/* admin.css — o painel do gestor.

   Carregado SEMPRE depois do `flowpest.css`: as cores (--fundo, --ouro, --texto…)
   vêm de lá e nenhum hex novo nasce aqui, com UMA exceção deliberada explicada
   logo abaixo (a barra lateral).

   O desenho é o "misto" aprovado em 17/08:
     · barra lateral SEMPRE escura, em qualquer tema — é o que dá personalidade
       sem depender de imagem, e é o padrão das referências que o dono trouxe;
     · área de trabalho clara de dia, escura à noite, com botão para forçar;
     · degradê de ouro bem fraco no fundo da área de trabalho (~4%). Percebe-se
       que "tem alguma coisa ali", não se percebe a cor.

   Menu SÓ TEXTO, sem ícone e sem emoji (decisão do dono, a mesma do app do
   técnico): emoji muda de desenho em cada aparelho e não é a nossa marca.
*/

/* ── A barra lateral tem paleta PRÓPRIA ──────────────────────────────────
   Ela não pode usar --barra/--texto porque esses viram claro no tema claro, e
   a lateral tem que ficar escura nos dois. Então ela aponta para os valores
   `--d-*` do flowpest.css — que são os MESMOS hex do tema escuro, sem cópia. */
:root {
  /* A cor ATRÁS de tudo. O painel passou a ter três níveis de profundidade
     (17/08, geometria pedida pelo dono): a moldura no fundo, os dois painéis
     arredondados por cima dela, e os cartões dentro deles. Sem o nível de
     baixo, "arredondar" não destacaria nada — cantos redondos só aparecem
     quando há algo diferente atrás. */
  --l-moldura:  #E7EAEE;   /* o valor CLARO, para quem não segue o tema
                              (a tela de entrada) poder apontar para ele */
  --moldura:    var(--l-moldura);
  --lat-fundo:  var(--d-barra);
  --lat-fundo2: var(--d-fundo);
  --lat-borda:  var(--d-borda);
  --lat-texto:  var(--d-texto);
  --lat-fraco:  var(--d-texto-fraco);
  --lat-ouro:   var(--d-ouro);
  --lat-larg:   244px;
  --moldura-folga: 10px;   /* a margem que revela a moldura */
  --raio-painel:   20px;
}

/* No escuro a moldura é mais funda que o próprio fundo escuro — é o que faz o
   painel parecer apoiado sobre algo, e não recortado nele. */
