/*
  Cardexa Design System — CAMADA 3: COMPONENTES (AGENT §2). Regra real da camada:
    - COR, RAIO e SOMBRA de componente vêm SEMPRE da camada SEMÂNTICA (var(--cx-color-* / radius-* / shadow-* / scrim))
      — nunca primitivo cru, nunca cor por tenant; é o que o white-label redefine.
    - ESCALA de espaçamento, TIPOGRAFIA e MOTION (var(--cx-space-* / text-* / font-* / leading / motion-* / ease)) são
      primitivos POR DESIGN: NÃO são themable (a marca não reescreve a métrica do sistema), então o componente
      pode lê-los direto da camada 1.
  Acessibilidade é aceite: foco sempre visível, motion respeita prefers-reduced-motion, alvos de toque
  generosos. Zero URL de rede. TAMANHO: não há teto (CSS-SEM-TETO-1). O antigo NFR "este arquivo + tokens
  ≤ 150KB" saiu do doc e dos testes: ele nunca segurou crescimento, só empurrava quem precisava de uma classe
  nova para escrever estilo embutido na tela. Precisou de peça de interface, escreve AQUI, sem contar bytes.
*/

/* ---- Base ---- */
*, *::before, *::after { box-sizing: border-box; }

body.cx-body,
.cx-root {
  margin: 0;
  font-family: var(--cx-font-family-base);
  font-size: var(--cx-text-md);
  line-height: var(--cx-leading);
  color: var(--cx-color-text);
  background: var(--cx-color-surface-muted);
  -webkit-font-smoothing: antialiased;
}

/* :not(.cx-btn): âncora estilizada de botão usa a cor do PRÓPRIO .cx-btn--* — o tinte de link (0,1,1) vencia
   os variants (0,1,0) e apagava o rótulo do primário (texto azul sobre fundo azul). */
.cx-root a:not(.cx-btn) { color: var(--cx-color-action); }

/* Foco visível universal (teclado). */
:where(a, button, input, select, textarea, [tabindex]):focus-visible {
  outline: 2px solid var(--cx-color-focus-ring);
  outline-offset: 2px;
  border-radius: var(--cx-radius-control);
}

/* Só-leitor-de-tela. */
.cx-sr-only {
  position: absolute !important;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0, 0, 0, 0);
  white-space: nowrap; border: 0;
}

/* ---- Botão ---- */
.cx-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--cx-space-2);
  font: inherit; font-weight: 600; line-height: 1;
  border: 1px solid transparent; border-radius: var(--cx-radius-control);
  padding: var(--cx-space-3) var(--cx-space-4); min-height: 2.75rem;
  cursor: pointer; text-decoration: none;
  transition: background-color var(--cx-motion-fast) var(--cx-ease), border-color var(--cx-motion-fast) var(--cx-ease);
}
.cx-btn--sm { min-height: 2.25rem; padding: var(--cx-space-2) var(--cx-space-3); font-size: var(--cx-text-sm); }
.cx-btn--lg { min-height: 3.25rem; padding: var(--cx-space-4) var(--cx-space-5); font-size: var(--cx-text-lg); }
.cx-btn--block { display: flex; width: 100%; }
.cx-btn[disabled], .cx-btn[aria-disabled="true"] { opacity: .5; cursor: not-allowed; }

.cx-btn--primary { background: var(--cx-color-action); color: var(--cx-color-text-on-action); }
.cx-btn--primary:hover { background: var(--cx-color-action-hover); }
.cx-btn--secondary { background: var(--cx-color-surface); color: var(--cx-color-text); border-color: var(--cx-color-border); }
.cx-btn--secondary:hover { background: var(--cx-color-surface-muted); }
.cx-btn--ghost { background: transparent; color: var(--cx-color-action); }
.cx-btn--ghost:hover { background: var(--cx-color-action-muted); }
.cx-btn--danger { background: var(--cx-color-danger); color: var(--cx-color-text-on-action); }

/* ---- Campo / input / select ---- */
.cx-field { display: grid; gap: var(--cx-space-1); margin-block-end: var(--cx-space-4); }
/* O `hidden` PRECISA desta linha (OVERLIMIT-DRAWER-UX-1). O `display: none` do atributo mora na folha do NAVEGADOR,
   e folha de autor vence folha de navegador seja qual for a especificidade: sem esta regra, `.cx-field { display:
   grid }` desfaz o `hidden` em silêncio e o campo escondido aparece na tela. Vale para qualquer campo do pacote,
   não só para o do limite extra: era um defeito latente do dia em que o campo virou grade. */
.cx-field[hidden] { display: none; }
.cx-field__label { font-size: var(--cx-text-sm); font-weight: 600; color: var(--cx-color-text); }
.cx-field__required { color: var(--cx-color-danger); margin-inline-start: 2px; }
.cx-input, .cx-select, .cx-textarea {
  font: inherit; color: var(--cx-color-text); background: var(--cx-color-surface);
  border: var(--cx-control-border-width) solid var(--cx-color-border); border-radius: var(--cx-radius-control);
  padding-inline: var(--cx-space-3); width: 100%;
}
/* ALTURA DO CONTROLE (FORM-ALTURA-1): o controle de UMA LINHA tem a altura EXATA do token e padding
   vertical ZERO. Duas razões, e as duas já produziram formulário torto:
   1. com `min-height` mais padding vertical, a altura final é "o token OU o conteúdo, o que for maior";
      basta o vizinho ter outra fonte (o mono do painel de parâmetros) para as duas caixas divergirem;
   2. a caixa de afixo já era `height` fixa, então os dois caminhos do MESMO campo respondiam a regras de
      naturezas diferentes. Era esse o par de 2.75rem x 2.5rem que o dono viu lado a lado na tela de
      Tarifas (o campo de dinheiro com R$ ao lado do campo de meses sem afixo).
   Quem centra o texto na vertical é o próprio controle. A caixa de afixo, mais abaixo, repete os MESMOS
   valores de altura, borda e padding: o que o olho vê tem de fechar a mesma conta nos dois caminhos. */
