/* A folha do painel — o painel com cara de CRM (D2b, 25/09/2026).
   ============================================================================================

   O desenho é o de `docs/superpowers/specs/2026-09-25-painel-visual-crm-design.md`: menu lateral
   fixo (a barra de baixo no celular), Conversas como tela inicial, o funil em colunas com a RÉGUA
   como a única ousadia, e uma base NEUTRA de CRM que recebe a cor de destaque do cliente.

   Arquivo separado por causa da CSP: `style-src 'self'` sem `unsafe-inline`, então nem `<style>`
   nem `style="…"` funcionam nesta tela. O JS nunca escreve estilo: ele copia o estado que o
   servidor devolveu para um `data-*` (ou um número para o `value` de um `<progress>`) e vai embora.
   Quem decide forma, fundo e cor é esta folha.

   ## A cor é do ESTADO

   Âmbar = alguém precisa agir. A cor do cliente (`--marca`) = a equipe no comando, e a ação e a
   seleção da tela. Cinza = a IA atende. Verde = venda, só no funil e nos números. Nada mais é
   colorido. `--accent` (coral) e `--danger` continuam guardados para toque e destrutivo: vermelho
   em "você está no comando" competiria com perigo de verdade.

   ## Os três estados continuam distinguíveis SEM COR

   Triângulo (pediram você), losango (a equipe no comando), pessoa (a IA atende) — a forma mora no
   avatar da linha e do cabeçalho. Mais a POSIÇÃO (o grupo em que a linha cai) e o RÓTULO escrito.
   Quem não enxerga o âmbar — sol na tela da recepção, ou daltonismo — continua lendo os três.

   ## A cor do cliente vem de fora desta folha

   `--marca` e `--on-marca` nascem aqui com a neutra da base, e a `/painel/marca.css` (gerada do
   `[painel] cor` do agente.toml, e carregada DEPOIS desta) os troca pelos do cliente, com os mesmos
   três seletores. Os tons derivados (o fundo da linha selecionada, o do estado "com a equipe") são
   `color-mix` sobre `--marca`: seguem a cor do cliente sem a rota precisar saber que existem.
*/

:root{
  --paper:#ECEFEE;--surface:#FFFFFF;--surface-2:#F5F7F6;--field:#F1F4F3;
  --rule:#D6DDDA;--rule-soft:#E7ECEA;
  --ink:#1C2624;--ink-soft:#56625F;--ink-faint:#5C6865;
  /* A abertura do app instalado (`instalavel.FUNDO_DO_APP`): ela aparece antes de qualquer CSS e
     não sabe o tema de ninguém, então é a tinta escura da base — não ofusca no escuro e não destoa
     no claro. Não pinta nada nesta tela. */
  --dark:#1C2624;
  --accent:#E9695E;
  --danger:#B8432F;--perigo-bg:#FBECE9;
  --st-agente:#7C8A86;
  /* O âmbar do desenho pinta forma e fundo. O TEXTO âmbar é um tom mais fundo: o `#B26B12` sobre o
     próprio fundo âmbar lê a 3,7:1, e "Pediu você" é texto de 12px que precisa ser lido de longe. */
  --st-pediu:#B26B12;--st-pediu-tinta:#955A0D;--st-pediu-bg:#FBEFD9;--st-pediu-soft:#EBCB94;
  --st-pediu-row:#FDF7EC;
  --venda:#2D7A4B;
  --marca:#2F5E57;--on-marca:#FFFFFF;
  --marca-bg:color-mix(in srgb,var(--marca) 9%,var(--surface));
  --st-humano:var(--marca);--st-humano-bg:var(--marca-bg);
  --st-humano-soft:color-mix(in srgb,var(--marca) 32%,var(--surface));
  --linha:#C9D2CF;
  --regua-trilho:#B3BDB9;
  --sw-off:#C9D2CF;--knob:#FFFFFF;--knob-shadow:0 1px 2px rgba(0,0,0,.22);
  --msg-agente:#DDE5E2;--msg-agente-who:#56625F;
  --gravando:#C93A3A;--gravando-bg:#FCEBEB;--gravando-ink:#A12525;
  --visor:rgba(12,15,14,.94);--visor-botao:rgba(255,255,255,.12);
  --visor-botao-hover:rgba(255,255,255,.22);--visor-tinta:#FFFFFF;
  /* A pilha do SISTEMA: a CSP e o funcionamento offline proíbem fonte externa, e fonte do sistema
     é o que abre instantâneo no celular do balcão. O caráter vem dos números tabulares e da escala
     enxuta (12 · 13 · 14 · 15 · 20 · 28), não de uma fonte "com personalidade". */
  --sans:system-ui,"Segoe UI Variable Text","Segoe UI",-apple-system,"SF Pro Text",Roboto,
    "Helvetica Neue",Arial,sans-serif;

  /* Claro é o padrão; os dois blocos escuros abaixo trocam para `dark`. Sem isto o navegador
     repinta os campos de senha e o seletor de data num tema e a folha no outro. */
  color-scheme:light;
}

/* O TEMA ESCURO — duas portas para o MESMO bloco, e o teste cobra que sejam iguais.
   ---------------------------------------------------------------------------------------------
   `[data-tema="escuro"]` é a escolha explícita da pessoa (o `tema.js` põe o atributo no `<html>`
   antes da primeira pintura). A `@media` é o `sistema`: o aparelho está escuro e a pessoa não
   escolheu `claro`. Duas cópias porque CSS não deixa uma regra valer para "atributo OU mídia"; o
   custo é elas divergirem, e é o `test_os_dois_blocos_escuros_sao_o_mesmo` que impede. A `--marca`
   escura daqui é a da neutra, calculada pela mesma conta da `marca.py` (o `test_marca.py` confere). */
:root[data-tema="escuro"]{
  --paper:#0F1413;--surface:#171D1C;--surface-2:#1D2524;--field:#1F2826;
  --rule:#27312E;--rule-soft:#212A28;
  --ink:#E2E8E5;--ink-soft:#A5B1AD;--ink-faint:#8A9894;
  --dark:#0F1413;
  --accent:#EF8176;
  --danger:#E8806F;--perigo-bg:#3A211E;
  --st-agente:#7F8C88;
  --st-pediu:#E3A04A;--st-pediu-tinta:#E3A04A;--st-pediu-bg:#2E2413;--st-pediu-soft:#5A4420;
  --st-pediu-row:#221C12;
  --venda:#57B27B;
  --marca:#53A599;--on-marca:#0F1413;
  --marca-bg:color-mix(in srgb,var(--marca) 16%,var(--surface));
  --st-humano:var(--marca);--st-humano-bg:var(--marca-bg);
  --st-humano-soft:color-mix(in srgb,var(--marca) 42%,var(--surface));
  --linha:#34403D;
  --regua-trilho:#34403D;
  --sw-off:#3A4643;--knob:#E2E8E5;--knob-shadow:0 1px 2px rgba(0,0,0,.5);
  --msg-agente:#222C2A;--msg-agente-who:#A5B1AD;
  --gravando:#E36464;--gravando-bg:#3A1D1D;--gravando-ink:#F4A7A7;
  --visor:rgba(6,8,8,.96);--visor-botao:rgba(255,255,255,.12);
  --visor-botao-hover:rgba(255,255,255,.22);--visor-tinta:#FFFFFF;
  color-scheme:dark;
}
@media (prefers-color-scheme: dark){
  :root:not([data-tema="claro"]){
    --paper:#0F1413;--surface:#171D1C;--surface-2:#1D2524;--field:#1F2826;
    --rule:#27312E;--rule-soft:#212A28;
    --ink:#E2E8E5;--ink-soft:#A5B1AD;--ink-faint:#8A9894;
    --dark:#0F1413;
    --accent:#EF8176;
    --danger:#E8806F;--perigo-bg:#3A211E;
    --st-agente:#7F8C88;
    --st-pediu:#E3A04A;--st-pediu-tinta:#E3A04A;--st-pediu-bg:#2E2413;--st-pediu-soft:#5A4420;
    --st-pediu-row:#221C12;
    --venda:#57B27B;
    --marca:#53A599;--on-marca:#0F1413;
    --marca-bg:color-mix(in srgb,var(--marca) 16%,var(--surface));
    --st-humano:var(--marca);--st-humano-bg:var(--marca-bg);
    --st-humano-soft:color-mix(in srgb,var(--marca) 42%,var(--surface));
    --linha:#34403D;
    --regua-trilho:#34403D;
    --sw-off:#3A4643;--knob:#E2E8E5;--knob-shadow:0 1px 2px rgba(0,0,0,.5);
    --msg-agente:#222C2A;--msg-agente-who:#A5B1AD;
    --gravando:#E36464;--gravando-bg:#3A1D1D;--gravando-ink:#F4A7A7;
    --visor:rgba(6,8,8,.96);--visor-botao:rgba(255,255,255,.12);
    --visor-botao-hover:rgba(255,255,255,.22);--visor-tinta:#FFFFFF;
    color-scheme:dark;
  }
}

