/* ============================================================================
   Benta · Design System · componentes
   ----------------------------------------------------------------------------
   Só classes `ds-*`. Nenhum valor cru: tudo sai de `tokens.css`.

   teto: excecao — é o arquivo que o consumidor linka; dividir obrigaria quem
   consome a montar a lista de arquivos, e essa lista é do DS.

   A regra que manda aqui: **o item não permitido sai do HTML**. Não existe
   classe para esconder por CSS o que a pessoa não alcança — quem monta a tela
   simplesmente não emite o item.

   O casco, o Meu Dia e a assistente têm referência no mockup. O que não tinha
   está marcado `derivado` — e derivado aqui significa: composto só de peças que
   já existiam, na mesma gramática.
   ============================================================================ */

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

html { color-scheme: light dark; }
[data-tema="claro"] { color-scheme: light; }
[data-tema="escuro"] { color-scheme: dark; }

body {
  margin: 0;
  background: var(--ds-fundo);
  color: var(--ds-texto);
  font: var(--ds-peso-400) var(--ds-tipo-14) / var(--ds-linha-1-6) var(--ds-fonte);
  -webkit-font-smoothing: antialiased;
}

a { color: var(--ds-marca); text-decoration: none; }
a:hover { color: var(--ds-marca-texto); }

:focus-visible {
  outline: 2px solid var(--ds-foco);
  outline-offset: 1px;
}

.ds-oculto { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }

/* Número é número: alinhado por dígito, sempre. */
.ds-num, .ds-indicador__valor, .ds-tabela td, .ds-tabela th {
  font-variant-numeric: tabular-nums;
}

/* ------------------------------------------------------------- casco -------- */
.ds-casca {
  display: grid;
  grid-template-columns: var(--ds-lateral-largura) minmax(0, 1fr);
  min-height: 100vh;
  background: var(--ds-fundo);
}
.ds-casca--recolhida { grid-template-columns: var(--ds-lateral-recolhida) minmax(0, 1fr); }
.ds-casca--com-assistente {
  grid-template-columns: var(--ds-lateral-largura) minmax(0, 1fr) var(--ds-assistente-largura);
}
/* ⚠️ **As duas classes juntas são o quarto estado do casco, e a ordem decide** (plano `plataforma-07`):
   recolhida **e** com o painel aberto. As duas regras acima valem duas e três colunas, e a última a
   aparecer venceria — sem esta, quem recolhesse a lateral com a Benta aberta veria a coluna voltar a
   `--ds-lateral-largura` (250px no estilo padrão, 240 no limpo), que é o defeito que se vê sem
   entender de onde vem. Medido no navegador: `64px 688px 400px` com o painel aberto e a coluna
   recolhida. */
.ds-casca--recolhida.ds-casca--com-assistente {
  grid-template-columns: var(--ds-lateral-recolhida) minmax(0, 1fr) var(--ds-assistente-largura);
}

.ds-lateral {
  display: flex;
  flex-direction: column;
  gap: var(--ds-esp-16);
  padding: var(--ds-esp-18);
  background: var(--ds-fundo-lateral);
  border-right: 1px solid var(--ds-borda);
  /* ⚠️ **A lateral cola na tela, e não na rolagem da página** (medido no navegador, e é o que o dono
     viu): sem isto, a grade estica a coluna até a altura do **documento**, e o rodapé do usuário
     desce junto com a página. `sticky` + a altura da janela prendem a coluna no lugar, e quem rola
     é o conteúdo à direita. */
  position: sticky;
  top: 0;
  height: 100vh;
}

/* O estilo **padrão** desenha o casco como o mockup: sem barra de topo e sem linha entre a lateral e
   o conteúdo — a lateral é um conjunto de cartões sobre o fundo lavanda, e o título mora no fluxo.
   O `limpo` mantém a barra e a linha, que é o desenho dele. */
[data-estilo="padrao"] .ds-lateral { border-right: 0; }
[data-estilo="padrao"] .ds-topo {
  height: auto;
  align-items: flex-start;
  padding: var(--ds-esp-24) var(--ds-esp-32) 0;
  background: transparent;
  border-bottom: 0;
}
[data-estilo="padrao"] .ds-topo__titulo--compacto { font-size: var(--ds-tipo-24); }
[data-estilo="padrao"] .ds-conteudo { gap: var(--ds-esp-18); padding-top: var(--ds-esp-18); }
.ds-casca--recolhida .ds-lateral { align-items: center; padding: var(--ds-esp-12) 0; }
/* ⚠️ **Recolhida, a marca empilha** (plano `plataforma-07`): o logo em cima e o botão de recolher
   embaixo, cada um com 40px na coluna de 64 — é o desenho do mockup (opção 1b), e é o que faz os
   dois caberem sem estourar a coluna. O nome do cliente sai do lado (não há largura para ele), e
   quem o devolve no hover é o `title` do logo. */
.ds-casca--recolhida .ds-lateral__marca {
  flex-direction: column;
  gap: var(--ds-esp-8);
  padding: var(--ds-esp-12);
}
.ds-casca--recolhida .ds-lateral__nome { display: none; }
/* ⚠️ **O vão do nome escondido não conta** (medido): o `<div>` que embrulha o nome continua filho da
   marca, e o `gap` da coluna ainda o espaçava — 8px a mais entre o logo e o botão (120px de marca
   em vez dos 112 do mockup). Escondido o embrulho, o desenho é o do mockup. */
.ds-casca--recolhida .ds-lateral__marca > div { display: none; }
.ds-casca--recolhida .ds-logo-cliente--cartao { --ds-logo-tamanho: 40px; }

/* O logo do cliente. Hoje é arquivo estático; amanhã vem do cliente ativo.
   Tamanhos medidos no mockup: 88 no login, 44 na lateral expandida,
   40 na recolhida, 38 no cartão da lateral do estilo padrão. */
