/* A INTER LOCAL, O MESMO ARQUIVO QUE O SITE USA.

   O token `--font-system` sempre disse "Inter, Arial, sans-serif", mas o
   `@font-face` que carrega o arquivo mora em `assets/site.css`, e a demo nao
   carrega essa folha — so `tokens.css` e esta aqui. Resultado medido na
   pagina publicada em 09/09/2026: nenhum face carregado, nenhum .woff2
   pedido, e pedir "Inter" dava exatamente a mesma metrica de pedir uma fonte
   inexistente. Nao caia nem em Arial: caia na sans-serif padrao do
   navegador. Site e demo desenhavam com tipos diferentes.

   Declaracao identica a de site.css, apontando para o MESMO arquivo — nao um
   segundo .woff2, nao a Google Fonts, nao CDN. Duas declaracoes do mesmo
   face na mesma origem nao baixam duas vezes: o navegador reaproveita.

   O caminho sobe dois niveis porque esta folha mora em demo/assets/ e a
   fonte mora em assets/, irmao de demo/. */
@font-face{font-family:Inter;src:url('../../assets/inter-latin.woff2') format('woff2');font-style:normal;font-weight:100 900;font-display:swap}
/* =============================================================================
 * DEMONSTRAÇÃO DA PLATAFORMA DATAPEX — estilos da aplicação.
 *
 * Segue o padrão de interface do painel que já está em produção: barra lateral
 * de módulos, um único sistema de botão, indicador numérico denso, cartão sem
 * sombra, título substantivo. O que foi herdado é a ESTRUTURA do padrão; os
 * valores vêm dos tokens da Datapex, nunca da outra marca.
 *
 * TRÊS REGRAS DE COR, herdadas do painel e válidas aqui sem exceção:
 *
 *   1. IDENTIDADE SEGUE A ENTIDADE, JAMAIS O RANKING. Uma unidade tem sempre a
 *      mesma cor, esteja em primeiro ou em último lugar. Colorir o último
 *      colocado de vermelho faz a cor mudar de significado a cada filtro.
 *
 *   2. IDENTIDADE E ESTADO NUNCA SE MISTURAM. Cor de entidade não vira status;
 *      cor de status não vira série. E cor de estado sempre vem com rótulo ao
 *      lado, porque a mesma tinta serve a domínios diferentes.
 *
 *   3. A MARCA NÃO PINTA DADO. Oxblood é assinatura e navegação — nunca
 *      barra, linha ou fatia. É a regra do próprio guia da marca: "não
 *      colorir séries/estados com a marca por padrão".
 *
 * QUATRO FAMÍLIAS DE COR, CADA UMA COM UM DOMÍNIO. Cada uma responde a uma
 * pergunta diferente, e é por isso que nenhuma pode invadir a outra:
 *
 *   IDENTIDADE ...... "onde eu estou"     barra do módulo ativo, selo
 *   NEUTRO .......... "o que eu escolhi"  chip selecionado, botão de ação
 *   SEMÂNTICO ....... "qual é o estado"   faixa do indicador, variação
 *   PAPEL DA MEDIDA . "que dado é este"   série do gráfico
 *
 * A identidade aparece UMA vez por tela, na lateral. Quando ela também
 * pintava o chip selecionado, apareciam quatro Oxbloods simultâneos — e a
 * cor que marca tudo deixa de marcar coisa alguma.
 *
 * TOKEN DE IDENTIDADE É `identity-readable`, NUNCA `brand-signature`.
 * Os dois valem #542E38 no tema claro, então parecem intercambiáveis — e não
 * são: `brand-signature` continua #542E38 no tema escuro e mede 1,38:1
 * contra a superfície escura, ou seja, o indicador de módulo ativo
 * simplesmente sumiria quando o tema escuro entrasse. `identity-readable`
 * resolve por tema (#B36F7B no escuro, 4,14:1) e é o token que o guia da
 * marca descreve como "leitura contextual da mesma identidade no dark".
 *
 * TODA COR VEM DE TOKEN. Nenhum hexadecimal escrito à mão neste arquivo — é o
 * que permite o tema escuro entrar depois sem reabrir cada componente.
 * ========================================================================== */

:root {
  /* UM token de transição para tudo que reage ao ponteiro. Duração e curva
     por componente produzem uma interface que parece montada por pessoas
     diferentes. Os valores vêm dos tokens de movimento da Datapex — 160ms é
     o tempo de feedback que o Brand System declara. */
  --t: 160ms cubic-bezier(0.2, 0, 0, 1);
  /* 240 e não 212: com o ícone na anatomia oficial (20px) e o rótulo no papel
     `navigation` (14px), a largura antiga cortava "Comercial" e "Analytics" em
     reticências. A largura acompanha a escala; não o contrário. */
  --lateral: 240px;

  /* ESCALA DE LEITURA DO BRAND SYSTEM 1.0, pelos papéis que ele nomeia.
     Antes esta folha usava 12,5px / peso 660 / 10,5px, que são os valores do
     painel de onde veio o padrão de interface — e valores pertencem à marca
     daquele produto, não a esta. A estrutura se herda; a escala, não. */
  --tipo-kpi: 28px;          --tipo-kpi-peso: 500;   /* kpiMedium */
  --tipo-kpi-grande: 40px;                           /* kpiLarge, ≥1600 */
  --tipo-tabela: 14px;                               /* table */
  --tipo-nav: 14px;          --tipo-nav-peso: 500;   /* navigation */
  --tipo-label: 13px;        --tipo-label-peso: 600; /* label */
  --tipo-caption: 12px;                              /* caption */
  --tipo-corpo: 14px;                                /* bodySmall: tela operacional */
  --tipo-h4: 20px;           --tipo-h4-peso: 600;    /* h4 */
}

*, *::before, *::after { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--color-background-default);
  color: var(--color-text-primary);
  font-family: var(--font-system);
  font-size: var(--tipo-corpo);
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

/* Dígito de largura fixa em todo número comparável: sem isso as colunas dançam
   a cada troca de filtro e o olho perde o alinhamento que as torna legíveis. */
.tile .v, .tab__num, .gr__valor, .gr__eixo, .comp__valor {
  font-variant-numeric: tabular-nums;
}

/* Foco visível e uniforme. `currentColor` em vez de token fixo: o mesmo anel
   precisa aparecer sobre superfície clara e sobre botão escuro, e herdar a
   tinta do componente carrega a garantia de contraste que ele já cumpre. */
:where(a, button, select, input, [tabindex]):focus-visible {
  outline: 2px solid currentColor;
  outline-offset: 3px;
  border-radius: var(--radius-small);
}

.pular {
  position: absolute; inset-inline-start: -9999px; inset-block-start: 0;
  z-index: 60; padding: var(--spacing-inline) var(--spacing-control);
  background: var(--color-action-primary-default);
  color: var(--color-action-primary-foreground);
  text-decoration: none;
}
.pular:focus { inset-inline-start: 0; }

/* Rótulo que existe para o leitor de tela e não ocupa espaço na tela. O
   filtro mostra o valor escolhido, que já diz o que ele é; quem navega por
   voz precisa do nome do campo mesmo assim. */
/* TEXTO SO PARA LEITOR DE TELA.
 *
 * As duas ancoras nao sao enfeite: sem elas o elemento absoluto assume a
 * POSICAO ESTATICA — onde ele cairia no fluxo. Dentro da trilha de filtros do
 * mobile, que rola na horizontal e tem 1240px de conteudo, a posicao estatica
 * de um destes rotulos fica em x=897. O elemento tem 1px e e invisivel, mas
 * ainda assim ESTICA O DOCUMENTO ate la: a pagina inteira passava a rolar
 * 523px para a direita, e o que aparecia era uma faixa branca.
 *
 * Ancorado em zero, ele nunca herda um deslocamento de rolagem. Continua
 * fora do fluxo (nao empurra nada, nao ganha `gap` de flex) e continua sendo
 * lido em voz alta na ordem do DOM, que e a unica coisa que importa nele.
 */
.sr-oculto {
  position: absolute; inset-inline-start: 0; inset-block-start: 0;
  inline-size: 1px; block-size: 1px;
  padding: 0; margin: 0; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap; border: 0;
}

/* ═══════════════════════════ BOTÕES ═══════════════════════════════════════
   Um sistema só: geometria fixa, e as variantes mudam apenas cor, fundo,
   sombra e borda — nunca a física do movimento, que é sempre "sobe 1px no
   hover, desce ao clicar". */
button, .botao {
  font: inherit; font-size: var(--tipo-tabela); font-weight: 560;
  padding: 7px 13px; min-block-size: 38px;
  border-radius: var(--radius-button);
  border: 1px solid var(--color-border-default);
  background: var(--color-surface-default);
  color: var(--color-text-primary);
  cursor: pointer; display: inline-flex; align-items: center; gap: 6px;
  box-shadow: var(--shadow-elevation1);
  text-decoration: none; white-space: nowrap;
  transition: transform var(--t), box-shadow var(--t), background var(--t),
              border-color var(--t), color var(--t);
}
button:hover:not(:disabled), .botao:hover {
  transform: translateY(-1px);
  box-shadow: var(--shadow-elevation2);
}
button:active:not(:disabled), .botao:active {
  transform: translateY(0);
  box-shadow: var(--shadow-elevation1);
}
/* Desabilitado não ganha cor própria: reduz opacidade e perde a sombra, para
   ficar chapado na página. Recolorir para cinza criaria mais um token sem
   necessidade. */
button:disabled { opacity: 0.45; cursor: not-allowed; box-shadow: none; transform: none; }

.botao--primario {
  background: var(--color-action-primary-default);
  border-color: var(--color-action-primary-default);
  color: var(--color-action-primary-foreground);
  font-weight: 640;
}
.botao--primario:hover { filter: brightness(1.12); }

/* Rótulo clicável que precisa parecer texto, não botão: anula a aparência
   inteira e cancela o movimento, senão um texto no meio de uma frase pularia. */
.botao--texto {
  padding: 0; min-block-size: 0; border: none; background: none; box-shadow: none;
  font-size: inherit; font-weight: inherit; color: var(--color-text-secondary);
  text-decoration: underline; text-underline-offset: 3px;
  text-decoration-color: var(--color-border-strong);
}
.botao--texto:hover:not(:disabled) {
  transform: none; box-shadow: none;
  color: var(--color-text-primary);
  text-decoration-color: currentColor;
}

/* ═══════════════════════════ ESTRUTURA ════════════════════════════════════ */
.app { display: grid; grid-template-columns: var(--lateral) 1fr; min-block-size: 100vh; }

/* ── barra lateral ─────────────────────────────────────────────────────────
   A largura é uma variável só, consumida pela grade. Mudá-la move o layout
   inteiro sem tocar em nenhuma outra regra. */
.lateral {
  position: sticky; inset-block-start: 0; block-size: 100vh; overflow: hidden auto;
  background: var(--color-surface-elevated);
  border-inline-end: 1px solid var(--color-border-default);
  display: flex; flex-direction: column; gap: 2px; padding: 14px 11px;
}
/* RESPIRO DA MARCA: 0,5 H a partir do contorno visível, que para 32px de
   altura total dá cerca de 11,76px. O guia é explícito que o respiro interno
   do viewBox conta mas a aplicação precisa completar a distância — 4px no
   topo e 6px nas laterais não completavam. */
.marca-topo {
  display: flex; align-items: center;
  padding: 12px 12px var(--spacing-control);
  /* ALTURA FIXA NOS DOIS ESTADOS. Símbolo e lockup têm a mesma altura, mas a
     caixa declarada é o que garante que trocar um pelo outro não mexa em
     nada abaixo. Recolher move a largura, nunca a altura. */
  min-block-size: calc(32px + 12px + var(--spacing-control));
}
.marca-topo a { display: flex; align-items: center; block-size: 32px;
  color: inherit; text-decoration: none; }
