/* ==========================================================================
   Design system do painel — white label
   Um só arquivo: tokens, layout, componentes.

   A COR DA MARCA não mora aqui: vem de /assets/marca.css, gerado a partir de
   .painel-marca.json. Este arquivo só declara `--marca` como reserva e deriva
   todos os tons dela com color-mix — trocar de cliente é trocar um hex.
   ========================================================================== */

/* Nunito, uma família só, em toda a interface. Pede a FAIXA de pesos (400..900)
   e não pesos soltos porque a fonte é variável e o painel usa valores fora da
   escala de 100 em 100 — 650 no nome do item, por exemplo. Com pesos discretos
   o navegador arredondaria e o 650 viraria 700. */
@import url('https://fonts.googleapis.com/css2?family=Nunito:ital,wght@0,400..900;1,400..700&display=swap');

:root {
  color-scheme: light;

  /* superfícies — papel levemente frio, neutro pra qualquer marca */
  --plano:        #f2f3f5;
  --plano-fundo:  #e6e8ec;
  --superficie:   #ffffff;
  --superficie-2: #f9fafb;
  --superficie-3: #eff1f4;

  /* tinta */
  --tinta:        #0f1216;
  --tinta-2:      #4c545e;
  --tinta-muda:   #838b95;

  /* traços */
  --borda:        #e2e5ea;
  --borda-forte:  #cdd2d9;
  --grade:        #eaedf1;

  /* marca — sobrescrita por /assets/marca.css; os tons saem daqui */
  --marca:        #2f5cff;
  --marca-escura: color-mix(in srgb, var(--marca) 84%, #000);
  --marca-fraca:  color-mix(in srgb, var(--marca) 9%, #fff);
  --marca-tinta:  color-mix(in srgb, var(--marca) 74%, #000);

  /* estado (dataviz status — sempre com ícone/rótulo junto) */
  --bom:          #0ca30c;
  --bom-tinta:    #06720d;
  --bom-fraco:    #e7f6e7;
  --atencao:      #fab219;
  --atencao-tinta:#8a5a00;
  --atencao-fraco:#fdf3e0;
  --grave:        #d03b3b;
  --grave-tinta:  #a52020;
  --grave-fraco:  #fdedec;
  --info:         #2a78d6;
  --info-tinta:   #1c5cab;
  --info-fraco:   #eaf2fd;
  /* `--ruim` era usado em quatro lugares (o mapa de cancelamento, o veredito das
     Calculadoras, a linha que sai da conta e a ressalva da entrega própria) e
     nunca foi definido: a cor caía pra preto no SVG e pra nada no CSS. É apelido
     de `--grave` de propósito — "ruim" e "grave" são o mesmo estado com dois
     nomes, e dois vermelhos diferentes só fariam a pessoa procurar diferença
     onde não há. */
  --ruim:         var(--grave);
  --ruim-fraco:   var(--grave-fraco);

  /* séries de gráfico (paleta validada — 3 slots, all-pairs seguro) */
  --serie-1: #2a78d6;
  --serie-2: #eb6834;
  --serie-3: #1baf7a;
  --eixo:    #c9c2ba;

  /* forma */
  --r-sm: 8px;
  --r-md: 12px;
  --r-lg: 18px;
  --r-xl: 26px;
  --sombra-1: 0 1px 2px rgba(15,18,22,.05), 0 1px 1px rgba(15,18,22,.03);
  --sombra-2: 0 2px 4px rgba(15,18,22,.04), 0 8px 20px -6px rgba(15,18,22,.10);
  --sombra-3: 0 18px 50px -12px rgba(15,18,22,.28), 0 4px 12px rgba(15,18,22,.08);

  /* A PROFUNDIDADE DOS BLOCOS, num lugar só.
     Cartão, KPI e painel usam este token — mexer aqui muda o painel inteiro, e
     nenhuma tela precisa de regra própria. Nasceu como exceção da Visão geral,
     onde a sombra de um fio deixava nove blocos se confundindo com o fundo; a
     leitura melhorou e passou a valer pra todas. */
  --sombra-cartao: 0 1px 2px rgba(15,18,22,.04), 0 6px 16px -8px rgba(15,18,22,.16);

  /* O RECUO INTERNO de um painel de duas colunas (a Central de novidades, e o
     que vier depois). Um número só, e o celular redefine o token em vez de
     cada regra repetir o valor menor. */
  --recuo-painel: 18px;

  /* A BARRA DE ROLAGEM, num lugar só.
     A do sistema entra grossa e escura e, num painel com rolagem dentro de
     cartão dentro de página, viram três traços cinza disputando atenção com o
     número que a pessoa foi ler. Fina, clara e sem trilho: ela informa que há
     mais conteúdo e sai da frente. `color-mix` em vez de um cinza fixo pra
     acompanhar a tinta do tema. */
  /* a altura útil de um painel que rola por dentro: a janela menos a barra de
     topo e o respiro da página */
  --altura-painel: calc(100dvh - 142px);

  /* Até onde uma lista cresce dentro de um cartão antes de rolar por dentro.
     Acima disso o cartão empurra o resto da tela pra baixo e some do campo de
     visão o cabeçalho que diz o que aquela lista é. */
  --altura-lista: 58vh;

  --barra: 10px;
  --barra-cor: color-mix(in srgb, var(--tinta-muda) 34%, transparent);
  --barra-cor-forte: color-mix(in srgb, var(--tinta-muda) 62%, transparent);
  /* A FAIXA DE CABEÇALHO de um painel de duas colunas: a marca de um lado e o
     título do outro nascem da mesma medida, então a emenda fica reta.
     56 é a conta do lado mais alto — o botão redondo de ação (39px) mais os
     8px de respiro em cima e embaixo. */
  --faixa-painel: 56px;
  --anel:     0 0 0 3px color-mix(in srgb, var(--marca) 22%, transparent);

  /* 268: o rótulo mais comprido é "Gestão de Delivery", e ele divide a linha
     com um ícone de 20px, o selo do módulo e a seta. A 256 saía "Gestão de
     Deli…" — nome de módulo cortado não identifica módulo nenhum. */
  --lateral: 268px;
  /* teto do conteúdo. Fica num token porque a barra de topo precisa do MESMO
     número pra alinhar o título com a primeira linha da página. */
  --largura-conteudo: 1500px;
  --topo-mobile: 58px;
  --nav-mobile: 66px;

  /**
   * AS BORDAS QUE O APARELHO COME.
   *
   * Só existem depois que o painel virou app instalável. No navegador a barra
   * de endereço e a de gestos ficam FORA da página, e nada disso importa. Em
   * pé, sem barra nenhuma, a página ocupa a tela inteira — e aí a faixa do
   * relógio no topo e a barra de gestos embaixo passam por cima do conteúdo.
   *
   * Ficam em variável, e não em `env()` espalhado, por dois motivos. O primeiro
   * é que já havia duas medidas de `env()` soltas no arquivo e uma delas estava
   * errada (ver .nav-mobile). O segundo é que assim dá pra MEDIR: a sonda de
   * navegador redefine estas quatro num aparelho de mentira e confere que o
   * topo desceu e que a barra de baixo cresceu, o que com `env()` cru é
   * impossível — não há como injetar valor nele.
   *
   * O 0px de reserva é pro que não é iPhone: sem ele, `calc()` com um valor
   * vazio invalida a regra inteira e a barra some.
   */
  --seguro-topo:  env(safe-area-inset-top, 0px);
  --seguro-baixo: env(safe-area-inset-bottom, 0px);
  --seguro-esq:   env(safe-area-inset-left, 0px);
  --seguro-dir:   env(safe-area-inset-right, 0px);

  --fonte: 'Nunito', ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif;
  /* Mesma família do corpo: o que separa título de texto agora é o PESO, não
     um segundo tipo. O token fica porque metade do painel o usa — e assim dá
     pra voltar a ter uma fonte de display trocando uma linha. */
  --fonte-display: var(--fonte);
  --peso-titulo: 800;   /* extrabold */
  --peso-nav: 600;      /* semibold */
}

* { box-sizing: border-box; }

/* precisa vencer o `display` das classes de layout (.pilha, .linha…),
   senão esconder uma tela com [hidden] não funciona */
[hidden] { display: none !important; }

html, body { height: 100%; }

body {
  margin: 0;
  font-family: var(--fonte);
  font-size: 14px;
  line-height: 1.5;
  color: var(--tinta);
  background: var(--plano);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* o `font-variation-settings: 'wdth'` saiu junto com o Archivo: a Nunito não
   tem eixo de largura, e a declaração ficaria apontando pro nada */
h1, h2, h3, h4 {
  font-family: var(--fonte-display);
  font-weight: var(--peso-titulo); letter-spacing: -.015em; margin: 0;
}

button, input, select, textarea { font: inherit; color: inherit; }

a { color: var(--info-tinta); text-decoration: none; }
a:hover { text-decoration: underline; }

:focus-visible { outline: 2px solid var(--marca); outline-offset: 2px; border-radius: 4px; }

.num { font-variant-numeric: tabular-nums; }

/* A fonte de ícone é SERVIDA POR NÓS, não pelo Google.
   Com o <link> pro fonts.googleapis.com, toda tela do painel dependia da
   internet chegar até lá pra desenhar ícone. Quando não chegava — restaurante
   com conexão ruim, firewall, Google fora do ar — a ligadura não formava e o
   NOME do ícone aparecia escrito: "delivery_dining", "pause_circle", "home"
   por cima do texto do menu. Testado bloqueando o domínio: as 16 telas viravam
   isso.

   O arquivo aqui é um subconjunto com só os ~94 ícones que o painel usa, pedido
   ao Google com `icon_names=`: 12 KB contra os ~4 MB da fonte inteira. */
@font-face {
  font-family: 'Material Symbols Rounded';
  font-style: normal;
  font-weight: 400;
  font-display: block;
  src: url('/assets/fontes/material-symbols.woff2') format('woff2');
}

/* ---- ícones do Google (Material Symbols) ----------------------------------
   O conteúdo do elemento é o NOME do ícone (`<span class="ico">home</span>`);
   quem desenha é a ligadura da fonte, servida por nós (@font-face acima).

   `text-transform: none` não é enfeite: num contexto em caixa alta a ligadura
   quebra e o nome aparece escrito na tela. Mesmo motivo do `letter-spacing`.
   O tamanho vem do `font-size` de cada lugar — o eixo `opsz` fica fixo em 24. */
.ico {
  font-family: 'Material Symbols Rounded';
  font-weight: normal; font-style: normal;
  line-height: 1; letter-spacing: normal; text-transform: none;
  white-space: nowrap; word-wrap: normal; direction: ltr;
  font-variation-settings: 'FILL' 0, 'wght' 400, 'GRAD' 0, 'opsz' 24;
  -webkit-font-feature-settings: 'liga';
  -webkit-font-smoothing: antialiased;
  user-select: none;
}

/* Vale pra QUALQUER coisa que role no painel — página, cartão, lista, modal.
   O `border` transparente com `background-clip` é o truque que afina o polegar
   sem afinar a área de clique: o rastro tem 9px, o traço visível tem 3. */
::-webkit-scrollbar { width: var(--barra); height: var(--barra); }
::-webkit-scrollbar-thumb {
  background: var(--barra-cor); border-radius: 20px;
  border: 3px solid transparent; background-clip: content-box;
}
::-webkit-scrollbar-thumb:hover { background: var(--barra-cor-forte); background-clip: content-box; }
::-webkit-scrollbar-track { background: transparent; }
/* as setinhas das pontas: o Chrome no Windows redesenha as duas assim que a
   barra é estilizada, e são elas que devolvem o aspecto pesado — ninguém
   rola clicando em seta */
::-webkit-scrollbar-button { display: none; width: 0; height: 0; }
::-webkit-scrollbar-corner { background: transparent; }
/* Firefox não tem os pseudo-elementos acima; tem estas duas.
   O `@supports not` é o que separa os dois mundos, e não é preciosismo: o
   Chrome hoje entende as duas propriedades e, quando elas aparecem, DESCARTA
   tudo que veio de `::-webkit-scrollbar`. Era exatamente o que acontecia — a
   barra continuava a do sistema, grossa e com as setinhas, só que repintada.
   Aqui o Chrome cai fora do bloco e fica com a versão fina de cima; o Firefox,
   que não conhece o seletor, entra e recebe o equivalente dele. */
@supports not selector(::-webkit-scrollbar) {
  * { scrollbar-width: thin; scrollbar-color: var(--barra-cor) transparent; }
}

/* ==========================================================================
   Layout — barra lateral no desktop, barra inferior no celular
   ========================================================================== */

.app { display: grid; grid-template-columns: var(--lateral) 1fr; min-height: 100dvh; }

.lateral {
  position: sticky; top: 0; height: 100dvh;
  display: flex; flex-direction: column; gap: 4px;
  padding: 18px 14px 14px;
  background: var(--superficie);
  border-right: 1px solid var(--borda);
  z-index: 20;
  /* Sem `overflow` de propósito: quem rola é o .nav (marca em cima e rodapé
     embaixo ficam parados, e é isso que os torna referência), e o flex já
     impede a barra de estourar. Um `overflow: hidden` aqui cortaria o menu do
     usuário, que é absolute e sai da barra quando ela está no modo rail. */
}

.marca-topo { display: flex; align-items: center; gap: 11px; padding: 4px 8px 18px; flex: none; position: relative; }
/* a esmaecida embaixo da marca é o par da do rodapé: com o menu rolado, o item
   de cima some por baixo dela em vez de aparecer cortado ao meio */
.lateral .marca-topo::after {
  content: ''; position: absolute; left: 0; right: 0; top: 100%; height: 14px;
  background: linear-gradient(to bottom, var(--superficie), transparent);
  pointer-events: none; z-index: 1;
}
.marca-selo {
  width: 36px; height: 36px; flex: none; border-radius: 11px;
  display: grid; place-items: center; font-size: 19px;
  /* Cor chapada, sem degradê nem brilho colorido. O degradê puxava um roxo
     (#7b8cff) que nem era da marca, e o box-shadow colorido em volta é o
     acabamento que faz interface parecer gerada — não desenhada. */
  background: var(--marca);
  color: #fff; font-family: var(--fonte-display); font-weight: var(--peso-titulo); letter-spacing: -.04em;
}
.marca-nome { display: block; font-family: var(--fonte-display); font-weight: var(--peso-titulo); font-size: 16px; letter-spacing: -.03em; line-height: 1.15; }
.marca-sub { display: block; font-size: 11.5px; color: var(--tinta-muda); letter-spacing: .02em; line-height: 1.3; }

/* `min-height: 0` é o que permite o item de flex encolher abaixo do conteúdo —
   sem isso o .nav cresce e é a página inteira que rola, levando junto a marca e
   o rodapé. A margem negativa devolve os 4px que o padding tira, pra o anel de
   foco de um item não ser cortado pelo overflow. */
.nav {
  display: flex; flex-direction: column; gap: 2px;
  flex: 1 1 auto; min-height: 0;
  overflow-y: auto; overscroll-behavior: contain;
  margin: 0 -4px; padding: 0 4px 6px;

}
/* A barra fica sempre visível, só clara: ela SÓ existe quando há conteúdo pra
   rolar, então é o próprio aviso de que o menu continua abaixo. Escondê-la no
   hover economizava um traço e custava a descoberta. */

/* Três blocos: o que se lê ao entrar, os módulos, e o histórico do dono. Só o
   do meio ganha rótulo — o respiro já separa os outros, e separador desenhado
   toda hora vira grade. */
/* Um bloco por módulo. O respiro entre eles é o que separa — separador
   desenhado a cada módulo viraria grade. */
.nav-bloco { display: flex; flex-direction: column; gap: 1px; }
.nav-bloco + .nav-bloco { margin-top: 4px; }

/* A LEGENDA DO MÓDULO. Ela não é clicável e não devia parecer: fica em cinza,
   menor que os destinos, e o peso do texto é o que a distingue — sem caixa,
   sem seta, sem ícone. O que o módulo tem embaixo dele é a resposta; o nome do
   módulo é só o rótulo da gaveta. */
.nav-titulo {
  display: flex; align-items: center; gap: 8px; width: 100%;
  font: inherit; font-size: 11.5px; font-weight: 700; letter-spacing: .01em;
  color: var(--tinta-muda); padding: 14px 11px 6px;
  border: 0; background: none; cursor: pointer; text-align: left;
}
.nav-titulo .rotulo { flex: 1; min-width: 0; }
.nav-titulo:hover { color: var(--tinta-2); }
.nav-titulo .seta { font-size: 17px; flex: none; transition: transform .18s; }
/* a seta aponta pra baixo quando o módulo está aberto e deitada quando fechado:
   é o único aviso de que ali tem mais coisa */
.nav-bloco.fechado > .nav-titulo .seta { transform: rotate(-90deg); }
.nav-bloco.fechado > .nav-item,
.nav-bloco.fechado > .nav-sub { display: none; }
/* o módulo da tela aberta acende — é o que responde "onde eu estou". Ele fica
   aberto e travado enquanto a pessoa navega dentro dele, então não há o que
   clicar na legenda: a seta sai e o cursor deixa de prometer um clique. */
/* O módulo da tela aberta fica aceso — é o "você está aqui". O que ele NÃO
   fica é travado: escondiam a seta e punham cursor de texto aqui, e o título
   virava um controle morto com cara de clicável. */
.nav-bloco.com-ativo > .nav-titulo { color: var(--marca-tinta); }
/* A CATEGORIA dentro do módulo — só o Delivery tem. Recuada até a coluna dos
   rótulos (20px de ícone + 10 de vão + 11 de recuo), pra ficar exatamente em
   cima do que ela agrupa e um degrau abaixo da legenda do módulo. */
.nav-sub {
  font-size: 11px; font-weight: 600; letter-spacing: .01em;
  color: var(--tinta-muda); opacity: .85; padding: 11px 11px 4px 41px;
}
.nav-item {
  display: flex; align-items: center; gap: 10px;
  padding: 7px 11px; border-radius: var(--r-md);
  font-size: 13.5px; font-weight: var(--peso-nav); color: var(--tinta-2);
  border: 0; background: none; cursor: pointer; text-align: left; width: 100%;
  transition: background .14s, color .14s;
}
.nav-item:hover { background: var(--superficie-3); color: var(--tinta); text-decoration: none; }
.nav-item .ic { width: 20px; text-align: center; font-size: 15px; flex: none; }
/* 18 numa grade de 24: o ícone acompanha o rótulo em vez de disputar com ele.
   Numa lista de trinta linhas, ícone grande vira ruído — é o texto que se lê. */
.nav-item .ic.ico { font-size: 18px; color: var(--tinta-muda); }
.nav-item:hover .ic.ico { color: var(--tinta-2); }
/* Rótulo comprido quebra em duas linhas em vez de virar reticências. São três
   em trinta e quatro ("Itens e complementos mais vendidos" precisaria de mais
   49px de coluna), e o compasso quebrado nessas três custa menos que esconder
   o fim do nome de quem procura justamente por ele. */
.nav-item .rotulo { min-width: 0; line-height: 1.3; }
.nav-item.ativo { background: var(--marca-fraca); color: var(--marca-tinta); font-weight: 700; }
.nav-item.ativo .ic.ico { color: var(--marca-tinta); }
.nav-item .selo {
  margin-left: auto; flex: none; font-size: 11px; font-weight: 700; padding: 1px 7px; border-radius: 20px;
  background: var(--marca); color: #fff; min-width: 20px; text-align: center;
}
.nav-item .selo.calmo { background: var(--superficie-3); color: var(--tinta-2); }

.lateral-rodape { flex: none; margin-top: auto; padding-top: 12px; border-top: 1px solid var(--borda); position: relative; }
/* âncora do menu do perfil: relativa e da altura do botão, pro menu flutuante
   abrir colado nele em vez de no topo do rodapé inteiro da lateral */
.ancora-conta { position: relative; }
/* a esmaecida diz "tem mais coisa em cima" sem gastar uma linha: sem ela o
   menu simplesmente termina cortado na borda do rodapé */
.lateral-rodape::before {
  content: ''; position: absolute; left: 0; right: 0; bottom: 100%; height: 20px;
  background: linear-gradient(to top, var(--superficie), transparent);
  pointer-events: none;
}

/* ---- pessoa logada + menu ---- */
.avatar {
  width: 30px; height: 30px; flex: none; border-radius: 10px;
  display: grid; place-items: center; font-size: 15px;
  background: var(--superficie-3); border: 1px solid var(--borda);
  /* EMOJI COMPOSTO NÃO PODE VAZAR PRA FORA DO QUADRADO.
     "🧑‍🍳" são três pontos de código unidos por ZWJ, e quando a fonte não
     desenha a ligadura ele sai como DOIS bonecos lado a lado — 40px de conteúdo
     num quadrado de 30. Sem o overflow, o segundo glifo escapava por cima do
     nome da pessoa. Com ele, o emoji ainda seria cortado ao meio; quem resolve
     é o `avatar-composto` que o JS põe quando conta mais de um código. */
  overflow: hidden; line-height: 1;
}
.avatar.grande { width: 52px; height: 52px; border-radius: 16px; font-size: 26px; }
/* emoji de vários códigos entra menor, pra caber inteiro em vez de ser aparado */
.avatar.composto { font-size: 11px; }
.avatar.grande.composto { font-size: 19px; }

.botao-usuario {
  display: flex; align-items: center; gap: 10px; width: 100%;
  border: 1px solid transparent; background: none; cursor: pointer; text-align: left;
  padding: 7px 9px; border-radius: var(--r-md);
  font-size: 13.5px; font-weight: var(--peso-nav); color: var(--tinta-2);
  transition: background .14s, border-color .14s;
}
.botao-usuario:hover, .botao-usuario[aria-expanded="true"] { background: var(--superficie-3); border-color: var(--borda); }
.botao-usuario .quem { min-width: 0; flex: 1; }
.botao-usuario .quem b { display: block; color: var(--tinta); font-weight: 700; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.botao-usuario .quem span { display: block; font-size: 11.5px; color: var(--tinta-muda); font-weight: 500; }
.botao-usuario .seta { font-size: 18px; color: var(--tinta-muda); flex: none; }
body.lateral-compacta .lateral .botao-usuario { justify-content: center; padding: 7px 0; }
body.lateral-compacta .lateral .botao-usuario .quem,
body.lateral-compacta .lateral .botao-usuario .seta { display: none; }

.menu-flutuante {
  position: absolute; z-index: 45; min-width: 216px;
  background: var(--superficie); border: 1px solid var(--borda); border-radius: var(--r-md);
  box-shadow: var(--sombra-3); padding: 6px; overflow: hidden;
  animation: sobe .16s cubic-bezier(.2,.8,.3,1);
}
.menu-flutuante.acima { bottom: calc(100% + 8px); left: 0; }
.menu-flutuante.abaixo { top: calc(100% + 8px); right: 0; }
.menu-flutuante .cabeca { padding: 9px 11px 10px; border-bottom: 1px solid var(--grade); margin-bottom: 6px; }
.menu-flutuante .cabeca b { display: block; font-size: 13.5px; }
.menu-flutuante .cabeca span { font-size: 12px; color: var(--tinta-muda); }
.menu-flutuante button, .menu-flutuante a {
  display: flex; align-items: center; gap: 10px; width: 100%;
  border: 0; background: none; cursor: pointer; text-align: left; text-decoration: none;
  padding: 9px 11px; border-radius: var(--r-sm);
  font-size: 13.5px; font-weight: var(--peso-nav); color: var(--tinta-2);
}
.menu-flutuante button:hover, .menu-flutuante a:hover { background: var(--superficie-3); color: var(--tinta); text-decoration: none; }
.menu-flutuante .ic { width: 18px; text-align: center; flex: none; }
.menu-flutuante .ic.ico { font-size: 19px; }
.menu-flutuante hr { border: 0; border-top: 1px solid var(--grade); margin: 6px -6px; }
.menu-flutuante .sair { color: var(--grave-tinta); }
.menu-flutuante .sair:hover { background: var(--grave-fraco); color: var(--grave-tinta); }

/* seletor de avatar */
.emojis { display: grid; grid-template-columns: repeat(auto-fill, minmax(46px, 1fr)); gap: 6px; }
.emojis button {
  aspect-ratio: 1; border: 1px solid var(--borda); background: var(--superficie);
  border-radius: var(--r-md); font-size: 21px; cursor: pointer;
  transition: border-color .14s, background .14s, transform .1s;
}
.emojis button:hover { border-color: var(--tinta-muda); transform: scale(1.06); }
.emojis button.ativo { border-color: var(--marca); background: var(--marca-fraca); box-shadow: var(--anel); }

/* A árvore Marca › Loja › ID vive DENTRO do seletor de lojas (o `.pulso-lojas`
   do rodapé da lateral saiu: empurrava o menu pra cima e brigava com ele). */
/* O cabeçalho da marca é CLICÁVEL — marca as lojas dela de uma vez. Por isso
   ele tem caixa de seleção, hover e foco: cabeçalho que responde ao clique sem
   parecer que responde é o mesmo defeito de um botão que não faz nada. */
.grupo-marca {
  display: flex; align-items: center; gap: 9px;
  font-size: 12.5px; font-weight: 700; color: var(--tinta);
  padding: 9px 10px 8px; margin-top: 6px; border-radius: var(--r-sm);
  border-top: 1px solid var(--borda); cursor: pointer; user-select: none;
}
.grupo-marca:first-child { border-top: 0; margin-top: 0; }
.grupo-marca:hover { background: var(--superficie-2); }
.grupo-marca:focus-visible { outline: 2px solid var(--marca); outline-offset: -2px; }
/* min-width: 0 é o que deixa o ellipsis funcionar dentro do flex */
.grupo-marca .nome { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.grupo-marca .apoio { flex: none; font-size: 11px; font-weight: 600; margin-left: auto; }
.grupo-marca .marca-check {
  width: 17px; height: 17px; flex: none; border-radius: 5px;
  border: 1.5px solid var(--borda-forte); display: grid; place-items: center;
  font-size: 11px; color: transparent; transition: background .12s, border-color .12s;
}
/* "parte" é o traço: com três de cinco marcadas, nem vazio nem cheio conta a
   verdade, e o clique seguinte marca as cinco */
.grupo-marca .marca-check.todas { background: var(--marca); border-color: var(--marca); color: #fff; }
.grupo-marca .marca-check.parte { border-color: var(--marca); color: var(--marca); font-weight: 700; }
.grupo-praca {
  display: flex; align-items: center; gap: 6px; flex-wrap: nowrap;
  font-size: 11.5px; font-weight: 700; color: var(--tinta-2);
  padding: 9px 2px 3px; border-top: 1px solid var(--borda); margin-top: 4px;
}
.grupo-praca:first-of-type { border-top: 0; margin-top: 0; padding-top: 2px; }
/* `min-width: 0` é o que faz o ellipsis funcionar: item de flex nasce com
   `min-width: auto` e se recusa a encolher abaixo do próprio conteúdo. */
.grupo-praca .nome { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.grupo-praca .apoio { margin-left: auto; flex: none; font-size: 11px; }
.grupo-praca .cidade { font-weight: 400; color: var(--tinta-muda); }
/* a unidade recua sob a marca — é o que faz a hierarquia se ler de relance */
.painel-lojas .linha-loja { padding-left: 26px; }
.nivel-tag {
  flex: none; font-size: 8.5px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase;
  background: var(--marca-fraca, rgba(47,92,255,.12)); color: var(--marca, #2f5cff);
  padding: 1px 5px; border-radius: 5px;
}
/* as lojas de um vínculo, abertas pelo botão Editar em Configurações */
.lojas-do-vinculo {
  margin-top: 10px; padding: 8px 10px;
  background: var(--superficie-2); border-radius: var(--r-sm);
}
.lojas-do-vinculo .praca {
  font-size: 11px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase;
  color: var(--tinta-muda); padding: 6px 0 3px;
}
.lojas-do-vinculo .praca:first-child { padding-top: 0; }
.lojas-do-vinculo .loja {
  display: flex; align-items: center; gap: 7px; flex-wrap: nowrap;
  padding: 2px 0 2px 6px; font-size: 12.5px;
}
.lojas-do-vinculo .loja .nome {
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

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

.barra-topo {
  position: sticky; top: 0; z-index: 15;
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
  padding: 16px max(26px, calc((100% - var(--largura-conteudo)) / 2 + 26px));
  background: color-mix(in srgb, var(--plano) 88%, transparent);
  backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--borda);
}
.barra-topo h1 { font-size: 21px; }
/* Título e legenda na mesma linha, centrados um pelo outro.
   `baseline` e não `center`: são dois tamanhos de texto muito diferentes (21px
   contra 12,5px), e alinhar pelo meio da caixa deixa a legenda parecendo alta.
   Pela base do texto os dois se apoiam na mesma linha, que é o que o olho lê
   como "lado a lado". `min-width: 0` porque o título pode ser longo e este
   bloco não pode empurrar os botões pra fora. */
.titulo-pagina { display: flex; align-items: baseline; gap: 10px; min-width: 0; flex-wrap: wrap; }
.barra-topo .legenda { font-size: 12.5px; color: var(--tinta-muda); }
/* A LEGENDA É A PRIMEIRA A SAIR quando a barra aperta.
   "atualizado agora mesmo" ao lado do título come ~150px, e num notebook de
   1280 é ela que empurra a linha de ações pra baixo. Entre perder a legenda e
   quebrar a barra em duas, a legenda perde: ela repete o que o ↻ de cada tela
   já diz, e a barra quebrada muda o desenho do painel inteiro. */
@media (max-width: 1320px) { .barra-topo .legenda { display: none; } }
/* sem `margin-left: auto`: quem reparte a folga agora são os .vao-busca, e a
   margem automática engoliria tudo antes deles */
.barra-topo .direita { display: flex; align-items: center; gap: 8px; }
/* o vão do #acaoResumo não existe quando a tela não tem resumo: `span` vazio
   herdaria o `gap` do flex e abriria um buraco antes do sino */
.barra-topo .direita > span:empty { display: none; }

/* ---- busca da barra de topo ----
   `flex: 1` sem largura fixa: ela toma o vão entre o título e os botões, seja
   ele qual for. Numa tela com menos botões sobra mais vão, e o campo cresce —
   é o "levemente maior" saindo do próprio layout, sem número por página.
   O `gap: 14px` da barra é o mesmo dos dois lados, então a distância pro título
   e pros botões é igual por construção. */
/* 3 partes pra busca, 1 pra cada vão: a folga se reparte sempre na mesma
   proporção, então os vãos ficam iguais em qualquer tela e a busca acompanha o
   espaço disponível. Quando ela bate no teto, o excedente volta pros vãos —
   que continuam iguais entre si. */
/* A BASE MENOR É O QUE IMPEDE A BARRA DE QUEBRAR.
   Medido em 1366px, largura de notebook comum: título 338 + busca 240 + ações
   429 + vãos = 1063 num espaço de 1036. Estourava por 27px, e o flex QUEBRA
   antes de encolher — então a linha inteira de ações caía pra baixo do título,
   em quase toda tela do painel. Com base 190 a conta fecha, e a busca continua
   crescendo até 640 quando há espaço. */
.busca-topo {
  flex: 3 1 190px; min-width: 150px; max-width: 640px;
  position: relative; display: flex; align-items: center;
}
.vao-busca { flex: 1 1 0; min-width: 0; }
@media (max-width: 820px) { .vao-busca { display: none; } }
.busca-topo .ic {
  position: absolute; left: 12px; font-size: 19px; color: var(--tinta-muda);
  pointer-events: none;
}
/* mesma altura, borda e raio dos botões vizinhos: na barra tudo se apoia na
   mesma linha, e um campo mais alto que o botão ao lado salta aos olhos */
.busca-topo input {
  /* altura cravada, não `min-height`: a caixa de linha do input variava com a
     fonte e deixava o campo 1px mais alto que o botão ao lado */
  width: 100%; height: 39px; line-height: 1.2;
  padding: 0 14px 0 39px; border-radius: var(--r-md);
  border: 1px solid var(--borda-forte); background: var(--superficie);
  font-size: 13.5px; font-weight: 600; color: var(--tinta);
  transition: border-color .14s, box-shadow .14s;
}
.busca-topo input::placeholder { font-weight: 500; color: var(--tinta-muda); }
.busca-topo input:hover { border-color: var(--tinta-muda); }
.busca-topo input:focus { outline: none; border-color: var(--marca); box-shadow: var(--anel); }
/* o X nativo do type=search brigava com o desenho */
.busca-topo input::-webkit-search-cancel-button { -webkit-appearance: none; }

.painel-busca {
  position: fixed; z-index: 55; max-height: min(60vh, 460px); overflow-y: auto;
  background: var(--superficie); border: 1px solid var(--borda);
  border-radius: var(--r-lg); box-shadow: var(--sombra-3); padding: 6px;
  animation: sobe .16s cubic-bezier(.2,.8,.3,1);
}
/* `achado-busca` e não `achado`: já existe um `.achado` (o resultado da busca
   transversal do agente), e ele é `flex-direction: column`. Reaproveitar o nome
   fazia esta linha herdar a coluna e empilhar ícone, título e selo. */
.painel-busca .achado-busca {
  display: flex; flex-direction: row; align-items: center; gap: 11px; width: 100%;
  border: 0; background: none; cursor: pointer; text-align: left;
  padding: 9px 11px; border-radius: var(--r-sm); font: inherit;
}
.painel-busca .achado-busca:hover { background: var(--superficie-3); }
.painel-busca .achado-busca > .ic { font-size: 19px; color: var(--tinta-muda); flex: none; }
.painel-busca .achado-busca .miolo { min-width: 0; flex: 1; }
.painel-busca .achado-busca strong { display: block; font-size: 13.5px; font-weight: 600; }
/* o resumo da tarefa é contexto, não título: uma linha e reticências */
.painel-busca .achado-busca .apoio {
  display: block; font-size: 12px; color: var(--tinta-muda);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.painel-busca .achado-busca .onde {
  flex: none; font-size: 10.5px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase;
  color: var(--tinta-muda); background: var(--superficie-3); padding: 2px 7px; border-radius: 20px;
}
.painel-busca .vazio-busca { padding: 14px 12px; font-size: 13px; color: var(--tinta-muda); }

/* botão só de ícone da barra: o mesmo corpo do sino, sem o selo */
.btn.so-icone { padding: 9px 11px; gap: 0; }
.btn.so-icone .ic { font-size: 19px; }
.btn.so-icone.pequeno { padding: 5px 7px; }
.btn.so-icone.pequeno .ic { font-size: 17px; }

/* AÇÃO DISCRETA — só o ícone, cinza claro, sem caixa.
   Nasceu nos posts (quatro botões repetidos em cada um, e com borda viravam uma
   grade de caixinhas competindo com o texto) e vale agora onde a ação é de
   quem escreveu, não de quem lê: fixar, fechar, editar, apagar. Num cinza claro
   ficam à disposição de quem pode mexer sem disputar a leitura de quem só passa
   os olhos. O fundo no hover fica — sem ele não dá pra saber onde o clique pega,
   e sem borda o alvo é invisível até o ponteiro chegar. */
.acoes-dono { display: flex; align-items: center; gap: 4px; }
/* `.acao-discreta` é a mesma coisa avulsa: serve pra linha que já tem o próprio
   contêiner de ações e só precisa do botão sem caixa, sem embrulhar tudo de novo */
.acoes-dono .btn.so-icone,
.btn.so-icone.acao-discreta {
  border: 0; background: none; color: var(--tinta-muda);
  padding: 5px; border-radius: var(--r-sm);
}
.acoes-dono .btn.so-icone:hover,
.btn.so-icone.acao-discreta:hover { background: var(--superficie-3); color: var(--tinta-2); }
.acoes-dono .btn.so-icone:focus-visible,
.btn.so-icone.acao-discreta:focus-visible { background: var(--superficie-3); }
/* apagar só fica vermelho na hora de clicar: em repouso é mais um cinza */
.acoes-dono .btn.perigo,
.btn.so-icone.acao-discreta.perigo { color: var(--tinta-muda); }
.acoes-dono .btn.perigo:hover,
.btn.so-icone.acao-discreta.perigo:hover { background: var(--grave-fraco); color: var(--grave-tinta); }
/* ligado (a conversa ESTÁ fixada): sem rótulo, a cor é o que diz o estado */
.acoes-dono .btn.so-icone.ligado,
.btn.so-icone.acao-discreta.ligado { color: var(--marca-tinta); background: var(--marca-fraca); }

@media (max-width: 820px) {
  /* na barra do celular não cabe título + busca + botões; a busca sai, e quem
     procura tela usa o menu, que ali é a gaveta inteira */
  .busca-topo { display: none; }
}

/* Centralizado, não encostado à esquerda.

   Recolher o menu alarga a coluna do conteúdo, e alinhado à esquerda tudo
   saltava 192px pro lado — o olho perdia a referência. Com `margin-inline:
   auto` a página ocupa o espaço que a barra liberou e a sobra se reparte
   igual dos dois lados, com o menu aberto ou fechado.

   Quando a coluna é mais estreita que o teto não sobra nada pra repartir e o
   `max()` do recuo cai nos 26px de sempre. */
.pagina { padding: 22px 26px 48px; max-width: var(--largura-conteudo); width: 100%; margin-inline: auto; }

.nav-mobile { display: none; }
.topo-mobile { display: none; }

/* barra lateral recolhida — o JS liga esta classe (por escolha do usuário
   ou automaticamente em tela estreita) */
/* tudo escopado em .lateral: essas classes também aparecem no conteúdo
   (prévia de Configurações, por exemplo) e não podem ser afetadas */
body.lateral-compacta { --lateral: 76px; }
/* Recolher o menu não arrasta a página.

   Antes, encolher a barra de 268 pra 76 alargava a coluna do conteúdo, e como
   ele é alinhado à esquerda TUDO saltava 192px pro lado — título, cartões,
   gráfico. O olho perde a referência e o clique seguinte erra o alvo.

   O recuo devolve exatamente o que a barra liberou, então a caixa do conteúdo
   fica idêntica nos dois estados: mesma origem, mesma largura, nada se move.
   Só vale pra quem ESCOLHEU recolher — em tela estreita o rail é imposto, e
   ali esses 192px são justamente o que a tela não tem pra dar. */
body.lateral-compacta .lateral .marca-topo { justify-content: center; padding: 4px 0 16px; }
body.lateral-compacta .lateral .marca-nome,
body.lateral-compacta .lateral .marca-sub,
body.lateral-compacta .lateral .nav-titulo,
body.lateral-compacta .lateral .nav-sub { display: none; }
/* `> .nav-item` de propósito: quem vira ícone solto é o destino do menu, e a
   legenda do módulo some — no rail o que sobra é uma coluna de ícones */
body.lateral-compacta .lateral .nav-bloco > .nav-item { justify-content: center; padding: 11px 0; position: relative; }
body.lateral-compacta .lateral .nav-bloco > .nav-item .rotulo { display: none; }
/* numa coluna de 37px o selo do tamanho normal monta em cima do ícone: aqui
   ele encolhe e senta na quina, como distintivo */
body.lateral-compacta .lateral .nav-bloco > .nav-item .selo {
  position: absolute; top: 1px; right: 2px; margin: 0;
  font-size: 9.5px; padding: 0 4px; min-width: 15px; line-height: 15px;
}
body.lateral-compacta .lateral .nav-bloco > .nav-item .ic { font-size: 20px; }
body.lateral-compacta .lateral .nav-bloco > .nav-item .ic.ico { color: inherit; }
body.lateral-compacta .lateral .recolher { justify-content: center; }
body.lateral-compacta .lateral .recolher .rotulo { display: none; }
body.lateral-compacta .lateral .recolher .seta { transform: rotate(180deg); }

.recolher {
  display: flex; align-items: center; gap: 11px; width: 100%;
  border: 0; background: none; cursor: pointer; text-align: left;
  padding: 8px 11px; margin-top: 4px; border-radius: var(--r-md);
  font-size: 12.5px; font-weight: var(--peso-nav); color: var(--tinta-muda);
  transition: background .14s, color .14s;
}
.recolher:hover { background: var(--superficie-3); color: var(--tinta-2); }
.recolher .seta { width: 20px; text-align: center; font-size: 19px; transition: transform .2s; }

@media (max-width: 820px) {
  .app { grid-template-columns: 1fr; }
  .lateral { display: none; }
  /* A altura SOMA a borda do aparelho em vez de descontar dela: com
     box-sizing: border-box, `height` fixa mais `padding-top` espremeria o
     conteudo da barra pra dentro do que sobrou. */
  .topo-mobile {
    display: flex; align-items: center; gap: 10px;
    position: sticky; top: 0; z-index: 25;
    height: calc(var(--topo-mobile) + var(--seguro-topo));
    padding: var(--seguro-topo) calc(16px + var(--seguro-dir)) 0 calc(16px + var(--seguro-esq));
    background: var(--superficie); border-bottom: 1px solid var(--borda);
  }
  .topo-mobile .marca-selo { width: 30px; height: 30px; border-radius: 9px; font-size: 16px; }
  .topo-mobile .titulo { font-family: var(--fonte-display); font-weight: var(--peso-titulo); font-size: 16px; }
  .topo-mobile .direita { margin-left: auto; display: flex; gap: 6px; position: relative; }
  .barra-topo { padding: 14px 16px; position: static; background: none; backdrop-filter: none; border: 0; }
  .barra-topo h1 { font-size: 19px; }
  .pagina {
    padding: 4px calc(16px + var(--seguro-dir))
             calc(var(--nav-mobile) + var(--seguro-baixo) + 32px)
             calc(16px + var(--seguro-esq));
  }
  .nav-mobile {
    display: grid; grid-auto-flow: column; grid-auto-columns: 1fr;
    position: fixed; inset: auto 0 0 0; z-index: 30;
    /* ERA `height: var(--nav-mobile)` com o padding por dentro. Num aparelho
       com barra de gestos (34px), os 66px da barra viravam 32px de conteudo e
       icone e rotulo ficavam pela metade — visivel so depois de instalado, que
       e quando a barra do sistema passa a existir. */
    height: calc(var(--nav-mobile) + var(--seguro-baixo));
    padding-bottom: var(--seguro-baixo);
    background: color-mix(in srgb, var(--superficie) 94%, transparent);
    backdrop-filter: blur(14px);
    border-top: 1px solid var(--borda);
  }
  .nav-mobile a {
    display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px;
    font-size: 10.5px; font-weight: var(--peso-nav); color: var(--tinta-muda); text-decoration: none;
    position: relative;
  }
  .nav-mobile a .ic { font-size: 22px; line-height: 1; }
  .nav-mobile a.ativo { color: var(--marca); }
  .nav-mobile a.ativo::before {
    content: ''; position: absolute; top: 0; left: 50%; transform: translateX(-50%);
    width: 28px; height: 3px; border-radius: 0 0 3px 3px; background: var(--marca);
  }
  .nav-mobile a .selo {
    position: absolute; top: 7px; right: calc(50% - 20px);
    background: var(--marca); color: #fff; font-size: 10px; font-weight: 700;
    min-width: 17px; padding: 0 4px; border-radius: 20px; line-height: 17px;
  }
}

/* ==========================================================================
   Cartões e blocos
   ========================================================================== */

.cartao {
  background: var(--superficie);
  border: 1px solid var(--borda);
  border-radius: var(--r-lg);
  box-shadow: var(--sombra-cartao);
  padding: 18px 20px;
}
.cartao.plano { box-shadow: none; }

.cartao.apertado { padding: 14px 16px; }
.cartao.nu { padding: 0; overflow: hidden; }

/* O `flex-wrap` aqui é irmão do que está logo abaixo em `.cartao-topo .acoes`,
   e precisou existir separado: nas Configurações os botões pendurados no topo
   do cartão são filhos DIRETOS, sem `.acoes` no meio, então a regra de baixo
   não os alcançava e eles somavam 190px de vazamento em 390px. */
.cartao-topo { display: flex; align-items: flex-start; gap: 12px; margin-bottom: 14px; flex-wrap: wrap; }
.cartao-topo > :first-child { min-width: 0; }
.cartao-topo h2 { font-size: 15.5px; letter-spacing: -.01em; }
.cartao-topo .sub { font-size: 12.5px; color: var(--tinta-muda); margin-top: 2px; line-height: 1.4; }
/* `flex-wrap` e `flex: 0 1 auto`: com DOIS botões no topo de um cartão (a ficha
   do pedido tem "Copiar o número" e "Ver todos de agora"), `flex: none` os
   mantinha lado a lado a qualquer custo — 290px numa tela de 390 empurravam a
   página inteira e davam 19px de rolagem lateral no celular. Podendo quebrar,
   o segundo botão desce e a página para de andar de lado. */
.cartao-topo .acoes {
  margin-left: auto; display: flex; gap: 8px; align-items: center;
  flex: 0 1 auto; flex-wrap: wrap; justify-content: flex-end; min-width: 0;
}

/* `stretch`, não `start`: irmãos na mesma faixa terminam na mesma altura, como
   os quatro da Visão geral. Com `start` cada cartão parava onde o conteúdo dele
   acabava e a linha ficava com degraus de até 300px — e a diferença de altura
   lia como diferença de importância, que não é o caso. */
.grelha { display: grid; gap: 16px; grid-template-columns: repeat(auto-fit, minmax(340px, 1fr)); align-items: stretch; }
/* `min-width: 0` nos filhos: item de grade nasce com `min-width: auto`, então o
   conteúdo mais largo de dentro (um gráfico, uma tabela, um nome sem espaço)
   empurra o cartão pra fora da coluna. O Chrome calcula esse mínimo menor e
   disfarça; o FIREFOX não — num celular de 360px o cartão saía 18px pra fora e
   a página inteira ganhava rolagem lateral. */
.grelha > *, .kpis > * { min-width: 0; }

/* Cartão de altura fixa que rola por dentro.
   344px é a conta do maior conteúdo: o gráfico de faturamento tem 210px de SVG,
   mais o cabeçalho e o respiro do cartão. Abaixo disso o gráfico ganharia uma
   barra de rolagem que não faz sentido num desenho de altura fixa. */
.cartao.mesma-altura { height: 344px; display: flex; flex-direction: column; }
.cartao.mesma-altura > .cartao-topo { flex: none; }
/* `min-height: 0` é o que faz o filho de flex poder encolher abaixo do próprio
   conteúdo — sem isto o `overflow` nunca entra em ação e o cartão estica */
.cartao.mesma-altura > .corpo-rolavel {
  flex: 1; min-height: 0; overflow-y: auto;
  /* a barra encosta na borda do cartão em vez de flutuar no meio do texto */
  margin-right: -12px; padding-right: 12px;
}
.grelha.duas { grid-template-columns: 1fr 1fr; }
.grelha.tres { grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); }
/* Duas colunas de pesos diferentes — a da esquerda manda. Isto morava num
   `style=` inline nas Configurações, e inline vence media query: a tela ficava
   com as duas colunas fixas no celular e vazava 526px pra fora da janela.
   Virou classe justamente pra a regra de baixo poder desmontar as colunas. */
.grelha.assimetrica { grid-template-columns: minmax(320px, 1fr) minmax(300px, .85fr); }
@media (max-width: 900px) { .grelha, .grelha.duas, .grelha.assimetrica { grid-template-columns: 1fr; } }
/* No celular os cartões ficam um embaixo do outro: não há altura de irmão pra
   casar, e a altura fixa só cria um rolo dentro do rolo da página — a pessoa
   passa o dedo e não sabe qual dos dois vai andar. Empilhado, o cartão cresce
   e quem rola é a página. */
@media (max-width: 720px) {
  .cartao.mesma-altura { height: auto; }
  .cartao.mesma-altura > .corpo-rolavel { overflow-y: visible; margin-right: 0; padding-right: 0; }
}

.pilha { display: flex; flex-direction: column; gap: 16px; }
/* um bloco vazio (ex.: alertas sem alerta) não deve gastar o espaçamento da pilha */
.pilha > div:empty { display: none; }
.linha { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
.espaco { flex: 1; }

/* ==========================================================================
   Indicadores (KPI)
   ========================================================================== */

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

/* Os quatro quadrantes da BCG são UMA matriz, não quatro cartões soltos: com
   `auto-fit` eles quebravam 3 + 1 e cada um ficava de um tamanho, que foi a
   reclamação do cliente. Aqui são sempre 4 colunas iguais (2 × 2 no estreito) e
   o rodapé de cada um é empurrado pra base, pra altura não depender de o rótulo
   caber em uma linha ou duas. */
.quadrantes-bcg { grid-template-columns: repeat(4, minmax(0, 1fr)); align-items: stretch; }
.quadrantes-bcg > .kpi { display: flex; flex-direction: column; }
.quadrantes-bcg > .kpi > .apoio { margin-top: auto; padding-top: 4px; }
@media (max-width: 900px) { .quadrantes-bcg { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

.kpi {
  background: var(--superficie); border: 1px solid var(--borda); border-radius: var(--r-lg);
  padding: 15px 17px; box-shadow: var(--sombra-cartao); position: relative; overflow: hidden;
  transition: border-color .14s, box-shadow .14s, transform .14s;
}
.kpis { overflow: visible; }

/* O CARTÃO APONTADO por um link de achado. Um anel da cor da marca que aparece
   e some: tempo de dizer "é este aqui" e sair da frente. Sem ele, a pessoa cai
   no meio de uma página com oito cartões iguais. */
.cartao-apontado { animation: apontar-cartao 2.4s ease-out; }
@keyframes apontar-cartao {
  0%, 60% { box-shadow: 0 0 0 3px var(--marca-fraca), 0 0 0 1px var(--marca); }
  100% { box-shadow: var(--sombra-cartao); }
}
@media (prefers-reduced-motion: reduce) {
  .cartao-apontado { animation: none; box-shadow: 0 0 0 3px var(--marca-fraca), 0 0 0 1px var(--marca); }
}

/* o degrau do funil é clicável: o cursor diz isso antes do clique, e o degrau
   acende no hover pra ficar claro QUAL deles vai abrir */
.degrau-funil { cursor: pointer; transition: fill-opacity .12s; }
.degrau-funil:hover { fill-opacity: .55 !important; }
.degrau-funil:focus-visible { outline: 2px solid var(--marca); outline-offset: 2px; }
/* a barra de etapa dos Cancelamentos filtra a lista de baixo — mesma regra do
   degrau do funil, porque é o mesmo gesto: a barra é o filtro */
.barra-etapa { cursor: pointer; transition: fill-opacity .12s; }
.barra-etapa:hover { fill-opacity: .72; }
.barra-etapa:focus-visible { outline: 2px solid var(--marca); outline-offset: 2px; }
/* o selo de perda na tabela vira botão sem deixar de ser selo */
.selo.clicavel { border: 0; cursor: pointer; font: inherit; font-size: 11.5px; font-weight: 600; }
.selo.clicavel:hover { filter: brightness(.94); }
/* o rótulo de bloco dentro do modal: separa as três leituras sem virar h3 */
.rotulo-bloco {
  font-size: 11px; font-weight: 700; letter-spacing: .07em; text-transform: uppercase;
  color: var(--tinta-muda); margin-bottom: 6px;
}

/* UMA FAIXA DE SEIS INDICADORES.
   Com `auto-fit` a grade abre seis colunas numa tela larga, mas quem preenche
   são os cartões: três indicadores param na metade e o resto da faixa fica
   vazio. Aqui as seis colunas são fixas, e as quebras são as que mantêm linhas
   cheias — 6, depois 3 + 3, depois 2 + 2 + 2. Nunca sobra meia fileira.
   Em seis colunas o cartão fica estreito, então o número desce de 31 para 26px:
   ainda é o maior elemento do cartão, e "até 5,1 km" continua numa linha só. */
.kpis.faixa-seis { grid-template-columns: repeat(6, minmax(0, 1fr)); }
.kpis.faixa-seis .kpi { padding: 14px 15px; display: flex; flex-direction: column; }
/* OS SEIS NÚMEROS NA MESMA ALTURA.
   Lado a lado, rótulo de uma linha e rótulo de duas ("CANCELADOS NESSE RAIO")
   deixavam os números em alturas diferentes, e a faixa lia como seis cartões
   soltos em vez de uma régua. Reservando duas linhas para todo rótulo, os
   números nascem no mesmo lugar; o rodapé de cada cartão vai para a base. */
.kpis.faixa-seis .rotulo {
  line-height: 1.3; min-height: 30px;      /* duas linhas de rótulo, sempre */
  align-items: flex-start; align-content: flex-start; padding-right: 16px;
}
/* a setinha de "isto leva a outro lugar" sai da linha do texto e vai pro canto:
   no cartão estreito ela roubava uma terceira linha do rótulo e empurrava o
   número desse cartão pra baixo do dos vizinhos */
.kpis.faixa-seis .kpi > .rotulo > .ico { position: absolute; top: 12px; right: 12px; }
.kpis.faixa-seis .extra { margin-top: auto; padding-top: 4px; }
.kpis.faixa-seis .valor { font-size: 26px; }
.kpis.faixa-seis .extra { font-size: 11.5px; }
@media (max-width: 1240px) { .kpis.faixa-seis { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .kpis.faixa-seis .valor { font-size: 31px; } }
/* no celular são dois por linha, e aí o cartão fica estreito de novo: o número
   volta a diminuir pra "até 5,1 km" não quebrar em duas linhas */
@media (max-width: 720px) {
  .kpis.faixa-seis { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .kpis.faixa-seis .valor { font-size: 24px; }
}
/* `flex-wrap` e `min-width: 0`: o rótulo é uma linha de flex, e sem eles o
   conteúdo mais largo dele (nome comprido + o botão de explicação) vira a
   largura MÍNIMA do cartão. Um KPI empurrava a coluna, a coluna empurrava a
   grade e a página inteira ganhava 77px de rolagem lateral — por causa de um
   rótulo de uma linha só. */
.kpi .rotulo {
  font-size: 11px; font-weight: 700; letter-spacing: .07em; text-transform: uppercase;
  color: var(--tinta-muda); display: flex; align-items: center; gap: 6px;
  flex-wrap: wrap; min-width: 0; overflow-wrap: anywhere;
}
/* o pedaço de texto solto dentro do rótulo também precisa poder encolher: é ele
   que estava fixando a largura mínima do cartão */
.kpi .rotulo > * { min-width: 0; }
/* O "i" DO CARTÃO DE INDICADOR.
   Num flex com quebra, o botão é um item à parte: como "PRAZO DE CONFIRMAÇÃO"
   ocupa a largura toda, ele não cabia ao lado e ia sozinho pra linha de baixo —
   uma bolinha solta 23px abaixo do texto que ela explica. Sem quebra entre os
   itens, quem cede é o TEXTO: ele se acomoda em duas linhas e o "i" fica ao
   lado, no meio delas.
   (o rótulo que começa com ícone continua como estava — lá o alinhamento é do
   ícone, que precisa ficar na primeira linha) */
.kpi .rotulo:has(> .explica):not(:has(> .ico)) { flex-wrap: nowrap; align-items: center; }
/* rótulo comprido ("VENDE MUITO E RENDE POUCO") tem que caber em duas linhas
   sem espremer o ícone nem desalinhar da primeira linha do texto */
.kpi .rotulo .ico { font-size: 17px; flex: none; align-self: flex-start; }
.kpi .rotulo:has(.ico) { align-items: flex-start; line-height: 1.35; }
.kpi .valor {
  font-family: var(--fonte-display); font-size: 31px; font-weight: 700; letter-spacing: -.035em;
  line-height: 1.1; margin-top: 7px;
}
.kpi .valor.menor { font-size: 25px; }
/* NOME DE LOJA CABE EM DUAS LINHAS, e não num corte de 22 caracteres.
   "Maior" e "Menor" existem pra dizer QUAL, e numa rede cujos nomes dividem o
   começo os dois liam "Forneria Original…" — a mesma resposta pra perguntas
   opostas. Duas linhas dão espaço ao pedaço que diferencia; passando disso, o
   nome inteiro está no title do cartão. */
.kpi .valor.nome {
  font-size: 19px; line-height: 1.2; letter-spacing: -.02em;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden; word-break: break-word;
}
.kpi .extra { font-size: 12px; color: var(--tinta-2); margin-top: 3px; }
.kpi .delta { font-size: 12px; font-weight: 700; margin-top: 4px; display: inline-flex; align-items: center; gap: 4px; }
/* a seta do delta é ícone do Google, não o triângulo ▲ — em 12px a ligadura
   fica miúda demais, então o ícone anda um pouco acima do tamanho do texto */
.delta .ico { font-size: 15px; }
.kpi .delta.sobe { color: var(--bom-tinta); }
.kpi .delta.desce { color: var(--grave-tinta); }
.kpi.destaque { background: var(--marca-fraca);
  border-color: color-mix(in srgb, var(--marca) 22%, #fff); }

/* KPI que também é botão: a Matriz BCG e a tela de pausados usam o cartão como
   seletor de nível/quadrante. Herda `font` porque <button> não herda sozinho. */
.kpi.clicavel {
  display: flex; flex-direction: column; align-items: flex-start;
  width: 100%; text-align: left; cursor: pointer; font: inherit; color: inherit;
  transition: border-color .12s, box-shadow .12s, background .12s;
}
/* o cartão que leva a algum lugar reage como botão: sobe um fio, ganha a cor
   da marca na borda e uma sombra mais presente. Antes o hover era tão discreto
   que a pessoa não sabia que dava pra clicar. */
.kpi.clicavel { cursor: pointer; }
.kpi.clicavel:hover {
  border-color: var(--marca); box-shadow: var(--sombra-2);
  transform: translateY(-2px);
}
.kpi.clicavel:active { transform: translateY(0); }
.kpi.clicavel:focus-visible { outline: 2px solid var(--marca); outline-offset: 2px; }
/* a seta do "clique aqui" anda pra frente no hover — o gesto que todo mundo já
   leu em mil interfaces */
.kpi.clicavel .rotulo .ico { transition: transform .14s; }
.kpi.clicavel:hover .rotulo .ico { transform: translateX(3px); }
@media (prefers-reduced-motion: reduce) {
  .kpi, .kpi.clicavel:hover, .kpi.clicavel .rotulo .ico { transition: none; transform: none; }
}
.kpi.clicavel.ativo {
  border-color: var(--cor-kpi, var(--marca));
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--cor-kpi, var(--marca)) 20%, transparent);
}
.kpi.clicavel .apoio { font-size: 12px; color: var(--tinta-2); margin-top: 2px; }
.kpi.clicavel.bom     .valor { color: var(--bom-tinta); }
.kpi.clicavel.atencao .valor { color: var(--atencao-tinta); }
.kpi.clicavel.grave   .valor { color: var(--grave-tinta); }

/* ==========================================================================
   Botões
   ========================================================================== */

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  border: 1px solid var(--borda-forte); border-radius: var(--r-md);
  padding: 9px 15px; font-size: 13.5px; font-weight: 600; line-height: 1.2;
  background: var(--superficie); color: var(--tinta); cursor: pointer;
  transition: background .14s, border-color .14s, transform .06s, box-shadow .14s;
  white-space: nowrap; text-decoration: none;
}
.btn:hover { background: var(--superficie-3); border-color: var(--tinta-muda); text-decoration: none; }
.btn:active { transform: translateY(1px); }
.btn:disabled { opacity: .45; cursor: not-allowed; transform: none; }

.btn.primario { background: var(--marca); border-color: var(--marca); color: #fff;
  box-shadow: 0 2px 8px -2px color-mix(in srgb, var(--marca) 55%, transparent); }
.btn.primario:hover { background: var(--marca-escura); border-color: var(--marca-escura); }
.btn.positivo { background: var(--bom-tinta); border-color: var(--bom-tinta); color: #fff; }
.btn.positivo:hover { background: #055a0a; border-color: #055a0a; }
/* ação positiva repetida linha a linha: contorno, pra não virar parede verde */
.btn.positivo-leve { background: var(--bom-fraco); border-color: #c2e5c2; color: var(--bom-tinta); }
.btn.positivo-leve:hover { background: var(--bom-tinta); border-color: var(--bom-tinta); color: #fff; }
.btn.perigo { background: var(--superficie); border-color: #f0c4c4; color: var(--grave-tinta); }
.btn.perigo:hover { background: var(--grave-fraco); border-color: var(--grave); }
.btn.perigo-forte { background: var(--grave); border-color: var(--grave); color: #fff; }
.btn.perigo-forte:hover { background: #a52020; border-color: #a52020; }
.btn.fantasma { background: none; border-color: transparent; color: var(--tinta-2); }
.btn.fantasma:hover { background: var(--superficie-3); border-color: transparent; }
.btn.pequeno { padding: 6px 11px; font-size: 12.5px; border-radius: var(--r-sm); }
/* O glifo num elemento próprio pra virar item de flex — só assim o `gap` do
   .btn vale pra ele. Solto no texto ("▶ Despausar") quem separava era o espaço
   da fonte, e o ▶ quase não tem folga lateral: colava na palavra. */
.btn > .ic { flex: none; font-size: .85em; line-height: 1; }
.btn.icone { padding: 8px; width: 34px; height: 34px; }
.btn.icone.pequeno { width: 28px; height: 28px; padding: 0; }
.btn.largo { width: 100%; padding: 12px 18px; font-size: 15px; }

/* ==========================================================================
   Campos
   ========================================================================== */

.campo { display: flex; flex-direction: column; gap: 5px; min-width: 0; }
.campo > label { font-size: 12.5px; font-weight: 600; color: var(--tinta-2); }
.campo .ajuda { font-size: 12px; color: var(--tinta-muda); line-height: 1.4; }
.campo .erro { font-size: 12px; color: var(--grave-tinta); font-weight: 600; display: flex; gap: 5px; align-items: center; }

.entrada {
  width: 100%; padding: 9px 12px;
  border: 1px solid var(--borda-forte); border-radius: var(--r-md);
  background: var(--superficie); font-size: 14px;
  transition: border-color .14s, box-shadow .14s;
}
.entrada::placeholder { color: var(--tinta-muda); }
.entrada:hover { border-color: var(--tinta-muda); }
.entrada:focus { outline: 0; border-color: var(--marca); box-shadow: var(--anel); }
.entrada.invalido { border-color: var(--grave); }
.entrada[type=date], .entrada[type=time], .entrada[type=datetime-local] { min-width: 0; }
textarea.entrada { resize: vertical; min-height: 76px; line-height: 1.5; }

.busca { position: relative; flex: 1; min-width: 180px; }
.busca .entrada { padding-left: 36px; }
/* A lupa vem da fonte de ícones, não do emoji: o emoji desenhava um 🔍
   colorido, de tamanho e alinhamento diferentes em cada sistema, dentro de um
   campo que é cinza e discreto em toda parte. */
.busca::before {
  content: 'search'; font-family: 'Material Symbols Rounded';
  font-variation-settings: 'FILL' 0, 'wght' 400, 'GRAD' 0, 'opsz' 24;
  -webkit-font-feature-settings: 'liga';
  letter-spacing: normal; text-transform: none; line-height: 1;
  position: absolute; left: 11px; top: 50%; transform: translateY(-50%);
  font-size: 17px; color: var(--tinta-muda); opacity: .75; pointer-events: none;
}
.busca .limpar {
  position: absolute; right: 6px; top: 50%; transform: translateY(-50%);
  border: 0; background: none; cursor: pointer; color: var(--tinta-muda);
  padding: 4px 7px; border-radius: 50%; font-size: 13px;
}
.busca .limpar:hover { background: var(--superficie-3); color: var(--tinta); }

/* segmentado — troca <select> por opções visíveis */
.segmentado {
  display: inline-flex; padding: 3px; gap: 2px;
  background: var(--superficie-3); border-radius: var(--r-md); border: 1px solid var(--borda);
}
/* `inline-flex` com vão: o botão pode ter ícone antes do rótulo, e sem isto o
   glifo encostava na primeira letra ("restaurant_menuCardápio" vira um borrão).
   `align-items: center` porque o ícone tem outra linha de base que o texto. */
.segmentado button {
  display: inline-flex; align-items: center; gap: 6px;
  border: 0; background: none; cursor: pointer; border-radius: 9px;
  padding: 6px 13px; font-size: 13px; font-weight: 600; color: var(--tinta-2);
  transition: background .14s, color .14s; white-space: nowrap;
}
.segmentado button .ico { font-size: 16px; flex: none; }
.segmentado button:hover { color: var(--tinta); }
.segmentado button.ativo { background: var(--superficie); color: var(--tinta); box-shadow: var(--sombra-1); }
.segmentado button .conta { opacity: .55; font-weight: 600; }
/* A FAIXA QUE QUEBRA. Com quatro opções tudo cabe numa linha; com sete, a
   última saía do cartão e virava uma função que só existia pra quem rolasse a
   página de lado — ou seja, pra ninguém. Aqui ela desce pra segunda linha. */
.segmentado.quebra { display: flex; flex-wrap: wrap; }
.segmentado.quebra button { white-space: normal; }
/* COLUNA QUE ORDENA. O cabeçalho vira alvo de clique sem virar botão: a seta
   só aparece na coluna que está mandando, senão nove setas competem entre si. */
.tabela th.ordenavel { cursor: pointer; user-select: none; white-space: nowrap; }
.tabela th.ordenavel:hover { color: var(--tinta); }
.tabela th.ordenavel.ativa { color: var(--marca-tinta); }
.tabela th.ordenavel .ico { font-size: 14px; vertical-align: -3px; }

/* O ATALHO DENTRO DE UMA FRASE. Um botão que se lê como parte do texto: a
   busca encontrou coisa noutro nível e o "3 em Complementos" leva até lá. Link
   de verdade não serve — não há URL, é troca de estado da mesma tela. */
.btn-vinculo {
  border: 0; background: none; padding: 0; font: inherit; cursor: pointer;
  color: var(--marca-tinta); font-weight: 600; text-decoration: underline;
  text-underline-offset: 2px;
}
.btn-vinculo:hover { color: var(--marca); }

/* o segmentado miúdo: mesma peça, na altura dos filtros do cabeçalho de tabela */
.segmentado.miudo { padding: 2px; }
.segmentado.miudo button { padding: 4px 10px; font-size: 12px; }
/* no celular o grupo quebra em duas linhas em vez de sumir na borda */
@media (max-width: 820px) {
  .segmentado { flex-wrap: wrap; max-width: 100%; }
  .segmentado button { flex: 1; min-width: max-content; }
}

/* caixinha de loja / dia — alvo grande, estado óbvio */
.opcoes { display: flex; gap: 7px; flex-wrap: wrap; }
/* A CAIXA DE MARCAR É A CAIXA — não um botão com uma caixa dentro.
   A cápsula com borda fazia cada opção parecer um botão que dispara alguma
   coisa, e marcada ela acendia inteira: dez opções marcadas viravam dez blocos
   azuis competindo com o conteúdo. Quem sinaliza o estado é o quadradinho, que
   é o que a pessoa já sabe ler. Sobra o rótulo, que é o que ela precisa ler. */
.opcao {
  display: inline-flex; align-items: center; gap: 8px; cursor: pointer;
  padding: 4px 2px; border: 0; background: none;
  font-size: 13px; font-weight: 600; color: var(--tinta-2);
  transition: color .14s;
  user-select: none;
}
.opcao:hover { color: var(--tinta); }
.opcao:hover .marca-check { border-color: var(--tinta-muda); }
.opcao input { position: absolute; opacity: 0; width: 0; height: 0; }
.opcao .marca-check {
  width: 17px; height: 17px; border-radius: 6px; flex: none;
  border: 1.5px solid var(--borda-forte); background: var(--superficie);
  display: grid; place-items: center; font-size: 11px; color: transparent;
  transition: background .14s, border-color .14s, color .14s;
}
/* marcada, muda o quadradinho e o peso do rótulo — não o fundo da linha toda */
.opcao:has(input:checked) { color: var(--tinta); }
.opcao:has(input:checked) .marca-check { background: var(--marca); border-color: var(--marca); color: #fff; }
.opcao:has(input:focus-visible) { outline: 2px solid var(--marca); outline-offset: 3px; border-radius: 6px; }
.opcao .ponto { width: 9px; height: 9px; border-radius: 3px; flex: none; }
.opcao.compacta { padding: 2px; font-size: 12.5px; }
/* a variante que mostra SÓ a caixa (dentro de tabela, por exemplo) */
.opcao.so-caixa { gap: 0; padding: 0; }

/* ==========================================================================
   Selos, chips e bolinhas de estado
   ========================================================================== */

.selo {
  display: inline-flex; align-items: center; gap: 5px; white-space: nowrap;
  font-size: 11.5px; font-weight: 700; border-radius: 20px; padding: 3px 10px;
  background: var(--superficie-3); color: var(--tinta-2);
}
.selo.bom     { background: var(--bom-fraco);     color: var(--bom-tinta); }
.selo.atencao { background: var(--atencao-fraco); color: var(--atencao-tinta); }
.selo.grave   { background: var(--grave-fraco);   color: var(--grave-tinta); }
.selo.info    { background: var(--info-fraco);    color: var(--info-tinta); }
.selo.marca   { background: var(--marca-fraca);   color: var(--marca-tinta); }
.selo.contorno { background: none; border: 1px solid var(--borda-forte); color: var(--tinta-2); }
/* o selo tem 11,5px de texto; o glifo do Material some nesse tamanho, e o `gap`
   de 5px do próprio selo já dá o respiro entre ícone e número */
.selo .ico { font-size: 14px; flex: none; }

.bolinha { width: 9px; height: 9px; border-radius: 50%; flex: none; display: inline-block; background: var(--tinta-muda); }
.bolinha.bom     { background: var(--bom); }
.bolinha.atencao { background: var(--atencao); }
.bolinha.grave   { background: var(--grave); }
.bolinha.vivo    { background: var(--bom); box-shadow: 0 0 0 0 rgba(12,163,12,.55); animation: pulso 2.2s infinite; }
@keyframes pulso {
  70%  { box-shadow: 0 0 0 7px rgba(12,163,12,0); }
  100% { box-shadow: 0 0 0 0 rgba(12,163,12,0); }
}

/* ==========================================================================
   Listas e tabelas (viram cartões no celular)
   ========================================================================== */

.lista { display: flex; flex-direction: column; }
.lista-item {
  display: flex; align-items: center; gap: 11px;
  padding: 11px 2px; border-bottom: 1px solid var(--grade); font-size: 13.5px;
}
.lista-item:last-child { border-bottom: 0; }
/* No celular a linha da lista quebra. Ela é flex e várias views penduram um
   `min-width` fixo no número da direita (150px nos Cancelamentos) — somado ao
   rótulo e à barrinha, não cabe em 390px e vaza a página inteira. Quebrando,
   o número desce pra segunda linha em vez de empurrar. */
@media (max-width: 720px) {
  .lista-item { flex-wrap: wrap; }
}
.lista-item .principal { font-weight: 600; }
.lista-item .apoio { color: var(--tinta-muda); font-size: 12.5px; }

/* O nome que abre a ficha do cliente — mesmo trato do `.item-nome` do cardápio:
   botão de verdade (foco, Enter, leitor de tela) com cara de texto. Fica com o
   peso do `.principal` porque a lista não pode mudar de aparência só porque a
   linha ganhou um destino. */
.nome-cliente {
  border: 0; background: none; padding: 0; cursor: pointer; text-align: left;
  font: inherit; font-weight: 600; color: var(--tinta); min-width: 0;
}
.nome-cliente:hover { color: var(--marca-tinta); text-decoration: underline; }
.nome-cliente:focus-visible { outline: 2px solid var(--marca); outline-offset: 2px; border-radius: 4px; }

.rolagem-x { overflow-x: auto; margin: 0 -20px; padding: 0 20px; }

/* DEZ LINHAS E ROLA.
   Os quadrantes do BCG são cartões um embaixo do outro, e um deles pode ter 40
   itens enquanto o vizinho tem 3: sem teto, a pessoa rola a página inteira só
   pra chegar no quadrante seguinte. Dez linhas é o que cabe de um olhar; o
   resto vem rolando ali mesmo. É teto, não altura fixa — quadrante com 6 itens
   ocupa 6 linhas, sem sobra em branco.
   A conta sai dos tokens: a linha da tabela mede 43px (11+11 de padding mais a
   linha de texto) e o cabeçalho, 35 — medidos na tela, não estimados. Ele fica
   preso no topo enquanto a lista corre por baixo. */
:root { --linha-tabela: 43px; --cabeca-tabela: 35px; }
.rolagem { max-height: calc(var(--cabeca-tabela) + 10 * var(--linha-tabela)); overflow-y: auto; }
/* E QUANDO ROLA, A BORDA PRECISA DIZER.
   O quadrante dizia "17" no título e desenhava dez linhas com o rodapé limpo —
   quem olhava concluía que a lista acabava ali e que o 17 estava errado. A
   classe é posta por JS depois de medir (CSS não sabe se transbordou), e some
   sozinha quando a pessoa chega no fim. */
.rolagem { position: relative; }
.rolagem.tem-mais {
  -webkit-mask-image: linear-gradient(to bottom, #000 calc(100% - 34px), transparent);
  mask-image: linear-gradient(to bottom, #000 calc(100% - 34px), transparent);
}

/* ROLAGEM DENTRO DO CARTÃO.
   Uma lista de dezenas de itens empurrava o rodapé da tela pra baixo e obrigava
   a rolar a página inteira — perdendo de vista os indicadores que dizem por
   onde começar. Presa aqui, a lista rola no lugar e o resto da tela fica.
   O `thead` já é `sticky`, então o cabeçalho da tabela acompanha.
   Só no desktop: no celular a tabela vira cartão empilhado e quem rola é a
   página, como deve. */
/* CARTÃO COM MUITO CONTEÚDO ROLA POR DENTRO.
   Uma lista de 200 linhas fazia um cartão de 4.000px: a pessoa rolava a página
   inteira e perdia de vista o cabeçalho, os filtros e os outros cartões. Presa
   ao teto, a lista rola no lugar e o resto da tela fica. Vale pra lista, pra
   tabela e pra grade de aulas — os três jeitos de um cartão ficar comprido.
   Só no desktop: no celular a tabela vira cartão empilhado e quem rola é a
   página, como deve. */
@media (min-width: 721px) {
  .rolagem-lista,
  .cartao .lista,
  .cartao > .rolagem-x,
  .cartao .grade-aulas { max-height: var(--altura-lista); overflow-y: auto; }
  /* o que já tem altura própria não entra na regra */
  .cartao.mesma-altura .lista,
  .cartao.mesma-altura > .rolagem-x { max-height: none; }
  /* nem o que já está DENTRO de um rolo: duas barras aninhadas fazem a pessoa
     rolar a de dentro achando que rola a de fora */
  .rolagem-lista .lista,
  .rolagem-lista .rolagem-x { max-height: none; overflow-y: visible; }

  /* A LISTA PRECISA DIZER QUE CONTINUA.
     Um cliente reportou que uma pessoa "não aparecia" na tela de acessos. Ela
     aparecia — estava embaixo, dentro do rolo. Nada na tela dizia isso: a
     barra de rolagem do sistema é fina e some quando ninguém mexe, então a
     lista simplesmente parecia terminar onde o cartão termina.
     A sombra abaixo aparece só quando há conteúdo escondido e some sozinha ao
     chegar na ponta, porque as camadas com `local` rolam junto e cobrem as
     camadas fixas. É CSS puro: não depende de evento de rolagem, e portanto
     não erra depois que a lista muda de tamanho. */
  .rolagem-lista, .cartao .lista, .cartao > .rolagem-x, .cartao .grade-aulas {
    background:
      linear-gradient(var(--superficie, #fff) 30%, rgba(255, 255, 255, 0)) top / 100% 22px no-repeat local,
      linear-gradient(rgba(255, 255, 255, 0), var(--superficie, #fff) 70%) bottom / 100% 22px no-repeat local,
      radial-gradient(farthest-side at 50% 0, rgba(15, 23, 42, .13), rgba(15, 23, 42, 0)) top / 100% 9px no-repeat scroll,
      radial-gradient(farthest-side at 50% 100%, rgba(15, 23, 42, .13), rgba(15, 23, 42, 0)) bottom / 100% 9px no-repeat scroll;
    /* a barra fica visível em vez de sobreposta: a sombra diz QUE há mais, a
       barra diz QUANTO — as duas juntas respondem a pergunta inteira */
    scrollbar-width: thin;
    scrollbar-gutter: stable;
  }
}

/* A MESMA SOMBRA, como classe avulsa.
   `.rolagem-lista` só vale no desktop, porque no celular quem rola é a página.
   Rolo dentro de MODAL é outra história: ele tem altura própria em qualquer
   largura, e some do mesmo jeito no celular. Esta classe é pra esses — o
   histórico de um cliente, a lista de itens de um combo.
   Nasceu de um relato de cliente: uma pessoa "não aparecia" numa lista, e
   estava embaixo, dentro de um rolo que nada anunciava. */
.rolo {
  overflow-y: auto;
  scrollbar-width: thin;
  scrollbar-gutter: stable;
  background:
    linear-gradient(var(--superficie, #fff) 30%, rgba(255, 255, 255, 0)) top / 100% 20px no-repeat local,
    linear-gradient(rgba(255, 255, 255, 0), var(--superficie, #fff) 70%) bottom / 100% 20px no-repeat local,
    radial-gradient(farthest-side at 50% 0, rgba(15, 23, 42, .13), rgba(15, 23, 42, 0)) top / 100% 8px no-repeat scroll,
    radial-gradient(farthest-side at 50% 100%, rgba(15, 23, 42, .13), rgba(15, 23, 42, 0)) bottom / 100% 8px no-repeat scroll;
}
/* O CABEÇALHO DA TABELA — a faixa de filtros dentro do próprio cartão.
   Um fio claro basta pra dizer "isto manda naquilo": caixa separada dava aos
   filtros o mesmo peso da tabela e sugeria que mexiam na tela inteira. */
.cabeca-tabela {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 12px 20px; border-bottom: 1px solid var(--grade);
}
/* o cartão que abriga cabeçalho + título + tabela não tem recuo próprio: quem
   recua é cada faixa, senão o fio do cabeçalho nasce e morre longe da borda */
.cartao.sem-recuo { padding: 0; }
.cartao.sem-recuo > .cartao-topo { padding: 16px 20px 0; margin: 0; }
.cartao.sem-recuo > #lista { padding: 14px 20px 18px; }
.cartao.sem-recuo .rolagem-x { margin: 0; padding: 0; }

/* a coluna da caixa de seleção: só o que a caixa ocupa */
table.tabela th.marca-col, table.tabela td.marca-col { width: 1%; padding-right: 0; }
table.tabela tr.marcada td { background: var(--marca-fraca); }
/* o ponto dentro do selo é menor que o solto: ali ele acompanha um texto de
   11px, e a cor já vem das classes globais de .bolinha */
.selo .bolinha { width: 7px; height: 7px; margin-right: 5px; }

/* a coluna de ação não disputa largura com o conteúdo, e o botão não quebra */
table.tabela th.acoes-col, table.tabela td.acoes-col { width: 1%; white-space: nowrap; }
.acoes-linha { display: flex; align-items: center; justify-content: flex-end; gap: 6px; }

table.tabela { width: 100%; border-collapse: collapse; font-size: 13.5px; }
table.tabela th {
  text-align: left; font-size: 11px; font-weight: 700; letter-spacing: .07em; text-transform: uppercase;
  color: var(--tinta-muda); padding: 9px 12px; border-bottom: 1px solid var(--borda);
  white-space: nowrap; position: sticky; top: 0; background: var(--superficie); z-index: 1;
}
table.tabela td { padding: 11px 12px; border-bottom: 1px solid var(--grade); vertical-align: middle; }
table.tabela tbody tr:last-child td { border-bottom: 0; }
table.tabela tbody tr:hover td { background: var(--superficie-2); }
/* a linha que leva a algum lugar avisa que leva */
table.tabela tbody tr.linha-clicavel { cursor: pointer; }
table.tabela tbody tr.linha-clicavel:hover td { background: var(--marca-fraca); }
table.tabela th.dir, table.tabela td.dir { text-align: right; }
table.tabela td.num, table.tabela th.num { font-variant-numeric: tabular-nums; }

@media (max-width: 720px) {
  table.cartoes, table.cartoes tbody, table.cartoes tr, table.cartoes td { display: block; width: 100%; }
  table.cartoes thead { display: none; }
  table.cartoes tr {
    border: 1px solid var(--borda); border-radius: var(--r-md);
    padding: 10px 12px; margin-bottom: 10px; background: var(--superficie);
  }
  /* `flex-wrap` e `min-width: 0`: a célula vira uma linha flex no celular, e sem
     poder quebrar ela empurra tudo que não couber pra fora da tela. A coluna
     "desfecho" dos Cancelamentos tem três ou quatro selos numa célula só —
     medido em 390px, davam 510px de rolagem lateral na página INTEIRA, não só
     na tabela. `min-width: 0` porque item de flex nasce com o mínimo do próprio
     conteúdo: sem ele, um selo de texto longo continua sem encolher. */
  table.cartoes td {
    border: 0; padding: 4px 0; display: flex; gap: 12px; align-items: center;
    flex-wrap: wrap; min-width: 0;
  }
  table.cartoes td > * { min-width: 0; }
  /* a célula de ação não tem rótulo pra mostrar: os botões ocupam a linha */
  table.cartoes td.acoes-col::before { display: none; }
  /**
   * A CÉLULA DE AÇÃO PRECISA DESFAZER O `width: 1%` DA TABELA DE VERDADE.
   *
   * Lá em cima, `table.tabela th.acoes-col, table.tabela td.acoes-col` pede
   * `width: 1%; white-space: nowrap` — que é o certo numa tabela: a coluna de
   * botões encolhe ao mínimo e deixa o espaço pras colunas de conteúdo.
   *
   * Só que aquela regra tem DUAS classes e vence o `table.cartoes td` genérico
   * que manda a célula ocupar a linha inteira no celular. Resultado medido em
   * /qualidade a 393px: a célula com 3px de largura e, dentro dela, botões de
   * 33 e 146px — sobrando 182px pra fora do cartão, fora da tela, sem jeito de
   * alcançar. "Escrever descrição" era um dos que sumiam.
   *
   * Aqui a especificidade empata e a ordem decide, que é como o arquivo já
   * resolve os outros casos de cartão.
   */
  table.cartoes td.acoes-col {
    padding-top: 8px; display: flex; width: 100%; white-space: normal;
  }
  table.cartoes td.acoes-col .acoes-linha { justify-content: flex-start; }
  table.cartoes td::before {
    content: attr(data-rotulo); flex: none; min-width: 92px;
    font-size: 11px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--tinta-muda);
  }
  table.cartoes td.destaque { font-size: 15px; font-weight: 700; padding-bottom: 6px; }
  table.cartoes td.destaque::before { display: none; }
  table.cartoes td.acoes { justify-content: flex-end; padding-top: 8px; }
  table.cartoes td.acoes::before { display: none; }
  table.cartoes tbody tr:hover td { background: none; }
  /* Só a tabela que VIRA CARTÃO abre mão da rolagem lateral — ela deixou de ser
     tabela, cada linha virou um bloco de largura cheia, e a rolagem sobrando
     só atrapalha. A regra valia pra qualquer `.rolagem-x` e isso derrubava a
     rolagem de tabelas que continuam tabela: `/operacao` e `/diagnostico`
     usam `table.tabela` sem `cartoes` e vazavam 527px e 588px em 390px de tela,
     porque o único container que as segurava tinha sido mandado calar.
     Se o navegador não conhecer `:has()`, a regra inteira é ignorada e a
     rolagem continua ligada — que é justamente o lado seguro de errar. */
  .rolagem-x:has(table.cartoes) { overflow: visible; margin: 0; padding: 0; }
}

/* ==========================================================================
   Estados: vazio, carregando, erro
   ========================================================================== */

.vazio { text-align: center; padding: 34px 20px; color: var(--tinta-muda); }
.vazio .emoji { font-size: 30px; display: block; margin-bottom: 8px; opacity: .8; }
.vazio .titulo { font-family: var(--fonte-display); font-size: 15px; font-weight: var(--peso-titulo); color: var(--tinta-2); margin-bottom: 4px; }
.vazio p { margin: 0 auto; max-width: 380px; font-size: 13px; line-height: 1.55; }
.vazio .btn { margin-top: 14px; }

.esqueleto {
  background: linear-gradient(100deg, var(--superficie-3) 30%, #f6f2ee 48%, var(--superficie-3) 66%);
  background-size: 300% 100%; animation: brilho 1.3s ease-in-out infinite;
  border-radius: var(--r-sm); height: 13px;
}
@keyframes brilho { to { background-position: -180% 0; } }
.esqueleto.alto { height: 74px; border-radius: var(--r-md); }
.esqueleto.titulo { height: 22px; width: 42%; }

.girando {
  display: inline-block; width: 14px; height: 14px; vertical-align: -2px;
  border: 2px solid var(--borda-forte); border-top-color: var(--marca);
  border-radius: 50%; animation: gira .7s linear infinite;
}
@keyframes gira { to { transform: rotate(360deg); } }

/* A AMPULHETA DO TÍTULO — só existe enquanto a tela está sendo montada.
   O esqueleto no corpo já diz que o painel está trabalhando, mas quem clicou no
   menu está olhando pro topo da página, não pro meio dela. Nasce escondida: um
   giro permanente ao lado do título viraria decoração, e decoração que gira
   ensina a ignorar exatamente o sinal que a gente quer que seja lido. */
/* Fica FORA do <h1> de propósito: `aplicarCabecalho` troca o título com
   `textContent` a cada tela, e textContent apaga qualquer filho — dentro do h1
   a ampulheta era destruída no primeiro clique e nunca mais voltava.
   `align-self: center` porque a faixa alinha pela linha de base do título, e
   um círculo não tem linha de base: alinhado por ela, ele afunda. */
.girando-titulo { display: none; align-self: center; flex: none; }
body.carregando-tela .girando-titulo { display: inline-block; }

.aviso {
  display: flex; gap: 11px; align-items: flex-start;
  padding: 12px 15px; border-radius: var(--r-md); font-size: 13px; line-height: 1.5;
  background: var(--info-fraco); color: var(--info-tinta); border: 1px solid #cfe1f8;
}
.aviso .ic { font-size: 15px; line-height: 1.3; flex: none; }
/* o glifo do Material é desenhado numa grade de 24: a 15px fica franzino */
.aviso .ic.ico { font-size: 19px; }
.aviso strong { display: block; margin-bottom: 2px; }
.aviso.atencao { background: var(--atencao-fraco); color: var(--atencao-tinta); border-color: #f4e0bd; }
.aviso.grave   { background: var(--grave-fraco);   color: var(--grave-tinta);   border-color: #f4cccb; }
.aviso.bom     { background: var(--bom-fraco);     color: var(--bom-tinta);     border-color: #c9e9c9; }

/* ==========================================================================
   Modal / folha
   ========================================================================== */

.fundo-modal {
  position: fixed; inset: 0; z-index: 60;
  background: rgba(15,18,22,.45); backdrop-filter: blur(3px);
  display: flex; align-items: flex-start; justify-content: center;
  padding: 42px 18px; overflow-y: auto;
  animation: aparece .16s ease-out;
}
@keyframes aparece { from { opacity: 0; } }

.modal {
  background: var(--superficie); border-radius: var(--r-xl);
  width: 100%; max-width: 560px; box-shadow: var(--sombra-3);
  animation: sobe .2s cubic-bezier(.2,.8,.3,1);
  overflow: hidden; margin: auto 0;
}
.modal.largo { max-width: 820px; }
@keyframes sobe { from { opacity: 0; transform: translateY(14px) scale(.985); } }

.modal-topo { display: flex; align-items: flex-start; gap: 14px; padding: 22px 24px 0; }
.modal-topo h2 { font-size: 19px; letter-spacing: -.02em; }
.modal-topo .sub { font-size: 13px; color: var(--tinta-muda); margin-top: 4px; line-height: 1.5; }
.modal-topo .fechar {
  margin-left: auto; flex: none; border: 0; background: var(--superficie-3); cursor: pointer;
  width: 32px; height: 32px; border-radius: 50%; color: var(--tinta-2);
  display: grid; place-items: center;
}
.modal-topo .fechar .ico { font-size: 19px; }
.modal-topo .fechar:hover { background: var(--borda); }
.modal-corpo { padding: 18px 24px; display: flex; flex-direction: column; gap: 16px; }
.modal-corpo.rolavel { max-height: min(62vh, 560px); overflow-y: auto; }
/* A TABELA DENTRO DO MODAL NÃO PODE SER ESPREMIDA.
   `.modal-corpo` é um flex em coluna, e um filho com `overflow` tem min-height
   resolvido em zero: a caixa de rolagem encolhia até 113px e uma tabela de 600
   ficava com duas linhas e meia à mostra, cortada no meio. Quem rola é o corpo
   do modal, então a caixa mantém a altura do conteúdo. */
.modal-corpo .rolagem-x, .modal-corpo .rolagem { flex: none; }
.modal-rodape {
  display: flex; gap: 10px; justify-content: flex-end; align-items: center;
  padding: 16px 24px; background: var(--superficie-2); border-top: 1px solid var(--borda);
}
.modal-rodape .esquerda { margin-right: auto; font-size: 12.5px; color: var(--tinta-muda); }

@media (max-width: 620px) {
  .fundo-modal { padding: 0; align-items: flex-end; }
  .modal { max-width: none; border-radius: var(--r-xl) var(--r-xl) 0 0; max-height: 94dvh; display: flex; flex-direction: column; animation: folha .24s cubic-bezier(.2,.8,.3,1); }
  .modal-corpo { overflow-y: auto; }
  .modal-corpo.rolavel { max-height: none; }
  .modal-rodape { padding-bottom: calc(16px + var(--seguro-baixo)); }
  .modal-rodape .btn { flex: 1; justify-content: center; }
  @keyframes folha { from { transform: translateY(100%); } }
}

/* seções dentro de um modal grande (ficha do item) */
.secao { padding-top: 18px; margin-top: 18px; border-top: 1px solid var(--grade); }
.secao:first-child { padding-top: 0; margin-top: 0; border-top: 0; }
.secao > h4 {
  font-size: 11px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase;
  color: var(--tinta-muda); margin-bottom: 10px;
}

/* prévia do que vai acontecer — o antídoto contra clique errado */
.previa {
  border: 1px solid var(--borda); border-radius: var(--r-md);
  background: var(--superficie-2); font-size: 13px;
  max-height: 210px; overflow-y: auto;
}
.previa .item {
  display: flex; align-items: center; gap: 9px; padding: 8px 13px;
  border-bottom: 1px solid var(--grade);
}
.previa .item:last-child { border-bottom: 0; }
.previa .item .de { color: var(--tinta-muda); text-decoration: line-through; }
.previa .item .para { font-weight: 700; }
/* o resumo fica colado embaixo mesmo quando a lista rola */
.previa .rodape {
  position: sticky; bottom: 0; padding: 8px 13px; font-size: 12px;
  color: var(--tinta-muda); background: var(--superficie-3); border-top: 1px solid var(--borda);
}

.travinha {
  display: flex; align-items: flex-start; gap: 10px; cursor: pointer;
  padding: 12px 14px; border-radius: var(--r-md);
  background: var(--grave-fraco); border: 1px solid #f4cccb; font-size: 13px; color: var(--grave-tinta);
}
.travinha input { margin-top: 2px; accent-color: var(--grave); width: 16px; height: 16px; flex: none; }

/* ==========================================================================
   Avisos flutuantes (toast) — com desfazer
   ========================================================================== */

.toasts {
  position: fixed; z-index: 80; right: 20px; bottom: 20px;
  display: flex; flex-direction: column-reverse; gap: 10px; max-width: min(400px, calc(100vw - 40px));
}
@media (max-width: 820px) { .toasts { right: 12px; left: 12px; bottom: calc(var(--nav-mobile) + 12px); max-width: none; } }

.toast {
  display: flex; align-items: center; gap: 11px;
  background: #14171c; color: #fff; padding: 12px 15px;
  border-radius: var(--r-md); box-shadow: var(--sombra-3); font-size: 13.5px; line-height: 1.4;
  animation: entra .22s cubic-bezier(.2,.8,.3,1);
}
@keyframes entra { from { opacity: 0; transform: translateY(10px) scale(.97); } }
.toast.saindo { animation: sai .18s ease-in forwards; }
@keyframes sai { to { opacity: 0; transform: translateY(6px) scale(.97); } }
.toast .ic { font-size: 15px; flex: none; }
.toast .txt { flex: 1; }
.toast .txt small { display: block; opacity: .65; font-size: 12px; margin-top: 1px; }
.toast .desfazer {
  flex: none; border: 1px solid rgba(255,255,255,.28); background: rgba(255,255,255,.08);
  color: #fff; border-radius: var(--r-sm); padding: 5px 11px; font-size: 12.5px; font-weight: 700; cursor: pointer;
}
.toast .desfazer:hover { background: rgba(255,255,255,.2); }
.toast.bom   { background: #0a4d13; }
.toast.grave { background: #7d1a1a; }

/* ==========================================================================
   Barra de ação em massa
   ========================================================================== */

/* A BARRA DE SELEÇÃO É FIXA, não sticky — e o motivo é um bug que o cliente
   pegou: com `sticky`, ela só aparece quando a pessoa rola até o FIM da lista,
   porque sticky gruda dentro do próprio contêiner. Num cardápio de 151 itens,
   marcar o primeiro item e não ver ação nenhuma é o que acontecia.
   Fixa no rodapé da área de conteúdo, ela aparece no instante em que algo é
   marcado, esteja a pessoa onde estiver na lista. */
.barra-lote {
  position: fixed; bottom: 16px; z-index: 30;
  left: calc(var(--lateral) + 24px); right: 24px;
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  padding: 12px 16px; border-radius: var(--r-lg);
  background: #14171c; color: #fff; box-shadow: var(--sombra-3);
  animation: sobe .2s cubic-bezier(.2,.8,.3,1);
}
.barra-lote .conta { font-family: var(--fonte-display); font-weight: 700; font-size: 15px; }
.barra-lote .apoio { font-size: 12.5px; opacity: .7; }
.barra-lote .btn { border-color: rgba(255,255,255,.25); background: rgba(255,255,255,.1); color: #fff; }
.barra-lote .btn:hover { background: rgba(255,255,255,.22); border-color: rgba(255,255,255,.4); }
.barra-lote .btn.primario { background: var(--marca); border-color: var(--marca); }
.barra-lote .btn.positivo { background: var(--bom); border-color: var(--bom); }
@media (max-width: 820px) {
  .barra-lote { bottom: calc(var(--nav-mobile) + 12px); left: 10px; right: 10px; }
}
/* o balão de suporte não pode ficar por baixo da barra de ação */
body:has(.barra-lote) .balao-suporte { bottom: 92px; }

/* ==========================================================================
   Gráficos
   ========================================================================== */

.grafico svg { display: block; width: 100%; height: auto; }
/* O gráfico ocupa o que sobra do cartão. Sem isto o `.grafico` não tem altura
   própria — quem manda é o SVG — e o desenho fica encostado no topo com meia
   caixa em branco embaixo, que é o que acontece quando a grade estica o cartão
   pra casar com o vizinho mais alto. Com o cartão em coluna e o gráfico
   crescendo, o desenho sabe quanta altura tem e distribui as linhas nela. */
.cartao:has(> .grafico) { display: flex; flex-direction: column; }
.cartao > .grafico { flex: 1 1 auto; min-height: 0; }
.grafico svg text { font-family: var(--fonte); }
.tick { font-size: 11px; fill: var(--tinta-muda); font-variant-numeric: tabular-nums; }
.rotulo-direto { font-size: 11px; font-weight: 700; fill: var(--tinta-2); font-variant-numeric: tabular-nums; }
.legenda { display: flex; gap: 16px; flex-wrap: wrap; font-size: 12.5px; color: var(--tinta-2); margin-top: 12px; }
.legenda span { display: inline-flex; gap: 6px; align-items: center; }
.legenda .ponto { width: 10px; height: 10px; border-radius: 3px; }

/* a dica que segue o mouse no gráfico usa o mesmo idioma do balão de ajuda:
   duas caixas flutuantes com aparências diferentes na mesma tela pareciam vir
   de sistemas diferentes */
.dica-grafico {
  position: fixed; z-index: 70; pointer-events: none; opacity: 0; transition: opacity .12s;
  background: var(--info-fraco); color: var(--tinta);
  border: 1px solid color-mix(in srgb, var(--info) 30%, white);
  font-size: 12.5px; line-height: 1.5;
  padding: 9px 12px; border-radius: var(--r-sm); max-width: 260px;
  box-shadow: 0 10px 30px rgba(20, 55, 105, .16);
}
.dica-grafico strong, .dica-grafico b { color: var(--info-tinta); }
.dica-grafico.ver { opacity: 1; }
.dica-grafico strong { font-weight: 700; }

/* ==========================================================================
   Tour de boas-vindas
   ========================================================================== */

.tour-fundo { position: fixed; inset: 0; z-index: 90; background: rgba(15,18,22,.58); animation: aparece .2s; }
.tour-foco {
  position: fixed; z-index: 91; border-radius: var(--r-lg); pointer-events: none;
  box-shadow: 0 0 0 9999px rgba(15,18,22,.58), 0 0 0 3px var(--marca);
  transition: all .3s cubic-bezier(.2,.8,.3,1);
}
.tour-balao {
  position: fixed; z-index: 92; width: min(340px, calc(100vw - 32px));
  background: var(--superficie); border-radius: var(--r-lg); box-shadow: var(--sombra-3);
  padding: 18px 20px; transition: all .3s cubic-bezier(.2,.8,.3,1);
}
.tour-balao h3 { font-size: 16px; margin-bottom: 6px; }
.tour-balao p { font-size: 13.5px; color: var(--tinta-2); line-height: 1.55; margin: 0; }
.tour-balao .rodape { display: flex; align-items: center; gap: 10px; margin-top: 16px; }
.tour-balao .passos { display: flex; gap: 5px; margin-right: auto; }
.tour-balao .passos i { width: 6px; height: 6px; border-radius: 50%; background: var(--borda-forte); }
.tour-balao .passos i.ativo { background: var(--marca); width: 18px; border-radius: 20px; }

/* ==========================================================================
   Guia
   ========================================================================== */

.guia-grelha { display: grid; gap: 12px; grid-template-columns: repeat(auto-fill, minmax(258px, 1fr)); }
.guia-cartao {
  text-align: left; cursor: pointer; font: inherit;
  background: var(--superficie); border: 1px solid var(--borda); border-radius: var(--r-lg);
  padding: 16px 18px; box-shadow: var(--sombra-1);
  transition: transform .14s, box-shadow .14s, border-color .14s;
}
.guia-cartao:hover { transform: translateY(-2px); box-shadow: var(--sombra-2); border-color: var(--borda-forte); }
.guia-cartao .emoji { font-size: 21px; display: block; margin-bottom: 9px; }
.guia-cartao h3 { font-size: 14.5px; margin-bottom: 4px; }
.guia-cartao p { font-size: 12.5px; color: var(--tinta-muda); margin: 0; line-height: 1.5; }

.passos-guia { counter-reset: passo; display: flex; flex-direction: column; gap: 14px; }
/* O item NÃO pode ser flex: quando o texto começa com <b>, o negrito vira um
   item de flex separado e o resto da frase cai numa coluna ao lado. Número
   absoluto + recuo preserva o texto correndo como texto. */
.passos-guia li {
  list-style: none; position: relative; padding-left: 38px;
  font-size: 14px; line-height: 1.6;
}
.passos-guia li::before {
  counter-increment: passo; content: counter(passo);
  position: absolute; left: 0; top: 1px;
  width: 25px; height: 25px; border-radius: 50%;
  background: var(--marca-fraca); color: var(--marca-tinta);
  font-family: var(--fonte-display); font-weight: 700; font-size: 13px;
  display: grid; place-items: center; margin-top: 1px;
}
.tecla {
  display: inline-flex; align-items: center; gap: 4px; vertical-align: baseline;
  background: var(--superficie-3); border: 1px solid var(--borda); border-radius: 6px;
  padding: 1px 7px; font-size: 12.5px; font-weight: 700; white-space: nowrap;
}
.tecla.marca { background: var(--marca); border-color: var(--marca); color: #fff; }
.tecla.bom { background: var(--bom-tinta); border-color: var(--bom-tinta); color: #fff; }

/* ==========================================================================
   Login
   ========================================================================== */

.tela-login {
  min-height: 100dvh; display: grid; grid-template-columns: 1.05fr .95fr;
  background: var(--plano);
}
.login-arte {
  position: relative; overflow: hidden; display: flex; flex-direction: column; justify-content: space-between;
  padding: 44px; color: #fff;
  /* Um bloco de cor, e só. Antes era um degradê radial de três paradas com um
     padrão de bolinhas mascarado por cima e a inicial da marca em 260px
     girada — três camadas de enfeite numa tela cuja única função é receber
     usuário e senha. */
  background: var(--marca);
}
.login-arte .fatia { display: none; }
.login-arte .selo-marca { display: flex; align-items: center; gap: 12px; position: relative; z-index: 1; }
.login-arte .selo-marca .quadro {
  width: 42px; height: 42px; border-radius: 13px; display: grid; place-items: center; font-size: 22px;
  background: rgba(255,255,255,.18); backdrop-filter: blur(6px); border: 1px solid rgba(255,255,255,.28);
}
.login-arte h2 {
  font-size: clamp(30px, 3.6vw, 46px); line-height: 1.06; letter-spacing: -.035em;
  max-width: 12ch; position: relative; z-index: 1;
}
.login-arte .frase { font-size: 15px; opacity: .88; max-width: 34ch; margin-top: 14px; line-height: 1.55; position: relative; z-index: 1; }
.login-arte .rodape { font-size: 12.5px; opacity: .7; position: relative; z-index: 1; }

.login-lado { display: grid; place-items: center; padding: 40px 24px; }
.login-caixa { width: 100%; max-width: 372px; }
.login-caixa .oi { font-size: 13px; font-weight: 700; letter-spacing: .1em; text-transform: uppercase; color: var(--marca); }
.login-caixa h1 { font-size: 29px; letter-spacing: -.03em; margin: 6px 0 6px; }
.login-caixa .sub { font-size: 14px; color: var(--tinta-muda); margin: 0 0 26px; line-height: 1.5; }
.login-caixa form { display: flex; flex-direction: column; gap: 15px; }
.login-caixa .entrada { padding: 12px 14px; font-size: 15px; }
.senha-campo { position: relative; }
.senha-campo .entrada { padding-right: 46px; }
.senha-campo .olho {
  position: absolute; right: 6px; top: 50%; transform: translateY(-50%);
  border: 0; background: none; cursor: pointer; padding: 7px 9px; border-radius: var(--r-sm); font-size: 15px;
}
.senha-campo .olho:hover { background: var(--superficie-3); }
.login-caixa .lembrar { display: flex; align-items: center; gap: 8px; font-size: 13.5px; color: var(--tinta-2); cursor: pointer; }
.login-caixa .lembrar input { width: 16px; height: 16px; accent-color: var(--marca); }
.login-caixa .recado { font-size: 12.5px; color: var(--tinta-muda); text-align: center; margin-top: 22px; line-height: 1.6; }

@media (max-width: 900px) {
  .tela-login { grid-template-columns: 1fr; }
  .login-arte { padding: 26px 22px 30px; min-height: 210px; }
  .login-arte h2 { font-size: 26px; max-width: none; }
  .login-arte .frase, .login-arte .rodape { display: none; }
  .login-arte .fatia { font-size: 170px; right: -40px; bottom: -70px; }
  .login-lado { padding: 30px 20px 50px; place-items: start center; }
}

/* ==========================================================================
   Utilitários
   ========================================================================== */

.so-leitor {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.mudo { color: var(--tinta-muda); }
.apoio { font-size: 12.5px; color: var(--tinta-muda); }
.forte { font-weight: 700; }
.centro { text-align: center; }
.sem-quebra { white-space: nowrap; }
.corta { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.clicavel { cursor: pointer; }
.so-mobile { display: none; }
@media (max-width: 820px) { .so-desktop { display: none !important; } .so-mobile { display: initial; } }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}

/* ==========================================================================
   Cardápio — lista agrupada por categoria
   Um cardápio real tem 150+ itens; tabela corrida vira parede. A categoria
   é a unidade em que a pessoa pensa ("as bebidas estão pausadas"), então é
   nela que a lista dobra e é nela que a ação em massa mora.
   ========================================================================== */

.grupo-cat { border: 1px solid var(--borda); border-radius: var(--r-md); overflow: hidden; margin-bottom: 10px; }
.grupo-cat:last-child { margin-bottom: 0; }

.cat-topo {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  padding: 9px 12px; background: var(--superficie-2); border-bottom: 1px solid var(--borda);
}
.grupo-cat.fechada .cat-topo { border-bottom: 0; }
.grupo-cat.fechada .cat-corpo { display: none; }

.cat-abrir {
  display: flex; align-items: center; gap: 9px; min-width: 0;
  border: 0; background: none; cursor: pointer; padding: 3px 2px; text-align: left;
  font: inherit; color: var(--tinta);
}
.cat-abrir:hover .cat-nome { color: var(--marca-tinta); }
/* A SETA PRECISA PARECER UM BOTÃO.
   Recolher categoria já existia, e o cliente pediu como funcionalidade nova —
   sinal de que ninguém achava o gatilho. Ele era um caractere de 11px em
   cinza-mudo, do tamanho de pontuação, encostado no nome.
   Agora tem área de toque própria, contorno no hover e tamanho de ícone. O
   comportamento é o mesmo; o que faltava era anunciar que existia. */
.cat-abrir .seta {
  font-size: 15px; line-height: 1; color: var(--tinta-muda);
  transition: transform .16s, background .12s, color .12s;
  flex: none; width: 22px; height: 22px; border-radius: 6px;
  display: grid; place-items: center;
}
.cat-abrir:hover .seta { background: var(--superficie-2); color: var(--tinta); }
.grupo-cat.fechada .cat-abrir .seta { transform: rotate(-90deg); }
.cat-nome { font-weight: 700; font-size: 14px; letter-spacing: -.01em; }
.cat-conta { font-size: 12.5px; color: var(--tinta-muda); white-space: nowrap; }
.cat-conta .pausados { color: var(--atencao-tinta); font-weight: 700; }

/* O campo de preço na linha ocupa o mesmo lugar do botão que substituiu:
   a linha não pode pular quando alguém clica pra editar. */
.preco-na-linha {
  width: 92px; padding: 4px 8px; text-align: right;
  font-size: 13.5px; font-weight: 600;
}

.item-linha {
  display: grid; align-items: center; gap: 10px;
  /* estado encolheu de 230px pra 170px: agora carrega um resumo curto
     ("2 no ar · 1 pausada"), não uma lista de lojas — e a folga foi pro nome */
  grid-template-columns: 26px minmax(0, 1fr) 108px minmax(0, 170px) auto;
  padding: 8px 12px; border-bottom: 1px solid var(--grade);
  transition: background .12s;
}

/* A ALÇA DE ARRASTAR CATEGORIA.
   Arrastar item não existe: a integração aceita a chamada de ordem, responde
   200 e ignora o valor. Categoria funciona, e é o nível que o cliente final
   percebe primeiro. */
.alca-cat {
  cursor: grab; color: var(--tinta-muda); font-size: 15px; line-height: 1;
  user-select: none; flex: none; padding: 2px;
}
.alca-cat:active { cursor: grabbing; }
.cat-topo:hover .alca-cat { color: var(--tinta); }
.grupo-cat.arrastando { opacity: .5; outline: 2px dashed var(--borda-forte); outline-offset: 2px; }
.item-linha:last-child { border-bottom: 0; }
.item-linha:hover { background: var(--superficie-2); }
.item-linha.marcado { background: var(--marca-fraca); }
.item-linha.diverge { box-shadow: inset 3px 0 0 var(--atencao); }

.item-linha .marcador { display: grid; place-items: center; cursor: pointer; padding: 4px; }
.item-linha .marcador input { width: 16px; height: 16px; accent-color: var(--marca); cursor: pointer; }

.item-nome {
  border: 0; background: none; cursor: pointer; text-align: left; padding: 2px 0;
  font: inherit; font-weight: 650; font-size: 14px; color: var(--tinta);
  display: flex; align-items: center; gap: 7px; min-width: 0;
  /* `wrap` porque o selo "≠ difere entre lojas" não encolhe (e não deve: é uma
     frase). Sem isto, nome comprido em tela estreita empurrava o selo pra fora
     da coluna, por cima do preço. Agora ele desce pra própria linha e o nome
     continua inteiro — cortar o nome do item seria pior que ganhar uma linha. */
  flex-wrap: wrap;
}
.item-nome:hover { color: var(--marca-tinta); text-decoration: underline; }
.item-nome .selo { flex: none; max-width: 100%; }

.item-preco {
  border: 1px solid transparent; background: none; cursor: pointer;
  padding: 4px 8px; border-radius: var(--r-sm); font: inherit; font-size: 13.5px;
  color: var(--tinta-2); text-align: right; white-space: nowrap;
  display: inline-flex; align-items: center; justify-content: flex-end; gap: 5px;
}
.item-preco:hover { border-color: var(--borda-forte); background: var(--superficie); color: var(--tinta); }
.item-preco .lapis { opacity: 0; font-size: 12px; transition: opacity .12s; }
.item-linha:hover .item-preco .lapis { opacity: .55; }

/* O estado agora é UM resumo curto, não uma pilha de selos com nome de loja.
   Uma frase discreta, colorida pelo estado — calma o suficiente pra não brigar
   com o nome e o preço, clara o bastante pra bater o olho. */
.item-estado { display: flex; min-width: 0; }
.estado-resumo {
  display: inline-flex; align-items: center; gap: 5px; min-width: 0;
  font-size: 12.5px; font-weight: 600; white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis; color: var(--tinta-2);
}
.estado-resumo .ic { font-size: 17px; flex: none; }
.estado-resumo.bom { color: var(--bom-tinta); }
.estado-resumo.atencao { color: var(--atencao-tinta); }

/* menu "Mais" da barra de ações — âncora do menu flutuante que já existe */
/* números-chave da Visão Geral com um realce de cor (pedido do cliente) */
.kpi .valor.destaque-num { color: var(--marca-tinta); }
/* O NÚMERO CABE ANTES DE SER APARADO. Num cartão de 175px, "R$ 31.480,50" a
   25px passava 3px da caixa e o centavo saía cortado — e número cortado é
   número errado. `vw` não resolve: a janela é larga, quem é estreito é o
   cartão. Dois pontos a menos na fonte resolvem sem mudar a hierarquia. */
.kpi .valor.menor { font-size: 23px; }

/* insights de comportamento por pessoa (Engajamento) */
.insights-pessoa { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 5px; }
.insights-pessoa .selo { font-size: 11px; font-weight: 500; }
.insights-pessoa .ic { font-size: 12px; color: var(--marca-tinta); vertical-align: -1px; }

/* chips clicáveis de bairro (abrem o perfil do bairro) */
.chips-bairros { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 6px; }
.chip-bairro {
  border: 1px solid var(--borda); background: var(--superficie); cursor: pointer;
  border-radius: 999px; padding: 4px 11px; font: inherit; font-size: 12.5px; color: var(--tinta-2);
  transition: border-color .12s, background .12s;
}
.chip-bairro:hover { border-color: var(--marca); background: var(--marca-fraca); color: var(--marca-tinta); }
.chip-bairro .mudo { font-weight: 700; }

/* barrinha proporcional inline (ranking de produtos mais cancelados) */
/* `display: block` e `width` explícita, e não só `flex-basis`.
   A barra nasceu dentro de linhas flex, onde `flex: 0 0 90px` bastava. Dentro
   de uma CÉLULA de tabela não há contexto flex: o flex-basis é ignorado, o
   <span> volta a ser inline, a altura não vale e ela colapsa pra zero pixel.
   Foi o que aconteceu com a coluna "Peso no dinheiro" do funil do cliente —
   quatro linhas de coluna completamente vazia, com o cabeçalho prometendo
   um dado que nunca aparecia. Com as três declarações ela funciona nos dois. */
.barra-mini {
  display: block; width: 90px; flex: 0 0 90px;
  height: 7px; border-radius: 999px; background: var(--grade);
  position: relative; overflow: hidden;
}
/* A COR DA BARRA VOLTA A SIGNIFICAR ALGUMA COISA.
   Sete telas escrevem `barra-mini ${… ? 'grave' : ''}` — a linha do pior
   horário em vermelho, o resto neutro; a origem "a própria loja cancelou" em
   âmbar, as outras não. Só que `.grave` e `.atencao` NUNCA existiram aqui: o
   `::before` era vermelho fixo, e as sete condicionais não pintavam nada.
   Resultado: tudo vermelho, sempre — inclusive uma distribuição de faixas de
   recompra, onde não há nada de errado acontecendo. Vermelho em toda barra é o
   mesmo que vermelho em nenhuma: para de marcar a que importa. */
.barra-mini::before {
  content: ''; position: absolute; inset: 0 auto 0 0; width: var(--pct, 0%);
  background: var(--marca); opacity: .5; border-radius: 999px;
}
/* A régua de perfis do funil do cliente: uma barra só, repartida.
   Quatro barrinhas separadas fariam a pessoa comparar alturas; repartida, ela
   lê a PROPORÇÃO, que é a pergunta — quanto do movimento é gente nova. */
.barra-perfis {
  display: flex; height: 12px; border-radius: 999px; overflow: hidden;
  background: var(--grade); margin-top: 4px;
}
.barra-perfis > span { display: block; height: 100%; }

.barra-mini.grave::before   { background: var(--grave); opacity: .55; }

/* o número do trecho que estourou a régua da etapa, na ficha do pedido */
.texto-grave { color: var(--grave-tinta); }
.barra-mini.atencao::before { background: var(--atencao); opacity: .7; }

/* selo "obrigatório" ao lado do rótulo de um campo */
.obrig {
  font-size: 10.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .03em;
  color: var(--grave-tinta); background: var(--grave-fraco);
  padding: 1px 6px; border-radius: 999px; margin-left: 6px; vertical-align: 1px;
}

/* projeção do mês, acima do gráfico de faturamento */
.proj-mes {
  display: flex; align-items: baseline; gap: 8px 12px; flex-wrap: wrap;
  padding: 9px 12px; margin-bottom: 10px; border-radius: var(--r-md);
  background: var(--marca-fraca); border: 1px solid var(--borda);
}
.proj-mes .rotulo { font-size: 11.5px; font-weight: 700; text-transform: uppercase;
  letter-spacing: .04em; color: var(--marca-tinta); }
.proj-mes .valor { font-family: var(--fonte-display); font-size: 21px; color: var(--marca-tinta); }
.proj-mes .apoio { font-size: 12px; color: var(--tinta-2); flex: 1 1 200px; }

/* A META DO MÊS, logo abaixo da projeção.
   Mora colada nela de propósito: são o mesmo assunto — para onde o mês vai e
   para onde ele deveria ir — e separados por um cartão a pessoa teria que
   comparar dois números de memória. O tom muda com o desfecho: neutro quando a
   projeção alcança a meta, âmbar quando não alcança, verde quando já bateu. */
.meta-mes {
  padding: 10px 12px; margin: -4px 0 10px; border-radius: var(--r-md);
  border: 1px solid var(--borda); background: var(--superficie-2);
}
.meta-mes.atencao { border-color: var(--atencao); background: var(--atencao-fraco); }
.meta-mes.bom { border-color: var(--bom); background: var(--bom-fraco); }
.meta-mes .num { font-family: var(--fonte-display); font-size: 17px; }

/* UMA régua com DUAS marcas: a barra é o que já entrou, o risco é onde a
   projeção termina. Em dois gráficos separados, saber se o buraco fecha viraria
   conta de cabeça. */
.barra-meta {
  position: relative; height: 8px; border-radius: 999px;
  background: var(--grade); margin-top: 10px;
}
.barra-meta > .feito {
  display: block; height: 100%; border-radius: 999px;
  background: var(--marca); transition: width .25s ease;
}
.barra-meta > .projetado {
  position: absolute; top: -3px; bottom: -3px; width: 2px;
  background: var(--tinta-2); border-radius: 1px;
}
.meta-mes.atencao .barra-meta > .feito { background: var(--atencao); }
.meta-mes.bom .barra-meta > .feito { background: var(--bom); }

/* seletor de período compartilhado (hoje / 7d / 30d / personalizado) */
.seletor-periodo { display: inline-flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.seletor-periodo .faixa-datas .entrada { padding: 6px 8px; font-size: 13px; }

.menu-mais { position: relative; display: inline-flex; }
.menu-mais .menu-flutuante.abaixo { top: calc(100% + 6px); right: 0; left: auto; }

.item-acoes { display: flex; gap: 6px; justify-content: flex-end; white-space: nowrap; }

@media (max-width: 900px) {
  .item-linha { grid-template-columns: 26px minmax(0, 1fr) auto; }
  .item-linha .item-preco { grid-column: 3; justify-self: end; }
  .item-linha .item-estado { grid-column: 2 / -1; }
  .item-linha .item-acoes { grid-column: 2 / -1; justify-content: flex-start; padding-bottom: 2px; }
  .cat-topo .btn { flex: 1; justify-content: center; }
}


/* ==========================================================================
   Ícone de explicação (ⓘ) — o padrão que o cliente pediu nas telas do Base:
   passar o mouse e entender pra que serve, sem sair da tela.
   ========================================================================== */

/* O TÍTULO QUE TEM UM "i" VIRA UMA LINHA FLEX.
   O botão é uma caixa de 16px empurrada por `vertical-align` — um número fixo
   que só acertava numa fonte. Num h2 de 15,5px ele descia 5px abaixo do meio da
   palavra, e a tela inteira ficava com bolinhas afundadas ao lado dos títulos.
   Centrando pelo flex, o alinhamento passa a valer em qualquer tamanho de
   letra: medido, o desvio caiu de 5,4px para 0,1px. */
h2:has(> .explica),
.principal:has(> .explica) { display: flex; align-items: center; flex-wrap: wrap; }

.explica {
  display: inline-flex; align-items: center; justify-content: center;
  width: 16px; height: 16px; flex: none; vertical-align: middle; margin-left: 5px;
  border-radius: 50%; border: 1px solid var(--borda-forte);
  font-size: 10.5px; font-weight: 700; font-family: var(--fonte);
  color: var(--tinta-muda); background: var(--superficie);
  cursor: help; position: relative; padding: 0;
}
.explica:hover, .explica:focus-visible {
  border-color: var(--info); color: var(--info-tinta); background: var(--info-fraco);
}

/* O BALÃO DE AJUDA, filho do <body>.
   Nenhum cartão o recorta, e a posição é medida em JavaScript a cada abertura
   (ver `posicionarAjuda`, em ui.js). Azul claro no lugar do preto: ele é
   informação de apoio, não alerta. O azul separa o balão da página sem gritar,
   e o texto quase preto sobre fundo claro é o que se lê sem cansar. */
.ajuda-flutuante {
  position: fixed; z-index: 200; max-width: min(320px, 92vw);
  background: color-mix(in srgb, var(--info) 13%, white);
  color: var(--tinta);
  border: 1px solid color-mix(in srgb, var(--info) 38%, white);
  border-radius: var(--r-md);
  padding: 11px 14px;
  font-size: 12.5px; font-weight: 500; line-height: 1.55; letter-spacing: 0; text-align: left;
  box-shadow: 0 10px 30px rgba(20, 55, 105, .16), 0 2px 6px rgba(20, 55, 105, .08);
  opacity: 0; visibility: hidden; transform: translateY(2px);
  transition: opacity .13s ease, transform .13s ease, visibility .13s;
  pointer-events: none;      /* o balão nunca rouba o mouse de quem está lendo */
}
.ajuda-flutuante.ver { opacity: 1; visibility: visible; transform: translateY(0); }
.ajuda-flutuante b, .ajuda-flutuante strong { color: var(--info-tinta); }

/* a seta é um quadrado girado com as MESMAS duas bordas do balão: assim ela
   parece um bico do próprio balão, e não um losango pousado em cima dele */
.ajuda-flutuante .seta {
  position: absolute; width: 10px; height: 10px; transform: translateX(-50%) rotate(45deg);
  background: color-mix(in srgb, var(--info) 13%, white);
  border: 1px solid color-mix(in srgb, var(--info) 38%, white);
}
.ajuda-flutuante:not(.abaixo) .seta { bottom: -6px; border-top: 0; border-left: 0; }
.ajuda-flutuante.abaixo .seta { top: -6px; border-bottom: 0; border-right: 0; }

@media (prefers-reduced-motion: reduce) {
  .ajuda-flutuante { transition: none; transform: none; }
}

/* ==========================================================================
   Permissões na tela — o servidor é quem barra de verdade; aqui a gente só
   evita oferecer botão que a pessoa não pode usar.
   ========================================================================== */
/* `item-status` faltava nesta lista e estava marcado em três botões dos
   Complementos: o botão aparecia pra quem não podia pausar e o 403 do servidor
   chegava como erro no rosto de quem clicou. A lista aqui precisa cobrir a
   ACOES_PERMISSAO inteira do auth.js — o que sobra dela vira botão-armadilha. */
body:not(.pode-item-status)  [data-precisa="item-status"],
body:not(.pode-item-preco)   [data-precisa="item-preco"],
body:not(.pode-item-criar)   [data-precisa="item-criar"],
body:not(.pode-item-excluir) [data-precisa="item-excluir"],
body:not(.pode-item-editar)  [data-precisa="item-editar"],
body:not(.pode-loja-horario) [data-precisa="loja-horario"],
body:not(.pode-loja-pausa)   [data-precisa="loja-pausa"],
body:not(.pode-regras)       [data-precisa="regras"] { display: none !important; }


/* Botão que se lê como link: ação secundária dentro de um cartão. */
.ligacao {
  background: none; border: 0; padding: 0; cursor: pointer;
  font: inherit; font-size: 12px; font-weight: 600; color: var(--marca-tinta);
  text-decoration: underline; text-underline-offset: 2px;
}
.ligacao:hover { color: var(--marca); }
/* Ícone dentro de link de texto. O sublinhado do link atravessa o glifo e lê
   como risco, não como link — e `text-decoration: none` no filho não apaga a
   linha do PAI. Então quem ganha ícone abre mão do sublinhado: o ícone mais a
   cor da marca já dizem que ali se clica, e no hover a cor muda. */
.ligacao { display: inline-flex; align-items: center; gap: 5px; text-align: left; }
.ligacao .ico { font-size: 15px; flex: none; }
.ligacao:has(.ico) { text-decoration: none; }
.ligacao:has(.ico):hover { text-decoration: none; color: var(--marca); }
.ligacao.perigo { color: var(--grave-tinta); }
.ligacao.perigo:hover { color: var(--grave); }

/* ==========================================================================
   Threads — lista de conversas à esquerda, conversa aberta à direita.
   No celular vira uma coluna só: a lista some quando há conversa aberta.
   ========================================================================== */
/* ==========================================================================
   Threads — a lista de assuntos e a conversa aberta, no painel de duas colunas
   ========================================================================== */
/* o rail das conversas é mais largo que o de canais: aqui cada linha carrega
   título, prévia e hora, e não só o nome do canal */
/* A lista rola SOZINHA, e é ela que precisa: são dezenas de assuntos, e sem
   altura o painel crescia até empurrar a conversa pra fora da janela — pra ler
   a última mensagem a pessoa rolava a página inteira, passando por toda a
   lista. Com o painel preso à janela, cada coluna rola no seu canto. */
.conversas { --largura-rail: 296px; align-items: stretch; }

.coluna-lista {
  display: flex; flex-direction: column; gap: 10px; min-width: 0; min-height: 0;
  padding: 14px 10px; background: var(--superficie-2);
  border-right: 1px solid var(--borda);
}
/* a busca e o botão ocupam a largura toda: são o cabeçalho do rail, e meia
   largura cada deixava os dois apertados sem ganhar nada */
.busca-lista { position: relative; display: flex; align-items: center; }
.busca-lista .ic { position: absolute; left: 11px; font-size: 18px; color: var(--tinta-muda); pointer-events: none; }
.busca-lista .entrada { width: 100%; padding-left: 36px; }
.coluna-lista > .btn.primario { width: 100%; }
.coluna-lista .segmentado:empty { display: none; }
/* a lista rola sozinha; o resto do rail fica parado */
.coluna-lista #listaThreads { flex: 1; min-height: 0; overflow-y: auto; margin: 0 -4px; padding: 0 4px; }

.item-thread {
  display: flex; gap: 10px; width: 100%; text-align: left; align-items: flex-start;
  padding: 9px 10px; border: 1px solid transparent; border-radius: var(--r-md);
  background: none; cursor: pointer; font: inherit; color: inherit;
  transition: background .12s, border-color .12s;
}
.item-thread:hover { background: var(--superficie-3); }
.item-thread.ativa { background: var(--marca-fraca); border-color: color-mix(in srgb, var(--marca) 26%, transparent); }
/* o ícone num quadrado arredondado, como no desenho — o mesmo pra toda conversa:
   é o que faz a coluna ler como uma lista, e não como um mosaico */
.item-thread .marca-thread {
  width: 30px; height: 30px; flex: none; border-radius: var(--r-sm);
  display: grid; place-items: center;
  background: var(--superficie-3); color: var(--tinta-2);
}
.item-thread.ativa .marca-thread { background: var(--superficie); color: var(--marca-tinta); }
.item-thread .marca-thread .ic { font-size: 17px; }
.item-thread .miolo { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1; }
.item-thread .topo { display: flex; align-items: center; gap: 5px; }
.item-thread .topo b {
  font-size: 13.5px; min-width: 0; flex: 1;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.item-thread .etiqueta { font-size: 14px; color: var(--tinta-muda); flex: none; }
.item-thread .topo .selo { flex: none; background: var(--marca); color: #fff; }
.item-thread .previa-msg,
.item-thread .rodape-item {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 12.5px;
}
.item-thread .previa-msg { color: var(--tinta-muda); }
.item-thread .rodape-item { font-size: 11px; color: var(--tinta-muda); }

.coluna-conversa { display: flex; flex-direction: column; min-width: 0; min-height: 0; }
/* mesma faixa de cabeçalho do outro painel: as duas colunas emendam retas */
.cabeca-thread {
  display: flex; align-items: center; gap: 11px; flex-wrap: wrap;
  min-height: var(--faixa-painel); padding: 8px var(--recuo-painel);
  border-bottom: 1px solid var(--borda);
}
.cabeca-thread > .ic { font-size: 20px; color: var(--tinta-muda); flex: none; }
.cabeca-thread .quem-thread { min-width: 0; flex: 1; }
.cabeca-thread .quem-thread b { display: block; font-size: 15px; line-height: 1.3; }
.cabeca-thread .quem-thread .apoio { display: block; font-size: 12.5px; line-height: 1.35; }
.cabeca-thread .acoes { flex: none; }

.sla-thread { padding: 10px var(--recuo-painel) 0; }
.aviso-fechada {
  display: flex; align-items: center; gap: 10px;
  margin: 0 var(--recuo-painel) var(--recuo-painel);
  padding: 12px 14px; border-radius: var(--r-md);
  background: var(--superficie-2); border: 1px solid var(--borda);
  font-size: 13px; color: var(--tinta-muda);
}
.aviso-fechada .ic { font-size: 19px; flex: none; }
.caixa-resposta { margin: 0 var(--recuo-painel) var(--recuo-painel); }

.mensagens {
  display: flex; flex-direction: column; gap: 14px;
  flex: 1; min-height: 0; overflow-y: auto;
  padding: 4px var(--recuo-painel) 14px;
}
.mensagem { display: flex; gap: 10px; }
/* um pouco menor que o do mural: a conversa tem muitas linhas seguidas */
.mensagem .avatar-post { width: 34px; height: 34px; font-size: 12px; }
.mensagem .corpo { min-width: 0; flex: 1; }
.mensagem .quem { display: flex; gap: 6px; align-items: baseline; font-size: 12.5px; margin-bottom: 2px; }
.mensagem .quem .mudo { font-size: 11.5px; color: var(--tinta-muda); font-weight: 500; }
.mensagem .texto { font-size: 14px; line-height: 1.55; overflow-wrap: anywhere; }
.mensagem .texto a { color: var(--marca-tinta); }

/* a primeira mensagem é a abertura do assunto: fundo próprio, como um post */
/* sem caixa na primeira mensagem: o desenho trata todas iguais, e o realce
   competia com o cabeçalho do assunto logo acima */
.mensagem.abertura .texto { color: var(--tinta); }
.mensagem.abertura .texto { font-size: 14.5px; }

.mensagem .pe { display: flex; align-items: center; gap: 10px; margin-top: 5px; }
.mensagem .reacoes { display: flex; gap: 4px; flex-wrap: wrap; }
.reacao {
  border: 1px solid var(--borda); background: var(--superficie);
  border-radius: 999px; padding: 1px 8px; font-size: 12px; cursor: pointer;
  line-height: 1.7; color: var(--tinta-2);
}
.reacao:hover { border-color: var(--borda-forte); background: var(--superficie-2); }
.reacao.adicionar { opacity: 0; transition: opacity .12s; }
.mensagem:hover .reacao.adicionar, .reacao.adicionar:focus-visible { opacity: 1; }
.mensagem .editar-msg { margin-left: auto; opacity: 0; transition: opacity .12s; }
.mensagem:hover .editar-msg, .mensagem .editar-msg:focus-within { opacity: 1; }

.caixa-resposta { display: flex; gap: 8px; align-items: flex-end; }
.caixa-resposta textarea { resize: none; min-height: 42px; width: 100%; }
/* o textarea agora vem embrulhado pra ancorar a lista de @ — o wrapper é que
   precisa esticar, senão ele encolhe e o botão Enviar come a caixa toda */
.caixa-resposta .caixa-mencao { flex: 1; min-width: 0; }
/* e ali a lista abre pra CIMA: embaixo da caixa de resposta é o fim da tela */
.caixa-resposta .sugestoes-mencao { top: auto; bottom: 100%; margin: 0 0 4px; }

.tags-thread { display: flex; flex-wrap: wrap; gap: 4px; margin: 1px 0 2px; }

/* ------------------------------------------------- cardápio da IA ("não entendi") */
/* Três sugestões soltas passavam a impressão de que ela só sabia aquilo. O
   cardápio por assunto mostra o alcance, e cada exemplo é clicável — a pessoa
   aprende o formato usando, não lendo instrução. */
.capacidades { display: flex; flex-direction: column; gap: 14px; margin-top: 16px;
  border-top: 1px solid var(--grade); padding-top: 14px; }
.capacidades .grupo { display: flex; flex-direction: column; gap: 7px; }
.capacidades .grupo > b {
  font-size: 11px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
  color: var(--tinta-muda);
}
.capacidades .exemplos { display: flex; flex-wrap: wrap; gap: 6px; }
.resposta-valor.menor { font-size: 19px; line-height: 1.35; }

/* ------------------------------------------------------ pausados e matriz BCG */
.lista-item.alinha-topo { align-items: flex-start; }
.miolo-pausado { display: flex; flex-direction: column; gap: 6px; width: 100%; min-width: 0; }
/* O cabeçalho do item: nome, categoria e a contagem. Uma cor só — a categoria
   virou texto de apoio em vez de mais um selo, senão três cores brigam numa
   linha que só precisa dizer QUAL item e QUANTO dele está fora do ar. */
.cabeca-item { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
.cabeca-item .apoio { font-size: 12.5px; }

/* GRADE DE VERDADE, cinco colunas fixas.
   Era `flex-wrap`, e aí cada loja tinha a largura do próprio nome: a segunda
   linha nunca casava com a primeira, e entre um item e outro nada se alinhava.
   Com cinco colunas iguais, a mesma loja cai sempre na mesma coluna e a leitura
   vertical funciona — que é o que permite bater o olho e ver qual caixinha
   ficou desmarcada. */
.ocorrencias { display: grid; grid-template-columns: repeat(5, 1fr); gap: 6px; }
@media (max-width: 1180px) { .ocorrencias { grid-template-columns: repeat(3, 1fr); } }
@media (max-width: 720px)  { .ocorrencias { grid-template-columns: repeat(2, 1fr); } }

/* Cada ocorrência é uma loja. SEM borda vermelha: com sete lojas pausadas eram
   sete molduras vermelhas idênticas repetindo o que o selo do cabeçalho já
   disse ("7 de 7 pausados"), e o que some no meio do vermelho é justamente a
   exceção — a loja que NÃO está pausada. Quem carrega o estado agora é o
   pontinho, que informa sem gritar. */
.ocorrencia {
  display: flex; align-items: center; gap: 7px; cursor: pointer; min-width: 0;
  padding: 4px 10px; border: 1px solid var(--borda); border-radius: 20px;
  font-size: 12px; background: var(--superficie);
}
.ocorrencia:hover { border-color: var(--borda-forte); }
.ocorrencia .loja {
  font-weight: 600; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ocorrencia input { position: absolute; opacity: 0; width: 0; height: 0; }
/* sem isto o "✓" fica visível o tempo todo — a caixinha só existe como estilo
   dentro de .opcao/.linha-loja, e aqui virava texto solto em toda ocorrência */
.ocorrencia .marca-check {
  width: 15px; height: 15px; flex: none; border-radius: 5px;
  border: 1.5px solid var(--borda-forte); background: var(--superficie);
  display: grid; place-items: center; font-size: 10px; color: transparent;
  transition: background .12s, border-color .12s, color .12s;
}
.ocorrencia:has(input:checked) { border-color: var(--marca); background: var(--marca-fraca); }
.ocorrencia:has(input:checked) .marca-check { background: var(--marca); border-color: var(--marca); color: #fff; }
.ocorrencia:has(input:focus-visible) { outline: 2px solid var(--marca); outline-offset: 2px; }

/* ------------------------------------------------------------------ provas */
.prova { display: flex; flex-direction: column; gap: 14px; }
.pergunta {
  border: 1px solid var(--borda); border-radius: var(--r-md);
  padding: 12px 14px 10px; margin: 0; min-width: 0;
}
.pergunta legend { font-weight: 700; font-size: 13.5px; padding: 0 6px; }
/* a pergunta que a pessoa deixou em branco, ao tentar enviar */
.pergunta.faltando { border-color: var(--atencao); background: var(--atencao-fraco); }
.pergunta.acertou  { border-color: color-mix(in srgb, var(--bom) 40%, transparent); }
.pergunta.errou    { border-color: color-mix(in srgb, var(--grave) 40%, transparent); }

.opcao-prova {
  display: flex; align-items: center; gap: 9px; padding: 6px 4px;
  cursor: pointer; font-size: 13.5px;
}
.opcao-prova input[type=radio] { position: absolute; opacity: 0; width: 0; height: 0; }
.marca-radio {
  width: 16px; height: 16px; flex: none; border-radius: 50%;
  border: 2px solid var(--borda-forte); background: var(--superficie);
  display: grid; place-items: center; transition: border-color .12s;
}
.opcao-prova input:checked + .marca-radio {
  border-color: var(--marca);
  box-shadow: inset 0 0 0 3px var(--marca);
}
.opcao-prova:hover .marca-radio { border-color: var(--marca); }
/* no gabarito não há rádio pra marcar: a opção certa se pinta sozinha */
.opcao-prova.certa { font-weight: 700; }
.opcao-prova.certa .marca-radio { border-color: var(--bom); box-shadow: inset 0 0 0 3px var(--bom); }
.gabarito .opcao-prova { cursor: default; }

.opcoes-editor { display: flex; flex-direction: column; gap: 4px; margin-top: 8px; }
.pergunta.editor .enunciado { margin-top: 4px; }
.pergunta.editor .opcao-texto { flex: 1; min-width: 0; }
.pergunta.editor .pe { margin-top: 8px; display: flex; gap: 12px; }

.rotulo-quadrante { font-size: 10.5px; font-weight: 700; fill: var(--tinta-muda); }
#grafico svg text.eixo { font-size: 10.5px; fill: var(--tinta-muda); }
#grafico svg { font-family: var(--fonte); }

.paleta-emoji { display: flex; flex-wrap: wrap; gap: 6px; }
.emoji-opcao {
  font-size: 22px; padding: 6px 9px; border: 1px solid var(--borda);
  background: var(--superficie); border-radius: var(--r-sm); cursor: pointer; line-height: 1;
}
.emoji-opcao:hover { background: var(--superficie-2); border-color: var(--borda-forte); }

/* ==========================================================================
   Videoaulas
   ========================================================================== */
.grade-aulas {
  display: grid; gap: 12px;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
}
.aula {
  border: 1px solid var(--borda); border-radius: var(--r-md);
  overflow: hidden; display: flex; flex-direction: column; background: var(--superficie);
}
.aula.vista { border-color: color-mix(in srgb, var(--bom) 34%, var(--borda)); }
.aula .capa {
  position: relative; display: block; width: 100%; padding: 0; border: 0; cursor: pointer;
  aspect-ratio: 16 / 9; background: var(--superficie-3); overflow: hidden;
}
.aula .capa img { width: 100%; height: 100%; object-fit: cover; display: block; }
.aula .capa .play {
  position: absolute; inset: 0; margin: auto; width: 44px; height: 44px;
  display: grid; place-items: center; border-radius: 50%;
  background: rgba(15,18,22,.62); color: #fff; font-size: 16px; padding-left: 3px;
  transition: transform .14s, background .14s;
}
.aula .capa:hover .play { transform: scale(1.08); background: var(--marca); }
.aula .capa .duracao,
.aula .capa .feito {
  position: absolute; bottom: 6px; font-size: 11px; font-weight: 600;
  padding: 2px 6px; border-radius: var(--r-sm); color: #fff;
}
.aula .capa .duracao { right: 6px; background: rgba(15,18,22,.72); }
.aula .capa .feito { left: 6px; background: var(--bom); }
.aula .miolo { padding: 10px 11px; display: flex; flex-direction: column; gap: 5px; flex: 1; }
.aula .miolo b { font-size: 14px; line-height: 1.35; }
.aula .miolo .apoio { font-size: 12px; }
.aula .pe { display: flex; align-items: center; gap: 8px; margin-top: auto; padding-top: 6px; }

/* 16:9 dentro do modal, sem depender de altura fixa */
.player { position: relative; aspect-ratio: 16 / 9; background: #000; border-radius: var(--r-md); overflow: hidden; }
.player iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }

@media (max-width: 900px) {
  /* empilhar é regra da moldura, junto com a de Novidades */
  .coluna-lista { position: static; max-height: 46vh; }
  .mensagens { max-height: none; }
}

/* ==========================================================================
   Investimentos
   ========================================================================== */
/* KPI fora da meta: a borda diz o que o número sozinho não diz */
.kpi.alerta { border-color: color-mix(in srgb, var(--grave) 40%, var(--borda)); background: var(--grave-fraco); }
.kpi.alerta .valor { color: var(--grave-tinta); }

#avisos:not(:empty) { display: flex; flex-direction: column; gap: 8px; }

.linha-investimento {
  display: flex; gap: 11px; align-items: flex-start; flex-wrap: wrap;
  padding: 12px 14px; border: 1px solid var(--borda); border-radius: var(--r-md);
  border-left-width: 4px; border-left-color: var(--borda-forte);
}
/* CAIXA COM BORDA DENTRO DE LISTA RESPIRA.
   `.lista` não tem vão: quem separa `.lista-item` é o fio de baixo, e isso está
   certo pra linha de tabela. Mas quando o filho é uma caixa COM BORDA, sem vão
   a borda de um encosta na do outro e as duas viram uma só — some a divisão que
   a borda existia pra fazer. Dez pixels resolvem, e a regra fica num lugar só
   pra caixa nova nascer certa. */
.lista > .linha-investimento + .linha-investimento,
.lista > .item-conhecimento + .item-conhecimento,
.lista > .insight + .insight,
.lista > .item-agenda + .item-agenda,
.lista > .item-teste + .item-teste,
.lista > .achado + .achado { margin-top: 10px; }
.linha-investimento.bom     { border-left-color: var(--bom); }
.linha-investimento.atencao { border-left-color: var(--atencao); }
.linha-investimento.grave   { border-left-color: var(--grave); }
.linha-investimento .emoji { font-size: 20px; line-height: 1.2; flex: none; }
.linha-investimento .miolo { flex: 1 1 260px; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.linha-investimento .topo { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.linha-investimento .topo b { font-size: 14px; }

.linha-investimento .numeros { display: flex; gap: 18px; flex-wrap: wrap; align-items: flex-start; }
.linha-investimento .acoes { display: flex; align-items: center; gap: 2px; flex: none; }
.linha-investimento .celula { display: flex; flex-direction: column; min-width: 78px; }
.linha-investimento .celula .rotulo {
  font-size: 10.5px; text-transform: uppercase; letter-spacing: .04em;
  color: var(--tinta-muda); font-weight: 700;
}
.linha-investimento .celula b { font-size: 15px; }
.linha-investimento .celula.destaque b { font-size: 19px; color: var(--marca-tinta); }
.linha-investimento .acoes { display: flex; gap: 9px; align-items: center; }

/* ==========================================================================
   Agenda
   ========================================================================== */
.item-agenda {
  display: flex; gap: 11px; align-items: flex-start;
  padding: 11px 14px; border: 1px solid var(--borda); border-radius: var(--r-md);
  border-left-width: 4px; border-left-color: var(--info);
}
.item-agenda.feito    { border-left-color: var(--bom); }
.item-agenda.falhou   { border-left-color: var(--grave); }
.item-agenda.desfeito { border-left-color: var(--borda-forte); opacity: .72; }
.item-agenda .emoji { font-size: 19px; line-height: 1.2; flex: none; }
.item-agenda .miolo { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.item-agenda .topo { display: flex; align-items: center; gap: 7px; flex-wrap: wrap; }
.item-agenda .acoes { display: flex; gap: 9px; align-items: center; flex: none; }

/* ==========================================================================
   Insights e testes
   ========================================================================== */
.insight {
  display: flex; gap: 12px; align-items: flex-start;
  padding: 13px 15px; border: 1px solid var(--borda); border-radius: var(--r-md);
  border-left-width: 4px; border-left-color: var(--info);
}
.insight.grave   { border-left-color: var(--grave);   background: var(--grave-fraco); }
.insight.atencao { border-left-color: var(--atencao); background: var(--atencao-fraco); }
.insight.bom     { border-left-color: var(--bom); }
/* o raio herda a cor do nível: vermelho no urgente, âmbar no atenção */
.insight .emoji { font-size: 20px; line-height: 1.2; flex: none; color: var(--tinta-muda); }
.insight.grave .emoji   { color: var(--grave); }
.insight.atencao .emoji { color: var(--atencao); }
.insight.bom .emoji     { color: var(--bom); }
.insight .miolo { flex: 1; min-width: 0; }
.insight .miolo b { font-size: 14.5px; display: block; }
/* o número é a prova do achado: fica logo abaixo do título, com peso próprio */
.insight .numero { font-size: 12.5px; font-weight: 700; color: var(--tinta-2); margin: 2px 0 5px; }
.insight .apoio { margin: 0 0 5px; }
.insight .acao { margin: 0; font-size: 12.5px; font-weight: 600; color: var(--marca-tinta); }
/* a ação que NÃO leva a lugar nenhum não pode ter cor de link */
.insight .acao.sem-destino { color: var(--tinta-2); font-weight: 500; }
a.acao { display: inline-block; text-decoration: none; }
a.acao:hover { text-decoration: underline; text-underline-offset: 2px; }
.insight .acoes { flex: none; }

/* O CARTÃO DA LEITURA — e não os achados dentro dele.
   Com os achados pequenos, o cartão passou a ter o tamanho exato do conteúdo e
   ficou parecendo um rodapé entre dois blocos grandes. Aqui ele ganha porte sem
   inchar o que está dentro: mais respiro na borda e o cabeçalho no tamanho de um
   título de seção. */
.cartao:has(> .lista.duas-colunas) { padding: 24px 26px; }
.cartao:has(> .lista.duas-colunas) > .cartao-topo { margin-bottom: 18px; }
/* o título continua no tamanho dos outros títulos de cartão: crescer só o
   desta seção deixaria "Leitura do funil" maior que "O caminho do pedido",
   logo abaixo, e a página perderia a régua */

/* ACHADOS EM DUAS COLUNAS.
   Cinco ou seis achados empilhados viravam uma torre de cartão: a leitura
   inteira cabia numa tela, mas empurrava tudo que vem depois. Em duas colunas
   a mesma coisa ocupa metade da altura.
   O `gap` do grid substitui o `margin-top` que separa item de item na lista
   empilhada — mantê-lo somaria os dois e a coluna sairia desalinhada. */
.lista.duas-colunas {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 7px;
  /* `stretch` e não `start`: com alturas livres, o achado curto da esquerda
     terminava no meio do achado comprido da direita e a dupla saía torta. Assim
     os dois de uma mesma linha fecham na mesma altura, e a linha lê como linha. */
  align-items: stretch;
}
/* o `margin-top` que separa item de item na lista empilhada vem de um seletor
   com três classes (`.lista > .insight + .insight`); para desligá-lo aqui o
   seletor precisa pesar mais, senão o segundo item da PRIMEIRA linha desce 10px
   sozinho — que era exatamente o desalinhamento que se via no topo do cartão */
.lista.duas-colunas > * + *,
.lista.duas-colunas > .insight + .insight { margin-top: 0; }
@media (max-width: 900px) { .lista.duas-colunas { grid-template-columns: 1fr; } }

/* o achado miúdo: mesma informação, tipografia dois degraus abaixo */
.insight.miudo { padding: 8px 10px; gap: 8px; }
.insight.miudo .emoji { font-size: 15px; }
.insight.miudo .miolo b { font-size: 12.5px; line-height: 1.35; }
.insight.miudo .numero { font-size: 11.5px; margin: 1px 0 3px; }
.insight.miudo .apoio { font-size: 11.5px; line-height: 1.45; margin: 0 0 3px; }
.insight.miudo .acao { font-size: 11.5px; }

.item-teste {
  display: flex; gap: 12px; align-items: flex-start; flex-wrap: wrap;
  padding: 12px 14px; border: 1px solid var(--borda); border-radius: var(--r-md);
  border-left-width: 4px; border-left-color: var(--borda-forte);
}
.item-teste.rodando   { border-left-color: var(--info); }
.item-teste.terminado { border-left-color: var(--atencao); }
.item-teste.decidido  { border-left-color: var(--bom); }
.item-teste .miolo { flex: 1 1 320px; min-width: 0; display: flex; flex-direction: column; gap: 4px; }
.item-teste .topo { display: flex; align-items: center; gap: 7px; flex-wrap: wrap; }
.item-teste .topo b { font-size: 14px; }
.item-teste .acoes { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.item-teste .resultado {
  font-size: 13px; line-height: 1.5; padding: 7px 10px; border-radius: var(--r-sm);
  background: var(--superficie-2); border: 1px solid var(--borda);
}
.item-teste .resultado.bom  { background: var(--bom-fraco);   border-color: #c9e9c9; color: var(--bom-tinta); }
.item-teste .resultado.ruim { background: var(--grave-fraco); border-color: #f4cccb; color: var(--grave-tinta); }

/* Tabela comparativa: a cor marca quem está fora da curva, o texto diz o quanto */
.tabela.comparativa td.ruim  { background: var(--grave-fraco); color: var(--grave-tinta); font-weight: 700; }
.tabela.comparativa td.otimo { background: var(--bom-fraco);   color: var(--bom-tinta);   font-weight: 700; }
.chip-legenda {
  display: inline-block; width: 11px; height: 11px; border-radius: 3px;
  vertical-align: -1px; margin-right: 3px;
}
.chip-legenda.ruim  { background: var(--grave-fraco); border: 1px solid #f4cccb; }
.chip-legenda.otimo { background: var(--bom-fraco);   border: 1px solid #c9e9c9; }
/* loja sem volume: aparece, mas recuada — não é comparável, e a tabela diz isso */
.tabela.comparativa tr.sem-volume td { color: var(--tinta-muda); }

/* ==========================================================================
   Conhecimento, Novidades e Estratificação
   ========================================================================== */
.item-conhecimento {
  display: flex; gap: 12px; align-items: flex-start; flex-wrap: wrap;
  padding: 12px 14px; border: 1px solid var(--borda); border-radius: var(--r-md);
}
.item-conhecimento.novo { border-color: color-mix(in srgb, var(--marca) 35%, var(--borda)); }
/* o cartão inteiro é o botão de ler: o alvo deixa de ser um retângulo de 40px
   e passa a ser a linha toda, que é o que a pessoa já tenta clicar */
.item-conhecimento.abrivel { cursor: pointer; transition: border-color .14s, background .14s; }
.item-conhecimento.abrivel:hover { border-color: var(--borda-forte); background: var(--superficie-2); }
.item-conhecimento.abrivel:focus-visible { outline: 2px solid var(--marca); outline-offset: 2px; }
.item-conhecimento .emoji { font-size: 20px; line-height: 1.2; flex: none; }
.item-conhecimento .miolo { flex: 1 1 280px; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.item-conhecimento .topo { display: flex; align-items: center; gap: 7px; flex-wrap: wrap; }
.item-conhecimento .topo b { font-size: 14.5px; }
.item-conhecimento .miolo p { margin: 0; }
.item-conhecimento .pe { font-size: 12px; }
.item-conhecimento .acoes { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }

/* O CARTÃO DA LOJA distribui o que tem pela altura que tem.
   Os quatro terminam na mesma altura (a grade casa), mas o conteúdo é desigual:
   uma loja tem dois avisos, a vizinha nenhum. Encostado no topo, sobrava meia
   caixa em branco embaixo de umas e não de outras, e os botões de cada cartão
   caíam numa altura diferente — quem varre os quatro procurando "Pausar" tinha
   que caçar. Com os botões colados no rodapé, os quatro ficam na mesma linha e
   o texto ocupa o meio. */
.cartao-loja { display: flex; flex-direction: column; }
.cartao-loja .acoes-loja { margin-top: auto; padding-top: 12px; }

/* Os dois botões do topo do Drive lado a lado: "Novo artigo" e "Enviar arquivo"
   têm rótulos de larguras diferentes e ficavam desiguais. A medida mínima
   comum casa os dois sem esticar nenhum além do necessário. */
#novoArtigo, #novoArquivo { min-width: 168px; justify-content: center; }

/* texto de artigo: largura de leitura, não de planilha */
.texto-longo { max-width: 68ch; font-size: 14.5px; line-height: 1.7; }
.texto-longo p { margin: 0 0 12px; }
.texto-longo ul, .texto-longo ol { margin: 0 0 12px; padding-left: 22px; }
.texto-longo li { margin-bottom: 5px; }
.texto-longo a { color: var(--marca-tinta); }

/* Novidades: linha do tempo, porque a ordem é a informação */
/* ==========================================================================
   Central de novidades — canais à esquerda, mural à direita

   O formato de mural não é enfeite: a novidade é uma CONVERSA da casa com a
   equipe, e lida como conversa (quem falou, quando, o que respondeu) em vez de
   linha do tempo de sistema. A origem virou canal e sai do caminho de quem não
   quer trocar de assunto.
   ========================================================================== */
/* A MOLDURA das telas de duas colunas (Novidades e Threads). Uma caixa só, com
   a divisória por dentro — em vez de dois cartões soltos que nunca terminam na
   mesma altura. Quem muda a largura do rail, o recuo ou a profundidade mexe
   aqui, e as duas telas seguem. */
.painel-duplo,
.central-novidades {
  display: grid; grid-template-columns: var(--largura-rail, 208px) minmax(0, 1fr);
  background: var(--superficie); border: 1px solid var(--borda);
  border-radius: var(--r-lg); overflow: hidden; box-shadow: var(--sombra-cartao);
}

/* O PAINEL PRESO À JANELA, e cada coluna rolando por dentro.
   Sem isto o painel cresce com o conteúdo e quem rola é a página inteira: pra
   ler a última mensagem ou o post mais antigo a pessoa passa por toda a lista,
   e o cabeçalho do canal sai de vista. Só vale onde as duas colunas estão lado
   a lado — no celular elas viram uma embaixo da outra e a página rolar é o
   certo, por isso a consulta de largura.
   O `grid-template-rows` não é redundante com o `max-height`: sem ele a linha
   continua do tamanho do CONTEÚDO, o `overflow: hidden` só corta o excesso, e
   as colunas nunca ficam sabendo que têm um teto — então nada rola por dentro. */
/* Empilhar no celular vale para as duas telas, e precisa vir DEPOIS da moldura:
   as duas regras têm a mesma especificidade, então quem estava mais embaixo no
   arquivo ganhava. A consulta de mídia lá em cima, na seção das threads, era
   sobrescrita aqui — e a conversa ficava espremida numa letra por linha. */
@media (max-width: 900px) {
  /**
   * `minmax(0, 1fr)` E NÃO `1fr`, e a diferença aqui não é sutileza de CSS.
   *
   * `1fr` é `minmax(auto, 1fr)`, e esse `auto` é o min-content do conteúdo — a
   * coluna CRESCE até caber o filho mais teimoso, em vez de espremê-lo. Num
   * iPhone de 393px a coluna virava 594px dentro de uma caixa de 361px, e como
   * a moldura tem `overflow: hidden`, o excesso era CORTADO: a tela de
   * Novidades ficava com o título pela metade, "Comentar" virava "Cor", e nada
   * disso dava pra alcançar porque a página nem rolava pro lado.
   *
   * Medido: `grid-template-columns` computado em 593.562px numa janela de 393.
   * Passou despercebido porque a varredura visual só rodava em 1500px de
   * desktop — no dia em que o painel virou app de celular, a tela que a
   * operação usa nunca tinha sido medida.
   *
   * `min-width: 0` nos filhos é a outra metade: item de grid nasce com
   * `min-width: auto`, que é a mesma trava pelo lado de dentro.
   */
  .painel-duplo,
  .central-novidades { grid-template-columns: minmax(0, 1fr); }
  .painel-duplo > *,
  .central-novidades > * { min-width: 0; }
}

@media (min-width: 901px) {
  .painel-duplo,
  .central-novidades { max-height: var(--altura-painel); grid-template-rows: minmax(0, 1fr); }
  /* os canais são poucos hoje, mas a lista é aberta: quando passar da altura,
     rola no lugar em vez de esticar o painel */
  .canais #listaCanais { flex: 1; min-height: 0; overflow-y: auto; margin: 0 -4px; padding: 0 4px; }
}

/* sem recuo no topo: quem dá o respiro é a faixa da marca, com o MESMO valor
   do cabeçalho do feed — assim as duas colunas começam na mesma altura */
.canais {
  display: flex; flex-direction: column; min-height: 0;
  border-right: 1px solid var(--borda); background: var(--superficie-2); padding: 0 10px 14px;
}
/* A marca do rail e o cabeçalho do feed são a MESMA faixa, uma de cada lado da
   divisória. Alinhar por recuo não bastava: são textos de tamanhos diferentes
   em caixas de estrutura diferente, e a marca ficava 10px acima. Dando a
   ALTURA da faixa aos dois e centrando o conteúdo, a emenda fica reta sozinha. */
.canais-marca {
  min-height: var(--faixa-painel); padding: 0 8px;
  display: flex; flex-direction: column; justify-content: center;
}
.canais-marca b { display: block; font-size: 14.5px; letter-spacing: -.01em; }
.canais-marca .apoio { font-size: 12px; }
.canais-titulo {
  font-size: 10.5px; font-weight: 700; letter-spacing: .09em; text-transform: uppercase;
  color: var(--tinta-muda); padding: 14px 8px 6px;
}
.canal {
  display: flex; align-items: center; gap: 7px; width: 100%;
  border: 0; background: none; cursor: pointer; text-align: left;
  padding: 7px 9px; border-radius: var(--r-sm); margin-bottom: 1px;
  font: inherit; font-size: 13.5px; font-weight: var(--peso-nav); color: var(--tinta-2);
}
.canal:hover { background: var(--superficie-3); color: var(--tinta); }
.canal.ativo { background: var(--marca-fraca); color: var(--marca-tinta); }
.canal .cerquilha { color: var(--tinta-muda); font-weight: 700; flex: none; }
.canal.ativo .cerquilha { color: var(--marca-tinta); }
/* o nome do canal pode ser longo ("novidade-da-plataforma"): quebra em duas
   linhas em vez de esticar a coluna */
.canal .nome { min-width: 0; overflow-wrap: anywhere; }
.canal .ponto-canal {
  width: 7px; height: 7px; border-radius: 50%; background: var(--marca); flex: none; margin-left: auto;
}

.feed { display: flex; flex-direction: column; min-width: 0; min-height: 0; }
/* o rolo dos posts: o cabeçalho e os filtros ficam, o mural passa por baixo */
.rolo-feed { flex: 1; min-height: 0; overflow-y: auto; }
.feed-topo {
  display: flex; align-items: center; gap: 9px; flex-wrap: wrap;
  min-height: var(--faixa-painel); padding: 8px var(--recuo-painel);
  border-bottom: 1px solid var(--borda);
}
.feed-topo .cerquilha { font-size: 17px; color: var(--tinta-muda); font-weight: 700; }
.feed-topo b { font-size: 16px; letter-spacing: -.01em; }
.feed-topo .apoio { font-size: 12.5px; }
.feed .chips { display: flex; gap: 7px; flex-wrap: wrap; padding: 12px var(--recuo-painel); }
.feed .chips:empty { display: none; }
.feed .chips .chip.ativo { background: var(--tinta); border-color: var(--tinta); color: #fff; }

/* O agente de notícias é um AVISO, não parte do feed. Sem recuo ele encostava
   na borda do cabeçalho e nas laterais, e lia como uma faixa presa ao título em
   vez de um bloco à parte. Mesmo recuo lateral do mural, mais um respiro em
   cima. `:not(:empty)` porque quem não publica não recebe esse bloco — e um
   padding num div vazio abriria um buraco sem conteúdo. */
.feed #noticias:not(:empty) { padding: 14px var(--recuo-painel) 2px; }

/* O estado vazio NÃO é `.mural` — é um `.cartao` solto dentro do #lista. Sem
   isto ele nascia sem recuo: encostava no bloco de notícias e sangrava até as
   bordas do feed, desalinhado de tudo o mais. */
.feed #lista > .cartao { margin: 14px var(--recuo-painel) var(--recuo-painel); }

.mural { display: flex; flex-direction: column; padding: 4px var(--recuo-painel) var(--recuo-painel); }
/* o dia como faixa: a linha atravessa e o texto senta no meio dela */
.dia-mural {
  display: flex; align-items: center; gap: 12px;
  margin: 14px 0 10px; font-size: 12px; color: var(--tinta-muda);
}
.dia-mural::before, .dia-mural::after { content: ''; flex: 1; height: 1px; background: var(--grade); }

.post { display: flex; gap: 12px; padding: 12px 0; }
.post + .post { border-top: 1px solid var(--grade); }
/* Iniciais no lugar da foto: o painel não guarda retrato de ninguém.
   Regra solta, sem prender ao `.post`, porque as duas telas de mural usam —
   novidades e threads — e um dia a terceira também vai. */
.avatar-post {
  width: 38px; height: 38px; flex: none; border-radius: var(--r-md);
  display: grid; place-items: center;
  background: var(--superficie-3); color: var(--tinta-2);
  font-size: 12.5px; font-weight: 700; letter-spacing: .02em;
}
.post.nova .avatar-post { background: var(--marca-fraca); color: var(--marca-tinta); }
.post .corpo { min-width: 0; flex: 1; }
.post .cabeca { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.post .cabeca .autor { font-size: 14px; }
.post .cabeca .hora { font-size: 12px; color: var(--tinta-muda); }
.post .cabeca .fixado { font-size: 16px; color: var(--tinta-muda); }
.post .lida { display: inline-flex; align-items: center; gap: 3px; font-size: 12.5px; color: var(--tinta-muda); }
.post .lida .ic { font-size: 15px; }
.post .conteudo { margin-top: 3px; }
.post .titulo-post { display: block; font-size: 14.5px; line-height: 1.4; }
.post .chamada { margin: 2px 0 0; font-size: 14px; color: var(--tinta-2); line-height: 1.55; }
.post .texto-longo { margin-top: 6px; }
/* as ações do dono só aparecem no post em foco: quatro ícones em toda linha
   competem com o texto, e quem publica sabe onde procurar */
/* o `.btn > .ic` encolhe o glifo pra .85em, que serve pro ▶ de texto mas
   deixa o ícone do Google minúsculo ao lado da palavra */
.reacoes-novidade .btn > .ic { font-size: 17px; }
.post .acoes-dono { opacity: 0; transition: opacity .14s; }
.post:hover .acoes-dono, .post:focus-within .acoes-dono { opacity: 1; }

@media (max-width: 900px) {
  /* numa coluna só, os canais viram uma fileira que rola na horizontal */
  .canais { border-right: 0; border-bottom: 1px solid var(--borda); padding: 10px; }
  .canais-marca, .canais-titulo { display: none; }
  .canais nav { display: flex; gap: 6px; overflow-x: auto; }
  .canal { width: auto; flex: none; margin: 0; }
  .canal .nome { overflow-wrap: normal; white-space: nowrap; }
  /* uma linha no lugar de cinco: o token muda e todo o recuo do painel segue */
  .central-novidades { --recuo-painel: 12px; }
  /* sem hover no toque: as ações do dono ficam sempre visíveis */
  .post .acoes-dono { opacity: 1; }
}

.linha-tempo { display: flex; flex-direction: column; }
.novidade { display: flex; gap: 14px; }
.novidade .marco { position: relative; flex: none; width: 14px; }
.novidade .marco::before {
  content: ""; position: absolute; left: 6px; top: 0; bottom: -1px;
  width: 2px; background: var(--borda);
}
.novidade:last-child .marco::before { bottom: auto; height: 26px; }
.ponto-tempo {
  position: absolute; left: 0; top: 20px; width: 14px; height: 14px;
  border-radius: 50%; background: var(--superficie);
  border: 3px solid var(--borda-forte);
}
.novidade.nova .ponto-tempo { border-color: var(--marca); }
.novidade .corpo {
  flex: 1; min-width: 0; margin-bottom: 14px;
  background: var(--superficie); border: 1px solid var(--borda);
  border-radius: var(--r-md); padding: 14px 16px; box-shadow: var(--sombra-1);
}
.novidade.nova .corpo { border-color: color-mix(in srgb, var(--marca) 32%, var(--borda)); }
.novidade .topo { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.novidade .topo b { font-size: 15.5px; }
.novidade .chamada { margin: 7px 0; font-size: 14.5px; color: var(--tinta-2); }
.novidade .pe { display: flex; align-items: center; gap: 9px; margin-top: 10px; }

/* Estratificação: os dois seletores são a tela inteira, então respiram */
.escolha { gap: 14px; flex-wrap: wrap; }
.campo-inline { display: flex; align-items: center; gap: 8px; font-size: 13.5px; color: var(--tinta-2); }
.campo-inline select { width: auto; min-width: 190px; }

/* peso da fatia: a barrinha diz em quanta base aquele número se apoia */
.peso {
  display: inline-block; width: 62px; height: 7px; border-radius: 4px;
  background: var(--superficie-3); overflow: hidden; vertical-align: middle;
}
.peso > span { display: block; height: 100%; background: var(--marca); border-radius: 4px; }


/* ==========================================================================
   Seções do menu — 27 telas numa coluna só viram parede.

   Tudo à vista, numa lista só. O pop-up que existia aqui resolvia a altura da
   coluna, mas cobrava um clique pra descobrir o que cada módulo tinha dentro —
   e quem não sabia o nome do módulo não achava a tela. Com a coluna rolando,
   a lista inteira cabe: o módulo virou legenda e cada destino tem seu ícone.
   ========================================================================== */
/* Sem legenda não há o que clicar: no rail o módulo fechado esconderia
   destinos sem dar como abrir. Lá a sanfona não vale. */
body.lateral-compacta .lateral .nav-bloco.fechado > .nav-item { display: flex; }

/* No rail, sem rótulo e sem legenda, o que separa um módulo do outro é o
   traço: o respiro sozinho não vence numa coluna de ícones. */
body.lateral-compacta .lateral .nav-bloco + .nav-bloco {
  border-top: 1px solid var(--borda); margin-top: 8px; padding-top: 8px;
}

/* ==========================================================================
   Menu completo no celular — a lateral vira gaveta.
   Sem isto, a barra de baixo dá acesso a 4 telas de 27.
   ========================================================================== */
@media (max-width: 820px) {
  /* a regra acima esconde a lateral; aqui ela volta como gaveta deslizante */
  .lateral {
    display: flex !important;
    position: fixed; top: 0; bottom: 0; left: 0; z-index: 45;
    width: min(300px, 86vw); max-width: none;
    transform: translateX(-102%);
    transition: transform .22s ease;
    box-shadow: var(--sombra-3);
    /* era `overflow-y: auto` (a gaveta inteira rolava); agora quem rola é o
       .nav, e a marca e o rodapé ficam parados também no celular */
  }
  body.gaveta-aberta .lateral { transform: none; }

  .fundo-gaveta {
    position: fixed; inset: 0; z-index: 44;
    background: rgba(15, 18, 22, .45); backdrop-filter: blur(2px);
  }

  /* o botão da gaveta se comporta como os outros itens da barra de baixo */
  .nav-mobile button {
    border: 0; background: none; font: inherit; cursor: pointer;
  }
  body.gaveta-aberta .nav-mobile #abrirMenuTudo { color: var(--marca); }

  /* dentro da gaveta o menu respira: alvo de dedo, não de ponteiro */
  .lateral .nav-bloco > .nav-item { padding: 10px 12px; font-size: 14.5px; }
  .lateral .nav-sub { padding-left: 44px; }
  /* recolher a lateral não faz sentido num celular */
  .lateral .recolher { display: none; }

  /* A tela estreita liga o modo compacto (só ícones) pra economizar largura no
     desktop. Na gaveta isso não vale: há espaço, e menu sem rótulo não se lê. */
  body.lateral-compacta { --lateral: 300px; }
  body.lateral-compacta .lateral .marca-topo { justify-content: flex-start; padding: 4px 0 16px; }
  body.lateral-compacta .lateral .marca-nome,
  body.lateral-compacta .lateral .marca-sub { display: block; }
  body.lateral-compacta .lateral .nav-bloco > .nav-item { justify-content: flex-start; padding: 11px 12px; }
  body.lateral-compacta .lateral .nav-bloco > .nav-item .rotulo { display: inline; }
  body.lateral-compacta .lateral .nav-bloco > .nav-item .selo { position: static; margin-left: auto; }
  body.lateral-compacta .lateral .nav-bloco > .nav-item .ic { font-size: 18px; }
  body.lateral-compacta .lateral .nav-titulo,
  body.lateral-compacta .lateral .nav-sub { display: block; }
  body.lateral-compacta .lateral .nav-bloco + .nav-bloco { border-top: 0; margin-top: 4px; padding-top: 0; }
  body.lateral-compacta .lateral .botao-usuario { justify-content: flex-start; padding: 8px 10px; }
  /* `block` no .quem: com `flex` o nome e o @login viravam itens lado a lado e
     saía "Equipe Forneria@forneria" numa linha só */
  body.lateral-compacta .lateral .botao-usuario .quem { display: block; }
  body.lateral-compacta .lateral .botao-usuario .seta { display: flex; }
}

@media (prefers-reduced-motion: reduce) {
  .lateral { transition: none; }
}

/* ==========================================================================
   No.Name IA
   ========================================================================== */
.caixa-pergunta form { display: flex; gap: 9px; align-items: center; }
.caixa-pergunta .lupa { font-size: 20px; flex: none; }
.caixa-pergunta input { font-size: 15.5px; padding: 12px 14px; }
.caixa-pergunta .exemplos { margin-top: 12px; }

.exemplos { display: flex; flex-wrap: wrap; gap: 7px; }
.chip {
  border: 1px solid var(--borda); background: var(--superficie);
  border-radius: 999px; padding: 6px 13px; font-size: 12.5px; font-weight: 500;
  color: var(--tinta-2); cursor: pointer; font-family: inherit;
  transition: border-color .12s, background .12s, color .12s;
}
.chip:hover { border-color: var(--marca); background: var(--marca-fraca); color: var(--marca-tinta); }

.resposta-cabeca { display: flex; gap: 12px; align-items: flex-start; margin-bottom: 12px; }
.resposta-cabeca .emoji { font-size: 22px; line-height: 1.2; flex: none; }
.resposta-cabeca p { margin: 0; font-size: 15.5px; line-height: 1.5; }
.resposta-cabeca .destaque-resposta {
  margin-top: 5px; font-size: 14px; font-weight: 600; color: var(--marca-tinta);
}
/* o número é a resposta: tem que ser a maior coisa da tela */
.resposta-valor {
  font-size: 42px; font-weight: 700; letter-spacing: -.025em; line-height: 1.1;
  margin-bottom: 4px;
}

/* ==========================================================================
   Seletor global de lojas — a rede inteira ou um recorte dela
   ========================================================================== */
.seletor-lojas { gap: 8px; font-weight: 600; }
/* NOME DE LOJA NÃO PODE EMPURRAR A BARRA. Com uma loja marcada o botão mostra o
   nome inteiro — "Forneria Original Pizza - Volta Redonda" —, e a barra que já
   estava no limite quebrava. O nome completo continua no title do botão. */
.seletor-lojas #rotuloLojas {
  max-width: 190px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.seletor-lojas .seta { font-size: 18px; opacity: .6; }
.seletor-lojas .ic { font-size: 19px; }
.seletor-lojas.filtrando {
  border-color: var(--marca); background: var(--marca-fraca); color: var(--marca-tinta);
}

.painel-lojas {
  position: fixed; top: 62px; right: 22px; z-index: 55;
  width: min(360px, calc(100vw - 32px)); max-height: min(70vh, 560px);
  display: flex; flex-direction: column;
  background: var(--superficie); border: 1px solid var(--borda);
  border-radius: var(--r-lg); box-shadow: var(--sombra-3); overflow: hidden;
}
.painel-lojas .topo { padding: 12px 13px 9px; border-bottom: 1px solid var(--borda); }
.painel-lojas .atalhos { display: flex; gap: 6px; padding: 10px 13px; flex-wrap: wrap; }
/* a lista rola sozinha: com 400 lojas o painel não pode crescer com a tela */
/**
 * `overscroll-behavior: contain` — ver a regra coletiva no fim deste arquivo.
 *
 * Sem ela, rolar a lista de lojas até o fim e continuar rolando empurrava a
 * PÁGINA atrás: medi 720px de deslocamento com o cursor parado dentro do
 * painel. Como o painel é `position: fixed`, ele não acompanha — fica cravado
 * enquanto o conteúdo dispara por baixo. Foi o "dar scroll no menu de IDs e
 * ia bugando" que o cliente relatou por texto e por áudio.
 */
.painel-lojas .lista-lojas {
  flex: 1; overflow-y: auto; overscroll-behavior: contain; padding: 0 7px 7px;
}
.painel-lojas .rodape {
  display: flex; align-items: center; gap: 10px; padding: 11px 13px;
  border-top: 1px solid var(--borda); background: var(--superficie-2);
}
.painel-lojas .rodape .apoio { flex: 1; }
/* fechar e reabrir: acima do rodapé de aplicar, separados por uma linha, porque
   são ações sobre a operação — não sobre o filtro que o Aplicar confirma */
/* quem não pode pausar loja não vê os botões — o servidor recusaria de todo
   jeito, e botão que só serve pra dar erro é pior que botão nenhum */
.painel-lojas .acoes-lojas { display: none; }
body.pode-loja-pausa .painel-lojas .acoes-lojas {
  display: flex; align-items: center; gap: 7px; padding: 9px 13px;
  border-top: 1px solid var(--borda);
}
.painel-lojas .acoes-lojas .apoio { margin-left: auto; font-size: 11.5px; text-align: right; }

/* ==========================================================================
   Precisa da sua atenção — o sino e o painel

   Tudo aqui é vermelho de propósito. Antes o aviso tinha dois níveis, amarelo e
   vermelho, e o amarelo virou a maioria — a cor deixou de significar nada. Se
   um ponto chegou nesta lista é porque pede ação agora; quem não pede não entra.
   ========================================================================== */
/* Sino e seletor de lojas vivem lado a lado, e botão de altura diferente ao lado
   do outro é a primeira coisa que se nota. Quem manda na altura é o glifo, e no
   celular o seletor perde o ícone e encolhia 1px — a altura mínima comum
   segura os dois iguais em qualquer largura. */
.barra-topo .direita > .btn { min-height: 39px; }
.btn.sino {
  position: relative; padding: 9px 11px; gap: 0;
}
/* 19px, o mesmo do ícone do seletor: é o glifo que manda na altura da caixa, e
   a 21px o sino ficava 2px mais alto que o vizinho */
.btn.sino .ic { font-size: 19px; }
.btn.sino.tem { border-color: var(--grave); color: var(--grave-tinta); }
.btn.sino.tem:hover { background: var(--grave-fraco); }
/* o número vem do desenho: círculo cheio, encostado no canto do ícone */
.btn.sino .conta {
  position: absolute; top: -6px; right: -6px;
  min-width: 20px; height: 20px; padding: 0 5px; border-radius: 20px;
  background: var(--grave); color: #fff;
  font-size: 11.5px; font-weight: 700; line-height: 20px; text-align: center;
  border: 2px solid var(--plano);
}

/* `top` e `left` são do JS, que ancora o painel no sino; aqui ficam só como
   reserva pro instante entre abrir e posicionar */
.painel-notificacoes {
  position: fixed; top: 62px; right: 22px; z-index: 55;
  width: min(460px, calc(100vw - 32px)); max-height: min(72vh, 620px);
  display: flex; flex-direction: column;
  background: var(--superficie); border: 1px solid var(--borda);
  border-radius: var(--r-lg); box-shadow: var(--sombra-3); overflow: hidden;
  animation: sobe .16s cubic-bezier(.2,.8,.3,1);
}
.painel-notificacoes .topo {
  display: flex; align-items: baseline; gap: 9px; flex-wrap: wrap;
  padding: 13px 15px; border-bottom: 1px solid var(--borda);
}
.painel-notificacoes .topo b { font-size: 14px; }
/* a lista rola sozinha: sete lojas com problema não podem esticar o painel */
.painel-notificacoes .lista { flex: 1; overflow-y: auto; padding: 10px; display: flex; flex-direction: column; gap: 8px; }

/* Três colunas: ícone · texto · botões. O texto é o único que estica, então os
   botões ficam colados na direita em qualquer largura de aviso. `start` no
   alinhamento pra o ícone acompanhar a primeira linha do título, e não o meio
   de um texto de três linhas. */
.notificacao {
  display: grid; grid-template-columns: auto minmax(0, 1fr) auto;
  gap: 11px; align-items: start;
  padding: 12px 13px; border-radius: var(--r-md);
  background: var(--grave-fraco); border: 1px solid #f4cccb; color: var(--grave-tinta);
}
.notificacao > .ic { font-size: 21px; line-height: 1.2; flex: none; }
.notificacao .miolo { min-width: 0; }
.notificacao strong { display: block; font-size: 13.5px; line-height: 1.35; }
.notificacao p { margin: 3px 0 0; font-size: 12.5px; line-height: 1.5; opacity: .9; }
.notificacao .acoes { display: flex; flex-direction: column; align-items: stretch; gap: 6px; }
.notificacao .acoes .btn { justify-content: flex-start; white-space: nowrap; }

/* Painel estreito: os botões não cabem na terceira coluna sem espremer o texto.
   Descem pra uma faixa própria, ainda alinhados à direita. */
@media (max-width: 560px) {
  .painel-notificacoes { top: auto; bottom: calc(var(--nav-mobile) + 10px); right: 10px; left: 10px; width: auto; }
  .notificacao { grid-template-columns: auto minmax(0, 1fr); }
  .notificacao .acoes { grid-column: 1 / -1; flex-direction: row; flex-wrap: wrap; justify-content: flex-end; }
}

.linha-loja {
  display: flex; align-items: center; gap: 9px;
  padding: 8px 10px; border-radius: var(--r-sm); cursor: pointer; font-size: 13.5px;
}
.linha-loja:hover { background: var(--superficie-2); }
.linha-loja input { position: absolute; opacity: 0; pointer-events: none; }
/* `flex: 1` zera o flex-basis mas NÃO anula o `min-width: auto` — sem o
   min-width:0 abaixo, nome de loja comprido estoura o seletor em vez de cortar */
.linha-loja .nome { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.linha-loja .apoio { font-size: 11.5px; flex: none; }
.linha-loja .marca-check {
  width: 17px; height: 17px; flex: none; border-radius: 5px;
  border: 1.5px solid var(--borda-forte); display: grid; place-items: center;
  font-size: 11px; color: transparent; transition: background .12s, border-color .12s;
}
.linha-loja input:checked ~ .marca-check {
  background: var(--marca); border-color: var(--marca); color: #fff;
}

@media (max-width: 820px) {
  .painel-lojas { top: auto; bottom: calc(var(--nav-mobile) + 10px); right: 10px; left: 10px; width: auto; }
  .seletor-lojas .ic { display: none; }
}

/* ==========================================================================
   "Como usar esta tela" — a ajuda no lugar onde a dúvida acontece
   ========================================================================== */
/* Mora dentro do pop-up aberto pelo botão do topo — o `.modal-corpo` já dá a
   moldura e a rolagem, então aqui só entra o ritmo do texto.
   78ch porque linha de manual longa demais cansa: é o limite de leitura
   confortável, e o modal `largo` é mais largo que isso. */
.como-usar { max-width: 78ch; font-size: 14px; line-height: 1.65; }
/* separador entre as tarefas: sem ele o fim de uma cola no título da seguinte */
.como-usar article + article { margin-top: 20px; padding-top: 18px; border-top: 1px solid var(--borda); }
.como-usar h3 { margin: 0 0 8px; font-size: 15px; }
.como-usar h3 .ico { font-size: 19px; vertical-align: -4px; margin-right: 2px; }
.como-usar p { margin: 0 0 10px; font-size: 14px; line-height: 1.6; color: var(--tinta-2); }
.como-usar p:last-child { margin-bottom: 0; }
.como-usar ol, .como-usar ul { margin: 0 0 10px; padding-left: 20px; }
.como-usar li { margin-bottom: 6px; font-size: 14px; line-height: 1.6; color: var(--tinta-2); }
.como-usar li:last-child { margin-bottom: 0; }
/* Os avisos coloridos vinham encostados um no outro — dois cartões de cor forte
   sem um fio de branco entre eles lêem como um bloco só. Margem nos dois lados
   porque eles também encostavam no passo de cima; entre dois seguidos as
   margens colapsam e o vão continua sendo 12px. */
.como-usar .aviso { margin: 12px 0; }
/* ícone dentro do texto corrido: acompanha a linha em vez de subir acima dela */
.como-usar .ico { font-size: 17px; vertical-align: -3px; }

/* ==========================================================================
   Relatório mensal — texto pra ler, não painel pra escanear
   ========================================================================== */
/* O rodapé do indicador do relatório: variação em cima, base embaixo.
   A ordem é essa porque a pergunta do relatório mensal é "melhorou ou piorou",
   e não "quanto foi mês passado" — esse é o número de conferência, e fica em
   cinza, menor, na segunda linha. */
.kpi .comparativo-mes { display: flex; flex-direction: column; gap: 1px; }
.kpi .comparativo-mes .variacao { line-height: 1.35; }
.kpi .comparativo-mes .base { color: var(--tinta-muda); font-size: 11.5px; }

.prosa { max-width: 72ch; }
.prosa p {
  display: flex; gap: 11px; align-items: flex-start;
  margin: 0 0 12px; font-size: 15.5px; line-height: 1.65; color: var(--tinta);
  padding: 10px 12px; border-radius: var(--r-md);
}
.prosa p:last-child { margin-bottom: 0; }
/* O TOM VIRA MEDALHA, e não emoji solto na frente da frase.
   O ícone dentro de um círculo da cor do tom dá ao parágrafo o mesmo peso
   visual de um cartão de achado — que é o vizinho dele na tela. Antes eram um
   emoji quebrado e uma listra: duas linguagens diferentes na mesma página. */
.prosa .marca-tom {
  flex: none; width: 26px; height: 26px; border-radius: 50%;
  display: grid; place-items: center; margin-top: 1px;
  background: var(--superficie-3); color: var(--tinta-muda);
}
.prosa .marca-tom .ico { font-size: 17px; }
.prosa .marca-tom.bom  { background: var(--bom-fraco);   color: var(--bom-tinta); }
.prosa .marca-tom.ruim { background: var(--grave-fraco); color: var(--grave-tinta); }
/* a cor fica na borda e num fundo levíssimo, nunca no texto: parágrafo
   colorido cansa de ler, e este é o texto mais longo do painel */
.prosa p.bom  { border-left: 3px solid var(--bom);   background: color-mix(in srgb, var(--bom) 4%, transparent); }
.prosa p.ruim { border-left: 3px solid var(--grave); background: color-mix(in srgb, var(--grave) 5%, transparent); }
.prosa p.neutro { border-left: 3px solid var(--borda-forte); }
/* O número destacado no meio da prosa — vale nos dois blocos do relatório.
   `nowrap` porque "R$ 28.400,00" partido entre duas linhas deixa de ser um
   valor e vira dois pedaços de texto. */
.prosa .num, .oportunidades .num {
  font-weight: 700; font-variant-numeric: tabular-nums; white-space: nowrap;
}

/* ==========================================================================
   Oportunidades do relatório mensal.

   Elas fecham o relatório — é a parte que o cliente pediu ("termina em
   oportunidades, não em números") e era a mais pobre da tela: um título e um
   parágrafo cinza, ao lado de um bloco de achados com número, leitura e ação.
   Aqui ganham a mesma anatomia, mantendo o que já era bom: a NUMERAÇÃO, que
   dá ordem de prioridade a quem vai atacar uma de cada vez.
   ========================================================================== */
.oportunidades { counter-reset: op; margin: 0; padding: 0; list-style: none; }
.oportunidades li {
  counter-increment: op; position: relative; padding: 12px 14px 12px 46px;
  border: 1px solid var(--borda); border-radius: var(--r-md);
  margin-bottom: 10px; background: var(--superficie);
}
.oportunidades li:last-child { margin-bottom: 0; }
.oportunidades li::before {
  content: counter(op); position: absolute; left: 12px; top: 12px;
  width: 24px; height: 24px; border-radius: 50%;
  background: var(--marca-fraca); color: var(--marca-tinta);
  font-weight: 700; font-size: 12.5px; display: grid; place-items: center;
}
/* o que veio do motor de insights carrega o nível: a borda esquerda avisa que
   aquela linha não é sugestão, é problema */
.oportunidades li.grave   { border-left: 3px solid var(--grave); }
.oportunidades li.atencao { border-left: 3px solid var(--atencao); }
/* `> b`, e não `b`: o seletor solto pegava também os números em negrito DENTRO
   do parágrafo e os transformava em bloco — cada valor destacado quebrava a
   frase em três pedaços empilhados. Só o título é bloco. */
.oportunidades li > b { font-size: 15px; display: block; }
/* o número é a manchete da oportunidade — vem antes do porquê, como no achado */
.oportunidades li .numero {
  font-size: 12.5px; font-weight: 700; color: var(--tinta-2); margin: 3px 0 5px;
}
.oportunidades li p { margin: 0; font-size: 14px; line-height: 1.6; color: var(--tinta-2); }
.oportunidades li .acao {
  display: inline-flex; align-items: center; gap: 4px; margin-top: 7px;
  font-size: 12.5px; font-weight: 600; color: var(--marca-tinta); text-decoration: none;
}
.oportunidades li .acao .ico { font-size: 15px; }
.oportunidades li .acao:hover { text-decoration: underline; }
.oportunidades li .acao.sem-destino { color: var(--tinta-2); font-weight: 500; }

/* ==========================================================================
   Mapa deslizante — tiles do OpenStreetMap posicionados à mão
   ========================================================================== */
.mapa {
  position: relative; height: 420px; overflow: hidden;
  border-radius: var(--r-md); background: #e8eaec;
  cursor: grab; touch-action: none; user-select: none;
}
.mapa.arrastando { cursor: grabbing; }
.mapa:focus-visible { outline: none; box-shadow: var(--anel); }
.mapa .tiles { position: absolute; inset: 0; }
.mapa .tiles img {
  /* left/top zerados: a posição vem de transform (ver desenharTiles), que o
     navegador resolve no compositor sem recalcular layout a cada movimento */
  position: absolute; left: 0; top: 0; width: 256px; height: 256px;
  /* o mapa é fundo: sem isto ele briga com os pontos por atenção */
  filter: saturate(.72) contrast(.94);
}
.mapa .camada { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }
/* só os alvos de dica recebem ponteiro — o resto continua arrastável */
.mapa .camada .entrega, .mapa .camada .pino { pointer-events: auto; cursor: pointer; }
.mapa .camada .entrega { stroke: #fff; stroke-width: 1.2; fill-opacity: .85; }
.mapa .camada .entrega:hover { r: 6; }
/* célula da malha de calor: sem borda, senão a grade vira o assunto */
.mapa .camada .celula { pointer-events: auto; cursor: pointer; }
.mapa .camada .celula:hover { stroke: #fff; stroke-width: 1.5; }
.mapa .camada .escala line { stroke: var(--tinta); stroke-width: 2; opacity: .8; }
.mapa .camada .escala text {
  font-size: 11px; font-weight: 700; fill: var(--tinta);
  paint-order: stroke; stroke: #fff; stroke-width: 3.5px; stroke-linejoin: round;
}

.mapa .controles {
  position: absolute; right: 10px; top: 10px; z-index: 2;
  display: flex; flex-direction: column; gap: 5px;
}
.btn-mapa {
  width: 32px; height: 32px; border-radius: 8px; cursor: pointer;
  border: 1px solid var(--borda); background: var(--superficie);
  font-size: 15px; font-weight: 700; color: var(--tinta-2);
  box-shadow: var(--sombra-1); display: grid; place-items: center;
}
.btn-mapa .ico { font-size: 19px; }
.btn-mapa:hover { background: var(--superficie-2); color: var(--tinta); }

.mapa .creditos {
  position: absolute; right: 0; bottom: 0; z-index: 2;
  background: rgba(255,255,255,.82); padding: 2px 7px;
  font-size: 10.5px; color: var(--tinta-2); border-top-left-radius: 6px;
}
.mapa .creditos a { color: inherit; }

.dica-mapa {
  position: absolute; z-index: 3; pointer-events: none;
  background: #14171c; color: #fff; border-radius: var(--r-sm);
  padding: 7px 10px; font-size: 12.5px; line-height: 1.5;
  max-width: 240px; box-shadow: var(--sombra-2);
}

@media (max-width: 820px) { .mapa { height: 320px; } }
/* no papel o mapa vira imagem morta: sem controles, sem créditos flutuando */
@media print {
  .mapa { height: 300px; }
  .mapa .controles, .mapa .dica-mapa { display: none !important; }
}

/* Aviso de versão nova — some sozinho quando a pessoa recarrega */
.aviso-versao {
  position: fixed; left: 50%; bottom: 20px; transform: translateX(-50%);
  z-index: 70; display: flex; align-items: center; gap: 12px;
  background: var(--tinta); color: #fff; border-radius: 999px;
  padding: 10px 12px 10px 18px; font-size: 13.5px; font-weight: 500;
  box-shadow: var(--sombra-3); max-width: calc(100vw - 24px);
}
.aviso-versao .ic { font-size: 19px; }
.aviso-versao .btn { flex: none; }
@media (max-width: 820px) { .aviso-versao { bottom: calc(var(--nav-mobile) + 14px); } }
@media print { .aviso-versao { display: none !important; } }

/* O plano do agente: o que ele VAI fazer, antes de fazer */
.cartao.plano { border-color: color-mix(in srgb, var(--marca) 34%, var(--borda)); }
.cartao.plano .previa { margin-top: 4px; }

/* resultado da busca transversal do agente */
.achado {
  display: flex; flex-direction: column; gap: 2px;
  padding: 10px 13px; border: 1px solid var(--borda); border-radius: var(--r-md);
  text-decoration: none; color: inherit; transition: border-color .12s, background .12s;
}
.achado:hover { border-color: var(--marca); background: var(--marca-fraca); text-decoration: none; }
.achado .onde {
  font-size: 10.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .05em;
  color: var(--marca-tinta);
}
.achado b { font-size: 14.5px; }

/* ==========================================================================
   Reações, comentários e qualidade do cadastro
   ========================================================================== */
.reacoes-novidade { display: flex; gap: 6px; align-items: center; flex-wrap: wrap; margin-top: 10px; }
.reacoes-novidade .reacao { font-size: 13px; padding: 3px 10px; }
.reacoes-novidade .reacao.minha {
  border-color: var(--marca); background: var(--marca-fraca); color: var(--marca-tinta); font-weight: 700;
}

.comentarios { margin-top: 10px; display: flex; flex-direction: column; gap: 9px; }
.comentario { display: flex; gap: 9px; align-items: flex-start; font-size: 13.5px; }
.comentario .avatar {
  width: 26px; height: 26px; flex: none; border-radius: 50%;
  display: grid; place-items: center; font-size: 14px; background: var(--superficie-3);
}
.comentario p { margin: 2px 0 0; color: var(--tinta-2); line-height: 1.55; }

/* ------------------------------------------------- tags de assunto e menções */
/* A tag carrega a própria cor em --tag, vinda do cadastro do assunto. Fundo e
   texto saem dela por color-mix, então qualquer cor que a casa escolher continua
   legível sem precisar cadastrar um par de cores pra cada tag. */
.tag-assunto {
  display: inline-flex; align-items: center; white-space: nowrap;
  font-size: 11.5px; font-weight: 700; border-radius: 20px; padding: 3px 9px;
  background: color-mix(in srgb, var(--tag, #495057) 12%, #fff);
  color: color-mix(in srgb, var(--tag, #495057) 78%, #000);
}
.tag-assunto.plano { background: none; padding: 0; }
.segmentado button .tag-assunto { pointer-events: none; }

.mencao {
  font-weight: 700; border-radius: 4px; padding: 0 3px;
  background: var(--marca-fraca); color: var(--marca-tinta);
}
/* @suporte se distingue das outras: é o canal com a gente, não com o colega */
.mencao.suporte { background: var(--atencao-fraco); color: var(--atencao-tinta); }

.caixa-mencao { position: relative; }
.sugestoes-mencao {
  position: absolute; left: 0; right: 0; top: 100%; z-index: 5; margin-top: 4px;
  background: var(--superficie); border: 1px solid var(--borda-forte);
  border-radius: var(--r-md); box-shadow: var(--sombra-2); overflow: hidden;
}
.sugestoes-mencao .sugestao {
  display: flex; align-items: center; gap: 8px; width: 100%;
  padding: 7px 10px; border: 0; background: none; cursor: pointer;
  text-align: left; font: inherit; font-size: 13px;
}
.sugestoes-mencao .sugestao:hover,
.sugestoes-mencao .sugestao.ativa { background: var(--superficie-3); }
.sugestoes-mencao .avatar {
  width: 22px; height: 22px; flex: none; border-radius: 50%;
  display: grid; place-items: center; font-size: 12px; background: var(--superficie-3);
}
.sugestoes-mencao .mudo { margin-left: auto; }

.item-qualidade {
  display: flex; gap: 14px; align-items: flex-start; flex-wrap: wrap;
  padding: 12px 15px; border: 1px solid var(--borda); border-radius: var(--r-md);
  border-left: 4px solid var(--atencao);
}
.item-qualidade .miolo { flex: 1 1 300px; min-width: 0; display: flex; flex-direction: column; gap: 5px; }
.item-qualidade .topo { display: flex; align-items: center; gap: 7px; flex-wrap: wrap; }
.item-qualidade .topo b { font-size: 14.5px; }
.item-qualidade .falhas { display: flex; gap: 5px; flex-wrap: wrap; }
.item-qualidade .miolo p { margin: 0; }
.item-qualidade .numeros { display: flex; gap: 18px; flex-wrap: wrap; }
.item-qualidade .celula { display: flex; flex-direction: column; min-width: 76px; }
.item-qualidade .celula .rotulo {
  font-size: 10.5px; text-transform: uppercase; letter-spacing: .04em;
  color: var(--tinta-muda); font-weight: 700;
}
.item-qualidade .celula b { font-size: 15px; }

/* SLA da thread: prazo combinado, não meta inventada */
.sla {
  display: inline-flex; align-items: center; gap: 4px; margin-top: 3px;
  font-size: 10.5px; font-weight: 700; padding: 2px 7px; border-radius: 999px;
}
.sla.ok        { background: var(--bom-fraco);     color: var(--bom-tinta); }
.sla.esperando { background: var(--info-fraco);    color: var(--info-tinta); }
.sla.estourou  { background: var(--grave-fraco);   color: var(--grave-tinta); }

/* ==========================================================================
   Impressão — é assim que o PDF é gerado: quem imprime é o navegador.
   Fora menu, botões e tudo que só serve pra clicar; fica o conteúdo.
   ========================================================================== */
.so-impressao { display: none; }
#resumoImpressao { display: none; }

/* PDF DO RESUMO (não da tela).
   Imprimir a tela toda e imprimir o resumo são coisas diferentes: a tela vira
   um relatório de várias páginas, o resumo cabe numa e é o que a pessoa manda
   pra alguém. Com `body.imprimindo-resumo` o painel inteiro sai do papel e
   fica só o texto — inclusive o modal, que o bloco de impressão esconde. */
@media print {
  body.imprimindo-resumo .app,
  body.imprimindo-resumo #cabecalhoImpressao { display: none !important; }
  body.imprimindo-resumo #resumoImpressao { display: block !important; }
  #resumoImpressao .titulo { font-size: 19px; font-weight: 800; letter-spacing: -.01em; }
  #resumoImpressao .marca-impressa { font-size: 11px; font-weight: 700; color: #2f5cff; }
  #resumoImpressao .linha-titulo {
    display: flex; align-items: baseline; justify-content: space-between; gap: 12px;
    border-bottom: 1.5px solid #16181d; padding-bottom: 8px;
  }
  #resumoImpressao .meta {
    display: flex; flex-wrap: wrap; gap: 4px 16px;
    margin-top: 5px; font-size: 9.5px; color: #5b6270;
  }
  #resumoImpressao pre {
    margin-top: 14px; font-family: inherit; font-size: 12px; line-height: 1.65;
    white-space: pre-wrap; word-wrap: break-word;
  }
  /* a linha de título de cada bloco vem marcada pelo montador do resumo */
  #resumoImpressao pre b { font-weight: 800; }
}

@media print {
  @page { size: A4 portrait; margin: 12mm 10mm; }

  html, body { background: #fff !important; }
  body { font-size: 11px; }

  .lateral, .nav-mobile, .topo-mobile, .menu-flutuante, .dica-grafico,
  .barra-topo .direita, .acoes, .segmentado, .opcoes, .botao-usuario,
  .nao-imprime, .toast, .modal-fundo, .rodape-pagina,
  [data-precisa], .btn { display: none !important; }

  .app { display: block !important; }
  .conteudo { margin: 0 !important; padding: 0 !important; max-width: none !important; }
  .pagina { padding: 0 !important; gap: 10px !important; }

  .so-impressao { display: block; margin-bottom: 12px; }
  #cabecalhoImpressao { border-bottom: 1.5px solid #16181d; padding-bottom: 8px; }
  #cabecalhoImpressao .linha-titulo {
    display: flex; align-items: baseline; justify-content: space-between; gap: 12px;
  }
  #cabecalhoImpressao strong { font-size: 18px; letter-spacing: -.01em; }
  #cabecalhoImpressao .marca-impressa { font-size: 11px; font-weight: 700; color: #2f5cff; }
  #cabecalhoImpressao .linha-meta {
    display: flex; flex-wrap: wrap; gap: 4px 16px; margin-top: 4px;
    font-size: 9.5px; color: #5b6270;
  }

  /* A barra de filtros vira uma caixa VAZIA no papel: seus controles são todos
     escondidos e sobra a moldura. Escondo o cartão inteiro — mas só quando
     ele não carrega conteúdo junto, que é o caso do mapa e de alguns resumos. */
  .cartao.apertado:not(:has(.kpis, .grafico, table, .lista, .mapa)) { display: none !important; }

  /* o título já está no cabeçalho impresso — repetir logo abaixo só ocupa
     espaço numa página que é cara */
  .barra-topo h1 { display: none !important; }
  .barra-topo { margin-bottom: 6px !important; }

  /* gráfico espremido não comunica: garante altura no papel */
  .grafico { min-height: 34mm; }
  .grafico svg { width: 100% !important; }
  .legenda { display: flex !important; flex-wrap: wrap; gap: 4px 12px; font-size: 9px; margin-top: 4px; }

  /* cor de série e sinal (bom/ruim) têm significado — não podem virar cinza */
  * { -webkit-print-color-adjust: exact !important; print-color-adjust: exact !important; }
  .selo { border: 1px solid #d4d8de; }

  /* cartão cortado no meio da página fica ilegível */
  .cartao, .kpi, .grafico, .vazio, .aviso {
    break-inside: avoid; page-break-inside: avoid;
    box-shadow: none !important; border: 1px solid #d4d8de !important;
  }
  .cartao { padding: 9px 11px !important; }
  .cartao-topo h2 { font-size: 13px !important; }

  /* na tela cabem 4 por linha com folga; no papel, 3 */
  .kpis { display: grid !important; grid-template-columns: repeat(3, 1fr) !important; gap: 7px !important; }
  .grelha { display: grid !important; grid-template-columns: repeat(2, 1fr) !important; gap: 8px !important; }
  .kpi .valor { font-size: 17px !important; }

  /* a rolagem horizontal some no papel: a tabela tem que caber inteira */
  .rolagem-x { overflow: visible !important; }
  .tabela { font-size: 9.5px !important; width: 100% !important; }
  .tabela th, .tabela td { padding: 3px 5px !important; }
  thead { display: table-header-group; }

  svg { max-width: 100% !important; height: auto !important; }
  a[href]::after { content: none !important; }
}

/* Buscando dados: o conteúdo recua um pouco e para de aceitar clique, pra não
   dar dois comandos em cima do mesmo carregamento. Entra só depois de 150ms
   (ver rodarAtualizacao) — refresh rápido não deve piscar. */
.conteudo.ocupado { opacity: .5; pointer-events: none; }
.conteudo { transition: opacity .14s ease; }
@media (prefers-reduced-motion: reduce) { .conteudo { transition: none; } }

/* Envio de vídeo: barra de progresso e capa de aula sem YouTube */
.barra-progresso { height: 6px; border-radius: 999px; background: var(--grade); overflow: hidden; margin-top: 8px; }
.barra-progresso > span { display: block; height: 100%; width: 0; background: var(--marca); transition: width .2s ease; }
.aula .capa .capa-propria {
  display: grid; place-items: center; width: 100%; height: 100%;
  font-size: 34px; background: color-mix(in srgb, var(--marca) 12%, var(--superficie));
}
.player video { width: 100%; height: 100%; display: block; background: #000; }
@media (prefers-reduced-motion: reduce) { .barra-progresso > span { transition: none; } }

/* ==========================================================================
   Balão de suporte — o canto inferior direito, em toda tela.

   Fica ACIMA de tudo menos dos modais (z 60): o relato costuma nascer de um
   problema que a pessoa está vendo na tela, e o balão precisa estar lá quando
   isso acontece. No celular ele encolhe pro ícone e o chat vira tela cheia,
   porque um cartão de 360px num aparelho de 360px é a tela inteira mesmo.
   ========================================================================== */
.balao-suporte {
  position: fixed; right: 20px; bottom: 20px; z-index: 55;
  display: flex; align-items: center; gap: 8px;
  padding: 12px 17px; border: 0; border-radius: 999px; cursor: pointer;
  background: var(--marca); color: #fff; font: inherit; font-weight: 600; font-size: 14px;
  box-shadow: 0 6px 20px rgba(0, 0, 0, .22);
  transition: transform .14s, box-shadow .14s;
}
.balao-suporte:hover { transform: translateY(-1px); box-shadow: 0 9px 26px rgba(0, 0, 0, .28); }
.balao-suporte:focus-visible { outline: 3px solid var(--marca-fraca); outline-offset: 2px; }
.balao-suporte .ic { font-size: 20px; }
.balao-suporte .selo {
  position: absolute; top: -3px; right: -3px; min-width: 20px; height: 20px;
  display: grid; place-items: center; padding: 0 5px;
  background: var(--grave); color: #fff; border-radius: 999px;
  font-size: 11px; font-weight: 700; border: 2px solid var(--superficie);
}

.chat-suporte {
  position: fixed; right: 20px; bottom: 84px; z-index: 56;
  width: 370px; max-height: min(560px, calc(100vh - 120px));
  display: flex; flex-direction: column; overflow: hidden;
  background: var(--superficie); border: 1px solid var(--borda);
  border-radius: var(--r-lg); box-shadow: 0 18px 48px rgba(0, 0, 0, .26);
}
.chat-suporte .cabeca {
  display: flex; align-items: center; gap: 8px; padding: 11px 13px;
  border-bottom: 1px solid var(--borda); background: var(--superficie-2);
}
.chat-suporte .cabeca b { font-size: 14px; }
.chat-suporte .cabeca .apoio { font-size: 12px; }
.chat-suporte .cabeca .voltar,
.chat-suporte .cabeca .fechar {
  border: 0; background: none; cursor: pointer; color: var(--tinta-2);
  display: grid; place-items: center; padding: 3px; border-radius: var(--r-sm);
}
.chat-suporte .cabeca .fechar { margin-left: auto; }
.chat-suporte .cabeca .voltar:hover,
.chat-suporte .cabeca .fechar:hover { background: var(--superficie-3); color: var(--tinta); }

.chat-suporte .corpo {
  flex: 1; overflow-y: auto; overscroll-behavior: contain;
  padding: 12px 13px; display: flex; flex-direction: column; gap: 9px;
}
.chat-suporte .vazio-chat { color: var(--tinta-muda); font-size: 13px; line-height: 1.5; }

/* mensagem: a sua encosta à direita e usa a cor da marca — é o padrão que
   todo mundo já leu em mil conversas, e aqui não é hora de inventar */
.chat-suporte .msg {
  max-width: 84%; align-self: flex-start; display: flex; flex-direction: column; gap: 2px;
  background: var(--superficie-2); border-radius: 14px 14px 14px 4px; padding: 8px 11px;
}
.chat-suporte .msg.minha {
  align-self: flex-end; background: var(--marca); color: #fff; border-radius: 14px 14px 4px 14px;
}
.chat-suporte .msg .autor { font-size: 11.5px; font-weight: 700; color: var(--marca-tinta); }
.chat-suporte .msg .texto { font-size: 13.5px; line-height: 1.45; white-space: pre-wrap; word-break: break-word; }
.chat-suporte .msg .quando { font-size: 10.5px; opacity: .7; align-self: flex-end; }

/* a caixa de entrada de quem atende */
.chat-suporte .linha-conversa {
  display: flex; flex-direction: column; gap: 2px; text-align: left; width: 100%;
  border: 0; background: none; cursor: pointer; font: inherit; color: var(--tinta);
  padding: 9px 10px; border-radius: var(--r-md);
}
.chat-suporte .linha-conversa:hover { background: var(--superficie-2); }
.chat-suporte .linha-conversa.nova { background: var(--marca-fraca); }
.chat-suporte .linha-conversa .quem { font-weight: 700; font-size: 13.5px; display: flex; align-items: center; gap: 6px; }
.chat-suporte .linha-conversa .quem .selo {
  background: var(--grave); color: #fff; border-radius: 999px; font-size: 10.5px;
  font-weight: 700; padding: 0 6px; min-width: 18px; text-align: center;
}
.chat-suporte .linha-conversa .previa {
  font-size: 12.5px; color: var(--tinta-2);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.chat-suporte .linha-conversa .quando { font-size: 11px; color: var(--tinta-muda); }
.chat-suporte .linha-conversa .atrasado { color: var(--grave); }

.chat-suporte .escrever {
  display: flex; gap: 8px; align-items: flex-end; padding: 10px 11px;
  border-top: 1px solid var(--borda); background: var(--superficie-2);
}
.chat-suporte .escrever textarea {
  flex: 1; resize: none; max-height: 110px; font: inherit; font-size: 13.5px;
  padding: 9px 11px; border: 1px solid var(--borda); border-radius: var(--r-md);
  background: var(--superficie); color: var(--tinta);
}
.chat-suporte .escrever textarea:focus { outline: 0; border-color: var(--marca); box-shadow: var(--anel); }

@media (max-width: 700px) {
  /* no celular a barra de baixo já ocupa o canto: o balão sobe pra não brigar */
  .balao-suporte { right: 14px; bottom: 78px; padding: 12px; }
  .balao-suporte .rotulo { display: none; }
  .chat-suporte {
    right: 8px; left: 8px; bottom: 8px; width: auto;
    max-height: calc(100vh - 90px);
  }
}

/* o protocolo fica no topo da conversa, fixo: é o número que a pessoa vai
   repetir por telefone, e caçar isso rolando o chat é ruim */
.chat-suporte .protocolo-suporte {
  position: sticky; top: -12px; z-index: 1;
  display: flex; align-items: center; gap: 6px; align-self: stretch;
  background: var(--marca-fraca); color: var(--marca-tinta);
  border-radius: var(--r-md); padding: 7px 10px; font-size: 12px;
}
.chat-suporte .protocolo-suporte b { letter-spacing: .04em; font-variant-numeric: tabular-nums; }
/* a mensagem do bot NÃO se veste de humano: fundo neutro, autor com o ícone do
   robô. Passar bot por gente destrói a confiança no canal na primeira vez que
   a pessoa percebe. */
.chat-suporte .msg.do-bot {
  background: var(--superficie-3, var(--superficie-2));
  border: 1px dashed var(--borda-forte);
}
.chat-suporte .msg.do-bot .autor { color: var(--tinta-2); display: flex; align-items: center; gap: 4px; }
.chat-suporte .msg.do-bot .texto b { color: var(--marca-tinta); }

/* ==========================================================================
   Novidades com cara de post — pedido do cliente ("visual de post de rede
   social mesmo"). O que muda em relação ao mural antigo: o post vira um cartão
   com respiro, o autor ganha @ e tempo relativo, as ações viram um rodapé
   separado por um fio, e comentário vira balão.
   ========================================================================== */
.mural .post {
  background: var(--superficie); border: 1px solid var(--borda);
  border-radius: var(--r-lg); padding: 14px 16px; margin-bottom: 12px;
  transition: border-color .14s, box-shadow .14s;
}
.mural .post + .post { border-top: 1px solid var(--borda); }
.mural .post:hover { border-color: var(--borda-forte); box-shadow: var(--sombra-cartao); }
.mural .post.nova { border-left: 3px solid var(--marca); }
.mural .post .avatar-post { width: 42px; height: 42px; font-size: 14px; }

.post .cabeca .arroba { font-size: 12.5px; color: var(--tinta-muda); }
.post .cabeca .ponto-sep { color: var(--tinta-muda); }
.post .conteudo .titulo-post { font-size: 15.5px; line-height: 1.35; display: block; margin-bottom: 2px; }
.post .conteudo .chamada { font-size: 14px; line-height: 1.55; }

/* rodapé de ações: separado do conteúdo por um fio, como em post de rede */
.post .barra-post {
  display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
  margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--grade);
}

/* comentário em balão, com o avatar do lado — não uma lista de linhas */
.post .comentarios { margin-top: 10px; display: flex; flex-direction: column; gap: 7px; }
.post .comentario {
  display: flex; gap: 8px; align-items: flex-start;
  background: var(--superficie-2); border-radius: 14px; padding: 8px 11px;
}
.post .comentario .avatar { flex: none; }
.post .comentario b { font-size: 13px; display: block; }
.post .comentario .apoio { font-size: 13px; line-height: 1.45; }

@media (max-width: 700px) {
  .mural .post { padding: 12px; border-radius: var(--r-md); }
  .mural .post .avatar-post { width: 34px; height: 34px; }
}

/* barra fina dentro de uma linha de lista — usada nas horas de maior movimento
   dos Anúncios, onde o número importa mais que o gráfico */
.barra-linha {
  display: block; height: 8px; border-radius: 999px;
  background: var(--superficie-3, var(--superficie-2)); overflow: hidden; min-width: 60px;
}
.barra-linha > span { display: block; height: 100%; background: var(--marca); border-radius: 999px; }

/* a área do quadrante da BCG é clicável — e precisa parecer: cursor de mão e
   um realce leve no hover, sem virar botão desenhado por cima do gráfico */
.zona-quadrante { cursor: pointer; transition: opacity .12s; }
.zona-quadrante:hover { opacity: .8 !important; }
.zona-quadrante.ativa { opacity: .85 !important; }

/* ==========================================================================
   Fila de notícias do mercado — era uma parede de texto com links minúsculos.
   Vira cartão: fonte e data em cima, título grande, resumo em duas linhas e as
   duas decisões como botões.
   ========================================================================== */
.noticia {
  display: flex; flex-direction: column; gap: 6px;
  padding: 13px 14px; border: 1px solid var(--borda); border-radius: var(--r-md);
  background: var(--superficie); margin-bottom: 9px;
  transition: border-color .14s;
}
.noticia:hover { border-color: var(--borda-forte); }
.noticia .fonte-linha { display: flex; align-items: center; gap: 8px; font-size: 12px; }
.noticia .titulo-noticia {
  font-size: 15px; font-weight: 650; line-height: 1.35; color: var(--tinta);
  text-decoration: none;
}
.noticia .titulo-noticia:hover { color: var(--marca-tinta); text-decoration: underline; }
/* duas linhas e ponto: resumo de RSS vem com 400 caracteres e ninguém lê */
.noticia .resumo-noticia {
  margin: 0; font-size: 13px; line-height: 1.5; color: var(--tinta-2);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.noticia .acoes-noticia { display: flex; gap: 7px; margin-top: 2px; }

/* barrinha de meta dentro do cartão de indicador: mostra a folga (ou o estouro)
   sem obrigar a pessoa a comparar dois números de cabeça */
.kpi .barra-meta {
  display: block; height: 4px; border-radius: 999px; margin: 5px 0 6px;
  background: var(--superficie-3, var(--superficie-2)); overflow: hidden;
}
.kpi .barra-meta > span { display: block; height: 100%; border-radius: 999px; }

/* ==========================================================================
   O menu recolhido precisa de volta — e de um alvo que se veja.

   Em tela estreita a barra nasce em rail, mas o botão de expandir existe
   sempre. Aberta numa tela estreita, ela flutua SOBRE o conteúdo: espremer uma
   página de 1100px pra caber um menu de 240px estraga as duas coisas.
   ========================================================================== */
body.lateral-sobreposta .lateral {
  position: fixed; top: 0; bottom: 0; left: 0; z-index: 40;
  box-shadow: 0 0 0 100vmax rgba(0, 0, 0, .28), 8px 0 28px rgba(0, 0, 0, .18);
}

/* E A PÁGINA PRECISA RETOMAR A LARGURA INTEIRA.
   `.app` é uma grade de duas colunas: menu e conteúdo. Ao virar sobreposta, a
   barra sai do fluxo (`position: fixed`) e o conteúdo passa a ser o PRIMEIRO
   item da grade — herdando a coluna estreita que era do menu. Entre 900 e
   1200px a página inteira encolhia para ~270px: cartões de um palmo, tabela
   ilegível, título quebrando letra a letra. Uma coluna só resolve, e é o que a
   sobreposição sempre quis dizer — o menu passa POR CIMA, não ao lado. */
body.lateral-sobreposta .app { grid-template-columns: 1fr; }

/* o X da gaveta: no desktop a lateral é fixa e não há o que fechar */
.fechar-gaveta { display: none; }
@media (max-width: 820px) {
  .fechar-gaveta {
    display: grid; place-items: center; margin-left: auto; flex: none;
    width: 36px; height: 36px; border-radius: var(--r-md);
    border: 1px solid var(--borda); background: var(--superficie);
    color: var(--tinta-2); cursor: pointer;
  }
  .fechar-gaveta:hover { background: var(--superficie-3); color: var(--tinta); }
  .fechar-gaveta .ico { font-size: 20px; }
}

/* TELA ESTREITA: o menu é usado com pressa, e às vezes com o dedo.
   Entre 821 e 1180px a barra é rail ou sobreposta — nos dois casos as linhas
   ganham altura de alvo (36px é o mínimo confortável pra toque) e o rail ganha
   um respiro maior entre os ícones, que ali são a única pista. */
@media (max-width: 1180px) {
  .nav-item { padding: 9px 11px; }
  .nav-titulo { padding: 14px 11px 6px; }
  body.lateral-compacta .lateral .nav-bloco > .nav-item { padding: 12px 0; }
  /* o botão de recolher é o que devolve o menu inteiro: aqui ele não pode ser
     um texto cinza no pé da coluna */
  .recolher { background: var(--superficie-2); border-color: var(--borda); }
}

/* o botão de recolher/expandir vira alvo de verdade: fundo próprio, seta que
   gira e um realce claro no hover. Antes era um texto cinza que ninguém via */
.recolher {
  border-radius: var(--r-md); border: 1px solid transparent;
  transition: background .14s, border-color .14s, color .14s;
}
.recolher:hover {
  background: var(--marca-fraca); border-color: var(--borda);
  color: var(--marca-tinta);
}
.recolher:focus-visible { outline: 2px solid var(--marca); outline-offset: 2px; }
body.lateral-compacta .lateral .recolher {
  background: var(--superficie-2); border-color: var(--borda);
}
body.lateral-compacta .lateral .recolher:hover { background: var(--marca-fraca); }
@media (prefers-reduced-motion: reduce) { .recolher, .recolher .seta { transition: none; } }

/* Chegou pela busca: o destino pisca na lateral por um instante. É o que ensina
   ONDE a tela mora — da próxima vez a pessoa vai direto pelo menu, sem buscar. */
@keyframes piscar-achado {
  0%, 100% { background: transparent; }
  30%, 70% { background: var(--marca-fraca); }
}
.nav-item.achado-piscando { animation: piscar-achado 1.6s ease-in-out; }
@media (prefers-reduced-motion: reduce) {
  .nav-item.achado-piscando { animation: none; background: var(--marca-fraca); }
}

/* a fila de correção da Saúde do cardápio: cada linha é um filtro, e a ativa
   fica marcada — senão a pessoa clica e não sabe que a lista de baixo mudou */
.lista-item.linha-clicavel { cursor: pointer; border-radius: var(--r-md); transition: background .12s; }
.lista-item.linha-clicavel:hover { background: var(--superficie-2); }
.lista-item.linha-clicavel.ativo { background: var(--marca-fraca); }

/* A CONTA ABERTA da Saúde do cardápio.
   Três degraus: o total, a parte afetada, o resto. O do meio é o que o
   indicador conta — por isso é o único com peso visual. O número fica numa
   coluna de largura fixa pra que os três se alinhem e a leitura vire uma
   conta, não três frases soltas. */
/* 2px entre os degraus colava um no outro: a conta lia como um parágrafo só,
   e o degrau destacado (o do meio) não tinha ar pra se destacar de nada. */
.conta-aberta { display: flex; flex-direction: column; gap: 10px; }
.conta-aberta .passo {
  display: flex; gap: 16px; align-items: baseline;
  padding: 14px 16px; border-radius: 10px;
  border-left: 3px solid var(--borda); background: var(--superficie-2);
}
.conta-aberta .passo-num {
  flex: none; min-width: 148px; text-align: right;
  font-size: 20px; font-weight: 700; color: var(--tinta);
  font-variant-numeric: tabular-nums;
}
.conta-aberta .passo-txt { color: var(--tinta-fraca); line-height: 1.5; }
.conta-aberta .passo.destaque {
  background: var(--atencao-fraco); border-left-color: var(--atencao);
}
.conta-aberta .passo.destaque .passo-num { color: var(--atencao-tinta); font-size: 23px; }
.conta-aberta .passo.destaque .passo-txt { color: var(--atencao-tinta); }
@media (max-width: 620px) {
  .conta-aberta .passo { flex-direction: column; gap: 4px; }
  .conta-aberta .passo-num { text-align: left; min-width: 0; }
}

/* Indicadores DENTRO de um cartão (os desfechos do cancelamento).
   Menores que os do topo da tela de propósito: ali são a manchete, aqui são
   o detalhe de um bloco que já tem título. */
.kpis.embutido { gap: 8px; }
.kpis.embutido .kpi { padding: 10px 12px; }
.kpis.embutido .valor { font-size: 22px; }
.kpis.embutido .valor.menor { font-size: 18px; }

/* PREÇO EDITÁVEL na linha (complementos).
   O cliente pediu pra tirar o "R$" botão e pôr o valor numa caixa. A caixa
   precisa PARECER caixa — senão ninguém descobre que dá pra digitar — sem
   virar um formulário dentro da tabela: fundo só no hover e no foco. */
.preco-campo {
  display: inline-flex; align-items: center; gap: 3px;
  border: 1px solid transparent; border-radius: 8px;
  padding: 2px 6px; transition: border-color .12s, background .12s;
}
.preco-campo:hover { border-color: var(--borda); background: var(--fundo-2); }
.preco-campo:focus-within { border-color: var(--principal); background: var(--fundo); }
.preco-campo .cifrao { color: var(--tinta-fraca); font-size: 12px; }
.preco-campo input {
  width: 72px; border: 0; background: none; padding: 0;
  color: var(--tinta); font: inherit; text-align: right;
  font-variant-numeric: tabular-nums;
}
.preco-campo input:focus { outline: none; }
.preco-campo input:read-only { color: var(--tinta-fraca); cursor: default; }
/* preço diferente entre lojas: o campo vazio com "difere" no lugar do valor */
.preco-campo.difere input::placeholder { color: var(--atencao-tinta); font-style: italic; }
/* o spinner do number tira espaço e não serve pra preço */
.preco-campo input::-webkit-outer-spin-button,
.preco-campo input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.preco-campo input[type=number] { -moz-appearance: textfield; }

/* ÁRVORE MARCA › LOJA › ID no editor de acesso.
   O recuo é a informação: sem ele, "Volta Redonda" e os IDs dela viram uma
   lista chapada de novo — que é exatamente o que o cliente reclamou. */
/* ==========================================================================
   ONDE CADA PESSOA ALCANÇA — a célula mais densa da tabela de Equipe.

   Marca, grupo e loja avulsa são três origens da MESMA coisa, e por isso saem
   com o mesmo desenho de ficha. O que muda entre elas é a cor e o ícone.

   O corte em quatro não é economia de pixel: é a régua da tabela. Uma pessoa
   com oito lojas de nome comprido dava à linha dela quatro vezes a altura das
   outras, e a tabela existe justamente pra comparar gente lado a lado.
   ========================================================================== */
.alcance { display: flex; flex-direction: column; align-items: flex-start; gap: 5px; }
/* o TOTAL é a resposta; as fichas são de onde ela sai. Vinha depois delas,
   em cinza, ou seja: depois de a pessoa já ter desistido de ler */
.alcance-total {
  font-size: 12.5px; font-weight: 700; color: var(--tinta);
  font-variant-numeric: tabular-nums;
}
.alcance-fontes { display: flex; flex-wrap: wrap; gap: 7px; }
.alcance-fontes.cortado > :nth-child(n+5) { display: none; }
/* O "+4 origens" era um link azul solto embaixo de uma fileira de fichas
   coloridas — no meio de tanto selo, lia como mais uma etiqueta, e ninguém
   clica em etiqueta. Botão de verdade, com borda e chevron: o verbo vem na
   frente ("Ver todas") e a contagem fica de apoio, porque o que se pede ali é
   a AÇÃO e não o número. */
.btn-ver-todas { align-self: flex-start; font-size: 12px; padding: 4px 9px; gap: 4px; }
.btn-ver-todas .ic { font-size: 15px; }
.btn-ver-todas .conta {
  font-weight: 700; color: var(--tinta-muda); font-variant-numeric: tabular-nums;
}
/* A FICHA PRINCIPAL — de onde vem a maior parte do alcance.
   Marca, grupo e loja avulsa saíam todas com o mesmo peso, e quatro azuis
   iguais lado a lado não dizem por onde começar a ler. Só a primeira origem
   fica azul e com ícone; as outras seguem legíveis, de contorno, sem competir. */
.alcance-fontes .selo.ficha-mestra { font-weight: 700; }
.alcance-fontes .selo.contorno { font-weight: 500; color: var(--tinta-2); }
/* A FICHA CABE NUMA LINHA — e o nome inteiro vai no title.
   Nome de loja é comprido ("Pizza - Feita Para Você! - Volta Redonda") e a
   ficha já quebrou em duas linhas pra caber: cada uma virava um bloco de
   altura variável, e a fileira perdia a régua. Agora ela é uma linha só, um
   ponto menor que o selo comum, e só encurta quando não cabe na coluna.
   Encurtar apaga o FIM do nome, que é justamente o que distingue uma loja da
   outra ("… - Volta Redonda" contra "… - Região Oceânica") — por isso o title
   de cada ficha carrega o nome completo. */
.alcance-fontes .selo { max-width: 100%; font-size: 10.5px; padding: 4px 10px; }
.alcance-fontes .selo .ico { font-size: 13px; }
/* o corte mora no TEXTO, não no selo: `text-overflow` não age sobre o conteúdo
   direto de um flex container, e o selo é `inline-flex` por causa do ícone */
.ficha-txt { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ==========================================================================
   AS PESSOAS COM ACESSO — um bloco por pessoa dentro de UM cartão.

   Era `table.tabela.cartoes`: cinco colunas de largura disputada. Funcionava
   enquanto os nomes eram curtos. Com "Forneria Original Pizza - Feita Para
   Você! - Região Oceânica" numa célula, a coluna estourava, a linha ganhava
   quatro vezes a altura das vizinhas e a régua que a tabela existia pra dar se
   perdia justo nas pessoas mais difíceis de conferir. E os botões ficavam numa
   quinta coluna encostada na borda da TELA — em monitor largo, meio palmo de
   vão entre o nome e o botão que remove aquele nome.

   Aqui a comparação continua possível (os três campos seguem rotulados e na
   mesma ordem em toda linha), mas num grid que ENCOLHE em vez de estourar.
   Quem separa uma pessoa da outra é um fio claro, não uma borda de caixa: são
   linhas de uma lista só, e caixa dentro de caixa dobraria a moldura.
   ========================================================================== */
/* CADA PESSOA É UM CARTÃO, e não uma faixa separada por um fio.
   Com identidade, avisos, papel, alcance e telas empilhados, um fio fino entre
   um bloco e o outro não segura a leitura: cinco acessos viram uma parede de
   texto onde não dá pra dizer onde a Ana termina e o João começa. O contorno
   faz esse trabalho — é o mesmo desenho de cartão do resto do painel, aplicado
   à unidade que importa aqui, que é a pessoa. */
/* A MATRIZ DE PERMISSÕES — quem pode o quê, num olhar.
   Ela existe porque a pergunta desta tela é de COMPARAÇÃO, e comparação não
   cabe em formulários que se abrem um perfil por vez. */
/* a linha do item que vende abaixo do custo se anuncia: numa tabela de sessenta
   linhas ordenada por contribuição, ele fica NO FIM — e é o mais urgente */
.linha-prejuizo { background: var(--grave-fraco); }
.linha-prejuizo td:first-child { box-shadow: inset 3px 0 0 var(--grave); }

.matriz-permissoes th.centro, .matriz-permissoes td.centro { text-align: center; }
.matriz-permissoes th:first-child, .matriz-permissoes td:first-child {
  text-align: left; min-width: 220px;
}
/* a faixa de grupo separa Cardápio de Operação sem virar mais uma tabela */
.matriz-permissoes .linha-grupo td {
  background: var(--superficie-2); font-size: 11px; font-weight: 700;
  letter-spacing: .07em; text-transform: uppercase; color: var(--tinta-muda);
  padding: 7px 12px;
}
.celula-permissao {
  border: 1px solid transparent; background: none; cursor: pointer;
  width: 30px; height: 30px; border-radius: 8px; display: inline-grid;
  place-items: center; transition: background .12s, border-color .12s, color .12s;
}
.celula-permissao .ico { font-size: 18px; line-height: 1; }
/* verde é o que a pessoa PODE; o cinza vazado é o que ela não pode — e ele é
   discreto de propósito: a tela precisa destacar o que está liberado, que é o
   que se revisa quando alguém pergunta "por que ele conseguiu fazer isso?" */
.celula-permissao.sim { color: var(--bom-tinta); background: var(--bom-fraco); }
.celula-permissao.nao { color: var(--tinta-muda); opacity: .5; }
.celula-permissao:hover { border-color: var(--borda-forte); opacity: 1; }
.celula-permissao:disabled { opacity: .35; cursor: wait; }
/* o ✓ do ADM não é botão: mesma cor, sem caixa, pra não convidar o clique */
/* o perfil não editável mostra o estado sem caixa de botão: mesma informação,
   sem convidar um clique que seria recusado */
.matriz-permissoes .marca-sim { color: var(--bom-tinta); font-size: 18px; }
.matriz-permissoes .marca-nao { color: var(--tinta-muda); font-size: 18px; opacity: .45; }

.pessoas { display: flex; flex-direction: column; gap: 10px; padding: 2px; }
.pessoa {
  padding: 14px 16px;
  border: 1px solid var(--borda);
  border-radius: 12px;
  background: var(--superficie);
  transition: border-color .12s ease, box-shadow .12s ease;
}
.pessoa:hover { border-color: var(--borda-forte); }
/* quem tem aviso grave se anuncia pela borda esquerda: numa lista longa é o
   que faz o olho parar antes de ler, que é o ponto do aviso */
.pessoa:has(.aviso-leve.ruim) { border-left: 3px solid var(--grave); }
.pessoa:has(.aviso-leve.atencao):not(:has(.aviso-leve.ruim)) {
  border-left: 3px solid var(--atencao);
}

/* a linha de identidade: quem é, e o que dá pra fazer com essa pessoa */
.pessoa-topo { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.pessoa-quem { min-width: 0; flex: 1 1 200px; }
.pessoa-quem strong { font-size: 14.5px; }
.pessoa-quem .apoio { color: var(--tinta-muda); font-size: 12.5px; }

/* AS AÇÕES DE UMA LINHA — só o ícone, sem caixa.
   Vale para as três listas desta tela (pessoas, grupos e perfis): botões com
   borda e rótulo repetidos em toda linha viram uma grade de caixinhas que
   compete com o conteúdo que a lista existe pra mostrar. O que cada um faz sai
   no title, ao passar o mouse. */
.acoes-icones { display: flex; align-items: center; gap: 2px; }
/* na linha da pessoa, a fileira termina a linha dela — e não a da tela */
.pessoa-acoes { margin-left: auto; }
/* O DESTRUTIVO GUARDA A COR EM REPOUSO.
   `.acao-discreta.perigo` deixa "apagar" cinza até o hover — certo nos posts,
   onde as quatro ações do dono são igualmente reversíveis. Aqui não: sem
   rótulo, a cor é a ÚNICA coisa que separa "remover o acesso da Ana" dos
   vizinhos inofensivos, e cinza-até-o-hover a esconderia justo de quem passa
   o olho rápido. */
.acoes-icones .btn.so-icone.acao-discreta.perigo { color: var(--grave-tinta); }
.acoes-icones .btn.so-icone.acao-discreta.perigo:hover { background: var(--grave-fraco); }

/* O AVISO DO ACESSO — linha discreta, colada na identidade de quem o tem.
   A faixa com fundo colorido foi tentada e desfeita: quase toda pessoa da lista
   tem pelo menos um aviso, e três linhas de âmbar por pessoa empurravam o resto
   do bloco pra baixo até caber só metade da lista na tela. Aviso que aparece em
   toda linha para de ser interrupção e vira o fundo. O ícone separa os níveis e
   o motivo fica no title. */
.aviso-leve { display: flex; gap: 5px; align-items: flex-start; margin-top: 4px; }
.aviso-leve .ic.ico { font-size: 14px; line-height: 1.35; flex: none; }

/* os três campos: papel, alcance e telas — rotulados, na mesma ordem em toda
   linha. `auto-fit` + `minmax` é o que encolhe em vez de estourar: em tela
   larga eles ficam alinhados entre pessoas, em tela estreita empilham. */
/* Os campos ficam num bloco recuado do cabeçalho: quem é a pessoa é uma
   pergunta, o que ela alcança é outra, e a faixa mais clara diz isso sem
   precisar de um título. */
.pessoa-campos {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: 12px 18px; margin-top: 12px;
  padding: 12px 14px;
  background: var(--superficie-2);
  border-radius: 9px;
}
.pessoa-campo { min-width: 0; }
/* a coluna do alcance é a densa: ela pede o dobro QUANDO HÁ ESPAÇO. O `span 2`
   fora da media query criaria uma coluna implícita nas larguras em que o
   `auto-fit` só cabe uma — e aí o campo vazaria o cartão pra fora. */
@media (min-width: 721px) {
  .pessoa-campo.alcance-campo { grid-column: span 2; }
}
.rotulo-campo {
  font-size: 10.5px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
  color: var(--tinta-muda); margin-bottom: 5px;
}

@media (max-width: 720px) {
  .pessoa-campos { grid-template-columns: 1fr; }
  /* no celular os três ícones continuam ao lado do nome — cabem, e mandá-los
     pra linha de baixo só criaria uma faixa vazia. O alvo de toque é que
     cresce: 5px de padding num glifo de 17px dá menos que os 44px de dedo. */
  .acoes-icones .btn.so-icone.pequeno { padding: 9px; }
}

.arvore-acesso { display: flex; flex-direction: column; gap: 2px; }
.arvore-marca {
  display: flex; align-items: center; gap: 6px;
  font-weight: 600; color: var(--tinta-fraca);
  text-transform: uppercase; letter-spacing: .04em; font-size: 11px;
  padding: 2px 0 6px;
}
.arvore-praca + .arvore-praca { margin-top: 6px; }
.arvore-praca .opcao.praca { padding: 5px 6px; border-radius: 8px; }
.arvore-praca .opcao.praca:hover { background: var(--fundo-2); }
.arvore-ids {
  display: flex; flex-direction: column; gap: 1px;
  margin-left: 12px; padding-left: 12px;
  border-left: 1px solid var(--borda);
}
.arvore-ids .opcao { padding: 4px 6px; border-radius: 8px; }
.arvore-ids .opcao:hover { background: var(--fundo-2); }
.arvore-acesso .mono { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 11px; }

/* Nome escrito ao lado do ponto na dispersão da BCG.
   Menor e mais apagado que o texto normal de propósito: ele identifica o
   ponto, não compete com ele. Sem eventos de ponteiro pra não roubar o
   hover da bolinha, que é onde está o número completo. */
.rotulo-ponto {
  font-size: 10.5px; fill: var(--tinta-fraca);
  pointer-events: none; paint-order: stroke;
  stroke: var(--fundo); stroke-width: 3px; stroke-linejoin: round;
}

/* Editor de permissões de um perfil.
   Agrupado como a pessoa pensa (Cardápio, Operação, Dinheiro), não como o
   código nomeia. Duas colunas quando cabe: a lista inteira numa coluna só
   vira rolagem, e rolagem esconde o que a pessoa está prestes a tirar. */
.permissoes {
  display: grid; gap: 16px;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
}
.permissao-grupo { display: flex; flex-direction: column; gap: 2px; }
.permissao-titulo {
  font-size: 11px; font-weight: 700; letter-spacing: .05em;
  text-transform: uppercase; color: var(--tinta-fraca);
  padding-bottom: 4px; border-bottom: 1px solid var(--borda); margin-bottom: 4px;
}
.permissao-grupo .opcao { padding: 5px 6px; border-radius: 8px; }
.permissao-grupo .opcao:hover { background: var(--fundo-2); }

/* Linha de categoria escolhida na Saúde do cardápio: a lista de baixo está
   filtrada por ela, e a tabela precisa dizer qual é sem a pessoa rolar. */
.tabela tr[data-categoria] { cursor: pointer; }
.tabela tr[data-categoria]:hover { background: var(--fundo-2); }
.tabela tr[data-categoria].ativo { background: var(--info-fraco); box-shadow: inset 3px 0 0 var(--marca); }

/* ==========================================================================
   FUNIL DE PEDIDOS
   O desenho é um funil de verdade — trapézios que estreitam —, e não barras
   empilhadas: a FORMA é a informação. Quem olha acha a perda antes de ler
   qualquer número, e é isso que uma tela de funil tem que entregar.
   ========================================================================== */
.funil-rotulo {
  font-size: 13px; font-weight: 600; fill: var(--tinta);
  pointer-events: none; paint-order: stroke;
  stroke: var(--fundo); stroke-width: 3px; stroke-linejoin: round;
}
.funil-numero {
  font-size: 12px; fill: var(--tinta-fraca);
  font-variant-numeric: tabular-nums; pointer-events: none;
  paint-order: stroke; stroke: var(--fundo); stroke-width: 3px; stroke-linejoin: round;
}
/* a perda fica na lateral, na altura da junção onde ela acontece */
.funil-perda {
  font-size: 11.5px; font-weight: 600; fill: var(--grave-tinta);
  font-variant-numeric: tabular-nums; pointer-events: none;
}
.bolinha-funil {
  display: inline-block; width: 9px; height: 9px; border-radius: 50%;
  margin-right: 6px; vertical-align: 0;
}
/* quadradinho de legenda embaixo de gráfico com duas séries */
.legenda-cor {
  display: inline-block; width: 10px; height: 10px; border-radius: 3px;
  margin: 0 3px 0 8px; vertical-align: -1px;
}
.legenda-cor:first-child { margin-left: 0; }

/* O cartão "quanto dá pra ganhar" no Funil.
   A borda esquerda verde separa a leitura de OPORTUNIDADE da leitura de perda
   que vem logo acima: são a mesma conta virada, e o olho precisa saber que
   virou. */
.cartao.destaque-ganho { border-left: 3px solid var(--bom); }

/* "Quanto falta pra bater a meta", no Super.
   Cada meta furada vira uma linha com o tamanho do buraco. O recuo separa a
   tarefa (negrito) da explicação (apoio) sem precisar de mais uma caixa. */
.falta-lista { display: flex; flex-direction: column; gap: 8px; margin-top: 6px; }
.falta-item { padding-left: 10px; border-left: 2px solid currentColor; opacity: .95; }
.falta-item .apoio { margin-top: 1px; }

/* "O que ampliar e o que cortar", em Investimentos.
   Os dois grupos precisam ser lidos como DECISÕES opostas, não como uma lista
   longa — daí o título colorido e o respiro entre eles. */
.grupo-veredito + .grupo-veredito { margin-top: 18px; }
.titulo-veredito {
  display: flex; align-items: center; gap: 6px;
  font-size: 12.5px; font-weight: 700; margin-bottom: 6px;
  padding-bottom: 5px; border-bottom: 1px solid var(--borda);
}
.titulo-veredito.bom { color: var(--bom-tinta); border-bottom-color: #c9e9c9; }
.titulo-veredito.grave { color: var(--grave-tinta); border-bottom-color: #f4cccb; }
.titulo-veredito .ic { font-size: 17px; }

/* As sete regras de ".mudou-*" saíram daqui: elas desenhavam a grade de
   variações do "O que mudou", e o bloco virou frase — as variações lidas em
   conjunto, que é o que a ajuda dele promete. Nenhum arquivo do painel escrevia
   mais essas classes; CSS que sobrevive ao HTML que ele pintava é peso morto
   que ainda por cima sugere um desenho que não existe. */

/* "Onde o tempo se perde" — os trechos do pedido como uma trilha.
   A largura de cada bloco é proporcional ao tempo que ele consome: o trecho
   que come o relógio fica visivelmente maior, e a pessoa vê antes de ler. */
.trilha-tempo { display: flex; gap: 3px; }
.trecho {
  min-width: 0; padding: 12px 14px; border-radius: 10px;
  background: var(--fundo-2); border: 1px solid var(--borda);
}
.trecho.maior { background: var(--atencao-fraco); border-color: #f4e0bd; }
.trecho-rotulo { font-size: 11.5px; color: var(--tinta-fraca); margin-bottom: 3px; }
.trecho.maior .trecho-rotulo { color: var(--atencao-tinta); }
.trecho-tempo { font-size: 20px; font-weight: 700; font-variant-numeric: tabular-nums; }
.trecho.maior .trecho-tempo { color: var(--atencao-tinta); }
.trecho-quem { font-size: 11px; color: var(--tinta-fraca); margin-top: 2px; }
@media (max-width: 620px) { .trilha-tempo { flex-direction: column; } .trecho { flex: none !important; } }

/* Campanhas com veredito, em Promoções.
   Chips em vez de tabela: aqui a pessoa está com a mão no botão de ligar e
   desligar, e precisa reconhecer o nome — não comparar oito colunas. */
.linha-campanhas { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.chip-campanha {
  display: flex; flex-direction: column; gap: 1px;
  padding: 7px 11px; border-radius: 10px;
  border: 1px solid var(--borda); background: var(--fundo-2);
}
.chip-campanha.bom { border-color: #c9e9c9; background: var(--bom-fraco); }
.chip-campanha.grave { border-color: #f4cccb; background: var(--grave-fraco); }
.chip-campanha .apoio { font-size: 11px; }

/* Curva ABC do cardápio.
   As três faixas lado a lado, com a letra grande à esquerda: a leitura é
   comparativa (quantos itens em cada grupo), e empilhar em lista faria a
   pessoa somar de cabeça. */
.grade-abc { display: grid; gap: 10px; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); }
.faixa-abc {
  display: flex; gap: 12px; align-items: flex-start;
  padding: 14px; border-radius: 12px;
  border: 1px solid var(--borda); background: var(--fundo-2);
}
.faixa-abc.bom { border-color: #c9e9c9; background: var(--bom-fraco); }
.faixa-abc.atencao { border-color: #f4e0bd; background: var(--atencao-fraco); }
.faixa-letra {
  font-size: 30px; font-weight: 800; line-height: 1;
  color: var(--tinta-fraca); flex: none; width: 30px; text-align: center;
}
.faixa-abc.bom .faixa-letra { color: var(--bom-tinta); }
.faixa-abc.atencao .faixa-letra { color: var(--atencao-tinta); }
.faixa-corpo { min-width: 0; }
.faixa-numero { font-size: 17px; font-weight: 700; }
.faixa-valor { font-size: 12.5px; color: var(--tinta-fraca); margin: 1px 0 3px; font-variant-numeric: tabular-nums; }

/* "O prazo que o cliente viu" — as três faixas do despacho.
   A largura é proporcional à quantidade: quem sai já atrasado ocupa a fatia
   que merece na barra, e a proporção se lê antes do número. */
.barra-promessa { display: flex; gap: 3px; margin-top: 14px; }
.faixa-promessa {
  min-width: 0; padding: 10px 12px; border-radius: 8px;
  background: var(--fundo-2); border: 1px solid var(--borda);
}
.faixa-promessa.bom { background: var(--bom-fraco); border-color: #c9e9c9; }
.faixa-promessa.atencao { background: var(--atencao-fraco); border-color: #f4e0bd; }
.faixa-promessa.grave { background: var(--grave-fraco); border-color: #f4cccb; }
.faixa-n { font-size: 18px; font-weight: 700; font-variant-numeric: tabular-nums; }
.faixa-promessa.bom .faixa-n { color: var(--bom-tinta); }
.faixa-promessa.atencao .faixa-n { color: var(--atencao-tinta); }
.faixa-promessa.grave .faixa-n { color: var(--grave-tinta); }
.faixa-txt { font-size: 11.5px; color: var(--tinta-fraca); }

/* ---------------------------------------------------------------- calculadoras
   Contas que decidem preço e modelo de entrega. A regra da tela é mostrar o
   CAMINHO, não só o resultado: cada linha da conta nomeada, com o seu valor e o
   seu sinal. Foi o defeito que o cliente apontou na calculadora que ele já
   usava — uma linha somava comissão e taxa de pagamento, e escondia qual das
   duas pesava. */
.grade-calc { display: grid; grid-template-columns: minmax(280px, 340px) 1fr; gap: 16px; align-items: start; }
@media (max-width: 900px) { .grade-calc { grid-template-columns: 1fr; } }

.campo-calc { display: block; margin-top: 12px; }
.rotulo-calc { display: block; font-size: 12px; font-weight: 600; color: var(--tinta-muda); margin-bottom: 4px; }
.rotulo-calc i { display: block; font-weight: 400; font-style: normal; opacity: .75; font-size: 11px; }
.entrada-calc { display: flex; align-items: stretch; border: 1px solid var(--borda); border-radius: 8px; overflow: hidden; }
.entrada-calc:focus-within { border-color: var(--marca); box-shadow: 0 0 0 3px var(--marca-fraca); }
.entrada-calc b { display: flex; align-items: center; padding: 0 9px; background: var(--fundo-fraco);
  color: var(--tinta-muda); font-size: 12px; font-weight: 600; border-right: 1px solid var(--borda); }
.entrada-calc input { flex: 1; min-width: 0; border: 0; outline: 0; background: transparent;
  padding: 9px 10px; font-size: 14px; color: var(--tinta); font-variant-numeric: tabular-nums; }

.duas-contas { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
@media (max-width: 760px) { .duas-contas { grid-template-columns: 1fr; } }

/* A RÉGUA DE QUILÔMETROS.
   O limite sozinho ("até 12 km") seria um número solto que a pessoa aceita ou
   não. Vendo o lucro encolher quilômetro a quilômetro, ela entende que o
   problema não começa na fronteira — começa muito antes dela. A barra vermelha
   cresce pro mesmo lado da azul de propósito: o que importa é o tamanho do
   prejuízo, e espelhar o eixo faria a pessoa ler dois gráficos em vez de um. */
.faixa-km { display: flex; align-items: center; gap: 10px; padding: 5px 0; font-size: 13px; }
.faixa-km + .faixa-km { border-top: 1px solid var(--grade); }
.faixa-km .km { flex: 0 0 46px; color: var(--tinta-2); font-variant-numeric: tabular-nums; }
.faixa-km .barra-km { flex: 1; height: 8px; border-radius: 999px; background: var(--grade); overflow: hidden; }
.faixa-km .barra-km i { display: block; height: 100%; background: var(--serie-1); border-radius: 999px; }
.faixa-km b { flex: 0 0 88px; text-align: right; font-variant-numeric: tabular-nums; }
.faixa-km.negativa .barra-km i { background: var(--grave); }
.faixa-km.negativa b { color: var(--grave-tinta); }

.cartao-conta { background: var(--cartao); border: 1px solid var(--borda); border-radius: 12px; padding: 14px 16px; }
/* o vencedor não muda de cor de fundo: muda a borda. Fundo colorido em cima de
   número faz a pessoa ler a cor antes do valor */
.cartao-conta.vencedor { border-color: var(--bom); box-shadow: 0 0 0 1px var(--bom); }
.topo-conta h3 { margin: 0; font-size: 15px; display: flex; align-items: center; gap: 8px; }
.topo-conta .apoio { margin: 2px 0 10px; }

.linha-conta { display: flex; justify-content: space-between; gap: 12px; align-items: baseline;
  padding: 7px 0; border-bottom: 1px dashed var(--borda-fraca); font-size: 13px; }
.linha-conta b { font-variant-numeric: tabular-nums; white-space: nowrap; }
.linha-conta.sai b { color: var(--ruim); }
.linha-conta.entra b { color: var(--tinta); }
.linha-conta.total { border-bottom: 0; border-top: 2px solid var(--borda); margin-top: 6px;
  padding-top: 10px; font-weight: 600; font-size: 15px; }
.pe-conta { margin-top: 8px; }

.veredito { display: flex; gap: 12px; align-items: flex-start; padding: 14px 16px; margin-bottom: 14px;
  background: var(--bom-fraco); border: 1px solid var(--bom); border-radius: 12px; }
.veredito.ruim { background: var(--ruim-fraco); border-color: var(--ruim); }
.veredito .ico { font-size: 22px; }

.ressalvas { margin-top: 14px; }
.ressalvas h4 { margin: 0 0 8px; font-size: 13px; color: var(--tinta-muda); }
.ressalva { display: flex; gap: 8px; align-items: flex-start; padding: 5px 0; font-size: 13px; }
.ressalva .ico { font-size: 16px; margin-top: 1px; }
.ressalva.full .ico { color: var(--bom); }
.ressalva.propria .ico { color: var(--ruim); }

/* A FAIXA DA CATEGORIA na tabela de sabores.
   Ela é um cabeçalho dentro do corpo: fundo próprio pra se separar das linhas,
   e o texto sem o peso de um dado — quem manda ali é o nome da categoria e a
   caixa que marca todos os sabores dela de uma vez. */
tr.faixa-categoria td { background: var(--superficie-2); border-bottom: 1px solid var(--borda); }
tr.faixa-categoria b { font-size: 13px; }
tr.faixa-categoria .apoio { margin-left: 8px; font-size: 12px; }
tr.faixa-categoria:hover td { background: var(--superficie-2); }

/* A árvore de telas no editor de acesso — mesma linguagem da árvore de lojas
   que já existe ali, pra as duas perguntas (onde entra / de quem são os
   números) se responderem do mesmo jeito. */
.arvore-acesso .ramo { padding: 6px 0; border-bottom: 1px dashed var(--borda-fraca); }
.arvore-acesso .ramo:last-child { border-bottom: 0; }
.arvore-acesso .galho { display: flex; align-items: center; gap: 8px; font-size: 13px; cursor: pointer; }
.arvore-acesso .galho .apoio { margin-left: auto; }
.arvore-acesso .folhas { display: grid; grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
  gap: 2px 12px; padding: 6px 0 4px 26px; }
.arvore-acesso .folha { display: flex; align-items: center; gap: 7px; font-size: 12.5px;
  color: var(--tinta-muda); cursor: pointer; padding: 2px 0; }

/* O mapa em tela cheia — ponto 51 da call. É o MESMO nó do mapa, movido pra
   cá e devolvido depois: um segundo mapa custaria o dobro de memória e perderia
   o zoom de quem expandiu. */
.mapa-cheio { position: fixed; inset: 0; z-index: 900; background: var(--fundo);
  display: flex; flex-direction: column; }
.mapa-cheio-topo { display: flex; align-items: center; gap: 12px; padding: 12px 16px;
  border-bottom: 1px solid var(--borda); background: var(--cartao); }
.mapa-cheio-topo .apoio { flex: 1; }
.mapa-cheio > #mapa { flex: 1; min-height: 0; height: auto !important; border-radius: 0; }
body.sem-rolagem { overflow: hidden; }

/* AS AÇÕES EM LOTE, no cabeçalho da tabela.
   Eram uma barra preta grudada no pé da janela: flutuando, ela tapava as duas
   últimas linhas da tabela — justamente quando a pessoa estava escolhendo
   linha, e o que ela precisava ver estava embaixo dela. Aqui usam a mesma
   faixa dos filtros, então não destoam de nada. */
.cabeca-tabela.acoes-lote {
  border-top: 1px solid var(--grade);
  background: var(--superficie-2);
}
.cabeca-tabela.acoes-lote .apoio { font-size: 12.5px; }

/* BOTÃO MIÚDO — a medida do selo que fica ao lado.
   Na linha do complemento, o botão do tamanho normal ficava mais alto que o
   selo "1 de 4 pausado(s)" e a linha desalinhava. Aqui ele tem a altura do
   selo: continua clicável (o alvo é o retângulo inteiro), e a linha lê como
   uma linha. */
.btn.miudo {
  /* a conta é a do selo: 3px de padding em cima e embaixo + a linha de texto.
     O selo não tem borda e o botão tem, então a linha aqui é 1px mais baixa —
     é o que faz os dois fecharem em ~23px e a linha parar de serrilhar. */
  padding: 3px 9px; font-size: 11.5px; gap: 5px; border-radius: 20px; line-height: 1.35;
}
.btn.miudo > .ic { font-size: 13px; }
/* só o ícone: o glifo é quadrado e mais alto que a letra, então o padding
   lateral cai e a altura continua a mesma dos irmãos com texto */
.btn.miudo.so-icone { padding: 3px 7px; line-height: 15px; }
.btn.miudo.so-icone > .ic { font-size: 15px; line-height: 15px; }
/* a caixa que marca o item inteiro: sem vão, porque o rótulo é o próprio nome
   do item, que vem logo ao lado */
.cabeca-item .opcao.so-caixa { margin-right: 2px; }

/* o balão encolhido: só o ícone, no canto. O rótulo sai da largura, não da
   opacidade — escondido por transparência ele continuaria cobrindo o botão
   de baixo, que é o problema que este estado resolve */
.balao-suporte.so-icone { padding: 12px; gap: 0; }
.balao-suporte.so-icone .rotulo { display: none; }

/* A área desenhada no mapa — ponto 52. A camada fica POR CIMA do mapa e captura
   o clique: sem isso o clique cairia no mapa e viraria arrasto. */
.area-camada { position: absolute; inset: 0; z-index: 5; cursor: crosshair; }
.area-traco { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }
.area-traco path { fill: color-mix(in srgb, var(--marca) 16%, transparent);
  stroke: var(--marca); stroke-width: 2; stroke-dasharray: 6 4; }
.area-traco circle { fill: var(--cartao); stroke: var(--marca); stroke-width: 2; }
.area-dica { position: absolute; left: 12px; right: 12px; bottom: 12px; cursor: default;
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  background: var(--cartao); border: 1px solid var(--borda); border-radius: 10px;
  padding: 9px 12px; font-size: 12.5px; box-shadow: 0 6px 20px rgba(0,0,0,.14); }
.area-dica .btn { margin-left: auto; }
#mapa { position: relative; }

/* A ESCOLHA PENDENTE no seletor de lojas.
   O painel guarda um rascunho e só filtra ao clicar em Aplicar — o que é certo,
   senão desmarcar onze lojas dispararia onze requisições. O que faltava era
   dizer que a escolha ainda não valeu: painel certo e mudo, na prática, é o
   mesmo que painel errado. */
#contaLojas.pendente { color: var(--marca); font-weight: 600; }
#aplicarLojas.pulsando { box-shadow: 0 0 0 3px var(--marca-fraca); }
@media (prefers-reduced-motion: no-preference) {
  #aplicarLojas.pulsando { animation: pulso-aplicar 1.6s ease-in-out infinite; }
}
@keyframes pulso-aplicar {
  0%, 100% { box-shadow: 0 0 0 3px var(--marca-fraca); }
  50% { box-shadow: 0 0 0 6px transparent; }
}

/* O botão de copiar o número do pedido, na linha de cancelamento. Discreto até
   o mouse chegar: a coluna é do NÚMERO, e um ícone forte competiria com ele. */
.btn-copiar { border: 0; background: transparent; cursor: pointer; padding: 2px 4px;
  color: var(--tinta-muda); opacity: .5; vertical-align: -3px; border-radius: 5px; }
.btn-copiar:hover, .btn-copiar:focus-visible { opacity: 1; background: var(--fundo-fraco); }
.btn-copiar .ico { font-size: 15px; }

/* O aviso de "tem loja marcada fora desta busca", no seletor de lojas.
   Cor de atenção e não de erro: nada quebrou, a pessoa só está prestes a
   aplicar mais do que está vendo. Ver contarLojas(), no index.html. */
#foraDaBusca {
  margin: 6px 2px 0; padding: 7px 10px;
  border: 1px solid color-mix(in srgb, var(--atencao) 35%, transparent);
  background: color-mix(in srgb, var(--atencao) 10%, transparent);
  border-radius: var(--r-sm); font-size: 12px; line-height: 1.45;
}

/* ==========================================================================
   ROLAGEM QUE NÃO ESCAPA — as sobreposições flutuantes

   Toda camada `position: fixed` que rola por dentro tem que CONTER a rolagem.
   A razão é específica dessas camadas: quando a lista de dentro chega ao fim,
   o navegador repassa o resto do gesto pra página — e a página anda enquanto a
   camada, por ser fixa, não anda. O olho vê o conteúdo de trás disparar sob um
   painel imóvel, que é a definição prática de "bugou".

   A lateral e o chat de suporte já tinham a regra, cada um descoberto do seu
   jeito. As quatro daqui ficaram de fora, e o filtro de lojas — o mais usado
   dos quatro — virou relato de cliente duas vezes. Ficam juntas pra que a
   próxima camada flutuante herde a decisão em vez de repetir o aprendizado.
   ========================================================================== */
.painel-busca,
.painel-notificacoes .lista,
.modal-corpo.rolavel,
.previa { overscroll-behavior: contain; }

/* ==========================================================================
   O QUE A API DO IFOOD NÃO LIBERA, quando a instalação escolhe não mostrar

   Pedido do cliente: "as coisas que a gente está dependendo da API pra
   funcionar, a gente podia ocultar. Pra não ficar tão zoado". A chave está em
   Configurações e liga a classe `sem-travado` no <html>.

   `display: none` e não `visibility` nem opacidade: o aviso escondido não pode
   deixar buraco de espaçamento no meio da tela, senão troca "parece quebrado"
   por "parece mal montado".

   O QUE NÃO LEVA [data-trava]: o aviso que manda a pessoa resolver no Portal.
   "Estes 4 cancelamentos são contestáveis" é dinheiro de volta, não é beco sem
   saída — some com essa chave e o cliente perde a recuperação sem saber que
   perdeu. A regra inteira está em src/travas-ifood.js.
   ========================================================================== */
.sem-travado [data-trava] { display: none !important; }

/* ==========================================================================
   SEM CONEXÃO — a faixa que diz de onde vem o zero

   Apareceu quando o painel virou app instalável. Antes, sem internet o
   navegador mostrava a página de erro dele. Agora o painel ABRE offline, e
   abria pintando "CANCELAMENTOS 0 — nenhum hoje": cada card certo no que sabe,
   o conjunto mentindo, porque zero por não ter acontecido e zero por não ter
   chegado ficavam idênticos na tela.

   Fica no topo do <body> e empurra o resto, em vez de flutuar por cima: cobrir
   o cabeçalho esconderia justamente o botão de atualizar. E não tem botão de
   fechar — dispensar o aviso e seguir lendo número velho como se fosse de agora
   é exatamente o que ela existe pra impedir.
   ========================================================================== */
.faixa-sem-conexao {
  display: flex; align-items: center; gap: 10px;
  padding: 9px 16px; font-size: 13px; line-height: 1.45;
  background: var(--atencao-fraco); color: var(--atencao-tinta);
  border-bottom: 1px solid var(--atencao);
  position: sticky; top: 0; z-index: 60;
}
.faixa-sem-conexao .ico { font-size: 19px; flex: none; }

/* ==========================================================================
   O QUE SÓ QUEBRA NO CELULAR

   A varredura visual passou a rodar em 393px (ver testes/varrer-visual.js), e a
   primeira passada achou cinco telas com conteúdo saindo da caixa. Nenhuma
   aparecia no desktop: com 1500px de largura todo mundo cabe, e o defeito só
   existe quando o espaço acaba.

   A família é uma só — filho que não pode encolher nem quebrar linha. Em flex e
   grid o padrão é `min-width: auto`, que significa "não encolha abaixo do meu
   conteúdo": num nome de loja comprido ou num botão com texto, isso empurra o
   filho pra fora do pai em vez de espremê-lo. Cada regra abaixo traz a medida
   que a acusou.
   ========================================================================== */
@media (max-width: 820px) {
  /* Medido em /qualidade: `.acoes-linha` com 3px de largura e botões de 33 e
     146px dentro, sobrando 182px pra fora do cartão. Alinhados à direita e sem
     quebra, os botões saíam da tela em vez de descer pra linha de baixo. */
  .acoes-linha {
    flex-wrap: wrap; justify-content: flex-start; min-width: 0; width: 100%;
  }

  /* Medido em /estratificacao: o LABEL com 339px dentro de uma linha de 327.
     O `min-width: 190px` do select é bom no desktop, onde sobra espaço, e é
     exatamente o que estoura quando não sobra. `min()` mantém os 190 enquanto
     couberem e cede a partir daí. */
  .campo-inline { flex-wrap: wrap; min-width: 0; }
  .campo-inline select { min-width: min(190px, 100%); max-width: 100%; }

  /* Medido em /equipe: `.alcance-fontes` com 319px dentro de 251. Ela já
     quebrava linha; quem não encolhia era a FICHA, com o nome da loja inteiro
     dentro. Agora a ficha cede e o nome é cortado com reticências — nome
     cortado se lê, ficha fora da tela não. */
  .alcance, .alcance-fontes { min-width: 0; max-width: 100%; }
  .alcance-fontes > * {
    min-width: 0; max-width: 100%;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }

  /* Medido em /diagnostico: nome de loja em <strong> com 87px dentro de um
     bloco de 49. Quebrar a palavra é feio e é melhor que sumir com metade do
     nome — aqui o nome é o que diz de qual loja se está falando. */
  .cartao strong { min-width: 0; overflow-wrap: anywhere; }
}