.cx-input, .cx-select { height: var(--cx-control-height); padding-block: 0; }
/* Texto longo: mesma moldura do input, só cresce na vertical (nunca na horizontal, que arrebentaria a coluna). */
.cx-textarea { resize: vertical; min-height: var(--cx-control-height-text); line-height: 1.5; padding-block: var(--cx-space-3); }
/* Anexo: o botão nativo do browser não obedece padding vertical, então o controle centra o próprio conteúdo. */
.cx-input--file { display: flex; align-items: center; }
.cx-input::placeholder, .cx-textarea::placeholder { color: var(--cx-color-text-muted); }
.cx-input--invalid, .cx-select--invalid, .cx-textarea--invalid { border-color: var(--cx-color-danger); }
/* Erro declarado na CAIXA do campo: serve à tela cujo erro é do formulário inteiro (login, troca de senha), onde
   a mensagem sai uma vez só no alerta e os campos só precisam do sinal de borda. */
.cx-field--invalid .cx-input, .cx-field--invalid .cx-select, .cx-field--invalid .cx-textarea,
.cx-field--invalid .cx-input-affix { border-color: var(--cx-color-danger); }

/* ---- ÍCONE DE INFORMAÇÃO do campo (CONSOLE-INFO-1, decisão 163 do dono) ----
   O "i" ao lado do rótulo abre uma explicação breve do parâmetro. TRÊS PORTAS, porque uma só sempre deixa alguém
   de fora: o mouse (:hover), o teclado (:focus-within — o gatilho é um <button> de verdade) e o TOQUE, que o
   script transforma em aria-expanded (tablet não tem hover, e era essa a exigência que matava o `title=""`).
   As duas primeiras são CSS PURA: sem script o ícone continua explicando o campo.
   A linha do rótulo existe porque BOTÃO NÃO PODE MORAR DENTRO DE <label> (elemento rotulável dentro do rótulo é
   marcação inválida e rouba o clique do controle). Ela é que declara a faixa 1 da subgrade, mais abaixo. */
.cx-field__labelrow { display: flex; align-items: center; gap: var(--cx-space-2); min-width: 0; }
.cx-field__labelrow > .cx-field__label { min-width: 0; }
/* Na caixa de marcar quem divide a linha com o ícone é o próprio CONTROLE, então esta linha mora na faixa 2. */
.cx-field__checkrow { display: flex; align-items: center; gap: var(--cx-space-2); min-width: 0; }

.cx-infotip { position: relative; display: inline-flex; flex: none; }
.cx-infotip__btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 1.25rem; height: 1.25rem; padding: 0;
  border: 0; border-radius: 50%; background: transparent; cursor: pointer;
  color: var(--cx-color-text-muted);
}
.cx-infotip__btn:hover, .cx-infotip__btn[aria-expanded="true"] {
  background: var(--cx-color-action-muted); color: var(--cx-color-action);
}
/* O painel é ESCONDIDO por visibilidade (não por `hidden`): assim a folha o revela sozinha no mouse e no teclado,
   sem depender de script, e ele continua alcançável pelo aria-describedby do controle, que lê elemento escondido. */
.cx-infotip__panel {
  position: absolute; z-index: 30; top: calc(100% + 6px); inset-inline-start: 0;
  width: max-content; max-width: min(22rem, 68vw);
  background: var(--cx-color-surface); color: var(--cx-color-text);
  border: 1px solid var(--cx-color-border); border-radius: var(--cx-radius-control);
  box-shadow: var(--cx-shadow-overlay); padding: var(--cx-space-3);
  font-size: var(--cx-text-xs); font-weight: 400; line-height: 1.5; white-space: normal; text-align: start;
  visibility: hidden; opacity: 0; transition: opacity 120ms ease;
}
.cx-infotip:hover > .cx-infotip__panel,
.cx-infotip:focus-within > .cx-infotip__panel,
.cx-infotip__btn[aria-expanded="true"] + .cx-infotip__panel { visibility: visible; opacity: 1; }
/* (FIX-PZ-1 item 2) A AJUDA DO CAMPO CABE NA COLUNA DO CAMPO.
   O dono abriu os Provedores de comunicação em 1440 e a página rolava de lado: 1511px de largura rolável numa
   janela de 1440. Não era a tabela nem a casca: era ESTE painel. Ele é `position: absolute` ancorado no ícone de
   20px (`inset-inline-start: 0`) e mede até 22rem; escondido por VISIBILIDADE, continua tendo caixa, e caixa de
   descendente absoluto entra no overflow rolável do documento mesmo invisível. No campo da TERCEIRA coluna da
   grade do formulário o ícone fica em x=1159, e 1159 + 352 = 1511 — o número exato que o dono viu.

   O conserto tem duas metades, e as duas são necessárias. (a) A âncora passa a ser a LINHA DO RÓTULO
   (`position: relative` nela, `static` no ícone): o painel deixa de se medir a partir de um ícone de 20px e passa
   a se medir a partir da largura do campo, que é onde ele visualmente pertence. (b) Dentro dessa âncora ele
   cresce PARA DENTRO da página (`inset-inline-end: 0`): a borda direita do painel encosta na borda direita do
   campo e o corpo cresce para a esquerda, sempre por cima da própria coluna.
   Medido nos 4 viewports + 412 em 6 telas dos dois heads: a página parou de transbordar em 1024/1280/1440/1884 e
   NENHUM painel passou a ser cortado na borda esquerda (a menor borda esquerda medida foi 75px, em 412). De
   quebra, os painéis do Produto & Parâmetros, que estouravam a coluna e eram clipados por um ancestral, passaram
   a caber (maior borda direita 1467 em 1884, 967 em 1024).

   Escopado às DUAS linhas de campo (rótulo e caixa de marcar), que hoje são o único lugar de onde a ajuda nasce
   (CxField, CxSelect, CxFormParts e o seletor de cor da marca fecham essa div): um infotip que apareça fora delas
   segue com o comportamento antigo em vez de herdar uma âncora que não existe. Nada de esconder o transbordo com
   `overflow`: esconder a barra esconderia a explicação, que é conteúdo. */