.marca-topo img { display: block; }
/* O mestre do tema vigente aparece; o outro sai do fluxo E da arvore de
   acessibilidade. Sem atributo de tema — script que nao rodou — vale o
   claro, que e o padrao da folha. */
.marca-topo img.marca-topo__lockup--escuro { display: none; }
[data-mode="dark"] .marca-topo img.marca-topo__lockup--claro { display: none; }
[data-mode="dark"] .marca-topo img.marca-topo__lockup--escuro { display: block; }

.grupo-nav {
  font-size: var(--tipo-caption); font-weight: var(--tipo-label-peso);
  text-transform: uppercase; letter-spacing: 0.06em;
  color: var(--color-text-muted);
  padding: var(--spacing-inline) 8px var(--spacing-compact);
}

.item-mod {
  display: flex; align-items: center; gap: 9px; inline-size: 100%;
  padding: 8px 9px; min-block-size: 38px;
  font-size: var(--tipo-nav); font-weight: var(--tipo-nav-peso);
  line-height: 1.4; text-align: start;
  color: var(--color-text-secondary);
  background: none; border: 1px solid transparent; border-radius: var(--radius-medium);
  /* O item de menu não usa o efeito de elevação dos botões de ação: navegar
     não é uma ação com consequência, e o menu inteiro pulando ao passar o
     mouse é ruído. */
  box-shadow: none; cursor: pointer;
  transition: background var(--t), color var(--t), border-color var(--t);
}
/* Mesma exclusão do item ativo: hoje as duas regras pintam a mesma cor e o
   defeito não aparece, mas basta alguém mudar uma delas para o item atual
   perder o destaque ao passar o mouse. */
.item-mod:not([aria-current="true"]):hover:not(:disabled) {
  transform: none; box-shadow: none;
  background: var(--color-surface-default);
  color: var(--color-text-primary);
}
/* ESTADO ATIVO SÓ POR ARIA, sem classe paralela. O atributo que o leitor de
   tela usa para anunciar "item atual" é o mesmo que dispara o estilo: não há
   como um ficar certo e o outro errado. */
/* ITEM ATIVO: VÉU QUE ESVANECE, não caixa com borda.
   O fundo é um gradiente da identidade que começa junto da barra e some até
   transparente na direita — o item pertence à lateral em vez de virar um
   retângulo colado sobre ela. As paradas (0 / 48 / 76 / 100%) e as opacidades
   (16 / 10,5 / 4 / 0%) são as do painel em produção; o que muda é a cor, que
   aqui vem da identidade Datapex.

   `color-mix` sobre `identity-readable` e não uma cor fixa: o token resolve
   por tema, então o véu escurece no claro e clareia no escuro sem que este
   componente precise saber em qual dos dois está.

   Um fundo branco chapado foi o que estava aqui, e desenhava justamente a
   caixa que o efeito existe para evitar. */
.item-mod[aria-current="true"] {
  color: var(--color-text-primary); font-weight: 640;
  border-color: transparent;
  border-inline-start: 3px solid var(--color-identity-readable);
  padding-inline-start: 7px;
  /* O véu é de SUPERFÍCIE, não de marca: é o mesmo branco que já separava o
     item ativo do cinza da lateral, agora esvanecendo em vez de terminar numa
     borda reta. A identidade fica só na barra de 3px — um lugar por tela é o
     que a faz significar alguma coisa. */
  background: linear-gradient(90deg,
    var(--color-surface-default) 0%,
    color-mix(in srgb, var(--color-surface-default) 66%, transparent) 48%,
    color-mix(in srgb, var(--color-surface-default) 26%, transparent) 76%,
    transparent 100%);
}
/* O hover do item atual adensa o mesmo véu, sem mudar a geometria. */
.item-mod[aria-current="true"]:hover {
  background: linear-gradient(90deg,
    var(--color-surface-default) 0%,
    var(--color-surface-default) 48%,
    color-mix(in srgb, var(--color-surface-default) 45%, transparent) 76%,
    transparent 100%);
}
/* O ícone do módulo atual acompanha a tinta do rótulo. A cor da marca fica
   reservada à barra: dois sinais coloridos no mesmo item dobrariam a presença
   da identidade sem dobrar a informação. */
.item-mod[aria-current="true"] .ic { stroke: var(--color-text-primary); }
.item-mod[disabled] { color: var(--color-action-disabled-foreground); cursor: not-allowed; }
/* Família de ícones do Brand System: grade 24×24, traço 2, pontas e junções
   arredondadas, uso preferencial em 20/24px. Estavam em 16px com traço 1,6,
   que é a anatomia do outro painel. */
.item-mod .ic {
  inline-size: 20px; block-size: 20px; flex: 0 0 auto; fill: none;
  stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round;
}
.item-mod .rotulo { overflow: hidden; text-overflow: ellipsis; }
.breve {
  margin-inline-start: auto; padding: 1px 5px; border-radius: var(--radius-tag);
  background: var(--color-surface-subtle); color: var(--color-text-muted);
  font-size: var(--tipo-caption); font-weight: var(--tipo-label-peso);
  text-transform: uppercase; letter-spacing: 0.04em;
}

.lateral__rodape {
  margin-block-start: auto; padding-block-start: var(--spacing-inline);
  display: flex; flex-direction: column; gap: 6px;
}
.lateral__rodape .botao { inline-size: 100%; justify-content: center; }
.lateral__cta .ic {
  inline-size: 20px; block-size: 20px; flex: 0 0 auto; fill: none;
  stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round;
}

/* Botão utilitário de rodapé: sem sombra e sem elevação, de propósito. Ele não
   pode competir com a ação principal logo acima. */
.btn-recolher {
  inline-size: 100%; justify-content: flex-start; gap: 9px;
  min-block-size: 34px; padding: 6px 9px; box-shadow: none;
  background: none; border-color: transparent;
  color: var(--color-text-muted); font-size: var(--tipo-caption);
}
.btn-recolher:hover:not(:disabled) {
  transform: none; box-shadow: none;
  background: var(--color-surface-default);
  color: var(--color-text-primary);
}
.btn-recolher .ic {
  inline-size: 16px; block-size: 16px; flex: 0 0 auto; fill: none;
  stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round;
  transition: transform var(--t);
}

/* ── BARRA RECOLHIDA ───────────────────────────────────────────────────
   Recolher é redefinir UMA variável. Nenhuma outra regra de layout muda,
   porque a grade inteira já consome `--lateral`. */
.app.recolhida { --lateral: 64px; }
.app.recolhida .lateral { padding-inline: 10px; }
.app.recolhida .item-mod,
.app.recolhida .lateral__rodape .botao,
.app.recolhida .btn-recolher { justify-content: center; gap: 0; padding-inline: 0; }
.app.recolhida .item-mod[aria-current="true"] {
  padding-inline-start: 0;
  /* Recolhida, o véu que esvanece precisaria de largura para acontecer e
     viraria um borrão de 60px: superfície cheia, e a barra segue sinalizando. */
  background: var(--color-surface-default);
}
/* O RÓTULO DE GRUPO NÃO SOME: VIRA SEPARADOR.
   Com `display: none` os dois rótulos levavam a própria altura junto, e todos
   os ícones subiam — o mesmo defeito que já apareceu em outras aplicações.
   `color: transparent` apaga o texto e PRESERVA a caixa, então nada se move;
   o traço no meio mantém o agrupamento legível; e o texto continua no leitor
   de tela, que é o que `display: none` também tirava. */
.app.recolhida .grupo-nav {
  position: relative; color: transparent; user-select: none;
}
.app.recolhida .grupo-nav::after {
  content: ''; position: absolute;
  inset-inline: 10px; inset-block-start: 50%;
  block-size: 1px; background: var(--color-border-default);
}
/* RECOLHIDA, O LOCKUP DÁ LUGAR AO SÍMBOLO.
   173px não cabem em 64px. Até 08/09 vivia aqui o "d" — e o registro que o
   autorizou dizia que ele valeria só até existir símbolo oficial. A
   Articulação foi aprovada em 07/09 e o pacote nomeia "sidebar recolhida"
   como caso dela, isolada e bicolor.

   O que NÃO se faz é recortar o lockup com object-fit para chegar ao mesmo
   resultado: recortar é deformar, e o guia proíbe. O símbolo entra como
   ativo próprio, com os dois paths do mestre oficial. */
.marca-simbolo { display: none; }
.app.recolhida .marca-topo { justify-content: center; padding-inline: 0; }
.app.recolhida .marca-topo img { display: none; }
.app.recolhida .marca-simbolo {
  display: block;
  /* RECOLHER NÃO AUMENTA NADA. Dentro do lockup o símbolo ocupa a altura
     inteira do conjunto — 136 de 136 unidades do viewBox. Então num lockup de
     32px ele mede 32px, e recolher a barra mantém a marca exatamente do
     tamanho em que ela já estava. O piso do pacote para o símbolo isolado é
     16px; 32 está bem acima.
     A razão precisa ser declarada: `inline-size: auto` num <svg> sem largura
     intrínseca não deduz a proporção do viewBox e o elemento sairia com 300px
     numa barra de 64. */
  block-size: 32px;
  inline-size: auto; aspect-ratio: 1 / 1;
}
.app.recolhida .breve { display: none; }
.app.recolhida .btn-recolher .ic { transform: rotate(180deg); }
/* O rótulo some da tela mas CONTINUA no leitor de tela: quem navega por voz
   perderia o nome do módulo se ele fosse removido com `display: none`. */
.app.recolhida .rotulo {
  position: absolute; inline-size: 1px; block-size: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap; border: 0;
}

/* ── topo do conteúdo ──────────────────────────────────────────────────── */
.conteudo { min-inline-size: 0; display: flex; flex-direction: column; }

.topline {
  display: flex; align-items: center; gap: var(--spacing-inline); flex-wrap: wrap;
  padding: var(--spacing-inline) var(--spacing-card);
  background: var(--color-surface-default);
  border-block-end: 1px solid var(--color-border-default);
  position: sticky; inset-block-start: 0; z-index: 30;
}
.topline__titulo { margin-inline-end: auto; display: flex; align-items: center; gap: 9px; }
.topline h2 {
  margin: 0; font-size: var(--tipo-h4); font-weight: var(--tipo-h4-peso);
  letter-spacing: -0.01em; line-height: 1.35;
}
.selo {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 2px 8px; border-radius: 999px;
  /* NEUTRO, E POR TRES MOTIVOS QUE SE SOMAM.

     1. Media: o selo sumia no tema escuro — 2,87:1 contra piso de 4,5 para
        12px. O fundo (identity-stone) e igual nos dois temas e a tinta
        (identity-readable) clareia no escuro; par instavel por construcao.

     2. Nao existe conserto com a cor da marca. Medidos: readable sobre
        subtle 3,08 no escuro, sobre elevated 3,57, sobre a superficie 4,14.
        A tinta clara da identidade nao fecha 12px sobre fundo escuro, e o
        texto nao e grande o bastante para cair no piso de 3:1.

     3. O contrato ja mandava: a identidade vive na navegacao e no ambiente,
        nao em rotulo nem em estado. Este selo e uma DECLARACAO — avisa que o
        dado e ficticio — e e justamente o que menos pode sumir.

     Neutro e que resolve por tema: 6,75:1 no claro, 7,39:1 no escuro. */
  background: var(--color-surface-subtle);
  color: var(--color-text-secondary);
  font-size: var(--tipo-caption); font-weight: 660; letter-spacing: 0.02em;
}
.selo::before {
  content: ''; inline-size: 5px; block-size: 5px; border-radius: 50%;
  background: currentColor; flex: 0 0 auto;
}