.ds-logo-cliente {
  display: block;
  flex: none;
  object-fit: contain;
  width: var(--ds-logo-tamanho, 44px);
  height: var(--ds-logo-tamanho, 44px);
}
.ds-logo-cliente--login { --ds-logo-tamanho: 88px; border-radius: var(--ds-raio-caixa); margin-bottom: var(--ds-esp-24); }
.ds-logo-cliente--cartao { --ds-logo-tamanho: 38px; }
[data-tema="escuro"] .ds-logo-cliente { background: #FFFFFF; padding: 2px; }

/* Só a marca do produto. Nunca o logo do cliente. */
.ds-logo-benta { display: block; width: 180px; height: auto; }

.ds-lateral__marca {
  display: flex;
  align-items: center;
  gap: var(--ds-esp-10);
  padding: var(--ds-esp-14);
  background: var(--ds-superficie);
  border-radius: var(--ds-raio-caixa);
  box-shadow: var(--ds-sombra-caixa);
}
.ds-lateral__nome {
  font: var(--ds-peso-700) var(--ds-tipo-13) / var(--ds-linha-1-25) var(--ds-fonte);
  color: var(--ds-texto);
}

/* **O botão de recolher e expandir** — o do mockup, e ele mora **na marca**, no topo da coluna
   (plano `plataforma-07`; a `casca.md` diz onde ele fica). Os dois desenhos são os do mockup, um por
   estado, e quem escolhe qual aparece é a **classe do casco**, e não script: sem JavaScript, o
   desenho do estado certo já está na tela — o mesmo raciocínio do painel e do menu do usuário.

   `margin-left: auto` empurra o botão para o canto direito da linha (é onde o mockup o desenha), e
   na recolhida ele volta a ser centralizado, porque a marca virou uma coluna. */
.ds-lateral__recolher {
  display: flex;
  align-items: center;
  justify-content: center;
  flex: none;
  margin-left: auto;
  width: var(--ds-esp-40);
  height: var(--ds-esp-40);
  border: 0;
  background: transparent;
  color: var(--ds-texto-3);
  cursor: pointer;
}
.ds-lateral__recolher:hover { color: var(--ds-texto); }
.ds-lateral__recolher svg { width: 18px; height: 18px; }
.ds-lateral__recolher--expandir { display: none; }
.ds-casca--recolhida .ds-lateral__recolher { margin-left: 0; }
.ds-casca--recolhida .ds-lateral__recolher--recolher { display: none; }
.ds-casca--recolhida .ds-lateral__recolher--expandir { display: block; }

/* O nav é quem rola: com muitos itens, os menus descem **dentro** da coluna, e o bloco do usuário
   continua no lugar. `min-height: 0` é o que deixa um filho de flex encolher e rolar em vez de
   esticar o pai — sem ele, a coluna cresce e o rodapé sai da tela. */
.ds-nav { display: flex; flex-direction: column; gap: var(--ds-esp-2); margin: 0; padding: 0; list-style: none; flex: 1; min-height: 0; overflow-y: auto; }
.ds-nav__grupo {
  padding: var(--ds-esp-14) var(--ds-esp-12) var(--ds-esp-4);
  font: var(--ds-peso-700) var(--ds-tipo-11) var(--ds-fonte);
  letter-spacing: var(--ds-letra-rotulo);
  text-transform: uppercase;
  color: var(--ds-rotulo-grupo);
}
.ds-nav__item {
  display: flex;
  align-items: center;
  gap: var(--ds-esp-10);
  height: var(--ds-esp-44);
  padding: 0 var(--ds-esp-14);
  border-radius: var(--ds-raio);
  color: var(--ds-texto-3);
  font: var(--ds-peso-500) var(--ds-tipo-14) var(--ds-fonte);
  /* O balão do hover é `absolute` e nasce **dentro** do item: sem isto quem o posiciona é o
     ancestral posicionado mais perto (a `.ds-lateral`, que é `sticky`), e o balão de todo item
     sairia no mesmo lugar — colado no topo da coluna. */
  position: relative;
}
.ds-nav__item:hover { background: var(--ds-superficie-alta); }
.ds-nav__item--ativo {
  background: var(--ds-selecao-fundo);
  color: var(--ds-selecao-texto);
  font-weight: var(--ds-peso-700);
  box-shadow: inset 2px 0 0 var(--ds-selecao-borda);
}
.ds-nav__item svg { flex: none; width: 17px; height: 17px; }

/* Recolhida: ícone só, com o rótulo em balão no hover. */
/* ⚠️ **A caixa voltou a ser quadrada** (plano `plataforma-07`, e é medida): o item aberto tem a
   altura de `--ds-esp-44` (a linha do rótulo), e recolhido o mockup desenha 40×40 — medido no
   navegador, 40×44 viravam quatro pixels de folga por item na coluna de 64. */
.ds-casca--recolhida .ds-nav__item {
  justify-content: center;
  width: var(--ds-esp-40);
  height: var(--ds-esp-40);
  padding: 0;
}
.ds-casca--recolhida .ds-nav__grupo { display: none; }
/* ⚠️ **A inicial do item fica de fora, e ela é a exceção declarada desta regra** (plano
   `plataforma-07`): o rótulo sai do lado (ele é o `span` sem classe), e o que sobra é o desenho — ou
   a **inicial**, na tela que não declarou ícone. Sem o segundo `:not`, a inicial era escondida pela
   mesma regra que esconde o rótulo, e a caixa saía vazia. */
.ds-casca--recolhida .ds-nav__item > span:not(.ds-balao):not(.ds-nav__inicial) { display: none; }
.ds-balao {
  position: absolute;
  left: var(--ds-esp-56);
  white-space: nowrap;
  display: none;
  padding: var(--ds-esp-6) var(--ds-esp-10);
  background: var(--ds-texto);
  color: var(--ds-fundo);
  box-shadow: var(--ds-sombra-menu);
  font-weight: var(--ds-peso-500);
  z-index: var(--ds-camada-menu);
}
.ds-casca--recolhida .ds-nav__item:hover .ds-balao { display: block; }

/* **A inicial de quem não tem ícone** (plano `plataforma-07`): a tela de plugin entra assim enquanto
   o manifesto não tiver onde declarar o desenho dela (§3). É o mesmo desenho que o mockup usa para a
   **pessoa** no bloco do usuário recolhido (`EN`), e ele só existe na recolhida — aberta, o rótulo
   inteiro está lá, e uma letra ao lado dele seria ruído. */
.ds-nav__inicial {
  display: none;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 20px;
  font: var(--ds-peso-700) var(--ds-tipo-12) / 1 var(--ds-fonte);
}
.ds-casca--recolhida .ds-nav__inicial { display: flex; }

.ds-lateral__rodape { position: relative; margin-top: auto; border-top: 1px solid var(--ds-borda); }
/* O bloco do usuário é um `<details>`: quem abre e fecha é o **navegador**, e é isso que mantém o
   `Sair` alcançável com o script bloqueado (decisão 201). O `<summary>` é o cartão, e o marcador
   nativo sai das duas engines. */
.ds-lateral__rodape > summary { list-style: none; }
.ds-lateral__rodape > summary::-webkit-details-marker { display: none; }
/* O menu do usuário abre **para cima**, ancorado na largura do rodapé — é assim que o mockup o
   desenha: o cartão do usuário fica na base da lateral, e o menu sobe por cima dele. */
.ds-lateral__rodape .ds-menu { position: absolute; left: 0; right: 0; bottom: calc(100% + var(--ds-esp-8)); }
/* ⚠️ Medido: o `position: absolute` **escapa** do fechado do `<details>` — o menu flutuava aberto
   antes de alguém clicar. Quem o esconde é o estado do próprio `details` (`[open]`), e por isso a
   regra é esta, e não um `x-show` que depende de script. */
.ds-lateral__rodape:not([open]) .ds-menu { display: none; }
.ds-lateral__rodape[open] .ds-usuario > svg { transform: rotate(180deg); }
/* No padrão ele é o **cartão** do rodapé do mockup (o do usuário): sem linha, com fundo e sombra —
   e **sem preenchimento próprio**, porque quem preenche é o `summary` dentro dele. Os dois
   preenchimentos somados davam um cartão mais alto que o mockup. */
[data-estilo="padrao"] .ds-lateral__rodape {
  padding: 0;
  background: var(--ds-superficie);
  border-top: 0;
  border-radius: var(--ds-raio-caixa);
  box-shadow: var(--ds-sombra-caixa);
}
.ds-usuario {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--ds-esp-8);
  width: 100%;
  min-height: var(--ds-esp-56);
  padding: var(--ds-esp-12) var(--ds-esp-14);
  border: 0;
  background: transparent;
  border-radius: var(--ds-raio-caixa);
  text-align: left;
  cursor: pointer;
}
.ds-usuario__nome { display: block; font: var(--ds-peso-700) var(--ds-tipo-13) / var(--ds-linha-1-3) var(--ds-fonte); color: var(--ds-texto); }
.ds-usuario__papel { display: block; font: var(--ds-peso-400) var(--ds-tipo-12) / var(--ds-linha-1-3) var(--ds-fonte); color: var(--ds-texto-3); }
.ds-usuario > svg { flex: none; width: 16px; height: 16px; color: var(--ds-texto-3); }
/* **Recolhida, quem assina o bloco são as iniciais** (plano `plataforma-07`), e o desenho é o do
   mockup: uma caixa de 40px com borda e as letras no meio (`EN`, para *Elanilze Natividade*). O nome
   e os papéis saem do lado, e o nome **inteiro** volta no `title` do `<summary>` — é o que o mockup
   também faz. O chevron do menu sai junto: com 40px, ele não cabe, e quem diz que o bloco abre é o
   próprio cartão. */
.ds-usuario__inicial {
  display: none;
  align-items: center;
  justify-content: center;
  flex: none;
  width: var(--ds-esp-40);
  height: var(--ds-esp-40);
  border: 1px solid var(--ds-borda-forte);
  color: var(--ds-texto);
  font: var(--ds-peso-600) var(--ds-tipo-13) var(--ds-fonte);
}
.ds-casca--recolhida .ds-usuario { justify-content: center; padding: 0; min-height: var(--ds-esp-40); }
.ds-casca--recolhida .ds-usuario > span:not(.ds-usuario__inicial) { display: none; }
.ds-casca--recolhida .ds-usuario > svg { display: none; }
.ds-casca--recolhida .ds-usuario__inicial { display: flex; }