*{box-sizing:border-box;margin:0;padding:0}

/* `hidden` é o que o JS liga e desliga, e várias destas caixas têm `display:flex`. Sem o
   `!important` o atributo perde para a regra do componente e a tela mostra tudo de uma vez. */
[hidden]{display:none !important}

html,body{height:100%}
body{
  font-family:var(--sans);font-size:14px;line-height:1.4;
  background:var(--paper);
  color:var(--ink-soft);
  -webkit-font-smoothing:antialiased;
}
button,input,select,textarea{font-family:inherit;font-size:inherit;color:inherit}
h1,h2,h3,h4{font-family:inherit;color:var(--ink);font-weight:600}

/* Foco visível em tudo que recebe foco. Quem atende usa o dedo, mas o teclado é como se navega o
   painel no computador da recepção — e o anel padrão some quando `outline` é reescrito. */
:focus-visible{outline:2px solid var(--marca);outline-offset:2px}

/* O rótulo que só o leitor de tela lê: o ícone sozinho não diz nada para quem não o vê. */
.sr{
  position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;
  clip:rect(0 0 0 0);white-space:nowrap;border:0;
}

/* ------------------------------------------------------------------ as telas de fora */

.centro{
  min-height:100vh;
  min-height:100dvh;
  display:flex;
  align-items:center;
  justify-content:center;
  padding:22px;
}
/* O cartão do login, do convite e da conta. Plano — 1px de divisória, sem sombra — e alinhado à
   esquerda, como o resto da tela: é ferramenta, não página de boas-vindas. */
.card,.acct{
  width:380px;max-width:100%;
  background:var(--surface);border:1px solid var(--rule);border-radius:12px;
  padding:28px;
}
.card .brandicone{display:block;width:44px;height:44px;border-radius:10px;margin-bottom:16px}
.card .brandmark{font-size:20px;font-weight:650;color:var(--ink);letter-spacing:-.01em}
.card .brandsub{font-size:13px;color:var(--ink-soft);margin:2px 0 20px}
.flabel{font-size:13px;color:var(--ink);font-weight:600;margin:16px 0 6px;display:block}
.finp{
  width:100%;height:44px;background:var(--field);border:1px solid var(--rule);border-radius:6px;
  padding:0 12px;color:var(--ink);font-size:14px;
}
.fbtn{
  width:100%;height:44px;border-radius:6px;background:var(--marca);color:var(--on-marca);
  font-weight:650;font-size:14px;border:none;margin-top:24px;cursor:pointer;
}
.fbtn[disabled]{opacity:.6;cursor:default}
.flink{font-size:13px;color:var(--ink-soft);margin-top:18px;line-height:1.5}
.flink.calma{color:var(--ink-faint)}

/* O aviso das telas de fora — erro de login, senha curta, convite queimado. Vazio ele não
   ocupa espaço, para o card não nascer com um buraco. */
.aviso{
  font-size:13px;line-height:1.5;margin-top:16px;
  padding:10px 12px;border-radius:6px;
  background:var(--st-pediu-bg);color:var(--ink);
}
.aviso:empty{display:none}

/* ------------------------------------------------------------------ a conta */

.acct{padding:24px}
.acct h3{font-size:20px;font-weight:650;margin-bottom:8px}
.arow{
  display:flex;align-items:center;gap:12px;width:100%;
  padding:14px 0;border:none;border-top:1px solid var(--rule);
  background:none;font-size:14px;color:var(--ink);text-align:left;cursor:pointer;
}
.acct form + form,.acct .aviso + .arow,.acct form + .aviso{margin-top:8px}
.acct .arow:first-of-type{margin-top:20px}
.arow svg{width:16px;height:16px;flex:none;color:var(--ink-soft)}
.arow.danger{color:var(--danger)}
.arow.danger svg{color:var(--danger)}
.arow .ch{margin-left:auto;color:var(--ink-faint)}

/* O textarea herda o campo, e só precisa da altura e da entrelinha que um input não tem.
   `font:inherit` porque textarea NÃO herda a fonte do documento por padrão: sem esta linha a
   primeira mensagem para uma cliente sai sendo escrita noutra fonte. */
.fta{
  height:auto;padding:10px 12px;line-height:1.45;resize:vertical;min-height:96px;
  font:inherit;font-size:14px;
}

/* ------------------------------------------------------------------ o app: o menu e o cabeçalho */

/* O menu à esquerda e a coluna principal ao lado. No celular (abaixo) a mesma caixa vira coluna, e
   o menu desce para a barra de baixo. */
.app{
  height:100vh;
  height:100dvh;
  display:flex;
  background:var(--paper);
}
.principal{flex:1;min-width:0;min-height:0;display:flex;flex-direction:column}

/* O TRILHO: 76px, ícone e palavra embaixo. O item ativo leva a cor do cliente e uma barra na borda
   esquerda — a seleção é da marca, como a conversa aberta na lista. */
.trilho{
  flex:none;width:76px;display:flex;flex-direction:column;gap:2px;padding:12px 0;
  background:var(--surface);border-right:1px solid var(--rule);
}
.trilho-marca{display:block;width:36px;height:36px;border-radius:8px;margin:2px auto 14px}
.aba{
  position:relative;display:flex;flex-direction:column;align-items:center;gap:4px;
  padding:9px 2px 8px;background:none;border:none;cursor:pointer;
  font-size:12px;font-weight:600;color:var(--ink-soft);
}
.aba svg{width:22px;height:22px;flex:none}
.aba:hover{color:var(--ink);background:var(--surface-2)}
/* O rótulo do item ativo é TINTA: a marca escrita sobre o próprio tingido lia a 3,7:1 no escuro.
   A cor do cliente fica na barra da borda e no ícone — forma, que pede 3:1. */
.aba[aria-current="page"]{color:var(--ink);background:var(--marca-bg)}
.aba[aria-current="page"] svg{color:var(--marca)}
.aba[aria-current="page"]::before{
  content:"";position:absolute;left:0;top:6px;bottom:6px;width:3px;border-radius:0 3px 3px 0;
  background:var(--marca);
}

/* O CABEÇALHO: 56px, o nome da vista à esquerda e o estado do mundo à direita (a chave geral). */
.topbar{
  display:flex;align-items:center;gap:12px;padding:0 20px;
  background:var(--surface);border-bottom:1px solid var(--rule);flex:none;
}
.appttl{font-size:20px;font-weight:650;color:var(--ink);letter-spacing:-.01em;white-space:nowrap}
.topbar .nova{
  display:inline-flex;align-items:center;gap:6px;height:32px;padding:0 12px;
  background:var(--surface);border:1px solid var(--linha);border-radius:6px;cursor:pointer;
  font-size:13px;font-weight:600;color:var(--ink);white-space:nowrap;
}
.topbar .nova:hover{background:var(--surface-2)}
.topbar .nova svg{width:15px;height:15px;flex:none}
.topbar .conta{
  display:inline-flex;align-items:center;gap:6px;background:none;border:none;cursor:pointer;
  font-size:13px;font-weight:600;color:var(--ink-soft);padding:6px;white-space:nowrap;
}
.topbar .conta svg{width:18px;height:18px;flex:none}
/* O nome da conta é o usuário, e usuário cresce ("rafaela.albuquerque"): corta com reticências
   em vez de empurrar o cabeçalho para fora da tela. Abaixo de 768px vai só para o leitor. */
.topbar .conta #conta-rotulo{max-width:16ch;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

/* O botão do tema. Um ícone por escolha no HTML, e a folha mostra o da escolha atual — o JS só
   copia a escolha para `data-escolha`, como faz com `data-estado`. */
.topbar .tema{
  display:flex;align-items:center;background:none;border:none;cursor:pointer;
  color:var(--ink-soft);padding:6px;
}
.topbar .tema svg{width:18px;height:18px;flex:none;display:none}
.tema[data-escolha="sistema"] .mk-sistema,
.tema[data-escolha="escuro"] .mk-escuro,
.tema[data-escolha="claro"] .mk-claro{display:block}

/* A CHAVE GERAL. O `margin-left:auto` é dela: é ela que abre a metade direita do cabeçalho, o
   estado do mundo. Dois `auto` na mesma linha dividiriam a sobra e jogariam a chave para o meio. */
