/* ============================================================ *
 * Mandala Chat — folha única, organizada por blocos.
 * Paleta monocromática (preto e branco) da UNNE Móveis.
 * Marca UNNE: preto e branco. O acento é claro (texto preto sobre ele).
 * ============================================================ */

/* ------------------------------ 1. Tokens ------------------------------ */
:root {
  --md-laranja: #F5F1EC;
  --md-laranja-luz: #FFFFFF;
  --md-preto: #0A0808;
  --md-branco: #FFFFFF;
  --md-neutro: #F5F1EC;
  --md-vermelho: #F93F06;
  --md-laranja-texto: #1A1A1A;
  --md-laranja-borda: #1A1A1A;
  --md-verde: #2E7D46;

  --cor-superficie: var(--md-neutro);
  --cor-cartao: var(--md-branco);
  --cor-cartao-alt: #FAF7F3;
  --cor-texto: var(--md-preto);
  --cor-texto-fraco: #6B6360;
  --cor-borda: rgba(10, 8, 8, 0.12);
  --cor-borda-forte: rgba(10, 8, 8, 0.28);
  --cor-barra: var(--md-preto);
  --cor-realce: #EDEDED;
  --cor-realce-texto: #333333;
  --cor-bolha: var(--md-branco);
  --cor-bolha-minha: #E9E9E9;
  --sombra-1: 0 1px 2px rgba(10, 8, 8, 0.04);
  --sombra-2: 0 4px 16px rgba(10, 8, 8, 0.07);

  --e-1: 4px; --e-2: 8px; --e-3: 12px; --e-4: 16px;
  --e-5: 24px; --e-6: 32px; --e-7: 48px;
  --raio: 6px;
  --fonte: 'Inter', system-ui, -apple-system, 'Segoe UI', sans-serif;

  --largura-lateral: 208px;
  --largura-lista: 344px;
  --largura-detalhes: 304px;
  --altura-cabecalho: 60px;

  /* Tamanho do texto da conversa. O corpo do chat multiplica por isto,
     então o A+/A− mexe em tudo junto — bolha, autor e hora — em vez de
     só na letra, que desalinharia o resto. */
  --escala-chat: 1;
  /* Altura dos filtros da lista. Os botões "Todas/Grupos/Diretas" e a
     lista de etiquetas tinham cada um a sua conta de padding, e davam
     alturas diferentes na mesma linha. Agora saem daqui os dois. */
  --altura-filtro: 24px;
  /* Altura do rodapé da conversa. A barra de escrever e a de gravar se
     substituem, então as duas saem daqui: com contas independentes elas
     davam 63 e 61px, e tocar no microfone fazia a conversa pular. */
  --altura-redator: 63px;
  /* Altura dos cinco controles da barra de escrever. O campo tinha 44px
     (a linha do texto mais a folga) e os botões 42px — com alinhamento
     pelo rodapé, o centro do campo ficava 1px acima do dos botões. Um
     pixel basta para a linha parecer torta. Agora os cinco saem daqui. */
  --altura-campo: 44px;
  /* Lado do botão de enviar. Ele é o único controle da barra que precisa
     ser QUADRADO, e `aspect-ratio` não dá conta disso num item de flex
     esticado: o flex resolve a LARGURA pelo conteúdo antes de esticar a
     altura, então a proporção era ignorada e o botão saía oval — era o
     "ovo laranja" que aparecia no celular. Medida explícita, que
     acompanha o zoom do chat como o campo ao lado. */
  --lado-enviar: calc(44px * var(--escala-chat));
}

/* Tema escuro: só os tokens mudam, nenhum componente sabe qual está ativo. */
[data-tema='escuro'] {
  --cor-superficie: #141110;
  --cor-cartao: #1D1917;
  --cor-cartao-alt: #241F1C;
  --cor-texto: #F5F1EC;
  --cor-texto-fraco: #A79E99;
  --cor-borda: rgba(245, 241, 236, 0.12);
  --cor-borda-forte: rgba(245, 241, 236, 0.26);
  --cor-barra: #0A0808;
  --cor-realce: #2A2A2A;
  --cor-realce-texto: #D0D0D0;
  --cor-bolha: #241F1C;
  --cor-bolha-minha: #2C2C2C;
  --md-laranja-texto: #F5F1EC;
  --md-laranja-borda: #F5F1EC;
  --sombra-1: 0 1px 2px rgba(0, 0, 0, 0.4);
  --sombra-2: 0 6px 20px rgba(0, 0, 0, 0.45);
  color-scheme: dark;
}

/* ------------------------------ 2. Base -------------------------------- */
* { box-sizing: border-box; }
html, body, #app { height: 100%; }
body {
  margin: 0;
  font-family: var(--fonte);
  font-size: 14px;
  color: var(--cor-texto);
  background: var(--cor-superficie);
  overflow: hidden;
}
button, input, textarea, select { font: inherit; color: inherit; }
:focus-visible { outline: 2px solid var(--md-laranja-borda); outline-offset: 2px; }

/* Em campo e pílula o anel com folga desenha uma SEGUNDA borda em volta
   da que já existe — parece defeito de alinhamento, não foco. Aqui ele
   encosta na borda do elemento e vira realce, que é o que deveria ser. */
input:focus-visible, textarea:focus-visible, select:focus-visible,
.filtro:focus-visible, .nav-item:focus-visible { outline-offset: -1px; }

/* O seletor de etiqueta é um rótulo com um <select> dentro: sem isto o
   anel aparecia no controle interno, desalinhado da pílula. */
.seletor-etiqueta:focus-within {
  outline: 2px solid var(--md-laranja-borda); outline-offset: -1px;
}
.seletor-etiqueta select:focus-visible { outline: none; }
h1 { font-size: 24px; margin: 0 0 var(--e-2); letter-spacing: -0.02em; }
h2 { font-size: 17px; margin: 0 0 var(--e-2); }
h3 { font-size: 14px; margin: 0 0 var(--e-1); }
p { margin: 0; }
.oculto { display: none !important; }
/* Classe com display próprio vence o [hidden] do navegador; isto reverte. */
[hidden] { display: none !important; }
.so-mobile { display: none; }
.centro { text-align: center; }
.centro .avatar { margin: 0 auto; }
.espaco-topo { margin-top: var(--e-3); }
.espaco-vertical { margin: var(--e-4) 0; }
.so-leitor {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap;
}

/* ------------------------- 3. Elementos comuns ------------------------- */
.rotulo-secao {
  font-size: 10px; font-weight: 700; text-transform: uppercase;
  letter-spacing: .08em; color: var(--cor-texto-fraco);
}