/* ── filtros ───────────────────────────────────────────────────────────── */
.filtros { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.f {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: var(--tipo-caption); color: var(--color-text-muted);
}
.f select, .f input[type="date"] {
  font: inherit; font-size: var(--tipo-tabela); color: var(--color-text-primary);
  min-block-size: 38px; padding: 4px 8px;
  background: var(--color-surface-default);
  border: 1px solid var(--color-border-default);
  border-radius: var(--radius-input);
  transition: border-color var(--t);
}
.f select:hover, .f input[type="date"]:hover { border-color: var(--color-border-strong); }
.f input[type="date"] { min-inline-size: 132px; }

/* Botão que abre a lista de seleção múltipla. Aberto muda BORDA e fundo, não
   elevação: é estado, não ação. */
.sel-btn {
  min-block-size: 38px; padding: 5px 10px; min-inline-size: 152px; max-inline-size: 220px;
  text-align: start; box-shadow: none;
  overflow: hidden; text-overflow: ellipsis; display: inline-block;
}
/* Aqui o defeito era real: com o painel aberto, passar o mouse devolvia a
   borda cinza e o botão deixava de sinalizar que estava aberto. */
.sel-btn:not([aria-expanded="true"]):hover:not(:disabled) {
  transform: none; box-shadow: none; border-color: var(--color-border-strong);
}
.sel-btn[aria-expanded="true"]:hover:not(:disabled) {
  transform: none; box-shadow: none;
  border-color: var(--color-text-primary);
}
/* Aberto é estado de controle, não identidade: muda a borda e a superfície,
   sem gastar a cor da marca. */
.sel-btn[aria-expanded="true"] {
  border-color: var(--color-border-strong);
  background: var(--color-surface-elevated);
  color: var(--color-text-primary);
}
.sel-caixa {
  position: absolute; z-index: 50; inline-size: 292px; max-block-size: 360px;
  display: flex; flex-direction: column;
  background: var(--color-surface-default);
  border: 1px solid var(--color-border-default);
  border-radius: var(--radius-medium);
  /* Popover pequeno é nível 1 na escala de elevação do Brand System. */
  box-shadow: var(--shadow-elevation1);
  padding: 8px;
}
.sel-caixa input[type="search"] {
  font: inherit; font-size: var(--tipo-tabela); min-block-size: 38px; padding: 4px 8px;
  border: 1px solid var(--color-border-default); border-radius: var(--radius-input);
  background: var(--color-surface-default); color: var(--color-text-primary);
  inline-size: 100%; margin-block-end: 6px;
}
.sel-lista { overflow-y: auto; flex: 1 1 auto; margin: 0; padding: 0; list-style: none; }
.sel-lista label {
  display: flex; align-items: center; gap: 7px;
  padding: 6px 7px; min-block-size: 32px; border-radius: var(--radius-small);
  font-size: var(--tipo-tabela); cursor: pointer;
}
.sel-lista label:hover { background: var(--color-surface-elevated); }
.sel-lista input { accent-color: var(--color-action-primary-default); inline-size: 15px; block-size: 15px; }
.sel-vazio {
  padding: var(--spacing-control); text-align: center;
  color: var(--color-text-muted); font-size: var(--tipo-caption);
}
.sel-rodape {
  display: flex; justify-content: space-between; align-items: center;
  gap: 6px; padding-block-start: 7px; margin-block-start: 5px;
  border-block-start: 1px solid var(--color-border-subtle);
  font-size: var(--tipo-caption); color: var(--color-text-muted);
}

/* ── conteúdo ──────────────────────────────────────────────────────────── */
/* FOLGA NO FIM, e ela tem função — mas não é mais a defesa principal.
   Trocar a dimensão de um cartão muda a altura dele (6 categorias dão 180px de
   gráfico, 3 dão 96). Encolher o documento abaixo da rolagem atual faz o
   navegador puxar a rolagem para caber, e a página sobe sozinha.
   Quem resolve isso agora é o JS: `redesenhar()` segura a altura do slot
   durante a troca e devolve o cartão ao lugar depois do desenho — ver o
   comentário longo em demo.js, com a medição.
   A folga daqui continua valendo pelo motivo mais simples: a última seção não
   deve terminar colada na borda inferior da janela. */
main {
  padding: var(--spacing-control) var(--spacing-card);
  /* 160px e não 46vh: a variação de altura MEDIDA de um cartão ao trocar de
     dimensão é de 84px, agora que a cardinalidade está limitada a 6. A folga
     anterior era quase cinco vezes o necessário e deixava um bloco vazio no
     fim da página. */
  padding-block-end: max(var(--spacing-region), 160px);
}
main:focus { outline: none; }
.envelope { max-inline-size: 1600px; margin-inline: auto; }

/* UMA nota por módulo, no topo — nunca uma por gráfico. O painel de referência
   tem 25 notas para 28 abas, e nenhum cartão repete esse tipo de parágrafo:
   texto explicativo espalhado transforma ferramenta em apresentação. */
.note {
  padding: 12px 16px; border-radius: var(--radius-card);
  font-size: var(--tipo-corpo); line-height: 1.5;
  color: var(--color-text-secondary);
  background: var(--color-surface-elevated);
  border: 1px solid var(--color-border-subtle);
  margin-block-end: var(--spacing-control);
}
.note b { color: var(--color-text-primary); font-weight: 640; }

.sec {
  display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap;
  margin-block: var(--spacing-card) var(--spacing-inline);
}
.sec:first-child { margin-block-start: 0; }
/* Título de seção é substantivo, nunca pergunta. */
.sec h2 {
  margin: 0; font-size: var(--tipo-h4); font-weight: var(--tipo-h4-peso);
  letter-spacing: -0.01em; line-height: 1.35;
}
/* Legenda de seção: fragmento em minúscula, sem ponto final — orientação, não frase. */
.sec .cap {
  color: var(--color-text-muted); font-size: var(--tipo-caption);
  letter-spacing: 0.01em;
}

/* ── indicador numérico ────────────────────────────────────────────────── */
.tiles {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(178px, 1fr));
  gap: 12px; margin-block-end: 16px;
}
/* QUATRO COLUNAS FIXAS NA TELA LARGA, não auto-fit.
   Com piso de 178px o auto-fit abria 7 colunas em 1290px e deixava os 2
   últimos indicadores sozinhos numa segunda fileira. Contagem fixa faz oito
   cartões virarem duas fileiras cheias de quatro, e a faixa lê como um bloco
   em vez de uma sobra. */