.ds-menu {
  background: var(--ds-superficie);
  border: 1px solid var(--ds-borda-forte);
  border-radius: var(--ds-raio-caixa);
  box-shadow: var(--ds-sombra-menu);
  overflow: hidden;
}
.ds-menu__item {
  display: flex;
  align-items: center;
  gap: var(--ds-esp-10);
  width: 100%;
  height: var(--ds-esp-40);
  padding: 0 var(--ds-esp-14);
  border: 0;
  border-bottom: 1px solid var(--ds-borda);
  background: transparent;
  color: var(--ds-texto);
  font: var(--ds-peso-400) var(--ds-tipo-14) var(--ds-fonte);
  /* O item é **link ou botão** — o `Sair` é `POST`, e o resto é `GET` —, e os dois precisam do
     mesmo desenho: sem isto o botão sai com o cinza do sistema e alinhado ao centro. */
  text-align: left;
  cursor: pointer;
}
.ds-menu__item:hover { background: var(--ds-superficie-alta); }
.ds-menu__item:last-child { border-bottom: 0; }
.ds-menu__alternador { justify-content: space-between; height: var(--ds-esp-44); }

/* Claro e escuro são dois desenhos. O alternador escolhe um, não filtra o outro. */
.ds-alternador { display: flex; border: 1px solid var(--ds-borda-forte); }
.ds-alternador__opcao {
  padding: var(--ds-esp-4) var(--ds-esp-10);
  color: var(--ds-texto-3);
  font: var(--ds-peso-400) var(--ds-tipo-13) var(--ds-fonte);
  /* A opção é **botão**: ela troca o atributo no `<html>`, e não navega. */
  border: 0;
  background: transparent;
  cursor: pointer;
}
.ds-alternador__opcao--escolhida {
  background: var(--ds-selecao-texto);
  color: var(--ds-superficie);
  font-weight: var(--ds-peso-600);
}

.ds-principal { display: flex; flex-direction: column; min-width: 0; }

.ds-topo {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--ds-esp-24);
  height: var(--ds-topo-altura);
  flex: none;
  padding: 0 var(--ds-esp-32);
  background: var(--ds-fundo-topo);
  border-bottom: 1px solid var(--ds-borda);
}
.ds-topo__titulo { font: var(--ds-peso-700) var(--ds-tipo-24) var(--ds-fonte); color: var(--ds-texto); }
.ds-topo__titulo--compacto { font-size: var(--ds-tipo-17); font-weight: var(--ds-peso-600); }
.ds-topo__recorte { font: var(--ds-peso-400) var(--ds-tipo-13) var(--ds-fonte); color: var(--ds-texto-3); }

/* **O conteúdo rola.** Era `overflow: hidden`, e o que não cabia era cortado em silêncio: a coluna
   de conteúdo de uma tela densa perde a largura do painel (`--ds-assistente-largura`), e a última
   coluna da tabela de preço do `/custo/` ficava inalcançável — é o defeito medido no navegador do
   dono em 24/09/2026. Quem rola é o conteúdo; o casco (lateral, topo, painel) continua parado.

   ⚠️ **Isto não dá rolagem dupla a ninguém:** o painel da Benta e a barra de mobile moram **fora**
   desta caixa, e cada um tem o seu próprio recipiente. Quem rola dentro deles é **um filho só**,
   pela regra da casa escrita no `.ds-assistente__fio`: o item que rola não cresce além do pai
   (`min-height: 0` + `flex: 1`). */
.ds-conteudo {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: var(--ds-esp-20);
  padding: var(--ds-esp-24) var(--ds-esp-32) var(--ds-esp-28);
  overflow: auto;
}

.ds-rodape {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--ds-esp-16);
  height: var(--ds-rodape-altura);
  flex: none;
  padding: 0 var(--ds-esp-32);
  background: var(--ds-fundo-topo);
  border-top: 1px solid var(--ds-borda);
}
.ds-rodape__frescor { font: var(--ds-peso-400) var(--ds-tipo-13) var(--ds-fonte); color: var(--ds-texto-fraco); }
.ds-rodape__assinatura { font: var(--ds-peso-400) var(--ds-tipo-13) var(--ds-fonte); color: var(--ds-marca); }

/* ------------------------------------------------------- tipografia --------- */
.ds-rotulo {
  display: block;
  font: var(--ds-peso-700) var(--ds-tipo-13) var(--ds-fonte);
  letter-spacing: var(--ds-letra-rotulo);
  text-transform: uppercase;
  color: var(--ds-rotulo);
}
.ds-rotulo--escuro { color: var(--ds-texto); }
.ds-titulo-tela { margin: 0; font: var(--ds-peso-700) var(--ds-tipo-24) var(--ds-fonte); color: var(--ds-texto); }
.ds-subtitulo-tela { font: var(--ds-peso-400) var(--ds-tipo-13) var(--ds-fonte); color: var(--ds-texto-3); }
.ds-texto { font: var(--ds-peso-400) var(--ds-tipo-14) / var(--ds-linha-1-6) var(--ds-fonte); color: var(--ds-texto-2); }
.ds-texto--fraco { color: var(--ds-texto-fraco); }

/* A procedência de todo número. Nenhum número aparece sem esta linha. */
.ds-fonte {
  display: block;
  font: var(--ds-peso-400) var(--ds-tipo-13) / var(--ds-linha-1-5) var(--ds-fonte);
  color: var(--ds-texto-fraco);
}

/* ---------------------------------------------------------- seção ----------- */
.ds-secao { display: flex; flex-direction: column; }
.ds-secao__cabecalho {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--ds-esp-16);
  padding-bottom: var(--ds-esp-10);
  border-bottom: 2px solid var(--ds-borda-secao);
}
.ds-secao__contagem { font: var(--ds-peso-400) var(--ds-tipo-13) var(--ds-fonte); color: var(--ds-texto-fraco); }

/* ---------------------------------------------------------- cartão ---------- */
.ds-cartao {
  display: flex;
  flex-direction: column;
  /* O respiro entre o que mora dentro: sem ele, o formulário, a tabela e a faixa ficam colados —
     que é o defeito que a tela de Autorização mostrou no padrão. Os cartões do mockup são colunas. */
  gap: var(--ds-esp-16);
  background: var(--ds-superficie);
  border: 1px solid var(--ds-borda);
  border-radius: var(--ds-raio-cartao);
  box-shadow: var(--ds-sombra);
  padding: var(--ds-esp-22) var(--ds-esp-24);
}
.ds-cartao--caixa { border-radius: var(--ds-raio-caixa); box-shadow: var(--ds-sombra-caixa); }
.ds-cartao--sem-preenchimento { padding: 0; overflow: hidden; }
.ds-cartao__divisor { height: 1px; background: var(--ds-borda-secao); margin: var(--ds-esp-14) 0; }
/* `.ds-pilha`: a **mesma** folga do cartão, um nível abaixo.

   ⚠️ **Ela existe porque o bloco de fragmento é um filho só.** O `.ds-cartao` empilha os filhos
   diretos, mas o que vem de um fragmento mora dentro da **região** (o `div` que a troca parcial
   usa como alvo) — e o formulário de criar e a tabela que estão lá dentro ficavam colados, um
   encostado no outro, que é metade do "embolado" que o dono viu. A pilha é a folga do cartão
   dentro da região, e ela **viaja com a região**: a troca parcial substitui o conteúdo, não o
   `div`, então a classe continua lá depois de cada `POST`. */
.ds-pilha { display: flex; flex-direction: column; gap: var(--ds-esp-16); }

/* --------------------------------------------------------- indicador -------- */
.ds-indicador__valor {
  display: block;
  margin-top: var(--ds-esp-8);
  font: var(--ds-peso-700) var(--ds-tipo-44) / var(--ds-linha-1) var(--ds-fonte);
  color: var(--ds-texto);
}
.ds-indicador__variacao { display: block; margin-top: var(--ds-esp-10); font: var(--ds-peso-500) var(--ds-tipo-13) var(--ds-fonte); color: var(--ds-texto-2); }
.ds-indicador__variacao--ok { color: var(--ds-ok); }
.ds-indicador__variacao--atencao { color: var(--ds-atencao); }
.ds-indicador__variacao--negativo { color: var(--ds-negativo); }