.cx-field__labelrow, .cx-field__checkrow { position: relative; }
.cx-field__labelrow > .cx-infotip, .cx-field__checkrow > .cx-infotip { position: static; }
.cx-field__labelrow > .cx-infotip > .cx-infotip__panel,
.cx-field__checkrow > .cx-infotip > .cx-infotip__panel { inset-inline-start: auto; inset-inline-end: 0; }

.cx-field__hint { font-size: var(--cx-text-xs); color: var(--cx-color-text-muted); margin: 0; }
.cx-field__error { font-size: var(--cx-text-sm); color: var(--cx-color-danger); font-weight: 600; margin: 0; }
/* Campo com unidade (prefixo/sufixo): a MOLDURA passa ao contêiner e o input interno fica nu — o anel de foco
   universal migra para a caixa via :focus-within (input sem borda não pode ficar sem sinal de foco). */
.cx-input-affix {
  display: flex; align-items: center; gap: 6px;
  background: var(--cx-color-surface); border: var(--cx-control-border-width) solid var(--cx-color-border);
  border-radius: var(--cx-radius-control); padding: 0 var(--cx-space-3);
  height: var(--cx-control-height);
}
/* MESMA conta de caixa do input puro: mesma altura (token), a mesma borda do token, mesmo padding lateral. Só
   assim o campo COM afixo e o campo SEM afixo, lado a lado na linha, terminam com a mesma medida final.
   O INPUT DE DENTRO TAMBÉM FECHA NO TOKEN (GRADE-FAIXAS-2). Ele lia `height: 100%`, e 100% da caixa de CONTEÚDO
   da moldura é o token menos as duas bordas: medido na aba de Usuários do Console, 38px de altura e topo 1px
   abaixo dos selects de 40px. A moldura estava certa e o controle de dentro não — meia peça alinhada é a mesma
   linha torta por outro caminho. Agora ele lê o token INTEIRO e desconta a borda da moldura em margem negativa
   nos dois lados, então a caixa dele coincide com a caixa da moldura: mesmo topo, mesma altura, mesma base, em
   qualquer casca que redefina o token. A moldura é `align-items: center`, e a margem negativa entra na conta do
   flex, então a soma continua exata (token - 2 bordas = a caixa de conteúdo) e nada transborda. */
.cx-input-affix > .cx-input {
  border: none; background: transparent; border-radius: 0;
  padding: 0; flex: 1; min-width: 0;
  height: var(--cx-control-height);
  margin-block: calc(-1 * var(--cx-control-border-width));
}
.cx-input-affix > .cx-input:focus-visible { outline: none; }
.cx-input-affix:focus-within { outline: 2px solid var(--cx-color-focus-ring); outline-offset: 2px; }
.cx-input-affix--invalid { border-color: var(--cx-color-danger); }
.cx-input-affix__unit { color: var(--cx-color-text-muted); font-size: var(--cx-text-sm); white-space: nowrap; }

/* ---- Layout de FORMULÁRIO (FORM-ALINHAMENTO-1) ----
   POR QUE ISTO EXISTE (a quinta reclamação do dono sobre "formulário torto"): o .cx-field é uma grade
   PRÓPRIA de quatro faixas (rótulo / controle / hint / erro). Dois campos lado a lado tinham grades
   INDEPENDENTES, então bastava um rótulo quebrar em duas linhas, ou um campo ter hint e o vizinho não,
   para os controles pararem em alturas diferentes. Era ISSO o formulário torto: não faltava estilo,
   faltava a LINHA. Cada tela inventava a sua em flex (align-items:flex-end era o erro mais comum, pois
   usa a base da caixa, e a caixa cresce com o hint) e saía torta de um jeito diferente.
   A correção mora num lugar só: as faixas do campo viram SUBGRADE das faixas da linha, então rótulo,
   controle, hint e erro dividem a MESMA faixa em toda a linha, independentemente de quebra de texto ou
   de hint ausente. Nenhuma tela precisa mais escolher alinhamento.
   row-gap:0 na subgrade é deliberado: faixa vazia (campo sem hint e sem erro) não pode cobrar
   espaçamento, então o respiro sai de margem nos elementos que EXISTEM. */
.cx-form { display: grid; gap: var(--cx-space-5); }

.cx-form__grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(16rem, 100%), 1fr));
  gap: var(--cx-space-4) var(--cx-space-5);
  align-items: start;
}

/* Linha de campos com uma AÇÃO ao lado (buscar, filtrar, escolher e ver). */
.cx-form-bar {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(14rem, 100%), 1fr));
  gap: var(--cx-space-4) var(--cx-space-3);
  align-items: start;
}