.chave{
  margin-left:auto;display:flex;align-items:center;gap:8px;
  font-size:13px;font-weight:600;color:var(--ink-soft);
  background:none;border:none;cursor:pointer;padding:6px 0;white-space:nowrap;
}
.sw{width:36px;height:20px;border-radius:10px;background:var(--sw-off);position:relative;transition:background .2s;flex:none}
.sw i{position:absolute;top:2px;left:2px;width:16px;height:16px;border-radius:50%;background:var(--knob);box-shadow:var(--knob-shadow);transition:left .2s}
/* `on` é a AGENTE LIGADA, não o botão apertado: o interruptor descreve a agente. Ligado, na cor
   do cliente — é o normal, e o normal não é âmbar: âmbar é a faixa da pausa, quando alguém precisa
   saber que a empresa está muda. */
.sw.on{background:var(--marca)}
.sw.on i{left:18px}
@media (prefers-reduced-motion: reduce){.sw,.sw i{transition:none}}

/* A faixa da chave geral ligada. Fora das colunas: no celular a lista some quando a conversa
   abre, e "a empresa inteira está muda" não pode sumir junto. Faixa de ponta a ponta sob o
   cabeçalho, no âmbar de "alguém precisa saber". */
.pausebanner{
  display:flex;align-items:center;gap:10px;padding:10px 20px;
  background:var(--st-pediu-bg);border-bottom:1px solid var(--st-pediu-soft);color:var(--st-pediu-tinta);
  font-size:13px;font-weight:600;flex:none;
}
.pausebanner svg{width:17px;height:17px;flex:none}
.pausebanner .re{
  margin-left:auto;color:var(--st-pediu-tinta);text-decoration:underline;font-weight:650;
  font-size:13px;background:none;border:none;cursor:pointer;padding:4px;white-space:nowrap;
}

/* O recado de quando um clique NÃO acontece. Existe porque o `_executar_no_painel` devolve 500
   quando o banco está travado: sem esta linha, quem atende aperta a chave geral, nada acontece, e
   ela vai embora achando que desligou a agente. */
.aviso-topo{
  padding:8px 20px;font-size:13px;color:var(--danger);font-weight:600;line-height:1.45;
  background:var(--surface);border-bottom:1px solid var(--rule);flex:none;
}
.aviso-topo:empty{display:none}

.corpo{flex:1;display:flex;min-height:0}
.coluna{display:flex;flex-direction:column;min-height:0;min-width:0;flex:1;background:var(--surface)}

/* No celular só uma coluna aparece por vez, e quem escolhe é `data-vista`. A lista é a raiz:
   ela é o que quem atende abre entre um atendimento e outro. */
.app[data-vista="lista"] .coluna-conversa{display:none}
.app[data-vista="conversa"] .coluna-lista{display:none}

.scroll{flex:1;overflow-y:auto;-webkit-overflow-scrolling:touch;background:var(--surface)}

/* ------------------------------------------------------------------ a linha do dia */

/* "Hoje 2 esperando a equipe, 1 sem resposta, R$ 3.000,00 em vendas" — uma linha de texto no topo
   da lista, com a contagem em peso 650. O painel inteiro mora no Relatório. */
.resumo{
  flex:none;padding:12px 16px;border-bottom:1px solid var(--rule);
  font-size:13px;line-height:1.5;color:var(--ink-soft);
}
.resumo-quando{font-weight:650;color:var(--ink);margin-right:2px}
.resumo-valor{font-weight:650;color:var(--ink);font-variant-numeric:tabular-nums}
.resumo-item[data-pede="sim"] .resumo-valor{color:var(--st-pediu-tinta)}
.resumo-item{white-space:nowrap}

/* ------------------------------------------------------------------ a lista */

/* O grupo, em caixa de frase, com a contagem alinhada à direita. "Precisam de você  2" é a
   informação que quem atende lê de longe, antes de ler qualquer nome. */
.ghead{
  display:flex;align-items:baseline;gap:8px;padding:16px 16px 6px;
  font-size:13px;font-weight:600;color:var(--ink-soft);
}
.ghead .ct{margin-left:auto;font-weight:650;color:var(--ink);font-variant-numeric:tabular-nums}
.ghead .ct:empty{display:none}

/* A LINHA: 60px, sem cartão em volta — a densidade de uma lista de CRM. A informação que se compara
   (a hora) fica numa coluna só, à direita. */
.crow{
  display:flex;gap:12px;align-items:flex-start;width:100%;min-height:60px;padding:10px 16px;
  border:none;border-top:1px solid var(--rule-soft);background:none;text-align:left;cursor:pointer;
}
.ghead + .crow{border-top:none}
.crow:hover{background:var(--surface-2)}

/* O AVATAR é onde a forma mora — e a forma é o que sobrevive à falta de cor. */
.crow .av{
  flex:none;width:28px;height:28px;border-radius:50%;display:grid;place-items:center;margin-top:1px;
  background:var(--surface-2);color:var(--st-agente);
}
.crow .av svg{width:14px;height:14px;display:none}

.crow .bd{flex:1;min-width:0;display:block}
.crow .l1{display:flex;align-items:baseline;gap:8px}
.crow .ph{
  font-size:14px;color:var(--ink);font-weight:600;white-space:nowrap;
  font-variant-numeric:tabular-nums;
}
.crow .tm{margin-left:auto;font-size:12px;color:var(--ink-faint);flex:none;font-variant-numeric:tabular-nums}

/* O NOME DO CONTATO vem primeiro, e o número vira a segunda leitura da linha. Quem encolhe é o
   NOME, nunca o número: o `wa_name` chega com até 60 caracteres, e o telefone é como quem atende
   acha a conversa no WhatsApp do celular. Vazio, o nome some pelo `:empty` e a linha é só o número
   — nada de rótulo "sem nome" ocupando o espaço da informação. */
