/* ============================================================
   Telas de análise
   ============================================================
   Nenhuma cor de domínio escrita aqui: tudo passa por var(--accent), que o
   [data-dominio] do body troca. A mesma folha serve às quatro áreas. */

/* ---------- A regra da dobra ----------
   TODA tela de análise cabe na janela, sem rolagem da página. Vale para as 21
   análises das quatro áreas; o Meu Perfil, que é formulário, rola normalmente.

   Isto não é obtido ajustando a altura de cada painel à mão, tela por tela —
   assim a primeira análise nova quebraria a regra sem ninguém notar. É
   estrutural:

     1. a área de conteúdo tem altura FIXA (janela menos o cabeçalho) e
        overflow hidden, então a página não tem como rolar;
     2. a grade de painéis ocupa a sobra com `flex: 1`;
     3. as linhas da grade são `1fr`, então dividem essa sobra entre si em vez
        de crescerem com o conteúdo.

   O efeito é que o painel recebe a altura disponível em vez de pedi-la. Quem
   tem conteúdo mais alto que isso rola por dentro do próprio cartão
   (painel--rolavel), que é contido e não empurra o resto da tela.

   `min-height: 0` aparece em cada nível da cadeia porque item de flex e de
   grid tem `min-height: auto` por padrão — sem zerar, o filho recusa encolher
   abaixo do próprio conteúdo e vaza para fora, que é o bug que a regra toda
   existe para evitar. */

/* A altura tem de ser limitada na cadeia INTEIRA, de fora para dentro. O .app
   nasce com `min-height: 100vh`, que deixa crescer; e o .conteudo tem `flex: 1`,
   cujo `flex-basis: 0` substitui qualquer `height` que se declare aqui. Por
   isso a trava começa no .app e desce por `min-height: 0` em cada elo. */
.app:has(.analise) {
  height: 100vh;
  /* `dvh` DEPOIS, e é o que conserta o iPhone. No Safari do iOS `100vh` é a
     altura da janela COM as barras do navegador recolhidas — um valor maior que
     a área realmente visível enquanto a barra de endereço está na tela. Como
     aqui a altura é fixa e quem rola é o `.conteudo` por dentro, o excedente
     não vira rolagem: vira conteúdo cortado nas duas pontas.

     Era o que sumia com o fim do título em cima e com a linha do rodapé de
     filtro embaixo. `dvh` acompanha a área visível de verdade; a linha anterior
     fica como reserva para quem não a conhece. */
  height: 100dvh;
}

.app:has(.analise) .principal {
  min-height: 0;
}

.conteudo:has(.analise) {
  display: flex;
  flex-direction: column;
  min-height: 0;
  overflow: hidden;
  /* O respiro generoso da área de conteúdo serve às telas de texto; numa
     análise ele custa 20px de altura que fazem falta na última linha de
     painéis. (A malha de pontos é do .conteudo, no shell.css — vale para toda
     a plataforma, não só para as análises.) */
  padding-top: 18px;
  /* Embaixo o respiro é menor: quem fecha a página é o rodapé de contexto,
     que já é texto leve e não precisa de folga para respirar. */
  padding-bottom: 8px;
}

/* O alvo que a tela redesenha fica entre o cabeçalho da análise e o fim da
   área: é ele que carrega a sobra até a .analise. */
.analise-alvo {
  flex: 1;
  min-height: 0;
}

.analise {
  display: flex;
  flex-direction: column;
  gap: 12px;
  height: 100%;
}

/* ---------- Cabeçalho da tela ---------- */
/* Uma linha só: a trilha do cabeçalho da plataforma já diz onde estamos, então
   aqui o título é discreto e divide a faixa com o filtro. */

.analise-cabecalho {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  margin-bottom: 14px;
}

.analise-titulo {
  font-size: 20px;
  font-weight: 700;
  letter-spacing: -0.02em;
}

/* Linha de apoio sob o título, por opção da tela. Só existe onde o título
   sozinho não diz de onde o conteúdo vem — em Insights, dizer que os achados
   saem das telas anteriores é o que separa análise de opinião. Sem `apoio` a
   tela nem gera este bloco, e o cabeçalho continua sendo a linha única de
   sempre. */
.analise-apoio {
  margin-top: 3px;
  font-size: 12px;
  color: var(--text-muted);
}

/* ---------- Filtro de período (hierarquia Ano › Mês) ---------- */

/* A faixa dos filtros. São dois espaços: o da esquerda é da tela (o Financeiro
   põe Empresa ali) e o da direita é do período. Quem não tem filtro próprio
   deixa a caixa vazia, e um div vazio num flex não ocupa largura nenhuma —
   por isso as telas antigas continuam com o filtro exatamente onde estava. */
.analise-filtros {
  display: flex;
  align-items: flex-end;
  gap: 10px;
  flex-shrink: 0;
}

.analise-filtro {
  position: relative;
  flex-shrink: 0;
}

.filtro-botao {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 7px 10px 7px 12px;
  font-family: inherit;
  color: var(--text-primary);
  background: var(--bg-secondary);
  border: 1px solid var(--border-color-light);
  border-radius: var(--radius-sm);
  transition: border-color var(--transition-fast), background var(--transition-fast);
}

.filtro-botao:hover,
.filtro-botao[aria-expanded="true"] {
  border-color: var(--accent);
}

.filtro-rotulo {
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--text-muted);
}

.filtro-valor {
  font-size: 12.5px;
  font-weight: 600;
}

/* Chevron deitado: aponta para baixo fechado e gira ao abrir, sinalizando
   "isto expande" sem precisar de um segundo ícone. */
.filtro-seta {
  width: 12px;
  height: 12px;
  color: var(--text-muted);
  transform: rotate(90deg);
  transition: transform var(--transition-fast);
}

.filtro-botao[aria-expanded="true"] .filtro-seta {
  transform: rotate(-90deg);
}

.filtro-painel {
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  z-index: 40;
  width: 268px;
  padding: 12px;
  text-align: left;
  background: var(--bg-elevated);
  border: 1px solid var(--border-color-light);
  border-radius: var(--radius-md);
  box-shadow: var(--sombra-modal);
}

.filtro-painel[hidden] { display: none; }

.filtro-arvore {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.filtro-ano-linha {
  display: flex;
  align-items: center;
  gap: 2px;
}

.filtro-caret {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 26px;
  background: transparent;
  color: var(--text-muted);
  flex-shrink: 0;
}

.filtro-caret-icone {
  width: 11px;
  height: 11px;
  transition: transform var(--transition-fast);
}

.filtro-ano.is-aberto .filtro-caret-icone { transform: rotate(90deg); }

.filtro-ano-nome {
  display: flex;
  align-items: center;
  gap: 7px;
  flex: 1;
  padding: 5px 9px;
  font-family: inherit;
  font-size: 13px;
  font-weight: 700;
  text-align: left;
  color: var(--text-secondary);
  background: transparent;
  border-radius: var(--radius-sm);
  transition: background var(--transition-fast), color var(--transition-fast);
}

.filtro-ano-nome:hover { background: var(--bg-hover); }

/* Três estados por ano — vazio, parcial, cheio — porque agora dá para marcar
   meses de vários anos: o ano precisa dizer quanto de si está na seleção. */
.filtro-ano.is-cheio .filtro-ano-nome,
.filtro-ano.is-parcial .filtro-ano-nome { color: var(--accent-tinta); }

.filtro-marca {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 15px;
  height: 15px;
  border: 1px solid var(--border-color-light);
  border-radius: 3px;
  flex-shrink: 0;
}

.filtro-ano.is-cheio .filtro-marca {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--on-accent);
}

/* Parcial: quadrado com o miolo preenchido, sem check — o "traço" clássico de
   seleção incompleta. */
.filtro-ano.is-parcial .filtro-marca {
  border-color: var(--accent);
  background:
    linear-gradient(var(--accent), var(--accent)) center / 7px 2px no-repeat;
}

.filtro-marca-icone {
  width: 10px;
  height: 10px;
  stroke-width: 3.2;
}

.filtro-tag {
  padding: 1px 6px;
  border-radius: 20px;
  background: var(--accent-soft);
  color: var(--accent-tinta);
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

/* Meses colapsados com grid 0fr → 1fr: anima sem precisar medir a altura,
   mesmo truque do acordeão da sidebar. */
.filtro-meses {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 4px;
  margin: 0 0 0 22px;
  max-height: 0;
  overflow: hidden;
  opacity: 0;
  transition: max-height var(--transition-base), opacity var(--transition-fast),
              margin var(--transition-base);
}

.filtro-ano.is-aberto .filtro-meses {
  max-height: 140px;
  margin: 5px 0 8px 22px;
  opacity: 1;
}

.filtro-mes {
  padding: 5px 0;
  font-family: inherit;
  font-size: 11px;
  font-weight: 600;
  color: var(--text-muted);
  background: var(--bg-tertiary);
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  transition: background var(--transition-fast), color var(--transition-fast),
              border-color var(--transition-fast);
}

.filtro-mes:hover {
  color: var(--text-primary);
  border-color: var(--border-color-light);
}

.filtro-mes.is-marcado {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--on-accent);
}

.filtro-acoes {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-top: 10px;
  padding-top: 10px;
  border-top: 1px solid var(--border-color);
}

/* ---------- Filtro de lista plana (Empresa, e o que vier) ---------- */

/* Mesma casca do filtro de período — muda só o miolo, que aqui é uma lista sem
   hierarquia. O painel ganha teto e rola: oito empresas cabem, mas o mesmo
   componente vai servir a listas de dezenas. */
.filtro-lista {
  display: flex;
  flex-direction: column;
  gap: 2px;
  max-height: 260px;
  overflow-y: auto;
}

.filtro-item {
  display: flex;
  align-items: center;
  gap: 9px;
  width: 100%;
  padding: 6px 7px;
  text-align: left;
  background: transparent;
  border: 0;
  border-radius: var(--radius-sm);
  color: var(--text-secondary);
  transition: background var(--transition-fast), color var(--transition-fast);
}

.filtro-item:hover {
  color: var(--text-primary);
  background: var(--bg-hover);
}

.filtro-item.is-marcado {
  color: var(--text-primary);
}

.filtro-item.is-marcado .filtro-marca {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--on-accent);
}

.filtro-item-texto {
  display: flex;
  flex-direction: column;
  gap: 1px;
  min-width: 0;
}

.filtro-item-nome {
  font-size: 12px;
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.filtro-item-apoio {
  font-size: 10.5px;
  color: var(--text-muted);
}

.filtro-dica {
  font-size: 10px;
  color: var(--text-muted);
}

.filtro-limpar {
  padding: 5px 10px;
  font-family: inherit;
  font-size: 11px;
  font-weight: 600;
  color: var(--text-secondary);
  background: transparent;
  border: 1px solid var(--border-color-light);
  border-radius: var(--radius-sm);
  white-space: nowrap;
}

.filtro-limpar:hover:not(:disabled) {
  background: var(--bg-hover);
  color: var(--text-primary);
}

.filtro-limpar:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

/* ---------- Rodapé de contexto ---------- */
/* Fica sobre a malha de pontos, sem cartão: é metadado da tela, não um bloco
   de análise, e não deve competir com os painéis. */

.analise-rodape {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 7px;
  padding-top: 9px;
  border-top: 1px solid var(--border-color);
  font-size: 11.5px;
  line-height: 1.5;
  /* Um degrau acima do muted: o rodapé declara o escopo dos números, então
     precisa ser lido, não apenas estar presente. */
  color: var(--text-secondary);
}

/* Alerta de comparativo suprimido: é ressalva, não erro — âmbar, não vermelho. */
.analise-rodape-alerta {
  color: var(--warning-tinta);
  font-weight: 600;
}

.analise-rodape-rotulo {
  padding: 3px 8px;
  border: 1px solid var(--border-color-light);
  border-radius: 20px;
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-secondary);
}

.analise-rodape strong {
  color: var(--accent-tinta);
  font-weight: 700;
}

.analise-rodape-sep {
  color: var(--border-color-light);
}

/* ---------- KPIs ---------- */
/* Colunas fixas, não auto-fit. Com auto-fit o navegador quebrava para 5 numa
   janela de 1366 e a segunda fila custava 117px de altura — o suficiente para
   jogar a última linha de painéis para fora da tela. Quebra só nos pontos
   escolhidos, onde a perda de altura já é inevitável. */
.kpis {
  display: grid;
  grid-template-columns: repeat(6, minmax(0, 1fr));
  gap: 12px;
}

/* Dois cartões dividindo a largura, para telas que repartem a página em lados e
   dão um par de KPIs a cada um. Fica fora do `repeat(6)` porque ali a unidade é
   a largura da PÁGINA; aqui é a largura da coluna. */
.kpis--par { grid-template-columns: repeat(2, minmax(0, 1fr)); }

/* Quatro indicadores em vez de seis. Não é a mesma coisa que deixar duas
   colunas vazias: com `repeat(6)` os quatro ficariam com dois terços da largura
   e um vão morto à direita, e a fileira deixaria de emoldurar a tela. */
.kpis--quatro { grid-template-columns: repeat(4, minmax(0, 1fr)); }