:root[data-tema="escuro"] { --moldura: #07090A; }
@media (prefers-color-scheme: dark) {
  :root:not([data-tema="claro"]) { --moldura: #07090A; }
}

/* ── Esqueleto ───────────────────────────────────────────────────────────
   Duas colunas: lateral fixa + o resto. `min-height:100dvh` em vez de 100vh
   porque no celular a barra de endereço do navegador come parte da `vh` e a
   página ficava com um vão embaixo ao rolar. */
body.adm {
  margin: 0;
  min-height: 100dvh;
  background: var(--moldura);
  padding: var(--moldura-folga);
}

.adm-grade {
  display: grid;
  grid-template-columns: var(--lat-larg) 1fr;
  gap: var(--moldura-folga);
  min-height: calc(100dvh - var(--moldura-folga) * 2);
}

/* ── Barra lateral ───────────────────────────────────────────────────── */
.adm-lateral {
  position: sticky;
  /* Gruda a uma folga do topo, e não em 0: assim ela para exatamente onde o
     painel começa, em vez de encostar na borda da janela. */
  top: var(--moldura-folga);
  height: calc(100dvh - var(--moldura-folga) * 2);
  display: flex;
  flex-direction: column;
  background: linear-gradient(180deg, var(--lat-fundo) 0%, var(--lat-fundo2) 100%);
  border: 1px solid var(--lat-borda);
  border-radius: var(--raio-painel);
  /* Sombra funda e larga: é o que separa a lateral escura da moldura, que
     também é escura no tema noturno. Sem ela, os dois viram uma mancha só. */
  box-shadow: 0 8px 28px rgba(0, 0, 0, .22);
  padding: 14px 10px 10px;
  /* A lateral inteira NÃO rola: quem rola é só a lista de seções (`.adm-nav`).
     Assim a marca fica presa em cima e o rodapé — tema, empresa, Sair — fica
     preso embaixo, sempre à vista. Antes a lateral inteira rolava e o rodapé
     ficava 220px abaixo da dobra: com a barra de rolagem escondida, ninguém
     descobriria que ele existe. */
  overflow: hidden;
}

.adm-marca {
  /* Centralizada e com respiro embaixo (pedido do dono, 17/08): encostada no
     "Visão geral", a marca parecia o primeiro item do menu. */
  display: flex;
  justify-content: center;
  padding: 4px 8px 22px;
  color: var(--lat-texto);
  line-height: 0;              /* o SVG é inline: sem isto sobra um vão embaixo */
}

.adm-nav {
  flex: 1;
  /* Rola quando a tela é baixa, mas SEM a barra cinza do sistema por cima do
     menu (o dono apontou em 17/08: "fica feio"). A rolagem continua
     funcionando pela roda do mouse, pelo toque e pelo teclado — some só o
     desenho da barra. As três linhas cobrem Firefox, Chrome/Safari e o Edge
     antigo, nessa ordem. */
  overflow-y: auto;
  scrollbar-width: none;
  -ms-overflow-style: none;
}
.adm-nav::-webkit-scrollbar { width: 0; height: 0; }

/* Título do grupo ("Operação", "Comercial"…). Ouro, pequeno e espaçado: ele
   corta a lista em blocos que o olho encontra sem ler. */
.adm-grupo {
  display: block;
  color: var(--lat-ouro);
  font-size: 10.5px;
  font-weight: 700;
  line-height: 1.4;
  text-transform: uppercase;
  letter-spacing: .12em;
  /* 10px e não 12: com 12 a lista passava 7px da tela num monitor de 720px de
     altura útil, e a lateral inteira entrava em rolagem por causa disso. */
  margin: 10px 0 4px;
  padding: 0 13px;
  text-decoration: none;
}
.adm-nav > .adm-grupo:first-child { margin-top: 0; }
/* O grupo logo depois do "Visão geral" respira mais: ele é o começo do menu de
   verdade, e colado no destaque os dois pareciam um bloco só. */
.adm-grupo-link + .adm-grupo { margin-top: 22px; }

/* "Visão geral" é grupo E destino ao mesmo tempo: um item só não merecia duas
   linhas. Como ele é clicável, ganha a mesma caixa dos itens — senão nada na
   tela contaria que dá para clicar. */
.adm-grupo-link {
  padding: 8px 12px;
  border: 1px solid rgba(255, 197, 61, .30);
  border-radius: var(--raio);
  transition: border-color var(--transicao);
  /* O DESTAQUE. Ele estava com a mesma cara dos rótulos que não clicam, e nada
     na tela contava a diferença.

     São duas camadas: um brilho estreito que atravessa a caixa devagar, e o
     fundo ouro fixo por baixo. O brilho é `background-size: 220%` deslizando de
     um lado ao outro — o mesmo truque das telas de "carregando", em câmera
     lenta e com opacidade baixa. 9 segundos: rápido o bastante para o olho
     pegar de passagem, lento o bastante para não pedir atenção enquanto a
     pessoa trabalha. */
  background:
    linear-gradient(100deg,
      rgba(255, 255, 255, 0) 38%,
      rgba(255, 255, 255, .16) 50%,
      rgba(255, 255, 255, 0) 62%) 0 0 / 220% 100% no-repeat,
    rgba(255, 197, 61, .10);
  /* Duas animações no mesmo elemento, e elas não brigam: a primeira mexe na
     POSIÇÃO do brilho, a segunda na COR do fundo, da borda e do texto. O
     brilho ficou branco justamente por causa disso — sendo ouro, ele sumiria
     em cima do ouro e destoaria em cima do violeta. */
  animation: brilho-passando 9s linear infinite,
             ouro-violeta 9s ease-in-out infinite;
}
@keyframes brilho-passando {
  from { background-position: 140% 0, 0 0; }
  to   { background-position: -140% 0, 0 0; }
}
/* Ouro → violeta → ouro. O violeta é a cor da IA na identidade v2, então o
   destaque do painel pisca na cor que o produto usa para "inteligência" —
   e não numa cor inventada. */
@keyframes ouro-violeta {
  0%, 100% {
    color: var(--d-ouro);
    border-color: rgba(255, 197, 61, .42);
    background-color: rgba(255, 197, 61, .10);
  }
  50% {
    color: var(--d-violeta);
    border-color: rgba(168, 85, 247, .45);
    background-color: rgba(168, 85, 247, .13);
  }
}
.adm-grupo-link:hover { border-color: var(--lat-ouro); }
.adm-grupo-link:focus-visible { outline: 2px solid var(--lat-ouro); outline-offset: -2px; }
.adm-grupo-link.ativo { border-color: var(--lat-ouro); }
/* Quem pediu menos movimento no aparelho não recebe o brilho — o
   `prefers-reduced-motion` do flowpest.css já mata a animação, e aqui o fundo
   ouro fixo garante que o destaque continue existindo parado. */

.adm-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  /* Compacto de propósito: são 13 itens e o menu precisa caber sem rolar num
     notebook de 720px de altura útil. `line-height` normal (1.6, herdado do
     corpo) somava 5px por linha e sozinho jogava a lista para fora da tela. */
  padding: 5px 12px;
  margin-bottom: 2px;
  border-radius: var(--raio);
  color: var(--lat-fraco);
  text-decoration: none;
  font-size: 13.5px;
  line-height: 1.45;
  font-weight: 500;
  /* A borda nasce transparente e só troca de COR nos estados. Se ela só
     aparecesse no hover, cada item pularia 1px ao passar o mouse. */
  border: 1px solid transparent;
  transition: background var(--transicao), color var(--transicao),
              border-color var(--transicao);
}
.adm-item:hover {
  border-color: var(--lat-ouro);
  background: rgba(255, 197, 61, .07);
  color: var(--lat-texto);
}
.adm-item:focus-visible { outline: 2px solid var(--lat-ouro); outline-offset: -2px; }

.adm-item.ativo {
  background: rgba(255, 197, 61, .12);
  border-color: rgba(255, 197, 61, .38);
  color: var(--lat-texto);
  font-weight: 600;
  /* A barrinha de ouro à esquerda é sombra interna, e não borda: assim ela
     convive com a borda do contorno em vez de disputar o mesmo lado. */
  box-shadow: inset 3px 0 0 var(--lat-ouro);
}

/* Rodapé da lateral: quem está logado + tema e Sair lado a lado.
   `flex: none` porque ele é irmão da `.adm-nav`, que estica: sem isso o
   navegador poderia espremê-lo para dar espaço à lista. */
.adm-rodape {
  flex: none;
  border-top: 1px solid var(--lat-borda);
  padding-top: 10px;
  margin-top: 10px;
}
/* As cinco ações dividem uma linha só, em ícone. Escritas por extenso elas
   ocupariam três linhas da lateral; aqui a pessoa aprende pela POSIÇÃO, que
   nunca muda. `display: contents` faz o <form> do Sair sumir do layout — ele
   existe só para o POST, e como caixa quebraria a linha em duas. */
.adm-rodape-acoes { display: flex; align-items: center; gap: 4px; }
.adm-rodape-acoes form { display: contents; }

.adm-icone {
  position: relative;
  flex: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 4px;
  height: 34px;
  padding: 0 6px;
  border: 1px solid transparent;
  border-radius: var(--raio);
  background: transparent;
  color: var(--lat-fraco);
  font: inherit;
  cursor: pointer;
  transition: color var(--transicao), border-color var(--transicao),
              background var(--transicao);
}
/* 18px de desenho num alvo de 34px: o ícone fica discreto, mas a área de
   clique continua do tamanho de um dedo. */
.adm-icone svg { width: 18px; height: 18px; flex: none; }
.adm-icone:hover { border-color: var(--lat-ouro); background: rgba(255, 197, 61, .07); color: var(--lat-texto); }
.adm-icone:focus-visible { outline: 2px solid var(--lat-ouro); outline-offset: -2px; }
.adm-icone.ativo { color: var(--lat-ouro); border-color: rgba(255, 197, 61, .38); background: rgba(255, 197, 61, .12); }

/* ── O botão de tema: sol OU lua, nunca os dois ──────────────────────────
   Mesma lógica de três blocos dos tokens de cor no flowpest.css: o padrão é
   claro (sol), o aparelho escuro troca para a lua, e a escolha na mão ganha do
   aparelho nos dois sentidos. `hidden` puro não serve aqui porque o CSS precisa
   religar o que escondeu. */
.adm-tema .adm-tema-lua { display: none; }
.adm-tema .adm-tema-sol { display: inline-flex; }
@media (prefers-color-scheme: dark) {
  :root:not([data-tema="claro"]) .adm-tema .adm-tema-sol { display: none; }
  :root:not([data-tema="claro"]) .adm-tema .adm-tema-lua { display: inline-flex; }
}
:root[data-tema="escuro"] .adm-tema .adm-tema-sol { display: none; }
:root[data-tema="escuro"] .adm-tema .adm-tema-lua { display: inline-flex; }
:root[data-tema="claro"] .adm-tema .adm-tema-sol { display: inline-flex; }
:root[data-tema="claro"] .adm-tema .adm-tema-lua { display: none; }
.adm-tema span { line-height: 0; }

/* O número ao lado do ícone de mensagens (o dono gostou dele ao lado, e não
   como bolha em cima). Só aparece quando há algo para ler. */
.adm-icone-conta {
  font-size: 11px;
  font-weight: 700;
  color: var(--lat-ouro);
  line-height: 1;
}
/* Com o número do lado, o botão de mensagens precisa de mais largura que os
   outros quatro — senão o ícone fica espremido contra o algarismo. */
.adm-icone:has(.adm-icone-conta) { flex: 1.5; }

.adm-conta-nome {
  display: block;
  padding: 0 12px 7px;
  color: var(--lat-texto);
  font-size: 12.5px;
  font-weight: 600;
  /* Nome de dedetizadora é longo; corta com reticências em vez de quebrar. */
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* ── Coluna de trabalho ──────────────────────────────────────────────── */
.adm-coluna {
  min-width: 0;               /* sem isto, uma tabela larga estica a coluna e
                                 empurra a lateral para fora da tela */
  display: flex;
  flex-direction: column;
  border: 1px solid var(--borda);
  border-radius: var(--raio-painel);
  /* `clip` e NÃO `hidden`. Os dois cortam o que passa da borda arredondada, mas
     `hidden` cria uma área de rolagem — e isso quebraria o `position: sticky` do
     topo, que passaria a grudar dentro da coluna em vez de na janela. `clip`
     corta sem criar área de rolagem, então o topo continua funcionando. */
  overflow: clip;
  /* O degradê fraquinho. Dois focos de luz bem diluídos — ouro no alto à
     direita, azul no alto à esquerda — sobre a cor de fundo de sempre.
     `fixed` mantém a luz parada enquanto o conteúdo rola.

     A cor de chegada é a MESMA cor com alfa 0, e não a palavra `transparent`:
     `transparent` é preto-transparente, e vários navegadores interpolam por ele
     — o degradê passa por um cinza sujo no meio do caminho e aparece como uma
     borda visível. Escrever `rgba(…, 0)` faz a cor sumir sem mudar de matiz. */
  background:
    /* Luz de cima: uma faixa clara que desce e some, para a área não ser um
       retângulo de cor chapada. É o degradê que o dono pediu em 17/08 — o que
       existia antes eram só os dois focos de cor dos cantos, fracos demais
       para se perceber no meio da tela. */
    linear-gradient(180deg,
                    rgba(255, 255, 255, .55) 0%,
                    rgba(255, 255, 255, 0) 46%),
    radial-gradient(900px 420px at 100% -8%,
                    rgba(255, 197, 61, .10), rgba(255, 197, 61, 0) 62%),
    radial-gradient(760px 380px at -6% -10%,
                    rgba(53, 80, 224, .07), rgba(53, 80, 224, 0) 64%),
    var(--fundo);
  background-attachment: fixed;
}

/* No escuro a faixa branca vira névoa cinza por cima do carvão: feia e suja.
   Lá ela cai para um véu quase imperceptível, só para o topo não ser chapado. */
:root[data-tema="escuro"] .adm-coluna {
  background:
    linear-gradient(180deg, rgba(255, 255, 255, .05) 0%, rgba(255, 255, 255, 0) 46%),
    radial-gradient(900px 420px at 100% -8%,
                    rgba(255, 197, 61, .07), rgba(255, 197, 61, 0) 62%),
    radial-gradient(760px 380px at -6% -10%,
                    rgba(53, 80, 224, .06), rgba(53, 80, 224, 0) 64%),
    var(--fundo);
}
@media (prefers-color-scheme: dark) {
  :root:not([data-tema="claro"]) .adm-coluna {
    background:
      linear-gradient(180deg, rgba(255, 255, 255, .05) 0%, rgba(255, 255, 255, 0) 46%),
      radial-gradient(900px 420px at 100% -8%,
                      rgba(255, 197, 61, .07), rgba(255, 197, 61, 0) 62%),
      radial-gradient(760px 380px at -6% -10%,
                      rgba(53, 80, 224, .06), rgba(53, 80, 224, 0) 64%),
      var(--fundo);
  }
}

.adm-topo {
  position: sticky;
  top: var(--moldura-folga);
  z-index: 5;
  display: flex;
  align-items: center;
  gap: 14px;
  /* Barra FINA (pedido do dono, 17/08): 52px de altura contra os 70 de antes.
     O que sobra vai para o conteúdo — que é o que o gestor veio ver. */
  min-height: 52px;
  padding: 7px 18px;
  border-bottom: 1px solid var(--borda);
  /* Semitransparente + blur: o conteúdo passa por baixo em vez de sumir numa
     faixa opaca. `color-mix` mistura a cor da barra com transparente, então
     ela continua saindo do token e acompanha o tema. */
  background: color-mix(in srgb, var(--barra) 82%, transparent);
  backdrop-filter: blur(10px);
}

.adm-titulo {
  margin: 0;
  font-size: 17px;
  font-weight: 700;
  letter-spacing: -.02em;
  flex: none;
  white-space: nowrap;
}

/* ── Abas do Dashboard ───────────────────────────────────────────────
   Elas moram na barra do topo (decisão do dono, 18/08): não custam altura nem
   largura, e a aba ativa faz o papel do título — que por isso some nesta tela.

   A marca da aba ativa é uma linha embaixo, e não um fundo: a barra já é uma
   superfície, e fundo dentro de fundo empilha caixas demais num espaço de
   53px. */
.adm-abas {
  display: flex;
  align-items: center;
  gap: 3px;
  flex: none;
  min-width: 0;
  overflow-x: auto;
  /* `overflow-y: hidden` EXPLÍCITO, e não por esquecimento (sessão 80, achado
     pelo dono no celular). A regra do CSS diz que, quando um dos eixos deixa
     de ser `visible`, o outro também deixa: só com `overflow-x: auto` a barra
     ganhava rolagem VERTICAL de brinde, e o dedo arrastava as abas para cima e
     para baixo. Declarar o eixo Y encerra o assunto.

     O `padding-bottom` é a outra metade do conserto, e apareceu MEDINDO por
     que havia o que rolar: o sublinhado da aba ativa é um `::after` em
     `bottom: -8px`, ou seja, 8px ABAIXO da caixa. Era essa sobra que a barra
     rolava - e, sem rolar, o sublinhado ficava recortado. Quer dizer: a marca
     dourada da aba ativa nunca foi vista sem arrastar. Com os 8px de
     respiro ela cabe dentro, aparece, e não sobra nada para rolar. */
  overflow-y: hidden;
  padding-bottom: 8px;
  scrollbar-width: none;
}
.adm-abas::-webkit-scrollbar { height: 0; }

/* Só ícone, no mesmo traço dos do rodapé. Sete palavras ocupariam metade da
   barra; sete desenhos cabem em um terço dela — e sobra espaço para a busca
   com IA, que ainda vai entrar aqui. */
.adm-aba {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  border-radius: 9px;
  color: var(--texto-fraco);
  text-decoration: none;
  transition: color var(--transicao), background var(--transicao);
}
.adm-aba svg { width: 19px; height: 19px; }
.adm-aba:hover { color: var(--texto); background: var(--fundo); }
.adm-aba:focus-visible { outline: 2px solid var(--ouro); outline-offset: -2px; }

/* A aba aberta fica OURO, e ganha um fundo fraquinho da mesma cor. Sem o
   fundo, um ícone dourado sozinho some quando o vizinho está em foco. */
.adm-aba.ativa {
  color: var(--ouro);
  background: color-mix(in srgb, var(--ouro) 12%, transparent);
}
.adm-aba.ativa::after {
  content: "";
  position: absolute;
  left: 11px; right: 11px; bottom: -8px;
  height: 2px;
  border-radius: 2px;
  background: var(--ouro);
}

/* ── Conteúdo das subabas ────────────────────────────────────────────
   Diferente da Visão geral, uma subaba PODE rolar: ela é consulta, não
   vigilância. Espremer um ranking de oito pragas para caber na dobra
   esconderia justamente o que se foi ali procurar. */
.sub { display: flex; flex-direction: column; gap: 14px; }

/* Avisos e a frase de "ainda sem uso" ficam ACIMA da coluna de blocos, com o
   mesmo respiro que separa um bloco do outro. */
.sub-avisos { margin-bottom: 14px; }
.sub-vazio {
  margin: 0 0 14px;
  font-size: 13.5px;
  color: var(--texto-fraco);
}

/* Baixar planilha: ação secundária de verdade. Tem contorno para se ler como
   clicável, mas fica no traço fino e alinhada à direita — não pode competir
   com os números, que são o motivo de a aba existir. */
.sub-baixar-linha { margin: 0; display: flex; justify-content: flex-end; }
.sub-baixar {
  display: inline-flex;
  align-items: center;
  padding: 8px 14px;
  border: 1px solid var(--borda-forte);
  border-radius: var(--raio);
  font-size: 13px;
  font-weight: 600;
  color: var(--texto-fraco);
  text-decoration: none;
  transition: color var(--transicao), border-color var(--transicao),
              background var(--transicao);
}
.sub-baixar:hover { color: var(--ouro); border-color: var(--ouro); background: var(--fundo); }
.sub-baixar:focus-visible { outline: 2px solid var(--azul); outline-offset: 2px; }

.sub-kpis {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: 10px;
}

/* Ranking: nome, barra proporcional, valor. */
.sub-rank {
  display: grid;
  grid-template-columns: minmax(90px, 190px) 1fr auto;
  align-items: center;
  gap: 12px;
  padding: 7px 0;
  border-bottom: 1px solid var(--borda);
}
.sub-rank:last-child { border-bottom: none; }
.sub-rank-nome {
  font-size: 13px; font-weight: 600;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.sub-rank-barra {
  height: 8px;
  border-radius: 999px;
  background: var(--fundo);
  overflow: hidden;
}
.sub-rank-barra i {
  display: block;
  height: 100%;
  width: var(--pct);
  border-radius: 999px;
  background: var(--ouro);
  animation: vg-enche .8s cubic-bezier(.2, .8, .2, 1) both;
}
.sub-rank-valor {
  font-size: 13px; font-weight: 700;
  font-variant-numeric: tabular-nums; white-space: nowrap;
}

/* ── Equipe agora ────────────────────────────────────────────────────
   Um cartão por técnico. Em tela larga eles ficam lado a lado; a partir de
   dois técnicos isso é o que permite comparar o dia de um com o do outro sem
   rolar. */
.eq-grade {
  display: grid;
  /* `min(420px, 100%)` e não `420px`: num celular de 375px o `minmax(420px,
     1fr)` cria uma coluna de 420px FIXOS, e o cartão passa 68px da tela — sem
     nem virar rolagem, porque a moldura corta. A pílula de estado e o selo de
     cada visita ficavam do lado de fora (medido em 19/08, iPhone de 375px). */
  grid-template-columns: repeat(auto-fit, minmax(min(420px, 100%), 1fr));
  gap: 12px;
}
.eq-card { padding: 14px 16px; }
.eq-topo {
  display: flex;
  align-items: center;
  gap: 11px;
  padding-bottom: 11px;
  border-bottom: 1px solid var(--borda);
}
.eq-avatar {
  flex: none;
  width: 38px; height: 38px;
  display: grid; place-items: center;
  border-radius: 999px;
  background: var(--ouro);
  color: var(--ouro-contra);
  font-size: 13px; font-weight: 800;
}
.eq-nome { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.eq-nome strong { font-size: 14.5px; font-weight: 700; }
.eq-nome small  { font-size: 11.5px; color: var(--texto-fraco); }

.eq-visitas { margin: 0; padding: 0; list-style: none; }
.eq-visita {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 0;
  border-bottom: 1px solid var(--borda);
}
.eq-visita:last-child { border-bottom: none; padding-bottom: 0; }
.eq-hora {
  flex: none; min-width: 76px;
  font-size: 12px; font-weight: 700;
  font-variant-numeric: tabular-nums;
}
.eq-quem { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.eq-quem strong { font-size: 13px; font-weight: 600;
                  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.eq-quem small  { font-size: 11px; color: var(--texto-fraco); }
.eq-marcas { display: flex; flex-wrap: wrap; gap: 4px; justify-content: flex-end; }
.eq-marca {
  padding: 2px 7px;
  border-radius: 999px;
  border: 1px solid var(--borda);
  font-size: 10.5px;
  color: var(--texto-fraco);
  white-space: nowrap;
}
/* Check-in longe do endereço: alerta suave, porque endereço mal cadastrado dá
   exatamente o mesmo sintoma que técnico que não desceu do carro. */
.eq-marca.longe { color: var(--laranja-txt); border-color: var(--laranja-borda); background: var(--laranja-fundo); }

/* As pílulas de estado, herdadas da faixa de equipe que existia na Visão geral. */
.vg-pill {
  flex: none;
  padding: 3px 10px;
  border-radius: 999px;
  border: 1px solid var(--borda);
  background: var(--superficie);
  font-size: 11.5px; font-weight: 600;
  white-space: nowrap;
}
.vg-pill.cor-verde    { color: var(--verde-txt);    border-color: var(--verde-borda);    background: var(--verde-fundo); }
.vg-pill.cor-vermelho { color: var(--vermelho-txt); border-color: var(--vermelho-borda); background: var(--vermelho-fundo); }
.vg-pill.cor-azul     { color: var(--azul);         border-color: var(--azul-borda);     background: var(--azul-fundo); }
.vg-pill.cor-cinza    { color: var(--texto-fraco); }

/* ── O "up" dos cartões (19/08) ──────────────────────────────────────
   O dono achou os cartões sem vida. O tratamento é sempre o mesmo e é de
   propósito discreto: uma FAIXA de cor no topo dizendo o estado, uma entrada
   que sobe, e resposta ao passar o mouse. Nada pisca sozinho na tela — num
   painel que fica aberto o dia inteiro, movimento perpétuo cansa e, pior,
   ensina a ignorar. A ÚNICA coisa que pulsa é "Em serviço", porque essa é
   literalmente a informação "está acontecendo agora".

   Quem pediu menos movimento no aparelho não recebe nada disso (regra no fim
   do arquivo): a cor e a faixa continuam, o movimento não. */

/* A faixa fica sobre a borda de cima do cartão, com as pontas seguindo o
   arredondamento — por isso `inset` em vez de `width: 100%`. */
.eq-card, .vg-kpi, .adm-kpi { position: relative; overflow: hidden; }
.eq-card::before, .vg-kpi::before, .adm-kpi::before {
  content: "";
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 3px;
  background: linear-gradient(90deg,
              var(--cor-faixa, var(--borda-forte)),
              color-mix(in srgb, var(--cor-faixa, var(--borda-forte)) 15%, transparent));
  opacity: .9;
}
.eq-card.estado-em_servico { --cor-faixa: var(--verde); }
.eq-card.estado-atrasado   { --cor-faixa: var(--vermelho); }
.eq-card.estado-concluido  { --cor-faixa: var(--azul); }
.eq-card.estado-aguardando { --cor-faixa: var(--borda-forte); }
.vg-kpi.alerta::before, .adm-kpi.alerta::before { --cor-faixa: var(--vermelho); }
.vg-kpi.positivo::before  { --cor-faixa: var(--verde); }

/* Sobe ao entrar. Escalonado: os cartões chegam em cascata, o que faz o olho
   varrer a tela na ordem de leitura em vez de receber tudo de uma vez. */
@keyframes adm-entra {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: none; }
}
.eq-grade > *, .sub-kpis > * {
  animation: adm-entra .34s cubic-bezier(.2, .8, .2, 1) both;
}
.eq-grade > :nth-child(2), .sub-kpis > :nth-child(2) { animation-delay: .05s; }
.eq-grade > :nth-child(3), .sub-kpis > :nth-child(3) { animation-delay: .10s; }
.eq-grade > :nth-child(4), .sub-kpis > :nth-child(4) { animation-delay: .15s; }
.eq-grade > :nth-child(n+5), .sub-kpis > :nth-child(n+5) { animation-delay: .20s; }

/* Resposta ao mouse: o cartão sobe 2px e a borda ganha contraste. O mesmo
   gesto que os cartões-link da Visão geral já faziam — agora vale também para
   os que não são link, senão metade da tela responde e a outra metade não. */
.eq-card, .vg-kpi, .adm-kpi {
  transition: border-color var(--transicao), transform var(--transicao),
              box-shadow var(--transicao);
}
.eq-card:hover, .vg-kpi:hover, .adm-kpi:hover {
  transform: translateY(-2px);
  border-color: var(--borda-forte);
}

/* O avatar deixa de ser um disco chapado: um leve degradê do ouro e um anel
   fino separando-o do cartão. */
.eq-avatar {
  background: linear-gradient(145deg,
              color-mix(in srgb, var(--ouro) 92%, white),
              var(--ouro));
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--ouro) 16%, transparent);
}

/* Quanto do dia já foi. Mesma barra do ranking, mais fina. */
.eq-progresso {
  height: 4px;
  margin: 10px 0 2px;
  border-radius: 999px;
  background: var(--fundo);
  overflow: hidden;
}
.eq-progresso i {
  display: block;
  height: 100%;
  width: var(--pct);
  border-radius: 999px;
  background: linear-gradient(90deg, var(--ouro),
              color-mix(in srgb, var(--ouro) 55%, var(--verde)));
  animation: vg-enche .9s cubic-bezier(.2, .8, .2, 1) both;
}

/* A linha da visita acende ao passar o mouse — ajuda a não perder a linha na
   horizontal num cartão com oito visitas. */
.eq-visita { border-radius: 8px; padding-left: 6px; padding-right: 6px;
             margin-left: -6px; margin-right: -6px;
             transition: background var(--transicao); }
.eq-visita:hover { background: var(--fundo); }

/* Remarcada ou cancelada: presente, mas claramente fora do dia. */
.eq-fora { opacity: .5; }
.eq-fora .eq-hora { text-decoration: line-through; }

/* O que a visita É, quando não é o serviço de sempre. */
.eq-tipo {
  font-weight: 700;
  color: var(--azul);
}
.eq-tipo::after { content: " · "; color: var(--texto-fraco); font-weight: 400; }

/* "Em serviço" é a única coisa que pulsa: é o estado que está mudando
   enquanto o gestor olha. Um ponto ao lado da pílula, respirando devagar. */
/* Preso ao cartão de técnico de propósito: verde aqui significa "está em
   serviço AGORA". Solto, a regra faria pulsar qualquer pílula verde que
   aparecesse em outra tela — inclusive uma que só diz "pago". */
.eq-card .vg-pill.cor-verde::before {
  content: "";
  display: inline-block;
  width: 6px; height: 6px;
  margin-right: 6px;
  border-radius: 50%;
  background: var(--verde);
  animation: adm-pulsa 2.4s ease-in-out infinite;
}
@keyframes adm-pulsa {
  0%, 100% { opacity: 1;  box-shadow: 0 0 0 0 color-mix(in srgb, var(--verde) 55%, transparent); }
  50%      { opacity: .6; box-shadow: 0 0 0 5px color-mix(in srgb, var(--verde) 0%, transparent); }
}

/* A barra do ranking também ganha o degradê — chapada ela parecia impressa. */
.sub-rank-barra i {
  background: linear-gradient(90deg, var(--ouro),
              color-mix(in srgb, var(--ouro) 70%, var(--laranja)));
}

/* ── SEM CINZA NO TEXTO (dono, 19/08) ───────────────────────────────
   Regra da área de trabalho: letra PRETA no tema claro, BRANCA no escuro.
   Ponto.

   A hierarquia passa a ser feita por TAMANHO e PESO — rótulo pequeno em caixa
   alta, valor grande, nota pequena — e não por desbotar a cor. Desbotar era o
   que deixava a tela com cara de morta: rótulo e nota tinham o mesmo cinza, e
   nenhum dos dois se lia bem.

   Uma linha, e não trinta: `--texto-fraco` é o token que todas as regras do
   conteúdo já usam. Trocá-lo aqui alcança rótulo, nota, título de grupo, nome
   do ranking e as etiquetas — e se um dia se quiser um meio-termo, é este
   único lugar que muda.

   A BARRA LATERAL fica de fora de propósito: ela é escura nos dois temas e tem
   os tokens próprios (`--lat-*`). Letra branca lá já é o normal. */
.adm-conteudo { --texto-fraco: var(--texto); }

/* Exceção: a bolinha do alerta neutro é um DESENHO, não texto. Com a troca
   acima ela viraria um ponto preto no claro, que se lê como marcador de lista
   e não como "aviso sem urgência". */
.adm-conteudo .nivel-azul .adm-alerta-ponto { background: var(--borda-forte); }

/* ── A tela de indicadores estava "apagada e sem graça" (dono, 19/08) ──
   Quatro mudanças, todas de leitura e nenhuma de enfeite:

   1. o cartão ganha PROFUNDIDADE (um degradê quase imperceptível) em vez de
      ser um retângulo chapado da cor do fundo;
   2. o RÓTULO sobe de contraste — era o mesmo cinza fraco da nota de rodapé,
      então título e observação tinham o mesmo peso;
   3. o "R$" encolhe e apaga: é a parte que ninguém precisa ler;
   4. porcentagem ganha BARRA — o número vira forma.

   A faixa do topo dos cartões neutros deixa de ser cinza e ganha um toque de
   ouro: é a cor da marca aparecendo de leve em toda tela, sem pintar nada. */
.eq-card, .vg-kpi, .adm-kpi, .sub-kpis > .adm-cartao {
  background: linear-gradient(180deg,
              color-mix(in srgb, var(--superficie) 94%, var(--texto) 6%),
              var(--superficie) 62%);
}
.vg-kpi::before, .adm-kpi::before {
  --cor-faixa: color-mix(in srgb, var(--ouro) 55%, var(--borda-forte));
}
.sub-kpis .adm-kpi-rotulo {
  color: color-mix(in srgb, var(--texto-fraco) 55%, var(--texto));
}
.kpi-cifrao {
  font-size: .62em;
  font-weight: 700;
  color: var(--texto-fraco);
  letter-spacing: 0;
}
.kpi-barra {
  display: block;
  height: 4px;
  margin-top: 8px;
  border-radius: 999px;
  background: var(--fundo);
  overflow: hidden;
}
.kpi-barra i {
  display: block;
  height: 100%;
  width: var(--pct);
  border-radius: 999px;
  background: linear-gradient(90deg, var(--ouro),
              color-mix(in srgb, var(--ouro) 60%, var(--verde)));
  animation: vg-enche .9s cubic-bezier(.2, .8, .2, 1) both;
}
/* Alerta pinta a barra junto: barra dourada embaixo de um número vermelho
   diria duas coisas diferentes sobre o mesmo dado. */
.vg-kpi.alerta .kpi-barra i {
  background: linear-gradient(90deg, var(--vermelho), var(--vermelho-txt));
}

/* O título do grupo ganha um traço de ouro à esquerda: são ele que reparte a
   tela em assuntos, e ele era o texto mais fraco dela. */
.sub .adm-grupo-kpi, .sub-titulo-grupo {
  display: flex;
  align-items: center;
  gap: 7px;
  color: color-mix(in srgb, var(--texto-fraco) 40%, var(--texto));
}
.sub .adm-grupo-kpi::before {
  content: "";
  width: 3px; height: 12px;
  border-radius: 2px;
  background: var(--ouro);
}

/* O vão onde a busca com IA vai morar. Vazio hoje; é ele que empurra o sino
   para a direita e reserva o meio da barra. Quando o campo entrar, ele herda
   esta caixa e nada mais no topo precisa mudar. */
.adm-busca-lugar { flex: 1; min-width: 0; }

/* Botões redondos do topo (sino, WhatsApp, tema). */
.adm-acao {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 38px;
  height: 38px;
  padding: 0 11px;
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  background: var(--superficie);
  color: var(--texto-fraco);
  font: inherit;
  font-size: 12.5px;
  font-weight: 600;
  text-decoration: none;
  cursor: pointer;
  transition: var(--transicao);
}
.adm-acao svg { width: 19px; height: 19px; }
.adm-acao:hover { border-color: var(--borda-forte); color: var(--texto); }
.adm-acao:focus-visible { outline: 2px solid var(--azul); outline-offset: 2px; }

/* ── Janelinha de notificações ───────────────────────────────────────── */
/* Elemento `popover` nativo: o navegador cuida de abrir por cima de tudo,
   fechar ao clicar fora e no Esc, e devolver o foco ao botão. O padrão dele é
   centralizar na tela; aqui a gente ancora no canto de cima à direita, do lado
   do botão que a abriu. */
.adm-janela {
  position: fixed;
  inset: auto;
  /* Logo abaixo da barra fina: 10 da moldura + 52 da barra + 6 de respiro. */
  top: 68px;
  right: 20px;
  width: min(340px, calc(100vw - 32px));
  max-height: min(70dvh, 460px);
  overflow-y: auto;
  margin: 0;
  padding: 0;
  background: var(--superficie);
  color: var(--texto);
  border: 1px solid var(--borda);
  border-radius: var(--raio-g);
  box-shadow: 0 18px 44px rgba(0, 0, 0, .28);
}
/* O véu que o navegador desenha atrás do popover. Fraco: isto é uma janelinha
   de canto, não um diálogo que exige decisão. */
.adm-janela::backdrop { background: rgba(0, 0, 0, .28); }

.adm-janela-topo {
  position: sticky;      /* o título fica à vista enquanto a lista rola */
  top: 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 12px 14px;
  background: var(--superficie);
  border-bottom: 1px solid var(--borda);
  font-size: 14px;
}
.adm-janela-vazia { margin: 0; padding: 22px 14px; color: var(--texto-fraco); font-size: 14px; }

.adm-avisos { margin: 0; padding: 0; list-style: none; }
.adm-aviso {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 10px 14px;
  border-bottom: 1px solid var(--borda);
}
.adm-aviso:last-child { border-bottom: none; }
/* Não lida ganha uma faixa de ouro na borda: dá para ver o que é novo sem ler
   nada, e sem gastar uma bolinha por linha. */
.adm-aviso.nova { box-shadow: inset 3px 0 0 var(--ouro); background: rgba(255, 197, 61, .05); }
.adm-aviso-titulo { font-size: 13.5px; font-weight: 600; line-height: 1.35; }
/* O aviso que leva a algum lugar (29/09): o título vira link, na cor de ação. */
a.adm-aviso-titulo { color: var(--azul); text-decoration: none; }
a.adm-aviso-titulo:hover { text-decoration: underline; }
.adm-aviso-corpo  { font-size: 12.5px; color: var(--texto-fraco); line-height: 1.4; }
.adm-aviso-data   { font-size: 11px; color: var(--texto-fraco); }

/* Bolinha de "tem coisa nova". Fica no canto do botão. */
.adm-bolha {
  position: absolute;
  top: -6px;
  right: -6px;
  min-width: 18px;
  padding: 1px 5px;
  border-radius: 999px;
  background: var(--ouro);
  color: var(--ouro-contra);
  font-size: 10.5px;
  font-weight: 800;
  line-height: 1.5;
}

.adm-conteudo {
  flex: 1;
  display: flex;
  flex-direction: column;
  /* 20px embaixo, e não 56: a Visão geral precisa caber sem rolar, e 56px de
     ar no rodapé eram 56px a menos para o gráfico. */
  padding: 18px 26px 20px;
  /* 1180px era um teto pensado para texto corrido, e num painel de indicadores
     ele só produzia faixa cinza à direita (o dono mediu ~330px na tela dele).
     Aqui quem precisa de largura é o gráfico: quanto mais largo, mais meses
     cabem sem as barras se espremerem.

     O teto novo existe só para monitor ultralargo (2560px e acima), onde uma
     linha de ponta a ponta obriga a virar a cabeça para ler. */
  max-width: 1700px;
  width: 100%;
  min-height: 0;   /* deixa os filhos encolherem em vez de estourar a coluna */
}

/* ── Peças que as páginas vão reusar ─────────────────────────────────── */
.adm-cartao {
  background: var(--superficie);
  border: 1px solid var(--borda);
  border-radius: var(--raio-g);
  padding: 16px 18px;
  /* Duas sombras somadas: uma rente à borda, que dá o contorno que a borda
     sozinha quase não faz no tema claro, e outra larga e diluída, que separa o
     cartão do fundo. O dono apontou em 18/08 que no claro os quadrados quase
     desapareciam. */
  box-shadow: 0 1px 2px rgba(20, 24, 27, .06),
              0 6px 16px rgba(20, 24, 27, .05);
}
/* No escuro, sombra clara não existe — o que separa é a própria escuridão. Uma
   sombra preta sobre carvão vira sujeira; então ela quase some e a borda
   assume. */
:root[data-tema="escuro"] .adm-cartao { box-shadow: 0 2px 10px rgba(0, 0, 0, .28); }
@media (prefers-color-scheme: dark) {
  :root:not([data-tema="claro"]) .adm-cartao { box-shadow: 0 2px 10px rgba(0, 0, 0, .28); }
}

.adm-cartoes {
  display: grid;
  /* `auto-fit` + `minmax`: os cartões se reorganizam sozinhos conforme a
     largura, sem uma média query para cada faixa de tela.

     `auto-FIT`, e não `auto-fill`. A diferença só aparece quando os cartões não
     enchem a fileira, que é o caso normal aqui: Contas tem três. Com
     `auto-fill` o navegador reservava as colunas vazias assim mesmo. Medido em
     10/09, em 1545px: cinco colunas de 231px para três cartões, o topo da
     página terminando em x=1008 enquanto a lista embaixo ia até 1494.

     486px de descompasso entre a metade de cima e a de baixo da mesma tela. E
     o efeito era lido como "a lista está espalhada", o que mandou duas sessões
     inteiras (88 e 89) mexerem na FILEIRA, onde o defeito nunca esteve. */
  grid-template-columns: repeat(auto-fit, minmax(212px, 1fr));
  gap: 12px;
}

.adm-kpi-rotulo {
  margin: 0;
  color: var(--texto-fraco);
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .08em;
}
.adm-kpi-valor {
  margin: 6px 0 0;
  font-size: 27px;
  font-weight: 800;
  letter-spacing: -.03em;
  line-height: 1.1;
}
.adm-kpi-nota { margin: 3px 0 0; font-size: 12px; color: var(--texto-fraco); }

/* ── Visão geral ─────────────────────────────────────────────────────── */
/* A tela CABE numa tela: nada de rolar para ver indicador. Por isso ela é uma
   grade de duas colunas com altura controlada, e não uma pilha de blocos.

   Esquerda: os números descendo (o mesmo agrupamento do Streamlit).
   Direita: o que exige ação — alertas, conversão e a agenda do dia.

   A direita é fixa em 320px porque lista de visita e alerta são texto curto;
   quem precisa de largura é o gráfico. */
.vg {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 320px;
  gap: 12px;
  /* `flex: 1` + `min-height: 0` = "ocupe o que sobrou da tela, e encolha se
     precisar". Sem o `min-height`, uma grade nunca encolhe abaixo do conteúdo
     e a página volta a rolar. */
  flex: 1;
  min-height: 0;
}
.vg-esquerda, .vg-direita {
  display: flex;
  flex-direction: column;
  gap: 8px;
  min-width: 0;
}
.vg-faixa { min-width: 0; flex: none; }

/* O bloco que ESTICA para ocupar a altura que sobrar (o gráfico à esquerda, a
   agenda à direita). É o que faz as duas colunas terminarem juntas em vez de
   deixarem um vão embaixo.

   O seletor traz as DUAS classes de propósito. Com `.vg-cresce` sozinho, ele e
   o `.vg-faixa` acima têm o mesmo peso, e quem ganha é o último escrito no
   arquivo — que era o `flex: none`. Resultado medido em 18/08: 379px vazios no
   pé da coluna da direita, exatamente a queixa do dono. Empatar em
   especificidade e depender da ordem é o tipo de coisa que volta a quebrar na
   próxima vez que alguém reorganizar o arquivo. */
.vg-faixa.vg-cresce {
  flex: 1 1 0;
  display: flex;
  flex-direction: column;
  min-height: 0;
}
.vg-faixa.vg-cresce > .adm-cartao { flex: 1; min-height: 0; }
.vg-faixa .adm-grupo-kpi { margin: 0 0 6px; }

/* Três indicadores por faixa, sempre. `1fr` e não `auto-fill`: as três faixas
   precisam ficar com as colunas ALINHADAS entre si, senão a leitura vertical
   (Recebido embaixo de Agendamentos) se perde. */
.vg-kpis { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; }
/* O conteúdo fica CENTRADO na altura do cartão.

   Os três cartões de uma faixa têm a mesma altura (a grade estica todos até o
   mais alto), mas não a mesma quantidade de linhas: um tem barra de progresso,
   outro tem a repartição por tipo, e o do meio tem só rótulo, número e nota.
   Alinhado ao topo, o mais curto ficava com um vão embaixo e parecia torto —
   foi o que o dono viu no "Valor de hoje" (18/08). Centrado, cada cartão
   distribui a sobra em cima e embaixo, e a faixa fica visualmente equilibrada. */
.vg-kpi { padding: 9px 14px; }
.vg-kpi .adm-kpi-rotulo, .vg-kpi .adm-kpi-nota { margin: 0; }
.vg-kpi .adm-kpi-valor { font-size: 22px; margin: 2px 0 0; }
.vg-kpi .adm-kpi-nota  { margin-top: 1px; }

/* A linha que reparte o número de cima. Ela mora dentro do mesmo cartão, com
   letra menor: é detalhe do número, não um número novo. */
.vg-detalhe {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 10px;
  margin: 6px 0 0;
  padding-top: 6px;
  border-top: 1px solid var(--borda);
  font-size: 10.5px;
  color: var(--texto-fraco);
}
.vg-detalhe b { color: var(--texto); font-variant-numeric: tabular-nums; }

/* ── O gráfico ───────────────────────────────────────────────────────── */
.vg-grafico { display: flex; align-items: center; padding: 10px 12px; }
/* O desenho cresce com o cartão, dentro de limites: abaixo de 130px as
   barras viram traços; acima de ~300px o gráfico fica esticado e o ar entre
   as barras vira buraco. */
.vg-svg { width: 100%; height: 100%; min-height: 130px; max-height: 300px; overflow: visible; }

.vg-legenda {
  float: right;
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 10px; font-weight: 600; letter-spacing: 0;
  text-transform: none; color: var(--texto-fraco);
}
.vg-marca-barra, .vg-marca-linha { display: inline-block; }
.vg-marca-barra { width: 9px; height: 9px; border-radius: 2px; background: var(--ouro); }
.vg-marca-linha { width: 12px; height: 2px; border-radius: 2px; background: var(--azul); margin-left: 8px; }

.vg-barra {
  fill: var(--ouro);
  /* Sobe do chão, uma depois da outra. `transform-box: fill-box` faz o
     `transform-origin` valer dentro da própria barra — sem ele, o SVG usa a
     origem do desenho inteiro e as barras crescem do canto errado. */
  transform-box: fill-box;
  transform-origin: bottom;
  animation: vg-sobe .6s cubic-bezier(.2, .8, .2, 1) both;
  animation-delay: calc(var(--i) * 70ms);
}
@keyframes vg-sobe { from { transform: scaleY(0); } to { transform: scaleY(1); } }

.vg-area {
  fill: var(--azul);
  opacity: 0;
  animation: vg-aparece .8s ease-out .5s both;
}
@keyframes vg-aparece { to { opacity: .10; } }

.vg-linha {
  fill: none;
  /* Azul: a cor complementar da marca (o violeta fica reservado para a IA).
     Ele contrasta com o ouro das barras sem brigar — são cores opostas na
     roda, e o olho separa as duas séries sem precisar da legenda. */
  stroke: var(--azul);
  stroke-width: 2.5;
  stroke-linecap: round;
  stroke-linejoin: round;
  /* Desenha-se sozinha: o traço inteiro fica escondido e vai sendo revelado.
     É o mesmo princípio do anel logo abaixo. */
  stroke-dasharray: var(--traco);
  stroke-dashoffset: var(--traco);
  animation: vg-traca 1.1s ease-out .35s both;
}
@keyframes vg-traca { to { stroke-dashoffset: 0; } }

.vg-ponto {
  fill: var(--azul);
  stroke: var(--superficie);
  stroke-width: 2;
  opacity: 0;
  animation: vg-pontinho .3s ease-out both;
  animation-delay: calc(.6s + var(--i) * 90ms);
}
@keyframes vg-pontinho { from { transform: scale(.4); } to { opacity: 1; transform: scale(1); } }

.vg-num, .vg-mes { text-anchor: middle; font-family: inherit; }
.vg-num { fill: var(--texto); font-size: 12px; font-weight: 700; }
.vg-mes { fill: var(--texto-fraco); font-size: 10.5px; }

/* ── Consulta do mês (parar o mouse em cima) ─────────────────────────────
   Sem JavaScript: uma faixa transparente por mês recebe o ponteiro e, no
   `:hover`, acende a coluna e revela a caixinha.

   `fill: transparent` e NÃO `fill: none`: os dois desenham nada, mas só o
   primeiro continua recebendo o mouse. Com `none` a faixa vira buraco e o
   ponteiro atravessa. */
.vg-alvo {
  fill: transparent;
  transition: fill .15s ease;
}
.vg-col:hover .vg-alvo { fill: color-mix(in srgb, var(--ouro) 10%, transparent); }

/* A caixinha nasce escondida e não recebe mouse — se recebesse, ela mesma
   roubaria o ponteiro da faixa e piscaria ao aparecer debaixo do cursor. */
.vg-dica {
  opacity: 0;
  pointer-events: none;
  transition: opacity .15s ease;
}
.vg-col:hover .vg-dica { opacity: 1; }

.vg-dica-caixa {
  fill: var(--superficie);
  stroke: var(--borda);
  stroke-width: 1;
  /* A sombra é desenhada, e não `box-shadow`: dentro de SVG a propriedade de
     caixa não vale. */
  filter: drop-shadow(0 4px 10px rgba(0, 0, 0, .18));
}
.vg-dica-mes, .vg-dica-linha { text-anchor: middle; font-family: inherit; }
.vg-dica-mes { fill: var(--texto); font-size: 11.5px; font-weight: 700; }
.vg-dica-linha { fill: var(--texto-fraco); font-size: 10.5px; }
.vg-dica-dinheiro { fill: var(--azul); font-weight: 600; }

/* ── Anéis de conversão ──────────────────────────────────────────────── */
.vg-aneis { display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px; padding: 10px 8px 8px; }
.vg-anel { display: flex; flex-direction: column; align-items: center; }
/* O desenho e o número vivem na MESMA caixa, e o número cobre a caixa inteira
   com centralização de flex. A versão anterior o posicionava por `top` fixo,
   contra a posição estática do elemento — e ele saía do centro assim que o
   texto mudava de largura ("57%" contra "—"). O dono viu isso em 18/08. */
.vg-anel-desenho { position: relative; width: 60px; height: 60px; }
.vg-anel-desenho svg { width: 60px; height: 60px; display: block; }
.vg-anel-trilha { fill: none; stroke: var(--borda); stroke-width: 6; }
.vg-anel-cheio {
  fill: none;
  stroke: var(--ouro);
  stroke-width: 6;
  stroke-linecap: round;
  stroke-dasharray: var(--perimetro);
  /* Começa vazio (traço todo escondido) e corre até a fatia certa. */
  stroke-dashoffset: var(--perimetro);
  animation: vg-anel-enche 1s cubic-bezier(.2, .8, .2, 1) both;
  animation-delay: calc(.2s + var(--i) * 140ms);
}
@keyframes vg-anel-enche { to { stroke-dashoffset: var(--vazio); } }
/* Todos os anéis em ouro: a cor do produto. Antes o terceiro era violeta,
   e cor diferente sem significado diferente é ruído. */

.vg-anel-valor {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 15px; font-weight: 800;
  font-variant-numeric: tabular-nums;
}
.vg-anel-rotulo { margin-top: 6px; font-size: 11.5px; font-weight: 600; text-align: center; }
.vg-anel-nota   { font-size: 10.5px; color: var(--texto-fraco); text-align: center; }

/* ── Barra de progresso do dia ───────────────────────────────────────
   Fica no pé do cartão "Visitas do dia". É a única barra da tela e mostra o
   ritmo, não o total: número puro diz "8 visitas", a barra diz "metade
   feita". */
.vg-progresso {
  display: block;
  height: 4px;
  margin-top: 8px;
  border-radius: 999px;
  background: var(--borda);
  overflow: hidden;
  position: relative;
}
.vg-progresso::after {
  content: "";
  position: absolute;
  inset: 0 auto 0 0;
  width: var(--pct);
  border-radius: 999px;
  background: var(--ouro);
  /* Enche da esquerda para a direita, junto com a entrada da tela. */
  animation: vg-enche .9s cubic-bezier(.2, .8, .2, 1) both;
}
@keyframes vg-enche { from { width: 0; } to { width: var(--pct); } }

/* ── Exige ação ──────────────────────────────────────────────────────
   Este é o bloco que ESTICA. Numa dedetizadora movimentada são seis ou sete
   alertas, e é a informação mais perecível da tela — se faltar espaço, ele
   rola por dentro em vez de empurrar o resto para fora. */
.vg-acoes { overflow-y: auto; padding: 10px 12px; }

/* ── Propostas (pipeline) ────────────────────────────────────────────
   Lista de linhas, e não cartões lado a lado. A razão é medida: em três
   colunas de ~100px, "SEM RESPOSTA" quebrava em duas linhas e desalinhava o
   valor em relação aos vizinhos. Aqui o texto ocupa a coluna que sobra e o
   valor fica encostado à direita — o alinhamento não depende do comprimento
   de nada. */
.vg-lista { padding: 2px 12px; }
.vg-linha-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  /* 7px e não 9: as três linhas daqui disputam altura com os alertas, que são
     a informação mais perecível da coluna. Medido em 18/08: com 9px, o sexto
     alerta ficava 10px abaixo da dobra da caixa. */
  padding: 7px 2px;
  border-bottom: 1px solid var(--borda);
  color: inherit;
  text-decoration: none;
  transition: border-color var(--transicao);
}
.vg-linha-item:last-child { border-bottom: none; }
.vg-linha-item:hover .vg-linha-valor { color: var(--ouro); }
.vg-linha-item:focus-visible { outline: 2px solid var(--ouro); outline-offset: -2px; border-radius: 6px; }

.vg-linha-txt { display: flex; flex-direction: column; min-width: 0; }
.vg-linha-txt strong { font-size: 12.5px; font-weight: 600; }
.vg-linha-txt small  { font-size: 10.5px; color: var(--texto-fraco); line-height: 1.3; }

.vg-linha-valor {
  flex: none;
  font-size: 16px;
  font-weight: 800;
  letter-spacing: -.02em;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  transition: color var(--transicao);
}

/* Em tela estreita a grade vira uma coluna só e a rolagem volta — no celular
   ela é natural, e espremer duas colunas em 400px seria pior. */
@media (max-width: 1080px) {
  .vg { grid-template-columns: 1fr; }
  /* Em coluna única a página volta a rolar (natural no celular), então os
     blocos que esticavam passam a ter teto em vez de altura elástica. */
  .vg-acoes { max-height: 300px; }

  /* E param de ESTICAR (sessão 80, colisão vista pelo dono no celular).
     Medido a 375px: a seção "Exige ação" tinha altura ZERO e o conteúdo dela
     era desenhado 23px abaixo, por cima de "Conversão e qualidade".

     `flex: 1 1 0` quer dizer "não tenha altura própria, ocupe a sobra". No
     computador existe sobra: a grade tem a altura da tela. Em coluna única a
     página volta a rolar, a linha da grade passa a ter a altura do CONTEÚDO e
     a sobra é zero - então o bloco fica com zero e o conteúdo transborda, sem
     erro nenhum, por cima do vizinho.

     Era a mesma causa do gráfico "achatado" no celular: ele também é
     `vg-cresce`, e também colapsava para altura zero. Escondê-lo lá tapou o
     sintoma dele; isto aqui cura a causa dos dois. */
  .vg-faixa.vg-cresce { flex: 0 0 auto; }
}
@media (max-width: 620px) {
  .vg-kpis { grid-template-columns: 1fr; }

  /* O gráfico SOME no celular (decisão do dono, sessão 80, olhando no
     aparelho). O desenho tem 600 por 170 unidades: espremido em ~330px de
     largura ele vira uma tira de 94px de altura, onde as barras viram traços
     e a linha do dinheiro encosta no nome dos meses. Não é gráfico, é ruído.

     E não se perde informação: o que ele mostra — OS concluídas e dinheiro
     recebido — já está escrito nos cartões de número logo acima, que no
     celular ficam em coluna e sobram legíveis. A consulta por mês depende de
     parar o mouse em cima, gesto que no telefone não existe.

     `display: none` no cartão inteiro, e não só no SVG, para não deixar uma
     moldura vazia com o título "Desempenho" em cima de nada.

     As TRÊS classes no seletor não são exagero - são necessidade, e isto foi
     visto medindo no navegador, não deduzido. A seção também casa com
     `.vg-faixa.vg-cresce`, que declara `display: flex`. Duas classes pesam
     mais que uma, então `.vg-desempenho` sozinho PERDIA e o gráfico continuava
     na tela do celular. Media query não acrescenta peso nenhum a essa conta. */
  .vg-faixa.vg-cresce.vg-desempenho { display: none; }
}

/* ── O celular (medido em 375px, 19/08) ──────────────────────────────
   A linha da visita tem quatro colunas — hora, cliente, marcas de check-in e
   estado. Em 330px de cartão elas não cabem lado a lado: o CLIENTE, que é a
   informação mais importante da linha, ficava com 35px e o nome era cortado em
   14 das 15 visitas. Então ela quebra em duas: quem e quando em cima, as
   marcas embaixo, alinhadas com o nome. */
@media (max-width: 560px) {
  .eq-visita { flex-wrap: wrap; row-gap: 5px; }
  .eq-hora   { min-width: 62px; }
  .eq-quem   { flex: 1 1 120px; }
  /* `order` alto joga as marcas para a segunda linha; o selo, que vem depois
     no HTML, sobe para o fim da primeira. */
  .eq-marcas { order: 5; flex-basis: 100%; justify-content: flex-start;
               padding-left: 62px; }

  /* O ranking tem três colunas — nome, barra, valor. Em 330px o nome fica com
     190px, sobram 25px para a BARRA, e uma barra de 25px não compara nada: ela
     é a razão de o bloco existir. No celular o nome e o valor dividem a
     primeira linha e a barra fica com a segunda inteira.

     O nome também passa a QUEBRAR em vez de ser cortado: "Barata Americana
     (Periplaneta americana)" virava "Barata Americana (Periplanet…". */
  .sub-rank { grid-template-columns: 1fr auto; row-gap: 7px; }
  .sub-rank-nome  { grid-column: 1; white-space: normal; overflow: visible; }
  .sub-rank-valor { grid-column: 2; }
  .sub-rank-barra { grid-column: 1 / -1; grid-row: 2; }
}


/* Rótulo que separa os blocos de indicadores. Mesma linguagem dos grupos da
   barra lateral, para a tela e o menu falarem igual. */
.adm-grupo-kpi {
  margin: 20px 0 8px;
  color: var(--texto-fraco);
  font-size: 10.5px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .1em;
}
.adm-conteudo > .adm-grupo-kpi:first-of-type { margin-top: 6px; }

/* Alertas: uma linha por pendência, cada uma levando à tela que resolve. */
.adm-alertas { display: flex; flex-direction: column; gap: 5px; }
/* Compacto de propósito. O sistema sabe gerar SEIS alertas ao mesmo tempo
   (contas vencidas, aprovações, follow-ups, estoque, reaplicações vencidas e a
   vencer). Medido em 18/08 com sete na tela: no tamanho anterior, dois ficavam
   escondidos atrás da rolagem — e alerta escondido é alerta perdido. */
.adm-alerta {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 6px 11px;
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  background: var(--superficie);
  color: var(--texto);
  text-decoration: none;
  font-size: 12.5px;
  line-height: 1.35;
  transition: border-color var(--transicao), transform var(--transicao);
}
.adm-alerta:hover { border-color: var(--borda-forte); transform: translateX(2px); }
.adm-alerta:focus-visible { outline: 2px solid var(--azul); outline-offset: 2px; }
/* O nível vira uma bolinha, e não o fundo inteiro colorido: com quatro alertas
   ativos, quatro faixas coloridas deixam a tela parecendo um alarme. */
.adm-alerta-ponto {
  flex: none; width: 8px; height: 8px; border-radius: 999px;
  background: var(--texto-fraco);
}
.nivel-vermelho .adm-alerta-ponto { background: var(--vermelho); }
.nivel-laranja  .adm-alerta-ponto { background: var(--laranja); }
.nivel-amarelo  .adm-alerta-ponto { background: var(--ouro); }
.nivel-azul     .adm-alerta-ponto { background: var(--texto-fraco); }

.adm-tudo-certo {
  margin: 0;
  padding: 9px 14px;
  border: 1px solid var(--verde-borda);
  border-radius: var(--raio);
  background: var(--verde-fundo);
  color: var(--verde-txt);
  font-size: 13.5px;
}

/* Cartão de indicador. Ele é um LINK, então precisa desfazer o que o navegador
   faz com link: sublinhado e azul.

   Isto já quebrou uma vez (18/08): o template passou a usar a classe `vg-kpi` e
   estas regras, presas ao nome antigo, deixaram de valer — os nove indicadores
   viraram links azuis sublinhados. Por isso o seletor cobre os dois nomes. */
.adm-kpi, .vg-kpi {
  /* Coluna centrada na vertical: os três cartões de uma faixa têm a mesma
     altura, mas não a mesma quantidade de linhas (um tem barra de progresso,
     outro a repartição por tipo). Alinhado ao topo, o mais curto ficava com um
     vão embaixo e parecia torto. */
  display: flex;
  flex-direction: column;
  justify-content: center;
  color: inherit;
  text-decoration: none;
  transition: border-color var(--transicao), transform var(--transicao);
}
a.adm-kpi:hover, a.vg-kpi:hover {
  border-color: var(--borda-forte);
  transform: translateY(-2px);
  box-shadow: 0 2px 4px rgba(20, 24, 27, .07),
              0 12px 24px rgba(20, 24, 27, .08);
}
a.adm-kpi:focus-visible, a.vg-kpi:focus-visible { outline: 2px solid var(--ouro); outline-offset: 2px; }
/* Só o cartão de vencido muda de cor, e só quando há o que cobrar. */
/* Os dois cartões que MUDAM DE COR, e só eles: o dinheiro que entrou e o que
   está atrasado. Cor aqui não é enfeite — é o resumo do mês em um relance.
   O verde é mais discreto que o vermelho de propósito: receber é o normal,
   atrasar é o que precisa de reação. */
/* O fundo preenchido saiu em 18/08: um retângulo vermelho inteiro no meio de
   nove cartões brancos gritava, e o dono preferiu o tratamento discreto do
   verde. Agora os dois falam a mesma língua — borda e número coloridos, fundo
   igual ao dos outros. */
.adm-kpi.alerta, .vg-kpi.alerta { border-color: var(--vermelho-borda); }
.adm-kpi.alerta .adm-kpi-valor, .vg-kpi.alerta .adm-kpi-valor { color: var(--vermelho-txt); }
.vg-kpi.positivo { border-color: var(--verde-borda); }
.vg-kpi.positivo .adm-kpi-valor { color: var(--verde-txt); }

/* `tabular-nums` deixa todo algarismo com a mesma largura. Sem isso, a coluna
   de valores "dança" quando o número muda — o 1 é mais estreito que o 8. */
.adm-kpi-valor { font-variant-numeric: tabular-nums; }

/* Agenda do dia: uma linha por visita. */
.adm-vazio-linha { margin: 6px 0 0; color: var(--texto-fraco); font-size: 13.5px; }

.adm-vazio {
  padding: 30px 18px;
  border: 1px dashed var(--borda-forte);
  border-radius: var(--raio-g);
  color: var(--texto-fraco);
  text-align: center;
}

/* ── Login ───────────────────────────────────────────────────────────── */
/* A tela de entrada é a única sem lateral, e é CLARA em qualquer tema (decisão
   do dono, 17/08): ela não segue o tema do aparelho de propósito — é a
   primeira impressão do produto, e primeira impressão não pode depender de
   configuração de quem olha. Por isso tudo aqui aponta para os tokens `--l-*`
   (a paleta clara) na mão, em vez dos nomes normais: num aparelho no modo
   escuro, `--superficie` seria quase preto e a página sumiria.

   A GEOMETRIA é a mesma da página principal do painel (decisão do dono,
   20/08): moldura clara por fora, página branca de cantos redondos apoiada em
   cima, e dentro dela dois retângulos — o formulário e o painel da arte. Só
   linhas retas com canto redondo; a versão anterior separava os dois lados com
   uma onda desenhada, e ela saiu.

   `min-height: 100dvh` não é detalhe: sem ele o corpo da página termina onde o
   conteúdo termina e a moldura corta numa linha reta no meio da tela. `100dvh`
   e não `100vh` porque no celular a barra de endereço come parte da `vh`. */
body.adm-entrada {
  min-height: 100dvh;
  padding: var(--moldura-folga);
  background: var(--l-moldura);
  color: var(--l-texto);
  display: grid;
}

/* Três níveis de profundidade, os mesmos do painel (moldura → painel →
   cartão): a moldura no fundo, esta página em cima dela, e dentro dela o
   painel escuro e o cartão branco do login. Sem o nível do meio ser mais
   fundo que o cartão, o cartão não teria como flutuar. */
.adm-entrada-pagina {
  background: var(--l-fundo);
  border: 1px solid var(--l-borda);
  border-radius: var(--raio-painel);
  /* Duas sombras somadas, como nos cartões do painel: uma rente à borda, que
     dá o contorno que a borda sozinha quase não faz no claro, e outra larga e
     diluída, que separa a página da moldura. */
  box-shadow: 0 1px 2px rgba(20, 24, 27, .06),
              0 10px 30px rgba(20, 24, 27, .07);
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--moldura-folga);
  padding: var(--moldura-folga);
  overflow: hidden;
}

/* ── O painel da arte ────────────────────────────────────────────────── */
/* Ele NÃO tem padding e NÃO é flex, de propósito. Medido em 20/08: com padding
   e `display:flex` aqui, tanto a camada do degradê (`inset: 0`) quanto a teia
   (`left: 100%`) são espremidas para dentro da caixa de CONTEÚDO — o degradê
   deixava uma tarja escura de 34px em volta do painel e o miolo da teia não
   pousava no canto. Quem afasta o texto das bordas é `.adm-arte-txt`. */
.adm-arte {
  position: relative;
  overflow: hidden;      /* é ele que recorta a teia pelo canto redondo */
  border-radius: var(--raio-painel);
  background: var(--d-fundo);
  color: var(--d-texto);
  /* A arte fica à ESQUERDA e o formulário à direita (decisão do dono, 20/08).
     Feito por `order` e não trocando o HTML: no teclado, o formulário deve
     continuar recebendo o foco antes da decoração. O mesmo `-1` serve ao
     celular, onde a única coluna vira duas linhas e a arte sobe para o topo. */
  order: -1;
}

/* O brilho. UM só, azul — a cor complementar da identidade v2. Havia mais duas
   manchas douradas (uma no alto à esquerda, outra no pé); o dono mandou tirar
   as duas em 20/08. O ouro não sumiu do painel: ele segue na marca e na teia,
   que é justamente onde ele deve estar. E o lado do texto ficou carvão liso,
   o que só ajuda a leitura do slogan. */
.adm-arte-fundo {
  position: absolute;
  inset: 0;
  overflow: hidden;
  border-radius: inherit;
  background:
    radial-gradient(110% 80% at 96% 30%, rgba(76, 111, 255, .26), transparent 60%);
}

/* A teia (desenhada por cálculo em `admin_web._teia_svg`). O miolo dela é o
   canto 0,0 do desenho, que fica no canto superior ESQUERDO da caixa: para o
   miolo pousar no canto do painel e a teia crescer para dentro, a caixa começa
   na borda direita (`left: 100%`) e é espelhada em torno desse mesmo ponto.
   A máscara radial faz o fio APAGAR ao se afastar, em vez de terminar cortado
   numa linha reta. */
.adm-teia {
  position: absolute;
  left: 100%;
  top: 0;
  width: 780px;
  height: 780px;
  color: var(--d-ouro);
  /* 20%: escolhido pelo dono em 20/08 olhando um controle deslizante sobre a
     tela de verdade. A 17% ele não a encontrava sozinho — e motivo de marca
     que ninguém percebe não paga o que custa. Acima de ~35% ela deixa de ser
     textura e começa a disputar com o slogan. */
  opacity: .20;
  pointer-events: none;
  transform: scaleX(-1);
  transform-origin: left top;
  -webkit-mask-image: radial-gradient(circle at 0 0, #000 0, #000 22%, transparent 72%);
          mask-image: radial-gradient(circle at 0 0, #000 0, #000 22%, transparent 72%);
}

.adm-arte-txt {
  position: relative;
  z-index: 2;
  height: 100%;
  padding: 38px 34px;
  display: flex;
  flex-direction: column;
}
.adm-arte-marca { line-height: 0; }
/* `auto` em cima e embaixo joga o texto para o MEIO do espaço que sobra
   abaixo da marca (pedido do dono, 20/08). Antes era `auto 0 0`, que empurrava
   tudo para o pé do painel. */
.adm-arte-frases { margin: auto 0; }
.adm-arte-frases h2 {
  margin: 0 0 16px;
  font-size: 30px;
  line-height: 1.24;
  font-weight: 700;
  letter-spacing: -.015em;
  /* Reparte as linhas de forma pareja em vez de encher a primeira e largar uma
     palavra sozinha na última — sem isso "para" ficava numa linha só dele
     (apontado pelo dono, 20/08). Navegador que ainda não conhece a propriedade
     ignora; por isso o template também amarra "para" à palavra seguinte com um
     espaço inquebrável. */
  text-wrap: balance;
}
.adm-arte-frases h2 em { font-style: normal; color: var(--d-ouro); }
.adm-arte-frases p {
  margin: 0;
  font-size: 14.5px;
  line-height: 1.62;
  color: var(--d-texto-fraco);
}

/* ── O lado do formulário ────────────────────────────────────────────── */
.adm-entrada-lado { display: grid; place-items: center; padding: 30px 26px; }
/* O cartão flutuante do login (pedido do dono, 20/08). Duas sombras somadas,
   a mesma receita dos cartões do painel: uma rente à borda, que dá o contorno
   que a borda sozinha quase não faz no claro, e outra larga e diluída, que
   descola o cartão da página. */
.adm-entrada-caixa {
  width: 100%;
  max-width: 374px;
  background: var(--l-superficie);
  border: 1px solid var(--l-borda);
  border-radius: var(--raio-painel);
  padding: 32px 28px 30px;
  box-shadow: 0 1px 2px rgba(20, 24, 27, .06),
              0 12px 32px rgba(20, 24, 27, .09);
}
.adm-entrada-topo { text-align: center; margin-bottom: 26px; }
.adm-entrada-topo h1 {
  margin: 0 0 5px;
  font-size: 24px;
  font-weight: 700;
  color: var(--l-texto);
  letter-spacing: -.01em;
}
.adm-entrada-topo p { margin: 0; font-size: 14px; color: var(--l-texto-fraco); }

/* Os campos não podem herdar os tokens do tema: num aparelho no modo escuro
   eles nasceriam pretos dentro da página branca. */
.adm-entrada .campo { margin-bottom: 12px; }
.adm-entrada .campo > span { color: var(--l-texto-fraco); }
.adm-entrada .campo input {
  background: var(--l-superficie);
  border: 1px solid var(--l-borda-forte);
  color: var(--l-texto);
}
.adm-entrada .campo input:focus {
  border-color: var(--l-ouro);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--l-ouro) 15%, transparent);
}

/* O olho da senha. O gestor digita no celular, muitas vezes no sol, e senha
   errada aqui custa um bloqueio de conta. O botão nasce `hidden` no HTML e só
   aparece quando o script assume — assim, sem JavaScript, ninguém vê um botão
   que não faz nada. */
.adm-olho { position: relative; display: block; }
.adm-olho input { padding-right: 44px; }
.adm-olho-btn {
  position: absolute;
  right: 6px;
  top: 50%;
  transform: translateY(-50%);
  background: none;
  border: none;
  padding: 7px;
  line-height: 0;
  cursor: pointer;
  color: var(--l-texto-fraco);
  border-radius: 8px;
}
.adm-olho-btn:hover { background: color-mix(in srgb, var(--l-texto) 7%, transparent); }
.adm-olho-btn:focus-visible { outline: 2px solid var(--l-ouro); outline-offset: 1px; }

/* Embaixo do campo de senha, e não ao lado do rótulo (decisão do dono, 20/08):
   é onde o olho já está quando a senha não entra. */
.adm-esqueci-linha { text-align: right; margin: -2px 0 18px; }
.adm-esqueci {
  font-size: 12.5px;
  font-weight: 600;
  color: var(--l-ouro);
  text-decoration: none;
}
.adm-esqueci:hover { text-decoration: underline; }

.adm-entrada-btn {
  width: 100%;
  padding: 12px;
  border: none;
  border-radius: var(--raio);
  /* Ouro VIVO com texto carvão, e não o ouro escurecido com texto branco: sobre
     branco, ouro escuro + branco dá 3,6:1 de contraste, abaixo do mínimo de
     4,5:1 para texto deste tamanho. Assim são 11:1 e a marca fica mais viva. */
  background: var(--d-ouro);
  color: var(--l-texto);
  font: inherit;
  font-size: 15px;
  font-weight: 700;
  cursor: pointer;
  transition: var(--transicao);
}
.adm-entrada-btn:hover { filter: brightness(1.06); }
.adm-entrada-btn:focus-visible { outline: 2px solid var(--l-texto); outline-offset: 2px; }

.adm-entrada .aviso {
  background: var(--l-vermelho-fundo);
  border: 1px solid var(--l-vermelho-borda);
  color: var(--l-vermelho-txt);
  margin-bottom: 14px;
}

/* O texto da tela de recuperação de senha, que divide a mesma moldura. */
.adm-entrada-texto { margin: 0 0 14px; font-size: 14px; line-height: 1.62;
                     color: var(--l-texto-fraco); }
.adm-entrada-texto:last-of-type { margin-bottom: 22px; }
.adm-entrada-texto strong { color: var(--l-texto); }
/* Lá o "botão" é um link de verdade (ele NAVEGA, não envia formulário), então
   herda o visual do botão e só corrige o que muda entre <a> e <button>. */
a.adm-entrada-btn { display: block; text-align: center; text-decoration: none; }

/* ── A entrada no celular ────────────────────────────────────────────── */
@media (max-width: 900px) {
  .adm-entrada-pagina { grid-template-columns: 1fr; grid-template-rows: auto 1fr; }
  /* A arte não some — é ela que diz o que o produto é, e é no celular que o
     dono mostra isso na feira. Ela vira uma faixa no alto, com o mesmo canto
     redondo (o `order: -1` que a põe em cima já vem da regra base). */
  .adm-arte { min-height: 268px; }
  .adm-arte-txt { padding: 22px 20px 24px; }
  .adm-teia { width: 520px; height: 520px; }
  .adm-arte-frases h2 { font-size: 23px; margin-bottom: 0; }
  /* A lista longa some (decisão do dono, 20/08): ela existe para quem lê por
     cima do ombro numa tela grande. No telefone rouba a altura do formulário,
     e ninguém lê dez itens numa faixa de 268px. */
  .adm-arte-frases p { display: none; }
  .adm-entrada-lado { padding: 26px 12px 20px; align-items: start; }
}

/* Celular BAIXO (Android antigo, ou navegador com barra grande). Medido em
   20/08 num 360x640: com a faixa em 268px a página pedia 694px e o botão
   "Entrar" ficava 22px abaixo da dobra. Numa tela de login, ter que rolar
   para achar o botão de entrar é defeito, não detalhe. A faixa encolhe; a
   marca e o slogan continuam cabendo (a soma deles é ~163px). */
@media (max-width: 900px) and (max-height: 720px) {
  .adm-arte { min-height: 196px; }
  .adm-arte-txt { padding: 18px 20px 20px; }
  .adm-arte-frases h2 { font-size: 21px; }
  .adm-entrada-topo { margin-bottom: 18px; }
  /* 8px embaixo e não 16: com o cartão do login, a 360x640 sobravam
     exatamente 8px de rolagem. Medido em 20/08. */
  .adm-entrada-lado { padding: 20px 12px 8px; }
  .adm-entrada-caixa { padding: 22px 18px 20px; }
}

/* ── Celular ─────────────────────────────────────────────────────────── */
/* A lateral vira gaveta. O interruptor é um <input type="checkbox"> escondido,
   e não JavaScript: assim o menu continua abrindo mesmo se um script quebrar,
   e não existe estado para dessincronizar. */
.adm-menu-alvo { display: none; }
.adm-menu-btn  { display: none; }
.adm-menu-fundo { display: none; }

@media (max-width: 900px) {
  /* Moldura mais fina: no celular cada pixel de largura conta, e 10px de cada
     lado tirariam 20px do conteúdo. */
  :root { --moldura-folga: 6px; --raio-painel: 16px; }
  .adm-grade { grid-template-columns: 1fr; }

  .adm-lateral {
    position: fixed;
    top: 0;
    left: 0;
    z-index: 20;
    width: 270px;
    height: 100dvh;
    /* Como gaveta ela sai da moldura e encosta na lateral da tela: os cantos
       arredondados ficam só do lado que aparece. */
    border-radius: 0 var(--raio-painel) var(--raio-painel) 0;
    transform: translateX(-100%);
    transition: transform .2s ease;
  }
  .adm-menu-alvo:checked ~ .adm-grade .adm-lateral { transform: translateX(0); }

  /* Véu escuro por cima do conteúdo: clicar nele fecha a gaveta (é um <label>
     apontando para o mesmo checkbox). */
  .adm-menu-alvo:checked ~ .adm-grade .adm-menu-fundo {
    display: block;
    position: fixed;
    inset: 0;
    z-index: 15;
    background: rgba(0, 0, 0, .5);
  }

  .adm-menu-btn { display: inline-flex; }
  .adm-topo     { padding: 12px 16px; }
  .adm-conteudo { padding: 16px 16px 48px; }
  .adm-titulo   { font-size: 17px; }

  /* As sete abas do Dashboard ocupam 284px e estavam com `flex: none`, ou
     seja: não encolhiam por nada. Num celular de 375px elas empurravam o
     SINO DE NOTIFICAÇÕES para fora da tela — o gestor não tinha como abrir os
     avisos (medido em 19/08). Agora a faixa de abas encolhe e rola sozinha, e
     os botões do topo voltam para dentro. A rolagem já estava pronta:
     `overflow-x: auto` sem barra visível. */
  .adm-abas { flex: 0 1 auto; min-width: 0; scroll-snap-type: x proximity; }
  /* `flex: none` nas ABAS, e não só no container: sem isto elas encolhiam de
     38px para 26px em vez de rolar — sete alvos apertados demais para o dedo,
     com o ícone de 19px quase encostando na borda. Agora elas mantêm o
     tamanho e a faixa é que rola. */
  .adm-aba  { flex: none; scroll-snap-align: center; }
}

/* Quem configurou "reduzir movimento" no aparelho não recebe a animação da
   gaveta nem as transições — é ajuste de acessibilidade, não enfeite. */
@media (prefers-reduced-motion: reduce) {
  .adm-lateral, .adm-item, .adm-acao, .adm-icone { transition: none; }
  .adm-grupo-link { animation: none; }  /* fica no ouro, parado */
  /* O "up" dos cartões (19/08): a COR e a faixa continuam — elas são
     informação. Some só o que se mexe: a entrada em cascata, o encher das
     barras, o pulso do "em serviço" e o levantar no hover. */
  .eq-grade > *, .sub-kpis > *, .eq-progresso i, .sub-rank-barra i,
  .kpi-barra i { animation: none; }
  .eq-progresso i, .sub-rank-barra i, .kpi-barra i { width: var(--pct); }
  .eq-card .vg-pill.cor-verde::before { animation: none; }
  .eq-card, .vg-kpi, .adm-kpi, .eq-visita { transition: none; }
  .eq-card:hover, .vg-kpi:hover, .adm-kpi:hover { transform: none; }
}

/* ══ AGENDA ═══════════════════════════════════════════════════════════════
   Duas colunas: o calendário do mês, largo, e a coluna da direita, que mostra
   o DIA escolhido ou a FICHA de uma visita — nunca os dois. Empilhar os dois
   faria a coluna crescer e obrigaria a rolar para ver o que acabou de abrir.

   A regra de cor desta tela, e ela vale em todo lugar:
     · a COR diz a SITUAÇÃO (agendado, em andamento, concluído, pendente);
     · o CONTORNO tracejado diz que é VISITA TÉCNICA (vistoria, sem preço).
   São dois eixos, e misturá-los numa cor só foi o erro do primeiro desenho:
   o gestor via verde e não sabia se era "deu certo" ou "é vistoria".

   Nada aqui depende de JavaScript. O abre-e-fecha das ações é o `<details>` do
   próprio navegador, e a navegação inteira é link. */

.ag {
  display: grid;
  /* 340px é o mínimo em que a rota do dia ainda se lê (hora, nome, endereço em
     três linhas). Tudo o que sobra vai para o calendário, que é quem precisa
     de largura: a 1280px de tela, cada dia fica com ~80px em vez dos 71px que
     a primeira medição deu — e 71px cortava "14:00 Padaria" no meio. */
  grid-template-columns: minmax(0, 1fr) 340px;
  gap: 14px;
  align-items: start;

  /* Onde a coluna da direita GRUDA: o pé da barra do topo mais uma folga.
     A conta: folga da moldura (10) + altura da barra (53) + respiro (11). */
  --ag-topo: 74px;
  /* A altura que sobra da janela depois da moldura, da barra e das folgas do
     conteúdo (10 + 53 + 18 em cima, 20 embaixo). */
  --ag-alto: clamp(460px, calc(100dvh - 101px), 920px);
}

/* ── O recado depois de uma ação ───────────────────────────────────────
   Ele nasce do código que a ação devolveu, nunca do que alguém digitou. */
.ag-recado, .cl-recado {
  margin: 0 0 12px;
  padding: 10px 14px;
  border-radius: var(--raio);
  border: 1px solid var(--borda);
  font-size: 13.5px;
  line-height: 1.45;
}
.ag-recado.ok, .cl-recado.ok       { background: var(--verde-fundo);    border-color: var(--verde-borda);    color: var(--verde-txt); }
.ag-recado.aviso, .cl-recado.aviso { background: var(--laranja-fundo);  border-color: var(--laranja-borda);  color: var(--laranja-txt); }

/* Serviços fechados pelo comercial, esperando horário (29/09): uma faixa no
   topo da Agenda, com um link por cliente. */
.ag-para-agendar {
  margin: 0 0 14px; padding: 10px 14px;
  border: 1px solid var(--laranja-borda); border-radius: var(--raio);
  background: var(--laranja-fundo);
}
.ag-para-agendar-titulo { margin: 0 0 6px; font-size: 13px; font-weight: 700; color: var(--laranja-txt); }
.ag-para-agendar ul { margin: 0; padding: 0; list-style: none; display: flex; flex-wrap: wrap; gap: 6px 18px; }
.ag-para-agendar a { color: var(--azul); font-weight: 600; text-decoration: none; font-size: 13px; }
.ag-para-agendar a:hover { text-decoration: underline; }
.ag-para-agendar small { margin-left: 4px; font-size: 11.5px; color: var(--texto-fraco); }
.ag-recado.erro, .cl-recado.erro   { background: var(--vermelho-fundo); border-color: var(--vermelho-borda); color: var(--vermelho-txt); }

/* ── A barra do mês ───────────────────────────────────────────────────── */
.ag-calendario {
  padding: 13px 15px 11px;
  /* O mês INTEIRO cabe na tela, sem rolar. Isso é regra, não meta: um
     calendário que precisa de rolagem para mostrar a última semana deixa de
     ser um mapa do mês. A altura vem da janela e as seis linhas se dividem
     dentro dela — em tela alta as células crescem, em tela baixa encolhem. */
  height: var(--ag-alto);
  display: flex;
  flex-direction: column;

  /* O calendário responde à PRÓPRIA largura, e não à da janela. É a diferença
     que importa aqui: a mesma janela de 1280px dá 583px de calendário com a
     ficha aberta ao lado e 903px sem ela, e uma média query não sabe disso —
     ela olha a janela. Com `container-type`, a regra do nome do cliente na
     etiqueta decide pelo espaço que existe de verdade.

     `inline-size` e NÃO `size`: contenção nos dois eixos faria o calendário
     ignorar a própria altura, e é dela que a grade das semanas depende. */
  container-type: inline-size;
  container-name: calendario;
}

.ag-barra {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 11px;
}
.ag-navegacao { display: flex; align-items: center; gap: 4px; }

.ag-mes {
  margin: 0;
  /* Largura mínima para o título não empurrar as setas de lugar a cada mês:
     "Maio de 2026" e "Setembro de 2026" têm larguras bem diferentes, e sem
     isto o "›" dançava horizontalmente ao navegar. */
  min-width: 172px;
  text-align: center;
  font-size: 17px;
  font-weight: 800;
  letter-spacing: -.02em;
}

.ag-seta {
  display: inline-flex; align-items: center; justify-content: center;
  width: 30px; height: 30px;
  border-radius: 9px;
  border: 1px solid var(--borda);
  background: var(--superficie);
  color: var(--texto-fraco);
  font-size: 19px; line-height: 1;
  text-decoration: none;
  transition: border-color .15s ease, color .15s ease, background .15s ease;
}
.ag-seta:hover { border-color: var(--borda-forte); color: var(--texto); }
.ag-seta:focus-visible { outline: 2px solid var(--azul); outline-offset: 2px; }
.ag-seta.pequena { width: 26px; height: 26px; font-size: 16px; border-radius: 8px; }

.ag-hoje {
  padding: 5px 12px;
  border-radius: 999px;
  border: 1px solid var(--azul-borda);
  background: var(--azul-fundo);
  color: var(--azul);
  font-size: 12.5px; font-weight: 600;
  text-decoration: none;
}
.ag-hoje:hover { border-color: var(--azul); }

.ag-conta { margin-left: auto; font-size: 12px; color: var(--texto-fraco); }

/* ── A grade do mês ───────────────────────────────────────────────────── */
/* A grade OCUPA a altura que sobrou e as semanas se dividem por igual. É o que
   faz o mês inteiro caber na tela sem rolagem: em vez de as células terem uma
   altura fixa que soma mais que a janela, é a janela que decide a altura da
   célula. Numa tela alta elas crescem; numa baixa, encolhem até o limite. */
.ag-grade { display: flex; flex-direction: column; gap: 4px; flex: 1; min-height: 0; }

.ag-semana {
  display: grid;
  /* `minmax(0, 1fr)` e não `1fr`: com `1fr` puro, um nome de cliente comprido
     dentro da etiqueta empurra a coluna e a grade deixa de ter sete partes
     iguais — a semana entorta a partir da terça. */
  grid-template-columns: repeat(7, minmax(0, 1fr));
  gap: 4px;
  flex: 1;
  min-height: 0;
}
.ag-semana.ag-cabecalho { flex: none; }

.ag-dia-nome {
  text-align: center;
  padding-bottom: 3px;
  font-size: 11px; font-weight: 700;
  letter-spacing: .06em;
  color: var(--texto-fraco);
}

.ag-dia {
  display: flex;
  flex-direction: column;
  gap: 3px;
  /* `min-height: 0` e não um piso em pixels: quem manda na altura é a grade,
     que divide o que sobrou da janela. Um piso aqui faria a soma das seis
     linhas estourar de novo a tela em janelas baixas — que é exatamente o
     defeito que esta mudança corrige. */
  min-height: 0;
  /* O que não couber na célula é CORTADO, não empurra a grade. O número total
     de visitas do dia continua dito pela pílula no canto, então cortar uma
     etiqueta não esconde informação — só encurta a prévia. */
  overflow: hidden;
  padding: 5px 6px 6px;
  border: 1px solid var(--borda);
  border-radius: 10px;
  background: var(--superficie);
  color: inherit;
  text-decoration: none;
  overflow: hidden;
  transition: border-color .15s ease, background .15s ease;
}
.ag-dia:hover { border-color: var(--borda-forte); }
.ag-dia:focus-visible { outline: 2px solid var(--azul); outline-offset: 1px; }

/* Dia do mês vizinho: continua na grade (senão a semana ficaria com buraco e
   as colunas deixariam de ser dias da semana), mas apagado. */
.ag-dia.fora { opacity: .4; }

/* Dia em que a empresa não trabalha. Fundo mais fundo, não borda diferente:
   assim o domingo vazio parece domingo, e não um domingo esquecido. */
.ag-dia.folga { background: var(--fundo); }

/* HOJE e DIA ABERTO são coisas diferentes e por isso têm marcas diferentes.
   Se fossem os dois um anel, o dia que é hoje E está aberto teria dois anéis
   concorrendo. Hoje = o NÚMERO em ouro; aberto = o ANEL azul na célula. */
.ag-dia.hoje .ag-numero {
  background: var(--ouro);
  color: var(--ouro-contra);
  border-radius: 999px;
  padding: 1px 7px;
}
.ag-dia.aberto {
  border-color: var(--azul);
  box-shadow: inset 0 0 0 1px var(--azul);
}

/* A linha de cima da célula: o dia à esquerda, quantas visitas à direita. */
.ag-dia-cabeca {
  display: flex; align-items: center; justify-content: space-between; gap: 4px;
  flex: none;
}

.ag-numero {
  font-size: 12px; font-weight: 700;
  font-variant-numeric: tabular-nums;
  /* Dentro do conteúdo do painel `--texto-fraco` VALE `--texto` (decisão de
     19/08: hierarquia por tamanho e peso, não por desbotar a cor). Escrever as
     duas regras aqui seria escrever a mesma cor duas vezes; quem apaga o dia do
     mês vizinho é a opacidade em `.ag-dia.fora`. */
  color: var(--texto-fraco);
}

/* Quantas visitas o dia tem, ao todo.
   Ela substituiu o "+3" que ficava embaixo das etiquetas, e por um motivo de
   honestidade: agora a célula CORTA o que não cabe conforme a altura da tela,
   e um "+3" calculado no servidor passaria a mentir em janela baixa. O total
   do dia é verdade em qualquer altura, e ainda diz mais — "este dia tem 17
   visitas" se lê de longe. Só aparece a partir de duas: com uma, a própria
   etiqueta já contou. */
.ag-conta-dia {
  flex: none;
  min-width: 17px;
  padding: 0 5px;
  border-radius: 999px;
  background: var(--fundo);
  border: 1px solid var(--borda);
  font-size: 10px; font-weight: 700;
  line-height: 15px;
  text-align: center;
  font-variant-numeric: tabular-nums;
  color: var(--texto-fraco);
}

/* A prévia do dia: quadradinhos de horário que QUEBRAM EM LINHA.
   Antes eram linhas empilhadas com hora e nome do cliente, e a terceira saía
   cortada ao meio pelo corte da célula (achado do dono, 22/08). Em linha, cada
   etiqueta ou aparece inteira ou não aparece — nunca pela metade.

   `--linha-chip` é a altura de uma fileira (etiqueta + respiro). O teto é
   escrito em FILEIRAS INTEIRAS, e é isso que impede o corte no meio. */
.ag-chips {
  /* A altura da etiqueta é CRAVADA, e não deixada para o `line-height` decidir.
     Sem isso ela mede 16,6px em vez de 17, a terceira fileira começa em 39,2
     dentro de uma caixa de 40, e 0,8px dela espia por baixo do corte — a
     frestinha que o dono fotografou em 22/08. Subpixel não se corrige no olho;
     corrige-se tirando o subpixel da conta. */
  --alt-chip: 17px;
  --gap-chip: 3px;
  display: flex; flex-wrap: wrap;
  align-content: flex-start;
  gap: var(--gap-chip);
  min-width: 0; min-height: 0;
  /* N fileiras = N alturas + (N-1) respiros. O respiro do FIM não entra: é ele
     que daria à fileira seguinte um vão para aparecer dentro. */
  max-height: calc(2 * var(--alt-chip) + 1 * var(--gap-chip));
  overflow: hidden;
}

/* Quantas FILEIRAS cabem depende da altura da janela, porque é ela que decide
   a altura da célula. Os cortes saíram da conta, não do olho:
   célula = (altura útil - 153) / 6, e cada fileira pede 20px depois de
   descontar os 30px de cabeçalho e folga da célula.

     até 700px  -> 1 fileira  (célula ~64px)
     até 800px  -> 2 fileiras (célula ~78px)
     acima      -> 3 fileiras (célula ~90px ou mais)

   O teto é sempre múltiplo de uma fileira: é isso que garante que nenhuma
   etiqueta apareça pela metade. */
@media (max-height: 700px) {
  .ag-chips { max-height: var(--alt-chip); }
}
@media (min-height: 801px) {
  .ag-chips { max-height: calc(3 * var(--alt-chip) + 2 * var(--gap-chip)); }
}

.ag-chip {
  flex: none;
  /* Altura cravada e caixa fechada: é o que faz a fileira medir exatamente o
     que o teto da prévia calcula. Ver a nota em `.ag-chips`. */
  height: var(--alt-chip, 17px);
  box-sizing: border-box;
  display: inline-flex; align-items: center;
  padding: 0 4px;
  border: 1px solid transparent;
  border-radius: 5px;
  font-size: 10.5px; font-weight: 700;
  line-height: 1;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.ag-chip.agendado  { background: var(--azul-fundo);     color: var(--azul);         border-color: var(--azul-borda); }
.ag-chip.andamento { background: var(--laranja-fundo);  color: var(--laranja-txt);  border-color: var(--laranja-borda); }
.ag-chip.concluido { background: var(--verde-fundo);    color: var(--verde-txt);    border-color: var(--verde-borda); }
.ag-chip.pendente  { background: var(--vermelho-fundo); color: var(--vermelho-txt); border-color: var(--vermelho-borda); }

/* Vistoria: mesma cor de situação, sem preenchimento. É o segundo eixo da
   leitura — "ir olhar" em vez de "ir fazer". */
.ag-chip.vistoria { background: transparent; border-style: dashed; }


/* ── A legenda ────────────────────────────────────────────────────────── */
.ag-legenda {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 14px;
  margin-top: 10px;
  padding-top: 9px;
  border-top: 1px solid var(--borda);
  font-size: 11.5px;
  color: var(--texto-fraco);
}
.ag-leg { display: inline-flex; align-items: center; gap: 5px; }
.ag-ponto {
  width: 9px; height: 9px;
  flex: none;
  border-radius: 50%;
  border: 1px solid transparent;
}
.ag-ponto.agendado  { background: var(--azul-fundo);     border-color: var(--azul-borda); }
.ag-ponto.andamento { background: var(--laranja-fundo);  border-color: var(--laranja-borda); }
.ag-ponto.concluido { background: var(--verde-fundo);    border-color: var(--verde-borda); }
.ag-ponto.pendente  { background: var(--vermelho-fundo); border-color: var(--vermelho-borda); }
.ag-ponto.vistoria  { background: transparent; border-style: dashed; }

/* ── A coluna da direita ──────────────────────────────────────────────── */
/* Ela GRUDA e rola POR DENTRO. Antes ela era só `sticky`, e isso não bastava:
   `sticky` não segura elemento mais alto que a janela — ele acompanha a
   rolagem até o pé dele aparecer. Um dia com 20 visitas dava 1.274px de coluna
   numa janela de 720px, e o efeito era a página inteira ficar comprida e o
   painel do dia "ir lá para baixo". Com teto de altura e rolagem própria, o
   dia fica sempre à vista e quem rola é só ele. */
.ag-lado {
  position: sticky;
  top: var(--ag-topo);
  min-width: 0;
  max-height: var(--ag-alto);
  overflow-y: auto;
  /* A barra de rolagem fica fina e discreta, mas VISÍVEL: aqui ela é
     informação ("tem mais coisa embaixo"), diferente do menu lateral, onde
     escondê-la foi pedido do dono. */
  scrollbar-width: thin;
  scrollbar-color: var(--borda-forte) transparent;
  /* Sem isto a sombra do cartão é cortada rente pela área de rolagem. */
  padding-right: 2px;
}
.ag-lado::-webkit-scrollbar { width: 8px; }
.ag-lado::-webkit-scrollbar-track { background: transparent; }
.ag-lado::-webkit-scrollbar-thumb {
  background: var(--borda-forte);
  border-radius: 999px;
  border: 2px solid transparent;
  background-clip: content-box;
}

.ag-dia-painel, .ag-ficha { padding: 14px 16px 16px; }

.ag-dia-topo {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 2px 8px;
  margin-bottom: 4px;
}
.ag-dia-nav { grid-column: 2; grid-row: 1 / span 2; display: flex; gap: 4px; }
.ag-dia-titulo {
  grid-column: 1; grid-row: 1;
  margin: 0;
  font-size: 16px; font-weight: 800; letter-spacing: -.02em;
}
.ag-dia-nota { grid-column: 1; grid-row: 2; margin: 0; font-size: 12.5px; color: var(--texto-fraco); }

.ag-hoje-marca {
  margin-left: 6px;
  padding: 1px 7px;
  border-radius: 999px;
  background: var(--ouro);
  color: var(--ouro-contra);
  font-size: 10.5px; font-weight: 700;
  letter-spacing: .04em;
  vertical-align: 2px;
}

.ag-dia-livre {
  margin: 16px 0 4px;
  padding: 18px 12px;
  border: 1px dashed var(--borda-forte);
  border-radius: var(--raio);
  font-size: 13px;
  color: var(--texto-fraco);
  text-align: center;
}

/* ── A rota do dia ────────────────────────────────────────────────────── */
.ag-rota { margin-top: 15px; }

.ag-rota-titulo {
  display: flex; align-items: baseline; justify-content: space-between; gap: 8px;
  margin: 0 0 5px;
  font-size: 11px; font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--ouro);
}
.ag-rota.sem-tecnico .ag-rota-titulo { color: var(--laranja-txt); }
.ag-rota-conta { font-size: 10.5px; font-weight: 600; letter-spacing: .04em; color: var(--texto-fraco); }
.ag-rota-aviso { margin: 0 0 6px; font-size: 12px; line-height: 1.45; color: var(--laranja-txt); }

.ag-paradas { margin: 0; padding: 0; list-style: none; }

.ag-parada-link {
  display: flex;
  gap: 9px;
  padding: 7px 8px;
  border: 1px solid transparent;
  border-radius: 9px;
  color: inherit;
  text-decoration: none;
  transition: background .15s ease, border-color .15s ease;
}
.ag-parada-link:hover { background: var(--fundo); border-color: var(--borda); }
.ag-parada-link:focus-visible { outline: 2px solid var(--azul); outline-offset: 1px; }
.ag-parada-link.atual { background: var(--azul-fundo); border-color: var(--azul-borda); }

/* A marca é uma BARRA vertical, e não um ponto: ela acompanha a altura da
   parada e faz a coluna de situações ser lida de cima a baixo de relance. */
.ag-parada-marca {
  flex: none;
  width: 4px;
  border-radius: 3px;
  border: 1px solid transparent;
  align-self: stretch;
}
.ag-parada-marca.agendado  { background: var(--azul);        border-color: var(--azul); }
.ag-parada-marca.andamento { background: var(--laranja);     border-color: var(--laranja); }
.ag-parada-marca.concluido { background: var(--verde);       border-color: var(--verde); }
.ag-parada-marca.pendente  { background: var(--vermelho);    border-color: var(--vermelho); }
.ag-parada-marca.cancelado { background: var(--borda-forte); border-color: var(--borda-forte); }
.ag-parada-marca.vistoria  { background: transparent; }

.ag-parada-corpo { min-width: 0; display: flex; flex-direction: column; }
.ag-parada-hora  { font-size: 11.5px; color: var(--texto-fraco); font-variant-numeric: tabular-nums; }
.ag-parada-quem  { font-size: 14px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ag-parada-onde  { font-size: 11.5px; color: var(--texto-fraco); line-height: 1.4; }

/* ── O trajeto entre duas paradas ─────────────────────────────────────────
   É o pedaço que transforma uma pilha de horários numa ROTA: sem ele, a lista
   diz o que vai acontecer; com ele, diz como o técnico atravessa o dia.

   O fio é um degradê repetido, e não uma borda tracejada, por um motivo
   prático: borda tracejada não se anima. Com o degradê, os traços DESCEM ao
   passar o mouse — o movimento mostra o sentido do percurso. */
.ag-trajeto {
  position: relative;
  display: flex; align-items: center; gap: 6px;
  margin: 0;
  padding: 5px 0 5px 30px;
  min-height: 26px;
  font-size: 11px;
  color: var(--texto-fraco);
}

.ag-trajeto-marca {
  position: absolute;
  left: 9px; top: 0; bottom: 0;
  width: 2px;
  border-radius: 2px;
  background: repeating-linear-gradient(
    to bottom,
    var(--borda-forte) 0 4px,
    transparent 4px 9px
  );
}

.ag-trajeto-tempo {
  padding: 1px 7px;
  border-radius: 999px;
  border: 1px solid var(--azul-borda);
  background: var(--azul-fundo);
  color: var(--azul);
  font-size: 11px; font-weight: 700;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.ag-trajeto-nota { font-size: 10.5px; }

/* Estimado pela linha reta, sem o Google. A pílula perde a cor: ela continua
   legível, mas deixa de ter o peso de um número medido. */
.ag-trajeto.estimado .ag-trajeto-tempo {
  border-color: var(--borda-forte);
  background: transparent;
  color: var(--texto-fraco);
}
.ag-trajeto.sem-mapa { opacity: .65; }
.ag-trajeto.sem-mapa .ag-trajeto-marca { opacity: .5; }

/* ── O movimento ──────────────────────────────────────────────────────────
   Ele acontece AO PASSAR O MOUSE na rota, e não sozinho. A regra da casa
   (escrita em 19/08, no bloco dos cartões) é que nada pisca sozinho num painel
   que fica aberto o dia inteiro: movimento perpétuo cansa e ensina a ignorar.
   Passando o mouse, o dono tem o efeito quando quer mostrá-lo — inclusive numa
   feira — e a tela parada continua parada.

   São duas coisas ao mesmo tempo: os traços do fio descem, e um ponto percorre
   o caminho de uma parada até a outra. */
@keyframes ag-fluir {
  to { background-position-y: 13px; }
}
@keyframes ag-percorrer {
  0%   { top: -3px;               opacity: 0; }
  12%  {                          opacity: 1; }
  88%  {                          opacity: 1; }
  100% { top: calc(100% - 3px);   opacity: 0; }
}

.ag-rota:hover .ag-trajeto:not(.sem-mapa) .ag-trajeto-marca {
  animation: ag-fluir 700ms linear infinite;
}
/* O ponto que anda. Nasce só no hover — um pseudo-elemento sem `content` não
   existe, então ele não pesa nada enquanto ninguém está olhando. */
.ag-rota:hover .ag-trajeto:not(.sem-mapa)::after {
  content: "";
  position: absolute;
  left: 6px;
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--azul);
  box-shadow: 0 0 0 3px var(--azul-fundo);
  animation: ag-percorrer 1.6s ease-in-out infinite;
}
/* Nos trechos estimados o ponto é cinza, como a pílula: o desenho inteiro
   conta a mesma história sobre a origem do número. */
.ag-rota:hover .ag-trajeto.estimado::after {
  background: var(--borda-forte);
  box-shadow: 0 0 0 3px var(--fundo);
}

/* ── A ficha da visita ────────────────────────────────────────────────── */
.ag-voltar {
  display: inline-block;
  margin-bottom: 9px;
  font-size: 12.5px; font-weight: 600;
  color: var(--azul);
  text-decoration: none;
}
.ag-voltar:hover { text-decoration: underline; }

.ag-ficha-topo { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.ag-ficha-nome {
  flex-basis: 100%;
  margin: 7px 0 1px;
  font-size: 19px; font-weight: 800; letter-spacing: -.025em;
  line-height: 1.2;
}
.ag-ficha-quando { flex-basis: 100%; margin: 0; font-size: 13px; color: var(--texto-fraco); }

.ag-situacao.agendado  { color: var(--azul);         border-color: var(--azul-borda);     background: var(--azul-fundo); }
.ag-situacao.andamento { color: var(--laranja-txt);  border-color: var(--laranja-borda);  background: var(--laranja-fundo); }
.ag-situacao.concluido { color: var(--verde-txt);    border-color: var(--verde-borda);    background: var(--verde-fundo); }
.ag-situacao.pendente  { color: var(--vermelho-txt); border-color: var(--vermelho-borda); background: var(--vermelho-fundo); }
.ag-situacao.cancelado { color: var(--texto-fraco); }
.ag-tipo { color: var(--texto-fraco); font-weight: 500; }

.ag-dados { margin: 14px 0 0; display: flex; flex-direction: column; gap: 9px; }
.ag-dados > div {
  display: grid;
  grid-template-columns: 78px minmax(0, 1fr);
  gap: 10px;
  align-items: baseline;
}
.ag-dados dt {
  font-size: 10.5px; font-weight: 700;
  text-transform: uppercase; letter-spacing: .07em;
  color: var(--texto-fraco);
}
.ag-dados dd { margin: 0; font-size: 13.5px; line-height: 1.5; min-width: 0; }
.ag-fraco { color: var(--texto-fraco); }

.ag-praga { display: inline-block; margin-right: 8px; }
.ag-praga i { font-style: normal; color: var(--texto-fraco); font-size: 12px; }
.ag-equipe { display: block; font-size: 12px; color: var(--texto-fraco); }
.ag-wpp { margin-left: 8px; font-size: 12.5px; color: var(--azul); text-decoration: none; }
.ag-wpp:hover { text-decoration: underline; }

.ag-carimbo {
  margin: 12px 0 0;
  padding: 8px 11px;
  border-radius: var(--raio);
  background: var(--fundo);
  font-size: 12px; line-height: 1.45;
  color: var(--texto-fraco);
}

.ag-encerrada {
  margin: 14px 0 0;
  padding: 10px 12px;
  border: 1px dashed var(--borda-forte);
  border-radius: var(--raio);
  font-size: 12.5px;
  color: var(--texto-fraco);
  text-align: center;
}

/* ── As três ações ────────────────────────────────────────────────────── */
.ag-acoes { margin-top: 15px; border-top: 1px solid var(--borda); }

.ag-acao { border-bottom: 1px solid var(--borda); }
.ag-acao summary {
  display: flex; align-items: center; justify-content: space-between;
  padding: 11px 2px;
  font-size: 13.5px; font-weight: 600;
  cursor: pointer;
  /* Some o triângulo padrão do navegador nos dois motores: sem as duas linhas,
     o Safari desenha o dele e o Chrome o meu, e a mesma tela fica diferente. */
  list-style: none;
}
.ag-acao summary::-webkit-details-marker { display: none; }
.ag-acao summary::after {
  content: "+";
  font-size: 17px; font-weight: 400;
  color: var(--texto-fraco);
  line-height: 1;
}
.ag-acao[open] summary::after { content: "\2212"; }   /* o sinal de menos */
.ag-acao summary:focus-visible { outline: 2px solid var(--azul); outline-offset: -2px; border-radius: 6px; }
.ag-acao.perigo summary { color: var(--vermelho-txt); }

.ag-form { display: flex; flex-direction: column; gap: 10px; padding: 2px 2px 14px; }
/* O `.btn` do flowpest nasce com 20px de folga em cima, pensado para o final
   de um formulário de página inteira. Dentro deste bloquinho, 20px separam
   demais. */
.ag-form .btn { margin-top: 2px; }
.ag-form .btn.perigo { border-color: var(--vermelho-borda); color: var(--vermelho-txt); }
.ag-form .btn.perigo:hover { background: var(--vermelho); color: #FFFFFF; border-color: var(--vermelho); }

.ag-caixa {
  display: flex; align-items: flex-start; gap: 8px;
  font-size: 12.5px; line-height: 1.45;
  color: var(--texto-fraco);
  cursor: pointer;
}
.ag-caixa input { margin: 2px 0 0; flex: none; width: 16px; height: 16px; accent-color: var(--azul); }

.ag-nota { margin: 0; font-size: 12px; line-height: 1.45; color: var(--texto-fraco); }

/* ── Visita não encontrada ────────────────────────────────────────────── */
.ag-vazio { padding: 22px 18px; text-align: center; }
.ag-vazio-titulo { margin: 0 0 4px; font-size: 15px; font-weight: 700; }
.ag-vazio-nota { margin: 0 0 12px; font-size: 12.5px; color: var(--texto-fraco); }

/* ── A lista de baixo ─────────────────────────────────────────────────── */
.ag-lista { margin-top: 14px; }
.ag-lista-topo { margin-bottom: 9px; }
.ag-lista-titulo { margin: 0; font-size: 15px; font-weight: 800; letter-spacing: -.02em; }
.ag-lista-nota { margin: 6px 0 0; font-size: 12px; color: var(--texto-fraco); }

/* ── O filtro da lista ────────────────────────────────────────────────────
   Ele fica ACIMA da lista e não numa gaveta: filtro escondido é filtro que
   ninguém usa, e "onde o Rafael esteve em março" é pergunta de todo dia.

   Campos nativos (`input[type=date]`, `select`), sem calendário próprio: o do
   sistema operacional já é conhecido, funciona pelo teclado e no celular abre
   a roda de data que a pessoa usa em todo aplicativo. */
.ag-filtro {
  display: flex; flex-wrap: wrap; align-items: flex-end; gap: 8px;
  margin-top: 9px;
}
.ag-filtro-campo { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.ag-filtro-campo > span {
  font-size: 10.5px; font-weight: 700;
  text-transform: uppercase; letter-spacing: .07em;
  color: var(--texto-fraco);
}
.ag-filtro-campo input, .ag-filtro-campo select {
  /* 38px e não os 46px do `.campo`: aqui são três controles lado a lado numa
     barra de apoio, não o formulário principal de uma tela. No celular a
     média query devolve a altura cheia. */
  min-height: 38px;
  max-width: 100%; min-width: 0;
  padding: 6px 10px;
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  background: var(--superficie);
  color: var(--texto);
  font: inherit; font-size: 13px;
}
.ag-filtro-campo input:focus, .ag-filtro-campo select:focus {
  outline: none; border-color: var(--azul);
}

.ag-filtro-btn {
  min-height: 38px;
  padding: 0 16px;
  border: 1px solid var(--azul-borda);
  border-radius: var(--raio);
  background: var(--azul-fundo);
  color: var(--azul);
  font: inherit; font-size: 13px; font-weight: 600;
  cursor: pointer;
}
.ag-filtro-btn:hover { border-color: var(--azul); }
.ag-filtro-limpar {
  align-self: center;
  padding: 0 4px;
  font-size: 12.5px; font-weight: 600;
  color: var(--texto-fraco);
  text-decoration: none;
}
.ag-filtro-limpar:hover { text-decoration: underline; }

.ag-linhas { margin: 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: 4px; }

.ag-linha {
  display: grid;
  grid-template-columns: 4px 104px minmax(0, 1fr) auto;
  gap: 12px;
  align-items: center;
  padding: 9px 13px;
  border: 1px solid var(--borda);
  border-radius: 10px;
  background: var(--superficie);
  color: inherit;
  text-decoration: none;
  transition: border-color .15s ease, background .15s ease;
}
.ag-linha:hover { border-color: var(--borda-forte); background: var(--fundo); }
.ag-linha:focus-visible { outline: 2px solid var(--azul); outline-offset: 1px; }

.ag-linha-marca { align-self: stretch; border-radius: 3px; border: 1px solid transparent; }
.ag-linha-marca.agendado  { background: var(--azul);     border-color: var(--azul); }
.ag-linha-marca.andamento { background: var(--laranja);  border-color: var(--laranja); }
.ag-linha-marca.concluido { background: var(--verde);    border-color: var(--verde); }
.ag-linha-marca.pendente  { background: var(--vermelho); border-color: var(--vermelho); }
.ag-linha-marca.vistoria  { background: transparent; }

.ag-linha-quando { display: flex; flex-direction: column; font-variant-numeric: tabular-nums; }
.ag-linha-quando b { font-size: 13px; font-weight: 700; }
.ag-linha-quando small { font-size: 11.5px; color: var(--texto-fraco); }

.ag-linha-quem { min-width: 0; display: flex; flex-direction: column; }
.ag-linha-quem strong { font-size: 14px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ag-linha-quem small  { font-size: 11.5px; color: var(--texto-fraco); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.ag-linha-fim { text-align: right; display: flex; flex-direction: column; }
.ag-linha-fim b { font-size: 13.5px; font-weight: 700; }
.ag-linha-fim small { font-size: 11px; color: var(--texto-fraco); }

.ag-paginas {
  display: flex; align-items: center; justify-content: center; gap: 14px;
  margin-top: 12px;
}
.ag-pagina {
  padding: 6px 14px;
  border: 1px solid var(--borda);
  border-radius: 999px;
  background: var(--superficie);
  color: var(--texto);
  font-size: 12.5px; font-weight: 600;
  text-decoration: none;
}
.ag-pagina:hover { border-color: var(--borda-forte); }
.ag-pagina.inerte { opacity: .38; }
.ag-pagina-conta { font-size: 12px; color: var(--texto-fraco); }

/* ── Telas médias: a coluna da direita desce ──────────────────────────── */
@media (max-width: 1180px) {
  .ag { grid-template-columns: 1fr; }
  /* Numa coluna só, nada gruda e nada tem teto de altura: a página rola
     inteira, e prender o painel do dia numa caixa de 600px criaria uma
     rolagem dentro de outra — o pior dos dois mundos. */
  .ag-lado { position: static; max-height: none; overflow: visible; }
  .ag-calendario { height: auto; }
  .ag-grade, .ag-semana { flex: none; }
  .ag-dia { min-height: 84px; }
}

/* ── Celular ──────────────────────────────────────────────────────────── */
@media (max-width: 700px) {
  .ag-calendario { padding: 11px 10px 10px; }
  .ag-mes { min-width: 0; font-size: 16px; }
  .ag-conta { flex-basis: 100%; margin-left: 0; }

  /* As setas de mês e de dia sobem para 44px. Elas são as teclas mais
     apertadas da tela — 26px de alvo com o polegar erra, e errar aqui troca o
     mês inteiro sem a pessoa perceber por quê. */
  .ag-seta, .ag-seta.pequena {
    width: 44px; height: 44px;
    font-size: 22px;
    border-radius: 12px;
  }
  .ag-hoje { min-height: 44px; display: inline-flex; align-items: center; }

  .ag-semana { gap: 3px; }
  /* No celular a grade volta a ter altura própria: a página rola de qualquer
     jeito (o painel do dia e a lista vêm embaixo), e amarrar a grade à altura
     da janela deixaria as células com 40px. */
  .ag-calendario { height: auto; }
  .ag-grade, .ag-semana { flex: none; }
  .ag-dia { min-height: 56px; padding: 4px 3px; gap: 4px; align-items: center; }
  /* A pílula de contagem some: a 48px de coluna ela e o número do dia disputam
     a mesma linha, e o que importa no telefone é onde há movimento — que os
     pontos coloridos já dizem. */
  .ag-dia-cabeca { justify-content: center; }
  .ag-conta-dia { display: none; }

  /* A etiqueta vira PONTO. A 375px de largura uma coluna tem ~48px, e nem o
     horário se lê ali — só suja. O texto continua no HTML (o leitor de tela e
     a dica ao tocar seguem completos), some apenas o desenho dele. Um dia com
     visita fica visivelmente diferente de um dia vazio, que é a única pergunta
     que a grade precisa responder num telefone. */
  .ag-chips {
    justify-content: center;
    gap: 3px;
    /* Sem teto em fileiras aqui: os pontos são pequenos e o `overflow` da
       célula já segura o excesso sem cortar nada pela metade. */
    max-height: none;
  }
  .ag-chip {
    width: 7px; height: 7px;
    padding: 0;
    border-radius: 50%;
    font-size: 0;
    line-height: 0;
  }
  /* No celular a altura cravada da etiqueta não vale — ela virou ponto. */
  .ag-chips { --alt-chip: 7px; }

  .ag-legenda { gap: 4px 10px; font-size: 11px; }

  .ag-dia-painel, .ag-ficha { padding: 13px 13px 15px; }
  .ag-dados > div { grid-template-columns: 70px minmax(0, 1fr); gap: 8px; }

  /* A linha da lista perde a coluna do valor: com 375px, quatro colunas
     espremem o nome do cliente até virar reticências. */
  .ag-linha { grid-template-columns: 4px 92px minmax(0, 1fr); gap: 10px; padding: 9px 10px; }
  .ag-linha-fim { display: none; }

  /* O filtro empilha, e os campos voltam ao alvo de toque cheio. As duas datas
     dividem a linha; o técnico e o botão ficam com a largura toda. */
  .ag-filtro { gap: 8px 6px; }
  .ag-filtro-campo { flex: 1 1 calc(50% - 3px); }
  .ag-filtro-campo:nth-of-type(3) { flex-basis: 100%; }
  .ag-filtro-campo input, .ag-filtro-campo select { min-height: 44px; font-size: 16px; }
  .ag-filtro-btn { flex: 1 1 100%; min-height: 44px; }
}

/* Quem pediu menos movimento no aparelho fica com a cor e a estrutura, e sem
   as transições — mesma regra do resto do painel. */
@media (prefers-reduced-motion: reduce) {
  .ag-dia, .ag-seta, .ag-parada-link, .ag-linha { transition: none; }
  /* Quem pediu menos movimento no aparelho fica com o CAMINHO desenhado e sem
     o percurso animado: o fio, a pílula do tempo e a cor continuam — eles são
     informação. Some só o que se mexe. */
  .ag-rota:hover .ag-trajeto .ag-trajeto-marca { animation: none; }
  .ag-rota:hover .ag-trajeto::after { content: none; }
}

/* ── Novo agendamento ─────────────────────────────────────────────────────
   Uma coluna só, e estreita. Formulário não é painel: linha de 1.400px obriga
   a varrer a tela com os olhos de uma ponta a outra para ler um rótulo e o seu
   campo. 780px é a largura em que o par rótulo/campo cabe num golpe de vista.

   Os campos são `.campo` e `.btn` do flowpest.css — as mesmas regras do portal
   e do app do técnico, com o alvo de toque de 46px e o `font-size: 16px` que
   impede o Safari do iPhone de dar zoom ao focar. */

.nv { max-width: 780px; }
.nv-caminho { margin: 0 0 10px; font-size: 12.5px; }
.nv-caminho a { color: var(--azul); text-decoration: none; font-weight: 600; }
.nv-caminho a:hover { text-decoration: underline; }

.nv-form { padding: 18px 20px 20px; display: flex; flex-direction: column; gap: 4px; }

/* `fieldset` de verdade, com `legend`: é o que agrupa os campos para quem usa
   leitor de tela. Ele vem com borda e recuo próprios do navegador, que são
   desfeitos aqui. */
.nv-bloco {
  border: 0; margin: 0; padding: 0 0 16px;
  display: flex; flex-direction: column; gap: 12px;
}
.nv-bloco + .nv-bloco { border-top: 1px solid var(--borda); padding-top: 16px; }

.nv-legenda {
  padding: 0;
  font-size: 11px; font-weight: 700;
  text-transform: uppercase; letter-spacing: .08em;
  color: var(--ouro);
}

.nv-rotulo { margin: 0; font-size: 13.5px; color: var(--texto-fraco); }
.nv-rotulo small { font-size: 11.5px; }

/* ── Escolhas em caixa (rádio e seleção) ──────────────────────────────────
   O controle nativo continua lá — só fica invisível. É ele que dá o
   comportamento de teclado, o agrupamento por `name` e o foco; a caixa em
   volta é só o desenho. */
.nv-opcoes { display: flex; flex-wrap: wrap; gap: 8px; }

.nv-opcao, .nv-praga, .nv-slot {
  /* `relative` SEGURA o controle escondido (o `absolute` logo abaixo) dentro
     da própria caixa. Sem isso ele se posicionava pela página: na grade de
     horários, que rola por dentro, os 420 rádios vazavam da caixa, a página
     ganhava 4.700px de altura, e tocar num horário mais para baixo fazia o
     navegador rolar a PÁGINA até o rádio, num vazio escuro longe do botão
     Confirmar. Era o "clique não funciona, fundo preto infinito" que a Couto
     relatou em 25/09. */
  position: relative;
  display: inline-flex; align-items: center; gap: 8px;
  padding: 9px 14px;
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  background: var(--superficie);
  font-size: 13.5px;
  cursor: pointer;
  transition: border-color .15s ease, background .15s ease;
}
.nv-opcao:hover, .nv-praga:hover, .nv-slot:hover { border-color: var(--borda-forte); }

/* A marca vem do ESTADO do controle (`:has(input:checked)`), e não só da
   classe que o servidor escreve. A classe só muda quando a página recarrega, e
   o passo 2 (os horários) e a Equipe não recarregam ao clicar: o horário
   escolhido ficava idêntico aos outros, e parecia que o clique não tinha
   pegado. A classe continua valendo para o primeiro desenho. */
.nv-opcao.marcada, .nv-praga.marcada, .nv-slot.marcada,
.nv-opcao:has(input:checked), .nv-praga:has(input:checked), .nv-slot:has(input:checked) {
  border-color: var(--azul);
  background: var(--azul-fundo);
  color: var(--azul);
  font-weight: 600;
}
/* E o contrário: a caixa que o servidor desenhou marcada perde a marca quando
   a pessoa escolhe outra (o horário antigo) ou desmarca (a Equipe). Sem isto,
   dois horários ficavam azuis ao mesmo tempo. */
.nv-opcao.marcada:has(input:not(:checked)),
.nv-praga.marcada:has(input:not(:checked)),
.nv-slot.marcada:has(input:not(:checked)) {
  border-color: var(--borda);
  background: var(--superficie);
  color: inherit;
  font-weight: inherit;
}
.nv-opcao small { display: block; font-size: 11.5px; font-weight: 400; color: var(--texto-fraco); }
.nv-opcao.marcada small, .nv-opcao:has(input:checked) small { color: var(--azul); opacity: .8; }
.nv-opcao.marcada:has(input:not(:checked)) small { color: var(--texto-fraco); opacity: 1; }

/* O controle fica com 1px e transparente, e não `display:none`: escondido de
   verdade ele sai da ordem de tabulação, e a escolha deixaria de ser
   alcançável pelo teclado. O `:focus-visible` do irmão devolve o anel de foco
   à caixa, que é o que a pessoa enxerga. */
.nv-opcao input, .nv-praga input, .nv-slot input {
  position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none;
}
.nv-opcao:has(input:focus-visible),
.nv-praga:has(input:focus-visible),
.nv-slot:has(input:focus-visible) { outline: 2px solid var(--azul); outline-offset: 2px; }

.nv-pragas { display: flex; flex-wrap: wrap; gap: 6px; }
.nv-praga { padding: 7px 12px; font-size: 13px; }

.nv-graus { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 10px; }
.nv-dupla { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 12px; }
.nv-meio  { max-width: 220px; }

.nv-imovel {
  margin: 0;
  padding: 9px 12px;
  border-radius: var(--raio);
  background: var(--fundo);
  font-size: 13px;
  color: var(--texto-fraco);
}
.nv-alerta { color: var(--laranja-txt); }

.nv-nota { margin: 0; font-size: 12.5px; line-height: 1.5; color: var(--texto-fraco); }
.nv-nota b { color: var(--texto); }
.nv-falta { text-align: center; padding: 10px 0 0; }

.nv-aviso {
  margin: 0;
  padding: 10px 13px;
  border: 1px solid var(--azul-borda);
  border-radius: var(--raio);
  background: var(--azul-fundo);
  color: var(--azul);
  font-size: 13px; line-height: 1.5;
}
.nv-aviso.perigo {
  border-color: var(--laranja-borda);
  background: var(--laranja-fundo);
  color: var(--laranja-txt);
}

.nv-bloqueio { padding: 20px 22px; }
.nv-bloqueio-titulo { margin: 0 0 5px; font-size: 15px; font-weight: 700; }
.nv-bloqueio-texto  { margin: 0 0 10px; font-size: 13.5px; line-height: 1.55; color: var(--texto-fraco); }

/* ── O resumo no passo 2 ──────────────────────────────────────────────── */
.nv-resumo {
  padding: 12px 14px;
  border-radius: var(--raio);
  background: var(--fundo);
  margin-bottom: 4px;
}
.nv-resumo-topo {
  display: flex; align-items: baseline; justify-content: space-between; gap: 10px;
  margin: 0 0 3px;
  font-size: 15px;
}
.nv-resumo-linha { margin: 1px 0 0; font-size: 12.5px; color: var(--texto-fraco); line-height: 1.5; }

/* ── A grade de horários ──────────────────────────────────────────────── */
.nv-grade {
  display: flex; flex-direction: column; gap: 10px;
  /* 60 dias de horários não cabem na tela, e empurrar o botão de confirmar
     para 4.000px abaixo esconderia a ação. A grade rola dentro da própria
     caixa e o botão fica sempre a um dedo de distância. */
  max-height: 340px;
  overflow-y: auto;
  padding: 10px 12px;
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  background: var(--fundo);
}
.nv-dia { display: flex; flex-direction: column; gap: 5px; }
.nv-dia-rotulo {
  margin: 0;
  font-size: 11.5px; font-weight: 700;
  letter-spacing: .04em;
  color: var(--texto-fraco);
}
.nv-slots { display: flex; flex-wrap: wrap; gap: 5px; }
.nv-slot { padding: 6px 11px; font-size: 12.5px; }

/* A estrada desde o serviço anterior do técnico (25/09), embaixo do horário.
   O horário que ele não alcança (só aparece com "considerar deslocamento:
   não") ganha borda tracejada laranja: dá para escolher, mas não passa por
   um horário comum. */
.nv-slot small { display: block; font-size: 10.5px; font-weight: 400; color: var(--texto-fraco); }
.nv-slot.apertado { border-style: dashed; border-color: var(--laranja-borda); }
.nv-slot.apertado small { color: var(--laranja-txt); }

/* "Outro horário" (28/09): o horário que o gestor digita, fora da grade e até
   fora da jornada. Uma caixa própria abaixo da grade, com os três campos lado
   a lado; no celular eles descem um embaixo do outro. */
.nv-livre {
  display: flex; flex-direction: column; gap: 10px;
  margin-top: 12px;
  padding: 12px;
  border: 1px dashed var(--borda-forte);
  border-radius: var(--raio);
}
.nv-livre > .nv-slot, .nv-livre > .nv-praga { align-self: flex-start; }
.nv-livre-campos {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: 10px;
}

/* A garantia é SUB-OPÇÃO da Execução: fica na largura do próprio texto,
   logo abaixo do par Execução/Visita, e não esticada como um campo. */
.nv-garantia { align-self: flex-start; }

/* A conta do sistema ao lado da duração digitada: referência, não campo. */
.nv-estimativa {
  margin: 0;
  align-self: end;
  padding: 10px 12px;
  border-radius: var(--raio);
  background: var(--fundo);
  font-size: 13px; line-height: 1.4;
  color: var(--texto-fraco);
}
.nv-estimativa b { color: var(--texto); }
.nv-estimativa small { display: block; font-size: 11.5px; }

/* O botão que leva ao assistente, na barra do calendário. */
.ag-novo {
  padding: 6px 14px;
  border-radius: 999px;
  border: 1px solid var(--ouro);
  background: transparent;
  color: var(--ouro);
  font-size: 12.5px; font-weight: 600;
  text-decoration: none;
  white-space: nowrap;
  transition: background .15s ease, color .15s ease;
}
.ag-novo:hover { background: var(--ouro); color: var(--ouro-contra); }

@media (max-width: 700px) {
  .nv-form { padding: 15px 14px 17px; }
  .nv-grade { max-height: 300px; }
  /* Na barra do calendário o botão desce para a linha de baixo, ocupando a
     largura toda: no celular ele é a ação mais provável da tela. E ganha os
     44px de alvo, como todo o resto que se toca aqui. */
  .ag-novo {
    flex-basis: 100%;
    display: flex; align-items: center; justify-content: center;
    min-height: 44px;
  }

  /* Alvo de toque de 44px, o mesmo mínimo que `.campo` respeita no resto do
     sistema. Medido em 20/08 num 375x812: as caixas de horário saíam com 34px,
     e 34px de alvo com o polegar erra a vizinha. */
  .nv-slot, .nv-praga, .nv-opcao {
    min-height: 44px;
    padding-top: 0; padding-bottom: 0;
    align-items: center;
  }
  .nv-slot { padding-left: 14px; padding-right: 14px; }
}

@media (prefers-reduced-motion: reduce) {
  .nv-opcao, .nv-praga, .nv-slot, .ag-novo { transition: none; }
}


/* ═══════════════════════════════════════════════════════════════════════
   CLIENTES (sessão 82)

   Duas telas na mesma rota: a LISTA (busca + linhas paginadas) e a FICHA (um
   cliente aberto, ocupando a largura toda). Nunca as duas juntas — a ficha tem
   imóveis, histórico e o comercial inteiro, e empilhada embaixo de vinte
   linhas de lista ela nasceria fora do campo de visão.

   Nenhum hex novo: as cores saem todas do flowpest.css, como no resto do
   painel. E nada se move sozinho — a regra de 19/08 vale aqui igual: num
   painel aberto o dia inteiro, movimento perpétuo cansa e ensina a ignorar.
   ═══════════════════════════════════════════════════════════════════════ */

/* ── A barra de busca ──────────────────────────────────────────────────── */
.cl-topo {
  display: flex; flex-wrap: wrap; align-items: center; gap: 10px;
  margin-bottom: 10px;
}
.cl-busca {
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px;
  flex: 1 1 420px; min-width: 0;
}
.cl-busca-campo { flex: 1 1 260px; min-width: 0; }
/* Rótulo que existe para o leitor de tela e não para o olho: o campo tem
   `placeholder`, mas `placeholder` não é rótulo — ele some ao digitar. */
.cl-oculto {
  position: absolute; width: 1px; height: 1px;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap;
}
.cl-busca-campo input {
  width: 100%; min-width: 0;
  min-height: 40px;
  padding: 7px 12px;
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  background: var(--superficie);
  color: var(--texto);
  font: inherit; font-size: 14px;
}
.cl-busca-campo input:focus { outline: none; border-color: var(--azul); }

.cl-caixa {
  display: inline-flex; align-items: center; gap: 7px;
  font-size: 13px; color: var(--texto-fraco);
  cursor: pointer;
}
.cl-caixa input { width: 16px; height: 16px; accent-color: var(--azul); }

.cl-btn-busca {
  min-height: 40px; padding: 0 18px;
  border: 1px solid var(--azul-borda);
  border-radius: var(--raio);
  background: var(--azul-fundo);
  color: var(--azul);
  font: inherit; font-size: 13.5px; font-weight: 600;
  cursor: pointer;
}
.cl-btn-busca:hover { border-color: var(--azul); }

.cl-limpar {
  padding: 0 4px;
  font-size: 12.5px; font-weight: 600;
  color: var(--texto-fraco); text-decoration: none;
}
.cl-limpar:hover { text-decoration: underline; }

/* A ação principal da tela, em ouro: é a única coisa aqui que CRIA algo. */
.cl-novo {
  min-height: 40px;
  display: inline-flex; align-items: center;
  padding: 0 18px;
  border-radius: var(--raio);
  background: var(--ouro);
  color: var(--ouro-contra);
  font-size: 13.5px; font-weight: 700;
  text-decoration: none;
  white-space: nowrap;
}
.cl-novo:hover { filter: brightness(1.06); }

.cl-conta { margin: 0 0 10px; font-size: 12.5px; color: var(--texto-fraco); }

/* ── As linhas da lista ────────────────────────────────────────────────── */
.cl-linhas { margin: 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: 5px; }

.cl-linha {
  display: grid;
  /* disco · quem · onde · quantas OS · quando. As três últimas têm largura
     fixa para os números ficarem alinhados de linha em linha — coluna que
     dança conforme o conteúdo obriga o olho a reprocurar a cada linha. */
  grid-template-columns: 38px minmax(0, 1fr) 132px 74px 116px;
  gap: 12px;
  align-items: center;
  padding: 10px 14px;
  border: 1px solid var(--borda);
  border-radius: 10px;
  background: var(--superficie);
  color: inherit;
  text-decoration: none;
  transition: border-color .15s ease, background .15s ease;
}
.cl-linha:hover { border-color: var(--borda-forte); background: var(--fundo); }
.cl-linha:focus-visible { outline: 2px solid var(--azul); outline-offset: 1px; }

/* O disco com a inicial. Mesmo tratamento do avatar da equipe (19/08): um
   degradê leve do ouro e um anel, para não parecer um selo chapado. */
.cl-avatar {
  width: 38px; height: 38px;
  display: grid; place-items: center;
  border-radius: 50%;
  border: 1px solid var(--borda);
  background: linear-gradient(160deg,
              color-mix(in srgb, var(--ouro) 22%, var(--superficie)),
              var(--superficie));
  color: var(--texto);
  font-size: 15px; font-weight: 800;
  flex: none;
}
.cl-avatar.grande { width: 54px; height: 54px; font-size: 21px; }

.cl-quem { min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.cl-quem strong { font-size: 14.5px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cl-quem small  { font-size: 11.5px; color: var(--texto-fraco); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* `contents`: o invólucro sai da conta da grade e os três blocos voltam a ser
   colunas de primeiro nível. Ele existe só para o celular ter o que agrupar. */
.cl-stats { display: contents; }
.cl-onde, .cl-numeros, .cl-quando { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.cl-onde b { font-size: 12.5px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cl-onde small, .cl-numeros small, .cl-quando small { font-size: 11px; color: var(--texto-fraco); }
.cl-numeros { text-align: right; }
.cl-numeros b { font-size: 16px; font-weight: 800; font-variant-numeric: tabular-nums; }
.cl-quando { text-align: right; }
.cl-quando b { font-size: 12.5px; font-weight: 700; font-variant-numeric: tabular-nums; }
/* Visita marcada é a informação mais acionável da linha — ela ganha a cor. */
.cl-quando b.cl-agendado { color: var(--azul); }
.cl-nunca { font-style: italic; }

/* ── Recados (o mesmo desenho da Agenda) ───────────────────────────────── */
.cl-vazio { text-align: center; padding: 26px 22px; }
.cl-vazio-titulo { margin: 0 0 4px; font-size: 15px; font-weight: 700; }
.cl-vazio-nota { margin: 0; font-size: 13px; line-height: 1.55; color: var(--texto-fraco); }
.cl-vazio .cl-voltar { display: inline-block; margin-top: 12px; }

.cl-voltar {
  font-size: 12.5px; font-weight: 600;
  color: var(--texto-fraco); text-decoration: none;
}
.cl-voltar:hover { color: var(--texto); text-decoration: underline; }

/* ── A ficha ───────────────────────────────────────────────────────────── */
.cl-ficha { display: flex; flex-direction: column; gap: 12px; }

.cl-cabecalho { display: flex; flex-direction: column; gap: 10px; }
.cl-identidade { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; }
.cl-nome-bloco { min-width: 0; flex: 1 1 240px; display: flex; flex-direction: column; gap: 3px; align-items: flex-start; }
.cl-nome { margin: 0; font-size: 21px; font-weight: 800; letter-spacing: -.02em; }
.cl-contato { margin: 0; font-size: 13px; color: var(--texto-fraco); }
.cl-desde { opacity: .85; }
.cl-razao { margin-top: 2px; }
.cl-acoes-topo { display: flex; gap: 8px; flex-wrap: wrap; margin-left: auto; align-self: center; }
/* `width` e `margin-top` NÃO são detalhe: o `.btn` do flowpest.css nasce
   `width: 100%; margin-top: 20px`, porque lá ele é o botão de um formulário de
   coluna única. Herdado aqui, cada ação virava uma faixa da largura do cartão e
   as quatro empilhavam 264px de altura — e a identidade, centralizada contra
   essa coluna, parecia solta no meio do cabeçalho. Medido em 1512px, em 26/08,
   depois de o dono apontar. Vale para esta tela E para a de Clientes, que tem
   o mesmo cabeçalho e já estava assim no ar. */
.cl-acoes-topo .btn {
  width: auto; flex: 0 0 auto; margin-top: 0;
  min-height: 40px; padding: 0 16px;
  display: inline-flex; align-items: center; font-size: 13.5px;
}

.cl-kpis { grid-template-columns: repeat(auto-fit, minmax(158px, 1fr)); }
.cl-kpis .adm-kpi-valor { font-size: 23px; }

/* Duas colunas: a larga com o que se OPERA (imóveis, visitas), a estreita com
   o que se CONSULTA (cotações, diagnósticos, follow-ups). A proporção 1.55/1
   é o que faz uma linha de histórico caber sem quebrar o nome do técnico. */
.cl-colunas {
  display: grid;
  grid-template-columns: minmax(0, 1.55fr) minmax(0, 1fr);
  gap: 12px;
  align-items: start;
}
.cl-coluna { display: flex; flex-direction: column; gap: 12px; min-width: 0; }

.cl-bloco { display: flex; flex-direction: column; gap: 10px; }
.cl-bloco-titulo {
  margin: 0;
  display: flex; align-items: center; gap: 8px;
  font-size: 14px; font-weight: 800; letter-spacing: -.01em;
}
.cl-conta-bloco {
  padding: 1px 8px;
  border-radius: 999px;
  background: var(--fundo);
  border: 1px solid var(--borda);
  font-size: 11.5px; font-weight: 700; color: var(--texto-fraco);
  font-variant-numeric: tabular-nums;
}

/* ── Cartão de imóvel ──────────────────────────────────────────────────── */
.cl-imovel {
  border: 1px solid var(--borda);
  border-radius: 10px;
  padding: 11px 13px;
  background: var(--superficie);
  display: flex; flex-direction: column; gap: 9px;
}
/* Imóvel arquivado continua visível (o histórico aponta para ele), mas recuado:
   ele não é escolha do dia a dia. */
.cl-imovel.arquivado { opacity: .72; border-style: dashed; }

.cl-imovel-topo { display: flex; gap: 12px; align-items: flex-start; }
.cl-fachada {
  width: 82px; height: 62px;
  object-fit: cover;
  border-radius: 8px;
  border: 1px solid var(--borda);
  flex: none;
  background: var(--fundo);
}
.cl-imovel-dados { min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.cl-imovel-nome {
  margin: 0;
  display: flex; align-items: center; gap: 7px; flex-wrap: wrap;
  font-size: 14px; font-weight: 700;
}
.cl-imovel-linha { margin: 0; font-size: 12.5px; line-height: 1.45; }
.cl-imovel-meta { margin: 0; font-size: 11.5px; color: var(--texto-fraco); line-height: 1.45; }

.cl-imovel-acoes { display: flex; flex-wrap: wrap; gap: 6px; }

/* ── As gavetas de ação (`<details>` nativo) ───────────────────────────── */
.cl-acao > summary {
  display: inline-flex; align-items: center;
  min-height: 32px; padding: 0 12px;
  border: 1px solid var(--borda);
  border-radius: 999px;
  background: var(--superficie);
  font-size: 12.5px; font-weight: 600;
  color: var(--texto-fraco);
  cursor: pointer;
  list-style: none;               /* tira o triângulo do Firefox */
  user-select: none;
}
.cl-acao > summary::-webkit-details-marker { display: none; }
.cl-acao > summary:hover { border-color: var(--borda-forte); color: var(--texto); }
.cl-acao[open] > summary { border-color: var(--azul-borda); background: var(--azul-fundo); color: var(--azul); }
.cl-acao.perigo[open] > summary { border-color: var(--vermelho-borda); background: var(--vermelho-fundo); color: var(--vermelho-txt); }
.cl-acao.destaque > summary { border-style: dashed; }
/* O botão que LEVA a outra página (os porta-iscas do imóvel), com a mesma
   cara das gavetas ao lado, para não parecer um link solto no cartão. */
.cl-acao-link {
  display: inline-flex; align-items: center;
  min-height: 32px; padding: 0 12px;
  border: 1px solid var(--borda); border-radius: 999px;
  background: var(--superficie);
  font-size: 12.5px; font-weight: 600;
  color: var(--texto-fraco); text-decoration: none;
}
.cl-acao-link:hover { border-color: var(--borda-forte); color: var(--texto); }

.cl-acao > form, .cl-acao > .cl-form-inline { margin-top: 10px; }
.cl-form { display: flex; flex-direction: column; gap: 10px; }
.cl-form-inline { margin-top: 6px; }
.cl-form-grade {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
  gap: 10px;
}
.cl-nota { margin: 0; font-size: 12px; line-height: 1.5; color: var(--texto-fraco); }
.cl-nota b { color: var(--texto); }

.cl-link-perigo {
  padding: 0; border: 0; background: none;
  color: var(--vermelho-txt);
  font: inherit; font-size: 12.5px; font-weight: 600;
  text-decoration: underline;
  cursor: pointer;
}

/* ── O histórico de visitas ────────────────────────────────────────────── */
.cl-visitas { margin: 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: 5px; }

.cl-visita-link {
  display: grid;
  grid-template-columns: 86px minmax(0, 1fr);
  gap: 11px;
  padding: 9px 12px;
  border: 1px solid var(--borda);
  border-left-width: 3px;
  border-radius: 9px;
  background: var(--superficie);
  color: inherit; text-decoration: none;
  transition: border-color .15s ease, background .15s ease;
}
.cl-visita-link:hover { border-color: var(--borda-forte); background: var(--fundo); }
.cl-visita-link:focus-visible { outline: 2px solid var(--azul); outline-offset: 1px; }

/* A cor é a SITUAÇÃO, e mora na borda da esquerda — a mesma linguagem da
   Agenda, onde cor significa situação e nada mais. */
.cl-visita.agendado  .cl-visita-link { border-left-color: var(--azul); }
.cl-visita.andamento .cl-visita-link { border-left-color: var(--laranja); }
.cl-visita.concluido .cl-visita-link { border-left-color: var(--verde); }
.cl-visita.pendente  .cl-visita-link { border-left-color: var(--vermelho); }
.cl-visita.cancelado .cl-visita-link { border-left-color: var(--borda-forte); }
.cl-visita.cancelado { opacity: .72; }

.cl-visita-quando { display: flex; flex-direction: column; font-variant-numeric: tabular-nums; }
.cl-visita-quando b { font-size: 13px; font-weight: 700; }
.cl-visita-quando small { font-size: 11px; color: var(--texto-fraco); }

.cl-visita-corpo { min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.cl-visita-linha1 { display: flex; align-items: center; gap: 7px; flex-wrap: wrap; }
.cl-visita-tec { font-size: 12.5px; font-weight: 600; }
.cl-visita-preco { margin-left: auto; font-size: 13px; font-weight: 700; font-variant-numeric: tabular-nums; }
.cl-visita-nota { display: flex; align-items: baseline; gap: 7px; flex-wrap: wrap; font-size: 12px; }
.cl-estrelas { color: var(--ouro); letter-spacing: 1px; }
.cl-visita-det { font-size: 11.5px; color: var(--texto-fraco); line-height: 1.45; }
.cl-visita-det.aviso { color: var(--laranja-txt); }

.cl-sit.agendado  { color: var(--azul);         border-color: var(--azul-borda);     background: var(--azul-fundo); }
.cl-sit.andamento { color: var(--laranja-txt);  border-color: var(--laranja-borda);  background: var(--laranja-fundo); }
.cl-sit.concluido { color: var(--verde-txt);    border-color: var(--verde-borda);    background: var(--verde-fundo); }
.cl-sit.pendente  { color: var(--vermelho-txt); border-color: var(--vermelho-borda); background: var(--vermelho-fundo); }
.cl-sit.cancelado { color: var(--texto-fraco); }

/* ── As listas da coluna estreita ──────────────────────────────────────── */
.cl-itens { margin: 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: 6px; }
.cl-item {
  padding: 9px 11px;
  border: 1px solid var(--borda);
  border-radius: 9px;
  background: var(--superficie);
  display: flex; flex-direction: column; gap: 3px;
}
.cl-item-topo { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; font-size: 13px; }
.cl-item-valor { margin-left: auto; font-variant-numeric: tabular-nums; }
.cl-item-meta {
  margin: 0;
  display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
  font-size: 11.5px; color: var(--texto-fraco);
}
.cl-item-nota { margin: 0; font-size: 11.5px; line-height: 1.45; color: var(--texto-fraco); }
.cl-item-acao {
  align-self: flex-start;
  margin-top: 3px;
  font-size: 12px; font-weight: 600;
  color: var(--azul); text-decoration: none;
}
.cl-item-acao:hover { text-decoration: underline; }

.cl-tom-ok    { color: var(--verde-txt);    border-color: var(--verde-borda);    background: var(--verde-fundo); }
.cl-tom-aviso { color: var(--laranja-txt);  border-color: var(--laranja-borda);  background: var(--laranja-fundo); }
.cl-tom-erro  { color: var(--vermelho-txt); border-color: var(--vermelho-borda); background: var(--vermelho-fundo); }
.cl-tom-info  { color: var(--azul);         border-color: var(--azul-borda);     background: var(--azul-fundo); }

/* ── Cadastro de cliente novo ──────────────────────────────────────────── */
.cl-novo-form { display: flex; flex-direction: column; gap: 12px; max-width: 980px; }
.cl-escolhas { display: flex; flex-wrap: wrap; gap: 10px; }
/* O rádio fica VISÍVEL aqui, ao contrário das caixas do assistente da Agenda:
   lá o servidor redesenha a cada escolha e marca a caixa escolhida; aqui nada
   recarrega, então esconder o controle deixaria a escolha sem sinal nenhum em
   navegador sem `:has`. */
.cl-escolha {
  display: flex; align-items: flex-start; gap: 9px;
  flex: 1 1 260px;
  padding: 11px 13px;
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  background: var(--superficie);
  cursor: pointer;
}
.cl-escolha:hover { border-color: var(--borda-forte); }
.cl-escolha input { margin-top: 2px; width: 17px; height: 17px; accent-color: var(--azul); flex: none; }
.cl-escolha b { display: block; font-size: 13.5px; }
.cl-escolha small { display: block; margin-top: 2px; font-size: 11.5px; color: var(--texto-fraco); line-height: 1.45; }
.cl-escolha:has(input:checked) { border-color: var(--azul); background: var(--azul-fundo); }

.cl-novo-acoes { display: flex; align-items: center; justify-content: flex-end; gap: 14px; }
.cl-novo-acoes .btn { min-height: 44px; padding: 0 22px; display: inline-flex; align-items: center; }

/* ── Telas médias: a coluna estreita desce ─────────────────────────────── */
@media (max-width: 1180px) {
  .cl-colunas { grid-template-columns: minmax(0, 1fr); }
}

/* ── Celular ───────────────────────────────────────────────────────────── */
@media (max-width: 720px) {
  /* A linha vira duas fileiras: quem, e os números embaixo. Cinco colunas em
     375px dariam 40px cada uma — nome cortado no terceiro caractere. */
  .cl-linha {
    grid-template-columns: 38px minmax(0, 1fr);
    row-gap: 6px;
  }
  /* Cidade, OS e data numa linha só. Medido em 22/08: empilhados davam 143px
     de altura por cliente (cinco por tela num aparelho de 812px). */
  .cl-stats {
    display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 14px;
    grid-column: 2;
  }
  .cl-onde, .cl-numeros, .cl-quando {
    flex-direction: row; align-items: baseline; gap: 5px;
    text-align: left;
  }
  .cl-numeros b, .cl-quando b { font-size: 13px; }

  /* Alvo de toque de 44px em tudo que se clica (a regra que a sessão 81 mediu
     na Agenda). Campo com 16px de fonte também impede o Safari do iPhone de
     dar zoom ao focar. */
  .cl-busca-campo input, .cl-btn-busca, .cl-novo { min-height: 44px; font-size: 16px; }
  .cl-btn-busca, .cl-novo { font-size: 14px; }
  .cl-acao > summary { min-height: 44px; padding: 0 16px; }
  .cl-form-grade { grid-template-columns: minmax(0, 1fr); }
  .cl-acoes-topo { margin-left: 0; width: 100%; }
  .cl-acoes-topo .btn { flex: 1 1 auto; justify-content: center; min-height: 44px; }
  /* Os links de texto viram alvo de 44px. Medido em 22/08 no aparelho de
     375px: "Voltar aos clientes" tinha 20px de altura e "Baixar proposta",
     19px — dedo não acerta, e a pessoa toca no cartão inteiro sem querer. */
  .cl-voltar, .cl-item-acao, .cl-limpar, .cl-link-perigo,
  .cl-convite-conta a {
    display: inline-flex; align-items: center; min-height: 44px;
  }
  /* A caixa de "só quem já teve serviço": o alvo é o RÓTULO inteiro, não o
     quadradinho de 16px que o sistema desenha. */
  .cl-caixa { min-height: 44px; }
  /* Anterior/Próxima da paginação. Elas nasceram na Agenda com 34px e a
     varredura da sessão 81 não as pegou — a lista de lá tem a mesma classe, e
     esta linha conserta as duas telas. */
  .ag-pagina { min-height: 44px; display: inline-flex; align-items: center; }
  .cl-visita-link { grid-template-columns: minmax(0, 1fr); }
  .cl-visita-preco { margin-left: 0; }
  .cl-fachada { width: 64px; height: 50px; }
  .cl-novo-acoes { justify-content: space-between; }
}

/* ── O convite a buscar ────────────────────────────────────────────────────
   A tela não abre listando todo mundo (dono, 22/08). O que ocupa o lugar da
   lista é este cartão: diz o que fazer, diz o tamanho da carteira e oferece o
   caminho de folhear para quem quiser. */
.cl-convite { text-align: center; padding: 30px 24px; }
.cl-convite-titulo { margin: 0 0 6px; font-size: 16px; font-weight: 800; letter-spacing: -.02em; }
.cl-convite-conta { margin: 12px 0 0; font-size: 12.5px; color: var(--texto-fraco); }
.cl-convite-conta a { color: var(--azul); font-weight: 600; text-decoration: none; }
.cl-convite-conta a:hover { text-decoration: underline; }
.cl-sem-achado { padding: 4px 2px 0; }

/* Enquanto a busca ao vivo vai e volta, a lista inteira esmaece — não some.
   Sumir daria um salto na página a cada tecla; esmaecer diz "isto ainda é o
   resultado anterior" sem mover nada de lugar. */
#cl-resultado[aria-busy="true"] { opacity: .55; transition: opacity .12s ease; }

/* ═══════════════════════════════════════════════════════════════════════
   HISTÓRICO (sessão 85)

   Três telas na mesma rota: a LISTA (duas abas, busca, período), a FICHA DA
   OS e a FICHA DO DIAGNÓSTICO. Nunca duas juntas — a ficha de uma OS tem
   execução, produtos, fotos, assinatura e avaliação, e empilhada embaixo de
   vinte linhas ela nasceria fora do campo de visão.

   Ela REUSA quase tudo de Clientes (`.cl-ficha`, `.cl-cabecalho`,
   `.cl-colunas`, `.cl-bloco`, `.cl-item*`, `.cl-form-grade`) de propósito: são
   as mesmas peças fazendo o mesmo papel, e uma segunda folha de estilo para
   "cartão com título e lista" seria a segunda a manter em dia. O que nasce
   aqui é só o que não existia — as abas, a linha da lista (que tem outras
   colunas), as galerias de foto e a caixa da proposta.

   Nenhum hex novo: as cores saem todas do flowpest.css. E nada se move
   sozinho — num painel aberto o dia inteiro, movimento perpétuo cansa.
   ═══════════════════════════════════════════════════════════════════════ */

/* ── As abas ───────────────────────────────────────────────────────────────
   São links, e não botões: trocar de aba é trocar de lugar, e o endereço tem
   de poder ser copiado. A aba ativa ganha uma régua embaixo em vez de fundo
   cheio — fundo cheio disputaria atenção com a ação em ouro à direita. */
.hi-abas {
  display: flex; gap: 4px;
  margin-bottom: 12px;
  border-bottom: 1px solid var(--borda);
  /* ROLA quando não cabe, em vez de cortar. Medido em 11/09, no celular de
     375px com as CINCO abas de Campanhas: o contêiner tinha 330px para 535px
     de abas, e "Sazonalidade" e "Histórico" ficavam inalcançáveis. O
     componente nasceu com duas abas e ninguém tinha esbarrado no limite.

     `overflow-x: auto` só cria barra quando falta espaço, então nenhuma tela
     de duas ou três abas muda. E `overflow-y: hidden` é preciso junto: sem
     ele o navegador liga a rolagem vertical também e corta o -1px com que a
     aba ativa cobre a linha de baixo. */
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: thin;
}
/* Aba não encolhe para caber: ou cabe, ou rola. Comprimida, ela vira duas
   linhas de texto dentro de um alvo de toque de 14px. */
.hi-abas .hi-aba { flex: 0 0 auto; white-space: nowrap; }
.hi-aba {
  padding: 9px 14px 10px;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  color: var(--texto-fraco);
  font-size: 13.5px; font-weight: 600;
  text-decoration: none;
  white-space: nowrap;
  transition: color .15s ease, border-color .15s ease;
}
.hi-aba:hover { color: var(--texto); }
.hi-aba.ativa { color: var(--texto); border-bottom-color: var(--ouro); }
.hi-aba:focus-visible { outline: 2px solid var(--azul); outline-offset: -2px; border-radius: 4px 4px 0 0; }

/* ── A barra de filtro ─────────────────────────────────────────────────── */
.hi-topo {
  display: flex; flex-wrap: wrap; align-items: center; gap: 10px;
  margin-bottom: 10px;
}
.hi-busca {
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px;
  flex: 1 1 460px; min-width: 0;
}
.hi-periodo select {
  min-height: 40px;
  padding: 0 10px;
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  background: var(--superficie);
  color: var(--texto);
  font: inherit; font-size: 13.5px;
}
.hi-periodo select:focus { outline: none; border-color: var(--azul); }

/* Com busca, a janela de tempo não vale. Sem esta frase o gestor lê "Últimos
   90 dias" no seletor ao lado e acredita. */
.hi-nota-periodo { color: var(--azul); }

/* ── As linhas da lista ────────────────────────────────────────────────────
   Seis colunas: disco · quem · o quê · quem fez (ou a situação) · quando ·
   quanto. As quatro últimas têm largura fixa para os valores ficarem alinhados
   de linha em linha — coluna que dança conforme o conteúdo obriga o olho a
   reprocurar a cada linha. */
.hi-linhas { margin: 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: 5px; }

.hi-linha {
  display: grid;
  grid-template-columns: 38px minmax(0, 1fr) 150px 130px 96px 110px;
  gap: 12px;
  align-items: center;
  padding: 10px 14px;
  border: 1px solid var(--borda);
  border-radius: 10px;
  background: var(--superficie);
  color: inherit;
  text-decoration: none;
  transition: border-color .15s ease, background .15s ease;
}
.hi-linha:hover { border-color: var(--borda-forte); background: var(--fundo); }
.hi-linha:focus-visible { outline: 2px solid var(--azul); outline-offset: 1px; }

.hi-quem { min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.hi-quem strong { font-size: 14.5px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.hi-quem small  { font-size: 11.5px; color: var(--texto-fraco); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* `contents`: o invólucro sai da conta da grade e os quatro blocos voltam a ser
   colunas de primeiro nível. Ele existe só para o celular ter o que agrupar. */
.hi-stats { display: contents; }
.hi-oque, .hi-quem-foi, .hi-quando, .hi-quanto {
  display: flex; flex-direction: column; gap: 1px; min-width: 0;
}
.hi-oque b, .hi-quem-foi b {
  font-size: 12.5px; font-weight: 600;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.hi-oque small, .hi-quem-foi small, .hi-quando small, .hi-quanto small {
  font-size: 11px; color: var(--texto-fraco);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.hi-quando, .hi-quanto { text-align: right; }
.hi-quando b { font-size: 12.5px; font-weight: 700; font-variant-numeric: tabular-nums; }
.hi-quanto b { font-size: 14px; font-weight: 800; font-variant-numeric: tabular-nums; }
.hi-quanto b.hi-sem-valor { color: var(--texto-fraco); font-weight: 600; }

/* As estrelas são caracteres tipográficos, não emoji: o painel não usa emoji
   (premissa do dono), e estes dois existem em qualquer fonte. */
.hi-estrelas { color: var(--ouro); letter-spacing: .5px; }
/* Na linha da lista ela ocupa o lugar da legenda, então tem o tamanho dela. */
.hi-quanto .hi-estrelas { font-size: 11px; }

/* Os mesmos quatro tons de `.cl-tom-*`, mas para TEXTO (a situação da cotação
   na linha da lista, o verbo do evento na linha do tempo). Sem fundo nem
   borda: numa lista de vinte linhas, vinte pastilhas coloridas viram um
   mosaico e nenhuma delas chama atenção. */
.hi-tom-ok    { color: var(--verde-txt); }
.hi-tom-aviso { color: var(--laranja-txt); }
.hi-tom-erro  { color: var(--vermelho-txt); }
.hi-tom-info  { color: var(--azul); }
.hi-fraco     { color: var(--texto-fraco); font-weight: 400; }

/* Enquanto a busca ao vivo vai e volta, a lista inteira esmaece — não some.
   Sumir daria um salto na página a cada tecla. Mesma regra de Clientes. */
#hi-resultado[aria-busy="true"] { opacity: .55; transition: opacity .12s ease; }

/* ── Os dados de uma ficha ─────────────────────────────────────────────────
   Uma `<dl>` de verdade (termo e definição), e não `<p>` com negrito: o leitor
   de tela anuncia "Técnico, Zé da Silva" em vez de ler duas frases soltas. */
.hi-dados {
  margin: 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 10px 18px;
}
.hi-dados > div { min-width: 0; }
.hi-dados dt {
  font-size: 11px; font-weight: 700; text-transform: uppercase;
  letter-spacing: .06em; color: var(--texto-fraco);
}
.hi-dados dd { margin: 2px 0 0; font-size: 13.5px; line-height: 1.45; overflow-wrap: anywhere; }
/* A pastilha do apelido do imóvel dentro de um `dd`. `inline-block` porque
   `.vg-pill` nasce `inline`, e inline com padding não faz a linha crescer: ela
   sobrava 1px em cima e 2px embaixo do bloco (medido em 26/08), comendo o vão
   da grade. */
.hi-dados dd .vg-pill { display: inline-block; vertical-align: middle; }
/* Endereço, áreas tratadas e método são frases, não rótulos: elas tomam a
   largura inteira em vez de caber num terço e quebrar em quatro linhas. */
.hi-dados .hi-largo { grid-column: 1 / -1; }

.hi-texto-livre {
  margin: 10px 0 0;
  font-size: 13px; line-height: 1.6;
  /* Texto escrito por pessoa (ou pela IA) pode vir com uma palavra de 80
     caracteres, e sem isto ela empurra o cartão para fora da tela. */
  overflow-wrap: anywhere;
}

/* O botão do certificado de execução, no fim do bloco de Execução.

   `.btn` do flowpest.css nasce com `margin-top: 20px` e `width: 100%` para
   ser o FIM de um formulário empilhado. Aqui ele é um link dentro de um
   parágrafo, e sem zerar os dois vira uma faixa atravessando o cartão. É a
   armadilha que já pegou cinco vezes (s85, s86, s90, s95, s97). */
.hi-certificado {
  display: flex; flex-direction: column; align-items: flex-start; gap: 6px;
  margin-top: 14px;
}
.hi-certificado .btn {
  margin-top: 0;
  width: auto;
  min-height: 38px;
  padding: 0 16px;
  text-decoration: none;
}
/* PDF e Word lado a lado (25/09), e o aviso do Word logo embaixo, em tom de
   atenção: o que se muda no Word não volta para o sistema. */
.hi-certificado-botoes { display: flex; flex-wrap: wrap; gap: 8px; }
.hi-aviso-word { color: var(--laranja-txt); }

/* O orçamento em aberto (29/09): "Agendar este orçamento" e, ao lado, o
   "Cliente recusou" numa gaveta (é o caminho raro, e pede motivo). Os `.btn`
   daqui zeram margem e largura pelo mesmo motivo do certificado acima. */
.hi-orcamento-acoes {
  display: flex; flex-wrap: wrap; align-items: flex-start; gap: 10px;
  margin-top: 14px;
}
.hi-orcamento-acoes .btn {
  margin-top: 0; width: auto; min-height: 38px; padding: 0 16px;
  text-decoration: none;
}
/* "Orçamento declinado" (dono, 29/09): caixa vermelha do MESMO tamanho e
   formato do "Agendar este orçamento" ao lado, porque é a outra saída do
   orçamento, e não um detalhe. A borda é o vermelho CHEIO, como a do botão
   dourado é o ouro cheio: o `--vermelho-borda` do tema escuro (#5C2020)
   quase some no cartão. Cheia ao passar o mouse, como o `.btn`. */
.hi-declinado > summary {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 38px; padding: 0 16px;
  border: 1.5px solid var(--vermelho); border-radius: var(--raio);
  background: var(--vermelho-fundo); color: var(--vermelho-txt);
  font-size: 15px; font-weight: 500;
  cursor: pointer; list-style: none; user-select: none;
  transition: background var(--transicao), color var(--transicao), border-color var(--transicao);
}
.hi-declinado > summary::-webkit-details-marker { display: none; }
.hi-declinado > summary:hover { background: var(--vermelho); border-color: var(--vermelho); color: #FFFFFF; }
.hi-declinado > summary:focus-visible { outline: 2px solid var(--azul); outline-offset: 2px; }
.hi-declinado[open] { flex-basis: 100%; }
.hi-declinado .cl-form { display: flex; flex-direction: column; gap: 8px; margin-top: 10px; }
/* O confirmar herda `.hi-orcamento-acoes .btn` (sem a margem e sem a largura
   cheia do `.btn`); aqui só a cor. */
.hi-declinado .btn.perigo { align-self: flex-start; border-color: var(--vermelho); color: var(--vermelho-txt); }
.hi-declinado .btn.perigo:hover { background: var(--vermelho); border-color: var(--vermelho); color: #FFFFFF; }

/* ── Alterar uma OS fechada (25/09) ─────────────────────────────────────── */
.hi-alteracoes { margin: 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: 8px; }
.hi-alteracoes li {
  display: flex; flex-direction: column; gap: 2px;
  padding-bottom: 8px;
  border-bottom: 1px solid var(--borda);
  font-size: 13px;
}
.hi-alteracoes li:last-child { border-bottom: none; padding-bottom: 0; }
.hi-alteracoes small { font-size: 11.5px; }

.hi-alterar-intro { margin: 10px 0 14px; }
.hi-alterar-lista { margin: 0 0 10px; padding: 0; list-style: none; display: flex; flex-direction: column; gap: 4px; }
.hi-alterar-lista li {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  padding: 6px 0;
  border-bottom: 1px solid var(--borda);
}
.hi-alterar-lista li:last-child { border-bottom: none; }
.hi-alterar-nome { flex: 1 1 200px; min-width: 0; font-size: 13.5px; }
.hi-alterar-grau select {
  min-height: 40px; padding: 6px 10px;
  border: 1px solid var(--borda); border-radius: var(--raio);
  background: var(--fundo); color: var(--texto); font: inherit; font-size: 13.5px;
}
/* "Remover" (dono, 29/09), no lugar da caixinha "Tirar". Por baixo continua
   uma caixa de marcar (é ela que o servidor lê, e funciona sem JavaScript),
   escondida dentro de um rótulo com cara de botão. Marcada, a linha fica
   riscada com "sai ao salvar" e o botão vira "Desfazer": nada some antes de
   salvar, e o clique errado se desfaz ali mesmo. Nos produtos o botão é de
   verdade e zera a quantidade (o zero é o que o servidor já entende como
   "tirar"); o estado dele é a classe `removido` na linha. */
.hi-remover {
  position: relative; flex: none;
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 34px; margin: 0; padding: 0 12px;
  border: 1px solid var(--vermelho); border-radius: var(--raio);
  background: transparent; color: var(--vermelho-txt);
  font: inherit; font-size: 12.5px; font-weight: 600;
  cursor: pointer; user-select: none;
}
.hi-remover:hover { background: var(--vermelho-fundo); }
.hi-remover:focus-visible,
.hi-remover:has(input:focus-visible) { outline: 2px solid var(--azul); outline-offset: 2px; }
.hi-remover input { position: absolute; width: 1px; height: 1px; margin: 0; opacity: 0; pointer-events: none; }
.hi-remover-nao { display: none; }
.hi-remover:has(input:checked), .removido .hi-remover { border-color: var(--borda); color: var(--texto-fraco); }
.hi-remover:has(input:checked) .hi-remover-sim, .removido .hi-remover-sim { display: none; }
.hi-remover:has(input:checked) .hi-remover-nao, .removido .hi-remover-nao { display: inline; }
.hi-sai { display: none; flex: none; font-size: 11.5px; font-weight: 600; color: var(--vermelho-txt); }
li:has(.hi-remover input:checked) .hi-sai, li.removido .hi-sai { display: inline; }
li:has(.hi-remover input:checked) .hi-alterar-nome,
li.removido .hi-produto-marca { text-decoration: line-through; color: var(--texto-fraco); }
li:has(.hi-remover input:checked) .hi-alterar-grau,
li.removido .hi-produto-qtd { opacity: .45; pointer-events: none; }
.hi-alterar-fotos li:has(.hi-remover input:checked) img { opacity: .35; }
.hi-alterar-fotos .hi-sai { text-align: center; }
.hi-alterar-novo { margin-top: 12px; }
/* "+ Acrescentar outra" (29/09): um botão de texto, discreto, logo abaixo da última linha. */
.hi-mais {
  margin-top: 8px; padding: 6px 0;
  border: 0; background: none; cursor: pointer;
  color: var(--azul); font: inherit; font-size: 13px; font-weight: 600;
}
.hi-mais:hover { text-decoration: underline; }

/* No celular, 44px em tudo que se toca (a regra da s81), para as peças de
   29 e 30/09. Medido em 30/09 a 375px: os botões do orçamento tinham 38, o
   "+ Acrescentar outra" 33, e os links de orçamento em aberto 17. */
@media (max-width: 720px) {
  .hi-orcamento-acoes .btn,
  .hi-declinado > summary { min-height: 44px; }
  .hi-mais { min-height: 44px; padding: 10px 0; }
  .nv-orcamentos a,
  .ag-para-agendar a { display: inline-flex; align-items: center; min-height: 44px; }
}
/* A lista de orçamentos em aberto no aviso do assistente da Agenda (29/09). */
.nv-orcamentos { margin: 6px 0 0; padding-left: 18px; }
.nv-orcamentos a { color: var(--azul); font-weight: 600; }
.hi-alterar-fotos { margin-bottom: 12px; }

/* ── As galerias ───────────────────────────────────────────────────────────
   Miniatura com `object-fit: cover`: foto de serviço vem em retrato e em
   paisagem no mesmo cartão, e sem o corte a fileira fica com alturas
   diferentes. A imagem cheia abre em aba nova — é a mesma rota. */
.hi-rotulo-galeria {
  margin: 12px 0 6px;
  font-size: 11px; font-weight: 700; text-transform: uppercase;
  letter-spacing: .06em; color: var(--texto-fraco);
}
.hi-rotulo-galeria:first-child { margin-top: 0; }

.hi-galeria {
  margin: 0; padding: 0; list-style: none;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(104px, 1fr));
  gap: 8px;
}
.hi-galeria li { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.hi-galeria a { display: block; border-radius: 8px; }
.hi-galeria a:focus-visible { outline: 2px solid var(--azul); outline-offset: 2px; }
.hi-galeria img {
  display: block; width: 100%; aspect-ratio: 4 / 3;
  object-fit: cover;
  border: 1px solid var(--borda); border-radius: 8px;
  background: var(--fundo);
}
.hi-legenda { font-size: 10.5px; color: var(--texto-fraco); }

/* A foto do diagnóstico é UMA, e é o assunto do cartão: ela ganha tamanho de
   verdade em vez de virar uma miniatura de 104px. O teto de altura existe para
   uma foto em retrato não empurrar o resto da ficha para fora da tela. */
.hi-foto-diag { display: block; max-width: 420px; border-radius: 10px; }
.hi-foto-diag img {
  display: block; width: 100%; max-height: 320px;
  object-fit: contain;
  border: 1px solid var(--borda); border-radius: 10px;
  background: var(--fundo);
}
.hi-foto-diag:focus-visible { outline: 2px solid var(--azul); outline-offset: 2px; }

/* ── A mensagem enviada ao cliente ─────────────────────────────────────────
   `<pre>` porque a mensagem TEM quebras de linha que importam (ela é montada
   pelo sistema com uma informação por linha). `white-space: pre-wrap` mantém
   as quebras e ainda deixa a linha longa dobrar em vez de rolar. */
.hi-mensagem {
  margin: 0;
  padding: 12px 14px;
  border: 1px solid var(--borda);
  border-left: 3px solid var(--verde-borda);
  border-radius: 8px;
  background: var(--fundo);
  font: inherit; font-size: 12.5px; line-height: 1.6;
  white-space: pre-wrap; overflow-wrap: anywhere;
}

/* ── Produtos usados ───────────────────────────────────────────────────── */
.hi-produtos { margin: 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: 6px; }
.hi-produtos li {
  display: flex; align-items: baseline; justify-content: space-between; gap: 10px;
  padding-bottom: 6px;
  border-bottom: 1px solid var(--borda);
  font-size: 13px;
}
.hi-produtos li:last-child { border-bottom: none; padding-bottom: 0; }
.hi-produtos b { font-variant-numeric: tabular-nums; white-space: nowrap; }

/* ── Avaliação e assinatura ────────────────────────────────────────────── */
.hi-nota-grande { margin: 0; display: flex; align-items: baseline; gap: 8px; font-size: 19px; }
.hi-nota-grande .hi-fraco { font-size: 12.5px; }

.hi-comentario {
  margin: 10px 0 0;
  padding: 8px 0 8px 12px;
  border-left: 3px solid var(--borda-forte);
  font-size: 13px; line-height: 1.6; font-style: italic;
  color: var(--texto);
  overflow-wrap: anywhere;
}

/* A assinatura é um traço escuro num PNG transparente: sem fundo claro ela
   some no tema escuro. Por isso o fundo é branco fixo, e não `var(--fundo)`. */
.hi-assinatura {
  display: block; width: 100%; max-width: 280px;
  border: 1px solid var(--borda); border-radius: 8px;
  background: #FFFFFF;
}

/* Quem recebeu o servico (sessao 96c). Fica LOGO ABAIXO do rabisco, porque
   e ele que da nome a assinatura. */
.hi-assinante {
  margin: 10px 0 0;
  font-size: 13px;
  color: var(--texto-fraco);
}
/* CPF que nao fecha nos digitos verificadores. Aparece de proposito: o gestor
   precisa ver o que foi digitado para corrigir com o cliente. Quem se cala e a
   mensagem do WhatsApp, que e o comprovante. */
.hi-marca-erro {
  display: inline-block;
  margin-left: 6px;
  padding: 1px 6px;
  border-radius: 999px;
  font-size: 11px;
  color: var(--vermelho-txt);
  border: 1px solid var(--vermelho-borda);
  background: var(--vermelho-fundo);
}

.hi-atalhos .cl-item { padding: 8px 10px; }

/* ── A caixa da proposta ───────────────────────────────────────────────────
   Os mesmos seis campos do painel antigo, no mesmo lugar: a equipe já lê esta
   caixa. O que muda é que ela não tem mais hex escrito à mão dentro do HTML. */
.hi-proposta {
  margin-top: 12px;
  padding: 12px 14px;
  border: 1px solid var(--azul-borda);
  border-radius: 10px;
  background: var(--azul-fundo);
}
.hi-proposta-topo {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 10px; flex-wrap: wrap;
  margin-bottom: 8px;
}
.hi-proposta-topo b { color: var(--azul); font-size: 13.5px; }
/* Dentro da caixa azul o rótulo também é azul, e não o cinza padrão: medido em
   26/08, `--texto-fraco` sobre `--azul-fundo` dá 4,13:1 no tema claro — abaixo
   dos 4,5:1 que texto normal precisa. Em azul são 5,39:1, e o rótulo continua
   se distinguindo do valor, que fica na cor cheia. */
.hi-proposta .hi-dados dt { color: var(--azul); }
.hi-proposta .cl-item-acao { margin-top: 10px; display: inline-block; }

/* ── Escolha de produtos na OS manual ─────────────────────────────────────
   Marcar e informar a quantidade na MESMA linha: em duas listas separadas (o
   que o painel antigo fazia) o gestor marca cinco produtos em cima e procura
   cinco campos embaixo. */
.hi-produtos-escolha { margin: 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: 4px; }
.hi-produtos-escolha li {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  padding: 6px 0;
  border-bottom: 1px solid var(--borda);
}
.hi-produtos-escolha li:last-child { border-bottom: none; }
.hi-produto-marca {
  display: flex; align-items: center; gap: 9px;
  flex: 1 1 220px; min-width: 0;
  font-size: 13.5px; cursor: pointer;
}
.hi-produto-marca input { width: 18px; height: 18px; accent-color: var(--azul); flex: none; }
.hi-produto-qtd { display: flex; align-items: center; gap: 6px; flex: none; }
.hi-produto-qtd input {
  width: 84px; min-height: 40px;
  padding: 6px 10px;
  border: 1px solid var(--borda); border-radius: var(--raio);
  background: var(--fundo); color: var(--texto);
  font: inherit; font-size: 14px; text-align: right;
}
.hi-produto-qtd input:focus { outline: none; border-color: var(--azul); }
.hi-produto-qtd small { font-size: 11.5px; color: var(--texto-fraco); }

/* O `textarea` de observações. `.campo` estiliza `input` e `select`, e um
   `textarea` sem regra herda a fonte do sistema — ele apareceria com outra
   letra no meio do formulário. */
.campo textarea {
  width: 100%; max-width: 100%; min-width: 0;
  background: var(--fundo); color: var(--texto);
  border: 1px solid var(--borda); border-radius: var(--raio);
  padding: 10px 12px; font: inherit; font-size: 16px;
  resize: vertical;
}
.campo textarea:focus { outline: none; border-color: var(--azul); }

/* ── Telas médias ─────────────────────────────────────────────────────────
   Seis colunas precisam de largura. Abaixo de 1100px caem para quatro: o que
   sai é "o quê" (a praga, que já está no título da ficha) e "quem fez". */
@media (max-width: 1100px) {
  .hi-linha { grid-template-columns: 38px minmax(0, 1fr) 130px 96px 110px; }
  .hi-quem-foi { display: none; }
}

/* ── Celular ───────────────────────────────────────────────────────────────
   Seis colunas em 375px dariam 40px cada uma. A linha vira duas fileiras:
   quem em cima, e os números embaixo numa linha que dobra. */
@media (max-width: 720px) {
  .hi-linha {
    grid-template-columns: 38px minmax(0, 1fr);
    row-gap: 6px;
  }
  .hi-quem-foi { display: flex; }
  .hi-stats {
    display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 14px;
    grid-column: 2;
  }
  .hi-oque, .hi-quem-foi, .hi-quando, .hi-quanto {
    flex-direction: row; align-items: baseline; gap: 5px;
    text-align: left;
  }
  .hi-quando b, .hi-quanto b { font-size: 13px; }
  /* As legendas que NÃO são dado somem: "técnico" embaixo do nome de uma
     pessoa e "sem avaliação" embaixo de um valor não dizem nada que a linha
     já não diga. Com elas os quatro blocos ficam largos demais para caber
     dois por fileira, e a linha vai de 117px para 165px — medido em 375px,
     em 26/08. As estrelas ficam, porque são o dado. */
  .hi-quem-foi small, .hi-quanto small { display: none; }

  /* Alvo de toque de 44px em tudo que se clica — a regra que a sessão 81
     mediu na Agenda e a 82 repetiu em Clientes. Campo com 16px de fonte também
     impede o Safari do iPhone de dar zoom ao focar. */
  .hi-periodo select { min-height: 44px; font-size: 16px; }
  .hi-aba { min-height: 44px; display: inline-flex; align-items: center; font-size: 14px; }
  .hi-produto-qtd input { min-height: 44px; font-size: 16px; }
  .hi-produto-marca { min-height: 44px; }
  .hi-remover { min-height: 44px; padding: 0 14px; }
  .hi-galeria { grid-template-columns: repeat(auto-fill, minmax(88px, 1fr)); }
  .hi-dados { grid-template-columns: minmax(0, 1fr); }
  .hi-foto-diag { max-width: 100%; }
}


/* ══════════════════════════════════════════════════════════════════════════
   ESTOQUE (sessão 86)
   ══════════════════════════════════════════════════════════════════════════

   Reusa quase tudo: `.adm-cartao` e `.adm-kpi-*` dos números, `.hi-abas` das
   abas, `.hi-topo`/`.hi-busca` da barra de filtro, `.cl-ficha`/`.cl-bloco`/
   `.cl-acao`/`.cl-form` da ficha, `.ag-paginas` da paginação. O que nasce aqui
   é só o que não existia: a linha de produto, a pastilha de situação, o
   extrato e os dois formulários de movimento.

   TUDO em token de cor. A tela antiga vive num Streamlit de tema ESCURO fixo
   (`base = "dark"` no config.toml) e por isso podia cravar `#E0E7FF` no HTML;
   aqui há dois temas, e cor cravada some num deles. */

/* ── O painel de alertas ──────────────────────────────────────────────── */

.es-painel { margin-bottom: 14px; }

.es-cartao {
  display: block;
  color: inherit;
  text-decoration: none;
  transition: border-color .15s ease, transform .15s ease;
}
/* Só o cartão que É link ganha reação ao passar o mouse: `.vazio` é um <div>,
   e prometer clique num número zero seria mentir com o cursor. */
a.es-cartao:hover { border-color: var(--borda-forte); transform: translateY(-1px); }
a.es-cartao:focus-visible { outline: 2px solid var(--azul); outline-offset: 1px; }

/* A cor entra pela BORDA e não pelo fundo: são cinco cartões lado a lado, e
   cinco fundos coloridos numa fileira viram um semáforo que não hierarquiza
   nada. A borda marca sem gritar. */
.es-cartao.tem-aviso { border-color: var(--laranja-borda); }
.es-cartao.tem-erro  { border-color: var(--vermelho-borda); }
.es-cartao.tem-aviso .adm-kpi-valor { color: var(--laranja-txt); }
.es-cartao.tem-erro  .adm-kpi-valor { color: var(--vermelho-txt); }

/* Zero é informação, mas não é notícia: o cartão apaga em vez de sumir, porque
   a fileira precisa ter sempre os mesmos cinco lugares — um painel que muda de
   forma a cada visita obriga a reler tudo. */
.es-cartao.vazio { opacity: .55; }

/* ── A linha de um produto ────────────────────────────────────────────── */

.es-linhas { margin: 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: 5px; }

.es-linha {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 150px 140px;
  gap: 12px;
  align-items: center;
  padding: 11px 14px;
  border: 1px solid var(--borda);
  border-radius: 10px;
  background: var(--superficie);
  color: inherit;
  text-decoration: none;
  transition: border-color .15s ease, background .15s ease;
}
.es-linha:hover { border-color: var(--borda-forte); background: var(--fundo); }
.es-linha:focus-visible { outline: 2px solid var(--azul); outline-offset: 1px; }

.es-quem { min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.es-quem strong { font-size: 14.5px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.es-quem small  { font-size: 11.5px; color: var(--texto-fraco); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* `contents`: o invólucro sai da conta da grade e os blocos voltam a ser
   colunas de primeiro nível. Ele existe só para o celular ter o que agrupar —
   a mesma solução do `.hi-stats`. */
.es-stats { display: contents; }
.es-saldo, .es-situacao { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.es-saldo { text-align: right; }
.es-saldo b { font-size: 14px; font-weight: 800; font-variant-numeric: tabular-nums; }
.es-saldo small { font-size: 11px; color: var(--texto-fraco); white-space: nowrap; }
.es-situacao { align-items: flex-end; }

/* ── A pastilha de situação ───────────────────────────────────────────── */

.es-pill {
  display: inline-block;
  padding: 3px 10px;
  border-radius: 999px;
  border: 1px solid var(--borda);
  background: var(--superficie);
  color: var(--texto-fraco);
  font-size: 11.5px; font-weight: 600;
  white-space: nowrap;
}
.es-pill.grande { padding: 5px 14px; font-size: 13px; }

.es-pill.cor-ok      { color: var(--verde-txt);    border-color: var(--verde-borda);    background: var(--verde-fundo); }
.es-pill.cor-aviso   { color: var(--laranja-txt);  border-color: var(--laranja-borda);  background: var(--laranja-fundo); }
.es-pill.cor-erro    { color: var(--vermelho-txt); border-color: var(--vermelho-borda); background: var(--vermelho-fundo); }
.es-pill.cor-info    { color: var(--azul);         border-color: var(--azul-borda);     background: var(--azul-fundo); }
/* `neutro` fica com o fundo e a borda da base: só a cor do texto muda, e é a
   cor de "não há nada a dizer sobre isto". */
.es-pill.cor-neutro  { color: var(--texto-fraco); }

/* ── A ficha ──────────────────────────────────────────────────────────── */

.es-identidade {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: 14px; flex-wrap: wrap;
  margin-top: 10px;
}

/* O link do canto do bloco ("Ver todas"). Vive no <h3>, então precisa desfazer
   o peso e o tamanho herdados do título. */
.cl-bloco-link {
  margin-left: auto;
  font-size: 12.5px; font-weight: 600;
  color: var(--azul); text-decoration: none;
}
.cl-bloco-link:hover { text-decoration: underline; }

/* ── Os dois formulários de movimento ─────────────────────────────────── */

/* Entrada e saída, lado a lado. `fieldset` de verdade (e não dois botões):
   são duas opções exclusivas, e é isso que um grupo de rádio significa para
   quem navega por teclado ou leitor de tela. */
.es-sentido {
  display: flex; gap: 8px;
  margin: 0 0 12px;
  padding: 0; border: 0;
}
.es-opcao {
  flex: 1;
  display: flex; align-items: center; justify-content: center; gap: 7px;
  padding: 9px 12px;
  border: 1px solid var(--borda);
  border-radius: 9px;
  background: var(--superficie);
  font-size: 13.5px; font-weight: 600;
  cursor: pointer;
  transition: border-color .15s ease, background .15s ease;
}
.es-opcao:hover { border-color: var(--borda-forte); }
/* `:has()` para o rótulo INTEIRO reagir à escolha, e não só o bolinha. O que
   se clica é a caixa toda, então é a caixa toda que precisa parecer marcada.
   Onde `:has()` não existe, o rádio nativo continua marcando — a tela perde o
   destaque, não a função. */
.es-opcao:has(input:checked) { border-color: var(--azul); background: var(--azul-fundo); }
.es-opcao:has(input:focus-visible) { outline: 2px solid var(--azul); outline-offset: 1px; }

.es-marcar {
  display: flex; align-items: flex-start; gap: 9px;
  margin: 14px 0 4px;
  font-size: 13px; line-height: 1.45;
  cursor: pointer;
}
.es-marcar input { width: 17px; height: 17px; flex: none; margin-top: 1px; accent-color: var(--azul); }

/* ── Para o certificado (25/09) ───────────────────────────────────────────
   Os campos que o certificado imprime por produto, à vista no cadastro. Um
   traço separa do cadastro de almoxarifado, e as pragas são as mesmas caixas
   do agendamento (`.nv-praga`), que mudam de cor ao marcar sem recarregar. */
.es-certificado {
  display: flex; flex-direction: column; gap: 10px;
  margin-top: 6px; padding-top: 14px;
  border-top: 1px solid var(--borda);
}
.es-certificado-titulo {
  margin: 0;
  font-size: 11.5px; font-weight: 700; letter-spacing: .05em;
  text-transform: uppercase; color: var(--texto-fraco);
}
.es-certificado > .cl-nota { margin-top: -6px; }
.es-pragas { margin: 0; padding: 0; border: 0; min-width: 0; }
/* A legenda com a cara do rótulo de um campo comum (`.campo > span`). */
.es-pragas legend { padding: 0; margin-bottom: 7px; font-size: 13.5px; color: var(--texto-fraco); }

/* O texto que substitui o seletor de unidade quando a categoria é armadilha.
   Herda `.campo` para ficar da mesma altura dos vizinhos na grade. */
.es-unidade-fixa b { font-size: 14px; font-weight: 700; }
.es-unidade-fixa small { font-size: 11.5px; color: var(--texto-fraco); }

/* ── O extrato ────────────────────────────────────────────────────────── */

.es-extrato { margin: 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: 4px; }

.es-mov {
  display: grid;
  grid-template-columns: 84px minmax(0, 1.2fr) minmax(0, 1.4fr) minmax(0, 1fr);
  gap: 12px;
  align-items: baseline;
  padding: 9px 12px;
  border: 1px solid var(--borda);
  border-radius: 9px;
  background: var(--superficie);
}
/* O resumo do consumo tem duas colunas só: produto e total. */
.es-mov.resumo { grid-template-columns: minmax(0, 1fr) 180px; }

.es-mov-quando, .es-mov-oque, .es-mov-quanto, .es-mov-quem {
  display: flex; flex-direction: column; gap: 2px; min-width: 0;
}
.es-mov-quando b { font-size: 12.5px; font-weight: 700; font-variant-numeric: tabular-nums; }
.es-mov-oque { flex-direction: row; align-items: baseline; gap: 8px; flex-wrap: wrap; }

.es-mov-produto {
  font-size: 13px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.es-mov-produto.forte { font-weight: 600; font-size: 13.5px; }

.es-mov-quanto b { font-size: 13.5px; font-weight: 700; font-variant-numeric: tabular-nums; }
.es-mov-quem b { font-size: 12.5px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.es-mov small {
  font-size: 11px; color: var(--texto-fraco); line-height: 1.4;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* Motivo e detalhe podem ser frases: eles são os únicos que quebram em duas
   linhas, porque cortá-los com reticências apagaria justamente o que a pessoa
   escreveu para ser lido depois. */
.es-mov-obs, .es-mov-detalhe { white-space: normal !important; }

/* ── O período do Consumo ─────────────────────────────────────────────── */

/* `align-items: flex-end` alinha a CAIXA DE MARGEM, e `.campo` do flowpest.css
   nasce `margin: 18px 0 6px` — ele foi escrito para formulário de coluna única,
   onde a margem é o espaço entre um campo e o de baixo. Numa fileira, esses 6px
   empurram o campo 6px acima do seletor e do botão. Medido em 04/09: os campos
   de data terminavam em 225px e o resto em 231px.

   É a MESMA armadilha que a s85 pegou com o `.btn` (`width: 100%;
   margin-top: 20px`) no cabeçalho da ficha. Todo componente daquela folha
   reusado numa FILEIRA precisa ter a margem zerada. */
.es-form-periodo { flex-wrap: wrap; align-items: flex-end; }
.es-form-periodo .campo { margin: 0; }
.es-campo-data { flex: 0 0 auto; min-width: 150px; }
.es-campo-data span { font-size: 11.5px; color: var(--texto-fraco); }

/* O campo de data veste o MESMO controle da fileira, e não o `.campo input` do
   flowpest.css, que tem 50px de altura e 16px de fonte. Aqueles 50px são do
   portal, onde o campo é de UMA COLUNA e o dedo é o alvo; aqui ele fica ao
   lado de um seletor e de um botão de 40px, e a fileira lê torta.

   Os 16px de fonte existem para o iPhone não dar zoom ao focar um campo — e
   não valem para `type="date"`, que abre o seletor do sistema e nunca o
   teclado. Medido em 04/09: 50px contra 40px dos vizinhos. */
.es-campo-data input {
  width: 100%; min-width: 0;
  min-height: 40px; height: 40px;
  padding: 0 10px;
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  background: var(--superficie);
  color: var(--texto);
  font: inherit; font-size: 13.5px;
}
.es-campo-data input:focus { outline: none; border-color: var(--azul); }
/* O seletor de produto do extrato tem nomes longos ("Barricade SC 500ml"), e a
   largura padrão de `.hi-periodo` os corta em três letras. */
.hi-periodo.larga { min-width: 260px; }

/* ── Telas médias ─────────────────────────────────────────────────────── */

@media (max-width: 1180px) {
  .es-mov { grid-template-columns: 76px minmax(0, 1fr) minmax(0, 1.2fr); }
  /* Numa grade de três, "quem fez" desce para a segunda fileira e ocupa as
     três colunas — assim ele não espreme as outras nem some. */
  .es-mov-quem { grid-column: 1 / -1; flex-direction: row; gap: 8px; align-items: baseline; }
}

/* ── Celular ──────────────────────────────────────────────────────────── */

@media (max-width: 700px) {
  /* A linha do produto vira duas fileiras: nome em cima, números embaixo. O
     invólucro `.es-stats` deixa de ser `contents` e volta a ser a caixa que
     agrupa os dois blocos numa fileira só. */
  .es-linha { grid-template-columns: 1fr; gap: 8px; }
  .es-stats {
    display: flex; align-items: center; justify-content: space-between;
    gap: 12px;
  }
  .es-saldo { text-align: left; }
  .es-situacao { align-items: flex-end; }

  /* O extrato no celular: TRÊS fileiras, não quatro.
     Na ordem do HTML os dois blocos estreitos (quando e quanto) ficam
     separados pelo bloco largo, e cada um sobrava numa fileira com a metade
     direita VAZIA — medido em 28/08: a linha dava 160px, com duas meias
     fileiras desperdiçadas. `order` os põe lado a lado sem mexer no HTML,
     que continua na ordem em que se lê no computador. */
  .es-mov, .es-mov.resumo { grid-template-columns: 1fr auto; gap: 6px 10px; }
  .es-mov-quando { order: 1; flex-direction: row; gap: 6px; align-items: baseline; }
  .es-mov-quanto { order: 2; text-align: right; align-items: flex-end; }
  .es-mov-oque   { order: 3; grid-column: 1 / -1; }
  .es-mov-quem   { order: 4; grid-column: 1 / -1; flex-direction: row; gap: 8px; align-items: baseline; flex-wrap: wrap; }
  /* O motivo escrito à mão é o único que pode quebrar: ele é frase. */
  .es-mov-quem .es-mov-obs { flex-basis: 100%; }

  .es-sentido { flex-direction: column; }
  .es-campo-data { min-width: 0; flex: 1 1 130px; }
  .hi-periodo.larga { min-width: 0; }
}


/* ══════════════════════════════════════════════════════════════════════════
   FOLLOW-UP (sessão 87)
   ══════════════════════════════════════════════════════════════════════════

   Reusa quase tudo: `.hi-abas` das abas, `.adm-cartao`/`.adm-kpi-*` dos
   números, `.es-extrato` e `.es-pill` do Estoque, `.cl-acao`/`.cl-form`/
   `.cl-nota` das gavetas, `.ag-paginas` da paginação. O que nasce aqui é a
   linha da fila e as bolinhas da cadência. */

/* ── O status do robô ─────────────────────────────────────────────────────
   Primeiro bloco da tela: se ele estiver vermelho, nada do resto está
   acontecendo sozinho. Cor pela BORDA ESQUERDA e não pelo fundo inteiro — é um
   aviso permanente, não um recado de ação, e uma faixa colorida ocupando a
   largura toda todo dia vira ruído que ninguém lê. */
.fu-robo {
  display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap;
  margin: 0 0 14px;
  padding: 11px 14px;
  border: 1px solid var(--borda);
  border-left: 3px solid var(--borda-forte);
  border-radius: 9px;
  background: var(--superficie);
  font-size: 13px;
}
.fu-robo strong { font-size: 13.5px; font-weight: 700; }
.fu-robo span { color: var(--texto-fraco); }

.fu-robo.tom-ok    { border-left-color: var(--verde); }
.fu-robo.tom-aviso { border-left-color: var(--laranja); }
.fu-robo.tom-erro  { border-left-color: var(--vermelho); }
.fu-robo.tom-ok    strong { color: var(--verde-txt); }
.fu-robo.tom-aviso strong { color: var(--laranja-txt); }
.fu-robo.tom-erro  strong { color: var(--vermelho-txt); }

.fu-painel { margin-bottom: 14px; }

/* ── O disparo manual ─────────────────────────────────────────────────────
   Os dois caminhos ficam SEPARADOS por uma linha: são ações diferentes, e a de
   baixo manda mensagem para quem recebeu ontem. Colar uma na outra é o que faz
   alguém clicar na errada. */
.fu-disparo form + form {
  margin-top: 14px;
  padding-top: 14px;
  border-top: 1px solid var(--borda);
}
.fu-disparo .btn:disabled { opacity: .45; cursor: not-allowed; }

/* ── A linha ──────────────────────────────────────────────────────────────
   Quatro colunas: quem · o quê · a cadência · quando sai. A gaveta da mensagem,
   quando existe, ocupa a fileira inteira embaixo. */
.fu-linha {
  display: grid;
  grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr) 160px 130px;
  gap: 12px;
  align-items: center;
  padding: 11px 14px;
  border: 1px solid var(--borda);
  border-radius: 10px;
  background: var(--superficie);
}
/* Quem sai HOJE ganha a borda esquerda — é a única linha sobre a qual há algo
   a decidir agora. */
.fu-linha.vencida { border-left: 3px solid var(--laranja); }

.fu-quem, .fu-oque, .fu-cadencia, .fu-quando {
  display: flex; flex-direction: column; gap: 2px; min-width: 0;
}
.fu-quem strong { font-size: 14.5px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fu-oque b { font-size: 13px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fu-cadencia b { font-size: 12.5px; font-weight: 700; font-variant-numeric: tabular-nums; }
.fu-linha small {
  font-size: 11px; color: var(--texto-fraco);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.fu-quando { align-items: flex-end; }
/* Tirar da cadência / Voltar para a cadência (13/10/2026): um botão de texto
   embaixo do "quando sai", sem abrir uma quinta coluna na grade da linha. */
.fu-cadencia-form { margin: 0; }
.fu-cadencia-btn {
  min-height: 32px; padding: 0 2px;
  border: 0; background: none;
  font: inherit; font-size: 12px; font-weight: 600;
  color: var(--texto-fraco); text-decoration: underline; text-underline-offset: 2px;
  cursor: pointer;
}
.fu-cadencia-btn:hover { color: var(--texto); }
.fu-cadencia-btn.ligar { color: var(--azul); }
@media (max-width: 700px) {
  .fu-cadencia-btn { min-height: 44px; }
}

/* ── As bolinhas da cadência ──────────────────────────────────────────────
   Quantas já saíram, qual é a próxima, quantas faltam. Elas vêm PRONTAS da
   camada de dados: contar na tela foi o que fez o Streamlit escrever "4/3"
   para quem tinha quatro tentativas configuradas.

   `aria-hidden` porque a mesma informação está escrita ao lado em texto
   ("tentativa 2 de 3") — para quem usa leitor de tela, as bolinhas seriam três
   ruídos sem significado. */
.fu-marcas { display: inline-flex; gap: 4px; align-items: center; }
.fu-marcas i {
  width: 8px; height: 8px; border-radius: 50%;
  border: 1px solid var(--borda-forte);
  background: transparent;
}
.fu-marcas i.feita   { background: var(--azul); border-color: var(--azul); }
.fu-marcas i.proxima { background: var(--laranja); border-color: var(--laranja); }
/* `futura` fica só com a borda: é o círculo vazio do que ainda não aconteceu. */

/* ── A mensagem, em gaveta ────────────────────────────────────────────────
   Ela repete em outras palavras o que a linha já diz — foi escrita para quem
   NÃO tem a linha na frente. Mesma decisão do resumo de WhatsApp na ficha da
   OS (s85). */
.fu-mensagem { grid-column: 1 / -1; margin-top: 4px; }
.fu-texto {
  margin: 8px 0 0;
  padding: 11px 13px;
  border: 1px solid var(--borda);
  border-radius: 9px;
  background: var(--fundo);
  font-size: 13px; line-height: 1.55;
  /* `pre-wrap`: a mensagem tem quebras de linha que fazem parte dela — é o
     texto que chega no WhatsApp do cliente, e colapsá-las mostraria um
     parágrafo que ninguém vai receber. */
  white-space: pre-wrap;
}

/* ── Telas médias ─────────────────────────────────────────────────────── */

@media (max-width: 1180px) {
  .fu-linha { grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr) 130px; }
  /* "quando sai" sobe para junto do nome: é a informação que decide se a linha
     interessa hoje, e ela não pode ser a primeira a sumir. */
  .fu-cadencia { grid-column: 1 / -1; flex-direction: row; gap: 8px; align-items: baseline; }
}

/* ── Celular ──────────────────────────────────────────────────────────── */

@media (max-width: 700px) {
  /* TRÊS fileiras, não quatro. `fu-cadencia` ocupa a largura toda e vem ANTES
     de `fu-quando` no HTML, então ela separava os dois blocos estreitos e
     empurrava "Sai hoje" para uma quarta fileira sozinha — 169px de linha,
     medido em 05/09. `order` os põe lado a lado sem mexer no HTML, que
     continua na ordem em que se lê no computador.

     É EXATAMENTE o mesmo defeito que o extrato do Estoque teve (e que eu
     corrigi um dia antes): num grid de duas colunas, todo bloco que ocupa a
     largura toda quebra a fileira de quem vem depois. */
  .fu-linha { grid-template-columns: 1fr auto; gap: 6px 10px; }
  .fu-quem     { order: 1; grid-column: 1 / -1; }
  .fu-oque     { order: 2; grid-column: 1; }
  .fu-quando   { order: 3; grid-column: 2; align-items: flex-end; }
  .fu-cadencia { order: 4; grid-column: 1 / -1; flex-direction: row; gap: 8px; align-items: baseline; }
  .fu-mensagem { order: 5; }
  .fu-robo { flex-direction: column; gap: 3px; }
}


/* ── A faixa de conversão (sessão 88) ─────────────────────────────────────
   Ela responde "a terceira mensagem vale a pena?". Fica no topo da aba
   Enviados, acima da lista, porque é a conclusão do que a lista detalha. */
.fu-conversao { margin-bottom: 14px; }

.fu-conv-topo {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 12px; flex-wrap: wrap;
  margin-bottom: 14px;
}
.fu-conv-topo h2 { margin: 0; font-size: 15px; font-weight: 700; }

/* O seletor de período. São links e não botões: cada um é um ENDEREÇO, e o
   gestor pode guardar nos favoritos o recorte que ele olha toda segunda. */
.fu-periodos { display: flex; gap: 4px; flex-wrap: wrap; }
.fu-periodo {
  padding: 4px 10px;
  border: 1px solid var(--borda);
  border-radius: 999px;
  background: var(--fundo);
  color: var(--texto-fraco);
  font-size: 12px; text-decoration: none; white-space: nowrap;
}
.fu-periodo:hover { border-color: var(--borda-forte); color: var(--texto); }
.fu-periodo.marcado {
  border-color: var(--azul); background: var(--azul-fundo); color: var(--azul);
  font-weight: 600;
}

/* Os números grandes. Quatro no máximo — o quinto viraria painel de avião. */
.fu-conv-numeros {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(130px, 1fr));
  gap: 10px;
  margin-bottom: 16px;
}
.fu-conv-num {
  display: flex; flex-direction: column; gap: 2px;
  padding: 11px 13px;
  border: 1px solid var(--borda);
  border-radius: 9px;
  background: var(--fundo);
}
.fu-conv-num b {
  font-size: 22px; font-weight: 700; line-height: 1.1;
  font-variant-numeric: tabular-nums;
}
.fu-conv-num small { font-size: 11.5px; color: var(--texto-fraco); line-height: 1.35; }
/* O dinheiro ganha a borda de destaque, não fundo colorido: é o número que se
   procura primeiro, e um retângulo verde ao lado de três brancos vira anúncio. */
.fu-conv-num.destaque { border-left: 3px solid var(--verde); }
.fu-conv-num.destaque b { color: var(--verde-txt); }

/* ── As barras ────────────────────────────────────────────────────────────
   Uma linha por tentativa. Barra e não rosca: a comparação aqui é entre três
   comprimentos, e comprimento se compara de olho — ângulo, não. */
.fu-barras { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }
.fu-barra {
  display: grid;
  grid-template-columns: 92px 1fr 84px;
  align-items: center;
  gap: 10px;
}
.fu-barra-nome { font-size: 12.5px; color: var(--texto-fraco); white-space: nowrap; }
.fu-barra-trilho {
  height: 10px; border-radius: 999px;
  background: var(--borda);
  overflow: hidden;
}
.fu-barra-cheia {
  display: block; height: 100%;
  border-radius: 999px;
  background: var(--azul);
  /* `min-width` para que 1 de 40 não vire uma barra invisível: quem converteu
     pouco precisa aparecer como pouco, não como nada. */
  min-width: 2px;
}
.fu-barra-num {
  display: flex; align-items: baseline; gap: 6px;
  justify-content: flex-end;
}
.fu-barra-num b { font-size: 14px; font-weight: 700; font-variant-numeric: tabular-nums; }
.fu-barra-num small { font-size: 11px; color: var(--texto-fraco); }

/* ── O resto: o que não entrou na taxa ────────────────────────────────────
   Fica embaixo e em texto corrido de propósito. São ressalvas, e ressalva em
   caixa de número vira número. */
.fu-conv-resto {
  display: flex; flex-wrap: wrap; gap: 6px 16px;
  margin: 14px 0 0;
  padding-top: 12px;
  border-top: 1px solid var(--borda);
  font-size: 12px; color: var(--texto-fraco);
}
.fu-conv-resto b { color: var(--texto); font-weight: 700; }
/* A cobrança em quem já agendou é o único item da faixa que pede ação. */
.fu-conv-resto .alerta b { color: var(--laranja-txt); }

@media (max-width: 700px) {
  .fu-conv-topo { flex-direction: column; align-items: stretch; gap: 8px; }
  .fu-barra { grid-template-columns: 82px 1fr 70px; gap: 8px; }
  .fu-conv-num b { font-size: 19px; }
}


/* ══════════════════════════════════════════════════════════════════════════
   FINANCEIRO — Aprovações e Contas a receber (sessão 89)
   ══════════════════════════════════════════════════════════════════════════

   Reusa `.hi-abas` das abas, `.adm-cartao`/`.adm-kpi-*` dos números,
   `.es-extrato` e `.es-pill` do Estoque, `.cl-acao`/`.cl-form` das gavetas e
   `_followup_paginas.html` da paginação. O que nasce aqui é a linha de item
   com dinheiro e a confirmação escrita. */

/* ── A fila vazia ─────────────────────────────────────────────────────────
   Ela EXPLICA em vez de só dizer "nada aqui": quem abre Aprovações pela
   primeira vez não sabe o que faz um item cair nesta tela. */
.fi-vazio h2 { margin: 0 0 6px; font-size: 15px; font-weight: 700; }
.fi-vazio p { margin: 0; font-size: 13px; color: var(--texto-fraco); line-height: 1.55; }

/* A contagem dentro do rótulo da aba. */
.fi-conta {
  display: inline-block;
  margin-left: 6px;
  padding: 1px 7px;
  border-radius: 999px;
  background: var(--borda);
  color: var(--texto-fraco);
  font-size: 11.5px; font-weight: 700;
  font-variant-numeric: tabular-nums;
}
.hi-aba.ativa .fi-conta { background: var(--azul-fundo); color: var(--azul); }

/* ── Os três números do topo ──────────────────────────────────────────────
   "Vencido" é o único que vira LINK, e por isso é o único que reage ao mouse:
   ver o total atrasado e não conseguir chegar nele é o que faz alguém filtrar
   na mão. */
.fi-topo { margin-bottom: 14px; }
.fi-topo small { font-size: 11px; color: var(--texto-fraco); }

/* Vermelho só quando há o que cobrar. Zero atrasado não é um alarme apagado,
   é uma boa notícia, e pintá-lo de vermelho ensinaria a ignorar a cor. */
.fi-vencido { border-left: 3px solid var(--vermelho); }
.fi-vencido .adm-kpi-valor { color: var(--vermelho-txt); }

/* ── O seletor "só as vencidas" ───────────────────────────────────────────
   Ele fica ao lado das abas porque é isso que ele faz: escolhe o que a lista
   mostra. Antes era um link escondido embaixo do número vencido, num cartão
   que parecia igual aos outros dois e se comportava diferente.

   É um link com cara de caixa de seleção: o estado mora na URL, o "voltar" do
   navegador funciona, e ele funciona com o JavaScript desligado. */
.fi-barra {
  display: flex; align-items: center; justify-content: space-between;
  gap: 14px; flex-wrap: wrap;
  margin-bottom: 14px;
}
.fi-barra .hi-abas { margin-bottom: 0; }

.fi-so-vencidas {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 6px 12px;
  border: 1px solid var(--borda);
  border-radius: 999px;
  background: var(--fundo);
  color: var(--texto-fraco);
  font-size: 12.5px; text-decoration: none; white-space: nowrap;
}
.fi-so-vencidas:hover { border-color: var(--borda-forte); color: var(--texto); }
.fi-so-vencidas .fi-caixa {
  width: 15px; height: 15px; flex-shrink: 0;
  border: 1.5px solid var(--borda-forte);
  border-radius: 4px;
  background: var(--superficie);
}
.fi-so-vencidas.marcado {
  border-color: var(--vermelho-borda);
  background: var(--vermelho-fundo);
  color: var(--vermelho-txt);
  font-weight: 600;
}
.fi-so-vencidas.marcado .fi-caixa {
  border-color: var(--vermelho);
  background: var(--vermelho);
  /* O tique, desenhado na borda: dois lados de um quadrado girado 45°. */
  position: relative;
}
.fi-so-vencidas.marcado .fi-caixa::after {
  content: ""; position: absolute;
  left: 4px; top: 1px; width: 4px; height: 8px;
  border: solid #FFFFFF; border-width: 0 2px 2px 0;
  transform: rotate(45deg);
}

/* ── O item de aprovação ──────────────────────────────────────────────────
   Empilhado, e não em grade: cada item tem um FORMULÁRIO, e formulário dentro
   de coluna estreita vira campo de 60px. Aqui a leitura é de cima para baixo —
   quem é, quanto era e virou, por quê, e então o que fazer. */
.fi-item {
  display: flex; flex-direction: column; gap: 8px;
  padding: 13px 15px;
  border: 1px solid var(--borda);
  border-radius: 10px;
  background: var(--superficie);
}
.fi-quem { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.fi-quem strong { font-size: 14.5px; font-weight: 600; }
.fi-quem small { font-size: 11.5px; color: var(--texto-fraco); }

.fi-valor { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
.fi-valor b { font-size: 16px; font-weight: 700; font-variant-numeric: tabular-nums; }
.fi-valor small { font-size: 11.5px; color: var(--texto-fraco); }

/* A troca de valor é o ASSUNTO da linha: aprovar sem ver o orçado é aprovar no
   escuro. Quando a diferença é grande, ela deixa de ser informação e vira
   aviso — e aí ganha fundo, não só cor de texto. */
.fi-troca { color: var(--laranja-txt); }
.fi-troca.alerta {
  padding: 2px 8px;
  border-radius: 7px;
  border: 1px solid var(--vermelho-borda);
  background: var(--vermelho-fundo);
  color: var(--vermelho-txt);
}

.fi-just {
  margin: 0;
  padding: 9px 12px;
  border-radius: 8px;
  background: var(--fundo);
  font-size: 12.5px; line-height: 1.55;
  /* A justificativa do técnico tem quebras de linha que fazem parte dela. */
  white-space: pre-wrap;
}

/* ── O formulário da aprovação ────────────────────────────────────────────
   Separado por uma linha do que está acima: em cima é o que aconteceu, embaixo
   é o que você vai fazer. */
.fi-form {
  display: flex; flex-direction: column; gap: 9px;
  margin-top: 2px;
  padding-top: 11px;
  border-top: 1px solid var(--borda);
}
.fi-form .campo { margin: 0; }
.fi-campo-valor { max-width: 220px; }
.fi-campo-valor input { font-variant-numeric: tabular-nums; }
.fi-form .btn { align-self: flex-start; }

/* O que a aprovação DISPARA, escrito embaixo do botão. Aprovar aqui manda
   WhatsApp; o botão sozinho não diz isso. */
.fi-efeito {
  margin: 0;
  font-size: 11.5px; color: var(--texto-fraco); line-height: 1.5;
}

/* ── A confirmação escrita ────────────────────────────────────────────────
   Aparece só quando há o que confirmar: valor muito longe do orçado, ou um
   cancelamento que não tem volta. É caixinha e não segundo clique porque o
   texto AO LADO é o aviso — um "tem certeza?" genérico não diz quantas vezes o
   orçado o número é. */
.fi-confirmo {
  display: flex; align-items: flex-start; gap: 9px;
  padding: 10px 12px;
  border: 1px solid var(--laranja-borda);
  border-radius: 9px;
  background: var(--laranja-fundo);
  font-size: 12.5px; line-height: 1.5;
  cursor: pointer;
}
.fi-confirmo input { margin-top: 2px; flex-shrink: 0; }
.fi-confirmo b { font-weight: 700; }

/* ── A linha da conta ─────────────────────────────────────────────────────
   Quatro colunas: quem · em que pé está · quanto · o que fazer. */
.fi-linha {
  /* QUEM de um lado, o resto AGRUPADO no outro. A s89 tentou o contrário:
     juntou o estado ao nome num bloco só, e o vazio não saiu do lugar. Medido
     em 10/09, o bloco esquerdo terminava em x=545 e o valor só começava em
     x=1147. 602px de deserto, porque o problema nunca foi onde o estado morava
     e sim que a coluna elástica tinha 726px para 221px de conteúdo.

     Agora o elástico fica SÓ debaixo do nome, e ele empurra estado, valor e
     ação para o fim da fileira, colados entre si. O vazio continua existindo,
     porque ele tem que ir para algum lugar. Só que agora fica depois do nome,
     onde o olho já terminou de ler, e não entre duas coisas que precisam ser
     lidas juntas. */
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto 140px 124px;
  gap: 20px;
  /* LINHA DE BASE, e não centro. Com `center` o alinhamento do valor dependia
     do DADO: conta sem forma de pagamento tem uma linha só no bloco do valor,
     e ele descia 11px em relação ao nome. Aconteceu em 6 das 8 fileiras
     medidas. Pela base, nome, pílula e valor pousam na mesma linha sempre,
     tenha o bloco uma linha ou três. */
  align-items: baseline;
  padding: 12px 14px;
  border: 1px solid var(--borda);
  border-radius: 10px;
  background: var(--superficie);
}

/* `.fi-quem` NÃO entra aqui de propósito: ele já é estilizado no bloco de
   Aprovações, que divide a classe com esta tela. Redeclarar mudaria a outra. */
.fi-prazo, .fi-dinheiro {
  display: flex; flex-direction: column; gap: 3px; min-width: 0;
}
.fi-prazo small, .fi-dinheiro small { font-size: 11px; color: var(--texto-fraco); }
.fi-dinheiro { align-items: flex-end; text-align: right; }
.fi-dinheiro b { font-size: 15.5px; font-weight: 700; font-variant-numeric: tabular-nums; }
.fi-pendura { color: var(--laranja-txt); font-weight: 600; }
.fi-prazo .es-pill { align-self: flex-start; }

/* O botão é o único bloco que NÃO segue a linha de base: ele é uma caixa de
   52px, não um texto, e pousá-lo na base do nome o jogaria para fora. */
.fi-acao { display: flex; justify-content: flex-end; align-self: center; }
/* A MESMA armadilha do `.cl-acoes-topo` (s85) e do `.es-form-periodo` (s86),
   pela terceira vez: o `.btn` do flowpest.css nasce com `margin-top: 20px`,
   porque lá ele é o botão que vem DEPOIS dos campos de um formulário de coluna
   única. Numa fileira não há campo nenhum acima dele, e a margem vira ar.

   Medido em 10/09: botão de 51,6px dentro de uma caixa de 71,6px. Esses 20px
   eram quem definia a altura da fileira, e por tabela quem produzia o
   desencontro de 11px entre o nome e o valor: com `align-items: center`, o
   bloco do valor (25px) descia mais que o do nome (47px) dentro dos 72px.

   O `display: flex` no form é o outro meio dos 20px: como bloco, ele ainda
   abriria um line-box para o botão `inline-flex` sentar na linha de base. */
.fi-acao form { width: 100%; display: flex; }
.fi-acao .btn { width: 100%; margin-top: 0; }

/* A gaveta ocupa a fileira inteira embaixo. */
.fi-gaveta { grid-column: 1 / -1; margin-top: 2px; }

/* O cancelamento fica SEPARADO da correção por uma linha: um se desfaz, o
   outro não. Colados, o clique errado é questão de tempo. */
.fi-cancelar {
  margin-top: 14px;
  padding-top: 14px;
  border-top: 1px solid var(--borda);
}
.fi-cancelar .btn.perigo {
  border-color: var(--vermelho-borda);
  color: var(--vermelho-txt);
}
.fi-cancelar .btn.perigo:hover {
  background: var(--vermelho); color: #FFFFFF; border-color: var(--vermelho);
}

/* ── Telas médias ─────────────────────────────────────────────────────── */

@media (max-width: 1080px) {
  .fi-linha { grid-template-columns: minmax(0, 1fr) auto 120px 110px; gap: 14px; }
}

/* ── Celular ──────────────────────────────────────────────────────────── */

@media (max-width: 700px) {
  /* Duas colunas, e o bloco que ocupa a largura toda vem SEMPRE por último de
     cada fileira. Foi assim que a linha do Estoque e a do Follow-up quebraram
     em 04 e 05/09: um bloco largo no meio empurra o resto da fileira. */
  .fi-linha { grid-template-columns: 1fr auto; gap: 8px 12px; align-items: center; }
  .fi-quem     { grid-column: 1 / -1; }
  .fi-prazo    { grid-column: 1 / -1; flex-direction: row; align-items: baseline;
                 gap: 8px; }
  .fi-dinheiro { grid-column: 1; align-items: flex-start; text-align: left; }
  .fi-acao     { grid-column: 2; align-self: center; }
  .fi-acao form, .fi-acao .btn { width: auto; }
  .fi-campo-valor { max-width: none; }
  .fi-form .btn { align-self: stretch; }
  .fi-barra { flex-direction: column; align-items: stretch; gap: 10px; }
}


/* ══════════════════════════════════════════════════════════════════════════
   AVALIAÇÕES (sessão 90)
   ══════════════════════════════════════════════════════════════════════════
   Reusa quase tudo: `.adm-cartoes`/`.adm-kpi-*` dos indicadores, `.fu-barras`
   do Follow-up para a distribuição, `.es-extrato` e `.es-pill` do Estoque,
   `.fi-so-vencidas` de Contas para os filtros, `.cl-bloco`/`.cl-conta` das
   seções e `_followup_paginas.html` da paginação. O que nasce aqui é a régua
   de estrelas e a linha de avaliação.

   E a lição de 10/09 vale desde a primeira linha: TODO componente do
   flowpest.css reusado dentro de uma fileira precisa ter a margem zerada. O
   `.btn` nasce com `margin-top: 20px`, escrito para quando ele fecha um
   formulário de coluna única; numa fileira não há campo acima dele e a margem
   vira ar. Já pegou o projeto três vezes (s85, s86, s90). */

.av-topo { margin-bottom: 14px; }

/* ── A régua de estrelas ──────────────────────────────────────────────────
   Um trilho e um preenchimento, e não cinco caracteres de estrela. O painel
   não usa emoji, e uma fileira de estrelas coladas é o tipo de coisa que o
   leitor de tela lê letra por letra. A NOTA vai escrita ao lado, em texto
   ("4 de 5"); isto aqui é o mesmo dado em outra forma, e por isso vai marcado
   `aria-hidden` no template. */
.av-estrelas {
  display: block;
  width: 88px; height: 8px;
  border-radius: 999px;
  background: var(--borda);
  overflow: hidden;
}
.av-estrelas-cheia {
  display: block; height: 100%;
  border-radius: 999px;
  background: var(--ouro);
}

.av-dist { margin-bottom: 14px; }
/* O `.cl-bloco` do painel não costuma ter título visível: quem diz o que a
   lista é são as abas e a linha de contagem. Esta tela não tem abas, então os
   títulos existem, mas no tamanho de rótulo de seção e não no de título de
   página, que é o que o `h2` solto do flowpest.css entrega (24px medidos). */
.av-dist h2, .av-titulo { margin: 0 0 12px; font-size: 15px; font-weight: 700; }
/* As notas 1 e 2 são as que pedem ação, e por isso são as únicas que mudam de
   cor. Pintar todas as cinco de cores diferentes seria semáforo sem sentido:
   nota 3 não é "atenção", é nota 3. */
.fu-barra-cheia.ruim { background: var(--vermelho); }

/* ── Os filtros ──────────────────────────────────────────────────────────
   São links, e não caixas marcáveis: mudar o recorte é mudar de lugar, e o
   lugar tem endereço. Vestem o mesmo controle do "Só as vencidas" de Contas. */
/* `.fi-barra` nasce `space-between`, porque em Contas ela tem as abas de um
   lado e uma caixa sozinha do outro. Aqui são sete controles do mesmo tipo, e
   espalhados pelos 1203px da fileira eles param de se ler como um grupo. */
.av-filtros { flex-wrap: wrap; gap: 8px; margin-bottom: 14px;
              justify-content: flex-start; }
.av-filtro-rotulo {
  font-size: 12.5px; color: var(--texto-fraco);
  align-self: center; margin-right: 2px;
}
/* "Limpar o filtro" é ação, não estado: não leva a caixinha das outras. */
.av-limpar .fi-caixa { display: none; }

/* ── Os comentários em destaque ──────────────────────────────────────────── */
.av-comentarios { list-style: none; margin: 0; padding: 0; display: grid; gap: 10px; }
.av-comentario {
  display: grid;
  grid-template-columns: 130px minmax(0, 1fr) 180px;
  gap: 16px;
  align-items: baseline;
  padding: 12px 14px;
  border: 1px solid var(--borda);
  border-radius: 10px;
  background: var(--superficie);
}
.av-coment-nota { display: flex; flex-direction: column; gap: 5px; }
.av-coment-nota b { font-size: 12.5px; font-weight: 600; color: var(--texto-fraco); }
/* O texto do cliente, com as aspas desenhadas em vez de digitadas: assim o que
   está entre elas é exatamente o que ele escreveu, sem caractere nosso junto. */
.av-coment-texto {
  margin: 0;
  padding-left: 14px;
  border-left: 2px solid var(--ouro);
  font-size: 14px; line-height: 1.6;
}
.av-coment-quem { display: flex; flex-direction: column; gap: 2px; text-align: right; }
.av-coment-quem strong { font-size: 13.5px; font-weight: 600; }
.av-coment-quem small { font-size: 11.5px; color: var(--texto-fraco); }

/* ── A linha da lista ─────────────────────────────────────────────────────
   Quatro blocos: quem · que nota deu · em que pé está · o que fazer. O
   comentário, quando existe, ocupa a fileira inteira embaixo, do mesmo jeito
   que a gaveta de Contas. */
.av-linha {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 104px auto 124px;
  gap: 10px 18px;
  align-items: baseline;
  padding: 12px 14px;
  border: 1px solid var(--borda);
  border-radius: 10px;
  background: var(--superficie);
}
.av-quem, .av-nota, .av-estado {
  display: flex; flex-direction: column; gap: 4px; min-width: 0;
}
.av-quem strong { font-size: 14.5px; font-weight: 600; }
.av-nota b { font-size: 13px; font-weight: 600; }
.av-quem small, .av-nota small, .av-estado small {
  font-size: 11.5px; color: var(--texto-fraco);
}
.av-estado { align-items: flex-end; text-align: right; }
.av-estado .es-pill { align-self: flex-end; }
/* O bloco da ação é uma CAIXA, e não texto: pousá-lo na linha de base do nome
   o jogaria para fora da fileira. */
.av-acao { display: flex; justify-content: flex-end; align-self: center; }
.av-acao .btn { width: 100%; margin-top: 0; padding: 9px 14px; font-size: 13px; }
.av-linha-coment {
  grid-column: 1 / -1;
  margin: 2px 0 0;
  padding: 10px 12px;
  border-left: 2px solid var(--ouro);
  border-radius: 0 8px 8px 0;
  background: var(--fundo);
  font-size: 13px; line-height: 1.6;
}

/* ── Telas médias ─────────────────────────────────────────────────────── */

@media (max-width: 1080px) {
  .av-comentario { grid-template-columns: 110px minmax(0, 1fr) 150px; gap: 12px; }
  .av-linha { grid-template-columns: minmax(0, 1fr) 96px auto 110px; gap: 8px 14px; }
}

/* ── Celular ──────────────────────────────────────────────────────────── */

@media (max-width: 700px) {
  /* Duas colunas, e o bloco que ocupa a largura toda vem SEMPRE por último de
     cada fileira. Foi assim que a linha do Estoque e a do Follow-up quebraram
     em 04 e 05/09: um bloco largo no meio empurra o resto da fileira. */
  .av-linha { grid-template-columns: 1fr auto; gap: 8px 12px; align-items: center; }
  .av-quem   { grid-column: 1 / -1; }
  .av-nota   { grid-column: 1; }
  .av-estado { grid-column: 2; }
  .av-acao   { grid-column: 1 / -1; align-self: stretch; }
  .av-acao .btn { width: auto; }

  .av-comentario { grid-template-columns: 1fr; gap: 8px; }
  .av-coment-nota { flex-direction: row; align-items: center; gap: 10px; }
  .av-coment-quem { text-align: left; }
  .av-filtros { flex-direction: row; }
}


/* ══════════════════════════════════════════════════════════════════════════
   REAPLICAÇÕES (sessão 90)
   ══════════════════════════════════════════════════════════════════════════
   Reusa quase tudo: `.adm-cartoes`/`.adm-kpi-*` dos indicadores, `.fu-robo` do
   Follow-up para o estado do robô, `.hi-abas`/`.fi-conta` dos recortes,
   `.es-extrato` e `.es-pill` do Estoque, `.cl-acao`/`.cl-form`/`.cl-nota` das
   gavetas e `_followup_paginas.html` da paginação. O que nasce aqui é a linha
   da fila e a marca de quem já respondeu.

   E a margem do `.btn` do flowpest.css vai zerada desde a primeira versão: ela
   nasce em 20px, escrita para quando o botão fecha um formulário de coluna
   única, e numa fileira vira ar. Já pegou o projeto três vezes (s85, s86, s90). */

.re-explica { margin: 0 0 12px; }
.re-topo { margin-bottom: 14px; }
.re-aviso {
  margin: 0 0 12px;
  padding: 10px 12px;
  border-left: 3px solid var(--laranja-borda);
  border-radius: 0 8px 8px 0;
  background: var(--laranja-fundo);
  color: var(--laranja-txt);
}
.re-filtros { margin-bottom: 14px; }

/* ── A linha da fila ──────────────────────────────────────────────────────
   Quatro blocos: quem e o que foi tratado · quanto falta · em que ponto da
   cadência · o que fazer. A gaveta do envio ocupa a fileira inteira embaixo. */
.re-linha {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto 190px 132px;
  gap: 10px 18px;
  align-items: baseline;
  padding: 12px 14px;
  border: 1px solid var(--borda);
  border-radius: 10px;
  background: var(--superficie);
}
/* Quem já marcou a visita continua na lista, mas recuado: ele não é mais
   trabalho a fazer, é confirmação de que o aviso funcionou. Sumir da tela faria
   o atendente achar que o aviso se perdeu. */
.re-linha.resolvida { opacity: .72; }

.re-quem, .re-prazo, .re-cadencia {
  display: flex; flex-direction: column; gap: 3px; min-width: 0;
}
.re-quem strong { font-size: 14.5px; font-weight: 600; }
.re-quem small, .re-prazo small, .re-cadencia small {
  font-size: 11.5px; color: var(--texto-fraco); line-height: 1.5;
}
.re-prazo .es-pill { align-self: flex-start; }
.re-resolvido { color: var(--verde-txt); font-weight: 600; }
.re-esgotado { color: var(--texto-fraco); font-style: italic; }
.re-cadencia { align-items: flex-end; text-align: right; }
.re-cadencia b { font-size: 12.5px; font-weight: 600; }

/* ── As ações ─────────────────────────────────────────────────────────────
   Duas que NÃO mandam mensagem (ver a ficha, abrir a conversa) ficam à vista.
   A que manda fica na gaveta abaixo. */
.re-acao {
  display: flex; flex-direction: column; gap: 6px;
  align-self: center; justify-content: flex-end;
}
.re-acao .btn {
  width: 100%; margin-top: 0;
  padding: 8px 12px; font-size: 12.5px;
}
.re-gaveta { grid-column: 1 / -1; margin-top: 2px; }
.re-sem-envio {
  grid-column: 1 / -1;
  margin: 2px 0 0;
  font-size: 11.5px; color: var(--texto-fraco); font-style: italic;
}

/* ── Telas médias ─────────────────────────────────────────────────────── */

@media (max-width: 1080px) {
  .re-linha { grid-template-columns: minmax(0, 1fr) auto 160px 118px; gap: 8px 14px; }
}

/* ── Celular ──────────────────────────────────────────────────────────── */

@media (max-width: 700px) {
  /* Duas colunas, e o bloco que ocupa a largura toda vem SEMPRE por último de
     cada fileira. Foi assim que a linha do Estoque e a do Follow-up quebraram
     em 04 e 05/09: um bloco largo no meio empurra o resto da fileira. */
  .re-linha { grid-template-columns: 1fr auto; gap: 8px 12px; align-items: center; }
  .re-quem     { grid-column: 1 / -1; }
  .re-prazo    { grid-column: 1; }
  .re-cadencia { grid-column: 2; }
  .re-acao     { grid-column: 1 / -1; flex-direction: row; }
  .re-acao .btn { width: auto; flex: 1 1 auto; }
  .re-filtros { flex-wrap: wrap; }
}


/* ══════════════════════════════════════════════════════════════════════════
   CAMPANHAS SAZONAIS (sessão 90)
   ══════════════════════════════════════════════════════════════════════════
   Reusa quase tudo: `.hi-abas`/`.fi-conta` das abas, `.es-extrato` e
   `.es-pill` do Estoque, `.cl-bloco`/`.cl-conta`/`.cl-nota`/`.cl-form` das
   seções e formulários, `.cl-acao` das gavetas, `.fi-confirmo`/`.fi-cancelar`
   da confirmação de Contas, `.av-titulo` dos títulos de seção.

   O que nasce aqui: o cartão de sugestão, o cartão de campanha agendada, a
   lista de destinatários e a grade de pragas por estação.

   E a margem do `.btn` do flowpest.css vai zerada onde ele entra em fileira:
   ela nasce em 20px, escrita para quando o botão fecha um formulário de coluna
   única. Já pegou o projeto três vezes (s85, s86, s90). */

.ca-explica { margin: 0 0 12px; }
.ca-abas { margin-bottom: 14px; }
.ca-bloco { margin-bottom: 14px; }

/* ── As pragas da estação, na aba de sugestões ──────────────────────────── */
.ca-alvos { list-style: none; margin: 0 0 14px; padding: 0; display: grid; gap: 8px; }
.ca-alvo {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 12px;
  align-items: baseline;
  padding: 10px 12px;
  border: 1px solid var(--borda);
  border-radius: 9px;
  background: var(--superficie);
}
.ca-alvo-nome { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.ca-alvo-nome strong { font-size: 14px; font-weight: 600; }
.ca-alvo-conta { display: flex; align-items: baseline; gap: 6px; white-space: nowrap; }
.ca-alvo-conta b { font-size: 15px; font-weight: 700; font-variant-numeric: tabular-nums; }
.ca-alvo-conta small, .ca-sem-base { font-size: 11.5px; color: var(--texto-fraco); }
/* "Sem base científica" muda o que a IA escreve, então não é decoração: é
   aviso. Mas também não é erro, por isso laranja e não vermelho. */
.ca-sem-base { color: var(--laranja-txt); }

.ca-gerar { margin: 0; }

/* ── O cartão de sugestão e o de campanha agendada ───────────────────────── */
.ca-sugestao, .ca-agendada {
  margin-top: 12px;
  padding: 14px;
  border: 1px solid var(--borda);
  border-radius: 10px;
  background: var(--superficie);
}
.ca-sug-topo, .ca-ag-topo {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 12px; flex-wrap: wrap;
  margin-bottom: 10px;
}
.ca-sug-topo strong, .ca-ag-quem strong { font-size: 15px; font-weight: 600; }
.ca-ag-quem { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.ca-ag-quem small { font-size: 11.5px; color: var(--texto-fraco); }

.ca-form { margin: 0; }
.ca-form textarea {
  min-height: 110px; resize: vertical;
  font-family: inherit; font-size: 14px; line-height: 1.6;
}
/* Os campos curtos em fileira. O `.campo` do flowpest.css nasce com
   `margin: 18px 0 6px`, escrito para formulário de uma coluna; numa fileira
   esses 6px empurram um campo para fora da linha dos outros (s86). */
.ca-linha-campos {
  display: flex; flex-wrap: wrap; gap: 12px; align-items: flex-end;
}
.ca-linha-campos .campo { margin: 0; flex: 1 1 180px; min-width: 160px; }

.ca-descartar { margin-top: 10px; padding-top: 12px; border-top: 1px solid var(--borda); }
.ca-descartar .btn { margin-top: 0; }

/* ── A campanha agendada ─────────────────────────────────────────────────── */
.ca-mensagem, .ca-linha-msg {
  margin: 0 0 10px;
  padding: 10px 12px;
  border-left: 2px solid var(--ouro);
  border-radius: 0 8px 8px 0;
  background: var(--fundo);
  font-size: 13.5px; line-height: 1.6;
  white-space: pre-wrap;
}
.ca-travada {
  margin: 0 0 10px;
  padding: 10px 12px;
  border-left: 3px solid var(--laranja-borda);
  border-radius: 0 8px 8px 0;
  background: var(--laranja-fundo);
  color: var(--laranja-txt);
}
.ca-ag-numeros { display: flex; flex-wrap: wrap; gap: 8px 20px; margin-bottom: 12px; }
.ca-ag-numeros span { display: flex; align-items: baseline; gap: 6px; }
.ca-ag-numeros b { font-size: 15px; font-weight: 700; font-variant-numeric: tabular-nums; }
.ca-ag-numeros small { font-size: 11.5px; color: var(--texto-fraco); }
.ca-ag-numeros .alerta b, .ca-resto .alerta { color: var(--laranja-txt); }

.ca-executar { margin: 0 0 10px; }
.ca-gaveta { margin-top: 8px; }

/* ── A lista de destinatários ────────────────────────────────────────────── */
.ca-destinatarios { margin-top: 10px; }
.ca-dest {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto 96px;
  gap: 10px 14px;
  align-items: baseline;
  padding: 9px 12px;
  border: 1px solid var(--borda);
  border-radius: 9px;
  background: var(--fundo);
}
.ca-dest-quem { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.ca-dest-quem strong { font-size: 13.5px; font-weight: 600; }
.ca-dest-quem small { font-size: 11px; color: var(--texto-fraco); }
.ca-dest form { display: flex; justify-content: flex-end; align-self: center; }
.ca-dest .btn {
  width: 100%; margin-top: 0;
  padding: 6px 10px; font-size: 12px;
}

/* ── A grade de pragas por estação ───────────────────────────────────────── */
.ca-estacao {
  margin: 0 0 14px;
  padding: 12px 14px;
  border: 1px solid var(--borda);
  border-radius: 10px;
  background: var(--superficie);
}
.ca-estacao legend {
  display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap;
  padding: 0 6px;
  font-size: 14px; font-weight: 700;
}
.ca-estacao legend small { font-size: 11.5px; font-weight: 400; color: var(--texto-fraco); }
.ca-pragas {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
  gap: 8px;
  margin-top: 8px;
}
.ca-praga {
  display: flex; align-items: flex-start; gap: 8px;
  padding: 8px 10px;
  border: 1px solid var(--borda);
  border-radius: 8px;
  font-size: 13px; line-height: 1.45;
  cursor: pointer;
}
.ca-praga:hover { border-color: var(--borda-forte); }
.ca-praga input { margin-top: 2px; flex-shrink: 0; }
.ca-praga span { display: flex; flex-direction: column; gap: 1px; min-width: 0; }

/* ── A linha do histórico ────────────────────────────────────────────────── */
.ca-linha {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto 170px;
  gap: 10px 18px;
  align-items: baseline;
  padding: 12px 14px;
  border: 1px solid var(--borda);
  border-radius: 10px;
  background: var(--superficie);
}
.ca-quem, .ca-estado, .ca-numeros {
  display: flex; flex-direction: column; gap: 3px; min-width: 0;
}
.ca-quem strong { font-size: 14.5px; font-weight: 600; }
.ca-quem small, .ca-numeros small { font-size: 11.5px; color: var(--texto-fraco); }
.ca-estado { align-items: flex-end; }
.ca-numeros { align-items: flex-end; text-align: right; }
.ca-numeros b { font-size: 15px; font-weight: 700; font-variant-numeric: tabular-nums; }
.ca-resto {
  grid-column: 1 / -1;
  display: flex; flex-wrap: wrap; gap: 4px 16px;
  margin: 2px 0 0;
  font-size: 11.5px; color: var(--texto-fraco);
}
.ca-linha-msg { grid-column: 1 / -1; margin: 4px 0 0; }

/* ── Telas médias ─────────────────────────────────────────────────────── */

@media (max-width: 1080px) {
  .ca-linha { grid-template-columns: minmax(0, 1fr) auto 140px; gap: 8px 14px; }
  .ca-dest { grid-template-columns: minmax(0, 1fr) auto 88px; }
}

/* ── Celular ──────────────────────────────────────────────────────────── */

@media (max-width: 700px) {
  /* Duas colunas, e o bloco que ocupa a largura toda vem SEMPRE por último de
     cada fileira. Foi assim que a linha do Estoque e a do Follow-up quebraram
     em 04 e 05/09: um bloco largo no meio empurra o resto da fileira. */
  .ca-linha { grid-template-columns: 1fr auto; gap: 8px 12px; align-items: center; }
  .ca-quem    { grid-column: 1 / -1; }
  .ca-numeros { grid-column: 1; align-items: flex-start; text-align: left; }
  .ca-estado  { grid-column: 2; }

  .ca-dest { grid-template-columns: 1fr auto; }
  .ca-dest-quem { grid-column: 1 / -1; }
  .ca-dest form { grid-column: 2; }
  .ca-dest .btn { width: auto; }

  .ca-alvo { grid-template-columns: 1fr; }
  .ca-alvo-conta { justify-content: flex-start; }
  .ca-linha-campos .campo { flex: 1 1 100%; }
  .ca-pragas { grid-template-columns: 1fr; }
}


/* ══════════════════════════════════════════════════════════════════════════
   CONFIGURAÇÕES — grupo Catálogo (sessão 93)
   ══════════════════════════════════════════════════════════════════════════
   A tela reúne o que no Streamlit eram cinco abas. O vocabulário aqui é
   pequeno de propósito: quase tudo reusa `.adm-cartao`, `.cl-bloco`,
   `.cl-item`, `.campo` e `.hi-abas`, que já existem. O que nasce novo é só o
   que esta tela tem e as outras não — a linha de praga com o preço na ponta,
   a linha de ajuste percentual e os selos do que falta preencher. */

.cf-painel { margin-bottom: 14px; }

/* Mesmo comportamento dos cartões do Estoque: número que leva a algum lugar
   reage ao mouse, número zerado apaga e não promete clique. */
.cf-cartao {
  display: block;
  color: inherit;
  text-decoration: none;
  transition: border-color .15s ease, transform .15s ease;
}
a.cf-cartao:hover { border-color: var(--borda-forte); transform: translateY(-1px); }
a.cf-cartao:focus-visible { outline: 2px solid var(--azul); outline-offset: 1px; }
.cf-cartao.tem-aviso { border-color: var(--laranja-borda); }
.cf-cartao.tem-aviso .adm-kpi-valor { color: var(--laranja-txt); }
.cf-cartao.vazio { opacity: .55; }

/* ── A lista de pragas, que também é o formulário de preços ─────────────── */

.cf-lista-form { display: flex; flex-direction: column; gap: 12px; }
.cf-tabela { display: flex; flex-direction: column; gap: 4px; padding: 10px; }

.cf-linha {
  display: grid;
  grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr) 150px;
  align-items: center;
  gap: 10px;
  padding: 7px 9px;
  border-radius: 8px;
}
.cf-linha:nth-child(odd) { background: var(--fundo); }

.cf-cabeca {
  padding-bottom: 4px;
  font-size: 11px; font-weight: 700; letter-spacing: .6px;
  text-transform: uppercase; color: var(--texto-fraco);
  background: none;
}
.cf-cabeca span:last-child { text-align: right; }

.cf-nome {
  min-width: 0;
  font-size: 13.5px; font-weight: 600;
  color: var(--texto); text-decoration: none;
}
.cf-nome:hover { color: var(--azul); text-decoration: underline; }
.cf-nome small {
  display: block; margin-top: 1px;
  font-size: 11.5px; font-weight: 400; color: var(--texto-fraco);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* Os selos dizem o que FALTA, não o que existe: uma praga bem configurada não
   precisa de cinco etiquetas verdes ocupando a linha. */
.cf-selos { display: flex; flex-wrap: wrap; gap: 4px; }
.cf-selo {
  padding: 2px 7px;
  border: 1px solid var(--laranja-borda); border-radius: 999px;
  background: var(--laranja-fundo); color: var(--laranja-txt);
  font-size: 10.5px; font-weight: 700; white-space: nowrap;
}
.cf-selo.ok   { border-color: var(--verde-borda); background: var(--verde-fundo); color: var(--verde-txt); }
.cf-selo.info { border-color: var(--azul-borda);  background: var(--azul-fundo);  color: var(--azul); }

.cf-preco input {
  width: 100%;
  min-height: 38px;
  padding: 0 10px;
  border: 1px solid var(--borda); border-radius: var(--raio);
  background: var(--superficie); color: var(--texto);
  font: inherit; font-size: 16px; text-align: right;
  font-variant-numeric: tabular-nums;
}
.cf-preco input:focus { outline: none; border-color: var(--azul); }

/* ── A linha de ajuste percentual ───────────────────────────────────────── */

.cf-pct {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 120px;
  align-items: center;
  gap: 10px;
}
.cf-pct-rotulo {
  font-size: 13px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.cf-pct-valor, .cf-pct-nome { display: flex; align-items: center; gap: 6px; }
.cf-pct-valor input, .cf-pct-nome input {
  width: 100%; min-width: 0;
  min-height: 38px;
  padding: 0 10px;
  border: 1px solid var(--borda); border-radius: var(--raio);
  background: var(--superficie); color: var(--texto);
  font: inherit; font-size: 16px;
}
.cf-pct-valor input { text-align: right; font-variant-numeric: tabular-nums; }
.cf-pct-valor input:focus, .cf-pct-nome input:focus { outline: none; border-color: var(--azul); }
.cf-pct-valor b { font-size: 13px; color: var(--texto-fraco); }

/* ── Ações e botões ─────────────────────────────────────────────────────── */

.cf-acoes {
  display: flex; align-items: center; justify-content: space-between;
  flex-wrap: wrap; gap: 12px;
  margin-top: 12px;
}
.cf-acoes .cl-item-nota { flex: 1 1 320px; }

/* O `.btn` do flowpest.css nasce com `margin-top: 20px`, escrito para quando
   ele fecha um formulário de coluna. Dentro de fileira, essa margem empurra o
   botão para baixo do alinhamento. Zerar é obrigatório toda vez que ele entra
   numa linha — já foi esquecido três vezes (s85, s86, s90). */
/* O botão de ação padrão do painel: desfaz as duas coisas que o `.btn` do
   flowpest.css traz para ser o fim de um formulário empilhado (`margin-top` e
   `width: 100%`) e fixa a altura de toque.
   `.mc-btn` (Minha conta) entrou nesta MESMA regra na sessão 95 em vez de
   ganhar uma cópia: o prefixo `cf-` é herança de a regra ter nascido nas
   Configurações, e duas regras idênticas seriam dois lugares para divergir. */
.cf-btn-salvar, .cf-btn-add, .cf-btn-modo, .cf-btn-perigo, .mc-btn, .pi-grade-baixar {
  margin-top: 0;
  min-height: 42px;
  padding: 0 20px;
  display: inline-flex; align-items: center; justify-content: center;
  width: auto;
}
.cf-btn-perigo { background: var(--vermelho-txt); border-color: var(--vermelho-txt); }

.cf-modo { display: flex; flex-direction: column; gap: 10px; align-items: flex-start; }

.cf-explica { margin: 0 0 12px; }

.cf-form-add { display: flex; flex-direction: column; gap: 10px; align-items: flex-start; }
.cf-form-linha { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 8px; }
.cf-form-linha .campo { flex: 1 1 200px; margin: 0; }

.cf-gerenciar { margin-top: 12px; }

/* ── Os blocos do certificado (sessão 97) ───────────────────────────────
   Uma fileira por bloco: a caixa de "aparece", o texto quando houver, o
   botão de salvar, e as setas de ordem à direita.

   Os botões zeram `margin-top` e `width` do `.btn` do flowpest.css pelo
   motivo de sempre: ele nasce para ser o FIM de um formulário empilhado. */
.cf-bloco-cert {
  display: flex; align-items: flex-start; gap: 10px;
  padding: 10px 0;
  border-top: 1px solid var(--borda);
}
.cf-bloco-cert:first-of-type { border-top: 0; }

.cf-bloco-linha {
  flex: 1 1 auto; min-width: 0;
  display: flex; flex-direction: column; align-items: flex-start; gap: 8px;
}
.cf-bloco-linha .campo { width: 100%; margin: 0; }

/* `.cl-escolha` nasce com `flex: 1 1 260px` para dividir uma FILEIRA com as
   irmãs. Aqui o contêiner é uma COLUNA, e num contêiner em coluna o
   `flex-basis` é ALTURA: a caixa de "aparece" virava um retângulo de 260px de
   altura com uma linha de texto dentro.

   É a mesma armadilha do `flex-basis` já anotada (a quarta da lista de CSS
   reusado), que até hoje só tinha aparecido no celular. Ela não depende da
   largura da tela: depende da DIREÇÃO do contêiner. */
.cf-bloco-linha .cl-escolha { flex: 0 0 auto; width: 100%; }

/* O botão que abre o texto dos três blocos editáveis. Nascia como as outras
   gavetas, uma pílula cinza escrita "Texto", e passava despercebido: o dono
   não o achou (24/09). É o único lugar da tela em que alguém digita, então
   ganha a cor de ação e uma seta que aponta para o lado fechado e para baixo
   aberto. A seta é borda girada, e não caractere, para não depender da fonte. */
.cf-texto-gaveta { width: 100%; }
.cf-texto-gaveta > summary {
  gap: 9px;
  border-color: color-mix(in srgb, var(--azul) 60%, transparent);
  color: var(--azul);
}
.cf-texto-gaveta > summary:hover {
  border-color: var(--azul);
  color: var(--azul);
  background: var(--azul-fundo);
}
.cf-texto-gaveta > summary::before {
  content: "";
  width: 6px; height: 6px;
  border-right: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  transform: rotate(-45deg);
  transition: transform .15s ease;
}
.cf-texto-gaveta[open] > summary::before { transform: rotate(45deg); }
.cf-texto-gaveta > .campo { margin-top: 10px; }

/* Proposta (30/09): de onde vem o conteúdo de cada bloco, numa linha embaixo
   do nome. Quem configura precisa saber que "Empresa responsável" sai de Minha
   conta, senão procura onde digitar. */
.cf-bloco-descricao {
  display: block; margin-top: 2px;
  font-size: 12px; font-weight: 400; line-height: 1.4;
  color: var(--texto-fraco);
}
.cf-texto-gaveta > .cl-item-nota { margin: 10px 0 0; }
.cf-texto-gaveta > .cl-form-grade { margin-top: 10px; }

/* O bloco que existe no modelo e ainda não desenha nada (as fotos, etapa 5).
   Borda tracejada no lugar da caixa de marcar: está na lista, na ordem certa,
   e não é uma escolha ainda. */
.cf-bloco-a-caminho {
  margin: 0; padding: 10px 12px;
  width: 100%;
  display: flex; flex-direction: column; gap: 3px;
  border: 1px dashed var(--borda-forte);
  border-radius: 10px;
}
.cf-bloco-a-caminho .cl-item-nota { margin: 0; }

/* Sempre DUAS vagas, com o "subir" na esquerda e o "descer" na direita: o
   primeiro bloco não tem "subir" e o último não tem "descer", e com a coluna
   encolhendo a caixa deles ficava 44px mais larga que a das outras (medido
   em 30/09: 1012 contra 968). */
.cf-bloco-setas { display: grid; grid-template-columns: 38px 38px; gap: 6px; flex: 0 0 auto; }
.cf-bloco-setas .cf-seta-sobe { grid-column: 1; }
.cf-bloco-setas .cf-seta-desce { grid-column: 2; }
.cf-bloco-setas .btn {
  margin-top: 0;
  width: auto; min-width: 38px;
  padding: 0 10px;
}

/* No celular, a coluna das setas tomava a largura da linha INTEIRA, embora as
   setas ocupem só o topo: o texto aberto ficava numa caixa de 185 px (medido
   em tela de 375 px, 24/09). Lá elas saem da coluna e vão para o canto de
   cima, e só a caixa de "aparece" deixa o espaço delas. No notebook a caixa
   já tinha 968 px, e nada muda. */
@media (max-width: 720px) {
  .cf-bloco-cert { position: relative; }
  .cf-bloco-setas { position: absolute; top: 10px; right: 0; }
  .cf-bloco-linha .cl-escolha,
  .cf-bloco-a-caminho { width: calc(100% - 92px); }
}

/* ── Adicionar praga ────────────────────────────────────────────────────── */

.cf-adicionar { margin-top: 14px; }
.cf-adicionar summary { cursor: pointer; }
.cf-busca-preset { margin: 0; }

.cf-preset {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(210px, 1fr));
  gap: 6px;
  max-height: 260px; overflow-y: auto;
  padding: 8px;
  border: 1px solid var(--borda); border-radius: var(--raio);
  background: var(--fundo);
}
.cf-preset-item {
  display: flex; align-items: center; gap: 8px;
  padding: 5px 7px; border-radius: 6px;
  font-size: 13px; cursor: pointer;
}
.cf-preset-item:hover { background: var(--superficie); }
.cf-preset-item input { width: 16px; height: 16px; accent-color: var(--azul); flex: none; }
.cf-livre { max-width: 420px; }

/* ── A ficha de uma praga ───────────────────────────────────────────────── */

.cf-ficha { display: flex; flex-direction: column; gap: 12px; }
.cf-ficha code {
  padding: 1px 5px; border-radius: 4px;
  background: var(--fundo); font-size: 11.5px;
}

.cf-preco-selo {
  padding: 5px 12px;
  border: 1px solid var(--verde-borda); border-radius: 999px;
  background: var(--verde-fundo); color: var(--verde-txt);
  font-size: 13px; font-weight: 700; white-space: nowrap;
}
.cf-preco-selo.sem {
  border-color: var(--laranja-borda); background: var(--laranja-fundo);
  color: var(--laranja-txt);
}

/* O interruptor usa a mesma caixa das escolhas, mas ocupa a largura toda: ele
   não disputa lugar com um irmão, é uma decisão sozinha. */
.cf-interruptor { flex: 1 1 100%; }

.cf-alerta {
  padding: 8px 10px;
  border: 1px solid var(--laranja-borda); border-radius: var(--raio);
  background: var(--laranja-fundo); color: var(--laranja-txt);
}
.cf-alerta b { color: inherit; }

.cf-usos .cl-item-topo { justify-content: space-between; }
.cf-excluir summary { cursor: pointer; color: var(--vermelho-txt); }
.cf-riscado { text-decoration: line-through; color: var(--texto-fraco); }

.cf-item-remover { flex-direction: row; align-items: center; justify-content: space-between; gap: 10px; }
.cf-item-remover form { margin: 0; }
.cf-servico { flex-direction: row; align-items: flex-end; gap: 10px; flex-wrap: wrap; }
.cf-servico form { margin: 0; }
.cf-servico .cf-form-linha { flex: 1 1 260px; }

/* ── Telas médias ───────────────────────────────────────────────────────── */
@media (max-width: 1100px) {
  /* Os selos do que falta são o primeiro a sair: eles repetem, em etiqueta, o
     que os cartões do topo já contam em número. O preço NÃO sai — ele é o
     motivo de a lista ser um formulário. */
  .cf-linha { grid-template-columns: minmax(0, 1fr) 130px; }
  .cf-selos { display: none; }
  .cf-cabeca span:nth-child(2) { display: none; }
}

/* ── Celular ────────────────────────────────────────────────────────────── */
@media (max-width: 720px) {
  /* Nome em cima, preço embaixo à direita: duas colunas em 375px dariam 160px
     para o nome da praga, e "Traça dos Alimentos (Plodia)" não cabe. */
  .cf-linha { grid-template-columns: 1fr; gap: 6px; padding: 9px; }
  .cf-linha:nth-child(odd) { background: var(--fundo); }
  .cf-cabeca { display: none; }
  .cf-preco { display: flex; justify-content: flex-end; }
  .cf-preco input { max-width: 160px; }
  .cf-selos { display: flex; }

  .cf-pct { grid-template-columns: 1fr; gap: 4px; }
  .cf-pct-rotulo { white-space: normal; }

  .cf-acoes { flex-direction: column; align-items: stretch; }
  .cf-acoes .btn { width: 100%; }
  /* `flex: 1 1 320px` foi escrito para uma FILEIRA, onde 320px é largura. Na
     coluna do celular o mesmo 320px vira ALTURA, e a nota abria um buraco de
     quase 300px entre o texto e o botão, que saía da tela. Medido em 15/09:
     `.cf-acoes` tinha 374px de altura para 82px de conteúdo. Mesma família da
     armadilha do `margin-top` do `.btn`: valor escrito para um eixo vazando
     no outro. */
  .cf-acoes .cl-item-nota { flex: 0 1 auto; }

  .cf-servico { flex-direction: column; align-items: stretch; }
  .cf-preset { grid-template-columns: 1fr; max-height: 220px; }
}


/* ── Configurações: os dois níveis de aba (sessão 94) ──────────────────────
   Dez abas numa fileira só não cabem. Os GRUPOS ficam acima, com peso de
   segmento (fundo, não sublinhado), e as abas do grupo ativo continuam sendo
   a fileira sublinhada de sempre — a mesma que Estoque e Histórico usam. */

.cf-grupos {
  display: flex; gap: 4px;
  margin-bottom: 10px;
  padding: 3px;
  border: 1px solid var(--borda); border-radius: 10px;
  background: var(--fundo);
  /* Rola quando não cabe, em vez de cortar: em 375px os três títulos somam
     mais que a largura do contêiner. Mesma decisão das abas de Campanhas. */
  overflow-x: auto; scrollbar-width: thin;
}
.cf-grupo {
  flex: 0 0 auto; white-space: nowrap;
  padding: 7px 14px; border-radius: 7px;
  color: var(--texto-fraco); text-decoration: none;
  font-size: 13px; font-weight: 600;
}
.cf-grupo:hover { color: var(--texto); }
.cf-grupo.ativo {
  background: var(--superficie); color: var(--texto);
  box-shadow: 0 1px 2px rgba(0, 0, 0, .18);
}

/* ── Técnicos ───────────────────────────────────────────────────────────── */

.cf-link input { font-family: ui-monospace, "Cascadia Code", Consolas, monospace; font-size: 13px; }

.cf-tecnico { padding: 0; }
.cf-tecnico > summary {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  padding: 10px 11px;
  cursor: pointer; font-size: 13.5px;
}
.cf-tecnico[open] > summary { border-bottom: 1px solid var(--borda); }
.cf-tecnico > form, .cf-tecnico > p, .cf-tecnico > div { margin: 10px 11px; }
.cf-tecnico-meta { font-size: 12px; color: var(--texto-fraco); }
.cf-codigo-pronto { align-items: center; }
.cf-codigo-pronto .cl-item-nota { flex: 1 1 240px; margin: 0; }

/* ── Atendimento ────────────────────────────────────────────────────────── */

.cf-sub { font-size: 12px; text-transform: uppercase; letter-spacing: .5px; color: var(--texto-fraco); }

.cf-dias { display: flex; flex-wrap: wrap; gap: 5px; }
.cf-dia {
  display: flex; align-items: center; gap: 6px;
  padding: 7px 10px;
  border: 1px solid var(--borda); border-radius: 8px;
  background: var(--superficie);
  font-size: 12.5px; cursor: pointer;
}
.cf-dia input { width: 15px; height: 15px; accent-color: var(--azul); flex: none; }
.cf-dia:has(input:checked) { border-color: var(--azul); background: var(--azul-fundo); }

/* ── Financeiro ─────────────────────────────────────────────────────────── */

.cf-formas {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
  gap: 6px;
}
.cf-forma {
  display: flex; align-items: flex-start; gap: 8px;
  padding: 9px 11px;
  border: 1px solid var(--borda); border-radius: var(--raio);
  background: var(--superficie);
  cursor: pointer;
}
.cf-forma input { margin-top: 2px; width: 16px; height: 16px; accent-color: var(--azul); flex: none; }
.cf-forma b { display: block; font-size: 13px; }
.cf-forma small { display: block; margin-top: 1px; font-size: 11px; color: var(--texto-fraco); }
.cf-forma:has(input:checked) { border-color: var(--azul); background: var(--azul-fundo); }

.cf-politicas { flex-direction: column; }

/* ── Follow-up ──────────────────────────────────────────────────────────── */

.cf-cenarios { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 12px; }
.cf-cenario {
  padding: 7px 13px;
  border: 1px solid var(--borda); border-radius: 999px;
  background: var(--superficie); color: var(--texto-fraco);
  font-size: 12.5px; font-weight: 600; text-decoration: none;
}
.cf-cenario:hover { border-color: var(--borda-forte); color: var(--texto); }
.cf-cenario.ativo { border-color: var(--azul); background: var(--azul-fundo); color: var(--azul); }

.cf-info {
  padding: 8px 10px;
  border: 1px solid var(--azul-borda); border-radius: var(--raio);
  background: var(--azul-fundo); color: var(--azul);
}
.cf-info b { color: inherit; }

.cf-tentativa { margin-bottom: 12px; }
.cf-tentativa-topo {
  display: flex; align-items: center; flex-wrap: wrap; gap: 12px;
}
.cf-tentativa-topo .cl-bloco-titulo { margin-right: auto; }
.cf-tentativa-quando { display: flex; align-items: center; gap: 6px; }
.cf-tentativa-quando .campo { margin: 0; }
.cf-tentativa-quando input { width: 72px; text-align: right; }
.cf-tentativa-quando select { min-height: 42px; }
.cf-tentativa-ativo { flex: 0 0 auto; padding: 8px 12px; }
.cf-tentativa-extras {
  display: flex; align-items: center; justify-content: space-between;
  flex-wrap: wrap; gap: 10px;
  padding-top: 10px; border-top: 1px solid var(--borda);
}
.cf-tentativa-extras form { margin: 0; }

/* ── Proposta ───────────────────────────────────────────────────────────── */

.cf-logo {
  max-height: 90px; max-width: 220px;
  object-fit: contain;
  padding: 6px;
  border: 1px solid var(--borda); border-radius: var(--raio);
  /* Fundo CLARO mesmo no tema escuro: logo de dedetizadora costuma ser escura
     com fundo transparente, e num cartão escuro ela some. É a mesma cor que o
     PDF vai ter. */
  background: #fff;
}
/* O seletor nativo de cor estica na largura toda do campo e vira uma barra
   escura de 400px que não parece um seletor. 64px é o tamanho em que ele se
   lê como amostra de cor. */
/* `.campo input` vale `width: 100%` e tem especificidade MAIOR que uma
   classe sozinha: `.cf-cor` perdia e o seletor continuava com 306px.
   Medido em 15/09 percorrendo as regras que casam com o elemento. */
.campo input.cf-cor { width: 64px; min-height: 42px; padding: 3px; cursor: pointer; }
.cf-grupo-texto { margin-bottom: 4px; }
.cf-grupo-texto > summary { cursor: pointer; padding: 6px 0; }

code {
  padding: 1px 5px; border-radius: 4px;
  background: var(--fundo);
  font-size: 11.5px;
}

/* ── Celular ────────────────────────────────────────────────────────────── */
@media (max-width: 720px) {
  .cf-tentativa-topo { flex-direction: column; align-items: stretch; gap: 8px; }
  .cf-tentativa-topo .cl-bloco-titulo { margin-right: 0; }
  .cf-tentativa-quando input { width: 100%; }
  .cf-tentativa-extras { flex-direction: column; align-items: flex-start; }
  .cf-formas { grid-template-columns: 1fr; }
  .cf-codigo-pronto { flex-direction: column; align-items: stretch; }
  .cf-logo { max-width: 100%; }
}

/* ── `<details>` que reusa cartão do painel (sessão 94) ─────────────────────
   `display: flex` num `<details>` DESLIGA o fechar dele: o navegador esconde o
   conteúdo do estado fechado com o `display: block` padrão, e trocado por flex
   o conteúdo aparece mesmo com `open === false`.

   Medido em 15/09 no navegador, com `getComputedStyle`: os técnicos abriam os
   três ao mesmo tempo (`.cl-item` é flex), e no Catálogo — que já estava NO AR
   desde 14/09 — o bloco "Adicionar praga" e, pior, o bloco "Excluir do
   catálogo" (com a caixa de confirmação e o botão vermelho) apareciam abertos
   sem ninguém ter clicado, porque `.cl-bloco` também é flex.

   A cura é só para o estado FECHADO: aberto, o flex é exatamente o que se quer.
   Vale para qualquer `<details>` do painel que reuse esses cartões, hoje e
   depois — é a mesma família da armadilha do `margin-top` do `.btn`. */
details.cl-bloco:not([open]),
details.cl-item:not([open]),
details.adm-cartao:not([open]) { display: block; }

/* A ficha de um técnico é um `<details>` com cara de item de lista. */
.cf-tecnico[open] { display: flex; flex-direction: column; }

/* A linha de uma faixa de duração: rótulo, horas e o remover, juntos.
   A primeira versão desenhava as faixas DUAS vezes (uma lista para digitar as
   horas, outra para remover), porque HTML não aceita formulário dentro de
   formulário. Quem resolve é o atributo `form=` no campo e no botão. */
.cf-faixa {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 110px 76px;
  align-items: center;
  gap: 10px;
}
.cf-faixa .cl-link-perigo, .cf-faixa .cf-fixa { justify-self: end; }
.cf-fixa { font-size: 11.5px; color: var(--texto-fraco); }
/* Os formulários vazios que só existem para o `form=` apontar não ocupam
   lugar na grade. */
.cf-faixa > form { display: none; }

@media (max-width: 720px) {
  .cf-faixa { grid-template-columns: minmax(0, 1fr) 96px 72px; gap: 6px; }
}

/* ── Pré-visualização do cabeçalho da proposta (sessão 94) ─────────────────
   Estava no Streamlit e não tinha vindo junto. Mostra cor e slogan sem custar
   a geração do PDF inteiro. Fundo CLARO sempre, mesmo no tema escuro: é papel
   que se está imitando, e a cor escolhida foi escolhida contra branco. */
.cf-previa {
  border: 1px solid var(--borda); border-radius: var(--raio);
  background: #fff; color: #222;
  padding: 14px;
}
.cf-previa-topo { display: flex; align-items: center; gap: 14px; }
.cf-previa-logo {
  width: 84px; height: 52px;
  object-fit: contain;
  display: flex; align-items: center; justify-content: center;
}
.cf-previa-logo.vazia {
  border: 1px dashed #ccc; border-radius: 4px;
  color: #bbb; font-size: 11px; letter-spacing: 1px;
}
.cf-previa-titulo { display: block; font-size: 17px; font-weight: 800; color: #222; }
.cf-previa-slogan { display: block; margin-top: 2px; font-size: 11.5px; color: #666; font-style: italic; }
.cf-previa-faixa {
  margin-top: 12px; padding: 5px 9px; border-radius: 4px;
  color: #fff; font-size: 12px; font-weight: 700;
}


/* ══════════════════════════════════════════════════════════════════════════
   MENSAGENS — a caixa de saída do WhatsApp (sessão 95)
   ══════════════════════════════════════════════════════════════════════════
   Espaço de nomes próprio (`mg-`) em vez de reusar o `fu-` do Follow-up. As
   duas telas mostram o mesmo tipo de coisa (o texto que vai para o cliente),
   mas o `.fu-texto` mora dentro de um `.fu-linha` em grade e tem regra de
   celular presa a ela. Emprestar aquela classe para cá é o erro que já pegou
   três vezes neste projeto: componente que parecia genérico e carregava o
   layout do vizinho junto. */

.mg-topo { display: flex; gap: 16px; align-items: flex-start; flex-wrap: wrap; }
/* `min-width: 0` e não `flex-basis` em pixels: a coluna do celular transforma
   base em ALTURA, e foi assim que a caixa de ações da Configurações ficou com
   374px de altura para 82px de conteúdo (medido em 15/09). Aqui o texto
   simplesmente ocupa a sobra, e no estreito a fileira quebra sozinha. */
.mg-topo-texto { flex: 1 1 0; min-width: 0; }
.mg-acoes { display: flex; gap: 8px; flex-wrap: wrap; }

/* `.btn` vem do flowpest.css desenhado para ser o FIM de um formulário
   empilhado, e traz DUAS coisas que só fazem sentido lá:

     margin-top  -> dentro de uma fileira vira um degrau (sessões 85, 86 e 90);
     width: 100% -> dentro de uma fileira ele engole a linha inteira.

   O segundo foi medido aqui em 16/09, percorrendo as regras que casam com o
   elemento em vez de ler o arquivo: o botão "Copiar" estava com 1064px de
   largura num cartão de 1064px. Os dois são zerados juntos, e no celular o
   `width: 100%` volta de propósito (lá o dedo agradece a área grande). */
.mg-btn { margin-top: 0; width: auto; }

.mg-lista { display: flex; flex-direction: column; gap: 10px; }
.mg-item { padding: 13px 15px; }
/* A mensagem nova se distingue por uma faixa na lateral, e não por fundo
   colorido: o cartão inteiro tinto brigaria com o `<pre>` que vem dentro. */
.mg-item.nova { border-left: 3px solid var(--ouro); }

.mg-cabeca {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 10px; flex-wrap: wrap;
  margin-bottom: 9px;
}
.mg-para {
  display: flex; align-items: center; gap: 7px; flex-wrap: wrap;
  font-size: 13px; font-weight: 700;
}
.mg-quando { font-size: 12px; color: var(--texto-fraco); white-space: nowrap; }

.mg-selo-novo, .mg-selo-tipo {
  padding: 2px 7px; border-radius: 999px;
  font-size: 10.5px; font-weight: 700; white-space: nowrap;
  text-transform: lowercase;
}
.mg-selo-novo {
  border: 1px solid var(--verde-borda);
  background: var(--verde-fundo); color: var(--verde-txt);
}
.mg-selo-tipo {
  border: 1px solid var(--borda);
  background: var(--fundo); color: var(--texto-fraco);
}

.mg-texto {
  margin: 0;
  padding: 11px 13px;
  border: 1px solid var(--borda); border-radius: 9px;
  background: var(--fundo);
  color: inherit;
  font-family: inherit;          /* não é código: é uma mensagem de WhatsApp */
  font-size: 13px; line-height: 1.55;
  /* `pre-wrap`: as quebras de linha fazem parte da mensagem, e colapsá-las
     mostraria um parágrafo que o cliente nunca vai receber. `break-word` para
     o link longo não empurrar a página para o lado no celular. */
  white-space: pre-wrap;
  overflow-wrap: break-word;
}

.mg-pe { display: flex; justify-content: flex-end; margin-top: 9px; }

.mg-perigo { margin-top: 14px; }

@media (max-width: 720px) {
  /* A data desce para a linha de baixo em vez de espremer o número do
     telefone contra ela. */
  .mg-quando { flex-basis: 100%; }
  .mg-pe { justify-content: stretch; }
  .mg-pe .mg-btn { width: 100%; }
}


/* ══════════════════════════════════════════════════════════════════════════
   MINHA CONTA — a ficha da empresa, o responsável, a integração e a senha
   ══════════════════════════════════════════════════════════════════════════
   A tela reusa `.cl-form-grade` (a grade que se reorganiza sozinha, de
   Clientes e Configurações) e o `.campo` do flowpest.css. O que nasce aqui são
   só as duas coisas que a grade não resolve. */

/* O campo que ocupa a fileira inteira: razão social, e-mail, rua. Nome de
   empresa e endereço não cabem em 210px, e deixá-los do tamanho do CEP faz o
   gestor digitar às cegas. `1 / -1` é da PRIMEIRA à ÚLTIMA coluna, qualquer
   que seja o número delas — a grade é `auto-fit`, então esse número muda com a
   largura da tela. */
.mc-largo { grid-column: 1 / -1; }

/* "Endereço" é um subtítulo DENTRO do mesmo formulário, e não outro cartão:
   separa sem sugerir que se salva em separado (o botão é um só). */
.mc-subtitulo { margin-top: 18px; }

/* ── Licenças e assinatura (sessão 97) ──────────────────────────────────
   Cada licença é um formulário INTEIRO, com salvar e remover próprios: a
   quantidade varia, e um botão só para todas faria uma linha mal digitada
   impedir de salvar as outras.

   O traço separa uma da outra sem cartão dentro de cartão, que é o que o
   painel evita desde a s85. */
.mc-licenca {
  padding: 12px 0;
  border-top: 1px solid var(--borda);
}
.mc-licenca:first-of-type { border-top: 0; }
.mc-licenca.nova { border-top: 1px dashed var(--borda); }

/* A fileira dos dois botões. `.btn` do flowpest.css nasce com `margin-top:
   20px` e `width: 100%` para ser o FIM de um formulário empilhado; dentro de
   uma fileira, os dois viram um botão gigante por linha. É a armadilha que já
   pegou quatro vezes (s85, s86, s90, s95), e por isso ela é zerada aqui. */
.mc-licenca-acoes {
  display: flex; flex-wrap: wrap; gap: 8px;
  margin-top: 10px;
}
.mc-licenca-acoes .btn {
  margin-top: 0;
  width: auto;
  min-height: 38px;
  padding: 0 16px;
}
.mc-licenca-acoes .btn.perigo {
  color: var(--vermelho-txt);
  border-color: var(--vermelho-borda);
}

/* A assinatura tem proporção de rabisco escaneado (larga e baixa). O fundo
   claro é fixo de propósito: assinatura é traço preto sobre branco, e no tema
   escuro ela sumiria contra o fundo do cartão. */
/* A logo na ficha da empresa. Veste a MESMA caixa da assinatura (traço sobre
   fundo claro), mas cabe um pouco mais alta: logo é desenho, assinatura é
   rabisco. */
.mc-logo {
  display: block;
  max-width: 220px; max-height: 90px;
  margin: 10px 0;
  padding: 8px;
  background: #fff;
  border: 1px solid var(--borda); border-radius: var(--raio);
}

.mc-assinatura {
  display: block;
  max-width: 280px; max-height: 110px;
  margin: 10px 0;
  padding: 8px;
  background: #fff;
  border: 1px solid var(--borda);
  border-radius: var(--raio);
}

/* ── Porta-iscas do imóvel (09/10/2026) ─────────────────────────────────── */
.pi-pagina { display: flex; flex-direction: column; gap: 12px; margin-top: 10px; }
.pi-contagem {
  margin: 0;
  display: flex; flex-wrap: wrap; align-items: center; gap: 6px 14px;
  font-size: 13px;
}
.pi-tipo-conta { display: inline-flex; align-items: center; gap: 6px; color: var(--texto-fraco); }
/* A bolinha com a cor do tipo, a mesma do mapa da empresa (verde, azul,
   laranja na Couto). A cor vem do banco já conferida (#RRGGBB). */
.pi-bolinha {
  display: inline-block; flex: none;
  width: 12px; height: 12px; border-radius: 50%;
  background: var(--cor, #888);
  box-shadow: 0 0 0 1px rgba(0, 0, 0, .15);
}
.pi-mapa { display: block; align-self: flex-start; max-width: 100%; }
.pi-mapa img {
  display: block;
  max-width: 100%; max-height: 360px;
  border: 1px solid var(--borda); border-radius: 8px;
  background: #fff;
}
.pi-revisoes { margin: 10px 0 0; padding-left: 18px; font-size: 12.5px; line-height: 1.7; }

.pi-setor { display: flex; flex-direction: column; gap: 6px; }
.pi-setor + .pi-setor { margin-top: 6px; }
.pi-setor-nome {
  margin: 0;
  display: flex; align-items: center; gap: 8px;
  font-size: 13px; font-weight: 800;
}
/* Grade e não lista: com 80 pontos, uma faixa da largura da tela por ponto
   vira uma rolagem sem fim no computador (medido: 47 faixas de 1060px). Em
   cartões, cabem três ou quatro por linha; no celular, um. */
.pi-lista {
  margin: 0; padding: 0; list-style: none;
  display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  gap: 6px; align-items: start;
}
.pi-ponto {
  border: 1px solid var(--borda); border-radius: 10px;
  padding: 8px 11px;
  background: var(--superficie);
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 6px 10px;
}
.pi-ponto-topo { display: flex; align-items: center; gap: 8px; min-width: 0; }
.pi-numero { font-variant-numeric: tabular-nums; font-size: 13.5px; }
.pi-tipo { font-size: 12.5px; color: var(--texto-fraco); }
/* A gaveta aberta ocupa a linha inteira do ponto, embaixo dos dados. */
.pi-ponto .cl-imovel-acoes { justify-content: flex-end; }
.pi-ponto details[open] { flex-basis: 100%; }

.pi-historico { margin: 0; padding: 0; list-style: none; display: flex; flex-direction: column; }
.pi-historico li {
  display: flex; flex-wrap: wrap; gap: 2px 10px;
  padding: 8px 0;
  border-top: 1px solid var(--borda);
  font-size: 12.5px; line-height: 1.5;
}
.pi-historico li:first-child { border-top: 0; }
.pi-hist-quando { color: var(--texto-fraco); font-variant-numeric: tabular-nums; }
.pi-hist-acao { font-weight: 700; }
.pi-hist-motivo { flex-basis: 100%; color: var(--texto-fraco); }
.pi-hist-autor { color: var(--texto-fraco); display: inline-flex; align-items: center; gap: 6px; }

/* No celular, as gavetas viram alvos de 44px (a regra do toque). */
@media (max-width: 720px) {
  .pi-pagina .cl-acao > summary { min-height: 44px; padding: 0 16px; }
  .cl-acao-link { min-height: 44px; padding: 0 16px; }
}

/* Os porta-iscas na ficha da OS do Histórico. */
.pi-siglas-resumo {
  margin: 0; padding: 0; list-style: none;
  display: flex; flex-wrap: wrap; gap: 6px 14px;
  font-size: 12.5px;
}
.pi-os-lista { margin: 4px 0 10px; padding: 0; list-style: none; display: flex; flex-direction: column; }
.pi-os-lista li {
  display: flex; flex-wrap: wrap; align-items: center; gap: 4px 10px;
  padding: 6px 0; border-top: 1px solid var(--borda);
  font-size: 12.5px;
}
.pi-os-lista li:first-child { border-top: 0; }
.pi-os-siglas { margin-left: auto; font-weight: 700; }
.pi-os-lista li.vazio .pi-os-siglas { font-weight: 500; color: var(--texto-fraco); }
/* O ponto com roedor naquela visita (12/10/2026): o mesmo vermelho da grade. */
/* `.cl-nota b` pinta o negrito da nota com a cor do texto e é mais
   específica que `.pi-os-ativ` sozinha (medido: saía sem o vermelho). */
.pi-os-lista li.ativ .pi-os-siglas, .cl-nota b.pi-os-ativ { color: var(--vermelho-txt); }

/* Alterar OS: as siglas de cada porta-isca. */
.pi-alterar { margin: 10px 0 0; padding: 0; list-style: none; display: flex; flex-direction: column; }
.pi-alterar li {
  display: grid; grid-template-columns: minmax(150px, 1fr) minmax(0, 1.2fr) minmax(0, 1.2fr);
  align-items: end; gap: 8px 12px;
  padding: 8px 0; border-top: 1px solid var(--borda);
}
.pi-alterar li:first-child { border-top: 0; }
.pi-alterar-ponto { display: flex; flex-direction: column; gap: 2px; font-size: 12.5px; padding-bottom: 8px; }
@media (max-width: 720px) {
  .pi-alterar li { grid-template-columns: 1fr 1fr; }
  .pi-alterar-ponto { grid-column: 1 / -1; flex-direction: row; gap: 8px; padding-bottom: 0; }
}

/* Configurações > Porta-iscas: tipos e legendas. */
.pi-config-lista { margin: 0; padding: 0; list-style: none; display: flex; flex-direction: column; }
.pi-config-lista > li {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 6px 10px;
  padding: 8px 0; border-top: 1px solid var(--borda);
}
.pi-config-lista > li:first-child { border-top: 0; }
.pi-config-lista > li.desligado { opacity: .65; }
.pi-config-lista details[open] { flex-basis: 100%; }
.pi-config-linha { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 10px; font-size: 13px; min-width: 0; }
.pi-config-sigla { min-width: 52px; font-variant-numeric: tabular-nums; }
.pi-config-lista input[type=color] { min-height: 40px; padding: 2px; }
@media (max-width: 720px) {
  .pi-config-lista .cl-acao > summary { min-height: 44px; padding: 0 16px; }
}


/* ── Porta-iscas por visita (12/10/2026) ─────────────────────────────────── */
.pi-grade-barra {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
  gap: 10px; margin-top: 12px;
}
.pi-grade-opcoes { display: flex; flex-wrap: wrap; gap: 6px; }
.cl-acao-link.ativo { border-color: var(--azul-borda); background: var(--azul-fundo); color: var(--azul); }

/* A caixa rola nos dois sentidos, e por isso o cabeçalho e a coluna do ponto
   ficam presos dentro dela: com 80 pontos e 12 visitas é uma planilha, e
   planilha sem cabeçalho preso se perde na terceira tela. */
/* `position: relative` prende à caixa o texto de leitor de tela das células
   (`.cl-oculto`, que é absoluto). Sem ela, o da última coluna escapa do
   recorte e dá à PÁGINA rolagem de lado no celular (medido: 715 px em 375). */
.pi-grade-caixa {
  position: relative;
  overflow: auto; max-height: 75vh;
  margin-top: 10px;
  border: 1px solid var(--borda); border-radius: var(--raio);
}
.pi-grade {
  border-collapse: separate; border-spacing: 0;
  width: max-content; min-width: 100%;
  font-size: 12.5px; font-variant-numeric: tabular-nums;
}
.pi-grade th, .pi-grade td {
  padding: 6px 8px;
  border-bottom: 1px solid var(--borda);
  text-align: center; vertical-align: middle; white-space: nowrap;
}
.pi-grade thead th {
  position: sticky; top: 0; z-index: 2;
  background: var(--superficie);
  font-weight: 700; color: var(--texto-fraco);
}
.pi-grade thead a { color: inherit; text-decoration: underline; text-underline-offset: 2px; }
.pi-grade thead a:hover { color: var(--azul); }
.pi-grade .pi-grade-ponto {
  position: sticky; left: 0; z-index: 1;
  background: var(--superficie);
  border-right: 1px solid var(--borda);
  text-align: left; font-weight: 500;
}
.pi-grade thead .pi-grade-ponto { z-index: 3; }
.pi-grade-ponto > b { margin: 0 4px; }
.pi-grade-tipo { color: var(--texto-fraco); }
.pi-grade-ponto .vg-pill { margin-left: 4px; }
.pi-grade tr.removido .pi-grade-ponto { color: var(--texto-fraco); }

.pi-grade td b { display: block; font-weight: 700; }
.pi-grade td span { display: block; color: var(--texto-fraco); }
.pi-grade td.ativ { background: var(--vermelho-fundo); color: var(--vermelho-txt); }
.pi-grade td.ativ span { color: inherit; }
/* Sem marcação: um ponto discreto. Não existia: riscada. As duas precisam se
   distinguir nos DOIS temas; só a cor de fundo some no claro. */
.pi-grade td.vazia { background: var(--fundo); }
.pi-grade td.vazia span[aria-hidden] { font-weight: 700; }
.pi-grade td.fora {
  background: repeating-linear-gradient(135deg, transparent 0 5px, var(--borda) 5px 6px);
}
.pi-grade .pi-grade-soma { color: var(--texto-fraco); border-right: 1px solid var(--borda); }
.pi-grade .pi-grade-soma b { display: inline; color: var(--texto); }
/* Na coluna da soma, o vermelho fica no número: a célula inteira pintada
   competiria com as células das visitas. */
.pi-grade td.pi-grade-soma.ativ { background: none; }
.pi-grade td.pi-grade-soma.ativ b { color: var(--vermelho-txt); }

/* O nome do setor ocupa a linha inteira; o texto fica preso à esquerda
   quando a tabela rola de lado. */
.pi-grade-setor th { text-align: left; background: var(--fundo); color: var(--texto); font-weight: 700; }
.pi-grade-setor th > span { position: sticky; left: 8px; }

.pi-grade tfoot th, .pi-grade tfoot td {
  border-bottom: 0; border-top: 1px solid var(--borda-forte);
  font-weight: 600;
}

.pi-grade-legenda {
  margin: 0; padding: 0; list-style: none;
  display: flex; flex-wrap: wrap; gap: 6px 16px;
  font-size: 12.5px;
}
.pi-grade-legenda + .pi-grade-legenda { margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--borda); }
.pi-grade-legenda li { display: inline-flex; align-items: center; gap: 6px; }

/* No celular, a coluna presa fica só com a cor e o número (o tipo está na
   legenda), para sobrar largura para as visitas. */
@media (max-width: 720px) {
  .pi-grade-tipo { display: none; }
  .pi-grade-opcoes .cl-acao-link { min-height: 44px; }
  .pi-grade-barra .pi-grade-baixar { width: 100%; min-height: 44px; }
}