/* O bloco do dia: um número grande, uma régua, três números menores. */
.ds-painel-numeros { display: flex; gap: var(--ds-esp-56); align-items: flex-start; }
.ds-painel-numeros__regua { width: 1px; align-self: stretch; background: var(--ds-borda-secao); }
.ds-painel-numeros__grupo { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--ds-esp-28); flex: 1; min-width: 0; }
.ds-painel-numeros__item .ds-valor-menor {
  display: block; margin-top: var(--ds-esp-6);
  font: var(--ds-peso-700) var(--ds-tipo-26) / var(--ds-linha-1) var(--ds-fonte);
  color: var(--ds-texto);
}

/* ----------------------------------------------------- o que mudou ---------- */
.ds-mudanca {
  display: grid;
  grid-template-columns: var(--ds-esp-16) minmax(0, 1fr) 140px 150px 220px;
  align-items: center;
  gap: var(--ds-esp-16);
  padding: var(--ds-esp-14) var(--ds-esp-20);
  border-bottom: 1px solid var(--ds-borda-secao);
}
.ds-mudanca:last-child { border-bottom: 0; }
.ds-mudanca__marca { width: 10px; height: 10px; background: var(--ds-texto-fraco); }
.ds-mudanca__marca--ok { background: var(--ds-ok); }
.ds-mudanca__marca--atencao { background: var(--ds-atencao); }
.ds-mudanca__marca--negativo { background: var(--ds-negativo); }
.ds-mudanca__texto { font: var(--ds-peso-400) var(--ds-tipo-14) var(--ds-fonte); color: var(--ds-texto); }
.ds-mudanca__valor { font: var(--ds-peso-500) var(--ds-tipo-14) var(--ds-fonte); text-align: right; color: var(--ds-texto-2); }
.ds-mudanca__valor--ok { color: var(--ds-ok); }
.ds-mudanca__valor--atencao { color: var(--ds-atencao); }
.ds-mudanca__valor--negativo { color: var(--ds-negativo); }
.ds-mudanca__detalhe { font: var(--ds-peso-400) var(--ds-tipo-13) var(--ds-fonte); color: var(--ds-texto-3); }
/* A linha que a assistente está discutindo. */
.ds-mudanca--em-foco { outline: 2px solid var(--ds-marca); outline-offset: -2px; }

/* ----------------------------------------------------- cartão de decisão ---- */
.ds-decisoes { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--ds-esp-16); }
.ds-cartao-decisao { display: flex; flex-direction: column; gap: var(--ds-esp-10); }
.ds-cartao-decisao__topo { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--ds-esp-10); }
.ds-cartao-decisao__titulo { font: var(--ds-peso-700) var(--ds-tipo-15) / var(--ds-linha-1-4) var(--ds-fonte); color: var(--ds-texto); }
.ds-cartao-decisao__acoes { display: flex; flex: none; gap: var(--ds-esp-6); }
.ds-cartao-decisao > .ds-botao { margin-top: auto; }

/* ---------------------------------------------------------- botão ----------- */
.ds-botao {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--ds-esp-8);
  height: var(--ds-esp-40);
  padding: 0 var(--ds-esp-14);
  border: 1px solid transparent;
  border-radius: var(--ds-raio-botao);
  cursor: pointer;
  font: var(--ds-peso-700) var(--ds-tipo-14) var(--ds-fonte);
  text-align: left;
}
.ds-botao--primario { background: var(--ds-acao); color: var(--ds-acao-texto); }
.ds-botao--primario:hover { background: var(--ds-acao-hover); }
.ds-botao--secundario {
  background: transparent;
  border-color: var(--ds-borda-forte);
  color: var(--ds-texto-2);
}
.ds-botao--secundario:hover { background: var(--ds-superficie-alta); }
.ds-botao--discreto { height: var(--ds-esp-36); padding: 0 var(--ds-esp-12); background: var(--ds-superficie-alta); border-color: var(--ds-borda-secao); color: var(--ds-texto-2); }
/* O botão de **ícone** do mockup (30×30, raio 9): é ele que carrega o pin do Meu Dia — fixar e
   tirar. O rótulo vai no `title`/`aria-label`, porque ícone sem nome é ícone que ninguém lê. */
.ds-botao--icone {
  width: var(--ds-esp-30);
  height: var(--ds-esp-30);
  padding: 0;
  border-radius: var(--ds-raio-icone);
  background: var(--ds-superficie-alta);
  border-color: var(--ds-borda-secao);
  color: var(--ds-texto-2);
}
.ds-botao--icone svg { width: 14px; height: 14px; }
.ds-botao--bloco { width: 100%; }
.ds-botao--grande { height: var(--ds-esp-52); border-radius: var(--ds-raio); }

/* A assistente tem cor própria, e só ela a usa. */
.ds-botao--assistente {
  height: var(--ds-esp-48);
  padding: 0 var(--ds-esp-18) 0 var(--ds-esp-8);
  border-radius: var(--ds-raio-pilula);
  background: var(--ds-assistente-fundo);
  border-color: var(--ds-assistente-borda);
  color: var(--ds-assistente-texto);
  box-shadow: var(--ds-sombra-assistente);
}
.ds-botao--assistente img { width: 34px; height: 34px; border-radius: 50%; object-fit: cover; }
.ds-icone-assistente {
  width: var(--ds-esp-36);
  height: var(--ds-esp-36);
  border: 0;
  border-radius: var(--ds-raio-icone);
  padding: 0;
  background: transparent;
  cursor: pointer;
}
.ds-icone-assistente img { width: 100%; height: 100%; border-radius: var(--ds-raio-icone); object-fit: cover; }

/* ---------------------------------------------------------- campo ----------- */
.ds-campo { display: block; }
.ds-campo__rotulo {
  display: block;
  margin-bottom: var(--ds-esp-8);
  font: var(--ds-peso-700) var(--ds-tipo-12) var(--ds-fonte);
  letter-spacing: var(--ds-letra-rotulo);
  text-transform: uppercase;
  color: var(--ds-rotulo);
}
.ds-campo__entrada {
  width: 100%;
  height: var(--ds-esp-52);
  padding: 0 var(--ds-esp-18);
  border: 1px solid var(--ds-borda);
  border-radius: var(--ds-raio);
  background: var(--ds-superficie-alta);
  color: var(--ds-texto);
  font: var(--ds-peso-400) var(--ds-tipo-15) var(--ds-fonte);
}
.ds-campo__entrada:focus-visible { outline: 2px solid var(--ds-foco); outline-offset: 1px; }
.ds-campo__aviso { display: block; margin-top: var(--ds-esp-10); font: var(--ds-peso-400) var(--ds-tipo-13) / var(--ds-linha-1-6) var(--ds-fonte); color: var(--ds-texto-fraco); }
/* `.ds-campo--linha`: o campo **curto** ao lado do botão — a ação que vive dentro de uma linha de
   tabela (renomear papel, liberar bloqueio).

   ⚠️ **Ele existe por medição, e o defeito era visível.** `.ds-campo__entrada` é `width: 100%`,
   e numa célula de tabela os `100%` são a largura que a tabela deu à **coluna**: o campo esticava
   até o fim dela, encostava na coluna vizinha e jogava o botão para a linha de baixo — a tela de
   Autorização "embolada". Na linha, o campo tem largura **declarada** e para de crescer; a
   etiqueta não encolhe; e o campo e o botão se alinham pelo pé, que é a base do campo.

   ⚠️ **E a folga dele subiu de 8 para 12 em 25/09**, a pedido do dono (*"aumente um pouco o respiro
   entre os inputs e botões"*): no desenho lado a lado, oito pixels deixavam o botão encostado no
   campo. A folga do **empilhado** é a da `.ds-pilha` (16, a mesma do cartão) — e ela não chega à
   tela quando o mesmo elemento também carrega `.ds-campo`, que é `display: block` e vem depois
   deste arquivo (o porquê está na `.ds-pilha`, acima). */