.crow .nm{
  font-size:14px;color:var(--ink);font-weight:600;
  min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
.crow .nm:empty{display:none}
.crow .nm:not(:empty)+.ph{font-size:12px;font-weight:400;color:var(--ink-faint);flex:none}
.crow .last{
  display:block;font-size:13px;color:var(--ink-soft);margin-top:2px;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
.crow .sl{
  display:none;font-size:12px;margin-top:3px;font-weight:600;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}

/* Os três estados na lista. O normal não ganha realce nenhum — marcar o normal é ruído, e o que
   precisa saltar é o que está esperando por ela. */
.crow[data-estado="agente"] .mk-agente{display:block}

.crow[data-estado="equipe_pediu"]{background:var(--st-pediu-row)}
.crow[data-estado="equipe_pediu"] .av{background:var(--st-pediu-bg);color:var(--st-pediu)}
.crow[data-estado="equipe_pediu"] .mk-pediu{display:block}
.crow[data-estado="equipe_pediu"] .sl{display:block;color:var(--st-pediu-tinta)}
.crow[data-estado="equipe_pediu"] .sl .mo{color:var(--ink);font-weight:400}

.crow[data-estado="humano"] .av{background:var(--st-humano-bg);color:var(--st-humano)}
.crow[data-estado="humano"] .mk-humano{display:block}
.crow[data-estado="humano"] .sl{display:block;color:var(--st-humano)}
.crow[data-estado="humano"] .sl .mo{color:var(--ink-soft);font-weight:400}

/* A resolvida: no fim da lista e mais apagada — é conversa que a equipe fechou, e a fala nova da
   lead a devolve ao grupo de sempre. `data-resolvida` e não um quarto `data-estado`: os estados são
   os três do servidor. */
.crow[data-resolvida="sim"] .sl{display:block;color:var(--ink-faint)}
.crow[data-resolvida="sim"] .last{color:var(--ink-faint)}

/* A conversa aberta: a SELEÇÃO é da cor do cliente — o fundo tingido e a barra na borda. */
.crow[aria-current="true"]{background:var(--marca-bg);box-shadow:inset 3px 0 0 var(--marca)}

/* ------------------------------------------------------------------ o cabeçalho da conversa */

/* No celular a lista some quando a conversa abre, e é ESTE bloco que impede quem atende de
   responder uma escalação achando que é conversa comum: a forma no avatar, o fundo e o rótulo. */
.chead{background:var(--surface);border-bottom:1px solid var(--rule);flex:none}
.chead .ctop{display:flex;align-items:center;gap:12px;padding:10px 16px;min-height:64px}
.chead .back{
  background:none;border:none;cursor:pointer;color:var(--ink-soft);
  display:flex;align-items:center;padding:6px;margin:-6px;
}
.chead .back svg{width:20px;height:20px}
.chead .cav{
  width:32px;height:32px;border-radius:50%;display:grid;place-items:center;
  background:var(--surface-2);color:var(--st-agente);flex:none;
}
.chead .cav svg{width:15px;height:15px;display:none}
.chead .cid{min-width:0}
/* O NOME manda no cabeçalho e o número vira a linha de apoio — a mesma hierarquia da lista. */
.chead .nm{
  font-size:15px;color:var(--ink);font-weight:650;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
.chead .nm:empty{display:none}
.chead .ph{font-size:15px;color:var(--ink);font-weight:650;font-variant-numeric:tabular-nums}
.chead .nm:not(:empty) + .ph{font-size:12px;color:var(--ink-faint);font-weight:400}
.chead .ph:empty::before{content:"—";color:var(--ink-faint)}
/* O estado em frase, e não em pedaços separados por ponto: "Você assumiu há 3 min: relato de
   reação, <agente> calado". Cada pedaço traz a própria pontuação do JS. */
.chead .cstate{font-size:12px;font-weight:600;margin-top:2px;line-height:1.4}
.chead .cstate .mo{color:var(--ink);font-weight:400}
.chead .cstate .sub{color:var(--ink-faint);font-weight:400}
.chead .cstate > span:empty{display:none}
/* RESOLVER, à direita do cabeçalho — com contorno: é botão que muda a conversa, e precisa parecer
   botão. Resolvida, fica apagado: não há o que resolver até a lead escrever. */
.chead .resolver{
  margin-left:auto;flex:none;height:32px;padding:0 12px;border-radius:6px;cursor:pointer;
  border:1px solid var(--linha);background:var(--surface);color:var(--ink);
  font-size:13px;font-weight:600;white-space:nowrap;
}
.chead .resolver:hover{background:var(--surface-2)}
.chead .resolver[data-resolvida="sim"]{color:var(--ink-faint);border-color:var(--rule);cursor:default}

/* Sem conversa aberta não há estado a mostrar — só o travessão do vazio "Escolha uma conversa". */
.chead:not([data-estado]) .cstate{display:none}
.chead:not([data-estado]) .cav{display:none}
.chead:not([data-estado]) .back{display:none}

.chead[data-estado="agente"] .cstate{color:var(--ink-soft)}
.chead[data-estado="agente"] .mk-agente{display:block}

/* O âmbar é plano: o fundo inteiro do cabeçalho, sem degradê — "alguém precisa agir" de ponta a ponta. */
.chead[data-estado="equipe_pediu"]{background:var(--st-pediu-row)}
.chead[data-estado="equipe_pediu"] .cstate{color:var(--st-pediu-tinta)}
.chead[data-estado="equipe_pediu"] .cav{background:var(--st-pediu-bg);color:var(--st-pediu)}
.chead[data-estado="equipe_pediu"] .mk-pediu{display:block}

.chead[data-estado="humano"] .cstate{color:var(--st-humano)}
.chead[data-estado="humano"] .cav{background:var(--st-humano-bg);color:var(--st-humano)}
.chead[data-estado="humano"] .mk-humano{display:block}

/* ------------------------------------------------------------------ a conversa */

/* O histórico sobre o cinza-mineral, os balões por cima: a fala da cliente em branco com
   divisória, a da IA num tom da base, a da equipe na cor do cliente. */
.conv{
  flex:1;padding:16px;overflow-y:auto;
  display:flex;flex-direction:column;gap:8px;background:var(--paper);
}
.datesep{align-self:center;font-size:12px;color:var(--ink-faint);margin:6px 0 2px;font-weight:600}
.msg{
  /* O `80ch` é o teto de leitura: sem moldura, a coluna da conversa cresce com o monitor, e `80%`
     de um monitor de 27" é uma linha atravessando a tela — o olho perde a linha na volta. O limite
     pertence ao TEXTO, então é medido em `ch`. */
  max-width:min(80%,80ch);
  padding:8px 12px;border-radius:8px;font-size:14px;line-height:1.45;
  color:var(--ink);
  /* O texto vem do WhatsApp: link colado sem espaço, "kkkkkk" de trinta letras. Sem isto a
     bolha estica e a conversa inteira rola de lado. */
  overflow-wrap:anywhere;
}
.msg .who{font-size:12px;font-weight:600;margin-bottom:2px}
.msg .txt{white-space:pre-wrap}
.msg .tm{font-size:12px;color:var(--ink-faint);margin-top:4px;text-align:right;font-variant-numeric:tabular-nums}

/* O que impede a foto de estourar a largura da conversa: uma imagem de celular tem 3000px. E
   `max-height` junto, porque foto de celular vem em retrato — só limitar a largura deixa o balão
   com meio metro de altura. `object-fit:contain` evita o corte. */
.msg .midia{
  display:block;max-width:100%;max-height:320px;height:auto;object-fit:contain;
  border-radius:6px;margin-bottom:6px;
}
/* ALTURA EXPLÍCITA, e é obrigatória: o `height:auto` da regra acima colapsa o player de áudio
   para ZERO no Chrome — o elemento existe, o `src` está certo, e quem atende vê um balão de texto sem
   nada para tocar. `auto` funciona para imagem e vídeo, que têm tamanho intrínseco; o controle de
   áudio não tem. */
.msg audio.midia{width:100%;min-width:180px;height:44px;max-height:none}
/* `currentColor` a 12% em vez de um token de campo: o balão da equipe tem fundo na cor do cliente,
   e um cinza de campo ali deixava o nome do arquivo ilegível justamente para quem o anexou.
   Derivado da cor do texto, o contraste acompanha o balão, seja ele qual for. */
.msg .midia-arquivo{
  display:inline-block;padding:8px 12px;border-radius:6px;
  background:color-mix(in srgb, currentColor 12%, transparent);
  border:1px solid color-mix(in srgb, currentColor 22%, transparent);
  color:inherit;text-decoration:none;font-size:13px;word-break:break-all;
}

/* Quem falou decide o lado e o fundo. O JS copia o `autor` que o servidor mandou e não sabe o que
   é cada um — autor desconhecido cai no balão de entrada, que é o lado que não afirma nada sobre a
   empresa. */
.msg[data-autor="usuario"],.msg:not([data-autor]){
  background:var(--surface);border:1px solid var(--rule);border-bottom-left-radius:2px;align-self:flex-start;
}
.msg[data-autor="usuario"] .who{color:var(--ink-faint)}
.msg[data-autor="agente"]{background:var(--msg-agente);border-bottom-right-radius:2px;align-self:flex-end}
.msg[data-autor="agente"] .who{color:var(--msg-agente-who)}
/* A equipe fala na cor do cliente: é a mesma cor de "a equipe no comando". */
.msg[data-autor="operador"]{
  background:var(--marca);color:var(--on-marca);border-bottom-right-radius:2px;align-self:flex-end;
}
.msg[data-autor="operador"] .who,.msg[data-autor="operador"] .tm{color:inherit;opacity:.8}

/* `sistema` são marcadores que o próprio código injeta ("[followup] …"). Virar balão de alguém
   seria pior — quem atende leria como fala da agente. Ficam com a cara do separador de data: um
   bilhete, não uma fala. */
.msg[data-autor="sistema"]{
  align-self:center;max-width:min(90%,80ch);text-align:center;
  background:none;border:1px dashed var(--linha);
  color:var(--ink-faint);font-size:12px;
}
.msg[data-autor="sistema"] .who{color:var(--ink-faint)}
.msg[data-autor="sistema"] .tm{text-align:center}

/* ------------------------------------------------------------------ a barra e o controle */

/* A linha de status abre o bloco de escrever: a divisória fica em cima dela, e não da barra, para
   o status, a confirmação e o campo lerem como uma coisa só. */
.statusline{
  font-size:12px;padding:8px 16px 0;display:flex;align-items:center;gap:6px;flex:none;
  background:var(--surface);border-top:1px solid var(--rule);
}
.statusline svg{width:12px;height:12px;flex:none;display:none}
.statusline > span:empty{display:none}
.statusline[data-estado="agente"]{color:var(--ink-soft)}
.statusline[data-estado="agente"] .mk-relogio{display:block}
.statusline[data-estado="equipe_pediu"]{color:var(--ink-soft)}
.statusline[data-estado="equipe_pediu"] .mk-alerta{display:block;color:var(--st-pediu)}
.statusline[data-estado="equipe_pediu"] .grifo{color:var(--st-pediu-tinta);font-weight:600}
.statusline[data-estado="humano"]{color:var(--st-humano);font-weight:600}
.statusline[data-estado="humano"] .mk-humano{display:block;fill:currentColor}

.bar{
  display:flex;gap:8px;padding:10px 12px 12px;background:var(--surface);
  align-items:center;flex:none;container:barra / inline-size;
}
.field{
  flex:1;min-width:0;height:40px;background:var(--field);border:1px solid var(--rule);border-radius:6px;
  padding:0 12px;color:var(--ink);font-size:14px;
}
/* O mesmo interruptor da barra de cima (`.chave`), no tamanho da barra de escrever: quem atende já
   aprendeu esse gesto para ligar e desligar a agente, e um segundo desenho para a mesma ideia
   seria uma coisa nova para aprender. */
.assinar{
  display:inline-flex;align-items:center;gap:7px;white-space:nowrap;flex:none;
  font-size:13px;color:var(--ink-soft);
  background:none;border:none;cursor:pointer;padding:6px 0;
}
.assinar .sw{width:32px;height:18px}
.assinar .sw i{width:14px;height:14px}
.assinar .sw.on i{left:16px}
/* Com CONTORNO e a palavra junto, não um clipe solto no meio da barra: o ícone sozinho já foi
   procurado duas vezes por quem estava olhando para ele. Botão que manda arquivo para a cliente
   precisa se parecer com botão. Gravar tem a mesma forma: os dois mandam arquivo. */
.anexar,.gravar{
  display:inline-flex;align-items:center;gap:6px;flex:none;
  height:40px;padding:0 12px;border-radius:6px;cursor:pointer;
  border:1px solid var(--linha);background:var(--surface);
  font-size:13px;font-weight:600;color:var(--ink);white-space:nowrap;
}
.anexar:hover,.gravar:hover{background:var(--surface-2)}
.anexar svg,.gravar svg{width:16px;height:16px;flex:none}
/* Gravando, fica vermelho: é o estado em que o microfone está aberto. */
.gravar[aria-pressed="true"]{
  border-color:var(--gravando);background:var(--gravando-bg);color:var(--gravando-ink);
}
/* O ponto que pisca — o sinal universal de "está gravando", e o que evita o microfone aberto
   sem ninguém perceber. `prefers-reduced-motion` desliga a piscada, não o sinal. */
.gravar[aria-pressed="true"] svg{animation:pulsando 1.1s ease-in-out infinite}
@keyframes pulsando{50%{opacity:.35}}
@media (prefers-reduced-motion: reduce){.gravar[aria-pressed="true"] svg{animation:none}}
.gravar-cancelar{
  flex:none;width:34px;height:34px;border-radius:6px;cursor:pointer;
  border:1px solid var(--linha);background:var(--surface);color:var(--ink-faint);
  font-size:13px;line-height:1;
}

/* O VISOR — a mídia em tela cheia, como no WhatsApp Web.
   Fundo quase opaco e não translúcido: foto de pele contra a conversa por trás vira ruído, e
   quem está olhando uma mancha precisa ver a mancha. */
.visor{
  position:fixed;inset:0;z-index:50;display:flex;align-items:center;justify-content:center;
  background:var(--visor);padding:56px 64px;
}
.visor-palco{
  max-width:100%;max-height:100%;display:flex;align-items:center;justify-content:center;
}
.visor-palco img,.visor-palco video{
  max-width:100%;max-height:calc(100vh - 112px);border-radius:6px;display:block;
}
.visor-fechar,.visor-seta,.visor-baixar{
  position:absolute;background:var(--visor-botao);color:var(--visor-tinta);border:none;cursor:pointer;
  border-radius:22px;font-size:15px;line-height:1;text-decoration:none;
}
.visor-fechar{top:14px;right:16px;width:38px;height:38px;font-size:16px}
.visor-baixar{top:14px;left:16px;padding:11px 16px;font-size:13px;font-weight:600}
.visor-seta{top:50%;transform:translateY(-50%);width:42px;height:60px;font-size:30px}
.visor-antes{left:12px}
.visor-depois{right:12px}
.visor-fechar:hover,.visor-seta:hover,.visor-baixar:hover{background:var(--visor-botao-hover)}
/* A foto e o vídeo do balão respondem ao toque — sem isto, o cursor não conta que dá para abrir. */
.msg img.midia,.msg video.midia{cursor:zoom-in}

/* NO CELULAR as palavras saem e ficam os símbolos.
   Medido em 400px de largura: com o rótulo da assinatura, o "Anexar" e o "Assumir", sobravam 32px
   para o campo de escrever — a barra estourava para fora da tela e quem responde pelo telefone não
   tinha onde digitar. O interruptor e o clipe continuam lá, e o campo volta a ser o que manda. */
@media (max-width: 560px){
  .bar{gap:6px}
  .field{min-width:0}
  .assinar #assinar-rotulo{
    position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;
  }
  .anexar{padding:0 10px;gap:0}
  .anexar span{
    position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;
  }
  /* O "Gravar" espremia o campo de volta para 72px em 390px. Parado, fica só o microfone;
     gravando, o rótulo é o cronômetro e continua à vista. */
  .gravar[aria-pressed="false"]{padding:0 10px;gap:0}
  .gravar[aria-pressed="false"] #gravar-rotulo{
    position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;
  }
}
/* NA COLUNA ESTREITA, a mesma troca — medida na PRÓPRIA barra, e não na tela. No computador de
   1280px, com o menu (76px), a lista (340px) e a ficha (300px), a conversa fica com 560px: medido,
   o campo de escrever sobrava com 50px e mostrava "Escr". A largura da tela não diz isso; a da
   barra diz. */
@container barra (max-width:620px){
  .anexar,.gravar[aria-pressed="false"]{padding:0 10px;gap:0}
  .assinar #assinar-rotulo,.anexar span,.gravar[aria-pressed="false"] #gravar-rotulo{
    position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;
  }
}
/* O CONTROLE diz O QUE VAI ACONTECER, e por isso também informa o estado atual: "Assumir" cheio na
   cor do cliente quando a agente está no comando; "Devolver" com contorno quando a equipe está. */