@media (min-width: 1180px) {
  .tiles { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}
.tile {
  position: relative; overflow: hidden;
  background: var(--color-surface-default);
  border: 1px solid var(--color-border-subtle);
  border-radius: var(--radius-card);
  padding: 14px 15px;
  /* Sem sombra: a profundidade vem de borda mais degrau de superfície. Sombra
     em todo cartão achata a hierarquia em vez de criá-la. */
  box-shadow: none;
}
/* O rótulo do indicador é o papel `label`: 13px, peso 600. Caixa alta com
   `letter-spacing` mantida porque é o que separa rótulo de valor sem gastar
   mais um degrau de tamanho. */
.tile .k {
  font-size: var(--tipo-label); color: var(--color-text-muted);
  text-transform: uppercase; letter-spacing: 0.05em;
  font-weight: var(--tipo-label-peso); line-height: 1.4;
}
/* O número é o herói: quem responde à pergunta é ele, não o rótulo. */
/* kpiMedium: 28px, peso 500, tracking -0.02em, altura de linha 1,2. O peso
   660 que estava aqui vinha do outro painel e engrossava o número muito além
   do que a escala da marca pede. */
.tile .v {
  font-size: var(--tipo-kpi); font-weight: var(--tipo-kpi-peso);
  letter-spacing: -0.02em; line-height: 1.2;
  margin-block-start: 4px;
}
.tile .d {
  font-size: var(--tipo-caption); letter-spacing: 0.01em; line-height: 1.45;
  color: var(--color-text-secondary); margin-block-start: 5px;
}

/* Faixa de papel no topo do cartão. Restrita a poucos papéis de propósito:
   quando todo cartão recebe faixa, a cor deixa de significar. */
.tile::after {
  content: ''; position: absolute; inset-inline: 0; inset-block-start: 0; block-size: 2px;
  background: linear-gradient(90deg, var(--papel, transparent), transparent 72%);
  opacity: 0.7;
}
/* A faixa de papel comunica ESTADO, e só. O papel "resultado", que usava a
   cor da marca no indicador de receita, saiu: receita não é um estado, é o
   número principal — e ele já se destaca por ser o primeiro e o maior. */
.tile[data-papel="meta-ok"]    { --papel: var(--color-chart-positive); }
.tile[data-papel="meta-baixo"] { --papel: var(--color-chart-negative); }
.tile[data-papel="atencao"]    { --papel: var(--color-semantic-warning-foreground); }
.tile[data-papel="neutro"]     { --papel: var(--color-chart-neutral); }

/* Variação: seta além da cor, porque cor sozinha não chega a quem não
   distingue as duas tintas. */
.comp { display: inline-flex; align-items: center; gap: 3px; font-weight: 640; }
.comp--sobe { color: var(--color-chart-positive); }
.comp--desce { color: var(--color-chart-negative); }
.comp--neutro { color: var(--color-text-muted); }

/* ── cartão ────────────────────────────────────────────────────────────── */
.card {
  background: var(--color-surface-default);
  border: 1px solid var(--color-border-subtle);
  /* Card tem 8px no Brand System; 12px é raio de modal. */
  border-radius: var(--radius-card);
  margin-block-end: 16px; overflow: hidden; box-shadow: none;
  min-inline-size: 0;
}
.card > header {
  padding: 11px 17px; border-block-end: 1px solid var(--color-border-subtle);
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  background: linear-gradient(180deg, var(--color-surface-elevated), transparent);
}
/* Título de cartão pelo papel `h4`: 20px seria a escala institucional, e a
   prancha diz que "a operação tem mais densidade" — aqui ele fica no degrau
   de `label` em peso e no de corpo em tamanho, que é o que a tela operacional
   do próprio Brand System mostra. */
.card > header h3 {
  margin: 0; font-size: var(--tipo-corpo); font-weight: var(--tipo-label-peso);
  letter-spacing: -0.008em; line-height: 1.4;
}
/* Apoio do cartão é UMA frase curta ao lado do título, dentro do cabeçalho —
   nunca um parágrafo abaixo do gráfico. */
.card > header .hint {
  font-size: var(--tipo-caption); letter-spacing: 0.01em;
  color: var(--color-text-muted);
}
.card > header .controles { margin-inline-start: auto; display: flex; gap: 12px; flex-wrap: wrap; align-items: flex-end; }
/* Seletor no cabeçalho do cartão: mesma anatomia do filtro do topo, para o
   visitante reconhecer o controle em vez de aprender um segundo padrão. */
.f--troca { flex-direction: column; align-items: flex-start; gap: 3px; }
.f--troca select { min-block-size: 38px; font-size: var(--tipo-tabela); }
.card .body { padding: 14px 17px 16px; min-inline-size: 0; }
.card .rodape-card {
  padding: 0 17px 12px; display: flex; justify-content: space-between;
  align-items: center; gap: 10px; flex-wrap: wrap;
}

/* ── slot ───────────────────────────────────────────────────────────────
   A caixa que demo.js reconstrói quando se troca a dimensão de UM cartão.

   O flow-root não é enfeite: sem ele a margem inferior do cartão ESCAPA do
   slot (colapso de margem), e o slot mede 16px a menos do que ocupa. Durante a
   troca, demo.js segura a altura do slot para o documento não encolher — e
   segurar uma altura reativa o contêiner da margem, fazendo o documento perder
   justamente esses 16px e a rolagem saltar. Contendo a margem sempre, o slot
   mede o que ocupa nos dois momentos, e o piso de altura vale de verdade.

   O espaçamento entre cartões não muda: os mesmos 16px, agora por dentro. */
.slot { display: flow-root; min-inline-size: 0; }

/* ── par de cartões ─────────────────────────────────────────────────────
   Duas leituras do mesmo recorte, lado a lado. Uma coluna só abaixo de
   1120px: em meia tela estreita o ranking perderia curso de barra sem ganhar
   comparação nenhuma — empilhado, cada gráfico volta à largura inteira.

   `align-items: start` e NÃO o esticar padrão do grid: os dois cartões mudam
   de altura por conta própria (6 categorias dão 180px de gráfico, 3 dão 96), e
   um deles pode estar em modo tabela. Esticado, o mais baixo ganharia um vazio
   do tamanho da diferença. Terminar em alturas diferentes é honesto; cartão
   com buraco no fim, não. A metade que o pedido trata é a de LARGURA. */
.dupla {
  display: grid; gap: 16px; grid-template-columns: minmax(0, 1fr);
  align-items: start;
  /* O respiro acima do par. Não dá para deixar com o `.sec` de dentro: lá ele
     é o primeiro filho da coluna e `.sec:first-child` zera a margem de topo. */
  margin-block-start: var(--spacing-card);
}
/* `minmax(0, …)` nas colunas do grid e `min-inline-size: 0` aqui: sem os dois,
   um conteúdo largo (a tabela do cartão) empurraria a coluna e estouraria o
   par em vez de rolar por dentro. */
.dupla__col { min-inline-size: 0; }
/* O `.sec` de dentro da coluna já recebeu o respiro pelo `.dupla`. Explícito
   em vez de depender do `:first-child`, que some se algo entrar antes dele. */
.dupla__col > .sec { margin-block-start: 0; }
/* A margem do cartão SOMARIA ao gap do grid e daria 32px embaixo do par. Quem
   separa as colunas é o gap; quem separa o par do que vem depois é a margem da
   próxima seção. */
.dupla__col > .slot > .card { margin-block-end: 0; }
@media (min-width: 1120px) {
  .dupla { grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr); }
  .dupla--igual { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
}

/* ── troca de métrica e dimensão ───────────────────────────────────────── */
.trocador { display: flex; flex-direction: column; gap: 3px; }
.trocador__rot {
  font-size: var(--tipo-caption); font-weight: var(--tipo-label-peso);
  letter-spacing: 0.04em; text-transform: uppercase;
  color: var(--color-text-muted);
}
.chips { display: flex; flex-wrap: wrap; gap: 4px; }
.chips button {
  position: relative;
  padding: 4px 11px; min-block-size: 30px; font-size: var(--tipo-caption); font-weight: 520;
  border-radius: 999px; box-shadow: none;
  background: var(--color-surface-default);
  border-color: var(--color-border-default);
  color: var(--color-text-secondary);
}
/* Area de toque ate 44px sem engordar o chip: 30 de desenho mais 7 de
   folga invisivel de cada lado. A mesma tecnica da lupa da tabela. */
.chips button::before { content: ''; position: absolute; inset: -7px; }
/* O HOVER NÃO PODE ALCANÇAR A PÍLULA SELECIONADA.
   `.chips button:hover:not(:disabled)` tem especificidade 0,3,1 e
   `.chips button[aria-pressed="true"]` tem 0,2,1. O hover vencia e devolvia
   a tinta escura sobre o preenchimento escuro do estado selecionado: passar o
   mouse na métrica ativa apagava o rótulo dela, contraste 1,00.

   É a MESMA classe de defeito que já tinha custado um CTA invisível no site.
   A correção não é aumentar a especificidade do estado — é excluir o estado
   do alcance do hover, para as duas regras deixarem de disputar e nenhuma
   ordem futura reabrir isso. */
.chips button:not([aria-pressed="true"]):hover:not(:disabled) {
  transform: none; box-shadow: none;
  border-color: var(--color-border-strong); color: var(--color-text-primary);
}
/* Selecionado preenche por inteiro em NEUTRO. O chip responde "o que eu
   escolhi ver", que é ação, não identidade — e a marca fica reservada para
   dizer onde a pessoa está. Medido: 15,71:1. */
.chips button[aria-pressed="true"] {
  background: var(--color-action-primary-default);
  border-color: var(--color-action-primary-default);
  color: var(--color-action-primary-foreground);
  font-weight: 640; box-shadow: none;
}
/* Hover PRÓPRIO do estado selecionado, senão a regra genérica de hover devolve
   a tinta escura sobre o preenchimento escuro e apaga o rótulo. */
.chips button[aria-pressed="true"]:hover:not(:disabled) {
  transform: none; box-shadow: none;
  background: var(--color-action-primary-hover);
  border-color: var(--color-action-primary-hover);
  color: var(--color-action-primary-foreground);
}

/* ── gráfico ───────────────────────────────────────────────────────────── */
/* Rolagem interna quando o gráfico precisa de mais largura do que a tela tem.
   O contrato analítico exige 480px mínimo em eixos para os rótulos caberem:
   espremer o gráfico até caber destrói justamente o que ele deveria mostrar. */
.gr-caixa { overflow-x: auto; }
.gr { display: block; }
.gr__grade { stroke: var(--color-chart-grid); stroke-width: 1; opacity: 0.55; }
.gr__zero { stroke: var(--color-chart-grid); stroke-width: 1.5; }
/* A cor da série vem do PAPEL da medida e é aplicada na própria marca pelo
   motor. Aqui ficam só os papéis que não dependem da medida escolhida. */
.gr__meta {
  fill: none; stroke: var(--color-chart-target); stroke-width: 1.5;
  stroke-dasharray: 5 4; opacity: 0.8;
}
.gr__ponto { stroke: var(--color-surface-default); stroke-width: 1.5; }
.gr__faixa { fill: var(--color-chart-negative); opacity: 0.06; }
.gr__eixo { fill: var(--color-chart-label); font-size: var(--tipo-caption); font-weight: 500; }
.gr__cat { fill: var(--color-chart-label); font-size: var(--tipo-caption); font-weight: 500; }
/* Texto do gráfico usa tinta de texto, nunca a cor da série: a cor escolhida
   para funcionar como área reprova como letra. */
.gr__valor { fill: var(--color-text-primary); font-size: var(--tipo-caption); font-weight: 640; }
.gr__nota { fill: var(--color-chart-negative); font-size: var(--tipo-caption); font-weight: 640; }
.gr__marca { transition: opacity var(--t); }
.gr__barra:hover .gr__marca { opacity: 0.82; }

.legenda {
  display: flex; flex-wrap: wrap; gap: 14px; align-items: center;
  margin-block-start: 10px; font-size: var(--tipo-caption); color: var(--color-text-secondary);
}
.legenda__item { display: inline-flex; align-items: center; gap: 6px; }
.legenda__marca { inline-size: 10px; block-size: 10px; border-radius: 2px; flex: 0 0 auto; }
.legenda__marca--meta {
  block-size: 3px; inline-size: 14px; border-radius: 2px;
  background: repeating-linear-gradient(90deg,
    var(--color-chart-target) 0 5px, transparent 5px 9px);
}
/* O papel da medida, escrito. É o que garante a leitura para quem não
   distingue as famílias de cor: medido com validador de paleta, o teal de
   "entra" e o vinho de "sai" ficam a ΔE 4,9 em protanopia, abaixo do piso de
   separação. A cor é atalho; o texto é a garantia. */
.legenda__papel { color: var(--color-text-muted); }

/* ── trilha de detalhe ──────────────────────────────────────────────────
   Diz por onde se desceu e devolve o caminho de volta. Sem ela, quem clicou
   duas vezes fica olhando 31 barras sem saber de que mês são. */
.trilha-linha {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  padding: 9px 17px; border-block-end: 1px solid var(--color-border-subtle);
  background: var(--color-surface-elevated);
}
.trilha { display: flex; align-items: center; gap: 5px; flex-wrap: wrap; min-inline-size: 0; }
.trilha__no {
  padding: 2px 7px; min-block-size: 26px; box-shadow: none;
  font-size: var(--tipo-caption); font-weight: 500;
  background: none; border-color: transparent;
  color: var(--color-text-secondary);
  text-decoration: underline; text-underline-offset: 3px;
  text-decoration-color: var(--color-border-default);
}
.trilha__no:hover:not(:disabled) {
  transform: none; box-shadow: none;
  background: var(--color-surface-default);
  text-decoration-color: currentColor;
}
.trilha__sep { color: var(--color-text-muted); font-size: var(--tipo-caption); }
/* O degrau atual não é botão: clicar nele não levaria a lugar nenhum. */
.trilha__atual {
  font-size: var(--tipo-caption); font-weight: 640; color: var(--color-text-primary);
  padding: 2px 7px;
}
.trilha__subir {
  min-block-size: 28px; min-inline-size: 28px; padding: 0 8px;
  justify-content: center; font-size: var(--tipo-label); box-shadow: none;
}
.trilha__subir:hover:not(:disabled) { transform: none; box-shadow: none;
  background: var(--color-surface-default); }

/* ── ponto que aceita detalhamento ──────────────────────────────────────
   A área sensível é a fatia inteira do passo, não a barra desenhada: num mês
   de valor baixo a barra tem poucos pixels de altura, e exigir acerto nela
   transformaria o detalhamento em teste de pontaria. */
.gr__alvo { fill: transparent; cursor: pointer; }
.gr__barra--clicavel:hover .gr__marca { opacity: 0.78; }
.gr__alvo:hover { fill: var(--color-text-primary); fill-opacity: 0.04; }
/* Foco de teclado precisa aparecer sobre o gráfico: `outline` em SVG é
   irregular entre navegadores, então o próprio retângulo ganha traço. */
/* Foco é "onde o teclado está" — parente de "onde eu estou", então usa a
   identidade, que resolve por tema. */
.gr__alvo:focus-visible {
  outline: none;
  fill: var(--color-text-primary); fill-opacity: 0.06;
  stroke: var(--color-identity-readable); stroke-width: 2;
}

/* Linha de tabela que abre detalhe. Precisa parecer clicável sem virar um
   botão dentro da célula. */
.tab tbody tr.clicavel { cursor: pointer; }
.tab tbody tr.clicavel:hover { background: var(--color-surface-elevated); }

/* Coluna de ação: estreita, encostada na direita, sem competir com o dado. */
.tab .tab__acao { inline-size: 1%; white-space: nowrap; padding-inline: 8px; text-align: end; }
.tab__lupa {
  position: relative;
  min-block-size: 28px; min-inline-size: 28px; padding: 3px 7px;
  justify-content: center; box-shadow: none;
  background: none; border-color: transparent;
  color: var(--color-text-muted);
}
/* ALVO DE 44px SEM ENGORDAR O BOTÃO.
   O contrato pede 44px de área clicável; um botão de 44px em cada linha
   engrossaria a tabela inteira e brigaria com a densidade de operação. A área
   sensível cresce por um pseudo-elemento invisível, e o desenho continua com
   28px. Medido: com -8px a área saía com 42px de altura, 2px abaixo do piso;
   -9px fecha 46. O número vem da medição, não da conta de cabeça. */
.tab__lupa::before {
  content: ''; position: absolute; inset: -9px;
}
.tab__lupa svg {
  inline-size: 15px; block-size: 15px; fill: none;
  stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round;
}
/* A lupa fica discreta até a linha ser percorrida — a affordance aparece
   quando é útil, sem transformar a tabela numa grade de botões. */
.tab__lupa:hover:not(:disabled) {
  transform: none; box-shadow: none;
  background: var(--color-surface-default);
  border-color: var(--color-border-default);
  color: var(--color-text-primary);
}
.tab tbody tr:hover .tab__lupa { color: var(--color-text-primary); }

/* ── gaveta de detalhamento ─────────────────────────────────────────────
   Abre pela lateral em vez de trocar de tela: o visitante continua vendo de
   onde veio, e fechar devolve o contexto inteiro sem recarregar nada. */
.gaveta-fundo {
  position: fixed; inset: 0; z-index: 70;
  background: var(--color-brand-carbon); opacity: 0.32;
}
.gaveta {
  position: fixed; inset-block: 0; inset-inline-end: 0; z-index: 71;
  /* 680 e não 560: a tabela de composição tem quatro colunas e ficava
     apertada, e numa tela de 1440 isto ainda deixa metade da página visível
     atrás, que é o motivo de a gaveta existir em vez de uma tela nova. */
  inline-size: min(680px, 100%);
  display: flex; flex-direction: column;
  background: var(--color-surface-default);
  border-inline-start: 1px solid var(--color-border-default);
  /* Gaveta é nível 2: "1 popover pequeno · 2 menu/drawer · 3 modal". */
  box-shadow: var(--shadow-elevation2);
}
.gaveta__topo {
  display: flex; align-items: flex-start; gap: 12px;
  padding: 14px 18px; border-block-end: 1px solid var(--color-border-subtle);
  background: linear-gradient(180deg, var(--color-surface-elevated), transparent);
}
.gaveta__olho {
  font-size: var(--tipo-caption); font-weight: var(--tipo-label-peso);
  text-transform: uppercase; letter-spacing: 0.05em;
  color: var(--color-text-muted);
}
.gaveta__titulo {
  margin: 3px 0 0; font-size: var(--tipo-h4); font-weight: var(--tipo-h4-peso);
  letter-spacing: -0.01em; line-height: 1.35;
}
.gaveta__fechar { margin-inline-start: auto; min-inline-size: 34px; justify-content: center; }
.gaveta__corpo { overflow-y: auto; padding: 16px 18px 24px; flex: 1 1 auto; }
.gaveta__corpo .tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 9px; }
.gaveta__corpo .tile { padding: 11px 12px; }
.gaveta__corpo .tile .v { font-size: var(--tipo-kpi); }
.gaveta__bloco { margin-block-start: 18px; }
.gaveta__bloco h4 {
  margin: 0 0 9px; font-size: var(--tipo-label); font-weight: var(--tipo-label-peso);
  text-transform: uppercase; letter-spacing: 0.055em; color: var(--color-text-muted);
}