.ds-campo--linha {
  display: flex;
  flex-direction: row;
  align-items: flex-end;
  gap: var(--ds-esp-12);
  white-space: nowrap;
}
.ds-campo--linha .ds-campo { flex: none; }
.ds-campo--linha .ds-campo__entrada { width: var(--ds-campo-curto); }

/* `.ds-campos`: o **formulário de vários campos** — a grade que **quebra** em linhas.

   ⚠️ **Ele existe por medição, e o defeito era visível.** O formulário do preço da `/custo/` nasceu
   com `.ds-campo--linha` — que é o desenho da **ação curta dentro de uma linha de tabela**, o campo
   em largura declarada e o botão ao lado — e dez campos: medido em 24/09/2026 na sonda
   `var/probe-custo.html`, ele pedia **3061px** numa caixa de 446px, e a coluna de conteúdo rolava
   **3262px** em vez de 560px. Aqui os campos **descem**: quem não cabe na linha vai para a de baixo,
   e a caixa para de esticar.

   O mínimo é o de **um campo**, e mora no token (`--ds-campos-minima`) — a mesma doutrina da
   `.ds-concessoes`: um número fixo no componente reprova, porque o que cabe numa tela não cabe na
   outra, e a grade é quem responde por isso.

   `align-items: end` alinha a **ação** pelo pé do campo: o botão tem altura própria e, sem isto, ele
   flutua no meio da linha enquanto os campos ficam na base. `derivado`: o mockup não tem formulário
   de vários campos em grade; a peça compõe a grade da `.ds-concessoes` com o campo da casa. */
.ds-campos {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(var(--ds-campos-minima), 1fr));
  gap: var(--ds-esp-16);
  align-items: end;
}

/* O código de 6 dígitos: uma casa por dígito, e a casa vazia é visível. */
.ds-codigo { display: flex; gap: var(--ds-esp-10); }
.ds-codigo__casa {
  width: 70px;
  height: 84px;
  /* ⚠️ `text-align: center`, e **não** o flex do mockup: lá a casa é uma `div` com
     `align-items`/`justify-content`, e num `input` o flex não centraliza nada — o campo não tem
     filho para centralizar, e o dígito ficava colado na borda esquerda (medido no navegador).
     O eixo vertical o próprio campo resolve: `input` de uma linha centraliza o texto na altura. */
  text-align: center;
  /* Os dígitos têm a mesma largura, como no mockup: sem isto, o número "dança" a cada troca. */
  font-variant-numeric: tabular-nums;
  border: 1px solid var(--ds-borda-secao);
  border-radius: var(--ds-raio);
  background: var(--ds-superficie-alta);
  font: var(--ds-peso-700) var(--ds-tipo-38) var(--ds-fonte);
  color: var(--ds-texto);
}
.ds-codigo__casa--cheia { border-color: var(--ds-borda); }
.ds-codigo__casa--atual { border-color: var(--ds-texto); outline: 2px solid var(--ds-foco); outline-offset: 1px; }
/* Sem script, quem diz o estado da casa é o **próprio campo**: `:focus` é a casa atual, e
   `:not(:placeholder-shown)` é a cheia — é o `placeholder=" "` do template que faz a diferença
   existir sem JavaScript. As classes (`--atual`, `--cheia`) ficam para quem as preferir. */
.ds-codigo__casa:focus { border-color: var(--ds-texto); outline: 2px solid var(--ds-foco); outline-offset: 1px; }
.ds-codigo__casa:not(:placeholder-shown) { border-color: var(--ds-borda); }
.ds-codigo__casa:focus:not(:placeholder-shown) { border-color: var(--ds-texto); }

/* --------------------------------------------------------- farol/selo ------- */
.ds-farol { display: flex; align-items: center; gap: var(--ds-esp-8); font: var(--ds-peso-400) var(--ds-tipo-13) var(--ds-fonte); color: var(--ds-texto-2); }
.ds-farol__marca { width: 10px; height: 10px; flex: none; background: var(--ds-texto-fraco); }
.ds-farol--ok .ds-farol__marca { background: var(--ds-ok); }
.ds-farol--atencao .ds-farol__marca { background: var(--ds-atencao); }
.ds-farol--negativo .ds-farol__marca { background: var(--ds-negativo); }

.ds-selo {
  display: inline-flex;
  align-items: center;
  padding: var(--ds-esp-6) var(--ds-esp-12);
  border-radius: var(--ds-raio-chip);
  font: var(--ds-peso-700) var(--ds-tipo-12) var(--ds-fonte);
  background: var(--ds-superficie-alta);
  color: var(--ds-texto-2);
}
.ds-selo--ok { background: var(--ds-ok-fundo); color: var(--ds-ok-texto); }
.ds-selo--atencao { background: var(--ds-atencao-fundo); color: var(--ds-atencao-texto); }
.ds-selo--negativo { background: var(--ds-negativo-fundo); color: var(--ds-negativo-texto); }

/* `.ds-chips`: o **conjunto** de pílulas — a folga entre elas mora aqui, e não em cada pílula.

   ⚠️ Medido no navegador: duas pílulas seguidas ficavam a **4px** uma da outra, que é a largura do
   espaço entre as etiquetas no HTML — é o que faz o conjunto parecer colado. Margem em cada pílula
   resolveria este caso e sujaria o próximo (a pílula do topo, sozinha, ganharia margem à toa): a
   folga é **do conjunto**, como no `.ds-decisoes` e na `.ds-pilha`. */
.ds-chips { display: flex; flex-wrap: wrap; gap: var(--ds-esp-8); }

.ds-chip {
  display: inline-flex;
  align-items: center;
  padding: var(--ds-esp-8) var(--ds-esp-11);
  border: 1px solid var(--ds-borda-forte);
  border-radius: var(--ds-raio);
  font: var(--ds-peso-400) var(--ds-tipo-13) var(--ds-fonte);
  color: var(--ds-texto-2);
  background: transparent;
}

/* `.ds-chip--acao`: a pílula que **é** o gesto — o `×` que tira o papel da pessoa (passo 5 do
   `plataforma-08`).

   ⚠️ **Ele existe porque a pílula é o item do vínculo, e o D16 pede o caminho de volta no mesmo
   item.** A pílula continua sendo pílula (mesma forma, mesma cor), e o que o modificador acrescenta
   é o que o `<button>` não herda: o cursor de quem clica e o hover que diz que ela responde. Sem
   isto, o `×` pareceria decoração — e o gesto de tirar virava adivinhação.

   O `gap` é o do próprio glifo: o nome e o `×` são dois pedaços do mesmo rótulo, e sem folga o `×`
   encosta na última letra. */
.ds-chip--acao {
  gap: var(--ds-esp-6);
  cursor: pointer;
}
.ds-chip--acao:hover { background: var(--ds-superficie-alta); }

/* ---------------------------------------------------------- tabela ---------- */
/* **A largura mínima da tabela é a dos rótulos.** O título da coluna não quebra, então a coluna
   encolhe até ele e não além: é o que impede o título de virar três linhas — o defeito medido em
   24/09/2026, o `ENTRADA · CACHE HIT` saindo em três — e o que faz a tabela **pedir** a rolagem do
   `.ds-conteudo` em vez de espremer as colunas.

   Medido no navegador (24/09/2026, sem a fonte Sora, na coluna de 716px): o mínimo de cada tabela
   é o `min-content` dela, que é o que a regra passa a valer — **1113px** na tabela de preço do
   `/custo/` (oito colunas, a que o dono viu cortada), **632px** na do Meu Dia (seis) e **362px** na
   de chave e valor do `/custo/` (quatro). As duas últimas cabem nos 716px, e é o que importa.

   ⚠️ E é por isso que o mínimo é **por rótulo**, e não um número fixo no `.ds-tabela`: um
   `min-width` de 1113px faria a tabela do Meu Dia — que cabe — rolar para sempre, e o conserto de
   uma tela viraria defeito em todas. */