/* A MESMA DISCIPLINA PARA O SLOT DE AÇÃO (GRADE-FAIXAS-2) — a quarta reprovação do dono na mesma linha de busca,
   agora medida em pixel: o botão "Filtrar" nascia 8px ABAIXO dos selects (topo 55,5 contra 47,5), com a mesma barra,
   a mesma faixa e o mesmo token de altura.
   A CAUSA, que nenhum olho pega e a conta entrega. Subgrade que declara o PRÓPRIO row-gap não desloca as faixas do
   pai: ela absorve a diferença de goteira METADE em cada faixa vizinha (CSS Grid 2 §5.2). Com a barra em row-gap 16
   e o campo em row-gap 0, a faixa 1 do campo cresce 8 e a faixa 2 do campo COMEÇA 8 ANTES da faixa 2 da barra. O
   `.cx-form-bar__action` ficava de fora desta regra e herdava a goteira de 16 do pai, então o botão continuava
   sentado no começo REAL da faixa 2 — 8px abaixo do vizinho. Os 8px não eram folga de estilo: eram metade do
   row-gap da barra.
   O CONSERTO É A LISTA DE SELETORES, não um número. Campo e slot de ação passam pela MESMA declaração de goteira,
   então o começo da faixa do controle é `faixa1_fim + (16 + 0) / 2` para os DOIS, por construção. Quem mudar o gap
   da barra amanhã move os dois juntos; não há segundo lugar onde errar. */
.cx-form__grid > .cx-field,
.cx-form-bar > .cx-field,
.cx-form-bar > .cx-form-bar__action {
  margin-block-end: 0;
  grid-row: span 4;
  grid-template-rows: subgrid;
  row-gap: 0;
}

/* FAIXA EXPLÍCITA POR FILHO (GRADE-FAIXAS-1) — a RAIZ do "formulário torto", terceira reprovação do dono na
   mesma linha de busca.
   O QUE ACONTECIA. Ter as quatro faixas não bastava: quem decidia em QUAL faixa cada filho caía era o
   auto-posicionamento da grade, ou seja, a ORDEM dos filhos que ainda estão no fluxo. O campo de busca usa
   rótulo escondido (`LabelHidden`), e rótulo escondido é `.cx-sr-only`, que é `position: absolute` — elemento
   absoluto NÃO é item de grade. Some do fluxo, o auto-posicionamento adianta todo mundo uma faixa, e o
   CONTROLE da busca sobe para a faixa 1 (a dos rótulos), um degrau ACIMA dos selects vizinhos, que têm rótulo
   visível na 1 e controle na 2. É o degrau que aparece no print da tela viva. A mesma torção nasceria de
   qualquer outra ausência: campo sem rótulo, rótulo trocado de lugar, filho extra escrito por um head.
   O CONSERTO. Cada filho declara a SUA faixa, então faixa não se ganha por ordem nem por presença do vizinho.
   O padrão é a faixa do CONTROLE (2): qualquer filho que não seja rótulo, ajuda ou erro é controle, inclusive
   os que o pacote não conhece (a moldura de afixo da lupa, a caixa de marcar, o wrapper que um head escreve
   em volta do seu input). As três exceções nomeadas vencem por especificidade. É a MESMA disciplina que o
   `.cx-form-bar__action` já usava para o botão; ela só não valia para os campos.
   NÃO se conserta mexendo no `.cx-sr-only`: esconder o rótulo dos olhos e mantê-lo no leitor de tela é o
   padrão certo de acessibilidade. O errado era a grade confiar em auto-posicionamento. */
.cx-form__grid > .cx-field > *,
.cx-form-bar > .cx-field > *,
.cx-form-bar > .cx-form-bar__action > * {
  grid-row: 2;
}
.cx-form__grid > .cx-field > .cx-field__label, .cx-form-bar > .cx-field > .cx-field__label {
  grid-row: 1;
  margin-block-end: var(--cx-space-1);
}
/* A LINHA DO RÓTULO (rótulo + ícone de informação, CONSOLE-INFO-1) ocupa a faixa do rótulo, e leva junto a margem
   que o rótulo sozinho carregava: sem esta declaração ela cairia no padrão dos filhos desconhecidos (a faixa do
   CONTROLE) e sentaria em cima do input, que é a linha torta da GRADE-FAIXAS-1 por uma porta nova.
   A da CAIXA DE MARCAR fica na faixa 2 de propósito: ali quem divide a linha com o ícone é o próprio controle. */
.cx-form__grid > .cx-field > .cx-field__labelrow, .cx-form-bar > .cx-field > .cx-field__labelrow {
  grid-row: 1;
  margin-block-end: var(--cx-space-1);
}
.cx-form__grid > .cx-field > .cx-field__checkrow, .cx-form-bar > .cx-field > .cx-field__checkrow {
  grid-row: 2;
}
.cx-form__grid > .cx-field > .cx-field__hint, .cx-form-bar > .cx-field > .cx-field__hint {
  grid-row: 3;
  margin-block-start: var(--cx-space-1);
}
.cx-form__grid > .cx-field > .cx-field__error, .cx-form-bar > .cx-field > .cx-field__error {
  grid-row: 4;
  margin-block-start: var(--cx-space-1);
}

/* Campo que ocupa a linha inteira (endereço, observação, texto longo). */
.cx-field--wide { grid-column: 1 / -1; }

/* TÍTULO DE SUBSEÇÃO dentro da grade (DASH-CONSERTOS-UI-1, reprovado A21): grupo que mistura assuntos ganha
   cortes com nome. O título é IRMÃO dos campos e toma a linha inteira — envolver os campos num div de seção
   colocaria um nível entre a grade e o `.cx-field`, e a subgrade só alcança filho DIRETO: era o formulário torto
   de volta. O respiro extra vai só no título que NÃO abre o corpo, para o primeiro bloco não descolar do
   cabeçalho do cartão. */
