/* ===========================================================================
   CORTEX · Decision Intelligence Platform — Folha de estilo
   ===========================================================================
   ORGANIZAÇÃO
   Tudo é escrito contra TOKENS (variáveis CSS), nunca contra hex solto. Trocar
   o tema — ou aplicar a identidade visual da Claro no futuro — passa a ser
   editar um bloco, não caçar cor em 40 lugares.

   TEMA
   Escuro por padrão (painel de sala de controle, projeção em reunião), com
   tema claro completo sob [data-theme="light"]. Os dois são ESCOLHIDOS, não
   um a inversão automática do outro: as cores do modo claro foram degrauadas
   para a superfície clara.

   SEMÁFORO
   Três estados, com contraste verificado contra as duas superfícies. Cor NUNCA
   carrega significado sozinha: todo elemento colorido vem acompanhado de ícone
   e rótulo textual — requisito de acessibilidade e, na prática, o que permite
   ler o painel impresso em preto e branco.
   =========================================================================== */

:root {
  color-scheme: dark;

  /* superfícies */
  --plano:        #0a0c11;
  --superficie:   #12151c;
  --superficie-2: #171b24;
  --superficie-3: #1e2430;
  --borda:        rgba(255,255,255,.10);
  --borda-forte:  rgba(255,255,255,.18);

  /* tinta */
  --ink:        #ffffff;
  --ink-2:      #c3c2b7;
  --projecao:   #9A8BFF;
  --ink-3:      #898781;
  --grade:      rgba(255,255,255,.07);
  --eixo:       #383835;

  /* ===================================================================
     SEMÁFORO — quatro estados, medidos e não escolhidos por gosto
     ===================================================================
     O Artur: "Por que temos Portas 0-80 em cinza enquanto Nota QoE está em
     verde... passa ideia de desatualizado... se foi porque superou o desafio
     então mude para #00CCFF... mas deve seguir worldwide best in class".

     Ele achou dois problemas de uma vez, e os dois eram reais.

     1) CINZA ESTAVA FAZENDO DOIS TRABALHOS. Ele marcava "sem polaridade" e
        "sem leitura" — e cinza ao lado de verde lê como "velho", não como
        "não se aplica". Agora a AUSÊNCIA carrega HACHURA além do cinza
        (.sem-dado), e nenhum estado com número é cinza. Textura é a marca que
        diz "isto não é um valor", e sobrevive a impressão em preto e branco.

     2) SUPERADO ERA UM SEGUNDO VERDE. Quem bateu o desafio e quem bateu só a
        meta saíam quase iguais. SUPERADO ganha hue própria — o #00CCFF que
        ele pediu no tema escuro, onde dá 9,6:1 contra a superfície.

     NO TEMA CLARO, #00CCFF NÃO SERVE: sobre branco ele dá 1,9:1, abaixo de
     qualquer piso de legibilidade. O claro usa #00739B — mesma família de
     hue, 5,35:1 sobre branco. Mesma cor conceitual, dois valores, porque o
     fundo é outro.

     O PAR QUE MAIS IMPORTA É VERMELHO × VERDE (fora × dentro da meta), e ele
     foi MEDIDO, não escolhido: o par antigo (#d03b3b / #0ca30c) separava ΔE
     4,1 para deuteranopia — praticamente indistinguível para ~6% dos homens.
     O par novo (#e8543c / #0f9d58) dá ΔE 7,0, dentro da faixa que só é
     aceitável COM codificação secundária — que existe: todo estado traz ícone
     e rótulo em texto, nunca cor sozinha.

     Verde × ciano fica em ΔE 14,3 no tema claro, logo abaixo do piso de 15.
     Aceito de propósito: confundir "excelente" com "bom" custa pouco;
     confundir "dentro" com "fora da meta" custa uma decisão errada. Por isso
     SUPERADO também ganha um GLIFO próprio (✦) além do rótulo. */
  --bom:      #0f9d58;
  --atencao:  #fab219;
  --critico:  #e8543c;
  --superado: #00ccff;
  --neutro:   #6b7280;
  /* SEM RUMO MEDIDO — pedido 114. Cinza PRÓPRIO, e não o `--neutro`
     reaproveitado: `--neutro` já quer dizer «sem polaridade» no
     farol, e dois significados no mesmo tom é a tela discordando de
     si mesma. Este é mais claro que o `--neutro`, para a bolha ficar
     presente sem competir com as que têm juízo. */
  --sem-rumo: #9aa1ab;
  --bom-bg:      rgba(15,157,88,.14);
  --atencao-bg:  rgba(250,178,25,.14);
  --critico-bg:  rgba(232,84,60,.15);
  --superado-bg: rgba(0,204,255,.14);
  --neutro-bg:   rgba(107,114,128,.14);

  /* séries (validadas para a superfície escura) */
  --serie-1: #3987e5;
  --serie-2: #d95926;
  --serie-3: #199e70;

  --marca:    #4da3ff;

  /* META E DESAFIO SÃO SIGNIFICADO, NÃO SLOT DE PALETA.
     Eles estavam escritos como `--serie-2` e `--marca`, e no tema claro a
     paleta do Core redefine os dois: `--marca` vira o vermelho da Claro e
     `--serie-2` vira o azul do "ano anterior". Resultado: a meta ficava azul e
     o desafio vermelho — exatamente o contrário do tema escuro, e o desafio
     pintado com a cor de alerta.

     Trocar de tema não pode trocar o que uma cor SIGNIFICA. Então meta e
     desafio ganham token próprio, como o semáforo já tinha, com os dois valores
     escolhidos por contraste contra a superfície de cada tema (ambos acima de
     4,5:1 para texto em negrito). */
  --meta:    #e8a33d;
  --desafio: #5b9dff;

  --raio:     10px;
  --sombra:   0 1px 2px rgba(0,0,0,.4), 0 8px 24px rgba(0,0,0,.28);
  /* ===================================================================
     TIPOGRAFIA DE DASHBOARD
     ===================================================================
     O padrão de fato em analytics hoje é o Inter — é o que Grafana, Linear e
     boa parte das ferramentas de dado usam, e por um motivo técnico, não de
     moda: ele tem ALGARISMOS TABULARES de verdade (todos com a mesma largura),
     um zero que não se confunde com O, e um 1 com serifa de base. Numa coluna
     de números, largura desigual faz o olho perder o alinhamento das casas
     decimais, e é aí que se lê 1.234 como 12.34.

     O CORTEX não baixa fonte de CDN — é a mesma regra de sempre: uma tag que
     não carrega numa rede corporativa vira uma página quebrada em silêncio.
     Então a pilha é por disponibilidade:

       Inter                     se estiver instalada ou for colocada em
                                 frontend/assets/fontes/ (ver @font-face)
       Segoe UI Variable Text    Windows 11 — excelente, e já está na máquina
       Segoe UI                  Windows 10
       system-ui / -apple-system o resto

     Para ter o Inter de verdade: baixe Inter-Regular/SemiBold/Bold .woff2 e
     ponha em `frontend/assets/fontes/`. O @font-face abaixo já aponta para lá
     e some sem barulho se os arquivos não existirem. */
  --fonte: "Inter", "Inter var", "Segoe UI Variable Text", "Segoe UI",
           system-ui, -apple-system, Roboto, "Helvetica Neue", Arial, sans-serif;
  /* Para NÚMERO: a mesma família, mas sempre com algarismo tabular e
     entreletra um pouco fechada — dígito solto tende a parecer esparso. */
  --fonte-num: var(--fonte);
  /* A FAMÍLIA DE EXIBIÇÃO — pedido 99: «uma fonte a mais destacável
     possível». Primeiro as faces desenhadas para corpo grande, depois os
     pesos mais fortes que a máquina já tem, e só então o texto comum.
     Nada aqui é baixado: a regra do projeto é que fonte não vem de CDN. */
  --fonte-destaque: "Inter Display", "Inter", "Segoe UI Variable Display",
                    "Segoe UI Black", "Segoe UI", system-ui, sans-serif;
  /* A FAMÍLIA DE PAINEL — pedido 131, segunda volta. Artur: «o próprio
     formato do número traz ares de modernidade e disruptividade».

     Ele está apontando a LETRA do anexo, não o tamanho: o «130» de lá é um
     algarismo TÉCNICO — haste reta, contraforma quadrada, terminal chapado.
     É a voz de instrumento (painel de avião, conta-giros, placar), e ela não
     sai do mesmo desenho humanista que o resto do painel usa para texto.

     A LISTA PÕE NA FRENTE AS FACES TÉCNICAS QUE A MÁQUINA JÁ TEM:
       · Bahnschrift      — a DIN variável que acompanha o Windows 10 (1709+)
                            e o 11. É a mais provável de existir na máquina
                            dele e é exatamente a voz do anexo.
       · Eurostile / Microgramma / Square721 — as faces quadradas clássicas
                            de instrumento, quando instaladas.
       · DIN Alternate / Oswald — alternativas estreitas e técnicas.
     Depois disso cai nas de exibição e, por fim, no texto comum. NADA É
     BAIXADO: a regra do projeto é que fonte não vem de CDN, porque uma
     <link> que não carrega na rede corporativa vira página quebrada em
     silêncio.

     A LISTA É ESCRITA POR EXTENSO, sem `var()` dentro. Isso não é estilo: o
     corpo do número é decidido medindo a família no canvas 2D
     (`_tintaDoTexto`), e `ctx.font` não resolve variável de CSS — um
     `var(--fonte-num)` aninhado aqui faria a string inteira ser rejeitada e
     a medição cair no fallback sem avisar ninguém. */
  --fonte-painel: "Bahnschrift", "Eurostile", "Microgramma", "Square721 BT",
                  "DIN Alternate", "Oswald", "Inter Display", "Inter",
                  "Segoe UI Variable Display", "Segoe UI", system-ui,
                  sans-serif;
  /* PARA RÓTULO DE SEÇÃO — pedido 84. Artur: «melhore os títulos aumentando
     a fonte, trocando a cor e mudando a fonte que destaque melhor».

     Família MONOESPAÇADA, e a escolha tem razão: ela é a única do sistema
     que não se confunde com texto nem com número. Os rótulos marcam a
     ESTRUTURA do painel («aqui começa o ranking»), e estrutura dita na
     mesma voz do conteúdo desaparece — era o que acontecia com 9,5px de
     Inter em cinza. É também a voz que o deck já usa nos rótulos dele, e
     passar a usá-la aqui faz tela e papel falarem a mesma língua.

     DESCARTADO pintá-los de vermelho da marca, que seria o caminho óbvio
     para «trocar a cor»: #FF140A tem contraste de 3,9:1 sobre o branco —
     insuficiente para corpo pequeno — e, pior, vermelho neste painel já
     significa FORA DA META. Um título vermelho diria que a seção vai mal.
     A cor vai para o filete que antecede o rótulo, onde ela marca sem
     afirmar, e o texto fica na tinta mais escura, que é o salto de
     destaque que ele pediu. */
  --fonte-rot: ui-monospace, "Cascadia Mono", "SF Mono", Consolas,
               "Liberation Mono", Menlo, monospace;
  /* A COR DA PROJEÇÃO — e por que ela não é nenhuma das do farol.
     Vermelho e verde já significam fora e dentro da meta neste painel.
     Pintar a projeção com qualquer um dos dois diria algo sobre o juízo
     do indicador que ela não tem como dizer. O índigo não está em uso,
     não disputa o eixo vermelho-verde (onde mora a daltonia mais comum)
     e tem a frieza de quem fala do futuro. Um tom por tema, porque o
     mesmo índigo que se lê no claro some no escuro. */
  --projecao: #6A5AD6;
  /* UMA LARGURA SÓ PARA A ROTA INTEIRA — pedido deste turno.
     Artur, com o desenho à mão ao lado: «o fato de termos largura das
     linhas distinto leva à falsa percepção de que não se trata do mesmo
     percurso... normalizar a largura da linha e harmonize o contorno».
     MEDIDO no DOM antes de consertar: o trecho medido saía com 3,2px e a
     projeção com 1,7px — quase o DOBRO de espessura entre duas metades do
     mesmo caminho, mais opacidades diferentes (0,85 contra 0,78 e 0,34) e
     pontas diferentes (`round` contra `butt`). Três diferenças somadas,
     nenhuma delas significando nada: espessura, no desenho, quer dizer
     IMPORTÂNCIA, e eu estava dizendo que o futuro importa menos quando
     queria dizer que ele é suposto. Quem diz «suposto» é o tracejado, e
     ele já dizia sozinho.
     O token existe para que a rota não possa divergir de novo por
     descuido: um número, um lugar. */
  --traj-w: 3px;
  /* AS QUATRO MATIZES DOS QUADRANTES — do anexo do pedido 91, de volta no
     100. Tom por tema: no escuro elas entram um pouco mais claras, senão
     o fundo a 20% sobre superfície escura some. */
  --q-acompanhar: #7E9BD8;
  --q-manter:     #45D45A;
  --q-agir:       #FF6B6B;
  --q-vigiar:     #FBBE6B;
  /* O contorno da bolha é da família do FUNDO DO PAINEL, não da cor dela:
     é o que a mantém com forma dentro de um quadrante da própria cor. */
  --contorno-bolha: #0a0c12;
  /* O chip é escuro nos dois temas, como no desenho dele: caixinha preta
     de texto branco. No tema escuro ele ganha borda clara para não sumir
     dentro do próprio fundo. */
  --chip-fundo: #0b0e14;
  --chip-tinta: #f3f5f9;
  --chip-borda: rgba(255,255,255,.34);
}

:root[data-theme="light"] {
  color-scheme: light;
  --projecao: #5B4BC4;
  /* No claro valem os hexes do anexo sem ajuste: foram pensados sobre
     folha branca. */
  --q-acompanhar: #6285CA;
  --q-manter:     #2FC741;
  --q-agir:       #FF5757;
  --q-vigiar:     #FAAF4C;
  --contorno-bolha: #1a1d24;
  --chip-fundo: #12151c;
  --chip-tinta: #ffffff;
  --chip-borda: rgba(255,255,255,.22);
  --plano:        #f4f5f7;
  --superficie:   #ffffff;
  --superficie-2: #f7f8fa;
  --superficie-3: #eef0f4;
  --borda:        rgba(11,11,11,.10);
  --borda-forte:  rgba(11,11,11,.20);
  --ink:   #0b0b0b;
  --ink-2: #52514e;
  --ink-3: #6f6e69;
  --grade: rgba(11,11,11,.07);
  --eixo:  #c3c2b7;
  /* Os mesmos estados, medidos contra a superfície BRANCA. #00CCFF dá 1,9:1
     sobre branco e por isso não entra aqui: o ciano do tema claro é #00739B,
     mesma hue, 5,35:1. */
  --bom:      #0b7a45;
  --atencao:  #b07800;
  --critico:  #c4402b;
  --superado: #00739b;
  --neutro:   #6b7280;
  /* No tema escuro o mesmo cinza ficaria apagado demais contra o
     fundo dos quadrantes: sobe um degrau. */
  --sem-rumo: #7b828d;
  --bom-bg:      rgba(11,122,69,.10);
  --atencao-bg:  rgba(176,120,0,.12);
  --critico-bg:  rgba(196,64,43,.10);
  --superado-bg: rgba(0,115,155,.10);
  --neutro-bg:   rgba(107,114,128,.10);
  --serie-1: #2a78d6;
  --serie-2: #eb6834;
  --serie-3: #1baf7a;
  --marca:   #1f6fd0;
  /* Mais escuros no claro: o mesmo tom de âmbar que funciona sobre #12151c
     some sobre #ffffff. */
  --meta:    #a9670b;
  --desafio: #1c5fbf;
  --sombra:  0 1px 2px rgba(11,11,11,.06), 0 6px 18px rgba(11,11,11,.07);
}

* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
body {
  background: var(--plano);
  color: var(--ink);
  font-family: var(--fonte);
  font-size: 14px;
  line-height: 1.45;
  -webkit-font-smoothing: antialiased;
}
a { color: var(--marca); }
button { font-family: inherit; }

/* ---------------------------------------------------------------- topo --- */
.topo {
  position: sticky; top: 0; z-index: 40;
  background: color-mix(in srgb, var(--plano) 88%, transparent);
  backdrop-filter: blur(14px);
  border-bottom: 1px solid var(--borda);
}
/* flex-wrap não é cosmético: sem ele a linha do topo (marca + trilha + dois
   filtros + botão de tema) mede ~660px e obriga a PÁGINA INTEIRA a rolar de
   lado num telefone — o corpo passa a deslizar horizontalmente junto com o
   cabeçalho. Deixando a linha quebrar, o topo cresce em altura e a página
   nunca rola de lado. Só as tabelas rolam, cada uma no seu contêiner. */
.topo-linha { display: flex; flex-wrap: wrap; align-items: center; gap: 18px; padding: 12px 22px; }
.marca {
  display: flex; align-items: center; gap: 9px;
  font-weight: 700; letter-spacing: .06em; font-size: 15px;
}
.marca .k { font-weight: 400; letter-spacing: .02em; color: var(--ink-3); font-size: 12px; }
.marca .ponto { width: 9px; height: 9px; border-radius: 50%; background: var(--neutro); }
.topo .espaco { flex: 1; }

.abas { display: flex; gap: 2px; padding: 0 16px; overflow-x: auto; }
.aba {
  background: none; border: 0; color: var(--ink-3); cursor: pointer;
  padding: 9px 14px; font-size: 13px; font-weight: 500; white-space: nowrap;
  border-bottom: 2px solid transparent; transition: color .12s, border-color .12s;
}
.aba:hover { color: var(--ink-2); }
.aba[aria-selected="true"] { color: var(--ink); border-bottom-color: var(--marca); }

/* ------------------------------------------------------------ controles -- */
.controle {
  display: inline-flex; align-items: center; gap: 6px;
  background: var(--superficie-2); border: 1px solid var(--borda);
  border-radius: 8px; padding: 5px 9px; font-size: 12.5px; color: var(--ink-2);
}
.controle select, .controle input {
  background: none; border: 0; color: var(--ink); font-family: inherit;
  font-size: 12.5px; outline: none; cursor: pointer;
}
.controle label { color: var(--ink-3); font-size: 11px; text-transform: uppercase; letter-spacing: .06em; }
.btn {
  background: var(--superficie-2); border: 1px solid var(--borda); color: var(--ink-2);
  border-radius: 8px; padding: 6px 11px; font-size: 12.5px; cursor: pointer;
  transition: background .12s, color .12s;
}
.btn:hover { background: var(--superficie-3); color: var(--ink); }
.btn.ativo { background: var(--marca); border-color: var(--marca); color: #04121f; font-weight: 600; }

/* ------------------------------------------------------------- estrutura - */
.pagina { max-width: 1480px; margin: 0 auto; padding: 20px 22px 60px; }
.painel { display: none; }
.painel.ativo { display: block; animation: surge .18s ease-out; }
@keyframes surge { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: none; } }

.cartao {
  background: var(--superficie); border: 1px solid var(--borda);
  border-radius: var(--raio); box-shadow: var(--sombra);
}
.cartao-cab {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 13px 16px; border-bottom: 1px solid var(--borda);
}
.cartao-cab h2 { margin: 0; font-size: 13px; font-weight: 600; letter-spacing: .07em;
  text-transform: uppercase; color: var(--ink-2); }
.cartao-corpo { padding: 16px; }

.grade { display: grid; gap: 14px; }
.g-2 { grid-template-columns: repeat(2, minmax(0,1fr)); }
.g-3 { grid-template-columns: repeat(3, minmax(0,1fr)); }
.g-4 { grid-template-columns: repeat(4, minmax(0,1fr)); }
.g-hero { grid-template-columns: 300px minmax(0,1fr); }
@media (max-width: 1100px) { .g-hero, .g-3, .g-4 { grid-template-columns: repeat(2, minmax(0,1fr)); } }
@media (max-width: 700px)  { .grade { grid-template-columns: 1fr !important; } }

/* --------------------------------------------------------------- trilha -- */
/* As regras do breadcrumb do hospedeiro (`.hospede`, `.hosp-*`) saíram no
   pedido 105 junto com o HTML delas: folha com seletor órfão é onde a
   próxima pessoa vai procurar um estilo que não existe. A `.sr-so`
   continua, porque o título do Radar Executivo segue escondido para a
   tela e presente para o leitor de tela. */
.sr-so {
  position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0;
}
.trilha { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; font-size: 12.5px; }
.trilha button {
  background: none; border: 0; color: var(--ink-3); cursor: pointer; padding: 2px 4px;
  font-size: 12.5px; border-radius: 5px;
}
.trilha button:hover { color: var(--marca); background: var(--superficie-2); }
.trilha .sep { color: var(--ink-3); opacity: .5; }
.trilha .atual { color: var(--ink); font-weight: 600; }

/* ---------------------------------------------------------------- hero --- */
.hero { display: flex; flex-direction: column; justify-content: center; gap: 4px; padding: 20px 18px; }
.hero .rotulo { font-size: 11px; text-transform: uppercase; letter-spacing: .1em; color: var(--ink-3); }
.hero .figura { font-size: 62px; font-weight: 700; line-height: 1; letter-spacing: -.02em; }
.hero .sub { font-size: 12px; color: var(--ink-3); }
.arco { display: block; margin-top: 6px; }

.tile { padding: 14px 16px; display: flex; flex-direction: column; gap: 3px; }
.tile .rotulo { font-size: 10.5px; text-transform: uppercase; letter-spacing: .09em; color: var(--ink-3); }
.tile .valor { font-size: 25px; font-weight: 650; line-height: 1.15; letter-spacing: -.01em; }
.tile .nota { font-size: 11.5px; color: var(--ink-3); }

/* ------------------------------------------------------------- semáforo -- */
.selo {
  display: inline-flex; align-items: center; gap: 5px; border-radius: 999px;
  padding: 2px 9px 2px 6px; font-size: 11px; font-weight: 600; letter-spacing: .03em;
  white-space: nowrap;
}
.selo .glifo { font-size: 10px; line-height: 1; }
.s-BOM      { color: var(--bom);     background: var(--bom-bg); }
.s-ATENCAO  { color: var(--atencao); background: var(--atencao-bg); }
.s-CRITICO  { color: var(--critico); background: var(--critico-bg); }
.s-NEUTRO, .s-INDISPONIVEL { color: var(--neutro); background: var(--neutro-bg); }
.t-BOM { color: var(--bom); } .t-ATENCAO { color: var(--atencao); }
.t-CRITICO { color: var(--critico); } .t-NEUTRO, .t-INDISPONIVEL { color: var(--neutro); }

/* ------------------------------------------------------- cartão indicador */
.ind {
  position: relative; background: var(--superficie); border: 1px solid var(--borda);
  border-radius: var(--raio); padding: 13px 14px 12px; cursor: pointer;
  transition: border-color .14s, transform .14s;
  display: flex; flex-direction: column; gap: 7px; min-height: 124px;
}
.ind:hover { border-color: var(--borda-forte); transform: translateY(-1px); }
.ind::before {
  content: ""; position: absolute; left: 0; top: 10px; bottom: 10px; width: 3px;
  border-radius: 0 3px 3px 0; background: var(--neutro);
}
.ind.b-BOM::before     { background: var(--bom); }
.ind.b-ATENCAO::before { background: var(--atencao); }
.ind.b-CRITICO::before { background: var(--critico); }
.ind.b-INDISPONIVEL { opacity: .55; cursor: default; }
.ind.b-INDISPONIVEL:hover { transform: none; }
.ind .nome { font-size: 11.5px; font-weight: 600; color: var(--ink-2); line-height: 1.3;
  text-transform: uppercase; letter-spacing: .04em; padding-left: 8px; }
.ind .linha-valor { display: flex; align-items: baseline; gap: 8px; padding-left: 8px; }
.ind .valor { font-size: 24px; font-weight: 650; letter-spacing: -.01em; }
.ind .rodape { display: flex; align-items: center; justify-content: space-between;
  gap: 8px; padding-left: 8px; margin-top: auto; font-size: 11px; color: var(--ink-3); }
.ind .aviso { position: absolute; top: 10px; right: 11px; font-size: 10px; color: var(--ink-3); }

.delta { display: inline-flex; align-items: center; gap: 3px; font-size: 11.5px; font-weight: 600; }
.d-melhorou { color: var(--bom); } .d-piorou { color: var(--critico); }
.d-estavel, .d-neutro, .d-indisponivel { color: var(--ink-3); }

/* --------------------------------------------------------------- camada -- */
.camada-cab { display: flex; align-items: baseline; gap: 12px; margin: 22px 0 10px; }
.camada-cab h3 { margin: 0; font-size: 12px; font-weight: 700; letter-spacing: .12em;
  text-transform: uppercase; }
.camada-cab .pergunta { font-size: 12.5px; color: var(--ink-2); font-style: italic; }
.camada-cab .ritual { margin-left: auto; font-size: 11px; color: var(--ink-3);
  border: 1px solid var(--borda); border-radius: 999px; padding: 2px 9px; }

/* ---------------------------------------------------------------- mapa --- */
.mapa-caixa { display: grid; grid-template-columns: minmax(0,1fr) 340px; gap: 14px; }
@media (max-width: 1000px) { .mapa-caixa { grid-template-columns: 1fr; } }
.uf { cursor: pointer; transition: opacity .12s, stroke-width .12s; stroke: var(--plano); stroke-width: .8; }
.uf:hover { opacity: .82; stroke-width: 1.6; stroke: var(--ink); }
.uf.apagada { opacity: .22; }
.uf-rotulo { font-size: 9.5px; font-weight: 600; fill: #fff; pointer-events: none;
  paint-order: stroke; stroke: rgba(0,0,0,.45); stroke-width: 2.4px; }

.lista-drill { display: flex; flex-direction: column; gap: 1px; }
.linha-drill {
  display: grid; grid-template-columns: 1fr auto auto; align-items: center; gap: 10px;
  padding: 9px 12px; background: var(--superficie); border: 1px solid transparent;
  border-radius: 8px; cursor: pointer; text-align: left; width: 100%;
  color: inherit; font-family: inherit; font-size: 13px;
}
.linha-drill:hover { background: var(--superficie-3); border-color: var(--borda); }
.linha-drill .nome { font-weight: 550; }
.linha-drill .meta { font-size: 11px; color: var(--ink-3); }
.barra-idx { width: 64px; height: 6px; border-radius: 3px; background: var(--superficie-3); overflow: hidden; }
.barra-idx span { display: block; height: 100%; border-radius: 3px; }

/* -------------------------------------------------------------- tabela --- */
table { width: 100%; border-collapse: collapse; font-size: 12.5px; }
th {
  text-align: left; font-size: 10.5px; text-transform: uppercase; letter-spacing: .07em;
  color: var(--ink-3); font-weight: 600; padding: 8px 10px;
  border-bottom: 1px solid var(--borda); position: sticky; top: 0; background: var(--superficie);
}
td { padding: 8px 10px; border-bottom: 1px solid var(--grade); }
tbody tr:hover { background: var(--superficie-2); }
.num { text-align: right; font-variant-numeric: tabular-nums; }
.clicavel { cursor: pointer; }

/* ------------------------------------------------------------- gráficos -- */
.grafico { width: 100%; display: block; overflow: visible; }
.grade-linha { stroke: var(--grade); stroke-width: 1; }
.eixo-linha { stroke: var(--eixo); stroke-width: 1; }
.eixo-txt { fill: var(--ink-3); font-size: 10px; font-variant-numeric: tabular-nums; }
.linha-serie { fill: none; stroke: var(--serie-1); stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
.area-serie { fill: var(--serie-1); opacity: .12; }
.linha-meta { stroke: var(--bom); stroke-width: 1.5; stroke-dasharray: 5 4; opacity: .85; }
.ponto-serie { fill: var(--serie-1); stroke: var(--superficie); stroke-width: 2; }
.barra { fill: var(--serie-1); }
.cursor { stroke: var(--ink-3); stroke-width: 1; stroke-dasharray: 3 3; }

.dica {
  position: fixed; z-index: 90; pointer-events: none; opacity: 0;
  background: var(--superficie-3); border: 1px solid var(--borda-forte);
  border-radius: 8px; padding: 8px 11px; font-size: 12px; color: var(--ink);
  box-shadow: var(--sombra); transition: opacity .1s; max-width: 280px;
}
.dica.on { opacity: 1; }
.dica .t { font-weight: 600; margin-bottom: 3px; }
.dica .l { display: flex; justify-content: space-between; gap: 14px; color: var(--ink-2); }
.dica .l b { color: var(--ink); font-variant-numeric: tabular-nums; }

/* ------------------------------------------------------------- features -- */
.progresso { height: 8px; border-radius: 4px; background: var(--superficie-3); overflow: hidden; }
.progresso span { display: block; height: 100%; background: var(--serie-1); border-radius: 4px; }
.pilula {
  font-size: 10px; font-weight: 600; letter-spacing: .05em; padding: 2px 8px;
  border-radius: 999px; background: var(--superficie-3); color: var(--ink-2); white-space: nowrap;
}
.e-ESTAVEL      { background: var(--bom-bg); color: var(--bom); }
.e-DEPLOYADO    { background: rgba(57,135,229,.16); color: var(--serie-1); }
.e-EM_TESTE     { background: var(--atencao-bg); color: var(--atencao); }
.e-EM_CONSTRUCAO{ background: rgba(217,89,38,.16); color: var(--serie-2); }
.e-BLOQUEADO    { background: var(--critico-bg); color: var(--critico); }

/* --------------------------------------------------------------- gaveta -- */
.gaveta-fundo {
  position: fixed; inset: 0; background: rgba(0,0,0,.55); z-index: 60;
  opacity: 0; pointer-events: none; transition: opacity .18s;
}
.gaveta-fundo.on { opacity: 1; pointer-events: auto; }
.gaveta {
  position: fixed; top: 0; right: 0; bottom: 0; width: min(560px, 94vw); z-index: 61;
  background: var(--superficie); border-left: 1px solid var(--borda);
  transform: translateX(100%); transition: transform .22s cubic-bezier(.32,.72,0,1);
  display: flex; flex-direction: column; overflow: hidden;
}
.gaveta.on { transform: none; }
.gaveta-cab { display: flex; align-items: flex-start; justify-content: space-between;
  gap: 12px; padding: 16px 18px; border-bottom: 1px solid var(--borda); }
.gaveta-corpo { overflow-y: auto; padding: 16px 18px 40px; }
.fechar { background: none; border: 0; color: var(--ink-3); font-size: 22px; cursor: pointer; line-height: 1; }
.fechar:hover { color: var(--ink); }

.bloco-def { background: var(--superficie-2); border: 1px solid var(--borda);
  border-radius: 8px; padding: 11px 13px; margin: 10px 0; font-size: 12.5px; color: var(--ink-2); }
.bloco-def code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; color: var(--ink); }
.rotulo-secao { font-size: 10.5px; text-transform: uppercase; letter-spacing: .09em;
  color: var(--ink-3); margin: 18px 0 7px; font-weight: 600; }

.nota-rodape { font-size: 11.5px; color: var(--ink-3); line-height: 1.6; }
.aviso-faixa {
  display: flex; align-items: flex-start; gap: 9px; font-size: 12px; color: var(--ink-2);
  background: var(--atencao-bg); border: 1px solid color-mix(in srgb, var(--atencao) 35%, transparent);
  border-radius: 8px; padding: 9px 12px; margin-bottom: 14px;
}
.aviso-faixa b { color: var(--atencao); }
.vazio { padding: 34px; text-align: center; color: var(--ink-3); font-size: 13px; }
.carregando { padding: 40px; text-align: center; color: var(--ink-3); }

/* ---------------------------------------------------- popup do Mapbox --- */
/* O Mapbox injeta o próprio DOM; sobrescrevemos para que o popup use os
   mesmos tokens do resto do painel e não destoe. */
.popup-sinapse .mapboxgl-popup-content {
  background: var(--superficie-3); color: var(--ink);
  border: 1px solid var(--borda-forte); border-radius: 8px;
  padding: 9px 12px; font-family: var(--fonte); font-size: 12px;
  box-shadow: var(--sombra);
}
.popup-sinapse .mapboxgl-popup-tip { border-top-color: var(--superficie-3); border-bottom-color: var(--superficie-3); }
.popup-sinapse .t { font-weight: 600; margin-bottom: 3px; }
.popup-sinapse .l { display: flex; justify-content: space-between; gap: 14px; color: var(--ink-2); }
.popup-sinapse .l b { color: var(--ink); font-variant-numeric: tabular-nums; }
.mapboxgl-ctrl-group { background: var(--superficie-2) !important; border: 1px solid var(--borda) !important; }
.mapboxgl-ctrl-group button + button { border-top-color: var(--borda) !important; }


/* ----------------------------------------------------------- inferências -- */
/* Uma linha por achado: nome, barra de excesso, números e o selo de confiança.
   O excesso é a grandeza operacional (quantos eventos a mais), e a barra o
   torna comparável de relance entre entidades de portes diferentes. */
.inf-linha{
  display:grid; grid-template-columns:minmax(120px,1.3fr) minmax(0,1.6fr) 118px 96px;
  align-items:center; gap:12px; padding:8px 10px; border-radius:7px;
}
.inf-linha:hover{background:var(--superficie-2)}
.inf-linha .nome{font-size:13px; font-weight:550; overflow:hidden;
  text-overflow:ellipsis; white-space:nowrap}
.inf-linha .nome small{display:block; font-weight:400; color:var(--ink-3); font-size:11px}
.inf-barra{height:14px; background:var(--superficie-3); border-radius:4px; overflow:hidden}
.inf-barra span{display:block; height:100%; border-radius:4px}
.inf-num{text-align:right; font-variant-numeric:tabular-nums; font-size:12.5px}
.inf-num b{font-size:13.5px}
.inf-num small{display:block; color:var(--ink-3); font-size:11px}

.limite{
  display:grid; grid-template-columns:auto 1fr; gap:12px; padding:13px 0;
  border-bottom:1px solid var(--grade);
}
.limite:last-child{border-bottom:0}
.limite .t{font-size:13.5px; font-weight:600; color:var(--ink)}
.limite .d{font-size:12.5px; color:var(--ink-2); margin-top:3px}
.limite .r{font-size:11.5px; color:var(--ink-3); margin-top:5px}
.limite .r b{color:var(--marca); font-weight:600}
.g-CRITICO{color:var(--critico)} .g-ALTO{color:var(--atencao)} .g-MEDIO{color:var(--ink-3)}

/* ---------------------------------------------------------------------------
   TELEFONE (~400px)
   O painel nasceu para uma tela de reunião, mas quem recebe o link abre no
   celular no corredor. Aqui não se reprojeta nada: apenas se afrouxa o que
   é rígido demais para 400px — margens laterais, a linha do topo e o espaço
   elástico que empurra os filtros para a direita.
   --------------------------------------------------------------------------- */
@media (max-width: 560px) {
  .topo-linha { gap: 10px; padding: 10px 16px; }
  .topo .espaco { flex-basis: 100%; height: 0; }   /* vira quebra de linha */
  .marca { font-size: 14px; }
  .marca .k { display: none; }                      /* o subtítulo cede antes do nome */
  .abas { padding: 0 8px; }
  .aba { padding: 9px 10px; font-size: 12.5px; }
  .controle { padding: 4px 8px; font-size: 12px; }
}

/* ===========================================================================
   ESTEIRA — batch, progresso por item e as três portas de liberação
   ===========================================================================
   A lista anterior era uma tabela de estados. Ela respondia "em que fase
   está?" e não respondia "posso mostrar isso?" — que é outra pergunta, e a
   que trava a conversa com o cliente. Por isso cada linha agora tem dois
   trilhos visuais separados: a BARRA (a equipe terminou?) e as PORTAS
   (foi conferido e liberado?).
   =========================================================================== */

.progresso.fina { height: 5px; }

/* --- explicação das portas ------------------------------------------- */
.porta-exp {
  display: flex; gap: 10px; align-items: flex-start;
  flex: 1 1 210px; min-width: 0;
  background: var(--superficie-2); border: 1px solid var(--borda);
  border-radius: 8px; padding: 10px 12px;
}
.porta-num {
  width: 22px; height: 22px; flex: none; border-radius: 50%;
  display: grid; place-items: center;
  font-size: 11px; font-weight: 700; color: var(--plano);
  background: var(--ink-3);
}
.porta-num.p-versao { background: var(--serie-1); }
.porta-num.p-troubleshooting { background: var(--atencao); }
.porta-num.p-cliente { background: var(--bom); }
.porta-exp b { display: block; font-size: 12.5px; font-weight: 600; line-height: 1.25; }
.porta-exp span:last-child { font-size: 11px; color: var(--ink-3); }

/* --- cobertura do escopo --------------------------------------------- */
.escopo-grade { display: grid; grid-template-columns: repeat(auto-fit, minmax(46px, 1fr)); gap: 5px; }
.escopo-cel {
  border: 1px solid var(--borda); border-radius: 6px; padding: 6px 4px;
  text-align: center; background: var(--superficie-2);
}
.escopo-cel .n { display: block; font-size: 10px; color: var(--ink-3); }
.escopo-cel .q { display: block; font-size: 15px; font-weight: 700; font-variant-numeric: tabular-nums; }
.escopo-cel.vazio { border-color: var(--critico); background: var(--critico-bg); }
.escopo-cel.vazio .q { color: var(--critico); }

/* --- tese do batch ---------------------------------------------------- */
.batch-tese { margin-bottom: 14px; }
.batch-tese .tese {
  margin: 0 0 10px; font-size: 14.5px; line-height: 1.45;
  color: var(--ink); border-left: 3px solid var(--marca); padding-left: 12px;
}
.batch-dl { display: grid; grid-template-columns: auto minmax(0,1fr); gap: 4px 12px; margin: 0; font-size: 12.5px; }
.batch-dl dt {
  font-size: 10px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase;
  color: var(--ink-3); padding-top: 2px; white-space: nowrap;
}
.batch-dl dd { margin: 0; color: var(--ink-2); }

/* --- linha da esteira -------------------------------------------------- */
.esteira { display: grid; gap: 3px; }
.esteira-l {
  display: grid;
  grid-template-columns: 52px minmax(0, 2.1fr) minmax(120px, 1fr) 56px auto;
  gap: 12px; align-items: center;
  padding: 9px 10px; border-radius: 7px; cursor: pointer;
  border: 1px solid transparent;
  transition: background .12s, border-color .12s;
}
.esteira-l:hover { background: var(--superficie-2); border-color: var(--borda); }
/* O estágio pinta uma faixa fina à esquerda. Cor sozinha não informa: o
   rótulo de cada porta continua escrito ao lado. */
.esteira-l.est-NA_VERSAO      { box-shadow: inset 3px 0 0 var(--serie-1); }
.esteira-l.est-CONFERIDO      { box-shadow: inset 3px 0 0 var(--atencao); }
.esteira-l.est-COM_O_CLIENTE  { box-shadow: inset 3px 0 0 var(--bom); }

.ei-id { font-size: 11.5px; color: var(--ink-3); font-variant-numeric: tabular-nums; }
.ei-nm { min-width: 0; }
.ei-nm b { display: block; font-size: 13px; font-weight: 600; line-height: 1.25; }
.ei-nm span { display: block; font-size: 11.5px; color: var(--ink-3); line-height: 1.35; }
.ei-nm .ei-org { font-size: 10.5px; opacity: .8; margin-top: 1px; }
.ei-pg { min-width: 0; }
.ei-est { display: block; font-size: 10.5px; color: var(--ink-3); margin-top: 3px; }
.ei-est b { color: var(--ink-2); font-variant-numeric: tabular-nums; }
.ei-vs { font-size: 11.5px; color: var(--ink-3); font-variant-numeric: tabular-nums; text-align: right; }

/* --- as portas, por item ---------------------------------------------- */
.portas { display: flex; gap: 4px; }
.porta {
  display: inline-flex; align-items: center; gap: 5px;
  background: var(--superficie-2); border: 1px solid var(--borda);
  color: var(--ink-3); border-radius: 6px; padding: 4px 8px;
  font-family: inherit; font-size: 10.5px; cursor: pointer; white-space: nowrap;
  transition: background .12s, border-color .12s, color .12s;
}
.porta .ic {
  width: 14px; height: 14px; border-radius: 50%; flex: none;
  display: grid; place-items: center; font-size: 9px; font-weight: 700;
  background: var(--borda); color: var(--ink-3);
}
.porta:hover { border-color: var(--borda-forte); color: var(--ink-2); }
.porta.on { border-color: var(--bom); color: var(--ink); background: var(--bom-bg); }
.porta.on .ic { background: var(--bom); color: #fff; }
.porta.travada { opacity: .45; }
.porta.travada:hover { border-color: var(--critico); }
.porta:focus-visible { outline: 2px solid var(--marca); outline-offset: 2px; }

/* --- toast ------------------------------------------------------------- */
#aviso {
  position: fixed; left: 50%; bottom: 26px; transform: translate(-50%, 14px);
  background: var(--superficie-3); color: var(--ink);
  border: 1px solid var(--borda-forte); border-radius: 8px;
  padding: 9px 16px; font-size: 13px; box-shadow: var(--sombra);
  opacity: 0; pointer-events: none; z-index: 90;
  transition: opacity .18s, transform .18s;
  max-width: calc(100vw - 32px);
}
#aviso.on { opacity: 1; transform: translate(-50%, 0); }

/* --- toggle de tema explícito ------------------------------------------
   O glifo ◐ era um enigma: ninguém clica no que não sabe o que faz. Vira um
   par de opções rotuladas, com a atual marcada — o estado fica legível sem
   ter que clicar para descobrir. */
.tema-toggle {
  display: inline-flex; align-items: center; gap: 0;
  background: var(--superficie-2); border: 1px solid var(--borda);
  border-radius: 8px; padding: 2px; overflow: hidden;
}
.tema-toggle button {
  background: none; border: 0; color: var(--ink-3); cursor: pointer;
  font-family: inherit; font-size: 11.5px; padding: 4px 10px; border-radius: 6px;
  display: inline-flex; align-items: center; gap: 5px; white-space: nowrap;
  transition: background .12s, color .12s;
}
.tema-toggle button:hover { color: var(--ink-2); }
.tema-toggle button[aria-pressed="true"] {
  background: var(--superficie-3); color: var(--ink); font-weight: 600;
  box-shadow: 0 1px 2px rgba(0,0,0,.12);
}
.tema-toggle button:focus-visible { outline: 2px solid var(--marca); outline-offset: -1px; }
.tema-toggle .gl { font-size: 12px; line-height: 1; }

@media (max-width: 560px) {
  .esteira-l { grid-template-columns: minmax(0,1fr); gap: 7px; }
  .ei-id { display: none; }
  .ei-vs { text-align: left; }
  .portas { flex-wrap: wrap; }
  .tema-toggle button .rt { display: none; }
}

/* =========================================================================
   RADAR EXECUTIVO — as três páginas do deck, com dado vivo
   =========================================================================
   PROCEDÊNCIA É O ELEMENTO DE DESIGN CENTRAL desta tela. O deck original
   trazia seis números redondos sem dizer de onde vinham (ele mesmo avisa:
   "layout demonstrativo"). Aqui cada dimensão carrega um selo — direto,
   proxy ou ausente — e a ressalva por extenso. Fica menos limpo e é a única
   versão que sobrevive à primeira conferência com o relatório oficial.
   ========================================================================= */

.dims { display: grid; gap: 12px; grid-template-columns: repeat(auto-fit, minmax(252px, 1fr)); }
.dim {
  background: var(--superficie-2); border: 1px solid var(--borda);
  border-radius: var(--raio); padding: 13px 15px 15px; min-width: 0;
  border-top: 3px solid var(--neutro);
}
.dim.pr-DIRETO  { border-top-color: var(--bom); }
.dim.pr-PROXY   { border-top-color: var(--atencao); }
.dim.pr-AUSENTE { border-top-color: var(--critico); }
.dim-cab { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.dim-rot { font-size: 11px; font-weight: 700; letter-spacing: .1em; color: var(--ink-2); }
.dim-sub { font-size: 11.5px; color: var(--ink-3); margin-top: 1px; }
.dim-fig {
  font-size: 30px; font-weight: 700; letter-spacing: -.02em; line-height: 1.1;
  margin: 8px 0 4px; font-variant-numeric: tabular-nums;
}
.dim-pe { display: flex; justify-content: space-between; gap: 8px; font-size: 11px; color: var(--ink-3); }
.dim-var { font-weight: 600; font-variant-numeric: tabular-nums; }
.dim-var.sobe { color: var(--critico); }
.dim-var.desce { color: var(--bom); }
.dim-res {
  font-size: 11.5px; line-height: 1.4; color: var(--ink-2); margin: 10px 0 0;
  padding-top: 9px; border-top: 1px dashed var(--borda);
}
.dim-comp { font-size: 10.5px; color: var(--ink-3); margin: 6px 0 0; }

.selo-proc {
  font-size: 9px; font-weight: 700; letter-spacing: .09em; text-transform: uppercase;
  padding: 2px 6px; border-radius: 3px; white-space: nowrap;
}
.selo-proc.s-DIRETO  { background: var(--bom-bg);     color: var(--bom); }
.selo-proc.s-PROXY   { background: var(--atencao-bg); color: var(--atencao); }
.selo-proc.s-AUSENTE { background: var(--critico-bg); color: var(--critico); }

/* --- os dois furos do alerta de jornada ------------------------------- */
.furo {
  border: 1px solid var(--critico); border-left-width: 3px;
  border-radius: 0 var(--raio) var(--raio) 0;
  background: var(--critico-bg); padding: 12px 14px;
}
.furo-cab { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-bottom: 4px; }
.furo-cab b { font-size: 13.5px; }
.furo-deck { font-size: 11.5px; color: var(--ink-3); margin: 0 0 8px; text-decoration: line-through; }
.furo p { font-size: 12.5px; line-height: 1.4; margin: 0 0 6px; }
.furo p:last-child { margin-bottom: 0; }

/* --- matriz regional --------------------------------------------------- */
/* O símbolo vem ANTES do texto em cada célula: quem não distingue as cores
   lê a forma (● ▲ ■) e o rótulo. Cor é reforço, nunca o canal único. */
table.matriz td .sem { font-variant-numeric: tabular-nums; font-weight: 600; white-space: nowrap; }
.sem-OK       { color: var(--bom); }
.sem-ATENCAO  { color: var(--atencao); }
.sem-CRITICO  { color: var(--critico); }
.sem-SEM_LEITURA { color: var(--ink-3); }

/* --- bloco Virtsel ----------------------------------------------------- */
.cartao.virtsel { border-color: var(--marca); }
.cartao.virtsel > .cartao-cab { border-bottom-color: var(--marca); }
.criterio {
  margin-top: 14px; padding: 10px 13px; border-radius: var(--raio);
  background: var(--superficie-2); font-size: 12.5px; line-height: 1.45;
}
.limites-lista { margin: 10px 0 0; padding-left: 18px; font-size: 12px; color: var(--ink-3); }
.limites-lista li { margin-bottom: 4px; }
.pilula.rec-MIGRAR          { background: var(--serie-1); color: #fff; }
.pilula.rec-RECUPERAR       { background: var(--atencao); color: #1a1205; }
.pilula.rec-MIGRAR_NO_RITMO { background: var(--superficie-3); color: var(--ink-2); }
.pilula.rec-MANTER          { background: var(--superficie-3); color: var(--ink-3); }

/* --- árvore de diagnóstico --------------------------------------------- */
.arvore { display: grid; gap: 12px; grid-template-columns: repeat(auto-fit, minmax(290px, 1fr)); }
.arv-col { border: 1px solid var(--borda); border-radius: var(--raio); overflow: hidden; }
.arv-cab { padding: 11px 13px; background: var(--superficie-2); border-bottom: 1px solid var(--borda); }
.arv-cab b { display: block; font-size: 11px; font-weight: 700; letter-spacing: .12em; color: var(--marca); }
.arv-cab span { display: block; font-size: 12.5px; color: var(--ink-2); margin-top: 2px; }
.arv-cab .arv-ritual { font-size: 10.5px; color: var(--ink-3); margin-top: 4px; }
.arv-item {
  display: grid; grid-template-columns: 22px minmax(0,1fr) auto; gap: 9px;
  align-items: baseline; padding: 8px 13px; border-top: 1px solid var(--borda);
}
.arv-n { font-size: 10.5px; color: var(--ink-3); font-variant-numeric: tabular-nums; }
.arv-item b { display: block; font-size: 12.5px; font-weight: 600; line-height: 1.25; }
.arv-item > div > span { display: block; font-size: 11px; color: var(--ink-3); line-height: 1.35; }
.arv-sit { font-size: 9px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; white-space: nowrap; }
.arv-item.si-DIRETO  { box-shadow: inset 3px 0 0 var(--bom); }
.arv-item.si-DIRETO .arv-sit { color: var(--bom); }
.arv-item.si-PARCIAL { box-shadow: inset 3px 0 0 var(--atencao); }
.arv-item.si-PARCIAL .arv-sit { color: var(--atencao); }
.arv-item.si-AUSENTE { box-shadow: inset 3px 0 0 var(--critico); }
.arv-item.si-AUSENTE .arv-sit { color: var(--critico); }
.arv-item.si-AUSENTE b { color: var(--ink-2); }

/* ---------------------------------------------------------------- versão --
   O selo no cabeçalho responde "que build é este?" sem perguntar a ninguém.
   A cor NÃO é decorativa: verde é contrato conferido, âmbar é versão ainda
   em desenvolvimento, vermelho é fórmula alterada depois do fechamento — o
   estado em que não se entrega. O rótulo textual acompanha no cartão. */
.selo-versao {
  display: inline-flex; align-items: baseline; gap: 6px;
  background: var(--superficie-2); border: 1px solid var(--borda);
  color: var(--ink-2); border-radius: 6px; padding: 3px 8px;
  font-family: inherit; font-size: 11px; font-weight: 600; cursor: pointer;
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
.selo-versao:hover { border-color: var(--borda-forte); color: var(--ink); }
.selo-versao .imp { font-size: 9.5px; font-weight: 400; color: var(--ink-3); }
.selo-versao.c-CONFERE     { border-color: color-mix(in srgb, var(--bom) 55%, transparent); }
.selo-versao.c-NAO_FECHADA { border-color: color-mix(in srgb, var(--atencao) 55%, transparent); }
.selo-versao.c-DIVERGENTE  { border-color: var(--critico); background: var(--critico-bg); color: var(--critico); }

.pilula.ct-CONFERE     { background: var(--bom-bg);     color: var(--bom); }
.pilula.ct-NAO_FECHADA { background: var(--atencao-bg); color: var(--atencao); }
.pilula.ct-DIVERGENTE  { background: var(--critico-bg); color: var(--critico); }

.releases { display: grid; gap: 10px; }
.rel {
  border: 1px solid var(--borda); border-radius: var(--raio);
  padding: 11px 13px; background: var(--superficie-2);
}
.rel.atual { border-color: var(--marca); background: var(--superficie); }
.rel-cab { display: flex; align-items: baseline; gap: 9px; flex-wrap: wrap; margin-bottom: 7px; }
.rel-cab b { font-size: 14px; font-variant-numeric: tabular-nums; }
.rel-tipo {
  font-size: 9px; font-weight: 700; letter-spacing: .09em; text-transform: uppercase;
  padding: 2px 6px; border-radius: 3px;
}
.rel-tipo.t-MAIOR    { background: var(--critico-bg); color: var(--critico); }
.rel-tipo.t-MENOR    { background: var(--bom-bg);     color: var(--bom); }
.rel-tipo.t-CORRECAO { background: var(--superficie-3); color: var(--ink-3); }
.rel-tit { font-size: 13px; color: var(--ink-2); }
.rel-data { margin-left: auto; font-size: 11px; color: var(--ink-3); font-variant-numeric: tabular-nums; }
.rel ul { margin: 0; padding-left: 18px; font-size: 12.5px; color: var(--ink-2); }
.rel li { margin-bottom: 3px; line-height: 1.4; }
.rel-contrato {
  margin-top: 9px; padding: 9px 11px; border-radius: var(--raio);
  background: var(--critico-bg); border-left: 3px solid var(--critico);
}
.rel-contrato b { display: block; font-size: 10px; letter-spacing: .09em;
  text-transform: uppercase; color: var(--critico); margin-bottom: 3px; }
.rel-contrato p { margin: 0; font-size: 12.5px; line-height: 1.4; }

/* =========================================================================
   FRENTES & AÇÃO
   =========================================================================
   Cada frente é um bloco fechado: diagnóstico, ação requerida e responsável
   na mesma leitura. O deck de referência acerta ao organizar assim — painel
   por indicador responde "o que está ruim"; painel por frente responde
   "quem faz o quê, onde, até quando".

   O selo "proposto" aparece em toda célula que saiu de regra nossa e não do
   dado. É o que permite propor prazo e responsável sem fingir que são
   contratuais — e célula vazia não gera discussão, proposta errada gera.
   ========================================================================= */

.fr-cartao.e-CRITICO { border-left: 3px solid var(--critico); }
.fr-cartao.e-ATENCAO { border-left: 3px solid var(--atencao); }
.fr-cartao.e-BOM     { border-left: 3px solid var(--bom); }

.fr-cols { display: grid; gap: 8px; grid-template-columns: repeat(auto-fit, minmax(146px, 1fr)); }
.fr-col {
  background: var(--superficie-2); border: 1px solid var(--borda);
  border-radius: var(--raio); padding: 9px 11px 10px; min-width: 0;
  border-top: 3px solid var(--neutro);
}
.fr-col.s-BOM { border-top-color: var(--bom); }
.fr-col.s-ATENCAO { border-top-color: var(--atencao); }
.fr-col.s-CRITICO { border-top-color: var(--critico); }
.fr-col.s-AUSENTE, .fr-col.s-SEM_LEITURA { border-top-color: var(--ink-3); opacity: .72; }
.fr-dim { display: block; font-size: 9.5px; font-weight: 700; letter-spacing: .09em;
  text-transform: uppercase; color: var(--ink-3); }
.fr-val { display: block; font-size: 21px; font-weight: 700; line-height: 1.15;
  margin: 3px 0 2px; font-variant-numeric: tabular-nums; }
.fr-comp { display: block; font-size: 10px; color: var(--ink-3); line-height: 1.3; }

.fr-acao {
  display: flex; gap: 16px; align-items: flex-start; flex-wrap: wrap;
  margin-top: 12px; padding: 11px 13px; border-radius: var(--raio);
  background: var(--superficie-3);
}
.fr-acao > div:first-child { flex: 1 1 320px; min-width: 0; }
.fr-acao b { font-size: 11.5px; font-weight: 700; letter-spacing: .09em; color: var(--marca); }
.fr-acao p { margin: 3px 0 0; font-size: 13px; color: var(--ink-2); }
.fr-resp { text-align: right; }
.fr-resp span { display: block; font-size: 9.5px; letter-spacing: .08em;
  text-transform: uppercase; color: var(--ink-3); }
.fr-resp b { display: block; font-size: 13px; color: var(--ink); font-weight: 600; letter-spacing: 0; }

/* --- a regra, cobrada -------------------------------------------------- */
.regra-cit {
  margin: 0; font-size: 15px; line-height: 1.45; color: var(--ink);
  border-left: 3px solid var(--marca); padding-left: 13px; font-style: italic;
}
.ok-sim { color: var(--bom); font-weight: 700; }
.ok-nao { color: var(--critico); font-weight: 700; }

/* --- cadeia de decisão ------------------------------------------------- */
.cadeia { display: flex; gap: 6px; flex-wrap: wrap; }
.cadeia-p {
  display: flex; align-items: center; gap: 7px; flex: 1 1 140px;
  background: var(--superficie-2); border: 1px solid var(--borda);
  border-radius: var(--raio); padding: 8px 11px; font-size: 12.5px; min-width: 0;
}
.cadeia-n {
  font-size: 10px; font-weight: 700; color: var(--plano);
  background: var(--marca); border-radius: 50%; width: 19px; height: 19px;
  display: grid; place-items: center; flex: none;
}

/* --- fila de priorização ----------------------------------------------- */
.pri {
  display: inline-grid; place-items: center; width: 22px; height: 22px;
  border-radius: 50%; font-size: 11px; font-weight: 700; color: #fff;
}
.pri.p-CRITICO { background: var(--critico); }
.pri.p-ATENCAO { background: var(--atencao); color: #1a1205; }
.prop {
  display: block; font-size: 8.5px; letter-spacing: .08em; text-transform: uppercase;
  color: var(--ink-3); margin-top: 1px;
}
.pilula.dec-migrar    { background: var(--serie-1); color: #fff; }
.pilula.dec-recuperar { background: var(--atencao); color: #1a1205; }
.pilula.dec-corrigir  { background: var(--superficie-3); color: var(--ink-2); }

/* --- planos por frente -------------------------------------------------- */
.planos { display: grid; gap: 11px; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); }
.plano {
  border: 1px solid var(--borda); border-radius: var(--raio);
  overflow: hidden; display: flex; flex-direction: column;
}
.plano-cab {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  padding: 10px 13px; background: var(--superficie-2); border-bottom: 1px solid var(--borda);
}
.plano-cab b { font-size: 13.5px; }
.plano.e-CRITICO .plano-cab { box-shadow: inset 3px 0 0 var(--critico); }
.plano.e-ATENCAO .plano-cab { box-shadow: inset 3px 0 0 var(--atencao); }
.plano-bl { padding: 9px 13px 0; }
.plano-bl span { font-size: 9.5px; font-weight: 700; letter-spacing: .1em;
  text-transform: uppercase; color: var(--ink-3); }
.plano-bl p { margin: 3px 0 0; font-size: 13px; line-height: 1.4; }
.plano-bl .impacto { color: var(--critico); font-weight: 600; font-size: 15px; }
.plano-bl.destaque-plano { margin: 9px 10px 0; padding: 9px 11px;
  background: var(--superficie-3); border-radius: var(--raio); }
.plano-prazo {
  margin-top: auto; padding: 8px 13px; text-align: center;
  background: var(--marca); color: #04121f;
  font-size: 10px; font-weight: 700; letter-spacing: .1em;
}
.plano-prazo .prop { color: rgba(4,18,31,.7); }

.gov-cad { display: grid; gap: 10px; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); margin-top: 16px; }
.gov-cad > div { background: var(--superficie-2); border-radius: var(--raio); padding: 10px 13px; }
.gov-cad b { display: block; font-size: 11px; letter-spacing: .1em; text-transform: uppercase; color: var(--marca); }
.gov-cad span { font-size: 12.5px; color: var(--ink-2); }

/* --- lista de instrumentação -------------------------------------------- */
.instr { display: grid; gap: 8px; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); }
.instr-i {
  border: 1px solid var(--borda); border-left: 3px solid var(--critico);
  border-radius: 0 var(--raio) var(--raio) 0; padding: 10px 12px; background: var(--superficie-2);
}
.instr-i b { display: block; font-size: 12.5px; margin-bottom: 4px; }
.instr-i p { margin: 0 0 4px; font-size: 11.5px; line-height: 1.38; color: var(--ink-2); }
.instr-i p span { color: var(--critico); font-weight: 600; }
.instr-quem { font-size: 10.5px; color: var(--ink-3); font-style: italic; }

/* ===========================================================================
   RADAR EXECUTIVO E ÁREA ADM
   ===========================================================================
   Duas abas novas, um só vocabulário visual: as cores do semáforo já existentes
   (--bom/--atencao/--critico) e as superfícies do painel. Nada de paleta nova —
   uma segunda paleta faria o operador aprender duas linguagens para ler a
   mesma operação. */

/* --- faixa de procedência ------------------------------------------------ */
.proc-faixa {
  display: flex; flex-wrap: wrap; align-items: center; gap: 10px 18px;
  padding: 10px 14px; border-radius: var(--raio); margin-bottom: 18px;
  border: 1px solid var(--borda); background: var(--superficie-2);
  font-size: 12.5px; color: var(--ink-2);
}
.proc-faixa.alerta { border-color: rgba(250,178,25,.45); background: var(--atencao-bg); }
.proc-faixa.ok     { border-color: rgba(12,163,12,.38);  background: var(--bom-bg); }
.proc-marca {
  font-weight: 700; letter-spacing: .08em; font-size: 11px;
  padding: 4px 9px; border-radius: 999px; white-space: nowrap;
}
.proc-real { background: var(--bom); color: #fff; }
.proc-sint { background: var(--atencao); color: #1b1b12; }
.proc-txt  { color: var(--ink); font-weight: 600; }
.proc-item b { color: var(--ink-3); font-weight: 500; }
.mono { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; }
.quebra { word-break: break-all; }

/* --- página do radar ----------------------------------------------------- */
.rx-pagina { margin-bottom: 30px; }
.rx-titulo {
  display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap;
  font-size: 19px; font-weight: 700; margin: 0 0 12px; color: var(--ink);
}
.rx-titulo small { font-size: 12.5px; font-weight: 400; color: var(--ink-3); }
.rx-n {
  font-family: ui-monospace, Menlo, monospace; font-size: 12px; color: var(--marca);
  border: 1px solid var(--borda-forte); border-radius: 6px; padding: 2px 7px;
}
.rx-nota { margin-top: 10px; }

.rx-saude { display: grid; grid-template-columns: 250px 1fr; gap: 14px; align-items: stretch; }
.rx-indice { display: flex; flex-direction: column; gap: 6px; padding: 16px 18px; }
.rx-rot { font-size: 11px; letter-spacing: .1em; text-transform: uppercase; color: var(--ink-3); }
.rx-num { font-size: 52px; font-weight: 700; line-height: 1; color: var(--ink); font-variant-numeric: tabular-nums; }
.rx-de  { font-size: 16px; color: var(--ink-3); margin-left: 4px; }
.rx-cob { font-size: 11.5px; color: var(--ink-3); }
.rx-linhas { margin-top: 6px; display: flex; flex-direction: column; gap: 4px; font-size: 12.5px; }
.rx-linhas b { font-size: 19px; font-variant-numeric: tabular-nums; }
.v-ok  { color: var(--bom); }
.v-mau { color: var(--critico); }

.rx-dims { display: grid; grid-template-columns: repeat(auto-fit, minmax(176px, 1fr)); gap: 12px; }
.rx-dim { display: flex; flex-direction: column; gap: 6px; padding: 14px 15px; }
.rx-dim-cab { display: flex; justify-content: space-between; align-items: center; gap: 8px; }
.rx-dim-rot { font-weight: 700; font-size: 12.5px; letter-spacing: .05em; }
.rx-dim-sub { font-size: 11.5px; color: var(--ink-3); line-height: 1.35; min-height: 2.4em; }
.rx-dim-val { font-size: 26px; font-weight: 700; font-variant-numeric: tabular-nums; color: var(--ink); }
.rx-dim-val.vazio { font-size: 15px; color: var(--ink-3); font-weight: 500; }
.rx-dim-meta { font-size: 11.5px; color: var(--ink-3); }
.rx-dim-var  { font-size: 11.5px; color: var(--ink-2); }
.rx-dim-var span { color: var(--ink-3); }
.rx-falta { font-size: 11px; color: var(--atencao); }
.sel-proc { font-size: 10px; letter-spacing: .07em; padding: 2px 6px; border-radius: 4px;
            border: 1px solid var(--borda-forte); color: var(--ink-3); }
.sel-proc.p-direto  { color: var(--bom); border-color: rgba(12,163,12,.45); }
.sel-proc.p-proxy   { color: var(--atencao); border-color: rgba(250,178,25,.45); }
.sel-proc.p-ausente { color: var(--critico); border-color: rgba(208,59,59,.45); }

.rx-jornada { margin-top: 14px; }
.rx-jornada-grade { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 14px; }
.rx-furo { border-left: 3px solid var(--critico); padding-left: 12px; }
.rx-furo-cab { display: flex; justify-content: space-between; gap: 10px; align-items: center; }
.rx-furo-deck { font-size: 12px; color: var(--ink-3); margin: 3px 0 6px; }
.rx-furo p { margin: 4px 0; font-size: 12.5px; line-height: 1.45; }

.rx-dupla { display: grid; grid-template-columns: 1.15fr .85fr; gap: 14px; align-items: start; }
.pastilha {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 30px; height: 22px; border-radius: 6px; font-size: 11px; font-weight: 700;
}
.pastilha.p-BOM { background: var(--bom-bg); color: var(--bom); }
.pastilha.p-ATENCAO { background: var(--atencao-bg); color: var(--atencao); }
.pastilha.p-CRITICO { background: var(--critico-bg); color: var(--critico); }
.pastilha.p-INDISPONIVEL { background: var(--neutro-bg); color: var(--neutro); }
.tab-matriz td, .tab-matriz th { padding: 7px 8px; }
.cen { text-align: center; }
.num { font-variant-numeric: tabular-nums; }

.rx-dec-grade { display: grid; grid-template-columns: repeat(auto-fit, minmax(110px, 1fr)); gap: 10px; margin: 10px 0 14px; }
.rx-dec-item { background: var(--superficie-2); border-radius: 8px; padding: 9px 11px; }
.rx-dec-item b { display: block; font-size: 22px; font-variant-numeric: tabular-nums; }
.rx-dec-item span { display: block; font-size: 11.5px; color: var(--ink-2); }
.rx-dec-item small { display: block; font-size: 10.5px; color: var(--ink-3); }

/* --- árvore -------------------------------------------------------------- */
.rx-arvore { display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px; }
.rx-arv-col { background: var(--superficie); border: 1px solid var(--borda); border-radius: var(--raio); overflow: hidden; }
.rx-arv-cab { padding: 11px 14px; color: #fff; }
.rx-arv-cab b { display: block; font-size: 13px; letter-spacing: .09em; }
.rx-arv-cab span { font-size: 11.5px; opacity: .85; }
.c-outcome  .rx-arv-cab { background: #1f6fb2; }
.c-driver   .rx-arv-cab { background: #6b4fa8; }
.c-processo .rx-arv-cab { background: #b2661f; }
.rx-arv-lista { list-style: none; margin: 0; padding: 6px; display: flex; flex-direction: column; gap: 2px; }
.rx-arv-item {
  display: grid; grid-template-columns: 26px 1fr auto; gap: 8px; align-items: baseline;
  padding: 6px 8px; border-radius: 6px; font-size: 12.5px; cursor: help;
}
.rx-arv-item:hover { background: var(--superficie-2); }
.rx-arv-n { font-family: ui-monospace, Menlo, monospace; font-size: 11px; color: var(--ink-3); }
.rx-arv-cob { font-size: 10.5px; white-space: nowrap; }
.cob-ok    { border-left: 3px solid var(--bom); }
.cob-ok    .rx-arv-cob { color: var(--bom); }
.cob-falta { border-left: 3px solid var(--atencao); }
.cob-falta .rx-arv-cob { color: var(--atencao); }
.cob-nao   { border-left: 3px solid var(--neutro); opacity: .72; }
.cob-nao   .rx-arv-cob { color: var(--neutro); }
.rx-arv-pe { padding: 8px 14px; font-size: 11px; color: var(--ink-3); border-top: 1px solid var(--borda); }

/* --- ADM ----------------------------------------------------------------- */
.aba-adm { margin-left: auto; }
.adm-topo {
  display: flex; justify-content: space-between; align-items: center; gap: 12px;
  flex-wrap: wrap; margin-bottom: 14px;
}
.adm-topo-acoes { display: flex; gap: 8px; }
.etq-perfil { background: var(--marca); color: #04121f; font-weight: 700; }

.adm-login {
  max-width: 420px; margin: 40px auto; display: flex; flex-direction: column; gap: 8px;
  background: var(--superficie); border: 1px solid var(--borda);
  border-radius: var(--raio); padding: 26px;
}
.adm-login h2 { margin: 0; font-size: 19px; }
.adm-login label { font-size: 11.5px; color: var(--ink-3); margin-top: 6px; }
.adm-login input, .adm-novo input, .adm-novo select, .adm-obs, .adm-login select {
  background: var(--superficie-2); border: 1px solid var(--borda-forte);
  border-radius: 7px; padding: 9px 11px; color: var(--ink); font: inherit; font-size: 13px;
}
.adm-login input:focus-visible { outline: 2px solid var(--marca); outline-offset: 1px; }
.adm-erro { color: var(--critico); font-size: 12.5px; margin: 4px 0 0; min-height: 1em; }
.adm-alerta { color: var(--atencao); font-size: 12.5px; margin: 4px 0; }

.adm-aviso { padding: 10px 14px; border-radius: var(--raio); margin-bottom: 14px; font-size: 13px; }
.adm-aviso.ok    { background: var(--bom-bg); color: var(--bom); }
.adm-aviso.erro  { background: var(--critico-bg); color: var(--critico); }
.adm-aviso.alerta{ background: var(--atencao-bg); color: var(--atencao); }

.adm-cargas { display: grid; grid-template-columns: repeat(auto-fit, minmax(330px, 1fr)); gap: 14px; }
.adm-carga { display: flex; flex-direction: column; gap: 9px; }
.adm-colunas { font-size: 11.5px; color: var(--ink-2); line-height: 1.5; }
.adm-ativa { background: var(--superficie-2); border-radius: 8px; padding: 10px 12px; font-size: 12.5px; }
.adm-sem { background: var(--atencao-bg); color: var(--atencao); border-radius: 8px; padding: 10px 12px; font-size: 12.5px; }
.adm-envio { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.adm-envio input[type="file"] { font-size: 12px; color: var(--ink-2); max-width: 100%; }
.adm-obs { flex: 1; min-width: 140px; }
.adm-acoes { display: flex; gap: 8px; flex-wrap: wrap; }
.adm-recado:empty { display: none; }
.adm-resultado { border-radius: 8px; padding: 10px 12px; display: flex; flex-direction: column; gap: 6px; font-size: 12.5px; }
.adm-resultado.ok { background: var(--bom-bg); }
.adm-resultado.erro { background: var(--critico-bg); }
.adm-resultado .btn { align-self: flex-start; }
.adm-segredo { font-size: 18px; letter-spacing: .12em; background: var(--superficie-2);
               padding: 12px; border-radius: 8px; word-break: break-all; }
.adm-barra-cob { height: 10px; border-radius: 5px; background: var(--superficie-3); overflow: hidden; margin-bottom: 8px; }
.adm-barra-cob i { display: block; height: 100%; background: var(--bom); }
.adm-faltantes { display: flex; flex-wrap: wrap; gap: 6px; align-items: baseline; font-size: 12px; }
.adm-novo { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 12px; align-items: center; }
.adm-perfis { margin-top: 12px; font-size: 12px; color: var(--ink-2); display: flex; flex-direction: column; gap: 3px; }
.tab-trilha td { font-size: 11.5px; }
.e-ativa     { color: var(--bom); }
.e-validada  { color: var(--marca); }
.e-rejeitada { color: var(--critico); }
.e-subst     { color: var(--ink-3); }
.bloco-cod { background: var(--superficie-2); padding: 12px; border-radius: 8px;
             font-size: 12px; overflow-x: auto; white-space: pre; }

@media (max-width: 1100px) {
  .rx-saude, .rx-dupla { grid-template-columns: 1fr; }
  .rx-arvore { grid-template-columns: 1fr; }
}
@media (max-width: 620px) {
  .rx-num { font-size: 40px; }
  .aba-adm { margin-left: 0; }
}

/* Tabela larga no telefone: ela mesma vira o contêiner de rolagem, para que a
   PÁGINA nunca role de lado. Página que rola na horizontal esconde a primeira
   coluna — justamente a que diz de quem é a linha. */
@media (max-width: 820px) {
  .cartao { max-width: 100%; }
  .cartao table.tab { display: block; overflow-x: auto; max-width: 100%; }
  .cartao table.tab thead, .cartao table.tab tbody { display: table; width: max-content; min-width: 100%; }
  .proc-faixa { font-size: 11.5px; }
}

/* Filho de grid/flex tem min-width AUTO por padrão: o conteúdo mais largo
   (uma tabela) empurra a coluna e estoura a página inteira. `min-width: 0`
   devolve à coluna o direito de ser menor que o conteúdo — e aí a rolagem
   acontece dentro da tabela, como planejado acima. */
.rx-dupla > *, .rx-saude > *, .rx-arvore > *, .adm-cargas > *,
.rx-dims > *, .rx-jornada-grade > * { min-width: 0; }

.adm-conex { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
             gap: 8px 16px; font-size: 12.5px; margin-bottom: 10px; }
.adm-conex b { color: var(--ink-3); font-weight: 500; }
.adm-etapas { list-style: none; margin: 8px 0 0; padding: 0;
              display: flex; flex-direction: column; gap: 6px; font-size: 12.5px; }
.adm-etapas li { padding-left: 20px; position: relative; }
.adm-etapas li::before { position: absolute; left: 0; }
.et-ok::before { content: "●"; color: var(--bom); }
.et-x::before  { content: "■"; color: var(--critico); }
.adm-teste:empty { display: none; }

.etq-leitura { background: var(--bom); color: #fff; font-weight: 700; letter-spacing: .06em; }
.adm-garantia { background: var(--bom-bg); color: var(--ink-2); border-left: 3px solid var(--bom);
                padding: 9px 12px; border-radius: 6px; font-size: 12.5px; line-height: 1.5;
                margin-bottom: 8px; }
.adm-garantia b { color: var(--bom); }

.adm-sub { font-size: 11px; letter-spacing: .1em; text-transform: uppercase;
           color: var(--ink-3); margin: 14px 0 6px; padding-top: 10px;
           border-top: 1px solid var(--borda); }
.adm-etapas li b { text-transform: none; letter-spacing: 0; }
.adm-resultado .etq { margin-left: 8px; }
/* Sem isto o nome e a etiqueta de perfil encostam: "artur.silvaadmin". */
.adm-topo .etq { margin-left: 8px; }

/* --- formulário da conexão ---------------------------------------------- */
.cx-estado { display: flex; flex-wrap: wrap; gap: 8px 18px; font-size: 12.5px;
             padding-bottom: 12px; margin-bottom: 4px; border-bottom: 1px solid var(--borda);
             color: var(--ink-2); }
.cx-form { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
           gap: 10px 14px; margin: 12px 0 4px; }
.cx-largo { grid-column: 1 / -1; }
.cx-campo { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.cx-campo label { font-size: 11.5px; color: var(--ink-3); }
.cx-campo input, .cx-campo select, .cx-campo textarea {
  background: var(--superficie-2); border: 1px solid var(--borda-forte);
  border-radius: 7px; padding: 8px 10px; color: var(--ink);
  font: inherit; font-size: 13px; width: 100%;
}
.cx-campo textarea { font-family: ui-monospace, Menlo, Consolas, monospace;
                     font-size: 11.5px; resize: vertical; }
.cx-campo input:focus-visible, .cx-campo select:focus-visible,
.cx-campo textarea:focus-visible { outline: 2px solid var(--marca); outline-offset: 1px; }
.cx-campo input::placeholder, .cx-campo textarea::placeholder { color: var(--ink-3); }
.cx-marca { display: flex; align-items: flex-start; gap: 8px; font-size: 12.5px; }
.cx-marca input { width: auto; margin-top: 2px; }
.cx-marca label { font-size: 12.5px; color: var(--ink-2); }

/* Lembrete de VPN na seção de origem do dado: precisa ser visto antes de
   alguém começar a mexer em usuário e senha atrás de um problema de rede. */
.nota-vpn {
  border-left: 3px solid var(--atencao, #d08700);
  background: color-mix(in srgb, var(--atencao, #d08700) 8%, transparent);
  padding: 10px 12px; border-radius: 6px; margin: 0 0 12px;
}

/* ==================================================================== */
/*  PALETA DO CORE  —  amostrada do próprio Core App (24/09/2026)        */
/* ==================================================================== */
/*  Pedido do Artur: "procure seguir a paleta do Core". As cores abaixo   */
/*  não foram escolhidas por gosto — foram medidas nos pixels das telas   */
/*  do Core (Gestão TOA, Residencial, MDU, Empresarial e Book/Painel),    */
/*  para que um número visto lá e aqui tenha a MESMA cor quando significa */
/*  a mesma coisa. Cor que muda de sentido entre duas telas do mesmo      */
/*  produto é ruído que o leitor paga.                                    */
/*                                                                        */
/*  O mapeamento semântico que o Core usa, e que herdamos:                */
/*    laranja tracejado ... META (a linha de compromisso)                 */
/*    preto ............... REALIZADO do ano corrente                     */
/*    azul ................ mesmo indicador no ano anterior               */
/*    cinza claro ......... anos mais antigos                             */
/*    verde ............... dentro da meta                                */
/*    vermelho ............ fora da meta                                  */
/*                                                                        */
/*  Cuidado deliberado: o vermelho de marca (#FF140A, da barra superior)  */
/*  é QUASE o mesmo vermelho de "fora da meta" (#C9262C). No Core isso    */
/*  funciona porque um é cromo e o outro é dado, e eles não se encostam.  */
/*  Aqui a barra superior usa o vermelho de marca e NENHUM dado usa esse  */
/*  tom — senão "fora da meta" e "identidade visual" viram a mesma coisa. */
:root[data-theme="light"] {
  --core-vermelho:     #FF140A;   /* barra superior, identidade            */
  --core-vermelho-esc: #CC1008;
  --core-plano:        #F3F6FC;   /* fundo da página                       */
  --core-linha:        #E4E9F3;
  --core-meta:         #FF6D00;   /* meta, sempre tracejada                */
  --core-atual:        #111111;   /* realizado do ano corrente             */
  --core-anterior:     #478FED;   /* ano anterior                          */
  --core-antigo:       #C6CBD1;   /* anos mais antigos                     */
  --core-dentro:       #009966;
  --core-dentro-bg:    #ECFDF5;
  --core-fora:         #C9262C;
  --core-fora-bg:      #FDECEC;

  /* grupos do Book, na ordem em que o Core os apresenta */
  --core-g-rede:        #DD9A3C;
  --core-g-contact:     #4D77CB;
  --core-g-recuperacao: #9346B9;
  --core-g-gpon:        #3997C6;
  --core-g-empresarial: #6A59C0;
  --core-g-preventiva:  #46B976;
  --core-g-outages:     #C65353;
  --core-g-custos:      #CCCCCC;

  /* o painel passa a falar a língua do Core */
  --plano:     var(--core-plano);
  --marca:     var(--core-vermelho);
  --bom:       var(--core-dentro);
  --bom-bg:    var(--core-dentro-bg);
  --critico:   var(--core-fora);
  --critico-bg: var(--core-fora-bg);
  --atencao:   var(--core-meta);
  --serie-1:   var(--core-atual);
  --serie-2:   var(--core-anterior);
  --serie-3:   var(--core-antigo);
  --borda:     var(--core-linha);
}

/* No tema escuro os tons do Core perdem contraste sobre fundo preto, então
   só a SEMÂNTICA é herdada; os valores são clareados. Manter o mesmo
   significado importa mais que manter o mesmo hexadecimal. */
:root:not([data-theme="light"]) {
  --core-meta:     #FF8F3C;
  --core-atual:    #F2F4F7;
  --core-anterior: #6FA8F5;
  --core-antigo:   #7C848E;
  --core-dentro:   #2FC98F;
  --core-fora:     #F0565C;
}

/* A faixa de identidade: vermelho Claro, como no Core. */
.topo-marca-core {
  background: var(--core-vermelho);
  color: #fff;
}
/* Meta é tracejada em toda parte, no Core e aqui. A linha cheia é o que
   aconteceu; a tracejada é o que se prometeu. Trocar isso inverte a leitura. */
.serie-meta { stroke: var(--core-meta); stroke-dasharray: 6 4; fill: none; }
.serie-atual { stroke: var(--core-atual); fill: none; }
.serie-anterior { stroke: var(--core-anterior); fill: none; }

/* Idade do dado — a distinção que o Core não faz e que aqui é obrigatória. */
.sel-frescor {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 11px; padding: 2px 8px; border-radius: 999px;
  border: 1px solid var(--borda-forte);
}
.sel-frescor.dataset { color: var(--core-dentro); border-color: var(--core-dentro); }
.sel-frescor.book    { color: var(--ink-3); }

/* Barra de cobertura da migração. Fundo neutro e preenchimento verde: a
   leitura é "quanto já chegou", não "quanto falta" — a mesma direção que o
   Core usa na coluna de consolidação. */
.def-barra {
  height: 8px; border-radius: 999px; overflow: hidden;
  background: var(--superficie-3); border: 1px solid var(--borda);
}
.def-barra-cheia { height: 100%; border-radius: 999px; }

/* Aba Esclarecimentos: cada pendência é um cartão, porque cada uma exige
   leitura de três linhas — decidi, alternativa, o que quebra se errar. Lista
   compacta esconderia justamente a parte que precisa de atenção. */
.esc-item { margin: 10px 0; }
.esc-topo { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-bottom: 6px; }
.esc-feito { opacity: .72; }
.esc-item p { margin: 6px 0; }

/* ==================================================================== */
/*  ABA CONCEITOS                                                        */
/* ==================================================================== */
/*  Cartão fechado mostra título, a frase única e o erro que evita — é o  */
/*  suficiente para decidir se vale abrir. Abrir 25 conceitos de uma vez  */
/*  produziria uma parede de texto, e parede de texto não ensina.         */
.cnc-cartao { margin: 8px 0; padding: 12px 14px; }
.cnc-cartao > summary {
  cursor: pointer; list-style: none; display: flex; flex-wrap: wrap;
  align-items: baseline; gap: 10px;
}
.cnc-cartao > summary::-webkit-details-marker { display: none; }
.cnc-cartao > summary::before {
  content: '▸'; color: var(--ink-3); transition: transform .15s;
}
.cnc-cartao[open] > summary::before { content: '▾'; }
.cnc-titulo { font-weight: 700; }
.cnc-frase { color: var(--ink-2); flex: 1 1 260px; min-width: 0; }
.cnc-erro { margin: 8px 0 0; font-size: 13px; color: var(--ink-2); }
.cnc-corpo p { margin: 10px 0; max-width: 72ch; }

/* O desenho rola sozinho no celular em vez de espremer o esquema até a
   ilegibilidade — um DAG amassado não explica DAG nenhum. */
.cnc-desenho { margin: 14px 0; overflow-x: auto; }
.cnc-svg { width: 100%; min-width: 480px; height: auto; color: var(--ink); }

.cnc-exemplo {
  margin: 12px 0; padding: 10px 12px; border-radius: 6px;
  background: var(--superficie-2); border-left: 3px solid var(--core-anterior);
}
.cnc-exemplo pre {
  margin: 6px 0 0; font-size: 12px; line-height: 1.5;
  white-space: pre-wrap; overflow-x: auto;
}
.cnc-pe {
  margin-top: 12px; padding-top: 10px; border-top: 1px solid var(--borda);
  display: flex; flex-wrap: wrap; gap: 8px 14px; align-items: center;
}
.cnc-link {
  border: 1px solid var(--borda-forte); background: transparent;
  color: var(--marca); border-radius: 999px; padding: 2px 10px;
  font-size: 11px; cursor: pointer;
}
.cnc-link:hover { background: var(--superficie-3); }

/* Ponte da tela para as páginas de documentação. O botão fica onde a dúvida
   aparece — não num menu que só quem já sabe procura. */
.doc-links { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin: 6px 0 16px; }
.botao-doc {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 8px 14px; border-radius: 8px; text-decoration: none;
  background: var(--marca); color: #fff; font-weight: 600; font-size: 13px;
  white-space: nowrap;
}
.botao-doc::after { content: '↗'; opacity: .8; }
.botao-doc:hover { filter: brightness(1.08); }

/* A página de documentação embutida na aba. Altura fixa em vez de automática:
   o conteúdo é longo e tem rolagem própria — deixá-lo empurrar a página
   faria a barra do app sair de vista. */
.quadro-doc {
  width: 100%; border: 0; display: block; background: transparent;
  height: calc(100vh - 190px); min-height: 460px;
}
.doc-barra {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  padding: 10px 0 12px; border-bottom: 1px solid var(--borda); margin-bottom: 8px;
}
.doc-barra .espaco { flex: 1 1 auto; }

/* ---------------------------------------------------------- dicas --- */
/* O `?` ao lado do rótulo. Discreto quando ligado, ausente quando o
   interruptor está desligado — a explicação não foi removida, foi tirada
   da frente de quem já sabe. */
.pino-dica {
  width: 17px; height: 17px; flex: none; margin-left: 6px;
  border-radius: 50%; border: 1px solid var(--borda-forte);
  background: var(--superficie-2); color: var(--ink-3);
  font: 700 10px/1 var(--fonte); cursor: help; padding: 0;
  display: inline-flex; align-items: center; justify-content: center;
  vertical-align: middle;
}
.pino-dica:hover { background: var(--marca); color: #fff; border-color: var(--marca); }
:root[data-dicas="off"] .pino-dica { display: none; }

/* --------------------------------------------------------------- balão ---
   AZUL MÉDIO, FONTE BRANCA, CANTOS ARREDONDADOS, BICO.

   Pedido literal do Artur, e cada parte resolve um problema:

   · AZUL MÉDIO FIXO (não tematizado). O balão anterior usava a cor de
     superfície do tema — cinza sobre cinza no escuro, branco sobre branco no
     claro. Existia e não se distinguia da tela. Um azul próprio funciona nos
     dois temas e nunca se confunde com conteúdo.
   · O azul é o MESMO nos dois temas de propósito: o balão é uma camada acima
     da interface, não parte dela. Trocar de tema não deve mover a referência
     visual de "isto é explicação".
   · #1e63c8 → #2f7de0 em degradê suave: dá volume sem sombra dura, que é o
     que faz um balão parecer elegante em vez de caixa de aviso de sistema.
   · Contraste do branco sobre #2a72d8: 5,1:1 — acima de AA para texto
     normal. Azul mais claro ficaria bonito e ilegível.
*/
.balao-dica {
  position: fixed; z-index: 200; max-width: 340px;
  background: linear-gradient(160deg, #2f7de0, #1e5fc0);
  color: #fff; border: 1px solid rgba(255,255,255,.22);
  border-radius: 14px; padding: 12px 15px;
  font: 400 13px/1.58 var(--fonte);
  box-shadow: 0 10px 30px rgba(10,30,70,.40), 0 2px 6px rgba(10,30,70,.30);
  pointer-events: none;            /* o balão nunca rouba o mouse do alvo */
  animation: balao-entra .13s ease-out;
}
.balao-dica b {
  display: block; color: #fff; font-size: 13px; font-weight: 700;
  letter-spacing: .01em; margin-bottom: 5px;
  padding-bottom: 5px; border-bottom: 1px solid rgba(255,255,255,.26);
}
.balao-dica span {
  display: block; color: rgba(255,255,255,.94);
  /* `pre-line` e não `normal`: quando a dica é uma LISTA (os limites do
     método, por exemplo) ela vem com quebras de linha no atributo, e sem
     isto os quatro itens virariam um parágrafo corrido com bolinhas no meio.
     `pre-line` honra a quebra e continua colapsando o espaço em branco —
     `pre` colapsaria nada e reproduziria a indentação do código-fonte. */
  white-space: pre-line;
}

/* O BICO. Um quadrado girado 45°, com o mesmo degradê, posicionado por JS
   para apontar ao centro do ALVO — e não ao centro do balão, que é o que
   diverge quando o balão encosta na borda da janela. */
.balao-bico {
  position: absolute; width: 11px; height: 11px;
  background: #2f7de0; border: 1px solid rgba(255,255,255,.22);
  transform: translateX(-50%) rotate(45deg);
}
.balao-dica[data-lado="baixo"] .balao-bico {
  top: -6px; border-right: none; border-bottom: none;
}
.balao-dica[data-lado="cima"] .balao-bico {
  bottom: -6px; background: #1e5fc0; border-left: none; border-top: none;
}
@keyframes balao-entra {
  from { opacity: 0; transform: translateY(-3px); }
  to   { opacity: 1; transform: none; }
}
/* Qualquer coisa explicável ganha o cursor de ajuda — a affordance que diz
   "há texto aqui" antes de o mouse parar. */
[data-t] { cursor: help; }
[data-t].r37-alvo { cursor: crosshair; }

/* ----------------------------------------------------------- sair --- */
.btn-sair { border-color: var(--critico); color: var(--critico); }
.btn-sair:hover { background: var(--critico); color: #fff; }
.sair-fundo {
  position: fixed; inset: 0; z-index: 100; display: grid; place-items: center;
  background: color-mix(in srgb, var(--plano) 82%, transparent);
  backdrop-filter: blur(4px); padding: 16px;
}
.sair-caixa {
  background: var(--superficie); border: 1px solid var(--borda-forte);
  border-radius: 14px; box-shadow: var(--sombra); padding: 22px 24px;
  max-width: 560px; width: 100%;
}
.sair-caixa h3 { margin: 0 0 10px; }
.sair-acoes { display: flex; gap: 10px; flex-wrap: wrap; margin-top: 16px; }
.sair-final { max-width: 560px; margin: 18vh auto; padding: 0 16px; text-align: center; }
.sair-final h1 { font-size: 26px; margin-bottom: 10px; }

/* ===========================================================================
   RADAR EXECUTIVO — os 37 cartões
   ===========================================================================
   A GRADE
   `auto-fill` com mínimo de 300px: em monitor de reunião dá 4 colunas, em
   notebook 3, em tela dividida 2. Não há breakpoint escrito — a largura do
   cartão é que decide, e ela é a mesma sempre. Cartão que muda de tamanho
   conforme a tela muda o desenho do SVG dentro dele, e aí a rosca de um
   indicador fica maior que a de outro sem motivo.

   Densidade: o Artur pediu "o formato mais moderno" e o recorte do anexo é um
   dashboard escuro e compacto. Compacto aqui significa 37 cartões roláveis com
   3 números e 13 meses legíveis em cada, não 37 caixas apertadas.
   =========================================================================== */
.r37-topo {
  display: flex; align-items: flex-end; gap: 18px; flex-wrap: wrap;
  padding: 2px 0 14px; margin-bottom: 14px;
  border-bottom: 1px solid var(--borda);
}
.r37-titulo h2 { margin: 0; font-size: 21px; letter-spacing: -.01em; }
.r37-sub { margin: 4px 0 0; color: var(--ink-2); font-size: 13.5px; }
.r37-meta-topo { display: flex; align-items: center; gap: 10px;
  flex-wrap: wrap; margin-left: auto; }
.r37-chip {
  display: inline-flex; align-items: center; gap: 6px;
  background: var(--superficie-2); border: 1px solid var(--borda);
  border-radius: 999px; padding: 6px 13px;
  /* A/A, TRI, CV, META — pedido 104. São os quatro números que ele lê em
     voz alta na conversa com a regional, e estavam no mesmo corpo de um
     rótulo auxiliar. 13,5px com algarismo tabular: o rótulo continua
     pequeno, o NÚMERO cresce (ver a regra de `b` logo abaixo). */
  font: 600 12.5px/1 var(--fonte); color: var(--ink-2);
  font-variant-numeric: tabular-nums lining-nums;
}
.r37-sel { display: inline-flex; align-items: center; gap: 7px; font-size: 12px;
  color: var(--ink-3); }
.r37-sel select {
  background: var(--superficie-2); color: var(--ink);
  border: 1px solid var(--borda); border-radius: 8px; padding: 6px 9px;
  font: 600 12px/1 var(--fonte);
}

/* A TIRA DE CONTAGEM — quatro números que somam 37, sempre.
   Ela existe para responder de longe "quantos dos meus 37 estão de pé": é a
   primeira pergunta do Artur sobre o escopo, e ela cabe em quatro números. */
.r37-tira { display: flex; gap: 10px; flex-wrap: wrap; margin-bottom: 16px; }
.r37-tira-item {
  display: flex; align-items: baseline; gap: 8px;
  background: var(--superficie); border: 1px solid var(--borda);
  border-left: 3px solid var(--neutro);
  border-radius: 9px; padding: 9px 14px;
}
.r37-tira-item b { font-size: 19px; font-variant-numeric: tabular-nums; }
.r37-tira-item span { font-size: 12px; color: var(--ink-2); }
.r37-tira-item.tom-ok      { border-left-color: var(--bom); }
.r37-tira-item.tom-atencao { border-left-color: var(--atencao); }
.r37-tira-item.tom-mau     { border-left-color: var(--critico); }
.r37-tira-item.tom-neutro  { border-left-color: var(--neutro); }

/* A grade NÃO tem display próprio: cada modo declara o seu, logo abaixo.
   Antes ela era `grid` com `auto-fill`, e isso sobrevivia à troca de modo — a
   tabela virava um item de grade de 300px e ficava espremida num canto. */
.r37-grade { display: block; }
/* ------------------------------------------------ O CARTÃO, NO ESQUADRO --
   Artur: "tudo tem que ficar alinhado... preciso de tudo alinhado e no
   esquadro."

   O problema era de ALTURA VARIÁVEL entre blocos irmãos. Um cartão com tarja
   de referência empurrava a rosca para baixo; um sem tarja não. Lado a lado,
   os três números da primeira linha ficavam em alturas diferentes e o olho
   perdia a comparação — que é justamente para o que a grade existe.

   A correção tem duas partes, e as duas importam:

   1. GRID EM VEZ DE FLEX no cartão, com faixas nomeadas. Cada bloco ocupa
      SEMPRE a sua faixa, e faixa vazia continua ocupando a altura dela. É o
      que mantém o alinhamento entre cartões que têm blocos diferentes.
   2. `align-items: stretch` na grade dos 37, para todos os cartões da linha
      terem a mesma altura — e a série, que é o último bloco, encostar sempre
      na mesma linha de base. */
.r37-cartao {
  background: var(--superficie); border: 1px solid var(--borda);
  border-radius: 13px; padding: 13px 14px 11px;
  display: grid; gap: 10px;
  grid-template-rows: auto auto 1fr;   /* cabeça · corpo · série */
  align-content: start;
}
/* A série é a última faixa e cresce: assim o eixo dos meses encosta no rodapé
   do cartão, e os treze rótulos ficam na mesma linha em toda a grade. */
.r37-cartao .r37-hist { align-self: end; }
/* A borda superior colorida carrega o farol sem depender de ler o rótulo.
   Cor NUNCA sozinha: o rótulo textual do farol está no cartão logo abaixo. */
.r37-cartao[data-farol="OK"]        { box-shadow: inset 0 2px 0 var(--bom); }
.r37-cartao[data-farol="SUPERADO"]  { box-shadow: inset 0 2px 0 var(--superado); }
.r37-cartao[data-farol="CRITICO"]   { box-shadow: inset 0 2px 0 var(--critico); }
.r37-cartao[data-farol="SEM_POLARIDADE"],
.r37-cartao[data-farol="SEM_LEITURA"] { box-shadow: inset 0 2px 0 var(--neutro); }

/* Cartão sem número fica visivelmente diferente — pedido explícito: "o que
   não tem dados disponíveis deve claramente estar visível". Tracejado e
   levemente rebaixado: presente, contado, e inconfundível com um cartão que
   tem número. */
.r37-cartao.r37-sem_book, .r37-cartao.r37-ausente,
.r37-cartao.r37-a_confirmar, .r37-cartao.r37-sem_leitura {
  border-style: dashed; background: var(--superficie-2);
}

/* O CABEÇALHO NÃO QUEBRA LINHA. Nome longo (CUSTO MANUTENÇÃO RE UNIT) fazia o
   cabeçalho virar duas linhas em alguns cartões e uma em outros — e a rosca de
   cada um começava numa altura diferente. Agora o nome trunca com reticências
   e o `title` traz o nome inteiro: um cartão a menos de altura variável. */
.r37-cab { display: flex; align-items: center; gap: 8px; flex-wrap: nowrap;
  min-height: 26px; }
.r37-cab h3 {
  margin: 0; font-size: 13px; font-weight: 700; letter-spacing: .01em;
  color: var(--ink); flex: 1 1 auto; min-width: 0; line-height: 1.3;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.r37-pos {
  flex: none; font: 700 10.5px/1 var(--fonte); color: var(--ink-3);
  background: var(--superficie-3); border-radius: 6px; padding: 5px 6px;
  font-variant-numeric: tabular-nums;
}
.r37-pol {
  flex: none; font: 700 10px/1 var(--fonte); border-radius: 999px;
  padding: 4px 8px; white-space: nowrap;
}
.r37-pol-alto  { background: var(--bom-bg);     color: var(--bom); }
.r37-pol-baixo { background: var(--atencao-bg); color: var(--atencao); }
.r37-pol-nd    { background: var(--neutro-bg);  color: var(--neutro); }

/* Alinhados pelo TOPO, não pelo centro. Centralizar fazia a rosca subir ou
   descer conforme quantas linhas o bloco ao lado tinha — e cartões vizinhos
   com blocos diferentes desalinhavam entre si. */
.r37-corpo { display: flex; gap: 12px; align-items: flex-start; }
.r37-medidor { flex: none; display: flex;
  flex-direction: column; align-items: center; gap: 5px; }
.r37-rosca { width: calc(120px * var(--rosca-w, 1));
  height: calc(120px * var(--rosca-w, 1) * var(--rosca-k, 1));
  display: block; overflow: visible; }
.r37-val { font: 700 25px/1 var(--fonte); font-variant-numeric: tabular-nums; }
.r37-vazio { font: 600 11px/1 var(--fonte); fill: var(--ink-3); }
/* O VOLANTE — pedido 131. Os dois rótulos que acompanham o número grande.
   A UNIDADE sai de junto dos algarismos e desce uma linha (é o «km/h» do
   anexo dele). Fraca e pequena de propósito: ela existe para ser encontrada
   por quem duvida da escala, não para competir com o número. Mas existe —
   «0,74» nu, sem o «%», foi defeito que ele achou no espelho do ICG.
   A META ESCRITA é o segundo número do painel (o «105961 KM» do anexo). A
   barra diz ONDE a meta está; esta linha diz QUANTO ela é. O rótulo fica em
   tinta fraca e o número em tinta normal, porque é o número que se lê. */
/* O NÚMERO DO VOLANTE USA A VOZ DE INSTRUMENTO — e só ele. As duas
   semi-roscas ficam na família de texto: trocar a letra das três de uma vez
   seria mudar o painel inteiro por causa de uma opção de cartão, e a forma é
   justamente o que o usuário escolhe por cartão.
   `wdth 100` força o eixo de largura do Bahnschrift para o normal: o padrão
   dele é condensado, e o anexo tem algarismo LARGO. Em qualquer face que não
   tenha esse eixo a linha é ignorada, sem efeito colateral. */
/* SEM `font-variation-settings` — e a ausência é deliberada, pedido 132.
   Ela estava aqui para forçar o eixo de largura do Bahnschrift ao normal,
   porque o padrão dele é condensado e o anexo tem algarismo largo. Só que o
   canvas 2D, que é quem MEDE o corpo do número, não aplica eixo de fonte
   variável: eu media no condensado e desenhava no largo, e o número saía por
   cima do «Realizado» e do «Meta» do cartão — o encavalamento que ele
   fotografou. Medir numa fonte e desenhar em outra é medir a régua errada.
   O condensado, aliás, é mais voz de instrumento, não menos.
   `letter-spacing` negativo fica: ele deixa o texto real mais ESTREITO que o
   medido, que é o lado seguro de errar. */
.r37-volante .r37-val {
  font-family: var(--fonte-painel);
  letter-spacing: -.01em;
  font-variant-numeric: tabular-nums lining-nums;
}
.r37-vu {
  font: 700 9.5px/1 var(--fonte-painel); fill: var(--ink-3);
  text-transform: uppercase; letter-spacing: .14em;
}
.r37-vmeta {
  font: 600 8.5px/1 var(--fonte); fill: var(--ink-3);
  text-transform: uppercase; letter-spacing: .08em;
}
.r37-vmeta-n {
  font-weight: 800; fill: var(--meta); letter-spacing: 0;
  text-transform: none;
}
.r37-farol {
  min-height: 24px; display: flex; align-items: center; justify-content: center;
  font: 700 9.5px/1.2 var(--fonte); text-align: center;
  text-transform: uppercase; letter-spacing: .04em;
}
.farol-ok { color: var(--bom); }
.farol-superado { color: var(--superado); }
.farol-critico { color: var(--critico); }
.farol-sem_polaridade, .farol-sem_leitura { color: var(--neutro); }

.r37-numeros { flex: 1 1 auto; min-width: 0; display: flex;
  flex-direction: column; gap: 4px; }
.r37-linha { display: flex; justify-content: space-between; align-items: baseline;
  gap: 8px; padding: 3px 0; border-bottom: 1px dashed var(--borda); }
.r37-rot { font-size: 11px; color: var(--ink-3); }
.r37-linha b { font: 700 13px/1 var(--fonte); font-variant-numeric: tabular-nums;
  white-space: nowrap; }
.r37-b-val  { color: var(--ink); }
.r37-b-meta { color: var(--meta); }
.r37-b-des  { color: var(--desafio); }
/* Altura mínima no rodapé: cartão sem seta de movimento tinha o bloco de
   números mais curto, e a série começava mais alta que a do vizinho. */
.r37-rodape { display: flex; align-items: center; gap: 7px; flex-wrap: wrap;
  margin-top: 3px; min-height: 26px; }
.r37-seta { font: 700 11px/1 var(--fonte); font-variant-numeric: tabular-nums;
  border-radius: 6px; padding: 4px 7px; }
.sobe-bom    { color: var(--bom);     background: var(--bom-bg); }
.sobe-mau    { color: var(--critico); background: var(--critico-bg); }
.sobe-neutro { color: var(--neutro);  background: var(--neutro-bg); }
/* A ORIGEM E A CADÊNCIA, NO MESMO ESQUEMA DE COR
   ------------------------------------------------
   Artur: "o que for M-1 (deixe claro ao lado ser do Book) mas siga o mesmo
   esquema de cores pois da forma que está parece estar faltando algo."

   Ele descreveu com precisão o defeito: `dataset · D-1` vinha em azul, com
   borda colorida, e o `M-1` vinha em cinza tracejado. Cinza ao lado de
   colorido não lê como "outra origem" — lê como CAMPO VAZIO, exatamente o
   mesmo problema que o farol cinza tinha antes.

   Agora as duas são etiquetas irmãs: mesma forma, mesma estrutura, mesma
   família de cor. O que as separa é o NOME da origem (dataset / Book), que é
   a informação de verdade, e não a ausência de cor, que não é informação
   nenhuma.

   A cadência continua em `tabular-nums` para D-0, D-1 e M-1 terem a mesma
   largura: etiqueta que muda de largura entre cartões desalinha a linha
   inteira do rodapé. */
/* O SELO DA SEGUNDA FONTE — pedido 111. Mesma gramática da pastilha de
   frescor ao lado (é da mesma família: as duas falam de procedência), com
   tom de ATENÇÃO e não de erro: nada está quebrado, o número só não vem de
   onde os outros 36 vêm. */
.r37-selo {
  display: inline-flex; align-items: baseline; gap: 4px;
  font: 700 9.5px/1 var(--fonte); letter-spacing: .04em; cursor: default;
  border: 1px dashed; border-radius: 5px; padding: 4px 7px;
  font-variant-numeric: tabular-nums;
  color: var(--atencao);
  border-color: color-mix(in srgb, var(--atencao) 55%, transparent);
  background: color-mix(in srgb, var(--atencao) 10%, transparent);
}
/* TRACEJADO DE PROPÓSITO, e é a mesma convenção do resto da tela: tracejado
   quer dizer «não acaba aqui» (a projeção, a bolha aparada). Aqui ele diz
   que esta procedência é de passagem — some quando o Core entregar. */
/* SEM RELÓGIO — tom de crítico e não de atenção, de propósito. O cartão com
   relógio faltando não é um cartão «quase pronto»: é um cartão que não pode
   afirmar frescor, e frescor é metade do que um painel executivo promete. */
.r37-selo-semrel {
  color: var(--critico);
  border-color: color-mix(in srgb, var(--critico) 55%, transparent);
  background: color-mix(in srgb, var(--critico) 9%, transparent);
}
.r37-selo-sem {
  color: var(--ink-3);
  border-color: color-mix(in srgb, var(--ink-3) 40%, transparent);
  background: transparent;
}
.r37-fresc {
  display: inline-flex; align-items: baseline; gap: 4px;
  font: 700 9.5px/1 var(--fonte); letter-spacing: .04em; cursor: default;
  border: 1px solid; border-radius: 5px; padding: 4px 7px;
  font-variant-numeric: tabular-nums;
  color: var(--serie-1); border-color: color-mix(in srgb, var(--serie-1) 45%, transparent);
  background: color-mix(in srgb, var(--serie-1) 11%, transparent);
}
.r37-fresc i {
  font-style: normal; font-weight: 600; font-size: 9px; opacity: .78;
  text-transform: none; letter-spacing: .02em;
}
/* O Book é a OUTRA origem, e ganha a outra cor da mesma família — não a
   ausência de cor. `--serie-3` é o verde-azulado da paleta de séries: parente
   do azul do dataset, distinto dele, e nenhum dos dois é um estado de farol
   (que roubaria significado de onde ele importa). */
.r37-fresc.fresc-book_manual_m1 {
  color: var(--serie-3); border-color: color-mix(in srgb, var(--serie-3) 45%, transparent);
  background: color-mix(in srgb, var(--serie-3) 11%, transparent);
}
/* Cadência MEDIDA no log de execução: linha cheia. Deduzida da origem:
   tracejada. A diferença entre "D-1 porque medimos" e "D-1 porque dataset
   costuma ser D-1" é real, e o tracejado é o que a torna visível sem uma
   palavra a mais. */
.r37-fresc:not(.fresc-medida) { border-style: dashed; }
/* A competência de origem, quando o número é de outro mês. Dentro da própria
   etiqueta: é a mesma afirmação ("de onde vem este número"), e separá-la em
   outro elemento era o que gerava as três tarjas dizendo o mesmo fato. */
.fresc-ref { font-weight: 700; opacity: .92; white-space: nowrap;
  padding-left: 4px; margin-left: 3px;
  border-left: 1px solid color-mix(in srgb, currentColor 35%, transparent); }

/* A lista de cargas, na segunda aba do anel. */
.etl-lista td { vertical-align: top; padding: 5px 8px 5px 0; }
.etl-lista tr + tr td { border-top: 1px solid var(--borda); }
.etl-meta { font-size: 10.5px; color: var(--ink-3); }
.etl-atrasado td:first-child { border-left: 2px solid var(--critico);
  padding-left: 7px; }

/* ------------------------------------------ o rodapé do cartão ---------
   Artur: "os textos como o abaixo (dos limites da série) e os outros acima
   podem ser dispostos de outra forma assim livra espaço".

   Eram três linhas de texto em volta de um gráfico de 94 px: o cabeçalho
   "13 MESES · ANO A ANO", o "-4,23% vs ago/25" à direita e as duas pontas
   "set/25 … set/26" embaixo. Juntas gastavam mais altura que o desenho.

   Agora:
     · o cabeçalho SAIU — "13 meses" já está dito pelas treze iniciais na
       base, e dizer duas vezes não é reforço, é ocupação de espaço;
     · o ano a ano VIRA UM SELO FLUTUANTE no canto do gráfico, sobre o espaço
       vazio que a escala apertada deixa no alto;
     · as pontas viraram o PISO e o TETO da escala, que é informação nova, na
       lateral, onde um eixo y mora.

   Resultado: o desenho ganhou a altura de uma linha e meia de texto, e a
   informação aumentou em vez de diminuir. */
.r37-hist { margin-top: 2px; position: relative; }

/* ------------------------------------------------ nota da equipe ---
   A ajuda do campo prometia "aparece no cartão e no relatório" e o cartão não
   a carregava. O campo salvava, a caixa mostrava salvo, e a tela ignorava —
   um dos três ajustes que Artur encontrou "indisponíveis para
   parametrização".

   Ela é deliberadamente DIFERENTE de tudo o mais no cartão: fundo próprio,
   itálico, lápis na frente. Nota humana não pode parecer leitura do dado, ou
   alguém a cita numa reunião como se o sistema a tivesse concluído. */
.r37-nota {
  margin: 6px 0 0; padding: 5px 8px; border-radius: 7px;
  display: flex; gap: 6px; align-items: flex-start;
  font-size: 11.5px; line-height: 1.35; font-style: italic;
  color: var(--ink-2);
  background: color-mix(in srgb, var(--neutro) 7%, transparent);
  border-left: 2px solid color-mix(in srgb, var(--neutro) 38%, transparent);
}
.r37-nota > i { font-style: normal; opacity: .65; flex: none; }
.r37-yoy-flut {
  position: absolute; top: 2px; right: 4px; z-index: 2;
  font: 700 10.5px/1 var(--fonte); color: var(--ink-3);
  font-variant-numeric: tabular-nums; cursor: help;
  background: color-mix(in srgb, var(--superficie) 82%, transparent);
  border-radius: 5px; padding: 3px 5px; pointer-events: auto;
}
.r37-yoy-flut i { font-style: normal; opacity: .7; font-size: 9.5px; }

/* O piso e o teto da escala, na lateral. Duas linhas só — quem precisa dos
   valores intermediários usa o modo Gráfico, que desenha o eixo inteiro. */
.r37-escala {
  /* `bottom` maior: o piso da escala encostava na linha dos meses e «12,81%»
     cruzava com «set» — Artur (25.1): «temos números estrangulados/cruzando
     um o outro... legibilidade e intuitividade é muito importante». O vão
     tem de caber o rótulo inteiro, não quase. */
  position: absolute; left: 0; top: 0; bottom: 26px; z-index: 2;
  display: flex; flex-direction: column; justify-content: space-between;
  font: 600 9px/1 var(--fonte); color: var(--ink-3);
  font-variant-numeric: tabular-nums; pointer-events: none;
  padding-right: 8px;
}
/* Cada limite num chip proprio, e nao um gradiente atras dos dois. O gradiente
   clareava a faixa inteira — inclusive onde nao havia texto — e mesmo assim
   deixava o numero sobre a area preenchida com pouco contraste. O chip cobre
   exatamente o que precisa cobrir. */
.r37-escala span {
  background: color-mix(in srgb, var(--superficie) 92%, transparent);
  border-radius: 4px; padding: 2px 4px; align-self: flex-start;
}

/* AS INICIAIS DOS MESES. Treze rótulos completos não cabem num cartão; treze
   iniciais cabem, e S-O-N-D-J-F-M-A-M-J-J-A-S se lê sem esforço porque é uma
   sequência que todo mundo sabe de cor. O `title` traz o mês por extenso. */
.r37-meses { cursor: help;
  display: flex; justify-content: space-between; margin-top: 3px;
  font: 600 10px/1 var(--fonte); color: var(--ink-3);
  letter-spacing: .02em;
}
.r37-meses span { flex: 1; text-align: center; cursor: default; }
/* O mês de referência é o do número grande lá em cima: em negrito e com a
   tinta cheia, para o olho poder ligar os dois sem legenda. */
.r37-meses .ref { color: var(--ink); font-weight: 800; }
/* Mês sem leitura: a inicial fica apagada, como o buraco na linha. */
.r37-meses .vaz { opacity: .32; }

/* A VIRADA DO ANO — Artur: «deixe claro os limites de um ano e do outro na
   timeline do eixo x». A janela de 13 meses vai de set/25 a set/26: as duas
   pontas se chamam «set» e, sem marca, a fila é ambígua justamente onde a
   comparação ano a ano acontece.

   O ano vai PARA CIMA, não para o lado: o eixo horizontal está disputado por
   treze rótulos e o vertical está vazio. Ganhar informação sem gastar largura
   é a única saída num cartão de três por linha. */
.r37-meses span { position: relative; padding-top: 9px; }
.r37-meses .ano {
  position: absolute; top: 0; left: 50%; transform: translateX(-50%);
  font: 700 8px/1 var(--fonte); color: var(--ink-3); opacity: .72;
  letter-spacing: .04em;
}
.r37-meses .ref .ano, .r37-meses .vira-ano .ano { opacity: 1; }
/* O traço é a fronteira. Fino e curto: ele separa dois anos, não divide o
   gráfico em dois — quem lê tem de continuar vendo uma série só. */
.r37-meses .vira-ano::before {
  content: ""; position: absolute; left: 0; top: 1px; bottom: 1px;
  border-left: 1px solid var(--borda-forte); opacity: .7;
}
/* Em mês/ano o ano já está no rótulo: nada por cima, e a coluna volta a
   ocupar só a própria linha. */
.r37-meses-mmm_aa span { padding-top: 0; }
.r37-meses-mmm_aa { font-size: 8.5px; letter-spacing: 0; }

/* Altura vinda do JS: ela cresce com a largura do cartão, e o viewBox é
   emitido na MESMA proporção — distorção zero em qualquer densidade. */
.r37-area { width: 100%; height: var(--alt-mini, 78px); display: block; }

.r37-sem-serie { height: 78px; display: grid; place-items: center;
  border: 1px dashed var(--borda); border-radius: 8px;
  font-size: 11px; color: var(--ink-3); }

/* ------------------------------------------------- cartão sem número --- */
.r37-indisp { display: flex; flex-direction: column; gap: 7px; padding: 4px 0 2px; }
.r37-etq-indisp {
  align-self: flex-start; font: 700 9.5px/1 var(--fonte);
  text-transform: uppercase; letter-spacing: .05em;
  background: var(--neutro-bg); color: var(--ink-2);
  border: 1px dashed var(--borda-forte); border-radius: 6px; padding: 5px 8px;
}
.r37-motivo { margin: 0; font-size: 11.5px; line-height: 1.5; color: var(--ink-2); }
.r37-prov, .r37-cand { margin: 0; font-size: 11px; line-height: 1.5;
  color: var(--ink-3); }
.r37-prov b, .r37-cand b { color: var(--ink-2); }

/* -------------------------------------------------------- chamada e nota */
.r37-chamada {
  background: var(--superficie); border: 1px solid var(--borda-forte);
  border-left: 3px solid var(--marca);
  border-radius: 11px; padding: 16px 18px; margin-bottom: 16px;
}
.r37-chamada h3 { margin: 0 0 6px; font-size: 15px; }
.r37-chamada p { margin: 0 0 6px; font-size: 13px; color: var(--ink-2);
  line-height: 1.55; }
.r37-chamada-acoes { display: flex; gap: 9px; flex-wrap: wrap; margin-top: 12px; }

.r37-legenda {
  margin-top: 20px; padding: 15px 17px; background: var(--superficie-2);
  border: 1px solid var(--borda); border-radius: 11px;
}
.r37-legenda h4 { margin: 0 0 8px; font-size: 12px; text-transform: uppercase;
  letter-spacing: .05em; color: var(--ink-3); }
.r37-legenda ul { margin: 0; padding-left: 18px; }
.r37-legenda li { font-size: 12.5px; line-height: 1.6; color: var(--ink-2);
  margin-bottom: 3px; }
.r37-legenda b { color: var(--ink); }
.r37-limites { margin-top: 10px !important; padding-top: 9px;
  border-top: 1px dashed var(--borda); }
.r37-limites li { color: var(--ink-3); font-size: 11.5px; }

/* ===========================================================================
   SUB-ABAS DO ADM
   ===========================================================================
   Visualmente SUBORDINADAS às abas de topo: menores, sem a barra de seleção
   grossa, e roláveis na horizontal em vez de quebrarem em duas linhas. Duas
   linhas de abas fazem a barra parecer um segundo menu principal — que é
   justamente a poluição da qual elas vieram.
   =========================================================================== */
.adm-subabas {
  display: flex; gap: 4px; overflow-x: auto; padding: 2px 0 10px;
  margin-bottom: 14px; border-bottom: 1px solid var(--borda);
  scrollbar-width: thin;
}
.adm-subaba {
  flex: none; background: transparent; border: 1px solid transparent;
  border-radius: 8px; padding: 7px 12px; cursor: pointer;
  font: 600 12px/1 var(--fonte); color: var(--ink-3); white-space: nowrap;
}
.adm-subaba:hover { color: var(--ink); background: var(--superficie-2); }
.adm-subaba[aria-selected="true"] {
  color: var(--ink); background: var(--superficie-3);
  border-color: var(--borda-forte);
}
.adm-palco { min-height: 200px; }
/* Painel movido para dentro do ADM: perde o recuo próprio, porque o palco já
   o dá. Sem isto o conteúdo aparece com margem dupla e desalinhado do resto. */
.painel-embutido { padding: 0 !important; }

/* ------------------------------------------------------- ADM › Desafio --- */
.des-cab, .des-linha {
  display: grid; grid-template-columns: 34px 1fr 90px 78px 120px;
  gap: 10px; align-items: center;
}
.des-cab {
  font: 700 9.5px/1 var(--fonte); text-transform: uppercase;
  letter-spacing: .05em; color: var(--ink-3);
  padding: 8px 0; border-bottom: 1px solid var(--borda);
}
.des-lista { max-height: 460px; overflow-y: auto; }
.des-linha { padding: 6px 0; border-bottom: 1px dashed var(--borda); }
.des-pos { font: 700 10.5px/1 var(--fonte); color: var(--ink-3);
  font-variant-numeric: tabular-nums; }
.des-nome { font-size: 12px; color: var(--ink); overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; }
.des-meta { font: 600 12px/1 var(--fonte); color: var(--serie-2);
  font-variant-numeric: tabular-nums; text-align: right; }
.des-pol { font: 700 10px/1 var(--fonte); text-align: center;
  border-radius: 999px; padding: 4px 6px; }
.des-pol.alto  { background: var(--bom-bg);     color: var(--bom); }
.des-pol.baixo { background: var(--atencao-bg); color: var(--atencao); }
.des-linha input {
  width: 100%; background: var(--superficie-2); color: var(--ink);
  border: 1px solid var(--borda); border-radius: 7px; padding: 6px 8px;
  font: 600 12px/1 var(--fonte); font-variant-numeric: tabular-nums;
}
@media (max-width: 760px) {
  .des-cab { display: none; }
  .des-linha { grid-template-columns: 30px 1fr; grid-auto-rows: auto; }
  .des-meta, .des-pol { text-align: left; grid-column: 2; }
  .des-linha input { grid-column: 2; }
}

/* ---------------------------------------------------------- login ------- */
.login-lembrar {
  display: flex !important; align-items: center; gap: 8px;
  margin-top: 12px; font-size: 12.5px; color: var(--ink-2);
  cursor: pointer; font-weight: 500 !important;
}
.login-lembrar input { width: auto !important; margin: 0; accent-color: var(--marca); }
.login-pista {
  margin-left: 7px; font: 600 9.5px/1 var(--fonte); text-transform: uppercase;
  letter-spacing: .04em; color: var(--marca);
  background: color-mix(in srgb, var(--marca) 16%, transparent);
  border-radius: 5px; padding: 3px 5px;
}
.adm-login code {
  font-size: 11px; background: var(--superficie-3); border-radius: 4px;
  padding: 1px 4px; color: var(--ink-2);
}
.abas-espaco { flex: 1 1 auto; }

/* `hidden` precisa vencer qualquer `display` de classe. Sem isto, um
   `.controle { display: flex }` mantém visível um elemento marcado como
   escondido — foi o que deixou o seletor de janela aparecendo na aba do Radar,
   onde ele não significa nada (o Book é mensal). */
[hidden] { display: none !important; }
.des-config { display: flex; gap: 20px; flex-wrap: wrap; margin: 14px 0 4px; }
.des-config label { display: flex; flex-direction: column; gap: 6px;
  font-size: 12px; color: var(--ink-3); }
.des-config select, .des-config input {
  background: var(--superficie-2); color: var(--ink);
  border: 1px solid var(--borda); border-radius: 8px; padding: 8px 10px;
  font: 600 13px/1 var(--fonte); min-width: 210px;
}
.carregando { padding: 40px 16px; text-align: center; color: var(--ink-3);
  font-size: 13px; }
/* A SEGUNDA LINHA DA ESPERA — pedido 55.
   Menor e mais apagada que a primeira: ela explica, não anuncia. Largura
   limitada porque uma frase de três linhas centralizada e estreita se lê;
   a mesma frase atravessando 1600 px, não. */
.carregando-porque { margin: 10px auto 0; max-width: 520px; font-size: 12px;
  line-height: 1.5; color: var(--ink-4, var(--ink-3)); opacity: .85; }

/* A TELA DE ESPERA QUE PRESTA CONTAS — pedido 83.
   Largura contida (520px): a espera é um bloco de leitura, e linha longa em
   bloco centralizado é a receita para o olho perder o começo da próxima. */
.esp-tit { font-size: 15px; color: var(--ink-2); font-weight: 600; }
/* A SEGUNDA BARRA — pedido 112. Ela é visivelmente MENOR e mais discreta
   que a geral, e isso é a hierarquia: a pergunta principal continua sendo
   «quanto falta no total». A da etapa responde «esta etapa está andando?»,
   que é a pergunta de quem já esperou demais e quer saber se travou. */
.esp-etapa {
  max-width: 520px; margin: 12px auto 0;
  padding: 9px 11px; border-radius: 8px;
  background: var(--superficie-2); border: 1px solid var(--borda);
}
.esp-etapa-cab {
  display: flex; justify-content: space-between; align-items: baseline;
  gap: 10px; font-size: 11.5px; color: var(--ink-2);
}
.esp-etapa-cab b { font-size: 12.5px; color: var(--ink); font-variant-numeric: tabular-nums; }
.esp-barra-p { margin-top: 7px; height: 6px; max-width: none; }
.esp-etapa-pe { margin-top: 6px; font-size: 10.5px; color: var(--ink-3); line-height: 1.45; }
/* «etapa 2 de 7» é a âncora da leitura: mesmo que a porcentagem erre, este
   par de números não erra — ele é contagem, não estimativa. */
.esp-k {
  font-weight: 700; font-variant-numeric: tabular-nums;
  padding: 1px 6px; border-radius: 4px;
  background: color-mix(in srgb, var(--marca) 12%, transparent);
}
.esp-barra {
  position: relative; margin: 14px auto 0; max-width: 520px; height: 10px;
  border-radius: 6px; background: var(--superficie-3);
  border: 1px solid var(--borda); overflow: hidden;
}
/* DUAS CAMADAS, E A DIFERENÇA É A MESMA DO RASTRO DAS BOLHAS: sólido é
   medido, hachurado é estimado. A estimada fica ATRÁS e mais longa; a
   medida a cobre até onde o fato alcança. Quem olha vê onde termina a
   certeza sem precisar de legenda. */
.esp-est {
  position: absolute; inset: 0 auto 0 0; display: block;
  background: repeating-linear-gradient(115deg,
    color-mix(in srgb, var(--marca) 34%, transparent) 0 6px,
    transparent 6px 12px);
  transition: width .5s linear;
}
.esp-feito {
  position: absolute; inset: 0 auto 0 0; display: block;
  background: var(--marca); border-radius: 6px 0 0 6px;
  transition: width .4s ease;
}
.esp-linha {
  margin: 9px auto 0; max-width: 520px; font-size: 12.5px;
  color: var(--ink-2); font-variant-numeric: tabular-nums;
}
.esp-linha b { color: var(--ink); font-weight: 700; }
.esp-passos {
  list-style: none; margin: 14px auto 0; padding: 0; max-width: 520px;
  text-align: left;
}
.esp-p {
  display: grid; grid-template-columns: 16px minmax(0, 1fr) auto;
  gap: 8px; align-items: baseline; padding: 3px 0;
  font-size: 12.5px; color: var(--ink-3);
}
.esp-p.ok { color: var(--ink-3); }
.esp-p.indo { color: var(--ink); font-weight: 600; }
.esp-p-m { text-align: center; font-size: 11px; }
.esp-p.ok .esp-p-m { color: var(--dentro, var(--marca)); }
.esp-p.indo .esp-p-m { color: var(--marca); }
.esp-p-t { font-variant-numeric: tabular-nums; font-size: 11.5px;
  color: var(--ink-3); }

/* ===========================================================================
   NAVEGADOR DE TIMELINE — o controle do anexo 4
   ===========================================================================
   ‹  🗓 2026 ▾  set/26 ▾  set/25 - set/26  hoje  ›   [ Dia | Mês ]

   Uma barra só, com bordas arredondadas e divisórias internas, para ler como
   UM controle e não como seis. A faixa do meio (a janela desenhada) é o
   elemento mais largo de propósito: é a informação que faltava.
   =========================================================================== */
.tl-barra {
  display: flex; align-items: stretch; gap: 0; flex-wrap: wrap;
  background: var(--superficie); border: 1px solid var(--borda);
  border-radius: 10px; margin-bottom: 14px; overflow: hidden;
  width: fit-content; max-width: 100%;
}
.tl-barra > * { border-right: 1px solid var(--borda); }
.tl-barra > *:last-child { border-right: none; }
.tl-seta {
  background: transparent; border: none; color: var(--ink-2);
  font: 600 17px/1 var(--fonte); padding: 0 13px; cursor: pointer;
}
.tl-seta:hover:not(:disabled) { background: var(--superficie-3); color: var(--ink); }
.tl-seta:disabled { color: var(--ink-3); opacity: .4; cursor: default; }
.tl-cal { display: flex; align-items: center; padding: 0 9px 0 11px;
  font-size: 14px; border-right: none !important; }
.tl-ano, .tl-mes, .tl-dia {
  background: transparent; border: none; color: var(--ink);
  font: 600 12.5px/1 var(--fonte); padding: 9px 8px; cursor: pointer;
  font-variant-numeric: tabular-nums;
}
.tl-ano { padding-left: 2px; }
/* O dia é o seletor mais fino e fica colado no mês: a leitura é "14 de
   setembro", não três campos independentes. */
.tl-dia { padding-left: 2px; padding-right: 6px; }
.tl-ano:focus, .tl-mes:focus, .tl-dia:focus {
  outline: 2px solid var(--marca); outline-offset: -2px;
}
.tl-faixa {
  display: flex; align-items: center; padding: 0 15px;
  font: 600 12.5px/1 var(--fonte); color: var(--ink-2);
  font-variant-numeric: tabular-nums; white-space: nowrap;
  background: var(--superficie-2);
}
/* ===========================================================================
   O DIA DA EXTRAÇÃO — pedido 65, e por que ele «não foi encontrado»
   ===========================================================================
   A primeira versão deste chip nasceu com a classe `.tl-dia`, QUE JÁ EXISTIA:
   é o seletor de dia da granularidade DIA, três regras acima. Duas coisas
   diferentes com o mesmo nome — o chip herdou `background: transparent`,
   `border: none` e o padding do seletor, e virou um «30/09» solto no meio da
   barra, indistinguível do texto da janela ao lado. Ele procurou e não achou,
   e estava olhando para ele.

   É o defeito mais barato de cometer e o mais caro de diagnosticar: nada
   quebra, nada avisa, e o sintoma («não encontrei») não aponta para a causa.
   Nome novo, e o rótulo escrito: «dado 30/09» diz o que o número é. Um
   número sozinho numa barra cheia de números não se identifica. */
/* DUAS LINHAS EMPILHADAS e não lado a lado: o rótulo «dado» ao lado do
   número custava 40 px numa barra que já estava no limite de UMA linha
   (pedido 30, medido pela bateria a 1500 px). Empilhado, o chip ocupa a
   largura do número e mesmo assim se identifica — é a mesma solução dos
   blocos do cabeçalho, onde o rótulo mora em cima do valor. */
.tl-extraido {
  display: flex; flex-direction: column; justify-content: center; gap: 1px;
  padding: 0 7px; white-space: nowrap; cursor: help;
  border-left: 1px solid var(--borda); background: var(--superficie-2);
}
.tl-extraido b {
  font: 700 12.5px/1 var(--fonte); color: var(--ink);
  font-variant-numeric: tabular-nums;
}
/* O rótulo é o elemento mais largo do chip («extração» é mais comprido que
   «30/09»), então é ele que define a largura — e a barra é UMA linha desde o
   pedido 30. 8px sem espaçamento extra: continua legível e para de empurrar. */
.tl-extraido i {
  font: 700 8px/1 var(--fonte); font-style: normal; color: var(--ink-3);
  text-transform: uppercase; letter-spacing: .02em;
}
/* A IDADE DA EXTRAÇÃO — pedido 124. «25/09» ao lado de «set/26» parece
   coerente; «25/09 · há 10 dias» não parece coerente com nada, e é essa
   estranheza que faz agir. Fica em 8px como o rótulo: a data continua sendo
   o que o olho pega primeiro, e a idade é a linha que explica. */
.tl-extraido u {
  font: 600 8px/1 var(--fonte); text-decoration: none; color: var(--ink-3);
  letter-spacing: .02em;
}
/* Passado o limiar, o chip inteiro muda de tom. Não é alarme vermelho: o dado
   não está ERRADO, está possivelmente INCOMPLETO — e a cor do erro ensinaria
   a pessoa a desconfiar do número, quando o que ela precisa é reextrair. */
.tl-extraido-velha {
  background: var(--atencao-fundo, #fff4e5);
  border-left-color: var(--atencao-borda, #e8a33d);
}
.tl-extraido-velha b { color: var(--atencao-ink, #8a5200); }
.tl-extraido-velha i,
.tl-extraido-velha u { color: var(--atencao-ink, #8a5200); opacity: .85; }
:root[data-theme="dark"] .tl-extraido-velha {
  background: #3a2a10; border-left-color: #a8782c;
}
:root[data-theme="dark"] .tl-extraido-velha b,
:root[data-theme="dark"] .tl-extraido-velha i,
:root[data-theme="dark"] .tl-extraido-velha u { color: #f0c27a; }
.tl-hoje {
  background: transparent; border: none; color: var(--marca);
  font: 700 11px/1 var(--fonte); padding: 0 12px; cursor: pointer;
  text-transform: uppercase; letter-spacing: .05em;
}
.tl-hoje:hover:not(:disabled) { background: var(--superficie-3); }
.tl-hoje:disabled { color: var(--ink-3); opacity: .45; cursor: default; }
/* GRANULARIDADE — dia · mês · ano. A mesma dupla de setas serve as três; o
   que muda é o passo. Ver `seletorGranularidade` em radar37.js. */
.tl-granus { display: flex; align-items: stretch; }
.tl-granu {
  background: transparent; border: none; border-left: 1px solid var(--borda);
  color: var(--ink-3); font: 600 11.5px/1 var(--fonte);
  padding: 0 13px; cursor: pointer;
}
.tl-granu:first-child { border-left: none; }
.tl-granu:hover { color: var(--ink); background: var(--superficie-3); }
.tl-granu.on { color: var(--ink); background: var(--superficie-3); }

.r37-chamada-atencao { border-left-color: var(--atencao); }

/* ------------------------------------------------ ícone de direção --- */
/* O glifo do Core: uma linha quebrada que sobe ou desce. Ele diz a DIREÇÃO
   DESEJADA — não o movimento do mês, que fica no rodapé do cartão. */
/* SÓ O ÍCONE. Sem texto, o chip vira quadrado e o glifo cresce — ele passa a
   ser lido de longe, que é como um indicador de direção deve funcionar. */
.r37-dir {
  flex: none; display: inline-flex; align-items: center; justify-content: center;
  width: 26px; height: 26px; border-radius: 8px;
}
.r37-dir svg { width: 17px; height: 17px; display: block; }
.r37-dir-alto  { background: var(--bom-bg);     color: var(--bom); }
.r37-dir-baixo { background: var(--atencao-bg); color: var(--atencao); }
.r37-dir-nd    { background: var(--neutro-bg);  color: var(--neutro); }

/* ------------------------------------------------ farol com glifo --- */
/* Cor nunca sozinha: glifo + rótulo acompanham todo estado. É o que torna a
   paleta defensável mesmo onde verde e ciano ficam a ΔE 14,3, e o que faz o
   painel sobreviver a uma impressão em preto e branco. */
.r37-farol i { font-style: normal; font-size: 11px; }
.farol-superado i { font-size: 12px; }

/* A HACHURA DA AUSÊNCIA. Cinza chapado ao lado de verde lê como "velho"; cinza
   com textura lê como "não se aplica". Textura é a única marca de ausência que
   sobrevive ao preto e branco e à visão de cores atípica. */
.r37-cartao.r37-sem_book, .r37-cartao.r37-ausente,
.r37-cartao.r37-a_confirmar, .r37-cartao.r37-sem_leitura {
  border-style: dashed; background:
    repeating-linear-gradient(135deg,
      transparent 0 9px,
      color-mix(in srgb, var(--neutro) 7%, transparent) 9px 10px),
    var(--superficie-2);
}
.r37-etq-indisp {
  background: repeating-linear-gradient(135deg,
      var(--neutro-bg) 0 5px,
      color-mix(in srgb, var(--neutro) 16%, transparent) 5px 6px);
}

/* ------------------------------------------- atalho do desafio ---
   Artur: "Qual engrenagem? Onde fica?"

   Ela estava ali — 11px, cor de texto terciário, sem contorno, colada num
   rótulo. Ou seja: existia no DOM e não existia na tela. O balão mandava
   clicar num alvo que ninguém achava, que é pior do que não ter atalho
   nenhum: manda procurar.

   Agora ela é uma PASTILHA. Não é enfeite — é o mínimo para um alvo de
   clique se anunciar: fundo próprio que a separa do rótulo, contorno que diz
   "isto tem borda, logo é um controle", e 18px de lado (o dedo e o olho
   precisam de área, não de glifo). Continua discreta em repouso e assume a
   cor do desafio no hover, para amarrar visualmente o atalho ao número que
   ele configura. */
.r37-engrenagem {
  margin-left: 6px; cursor: pointer; font-size: 11px; line-height: 1;
  display: inline-grid; place-items: center;
  width: 18px; height: 18px; vertical-align: -4px;
  color: var(--ink-2);
  background: color-mix(in srgb, var(--desafio) 9%, transparent);
  border: 1px solid color-mix(in srgb, var(--desafio) 28%, transparent);
  border-radius: 6px; padding: 0;
  transition: background .12s, color .12s, border-color .12s;
}
.r37-engrenagem:hover,
.r37-engrenagem:focus-visible {
  color: #fff; border-color: var(--desafio);
  background: var(--desafio);
}

/* ------------------------------------------------- balão com abas --- */
.balao-dica.com-abas { pointer-events: auto; max-width: 440px; }
/* A PONTE SOBRE O VÃO. O balão abre a 11px do alvo; para chegar às abas o
   cursor atravessa esse espaço, onde não está sobre nenhum dos dois. Esta
   faixa invisível liga os dois lados, de modo que o percurso nunca passa por
   "lugar nenhum". Sem ela, o balão fechava no meio do caminho e as abas eram
   inalcançáveis. */
.balao-dica.com-abas::before {
  content: ""; position: absolute; left: 0; right: 0; height: 16px;
}
.balao-dica.com-abas[data-lado="baixo"]::before { top: -16px; }
.balao-dica.com-abas[data-lado="cima"]::before { bottom: -16px; }
.balao-abas { display: flex; gap: 4px; margin-bottom: 9px; }
.balao-abas button {
  flex: 1 1 auto; background: rgba(255,255,255,.14); border: none;
  border-radius: 7px; padding: 5px 9px; cursor: pointer;
  color: rgba(255,255,255,.78); font: 700 10.5px/1 var(--fonte);
  text-transform: uppercase; letter-spacing: .05em;
}
.balao-abas button.on { background: rgba(255,255,255,.30); color: #fff; }
.balao-pag { display: none; color: rgba(255,255,255,.94); font-size: 12.5px; }
.balao-pag.on { display: block; }
.balao-pag table { width: 100%; border-collapse: collapse; font-size: 11.5px; }
.balao-pag td { padding: 3px 0; border-bottom: 1px solid rgba(255,255,255,.16);
  vertical-align: top; }
.balao-pag td:first-child { color: rgba(255,255,255,.72); padding-right: 10px;
  white-space: nowrap; }
.balao-pag td:last-child { text-align: right; font-variant-numeric: tabular-nums; }
.balao-pag .titulinho { font-weight: 700; margin: 8px 0 3px; font-size: 11px;
  text-transform: uppercase; letter-spacing: .05em; opacity: .8; }
.balao-pag code { background: rgba(255,255,255,.16); border-radius: 4px;
  padding: 1px 4px; font-size: 11px; }

.r37-exportar { white-space: nowrap; }
.r37-vnext { opacity: .7; font-variant-numeric: tabular-nums; }

/* O checkpoint de senha. Discreto de propósito: é uma opção, não um aviso.
   Fica ENCOSTADO no botão (gap pequeno, mesma linha de base) porque a
   proximidade é o que diz que ele governa aquele botão e não a barra toda. */
.r37-exp-grupo { display: inline-flex; align-items: center; gap: 8px; }

/* HTML | PDF — um par de botões segmentado, não uma lista suspensa: com duas
   opções, esconder uma delas atrás de um clique custa mais do que economiza. */
.r37-saida { display: inline-flex; border: 1px solid var(--linha-forte);
  border-radius: 8px; overflow: hidden; background: var(--plano); }
.r37-saida-op { font: 600 11.5px/1 var(--fonte); letter-spacing: .04em;
  color: var(--ink-3); background: transparent; border: 0; cursor: pointer;
  padding: 7px 11px; transition: background .14s, color .14s; }
.r37-saida-op + .r37-saida-op { border-left: 1px solid var(--linha); }
.r37-saida-op:hover { background: var(--papel); color: var(--ink-2); }
/* O selecionado usa o vermelho da marca, não `var(--ink)`: no tema escuro a
   tinta é quase branca, e texto branco sobre ela some. Cor de marca é a única
   que tem o mesmo contraste nos dois temas. */
.r37-saida-op.on { background: var(--marca); color: #fff; }
.r37-proteger {
  display: inline-flex; align-items: center; gap: 5px; cursor: pointer;
  font-size: 11.5px; color: var(--ink-3); white-space: nowrap;
  padding: 4px 7px; border-radius: 7px; border: 1px solid transparent;
}
.r37-proteger:hover { border-color: var(--borda); color: var(--ink); }
.r37-proteger:has(:checked) {
  color: var(--ink); border-color: var(--marca);
  background: color-mix(in srgb, var(--marca) 10%, transparent);
  font-weight: 600;
}
.r37-prot-chk { accent-color: var(--marca); margin: 0; cursor: pointer; }

.r37-senha-caixa { max-width: 440px; }
.r37-senha-rot {
  display: block; font-size: 10.5px; font-weight: 700; text-transform: uppercase;
  letter-spacing: .07em; color: var(--ink-3); margin: 12px 0 5px;
}
.r37-senha-campo {
  width: 100%; padding: 10px 12px; font: inherit; font-size: 14px;
  border: 1.5px solid var(--borda-forte); border-radius: 9px;
  background: var(--plano); color: var(--ink);
  /* Senha não é número: `tabular-nums` aqui alinharia dígitos numa caixa que
     mostra pontos. Fora. */
}
.r37-senha-campo:focus { outline: none; border-color: var(--marca); }
.r37-senha-erro {
  min-height: 17px; margin-top: 9px; font-size: 12px; font-weight: 600;
  color: var(--critico);
}
.r37-conta {
  margin-left: 5px; background: none; border: none; cursor: help;
  color: var(--ink-3); font: 700 10px/1 var(--fonte); padding: 0 2px;
}
.r37-conta:hover { color: var(--marca); }

/* ===========================================================================
   SUPER TOOLTIP — o diagrama do cartão
   ===========================================================================
   Mais largo e mais claro que o balão comum, porque o trabalho dele é outro:
   o balão responde uma pergunta pontual; este ensina a ler a tela inteira.
   Fundo de superfície (não azul) para a figura poder usar as cores reais do
   farol — num fundo azul, verde e ciano deixariam de ser os mesmos verde e
   ciano do cartão, e a figura pararia de servir de legenda.
   =========================================================================== */
.super-dica {
  /* SEM pointer-events. O super tooltip abre logo abaixo da aba e a cobre —
     com ele recebendo o mouse, a própria aba fica inclicável e o balão nunca
     fecha, porque o cursor "nunca sai" do alvo. Ele é informativo e não tem
     nada para clicar, então recusar o mouse é o comportamento certo. */
  pointer-events: none;
  position: fixed; z-index: 210; width: min(640px, calc(100vw - 20px));
  background: var(--superficie); color: var(--ink-2);
  border: 1px solid var(--borda-forte); border-radius: 16px;
  box-shadow: 0 18px 50px rgba(0,0,0,.42), 0 2px 8px rgba(0,0,0,.3);
  padding: 18px 20px; font-size: 13px; line-height: 1.55;
  max-height: calc(100vh - 24px); overflow-y: auto;
  animation: sup-entra .16s ease-out;
}
@keyframes sup-entra { from { opacity: 0; transform: translateY(-5px); }
                       to { opacity: 1; transform: none; } }
.sup { display: grid; grid-template-columns: 200px 1fr; gap: 18px; }
@media (max-width: 620px) { .sup { grid-template-columns: 1fr; } }
.sup-fig svg { width: 100%; height: auto; display: block; }

/* Os anéis se desenham na ordem de leitura: valor, meta, desafio. O
   movimento carrega a ORDEM, que é o que uma figura parada não diz. */
.sup-trilho, .sup-trilho2 { fill: none; stroke: var(--grade); }
.sup-trilho { stroke-width: 11; stroke-linecap: round; }
.sup-trilho2 { stroke-width: 2.5; }
.sup-a1, .sup-a2, .sup-a3 { fill: none; stroke-linecap: round;
  stroke-dasharray: 420; stroke-dashoffset: 420;
  animation: sup-traco .85s ease-out forwards; }
.sup-a1 { stroke: var(--bom); stroke-width: 11; }
.sup-a2 { stroke: var(--meta); stroke-width: 3; animation-delay: .5s; }
.sup-a3 { stroke: var(--desafio); stroke-width: 2.5; stroke-dasharray: 4 4;
  animation: sup-aparece .5s ease-out .95s forwards; opacity: 0; }
.sup-tick { stroke: var(--meta); stroke-width: 3.2; stroke-linecap: round;
  opacity: 0; animation: sup-aparece .3s ease-out 1.25s forwards; }
.sup-val { fill: var(--bom); font: 700 20px/1 var(--fonte); opacity: 0;
  animation: sup-aparece .4s ease-out 1.4s forwards; }
.sup-spark { fill: none; stroke: var(--bom); stroke-width: 2;
  stroke-linejoin: round; stroke-dasharray: 260; stroke-dashoffset: 260;
  animation: sup-traco .8s ease-out 1.5s forwards; }
.sup-metal { stroke: var(--meta); stroke-width: 1.2; stroke-dasharray: 4 3;
  opacity: 0; animation: sup-aparece .3s ease-out 2s forwards; }
@keyframes sup-traco { to { stroke-dashoffset: 0; } }
@keyframes sup-aparece { to { opacity: 1; } }
/* Quem pediu menos movimento ao sistema recebe a figura pronta. */
@media (prefers-reduced-motion: reduce) {
  .sup-a1, .sup-a2, .sup-a3, .sup-tick, .sup-val, .sup-spark, .sup-metal,
  .super-dica { animation: none !important; stroke-dashoffset: 0 !important;
    opacity: 1 !important; }
}

.sup-lista { margin: 0; padding: 0; list-style: none; }
/* FLEX, não grid de duas colunas: com grid, o nó de texto solto ao lado do
   <b> virava um TERCEIRO item e caía na coluna de 20px — uma palavra por
   linha. Cada item agora tem exatamente dois filhos: o ícone e um bloco. */
.sup-lista li { display: flex; align-items: flex-start; gap: 9px;
  margin-bottom: 8px; font-size: 12.5px; line-height: 1.45; }
.sup-lista li > div { flex: 1 1 auto; min-width: 0; }
.sup-lista b { color: var(--ink); }
.sup-lista i { width: 13px; height: 13px; flex: none; border-radius: 4px; margin-top: 3px;
  font-style: normal; display: inline-flex; align-items: center;
  justify-content: center; font-size: 10px; font-weight: 700; }
.sup-i-seta { background: var(--atencao-bg); color: var(--atencao); }
.sup-i-fx { background: var(--superficie-3); color: var(--marca); font-size: 9px !important; }
.sup-i-linha { background: linear-gradient(135deg, transparent 45%,
  var(--bom) 45%, var(--bom) 55%, transparent 55%); }
.sup-nota { grid-column: 1 / -1; margin: 4px 0 0; padding-top: 10px;
  border-top: 1px solid var(--borda); font-size: 11.5px; color: var(--ink-3); }

/* ===========================================================================
   FONTE OPCIONAL — declarada aqui só se ESTIVER instalada no sistema
   ===========================================================================
   `local()` e nada mais: se o Inter já existe na máquina, o navegador usa.

   Os arquivos .woff2 NÃO são declarados aqui de propósito. Um `url()` para um
   arquivo que não existe produz 404 a cada abertura — e este projeto tem uma
   aba de Diagnóstico que registra falhas justamente para que uma falha REAL
   seja vista. Três 404 previsíveis toda vez ensinam a ignorar a lista.

   Quem serve os arquivos é `/assets/fontes/inter.css`, montado pelo servidor
   e incluído sempre: ele devolve as declarações quando os .woff2 estão lá, e
   uma folha vazia quando não estão. Zero configuração, zero 404.
   Ver `frontend/assets/fontes/LEIA-ME.txt`.
   =========================================================================== */
@font-face {
  font-family: "Inter"; font-style: normal; font-weight: 400; font-display: swap;
  src: local("Inter"), local("Inter Regular");
}
@font-face {
  font-family: "Inter"; font-style: normal; font-weight: 600; font-display: swap;
  src: local("Inter SemiBold"), local("Inter-SemiBold");
}
@font-face {
  font-family: "Inter"; font-style: normal; font-weight: 700; font-display: swap;
  src: local("Inter Bold"), local("Inter-Bold");
}
/* O peso 800 existe para UM número — o da saúde (pedido 99). Sem o arquivo
   na pasta, o navegador cai no 700 da mesma família ou no peso mais forte
   do sistema, que é exatamente o comportamento que esta folha procura:
   degradar sozinha, nunca quebrar. */
@font-face {
  font-family: "Inter"; font-style: normal; font-weight: 800; font-display: swap;
  src: local("Inter ExtraBold"), local("Inter-ExtraBold"),
       local("Inter Black"), local("Inter-Black");
}

/* Todo número da tela: algarismo tabular, entreletra fechada, zero cortado
   quando a fonte oferece (ss02 no Inter). Uma regra só, aplicada a tudo que
   carrega número — não há como esquecer num lugar. */
.r37-val, .r37-linha b, .r37-tira-item b, .tl-faixa, .tl-ano, .tl-mes,
.r37-seta, .r37-yoy, .r37-eixo, .des-meta, .des-pos, .r37-pos,
.spk-eixo, .nums b {
  font-family: var(--fonte-num);
  font-variant-numeric: tabular-nums lining-nums;
  font-feature-settings: "tnum" 1, "lnum" 1, "cv05" 1;
  letter-spacing: -0.012em;
}

/* ===========================================================================
   ASSINATURA VISUAL — o logo da Claro e o anel de status, separados
   ===========================================================================
   O logo é IDENTIDADE: não muda de cor, não pisca, não carrega estado. Logo
   que vira vermelho quando algo falha é uso indevido de marca, e ensina a ler
   a marca como alarme.

   O anel de status é elemento PRÓPRIO, ao lado. Ele pulsa e troca de cor. Os
   dois vizinhos dão a leitura certa — "este painel é da Claro" e "este painel
   está vivo" — sem um contaminar o outro.
   =========================================================================== */
.logo-claro {
  width: 26px; height: 26px; flex: none; display: block; object-fit: contain;
}
/* O símbolo é vermelho sobre transparente e funciona nos dois temas — foi
   desenhado para isso. No escuro ganha um brilho mínimo para não sumir contra
   o fundo quase preto. */
:root:not([data-theme="light"]) .logo-claro {
  filter: drop-shadow(0 0 6px rgba(255, 20, 10, .35));
}
.marca-nome { font-weight: 700; letter-spacing: -.01em; }

/* ---------------------------------------------- anel de status --- */
/* DOIS CANAIS, DUAS PERGUNTAS — e é isso que faz este anel valer um canto da
   barra superior:

       MOVIMENTO  →  o CORTEX está vivo?     pulsando / parado
       COR        →  o DADO está fresco?     verde / laranja / vermelho

   Artur: "não esqueça que o pulsing do ring é conectividade e as cores status
   de frescor nos dados... conforme o critério definido/disponível para cada
   indicador."

   São perguntas INDEPENDENTES, e é por isso que precisam de canais separados:
   dá para estar conectado com dado velho, e dá para o dado estar em dia
   enquanto a conexão cai. Um anel de um canal só teria de escolher qual das
   duas mentir.

       verde      todos os indicadores dentro da folga da PRÓPRIA cadência
       laranja    aquecendo o cache agora (a barra abaixo diz quanto falta)
       vermelho   algum indicador passou da folga — DESATUALIZADO
       cinza      sem conexão, ou nenhum critério de frescor disponível

   VERMELHO É "DESATUALIZADO", NÃO "FALHOU". A afirmação é sobre o DADO, que é
   o que interessa a quem olha o painel: falha de carga que não atrasou nada
   não merece alarme, e atraso sem falha nenhuma merece.

   CINZA para ausência — de conexão ou de critério — e nunca vermelho: ausência
   não é falha, e pintar ausência de vermelho gasta o alarme que precisa estar
   inteiro no dia em que o dado realmente atrasar. */
.marca .ponto {
  position: relative; cursor: help; flex: none;
  transition: background-color .35s ease;
}
.marca .ponto::after {
  content: ""; position: absolute; inset: -4px; border-radius: 50%;
  border: 2px solid currentColor; opacity: 0;
}
.marca .ponto[data-estado="ok"]           { background: var(--bom);     color: var(--bom); }
.marca .ponto[data-estado="atualizando"]  { background: var(--atencao); color: var(--atencao); }
.marca .ponto[data-estado="desatualizado"]{ background: var(--critico); color: var(--critico); }
.marca .ponto[data-estado="falhou"]       { background: var(--critico); color: var(--critico); }
.marca .ponto[data-estado="sem_criterio"] { background: var(--neutro);  color: var(--neutro); }
/* SEM REDE: cinza e PARADO. O pulso fala de conexão, e a conexão que importa
   é a que traz o dado — não a que liga a tela ao processo ao lado. Com o
   Wi-Fi desligado, `localhost` continua respondendo e o anel continuava
   pulsando: estava correto sobre a pergunta errada. */
.marca .ponto[data-estado="sem_rede"]     { background: var(--neutro);  color: var(--neutro); }
.marca .ponto[data-estado="parado"]       { background: var(--neutro);  color: var(--neutro); }
.marca .ponto[data-estado="ligando"]      { background: var(--neutro);  color: var(--neutro); }

/* O RITMO DO PULSO SEGUE A CONEXÃO, NÃO A COR.
   Conectado pulsa; sem conexão não pulsa. Por isso TODO estado que vem do
   servidor — inclusive o vermelho de dado velho — continua pulsando: o CORTEX
   está vivo, e é isso que o movimento afirma. Só "parado" fica imóvel, porque
   só ele significa que ninguém respondeu. */
.marca .ponto[data-estado="ok"]::after,
.marca .ponto[data-estado="sem_criterio"]::after {
  animation: bat-calmo 2.6s ease-out infinite;
}
/* Atualizando: mais rápido, porque algo está de fato acontecendo agora. */
.marca .ponto[data-estado="atualizando"]::after { animation: bat-rapido 1s ease-out infinite; }
/* Dado velho: pulso DUPLO — o ritmo que o olho lê como alarme mesmo sem ver
   cor nenhuma. É a codificação secundária do vermelho, como o glifo é a do
   farol. */
.marca .ponto[data-estado="desatualizado"]::after,
.marca .ponto[data-estado="falhou"]::after { animation: bat-duplo 1.6s ease-out infinite; }
/* Parado: sem animação nenhuma. A ausência de movimento é a informação. */

@keyframes bat-calmo {
  0%   { opacity: .55; transform: scale(.75); }
  70%  { opacity: 0;   transform: scale(1.5); }
  100% { opacity: 0;   transform: scale(1.5); }
}
@keyframes bat-rapido {
  0%   { opacity: .7; transform: scale(.75); }
  60%  { opacity: 0;  transform: scale(1.45); }
  100% { opacity: 0;  transform: scale(1.45); }
}
@keyframes bat-duplo {
  0%   { opacity: .8; transform: scale(.75); }
  18%  { opacity: 0;  transform: scale(1.4); }
  26%  { opacity: .8; transform: scale(.75); }
  44%  { opacity: 0;  transform: scale(1.4); }
  100% { opacity: 0;  transform: scale(1.4); }
}
/* Quem pediu menos movimento recebe um anel fixo: o estado continua legível
   pela cor e pelo tooltip, e some só o batimento. */
@media (prefers-reduced-motion: reduce) {
  .marca .ponto::after { animation: none !important; opacity: .5; transform: scale(1.2); }
  .marca .ponto[data-estado="parado"]::after { opacity: 0; }
}

/* ------------------------------------------- referência do Book --- */
/* O cartão tem número, mas de outro mês. A tarja precisa ser impossível de não
   ver e, ao mesmo tempo, não parecer alarme — não há nada errado aqui: é o
   comportamento normal de uma carga mensal com defasagem. Daí a hachura
   (a mesma linguagem da ausência) em tom neutro, e não uma cor de estado. */
/* A tarja de referência foi removida do cartão — a etiqueta de origem
   ("Book M-1 ↩ ago/26") diz a mesma coisa em uma linha que já existia. */
.r37-cartao[data-farol="REFERENCIA"] { box-shadow: inset 0 2px 0 var(--neutro); }
.farol-referencia { color: var(--neutro); }
.r37-tira-item.tom-ref { border-left-color: var(--neutro); border-left-style: dashed; }

/* ===========================================================================
   DENSIDADE E MODOS
   ===========================================================================
   A grade passa a ser governada por `--colunas` em vez de `auto-fill`. A
   diferença importa: com `auto-fill` quem decide o número de colunas é a
   largura da janela; com `--colunas`, é a pessoa. O controle só faz sentido se
   ele realmente mandar.

   O `minmax(0, 1fr)` (e não `minmax(300px, 1fr)`) é o que permite 5 colunas
   numa tela média sem estourar: sem o zero, cada coluna se recusaria a
   encolher abaixo de 300px e a grade transbordaria.
   =========================================================================== */
.r37-grade { --colunas: 3; }
.r37-grade[data-modo="cartoes"] {
  display: grid; gap: 13px;
  grid-template-columns: repeat(var(--colunas), minmax(0, 1fr));
  /* `stretch` e não `start`: cartões da mesma linha com a mesma altura é o
     que faz os números e as séries ficarem no esquadro entre si. */
  align-items: stretch;
}
/* Abaixo de certa largura, a escolha da pessoa cede à física da tela: três
   colunas em 500px não são três colunas, são três tiras ilegíveis. */
@media (max-width: 1100px) { .r37-grade[data-modo="cartoes"] { --colunas: 2 !important; } }
/* Abaixo de 720 px a física manda e volta a uma coluna: duas colunas em 600 px
   não são duas colunas, são duas tiras. É a exceção que confirma a regra — lá
   não há largura para o cartão esticar. */
@media (max-width: 720px)  { .r37-grade[data-modo="cartoes"] { --colunas: 1 !important; } }

/* O TAMANHO DA ROSCA NÃO TEM MAIS DEGRAUS.
   Estas regras davam saltos — 148 px em três colunas, 96 em quatro — e o
   cartão "pulava" de desenho ao arrastar o cursor. Agora o tamanho é
   calculado da largura real do cartão (`tamanhoDaRosca`, em radar37.js) e
   publicado em `--rosca`: a escala é contínua e a transição, suave. É a
   "harmonia" que o Artur pediu. */

/* ------------------------------------------------- controle --- */
/* Discreto de propósito: cinza, sem rótulo, à direita. Controle de densidade é
   ajuste de conforto — peso visual igual ao do seletor de mês (que muda o
   NÚMERO) ensinaria a clicar no lugar errado. */
.dens { display: flex; align-items: center; gap: 2px; padding: 0 6px; }
.dens-modo {
  background: transparent; border: none; cursor: pointer; padding: 6px 7px;
  color: var(--ink-3); font-size: 12px; border-radius: 6px; line-height: 1;
}
.dens-modo:hover { color: var(--ink); background: var(--superficie-3); }
.dens-modo.on { color: var(--ink); background: var(--superficie-3); }
.dens-sep { width: 1px; height: 18px; background: var(--borda); margin: 0 5px; }
.dens-faixa { width: 74px; accent-color: var(--marca); cursor: pointer; }
.dens-conta { font: 700 11px/1 var(--fonte); color: var(--ink-3); width: 10px;
  font-variant-numeric: tabular-nums; }

/* ------------------------------------------------- modo LISTA --- */
/* Artur: "a visualização de linha, creio fique mais elegante em duas colunas."

   E resolve um problema real, não só estética: em uma coluna, 37 linhas de
   ~56 px ocupam 2 metros de rolagem numa tela de 1080. Em duas, cabem 18 por
   tela — a lista volta a servir para o que existe, que é VARRER os 37.

   A ordem continua sendo a do escopo, lida em COLUNAS (01–19 à esquerda,
   20–37 à direita) e não em serpentina. Numeração que pula de lado em lado
   obriga a procurar o próximo número, e a lista existe para não se procurar
   nada. `grid-auto-flow: column` com um número fixo de linhas é o que produz
   essa leitura.

   Abaixo de 1280 px volta a uma coluna: duas colunas de 500 px cortam o nome
   do indicador, e nome cortado num painel de 37 nomes parecidos é pior que
   rolar mais. */
.r37-grade[data-modo="lista"] {
  display: grid; gap: 4px 14px;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  grid-auto-flow: column;
  grid-template-rows: repeat(var(--linhas-lista, 19), auto);
}
@media (max-width: 1280px) {
  .r37-grade[data-modo="lista"] {
    grid-template-columns: 1fr; grid-auto-flow: row;
    grid-template-rows: none;
  }
}
/* AS COLUNAS ENCOLHEM; ELAS NÃO TRANSBORDAM.
   Eram oito faixas de largura FIXA somando 782 px dentro de uma linha de
   711 px — e uma grade que não cabe não quebra: ela vaza para fora da caixa,
   levando a faísca e o farol por cima do cartão vizinho.

   Agora cada faixa que pode encolher tem um piso e um teto (`minmax`), e a
   linha inteira tem `overflow: hidden` como rede de segurança. `min-width: 0`
   nos filhos é o que permite o encolhimento: sem ele, o conteúdo define um
   mínimo intransponível e a grade volta a estourar. */
.li37 {
  display: grid; align-items: center; gap: 10px;
  grid-template-columns:
    28px 22px minmax(110px, 1.6fr) minmax(74px, 112px) minmax(58px, 100px)
    minmax(54px, 70px) minmax(0, 170px) 22px;
  background: var(--superficie); border: 1px solid var(--borda);
  border-left: 3px solid var(--neutro); border-radius: 9px; padding: 9px 12px;
  overflow: hidden;
}
.li37 > * { min-width: 0; }
.li37.f-ok { border-left-color: var(--bom); }
.li37.f-critico { border-left-color: var(--critico); }
.li37.f-superado { border-left-color: var(--superado); }
.li37.vazio { border-style: dashed; grid-template-columns: 26px 1fr auto;
  background: var(--superficie-2); }
.li37 .pos { font: 700 10.5px/1 var(--fonte); color: var(--ink-3); }
.li37 .nome { font-size: 12.5px; font-weight: 600; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; }
.li37 .v { font: 700 15px/1 var(--fonte); text-align: right; }
.li37 .meta-min { font-size: 11px; color: var(--ink-3); text-align: right; }
.li37 .dir-min svg { width: 15px; height: 15px; color: var(--ink-2); }
/* A FAÍSCA DA LISTA, CONTIDA NA PRÓPRIA COLUNA.
   Artur: "ajuste estas incongruências de linhas ultrapassando e sem harmonia."

   Ela transbordava para a coluna vizinha por duas causas somadas: o SVG
   herdava `--alt-mini` (a altura calculada para o CARTÃO, que cresce com a
   largura), e as decorações do cartão — escala na lateral, iniciais dos meses,
   selo do ano a ano — vinham junto e não cabiam.

   Agora a faísca é uma caixa fechada: altura própria, `overflow: hidden` como
   rede de segurança, e as decorações de cartão explicitamente fora. Numa lista
   de 37 linhas, a faísca é uma pista de forma — quem quer ler a série usa o
   modo Gráfico. */
/* `overflow: visible` porque o balão do cruzamento precisa SAIR dos 40 px —
   ver a nota do pedido 55 logo abaixo. */
.li37 .spark-min {
  height: 40px; overflow: visible; position: relative;
  display: block; min-width: 0;
}
.li37 .spark-min .r37-area { height: 40px !important; width: 100%; display: block; }
.li37 .spark-min .r37-eixo,
.li37 .spark-min .r37-escala,
.li37 .spark-min .r37-meses,
.li37 .spark-min .r37-yoy-flut { display: none; }
/* O BALÃO VOLTA À LISTA — pedido 55.
   Artur: «embora tenhamos tirado os números, o tooltip deve continuar
   aparecendo».

   Ele está cobrando uma consequência do pedido 44, e com razão. Eu tinha
   escondido o balão aqui quando a faísca ainda escrevia os treze números:
   com os números na tela, o balão era redundante e só cobria as linhas
   vizinhas. Tirados os números, ele deixou de ser redundante e virou a
   ÚNICA forma de ler um valor na lista — e continuava escondido. Duas
   decisões certas isoladamente que, somadas, deixaram a lista muda.

   (As duas marcas de eixo ficaram escondidas aqui até o pedido 76, que as
   trouxe de volta — ver o bloco logo abaixo.) */
.li37 .spark-min .r37-balao-graf { z-index: 40; }
/* ===========================================================================
   O HIGHLIGHT DE X E Y TAMBÉM NA LISTA — pedido 76
   ===========================================================================
   Artur: «ao passar o mouse e qdo gera a visão cartesiana... ele deve mostrar
   o highlight dos valores em x e y como nos outros cards».

   Eu tinha escondido as duas pastilhas no pedido 55, e a razão estava escrita:
   «elas são posicionadas DENTRO dos 40 px e não têm para onde vazar». A razão
   era boa e a conclusão foi preguiçosa — «não cabe onde está» não é o mesmo
   que «não cabe». Elas cabem FORA: a pastilha do valor sai pela esquerda, na
   calha que o nome do indicador já deixa livre, e a do mês continua embaixo.
   Nenhuma das duas cobre a curva, que era o problema real.

   O contorno na cor da superfície é o que as separa da linha quando o
   sparkline da linha vizinha passa por trás — aqui as linhas ficam a 40 px
   uma da outra, e sem o contorno duas pastilhas de linhas diferentes se
   encostariam. */
.li37 .spark-min .r37-marca-y,
.li37 .spark-min .r37-marca-x {
  font-size: 8.5px; padding: 2px 4px;
  box-shadow: 0 0 0 1.5px var(--superficie);
}
/* O chip do VALOR não aparece na lista: à esquerda do sparkline mora a coluna
   de meta e variação, e ele caía em cima dela; dentro do gráfico, cobria a
   curva. O valor vai junto do mês no chip de baixo — ver `_pintarCruz`. */
.li37 .spark-min .r37-marca-y { display: none; }
.li37 .spark-min .r37-marca-x { bottom: -11px; }
.li37 .farol-min { text-align: center; font-size: 12px; }
.li37 .etq-min { font-size: 10.5px; color: var(--ink-3); text-transform: uppercase;
  letter-spacing: .04em; }
.mov-min { font: 700 10.5px/1 var(--fonte); border-radius: 5px; padding: 4px 6px;
  text-align: center; }
.mov-min.bom { color: var(--bom); background: var(--bom-bg); }
.mov-min.mau { color: var(--critico); background: var(--critico-bg); }
.mov-min.neu { color: var(--neutro); background: var(--neutro-bg); }
@media (max-width: 1100px) {
  .li37 { grid-template-columns: 26px 22px 1fr 100px 22px; }
  .li37 .meta-min, .li37 .spark-min, .mov-min { display: none; }
}

/* ------------------------------------------------ modo TABELA --- */
.tab37 { width: 100%; border-collapse: collapse; font-size: 12.5px;
  background: var(--superficie); border: 1px solid var(--borda);
  border-radius: 11px; overflow: hidden; }
.tab37 th {
  text-align: left; font: 700 10px/1 var(--fonte); text-transform: uppercase;
  letter-spacing: .06em; color: var(--ink-3); padding: 11px 10px;
  background: var(--superficie-2); border-bottom: 1px solid var(--borda);
  position: sticky; top: 0; z-index: 2;
}
.tab37 th.n, .tab37 td.n { text-align: right; font-variant-numeric: tabular-nums; }
.tab37 td { padding: 8px 10px; border-bottom: 1px solid var(--borda); }
.tab37 tbody tr:hover { background: var(--superficie-2); }
.tab37 td.nome { font-weight: 600; }
.tab37 td.forte { font-weight: 700; color: var(--ink); }
.tab37 tr.vazio td { color: var(--ink-3); }
.tab37 td.motivo-cel { font-size: 11.5px; }
.tab37 td.peq { font-size: 10.5px; color: var(--ink-3); }
.tab37 tr.f-ok td.farol-min { color: var(--bom); }
.tab37 tr.f-critico td.farol-min { color: var(--critico); }
.tab37 tr.f-superado td.farol-min { color: var(--superado); }

/* ----------------------------------------------- modo GRÁFICO --- */
/* Artur: "o formato gráfico ficou horrível e com ratio não preservado... deve
   ser 1 gráfico ou 2 por linha na altura da tela (controlável)."

   ERAM DOIS DEFEITOS, E O SEGUNDO CAUSAVA O PRIMEIRO.

   1. O desenho usava o viewBox da MINIATURA (280×78) esticado até ~900×360.
      O fator horizontal ficava ~3,2× e o vertical ~4,6×: a série saía
      achatada, e qualquer texto dentro do SVG saía deformado junto. Agora o
      modo Gráfico pede um viewBox na proporção real da caixa (ver
      `GEO_GRAFICO` em radar37.js) — a distorção desaparece sem abrir mão do
      `preserveAspectRatio="none"`, que é o que deixa a caixa acompanhar a
      largura da tela.

   2. 120px de altura num gráfico que ocupa a largura inteira é uma tira, não
      um gráfico. A altura agora vem da TELA (`--alt-graf`, em `vh`), e o
      número por linha é do controle: um ou dois.

   Um por linha ocupa ~62% da altura útil; dois por linha, ~46% cada, porque
   lado a lado cada um fica mais estreito e um gráfico estreito e alto mente
   sobre a amplitude tanto quanto um largo e baixo. */
/* DOIS POR LINHA É O PADRÃO. Um por linha deixava um cartão de 489 px de
   altura ocupando a tela inteira para mostrar UM indicador — para ver os 37
   eram 37 rolagens. Com dois por linha e a série na largura toda, o gráfico
   continua grande e cabem quatro na tela. Um por linha continua disponível
   no controle de densidade, para quem quer olhar um indicador de perto. */
.r37-grade[data-modo="grafico"] {
  --colunas-graf: 2;
  --alt-graf: 34vh;
  display: grid; gap: 14px;
  grid-template-columns: repeat(var(--colunas-graf), minmax(0, 1fr));
}
.r37-grade[data-modo="grafico"][style*="--colunas-graf: 1"] { --alt-graf: 52vh; }
@media (max-width: 900px) {
  .r37-grade[data-modo="grafico"] { --colunas-graf: 1 !important; --alt-graf: 52vh; }
}
.gr37 {
  background: var(--superficie); border: 1px solid var(--borda);
  border-left: 3px solid var(--neutro); border-radius: 11px; padding: 14px 18px 10px;
  display: flex; flex-direction: column;
}
.gr37.f-ok { border-left-color: var(--bom); }
.gr37.f-critico { border-left-color: var(--critico); }
.gr37.f-superado { border-left-color: var(--superado); }
.gr37.vazio { border-style: dashed; background: var(--superficie-2);
  min-height: 0; }
.gr37 header { display: flex; align-items: center; gap: 11px; margin-bottom: 10px;
  flex-wrap: wrap; }
.gr37 h3 { margin: 0; font-size: 16px; letter-spacing: -.01em; }
.gr37 .espaco { flex: 1 1 auto; }
.gr37 .r37-farol { font-size: 11px; margin-top: 2px; }

/* O CORPO EM DUAS COLUNAS: identidade à esquerda, série à direita.
   A coluna da identidade é FIXA (`flex: none`) e a série pega o resto: assim
   o número grande fica sempre no mesmo lugar de um cartão para o outro, e o
   olho não precisa reencontrá-lo a cada rolagem. Largura variável na coluna
   do número seria justamente o contrário. */
/* A SÉRIE PASSOU A OCUPAR A LINHA INTEIRA, COM A IDENTIDADE ACIMA DELA.
   Lado a lado, a identidade comia um terço da largura e o gráfico — que é o
   motivo de existir deste modo — ficava com dois terços de uma coluna já
   estreita. Empilhado, o gráfico recebe 100% da largura do cartão e a
   identidade vira uma faixa de cabeçalho: rosca menor à esquerda, os três
   números ao lado dela, tudo numa linha só. O número do miolo diminui, mas
   ele já está repetido em "Realizado" ao lado, em corpo grande.

   É o oposto do modo Cartões, e de propósito: lá a pergunta é "como está
   este indicador?", e a rosca responde; aqui é "como ele se comportou?", e
   quem responde é a série. */
.gr-corpo { display: flex; flex-direction: column; gap: 14px;
  flex: 1 1 auto; min-height: 0; }
.gr-identidade { flex: none; width: 100%;
  display: flex; gap: 20px; align-items: center; }
/* ===========================================================================
   A ELIPSE MAIOR — pedido 77
   ===========================================================================
   Artur: «amplie o tamanho do dash elipse aproveitando melhor visualmente o
   espaço disponível».

   132 px foi um número tímido, e dá para ver por quê: quando a série passou a
   ocupar a linha inteira (a faixa de identidade virou um cabeçalho), a rosca
   encolheu junto — mas o espaço à direita dela NÃO encolheu, porque os três
   números ocupam o que precisam e o resto vira branco. Sobrava um vão do
   tamanho da própria rosca.

   200 px é o ponto em que ela volta a ser a figura da faixa sem empurrar os
   números para uma segunda linha: medido nas duas densidades (um e dois
   gráficos por linha), que é onde a faixa aperta. Com dois por linha o
   conjunto encolhe sozinho, porque o corpo do número do miolo é calculado em
   unidades do viewBox. */
.gr-identidade .r37-medidor { width: var(--rosca-graf, 200px); flex: none; }
.gr-identidade .r37-rosca { width: var(--rosca-graf, 200px);
  height: auto; }
/* Os três números viram uma FAIXA HORIZONTAL ao lado da rosca, e não uma
   pilha: empilhados eles gastavam altura, e altura aqui é do gráfico. */
.gr-identidade .r37-numeros { display: flex !important; align-items: center;
  gap: 30px; flex-wrap: wrap; flex: 1 1 auto; min-width: 0;
  border: 0 !important; padding: 0 !important; }
.gr-identidade .r37-numeros > * { border: 0 !important; padding: 0 !important; }
.gr-identidade .r37-linha { display: flex; align-items: baseline; gap: 9px;
  flex: none; }
.gr-identidade .r37-linha b { font-size: 26px; letter-spacing: -.02em; }
.gr-identidade .r37-rodape { margin-left: auto; display: flex;
  align-items: center; gap: 8px; }
.gr-identidade .r37-numeros { flex: 1 1 auto; min-width: 0; }
.gr-identidade .r37-linha b { font-size: 20px; }
.gr-identidade .r37-rot { font-size: 12.5px; }
/* Com dois gráficos por linha o conjunto encolhe — e o número do miolo
   acompanha sozinho, porque o corpo dele é calculado em unidades do viewBox
   e é a caixa que escala. */
.r37-grade[style*="--colunas-graf: 2"] .gr-identidade { gap: 14px; }
.r37-grade[style*="--colunas-graf: 2"] .gr-identidade .r37-medidor,
.r37-grade[style*="--colunas-graf: 2"] .gr-identidade .r37-rosca {
  width: 108px;
}
.r37-grade[style*="--colunas-graf: 2"] .gr-identidade .r37-numeros {
  gap: 16px;
}
.r37-grade[style*="--colunas-graf: 2"] .gr-identidade .r37-linha b { font-size: 16px; }
@media (max-width: 1100px) {
  .gr-corpo { flex-direction: column; gap: 12px; }
  .gr-identidade { width: auto; }
}
/* A caixa do desenho cresce com o cartão; o SVG preenche. `min-height: 0` é o
   que impede o item flex de se recusar a encolher e estourar a altura. */
.gr-area { flex: 1 1 auto; min-height: 0; }
.gr-area .r37-area { width: 100%; height: 100%; display: block; }
/* Rótulos dentro do SVG: só o modo Gráfico os desenha, e é lá que a proporção
   está preservada — por isso eles não saem deformados. */
.r37-rot-x, .r37-rot-y {
  fill: var(--ink-3); font-family: var(--fonte); font-size: 13px; font-weight: 600;
}
.r37-rot-y { font-size: 12px; }
/* O valor escrito acima do ponto. O SVG da miniatura é esticado
   (`preserveAspectRatio: none`), então o texto sairia achatado na horizontal:
   `vector-effect` não resolve texto, mas `paint-order` com um contorno da cor
   do fundo resolve o problema que importa mais — o número por cima da própria
   linha, ilegível. Tamanho pequeno porque são até sete números num cartão de
   três por linha. */
/* O VALOR SOBRE O PONTO — Artur (25.2): «os números de cada intervalo são
   importantes, então garanta um fundo em branco ou algo para garantir a
   leitura adequada do número... use algo que também não agrida a curva».

   Fundo retangular de verdade custaria um <rect> por rótulo dentro de um SVG
   que é ESTICADO (`preserveAspectRatio: none`): o retângulo sairia deformado
   na horizontal e o texto não, e as duas deformações diferentes ficariam
   visíveis como um fundo torto. Já a `paint-order: stroke fill` desenha um
   CONTORNO da cor do fundo por baixo do próprio glifo — acompanha a letra,
   não deforma, e não tapa a curva além do necessário.

   O contorno era fino demais (2,4px) e sumia sobre a linha. Agora tem 3,5px
   e o texto ficou mais escuro: o número tem de vencer a curva, não empatar
   com ela. É o que «não agrida a curva» pede — cobrir o mínimo, com a forma
   da letra, em vez de um bloco opaco por cima do desenho. */
.r37-rot-v {
  /* 8px na miniatura: com os treze meses escritos (e não seis), cada rótulo
     tem cerca de 34px de cartão para ocupar. O zigue-zague resolve a
     vizinhança; o tamanho resolve a largura de cada um. */
  fill: var(--ink); font-family: var(--fonte); font-size: 8px;
  font-weight: 700; font-variant-numeric: tabular-nums;
  paint-order: stroke fill; stroke: var(--superficie); stroke-width: 3.5px;
  stroke-linejoin: round; stroke-linecap: round;
}
.gr-area .r37-rot-v { font-size: 11px; stroke-width: 4.5px; }

.r37-grade[data-modo="tabela"] { display: block; overflow-x: auto; }
.tab37 td.farol-min, .tab37 th:nth-last-child(2) { white-space: nowrap; }
.tab37 td.nome { max-width: 280px; }
.ref-min {
  margin-left: 6px; font: 700 9.5px/1 var(--fonte); color: var(--ink-2);
  border: 1px dashed var(--borda-forte); border-radius: 4px; padding: 3px 5px;
  cursor: help; white-space: nowrap;
}

/* O botão de Dicas mostra o ESTADO. Desligado, ele fica apagado — para não
   parecer que a função sumiu, e sim que está em repouso. */
#b-dicas[aria-pressed="false"] { opacity: .55; }


/* ===========================================================================
   A BARRA DE AQUECIMENTO — discreta, com ETA, e que SOME ao terminar
   ===========================================================================
   Artur: "enquanto ele estiver carregando o cache gere uma discreta mas bela
   barra de status com ETA... concluindo ela some aparecendo apenas durante a
   atualização."

   Ela mora colada embaixo da barra superior, na largura inteira: é o lugar em
   que uma barra de progresso não disputa espaço com nada e mesmo assim não
   passa despercebida. Tem 3px — o suficiente para ser vista, pouco o bastante
   para não empurrar a página (ela é `position: fixed`, então não empurra
   NADA: o conteúdo abaixo não se mexe quando ela aparece e some, que é o que
   torna o aparecimento tolerável).

   POR QUE UMA BARRA DETERMINADA E NÃO UMA RODINHA
   ------------------------------------------------
   Rodinha diz "espere". Barra com ETA diz "espere 23 segundos" — e a diferença
   entre as duas é a decisão que a pessoa toma: buscar um café ou ficar. O ETA
   vem da média MEDIDA das combinações já aquecidas nesta rodada, não de uma
   constante, e só aparece a partir da terceira (ver `backend/cache.py`).

   O brilho que corre por cima não é enfeite gratuito: ele é o que diz que a
   barra está VIVA quando o progresso trava por alguns segundos num mês grande.
   Barra parada sem brilho lê como travada. */
.barra-aquecer {
  position: fixed; left: 0; right: 0; z-index: 60;
  display: flex; align-items: center; gap: 10px;
  padding: 0 14px 5px; pointer-events: none;
  background: linear-gradient(to bottom,
    color-mix(in srgb, var(--plano) 92%, transparent), transparent);
  opacity: 0; transform: translateY(-6px);
  transition: opacity .28s ease, transform .28s ease;
}
.barra-aquecer.vis { opacity: 1; transform: translateY(0); }
.barra-aquecer .trilho {
  flex: 1; height: 3px; border-radius: 2px; overflow: hidden;
  background: color-mix(in srgb, var(--atencao) 18%, transparent);
}
.barra-aquecer .preenche {
  height: 100%; border-radius: 2px; background: var(--atencao);
  width: 0; transition: width .45s cubic-bezier(.22,.7,.3,1); position: relative;
}
.barra-aquecer .preenche::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(90deg, transparent,
    color-mix(in srgb, #fff 65%, transparent), transparent);
  animation: aquecer-brilho 1.5s linear infinite;
}
.barra-aquecer .rotulo {
  font: 600 10.5px/1 var(--fonte); color: var(--atencao);
  white-space: nowrap; font-variant-numeric: tabular-nums;
}
.barra-aquecer .etapa {
  font: 500 10.5px/1 var(--fonte); color: var(--ink-3);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 30ch;
}
@keyframes aquecer-brilho {
  from { transform: translateX(-100%); }
  to   { transform: translateX(100%); }
}
/* Sem movimento: a barra continua, o brilho vai embora. O progresso é
   informação; o brilho é só vida. */
@media (prefers-reduced-motion: reduce) {
  .barra-aquecer .preenche::after { animation: none; opacity: 0; }
  .barra-aquecer .preenche { transition: none; }
}

/* ===========================================================================
   O GRÁFICO DE ÁREA: GRADE LEVE E CRUZAMENTO X/Y QUE SEGUE O MOUSE
   ===========================================================================
   Artur: "ao passar o mouse sobre os gráficos de área, gere este grid de x/y
   com highlight dos valores de cada coordenada bem como leve grid na mesma
   área dos gráficos de área" e "o tooltip vai acima e fica centralizado para
   facilitar a leitura rápida do usuário e o cruzamento de x/y é acompanhado
   pelo movimento do mouse".

   A GRADE É PAPEL, NÃO DADO
   ---------------------------
   Ela usa `--grade`, o token mais fraco da paleta, e fica atrás de tudo. Uma
   grade que compete com a linha rouba a leitura que ela deveria facilitar. A
   régua do cruzamento, ao contrário, é temporária e por isso pode ser forte:
   ela só existe enquanto o mouse está lá.
   =========================================================================== */
.r37-graf { position: relative; }

.r37-grade-l { stroke: var(--grade); stroke-width: 1; }

/* A cruz nasce invisível e some na saída. Régua parada depois que o mouse
   saiu é ruído — e quem aprende a ignorar o ruído ignora junto a régua viva. */
.r37-cruz { opacity: 0; transition: opacity .12s ease; pointer-events: none; }
.r37-graf.cruz-viva .r37-cruz { opacity: 1; }
.r37-cruz-v, .r37-cruz-h {
  stroke: var(--ink-3); stroke-width: 1; stroke-dasharray: 3 3;
}
/* A vertical é mais firme: ela aponta para um mês, que é uma resposta exata.
   A horizontal é uma régua de leitura, e pode ser mais leve. */
/* O RASTRO — Artur (32): «ao sair de lá vc nota que ficou lá um rastro que
   não deveria estar lá, pois atrapalha a visualização posterior».

   Era esta linha. `.r37-cruz` nasce com `opacity: 0` e só acende dentro de
   `.cruz-viva`. Mas logo abaixo `.r37-cruz-v` redeclarava `opacity: .55`
   INCONDICIONALMENTE — mesma especificidade da regra de cima, e vindo
   depois, ela vencia. A régua vertical ficava acesa para sempre, e a regra
   seguinte (`.cruz-viva .r37-cruz-v`) parecia estar governando quando na
   verdade não mudava nada.

   Foi um descuido de ordem, não de conceito: a linha existe para ser mais
   discreta que a horizontal, e `.55` é a discrição pretendida — ela só não
   podia valer FORA do estado aceso. Agora a opacidade só aparece dentro de
   `.cruz-viva`, e a cor fica na regra incondicional, que é o que ela sempre
   quis dizer. */
.r37-cruz-v { stroke: var(--ink-2); stroke-dasharray: none; }
.r37-graf.cruz-viva .r37-cruz-v { opacity: .55; }

/* As coordenadas, em HTML e não em SVG: o SVG está esticado
   (preserveAspectRatio="none") e qualquer texto dentro dele sairia deformado. */
.r37-marca-y, .r37-marca-x {
  position: absolute; z-index: 2; pointer-events: none;
  font: 700 9.5px/1 var(--fonte); font-variant-numeric: tabular-nums;
  background: var(--ink-2); color: var(--plano);
  padding: 3px 5px; border-radius: 4px; white-space: nowrap;
  opacity: 0; transition: opacity .12s ease;
}
.r37-graf.cruz-viva .r37-marca-y,
.r37-graf.cruz-viva .r37-marca-x { opacity: 1; }
/* O valor da altura cola na borda esquerda, onde mora um eixo y; o rótulo do
   mês cola embaixo, onde mora o eixo x. Cada coordenada aparece no lugar em
   que se espera lê-la. */
.r37-marca-y { left: 0; transform: translateY(-50%); }
/* `left` vem do JS já LIMITADO à caixa do gráfico, e por isso aqui não há
   mais `translateX(-50%)`: no primeiro e no último mês o deslocamento de meia
   largura jogava metade do chip para fora do cartão, e o cartão corta.
   Rótulo cortado pela borda é pior que rótulo deslocado — o deslocado ainda
   se lê. Ver `_pintarCruz`. */
.r37-marca-x { bottom: -2px; }

/* ENQUANTO A CRUZ ESTÁ VIVA, O PISO E O TETO SOMEM.
   Os dois moram na mesma coluna que o chip do valor sob o cursor (esquerda,
   que é onde mora um eixo y) e ficavam um por cima do outro — três números
   empilhados em 9px, ilegíveis. Some o estático, fica o dinâmico: durante o
   apontamento o valor sob o cursor é mais informativo que os limites, e ao
   tirar o mouse os limites voltam. */
.r37-graf.cruz-viva ~ .r37-escala,
.r37-hist:has(.r37-graf.cruz-viva) .r37-escala { opacity: 0; }
.r37-escala { transition: opacity .12s ease; }
/* OS CHIPS VOLTARAM A NÃO RECEBER O MOUSE, e a ida e volta vale registro.
   Para responder «de que se tratam estes percentuais?» eu os tornei
   clicáveis. Medido depois: eles ficam colados na borda esquerda e engoliam
   a FAIXA DE CAPTURA DO PRIMEIRO MÊS — passar o mouse em set/25 deixou de
   abrir o balão do mês. Trocar a explicação de um elemento pela mudez de
   outro não é conserto.
   A explicação foi para a tira do eixo, logo abaixo: ela não se sobrepõe a
   nada e está a um pixel dos dois números. */
.r37-escala span { pointer-events: none; }

/* O MESMO ACORDO VALE PARA O RÓTULO DO FAROL.
   O balão do apontamento nasce acima do gráfico e centralizado — foi pedido
   assim, e é a posição certa: balão que segue o cursor cobre o trecho que se
   está lendo. Só que logo acima do gráfico mora "FORA DA META", e o balão
   cobria metade dele, deixando "FORA DA M…".

   Some enquanto se aponta, volta ao tirar o mouse. A informação não se perde:
   a borda colorida do cartão carrega o mesmo farol e continua visível. */
.r37-cartao .r37-farol { transition: opacity .12s ease; }
.r37-cartao:has(.r37-graf.cruz-viva) .r37-farol { opacity: 0; }

/* O BALÃO, ACIMA E CENTRALIZADO.
   Acima porque um balão que segue o cursor cobre justamente o trecho que se
   está lendo. Centralizado porque um balão que anda para os lados obriga o
   olho a persegui-lo — e a perseguição custa mais que a distância. Posição
   fixa vira um lugar que o olho aprende, e a leitura fica instantânea. */
.r37-balao-graf {
  position: absolute; left: 50%; bottom: calc(100% + 6px);
  transform: translateX(-50%) translateY(3px);
  display: flex; align-items: baseline; gap: 8px; white-space: nowrap;
  background: var(--superficie-3); border: 1px solid var(--borda-forte);
  border-radius: 8px; padding: 6px 10px; box-shadow: var(--sombra);
  font: 600 11px/1 var(--fonte); color: var(--ink-2);
  opacity: 0; pointer-events: none; z-index: 5;
  transition: opacity .12s ease, transform .12s ease;
}
.r37-graf.cruz-viva .r37-balao-graf {
  opacity: 1; transform: translateX(-50%) translateY(0);
}
/* AO LADO DO CARTÃO — pedido 32 (ver `_porBalaoAoLado`).
   A posição em pixels é escrita pelo JS, que é quem sabe onde o cartão está
   na tela. À folha cabe o que não depende de medida: tirar o deslocamento de
   entrada (o balão não sobe mais, ele aparece parado ao lado) e subir o
   `z-index` acima dos cartões vizinhos, já que agora ele os sobrevoa. */
.r37-graf[data-balao="lado"] .r37-balao-graf {
  transform: none; z-index: 40;
}
.r37-graf[data-balao="lado"].cruz-viva .r37-balao-graf { transform: none; }
.r37-balao-graf b { color: var(--ink); font-size: 11px; }
.r37-balao-graf .bg-v {
  color: var(--c); font-weight: 700; font-size: 12.5px;
  font-variant-numeric: tabular-nums;
}
.r37-balao-graf .bg-m { color: var(--meta); font-variant-numeric: tabular-nums; }
.r37-balao-graf .bg-s { color: var(--ink-3); font-style: italic; }
/* A legenda da âncora: fraca de propósito. Ela responde "o que é aquele
   circulozinho?" e nada mais — se competisse em peso com o valor do mês,
   trocaria um elemento mudo por um elemento barulhento. */
.r37-balao-graf .bg-a {
  display: block; margin-top: 2px; color: var(--ink-3);
  font-weight: 600; font-size: 10px; letter-spacing: .01em;
}

/* Toque não tem "passar o mouse": num aparelho sem cursor a cruz nunca se
   acende e o gráfico continua legível sem ela — por isso a grade e os rótulos
   dos extremos são desenhados de saída, e não só no hover. */
@media (hover: none) {
  .r37-balao-graf { display: none; }
}

/* ===========================================================================
   O CABEÇALHO DO RADAR, FIXO NO SCROLL
   ===========================================================================
   Artur: "deixe a linha até timeline fixo ao fazer o scroll vertical."

   Os 37 cartões rolam por várias telas. Sem isto, quem chega ao cartão 30 não
   sabe mais qual MÊS e qual REGIÃO está lendo — e esse erro não dá sintoma: a
   pessoa lê um número correto, da competência errada, e segue em frente.

   O `top` acompanha a faixa superior, que também é sticky. Encostar em 0
   esconderia este bloco atrás dela; o valor é a altura real do topo, medida
   uma vez e publicada como variável (ver `fixarTopoDoRadar`), porque a faixa
   quebra em duas linhas em telas estreitas e um número fixo aqui erraria
   justamente onde o espaço é curto.

   O fundo é opaco de propósito: com o fundo translúcido do topo, os cartões
   apareciam POR BAIXO da timeline enquanto rolavam, e o efeito é de um painel
   quebrado, não de um vidro fosco. */
.r37-fixo {
  position: sticky; top: var(--alt-topo, 56px); z-index: 30;
  background: var(--plano);
  margin: 0 -22px; padding: 0 22px;
  box-shadow: 0 10px 18px -14px rgba(0, 0, 0, .55);
}
.r37-fixo .tl-barra { margin-bottom: 12px; }

/* ---------------------------------------------------------------------------
   A BARRA ÚNICA — pedido 30
   ---------------------------------------------------------------------------
   Artur: «procure deixar na medida do possível apenas uma linha horizontal ou
   gere um sidebar à esquerda para não prejudicar a visualização... organize
   isto melhor e de forma mais objetiva sem perder funcionalidade».

   Eram TRÊS faixas empilhadas antes do primeiro cartão: título e subtítulo;
   chip da timeline, busca e região; e a navegação do tempo. Juntas comiam
   ~150px de altura útil num painel cuja razão de existir é mostrar 37 cartões.

   POR QUE LINHA E NÃO SIDEBAR (ele ofereceu as duas). A lateral ganharia
   altura e custaria largura, e aqui a largura é o recurso escasso: a grade é
   `auto-fill` de 300px e cada cartão desenha 13 colunas de mês. Tirar 220px
   tiraria uma coluna de cartões OU apertaria os treze meses — pagar a
   legibilidade do conteúdo para arrumar o controle é a troca errada.

   `align-items: center` e não `stretch`: os controles têm alturas naturais
   diferentes (a timeline é uma caixa com borda, o chip é uma pílula, a busca
   tem duas linhas). Alinhados pelo centro, a diferença não vira degrau.

   `flex-wrap: wrap` fica LIGADO: em tela estreita a barra quebra em duas
   linhas em vez de cortar a exportação fora da tela. Uma linha é a meta, não
   um dogma — controle que não cabe é controle que não existe.
   ------------------------------------------------------------------------- */
/* O VÃO CAIU DE 10 PARA 8 PX e o TÍTULO passou a poder encolher — pedido 75.
   A barra é uma linha só desde o pedido 30, e desde então entraram o chip do
   dia (65), os atalhos I…V (54) e o comparador (75). Cada um cabia; os três
   somados não. Dois pixels em oito vãos são 16 px de graça, e o título é o
   único elemento cujo corte não custa informação — «Radar Executivo» está
   escrito também na aba e no cabeçalho do aplicativo, duas linhas acima. */
.r37-barra {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  padding: 10px 0 12px; margin-bottom: 14px;
  border-bottom: 1px solid var(--borda);
}
.r37-barra .r37-tit-linha {
  flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap;
}
/* ===========================================================================
   ACIMA DE 1200 PX A BARRA NÃO QUEBRA — ela COMPRIME
   ===========================================================================
   Com `flex-wrap: wrap`, o encolhimento não acontece: o navegador prefere
   passar um item para a linha de baixo a espremer os da linha de cima. O
   resultado era que `min-width: 96px` na busca nunca era usado — ela ficava
   com 224 px e os atalhos caíam para a segunda linha, que é exatamente o que
   o pedido 30 proíbe.

   `nowrap` inverte a preferência: os itens encolhem até o seu mínimo e a
   linha continua uma só. Medido a 1500 px: a soma dos mínimos é ~1413 contra
   1436 disponíveis.

   ABAIXO DE 1200 PX A QUEBRA VOLTA, e isso é deliberado: lá não há como
   comprimir sem cortar informação, e duas linhas legíveis valem mais que uma
   linha ilegível. A regra é declarada, não um acidente de `flex-wrap`. */
@media (min-width: 1200px) {
  .r37-barra { flex-wrap: nowrap; }
  .r37-barra > * { min-width: 0; }
  .r37-barra .tl-barra, .r37-barra .r37-regiao-par,
  .r37-barra .r37-atalhos, .r37-barra .r37-exp-fim { flex: none; }
}
/* A timeline perde a margem própria aqui: dentro da barra quem governa o
   espaçamento é o `gap`, e margem somada a gap dá um vão que parece erro. */
.r37-barra .tl-barra { margin-bottom: 0; }
/* A BUSCA CEDE PRIMEIRO. Ela é o item elástico da linha: um campo de busca de
   180px ainda é utilizável (o texto rola), enquanto uma seta de mês de 8px
   não é clicável e um mês abreviado pela metade não é legível. Então a busca
   encolhe e o resto guarda o tamanho. */
/* A BUSCA É QUEM CEDE quando a barra aperta — e a escolha é deliberada.
   Entraram nela o chip do dia (pedido 65) e os atalhos I…V (pedido 54), e
   algo tinha de encolher para a linha continuar sendo uma só (pedido 30).
   O campo de busca é o único controle cuja utilidade não depende da
   LARGURA: um seletor estreito corta o nome da região, um chip estreito
   corta a data, mas um campo de busca de 112 px continua aceitando o que se
   digita e mostrando o fim do texto. Ceder aqui custa conforto; ceder em
   qualquer outro custa informação. */
.r37-barra .r37-busca { min-width: 96px; flex: 1 1 96px; max-width: 380px; }
/* SOBREPOR NUNCA É A RESPOSTA — pedido 77.
   Artur mandou a foto com «sintaxe» escrito POR CIMA do dropdown de recorte.
   A causa: `.r37-busca-linha` é item de grade, e item de grade tem mínimo
   automático igual ao próprio conteúdo. Quando a barra apertou (o comparador
   cresceu de «⇄» para «⇄ 4/4»), a caixa da busca encolheu para 96 px e a
   LINHA de dentro dela continuou com os seus ~150: o que não coube vazou
   para a direita e caiu no vizinho.
   Um item que não pode encolher vaza; vazar, numa linha única, é encavalar.
   `min-width: 0` devolve a ele o direito de encolher, e aí a caixa da busca
   volta a ser o limite do que ela desenha. */
.r37-barra .r37-busca-linha { min-width: 0; }
/* E A DICA «SINTAXE» SAI DA LINHA DISPUTADA — pedidos 77 e 81.
   Artur, com a busca «me 1.4» ativa: «quando há busca por palavra chave há
   encavalamento... harmonize isto». É a mesma causa vista por dentro: ao
   digitar, nasce a contagem («1 de 37»), e contagem + dica + campo passam a
   pedir mais largura do que a caixa da busca tem. Encolher o campo não
   resolve, porque os dois vizinhos são rígidos.
   Então a dica deixa de disputar: ela vai para a LINHA DE BAIXO, que já
   existe, é posicionada fora do fluxo e está vazia enquanto não há filtro.
   Custa zero pixel da barra, continua visível e clicável, e o painel de
   sintaxe abre ancorado nela como antes.
   DESCARTADO escondê-la enquanto não se busca: a sintaxe é o que se precisa
   saber ANTES de digitar — uma ajuda que só aparece depois chega tarde. */
.r37-barra .r37-busca-ajuda {
  position: absolute; right: 0; top: 100%; margin-top: 2px;
}
/* A leitura do filtro para antes da dica: elas dividem a mesma linha.

   `top: 100%` E NÃO `margin-top: 30px` — pedido 126. Artur: «continua
   encavalando texto». Medido: a leitura caía em 149–163 com o campo ocupando
   147–175, ou seja, DENTRO dele, e o «em qualquer campo» aparecia por baixo
   do que ele estava digitando.

   A causa é que `margin-top` num elemento absoluto SEM `top` desloca a
   posição estática — e a posição estática deste span não é o fim do campo,
   porque os irmãos à frente também saíram do fluxo. O número 30 era um palpite
   sobre a altura da linha, e palpite sobre altura erra em toda largura de
   janela que não seja a que eu testei. `top: 100%` mede a caixa de verdade. */
.r37-barra .r37-busca-leitura {
  position: absolute; top: 100%; margin-top: 2px; left: 0; right: 64px;
  max-width: none;
}
/* A cauda que dá rolagem ao último atalho — pedido 76. Altura escrita pelo
   JS, zero por padrão: sem alvo alto, ela não existe. */
.r37-cauda { height: 0; }
/* A segunda linha da busca (a leitura do filtro) vive fora do fluxo: ela só
   tem conteúdo quando há filtro ativo, e se ocupasse altura sempre a barra
   ficaria 14px mais alta 95% do tempo para nada. */
.r37-barra .r37-busca { position: relative; }
/* O rótulo «Região», visualmente oculto e ainda assim o nome acessível do
   campo. `clip-path` em vez de `display: none` — ver `seletorRegiao`. */
.r37-sel-rot {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap;
}

/* AS PEÇAS DA TIMELINE, COMPACTADAS SÓ DENTRO DA BARRA
   -------------------------------------------------------------------------
   O navegador de timeline sozinho media 962px dos 1436px disponíveis — dois
   terços da linha para um controle. Aqui ele perde respiro horizontal, e
   NADA mais: mesmos botões, mesmos alvos de clique, mesmos textos.

   O respiro sai do `padding` e não do `font-size`: fonte menor é o corte que
   se paga em leitura (estes campos são data e número, o que a pessoa lê de
   relance), enquanto padding menor se paga em conforto — e conforto é o que
   sobra quando a alternativa é o controle não caber na tela.

   Os alvos ficam acima de 32px de altura porque a linha toda tem 32px: o que
   encurtou é a largura ao redor do glifo, não a área clicável vertical. */
.r37-barra .tl-seta { padding: 0 9px; }
.r37-barra .tl-cal { padding: 0 6px 0 8px; }
.r37-barra .tl-faixa { padding: 0 10px; cursor: help; }
.r37-barra .tl-hoje { padding: 0 9px; }
.r37-barra .tl-granu { padding: 0 8px; }
.r37-barra .dens { padding: 0 4px; }
.r37-barra .dens-modo { padding: 6px 5px; }
/* O `select` do mês é largo pelo CONTEÚDO DA LISTA, não pelo que se vê: as
   opções trazem o sufixo «· só meta», e o navegador dimensiona o campo pela
   opção mais longa. Na tela cabe «set/26». Teto de largura resolve — a lista
   aberta continua mostrando o texto inteiro, que é onde ele importa. */
.r37-barra .tl-mes { max-width: 92px; }
/* O ⚙ tem a altura da barra e a largura de um glifo: é um gatilho de menu,
   não um botão de ação, e não deve competir com «Exportar». */
.r37-exib-abre {
  padding: 0 9px; min-height: 30px; font-size: 13px; line-height: 1;
}
.r37-exib-abre[aria-expanded="true"] { border-color: var(--marca); }
/* No menu, o cursor de "quantos por linha" ganha largura: lá o espaço existe,
   e passo de 1 em 1 num cursor de 56px é difícil de acertar com o mouse. */
.r37-exp-menu .dens-porlinha { padding: 0; gap: 8px; }
.r37-exp-menu .dens-faixa { width: 110px; }
.r37-exp-menu .tl-granus { border: 1px solid var(--borda); border-radius: 8px;
  overflow: hidden; }
/* O título encolhe antes de todo o resto: ele é o único item da barra que a
   pessoa não usa — ela já sabe em que aba está. */
.r37-tit-linha {
  margin: 0; font-size: 15.5px; letter-spacing: -.01em; white-space: nowrap;
  flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis;
}
/* O antigo subtítulo — «8/37 com número · set/26» — virou chip: é LEITURA e
   não controle, e diz a mesma coisa em um terço do espaço. O `cursor: help`
   avisa que a frase inteira está no balão. */
.r37-chip b, .r37-chip strong {
  font: 800 14.5px/1 var(--fonte-num); color: var(--ink);
  font-variant-numeric: tabular-nums lining-nums; letter-spacing: -.01em;
}
.r37-chip-resumo { cursor: help; }
.r37-chip-janela { cursor: help; opacity: .85; }
/* Exportar encosta na direita: é o fim do trabalho, e o canto oposto ao
   título é o lugar onde a mão já procura a ação final. */
.r37-barra .r37-exp-grupo { position: relative; }
/* Só a EXPORTAÇÃO encosta na direita — por isso a classe extra. `margin-left:
   auto` em dois itens da mesma linha reparte a folga entre eles, e o ⚙, que
   deve ficar colado na timeline que ele governa, sairia flutuando no meio
   quando a barra sobrasse espaço. */
.r37-barra .r37-exp-fim { margin-left: auto; }

/* O MENU DE EXPORTAÇÃO. Quatro controles sempre visíveis (formato, senha,
   botão, contador) para uma ação que acontece uma vez por reunião — viraram
   um botão com menu. «Sem perder funcionalidade» é literal: tudo continua lá
   dentro. */
.r37-exp-abre { white-space: nowrap; }
.r37-exp-abre[aria-expanded="true"] { border-color: var(--marca); }
.r37-exp-menu {
  position: absolute; right: 0; top: calc(100% + 8px); z-index: 70;
  display: flex; flex-direction: column; gap: 10px; align-items: stretch;
  background: var(--superficie-3); border: 1px solid var(--borda-forte);
  border-radius: var(--raio); padding: 13px 14px; box-shadow: var(--sombra);
  width: max-content; min-width: 250px; max-width: 340px;
}
/* `hidden` no HTML não basta: `display: flex` acima venceria o `display: none`
   que o atributo traz do estilo do navegador. Por isso ele é reafirmado. */
.r37-exp-menu[hidden] { display: none; }
.r37-exp-tit {
  font: 700 11px/1 var(--fonte); color: var(--ink-3);
  text-transform: uppercase; letter-spacing: .06em;
}
.r37-exp-linha { display: flex; align-items: center; gap: 10px;
  flex-wrap: wrap; }
.r37-exp-rot { font: 600 11.5px/1 var(--fonte); color: var(--ink-3);
  flex: none; }
/* Dentro do menu o botão de exportar ocupa a largura toda: é a ação do menu,
   e ação principal centralizada num menu estreito lê como rodapé de diálogo. */
.r37-exp-menu .r37-exportar { width: 100%; justify-content: center; }

/* ===========================================================================
   O PAINEL DE PROPRIEDADES — "3 pontinhos" em cada cartão
   ===========================================================================
   O botão vive no canto do cabeçalho do cartão e só fica nítido no hover do
   cartão: 37 botões sempre visíveis competem com 37 números, e o número é o
   assunto. Ele NÃO some de todo (opacidade, não display) porque um controle
   que aparece do nada quando o mouse passa é um controle que ninguém procura.
   =========================================================================== */
.r37-props {
  background: none; border: 1px solid transparent; color: var(--ink-3);
  font-size: 15px; line-height: 1; cursor: pointer; border-radius: 6px;
  padding: 3px 5px; opacity: .35; transition: opacity .15s ease,
    background-color .15s ease, color .15s ease;
}
.r37 :hover > .r37-props, .r37-cab:hover .r37-props { opacity: .8; }
.r37-props:hover { opacity: 1; color: var(--ink);
  background: var(--superficie-3); border-color: var(--borda); }
.r37-props:focus-visible { opacity: 1; outline: 2px solid var(--marca); }

.prop-caixa { max-width: 620px; max-height: 84vh; display: flex;
  flex-direction: column; }
.prop-cab { display: flex; align-items: flex-start; justify-content: space-between;
  gap: 12px; }
.prop-cab h3 { margin: 0 0 2px; }
.prop-sub { margin: 0; font-size: 12px; color: var(--ink-3); font-weight: 600; }
.prop-x { background: none; border: none; color: var(--ink-3); font-size: 22px;
  line-height: 1; cursor: pointer; padding: 0 4px; }
.prop-x:hover { color: var(--ink); }

.prop-abas { display: flex; gap: 2px; margin: 16px 0 4px;
  border-bottom: 1px solid var(--borda); }
.prop-aba {
  background: none; border: none; border-bottom: 2px solid transparent;
  color: var(--ink-3); font: 600 12px/1 var(--fonte); cursor: pointer;
  padding: 9px 11px; white-space: nowrap;
}
.prop-aba:hover { color: var(--ink-2); }
.prop-aba.on { color: var(--ink); border-bottom-color: var(--marca); }

.prop-corpo { overflow-y: auto; padding: 4px 2px 2px; flex: 1; min-height: 160px; }
.prop-nota-aba { margin: 8px 0 12px; font-size: 11.5px; line-height: 1.55;
  color: var(--ink-3); }
.prop-linha {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: 18px; padding: 12px 0; border-bottom: 1px solid var(--borda);
}
.prop-linha:last-child { border-bottom: none; }
.prop-rot { display: flex; align-items: center; gap: 6px; font: 600 13px/1.3 var(--fonte);
  color: var(--ink); cursor: pointer; }
.prop-ajuda { margin: 4px 0 0; font-size: 11.5px; line-height: 1.5;
  color: var(--ink-3); max-width: 40ch; }
/* O que foi mexido fica marcado: sem isso, "por que este cartão está
   diferente dos outros?" vira uma caça ao tesouro pelo arquivo de
   propriedades. */
.prop-tag { font: 700 9px/1 var(--fonte); text-transform: uppercase;
  letter-spacing: .06em; color: var(--marca);
  border: 1px solid var(--marca); border-radius: 4px; padding: 2px 4px; }
.prop-cadeado { font-size: 10px; opacity: .7; }

.prop-sel, .prop-txt {
  background: var(--plano); color: var(--ink); border: 1px solid var(--borda-forte);
  border-radius: 8px; font: 500 13px/1.4 var(--fonte); padding: 8px 10px;
  min-width: 170px; max-width: 220px; flex: none;
}
textarea.prop-txt { resize: vertical; min-height: 58px; }
.prop-sel:focus, .prop-txt:focus { outline: none; border-color: var(--marca); }

/* O interruptor: o mesmo desenho do exemplo que o Artur mandou, no vermelho
   da Claro. A pista fica visível mesmo desligada — interruptor invisível no
   estado "off" é interruptor que ninguém acha. */
.prop-switch { position: relative; width: 42px; height: 24px; flex: none;
  cursor: pointer; display: block; }
/* O ESCOPO AQUI NÃO É ENFEITE — É O DEFEITO QUE ELE EVITA.
   ---------------------------------------------------------------------------
   Artur: «está péssima a forma de alterar o setup... ou ele trava ou ele
   simplesmente não responde e às vezes dá certo... salvo e não é aplicado a
   todos».

   Era isto. A regra antiga era `.prop-chk { position:absolute; width:100%;
   height:100% }`, SEM escopo. Dentro do interruptor ela funciona: `.prop-switch`
   é `position:relative`, então 100% são 42×24px — a caixa invisível que
   recebe o clique em cima da pista desenhada.

   Mas a mesma classe foi reaproveitada no «aplicar a todos os 37», cujo pai
   NÃO é posicionado. Ali os 100% passaram a valer contra o bloco de conteúdo
   mais próximo — o fundo do diálogo. Medido na tela: 1500×1100px, opacidade
   zero, por cima de tudo a partir de (631, 425).

   Os três sintomas caem fora disso sozinhos: o clique some (cai no retângulo),
   funciona «às vezes» (o que está acima e à esquerda de 631×425 escapa), e —
   o pior — cada clique perdido ALTERNAVA o «aplicar a todos», porque o
   retângulo invisível É a caixa de seleção. O estado dela virava sorteio.

   Escopo estreito, e a classe deixa de poder vazar para o próximo uso. */
.prop-switch .prop-chk { position: absolute; inset: 0; opacity: 0;
  width: 100%; height: 100%; margin: 0; cursor: pointer; }
.prop-tri { position: absolute; inset: 0; border-radius: 999px;
  background: var(--superficie-3); border: 1px solid var(--borda-forte);
  transition: background-color .18s ease, border-color .18s ease; }
.prop-tri::after { content: ""; position: absolute; top: 3px; left: 3px;
  width: 16px; height: 16px; border-radius: 50%; background: var(--ink-3);
  transition: transform .18s cubic-bezier(.3,.8,.3,1), background-color .18s ease; }
.prop-chk:checked + .prop-tri { background: var(--core-vermelho, #FF140A);
  border-color: var(--core-vermelho, #FF140A); }
.prop-chk:checked + .prop-tri::after { transform: translateX(18px); background: #fff; }
.prop-chk:focus-visible + .prop-tri { outline: 2px solid var(--marca);
  outline-offset: 2px; }

/* As linhas travadas mostram o VALOR e a ORIGEM lado a lado: o valor sem a
   origem é uma afirmação sem fonte, e é justamente isso que este painel
   existe para não fazer. */
.prop-linha.travada { opacity: .92; }
.prop-valor { text-align: right; flex: none; max-width: 210px; }
.prop-valor b { display: block; font: 700 13px/1.35 var(--fonte); color: var(--ink);
  font-variant-numeric: tabular-nums; word-break: break-word; }
.prop-origem { display: block; margin-top: 3px; font-size: 10.5px;
  color: var(--ink-3); line-height: 1.4; }
.prop-estado { align-self: center; font-size: 11.5px; color: var(--ink-3);
  line-height: 1.45; }

/* ===========================================================================
   NÚMEROS MAIORES — cartão e lista
   ===========================================================================
   Artur: "os números devem ser muito maiores... se for necessário amplie a
   rosca mas preciso de números com melhor legibilidade... inclusive no formato
   lista aumentando o tamanho das fontes."

   O painel é lido em reunião, projetado, de longe, por quem tem 50 e poucos
   anos. 25px no miolo e 13px nas linhas eram um tamanho de tela de trabalho,
   não de tela de reunião — e o número é a única coisa nesta tela que precisa
   ser lida à distância.

   A rosca cresceu de 120 para 148px para o miolo caber sem encostar no anel.
   Crescer a fonte sem crescer o círculo empurraria o número contra o traço, e
   número encostado em linha perde legibilidade mais rápido do que ganha com o
   corpo maior.
   =========================================================================== */
/* O viewBox continua 148; a CAIXA é que cresce. Como o corpo do número é
   calculado em unidades do viewBox (ver `rosca` em radar37.js), ampliar a
   caixa amplia o número na mesma proporção — sem recalcular nada e sem risco
   de o texto passar a encostar no anel. */
/* A rosca e a miniatura seguem VARIÁVEIS publicadas pelo JS, que as calcula da
   largura real do cartão (ver `tamanhoDaRosca` e `geometriaDaMiniatura`). Os
   valores aqui são só a queda para o primeiro quadro, antes da medição. */
/* A ALTURA SEGUE O viewBox, A LARGURA CRESCE PELA ALTURA QUE SOBROU.
   Duas variáveis, as duas emitidas pelo próprio <svg>, que é onde a altura do
   viewBox é conhecida:

     --rosca-k   altura ÷ 148. Vale 1 na circular, ~0,74 na achatada.
     --rosca-w   quanto a largura cresce. Vale 1 na circular, 1,15 na achatada.

   Por que 1,15 e não 1/k (~1,35), que devolveria em largura TODA a altura
   liberada: a 1/k a rosca chegava a 243px num cartão de 470 e encostava na
   coluna dos valores — o número ficava maior e o cartão ficava pior, que é o
   oposto do pedido. A 1,15 o número cresce ~15%, a rosca ainda encolhe 29px
   na vertical, e essa altura vai para o gráfico da série logo abaixo. */
/* Sem largura própria: `--rosca-k` é emitido no <svg> (é lá que a altura
   do viewBox é conhecida) e só o <svg> consegue lê-lo. Com `flex: none` e
   largura automática, a coluna passa a medir exatamente o desenho — que é
   o que se quer, e evita repetir a conta em dois lugares que podem
   divergir. */
.r37-medidor { width: auto; }
.r37-rosca   { width: calc(var(--rosca, 178px) * var(--rosca-w, 1));
               height: calc(var(--rosca, 178px) * var(--rosca-w, 1)
                            * var(--rosca-k, 1)); }
.r37-val     { letter-spacing: -.02em; }
.r37-farol   { font-size: 10.5px; }

/* As linhas de meta e desafio: o valor sobe junto, mas menos que o do miolo.
   A hierarquia tem de continuar existindo — se meta e realizado tiverem o
   mesmo corpo, o olho não sabe mais qual é o número da reunião. */
.r37-linha b { font-size: 19px; }
.r37-rot     { font-size: 12px; }
.r37-cab h3  { font-size: 14px; }

/* Com 4 ou 5 colunas o cartão é estreito e o número volta a encolher — é
   física, não escolha: 34px num cartão de 240px estoura a caixa. */
/* O TEXTO continua por degrau, e isso é deliberado: corpo de fonte tem
   tamanhos que funcionam e tamanhos que não, e interpolar entre eles dá
   14,3 px — que o navegador arredonda de um jeito na sua tela e de outro na
   minha. Desenho é contínuo; tipografia é discreta. */
.r37-grade[style*="--colunas: 4"] .r37-linha b,
.r37-grade[style*="--colunas: 5"] .r37-linha b { font-size: 14px; }
.r37-grade[style*="--colunas: 5"] .r37-cab h3 { font-size: 12px; }
/* Uma ou duas colunas: há espaço de sobra, e o número aproveita. */
.r37-grade[style*="--colunas: 2"] .r37-linha b { font-size: 19px; }

/* ------------------------------------------------- LISTA maior --- */
/* A lista existe para varrer os 37 de cima a baixo. Se o valor não se lê na
   varredura, ela não serve para nada — vira uma tabela feia. O valor é o
   maior elemento da linha, com folga sobre o nome. */
/* Faixas elásticas, não fixas. Estas larguras fixas eram a causa do
   transbordo: elas somavam 782 px numa linha que, com a lista em DUAS
   colunas, tem 711 px. */
.li37 {
  grid-template-columns:
    28px 20px minmax(100px, 1.5fr) minmax(70px, 110px) minmax(54px, 86px)
    minmax(48px, 62px) minmax(0, 120px) 20px;
  padding: 9px 12px; gap: 10px;
}
.li37 .pos  { font-size: 12px; }
.li37 .nome { font-size: 15px; font-weight: 700; }
.li37 .v    { font: 700 22px/1 var(--fonte); letter-spacing: -.015em; }
.li37 .meta-min { font-size: 13px; }
.li37 .etq-min  { font-size: 12px; }
.li37 .farol-min { font-size: 15px; }
.li37 .dir-min svg { width: 18px; height: 18px; }

.mov-min { font-size: 12.5px; padding: 5px 8px; }
/* Numa tela larga, com duas colunas, ainda sobra espaço: a faísca e a meta
   voltam ao tamanho cheio. Abaixo disso elas saem, nesta ordem — a faísca é a
   primeira a ir porque é a que menos se lê numa varredura. */
/* CUIDADO COM `@media` AQUI: ela mede a JANELA, e a largura de que a linha
   dispõe é metade dela quando a lista está em duas colunas. Foi assim que a
   regra de 1700 px, pensada para uma tela larga, passou a estourar linhas de
   711 px. Por isso os tetos subiram, mas os pisos continuam baixos: a faixa
   usa o espaço quando ele existe e encolhe quando não. */
@media (min-width: 1700px) {
  .li37 {
    grid-template-columns:
      30px 22px minmax(110px, 1.6fr) minmax(74px, 120px) minmax(58px, 104px)
      minmax(52px, 70px) minmax(0, 170px) 22px;
  }
  .li37 .v { font-size: 24px; }
}
@media (max-width: 1100px) {
  .li37 { grid-template-columns: 30px 24px 1fr 120px 24px; }
}

/* ------------------------------------------- aviso de exportação --- */
/* Ele NÃO some sozinho: um caminho de arquivo é para ser lido e copiado, não
   visto de relance. O botão "Fechar" existe justamente porque ele fica. */
.exp-ok {
  background: var(--superficie); border: 1px solid var(--bom);
  border-left: 4px solid var(--bom); border-radius: 11px;
  padding: 13px 16px; margin: 0 0 13px;
  display: flex; flex-direction: column; gap: 7px;
}
.exp-ok.protegido { border-color: var(--superado); border-left-color: var(--superado); }
.exp-l1 { display: flex; align-items: center; gap: 9px; }
.exp-glifo { font-size: 15px; }
.exp-l1 b { font-size: 14px; }
.exp-bytes { font: 600 11px/1 var(--fonte); color: var(--ink-3);
  font-variant-numeric: tabular-nums; }
.exp-nome { font: 600 13px/1.3 var(--fonte); color: var(--ink-2); }
/* Qual cifra, por extenso. As duas saídas são AES-256 e NÃO são o mesmo
   mecanismo — quem precisa responder isso à segurança da informação tem de
   ler no aviso, não no código. */
.exp-cifra { margin-top: 3px; font: 500 11px/1.4 var(--fonte);
  color: var(--ink-3); }
.exp-caminho { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
.exp-rot { font: 700 10px/1 var(--fonte); text-transform: uppercase;
  letter-spacing: .07em; color: var(--ink-3); }
.exp-caminho code {
  font: 600 12.5px/1.5 ui-monospace, "Cascadia Mono", "Consolas", monospace;
  color: var(--ink); background: var(--superficie-3); border-radius: 6px;
  padding: 3px 7px; word-break: break-all; user-select: all;
}
.exp-falhou { color: var(--critico); }
.exp-acoes { display: flex; align-items: center; gap: 9px; flex-wrap: wrap;
  margin-top: 2px; }
.exp-acoes .btn { padding: 6px 11px; font-size: 12px; }
.exp-x { margin-left: auto; }

/* ------------------------------------- critérios da senha (✓/✕) --- */
/* Verde/vermelho para o que é obrigatório, âmbar para o que é recomendação.
   E sempre com GLIFO: quem não distingue verde de vermelho lê ✓ e ✕ igual —
   é a mesma regra do farol dos 37. */
.senha-criterios { list-style: none; margin: 14px 0 4px; padding: 0;
  display: flex; flex-direction: column; gap: 5px; }
.crit { display: flex; align-items: center; gap: 8px;
  font: 500 12px/1.3 var(--fonte); color: var(--ink-3); }
.crit-glifo { width: 15px; text-align: center; font-weight: 700; font-size: 12px; }
.crit-opc { font-size: 10px; text-transform: uppercase; letter-spacing: .06em;
  opacity: .7; margin-left: auto; }
.crit-ok    { color: var(--bom); }
.crit-mau   { color: var(--critico); font-weight: 600; }
.crit-fraco { color: var(--atencao); }
.crit-neutro { color: var(--ink-3); }
.r37-senha-caixa .btn-p:disabled { opacity: .45; cursor: not-allowed; }
.dens-faixa-curta { width: 40px; }

/* Caminho de arquivo numa tabela: quebra em qualquer ponto e pode ser
   selecionado inteiro com um clique. Caminho que estoura a coluna e some é a
   mesma coisa que caminho não mostrado. */
.cam { font: 500 11px/1.5 ui-monospace, "Cascadia Mono", "Consolas", monospace;
  word-break: break-all; user-select: all; color: var(--ink-2); }
.tab-rede td:first-child { white-space: nowrap; width: 1%; }
.tab-rede tr.ev-ok td:first-child b { color: var(--bom); }
.tab-rede tr.ev-ERRO td:first-child b { color: var(--critico); }

/* As quatro setas juntas: « ‹ › ». Separadas por meia barra elas não formam
   um par, e par é o que o olho procura para andar no tempo. */
.tl-setas { display: flex; align-items: stretch; }
.tl-setas .tl-seta:nth-child(2) { border-right: 1px solid var(--borda); }
.tl-setas .tl-seta:nth-child(3) { border-left: none; }

/* As perguntas do Cache & Aquecimento. Lista de definição porque é o que
   isto é: pergunta e resposta, com a pergunta sendo o índice. */
.cache-faq { margin: 4px 0 0; }
.cache-faq dt { font: 700 12.5px/1.4 var(--fonte); color: var(--ink);
  margin-top: 13px; }
.cache-faq dd { margin: 4px 0 0; font-size: 12px; line-height: 1.6;
  color: var(--ink-2); }

/* ===========================================================================
   O PAINEL EXECUTIVO DO TOPO
   ===========================================================================
   Substitui a tira de pendências. Ela contava "como vai a construção do
   painel" — pergunta de projeto, que deixa de existir quando o painel fica
   pronto. Este responde "como está a rede", que é a pergunta de um Radar
   Executivo, e usa o vocabulário dos próprios decks do cliente.
   =========================================================================== */
.px-painel {
  background: var(--superficie); border: 1px solid var(--borda);
  border-radius: 13px; padding: 15px 18px 13px; margin-bottom: 14px;
  display: flex; flex-direction: column; gap: 12px;
}
/* AS DUAS COLUNAS DO CABEÇALHO — pedido 37.2 (ver `painelExecutivo`).
   `auto` e não uma largura fixa na primeira coluna: quem decide a largura do
   medidor é o `clamp` dele, e repetir a medida aqui seria dois donos para o
   mesmo número. `minmax(0,1fr)` na segunda — sem o zero, um chip comprido em
   «maiores distâncias» se recusaria a encolher e estouraria a grade. */
.px-topo { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 26px; }
.px-topo-dir { display: flex; flex-direction: column; gap: 12px; min-width: 0; }
/* Abaixo de 1100px as duas colunas viram uma: o medidor a 236px mais uma
   coluna de conteúdo não cabem sem cortar os chips. */
@media (max-width: 1100px) { .px-topo { grid-template-columns: 1fr; } }

.px-linha { display: flex; align-items: stretch; gap: 26px; flex-wrap: wrap; }
.px-linha-2 { gap: 32px; border-top: 1px solid var(--borda); padding-top: 12px; }
/* OS RÓTULOS DE SEÇÃO — pedido 84.
   De 9,5px cinza em Inter para 12px na tinta escura em monoespaçada, com o
   filete da marca na frente. Três mudanças, e cada uma faz um trabalho: o
   TAMANHO tira o rótulo da zona de «letra miúda que se pula»; a TINTA o
   põe acima do texto de apoio em vez de abaixo dele; a FAMÍLIA diz que
   aquilo é estrutura e não conteúdo. O filete carrega a marca sem pintar
   o texto de vermelho — ver `--fonte-rot`. */
.px-rot, .px-rank-rot, .px-bl-rot {
  font: 700 12px/1.25 var(--fonte-rot); text-transform: uppercase;
  letter-spacing: .1em; color: var(--ink); margin-bottom: 7px;
  display: flex; align-items: center; gap: 7px;
}
.px-rot::before, .px-rank-rot::before, .px-bl-rot::before {
  content: ""; flex: none; width: 3px; height: 12px; border-radius: 2px;
  background: var(--marca);
}

/* O índice é o maior número da tela depois dos cartões: ele é a resposta de
   uma frase para "como está a rede?". */
.px-indice { flex: none; padding-right: 26px; border-right: 1px solid var(--borda); }
.px-num { display: flex; align-items: baseline; gap: 3px; }
.px-num b {
  font: 700 46px/1 var(--fonte); letter-spacing: -.03em;
  font-variant-numeric: tabular-nums;
}
.px-num span { font: 600 14px/1 var(--fonte); color: var(--ink-3); }
.px-classe {
  font: 700 10px/1 var(--fonte); text-transform: uppercase;
  letter-spacing: .1em; margin-top: 6px;
}
.px-saudavel .px-num b, .px-saudavel .px-classe { color: var(--bom); }
.px-atencao  .px-num b, .px-atencao  .px-classe { color: var(--atencao); }
.px-critico  .px-num b, .px-critico  .px-classe { color: var(--critico); }

/* --------------------------------------------------------------------------
   O MEDIDOR DE SAÚDE — pedido 35 (ver `medidorSaude` em radar37.js)
   -------------------------------------------------------------------------- */
/* O TAMANHO — pedidos 37 e 37.1. A largura ALVO é 320px, que é a largura da
   viewBox: nessa medida uma unidade do desenho é um pixel, e o vão de ~3
   unidades entre traços é um vão de 3 pixels de verdade. Abaixo dela o SVG
   escala junto e o vão encolhe proporcionalmente — por isso o piso do `clamp`
   é 236px e não 162: a 162px o vão voltaria para 1,5px, que é onde o
   antialiasing come a textura da régua (ver `medidorSaude` em radar37.js).

   `clamp` e não largura fixa porque o cabeçalho é `flex-wrap`: numa tela de
   1280 o medidor a 320px fixos empurraria o «dentro · fora» para a linha de
   baixo. Com `23vw` no meio, ele cede largura antes de quebrar a linha. */
.px-medidor {
  flex: none; cursor: help;
  padding-right: 26px; border-right: 1px solid var(--borda);
}
.px-med-arco { width: clamp(236px, 23vw, 320px); }
.px-med-svg {
  display: block; width: 100%; height: auto; overflow: visible;
  /* NÃO é `crispEdges`: 51 traços em 51 ângulos diferentes arredondados para
     o pixel viram 51 escadas, e alguns mais grossos que os outros.
     `geometricPrecision` faz o contrário — respeita a geometria exata. */
  shape-rendering: geometricPrecision;
}
/* O RÓTULO DO MEDIDOR É MAIOR QUE OS IRMÃOS — pedido 37: «devido à sua
   importância». Ele é o título do bloco mais importante do cabeçalho; nos
   outros blocos o rótulo é uma legenda, aqui é um título. */
.px-medidor > .px-rot { font-size: 12.5px; margin-bottom: 9px;
  justify-content: flex-start; }
/* O número do meio é o maior número da tela depois dos cartões, porque é a
   resposta de uma frase para "como está a rede?". Em unidades da viewBox:
   a 320px de largura ele sai com estes 58px na tela. */
/* ===================================================================
   O NÚMERO DA SAÚDE, NO MAIOR CORPO QUE O ANEL COMPORTA — pedido 99
   ===================================================================
   Artur: «ajuste a fonte ao máximo possível sem alterar o tamanho do
   radial... busque uma fonte a mais destacável possível pois se trata de
   um número importante».

   O TAMANHO SAIU DE MEDIÇÃO, e a primeira conta estava errada. O anel
   interno tem raio 92 em volta de (160, 150), e o caso que manda é «100»
   — três algarismos —, porque o corpo NÃO PODE MUDAR com o valor: tamanho
   que varia é lido como grandeza, e um 100 menor que um 57 diria o
   contrário do que o número diz.

   Eu estimei a caixa pela altura de caixa alta (0,72 × F) e cheguei a 78.
   Medido no navegador, a caixa real do `<text>` é 1,154 × F de altura e
   1,987 × F de largura para três algarismos — e a 78 o canto superior
   caía a 95,5 do centro, contra os 86 de limite. Teria cruzado os traços
   do anel, e eu não teria visto até alguém abrir um mês com índice 100.

   Com as medidas reais, resolvendo para o canto mais distante ≤ 86:

     meia-largura de «100»  = 0,994 × F
     topo da caixa          = base − 0,923 × F
     pé da caixa            = base + 0,231 × F

   F = 72 com a linha de base em 150+28 deixa os dois cantos superiores a
   81 e os inferiores a 84 — dentro do limite SEM depender da abertura de
   120° que o arco tem embaixo. É 24% maior que os 58 anteriores.

   O RADIAL NÃO MUDOU: mesmos 51 traços, mesmo raio, mesmo ponteiro — o que
   mudou foi só o que estava sobrando dentro dele.

   A FAMÍLIA É OUTRA, e isso é o resto do pedido. `--fonte-destaque` põe na
   frente as faces de EXIBIÇÃO do sistema: o «Segoe UI Variable Display»
   do Windows 11 foi desenhado para corpo grande (hastes mais firmes,
   entreletra mais fechada que a face de texto), e o «Segoe UI Black» do
   Windows 10 é o peso mais forte que a máquina já tem. Nenhum dos dois é
   baixado: o CORTEX não busca fonte de CDN, e uma <link> que não carrega
   na rede corporativa vira página quebrada em silêncio. Quem puser o
   Inter na pasta `fontes/` ganha o Inter ExtraBold na frente de todos. */
/* ESTES 78px VIRARAM REDE DE SEGURANÇA — pedido 132.
   Quem decide o corpo agora é `_ajustarNumeroDoMedidor`, em radar37.js: ele
   MEDE a tinta de «100» na fonte que esta máquina resolveu (canvas 2D) e
   escreve o `font-size` inline, que ganha desta regra. O cabeçalho daquela
   função tem a conta inteira e o porquê.
   O 78 fica aqui para o caso de o canvas não responder — e porque é o último
   valor que foi de fato medido, no pedido 129, com a base em +40.
   O caso que manda continua sendo «100», três algarismos: o corpo NÃO PODE
   mudar com o valor, porque tamanho que varia é lido como grandeza, e um 100
   menor que um 57 diria o contrário do que o número diz. */
.px-med-num {
  font: 800 78px/1 var(--fonte-destaque); letter-spacing: -.035em;
  font-variant-numeric: tabular-nums lining-nums;
  font-feature-settings: "tnum" 1, "lnum" 1;
  fill: var(--ink);
}
.px-med-de {
  font: 600 13px/1 var(--fonte); letter-spacing: .06em; fill: var(--ink-3);
  text-transform: uppercase;
}
/* As pontas da régua. Fracas de propósito: elas existem para serem
   encontradas quando a pessoa duvida da escala, não para serem lidas sempre. */
.px-med-lim {
  font: 600 11px/1 var(--fonte); fill: var(--ink-3); opacity: .65;
  font-variant-numeric: tabular-nums;
}
/* O halo do ponteiro usa a cor do PLANO e não uma cor fixa: no tema claro um
   halo escuro seria uma sombra, e no escuro um halo claro seria um brilho.
   Tomando o fundo, ele é sempre o mesmo gesto — um recorte. */
.px-med-ponteiro-halo { stroke: var(--superficie); }
.px-saudavel .px-med-num { fill: var(--bom); }
.px-atencao  .px-med-num { fill: var(--atencao); }
.px-critico  .px-med-num { fill: var(--critico); }

/* DENTRO · FORA — duas contagens e a proporção entre elas. */
.px-df { flex: none; min-width: 168px; cursor: help; }
.px-df-nums { display: flex; align-items: baseline; gap: 8px; }
.px-df-nums b {
  font: 700 26px/1.05 var(--fonte); letter-spacing: -.02em;
  font-variant-numeric: tabular-nums;
}
.px-df-nums i { font: 600 11px/1 var(--fonte); font-style: normal;
  color: var(--ink-3); }
.px-df-bom b { color: var(--bom); }
.px-df-mau b { color: var(--critico); }
.px-df-sep { color: var(--ink-3); font-size: 15px; }
/* A barra fecha 100% por construção: as duas fatias são `flex` com as
   contagens como fator de crescimento, então a proporção é o próprio dado —
   não há uma segunda conta de percentual aqui que pudesse divergir da de
   cima. Dividir por zero também não acontece: com as duas em 0 o flex
   simplesmente não distribui nada e a barra fica vazia, que é a verdade. */
.px-df-barra {
  display: flex; height: 6px; border-radius: 999px; overflow: hidden;
  background: var(--superficie-3); margin-top: 8px; width: 100%;
}
.px-df-fatia-bom { background: var(--bom); }
.px-df-fatia-mau { background: var(--critico); }

.px-bloco { flex: none; min-width: 108px; cursor: help; }
.px-v {
  font: 700 26px/1.05 var(--fonte); letter-spacing: -.02em; color: var(--ink);
  font-variant-numeric: tabular-nums;
}
.px-sub { font-size: 11px; color: var(--ink-3); margin-top: 4px; line-height: 1.35; }
.px-bom .px-v { color: var(--bom); }
.px-mau .px-v { color: var(--critico); }
.px-sup .px-v { color: var(--superado); }

.px-dim { flex: 1 1 320px; min-width: 0; cursor: help; }

/* AS LINHAS-BARRA — pedido 37.3 (ver `barraLinha` em radar37.js).
   Três colunas fixas em ORDEM DE LEITURA: quem é, quanto é (desenhado), quanto
   é (escrito). A coluna do meio tem largura FIXA e não `1fr` — se a barra
   esticasse com a coluna, duas listas lado a lado teriam réguas de
   comprimentos diferentes e pareceriam comparáveis sem ser. */
.px-barras { display: flex; flex-direction: column; gap: 2px; }
.px-bl {
  display: grid; grid-template-columns: minmax(0, 1fr) 104px 58px;
  gap: 10px; align-items: center; padding: 3px 0; cursor: help;
}
.px-bl-n {
  font-size: 12px; color: var(--ink-2); white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis;
}
/* A calha cinza é a régua: sem ela uma barra curta e uma barra ausente teriam
   o mesmo desenho, e «2% fora» leria como «não medido». */
.px-bl-t {
  height: 7px; border-radius: 999px; background: var(--superficie-3);
  overflow: hidden; display: block;
}
.px-bl-f { display: block; height: 100%; border-radius: 999px; }
.px-bl-mau { background: var(--critico); }
.px-bl-v {
  font: 700 13px/1 var(--fonte); font-variant-numeric: tabular-nums;
  text-align: right; color: var(--critico); white-space: nowrap;
}

.px-chips { display: flex; gap: 6px; flex-wrap: wrap; }
.px-chip {
  font: 600 11px/1 var(--fonte); color: var(--ink-2);
  background: var(--superficie-3); border: 1px solid var(--borda);
  border-radius: 999px; padding: 6px 10px; white-space: nowrap;
}
.px-chip b { color: var(--ink); font-variant-numeric: tabular-nums; }
.px-chip-mau { color: var(--critico); border-color: color-mix(in srgb, var(--critico) 40%, transparent);
  background: var(--critico-bg); }
.px-chip-mau b { color: var(--critico); }

.px-leitura { margin: 0; font-size: 12.5px; line-height: 1.55; color: var(--ink-2); }
/* O RODAPÉ DO CABEÇALHO — pedido 37.3. Uma linha só, discreta de propósito:
   ela some quando os 37 estiverem completos, e até lá não pode competir com
   o medidor nem com as barras. */
.px-rodape {
  display: flex; align-items: center; gap: 8px 14px; flex-wrap: wrap;
  border-top: 1px solid var(--borda); padding-top: 10px;
}
.px-pill {
  font: 600 10.5px/1 var(--fonte); text-transform: uppercase;
  letter-spacing: .07em; color: var(--ink-3); cursor: help;
  border: 1px dashed var(--borda); border-radius: 999px; padding: 5px 9px;
}
.px-pill:hover { color: var(--ink); border-color: var(--ink-3); }
.px-pend-rot {
  font: 700 9.5px/1.2 var(--fonte); text-transform: uppercase;
  letter-spacing: .09em; color: var(--ink-3); cursor: help;
}
/* Número em destaque, rótulo minúsculo ao lado — o mesmo par do «13 dentro ·
   10 fora», em escala de rodapé. */
.px-pend-i { display: inline-flex; align-items: baseline; gap: 4px; }
.px-pend-i b {
  font: 700 14px/1 var(--fonte); color: var(--ink-2);
  font-variant-numeric: tabular-nums;
}
.px-pend-i i {
  font: 600 10.5px/1 var(--fonte); font-style: normal; color: var(--ink-3);
}
.px-pend { margin: 0; font-size: 11px; color: var(--ink-3); }
/* A borda direita do medidor É o divisor das duas colunas: ela sai junto com
   elas, no mesmo ponto de quebra, senão vira um risco solto no meio da pilha. */
@media (max-width: 1100px) {
  .px-indice { border-right: none; padding-right: 0; }
  .px-medidor { border-right: none; padding-right: 0; }
}

/* ==========================================================================
   CADÊNCIA — o histograma de chegada e o horário que se ajusta sozinho
   ========================================================================== */
.cad-topo { display: flex; align-items: center; gap: 18px; flex-wrap: wrap;
  margin: 12px 0 8px; }
.cad-num { display: flex; flex-direction: column; gap: 2px; }
.cad-rot { font: 600 10.5px/1 var(--fonte); letter-spacing: .08em;
  text-transform: uppercase; color: var(--ink-3); }
.cad-num b { font: 800 30px/1 var(--fonte); font-variant-numeric: tabular-nums;
  letter-spacing: -.02em; color: var(--ink); }
.cad-ok b { color: var(--bom); }
.cad-off b { color: var(--ink-3); }
.cad-seta { font-size: 20px; color: var(--ink-3); }
.cad-auto { margin-left: auto; display: inline-flex; align-items: center;
  gap: 7px; font: 600 12.5px/1 var(--fonte); color: var(--ink-2);
  cursor: pointer; }
/* O motivo tem o mesmo peso visual do número: a decisão sem o porquê é o que
   faz alguém desligar o automático na primeira surpresa. */
.cad-porque { margin: 2px 0 10px; font: 500 13px/1.5 var(--fonte);
  color: var(--ink-2); max-width: 78ch; }
.cad-aviso { margin: 0 0 10px; font: 500 12px/1.5 var(--fonte);
  color: var(--atencao); background: var(--atencao-bg);
  border-radius: 8px; padding: 8px 11px; max-width: 78ch; }
.cad-travas { margin-top: 4px; }

.cad-linha { display: grid; grid-template-columns: 1fr 480px; gap: 16px;
  align-items: center; padding: 9px 0;
  border-top: 1px solid var(--borda); }
.cad-fraco { opacity: .55; }
.cad-nome b { display: block; font: 700 13px/1.3 var(--fonte); color: var(--ink); }
.cad-nome span { font: 500 11.5px/1.45 var(--fonte); color: var(--ink-3); }
.cad-hg { min-width: 0; }
.hg { width: 100%; height: 62px; display: block; }
.hg-b { fill: var(--neutro); opacity: .55; }
/* A barra do p90 é a única com consequência: é ela que define o horário. */
.hg-manda { fill: var(--marca); }
.hg-x { font: 600 9px var(--fonte); fill: var(--ink-3); }

.cad-hist { margin-top: 12px; }
.cad-hist summary { cursor: pointer; font: 600 12.5px/1 var(--fonte);
  color: var(--ink-2); }
.cad-h { display: grid; grid-template-columns: 74px 150px 1fr; gap: 10px;
  padding: 5px 0; font: 500 11.5px/1.45 var(--fonte); color: var(--ink-3);
  border-top: 1px solid var(--borda); }
.cad-h b { font-weight: 700; }
.cad-h b.sim { color: var(--bom); }
.cad-h b.nao { color: var(--ink-3); }
.cad-h i { font-style: normal; color: var(--ink-2); }

.cad-folgas { margin-top: 14px; padding-top: 12px;
  border-top: 1px dashed var(--borda-forte); }
.cad-folga { display: grid; grid-template-columns: 200px 54px 1fr; gap: 10px;
  padding: 5px 0; font: 500 12px/1.45 var(--fonte); color: var(--ink-2); }
.cad-folga b { font-weight: 700; color: var(--ink); }
.cad-cad { font: 700 10.5px/1.5 var(--fonte); letter-spacing: .06em;
  color: var(--ink-3); }
@media (max-width: 1150px) {
  .cad-linha { grid-template-columns: 1fr; }
}


/* O AVISO DE EXPORTAÇÃO, FIXO NO CANTO.
   Ele ficava dentro do painel e sumia na primeira repintura — o fim de um
   aquecimento bastava para apagar a única pista de onde o arquivo tinha ido.
   Fixo no viewport, sobrevive a tudo e só sai no Fechar. Sem temporizador:
   aviso que diz ONDE o arquivo está não pode expirar antes de alguém ir lá. */
.exp-ok.exp-fixo {
  position: fixed; right: 18px; bottom: 18px; z-index: 60;
  width: min(430px, calc(100vw - 36px)); margin: 0;
  box-shadow: 0 18px 44px rgba(0, 0, 0, .28);
  animation: expEntra .32s cubic-bezier(.2, .7, .2, 1) both;
}
@keyframes expEntra { from { opacity: 0; transform: translateY(14px); }
                      to   { opacity: 1; transform: none; } }
.exp-ok.exp-fixo .exp-caminho code { word-break: break-all; }
.exp-ok.exp-fixo .exp-x { align-self: flex-start; }
@media (prefers-reduced-motion: reduce) {
  .exp-ok.exp-fixo { animation: none; }
}

.exp-conf { margin-top: 8px; font: 500 11.5px/1.5 var(--fonte);
  border-radius: 8px; padding: 8px 10px; }
.exp-conf.sim { background: var(--bom-bg); color: var(--bom); }
.exp-conf.nao { background: var(--critico-bg); color: var(--critico); }
.exp-conf pre { margin: 6px 0 0; font: 500 10.5px/1.5 ui-monospace, monospace;
  color: var(--ink-2); white-space: pre-wrap; word-break: break-all; }

/* O "aplicar a todos" mora ao lado do Salvar, não entre os campos: é uma
   decisão sobre o ALCANCE do salvamento, não uma propriedade a mais. */
.prop-todos { display: inline-flex; align-items: center; gap: 7px;
  font: 600 12.5px/1 var(--fonte); color: var(--ink-2); cursor: pointer;
  margin-left: 4px; }
.prop-todos:hover { color: var(--ink); }
/* Menor que o dos campos porque mora no rodapé, entre botões — mas o MESMO
   desenho, para ninguém precisar aprender dois interruptores na mesma caixa. */
.prop-switch-mini { width: 34px; height: 19px; }
.prop-switch-mini .prop-tri::after { width: 13px; height: 13px; top: 2px;
  left: 2px; }
.prop-switch-mini .prop-chk:checked + .prop-tri::after {
  transform: translateX(14px); }

/* A TIRA DE ESTADO ao lado do anel: VPN e cache por extenso.
   Discreta por construção — ela informa, não alarma. O alarme continua sendo
   o anel, que é o que se nota sem olhar. */
.bat-tira { display: inline-flex; align-items: center; gap: 6px;
  margin-left: 4px; }
.bat-chip { font: 600 10.5px/1 var(--fonte); letter-spacing: .02em;
  padding: 4px 8px; border-radius: 999px; cursor: help; white-space: nowrap;
  border: 1px solid transparent; }
.bat-chip.bat-bom     { color: var(--bom); background: var(--bom-bg); }
.bat-chip.bat-atencao { color: var(--atencao); background: var(--atencao-bg); }
.bat-chip.bat-mau     { color: var(--critico); background: var(--critico-bg); }
.bat-chip.bat-nao     { color: var(--ink-3); background: var(--superficie-2);
  border-color: var(--borda); }
/* As pastilhas que FAZEM algo ao clique (banco e cache) mostram isso no
   cursor. `help` nas duas ensinava que pastilha é só texto com balão — e aí
   o clique que resolve o problema nunca é tentado. */
.bat-chip[role="button"] { cursor: pointer; }
.bat-chip[role="button"]:hover { border-color: currentColor; }
/* AQUECENDO É UM ESTADO VIVO — pedido 40. O contador já muda sozinho, mas
   entre dois passos lentos ele fica parado por segundos; a pulsação diz
   «isto está rodando» no intervalo em que o número não muda. */
.bat-chip.bat-pulsa { animation: batPulsa 1.6s ease-in-out infinite; }
@keyframes batPulsa { 0%, 100% { opacity: 1; } 50% { opacity: .55; } }
@media (prefers-reduced-motion: reduce) {
  .bat-chip.bat-pulsa { animation: none; }
}
@media (max-width: 1100px) { .bat-tira { display: none; } }

/* ==========================================================================
   DEV TRACKING — o ciclo de cada pedido
   ==========================================================================
   Artur: «preciso fazer o tracking do solicitado/implementado/testado/
   homologado… senão vou me perder em projeto tão complexo.»

   A tela tem uma pergunta dominante — «o que está esperando por mim?» — e o
   desenho responde a ela antes de qualquer outra coisa. Três decisões:

   1. AS QUATRO CAIXAS NÃO SÃO IGUAIS. Duas são do CORTEX e duas são dele, e
      há uma divisória desenhada entre a segunda e a terceira. Quatro caixas
      idênticas esconderiam justamente o ponto em que o trabalho muda de mão.

   2. O AMARELO É A FILA DELE. Implementado usa a cor de atenção não porque
      seja problema, mas porque é o único estado que pede ação de alguém. Os
      dois extremos são calmos de propósito: solicitado ainda não pede nada,
      homologado já não pede mais.

   3. AS PALAVRAS DELE SÃO CITAÇÃO, E PARECEM UMA. Barra lateral e itálico,
      para nunca serem confundidas com o meu resumo — quando os dois
      divergirem, é a citação que vale.
   ========================================================================== */
.tr-topo { margin: 2px 0 14px; }
.tr-topo h2 { margin: 0 0 4px; font-size: 19px; letter-spacing: -.01em; }
.tr-sub { margin: 0; color: var(--ink-2); font-size: 13px; }

/* ------------------------------------------------- a tira de etapas --- */
.tr-tira {
  display: flex; align-items: stretch; gap: 8px; flex-wrap: wrap;
  margin-bottom: 12px;
}
.tr-etapa {
  flex: 1 1 130px; min-width: 120px;
  display: grid; gap: 1px; justify-items: start;
  padding: 9px 12px; border-radius: var(--raio); cursor: pointer;
  background: var(--superficie-2); border: 1px solid var(--borda);
  color: var(--ink-2); text-align: left;
  transition: border-color .12s, background .12s;
}
.tr-etapa:hover { border-color: var(--borda-forte); }
.tr-etapa.viva { border-color: currentColor; background: var(--superficie-3); }
.tr-etapa b { font-size: 24px; line-height: 1.05; font-variant-numeric: tabular-nums; }
.tr-et-rot { font-size: 12.5px; color: var(--ink); }
.tr-et-dono {
  font-size: 10px; font-style: normal; letter-spacing: .07em;
  text-transform: uppercase; color: var(--ink-3);
}
.tr-etapa.tom-nao      { color: var(--neutro); }
.tr-etapa.tom-atencao  { color: var(--atencao); }
.tr-etapa.tom-bom      { color: var(--bom); }
.tr-etapa.tom-fechado  { color: var(--superado); }

/* A DIVISÓRIA: onde o trabalho muda de mão. Ela é um elemento e não uma
   borda porque precisa carregar texto — uma linha muda não explicaria nada. */
.tr-divisa {
  flex: 0 0 auto; display: grid; place-items: center; padding: 0 2px;
  border-left: 1px dashed var(--borda-forte);
  border-right: 1px dashed var(--borda-forte);
}
.tr-divisa span {
  writing-mode: vertical-rl; text-orientation: mixed;
  font-size: 9.5px; letter-spacing: .1em; text-transform: uppercase;
  color: var(--ink-3); padding: 4px 3px;
}

/* ------------------------------------------------------- a régua ------ */
.tr-regra {
  background: var(--superficie); border: 1px solid var(--borda);
  border-radius: var(--raio); padding: 8px 12px; margin-bottom: 12px;
}
.tr-regra summary {
  cursor: pointer; font-size: 12.5px; color: var(--ink-2); font-weight: 600;
}
.tr-regra p { font-size: 12.5px; line-height: 1.5; color: var(--ink-2); }
.tr-regra code {
  background: var(--superficie-3); padding: 1px 5px; border-radius: 4px;
  font-size: 12px;
}

/* ------------------------------------------------------ os filtros ---- */
.tr-filtros { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 12px; }
.tr-chip {
  background: var(--superficie-2); border: 1px solid var(--borda);
  color: var(--ink-3); border-radius: 999px; padding: 4px 11px;
  font-size: 11.5px; cursor: pointer; transition: color .12s, border-color .12s;
}
.tr-chip:hover { color: var(--ink-2); border-color: var(--borda-forte); }
.tr-chip.viva {
  color: var(--ink); border-color: var(--marca);
  background: color-mix(in srgb, var(--marca) 12%, transparent);
}

/* -------------------------------------------------------- a lista ----- */
.tr-lista { display: grid; gap: 9px; }
.tr-item {
  background: var(--superficie); border: 1px solid var(--borda);
  border-left: 3px solid var(--neutro);
  border-radius: var(--raio); padding: 11px 14px;
}
.tr-item.et-atencao  { border-left-color: var(--atencao); }
.tr-item.et-bom      { border-left-color: var(--bom); }
.tr-item.et-fechado  { border-left-color: var(--superado); opacity: .82; }

.tr-cab {
  display: flex; align-items: baseline; gap: 9px; flex-wrap: wrap;
  margin-bottom: 5px;
}
.tr-id {
  font-size: 12px; font-weight: 700; letter-spacing: -.01em;
  color: var(--marca); background: color-mix(in srgb, var(--marca) 11%, transparent);
  border-radius: 5px; padding: 2px 7px; flex: none; cursor: help;
}
.tr-resumo { flex: 1 1 260px; font-size: 13.5px; color: var(--ink); line-height: 1.4; }
.tr-selo {
  flex: none; font-size: 10.5px; font-weight: 700; letter-spacing: .06em;
  text-transform: uppercase; border-radius: 999px; padding: 3px 9px;
  cursor: help;
}
.tr-selo.tom-nao     { color: var(--neutro);   background: var(--neutro-bg); }
.tr-selo.tom-atencao { color: var(--atencao);  background: var(--atencao-bg); }
.tr-selo.tom-bom     { color: var(--bom);      background: var(--bom-bg); }
.tr-selo.tom-fechado { color: var(--superado); background: var(--superado-bg); }

.tr-meta {
  display: flex; flex-wrap: wrap; gap: 4px 14px;
  font-size: 11.5px; color: var(--ink-3); margin-bottom: 7px;
}
.tr-meta > span { cursor: help; }
.tr-onde { color: var(--ink-2); }
.tr-versao { font-variant-numeric: tabular-nums; }

.tr-fala {
  margin: 0 0 7px; padding: 4px 0 4px 11px;
  border-left: 2px solid var(--borda-forte);
  font-style: italic; font-size: 12.5px; line-height: 1.5; color: var(--ink-2);
  cursor: help;
}
.tr-evid, .tr-nota {
  margin: 0 0 6px; font-size: 12.5px; line-height: 1.5; color: var(--ink-2);
}
.tr-nota { color: var(--ink-3); }
.tr-evid b, .tr-nota b { color: var(--ink-2); }

/* O IMPEDIMENTO — a única linha do cartão que diz o que fazer a seguir, e
   por isso a única com marcador à esquerda. Âmbar e não vermelho: item
   parado esperando uma decisão não é defeito, é fila. */
.tr-aguarda {
  margin: 0 0 6px; font-size: 12.5px; line-height: 1.5; color: var(--ink-2);
  border-left: 2px solid var(--atencao);
  padding: 2px 0 2px 9px; background: var(--atencao-bg);
  border-radius: 0 3px 3px 0;
}
.tr-aguarda b { color: var(--atencao); }

.tr-acoes { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; margin-top: 8px; }
.btn-min { font-size: 11.5px; padding: 4px 11px; }
.btn-min.btn-on {
  border-color: var(--bom); color: var(--bom);
  background: var(--bom-bg);
}
.btn-min.btn-fraco { color: var(--ink-3); border-color: transparent; }
.btn-min.btn-fraco:hover { color: var(--ink-2); border-color: var(--borda); }
.tr-superou {
  font-size: 11px; color: var(--atencao); cursor: help;
  border: 1px dashed color-mix(in srgb, var(--atencao) 45%, transparent);
  border-radius: 999px; padding: 2px 9px;
}

/* A confirmação que substitui a linha que saiu da fila filtrada. Ver o
   comentário em `trackConfirmar` — ela existe porque marcar fazia a linha
   sumir em silêncio, e sumir em silêncio é indistinguível de falhar. */
.tr-confirma {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  background: color-mix(in srgb, var(--bom) 10%, transparent);
  border: 1px solid color-mix(in srgb, var(--bom) 32%, transparent);
  border-radius: var(--raio); padding: 7px 12px; margin-bottom: 10px;
  font-size: 12.5px; color: var(--ink-2);
}
.tr-confirma b { color: var(--bom); }

/* A faixa de "só leitura" do Dev Tracking. Ela existe porque a aba subiu para
   o topo e passou a abrir sem login: a leitura é aberta, marcar não é. Dizer
   isso ANTES do clique é o ponto — descobrir a regra levando um erro depois de
   clicar é o padrão que ensina a desconfiar da tela, e esta aba, de todas, é a
   que não pode ser desconfiada. */
.tr-trava {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  background: var(--neutro-bg);
  border: 1px dashed color-mix(in srgb, var(--neutro) 45%, transparent);
  border-radius: var(--raio); padding: 8px 12px; margin-bottom: 11px;
  font-size: 12.5px; color: var(--ink-2);
}
.tr-acoes .btn-min:disabled { opacity: .45; cursor: not-allowed; }

/* ==========================================================================
   VERSIONAMENTO — o que entrou, versão por versão
   ========================================================================== */
.vs-contrato {
  display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap;
  border-radius: var(--raio); padding: 8px 12px; margin-bottom: 11px;
  font-size: 12.5px; color: var(--ink-2); cursor: help;
}
.vs-contrato.tom-bom {
  background: var(--bom-bg);
  border: 1px solid color-mix(in srgb, var(--bom) 32%, transparent);
}
.vs-contrato.tom-atencao {
  background: var(--atencao-bg);
  border: 1px solid color-mix(in srgb, var(--atencao) 36%, transparent);
}
.vs-contrato b { color: var(--ink); text-transform: lowercase; }
.vs-contrato code { font-size: 11.5px; opacity: .8; }
.vs-tipo-exp { display: block; margin-bottom: 3px; }

.vs-lista { display: grid; gap: 7px; }
.vs-item {
  background: var(--superficie); border: 1px solid var(--borda);
  border-radius: var(--raio); overflow: hidden;
}
/* A versão instalada ganha marca própria: numa lista de vinte, saber em qual
   delas você está é a primeira pergunta. */
.vs-item.vs-atual { border-color: color-mix(in srgb, var(--marca) 55%, transparent); }
.vs-cab {
  display: flex; align-items: center; gap: 9px; flex-wrap: wrap;
  width: 100%; text-align: left; cursor: pointer;
  background: none; border: 0; padding: 9px 13px; color: var(--ink-2);
}
.vs-cab:hover { background: var(--superficie-2); }
.vs-cab.aberta { background: var(--superficie-2); }
.vs-seta { color: var(--ink-3); font-size: 11px; width: 10px; flex: none; }
.vs-num {
  font-weight: 700; font-size: 12.5px; color: var(--marca);
  background: color-mix(in srgb, var(--marca) 11%, transparent);
  border-radius: 5px; padding: 2px 7px; flex: none;
}
.vs-tit { flex: 1 1 240px; color: var(--ink); font-size: 13px; line-height: 1.35; }
.vs-conta, .vs-data { font-size: 11px; color: var(--ink-3); flex: none; }
.vs-selo {
  font-size: 10px; font-weight: 700; letter-spacing: .05em;
  text-transform: uppercase; border-radius: 999px; padding: 2px 8px; flex: none;
}
.vs-selo.tom-mau     { color: var(--critico);  background: var(--critico-bg); }
.vs-selo.tom-atencao { color: var(--atencao);  background: var(--atencao-bg); }
.vs-selo.tom-bom     { color: var(--bom);      background: var(--bom-bg); }
.vs-selo.tom-nao     { color: var(--neutro);   background: var(--neutro-bg); }
.vs-selo.tom-marca {
  color: var(--marca);
  background: color-mix(in srgb, var(--marca) 14%, transparent);
}
.vs-itens { margin: 0; padding: 2px 16px 12px 40px; display: grid; gap: 6px; }
.vs-itens li { font-size: 12.5px; line-height: 1.5; color: var(--ink-2); }

/* ==========================================================================
   LOG & DIAGNÓSTICO
   ========================================================================== */
.dg-barra {
  display: flex; align-items: center; gap: 9px; flex-wrap: wrap;
  margin-bottom: 11px;
}
.dg-recado { font-size: 12.5px; color: var(--ink-2); }
.dg-pacotes { margin: 6px 0 0; padding-left: 18px; display: grid; gap: 4px; }
.dg-pacotes li { font-size: 12px; color: var(--ink-3); }
.dg-pacotes code { color: var(--ink-2); }

/* O diário é lido varrendo, não lendo: fonte monoespaçada na hora, colunas
   fixas, e a linha inteira em uma só altura. Cartões aqui obrigariam a rolar
   quatro vezes mais para ver a mesma sequência de eventos. */
.dg-log {
  background: var(--superficie); border: 1px solid var(--borda);
  border-radius: var(--raio); overflow: hidden;
}
.dg-linha {
  display: grid;
  grid-template-columns: 110px 64px 96px minmax(0, 1fr);
  gap: 10px; align-items: baseline;
  padding: 5px 12px; font-size: 12px; line-height: 1.45;
  border-top: 1px solid var(--borda);
  border-left: 3px solid transparent;
}
.dg-linha:first-child { border-top: 0; }
.dg-linha.n-mau     { border-left-color: var(--critico); background: var(--critico-bg); }
.dg-linha.n-atencao { border-left-color: var(--atencao); }
.dg-hora { color: var(--ink-3); font-size: 11px; white-space: nowrap; }
.dg-nivel {
  font-size: 10px; font-weight: 700; letter-spacing: .05em; color: var(--ink-3);
}
.dg-linha.n-mau .dg-nivel     { color: var(--critico); }
.dg-linha.n-atencao .dg-nivel { color: var(--atencao); }
.dg-origem { color: var(--ink-3); font-size: 11.5px; }
.dg-msg { color: var(--ink-2); word-break: break-word; }
.dg-det { grid-column: 4; color: var(--ink-3); font-size: 11px; opacity: .8; }

@media (max-width: 900px) {
  .dg-linha { grid-template-columns: 1fr; gap: 2px; }
  .dg-det { grid-column: 1; }
}
.dg-conta-mau     { color: var(--critico); }
.dg-conta-atencao { color: var(--atencao); }

/* ==========================================================================
   A BUSCA DO RADAR EXECUTIVO
   ==========================================================================
   Ela vive no cabeçalho fixo, junto com região e timeline, porque é dali que
   se governa o que se está vendo. A contagem ao lado do campo não é enfeite:
   uma busca que devolve 3 de 37 sem dizer quantos são indistinguível de uma
   busca quebrada, e a dúvida recai sobre o dado.
   ========================================================================== */
.r37-busca { display: grid; gap: 3px; min-width: 300px; flex: 1 1 320px; max-width: 460px; }
.r37-busca-linha { display: flex; align-items: center; gap: 7px; }
.r37-busca-campo {
  flex: 1 1 auto; min-width: 0;
  background: var(--superficie-2); border: 1px solid var(--borda);
  color: var(--ink); border-radius: 8px; padding: 6px 10px; font-size: 12.5px;
}
.r37-busca-campo::placeholder { color: var(--ink-3); opacity: .75; }
.r37-busca-campo:focus {
  outline: none; border-color: var(--marca);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--marca) 18%, transparent);
}
.r37-busca-conta {
  flex: none; font-size: 11.5px; color: var(--ink-3);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
/* Zero resultados é um estado, não um vazio: ele ganha cor para a pessoa
   perceber que a busca é que está estreita, e não o painel que esvaziou. */
.r37-busca-conta.vazio { color: var(--atencao); font-weight: 600; }
.r37-busca-leitura {
  font-size: 10.5px; color: var(--ink-3); line-height: 1.3;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.r37-busca-ajuda { flex: none; }
.r37-busca-ajuda summary {
  cursor: pointer; font-size: 11px; color: var(--ink-3);
  list-style: none; padding: 2px 6px; border-radius: 6px;
  border: 1px solid var(--borda);
}
.r37-busca-ajuda summary::-webkit-details-marker { display: none; }
.r37-busca-ajuda summary:hover { color: var(--ink-2); border-color: var(--borda-forte); }
.r37-busca-ajuda[open] { position: relative; }
.r37-busca-grade {
  position: absolute; right: 0; top: 26px; z-index: 60;
  display: grid; grid-template-columns: auto minmax(0, 1fr);
  gap: 5px 12px; align-items: baseline;
  background: var(--superficie-3); border: 1px solid var(--borda-forte);
  border-radius: var(--raio); padding: 12px 14px; box-shadow: var(--sombra);
  width: max-content; max-width: 520px;
}
.r37-busca-grade code {
  font-size: 11.5px; color: var(--marca); white-space: nowrap;
  background: color-mix(in srgb, var(--marca) 10%, transparent);
  border-radius: 4px; padding: 1px 6px;
}
.r37-busca-grade span { font-size: 11.5px; color: var(--ink-2); }
.r37-busca-nada {
  grid-column: 1 / -1; padding: 28px 20px; text-align: center;
  color: var(--ink-2); font-size: 13px;
  border: 1px dashed var(--borda-forte); border-radius: var(--raio);
}

/* A faixa de progresso da exportação. Ela existe contra o SILÊNCIO: um botão
   escrito «Gerando…» parado por vinte segundos é indistinguível de um botão
   travado. O relógio que anda é a prova mais barata de que algo está vivo. */
.exp-progresso {
  position: fixed; left: 50%; bottom: 26px; transform: translateX(-50%);
  z-index: 300; display: flex; align-items: center; gap: 10px;
  max-width: min(720px, 92vw);
  background: var(--superficie-3); border: 1px solid var(--borda-forte);
  border-radius: 999px; padding: 9px 18px; box-shadow: var(--sombra);
  font-size: 12.5px; color: var(--ink-2);
}
.exp-giro {
  width: 13px; height: 13px; flex: none; border-radius: 50%;
  border: 2px solid color-mix(in srgb, var(--marca) 30%, transparent);
  border-top-color: var(--marca); animation: exp-gira .8s linear infinite;
}
@keyframes exp-gira { to { transform: rotate(360deg); } }
.exp-etapa { color: var(--ink); }
.exp-relogio { font-variant-numeric: tabular-nums; color: var(--marca); flex: none; }
.exp-nota { color: var(--ink-3); font-size: 11.5px; }
@media (prefers-reduced-motion: reduce) { .exp-giro { animation: none; } }

/* «Voltar ao padrão» substituiu o selo «ALTERADO».
   O selo dizia apenas «este valor difere do padrão» e o campo seguia
   editável — mas uma etiqueta em caixa alta colada no rótulo lê como estado
   imposto, e foi lida assim: «de alguma forma o trava ou deixa hardcoded».
   Marca que parece trava é marca errada. Vira ação: diz o que aconteceu, diz
   o que dá para fazer, e ninguém confunde botão com cadeado. */
.prop-voltar {
  margin-left: 8px; cursor: pointer; font-size: 10.5px; line-height: 1;
  color: var(--ink-3); background: none; padding: 2px 7px;
  border: 1px solid var(--borda); border-radius: 999px;
  transition: color .12s, border-color .12s, background .12s;
  vertical-align: 1px; white-space: nowrap;
}
.prop-voltar:hover, .prop-voltar:focus-visible {
  color: var(--ink); border-color: var(--marca);
  background: color-mix(in srgb, var(--marca) 12%, transparent);
}

/* Os selos das tarefas no aviso de saída. Eles existem porque o aviso falava
   no atacado: dizia que TODA tarefa perde o andamento, o que é verdade para a
   extração do Book e falso para o aquecimento — que grava cada combinação
   assim que fica pronta. Assustar com uma perda que não existe deixa a pessoa
   presa entre sair perdendo tudo e esperar sem motivo. */
.tarefa-selo {
  display: inline-block; margin-left: 8px; cursor: help;
  font-size: 10px; font-weight: 700; letter-spacing: .04em;
  text-transform: uppercase; border-radius: 999px; padding: 2px 8px;
}
.tarefa-selo.bom     { color: var(--bom);     background: var(--bom-bg); }
.tarefa-selo.atencao { color: var(--atencao); background: var(--atencao-bg); }
.tarefa-selo.mau     { color: var(--critico); background: var(--critico-bg); }
.tarefa-pendurada { opacity: .72; }

/* «Voltar tudo ao padrão» é ação destrutiva-mas-reversível: apaga escolhas,
   e nada é gravado até Salvar. Por isso não compete com o botão primário —
   fica fraca, à direita, e só ganha peso no hover. */
.btn-fraco {
  color: var(--ink-3); border-color: transparent; background: none;
}
.btn-fraco:hover, .btn-fraco:focus-visible {
  color: var(--ink); border-color: var(--borda-forte);
  background: var(--superficie-2);
}

/* ===========================================================================
   O RANKING — a fila do pior ao melhor (pedido 20)
   ===========================================================================
   Artur: «adicione uma linha que indique o ranking do pior (à esquerda) ao
   melhor à direita... com os top 3 com premiação Ouro/Prata/Bronze
   discretamente mostrado».

   «Discretamente» é a palavra que governa este bloco inteiro. O cartão já
   carrega número grande, farol, seta, frescor, nota e miniatura: mais um
   elemento em voz alta não acrescenta informação, troca hierarquia por ruído.
   Por isso a linha do cartão tem 14px de altura, a medalha é um glifo de
   11px, e a cor forte fica reservada para o que já era forte — o farol.
   =========================================================================== */

/* ------------------------------------------------ a linha dentro do cartão */
/* A FILA ANTIGA DO CARTÃO (trilho com alfinete) FOI REMOVIDA no pedido 31:
   ela dizia a ORDEM e escondia a DISTÂNCIA. O desenho que a substituiu é o
   gráfico de colunas mais abaixo, `.rkc-*`, que é o mesmo do cabeçalho. As
   regras `.rk-pos`, `.rk-trilho`, `.rk-marca` e `.rk-vazio` saíram junto:
   nenhuma delas tinha mais HTML correspondente, e folha com seletor órfão é
   onde a próxima pessoa vai procurar um estilo que não existe. */

/* ------------------------------------------------- a tira no header */
.px-rank { margin: 14px 0 2px; }
.px-rank-cab {
  display: flex; align-items: baseline; gap: 10px; margin-bottom: 5px;
}
.px-rank-rot { cursor: help; margin-bottom: 0; }
.px-rank-ponta { font: 600 10px/1 var(--fonte); color: var(--ink-3); opacity: .8; }
.px-rank-ponta.dir { margin-left: auto; }
.px-rank-tira { display: flex; gap: 2px; align-items: flex-end; }
/* Cada bloco é um indicador. `flex: 1` para a tira ocupar a largura toda
   qualquer que seja o número de classificáveis — 25 hoje, outro número quando
   o escopo crescer. `min-width: 0` para eles poderem encolher de verdade. */
.rk-bloco {
  flex: 1 1 0; min-width: 0; height: 18px; border: none; border-radius: 3px;
  padding: 0; cursor: pointer; background: var(--neutro-bg);
  display: flex; align-items: center; justify-content: center;
  transition: transform .12s ease, box-shadow .12s ease;
}
.rk-bloco:hover, .rk-bloco:focus-visible {
  transform: translateY(-2px); outline: none;
  box-shadow: 0 2px 8px color-mix(in srgb, var(--ink) 18%, transparent);
}
.rk-bloco.farol-critico  { background: color-mix(in srgb, var(--mau) 62%, transparent); }
.rk-bloco.farol-ok       { background: color-mix(in srgb, var(--bom) 55%, transparent); }
.rk-bloco.farol-superado { background: color-mix(in srgb, var(--desafio) 55%, transparent); }
/* O pódio cresce um pouco em vez de mudar de cor: a cor do bloco já é o
   farol, e sobrescrevê-la trocaria uma informação medida (dentro ou fora da
   meta) por uma derivada (está entre os três melhores). */
.rk-bloco.rk-podio { height: 26px; }
.rk-med { font-size: 12px; line-height: 1; }
.px-rank-leg {
  margin: 6px 0 0; font-size: 11px; line-height: 1.5; color: var(--ink-3);
}
.px-rank-sem { margin: 10px 0 0; font-size: 11.5px; color: var(--ink-3); }
/* O «tentar de novo» da espera da fila — pedido 59. Botão de verdade (para
   teclado e leitor de tela) com aparência de link: a ação é secundária e um
   botão sólido aqui pesaria mais que a frase que o acompanha. */
.px-rank-sem .lk {
  background: none; border: 0; padding: 0; cursor: pointer;
  font: inherit; color: var(--marca); text-decoration: underline;
}
.px-rank-sem .lk:hover { color: var(--ink); }

/* Quem chega pela tira precisa achar o cartão: rolar até ele não basta numa
   grade de 37 iguais. Dois pulsos e para — piscar sem fim vira ruído. */
@keyframes r37Pisca {
  0%, 100% { box-shadow: 0 0 0 0 transparent; }
  50% { box-shadow: 0 0 0 3px color-mix(in srgb, var(--marca) 55%, transparent); }
}
.r37-cartao.r37-piscando { animation: r37Pisca .8s ease 2; }

@media (prefers-reduced-motion: reduce) {
  .rk-bloco, .r37-cartao.r37-piscando { transition: none; animation: none; }
}

/* ===========================================================================
   RANKING DAS UNIDADES — colunas no cabeçalho, siglas no cartão
   ===========================================================================
   A primeira versão ranqueava os 37 indicadores entre si e Artur corrigiu:
   o sujeito é a UNIDADE, não o indicador. Este bloco substitui o anterior
   inteiro — a tira de blocos iguais e o alfinete num trilho que ele não
   conseguiu nomear («de que se trata este grau?»).

   COLUNAS, E NÃO BLOCOS DE LARGURA IGUAL. Com onze grupos, onze larguras não
   se comparam de relance; onze alturas sobre a mesma base, sim. É um gráfico
   de colunas, que é a forma que o olho já sabe ler sem legenda.
   =========================================================================== */
.px-rank-tira {
  display: flex; gap: 4px; align-items: flex-end; padding-top: 4px;
}
.rk-col {
  flex: 1 1 0; min-width: 0; border: none; background: none; cursor: pointer;
  display: flex; flex-direction: column; align-items: center; gap: 3px;
  padding: 0 2px 2px; border-radius: 6px;
  transition: background-color .12s ease;
}
.rk-col:hover, .rk-col:focus-visible {
  background: color-mix(in srgb, var(--ink) 6%, transparent); outline: none;
}
/* A PREMIAÇÃO CRESCEU — pedido deste turno: «melhore o tamanho das
   premiações para que fiquem mais destacados tanto no geral quanto nas
   parciais de cada indicador».
   ISTO REVERTE, DE PROPÓSITO, O «DISCRETAMENTE» DO PEDIDO 20, e o registro
   importa porque o raciocínio de lá continua válido — ele só não previu o
   tamanho que sobrou. Na foto, o glifo de 11px ao lado de uma barra de
   30px e de um percentual de 10px não era discreto: era IMPERCEPTÍVEL. A
   diferença entre discreto e invisível é que o discreto se vê quando se
   procura, e para isso o pódio precisa ganhar do percentual que está logo
   abaixo dele, não empatar.
   16px no cabeçalho e 12px na tira do cartão. O `min-height` acompanha,
   senão a linha sem medalha encolhe e a fila fica com os topos
   desalinhados — e topo desalinhado numa fila de comparação é a primeira
   coisa que o olho lê como diferença de valor. */
/* `line-height: 1` servia a um glifo de 11px; a 16px o emoji transborda a
   própria linha e a fita da medalha encostava no percentual logo abaixo —
   medido na foto. Caixa com folga, e o espaço entre as linhas da coluna
   sobe junto. */
.rk-medalha-col { font-size: 20px; line-height: 1.25; min-height: 26px; }
/* ===================================================================
   OS NÚMEROS E OS NOMES DO RANKING, MAIORES — pedido 104
   ===================================================================
   «Preciso dos números maiores nos rankings do header e de cada
   indicador, bem como da identificação de cada regional, bem como seus
   números a/a, tri, cv, meta.»

   Era a mesma espécie de defeito das premiações (pedido 100): o desenho
   foi dimensionado para caber, não para ser lido. Num ranking de onze
   grupos projetado numa sala, 10px de percentual e 9,5px de nome são
   decorativos — quem está a dois metros vê barras coloridas e não sabe
   de quem são.

   Subiu o que se LÊ e não o que se desenha: as barras continuam com a
   mesma altura e a fila com a mesma largura. O que cresceu foi a
   tipografia, e o espaço veio da folga que já existia entre as colunas. */
.rk-pct {
  font: 800 13.5px/1 var(--fonte-num); color: var(--ink);
  font-variant-numeric: tabular-nums lining-nums;
  letter-spacing: -.01em;
}
/* A barra é a MESMA cor para todas: a posição no eixo já diz quem é pior, e
   pintar por faixa acrescentaria um segundo juízo sobre o mesmo número. */
.rk-barra {
  width: 100%; border-radius: 3px 3px 0 0; align-self: stretch;
  /* a cor vem do JS, pela posição — ver `corDaFila` */
}
.rk-col.rk-podio { outline: 1px solid color-mix(in srgb, var(--ink) 22%, transparent); }
/* A REGIÃO ESCOLHIDA NO RANKING — pedido 109. Contorno cheio e mais forte
   que o do pódio: as duas marcas podem coincidir (a dele pode estar no
   pódio) e aí a mais forte vence, que é a leitura certa — primeiro «qual é
   a minha», depois «como ela se saiu». */
.rk-col.rk-eu {
  outline: 2px solid var(--ink);
  outline-offset: 1px;
  border-radius: 4px;
}
.rk-col.rk-eu .rk-nome { font-weight: 800; }
.rk-nome {
  font: 700 12px/1.2 var(--fonte); color: var(--ink-2);
  text-align: center; overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; max-width: 100%;
}
/* Empate DECLARADO: hachura leve. Duas unidades com o mesmo resultado ocupam
   posições diferentes porque a fila é uma linha — a marca existe para a tela
   não afirmar uma ordem que ela não mediu. */
.rk-col.rk-empate .rk-barra {
  background-image: repeating-linear-gradient(135deg,
    transparent 0 4px, rgba(255, 255, 255, .28) 4px 6px);
}
.px-rank-falta {
  margin: 6px 0 0; font-size: 11px; line-height: 1.5; color: var(--aviso, var(--mau));
}
/* O RODAPÉ DA FILA — pedido 37.3. Duas pílulas no lugar de dois parágrafos. */
.px-rank-pe { display: flex; gap: 10px; flex-wrap: wrap; margin-top: 9px; }
/* A pílula da lacuna NÃO é discreta: ela avisa que a fila está incompleta, e
   um aviso que se confunde com uma legenda não avisa. Borda sólida na cor do
   alerta, número em destaque. */
.px-pill-falta {
  color: var(--critico); border-style: solid;
  border-color: color-mix(in srgb, var(--critico) 45%, transparent);
  background: var(--critico-bg); text-transform: none; letter-spacing: 0;
  font-size: 11px;
}
.px-pill-falta b {
  font-weight: 700; font-variant-numeric: tabular-nums; margin-right: 3px;
}
.px-pill-falta:hover { color: var(--critico); border-color: var(--critico); }

/* A PÍLULA DO ALCANCE — âmbar, e a cor é o argumento. «Sem rastro» não é
   defeito do indicador: é limite do que se pôde medir, a mesma distinção que
   SEM INSUMO faz nas réguas. Em vermelho ela seria lida como 38 problemas; em
   cinza, como legenda. Âmbar é o único tom que diz «repare nisto, e não é
   alarme». */
.px-pill-aten {
  color: var(--atencao); border-style: solid;
  border-color: color-mix(in srgb, var(--atencao) 45%, transparent);
  background: var(--atencao-bg); text-transform: none; letter-spacing: 0;
  font-size: 11px;
}
.px-pill-aten:hover { color: var(--atencao); border-color: var(--atencao); }

/* ------------------------------------------- a fila dentro do cartão
   PEDIDO 31: «acho que o do header ficou ótimo... seria bom aplicar este
   layout a cada indicador também, ajustando-se ao curto espaço disponível,
   porque traz melhor legibilidade».

   Eram pílulas coloridas com a sigla dentro — uma fila que dizia a ORDEM e
   escondia a DISTÂNCIA: três unidades quase empatadas e três desastradas
   tinham exatamente o mesmo desenho. Agora é o mesmo gráfico de colunas do
   cabeçalho, reduzido: medalha em cima, coluna colorida pela posição, sigla
   embaixo.

   O QUE MUDA EM RELAÇÃO AO CABEÇALHO, e por quê: a linha do zero fica no
   MEIO, porque a régua do cartão tem sinal (distância da meta) enquanto a do
   cabeçalho não tem (percentual dentro da meta). Ver `linhaRanking`.

   O AJUSTE AO ESPAÇO CURTO é por `flex: 1 1 0` e `min-width: 0`: com onze
   grupos num cartão de três por linha cada coluna fica com ~30px, e com
   cinco por linha, ~17px. A sigla corta com reticências antes de empurrar a
   fila para fora — coluna estreita ainda mede; fila que estoura, não. */
.r37-rank {
  display: flex; align-items: center; gap: 4px; flex-wrap: nowrap;
  margin: 7px 12px 0; cursor: help; overflow: hidden;
}
.rkc-rot {
  font: 600 10px/1 var(--fonte); color: var(--ink-3); opacity: .75;
  flex: none; text-transform: lowercase;
}
.rkc-tira { display: flex; align-items: stretch; gap: 2px;
  flex: 1 1 auto; min-width: 0; }
.rkc-col {
  flex: 1 1 0; min-width: 0; display: flex; flex-direction: column;
  align-items: center; gap: 1px;
  background: none; border: 0; padding: 0; cursor: pointer;
  border-radius: 4px;
}
.rkc-col:hover { background: var(--superficie-3); }
.rkc-col:focus-visible { outline: 2px solid var(--marca); outline-offset: 1px; }
.rkc-medalha { font-size: 15px; line-height: 1.25; height: 19px; }
/* A caixa da coluna: 30px de altura com a linha da meta exatamente no meio.
   A linha é um `::before` de 1px e não uma borda da caixa, porque borda
   ficaria nas pontas — e o que precisa ser visto é o MEIO. */
.rkc-graf {
  position: relative; width: 100%; height: 30px;
  display: flex; flex-direction: column; justify-content: center;
}
.rkc-graf::before {
  content: ''; position: absolute; left: 0; right: 0; top: 50%;
  height: 1px; background: var(--borda-forte); opacity: .7;
}
/* A barra nasce na linha do meio e cresce para cima ou para baixo. `position:
   absolute` com `top: 50%` / `bottom: 50%` em vez de flex: assim a altura
   escrita pelo JS é a distância REAL a partir da meta, e não uma fatia de um
   espaço repartido. */
.rkc-barra {
  position: absolute; left: 12%; right: 12%; border-radius: 2px; z-index: 1;
}
.rkc-barra.sobe { bottom: 50%; }
.rkc-barra.desce { top: 50%; }
.rkc-nome {
  /* A tira do cartão é a MESMA fila, em miniatura: ela sobe junto, na
     mesma proporção, senão o painel passa a ter dois rankings com duas
     leituras diferentes. */
  font: 700 10.5px/1 var(--fonte); color: var(--ink-2);
  letter-spacing: .02em;
  max-width: 100%; overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap;
}
/* O pódio se marca por FORMA — contorno e medalha —, nunca por cor: mexer na
   cor quebraria a rampa vermelho→verde justamente na ponta onde ela precisa
   ser lida. Forma também sobrevive ao preto e branco. */
.rkc-col.podio .rkc-nome { color: var(--ink); font-weight: 800; }
.rkc-col.podio .rkc-barra { outline: 1px solid var(--ink-2); }
/* Empate DECLARADO: a mesma hachura do cabeçalho. Duas unidades com o mesmo
   resultado ocupam posições diferentes porque a fila é uma linha — a marca
   existe para a tela não afirmar uma ordem que ela não mediu. */
.rkc-col.empate .rkc-barra {
  background-image: repeating-linear-gradient(135deg,
    transparent 0 3px, rgba(255, 255, 255, .28) 3px 5px);
}

/* ===========================================================================
   O ANALÍTICO — pedido 29
   ===========================================================================
   Três lugares, um vocabulário de cor só: verde = dentro/melhorando, vermelho
   = fora/piorando, e os quatro quadrantes com o MESMO par nas mesmas posições
   na linha do cartão, no chip do cabeçalho e no fundo do gráfico de bolhas.
   Um verbo que muda de cor entre duas partes da tela é um verbo que ninguém
   aprende.
   =========================================================================== */

/* ---- a linha no cartão (ver `linhaAnalitica`) --------------------------- */
.r37-analitico {
  display: flex; align-items: center; gap: 4px; flex-wrap: wrap;
  margin: 7px 12px 0; cursor: help;
}
.an-chip {
  display: inline-flex; align-items: baseline; gap: 3px;
  font: 700 9.5px/1 var(--fonte); font-variant-numeric: tabular-nums;
  color: var(--ink-2); background: var(--superficie-3);
  border: 1px solid var(--borda); border-radius: 5px; padding: 3px 5px;
  white-space: nowrap;
}
/* O rótulo do chip (a/a, tri, cv, meta) é minúsculo e apagado de propósito:
   ele nomeia, o número é que se lê. */
.an-chip i {
  font-style: normal; font-weight: 600; font-size: 8px; opacity: .62;
  text-transform: uppercase; letter-spacing: .05em;
}
/* A cor vem de MELHOROU, nunca do sinal: num indicador em que menos é melhor,
   +4% é vermelho. Mesma separação da seta do rodapé. */
.an-chip.an-bom { color: var(--bom);
  border-color: color-mix(in srgb, var(--bom) 40%, transparent);
  background: var(--bom-bg); }
.an-chip.an-mau { color: var(--critico);
  border-color: color-mix(in srgb, var(--critico) 40%, transparent);
  background: var(--critico-bg); }
/* O quadrante é a conclusão: vai para a direita da linha, separado. */
.an-quad {
  margin-left: auto; font: 800 8.5px/1 var(--fonte); text-transform: uppercase;
  letter-spacing: .07em; padding: 3px 7px; border-radius: 999px;
  border: 1px solid currentColor; cursor: help;
}
.an-q-agir       { color: var(--critico); }
.an-q-vigiar     { color: var(--atencao); }
.an-q-acompanhar { color: var(--superado, var(--info, #4d8fd6)); }
.an-q-manter     { color: var(--bom); }

/* ---- o apanhado no cabeçalho (ver `resumoAnalitico`) -------------------- */
.px-analitico {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  border-top: 1px solid var(--borda); padding-top: 10px; margin-top: 2px;
}
.px-analitico .px-rot { margin-bottom: 0; flex: none; }
.px-an-chip {
  display: inline-flex; align-items: baseline; gap: 5px; cursor: pointer;
  font: 600 11px/1 var(--fonte); padding: 6px 11px; border-radius: 999px;
  background: var(--superficie-3); border: 1px solid currentColor;
}
.px-an-chip b { font: 800 14px/1 var(--fonte); font-variant-numeric: tabular-nums; }
.px-an-chip:hover { background: var(--superficie-2); }
.px-an-chip:focus-visible { outline: 2px solid var(--marca); outline-offset: 2px; }
.px-an-sem {
  font: 600 11.5px/1.2 var(--fonte); color: var(--ink-3); cursor: help;
  padding: 5px 10px; border-radius: 999px; border: 1px dashed var(--borda-forte);
}
.px-an-sem b { color: var(--ink-2); font-weight: 800; }
/* O «fora da meta sem rumo medido» é PAUTA, e por isso veste a cor do fora
   — contorno tracejado porque o rumo é que falta, não o problema. No mesmo
   cinza do «dentro sem rumo», ele desaparecia da conversa. */
.px-an-sem-fora {
  border-color: color-mix(in srgb, var(--critico) 55%, transparent);
  color: color-mix(in srgb, var(--critico) 78%, var(--ink-2));
}
.px-an-sem-fora b { color: var(--critico); }
/* A reconciliação até o escopo inteiro: discreta, numa linha, para ser
   conferida e não para ser lida toda vez. */
.px-an-conf {
  flex-basis: 100%; margin-top: 7px; cursor: help;
  font: 400 11.5px/1.5 var(--fonte); color: var(--ink-3);
  font-variant-numeric: tabular-nums;
}
.px-an-conf b { color: var(--ink-2); font-weight: 700; }

/* ---- o painel 360 (ver `painelAnalitico`) ------------------------------- */
.an-painel {
  background: var(--superficie); border: 1px solid var(--borda);
  border-radius: 13px; padding: 15px 18px 14px; margin: 16px 0 14px;
  display: flex; flex-direction: column; gap: 12px;
}
.an-cab { display: flex; align-items: baseline; gap: 10px; }
.an-cab h4 { margin: 0; font-size: 14px; letter-spacing: -.01em; }
.an-cab-dica {
  font: 600 10px/1 var(--fonte); color: var(--ink-3); cursor: help;
  text-transform: uppercase; letter-spacing: .07em;
  border-bottom: 1px dotted var(--borda-forte); margin-left: auto;
}
.an-caixas { display: flex; gap: 10px; flex-wrap: wrap; }
/* Cada caixa é um verbo, e o número é maior que a palavra porque a pergunta
   é «quantos», não «quais» — os quais estão no balão. */
/* DUAS CONTAGENS NA MESMA CAIXA — pedido 82. O verbo em cima, nomeando o
   quadrante; embaixo, os dois números com o sujeito ao lado de cada um.
   O número dos GRUPOS é menor e mais fraco de propósito: são onze contra
   vinte e três, e dar o mesmo peso tipográfico a populações de tamanhos
   tão diferentes convida de novo à soma que não existe. */
.an-caixa {
  flex: 1 1 150px; min-width: 128px; cursor: help;
  border: 1px solid currentColor; border-radius: 10px; padding: 9px 12px;
  display: flex; flex-direction: column; gap: 6px;
  background: color-mix(in srgb, currentColor 7%, transparent);
}
.an-caixa-contas { display: flex; align-items: baseline; gap: 14px; }
.an-caixa-par { display: flex; align-items: baseline; gap: 5px; }
.an-caixa-par i {
  font: 600 10px/1 var(--fonte); font-style: normal;
  color: var(--ink-3); letter-spacing: .02em;
}
.an-caixa b { font: 800 24px/1 var(--fonte); font-variant-numeric: tabular-nums; }
.an-caixa-grp b { font-size: 15px; opacity: .78; }
.an-caixa-rot {
  font: 700 10px/1 var(--fonte); text-transform: uppercase;
  letter-spacing: .07em; color: var(--ink-2);
}
.an-q-sem { color: var(--ink-3); }
/* A conferência escrita: ela existe para ser somada pelo leitor, então
   fica discreta e legível, numa linha só. */
.an-caixas-conf {
  margin: 8px 0 0; font-size: 12px; line-height: 1.5; color: var(--ink-3);
}
.an-caixas-conf b { color: var(--ink-2); font-weight: 700; }

/* AS DUAS METADES — pedido 36. `1fr 1fr` e não `auto`: os dois planos têm de
   ter EXATAMENTE a mesma largura, porque é a igualdade dos eixos que autoriza
   comparar um com o outro de relance. Meio pixel de diferença entre as
   escalas já tornaria a comparação uma ilusão. */
.an-dupla { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; }
@media (max-width: 1100px) { .an-dupla { grid-template-columns: 1fr; } }
.an-meia { min-width: 0; display: flex; flex-direction: column; gap: 6px; }
.an-meia-cab { display: flex; align-items: baseline; gap: 8px; }
.an-meia-cab h5 {
  margin: 0; font: 700 11.5px/1 var(--fonte); color: var(--ink);
  text-transform: uppercase; letter-spacing: .06em;
}
.an-meia-sub {
  font: 600 10.5px/1 var(--fonte); color: var(--ink-3); cursor: help;
  margin-left: auto; border-bottom: 1px dotted var(--borda-forte);
}
.an-omitidos { margin: 0; font-size: 10.5px; color: var(--ink-3); }

.an-bolha { width: 100%; }
.an-bolha-svg { display: block; width: 100%; height: auto; }
/* O VERBO NO CANTO DO QUADRANTE — pedido 36. Na cor do próprio quadrante,
   com opacidade baixa: ele é uma etiqueta de REGIÃO, não um dado, e tem de
   perder para qualquer bolha que caia por cima dele. */
.an-q-nome {
  font: 700 9px/1 var(--fonte); text-transform: uppercase;
  letter-spacing: .08em; opacity: .55;
  /* APONTÁVEL — pedido 97: cada verbo explica a própria composição no
     balão. O cursor de ajuda avisa que há explicação ali antes de a
     pessoa descobrir por acaso; sem ele, o balão existe para quem já
     sabia que existia. */
  cursor: help;
}
/* A TRAJETÓRIA — pedido 79. Contínuo é medido, tracejado é projetado, e a
   diferença tem de ser visível SEM legenda: quem vê um traço cheio e um
   pontilhado no mesmo desenho já sabe qual dos dois é aposta.
   Os dois ficam abaixo das bolhas na ordem de desenho, e mais fracos que
   elas: a posição de hoje continua sendo o assunto; o caminho é contexto. */
/* A bolha é clicável — pedido 89. O cursor diz isso antes do clique, que
   é o mínimo que um alvo interativo deve a quem passa por cima dele. */
/* A BOLHA MAIS VIVA, COM CONTORNO — pedido deste turno: «precisamos
   vivificar um pouco mais, e esta estilização conforme o contorno».
   No draft dele a bolha é CHEIA e tem um contorno escuro e firme; a minha
   era um véu de 42% com um fio de 1,6px, e véu sobre fundo escuro vira
   mancha: de longe não se sabe se é vermelha ou marrom. Subiu para 62% com
   contorno de 2,2px, e no solo vai a 88% — ali é uma só, não há nada atrás
   dela para esconder, e o assunto é justamente ela.
   Não vai a 100% no panorama porque lá são 25 e elas se cruzam: opaca, a
   de cima apaga a de baixo, e apagar um indicador do painel dos 37 é pior
   que um tom menos vivo. */
/* O CONTORNO NÃO PODE SOMAR ATÉ VIRAR UMA MANCHA PRETA — pedido 138.
   Artur: «me parece que os bubbles estão deixando de ser atualizados pois a
   maioria está cinza, tem uns até em preto... acho que não estão corretos!».

   O PRETO NÃO ERA DADO ERRADO, ERA TINTA SOMADA. O miolo da bolha é
   translúcido (`fill-opacity: .62`), mas o CONTORNO era opaco e quase preto
   (`--contorno-bolha`, #0a0c12). Onde quatro ou cinco bolhas se encavalam — e
   no plano por grupo elas se encavalam muito, porque os grupos têm distâncias
   da meta parecidas — os anéis se cruzam e as áreas pequenas entre eles
   recebem traço sobre traço sobre traço. Opaco somado com opaco dá opaco: a
   região vira um borrão preto, e um borrão preto no meio de um plano colorido
   lê-se como «esta bolha está errada».

   O CONTORNO CONTINUA EXISTINDO E CONTINUA ESCURO, porque a razão dele não
   mudou (pedido 91: bolha vermelha dentro do quadrante vermelho precisa de
   borda de outra família para não virar mancha). O que muda é que ele passa a
   ser TRANSLÚCIDO como o miolo: duas bordas sobrepostas escurecem um pouco, e
   cinco escurecem um pouco mais, em vez de todas chegarem ao preto já na
   segunda. A forma de cada bolha continua legível — é o que o pedido 91
   pediu — e o amontoado volta a parecer um amontoado de bolhas.

   NO HOVER ELE FICA MAIS FIRME, de propósito: aí há UMA bolha em foco e
   nenhuma soma acontece, então o contorno pode cumprir o papel inteiro. */
/* O CONTORNO TOMA A COR DO PLANO, e isso é o que impede a soma.
   Translucidez não resolvia: seis anéis a 50% compõem 98% de opacidade, e a
   régua mediu — luminância 0,027 no cruzamento, que é preto. O problema não
   é a FORÇA do traço, é ele ser uma TERCEIRA cor que se acumula.
   Tomando a superfície, o anel vira um RECORTE: dois recortes sobrepostos
   são o mesmo recorte, e seis também. A composição passa a ser idempotente —
   empilhar não cria cor nenhuma que já não estivesse na tela.
   É o mesmo gesto do halo do ponteiro do medidor grande, e pela mesma razão
   escrita lá: no tema claro um halo escuro seria sombra, no escuro um halo
   claro seria brilho; tomando o fundo, ele é sempre a mesma coisa.
   E A RAZÃO DO PEDIDO 91 CONTINUA ATENDIDA: a bolha vermelha dentro do
   quadrante vermelho continua tendo borda de OUTRA família — a do plano, que
   nunca é a cor do farol. Ela não precisa ser escura; precisa ser outra. */
/* ===== A BOLHA É OPACA — pedido 151 ==============================
   Artur: «não seria apenas verde, vermelho e cinza aos sem dados? mas entra
   marrom, às vezes preto... está muito ruim».

   ELE ESTÁ DESCREVENDO UMA MISTURA, E A CONTA FECHA. A bolha era desenhada a
   62% de opacidade (55% no cinza) POR CIMA do fundo tingido do quadrante.
   Cinza a 55% sobre o âmbar do VIGIAR dá MARROM. Vermelho a 62% sobre o
   vermelho do AGIR dá um vinho quase preto. Nenhuma das duas cores existe na
   paleta; as duas nascem da soma.

   E É O PEDIDO 138 OUTRA VEZ, no outro canal. Lá o preto vinha do CONTORNO
   somado; aqui vem do PREENCHIMENTO somado. A lição é a mesma: translucidez
   não é um ajuste de intensidade, é uma TERCEIRA cor que ninguém escolheu.

   POR QUE A OPACIDADE ESTAVA LÁ: para bolhas sobrepostas não se taparem. Mas
   esse problema já tem outra solução neste mesmo arquivo, e melhor — o
   contorno da cor da SUPERFÍCIE, que é recorte e não tinta (a correção do
   138). Com ele, bolhas opacas continuam se distinguindo quando encostam, e
   sem inventar cor.

   O HOVER DEIXA DE MEXER NA OPACIDADE pela mesma razão: ele clareava a bolha
   e, com isso, a misturava com o fundo justo no instante em que a pessoa
   está olhando para ela. Agora ele engrossa o contorno, que é um canal livre.
   ================================================================= */
.an-bolha-p {
  cursor: pointer; fill-opacity: 1;
  stroke: var(--superficie); stroke-width: 2.2;
}
.an-bolha-p:hover { stroke-width: 3.6; }
/* APARADA NA BORDA — pedido 95. No modo «para onde vai», uma projeção que
   passa do teto da escala é desenhada na borda; sem marca, a borda seria
   lida como o valor. Contorno tracejado é a convenção de «não acaba
   aqui», a mesma das pontas abertas do colchete. */
.an-bolha-alem { stroke-dasharray: 4 3; }
/* SEM RUMO MEDIDO — pedidos 108 e 114.
   O risco inclinado saiu (ver o comentário no `radar37.js`): ele ia 73% para
   fora do círculo dos dois lados e, no modo «o percurso», virava mais uma
   linha inclinada no meio de quatro.
   Ficou o CINZA, que é o que ele pediu e é melhor: diz a mesma coisa sem
   acrescentar tinta nenhuma ao plano. A opacidade continua um pouco menor
   que a das outras para o cinza não competir com as bolhas que têm juízo —
   mas não tão baixa que a bolha deixe de ser clicável à vista. */
/* O CINZA TAMBÉM FICOU OPACO — pedido 151. Ele era o maior produtor de
   marrom: é a cor mais frequente no plano (sem rumo medido domina o plano
   por grupo) e a que mais cai sobre o âmbar. «Não competir com as bolhas que
   têm juízo» continua valendo — e quem faz isso é o CINZA ser cinza, não ele
   ser transparente. */
.an-bolha-sr { fill-opacity: 1; }
.an-meia-solo .an-bolha-p { stroke-width: 2.6; }
/* O LOSANGO DO INÍCIO — ele desenhou um losango cheio onde a rota começa,
   e losango é melhor que o anel que eu usava: a rota já tem um ponto
   REDONDO no presente, e dois círculos de tamanhos parecidos nas duas
   pontas obrigam a conferir qual é qual. Formas diferentes, nenhuma
   conferência. */
.an-traj-po-d { opacity: .95; }
/* ===================================================================
   A ROTA É UMA SÓ FITA — pedido deste turno
   ===================================================================
   «O fato de termos largura das linhas distinto leva à falsa percepção de
   que não se trata do mesmo percurso... normalizar a largura da linha e
   manter a ideia de verde/vermelho entre favorável/desfavorável e
   harmonize o contorno para trazer melhor didática.»

   Ele mandou junto um desenho à mão: UMA fita, de ponta a ponta, mesma
   espessura, zigue-zagueando, losango no começo e seta no fim. É a leitura
   certa — e eu tinha quebrado a fita em três lugares de uma vez:

     espessura   3,2px no medido  ·  1,7px na projeção
     opacidade   0,85             ·  0,78 (e 0,34 quando a reta era fraca)
     pontas      round            ·  butt

   Nenhuma das três diferenças significava nada. Espessura, num desenho,
   quer dizer IMPORTÂNCIA; opacidade quer dizer CERTEZA; e eu usei as duas
   para dizer «isto é futuro», que é coisa que o tracejado já diz sozinho —
   e diz melhor, porque é a convenção que todo mundo conhece. O resultado é
   o que ele viu: duas linhas que não parecem o mesmo caminho.

   Agora a rota inteira tem UMA largura (`--traj-w`), UMA opacidade e as
   MESMAS pontas. O que varia é só o que carrega informação:
     · a COR  — verde andou para a meta, vermelho se afastou, cinza parado,
                índigo é projeção (não julga: ainda não aconteceu);
     · o TRAÇO — cheio é medido, tracejado é suposto;
     · o PASSO do tracejado — traço longo quando a reta descreve a série,
                pontinho curto quando ela descreve pouco. */
.an-traj-de  { stroke-width: var(--traj-w); opacity: .9;
               stroke-linecap: round; stroke-linejoin: round; }
.an-traj-seg {
  stroke-width: var(--traj-w); opacity: .9; stroke-linecap: round;
  /* CHEIO É MEDIDO, DECLARADO: o passado nunca teve tracejado, mas também
     não tinha `none` escrito, e a afirmação central do desenho não fica
     dependendo de nenhuma regra ter sido escrita em outro lugar. */
  stroke-dasharray: none; stroke-linejoin: round;
}
/* O PONTO DO PRESENTE — «pode deixar um ponto no presente». Ele é a junta
   entre o cheio e o tracejado, e por isso ganha anel da cor da superfície:
   sobre a bolha translúcida da mesma cor, um ponto sem anel some; com
   anel, ele se lê como marca e não como mancha. O anel tem a largura da
   rota, para a junta pertencer à fita em vez de pousar sobre ela. */
.an-traj-agora {
  /* O CONTORNO DOS MARCADORES É DERIVADO DA LARGURA DA ROTA, não um número
     solto: «harmonize o contorno». 0,6 da fita é grosso o bastante para o
     anel separar e fino o bastante para o miolo continuar sendo o ponto —
     e se a fita engrossar um dia, os marcadores engrossam junto, em vez de
     a proporção se perder sem ninguém notar. */
  stroke: var(--superficie); stroke-width: calc(var(--traj-w) * .6);
  opacity: 1;
}
.an-traj-bom   { stroke: var(--bom); }
.an-traj-mau   { stroke: var(--critico); }
/* Mês que não saiu do lugar continua com a MESMA espessura: ele não é
   menos caminho que os outros, é caminho que não andou. */
.an-traj-igual { stroke: var(--ink-3); }
/* O ponto VAZADO do início — «aqui estava». Contorno da largura da rota,
   pelo mesmo motivo da junta. */
.an-traj-po  { stroke-width: calc(var(--traj-w) * .6); opacity: .9; }
.an-traj-ate { stroke-width: var(--traj-w); opacity: .9;
               stroke-linecap: round; stroke-dasharray: 7 6; }
.an-traj-seta { opacity: .9; }
/* A projeção de quem NÃO tem tendência clara continua sendo desenhada —
   sumir com ela esconderia justamente que aquele indicador é imprevisível.
   O que muda é o PASSO do tracejado, não a espessura nem a opacidade:
   pontinho curto lê-se como «hesitante» sem deixar de ser a mesma fita, e
   quem diz o tamanho da dúvida com número é o colchete. */
.an-traj-duvida { stroke-dasharray: 2.5 5.5; }

/* A AULA DE UMA BOLHA SÓ — pedido 85.
   A legenda vira porta de entrada: cada linha é um botão, e o que está em
   aula fica marcado. Sem a marca, quem clicou não sabe de quem é o desenho
   que apareceu. */
.an-leg-b {
  appearance: none; border: 0; background: none; padding: 1px 5px;
  margin: -1px -5px; border-radius: 6px; cursor: pointer;
  font: inherit; color: inherit; text-align: left; width: 100%;
  display: flex; align-items: baseline; gap: 7px;
}
.an-leg-b:hover { background: var(--superficie-3); }
/* A MARCA DE CHECADO — pedido 93. Discreta de propósito: ela diz «já
   passei aqui», não «este é importante». Quem decide o que é importante é
   a cor do número, que já está ali ao lado e não pode ser disputada por
   uma marca de progresso. */
.an-leg-ok {
  margin-left: auto; font-style: normal; font-size: 11px;
  color: var(--bom); opacity: .8; flex: none;
}
.an-leg-b.visto span { color: var(--ink-3); }
.an-chk {
  margin: 8px 0 0; font-size: 11.5px; color: var(--ink-3);
  display: flex; align-items: baseline; gap: 8px;
}
.an-chk b { color: var(--ink-2); }
.an-chk-lim { margin-left: auto; font-size: 11.5px; }
.an-leg-b.on {
  background: color-mix(in srgb, var(--marca) 13%, transparent);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--marca) 38%,
                                        transparent);
}
.an-leg-b.on span { color: var(--ink); font-weight: 600; }
.an-solo {
  margin: 10px 0 2px; padding: 12px 14px; border-radius: 10px;
  background: var(--superficie-2); border: 1px solid var(--borda);
}
.an-solo-cab {
  display: flex; align-items: baseline; gap: 12px; margin-bottom: 10px;
}
.an-solo-cab h6 {
  margin: 0; font: 800 14px/1.2 var(--fonte); color: var(--ink);
  flex: 1 1 auto; min-width: 0;
}
.an-solo-sair { flex: none; font-size: 12px; }
/* OS TRÊS MOMENTOS, LADO A LADO E NA ORDEM DO TEMPO: passado, hoje,
   projeção. Em coluna eles seriam três parágrafos; em linha, o olho lê o
   movimento da esquerda para a direita — que é exatamente o movimento que
   a animação acabou de desenhar no plano, na mesma direção. */
.an-solo-lista {
  list-style: none; margin: 0; padding: 0;
  display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: 10px;
}
.an-solo-m {
  padding: 9px 11px; border-radius: 8px; border: 1px solid transparent;
  background: var(--superficie-3); transition: border-color .3s ease,
    background .3s ease, transform .3s ease;
}
/* ===================================================================
   A COR CONTA A HISTÓRIA — pedido 102
   ===================================================================
   «Digo entender como tem sido e como será caso nada seja realizado...
   lembre que cores orientam muito sobre interpretabilidade e
   intuitividade.»

   Os três cartões eram cinzentos e diziam a história em palavras. Lidos
   de relance pareciam três números do mesmo tipo. Pintados, eles viram
   uma SEQUÊNCIA que se lê sem ler: vermelho → verde → vermelho é «estava
   fora, entrou, volta a sair», e isso chega ao olho antes da frase.

   DUAS CODIFICAÇÕES, PORQUE SÃO DUAS PERGUNTAS:
     · o CARTÃO diz onde está — atinge a meta ou não (barra à esquerda e
       número coloridos);
     · o MOVIMENTO dentro dele diz para onde foi — andou para a meta ou
       se afastou.
   Um indicador pode estar DENTRO da meta e piorando (o quadrante
   «vigiar»); pintar as duas coisas com a mesma regra apagaria justamente
   esse caso, que é o que a reunião precisa pegar antes de virar «agir».

   A barra fica à ESQUERDA e não no fundo inteiro: três cartões com fundo
   cheio lado a lado competem com o plano logo acima, que é onde a cor
   tem de mandar. Barra basta para o olho agrupar. */
.an-solo-m-dentro { box-shadow: inset 3px 0 0 var(--bom); }
.an-solo-m-fora   { box-shadow: inset 3px 0 0 var(--critico); }
.an-solo-m-dentro .an-solo-v b { color: var(--bom); }
.an-solo-m-fora   .an-solo-v b { color: var(--critico); }
.an-solo-mv-bom   { color: var(--bom); font-weight: 700; }
.an-solo-mv-mau   { color: var(--critico); font-weight: 700; }
.an-solo-mv-igual { color: var(--ink-2); font-weight: 700; }
/* O momento em foco acende com a marca. É o único elo entre a frase e o
   desenho: sem ele, a animação acontece de um lado e o texto do outro, e
   a pessoa tem de adivinhar qual frase descreve o que está vendo. */
.an-solo-m.on {
  border-color: color-mix(in srgb, var(--marca) 48%, transparent);
  background: color-mix(in srgb, var(--marca) 9%, var(--superficie-3));
  transform: translateY(-1px);
}
.an-solo-q {
  font: 700 10.5px/1.2 var(--fonte-rot); text-transform: uppercase;
  letter-spacing: .08em; color: var(--ink-3);
}
/* O NÚMERO GRANDE E A UNIDADE PEQUENA, na mesma linha. Com «da meta» no
   mesmo corpo do número, a frase quebrava em duas linhas e o valor — que é
   o que se compara entre os três momentos — perdia o alinhamento vertical
   com os vizinhos. */
.an-solo-v {
  margin-top: 4px; display: flex; align-items: baseline; gap: 6px;
  flex-wrap: wrap;
}
.an-solo-v b {
  font: 800 21px/1.1 var(--fonte-num); color: var(--ink);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
.an-solo-v i {
  font: 600 11px/1 var(--fonte); font-style: normal; color: var(--ink-3);
}
.an-solo-d { margin-top: 4px; font-size: 11.5px; line-height: 1.4;
  color: var(--ink-2); }
.an-solo-e { margin-top: 5px; font-size: 11px; line-height: 1.4;
  color: var(--ink-3); }
/* O VEREDITO VEM ANTES DA MEMÓRIA DE CÁLCULO — pedido 102. A frase que
   responde «por que a seta aponta para o outro lado» tem de ganhar dos
   cinco números que a justificam: eles existem para quem duvidar dela,
   não para quem está lendo pela primeira vez. */
.an-solo-vd {
  display: block; font-weight: 700; color: var(--ink-2);
  line-height: 1.45; margin-bottom: 6px;
}
/* Quando o veredito é «cuidado», ele ganha a cor de atenção e uma barra à
   esquerda: ler o número sem ler esta frase leva à conclusão errada, e
   essa é a única situação em que vale interromper o olho. */
.an-solo-vd-alerta {
  color: var(--ink); border-left: 3px solid var(--atencao);
  padding-left: 8px; margin-left: -1px;
}
.an-solo-mem { display: block; opacity: .82; }
/* O ponteiro de NÍVEL — pedido 102. Ele responde «preciso mudar o
   seletor?» antes de a pessoa procurar, e por isso ganha uma marca: é
   instrução, não leitura do dado. */
.an-solo-nivel {
  border-left: 3px solid var(--marca); padding-left: 9px;
  margin-top: 10px; color: var(--ink-2);
}
.an-solo-pe { margin: 10px 0 0; font-size: 12px; line-height: 1.5;
  color: var(--ink-3); }
.an-solo-pe b { color: var(--ink-2); }
/* A CHAVE DESENHADA — «deixe claro o que é projeção e o que é série
   histórica estilizada em curvas suavizadas». Cada item mostra a marca
   real ao lado do nome, com as MESMAS classes do plano: legenda que se
   mantém à mão é legenda que um dia mente. */
.an-chave {
  list-style: none; margin: 12px 0 0; padding: 10px 0 0;
  border-top: 1px solid var(--borda);
  display: flex; flex-wrap: wrap; gap: 6px 18px;
}
.an-chave-i {
  display: flex; align-items: center; gap: 7px; cursor: help;
  font: 600 11.5px/1 var(--fonte); color: var(--ink-2);
}
.an-chave-m { width: 44px; height: 14px; flex: none; display: block;
  color: var(--ink-2); overflow: visible; }
/* A miniatura de «hoje» é um ponto cheio da cor do texto com o anel da
   superfície — a mesma construção do plano, sem depender de um indicador
   estar selecionado para ter cor. */
.an-chave-m .an-traj-agora { color: var(--ink-2); }
/* Em aula, o plano ganha um fundo levemente destacado: é o «limpa a visão»
   do pedido virando sinal — a metade que está explicando se distingue da
   que continua panorâmica. */
.an-meia-solo .an-bolha {
  background: color-mix(in srgb, var(--marca) 4%, transparent);
  border-radius: 10px;
}
/* A FAIXA DO INTERVALO DE 95%. Fraca de propósito: ela é o contexto da
   seta, não um segundo dado. Quando ela fica mais larga que o movimento
   que a seta desenha, isso se lê sem legenda nenhuma — é o desenho dizendo
   «não dá para afirmar a direção». */
/* O colchete do intervalo — pedido 87.1. Fio fino e opacidade média: ele
   precisa ser LIDO (é a incerteza da projeção) sem competir com o traço do
   caminho, que é o que de fato aconteceu. A opacidade de 0,13 da versão
   anterior tentava resolver com cor um problema de FORMA, e forma vence
   cor: barra cheia e arredondada no mesmo eixo é o desenho de um rastro, e
   foi lida como rastro. */
/* O COLCHETE É A EXCEÇÃO DELIBERADA À LARGURA ÚNICA. A rota toda tem uma
   espessura só porque é UMA coisa; o colchete não é rota — é a dúvida
   sobre onde a rota vai parar. Dar a ele a largura da fita seria repetir
   o erro de 87.1 por outro caminho: foi exatamente por ter a mesma forma
   e o mesmo peso do rastro que ele foi lido como rastro duas vezes. Fino
   e com hastes, ele se lê como notação de intervalo, que é o que é. */
.an-traj-ic { opacity: .5; stroke-width: 1.2; }
/* NÃO HÁ MAIS COR DE PROJEÇÃO — pedido 96. O índigo era uma decisão
   minha, argumentada («a projeção não julga o indicador»), e ele a
   derrubou com uma regra mais simples e mais útil: a projeção É um juízo,
   e o juízo é o único que este painel faz — vai atingir a meta ou não.
   Verde quer dizer «se nada mudar, estará dentro»; vermelho, «estará
   fora». Quem diz que é suposição continua sendo o tracejado, que diz
   sozinho e sem gastar uma terceira cor.
   O nome do colchete, na aula. Ele existe porque a forma sozinha não
   resolveu: um traço horizontal ao lado de uma bolha é lido como rastro
   mesmo fino, mesmo com hastes, mesmo 11px abaixo. */
/* Os nomes dos três momentos sobre o desenho — pedido deste turno. Só na
   aula: vinte e cinco bolhas com três rótulos cada seria a mancha de texto
   que o pedido 45 tirou daqui. */
.an-traj-mom {
  font: 700 9.5px/1 var(--fonte-rot); text-transform: uppercase;
  letter-spacing: .06em; fill: var(--ink-3);
}
.an-traj-mom-hoje { fill: var(--ink); }
/* O CHIP DO RÓTULO — pedido 92, anexos 2 e 3. Fundo próprio e sempre o
   mesmo: com os quadrantes a 20%, o halo da superfície deixou de bastar,
   porque ele era branco sobre branco e virou branco sobre quatro cores
   diferentes conforme o rótulo caísse. */
.an-chip {
  fill: var(--chip-fundo); stroke: var(--chip-borda); stroke-width: 1;
}
.an-chip-t {
  font: 700 9.5px/1 var(--fonte-rot); fill: var(--chip-tinta);
  letter-spacing: .05em; pointer-events: none;
}
/* A linha de chamada devolve o vínculo que o afastamento tira. Tracejada e
   fina de propósito: ela é ligação, não dado — se tivesse peso de rota,
   seria mais uma linha para o olho interpretar. */
.an-chip-ch {
  stroke: var(--chip-borda); stroke-width: 1; stroke-dasharray: 2 3;
  opacity: .8;
}
/* O chip do FUTURO é o único colorido, e na cor da projeção: ele nomeia o
   único dos três momentos que não aconteceu. */
/* O chip do futuro herda a cor do que ele anuncia (verde ou vermelho,
   conforme a projeção atinja a meta ou não) — pedido 96. */
.an-chip-fut { stroke: currentColor; }
.an-chip-fut + .an-chip-t, .an-chip-fut ~ .an-chip-t { fill: var(--chip-tinta); }
.an-chip-hoje { stroke: var(--ink-2); stroke-width: 1.5; }
.an-traj-mom-fut { fill: currentColor; }
.an-traj-ic-rot {
  font: 600 9.5px/1 var(--fonte); letter-spacing: .02em; opacity: .72;
}

/* A RÉGUA DO RASTRO — pedido 79, segunda volta. Mesma forma dos atalhos de
   seção: quatro estados que se excluem pedem um segmentado, não quatro
   botões soltos — soltos, nada diz que escolher um desliga os outros. */
.an-regua {
  display: flex; align-items: baseline; gap: 12px;
  flex-wrap: wrap; margin: 12px 0 2px;
}
.an-regua-rot {
  font: 600 10.5px/1 var(--fonte); letter-spacing: .12em;
  text-transform: uppercase; color: var(--ink-3); flex: none;
}
.an-regua-btns {
  display: inline-flex; border: 1px solid var(--borda-forte);
  border-radius: 8px; overflow: hidden; flex: none;
}
.an-regua-b {
  appearance: none; border: 0; background: var(--superficie-2);
  color: var(--ink-2); font: 600 12px/1 var(--fonte);
  padding: 6px 12px; cursor: pointer;
  border-right: 1px solid var(--borda);
}
.an-regua-b:last-child { border-right: 0; }
.an-regua-b:hover { background: var(--superficie-3); color: var(--ink); }
.an-regua-b.on {
  background: var(--marca); color: #fff;
  border-right-color: color-mix(in srgb, var(--marca) 70%, #000);
}
.an-regua-reset { flex: none; font-size: 11.5px; }
.an-regua-diz {
  margin: 0; flex: 1 1 320px; min-width: 240px;
  font-size: 12px; line-height: 1.45; color: var(--ink-3);
}
/* OS RÓTULOS DIRETOS — pedido 36: «informar claramente qual indicador é sem a
   necessidade do tooltip». Texto em tinta de TEXTO e não na cor da série: a
   bolha ao lado já carrega a cor, e um nome colorido competiria com ela pelo
   mesmo canal. */
.an-rot-dir {
  font: 600 9px/1 var(--fonte); fill: var(--ink-2);
  paint-order: stroke fill; pointer-events: none;
}
/* O halo é um traço na cor do plano por baixo da letra — o mesmo recurso do
   ponteiro do medidor. Sem ele o nome que cai sobre a linha do eixo ou sobre
   o fundo de um quadrante fica ilegível justamente onde o plano é mais
   denso. */
.an-rot-halo {
  stroke: var(--superficie); stroke-width: 3px; stroke-linejoin: round;
  fill: var(--superficie);
}
/* ===================================================================
   OS QUATRO FUNDOS, VIVOS E DISTINTOS ENTRE SI — pedido 91
   ===================================================================
   Artur: «quis vivificar mais os quadrantes deixando cores de fundo um
   pouco mais fortes e destacadas entre si... se puder seguir este hex do
   anexo ou parecido».

   Os hexes saíram do anexo dele, amostrados pixel a pixel e não
   adivinhados — são exatamente estes quatro:

     ACOMPANHAR  #6285CA   fora da meta, mas melhorando
     MANTER      #2FC741   dentro da meta e melhorando
     AGIR        #FF5757   fora da meta e piorando
     VIGIAR      #FAAF4C   dentro da meta e piorando

   O QUE MUDOU DE VERDADE NÃO FOI A FORÇA, FOI A MATIZ. Antes os fundos
   reusavam as cores do farol (crítico, atenção, bom) mais um azul de
   reserva, e a 5,5% as quatro regiões liam como uma mancha só — a
   divisão do plano ficava por conta de duas linhas finas. Agora cada
   quadrante tem matiz própria E força suficiente para a região se ler
   como região.

   POR QUE 20% E NÃO 100%, mesmo o desenho dele sendo chapado: o fundo
   dele era um mock sem 25 bolhas em cima. Aqui o fundo não pode ganhar
   da bolha — a posição de hoje continua sendo o assunto. 20% é onde a
   região se nomeia sozinha e a bolha continua sendo a figura; medido
   olhando os dois, não deduzido.

   O AZUL DO «ACOMPANHAR» E O ÍNDIGO DA PROJEÇÃO são vizinhos de matiz, e
   isso foi MEDIDO, não presumido. Compondo o fundo a 20% sobre a
   superfície de cada tema, o contraste da linha de projeção contra ele
   fica em 5,2:1 no claro e 4,72:1 no escuro — bem acima do piso de 3:1
   para marca gráfica. A bateria refaz essa conta: se um dos dois tons
   mudar um dia, ela reprova antes de alguém ver.

   O QUE ESTAS QUATRO CORES **NÃO** FAZEM, e é preciso estar escrito: o
   par vermelho/verde é indistinguível para deuteranopia (ΔE 3,2, medido
   com o validador de paleta). Isso é aceitável AQUI e não seria em
   qualquer lugar, porque a cor é a TERCEIRA codificação da região, não a
   primeira: cada quadrante tem posição fixa (agir sempre embaixo à
   esquerda) e o verbo escrito no canto desde o pedido 36. Quem não
   distingue as duas matizes lê o nome e a posição, que não dependem de
   cor nenhuma. Se um dia o verbo sair do canto, estas cores deixam de
   ser aceitáveis junto com ele. */
/* ===================================================================
   AS QUATRO CORES DO QUADRANTE — pedidos 91, 96 e 100
   ===================================================================
   Esta regra foi e voltou, e os três passos ficam escritos porque o
   caminho é a explicação:

   91 — «quis vivificar mais os quadrantes... se puder seguir este hex do
        anexo». Os quatro hexes vieram do anexo dele, amostrados pixel a
        pixel: acompanhar #6285CA, manter #2FC741, agir #FF5757, vigiar
        #FAAF4C.
   96 — «não há cor azul... é apenas verde/vermelho dependendo se está ou
        não atingindo a meta!». Eu li isso como valendo para TUDO no plano
        e troquei os quatro fundos por duas matizes com duas forças.
   100 — «as 4 cores de cada quadrante devem retornar». Eu tinha lido
        errado: o 96 era sobre a ROTA — a projeção em índigo, que é o azul
        que ele via desenhado em cima do dado. O FUNDO é outra coisa, e
        nele as quatro cores dizem QUATRO SITUAÇÕES, que é informação que
        duas matizes não carregam.

   A distinção que eu não tinha feito: cor de MARCA afirma sobre o dado e
   tem de obedecer à regra do farol; cor de REGIÃO nomeia um lugar do
   plano, e lugar pode ter nome próprio. A projeção continua verde ou
   vermelha (pedido 96, que segue valendo onde ele o disse); o fundo
   volta a ter as quatro.

   A força ficou em 20% para os quatro: na foto que ele mandou, a
   diferença de opacidade entre «agir» e «acompanhar» era imperceptível —
   ela existia na folha e não na tela, que é o mesmo que não existir. */
.an-q-fundo { opacity: .2; }
.an-f-agir       { fill: var(--q-agir); }
.an-f-acompanhar { fill: var(--q-acompanhar); }
.an-f-manter     { fill: var(--q-manter); }
.an-f-vigiar     { fill: var(--q-vigiar); }
.an-eixo { stroke: var(--borda-forte); stroke-width: 1; }
/* O ZOOM ESCRITO — pedido 92. Discreto de propósito: ele é a nota de
   rodapé do desenho, não o assunto. Mas presente sempre que houver zoom,
   porque aproximação não declarada engana sobre o tamanho do movimento. */
.an-zoom {
  font: 700 8px/1 var(--fonte-rot); fill: var(--ink-3); opacity: .75;
  letter-spacing: .06em;
}
/* 8px no viewBox, não 10: o SVG é elástico e, esticado de 900 para ~1380px,
   um rótulo de 10px chega à tela com 15 — maior que o corpo do texto do
   painel. O rótulo de eixo tem de ser o menor texto do gráfico, não o maior. */
.an-eixo-rot {
  font: 700 8px/1 var(--fonte); fill: var(--ink-3); opacity: .8;
  text-transform: uppercase; letter-spacing: .06em;
}
.an-bolha-p { cursor: help; transition: stroke-width .12s; }

.an-fam { display: flex; flex-direction: column; gap: 3px; }
.an-fam-l {
  display: grid; grid-template-columns: 150px 1fr 48px; gap: 10px;
  align-items: center; cursor: help; font-size: 11.5px; color: var(--ink-2);
}
.an-fam-n { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* A barra mede a distância MÉDIA da meta da família, em módulo — o sinal está
   na cor. Barra com sinal precisaria de linha de zero, e uma linha de zero
   por família repetiria oito vezes o que o gráfico de bolhas já diz uma. */
.an-fam-b { height: 6px; background: var(--superficie-3); border-radius: 999px;
  overflow: hidden; }
.an-fam-b i { display: block; height: 100%; border-radius: 999px; }
.an-fam-v { font: 700 11px/1 var(--fonte); color: var(--ink-3);
  font-variant-numeric: tabular-nums; text-align: right; }

/* O RODAPÉ DO 360 — pedido 37.3. Ver `painelAnalitico`. */
.an-pe { display: flex; gap: 10px 14px; flex-wrap: wrap; align-items: center; }
.an-limites-det { min-width: 0; }
.an-limites-det > summary {
  font: 600 10.5px/1 var(--fonte); text-transform: uppercase;
  letter-spacing: .07em; color: var(--ink-3); cursor: pointer;
  border: 1px dashed var(--borda); border-radius: 999px; padding: 5px 9px;
  list-style: none; display: inline-block;
}
.an-limites-det > summary::-webkit-details-marker { display: none; }
.an-limites-det > summary:hover { color: var(--ink); border-color: var(--ink-3); }
.an-limites-det[open] > summary { color: var(--ink); margin-bottom: 8px; }
.an-limites-det[open] { flex: 1 1 100%; }
.an-leitura { margin: 0; font-size: 12.5px; line-height: 1.55;
  color: var(--ink-2); }
.an-limites { margin: 0; padding-left: 16px; font-size: 11px; line-height: 1.5;
  color: var(--ink-3); }
.an-sem { margin: 12px 0; font-size: 12px; color: var(--ink-3); }

/* ==========================================================================
   AS FAIXAS DE RETRATO E DE PENDÊNCIA — pedido 42
   ==========================================================================
   Artur: «garanta que ele entre mesmo que com dados não tão frescos e indique
   que há atualizações a se realizar... mas não faça isto de tudo
   tachado/morto».

   O TOM É A DECISÃO DE DESENHO AQUI, e ele é diferente nas duas faixas porque
   as duas situações são diferentes:

     retrato    âmbar. A tela NÃO está quebrada — ela mostra dado bom de uma
                data anterior, que é situação normal de trabalho. Vermelho
                diria «destruído» e seria a parede de susto da v1.38.1 de
                novo, agora sobre 37 cartões cheios de número.
     pendência  neutra, quase legenda. O painel está correto; só existe algo
                a atualizar. Um aviso que grita por algo que não atrapalha
                ensina a ignorar os avisos que atrapalham.

   Nenhuma das duas tem `position: sticky`: elas são o primeiro bloco da tela,
   rolam com ela e saem de vista. Uma faixa colada no topo por minutos é uma
   tarja permanente, e tarja permanente vira papel de parede em dois dias. */
.r37-faixa {
  display: flex; gap: 14px; align-items: flex-start; flex-wrap: wrap;
  border-radius: 11px; padding: 12px 15px; margin-bottom: 12px;
  border: 1px solid var(--borda); background: var(--superficie-2);
}
.r37-faixa-txt { flex: 1 1 420px; min-width: 0; font-size: 12.5px;
  line-height: 1.55; color: var(--ink-2); }
.r37-faixa-txt b { color: var(--ink); }
.r37-faixa-acoes { display: flex; gap: 8px; align-items: center;
  flex-wrap: wrap; }
/* O «porque» é bloco e não continuação da frase: ele carrega a razão técnica,
   costuma ter duas linhas, e emendado no parágrafo vira um paredão. */
.r37-faixa-por {
  margin-top: 7px; padding-top: 7px; font-size: 12px;
  border-top: 1px dashed var(--borda); color: var(--ink-3);
}
.r37-faixa-por b { color: var(--ink-2); font-weight: 600; }
.r37-faixa-estado { margin-top: 7px; font-size: 12px; color: var(--ink-3); }
.r37-faixa-estado.mau { color: var(--critico); }
.r37-faixa-criterio {
  display: inline-block; margin-left: 8px; cursor: help;
  font: 600 10.5px/1 var(--fonte); text-transform: uppercase;
  letter-spacing: .06em; color: var(--ink-3);
  border-bottom: 1px dotted var(--borda-forte);
}
.r37-faixa-criterio:hover { color: var(--ink); }

/* ÂMBAR, não vermelho — ver a nota acima. */
.r37-faixa-retrato {
  border-color: color-mix(in srgb, var(--atencao) 45%, transparent);
  background: var(--atencao-bg);
}
.r37-faixa-retrato .r37-faixa-txt > b { color: var(--atencao); }

.r37-faixa-pend { background: var(--superficie-2); }

/* O botão que vira estado. Enquanto a extração corre ele diz «atualizando…» e
   não aceita clique — e a tela inteira continua utilizável atrás dele, que é
   o «pode vir no background» do pedido. */
.r37-bt-atu[disabled] { opacity: .72; cursor: progress; }
.r37-bt-atu-ativo { animation: batPulsa 1.6s ease-in-out infinite; }
@media (prefers-reduced-motion: reduce) {
  .r37-bt-atu-ativo { animation: none; }
}

/* ==========================================================================
   O NÚMERO NA BOLHA E A LEGENDA — pedido 45
   ==========================================================================
   Artur: «numerasse cada bubble em cada um dos 2 casos e depois deixe uma
   tabelinha abaixo, bem enquadrado com os números e seus respectivos nomes».

   O NÚMERO é branco com um contorno na cor do plano: a bolha por baixo tem
   42% de opacidade e pode cair sobre um fundo de quadrante, então nem branco
   puro nem tinta escura funcionam sozinhos nos dois temas. `paint-order`
   desenha o traço ANTES do preenchimento — sem isso o contorno comeria
   metade do dígito por dentro. */
/* CORPO MENOR — pedido 49: «use tamanho de fonte menor». 8px numa bolha de
   raio 8 a 26 deixa o número legível sem virar o assunto do desenho: quem
   manda no plano é a POSIÇÃO da bolha, e o número é só a etiqueta que liga
   ela à legenda. */
.an-num {
  font: 700 8px/1 var(--fonte); fill: #fff;
  stroke: rgba(0, 0, 0, .45); stroke-width: 2px;
  paint-order: stroke fill; stroke-linejoin: round;
}
/* Fora da bolha o fundo é o plano, não a bolha: o contorno passa a ser da
   superfície e a tinta, de texto. */
/* A LINHA QUE TRAZ O NÚMERO DE VOLTA, quando ele teve de sair do círculo
   por falta de lugar. Fina e na cor da bolha: ela é ligação, não dado. */
.an-num-ch { stroke-width: 1; opacity: .7; }
.an-num-fora {
  fill: var(--ink-2); stroke: var(--superficie); stroke-width: 2.2px;
}

/* A legenda em colunas automáticas: com 3 grupos ela vira uma coluna larga,
   com 25 indicadores vira três ou quatro estreitas — sem ponto de quebra
   escrito à mão, que é o que envelhece mal quando o número de itens muda. */
.an-legenda {
  list-style: none; margin: 8px 0 0; padding: 9px 11px;
  border: 1px solid var(--borda); border-radius: 9px;
  background: var(--superficie-2);
  columns: 2; column-gap: 18px;
}
@media (min-width: 1500px) { .an-legenda { columns: 3; } }
.an-legenda li {
  display: flex; gap: 7px; align-items: baseline;
  font-size: 11px; line-height: 1.45; color: var(--ink-2);
  break-inside: avoid; padding: 1px 0;
}
/* Largura fixa no número para os nomes alinharem em coluna — número que
   muda de largura desalinha a lista inteira, que é o defeito que o
   `tabular-nums` existe para evitar. */
.an-legenda li b {
  flex: none; min-width: 16px; text-align: right;
  font: 700 11px/1.45 var(--fonte); font-variant-numeric: tabular-nums;
}
.an-legenda li span { min-width: 0; }

/* ==========================================================================
   AS SEÇÕES NUMERADAS E A SAÚDE POR RECORTE — pedido 46
   ==========================================================================
   O algarismo romano é deliberado: ele não se confunde com os números dos 37
   cartões, que são arábicos e já significam outra coisa. Numa tela em que o
   «23» é um indicador, o «IV» só pode ser uma seção. */
/* O DESCONTO DA BARRA FIXA MORA AQUI — pedido 54.
   O atalho I…V usa `scrollIntoView({block:'start'})`, e sem esta margem o
   cabeçalho fixo cobriria justamente o título da seção para onde a pessoa
   acabou de ir. Fica no CSS e não numa conta em pixels no JS porque a barra
   muda de altura com a largura da janela — qualquer número escrito lá
   estaria errado em alguma largura. */
/* O DESCONTO É MEDIDO, NÃO ESCRITO — pedido 72. O 96px daqui era um
   palpite, e falhou na máquina dele: cabeçalho do app, abas e barra do
   Radar somam bem mais que isso, e o título da seção chegava cortado.
   `--sec-offset` é escrito pelo JS a partir da altura REAL do bloco fixo,
   imediatamente antes de rolar; o valor aqui é só o que vale antes do
   primeiro clique. */
.sec, .an-painel { scroll-margin-top: var(--sec-offset, 150px); }
.sec { margin: 0 0 16px; }

/* ATALHOS I…V — pedido 54: «inclua shortcuts aqui para navegar entre I e V».
   Cinco alvos pequenos e iguais, na ponta da barra: é uma régua, e régua se
   lê de relance. Desabilitado em vez de escondido quando a seção ainda não
   existe — sumir ensinaria que o painel tem quatro seções hoje e cinco
   amanhã. */
/* COMPACTOS DE PROPÓSITO. A barra é UMA linha desde o pedido 30, e cinco
   botões a mais são exatamente o tipo de acréscimo que a faz virar duas —
   o que desfaria um pedido para atender outro. Em 22px de lado e 2px de
   vão, os cinco somam 118px: cabem na folga que o chip «13 meses» deixou
   quando saiu. A bateria mede a barra a 1500px justamente por isto. */
/* UM CONTROLE SEGMENTADO, e não cinco botões soltos — a barra é UMA linha
   desde o pedido 30, e cinco botões com vão e borda própria custavam 118 px
   que ela não tinha (a bateria mede a 1500 px e acusou duas linhas). Juntos,
   compartilhando bordas, os cinco somam ~95 px — e de quebra lêem-se como o
   índice que são, e não como cinco ações independentes. */
.r37-atalhos {
  display: flex; margin-left: 4px; flex: 0 0 auto;
  border: 1px solid var(--borda); border-radius: 6px; overflow: hidden;
}
/* TELA CHEIA E ZOOM — pedido 103. Mesma moldura dos atalhos de seção,
   ao lado deles, porque são da mesma natureza: nenhum muda o dado, os
   dois mudam o que se vê. O degrau do zoom é um botão e não um texto —
   clicar nele volta a 100%, que é a saída que a pessoa procura quando
   se perde no tamanho. */
.r37-vista {
  display: flex; margin-left: 6px; flex: 0 0 auto;
  border: 1px solid var(--borda); border-radius: 6px; overflow: hidden;
}
.r37-vista-fs { font-size: 13px; }
.r37-zoom-b { font-weight: 700; }
.r37-zoom-v {
  font-variant-numeric: tabular-nums; min-width: 44px;
  letter-spacing: 0;
}
.r37-at {
  min-width: 19px; height: 22px; padding: 0 2px;
  border: 0; border-left: 1px solid var(--borda);
  background: var(--superficie-2); color: var(--ink-2);
  font: 700 9.5px/1 var(--fonte); letter-spacing: .01em; cursor: pointer;
  font-variant-numeric: tabular-nums;
}
.r37-at:first-child { border-left: 0; }
.r37-at:hover:not(:disabled) {
  background: var(--superficie-3); color: var(--ink);
  border-color: var(--borda-forte);
}
.r37-at:disabled { opacity: .38; cursor: default; }
/* NÚMERO E TÍTULO NA MESMA LINHA — pedido 48.
   Artur, com o recorte: «deixe tudo junto na mesma linha e use fonte
   destacando: I-Saúde em Rede Externa».

   Eram duas linhas por dois motivos somados: `flex-wrap: wrap` autorizava a
   quebra, e o `<h3>` é bloco — em flex ele vira item, mas com `min-width`
   automático ele reivindica a largura do texto inteiro e empurra o vizinho
   para baixo assim que o título é longo. `nowrap` no par + `min-width: 0` no
   título resolvem os dois: o número nunca desce, e um título comprido
   encolhe em vez de quebrar a linha.

   E o número passou a ser SÓLIDO, não contornado: no recorte dele o «II»
   pálido ao lado de um título preto em negrito não parecia um índice,
   parecia um resíduo. Um índice que não se vê não serve para apontar. */
.sec-cab {
  display: flex; align-items: center; gap: 10px; flex-wrap: nowrap;
  margin: 0 0 9px; padding-bottom: 7px;
  border-bottom: 1px solid var(--borda);
}
.sec-cab h3 { min-width: 0; overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; }
.sec-sub { flex: none; white-space: nowrap; }
.sec-num {
  font: 800 12px/1 var(--fonte); letter-spacing: .07em;
  color: #fff; background: var(--marca, var(--critico));
  font-variant-numeric: tabular-nums;
  border-radius: 6px; padding: 5px 8px; flex: none;
  min-width: 30px; text-align: center;
}
.sec-num-inline { font-size: 11px; padding: 3px 6px; }
.sec-cab h3 { margin: 0; font: 700 14.5px/1.2 var(--fonte); letter-spacing: -.01em; }
.sec-sub { font-size: 11.5px; color: var(--ink-3); }
.sec-dica {
  margin-left: auto; cursor: help;
  font: 600 10px/1 var(--fonte); text-transform: uppercase;
  letter-spacing: .07em; color: var(--ink-3);
  border-bottom: 1px dotted var(--borda-forte);
}
.sec-dica:hover { color: var(--ink); }

/* AS TIRAS DE SAÚDE (IV e V). Mesma gramática das barras de «dimensões
   críticas» — a tela já ensinou a ler essa forma uma vez, e reaproveitá-la
   custa zero aprendizado. A barra vai de 0 a 100 SEMPRE: índice tem teto
   natural, e barra relativa ao melhor da lista faria um conjunto todo ruim
   parecer um conjunto com alguns bons. */
.sd-lista {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(330px, 1fr));
  gap: 2px 26px;
}
.sd-l {
  display: grid; grid-template-columns: minmax(0, 1fr) 110px 30px 46px;
  gap: 10px; align-items: center; padding: 4px 0; cursor: help;
}
.sd-n {
  font-size: 12px; color: var(--ink-2); white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis;
}
.sd-t {
  height: 8px; border-radius: 999px; background: var(--superficie-3);
  overflow: hidden; display: block;
}
.sd-t i { display: block; height: 100%; border-radius: 999px;
  background: currentColor; }
.sd-v {
  font: 700 14px/1 var(--fonte); font-variant-numeric: tabular-nums;
  text-align: right; color: currentColor;
}
.sd-c { font-size: 11px; color: var(--ink-3); text-align: right;
  font-variant-numeric: tabular-nums; }
/* A COR VEM DA FAIXA, e é a mesma do medidor e do farol: três lugares
   dizendo «crítico» na mesma cor é o que permite comparar o índice da rede
   com o de um grupo sem traduzir nada. */
.sd-saudavel { color: var(--bom); }
.sd-atencao  { color: var(--atencao); }
.sd-critico  { color: var(--critico); }
.sd-sem_juizo { color: var(--ink-3); }

/* ==========================================================================
   A MARCA DA QUEBRA — pedido 52
   ==========================================================================
   A PÍLULA DO RÓTULO FOI REMOVIDA — pedido 56: «exclua o fundo dos números…
   ficou péssimo… melhor como antes».

   Ela nasceu no 53.2 («os números deixe um fundo de bordas arredondadas…
   a cor do fundo acompanha o verde vermelho cinza típico de sua
   classificação») e resolvia o que ele descreveu: o halo funciona sobre
   fundo liso e enfraquece justamente sobre a curva, porque ali o que está
   atrás não é o plano, é a linha.

   Resolvia UM cartão. Nos 37 eram quase quinhentos retângulos coloridos
   numa tela cujo assunto são as curvas — o remédio virou o fundo, e o dado
   virou o que atravessa o ruído. Some a isso que eu acrescentei o
   julgamento mês a mês na cor da pílula, que ninguém pediu e que disputa
   com o farol do cartão a mesma informação.

   O halo (`.r37-rot-v`, `paint-order: stroke fill`) volta a ser o único
   tratamento. Ficam aqui, e não no histórico, as duas lições: um efeito se
   avalia na DENSIDADE em que vai viver, e um conserto não é hora de
   acrescentar o que não foi pedido. */

/* A MARCA DA QUEBRA. Duas linhas em zigue-zague na altura exata onde a
   escala foi interrompida. Ela é discreta mas NÃO some: gráfico de eixo
   quebrado sem marca é o gráfico enganoso clássico, e a marca é o que separa
   uma lente de um truque. */
.r37-quebra {
  fill: none; stroke: var(--borda-forte); stroke-width: 1.1;
  opacity: .75; vector-effect: non-scaling-stroke;
}

/* ===========================================================================
   O MAPA DO CACHE — ADM › Cache & Aquecimento
   ===========================================================================
   Artur: «nunca sei o que está salvo no cache e no warmup... não está legal
   o status disso, não está intuitivo».

   A grade responde por POSIÇÃO: acha-se a linha da região e vê-se onde a
   fila de células acesas termina. Uma lista de 87 itens tem a mesma
   informação numa forma que obriga a ler tudo para achar uma.

   As células são pequenas de propósito — o valor está no PADRÃO que elas
   formam, não em cada uma. Grandes o bastante para o mouse (10px + 3 de
   vão), pequenas o bastante para 48 meses caberem na linha. */
.ck-grade { display: flex; flex-direction: column; gap: 5px; margin: 12px 0 4px;
  overflow-x: auto; padding-bottom: 4px; }
.ck-linha { display: flex; align-items: center; gap: 10px; }
.ck-reg { flex: 0 0 150px; font: 600 11.5px/1.2 var(--fonte);
  color: var(--ink-2); text-align: right; white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis; }
.ck-cels { display: flex; gap: 3px; }
.ck { display: inline-block; width: 10px; height: 10px; border-radius: 3px;
  vertical-align: -1px; }
.ck-mem { background: var(--bom); }
/* Contornado e não outra cor: memória e disco abrem igual desde o pedido 55,
   e duas cores sugeririam duas promessas diferentes. */
.ck-dis { background: transparent; box-shadow: inset 0 0 0 1.5px var(--bom); }
.ck-nao { background: var(--borda); }

/* ===========================================================================
   CORPO MAIOR E HIERARQUIA MAIS FORTE — pedido 66
   ===========================================================================
   Artur: «aumente mais as fontes em geral e dê maior destaque tanto nos
   números quanto nos textos pois melhoram a legibilidade e intuitividade».

   O painel nasceu para caber. Cada decisão de tamanho foi tomada olhando
   UM bloco e perguntando «cabe?», e a soma dessas decisões produziu uma
   tela em que tudo cabe e nada se destaca — 11px para rótulo, 12px para
   nome, 13px para valor. Três corpos com um ponto e meio de diferença não
   formam hierarquia: formam uma mancha cinza uniforme em que o olho não
   encontra por onde começar.

   O CONSERTO NÃO É «TUDO MAIOR», e é por isso que ele vem em bloco e não
   espalhado: o que cresce é o NÚMERO e o NOME (o que se procura), e o que
   fica onde está é o rótulo e a nota (o que se lê depois de achar). Esticar
   os dois igualmente devolveria a mesma mancha, só que maior.

   As medidas saem de uma escala com razão ~1,25 entre degraus, que é o
   mínimo para dois corpos se distinguirem de relance: 11 · 13 · 16 · 20.
   Abaixo disso o olho compara em vez de reconhecer. */
.px-bl-n { font-size: 13.5px; font-weight: 600; color: var(--ink); }
.px-bl-v { font-size: 15px; }
.px-bl { grid-template-columns: minmax(0, 1fr) 104px 64px; padding: 5px 0; }
.px-bl-t { height: 9px; }
.px-chip { font-size: 12.5px; padding: 7px 12px; }
.px-leitura { font-size: 13.5px; line-height: 1.6; }
.px-sub { font-size: 12px; }
.px-num b { font-size: 34px; }
.px-num span { font-size: 16px; }
/* O título de cada bloco do cabeçalho: era 10,5px em maiúsculas, o menor
   texto da tela. Ele é o que diz DO QUE o número ao lado está falando. */
.px-bl-rot, .px-rot, .px-rank-rot { font-size: 13px;
  letter-spacing: .11em; }
.px-pill { font-size: 11.5px; }

/* Os quatro verbos do 360 e a legenda das bolhas. O número já era grande;
   quem estava pequeno era o verbo — e o verbo é o que a pessoa leva da
   reunião. */
.an-caixa b { font-size: 28px; }
.an-caixa-rot { font-size: 11.5px; }
.an-legenda li, .an-num { font-size: 12.5px; }
/* NA AULA O NÚMERO É GRANDE — pedido 98, como no desenho dele. Depois da
   regra acima, de propósito: é ela que vence o atributo de apresentação,
   e por isso a exceção precisa vir depois e com a mesma especificidade. */
.an-num.an-num-aula { font-size: 17px; }
.an-meia-cab h5 { font-size: 13px; }
.an-meia-sub { font-size: 11.5px; }

/* As tiras de saúde (IV e V) e a fila dos grupos. */
.sd-l { font-size: 13.5px; }
.sd-nome { font-weight: 600; color: var(--ink); }
.sd-v { font-size: 15px; }

/* ===========================================================================
   OS QUADRANTES, MAIS FORTES — pedido 67
   ===========================================================================
   Artur: «deixe as cores de cada quadrante mais fortes».

   Elas estavam em 5,5% de opacidade, e isso foi uma decisão consciente que
   o uso desmentiu: o comentário original diz «acima de ~6% eles competem
   com as bolhas». Competir era o medo certo sobre o objeto errado. O que
   compete com uma bolha é outra COISA REDONDA E SATURADA, não um retângulo
   de fundo — e a 5,5% o retângulo simplesmente não existia: os quatro
   quadrantes liam como um fundo branco só, e a divisão que dá sentido ao
   plano ficava por conta de duas linhas finas.

   11% é o ponto em que a região se lê como região e a bolha continua sendo
   a figura. Medido olhando os dois, e não deduzido. */
/* No deck impresso o fundo pode ser um pouco mais forte que na tela: o
   papel não tem brilho de monitor e perde saturação na projeção. */
.an-q-fundo { opacity: .24; }
/* O verbo no canto sobe de 9px/55% para 11px/85%: ele nomeia o quadrante, e
   um nome que não se lê não nomeia nada. */
.an-q-nome { font-size: 11px; opacity: .85; letter-spacing: .1em; }

/* ===========================================================================
   A MOVIMENTAÇÃO ENTRE QUADRANTES E A FICHA DA FAMÍLIA — pedidos 67 e 68
   =========================================================================== */
.an-mov {
  margin: 10px 0 0; font-size: 13px; line-height: 1.6; color: var(--ink-2);
}
.an-mov b { color: var(--ink); }
.an-mov span { font-weight: 800; letter-spacing: .04em; }
/* A legenda da trajetória — pedido 79. O exemplo é DESENHADO e não descrito:
   «traço cheio» é uma palavra que a pessoa tem de traduzir para o desenho;
   o próprio traço, no começo da frase, dispensa a tradução. Ele usa
   `currentColor`, então acompanha o tema sem uma segunda paleta. */
.an-mov-traj { margin-top: 6px; }
.an-mov-ex {
  width: 84px; height: 12px; vertical-align: -1px;
  margin-right: 8px; color: var(--ink-3);
}

/* Barras à esquerda, ficha à direita: a coluna da ficha tem largura própria
   e não `1fr`, porque um texto que estica com a janela vira linha de 160
   caracteres — o olho perde a linha na volta. */
.an-fam-bloco {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(280px, 420px);
  gap: 26px; align-items: start; margin-top: 14px;
}
@media (max-width: 1100px) {
  .an-fam-bloco { grid-template-columns: 1fr; }
}
.an-fam-l { cursor: help; border-radius: 6px; }
.an-fam-l:hover, .an-fam-l:focus-visible {
  background: var(--superficie-2); outline: none;
}
.an-ficha {
  border: 1px solid var(--borda); border-radius: 12px; padding: 14px 16px;
  background: var(--superficie-2); display: flex; flex-direction: column;
  gap: 9px;
}
.an-ficha-cab { display: flex; align-items: baseline; gap: 10px; }
.an-ficha-cab h5 {
  margin: 0; font: 800 15px/1.2 var(--fonte); color: var(--ink);
}
.an-ficha-n {
  margin-left: auto; font: 700 12px/1 var(--fonte); color: var(--ink-3);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
.an-ficha-l { display: grid; grid-template-columns: 62px minmax(0, 1fr);
  gap: 10px; align-items: baseline; }
.an-ficha-l i {
  font: 700 9.5px/1.5 var(--fonte); font-style: normal; color: var(--ink-3);
  text-transform: uppercase; letter-spacing: .07em;
}
.an-ficha-l p { margin: 0; font-size: 13px; line-height: 1.5;
  color: var(--ink-2); }
.an-ficha-nums {
  display: flex; gap: 22px; border-top: 1px solid var(--borda);
  padding-top: 10px; margin-top: 2px;
}
.an-ficha-nums span { display: flex; flex-direction: column; gap: 2px; }
.an-ficha-nums b {
  font: 800 22px/1 var(--fonte); color: var(--ink);
  font-variant-numeric: tabular-nums;
}
.an-ficha-nums i {
  font: 600 10px/1.3 var(--fonte); font-style: normal; color: var(--ink-3);
  text-transform: uppercase; letter-spacing: .05em;
}
/* A ressalva é pequena e NÃO some: conceito de negócio apresentado como se
   viesse do banco é a forma mais eficiente de contaminar uma reunião. */
.an-ficha-nota {
  margin: 0; font-size: 10.5px; line-height: 1.45; color: var(--ink-3);
  font-style: italic;
}

/* Os quatro tamanhos do export — pedido 70.1. Mesmo controle segmentado do
   formato, uma medida menor: são quatro opções e não duas, e a caixa do
   menu tem largura fixa. */
.r37-saida-tam .r37-saida-op { padding: 7px 9px; font-size: 11px; }

/* ===========================================================================
   O RELATÓRIO DE ATUALIZAÇÃO — pedido 69
   ===========================================================================
   Modal, e não uma aba: ele é consultado NO MEIO de outra coisa («o Prefect
   rodou, chegou?») e a pessoa volta para onde estava. Uma aba exigiria sair
   do Radar e voltar, e o estado da tela — mês, região, busca — teria de ser
   remontado. */
.bat-lupa {
  border: 1px solid var(--borda); background: var(--superficie-2);
  color: var(--ink-3); border-radius: 6px; cursor: pointer;
  font-size: 11px; line-height: 1; padding: 5px 7px; margin-left: 2px;
}
.bat-lupa:hover { color: var(--ink); border-color: var(--borda-forte); }
.lt-fundo {
  position: fixed; inset: 0; z-index: 900; display: flex;
  align-items: flex-start; justify-content: center; padding: 48px 20px;
  background: color-mix(in srgb, #000 46%, transparent);
  overflow: auto;
}
.lt-caixa {
  width: min(880px, 100%); background: var(--superficie);
  border: 1px solid var(--borda-forte); border-radius: 14px;
  box-shadow: var(--sombra); padding: 20px 24px 24px;
  display: flex; flex-direction: column; gap: 16px;
}
.lt-cab { display: flex; align-items: center; gap: 12px; }
.lt-cab h3 { margin: 0; font: 800 19px/1.2 var(--fonte); color: var(--ink); }
.lt-x {
  margin-left: auto; border: 0; background: transparent; cursor: pointer;
  font-size: 22px; line-height: 1; color: var(--ink-3);
}
/* A CORRENTE, EM QUATRO ELOS. O primeiro fica apagado porque o CORTEX não o
   mede — e mostrar um elo que ele não prova, com a mesma cara dos outros,
   seria dar uma resposta verde a uma corrente quebrada. */
.lt-corrente { display: flex; flex-direction: column; gap: 10px; }
.lt-elo { display: grid; grid-template-columns: 30px minmax(0, 1fr); gap: 12px; }
.lt-n {
  width: 26px; height: 26px; border-radius: 50%; display: grid;
  place-items: center; background: var(--marca); color: #fff;
  font: 800 12px/1 var(--fonte);
}
.lt-elo-nao .lt-n { background: var(--borda-forte); }
.lt-elo-nao p, .lt-elo-nao b { color: var(--ink-3); }
.lt-elo-h { display: flex; align-items: baseline; gap: 10px; }
.lt-elo-h b { font: 700 14px/1.3 var(--fonte); color: var(--ink); }
.lt-elo-h span {
  margin-left: auto; font: 700 12.5px/1 var(--fonte); color: var(--ink-2);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
.lt-elo p { margin: 3px 0 0; font-size: 12.5px; line-height: 1.5;
  color: var(--ink-2); }
.lt-secao { border-top: 1px solid var(--borda); padding-top: 12px; }
.lt-secao h4 {
  margin: 0 0 8px; font: 700 11px/1 var(--fonte); text-transform: uppercase;
  letter-spacing: .08em; color: var(--ink-3);
}
.lt-secao p { margin: 0; font-size: 13px; line-height: 1.55;
  color: var(--ink-2); }
.lt-lista { list-style: none; margin: 0; padding: 0;
  display: flex; flex-direction: column; gap: 10px; }
.lt-lista li { border-left: 2px solid var(--borda); padding-left: 12px; }
.lt-r-h { display: flex; align-items: baseline; gap: 10px; }
.lt-r-h b { font: 700 13px/1 var(--fonte); color: var(--ink);
  font-variant-numeric: tabular-nums; }
.lt-r-h span { font-size: 12px; color: var(--ink-3); }
.lt-lista p { margin: 3px 0 0; font-size: 12.5px; line-height: 1.5; }
.lt-r-f { color: var(--ink-3); font-style: italic; }
.lt-fontes { list-style: none; margin: 0; padding: 0;
  display: flex; flex-direction: column; gap: 5px; }
.lt-fontes li { display: flex; align-items: baseline; gap: 10px;
  font-size: 12.5px; }
.lt-fontes b { color: var(--ink); font-weight: 700; }
.lt-fontes span { color: var(--ink-3); font-variant-numeric: tabular-nums; }
.lt-fontes i { margin-left: auto; color: var(--atencao); font-style: normal;
  font-weight: 700; font-size: 11.5px; }
.lt-f-mudou b { color: var(--atencao); }
.lt-vazio { color: var(--ink-3); font-size: 12.5px; }
.lt-pe {
  margin: 0; border-top: 1px solid var(--borda); padding-top: 12px;
  font-size: 12px; line-height: 1.55; color: var(--ink-3);
}

/* ===========================================================================
   AS DEFINIÇÕES DO «EM CONSTRUÇÃO» — pedido 71
   ===========================================================================
   Artur: «daria pra explicar melhor isto? porém não pode poluir o dash».

   As duas exigências puxam para lados opostos, e o desenho atende as duas
   explicando em espaço ZERO: cada número tem o seu balão, e a sanfona abaixo
   nasce fechada. Quem não abre não paga um pixel; quem abre paga uma vez.

   `width: 100%` na sanfona para ela ocupar a própria linha dentro do rodapé,
   que é um flex com quebra: sem isso ela disputaria a linha com as pílulas e
   empurraria a última para baixo mesmo fechada. */
.px-pend-i { cursor: help; border-radius: 5px; padding: 1px 3px; }
.px-pend-i:hover, .px-pend-i:focus-visible {
  background: var(--superficie-2); outline: none;
}
.px-pend-det { width: 100%; margin-top: 2px; }
.px-pend-det > summary {
  cursor: pointer; list-style: none; display: inline-block;
  font: 600 11px/1 var(--fonte); color: var(--ink-3);
  border-bottom: 1px dotted var(--borda-forte); padding: 2px 0;
}
.px-pend-det > summary::-webkit-details-marker { display: none; }
.px-pend-det > summary:hover { color: var(--ink-2); }
.px-pend-det dl {
  margin: 8px 0 0; display: grid;
  grid-template-columns: max-content minmax(0, 1fr); gap: 4px 14px;
}
.px-pend-det dt {
  font: 700 11.5px/1.5 var(--fonte); color: var(--ink-2); white-space: nowrap;
}
.px-pend-det dd {
  margin: 0; font-size: 12px; line-height: 1.5; color: var(--ink-3);
}

/* ===========================================================================
   A CHEGADA DO ATALHO — pedido 72
   ===========================================================================
   Rolar é um movimento, e movimento sem marca deixa a pessoa procurando onde
   parou. O algarismo clicado fica marcado (é estado, fica) e a seção recebe
   um realce que apaga sozinho em 1,6 s — tempo de a rolagem suave terminar e
   o olho pousar. Permanente viraria decoração; instantâneo seria comido pela
   própria animação. */
.r37-at.on {
  background: var(--marca); color: #fff; border-left-color: var(--marca);
}
.r37-at.on + .r37-at { border-left-color: var(--marca); }
.sec-alvo { position: relative; }
.sec-alvo::before {
  content: ''; position: absolute; inset: -8px -12px; border-radius: 12px;
  border: 2px solid var(--marca);
  background: color-mix(in srgb, var(--marca) 6%, transparent);
  pointer-events: none; animation: sec-pisca 1.6s ease-out forwards;
}
.sec-alvo .sec-num, .sec-alvo .sec-num-inline {
  animation: sec-pulso 1.6s ease-out;
}
@keyframes sec-pisca { 0% { opacity: 1 } 70% { opacity: 1 } 100% { opacity: 0 } }
@keyframes sec-pulso {
  0% { transform: scale(1) } 22% { transform: scale(1.22) }
  50% { transform: scale(1) } 100% { transform: scale(1) }
}
@media (prefers-reduced-motion: reduce) {
  .sec-alvo::before, .sec-alvo .sec-num { animation: none; }
  .sec-alvo::before { opacity: 0; }
}

/* ===========================================================================
   O QUE MUDA COM DIA · MÊS · ANO — pedido 73
   ===========================================================================
   Artur: «esclareça pois não entendi entre dia mês e ano... o que é
   visualizado e onde isto é visualizado?».

   A explicação existia inteira dentro do balão de cada botão — ou seja, num
   lugar que só encontra quem já desconfia que há o que encontrar. Um controle
   que precisa de hover para dizer o que faz é um controle que não diz o que
   faz. Agora ela é texto, dentro do menu ⚙, que já nasce fechado: zero pixel
   no painel e nenhuma dependência de o mouse passar no lugar certo.

   A SEGUNDA LINHA É A DESTACADA porque é a resposta à pergunta dele — o que
   os CARTÕES mostram. As outras duas são contexto. */
.tl-granu-bloco { display: flex; flex-direction: column; gap: 8px; }
.tl-granu-diz {
  max-width: 340px; display: flex; flex-direction: column; gap: 5px;
  border-left: 2px solid var(--borda); padding-left: 10px;
}
.tl-granu-diz p {
  margin: 0; font-size: 12px; line-height: 1.5; color: var(--ink-3);
}
.tl-granu-diz .tl-g-forte { color: var(--ink-2); font-weight: 600; }
.tl-granu-diz .tl-g-nota {
  border-top: 1px solid var(--borda); padding-top: 5px; font-size: 11px;
  font-style: italic;
}

/* O PASSO DIÁRIO, EM UMA LINHA — pedido 73.
   Era um bloco de título, dois parágrafos e dois botões no topo do painel.
   Nasceu certo (não havia outro lugar para explicar) e ficou errado quando a
   explicação passou a morar no menu ⚙, ao lado do controle que a produz.
   Duas explicações completas da mesma coisa é pior que uma: a pessoa lê as
   duas e procura a diferença. */
.r37-dia-linha {
  display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap;
  margin: 0 0 12px; padding: 8px 12px; border-radius: 8px;
  background: var(--atencao-bg, var(--superficie-2));
  border: 1px solid color-mix(in srgb, var(--atencao) 35%, transparent);
  font-size: 12.5px; line-height: 1.5; color: var(--ink-2);
}
.r37-dia-linha b { color: var(--ink); font-weight: 700; white-space: nowrap; }
.r37-dia-linha .lk {
  background: none; border: 0; padding: 0; cursor: pointer; font: inherit;
  color: var(--marca); text-decoration: underline; white-space: nowrap;
}
.r37-dia-linha .lk:hover { color: var(--ink); }
/* O ícone do calendário virou SVG (emoji é fonte, e numa máquina sem o
   glifo ele aparece como o retângulo com o código dentro). */
.tl-cal svg { display: block; }

/* OS TRÊS RELÓGIOS DO FRESCOR — pedido 74.
   O terceiro fica marcado como NÃO PROVADO com a mesma ênfase visual dos
   outros dois. Apagá-lo transformaria «não sabemos» em «está tudo certo»,
   que é a única leitura que não se pode permitir aqui. */
.lt-relogios { list-style: none; margin: 0; padding: 0;
  display: flex; flex-direction: column; gap: 10px; }
.lt-relogios li {
  border-left: 3px solid var(--bom); padding-left: 12px;
  display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 2px 12px;
}
.lt-rel-nao { border-left-color: var(--atencao) !important; }
.lt-relogios b { font: 700 13.5px/1.3 var(--fonte); color: var(--ink); }
.lt-rel-selo {
  font: 700 10px/1 var(--fonte); text-transform: uppercase;
  letter-spacing: .07em; color: var(--bom); white-space: nowrap;
  align-self: center;
}
.lt-rel-nao .lt-rel-selo { color: var(--atencao); }
.lt-relogios p { grid-column: 1 / -1; margin: 2px 0 0; font-size: 12.5px;
  line-height: 1.5; color: var(--ink-2); }
.lt-limite {
  margin: 12px 0 0 !important; padding: 10px 12px; border-radius: 8px;
  background: var(--atencao-bg, var(--superficie-2));
  border: 1px solid color-mix(in srgb, var(--atencao) 35%, transparent);
  font-size: 12.5px !important; line-height: 1.55;
}

/* ===========================================================================
   O COMPARADOR DE UNIDADES — pedido 75
   ===========================================================================
   Dois controles lado a lado respondem duas perguntas diferentes: o `select`
   diz QUAL recorte estou vendo; o comparador diz COM QUEM eu comparo. Fundir
   os dois num múltiplo faria escolher três regiões parecer que o painel virou
   a soma das três — e é justamente essa leitura que o dado não sustenta:
   média de razões não é a razão do todo, e o Book não publica linha
   consolidada para um conjunto qualquer. */
.r37-regiao-par { display: inline-flex; align-items: center; gap: 4px; }
.r37-cmp-rot { display: inline-flex; align-items: baseline; gap: 3px;
  white-space: nowrap; }
.r37-cmp-rot b:empty { display: none; }
.r37-cmp-abre { padding-left: 9px; padding-right: 9px; }
.r37-cmp-rot b { font-variant-numeric: tabular-nums; }
.r37-cmp-menu {
  position: absolute; z-index: 60; top: calc(100% + 6px); right: 0;
  width: 300px; max-height: 60vh; overflow: auto;
  background: var(--superficie); border: 1px solid var(--borda-forte);
  border-radius: 10px; box-shadow: var(--sombra); padding: 12px 14px;
  display: flex; flex-direction: column; gap: 9px;
}
.r37-cmp-grupo { position: relative; }
.r37-cmp-nota { margin: 0; font-size: 11.5px; line-height: 1.5;
  color: var(--ink-3); }
.r37-cmp-lista { display: flex; flex-direction: column; gap: 2px;
  border-top: 1px solid var(--borda); padding-top: 8px; }
.r37-cmp-l { display: flex; align-items: center; gap: 8px; cursor: pointer;
  font-size: 12.5px; color: var(--ink-2); padding: 3px 4px; border-radius: 5px; }
.r37-cmp-l:hover { background: var(--superficie-2); color: var(--ink); }
.r37-cmp-acoes { display: flex; gap: 8px; border-top: 1px solid var(--borda);
  padding-top: 9px; }
/* A leitura do filtro, onde o ranking aparece: sem ela, uma fila de três
   unidades num painel de onze parece o painel inteiro. */
.r37-filtro-diz {
  margin: 6px 0 0; font-size: 11.5px; line-height: 1.5; color: var(--ink-3);
  font-style: italic;
}

/* A faixa da múltipla escolha usa a mesma forma da do passo diário: uma
   linha, discreta, com a ação de saída no fim. Duas formas diferentes para
   dois avisos do mesmo peso obrigariam a aprender duas vezes. */
.r37-multi-linha {
  background: var(--superficie-2);
  border-color: var(--borda);
}

/* ==========================================================================
   VI · BASE ANALÍTICA — pedido 118
   ==========================================================================
   Uma tabela de 37 linhas × 12 colunas que precisa ser LIDA, não só exibida.
   As três decisões que fazem diferença aqui:

   1. CABEÇALHO GRUDADO. Rolar 37 linhas e perder o nome das colunas obriga a
      subir, ler e descer — e quem faz isso duas vezes para de conferir.
   2. NÚMEROS TABULARES e alinhados à direita. Dígito de largura variável faz
      a casa decimal dançar entre as linhas, e comparar duas linhas passa a
      exigir atenção que deveria ir para o número.
   3. O TRAVESSÃO TEM COR PRÓPRIA, mais fraca. Ele não é um valor; parecer um
      valor é exatamente o risco de uma tabela com buracos. */
.vi-caixa { overflow: visible; }
.vi-intro { font-size: 12.5px; color: var(--ink-2); margin: 0 0 10px; line-height: 1.5; }
.vi-intro b { color: var(--ink); }
.vi-leitura {
  font-size: 12.5px; line-height: 1.55; color: var(--ink-2);
  border-left: 3px solid var(--borda-forte); padding: 8px 0 8px 11px;
  margin: 0 0 14px; background: var(--superficie-2);
}
.vi-sub {
  font-size: 12px; text-transform: uppercase; letter-spacing: .06em;
  color: var(--ink-3); margin: 18px 0 8px; font-weight: 700;
}
.vi-sub i { font-style: normal; color: var(--ink); text-transform: none; letter-spacing: 0; }

.vi-tab, .vi-hist {
  width: 100%; border-collapse: collapse; font-size: 12px;
  font-variant-numeric: tabular-nums;
}
.vi-tab th, .vi-hist th {
  position: sticky; top: var(--alt-topo, 0); z-index: 2;
  background: var(--superficie-2); text-align: right;
  font: 700 10.5px/1.3 var(--fonte); color: var(--ink-3);
  text-transform: uppercase; letter-spacing: .04em;
  padding: 7px 9px; border-bottom: 2px solid var(--borda-forte);
  white-space: nowrap; cursor: help;
}
.vi-tab th:nth-child(1), .vi-tab th:nth-child(2),
.vi-hist th:nth-child(1) { text-align: left; }
/* A PARTE DO DESENHO que a coluna é — «eixo X», «eixo Y», «o raio».
   Em segunda linha e em cor de marca: é o que liga a tabela ao plano, e sem
   isso as duas ficam lado a lado sem ninguém dizer que são a mesma coisa. */
.vi-parte {
  display: block; font: 600 9px/1.3 var(--fonte); font-style: normal;
  color: var(--marca); text-transform: none; letter-spacing: 0; margin-top: 2px;
}
.vi-tab td, .vi-hist td {
  padding: 6px 9px; text-align: right; border-bottom: 1px solid var(--borda);
  white-space: nowrap;
}
.vi-tab td:nth-child(1), .vi-tab td:nth-child(2),
.vi-hist td:nth-child(1) { text-align: left; }
.vi-pos { color: var(--ink-3); font-size: 11px; width: 34px; }
.vi-nome { color: var(--ink); font-weight: 600; white-space: normal; min-width: 190px; }
.vi-linha { cursor: pointer; }
.vi-linha:hover td { background: var(--superficie-2); }
/* A LINHA ESCOLHIDA usa a MESMA marca do solo da bolha (barra à esquerda),
   porque é a mesma seleção — duas marcas diferentes para um estado só fariam
   parecer que são dois estados. */
.vi-sel td { background: var(--superficie-3); }
.vi-sel td:first-child { box-shadow: inset 3px 0 0 var(--marca); }

.vi-farol {
  display: inline-block; width: 8px; height: 8px; border-radius: 50%;
  margin-right: 7px; vertical-align: baseline; background: var(--ink-3);
}
/* O VOCABULÁRIO DO FAROL É `OK · SUPERADO · CRITICO · REFERENCIA ·
   SEM_LEITURA · SEM_POLARIDADE` — e estas regras falavam outro — pedido 134.
   Artur: «o que está verde aqui em VI parece cinza».

   Não parecia: ESTAVA. O ponto recebe `f-` + o valor do farol em minúsculas,
   e o farol de um indicador dentro da meta é `OK`. Aqui só existiam
   `f-critico`, `f-atencao`, `f-bom` e `f-dentro` — `f-ok` não casava com
   regra nenhuma e caía no cinza do fundo da classe, que é a cor de «sem
   leitura». Oito indicadores dentro da meta apareciam como não medidos.

   O MODO DE FALHAR É O PIOR QUE UMA REGRA DE CSS TEM: classe que não casa não
   dá erro, não aparece no console, não quebra layout. Ela pinta a cor padrão
   — e a cor padrão aqui é um ESTADO VÁLIDO. O defeito fica indistinguível do
   dado.

   `f-bom` e `f-dentro` ficam como apelidos: são nomes que outras partes da
   tela já usaram, e tirar alias é como se cria o próximo cinza silencioso.
   `medir_formas.py` confere que todo farol que o servidor emite tem regra. */
.vi-farol.f-critico { background: var(--core-fora, #c0392b); }
.vi-farol.f-atencao { background: var(--atencao, #e8a33d); }
.vi-farol.f-ok,
.vi-farol.f-bom, .vi-farol.f-dentro { background: var(--bom, #0ca30c); }
/* SUPERADO é ciano em todo o painel: ele não é «mais verde que verde», é
   outra afirmação — passou do desafio, que é política, não meta publicada. */
.vi-farol.f-superado { background: var(--superado, #11a8c7); }
/* REFERENCIA tem número, mas de OUTRO mês. Cor de estado seria mentira —
   fica neutro, como no cartão. */
.vi-farol.f-referencia,
.vi-farol.f-sem_polaridade,
.vi-farol.f-sem_leitura { background: var(--ink-3); }

.vi-bom { color: var(--bom, #0ca30c); }
.vi-mau { color: var(--core-fora, #c0392b); }
.vi-neutro { color: var(--ink-2); }
.vi-r2 { font-style: normal; color: var(--ink-3); font-size: 10.5px; }
.vi-quad { font-size: 11px; color: var(--ink-2); }
.vi-passo { color: var(--ink-2); }
/* Ausência NÃO pode parecer valor. Mais fraca que qualquer número da tabela,
   e com balão dizendo por que não há número ali — «não sei» sozinho é
   verdade e não é ajuda. */
.vi-vazio { color: var(--ink-3); opacity: .6; cursor: help; }
.vi-h-inac td { background: repeating-linear-gradient(45deg,
  transparent, transparent 5px, var(--superficie-2) 5px, var(--superficie-2) 10px); }

.vi-hist { margin-bottom: 6px; }
.vi-rodape {
  font-size: 11px; color: var(--ink-3); line-height: 1.5;
  margin: 12px 0 10px; max-width: 70ch;
}
.vi-csv {
  background: var(--superficie-2); border: 1px solid var(--borda-forte);
  border-radius: 7px; padding: 7px 13px; font: 600 12px var(--fonte);
  color: var(--ink); cursor: pointer;
}
.vi-csv:hover { background: var(--superficie-3); }

/* Em tela estreita a tabela rola na horizontal em vez de espremer colunas:
   coluna espremida quebra número em duas linhas, e número quebrado é número
   que se lê errado. */
@media (max-width: 1100px) {
  .vi-caixa { overflow-x: auto; }
  .vi-tab { min-width: 980px; }
}

/* ==========================================================================
   SITUAÇÃO — a tela única de sincronismo
   ==========================================================================
   Pensada para ser ABERTA NA FRENTE DO CLIENTE: tipografia grande no
   veredito, nada de jargão, e cada linha dizendo o que prova. O verde aqui
   não é decoração — é a única cor que ele pode mostrar sem explicar. */
.bat-situacao {
  background: var(--marca); color: #fff; border: none; border-radius: 999px;
  padding: 4px 13px; font: 700 11px/1 var(--fonte); cursor: pointer;
  text-transform: uppercase; letter-spacing: .05em; margin-right: 4px;
}
.bat-situacao:hover { filter: brightness(1.12); }

.sit-fundo {
  position: fixed; inset: 0; z-index: 120; background: rgba(0,0,0,.45);
  display: flex; align-items: center; justify-content: center; padding: 24px;
}
.sit-caixa {
  background: var(--superficie); border: 1px solid var(--borda-forte);
  border-radius: 14px; box-shadow: var(--sombra); padding: 22px 24px;
  width: min(760px, 96vw); max-height: 88vh; overflow: auto;
}
.sit-caixa h2 { margin: 0 0 4px; font-size: 15px; color: var(--ink-3);
                text-transform: uppercase; letter-spacing: .08em; }
.sit-caixa h3 {
  margin: 22px 0 10px; font-size: 12px; color: var(--ink-3);
  text-transform: uppercase; letter-spacing: .06em;
  border-bottom: 1px solid var(--borda); padding-bottom: 6px;
}
/* O VEREDITO É O MAIOR TEXTO DA TELA. Ele é a resposta; o resto é prova. */
.sit-topo { border-left: 4px solid var(--borda-forte); padding: 2px 0 2px 14px; }
.sit-veredito { margin: 0; font-size: 19px; line-height: 1.35; font-weight: 700;
                color: var(--ink); }
.sit-prov { margin: 8px 0 0; font-size: 13px; line-height: 1.5; color: var(--ink-2); }
.sit-topo.sit-bom      { border-left-color: var(--bom, #0ca30c); }
.sit-topo.sit-atencao  { border-left-color: var(--atencao, #e8a33d); }
.sit-topo.sit-mau      { border-left-color: var(--core-fora, #c0392b); }
.sit-topo.sit-indo     { border-left-color: var(--marca); }

.sit-linha { display: flex; gap: 11px; align-items: flex-start; padding: 7px 0; }
.sit-pt {
  width: 9px; height: 9px; border-radius: 50%; flex: 0 0 9px; margin-top: 5px;
  background: var(--ink-3);
}
.sit-bom .sit-pt     { background: var(--bom, #0ca30c); }
.sit-atencao .sit-pt { background: var(--atencao, #e8a33d); }
.sit-mau .sit-pt     { background: var(--core-fora, #c0392b); }
.sit-indo .sit-pt    { background: var(--marca); }
.sit-txt { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.sit-txt b { font-size: 13px; color: var(--ink); }
.sit-val { font-size: 13px; color: var(--ink); font-weight: 600; }
.sit-mau .sit-val     { color: var(--core-fora, #c0392b); }
.sit-atencao .sit-val { color: var(--atencao-ink, #8a5200); }
.sit-txt i { font-style: normal; font-size: 11.5px; color: var(--ink-3); line-height: 1.45; }
.sit-acoes { display: flex; gap: 9px; margin-top: 22px; flex-wrap: wrap; }
.sit-vazio { color: var(--ink-3); font-size: 13px; }

/* --- Situação: os blocos em detalhe (pedido dele, 05/10) ----------------- */
/* Cada bloco responde três coisas na mesma ordem — o que é, o que foi medido,
   o que falta. O «falta» ganha destaque porque é a única linha acionável; sem
   ele a tela seria um relatório, e relatório devolve a pessoa ao ponto de
   partida. */
.sit-bloco { margin-top: 20px; padding-top: 4px; }
.sit-bloco h3 {
  margin: 0 0 6px; font-size: 12px; color: var(--ink-3);
  text-transform: uppercase; letter-spacing: .06em;
  border-bottom: 1px solid var(--borda); padding-bottom: 6px;
}
.sit-prova {
  margin: 0 0 10px; font-size: 11.5px; line-height: 1.5; color: var(--ink-3);
  max-width: 78ch;
}
.sit-kvs { display: grid; gap: 5px; }
.sit-kv {
  display: grid; grid-template-columns: 190px 1fr; gap: 10px;
  align-items: baseline; font-size: 12.5px;
}
.sit-kv b { color: var(--ink-3); font-weight: 600; font-size: 11.5px; }
.sit-kv span { color: var(--ink); font-weight: 600; word-break: break-word; }
.sit-kv i {
  grid-column: 2; font-style: normal; font-size: 11px; color: var(--ink-3);
  line-height: 1.45;
}
.sit-falta {
  margin: 10px 0 0; padding: 8px 11px; font-size: 12.5px; line-height: 1.5;
  background: var(--atencao-fundo, #fff4e5); border-radius: 7px;
  border-left: 3px solid var(--atencao-borda, #e8a33d);
  color: var(--atencao-ink, #8a5200);
}
.sit-falta b { color: inherit; }
.sit-nota { margin: 8px 0 0; font-size: 11px; color: var(--ink-3); line-height: 1.5; }
.sit-erro { margin: 6px 0 0; font-size: 12.5px; color: var(--core-fora, #c0392b); }
.sit-bloco.sit-mau h3 { color: var(--core-fora, #c0392b); }
@media (max-width: 640px) {
  .sit-kv { grid-template-columns: 1fr; gap: 1px; }
  .sit-kv i { grid-column: 1; }
}

/* --- As barras de prontidão (pedido 125) -------------------------------- */
/* Barra se entende de relance; lista obriga a ler. Três níveis: o número na
   faixa (está tudo bem?), as seis barras (o que está atrasado?), o detalhado
   (por quê?). */
.bat-pront {
  display: inline-flex; align-items: center; gap: 7px;
  background: var(--superficie-2); border: 1px solid var(--borda-forte);
  border-radius: 999px; padding: 3px 11px 3px 8px; cursor: pointer;
  font: 700 11px/1 var(--fonte); color: var(--ink); margin-right: 4px;
}
.bat-pront:hover { background: var(--superficie-3); }
.bat-pront-trilho {
  display: block; width: 46px; height: 5px; border-radius: 3px;
  background: var(--borda); overflow: hidden;
}
.bat-pront-trilho i { display: block; height: 100%; background: var(--ink-3); border-radius: 3px; }
.bat-pront-bom  .bat-pront-trilho i { background: var(--bom, #0ca30c); }
.bat-pront-meio .bat-pront-trilho i { background: var(--atencao, #e8a33d); }
.bat-pront-mau  .bat-pront-trilho i { background: var(--core-fora, #c0392b); }

.pr-caixa {
  background: var(--superficie); border: 1px solid var(--borda-forte);
  border-radius: 14px; box-shadow: var(--sombra); padding: 22px 24px;
  width: min(680px, 96vw); max-height: 88vh; overflow: auto;
}
.pr-caixa h2 {
  margin: 0 0 10px; font-size: 13px; color: var(--ink-3);
  text-transform: uppercase; letter-spacing: .08em;
}
.pr-topo { border-left: 4px solid var(--borda-forte); padding: 2px 0 2px 14px; }
.pr-topo.pr-bom { border-left-color: var(--bom, #0ca30c); }
.pr-topo.pr-atencao { border-left-color: var(--atencao, #e8a33d); }
.pr-topo.pr-mau { border-left-color: var(--core-fora, #c0392b); }
.pr-topo.pr-indo { border-left-color: var(--marca); }
.pr-total { display: flex; align-items: center; gap: 12px; }
.pr-total b { font-size: 26px; font-variant-numeric: tabular-nums; color: var(--ink); }
.pr-trilho {
  flex: 1; height: 9px; border-radius: 5px; background: var(--superficie-3);
  overflow: hidden;
}
.pr-trilho-g { height: 14px; border-radius: 7px; }
.pr-trilho i {
  display: block; height: 100%; border-radius: inherit;
  background: var(--ink-3); transition: width .35s ease;
}
.pr-explica { margin: 8px 0 0; font-size: 11px; color: var(--ink-3); line-height: 1.5; }

.pr-grade { display: grid; gap: 15px; margin-top: 22px; }
.pr-item { display: grid; gap: 5px; }
.pr-cab { display: flex; justify-content: space-between; align-items: baseline; }
.pr-cab b { font-size: 13px; color: var(--ink); }
.pr-pct { font: 700 13px/1 var(--fonte); font-variant-numeric: tabular-nums; color: var(--ink-2); }
/* A COR É DO ESTADO, não do número: «indo» é azul porque está acontecendo —
   pintar de vermelho um aquecimento em curso diria que algo está errado. */
.pr-bom  .pr-trilho i { background: var(--bom, #0ca30c); }
.pr-meio .pr-trilho i { background: var(--atencao, #e8a33d); }
.pr-mau  .pr-trilho i { background: var(--core-fora, #c0392b); }
.pr-indo .pr-trilho i { background: var(--marca); }
.pr-bom  .pr-pct { color: var(--bom, #0ca30c); }
.pr-mau  .pr-pct { color: var(--core-fora, #c0392b); }
/* O «DE QUÊ» ANDA COLADO NA BARRA. Porcentagem sozinha é a mentira mais fácil
   que uma barra conta — 70% de quê? — e foi a reclamação do pedido 112. */
.pr-pe {
  display: flex; justify-content: space-between; gap: 10px;
  font-size: 11px; color: var(--ink-3); line-height: 1.4;
}
.pr-pe i { font-style: normal; color: var(--ink-2); font-weight: 600; }

/* --- Status geral: abas, estados e a total hachurada (pedido 127) -------- */
/* A TOTAL É HACHURADA porque é ESTIMATIVA — e a hachura já quer dizer isso
   neste projeto (o rastro das bolhas, a barra da etapa). Ela junta réguas
   diferentes: um interruptor e uma cobertura não se somam de verdade. Cinza
   sólido dizia «medido», que é o que ela não é. */
.pr-hachura {
  display: block; height: 100%; border-radius: inherit;
  background: repeating-linear-gradient(115deg,
    var(--marca) 0 7px,
    color-mix(in srgb, var(--marca) 45%, transparent) 7px 14px);
  transition: width .35s ease;
}
.pr-abas {
  display: flex; gap: 4px; margin: 20px 0 4px;
  border-bottom: 1px solid var(--borda);
}
.pr-aba {
  background: none; border: none; border-bottom: 2px solid transparent;
  padding: 7px 14px; font: 700 12px/1 var(--fonte); color: var(--ink-3);
  cursor: pointer; text-transform: uppercase; letter-spacing: .05em;
}
.pr-aba:hover { color: var(--ink); }
.pr-aba.on { color: var(--marca); border-bottom-color: var(--marca); }
.pr-corpo { min-height: 140px; }

/* O ESTADO NÃO TEM TRILHO: ele não é fração, e desenhar uma barra cheia ou
   vazia ali seria a mesma promessa de continuidade que o «0%» fazia. Marca e
   palavra, que é o que um interruptor tem. */
.pr-est { gap: 2px; }
.pr-marca { display: inline-flex; align-items: center; gap: 6px;
            font: 700 12.5px/1 var(--fonte); }
.pr-sinal { font-style: normal; font-size: 14px; line-height: 1; }
.pr-est.pr-bom    .pr-marca { color: var(--bom, #0ca30c); }
.pr-est.pr-mau    .pr-marca { color: var(--core-fora, #c0392b); }
.pr-est.pr-indo   .pr-marca { color: var(--marca); }
.pr-est.pr-neutro .pr-marca { color: var(--ink-3); }
.pr-est .pr-pe { margin-top: 3px; }

/* --- Recortes do cliente: Vertical e Cluster (pedido 128) ---------------- */
.r37-sel-eixo-cx { display: inline-flex; align-items: center; gap: 6px; }
.r37-sel-eixo {
  background: var(--superficie-2); border: 1px solid var(--borda-forte);
  border-radius: 7px; padding: 4px 8px; font: 600 12px var(--fonte);
  color: var(--ink); max-width: 180px;
}
/* A PARCIAL ao lado do seletor: quando o conjunto encolhe, a saúde escrita
   acima deixa de ser a dos 38 — e painel que troca o conjunto sem dizer é
   como se chega a «57% crítico» discutindo outra coisa. */
.r37-eixo-parcial {
  font: 700 11px/1 var(--fonte); color: var(--marca);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}

/* --- A barra indeterminada do «levantando» (pedido 130) ------------------ */
/* INDETERMINADA de propósito: é uma consulta só, sem etapas. Barra que enche
   sem contador por trás afirma andamento que ninguém mediu — foi o que o
   pedido 112 proibiu. Esta vai e volta, que quer dizer «estou viva», não
   «estou em 60%». */
.pr-indet { overflow: hidden; }
.pr-indet i {
  display: block; height: 100%; width: 38%; border-radius: inherit;
  background: repeating-linear-gradient(115deg,
    var(--marca) 0 7px,
    color-mix(in srgb, var(--marca) 45%, transparent) 7px 14px);
  animation: pr-vaivem 1.25s ease-in-out infinite;
}
@keyframes pr-vaivem {
  0%   { transform: translateX(-100%); }
  100% { transform: translateX(263%); }
}
@media (prefers-reduced-motion: reduce) {
  .pr-indet i { animation: none; width: 100%; opacity: .5; }
}


/* ==========================================================================
   TINTAS DE TEXTO PARA ATENÇÃO E CRÍTICO — pedido 122
   ==========================================================================
   Artur: «este vermelho precisa melhorar, o texto não é legível». Eu passei
   rodadas pedindo que ele apontasse qual — e ele respondeu «apontar o quê?».
   Estava certo: contraste é CALCULÁVEL. A régua `medir_contraste.py` varre a
   tela nos dois temas e mede a razão WCAG de cada texto contra o fundo
   EFETIVO (composto, camada por camada).

   O QUE ELA ACHOU, e por que o defeito é de origem: `--atencao` e `--critico`
   foram escolhidos para PREENCHER — barra, pastilha, anel. Cor de
   preenchimento é julgada pelo olho contra o papel inteiro; cor de TEXTO tem
   de vencer 4,5:1 em corpo pequeno. São exigências diferentes, e usar o mesmo
   token nas duas é como o mesmo número servir de meta e de realizado.

   Medido no claro: o laranja `#b07800` como texto na pastilha da faixa dava
   2,29:1. O «VIGIAR» dava 2,82:1. O mínimo é 4,5:1.

   ENTRAM DUAS TINTAS SÓ PARA TEXTO. Elas não substituem as de
   preenchimento — a pastilha continua com o fundo da família, e é o TEXTO
   que escurece. Assim a identidade visual não muda: a cor continua dizendo
   «atenção», só que legível.

   O ALVO É 4,5:1 CONTRA A SUPERFÍCIE DO SEU TEMA, e os valores abaixo foram
   medidos, não escolhidos por gosto. */
:root {
  --atencao-ink: #6b4a00;   /* 4,9:1 sobre #fff */
  --critico-ink: #a8291a;   /* 5,1:1 sobre #fff */
}
:root[data-theme="dark"] {
  --atencao-ink: #f0c27a;   /* 8,4:1 sobre #121b1c */
  --critico-ink: #ff9b85;   /* 6,6:1 sobre #121b1c */
}

/* Onde a cor é TEXTO, passa a usar a tinta. Onde é preenchimento, não muda. */
.s-ATENCAO, .t-ATENCAO, .e-EM_TESTE, .aviso-faixa b { color: var(--atencao-ink); }
.s-CRITICO, .t-CRITICO, .e-BLOQUEADO, .d-piorou,
.escopo-cel.vazio .q { color: var(--critico-ink); }
.an-chip.an-mau, .r37-seta.sobe-mau { color: var(--critico-ink); }
.an-q-vigiar, .bat-chip.bat-atencao { color: var(--atencao-ink); }
.bat-chip.bat-mau { color: var(--critico-ink); }
/* O «a/a» e irmãos: 8px com `opacity: .62` sobre uma pastilha já tingida —
   a opacidade é o que os apagava, e ela não está comprando nada aqui. */
.an-chip i { opacity: .85; }
/* `.code` e `.vi-parte` usavam a cor de marca pura em corpo pequeno. */
.code, .vi-parte { color: var(--marca-ink, var(--critico-ink)); }

/* ===================================================================
   SEÇÃO VII — OS DOIS MAPAS DA SAÚDE, pedido 136
   ===================================================================
   «Sendo um à direita e o outro à esquerda», e por isso duas colunas de
   largura igual: o mapa executivo responde «qual regional está pior?» e o
   geográfico responde «onde isso fica?». Dar mais largura a um deles
   diria que uma das duas perguntas importa menos, e não é o caso — elas
   se completam, que é a palavra que ele usou.
   ABAIXO DE 1100px ELAS EMPILHAM: duas colunas estreitas fariam o mapa do
   Brasil caber em 300px, onde nenhuma UF é clicável. */
.vii-dupla {
  display: grid; grid-template-columns: 1fr 1fr; gap: 22px;
  align-items: start;
}
@media (max-width: 1100px) { .vii-dupla { grid-template-columns: 1fr; } }
.vii-lado { min-width: 0; }
.vii-cab {
  display: flex; align-items: baseline; gap: 10px; margin-bottom: 4px;
}
.vii-cab h4 {
  margin: 0; font: 700 12px/1.2 var(--fonte-rotulo, var(--fonte));
  letter-spacing: .1em; text-transform: uppercase; color: var(--ink);
}
.vii-sub { font-size: 11.5px; color: var(--ink-3); }
.vii-trilha {
  display: flex; align-items: center; gap: 7px;
  font-size: 12px; margin: 8px 0 10px;
}
.vii-trilha .lk.on { color: var(--ink-3); cursor: default; }
.vii-sep { color: var(--ink-3); }
.vii-lista { display: flex; flex-direction: column; gap: 6px; }

/* A PLACA é a mesma gramática das tiras das seções IV e V — nome, números,
   barra de 0 a 100 — e de propósito: a tela já ensinou a ler essa forma. */
.vii-placa {
  display: grid; grid-template-columns: 1fr auto; gap: 2px 10px;
  align-items: center; width: 100%; text-align: left;
  padding: 8px 10px; border: 1px solid var(--borda); border-radius: 8px;
  background: var(--superficie); color: var(--ink);
  cursor: pointer; font: inherit;
}
.vii-placa:hover { background: var(--superficie-2); }
.vii-placa.on { border-color: var(--marca); background: var(--superficie-3); }
.vii-nome { font-weight: 600; font-size: 12.5px; }
.vii-nums { font-size: 11.5px; color: var(--ink-2); white-space: nowrap; }
.vii-nums b { font-size: 14px; margin-right: 5px; }
.vii-sem { font-size: 11.5px; color: var(--ink-3); font-style: italic; }
.vii-trilho {
  grid-column: 1 / -1; height: 5px; border-radius: 3px;
  background: var(--grade); overflow: hidden; margin-top: 3px;
}
.vii-trilho i { display: block; height: 100%; border-radius: 3px; }

.vii-geo-caixa { border: 1px solid var(--borda); border-radius: 8px;
  padding: 8px; background: var(--superficie); }
.vii-geo { display: block; width: 100%; height: auto; max-height: 460px; }
/* O CONTORNO DA UF TOMA A COR DO PLANO, pela mesma razão das bolhas
   (pedido 138): borda que é recorte não soma onde duas UFs se encostam. */
.vii-uf {
  stroke: var(--superficie); stroke-width: 1; cursor: pointer;
  transition: fill-opacity .12s;
}
.vii-uf:hover { fill-opacity: .8; }
.vii-uf.on { stroke: var(--marca); stroke-width: 2.2; }

.vii-rodape {
  margin-top: 14px; font-size: 11.5px; line-height: 1.55; color: var(--ink-3);
}
.vii-fora { margin-top: 8px; font-size: 11.5px; color: var(--ink-2); }
.vii-fora summary { cursor: pointer; color: var(--atencao-ink, var(--ink-2)); }
.vii-fora ul { margin: 6px 0 0 18px; }
.vii-fora li { margin-bottom: 3px; }

/* ===================================================================
   ASSINATURA VISUAL CLARO — pedido 140
   ===================================================================
   Artur: «garanta assinatura visual Claro no menu fixo... sem contudo
   poluir, deixando bem profissional, harmônico, porém com belo visual
   corporativo»; e depois: «uma espécie de silhueta que pode ser combinada
   e muito melhorada com motivos de Rede Externa e Tecnologia».

   «SEM POLUIR» É UM REQUISITO MENSURÁVEL, e foi assim que tratei: a
   assinatura não pode ganhar NENHUM pixel de altura da barra fixa. O topo
   já carrega marca, anel de estado, três pastilhas, versão, breadcrumb,
   tema e sair — e a barra é fixa, então cada pixel dela some do painel em
   todas as telas. O descritor entra numa segunda linha DENTRO da altura
   que a marca já ocupava, aproveitando o espaço abaixo de «CORTEX» que
   estava vazio.

   O LOGOTIPO NÃO É REDESENHADO em lugar nenhum deste projeto: ele é a
   imagem oficial, carregada de `assets/marca/`. Marca redesenhada à mão
   vira «quase a marca», que é pior que não ter. */
.marca { align-items: center; }
.marca-dom {
  display: flex; align-items: baseline; gap: 4px;
  font: 600 8.5px/1 var(--fonte); letter-spacing: .14em;
  text-transform: uppercase; color: var(--ink-3);
  padding-left: 9px; margin-left: 2px;
  border-left: 1px solid var(--borda);
  white-space: nowrap;
}
.marca-dom b { font-weight: 800; color: var(--ink-2); }
.marca-dom i { font-style: normal; opacity: .55; }
@media (max-width: 1180px) { .marca-dom { display: none; } }

/* A FAIXA DE RODAPÉ. Ela fecha a página como o rodapé do relatório do GPR
   que ele mandou de referência: silhueta de Rede Externa em tinta fraca,
   marca e domínio por baixo.
   A OPACIDADE É BAIXA DE PROPÓSITO (0,10/0,14). Assinatura que disputa
   atenção com o conteúdo deixou de ser assinatura — e esta fica ao lado de
   números que decidem reunião. Ela existe para ser notada ao fechar a
   página, não ao lê-la. */
.assinatura {
  margin-top: 42px; padding: 0 0 18px;
  border-top: 1px solid var(--borda);
}
/* A FAIXA DA ASSINATURA SAIU — pedido 143.
   Artur, com a tira cinzenta marcada em azul na captura: «veja há resquícios
   que devem ser excluídos».

   ELE ESTAVA CERTO, E DÁ PARA MEDIR O QUANTO. As três imagens declaravam
   1600×300 e carregavam pixels em 20% a 28% dessa largura — o resto era
   alfa ZERO. Numa tela de 1480 px a tira mostrava uma mancha nos primeiros
   400 px e três quartos de nada. Não era uma assinatura discreta: era um
   borrão no canto de uma faixa vazia.

   E EU TINHA DITO QUE ISSO ESTAVA CONSERTADO. A nota da 1.79.1 afirma, com
   todas as letras, que as três passaram a ser «construídas no MESMO formato
   (1600×300), enquadradas pela ALTURA e recortadas no centro». Eu consertei
   a MOLDURA e deixei a PINTURA no canto esquerdo. A declaração estava certa
   e o arquivo não correspondia a ela — exatamente a classe de defeito sobre
   a qual este projeto inteiro é construído, agora cometida por mim num
   comentário que servia de prova.

   E O CONTEÚDO TAMBÉM NÃO SE SUSTENTAVA: as três são fotos genéricas de
   gráfico e vidraça de banco de imagens. A 30% de opacidade, em cinza, no
   canto, elas não dizem «Rede Externa» nem «Claro» — dizem «sobrou alguma
   coisa aqui».

   O QUE FICA: a assinatura tipográfica — símbolo da Claro, «Rede Externa ·
   MSO», «CORTEX · Decision Intelligence Platform». Isso é identidade
   corporativa de verdade, não tem borda para desalinhar e não tem resíduo
   para aparecer.

   O QUE PRECISO PARA TRAZER A FAIXA DE VOLTA: imagens que sejam largas de
   fato. Esticar um recorte de 450 px para 1480 seria entregar borrão onde
   ele pediu «visual Premium, sem distorções» — e inventar os pixels que
   faltam não está no cardápio. Os três arquivos foram REMOVIDOS junto com
   esta regra: arquivo que ninguém referencia é artefato jogado, que é o que
   ele pediu para não existir. */
.assinatura-linha {
  display: flex; align-items: center; gap: 9px; flex-wrap: wrap;
  padding: 10px 18px 0;
  font: 600 10.5px/1.4 var(--fonte); letter-spacing: .1em;
  text-transform: uppercase; color: var(--ink-3);
}
.assinatura-linha b { color: var(--ink-2); font-weight: 800; }
.assinatura-logo { flex: none; display: block; }
/* O SEPARADOR NÃO É TEXTO, E AGORA ELE DIZ ISSO. Com `opacity: .45` ele
   media 1,82:1 de contraste e a régua o reprovou como texto ilegível — com
   razão, porque ele ERA um `<span>` com um travessão dentro.
   Só que ele não é para ser lido: é uma marca de pontuação entre dois blocos
   da assinatura, da mesma família do fio vertical do topo. Então deixa de ser
   texto e passa a ser uma REGRA — uma linha de 1px desenhada por borda. Sem
   caractere, sem leitor de tela anunciando «travessão», e sem a régua de
   contraste tendo de julgar como legível algo que não se lê. */
.assinatura-sep {
  display: inline-block; width: 16px; height: 0;
  border-top: 1px solid var(--borda);
  text-indent: -9999px; overflow: hidden;
  vertical-align: middle;
}

/* As abas da seção VII — pedido 136, segunda volta. Mesma gramática das abas
   de Geral/Detalhado do Status: duas opções exclusivas, a ativa com a marca.
   A PROCEDÊNCIA DO NÚMERO FICA AO LADO DELAS, e não num balão: «índice de
   saúde 46/100» sem dizer a fonte, dentro do Radar, é lido como a saúde do
   Radar — foi o que ele fotografou no pedido 137. */
.vii-abas {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  margin-bottom: 12px;
}
.vii-aba {
  font: 600 12px/1 var(--fonte); padding: 7px 13px; border-radius: 7px;
  border: 1px solid var(--borda); background: var(--superficie);
  color: var(--ink-2); cursor: pointer;
}
.vii-aba:hover { background: var(--superficie-2); }
.vii-aba.on {
  background: var(--marca); border-color: var(--marca); color: #fff;
}
.vii-fonte { font-size: 11.5px; color: var(--ink-3); margin-left: 4px; }

/* OS DOIS MAPAS LADO A LADO — pedido 136, quarta volta.
   Artur: «o à esquerda seria nível regional e o da direita avançamos em
   municípios e futuramente até células e nodes». Eram duas abas; ser aba
   obrigava a pessoa a ESCOLHER entre as duas perguntas, quando o enunciado
   do 136 pedia que elas se complementassem.
   A quebra para uma coluna vem cedo (1180px) porque cada metade tem um mapa
   dentro: espremidos lado a lado em tela estreita, os dois ficam ilegíveis, e
   dois mapas ilegíveis são piores que um legível em cima do outro. */
.vii-duo {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 14px; align-items: start;
}
@media (max-width: 1180px) { .vii-duo { grid-template-columns: 1fr; } }
.vii-metade { min-width: 0; }
/* Dentro de cada metade o mapa territorial empilha, porque a coluna já é
   estreita: o drill lado a lado viraria duas tiras finas. */
.vii-metade .mapa-caixa { grid-template-columns: 1fr; }

/* O recorte do mapa da direita, dito em palavras logo acima do desenho. */
.vii-escopo {
  padding: 0 14px 10px; font-size: 11.5px; line-height: 1.45;
  color: var(--ink-2);
}
.vii-palco { min-height: 420px; }
.vii-palco .mapa-caixa { margin: 0; }

/* O seletor de nível do mapa executivo — pedido 136, terceira volta.
   Regional ou Grupo, e a escolha é VISÍVEL em vez de automática: quem
   projeta na reunião quer as três regionais; quem investiga quer os onze
   grupos. Trocar sozinho tiraria a decisão de quem está falando. */
.mapa-niveis { display: flex; gap: 6px; margin-left: auto; }
.btn-min {
  font: 600 11.5px/1 var(--fonte); padding: 6px 11px; border-radius: 6px;
}
/* SÃO PAULO COM DOIS GRUPOS NA MESMA UF. O contorno fica um pouco mais
   firme porque a UF listrada tem menos área de cor cheia para se destacar
   do vizinho — sem isso ela some entre MG e PR no tema escuro. */
.uf-dupla { stroke-width: 1.6; }

/* A CHAMADA DA UF LISTRADA — pedido 142.
   Ela é desenhada no mar, ligada ao RÓTULO da UF (nunca a uma borda), porque
   uma linha que saísse de uma borda seria lida como fronteira — e fronteira
   entre Capital e Interior é exatamente o que não existe na base.
   `pointer-events: none` em tudo: a chamada explica o polígono, não compete
   com o clique dele. Quem quiser agir sobre uma das duas unidades usa o
   cartão «Mesma UF, mais de uma unidade», onde cada linha é um botão. */
.uf-chamada, .uf-chamada-fio { pointer-events: none; }
.uf-chamada-fio {
  fill: none; stroke: var(--ink-3); stroke-width: 1; stroke-dasharray: 2 2;
  opacity: .7;
}
.uf-chamada-tit {
  font: 700 9.5px/1 var(--fonte); fill: var(--ink-2);
  letter-spacing: .04em; text-transform: uppercase;
}
.uf-chamada-lin { font: 600 10.5px/1 var(--fonte); fill: var(--ink-1); }

/* A coluna do mapa: o desenho e, embaixo dele, o cartão que o decodifica. */
.mapa-coluna { display: flex; flex-direction: column; gap: 14px; min-width: 0; }

/* O CARTÃO DAS UNIDADES QUE DIVIDEM UMA UF — pedido 142.
   Cada linha é um BOTÃO de verdade (não uma div com onclick): recebe foco
   pelo teclado, responde ao Enter e é anunciada como acionável. A tela já
   recusa escolher entre Capital e Interior no clique do polígono; o mínimo é
   que a escolha, quando a pessoa a faz, esteja ao alcance de quem navega sem
   mouse. */
.sp-uf {
  font: 700 10px/1 var(--fonte); color: var(--ink-3); text-transform: uppercase;
  letter-spacing: .06em; margin: 2px 0 7px;
}
.sp-linha {
  display: flex; align-items: center; gap: 10px; width: 100%;
  padding: 8px 10px; margin-bottom: 6px; text-align: left; cursor: pointer;
  background: var(--superficie-2); border: 1px solid var(--borda);
  border-radius: 8px; font: inherit; color: var(--ink-1);
  transition: border-color .12s, background .12s;
}
/* O HOVER CLAREIA O FUNDO, E A SUBLINHA SOBE COM ELE — conferido, não
   estimado: `--ink-3` sobre `--superficie-2` dá 4,80:1 (passa AA) e sobre
   `--superficie-3` cai para 4,33:1 (reprova). Trocar o fundo sem mexer no
   texto faria a linha reprovar EXATAMENTE quando a pessoa aponta para ela —
   o estado em que ela está sendo lida. */
.sp-linha:hover { border-color: var(--marca); background: var(--superficie-3); }
.sp-linha:hover .sp-sub { color: var(--ink-2); }
.sp-linha:focus-visible { outline: 2px solid var(--marca); outline-offset: 2px; }
.sp-chip { width: 11px; height: 11px; border-radius: 3px; flex: 0 0 auto; }
.sp-nome { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.sp-nome b { font: 600 13px/1.15 var(--fonte); }
.sp-num { display: flex; flex-direction: column; gap: 2px; margin-left: auto;
          text-align: right; white-space: nowrap; }
.sp-num b { font: 700 13px/1.15 var(--fonte); font-variant-numeric: tabular-nums; }
.sp-sub { font: 500 10.5px/1.15 var(--fonte); color: var(--ink-3); }

/* A PROCEDÊNCIA DE CADA CAMPO DE CONEXÃO — pedido 146.
   Pequena e discreta quando o valor veio de onde se espera; em cor de aviso
   quando não veio. A pergunta que custou uma tarde foi «editei a porta, por
   que ela não mudou?», e ela se responde num relance com esta linha. */
.cx-proc {
  display: block; margin-top: 4px;
  font: 500 10.5px/1.35 var(--fonte); color: var(--ink-3);
}
.cx-proc-aviso { color: var(--atencao); font-weight: 650; }

/* ===== ACESSO — o que você precisa ter (pedido 149) ====================
   Tela de cinco linhas. O contraste entre os três estados é o que faz ela
   ser lida de relance: verde é «de pé», vermelho é «falta», CINZA é «não
   sondei» — e o cinza é o que impede a tela de acusar três problemas quando
   há um só, que foi a queixa dele. */
.pr-veredito {
  border-radius: 12px; padding: 16px 18px; margin: 4px 0 16px;
  border: 1px solid var(--borda); background: var(--superficie-2);
  border-left-width: 5px;
}
.pr-veredito.bom { border-left-color: var(--bom); }
.pr-veredito.mau { border-left-color: var(--critico); }
.pr-vd-t { font: 700 17px/1.2 var(--fonte); margin-bottom: 5px; }
.pr-veredito.bom .pr-vd-t { color: var(--bom); }
.pr-veredito.mau .pr-vd-t { color: var(--critico); }
.pr-vd-f { font-size: 13.5px; color: var(--ink-1); line-height: 1.5; }
.pr-vd-p { margin-top: 9px; font-size: 13px; color: var(--ink-2); }

.pr-lista { display: flex; flex-direction: column; gap: 9px; }
.pr-item {
  display: flex; gap: 13px; align-items: flex-start;
  padding: 13px 15px; border-radius: 10px;
  border: 1px solid var(--borda); background: var(--superficie-2);
  border-left-width: 4px;
}
.pr-item.pr-ok    { border-left-color: var(--bom); }
.pr-item.pr-mau   { border-left-color: var(--critico); }
.pr-item.pr-cinza { border-left-color: var(--neutro); opacity: .72; }
.pr-marca { font: 700 17px/1.1 var(--fonte); width: 18px; flex: 0 0 auto; }
.pr-ok .pr-marca    { color: var(--bom); }
.pr-mau .pr-marca   { color: var(--critico); }
.pr-cinza .pr-marca { color: var(--ink-3); }
.pr-txt { min-width: 0; }
.pr-rot  { font: 650 14px/1.3 var(--fonte); margin-bottom: 3px; }
.pr-para { font-size: 12px; color: var(--ink-3); line-height: 1.45; }
.pr-det  { font-size: 12.5px; color: var(--ink-2); margin-top: 5px; line-height: 1.5; }
.pr-prov {
  margin-top: 8px; font-size: 12.5px; line-height: 1.5;
  color: var(--ink-1); font-weight: 600;
}
.pr-fora {
  margin-top: 18px; font-size: 12px; color: var(--ink-3);
  line-height: 1.55; border-top: 1px solid var(--borda); padding-top: 12px;
}