.ds-tabela { width: 100%; border-collapse: collapse; background: var(--ds-superficie); }
.ds-tabela th {
  padding: var(--ds-esp-10) var(--ds-esp-16);
  border-bottom: 1px solid var(--ds-borda-forte);
  font: var(--ds-peso-700) var(--ds-tipo-13) var(--ds-fonte);
  letter-spacing: var(--ds-letra-tabela);
  text-transform: uppercase;
  color: var(--ds-rotulo);
  text-align: left;
  white-space: nowrap;
}
.ds-tabela th.ds-num, .ds-tabela td.ds-num { text-align: right; }
.ds-tabela td {
  padding: var(--ds-esp-11) var(--ds-esp-16);
  border-bottom: 1px solid var(--ds-borda-secao);
  font: var(--ds-peso-400) var(--ds-tipo-14) var(--ds-fonte);
  color: var(--ds-texto);
}
.ds-tabela td.ds-num--forte { font-weight: var(--ds-peso-500); }
.ds-tabela td.ds-num--negativo { color: var(--ds-negativo); }
.ds-tabela tfoot td {
  border-top: 2px solid var(--ds-borda-forte);
  border-bottom: 0;
  font-weight: var(--ds-peso-700);
}
.ds-tabela--densa td { padding: var(--ds-esp-10) var(--ds-esp-12); }
/* Célula sem dado. Traço é resposta; zero seria mentira. */
.ds-sem-dado { color: var(--ds-texto-fraco); }

/* `.ds-rolagem`: a **caixa que rola** no eixo x — a tabela larga rola **dentro** do cartão, e o
   cartão para de ser atravessado.

   ⚠️ **O defeito, medido em 24/09/2026.** A tabela de preço do `/custo/` tem oito colunas e pede o
   `min-content` dela — **1113px** na coluna de 716px (o casco com o painel aberto). Sem caixa
   nenhuma, o navegador espremia as colunas que podiam quebrar: `deepseek · deepseek-flash` saía em
   **três** linhas e a vigência em **duas**; e quem rolava era a coluna **inteira**
   (`.ds-conteudo`, `scrollWidth` de 3262px).

   `width: max-content` **devolve à tabela a forma dela**: as colunas param de ser espremidas, e o
   título e a célula ficam numa linha só — quem rola é a caixa. O `min-width: 100%` é para a tabela
   que **cabe** não sair menor que o cartão: sem ele, as seis colunas do Meu Dia (medido: 632px)
   encolheriam até o conteúdo, e a tabela deixaria de ocupar a largura do cartão.

   ⚠️ **A doutrina é a do `.ds-tabela` logo acima** — o mínimo é **por rótulo**, e não um número
   fixo: um `min-width` de 1113px faria a tabela do Meu Dia, que cabe, rolar para sempre, e o
   conserto de uma tela viraria defeito em todas. É a mesma lição que o comentário da `.ds-concessoes`
   já fixou para a grade de listas.

   ⚠️ **E o conserto de 24/09 continua de pé:** o `.ds-conteudo` **rola** em vez de cortar em
   silêncio, e é ele que prende o
   `testes/plataforma/test_painel_da_assistente.py::CasosDaColunaEstreita`. O `overflow: auto` do
   `.ds-conteudo` **não** se mexe — a caixa é a rolagem **de dentro**, no cartão de quem é a tabela,
   e as duas convivem: a coluna rola se ainda faltar, e a caixa rola primeiro.

   ⚠️ **E a caixa tem de se anunciar** (24/09/2026, o pedaço que faltava dos dois consertos). No
   macOS a barra é de **sobreposição**: ela existe só enquanto a pessoa rola e some depois. Medido
   na bancada (`ui/ds/referencia.html#coluna-estreita`, janela de 1209px, o desenho de antes): a
   caixa tem **600px** e a tabela **1613px**, e a barra **ocupa 0px** — a captura mostra a tabela
   cortada na altura da coluna `ENTRADA`, sem nada que diga que há mais tabela à direita. É o mesmo
   efeito do defeito que o dono reclamou, a tabela parecendo cortada, e olhando a bancada ele diria
   que nada mudou.

   Por isso a caixa declara a barra nas **duas** sintaxes: `scrollbar-width`/`scrollbar-color`, que
   é o que o Firefox entende, e o `::-webkit-scrollbar` logo abaixo, que é o que **desliga a
   sobreposição** no Chrome e no Safari — a regra que faz a barra **reservar** a altura dela.
   Medido depois da regra, na mesma janela: a barra ocupa **12px** e aparece sem ninguém rolar.
   As cores e a medida saem de token: o polegar é `--ds-borda-forte`, o mesmo tom das bordas de
   controle, e a trilha é a superfície alta. */
.ds-rolagem {
  overflow-x: auto;
  scrollbar-width: thin;
  scrollbar-color: var(--ds-borda-forte) var(--ds-superficie-alta);
}
.ds-rolagem > .ds-tabela { width: max-content; min-width: 100%; }
/* A barra visível no Chrome e no Safari. O par `width`/`height` é o que dá espessura à barra dos
   dois eixos: sem ele o motor não desenha polegar nenhum, e a barra volta a ser a de sobreposição. */
.ds-rolagem::-webkit-scrollbar { height: var(--ds-rolagem-barra); width: var(--ds-rolagem-barra); }
.ds-rolagem::-webkit-scrollbar-track { background: var(--ds-superficie-alta); }
.ds-rolagem::-webkit-scrollbar-thumb {
  background: var(--ds-borda-forte);
  border-radius: var(--ds-raio-chip);
}

/* -------------------------------------------------- gráfico de barras ------- */
.ds-barras { display: flex; align-items: flex-end; gap: var(--ds-esp-28); padding: 0 var(--ds-esp-4); border-bottom: 1px solid var(--ds-borda-secao); }
.ds-barras__serie { flex: 1; display: flex; flex-direction: column; gap: var(--ds-esp-6); }
.ds-barras__rotulo { font: var(--ds-peso-500) var(--ds-tipo-13) var(--ds-fonte); color: var(--ds-texto-2); }
.ds-barras__barra { display: block; background: var(--ds-acao); }
/* Semana sem carga não vira estimativa: vira tracejado vazio. */
.ds-barras__barra--ausente { background: transparent; border: 1px dashed var(--ds-traco-ausente); }
.ds-barras__eixo { display: flex; gap: var(--ds-esp-28); padding: var(--ds-esp-8) var(--ds-esp-4) 0; }
.ds-barras__eixo span { flex: 1; font: var(--ds-peso-400) var(--ds-tipo-13) var(--ds-fonte); color: var(--ds-texto-3); }

/* --------------------------------------------------------- progresso ------- */
.ds-progresso { height: 14px; border-radius: var(--ds-raio-chip); background: var(--ds-superficie-alta); overflow: hidden; }
.ds-progresso__barra { height: 100%; background: var(--ds-ok); }
.ds-meta { display: flex; align-items: center; gap: var(--ds-esp-18); }
.ds-meta__numero { font: var(--ds-peso-700) var(--ds-tipo-30) var(--ds-fonte); color: var(--ds-texto); }
.ds-meta__linha { display: flex; align-items: center; gap: var(--ds-esp-10); font: var(--ds-peso-700) var(--ds-tipo-17) var(--ds-fonte); color: var(--ds-texto); }
.ds-meta__esperado { font: var(--ds-peso-400) var(--ds-tipo-14) var(--ds-fonte); color: var(--ds-texto-fraco); }

/* ------------------------------------------------------ estado de dado ------ */
/* Estados de dado são do plugin: o DS entrega o desenho, o plugin diz qual é.
   `data-estado` no bloco escolhe o tratamento. */