.cx-form__grid > .cx-form__subhead {
  grid-column: 1 / -1; margin: 0;
  font-size: var(--cx-text-sm); font-weight: 600; color: var(--cx-color-text);
}
.cx-form__grid > .cx-form__subhead:not(:first-child) { margin-block-start: var(--cx-space-2); }

/* DASH-FORMGRID-1: pilha de caixas de marcar DENTRO da grade de campos. Ela nunca divide linha com um campo de
   texto (a caixa de marcar não tem faixa de rótulo por cima para dividir com o vizinho), então toma a linha
   inteira. Sem isto, os quatro interruptores da política de senha precisavam de um div de span por fora, cada
   um cobrando o gap inteiro da grade entre uma caixa e a seguinte. */
.cx-form__grid > .cx-checks, .cx-form-bar > .cx-checks { grid-column: 1 / -1; }

/* O botão da barra senta na faixa do CONTROLE, nunca na base da caixa. Ele participa da subgrade em vez
   de receber faixa absoluta: assim, quando a barra colapsa para uma coluna (tela estreita), a ação vira
   a própria banda e empilha embaixo, em vez de colidir com o primeiro campo.
   FAIXA e GOTEIRA do slot saem da regra compartilhada com o `.cx-field`, mais acima (GRADE-FAIXAS-2) — é de lá
   que vem a igualdade de topo com o controle vizinho. Aqui fica só o que é PRÓPRIO do slot: ser grade e ser LINHA.
   N BOTÕES EM LINHA (GRADE-FAIXAS-2, reprovação B26). O slot punha todos os filhos na faixa 2 de uma coluna só, e
   dois botões na mesma célula se atropelam: em `/audit/emails` (Filtrar + Limpar) o segundo cobria o primeiro.
   Com fluxo em COLUNA, cada filho da faixa 2 abre a SUA coluna e eles saem lado a lado com o gap padrão. As
   colunas são `auto` de propósito: com um botão só, a coluna única estica e o slot fica com a MESMA largura de
   antes (nada regride nas nove montagens de um botão); com N, o espaço se divide entre eles. Nenhuma medida depende
   do texto do botão. */
.cx-form-bar__action {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: auto;
  column-gap: var(--cx-space-2);
}
.cx-form-bar__action > * { align-self: start; }
/* O botão da barra lê a MESMA altura do campo ao lado: um botão de 44px encostado num campo de 40px é a
   mesma linha torta por outro caminho (FORM-ALTURA-1). */
.cx-form-bar__action > .cx-btn { min-height: var(--cx-control-height); height: var(--cx-control-height); }

/* A LINHA DE BOTÕES QUE QUEBRA (COBR-D4-FIX-1 item 2, achado 2 da prova viva do adendo 177-e).

   O QUE ACONTECIA. Em 1024 os indicadores rolavam DE LADO: 1070px de largura rolável numa janela de 1024, com o
   botão "Ver as linhas" cortado na borda. A medição em Edge headless achou o mesmo defeito em SEIS combinações de
   tela e viewport, e não só na que o dono viu (indicadores/régua e /ROI transbordavam 42px em 1280 e 2px em 1440;
   a lista bruta, 57px em 1024).
   A CONTA, na tela viva a 1024: a barra tem 712px em três faixas de 229,3px, e o slot de ação leva `Aplicar`
   (114px) + `Exportar CSV` (98px) + `Ver as linhas` (79px) mais duas goteiras de 8px — 307px de conteúdo numa
   faixa de 229px. O slot é uma GRADE de fluxo por coluna, e grade NÃO QUEBRA LINHA: os 78px que sobram saem pela
   direita da faixa e, quando a faixa é a última da barra, saem da janela.

   POR QUE NÃO DEU PARA CONSERTAR SÓ NA FOLHA. Quem quebra linha é o FLEX, e um contêiner flex não pode ser
   subgrade. Trocar o slot por flex jogaria fora o mecanismo de faixas da GRADE-FAIXAS-2 (quarta reprovação do
   dono na mesma linha de busca) ou obrigaria a devolver a meia-goteira como NÚMERO, que é exatamente o que
   aquela fatia eliminou. Medimos os dois caminhos no navegador antes de escolher.

   O CONSERTO. O slot fica INTACTO — faixas, goteira e altura, tudo como estava — e a linha que quebra entra
   DENTRO dele. Ela é o filho ÚNICO do slot, então herda a faixa do CONTROLE pela regra que o slot já tem
   (`.cx-form-bar > .cx-form-bar__action > * { grid-row: 2 }`): nenhuma declaração de posição nova aqui, nenhum
   número, e nenhum segundo lugar onde a faixa possa errar. Quando os botões não cabem, o que não coube DESCE e a
   faixa cresce; a barra fica mais alta em vez de mais larga.
   O slot de UM botão só não ganha marcação nova e mede byte a byte o que media antes. */
.cx-form-bar__actionrow {
  display: flex;
  flex-wrap: wrap;
  align-items: start;
  gap: var(--cx-space-2);
}
/* FORM-ALTURA-1 com a marcação nova: o botão deixou de ser filho DIRETO do slot, então a regra de cima não o
   alcança mais. Esta é o par dela, e diz a mesma coisa. */
.cx-form-bar__actionrow > .cx-btn { min-height: var(--cx-control-height); height: var(--cx-control-height); }

/* ---- Caixa de marcar ----
   Substitui o `<label style="display:inline-flex;align-items:center;gap:8px;cursor:pointer">` que sete
   telas repetiam à mão, cada uma com o seu gap. */