.ctrl{
  height:40px;padding:0 16px;border-radius:6px;font-weight:650;font-size:14px;
  display:inline-flex;align-items:center;gap:7px;white-space:nowrap;flex:none;
  border:1px solid transparent;cursor:pointer;background:var(--marca);color:var(--on-marca);
}
.ctrl svg{width:16px;height:16px;flex:none;display:none}
.ctrl .mk-assumir{display:block}
.ctrl[data-estado="humano"] .mk-assumir{display:none}
.ctrl[data-estado="humano"] .mk-devolver{display:block}

/* DEVOLVER alterna cor e forma JUNTAS: assumir é cheio (a ação que toma a conversa), devolver é o
   contorno (a que solta). Sem isto a única diferença entre tomar e soltar seria a palavra. */
.ctrl[data-estado="humano"]{
  background:var(--surface);border-color:var(--st-humano-soft);color:var(--st-humano);
}

.field[disabled],.ctrl[disabled]{
  cursor:default;
  background:var(--surface-2);
  border-color:transparent;
  color:var(--ink-faint);
}
.ctrl[disabled] svg{opacity:.5}
/* "DURANTE O ENVIO": o botão fica cinza enquanto o pedido está no ar — é o que impede o segundo
   toque de virar um segundo POST, e o que diz que o primeiro ainda não voltou. Os dois glifos
   somem: nenhuma das duas setas descreve "esperando". */
.ctrl.enviando{background:var(--surface-2);color:var(--ink-soft);border-color:transparent}
.ctrl.enviando svg{display:none}
.embreve{font-size:12px;color:var(--ink-faint);padding:0 16px 10px;flex:none;line-height:1.45;background:var(--surface)}
.acct .embreve{padding:8px 0 0;background:none}

/* O segundo controle do estado âmbar: texto sublinhado e não botão cheio, de propósito — a ação
   principal do âmbar continua sendo "Assumir", na barra. Este é o caminho do falso positivo, e
   existe para a conversa não passar por `expira_em = ''` no meio do caminho. */
.naoera{
  align-self:flex-start;margin:6px 16px 0;padding:4px 0;flex:none;
  background:none;border:none;cursor:pointer;text-align:left;
  font-size:13px;font-weight:600;color:var(--st-pediu-tinta);text-decoration:underline;
}

/* A confirmação de devolver uma escalação — a ÚNICA ação desta tela que pergunta antes, porque
   é a única que apaga informação. Inline e não modal: um modal cobriria a conversa, que é
   justamente o que quem atende precisa reler antes de soltar um relato de reação de volta. */
.confirm{
  background:var(--st-pediu-bg);border:1px solid var(--st-pediu-soft);border-radius:8px;
  padding:12px 14px;font-size:13px;line-height:1.5;
  color:var(--ink);margin:8px 12px 0;flex:none;
}
.confirm .mo{font-weight:650}
.confirm .btns{display:flex;gap:8px;margin-top:10px}
.confirm .y{background:var(--marca);color:var(--on-marca);border:none;border-radius:6px;padding:8px 14px;
  font-weight:650;font-size:13px;cursor:pointer}
.confirm .n{background:var(--surface);color:var(--ink);border:1px solid var(--linha);border-radius:6px;
  padding:8px 14px;font-size:13px;cursor:pointer}

/* ------------------------------------------------------------------ os vazios */