.ds-estado[data-estado="vazio"] { }
.ds-faixa {
  display: flex;
  gap: var(--ds-esp-16);
  align-items: flex-start;
  padding: var(--ds-esp-16) var(--ds-esp-20);
  border: 1px solid var(--ds-aviso-borda);
  background: var(--ds-aviso-fundo);
}
.ds-faixa__marca { width: 10px; height: 10px; flex: none; margin-top: var(--ds-esp-6); background: var(--ds-aviso-marca); }
.ds-faixa__titulo { font: var(--ds-peso-600) var(--ds-tipo-15) / var(--ds-linha-1-4) var(--ds-fonte); color: var(--ds-texto); }
.ds-faixa__texto { margin-top: var(--ds-esp-6); font: var(--ds-peso-400) var(--ds-tipo-13) / var(--ds-linha-1-6) var(--ds-fonte); color: var(--ds-texto-2); }
.ds-faixa__fonte { margin-top: var(--ds-esp-6); font: var(--ds-peso-400) var(--ds-tipo-13) var(--ds-fonte); color: var(--ds-texto-fraco); }
.ds-faixa--negativo { border-color: var(--ds-negativo); background: var(--ds-negativo-fundo); }
.ds-faixa--negativo .ds-faixa__marca { background: var(--ds-negativo); }
.ds-faixa--atrasado { border-color: var(--ds-atencao); background: var(--ds-atencao-fundo); }
.ds-faixa--atrasado .ds-faixa__marca { background: var(--ds-atencao); }
/* `derivado`: quarentena e inválido não têm referência no mockup. Usam a mesma
   faixa, com o marcador do farol negativo e o título mudando. */
.ds-faixa--invalido, .ds-faixa--quarentena, .ds-faixa--erro { border-color: var(--ds-negativo); background: var(--ds-negativo-fundo); }
.ds-faixa--invalido .ds-faixa__marca, .ds-faixa--quarentena .ds-faixa__marca, .ds-faixa--erro .ds-faixa__marca { background: var(--ds-negativo); }

/* Vazio: nada aconteceu — e isso é uma resposta, não um buraco. */
.ds-vazio {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--ds-esp-8);
  padding: var(--ds-esp-24) var(--ds-esp-24);
  background: var(--ds-superficie);
  border: 1px dashed var(--ds-traco-ausente);
  border-radius: var(--ds-raio-cartao);
}
.ds-vazio__titulo { font: var(--ds-peso-700) var(--ds-tipo-15) var(--ds-fonte); color: var(--ds-texto); }
.ds-vazio__texto { font: var(--ds-peso-400) var(--ds-tipo-13) / var(--ds-linha-1-6) var(--ds-fonte); color: var(--ds-texto-3); }

/* O que estava sendo esperado e não chegou. */
.ds-esperando { display: flex; align-items: center; gap: var(--ds-esp-10); font: var(--ds-peso-400) var(--ds-tipo-13) var(--ds-fonte); color: var(--ds-texto-fraco); }
.ds-esperando__anel { width: 14px; height: 14px; flex: none; border: 2px solid var(--ds-traco-ausente); border-top-color: var(--ds-atencao); border-radius: 50%; }

/* ------------------------------------------------------ assistente ---------- */
/* O painel reservado pela casca. Sem motor: o DS desenha, o motor preenche.

   ⚠️ **A altura do painel é a da janela, e quem rola é o fio.** O painel resolve como a irmã dele
   na grade, a `.ds-lateral`: `sticky` + `height: 100vh` prendem a coluna na janela, e a conversa
   rola **dentro** do fio, com o topo e a caixa parados. É esta altura que chega inteira até o fio —
   sem ela, a grade estica o `<aside>` até a altura do **documento**, e a rolagem vai para a página.

   Medido no Chrome headless (vinte e quatro balões, o conteúdo da tela longo), antes e depois:
   painel de 3419px → 813px (a janela), fio de 3271px sem rolagem própria (`scrollHeight` igual ao
   `clientHeight`) → 665px com rolagem (`scrollHeight` 3271, rolou até 2606), e a **caixa fora da
   tela** antes (base em 3419px, contra a janela de 813px), dentro depois (base 813). A contraprova,
   com o painel sem esta regra, devolve os 3419px e a caixa fora: é a altura do painel que segura o
   fio. */
.ds-assistente {
  display: flex;
  flex-direction: column;
  min-width: 0;
  position: sticky;
  top: 0;
  height: 100vh;
  background: var(--ds-superficie);
  border-left: 2px solid var(--ds-assistente-borda);
}
/* Recolhido pelo botão do topo (passo 26): o painel sai e a faixa dele volta ao conteúdo.
   `derivado` — o mockup não tem o painel, e o DS o desenha sempre aberto. */
.ds-assistente--recolhido { display: none; }
.ds-assistente__topo {
  flex: none;
  display: flex;
  align-items: center;
  gap: var(--ds-esp-12);
  padding: var(--ds-esp-16) var(--ds-esp-18);
  border-bottom: 1px solid var(--ds-divisor);
}
.ds-assistente__topo img { width: 36px; height: 36px; border-radius: 50%; object-fit: cover; flex: none; }
.ds-assistente__nome { font: var(--ds-peso-700) var(--ds-tipo-15) var(--ds-fonte); color: var(--ds-marca-texto); }
.ds-assistente__papel { font: var(--ds-peso-400) var(--ds-tipo-12) var(--ds-fonte); color: var(--ds-texto-3); }
/* ⚠️ **A única área com rolagem do painel.** O `min-height: 0` é a regra da casa para o filho de
   flex que rola — a mesma do `.ds-nav`: o item que rola não cresce além do pai. Com `overflow-y:
   auto` o mínimo automático do Chrome já é zero (medido: tirar a declaração não move um pixel), e o
   zero fica **declarado** porque é ele que diz, na folha, que este filho encolhe de propósito. */
.ds-assistente__fio { flex: 1; min-height: 0; display: flex; flex-direction: column; gap: var(--ds-esp-14); padding: var(--ds-esp-18); overflow-y: auto; }
.ds-assistente__rodape { flex: none; padding: var(--ds-esp-16) var(--ds-esp-18); border-top: 1px solid var(--ds-divisor); }

/* O recorte que ela está lendo. Sem isto, a resposta não tem chão. */
.ds-contexto {
  padding: var(--ds-esp-12) var(--ds-esp-14);
  background: var(--ds-marca-fundo);
  border: 1px solid var(--ds-marca-suave);
  border-radius: var(--ds-raio-chip);
}
.ds-contexto__valor { margin-top: var(--ds-esp-6); font: var(--ds-peso-400) var(--ds-tipo-13) / var(--ds-linha-1-6) var(--ds-fonte); color: var(--ds-texto-2); }

/* O balão de fala dos dois lados. `white-space: pre-wrap` (24/09) porque a pergunta guardada pode
   ter **quebra de linha** — a caixa aceita mais de uma linha, e o fio guarda o texto como ele foi
   escrito: sem isto, o balão mostra a pergunta inteira numa linha só. A propriedade preserva a
   quebra e continua quebrando o texto na largura do balão. */
.ds-balao-fala { max-width: 300px; padding: var(--ds-esp-12) var(--ds-esp-16); font: var(--ds-peso-400) var(--ds-tipo-14) / var(--ds-linha-1-6) var(--ds-fonte); white-space: pre-wrap; }
.ds-balao-fala--assistente {
  align-self: flex-start;
  background: var(--ds-superficie-alta);
  color: var(--ds-texto);
  border-radius: var(--ds-raio-caixa) var(--ds-raio-caixa) var(--ds-raio-caixa) var(--ds-esp-4);
}
.ds-balao-fala--usuario {
  align-self: flex-end;
  background: var(--ds-selecao-fundo);
  color: var(--ds-texto);
  border-radius: var(--ds-raio-caixa) var(--ds-raio-caixa) var(--ds-esp-4) var(--ds-raio-caixa);
}
/* A fonte que ela cita. Sem fonte, ela não afirma — e diz que não sabe. */
.ds-citacao { margin-top: var(--ds-esp-10); font: var(--ds-peso-400) var(--ds-tipo-13) / var(--ds-linha-1-6) var(--ds-fonte); color: var(--ds-texto-fraco); }
.ds-nao-sei { font: var(--ds-peso-500) var(--ds-tipo-14) var(--ds-fonte); color: var(--ds-atencao); }

.ds-sugestoes { display: flex; flex-wrap: wrap; gap: var(--ds-esp-8); }