.cx-check { display: flex; align-items: center; gap: var(--cx-space-2); cursor: pointer; font-size: var(--cx-text-sm); color: var(--cx-color-text); }
.cx-check__box { inline-size: 1rem; block-size: 1rem; flex: none; margin: 0; accent-color: var(--cx-color-action); }
.cx-check--disabled { color: var(--cx-color-text-muted); cursor: not-allowed; }
.cx-checks { display: grid; gap: var(--cx-space-2); }

/* INTERRUPTOR: a mesma caixa de marcar, desenhada como chave. Ele precisa de :checked, que atributo inline não
   expressa, e por isso vivia num bloco <style> solto DENTRO de uma página do Console, com o comentário dizendo o
   motivo: "fora do skin console.css budgetado". Aquele teto de tamanho não existe mais (CSS-SEM-TETO-1): peça de
   interface se escreve AQUI, no pacote, sem contar bytes. E a marcação que o acompanha ganhou o nome acessível
   que o rótulo vazio de antes não dava. */
.cx-check__switch { position: relative; display: inline-block; inline-size: 42px; block-size: 24px; flex: none; }
.cx-check__switch > .cx-check__box { position: absolute; inset: 0; inline-size: 100%; block-size: 100%; opacity: 0; margin: 0; cursor: pointer; }
.cx-check__track { position: absolute; inset: 0; border-radius: var(--cx-radius-pill); background: var(--cx-color-border); transition: background .15s; }
.cx-check__track::after {
  content: ""; position: absolute; top: 3px; left: 3px; inline-size: 18px; block-size: 18px;
  border-radius: 50%; background: var(--cx-color-surface); box-shadow: var(--cx-shadow-raised); transition: left .15s;
}
.cx-check__box:checked + .cx-check__track { background: var(--cx-color-action); }
.cx-check__box:checked + .cx-check__track::after { left: 21px; }
.cx-check__box:disabled { cursor: default; }
.cx-check__box:disabled + .cx-check__track { background: var(--cx-color-surface-muted); }
.cx-check__box:disabled + .cx-check__track::after { background: var(--cx-color-border); box-shadow: none; }
.cx-check__box:disabled:checked + .cx-check__track { background: var(--cx-color-border); }

/* Grupo de campos com título (fieldset/legend). O Dashboard já emitia `cx-fieldset` sem que a classe existisse
   em folha nenhuma, ou seja, o grupo saía sem moldura e sem respiro (FORM-ALINHAMENTO-1). */
.cx-fieldset {
  border: 1px solid var(--cx-color-border); border-radius: var(--cx-radius-surface);
  padding: var(--cx-space-4); margin: 0; display: grid; gap: var(--cx-space-2);
}
.cx-fieldset > legend { font-size: var(--cx-text-sm); font-weight: 600; color: var(--cx-color-text); padding-inline: var(--cx-space-2); }

/* ---- Badge ---- */
.cx-badge {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: var(--cx-text-xs); font-weight: 700; line-height: 1;
  padding: 4px 10px; border-radius: var(--cx-radius-pill);
  border: 1px solid var(--cx-color-border); background: var(--cx-color-surface-muted); color: var(--cx-color-text);
}
.cx-badge--success { background: var(--cx-color-success-surface); color: var(--cx-color-success); border-color: transparent; }
.cx-badge--warning { background: var(--cx-color-warning-surface); color: var(--cx-color-warning); border-color: transparent; }
.cx-badge--danger  { background: var(--cx-color-danger-surface);  color: var(--cx-color-danger);  border-color: transparent; }
.cx-badge--info    { background: var(--cx-color-info-surface);    color: var(--cx-color-info);    border-color: transparent; }

/* ---- Alerta / toast ---- */
.cx-alert {
  display: flex; align-items: flex-start; gap: var(--cx-space-3);
  padding: var(--cx-space-3) var(--cx-space-4); border-radius: var(--cx-radius-surface);
  border: 1px solid var(--cx-color-border); background: var(--cx-color-surface-muted);
  margin-block-end: var(--cx-space-4);
}
.cx-alert__body { flex: 1; }
.cx-alert__title { font-weight: 700; margin: 0 0 2px; }
.cx-alert__message { margin: 0; }
.cx-alert--success { background: var(--cx-color-success-surface); border-color: transparent; color: var(--cx-color-success); }
.cx-alert--warning { background: var(--cx-color-warning-surface); border-color: transparent; color: var(--cx-color-warning); }
.cx-alert--danger  { background: var(--cx-color-danger-surface);  border-color: transparent; color: var(--cx-color-danger); }
.cx-alert--info    { background: var(--cx-color-info-surface);    border-color: transparent; color: var(--cx-color-info); }
.cx-alert .cx-btn { color: inherit; }

/* ---- Card ---- */
.cx-card {
  background: var(--cx-color-surface-raised); border: 1px solid var(--cx-color-border);
  border-radius: var(--cx-radius-surface); box-shadow: var(--cx-shadow-raised); overflow: hidden;
}
.cx-card__header { padding: var(--cx-space-4) var(--cx-space-5); border-block-end: 1px solid var(--cx-color-border); }
.cx-card__title { margin: 0; font-size: var(--cx-text-lg); }
.cx-card__subtitle { margin: 2px 0 0; color: var(--cx-color-text-muted); font-size: var(--cx-text-sm); }
.cx-card__body { padding: var(--cx-space-5); }
.cx-card__footer { padding: var(--cx-space-4) var(--cx-space-5); border-block-start: 1px solid var(--cx-color-border); display: flex; gap: var(--cx-space-2); justify-content: flex-end; }