.avatar {
  width: 40px; height: 40px; border-radius: 50%; flex: none;
  background: var(--md-preto); color: var(--md-branco);
  display: grid; place-items: center;
  font-weight: 750; font-size: 14px; letter-spacing: -.02em;
  overflow: hidden;
}
[data-tema='escuro'] .avatar { background: #35302D; }
.avatar img { width: 100%; height: 100%; object-fit: cover; display: block; }
.avatar.p { width: 30px; height: 30px; font-size: 11px; }
.avatar.g { width: 72px; height: 72px; font-size: 24px; }
.avatar.grupo { border-radius: var(--raio); background: var(--md-laranja); color: var(--md-preto); }

.pessoa { display: flex; align-items: center; gap: var(--e-2); min-width: 0; }
.pessoa-corpo { min-width: 0; display: flex; flex-direction: column; }
.pessoa-corpo strong { font-size: 13px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pessoa-corpo small {
  font-size: 11px; color: var(--cor-texto-fraco);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

.presenca { width: 8px; height: 8px; border-radius: 50%; background: #9A938C; flex: none; }
.presenca.online { background: var(--md-verde); }

/* Bolinha de presença sobre o avatar. O anel na cor do fundo separa a
   bolinha da foto — sem ele, ela some em foto clara. */
.avatar-status { position: relative; display: inline-flex; flex: none; }
.avatar-status > .presenca {
  position: absolute; right: -1px; bottom: -1px;
  width: 11px; height: 11px;
  border: 2px solid var(--cor-cartao);
  box-shadow: 0 0 0 1px rgba(0, 0, 0, .12);
}
.avatar-status.p > .presenca { width: 9px; height: 9px; border-width: 2px; }
.avatar-status.g > .presenca { width: 18px; height: 18px; border-width: 3px; right: 2px; bottom: 2px; }

/* Sobre fundos diferentes o anel acompanha a superfície de trás. */
.lateral .avatar-status > .presenca { border-color: var(--cor-barra); }
.conversa-item .avatar-status > .presenca,
.linha-equipe .avatar-status > .presenca { border-color: var(--cor-cartao); }
.conversa-item.ativo .avatar-status > .presenca { border-color: var(--cor-realce); }
.modal-linha .avatar-status > .presenca,
.participante .avatar-status > .presenca { border-color: var(--cor-cartao-alt); }
.modal .centro .avatar-status > .presenca { border-color: var(--cor-cartao); }

/* Offline fica discreto; online chama atenção. */
.avatar-status > .presenca:not(.online) { opacity: .55; }

.chip {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 2px 8px; border-radius: 5px; font-size: 11px; font-weight: 650;
  border: 1px solid var(--cor-borda-forte); white-space: nowrap; font-style: normal;
  background: var(--cor-cartao-alt); color: var(--cor-texto-fraco);
}
.chip.etiqueta {
  border-color: color-mix(in srgb, var(--tag, var(--md-laranja)) 45%, transparent);
  background: color-mix(in srgb, var(--tag, var(--md-laranja)) 12%, transparent);
  color: color-mix(in srgb, var(--tag, var(--md-laranja)) 80%, var(--cor-texto));
}
.chip .ponto {
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--tag, var(--md-laranja)); flex: none;
}
.selo-marca {
  border: 1px solid var(--md-laranja); color: var(--md-laranja);
  font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .06em;
  border-radius: 999px; padding: 2px 9px; white-space: nowrap;
}

button, .botao {
  border-radius: var(--raio); padding: 9px var(--e-4);
  border: 1px solid transparent; cursor: pointer; background: none;
}
/* Ícone solto dentro de botão: alinha com o texto em vez de sentar na
   linha de base. O TAMANHO vem do próprio SVG (icons.js), não daqui —
   assim nenhum lugar novo precisa lembrar de dimensionar o ícone. */
button > svg, .botao > svg { vertical-align: -3px; }
.primario { background: var(--md-laranja); color: var(--md-preto); font-weight: 700; }
.primario:hover:not(:disabled) { background: var(--md-laranja-luz); }
.secundario { background: var(--cor-cartao); border-color: var(--cor-borda-forte); color: var(--cor-texto); }
.secundario:hover:not(:disabled) { border-color: var(--cor-texto); }
.perigo { background: var(--cor-cartao); border-color: var(--md-vermelho); color: var(--md-laranja-texto); }
.compacto { padding: 5px 10px; font-size: 12px; }
.largo { width: 100%; }
button:disabled { opacity: .45; cursor: not-allowed; }

.botao-icone {
  width: 32px; height: 32px; padding: 0; border-radius: var(--raio);
  display: grid; place-items: center; color: var(--cor-texto-fraco);
}
.botao-icone:hover:not(:disabled) { background: var(--cor-cartao-alt); color: var(--cor-texto); }
.botao-icone svg { width: 17px; height: 17px; }
.botao-icone.ativo { color: var(--md-laranja-texto); background: var(--cor-realce); }

label { display: block; font-size: 12px; font-weight: 650; margin-bottom: var(--e-1); }
input, select, textarea {
  width: 100%; padding: 8px var(--e-3);
  border: 1px solid var(--cor-borda-forte); border-radius: var(--raio);
  background: var(--cor-cartao); color: var(--cor-texto);
}
input:disabled, textarea:disabled { opacity: .6; cursor: not-allowed; }
.campo { margin-bottom: var(--e-3); }
.erro { color: var(--md-laranja-texto); font-size: 12px; min-height: 18px; }
.nota { font-size: 12px; color: var(--cor-texto-fraco); line-height: 1.45; }
.aviso {
  border-left: 3px solid var(--md-laranja-borda); background: var(--cor-realce);
  color: var(--cor-realce-texto); padding: var(--e-3) var(--e-4);
  border-radius: var(--raio); font-size: 12px; line-height: 1.5;
}

.vazio {
  margin: auto; padding: var(--e-6) var(--e-4); text-align: center;
  color: var(--cor-texto-fraco); max-width: 380px;
}
.vazio svg { width: 34px; height: 34px; opacity: .45; margin-bottom: var(--e-3); }
.vazio strong { display: block; color: var(--cor-texto); font-size: 15px; margin-bottom: var(--e-1); }
.vazio p { font-size: 12px; line-height: 1.5; }

/* ------------------------------ 4. Marca ------------------------------- */
/* Os PNGs oficiais têm 5,2% de área transparente à esquerda; o recuo
   negativo alinha o traço visível com o texto abaixo, como no sistema. */
.marca img { display: block; height: 26px; width: auto; margin-left: -7px; }
.marca-sub {
  display: block; margin-top: 5px; font-size: 10px; letter-spacing: .12em;
  text-transform: uppercase; color: var(--md-laranja); font-weight: 700;
}

/* ---------------------------- 5. Estrutura ----------------------------- */
.app { height: 100%; display: flex; align-items: stretch; }

/* Barra lateral escura e fixa. */
.lateral {
  width: var(--largura-lateral); flex: 0 0 var(--largura-lateral);
  background: var(--cor-barra); color: #F5F1EC;
  display: flex; flex-direction: column; gap: var(--e-2);
  padding: var(--e-4) var(--e-3) var(--e-3);
  overflow-y: auto;
}
.lateral-marca { padding: 0 var(--e-2) var(--e-2); }
.lateral-sep { height: 1px; background: rgba(255, 255, 255, .14); margin: 2px 0 var(--e-2); }
.lateral-nav { display: flex; flex-direction: column; gap: 1px; flex: 1; }
.lateral .rotulo-secao { color: rgba(255, 255, 255, .42); padding: var(--e-3) var(--e-2) var(--e-1); }
.nav-item {
  display: flex; align-items: center; gap: var(--e-2);
  color: rgba(255, 255, 255, .80); font-size: 13px; text-align: left;
  padding: 7px var(--e-3); border-radius: var(--raio); width: 100%;
}
.nav-item svg { width: 16px; height: 16px; flex: none; }
.nav-item:hover { background: rgba(255, 255, 255, .09); color: #fff; }
.nav-item.ativo { background: var(--md-laranja); color: var(--md-preto); font-weight: 700; }
.nav-item .contador {
  margin-left: auto; background: var(--md-laranja); color: var(--md-preto);
  font-size: 10px; font-weight: 800; min-width: 18px; height: 18px;
  border-radius: 999px; display: grid; place-items: center; padding: 0 5px;
}
.nav-item.ativo .contador { background: var(--md-preto); color: #fff; }

.lateral-rodape {
  display: flex; flex-direction: column; gap: var(--e-2);
  padding-top: var(--e-3); border-top: 1px solid rgba(255, 255, 255, .14);
}
/* Relógio da sessão: ícone pequeno, rótulo dizendo o que é, e o tempo à
   direita. Números tabulares para os dígitos não dançarem a cada
   segundo. É informação, não botão — por isso o peso discreto. */
.lateral-tempo {
  display: flex; align-items: center; gap: 6px;
  padding: 2px var(--e-2) var(--e-1);
  font-size: 11px; color: rgba(255, 255, 255, .55);
}
.lateral-tempo svg { width: 12px; height: 12px; flex: none; opacity: .6; }
.lateral-tempo .rotulo-tempo { letter-spacing: .04em; }
.lateral-tempo .valor-tempo {
  margin-left: auto; font-size: 12px; font-weight: 650;
  font-variant-numeric: tabular-nums; color: rgba(255, 255, 255, .88);
}

/* Atalho para fora: mesma linha da navegação, sem sublinhado de link. */
/* O "Mais" existe só na barra de baixo do celular. Na lateral do
   computador todos os destinos já estão à vista, e ele aparecia como um
   item repetido no fim da lista. */
.nav-mais { display: none; }

.nav-item.externo { text-decoration: none; }
.nav-item.externo svg { opacity: .75; }

.lateral-linha { display: flex; align-items: center; gap: var(--e-2); }
.lateral-usuario { flex: 1; min-width: 0; display: flex; align-items: center; gap: var(--e-2); padding: 0; }
.lateral-usuario .avatar { background: var(--md-laranja); color: var(--md-preto); }
.lateral-usuario .identidade { min-width: 0; display: flex; flex-direction: column; text-align: left; }
.lateral-usuario .nome {
  font-size: 12px; color: #fff; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap;
}
.lateral-usuario .identidade small {
  font-size: 10px; color: rgba(255, 255, 255, .55); text-transform: capitalize;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.lateral-botao {
  border: 1px solid rgba(255, 255, 255, .28); color: rgba(255, 255, 255, .85);
  padding: 5px 10px; font-size: 12px; border-radius: var(--raio);
}
.lateral-botao:hover { border-color: #fff; color: #fff; }
.lateral-botao.quadrado { width: 30px; height: 26px; padding: 0; display: grid; place-items: center; flex: none; }
.lateral-botao svg { width: 14px; height: 14px; }

/* --------------------------- 6. Lista lateral -------------------------- */
.lista {
  width: var(--largura-lista); flex: 0 0 var(--largura-lista);
  background: var(--cor-cartao); border-right: 1px solid var(--cor-borda);
  display: flex; flex-direction: column; min-width: 0;
  /* min-height: 0 é o que permite encolher abaixo do conteúdo. Sem ele,
     no celular — onde .app vira coluna — a lista crescia até caber todas
     as conversas, o overflow interno nunca entrava em ação e o body
     cortava o excesso: dava para ver o começo e não rolava. */
  min-height: 0;
}
.lista-cabecalho,
.conversa-cabecalho,
.detalhes-cabecalho {
  height: var(--altura-cabecalho); flex: 0 0 var(--altura-cabecalho);
  display: flex; align-items: center; gap: var(--e-2);
  padding: 0 var(--e-3); border-bottom: 1px solid var(--cor-borda);
}
.lista-cabecalho h2 { margin: 0; font-size: 15px; }
.lista-cabecalho .acoes, .conversa-cabecalho .acoes { margin-left: auto; display: flex; gap: 2px; }

/* Quem do time está online agora, no topo da lista */
.faixa-online { padding: var(--e-3) var(--e-3) var(--e-2); border-bottom: 1px solid var(--cor-borda); }
.faixa-online.vazia {
  display: flex; align-items: center; gap: var(--e-2);
  font-size: 12px; color: var(--cor-texto-fraco);
}
.online-lista { display: flex; gap: var(--e-2); overflow-x: auto; padding: var(--e-2) 0 2px; scrollbar-width: none; }
.online-lista::-webkit-scrollbar { display: none; }
.pessoa-online {
  display: flex; flex-direction: column; align-items: center; gap: 3px;
  padding: 0; min-width: 46px; color: var(--cor-texto-fraco);
}
.pessoa-online span {
  font-size: 10px; font-weight: 650; max-width: 52px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.pessoa-online:hover { color: var(--md-laranja-texto); }

.busca { padding: var(--e-3) var(--e-3) var(--e-2); position: relative; }
.busca svg {
  position: absolute; left: 22px; top: 50%; transform: translateY(-40%);
  width: 15px; height: 15px; color: var(--cor-texto-fraco); pointer-events: none;
}
/* Espaço à direita para a dica do atalho não ficar por cima do texto
   digitado — sem isto, uma busca longa passa por baixo dela. */
.busca input { padding-left: 32px; padding-right: 44px; background: var(--cor-cartao-alt); }
.dica-atalho {
  position: absolute; right: 20px; top: 50%; transform: translateY(-50%);
  padding: 2px 6px; border-radius: 5px;
  background: var(--cor-cartao); border: 1px solid var(--cor-borda-forte);
  color: var(--cor-texto-fraco); cursor: pointer;
  font: 600 10.5px/1.5 ui-monospace, SFMono-Regular, Menlo, monospace;
}
.dica-atalho:hover { color: var(--cor-texto); border-color: var(--md-laranja); }
/* No celular não há teclado para atalho; a dica só roubaria espaço da
   busca, que ali é estreita. */
@media (max-width: 720px) { .dica-atalho { display: none; } .busca input { padding-right: 12px; } }

.filtros {
  display: flex; gap: var(--e-1); overflow-x: auto;
  padding: 0 var(--e-3) var(--e-2); scrollbar-width: none;
}
.filtros::-webkit-scrollbar { display: none; }
.filtro {
  border: 1px solid var(--cor-borda-forte); border-radius: 999px;
  min-height: var(--altura-filtro); padding: 0 10px; font-size: 11px; font-weight: 650;
  color: var(--cor-texto-fraco); white-space: nowrap;
  display: inline-flex; align-items: center; gap: 5px;
}
.filtro .ponto { width: 7px; height: 7px; border-radius: 50%; background: var(--tag, var(--md-laranja)); }
/* Passar o mouse muda o FUNDO, não a cor da letra.
   Antes o texto ia para o branco cheio — a mesma promoção que o olho lê
   como "este está selecionado". Com "Todas" marcado e o ponteiro sobre
   "Diretas", a barra parecia ter dois filtros ativos ao mesmo tempo. */
.filtro:hover { background: var(--cor-cartao-alt); border-color: var(--cor-borda-forte); }
.filtro.ativo {
  background: var(--md-laranja); border-color: var(--md-laranja); color: var(--md-preto);
}
/* O ativo não reage ao ponteiro: ele já está no seu estado final, e
   qualquer mudança ali sugere que ainda há algo a escolher. */
.filtro.ativo:hover { background: var(--md-laranja); border-color: var(--md-laranja); }
/* Faixa de filtros: tipos à esquerda (rolam de lado se não couberem) e a
   lista de etiquetas fixa à direita, para nunca sair da vista. */
.barra-filtros {
  display: flex; align-items: center; gap: var(--e-1);
  padding: 0 var(--e-3) var(--e-2);
  /* Nada escapa da lista: o que não couber encolhe ou rola por dentro. */
  min-width: 0; overflow: hidden;
}
/* `flex: 1` empurrava a lista de etiquetas para a borda direita, longe
   dos outros filtros — parecia um controle solto de outra seção. Aqui os
   filtros ocupam só o que precisam e a lista vem logo depois, lendo-se
   como um grupo só. */
.barra-filtros .filtros { flex: 0 1 auto; min-width: 0; padding: 0; }

.seletor-etiqueta {
  /* Encolhe junto com o resto. Com `flex: none` ele não cedia um pixel:
     numa barra apertada — letra maior do sistema, janela estreita — ele
     passava por cima da borda da lista em vez de diminuir. */
  display: inline-flex; align-items: center; gap: 5px;
  flex: 0 1 auto; min-width: 0;
  min-height: var(--altura-filtro); padding: 0 8px 0 10px;
  border: 1px solid var(--cor-borda-forte);
  border-radius: 999px; color: var(--cor-texto-fraco); cursor: pointer;
}
.seletor-etiqueta:hover { color: var(--cor-texto); }
.seletor-etiqueta .ponto {
  width: 7px; height: 7px; border-radius: 50%; flex: none;
  background: var(--tag, var(--md-laranja));
}
/* Sem filtro não há cor para mostrar, e um ponto cinza só ocuparia espaço. */
.seletor-etiqueta:not(.ativo) .ponto { display: none; }
.seletor-etiqueta.ativo { border-color: var(--tag, var(--md-laranja)); color: var(--cor-texto); }

.seletor-etiqueta select {
  appearance: none; border: 0; background: transparent; color: inherit;
  font: inherit; font-size: 11px; font-weight: 650; cursor: pointer;
  padding: 0 15px 0 0; max-width: 116px; min-width: 0; text-overflow: ellipsis;
  overflow: hidden; white-space: nowrap;
  /* Mesma setinha desenhada no fundo que o seletor de papel usa. */
  background-image: linear-gradient(45deg, transparent 50%, currentColor 50%),
    linear-gradient(135deg, currentColor 50%, transparent 50%);
  background-position: right 4px center, right 0 center;
  background-size: 5px 5px, 5px 5px; background-repeat: no-repeat;
}
/* A lista aberta é desenhada pelo sistema: sem isto herda o fundo transparente. */
.seletor-etiqueta select option { background: var(--cor-cartao); color: var(--cor-texto); }

@media (max-width: 720px) {
  /* No celular o dedo precisa de alvo: a lista inteira vira área de toque.
     A largura é menor que no desktop porque, com um nome de etiqueta longo,
     a faixa empurrava "Diretas" para fora da vista. */
  .seletor-etiqueta select { padding: 0 15px 0 0; font-size: 12px; max-width: 88px; }
}

.lista-titulo {
  display: flex; align-items: center; justify-content: space-between;
  padding: var(--e-2) var(--e-4) var(--e-1);
}
.lista-titulo .selo-contagem {
  font-size: 10px; font-weight: 700; color: var(--cor-texto-fraco);
  background: var(--cor-cartao-alt); border: 1px solid var(--cor-borda);
  border-radius: 999px; padding: 1px 7px;
}
/* A rolagem vive no envoltório: conversas e resultados descem juntos.
   `min-height: 0` é o que permite a caixa encolher dentro da coluna
   flex — sem isso ela adota a altura do conteúdo e estoura o painel. */
.lista-rolagem {
  flex: 1; min-height: 0; overflow-y: auto; padding-bottom: var(--e-4);
  overscroll-behavior: contain; -webkit-overflow-scrolling: touch;
}
.lista-itens { flex: none; }

.conversa-item {
  width: 100%; display: flex; gap: var(--e-3); text-align: left;
  padding: 11px var(--e-3); border-radius: 0;
  border-left: 3px solid transparent;
  /* Sem isto o avatar estica até a altura da linha, e a bolinha de
     presença — que é posicionada pelo rodapé dele — desce junto quando
     a etiqueta faz a linha crescer. */
  align-items: flex-start;
}
.conversa-item:hover { background: var(--cor-cartao-alt); }
.conversa-item.ativo { background: var(--cor-realce); border-left-color: var(--md-laranja); }
/* Duas faixas, não três: nome+hora em cima, e embaixo prévia, etiqueta
   e contador na MESMA linha. A etiqueta ficava numa terceira faixa e
   aparecia longe da prévia; ao lado ela some no meio da leitura, que é
   o lugar certo para um rótulo pequeno. */
.conversa-item .corpo {
  min-width: 0; flex: 1;
  display: flex; flex-direction: column; gap: 3px;
}
.conversa-item .corpo > * { flex: none; min-height: 0; }
/* A prévia cede espaço; quem tem tamanho fixo fica inteiro. */
.conversa-item .previa { flex: 1; }
.conversa-item .etiquetas { flex: none; }
.conversa-item .linha { display: flex; align-items: center; gap: var(--e-2); }
.conversa-item .linha strong {
  font-size: 13px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.conversa-item time { margin-left: auto; font-size: 10px; color: var(--cor-texto-fraco); flex: none; }
/* CUIDADO: existe uma `.previa` genérica (pré-visualização de arquivo)
   com `display: grid; place-items: center; margin: 12px 0`. Como esta
   regra não declarava display nem margem, a genérica vencia por omissão:
   o texto da conversa saía centralizado e a faixa ganhava 24px de sobra.
   Os dois valores abaixo existem para barrar aquela regra — não remova
   sem renomear uma das duas classes. */
.conversa-item .previa {
  display: block; margin: 0;
  font-size: 12px; color: var(--cor-texto-fraco);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.conversa-item .nao-lidas {
  margin-left: auto; flex: none; background: var(--md-laranja); color: var(--md-preto);
  font-size: 10px; font-weight: 800; min-width: 18px; height: 18px;
  border-radius: 999px; display: grid; place-items: center; padding: 0 5px;
}
.conversa-item .etiquetas { display: flex; gap: 4px; line-height: 1; }
/* A lista é densa: a mesma etiqueta que cabe num cabeçalho fica grande
   demais aqui e empurra a linha para baixo. Menor só neste contexto. */
.conversa-item .etiquetas .chip {
  padding: 0 6px; font-size: 10px; line-height: 15px; gap: 4px; border-radius: 4px;
  font-weight: 700; letter-spacing: .01em;
}
.conversa-item .etiquetas .chip .ponto { width: 6px; height: 6px; }
/* Mensagens encontradas, abaixo da lista de conversas */
.secao-busca { border-top: 1px solid var(--cor-borda); padding: var(--e-2) var(--e-3) var(--e-4); }
.secao-busca .rotulo-secao { display: block; margin-bottom: var(--e-1); }
.achado {
  display: grid; grid-template-columns: 1fr auto; gap: 0 var(--e-2);
  width: 100%; text-align: left; padding: 7px var(--e-2); border-radius: var(--raio);
}
.achado:hover { background: var(--cor-cartao-alt); }
/* Posição explícita das três peças. Com `grid-row: 1` só no time, o
   algoritmo posicionava ELE primeiro — itens de linha definida vêm
   antes dos automáticos — e ele tomava a coluna 1, empurrando o nome
   para a direita. Dizendo a célula de cada um, não há disputa. */
.achado strong {
  grid-area: 1 / 1; font-size: 12.5px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.achado time { grid-area: 1 / 2; font-size: 10px; color: var(--cor-texto-fraco); }
.achado span {
  grid-area: 2 / 1 / 3 / -1; font-size: 11.5px; color: var(--cor-texto-fraco);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

.carregar-mais {
  display: block; width: calc(100% - var(--e-4)); margin: var(--e-2) auto;
  padding: 8px; font-size: 12px; font-weight: 650; color: var(--cor-texto-fraco);
  border: 1px dashed var(--cor-borda-forte); border-radius: var(--raio);
}
.carregar-mais:hover { color: var(--md-laranja-texto); border-color: var(--md-laranja); }

/* Zoom do texto da conversa. Letras em vez de lupa: dizem o que fazem
   sem precisar de legenda, e cabem no mesmo quadrado dos outros ícones. */
.zoom-chat { display: inline-flex; gap: 2px; }
.zoom-chat .botao-icone { width: 28px; height: 28px; font-size: 12px; font-weight: 700; }

/* ---------------------------- 7. Conversa ------------------------------ */
.conversa {
  flex: 1; min-width: 0; min-height: 0; display: flex; flex-direction: column;
  background: var(--cor-superficie);
}
.conversa-cabecalho { background: var(--cor-cartao); }
/* Arrastando arquivo para cima da conversa */
.conversa.recebendo-arquivo { outline: 2px dashed var(--md-laranja); outline-offset: -8px; }
.conversa.recebendo-arquivo .mensagens { opacity: .5; }
.conversa-cabecalho .titulo { min-width: 0; display: flex; flex-direction: column; }
/* O nome ganha reticências como o subtítulo já tinha. Sem isto, um nome
   de três palavras quebrava em duas linhas dentro de um cabeçalho de
   altura FIXA e empurrava o subtítulo para fora — no celular, onde a
   largura é curta, acontecia com quase todo nome completo. */
.conversa-cabecalho .titulo strong {
  font-size: 14px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.conversa-cabecalho .titulo small {
  font-size: 11px; color: var(--cor-texto-fraco); margin-top: 1px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* O corpo embrulha a área de mensagens para o botão de descer poder
   flutuar sobre ela sem sair do lugar durante a rolagem. */
.corpo-conversa { flex: 1; min-height: 0; position: relative; display: flex; }

/* Botão de voltar ao fim da conversa.
   Era um aro fino e vazado sobre o fundo escuro: lia-se como moldura, e
   não como botão. Agora tem corpo sólido, sombra que o descola da
   conversa e um desenho mais firme — continua discreto, mas parece algo
   em que se clica. */
.descer {
  position: absolute; right: var(--e-4); bottom: var(--e-4); z-index: 5;
  width: 36px; height: 36px; border-radius: 50%;
  background: var(--cor-cartao-alt); border: 1px solid var(--cor-borda);
  color: var(--cor-texto);
  box-shadow: 0 6px 18px rgba(10, 8, 8, .34), 0 1px 3px rgba(10, 8, 8, .22);
  display: grid; place-items: center;
  transition: transform .12s, background .12s, border-color .12s;
}
.descer svg {
  width: 17px; height: 17px; transform: rotate(-90deg);
  stroke-width: 2.4;
}
.descer:hover {
  border-color: var(--md-laranja); color: var(--md-laranja);
  transform: translateY(-1px);
}
.descer:active { transform: translateY(0); }
.descer .contador {
  position: absolute; top: -4px; right: -4px;
  background: var(--md-laranja); color: var(--md-preto);
  font-size: 10px; font-weight: 800; min-width: 18px; height: 18px;
  border-radius: 999px; display: grid; place-items: center; padding: 0 4px;
}

/* Linha "mensagens novas", onde a leitura parou. */
.divisor-novas {
  align-self: stretch; display: flex; align-items: center; gap: var(--e-3);
  margin: var(--e-4) 0 var(--e-2);
}
.divisor-novas::before, .divisor-novas::after {
  content: ''; flex: 1; height: 1px; background: var(--md-laranja); opacity: .45;
}
.divisor-novas span {
  font-size: 10px; font-weight: 800; text-transform: uppercase; letter-spacing: .08em;
  color: var(--md-laranja); white-space: nowrap;
}

/* Destaque de quem chega pela citação: chama o olho e sai sozinho. */
.mensagem.destacada { animation: piscar-mensagem 1.8s ease-out; }
@keyframes piscar-mensagem {
  0%, 40% { background: color-mix(in srgb, var(--md-laranja) 22%, transparent); }
  100% { background: inherit; }
}

/* Convite para ligar os avisos do navegador. */
.faixa-avisos {
  display: flex; align-items: center; gap: var(--e-2);
  padding: var(--e-3); margin: var(--e-3) var(--e-3) 0;
  border: 1px solid var(--cor-borda); border-radius: var(--raio);
  background: var(--cor-cartao-alt);
}
.faixa-avisos svg { width: 16px; height: 16px; flex: none; color: var(--md-laranja); }
.faixa-avisos span { flex: 1; min-width: 0; font-size: 12px; color: var(--cor-texto-fraco); }

.mensagens {
  flex: 1; overflow-y: auto; padding: var(--e-5) clamp(var(--e-4), 5vw, var(--e-7));
  display: flex; flex-direction: column; align-items: flex-start; gap: 2px;
  overscroll-behavior: contain; -webkit-overflow-scrolling: touch;
}
.divisor-dia { align-self: center; margin: var(--e-4) 0 var(--e-3); }
.divisor-dia span {
  font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .08em;
  color: var(--cor-texto-fraco); background: var(--cor-cartao);
  border: 1px solid var(--cor-borda); border-radius: 999px; padding: 3px 12px;
}

/* Linha com a foto de quem escreveu, em conversa de grupo */
/* ------------- Os vãos ENTRE mensagens acompanham o A+/A− -------------
 * Este é o "colado".
 *
 * A letra cresce com o A+ (`--escala-chat`); os vãos estavam presos em
 * pixels. Com o chat em 1,3x o texto ficava grande e o espaço entre uma
 * mensagem e outra continuava em 2px — proporcionalmente MENOR do que
 * antes. As bolhas encostavam umas nas outras e a conversa virava um
 * bloco só.
 *
 * O mesmo já tinha sido corrigido DENTRO da bolha (ver o `row-gap` em
 * `.mensagem`), mas parou ali: entre as bolhas, e entre o avatar e a
 * bolha, os números continuaram fixos.
 * --------------------------------------------------------------------- */
.linha-mensagem {
  display: flex; align-items: flex-end;
  gap: calc(9px * var(--escala-chat));
  max-width: min(78%, 660px);
}
.linha-mensagem + .linha-mensagem { margin-top: calc(7px * var(--escala-chat)); }
/* Troca de autor ganha respiro; sequência do mesmo autor fica junta. */
.linha-mensagem + .linha-mensagem:not(.emenda) { margin-top: calc(18px * var(--escala-chat)); }

/* A TROCA entre quem escreveu e eu.
 *
 * Num grupo, a minha mensagem é uma bolha solta e a dos outros vem
 * embrulhada junto do avatar (`.linha-mensagem`). As duas regras acima
 * cobrem "bolha depois de bolha" e "embrulho depois de embrulho" — e
 * nenhuma delas alcança a passagem de um para o outro, que é justamente
 * onde o autor SEMPRE muda.
 *
 * O resultado: a resposta de outra pessoa colava na minha mensagem, sem
 * nenhum respiro, enquanto duas mensagens minhas seguidas tinham. Era o
 * "colado com os chats das demais pessoas". */
.linha-mensagem + .mensagem,
.mensagem + .linha-mensagem { margin-top: calc(18px * var(--escala-chat)); }
.linha-mensagem .avatar { margin-bottom: calc(2px * var(--escala-chat)); }
/* O avatar da conversa cresce com o A+, como o texto.
   Ele estava preso em 30px enquanto a vaga que o substitui nas mensagens
   seguidas já acompanhava a escala — com o chat em 1,3x davam 30 e 39px,
   e as bolhas da mesma pessoa saíam desalinhadas umas das outras. Foi
   defeito que eu mesmo criei ao escalar só um dos dois lados. */
.linha-mensagem .avatar.p {
  width: calc(30px * var(--escala-chat)); height: calc(30px * var(--escala-chat));
  font-size: calc(11px * var(--escala-chat));
}
/* A vaga tem exatamente a mesma largura — é ela que mantém a bolha da
   mensagem seguida alinhada com a que mostra a foto. */
.vaga-avatar { width: calc(30px * var(--escala-chat)); flex: none; }

.mensagem {
  max-width: min(74%, 620px); background: var(--cor-bolha);
  border: 1px solid var(--cor-borda); border-radius: var(--raio);
  /* Recheio proporcional ao texto, pelo mesmo motivo do vão acima. */
  padding: calc(8px * var(--escala-chat)) calc(12px * var(--escala-chat)) calc(6px * var(--escala-chat));
  box-shadow: var(--sombra-1);
  /* Âncora do botão de apagar, que é posicionado em absoluto. Sem isto
     ele se prenderia à página e apareceria longe da mensagem. */
  position: relative;
}
.mensagem.minha {
  align-self: flex-end; background: var(--cor-bolha-minha);
  border-color: color-mix(in srgb, var(--md-laranja) 26%, transparent);
}
.mensagem.emenda { border-top-left-radius: 2px; }
.mensagem.minha.emenda { border-top-right-radius: 2px; }
.linha-mensagem .mensagem { max-width: 100%; }
.mensagem + .mensagem { margin-top: calc(7px * var(--escala-chat)); }
/* Troca de autor ganha respiro; sequência do mesmo autor fica junta. */
.mensagem + .mensagem:not(.emenda) { margin-top: calc(18px * var(--escala-chat)); }
.mensagem .autor {
  display: block; font-size: calc(12.5px * var(--escala-chat)); font-weight: 700;
  color: var(--md-laranja-texto); margin: 0;
}
.mensagem .texto {
  font-size: calc(15.5px * var(--escala-chat)); line-height: 1.5;
  white-space: pre-wrap; word-break: break-word;
}
/* Trecho citado dentro da bolha */
/* O trecho citado é um bloco à parte, e precisa parecer um.
   Com 5px de recheio e a barra colada no texto, ele se misturava à
   resposta: numa conversa em que quase toda mensagem cita a anterior, a
   tela vira um muro de texto e não se distingue o que é citação do que é
   a resposta de fato. */
.citacao {
  display: block; margin: 0;
  padding: calc(8px * var(--escala-chat)) calc(11px * var(--escala-chat));
  /* Fundo mais firme e barra mais grossa. Com o contraste anterior a
     citação se dissolvia no fundo da bolha: os dois blocos liam-se como
     um só, e era isso que parecia "colado" — não era o vão, era a falta
     de separação visual entre o que foi citado e a resposta. */
  border-left: 4px solid var(--md-laranja);
  background: rgba(255, 85, 0, .16); border-radius: 0 6px 6px 0;
  width: 100%; text-align: left; cursor: default;
}
/* Quando a citação é botão, dá para tocar e ir à mensagem original. */
button.citacao { cursor: pointer; }
button.citacao:hover { background: rgba(255, 85, 0, .14); }
/* O nome de quem foi citado acompanha o zoom do chat, como o resto da
   bolha: preso em 11px, com o texto em 1,3x, virava um detalhe ilegível. */
.citacao strong {
  display: block; margin-bottom: calc(3px * var(--escala-chat));
  font-size: calc(11.5px * var(--escala-chat)); color: var(--md-laranja-texto);
}
.citacao small {
  display: block; font-size: calc(12px * var(--escala-chat));
  line-height: 1.35; color: var(--cor-texto-fraco);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* Botão de responder: só aparece ao passar o mouse na bolha */
.mensagem { position: relative; }
/* Barra de ações da mensagem: responder, apagar e o que vier.
   Antes cada botão era posicionado sozinho em top/right e os dois
   ficavam empilhados no mesmo canto. Em linha, eles se enfileiram. */
.acoes-mensagem {
  /* Flutuando na borda de cima, e não dentro da bolha: posicionados
     dentro, cobriam as últimas palavras do texto. */
  position: absolute; top: -11px; right: 8px; z-index: 2;
  display: flex; gap: 3px;
  opacity: 0; transition: opacity .12s;
}
.mensagem:hover .acoes-mensagem,
.acoes-mensagem:focus-within { opacity: 1; }

.acao-mensagem {
  width: 24px; height: 24px; padding: 0; border-radius: 50%;
  display: grid; place-items: center;
  background: var(--cor-cartao); border: 1px solid var(--cor-borda);
  color: var(--cor-texto-fraco);
}
.acao-mensagem svg { width: 13px; height: 13px; }
.acao-mensagem { box-shadow: var(--sombra-1); }
.acao-mensagem:hover { color: var(--md-laranja-texto); border-color: var(--md-laranja); }
.acao-mensagem.apagar:hover { color: var(--md-vermelho); border-color: var(--md-vermelho); }

/* Barra do que está sendo respondido, acima do compositor */
.barra-resposta {
  display: flex; align-items: center; gap: var(--e-2);
  padding: var(--e-2) var(--e-3); background: var(--cor-cartao);
  border-top: 1px solid var(--cor-borda); border-left: 3px solid var(--md-laranja);
}
.barra-resposta > svg { width: 16px; height: 16px; color: var(--md-laranja); flex: none; }
.barra-resposta strong { font-size: 12px; color: var(--md-laranja-texto); }
.barra-resposta small {
  font-size: 11.5px; color: var(--cor-texto-fraco);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.barra-resposta .botao-icone { margin-left: auto; }

/* A hora sobe para a linha do texto quando cabe — e só quando cabe.
 *
 * Em bloco, ela ficava SEMPRE numa linha própria: um "Oi" virava um
 * retângulo alto e estreito com a hora sozinha embaixo, e uma conversa
 * de respostas curtas virava uma coluna de caixinhas altas. É o que mais
 * salta aos olhos no celular, onde quase toda resposta é curta.
 *
 * Em flex com quebra: texto e hora dividem a linha se couberem, e a hora
 * desce sozinha para a direita quando o texto ocupa a largura toda. Sem
 * medir nada em JavaScript — é o próprio layout que decide. */
.mensagem {
  display: flex; flex-wrap: wrap; align-items: baseline;
  /* Vertical E horizontal. Só com `column-gap`, autor, citação e texto
     ficavam encostados um no outro — a bolha virava um bloco compacto
     sem hierarquia, que foi o "tudo colando". */
  /* O vão acompanha o zoom do chat, como a letra.
     Fixo em 5px, com o texto em 1,3x, ele encolhia em proporção: a bolha
     ficava com a letra grande e os blocos colados uns nos outros. */
  column-gap: var(--e-3); row-gap: calc(7px * var(--escala-chat));
}
/* Tudo ocupa a linha inteira por padrão; SÓ o texto e a hora dividem uma.
   A primeira versão listava quem devia ocupar a linha toda (imagem,
   áudio, citação) e errou: imagem e vídeo vêm dentro de um `<button>`
   que abre a visualização, então a regra não os alcançava — a foto virou
   item de flex ao lado do nome do arquivo, com um vão enorme entre os
   dois. Listar as exceções é frágil; o padrão seguro é o inverso, e
   qualquer conteúdo novo na bolha já nasce certo. */
.mensagem > * { flex: 0 0 100%; max-width: 100%; }

/* Bolha com foto ou vídeo é estreita como a mídia.
   Antes a largura vinha da LEGENDA: uma frase longa esticava a bolha até
   o limite e a imagem ficava encolhida num canto, com um vazio do tamanho
   da tela ao lado dela. Limitando aqui, a legenda quebra embaixo da foto
   — que é como se lê uma foto legendada. */
.mensagem:has(> .abrir-imagem, > .abrir-video) {
  /* 320px era estreito demais: numa tela de computador a foto ficava do
     tamanho de uma miniatura, e quem recebia uma arte para aprovar tinha
     que abrir para enxergar. 420 é perto do que o WhatsApp usa e ainda
     deixa claro que é uma bolha, não a tela inteira.
     A porcentagem continua mandando em tela estreita. */
  max-width: min(78%, calc(420px * var(--escala-chat)));
  /* E ENCOLHE até o conteúdo. O `max-width` acima é só teto; sem isto a
     bolha ocupava a largura inteira dele mesmo quando a foto era mais
     estreita — o que acontece sempre em foto EM PÉ, porque ela é
     limitada pela altura (max-height: 420px) e sobra largura.
     Dava uma caixa bem maior que a foto, com vazio à direita e a hora
     solta nele. Em foto deitada nunca apareceu: ali a largura bate no
     teto e preenche por acaso. */
  width: fit-content;
}
/* A mídia NÃO é esticada para preencher a bolha: figurinha usa o mesmo
   elemento da foto, e uma figurinha de 100px ampliada para 320 vira um
   borrão. Ela fica no tamanho dela, e o teto acima é só o limite.

   `align-self: start` porque a bolha é um flex em coluna, e em coluna o
   filho é ESTICADO na largura por padrão. Sem isto o botão ocupava a
   bolha inteira mesmo com uma foto estreita dentro — parte do vazio que
   aparecia ao lado de foto em pé. */
.mensagem > .abrir-imagem, .mensagem > .abrir-video {
  display: block; max-width: 100%; align-self: start;
}

/* ------------------------------------------------------------------ *
 * Foto em pé: a bolha tem que encolher junto.
 *
 * MEDIDO no navegador, com uma foto de 600×1000 numa tela de 1440:
 * bolha 376px, imagem 252px, 124 pixels de vazio à direita e a hora
 * solta nele. Em foto deitada nunca apareceu — ali a largura bate no
 * teto e preenche por acaso, que é o que fazia parecer que só "algumas"
 * fotos estavam erradas.
 *
 * A causa é a ORDEM em que o navegador decide as coisas. A largura da
 * bolha sai da largura NATURAL da imagem (600px), e só depois o teto de
 * altura a desenha com 252. Os dois números nunca se encontram: o teto
 * de altura não volta para corrigir a largura já decidida.
 *
 * A saída é não ter teto de altura. Limitando só pela largura, os dois
 * números passam a ser o mesmo, e a bolha abraça a foto sempre. Foto em
 * pé fica alta — como no WhatsApp, onde retrato também ocupa a tela
 * toda na vertical. Alto é honesto; vazio ao lado não é.
 * ------------------------------------------------------------------ */
.mensagem > .texto { flex: 0 1 auto; margin: 0; }

.mensagem > .rodape { flex: 0 1 auto; }
.mensagem .rodape {
  display: flex; align-items: center; justify-content: flex-end; gap: var(--e-1);
  margin-left: auto;
  /* Acompanha o A+/A− como o resto da bolha. Presa em 10px, com o texto
     em 1,3x, a hora virava um detalhe ilegível embaixo de letra grande —
     e era justamente quem mais aumenta a fonte que menos conseguia lê-la. */
  font-size: calc(10.5px * var(--escala-chat)); color: var(--cor-texto-fraco); margin-top: 2px;
}
.mensagem .rodape svg { width: 13px; height: 13px; }
/* Recibo de leitura: cinza quando saiu, laranja quando foi vista. */
.recibo { display: inline-flex; color: var(--cor-texto-fraco); transition: color .15s; }
.recibo.vista { color: var(--md-laranja); }
.mensagem.pendente { opacity: .6; }

.digitando {
  align-self: flex-start; font-size: 11px; color: var(--cor-texto-fraco);
  padding: var(--e-2) 0 0; font-style: italic;
}

.redator {
  position: relative; /* âncora do menu de anexo, que sobe a partir daqui */
  /* Os botões ficam embaixo, alinhados com a última linha do que se
     escreve — é para onde o olho vai quando o texto cresce. O encaixe
     depende de eles terem a MESMA altura do campo de uma linha; com
     alturas diferentes sobrava um degrau de poucos pixels que dava a
     impressão de coisa fora do lugar. */
  display: flex; align-items: flex-end; gap: 6px;
  /* Menos folga em volta: a faixa inteira tinha quase 80px de altura
     para escrever uma linha, e cada pixel aqui é uma linha de conversa
     a menos na tela. */
  min-height: var(--altura-redator); padding: 9px 10px; background: var(--cor-cartao);
  border-top: 1px solid var(--cor-borda);
}
.redator input[type='file'] { display: none; }
.redator textarea {
  /* Um pouco mais alta e com texto acompanhando o zoom do chat: escrever
     numa faixa menor que a das mensagens que se lê é desconfortável. */
  flex: 1; resize: none; min-height: var(--altura-campo); max-height: 180px;
  padding: 10px 14px; background: var(--cor-cartao-alt);
  border-radius: var(--raio); line-height: 1.45;
  font-size: calc(15.5px * var(--escala-chat));
}
/* Emoji, anexo e microfone vinham do tamanho geral de botão de ícone —
   32px com desenho de 17px. Ao lado de um campo de 46px e de um botão de
   enviar laranja, eles sumiam: três escalas diferentes na mesma linha.
   Aqui a barra inteira passa a ter uma escala só. */
.redator > .botao-icone {
  /* Mesma conta do botão de enviar, e pelo mesmo motivo: `aspect-ratio`
     com `stretch` não fecha o quadrado. */
  align-self: flex-end;
  width: var(--lado-enviar); height: var(--lado-enviar); border-radius: 50%;
}
.redator .botao-icone svg { width: 20px; height: 20px; }
/* Os ícones vinham no cinza mais fraco da interface e sumiam ao lado do
   campo e do botão laranja. Continuam discretos, mas visíveis. */
.redator .botao-icone { color: var(--cor-texto); opacity: .75; }
.redator .botao-icone:hover:not(:disabled) { opacity: 1; }

.redator .enviar {
  /* A altura vem da LINHA, não de um número fixo.
     A caixa de escrever cresce com o zoom do texto (A+) e com a segunda
     linha digitada; o botão ficava preso em 44px e passava a parecer
     afundado ao lado dela. `stretch` faz ele acompanhar, e a proporção
     1:1 o mantém redondo em qualquer altura. */
  /* Alinhado pelo RODAPÉ, e não esticado. Esticar fazia a altura crescer
     com a segunda linha digitada enquanto a largura ficava no conteúdo:
     o resultado era uma elipse cada vez mais alta. Quadrado fixo, no pé
     da caixa, é também onde o WhatsApp põe o dele. */
  align-self: flex-end;
  width: var(--lado-enviar); height: var(--lado-enviar);
  padding: 0; flex: none;
  /* Redondo, como a caixa de escrever ao lado.
     A medida e a posição já batiam — o que desencontrava era a FORMA:
     uma pílula totalmente arredondada ao lado de um quadrado de canto
     pequeno. O olho lê a diferença de raio como desalinhamento, e
     nenhum ajuste de pixel resolve isso. */
  border-radius: 50%;
  background: var(--md-laranja); color: var(--md-preto); display: grid; place-items: center;
}
.redator .enviar:hover:not(:disabled) { background: var(--md-laranja-luz); }
.redator .enviar svg { width: 20px; height: 20px; }
.redator-bloqueado {
  padding: var(--e-3); background: var(--cor-cartao); border-top: 1px solid var(--cor-borda);
}

/* ----------------------------- 8. Detalhes ----------------------------- */
.detalhes {
  width: var(--largura-detalhes); flex: 0 0 var(--largura-detalhes);
  background: var(--cor-cartao); border-left: 1px solid var(--cor-borda);
  overflow-y: auto;
}
.detalhes-cabecalho { justify-content: space-between; }
.detalhes-identidade { text-align: center; padding: var(--e-5) var(--e-4); border-bottom: 1px solid var(--cor-borda); }
.detalhes-identidade .avatar { margin: 0 auto var(--e-3); }
.detalhes-identidade h3 { font-size: 15px; }
.detalhes-secao { padding: var(--e-4); border-bottom: 1px solid var(--cor-borda); }
.detalhes-secao .topo {
  display: flex; align-items: center; justify-content: space-between; margin-bottom: var(--e-2);
}
.opcoes-etiqueta { display: flex; flex-direction: column; gap: 1px; }
.opcoes-etiqueta label {
  display: flex; align-items: center; gap: var(--e-2); margin: 0;
  padding: 6px var(--e-2); border-radius: var(--raio); cursor: pointer; font-weight: 500; font-size: 13px;
}
.opcoes-etiqueta label:hover { background: var(--cor-cartao-alt); }
.opcoes-etiqueta input { width: auto; accent-color: var(--md-laranja); }
.opcoes-etiqueta .ponto { width: 9px; height: 9px; border-radius: 50%; background: var(--tag); flex: none; }
.participantes { display: flex; flex-direction: column; gap: var(--e-1); }
.participante {
  display: flex; align-items: center; gap: var(--e-2);
  padding: 5px var(--e-2); width: 100%; text-align: left; border-radius: var(--raio);
}
.participante:hover { background: var(--cor-cartao-alt); }
.conversa-cabecalho .titulo[data-acao] { cursor: pointer; }
.conversa-cabecalho .titulo[data-acao]:hover strong { color: var(--md-laranja-texto); }
.participante .papel { margin-left: auto; font-size: 10px; color: var(--cor-texto-fraco); text-transform: uppercase; }

/* Áudio e imagem dentro da bolha */
/* Player de áudio próprio — ver o porquê em markup.js. */
.audio-msg {
  display: flex; align-items: center; gap: var(--e-2);
  width: min(250px, 62vw); margin: 3px 0 1px;
}
.audio-msg .audio { display: none; }
.audio-tocar {
  width: 30px; height: 30px; flex: none; padding: 0; border-radius: 50%;
  display: grid; place-items: center;
  background: var(--md-laranja); color: var(--md-preto);
}
.audio-tocar:hover { background: var(--md-laranja-luz); }
.audio-tocar svg { width: 14px; height: 14px; }
/* Um ícone por vez: pausa só aparece enquanto toca. */
.audio-tocar svg:last-child, .audio-tocar.tocando svg:first-child { display: none; }
.audio-tocar.tocando svg:last-child { display: block; }

.audio-barra {
  flex: 1; height: 3px; border-radius: 999px; cursor: pointer;
  background: color-mix(in srgb, var(--cor-texto) 16%, transparent);
  position: relative;
}
.audio-progresso {
  display: block; width: 0; height: 100%; border-radius: 999px;
  background: var(--md-laranja);
}
/* Alvo de clique maior que o traço, para acertar sem mira fina. */
.audio-barra::after { content: ''; position: absolute; inset: -9px 0; }
.audio-tempo {
  font-size: 11px; color: var(--cor-texto-fraco); flex: none;
  font-variant-numeric: tabular-nums; min-width: 32px; text-align: right;
}
/* A altura acompanha a largura nova; sem isto uma foto em pé continuava
   cortada em 320 e a bolha larga sobrava dos lados. */
/* `width: 100%` + `object-fit: cover` é o que concilia as duas coisas
   que brigavam.
 *
 * Com `max-height` sozinho a foto encolhia em LARGURA junto, e sobrava
 * bolha vazia ao lado — foto em pé ficava com 124px de nada à direita.
 * Sem teto nenhum, uma foto de celular ocupava a conversa inteira na
 * vertical, que foi o que apareceu depois.
 *
 * Aqui a largura é definida (100% da bolha, que por sua vez nasce do
 * tamanho natural da imagem e para no teto de 420). Com a largura
 * DEFINIDA, o teto de altura não encolhe mais nada: ele corta. É o que
 * o WhatsApp faz com foto muito comprida — mostra um pedaço na conversa
 * e a foto inteira ao abrir.
 *
 * Foto pequena não é esticada: a bolha nasce do tamanho dela, então
 * 100% da bolha É o tamanho dela. */
.mensagem .imagem {
  display: block; width: 100%; max-width: 100%;
  height: auto; max-height: calc(520px * var(--escala-chat)); object-fit: cover;
  border-radius: var(--raio); margin: 2px 0;
}
/* Figurinha tem fundo transparente e forma própria: cortar uma é
   estragá-la. Ela fica do tamanho que é. */
.mensagem .imagem[alt="Figurinha"] {
  width: auto; max-height: none; object-fit: contain;
}
.abrir-imagem { padding: 0; border: 0; background: none; display: block; cursor: zoom-in; }
/* Sem contorno no passar do mouse.
 *
 * Havia um `outline` laranja de 2px aqui, e ele era lido como DEFEITO:
 * é a mesma cor e a mesma espessura que marcam mensagem escolhida, então
 * passar o mouse fazia a foto parecer selecionada — ou quebrada. Foi
 * relatado três vezes como "a foto está bugada".
 *
 * O cursor de lupa já diz que dá para abrir, e o WhatsApp não contorna
 * foto nenhuma. Sinal que precisa ser explicado não é sinal. */
.abrir-imagem:hover .imagem { filter: brightness(1.06); }
.baixar-midia {
  display: inline-flex; align-items: center; gap: 6px; margin: 2px 0;
  padding: 6px 10px; border: 1px solid var(--cor-borda-forte); border-radius: var(--raio);
  font-size: 12px; font-weight: 650; color: var(--cor-texto); text-decoration: none;
  background: var(--cor-cartao-alt);
}
.baixar-midia:hover { border-color: var(--md-laranja); color: var(--md-laranja-texto); }
.baixar-midia svg { width: 15px; height: 15px; }
.baixar-midia:disabled { opacity: .5; }

/* Cartão de documento na bolha e nas listas */
.cartao-arquivo, .linha-arquivo {
  display: flex; align-items: center; gap: var(--e-2); width: 100%;
  padding: var(--e-2); margin: 2px 0; text-align: left;
  border: 1px solid var(--cor-borda-forte); border-radius: var(--raio);
  background: var(--cor-cartao-alt); color: var(--cor-texto);
}
.cartao-arquivo:hover, .linha-arquivo:hover { border-color: var(--md-laranja); }
.cartao-arquivo svg { width: 15px; height: 15px; color: var(--cor-texto-fraco); flex: none; }
.selo-extensao {
  flex: none; width: 34px; height: 34px; border-radius: var(--raio);
  background: var(--md-laranja); color: var(--md-preto);
  display: grid; place-items: center;
  font-size: 9px; font-weight: 800; text-transform: uppercase; letter-spacing: .02em;
}
.arquivo-corpo { min-width: 0; display: flex; flex-direction: column; flex: 1; }
.arquivo-corpo strong { font-size: 12.5px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.arquivo-corpo small { font-size: 10.5px; color: var(--cor-texto-fraco); }

/* Documento DENTRO da conversa. Na lista de arquivos do painel o cartão
   pequeno serve — são dezenas em coluna. Na bolha ele é a mensagem
   inteira, e apertado assim o nome do arquivo cabia em meia dúzia de
   letras antes das reticências: não dava para saber qual PDF chegou sem
   abrir. Aqui ele ganha largura e o selo do tipo fica legível. */
/* Quem tem largura é a BOLHA, não o cartão — igual à regra das fotos.
   Limitar o cartão o deixava menor que a bolha, e a hora subia para o
   espaço vago ao lado dele: sobrava um vazio no meio da mensagem. */
.mensagem:has(> .cartao-arquivo) {
  max-width: min(78%, calc(420px * var(--escala-chat)));
}
.mensagem > .cartao-arquivo {
  min-width: min(260px, 100%);
  padding: calc(10px * var(--escala-chat));
  gap: calc(10px * var(--escala-chat));
}
.mensagem > .cartao-arquivo .selo-extensao {
  width: calc(44px * var(--escala-chat)); height: calc(44px * var(--escala-chat));
  font-size: calc(10.5px * var(--escala-chat));
}
.mensagem > .cartao-arquivo .arquivo-corpo strong {
  font-size: calc(13.5px * var(--escala-chat));
  /* Duas linhas em vez de cortar no meio da primeira: nome de arquivo
     costuma ter a parte que identifica no FIM ("...-v3-final.pdf"). */
  white-space: normal; overflow-wrap: anywhere; line-height: 1.3;
}
.mensagem > .cartao-arquivo .arquivo-corpo small { font-size: calc(11.5px * var(--escala-chat)); }

/* Galeria no painel de detalhes */
.grade-arquivos {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 4px; margin-bottom: var(--e-2);
}
.miniatura { padding: 0; border-radius: var(--raio); overflow: hidden; aspect-ratio: 1; }
.miniatura img,
.miniatura video { width: 100%; height: 100%; object-fit: cover; display: block; background: #000; }
/* A miniatura de vídeo precisa da âncora para o botão de play ficar por cima. */
.miniatura { position: relative; }
.marca-play-mini svg { width: 30px; height: 30px; padding: 8px; box-shadow: none; }
.miniatura:hover { outline: 2px solid var(--md-laranja); outline-offset: -2px; }
.lista-arquivos { display: flex; flex-direction: column; gap: 2px; }

/* Pré-visualização */
.titulo-arquivo { font-size: 15px; word-break: break-all; }
.previa { margin: var(--e-3) 0; display: grid; place-items: center; }
.cartao-arquivo.grande { width: min(360px, 100%); padding: var(--e-4); }
.cartao-arquivo.grande .selo-extensao { width: 48px; height: 48px; font-size: 11px; }
.cartao-arquivo.grande .arquivo-corpo strong { font-size: 14px; white-space: normal; word-break: break-word; }
/* `dvh` no lugar de `vh`: no celular a barra do navegador aparece e
   some, e `vh` conta sempre a tela maior — a prévia ficava mais alta que
   o espaço real e empurrava o botão de enviar para fora. */
/* 62dvh deixava quase um terço da janela vazio: quem abre a
   pré-visualização quer VER o arquivo, e o resto do modal já é só título
   e um botão. 78 é o máximo antes de o título começar a sair da tela em
   celular deitado. */
.previa-imagem { max-width: 100%; max-height: 78vh; max-height: 78dvh; border-radius: var(--raio); display: block; }
.previa-pdf { width: 100%; height: 78vh; height: 78dvh; border: 1px solid var(--cor-borda); border-radius: var(--raio); }
.previa-video { max-width: 100%; max-height: 78vh; max-height: 78dvh; border-radius: var(--raio); }

@media (max-width: 720px) {
  /* Na tela do celular a prévia dividia espaço com título, legenda e
     botões — com 62% da altura só para a imagem, enviar exigia rolar o
     modal. O que importa aqui é reconhecer o arquivo, não admirá-lo. */
  .previa-imagem, .previa-video { max-height: 40dvh; }
  .previa-pdf { height: 40dvh; }
  .previa { margin: var(--e-2) 0; }
}
.previa-audio { width: 100%; }
.botao-baixar { display: block; text-align: center; text-decoration: none; }

/* Menu do botão de anexo. Sobe a partir do redator, como o de emojis. */
.menu-anexo {
  position: absolute; bottom: calc(100% + 6px); left: var(--e-2); z-index: 20;
  display: flex; flex-direction: column; gap: 2px; padding: var(--e-1);
  min-width: 268px; background: var(--cor-cartao);
  border: 1px solid var(--cor-borda); border-radius: var(--raio);
  box-shadow: var(--sombra-2);
}
.opcao-anexo {
  display: flex; align-items: center; gap: var(--e-3);
  padding: var(--e-2); border-radius: var(--raio); text-align: left; width: 100%;
}
.opcao-anexo:hover { background: var(--cor-cartao-alt); }
/* Quando a opção é um link (Promoin, Drive), o navegador pintava de roxo
   e sublinhava — destoava de todas as outras linhas da mesma lista. */
a.opcao-anexo, a.opcao-anexo:visited { color: var(--cor-texto); text-decoration: none; }
a.opcao-anexo strong, a.opcao-anexo small { text-decoration: none; }
.opcao-anexo svg { width: 17px; height: 17px; flex: none; color: var(--md-laranja-texto); }
.opcao-anexo span { display: flex; flex-direction: column; min-width: 0; }
.opcao-anexo strong { font-size: 13px; }
.opcao-anexo small { font-size: 11px; color: var(--cor-texto-fraco); }

/* Barra de gravação, no lugar do redator */
/* A barra de gravação SUBSTITUI a de escrever, então as duas precisam
   ter a mesma altura: com medidas diferentes, tocar no microfone fazia o
   rodapé encolher e a conversa dar um pulo para baixo. A altura sai da
   conta da outra barra — 9px de folga em cima e embaixo de um controle
   de 42px. */
.gravando {
  display: flex; align-items: center; gap: var(--e-2);
  min-height: var(--altura-redator); padding: 9px 10px; background: var(--cor-cartao);
  border-top: 1px solid var(--cor-borda);
}
.gravando .botao-icone, .gravando .secundario, .gravando .primario {
  min-height: 42px;
}
.gravando strong { font-size: 13px; }
.gravando time { font-variant-numeric: tabular-nums; color: var(--cor-texto-fraco); font-size: 12px; }
.gravando .secundario { margin-left: auto; }
.ponto-gravando {
  width: 10px; height: 10px; border-radius: 50%; background: var(--md-vermelho);
  animation: pulsar 1.2s infinite; flex: none;
}
@keyframes pulsar { 50% { opacity: .3; } }

/* Seletor de emoji */
.emojis {
  max-height: 290px; overflow-y: auto; padding: var(--e-3);
  background: var(--cor-cartao); border-top: 1px solid var(--cor-borda);
}
.emoji-grupo + .emoji-grupo { margin-top: var(--e-3); }
/* Numa tela larga o painel cabia 26 emojis por linha, cada um em 20px:
   um mostruário de figurinhas minúsculas em que se perde o que se
   procura. Célula maior faz menos colunas e desenho maior — dá para
   reconhecer o rosto sem chegar perto da tela.
   O teto por linha impede que, numa tela muito larga, o painel volte a
   virar uma fita de um lado ao outro. */
.emoji-grade {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(46px, 1fr));
  gap: 2px; margin-top: var(--e-1); max-width: 760px;
}
.emoji {
  font-size: 28px; line-height: 1; padding: 7px 0; border-radius: var(--raio);
  background: none; border: 0; cursor: pointer;
}
.emoji:hover { background: var(--cor-cartao-alt); }

/* Foto de perfil */
.foto-perfil { position: relative; width: 72px; margin: 0 auto; }
.troca-foto {
  position: absolute; right: -4px; bottom: -4px; width: 28px; height: 28px; padding: 0;
  border-radius: 50%; background: var(--md-laranja); color: var(--md-preto);
  display: grid; place-items: center; border: 2px solid var(--cor-cartao);
}
.troca-foto svg { width: 14px; height: 14px; }
.linha-botoes { display: flex; gap: var(--e-2); justify-content: center; margin-top: var(--e-3); }

.numero-zap { font-size: 15px; font-weight: 700; font-variant-numeric: tabular-nums; }
.lista-numeros { display: flex; flex-wrap: wrap; gap: var(--e-1); margin-top: var(--e-2); }
.lista-numeros .chip { font-variant-numeric: tabular-nums; }

/* Supervisão */
.pessoas-supervisao { display: flex; flex-wrap: wrap; gap: var(--e-1); margin: var(--e-2) 0; }
.chip-pessoa {
  display: inline-flex; align-items: center; gap: 6px; padding: 3px 10px 3px 3px;
  border: 1px solid var(--cor-borda-forte); border-radius: 999px;
  font-size: 12px; font-weight: 650; color: var(--cor-texto-fraco);
}
.chip-pessoa .avatar { width: 22px; height: 22px; font-size: 9px; }
.chip-pessoa:hover { color: var(--cor-texto); }
.chip-pessoa.ativo { background: var(--cor-realce); border-color: var(--md-laranja); color: var(--cor-realce-texto); }
/* Quem saiu da empresa: apagado e com a borda tracejada, para ler como
   "isto é histórico" antes de ler o nome. Continua clicável — o ponto de
   mostrá-lo é justamente poder abrir. */
.chip-pessoa.desligado { border-style: dashed; opacity: .62; }
.chip-pessoa.desligado:hover { opacity: 1; }
.chip-pessoa.desligado .avatar { filter: grayscale(1); }
.chip-pessoa.desligado.ativo { opacity: 1; filter: none; }
.botao-desligados { width: 100%; margin-top: var(--e-2); }

/* Abas Interno / WhatsApp dentro da supervisão */
.abas-fonte {
  display: flex; gap: 2px; margin: var(--e-2) 0 var(--e-1);
  background: var(--cor-cartao-alt); border: 1px solid var(--cor-borda);
  border-radius: var(--raio); padding: 2px;
}
.abas-fonte .aba {
  flex: 1; padding: 5px 8px; font-size: 12px; font-weight: 650;
  color: var(--cor-texto-fraco); border-radius: 4px;
}
.abas-fonte .aba:hover { color: var(--cor-texto); }
.abas-fonte .aba.ativo { background: var(--md-laranja); color: var(--md-preto); }

/* --------------------- Páginas de cadastro ---------------------------- */
.pagina { flex: 1; min-width: 0; overflow-y: auto; background: var(--cor-superficie); }
.pagina-cabecalho {
  padding: var(--e-5) clamp(var(--e-4), 4vw, var(--e-6)) var(--e-4);
  border-bottom: 1px solid var(--cor-borda); background: var(--cor-cartao);
}
.pagina-cabecalho h1 { font-size: 21px; margin-bottom: var(--e-1); }
.pagina-cabecalho .subtitulo { margin: 0; max-width: 70ch; font-size: 13px; }
.pagina-corpo { padding: var(--e-4) clamp(var(--e-4), 4vw, var(--e-6)) var(--e-7); max-width: 1100px; }
.tabela-equipe.alta { max-height: none; }
.formulario-estreito { max-width: 460px; }

/* ---------------------------- Painéis -------------------------------- *
 * As páginas de cadastro são tabela + formulário sobre o fundo bege. Sem
 * moldura tudo flutua solto e nada diz onde um bloco termina e o outro
 * começa. O painel é a superfície de leitura: cartão branco, borda fina
 * e a sombra rasa que o resto do sistema já usa.
 * --------------------------------------------------------------------- */
.painel {
  background: var(--cor-cartao); border: 1px solid var(--cor-borda);
  border-radius: var(--raio); box-shadow: var(--sombra-1);
  padding: var(--e-3); margin-bottom: var(--e-4);
}
.painel + .painel { margin-top: 0; }
.painel-titulo {
  display: block; font-size: 11px; font-weight: 700; letter-spacing: .05em;
  text-transform: uppercase; color: var(--cor-texto-fraco);
  padding-bottom: var(--e-2); margin-bottom: var(--e-2);
  border-bottom: 1px solid var(--cor-borda);
}
/* Painel que existe só para segurar a tabela: as linhas encostam nas
   bordas e a própria listra zebrada faz o trabalho de separar. */
.painel.colado { padding: var(--e-3) var(--e-2) var(--e-2); }

/* Downloads da área de configurações: botões lado a lado que quebram em
   telas estreitas, em vez de se espremerem. */
.linha-downloads { display: flex; flex-wrap: wrap; gap: var(--e-2); margin-top: var(--e-2); }
.linha-downloads a { text-decoration: none; }

/* Senha provisória: grande, monoespaçada e selecionável de uma vez. Ela
   vai ser lida em voz alta ou digitada por outra pessoa — ambiguidade
   entre l, I e 1 aqui custa uma ligação a mais. */
.senha-provisoria {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 22px; font-weight: 700; letter-spacing: .08em;
  text-align: center; padding: var(--e-3); margin: var(--e-3) 0;
  background: var(--cor-realce); color: var(--cor-realce-texto);
  border: 1px solid var(--md-laranja-borda); border-radius: var(--raio);
  user-select: all; word-break: break-all;
}

/* Conteúdo que não ganha nada em esticar: etiquetas é uma lista de
   nomes curtos, e uma linha de 1100px para escrever "Marketing" deixa
   um vazio enorme à direita. */
.coluna-estreita { max-width: 600px; }

/* ------------------------- Base de contatos -------------------------- *
 * Cabeçalho e linhas usam a MESMA grade. As larguras são fixas de
 * propósito: cada linha é uma grade independente, então com `auto` cada
 * uma calcularia a sua própria e as colunas dançariam de linha para
 * linha. Só a primeira coluna é elástica.
 * --------------------------------------------------------------------- */
.base-contatos { --grade-contato: minmax(0, 1fr) 164px 92px 82px 132px; }

.cabecalho-contatos,
.linha-contato {
  display: grid; grid-template-columns: var(--grade-contato);
  align-items: center; gap: var(--e-3);
}
.cabecalho-contatos {
  padding: var(--e-2) var(--e-2) 6px;
  border-bottom: 1px solid var(--cor-borda-forte);
  font-size: 10px; font-weight: 700; letter-spacing: .05em;
  text-transform: uppercase; color: var(--cor-texto-fraco);
}
.cabecalho-contatos .ao-fim { text-align: right; }

.linha-contato {
  padding: 7px var(--e-2);
  border-bottom: 1px solid var(--cor-borda);
}
.linha-contato:nth-child(odd) { background: var(--cor-cartao-alt); }
.linha-contato:hover { background: var(--cor-realce); }
.linha-contato .coluna-telefone a { font-variant-numeric: tabular-nums; font-size: 12.5px; }
.linha-contato .coluna-data { justify-self: start; }
/* Números à direita: a coluna vira uma pilha fácil de comparar. */
.linha-contato .coluna-msg {
  white-space: nowrap; text-align: right; font-variant-numeric: tabular-nums;
}
.linha-contato .coluna-acoes {
  display: flex; align-items: center; gap: var(--e-1); justify-content: flex-end;
}
.linha-contato .pessoa-corpo strong { display: flex; align-items: center; gap: 6px; }

/* Busca e exportar lado a lado; a contagem logo abaixo, discreta. */
.barra-ferramentas { display: flex; align-items: center; gap: var(--e-3); margin: var(--e-3) 0 var(--e-2); }
.barra-ferramentas .busca-modal, .barra-ferramentas .campo-busca { flex: 1; min-width: 0; }
.acao-exportar { flex: none; text-decoration: none; white-space: nowrap; }
.contagem-base { margin: 0 0 var(--e-2); }
.editor-contato {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: var(--e-2); align-items: end;
  padding: var(--e-3); margin: 2px 0 var(--e-3);
  border: 1px solid var(--md-laranja); border-radius: var(--raio);
  background: var(--cor-cartao);
}
.editor-contato .campo { margin: 0; }
.editor-contato .erro, .editor-contato .linha-acoes { grid-column: 1 / -1; }

/* Etiquetas como página */
.lista-etiquetas { display: flex; flex-direction: column; }
.linha-etiqueta {
  display: flex; align-items: center; gap: var(--e-3);
  padding: 7px var(--e-2); border-radius: var(--raio);
}
.linha-etiqueta:nth-child(odd) { background: var(--cor-cartao-alt); }
.linha-etiqueta:hover { background: var(--cor-realce); }
.linha-etiqueta strong { flex: 1; font-size: 13px; }
.ponto-etiqueta { width: 11px; height: 11px; border-radius: 50%; background: var(--tag); flex: none; }

/* Linha que se edita no lugar: cor, nome e as duas ações.
   O nome é um campo sem moldura até receber o ponteiro — com caixa em
   volta de cada linha, uma lista de doze etiquetas viraria um
   formulário, e o que se quer ver ali é a LISTA. */
.linha-etiqueta.editavel { gap: var(--e-2); }
.linha-etiqueta .cor-etiqueta { flex: none; width: 30px; height: 26px; padding: 2px; }
.linha-etiqueta .nome-etiqueta {
  flex: 1; min-width: 0; font-size: 13px; font-weight: 600;
  background: none; border: 1px solid transparent; padding: 4px 6px;
  transition: border-color .12s, background .12s;
}
.linha-etiqueta:hover .nome-etiqueta { border-color: var(--cor-borda); }
.linha-etiqueta .nome-etiqueta:focus {
  background: var(--cor-cartao); border-color: var(--md-laranja-borda);
}
/* Some quando não há o que salvar, em vez de ficar apagado: um botão
   desabilitado em cada uma das doze linhas é ruído permanente. */
.linha-etiqueta .salvar-etiqueta:disabled {
  visibility: hidden; pointer-events: none;
}

/* Criar etiqueta: nome ocupa o resto, cor e botão têm largura própria. */
.linha-nova-etiqueta { display: flex; align-items: center; gap: var(--e-2); }
.linha-nova-etiqueta input[type='text'] { flex: 1; min-width: 0; }
.campo-cor {
  width: 40px; height: 34px; padding: 2px; flex: none;
  border: 1px solid var(--cor-borda-forte); border-radius: var(--raio); cursor: pointer;
}

@media (max-width: 860px) {
  /* Sem espaço para cinco colunas: a linha vira cartão e o cabeçalho de
     colunas perde o sentido. Flex em vez de grade porque aqui o que
     importa é quebrar bem, não alinhar entre linhas. */
  .cabecalho-contatos { display: none; }
  .linha-contato { display: flex; flex-wrap: wrap; align-items: center; gap: var(--e-1) var(--e-2); }
  .linha-contato .coluna-pessoa { flex: 1 0 100%; }
  .linha-contato .coluna-msg { text-align: left; }
  .linha-contato .coluna-acoes { margin-left: auto; }
  .barra-ferramentas { flex-wrap: wrap; }
}

/* ------------------------------ 9. Modais ------------------------------ */
.modal-fundo {
  position: fixed; inset: 0; z-index: 50;
  /* Instalado na tela inicial o app ocupa a tela toda, inclusive a faixa
     do relógio e a do indicador de início. Sem este recuo, o "×" de
     fechar fica debaixo do relógio e a última opção da lista debaixo do
     risco de início do iPhone — os dois inalcançáveis. No navegador
     comum os valores são zero e nada muda. */
  padding: calc(var(--e-4) + env(safe-area-inset-top, 0px)) var(--e-4)
           calc(var(--e-4) + env(safe-area-inset-bottom, 0px));
  background: rgba(10, 8, 8, .55); display: grid; place-items: center;
}
.modal {
  width: min(480px, 100%); max-height: 88vh; overflow-y: auto; position: relative;
  /* dvh acompanha a barra do navegador que aparece e some; quem não
     entende dvh fica com o vh acima. */
  max-height: 88dvh;
  background: var(--cor-cartao); border: 1px solid var(--cor-borda);
  border-radius: 10px; padding: var(--e-5); box-shadow: var(--sombra-2);
}
.modal.larga { width: min(640px, 100%); }
.modal-fechar { position: absolute; top: var(--e-3); right: var(--e-3); }
.modal .rotulo-secao { display: block; color: var(--md-laranja-texto); margin-bottom: var(--e-1); }
.modal h2 { margin-bottom: var(--e-2); }
.modal-lista { display: flex; flex-direction: column; gap: 2px; max-height: 260px; overflow-y: auto; margin: var(--e-3) 0; }
.modal-linha {
  display: flex; align-items: center; gap: var(--e-2);
  padding: var(--e-2); border-radius: var(--raio); background: var(--cor-cartao-alt);
  width: 100%; text-align: left;
}
.modal-linha:hover { background: var(--cor-realce); }
.modal-linha .presenca { margin-left: auto; }
.modal-lista.alta { max-height: 380px; }

/* Tela de equipe: grade de colunas fixas, para nome comprido não
   empurrar os controles de lugar em lugar. */
.equipe-topo { display: flex; flex-direction: column; gap: var(--e-2); margin: var(--e-3) 0; }
.busca-modal { position: relative; }
.busca-modal svg {
  position: absolute; left: 10px; top: 50%; transform: translateY(-45%);
  width: 15px; height: 15px; color: var(--cor-texto-fraco); pointer-events: none;
}
.busca-modal input { padding-left: 32px; }

.tabela-equipe { max-height: 400px; overflow-y: auto; }
/* Larguras fixas nas duas últimas colunas. Com `auto` cada linha media o
   seu próprio conteúdo e quem tem o botão "Acompanha" empurrava o
   controle de poder para a esquerda, desalinhando a coluna inteira. */
.linha-equipe {
  display: grid; grid-template-columns: minmax(0, 1fr) 140px 206px;
  align-items: center; gap: var(--e-3);
  padding: 7px var(--e-2);
  border-bottom: 1px solid var(--cor-borda);
}
.linha-equipe:last-child { border-bottom: 0; }
.linha-equipe:hover { background: var(--cor-realce); }
.coluna-pessoa { display: flex; align-items: center; gap: var(--e-2); min-width: 0; }
.coluna-acompanha { min-width: 132px; display: flex; justify-content: flex-end; }
.coluna-acompanha .acompanha { display: inline-flex; align-items: center; gap: 5px; white-space: nowrap; }
.coluna-acompanha svg { width: 14px; height: 14px; }

/* Papel como lista suspensa. Era um controle segmentado de três botões
   repetido em cada linha: com 30 pessoas, noventa botões laranja
   competindo por atenção. A lista mostra só o papel atual e guarda as
   opções até serem pedidas. */
.coluna-papel { display: flex; justify-content: flex-end; }
.seletor-papel {
  width: auto; min-width: 128px; padding: 5px 26px 5px 10px;
  font-size: 12px; font-weight: 650; color: var(--cor-texto);
  background: var(--cor-cartao); border: 1px solid var(--cor-borda-forte);
  border-radius: var(--raio); cursor: pointer; appearance: none;
  /* Setinha desenhada no próprio fundo: um SVG a menos para carregar. */
  background-image: linear-gradient(45deg, transparent 50%, var(--cor-texto-fraco) 50%),
    linear-gradient(135deg, var(--cor-texto-fraco) 50%, transparent 50%);
  background-position: right 13px center, right 8px center;
  background-size: 5px 5px, 5px 5px; background-repeat: no-repeat;
}
.seletor-papel:hover:not(:disabled) { border-color: var(--cor-texto); }
.seletor-papel:disabled { opacity: .5; cursor: not-allowed; }

@media (max-width: 620px) {
  .linha-equipe { grid-template-columns: 1fr; gap: var(--e-2); }
  .coluna-acompanha { justify-content: flex-start; min-width: 0; }
}
details summary { cursor: pointer; font-size: 13px; font-weight: 650; padding: var(--e-2) 0; }
details[open] summary { color: var(--md-laranja-texto); }
.modal-linha input { width: auto; accent-color: var(--md-laranja); }
.modal hr { border: 0; border-top: 1px solid var(--cor-borda); margin: var(--e-4) 0; }
.qr-moldura {
  margin: var(--e-4) auto; width: min(300px, 100%); background: #fff;
  border-radius: 10px; padding: var(--e-3); box-shadow: var(--sombra-2);
}
.qr-moldura img { width: 100%; display: block; }

/* ------------------------------------------------------------------ *
 * Aviso flutuante.
 *
 * Vinha do rodapé e caía em cima do que a pessoa estava escrevendo —
 * justamente a parte da tela que não pode ser tapada. No alto ele não
 * disputa espaço com nada: o cabeçalho é fixo e o texto que importa
 * fica embaixo dele.
 *
 * O recuo do topo soma a área segura do iPhone, senão em tela cheia o
 * aviso nasceria debaixo do relógio.
 * ------------------------------------------------------------------ */
.aviso-flutuante {
  position: fixed; left: 50%; z-index: 60;
  top: calc(var(--altura-cabecalho, 52px) + 12px + env(safe-area-inset-top, 0px));
  max-width: min(420px, calc(100vw - 24px));
  transform: translate(-50%, -12px); opacity: 0; transition: .18s ease;
  background: var(--md-preto); color: #F5F1EC; border: 1px solid rgba(255,255,255,.18);
  border-radius: var(--raio); padding: 10px var(--e-4); font-size: 13px;
  box-shadow: var(--sombra-2); text-align: center;
}
.aviso-flutuante.visivel { opacity: 1; transform: translate(-50%, 0); }
.aviso-flutuante.erro { border-color: var(--md-vermelho); color: #FFB9A4; }
.aviso-flutuante.sucesso { border-color: #4C9A5E; color: #A7E3B8; }

/* ------------------------------ 10. Acesso ----------------------------- */
.acesso {
  height: 100%; display: grid; place-items: center;
  background: var(--md-preto); padding: var(--e-4); overflow-y: auto;
}
.acesso-caixa {
  width: min(420px, 100%); background: var(--cor-cartao);
  border-radius: 10px; padding: var(--e-6); box-shadow: var(--sombra-2);
}
[data-tema='claro'] .acesso-caixa, :root:not([data-tema='escuro']) .acesso-caixa { border: 1px solid rgba(255,255,255,.08); }
.acesso-caixa .marca { margin-bottom: var(--e-5); }
.acesso-caixa .marca img { height: 30px; margin-left: -8px; }
.acesso-caixa .marca-sub { color: var(--md-laranja-texto); }
.acesso-caixa h1 { font-size: 21px; margin: var(--e-4) 0 var(--e-1); }
.acesso-caixa form { margin-top: var(--e-4); }
.acesso-rodape {
  margin-top: var(--e-4); padding-top: var(--e-3); border-top: 1px solid var(--cor-borda);
  font-size: 11px; color: var(--cor-texto-fraco); line-height: 1.5;
}

/* --------------------------- 11. Responsivo ---------------------------- */
/* Abaixo disso a coluna de detalhes vira sobreposição: a conversa
   precisa de largura para as bolhas não virarem uma coluna estreita. */
@media (max-width: 1240px) {
  :root { --largura-lista: 312px; }
  .detalhes {
    position: fixed; top: 0; right: 0; bottom: 0; z-index: 20;
    width: min(320px, 90vw); box-shadow: -12px 0 32px rgba(10, 8, 8, .28);
  }
}

/* ------------------- A lateral vira trilho de ícones ------------------ *
 * Entre 721px e 900px a barra encolhe para 64px e perde os rótulos. O
 * que sobra precisa ser desenhado como trilho, e não como a barra larga
 * com o texto escondido — foi isso que deu errado:
 *
 *  · o item continuava com `width: 100%`, então o realce do item ativo
 *    virava uma pastilha mais alta que larga encostando nas bordas, e o
 *    contador, ancorado no canto dela, ficava longe do ícone;
 *  · os rótulos de seção sumiam por completo e os onze destinos viravam
 *    uma coluna única, sem a divisão que a barra larga tem;
 *  · os relógios continuavam em linha ("Sessão" + valor) numa faixa de
 *    48px úteis, e saíam cortados pela borda — "essão 00:0".
 * --------------------------------------------------------------------- */
@media (max-width: 900px) {
  :root { --largura-lateral: 64px; }
  .lateral { padding: var(--e-3) var(--e-2); align-items: center; }
  .lateral-marca, .nav-item span,
  .lateral-usuario .identidade { display: none; }

  /* Alvo quadrado, centrado. É o realce do item ativo que define a
     forma do trilho; tudo o mais se alinha a ele. */
  .lateral-nav { align-items: center; gap: 2px; }
  .nav-item {
    width: 40px; height: 40px; padding: 0;
    justify-content: center; position: relative;
  }
  .nav-item svg { width: 19px; height: 19px; }

  /* O contador encosta no canto do alvo, não no canto da barra. O anel
     da cor da lateral o descola do ícone: sem ele, contador e ícone
     viram uma mancha só quando o número cobre o desenho. */
  .nav-item .contador {
    position: absolute; top: 0; right: 0; margin: 0;
    min-width: 16px; height: 16px; font-size: 9px; padding: 0 3px;
    box-shadow: 0 0 0 2px var(--cor-barra);
  }

  /* O rótulo da seção vira um traço. A divisão entre os grupos é
     informação — some ela, e "Etiquetas" fica visualmente colado nos
     atalhos externos. Some o texto, fica a separação. */
  .lateral .rotulo-secao {
    display: block; width: 22px; height: 1px; padding: 0; margin: 7px auto 6px;
    background: rgba(255, 255, 255, .16);
    overflow: hidden; text-indent: -999em; white-space: nowrap;
  }
  /* Menos o primeiro: um traço logo abaixo do separador da marca são
     duas linhas coladas sem nada entre elas. */
  .lateral-nav > .rotulo-secao:first-child { display: none; }

  /* Relógios empilhados. Em linha eles não cabem em 48px — e cortar o
     número é pior do que não mostrar, porque "00:0" parece um defeito. */
  .lateral-tempo {
    flex-direction: column; gap: 0; align-items: center;
    width: 100%; padding: 2px 0; text-align: center;
  }
  .lateral-tempo svg { display: none; }
  .lateral-tempo .rotulo-tempo { font-size: 9px; letter-spacing: .02em; opacity: .75; }
  .lateral-tempo .valor-tempo { margin: 0; font-size: 12px; }

  .lateral-rodape { align-items: center; }
  .lateral-linha { flex-direction: column; }
  .lateral-botao span { display: none; }
  .lateral-botao { width: 34px; height: 30px; padding: 0; display: grid; place-items: center; }
}

@media (max-width: 720px) {
  .app { position: relative; }
  .lista { width: 100%; flex: 1; }
  .conversa {
    position: fixed; inset: 0; left: 64px; z-index: 15;
    display: none;
  }
  .app[data-aberta='sim'] .conversa { display: flex; }
  .app[data-aberta='sim'] .lista { display: none; }
  .detalhes { left: 64px; width: auto; }
  .mensagem { max-width: 86%; }
  /* Voltar é o controle mais usado no celular: precisa de área de dedo. */
  .so-mobile { display: grid; place-items: center; min-width: 44px; min-height: 44px; margin-left: -6px; }
  /* O teclado do celular já tem emoji; o botão só roubava espaço do texto. */
  #botao-emoji { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  * { animation: none !important; transition: none !important; }
}

/* ------------------------------------------------------------------ *
 * Celular. A barra lateral vira barra inferior, como em todo
 * aplicativo de conversa: abrir um chat toma a tela inteira e a barra
 * sai de cena — voltar é pelo "<" do cabeçalho. Escrito depois das
 * outras faixas de largura de propósito, para vencer no empate.
 * ------------------------------------------------------------------ */
@media (max-width: 720px) {
  .app { flex-direction: column; position: relative; }

  /* Instalado na tela inicial, o app ocupa a tela inteira e o cabeçalho
     encostaria no relógio e no notch. O recuo do sistema devolve esse
     espaço. No navegador comum o valor é zero e nada muda de lugar. */
  .lista-cabecalho, .conversa-cabecalho, .detalhes-cabecalho {
    height: calc(var(--altura-cabecalho) + env(safe-area-inset-top, 0px));
    flex-basis: calc(var(--altura-cabecalho) + env(safe-area-inset-top, 0px));
    padding-top: env(safe-area-inset-top, 0px);
  }

  /* Altura do alvo de cada aba. A altura da barra sai daqui, e o
      espaço que a lista reserva embaixo sai da altura da barra — assim
      aumentar a aba não deixa a última conversa escondida atrás dela,
      que foi o que aconteceu quando estes números eram independentes. */
  :root {
    --alvo-nav: 64px;
    --altura-barra: calc(var(--alvo-nav) + 9px);
  }

  .lateral {
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 40;
    width: auto; flex: none; height: auto; overflow: visible;
    flex-direction: row; align-items: stretch; gap: 0;
    padding: 4px var(--e-2) calc(4px + env(safe-area-inset-bottom, 0px));
    border-top: 1px solid rgba(255, 255, 255, .14);
  }
  .lateral-marca, .lateral-sep, .lateral .rotulo-secao { display: none; }

  /* Os relógios de sessão saem no celular. Eles entravam na mesma linha
     da navegação e comiam a largura dos botões — sobrava um item gigante
     e o resto ficava fora da tela. A informação continua no computador e
     no relatório; aqui o espaço vale mais para navegar. */
  .lateral-tempo { display: none; }

  /* ---------------------- Barra de baixo ------------------------- *
   * Antes: os nove destinos numa tira que rolava de lado. Cabiam quatro,
   * os outros ficavam escondidos sem aviso, e os rótulos apareciam
   * cortados no meio da palavra ("Equipe" virava "Equip", "Contatos"
   * virava "C"). Uma máscara de desvanecer tentava avisar que rolava;
   * continuava sendo uma barra de navegação que esconde para onde dá
   * para ir.
   *
   * Agora: colunas iguais, sem rolagem. Os quatro primeiros destinos
   * ficam à mão e o resto — cadastros, atalhos, perfil, tema e sair —
   * abre no botão "Mais". É o que todo aplicativo de celular faz, e pelo
   * mesmo motivo: numa tela de 375px não existe espaço para nove.
   * ---------------------------------------------------------------- */
  .lateral-nav {
    flex: 1; min-width: 0; overflow: visible;
    display: grid; grid-auto-flow: column; grid-auto-columns: 1fr; gap: 0;
    mask-image: none; -webkit-mask-image: none;
  }

  /* Do quarto em diante, só pelo "Mais". A marca vem do markup. */
  .lateral-nav .fora-da-barra { display: none; }

  .nav-item {
    position: relative; width: auto; min-width: 0;
    flex-direction: column; justify-content: center; gap: 4px;
    padding: 9px 2px; min-height: var(--alvo-nav); text-align: center;
    border-radius: var(--raio);
  }
  .nav-item svg { width: 27px; height: 27px; flex: none; }
  .nav-item span {
    /* Com quatro colunas em vez de sete sobra largura, e o rótulo pode
       voltar a um tamanho que se lê de relance. */
    display: block; font-size: 11.5px; line-height: 1.15; font-weight: 650;
    /* A coluna manda na largura; o rótulo se vira dentro dela. Largura
       fixa aqui foi o que cortava as palavras. */
    max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  .nav-item .contador { position: absolute; top: 2px; right: 50%; margin: 0 -22px 0 0; }

  .nav-mais { display: flex; }

  /* Perfil, tema e sair passaram para dentro do "Mais": na barra eles
     roubavam a largura de um destino inteiro. */
  .lateral-rodape { display: none; }

  /* Altura real da janela. No celular a barra do navegador aparece e
     some, e 100% resolvia para a altura maior — o rodapé ficava atrás
     dela. `dvh` acompanha; quem não entende dvh fica com o 100% de antes. */
  html, body, #app { height: 100%; }
  html, body, #app { height: 100dvh; }

  /* A lista ocupa a tela e deixa folga para a barra de baixo. */
  .lista { width: 100%; flex: 1; min-width: 0; min-height: 0; border-right: none; }

  /* Dedo não é ponteiro: os alvos da lista ganham área. */
  .conversa-item { padding: 13px var(--e-3); }
  .botao-icone { min-width: 40px; min-height: 40px; }
  .lista-rolagem, .pagina {
    padding-bottom: calc(var(--altura-barra) + 10px + env(safe-area-inset-bottom, 0px));
  }

  /* A conversa se mede pela janela REALMENTE visível, não pela do
     layout. É isto que a faz ficar parada quando o teclado sobe — ver a
     nota sobre `visualViewport` em main.js. Sem a variável (navegador
     antigo, ou antes da primeira medida) cai no comportamento de antes. */
  .conversa {
    position: fixed; left: 0; right: 0; z-index: 45; display: none;
    top: var(--desvio-visivel, 0px);
    height: var(--altura-visivel, 100dvh);
  }
  /* Enquanto se escreve, a barra de baixo sai de cena: com o teclado
     aberto sobram uns 300px de tela, e ela comeria um terço disso para
     mostrar destinos que ninguém vai tocar no meio de uma frase. */
  body.teclado-aberto .lateral { display: none; }
  body.teclado-aberto .lista-rolagem, body.teclado-aberto .pagina { padding-bottom: 10px; }

  /* Com o teclado aberto, a folga da barra de gestos do celular não faz
     mais sentido: o teclado está EM CIMA dela. Mas o navegador continua
     informando o mesmo recuo, e ele virava uma faixa vazia entre o campo
     de escrever e o teclado — a sobra que aparecia no print.
     Some enquanto se escreve, volta quando o teclado fecha. */
  body.teclado-aberto .redator { padding-bottom: var(--e-2); }
  .app[data-aberta='sim'] .conversa { display: flex; }
  .app[data-aberta='sim'] .lista { display: none; }
  .app[data-aberta='sim'] .lateral { display: none; }
  .detalhes { left: 0; width: auto; z-index: 50; }
  .redator { padding-bottom: calc(var(--e-3) + env(safe-area-inset-bottom, 0px)); }
  .mensagem { max-width: 86%; }
  .linha-mensagem { max-width: 88%; }
  .so-mobile { display: grid; }

  /* Alvo de toque confortável, e 16px nos campos para o iPhone não
     dar zoom sozinho ao focar — depois do zoom a tela fica torta. */
  input, textarea, select { font-size: 16px; }
  :root { --altura-filtro: 36px; }
  .filtro { padding: 0 12px; font-size: 12px; }
  .busca input { min-height: 44px; }
  .lista-cabecalho .acoes .botao-icone,
  .conversa-cabecalho .acoes .botao-icone { min-width: 40px; min-height: 40px; }
  /* Alvo maior para o dedo — e a mesma medida para os cinco, senão o
     desencontro de 1px volta com outro número. */
  :root { --altura-campo: 46px; }
  .redator .botao-icone svg { width: 22px; height: 22px; }
  .redator .enviar svg { width: 21px; height: 21px; }
}

/* Barra que aparece quando há contatos marcados para remover. */
.barra-selecao {
  position: sticky; top: 0; z-index: 4;
  display: flex; align-items: center; gap: var(--e-3);
  padding: var(--e-2) var(--e-3); margin-bottom: var(--e-2);
  border: 1px solid var(--md-laranja-borda); border-radius: var(--raio);
  background: var(--cor-realce); color: var(--cor-realce-texto);
}
.barra-selecao strong { font-size: 12px; margin-right: auto; }

.perigo:hover:not(:disabled) { border-color: var(--md-vermelho); background: var(--cor-realce); }

.linha-contato .marcar-contato { width: 15px; height: 15px; flex: none; margin-right: 2px; }
.linha-contato .remover-contato { width: 28px; height: 28px; }
.linha-contato .remover-contato:hover { color: var(--md-laranja-texto); }

/* Quem perdeu o acesso continua na lista, mas apagado. */
.linha-equipe.inativa { opacity: .55; }
.linha-equipe.inativa .poder { pointer-events: none; }

/* Sugestão de contato salvo, no "Nova conversa". */
.sugestoes-contato {
  margin-top: var(--e-2); border: 1px solid var(--cor-borda);
  border-radius: var(--raio); max-height: 190px; overflow-y: auto;
}
.sugestao-contato {
  display: flex; align-items: center; gap: var(--e-2);
  width: 100%; padding: 7px var(--e-2); text-align: left;
}
.sugestao-contato:hover { background: var(--cor-cartao-alt); }
.sugestao-contato + .sugestao-contato { border-top: 1px solid var(--cor-borda); }

/* Topo das páginas de cadastro: busca à esquerda, ação à direita. */
.linha-topo { display: flex; align-items: center; gap: var(--e-3); }
.linha-topo .busca-modal { flex: 1; min-width: 0; }
.linha-topo button { flex: none; }

/* Paginação das bases (contatos, equipe). */
.paginacao {
  display: flex; align-items: center; justify-content: center; gap: var(--e-3);
  padding: var(--e-3) 0 var(--e-5);
}
.paginacao button[disabled] { opacity: .45; cursor: not-allowed; }

/* Troca de senha no perfil: o gatilho tem de parecer um botão. Antes era
   um <summary> cru e ninguém achava o campo. */
.bloco-senha { margin: var(--e-2) 0 0; }
.bloco-senha > summary {
  display: flex; align-items: center; gap: var(--e-2);
  padding: 10px var(--e-3); border: 1px solid var(--cor-borda-forte);
  border-radius: var(--raio); background: var(--cor-cartao-alt);
  font-size: 13px; font-weight: 650; color: var(--cor-texto);
  list-style: none; min-height: 42px;
}
.bloco-senha > summary::-webkit-details-marker { display: none; }
.bloco-senha > summary::after {
  content: ''; margin-left: auto; width: 7px; height: 7px;
  border-right: 2px solid currentColor; border-bottom: 2px solid currentColor;
  transform: rotate(45deg); transition: transform .16s ease;
}
.bloco-senha[open] > summary::after { transform: rotate(-135deg); }
.bloco-senha > summary:hover { border-color: var(--md-laranja); color: var(--md-laranja-texto); }
.bloco-senha > summary svg { width: 16px; height: 16px; flex: none; color: var(--md-laranja); }
.bloco-senha[open] > summary { border-color: var(--md-laranja); margin-bottom: var(--e-3); }

/* Endereço dentro da mensagem. Quebra em qualquer ponto: link longo do
   Drive não pode esticar a bolha além da largura da conversa. */
.link-mensagem {
  color: var(--md-laranja-texto); text-decoration: underline;
  text-underline-offset: 2px; word-break: break-all;
}
.link-mensagem:hover { text-decoration-thickness: 2px; }
/* Na MINHA bolha o link é preto — o que funciona no tema claro, onde a
   bolha é bege. No escuro a bolha é marrom-escura e o preto sumia: o
   endereço ficava ilegível, visível só pelo sublinhado.
   O laranja claro já é o token de destaque do tema escuro, e é o mesmo
   que o link da bolha do outro lado usa. */
.mensagem.minha .link-mensagem { color: var(--md-preto); }
[data-tema='escuro'] .mensagem.minha .link-mensagem { color: var(--md-laranja-texto); }

/* Trocar a capa do grupo, no painel de detalhes. Só aparece para a
   administração — o servidor recusa de qualquer jeito, isto é para não
   oferecer a quem não pode. */
.acoes-grupo {
  /* Antes era `flex-wrap` centralizado: três botões de larguras
     diferentes quebravam em 2 + 1, cada linha terminando num lugar, e o
     bloco inteiro parecia desalinhado. Em grade de colunas iguais eles
     dividem a largura e as linhas fecham no mesmo ponto. */
  display: grid; grid-template-columns: repeat(2, 1fr);
  gap: var(--e-2); margin-top: var(--e-4);
}
/* Botão sozinho na última linha ocupa as duas colunas: meia linha vazia
   é o que dava o aspecto de coisa inacabada. */
.acoes-grupo > button:last-child:nth-child(odd) { grid-column: 1 / -1; }
.acoes-grupo button { width: 100%; }

/* Apagar a conversa fica atrás de uma linha, separado do resto: é a
   única ação sem volta do painel e não pode parecer mais uma opção da
   fila, do mesmo tamanho e do mesmo peso das outras. */
.acoes-destrutivas {
  margin-top: var(--e-4); padding-top: var(--e-4);
  border-top: 1px solid var(--cor-borda);
}
.acoes-destrutivas button { width: 100%; }

/* Segunda linha do relógio: o acumulado do dia, mais discreto que a
   sessão atual — é referência, não o número que se olha o tempo todo. */
.lateral-tempo .rotulo-tempo.recuado { padding-left: 18px; }
.lateral-tempo .valor-tempo.fraco { font-weight: 600; color: rgba(255, 255, 255, .62); }
.lateral-tempo + .lateral-tempo { margin-top: -4px; }

/* ------------------- Configurações: números do topo ------------------ *
 * Eram chips em fila, que misturavam número e rótulo numa só linha e
 * obrigavam a ler tudo para achar um dado. Em grade, com o número
 * grande acima do rótulo, a leitura é de relance.
 * -------------------------------------------------------------------- */
/* Os números em grupos — "Hoje", "No total", "Espaço" — porque as
   perguntas são diferentes. Numa fileira só, "489 mensagens do time"
   (desde sempre) tinha o mesmo peso de tudo, e não dava para saber se o
   sistema andou hoje. */
.grade-numeros { display: flex; flex-direction: column; gap: var(--e-4); }
.grupo-numeros .rotulo-secao { display: block; margin-bottom: var(--e-2); }

/* As divisórias saem de cada célula (sombra interna), e não de um vão de
   1px sobre fundo colorido. Com o vão, a última linha incompleta deixava
   à mostra um retângulo escuro do tamanho das células que faltavam —
   parecia um bloco quebrado no meio do painel. */
.numeros {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(148px, 1fr));
  background: var(--cor-cartao);
  border: 1px solid var(--cor-borda); border-radius: var(--raio); overflow: hidden;
}
.numeros .numero {
  display: flex; flex-direction: column; gap: 2px;
  padding: var(--e-3); box-shadow: inset -1px -1px 0 var(--cor-borda);
}
.numeros .numero strong {
  font-size: 19px; font-variant-numeric: tabular-nums; letter-spacing: -.01em;
}
.numeros .numero small { font-size: 11px; color: var(--cor-texto-fraco); line-height: 1.3; }

/* Cada painel de download vira um bloco com hierarquia clara: título,
   explicação e ação — nessa ordem, com a ação encostada no rodapé. */
.painel .linha-downloads {
  margin-top: var(--e-3); padding-top: var(--e-3);
  border-top: 1px solid var(--cor-borda);
}
.painel .nota + .nota { margin-top: var(--e-2); }


/* Bolha de mensagem apagada: fica no lugar, sem conteúdo. */
.mensagem.apagada { background: transparent; border-style: dashed; box-shadow: none; }
.mensagem.apagada .texto {
  display: flex; align-items: center; gap: 6px;
  color: var(--cor-texto-fraco); font-style: italic;
}
.mensagem.apagada .texto svg { width: 13px; height: 13px; flex: none; }

@media (max-width: 720px) {
  /* ---------------------- Equipe no celular ----------------------- *
   * As três colunas fixas (pessoa · papel · ações) não cabem em 375px:
   * cada pessoa virava três blocos empilhados, com o seletor órfão à
   * direita e um vazio enorme ao lado. Com 25 pessoas, rolagem sem fim.
   *
   * Aqui viram duas linhas: a pessoa ocupa a primeira inteira, e na
   * segunda ficam o papel à esquerda e as ações à direita.
   * ----------------------------------------------------------------- */
  .linha-equipe {
    grid-template-columns: auto 1fr;
    gap: var(--e-2) var(--e-2);
    padding: 10px var(--e-2);
    align-items: center;
  }
  .linha-equipe .coluna-pessoa { grid-column: 1 / -1; }
  .linha-equipe .coluna-papel { grid-column: 1; justify-content: flex-start; }
  .linha-equipe .seletor-papel { min-width: 0; width: auto; }
  .linha-equipe .coluna-acompanha {
    grid-column: 2; justify-content: flex-end; flex-wrap: nowrap;
  }
  /* "Acompanha" perde o texto e fica só o olho: o rótulo empurrava o
     "Remover" para fora da tela em nome longo. */
  .linha-equipe .acompanha span { display: none; }

  /* Alvo de dedo. Os botões compactos ficavam com 26px de altura — bons
     para ponteiro, pequenos demais para toque, que precisa de ~44px.
     A altura cresce sem mudar a aparência: o preenchimento é vertical. */
  .linha-equipe .coluna-acompanha button,
  .linha-equipe .seletor-papel { min-height: 40px; }
  .linha-equipe .coluna-acompanha .botao-icone { min-width: 40px; }
  .linha-equipe .acompanha { padding: 5px 10px; }

  /* O topo da página: busca e ação lado a lado ficavam apertados. */
  .linha-topo { flex-wrap: wrap; }
  .linha-topo .busca-modal { flex: 1 1 100%; }
  .linha-topo button { flex: 1 1 auto; }

  /* Cabeçalho da página ocupa altura demais no celular. */
  .pagina-cabecalho { padding: var(--e-3) var(--e-3) var(--e-2); }
  .pagina-cabecalho h1 { font-size: 18px; }
  .pagina-cabecalho .subtitulo { font-size: 12px; }
  .pagina-corpo { padding: var(--e-3) var(--e-3) var(--e-7); }
}

/* Vídeo na conversa: capa com o primeiro quadro, como num aplicativo de
   mensagem. O quadro é desenhado pelo próprio navegador — não há
   miniatura gerada no servidor. */
.abrir-video {
  position: relative; display: block; padding: 0; border: 0;
  background: none; cursor: pointer; margin: 2px 0; line-height: 0;
}
.video-previa {
  display: block; max-width: 100%; max-height: 420px;
  border-radius: var(--raio); background: #000;
  /* Sem altura mínima, um vídeo cujo quadro não carregou colapsa para
     zero e a bolha vira uma linha fina. */
  min-width: 150px; min-height: 96px;
  object-fit: cover;
}
.abrir-video:hover .video-previa { outline: 2px solid var(--md-laranja); outline-offset: -2px; }

.marca-play {
  position: absolute; inset: 0; display: grid; place-items: center;
  pointer-events: none;
}
.marca-play svg {
  width: 44px; height: 44px; color: #fff;
  background: rgba(0, 0, 0, .55); border-radius: 50%; padding: 11px;
  /* O fundo escuro some num vídeo escuro; a sombra devolve o contorno. */
  box-shadow: 0 1px 10px rgba(0, 0, 0, .5);
}
.duracao-video {
  position: absolute; right: 7px; bottom: 7px;
  padding: 2px 6px; border-radius: 4px; pointer-events: none;
  background: rgba(0, 0, 0, .65); color: #fff;
  font-size: 11px; font-weight: 650; line-height: 1.5;
  font-variant-numeric: tabular-nums;
}

/* ------------------------------------------------------------------ *
 * Arrastar a bolha para responder, como no WhatsApp.
 *
 * A seta mora na própria bolha, 42px à esquerda dela. Parada, a bolha
 * cobre essa posição e a seta fica invisível; ao ser puxada, as duas
 * andam juntas e a seta entra em cena no espaço que abriu.
 * ------------------------------------------------------------------ */
/* Diz ao navegador: a rolagem vertical é sua, o movimento horizontal é
   nosso. Sem esta linha o celular começa a rolar e para de mandar os
   eventos do arrasto no meio do caminho. */
.mensagem { touch-action: pan-y; }
.mensagem.arrastando { transition: none; cursor: grabbing; }
/* Arrastar com o mouse não pode sair selecionando o texto da conversa. */
body.arrastando-mensagem { user-select: none; -webkit-user-select: none; }
.mensagem::before {
  content: "↩";
  position: absolute; left: -42px; top: 50%;
  width: 30px; height: 30px; margin-top: -15px;
  display: grid; place-items: center; border-radius: 50%;
  background: var(--cor-cartao-alt); color: var(--cor-texto-fraco);
  font-size: 15px; line-height: 1;
  opacity: 0; transform: scale(.7);
  transition: opacity .12s, transform .12s, background .12s, color .12s;
  pointer-events: none;
}
.mensagem.arrastando::before { opacity: .5; transform: scale(.85); }
/* Passou do ponto: laranja avisa que soltar agora responde. */
.mensagem.vai-responder::before {
  opacity: 1; transform: scale(1);
  background: var(--md-laranja); color: var(--md-preto);
}
/* Volta suave ao soltar sem responder. */
.mensagem { transition: transform .16s ease-out; }


/* ------------------------------------------------------------------ *
 * Janela estreita, mas com mouse.
 *
 * A faixa de celular acima aumenta tudo de propósito: dedo precisa de
 * área. Só que ela pega por LARGURA, e quem usa o chat numa janela
 * estreita no computador herdava alvos de 40px e fontes de 16px sem
 * precisar — a tela ficava com cara de aplicativo esticado, com pouca
 * conversa visível e muito espaço vazio.
 *
 * `pointer: fine` é o que distingue os dois casos: mouse e trackpad são
 * finos, dedo é grosso. O celular de verdade não entra aqui e continua
 * com os alvos grandes.
 * ------------------------------------------------------------------ */
@media (max-width: 720px) and (pointer: fine) {
  .conversa-item { padding: 7px var(--e-3); }
  .botao-icone { min-width: 30px; min-height: 30px; }

  :root { --altura-filtro: 26px; }
  .filtro { padding: 0 10px; font-size: 11px; }
  .seletor-etiqueta select { padding: 0 15px 0 0; font-size: 11px; max-width: 116px; }

  /* Os 16px existem só para o iPhone não dar zoom ao focar um campo. */
  input, textarea, select { font-size: 13px; }
  .busca { padding: var(--e-2) var(--e-3) 6px; }
  .busca input { min-height: 32px; }

  .lista-cabecalho .acoes .botao-icone,
  .conversa-cabecalho .acoes .botao-icone { min-width: 30px; min-height: 30px; }
  .redator .botao-icone, .redator .enviar { min-width: 32px; min-height: 32px; }

  /* O cartão da conexão do WhatsApp ocupava quase um quinto da altura. */
  .detalhes-secao { padding: var(--e-2) var(--e-3); }

  /* A barra de baixo não precisa de altura de dedo. */
  :root { --alvo-nav: 46px; }
  .lateral { padding: 2px var(--e-2) 2px; }
  .lateral-linha .lateral-botao.quadrado { width: 32px; height: 32px; }
  .nav-item svg { width: 20px; height: 20px; }
  .nav-item span { font-size: 10px; }

  .mensagem { max-width: 92%; }
  .linha-mensagem { max-width: 94%; }
}

/* ------------------------------------------------------------------ *
 * Celular de verdade: a lista cresce.
 *
 * A faixa de largura acima já dava área de toque, mas o texto continuava
 * do tamanho do computador — no braço esticado, nome e prévia ficavam
 * pequenos demais para ler de relance. Aqui só entra quem tem ponteiro
 * grosso, isto é, dedo: a janela estreita no computador segue compacta,
 * que é o que ela precisa ser.
 * ------------------------------------------------------------------ */
@media (max-width: 720px) and (pointer: coarse) {
  .conversa-item { padding: 16px var(--e-3); gap: 13px; }
  .conversa-item .avatar.p { width: 50px; height: 50px; font-size: 17px; }
  .conversa-item .linha strong { font-size: 17px; }
  .conversa-item .previa { font-size: 15px; }
  .conversa-item time { font-size: 12px; }
  .conversa-item .etiquetas .chip { padding: 1px 8px; font-size: 11.5px; line-height: 19px; }
  .conversa-item .nao-lidas { font-size: 12px; min-width: 23px; height: 23px; }

  /* O título da conversa aberta acompanha, senão a bolha fica maior que
     o nome de quem está do outro lado. */
  .conversa-cabecalho .titulo strong { font-size: 17px; }
  .lista-cabecalho h2 { font-size: 18px; }
  .rotulo-secao { font-size: 11px; }
}
/* ------------------------------------------------------------------ *
 * Folha "Mais" da barra de baixo.
 *
 * Reaproveita a linha do menu de anexo (`.opcao-anexo`), mas com peso
 * próprio: ali são três opções num menu pequeno, aqui são nove e é a
 * única porta para metade do sistema no celular. Os tamanhos ficam
 * escopados nesta classe para não engordar o menu de anexo junto.
 * ------------------------------------------------------------------ */
.folha-navegacao { display: flex; flex-direction: column; gap: 1px; margin-top: var(--e-2); }
.folha-navegacao .opcao-anexo { min-height: 52px; padding: var(--e-2) var(--e-3); gap: var(--e-3); }
.folha-navegacao .opcao-anexo svg { width: 23px; height: 23px; }
.folha-navegacao .opcao-anexo strong { font-size: 15px; }
.folha-navegacao .opcao-anexo small { font-size: 12.5px; }

/* Separa os destinos do sistema (perfil, tema, sair), que são de outra
   natureza: não levam a uma tela de trabalho. */
.folha-sep {
  height: 1px; background: var(--cor-borda);
  margin: var(--e-2) var(--e-3);
}

@media (pointer: coarse) {
  /* No dedo cada linha precisa ser alvo, mas são nove delas: passando de
     54px a folha encosta no pé da tela num celular pequeno e a última
     opção — Sair — fica atrás do indicador de início. 54px continua bem
     acima dos 44px recomendados. */
  .folha-navegacao .opcao-anexo { min-height: 54px; padding: 10px var(--e-3); }
  .folha-navegacao .opcao-anexo svg { width: 23px; height: 23px; }
  .folha-navegacao .opcao-anexo strong { font-size: 15px; }
  .folha-navegacao .opcao-anexo small { font-size: 12.5px; }
  .folha-sep { margin: 6px var(--e-3); }
}

/* ------------------------------------------------------------------ *
 * Painel da administração.
 *
 * Leitura de cima para baixo, do geral ao específico: primeiro os
 * números do período, depois a forma da semana, depois quem fez, e por
 * último o que está parado — que é o único bloco onde se age.
 *
 * As barras têm a proporção posta por JavaScript (--altura, --parte,
 * --largura). A CSP proíbe estilo embutido; é a mesma razão de as cores
 * de etiqueta virem pelo CSSOM.
 * ------------------------------------------------------------------ */
.painel-admin { display: flex; flex-direction: column; gap: var(--e-4); }
.painel-conteudo { display: flex; flex-direction: column; gap: var(--e-4); }

.filtro-periodo {
  display: flex; align-items: center; gap: var(--e-1); flex-wrap: wrap;
}
.periodo-datas {
  display: inline-flex; align-items: center; gap: 6px; margin-left: auto;
  color: var(--cor-texto-fraco); font-size: 11px;
}
.periodo-datas input {
  min-height: var(--altura-filtro); padding: 0 8px; width: auto;
  font-size: 11px; color: var(--cor-texto);
  background: var(--cor-cartao); border: 1px solid var(--cor-borda-forte);
  border-radius: var(--raio);
}

/* ------------------------------ cartões ---------------------------- */
.indicadores {
  display: grid; gap: var(--e-2);
  grid-template-columns: repeat(auto-fit, minmax(168px, 1fr));
}
.cartao-indicador {
  display: flex; flex-direction: column; gap: 2px;
  padding: var(--e-3) var(--e-4);
  background: var(--cor-cartao); border: 1px solid var(--cor-borda);
  border-radius: var(--raio); border-left: 3px solid var(--md-laranja);
}
.cartao-indicador strong { font-size: 27px; line-height: 1.1; font-variant-numeric: tabular-nums; }
.cartao-indicador span { font-size: 12px; font-weight: 650; color: var(--cor-texto); }
.cartao-indicador small { font-size: 11px; color: var(--cor-texto-fraco); }
/* Fila parada é o único número em que se AGE; por isso destoa dos outros. */
.cartao-indicador.alerta { border-left-color: var(--md-vermelho); }
.cartao-indicador.alerta strong { color: var(--md-vermelho); }

.bloco-painel {
  padding: var(--e-4); background: var(--cor-cartao);
  border: 1px solid var(--cor-borda); border-radius: var(--raio);
}
.bloco-topo {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--e-2); margin-bottom: var(--e-3); flex-wrap: wrap;
}
/* A linha divisória é do BLOCO, não do título.
   `.painel-titulo` traz um `border-bottom` próprio; dentro de uma linha
   flex ele só media a largura da palavra e desenhava um traço curto e
   solto embaixo dela — parecia sublinhado por engano. */
.bloco-topo > .painel-titulo {
  border-bottom: 0; padding-bottom: 0; margin-bottom: 0;
}
.bloco-topo:has(> .painel-titulo) {
  padding-bottom: var(--e-2); border-bottom: 1px solid var(--cor-borda);
}
.legenda { display: inline-flex; align-items: center; gap: 10px; font-size: 11px; color: var(--cor-texto-fraco); }
.ponto-legenda { width: 9px; height: 9px; border-radius: 2px; display: inline-block; margin-right: 3px; }
.ponto-legenda.interno { background: var(--md-laranja); }
.ponto-legenda.whats { background: #2f7d5f; }

/* ------------------------- gráfico por dia ------------------------- */
.grafico-dias {
  display: flex; align-items: flex-end; gap: 6px;
  height: 148px; padding-top: var(--e-2);
}
.coluna-dia { flex: 1; min-width: 0; display: flex; flex-direction: column; align-items: center; gap: 5px; height: 100%; }
.coluna-dia .barra {
  width: 100%; max-width: 46px; margin-top: auto;
  height: var(--altura, 0%); min-height: 3px;
  display: flex; flex-direction: column; justify-content: flex-end;
  border-radius: 4px; overflow: hidden; background: var(--cor-cartao-alt);
}
.coluna-dia .parte { display: block; width: 100%; height: var(--parte, 0%); }
.coluna-dia .parte.whats { background: #2f7d5f; }
.coluna-dia .parte.interno { background: var(--md-laranja); }
.coluna-dia small { font-size: 10px; color: var(--cor-texto-fraco); font-variant-numeric: tabular-nums; }

/* ---------------------------- ranking ------------------------------ */
.ranking { display: flex; flex-direction: column; gap: var(--e-2); }
.linha-ranking { display: flex; align-items: center; gap: var(--e-3); }
.linha-ranking .posicao {
  width: 22px; flex: none; text-align: right;
  font-size: 13px; font-weight: 800; color: var(--cor-texto-fraco);
  font-variant-numeric: tabular-nums;
}
/* O primeiro lugar não ganha medalha: o número já ordena, e destacar o
   topo transforma acompanhamento em competição. */
.ranking-corpo { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.ranking-topo { display: flex; align-items: baseline; gap: var(--e-2); }
.ranking-topo strong { font-size: 13.5px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ranking-total { margin-left: auto; font-size: 13.5px; font-variant-numeric: tabular-nums; }
.barra-ranking {
  display: block; height: 5px; border-radius: 999px;
  background: var(--md-laranja); width: var(--largura, 0%); min-width: 3px;
}
.ranking-nota { font-size: 11px; color: var(--cor-texto-fraco); }

/* ------------------------ esperando resposta ----------------------- */
.fila-espera { display: flex; flex-direction: column; }
.linha-espera {
  display: flex; align-items: center; gap: var(--e-2);
  padding: 6px 0; border-bottom: 1px solid var(--cor-borda);
}
.linha-espera:last-child { border-bottom: none; }
.linha-espera.escondida { display: none; }
.espera-quem { display: flex; align-items: baseline; gap: 6px; min-width: 0; flex: 1; }
.espera-quem strong {
  font-size: 12.5px; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.espera-quem small { font-size: 11px; color: var(--cor-texto-fraco); white-space: nowrap; flex: none; }
/* O selo de grupo é informação secundária: discreto para não competir
   com o nome, que é o que a pessoa procura na lista. */
.fila-espera .chip {
  flex: none; padding: 0 5px; font-size: 9.5px; line-height: 15px;
  border-radius: 3px; color: var(--cor-texto-fraco);
}
.espera-tempo {
  flex: none; font-size: 11.5px; font-weight: 650;
  color: var(--cor-texto-fraco); font-variant-numeric: tabular-nums;
}
/* Três faixas em vez de tudo vermelho: quando toda linha grita, nenhuma
   chama atenção. Vermelho fica para o que passou de uma semana. */
.espera-tempo.atencao { color: var(--md-laranja-texto); }
.espera-tempo.grave { color: var(--md-vermelho); }

@media (max-width: 720px) {
  .periodo-datas { margin-left: 0; width: 100%; }
  .periodo-datas input { flex: 1; min-width: 0; }
  .grafico-dias { height: 120px; gap: 3px; }
  .cartao-indicador strong { font-size: 23px; }
  /* No celular o nome de quem espera importa mais que o nome de quem
     atende — sem isso os dois disputam a mesma linha estreita. */
  .espera-quem small { display: none; }
}

/* Os dois canais lado a lado: interno e WhatsApp têm números próprios e
   filas próprias. Misturar os dois num total só escondia qual dos dois
   estava parado — que é a primeira pergunta de quem abre este painel. */
.canais {
  display: grid; gap: var(--e-2);
  grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
  /* `start` deixava um painel mais curto que o outro conforme a fila de
     cada canal; esticados, as bordas fecham na mesma linha. */
  align-items: stretch;
}
.bloco-painel.canal { display: flex; flex-direction: column; gap: var(--e-2); }
.bloco-painel.canal .rotulo-secao { margin-top: var(--e-1); }

.numeros-canal {
  /* Quatro colunas fixas nos dois canais: com `auto-fit`, um painel de
     dois números fazia caixas do dobro da largura das do outro, e os
     blocos deixavam de se ler como o mesmo tipo de informação. */
  display: grid; gap: 1px; background: var(--cor-borda);
  grid-template-columns: repeat(4, minmax(0, 1fr));
  border: 1px solid var(--cor-borda); border-radius: var(--raio); overflow: hidden;
}
.numero-canal {
  display: flex; flex-direction: column; gap: 1px;
  padding: var(--e-2) var(--e-3); background: var(--cor-cartao);
}
.numero-canal strong { font-size: 19px; line-height: 1.1; font-variant-numeric: tabular-nums; }
.numero-canal span { font-size: 10.5px; color: var(--cor-texto-fraco); }
.numero-canal.alerta strong { color: var(--md-vermelho); }

.bloco-topo .ponto-legenda { width: 10px; height: 10px; }
.fila-espera .nota { padding-top: var(--e-2); font-size: 11px; }

/* ------------------------------------------------------------------ *
 * Mensagem fixada.
 *
 * Uma por vez no alto da conversa, com contador quando há mais. Listar
 * todas empurraria a conversa para baixo — e o ganho de fixar é ter o
 * recado à mão SEM perder a tela de vista.
 * ------------------------------------------------------------------ */
.barra-fixadas {
  display: flex; align-items: center; gap: var(--e-2);
  padding: 7px var(--e-3); background: var(--cor-cartao-alt);
  border-bottom: 1px solid var(--cor-borda);
  border-left: 3px solid var(--md-laranja);
}
.barra-fixadas > svg { width: 15px; height: 15px; flex: none; color: var(--md-laranja-texto); }
.fixada-corpo {
  flex: 1; min-width: 0; text-align: left; padding: 0; background: none;
  display: flex; flex-direction: column; gap: 1px; cursor: pointer;
}
.fixada-corpo strong {
  font-size: 12.5px; font-weight: 600; color: var(--cor-texto);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.fixada-corpo small { font-size: 10.5px; color: var(--cor-texto-fraco); }
.fixada-corpo:hover strong { color: var(--md-laranja-texto); }
.barra-fixadas .selo-contagem { flex: none; font-variant-numeric: tabular-nums; }
.barra-fixadas .botao-icone { flex: none; width: 28px; height: 28px; }
.barra-fixadas .botao-icone svg { width: 14px; height: 14px; }

/* Alfinete aceso na bolha que está fixada: sem isto, o único jeito de
   saber qual mensagem está na barra é comparando o texto. */
.acao-mensagem.fixada { color: var(--md-laranja-texto); border-color: var(--md-laranja); }

/* Ponto de estado da conexão, ao lado do título da lista do WhatsApp.
   Substituiu a faixa que anunciava o número em cima de toda conversa. */
.selo-conexao {
  display: inline-grid; place-items: center; flex: none;
  width: 20px; height: 20px; padding: 0; border-radius: 50%;
  background: none; cursor: pointer;
}
.selo-conexao:hover { background: var(--cor-cartao-alt); }
.selo-conexao .presenca { width: 9px; height: 9px; }
/* Fora do ar não pode ser discreto como estar no ar. */
.selo-conexao.offline .presenca, .selo-conexao.not_connected .presenca,
.selo-conexao.disabled .presenca { background: var(--md-vermelho); }
.selo-conexao.qr .presenca, .selo-conexao.connecting .presenca { background: var(--md-laranja); }

.estado-conexao { display: flex; align-items: flex-start; gap: var(--e-3); }
.estado-conexao .presenca { margin-top: 6px; flex: none; }
.estado-conexao strong { font-size: 15px; }
.numero-conectado {
  display: block; font-size: 13px; color: var(--cor-texto-fraco);
  font-variant-numeric: tabular-nums; margin-top: 1px;
}

/* ------------------------------------------------------------------ *
 * Cartão de serviço ligado à conta (Todoist, e o que vier depois).
 *
 * Mesmo desenho do cartão de conexão do WhatsApp, de propósito: são a
 * mesma pergunta — "isto está ligado à minha conta?" — e antes uma era
 * um cartão com barra colorida e a outra um painel alto com título
 * sublinhado e dois parágrafos. Duas formas para a mesma ideia fazem a
 * página parecer montada por pessoas diferentes.
 * ------------------------------------------------------------------ */
.cartao-servico {
  display: flex; align-items: center; gap: var(--e-3);
  padding: var(--e-3) var(--e-4); background: var(--cor-cartao);
  border: 1px solid var(--cor-borda); border-radius: var(--raio);
  border-left: 3px solid var(--cor-borda-forte);
  margin-bottom: var(--e-4);
}
/* Ligado muda a barra, como o cartão do WhatsApp fica verde: dá para
   ver o estado antes de ler qualquer palavra. */
.cartao-servico.ligado { border-left-color: var(--md-laranja); }
.servico-marca {
  flex: none; width: 36px; height: 36px; border-radius: var(--raio);
  display: grid; place-items: center;
  background: var(--cor-cartao-alt); color: var(--md-laranja-texto);
}
.servico-marca svg { width: 18px; height: 18px; }
.servico-corpo { flex: 1; min-width: 0; }
.servico-corpo strong { display: block; font-size: 14px; }
.servico-corpo .nota { margin: 2px 0 0; }
.cartao-servico > button { flex: none; }

/* Aba Conexão. O cartão do estado é a resposta à única pergunta que
   importa; o "como funciona" existe para quem chegou com dúvida. */
.cartao-conexao {
  padding: var(--e-4); background: var(--cor-cartao);
  border: 1px solid var(--cor-borda); border-radius: var(--raio);
  border-left: 3px solid var(--md-verde, #2f7d5f);
}
/* Fora do ar muda a cor da borda, não só o ponto: o cartão inteiro
   precisa dizer que há algo errado antes de alguém ler o texto. */
.cartao-conexao.offline, .cartao-conexao.not_connected,
.cartao-conexao.disabled { border-left-color: var(--md-vermelho); }
.cartao-conexao.qr, .cartao-conexao.connecting { border-left-color: var(--md-laranja); }

.cartao-conexao .estado-conexao { align-items: center; }
.cartao-conexao .estado-corpo { flex: 1; min-width: 0; }
.cartao-conexao .estado-corpo .nota { margin-top: 3px; }
.cartao-conexao .primario { width: 100%; }

.lista-explicativa { display: flex; flex-direction: column; gap: var(--e-3); margin-top: var(--e-2); }
.lista-explicativa li { list-style: none; font-size: 12.5px; color: var(--cor-texto-fraco); line-height: 1.5; }
.lista-explicativa strong { display: block; color: var(--cor-texto); font-size: 13px; margin-bottom: 1px; }


/* ------------------------------------------------------------------ *
 * Zoom indesejado no celular.
 *
 * O iPhone amplia a página sozinho quando o campo focado tem fonte
 * MENOR que 16px. O campo de mensagem estava em 15,5px — meio ponto
 * abaixo do limite —, e a regra geral de 16px não o alcançava porque
 * `.redator textarea` é mais específica que `textarea`. Resultado: tocar
 * para escrever ampliava a tela, e voltar dependia de fechar o teclado.
 *
 * `max()` mantém o aumento escolhido em A+ e impede a queda abaixo de 16.
 * ------------------------------------------------------------------ */
@media (pointer: coarse) {
  .redator textarea { font-size: max(16px, calc(15.5px * var(--escala-chat))); }
  .busca input, .modal input, .modal textarea, .modal select { font-size: 16px; }
}

/* Sem o atraso do toque duplo, que é o que o navegador reserva para
   decidir se você quis ampliar. Também evita o zoom acidental ao tocar
   duas vezes rápido numa mensagem. */
html { touch-action: manipulation; -webkit-text-size-adjust: 100%; }

/* O painel da conversa NÃO anima transform.
   Tinha uma transição aqui para o gesto de puxar da borda, que foi
   removido em 15/09/2026 — ver a nota em main.js. Uma transição de
   transform no painel inteiro faz o navegador promovê-lo a camada e
   repintar a conversa toda a cada quadro; sem o gesto, é custo sem uso. */

/* Preferências de aviso e conversas silenciadas. */
.lista-opcoes { display: flex; flex-direction: column; gap: 1px; margin-top: var(--e-2); }
.linha-opcao {
  display: flex; align-items: center; gap: var(--e-3);
  padding: var(--e-2) 0; cursor: pointer;
}
.linha-opcao + .linha-opcao { border-top: 1px solid var(--cor-borda); }
.opcao-texto { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.opcao-texto strong { font-size: 13.5px; }
.opcao-texto small { font-size: 11.5px; color: var(--cor-texto-fraco); }
.linha-opcao input[type='checkbox'] { width: 18px; height: 18px; flex: none; accent-color: var(--md-laranja); }

.lista-silenciadas { display: flex; flex-direction: column; margin-top: var(--e-2); }
.linha-silenciada {
  display: flex; align-items: center; gap: var(--e-2);
  padding: var(--e-2) 0; border-bottom: 1px solid var(--cor-borda);
}
.linha-silenciada:last-child { border-bottom: none; }
.silenciada-corpo { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.silenciada-corpo strong { font-size: 13px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.silenciada-corpo small { font-size: 11px; color: var(--cor-texto-fraco); }

/* ------------------------------------------------------------------ *
 * Medidores do servidor.
 *
 * Barra em vez de número puro porque o que importa aqui é a PROPORÇÃO:
 * "38 GB" não diz nada; "38% do disco" diz. A cor muda sozinha nos
 * cortes que importam — 70% é hora de olhar, 85% é hora de agir.
 * ------------------------------------------------------------------ */
.medidores { display: flex; flex-direction: column; gap: var(--e-3); margin-top: var(--e-2); }
.medidor { display: flex; flex-direction: column; gap: 4px; }
.medidor-topo { display: flex; align-items: baseline; justify-content: space-between; gap: var(--e-2); }
.medidor-topo strong { font-size: 13px; }
.medidor-topo b { font-size: 14px; font-variant-numeric: tabular-nums; color: var(--md-verde, #2f7d5f); }
.medidor small { font-size: 11px; color: var(--cor-texto-fraco); }

.medidor-trilho {
  display: block; height: 7px; border-radius: 999px;
  background: var(--cor-cartao-alt); overflow: hidden;
}
.medidor-trilho i {
  display: block; height: 100%; width: var(--largura, 0%);
  background: #2f7d5f; border-radius: 999px;
  transition: width .3s ease-out;
}
.medidor.atencao .medidor-trilho i { background: var(--md-laranja); }
.medidor.atencao .medidor-topo b { color: var(--md-laranja-texto); }
.medidor.grave .medidor-trilho i { background: var(--md-vermelho); }
.medidor.grave .medidor-topo b { color: var(--md-vermelho); }

/* ------------------------------------------------------------------ *
 * A caixa de escrever.
 *
 * Emoji, anexo e texto num invólucro só, com a borda e o fundo que antes
 * eram do campo. Os ícones passam a ser parte do campo, não vizinhos
 * dele — que é o que fazia a barra parecer desmontada mesmo com os
 * espaçamentos certos.
 * ------------------------------------------------------------------ */
.caixa-mensagem {
  flex: 1; min-width: 0;
  /* `center` com uma linha, e o campo cresce para baixo quando o texto
     passa de uma: os ícones ficam junto da PRIMEIRA linha, que é onde o
     olho está. Com `flex-end` eles desciam acompanhando o texto. */
  display: flex; align-items: center; gap: 0;
  background: var(--cor-cartao-alt);
  border: 1px solid transparent; border-radius: 22px;
  padding-right: 4px;
  transition: border-color .12s;
}
/* O realce de foco vai para a CAIXA, não para o campo lá dentro: assim
   a borda laranja contorna o conjunto e não desenha um retângulo solto. */
.caixa-mensagem:focus-within { border-color: var(--md-laranja-borda); }

/* O campo perde fundo, BORDA e cantos: quem os tem agora é a caixa.
   Faltava a borda — e ela continuava desenhando um retângulo dentro da
   pílula, com uma linha vertical logo depois do clipe. Era isso que
   parecia defeito de alinhamento. */
.redator .caixa-mensagem textarea {
  background: none; border: 0; border-radius: 0;
  padding: 11px 10px 11px 4px; box-shadow: none;
}
.redator .caixa-mensagem textarea:focus,
.redator .caixa-mensagem textarea:focus-visible { outline: none; box-shadow: none; }

/* Dentro da caixa os botões encolhem: 44px cada deixava a caixa alta
   demais e empurrava o texto para longe da borda esquerda. */
.caixa-mensagem .botao-icone {
  width: 38px; height: 38px; margin-bottom: 3px; border-radius: 50%;
}
.caixa-mensagem .botao-icone:first-child { margin-left: 3px; }

/* ------------------------------------------------------------------ *
 * Silêncio da conversa, no painel de detalhes.
 *
 * Nasceu sem estilo e o sino caiu numa linha própria, com a lista
 * ocupando a largura toda — parecia defeito. Segue o mesmo desenho do
 * seletor de etiqueta: um rótulo que contém o ícone e a lista, lidos
 * como um controle só.
 * ------------------------------------------------------------------ */
.seletor-silencio {
  display: flex; align-items: center; gap: var(--e-2);
  width: 100%; min-height: 38px; padding: 0 10px;
  background: var(--cor-cartao-alt);
  border: 1px solid var(--cor-borda-forte); border-radius: var(--raio);
  color: var(--cor-texto-fraco); cursor: pointer;
}
.seletor-silencio:hover { border-color: var(--cor-texto-fraco); }
.seletor-silencio > svg { width: 16px; height: 16px; flex: none; }
/* Silenciada: o sino muda de cor, não só o texto da lista. */
.seletor-silencio:has(select:not([value=""])) > svg { color: var(--md-laranja-texto); }

.seletor-silencio select {
  flex: 1; min-width: 0; appearance: none; border: 0; background: transparent;
  color: var(--cor-texto); font: inherit; font-size: 12.5px; font-weight: 600;
  padding: 8px 16px 8px 0; cursor: pointer;
  /* Mesma setinha desenhada no fundo dos outros seletores. */
  background-image: linear-gradient(45deg, transparent 50%, var(--cor-texto-fraco) 50%),
    linear-gradient(135deg, var(--cor-texto-fraco) 50%, transparent 50%);
  background-position: right 9px center, right 4px center;
  background-size: 5px 5px, 5px 5px; background-repeat: no-repeat;
}
.seletor-silencio select option { background: var(--cor-cartao); color: var(--cor-texto); }
.seletor-silencio select:focus-visible { outline: none; }
.seletor-silencio:focus-within { border-color: var(--md-laranja-borda); }

/* ------------------------------------------------------------------ *
 * Menu de ações da mensagem.
 *
 * Um gatilho só, e as opções com nome. Antes eram botões redondos de
 * 24px lado a lado na quina da bolha — e um deles apagava a mensagem.
 * Alvo pequeno ao lado de ação destrutiva é onde o erro acontece.
 * ------------------------------------------------------------------ */
.acoes-mensagem { position: absolute; top: -11px; right: 8px; z-index: 3; display: flex; }
.gatilho-acoes {
  width: 26px; height: 26px; padding: 0; border-radius: 50%;
  display: grid; place-items: center;
  background: var(--cor-cartao); border: 1px solid var(--cor-borda);
  color: var(--cor-texto-fraco); opacity: 0; transition: opacity .12s;
}
.mensagem:hover .gatilho-acoes,
.acoes-mensagem:focus-within .gatilho-acoes,
.gatilho-acoes[aria-expanded='true'] { opacity: 1; }
.gatilho-acoes:hover { color: var(--cor-texto); border-color: var(--cor-borda-forte); }
.gatilho-acoes svg { width: 14px; height: 14px; }

/* O menu abre AO LADO da bolha, nunca por cima da conversa.
   Mensagem recebida (bolha à esquerda) abre à direita; a minha (bolha à
   direita) abre à esquerda. Antes ele descia a partir do botão e tapava
   as duas ou três mensagens seguintes — justamente o contexto que a
   pessoa precisa ver para decidir o que fazer. */
.menu-mensagem {
  position: absolute; top: 0; left: calc(100% + 8px); z-index: 20; min-width: 172px;
  display: flex; flex-direction: column; gap: 1px; padding: 4px;
  background: var(--cor-cartao); border: 1px solid var(--cor-borda);
  border-radius: var(--raio); box-shadow: var(--sombra-2);
}
.mensagem.minha .menu-mensagem { left: auto; right: calc(100% + 8px); }
.opcao-mensagem {
  display: flex; align-items: center; gap: var(--e-2);
  padding: 8px 10px; border-radius: var(--raio); width: 100%;
  text-align: left; font-size: 13px; color: var(--cor-texto);
}
.opcao-mensagem:hover { background: var(--cor-cartao-alt); }
.opcao-mensagem svg { width: 15px; height: 15px; flex: none; color: var(--cor-texto-fraco); }
/* Apagar em vermelho e por último: a cor avisa antes da leitura. */
.opcao-mensagem.perigo { color: var(--md-vermelho); }
.opcao-mensagem.perigo svg { color: var(--md-vermelho); }

/* Escolher para onde encaminhar. */
.lista-destinos { display: flex; flex-direction: column; max-height: 46vh; overflow-y: auto; }
.destino {
  display: flex; align-items: center; gap: var(--e-3);
  padding: var(--e-2); border-radius: var(--raio); width: 100%; text-align: left;
}
.destino:hover { background: var(--cor-cartao-alt); }
.destino-corpo { display: flex; flex-direction: column; min-width: 0; }
.destino-corpo strong { font-size: 13px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.destino-corpo small { font-size: 11px; color: var(--cor-texto-fraco); }

/* No celular a bolha ocupa quase a largura toda: não sobra lado nenhum.
   Aí o menu vira folha presa no rodapé — o mesmo lugar em que o WhatsApp
   põe, e o único que não cobre a conversa. */
@media (max-width: 720px) {
  .gatilho-acoes { opacity: 1; }

  .menu-mensagem {
    position: fixed; inset: auto 0 0 0; top: auto; left: 0; right: 0;
    /* ACIMA do compositor (45) e da barra de navegação (40).
       O z-index de 20 que vem da regra geral serve no computador, onde o
       menu abre ao LADO da bolha e não disputa espaço com nada. No
       celular ele é folha no rodapé, no mesmo lugar onde moram os dois —
       e ficava atrás deles: a pessoa tocava em "responder" e via o menu
       aparecer por baixo da caixa de texto, com metade escondida.

       48 e não mais: o fundo do modal está em 50, e um menu de mensagem
       flutuando por cima de uma janela de confirmação seria trocar um
       defeito por outro pior. */
    z-index: 48;
    min-width: 0; padding: var(--e-2) var(--e-2) calc(var(--e-2) + env(safe-area-inset-bottom, 0px));
    border-radius: 14px 14px 0 0; border-bottom: none;
    box-shadow: 0 -10px 30px rgba(0, 0, 0, .45);
  }
  .mensagem.minha .menu-mensagem { right: 0; left: 0; }
  .menu-mensagem .opcao-mensagem { min-height: 48px; font-size: 15px; }
  .menu-mensagem .opcao-mensagem svg { width: 19px; height: 19px; }
}

/* ------------------------------------------------------------------ *
 * Enquadrar a foto.
 *
 * A janela é quadrada e a máscara desenha o círculo por cima — o mesmo
 * círculo do avatar. Ver o resultado enquanto arrasta é o que evita a
 * foto sair cortada no pescoço depois de salva.
 * ------------------------------------------------------------------ */
.corte-area {
  position: relative; overflow: hidden; margin: var(--e-3) auto 0;
  background: var(--md-preto); border-radius: var(--raio);
  cursor: grab; touch-action: none; user-select: none;
}
.corte-area:active { cursor: grabbing; }
.corte-area img { position: absolute; top: 0; left: 0; max-width: none; transform-origin: 0 0; }
/* Escurece fora do círculo, sem atrapalhar o arrasto. */
.corte-mascara {
  position: absolute; inset: 0; pointer-events: none;
  box-shadow: 0 0 0 999px rgba(10, 8, 8, .62) inset;
  border-radius: 50%;
}
.corte-zoom { display: flex; align-items: center; gap: var(--e-3); margin-top: var(--e-3); }
.corte-zoom small { color: var(--cor-texto-fraco); font-size: 12px; flex: none; }
.corte-zoom input[type='range'] { flex: 1; accent-color: var(--md-laranja); }

/* Marca de mensagem corrigida. Discreta mas permanente: quem lê precisa
   saber que o texto mudou depois de enviado, sem que isso dispute a
   atenção com o conteúdo. */
.marca-editada {
  font-size: 10px; font-style: normal; color: var(--cor-texto-fraco);
  opacity: .75; margin-right: 4px;
}

/* Dois campos lado a lado no formulário de tarefa. Empilhados, o
   formulário ficava com sete campos em coluna e não cabia na tela. */
.linha-campos { display: flex; gap: var(--e-3); }
.linha-campos .campo { flex: 1; min-width: 0; }
@media (max-width: 620px) { .linha-campos { flex-direction: column; gap: 0; } }


/* Linha de ajuste: explicação à esquerda, controle à direita.
   O texto explica o EFEITO, não o nome do campo — quem muda um ajuste
   precisa saber o que muda para a equipe, não como ele se chama. */
.linha-ajuste {
  display: flex; align-items: center; gap: var(--e-3);
  padding: var(--e-3) 0; border-bottom: 1px solid var(--cor-borda);
}
.linha-ajuste:last-child { border-bottom: none; }
.ajuste-texto { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.ajuste-texto strong { font-size: 13.5px; }
.ajuste-texto small { font-size: 11.5px; color: var(--cor-texto-fraco); line-height: 1.45; }
.linha-ajuste .seletor-papel { flex: none; }
/* Ajuste que não se muda aqui aparece como selo, não como campo travado:
   campo desabilitado convida ao clique e frustra. */
.linha-ajuste .chip { flex: none; }

@media (max-width: 620px) {
  .linha-ajuste { flex-direction: column; align-items: stretch; gap: var(--e-2); }
}

/* ------------------------------------------------------------------ *
 * Configurações.
 *
 * Antes era uma pilha de sete caixas iguais: o ajuste que muda a regra
 * da empresa tinha o mesmo peso visual do link de download. Agora os
 * grupos têm cabeçalho próprio, e cada tipo de coisa tem uma forma
 * distinta — cartão de ajuste com controle à direita, cartão de
 * download com ícone e seta. A forma diz o que fazer antes da leitura.
 * ------------------------------------------------------------------ */
.coluna-config { max-width: 720px; display: flex; flex-direction: column; gap: var(--e-5); }

.secao-cabecalho { margin-bottom: var(--e-3); }
.secao-cabecalho h3 { font-size: 15px; margin-bottom: 2px; }
.secao-cabecalho p { font-size: 12.5px; color: var(--cor-texto-fraco); line-height: 1.5; }

/* ------------------------------ ajustes --------------------------- */
.ajuste-cartao {
  display: flex; align-items: center; gap: var(--e-3);
  padding: var(--e-3); background: var(--cor-cartao);
  border: 1px solid var(--cor-borda); border-radius: var(--raio);
}
.ajuste-cartao + .ajuste-cartao { margin-top: var(--e-2); }
.ajuste-marca {
  width: 36px; height: 36px; flex: none; border-radius: var(--raio);
  display: grid; place-items: center;
  background: var(--cor-cartao-alt); color: var(--md-laranja-texto);
}
.ajuste-marca svg { width: 18px; height: 18px; }
.ajuste-corpo { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.ajuste-corpo strong { font-size: 13.5px; }
.ajuste-corpo small { font-size: 11.5px; color: var(--cor-texto-fraco); line-height: 1.5; }
.ajuste-cartao .seletor-papel { flex: none; }
/* O que não se muda aqui é selo, não campo travado: campo desabilitado
   convida ao clique e frustra. */
.chip.fixo { flex: none; opacity: .8; }
.nota.recuada { margin-top: var(--e-2); padding-left: 2px; }

/* ----------------------------- downloads -------------------------- */
.grade-downloads { display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--e-2); }
.cartao-download {
  display: flex; align-items: center; gap: var(--e-3);
  padding: var(--e-3); background: var(--cor-cartao);
  border: 1px solid var(--cor-borda); border-radius: var(--raio);
  color: var(--cor-texto); text-decoration: none; transition: border-color .12s;
}
.cartao-download:hover { border-color: var(--cor-borda-forte); background: var(--cor-cartao-alt); }
.download-icone {
  width: 36px; height: 36px; flex: none; border-radius: var(--raio);
  display: grid; place-items: center;
  background: var(--cor-cartao-alt); color: var(--md-laranja-texto);
}
.download-icone svg { width: 18px; height: 18px; }
.download-corpo { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.download-corpo strong { font-size: 13px; }
.download-corpo small { font-size: 11px; color: var(--cor-texto-fraco); line-height: 1.45; }
.download-seta { flex: none; color: var(--cor-texto-fraco); }
.download-seta svg { width: 16px; height: 16px; }

/* O banco inteiro é outra coisa: sai da grade e ganha borda de alerta,
   porque baixar ali é levar todas as conversas da empresa num arquivo. */
.cartao-download.perigo { border-color: var(--md-vermelho); }
.cartao-download.perigo .download-icone { color: var(--md-vermelho); }

@media (max-width: 720px) {
  .grade-downloads { grid-template-columns: 1fr; }
  .ajuste-cartao { flex-wrap: wrap; }
  .ajuste-cartao .seletor-papel, .chip.fixo { margin-left: 48px; }
}

/* ------------------------------------------------------------------ *
 * Aparelhos conectados (aba Conexão, administração).
 *
 * Um cartão por pessoa, uma linha por aparelho. O ícone diz de relance
 * se é celular ou computador — que é a informação usada para decidir
 * qual desconectar, e antes exigia ler "Mozilla/5.0 (Macintosh...".
 *
 * O botão de desconectar é discreto até o ponteiro chegar perto: ele
 * derruba a sessão de outra pessoa, e não deve competir por atenção com
 * a leitura da lista.
 * ------------------------------------------------------------------ */
/* Em colunas, e não numa fila só.
   São 26 pessoas: empilhadas, a tela virava uma rolagem de vários metros
   para achar UMA, e cada cartão ocupava a largura inteira do painel só
   para mostrar duas linhas. Em grade, a equipe toda cabe em uma ou duas
   telas e a busca vira varredura de olho. */
.lista-aparelhos {
  /* A explicação acima é um parágrafo solto e encostava na primeira
     linha de cartões — o texto parecia legenda do cartão, não do painel. */
  margin-top: var(--e-3);
  display: grid; gap: var(--e-2);
  grid-template-columns: repeat(auto-fill, minmax(268px, 1fr));
  align-items: start;
}
/* "Carregando…", "ninguém conectado" e o erro ocupam a linha toda. */
.lista-aparelhos > p { grid-column: 1 / -1; margin: 0; }

.cartao-pessoa {
  padding: 7px 10px;
  background: var(--cor-cartao-alt);
  border: 1px solid var(--cor-borda); border-radius: var(--raio);
}

/* A linha da pessoa é o `<summary>`: clicável inteira, sem a setinha
   padrão do navegador — ela desalinhava o avatar e não combinava com
   nada mais da tela. O sinal de que abre é o cursor e o realce. */
.cartao-pessoa > summary { list-style: none; cursor: pointer; }
.cartao-pessoa > summary::-webkit-details-marker { display: none; }
.cartao-pessoa > summary:hover { color: var(--md-laranja-texto); }
.cartao-pessoa[open] > summary { margin-bottom: 4px; }

.pessoa-topo { display: flex; align-items: center; gap: var(--e-2); }
.pessoa-nome { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.pessoa-nome strong { font-size: 13px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pessoa-nome small { font-size: 11px; color: var(--cor-texto-fraco); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.vagas {
  flex: none; font-size: 11px; font-weight: 700; font-variant-numeric: tabular-nums;
  padding: 2px 8px; border-radius: 999px;
  color: var(--cor-texto-fraco); border: 1px solid var(--cor-borda-forte);
}
/* Sem vaga: a próxima entrada dessa pessoa derruba um aparelho, e isso
   merece ser visto antes de se ler o número. */
.vagas.cheio { color: var(--md-laranja-texto); border-color: var(--md-laranja-borda); }

.linha-aparelho {
  display: flex; align-items: center; gap: var(--e-2);
  padding: 4px 0 4px 2px; border-top: 1px solid var(--cor-borda);
}
.aparelho-icone { flex: none; color: var(--cor-texto-fraco); display: grid; place-items: center; }
.aparelho-icone svg { width: 16px; height: 16px; }
.aparelho-nome { flex: 1; min-width: 0; font-size: 12.5px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* O horário encolhe antes do nome do aparelho: numa coluna estreita,
   "entrou agora há pouco" empurrava "Windows · Chrome" para fora. */
.linha-aparelho time {
  flex: 0 1 auto; min-width: 0; font-size: 11px; color: var(--cor-texto-fraco);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

.botao-icone.soltar {
  width: 26px; height: 26px; flex: none; border-radius: 50%;
  color: var(--cor-texto-fraco); opacity: 0; transition: opacity .12s, color .12s;
}
.botao-icone.soltar svg { width: 13px; height: 13px; }
.linha-aparelho:hover .botao-icone.soltar,
.botao-icone.soltar:focus-visible { opacity: 1; }
.botao-icone.soltar:hover { color: var(--md-vermelho); }

/* No dedo não existe passar o ponteiro: o botão fica sempre visível. */
@media (pointer: coarse) { .botao-icone.soltar { opacity: 1; } }

/* ------------------------------------------------------------------ *
 * Subtarefas, no modal de criar tarefa.
 *
 * Antes era um textarea de "uma por linha". Simples de escrever e sem
 * lugar para a informação que faltava: QUEM faz cada uma. Uma lista com
 * responsável por linha só existe se cada linha for uma linha de
 * verdade, com os seus próprios controles.
 * ------------------------------------------------------------------ */
.lista-subtarefas { display: flex; flex-direction: column; gap: var(--e-1); margin-bottom: var(--e-2); }
/* Em grade, e não em flex.
   Com flex, o campo de texto encolhia sem piso: numa coluna estreita ele
   ficava com uma letra visível enquanto o seletor de responsável mantinha
   os seus 150px. A grade dá ordem fixa de prioridade — o texto fica com
   tudo o que sobra depois de um seletor de largura conhecida. */
.subtarefa {
  display: grid; grid-template-columns: minmax(96px, 1fr) 138px 30px;
  align-items: center; gap: var(--e-2);
}
.subtarefa .sub-texto, .subtarefa .sub-dono { min-width: 0; }
.subtarefa .sub-remover {
  flex: none; width: 30px; height: 30px; border-radius: 50%;
  font-size: 17px; line-height: 1; color: var(--cor-texto-fraco);
}
.subtarefa .sub-remover:hover { color: var(--md-vermelho); background: var(--cor-cartao-alt); }

/* Numa coluna estreita, o texto sobe para uma linha só dele. A conta é
   da COLUNA, não da tela: o modal já foi largo numa janela larga e o
   campo continuava espremido, porque quem é estreito ali é o formulário.
   `@container` mede o que importa. */
.tarefa-corpo { container-type: inline-size; }
@container (max-width: 330px) {
  .subtarefa { grid-template-columns: 1fr 30px; }
  .subtarefa .sub-texto { grid-column: 1 / -1; }
}
/* Sem suporte a container queries, a tela decide — pior, mas nunca pior
   do que o campo sumir. */
@supports not (container-type: inline-size) {
  @media (max-width: 620px) {
    .subtarefa { grid-template-columns: 1fr 30px; }
    .subtarefa .sub-texto { grid-column: 1 / -1; }
  }
}

/* ------------------------------------------------------------------ *
 * Criar tarefa, no desenho da tela de tarefa do próprio Todoist.
 *
 * À ESQUERDA o que se escreve — nome, descrição, subtarefas — com o nome
 * em corpo grande, porque é o que a pessoa lê depois na lista. À DIREITA
 * o que se escolhe, um campo por linha. Enfileirados numa coluna só, os
 * nove campos viravam um formulário longo em que o nome da tarefa tinha
 * o mesmo peso visual de "Seção".
 *
 * Sem etiqueta, lembrete e local: o chat não alimenta nenhum dos três.
 * ------------------------------------------------------------------ */
/* Mais larga que os outros modais: são duas colunas com um campo de
   escrever em cada linha de subtarefa. Na largura padrão (480px) sobravam
   176px para a esquerda e o campo de texto cabia uma letra. */
.modal:has(.form-tarefa) { width: min(760px, 100%); }

.form-tarefa {
  display: grid; gap: 0 var(--e-5);
  grid-template-columns: minmax(0, 1fr) 232px;
  grid-template-areas: 'corpo lado' 'rodape rodape';
}
/* Coluna em pé: a descrição cresce e ocupa o vão que sobrava entre ela
   e as subtarefas. A direita tem seis campos e fica sempre mais alta que
   a esquerda; sem isto o lado de escrever ficava com um buraco no meio. */
.tarefa-corpo {
  grid-area: corpo; min-width: 0;
  display: flex; flex-direction: column;
}
.tarefa-corpo .tarefa-descricao { flex: 1 1 auto; }
.tarefa-corpo .tarefa-subtarefas { flex: none; }
.tarefa-lado {
  grid-area: lado; min-width: 0;
  display: flex; flex-direction: column; gap: 9px;
  padding-left: var(--e-5); border-left: 1px solid var(--cor-borda);
}
/* Rótulo colado no campo: com a folga padrão, seis campos empilhados
   viravam uma coluna muito mais alta que o lado de escrever. */
.tarefa-lado .campo label { margin-bottom: 3px; }
.tarefa-lado .campo { margin: 0; }
.tarefa-rodape { grid-area: rodape; margin-top: var(--e-4); }

/* O nome é o título da tarefa, não mais um campo: sem caixa, em corpo
   grande, do jeito que ele vai aparecer depois. */
.tarefa-nome {
  width: 100%; font-size: 19px; font-weight: 700; line-height: 1.3;
  background: none; border: 0; margin-bottom: var(--e-1);
  /* Folga à direita: o texto longo corria por baixo da linha divisória
     das colunas e encostava nela sem respiro nenhum. */
  padding: 0 var(--e-3) var(--e-2) 0;
}
.tarefa-nome:focus, .tarefa-nome:focus-visible { outline: none; box-shadow: none; }
.tarefa-descricao {
  width: 100%; min-height: 84px; background: none; border: 0; padding: 0; resize: vertical;
  color: var(--cor-texto-fraco); font-size: 13.5px; line-height: 1.5;
}
.tarefa-descricao:focus, .tarefa-descricao:focus-visible { outline: none; box-shadow: none; }

.tarefa-subtarefas {
  margin-top: var(--e-4); padding-top: var(--e-3);
  border-top: 1px solid var(--cor-borda);
}
.tarefa-subtarefas .rotulo-secao { display: block; margin-bottom: var(--e-2); }

/* "+ Adicionar subtarefa" é um link de ação, não um botão de comando:
   competindo em peso com "Criar tarefa" ele confundia qual era o fim do
   formulário. */
.ligacao-add {
  padding: 4px 0; background: none; border: 0;
  color: var(--md-laranja-texto); font-size: 13px; font-weight: 600;
}
.ligacao-add:hover { text-decoration: underline; }

/* No celular as duas colunas viram uma: 232px de lado direito não cabem
   ao lado de um campo de texto numa tela de 375px. */
@media (max-width: 720px) {
  .form-tarefa {
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas: 'corpo' 'lado' 'rodape';
  }
  .tarefa-lado {
    padding-left: 0; padding-top: var(--e-4); margin-top: var(--e-4);
    border-left: 0; border-top: 1px solid var(--cor-borda);
  }
}

/* ------------------------------------------------------------------ *
 * Escolher várias mensagens para encaminhar de uma vez.
 *
 * Encaminhar um trecho de conversa de cinco mensagens abrindo o seletor
 * de destino cinco vezes é o tipo de tarefa que se faz uma vez e nunca
 * mais — então ou dá para escolher várias, ou o recurso não existe.
 *
 * No modo de escolha o compositor SAI e entra a barra: com os dois na
 * tela a pessoa escreveria uma mensagem que não seria enviada, porque
 * naquele momento o botão de enviar é o de encaminhar.
 * ------------------------------------------------------------------ */
.mensagem.escolhivel { cursor: pointer; padding-left: 34px; }
/* Escolhendo, a bolha INTEIRA é um alvo só — como no WhatsApp: clicar
   na imagem, no áudio, no documento ou num link marca a mensagem.
 *
 * Sem isto a imagem era impossível de marcar. O despacho de clique
 * procura o `data-acao` mais próximo subindo a árvore, e o botão da
 * imagem tem o seu (`ver-arquivo`); ele vencia o `alternar-escolha` da
 * bolha, então clicar abria o visualizador em vez de escolher. A lupa
 * no ponteiro era o sintoma visível disso — o cursor `zoom-in` era do
 * botão que estava engolindo o clique.
 *
 * Desligar o ponteiro nos filhos resolve os dois de uma vez: o evento
 * (e o cursor) passam a ser da bolha. Vale para todo controle de
 * dentro, não só imagem, que é o que evita o mesmo choque com o player
 * de áudio e com o link. */
.mensagem.escolhivel * { pointer-events: none; }
/* A marca fica na margem interna aberta acima — sobre o texto, ela
   cobriria a primeira palavra de toda mensagem curta. */
.mensagem .marca-escolha {
  position: absolute; left: 9px; top: 50%; transform: translateY(-50%);
  width: 18px; height: 18px; border-radius: 50%;
  border: 1.5px solid var(--cor-borda-forte); color: transparent;
  display: grid; place-items: center; transition: background .12s, color .12s, border-color .12s;
}
.mensagem .marca-escolha svg { width: 12px; height: 12px; }
.mensagem.escolhivel:hover .marca-escolha { border-color: var(--md-laranja-borda); }
.mensagem.escolhida .marca-escolha {
  background: var(--md-laranja); border-color: var(--md-laranja); color: var(--md-preto);
}
/* A bolha escolhida ganha contorno, não fundo: trocar o fundo apagaria
   a diferença entre a minha mensagem e a do outro, que é o que orienta
   a leitura enquanto se escolhe. */
.mensagem.escolhida { outline: 2px solid var(--md-laranja); outline-offset: 1px; }
/* Em modo de escolha o menu da bolha sai do caminho: clicar nela é
   marcar, e um menu que abre no meio disso é clique perdido. */
.mensagem.escolhivel .acoes-mensagem { display: none; }

.barra-selecao {
  display: flex; align-items: center; gap: var(--e-3);
  min-height: var(--altura-redator); padding: 9px 10px;
  background: var(--cor-cartao); border-top: 1px solid var(--cor-borda);
  padding-bottom: calc(9px + env(safe-area-inset-bottom, 0px));
}
.barra-selecao strong { flex: 1; min-width: 0; font-size: 13.5px; }
.barra-selecao .primario { flex: none; }

/* ------------------------------------------------------------------ *
 * Marcar pessoas com @.
 *
 * A lista nasce ACIMA do compositor, não abaixo: abaixo ela ficaria
 * atrás do teclado no celular, que é onde mais se usa.
 * ------------------------------------------------------------------ */
.lista-marcar {
  max-height: 232px; overflow-y: auto;
  background: var(--cor-cartao); border-top: 1px solid var(--cor-borda);
  padding: var(--e-1) 0;
}
.pessoa-marcar {
  display: flex; align-items: center; gap: var(--e-2);
  width: 100%; padding: 6px var(--e-3); text-align: left;
  background: none; border: 0; cursor: pointer;
}
/* Destaque no item escolhido pelas setas, igual ao do ponteiro: quem usa
   o teclado precisa enxergar onde está antes de apertar Enter. */
.pessoa-marcar:hover, .pessoa-marcar.ativa { background: var(--cor-cartao-alt); }
.pessoa-marcar .pessoa-corpo { min-width: 0; display: flex; flex-direction: column; }
.pessoa-marcar strong { font-size: 13.5px; }
.pessoa-marcar small { font-size: 11.5px; color: var(--cor-texto-fraco); }
.marcar-todos {
  width: 30px; height: 30px; flex: none; border-radius: 50%;
  display: grid; place-items: center; font-weight: 700;
  background: var(--md-laranja); color: var(--md-preto);
}

/* A marcação dentro da bolha. Peso e cor, sem fundo: numa mensagem que
   marca três pessoas, três retângulos coloridos competiriam com o texto. */
.marcacao { color: var(--md-laranja-texto); font-weight: 700; }
.mensagem.minha .marcacao { color: var(--md-laranja); }

/* Sino cortado na lista: esta conversa está silenciada.
   Discreto de propósito — é um estado permanente, e um ícone forte ao
   lado de cada nome competiria com o que muda ali (hora e não lidas). */
.marca-silencio {
  flex: none; display: inline-grid; place-items: center;
  color: var(--cor-texto-fraco); opacity: .75;
}
.marca-silencio svg { width: 13px; height: 13px; }
.conversa-item.ativo .marca-silencio { opacity: .9; }

/* Alfinete de conversa fixada, na lista. Mesma discrição do sino cortado:
   é estado permanente, não alerta. */
.marca-fixada {
  flex: none; display: inline-grid; place-items: center;
  color: var(--md-laranja-texto); opacity: .9;
}
.marca-fixada svg { width: 13px; height: 13px; }

/* O botão de fixar, no painel de detalhes, carrega o ícone junto do texto. */
.detalhes-secao [data-acao="fixar-conversa"] {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
}
.detalhes-secao [data-acao="fixar-conversa"] svg { width: 14px; height: 14px; }

/* Busca de participantes, ao criar ou editar um grupo.
   São 26 pessoas: sem ela, achar alguém é rolar a lista de olho. */
.topo-participantes {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: var(--e-2); margin-top: var(--e-3);
}
.conta-escolhidos { font-size: 11px; font-weight: 650; color: var(--md-laranja-texto); }
.busca-participante { width: 100%; margin: var(--e-1) 0 var(--e-2); }
/* A linha escondida pela busca sai do fluxo inteira, sem deixar o vão
   da lista no lugar dela. */
.modal-lista .modal-linha[hidden] { display: none !important; }

/* Marca de super admin, na tela da Equipe.
   Fica junto do seletor de papel porque responde à mesma pergunta —
   "o que esta pessoa pode" — mas é privacidade, não hierarquia. */
.marca-super {
  display: inline-flex; align-items: center; gap: 5px; margin-left: var(--e-2);
  font-size: 11px; font-weight: 650; color: var(--cor-texto-fraco); cursor: pointer;
}
.marca-super input { width: auto; accent-color: var(--md-laranja); margin: 0; }
.marca-super:hover { color: var(--cor-texto); }
.chip-super {
  background: var(--cor-realce); color: var(--cor-realce-texto);
  border-color: var(--md-laranja-borda);
}

/* ---------------------- Chamar a atenção (toque) ---------------------- *
 * O toque no meio da conversa. Segue os divisores de dia, não as bolhas:
 * é um acontecimento, não uma frase para ler. A cor de alerta o separa
 * do resto sem precisar de tamanho maior.
 * ---------------------------------------------------------------------- */
.toque { display: flex; justify-content: center; margin: var(--e-3) 0; }
.toque > span {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 5px 12px; border-radius: 999px;
  background: color-mix(in srgb, var(--md-laranja) 16%, transparent);
  border: 1px solid color-mix(in srgb, var(--md-laranja) 38%, transparent);
  color: var(--md-laranja-texto, var(--md-laranja));
  font-size: 12px; font-weight: 600;
}
.toque svg { width: 14px; height: 14px; }
.toque time { font-weight: 400; opacity: .7; margin-left: 4px; }

/* O botão fica na cor de alerta o tempo todo: ele não é "mais uma
   opção" da barra, e quem procura por ele em pressa precisa achá-lo sem
   ler o rótulo. */
.botao-icone.chamar { color: var(--md-laranja-texto, var(--md-laranja)); }
.botao-icone.chamar:hover { background: color-mix(in srgb, var(--md-laranja) 18%, transparent); }

/* A tela tremendo ao receber um toque.
   Só translação, sem mudar tamanho nem cor: o objetivo é ser notado pelo
   canto do olho, não embaralhar a leitura de quem já estava olhando. */
@keyframes tremer-toque {
  0%, 100% { transform: translateX(0); }
  10%, 50%, 90% { transform: translateX(-7px); }
  30%, 70%      { transform: translateX(7px); }
}
.app.tremendo { animation: tremer-toque .55s ease-in-out; }

/* Quem pediu menos movimento no sistema continua recebendo o toque —
   pela vibração, pelo som e pela mensagem na conversa —, mas sem a tela
   sacudindo. */
@media (prefers-reduced-motion: reduce) {
  .app.tremendo { animation: none; }
}

/* ------------- A hora na última linha do texto (como no zap) ---------- *
 * Antes o rodapé era um bloco à parte e ocupava uma linha inteira: "Ok"
 * virava uma bolha de duas linhas, e uma conversa de respostas curtas
 * ficava com o dobro da altura que precisa. É o que mais denuncia um
 * chat feito pela metade.
 *
 * Como funciona: uma cópia invisível do rodapé vai no fim do parágrafo e
 * reserva exatamente a largura dele (ver `markup.js`); a de verdade é
 * posicionada em cima da reserva. Assim o texto quebra sozinho quando
 * não sobra espaço, e a hora desce junto — sem medir nada em JavaScript.
 * --------------------------------------------------------------------- */
.mensagem .rodape.sombra {
  position: static; visibility: hidden;
  display: inline-flex; vertical-align: baseline;
  /* O vão entre a última palavra e a hora também acompanha a letra:
     preso em 8px, com o texto grande a hora encostava no texto. */
  margin: 0 0 0 calc(10px * var(--escala-chat)); flex: none;
  /* Nunca quebra: se a reserva quebrasse de linha, ela deixaria de
     marcar onde a hora cabe e a hora cairia em cima do texto. */
  white-space: nowrap;
}
/* Só quando existe texto E há reserva de espaço. Em bolha de foto ou
   áudio o rodapé continua no fluxo, embaixo da mídia — ali não há última
   linha para dividir. A mensagem apagada também fica de fora: ela tem
   `.texto`, mas é um aviso montado à parte, sem a cópia invisível — sem
   a reserva, a hora cairia em cima do "Mensagem apagada". */
.mensagem:has(> .texto > .rodape.sombra) > .rodape:not(.sombra) {
  position: absolute; margin: 0;
  right: calc(12px * var(--escala-chat));
  bottom: calc(6px * var(--escala-chat));
}

/* ---------------- O canto que fecha a sequência ---------------------- *
 * A bolha já perde o canto de CIMA quando continua a fala anterior
 * (`.emenda`). Faltava o par disso: a última bolha da sequência perde o
 * canto de BAIXO, do lado de quem falou. É o que o bico do WhatsApp faz
 * — dizer onde a fala termina — sem desenhar um triângulo.
 *
 * Triângulo foi descartado de propósito: a bolha tem borda de 1px, e um
 * bico com borda ou fica com emenda visível na diagonal ou precisa de um
 * segundo pseudo-elemento — e o `::before` já é o ícone de arrastar para
 * responder. Canto reto não tem artefato em zoom nenhum.
 *
 * "Última da sequência" é a que NÃO é seguida de uma emenda: serve
 * também para a última da conversa e para a que vem antes de um divisor
 * de dia, sem precisar marcar nada no HTML.
 * --------------------------------------------------------------------- */
.mensagem:not(.minha):not(:has(+ .mensagem.emenda)) { border-bottom-left-radius: 0; }
.mensagem.minha:not(:has(+ .mensagem.emenda)) { border-bottom-right-radius: 0; }

/* A marca de rascunho na lista. Cor de realce e itálico para se separar
   do texto da mensagem sem precisar de ícone: a linha da prévia já é
   estreita, e um ícone ali comeria as primeiras palavras. */
.marca-rascunho {
  color: var(--md-laranja-texto, var(--md-laranja));
  font-style: italic; font-weight: 600;
}

/* ------------------- Mensagem que não conseguiu sair ------------------ *
 * Fica na conversa, no lugar dela, com o motivo e um botão. Some da tela
 * seria pior: quem não visse o aviso passageiro ficaria achando que
 * enviou. A borda tracejada diz "isto ainda não é uma mensagem" sem
 * precisar de texto explicando.
 * --------------------------------------------------------------------- */
.mensagem.falhou { border-style: dashed; opacity: .92; }
.rodape-falha {
  display: flex; align-items: center; gap: var(--e-2);
  justify-content: space-between; flex-wrap: wrap;
  margin-top: calc(6px * var(--escala-chat));
}
.motivo-falha {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: calc(11px * var(--escala-chat));
  color: var(--cor-texto-fraco);
  /* O motivo pode ser uma frase inteira do servidor; sem isto ele
     empurrava o botão para fora da bolha. */
  min-width: 0; overflow-wrap: anywhere;
}
.motivo-falha svg { width: 12px; height: 12px; flex: none; }
.tentar-de-novo {
  flex: none; padding: 4px 10px; border-radius: 999px;
  border: 1px solid var(--md-laranja);
  background: none; color: var(--md-laranja-texto, var(--md-laranja));
  font-size: calc(11.5px * var(--escala-chat)); font-weight: 650; cursor: pointer;
}
.tentar-de-novo:hover { background: color-mix(in srgb, var(--md-laranja) 16%, transparent); }

/* ------------- Mensagem que chegou mas não pôde ser lida -------------- *
 * Mesma aparência da mensagem apagada — borda tracejada, texto em
 * itálico — porque as duas dizem a mesma coisa para quem lê: "existe
 * algo aqui que você não vai ver". Não é erro do sistema nem culpa de
 * ninguém, então nada de vermelho: é um aviso, não um alarme.
 * --------------------------------------------------------------------- */
.mensagem.ilegivel { background: transparent; border-style: dashed; box-shadow: none; }
.mensagem.ilegivel .texto {
  display: flex; align-items: center; gap: 6px;
  color: var(--cor-texto-fraco); font-size: calc(13.5px * var(--escala-chat));
}
.mensagem.ilegivel .texto svg { width: 14px; height: 14px; flex: none; }

/* A lista de atalhos. Tecla à esquerda em largura fixa para as
   descrições alinharem numa coluna só — em larguras diferentes a lista
   vira um ziguezague e ninguém varre com o olho. */
.lista-atalhos { display: flex; flex-direction: column; gap: 2px; margin-top: var(--e-3); }
.linha-atalho {
  display: flex; align-items: center; gap: var(--e-3);
  padding: 7px var(--e-2); border-radius: var(--raio);
}
.linha-atalho:nth-child(odd) { background: var(--cor-cartao-alt); }
.linha-atalho kbd {
  flex: none; width: 120px;
  font: 600 11.5px/1.4 ui-monospace, SFMono-Regular, Menlo, monospace;
  color: var(--cor-texto); text-align: center;
  padding: 3px 6px; border-radius: 5px;
  background: var(--cor-cartao); border: 1px solid var(--cor-borda-forte);
}
.linha-atalho span { font-size: 13px; color: var(--cor-texto-fraco); }

/* ==================== Visualizador em tela cheia ====================== *
 * Fundo preto e nada mais. Qualquer outra cor disputa com a imagem e
 * falseia as cores de quem está aprovando uma arte — que é o uso real
 * disto aqui.
 * ====================================================================== */
.visualizador {
  position: fixed; inset: 0; z-index: 120;
  background: #000;
  display: grid; grid-template-columns: auto 1fr auto; align-items: center;
  /* A barra de cima flutua POR CIMA da imagem, e não acima dela: numa
     tela deitada, reservar uma faixa para o título deixaria a foto
     menor justamente onde há menos altura. */
  overscroll-behavior: contain;
  touch-action: none;
}
.visualizador-topo {
  position: absolute; top: 0; left: 0; right: 0; z-index: 2;
  display: flex; align-items: center; gap: var(--e-2);
  padding: calc(10px + env(safe-area-inset-top, 0px)) var(--e-3) 10px;
  color: #fff;
  /* Degradê em vez de faixa sólida: sobre uma foto clara o texto
     precisa de fundo, mas uma barra opaca corta a imagem em duas. */
  background: linear-gradient(to bottom, rgba(0, 0, 0, .75), transparent);
}
.visualizador-nome {
  flex: 1; min-width: 0; font-size: 14px; font-weight: 600;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.visualizador-conta { font-size: 12px; color: rgba(255, 255, 255, .7); flex: none; }
.visualizador-topo .botao-icone { color: #fff; flex: none; }
.visualizador-topo .botao-icone:hover { background: rgba(255, 255, 255, .16); }

.visualizador-palco {
  grid-column: 1 / -1; grid-row: 1;
  width: 100%; height: 100%;
  display: grid; place-items: center; overflow: hidden;
}
.visualizador-midia {
  max-width: 100vw; max-height: 100vh; max-height: 100dvh;
  display: block; transform-origin: center center;
  /* Sem isto o navegador oferece "arrastar imagem" e o gesto de
     deslizar vira um arrasto de arquivo no meio do caminho. */
  user-select: none; -webkit-user-drag: none;
}
.visualizador.ampliado .visualizador-midia { cursor: grab; }

/* Setas só no computador e só quando há para onde ir. No celular o
   gesto é deslizar, e duas setas fixas cobririam a imagem. */
.visualizador-seta {
  grid-row: 1; z-index: 2; position: relative;
  width: 44px; height: 44px; margin: 0 var(--e-2);
  border-radius: 50%; border: 0; cursor: pointer;
  display: none; place-items: center;
  background: rgba(0, 0, 0, .45); color: #fff;
}
.visualizador-seta:hover { background: rgba(0, 0, 0, .7); }
.visualizador-seta svg { width: 22px; height: 22px; }
.visualizador-seta.seguinte { grid-column: 3; transform: rotate(180deg); }
.visualizador-seta.anterior { grid-column: 1; }
.visualizador.tem-galeria .visualizador-seta { display: grid; }
/* Ampliada, as setas saem: ali o arrasto é para mover a imagem, e um
   botão no caminho do dedo atrapalha. */
.visualizador.ampliado .visualizador-seta { display: none; }
@media (hover: none) { .visualizador-seta { display: none !important; } }

/* O leitor de PDF ocupa a janela quase inteira: era 62% e sobrava
   um terço vazio numa tela onde só o documento importa. */
.previa-pdf { min-height: 60vh; }

/* ------------------- A tira de miniaturas do visualizador ------------- *
 * As mesmas imagens que já estão na conversa — então elas vêm do cache
 * do navegador e a tira não custa download nenhum. É por isso que ela é
 * montada UMA vez: refazer a cada troca jogaria esse cache fora.
 * --------------------------------------------------------------------- */
.visualizador-tira {
  position: absolute; left: 0; right: 0; bottom: 0; z-index: 2;
  display: none; gap: 6px;
  padding: 10px var(--e-3) calc(10px + env(safe-area-inset-bottom, 0px));
  overflow-x: auto; scrollbar-width: none;
  background: linear-gradient(to top, rgba(0, 0, 0, .8), transparent);
}
.visualizador-tira::-webkit-scrollbar { display: none; }
.visualizador.tem-galeria .visualizador-tira { display: flex; }
/* `safe center`, e não `center` puro: com miniaturas demais para caber,
   o centro comum empurra as primeiras para fora do alcance da rolagem e
   elas ficam inacessíveis. O `safe` desiste de centralizar nesse caso. */
.visualizador-tira { justify-content: safe center; }
/* Ampliado, a tira sai: ali o dedo está movendo a imagem e ela só
   atrapalharia a borda de baixo. */
.visualizador.ampliado .visualizador-tira { display: none; }

.visualizador-miniatura {
  flex: none; width: 54px; height: 54px; padding: 0;
  border: 2px solid transparent; border-radius: 6px;
  overflow: hidden; cursor: pointer; background: #222;
  opacity: .55; transition: opacity .12s, border-color .12s;
  position: relative;
}
.visualizador-miniatura img,
.visualizador-miniatura video { width: 100%; height: 100%; object-fit: cover; display: block; }
.visualizador-miniatura:hover { opacity: .85; }
.visualizador-miniatura.ativa { opacity: 1; border-color: var(--md-laranja); }

/* PDF ocupa a janela inteira: quem desenha ali é o leitor do navegador,
   com barra de páginas, zoom e busca — e ele precisa do espaço todo
   para isso valer de alguma coisa. */
.visualizador.documento { background: #1b1b1b; }
.visualizador-documento {
  width: 100%; height: 100%; border: 0; display: block;
  /* Abre abaixo do cabeçalho flutuante, senão a barra de ferramentas do
     leitor nasce escondida atrás do nome do arquivo. */
  padding-top: 52px; box-sizing: border-box; background: #1b1b1b;
}

/* ------------- A hora SOBRE a imagem, como no WhatsApp ---------------- *
 * Numa bolha de foto sem legenda, a hora ficava numa faixa abaixo da
 * imagem: uma tira de bolha sobrando embaixo de cada foto, e a bolha
 * mais alta do que a imagem que ela mostra.
 *
 * Por cima, no canto, ela some do caminho — e a foto passa a ocupar a
 * bolha inteira, que é o que dá a impressão de "a imagem É a mensagem".
 * --------------------------------------------------------------------- */
.mensagem:has(> .abrir-imagem, > .abrir-video):not(:has(> .texto)) {
  /* Recheio mínimo: a moldura em volta da foto é o que mais denuncia
     bolha de mídia mal feita. */
  padding: 3px;
  /* SEM `overflow: hidden`. A barra de ações da mensagem (responder,
     apagar) flutua acima da borda de cima, de propósito — dentro da
     bolha ela cobriria o conteúdo. Recortar aqui a fazia sumir. */
}

/* Altura mínima enquanto a imagem não chegou.
 *
 * Um `<img>` sem arquivo carregado ainda não tem altura: com o recheio
 * de 3px, a bolha inteira virava uma tira de seis pixels — e a mensagem
 * parecia não existir até a foto terminar de baixar. Antes isso não
 * aparecia porque o recheio grande e a hora embaixo davam corpo à bolha
 * de qualquer jeito; ao encolher os dois, o buraco ficou à mostra.
 *
 * Foto carregada é sempre mais alta que isto, então o mínimo não
 * distorce nada — ele só reserva o lugar. */
.mensagem:has(> .abrir-imagem, > .abrir-video) > .abrir-imagem,
.mensagem:has(> .abrir-imagem, > .abrir-video) > .abrir-video {
  min-height: calc(64px * var(--escala-chat));
  min-width: calc(110px * var(--escala-chat));
}
/* Figurinha é pequena por natureza e não deve ser esticada: ela usa o
   mesmo elemento da foto, então a exceção é aqui. */
.mensagem:has(> .abrir-imagem .imagem[alt="Figurinha"]) > .abrir-imagem {
  min-height: 0; min-width: 0;
}
.mensagem:has(> .abrir-imagem, > .abrir-video):not(:has(> .texto)) > .rodape:not(.sombra) {
  position: absolute; right: 8px; bottom: 7px; margin: 0;
  padding: 2px 7px; border-radius: 999px;
  /* Fundo escuro próprio: a hora precisa ser legível tanto sobre um
     comprovante branco quanto sobre uma foto escura. Sombra de texto
     sozinha falha nos dois extremos. */
  background: rgba(0, 0, 0, .45);
  color: rgba(255, 255, 255, .92);
  backdrop-filter: blur(2px);
}
.mensagem:has(> .abrir-imagem, > .abrir-video):not(:has(> .texto)) > .rodape .recibo { color: rgba(255, 255, 255, .92); }
.mensagem:has(> .abrir-imagem, > .abrir-video):not(:has(> .texto)) > .rodape .recibo.vista { color: #7fd4ff; }
/* O autor, em grupo, também sobe para dentro da bolha de foto. */
.mensagem:has(> .abrir-imagem, > .abrir-video):not(:has(> .texto)) > .autor { padding: 4px 6px 2px; }
.mensagem:has(> .abrir-imagem, > .abrir-video) .imagem,
.mensagem:has(> .abrir-imagem, > .abrir-video) .video-previa { border-radius: 4px; }

/* ---------------- Cartão de PDF com a primeira página ----------------- *
 * O nome de um PDF quase nunca diz o que ele é ("S26090431967D.pdf"). A
 * capa diz em um olhar se é o contrato, o comprovante ou a certidão —
 * é por isso que o WhatsApp a mostra, e é o que faltava aqui.
 * --------------------------------------------------------------------- */
.cartao-arquivo.com-capa {
  flex-direction: column; align-items: stretch; gap: 0;
  padding: 3px; overflow: hidden;
}
.capa-pdf {
  display: block; overflow: hidden;
  border-radius: 5px 5px 0 0; background: #fff;
  /* Altura fixa e corte no topo: a primeira página de um documento
     tem o cabeçalho, que é a parte que identifica. Mostrar a página
     inteira encolhida transformaria o texto em cinza sem significado. */
  height: calc(150px * var(--escala-chat));
}
.capa-pdf img { width: 100%; height: 100%; object-fit: cover; object-position: top center; display: block; }
.cartao-arquivo.com-capa .cartao-linha {
  display: flex; align-items: center; gap: calc(10px * var(--escala-chat));
  padding: calc(9px * var(--escala-chat)) calc(8px * var(--escala-chat));
}
/* Sem capa, o cartão continua sendo uma linha só — a estrutura nova não
   pode mudar o que já estava certo para os outros formatos. */
.cartao-arquivo:not(.com-capa) .cartao-linha {
  display: flex; align-items: center; gap: var(--e-2); min-width: 0; flex: 1;
}
.cartao-arquivo:not(.com-capa) { align-items: center; }

/* ------------- O botão de ações da mensagem no celular --------------- *
 * No computador ele nasce invisível e aparece ao passar o mouse, pendurado
 * um pouco ACIMA da bolha — ali não atrapalha nada, porque some assim que
 * o ponteiro sai.
 *
 * No celular não existe "passar o mouse". O que existe é o toque, que dá
 * foco — e o botão ficava aceso, meio para fora da bolha, por cima da
 * mensagem de cima. Um elemento solto no meio da conversa, sem relação
 * visível com nada.
 *
 * Aqui ele entra PARA DENTRO da bolha, no canto, e ganha fundo próprio:
 * dentro de uma foto ele precisa ser legível sobre qualquer imagem.
 * --------------------------------------------------------------------- */
@media (hover: none) {
  .acoes-mensagem { top: 4px; right: 4px; }
  .gatilho-acoes {
    background: rgba(0, 0, 0, .45);
    border-color: rgba(255, 255, 255, .22);
    color: rgba(255, 255, 255, .92);
    backdrop-filter: blur(2px);
  }
  /* Sem foto, a bolha já tem fundo próprio e o botão pode ser discreto. */
  .mensagem:not(:has(> .abrir-imagem, > .abrir-video)) .gatilho-acoes {
    background: var(--cor-cartao); border-color: var(--cor-borda);
    color: var(--cor-texto-fraco); backdrop-filter: none;
  }
  /* SEMPRE visível no celular, e não só depois de um toque.
     Esconder até o toque parece mais limpo e deixa o menu inalcançável:
     no telefone não há como "passar o mouse" para descobrir que ele
     existe, e é por ali que se apaga, fixa e encaminha. Discreto
     resolve; invisível não. */
  .gatilho-acoes { opacity: .55; }
  .gatilho-acoes[aria-expanded='true'] { opacity: 1; }
}

/* ------------------------------------------------------------------ *
 * A lupa da conversa.
 *
 * Fica entre o cabeçalho e as mensagens fixadas, e some quando fechada —
 * não é filtro permanente, é uma ferramenta que se pega e se larga.
 * ------------------------------------------------------------------ */
.barra-busca-conversa {
  display: flex; align-items: center; gap: var(--e-2);
  padding: 7px 10px;
  background: var(--cor-cartao); border-bottom: 1px solid var(--cor-borda);
}
.barra-busca-conversa > svg { width: 16px; height: 16px; color: var(--cor-texto-fraco); flex: none; }
.campo-busca-conversa {
  flex: 1; min-width: 0;
  background: var(--cor-cartao-alt); color: var(--cor-texto);
  border: 1px solid var(--cor-borda); border-radius: var(--raio);
  padding: 6px 10px; font-size: 14px;
}
.campo-busca-conversa:focus-visible { outline-offset: -1px; }
/* Largura fixa para o contador: sem ela, passar de "9 de 12" para
   "10 de 12" empurrava as setas um pixel para o lado a cada salto. */
.contagem-busca {
  flex: none; min-width: 11ch; text-align: right;
  font-size: 12px; color: var(--cor-texto-fraco); font-variant-numeric: tabular-nums;
}
.contagem-busca.vazia { color: var(--md-laranja-borda); }
.barra-busca-conversa .botao-icone { flex: none; }
.barra-busca-conversa .botao-icone[disabled] { opacity: .35; cursor: default; }

@media (max-width: 720px) {
  /* No celular o contador vira só o número: "3/12" cabe, a frase não. */
  .contagem-busca { min-width: 7ch; font-size: 11px; }
}