@media (max-width: 1180px) {
  .kpis { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .kpis--quatro { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .kpis--par { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 680px) {
  .kpis { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* Coluna, para o rodapé poder ser empurrado até a base — ver .kpi-rodape. */
.kpi {
  display: flex;
  flex-direction: column;
  padding: 13px 15px;
  background: var(--bg-secondary);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-md);
}

/* Cartão em ALERTA: número e ícone no vermelho saturado, borda respirando. É o
   mesmo efeito do sino de notificação, e de propósito — quem já viu o sino
   aceso reconhece o gesto sem precisar aprender um segundo vocabulário.

   Usa `--alerta` e não `--danger`: o danger é dessaturado justamente para que
   dezenas dele convivam numa tela sem gritar, e ao lado de uma borda em
   #ff4242 ele leria como um segundo vermelho, desbotado. Aqui os dois têm de
   ser a mesma cor para o cartão ser lido como uma coisa só.

   RESSALVA, porque o custo é real: no sino o vermelho é uma pendência que some
   quando você olha. Aqui ele é permanente — o valor inadimplente está sempre
   lá. Um alerta que nunca apaga vira paisagem, então este é o único cartão da
   tela que o recebe. Espalhá-lo pelos outros gastaria o efeito. */
.kpi--alerta {
  border-color: var(--alerta-borda);
  animation: respirar-borda 1.8s ease-in-out infinite;
}

.kpi--alerta .kpi-valor { color: var(--alerta); }

.kpi--alerta .kpi-icone {
  background: var(--alerta-fundo);
  color: var(--alerta);
}

/* Irmã de `respirar-alerta` (shell.css), sem a `color`: lá a animação governa
   o texto do botão inteiro; aqui o número precisa ficar parado no vermelho
   cheio, e quem respira é só a moldura. */
@keyframes respirar-borda {
  0%, 100% {
    border-color: var(--alerta-borda-fraca);
    box-shadow: 0 0 0 0 rgba(238, 77, 77, 0);
  }
  50% {
    border-color: var(--alerta-borda);
    box-shadow: 0 0 10px 0 var(--alerta-brilho);
  }
}

/* Mesma leitura do sino: a preferência existe para conter MOVIMENTO, e aqui
   nada se move. O que ela corta é o brilho, que é o que puxa o olho
   periférico; a borda continua respirando. */
@media (prefers-reduced-motion: reduce) {
  @keyframes respirar-borda {
    0%, 100% { border-color: var(--alerta-borda-fraca); }
    50%      { border-color: var(--alerta-borda); }
  }
}

.kpi-topo {
  display: flex;
  align-items: center;
  gap: 9px;
}

.kpi-icone {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  border-radius: var(--radius-sm);
  background: var(--accent-soft);
  color: var(--accent-tinta);
  flex-shrink: 0;
}

.kpi-icone .icone {
  width: 14px;
  height: 14px;
}

.kpi-titulo {
  font-size: 12px;
  font-weight: 600;
  color: var(--text-secondary);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Fileira cujos títulos podem ocupar DUAS linhas. É declaração da tela, e não
   o padrão: em quase todas as análises o título cabe numa linha, e quebrar sem
   necessidade só afastaria o rótulo do número.

   Vale para a fileira INTEIRA, nunca para um cartão só. Com um cartão quebrando
   sozinho, o valor dele desceria 15px e a fila de números — que é o que se lê
   de relance — deixaria de se alinhar. Reservando as duas linhas em todos, os
   seis valores continuam na mesma altura.

   Em Comercial o que força isso é "Custo logístico Absorvido": pede 140px numa
   coluna de 121, e a reticência comeria justamente a palavra que diz o que o
   número é. */
.kpis--titulo-duplo .kpi-topo {
  align-items: flex-start;
}

.kpis--titulo-duplo .kpi-titulo {
  white-space: normal;
  line-height: 1.25;
  min-height: 30px;      /* duas linhas a 12px */
}

.kpi-valor {
  margin-top: 9px;
  font-size: 23px;
  font-weight: 800;
  letter-spacing: -0.03em;
  line-height: 1.1;
}

/* KPI cujo valor é um nome, e não um número: "Top Whey 3W - Chocolate - 3kg"
   em 23px estouraria o cartão. Cai de corpo e passa a quebrar em duas linhas —
   truncar seria pior, porque é justamente o fim do nome (o sabor e o peso) que
   distingue um SKU do outro. */
.kpi-valor.is-texto {
  font-size: 15px;
  line-height: 1.25;
  letter-spacing: -0.01em;
}

/* Linha de apoio no lugar da variação: contexto do próprio recorte ("de 36 no
   catálogo"), e não comparação com outro período. Vai para a base pelo mesmo
   motivo do .kpi-rodape. */
.kpi-apoio {
  margin-top: auto;
  padding-top: 7px;
  font-size: 10.5px;
  font-style: italic;
  color: var(--text-muted);
}

.kpi-apoio strong {
  color: var(--text-secondary);
  font-style: normal;
  font-weight: 700;
}

/* `margin-top: auto` cola o rodapé na base do cartão. Os seis cartões têm a
   mesma altura (são células de grade), mas o valor acima varia de uma para
   duas linhas — "Top Whey 3W - Chocolate - 3kg" quebra, "36" não. Sem isto o
   rodapé nasce logo abaixo do valor e a linha de rodapés fica serrilhada.
   O padding garante o respiro mínimo que o margin deixou de dar. */
.kpi-rodape {
  display: flex;
  align-items: baseline;
  gap: 7px;
  margin-top: auto;
  padding-top: 7px;
  font-size: 10.5px;
}

.kpi-var-rotulo {
  color: var(--text-muted);
  font-style: italic;
}

.kpi-var {
  font-weight: 700;
  white-space: nowrap;
}

/* Alta é verde e baixa é vermelha por convenção de leitura financeira. Onde
   a direção "boa" for invertida (custo, churn), a tela passa a classe trocada
   em vez de mudar esta regra. */
.kpi-var.is-sobe   { color: var(--success-tinta); }
.kpi-var.is-desce  { color: var(--danger-tinta); }
.kpi-var.is-estavel{ color: var(--text-muted); }
/* Segundo dado do MESMO período, não comparação: o desvio ao lado da média, a
   fatia ao lado da contagem. Sem verde nem vermelho porque ali não há subiu nem
   caiu — é o número qualificando a si mesmo. */
.kpi-var.is-neutro { color: var(--text-primary); }

/* Terceiro estado, para indicador que tem um limiar ABSOLUTO além do relativo.
   O ROAS é o caso: 0,95x é o melhor do portfólio (acima da média) e ainda
   assim devolve menos do que consumiu. Verde diria "bom" e vermelho diria
   "pior que os outros" — os dois errados. Âmbar é "o melhor de um conjunto que
   não está bom", que é o que o número diz. */
.kpi-var.is-atencao{ color: var(--warning-tinta); }

/* ---------- Grade dos painéis ---------- */
/* Uma grade só para as duas linhas, com 24 colunas. Os spans 16+8 na primeira
   e 9+7+8 na segunda fazem a divisória da direita cair exatamente no mesmo x
   — com duas grades independentes não haveria como garantir isso, porque cada
   uma resolveria seus `fr` sobre a própria largura. */

.analise-grade {
  display: grid;
  grid-template-columns: repeat(24, minmax(0, 1fr));
  gap: 12px;
  /* `0 1 auto`, e não `1`: a grade fica com a altura NATURAL do conteúdo e só
     encolhe se não houver espaço. É o que garante que a regra da dobra não
     reorganize uma tela que já cabia — a Visão Executiva foi desenhada com
     linhas de altura natural e continua exatamente como era.
     Com `flex: 1` a grade se esticaria para preencher a janela, empurrando o
     rodapé para o fim e mudando a proporção de todos os painéis. */
  flex: 0 1 auto;
  min-height: 0;
  /* `minmax(0, auto)`: a linha tem a altura do conteúdo, mas PODE encolher.
     Com `auto` puro ela se recusa, e numa janela baixa a última linha era
     cortada pelo overflow do .conteudo em vez de ceder. */
  grid-auto-rows: minmax(0, auto);
}

/* Linhas de altura IGUAL, por opção da tela. Só faz sentido onde um painel
   acompanha duas linhas (painel--h2) e precisa que as duas somem exatamente a
   altura dele. É declaração de layout, não conserto de altura: por isso a tela
   pede, em vez de virar padrão e reorganizar as outras vinte. */
.analise-grade--iguais {
  grid-auto-rows: minmax(0, 1fr);
  flex: 1;
}

/* Duas linhas em proporção desigual, por opção da tela. Não é ajuste fino de
   altura: é o reconhecimento de que as duas linhas têm naturezas diferentes.

   Onde a linha de cima carrega painéis com NOTA — texto de interpretação, de
   altura fixa, que não encolhe — e a de baixo carrega só desenho, que escala
   com o espaço, dividir meio a meio dá o pior dos dois: a nota espreme o
   gráfico em cima e sobra vão embaixo. Em Clientes a diferença é de 60px por
   painel, o suficiente para a matriz 5x5 perder uma linha.

   Vale só com --iguais, que é quem estabelece as linhas em fr. */
.analise-grade--iguais.analise-grade--topo-alto {
  grid-template-rows: 1.18fr 0.82fr;
}

/* O contrário: linha de cima MENOR. Em Geografia a de cima é uma tabela de seis
   estados — que não cresce com o cartão — e a de baixo tem dispersão e barras,
   que crescem. Meio a meio deixava a tabela com meia altura vazia enquanto o
   gráfico de bolhas ficava sem espaço para separar os pontos. */
.analise-grade--iguais.analise-grade--topo-baixo {
  grid-template-rows: 0.86fr 1.14fr;
}

@media (max-width: 1180px) {
  .analise-grade--iguais.analise-grade--topo-baixo { grid-template-rows: none; }
}

@media (max-width: 1180px) {
  /* Numa coluna só as linhas deixam de ser duas e a proporção não faz sentido. */
  .analise-grade--iguais.analise-grade--topo-alto { grid-template-rows: none; }
}

.painel--w16 { grid-column: span 16; }
.painel--w15 { grid-column: span 15; }
.painel--w14 { grid-column: span 14; }
.painel--w12 { grid-column: span 12; }
.painel--w11 { grid-column: span 11; }
.painel--w10 { grid-column: span 10; }
.painel--w9  { grid-column: span 9; }
.painel--w8  { grid-column: span 8; }
.painel--w7  { grid-column: span 7; }
.painel--w6  { grid-column: span 6; }
.painel--w5  { grid-column: span 5; }

/* Painel que acompanha DUAS linhas da grade. Em Produtos é o bloco de Pareto:
   ele tem waffles, régua e tabela, e sozinho é tão alto quanto os dois painéis
   empilhados ao lado. */
.painel--h2 { grid-row: span 2; }

@media (max-width: 1180px) {
  .analise-grade { grid-template-columns: 1fr; }
  .painel--w16, .painel--w15, .painel--w14, .painel--w12, .painel--w11,
  .painel--w10, .painel--w9, .painel--w8, .painel--w7, .painel--w6,
  .painel--w5 { grid-column: 1 / -1; }
  /* Numa coluna só não há largura para duas leituras lado a lado. */
  .painel-duplo { grid-template-columns: minmax(0, 1fr); }
  /* Numa coluna só não há vizinho para acompanhar: o span viraria um vão. */
  .painel--h2 { grid-row: auto; }
}

/* ---------- Painel ---------- */

.painel {
  display: flex;
  flex-direction: column;
  min-width: 0;
  /* Recebe a altura da linha da grade em vez de pedi-la. O overflow hidden é a
     última barreira: conteúdo que não coube fica recortado no cartão e nunca
     vaza para empurrar a tela. */
  min-height: 0;
  overflow: hidden;
  padding: 14px 16px 16px;
  /* Opaco de propósito: é ele que recorta a malha de pontos do fundo da
     página, deixando a textura só nas frestas entre os cartões. */
  background: var(--bg-secondary);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-md);
}

.painel-topo {
  display: flex;
  align-items: flex-start;
  gap: 9px;
  margin-bottom: 12px;
}

/* Controles do painel, à direita do cabeçalho. `margin-left: auto` empurra o
   grupo para a borda sem que o bloco do título precise saber que eles existem
   — painel sem ações continua exatamente como era. */
.painel-acoes {
  display: flex;
  gap: 6px;
  margin-left: auto;
  flex-shrink: 0;
}

.painel-icone {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  border-radius: var(--radius-sm);
  background: var(--accent-soft);
  color: var(--accent-tinta);
  flex-shrink: 0;
}

.painel-icone .icone {
  width: 14px;
  height: 14px;
}

.painel-titulo {
  font-size: 14px;
  font-weight: 700;
}

.painel-apoio {
  margin-top: 2px;
  font-size: 11.5px;
  color: var(--text-muted);
}

/* O corpo ocupa a sobra e centra o conteúdo verticalmente. Sem isso, um painel
   esticado pela altura do vizinho deixa o gráfico grudado no topo e um vão
   morto embaixo — foi o que acontecia no Ranking e no Melhor/pior. */
.painel-corpo {
  flex: 1;
  min-width: 0;
  min-height: 0;
  display: flex;
  flex-direction: column;
  /* `safe` é o que resolve o conflito entre centrar e não perder conteúdo:
     enquanto cabe, o corpo fica centrado; quando não cabe, o alinhamento cai
     para o início sozinho e a rolagem alcança o resto. Sem o `safe`, o
     conteúdo centrado transborda para os DOIS lados e o começo fica
     inalcançável — é o mesmo bug que o painel--rolavel já contornava à mão. */
  /* A primeira linha é o degrau para quem não conhece `safe`: sem ela a
     declaração inválida seria descartada e o padrão viraria flex-start. */
  justify-content: center;
  justify-content: safe center;
  /* Rolagem dentro do cartão em vez de recorte mudo. Em janela de 1080p nada
     rola; em telas mais baixas o que sobra continua alcançável. */
  overflow-y: auto;
}

/* Texto de leitura ao pé do painel: é interpretação, não dado, então vem em
   itálico e com peso visual menor. */
.painel-nota {
  margin-top: 12px;
  padding-top: 10px;
  border-top: 1px solid var(--border-color);
  font-size: 11px;
  font-style: italic;
  line-height: 1.55;
  color: var(--text-secondary);
}

.painel-nota strong {
  color: var(--text-primary);
  font-style: normal;
}

/* Categorias podem passar de dez: rola dentro do painel em vez de esticar a
   linha inteira e desalinhar os vizinhos.

   justify-content de volta para flex-start: num container com overflow, o
   `center` herdado empurra o conteúdo para o meio e deixa o começo da lista
   fora da área visível — os dois maiores valores do ranking sumiam. */
/* SEM ESMAECIMENTO no pé. Havia aqui um
   `mask-image: linear-gradient(to bottom, #000 calc(100% - 22px), transparent)`
   que dissolvia a última linha para dizer que a lista continua. Duas razões
   para ele ter saído:

   - o efeito é indistinguível de um borrão, e apagava um dado de verdade — a
     última categoria visível ficava com valor e participação ilegíveis;
   - o recado que ele dava já é dado pela BARRA DE ROLAGEM, que aparece
     exatamente quando há o que rolar. Dois avisos para a mesma coisa, e o
     segundo custava a leitura de uma linha.

   O corte reto no fim da área é o comportamento normal de qualquer lista que
   rola, e é o que o olho já sabe ler. */
.painel--rolavel .painel-corpo {
  max-height: 138px;
  overflow-y: auto;
  padding-right: 6px;
  justify-content: flex-start;
}

/* ---------- Barras horizontais ---------- */

.g-barras {
  display: flex;
  flex-direction: column;
  gap: 7px;
}

/* Variante enxuta, pedida pela tela que precisa dela. NÃO mexer nas medidas
   padrão para fazer uma tela caber: elas valem para as 21 análises, e apertar
   a barra aqui muda o Ranking de Canais da Visão Executiva sem que ninguém
   tenha pedido. Quem tem restrição de altura declara a restrição. */
.g-barras--compacto {
  gap: 4px;
}

/* Três colunas: nome, trilho e a FAIXA RESERVADA.
   A terceira coluna fica vazia — ninguém escreve nela. A largura dela é a do
   rótulo mais largo da lista (calculada em Graficos.barras) e existe só para
   que o par valor+apoio, que é ancorado no fim da barra e transborda o trilho,
   sempre tenha para onde ir. É o que garante que o rótulo nunca precise entrar
   por cima do preenchido — nem na barra de 100%.
   Largura fixa e igual em todas as linhas: variável, o trilho mudaria de
   tamanho a cada linha e as barras deixariam de ser comparáveis. */
.g-barra {
  display: grid;
  grid-template-columns: 88px minmax(0, 1fr) var(--g-barra-reserva, 80px);
  align-items: center;
  gap: 9px;
}

/* Rótulos longos (nome de SKU) ganham mais coluna. A barra fica menor, mas ela
   já é comparativa: o que se lê nela é a proporção entre as linhas, não o
   comprimento absoluto. Um nome truncado, esse sim, perde informação.

   Dois degraus porque o custo é diferente conforme a largura do painel: num
   cartão estreito, dar 176px ao nome deixaria a barra curta demais para
   comparar. */
.g-barras--rotulo-largo .g-barra {
  grid-template-columns: 176px minmax(0, 1fr) var(--g-barra-reserva, 80px);
}

.g-barras--rotulo-medio .g-barra {
  grid-template-columns: 140px minmax(0, 1fr) var(--g-barra-reserva, 80px);
}

/* Um ponto a mais no nome, já que agora há coluna para ele. Fica no
   modificador, e não no .g-barra-rotulo: mudar o corpo padrão mexeria no
   ranking de todas as outras análises. */
.g-barras--rotulo-medio .g-barra-rotulo,
.g-barras--rotulo-largo .g-barra-rotulo {
  font-size: 12.5px;
}

.g-barra-rotulo {
  font-size: 11.5px;
  color: var(--text-secondary);
  text-align: right;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.g-barra-trilho {
  position: relative;
  display: flex;
  align-items: center;
  height: 22px;
  min-width: 0;
}

.g-barras--compacto .g-barra-trilho {
  height: 18px;
}

.g-barra-preenche {
  height: 100%;
  border-radius: 3px;
  background: var(--accent);
  min-width: 3px;
}

/* SEM SOMBRA, e isso é consequência do posicionamento, não uma escolha de
   estilo: o par vive sempre sobre o trilho vazio ou sobre a faixa reservada,
   nunca sobre o preenchido. Não há nada de que o texto precise se defender.
   Aqui havia `text-shadow: 0 1px 3px rgba(0,0,0,.75)`, dos tempos em que o
   valor era ancorado na borda direita e caía por cima do âmbar. */
.g-barra-valor {
  font-size: 11px;
  font-weight: 700;
  color: var(--text-primary);
  pointer-events: none;
}

/* Ancorado no fim da barra pelo `left` inline; o translate dá o respiro.
   Transborda o trilho de propósito — o destino é a faixa reservada ao lado. */
.g-barra-fim {
  position: absolute;
  display: flex;
  align-items: baseline;
  gap: 8px;
  white-space: nowrap;
  transform: translateX(7px);
  pointer-events: none;
}

.g-barra-apoio {
  font-size: 11px;
  font-weight: 600;
  color: var(--accent-tinta);
  white-space: nowrap;
}

/* Ranking que precisa caber no cartão sem rolagem nenhuma. Opt-in: o ranking
   padrão NÃO encolhe, porque na maioria dos painéis a barra na medida de
   projeto (22px) é o que se quer, e rolar dentro do cartão é aceitável.

   Onde não é — oito origens num painel de meia altura, por exemplo — a lista
   cede altura em vez de estourar: como item de flex ela encolhe primeiro, e o
   `min-height: 0` em cada elo permite descer abaixo do conteúdo natural. A
   barra parte de 22px e só cede se faltar espaço, com piso de 12px, abaixo do
   qual deixa de ser barra.
   Coeficiente em `vh` erraria nos dois sentidos: sobraria numa tela e faltaria
   noutra, e a conta teria de ser refeita a cada mudança de conteúdo. */
.barras-encolhem {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-height: 0;
  /* Mesma barreira do funil e da matriz: o flex já garante o encaixe, e o que
     sobra é fração de pixel — que sem isto acende 10px de barra de rolagem no
     corpo do painel. */
  overflow: hidden;
}

/* As barras não crescem (`flex: 0 1 22px` abaixo), então numa lista curta
   sobra espaço. Centrado, esse resto vira respiro igual em cima e embaixo;
   sem isto a lista se empilha no topo e o vão morto se junta todo no pé do
   cartão. `safe` pelo motivo de sempre: quando não couber, o alinhamento cai
   para o começo em vez de esconder as primeiras barras. */
.barras-encolhem .g-barras {
  flex: 1;
  min-height: 0;
  gap: clamp(3px, 0.65vh, 7px);
  justify-content: center;
  justify-content: safe center;
}

.barras-encolhem .g-barra {
  flex: 0 1 22px;
  min-height: 0;
}

.barras-encolhem .g-barra-trilho {
  height: 100%;
  min-height: 12px;
}

/* Variante que também CRESCE. A `barras-encolhem` só cede altura: numa lista
   curta dentro de um cartão alto — seis filiais, três naturezas de custo — as
   barras ficam na medida de 22px e sobra meio cartão vazio em volta.

   Aqui as linhas dividem a altura disponível entre si e a barra sobe até um
   teto. O teto importa: sem ele, três naturezas num cartão de 260px virariam
   três blocos de 80px, que já não se leem como barra. O que passa do teto vira
   respiro entre as linhas, e é isso que faz o desenho ocupar o cartão inteiro
   sem engordar.

   O teto é, na prática, o controle do ESPAÇAMENTO: a linha tem a altura que a
   divisão der, então tudo o que a barra não ocupa vira vão entre uma e outra.
   Subir o teto aproxima as barras; baixá-lo as afasta. Por isso ele é variável
   — a tela ajusta sem precisar de outra classe. */
/* A linha cresce até um TETO. Sem ele, seis barras num cartão alto ficavam a
   28px umas das outras — o desenho preenchia o cartão, mas espalhado, e barras
   distantes deixam de se comparar entre si, que é a única coisa que uma barra
   serve para fazer. Com o teto, a sobra vira respiro simétrico em cima e
   embaixo (o `safe center` do container) em vez de vão entre as linhas. */
/* 50px de linha para 44px de barra: sobram 3px de cada lado, mais o `gap` do
   container. É o mínimo que ainda separa uma barra da seguinte — abaixo disso
   as seis viram um bloco só e o olho perde onde uma acaba. */
.barras-encolhem--cheio .g-barra {
  flex: 1 1 auto;
  max-height: var(--g-barra-linha, 50px);
}

.barras-encolhem--cheio .g-barra-trilho {
  max-height: var(--g-barra-teto, 44px);
}

/* ---------- Roscas ---------- */

.g-roscas {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 10px;
  align-items: start;
  height: 100%;
  align-content: center;
}

.g-rosca {
  text-align: center;
  min-width: 0;
}

.g-rosca svg {
  width: 100%;
  max-width: 96px;
  height: auto;
}

/* "Track / vazio" do guia: o trilho é fundo, não dado — nunca laranja. */
/* A LARGURA DO TRAÇO NÃO MORA AQUI. Ela vem inline, de ROSCA_TRACO em
   graficos.js, porque o comprimento do arco é calculado descontando a ponta
   arredondada — e esse desconto é a própria largura. Reescrevê-la no CSS
   quebraria a conta em silêncio: o anel continuaria desenhando, só que dizendo
   uma proporção errada. */
.g-rosca-trilho {
  fill: none;
  stroke: var(--bg-tertiary);
}

.g-rosca-arco {
  fill: none;
  stroke: var(--accent);
  stroke-linecap: round;
}

/* Arco por significado, não por posição. Um medidor de inadimplência no acento
   do domínio fica da mesma cor do resto da tela e deixa de avisar. */
.g-rosca-arco.is-perigo { stroke: var(--danger); }
.g-rosca-arco.is-atencao { stroke: var(--warning); }
.g-rosca-arco.is-bom { stroke: var(--success); }

/* Discreto de propósito: o número dentro da rosca já é reforçado pelo próprio
   arco, então peso 800 e corpo grande faziam três medidores pequenos gritarem
   mais alto que os KPIs do topo. */
.g-rosca-num {
  fill: var(--text-primary);
  font-size: 19px;
  font-weight: 600;
  letter-spacing: -0.02em;
}

/* Nome DENTRO do anel, sob o número. Menor e mais apagado que o percentual de
   propósito: os dois ocupam o mesmo miolo, e sem a diferença de peso o rótulo
   competiria com o dado. */
.g-rosca-dentro {
  fill: var(--text-secondary);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.04em;
}

.g-rosca-titulo {
  margin-top: 6px;
  font-size: 11px;
  color: var(--text-secondary);
  line-height: 1.35;
}

.g-rosca-apoio {
  margin-top: 2px;
  font-size: 15px;
  font-weight: 700;
}

/* ---------- Combo barras + linha ---------- */

/* Gráfico em SVG encolhe em vez de rolar. A altura sai da proporção da
   viewBox, mas o max-height a limita ao espaço do cartão; como o
   preserveAspectRatio é `meet`, o desenho inteiro se reduz para caber em vez
   de ser cortado. Rolar um gráfico não faz sentido — metade de um gráfico não
   informa metade. */
.g-combo {
  width: 100%;
  height: auto;
  max-height: 100%;
  display: block;
  overflow: visible;
}

.g-combo-base {
  stroke: var(--border-color-light);
  stroke-width: 1;
}

/* Série única = um laranja só, conforme o guia. A sazonalidade é contada pelo
   preenchimento, não por outra cor: meses comuns apagados, novembro e dezembro
   cheios. Trocar a cor deles sugeriria outra categoria de dado. */
.g-combo-barra {
  fill: var(--accent);
  opacity: 0.42;
  transition: opacity var(--transition-fast);
}

.g-combo-barra.is-destaque {
  opacity: 1;
}

/* Duas séries empilhadas. Opacidade cheia: no modo de série única a
   transparência distingue destaque de comum, mas com duas cores empilhadas ela
   deixaria a de baixo aparecer através da de cima. */
.g-combo-barra.is-a { fill: var(--accent); opacity: 1; }
.g-combo-barra.is-b { fill: var(--bg-tertiary); opacity: 1; }
.g-combo-barra.is-a:hover,
.g-combo-barra.is-b:hover { opacity: 0.82; }

.g-combo-barra:hover {
  opacity: 0.85;
}

.g-combo-barra.is-destaque:hover {
  opacity: 0.8;
}

/* Comparação A vs. B: a barra é o laranja e a linha é o azul neutro. Duas
   grandezas diferentes (R$ e %) precisam de cores diferentes, senão o leitor
   assume que a linha é o mesmo dado das barras em outra forma. */
.g-combo-linha {
  fill: none;
  stroke: var(--serie-b);
  stroke-width: 2;
  stroke-linejoin: round;
}

.g-combo-ponto {
  fill: var(--serie-b);
}

.g-combo-rot-barra {
  fill: var(--text-secondary);
  font-size: 10.5px;
  font-weight: 600;
}

/* Pílula da cor da série, para o rótulo da margem não se confundir com o
   rótulo de faturamento que fica logo acima da barra. */
.g-combo-pilula {
  fill: var(--serie-b);
}

.g-combo-rot-linha {
  fill: #10222e;
  font-size: 9.5px;
  font-weight: 700;
}

.g-combo-rot-x {
  fill: var(--text-secondary);
  font-size: 11px;
}

/* Segundo nível do eixo de categoria — o ano sob os meses. Mais apagado: ele
   qualifica os doze rótulos acima, não é um décimo terceiro. */
.g-combo-rot-x.is-nivel2 {
  fill: var(--text-muted);
  font-size: 10.5px;
}

/* Legenda das séries, no alto à esquerda. */
.g-combo-legenda {
  fill: var(--text-secondary);
  font-size: 10.5px;
}

.g-combo-chave.is-a { fill: var(--accent); }
.g-combo-chave.is-b { fill: var(--bg-tertiary); }
.g-combo-chave.is-linha { fill: var(--serie-b); }

.g-combo-eixo {
  fill: var(--text-muted);
  font-size: 10px;
}

/* Variante desenhada sobre a medida real da caixa (ver Graficos.comboBarraLinha).
   Aqui a viewBox JÁ é o tamanho na tela, então o SVG ocupa a caixa inteira: o
   `height: auto` da razão fixa deixaria vão morto acima e abaixo. */
/* Rola NA HORIZONTAL quando o desenho é mais largo que o cartão. É o caso do
   Pareto: dezenove motivos com nome não cabem em meia tela, e espremê-los até
   caberem produziria dezenove tiras sem rótulo legível — que responde a
   pergunta do Pareto por conta própria. Meio gráfico rolável ainda informa
   metade; um gráfico ilegível inteiro não informa nada. */
.g-combo-caixa {
  flex: 1;
  min-height: 0;
  min-width: 0;
  display: flex;
  overflow-x: auto;
  overflow-y: hidden;
}

.g-combo--medido {
  height: 100%;
  max-height: none;
}

/* ---------- Waffle ---------- */

.g-waffle {
  display: flex;
  align-items: center;
  gap: 14px;
  min-width: 0;
  /* Não encolhe: a grade lá dentro tem largura fixa e, se o invólucro cedesse,
     ela transbordaria por baixo do texto vizinho em vez de empurrá-lo. */
  flex-shrink: 0;
}

.g-waffle-grade {
  display: grid;
  grid-template-columns: repeat(10, 1fr);
  gap: 2.5px;
  width: 108px;
  flex-shrink: 0;
}

/* Quando a grade é o único elemento do bloco, ela é o assunto e pode crescer.
   A largura acompanha a altura da janela porque é ela que decide quanto o
   cartão tem para gastar: 150px numa tela de 1080 e ~120px numa de 850, sem
   ponto de quebra. Medida fixa faria a grade caber numa e forçar rolagem na
   outra. */
.g-waffle-grade.is-grande {
  width: clamp(96px, 14vh, 150px);
  gap: 3px;
}

/* Quadrado de canto arredondado, não círculo: entre quadrados o vão é
   constante em qualquer direção, então a mancha de cor lê como área preenchida
   — que é o que um waffle mede. Círculos deixam frestas nas diagonais e a
   mesma proporção parece menor. */
.g-waffle-ponto {
  aspect-ratio: 1;
  border-radius: 2px;
  background: var(--bg-elevated);
}

.g-waffle-ponto.is-cheio {
  background: var(--accent);
}

.g-waffle-leitura {
  min-width: 0;
}

.g-waffle-num {
  font-size: 34px;
  font-weight: 800;
  letter-spacing: -0.04em;
  line-height: 1;
}

.g-waffle-titulo {
  margin-top: 2px;
  font-size: 13px;
  color: var(--text-secondary);
}

.g-waffle-apoio {
  margin-top: 2px;
  font-size: 11px;
  color: var(--text-muted);
}

/* ---------- Bolhas ---------- */

/* A caixa recebe a sobra do cartão; o SVG é desenhado depois, já com a viewBox
   nas medidas dela (ver Graficos.bolhas). Existe como elemento separado porque
   é preciso ter algo medível no DOM ANTES de desenhar. */
/* `relative` porque o balão da bolha se posiciona em relação a esta caixa —
   é ela o elemento estável da tela, o mesmo que o ResizeObserver mede e onde o
   ouvinte do ponteiro vive. O quadro interno é refeito a cada redimensionamento
   e não serviria de âncora. */
.g-bolhas-caixa {
  position: relative;
  flex: 1;
  min-height: 0;
  min-width: 0;
  display: flex;
}

.g-bolhas {
  width: 100%;
  height: 100%;
  display: block;
  overflow: visible;
}

.g-bolhas-grade {
  stroke: var(--border-color);
  stroke-width: 1;
  stroke-dasharray: 2 5;
}

.g-bolhas-eixo {
  fill: var(--text-muted);
  font-size: 11px;
}

/* Verde acima da referência, vermelho abaixo — o mesmo par que os KPIs usam
   para subir e descer. Reaproveitar as cores de estado, em vez de inventar uma
   escala nova, é o que deixa a leitura imediata em qualquer tela. */
.g-bolhas-ponto {
  opacity: 0.85;
  transition: opacity var(--transition-fast);
}

.g-bolhas-ponto.is-acima  { fill: var(--success); }
.g-bolhas-ponto.is-abaixo { fill: var(--danger); }
.g-bolhas-ponto:hover     { opacity: 1; }

.g-bolhas-ref {
  stroke: var(--accent);
  stroke-width: 1.5;
  stroke-dasharray: 6 4;
}

.g-bolhas-ref-rot {
  fill: var(--accent);
  font-size: 11.5px;
  font-weight: 600;
}

.g-bolhas-legenda {
  display: flex;
  flex-wrap: wrap;
  gap: 3px 11px;
  margin-bottom: 6px;
  flex-shrink: 0;
}

.g-bolhas-chip {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: 11px;
  color: var(--text-secondary);
}

.g-bolhas-chip-cor {
  width: 8px;
  height: 8px;
  border-radius: 50%;
}

.g-bolhas-chip-cor.is-acima  { background: var(--success); }
.g-bolhas-chip-cor.is-abaixo { background: var(--danger); }

/* ---------- Funil ---------- */

/* Grade de duas colunas: o nome da etapa à esquerda, a faixa à direita. O
   passo entre duas etapas ocupa só a segunda coluna, centrado sob a faixa de
   cima — é ali que a taxa pertence, entre as duas que ela liga. */
/* Ocupa o cartão inteiro: as linhas em `1fr` (declaradas por Graficos.funil)
   só têm sobra para repartir se a grade souber qual é a altura disponível. */
.g-funil {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: center;
  column-gap: 14px;
  /* Sem vão entre as linhas: o respiro de cada passo é o padding dele. Assim
     a taxa fica visivelmente ligada às duas faixas que conecta, em vez de
     flutuar à mesma distância de tudo — e a altura economizada volta para as
     faixas, que é onde ela faz diferença. */
  row-gap: 0;
  width: 100%;
  flex: 1;
  min-height: 0;
  /* As linhas em `1fr` já garantem que o conjunto cabe na caixa — o que sobra
     aqui é fração de pixel (uma grade de 135,39px dentro de um corpo cujo
     clientHeight arredonda para 135). Sem isto, esse 0,39px acende a barra de
     rolagem do .painel-corpo: 10px de barra por meio pixel de conteúdo.
     É a mesma barreira que o .painel já aplica a si mesmo. */
  overflow: hidden;
}

.g-funil-rotulo {
  font-size: 12px;
  font-style: italic;
  color: var(--text-secondary);
  text-align: right;
  white-space: nowrap;
}

.g-funil-faixa {
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: 0;
  height: 100%;
}

/* A faixa acompanha a linha da grade — cresce até o teto num cartão alto e
   cede até o piso num cartão baixo, sem ponto de quebra. O teto existe porque
   uma faixa de 60px viraria um bloco de cor: o funil deixaria de ser lido como
   uma sequência de etapas. */
.g-funil-barra {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  max-height: 36px;
  padding: 0 10px;
  border-radius: var(--radius-sm);
  font-size: clamp(12px, 1.6vh, 16px);
  font-weight: 800;
  letter-spacing: -0.02em;
  /* Tinta escura: os primeiros degraus da rampa são claros. */
  color: #241703;
}

.g-funil-barra.is-tinta-clara {
  color: var(--text-primary);
}

.g-funil-passo {
  grid-column: 2;
  text-align: center;
  padding: 2px 0;
  font-size: 10.5px;
  /* Entrelinha curta: é uma linha só, e a de 1.5 do corpo do texto custaria
     5px por passo — 15px que saem da altura das faixas. */
  line-height: 1.3;
  color: var(--text-muted);
}

/* Vermelho quando a taxa é de outra ordem de grandeza que as demais — não é
   decoração: é a única forma de a queda aparecer, já que o estreitamento das
   faixas é decorativo (ver Graficos.funil). */
.g-funil-passo.is-alerta {
  color: var(--danger-tinta);
  font-weight: 600;
}

/* ---------- Waffle com texto de leitura ao lado ---------- */

/* Irmão de `.concentra-topo`, que é do Pareto de Produtos e carrega um
   `margin-top` para se descolar das abas daquela tela. Aqui não há abas acima,
   e aquela margem custava exatamente os 2px que acendiam a barra de rolagem.
   Duas classes em vez de uma condicional: mexer na do Produtos para caber
   aqui é o tipo de acoplamento que faz uma tela quebrar a outra. */
/* Centrado, e não encostado à esquerda: com o texto ocupando toda a sobra, o
   waffle ficava colado na borda do cartão. Limitando a coluna de texto, o par
   inteiro encolhe e cabe centralizado — o waffle entra para dentro do cartão
   e o texto ganha altura em vez de largura. */
.waffle-leitura {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 18px;
  min-width: 0;
}

/* A leitura do waffle é maior aqui que no ranking de Produtos: neste cartão
   ela é a frase inteira do relatório, e não um rótulo de duas palavras.
   O teto de largura é o que mantém o waffle para dentro do cartão — sem ele o
   texto se estica e devolve a grade à borda. */
.waffle-leitura .g-waffle-titulo {
  max-width: 22ch;
  font-size: 15px;
  line-height: 1.45;
}

/* ---------- Matriz de calor ---------- */

.g-matriz {
  display: grid;
  gap: 3px;
  flex: 1;
  min-height: 0;
  width: 100%;
  /* Mesma barreira do funil: as linhas em `1fr` já garantem o encaixe, e o que
     sobra é fração de pixel. Sem isto ela acende a barra de rolagem do corpo. */
  overflow: hidden;
}

.g-matriz-cab,
.g-matriz-canto,
.g-matriz-lado {
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 11px;
  font-weight: 700;
  color: var(--text-muted);
}

.g-matriz-canto,
.g-matriz-lado {
  padding-right: 8px;
  justify-content: flex-end;
}

.g-matriz-canto {
  font-size: 10.5px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

/* A célula empilha duas camadas: a tinta de acento, cuja opacidade É o dado,
   e o número por cima. Camada separada, e não `background` calculado em JS,
   para a cor continuar saindo de var(--accent) e acompanhar o domínio. */
.g-matriz-celula {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: 0;
  border-radius: 4px;
  background: var(--bg-tertiary);
  overflow: hidden;
}

.g-matriz-tinta {
  position: absolute;
  inset: 0;
  background: var(--accent);
}

/* SEM SOMBRA. Havia `text-shadow: 0 1px 3px rgba(0,0,0,.75)` aqui, sustentando
   o texto claro sobre as células cheias de âmbar; no tema claro ele virava um
   borrão preto sob cada número da grade. Quem sustenta a leitura agora é a
   tinta, que acompanha o quanto a célula está cheia — ver `MATRIZ_TINTA_ESCURA`
   em graficos.js para o limiar e para o que se perde nessa troca. */
.g-matriz-num {
  position: relative;
  font-size: clamp(11px, 1.5vh, 13.5px);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--text-primary);
}

/* Célula cheia: o acento já cobriu o fundo e a leitura se inverte.
   `--on-accent` é exatamente a cor que a paleta reserva para texto sobre o
   acento — cada domínio define a sua, e por isso isto funciona nos quatro sem
   uma linha de condicional. */
.g-matriz-num.is-cheia {
  color: var(--on-accent);
}

/* ---------- Rosca de fatias ---------- */

/* Centrado dentro do bloco pelo mesmo motivo do waffle: encostado à esquerda,
   a rosca ficava na borda do cartão enquanto sobrava vão do outro lado. */
.g-roscaf {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 18px;
  min-width: 0;
  width: 100%;
}

/* A rosca acompanha a altura do cartão, com teto para não engolir a legenda
   num painel alto. */
.g-roscaf-svg {
  width: clamp(84px, 15vh, 132px);
  height: auto;
  flex-shrink: 0;
}

.g-roscaf-trilho {
  fill: none;
  stroke: var(--bg-tertiary);
}

.g-roscaf-arco {
  fill: none;
  transition: opacity var(--transition-fast);
}

.g-roscaf-arco:hover {
  opacity: 0.82;
}

.g-roscaf-legenda {
  display: flex;
  flex-direction: column;
  gap: 8px;
  min-width: 0;
}

/* Grade e não flex: os percentuais das linhas precisam alinhar entre si, e num
   flex cada linha resolveria a própria largura. */
.g-roscaf-item {
  display: grid;
  grid-template-columns: 9px auto 1fr auto;
  align-items: baseline;
  gap: 8px;
  min-width: 0;
}

.g-roscaf-cor {
  width: 9px;
  height: 9px;
  border-radius: 2px;
}

.g-roscaf-rotulo {
  font-size: 12px;
  color: var(--text-secondary);
  white-space: nowrap;
}

.g-roscaf-valor {
  font-size: 13.5px;
  font-weight: 700;
  white-space: nowrap;
}

.g-roscaf-pct {
  font-size: 11.5px;
  font-weight: 600;
  color: var(--accent-tinta);
  white-space: nowrap;
}

/* ---------- Colunas verticais ---------- */

/* O `padding-top` reserva o espaço dos rótulos, que flutuam acima do topo de
   cada barra. Como a altura de cada barra é percentual do trilho, e o trilho
   encolhe por igual, as proporções entre elas não mudam.
   Com selo o par ocupa duas linhas e a reserva dobra quase. */
.g-colunas {
  display: flex;
  align-items: stretch;
  gap: clamp(6px, 1.2vw, 16px);
  flex: 1;
  min-height: 0;
  width: 100%;
  padding-top: 20px;
}

.g-colunas--selo {
  padding-top: 36px;
}

.g-coluna {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-width: 0;
  min-height: 0;
  gap: 5px;
}

.g-coluna-valor,
/* O rótulo QUEBRA em várias linhas. `nowrap` servia enquanto todo eixo de
   colunas era curto ("0-5k", "18-24 anos"); com "Subutilização Crítica (<50%)"
   em quatro colunas, os quatro rótulos se encavalavam num único borrão de
   texto. Quebrando, cada um ocupa a largura da própria coluna — que é
   exatamente o espaço que ele tem direito a usar. */
.g-coluna-rotulo {
  text-align: center;
  flex-shrink: 0;
  line-height: 1.25;
  overflow-wrap: anywhere;
}

.g-coluna-valor {
  font-size: 11px;
  font-weight: 700;
  color: var(--text-secondary);
}

.g-coluna-rotulo {
  font-size: 11.5px;
  color: var(--text-muted);
}

/* O trilho absorve a sobra; a barra cresce de baixo para cima dentro dele. É
   o que faz a altura ser percentual do espaço disponível, e não de um número
   fixo que erraria em metade das janelas. */
.g-coluna-trilho {
  display: flex;
  align-items: flex-end;
  justify-content: center;
  flex: 1;
  min-height: 0;
}

/* Não ocupa a célula inteira: com a coluna colada na vizinha, o vão entre elas
   vinha só do `gap` e a leitura virava uma faixa contínua. Deixando folga dos
   dois lados, cada coluna se lê como uma barra. */
/* `relative` porque o rótulo do valor é ancorado NELA, e não no topo da
   célula — ver `.g-coluna-topo`. */
.g-coluna-barra {
  position: relative;
  width: 74%;
  min-height: 3px;
  border-radius: 3px 3px 0 0;
  background: var(--accent);
  transition: opacity var(--transition-fast);
}

.g-coluna-barra:hover {
  opacity: 0.82;
}

/* ---------- Abas e régua de corte ---------- */

/* Duas leituras do mesmo assunto, uma de cada vez. Abas e não dois painéis
   lado a lado: a segunda existe para confirmar a primeira, e vê-las juntas
   tiraria justamente o efeito de "isto se confirma aqui". */
.aba-barra {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

/* Sem `flex: 1`: esticados para a largura toda, os dois viravam blocos e o
   rótulo mais longo quebrava em duas linhas, dobrando a altura do cabeçalho do
   painel. Com `nowrap` cada um fica do tamanho do próprio texto. */
.aba-botao {
  padding: 5px 12px;
  border: 1px solid var(--border-color);
  border-radius: var(--radius-pill, 20px);
  background: transparent;
  color: var(--text-secondary);
  font-size: 11.5px;
  font-weight: 600;
  white-space: nowrap;
  cursor: pointer;
  transition: background var(--transition-fast), color var(--transition-fast),
              border-color var(--transition-fast);
}

.aba-botao:hover {
  background: var(--bg-hover);
  color: var(--text-primary);
}

.aba-botao[aria-selected="true"] {
  background: var(--bg-elevated);
  border-color: var(--border-color-light);
  color: var(--text-primary);
}

/* Régua de corte: os cinco alvos de receita. Ocupam a largura toda em partes
   iguais porque são uma escala, não um menu — a ordem e o espaçamento
   constante são parte da informação.

   O respiro acima é maior que o de baixo de propósito: a régua comanda os
   waffles, e o vão os separa o bastante para não parecerem a legenda deles.
   A altura sai da tabela, que rola de qualquer jeito — ver .tabela-caixa. */
.corte-regua {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 6px;
  margin: 24px 0 14px;
}

.corte-botao {
  padding: 5px 4px;
  border: 1px solid var(--border-color);
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--text-secondary);
  font-size: 12px;
  font-weight: 700;
  cursor: pointer;
  transition: background var(--transition-fast), color var(--transition-fast);
}

.corte-botao:hover {
  background: var(--bg-hover);
  color: var(--text-primary);
}

.corte-botao[aria-pressed="true"] {
  background: var(--accent);
  border-color: var(--accent);
  color: #241703;
}

.corte-frase {
  font-size: 12px;
  line-height: 1.55;
  color: var(--text-secondary);
  text-align: center;
}

.corte-frase strong {
  color: var(--text-primary);
}

.waffles-par {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
  /* Desgruda do cabeçalho do painel: as abas ficam logo acima e, encostados
     nelas, os waffles pareciam parte do controle em vez do resultado dele. */
  margin-top: 10px;
}

/* Centra o par grade+percentual na metade que lhe cabe. Como item de grade o
   .g-waffle já ocupa a célula inteira, mas o conteúdo dele nasce à esquerda e
   os dois blocos ficavam encostados na borda esquerda de cada metade. */
.waffles-par .g-waffle {
  justify-content: center;
}

/* ---------- Tabela do corte ---------- */

.tabela-corte {
  width: 100%;
  border-collapse: collapse;
  font-size: 12px;
}

.tabela-corte th {
  position: sticky;
  top: 0;
  padding: 6px 8px;
  background: var(--bg-secondary);
  border-bottom: 1px solid var(--border-color-light);
  color: var(--text-muted);
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  text-align: left;
}

.tabela-corte td {
  padding: 6px 8px;
  border-bottom: 1px solid var(--border-color);
}

.tabela-corte tr:last-child td {
  border-bottom: none;
}

.tabela-corte .col-num {
  text-align: right;
  font-variant-numeric: tabular-nums;
}

/* O nome é a única coluna que pode ser longa: ela absorve a sobra e trunca,
   para as três colunas numéricas nunca saírem do lugar. */
.tabela-corte .col-nome {
  max-width: 0;
  width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Absorve a sobra do painel em vez de ter altura fixa: o bloco acima dela
   muda de tamanho conforme o corte (a frase quebra em uma ou duas linhas), e
   uma altura fixa deixaria um vão embaixo num caso e cortaria no outro.

   É por ser `flex: 1` que os respiros acima podem ser generosos sem conta
   nenhuma: cada pixel dado aos waffles e à régua sai daqui, e a tabela rola
   desde o corte de 60% (18 linhas), então perder altura não esconde nada que
   já não estivesse abaixo da rolagem. */
.tabela-caixa {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
}

/* Painel cujo conteúdo se empilha do topo. O `center` herdado só faz sentido
   quando o corpo é um gráfico só; aqui há waffles, régua, frase e tabela, e
   centrar o conjunto esconderia o começo assim que ele passasse da altura. */
.painel--empilhado .painel-corpo {
  justify-content: flex-start;
}

/* Cabeçalho de uma seção DENTRO de um painel — o painel da esquerda tem duas.
   Sem ícone, e com respiro acima, para não competir com o cabeçalho do painel:
   é subtítulo, não outro cartão. */
.painel-topo--interno {
  margin-top: 16px;
  margin-bottom: 8px;
}

.painel-topo--interno .painel-titulo {
  font-size: 13px;
}

/* Variante para seção que ABRE uma coluna: não há nada acima dela para se
   descolar, então o respiro superior sairia como um degrau contra a coluna
   vizinha. Embaixo, ao contrário, o respiro precisa ser maior que o padrão —
   o que vem depois é o rótulo de valor das colunas, e com 8px ele encostava
   no subtítulo e os dois se liam como um bloco de texto só. */
.painel-topo--interno.is-no-topo {
  margin-top: 0;
  margin-bottom: 18px;
}

/* ---------- Painel com duas leituras lado a lado ---------- */

/* Um cartão só, dois blocos. É a forma do relatório de origem para pares que
   se leem juntos — faturamento por sexo e LTV por faixa descrevem os mesmos
   clientes por dois cortes.

   Cada bloco carrega o PRÓPRIO escopo no subtítulo. Aqui isso não é zelo
   excessivo: um dos dois responde ao filtro e o outro não, e agora eles
   dividem a mesma moldura — sem o rótulo, a moldura sugeriria que os dois
   falam do mesmo recorte. */
.painel-duplo {
  display: grid;
  grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.15fr);
  gap: 22px;
  flex: 1;
  min-height: 0;
  align-items: stretch;
}

/* Cabeçalho no topo e o desenho ocupando o resto — e NÃO o conjunto centrado.
   Centrar o bloco inteiro empurrava o título para o meio do cartão e roubava
   altura do desenho justamente onde ela falta. */
.painel-duplo-bloco {
  display: flex;
  flex-direction: column;
  min-width: 0;
  min-height: 0;
}

/* Absorve a sobra do bloco. O `center` vale para desenho de altura própria
   (a rosca); quem tem `flex: 1` — as colunas — ignora e preenche. */
.painel-duplo-corpo {
  display: flex;
  flex-direction: column;
  justify-content: center;
  flex: 1;
  min-width: 0;
  min-height: 0;
}

/* ---------- Concentração de venda ---------- */

.concentra-topo {
  display: flex;
  align-items: center;
  gap: 16px;
  /* Mesmo respiro que os waffles têm na aba Pareto: encostado nas abas, o
     bloco parecia parte do controle em vez do resultado dele. */
  margin-top: 10px;
}

/* A folga desta aba vai toda para o TOPO, e não repartida entre as barras:
   esticar os vãos da lista descola os itens uns dos outros sem motivo — eles
   são um ranking, e a distância entre eles não significa nada — e ainda joga
   a última barra em cima da linha do "Outros".
   Alinhando ao pé, o bloco inteiro desce, o vão vira respiro entre as abas e
   o waffle, e o conteúdo termina junto da borda inferior. */
/* Esta aba não tem elemento rolável para absorver o excesso — a lista de dez
   precisa aparecer inteira, sem barra de rolagem dentro do cartão.

   A lista encolhe o EXATO necessário em vez de seguir uma fórmula de altura de
   janela: como item de flex ela cede primeiro (`flex-shrink`), e o
   `min-height: 0` em cada elo permite descer abaixo do conteúdo natural. A
   barra acompanha a linha com `height: 100%`, entre um teto (a medida de
   projeto, 22px) e um piso (11px, abaixo do qual deixa de ser barra).
   Coeficiente em `vh` erraria nos dois sentidos: sobraria numa tela e faltaria
   noutra, e a conta teria de ser refeita a cada mudança de conteúdo. */
.concentra-barras {
  display: flex;
  flex-direction: column;
  min-height: 0;
}

.concentra-barras .g-barras {
  flex: 1;
  min-height: 0;
  gap: clamp(3px, 0.65vh, 7px);
}

/* A base de 22px é a medida de projeto — a linha PARTE dela e só cede se
   faltar espaço. Sem a base explícita a linha passaria a ser medida pelo texto
   do rótulo (~18px) e a barra encolheria mesmo num cartão com sobra. */
.concentra-barras .g-barra {
  flex: 0 1 22px;
  min-height: 0;
}

.concentra-barras .g-barra-trilho {
  height: 100%;
  min-height: 11px;
}

.painel-corpo.is-ao-pe .painel-topo--interno {
  margin-top: clamp(6px, 1.5vh, 16px);
}

.painel--empilhado .painel-corpo.is-ao-pe {
  /* `safe` pelo mesmo motivo do `safe center` do .painel-corpo: numa janela
     baixa o conteúdo passa a ser mais alto que o cartão, e alinhar ao pé sem
     ele empurraria o começo para fora do alcance da rolagem. */
  justify-content: flex-end;
  justify-content: safe flex-end;
}

/* O waffle tem largura fixa; o texto fica com a sobra. Sem o min-width:0 uma
   palavra longa impediria o flex de encolher e empurraria a grade. */
.concentra-leitura {
  min-width: 0;
  font-size: 11.5px;
  font-style: italic;
  line-height: 1.6;
  color: var(--text-secondary);
}

.concentra-leitura strong {
  color: var(--text-primary);
  font-style: normal;
}

.concentra-outros {
  margin-top: 10px;
  padding-top: 9px;
  border-top: 1px solid var(--border-color);
  font-size: 11px;
  font-style: italic;
  text-align: center;
  color: var(--text-muted);
}

/* ---------- Melhor/pior ---------- */

/* Tudo centralizado: são dois números em confronto, e alinhá-los à esquerda
   faria o par parecer duas colunas de uma tabela em vez de uma comparação. */
.extremos {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 14px;
  text-align: center;
}

.extremo-rotulo {
  font-size: 12px;
  color: var(--text-secondary);
}

.extremo.is-melhor .extremo-rotulo strong { color: var(--success-tinta); }
.extremo.is-pior   .extremo-rotulo strong { color: var(--danger-tinta); }

/* Sem flex:1 — quem centra verticalmente é o .painel-corpo. Deixar o bloco
   crescer o empurrava para o topo e jogava toda a sobra para o rodapé. */

.extremo-valor {
  margin-top: 7px;
  font-size: 23px;
  font-weight: 800;
  letter-spacing: -0.03em;
  line-height: 1.1;
}

.extremo-valor span {
  font-size: 13px;
  font-weight: 600;
  color: var(--text-secondary);
}

.extremo-apoio {
  margin-top: 5px;
  font-size: 11.5px;
  color: var(--text-muted);
}

.extremos-gap {
  margin-top: 14px;
  padding-top: 11px;
  border-top: 1px solid var(--border-color);
  font-size: 12px;
  text-align: center;
  color: var(--text-secondary);
}

.extremos-gap strong {
  color: var(--accent-tinta);
}

/* ---------- Confronto em caixa ---------- */

/* Variante do `.extremos` para o par que é uma DEMONSTRAÇÃO, e não um ranking.
   Em Comercial os dois números são a mesma margem medida de dois jeitos, e o
   ponto do cartão é a distância entre eles: a moldura separa as duas contas e
   deixa claro que não são duas categorias comparadas, e sim antes e depois.

   Modificador e não medida nova do `.extremos`: a Visão Executiva usa o bloco
   sem caixa e continua exatamente como estava. */
.extremos--caixa {
  gap: 18px;
}

/* Respiros em `clamp` de vh, e não fixos: este é o cartão mais cheio da tela —
   dois números grandes emoldurados MAIS a frase que os liga — e é o primeiro a
   estourar quando a janela baixa. O piso de cada clamp é o ponto em que a
   caixa ainda se lê como caixa; o teto é a medida de projeto. */
.extremos--caixa .extremo {
  padding: clamp(8px, 1.45vh, 13px) 12px clamp(7px, 1.3vh, 12px);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-md);
  /* Levemente mais claro que o painel, e não mais escuro: o cartão já é a cor
     de fundo secundária, e descer de novo faria a caixa parecer um buraco. */
  background: var(--veu-sutil);
}

/* Aqui quem carrega o juízo é o VALOR, não o rótulo. No `.extremos` original o
   rótulo diz "Melhor:"/"Pior:" e é ele que se pinta; aqui os rótulos são nomes
   de medida — pintá-los diria que uma forma de medir é melhor que a outra. */
.extremos--caixa .extremo-rotulo {
  font-size: 12.5px;
  color: var(--text-secondary);
}

.extremos--caixa .extremo.is-melhor .extremo-valor { color: var(--success-tinta); }
.extremos--caixa .extremo.is-pior   .extremo-valor { color: var(--danger-tinta); }

/* Peso 700 em vez dos 800 herdados. Aqui o número já é grande, colorido e
   emoldurado — três destaques somados — e o traço mais grosso deixava o dígito
   pastoso em vez de forte. Na Visão Executiva o mesmo bloco continua com 800:
   lá o valor não tem caixa nem cor de fundo para se apoiar. */
.extremos--caixa .extremo-valor {
  margin-top: clamp(5px, 1vh, 9px);
  font-size: clamp(21px, 3vh, 26px);
  font-weight: 700;
}

.extremos--caixa .extremo-apoio {
  margin-top: clamp(4px, 0.85vh, 7px);
}

/* Só onde a variante em caixa é usada — daí o seletor de irmão adjacente e não
   uma medida nova em `.extremos-gap`, que a Visão Executiva também usa. */
.extremos--caixa + .extremos-gap {
  margin-top: clamp(8px, 1.4vh, 12px);
  padding-top: clamp(6px, 1.1vh, 10px);
}

/* ---------- Treemap ---------- */

.g-treemap-caixa {
  flex: 1;
  min-width: 0;
  min-height: 0;
}

/* Os blocos são posicionados em pixels absolutos calculados no JS sobre a
   medida real da caixa — daí o `relative` aqui e o `absolute` neles. Não dá
   para fazer com grid: as fatias do squarified não se alinham em linhas nem em
   colunas, é essa a graça. */
.g-treemap {
  position: relative;
  width: 100%;
  height: 100%;
  overflow: hidden;
}

.g-treemap-bloco {
  position: absolute;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  padding: 7px 9px;
  border-radius: 3px;
  overflow: hidden;
}

/* Tinta clara em todos os blocos, e não conforme o tom como no funil: aqui o
   texto fica sobre o CANTO do bloco, e os tons 1 e 2 da rampa já são escuros o
   bastante nas bordas para o branco funcionar em toda a série. Uma cor de
   texto por bloco faria a lista de cidades mudar de cor a cada filtro. */
.g-treemap-rotulo {
  font-size: 13px;
  font-weight: 600;
  line-height: 1.2;
  color: #fff;
  /* O rótulo não pode empurrar o valor para fora: quando o nome não cabe, ele
     é cortado e o valor continua no pé do bloco, que é onde se procura. */
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.g-treemap-valor {
  font-size: 12px;
  font-weight: 700;
  color: #fff;
}

/* ---------- Mapa por estado ---------- */

/* Absorve TODA a sobra do painel — é o elemento que a tela veio mostrar. Ver
   `.mapa-painel` adiante para o que impede o ranking de disputar essa sobra. */
.g-mapa-caixa {
  flex: 1;
  min-width: 0;
  min-height: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* O quadro é a referência dos controles, que flutuam sobre o desenho. */
.g-mapa-quadro {
  position: relative;
  width: 100%;
  height: 100%;
  min-height: 0;
}

.g-mapa {
  width: 100%;
  height: 100%;
  /* Sem isto o navegador trata o arrasto de um dedo como rolagem da página e o
     `pointermove` nunca chega ao mapa. */
  touch-action: none;
}

.g-mapa-quadro.is-ampliado .g-mapa { cursor: grab; }
.g-mapa-quadro.is-ampliado .g-mapa:active { cursor: grabbing; }

.g-mapa-uf {
  /* A cor sai do acento do domínio; quem varia é a opacidade, calculada no JS
     a partir do valor. Mesma mecânica da matriz de calor. */
  fill: var(--accent);
  /* Traço da cor do fundo do painel: os estados se tocam, e o que separa um do
     outro é a fresta que este traço abre. Uma borda por cima faria o mapa
     parecer recortado com tesoura.

     `non-scaling-stroke` mantém a espessura em pixels de tela: com o zoom
     mexendo na viewBox, um traço em unidades de desenho engrossaria junto e, a
     12x, viraria uma teia por cima dos estados. */
  stroke: var(--bg-secondary);
  stroke-width: 1.1px;
  vector-effect: non-scaling-stroke;
  stroke-linejoin: round;
}

/* ---------- Sigla dentro do estado ---------- */

/* O tamanho vem do JS, em unidades de desenho recalculadas a cada zoom, para
   dar sempre os mesmos pixels na tela. */
.g-mapa-rotulo {
  font-size: var(--g-mapa-fonte, 11px);
  font-weight: 700;
  letter-spacing: 0.04em;
  fill: #fff;
  /* Contorno escuro por baixo do preenchimento: a sigla pousa sobre tons que
     vão do marrom quase preto ao âmbar aceso, e nenhuma cor chapada de texto
     se lê em cima dos dois. `paint-order` é o que põe o traço ATRÁS — sem ele
     o contorno comeria metade da letra. */
  stroke: rgba(0, 0, 0, 0.55);
  stroke-width: 2.6px;
  vector-effect: non-scaling-stroke;
  paint-order: stroke fill;
  text-anchor: middle;
  dominant-baseline: central;
  /* O rótulo não pode roubar o ponteiro do estado: quem responde ao passar do
     mouse com o valor é o <path>. */
  pointer-events: none;
  transition: opacity 0.15s ease;
}

/* Escondido, e não removido: o zoom o traz de volta assim que houver espaço, e
   a transição faz isso aparecer como revelação em vez de piscada. */
.g-mapa-rotulo.is-oculto { opacity: 0; }

/* ---------- Controles de zoom ---------- */

.g-mapa-ctrl {
  position: absolute;
  top: 0;
  right: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.g-mapa-bt {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  padding: 0;
  font-size: 13px;
  line-height: 1;
  color: var(--text-secondary);
  background: var(--bg-tertiary);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: color 0.15s ease, background 0.15s ease, border-color 0.15s ease;
}

.g-mapa-bt:hover {
  color: var(--accent-tinta);
  background: var(--bg-hover);
  border-color: var(--border-color-light);
}

/* O reset só existe quando há o que desfazer. Visível o tempo todo, ele seria
   um botão morto em 90% das aberturas da tela. */
.g-mapa-bt--reset { display: none; }
.g-mapa-quadro.is-ampliado .g-mapa-bt--reset { display: flex; }

/* ---------- Balão do estado ---------- */

/* Fundo elevado e não branco: o balão é a camada mais próxima do leitor, e
   `--bg-elevated` é justamente o tom que a plataforma reserva para o que
   flutua acima de tudo (popovers e selos). Branco seria um buraco de luz no
   meio de uma tela escura — é o que o relatório de origem faz e é o que se
   está corrigindo aqui.

   `pointer-events: none` é obrigatório: o balão anda colado no cursor, e se
   ele capturasse o ponteiro o estado embaixo deixaria de ser detectado e a
   leitura piscaria sem parar. */
.g-mapa-dica,
.g-dica {
  position: absolute;
  z-index: 3;
  min-width: 178px;
  padding: 9px 11px 10px;
  background: var(--bg-elevated);
  border: 1px solid var(--border-color-light);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-lg);
  pointer-events: none;
}

.g-mapa-dica-topo,
.g-dica-topo {
  display: flex;
  align-items: baseline;
  gap: 7px;
  padding-bottom: 7px;
  margin-bottom: 7px;
  border-bottom: 1px solid var(--border-color);
}

/* A sigla no acento do domínio: é o elo entre o balão e o estado aceso embaixo
   dele. */
.g-mapa-dica-sigla,
.g-dica-nome {
  font-size: 14px;
  font-weight: 800;
  letter-spacing: 0.02em;
  color: var(--accent-tinta);
}

.g-mapa-dica-sub,
.g-dica-sub {
  font-size: 11px;
  color: var(--text-muted);
}

.g-mapa-dica-linhas,
.g-dica-linhas {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

/* Rótulo à esquerda, valor à direita e o vão no meio — a mesma leitura da
   ficha do relatório, sem a tabela. O `gap` de 18px impede que um rótulo longo
   ("% Pedidos Frete Grátis") encoste no número. */
.g-mapa-dica-linha,
.g-dica-linha {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 18px;
  font-size: 11.5px;
}

.g-mapa-dica-linha dt,
.g-dica-linha dt {
  color: var(--text-secondary);
}

.g-mapa-dica-linha dd,
.g-dica-linha dd {
  font-weight: 700;
  color: var(--text-primary);
  white-space: nowrap;
}

/* Painel do mapa: o desenho fica com a sobra e o ranking desce para o pé.

   Sem isto o mapa não cresce. `.barras-encolhem` nasce com `flex: 1` — nas
   telas em que ele é o único conteúdo do cartão isso é o certo — e aqui os dois
   passariam a dividir a folga meio a meio, deixando o mapa com metade do que
   podia ter. Devolvendo o ranking à altura natural dele, toda a sobra vai para
   o desenho e o título desce junto. */
.mapa-painel .barras-encolhem {
  flex: 0 1 auto;
}

/* Respiro maior que o `painel-topo--interno` padrão: aqui o que vem acima é um
   desenho que sangra até a borda, e 16px o deixavam colado no título. */
.mapa-painel .painel-topo--interno {
  margin-top: clamp(14px, 2.6vh, 24px);
}

/* ---------- Insights & Recomendações ---------- */

/* As duas grades são IRMÃS dos dois cabeçalhos, e não filhas de seções
   aninhadas. Isso é o que faz as três linhas de cartão terem a mesma altura sem
   nenhuma medida fixa: os cabeçalhos ficam com a altura do texto (`0 0 auto`) e
   a sobra é repartida 2:1 entre as grades — dois terços para as duas linhas de
   achados, um terço para a linha de ações. Aninhado, o `flex` das seções
   incluiria o cabeçalho na conta e as linhas sairiam desiguais. */
.insights {
  display: flex;
  flex-direction: column;
  gap: 10px;
  flex: 1;
  min-height: 0;
}

.insight-topo {
  display: flex;
  align-items: center;
  gap: 9px;
  flex: 0 0 auto;
}

.insight-num {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 19px;
  height: 19px;
  font-size: 11px;
  font-weight: 800;
  color: var(--accent-tinta);
  background: var(--accent-soft);
  border-radius: var(--radius-sm);
  flex-shrink: 0;
}

.insight-secao {
  font-size: 13px;
  font-weight: 600;
  color: var(--text-secondary);
}

.insight-grade {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 12px;
  min-height: 0;
}

/* Duas linhas contra uma: ver a nota do `.insights`. `minmax(0, 1fr)` nas
   linhas é o que permite o cartão ceder altura numa janela baixa em vez de
   estourar a dobra. */
.insight-grade--achados {
  flex: 2;
  grid-auto-rows: minmax(0, 1fr);
}

.insight-grade--acoes {
  flex: 1;
  grid-auto-rows: minmax(0, 1fr);
}

@media (max-width: 1180px) {
  .insight-grade { grid-template-columns: minmax(0, 1fr); }
  .insight-grade--achados,
  .insight-grade--acoes { flex: 0 0 auto; grid-auto-rows: auto; }
}

/* ---------- Cartão de achado ---------- */

/* A faixa de cor no topo é o único lugar em que o tom aparece antes do número.
   É de propósito: quem bate o olho na tela precisa saber de longe quantos
   achados são alerta e quantos são boa notícia, sem ler nenhum deles. */
.achado {
  display: flex;
  flex-direction: column;
  min-width: 0;
  min-height: 0;
  overflow: hidden;
  padding: 12px 14px 13px;
  background: var(--bg-secondary);
  border: 1px solid var(--border-color);
  border-top: 2px solid var(--achado-cor);
  border-radius: var(--radius-md);
}

.achado--alerta  { --achado-cor: var(--danger); }
.achado--bom     { --achado-cor: var(--success); }
.achado--atencao { --achado-cor: var(--warning); }

/* ---------- Resposta ao ponteiro ---------- */

/* Mesma linguagem dos cartões de capacidade do login: o cartão sobe 2px, a
   borda clareia e a sombra dá a distância do fundo. O que muda é a cor do
   banho: lá é o verde da marca, fixo; aqui é a cor do PRÓPRIO cartão — vermelho
   no achado de alerta, verde no positivo, âmbar no de atenção. O tom já está na
   faixa do topo, e a lavagem só o derrama para dentro.

   A borda de cima é preservada na declaração de três valores (topo / laterais /
   base): trocar o `border-color` inteiro apagaria a faixa colorida justo na
   hora em que ela deve ficar mais evidente. */
.achado,
.acao {
  transition: transform var(--transition-fast),
              border-color var(--transition-fast),
              box-shadow var(--transition-fast),
              background var(--transition-fast);
}

.achado:hover {
  transform: translateY(-2px);
  border-color: var(--achado-cor) var(--border-color-light) var(--border-color-light);
  background:
    linear-gradient(180deg,
      color-mix(in srgb, var(--achado-cor) 9%, transparent) 0%,
      transparent 46%),
    var(--bg-secondary);
  box-shadow: var(--shadow-md);
}

.acao:hover {
  transform: translateY(-2px);
  border-color: var(--accent) var(--border-color-light) var(--border-color-light);
  background:
    linear-gradient(180deg,
      color-mix(in srgb, var(--accent) 9%, transparent) 0%,
      transparent 46%),
    var(--bg-secondary);
  box-shadow: var(--shadow-md);
}

/* Quem prefere menos movimento na tela não recebe o salto — só o realce de cor,
   que é o que carrega a informação de "estou aqui". */
@media (prefers-reduced-motion: reduce) {
  .achado, .acao { transition: border-color var(--transition-fast), background var(--transition-fast); }
  .achado:hover, .acao:hover { transform: none; }
}

.achado-topo {
  display: flex;
  align-items: center;
  gap: 7px;
  margin-bottom: 7px;
}

.achado-icone {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 21px;
  height: 21px;
  border-radius: var(--radius-sm);
  color: var(--achado-cor);
  /* Fundo tirado da própria cor do tom, e não um cinza fixo: assim a pastilha
     acompanha os três tons sem três regras. */
  background: color-mix(in srgb, var(--achado-cor) 16%, transparent);
  flex-shrink: 0;
}

.achado-icone .icone { width: 12px; height: 12px; }

.achado-chapa {
  font-size: 11px;
  font-weight: 600;
  color: var(--text-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.achado-titulo {
  font-size: 13.5px;
  font-weight: 700;
  line-height: 1.3;
  margin-bottom: 8px;
}

/* O invólucro é quem fica com a sobra do cartão e centra o texto nela. Precisa
   existir: o parágrafo é um `-webkit-box` — é assim que o corte por número de
   linhas funciona — e um `-webkit-box` não se alinha sozinho dentro do flex.

   `safe center` pelo motivo de sempre: quando o texto é mais alto que a folga,
   centrar de verdade esconderia o começo dos dois lados; com o `safe` o
   alinhamento cai para o topo e o corte acontece só no pé. */
.achado-corpo,
.acao-corpo {
  display: flex;
  flex-direction: column;
  justify-content: center;
  justify-content: safe center;
  flex: 1;
  min-height: 0;
  overflow: hidden;
}

/* Centrado como no relatório de origem. E com `line-clamp`: o texto é o
   conteúdo mais elástico do cartão, e numa janela baixa ele é quem tem de
   ceder — cortado com reticências, e não empurrando o número para fora. */
.achado-texto {
  min-height: 0;
  font-size: 11.5px;
  line-height: 1.5;
  text-align: center;
  color: var(--text-secondary);
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 4;
  line-clamp: 4;
  overflow: hidden;
}

.achado-numero {
  margin-top: 10px;
  font-size: 21px;
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1.1;
  color: var(--achado-cor);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.achado-apoio {
  margin-top: 5px;
  font-size: 11px;
  color: var(--text-muted);
}

/* ---------- Cartão de ação ---------- */

/* É um <button>: além do cartão, precisa desfazer o que o navegador impõe a um
   controle — alinhamento centralizado, tipografia própria e largura de
   conteúdo. */
.acao {
  display: flex;
  flex-direction: column;
  min-width: 0;
  min-height: 0;
  width: 100%;
  overflow: hidden;
  padding: 12px 14px 12px;
  font: inherit;
  color: inherit;
  text-align: left;
  background: var(--bg-secondary);
  border: 1px solid var(--border-color);
  border-top: 2px solid var(--accent);
  border-radius: var(--radius-md);
}

/* O anel de foco fica FORA do cartão: por dentro ele encostaria na faixa
   colorida do topo e se leria como parte do desenho. */
.acao:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.acao-topo {
  display: flex;
  align-items: flex-start;
  gap: 9px;
  margin-bottom: 8px;
}

.acao-num {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 19px;
  height: 19px;
  font-size: 11px;
  font-weight: 800;
  color: var(--accent-tinta);
  background: var(--accent-soft);
  border-radius: var(--radius-sm);
  flex-shrink: 0;
}

.acao-titulo {
  font-size: 13px;
  font-weight: 700;
  line-height: 1.3;
}

.acao-texto {
  min-height: 0;
  font-size: 11.5px;
  line-height: 1.55;
  text-align: center;
  color: var(--text-secondary);
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 5;
  line-clamp: 5;
  overflow: hidden;
}

/* O pé fecha o cartão com duas coisas diferentes nas duas pontas: à esquerda a
   PROCEDÊNCIA (de quais achados a recomendação saiu) e à direita o DESTINO
   (para onde o clique leva). Separadas por uma linha porque nenhuma das duas é
   parte do argumento — uma é de onde veio, a outra é para onde vai. */
.acao-liga {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  margin-top: 10px;
  padding-top: 8px;
  border-top: 1px solid var(--border-color);
  font-size: 10.5px;
  font-weight: 600;
  color: var(--accent-tinta);
}

.acao-fonte {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.acao-destino {
  display: inline-flex;
  align-items: baseline;
  gap: 4px;
  white-space: nowrap;
  flex-shrink: 0;
}

/* A seta anda ao passar o mouse. É o que diz "isto vai te levar a algum lugar"
   sem precisar de mais texto num pé que já tem duas informações. */
.acao-seta {
  display: inline-block;
  font-size: 13px;
  line-height: 1;
  transition: transform var(--transition-fast);
}

.acao:hover .acao-seta,
.acao:focus-visible .acao-seta {
  transform: translateX(3px);
}

/* ============================================================
   Financeiro · Visão Geral
   ============================================================ */

/* ---------- Panorama (os dois lados) ---------- */

/* A moldura das duas colunas. Existe por causa da DIVISÓRIA: no relatório de
   origem ela corre do topo do panorama até o pé do aging, e uma linha por
   bloco quebraria no vão entre eles.

   Desenhada em ::before a 50%: com duas colunas iguais, a metade cai
   exatamente no meio do vão, e a linha acompanha qualquer largura sem depender
   do valor do `column-gap`. Absoluta, então não vira item da grade nem
   atrapalha o empilhamento. */
.fin-colunas {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 12px;
  flex: 0 0 auto;
  min-width: 0;
}

.fin-colunas::before {
  content: "";
  position: absolute;
  left: 50%;
  top: 0;
  bottom: 0;
  width: 1px;
  background: var(--border-color-light);
  pointer-events: none;
}

/* Receber e pagar lado a lado, com a MESMA estrutura interna. É o que permite
   comparar os dois de relance: o saldo do esquerdo está na altura do saldo do
   direito, e os dois medidores no mesmo eixo.

   O vão entre as colunas é maior que o das grades comuns (30px contra 12): é
   ele que dá respiro à divisória, e de quebra tira largura de cartões e barras
   que estavam esticados demais. */
.fin-panorama {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 12px 30px;
  flex: 0 0 auto;
  min-height: 0;
}

/* A Inadimplência espelha os dois lados INTEIROS, não bloco a bloco: cada lado
   é uma coluna com seus quatro painéis, e a divisória corre entre elas de cima
   a baixo. Mesmo vão de 30px da Visão Geral, pelo mesmo motivo. */
.fin-colunas--inad {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 12px 30px;
}

@media (max-width: 1180px) {
  /* Numa coluna só não há dois lados para separar. */
  .fin-panorama { grid-template-columns: minmax(0, 1fr); }
  .fin-colunas--inad { grid-template-columns: minmax(0, 1fr); }
  .fin-colunas::before { display: none; }
}

/* ---------- Inadimplência ---------- */

/* Alturas fixas, como no floating da Visão Geral e pelo mesmo motivo: sem uma
   altura definida, o SVG medido cai na altura intrínseca e o ResizeObserver
   remede maior a cada quadro. */
.painel--inad-aging { flex: 0 0 auto; height: 216px; }
.painel--inad-var   { flex: 0 0 auto; height: 210px; }
.painel--inad-serie { flex: 0 0 auto; height: 250px; }

.painel--inad-aging .painel-corpo,
.painel--inad-var .painel-corpo,
.painel--inad-serie .painel-corpo {
  display: flex;
  flex-direction: column;
  min-height: 0;
  flex: 1;
}

.painel--inad-top .painel-corpo { padding-top: 2px; }

.g-combo-caixa {
  flex: 1;
  min-width: 0;
  min-height: 0;
}

/* O selo da variação, entre o valor e a coluna. Fundo tingido e não só texto
   colorido: são doze deles na tela, e em texto puro virariam um mosaico de
   vermelho e verde disputando com as barras. */
.g-coluna-selo {
  align-self: center;
  flex-shrink: 0;
  min-height: 15px;
  padding: 1px 6px;
  border-radius: 999px;
  font-size: 9.5px;
  font-weight: 700;
  white-space: nowrap;
  color: var(--text-muted);
}

/* Alta de inadimplência é RUIM e baixa é BOA — o contrário da leitura usual de
   "subiu = verde". Por isso os tons são nomeados pela direção do número e
   pintados pela consequência. */
.g-coluna-selo.is-alta  { background: var(--danger-soft);  color: var(--danger-tinta); }
.g-coluna-selo.is-baixa { background: var(--success-soft); color: var(--success-tinta); }

/* Ancorado no topo da BARRA, e não no topo da célula: com alturas desiguais um
   rótulo alinhado lá em cima deixa de dizer de quem é. A reserva de espaço
   está no `.g-colunas`, junto do resto do layout. */
.g-coluna-topo {
  position: absolute;
  bottom: calc(100% + 3px);
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  pointer-events: none;
  /* NÃO QUEBRA LINHA, e isto não é preferência de estilo — é o que conserta um
     corte. Um absoluto com `left` e sem `right` tem a largura de
     encolhe-para-caber limitada ao que sobra até a borda direita do pai: com
     `left: 50%`, METADE da barra. Medido: barra de 114px, 57px para o rótulo.
     "268h 20min" não cabia, quebrava em duas linhas, e as duas linhas passavam
     dos 20px reservados acima do gráfico — o topo do rótulo saía cortado.
     Sem quebra ele volta a uma linha e cabe; centrado pelo `translateX`, se um
     dia for mais largo que a barra ele transborda para os dois lados por
     igual, que é o comportamento certo para um rótulo de valor. */
  white-space: nowrap;
}

/* A barra mais inadimplente sai do acento. Vermelho e não uma quarta cor: o
   lado Receber já é teal e o Pagar já é âmbar, e esta é a única marcação que
   precisa saltar dos DOIS sem virar mais um elemento da paleta de cada um —
   além de ser, de fato, a leitura de risco. */
.g-barra-preenche.is-destaque { background: var(--danger); }

/* As duas séries da `linhaMultipla`. `--serie-b` é o azul neutro que a paleta
   já reserva para a segunda série de uma comparação A vs. B.

   Só o TRAÇO troca de stroke; o ponto troca de `fill` e mantém o stroke da cor
   do fundo, que é o halo que o separa da linha quando os dois se cruzam. */
.g-linha-traco.is-a { stroke: var(--accent); }
.g-linha-ponto.is-a { fill: var(--accent); }
.g-linha-traco.is-b { stroke: var(--serie-b); }
.g-linha-ponto.is-b { fill: var(--serie-b); }

.g-linha-marca { fill: var(--accent); }
.g-linha-marca.is-a { fill: var(--accent); }
.g-linha-marca.is-b { fill: var(--serie-b); }

/* Na Inadimplência a segunda série NÃO é o azul neutro: é o Pagar, e a tela
   inteira já o codifica em âmbar. Este é o único desenho onde os dois lados
   aparecem juntos, então ele repete as duas cores que o leitor acabou de ver em
   vez de introduzir uma terceira. */
.painel--inad-serie .g-linha-traco.is-b { stroke: var(--warning); }
.painel--inad-serie .g-linha-ponto.is-b,
.painel--inad-serie .g-linha-marca.is-b { fill: var(--warning); }

.fin-lado {
  display: flex;
  flex-direction: column;
  gap: 7px;
  min-width: 0;
}

/* RECEBER e PAGAR são coisas diferentes, e a cor é o que diz isso antes de
   qualquer rótulo ser lido. O lado do pagar redefine `--accent` no próprio
   bloco — mesmo mecanismo do `[data-dominio]` no <body>, aplicado a um pedaço
   da tela em vez da página inteira. Tudo que sai do acento acompanha sozinho:
   o título, o ícone do saldo e as barras do aging. Nenhuma cor precisa ser
   escrita nos componentes.

   A mesma classe vale no painel de aging, que vive em outra grade. */
.fin-lado--pagar {
  --accent: var(--warning);
  --accent-soft: var(--warning-soft);
  --accent-tinta: var(--warning-tinta);
  --on-accent: #241703;
}

.fin-lado-titulo {
  font-size: 13px;
  font-weight: 700;
  color: var(--accent-tinta);
}

/* O cartão externo do lado. Dentro dele, só o saldo ganha borda própria — a
   inadimplência e o medidor dividem esta superfície, que é o que o relatório
   de origem faz e o que os mantém lidos como uma coisa só. */
.fin-grupo {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 152px;
  gap: 10px;
  padding: 10px;
  background: var(--bg-secondary);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-md);
}

.fin-grupo-col {
  display: flex;
  flex-direction: column;
  gap: 8px;
  min-width: 0;
}

/* O sub-cartão do saldo. Um pouco mais claro que o grupo, e não mais escuro:
   o cartão já é a superfície escura da plataforma, e descer de novo abriria um
   buraco em vez de destacar. */
.fin-saldo {
  display: flex;
  flex-direction: column;
  justify-content: center;
  flex: 1;
  min-width: 0;
  padding: 10px 12px;
  background: var(--veu-sutil);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-sm);
}

/* Sem borda e sem fundo: está sobre o cartão externo, junto do medidor.

   O recuo à esquerda é o que alinha o ícone de alerta com o do saldo, logo
   acima. Ele precisa somar o que o sub-cartão do saldo acrescenta por conta
   própria — 1px de borda mais 12px de respiro —, senão os dois ícones ficam
   11px fora de prumo dentro do mesmo cartão. */
.fin-inad {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 0 2px 2px 13px;
}

/* O medidor tem largura fixa e o resto fica com a sobra: uma rosca que estica
   deixa de ser redonda, e a leitura de "quanto do círculo está pintado"
   depende de ele ser um círculo. */
.fin-grupo-medidor {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

/* Ícone à esquerda, rótulo ocupando o resto: é o `is-centro` no rótulo que o
   deixa no meio do cartão, e não do espaço que sobrou do ícone. */
.fin-cartao-topo {
  display: flex;
  align-items: center;
  gap: 8px;
}

.fin-cartao-icone {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  border-radius: var(--radius-sm);
  color: var(--text-secondary);
  background: var(--bg-tertiary);
  flex-shrink: 0;
}

.fin-cartao-icone.is-acento { color: var(--accent-tinta); background: var(--accent-soft); }
.fin-cartao-icone.is-alerta { color: var(--warning-tinta); background: var(--warning-soft); }

.fin-cartao-icone .icone { width: 12px; height: 12px; }

.fin-cartao-rotulo {
  font-size: 11.5px;
  color: var(--text-secondary);
}

/* Compensa a largura do ícone para o texto ficar no centro do CARTÃO. Sem
   isso ele fica no centro da sobra, deslocado 15px para a direita. */
.fin-cartao-rotulo.is-centro {
  flex: 1;
  text-align: center;
  margin-right: 30px;
}

.fin-cartao-valor {
  margin-top: 10px;
  font-size: clamp(17px, 2.4vh, 21px);
  font-weight: 700;
  letter-spacing: -0.02em;
  text-align: center;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.fin-cartao-cols {
  display: grid;
  grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr);
  gap: 10px;
  flex: 1;
  min-width: 0;
}

.fin-cartao-col {
  display: flex;
  flex-direction: column;
  gap: 3px;
  min-width: 0;
}

/* `--alerta` e não `--danger`, igual ao cartão Inadimplente da tela de
   Inadimplência. O danger é dessaturado de propósito — é o vermelho de leitura,
   feito para conviver aos montes numa tela sem gritar — e num número de 13px
   sobre fundo escuro ele sai rosado. Aqui não são dezenas: são dois números, e
   os dois nomeiam o problema que a tela existe para mostrar. Manter os dois
   vermelhos diferentes entre as duas telas do Financeiro faria "inadimplente"
   ter duas cores dependendo de onde se olha. */
.fin-cartao-num {
  font-size: 13px;
  font-weight: 700;
  color: var(--alerta);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* O arco do medidor acompanha, e SÓ aqui: `is-perigo` é o tom genérico de
   "perigo" do componente de rosca, e levá-lo ao vermelho saturado no arquivo
   todo mudaria o significado dele para as telas que ainda vão usá-lo. O arco
   divide o cartão com os dois números — deixá-lo no rosa antigo colocaria dois
   vermelhos dentro da mesma moldura. */
.fin-grupo-medidor .g-rosca-arco.is-perigo { stroke: var(--alerta); }

.fin-medidor {
  display: flex;
  align-items: center;
  justify-content: center;
  flex: 1;
  min-height: 0;
  margin-top: 6px;
}

.fin-medidor .g-rosca { width: 100%; }

/* ---------- Controles do fluxo ---------- */

.fin-controles {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex: 0 0 auto;
  flex-wrap: wrap;
}

.fin-abas {
  display: flex;
  gap: 6px;
}

.fin-aba {
  padding: 5px 13px;
  font-size: 11.5px;
  font-weight: 600;
  color: var(--text-secondary);
  background: var(--bg-secondary);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-sm);
  transition: color var(--transition-fast), background var(--transition-fast),
              border-color var(--transition-fast);
}

.fin-aba:hover {
  color: var(--text-primary);
  border-color: var(--border-color-light);
}

/* A aba ativa é o acento cheio, não uma borda: são sete opções lado a lado e
   um contorno sozinho não separa a escolhida das vizinhas de relance. */
.fin-aba.is-ativa {
  color: var(--on-accent);
  background: var(--accent);
  border-color: var(--accent);
}

.fin-aba:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* ---------- Fora da dobra ---------- */

/* Análise que PODE ser mais alta que a janela, por decisão de projeto. A Visão
   Geral do Financeiro é o caso: a página de origem foi desenhada em 1280x1060,
   e são cinco blocos densos que perderiam a leitura se fossem espremidos.

   Quem rola é a ÁREA DE CONTEÚDO, não a página: o `.app` continua travado em
   100vh, então a sidebar e o cabeçalho ficam parados e só a análise anda.
   Deixar a página inteira crescer levaria o menu e o filtro de período para
   fora da tela — no relatório de origem isso acontece, mas lá não há menu
   lateral para perder.

   As duas regras desfazem, só para esta análise, o `overflow: hidden` do
   conteúdo e o `height: 100%` da coluna. A especificidade é a MESMA (`:has()`
   vale pelo argumento mais específico, e `.analise--rolavel` é uma classe como
   `.analise`), então o que decide é a ordem — e é por isso que este bloco mora
   aqui embaixo, e não junto das regras que ele corrige. */
.conteudo:has(.analise--rolavel) {
  overflow-y: auto;
}

/* O respiro do fim fica no CONTEÚDO, não no contêiner de rolagem. Posto como
   `padding-bottom` do `.conteudo` ele não aparece: o navegador não conta a
   borda inferior de um contêiner rolável como espaço percorrível, e o rodapé
   continuava terminando a meio pixel da borda. No filho, entra no
   `scrollHeight` e a rolagem vai até depois dele.

   Nas análises da dobra isso não existe: lá o rodapé é a última coisa da tela
   e encostar embaixo está certo, porque nada vem depois. Aqui ele é o fim de
   uma rolagem, e sem folga o texto para colado na barra do sistema, dando a
   impressão de que a página foi cortada. */
.analise--rolavel {
  height: auto;
  padding-bottom: 26px;
}

/* Sem dobra não há sobra para repartir: cada bloco fica com a altura do próprio
   conteúdo, e quem cede é a página. O vão entre as colunas acompanha o do
   panorama, para a divisória cair no meio dos dois blocos. */
.analise-grade--fin-aging {
  flex: 0 0 auto;
  column-gap: 30px;
}

/* Uma coluna de ícones para a tela inteira. O painel padrão põe o dele a 17px
   da borda; o do saldo cai em 24, porque o sub-cartão soma a própria borda e o
   próprio respiro ao recuo do grupo. Trazer o saldo para 17 exigiria espremer
   o sub-cartão, então quem se move é o painel — e como modificador da tela, não
   mexendo na medida de `.painel`, que vale para as outras vinte análises. */
.analise-grade--fin-aging .painel {
  padding-left: 23px;
}

/* Altura DEFINIDA, e não `min-height`. O gráfico é medido e desenhado sobre o
   tamanho da caixa; a caixa tem `height: 100%` e o painel, `flex: 1`. Fora da
   dobra, a coluna da análise deixa de ter altura definida — e aí `height: 100%`
   não resolve, o SVG cai no tamanho intrínseco da viewBox, o ResizeObserver
   mede maior, redesenha maior, e o painel cresce a cada quadro. Chegou a 6.978
   px antes de eu travar. Com altura definida a cadeia fecha e o laço não
   existe. 200px é onde a curva tem amplitude para as pílulas de valor. */
.painel--fin-floating {
  flex: 0 0 auto;
  height: 200px;
}

.painel--fin-tabela { flex: 0 0 auto; }

/* ---------- Gráfico de linha ---------- */

/* Rola na horizontal DENTRO do cartão, igual à tabela do fluxo: acima de umas
   duas dezenas de dias o desenho fica mais largo que a caixa em vez de se
   espremer nela. O `overflow-y: hidden` impede que a barra horizontal, ao
   aparecer, provoque também uma vertical de um fio. */
.g-linha-caixa {
  flex: 1;
  min-width: 0;
  min-height: 0;
  overflow-x: auto;
  overflow-y: hidden;
}

/* `block` e não o `inline` padrão do SVG: como elemento de linha ele ganha o
   espaço do descendente da fonte embaixo, e são 5px que fazem o corpo do painel
   transbordar e acender barra de rolagem. */
.g-linha { display: block; width: 100%; height: 100%; }

.g-linha-area {
  fill: var(--accent);
  fill-opacity: 0.13;
}

.g-linha-traco {
  fill: none;
  stroke: var(--accent);
  stroke-width: 2;
  stroke-linejoin: round;
  stroke-linecap: round;
}

.g-linha-ponto {
  fill: var(--accent);
  stroke: var(--bg-secondary);
  stroke-width: 1.5;
}

.g-linha-zero {
  stroke: var(--border-color-light);
  stroke-width: 1;
  stroke-dasharray: 3 3;
}

.g-linha-pilula {
  fill: var(--bg-elevated);
  stroke: var(--border-color);
  stroke-width: 1;
}

.g-linha-valor {
  font-size: 10px;
  font-weight: 700;
  fill: var(--text-primary);
}

/* Saldo negativo: a pílula inverte para fundo claro e texto escuro. É a única
   inversão do tema, e é de propósito — num acumulado de caixa o que se procura
   é o trecho em que a curva deve, e ele precisa saltar da faixa. */
.g-linha-pilula.is-negativo {
  fill: var(--danger-light);
  stroke: var(--danger);
}

.g-linha-valor.is-negativo { fill: var(--on-danger-light); }

.g-linha-eixo {
  font-size: 10px;
  fill: var(--text-muted);
}

/* ---------- Tabela do fluxo ---------- */

/* Rola na horizontal DENTRO do cartão. Em 180 dias são 181 colunas — é o que o
   relatório de origem faz, e é o que mantém a regra da dobra: a página nunca
   cresce, quem anda é a tabela. */
.fin-tab-caixa {
  flex: 1;
  min-width: 0;
  min-height: 0;
  overflow: auto;
}

.fin-tab {
  border-collapse: collapse;
  width: 100%;
  font-size: 11px;
  white-space: nowrap;
}

.fin-tab th,
.fin-tab td {
  padding: 4px 10px;
  text-align: right;
}

.fin-tab thead th {
  font-weight: 600;
  color: var(--text-secondary);
  border-bottom: 1px solid var(--border-color);
  /* O cabeçalho das datas tem duas linhas e o TOTAL tem uma. Alinhado pela
     base, o TOTAL fica na mesma linha das datas em vez de flutuar no meio. */
  vertical-align: bottom;
}

/* O dia da semana em cima da data. Sem ele o leitor precisa contar no calendário
   para entender por que uma coluna zerou — e nas janelas longas, de 90 ou 180
   dias, isso é impossível de fazer de cabeça. */
.fin-tab-dow {
  display: block;
  margin-bottom: 1px;
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-muted);
}

/* Sábado e domingo em azul: é a única marcação que precisa saltar sem competir
   com o teal do Financeiro (acento) nem com o vermelho das saídas. */
.fin-tab thead th.is-fds,
.fin-tab thead th.is-fds .fin-tab-dow { color: var(--info-tinta); }
.fin-tab-num.is-fds { color: var(--info-tinta); }

/* A coluna dos rótulos gruda na esquerda ao rolar: sem ela, num horizonte de
   90 dias o leitor perde qual linha está olhando. */
.fin-tab tbody th,
.fin-tab-canto {
  position: sticky;
  left: 0;
  z-index: 1;
  text-align: left;
  font-weight: 600;
  color: var(--text-primary);
  background: var(--bg-secondary);
}

.fin-tab-canto { z-index: 2; }

.fin-tab tbody tr + tr th,
.fin-tab tbody tr + tr td {
  border-top: 1px solid var(--border-color);
}

.fin-tab-num { color: var(--text-primary); font-variant-numeric: tabular-nums; }
.fin-tab-num.is-saida { color: var(--danger-tinta); }
.fin-tab-num.is-negativo { color: var(--danger-tinta); }
.fin-tab-total { color: var(--accent-tinta); font-weight: 700; }

/* ---------- Realizado ---------- */

.rea-bloco {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

/* O total e os seis indicadores dividem UMA faixa. No relatório de origem o
   total é a âncora da linha e os seis ao lado são a decomposição dele; em duas
   fileiras separadas pareceriam sete medidas independentes. */
.rea-faixa {
  display: grid;
  grid-template-columns: minmax(190px, 0.85fr) 3fr;
  gap: 12px;
  flex: 0 0 auto;
}

/* Mesma superfície dos demais cartões. O destaque fica por conta do ÍCONE e do
   TÍTULO no acento do lado — teal no recebido, âmbar no pago — e do corpo maior
   do número. Um fundo tingido a mais competia com as barras e os selos que já
   carregam a cor do lado logo abaixo. */
.rea-destaque {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 7px;
  padding: 13px 16px;
  background: var(--bg-secondary);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-md);
}

.rea-destaque-topo {
  display: flex;
  align-items: center;
  gap: 9px;
}

/* Pastilha igual à dos KPIs das outras telas: fundo do acento diluído, glifo no
   acento cheio. O acento sólido de antes vinha do fundo tingido — sozinho num
   cartão escuro ele virava o elemento mais forte da faixa. */
.rea-destaque-icone {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  border-radius: var(--radius-sm);
  background: var(--accent-soft);
  color: var(--accent-tinta);
  flex-shrink: 0;
}

.rea-destaque-icone .icone { width: 14px; height: 14px; }

.rea-destaque-rotulo {
  font-size: 12.5px;
  font-weight: 700;
  color: var(--accent-tinta);
}

.rea-destaque-valor {
  font-size: 23px;
  font-weight: 800;
  color: var(--text-primary);
  letter-spacing: -0.01em;
}

.rea-itens {
  display: grid;
  grid-template-columns: repeat(6, minmax(0, 1fr));
  gap: 10px;
  padding: 13px 15px;
  background: var(--bg-secondary);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-md);
}

.rea-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 7px;
  min-width: 0;
}

.rea-item-rotulo {
  font-size: 11.5px;
  color: var(--text-secondary);
  text-align: center;
  line-height: 1.25;
}

.rea-item-valor {
  font-size: 15px;
  font-weight: 700;
  color: var(--text-primary);
  white-space: nowrap;
}

/* O % de atraso é o único dos seis que tem sinal de bom ou ruim. `--danger` e
   não `--alerta`: é um rótulo de leitura ao lado de cinco números neutros, não
   um aviso — o vermelho saturado fica reservado para os cartões de
   inadimplência. */
.rea-item-valor.is-alerta { color: var(--danger-tinta); }

/* A série é o gráfico mais largo dos três: é o único que carrega uma forma, e
   espremida em um terço ela vira um risco. */
.analise-grade--rea {
  grid-template-columns: 1.15fr 1fr 1fr;
  flex: 0 0 auto;
}

/* Altura definida pelo mesmo motivo do floating da Visão Geral: sem ela o SVG
   medido cai na altura intrínseca e o ResizeObserver remede maior a cada
   quadro. Os três painéis compartilham a altura para a fileira ficar reta. */
.painel--rea-serie,
.painel--rea-dep { height: 238px; }

.painel--rea-serie .painel-corpo,
.painel--rea-dep .painel-corpo {
  display: flex;
  flex-direction: column;
  min-height: 0;
  flex: 1;
}

/* Dez departamentos em 238px não cabem inteiros: a lista rola dentro do
   cartão, como a tabela do fluxo. Cortar em cinco esconderia metade do
   ranking, e encolher as barras deixaria os rótulos ilegíveis. */
.painel--rea-dep .g-barras {
  overflow-y: auto;
  min-height: 0;
  flex: 1;
}

@media (max-width: 1180px) {
  .rea-faixa { grid-template-columns: minmax(0, 1fr); }
  .rea-itens { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .analise-grade--rea { grid-template-columns: minmax(0, 1fr); }
}

/* ---------- Ações de um painel ---------- */

.painel-acao {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  border: 1px solid var(--border-color);
  border-radius: var(--radius-sm);
  background: var(--bg-tertiary);
  color: var(--text-secondary);
  cursor: pointer;
  transition: color var(--transition-fast), border-color var(--transition-fast),
              background var(--transition-fast);
}

.painel-acao:hover { color: var(--accent-tinta); border-color: var(--accent); }
.painel-acao .icone { width: 14px; height: 14px; }

/* Desabilitado continua visível, só apagado: o botão de exportar some da mão
   quando a biblioteca não carrega, e sumir de vez faria a pessoa procurar um
   botão que ela viu ontem. Apagado com `title` explicando é honesto. */
.painel-acao:disabled { opacity: .4; cursor: not-allowed; }
.painel-acao:disabled:hover { color: var(--text-secondary); border-color: var(--border-color); }

/* Ligado fica com a cara do acento — o botão de foco precisa dizer que a tela
   está num estado diferente, senão o único indício é o tamanho. */
.painel-acao[aria-pressed="true"] {
  background: var(--accent-soft);
  border-color: var(--accent);
  color: var(--accent-tinta);
}

/* Mesma gramática do menu lateral: seta para a direita fechado, para baixo
   aberto. Quem já abriu uma categoria da sidebar não precisa aprender nada. */
.painel-acao-caret { transition: transform var(--transition-base); }
.painel-acao[aria-expanded="true"] .painel-acao-caret { transform: rotate(90deg); }

/* ---------- Modo de foco ---------- */

/* Camada por cima da aplicação, não fullscreen do navegador: o Esc continua
   sendo do documento, o cabeçalho volta na hora e nada pisca em tela cheia. */
.painel.is-foco {
  position: fixed;
  inset: 14px;
  z-index: 60;
  height: auto;
  margin: 0;
  display: flex;
  flex-direction: column;
  box-shadow: var(--sombra-modal);
}

/* O corpo passa a mandar na altura, e a tabela rola dentro dele. É isto que
   faz o foco valer a pena: em vez de a matriz crescer para fora da dobra, ela
   ganha a janela inteira e mostra mais linhas de uma vez. */
.painel.is-foco .painel-corpo {
  flex: 1;
  min-height: 0;
  display: flex;
}

.painel.is-foco .fin-tab-caixa { max-height: none; }

/* A matriz de calor no foco: a caixa cresce com o painel e a tabela para de
   esticar as linhas — em tela cheia o que se quer é ver MAIS linhas, não linhas
   mais altas. */
.painel.is-foco .g-tabela-caixa { max-height: none; }
.painel.is-foco .g-tabela { height: auto; }

/* Escurece o que ficou atrás. Sem isso a camada flutua sobre um fundo de mesma
   cor e não se lê como "modo". */
body.tem-foco::after {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 55;
  background: var(--veu-modal);
}

/* ---------- DRE ---------- */

.dre-cartoes {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 12px;
  flex: 0 0 auto;
}

.dre-cartao {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 14px 16px;
  background: var(--bg-secondary);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-md);
}

.dre-cartao-topo { display: flex; align-items: flex-start; gap: 10px; }

.dre-cartao-icone {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  flex-shrink: 0;
  border-radius: var(--radius-sm);
  background: var(--accent-soft);
  color: var(--accent-tinta);
}

.dre-cartao-icone.is-bom    { background: var(--success-soft); color: var(--success-tinta); }
.dre-cartao-icone.is-alerta { background: var(--danger-soft);  color: var(--danger-tinta); }
.dre-cartao-icone .icone { width: 14px; height: 14px; }

.dre-cartao-titulo { font-size: 12.5px; font-weight: 700; color: var(--text-primary); }
.dre-cartao-periodo { font-size: 10.5px; color: var(--text-muted); margin-top: 1px; }

.dre-cartao-valor {
  font-size: 26px;
  font-weight: 800;
  letter-spacing: -0.015em;
  color: var(--success-tinta);
}

.dre-cartao-valor.is-negativo { color: var(--danger-tinta); }

.dre-cartao-pes {
  display: flex;
  flex-direction: column;
  gap: 3px;
  font-size: 11px;
}

.dre-cartao-pes > div { display: flex; gap: 6px; }
.dre-cartao-pes dt { color: var(--text-muted); }
.dre-cartao-pes dd { color: var(--text-secondary); font-weight: 600; }

/* O valor ao lado do mês, um degrau abaixo dele na hierarquia: o mês é a
   resposta ("quando"), o valor é o contexto ("quanto"). Mesma cor do rótulo à
   esquerda, para os três elementos da linha se lerem como rótulo · resposta ·
   contexto e não como três informações de mesmo peso. */
.dre-cartao-pe-valor {
  margin-left: 7px;
  color: var(--text-muted);
  font-weight: 500;
}
.dre-cartao-ah { margin-top: 3px; }

.dre-var { font-weight: 700; white-space: nowrap; }
.dre-var.is-sobe  { color: var(--success-tinta); }
.dre-var.is-desce { color: var(--danger-tinta); }
.dre-var.is-vazio { color: var(--text-muted); font-weight: 500; }

/* A seta é o que se lê PRIMEIRO — antes do número, e às vezes no lugar dele,
   quando o olho só quer saber a direção. No mesmo corpo do percentual ela
   virava pontuação. Elemento próprio para poder crescer sem mexer no dígito,
   que precisa continuar alinhado com os das outras linhas. */
.dre-seta {
  font-style: normal;
  font-size: 1.35em;
  font-weight: 700;
  line-height: 0;
  margin-left: 3px;
  vertical-align: -1px;
}

/* ---- Ponto de equilíbrio ---- */

/* Altura pelo conteúdo, não mais fixa em 208px, e padding igual ao do cartão
   (o painel comum usa 14px 16px 16px; o cartão, 14px 16px). Com o bloco da
   esquerda tendo os mesmos filhos de um cartão, este painel passa a medir o
   mesmo que os três de cima POR CONSTRUÇÃO — não há número para manter em dia
   quando o conteúdo do cartão mudar. */
.painel--dre-equilibrio {
  flex: 0 0 auto;
  height: auto;
  padding-bottom: 14px;
}

.painel--dre-equilibrio .painel-corpo { display: flex; flex: 1; min-height: 0; }

/* Lucro Líquido à esquerda, ponto de equilíbrio à direita. A coluna larga é a
   do lucro porque ela carrega a sparkline dos doze meses — a da meta só tem a
   barra e dois números, e esticá-la deixaria a barra comprida demais para o
   que ela mede. Ao trocar os blocos de lado, as larguras trocam junto. */
.dre-equilibrio {
  display: grid;
  grid-template-columns: minmax(0, 1.4fr) minmax(260px, 1fr);
  gap: 26px;
  flex: 1;
  min-height: 0;
}

/* Alinhado ao topo, e não centrado como era: agora este bloco abre com o
   cabeçalho do painel, e ele precisa nascer na mesma altura do cabeçalho do
   Lucro Líquido ao lado. Centrado, os dois títulos ficariam em linhas
   diferentes e o par pareceria desalinhado por engano. */
.dre-meta { display: flex; flex-direction: column; gap: 5px; }

/* O cabeçalho já traz 12px embaixo; com o gap da coluna somando, o respiro até
   o número grande virava um degrau maior que o do outro lado. */
.dre-meta .painel-topo { margin-bottom: 4px; }

/* Verde, e não o acento: o ponto de equilíbrio é uma meta — a leitura é
   "bateu ou não bateu", a mesma do percentual logo abaixo, que já é verde
   quando passa de 100%. O acento fica reservado ao Lucro Líquido, do outro
   lado, que é resultado e não meta. */
.dre-meta .painel-icone { background: var(--success-soft); color: var(--success-tinta); }

.dre-meta-pct { font-size: 30px; font-weight: 800; letter-spacing: -0.02em; }
.dre-meta-pct.is-bom  { color: var(--success-tinta); }
.dre-meta-pct.is-ruim { color: var(--danger-tinta); }

.dre-meta-rotulo { font-size: 11px; color: var(--text-muted); }

/* Barra e não arco: o progresso passa de 100% e um círculo cheio não sabe
   mostrar excesso. A marca fica no ponto de equilíbrio e o preenchimento a
   ultrapassa quando se bate acima da meta. */
/* Mais fina e mais curta que antes (era 9px de altura e a largura inteira da
   coluna): esticada de ponta a ponta ela pesava mais que o número que ilustra,
   e a altura extra empurrava o painel para além dos cartões de cima. O limite
   de largura não afeta a leitura — preenchimento e marca dos 100% são
   percentuais da própria barra, então a proporção é a mesma em qualquer
   comprimento. */
.dre-barra {
  position: relative;
  height: 6px;
  max-width: 320px;
  margin: 5px 0 3px;
  border-radius: 999px;
  background: var(--bg-tertiary);
  overflow: visible;
}

.dre-barra-preenche {
  height: 100%;
  border-radius: 999px;
  background: var(--danger);
  transition: width var(--transition-fast);
}

.dre-barra-preenche.is-bom { background: var(--success); }

.dre-barra-meta {
  position: absolute;
  top: -4px;
  bottom: -4px;
  width: 2px;
  border-radius: 1px;
  background: var(--text-secondary);
}

.dre-meta-detalhe { font-size: 11.5px; color: var(--text-secondary); }

/* Duas colunas: a leitura à esquerda, o gráfico ao lado. O gráfico ficava
   embaixo do valor, e isso deixou de caber quando o bloco ganhou os três pés
   do cartão — empilhados, sobrariam uns 30px de altura para a sparkline. */
.dre-lucro {
  display: grid;
  grid-template-columns: minmax(178px, auto) minmax(0, 1fr);
  gap: 18px;
  min-width: 0;
  min-height: 0;
}

/* O `gap: 10px` não é escolha estética: é o mesmo do `.dre-cartao`. Junto com o
   padding igualado do painel, é ele que faz este bloco medir exatamente o que
   medem os cartões da linha de cima. Mexer num sem o outro desalinha a faixa. */
.dre-lucro-info {
  display: flex;
  flex-direction: column;
  gap: 10px;
  min-width: 0;
}

/* O valor no acento, e não no verde dos cartões de cima. Lá o verde diz "este
   indicador é dos bons"; aqui o número é o resultado que a matriz fecha, e o
   acento é a cor com que ele aparece na tabela do DRE. Mesma razão do ícone. */
.dre-lucro-info .dre-cartao-valor { color: var(--accent-tinta); }
.dre-lucro-info .dre-cartao-valor.is-negativo { color: var(--danger-tinta); }

/* ---- O desenho da série, igual ao do relatório de origem ----
   Traço mais grosso e marcador maior que o padrão da plataforma. O padrão foi
   calibrado para gráficos que ocupam um painel inteiro; aqui a série divide
   espaço com um número grande ao lado, e na escala reduzida 2px de traço e 3px
   de ponto somem. As regras ficam escopadas para não engrossar as linhas das
   outras nove telas. */
.dre-lucro .g-linha-traco { stroke-width: 3; }
.dre-lucro .g-linha-ponto { r: 4.5; stroke-width: 2; }

/* A largura era o que mais afastava do original: solta, a série se espalhava
   pela metade da tela e achatava as variações — doze meses viram uma régua.
   Com o teto, a proporção volta a ser a do relatório, e a folga que sobra
   separa este bloco do ponto de equilíbrio ao lado. */
.dre-lucro .g-linha-caixa { max-width: 430px; }

/* A marca do zero não existe no desenho de origem. Ela ajuda onde a série
   cruza o eixo e o leitor precisa saber de que lado está; aqui o valor já está
   escrito ao lado em corpo grande, e a linha pontilhada só competia com o
   traço. */
.dre-lucro .g-linha-zero { display: none; }

/* ---- Matriz ---- */

.painel--dre-tabela { flex: 0 0 auto; }

.dre-tab thead th { vertical-align: bottom; }

/* "Valor" e "%AH" no azul neutro: são RÓTULOS DE MEDIDA, não meses. Em cinza
   somem, e na cor do texto competiriam com os nomes dos meses logo acima —
   que é o que de fato organiza a leitura horizontal. */
.dre-tab .dre-sub {
  font-size: 10px;
  font-weight: 600;
  color: var(--info-tinta);
  padding-top: 1px;
}

/* A coluna do %AH anda colada no valor que ela qualifica: é a mesma leitura,
   não uma segunda medida. */
.dre-ah {
  text-align: right;
  font-size: 10.5px;
  padding-left: 2px !important;
  white-space: nowrap;
}

/* As linhas '=' são resultado, não movimento. Vão INTEIRAS no azul — rótulo e
   números —, o que faz achar Receita Líquida, Lucro Bruto, EBITDA e Lucro
   Líquido sem ler as treze.

   O azul e não o acento do domínio: o teal já é a cor de tudo no Financeiro e
   aqui precisava de algo que separasse subtotal de movimento dentro da MESMA
   tabela. E o `--info` é o azul que a paleta reserva para marcação neutra.

   A única coisa que NÃO acompanha é o %AH: ali o vermelho e o verde dizem
   direção, e trocá-los por azul apagaria a leitura que importa. */
.dre-tab tbody tr.is-subtotal th,
.dre-tab tbody tr.is-subtotal td {
  font-weight: 700;
  color: var(--info-tinta);
}

.dre-tab tbody tr.is-subtotal .fin-tab-num.is-negativo { color: var(--info-tinta); }

/* O %AH mantém o próprio tom. Vem depois para ganhar da regra acima. */
.dre-tab tbody tr.is-subtotal .dre-var.is-sobe  { color: var(--success-tinta); }
.dre-tab tbody tr.is-subtotal .dre-var.is-desce { color: var(--danger-tinta); }

.dre-tab tbody th {
  max-width: 300px;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ---- As três réguas do relatório de origem ----

   A coluna de rótulos tem 284px, ditados pela linha mais longa ("CMV / CPV —
   Custo das Mercadorias Vendidas"). Os rótulos curtos deixam vão até ali, e sem
   uma régua esse vão lê como buraco entre o nome e o número — foi o que se viu.
   A borda fecha a coluna e o vão vira margem.

   Ela vai no ACENTO e não no cinza das bordas comuns porque separa duas coisas
   de naturezas diferentes — o que se mede e as medidas —, não duas células
   vizinhas. É a mesma decisão do relatório de origem. E como a coluna é sticky,
   a régua acompanha a rolagem horizontal, que é justamente quando ela mais
   importa. */
/* A vertical vive só no CORPO. No canto ela virava uma ponta subindo acima da
   régua do cabeçalho, sem fechar nada — a divisão que ela marca começa onde
   começam os dados. */
.dre-tab tbody th { border-right: 2px solid var(--accent); }

/* `width: 1%` é o truque padrão para "encolher até o conteúdo" numa tabela de
   largura 100%: o navegador dá à coluna só o que ela precisa e reparte o resto
   entre as outras.

   Sem isso, com POUCOS MESES a coluna de rótulos esticava. Em 2026 há três
   meses — oito colunas ao todo —, e a tabela precisa preencher os 100% de
   qualquer jeito: sobrava largura, e a maior parte ia para a primeira coluna,
   afastando o nome da linha do seu próprio número. Com doze meses o problema
   não aparecia porque não sobra nada para repartir. */
.dre-tab .fin-tab-canto,
.dre-tab tbody th { width: 1%; white-space: nowrap; }

/* A régua horizontal fecha só a faixa de "Valor / %AH" — a que de fato termina
   o cabeçalho. Sob a linha dos MESES não vai nada: eles já se separam pelo
   agrupamento das duas colunas, e uma segunda régua ali criava duas divisões
   onde existe uma. */
.dre-tab thead tr:first-child th { border-bottom: none; }
.dre-tab thead tr:last-child th  { border-bottom: 1px solid var(--accent); }

/* O mês manda nas DUAS colunas abaixo dele, então fica no centro delas. O canto
   fica de fora: é vazio, e centralizar nada não faz diferença.

   E "Valor"/"%AH" TAMBÉM centralizam, nas colunas deles. Isso não é simetria
   por gosto: herdando o `text-align: right` da tabela, o texto "Valor" ficava
   empurrado para a borda direita da coluna — a 359px, praticamente em cima do
   centro geométrico do par, que é 355. O mês, corretamente centralizado, caía
   sobre ele e parecia desalinhado. Com os rótulos no centro das próprias
   colunas o mês passa a ficar visivelmente ENTRE os dois.

   Os NÚMEROS do corpo continuam à direita, porque ali o que importa é o
   alinhamento das casas entre uma linha e outra. */
.dre-tab thead tr:first-child th:not(.fin-tab-canto),
.dre-tab thead tr:last-child th { text-align: center; }

/* O canto tem `rowspan=2` e mora na PRIMEIRA linha do cabeçalho — a regra acima
   o zerava junto com os meses. Sem isto a régua começava só depois dele, e o
   trecho da esquerda, justamente onde fica o botão de expandir, ficava sem
   fechamento. A régua atravessa o cabeçalho inteiro e a vertical nasce dela
   para baixo.

   O seletor repete `thead tr:first-child` de propósito: precisa empatar em
   especificidade com a regra que zera a linha dos meses e ganhar por vir
   depois. Só `.dre-tab .fin-tab-canto` perde e a borda não aparece. */
.dre-tab thead tr:first-child th.fin-tab-canto {
  border-bottom: 1px solid var(--accent);
}

/* ---- Abrir até o plano de contas ---- */

/* O botão é INLINE dentro da célula, e a célula continua uma célula de tabela.
   Com `display: flex` no <th> o navegador perde a largura intrínseca do
   conteúdo — combinado com o `width: 1%` acima, a coluna colapsava para os
   22px do botão e o rótulo sumia. */
/* O "+" e o "−" são DESENHADOS, não escritos. Como glifos eles nunca centram
   num quadrado de 15px: o "+" se apoia no eixo matemático da fonte e o "−" fica
   ainda mais alto, então cada um sentava numa altura diferente e nenhuma era o
   meio do botão. Duas barras posicionadas por `transform` centram por
   construção e não dependem de fonte nenhuma.

   O texto continua no HTML, invisível: serve de reserva se o CSS não carregar,
   e o estado real quem carrega é o `aria-expanded`. */
.dre-abrir {
  position: relative;
  display: inline-block;
  /* `middle` nos DOIS — botão e rótulo. Sozinho no botão, ele se alinharia
     pela linha de base do texto e ficaria alto; um deslocamento fixo em pixels,
     como eu tinha, só acerta num corpo de fonte. Com os dois na mesma
     referência eles se centram um pelo outro. */
  vertical-align: middle;
  margin-right: 6px;
  width: 15px;
  height: 15px;
  flex-shrink: 0;
  border: 1px solid var(--border-color);
  border-radius: 3px;
  background: var(--bg-tertiary);
  color: var(--text-secondary);
  font-size: 0;
  cursor: pointer;
  transition: color var(--transition-fast), border-color var(--transition-fast);
}

.dre-abrir:not(.is-vazio)::before,
.dre-abrir:not(.is-vazio)::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  background: currentColor;
}

.dre-abrir::before { width: 7px; height: 1px; }   /* barra do "-" e do "+" */
.dre-abrir::after  { width: 1px; height: 7px; }   /* haste que faz o "+"   */

/* Aberto vira "−": some a haste. */
.dre-abrir[aria-expanded="true"]::after { display: none; }

/* Os controles da matriz moram no CANTO do cabeçalho — o retângulo que sobrou
   quando o rótulo "DRE" saiu dali. Alinhados à esquerda de propósito: ficam na
   mesma coluna dos botões de expandir das linhas, logo acima deles, e o gesto
   "isto comanda aquela coluna" se lê sem legenda. */
.dre-acoes {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 2px 0;
}

.dre-abrir:hover { color: var(--info-tinta); border-color: var(--info); }

/* Ocupa o lugar sem desenhar nada: sem isso, as linhas que não abrem ficariam
   com o rótulo 22px à esquerda das que abrem. */
.dre-abrir.is-vazio { border-color: transparent; background: none; cursor: default; }

/* O par do `vertical-align` acima: o rótulo precisa da mesma referência do
   botão, senão só um dos dois se move. */
.dre-tab tbody th > span { vertical-align: middle; }

/* Linha aberta: um degrau na escala de fundos, nada além disso. `--bg-tertiary`
   é o tom logo acima do painel — dá para ver de onde saíram as contas sem que a
   linha vire um destaque que compete com os subtotais em azul.

   O `th` precisa ser dito à parte: ele é sticky e carrega o próprio fundo, que
   de outra forma passaria por cima da cor da linha ao rolar na horizontal. */
.dre-tab tbody tr.is-aberta > th,
.dre-tab tbody tr.is-aberta > td { background: var(--bg-tertiary); }

.dre-tab tbody tr.is-aberta .dre-abrir {
  border-color: var(--info);
  color: var(--info-tinta);
}

.dre-conta.is-oculta { display: none; }

.dre-conta th { font-weight: 500; color: var(--text-secondary); }

/* Recuo do nível de conta: 15px do botão mais o vão, para o nome da conta
   começar exatamente onde começa o da linha que a contém. */
.dre-conta-nome { padding-left: 22px; font-size: 10.5px; }

.dre-conta .fin-tab-num { color: var(--text-secondary); }

@media (max-width: 1180px) {
  .dre-cartoes { grid-template-columns: minmax(0, 1fr); }
  .dre-equilibrio { grid-template-columns: minmax(0, 1fr); }
  .painel--dre-equilibrio { height: auto; }

  /* Empilhado, o gráfico perde a altura que herdava da coluna vizinha e a
     caixa nasce com zero — e `aoMedir` desiste de desenhar abaixo de 2px, ou
     seja, a sparkline simplesmente sumiria em vez de encolher. */
  .dre-lucro { grid-template-columns: minmax(0, 1fr); }
  .dre-lucro .g-linha-caixa { min-height: 90px; }
}

/* ---------- Estados ---------- */

/* ---------- People Analytics · Visão Geral ---------- */

/* A tela NÃO rola: `.analise` já é `height: 100%`, e as três faixas repartem o
   que sobra. Os cartões têm altura natural; o miolo e o rodapé disputam a
   folga em proporção. Se um painel novo entrar aqui, a altura sai de um destes
   dois números — não existe para onde empurrar. */
.rh-kpis {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 10px;
  flex: 0 0 auto;
}

.rh-meio { display: grid; grid-template-columns: 1.15fr 1fr 0.85fr; gap: 12px; flex: 1.35 1 0; min-height: 0; }
.rh-baixo { display: flex; flex: 1 1 0; min-height: 0; }
.rh-baixo > .painel { flex: 1; min-height: 0; }

/* Três leituras num cartão só. A do meio é texto e fala das outras duas, então
   fica entre elas — e por isso não há borda separando nada aqui. */
.rh-rodape {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr) minmax(0, 1fr);
  gap: 20px;
  flex: 1;
  min-height: 0;
}

.rh-bloco { display: flex; flex-direction: column; gap: 2px; min-width: 0; min-height: 0; }

.rh-kpis .rh-cartao,
.rh-meio > .painel,
.rh-baixo > .painel { min-height: 0; }

/* Cartão compacto: são oito numa faixa, contra três no DRE. O valor cai de
   26px para 21px e o rodapé desaparece — com oito cartões, uma linha de apoio
   em cada viraria um parágrafo distribuído pela tela. */
/* Compacto de propósito: a faixa de oito cartões divide a janela com cinco
   painéis, e cada pixel gasto aqui sai da altura dos gráficos — ou empurra o
   rodapé para fora da tela, que foi o que aconteceu na primeira versão. */
.rh-cartao {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 8px 12px;
  background: var(--bg-secondary);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-md);
}

.rh-cartao-topo { display: flex; align-items: center; gap: 8px; }

.rh-cartao-icone {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  flex-shrink: 0;
  border-radius: var(--radius-sm);
  background: var(--bg-tertiary);
  color: var(--text-secondary);
}

.rh-cartao-icone .icone { width: 13px; height: 13px; }
.rh-cartao-icone.is-acento { background: var(--accent-soft); color: var(--accent-tinta); }
.rh-cartao-icone.is-bom    { background: var(--success-soft); color: var(--success-tinta); }
.rh-cartao-icone.is-alerta { background: var(--danger-soft);  color: var(--danger-tinta); }

.rh-cartao-titulo { font-size: 11.5px; font-weight: 600; color: var(--text-secondary); }

.rh-cartao-valor {
  font-size: 19px;
  font-weight: 800;
  letter-spacing: -0.015em;
  color: var(--text-primary);
}

.rh-cartao-valor.is-acento { color: var(--accent-tinta); }
.rh-cartao-valor.is-alerta { color: var(--danger-tinta); }

/* Rosca e barras lado a lado. A rosca não cresce com a caixa — ela tem tamanho
   próprio —, então a coluna dela é fixa e a folga toda vai para as faixas, que
   são cinco e precisam de largura para o rótulo caber numa linha. */
.rh-composicao {
  display: grid;
  grid-template-columns: 132px minmax(0, 1fr);
  gap: 16px;
  align-items: center;
  flex: 1;
  min-height: 0;
}

/* A rosca empilha: desenho em cima, legenda embaixo. Lado a lado — que é o
   padrão do componente — a legenda transbordava da coluna e escrevia por cima
   das barras de faixa etária. */
.rh-genero { min-width: 0; }
.rh-genero .g-roscaf { flex-direction: column; align-items: center; gap: 10px; }
.rh-genero .g-roscaf-svg { width: 96px; height: 96px; }
.rh-genero .g-roscaf-legenda { width: 100%; }
.rh-genero .g-roscaf-item { font-size: 10.5px; }
/* Dois números por linha não cabem em 132px. Fica o percentual, que é a leitura
   da rosca; a contagem exata está no cartão de headcount. */
.rh-genero .g-roscaf-valor { display: none; }

.rh-faixas { min-width: 0; }

/* Número grande à esquerda, série à direita — a mesma gramática do Lucro
   Líquido no DRE, para as duas telas se lerem com o mesmo vocabulário. */
/* `stretch`, e não `center`: com os itens centrados, a coluna da esquerda ficava
   com a altura natural do número e a caixa do gráfico nascia com zero — o
   `aoMedir` desiste abaixo de 2px, e a linha do turnover simplesmente não
   aparecia. */
.rh-turnover {
  display: grid;
  grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr);
  gap: 16px;
  align-items: stretch;
  flex: 1;
  min-height: 0;
}

.rh-rodape .rh-narrativa { align-self: center; }

/* A rosca do relatório de origem é AMARELA e BRANCA, não dois tons de dourado.
   Redefinir a variável aqui, e não sobrescrever o `stroke`, porque o componente
   escreve a cor em atributo `style` inline — uma regra de folha de estilo
   perderia para ele, e só um `!important` venceria. Custom property inline
   resolve no contexto do elemento, então basta trocá-la no ancestral. */
.rh-genero { --rampa-2: #f2f0e8; }

/* Pílula de valor no acento, com texto escuro — como no relatório. O padrão da
   plataforma é fundo neutro, que funciona nos outros domínios porque o acento
   deles é escuro e a pílula precisava se destacar do traço; em dourado, o
   traço é claro e quem precisa de contraste é o texto. */
/* Marcador maior que o padrão da plataforma. As três séries desta tela são
   curtas — seis pontos —, e num desenho suavizado o ponto é o que diz onde
   está o dado medido e onde está a interpolação. Com 3px ele desaparecia sob
   o traço de 2px. */
/* Marcador de 8px de RAIO — o dobro do que era. Nesta escala ele deixa de ser
   um detalhe do traço e passa a ser o elemento principal do desenho, que é o
   efeito pedido: são seis a doze pontos por série, e cada um é um mês inteiro.
   O contorno sobe junto, senão dois meses vizinhos com valores próximos viram
   uma mancha só. */
.analise[data-dominio="rh"] .g-linha-ponto { r: 8px; stroke-width: 2.5; }

.analise[data-dominio="rh"] .g-linha-pilula { fill: var(--accent); }
.analise[data-dominio="rh"] .g-linha-valor  { fill: var(--on-accent); font-weight: 700; }



.rh-destaque {
  font-size: 23px;
  font-weight: 800;
  letter-spacing: -0.015em;
  color: var(--accent-tinta);
}

.rh-destaque.is-bom    { color: var(--success-tinta); }
.rh-destaque.is-alerta { color: var(--danger-tinta); }

/* O turnover é a ÚNICA série vermelha da tela, como no relatório de origem.
   Não é decoração: as outras duas — headcount e variação de quadro — medem
   coisas que sobem e descem sem juízo de valor, e o turnover não. A cor
   responde antes de o leitor chegar ao eixo. */
/* O seletor repete `.analise[data-dominio="rh"]` de propósito: a regra dourada
   do domínio tem três classes, e sem repetir o ancestral esta teria duas e
   perderia — o rótulo saía dourado sobre fundo rosa, misturando as duas cores.
   Vermelho cheio no fundo e texto claro, como no relatório de origem: rosa é o
   `--danger-light`, que a plataforma usa para saldo negativo em acumulado de
   caixa, e não é isto aqui. */
/* #B82631 é o vermelho do relatório de origem, informado pelo dono do projeto —
   não é o `--danger` da plataforma, que é mais claro e mais alaranjado. Fica
   como variável nomeada e local: é a cor DAQUELE gráfico, não um novo tom do
   tema, e ninguém deve alcançá-la a partir de outra tela. */
/* Sobe para a raiz da tela porque agora dois cartões de KPI também a usam —
   turnover e demissões. Continua LOCAL: não entra no tema, para nenhuma outra
   tela alcançá-la por acidente. */
.analise[data-dominio="rh"] { --risco: #b82631; }

.rh-cartao-icone.is-risco { background: rgba(184, 38, 49, 0.16); color: var(--risco); }
.rh-cartao-valor.is-risco { color: var(--risco); }

/* Valor negativo vira vermelho em qualquer série da tela — ponto e pílula. Na
   variação de quadro isso é a leitura inteira: a linha atravessa o zero doze
   vezes no ano, e a cor diz de que lado está cada mês sem obrigar a procurar a
   linha tracejada. O traço em si continua dourado, porque ele é UMA série e
   não muda de identidade a cada ponto. */
.analise[data-dominio="rh"] .g-linha-ponto.is-negativo  { fill: var(--risco); }
.analise[data-dominio="rh"] .g-linha-pilula.is-negativo { fill: var(--risco); stroke: none; }
.analise[data-dominio="rh"] .g-linha-valor.is-negativo  { fill: #fff; }

.analise[data-dominio="rh"] .rh-bloco--risco .g-linha-traco  { stroke: var(--risco); }
.analise[data-dominio="rh"] .rh-bloco--risco .g-linha-ponto  { fill: var(--risco); stroke: var(--bg-secondary); }
.analise[data-dominio="rh"] .rh-bloco--risco .g-linha-pilula { fill: var(--risco); stroke: none; }
.analise[data-dominio="rh"] .rh-bloco--risco .g-linha-valor  { fill: #fff; }
.analise[data-dominio="rh"] .rh-bloco--risco .rh-destaque    { color: var(--risco); }

.rh-narrativa {
  font-size: 12px;
  line-height: 1.55;
  color: var(--text-secondary);
}

.rh-narrativa strong { color: var(--text-primary); font-weight: 700; }

/* Abaixo de 1180px a tela deixa de caber em uma janela e passa a rolar — é o
   único ponto em que abrimos mão da regra, porque espremer oito cartões e
   cinco painéis num telefone entrega uma tela ilegível em vez de compacta. */
@media (max-width: 1180px) {
  .analise:has(.rh-kpis) { height: auto; padding-bottom: 26px; }
  .rh-kpis  { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .rh-meio,
  .rh-baixo { grid-template-columns: minmax(0, 1fr); flex: 0 0 auto; }
  .rh-meio > .painel,
  .rh-baixo > .painel { min-height: 210px; }
  .rh-composicao,
  .rh-turnover { grid-template-columns: minmax(0, 1fr); }
}

/* ---------- People Analytics · Quadro Pessoal ---------- */

/* Três faixas: cartões com altura natural, quebras e lista repartindo o resto.
   A lista leva a maior fatia porque é a leitura principal da tela — as quebras
   respondem "como o quadro se distribui" e ela responde "quem são". */
.qp-kpis {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: 10px;
  flex: 0 0 auto;
}

.qp-quebras { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; flex: 1 1 0; min-height: 0; }
.qp-lista { display: flex; flex: 1.5 1 0; min-height: 0; }
.qp-lista > .painel { flex: 1; min-height: 0; }

.qp-quebras > .painel { min-height: 0; }

/* Reaproveita o cartão da Visão Geral e acrescenta a linha de apoio, que lá não
   existe. São cinco em vez de oito, então o valor pode voltar ao tamanho cheio. */
.qp-kpis .rh-cartao-valor { font-size: 20px; }
.rh-cartao-apoio { font-size: 10.5px; color: var(--text-muted); }
.rh-cartao-apoio strong { color: var(--text-secondary); font-weight: 700; }

/* Escolaridade é texto longo e não cabe em 20px sem estourar o cartão. */
.qp-kpis .rh-cartao:nth-child(4) .rh-cartao-valor { font-size: 13.5px; line-height: 1.3; }

/* Os três segmentadores dividem a caixa do cabeçalho. `wrap` porque numa janela
   estreita eles descem em vez de espremer os rótulos até a ilegibilidade. */
.qp-filtros { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }

/* Cada segmentador ancora o PRÓPRIO painel. Sem isto, o `position: absolute` do
   painel procura o ancestral posicionado mais próximo — que é a caixa dos três
   — e o `right: 0` cola todos eles na borda direita do grupo: abrir "Empresa"
   abria uma janela sob "Situação". */
.qp-filtros > div { position: relative; }

/* E alinhado pela ESQUERDA, não pela direita. O padrão da plataforma nasceu
   para um filtro só, encostado no canto direito do cabeçalho; numa fileira que
   se lê da esquerda para a direita, a janela precisa começar onde o botão
   começa. */
.qp-filtros .filtro-painel { right: auto; left: 0; }

/* Título à esquerda, ações à direita, na mesma linha. O `is-no-topo` zera o
   respiro de cima do cabeçalho interno: aqui não há nada acima dele. */
.qp-lista-topo {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
  flex: 0 0 auto;
}

.qp-lista-topo .painel-topo--interno { margin-bottom: 10px; }

/* Quem rola é a lista, dentro do painel — a página inteira continua fixa. O
   cabeçalho gruda no topo para o leitor não perder de vista qual coluna é qual
   depois de descer trinta nomes. */
.qp-tabela-caixa {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  overflow-x: auto;
}

.qp-tabela thead th {
  position: sticky;
  top: 0;
  z-index: 1;
  background: var(--bg-secondary);
}

.qp-tabela .qp-nome { font-weight: 600; color: var(--text-primary); white-space: nowrap; }
.qp-tabela .qp-cargo,
.qp-tabela .qp-formacao {
  max-width: 190px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

@media (max-width: 1180px) {
  .analise:has(.qp-kpis) { height: auto; padding-bottom: 26px; }
  .qp-kpis { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .qp-quebras { grid-template-columns: minmax(0, 1fr); flex: 0 0 auto; }
  .qp-quebras > .painel { min-height: 190px; }
  .qp-lista { flex: 0 0 auto; min-height: 320px; }
}

/* ---------- People Analytics · Turnover ---------- */

/* Quatro faixas: oito cartões em duas linhas com altura natural, e dois blocos
   de painéis repartindo o resto. O de cima leva mais porque carrega a série e a
   rosca, que precisam de altura para não virar risco. */
.tv-kpis {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 10px;
  flex: 0 0 auto;
}

.tv-meio  { display: grid; grid-template-columns: 1fr 1.15fr; gap: 12px; flex: 1.2 1 0; min-height: 0; }
.tv-baixo { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; flex: 1 1 0; min-height: 0; }

.tv-meio > .painel,
.tv-baixo > .painel { min-height: 0; }

/* SÓ o painel com abas perde o centro do corpo, e só o cabeçalho dele é que
   fica preso: trocar de Causa (8 barras) para Motivo (3) mudava a altura do
   conteúdo, e com tudo centrado o título e as abas desciam para o meio do
   cartão — o controle fugia do clique que acabou de acontecer.
   O DESENHO continua centrado, agora dentro do espaço que sobra: ele é que
   pode se mexer, o controle não. Os outros dois painéis da faixa mantêm o
   comportamento padrão. */
.tv-baixo .painel-corpo:has(.tv-saida-topo) { justify-content: flex-start; }

#tv-saida {
  display: flex;
  flex-direction: column;
  justify-content: center;
  flex: 1;
  min-height: 0;
}

/* A TELA INTEIRA no vermelho do relatório: não há indicador bom aqui. O acento
   dourado do domínio continua valendo para a navegação e o cabeçalho — o que
   troca é só o desenho dos dados. */
.analise[data-dominio="rh"] .tv-meio .g-linha-traco  { stroke: var(--risco); }
.analise[data-dominio="rh"] .tv-meio .g-linha-ponto  { fill: var(--risco); stroke: var(--bg-secondary); }
.analise[data-dominio="rh"] .tv-meio .g-linha-pilula { fill: var(--risco); stroke: none; }
.analise[data-dominio="rh"] .tv-meio .g-linha-valor  { fill: #fff; }

/* A rampa das barras e da rosca vira uma escala de vermelho. Mesma técnica da
   rosca de gênero na Visão Geral: redefinir a variável no ancestral, porque o
   componente escreve a cor em `style` inline e regra de folha perderia. */
.analise[data-dominio="rh"] .tv-meio,
.analise[data-dominio="rh"] .tv-baixo {
  --rampa-1: #b82631;
  --rampa-2: #a33740;
  --rampa-3: #8c3b42;
  --rampa-4: #723840;
  --rampa-5: #5a333a;
  --rampa-6: #442c31;
}

/* Menos o segundo tom da rosca, que é branco — como no relatório. */
.analise[data-dominio="rh"] .tv-meio .rh-genero { --rampa-2: #f2f0e8; }

/* Aqui a rosca manda e as barras cedem: são só duas fatias, e é nelas que está
   a leitura de "qual lado gira mais". As cinco faixas ao lado já se leem pelo
   comprimento — encolher a barra não custa informação, encolher a rosca sim. */
.tv-meio .rh-composicao { grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr); gap: 10px; }
.tv-meio .rh-genero .g-roscaf { flex-direction: column; gap: 4px; }
.tv-meio .rh-genero .g-roscaf-svg { width: 100%; height: auto; max-height: 150px; }

/* Com o valor escrito na fatia, a legenda não repete número: fica só a cor e o
   nome, que é o que ela existe para dizer. */
.tv-meio .rh-genero .g-roscaf-valor,
.tv-meio .rh-genero .g-roscaf-pct { display: none; }

.g-roscaf-marca {
  font-size: 9.5px;
  font-weight: 700;
  fill: var(--text-primary);
}

.g-roscaf-marca-pct { font-weight: 600; fill: var(--text-muted); }

/* Título à esquerda, abas à direita. */
.tv-saida-topo {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 10px;
  flex: 0 0 auto;
}

.tv-saida-topo .painel-topo--interno { margin-bottom: 10px; }

.tv-abas { display: flex; gap: 4px; flex-shrink: 0; }

.tv-aba {
  padding: 3px 10px;
  font-family: inherit;
  font-size: 10.5px;
  font-weight: 700;
  color: var(--text-muted);
  background: var(--bg-tertiary);
  border: 1px solid var(--border-color);
  border-radius: 20px;
  cursor: pointer;
  transition: color var(--transition-fast), background var(--transition-fast),
              border-color var(--transition-fast);
}

.tv-aba:hover { color: var(--text-primary); }

/* A aba ligada usa o vermelho da tela, não o acento: ela seleciona um recorte
   dos desligamentos, e pertence ao mesmo assunto que o desenho abaixo dela. */
.tv-aba[aria-pressed="true"] {
  color: #fff;
  background: var(--risco);
  border-color: var(--risco);
}

@media (max-width: 1180px) {
  .analise:has(.tv-kpis) { height: auto; padding-bottom: 26px; }
  .tv-kpis  { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .tv-meio,
  .tv-baixo { grid-template-columns: minmax(0, 1fr); flex: 0 0 auto; }
  .tv-meio > .painel,
  .tv-baixo > .painel { min-height: 210px; }
}

/* ---------- People Analytics · Presença & Jornada ---------- */

.pj-kpis {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: 10px;
  flex: 0 0 auto;
}

/* Rótulo de seção: a tela junta duas leituras que não se falam, e sem esta
   divisória o leitor compara o gráfico de dois meses do absenteísmo com o de
   seis das horas extras e conclui que falta carga. Discreto de propósito — é
   uma placa de rua, não um título. */
.pj-secao {
  flex: 0 0 auto;
  margin-top: 2px;
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-muted);
}

.pj-faixa {
  display: grid;
  grid-template-columns: 1fr 1.1fr 1fr;
  gap: 12px;
  flex: 1 1 0;
  min-height: 0;
}

.pj-faixa > .painel { min-height: 0; }

/* A rosca aqui divide com as barras, como no Turnover: são duas fatias e é
   nelas que está a leitura. */
.pj-composicao {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr);
  gap: 10px;
  align-items: center;
  flex: 1;
  min-height: 0;
}

.pj-composicao .rh-genero { min-width: 0; }
.pj-composicao .rh-genero .g-roscaf { flex-direction: column; gap: 4px; }
.pj-composicao .rh-genero .g-roscaf-svg { width: 100%; height: auto; max-height: 132px; }
.pj-composicao .rh-genero .g-roscaf-valor,
.pj-composicao .rh-genero .g-roscaf-pct { display: none; }

/* Barras com mais espaço: a rosca cede largura porque ela é só duas fatias com
   o número escrito ao lado, e não perde nada ao encolher. As quatro faixas, sim
   — é o comprimento delas que carrega a comparação. */
.pj-composicao { grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.35fr); }

/* Rótulo da rosca maior: aqui ele carrega DUAS informações — a contagem e a
   participação — e no tamanho do padrão a segunda linha ficava ilegível. */
.pj-composicao .g-roscaf-marca { font-size: 12px; }
.pj-composicao .g-roscaf-marca-pct { font-size: 10px; }

/* Duas colunas só — a base de faltas tem jan e fev. Sem teto de largura elas
   ocupariam meio painel cada e virariam dois blocos, não um gráfico. O `auto`
   nas laterais centra o conjunto no espaço que sobra. */
.painel--pj-colunas .g-colunas { max-width: 320px; margin: 0 auto; }

/* Pílula no topo da coluna, como no relatório: fundo do acento e texto escuro.
   O `--junto` do componente já posiciona o rótulo colado na barra; o que falta
   é o fundo, e ele importa — "288h 20min" em texto solto sobre o painel escuro
   se lê como legenda, e dentro da pílula se lê como o valor daquela coluna. */
.painel--pj-colunas .g-coluna-valor {
  padding: 2px 8px;
  border-radius: 20px;
  background: var(--accent);
  color: var(--on-accent);
  font-size: 10.5px;
  font-weight: 700;
}

@media (max-width: 1180px) {
  .analise:has(.pj-kpis) { height: auto; padding-bottom: 26px; }
  .pj-kpis  { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .pj-faixa { grid-template-columns: minmax(0, 1fr); flex: 0 0 auto; }
  .pj-faixa > .painel { min-height: 200px; }
  .pj-composicao { grid-template-columns: minmax(0, 1fr); }
}

/* ---------- People Analytics · Custo de Folha ---------- */

.cf-kpis {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: 10px;
  flex: 0 0 auto;
}

.cf-meio  { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; flex: 1 1 0; min-height: 0; }
.cf-baixo { display: grid; grid-template-columns: 1.25fr 1fr 1fr; gap: 12px; flex: 1 1 0; min-height: 0; }

.cf-meio > .painel,
.cf-baixo > .painel { min-height: 0; }

/* Treemap e cascata se desenham na medida da caixa; sem `flex: 1` num pai flex
   elas nascem com zero — foi o erro que deixou as colunas do absenteísmo
   chatas. Aqui as caixas são flex-child de verdade. */
.g-treemap-caixa,
.g-cascata-caixa { display: flex; flex: 1; min-width: 0; min-height: 0; }
.g-treemap-caixa > *,
.g-cascata-caixa > * { flex: 1; min-width: 0; }

/* O treemap do relatório NÃO usa a rampa do domínio: ele alterna matizes —
   amarelo, salmão, amarelo, rosa, rosa. E faz sentido no formato: numa rampa
   monocromática, dois retângulos vizinhos de tamanho parecido ficam com tons
   quase iguais e a fronteira entre eles some. A matiz separa o que a área não
   separa. Redefinido na variável, como nas outras roscas, porque o componente
   escreve a cor em `style` inline. */
.g-treemap-caixa {
  --rampa-1: #e3c93f;
  --rampa-2: #e8896a;
  --rampa-3: #d9c24d;
  --rampa-4: #e0596d;
  --rampa-5: #cf5468;
  --rampa-6: #b8556e;
}

/* ---- Cascata ---- */

.g-cascata { display: block; width: 100%; height: 100%; }

.g-cascata-barra { fill: var(--rampa-1); }

/* A coluna do TOTAL em vermelho: ela não é mais uma parcela, é o fechamento —
   e no relatório de origem é a única fora da paleta da série. */
.g-cascata-barra.is-total { fill: var(--risco, var(--danger)); }

.g-cascata-elo {
  stroke: var(--border-color-light);
  stroke-width: 1;
  stroke-dasharray: 3 3;
}

.g-cascata-pilula { fill: var(--accent); }
.g-cascata-pilula.is-total { fill: var(--risco, var(--danger)); }

.g-cascata-valor {
  font-size: 10px;
  font-weight: 700;
  fill: var(--on-accent);
}

.g-cascata-valor.is-total { fill: #fff; }

.g-cascata-rotulo {
  font-size: 9.5px;
  fill: var(--text-muted);
}

/* O percentual de encargo ao lado do valor, em vermelho: é a leitura de peso
   — quanto daquele tipo de folha é obrigação, não salário. */
.painel--cf-tipos .g-barra-apoio { color: var(--risco, var(--danger)); font-weight: 700; }

@media (max-width: 1180px) {
  .analise:has(.cf-kpis) { height: auto; padding-bottom: 26px; }
  .cf-kpis  { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .cf-meio,
  .cf-baixo { grid-template-columns: minmax(0, 1fr); flex: 0 0 auto; }
  .cf-meio > .painel,
  .cf-baixo > .painel { min-height: 230px; }
}

/* ============================================================
   Logística
   ============================================================
   A PALETA É A DO RELATÓRIO DE ORIGEM, e fica presa à análise — não ao domínio.
   Em People Analytics o acento do domínio inteiro virou o dourado do relatório,
   porque o roxo que estava lá não vinha de lugar nenhum; aqui o azul de
   Logística é o que separa a área do Financeiro na barra lateral, e o verde do
   relatório (#00C8AD) está a um passo do teal do Financeiro (#14B8A6). Trocar o
   acento do domínio deixaria duas áreas com a mesma cor no menu.

   Redefinir as variáveis no `.analise` resolve os dois lados: os gráficos saem
   exatamente como no Power BI e a casca continua dizendo onde você está. Como é
   herança de custom property, cada componente continua lendo var(--accent) sem
   saber de nada.

   `--serie-b` é a linha e a pílula da margem; trocá-la aqui pinta as duas de uma
   vez, porque as duas já apontavam para ela. */
.analise[data-dominio="logistica"] {
  --accent: #00c8ad;
  --accent-soft: rgba(0, 200, 173, 0.14);
  /* A TINTA acompanha o acento local, senão a participação ao lado do ranking
     sairia no azul do domínio enquanto as barras saem no teal do relatório —
     duas cores para a mesma coisa na mesma linha. No tema escuro ela é o
     próprio teal; no claro, o teal rebaixado (#00c8ad sobre branco dá 1,9:1).
     Ver `--accent-tinta` no variables.css. */
  --accent-tinta: #00c8ad;
  --serie-b: #3f7db7;

  --log-receita: #2dd4a7;
  --log-custo: #1b3b32;
  --log-ontime: #2e9bf0;
  --log-infull: #f0a88c;

  /* Os três tons dos ÍCONES, amostrados pixel a pixel da imagem de fundo do
     relatório (StaticResources/RegisteredResources/Visao_Executiva…png), e não
     estimados de um print — num print o anti-aliasing sobre fundo escuro puxa
     todo traço fino para o cinza, e as três cores chegariam parecidas.

     O critério do relatório é de conteúdo: coral onde o assunto é custo, azul
     onde é resultado ou passagem do tempo, verde no resto. */
  --log-icone-verde: #3ddc97;
  --log-icone-coral: #e0704f;
  --log-icone-azul:  #4d8fe0;

  /* "Está normal": o azul-turquesa que o relatório usa nas faixas de ocupação
     do meio. Sai da paleta do próprio visual (#25BABD) — não é o azul dos
     ícones nem o verde do nível de serviço, e é isso que faz dele um terceiro
     estado em vez de mais um tom de algo que já existe. */
  --log-normal: #25babd;

  /* Fim escuro do degradê das barras. Mesma matiz do acento, com metade da
     luminosidade: é sombra da própria cor, não uma segunda cor. */
  --log-barra-fim: #04695c;
}

/* O mesmo teal, rebaixado para escrever sobre branco. Fica aqui e não no
   variables.css porque o acento que ele acompanha também nasce aqui — os dois
   têm de andar no mesmo lugar para não se separarem numa edição futura. */
:root[data-tema="claro"] .analise[data-dominio="logistica"] {
  --accent-tinta: #056e60;
}

.analise[data-dominio="logistica"] .kpi-icone.is-verde,
.analise[data-dominio="logistica"] .painel-icone.is-verde {
  color: var(--log-icone-verde);
  background: rgba(61, 220, 151, 0.13);
}

.analise[data-dominio="logistica"] .kpi-icone.is-coral,
.analise[data-dominio="logistica"] .painel-icone.is-coral {
  color: var(--log-icone-coral);
  background: rgba(224, 112, 79, 0.13);
}

.analise[data-dominio="logistica"] .kpi-icone.is-azul,
.analise[data-dominio="logistica"] .painel-icone.is-azul {
  color: var(--log-icone-azul);
  background: rgba(77, 143, 224, 0.13);
}

.analise[data-dominio="logistica"] .g-combo-barra.is-a { fill: var(--log-receita); }
.analise[data-dominio="logistica"] .g-combo-chave.is-a { fill: var(--log-receita); }

/* O custo é quase da cor do cartão, e é assim no relatório: ele é o que sobra
   embaixo da receita, não uma segunda leitura. O contorno é o que impede o
   bloco de sumir contra o fundo quando o mês tem custo alto. */
.analise[data-dominio="logistica"] .g-combo-barra.is-b {
  fill: var(--log-custo);
  stroke: rgba(45, 212, 167, 0.28);
  stroke-width: 0.6;
}

.analise[data-dominio="logistica"] .g-combo-chave.is-b { fill: var(--log-custo); }

/* Texto claro na pílula da margem: o azul de origem é escuro o bastante para o
   padrão (tinta escura sobre pílula clara) ficar ilegível. */
.analise[data-dominio="logistica"] .g-combo-rot-linha { fill: #ffffff; }

/* Os três anéis: verde, azul e coral, como no relatório. Não é rampa nem
   semântica — são três recortes do mesmo total, e a cor só os separa. */
.analise[data-dominio="logistica"] .g-rosca-arco.is-otif   { stroke: var(--log-receita); }
.analise[data-dominio="logistica"] .g-rosca-arco.is-ontime { stroke: var(--log-ontime); }
.analise[data-dominio="logistica"] .g-rosca-arco.is-infull { stroke: var(--log-infull); }

/* Natureza de custo em coral, a única família que o relatório usa aqui — e o
   único lugar da tela com rampa, para os três degraus não se confundirem com o
   verde do ranking, que é série única. */
.painel--log-natureza {
  --rampa-1: #ffc9b1;
  --rampa-2: #d98a66;
  --rampa-3: #c67958;
}

.painel--log-natureza .g-barra-apoio {
  color: var(--text-primary);
  font-weight: 700;
}

/* O combo precisa de altura: com legenda no topo e dois níveis de eixo embaixo,
   as margens comem 80px antes de sobrar traço. */
.painel--log-serie .painel-corpo { min-height: 190px; }

/* ---------- Ranking de filiais + extremos ---------- */

/* Duas leituras num cartão só, como no relatório: o ranking ocupa a sobra e o
   par melhor/pior fica ancorado no pé, separado por um fio. `auto` na segunda
   faixa é o que impede o bloco de extremos de encolher quando a janela baixa —
   quem cede é a lista de barras, que tem para onde. */
.painel--log-ranking .painel-corpo {
  display: grid;
  grid-template-rows: minmax(0, 1fr) auto;
  gap: 12px;
  justify-content: stretch;
}

.log-ranking { min-height: 0; }

/* Degradê ao longo do COMPRIMENTO da barra, do acento até a sombra dele. O
   sentido importa: claro na base, escuro na ponta. Assim o degradê acompanha a
   leitura — quanto mais longe a barra vai, mais fundo o tom — em vez de brigar
   com ela.

   E o gradiente é da barra, não do trilho: como cada barra tem comprimento
   diferente, todas terminam no mesmo tom escuro, e a variação entre elas fica
   sendo o comprimento, que é o dado. Um gradiente fixo no trilho faria a barra
   curta ficar toda clara e a longa toda escura — duas cores diferentes para o
   mesmo tipo de coisa. */
.log-ranking .g-barra-preenche {
  background: linear-gradient(90deg, var(--accent), var(--log-barra-fim));
}

.log-extremos {
  padding-top: 12px;
  border-top: 1px solid var(--border-color);
}

.log-extremos-titulo {
  margin-bottom: 10px;
  text-align: center;
  font-size: 11px;
  color: var(--text-secondary);
}

.log-extremos-par {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px;
}

/* Cada metade centra o próprio conteúdo. Alinhado à esquerda, os dois blocos
   encostavam na divisa esquerda de suas colunas e abriam um vão morto na
   direita do cartão — o par lia como uma coisa só empurrada para um lado, em
   vez de duas leituras equilibradas. */
.log-extremo { text-align: center; }

.log-extremo-topo {
  display: flex;
  align-items: baseline;
  justify-content: center;
  gap: 4px;
  font-size: 12px;
  margin-bottom: 4px;
}

.log-extremo-topo strong { font-weight: 700; }

.log-extremo.is-melhor .log-extremo-topo { color: var(--log-receita); }
.log-extremo.is-pior   .log-extremo-topo { color: var(--log-infull); }

.log-extremo-seta { font-size: 13px; line-height: 1; }

.log-extremo-pct { font-weight: 700; }

.log-extremo-valor {
  font-size: 17px;
  font-weight: 700;
  color: var(--text-primary);
  letter-spacing: -0.02em;
}

.log-extremo-rot {
  margin-top: 1px;
  font-size: 10.5px;
  color: var(--text-muted);
}

/* ---------- Anéis de nível de serviço ---------- */

.log-aneis { align-items: center; }

.log-anel { text-align: center; min-width: 0; }

/* O anel maior que o padrão de 96px: aqui ele carrega número E nome dentro,
   e no tamanho comum os dois textos encostariam nas bordas do arco. */
.log-anel .g-rosca svg { max-width: 118px; }

.log-anel-rot {
  margin-top: 10px;
  font-size: 11px;
  color: var(--text-secondary);
}

.log-anel-num {
  font-size: 15px;
  font-weight: 700;
  color: var(--text-primary);
}

@media (max-width: 1180px) {
  .painel--log-ranking .painel-corpo { grid-template-rows: auto auto; }
}

/* ---------- Tabela com calor ---------- */

/* A tabela rola DENTRO do cartão, com o cabeçalho grudado no topo: seis estados
   e sete colunas não cabem num painel de meia altura, e sem o `sticky` quem
   rola perde o nome da coluna justamente quando precisa dele. */
.painel--rolavel-tabela .painel-corpo {
  justify-content: flex-start;
  overflow: hidden;
}

.g-tabela-caixa {
  flex: 1;
  min-height: 0;
  overflow: auto;
}

/* `height: 100%` faz as linhas DIVIDIREM a altura do cartão quando sobra
   espaço — quatro faixas de ocupação deixavam dois terços do painel vazios
   embaixo. Não estica o que não cabe: numa tabela mais alta que a caixa o
   valor é ignorado e as linhas ficam na altura natural, com rolagem. Um só
   comportamento serve aos dois casos. */
.g-tabela {
  width: 100%;
  height: 100%;
  border-collapse: collapse;
  font-size: 11.5px;
}

.g-tabela thead th {
  position: sticky;
  top: 0;
  z-index: 1;
  padding: 6px 8px;
  text-align: left;
  font-weight: 700;
  color: var(--text-secondary);
  background: var(--bg-secondary);
  border-bottom: 1px solid var(--border-color-light);
  white-space: nowrap;
}

.g-tabela thead th.is-num { text-align: right; }

.g-tabela tbody tr + tr th,
.g-tabela tbody tr + tr td { border-top: 1px solid var(--border-color); }

.g-tabela td,
.g-tabela .g-tabela-nome {
  padding: 5px 8px;
  text-align: left;
  font-weight: 500;
}

.g-tabela .g-tabela-nome {
  color: var(--text-primary);
  white-space: nowrap;
}

/* A célula com calor é uma pilha de duas camadas: a tinta ocupa a célula
   inteira e o número fica por cima. Pintar o `background` direto impediria a
   opacidade variável de conviver com a borda entre linhas. */
.g-tabela td {
  position: relative;
  text-align: right;
  color: var(--text-primary);
}

.g-tabela-tinta {
  position: absolute;
  inset: 0;
  background: var(--log-icone-coral, var(--accent));
  pointer-events: none;
}

.g-tabela-num {
  position: relative;
  white-space: nowrap;
}

/* ---------- Bolhas por categoria ---------- */

/* Seis matizes distintas, e não uma rampa: aqui a cor é o NOME do item, não a
   posição dele numa escala. Uma rampa diria que Biguaçu vem antes de Campinas
   em alguma coisa, e a única ordem que existe entre filiais é alfabética. */
/* O quadro é a âncora do balão: ele posiciona `absolute` em relação a este
   elemento, e sem `relative` aqui a referência subiria até a página. */
.g-bolhas-quadro {
  position: relative;
  flex: 1;
  min-height: 0;
  min-width: 0;
}

.g-bolhas-quadro .g-bolhas { width: 100%; height: 100%; }

/* Cursor de leitura: a bolha responde ao ponteiro, e o cursor precisa dizer
   isso antes de a pessoa descobrir por acidente. */
.g-bolhas-ponto { cursor: default; }

/* O balão da dispersão fica DENTRO do quadro (o do mapa fica dentro do dele).
   `pointer-events: none` é obrigatório nos dois: ele anda colado ao cursor, e
   se capturasse o ponteiro a bolha embaixo deixaria de ser detectada e a
   leitura piscaria sem parar. */
.g-dica { pointer-events: none; }

.g-dica-item[hidden] { display: none; }

.g-bolhas-ponto.is-cat0, .g-bolhas-chip-cor.is-cat0 { fill: #e8845c; background: #e8845c; }
.g-bolhas-ponto.is-cat1, .g-bolhas-chip-cor.is-cat1 { fill: #cfd6de; background: #cfd6de; }
.g-bolhas-ponto.is-cat2, .g-bolhas-chip-cor.is-cat2 { fill: #b25b3a; background: #b25b3a; }
.g-bolhas-ponto.is-cat3, .g-bolhas-chip-cor.is-cat3 { fill: #7f8b99; background: #7f8b99; }
.g-bolhas-ponto.is-cat4, .g-bolhas-chip-cor.is-cat4 { fill: #4d8fe0; background: #4d8fe0; }
.g-bolhas-ponto.is-cat5, .g-bolhas-chip-cor.is-cat5 { fill: #8b6f9e; background: #8b6f9e; }

/* ---------- Peças das telas de Logística ---------- */

/* Leitura de fechamento no pé de um cartão: um número grande e uma linha de
   contexto. Repete-se em quatro painéis (média da rede, média do top 10, gap
   entre regiões), então mora aqui e não em cada tela. */
/* Coral, e não o acento verde da análise. O verde é a cor do NÍVEL DE SERVIÇO
   em toda a Logística — OTIF, entregas no prazo. Estes dois números são outra
   coisa: a média da rede que os extremos acima cercam, e a média do top 10 de
   custo. Pintá-los de verde os ligaria à leitura errada. É a cor do relatório
   de origem nos dois. */
.ns-media {
  font-size: 25px;
  font-weight: 800;
  letter-spacing: -0.03em;
  color: var(--log-infull, var(--accent));
  text-align: center;
}

.ns-gap,
.ut-gap {
  margin-top: 2px;
  font-size: 11.5px;
  color: var(--text-secondary);
  text-align: center;
}

.ns-gap strong,
.ut-gap strong { color: var(--text-primary); }

.ut-gap {
  padding-top: 10px;
  border-top: 1px solid var(--border-color);
}

/* Top 10 de veículos: dez linhas num cartão de duas faixas de grade. Aqui a
   barra NÃO cresce — dez barras de 44px estourariam o cartão —, então volta ao
   comportamento de `barras-encolhem` puro. */
.log-top10 .g-barra-trilho { max-height: 22px; }

/* Placa é nome curto e igual em todas as linhas: a coluna do rótulo pode ceder
   largura para a barra. */
.log-top10 .g-barra,
.log-top-ociosos .g-barra { grid-template-columns: 76px minmax(0, 1fr) var(--g-barra-reserva, 80px); }

/* Ranking em CORAL em vez do acento verde. Em Logística o verde é a cor do
   nível de serviço — OTIF, entregas no prazo — e o coral é a do custo e do
   volume. A escolha é por assunto, não por variedade: um ranking de veículos
   caros em verde diria "isto está bom".

   Vale para os cinco rankings que o relatório pinta assim: veículos mais caros,
   veículos mais ociosos, sobrecarga por tipo, cidades de maior tícket e
   distância média percorrida. */
.barras-coral .g-barra-preenche {
  background: linear-gradient(90deg, var(--log-infull), var(--log-icone-coral));
}

/* ---------- Carga & Frete ---------- */

/* `margin-top: auto` ancora o texto no PÉ do cartão. Colado nas barras, o fio
   divisório dividia o painel no meio e sobrava um vão morto embaixo — a
   leitura de fechamento fica melhor onde a leitura termina. */
.cg-narrativa {
  margin-top: auto;
  padding-top: 10px;
  border-top: 1px solid var(--border-color);
  font-size: 11.5px;
  line-height: 1.6;
  color: var(--text-secondary);
}

.cg-narrativa strong { color: var(--text-primary); }

/* As DUAS BARRAS ficam centradas na sobra, e o texto continua no pé.
   São só duas — dois cenários, não um ranking —, então elas não têm altura
   para ocupar o cartão. Com `margin-top: auto` apenas na narrativa, ela sozinha
   absorvia toda a folga: as barras ficavam grudadas no cabeçalho e sobrava um
   vão morto no meio do painel.

   O `auto` aqui também não centra as barras no cartão inteiro, e é isso que se
   quer: as duas margens automáticas repartem a folga em partes iguais — metade
   acima das barras, metade entre elas e o texto —, o que deixa as barras
   centradas no espaço ACIMA da narrativa. Centrá-las no cartão inteiro as faria
   descer por trás do fio divisório.

   Não usa `justify-content` no `.painel-corpo` porque margem automática vence
   `justify-content`: enquanto a narrativa tiver a dela, o alinhamento do
   container é ignorado. Ou os dois usam margem, ou nenhum. */
.cg-cenario {
  flex: 0 0 auto;
  margin-top: auto;
}

.cg-risco {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px;
}

.cg-risco-cartao {
  padding: 10px 12px;
  border: 1px solid var(--border-color);
  border-radius: var(--radius-md);
  background: var(--bg-tertiary);
  text-align: center;
}

.cg-risco-rot {
  font-size: 11px;
  color: var(--text-secondary);
  margin-bottom: 4px;
}

.cg-risco-valor {
  font-size: 21px;
  font-weight: 800;
  letter-spacing: -0.03em;
  color: var(--log-icone-coral);
}

.cg-tipos { flex: 0 0 auto; margin-top: 12px; }

/* AS PONTAS SÃO O PROBLEMA; O MEIO É O NORMAL.

   As quatro faixas estão em ordem de ocupação, e a cor separa as duas leituras:
   coral nas extremidades — carga abaixo de 50% de um lado, acima de 100% do
   outro — e azul nas duas do meio, que é onde o caminhão sai como deveria.

   Não é gradiente nem ranking: é uma classificação de dois estados sobre uma
   escala ordenada. Tingir as quatro na mesma família diria que a sobrecarga é
   uma subutilização pior, quando é o defeito oposto. */
.painel--cg-ocupacao .g-coluna-barra { background: var(--log-normal); }
.painel--cg-ocupacao .g-coluna:first-child .g-coluna-barra,
.painel--cg-ocupacao .g-coluna:last-child .g-coluna-barra {
  background: var(--log-icone-coral);
}

/* ---------- Geografia ---------- */

/* O mapa tinge em coral, e não no acento verde da análise: verde é a cor do
   nível de serviço em toda a Logística, e um mapa verde sugeriria que o estado
   mais escuro é o que entrega melhor — quando o que ele mostra é volume. */
.painel--geo-mapa .g-mapa-uf { fill: var(--log-icone-coral); }

.painel--geo-mapa .painel-corpo { overflow: hidden; }

/* KPI de perda: o número em vermelho, o cartão igual aos outros. Distinto de
   `kpi--alerta`, que pisca a borda — aqui não há incidente, há um custo alto
   que precisa ser lido como custo. */
.kpi--risco .kpi-valor { color: var(--log-icone-coral); }

/* ---------- Combo de série única em Logística (o Pareto) ---------- */

/* Coluna coral e CHEIA. A opacidade de 0,42 do combo padrão existe para
   distinguir barra comum de barra em destaque — no Pareto não há destaque, há
   uma série só, e a barra lavada perdia contra a linha do acumulado, que é a
   segunda leitura e não a primeira. */
.analise[data-dominio="logistica"] .g-combo-barra:not(.is-a):not(.is-b) {
  fill: var(--log-infull);
  opacity: 1;
}

.analise[data-dominio="logistica"] .g-combo-barra:not(.is-a):not(.is-b):hover {
  opacity: 0.82;
}

/* Pastilha neutra do rótulo da coluna: cinza contra o azul do acumulado, para
   as duas séries se distinguirem pela cor da pastilha e não só pela altura. */
.g-combo-pilula-barra {
  fill: var(--bg-elevated);
  stroke: var(--border-color-light);
  stroke-width: 1;
}

/* ---------- Linha de Custos & Frota ---------- */

/* Coral, como no relatório. `--accent` daria verde, e verde nesta tela é a cor
   do nível de serviço — não do custo. */
.painel--cf-linha .g-linha-traco { stroke: var(--log-infull); }
.painel--cf-linha .g-linha-ponto { fill: var(--log-infull); }
.painel--cf-linha .g-linha-pilula {
  fill: var(--log-infull);
  stroke: none;
}
.painel--cf-linha .g-linha-valor { fill: #2a1409; }

/* ---------- Matriz de dois níveis ---------- */

.g-tabela-abre {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 14px;
  height: 14px;
  margin-right: 6px;
  padding: 0;
  border: 1px solid var(--border-color-light);
  border-radius: 3px;
  background: transparent;
  color: var(--text-secondary);
  font-size: 12px;
  line-height: 1;
  cursor: pointer;
}

.g-tabela-abre:hover {
  border-color: var(--accent);
  color: var(--accent-tinta);
}

.g-tabela-pai .g-tabela-nome { font-weight: 700; }

/* O mestre é menor que o `painel-acao` padrão: ele mora dentro de uma célula de
   cabeçalho de 11,5px, e no tamanho de botão de painel empurraria a linha
   inteira para baixo. */
.g-tabela-tudo {
  width: 18px;
  height: 18px;
  margin-right: 6px;
  vertical-align: -4px;
}

.g-tabela-tudo .icone { width: 11px; height: 11px; }

/* O caret aponta para baixo quando tudo está aberto e para a direita quando
   tudo está fechado — mesmo gesto do DRE. */
.g-tabela-tudo .painel-acao-caret {
  transition: transform var(--transition-fast);
}

.g-tabela-tudo[aria-expanded="true"] .painel-acao-caret { transform: rotate(90deg); }

/* A filha se distingue pela indentação, e não por outra cor de fundo: o fundo
   da célula já carrega o calor do valor, e uma segunda camada de cinza por
   baixo dele mudaria o tom de todas as filhas. */
.g-tabela-filho .g-tabela-nome {
  padding-left: 28px;
  color: var(--text-secondary);
  font-weight: 500;
}

.g-tabela-filho[hidden] { display: none; }

/* ============================================================
   Visão Geral — a home
   ============================================================
   A única tela que NÃO segue a regra da dobra. As análises cabem numa janela
   porque são um retrato de um recorte; a home é uma entrada, e entrada se
   percorre. Rolar aqui é o gesto certo. */
.home {
  display: flex;
  flex-direction: column;
  gap: 26px;
  padding-bottom: 30px;
}

.home-eyebrow {
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--brand);
  margin-bottom: 4px;
}

.home-titulo {
  font-size: 34px;
  font-weight: 800;
  letter-spacing: -0.03em;
  line-height: 1.1;
}

.home-texto {
  margin-top: 8px;
  max-width: 62ch;
  font-size: 13.5px;
  line-height: 1.65;
  color: var(--text-secondary);
}

.home-texto strong { color: var(--text-primary); }

.home-secao {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.home-secao-topo {
  display: flex;
  align-items: center;
  gap: 12px;
}

.home-secao-titulo {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-muted);
}

.home-setas {
  display: flex;
  gap: 6px;
  margin-left: auto;
}

.home-seta[hidden] { display: none; }
.home-seta:disabled { opacity: 0.3; cursor: default; }

/* As duas setas são o MESMO chevron, e a da esquerda é o espelho da direita —
   não um segundo desenho parecido. Espelhar em vez de manter dois ícones no
   catálogo garante que peso do traço, tamanho e ângulo batam sempre, inclusive
   se o chevron for redesenhado um dia. */
.home-seta[data-passo="-1"] .icone { transform: scaleX(-1); }

/* ---------- Área única: capa inteira + as análises dela ----------

   Quem tem UM domínio não tem carrossel — não há o que girar, e o palco largo
   deixava a capa sozinha no meio com vazio dos dois lados. Aqui a capa fica
   inteira à esquerda e as telas daquela área ocupam a direita.

   A capa é um pouco maior que a coluna das telas (1.05fr contra 1fr) porque ela
   é a imagem e elas são texto: dividir ao meio dava a impressão de duas listas
   lado a lado, e o que se quer é uma entrada com o índice ao lado. */
.home-solo {
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr);
  gap: 18px;
  align-items: start;
}

/* Desfaz o que o carrossel impõe. Fora do trilho não existe "longe do centro":
   a capa é a única, está sempre em foco, e a escala e o desfoque calculados a
   partir de `--longe` a deixariam permanentemente encolhida e borrada.

   DUAS CLASSES no seletor, e não uma. `.home-capa` declara `--longe: 1` e mora
   MAIS ABAIXO neste arquivo; com a mesma especificidade, quem vem depois vence,
   e a capa saía borrada mesmo com a regra escrita. Subir a especificidade
   resolve onde quer que cada bloco esteja — mover um deles resolveria hoje e
   voltaria a quebrar na próxima vez que alguém reorganizasse o arquivo.

   E `transform: none`: a escala também sai daqui, senão o `scale(1 - 0.12 *
   --longe)` continua ativo com valor 1 e cria um contexto de empilhamento sem
   necessidade. */
.home-capa.home-capa-fixa {
  --longe: 0;
  flex: none;
  width: 100%;
  scroll-snap-align: none;
  transform: none;
  filter: none;
  opacity: 1;
}

.home-capa.home-capa-fixa:hover { transform: translateY(-3px); }

/* Duas ou três áreas: as capas lado a lado, sem trilho e sem cópias. O número
   de colunas vem do JS em `--colunas`, porque ele é o único que sabe quantas
   áreas a pessoa tem — uma regra por quantidade (`:has(> :nth-child(3))` e
   afins) diria a mesma coisa três vezes e num seletor que ninguém lê. */
.home-capas-grade {
  display: grid;
  grid-template-columns: repeat(var(--colunas, 3), minmax(0, 1fr));
  gap: 16px;
}

/* O título ganha o ícone da área, porque aqui ele NOMEIA a área em vez de
   rotular uma seção genérica ("Painéis"). */
.home-secao-titulo-area {
  display: flex;
  align-items: center;
  gap: 8px;
  color: var(--dominio-cor, var(--accent));
}

.home-secao-icone .icone { width: 15px; height: 15px; }

.home-solo-telas {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px;
  list-style: none;
  margin: 0;
  padding: 0;
}

/* Cada análise é um BOTÃO de largura inteira, e não um link dentro de um
   cartão: a área toda responde ao clique e o Tab alcança sem atributo extra —
   a mesma decisão da capa. */
.home-tela {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 12px 12px;
  border: 1px solid var(--border-color);
  border-radius: var(--radius-md);
  background: var(--bg-secondary);
  color: var(--text-primary);
  cursor: pointer;
  text-align: left;
  transition: border-color var(--transition-base), background var(--transition-base),
              transform var(--transition-base);
}

.home-tela:hover {
  border-color: var(--dominio-cor, var(--accent));
  background: var(--bg-tertiary, var(--bg-secondary));
  transform: translateY(-2px);
}

.home-tela-icone {
  display: flex;
  align-items: center;
  justify-content: center;
  flex: none;
  width: 28px;
  height: 28px;
  border-radius: var(--radius-sm);
  background: color-mix(in srgb, var(--dominio-cor, var(--accent)) 16%, transparent);
  color: var(--dominio-cor, var(--accent));
}

.home-tela-icone .icone { width: 15px; height: 15px; }

/* `min-width: 0` para o nome poder encolher dentro do grid — sem isso "Insights
   & Recomendações" força a coluna a crescer e as duas ficam de larguras
   diferentes. */
.home-tela-nome {
  flex: 1;
  min-width: 0;
  font-size: 13px;
  font-weight: 600;
  line-height: 1.25;
}

.home-tela-ir {
  flex: none;
  display: flex;
  color: var(--text-muted);
  transition: transform var(--transition-base), color var(--transition-base);
}

.home-tela-ir .icone { width: 14px; height: 14px; }

.home-tela:hover .home-tela-ir {
  color: var(--dominio-cor, var(--accent));
  transform: translateX(3px);
}

/* ---------- Corpo em duas colunas ---------- */

/* A coluna da direita é de GENTE, não de dado de negócio — quem está usando a
   plataforma, quanto avançou, onde está na fila. Fica ao lado e não abaixo
   porque é leitura de acompanhamento: você passa o olho, não estuda.

   320px é o que cabe um ranking com nome, nível e XP sem quebrar linha. Abaixo
   de 1180 ela vai para o fim da página: espremida, deixaria de ser um canto e
   passaria a competir com o conteúdo. */
.home-corpo {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 320px;
  gap: 22px;
  align-items: start;
}

.home-corpo.is-sem-lado { grid-template-columns: minmax(0, 1fr); }

.home-principal {
  display: flex;
  flex-direction: column;
  gap: 26px;
  min-width: 0;
}

.home-lado {
  display: flex;
  flex-direction: column;
  gap: 12px;
  position: sticky;
  /* PARA ABAIXO DA BARRA, não debaixo dela. Com `top: 0` a coluna encostava no
     topo da janela — que é onde o cabeçalho está grudado, com `z-index` maior —
     e o nível e o XP ficavam escondidos atrás dele. O deslocamento é a altura
     do próprio cabeçalho, lida da variável: se ela mudar, isto acompanha. */
  top: calc(var(--header-height) + 16px);
  /* Rede de segurança para janela baixa: se a coluna não couber no que sobra da
     tela, ela rola por dentro em vez de ter o pé cortado sem jeito de alcançar.
     Cabendo, nada acontece — `auto` não desenha barra que não precisa. */
  max-height: calc(100vh - var(--header-height) - 32px);
  overflow-y: auto;
  scrollbar-width: thin;
}

/* ---------- Carrossel giratório ---------- */

/* O palco recorta o que passa das bordas e esmaece as pontas: sem isso a capa
   que está saindo é cortada em linha reta, e o corte reto parece defeito de
   layout em vez de "tem mais coisa ali". */
/* A folga vertical NÃO pode morar aqui. O `mask-image` recorta o que passa da
   caixa deste elemento, então padding no palco não abre espaço nenhum para a
   capa que sobe no hover — ela ainda seria cortada, só que pela máscara em vez
   de pelo trilho. A folga foi para dentro do `.home-capas`, onde ela conta. */
.home-palco {
  position: relative;
  margin: 0 -6px;
  mask-image: linear-gradient(to right, transparent 0, #000 7%, #000 93%, transparent 100%);
}

/* Rola na horizontal com encaixe NO CENTRO. `scroll-snap` em vez de paginação
   calculada: o navegador já sabe parar num cartão inteiro, e arrastar com o
   dedo continua funcionando sem nenhuma linha de JS. O `center` é o que faz a
   porta giratória — o cartão que encaixa é o do meio, não o da esquerda. */
.home-capas {
  /* A largura da capa é uma LENGTH, não um percentual: o mesmo valor precisa
     servir ao `flex-basis` (que resolve contra o conteúdo do trilho) e ao
     `padding` (que resolve contra a caixa dele). Em percentual os dois dão
     números diferentes assim que o padding existe — e a primeira capa nunca
     chega ao centro. */
  --capa-larg: min(320px, 34vw);
  display: flex;
  gap: 16px;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
  /* Metade do palco de cada lado, para a PRIMEIRA e a ÚLTIMA capa também
     conseguirem chegar ao centro. Sem isso elas encostam na borda e nunca
     entram em foco. */
  padding-inline: calc(50% - var(--capa-larg) / 2);
  /* FOLGA VERTICAL, e ela é obrigatória. `overflow-x: auto` faz o navegador
     tratar o eixo Y como `auto` também — o trilho vira um recorte nos dois
     sentidos, e um recorte de rolagem corta na borda do PADDING. Sem esta
     folga, a capa que sobe 3px no hover tinha o topo decepado, e a sombra da
     capa em foco morria na borda. Com ela, a capa se mexe dentro do padding e
     nada encosta no limite. */
  padding-block: 10px;
}

.home-capas::-webkit-scrollbar { display: none; }

/* A capa é a Home do relatório de origem, reduzida. Quem já viu o painel no
   Power BI reconhece antes de ler o nome — e é isso que a miniatura tem a
   oferecer sobre uma capa desenhada aqui. */
/* `--longe` vem do JS: 0 no centro do palco, 1 a uma capa de distância. Todo o
   efeito da porta giratória sai daqui — escala, desfoque e opacidade
   interpolados por essa única variável, sem classe intermediária e sem o JS
   precisar saber nada de aparência. */
.home-capa {
  --longe: 1;
  position: relative;
  flex: 0 0 var(--capa-larg);
  aspect-ratio: 16 / 9;
  scroll-snap-align: center;
  border: 1px solid var(--border-color);
  border-radius: var(--radius-lg);
  overflow: hidden;
  padding: 0;
  background: var(--bg-secondary);
  cursor: pointer;
  text-align: left;
  /* Recua até 12% e desfoca até 2,4px conforme se afasta do meio. O desfoque é
     pequeno de propósito: o suficiente para o olho saber qual é a principal,
     não tanto que a vizinha deixe de ser reconhecível — ela ainda é o destino
     do próximo clique. */
  transform: scale(calc(1 - 0.12 * var(--longe)));
  filter: blur(calc(2.4px * var(--longe)));
  opacity: calc(1 - 0.42 * var(--longe));
  transition: transform var(--transition-base), filter var(--transition-base),
              opacity var(--transition-base), border-color var(--transition-base);
}

/* No foco a capa ganha a cor do domínio na borda: é a mesma cor que a interface
   vai vestir quando você entrar, então a moldura já anuncia o destino. */
.home-capa.is-foco {
  border-color: var(--dominio-cor, var(--accent));
  box-shadow: 0 12px 34px rgba(0, 0, 0, 0.45);
}

.home-capa:hover {
  transform: scale(calc(1 - 0.12 * var(--longe))) translateY(-3px);
  border-color: var(--dominio-cor, var(--accent));
}

/* Só a capa em foco responde ao clique. Uma capa desfocada e recuada não parece
   clicável, e clicar nela sem querer tiraria a pessoa da tela — o gesto ali é
   girar o carrossel, não entrar. */
.home-capa:not(.is-foco) .home-capa-entrar { opacity: 0; }

.home-capa-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  transition: transform var(--transition-base);
}

.home-capa:hover .home-capa-img { transform: scale(1.03); }

/* Véu por cima da foto, mais denso embaixo: as capas têm áreas claras (a mesa
   do Financeiro, o laranja do E-commerce) e o nome branco sumiria em cima
   delas. O véu é do tom do DOMÍNIO, não preto — é o que liga a miniatura à
   cor que a interface vai vestir quando você entrar. */
.home-capa-tinta {
  position: absolute;
  inset: 0;
  background: linear-gradient(to top,
    rgba(10, 10, 11, 0.92) 0%,
    rgba(10, 10, 11, 0.55) 42%,
    rgba(10, 10, 11, 0.1) 100%);
}

.home-capa-texto {
  position: absolute;
  left: 16px;
  bottom: 14px;
  right: 46px;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.home-capa-nome {
  font-size: 16px;
  font-weight: 800;
  letter-spacing: -0.02em;
  color: #fff;
}

.home-capa-analises {
  font-size: 11.5px;
  color: var(--dominio-cor, var(--accent));
  font-weight: 600;
}

.home-capa-entrar {
  position: absolute;
  right: 14px;
  bottom: 14px;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: var(--dominio-cor, var(--accent));
  color: #0a0a0b;
  transition: transform var(--transition-base);
}

.home-capa-entrar .icone { width: 14px; height: 14px; }
.home-capa:hover .home-capa-entrar { transform: translateX(3px); }

/* Cada capa e cada cartão veste a cor do próprio domínio. É o mesmo mapa do
   `[data-dominio]` do variables.css, aplicado por ATRIBUTO em vez de por
   ancestral: aqui os quatro convivem na mesma tela e nenhum é "o" acento. */
[data-dominio="ecommerce"]  { --dominio-cor: var(--dominio-ecommerce); }
[data-dominio="financeiro"] { --dominio-cor: var(--dominio-financeiro); }
[data-dominio="rh"]         { --dominio-cor: var(--dominio-rh); }
[data-dominio="logistica"]  { --dominio-cor: var(--dominio-logistica); }

/* ---------- Indicadores por domínio ---------- */

/* As colunas acompanham o número de áreas, informado pelo JS em `--colunas`.
   Fixo em quatro, uma pessoa com duas áreas via metade da linha vazia: `1fr` de
   quatro colunas continua valendo um quarto por mais que só dois cartões
   entrem nela. O 4 é o padrão de quem tem a plataforma inteira. */
.home-kpis {
  display: grid;
  grid-template-columns: repeat(var(--colunas, 4), minmax(0, 1fr));
  gap: 12px;
}

.home-kpi {
  /* Coluna flex para a linha de apoio poder ser empurrada até o rodapé com
     `margin-top: auto`. Sem isso, o divisor de cada cartão parava onde o
     conteúdo acima dele terminasse — e o Financeiro, que não tem pastilha de
     variação, ficava com o divisor uma linha acima dos outros três. Quatro
     divisores em alturas diferentes quebram a leitura horizontal, que é o
     motivo de os cartões estarem lado a lado. */
  display: flex;
  flex-direction: column;
  padding: 14px 16px 15px;
  background: var(--bg-secondary);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-md);
  /* O fio do domínio no topo: quatro cartões iguais precisavam de um sinal de
     a quem pertencem que não fosse só o texto. */
  border-top: 2px solid var(--dominio-cor, var(--accent));
}

.home-kpi-topo {
  display: flex;
  align-items: center;
  gap: 7px;
  margin-bottom: 10px;
}

.home-kpi-icone {
  display: flex;
  color: var(--dominio-cor, var(--accent));
}

.home-kpi-icone .icone { width: 15px; height: 15px; }

.home-kpi-dominio {
  font-size: 12px;
  font-weight: 700;
  color: var(--text-primary);
}

/* O ano de CADA cartão, porque não existe um comum aos quatro. */
.home-kpi-ano {
  margin-left: auto;
  font-size: 11px;
  font-weight: 600;
  color: var(--text-muted);
  padding: 1px 7px;
  border: 1px solid var(--border-color);
  border-radius: 999px;
}

/* Base defasada: a própria pastilha do ano avisa. Âmbar e não vermelho — o
   dado não está errado nem em risco, está velho —, e o `title` diz de quantos
   anos é o atraso. Custa zero altura, que é o ponto: era como rodapé que ele
   desalinhava os quatro cartões. */
.home-kpi.is-defasado .home-kpi-ano {
  color: var(--warning-tinta);
  border-color: var(--warning);
  background: var(--warning-soft);
  cursor: help;
}

/* ---------- Área única: um indicador por cartão ----------

   `min-height` no topo porque só o primeiro cartão leva ícone e pastilha de
   ano, e os dois são mais altos que uma linha de texto. Sem o piso, o cabeçalho
   dos outros três fica dois pixels mais baixo e os quatro valores — que são o
   que se lê na horizontal — saem desalinhados. */
.home-kpi-solo .home-kpi-topo { min-height: 21px; }

/* Sem a lista de apoio no rodapé, a margem embaixo do valor não separa mais
   nada; e a pastilha de variação, que só o primeiro tem, desce para a base
   para não abrir um buraco entre ela e o valor. */
.home-kpi-solo .home-kpi-valor { margin-bottom: 0; }

.home-kpi-solo .home-kpi-var {
  margin-top: auto;
  align-self: flex-start;
}

.home-kpi-rotulo {
  font-size: 11.5px;
  color: var(--text-secondary);
}

.home-kpi-valor {
  font-size: 25px;
  font-weight: 800;
  letter-spacing: -0.03em;
  line-height: 1.2;
  margin-bottom: 10px;
}

/* A direção do indicador. Fica colada no valor, e não na linha de apoio: a
   pergunta "comparado com o quê?" nasce junto com o número, não depois dele. */
.home-kpi-var {
  display: inline-flex;
  align-items: baseline;
  /* Como item de uma coluna flex ele esticaria na largura toda do cartão e a
     pastilha viraria uma faixa. O `flex-start` devolve a largura ao conteúdo. */
  align-self: flex-start;
  gap: 5px;
  margin-bottom: 10px;
  font-size: 12px;
  font-weight: 700;
  padding: 2px 8px;
  border-radius: 999px;
  background: var(--bg-tertiary);
}

.home-kpi-var small {
  font-size: 10px;
  font-weight: 600;
  color: var(--text-muted);
}

/* Verde e vermelho aqui são leitura de bom/ruim, e QUEM DECIDE é o banco pelo
   `sentido` — não a direção da seta. Um "vencido a receber" caindo é ótimo e
   subiria em verde se a cor viesse do sinal. Sem `sentido`, `is-neutro`: seta
   sem julgamento é melhor que julgamento errado. */
.home-kpi-var.is-bom    { color: var(--success-tinta); background: var(--success-soft); }
.home-kpi-var.is-ruim   { color: var(--danger-tinta);  background: var(--danger-soft); }
.home-kpi-var.is-neutro { color: var(--text-secondary); }
.home-kpi-var.is-parado { color: var(--text-muted); }

.home-kpi-apoio {
  display: flex;
  gap: 18px;
  /* Colado no rodapé do cartão, e é o `auto` que alinha os quatro divisores na
     mesma altura mesmo quando um cartão tem uma linha a menos que os outros. */
  margin-top: auto;
  padding-top: 10px;
  border-top: 1px solid var(--border-color);
}

.home-kpi-apoio dt {
  font-size: 10.5px;
  color: var(--text-muted);
}

.home-kpi-apoio dd {
  font-size: 12.5px;
  font-weight: 700;
  color: var(--text-primary);
}


/* ---------- Insights ---------- */

/* A leitura da plataforma inteira, acima das colunas e ocupando a largura toda:
   ela fala das quatro áreas, então não cabe dentro de uma. */
.home-insight-geral {
  margin-bottom: 12px;
}

/* Uma COLUNA POR ÁREA. Três linhas fixas — o título e os dois cartões — e cada
   grupo ocupa as três com `subgrid`, que é o que faz os cartões da segunda
   linha começarem na mesma altura em todas as colunas mesmo com textos de
   tamanhos diferentes. Sem o subgrid cada coluna se resolveria sozinha e os
   cartões voltariam a ficar em degrau.

   Onde `subgrid` não existir, a regra é ignorada e o grupo vira um grid comum:
   os cartões continuam empilhados na coluna certa, só perdem o alinhamento
   entre colunas. Degrada no acabamento, não na organização. */
/* Uma coluna por ÁREA COM ACHADO — ver a nota no `montar`. O `subgrid` de cada
   grupo alinha cabeçalho e cartões na mesma altura entre as colunas, e é isso
   que permite ler a faixa na horizontal. */
.home-insights {
  display: grid;
  grid-template-columns: repeat(var(--colunas, 4), minmax(0, 1fr));
  grid-template-rows: auto 1fr 1fr;
  gap: 10px 12px;
}

.home-insight-grupo {
  display: grid;
  grid-row: span 3;
  grid-template-rows: subgrid;
  gap: 10px;
}

/* ---------- Área única ----------

   A grade tem uma COLUNA POR ÁREA, e o `subgrid` alinha os cartões de todas na
   mesma altura — o que só faz sentido quando há mais de uma para alinhar. Com
   uma, sobrava uma tira estreita e três quartos de vazio.

   Aqui a área toma a largura inteira e são os ACHADOS dela que se dividem em
   colunas. O `subgrid` sai junto: sem vizinha, ele só imporia altura fixa a
   cartões de textos de tamanhos diferentes. */
.home-insights.is-solo {
  grid-template-columns: minmax(0, 1fr);
  grid-template-rows: none;
}

.home-insights.is-solo .home-insight-grupo {
  grid-row: auto;
  grid-template-rows: none;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  align-items: start;
}

/* O nome da área é o cabeçalho da faixa inteira, não da primeira coluna. */
.home-insights.is-solo .home-insight-grupo-nome { grid-column: 1 / -1; }

/* O nome da área substitui a etiqueta que cada cartão tinha. Carrega a cor do
   domínio e o mesmo ícone do menu — é o cabeçalho da coluna, não um rótulo
   repetido duas vezes abaixo. */
.home-insight-grupo-nome {
  display: flex;
  align-items: center;
  gap: 6px;
  padding-bottom: 7px;
  border-bottom: 1px solid var(--border-color);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--dominio-cor, var(--accent));
}

.home-insight-grupo-icone { display: flex; }
.home-insight-grupo-icone .icone { width: 14px; height: 14px; }

.home-insight {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 15px 17px 14px;
  background: var(--bg-secondary);
  border: 1px solid var(--border-color);
  border-left: 3px solid var(--dominio-cor, var(--accent));
  border-radius: var(--radius-md);
  text-align: left;
  cursor: pointer;
  transition: border-color var(--transition-fast), transform var(--transition-fast);
}

.home-insight:hover {
  transform: translateY(-2px);
  border-color: var(--border-color-light);
  border-left-color: var(--dominio-cor, var(--accent));
}

/* Severidade 3 respira em vermelho na borda: é perda dimensionada em dinheiro,
   e precisa se separar das leituras de composição. A cor do domínio continua
   à esquerda — as duas informações são diferentes e cabem juntas. */
.home-insight.is-sev3 { border-color: var(--alerta-borda-fraca); }

/* O insight que lê as quatro áreas não abre tela nenhuma: sem cursor de clique,
   sem o salto no hover. Prometer uma ação que não existe é pior que não ter. */
.home-insight.is-leitura {
  cursor: default;
  border-left-color: var(--text-muted);
}

.home-insight.is-leitura:hover { transform: none; }

.home-insight-topo {
  display: flex;
  align-items: baseline;
  gap: 10px;
}

/* ---------- O alinhamento interno dos cartões agrupados ----------

   Quatro faixas fixas: selo, título, texto e rodapé. O cartão deixa de empilhar
   o conteúdo e passa a distribuí-lo em linhas de altura reservada — é o que faz
   quatro cartões lado a lado terem título, texto e "Abrir a análise" na mesma
   altura mesmo quando um tem selo e o outro não, ou quando um título ocupa uma
   linha e o vizinho ocupa duas.

   Só vale dentro dos grupos. O cartão da plataforma fica numa faixa sozinho,
   não tem com quem alinhar, e não tem rodapé — a quarta linha nele seria um
   vazio no pé do cartão. */
.home-insight-grupo .home-insight {
  display: grid;
  grid-template-rows: auto auto 1fr auto;
  gap: 7px;
}

/* A linha do selo é RESERVADA, esteja ela ocupada ou não. Antes ela sumia
   quando vazia, e o título do cartão sem valor em jogo subia — que é
   exatamente o degrau que se via entre as colunas. */
.home-insight-grupo .home-insight-topo {
  min-height: 21px;
}

/* Dois títulos de altura: um de uma linha e um de duas passam a começar E
   terminar juntos, e o texto abaixo dos dois arranca do mesmo lugar. Em `em`
   para acompanhar a fonte — em pixel, um ajuste de corpo desalinharia tudo de
   novo sem ninguém perceber. */
.home-insight-grupo .home-insight-titulo {
  min-height: 2.6em;
}

/* O texto ocupa a folga (`1fr`), mas ancorado no TOPO da faixa: sem isso ele
   flutuaria no meio do espaço sobrando e o parágrafo curto ficaria descolado do
   próprio título. */
.home-insight-grupo .home-insight-texto {
  align-self: start;
}

/* E o rodapé encostado embaixo, que é o pedido: como o texto absorve a folga,
   "Abrir a análise" cai no pé de todos os cartões da linha. */
.home-insight-grupo .home-insight-ir {
  align-self: end;
}

.home-insight-tag {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--dominio-cor, var(--accent));
}

.home-insight.is-leitura .home-insight-tag { color: var(--text-muted); }

/* O valor em jogo é o que ORDENA a lista. Mostrá-lo é o que faz a ordem ser
   lida como ordem, e não como uma sequência qualquer — sem ele, "por que este
   veio primeiro?" não tem resposta na tela. */
.home-insight-risco {
  flex: 0 0 auto;
  /* À direita esteja ou não acompanhado da etiqueta da área — dentro dos grupos
     ele fica sozinho nesta linha, e sem a margem automática cairia à esquerda. */
  margin-left: auto;
  font-size: 10.5px;
  font-weight: 700;
  white-space: nowrap;
  padding: 2px 8px;
  border-radius: 999px;
  color: var(--text-secondary);
  background: var(--bg-tertiary);
  border: 1px solid var(--border-color);
}

.home-insight.is-sev3 .home-insight-risco {
  color: var(--danger-tinta);
  background: var(--danger-soft);
  border-color: var(--alerta-borda-fraca);
}

.home-insight-titulo {
  font-size: 14.5px;
  font-weight: 700;
  line-height: 1.3;
  color: var(--text-primary);
}

.home-insight-texto {
  font-size: 12.5px;
  line-height: 1.6;
  color: var(--text-secondary);
}

.home-insight-texto strong { color: var(--text-primary); }

.home-insight-ir {
  display: flex;
  align-items: center;
  gap: 4px;
  margin-top: 4px;
  font-size: 11.5px;
  font-weight: 600;
  color: var(--dominio-cor, var(--accent));
}

.home-insight-ir .icone { width: 13px; height: 13px; }

/* ---------- Coluna de gente ---------- */

.home-eu,
.home-com,
.home-ultimas {
  padding: 15px 16px;
  background: var(--bg-secondary);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-md);
}

.home-eu-topo {
  display: flex;
  align-items: baseline;
  gap: 8px;
  margin-bottom: 12px;
}

.home-eu-nome {
  font-size: 14px;
  font-weight: 800;
  letter-spacing: -0.02em;
}

.home-eu-pos {
  margin-left: auto;
  font-size: 11px;
  font-weight: 600;
  color: var(--fogo-tinta);
  padding: 1px 8px;
  border: 1px solid var(--fogo-borda);
  background: var(--fogo-fundo);
  border-radius: 999px;
}

.home-eu-anel {
  display: flex;
  align-items: center;
  gap: 14px;
}

/* O anel herda o âmbar da gamificação, não o acento do domínio: XP e sequência
   não pertencem a nenhuma análise — é a mesma razão pela qual `--fogo` existe
   fora dos acentos, lá no variables.css. */
.home-eu-anel .g-rosca { flex: 0 0 78px; }
.home-eu-anel .g-rosca svg { max-width: 78px; }
.home-eu-anel .g-rosca-arco { stroke: var(--fogo); }
.home-eu-anel .g-rosca-num { font-size: 17px; }

.home-eu-rot {
  font-size: 12px;
  font-weight: 700;
  color: var(--text-primary);
}

.home-eu-xp {
  font-size: 19px;
  font-weight: 800;
  letter-spacing: -0.02em;
  color: var(--fogo-tinta);
}

.home-eu-falta {
  font-size: 11px;
  color: var(--text-muted);
  line-height: 1.4;
}

.home-eu-falta strong { color: var(--text-secondary); }

.home-eu-linhas {
  display: flex;
  gap: 14px;
  margin-top: 13px;
  padding-top: 11px;
  border-top: 1px solid var(--border-color);
}

.home-eu-linhas dt { font-size: 10.5px; color: var(--text-muted); }
.home-eu-linhas dd { font-size: 12.5px; font-weight: 700; }

/* ---------- Comunidade ---------- */

.home-com-topo {
  display: flex;
  flex-direction: column;
  gap: 3px;
  margin-bottom: 11px;
}

.home-com-titulo {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-secondary);
}

.home-com-titulo .icone { width: 14px; height: 14px; color: var(--brand); }

.home-com-titulo { text-decoration: none; }
.home-com-titulo:hover .home-com-ir { color: var(--brand); }

.home-com-ir {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 3px;
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0;
  text-transform: none;
  color: var(--text-muted);
  transition: color var(--transition-fast);
}

.home-com-ir .icone { width: 11px; height: 11px; color: currentColor; }

.home-com-vivo { font-size: 11.5px; color: var(--text-muted); }
.home-com-vivo strong { color: var(--brand); }

.home-com-lista {
  display: flex;
  flex-direction: column;
  gap: 2px;
  list-style: none;
}

.home-com-item {
  display: grid;
  grid-template-columns: 18px minmax(0, 1fr) auto auto;
  align-items: center;
  gap: 8px;
  padding: 5px 7px;
  border-radius: var(--radius-sm);
  font-size: 12px;
}

/* A própria linha em destaque: numa lista de nomes parecidos, achar o seu não
   pode depender de ler todos. */
.home-com-item.is-eu {
  background: var(--fogo-fundo);
  box-shadow: inset 0 0 0 1px var(--fogo-borda);
}

.home-com-pos {
  font-size: 11px;
  font-weight: 700;
  color: var(--text-muted);
  text-align: right;
}

.home-com-item.is-eu .home-com-pos { color: var(--fogo-tinta); }

.home-com-nome {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--text-primary);
}

.home-com-nivel { font-size: 10.5px; color: var(--text-muted); }
.home-com-xp { font-size: 11.5px; font-weight: 700; color: var(--text-secondary); }

.home-com-pe {
  margin-top: 11px;
  padding-top: 10px;
  border-top: 1px solid var(--border-color);
  font-size: 11.5px;
  color: var(--text-muted);
}

.home-com-pe strong { color: var(--text-primary); }

/* ---------- Suas últimas análises ---------- */

.home-ultimas-topo {
  margin-bottom: 10px;
}

.home-ultimas-titulo {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-secondary);
}

.home-ultimas-titulo .icone {
  width: 14px;
  height: 14px;
  color: var(--brand);
}

.home-ultimas-lista {
  display: flex;
  flex-direction: column;
  gap: 2px;
  list-style: none;
}

/* A linha inteira é o botão, não um link dentro dela: a área de clique passa a
   ser o cartão todo e o teclado alcança pelo Tab sem atributo extra — o mesmo
   critério das capas do carrossel. */
.home-ultima {
  display: flex;
  align-items: center;
  gap: 9px;
  width: 100%;
  padding: 7px 8px;
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  background: transparent;
  text-align: left;
  cursor: pointer;
  transition: background var(--transition-fast), border-color var(--transition-fast);
}

.home-ultima:hover {
  background: var(--bg-tertiary);
  border-color: var(--border-color);
}

.home-ultima-icone {
  display: flex;
  color: var(--text-muted);
}

.home-ultima-icone .icone { width: 15px; height: 15px; }

/* `min-width: 0` para o nome longo poder truncar: sem isso o item de flex se
   recusa a encolher abaixo do conteúdo e empurra a data para fora do cartão. */
.home-ultima-txt {
  display: flex;
  flex-direction: column;
  gap: 1px;
  min-width: 0;
  flex: 1;
}

.home-ultima-tela {
  font-size: 12.5px;
  font-weight: 600;
  color: var(--text-primary);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.home-ultima-area {
  font-size: 10.5px;
  color: var(--text-muted);
}

/* A data não encolhe nunca: é ela que responde "quando", e um "há 3 di…" não
   responde nada. Quem cede espaço é o nome da tela, logo acima. */
.home-ultima-dia {
  flex: 0 0 auto;
  font-size: 10.5px;
  font-weight: 600;
  color: var(--text-muted);
  white-space: nowrap;
}

@media (max-width: 1180px) {
  /* A coluna de gente vai para o FIM: espremida a 200px ela deixaria de ser um
     canto de acompanhamento e passaria a disputar espaço com o conteúdo. */
  .home-corpo { grid-template-columns: minmax(0, 1fr); }
  /* DESFAZ A ROLAGEM PRÓPRIA, e não só o `sticky`.
     Empilhada, a coluna deixou de ser uma barra lateral e virou mais um bloco
     da página — mas o `max-height` e o `overflow-y` do desktop continuavam
     valendo, e ela abria uma segunda barra de rolagem dentro da primeira. No
     celular o efeito é o pior possível: o dedo rola a página e a lista de
     dentro fica parada, ou o contrário, dependendo de onde ele encostou.
     A rede de segurança que eles eram só faz sentido enquanto a coluna divide
     a altura da tela com o conteúdo ao lado. */
  .home-lado {
    position: static;
    max-height: none;
    overflow: visible;
  }
  .home-kpis { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .home-insights { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .home-capas { --capa-larg: min(320px, 56vw); }
  /* Sem a coluna de gente ao lado, a linha fica larga demais para uma capa de
     16/9 esticada — ela viraria um banner e comeria a dobra. Empilhar devolve a
     capa ao tamanho de leitura e põe as análises logo abaixo, em três colunas. */
  .home-solo { grid-template-columns: minmax(0, 1fr); }
  .home-solo .home-capa-fixa { max-width: 520px; }
  .home-solo-telas { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

@media (max-width: 680px) {
  .home-kpis { grid-template-columns: minmax(0, 1fr); }
  /* Numa coluna só o subgrid não tem o que alinhar — cada área vira um bloco
     corrido, e as linhas fixas dariam altura vazia onde não há segundo cartão. */
  .home-insights {
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: none;
  }
  .home-insight-grupo {
    grid-row: auto;
    grid-template-rows: none;
  }
  /* A variante de área única também desce para uma coluna. A regra dela é mais
     específica que a de cima, então precisa ser desfeita por nome — senão os
     dois achados ficam lado a lado num celular, com quatro palavras por linha. */
  .home-insights.is-solo .home-insight-grupo {
    grid-template-columns: minmax(0, 1fr);
  }
  /* Três capas numa tela de celular sairiam com 100px de largura cada — a
     miniatura do relatório, que é a razão de a capa ser uma foto, deixaria de
     ser reconhecível. Empilhadas, cada uma volta ao tamanho de leitura. */
  .home-capas-grade { grid-template-columns: minmax(0, 1fr); }
  .home-capas { --capa-larg: 78vw; }
  .home-titulo { font-size: 26px; }
  .home-solo .home-capa-fixa { max-width: none; }
  .home-solo-telas { grid-template-columns: minmax(0, 1fr); }
}


/* ---------- Slide de imagem ----------
   Um slide que não é análise: a imagem inteira, centrada, sem cortar. `contain`
   e não `cover` porque quem põe um gráfico exportado ou um aviso no telão
   precisa dele completo — `cover` preencheria a área comendo as bordas, que é
   justamente onde costuma estar a legenda. */

.slide-imagem {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: calc(100vh - var(--header-height) - 56px);
}

.slide-imagem img {
  max-width: 100%;
  max-height: calc(100vh - var(--header-height) - 56px);
  object-fit: contain;
  border-radius: var(--radius-md);
}


/* ============================================================
   CELULAR — o painel deixa de caber e passa a rolar
   ============================================================
   As análises foram desenhadas para CABER NA TELA sem rolagem: a cadeia inteira
   é de altura fixa (`.principal` → `.conteudo` → `.analise` → `.analise-grade`),
   e as linhas da grade usam `minmax(0, 1fr)` para dividir o que sobra. É o certo
   para desktop e é o que faz a apresentação em TV funcionar.

   No celular esse modelo não tem como valer. Medido numa tela de 375×812: depois
   do cabeçalho e dos KPIs, sobravam 162px para quatro painéis — 31,6px cada, ou
   seja, só a barra de título. Os gráficos não apareciam, e não por defeito de
   desenho: `1fr` de uma altura que não existe é zero.

   Então aqui o modelo INVERTE. Não é o mesmo painel menor: é outro objeto —
   uma pilha que rola, um gráfico embaixo do outro, cada um com altura própria.
   Tentar preservar "cabe na tela" em 375px daria quatro faixas ilegíveis.
   ============================================================ */

@media (max-width: 720px) {
  /* A cadeia toda solta a altura — os DOIS, e não só `.analise`. Sem o
     `.analise-alvo` junto, o filho cresce e o pai continua em 640px: o
     conteúdo passa a existir e permanece recortado, que é o pior dos dois
     mundos — o gráfico é desenhado e ninguém o vê. */
  /* ============================================================
     O RODAPÉ SAÍA DA ÁREA ROLÁVEL — a causa, medida
     ============================================================
     Aumentar a folga não resolvia porque o problema nunca foi de folga.

     `.analise-alvo` é `flex: 1 1 0%` — a base zero vem do desktop, onde a
     análise cabe na tela e o alvo divide a altura com o que houver. No celular
     nada cabe, e `1 1 0%` continua valendo: medido em 375px, o alvo ficou com
     630px enquanto o conteúdo dentro dele tinha 3.865px. Ele TRANSBORDAVA com
     `overflow: visible`.

     Transbordo não entra no `scrollHeight` do pai. O `.conteudo` calculava
     3.883px de altura rolável para um rodapé que começava em 3.894 — ou seja,
     o rodapé estava FORA do que dava para rolar, e nenhum `padding-bottom`
     alcança o que já está além do fim.

     `0 0 auto` faz o alvo ter a altura do próprio conteúdo. Aí o `scrollHeight`
     passou de 3.883 para 3.979, e o rodapé terminou 40px acima da barra — que é
     exatamente a folga pedida no `padding-bottom`. Medido antes e depois. */
  .analise-alvo { flex: 0 0 auto; }

  .analise-alvo,
  .analise { height: auto; }

  /* E a rolagem. Precisa REPETIR o `:has(.analise)` do bloco lá em cima: aquela
     regra tem duas classes de especificidade, e um `.conteudo` sozinho dentro
     de media query perde para ela — media query não soma especificidade.
     Sem esta linha o conteúdo cresce e continua recortado: medido em 1725px
     dentro de 744px, com 981px invisíveis. */
  .conteudo:has(.analise) { overflow-y: auto; }

  /* E A FOLGA DO RODAPÉ, repetida aqui pelo mesmo motivo da linha acima:
     `.conteudo:has(.analise)` tem duas classes de especificidade e declara
     `padding-bottom: 8px`. O `.conteudo` do shell.css tem uma, e media query
     não soma especificidade — então nas ANÁLISES a folga que existe para a
     barra inferior era descartada, e o rodapé de "Filtro aplicado" terminava
     debaixo dela.

     O valor é o mesmo de lá, e sai da variável que mede a barra. */
  .conteudo:has(.analise) {
    padding-bottom: calc(var(--barra-inferior-altura, 56px) + 40px
                         + env(safe-area-inset-bottom, 0px));
  }

  .analise-grade {
    /* Uma coluna. As 24 colunas existem para compor larguras (w7, w9, w16…) e
       no celular não há o que compor: tudo ocupa a linha inteira. */
    grid-template-columns: minmax(0, 1fr);

    /* A altura de cada painel deixa de ser dividida e passa a ser PEDIDA.
       260px é o menor tamanho em que um gráfico de barras com eixo ainda se
       lê — abaixo disso os rótulos começam a se sobrepor. O `auto` no topo
       deixa crescer quem precisa (tabela, ranking longo). */
    grid-auto-rows: minmax(260px, auto);
    flex: 0 0 auto;
  }

  /* As classes de composição perdem o efeito: `w7` e `w16` não significam nada
     numa coluna só, e `h2` pediria altura dobrada num contexto onde a altura
     já é livre. Anuladas de uma vez, em vez de uma regra por variante. */
  .analise-grade > [class*="painel--w"],
  .analise-grade > [class*="painel--h"] {
    grid-column: 1 / -1;
    grid-row: auto;
  }

  /* `overflow: hidden` no painel é a trava que impede conteúdo de vazar quando
     a altura é imposta de fora. Aqui a altura é natural, então recortar só
     esconderia o gráfico que acabou de ganhar espaço. */
  .painel { overflow: visible; }
}