.empty{
  flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;
  text-align:center;padding:30px;gap:6px;background:var(--surface);
}
.empty .ic{
  width:48px;height:48px;border-radius:8px;background:var(--surface-2);
  display:grid;place-items:center;color:var(--ink-faint);margin-bottom:8px;
}
.empty .ic svg{width:22px;height:22px}
.empty .ic.perigo{color:var(--danger);background:var(--perigo-bg)}
.empty h3{font-size:15px}
.empty p{font-size:13px;color:var(--ink-soft);max-width:280px;line-height:1.55}
.empty .retry{
  margin-top:12px;height:36px;padding:0 16px;border-radius:6px;background:var(--surface);
  border:1px solid var(--linha);color:var(--ink);font-weight:600;font-size:13px;cursor:pointer;
}
.coluna-conversa > .empty{background:var(--paper)}

/* ------------------------------------------------------------------ o celular: o menu embaixo */

/* Abaixo de 768px o trilho vira a barra de baixo, com os mesmos cinco itens dividindo a largura —
   nada de faixa que rola de lado escondendo o quinto. A barra respeita a barra de gestos do app
   instalado. E a conversa aberta cobre a barra: ela abre por cima, com "voltar", e a barra de
   escrever precisa da altura inteira (o teclado já come metade da tela). */
@media (max-width:767px){
  .app{flex-direction:column}
  .trilho{
    order:2;width:auto;flex-direction:row;gap:0;padding:0;padding-bottom:env(safe-area-inset-bottom);
    border-right:none;border-top:1px solid var(--rule);
  }
  .trilho-marca{display:none}
  .aba{flex:1;min-width:0;padding:8px 2px 7px;gap:3px}
  .aba[aria-current="page"]::before{left:22%;right:22%;top:0;bottom:auto;width:auto;height:3px;border-radius:0 0 3px 3px}
  .app[data-aba="conversas"][data-vista="conversa"] .trilho{display:none}
  .topbar{padding:0 14px}
  .topbar .conta #conta-rotulo{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}
}

/* ------------------------------------------------------------------ computador */

/* Acima daqui, lista e conversa lado a lado — e `data-vista` deixa de mandar. Só a lista tem
   largura fixa; a conversa é "ocupe o que sobrar". Largura fixa de tela inteira era moldura de
   maquete, e quem a viu leu como quebrado. */
@media (min-width:900px){
  .app[data-vista="lista"] .coluna-conversa,
  .app[data-vista="conversa"] .coluna-lista{display:flex}
  .coluna-lista{flex:none;width:340px;border-right:1px solid var(--rule)}
  .coluna-conversa{flex:1}
  .chead .back{display:none}
}

@media (max-width:560px){
  /* 400px de largura medidos: com "Nova conversa" por extenso, a barra do topo estoura e o
     "Sua conta" sai da tela. O sinal de mais sozinho diz o mesmo — é o gesto de toda agenda. */
  .topbar .nova #nova-rotulo{
    position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;
  }
  .topbar .nova{width:32px;padding:0;justify-content:center}
  /* Em 390px o nome da vista, "<agente> ligado", o mais, o tema e a conta não cabem numa linha.
     O nome da vista sai da VISTA — a barra de baixo já diz em qual se está —, mas continua para o
     leitor de tela (`display:none` tirava o `<h1>` da árvore). O espaço entre os itens encolhe. */
  .topbar{gap:6px;padding-left:14px;padding-right:14px}
  .topbar .appttl{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}
  .topbar .chave{order:-1;margin-left:0}
  .topbar .nova{margin-left:auto}
}

/* ------------------------------------------------------------------ a ficha */

/* Faixa recolhível sob o cabeçalho em toda tela abaixo de 1200px, e coluna fixa à direita acima
   disso. Só tokens: a ficha nasce nos dois temas sem uma linha a mais. */
.coluna-conversa{position:relative}
.ficha{background:var(--surface);border-bottom:1px solid var(--rule);flex:none}
.ficha-alternar{
  display:flex;align-items:center;gap:8px;width:100%;padding:10px 16px;
  background:none;border:none;cursor:pointer;text-align:left;
  font-size:13px;font-weight:600;color:var(--ink);
}
.ficha-alternar::after{content:"▾";color:var(--ink-faint)}
.ficha[data-aberta="sim"] .ficha-alternar::after{content:"▴"}
/* A etapa, à direita do "Ficha" — o metadado alinhado à direita, e não pendurado num ponto. */
.ficha-resumo{margin-left:auto;color:var(--ink-soft);font-weight:400}
.ficha-corpo{padding:0 16px 12px;max-height:min(45vh,300px);overflow-y:auto}
.ficha[data-aberta="nao"] .ficha-corpo{display:none}
.ficha-linha{display:flex;gap:8px;align-items:baseline;font-size:13px;color:var(--ink);margin:6px 0}
.ficha-linha .rot{font-size:12px;color:var(--ink-soft);min-width:104px;flex:none}
.ficha-linha b{font-weight:600}
.ficha-titulo{font-size:13px;color:var(--ink);font-weight:600;margin:18px 0 6px}
.ficha-lista .item{display:flex;gap:8px;padding:6px 0;border-top:1px solid var(--rule-soft)}
.ficha-lista dt{font-size:12px;color:var(--ink-soft);min-width:104px;flex:none}
.ficha-lista dd{font-size:13px;color:var(--ink);overflow-wrap:anywhere}
.ficha-vazia{font-size:13px;color:var(--ink-faint);margin-top:8px}
/* O `<select>` do responsável e os campos da ficha: o fundo de campo da casa, nos dois temas. */
.ficha-select,.ficha-campo{
  flex:1;min-width:0;height:32px;background:var(--field);border:1px solid var(--rule);border-radius:6px;
  padding:0 8px;color:var(--ink);font-family:inherit;font-size:13px;
}

@media (min-width:1200px){
  .ficha{
    position:absolute;top:0;right:0;bottom:0;width:300px;overflow-y:auto;
    border-bottom:none;border-left:1px solid var(--rule);padding:12px 0;
  }
  .ficha-alternar{display:none}
  .ficha[data-aberta="nao"] .ficha-corpo{display:block}
  .ficha-corpo{max-height:none;overflow:visible}
  .ficha-corpo > .ficha-linha:first-child{margin-top:0}
  /* Tudo da coluna da conversa abre espaço para a ficha — menos o visor, que é `fixed` e cobre a
     tela inteira: com margem, ele deixaria 300px da conversa descobertos ao lado da foto. */
  .app[data-ficha="sim"] .coluna-conversa > :not(.ficha):not(.visor){margin-right:300px}
}

/* ------------------------------------------------------------------ as vistas */

.vista{flex:1;min-height:0;display:flex;flex-direction:column;background:var(--surface)}
.vista-aviso{margin:12px 20px 0;font-size:13px;color:var(--danger);font-weight:600;line-height:1.45;flex:none}
.vista-vazia{font-size:13px;color:var(--ink-soft);padding:16px 20px;flex:none}
/* O título de seção dentro de uma vista: 15px/600, caixa de frase. */
.secao-titulo{font-size:15px;font-weight:600;color:var(--ink);padding:20px 20px 10px;flex:none}

/* ------------------------------------------------------------------ o quadro do funil */

/* Uma coluna por etapa, lado a lado, sobre o cinza-mineral, e o quadro rola de lado — no celular
   com encaixe por coluna, para o dedo não parar no meio de duas. Cada coluna rola para baixo
   sozinha: a página nunca. */
#vista-funil{background:var(--paper)}
.quadro{
  flex:1;min-height:0;display:flex;gap:16px;padding:16px 20px 20px;
  overflow-x:auto;overflow-y:hidden;scroll-snap-type:x mandatory;scroll-padding:0 20px;
}
.coluna-funil{
  flex:none;width:min(84vw,280px);display:flex;flex-direction:column;min-height:0;
  scroll-snap-align:start;
}

/* A RÉGUA DO FUNIL.
   ---------------------------------------------------------------------------------------------
   O cabeçalho de cada coluna mede a etapa contra a maior coluna do quadro: uma linha fina na cor
   do cliente sobre um trilho claro, cujo comprimento É a contagem (que continua escrita ao lado do
   nome). Lado a lado, as réguas desenham o funil de relance, sem gráfico à parte; o trilho mostra
   a escala inteira. Fina de propósito: a primeira versão, um bloco de 14px, pesava mais que os
   cartões. A ousadia do quadro é a coluna da venda, que troca a régua pelo dinheiro que entrou, em
   28px e no verde de venda. As medidas têm a mesma altura nas duas formas, para os cartões de todas
   as colunas começarem na mesma linha. */