@media (max-width: 640px) {
  /* Em tela estreita a gaveta ocupa quase tudo e sobe de baixo: 560px de
     largura numa tela de 375 seria a tela inteira com uma borda inútil. */
  .gaveta {
    inset-block-start: auto; inset-inline: 0; inline-size: 100%;
    max-block-size: 88vh;
    border-inline-start: none;
    border-block-start: 1px solid var(--color-border-default);
    border-start-start-radius: var(--radius-large);
    border-start-end-radius: var(--radius-large);
  }
  .gaveta__corpo .tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* ── tabela ────────────────────────────────────────────────────────────── */
/* Rolagem DENTRO do cartão, com cabeçalho fixo. Tabela longa se resolve com
   rolagem interna, não com paginação numerada. */
.tw { overflow: auto; max-block-size: 62vh; }
.tab {
  inline-size: 100%; border-collapse: collapse;
  font-size: var(--tipo-tabela); line-height: 1.4;
}
.tab thead th {
  position: sticky; inset-block-start: 0; z-index: 2;
  background: var(--color-surface-elevated);
  font-size: var(--tipo-label); font-weight: var(--tipo-label-peso);
  letter-spacing: 0.01em; color: var(--color-text-secondary);
  border-block-end: 1px solid var(--color-border-default);
}
.tab th, .tab td {
  padding: 7px 12px; text-align: start;
  border-block-end: 1px solid var(--color-border-subtle);
  white-space: nowrap;
}
.tab tbody th { font-weight: 500; }
.tab tbody tr:last-child th, .tab tbody tr:last-child td { border-block-end: 0; }
.tab__num { text-align: end; }
/* Cabeçalho ordenável: botão de verdade, para o teclado alcançar e o leitor de
   tela anunciar. A seta mostra a direção sem depender só de cor. */
.tab thead th { position: sticky; }
.tab__ordenar {
  all: unset; cursor: pointer; display: inline-flex; align-items: center; gap: 4px;
  font: inherit; color: inherit; min-block-size: 28px; padding: 0 2px;
  border-radius: var(--radius-small);
}
.tab__ordenar:hover { color: var(--color-text-primary); }
.tab__ordenar:focus-visible { outline: 2px solid currentColor; outline-offset: 2px; }
.tab__num .tab__ordenar { flex-direction: row-reverse; }
.tab__seta { font-size: var(--tipo-caption); line-height: 1; }
/* A posição do critério só aparece quando há mais de um: com um só ela diria
   "primeiro de um", que é ruído. */
.tab__pos {
  font-size: 9px; font-weight: 700; line-height: 1;
  /* Neutro, não identidade: a posição do critério diz "o que eu escolhi",
     que é a família do controle. A marca fica reservada para "onde eu estou". */
  color: var(--color-text-primary);
}

/* Alça de ajuste na borda direita do cabeçalho: área de 10px para pegar com
   folga, traço visível só quando a pessoa se aproxima ou arrasta. */
.tab thead th { position: sticky; padding-inline-end: 16px; }
.tab__grip {
  position: absolute; inset-block: 0; inset-inline-end: 0;
  inline-size: 10px; cursor: col-resize; z-index: 3;
}
.tab__grip::after {
  content: ''; position: absolute; inset-block: 6px; inset-inline-end: 4px;
  inline-size: 1px; background: var(--color-border-default);
}
.tab thead th:hover .tab__grip::after,
.tab__grip--ativo::after {
  inset-block: 0; inline-size: 2px;
  background: var(--color-text-primary);
}
/* Coluna ajustada à mão QUEBRA o texto; nada some por reticências. Cortar
   justamente o que a pessoa estreitou a coluna para ver ao lado seria o
   contrário do que ela pediu. */
.tab--fixa { table-layout: fixed; }
.tab--fixa th, .tab--fixa td { white-space: normal; overflow-wrap: anywhere; }
.tab tbody tr:hover { background: var(--color-surface-elevated); }

.vazio {
  padding: var(--spacing-section) var(--spacing-control);
  text-align: center; color: var(--color-text-muted);
}

/* ── telas estreitas ───────────────────────────────────────────────────── */
@media (max-width: 900px) {
  /* A lateral não vira gaveta: gira e vira uma trilha horizontal rolável. Uma
     gaveta esconde a navegação atrás de um toque; a trilha mantém os módulos
     visíveis, que é o que uma demonstração precisa. */
  .app { grid-template-columns: 1fr; }
  .lateral {
    position: sticky; inset-block-start: 0; block-size: auto; z-index: 40;
    flex-direction: row; align-items: center; gap: 4px; padding: 8px 10px;
    overflow-x: auto; scrollbar-width: none;
    border-inline-end: none; border-block-end: 1px solid var(--color-border-default);
  }
  .lateral::-webkit-scrollbar { display: none; }
  .grupo-nav, .lateral__rodape { display: none; }
  /* Em tela estreita a lateral já é uma trilha horizontal: recolher não tem
     o que recolher, e o botão sairia oferecendo uma ação sem efeito. */
  .app.recolhida { --lateral: 1fr; }
  .app.recolhida .rotulo {
    position: static; inline-size: auto; block-size: auto;
    margin: 0; clip-path: none;
  }
  /* Na trilha horizontal o respiro à direita é o que separa a marca do
     primeiro módulo; o vertical vem do padding da própria trilha. */
  .marca-topo { padding: 0 12px 0 0; flex: 0 0 auto; }
  .item-mod { inline-size: auto; flex: 0 0 auto; }
  /* Na trilha horizontal o item é curto e a barra fica embaixo: um gradiente
     que some para a direita não teria distância para acontecer. Véu uniforme. */
  .item-mod[aria-current="true"] {
    border-inline-start: 1px solid transparent;
    padding-inline-start: 9px;
    border-block-end: 2px solid var(--color-identity-readable);
    background: var(--color-surface-default);
  }
  .topline { position: static; padding: var(--spacing-inline) var(--spacing-control); }
  .topline__titulo { inline-size: 100%; }
  /* Trilha única de filtros com máscara na borda, sinalizando que há mais
     controle fora da tela.

     O `#000` abaixo é o ÚNICO hexadecimal do arquivo, e não é cor: numa
     máscara o preto significa "totalmente opaco". Não existe token para isso
     porque não é uma decisão de marca — é a escrita idiomática de uma
     máscara, e trocar por um token de cor mudaria o significado. */
  .filtros {
    inline-size: 100%; flex-wrap: nowrap; overflow-x: auto; padding-block-end: 6px;
    scrollbar-width: none;
    -webkit-mask-image: linear-gradient(90deg, #000 92%, transparent);
            mask-image: linear-gradient(90deg, #000 92%, transparent);
  }
  .filtros::-webkit-scrollbar { display: none; }
  .f { flex: 0 0 auto; }
  /* 16px evita o zoom automático do iOS ao focar o campo. */
  /* 16px não é um papel da escala: é o piso abaixo do qual o iOS dá zoom
     sozinho ao focar o campo, jogando o layout para fora da tela. É prevenção
     de comportamento do navegador, não decisão tipográfica. */
  .f select, .f input[type="date"], .sel-caixa input[type="search"] { font-size: 16px; }
  main { padding: var(--spacing-control); padding-block-end: max(var(--spacing-section), 140px); }
  .tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 9px; }
  .tile { padding: 12px; }
  /* kpiMedium não tem degrau menor no mobile: a escala declara 28px nos dois.
     Quem aperta é o padding do cartão, não o número. */
  .tile { padding: 11px 10px; }
  .card { border-radius: var(--radius-medium); }
  .card > header { padding: 10px 13px; gap: 8px; }
  .card > header .controles { margin-inline-start: 0; inline-size: 100%; }
  .card .body { padding: 12px; }
  .card .rodape-card { padding: 0 13px 10px; }
  .tw { max-block-size: 52vh; }
}

@media (max-width: 420px) {
  .tile { padding: 10px 9px; }
  .tiles { gap: 8px; }
}

@media (min-width: 1600px) {
  /* kpiLarge nas telas que comportam: 40px, mesmo peso 500. */
  .tile .v { font-size: var(--tipo-kpi-grande); letter-spacing: -0.03em; }
}

/* Regra única e global, em vez de uma versão sem transição por componente. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    transition-duration: 0.001ms !important;
  }
}

/* ══════════════════════════ BANCADA DO ANALYTICS ═════════════════════════
   O construtor de perguntas: catálogo de medidas em cima, fila de colunas
   embaixo. Duas faixas, e a ordem entre elas é a ordem do gesto — primeiro
   escolher, depois arrumar.

   Nenhuma cor de identidade aqui. A marca assina a tela e marca o módulo
   ativo; ela não pinta controle de dado. As únicas cores destes blocos são as
   do próprio catálogo de medidas, e cada uma vem de M.corDe() — a mesma que a
   série usa no gráfico, o que faz a pílula e a barra falarem a mesma língua
   sem legenda extra. */
.bancada__controles {
  display: flex; flex-wrap: wrap; align-items: flex-end;
  gap: var(--spacing-control);
  margin-block-end: var(--spacing-card);
}

.catalogo {
  display: flex; flex-wrap: wrap; gap: var(--spacing-card);
  padding-block-end: var(--spacing-control);
  border-block-end: 1px solid var(--color-border-subtle);
}
.grupo-med { display: flex; flex-direction: column; gap: var(--spacing-micro); }
.grupo-med__rot {
  font-size: var(--tipo-caption); font-weight: var(--tipo-label-peso);
  text-transform: uppercase; letter-spacing: 0.06em;
  color: var(--color-text-muted);
}
.grupo-med__pills { display: flex; flex-wrap: wrap; gap: var(--spacing-micro); }

/* A pílula de medida. Alvo de 44px sem engordar o desenho, pelo mesmo
   pseudo-elemento que a lupa da tabela usa — e pelo mesmo motivo: três faixas
   de botões de 44px empurrariam a resposta para fora da primeira tela. */
.pilula-med {
  position: relative;
  display: inline-flex; align-items: center; gap: var(--spacing-micro);
  min-block-size: 32px; padding: 4px 10px;
  border: 1px solid var(--color-border-default);
  border-radius: var(--radius-tag);
  background: var(--color-surface-default);
  color: var(--color-text-secondary);
  font-size: var(--tipo-caption);
}
.pilula-med::before { content: ''; position: absolute; inset: -6px; }
.pilula-med__marca {
  inline-size: 10px; block-size: 10px; border-radius: 2px; flex: none;
}
.pilula-med__pos {
  font-size: 10px; font-weight: var(--tipo-label-peso);
  color: var(--color-text-muted);
}
.pilula-med[aria-pressed='true'] {
  border-color: var(--color-border-strong);
  background: var(--color-action-selected);
  color: var(--color-text-primary);
}
/* Cheio não desaparece: continua focável e clicável, e explica ao ser
   acionado. Sumir com a opção esconderia a regra em vez de ensiná-la. */
.pilula-med[aria-disabled='true'] { opacity: 0.5; }

/* A fila: uma ficha por coluna escolhida, na ordem em que ela sai na tabela.
   As setas ficam SEMPRE visíveis — nunca reveladas por passar o mouse. Um
   controle que só aparece no hover não existe para quem usa teclado nem para
   quem está no toque. */
.fila {
  display: flex; flex-wrap: wrap; gap: var(--spacing-inline);
  margin-block-start: var(--spacing-control);
}
.fila--vazia { align-items: center; gap: var(--spacing-control); }
.fila--vazia .vazio { margin: 0; }
.ficha {
  display: inline-flex; align-items: center; gap: var(--spacing-micro);
  padding: 4px 6px 4px 10px;
  border: 1px solid var(--color-border-default);
  border-radius: var(--radius-tag);
  background: var(--color-surface-elevated);
  font-size: var(--tipo-caption);
}
.ficha__pos {
  font-weight: var(--tipo-label-peso); color: var(--color-text-muted);
  min-inline-size: 12px;
}
.ficha__marca { inline-size: 10px; block-size: 10px; border-radius: 2px; flex: none; }
.ficha__nome { color: var(--color-text-primary); font-weight: var(--tipo-label-peso); }
/* O selo diz um FATO de código, não um enfeite: a primeira medida é a que o
   gráfico desenha e a que ordena as linhas. Sem esta frase, mover uma coluna
   reorganiza a tabela inteira sem causa aparente. */
.ficha__selo {
  font-size: 10px; color: var(--color-text-muted);
  padding-inline-start: var(--spacing-micro);
  border-inline-start: 1px solid var(--color-border-default);
}
.ficha__seta, .ficha__tirar {
  position: relative;
  min-block-size: 26px; min-inline-size: 26px; padding: 0 4px;
  justify-content: center; box-shadow: none;
  background: none; border-color: transparent;
  color: var(--color-text-muted);
  font-size: var(--tipo-caption);
}
/* Área de 44px por pseudo-elemento, como a lupa. Com -9px em botão de 26px a
   área fecha 44. */
.ficha__seta::before, .ficha__tirar::before {
  content: ''; position: absolute; inset: -9px;
}
.ficha__seta:hover:not(:disabled), .ficha__tirar:hover:not(:disabled) {
  transform: none; box-shadow: none;
  background: var(--color-action-selected); color: var(--color-text-primary);
}
.ficha__seta:disabled { opacity: 0.35; }

/* A bancada é controle, não resultado: fica um degrau abaixo do cartão que
   responde, para o olho descer do que se monta para o que se lê. */
.card--bancada { background: var(--color-surface-elevated); }

/* ══════════════════════ ANALYTICS — construtor de visões ══════════════════
   O gesto é o do painel em produção: lista de visões, "+ nova visão", e um
   editor onde se escolhe o VISUAL primeiro, numa grade agrupada em blocos, e
   só então os campos daquele visual.

   Nenhuma cor de identidade aqui. A marca assina a tela e marca o módulo
   ativo; ela não pinta controle de dado. As únicas cores destes blocos são as
   do catálogo de medidas, e cada uma vem de M.corDe() — a mesma que a série
   usa no gráfico, o que faz a pílula e a barra falarem a mesma língua. */

.an-visao {
  display: flex; flex-direction: column; align-items: flex-start; gap: 2px;
  min-block-size: 44px; padding: var(--spacing-compact) var(--spacing-control);
  border: 1px solid var(--color-border-default);
  border-radius: var(--radius-medium);
  background: var(--color-surface-default);
  text-align: start;
}
.an-visao[aria-current='true'] {
  border-color: var(--color-border-strong);
  background: var(--color-action-selected);
}
.an-visao__nome { font-weight: var(--tipo-label-peso); color: var(--color-text-primary); }
.an-visao__n { font-size: var(--tipo-caption); color: var(--color-text-muted); }

.an-nome {
  min-block-size: 38px; min-inline-size: 220px;
  padding: 4px var(--spacing-compact);
  border: 1px solid var(--color-border-default);
  border-radius: var(--radius-input);
  background: var(--color-surface-default); color: var(--color-text-primary);
}

/* ÁREA DE ACRESCENTAR, não botãozinho de canto: com um elemento alto na tela,
   um botão no rodapé fica longe do olho e do cursor. Faixa de largura inteira,
   sempre no caminho de quem acabou de montar o elemento de cima. */
.an-add-zona {
  display: flex; justify-content: center;
  margin-block-start: var(--spacing-card);
  padding: var(--spacing-control);
  border: 1px dashed var(--color-border-strong);
  border-radius: var(--radius-medium);
}

/* A grade diz o que ela É antes de listar as opções: três blocos de ícones sem
   título viram um enigma. */
.an-grade {
  margin-block-start: var(--spacing-control);
  padding: var(--spacing-control);
  border: 1px solid var(--color-border-default);
  border-radius: var(--radius-medium);
  background: var(--color-surface-elevated);
}
.an-grade__cab {
  margin: 0 0 var(--spacing-compact);
  font-size: var(--tipo-caption); color: var(--color-text-secondary);
}
.an-grade__blocos {
  display: flex; flex-direction: column; gap: var(--spacing-compact);
}
.an-bloco__icones { display: flex; flex-wrap: wrap; gap: var(--spacing-micro); }
.an-bloco { display: flex; flex-direction: column; gap: var(--spacing-micro); }
.an-bloco__rot {
  font-size: var(--tipo-caption); font-weight: var(--tipo-label-peso);
  text-transform: uppercase; letter-spacing: 0.06em;
  color: var(--color-text-muted);
}
.an-bloco__icones { display: flex; flex-wrap: wrap; gap: var(--spacing-micro); }
.an-icone {
  /* Vence o nowrap da regra base de botao. Sem isto o rotulo nao quebra e
     atropela o tile vizinho, por mais estreito que o tile seja. */
  white-space: normal;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  /* 92px, e nao 66: "Concentracao" tem 82px na Inter e nao cabia em 58px de
     area util. Como o rotulo leva `overflow-wrap: anywhere` — que existe para
     vencer o `nowrap` da regra base de botao —, a palavra era partida em
     QUALQUER letra, e o tile mostrava "Concentr / acao". `anywhere` vence a
     hifenizacao, e o Chrome nao tem os padroes de pt-BR aqui, entao nao ha
     como pedir a quebra correta: a saida e o tile caber a palavra.

     "Numero com lista" continua em duas linhas, e esta certo — quebra no
     espaco, que e onde a lingua permite. Em 320px os tiles passam de tres
     para dois por linha, sem estouro e sem rolagem lateral (medido). */
  gap: var(--spacing-micro); inline-size: 92px; min-block-size: 78px;
  padding: var(--spacing-compact) 4px;
  border: 1px solid var(--color-border-default);
  border-radius: var(--radius-medium);
  background: var(--color-surface-default);
}
.an-icone[aria-pressed='true'] {
  border-color: var(--color-border-strong);
  background: var(--color-action-selected);
}
.an-icone__desenho { font-size: 18px; line-height: 1; color: var(--color-text-secondary); }
.an-icone__rot {
  inline-size: 100%; min-inline-size: 0;
  font-size: var(--tipo-caption); color: var(--color-text-secondary);
  text-align: center; line-height: 1.25; overflow-wrap: anywhere; hyphens: auto;
}

/* Um elemento da visão. Metade e inteira dividem a mesma faixa, e o `min-width`
   é o que impede a coluna de meia largura de espremer a tabela dentro dela. */
.an-editor > div { display: flex; flex-wrap: wrap; gap: var(--spacing-card); }
.an-el { min-inline-size: 0; }
.an-el--inteira { flex: 1 1 100%; }
.an-el--meia { flex: 1 1 340px; }
.an-el__barra {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--spacing-micro);
  margin-block-end: var(--spacing-compact);
}
.an-el__pos {
  font-weight: var(--tipo-label-peso); color: var(--color-text-muted);
  min-inline-size: 14px;
}
.an-el__tipo {
  font-size: var(--tipo-caption); font-weight: var(--tipo-label-peso);
  text-transform: uppercase; letter-spacing: 0.06em;
  color: var(--color-text-secondary);
}
.an-el__seta, .an-el__acao {
  position: relative;
  min-block-size: 28px; padding: 2px var(--spacing-inline);
  box-shadow: none; background: none;
  border-color: var(--color-border-default);
  color: var(--color-text-secondary);
  font-size: var(--tipo-caption);
}
/* Área de 44px sem engordar o botão, pelo mesmo pseudo-elemento da lupa da
   tabela — e pelo mesmo motivo: uma barra de botões de 44px por elemento
   empurraria o resultado para fora da primeira tela. */
.an-el__seta::before, .an-el__acao::before { content: ''; position: absolute; inset: -8px; }
.an-el__seta:disabled { opacity: 0.35; }

/* PAR DE LARGURA — dois botoes colados que se comportam como um controle so.
   Fica no cabecalho do elemento, ao lado das setas, porque largura e decisao
   de ARRANJO: onde o elemento fica na tela, nao o que ele mostra. */
.an-el__larguras { display: inline-flex; margin-inline-start: var(--spacing-micro); }
.an-el__larg {
  position: relative;
  min-block-size: 28px; padding: 2px var(--spacing-inline);
  box-shadow: none; background: none;
  border: 1px solid var(--color-border-default);
  color: var(--color-text-secondary);
  font-size: var(--tipo-caption);
  border-radius: 0;
}
.an-el__larg:first-child { border-start-start-radius: var(--radius-input); border-end-start-radius: var(--radius-input); }
.an-el__larg:last-child { border-start-end-radius: var(--radius-input); border-end-end-radius: var(--radius-input); margin-inline-start: -1px; }
/* Alvo de toque de 44px sem engordar o desenho, igual as setas. */
.an-el__larg::before { content: ''; position: absolute; inset: -8px; }
/* O estado marcado nao pode ser alcancado pelo hover: foi esse o defeito que
   ja reincidiu neste projeto, e o portao de estilo o verifica. */
.an-el__larg[aria-pressed="true"] {
  background: var(--color-action-primary-default);
  border-color: var(--color-action-primary-default);
  color: var(--color-action-primary-foreground);
  z-index: 1;
}
.an-el__larg:hover:not([aria-pressed="true"]) {
  background: var(--color-surface-subtle); color: var(--color-text-primary);
  transform: none; box-shadow: none;
}
/* As setas e a acao tinham hover proprio; o par de largura tambem precisa,
   senao herda o "pulinho" do botao comum e destoa dos vizinhos. */
.an-el__seta:hover:not(:disabled), .an-el__acao:hover {
  background: var(--color-surface-subtle); color: var(--color-text-primary);
  transform: none; box-shadow: none;
}
/* Empurra o remover para a borda direita, como no painel. */
.an-el__vao { margin-inline-start: auto; }

/* ALCA DE ARRASTAR. O cursor e o unico aviso de que ela pega — por isso o
   par grab/grabbing, e por isso o title cita as setas: quem nao usa mouse
   precisa saber que existe o outro caminho. */
.an-grip {
  cursor: grab; user-select: none;
  color: var(--color-text-muted); font-size: 13px; line-height: 1;
  padding: 6px 4px; border-radius: var(--radius-input);
}
.an-grip:active { cursor: grabbing; }
.an-grip:hover { color: var(--color-text-primary); background: var(--color-surface-subtle); }

/* O cartao em transito perde peso; o cartao sob o cursor ganha um traco na
   borda inteira, para o destino ser obvio antes de soltar. Contorno, e nao
   deslocamento: mover o alvo enquanto se arrasta e o que faz a peca cair no
   lugar errado. */
.an-el--arrastando { opacity: 0.45; }
.an-el--alvo { outline: 2px dashed var(--color-action-primary-default); outline-offset: 3px; }

/* O × e simbolo, entao ele precisa de area de toque propria e de peso
   suficiente para nao virar sujeira ao lado do par de largura. */
.an-el__x {
  min-inline-size: 30px; padding-inline: var(--spacing-micro);
  font-size: 15px; line-height: 1;
}

/* ══════════════ SELETOR DE COLUNAS ═════════════════════════════════════
   Botao que diz quantas, menu com todas, selo com a posicao. Compacto para
   caber na linha dos campos — e e a compactacao que permite oferecer a
   escolha de colunas em qualquer tabela, e nao so em duas. */
.sel-med { position: relative; display: inline-flex; }
.sel-alvo {
  display: inline-flex; align-items: center; gap: var(--spacing-micro);
  min-block-size: 38px; padding: 4px var(--spacing-inline);
  font-size: var(--tipo-tabela);
  background: var(--color-surface-default);
  border: 1px solid var(--color-border-default);
  border-radius: var(--radius-input);
  color: var(--color-text-primary); box-shadow: none;
}
.sel-alvo:hover { border-color: var(--color-border-strong); transform: none; box-shadow: none; }
/* Aberto NAO e alcancavel pelo hover — o defeito que ja reincidiu aqui. */
.sel-alvo[aria-expanded="true"] { border-color: var(--color-action-primary-default); }
.sel-alvo__seta { color: var(--color-text-muted); font-size: 10px; }
.sel-menu {
  position: absolute; inset-block-start: calc(100% + 4px); inset-inline-start: 0;
  z-index: 40; min-inline-size: 258px;
  max-block-size: min(58vh, 340px); overflow: auto;
  padding: var(--spacing-micro);
  background: var(--color-surface-default);
  border: 1px solid var(--color-border-default);
  border-radius: var(--radius-medium);
  box-shadow: var(--sombra-1);
}
/* 38px é o piso de alvo declarado do sistema, e a linha de menu estava
   fora dele: 21px de linha mais 6+6 de padding davam 33px, com ZERO de
   folga entre um item e o vizinho. Num menu de dez medidas isso é o lugar
   mais fácil de errar o toque, e errar aqui troca a coluna da tabela.
   Quando as dez linhas passam da altura máxima, o menu rola dentro de si —
   já era o comportamento contratado, agora ele de fato acontece. */
.sel-item {
  display: flex; align-items: center; gap: var(--spacing-micro);
  min-block-size: 38px;
  padding: 6px var(--spacing-inline); border-radius: var(--radius-input);
  font-size: var(--tipo-tabela); color: var(--color-text-secondary);
  cursor: pointer; white-space: nowrap;
}
.sel-item:hover { background: var(--color-surface-subtle); color: var(--color-text-primary); }
.sel-item--on { color: var(--color-text-primary); font-weight: 560; }
.sel-item[aria-disabled="true"] { opacity: 0.5; }
.sel-item input { margin: 0; flex: none; }
/* A marca de cor repete o papel da medida, igual a ficha antiga: a cor e
   atalho, o texto do papel ao lado e a garantia. */
.sel-item__marca { inline-size: 9px; block-size: 9px; border-radius: 2px; flex: none; }
.sel-item__nome { flex: 1; }
.sel-item__papel { color: var(--color-text-muted); font-size: var(--tipo-caption); }
/* A posicao na ordem de marcacao: e ela que define a ordem das colunas. */
.sel-item__pos {
  flex: none; min-inline-size: 17px; block-size: 17px;
  display: grid; place-items: center; border-radius: 5px;
  background: var(--color-action-primary-default);
  color: var(--color-action-primary-foreground);
  font-size: 10px; font-weight: 700;
}
.an-estado { font-size: var(--tipo-caption); }
.an-el__editor {
  margin-block-end: var(--spacing-control);
  padding: var(--spacing-control);
  border: 1px solid var(--color-border-subtle);
  border-radius: var(--radius-medium);
  background: var(--color-surface-elevated);
}
.an-el__campos {
  display: flex; flex-wrap: wrap; align-items: flex-end; gap: var(--spacing-control);
}
.an-el__rot {
  display: block; margin-block-end: var(--spacing-micro);
  font-size: var(--tipo-caption); color: var(--color-text-muted);
}
.an-colunas { margin-block-start: var(--spacing-control); }

/* A FAIXA DE INDICADORES DOS MÓDULOS TEM QUATRO COLUNAS FIXAS — é o desenho
   dela, com oito indicadores em duas linhas. Um card do Analytics é UM
   indicador dentro de um elemento que já tem largura própria: reaproveitar a
   faixa dava um cartão de 137px com "R$ 115,9 mi" quebrado em três linhas. */
.an-tiles { grid-template-columns: 1fr; }

/* ── Analytics: a explicação de abertura e o estado vazio ──────────────────
   A tela abre sem visão nenhuma, de propósito: o que está sendo demonstrado é
   a ferramenta, e uma visão pronta rouba o gesto que o visitante precisa fazer
   para entender que ela é dele. No lugar dela, os três passos. */
.an-como {
  margin-block-end: var(--spacing-card);
  padding: var(--spacing-card);
  border: 1px solid var(--color-border-default);
  border-radius: var(--radius-card);
  background: var(--color-surface-default);
}
.an-como__tit { margin: 0 0 var(--spacing-control); font-size: var(--tipo-h3); }
.an-como__passos {
  display: grid; gap: var(--spacing-control);
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  margin: 0; padding: 0; list-style: none;
}
.an-como__passos li {
  display: flex; align-items: flex-start; gap: var(--spacing-inline);
  color: var(--color-text-secondary);
}
/* O número do passo é ORDEM, não decoração: os três só fazem sentido nessa
   sequência, e sem ele a grade viraria três frases soltas lado a lado. */
.an-como__n {
  flex: none;
  display: grid; place-items: center;
  inline-size: 24px; block-size: 24px;
  border-radius: 50%;
  background: var(--color-action-selected);
  color: var(--color-text-primary);
  font-size: var(--tipo-caption); font-weight: var(--tipo-label-peso);
}
.an-como__nota {
  margin: var(--spacing-control) 0 0;
  padding-block-start: var(--spacing-control);
  border-block-start: 1px solid var(--color-border-subtle);
  font-size: var(--tipo-caption); color: var(--color-text-muted);
}

/* Estado vazio como CONVITE, não como aviso de erro. Com uma visão só, a faixa
   antiga ficava com um cartãozinho à esquerda e um vão até o botão do canto
   direito — parecia carregamento pela metade. */
.an-inicio { text-align: center; }
.an-inicio__txt {
  max-inline-size: 52ch; margin: var(--spacing-compact) auto var(--spacing-card);
  color: var(--color-text-secondary);
}
.an-inicio__nota {
  margin: var(--spacing-control) 0 0;
  font-size: var(--tipo-caption); color: var(--color-text-muted);
}

/* Com visões, uma grade que preenche a largura em vez de encostar tudo na
   esquerda. */
.an-lista {
  display: grid; gap: var(--spacing-inline);
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
}

/* A escolha de colunas fora do construtor de visões: numa tabela de módulo ela
   não vive dentro de um editor, então ganha o próprio respiro e um fio que a
   separa da tabela que ela governa. */
.an-colunas--solta {
  margin-block: var(--spacing-control) var(--spacing-card);
  padding-block-end: var(--spacing-control);
  border-block-end: 1px solid var(--color-border-subtle);
}

/* ══════════ PISO DE ALVO SEM ENGORDAR O DESENHO ═══════════════════════
   Medido em 08/09/2026: estes controles ficavam entre 21 e 34px, abaixo do
   piso de 38px que este produto declara para botao. Crescer o desenho
   mudaria a densidade de telas ja aprovadas; a folga invisivel resolve o
   alvo e nao mexe em um pixel do que se ve.

   Vale so para BOTAO. Campo de formulario nao renderiza pseudo-elemento —
   esses cresceram de verdade, acima. */
.trilha__subir, .trilha__no, .botao--texto, .tab__ordenar, .btn-recolher, .marca-topo a {
  position: relative;
}
.trilha__subir::before, .trilha__no::before, .botao--texto::before,
.tab__ordenar::before, .btn-recolher::before, .marca-topo a::before {
  content: ''; position: absolute; inset: -9px;
}
/* O cabecalho da tabela e denso: a folga vertical bastaria para o alvo, mas
   -9px na horizontal faria o alvo de uma coluna invadir o da vizinha. */
.tab__ordenar::before { inset: -9px -2px; }

/* ══════════ BLOCO PENDURADO DIRETO NO CARTAO ══════════════════════════
   Medido em 08/09/2026: o rotulo de colunas da carteira ficava a 1px da
   borda esquerda, e a nota do inicio do Analytics a 3px da base. Nao era
   falta de padding no cartao — era elemento no lugar errado da caixa: o
   respiro do cartao mora em `.card .body`, e estes dois foram anexados ao
   `.card`, que tem padding zero.

   Corrigido pelo CSS e nao pela marcacao porque o corpo do cartao ja e
   usado por outro conteudo nesses dois lugares; mover o bloco para dentro
   dele mudaria a hierarquia por um problema de respiro. O respiro repetido
   aqui e o MESMO do corpo — se um dia mudar la, muda aqui junto. */
.card > .an-colunas,
.card > .an-inicio__nota,
.card > .an-inicio__txt { padding-inline: 17px; }
.card > .an-inicio__nota { padding-block-end: 16px; }

/* ══════════════════ ALTERNADOR DE TEMA ═════════════════════════════════
   Piso de 38px como todo botao. Fica junto do titulo e do selo, nao na
   barra de filtros: tema nao muda o que a analise responde. */
.btn-tema {
  min-block-size: 38px; padding: 4px var(--spacing-inline);
  gap: var(--spacing-micro); box-shadow: none;
  background: var(--color-surface-default);
  border: 1px solid var(--color-border-default);
  color: var(--color-text-secondary);
  font-size: var(--tipo-caption);
}
.btn-tema:hover:not(:disabled) {
  transform: none; box-shadow: none;
  border-color: var(--color-border-strong); color: var(--color-text-primary);
}
.btn-tema__ic { font-size: 14px; line-height: 1; }

/* Abaixo de 560px o rotulo sai e fica so o simbolo — a barra de topo ja
   disputa espaco com o titulo e o selo. O nome continua no title e no
   rotulo assistivo, entao nada se perde para quem nao ve o texto. */
@media (max-width: 560px) {
  .btn-tema__rot { position: absolute; inline-size: 1px; block-size: 1px;
    overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
  .btn-tema { inline-size: 38px; justify-content: center; padding-inline: 0; }
}

/* A linha de principio fica acima da nota, com peso proprio mas sem virar
   destaque: e explicacao, nao chamada. */
.an-como__principio {
  margin: var(--spacing-control) 0 var(--spacing-micro);
  padding-block-start: var(--spacing-compact);
  border-block-start: 1px solid var(--color-border-subtle);
  font-size: var(--tipo-caption); color: var(--color-text-secondary);
}
.an-como__principio b { color: var(--color-text-primary); }

/* ══════════════════════ BARRA COMPACTA E FOLHAS (MOBILE) ═══════════════ */
/* Entre 641 e 900px a lateral já vira uma trilha horizontal rolável, e isso
   basta. Abaixo de 640px a trilha deixa de bastar: sete módulos numa tela de
   375px viram uma fita que só se descobre arrastando, e o filtro come a
   altura útil antes do primeiro número. Por isso, e só aqui, a navegação sai
   da tela e vira barra + folha.

   A lateral NÃO é removida do documento: `display: none` a tira também da
   árvore de acessibilidade, então nunca existem duas navegações anunciadas,
   e girar o aparelho a traz de volta com o estado certo — quem escreve o
   módulo ativo é o mesmo `aria-current` dos dois lados. */

.barra-mobile { display: none; }
.filtros__abrir { display: none; }

@media (max-width: 640px) {
  .lateral { display: none; }

  .barra-mobile {
    display: flex; align-items: center; gap: var(--spacing-inline);
    position: sticky; inset-block-start: 0; z-index: 45;
    padding: 8px var(--spacing-control);
    background: var(--color-surface-default);
    border-block-end: 1px solid var(--color-border-default);
  }
  /* O símbolo não tem dimensão própria dentro de um <use>: sem isto o SVG
     assume o padrão de 300x150 do navegador e empurra a barra inteira. */
  /* Sem `color` aqui: o <symbol> ja declara os proprios preenchimentos a
     partir dos tokens de identidade, e repetir a cor no <svg> nao mudava
     nada no desenho — so gastava identidade fora do contrato. */
  .barra-mobile__marca {
    inline-size: 22px; block-size: 22px; flex: 0 0 auto;
  }
  /* O nome do módulo ocupa o lugar do <h1>, que aqui seria uma segunda
     linha de texto dizendo a mesma coisa. Ele encolhe antes dos botões:
     rótulo cortado é recuperável, botão cortado não. */
  .barra-mobile__modulo {
    flex: 1 1 auto; min-inline-size: 0;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    font-size: var(--tipo-h4); font-weight: var(--tipo-h4-peso);
    color: var(--color-text-primary);
  }
  .barra-mobile__acao {
    flex: 0 0 auto; min-block-size: 38px; padding: 4px var(--spacing-inline);
    background: var(--color-surface-default);
    border: 1px solid var(--color-border-default);
    border-radius: var(--radius-button);
    color: var(--color-text-secondary); font-size: var(--tipo-caption);
  }
  .barra-mobile__acao:hover { border-color: var(--color-border-strong); color: var(--color-text-primary); }
  .barra-mobile .btn-tema { flex: 0 0 auto; }

  /* Com a barra compacta acima, o <h1> repetiria o módulo. Some o título e
     fica o selo, que é a informação que a barra NÃO dá. */
  .topline h2 { display: none; }
  .topline .btn-tema { display: none; }
  .topline { gap: var(--spacing-inline); }
  /* O bloco de 900px dá a linha inteira ao título, e com razão: lá o <h1>
     ainda está lá. Aqui ele saiu para a barra compacta, e manter 100% deixa
     o selo sozinho ocupando a largura toda e joga o botão de filtros para a
     linha de baixo — 34px de altura gastos numa tela que não tem. */
  .topline__titulo { inline-size: auto; }

  /* O botão só existe quando o formulário saiu daqui; o seletor é ancorado
     no PAI original, e não na classe do formulário, porque dentro da folha
     ele precisa reaparecer — é o mesmo elemento, movido. */
  .filtros__abrir { display: inline-flex; min-block-size: 38px; }
  .topline > .filtros { display: none; }

  .filtros__conta {
    min-inline-size: 18px; padding: 0 5px; margin-inline-start: 6px;
    border-radius: var(--radius-tag);
    background: var(--color-action-primary-default);
    color: var(--color-action-primary-foreground);
    font-size: var(--tipo-caption); font-weight: 700; line-height: 18px;
    text-align: center;
  }
}

/* ── folha (diálogo que sobe de baixo) ─────────────────────────────────── */
/* Sobe de baixo porque é onde o polegar alcança; a gaveta lateral existe
   para conteúdo que se lê ao lado, e aqui não há "ao lado". */
.folha-fundo {
  position: fixed; inset: 0; z-index: 80;
  display: flex; align-items: flex-end; justify-content: center;
}
/* O véu é um pseudo-elemento, e não o fundo do próprio contêiner, porque
   aqui o contêiner ENVOLVE a folha: `opacity` nele apagaria junto o painel
   que ele existe para destacar. Mesma cor e mesma opacidade da gaveta — é o
   mesmo gesto de "o que está atrás saiu de cena", e sai do mesmo token. */
.folha-fundo::before {
  content: ''; position: absolute; inset: 0;
  background: var(--color-brand-carbon); opacity: 0.32;
}
.folha {
  position: relative; z-index: 81;
  inline-size: min(560px, 100%); max-block-size: 86vh;
  display: flex; flex-direction: column;
  background: var(--color-surface-default);
  border-block-start: 1px solid var(--color-border-default);
  border-start-start-radius: var(--radius-large);
  border-start-end-radius: var(--radius-large);
  /* Nível 2 de sombra, como a gaveta. O que torna esta folha modal é o véu
     atrás dela, não uma sombra mais forte: empilhar mais sombra sobre um
     fundo já escurecido não acrescenta profundidade, só borra a borda. */
  box-shadow: var(--shadow-elevation2);
}
.folha__topo {
  display: flex; align-items: center; gap: 12px;
  padding: 14px 18px; border-block-end: 1px solid var(--color-border-subtle);
  background: linear-gradient(180deg, var(--color-surface-elevated), transparent);
}
.folha__tit {
  margin: 0; font-size: var(--tipo-h4); font-weight: var(--tipo-h4-peso);
  color: var(--color-text-primary);
}
.folha__x {
  margin-inline-start: auto; min-inline-size: 38px; min-block-size: 38px;
  justify-content: center;
  background: transparent; border: 1px solid transparent;
  border-radius: var(--radius-button); color: var(--color-text-secondary);
}
.folha__x:hover { border-color: var(--color-border-default); color: var(--color-text-primary); }
.folha__corpo { overflow-y: auto; padding: 14px 18px 24px; flex: 1 1 auto; }

/* Enquanto a folha está aberta o documento atrás não rola: sem isto, arrastar
   dentro da folha e chegar ao fim continua rolando a página embaixo, e a
   pessoa fecha o diálogo em outro ponto da tela. */
body.com-folha { overflow: hidden; }

/* Os filtros DENTRO da folha voltam a ser uma coluna. Na barra estreita eles
   são uma trilha horizontal com máscara na borda; herdar isso aqui produziria
   uma fita rolável dentro de um painel que tem altura de sobra. */
.folha__corpo .filtros {
  display: flex; flex-direction: column; align-items: stretch;
  flex-wrap: nowrap; gap: var(--spacing-inline);
  inline-size: 100%; overflow-x: visible; padding-block-end: 0;
  -webkit-mask-image: none;
          mask-image: none;
}
.folha__corpo .f { flex: 0 0 auto; inline-size: 100%; }
.folha__corpo .f select,
.folha__corpo .f input { inline-size: 100%; }

/* ── folha de módulos ──────────────────────────────────────────────────── */
.folha-modulos { display: flex; flex-direction: column; gap: 2px; }
.folha-modulo {
  display: flex; align-items: center; gap: 10px;
  inline-size: 100%; min-block-size: 44px; padding: 8px 10px;
  background: transparent; border: 1px solid transparent;
  border-radius: var(--radius-medium);
  color: var(--color-text-secondary); text-align: start;
  font-size: var(--tipo-nav); font-weight: var(--tipo-nav-peso);
}
/* O :not do estado vem ANTES do :hover, como na lateral: sem ele o passar
   do dedo repinta o modulo atual com o fundo do inativo, e por um instante
   a lista nao diz mais onde a pessoa esta. */
.folha-modulo:not([aria-current="true"]):hover:not([disabled]) {
  background: var(--color-surface-elevated); color: var(--color-text-primary);
}
.folha-modulo[disabled] { color: var(--color-action-disabled-foreground); cursor: not-allowed; }
/* Mesmo sinal da lateral: filete de identidade marcando onde a pessoa está.
   O módulo atual continua clicável e continua na lista — some-lo faria a
   lista mudar de tamanho a cada abertura. */
.folha-modulo[aria-current="true"] {
  background: var(--color-action-selected);
  color: var(--color-text-primary);
  border-inline-start: 2px solid var(--color-identity-readable);
  padding-inline-start: 9px;
}
.folha-modulo__rot { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ── menu de colunas em tela estreita ──────────────────────────────────── */
/* O menu é um popover ancorado ao botão, com 258px de largura mínima. Numa
   tela de 320 o botão pode estar a 145px da borda, e o menu terminava em 403.
   Ele não vazava para fora da página: o cartão corta com `overflow: hidden`,
   então o resto do menu simplesmente SUMIA — quatro medidas invisíveis, sem
   nenhuma barra de rolagem dizendo que existiam. Menu cortado em silêncio é
   pior que menu que vaza, porque quem olha não sabe que falta algo.

   Aqui ele deixa de ser ancorado e sobe de baixo, como as outras folhas desta
   tela. `fixed` escapa do corte do cartão porque nenhum ancestral cria bloco
   de contenção — transform, filter, will-change e contain conferidos na
   página real, não supostos. z-index 60: acima da barra compacta (45), abaixo
   da folha modal (80/81), que deve sempre cobri-lo. */
@media (max-width: 640px) {
  .sel-menu {
    position: fixed; z-index: 60;
    inset-inline: var(--spacing-inline);
    inset-block: auto var(--spacing-inline);
    inline-size: auto; min-inline-size: 0;
    max-block-size: 60vh;
    border-radius: var(--radius-large);
    box-shadow: var(--shadow-elevation2);
  }
}


/* ═══════════════════════════════════════════════════════════════════════
   A CASCA DA ROTA PÚBLICA

   Só existe em /demo/. É a moldura mínima que diz onde a pessoa está, o que
   ela vai encontrar e como voltar — sem wordmark externo (a aplicação já tem o
   dela, e dois wordmarks em sequência seria repetição), sem menu institucional
   e sem convite comercial.

   UMA FAIXA SÓ, e não três. A primeira versão tinha cabeçalho, depois uma
   faixa de intro, depois a aplicação: descer a página virava três paradas
   antes do produto, e a do meio era só texto. Aqui o texto mora no próprio
   cabeçalho, na coluna do meio que antes estava vazia, e a aplicação começa
   logo abaixo.
   ═══════════════════════════════════════════════════════════════════════ */

.casca-topo {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: center;
  gap: var(--spacing-card);
  /* O corpo da página não tem recuo: a aplicação sangra até a borda de
     propósito. A casca precisa do recuo dela, e ele é o mesmo da coluna
     principal, para o título nascer alinhado com o título do módulo. */
  padding-inline: var(--spacing-card);
  padding-block: var(--spacing-inline);
  border-block-end: 1px solid var(--color-border-subtle);
}

.casca-topo__voltar {
  font-size: var(--tipo-label); font-weight: var(--tipo-label-peso);
  color: var(--color-text-secondary); text-decoration: none;
  white-space: nowrap;
  /* alvo de toque: o link é pequeno como texto, não como área */
  padding: 8px 0; min-block-size: 38px; display: inline-flex; align-items: center;
}
.casca-topo__voltar:hover { color: var(--color-text-primary); }

.casca-topo__texto { min-inline-size: 0; }

/* É o h1 da página. Pequeno de propósito — a casca é moldura, não capa —,
   mas continua sendo o título de verdade na árvore de acessibilidade. */
.casca-topo__titulo {
  margin: 0; font-size: var(--tipo-corpo); font-weight: 620;
  letter-spacing: -0.005em; line-height: 1.35; color: var(--color-text-primary);
}

.casca-topo__suporte {
  margin: 2px 0 0; font-size: var(--tipo-caption); line-height: 1.45;
  color: var(--color-text-secondary);
}

/* Em tela estreita as três colunas não cabem lado a lado: viram duas linhas —
   a de navegação (voltar e identificação) e a do texto. */
@media (max-width: 900px) {
  .casca-topo {
    grid-template-columns: 1fr;
    row-gap: 8px;
    padding-inline: var(--spacing-control);
    padding-block: 10px 12px;
  }
}