/* ---- Stack (coluna de superfícies com respiro) ----
   O .cx-card não carrega margem, então dois cartões concatenados encostavam um no outro (reprovação A17 do dono).
   O respiro do empilhamento é do CONTÊINER, nunca do cartão: mesmo token das colunas de grupo do protótipo. */
.cx-stack { display: flex; flex-direction: column; gap: var(--cx-space-5); min-width: 0; }

/* ---- Empty state ---- */
.cx-empty { text-align: center; padding: var(--cx-space-8) var(--cx-space-4); color: var(--cx-color-text-muted); }
.cx-empty__glyph { font-size: 2.5rem; opacity: .5; }
.cx-empty__title { font-weight: 700; color: var(--cx-color-text); margin: var(--cx-space-2) 0 0; }
.cx-empty__desc { margin: var(--cx-space-1) 0 var(--cx-space-4); }

/* ---- Skeleton ---- */
.cx-skeleton { display: grid; gap: var(--cx-space-2); }
.cx-skeleton__line {
  height: .9rem; border-radius: var(--cx-radius-control);
  background: linear-gradient(90deg, var(--cx-color-surface-muted), var(--cx-color-border), var(--cx-color-surface-muted));
  background-size: 200% 100%; animation: cx-shimmer 1.4s ease-in-out infinite;
}
.cx-skeleton__line:nth-child(even) { width: 80%; }
@keyframes cx-shimmer { from { background-position: 200% 0; } to { background-position: -200% 0; } }

/* ---- Breadcrumb ---- */
.cx-breadcrumb__list { display: flex; flex-wrap: wrap; gap: var(--cx-space-2); list-style: none; padding: 0; margin: 0; font-size: var(--cx-text-sm); }
.cx-breadcrumb__item { display: inline-flex; gap: var(--cx-space-2); color: var(--cx-color-text-muted); }
.cx-breadcrumb__sep { color: var(--cx-color-border); }

/* ---- Stepper ---- */
.cx-stepper { display: flex; flex-wrap: wrap; gap: var(--cx-space-4); list-style: none; padding: 0; margin: 0; }
.cx-stepper__step { display: grid; grid-template-columns: auto 1fr; align-items: center; gap: var(--cx-space-2); color: var(--cx-color-text-muted); }
.cx-stepper__marker {
  display: inline-grid; place-items: center; width: 1.75rem; height: 1.75rem; border-radius: var(--cx-radius-pill);
  border: 2px solid var(--cx-color-border); font-size: var(--cx-text-sm); font-weight: 700;
}
.cx-stepper__step--current { color: var(--cx-color-text); }
.cx-stepper__step--current .cx-stepper__marker { border-color: var(--cx-color-action); color: var(--cx-color-action); }
.cx-stepper__step--done .cx-stepper__marker { background: var(--cx-color-action); border-color: var(--cx-color-action); color: var(--cx-color-text-on-action); }
.cx-stepper__desc { grid-column: 2; font-size: var(--cx-text-xs); }

/* ---- Topbar / sidenav ---- */
/* flex-wrap: num viewport estreito a área à direita (usuário/sair) desce de linha em vez de estourar 100vw. */
.cx-topbar {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--cx-space-5);
  padding: var(--cx-space-3) var(--cx-space-5); background: var(--cx-color-surface);
  border-block-end: 1px solid var(--cx-color-border);
}
.cx-topbar__brand { display: inline-flex; align-items: center; gap: var(--cx-space-2); text-decoration: none; color: var(--cx-color-text); }
.cx-topbar__name { font-weight: 700; font-size: var(--cx-text-lg); }
.cx-topbar__nav ul { display: flex; gap: var(--cx-space-4); list-style: none; margin: 0; padding: 0; }
.cx-topbar__nav a { color: var(--cx-color-text-muted); text-decoration: none; font-weight: 600; }
.cx-topbar__nav a[aria-current="page"] { color: var(--cx-color-action); }
.cx-topbar__trailing { margin-inline-start: auto; }
.cx-topbar__user { overflow-wrap: anywhere; }
.cx-sidenav { background: var(--cx-color-surface); border-inline-end: 1px solid var(--cx-color-border); padding: var(--cx-space-3); min-width: 14rem; }
.cx-sidenav__list { list-style: none; margin: 0; padding: 0; display: grid; gap: 2px; }
.cx-sidenav__link { display: block; padding: var(--cx-space-2) var(--cx-space-3); border-radius: var(--cx-radius-control); color: var(--cx-color-text); text-decoration: none; }
.cx-sidenav__link:hover { background: var(--cx-color-surface-muted); }
.cx-sidenav__link--active { background: var(--cx-color-action-muted); color: var(--cx-color-action); font-weight: 600; }

/* ---- Tabela / paginação ---- */
.cx-table-wrap { overflow-x: auto; }
.cx-table { width: 100%; border-collapse: collapse; background: var(--cx-color-surface); }
.cx-table th, .cx-table td { padding: var(--cx-space-3) var(--cx-space-4); text-align: start; border-block-end: 1px solid var(--cx-color-border); }
.cx-table thead th { font-size: var(--cx-text-sm); color: var(--cx-color-text-muted); }
.cx-table .cx-num { text-align: end; font-variant-numeric: tabular-nums; }
/* (CONSTRANGE-3, item 1) Valor monetário NUNCA quebra: "R$" numa linha e o número na de baixo era a coluna Pago da
   Rolagem a 1440. Quem cede numa tabela apertada é o rótulo da coluna (TableOptions.WrapHeaders) ou a rolagem
   horizontal do .cx-table-wrap, dentro do quadro; nunca o dinheiro. */