.coluna-topo{padding:0 2px 10px;flex:none}
.coluna-nome{display:flex;align-items:baseline;gap:8px;font-size:14px;font-weight:600;color:var(--ink)}
.coluna-topo .ct{margin-left:auto;font-weight:650;color:var(--ink-soft);font-variant-numeric:tabular-nums}
.coluna-medida{height:34px;display:flex;align-items:center}
.regua{
  -webkit-appearance:none;appearance:none;display:block;width:100%;height:6px;
  border:none;border-radius:3px;background:var(--regua-trilho);color:var(--marca);overflow:hidden;
}
.regua::-webkit-progress-bar{background:var(--regua-trilho);border-radius:3px}
.regua::-webkit-progress-value{background:var(--marca);border-radius:3px}
.regua::-moz-progress-bar{background:var(--marca);border-radius:3px}
.coluna-total{
  font-size:28px;font-weight:650;line-height:1;color:var(--venda);letter-spacing:-.02em;
  font-variant-numeric:tabular-nums;white-space:nowrap;
}
.coluna-funil[data-venda="sim"] .regua{display:none}
.coluna-funil:not([data-venda="sim"]) .coluna-total{display:none}
/* A coluna sem ninguém diz que está vazia: em branco, ela parecia quebrada, ou ainda carregando. */
.coluna-vazia{font-size:13px;color:var(--ink-faint);padding:6px 2px}

.coluna-cartoes{
  flex:1;min-height:0;overflow-y:auto;padding:2px 0 8px;display:flex;flex-direction:column;gap:8px;
}
/* O CARTÃO é plano: 1px de divisória, raio 8, sem sombra. A hierarquia está no cabeçalho da
   coluna, não em cada cartão. À esquerda quem é; à direita o que se compara (valor, desde quando,
   de quem é). */
/* `position:relative` é a âncora do nome do responsável só para leitor de tela (`.sr`, absoluto):
   sem ela, o bloco de conteção dele é a página, e o nome da última coluna — a 1.400px, dentro do
   quadro que rola — alargava o documento inteiro no celular (medido: 1.471px numa tela de 390). */
.cartao{
  position:relative;
  background:var(--surface);border:1px solid var(--rule);border-radius:8px;padding:10px 12px;
  display:grid;grid-template-columns:minmax(0,1fr) auto;column-gap:10px;row-gap:8px;
}
.cartao-abrir{
  grid-column:1;display:flex;flex-direction:column;align-items:flex-start;gap:2px;padding:0;min-width:0;
  background:none;border:none;cursor:pointer;text-align:left;
}
.cartao-abrir .nm{font-size:14px;font-weight:600;color:var(--ink);overflow-wrap:anywhere}
.cartao-abrir .nm:empty{display:none}
.cartao-abrir .ph{font-size:12px;color:var(--ink-faint);font-variant-numeric:tabular-nums}
.cartao-abrir .nm:empty + .ph{font-size:14px;font-weight:600;color:var(--ink)}
.cartao-abrir:hover .nm,.cartao-abrir:hover .nm:empty + .ph{text-decoration:underline}
/* O nome abre a conversa; no teclado, o anel aparece em volta dele — é o mesmo Tab que abre o
   controle de mover do cartão. */
.cartao-abrir:focus-visible{outline:2px solid var(--marca);outline-offset:3px;border-radius:4px}
.cartao-meta{
  grid-column:2;display:flex;flex-direction:column;align-items:flex-end;gap:3px;
  font-size:12px;color:var(--ink-faint);text-align:right;
}
.cartao-meta span:empty{display:none}
.cartao-meta .valor{font-size:13px;color:var(--ink);font-weight:650;font-variant-numeric:tabular-nums}
.cartao-meta .tm{font-variant-numeric:tabular-nums}
.resp-iniciais{
  display:grid;place-items:center;min-width:22px;height:22px;padding:0 4px;border-radius:11px;
  background:var(--surface-2);border:1px solid var(--rule);
  font-size:12px;font-weight:650;color:var(--ink-soft);line-height:1;
}
.cartao-mover{grid-column:1 / -1;display:flex;flex-wrap:wrap;gap:6px}

/* O CONTROLE DE MOVER fica guardado. Com o "Mover para…" e o "Mover" à vista em todo cartão, o
   quadro era uma grade de formulários e a lead ficava por baixo. Ele aparece com o cartão em foco
   (o Tab no nome já o abre, e o `:focus-within` o mantém aberto enquanto se escolhe o destino e se
   digita o valor da venda), com o mouse por cima, ou aberto de propósito pelo botão do celular. */
.cartao .cartao-mover{display:none}
/* O foco que abre é o do NOME e o de dentro do controle — nunca `.cartao:focus-within`: no
   Android tocar num botão lhe dá o foco, e o "Fechar" (dentro do cartão) mantinha o controle
   aberto (revisão final do D2b). */
.cartao:has(.cartao-abrir:focus,.cartao-mover:focus-within) .cartao-mover,.cartao[data-movendo="sim"] .cartao-mover{display:flex}
@media (hover:hover){
  .cartao:hover .cartao-mover{display:flex}
  .cartao:hover{border-color:var(--linha)}
}
/* No celular não há "passar por cima": um botão compacto abre o controle e leva o foco ao
   `<select>`. Só onde não há hover — no computador ele seria um terceiro "Mover" no cartão. */
.cartao-revelar{
  display:none;grid-column:2;justify-self:end;align-self:end;align-items:center;height:28px;padding:0 10px;
  border:1px solid var(--linha);border-radius:6px;background:var(--surface);cursor:pointer;
  font-size:13px;font-weight:600;color:var(--ink);
}
.cartao-revelar[aria-expanded="true"]{color:var(--ink-soft)}
@media (hover:none){
  .cartao-revelar{display:inline-flex}
  /* O botão mora na coluna da direita, sob a hora: o nome ocupa as duas linhas da esquerda, e o
     cartão não cresce uma linha só para o botão. */
  .cartao-abrir{grid-row:1 / span 2}
}
/* O campo que a etapa pede ganha linha própria, com o rótulo à vista: o placeholder some ao
   digitar, e "1.500" sem dizer o que é, num cartão de 280px, é um número solto. */
.cartao-campos{flex-basis:100%;display:flex;flex-direction:column;gap:6px}
.cartao-campos:empty{display:none}
.cartao-campo-rotulo{display:flex;flex-direction:column;gap:4px;font-size:12px;font-weight:600;color:var(--ink-soft)}
.cartao-para,.cartao-campo{
  flex:1;min-width:0;height:30px;background:var(--surface);border:1px solid var(--rule);border-radius:6px;
  padding:0 8px;color:var(--ink);font-family:inherit;font-size:13px;
}
/* Dentro do rótulo (coluna), o `flex:1` do campo zerava a altura: o valor da venda nascia com 18px. */
.cartao-campo-rotulo .cartao-campo{flex:none}
.cartao-ok{
  flex:none;height:30px;background:var(--marca);color:var(--on-marca);border:none;border-radius:6px;
  padding:0 12px;font-size:13px;font-weight:650;cursor:pointer;
}
/* Sem destino escolhido, o botão é só contorno: sessenta "Mover" cheios na cor do cliente, um por
   cartão, gritavam mais que as réguas. Ele acende quando há para onde ir. */
.cartao-ok[disabled]{background:var(--surface);color:var(--ink-faint);box-shadow:inset 0 0 0 1px var(--rule);cursor:default}
#vista-funil .confirm{margin:16px 20px 0}
/* O vazio da vista logo abaixo do topo dela, e não no pé da tela: a grade e a lista ocupam a sobra
   (`flex:1`), e o "nada marcado" ia parar a 700px do botão que escolheu o período. */
#vista-agenda .agenda-topo{order:-2}
#agenda-vazia,#tarefas-vazia{order:-1}
#vista-funil .vista-aviso{margin:12px 20px 0}

/* ------------------------------------------------------------------ a agenda */

/* No celular e no modo "dia", uma lista que rola para baixo, sem os dias vazios. No computador
   largo, a semana vira grade de sete colunas — e aí o dia vazio aparece: "terça livre" é o que a
   equipe procura quando vai oferecer horário. */