.ds-entrada { display: flex; align-items: center; border: 1px solid var(--ds-borda); background: var(--ds-superficie-alta); padding: 0 var(--ds-esp-6) 0 var(--ds-esp-16); border-radius: var(--ds-raio-pilula); }
/* O campo da caixa — e ele é um de dois: a regra vale para o `<input>` de uma linha e para o
   `<textarea>` que a caixa da assistente usa desde 24/09. */
.ds-entrada input,
.ds-entrada textarea {
  flex: 1;
  min-width: 0;
  border: 0;
  background: transparent;
  color: var(--ds-texto);
  font: var(--ds-peso-400) var(--ds-tipo-14) var(--ds-fonte);
  outline: none;
}
.ds-entrada input { height: var(--ds-esp-44); }
/* ⚠️ **O campo aceita mais de uma linha, e a altura acompanha o texto até um teto** (24/09): com
   `field-sizing: content` o navegador mede o conteúdo, e o `max-height` — **três linhas** de
   `--ds-tipo-14` com a entrelinha do balão, mais o respiro do campo — é onde ele para e passa a
   rolar (`overflow-y: auto`). Onde o `field-sizing` não existe, o que fica é o `rows="1"` do
   markup: uma linha que rola, e nada quebrado. O `min-height` é a altura do campo de uma linha de
   antes (o mesmo `--ds-esp-44` do `<input>`), e o `resize: none` é do desenho: quem cresce é o
   texto, e não a mão. */
.ds-entrada textarea {
  min-height: var(--ds-esp-44);
  max-height: calc(var(--ds-tipo-14) * var(--ds-linha-1-6) * 3 + var(--ds-esp-22));
  padding: var(--ds-esp-11) 0;
  resize: none;
  overflow-y: auto;
  field-sizing: content;
}
.ds-entrada__enviar {
  flex: none;
  width: var(--ds-esp-36);
  height: var(--ds-esp-36);
  border: 0;
  border-radius: 50%;
  background: var(--ds-marca);
  color: #FFFFFF;
  cursor: pointer;
}

/* ------------------------------------------------------ concessões --------- */
/* A tela de Autorização: as três listas do papel. Marcar concede; desmarcar
   revoga — o mesmo item, o mesmo lugar. `derivado`: sem referência no mockup.

   **As listas empilham quando não cabem**, em vez de rolar de lado: lista que empilha é melhor
   que lista que exige arrastar a página. O mínimo é o de **uma** lista — o item mais largo, que é
   o nome da função mais a origem —, e ele mora no token; a lista larga demais para o mínimo vai
   para a linha de baixo, e a coluna estreita fica legível em vez de espremida. */
.ds-concessoes {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(var(--ds-concessoes-minima), 1fr));
  gap: var(--ds-esp-18);
}
.ds-concessoes__coluna { display: flex; flex-direction: column; }
.ds-concessoes__lista { display: flex; flex-direction: column; gap: var(--ds-esp-2); margin: var(--ds-esp-10) 0 0; padding: 0; list-style: none; }
.ds-concessoes__item {
  display: flex;
  align-items: center;
  gap: var(--ds-esp-10);
  min-height: var(--ds-esp-40);
  padding: 0 var(--ds-esp-12);
  border-radius: var(--ds-raio-chip);
  font: var(--ds-peso-400) var(--ds-tipo-14) var(--ds-fonte);
  color: var(--ds-texto-2);
}
.ds-concessoes__item--alcanca { background: var(--ds-selecao-fundo); color: var(--ds-selecao-texto); font-weight: var(--ds-peso-600); }
.ds-concessoes__origem { margin-left: auto; font: var(--ds-peso-400) var(--ds-tipo-13) var(--ds-fonte); color: var(--ds-texto-fraco); }

/* ----------------------------------------------------------- login ---------- */
/* Dois painéis: a marca à esquerda, o acesso à direita. O cliente entra uma vez. */
.ds-login { display: grid; grid-template-columns: 560px minmax(0, 1fr); min-height: 100vh; }
.ds-login__marca {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  padding: var(--ds-esp-56);
  background: #211D3D;
}
.ds-login__promessa { font: var(--ds-peso-300) var(--ds-tipo-38) / var(--ds-linha-1-25) var(--ds-fonte); color: #FFFFFF; max-width: 400px; }
.ds-login__explicacao { margin-top: var(--ds-esp-18); font: var(--ds-peso-400) var(--ds-tipo-15) / var(--ds-linha-1-6) var(--ds-fonte); color: #C6BEE6; max-width: 380px; }
.ds-login__assinatura { font: var(--ds-peso-400) var(--ds-tipo-13) var(--ds-fonte); letter-spacing: var(--ds-letra-miudo); text-transform: uppercase; color: #8E93B4; }
.ds-login__acesso { display: flex; flex-direction: column; justify-content: center; padding: var(--ds-esp-56) 68px; background: var(--ds-superficie); }
/* A coluna do acesso é um bloco de **440px**, como o mockup: o campo, o botão e os avisos param no
   mesmo lugar, e não esticam até a borda da janela — em tela larga, o campo de 1200px não é campo. */
.ds-login__acesso > * { width: 100%; max-width: var(--ds-login-largura); }
.ds-login__campo .ds-botao { margin-top: var(--ds-esp-16); }
/* A coluna do **código** é mais larga: as seis casas (70px cada, com 10 de intervalo) não cabem nos
   440 da tela do e-mail — o mockup 4b desenha esta coluna com 518. */
.ds-login__campo--codigo { --ds-login-largura: 518px; max-width: var(--ds-login-largura); }
.ds-login__cliente { font: var(--ds-peso-700) var(--ds-tipo-25) / var(--ds-linha-1-3) var(--ds-fonte); color: var(--ds-texto); }
.ds-login__ajuda { margin-top: var(--ds-esp-10); font: var(--ds-peso-400) var(--ds-tipo-14) / var(--ds-linha-1-6) var(--ds-fonte); color: var(--ds-texto-fraco); }
.ds-login__campo { margin-top: var(--ds-esp-28); }
.ds-login__acoes { display: flex; gap: var(--ds-esp-24); margin-top: var(--ds-esp-16); font: var(--ds-peso-400) var(--ds-tipo-13) var(--ds-fonte); color: var(--ds-texto-fraco); }
/* Reenviar só volta a ser clicável quando o contador zera. */
.ds-login__reenviar { color: var(--ds-texto); font-weight: var(--ds-peso-700); }
.ds-login__reenviar[aria-disabled="true"] { color: var(--ds-texto-fraco); font-weight: var(--ds-peso-400); }
/* A assinatura de tecnologia do mockup: encostada no pé da coluna do acesso, em texto — link para
   fora é o que a varredura de template proíbe, e a marca aqui é palavra, não endereço. */
.ds-login__tecnologia {
  display: flex;
  align-items: center;
  gap: var(--ds-esp-8);
  margin-top: auto;
  padding-top: var(--ds-esp-44);
  font: var(--ds-peso-400) var(--ds-tipo-13) var(--ds-fonte);
  color: var(--ds-texto-fraco);
}
.ds-login__tecnologia strong { color: var(--ds-marca); }

/* --------------------------------------------------- barra de mobile ------- */
.ds-barra-mobile {
  flex: none;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  background: var(--ds-superficie);
  border-radius: var(--ds-raio-cartao) var(--ds-raio-cartao) 0 0;
  padding: var(--ds-esp-10) var(--ds-esp-12) var(--ds-esp-18);
}
.ds-barra-mobile__item {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--ds-esp-4);
  color: var(--ds-texto-fraco);
  font: var(--ds-peso-500) var(--ds-tipo-12) var(--ds-fonte);
}
.ds-barra-mobile__item--ativo { color: var(--ds-selecao-texto); font-weight: var(--ds-peso-700); }
.ds-barra-mobile__item--ativo .ds-barra-mobile__icone { background: var(--ds-selecao-fundo); }
.ds-barra-mobile__icone { display: flex; align-items: center; justify-content: center; min-width: 36px; height: 26px; border-radius: 13px; }
.ds-barra-mobile__item img { width: 22px; height: 22px; border-radius: 50%; object-fit: cover; }