.cx-table td.cx-num { white-space: nowrap; }
.cx-pagination { display: flex; align-items: center; gap: var(--cx-space-4); padding: var(--cx-space-3) var(--cx-space-4); }
.cx-pagination__status { color: var(--cx-color-text-muted); font-size: var(--cx-text-sm); }
.cx-pagination a { text-decoration: none; font-weight: 600; }
.cx-pagination .cx-is-disabled { color: var(--cx-color-border); }

/* ---- Modal ---- */
.cx-modal { position: fixed; inset: 0; display: grid; place-items: center; padding: var(--cx-space-4); z-index: 100; }
.cx-modal[hidden] { display: none; }
.cx-modal__backdrop { position: absolute; inset: 0; background: var(--cx-color-scrim); }
.cx-modal__dialog {
  position: relative; width: min(32rem, 100%); background: var(--cx-color-surface-raised);
  border-radius: var(--cx-radius-surface); box-shadow: var(--cx-shadow-overlay); max-height: 90vh; overflow: auto;
}
.cx-modal__header { display: flex; align-items: center; justify-content: space-between; padding: var(--cx-space-4) var(--cx-space-5); border-block-end: 1px solid var(--cx-color-border); }
.cx-modal__title { margin: 0; font-size: var(--cx-text-lg); }
.cx-modal__body { padding: var(--cx-space-5); }
.cx-modal__footer { display: flex; gap: var(--cx-space-2); justify-content: flex-end; padding: var(--cx-space-4) var(--cx-space-5); border-block-start: 1px solid var(--cx-color-border); }

/* ---- Auth ---- */
.cx-auth { min-height: 100vh; display: grid; place-items: center; padding: var(--cx-space-5); }
.cx-auth__card { width: min(24rem, 100%); }
.cx-auth__card.cx-card { padding: var(--cx-space-6); }
.cx-auth__card .cx-card__body { padding: 0; }
.cx-auth__brand { display: flex; justify-content: center; margin-block-end: var(--cx-space-4); }
.cx-auth__heading { text-align: center; font-size: var(--cx-text-xl); margin: 0 0 var(--cx-space-5); }
.cx-auth__desc { color: var(--cx-color-text-muted); margin-block-start: 0; }
/* DASH-FORMGRID-1: o respiro acima do botão era a soma da margem inferior do último campo (space-4) com este
   space-2. Os campos de login e de troca de senha entraram na grade, que ZERA aquela margem, então a soma tinha
   de virar uma coisa só: space-5, que é exatamente o mesmo total de antes. */
.cx-auth__actions { margin-block-start: var(--cx-space-5); }
.cx-auth__aux { text-align: center; margin-block-start: var(--cx-space-4); font-size: var(--cx-text-sm); }

/* ---- Layout utilitário do shell ---- */
.cx-shell { display: grid; grid-template-columns: auto 1fr; min-height: 100vh; }
.cx-shell__main { padding: var(--cx-space-6); }
@media (max-width: 48rem) { .cx-shell { grid-template-columns: 1fr; } .cx-sidenav { display: none; } }

/* ---- Padrões de página (Marco 2) ---- */
.cx-page { display: grid; gap: var(--cx-space-5); }
.cx-page--narrow { max-width: 32rem; }
.cx-page__head { display: flex; align-items: center; gap: var(--cx-space-4); flex-wrap: wrap; }
.cx-page__title { margin: 0; font-size: var(--cx-text-2xl); }
/* Chrome de cartão do filtro. O LAYOUT vem do .cx-form-bar que o acompanha (FORM-ALINHAMENTO-1). */
.cx-filterbar { background: var(--cx-color-surface); border: 1px solid var(--cx-color-border); border-radius: var(--cx-radius-surface); padding: var(--cx-space-4); }
/* DASH-FORMGRID-1: o respiro acima do rodapé de ações subiu de space-2 para space-4. Dentro da grade a margem
   inferior do campo é ZERADA (é a grade quem espaça), então o botão logo abaixo do último campo ficava colado;
   space-4 é exatamente o que a margem do campo dava antes e o mesmo gap de linha da grade. */
.cx-form__actions { display: flex; gap: var(--cx-space-2); justify-content: flex-end; margin-block-start: var(--cx-space-4); }

.cx-tabs__list { display: flex; gap: var(--cx-space-1); border-block-end: 1px solid var(--cx-color-border); }
.cx-tabs__tab { appearance: none; background: transparent; border: 0; border-block-end: 2px solid transparent; font: inherit; font-weight: 600; color: var(--cx-color-text-muted); padding: var(--cx-space-3) var(--cx-space-4); cursor: pointer; }
.cx-tabs__tab[aria-selected="true"] { color: var(--cx-color-action); border-block-end-color: var(--cx-color-action); }
.cx-tabs__panel { padding-block-start: var(--cx-space-4); }

/* min(12rem, 100%): abaixo de ~12rem úteis a trilha encolhe com o contêiner em vez de estourar a tela. */
.cx-kpis { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(12rem, 100%), 1fr)); gap: var(--cx-space-4); }
.cx-kpi { background: var(--cx-color-surface); border: 1px solid var(--cx-color-border); border-radius: var(--cx-radius-surface); padding: var(--cx-space-4); }
.cx-kpi__label { margin: 0; color: var(--cx-color-text-muted); font-size: var(--cx-text-sm); }
.cx-kpi__value { margin: var(--cx-space-1) 0 0; font-size: var(--cx-text-2xl); font-weight: 700; font-variant-numeric: tabular-nums; }
.cx-kpi__delta { margin: var(--cx-space-2) 0 0; }

/* ---- Motion reduzido (aceite de acessibilidade) ---- */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .001ms !important; animation-iteration-count: 1 !important; transition-duration: .001ms !important; }
  .cx-skeleton__line { animation: none; }
}