.agenda-topo{
  display:flex;align-items:center;flex-wrap:wrap;gap:6px;padding:14px 20px;flex:none;
  border-bottom:1px solid var(--rule);
}
.agenda-nav,.agenda-hoje,.agenda-modo{
  height:32px;padding:0 12px;border-radius:6px;border:1px solid var(--linha);cursor:pointer;
  background:var(--surface);color:var(--ink);font-size:13px;font-weight:600;
}
.agenda-nav:hover,.agenda-hoje:hover,.agenda-modo:hover{background:var(--surface-2)}
.agenda-nav{width:32px;padding:0;font-size:16px;line-height:1}
.agenda-periodo{font-size:15px;font-weight:600;color:var(--ink);margin-left:6px}
.agenda-modo{margin-left:auto}
.agenda{
  flex:1;min-height:0;overflow-y:auto;padding:16px 20px 20px;display:flex;flex-direction:column;gap:16px;
}
.agenda-dia{display:flex;flex-direction:column;gap:6px;min-width:0}
.agenda-dia[data-vazio="sim"]{display:none}
.agenda-dia-topo{font-size:13px;font-weight:600;color:var(--ink-soft);padding-bottom:6px;border-bottom:1px solid var(--rule)}
.agenda-dia-itens{display:flex;flex-direction:column;gap:6px}
/* O horário marcado é "a equipe no comando" do dia: a borda e a hora na cor do cliente. */
.compromisso{
  display:flex;flex-direction:column;align-items:flex-start;gap:2px;width:100%;padding:8px 10px;
  border:1px solid var(--rule);border-left:3px solid var(--marca);border-radius:6px;
  background:var(--surface);cursor:pointer;text-align:left;
}
.compromisso:hover{background:var(--marca-bg)}
.compromisso .hora{font-size:13px;font-weight:650;color:var(--marca);font-variant-numeric:tabular-nums}
.compromisso .nm{font-size:13px;font-weight:600;color:var(--ink);overflow-wrap:anywhere}
.compromisso .servico{font-size:12px;color:var(--ink-soft)}
.compromisso .servico:empty{display:none}
@media (min-width:900px){
  .agenda[data-modo="semana"]{
    display:grid;grid-template-columns:repeat(7,minmax(0,1fr));align-items:start;gap:12px;
  }
  .agenda[data-modo="semana"] .agenda-dia[data-vazio="sim"]{display:flex}
}

/* ------------------------------------------------------------------ as tarefas */

/* A mesma linha na ficha e na lista de hoje: linhas com divisória, sem cartão. A atrasada escreve
   o prazo na cor de perigo — é a única coisa desta lista que alguém precisa ver de longe —, e a
   feita fica riscada até sair. */
.tarefas{list-style:none;display:flex;flex-direction:column;margin:0 0 8px}
.tarefas-de-hoje{flex:1;min-height:0;overflow-y:auto;padding:4px 20px 20px;margin:0}
.tarefa{
  display:flex;align-items:flex-start;gap:10px;padding:10px 0;
  border-top:1px solid var(--rule-soft);
}
.tarefa:first-child{border-top:none}
.tarefa-feita{
  flex:none;width:20px;height:20px;border-radius:4px;border:1.5px solid var(--linha);
  background:var(--surface);cursor:pointer;margin-top:1px;display:grid;place-items:center;padding:0;
}
.tarefa-feita[aria-pressed="true"]{background:var(--marca);border-color:var(--marca)}
.tarefa-feita[aria-pressed="true"]::after{content:"✓";color:var(--on-marca);font-size:12px;line-height:1}
/* No toque, 20px é o dedo errando de tarefa: o alvo cresce para 32px. */
@media (pointer:coarse){
  .tarefa-feita{width:32px;height:32px;border-radius:6px;margin-top:-4px}
}
.tarefa-desfazer{
  flex:none;align-self:center;background:none;border:none;padding:4px 2px;cursor:pointer;
  color:var(--ink-soft);font-size:12px;font-weight:600;text-decoration:underline;
}
.tarefa-corpo{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}
.tarefa-titulo{font-size:14px;color:var(--ink);font-weight:600;overflow-wrap:anywhere}
.tarefa[data-feita="sim"] .tarefa-titulo{text-decoration:line-through;color:var(--ink-faint)}
.tarefa-meta{display:flex;flex-wrap:wrap;gap:4px 12px;font-size:12px;color:var(--ink-faint);font-variant-numeric:tabular-nums}
.tarefa-meta span:empty{display:none}
.tarefa[data-atrasada="sim"] .tarefa-quando{color:var(--danger);font-weight:600}
.tarefa-conversa{
  flex:none;max-width:40%;background:none;border:none;cursor:pointer;padding:0;
  font-size:13px;font-weight:600;color:var(--marca);text-decoration:underline;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
.ficha .tarefas .tarefa{padding:8px 0}
.ficha .tarefa-titulo{font-size:13px}
.tarefa-nova{display:flex;flex-wrap:wrap;gap:6px;margin-top:4px}
.tarefa-nova .ficha-campo{flex:1 1 140px}
.tarefa-ok{
  flex:none;height:32px;background:var(--marca);color:var(--on-marca);border:none;border-radius:6px;
  padding:0 12px;font-size:13px;font-weight:650;cursor:pointer;
}
.tarefa-ok[disabled]{opacity:.5;cursor:default}

/* ------------------------------------------------------------------ o relatório */

/* A vista rola inteira: os números do dia em cima, a tabela por origem embaixo. */
#vista-relatorio{overflow-y:auto}

/* OS NÚMEROS DO DIA: uma grade que quebra linha em QUALQUER largura — nenhum número fica escondido
   atrás de uma rolagem de lado, no dedo ou no mouse. Células com divisória, sem cartão: a leitura
   é de tabela. O valor em 28px é o outro número grande do desenho, junto do total da venda. */
.numeros{flex:none;padding:0 20px}
.numeros-topo{display:flex;align-items:center;gap:8px;margin-bottom:10px}
.numeros-rotulo{font-size:13px;color:var(--ink-soft);font-weight:600}
.numeros-dia,.relatorio-dia{
  height:32px;background:var(--field);border:1px solid var(--rule);border-radius:6px;padding:0 8px;
  color:var(--ink);font-family:inherit;font-size:13px;
}
.numeros-faixa{
  display:grid;grid-template-columns:repeat(auto-fill,minmax(150px,1fr));
  border-top:1px solid var(--rule);border-left:1px solid var(--rule);
}
.numero{
  display:flex;flex-direction:column;gap:4px;padding:14px 16px;min-width:0;
  border-right:1px solid var(--rule);border-bottom:1px solid var(--rule);background:var(--surface);
}
.numero .valor{
  font-size:28px;font-weight:650;line-height:1.1;color:var(--ink);letter-spacing:-.02em;
  font-variant-numeric:tabular-nums;
}
.numero .rotulo{font-size:13px;color:var(--ink-soft)}
.numero .sub{font-size:12px;color:var(--ink-faint);font-variant-numeric:tabular-nums}
.numero .sub:empty{display:none}
/* Os dois que pedem gente ganham a cor do "pediram você" — e só quando há alguém esperando: o JS
   põe `data-pede="sim"` acima de zero. "Esperando a equipe: 0" em âmbar era alarme falso todo dia. */
.numero[data-pede="sim"]{background:var(--st-pediu-bg)}
.numero[data-pede="sim"] .valor{color:var(--st-pediu-tinta)}

/* A tabela rola de lado DENTRO da caixa dela (no celular ela passa da largura da tela), e a página
   nunca. Origem e campanha à esquerda; os números à direita, tabulares, para as casas se alinharem. */
.relatorio-topo{display:flex;align-items:center;flex-wrap:wrap;gap:8px;padding:0 20px 10px;flex:none}
.relatorio-nota{margin:0 20px 8px;font-size:12px;color:var(--ink-faint);flex:none}
.relatorio-ver{
  height:32px;padding:0 14px;border-radius:6px;border:1px solid var(--linha);cursor:pointer;
  background:var(--surface);color:var(--ink);font-size:13px;font-weight:600;
}
.relatorio-rolagem{flex:none;overflow:auto;padding:0 20px 20px}
.relatorio{border-collapse:collapse;width:100%;min-width:560px;font-size:13px;color:var(--ink)}
.relatorio th,.relatorio td{
  padding:8px 10px;text-align:right;white-space:nowrap;border-bottom:1px solid var(--rule-soft);
}
.relatorio td{font-variant-numeric:tabular-nums}
.relatorio th:nth-child(-n+2),.relatorio td:nth-child(-n+2){text-align:left}
.relatorio thead th{font-size:12px;color:var(--ink-soft);font-weight:600;border-bottom:1px solid var(--rule)}
.relatorio tfoot th{font-weight:650;border-bottom:none;border-top:1px solid var(--rule);font-variant-numeric:tabular-nums}

/* ------------------------------------------------------------------ o app instalado no celular */

/* Instalado, o painel ocupa a tela INTEIRA (`viewport-fit=cover`): sem estas margens o cabeçalho
   fica embaixo do entalhe da câmera e a barra de escrever embaixo da barra de gestos — o campo
   existe, mas o dedo não alcança. A barra de baixo do menu tem a dela, no bloco do celular. `env()`
   vale zero no computador e no navegador comum, então nada muda fora do app. */
.app{padding-left:env(safe-area-inset-left);padding-right:env(safe-area-inset-right)}
.topbar{padding-top:env(safe-area-inset-top);height:calc(56px + env(safe-area-inset-top))}
.bar{padding-bottom:calc(12px + env(safe-area-inset-bottom))}
.centro{
  padding:calc(22px + env(safe-area-inset-top)) calc(22px + env(safe-area-inset-right))
    calc(22px + env(safe-area-inset-bottom)) calc(22px + env(safe-area-inset-left));
}
.visor-fechar,.visor-baixar{top:calc(14px + env(safe-area-inset-top))}
