    .precs-wa-wrap{
      display: grid; grid-template-columns: minmax(280px, 380px) minmax(0, 1fr);
      /* (1.1.96) O MESMO 130px ERRADO do card de mailing morava aqui — ver o comentário longo
         em 00-base.css, ao lado de `[data-card-key="mailing"]`. O desconto é header medido (em
         pixel real, por isso antes da divisão) mais os dois respiros do <main> (em unidade de
         autor, por isso depois). Esta cópia paga o mesmo preço: 8px de barra de rolagem na
         escala 1, que virou o caso comum quando a escala passou a depender da tela. */
      gap: 0; min-height: 420px;
      height: calc((100vh - var(--precs-header-h, 74px)) / var(--precs-escala, 1) - var(--space-8) * 2);
      max-width: 1600px; margin: 0 auto;
      background: var(--bg-secondary); border: 1px solid var(--border-color);
      border-radius: var(--radius-card); overflow: hidden;
    }
    /* TELA CHEIA, NÃO CARD (pedido do Pedro, 24/08/2026). Com o modo aberto o `data-wa`
       entra na raiz — mesmo mecanismo do `data-tv` — e o inbox cola no header e nas
       bordas: sem moldura, sem raio, sem folga do <main>, altura até o rodapé da janela.
       A página não rola: quem rola são as colunas, como num app de verdade. O zoom da
       densidade continua valendo (é texto de trabalho, não parede de longe), por isso o
       130px da conta divide pela escala. */
    /* (1.1.38) O MODO CHEIO GANHOU UM DEGRAU DE ESCALA, e só ele.
       "meu monitor é gigante e as coisas estão muito pequenas... acho que na preferência
       Normal deveria estar um pouco maior" (Pedro, 28/08/2026) — e na mesma mensagem ele diz
       que DENTRO da campanha o tamanho está bom. Não é o painel que está pequeno: é esta tela.
       O inbox em tela cheia usa duas colunas numa largura de monitor grande, e o mesmo corpo
       que serve num card de campanha some quando tem 1600px de respiro em volta.
       Então o zoom sobe ~12% APENAS sob `data-wa`, empilhando com a densidade escolhida em vez
       de substituí-la: quem está no compacto continua mais apertado que quem está no normal.
       O painel lateral fica de fora de propósito (ele divide a tela com a campanha, e lá o
       tamanho já está certo). */
    /* O zoom MULTIPLICA a densidade, e chegar aqui custou duas tentativas erradas:
        1. `zoom: 1.12` seco SOBRESCREVE a densidade em vez de compor — a regra do data-fonte
           também é `zoom` no `main`, e quem estivesse no compacto pularia direto para 1,12.
        2. `zoom: calc(var(--precs-escala) * 1.12)` é declaração INVÁLIDA e foi descartada em
           silêncio, então o zoom voltou a ser o da densidade enquanto a conta da altura já
           dividia pelo valor composto. A parede ficou 10,7% curta, e o teste mediu isso como
           89px sobrando no rodapé — o número bate com a proporção, que foi como o diagnóstico
           fechou.
       Por isso os três valores estão escritos por extenso, um por densidade, e a variável
       `--precs-escala-wa` carrega o MESMO número para a conta da altura logo abaixo. Duas
       fontes para a mesma escala divergiriam; aqui elas nascem no mesmo bloco. */
    html[data-wa] main{ padding: 0; max-width: none; gap: 0; }
    html[data-wa][data-fonte="compacto"]    main{ zoom: .81; }
    html[data-wa][data-fonte="normal"]      main{ zoom: .95; }
    html[data-wa][data-fonte="confortavel"] main{ zoom: 1.12; }
    html[data-wa][data-fonte="compacto"]    { --precs-escala-wa: .81; }
    html[data-wa][data-fonte="normal"]      { --precs-escala-wa: .95; }
    html[data-wa][data-fonte="confortavel"] { --precs-escala-wa: 1.12; }
    html[data-wa] body{ overflow: hidden; }
    /* Os tooltips do header (engrenagem, WhatsApp) abrem para BAIXO — por cima da
       parede colada no header. Sem o contexto de empilhamento, a coluna de conversas
       (que vem depois no DOM) pintava por cima do balão e o cortava ao meio: era "a
       barra em cima do tooltip" do relato de 24/08/2026. */
    html[data-wa] header{ position: relative; z-index: 60; }
    html[data-wa] .precs-wa-wrap{
      max-width: none; width: 100%; margin: 0;
      /* A escala do modo cheio (não a da densidade) entra na conta da altura: `100vh` dentro
         de um elemento com zoom ainda é resolvido contra a janela, mas o resultado renderiza
         multiplicado — sem dividir aqui, a parede passa do rodapé por exatamente essa
         proporção e a lista ganha uma rolagem que não deveria existir. */
      height: calc((100vh - var(--precs-header-h, 64px)) / var(--precs-escala-wa, 1));
      min-height: 0; border: 0; border-radius: 0;
    }
    /* A TRANSIÇÃO DO MODO: a parede desliza de baixo com um fade curto, e a volta ao
       discador usa o precsSecFade que toda section já tem. Sem isto a troca era um
       corte seco — "falta uma animação de transição" (24/08/2026). */
    @keyframes precsWaEntra{
      from{ opacity: 0; transform: translateY(14px); }
      to{ opacity: 1; transform: none; }
    }
    html[data-wa] #whatsapp-section.section.active{
      animation: precsWaEntra 260ms var(--ease-1);
    }
    @media (prefers-reduced-motion: reduce){
      html[data-wa] #whatsapp-section.section.active{ animation: none; }
    }

    /* ---- A COLUNA DAS CONVERSAS ---- */
    .precs-wa-lista{ display: flex; flex-direction: column; min-height: 0;
      border-right: 1px solid var(--border-color); background: var(--bg-secondary); }
    /* (1.1.37) DUAS LINHAS, como o WhatsApp Web: controles em cima, busca na largura inteira
       embaixo. Quatro itens numa linha só deixavam a busca com um terço do espaço no painel
       lateral, e era isso que aparecia torto nos prints de 27/08/2026. */
    /* (1.1.39) A ALTURA DOS DOIS CABEÇALHOS VIROU UMA MEDIDA SÓ.
       Este topo (título + busca) é fixo em ~102px; o do chat variava entre 65px e 99px,
       porque a segunda linha dele some quando não há negócio nem etiqueta
       (`.precs-wa-topo-l2:empty`). As duas barras ficavam desalinhadas por 3px num caso e por
       37px no outro — "poderia ter a mesma altura pra ficar as 2 linhas alinhadas"
       (Pedro, 28/08/2026).
       O token abaixo é `min-height` nos dois, e não `height`: os chips do cabeçalho podem
       quebrar linha, e travar a altura os cortaria.

       O VALOR é a altura do cabeçalho do chat COM o bloco do negócio (o mais alto dos dois
       arranjos), e não a do topo da lista: assim a lista cresce um pouco e o chat não precisa
       encolher nada. Medido no navegador, não estimado — a conta de somar padding e conteúdo
       dava 103 e o real é 108, porque o bloco do negócio tem duas linhas de texto. */
    :root{ --precs-wa-topo-h: 108px; }
    .precs-wa-lista-topo{ display: flex; flex-direction: column; gap: var(--space-2);
      padding: var(--space-3); border-bottom: 1px solid var(--border-color); flex: 0 0 auto;
      min-height: var(--precs-wa-topo-h); box-sizing: border-box; justify-content: center; }
    .precs-wa-lista-l1{ display: flex; gap: var(--space-2); align-items: center; min-width: 0; }
    /* O título ocupa o meio e empurra os ícones para a direita, que é o arranjo do WhatsApp
       Web. Vale nos dois enquadramentos: na tela cheia ele fica ao lado do "← discador", no
       painel lateral ele é o único rótulo (o "discador" some por CSS, porque ali a tela do
       discador está atrás e visível). */
    /* (1.1.38) O título deixou de ser texto solto. O ícone da marca vem no verde oficial e a
       palavra ganha o tratamento que a torna reconhecível sem a fonte proprietária do
       logotipo (que não temos licença para redistribuir, e o painel não carrega webfont
       externa por desenho): peso alto, letras juntas, e o "A" do meio em caixa alta — que é o
       traço que o olho identifica na marca. */
    .precs-wa-lista-tit{ flex: 1 1 auto; min-width: 0; display: inline-flex; align-items: center;
      gap: 7px; white-space: nowrap; overflow: hidden; }
    .precs-wa-marca{ flex: 0 0 auto; display: inline-flex; }
    .precs-wa-marca svg{ display: block; }
    .precs-wa-lista-tit b{ font-family: 'Sora', 'Montserrat', sans-serif; font-weight: 700;
      font-size: .95rem; letter-spacing: -.02em; color: var(--text-primary);
      overflow: hidden; text-overflow: ellipsis; }
    .precs-wa-lista-tit em{ font-style: normal; }
    /* (1.1.39) Aqui morava o `.precs-wa-voltar`, a pílula "← discador". Ela chamava
       `precsWaAlternar`, exatamente como o botão do header ao lado da engrenagem, e foi
       removida a pedido do Pedro em 28/08/2026 ("é desnecessário, só ocupa espaço"). A
       compensação está em `#precs-wa-btn.on` e no Esc, que passou a valer em tela cheia. */
    /* A busca com a lupa dentro, como no aplicativo. O wrapper é quem tem a moldura; o input
       fica transparente, senão seriam duas caixas encaixadas. */
    .precs-wa-busca-wrap{ display: flex; align-items: center; gap: var(--space-2);
      background: var(--bg-tertiary); border: 1px solid var(--border-color);
      border-radius: var(--radius-pill); padding: 0 14px; min-width: 0;
      transition: border-color var(--dur-1, .15s) ease, box-shadow var(--dur-1, .15s) ease; }
    .precs-wa-busca-wrap:focus-within{ border-color: var(--precs-gold, #B49552);
      box-shadow: 0 0 0 3px color-mix(in srgb, var(--precs-gold, #B49552) 16%, transparent); }
    .precs-wa-busca-ico{ flex: 0 0 auto; display: inline-flex; color: var(--text-muted); }
    .precs-wa-busca{ flex: 1 1 auto; min-width: 0; background: transparent;
      border: 0; padding: 7px 0; font-family: 'Poppins', sans-serif; font-size: .8rem;
      color: var(--text-primary); }
    .precs-wa-busca::placeholder{ color: var(--text-muted); }
    .precs-wa-busca:focus, .precs-wa-busca:focus-visible{ outline: none; }
    @media (prefers-reduced-motion: reduce){ .precs-wa-busca-wrap{ transition: none; } }

    .precs-wa-conversas{ flex: 1 1 auto; min-height: 0; overflow-y: auto;
      overscroll-behavior: contain; }
    .precs-wa-conv{ display: flex; width: 100%; align-items: center; gap: var(--space-3);
      padding: var(--space-3); background: transparent; border: 0;
      border-bottom: 1px solid var(--border-color); cursor: pointer; text-align: left;
      position: relative;
      transition: background var(--dur-1, .15s) ease; }
    /* (1.1.41) A FITA DA ETIQUETA, e por que ela é um `::after` e não um `box-shadow`.
       A borda esquerda também é da conversa aberta (`inset 3px` dourado, logo abaixo), e um
       segundo `box-shadow` no mesmo elemento seria sobrescrito por aquela regra em vez de
       somar. Pseudoelemento não disputa propriedade com ninguém.
       Sem etiqueta a tira fica transparente e continua ocupando o lugar, então nenhuma linha
       muda de largura por ganhar ou perder etiqueta.

       (1.1.41 · 2ª volta) ELA VOLTOU PARA A ESQUERDA, porque na direita NINGUÉM A VIA.
       "não vi a fita colorida" (Pedro, 31/08/2026) — e não era sutileza de cor: a lista rola,
       então a barra de rolagem fica exatamente sobre os 3px da borda direita e cobre a tira
       inteira. Na esquerda ela é o primeiro pixel que o olho cruza ao varrer a coluna, que é
       para o que ela existe.
       A conversa ABERTA continua com o fio dourado, e agora ele fica POR CIMA: são 4px contra
       3px, então quando os dois coincidem lê-se "aberta", que é o estado mais volátil dos
       dois e o único que muda a cada clique. */
    .precs-wa-conv::after{
      content: ''; position: absolute; left: 0; top: 0; bottom: 0; width: 3px;
      background: var(--fita, transparent); pointer-events: none;
    }
    .precs-wa-conv:hover{ background: var(--bg-tertiary); }
    .precs-wa-conv.aberta{ background: var(--bg-tertiary);
      /* 4px contra os 3px da fita da etiqueta: quando os dois caem no mesmo lugar, o dourado
         de "aberta" vence — é o estado que muda a cada clique, e o que o operador precisa
         achar primeiro. A fita continua visível nas outras linhas da coluna. */
      box-shadow: inset 4px 0 0 var(--precs-gold, #B49552); }
    .precs-wa-conv:focus-visible{ outline: 2px solid var(--precs-gold, #B49552); outline-offset: -2px; }
    /* (1.1.40) O AVATAR GANHOU COR POR PESSOA. Era um tom só de ouro para todos, e numa caixa
       com vinte credores viravam vinte círculos idênticos — a única coisa a distinguir um do
       outro era um par de letras a .82rem. A cor vem por `--av`, escolhida em JS por hash do
       NÚMERO (`precsWaAvatarCor`), dentro da família do ouro. O fundo é uma lavagem e a tinta é
       a cor cheia, o mesmo esquema das etiquetas lavadas — assim o contraste não depende do
       tom sorteado. Sem `--av` (o cabeçalho da conversa) o ouro da marca continua valendo. */
    .precs-wa-av{ flex: 0 0 auto; width: 40px; height: 40px; border-radius: 50%;
      display: inline-flex; align-items: center; justify-content: center;
      background: color-mix(in srgb, var(--av, var(--precs-gold-forma, #B49552)) 42%,
        var(--bg-secondary));
      color: color-mix(in srgb, var(--av, var(--precs-gold-forma, #B49552)) 30%,
        var(--text-primary));
      font-family: 'Montserrat', sans-serif; font-weight: 700; font-size: .82rem; }
    .precs-wa-conv-meio{ flex: 1 1 auto; min-width: 0; display: flex;
      flex-direction: column; gap: 2px; }
    /* (1.1.40) O nome e o selo do negócio são IRMÃOS, não aninhados. O selo morava dentro do
       nome, que corta com reticências — então nome comprido levava o `#148280` embora. */
    .precs-wa-conv-linha1{ display: flex; align-items: center; gap: 0; min-width: 0; }
    .precs-wa-conv-nome{ font-family: 'Montserrat', sans-serif; font-weight: 700;
      font-size: .88rem; color: var(--text-primary); white-space: nowrap;
      overflow: hidden; text-overflow: ellipsis; }
    .precs-wa-conv-previa{ font-size: .76rem; color: var(--text-muted);
      white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
    .precs-wa-conv.naolida .precs-wa-conv-previa{ color: var(--text-secondary); font-weight: 600; }
    /* (1.1.37) A conversa aberta pelo "+" e ainda sem mensagem: prévia em itálico, para a
       linha dizer que é um rascunho sem competir com quem tem conversa de verdade. */
    .precs-wa-conv-previa.rascunho{ font-style: italic; opacity: .85; }
    /* O ícone da prévia herda a cor dela, então escurece quando lida e acende quando não. */
    .precs-wa-previa-ico{ flex: 0 0 auto; vertical-align: -2px; margin-right: 4px; }
    .precs-wa-conv-eu{ font-weight: 700; color: var(--text-muted); }
    .precs-wa-conv.naolida .precs-wa-conv-eu{ color: var(--text-secondary); }
    /* (1.1.41) "Rascunho:" na frente da prévia. Laranja e não ouro: o ouro desta tela quer
       dizer "a PRECS", e aqui a mensagem é "tem trabalho parado", que é aviso. Usa a variante
       `-text` do acento e não o acento cru, pela regra da casa — acento cru é cor de FORMA
       (fio, borda, ponto), e como TEXTO sobre fundo claro ele reprova AA. */
    .precs-wa-conv-rasc{ font-weight: 700;
      color: var(--accent-orange-text, var(--accent-orange)); }
    /* (1.1.40) O "+N" das etiquetas que não couberam. Contorno e não preenchimento: ele conta,
       não classifica — se tivesse cor, disputaria com as três etiquetas de verdade ao lado. */
    .precs-wa-etq-mais{ flex: 0 0 auto; display: inline-flex; align-items: center; min-height: 17px;
      padding: 1px 7px; border-radius: var(--radius-pill);
      font-family: 'Manrope', 'Poppins', sans-serif; font-size: .62rem; font-weight: 700;
      color: var(--text-muted); border: 1px solid var(--border-color); }
    .precs-wa-conv-lado{ flex: 0 0 auto; display: flex; flex-direction: column;
      align-items: flex-end; gap: 4px; }
    .precs-wa-conv-hora{ font-family: 'JetBrains Mono', monospace; font-size: .68rem;
      color: var(--text-muted); }
    /* O ponto de não-lida: OURO, com um pulso curto na chegada. É o único
       movimento da lista, e existe para o canto do olho — quem está no discador
       com o modo aberto em outra janela percebe. */
    @keyframes precsWaPonto{ from{ transform: scale(.4); } to{ transform: scale(1); } }
    /* (1.1.40) `--precs-gold-hi` virou `--precs-gold-forma` pela MESMA razão do botão de
       enviar em 1.1.39: no PRECS Claro aquele token vale #8F7431, um bronze pensado para
       TEXTO. Como fundo de um ponto de 10px ele lê como sujeira na coluna, não como aviso. */
    .precs-wa-ponto{ width: 10px; height: 10px; border-radius: 50%;
      background: var(--precs-gold-forma, #B49552);
      animation: precsWaPonto 240ms var(--ease-1); }
    @media (prefers-reduced-motion: reduce){ .precs-wa-ponto{ animation: none; } }

    /* ---- A COLUNA DO CHAT ---- */
    .precs-wa-chat{ display: flex; flex-direction: column; min-height: 0; min-width: 0;
      background: var(--bg-primary); }
    /* position:relative ancora o popover de vinculo (.precs-wa-vinc-pop) */
    /* (1.1.37) DUAS LINHAS: identidade em cima, contexto embaixo. O motivo está no comentário
       de precsWaPintarTopo (app.js) — nos 440px do painel lateral as duas coisas na mesma
       linha espremiam o etiquetador contra a borda, e a altura do cabeçalho pulava entre
       conversas com e sem negócio. A linha 2 some sozinha quando não tem o que dizer. */
    /* (1.1.41 · 2ª volta) DEIXOU DE SER COLUNA E DEIXOU DE TER ALTURA CRAVADA.
       Coluna era por causa das duas linhas, que viraram uma fila só (ver `.precs-wa-topo-fila`
       logo abaixo): agora é uma linha com a fila à esquerda e o ✕ à direita.
       E a altura foi SOLTA. Ela era `min-height: var(--precs-wa-topo-h)` (108px) para casar com
       a barra da lista, e com o conteúdo numa linha isso deixava ~44px de vazio no topo de toda
       conversa. Soltar devolve esses 44px para a thread, que é onde o operador está olhando. O
       preço é o degrau entre as duas barras no encontro das colunas: decisão do Pedro em
       31/08/2026, com o degrau visto antes de escolher. O `--precs-wa-topo-h` continua valendo
       para o topo da LISTA e para a âncora do painel lateral. */
    /* (1.1.44) O CABEÇALHO ENTROU NA COLUNA DE LEITURA, e o comentário do teto (mais acima)
       registrava que ele e o compositor tinham ficado de fora. O efeito de deixá-los fora é o
       mesmo que motivou o teto: num monitor largo a conversa fica numa faixa de 1000px e a
       barra de cima atravessa a tela inteira, então o nome do credor e o X ficam a centenas de
       pixels da mensagem a que pertencem.
       O RECURSO É PADDING E NÃO `max-width`, de propósito: a barra continua sangrando de ponta
       a ponta (fundo e borda inferior), e só o CONTEÚDO é empurrado para a faixa central — é o
       mesmo princípio do teto ir nos FILHOS da thread e não no contêiner dela.
       O `max()` é o que faz isso desaparecer sozinho onde não cabe: no painel lateral de 440px
       a conta dá negativo e o recuo volta a ser o normal, sem precisar de regra por modo. */
    .precs-wa-chat-topo{ position: relative; display: flex; align-items: center;
      gap: var(--space-3);
      padding: var(--space-3) max(var(--space-4),
               calc((100% - var(--precs-wa-leitura, 1000px)) / 2));
      border-bottom: 1px solid var(--border-color);
      background: var(--bg-secondary); flex: 0 0 auto; box-sizing: border-box; }
    /* (1.1.41 · 2ª volta) UMA FILA SÓ, e a quebra decidida pela LARGURA e não por um `if`.
       Em tela cheia cabe tudo lado a lado (nome, etiquetar, lembrar, negócio, etiquetas) e a
       segunda linha não acontece; no painel de 440px, ou com muitas etiquetas, ela quebra
       sozinha e o resultado é o layout de duas linhas de antes.
       `align-items: center` e não `baseline`: os itens têm alturas diferentes (avatar de 40px,
       botões de 26px, chips de 19px) e alinhar por linha de base deixaria o avatar pendurado. */
    .precs-wa-topo-fila{ flex: 1 1 auto; min-width: 0;
      display: flex; align-items: center; flex-wrap: wrap;
      gap: var(--space-2) var(--space-3); }
    /* O contêiner de chips existe SEMPRE, mesmo vazio (`precsWaTopoChips` escreve dentro dele
       sem repintar o cabeçalho), então quem some é ele por atributo — nunca a fila. */
    .precs-wa-topo-etqs[hidden]{ display: none; }
    .precs-wa-topo-meio{ display: flex; flex-direction: column; gap: 1px; min-width: 0;
      flex: 0 1 auto; }
    /* (1.1.40) CORTA COM RETICÊNCIAS, como a linha da lista já fazia (`.precs-wa-conv-nome`).
       Sem isto, nome comprido de credor quebrava em duas ou três linhas e esticava o
       cabeçalho — nos 440px do painel sobram ~227px para nome e telefone. */
    .precs-wa-topo-nome{ font-family: 'Montserrat', sans-serif; font-weight: 700;
      font-size: .95rem; color: var(--text-primary);
      white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
    .precs-wa-topo-fone{ font-family: 'JetBrains Mono', monospace; font-size: .72rem;
      color: var(--text-muted);
      white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

    /* (1.1.37) A TEXTURA DO FUNDO. O WhatsApp tem o rabisco atrás das bolhas, e ele faz mais
       do que enfeitar: separa o plano da conversa do plano da interface, e é metade do
       "parece o WhatsApp". Aqui o desenho é nosso (losangos do monograma), em SVG embutido
       como data: URI — nenhum arquivo novo, nenhuma requisição, nada de CDN.

       A TINTA VEM DE `currentColor`, e é por isso que ela atravessa os cinco temas sem uma
       linha por tema: a thread herda `--text-primary`, e o `mask` pinta o padrão com essa
       cor a 3,5% de opacidade. No tema de CONTRASTE ela some por completo — quem escolheu
       contraste não pediu textura atrás do texto. */
    /* ======================================================================
       (1.1.40) O TETO DA COLUNA DE LEITURA.
       A base do `.precs-wa-wrap` tinha `max-width: 1600px`, mas `html[data-wa]` o anula — e
       como `data-wa` é o único estado em que a section fica ativa, aquele teto era caminho
       morto. Sem substituto, a thread absorvia 100% do excedente: num monitor de 2560px ela
       recebia 2315px e, com o balão limitado a `min(62ch, 78%)`, a conversa virava duas fitas
       de ~500px encostadas em bordas opostas, com 1300px de papel de parede vazio no meio — e
       o separador de dia flutuando sozinho a 700px das duas.
       O teto vai nos FILHOS e não no contêiner: a barra de rolagem continua na borda da
       coluna (é onde a mão procura) e o papel de parede segue de ponta a ponta, que é o que
       impede a tela de parecer estreita. Cabeçalho e compositor não são tocados. */
    :root{ --precs-wa-leitura: 1000px; }
    .precs-wa-thread{ flex: 1 1 auto; min-height: 0; overflow-y: auto;
      overscroll-behavior: contain; padding: var(--space-4);
      display: flex; flex-direction: column; align-items: center; gap: var(--space-2); }
    .precs-wa-thread > *{ width: 100%; max-width: var(--precs-wa-leitura, 1000px); }
    /* ====================================================================
       (1.1.38) O PAPEL DE PAREDE DA CONVERSA, e por que ele deixou de ser um só.
       "esse fundo totalmente preto nas conversas é meio ruim" (Pedro, 28/08/2026). Eram duas
       queixas dentro de uma: o padrão era discreto demais para se ver, e o FUNDO por baixo
       dele era `--bg-primary` puro — no tema PRECS isso é quase preto chapado, que num painel
       de conversa longa cansa.
       As duas coisas foram separadas. `--precs-wa-papel-fundo` é a superfície (um gradiente
       suave que tira o chapado) e `--precs-wa-textura` é o desenho por cima. Trocar de papel
       troca as duas, e quem escolhe é o operador (`data-wa-papel` na raiz, salvo nas
       preferências por ramal, como tema e densidade).
       ==================================================================== */
    /* (1.1.38 · 2ª volta) O PAPEL MUDOU DE DONO, E ISSO ERA UM DEFEITO DE VERDADE.
       "por algum motivo cortou pela metade, ele fica só na primeira parte" (Pedro,
       28/08/2026). O `::before` era filho de `.precs-wa-thread`, que é justamente o elemento
       que ROLA: um `position:absolute; inset:0` ali cobre o retângulo VISÍVEL e depois sobe
       junto com o conteúdo, então da segunda tela em diante não havia mais papel nenhum —
       aparecia como um fundo que "acaba no meio".
       Agora o papel mora em `.precs-wa-chat`, que é o pai que NÃO rola. Ele cobre a coluna
       inteira, e o cabeçalho e o compositor continuam por cima porque têm fundo próprio
       (`--bg-secondary`). A thread fica transparente para deixá-lo aparecer. */
    .precs-wa-chat{ position: relative; isolation: isolate;
      background: var(--precs-wa-papel-fundo, var(--bg-primary)); }
    .precs-wa-chat::before{
      content: ''; position: absolute; inset: 0; z-index: -1; pointer-events: none;
      color: var(--text-primary);
      opacity: var(--precs-wa-papel-forca, .05); background: currentColor;
      -webkit-mask-image: var(--precs-wa-textura); mask-image: var(--precs-wa-textura);
      -webkit-mask-size: var(--precs-wa-papel-escala, 78px) var(--precs-wa-papel-escala, 78px);
      mask-size: var(--precs-wa-papel-escala, 78px) var(--precs-wa-papel-escala, 78px);
      -webkit-mask-repeat: repeat; mask-repeat: repeat; }
    .precs-wa-thread{ background: transparent; }
    /* Contraste continua sem textura: quem escolheu contraste não pediu desenho atrás do
       texto. O fundo liso vale para ele, sempre.

       (1.1.40) E AGORA VALE MESMO. `html[data-theme="contraste"]` e `html[data-wa-papel="…"]`
       têm especificidade IDÊNTICA (0,1,1), e os blocos de papel vêm depois na folha — então
       eles venciam. Contraste + Constelação recebia de volta o gradiente azul e dourado que
       este bloco existe para zerar; a textura sumia (aquela regra é de seletor composto e mais
       específica) mas o fundo colorido ficava, que é o pior dos dois mundos: o tema de
       acessibilidade com cor decorativa e sem o desenho que a justificaria.
       O `[data-wa-papel]` no seletor sobe a especificidade para 0,2,1 e o empate acaba —
       melhor do que depender de ordem, que a próxima edição do arquivo desfaz sem avisar. */
    /* (1.1.41 · 2ª volta) O CONTRASTE DEIXOU DE APAGAR O PAPEL DA CONVERSA.
       A regra existia desde a 1.1.38 com o argumento "quem escolheu contraste não pediu
       desenho atrás do texto". O argumento não se sustenta: o tema do DISCADOR e o fundo da
       CONVERSA são duas escolhas diferentes, feitas em dois lugares diferentes do mesmo modal,
       e uma anular a outra deixava as quatro miniaturas idênticas e o clique sem efeito —
       "no contraste o timbrado sumir não faz sentido" (Pedro, 31/08/2026).
       Quem não quer desenho tem o papel LISO, que é exatamente essa escolha e está a um
       clique. O que fica é a conta de contraste do TEXTO, que os testes medem: a textura vale
       de .05 a .11 de opacidade atrás de balões que têm fundo próprio e opaco, então ela não
       entra no par medido. O aviso do modal saiu junto. */
    /* (1.1.41) E a MINIATURA da galeria segue o contraste junto, senão a prévia oferece um
       desenho que a tela não vai entregar. Precisa ser regra própria: o token do papel está
       declarado no PRÓPRIO `.precs-papel-mini[data-papel=…]`, e valor no elemento vence
       qualquer coisa herdada do `html`. */


    /* (1.1.41) CADA PAPEL SE DECLARA DUAS VEZES, E ISSO NAO E REPETICAO.
       A galeria do modal de Preferencias mostra uma MINIATURA de verdade de cada papel: o
       mesmo gradiente e a mesma textura que vao para tras das mensagens, em 168x58. Para
       isso a miniatura precisa dos quatro tokens (`--precs-wa-papel-fundo`, `--precs-wa-
       textura`, `--precs-wa-papel-forca`, `--precs-wa-papel-escala`), que ate a 1.1.40 so
       existiam em `html` e `html[data-wa-papel="..."]`.
       A saida foi acrescentar `.precs-papel-mini[data-papel="..."]` ao MESMO bloco, em vez
       de copiar os valores para um bloco proprio da miniatura. Copia divergiria na primeira
       vez que alguem afinasse a forca de um papel e esquecesse a previa: a galeria passaria
       a mentir sobre o que o operador vai receber, que e exatamente o que ela existe para
       nao fazer.

       PAPEL NOVO, ENTAO, SAO TRES COISAS E MAIS NENHUMA: uma entrada em `PRECS_PAPEIS`
       (index.html), um bloco de tokens com os dois seletores aqui, e um card na grade. */
    /* ---- PAPEL 1 (padrão): PRECS. O losango de quatro pontas do "✦" da marca, em três
       tamanhos, com pontinhos entre eles — o mesmo vocabulário do selo que fecha a logo. */
    html,
    .precs-papel-mini[data-papel="precs"],
    .precs-supconv-palco[data-papel="precs"]{
      --precs-wa-papel-fundo:
        radial-gradient(120% 80% at 50% 0%, color-mix(in srgb, var(--precs-gold, #B49552) 5%, transparent), transparent 60%),
        linear-gradient(180deg, color-mix(in srgb, var(--text-primary) 4%, var(--bg-primary)), var(--bg-primary) 70%);
      --precs-wa-papel-forca: .06;
      --precs-wa-papel-escala: 92px;
      --precs-wa-textura: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='92' height='92' viewBox='0 0 92 92'%3E%3Cg fill='%23000'%3E%3Cpath d='M23 10c1.6 5.4 3.6 7.4 9 9-5.4 1.6-7.4 3.6-9 9-1.6-5.4-3.6-7.4-9-9 5.4-1.6 7.4-3.6 9-9z'/%3E%3Cpath d='M69 56c1.6 5.4 3.6 7.4 9 9-5.4 1.6-7.4 3.6-9 9-1.6-5.4-3.6-7.4-9-9 5.4-1.6 7.4-3.6 9-9z'/%3E%3Cpath d='M69 14c1 3.2 2.2 4.4 5.4 5.4-3.2 1-4.4 2.2-5.4 5.4-1-3.2-2.2-4.4-5.4-5.4 3.2-1 4.4-2.2 5.4-5.4z'/%3E%3Cpath d='M23 60c1 3.2 2.2 4.4 5.4 5.4-3.2 1-4.4 2.2-5.4 5.4-1-3.2-2.2-4.4-5.4-5.4 3.2-1 4.4-2.2 5.4-5.4z'/%3E%3Ccircle cx='46' cy='37' r='1.6'/%3E%3Ccircle cx='46' cy='83' r='1.6'/%3E%3Ccircle cx='0' cy='37' r='1.6'/%3E%3Ccircle cx='92' cy='37' r='1.6'/%3E%3C/g%3E%3C/svg%3E");
    }

    /* ---- PAPEL 2: CONSTELAÇÃO. Estrelas menores, mais espalhadas, ligadas por linhas finas.
       Mais silencioso que o primeiro: serve para quem passa o dia lendo texto na thread. */
    /* (1.1.38 · 2ª volta) "o constelação nem tanto, pode tentar ser criativo nesse novamente."
       A primeira versão era uma malha de linhas que, repetida, virava favo de mel: o olho lia
       a GRADE do ladrilho em vez das estrelas. Dois erros ali — as linhas eram longas demais
       (atravessavam o quadro e emendavam com a cópia ao lado) e tudo tinha o mesmo peso.
       Esta é uma noite de verdade: poeira de estrelas em três tamanhos, DUAS constelações
       curtas que se fecham dentro do quadro (não emendam), e um cometa com rastro atravessando
       o campo. O ladrilho é maior (200px) para o padrão levar mais tempo até se repetir. */
    html[data-wa-papel="constelacao"],
    .precs-papel-mini[data-papel="constelacao"],
    .precs-supconv-palco[data-papel="constelacao"]{
      --precs-wa-papel-fundo:
        radial-gradient(90% 60% at 78% 8%, color-mix(in srgb, var(--accent-blue, #5E6AD2) 9%, transparent), transparent 60%),
        radial-gradient(70% 50% at 15% 95%, color-mix(in srgb, var(--precs-gold, #B49552) 6%, transparent), transparent 60%),
        linear-gradient(165deg, color-mix(in srgb, var(--text-primary) 6%, var(--bg-primary)), var(--bg-primary) 62%);
      --precs-wa-papel-forca: .08;
      --precs-wa-papel-escala: 200px;
      --precs-wa-textura: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='200' viewBox='0 0 200 200'%3E%3Cg stroke='%23000' fill='none' stroke-linecap='round'%3E%3Cg stroke-width='.8' opacity='.5'%3E%3Cpath d='M34 40 L58 30 L74 52 L58 30 L52 8'/%3E%3Cpath d='M126 132 L150 122 L166 144 L150 122 L144 100'/%3E%3C/g%3E%3Cg stroke-width='1' opacity='.35'%3E%3Cpath d='M150 44 q18 10 34 32'/%3E%3C/g%3E%3C/g%3E%3Cg fill='%23000'%3E%3Cpath d='M34 34c1.1 4 2.2 5.1 6.2 6.2-4 1.1-5.1 2.2-6.2 6.2-1.1-4-2.2-5.1-6.2-6.2 4-1.1 5.1-2.2 6.2-6.2z'/%3E%3Cpath d='M126 126c1.1 4 2.2 5.1 6.2 6.2-4 1.1-5.1 2.2-6.2 6.2-1.1-4-2.2-5.1-6.2-6.2 4-1.1 5.1-2.2 6.2-6.2z'/%3E%3Cpath d='M150 40c.8 3 1.6 3.8 4.6 4.6-3 .8-3.8 1.6-4.6 4.6-.8-3-1.6-3.8-4.6-4.6 3-.8 3.8-1.6 4.6-4.6z'/%3E%3Cpath d='M74 47c.7 2.6 1.4 3.3 4 4-2.6.7-3.3 1.4-4 4-.7-2.6-1.4-3.3-4-4 2.6-.7 3.3-1.4 4-4z'/%3E%3Ccircle cx='58' cy='30' r='2.1'/%3E%3Ccircle cx='52' cy='8' r='1.6'/%3E%3Ccircle cx='150' cy='122' r='2.1'/%3E%3Ccircle cx='166' cy='144' r='1.8'/%3E%3Ccircle cx='144' cy='100' r='1.5'/%3E%3Ccircle cx='184' cy='76' r='2.4'/%3E%3Ccircle cx='16' cy='96' r='1.5'/%3E%3Ccircle cx='96' cy='176' r='1.5'/%3E%3Ccircle cx='188' cy='188' r='1.2'/%3E%3Ccircle cx='8' cy='166' r='1.2'/%3E%3Ccircle cx='104' cy='84' r='1.2'/%3E%3Ccircle cx='176' cy='12' r='1'/%3E%3Ccircle cx='68' cy='112' r='1'/%3E%3Ccircle cx='118' cy='60' r='1'/%3E%3Ccircle cx='24' cy='140' r='.9'/%3E%3Ccircle cx='88' cy='140' r='.9'/%3E%3Ccircle cx='158' cy='176' r='.9'/%3E%3Ccircle cx='198' cy='118' r='.9'/%3E%3Ccircle cx='2' cy='58' r='.9'/%3E%3C/g%3E%3C/svg%3E");
    }

    /* ---- PAPEL 3: LISO. Sem desenho, e ainda assim sem o preto chapado — o gradiente fica.
       Existe porque tem gente que não quer nada atrás do texto, e "nada" não deve significar
       "de volta ao problema original". */
    html[data-wa-papel="liso"] .precs-wa-chat::before,
    .precs-supconv-palco[data-papel="liso"] .precs-wa-chat::before,
    .precs-papel-mini[data-papel="liso"]::before{ display: none; }
    /* (1.1.59) E O PALCO DA ABA CONVERSAS PRECISA DESLIGAR O `liso` DA RAIZ DO GESTOR.
       Os tokens dos outros tres papeis o palco herda de si mesmo (valor no elemento vence
       herdado, como o comentario do bloco acima ja registra), mas a regra de cima e
       DESCENDENTE e nao token: se o gestor usa `liso` no proprio WhatsApp,
       `html[data-wa-papel="liso"] .precs-wa-chat::before` casaria DENTRO do palco e apagaria
       a textura da operadora. Os tres seletores abaixo devolvem o `display` quando o palco
       declara um papel com desenho. Sao tres linhas, contra os mais de cem blocos que
       escopar o TEMA exigiria — e e por isso que o papel e escopavel e o tema nao. */
    .precs-supconv-palco[data-papel="precs"] .precs-wa-chat::before,
    .precs-supconv-palco[data-papel="constelacao"] .precs-wa-chat::before,
    .precs-supconv-palco[data-papel="timbrado"] .precs-wa-chat::before{ display: block; }
    html[data-wa-papel="liso"],
    .precs-papel-mini[data-papel="liso"],
    .precs-supconv-palco[data-papel="liso"]{
      --precs-wa-papel-fundo:
        linear-gradient(180deg, color-mix(in srgb, var(--text-primary) 4%, var(--bg-primary)), var(--bg-primary) 80%);
    }

    /* ---- PAPEL 4: TIMBRADO. O guilhochê do título de crédito: a trança de duas ondas
       cruzadas, a roseta de elipses giradas e o fio de borda. É o desenho que o precatório
       tem impresso, e é o único dos quatro que fala do que a casa faz.

       As duas contas que fazem o ladrilho não aparecer COMO ladrilho, que foi o erro da
       primeira versão do Constelação (linha longa emendando com a cópia ao lado, e o olho
       lendo a grade em vez do desenho):
         • as ondas têm período 20 e o quadro tem 160, então cabem 8 meias-ondas exatas: a
           curva chega em x=160 na MESMA altura e com a MESMA inclinação com que saiu de x=0,
           e a emenda horizontal some. Mudar a largura do ladrilho sem mudar o período traz a
           costura de volta;
         • a roseta FECHA dentro do quadro (raio 34 contra centro em 80), então ela nunca
           toca a borda e nunca precisa casar com a vizinha.
       A FORÇA É .11, quase o dobro do PRECS, e isso não é o Timbrado gritar mais. Os outros
       três papéis desenham com forma CHEIA (o losango, as estrelas), e este desenha com
       TRAÇO de meio pixel: o antialiasing come a maior parte da tinta antes de a opacidade
       ser aplicada, então a mesma força dá um cinza muito mais fraco. Medido na sonda: em
       .05 o guilhochê sumia por completo em tela escura. Comparar papel de traço com papel
       de forma pelo número da força é comparar coisas diferentes; o que se compara é o
       resultado renderizado. */
    html[data-wa-papel="timbrado"],
    .precs-papel-mini[data-papel="timbrado"],
    .precs-supconv-palco[data-papel="timbrado"]{
      --precs-wa-papel-fundo:
        radial-gradient(110% 70% at 50% 0%, color-mix(in srgb, var(--precs-gold, #B49552) 4%, transparent), transparent 62%),
        linear-gradient(180deg, color-mix(in srgb, var(--text-primary) 4%, var(--bg-primary)), var(--bg-primary) 74%);
      --precs-wa-papel-forca: .11;
      --precs-wa-papel-escala: 160px;
      --precs-wa-textura: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160' viewBox='0 0 160 160'%3E%3Cg fill='none' stroke='%23000' stroke-linecap='round'%3E%3Cg stroke-width='.75'%3E%3Cpath d='M0 26 q10 -7 20 0 t20 0 t20 0 t20 0 t20 0 t20 0 t20 0 t20 0'/%3E%3Cpath d='M0 26 q10 7 20 0 t20 0 t20 0 t20 0 t20 0 t20 0 t20 0 t20 0'/%3E%3Cpath d='M0 134 q10 -7 20 0 t20 0 t20 0 t20 0 t20 0 t20 0 t20 0 t20 0'/%3E%3Cpath d='M0 134 q10 7 20 0 t20 0 t20 0 t20 0 t20 0 t20 0 t20 0 t20 0'/%3E%3C/g%3E%3Cg stroke-width='.65' opacity='.9'%3E%3Cellipse cx='80' cy='80' rx='34' ry='11'/%3E%3Cellipse cx='80' cy='80' rx='34' ry='11' transform='rotate(30 80 80)'/%3E%3Cellipse cx='80' cy='80' rx='34' ry='11' transform='rotate(60 80 80)'/%3E%3Cellipse cx='80' cy='80' rx='34' ry='11' transform='rotate(90 80 80)'/%3E%3Cellipse cx='80' cy='80' rx='34' ry='11' transform='rotate(120 80 80)'/%3E%3Cellipse cx='80' cy='80' rx='34' ry='11' transform='rotate(150 80 80)'/%3E%3Ccircle cx='80' cy='80' r='4.5'/%3E%3C/g%3E%3Cg stroke-width='.6' opacity='.7'%3E%3Cellipse cx='0' cy='80' rx='19' ry='6'/%3E%3Cellipse cx='0' cy='80' rx='19' ry='6' transform='rotate(30 0 80)'/%3E%3Cellipse cx='0' cy='80' rx='19' ry='6' transform='rotate(60 0 80)'/%3E%3Cellipse cx='0' cy='80' rx='19' ry='6' transform='rotate(90 0 80)'/%3E%3Cellipse cx='0' cy='80' rx='19' ry='6' transform='rotate(120 0 80)'/%3E%3Cellipse cx='0' cy='80' rx='19' ry='6' transform='rotate(150 0 80)'/%3E%3Cellipse cx='160' cy='80' rx='19' ry='6'/%3E%3Cellipse cx='160' cy='80' rx='19' ry='6' transform='rotate(30 160 80)'/%3E%3Cellipse cx='160' cy='80' rx='19' ry='6' transform='rotate(60 160 80)'/%3E%3Cellipse cx='160' cy='80' rx='19' ry='6' transform='rotate(90 160 80)'/%3E%3Cellipse cx='160' cy='80' rx='19' ry='6' transform='rotate(120 160 80)'/%3E%3Cellipse cx='160' cy='80' rx='19' ry='6' transform='rotate(150 160 80)'/%3E%3C/g%3E%3Cg stroke-width='.6' opacity='.5'%3E%3Cpath d='M0 5 H160'/%3E%3Cpath d='M0 8 H160'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E");
    }

    /* O SEPARADOR DE DIA: a pílula centrada que o aplicativo usa. Ela é o que libera a bolha
       a mostrar só HH:MM (ver precsWaPintarThread). `position: sticky` prende o dia corrente
       no topo enquanto se rola o histórico, que é o comportamento do WhatsApp Web. */
    /* (1.1.39) O DIA VIROU UM BLOCO, E É ISSO QUE PARA A SOBREPOSIÇÃO.

       O `sticky` está certo — é o comportamento do WhatsApp Web, o dia corrente acompanha a
       rolagem. O que estava errado era a estrutura: todas as pílulas eram IRMÃS de todas as
       bolhas, no mesmo contêiner. Em `sticky`, o elemento só é solto quando o BLOCO CONTENEDOR
       dele sai da tela, e o contenedor de todas era a thread inteira — então cada pílula que
       já tinha passado ficava travada em `top: 0` e a próxima encostava na anterior: "o mini
       balão de HOJE/ONTEM, se eu desço tudo eles ficam se sobrepondo" (Pedro, 28/08/2026).

       Com um `<section>` por dia (ver `precsWaPintarThread`), o bloco do dia seguinte empurra
       a pílula do anterior para fora, que é o mecanismo que o padrão precisa para funcionar.

       O `gap` do grupo repete o da thread de propósito: a `<section>` entrou entre o contêiner
       e as bolhas, e sem repetir o espaçamento as mensagens do mesmo dia se colariam. */
    .precs-wa-diagrupo{ display: flex; flex-direction: column; gap: var(--space-2);
      min-width: 0; }
    .precs-wa-dia{ display: flex; justify-content: center; margin: var(--space-1) 0;
      position: sticky; top: 0; z-index: 2; pointer-events: none; }
    .precs-wa-dia span{ display: inline-flex; align-items: center;
      padding: 3px var(--space-3); border-radius: var(--radius-pill);
      background: var(--bg-secondary); border: 1px solid var(--border-color);
      color: var(--text-secondary);
      /* Sombra própria e mais funda que a `--shadow` genérica: a pílula flutua POR CIMA das
         bolhas, e é a sombra que diz que ela está num plano acima em vez de encaixada entre
         duas mensagens. */
      box-shadow: 0 2px 10px -3px var(--precs-wa-balao-sombra, rgba(0,0,0,.35));
      font-family: 'Manrope', 'Poppins', sans-serif; font-size: .66rem; font-weight: 700;
      text-transform: uppercase; letter-spacing: var(--ls-caps); }

    /* (1.1.40) O DIVISOR DE NÃO LIDAS, onde a leitura parou na última vez.
       Dourado e com o nome escrito, ao contrário da pílula de dia (que é neutra e sticky):
       são duas informações diferentes e não podem parecer a mesma coisa. Este NÃO é sticky —
       ele marca um ponto no histórico, e um ponto que acompanha a rolagem deixa de ser ponto. */
    .precs-wa-corte{ display: flex; align-items: center; gap: var(--space-3);
      margin: var(--space-2) 0; color: var(--precs-gold-title, var(--precs-gold, #B49552)); }
    .precs-wa-corte::before, .precs-wa-corte::after{ content: ''; flex: 1 1 auto; height: 1px;
      background: color-mix(in srgb, var(--precs-gold-forma, #B49552) 45%, transparent); }
    .precs-wa-corte span{ flex: 0 0 auto;
      font-family: 'Manrope', 'Poppins', sans-serif; font-size: .62rem; font-weight: 700;
      text-transform: uppercase; letter-spacing: var(--ls-caps); }

    /* ======================================================================
       (1.1.40) A CITAÇÃO DENTRO DA BOLHA, e a barra de "respondendo a".
       O desenho é o do aplicativo e a razão é a mesma: numa negociação com dez propostas na
       tela, "pode ser" sem saber a QUE pode ser não informa nada. A faixa vertical à esquerda
       é o que faz o bloco ler como "citado" e não como parte da fala. */
    .precs-wa-cit{ display: flex; flex-direction: column; gap: 1px; width: 100%;
      text-align: left; cursor: pointer; padding: 4px 8px; margin-bottom: 2px;
      border: 0; border-left: 3px solid var(--precs-gold-forma, #B49552);
      border-radius: var(--radius-sm, 6px);
      background: color-mix(in srgb, var(--text-primary) 8%, transparent);
      transition: background var(--dur-1, .15s) ease; }
    .precs-wa-cit:hover{ background: color-mix(in srgb, var(--text-primary) 14%, transparent); }
    .precs-wa-cit:focus-visible{ outline: 2px solid var(--precs-gold-hi, #FFC95B);
      outline-offset: 1px; }
    /* Citação de mensagem PRÓPRIA muda a cor da faixa: saber de quem é a fala citada é metade
       da informação, e ler o nome toda vez é lento. */
    .precs-wa-cit.propria{ border-left-color: color-mix(in srgb, var(--text-primary) 45%, transparent); }
    .precs-wa-cit i{ font-style: normal; font-family: 'Manrope', 'Poppins', sans-serif;
      font-size: .62rem; font-weight: 700;
      color: var(--precs-gold-title, var(--precs-gold, #B49552)); }
    .precs-wa-cit.propria i{ color: var(--text-secondary); }
    .precs-wa-cit b{ font-weight: 400; font-size: .78rem; color: var(--text-secondary);
      line-height: 1.3; overflow: hidden; text-overflow: ellipsis;
      display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; }
    /* A citação cujo original não está na página não é clicável: não há para onde levar. */
    .precs-wa-cit-longe{ cursor: default; }
    .precs-wa-cit-longe:hover{ background: color-mix(in srgb, var(--text-primary) 8%, transparent); }
    /* O realce de quem foi ENCONTRADA por um clique na citação. Sem ele o `scrollIntoView`
       deixa a pessoa no meio da thread sem saber qual das bolhas era o destino. */
    @keyframes precsWaAchada{
      0%{ box-shadow: 0 0 0 0 color-mix(in srgb, var(--precs-gold-forma, #B49552) 70%, transparent); }
      100%{ box-shadow: 0 0 0 8px transparent; } }
    .precs-wa-msg.achada .precs-wa-balao{
      animation: precsWaAchada 1.4s ease-out;
      outline: 2px solid color-mix(in srgb, var(--precs-gold-forma, #B49552) 60%, transparent);
      outline-offset: 2px; }
    /* O selo de ENCAMINHADA: proposta repassada de outro contato lê diferente de proposta
       escrita para você, e a Meta manda essa informação. */
    .precs-wa-enc{ align-self: flex-start; font-family: 'Manrope', 'Poppins', sans-serif;
      font-size: .6rem; font-weight: 700; text-transform: uppercase;
      letter-spacing: var(--ls-caps); color: var(--text-muted); }

    /* A barra do compositor, quando há citação em curso. */
    .precs-wa-citando{ flex: 1 0 100%; display: flex; align-items: center;
      gap: var(--space-2); padding: var(--space-2) var(--space-3);
      border-radius: var(--radius-inner);
      border-left: 3px solid var(--precs-gold-forma, #B49552);
      background: var(--bg-tertiary); }
    .precs-wa-citando-txt{ flex: 1 1 auto; min-width: 0; display: flex;
      flex-direction: column; gap: 1px; }
    .precs-wa-citando-txt i{ font-style: normal;
      font-family: 'Manrope', 'Poppins', sans-serif; font-size: .62rem; font-weight: 700;
      text-transform: uppercase; letter-spacing: var(--ls-caps);
      color: var(--precs-gold-title, var(--precs-gold, #B49552)); }
    .precs-wa-citando-txt b{ font-weight: 400; font-size: .78rem;
      color: var(--text-secondary); white-space: nowrap; overflow: hidden;
      text-overflow: ellipsis; }
    .precs-wa-citando-x{ flex: 0 0 auto; width: 26px; height: 26px; cursor: pointer;
      display: inline-flex; align-items: center; justify-content: center; padding: 0;
      background: transparent; border: 1px solid var(--border-color); border-radius: 50%;
      color: var(--text-muted);
      transition: color var(--dur-1, .15s) ease, border-color var(--dur-1, .15s) ease; }
    .precs-wa-citando-x:hover{ color: var(--accent-red, #ef4444);
      border-color: var(--accent-red, #ef4444); }
    .precs-wa-citando-x:focus-visible{ outline: 2px solid var(--precs-gold-hi, #FFC95B);
      outline-offset: 2px; }
    @media (prefers-reduced-motion: reduce){
      .precs-wa-cit, .precs-wa-citando-x{ transition: none; }
      .precs-wa-msg.achada .precs-wa-balao{ animation: none; } }

    /* ---- OS BALÕES ---- */
    @keyframes precsWaMsgIn{ from{ opacity: 0; transform: translateY(6px); }
      to{ opacity: 1; transform: none; } }
    /* (1.1.39) A entrada só vale para bolha NOVA, pelo mesmo motivo da etiqueta: a thread é
       reescrita por inteiro a cada repintura, inclusive no poll de 8s, e com a animação na
       regra base a conversa toda reencenava o "sobe e aparece" de tempos em tempos. Quem
       decide o que é novo é `precsWaPintarThread`, comparando com a leva anterior. */
    .precs-wa-msg{ display: flex; }
    .precs-wa-msg.entrando{ animation: precsWaMsgIn 180ms ease; }
    @media (prefers-reduced-motion: reduce){ .precs-wa-msg.entrando{ animation: none; } }
    .precs-wa-msg.credor{ justify-content: flex-start; }
    .precs-wa-msg.propria{ justify-content: flex-end; }
    .precs-wa-balao{ max-width: min(62ch, 78%); padding: 8px 12px;
      border-radius: var(--radius-card); font-size: .88rem; line-height: 1.45;
      display: flex; flex-direction: column; gap: 4px; }
    /* (1.1.38 · 2ª volta) OS BALÕES FICARAM SÓLIDOS, E ISSO É O QUE CONSERTA O RABICHO.
       O rabicho antigo era um par de triângulos de `border`, e o Pedro descreveu bem em
       28/08/2026: "ficou meio triângulo do lado do card, não ficou natural". O motivo é
       estrutural — o balão tinha FUNDO TRANSLÚCIDO e BORDA de 1px, e um bico de borda nunca
       encosta direito num fundo que deixa passar o que está atrás: sobra costura de um lado
       e um degrau do outro.
       Agora o balão é opaco (mistura calculada, sem alpha), sem borda, com uma sombra fina —
       que é como o balão do WhatsApp é feito. Assim o rabicho pode ser um recorte SÓLIDO da
       mesma cor, sem borda para desencontrar. */
    .precs-wa-msg.credor .precs-wa-balao{
      background: var(--precs-wa-balao-credor);
      border-bottom-left-radius: 4px; color: var(--text-primary);
      box-shadow: 0 1px 1.5px var(--precs-wa-balao-sombra); }
    /* (1.1.37) O AGRUPAMENTO: mensagens seguidas da mesma pessoa dentro de 3 minutos são um
       bloco de fala. Elas encostam (o gap do container vira quase nada), perdem o canto
       cortado que marca o fim do bloco e perdem o rabicho — no aplicativo só a PRIMEIRA
       bolha do grupo tem rabicho, e é isso que faz seis mensagens seguidas lerem como uma
       pessoa falando em vez de seis avisos empilhados. */
    .precs-wa-msg.agrupada{ margin-top: calc(var(--space-2) * -1 + 3px); }
    .precs-wa-msg.agrupada.credor .precs-wa-balao{ border-bottom-left-radius: var(--radius-card); }
    .precs-wa-msg.agrupada.propria .precs-wa-balao{ border-bottom-right-radius: var(--radius-card); }
    /* O balão PRÓPRIO é ouro — a marca — e não o verde do WhatsApp. O texto usa
       o token de texto normal: o tint é fraco de propósito para o contraste
       passar nos cinco temas sem token novo. */
    .precs-wa-msg.propria .precs-wa-balao{
      background: var(--precs-wa-balao-proprio);
      border-bottom-right-radius: 4px; color: var(--text-primary);
      box-shadow: 0 1px 1.5px var(--precs-wa-balao-sombra); }
    /* As duas cores dos balões, calculadas a partir dos tokens do tema. `color-mix` sem alpha
       é o que os torna OPACOS: o balão precisa ser sólido para o rabicho colar nele, e um
       fundo translúcido sobre o papel de parede também deixava o desenho aparecer por dentro
       da bolha, o que atrapalhava a leitura. */
    /* (1.1.39) O BALÃO DO TEMA CLARO SUMIA NO PAPEL, E A CONTA EXPLICA POR QUÊ.
       Balão do credor era `color-mix(--text-primary 7%, #FFF)` ≈ #F0EFEF; o papel da thread é
       `color-mix(--text-primary 4%, --bg-primary)` ≈ #F2F1EE a #F7F6F3. Um a três por cento de
       diferença de luminância, e o balão não tem borda (decisão do rabicho, logo abaixo): "no
       modo claro o balão parece que é da cor do fundo" (Pedro, 28/08/2026), e estava mesmo.

       No claro o balão do credor passa a ser `--bg-secondary` PURO — branco sobre papel bege,
       que é exatamente o que o aplicativo faz — e a sombra ganha peso, porque com o fundo
       resolvido é ela quem desenha a borda do balão.

       O balão próprio migra de `--precs-gold` para `--precs-gold-forma`. No tema claro o
       `--precs-gold` vira bronze #7A6320 para proteger TEXTO, e aqui ele é SUPERFÍCIE: o
       resultado era um balão pardo em vez de dourado. `--precs-gold-forma` existe desde 1.1.4
       exatamente para "o ouro como forma, que não tem letra em cima e não precisa pagar esse
       preço" — e ele também dá ao tema Contraste o ouro clareado (#E8C46A) daquele tema, que
       antes não chegava aqui. */
    html{
      --precs-wa-balao-credor: var(--bg-secondary);
      --precs-wa-balao-proprio: color-mix(in srgb, var(--precs-gold-forma, #B49552) 30%, var(--bg-secondary));
      --precs-wa-balao-sombra: rgba(42, 39, 34, .22);
    }
    /* (1.1.41) O bordô entra aqui junto com os outros dois escuros: os balões da conversa se
       derivam de `--text-primary` e `--bg-secondary`, então a fórmula já é a certa para ele —
       o que faltaria é só a regra alcançá-lo. */
    html[data-theme="precs"], html[data-theme="contraste"], html[data-theme="bordo"],
    html[data-theme="zebrado"], html[data-theme="saphira"],
    html[data-theme="topazio"], html[data-theme="ametista"], html[data-theme="rubi"],
    html[data-theme="leao"], html[data-theme="sakura"],
    html[data-theme="galaxia"]{
      --precs-wa-balao-credor: color-mix(in srgb, var(--text-primary) 9%, var(--bg-secondary));
      --precs-wa-balao-proprio: color-mix(in srgb, var(--precs-gold-forma, #B49552) 22%, var(--bg-secondary));
      --precs-wa-balao-sombra: rgba(0, 0, 0, .35);
    }
    /* O RABICHO, refeito: UM elemento só, com a forma recortada por `mask`.
       O SVG é o mesmo desenho do bico do WhatsApp — a curva que sai do canto do balão e volta.
       Como o balão agora é sólido e sem borda, o rabicho é só um retângulo com a MESMA cor de
       fundo recortado nessa forma: ele nasce colado, sem costura possível. `top: 0` e altura
       do balão inteiro não: ele mora no pé, que é de onde o bico sai.
       Some na bolha agrupada, porque no aplicativo só a primeira fala do bloco tem bico. */
    .precs-wa-balao{ position: relative; }
    .precs-wa-msg:not(.agrupada) .precs-wa-balao::after{
      content: ''; position: absolute; bottom: 0; width: 10px; height: 14px;
      pointer-events: none;
      -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
      -webkit-mask-size: 100% 100%; mask-size: 100% 100%; }
    .precs-wa-msg.credor:not(.agrupada) .precs-wa-balao::after{
      left: -9px; background: var(--precs-wa-balao-credor);
      -webkit-mask-image: var(--precs-wa-rabicho-esq); mask-image: var(--precs-wa-rabicho-esq); }
    .precs-wa-msg.propria:not(.agrupada) .precs-wa-balao::after{
      right: -9px; background: var(--precs-wa-balao-proprio);
      -webkit-mask-image: var(--precs-wa-rabicho-dir); mask-image: var(--precs-wa-rabicho-dir); }
    html{
      --precs-wa-rabicho-esq: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='14' viewBox='0 0 10 14'%3E%3Cpath fill='%23000' d='M10 0v14C10 14 8.4 12.4 5.2 10.6 2.6 9.1 0 8.4 0 8.4c3.6-.6 6.2-2.2 7.6-4.2C9 2.2 10 0 10 0z'/%3E%3C/svg%3E");
      --precs-wa-rabicho-dir: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='14' viewBox='0 0 10 14'%3E%3Cpath fill='%23000' d='M0 0v14c0 0 1.6-1.6 4.8-3.4C7.4 9.1 10 8.4 10 8.4c-3.6-.6-6.2-2.2-7.6-4.2C1 2.2 0 0 0 0z'/%3E%3C/svg%3E");
    }
    .precs-wa-texto{ white-space: pre-wrap; word-break: break-word; }
    /* (1.1.40) O LINK DENTRO DA BOLHA. Sublinhado e não só colorido: cor sozinha não é
       affordance suficiente, e no balão próprio (dourado) qualquer cor de link brigaria com o
       fundo. `currentColor` mantém o link legível nos dois lados sem uma regra por lado. */
    .precs-wa-link{ color: inherit; text-decoration: underline;
      text-underline-offset: 2px;
      text-decoration-color: color-mix(in srgb, currentColor 45%, transparent);
      transition: text-decoration-color var(--dur-1, .15s) ease; }
    .precs-wa-link:hover{ text-decoration-color: currentColor; }
    .precs-wa-link:focus-visible{ outline: 2px solid var(--precs-gold-hi, #FFC95B);
      outline-offset: 2px; border-radius: 3px; }
    .precs-wa-texto b{ font-weight: 700; }
    .precs-wa-texto i{ font-style: italic; }
    .precs-wa-texto s{ text-decoration: line-through; opacity: .75; }
    .precs-wa-cod{ font-family: 'JetBrains Mono', monospace; font-size: .82em;
      background: color-mix(in srgb, var(--text-primary) 8%, transparent);
      border-radius: var(--radius-sm, 6px); padding: 1px 5px; }
    @media (prefers-reduced-motion: reduce){ .precs-wa-link{ transition: none; } }
    /* (1.1.40) MENSAGEM SÓ COM EMOJI: sem balão e grande, como no aplicativo. O balão existe
       para separar fala de fala; com um emoji sozinho ele vira uma moldura maior que o
       conteúdo. */
    .precs-wa-msg.soemoji .precs-wa-balao{ background: none; box-shadow: none; padding: 2px 0; }
    .precs-wa-msg.soemoji .precs-wa-balao::after{ display: none; }
    .precs-wa-msg.soemoji .precs-wa-texto{ font-size: 2.4rem; line-height: 1.15; }
    .precs-wa-rodape-msg{ display: flex; align-items: center; gap: 6px;
      justify-content: flex-end; }
    .precs-wa-msg-hora{ font-family: 'JetBrains Mono', monospace; font-size: .64rem;
      color: var(--text-muted); }
    /* (1.1.38 · 2ª volta) DENTRO DO BALÃO PRÓPRIO A TINTA SOBE UM DEGRAU. O balão deixou de
       ser translúcido e virou opaco (é o que fez o rabicho colar), e com isso o fundo dele
       escureceu: a hora e o selo em `--text-muted` caíram para 4,09:1 nos temas claros, abaixo
       do mínimo de 4,5. `--text-secondary` devolve a margem sem mexer na cor do balão, que é
       a identidade. Medido pelo teste-contraste-render nos cinco temas. */
    /* (1.1.40) O TICK ENTROU NESTA LISTA, e ele faltava desde a 1.1.38.
       A regra existe porque o balão ficou opaco e o par `--text-muted` sobre ele caiu para
       4,09:1 — abaixo do mínimo. Hora e selo subiram para `--text-secondary`; o tick, que só
       existe em balão próprio e portanto sempre esteve sobre esse mesmo fundo, ficou de fora
       por esquecimento. */
    .precs-wa-msg.propria .precs-wa-msg-hora,
    .precs-wa-msg.propria .precs-wa-tick,
    .precs-wa-msg.propria .precs-wa-eco{ color: var(--text-secondary); }
    /* O "lido" e o "falhou" continuam com a cor própria: eles são sinal, não texto de apoio. */
    .precs-wa-msg.propria .precs-wa-tick.lido{ color: var(--accent-blue); }
    .precs-wa-msg.propria .precs-wa-tick.falhou{ color: var(--accent-red); }
    /* (1.1.40) O `letter-spacing: -1px` saiu com os glifos. Ele existia para colar os dois
       `✓✓` de texto, e obrigava a linha do eco logo abaixo a DESFAZÊ-LO com `letter-spacing: 0`
       — um hack e o antídoto do hack, lado a lado. Com SVG o desenho já vem colado. */
    /* (1.1.41) O PULSO DO DEGRAU DO TICK. Curto e pequeno de propósito: ele acontece numa
       conversa que a pessoa está lendo, e um movimento grande no canto do balão puxaria o olho
       para longe do texto. Só dispara na repintura em que o status MUDOU — quem decide é
       `precsWaPintarThread`, comparando com a leva anterior; na regra base a thread inteira
       pulsaria a cada tique de 8s. */
    @keyframes precsWaTickSobe{
      from{ transform: scale(.62); opacity: .25; }
      60%{ transform: scale(1.12); opacity: 1; }
      to{ transform: scale(1); opacity: 1; }
    }
    .precs-wa-tick.subiu{ animation: precsWaTickSobe 260ms var(--ease-1); }
    /* O triângulo de "ouviu" é menor que os ticks de propósito: ele é o segundo selo da
       dupla, e dois desenhos do mesmo peso lado a lado brigariam pela leitura. */
    .precs-wa-tick.ouviu{ margin-left: -1px; }
    .precs-wa-tick.ouviu svg{ width: 10px; height: 10px; }
    @media (prefers-reduced-motion: reduce){
      .precs-wa-tick.subiu{ animation: none; }
    }
    .precs-wa-tick{ font-size: .68rem; color: var(--text-muted);
      display: inline-flex; align-items: center; }
    .precs-wa-tick svg{ display: block; width: 15px; height: 15px; }
    .precs-wa-tick.falhou svg{ width: 13px; height: 13px; }
    .precs-wa-tick.lido{ color: var(--accent-blue); }
    .precs-wa-tick.falhou{ color: var(--accent-red); font-weight: 700; cursor: help; }
    /* (1.1.38) O eco não tem tick (ver precsWaTicks): fica um ponto discreto, que é lugar
       clicável para o tooltip e mantém o alinhamento do rodapé da bolha. */
    .precs-wa-tick.eco-sem-tick{ cursor: help; opacity: .5; letter-spacing: 0; }
    /* O selo do ECO: o que a operadora mandou pelo celular (coexistência). */
    .precs-wa-eco{ font-size: .6rem; font-weight: 700; text-transform: uppercase;
      letter-spacing: var(--ls-caps); color: var(--text-muted);
      border: 1px solid var(--border-color); border-radius: var(--radius-pill);
      padding: 1px 6px; cursor: help; }
    .precs-wa-midia{ font-size: .8rem; color: var(--text-secondary);
      background: var(--bg-tertiary); border-radius: var(--radius-inner);
      padding: 6px 10px; cursor: help; }
    /* (1.1.22) MÍDIA DE VERDADE NA BOLHA: imagem inline com teto de tamanho (a bolha manda no
       layout, não a foto), player de áudio compacto, documento como botão de baixar e a
       reação pendurada no pé — pedido da Ana Carolina em 25/08/2026. */
    /* (1.1.40) A ALTURA DE ESPERA. Sem ela, a bolha ia de ~30px (o chip "carregando imagem…")
       para até 320px quando o blob resolvia — e como a thread rola sozinha para o fim, o salto
       sacode a leitura de quem estava no meio dela. `min-height` e não `aspect-ratio`: a
       proporção real da foto do credor é desconhecida até ela chegar, e chutar uma proporção
       erraria para o outro lado. */
    .precs-wa-midia.carregando{ display: inline-flex; align-items: center;
      justify-content: center; min-height: 160px; width: 220px;
      background: color-mix(in srgb, var(--text-primary) 5%, transparent);
      border-radius: var(--radius-inner); }
    /* (1.1.40) Vídeo e figurinha, que até aqui caíam no chip "abra no celular". O vídeo usa o
       controle nativo de propósito: ele traz tela cheia, legenda e o gesto que o operador já
       conhece, e refazer isso à mão renderia menos do que rendeu no áudio (onde o ganho foi a
       velocidade de reprodução). A figurinha não tem moldura — ver `.precs-wa-msg.figurinha`. */
    .precs-wa-video{ display: block; max-width: 280px; width: 100%;
      border-radius: var(--radius-inner); background: #000; }
    .precs-wa-fig{ display: block; width: 140px; height: 140px; object-fit: contain; }
    .precs-wa-msg.figurinha .precs-wa-balao{ background: none; box-shadow: none; padding: 0; }
    .precs-wa-msg.figurinha .precs-wa-balao::after{ display: none; }
    .precs-wa-msg.figurinha .precs-wa-rodape-msg{ padding: 2px 4px 0; }
    .precs-wa-img{ display: block; max-width: 280px; max-height: 320px; width: auto;
      border-radius: var(--radius-inner); cursor: zoom-in; }
    /* ======================================================================
       (1.1.40) O PLAYER DE ÁUDIO DO PAINEL.
       Aqui morava `.precs-wa-audio{ width: 260px; height: 40px }`, uma linha para dar tamanho
       ao `<audio controls>` NATIVO — o único elemento da thread que não respondia a tema, não
       usava fonte da casa e não tinha o anel de foco do painel. O `<audio>` continua vivo como
       motor, escondido; o que se vê é isto.
       A COR DA BARRA depende do lado: no balão do credor ela é o ouro da marca; no balão
       próprio o ouro já é o fundo, e ouro sobre ouro não se lê — lá ela usa a tinta do texto.
       ====================================================================== */
    .precs-wa-som{ display: flex; align-items: center; gap: var(--space-2);
      width: 260px; max-width: 100%;
      --precs-som-cor: var(--precs-gold-forma, #B49552); }
    .precs-wa-som.propria{ --precs-som-cor: var(--text-primary); }
    .precs-wa-som audio{ display: none; }
    .precs-wa-som-play{ flex: 0 0 auto; width: 32px; height: 32px; border-radius: 50%;
      display: inline-flex; align-items: center; justify-content: center; cursor: pointer;
      padding: 0; border: 1px solid color-mix(in srgb, var(--precs-som-cor) 45%, transparent);
      background: color-mix(in srgb, var(--precs-som-cor) 14%, transparent);
      color: var(--precs-som-cor);
      transition: background var(--dur-1, .15s) ease, transform var(--dur-1, .15s) ease; }
    .precs-wa-som-play:hover{
      background: color-mix(in srgb, var(--precs-som-cor) 26%, transparent); }
    .precs-wa-som-play:active{ transform: scale(.94); }
    .precs-wa-som-play:focus-visible{ outline: 2px solid var(--precs-gold-hi, #FFC95B);
      outline-offset: 2px; }
    .precs-wa-som-play svg{ display: block; }
    /* A barra tem 4px de traço e 18px de área de clique: o alvo do ponteiro não pode ter a
       espessura do desenho, senão acertar a barra vira perícia. */
    .precs-wa-som-barra{ flex: 1 1 auto; position: relative; height: 18px; cursor: pointer;
      display: flex; align-items: center; min-width: 40px; touch-action: none; }
    .precs-wa-som-barra::before{ content: ''; position: absolute; left: 0; right: 0; height: 4px;
      border-radius: var(--radius-pill);
      background: color-mix(in srgb, var(--precs-som-cor) 22%, transparent); }
    .precs-wa-som-cheio{ position: absolute; left: 0; height: 4px; width: 0;
      border-radius: var(--radius-pill); background: var(--precs-som-cor); }
    .precs-wa-som-bola{ position: absolute; top: 50%; left: 0; width: 10px; height: 10px;
      margin: -5px 0 0 -5px; border-radius: 50%; background: var(--precs-som-cor);
      box-shadow: 0 0 0 3px color-mix(in srgb, var(--precs-som-cor) 22%, transparent);
      opacity: 0; transition: opacity var(--dur-1, .15s) ease; }
    .precs-wa-som:hover .precs-wa-som-bola,
    .precs-wa-som.tocando .precs-wa-som-bola,
    .precs-wa-som-barra:focus-visible ~ .precs-wa-som-bola{ opacity: 1; }
    .precs-wa-som-barra:focus-visible{ outline: 2px solid var(--precs-gold-hi, #FFC95B);
      outline-offset: 3px; border-radius: var(--radius-pill); }
    .precs-wa-som-t{ flex: 0 0 auto; font-family: 'JetBrains Mono', monospace;
      font-size: .64rem; color: var(--text-secondary); white-space: nowrap; }
    .precs-wa-som-vel{ flex: 0 0 auto; cursor: pointer; padding: 1px 6px;
      border-radius: var(--radius-pill); background: transparent;
      border: 1px solid color-mix(in srgb, var(--precs-som-cor) 35%, transparent);
      color: var(--text-secondary);
      font-family: 'JetBrains Mono', monospace; font-size: .6rem; font-weight: 700;
      transition: color var(--dur-1, .15s) ease, border-color var(--dur-1, .15s) ease; }
    .precs-wa-som-vel:hover{ color: var(--precs-som-cor);
      border-color: var(--precs-som-cor); }
    .precs-wa-som-vel:focus-visible{ outline: 2px solid var(--precs-gold-hi, #FFC95B);
      outline-offset: 2px; }
    @media (prefers-reduced-motion: reduce){
      .precs-wa-som-play, .precs-wa-som-bola, .precs-wa-som-vel{ transition: none; }
      .precs-wa-som-play:active{ transform: none; } }
    /* No painel de 440px o player divide a linha com o nome do arquivo e dois botões. */
    html[data-wa-drawer] .precs-wa-som{ width: 100%; }
    .precs-wa-doc{ display: inline-flex; align-items: center; gap: 6px; cursor: pointer;
      font-family: 'Manrope', 'Poppins', sans-serif; font-size: .8rem; font-weight: 600;
      color: var(--text-primary); background: var(--bg-tertiary);
      border: 1px solid var(--border-color); border-radius: var(--radius-inner);
      padding: 8px 12px; max-width: 300px; overflow: hidden; text-overflow: ellipsis;
      white-space: nowrap; }
    .precs-wa-doc:hover{ border-color: var(--precs-gold, #B49552); }
    /* (1.1.40) A REAÇÃO FICAVA INVISÍVEL NO TEMA CLARO, e a conta explica: o fundo dela era
       `--bg-secondary`, que é EXATAMENTE `--precs-wa-balao-credor` no claro (ver o bloco de
       variáveis dos balões). Chip e balão com o mesmo fundo, separados por 1px de borda.
       Agora ela mistura a tinta do texto com o fundo do próprio balão, então destaca em
       qualquer tema, e ganha sombra para ler como coisa pendurada — que é o que ela é.
       E o `align-self` deixou de ser sempre `flex-start`: na bolha própria a reação ia para o
       canto ESQUERDO, oposto ao lado da fala. */
    .precs-wa-reacoes{ align-self: flex-start; margin-top: -2px; font-size: .82rem;
      background: color-mix(in srgb, var(--text-primary) 10%, var(--precs-wa-balao-credor));
      border: 1px solid color-mix(in srgb, var(--text-primary) 14%, transparent);
      box-shadow: 0 1px 3px -1px var(--precs-wa-balao-sombra, rgba(0,0,0,.35));
      border-radius: var(--radius-pill); padding: 0 7px; cursor: help; }
    .precs-wa-msg.propria .precs-wa-reacoes{ align-self: flex-end;
      background: color-mix(in srgb, var(--text-primary) 10%, var(--precs-wa-balao-proprio)); }
    /* ====================================================================
       (1.1.23) O PAINEL LATERAL (drawer) — o WhatsApp por cima da tela do discador.
       Pedido de 25/08/2026: no TPA o operador quer responder mensagem sem perder o mailing, a
       qualificação e o cronômetro de vista. O conteúdo é o MESMO nó do modo cheio; o que muda
       é o enquadramento, por `data-wa-drawer` na raiz — mesmo mecanismo do `data-wa`/`data-tv`.
       ==================================================================== */
    /* (1.1.37) A SOMBRA DO PAINEL VIRA TOKEN. Ela era `rgba(0,0,0,.45)` cravado, e preto a
       45% ao lado de um fundo claro não lê como profundidade: lê como sujeira. Os tokens de
       sombra da casa (`--shadow-lg`) são valores INTEIROS de box-shadow, e aqui o que varia
       é só a cor dentro de um desenho de sombra lateral — por isso o token é de cor. */
    html{ --precs-wa-drawer-sombra: rgba(42, 39, 34, .18); }
    html[data-theme="precs"], html[data-theme="contraste"], html[data-theme="bordo"],
    html[data-theme="zebrado"], html[data-theme="saphira"],
    html[data-theme="topazio"], html[data-theme="ametista"], html[data-theme="rubi"],
    html[data-theme="leao"], html[data-theme="sakura"],
    html[data-theme="galaxia"]{
      --precs-wa-drawer-sombra: rgba(0, 0, 0, .45); }
    /* (1.1.114) A CAMADA DOS PAINÉIS LATERAIS VIRA TOKEN. O painel da comunicação interna
       (00-base.css, `data-chat-drawer`) fica na MESMA camada que este: dois painéis, um de cada
       lado, uma camada só. O número que era literal aqui passa a ser a única definição. */
    html{ --precs-camada-drawer: 9000; }

    /* (1.1.37) O TOPO DO PAINEL DEIXOU DE SER PALPITE.
       Era `top: 64px`, e o 64 nunca foi verdade: o `header` recebe o `zoom` da densidade
       (0,72 / 0,85 / 1), então a altura REAL dele muda por operador. Em compacto sobrava uma
       faixa entre o header e o painel ("a janelinha do WhatsApp descola do topo", 27/08/2026);
       em confortável ele subia por cima do header. Agora quem escreve `--precs-header-h` é o
       `precsMedirHeader` do app.js, por ResizeObserver, e o fallback de 64px só vale no quadro
       entre o CSS carregar e a primeira medida.

       E O HEADER GRUDA ENQUANTO O PAINEL ESTÁ ABERTO. Sem isto a medida certa não bastava: o
       painel é `fixed` (ancorado na janela) e a tela da campanha rola por baixo dele, então o
       header subia com a rolagem e o buraco voltava a aparecer. `sticky` no header é o mesmo
       remédio do `position: relative` que o modo cheio já usava logo acima, com um motivo a
       mais: o botão do WhatsApp continua alcançável com a tela rolada. */
    html[data-wa-drawer] header, html[data-chat-drawer] header{ position: sticky; top: 0; z-index: 60; }
    html[data-wa-drawer] #whatsapp-section.section{
      display: block; position: fixed; top: var(--precs-header-h, 64px); right: 0; bottom: 0;
      width: min(440px, 94vw); z-index: var(--precs-camada-drawer);
      border-left: 1px solid var(--border-color);
      box-shadow: -18px 0 40px -12px var(--precs-wa-drawer-sombra, rgba(0,0,0,.45));
      animation: precsWaDrawerEntra .26s var(--ease-2);
    }
    @keyframes precsWaDrawerEntra{
      from{ opacity: .4; transform: translateX(26px); }
      to{ opacity: 1; transform: none; }
    }
    /* (1.1.31 · 1.1.29) A SAÍDA DO PAINEL, e ela levou três medições para ficar de pé.

       Em 25/08 o Pedro pediu simetria ("a animação de fechar deve ser a mesma de abrir, senão
       não faz sentido") e eu espelhei os QUADROS: 26px e .26s, invertidos. Em 26/08 ele voltou
       com "dá uma quebrada pequena e depois fecha em vez de só fechar reto". Uma sonda quadro
       a quadro (rect + opacidade a cada requestAnimationFrame) mostrou os dois defeitos:

        • A CURVA NÃO TINHA SIDO INVERTIDA junto. `cubic-bezier(.16,1,.3,1)` é uma ease-OUT:
          corre no começo e se acomoda no fim, que é o que uma ENTRADA quer. Tocada ao
          contrário, ela fazia 83% do deslocamento nos primeiros 80ms e arrastava os 17%
          restantes pelos 170ms seguintes. Era o tranco seguido do painel parado no meio.

        • O FIM ERA OPACIDADE .4. A entrada NASCE em .4 e ninguém percebe, porque ela está
          aparecendo; a saída TERMINAR em .4 deixa o nó 40% visível quando o `display:none`
          chega, e esses 40% somem num quadro só. Era o estalo do fim.

       Inverter a curva de verdade (`reverse(x1,y1,x2,y2) = (1-x2,1-y2,1-x1,1-y1)`, que dá
       `cubic-bezier(.7,0,.84,0)`) foi medido também, e trocou um defeito por outro: opacidade
       parada em 1,00 por 150ms e a saída inteira espremida no fim, cortada em 0,50 pela
       remoção do nó. Simetria perfeita perdeu para o resultado certo.

       O QUE FICOU É O QUE ELE PEDIU AO PÉ DA LETRA: reta. `linear`, .2s, indo até opacidade 0.
       Medido: passo constante de 2,17px e 0,083 de opacidade por quadro, zero alcançado aos
       208ms, e o `forwards` segura invisível até a remoção em 260ms. Sem tranco no começo, sem
       arrasto no meio, sem estalo no fim. A duração menor que a da entrada é de propósito e é
       regra conhecida de movimento: saída percebida como lenta incomoda, entrada não. */
    @keyframes precsWaDrawerSai{
      from{ opacity: 1; transform: none; }
      to{ opacity: 0; transform: translateX(26px); }
    }
    html[data-wa-drawer] #whatsapp-section.section.wa-drawer-saindo{
      animation: precsWaDrawerSai .2s linear forwards; }
    @media (prefers-reduced-motion: reduce){
      html[data-wa-drawer] #whatsapp-section.section,
      html[data-wa-drawer] #whatsapp-section.section.wa-drawer-saindo{ animation: none; } }
    /* UMA COISA POR VEZ: 440px não comportam as duas colunas do inbox, então o painel mostra a
       LISTA ou a CONVERSA, como num telefone. Quem decide é precsWaDrawerSincronizar. */
    html[data-wa-drawer] .precs-wa-wrap{
      grid-template-columns: minmax(0, 1fr); height: 100%; min-height: 0;
      max-width: none; margin: 0; border: 0; border-radius: 0;
      /* (1.1.37) O `overflow: hidden` do modo card existe para o border-radius não vazar. Aqui
         não há raio (linha acima), e ele estava CORTANDO os popovers de etiqueta e de vínculo
         dentro dos 440px — parte do "o botão de etiquetar é muito inexistente" de 27/08/2026:
         o botão abria um seletor que nascia fora da área visível. As duas colunas já contêm a
         própria rolagem (.precs-wa-conversas e .precs-wa-thread), então soltar aqui não deixa
         nada escapar. */
      overflow: visible; }
    html[data-wa-drawer] .precs-wa-chat{ overflow: visible; }
    /* Os popovers nunca mais largos que o painel.
       (1.1.39) O `right: var(--space-2); left: auto` daqui SAIU: com a âncora no botão, quem
       decide o lado é `precsWaPopAjustar`, que mede e vira para `.pop-esq` só quando de fato
       falta espaço. Forçar o lado direito aqui anulava a ancoragem justamente no painel
       estreito, que é onde ela mais faz falta. */
    html[data-wa-drawer] .precs-wa-etiq-pop,
    html[data-wa-drawer] .precs-wa-vinc-pop{
      max-width: calc(min(440px, 94vw) - var(--space-6)); }
    html[data-wa-drawer] .precs-wa-vinc-pop{ flex-wrap: wrap; }
    html[data-wa-drawer] .precs-wa-vinc-input{ width: 100%; max-width: none; }
    html[data-wa-drawer="thread"] .precs-wa-lista{ display: none; }
    html[data-wa-drawer="lista"] .precs-wa-chat{ display: none; }
    /* (1.1.39) Aqui morava `html[data-wa-drawer] .precs-wa-voltar{ display:none }`, que
       escondia o "← discador" no painel lateral. O botão inteiro foi removido em 28/08/2026
       (ele repetia o do header), então a regra ficou sem sujeito. */
    /* (1.1.24) OS DOIS CONTROLES ENTRARAM NA LINHA, em vez de flutuarem por cima.
       Na primeira volta eles eram `position: fixed` com coordenadas calculadas, e o resultado
       foi o que o Pedro viu em 25/08/2026: "o botão de fechar está torto". Flutuante sobre um
       cabeçalho que tem busca e "+" não tem como ficar alinhado em toda largura de tela. Agora
       o ✕ é o último item do topo da lista e o "voltar" é o primeiro do topo do chat: os dois
       alinham sozinhos, pelo mesmo flex que já posiciona os vizinhos. */
    .precs-wa-drawer-x, .precs-wa-drawer-voltar{ display: none; }
    html[data-wa-drawer] .precs-wa-drawer-x{
      display: inline-flex; align-items: center; justify-content: center;
      order: 9; flex: 0 0 auto; width: 32px; height: 32px; border-radius: var(--radius-pill);
      background: transparent; border: 1px solid var(--border-color);
      color: var(--text-secondary); cursor: pointer; font-size: .78rem; padding: 0; }
    .precs-wa-drawer-x:hover{ color: var(--accent-red, #ef4444);
      border-color: var(--accent-red, #ef4444); }
    /* (1.1.37) O ✕ TAMBÉM NO CABEÇALHO DA CONVERSA, e só dentro do painel lateral. Com a
       conversa aberta a coluna da lista está `display:none`, e o ✕ dela ia junto: quem
       perdesse o ← (foi o que o defeito da assinatura fazia) ficava sem nenhuma saída.
       ← volta para a lista, ✕ fecha o painel: ações diferentes, botões diferentes. */
    .precs-wa-topo-x{ display: none; }
    html[data-wa-drawer] .precs-wa-topo-x{
      display: inline-flex; align-items: center; justify-content: center;
      flex: 0 0 auto; margin-left: auto; width: 30px; height: 30px;
      border-radius: var(--radius-pill); background: transparent;
      border: 1px solid var(--border-color); color: var(--text-secondary);
      cursor: pointer; padding: 0;
      transition: color var(--dur-1, .15s) ease, border-color var(--dur-1, .15s) ease; }
    html[data-wa-drawer] .precs-wa-topo-x:hover{ color: var(--accent-red, #ef4444);
      border-color: var(--accent-red, #ef4444); }
    /* (1.1.37) NO PAINEL LATERAL O NEGÓCIO OCUPA A LINHA INTEIRA. Com `max-width: 42%` dentro
       de 440px ele sobrava com ~180px, e título e organização viravam "Prec…" e "Prefei…":
       um bloco que existe para IDENTIFICAR o negócio e não identificava nada. Aqui ele toma a
       linha, e as etiquetas descem para a linha seguinte pelo `flex-wrap` que a l2 já tem. */
    html[data-wa-drawer] .precs-wa-neg{ max-width: none; flex: 1 1 100%; }
    /* E o compositor cabe em UMA linha: no painel estreito o "MODELO" caía sozinho embaixo,
       comendo altura de thread para dizer o que um botão menor diz igual. */
    html[data-wa-drawer] .precs-wa-tpl-btn{ padding: 8px 10px; font-size: .66rem; }
    html[data-wa-drawer] .precs-wa-rodape{ padding: var(--space-3); gap: var(--space-1); }
    html[data-wa-drawer] .precs-wa-enviar{ width: 36px; height: 36px; }
    html[data-wa-drawer] .precs-wa-mic{ width: 34px; height: 34px; }
    /* A seta de voltar do cabeçalho do chat (a mesma da tela estreita) reaparece no painel:
       ele também mostra uma coisa por vez, e um segundo botão faria duas portas para a mesma
       sala. Ganha moldura para não ficar uma seta solta encostada no avatar. */
    html[data-wa-drawer] .precs-wa-voltar-lista{
      display: inline-flex; align-items: center; justify-content: center;
      width: 30px; height: 30px; flex: 0 0 auto; border-radius: var(--radius-pill);
      border: 1px solid var(--border-color); color: var(--text-secondary); }
    html[data-wa-drawer] .precs-wa-voltar-lista:hover{ color: var(--precs-gold, #B49552);
      border-color: color-mix(in srgb, var(--precs-gold, #B49552) 50%, var(--border-color)); }

    /* ====================================================================
       (1.1.23) O NEGÓCIO E AS ETIQUETAS NO CABEÇALHO DA CONVERSA.
       "Só NEGÓCIO em dourado é muito pouco" (Julia, 25/08/2026): o selo virou um bloco que
       IDENTIFICA o negócio e leva ao Pipedrive, e ao lado dele mora o etiquetador.
       ==================================================================== */
    /* (22/09/2026) BASE ZERO, TETO EM PIXEL. Com `flex-basis: auto` o bloco entrava na conta da
       fila com a largura do CONTEÚDO (título de processo + organização por extenso), e a fila
       com `flex-wrap` o jogava para uma segunda linha antes de deixá-lo encolher. Base 0 faz
       ele caber no que sobrar e crescer até o teto; o texto dentro já tem reticências. */
    .precs-wa-neg{ display: inline-flex; align-items: center; gap: var(--space-2);
      flex: 1 1 0; min-width: 0; max-width: 340px;
      padding: var(--space-1) var(--space-2); border-radius: var(--radius-inner);
      background: var(--bg-tertiary); border: 1px solid var(--border-color); }
    /* (1.1.38) O quadradinho com a letra P saiu; quem entra é o logo de verdade, que já vem
       com o próprio fundo verde da marca. */
    .precs-wa-neg .precs-pipe-logo{ flex: 0 0 auto; }
    .precs-wa-neg-txt{ display: flex; flex-direction: column; min-width: 0; line-height: 1.25; }
    .precs-wa-neg-txt b{ font-size: .76rem; color: var(--text-primary); cursor: pointer;
      overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
    .precs-wa-neg-txt i{ font-style: normal; font-size: .66rem; color: var(--text-muted);
      overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
    /* (1.1.38) Era DOURADO, e dizia a coisa errada: ouro é a cor da PRECS, e este botão leva
       para FORA, para o Pipedrive. Agora usa o verde da marca, igual ao `.precs-pipe-btn` do
       resto do painel — que é o que a equipe já lê como "isto me leva para lá". */
    .precs-wa-neg-abrir{ flex: 0 0 auto; display: inline-flex; align-items: center; gap: 4px;
      font-family: 'Manrope', 'Poppins', sans-serif;
      font-size: .66rem; font-weight: 700; text-decoration: none; white-space: nowrap;
      color: #fff; border: 1px solid transparent;
      background: linear-gradient(90deg, var(--pipe-verde, #017737), var(--pipe-verde-2, #0B8A4A));
      border-radius: var(--radius-pill); padding: 3px var(--space-2);
      transition: filter var(--dur-1, .15s) ease; }
    .precs-wa-neg-abrir:hover{ filter: brightness(1.12); }
    .precs-wa-neg-abrir:focus-visible{ outline: 2px solid var(--precs-gold, #B49552);
      outline-offset: 2px; }
    @media (prefers-reduced-motion: reduce){ .precs-wa-neg-abrir{ transition: none; } }
    /* O selo compacto da lista (só diz que a conversa TEM negócio).
       (1.1.39) DEIXOU DE ESCREVER A PALAVRA. Era "NEGÓCIO" em caixa alta ao lado do nome, e
       em nome comprido a linha inteira ia embora. Agora carrega o logotipo do Pipedrive —
       o MESMO `precsPipeLogoHTML` do bloco do negócio no cabeçalho, que é o paralelo que o
       Pedro apontou em 28/08/2026 ("substituir essa palavra feia por um ícone do pipe, que é
       o que se fez na conversa selecionada"). O contorno dourado fica: é ele que diz que o
       selo pertence à casa e não é um adorno do Pipedrive. */
    /* (1.1.39 · 2ª volta) E ganhou o NÚMERO, mais o clique que abre o negócio.
       O vocabulário é o mesmo da pílula `p #148280` de "Últimos leads trabalhados" na tela de
       ocioso — mesma cor, mesmo formato, mesmo gesto. Duas telas que falam de negócio passam
       a falar igual, e o operador economiza os dois cliques de abrir a conversa só para
       clicar em "abrir no Pipe" lá dentro.
       O contorno dourado saiu: com o verde do Pipedrive preenchendo, o ouro por fora virava
       uma segunda moldura disputando a atenção com o nome do credor ao lado. */
    .precs-wa-neg-selo{ margin-left: var(--space-2); flex: 0 0 auto;
      display: inline-flex; align-items: center; gap: 4px; cursor: pointer;
      padding: 1px 6px 1px 3px; border-radius: var(--radius-pill); line-height: 1;
      background: color-mix(in srgb, var(--pipe-verde, #017737) 16%, var(--bg-secondary));
      border: 1px solid color-mix(in srgb, var(--pipe-verde-2, #0B8A4A) 45%, transparent);
      transition: background var(--dur-1, .15s) ease, border-color var(--dur-1, .15s) ease,
        transform var(--dur-1, .15s) ease; }
    .precs-wa-neg-selo:hover{ transform: translateY(-1px);
      background: color-mix(in srgb, var(--pipe-verde, #017737) 26%, var(--bg-secondary));
      border-color: var(--pipe-verde-2, #0B8A4A); }
    .precs-wa-neg-selo .precs-pipe-logo{ display: block; }
    .precs-wa-neg-selo i{ font-style: normal;
      font-family: 'JetBrains Mono', monospace; font-size: .6rem; font-weight: 700;
      color: color-mix(in srgb, var(--pipe-verde-2, #0B8A4A) 45%, var(--text-primary)); }
    @media (prefers-reduced-motion: reduce){
      .precs-wa-neg-selo{ transition: none; }
      .precs-wa-neg-selo:hover{ transform: none; } }

    /* ====================================================================== */
    /* AS ETIQUETAS — catálogo fixo (ver PRECS_WA_ETIQUETAS no app.js).         */
    /* ====================================================================== */
    /* (1.1.38 · 2ª volta) A FONTE DAS ETIQUETAS. "a fonte delas parece que é feia, parece
       estar em Arial" (Pedro, 28/08/2026) — e estava mesmo: o chip não declarava
       `font-family`, então herdava a do documento em vez da tipografia da casa.

       (1.1.39) E A COR DA TINTA DEIXOU DE SER PRETO OU BRANCO.
       O chip era a cor do catálogo chapada, com a tinta escolhida em JS por
       `precsCorTextoContraste`: preto sobre o dourado e o verde, branco sobre o vermelho e o
       índigo. Cada chip passava no contraste sozinho e mesmo assim o conjunto lia mal —
       "algumas etiquetas têm fonte preta, outras branca" (28/08/2026). Oito pílulas de cor
       cheia embaixo de um nome é uma faixa de semáforo, não uma linha de lista.

       Agora ele é LAVADO: a cor entra a 14% no fundo, cheia a 42% na borda, e o texto é a
       própria cor puxada para o lado de `--text-primary`. Três consequências:
         · a tinta de todos os chips passa a ser da mesma família (some a alternância);
         · como `--text-primary` é escuro no Claro e claro nos escuros, a MESMA fórmula
           escurece a tinta num tema e clareia no outro — sem regra por tema;
         · e, por ser CSS, ela acompanha a troca de tema SOZINHA. O valor cravado no `style=`
           pelo JS só mudaria na próxima repintura, e trocar de tema não repinta nada.
       Os pares medidos por `teste-contraste-render.js` (sondas `wa-etiq-*`) são a prova de
       que a conta fecha em AA nos cinco temas — o `color-mix` não garante isso sozinho, e a
       primeira tentativa provou o ponto: com a tinta a 62% da cor, o dourado e o cinza
       reprovavam nos três temas claros por muito pouco (4,13 e 4,12 contra os 4,5 exigidos).
       A 50% o pior par mede 4,87 no claro clássico e 7,03 no PRECS. Mexer neste número sem
       rodar aquele teste é apostar.

       O fundo mistura com `--bg-secondary` e não com `transparent` de propósito: o chip da
       lista fica sobre a linha da conversa e o do cabeçalho sobre a barra, duas superfícies
       diferentes, e um fundo translúcido mudaria de cor entre os dois. */
    .precs-wa-etiq{ display: inline-flex; align-items: center; min-height: 19px;
      padding: 2px 9px;
      border-radius: var(--radius-pill);
      font-family: 'Manrope', 'Poppins', sans-serif;
      font-size: .68rem; font-weight: 700; letter-spacing: .01em;
      white-space: nowrap;
      background: color-mix(in srgb, var(--etq) 14%, var(--bg-secondary));
      border: 1px solid color-mix(in srgb, var(--etq) 42%, transparent);
      color: color-mix(in srgb, var(--etq) 50%, var(--text-primary));
      transition: border-color var(--dur-1, .15s) ease, transform var(--dur-1, .15s) ease,
        box-shadow var(--dur-1, .15s) ease; }
    .precs-wa-etiq.mini{ font-size: .62rem; padding: 1px 8px; min-height: 17px; }
    /* (1.1.39) O hover que faltava: "ao passar o mouse em cima das etiquetas poderia ter
       alguma animação de hover ou levitar" (28/08/2026). Levita 1px e a borda fecha. */
    .precs-wa-etiq:hover{ transform: translateY(-1px);
      border-color: color-mix(in srgb, var(--etq) 70%, transparent);
      box-shadow: 0 2px 6px -2px color-mix(in srgb, var(--etq) 55%, transparent); }
    /* ======================================================================
       (1.1.39) A ANIMAÇÃO DE ENTRADA SAIU DA REGRA BASE — É O CONSERTO DO "TICA TUDO".

       Ela estava em `.precs-wa-etiq`, e `animation` dispara toda vez que o nó NASCE. Como a
       lista de conversas era reescrita por `innerHTML` inteiro a cada mudança visível (trocar
       de conversa, etiquetar qualquer conversa, mensagem nova em qualquer uma), todas as
       etiquetas de todas as linhas reencenavam o "nasce encolhendo" ao mesmo tempo: "quando
       troco de conversa minhas etiquetas ficam ticando... tica tudo na verdade" (28/08/2026).

       O conserto tem duas metades e as duas são necessárias. Aqui, a animação passa a exigir
       a classe `entrando`. No JS, a lista deixou de ser refeita inteira (assinatura por linha,
       ver `precsWaPintarConversas`) e só os chips realmente novos recebem a classe (ver
       `precsWaTopoChips`). Sem a primeira metade, a segunda ainda deixaria o chip do cabeçalho
       piscando; sem a segunda, a primeira mataria a animação onde ela é boa.

       O chip da lista (`.mini`) nunca anima: naquela coluna a etiqueta é referência de leitura,
       não retorno de um gesto que a pessoa acabou de fazer. */
    /* (1.1.41) O ícone do chip. `1em` e não pixel: o chip existe em dois corpos (.68rem no
       cabeçalho e .62rem no mini, embora o mini não desenhe ícone), e um tamanho cravado
       ficaria desproporcional num dos dois. `currentColor` faz o desenho herdar a MESMA tinta
       lavada do rótulo — a que o teste-contraste-render mede — em vez de abrir uma segunda
       conta de cor que ninguém audita. */
    .precs-wa-etiq-ico{ flex: 0 0 auto; display: inline-flex; align-items: center;
      justify-content: center; width: 1em; height: 1em; margin-right: 3px; }
    /* No `mini` da lista o desenho encolhe e cola mais no rótulo: são dois chips disputando
       245px com o nome e a prévia, e cada pixel a mais empurra o "+N" para fora do recorte. */
    .precs-wa-etiq.mini .precs-wa-etiq-ico{ width: .95em; height: .95em; margin-right: 2px; }
    .precs-wa-etiq-ico svg{ display: block; width: 100%; height: 100%; }
    .precs-wa-etiq.entrando{ animation: precsWaEtiqEntra 180ms var(--ease-1); }
    @keyframes precsWaEtiqEntra{
      from{ opacity: 0; transform: scale(.86); }
      to{ opacity: 1; transform: none; } }
    @media (prefers-reduced-motion: reduce){
      .precs-wa-etiq{ transition: none; }
      .precs-wa-etiq.entrando{ animation: none; }
      .precs-wa-etiq:hover{ transform: none; box-shadow: none; } }
    .precs-wa-topo-etqs{ display: flex; flex-wrap: wrap; gap: 4px; min-width: 0; }
    .precs-wa-topo-etqs[hidden]{ display: none; }
    /* (1.1.40) UMA FILA, SEMPRE — é isto que dá altura previsível à coluna.
       O teto de duas etiquetas em JS não basta sozinho: a largura depende de QUAIS rótulos
       são, e as duas mais largas do catálogo somam 257px num miolo de 245. Quem garante a
       linha única é o `nowrap` com recorte; o "+N" fica FORA da fila recortada, senão ele
       seria cortado junto com aquilo que está contando. */
    .precs-wa-conv-etqs{ display: flex; flex-wrap: nowrap; align-items: center;
      gap: 3px; margin-top: 3px; min-width: 0; }
    .precs-wa-etqs-fila{ display: flex; flex-wrap: nowrap; gap: 3px;
      overflow: hidden; min-width: 0; flex: 0 1 auto; }
    /* (1.1.37) O ETIQUETADOR DEIXOU DE SER FANTASMA. Ele era um círculo de 32px com o emoji
       🏷️, transparente, empurrado para a borda: "o de etiquetar é muito inexistente"
       (27/08/2026). Agora tem ícone em SVG, rótulo escrito, e acende quando o seletor está
       aberto. O rótulo some por conta própria quando a largura não dá. */
    .precs-wa-etiq-btn{ flex: 0 0 auto; height: 30px; cursor: pointer;
      display: inline-flex; align-items: center; gap: 5px;
      padding: 0 var(--space-3);
      background: transparent; border: 1px solid var(--border-color);
      border-radius: var(--radius-pill); color: var(--text-secondary);
      font-family: 'Manrope', 'Poppins', sans-serif; font-size: .74rem; font-weight: 700;
      transition: color var(--dur-1, .15s) ease, border-color var(--dur-1, .15s) ease,
        background var(--dur-1, .15s) ease; }
    .precs-wa-etiq-btn:hover{ color: var(--precs-gold, #B49552);
      border-color: var(--precs-gold, #B49552); }
    .precs-wa-etiq-btn.on{ color: var(--precs-gold-title, var(--precs-gold, #B49552));
      border-color: var(--precs-gold, #B49552);
      background: color-mix(in srgb, var(--precs-gold, #B49552) 12%, transparent); }
    .precs-wa-etiq-btn svg{ flex: 0 0 auto; }
    @media (max-width: 1120px){ .precs-wa-etiq-btn-txt{ display: none; } }
    html[data-wa-drawer] .precs-wa-etiq-btn-txt{ display: none; }
    html[data-wa-drawer] .precs-wa-etiq-btn{ width: 32px; padding: 0; justify-content: center; }
    /* ======================================================================
       (1.1.39) A ÂNCORA DO POPOVER É O BOTÃO, NÃO O CABEÇALHO.

       Os dois popovers do topo eram `position:absolute` presos ao `right` de
       `.precs-wa-chat-topo`. Só que os botões que os abrem ficam no COMEÇO da linha: "os
       botões ficam na esquerda e os cards de seleção e escrever a lead vão pro outro lado da
       tela, não faz sentido né" (Pedro, 28/08/2026). E, presos ao mesmo canto com 4px de
       diferença de `right`, quando os dois abriam juntos eles se cobriam.

       Agora cada botão vem embrulhado numa âncora, e o popover é `left: 0` DELA. `.pop-esq`
       (posta por `precsWaPopAjustar` depois de medir) vira para a direita quando a âncora
       está perto da borda da janela — o caso dos 440px do painel lateral. */
    .precs-wa-anc{ position: relative; display: inline-flex; align-items: center;
      min-width: 0; max-width: 100%; }
    /* A âncora entrou ENTRE a linha e o que ela embrulha, então ela precisa herdar o papel de
       item flexível — senão o bloco do negócio, que dimensiona por `max-width: 42%`, passa a
       calcular 42% de uma âncora que já encolheu ao mínimo, e o título vira duas letras
       empilhadas. Foi o que apareceu no primeiro print de conferência da 1.1.39. */
    .precs-wa-topo-l2 > .precs-wa-anc{ flex: 0 1 auto; min-width: 0; max-width: 42%; }
    .precs-wa-anc > .precs-wa-neg{ max-width: 100%; width: 100%; }
    html[data-wa-drawer] .precs-wa-topo-l2 > .precs-wa-anc{ max-width: none; flex: 1 1 100%; }
    /* O etiquetador fica COLADO no nome, e não jogado na borda oposta do cabeçalho: "podemos
       melhorar levando pro lado do nome" (Pedro, 28/08/2026). Para isso o bloco de identidade
       para de esticar e quem empurra o resto para a direita é a margem da âncora. */
    .precs-wa-topo-l1 > .precs-wa-anc{ flex: 0 0 auto; margin-right: auto; }
    /* ======================================================================
       (1.1.41) O LEMBRETE DE RETORNO: o botão do cabeçalho, o popover e o chip da lista.

       O botão veste o `.precs-wa-etiq-btn` porque é o mesmo tipo de controle, na mesma linha,
       ao lado. Três estados que se somam:
         • `.tem`    — há lembrete marcado, e o rótulo do botão vira a hora;
         • `.venceu` — a hora chegou. Vermelho, e é a única coisa desta tela que grita: a fila
                       do dia é feita dos vencidos, e um lembrete que passou sem ninguém ver
                       não serviu para nada;
         • `.on`     — o popover está aberto (herdado do etiquetador).
       O vermelho usa `--accent-red` como FORMA (fio e fundo lavado) e a variante de texto na
       tinta, pela regra da casa: acento cru como texto reprova AA no tema claro. */
    .precs-wa-lemb-btn.tem{
      border-color: color-mix(in srgb, var(--precs-gold-forma, #B49552) 42%, transparent);
      color: var(--precs-gold-title, var(--precs-gold, #B49552));
    }
    .precs-wa-lemb-btn.venceu{
      border-color: color-mix(in srgb, var(--accent-red, #EF4444) 55%, transparent);
      background: color-mix(in srgb, var(--accent-red, #EF4444) 12%, transparent);
      color: var(--accent-red-text, var(--accent-red, #EF4444));
    }
    .precs-wa-lemb-pop{
      position: absolute; top: calc(100% + 6px); right: 0; z-index: 30;
      min-width: 214px;
      background: var(--bg-secondary);
      border: 1px solid var(--border-color);
      border-radius: var(--radius-card);
      box-shadow: var(--shadow-lg);
      padding: 4px;
      animation: precsWaPopEntra 140ms var(--ease-1);
    }
    @media (prefers-reduced-motion: reduce){ .precs-wa-lemb-pop{ animation: none; } }
    .precs-wa-lemb-tit{
      padding: 6px 8px 5px; font-family: 'Manrope', 'Poppins', sans-serif;
      font-size: .64rem; font-weight: 700; color: var(--text-muted);
      text-transform: uppercase; letter-spacing: var(--ls-caps, .04em);
    }
    /* Cada atalho mostra o rótulo E a hora exata que ele vai gravar. Sem a hora, "em 3 horas"
       obriga a pessoa a fazer a conta de cabeça para saber se cai depois do expediente. */
    .precs-wa-lemb-op{
      display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-3);
      width: 100%; padding: 7px 8px; border: 0; border-radius: var(--radius-inner);
      background: transparent; color: var(--text-secondary);
      font-family: inherit; font-size: .78rem; text-align: left; cursor: pointer;
      transition: background var(--dur-1, .15s) ease, color var(--dur-1, .15s) ease;
    }
    .precs-wa-lemb-op:hover{ background: var(--bg-tertiary); color: var(--text-primary); }
    .precs-wa-lemb-op b{ font-weight: 600; }
    .precs-wa-lemb-op i{ font-style: normal; font-family: 'JetBrains Mono', monospace;
      font-size: .68rem; color: var(--text-muted); }
    .precs-wa-lemb-op.tirar{
      margin-top: 3px; border-top: 1px solid var(--border-color); border-radius: 0;
      color: var(--accent-red-text, var(--accent-red, #EF4444));
    }
    @media (prefers-reduced-motion: reduce){ .precs-wa-lemb-op{ transition: none; } }
    /* O chip da LINHA da lista. Ele vem antes das etiquetas porque responde outra pergunta:
       as etiquetas dizem em que fase a conversa está, o lembrete diz se ela é para AGORA. */
    .precs-wa-conv-lemb{
      /* `align-self` porque o pai (`.precs-wa-conv-meio`) e uma coluna flex: sem isto o
         `inline-flex` do chip nao impede o ESTICAMENTO, e a pilula atravessa a linha inteira
         como se fosse uma barra. */
      align-self: flex-start;
      display: inline-flex; align-items: center; gap: 3px;
      margin-right: 4px; padding: 1px 6px 1px 4px;
      border-radius: var(--radius-pill, 999px);
      border: 1px solid color-mix(in srgb, var(--text-primary) 16%, transparent);
      font-family: 'Manrope', 'Poppins', sans-serif; font-size: .62rem; font-weight: 700;
      color: var(--text-muted); white-space: nowrap;
    }
    .precs-wa-conv-lemb svg{ width: 10px; height: 10px; }
    .precs-wa-conv-lemb.venceu{
      border-color: color-mix(in srgb, var(--accent-red, #EF4444) 50%, transparent);
      background: color-mix(in srgb, var(--accent-red, #EF4444) 13%, var(--bg-secondary));
      color: var(--accent-red-text, var(--accent-red, #EF4444));
    }
    .precs-wa-etiq-pop{ position: absolute; top: calc(100% + 6px); left: 0;
      z-index: 40; display: flex; flex-direction: column; gap: 2px; padding: var(--space-2);
      min-width: 220px; background: var(--bg-secondary);
      border: 1px solid var(--border-color); border-radius: var(--radius-card);
      box-shadow: var(--shadow-lg);
      animation: precsWaPopEntra 140ms var(--ease-1); }
    .precs-wa-etiq-pop.pop-esq{ left: auto; right: 0; }
    @keyframes precsWaPopEntra{
      from{ opacity: 0; transform: translateY(-4px); }
      to{ opacity: 1; transform: none; } }
    /* (1.1.38 · 2ª volta) "a animação de colocar etiqueta é muito dura, poderia ter animação
       ao selecionar, hover algo do tipo". O seletor não tinha transição nenhuma: a linha
       trocava de estado num quadro. Entrou o hover que desliza e o marcado com a cor da
       própria etiqueta no fundo.

       (1.1.39) E SÓ AGORA ISSO SE VÊ. A transição já estava escrita e mesmo assim o que
       aparecia era um salto — "a animação ficou ruim de só crescer a bola" (28/08/2026). A
       causa não era o CSS: `precsWaEtiquetaAlternar` repintava o cabeçalho inteiro por
       `innerHTML`, e transição não roda em nó que acabou de nascer (ele já vem no estado
       final; não há valor anterior de onde interpolar). Só `animation` sobrevivia a isso, e
       era por isso que o ✓ animava e o resto não. O toggle agora mexe no nó vivo.

       Junto, a marcação ganhou corpo: a linha inteira se pinta com a cor, o ✓ desliza da
       direita e a bolinha cresce com anel — três sinais em vez de um. */
    .precs-wa-etiq-op{ display: flex; align-items: center; gap: var(--space-2); cursor: pointer;
      padding: var(--space-2); border-radius: var(--radius-inner);
      background: transparent; border: 1px solid transparent; text-align: left;
      font-family: 'Manrope', 'Poppins', sans-serif; font-size: .78rem; font-weight: 600;
      color: var(--text-secondary);
      transition: background var(--dur-2, .2s) ease, color var(--dur-1, .15s) ease,
        border-color var(--dur-2, .2s) ease, transform var(--dur-1, .15s) ease; }
    .precs-wa-etiq-op:hover{ background: var(--bg-tertiary); color: var(--text-primary);
      transform: translateX(2px); }
    .precs-wa-etiq-op:active{ transform: translateX(2px) scale(.98); }
    .precs-wa-etiq-op.on{ color: var(--text-primary);
      border-color: color-mix(in srgb, var(--etq) 55%, transparent);
      background: color-mix(in srgb, var(--etq) 16%, transparent); }
    .precs-wa-etiq-op-nome{ min-width: 0; }
    .precs-wa-etiq-bola{ width: 10px; height: 10px; flex: 0 0 auto; border-radius: 50%;
      background: var(--etq);
      transition: transform var(--dur-2, .2s) var(--ease-1),
        box-shadow var(--dur-2, .2s) ease; }
    .precs-wa-etiq-op.on .precs-wa-etiq-bola{ transform: scale(1.35);
      box-shadow: 0 0 0 3px color-mix(in srgb, var(--etq) 28%, transparent); }
    /* O ✓ existe SEMPRE no HTML e some por opacidade, e não por presença: um nó que só nasce
       quando a etiqueta acende nunca teria de onde deslizar. */
    .precs-wa-etiq-ok{ margin-left: auto; color: var(--etq); font-weight: 700;
      opacity: 0; transform: translateX(4px);
      transition: opacity var(--dur-2, .2s) ease,
        transform var(--dur-2, .2s) var(--ease-1); }
    .precs-wa-etiq-op.on .precs-wa-etiq-ok{ opacity: 1; transform: none; }
    @media (prefers-reduced-motion: reduce){
      .precs-wa-etiq-op, .precs-wa-etiq-bola, .precs-wa-etiq-ok{ transition: none; }
      .precs-wa-etiq-op:hover, .precs-wa-etiq-op:active{ transform: none; }
      .precs-wa-etiq-pop{ animation: none; }
      .precs-wa-etiq-ok{ transform: none; } }
    /* O cabeçalho continua `relative` porque o `overflow: visible` do painel lateral depende
       dele; a ancoragem dos popovers passou para `.precs-wa-anc`. */
    .precs-wa-chat-topo{ position: relative; }

    /* ======================================================================
       (1.1.40) O ACABAMENTO QUE FALTAVA, num bloco só.
       Nove controles do modo não tinham `:focus-visible` e sete transições não tinham guarda
       de `prefers-reduced-motion`. Nenhum deles é defeito que apareça num print — aparecem
       para quem navega por teclado e para quem marcou "reduzir movimento" no sistema, que são
       exatamente as pessoas que ninguém vê testando. O padrão do anel já estava estabelecido
       (o botão de enviar, o de conversa nova, o modal de modelos); o que faltava era aplicá-lo
       nos que ficaram de fora, um de cada vez, conforme o modo cresceu. */
    .precs-wa-clip:focus-visible,
    .precs-wa-mic:focus-visible,
    .precs-wa-tpl-btn:focus-visible,
    .precs-wa-anexo-enviar:focus-visible,
    .precs-wa-anexo-x:focus-visible,
    .precs-wa-nova-ok:focus-visible,
    .precs-wa-espelho-sel:focus-visible,
    .precs-wa-tpl-voltar:focus-visible,
    .precs-wa-reagir-e:focus-visible,
    .precs-wa-reagir-x:focus-visible,
    .precs-wa-visor-nav:focus-visible,
    .precs-wa-neg-selo:focus-visible{
      outline: 2px solid var(--precs-gold-hi, #FFC95B); outline-offset: 2px; }

    /* A ação primária da prévia de anexo não tinha hover nenhum — o botão que MANDA o
       arquivo para o credor era o único do rodapé sem retorno ao passar o mouse. */
    .precs-wa-anexo-enviar{ transition: filter var(--dur-1, .15s) ease; }
    .precs-wa-anexo-enviar:hover{ filter: brightness(1.1); }
    .precs-wa-espelho-sel:hover{ border-color: var(--precs-gold-forma, #B49552); }

    @media (prefers-reduced-motion: reduce){
      .precs-wa-clip, .precs-wa-mic, .precs-wa-tpl-btn, .precs-wa-tpl-item,
      .precs-wa-tpl-enviar, .precs-wa-nova-ok, .precs-wa-vinc-btn,
      .precs-wa-anexo-enviar{ transition: none; }
    }

    /* Fonte DECLARADA onde ela era herdada do documento. O modo inteiro fala Manrope nos
       rótulos e Poppins no corpo; estes cinco falavam o que sobrasse. */
    .precs-wa-24h{ font-family: 'Poppins', sans-serif; }
    .precs-wa-vazio b{ font-family: 'Montserrat', sans-serif; }
    .precs-wa-vazio span{ font-family: 'Poppins', sans-serif; }
    .precs-wa-grav-txt{ font-family: 'Manrope', 'Poppins', sans-serif; }
    .precs-wa-espelho-rotulo{ font-family: 'Poppins', sans-serif; }
    .precs-wa-espelho-sel{ font-family: 'Poppins', sans-serif; }
    .precs-wa-tpl-head{ font-family: 'Montserrat', sans-serif; }

    /* `cursor: help` promete um tooltip. Nos chips de mídia em CARREGAMENTO e na faixa do
       espelho não existe `data-tipv` nenhum, e o cursor apontava para o nada. */
    .precs-wa-midia.carregando, .precs-wa-espelho .precs-wa-24h{ cursor: default; }

    /* O FILTRO POR ETIQUETA, no topo da lista: só existe quando alguma conversa tem etiqueta. */
    .precs-wa-etq-filtro{ display: flex; flex-wrap: wrap; gap: 4px;
      padding: var(--space-2) var(--space-3); border-bottom: 1px solid var(--border-color); }
    .precs-wa-etq-filtro[hidden]{ display: none; }
    /* (1.1.37) O CHIP DE FILTRO DESLIGADO ERA O QUE SUMIA NOS TEMAS CLAROS.
       O chip APLICADO sempre esteve certo: cor da etiqueta no fundo e tinta calculada por
       contraste (precsCorTextoContraste). Quem reprovava era este, o do filtro em repouso:
       `--text-muted` sobre fundo transparente, com a borda a 45% de opacidade. No PRECS Claro
       isso é cinza pálido sobre branco, e foi o "em alguns temas as etiquetas ficam
       ilegíveis" de 27/08/2026.
       Três mudanças na mesma direção: o texto sobe para `--text-secondary` (que é tokenizado
       para passar em todos os temas), o fundo ganha uma lavagem da PRÓPRIA cor da etiqueta —
       assim o chip continua dizendo de qual etiqueta é sem depender só da borda — e a borda
       fecha em 60%.

       (1.1.39) E O LIGADO DEIXOU DE SER SÓLIDO. Ele era cor cheia com a tinta calculada em JS,
       o que fazia esta faixa ter DUAS gramáticas ao mesmo tempo: os desligados lavados e o
       ligado chapado, com preto ou branco por cima conforme a cor. Agora o ligado é o mesmo
       chip com mais peso — fundo mais forte, borda cheia e a tinta da mesma fórmula do chip da
       conversa. Filtro e etiqueta passaram a ser visivelmente a mesma coisa, que é o que eles
       são. Com isso `--etq-txt` (e `precsCorTextoContraste` no modo WhatsApp) deixa de ter
       consumidor; a função continua viva para as etiquetas do Pipedrive, que são outro
       assunto e seguem sólidas. */
    .precs-wa-etq-f{ display: inline-flex; align-items: center; gap: 4px; cursor: pointer;
      padding: 1px 8px; border-radius: var(--radius-pill); font-size: .63rem; font-weight: 700;
      font-family: 'Manrope', 'Poppins', sans-serif;
      background: color-mix(in srgb, var(--etq) 12%, var(--bg-secondary));
      color: var(--text-secondary);
      border: 1px solid color-mix(in srgb, var(--etq) 45%, transparent);
      transition: color var(--dur-1, .15s) ease, background var(--dur-1, .15s) ease,
        border-color var(--dur-1, .15s) ease, transform var(--dur-1, .15s) ease; }
    .precs-wa-etq-f:hover{ color: var(--text-primary); transform: translateY(-1px);
      background: color-mix(in srgb, var(--etq) 22%, var(--bg-secondary));
      border-color: color-mix(in srgb, var(--etq) 70%, transparent); }
    /* (1.1.41) "Limpar" veste o mesmo botão da barra, sem a cor de etiqueta nenhuma: ele não
       É uma etiqueta, e pintá-lo com `--etq` sugeriria uma nona que ninguém pode aplicar.
       O ✕ vem do mesmo `PRECS_WA_ICO.fechar` do resto do modo. */
    .precs-wa-etq-f.limpar{
      --etq: var(--text-muted);
      gap: 3px; font-weight: 600;
      color: var(--text-secondary);
      border-style: dashed;
    }
    .precs-wa-etq-f.limpar:hover{ color: var(--text-primary); }
    /* (1.1.41) O chip sem ninguem em vista. Ele fica na barra (esconder faria a faixa mudar de
       altura a cada clique, e a lista abaixo pularia junto) e para de responder. */
    .precs-wa-etq-f.morto{ opacity: .38; cursor: not-allowed; }
    .precs-wa-etq-f.morto:hover{ transform: none; }
    .precs-wa-etq-f.limpar svg{ width: 11px; height: 11px; }
    .precs-wa-etq-f.on{
      background: color-mix(in srgb, var(--etq) 30%, var(--bg-secondary));
      border-color: var(--etq);
      color: color-mix(in srgb, var(--etq) 55%, var(--text-primary)); }
    .precs-wa-etq-f i{ font-style: normal; opacity: .75; }
    @media (prefers-reduced-motion: reduce){
      .precs-wa-etq-f{ transition: none; }
      .precs-wa-etq-f:hover{ transform: none; } }

    /* (1.1.23) GRAVAÇÃO DE ÁUDIO: o compositor dá lugar à faixa enquanto o microfone está
       aberto — com o campo de texto ali, digitar e mandar por engano durante a gravação é
       questão de tempo. */
    /* O botão do seletor de emoji veste o mesmo do clipe e do microfone: ele é um controle do
       compositor, e três formas diferentes na mesma barra seriam três coisas para o olho
       separar antes de escolher. */
    .precs-wa-emoji-btn{
      flex: 0 0 auto; width: 34px; height: 34px; padding: 0;
      display: inline-flex; align-items: center; justify-content: center;
      border: 0; border-radius: 50%; background: transparent;
      color: var(--text-muted); cursor: pointer;
      transition: background var(--dur-1, .15s) ease, color var(--dur-1, .15s) ease;
    }
    .precs-wa-emoji-btn:hover{ background: var(--bg-tertiary); color: var(--text-primary); }
    .precs-wa-emoji-btn:focus-visible{ outline: var(--focus-ring-largura) solid var(--focus-ring-cor);
      outline-offset: 2px; }
    .precs-wa-mic{ flex: 0 0 auto; display: inline-flex; align-items: center;
      justify-content: center; width: 38px; height: 38px; background: transparent;
      border: 1px solid var(--border-color); border-radius: var(--radius-pill);
      color: var(--text-secondary); cursor: pointer;
      transition: color var(--dur-1) ease, border-color var(--dur-1) ease; }
    .precs-wa-mic:hover{ color: var(--precs-gold, #B49552);
      border-color: color-mix(in srgb, var(--precs-gold, #B49552) 50%, var(--border-color)); }
    .precs-wa-grav{ flex: 1 1 100%; display: flex; align-items: center; gap: var(--space-2);
      padding: var(--space-2) var(--space-3); border-radius: var(--radius-card);
      background: var(--bg-tertiary); border: 1px solid var(--border-color); }
    .precs-wa-grav-dot{ width: 10px; height: 10px; border-radius: 50%; flex: 0 0 auto;
      background: var(--accent-red, #ef4444); animation: precsAoVivoDot 1.3s ease-in-out infinite; }
    @media (prefers-reduced-motion: reduce){ .precs-wa-grav-dot{ animation: none; } }
    .precs-wa-grav-txt{ font-size: .8rem; color: var(--text-primary); font-weight: 600; }
    .precs-wa-grav-t{ font-family: 'JetBrains Mono', monospace; font-size: .82rem;
      color: var(--text-secondary); }
    /* (1.1.38 · 2ª volta) OS DOIS BOTÕES DA GRAVAÇÃO. Eram duas pílulas de contorno cinza com
       texto minúsculo, iguais entre si — e elas fazem coisas opostas: uma joga fora o áudio, a
       outra o transforma em mensagem. Botão que descarta e botão que confirma não podem ter o
       mesmo peso visual.
       Agora: "descartar" é fantasma que fica vermelho ao passar o mouse (destrutivo se anuncia
       antes de ser clicado), e "parar" é sólido no ouro, com o quadradinho de parar que a
       linguagem de gravação usa em toda parte. */
    .precs-wa-grav-x, .precs-wa-grav-ok{ cursor: pointer; display: inline-flex;
      align-items: center; gap: 6px; height: 30px;
      font-family: 'Manrope', 'Poppins', sans-serif;
      font-size: .72rem; font-weight: 700; padding: 0 var(--space-3);
      border-radius: var(--radius-pill); border: 1px solid var(--border-color);
      background: transparent; color: var(--text-secondary);
      transition: color var(--dur-1, .15s) ease, border-color var(--dur-1, .15s) ease,
        background var(--dur-1, .15s) ease, filter var(--dur-1, .15s) ease; }
    .precs-wa-grav-x{ margin-left: auto; }
    .precs-wa-grav-x:hover{ color: var(--accent-red, #ef4444);
      border-color: var(--accent-red, #ef4444);
      background: color-mix(in srgb, var(--accent-red, #ef4444) 10%, transparent); }
    .precs-wa-grav-ok{ background: var(--precs-gold-forma, #B49552);
      border-color: var(--precs-gold-forma, #B49552); color: var(--precs-wa-tinta-ouro, #131315); }
    .precs-wa-grav-ok:hover{ filter: brightness(1.1); }
    .precs-wa-grav-ok:focus-visible, .precs-wa-grav-x:focus-visible{
      outline: 2px solid var(--precs-gold-hi, #FFC95B); outline-offset: 2px; }
    /* O quadradinho de "parar" e o xis de "descartar", desenhados em CSS: dois ícones a mais
       no mapa de SVG por dois glifos geométricos não se justifica. */
    .precs-wa-grav-ok::before{ content: ''; width: 9px; height: 9px; border-radius: 2px;
      background: currentColor; }
    @media (prefers-reduced-motion: reduce){
      .precs-wa-grav-x, .precs-wa-grav-ok{ transition: none; } }
    /* (1.1.40) A prévia usa o MESMO player da bolha (`precsWaAudioHTML`), então aqui só
       sobra a largura. Os 220px fixos do `<audio>` nativo somados a "enviar" e ao ✕ deixavam
       menos de 70px para o nome do arquivo nos 440px do painel, e a linha não quebrava. */
    .precs-wa-anexo .precs-wa-som{ flex: 1 1 180px; width: auto; min-width: 140px; }

    /* (1.1.23) A PRÉVIA DO ANEXO (Ctrl+V, arrastar ou clipe): ocupa a linha inteira acima do
       compositor — daí o `flex-wrap` no rodapé — e exige um segundo gesto para sair. */
    .precs-wa-rodape{ flex-wrap: wrap; }
    .precs-wa-anexo{ flex: 1 0 100%; display: flex; align-items: center;
      gap: var(--space-2); padding: var(--space-2); margin-bottom: var(--space-2);
      background: var(--bg-tertiary); border: 1px solid var(--border-color);
      border-radius: var(--radius-inner); }
    .precs-wa-anexo-thumb{ width: 44px; height: 44px; object-fit: cover; flex: 0 0 auto;
      border-radius: var(--radius-sm); }
    /* (1.1.40) Era o emoji 📄, o último ícone não-SVG do rodapé. Agora carrega o mesmo
       desenho de documento da prévia da lista, num corpo que preenche o quadrado. */
    .precs-wa-anexo-ico{ width: 44px; height: 44px; flex: 0 0 auto; display: inline-flex;
      align-items: center; justify-content: center; color: var(--text-secondary);
      background: var(--bg-primary); border-radius: var(--radius-sm); }
    .precs-wa-anexo-ico .precs-wa-previa-ico{ width: 20px; height: 20px; margin: 0; }
    .precs-wa-anexo-nome{ flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column;
      font-size: .78rem; color: var(--text-primary); overflow: hidden;
      text-overflow: ellipsis; white-space: nowrap; }
    .precs-wa-anexo-nome i{ font-style: normal; font-size: .68rem; color: var(--text-muted); }
    .precs-wa-anexo-enviar{ flex: 0 0 auto; cursor: pointer;
      font-family: 'Manrope', 'Poppins', sans-serif; font-size: .72rem; font-weight: 700;
      padding: var(--space-1) var(--space-3); border-radius: var(--radius-pill);
      background: var(--precs-gold-forma, #B49552);
      border: 1px solid var(--precs-gold-forma, #B49552);
      color: var(--precs-wa-tinta-ouro, #131315); }
    .precs-wa-anexo-x{ flex: 0 0 auto; width: 26px; height: 26px; cursor: pointer;
      display: inline-flex; align-items: center; justify-content: center;
      background: transparent; border: 1px solid var(--border-color); border-radius: 50%;
      color: var(--text-muted); font-size: .72rem; padding: 0; }
    .precs-wa-anexo-x:hover{ color: var(--accent-red, #ef4444);
      border-color: var(--accent-red, #ef4444); }

    .precs-wa-clip{ flex: 0 0 auto; display: inline-flex; align-items: center;
      justify-content: center; width: 38px; height: 38px; background: transparent;
      border: 1px solid var(--border-color); border-radius: var(--radius-pill);
      color: var(--text-secondary); cursor: pointer;
      transition: color var(--dur-1) ease, border-color var(--dur-1) ease; }
    .precs-wa-clip:hover{ color: var(--precs-gold, #B49552);
      border-color: color-mix(in srgb, var(--precs-gold, #B49552) 50%, var(--border-color)); }
    /* (1.1.22) REAGIR: o botão vive ao lado da bolha e só aparece no hover (numa thread de 50
       mensagens, 50 carinhas fixas seriam ruído); o seletor é um popover único com os seis
       emojis do aplicativo, e o seu emoji atual ganha o anel dourado. */
    /* (1.1.39) O BOTÃO DE REAGIR DEIXOU DE SER UM EMOJI CINZA.
       Ele era a carinha crua com `filter: grayscale(1)` por cima — e o `grayscale` só existia
       porque emoji não aceita `currentColor`: ela nascia colorida e gritava mais que a
       mensagem. Remendo em cima de remendo, e o resultado era o que o Pedro descreveu em
       28/08/2026: "o botão de reagir a mensagem é muito feio, tipo feito em IA".
       Agora é SVG em `currentColor` (`PRECS_WA_ICO.reagir`), o último controle do modo a
       migrar. Junto com isso:
        · repouso a .35 em vez de 0 invisível — o operador precisa ao menos SUSPEITAR que dá
          para reagir; o botão que só existe no hover é um botão que ninguém descobre;
        · o hover acende no ouro, com fundo e borda, como todo controle do painel;
        · uma margem que o afasta do rabicho, que ele encostava (o rabicho sai 9px do balão). */
    .precs-wa-reagir-btn{ align-self: center; flex: 0 0 auto; width: 28px; height: 28px;
      margin: 0 6px; display: inline-flex; align-items: center; justify-content: center;
      background: transparent; border: 1px solid transparent; border-radius: 50%;
      cursor: pointer; opacity: .35; padding: 0; color: var(--text-muted);
      transition: opacity var(--dur-1) ease, border-color var(--dur-1) ease,
        background var(--dur-1) ease, color var(--dur-1) ease,
        transform var(--dur-1) ease; }
    .precs-wa-reagir-btn svg{ display: block; }
    .precs-wa-msg:hover .precs-wa-reagir-btn,
    .precs-wa-reagir-btn:focus-visible{ opacity: 1; color: var(--text-secondary); }
    .precs-wa-reagir-btn:hover{ opacity: 1;
      color: var(--precs-gold-title, var(--precs-gold, #B49552));
      border-color: color-mix(in srgb, var(--precs-gold, #B49552) 55%, transparent);
      background: color-mix(in srgb, var(--precs-gold, #B49552) 12%, transparent);
      transform: scale(1.08); }
    .precs-wa-reagir-btn:active{ transform: scale(.94); }
    @media (prefers-reduced-motion: reduce){
      .precs-wa-reagir-btn{ transition: none; }
      .precs-wa-reagir-btn:hover, .precs-wa-reagir-btn:active{ transform: none; } }
    .precs-wa-reagir-pop{ position: fixed; z-index: 10060; display: none;
      align-items: center; gap: 2px; padding: 6px 8px;
      background: var(--bg-secondary); border: 1px solid var(--border-color);
      border-radius: var(--radius-pill); box-shadow: var(--shadow-lg); }
    .precs-wa-reagir-pop.open{ display: inline-flex; }
    .precs-wa-reagir-e{ width: 36px; height: 36px; display: inline-flex; align-items: center;
      justify-content: center; background: transparent; border: 2px solid transparent;
      border-radius: 50%; font-size: 1.15rem; cursor: pointer; padding: 0;
      transition: transform var(--dur-1) ease; }
    .precs-wa-reagir-e:hover{ transform: scale(1.18); }
    .precs-wa-reagir-e.minha{ border-color: var(--precs-gold, #B49552); }
    @media (prefers-reduced-motion: reduce){ .precs-wa-reagir-e{ transition: none; } }
    .precs-wa-reagir-x{ width: 30px; height: 30px; display: inline-flex; align-items: center;
      justify-content: center; background: transparent; border: 1px solid var(--border-color);
      border-radius: 50%; color: var(--text-muted); cursor: pointer; font-size: .8rem;
      margin-left: 4px; }
    .precs-wa-reagir-x:hover{ color: var(--accent-red, #ef4444);
      border-color: var(--accent-red, #ef4444); }

    /* ---- O COMPOSITOR / A FAIXA DE 24H ---- */
    /* (1.1.41) Âncora do popover do compositor (`#precs-wa-comp-pop`): ele abre POR CIMA do
       rodapé, e é filho dele — ver o comentário de `precsWaCompPopPintar` para o porquê de o
       popover morar aqui dentro e não na coluna da conversa. */
    /* ======================================================================
       (1.1.41) OS CARTÕES DE LOCALIZAÇÃO E DE CONTATO, e as pílulas de botão.

       Os dois cartões vestem a mesma forma porque respondem ao mesmo gesto do credor: "toma
       esse dado aqui". A diferença é o ícone e o que o clique faz — o de localização é uma
       âncora que abre o mapa em outra aba; o de contato não abre nada sozinho (o número veio
       da agenda de um terceiro, e abrir conversa com quem nunca escreveu para a PRECS gastaria
       um modelo aprovado e começaria algo que ninguém autorizou). */
    .precs-wa-cartao{
      display: flex; align-items: center; gap: 8px;
      margin: 2px 0 4px; padding: 7px 9px;
      border-radius: var(--radius-inner);
      border: 1px solid color-mix(in srgb, var(--text-primary) 13%, transparent);
      background: color-mix(in srgb, var(--text-primary) 5%, transparent);
      text-decoration: none; color: inherit;
      transition: background var(--dur-1, .15s) ease, border-color var(--dur-1, .15s) ease;
    }
    a.precs-wa-cartao:hover{
      background: color-mix(in srgb, var(--text-primary) 9%, transparent);
      border-color: color-mix(in srgb, var(--precs-gold-forma, #B49552) 45%, transparent);
    }
    .precs-wa-cartao-ico{ flex: 0 0 auto; display: inline-flex;
      color: var(--precs-gold-title, var(--precs-gold, #B49552)); }
    .precs-wa-cartao-txt{ flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column;
      gap: 1px; }
    .precs-wa-cartao-txt b{ font-size: .82rem; font-weight: 600; color: var(--text-primary);
      overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
    .precs-wa-cartao-txt i{ font-style: normal; font-size: .72rem; color: var(--text-secondary);
      overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
    /* As coordenadas em monoespaçada, como todo número desta tela (telefone, hora, duração). */
    .precs-wa-cartao-txt u{ text-decoration: none; font-family: 'JetBrains Mono', monospace;
      font-size: .64rem; color: var(--text-muted); }
    .precs-wa-cartao-btn{
      flex: 0 0 auto; padding: 4px 9px; border-radius: var(--radius-pill, 999px);
      border: 1px solid var(--border-color); background: transparent;
      color: var(--text-secondary); font-family: inherit; font-size: .68rem; font-weight: 600;
      cursor: pointer;
    }
    .precs-wa-cartao-btn:hover{ color: var(--text-primary); background: var(--bg-tertiary); }

    /* As opções OFERECIDAS ao credor, no pé da bolha. Pílulas inertes de propósito: elas são o
       registro do que foi mandado, e quem clica é o credor no celular dele. Um botão clicável
       aqui prometeria uma ação que o painel não tem como executar. O separador em cima é o que
       o aplicativo faz, e é o que impede a leitura de "o texto continua nos botões". */
    .precs-wa-botoes{
      display: flex; flex-wrap: wrap; gap: 4px;
      margin-top: 6px; padding-top: 6px;
      border-top: 1px solid color-mix(in srgb, var(--text-primary) 14%, transparent);
    }
    .precs-wa-botao{
      display: inline-flex; align-items: center; justify-content: center;
      padding: 4px 10px; border-radius: var(--radius-pill, 999px);
      border: 1px solid color-mix(in srgb, var(--precs-gold-forma, #B49552) 40%, transparent);
      font-family: 'Manrope', 'Poppins', sans-serif; font-size: .7rem; font-weight: 600;
      color: var(--text-secondary);
    }
    a.precs-wa-botao.link{ text-decoration: none;
      color: var(--precs-gold-title, var(--precs-gold, #B49552)); }
    a.precs-wa-botao.link:hover{
      background: color-mix(in srgb, var(--precs-gold-forma, #B49552) 14%, transparent); }

    /* ======================================================================
       (1.1.41) O PAINEL DE MENSAGEM INTERATIVA, encostado no compositor.

       Ele não é modal porque o CORPO da mensagem continua sendo o texto do campo de baixo: os
       botões só acrescentam as opções de resposta. Um modal esconderia justamente o texto que
       a pessoa está compondo. */
    .precs-wa-inter{
      flex: 1 1 100%; order: -1;
      margin-bottom: var(--space-2); padding: 9px;
      border: 1px solid color-mix(in srgb, var(--precs-gold-forma, #B49552) 34%, transparent);
      border-radius: var(--radius-card);
      background: var(--bg-tertiary);
    }
    .precs-wa-inter-topo{ display: flex; align-items: center; justify-content: space-between;
      gap: var(--space-2); margin-bottom: 8px; }
    .precs-wa-inter-seg{ display: flex; gap: 4px; }
    .precs-wa-inter-seg button{
      padding: 4px 10px; border-radius: var(--radius-pill, 999px);
      border: 1px solid var(--border-color); background: transparent;
      color: var(--text-muted); font-family: inherit; font-size: .72rem; font-weight: 600;
      cursor: pointer;
    }
    .precs-wa-inter-seg button.on{
      color: var(--precs-gold-title, var(--precs-gold, #B49552));
      border-color: color-mix(in srgb, var(--precs-gold-forma, #B49552) 55%, transparent);
      background: color-mix(in srgb, var(--precs-gold-forma, #B49552) 12%, transparent);
    }
    .precs-wa-inter-x{ flex: 0 0 auto; width: 26px; height: 26px; padding: 0;
      display: inline-flex; align-items: center; justify-content: center;
      border: 0; border-radius: 50%; background: transparent; color: var(--text-muted);
      cursor: pointer; }
    .precs-wa-inter-x:hover{ background: var(--bg-secondary); color: var(--text-primary); }
    .precs-wa-inter-campos{ display: flex; flex-wrap: wrap; gap: 6px; }
    .precs-wa-inter-campos input{
      flex: 1 1 140px; min-width: 0; padding: 6px 10px;
      border: 1px solid var(--border-color); border-radius: var(--radius-pill, 999px);
      background: var(--bg-primary); color: var(--text-primary);
      font-family: 'Poppins', sans-serif; font-size: .76rem;
    }
    .precs-wa-inter-campos input:focus{ outline: none;
      border-color: color-mix(in srgb, var(--precs-gold-forma, #B49552) 55%, var(--border-color));
      box-shadow: 0 0 0 3px color-mix(in srgb, var(--precs-gold-forma, #B49552) 16%, transparent); }
    .precs-wa-inter-dica{ margin-top: 6px; font-size: .68rem; color: var(--text-muted); }
    .precs-wa-inter-enviar{
      width: 100%; margin-top: 8px; padding: 7px;
      border: 0; border-radius: var(--radius-pill, 999px);
      background: var(--precs-gold-forma, #B49552);
      color: var(--precs-wa-tinta-ouro, #131315);
      font-family: inherit; font-size: .78rem; font-weight: 700; cursor: pointer;
    }
    /* Desabilitado enquanto o corpo ou os botões não estão válidos: a Meta recusaria com um
       erro 100 genérico que não diz qual dos limites estourou, e o operador levaria a culpa. */
    .precs-wa-inter-enviar:disabled{ opacity: .45; cursor: not-allowed; }
    /* (1.1.44) O compositor entra na mesma faixa de leitura do cabeçalho e da thread, pelo
       mesmo motivo e com o mesmo recurso — ver o comentário em `.precs-wa-chat-topo`. Sem isto
       ele era a única peça da conversa que atravessava a tela: num monitor de 2560px o campo de
       digitar media mais que o dobro da largura das mensagens que ele responde. */
    .precs-wa-rodape{ position: relative;
      flex: 0 0 auto; display: flex; align-items: center; gap: var(--space-2);
      padding: var(--space-3) max(var(--space-4),
               calc((100% - var(--precs-wa-leitura, 1000px)) / 2));
      border-top: 1px solid var(--border-color);
      background: var(--bg-secondary); min-height: 30px; }
    .precs-wa-rodape:empty{ display: none; }
    /* ======================================================================
       (1.1.41) O POPOVER DO COMPOSITOR: a barra "/" e o seletor de emoji.

       `bottom: 100%` e não uma altura calculada: o rodapé muda de altura sozinho (o textarea
       cresce até 120px, a prévia de anexo entra, a barra de citação entra), e qualquer número
       cravado aqui descolaria da borda no primeiro desses casos.

       O teto de altura é `min(46vh, 380px)`: no painel lateral de 440px a conversa inteira
       tem pouca altura, e uma lista que come metade da tela esconde justamente a mensagem que
       a pessoa está respondendo. */
    .precs-wa-comp-pop{
      /* (1.1.44) O POPOVER ACOMPANHA A FAIXA DE LEITURA, e sem isto ele passaria a mentir
         sobre a que campo pertence: ele é `absolute` dentro do rodapé, então mede contra a
         caixa de padding DELE, que continua sangrando de ponta a ponta. Com o compositor
         recolhido para os 1000px centrais e o popover não, a lista de comandos "/" ficaria
         mais larga que o campo que a abriu. Mesma conta dos dois, num lugar só. */
      position: absolute;
      left:  max(var(--space-3), calc((100% - var(--precs-wa-leitura, 1000px)) / 2));
      right: max(var(--space-3), calc((100% - var(--precs-wa-leitura, 1000px)) / 2));
      bottom: calc(100% + 6px); z-index: 40;
      max-height: min(46vh, 380px); overflow-y: auto;
      background: var(--bg-secondary);
      border: 1px solid var(--border-color);
      border-radius: var(--radius-card);
      box-shadow: var(--shadow-lg);
      animation: precsWaPopEntra 140ms var(--ease-1);
    }
    @media (prefers-reduced-motion: reduce){ .precs-wa-comp-pop{ animation: none; } }
    /* O seletor de emoji e ESTREITO e ancorado a DIREITA, onde esta o botao que o abre. A
       barra "/" ocupa a largura toda porque cada linha dela e uma frase; a grade de emoji
       esticada por 1.200px vira uma fileira unica por grupo, com meio metro de vazio ao lado,
       e o olho tem que atravessar a tela para ler a proxima categoria. */
    .precs-wa-comp-pop.emoji{
      left: auto; right: var(--space-3);
      width: min(420px, calc(100% - 2 * var(--space-3)));
    }
    .precs-wa-comp-tit{
      position: sticky; top: 0; z-index: 1;
      display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-2);
      padding: 7px 10px; background: var(--bg-secondary);
      border-bottom: 1px solid var(--border-color);
      font-family: 'Manrope', 'Poppins', sans-serif;
      font-size: .68rem; font-weight: 700; color: var(--text-secondary);
      text-transform: uppercase; letter-spacing: var(--ls-caps, .04em);
    }
    .precs-wa-comp-tit i{ font-style: normal; font-weight: 500; text-transform: none;
      letter-spacing: 0; color: var(--text-muted); font-size: .66rem; }
    .precs-wa-comp-vazio{ padding: 14px 12px; font-size: .78rem; color: var(--text-muted); }

    /* ---- Respostas rápidas ---- */
    .precs-wa-rapida{
      display: grid; grid-template-columns: auto 1fr; gap: 2px 8px;
      width: 100%; padding: 8px 10px; border: 0; background: transparent;
      color: var(--text-secondary); font-family: inherit; text-align: left; cursor: pointer;
      border-bottom: 1px solid var(--border-color);
    }
    .precs-wa-rapida:last-child{ border-bottom: 0; }
    .precs-wa-rapida b{
      grid-column: 1; font-family: 'JetBrains Mono', monospace; font-size: .72rem;
      color: var(--precs-gold-title, var(--precs-gold, #B49552));
    }
    .precs-wa-rapida i{ grid-column: 2; font-style: normal; font-size: .74rem; font-weight: 600;
      color: var(--text-primary); }
    /* O texto do molde é a terceira linha e ocupa as duas colunas: ele é longo, e alinhá-lo
       à direita do atalho deixaria uma coluna de 40px para uma frase inteira. */
    .precs-wa-rapida span{
      grid-column: 1 / -1; font-size: .72rem; line-height: 1.35; color: var(--text-muted);
      overflow: hidden; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
    }
    .precs-wa-rapida:hover,
    .precs-wa-rapida.sel{ background: var(--bg-tertiary); }
    .precs-wa-rapida.sel{
      box-shadow: inset 3px 0 0 var(--precs-gold-forma, #B49552);
    }

    /* ---- Seletor de emoji ---- */
    .precs-wa-comp-busca{ position: sticky; top: 0; z-index: 1;
      padding: 8px; background: var(--bg-secondary);
      border-bottom: 1px solid var(--border-color); }
    .precs-wa-comp-busca input{
      width: 100%; box-sizing: border-box; padding: 6px 10px;
      border: 1px solid var(--border-color); border-radius: var(--radius-pill, 999px);
      background: var(--bg-primary); color: var(--text-primary);
      font-family: 'Poppins', sans-serif; font-size: .76rem;
    }
    .precs-wa-comp-busca input:focus{ outline: none;
      border-color: color-mix(in srgb, var(--precs-gold-forma, #B49552) 55%, var(--border-color));
      box-shadow: 0 0 0 3px color-mix(in srgb, var(--precs-gold-forma, #B49552) 16%, transparent); }
    .precs-wa-emoji-grupo{
      padding: 8px 10px 3px; font-family: 'Manrope', 'Poppins', sans-serif;
      font-size: .64rem; font-weight: 700; color: var(--text-muted);
      text-transform: uppercase; letter-spacing: var(--ls-caps, .04em);
    }
    .precs-wa-emoji-grade{
      display: grid; grid-template-columns: repeat(auto-fill, minmax(34px, 1fr));
      gap: 2px; padding: 0 6px 6px;
    }
    .precs-wa-emoji{
      display: inline-flex; align-items: center; justify-content: center;
      width: 100%; aspect-ratio: 1 / 1; padding: 0;
      border: 0; border-radius: var(--radius-inner); background: transparent;
      font-size: 1.15rem; line-height: 1; cursor: pointer;
      transition: background var(--dur-1, .15s) ease, transform var(--dur-1, .15s) ease;
    }
    .precs-wa-emoji:hover{ background: var(--bg-tertiary); transform: scale(1.16); }
    .precs-wa-emoji:focus-visible{ outline: var(--focus-ring-largura) solid var(--focus-ring-cor);
      outline-offset: -2px; }
    @media (prefers-reduced-motion: reduce){
      .precs-wa-emoji{ transition: none; }
      .precs-wa-emoji:hover{ transform: none; }
    }
    .precs-wa-input{ flex: 1 1 auto; min-width: 0; resize: none;
      background: var(--bg-tertiary); border: 1px solid var(--border-color);
      border-radius: var(--radius-card); padding: 10px 14px;
      font-family: 'Poppins', sans-serif; font-size: .88rem; color: var(--text-primary);
      max-height: 120px; }
    .precs-wa-input::placeholder{ color: var(--text-muted); }
    .precs-wa-input:focus-visible{ outline: 2px solid var(--precs-gold, #B49552); outline-offset: 1px; }
    /* (1.1.39) O BOTÃO DE ENVIAR ERA BRONZE, NÃO OURO — E A CULPA ERA DO TOKEN ESCOLHIDO.
       Ele pintava o fundo com `--precs-gold`, que no PRECS Claro vale #7A6320: o tema escurece
       esse token de propósito, para proteger o TEXTO dourado sobre fundo branco. Aqui o ouro é
       SUPERFÍCIE, com o avião quase preto (#131315) por cima — a soma dava um disco escuro,
       que é o "o botão de enviar mensagem é muito escuro" do Pedro em 28/08/2026.
       `--precs-gold-forma` é o token que existe exatamente para este caso (ver o bloco do
       tema claro): ouro de marca onde não há letra por cima. E a tinta virou token também,
       porque um `#131315` cravado no meio de um botão é a próxima cor a divergir do tema.
       Entraram ainda `:active` e o estado `enviando`: a flag já existia no JS desde 1.1.22 e
       nunca chegava ao botão, então segurar Enter numa rede lenta não dava retorno nenhum. */
    :root{ --precs-wa-tinta-ouro: #131315; }
    html[data-theme="contraste"]{ --precs-wa-tinta-ouro: #000000; }
    .precs-wa-enviar{ flex: 0 0 auto; width: 40px; height: 40px; border-radius: 50%;
      display: inline-flex; align-items: center; justify-content: center;
      background: var(--precs-gold-forma, #B49552); border: 0; cursor: pointer;
      color: var(--precs-wa-tinta-ouro);
      transition: filter var(--dur-1, .15s) ease, transform var(--dur-1, .15s) ease; }
    .precs-wa-enviar:hover{ filter: brightness(1.1); }
    .precs-wa-enviar:active{ transform: scale(.94); }
    .precs-wa-enviar.enviando{ filter: brightness(.88); cursor: progress; }
    .precs-wa-enviar:focus-visible{ outline: 2px solid var(--precs-gold-hi, #FFC95B); outline-offset: 2px; }
    @media (prefers-reduced-motion: reduce){
      .precs-wa-enviar{ transition: none; }
      .precs-wa-enviar:active{ transform: none; } }
    .precs-wa-tpl-btn{ flex: 0 0 auto; background: transparent;
      border: 1px solid var(--border-color); border-radius: var(--radius-pill);
      padding: 8px 14px; cursor: pointer; font-family: 'Manrope', 'Poppins', sans-serif;
      font-size: .72rem; font-weight: 700; text-transform: uppercase;
      letter-spacing: var(--ls-caps); color: var(--text-secondary);
      transition: color var(--dur-1, .15s) ease, border-color var(--dur-1, .15s) ease; }
    .precs-wa-tpl-btn:hover{ color: var(--precs-gold, #B49552); border-color: var(--precs-gold, #B49552); }
    .precs-wa-tpl-btn.destaque{ color: var(--precs-gold-title, var(--precs-gold, #B49552));
      border-color: var(--precs-gold, #B49552); }
    .precs-wa-24h{ flex: 1 1 auto; font-size: .8rem; color: var(--text-secondary);
      line-height: 1.4; cursor: help; }
    .precs-wa-24h b{ color: var(--accent-orange); }

    /* ---- CONVERSA NOVA (o "+" do topo da lista abre um cartão, não uma
       linha espremida — retrabalho visual pedido em 25/08/2026) ---- */
    .precs-wa-nova-btn{ flex: 0 0 auto; display: inline-flex; align-items: center;
      justify-content: center; width: 34px; height: 34px; border-radius: var(--radius-pill);
      border: 1px solid var(--precs-gold); background: var(--precs-gold-light);
      color: var(--precs-gold-title, var(--precs-gold)); cursor: pointer;
      transition: filter .15s ease, border-color .15s ease; }
    .precs-wa-nova-btn:hover{ filter: brightness(1.12); }
    .precs-wa-nova-btn:focus-visible{ outline: 2px solid var(--precs-gold-hi, #FFC95B);
      outline-offset: 2px; }
    @media (prefers-reduced-motion: reduce){ .precs-wa-nova-btn{ transition: none; } }
    .precs-wa-nova{ display: flex; flex-direction: column; gap: var(--space-2);
      padding: var(--space-3); border-bottom: 1px solid var(--border-color);
      background: var(--bg-secondary);
      animation: precsWaEntra 180ms var(--ease-1); }
    @media (prefers-reduced-motion: reduce){ .precs-wa-nova{ animation: none; } }
    .precs-wa-nova[hidden]{ display: none; }
    /* (1.1.24) POLIMENTO DA CONVERSA NOVA (25/08/2026). O bloco era funcional e desalinhado: o
       "+55" e o campo tinham alturas diferentes, o título competia em peso com o nome das
       conversas logo abaixo, e o número saía na fonte de texto — sendo que o painel inteiro usa
       monoespaçada para número (telefone, protocolo, tempo). Três correções na mesma direção:
       uma altura só na linha, o número em monoespaçada com respiro entre os dígitos, e o
       título rebaixado ao papel de rótulo. */
    .precs-wa-nova-titulo{ font-family: 'Montserrat', sans-serif; font-weight: 700;
      font-size: .68rem; letter-spacing: var(--ls-caps); text-transform: uppercase;
      color: var(--text-muted); }
    .precs-wa-nova-linha{ display: flex; gap: var(--space-2); align-items: stretch; }
    .precs-wa-nova-55{ flex: 0 0 auto; display: inline-flex; align-items: center;
      height: 38px; padding: 0 var(--space-3); border-radius: var(--radius-inner);
      border: 1px solid var(--border-color); background: var(--bg-tertiary);
      color: var(--text-muted); font-family: 'JetBrains Mono', monospace;
      font-size: .82rem; font-weight: 600; }
    .precs-wa-nova-fone{ flex: 1 1 auto; min-width: 0; height: 38px;
      padding: 0 var(--space-3); border-radius: var(--radius-inner);
      border: 1px solid var(--border-color); background: var(--bg-primary);
      color: var(--text-primary); font-family: 'JetBrains Mono', monospace;
      font-size: .88rem; letter-spacing: var(--ls-caps);
      transition: border-color var(--dur-1) ease, box-shadow var(--dur-1) ease; }
    .precs-wa-nova-fone::placeholder{ color: var(--text-muted); letter-spacing: normal; }
    .precs-wa-nova-fone:focus{ outline: none; border-color: var(--precs-gold);
      box-shadow: 0 0 0 3px color-mix(in srgb, var(--precs-gold, #B49552) 18%, transparent); }
    @media (prefers-reduced-motion: reduce){ .precs-wa-nova-fone{ transition: none; } }
    .precs-wa-nova-ok{ flex: 0 0 auto; height: 38px; padding: 0 var(--space-4);
      border-radius: var(--radius-inner); border: 1px solid var(--precs-gold);
      background: var(--precs-gold-forma, #B49552); color: var(--precs-wa-tinta-ouro, #131315);
      font-family: 'Manrope', 'Poppins', sans-serif; font-size: .78rem; font-weight: 700;
      cursor: pointer; transition: filter .15s ease; }
    .precs-wa-nova-ok:hover{ filter: brightness(1.08); }
    .precs-wa-nova-dica{ font-size: .72rem; color: var(--text-muted); line-height: 1.45; }

    /* ---- A BARRA DO ESPELHO (ramal whatsappEspelho: qual caixa está na tela) ---- */
    .precs-wa-espelho{ display: flex; gap: var(--space-2); align-items: center;
      padding: var(--space-2) var(--space-3);
      border-bottom: 1px solid var(--border-color); background: var(--bg-secondary); }
    .precs-wa-espelho[hidden]{ display: none; }
    .precs-wa-espelho-rotulo{ font-size: 0.78rem; color: var(--text-muted);
      white-space: nowrap; }
    .precs-wa-espelho-sel{ flex: 1 1 auto; min-width: 0; height: 30px;
      padding: 0 var(--space-2); border-radius: var(--radius-inner);
      border: 1px solid var(--precs-gold); background: var(--bg-primary);
      color: var(--text-primary); font: inherit; font-size: 0.85rem; }
    .precs-wa-espelho-selo{ flex: 0 0 auto; font-size: 0.68rem; font-weight: 700;
      letter-spacing: var(--ls-caps); text-transform: uppercase; color: var(--text-muted);
      border: 1px solid var(--border-color); border-radius: var(--radius-pill);
      padding: 2px 8px; white-space: nowrap; }
    /* (1.1.38) Escrever na caixa de outra pessoa é estado de ATENÇÃO, e o selo tem que
       parecer um. Laranja e não vermelho: não é erro, é responsabilidade. */
    .precs-wa-espelho-selo.escreve{ color: var(--accent-orange, #F59336); cursor: help;
      border-color: color-mix(in srgb, var(--accent-orange, #F59336) 55%, transparent);
      background: color-mix(in srgb, var(--accent-orange, #F59336) 12%, transparent); }

    /* ---- O VÍNCULO COM O NEGÓCIO (chip na lista, botão e popover no topo) ---- */
    /* (1.1.37) AQUI MORAVA UMA SEGUNDA `.precs-wa-neg`, a pílula dourada de 1.1.18, e ela
       vinha DEPOIS do bloco de 1.1.23 no arquivo: mesma especificidade, então a ordem
       decidia, e a antiga derrubava `display`, `padding`, `border` e `border-radius` do
       bloco novo. O resultado é que o cabeçalho da conversa nunca mostrou título,
       organização, etapa e valor do negócio como foi desenhado — mostrava a pílula que a
       Julia já tinha resumido em 25/08/2026 como "muito pouco". Regra apagada; a que vale
       é a única que sobrou, no bloco "O NEGÓCIO E AS ETIQUETAS NO CABEÇALHO DA CONVERSA".
       O selo compacto da LISTA é outro seletor (`.precs-wa-neg-selo`) e continua de pé. */
    .precs-wa-vinc-btn{ flex: 0 0 auto; height: 30px; padding: 0 var(--space-3);
      border-radius: var(--radius-pill); border: 1px dashed var(--border-color);
      background: transparent; color: var(--text-muted); font: inherit;
      font-size: 0.78rem; cursor: pointer; transition: filter .15s ease; }
    .precs-wa-vinc-btn:hover{ color: var(--precs-gold); border-color: var(--precs-gold); }
    .precs-wa-vinc-chip{ flex: 0 0 auto; display: inline-flex; align-items: center;
      height: 30px; padding: 0 var(--space-3); border-radius: var(--radius-pill);
      border: 1px solid var(--precs-gold); background: var(--precs-gold-light);
      color: var(--precs-gold); font-size: 0.78rem; font-weight: 700;
      cursor: pointer; white-space: nowrap; }
    /* (1.1.39) Ancorado no disparador (ver `.precs-wa-anc`), e não mais no canto direito do
       cabeçalho — que era o lado oposto ao do botão que o abre. */
    /* (22/09/2026) O popover virou COLUNA: a linha do campo, a lista de resultados da busca por
       nº do precatório e a dica. Era uma fila horizontal de campo + botões, que não tinha onde
       pôr os resultados. */
    .precs-wa-vinc-pop{ position: absolute; top: calc(100% + 6px); left: 0;
      z-index: 30; display: flex; flex-direction: column; gap: var(--space-2);
      align-items: stretch;
      padding: var(--space-3); border-radius: var(--radius-inner);
      border: 1px solid var(--border-color); background: var(--bg-secondary);
      box-shadow: var(--shadow-lg, 0 8px 24px rgba(0,0,0,.35));
      animation: precsWaEntra 160ms var(--ease-1); }
    .precs-wa-vinc-linha{ display: flex; gap: var(--space-2); align-items: center; }
    .precs-wa-vinc-dica{ font-family: var(--font-corpo); font-size: var(--fs-2);
      color: var(--text-muted); max-width: 320px; }
    .precs-wa-vinc-aviso{ font-family: var(--font-corpo); font-size: var(--fs-3);
      color: var(--text-muted); padding: var(--space-1) 0; }
    .precs-wa-vinc-lista{ display: flex; flex-direction: column; gap: var(--space-1);
      max-height: 232px; overflow-y: auto; }
    .precs-wa-vinc-op{ display: flex; flex-direction: column; align-items: flex-start; gap: var(--space-0);
      width: 100%; padding: var(--space-2); cursor: pointer; text-align: left;
      border: 1px solid var(--border-color); border-radius: var(--radius-inner);
      background: var(--bg-primary); color: var(--text-primary);
      transition: border-color var(--dur-1) var(--ease-1); }
    .precs-wa-vinc-op:hover{ border-color: var(--precs-gold); }
    .precs-wa-vinc-op b{ font-family: var(--font-acao); font-size: var(--fs-4); font-weight: 700;
      overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 100%; }
    .precs-wa-vinc-op i{ font-style: normal; font-family: var(--font-corpo);
      font-size: var(--fs-2); color: var(--text-muted);
      overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 100%; }
    .precs-wa-vinc-pop.pop-esq{ left: auto; right: 0; }
    @media (prefers-reduced-motion: reduce){ .precs-wa-vinc-pop{ animation: none; } }
    .precs-wa-vinc-input{ width: 280px; max-width: 46vw; height: 34px;
      padding: 0 var(--space-3); border-radius: var(--radius-inner);
      border: 1px solid var(--border-color); background: var(--bg-primary);
      color: var(--text-primary); font: inherit; font-size: 0.85rem; }
    .precs-wa-vinc-input:focus{ outline: none; border-color: var(--precs-gold); }
    .precs-wa-vinc-remover{ flex: 0 0 auto; height: 34px; padding: 0 var(--space-3);
      border-radius: var(--radius-inner); border: 1px solid var(--border-color);
      background: transparent; color: var(--text-muted); font: inherit;
      font-size: 0.82rem; cursor: pointer; }
    .precs-wa-vinc-remover:hover{ color: var(--accent-red, #c0392b);
      border-color: currentColor; }

    /* (1.1.38) Os três "A" do seletor de tamanho. Não é decoração: o controle mostra o que
       faz. Alinhados pela base para os três parecerem a mesma letra em corpos diferentes. */
    .precs-seg-aa{ display: inline-block; font-family: 'Montserrat', sans-serif; font-weight: 700;
      line-height: 1; vertical-align: baseline; }
    .precs-seg-aa.p{ font-size: .68em; }
    .precs-seg-aa.m{ font-size: .85em; }
    .precs-seg-aa.g{ font-size: 1.02em; }

    /* ---- (1.1.38) OS ACHADOS DENTRO DAS MENSAGENS ----
       Bloco separado, acima das conversas, com fundo próprio: são duas perguntas diferentes
       ("quais conversas se chamam assim" e "onde alguém escreveu isso") e misturá-las faria a
       pessoa não saber por que uma linha apareceu. */
    /* (1.1.39) A SUGESTÃO DE ABRIR CONVERSA COM O NÚMERO DIGITADO.
       Fica no topo da lista, acima dos achados, e é a resposta da tela a "digitei um telefone
       e não achei nada". Dourada e não neutra de propósito: ela não é um resultado da busca,
       é uma AÇÃO — e misturá-la visualmente com as linhas de conversa faria o operador clicar
       achando que já existe conversa com aquele número. */
    .precs-wa-sugestao{ width: 100%; display: flex; align-items: center; gap: var(--space-3);
      padding: var(--space-3); cursor: pointer; text-align: left;
      background: color-mix(in srgb, var(--precs-gold-forma, #B49552) 10%, transparent);
      border: 0; border-bottom: 1px solid var(--border-color);
      border-left: 3px solid var(--precs-gold-forma, #B49552);
      transition: background var(--dur-1, .15s) ease; }
    .precs-wa-sugestao:hover{
      background: color-mix(in srgb, var(--precs-gold-forma, #B49552) 18%, transparent); }
    .precs-wa-sugestao:focus-visible{ outline: 2px solid var(--precs-gold, #B49552);
      outline-offset: -2px; }
    .precs-wa-sugestao-ico{ flex: 0 0 auto; width: 34px; height: 34px; border-radius: 50%;
      display: inline-flex; align-items: center; justify-content: center;
      background: var(--precs-gold-forma, #B49552); color: var(--precs-wa-tinta-ouro, #131315); }
    .precs-wa-sugestao-txt{ display: flex; flex-direction: column; gap: 2px; min-width: 0; }
    .precs-wa-sugestao-txt b{ font-family: 'Manrope', 'Poppins', sans-serif;
      font-size: .82rem; font-weight: 700; color: var(--text-primary); }
    .precs-wa-sugestao-txt i{ font-style: normal; font-size: .7rem; color: var(--text-muted);
      overflow: hidden; text-overflow: ellipsis; }
    @media (prefers-reduced-motion: reduce){ .precs-wa-sugestao{ transition: none; } }

    .precs-wa-achados{ display: flex; flex-direction: column; gap: 2px;
      padding: var(--space-2) var(--space-2) var(--space-3);
      border-bottom: 1px solid var(--border-color);
      background: color-mix(in srgb, var(--precs-gold, #B49552) 6%, transparent); }
    .precs-wa-achados-tit{ font-family: 'Manrope', 'Poppins', sans-serif; font-size: .64rem;
      font-weight: 700; text-transform: uppercase; letter-spacing: var(--ls-caps);
      color: var(--text-muted); padding: 0 var(--space-2) var(--space-1); }
    .precs-wa-achado{ display: flex; flex-direction: column; gap: 1px; width: 100%;
      text-align: left; cursor: pointer; border: 0; background: transparent;
      padding: var(--space-2); border-radius: var(--radius-inner); }
    .precs-wa-achado:hover{ background: var(--bg-tertiary); }
    .precs-wa-achado:focus-visible{ outline: 2px solid var(--precs-gold, #B49552);
      outline-offset: -2px; }
    .precs-wa-achado-nome{ display: flex; align-items: center; gap: var(--space-2);
      font-family: 'Montserrat', sans-serif; font-weight: 700; font-size: .8rem;
      color: var(--text-primary); }
    /* Quantas vezes o termo aparece naquela conversa: é o que diferencia "falou uma vez" de
       "é o assunto da conversa". */
    .precs-wa-achado-nome i{ font-style: normal; font-size: .6rem; font-weight: 700;
      padding: 0 6px; border-radius: var(--radius-pill);
      background: var(--precs-gold-light, rgba(180,149,82,.16));
      color: var(--precs-gold-title, var(--precs-gold, #B49552)); }
    .precs-wa-achado-trecho{ font-size: .74rem; color: var(--text-muted); line-height: 1.35;
      display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
      overflow: hidden; }
    .precs-wa-achado-trecho mark{ background: transparent; padding: 0;
      color: var(--precs-gold-title, var(--precs-gold, #B49552)); font-weight: 700; }
    /* O teto da varredura, dito em voz baixa mas dito: busca que para num limite e não avisa
       ensina "não existe" quando o certo é "não procurei tudo". */
    .precs-wa-achados-teto{ font-size: .68rem; color: var(--text-muted); line-height: 1.4;
      padding: var(--space-2) var(--space-2) 0; font-style: italic; }

    /* ---- O SKELETON DA LISTA (loader da primeira abertura) ---- */
    /* (1.1.40) `min-height` casada com a linha real (40px de avatar + 12+12 de padding + a
       borda), senão a lista saltava quando os dados chegavam por cima do skeleton. */
    .precs-wa-skel{ display: flex; align-items: center; gap: var(--space-3);
      padding: var(--space-3); border-bottom: 1px solid var(--border-color);
      min-height: 65px; box-sizing: border-box; }
    .precs-wa-skel-av{ width: 40px; height: 40px; border-radius: 50%; flex: 0 0 auto; }
    .precs-wa-skel-meio{ flex: 1 1 auto; min-width: 0; display: flex;
      flex-direction: column; gap: 7px; }
    .precs-wa-skel-meio .precs-skel-bar{ height: 11px; border-radius: var(--radius-pill); }

    /* ---- ESTADOS VAZIOS (a lição da parede: vazio que explica) ---- */
    .precs-wa-vazio{ display: flex; flex-direction: column; gap: var(--space-2);
      padding: var(--space-5); text-align: center; align-items: center; }
    .precs-wa-vazio b{ font-size: .9rem; color: var(--text-primary); }
    .precs-wa-vazio span{ font-size: .78rem; color: var(--text-muted); line-height: 1.5;
      max-width: 46ch; }
    .precs-wa-vazio.grande{ margin: auto; }

    /* ====================================================================
       (1.1.37) O VISOR DE IMAGEM. Mesmo esqueleto dos modais canônicos (.open/.closing,
       pmEntra, registro em PRECS_MODAIS), com uma diferença: aqui o assunto é a FOTO, então
       a moldura recua e o véu é mais fechado do que o dos outros modais. z-index acima do
       painel lateral (9000) e do popover de reação (10060), que são as duas coisas que
       podem estar na tela quando o operador clica numa imagem.
       ==================================================================== */
    .precs-wa-visor{ display: none; position: fixed; inset: 0; z-index: 10100;
      background: rgba(0,0,0,.78); backdrop-filter: blur(3px);
      align-items: center; justify-content: center; padding: 2vh 2vw; overflow: hidden; }
    .precs-wa-visor.open{ display: flex; }
    .precs-wa-visor.closing{ animation: precsOverlayOut var(--dur-2) ease forwards; }
    .precs-wa-visor.closing .precs-wa-visor-caixa{
      animation: precsModalOut var(--dur-2) var(--ease-3) forwards; }
    .precs-wa-visor-caixa{ display: flex; flex-direction: column; gap: var(--space-2);
      max-width: 96vw; max-height: 94vh; animation: pmEntra var(--dur-3) ease; }
    @media (prefers-reduced-motion: reduce){
      .precs-wa-visor.closing,
      .precs-wa-visor.closing .precs-wa-visor-caixa{ animation: none; }
      .precs-wa-visor-caixa{ animation: none; }
    }
    /* O topo e o pé usam texto claro fixo, e é a única exceção de token do modo inteiro:
       eles vivem sobre o véu preto do visor, que é o mesmo nos cinco temas. Um token de
       tema aqui daria texto escuro sobre preto no PRECS Claro. */
    .precs-wa-visor-topo{ display: flex; align-items: center; gap: var(--space-3);
      color: #F3F3F3; flex: 0 0 auto; }
    .precs-wa-visor-tit{ flex: 1 1 auto; min-width: 0; font-family: 'Montserrat', sans-serif;
      font-weight: 700; font-size: .86rem; white-space: nowrap; overflow: hidden;
      text-overflow: ellipsis; }
    .precs-wa-visor-btn{ flex: 0 0 auto; height: 30px; padding: 0 var(--space-3);
      border-radius: var(--radius-pill); cursor: pointer;
      border: 1px solid rgba(243,243,243,.35); background: transparent; color: #F3F3F3;
      font-family: 'Manrope', 'Poppins', sans-serif; font-size: .72rem; font-weight: 700;
      transition: border-color var(--dur-1, .15s) ease, color var(--dur-1, .15s) ease; }
    .precs-wa-visor-btn:hover{ color: var(--precs-gold-hi, #FFC95B);
      border-color: var(--precs-gold-hi, #FFC95B); }
    .precs-wa-visor-x{ flex: 0 0 auto; width: 30px; height: 30px; border-radius: 50%;
      display: inline-flex; align-items: center; justify-content: center; cursor: pointer;
      border: 1px solid rgba(243,243,243,.35); background: transparent; color: #F3F3F3;
      font-size: .8rem; padding: 0; }
    .precs-wa-visor-x:hover{ color: var(--accent-red, #ef4444);
      border-color: var(--accent-red, #ef4444); }
    .precs-wa-visor-palco{ position: relative; display: flex; align-items: center;
      justify-content: center; min-height: 0; }
    /* (1.1.38) O zoom mora no `transform`, e nao no width/height: assim ele nao reflui a
       pagina a cada quadro de arrasto, e o `will-change` mantem a camada na GPU. A transicao
       vale para o clique (que salta de 1x para 2,5x) e some no arrasto, senao a foto ficaria
       "nadando" atras do cursor. */
    .precs-wa-visor-img{ display: block; max-width: 92vw; max-height: 80vh;
      width: auto; height: auto; object-fit: contain;
      border-radius: var(--radius-inner); background: rgba(0,0,0,.3);
      cursor: zoom-in; transform-origin: center center; will-change: transform;
      transition: transform .18s var(--ease-1); user-select: none; }
    .precs-wa-visor-img.ampliada{ cursor: grab; transition: none; }
    .precs-wa-visor-img.ampliada:active{ cursor: grabbing; }
    @media (prefers-reduced-motion: reduce){ .precs-wa-visor-img{ transition: none; } }
    /* O palco recorta o que passa da borda com a foto ampliada, senao ela invadiria o topo e
       o pe do visor. */
    .precs-wa-visor-palco{ overflow: hidden; }
    .precs-wa-visor-zoom{ flex: 0 0 auto; font-family: 'JetBrains Mono', monospace;
      font-size: .7rem; color: rgba(243,243,243,.75); min-width: 3.5ch; }
    /* As setas ficam POR CIMA da foto, encostadas nas bordas do palco: no meio da tela elas
       cobririam justamente o que se quer ver. Desabilitadas na borda da coleção, para a tela
       dizer onde a sequência acaba em vez de o clique não fazer nada. */
    .precs-wa-visor-nav{ position: absolute; top: 50%; transform: translateY(-50%);
      width: 40px; height: 40px; border-radius: 50%; cursor: pointer;
      display: inline-flex; align-items: center; justify-content: center;
      border: 1px solid rgba(243,243,243,.3); background: rgba(0,0,0,.45); color: #F3F3F3;
      /* (1.1.40) O `padding: 0 0 3px` que estava aqui era o remendo de baseline dos glifos
         `&#8249;/&#8250;`, que renderizavam na fonte de texto e nasciam fora do centro. Com
         SVG o botão centra sozinho. */
      line-height: 0; padding: 0;
      transition: opacity var(--dur-1, .15s) ease, border-color var(--dur-1, .15s) ease; }
    .precs-wa-visor-nav svg, .precs-wa-visor-x svg{ display: block; }
    .precs-wa-visor-nav.ant{ left: 10px; }
    .precs-wa-visor-nav.prox{ right: 10px; }
    .precs-wa-visor-nav:hover:not(:disabled){ border-color: var(--precs-gold-hi, #FFC95B); }
    .precs-wa-visor-nav:disabled{ opacity: .25; cursor: default; }
    .precs-wa-visor-pe{ display: flex; flex-direction: column; gap: 2px; flex: 0 0 auto;
      max-width: 92vw; text-align: center; align-items: center; }
    .precs-wa-visor-legenda{ font-size: .84rem; color: #F3F3F3; line-height: 1.4;
      max-width: 70ch; word-break: break-word; }
    .precs-wa-visor-quando{ font-family: 'JetBrains Mono', monospace; font-size: .68rem;
      color: rgba(243,243,243,.6); }

    /* ---- O MODAL DE MODELOS (mesmo esqueleto dos modais canônicos) ---- */
    .precs-wa-tpl-overlay{ display: none; position: fixed; inset: 0; z-index: 9999;
      /* (1.1.146) O VÉU MAIS LEVE: a operadora precisa LER a ficha da ligação (nome do credor, número) por trás do
         modal enquanto preenche a variável. Sem o blur e com .35 de escuro o texto de trás continua legível; o
         modal segue destacado pela própria moldura. */
      background: rgba(0,0,0,.35); backdrop-filter: none;
      align-items: center; justify-content: center; padding: 2vh 2vw; overflow: hidden; }
    .precs-wa-tpl-overlay.open{ display: flex; }
    .precs-wa-tpl-overlay.closing{ animation: precsOverlayOut var(--dur-2) ease forwards; }
    .precs-wa-tpl-overlay.closing .precs-wa-tpl-modal{
      animation: precsModalOut var(--dur-2) var(--ease-3) forwards; }
    .precs-wa-tpl-modal{ width: min(680px, 94vw); max-height: 88vh;
      display: flex; flex-direction: column;
      background: var(--bg-secondary); border: 1px solid var(--border-color);
      border-radius: var(--radius-card); box-shadow: var(--shadow-lg);
      animation: pmEntra var(--dur-3) ease; }
    @media (prefers-reduced-motion: reduce){
      .precs-wa-tpl-overlay.closing,
      .precs-wa-tpl-overlay.closing .precs-wa-tpl-modal{ animation: none; }
      .precs-wa-tpl-modal{ animation: none; }
    }
    .precs-wa-tpl-head{ display: flex; align-items: center; justify-content: space-between;
      flex: 0 0 auto; padding: var(--space-4) var(--space-5);
      border-bottom: 1px solid var(--border-color); font-weight: 700; font-size: .95rem;
      color: var(--text-primary); }
    .precs-wa-tpl-titulo{ display: inline-flex; align-items: center; gap: var(--space-2); }
    .precs-wa-tpl-body{ padding: var(--space-4); overflow-y: auto; min-height: 0;
      display: flex; flex-direction: column; gap: var(--space-3); }
    /* (1.1.41) O aviso de opt-out de marketing, no topo do seletor de modelos. Laranja de
       AVISO e nao vermelho de erro: nada quebrou, e a operadora tem caminho (os modelos de
       utilidade continuam valendo). Variante `-text` na tinta, pela regra da casa. */
    .precs-wa-tpl-aviso{
      margin-bottom: var(--space-3); padding: 9px 11px;
      border-radius: var(--radius-inner);
      border: 1px solid color-mix(in srgb, var(--accent-orange, #F59E0B) 40%, transparent);
      background: color-mix(in srgb, var(--accent-orange, #F59E0B) 10%, transparent);
      color: var(--accent-orange-text, var(--accent-orange, #F59E0B));
      font-size: .76rem; line-height: 1.4;
    }
    /* O modelo bloqueado FICA na lista, apagado. Some-lo faria a operadora procurar um modelo
       que ela sabe que existe, sem nada na tela explicando o que houve. */
    .precs-wa-tpl-item.bloqueado{ opacity: .42; cursor: not-allowed; }
    .precs-wa-tpl-item.bloqueado:hover{ background: transparent; transform: none; }
    .precs-wa-tpl-lista{ display: flex; flex-direction: column; gap: var(--space-2); }
    .precs-wa-tpl-item{ display: flex; flex-direction: column; gap: 4px; text-align: left;
      background: var(--bg-tertiary); border: 1px solid var(--border-color);
      border-radius: var(--radius-inner); padding: var(--space-3); cursor: pointer;
      transition: border-color var(--dur-1, .15s) ease; }
    .precs-wa-tpl-item:hover{ border-color: var(--precs-gold, #B49552); }
    .precs-wa-tpl-item:focus-visible{ outline: 2px solid var(--precs-gold, #B49552); outline-offset: 1px; }
    .precs-wa-tpl-nome{ font-family: 'Montserrat', sans-serif; font-weight: 700;
      font-size: .88rem; color: var(--text-primary); }
    .precs-wa-tpl-cat{ font-size: .66rem; font-weight: 700; text-transform: uppercase;
      letter-spacing: var(--ls-caps); color: var(--text-muted); }
    .precs-wa-tpl-corpo{ font-size: .78rem; color: var(--text-secondary); line-height: 1.4;
      display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
      overflow: hidden; }
    .precs-wa-tpl-voltar{ align-self: flex-start; background: transparent; border: 0;
      cursor: pointer; font-family: 'Manrope', 'Poppins', sans-serif; font-size: .74rem;
      font-weight: 700; color: var(--text-muted); padding: 2px 0; }
    .precs-wa-tpl-voltar:hover{ color: var(--precs-gold, #B49552); }
    .precs-wa-tpl-nome-g{ font-family: 'Montserrat', sans-serif; font-weight: 700;
      font-size: 1.05rem; color: var(--precs-gold-title, var(--precs-gold, #B49552)); }
    .precs-wa-tpl-campos{ display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
      gap: var(--space-3); }
    .precs-wa-tpl-campo{ display: flex; flex-direction: column; gap: 4px; }
    .precs-wa-tpl-campo span{ font-size: .68rem; font-weight: 700; text-transform: uppercase;
      letter-spacing: var(--ls-caps); color: var(--text-muted); }
    .precs-wa-tpl-campo input{ background: var(--bg-tertiary);
      border: 1px solid var(--border-color); border-radius: var(--radius-inner);
      padding: 8px 12px; font-family: 'Poppins', sans-serif; font-size: .84rem;
      color: var(--text-primary); }
    .precs-wa-tpl-campo input:focus-visible{ outline: 2px solid var(--precs-gold, #B49552); outline-offset: 1px; }
    .precs-wa-tpl-semvar{ font-size: .78rem; color: var(--text-muted); }
    /* A pré-visualização É um balão próprio: o operador vê exatamente a bolha
       que o credor vai receber, marcas {{}} ainda visíveis no que faltou. */
    /* (1.1.40) A PRÉVIA PASSOU A SER A BOLHA DE VERDADE.
       Ela promete "isto é o que o credor vai receber" e usava `--precs-gold-light` com borda
       dourada — uma cor que não existe em lugar nenhum da thread. Agora usa
       `--precs-wa-balao-proprio`, o MESMO token do balão de saída, e perde a borda pelo mesmo
       motivo que o balão perdeu (ver o bloco do rabicho): balão do WhatsApp não tem contorno.
       Assim a promessa passa a ser verdade. */
    .precs-wa-tpl-preview{ align-self: flex-end; max-width: 62ch; padding: 8px 12px;
      border-radius: var(--radius-card); border-bottom-right-radius: 4px;
      background: var(--precs-wa-balao-proprio);
      box-shadow: 0 1px 1.5px var(--precs-wa-balao-sombra); color: var(--text-primary);
      font-size: .88rem; line-height: 1.45; white-space: pre-wrap; word-break: break-word; }
    /* A variável ainda não preenchida: um marcador, e não `{{nome}}` cru — que é vocabulário
       da Meta, não da pessoa que vai apertar enviar. */
    .precs-wa-tpl-vaga{ display: inline-block; padding: 0 5px; border-radius: var(--radius-sm, 6px);
      font-family: 'Manrope', 'Poppins', sans-serif; font-size: .9em; font-weight: 700;
      color: var(--precs-gold-title, var(--precs-gold, #B49552));
      background: color-mix(in srgb, var(--precs-gold-forma, #B49552) 16%, transparent);
      border: 1px dashed color-mix(in srgb, var(--precs-gold-forma, #B49552) 45%, transparent); }
    .precs-wa-tpl-acoes{ display: flex; justify-content: flex-end; }
    .precs-wa-tpl-enviar{ background: var(--precs-gold-forma, #B49552); border: 0;
      border-radius: var(--radius-pill); padding: 10px 20px; cursor: pointer;
      font-family: 'Manrope', 'Poppins', sans-serif; font-size: .8rem; font-weight: 700;
      color: var(--precs-wa-tinta-ouro, #131315); transition: filter var(--dur-1, .15s) ease; }
    .precs-wa-tpl-enviar:hover{ filter: brightness(1.1); }
    .precs-wa-tpl-enviar:disabled{ opacity: .6; cursor: default; }
    .precs-wa-tpl-enviar:focus-visible{ outline: 2px solid var(--precs-gold-hi, #FFC95B); outline-offset: 2px; }

    /* O voltar-para-a-lista só existe na tela estreita: na larga as duas colunas
       estão sempre visíveis e ele seria um botão que não faz nada. */
    .precs-wa-voltar-lista{ display: none; background: transparent; border: 0;
      cursor: pointer; color: var(--text-secondary); font-size: 1.1rem; padding: 4px 8px; }
    @media (max-width: 900px){
      .precs-wa-voltar-lista{ display: inline-flex; }
    }

    /* Tela estreita: a lista vira coluna cheia e o chat esconde até abrir uma
       conversa — comportamento de app. O corte em 900px cobre a janela lado a
       lado com a 3C que as operadoras usam. */
    /* (1.1.40) O SELETOR MUDOU DE CLASSE PARA ATRIBUTO, e isso conserta um beco.
       Aqui estava `.precs-wa-wrap.conversa-aberta`, um SEGUNDO mecanismo de "uma coisa por
       vez" que não conversava com o `data-wa-drawer` do painel. Ele tinha especificidade
       maior (0,3,0 contra 0,2,1) e vinha depois, então numa janela abaixo de 900px com o
       painel aberto ele vencia: voltar para a lista mostrava o chat vazio, e o ← não tinha
       para onde levar. Agora os dois enquadramentos leem `data-wa-vista`, escrito por
       `precsWaVistaSincronizar`. */
    @media (max-width: 900px){
      .precs-wa-wrap{ grid-template-columns: 1fr; }
      .precs-wa-chat{ display: none; }
      html[data-wa-vista="thread"] .precs-wa-lista{ display: none; }
      html[data-wa-vista="thread"] .precs-wa-chat{ display: flex; }
    }

    /* ======================================================================
       (1.1.17) A MODAL DE ANÁLISE DAS LISTAS.
       Mesmo esqueleto do modal de Estatísticas (véu, `pmEntra`, corpo que rola por dentro), com
       um corpo em coluna em vez de grade de dois. Nenhum token novo de cor: a severidade reusa
       `--accent-orange` (peso 0, que pede ação na 3C) e `--text-muted` (lista sem número, que
       pede mailing novo).
       ====================================================================== */
    /* ======================================================================
       (1.1.34) A CAMPANHA POR INTEIRO — a tela que o Enter da parede abre.

       PEDIDO DO PEDRO, 26/08/2026: "ao clicar o enter do botão abre ela por completo na TV, e dá
       pra mostrar mais bonito alguns dados".

       ELA É QUASE A JANELA INTEIRA (96vw x 94vh) e não um card centrado, porque o que está atrás
       dela é uma parede lida a quatro metros: uma modal de 1100px no meio de uma TV de 55" seria
       menor do que o card que ela veio ampliar.

       OS TAMANHOS SAEM DE `vh`/`vmin` E NÃO DE `rem`. É a mesma decisão do motor de tamanho da
       parede, pelo mesmo motivo: o tamanho da TV é desconhecido e o mini-PC pode sair em 4K com
       escala do Windows em 100%, o que dobraria a contagem de px de CSS e reduziria tudo à metade
       do tamanho físico. Aqui a caixa é a janela (`position: fixed`), então `vh` já é a unidade da
       caixa — não há necessidade de container query, e um `clamp()` com piso guarda o monitor do
       supervisor, que é a outra tela onde isto pode abrir.
       ====================================================================== */
    .precs-tvamp-overlay{
      display: none; position: fixed; inset: 0; z-index: 9999;
      background: rgba(0,0,0,.72); backdrop-filter: blur(3px);
      align-items: center; justify-content: center; overflow: hidden;
    }
    .precs-tvamp-overlay.open{ display: flex; }
    .precs-tvamp-overlay.closing{ animation: precsOverlayOut var(--dur-2) ease forwards; }
    .precs-tvamp-overlay.closing .precs-tvamp-modal{
      animation: precsModalOut var(--dur-2) var(--ease-3) forwards; }
    @media (prefers-reduced-motion: reduce){
      .precs-tvamp-overlay.closing,
      .precs-tvamp-overlay.closing .precs-tvamp-modal,
      .precs-tvamp-modal{ animation: none; }
    }
    .precs-tvamp-modal{
      width: 96vw; height: 94vh; display: flex; flex-direction: column; min-height: 0;
      background: var(--bg-secondary); border: 1px solid var(--border-color);
      border-radius: var(--radius-card); box-shadow: var(--shadow-lg);
      /* `pmEntra` é o crescimento que os modais da casa já usam. Ele cresce do CENTRO e não do
         card de origem: crescer do card exigiria `transform-origin` calculado por JS a cada
         abertura, e o custo disso é um `style` inline disputando com a animação — o mesmo tipo de
         briga que a parede resolveu tirando `transform` do realce do cursor. */
      animation: pmEntra var(--dur-3) ease;
    }
    .precs-tvamp-head{
      display: flex; align-items: center; gap: var(--space-4); flex: 0 0 auto;
      padding: clamp(10px, 1.6vh, 22px) clamp(14px, 1.8vw, 32px);
      border-bottom: 1px solid var(--border-color);
    }
    .precs-tvamp-titulo{
      flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
      font-family: 'Sora', 'Poppins', sans-serif; font-weight: 700;
      font-size: clamp(1.1rem, 3.4vh, 2.6rem); color: var(--precs-gold-title, #D3B26B);
    }
    /* AS DICAS DE TECLA FICAM NA TELA, e isto não é enfeite: quem opera é "qualquer um da sala",
       e a tecla que fecha precisa estar escrita onde a pessoa já está olhando. É o mesmo argumento
       do "F11 para tela cheia" no rodapé da parede. */
    .precs-tvamp-dicas{
      flex: 0 0 auto; display: inline-flex; align-items: center; gap: 6px;
      font-size: clamp(.6rem, 1.5vh, .95rem); color: var(--text-muted);
    }
    .precs-tvamp-dicas b{
      display: inline-block; min-width: 1.6em; padding: 1px 5px; text-align: center;
      border: 1px solid var(--border-color); border-radius: 4px;
      background: var(--bg-tertiary); color: var(--text-secondary); font-weight: 700;
      font-family: 'JetBrains Mono', monospace;
    }
    /* NA TV O X SOME. Não há mouse na sala, e um botão que ninguém alcança só ocupa o lugar onde a
       tecla deveria estar escrita. No monitor do supervisor ele fica. */
    html[data-tv] .precs-tvamp-head .precs-prefs-close{ display: none; }
    .precs-tvamp-body{
      flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column;
      gap: clamp(8px, 1.4vh, 20px); padding: clamp(10px, 1.6vh, 24px) clamp(14px, 1.8vw, 32px);
      overflow: hidden;
    }

    /* ======================================================================
       (1.1.35) A TROCA DE CAMPANHA DENTRO DA AMPLIADA TEM DIREÇÃO.

       PEDIDO DO PEDRO, 27/08/2026: "eu tava falando de animação entre as campanhas no modo foco —
       selecionei, cliquei enter pra entrar, daí se aperto seta pra direita pra alternar não tem
       animação, isso que eu tava reclamando".

       A parede já entrava com direção desde a levitação; aqui o conteúdo trocava de estalo, porque
       esta tela é remontada por `innerHTML` a cada troca. O corpo é sempre um nó novo, então o
       carimbo de direção nele faz a animação nascer junto — sem `reflow` forçado, sem remover e
       repor classe.

       O DESLOCAMENTO É MAIOR QUE O DA PAREDE (40px contra 28px) e leva opacidade junto: aqui a tela
       inteira trocou de assunto, e não só o realce mudou de card. E a moldura fica PARADA — é ela
       que sustenta a leitura de "mesma janela, outra campanha". */
    @keyframes precsTvAmpEntraDir{
      from{ transform: translateX(-40px); opacity: 0; }
      to{ transform: none; opacity: 1; }
    }
    @keyframes precsTvAmpEntraEsq{
      from{ transform: translateX(40px); opacity: 0; }
      to{ transform: none; opacity: 1; }
    }
    @keyframes precsTvAmpEntraBaixo{
      from{ transform: translateY(-34px); opacity: 0; }
      to{ transform: none; opacity: 1; }
    }
    @keyframes precsTvAmpEntraCima{
      from{ transform: translateY(34px); opacity: 0; }
      to{ transform: none; opacity: 1; }
    }
    .precs-tvamp-body[data-entra]{
      animation-duration: 260ms;
      animation-timing-function: cubic-bezier(.2, .8, .3, 1);
      animation-fill-mode: both;
    }
    .precs-tvamp-body[data-entra="dir"]{ animation-name: precsTvAmpEntraDir; }
    .precs-tvamp-body[data-entra="esq"]{ animation-name: precsTvAmpEntraEsq; }
    .precs-tvamp-body[data-entra="baixo"]{ animation-name: precsTvAmpEntraBaixo; }
    .precs-tvamp-body[data-entra="cima"]{ animation-name: precsTvAmpEntraCima; }
    @media (prefers-reduced-motion: reduce){
      .precs-tvamp-body[data-entra]{ animation: none; }
    }

    /* ---- O TOPO: rosca, número e a curva ----
       Três colunas, e a curva é a que mais cresce: ela é a informação que esta tela tem e o card
       não tem, então é ela que justifica a tela existir. */
    .precs-tvamp-topo{
      flex: 0 0 auto; display: grid; align-items: center;
      grid-template-columns: auto minmax(0, 1fr) minmax(0, 1.15fr);
      gap: clamp(12px, 2vw, 40px);
      padding: clamp(8px, 1.4vh, 20px) clamp(10px, 1.4vw, 24px);
      /* (1.1.66) B6b — O RAIO É O DA CÉLULA, E NÃO O DE BLOCO INTERNO.
         `--radius-inner` são 8px e `--radius-card` são 12px, e toda célula da parede usa o
         segundo. Esta faixa é o card da campanha ampliado, então ela usa o raio de card: a
         ampliada é o mesmo desenho, maior, e um canto diferente é a única coisa que dizia o
         contrário. */
      border: 1px solid var(--border-color); border-radius: var(--radius-card);
      /* (1.1.66) B6b — O FILETE VOLTOU A SER SINAL DE GRAU.
         Ele era 8px fixo para crítica, atenção e calma. Na parede ele é 4, 7 e 10px, e o bloco
         da faixa lá diz explicitamente que a faixa fala por "cor, filete e área". Aqui a área é
         sempre a mesma (a tela inteira) e o filete era sempre o mesmo, então sobrava só a cor --
         ou seja, a ampliada usava metade do vocabulário que o mural usa para a mesma pergunta.
         Os três valores são os mesmos px do card, e de propósito: quem olha a parede e depois
         entra numa campanha vê a mesma espessura, e não uma tradução. */
      border-left: 4px solid var(--border-color);
    }
    /* A FAIXA PINTA A BORDA E O TINT, exatamente como no card da parede — e a cor vem do card vivo
       (ver `precsSupTvAmpPintar`), não de uma segunda conta. Duas contas de nível na mesma tela é
       como a ampliada acabaria dizendo "atenção" com a parede dizendo "crítica" atrás. */
    .precs-tvamp-topo.tv-critica{
      border-left-color: var(--accent-red); border-left-width: 10px;
      background: color-mix(in srgb, var(--accent-red) 9%, var(--bg-secondary));
    }
    .precs-tvamp-topo.tv-atencao{
      border-left-color: var(--accent-orange); border-left-width: 7px;
      background: color-mix(in srgb, var(--accent-orange) 7%, var(--bg-secondary));
    }
    /* (1.1.65) A TRANQUILA PERDEU O DOURADO AQUI, e o motivo e vocabulario e nao gosto: na
       parede o filete dourado significa CAMPANHA PAUSADA (`.precs-campsaldo-parada`, com o
       argumento escrito la: "o dourado carrega o peso institucional certo: e o alerta mais forte
       do card"). A ampliada estava dizendo "pausada" numa campanha tranquila, e a mesma campanha
       aparecia cinza no mural e dourada aqui.
       `--st-offline` e o filete base do card na parede, ou seja: a ampliada passa a dizer o mesmo
       que o mural sobre a mesma campanha. */
    .precs-tvamp-topo.tv-calma{ border-left-color: var(--st-offline); }
    /* E A COR DO ARCO SEGUE A FAIXA. As regras que pintam o arco (`.precs-campsaldo-critico
       .cs-arco` e irmãs) casam com a raiz do CARD, e aqui a raiz é outra — sem estas três linhas a
       rosca saía VERDE numa campanha crítica, com a borda vermelha ao lado dela e a parede
       vermelha atrás. Duas cores discordando sobre a mesma campanha na mesma tela é pior que
       nenhuma cor. */
    .precs-tvamp-topo.tv-critica .cs-arco{ stroke: var(--accent-red); }
    .precs-tvamp-topo.tv-atencao .cs-arco{ stroke: var(--accent-orange); }
    .precs-tvamp-topo.tv-calma .cs-arco{ stroke: var(--accent-green); }

    /* A ROSCA REUSA O TOKEN DA PAREDE, e isto conserta um defeito que o primeiro desenho tinha:
       `html[data-tv] .precs-campsaldo-rosca{ width: var(--tv-rosca) }` existe e vence qualquer
       largura escrita aqui — mas `--tv-rosca` só é declarado em `.precs-campsaldo > *`, dentro do
       card. Fora dele o `var()` fica inválido em tempo de valor computado, a largura cai para
       `auto` e a rosca virava uma pílula vertical de 20px com o número por cima do rótulo (visto
       no primeiro print desta tela). Declarando o token AQUI, as cinco regras da parede (largura,
       texto, sinal de `%`, rótulo e espessura do anel) passam a valer de graça e com as mesmas
       proporções — que é o ponto: a ampliada é o mesmo desenho, maior. */
    .precs-tvamp-topo{ --tv-rosca: clamp(90px, 21vh, 300px); }
    .precs-tvamp-rosca{ flex: 0 0 auto; }
    .precs-tvamp-num b{
      display: block; font-family: 'JetBrains Mono', monospace; font-weight: 700; line-height: 1;
      /* A RAZÃO NÚMERO/ROSCA FICA EM 0,62, o mesmo número da parede. Foi ela que fez todas as
         densidades parecerem o mesmo desenho, e esta tela faz parte do mesmo desenho. */
      font-size: calc(var(--tv-rosca) * .62);
      color: var(--text-primary);
    }
    .precs-tvamp-num span{
      display: block; margin-top: .3em; font-size: clamp(.6rem, 1.6vh, 1.05rem);
      font-weight: 700; text-transform: uppercase; letter-spacing: var(--ls-caps);
      color: var(--text-muted);
    }
    .precs-tvamp-proj{
      margin-top: clamp(6px, 1.2vh, 16px); font-size: clamp(.8rem, 2.4vh, 1.7rem);
      color: var(--text-secondary);
    }
    .precs-tvamp-proj b{ color: var(--precs-gold-hi, #FFC95B); font-weight: 700; }
    .precs-tvamp-semproj{ color: var(--text-muted); font-style: italic; }

    .precs-tvamp-ritmo{ min-width: 0; display: flex; flex-direction: column; gap: 4px; }
    /* A CURVA AQUI IGNORA O `@container` DA PAREDE. Lá o gráfico só aparece em card alto, porque
       54px de gráfico saem de onde os nomes de mailing moram. Aqui ele é o motivo da tela, então a
       regra é o oposto: ele aparece sempre, e grande. */
    .precs-tvamp-ritmo .precs-tv-ritmo{
      display: block; width: 100%; height: clamp(64px, 13vh, 190px);
    }
    .precs-tvamp-ritmo .precs-tv-ritmo-vazio{
      display: flex; align-items: center; justify-content: center;
      height: clamp(64px, 13vh, 190px);
      font-family: 'JetBrains Mono', monospace; color: var(--text-muted);
      font-size: clamp(.7rem, 1.8vh, 1.1rem);
    }
    .precs-tvamp-ritmo-lbl{
      display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-3);
      font-size: clamp(.55rem, 1.4vh, .9rem); font-weight: 700; text-transform: uppercase;
      letter-spacing: var(--ls-caps); color: var(--text-muted);
    }
    /* O número do ritmo agora, na ponta do rótulo: a curva diz a forma e ele diz a grandeza. */
    .precs-tvamp-ritmo-lbl b{
      font-family: 'JetBrains Mono', monospace; text-transform: none; letter-spacing: 0;
      font-size: 1.5em; color: var(--precs-gold-hi, #FFC95B); white-space: nowrap;
    }
    /* Campanha seca fala com a cor do alerta: é o único caso desta linha que manda alguém agir. */
    .precs-tvamp-seca{ color: var(--accent-red); font-weight: 700; }

    /* ---- As duas colunas: mailing e gente ---- */
    /* ======================================================================
       (1.1.68) A FAIXA DE MÉTRICAS DA CAMPANHA — as taxas que a 3C mostra.

       Pedido do Pedro em 12/09/2026, com o print da tela de campanha deles: taxa de atendimento,
       abandono, completamento e contato com a pessoa certa, ao mergulhar numa campanha.

       ALTURA EM `vh` E NÃO EM `rem`, e isto é requisito e não estilo. O `.precs-tvamp-body` é
       `overflow: hidden` e NÃO ROLA: bloco que não couber SOME, sem erro nenhum. Com `flex: 0 0
       auto` a faixa nunca é comprimida pelas colunas, e com a tipografia em `clamp(...vh)` ela
       encolhe junto com a janela em vez de empurrar o resto para fora.

       O NÚMERO É O QUE SE LÊ A QUATRO METROS, então ele leva o tamanho; o absoluto embaixo existe
       porque 0,65% pode ser 17 ligações ou 1.700, e a ação é outra em cada caso; e o rótulo fica
       por último, pequeno, porque quem olha a parede todo dia já sabe a ordem das quatro caixas.

       O `grid` de quatro colunas iguais mais a nota: caixas de larguras diferentes fariam o olho
       comparar tamanho de caixa em vez de tamanho de número. */
    .precs-tvamp-kpis{
      flex: 0 0 auto; display: grid; align-items: stretch;
      grid-template-columns: repeat(7, minmax(0, 1fr)) auto;
      gap: clamp(6px, 0.9vw, 16px);
    }
    .precs-tvamp-kpi{
      display: flex; flex-direction: column; gap: clamp(1px, 0.2vh, var(--space-1));
      padding: clamp(6px, 1vh, 14px) clamp(var(--space-2), 0.9vw, 18px);
      border: 1px solid var(--border-color); border-radius: var(--radius-card);
      background: var(--bg-secondary); cursor: help; min-width: 0;
    }
    .precs-tvamp-kpi b{
      font-family: var(--font-num); font-variant-numeric: tabular-nums;
      font-size: clamp(1.1rem, 3.2vh, 2.4rem); line-height: 1;
      color: var(--text-primary);
    }
    .precs-tvamp-kpi-abs{
      font-family: var(--font-num); font-variant-numeric: tabular-nums;
      font-size: clamp(.6rem, 1.2vh, .95rem); color: var(--text-secondary);
      white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
    }
    .precs-tvamp-kpi-rot{
      font-size: clamp(.58rem, 1.1vh, .9rem); color: var(--text-muted);
      text-transform: uppercase; letter-spacing: var(--ls-caps);
      white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
    }
    /* A NOTA DA BASE DE CÁLCULO fica na faixa e não num rodapé: ela é a ressalva das quatro caixas
       ao mesmo tempo, e uma ressalva longe do número que ela ressalva não é lida. Escrita na
       vertical seria ilegível a quatro metros; deitada e apagada, ela ocupa o mínimo e o balão
       carrega o resto. */
    .precs-tvamp-kpi-nota{
      display: flex; align-items: flex-end; cursor: help;
      font-size: clamp(.55rem, 1vh, .85rem); color: var(--text-muted);
      padding-bottom: clamp(var(--space-1), 0.8vh, var(--space-3)); white-space: nowrap;
    }
    /* (1.1.70) A SEGUNDA CONTA (`.precs-tvamp-kpi-todas`) SAIU daqui junto com a função que a
       montava. Ela comparava as taxas sobre as listas ativas com as taxas sobre todas, para
       descobrir qual das duas a tela da 3C estava mostrando. A resposta veio por outro caminho e
       dissolveu a pergunta: os cards deles são do DIA, e a rota do dia só conta o que foi discado
       hoje — lista parada não discou, então não há duas contas para comparar. */
    /* NO MONITOR DO SUPERVISOR as quatro caixas viram duas linhas de duas: em 900px, quatro
       colunas mais a nota dão ~150px por caixa, e o absoluto ("1.234 de 56.789") não cabe. */
    /* (1.1.70) SETE CAIXAS, e nao mais quatro: a troca para a fonte do DIA trouxe a conversao
       (denominador que nao podia ser provado antes), a caixa postal como numero proprio (a 3C
       separa `abandoned` de `abandoned_due_amd`) e a ociosidade media por agente, que era a sexta
       metrica do pedido e nao estava em lugar nenhum.

       OS DOIS DEGRAUS sao onde o absoluto ("1.234 de 56.789") para de caber: abaixo de 1500px
       viram quatro por linha, abaixo de 900 viram duas. Numa TV de 85" as sete cabem lado a lado,
       que e a leitura que o Pedro pediu — a tela da 3C na horizontal. */
    @media (max-width: 1500px){
      .precs-tvamp-kpis{ grid-template-columns: repeat(4, minmax(0, 1fr)); }
      .precs-tvamp-kpi-nota{ grid-column: 1 / -1; padding-bottom: 0; }
    }
    @media (max-width: 900px){
      .precs-tvamp-kpis{ grid-template-columns: repeat(2, minmax(0, 1fr)); }
      .precs-tvamp-kpi-nota{ grid-column: 1 / -1; padding-bottom: 0; }
    }
    .precs-tvamp-cols{
      flex: 1 1 auto; min-height: 0; display: grid; gap: clamp(10px, 1.6vw, 28px);
      grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr);
    }
    /* ABAIXO DE 900px DE LARGURA AS COLUNAS EMPILHAM. Não é o caso da TV; é o do monitor do
       supervisor, que é onde isto também abre. */
    @media (max-width: 900px){
      .precs-tvamp-cols{ grid-template-columns: minmax(0, 1fr); }
    }
    /* OS BLOCOS NÃO ESTICAM À FORÇA: `align-self: start` com `max-height: 100%` faz a caixa ter a
       altura do conteúdo até o limite da linha, e rolar por dentro só acima disso. Esticar era o
       mesmo defeito que o Pedro apontou na parede com três campanhas ("ficou um espação embaixo"),
       aqui em escala menor: uma campanha com uma lista ativa dava uma caixa de 600px com uma linha
       dentro. Espaço vazio FORA de uma moldura lê como respiro; dentro dela lê como tela quebrada. */
    .precs-tvamp-bloco{
      align-self: start; max-height: 100%;
      min-height: 0; display: flex; flex-direction: column;
      border: 1px solid var(--border-color); border-radius: var(--radius-inner);
      background: var(--bg-tertiary); overflow: hidden;
    }
    .precs-tvamp-bloco-tit{
      flex: 0 0 auto; display: flex; align-items: baseline; justify-content: space-between;
      gap: var(--space-3); padding: clamp(6px, 1.1vh, 14px) clamp(8px, 1vw, 18px);
      border-bottom: 1px solid var(--border-color);
      font-size: clamp(.58rem, 1.5vh, .95rem); font-weight: 700; text-transform: uppercase;
      letter-spacing: var(--ls-caps); color: var(--precs-gold-title, #D3B26B);
    }
    .precs-tvamp-bloco-tit i{
      font-style: normal; text-transform: none; letter-spacing: 0; font-weight: 600;
      color: var(--text-muted);
    }
    /* AS DUAS LISTAS ROLAM, e a ORDEM é o que torna isso honesto: as listas vêm por `resta`
       crescente (quem seca primeiro) e a gente por estado (quem está em conversa primeiro). O que
       fica fora da vista numa TV sem mouse é, por construção, o que menos pede ação. */
    .precs-tvamp-listas, .precs-tvamp-ops{
      flex: 1 1 auto; min-height: 0; overflow-y: auto;
      padding: clamp(4px, .8vh, 10px) clamp(8px, 1vw, 18px);
    }
    .precs-tvamp-nada{
      padding: clamp(12px, 3vh, 40px); text-align: center; color: var(--text-muted);
      font-size: clamp(.7rem, 1.8vh, 1.05rem);
    }

    /* Uma linha de lista: nome, quanto falta, quanto era, a barra e o peso. Cinco colunas, a mesma
       ordem de leitura da parede — e a barra reusa `.precs-camplista-barra`, que já é a forma que
       o card e a modal de análise usam. Três desenhos para a mesma informação é o que faz alguém
       comparar coisas que não se comparam. */
    .precs-tvamp-lista{
      display: grid; align-items: center; gap: clamp(6px, 1vw, 18px);
      grid-template-columns: minmax(0, 1fr) auto auto clamp(50px, 7vw, 130px) auto;
      padding: clamp(3px, .7vh, 9px) 0;
      /* (1.1.66) B6b — BORDA CHEIA, como a linha de lista da parede. A meia-borda daqui era a
         terceira divergência sem motivo escrito entre as duas telas, junto do raio e do filete. */
      border-bottom: 1px solid var(--border-color);
      font-size: clamp(.72rem, 1.9vh, 1.15rem);
    }
    .precs-tvamp-lista:last-child{ border-bottom: 0; }
    /* O NOME DA LISTA EM DUAS LINHAS, e não em uma com reticências. Medido no cenário rico: nove
       listas do mesmo estado saíam todas como "ESTADO_MATO_GROSSO_DO_SUL_ID1_PROSPEC…" — nove
       linhas idênticas, e o nome do mailing é justamente a resposta acionável desta tela. Nomes de
       mailing diferem no FIM (`_LOTE_00`, `_LOTE_01`), que é exatamente o pedaço que a reticência
       à direita come. Duas linhas mostram o fim; `break-all` é obrigatório porque não há espaço
       nenhum para o navegador quebrar. */
    .precs-tvamp-lista-nome{
      min-width: 0; overflow: hidden; color: var(--text-primary); font-weight: 600;
      display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
      white-space: normal; word-break: break-all; line-height: 1.15;
    }
    .precs-tvamp-lista-num{
      font-family: 'JetBrains Mono', monospace; font-weight: 700; color: var(--text-primary);
      font-size: 1.1em;
    }
    .precs-tvamp-lista-de, .precs-tvamp-lista-peso{
      font-size: .82em; color: var(--text-muted); white-space: nowrap;
    }
    /* LISTA ZERADA É A RESPOSTA ACIONÁVEL DESTA TELA, então ela se declara em vez de ficar só no
       fim da ordem. */
    .precs-tvamp-lista.zerada .precs-tvamp-lista-num{ color: var(--accent-red); }
    .precs-tvamp-lista.zerada .precs-tvamp-lista-nome{ color: var(--text-secondary); }

    /* Uma linha de gente: rosto, nome com faixa, estado com cronômetro, ligações e a distribuição
       do tempo. A barra de baldes (`precsSupBarra`) é o dado que NENHUMA superfície da parede
       mostra, e é o que responde "essa pessoa está falando ou está esperando o discador". */
    .precs-tvamp-op{
      display: grid; align-items: center; gap: clamp(6px, 1vw, 16px);
      grid-template-columns: auto minmax(0, 1fr) auto auto clamp(60px, 8vw, 150px);
      padding: clamp(3px, .7vh, 9px) 0;
      /* (1.1.66) B6b — BORDA CHEIA, como a linha de lista da parede. A meia-borda daqui era a
         terceira divergência sem motivo escrito entre as duas telas, junto do raio e do filete. */
      border-bottom: 1px solid var(--border-color);
      font-size: clamp(.72rem, 1.9vh, 1.15rem);
    }
    .precs-tvamp-op:last-child{ border-bottom: 0; }
    .precs-tvamp-op .precs-sup-av{
      width: clamp(26px, 4.4vh, 56px); height: clamp(26px, 4.4vh, 56px); flex: 0 0 auto;
    }
    /* (1.1.155) o nome vira coluna: a linha do nome (com a faixa) e, embaixo, o dia do operador (falou, TPA, ocioso). */
    .precs-tvamp-op-nome{
      min-width: 0; display: flex; flex-direction: column; align-items: flex-start; gap: var(--space-0);
      overflow: hidden; white-space: nowrap;
      color: var(--text-primary); font-weight: 600;
    }
    .precs-tvamp-op-nome-l{ display: inline-flex; align-items: center; gap: 6px; max-width: 100%; overflow: hidden; }
    .precs-tvamp-op-hoje{ font-family: var(--font-num); font-weight: 500; color: var(--text-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%; }
    /* (1.1.61) D1, a segunda metade: aqui a faixa tambem saia em 96x16px por falta de regra.
       Na parede o tamanho NAO pode ser cravado, e por isso este numero nao e o 66px da ficha.
       Tudo nesta linha e funcao da altura da tela, porque a distancia de leitura e de metros e
       nao de centimetros: o avatar e `clamp(26px, 4.4vh, 56px)` e o corpo da linha e
       `clamp(.72rem, 1.9vh, 1.15rem)`. Uma faixa fixa ficaria enorme ao lado do avatar de 26px e
       minuscula ao lado do de 56px. O `clamp` abaixo acompanha a mesma escala, e o `height:auto`
       preserva a proporcao de 6:1 do viewBox nas duas pontas. */
    .precs-tvamp-op-nome .precs-faixinha svg{ width: clamp(44px, 5.6vh, 78px); height: auto; }
    .precs-tvamp-op-estado{
      display: inline-flex; align-items: center; gap: 5px; white-space: nowrap;
      font-family: 'JetBrains Mono', monospace; font-size: .92em;
    }
    .precs-tvamp-op-lig{
      display: inline-flex; align-items: baseline; gap: 4px; white-space: nowrap;
      font-family: 'JetBrains Mono', monospace; font-weight: 700; color: var(--text-primary);
    }
    .precs-tvamp-op-lig i{
      font-style: normal; font-family: 'Manrope', 'Poppins', sans-serif; font-weight: 600;
      font-size: .7em; color: var(--text-muted);
    }
    .precs-tvamp-op .precs-sup-barra{ width: 100%; }

    /* O pé: o carimbo de honestidade e o aviso de que a tela volta sozinha. O segundo é requisito
       de operação, não cortesia — ninguém deve ficar em dúvida se "esqueceu a TV aberta". */
    .precs-tvamp-pe{
      flex: 0 0 auto; display: flex; align-items: center; justify-content: space-between;
      gap: var(--space-3); font-size: clamp(.58rem, 1.4vh, .9rem); color: var(--text-muted);
      font-family: 'JetBrains Mono', monospace;
    }
    .precs-tvamp-carimbo.velho{ color: var(--accent-orange); }

    .precs-listas-overlay{
      display: none; position: fixed; inset: 0; z-index: 9999;
      background: rgba(0,0,0,.55); backdrop-filter: blur(2px);
      align-items: center; justify-content: center; padding: 2vh 2vw; overflow: hidden;
    }
    .precs-listas-overlay.open{ display: flex; }
    .precs-listas-overlay.closing{ animation: precsOverlayOut var(--dur-2) ease forwards; }
    .precs-listas-overlay.closing .precs-listas-modal{
      animation: precsModalOut var(--dur-2) var(--ease-3) forwards; }
    @media (prefers-reduced-motion: reduce){
      .precs-listas-overlay.closing,
      .precs-listas-overlay.closing .precs-listas-modal{ animation: none; }
    }
    .precs-listas-modal{
      width: min(1100px, 94vw); max-height: 92vh; display: flex; flex-direction: column;
      background: var(--bg-secondary); border: 1px solid var(--border-color);
      border-radius: var(--radius-card); box-shadow: var(--shadow-lg);
      animation: pmEntra var(--dur-3) ease;
    }
    @media (prefers-reduced-motion: reduce){ .precs-listas-modal{ animation: none; } }
    .precs-listas-head{
      display: flex; align-items: center; justify-content: space-between; flex: 0 0 auto;
      padding: var(--space-4) var(--space-5); border-bottom: 1px solid var(--border-color);
      font-weight: 700; font-size: .95rem; color: var(--text-primary);
    }
    .precs-listas-titulo{ display: inline-flex; align-items: center; gap: var(--space-2);
      min-width: 0; }
    #precs-listas-camp{ overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
    .precs-listas-body{ padding: var(--space-4); overflow-y: auto; min-height: 0;
      display: flex; flex-direction: column; gap: var(--space-3); }
    .precs-listas-vazio{ padding: 2.5rem; text-align: center; color: var(--text-muted);
      font-size: .85rem; line-height: 1.5; }

    /* Os cinco números do topo. Eles respondem antes da tabela: se "com peso 0" está em zero, a
       tabela vira só inventário. */
    .precs-listas-resumo{ display: flex; flex-wrap: wrap; gap: var(--space-3); }
    .precs-listas-kpi{ flex: 1 1 120px; min-width: 0; padding: var(--space-2) var(--space-3);
      background: var(--bg-tertiary); border: 1px solid var(--border-color);
      border-radius: var(--radius-inner); cursor: help; }
    .precs-listas-kpi b{ display: block; font-family: 'JetBrains Mono', monospace;
      font-size: 1.35rem; font-weight: 700; color: var(--text-primary); line-height: 1.2; }
    .precs-listas-kpi span{ font-size: .62rem; font-weight: 700; text-transform: uppercase;
      letter-spacing: var(--ls-caps); color: var(--text-muted); }
    .precs-listas-kpi.alerta b{ color: var(--accent-orange); }

    /* A tabela rola dentro do corpo, e o cabeçalho fica: com 60 linhas, rolar e perder o nome da
       coluna é o mesmo que não ter ordenação. */
    .precs-listas-tabwrap{ overflow: auto; border: 1px solid var(--border-color);
      border-radius: var(--radius-inner); }
    .precs-listas-tab{ width: 100%; border-collapse: collapse; font-size: .82rem; }
    .precs-listas-tab thead th{ position: sticky; top: 0; z-index: 1;
      background: var(--bg-tertiary); text-align: left; padding: 0;
      border-bottom: 1px solid var(--border-color); cursor: help; }
    .precs-listas-tab thead th.num{ text-align: right; }
    .precs-listas-tab thead th button{ width: 100%; background: transparent; border: 0;
      padding: var(--space-2) var(--space-3); cursor: pointer; display: inline-flex;
      align-items: center; gap: 4px; justify-content: inherit;
      font-family: 'Manrope', 'Poppins', sans-serif; font-size: .64rem; font-weight: 700;
      text-transform: uppercase; letter-spacing: var(--ls-caps); color: var(--text-muted);
      transition: color var(--dur-1, .15s) ease; }
    @media (prefers-reduced-motion: reduce){ .precs-listas-tab thead th button{ transition: none; } }
    .precs-listas-tab thead th.num button{ justify-content: flex-end; }
    .precs-listas-tab thead th button:hover{ color: var(--text-primary); }
    .precs-listas-tab thead th.ord button{ color: var(--precs-gold, #B49552); }
    .precs-listas-tab tbody tr{ border-bottom: 1px solid var(--border-color); }
    .precs-listas-tab tbody tr:last-child{ border-bottom: 0; }
    .precs-listas-tab td{ padding: var(--space-2) var(--space-3); color: var(--text-secondary);
      vertical-align: middle; }
    .precs-listas-tab td.num{ text-align: right; font-family: 'JetBrains Mono', monospace; }
    .precs-listas-tab td.forte{ color: var(--text-primary); font-weight: 700; }
    .precs-listas-tab td.nome{ max-width: 380px; }
    .precs-listas-tab td.nome span{ display: block; color: var(--text-primary); font-weight: 600;
      overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
    .precs-listas-tab td.nome i{ font-style: normal; font-size: .68rem; color: var(--text-muted);
      font-family: 'JetBrains Mono', monospace; }
    /* Peso 0 e sem número são estados DIFERENTES e pedem ações opostas: um espera peso na 3C, o
       outro espera mailing novo. Marcar os dois igual foi o defeito que o submenu já corrigiu. */
    .precs-listas-tab tbody tr.sep td{ background: var(--bg-tertiary); font-size: .68rem;
      color: var(--accent-orange); font-weight: 700; padding: 6px var(--space-3); }
    .precs-listas-tab tbody tr.parada td.nome span{ color: var(--accent-orange); }
    .precs-listas-tab tbody tr.zerada td.forte{ color: var(--text-muted); font-weight: 500; }
    .precs-listas-peso0{ font-size: .62rem; font-weight: 700; text-transform: uppercase;
      letter-spacing: var(--ls-caps); color: var(--accent-orange); }
    /* A barra fica ANTES do percentual, na mesma célula: o olho varre a coluna de barras e para na
       que está cheia, sem ler número nenhum. */
    .precs-listas-barra{ display: inline-block; width: 64px; height: 6px; margin-right: 8px;
      vertical-align: middle; border-radius: var(--radius-pill);
      background: var(--bg-tertiary); overflow: hidden; }
    .precs-listas-barra i{ display: block; height: 100%; border-radius: var(--radius-pill);
      background: var(--precs-gold-forma, var(--precs-gold, #B49552));
      transition: width var(--dur-3, .3s) var(--ease-1); }
    @media (prefers-reduced-motion: reduce){ .precs-listas-barra i{ transition: none; } }
    .precs-listas-teto{ font-size: .72rem; color: var(--text-muted); line-height: 1.5; }

    /* O segundo alvo no card: discreto de propósito. O botão de cima responde a pergunta comum. */
    /* (1.1.95) O ESTILO DO BOTAO "ANALISAR" SAIU DAQUI, e o que ficou e so a regra da parede.
       Ele tinha DUAS versoes concorrentes: esta, tracejada, da primeira escrita; e a da leva
       1.1.85, em `60-campanhas-e-tv.css`, que carrega depois e por isso vencia inteira. A
       versao antiga nao pintava nada na tela havia levas, e ainda assim contava tipografia,
       familia e espacamento literais na catraca de estilo — regra morta cobrando pedagio.
       A linha abaixo FICA porque ela nao esta repetida la: sem ela o botao reaparece na parede
       de TV, onde ninguem clica. */
    html[data-tv] .precs-camplista-lupa{ display: none; }

    .precs-stats-overlay {
      display: none; position: fixed; inset: 0; z-index: 9999;
      background: rgba(0,0,0,.55); backdrop-filter: blur(2px);
      align-items: center; justify-content: center; padding: 2vh 2vw; overflow: hidden;
    }
    .precs-stats-overlay.open { display: flex; }
    /* saída animada (mesmo padrão do modal de Preferências) */
    .precs-stats-overlay.closing { animation: precsOverlayOut var(--dur-2) ease forwards; }
    .precs-stats-overlay.closing .precs-stats-modal { animation: precsModalOut var(--dur-2) var(--ease-3) forwards; }
    @media (prefers-reduced-motion: reduce) {
      .precs-stats-overlay.closing, .precs-stats-overlay.closing .precs-stats-modal { animation: none; }
    }
    .precs-stats-modal {
      width: min(1280px, 96vw); max-height: 94vh; display: flex; flex-direction: column;
      background: var(--bg-secondary); border: 1px solid var(--border-color);
      border-radius: var(--radius-card); box-shadow: var(--shadow-lg); animation: pmEntra var(--dur-3) ease;
    }
    .precs-stats-head {
      display: flex; align-items: center; justify-content: space-between; flex: 0 0 auto;
      padding: var(--space-4) var(--space-5); border-bottom: 1px solid var(--border-color);
      font-weight: 700; font-size: .95rem; color: var(--text-primary);
    }
    /* corpo rola POR DENTRO (nunca a página), e só se faltar altura */
    .precs-stats-body {
      padding: var(--space-4); display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--space-3);
      overflow-y: auto; min-height: 0;
    }
    @media (max-width: 720px) { .precs-stats-body { grid-template-columns: 1fr; } }
    .precs-stats-loading { padding: 3rem; text-align: center; color: var(--text-muted); grid-column: 1/-1; }
    /* (1.1.79) O ESTADO DE CARREGANDO PASSA A TER O LOGO DA MARCA (ver precsSupMergulhoPintar).
       A altura mínima evita o pulo de layout: o modal tem 94vh de teto e o corpo em grid, então
       um bloco de 120px seguido de uma tela cheia de cards faria a caixa saltar duas vezes. */
    .precs-stats-body .precs-stats-carregando {
      display: flex; flex-direction: column; align-items: center; justify-content: center;
      gap: var(--space-2); min-height: 46vh; padding: var(--space-6) var(--space-4);
    }
    .precs-stats-body .precs-stats-loading-sub {
      max-width: 42ch; font-size: var(--fs-4); color: var(--text-muted); text-wrap: pretty;
    }
    /* (1.1.9) Janela do mergulho por operador (Hoje / 7 dias / 14 dias). Ocupa a largura
       inteira do corpo em grade e reusa `.precs-seg`, que é o controle de escolha única do
       projeto — o mesmo de Tema e Fonte nas Preferências. `max-content` para os três botões
       não esticarem até a borda num modal largo, e `justify-self:start` porque em grade um
       item com largura automática seria centralizado pelo `stretch` padrão. */
    .precs-stats-janela { grid-column: 1/-1; justify-self: start; width: max-content; }
    /* 7 e 14 dias ficam desabilitados enquanto a 3C não aceitar filtrar o histórico por
       agente. O motivo vai no `title`; aqui é só a aparência de indisponível, porque o
       estilo base de `.precs-seg button` não previa desabilitado. */
    .precs-seg button:disabled { opacity: .45; cursor: not-allowed; }
    .precs-seg button:disabled:hover { color: var(--text-secondary); }
    /* PRECS — skeleton de carregamento (placeholders que pulsam) */
    .precs-skel {
      background: linear-gradient(90deg,
        var(--bg-tertiary) 25%,
        color-mix(in srgb, var(--bg-tertiary) 55%, var(--text-muted)) 37%,
        var(--bg-tertiary) 63%);
      background-size: 400% 100%;
      border-radius: var(--radius-inner); animation: precsSkel 1.2s ease infinite;
    }
    @keyframes precsSkel { 0%{ background-position: 100% 0; } 100%{ background-position: 0 0; } }
    @media (prefers-reduced-motion: reduce){ .precs-skel { animation: none; } }
    .precs-stat-card { background: var(--bg-primary); border: 1px solid var(--border-color); border-radius: var(--radius-card); padding: var(--space-3) var(--space-4); }
    .precs-stat-card.full { grid-column: 1 / -1; }
    .precs-stat-card h4 { font-size: .66rem; text-transform: uppercase; letter-spacing: var(--ls-caps); color: var(--text-muted); margin-bottom: var(--space-3); font-weight: 700; }
    /* barras genéricas do modal (dia / hora) */
    /* (1.1.78) `position: relative` porque a camada de desenho (o canvas do Chart.js) vive
       dentro desta caixa. Ver o bloco dos gráficos em app.js para o porquê de o desenho e a
       interação serem camadas separadas. */
    .st-bars { display: flex; align-items: flex-end; gap: var(--space-1); height: 96px; position: relative; }
    /* O CANVAS NÃO RECEBE CLIQUE. Quem responde continua sendo `.st-bar-col`, que tem
       `role=button`, foco por teclado e os `data-*` dos filtros. E ele vem DEPOIS das colunas no
       DOM, que é o que o põe por cima sem precisar de `z-index` (elemento posicionado sem
       `z-index` pinta na ordem do documento). */
    .st-graf { position: absolute; left: 0; top: 0; pointer-events: none; }
    /* Com o canvas ativo, as barras em `div` saem de cena e a trilha fica: ela é o fundo claro
       (e o tracejado do dia sem dado), que continua sendo nosso. `visibility` e não `display`
       para a coluna manter a mesma geometria, que é de onde o canvas tira a faixa de desenho. */
    .st-bars.st-graf-on .st-bar,
    .st-bars.st-graf-on .st-media { visibility: hidden; }
    /* E as colunas passam a ser posicionadas pelo próprio gráfico (`left`/`width` inline, do
       centro real de cada barra). Sem isto, o alvo de clique e a barra desenhada seriam duas
       contas parecidas, que é o mesmo que duas contas diferentes. */
    .st-bars.st-graf-on .st-bar-col { position: absolute; top: 0; bottom: 0; }

    /* (1.1.78) O MESMO ARRANJO NO DONUT, com a ordem das camadas invertida: aqui o canvas fica
       POR BAIXO do SVG, porque o SVG ainda carrega o anel de fundo, o número do centro (que o
       foco reescreve) e o alvo do clique. `position: relative` no SVG é o que o põe por cima do
       canvas posicionado; sem isso, elemento posicionado pinta sobre elemento que não é. */
    .precs-stats-body .pm-donut-wrap { position: relative; }
    .precs-stats-body .pm-donut-graf { position: absolute; pointer-events: none; }
    .precs-stats-body .pm-donut-wrap.pm-graf-on .pm-donut { position: relative; }
    /* A fatia fica sem tinta e continua clicável: `pointer-events: stroke` acerta o traço mesmo
       transparente, que é o que mantém o clique, o foco por teclado e o `<title>` nativo. */
    .precs-stats-body .pm-donut-wrap.pm-graf-on .pm-donut-seg {
      stroke: transparent; pointer-events: stroke;
    }
    /* E o anel de fundo sai junto: ele é opaco, mora no mesmo raio e, com o SVG por cima do
       canvas, TAPAVA o desenho inteiro (medido: o canvas tinha 737 pixels pintados e a tela
       mostrava um anel cinza). Ele existia para dar corpo ao anel quando uma fatia pequena não
       preenchia a volta; o canvas desenha a volta fechada, então não falta nada.

       É `opacity` e não `stroke` porque a cor dele é INLINE no markup (`style="stroke:var(...)"`,
       ver precsDonutQualificacoes), e regra de folha não vence atributo de estilo. */
    .precs-stats-body .pm-donut-wrap.pm-graf-on .pm-donut-base { opacity: 0; }
    /* (1.1.79) O CARD DO DONUT ABRAÇA O PRÓPRIO CONTEÚDO, em vez de ser esticado.
       Ele divide a linha do grid com a lista de ligações, que é alta, e o `stretch` do grid
       esticava os dois. Na 1.1.78 eu centrei o conteúdo dentro do card esticado, e o resultado
       foi pior de outro jeito: com sete qualificações sobravam 250px em branco em cima e 200
       embaixo, DENTRO da moldura, e um card vazio por dentro lê como tela quebrada.
       `align-self: start` faz a moldura terminar onde o conteúdo termina; o vão continua
       existindo, mas do lado de fora dela, que é onde vão em branco é só respiro. */
    .precs-stats-body .precs-stat-card-donut { align-self: start; }

    /* (1.1.79) OS CARDS ENTRAM EM CASCATA. A classe vem do JS e só aparece quando a tela está
       ENTRANDO (ver `precsGrafVaiAnimar`), nunca nas repinturas de progresso do mergulho.
       Movimento curto e de baixo para cima, o mesmo vocabulário do `pmEntra` que o modal já usa:
       o que se quer é a tela assentando, não uma apresentação. */
    .precs-stats-body.precs-stats-entra > .precs-stat-card {
      animation: precsStatCardEntra var(--dur-3) var(--ease-2) both;
    }
    .precs-stats-body.precs-stats-entra > .precs-stat-card:nth-child(2) { animation-delay: 40ms; }
    .precs-stats-body.precs-stats-entra > .precs-stat-card:nth-child(3) { animation-delay: 80ms; }
    .precs-stats-body.precs-stats-entra > .precs-stat-card:nth-child(4) { animation-delay: 120ms; }
    .precs-stats-body.precs-stats-entra > .precs-stat-card:nth-child(5) { animation-delay: 160ms; }
    @keyframes precsStatCardEntra {
      from { opacity: 0; transform: translateY(6px); }
      to   { opacity: 1; transform: none; }
    }
    @media (prefers-reduced-motion: reduce){
      .precs-stats-body.precs-stats-entra > .precs-stat-card { animation: none; }
    }
    .st-bar-col { flex: 1; display: flex; flex-direction: column; align-items: center; gap: var(--space-1); height: 100%; justify-content: flex-end; min-width: 0; }
    .st-bar-val { font-size: .58rem; color: var(--text-secondary); font-weight: 600; min-height: .8em; }
    .st-bar-track { width: 100%; height: 66px; display: flex; align-items: flex-end; position: relative; }
    /* PRECS (1.1.2) — LINHA DA PRÓPRIA MÉDIA.
       Um traço por COLUNA, e não um só atravessando o gráfico. Parece contraintuitivo,
       mas é o que funciona aqui: a trilha tem altura fixa (66px) e o rótulo do eixo
       fica abaixo dela, então uma linha única posicionada sobre .st-bars dependeria de
       adivinhar a altura do rótulo e quebraria a cada mudança de fonte ou densidade.
       Ancorada na própria trilha, ela usa a MESMA escala das barras por construção. O
       gap de 0,3rem entre colunas vira a interrupção do tracejado, o que ajuda a
       distinguir a referência das barras. */
    .st-media {
      position: absolute; left: 0; right: 0; height: 0; z-index: 1; pointer-events: none;
      border-top: 1px dashed color-mix(in srgb, var(--text-muted) 85%, transparent);
    }
    /* Destaque da melhor hora: só o rótulo e o valor mudam de peso e cor. A BARRA
       segue igual às outras de propósito — engrossar ou trocar a cor dela distorceria
       a leitura da altura, que é o dado. */
    .st-bar-col.st-melhor .st-bar-val,
    .st-bar-col.st-melhor .st-bar-lbl { color: var(--m-cpc); font-weight: 700; }
    .st-legenda {
      display: flex; align-items: center; gap: var(--space-2);
      margin-top: var(--space-2); font-size: .62rem; color: var(--text-muted);
    }
    .st-legenda-linha { width: 16px; height: 0; border-top: 1px dashed color-mix(in srgb, var(--text-muted) 85%, transparent); flex: none; }
    .st-legenda-pico { width: 8px; height: 8px; border-radius: 2px; background: var(--m-cpc); flex: none; }
    .st-bar { width: 100%; border-radius: 4px 4px 0 0; background: var(--m-ligacoes,#E8A33D); min-height: 2px; position: relative; overflow: hidden; height: 0; transition: height .5s var(--ease-1); }
    .st-bar i { position: absolute; left: 0; right: 0; bottom: 0; background: var(--m-atendidas,#22C55E); height: 0; transition: height .5s var(--ease-1); }
    .st-bar-lbl { font-size: .52rem; color: var(--text-muted); white-space: nowrap; }
    /* (1.1.77) A LEGENDA DE QUALIFICACOES NAO ROLA MAIS, e o motivo veio de um erro de
       leitura real. Ela tinha `max-height: 300px; overflow-y: auto`, pela regra de "listas
       longas rolam dentro do proprio card, entao o modal nunca rola a tela".

       O CUSTO APARECEU EM 14/09/2026: o Pedro somou o CPC pelas qualificacoes que via e
       faltavam duas. Estavam em 9o e 10o lugar de DOZE, abaixo do corte. Nada avisava que
       havia mais, entao a conclusao natural foi que o numero de cima estava errado.

       A TROCA E DELIBERADA: o card cresce e o modal rola, em vez de a lista cortar em
       silencio. Sao no maximo ~15 linhas (a maior lista da conta tem 12 qualificacoes mais
       Mudo, Caixa Postal e "Nao qualificada"), entao o card nao vira uma parede. E o
       cabecalho passou a contar os tipos, que e a defesa para o dia em que virar.

       O HISTORICO CONTINUA ROLANDO (`.st-hist`), e ali a regra ainda vale: ele tem
       centenas de linhas e ninguem espera ver todas de uma vez. */
    .precs-stats-body .pm-leg-wrap { max-height: none; overflow-y: visible; }

    /* (1.1.77) A COLUNA DO DIA COMO FILTRO. O gesto e o mesmo do donut logo abaixo, entao a
       marca de selecao tambem e: borda na cor do dado. Sem `background` na coluna inteira,
       que competiria com a leitura da ALTURA da barra, que e o dado. */
    .precs-stats-body .st-bar-col.st-bar-clic { cursor: pointer; border-radius: var(--radius-sm); }
    /* (1.1.79) O HOVER E O FOCO PRECISARAM MUDAR DE ALVO. Eles clareavam `.st-bar`, que a 1.1.78
       escondeu para o canvas desenhar no lugar: o gesto continuava existindo e não pintava mais
       nada. É o mesmo defeito que o pulso da seleção teve, e a mesma correção — a resposta passa
       para a TRILHA, que é DOM e continua visível por trás do desenho.

       E o foco por teclado ganha anel de verdade, no padrão do painel: antes ele dependia do
       mesmo `filter` do hover, ou seja, quem navega por Tab não tinha marca nenhuma desde a
       1.1.78. */
    .precs-stats-body .st-bar-col.st-bar-clic:hover .st-bar-track {
      background: color-mix(in srgb, var(--text-muted) 16%, transparent);
    }
    .precs-stats-body .st-bar-col.st-bar-clic:focus-visible {
      outline: 2px solid var(--precs-gold-hi); outline-offset: 2px;
    }
    .precs-stats-body .st-bar-col.st-bar-dia-sel .st-bar-val,
    .precs-stats-body .st-bar-col.st-bar-dia-sel .st-bar-lbl {
      color: var(--m-ligacoes); font-weight: 700;
    }
    .precs-stats-body .st-bar-col.st-bar-dia-sel .st-bar-track {
      box-shadow: inset 0 0 0 1px var(--m-ligacoes); border-radius: var(--radius-sm);
    }

    /* (1.1.77) O MESMO PARA A HORA, na cor do proprio grafico (--m-cpc, que e a cor das
       barras de hora). A marca acompanha o dado que ela marca; usar a cor do grafico de dias
       aqui faria os dois recortes parecerem a mesma coisa. */
    .precs-stats-body .st-bar-col.st-bar-hora-sel .st-bar-val,
    .precs-stats-body .st-bar-col.st-bar-hora-sel .st-bar-lbl {
      color: var(--m-cpc); font-weight: 700;
    }
    .precs-stats-body .st-bar-col.st-bar-hora-sel .st-bar-track {
      box-shadow: inset 0 0 0 1px var(--m-cpc); border-radius: var(--radius-sm);
    }

    /* (1.1.77) O INDICIO DE QUE DA PARA CLICAR, e ele precisa existir em repouso.
       Pedido do Pedro: "de indicios q de pra selecionar". Cursor e hover so aparecem depois
       que o mouse ja esta em cima — quem nunca passou o mouse ali nao descobre. Entao a
       coluna clicavel tem uma base sutil permanente, que some quando ela vira a selecionada
       (ai a borda e a cor do numero ja dizem, e as duas marcas juntas poluiriam). */
    .precs-stats-body .st-bar-col.st-bar-clic .st-bar-track {
      background: color-mix(in srgb, var(--text-muted) 9%, transparent);
      border-radius: var(--radius-sm);
      transition: background var(--dur-1) ease, box-shadow var(--dur-2) ease;
    }
    .precs-stats-body .st-bar-col.st-bar-dia-sel .st-bar-track,
    .precs-stats-body .st-bar-col.st-bar-hora-sel .st-bar-track { background: transparent; }

    /* ======================================================================
       (1.1.79) A MARCA DE SELEÇÃO DEPOIS DO CANVAS.

       RELATO DO PEDRO, 15/09/2026: "ao selecionar o de horas também parece que não está
       selecionado". E ele tinha razão por um motivo concreto: a 1.1.77 anunciava a escolha com
       um PULSO na barra (`precs-st-pulso` em `.st-bar`), e a 1.1.78 escondeu `.st-bar` para o
       canvas desenhar no lugar. O pulso continuou existindo, aplicado a um elemento invisível.

       A marca passa a viver onde ela pode ser vista: no RÓTULO, que é DOM e é onde o olho vai
       parar para saber QUAL hora foi escolhida. Ele vira uma pílula na cor do dado, com a tinta
       escura por cima, e é a mesma forma nos dois gráficos (muda só a cor, como já era).

       O anel da trilha sobe de 1px para 2px pelo mesmo motivo: com a base a 5% e a grade
       desenhada atrás, 1px de anel some. */
    /* A PÍLULA NÃO É PREENCHIDA COM A COR DO DADO, e isso é sobre as 21 paletas. Os `--m-*`
       trocam de claridade entre as duas famílias: nos escuros são cores CLARAS (#E8A33D, #8AA0E6)
       e nos claros são ESCURAS (#A34B00, #1D4ED8). Preencher a pílula com elas exigiria uma tinta
       que virasse junto, e a tinta escura sobre o azul do claro dá 2,1:1 — ilegível justamente
       no rótulo que diz o que foi escolhido.

       Então a forma é a mesma que a legenda do donut já usa para "escolhida" (`.pm-leg-sel`):
       moldura na cor do dado, fundo com um véu dela, e o texto na cor de texto do tema. Uma
       marca só, em dois lugares, e segura em qualquer paleta. */
    .precs-stats-body .st-bar-col.st-bar-dia-sel .st-bar-lbl,
    .precs-stats-body .st-bar-col.st-bar-hora-sel .st-bar-lbl {
      color: var(--text-primary); font-weight: 700;
      background: color-mix(in srgb, var(--st-sel-cor) 22%, transparent);
      box-shadow: inset 0 0 0 1px var(--st-sel-cor);
      border-radius: var(--radius-pill); padding: 1px var(--space-2);
      animation: precsStSelPop var(--dur-2) var(--ease-2);
    }
    .precs-stats-body .st-bar-col.st-bar-dia-sel { --st-sel-cor: var(--m-ligacoes); }
    .precs-stats-body .st-bar-col.st-bar-hora-sel { --st-sel-cor: var(--m-cpc); }
    .precs-stats-body .st-bar-col.st-bar-dia-sel .st-bar-track,
    .precs-stats-body .st-bar-col.st-bar-hora-sel .st-bar-track {
      box-shadow: inset 0 0 0 2px var(--st-sel-cor);
    }
    @keyframes precsStSelPop {
      from { transform: scale(.82); opacity: .4; }
      to   { transform: scale(1); opacity: 1; }
    }
    @media (prefers-reduced-motion: reduce){
      .precs-stats-body .st-bar-col.st-bar-dia-sel .st-bar-lbl,
      .precs-stats-body .st-bar-col.st-bar-hora-sel .st-bar-lbl { animation: none; }
    }
    /* (1.1.78) COM O CANVAS, A BASE FICA MAIS LEVE. Ela nasceu na 1.1.77 como o indício
       permanente de "dá para clicar aqui", e continua sendo isso. Só que agora existe uma grade
       desenhada atrás das barras, e a 9% a base virava uma barra fantasma de altura cheia em
       toda coluna, competindo com o dado. */
    .st-bars.st-graf-on .st-bar-col.st-bar-clic .st-bar-track {
      background: color-mix(in srgb, var(--text-muted) 5%, transparent);
    }
    /* E o hover vem DEPOIS, porque empata em especificidade com a regra acima (`:hover` vale uma
       classe) e num empate vence quem vem por último. Escrito aqui, junto do que ele precisa
       vencer, em vez de lá em cima ao lado dos outros estados: a ordem é o que faz a regra valer,
       e separar as duas esconde isso de quem for mexer. */
    .st-bars.st-graf-on .st-bar-col.st-bar-clic:hover .st-bar-track {
      background: color-mix(in srgb, var(--text-muted) 16%, transparent);
    }
    /* (1.1.78) O DONUT CRESCE NO MODAL (era 92px, o tamanho do card "Meu desempenho", que é
       muito menor). Aqui ele divide a linha com a lista de ligações e tem espaço de sobra. */
    .precs-stats-body .pm-donut { width: 132px; height: 132px; }
    /* E o rótulo do chip sobe um degrau (10px para 11px). Seis rótulos em versalete, a 10px,
       embaixo de um número de 24px: a distância entre os dois era grande demais para a linha
       ler como um conjunto. Um degrau da própria rampa, e só dentro do modal. */
    .precs-stats-body .pm-lbl { font-size: var(--fs-3); }

    /* A ANIMACAO DA SELECAO. Um pulso curto na barra, uma vez, no momento do clique — o
       suficiente para o olho achar o que mudou numa tela com tres graficos e uma lista que
       muda junto. Nao e loop: animacao que repete vira ruido depois do segundo ciclo. */
    @keyframes precs-st-pulso {
      0%   { transform: scaleY(1);    filter: brightness(1); }
      45%  { transform: scaleY(1.06); filter: brightness(1.35); }
      100% { transform: scaleY(1);    filter: brightness(1); }
    }
    .precs-stats-body .st-bar-col.st-bar-dia-sel .st-bar,
    .precs-stats-body .st-bar-col.st-bar-hora-sel .st-bar {
      transform-origin: bottom center;
      animation: precs-st-pulso var(--dur-3) var(--ease-1) 1;
    }
    /* Quem pediu menos movimento no sistema nao recebe o pulso. A selecao continua
       legivel pela borda e pela cor, que nao dependem de animacao nenhuma. */
    @media (prefers-reduced-motion: reduce) {
      .precs-stats-body .st-bar-col.st-bar-dia-sel .st-bar,
      .precs-stats-body .st-bar-col.st-bar-hora-sel .st-bar { animation: none; }
    }

    /* (1.1.77) O CHIP DO CPC COMO FILTRO. So ele e clicavel entre os seis, entao o indicio
       tem que distinguir ele dos outros cinco em repouso: um anel na propria cor da metrica. */
    .precs-stats-body .pm-stat.pm-stat-clic {
      cursor: pointer;
      box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--pm-cor) 35%, transparent);
      transition: box-shadow var(--dur-1) ease, background var(--dur-1) ease;
    }
    .precs-stats-body .pm-stat.pm-stat-clic:hover,
    .precs-stats-body .pm-stat.pm-stat-clic:focus-visible {
      box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--pm-cor) 60%, transparent);
    }
    .precs-stats-body .pm-stat.pm-stat-sel {
      box-shadow: inset 0 0 0 2px var(--pm-cor);
      background: color-mix(in srgb, var(--pm-cor) 12%, transparent);
      animation: precsChipLiga var(--dur-3) var(--ease-2);
    }
    /* (1.1.79) O CHIP DO CPC CONFIRMA O CLIQUE. Pedido do Pedro, 15/09/2026: "ao selecionar o
       card de CPC dá para melhorar também". Ele é o único chip que filtra, e a única resposta
       era o anel aparecer: num chip de 24px de número, dois pixels de borda passam despercebidos
       do outro lado da tela. A tinta entra de dentro para fora, e a escala é pequena de propósito
       — o chip está numa fileira de seis, e escalar demais empurraria a leitura dos vizinhos. */
    @keyframes precsChipLiga {
      0%   { transform: scale(1); box-shadow: inset 0 0 0 2px var(--pm-cor); }
      45%  { transform: scale(1.035); box-shadow: inset 0 0 0 3px var(--pm-cor); }
      100% { transform: scale(1); box-shadow: inset 0 0 0 2px var(--pm-cor); }
    }
    @media (prefers-reduced-motion: reduce){
      .precs-stats-body .pm-stat.pm-stat-sel { animation: none; }
    }
    /* Últimas ligações (histórico compacto) */
    /* PRECS (1.1.10) — cabeçalho da lista de ligações do modal de estatísticas: busca e
       contagem. A lista deixou de ser "as 10 mais recentes" e passou a ser o período
       inteiro, então ela precisa dizer quantas está mostrando e deixar filtrar. */
    .st-hist-topo { display: flex; align-items: center; gap: var(--space-2); margin-bottom: var(--space-2); }
    .st-hist-busca {
      flex: 1; min-width: 0; padding: var(--space-1) var(--space-3);
      background: var(--bg-tertiary); color: var(--text-primary);
      border: 1px solid var(--border-color); border-radius: var(--radius-inner);
      font-size: .78rem; font-family: 'Manrope','Poppins',sans-serif;
    }
    .st-hist-busca:focus {
      outline: none; border-color: var(--precs-gold,#B49552);
      box-shadow: 0 0 0 3px var(--precs-gold-light, rgba(180,149,82,.16));
    }
    .st-hist-conta { font-size: .68rem; color: var(--text-muted); white-space: nowrap;
      font-family: 'JetBrains Mono', monospace; }
    .st-hist-aviso { margin-top: var(--space-2); font-size: .68rem; color: var(--text-muted); line-height: 1.4; }
    .st-hist-vazio { padding: var(--space-3); font-size: .76rem; color: var(--text-muted); }
    .st-hist { display: flex; flex-direction: column; max-height: 320px; overflow-y: auto; }
    /* (1.1.15) TRÊS ZONAS NUMA FAIXA: ação, leitura, vínculo. O desenho anterior empilhava
       negócio, protocolo e play na coluna da direita, e o protocolo de 22 caracteres em
       monoespaçada era o que mais chamava atenção na linha. Ver o comentário do markup em
       precsRenderStats (app.js) para o porquê de cada zona. */
    /* (1.1.78) A COLUNA DE AÇÃO PASSOU DE 1.35rem PARA 1.25rem, que é exatamente os 20px do
       botão de ouvir e do espaçador. Sobravam 1,6px, e a bolinha do play ficava fora do meio
       da faixa em toda linha com gravação. */
    .st-hist-row { display: grid; grid-template-columns: 1.25rem 1fr auto; align-items: center; gap: var(--space-2); padding: var(--space-2) var(--space-2); border-top: 1px solid var(--border-color); border-radius: var(--radius-sm); transition: background-color .14s ease; }
    .st-hist-row:first-child { border-top: none; }
    .st-hist-row:hover { background: color-mix(in srgb, var(--precs-gold, #B49552) 8%, transparent); }
    /* Só a linha que TEM protocolo é clicável, e o cursor é o que anuncia isso. */
    .st-hist-row[data-prot] { cursor: pointer; }
    /* (1.1.79) A LINHA QUE ENTRA NO FILTRO SE ANUNCIA. O atraso vem do JS (`--st-atraso`), em
       cascata, e só para as primeiras: é o que faz a lista parecer chegar em vez de trocar de
       conteúdo entre dois quadros. Curta de propósito, porque ela acontece a cada clique. */
    .st-hist-row.st-hist-entra { animation: precsHistEntra var(--dur-3) var(--ease-2) both; animation-delay: var(--st-atraso, 0ms); }
    @keyframes precsHistEntra {
      from { opacity: 0; transform: translateY(-4px); }
      to   { opacity: 1; transform: none; }
    }
    @media (prefers-reduced-motion: reduce){ .st-hist-row.st-hist-entra { animation: none; } }
    /* Espaçador da coluna de ação, para a linha sem gravação alinhar com as outras. */
    .st-hist-vago { display: block; width: 20px; height: 20px; }
    .st-hist-main { display: flex; align-items: baseline; gap: var(--space-2); min-width: 0; }
    /* (1.1.78) AS DUAS PRIMEIRAS ZONAS GANHAM LARGURA, e é isso que põe as qualificações uma
       embaixo da outra.

       Antes as três zonas eram `flex` sem largura nenhuma: a coluna do número tinha a largura
       do texto dele, e como a 3C entrega de 10 a 13 dígitos, cada linha começava a hora e a
       qualificação num ponto diferente.

       A LARGURA É EM `ch`, E ELA MORA NO FILHO DE PROPÓSITO. `1ch` é a largura do "0" na fonte
       DO ELEMENTO — as duas são monoespaçadas, então `15ch` é exatamente `(41) 99910-4324` e
       `11ch` é exatamente `14/09 18:24`. A mesma conta feita no pai (`grid-template-columns`)
       leria a fonte do pai, que é a de texto, e erraria por uns bons pixels.

       É `min-width` e não `width`: número de fora, 0800 ou ramal curto continuam aparecendo
       inteiros, empurrando só a própria linha. Truncar telefone não é opção. */
    .st-hist-num { font-size: .8rem; font-weight: 600; color: var(--text-primary); font-family: 'JetBrains Mono', monospace; flex: 0 0 auto; min-width: 15ch; white-space: nowrap; }
    /* (1.1.74) O NÚMERO SE ANUNCIA COMO CÓPIA PRÓPRIA. A linha inteira já copiava o protocolo, e
       tentar SELECIONAR o telefone terminava copiando o protocolo por cima — o relato foi de um
       operador que se estressou tentando. Agora o clique no número copia o número, e a pista é o
       sublinhado pontilhado que o resto do painel já usa para "tem ação aqui".

       O `user-select: text` é explícito porque a linha é clicável: arrastar para selecionar
       continua valendo, e a seleção agora vence o clique (ver precsStatsCopiarProt). */
    /* (1.1.78) O PONTEIRO VOLTA A SER O DA LINHA. Era `cursor: copy`, que no Windows é a seta
       com um "+" ao lado, e o Pedro reclamou dele por nome: "o ponteiro do mouse ao passar por
       cima do número fica estranho, sei que é pra copiar mas não precisa mudar o ponteiro
       também". O sublinhado pontilhado e o dourado no hover já anunciam a ação, e eles não
       trocam o ponteiro do resto da linha, que também copia. */
    .st-hist-num[data-copiavel]{
      user-select: text; cursor: pointer;
      text-decoration: underline dotted;
      text-decoration-color: color-mix(in srgb, var(--text-muted) 55%, transparent);
      text-underline-offset: 3px;
    }
    /* (1.1.78) `--accent-gold` NUNCA EXISTIU. Dois usos no projeto, zero declarações, então este
       hover não pintava nada desde que foi escrito (o `teste-tokens` acusa desde então). O token
       real é `--precs-gold`, que nos temas claros já é o bronze #7A6320 e por isso não viola a
       regra de não usar o ouro da marca como texto em fundo claro. */
    .st-hist-num[data-copiavel]:hover{ color: var(--precs-gold); }
    /* A hora acompanha o número na fonte de número: além de combinar, é o que faz o `11ch`
       abaixo ser exato. */
    .st-hist-dh { font-size: .66rem; color: var(--text-muted); flex: 0 0 auto; font-family: var(--font-num); min-width: 11ch; }
    /* A qualificação é a única que cede espaço: nome longo trunca e o completo fica no balão
       da linha. Número e hora não podem truncar, porque são o que identifica a ligação. */
    .st-hist-qual { display: inline-flex; align-items: center; gap: var(--space-1); font-size: .72rem; color: var(--text-secondary); min-width: 0; flex: 1 1 auto; }
    .st-hist-qn { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
    .st-hist-dot { width: 7px; height: 7px; border-radius: 50%; flex: 0 0 auto; }
    .st-hist-ids { display: flex; align-items: center; gap: var(--space-1); font-size: .6rem; color: var(--text-muted); font-family: 'JetBrains Mono', monospace; flex: 0 0 auto; }
    /* (1.1.6) O selo do Pipedrive entrou nesta coluna, que é bem mais compacta que a da
       tabela da campanha (.6rem contra .72rem). Sem reduzir, ele empurraria a linha do
       protocolo e faria a fila de 10 ligações crescer de altura.
       (1.1.15) O protocolo saiu da coluna e o selo ficou sozinho nela. O tamanho reduzido
       continua valendo, agora por outro motivo: a linha é uma faixa só, e o selo grande
       roubaria da qualificação a largura que ela acabou de ganhar. */
    /* (1.1.78) UMA CAIXA SÓ PARA A COLUNA INTEIRA. Aqui conviviam TRÊS aparências do mesmo
       selo, e o Pedro reclamou delas: "os botões do integração Pipe tudo de tamanhos
       diferentes, não tem um padrão".

       De onde vinha cada diferença:
        · o id tem de 4 a 7 dígitos, e a largura era a do texto (`fit-content`), então cada
          linha tinha um selo de um tamanho;
        · `.hist-pipe-nota` acrescenta uma borda de 1px e compensa com `padding` menor, mas a
          compensação mora numa regra de especificidade 0,1,0 e esta aqui é 0,2,0 — dentro
          desta lista sobrava só a borda, e o selo da nota ficava 2px maior que o vizinho;
        · e a ligação SEM negócio emitia um `<span>` sem classe nenhuma, que herdava a fonte
          da coluna e não tinha caixa.

       A correção é a mesma para as três: altura fixa, piso de largura e `tabular-nums`, para o
       número não dançar. E a moldura passa a existir SEMPRE, transparente, para a variante
       tracejada trocar a cor da borda em vez de crescer a caixa.

       O PISO É 4.8rem PORQUE FOI MEDIDO: o selo de um id de 7 dígitos (o maior da conta) com o
       logo e o `#` ocupa 76,2px. Em `rem` e não em `px` para acompanhar o zoom por `data-fonte`;
       em `rem` e não em `ch` porque o selo e o vão sem negócio têm tamanhos de fonte diferentes,
       e `ch` daria duas larguras para a mesma coluna. */
    /* (1.1.79) O tamanho e a forma saíram daqui: agora são os da caixa canônica
       (`10-supervisao.css`). O que fica é o que é DESTA coluna — o piso de largura, para os
       selos ficarem todos do mesmo tamanho independentemente do número de dígitos, e a moldura
       transparente, para a variante tracejada não crescer a caixa. */
    .st-hist-ids .hist-pipe {
      border: 1px solid transparent; min-width: 5.6rem;
    }
    /* O tracejado continua sendo o sinal (ver o porquê em 10-supervisao.css); o que muda é
       ele não custar mais 2px de caixa. O `border-style` precisa vir aqui porque a regra
       acima é mais específica que a da folha da supervisão e venceria com `solid`. */
    .st-hist-ids .hist-pipe-nota {
      padding: 0 var(--space-1);
      border-style: dashed; border-color: rgba(255,255,255,.42);
    }
    /* Sem negócio ocupa o mesmo lugar, apagado. Antes a coluna encolhia nessas linhas e o selo
       das vizinhas parecia maior do que era. */
    .st-hist-ids .hist-pipe-vazio {
      display: inline-flex; align-items: center; justify-content: center;
      min-width: 5.6rem; height: 18px; color: var(--text-muted);
      font-variant-numeric: tabular-nums;
    }
    .st-hist-ids .hist-pipe-p { font-size: .58rem; }
    /* (1.1.78) A linha do histórico entrou nesta guarda: ela tem transição de fundo desde a
       1.1.15 e ficou de fora quando a guarda foi escrita. */
    @media (prefers-reduced-motion: reduce) { .st-bar, .st-bar i, .st-hist-row { transition: none; } }

    /* ====================================================================
       (19/09/2026) MÍDIA: vídeo sob clique, figurinha e vídeo no visor, e os dois motivos de
       um arquivo não abrir. Ver `precsWaMidiaHTML` e `precsWaVisorPintar` (app.js).
       ==================================================================== */
    /* A placa do vídeo: a pré-carga nunca o pedia e nada mais pedia, então a bolha dizia
       "carregando vídeo…" para sempre. Agora é um botão honesto; o vídeo é o arquivo mais
       pesado da conversa e só desce quando alguém pede. */
    .precs-wa-video-placa{
      display: inline-flex; align-items: center; justify-content: center; gap: var(--space-2);
      min-width: 180px; min-height: 96px; cursor: pointer;
      border: 1px dashed var(--border-color); border-radius: var(--radius-inner);
      background: transparent; color: var(--text-secondary);
      font-family: var(--font-acao); font-size: var(--fs-2);
    }
    .precs-wa-video-placa:hover{ color: var(--text-primary); border-color: var(--precs-gold); }
    .precs-wa-video-placa:focus-visible{ outline: 2px solid var(--precs-gold); outline-offset: 2px; }
    .precs-wa-video-wrap{
      display: inline-flex; flex-direction: column; align-items: flex-start; gap: var(--space-1);
    }
    .precs-wa-video-amp{
      border: 0; background: transparent; cursor: pointer; padding: 0 var(--space-1);
      font-family: var(--font-acao); font-size: var(--fs-1); color: var(--text-muted);
    }
    .precs-wa-video-amp:hover{ color: var(--precs-gold-title); }
    .precs-wa-fig[onclick]{ cursor: zoom-in; }
    /* Os dois motivos, ditos por classe: `expirada` (a Meta descartou e o arquivo não foi
       preservado no bucket) e `grande` (existe, mas não cabe na resposta e nem o link saiu). */
    .precs-wa-midia.expirada{ color: var(--text-muted); }
    .precs-wa-midia.grande{ color: var(--accent-orange-text); }
    /* O segundo palco do visor. Um dos dois fica `hidden` por vez, e o par `display:none` está
       declarado porque o display de autor vence a regra de UA. */
    .precs-wa-visor-video{ display: block; max-width: 92vw; max-height: 80vh; }
    .precs-wa-visor-video[hidden], .precs-wa-visor-img[hidden]{ display: none; }

    /* ======================================================================
       (1.1.103, 21/09/2026) A LIGAÇÃO PELA CALLING API.

       Três peças: o botão "ligar" no cabeçalho da conversa (herda .precs-wa-etiq-btn, como o de
       etiquetar e o de lembrar), a FAIXA de chamada que ocupa o lugar dele enquanto a ligação
       vive (cronômetro e botão de desligar), e o AVISO de chamada entrando no topo da lista, com
       atender e recusar. Mais a bolha de sistema na thread, no vocabulário do divisor de
       "mensagens não lidas": um evento da conversa, não uma fala.

       As cores são as de ESTADO do painel e nunca mudam por tema: verde é "em chamada" (o mesmo
       da tabela da supervisão), o ouro é transição (chamando, tocando) e o vermelho é desligar
       e recusar. Nenhum token novo: token novo num tema obriga os 21. */
    .precs-wa-lig-faixa{ display: inline-flex; align-items: center; gap: var(--space-2);
      height: 30px; padding: 0 var(--space-3); border: 1px solid var(--border-color);
      border-radius: var(--radius-pill); color: var(--text-secondary);
      font-family: var(--font-acao); font-size: var(--fs-4); font-weight: 700; }
    .precs-wa-lig-faixa b{ font-weight: 700; white-space: nowrap; }
    .precs-wa-lig-faixa i{ font-style: normal; color: var(--text-muted); font-weight: 600; }
    .precs-wa-lig-faixa svg{ flex: 0 0 auto; }
    .precs-wa-lig-faixa.discando, .precs-wa-lig-faixa.tocando, .precs-wa-lig-faixa.atendendo{
      color: var(--precs-gold); border-color: var(--precs-gold); }
    .precs-wa-lig-faixa.em-chamada{ color: var(--accent-green); border-color: var(--accent-green);
      background: var(--accent-green-light); }
    .precs-wa-lig-faixa.em-chamada .precs-wa-lig-cron{ color: var(--accent-green);
      font-variant-numeric: tabular-nums; min-width: 5ch; }
    .precs-wa-lig-faixa.tocando > svg:first-child, .precs-wa-lig-faixa.discando > svg:first-child,
    .precs-wa-lig-faixa.atendendo > svg:first-child{
      animation: precsWaLigPulso 1.1s var(--ease-1) infinite; }
    @keyframes precsWaLigPulso{ 0%, 100%{ transform: scale(1); opacity: 1; }
      50%{ transform: scale(1.2); opacity: .65; } }
    .precs-wa-lig-faixa.fim{ color: var(--text-muted); }
    .precs-wa-lig-faixa.sem-permissao{ color: var(--accent-orange-text); border-color: var(--accent-orange); }
    .precs-wa-lig-desligar, .precs-wa-lig-pedir{ display: inline-flex; align-items: center;
      justify-content: center; height: 22px; min-width: 22px; padding: 0 var(--space-2);
      cursor: pointer; border: 1px solid transparent; border-radius: var(--radius-pill);
      background: transparent; color: inherit; font-family: var(--font-acao);
      font-size: var(--fs-3); font-weight: 700;
      transition: background var(--dur-1) var(--ease-1), color var(--dur-1) var(--ease-1); }
    .precs-wa-lig-desligar{ color: var(--accent-red); }
    .precs-wa-lig-desligar:hover{ background: var(--accent-red-light); }
    .precs-wa-lig-pedir{ color: var(--precs-gold); border-color: var(--precs-gold); }
    .precs-wa-lig-pedir:hover{ background: color-mix(in srgb, var(--precs-gold) 12%, transparent); }
    .precs-wa-lig-quem{ max-width: 140px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
    /* (22/09/2026) A GRAVAÇÃO: o selo REC na faixa, a frase que o operador LÊ (decisão da
       Diretoria: o aviso é lido, então ele fica na frente de quem atende, e não numa dica de
       hover), e o botão de ouvir na bolha da chamada com o player que abre embaixo dela. */
    .precs-wa-lig-rec{ display: inline-flex; align-items: center; gap: var(--space-1);
      color: var(--accent-red); font-family: var(--font-acao); font-size: var(--fs-1);
      font-weight: 700; letter-spacing: var(--ls-caps); }
    .precs-wa-lig-rec i{ width: 7px; height: 7px; border-radius: var(--radius-pill);
      background: var(--accent-red); animation: precsWaLigPulso 1.6s var(--ease-1) infinite; }
    .precs-wa-lig-aviso{ display: inline-flex; align-items: center; margin-left: var(--space-2);
      padding: var(--space-1) var(--space-2); border-radius: var(--radius-pill);
      border: 1px dashed var(--accent-red); color: var(--accent-red-text);
      background: var(--accent-red-light);
      font-family: var(--font-corpo); font-size: var(--fs-2); }
    .precs-wa-lig-ouvir{ display: inline-flex; align-items: center; gap: var(--space-1);
      padding: 0 var(--space-2); cursor: pointer; border-radius: var(--radius-pill);
      border: 1px solid var(--border-color); background: transparent;
      color: var(--text-secondary); font-family: var(--font-acao); font-size: var(--fs-2);
      font-weight: 700;
      transition: color var(--dur-1) var(--ease-1), border-color var(--dur-1) var(--ease-1); }
    .precs-wa-lig-ouvir:hover{ color: var(--precs-gold); border-color: var(--precs-gold); }
    .precs-wa-lig-ouvir svg{ width: 11px; height: 11px; }
    .precs-wa-lig-player{ display: flex; justify-content: center; width: 100%;
      margin-top: var(--space-1);
      font-family: var(--font-corpo); font-size: var(--fs-2); color: var(--text-muted); }
    .precs-wa-lig-player[hidden]{ display: none; }
    .precs-wa-lig-player audio{ width: min(420px, 80%); height: 34px; }
    .precs-wa-msg.sistema.ligacao{ flex-wrap: wrap; }
    /* O aviso de chamada entrando, no topo da lista. O par `hidden`/`display:none` está
       declarado porque o display de autor vence a regra de UA (lição da 1.1.61). */
    .precs-wa-lig-entrando{ display: flex; align-items: center; gap: var(--space-2);
      margin: 0 var(--space-3) var(--space-2); padding: var(--space-2) var(--space-3);
      border: 1px solid var(--accent-green); border-radius: var(--radius-card);
      background: var(--accent-green-light); color: var(--text-primary); }
    .precs-wa-lig-entrando[hidden]{ display: none; }
    .precs-wa-lig-ent-ico{ display: inline-flex; flex: 0 0 auto; color: var(--accent-green);
      animation: precsWaLigPulso 1.1s var(--ease-1) infinite; }
    .precs-wa-lig-ent-txt{ flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; }
    .precs-wa-lig-ent-txt b{ font-family: var(--font-acao); font-size: var(--fs-4); font-weight: 700; }
    .precs-wa-lig-ent-txt i{ font-style: normal; font-size: var(--fs-3); color: var(--text-secondary);
      overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
    .precs-wa-lig-ent-btn{ flex: 0 0 auto; height: 28px; padding: 0 var(--space-3); cursor: pointer;
      border: 1px solid transparent; border-radius: var(--radius-pill);
      font-family: var(--font-acao); font-size: var(--fs-3); font-weight: 700;
      transition: filter var(--dur-1) var(--ease-1); }
    .precs-wa-lig-ent-btn:hover{ filter: brightness(1.08); }
    .precs-wa-lig-ent-btn.atender{ background: var(--accent-green); color: var(--on-accent-ink); }
    .precs-wa-lig-ent-btn.recusar{ background: transparent; color: var(--accent-red);
      border-color: var(--accent-red); }
    /* A bolha de sistema da chamada: centrada, sem balão, no desenho do divisor de não lidas. */
    .precs-wa-msg.sistema{ justify-content: center; }
    .precs-wa-lig-bolha{ display: inline-flex; align-items: center; gap: var(--space-2);
      padding: var(--space-1) var(--space-3); border-radius: var(--radius-pill);
      border: 1px solid var(--border-color); background: var(--bg-secondary);
      color: var(--text-secondary); font-family: var(--font-corpo); font-size: var(--fs-3); }
    .precs-wa-lig-bolha > svg{ color: var(--accent-green); flex: 0 0 auto; }
    .precs-wa-lig-bolha.perdida > svg{ color: var(--accent-red); }
    .precs-wa-lig-bolha .precs-wa-msg-hora{ font-style: normal; color: var(--text-muted); }
    /* (22/09/2026) A PERMISSÃO DE CHAMADA: o chip ao lado de "ligar" (verde vale; sem permissão
       vira o botão que abre o pedido), a marca na bolha da resposta e o popover do texto editável
       (herda .precs-wa-lemb-pop, que já tem posição, sombra e camada). */
    .precs-wa-lig-perm-chip{ display: inline-flex; align-items: center; gap: var(--space-1);
      height: 22px; padding: 0 var(--space-2); border-radius: var(--radius-pill);
      border: 1px solid var(--border-color); background: transparent; color: var(--text-muted);
      font-family: var(--font-acao); font-size: var(--fs-2); font-weight: 700; cursor: pointer;
      transition: color var(--dur-1) var(--ease-1), border-color var(--dur-1) var(--ease-1); }
    .precs-wa-lig-perm-chip:hover{ color: var(--precs-gold); border-color: var(--precs-gold); }
    .precs-wa-lig-perm-chip svg{ width: 11px; height: 11px; }
    .precs-wa-lig-perm-chip.ok{ color: var(--accent-green-text); border-color: var(--accent-green);
      background: var(--accent-green-light); cursor: default; }
    .precs-wa-lig-perm-chip.ok:hover{ color: var(--accent-green-text); border-color: var(--accent-green); }
    .precs-wa-lig-perm-chip.nao{ color: var(--accent-red-text); border-color: var(--accent-red); }
    /* (22/09/2026) A resposta ao pedido de permissão virou EVENTO (pílula centrada, como a
       chamada), então ela usa `.precs-wa-lig-bolha` e não precisa de marca dentro do balão. */
    .precs-wa-perm-pop{ min-width: 300px; max-width: 360px; }
    .precs-wa-perm-txt{ display: block; width: 100%; min-height: 84px; resize: vertical;
      box-sizing: border-box; padding: var(--space-2); margin: 0;
      border: 1px solid var(--border-color); border-radius: var(--radius-inner);
      background: var(--bg-primary); color: var(--text-primary);
      font-family: var(--font-corpo); font-size: var(--fs-4); }
    .precs-wa-perm-txt:focus-visible{ outline: 2px solid var(--precs-gold); outline-offset: 1px; }
    .precs-wa-perm-dica{ display: block; padding: var(--space-1) var(--space-2);
      font-family: var(--font-corpo); font-size: var(--fs-2); color: var(--text-muted); }
    .precs-wa-perm-acoes{ display: flex; justify-content: flex-end; gap: var(--space-2);
      padding: var(--space-1) var(--space-2) var(--space-2); }

/* ==========================================================================
   (22/09/2026) O PLAYER DE GRAVAÇÃO
   --------------------------------------------------------------------------
   Ele substitui o `<audio controls>` nativo, e o motivo está no app.js: o widget do navegador
   não é alcançável por CSS, então era o único retângulo da tela que ignorava o tema. Aqui tudo
   sai de token, e no PRECS Claro ele vira claro junto com o resto.

   A BARRA TEM ALTURA DE TOQUE MAIOR QUE A DE DESENHO. O fio visível tem 4px; a área que recebe
   o `pointerdown` tem a altura da linha inteira, por `padding` vertical no trilho. Barra de
   4px é fácil de ler e difícil de acertar, e quem está conferindo uma gravação arrasta muito.
   ========================================================================== */
/* Sem `display` de autor aqui: o container que recebe a classe ja tem o dele (a bolha da
   thread centra, a linha da aba nao), e sobrescrever faria o player da thread sair do centro.
   O `<audio>` cru fica escondido — quem desenha e o `.precs-aud-cx`. */
.precs-aud{ width: 100%; }
.precs-aud audio{ display: none; }
.precs-wa-lig-player.precs-aud .precs-aud-cx{ max-width: 460px; margin: 0 auto; }
.precs-aud-cx{
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  background: var(--bg-tertiary);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-inner);
}
.precs-aud-b{
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  min-width: 26px;
  height: 26px;
  padding: 0 var(--space-1);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-sm);
  background: var(--bg-secondary);
  color: var(--text-secondary);
  font-family: var(--font-acao);
  font-size: var(--fs-3);
  cursor: pointer;
  text-decoration: none;
  transition: background var(--dur-1) var(--ease-1), color var(--dur-1) var(--ease-1),
              border-color var(--dur-1) var(--ease-1);
}
/* ATENCAO AO TOKEN: `--precs-gold-soft` e uma COR DE OURO (#D2AE52 no escuro), e nao um
   fundo suave — o nome engana. Usado como `background` com texto dourado por cima, o
   rotulo some: foi o que aconteceu com o chip aceso e com o botao de ouvir, medido na
   tela do Pedro em 22/09/2026. O fundo suave da marca e `--precs-gold-light`, que ja e
   um rgba de 16%. */
.precs-aud-b:hover{
  background: var(--precs-gold-light);
  border-color: var(--precs-gold);
  color: var(--precs-gold-title);
}
.precs-aud-b:focus-visible{ outline: 2px solid var(--precs-gold); outline-offset: 1px; }
.precs-aud-play{ color: var(--precs-gold-title); }
.precs-aud.tocando .precs-aud-play{ background: var(--precs-gold-light); border-color: var(--precs-gold); }
.precs-aud-vel{ font-variant-numeric: tabular-nums; }

/* O trilho: `padding` vertical grande e fio fino dentro, para o alvo do dedo ser a linha toda
   sem que o desenho engorde. O `--pos` do preenchido é escrito pelo JS em porcentagem. */
.precs-aud-trilho{
  position: relative;
  flex: 1 1 auto;
  min-width: 0;
  height: 4px;
  margin: var(--space-2) 0;
  border-radius: var(--radius-pill);
  background: var(--border-color);
  cursor: pointer;
  touch-action: none;
}
.precs-aud-trilho::before{
  content: '';
  position: absolute;
  inset: calc(var(--space-2) * -1) 0;
}
.precs-aud-feito{
  height: 100%;
  width: 0;
  border-radius: var(--radius-pill);
  background: var(--precs-gold);
  pointer-events: none;
}
.precs-aud-bola{
  position: absolute;
  top: 50%;
  left: 0;
  width: 10px;
  height: 10px;
  margin-left: -5px;
  border-radius: var(--radius-pill);
  background: var(--precs-gold-light);
  transform: translateY(-50%) scale(0);
  transition: transform var(--dur-1) var(--ease-1);
  pointer-events: none;
}
.precs-aud-trilho:hover .precs-aud-bola,
.precs-aud-trilho.arrastando .precs-aud-bola,
.precs-aud-trilho:focus-visible .precs-aud-bola{ transform: translateY(-50%) scale(1); }
.precs-aud-trilho:focus-visible{ outline: 2px solid var(--precs-gold); outline-offset: 4px; }
.precs-aud-t{
  flex: 0 0 auto;
  font-family: var(--font-num);
  font-size: var(--fs-3);
  color: var(--text-secondary);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.precs-aud-t i{ color: var(--text-muted); font-style: normal; padding: 0 var(--space-0); }
.precs-aud-t b{ color: var(--text-muted); font-weight: 400; }
.precs-aud.falhou .precs-aud-cx{ border-color: var(--accent-red); }

/* ==========================================================================
   (22/09/2026) A MENSAGEM APAGADA
   --------------------------------------------------------------------------
   Ela continua legível, e isso é a decisão — ver `precsWaApagadaHTML` no app.js. O que muda é
   o PESO: o balão fica com a borda tracejada e o texto um pouco recuado, para o olho separar
   "o que está valendo" de "o que foi retirado" sem ter de ler a etiqueta em cada bolha.

   Vermelho no rótulo e não no balão inteiro: o vocabulário de estado do painel reserva o
   vermelho para o que exige ação, e uma mensagem apagada é um FATO, não um problema. Tingir o
   balão faria uma conversa com cinco apagamentos parecer uma conversa em chamas.
   ========================================================================== */
.precs-wa-msg.apagada .precs-wa-balao{
  border: 1px dashed var(--accent-red);
  opacity: .82;
}
.precs-wa-msg.apagada .precs-wa-texto{ font-style: italic; }
.precs-wa-apagada{
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  margin-bottom: var(--space-1);
  font-family: var(--font-rotulo);
  font-size: var(--fs-2);
  letter-spacing: var(--ls-caps);
  text-transform: uppercase;
  color: var(--accent-red-text);
  cursor: help;
}

    /* ==========================================================================
       (1.1.142) A AMPLIADA DA PAREDE NO CELULAR ("a tela de dentro não está configurada pro celular", Pedro,
       25/09/2026). A parede no celular já existia (html[data-tv][data-aparelho]); a ampliada não: o número gigante
       era `--tv-rosca` em vh, o corpo `overflow: hidden` (na TV o que não cabe some, aqui rola), o X ficava
       escondido pela regra da TV e a dica "Esc volta" não fala com dedo. Aqui: tela cheia, rolagem, uma coluna
       no topo (rosca, número e ritmo um embaixo do outro), rosca e número medidos pela LARGURA, o X à vista e
       grande, e as dicas de teclado fora. O botão voltar do aparelho também fecha (precsNavInstalar).
       ========================================================================== */
    html[data-tv][data-aparelho] .precs-tvamp-overlay{ align-items: stretch; justify-content: stretch; }
    html[data-tv][data-aparelho] .precs-tvamp-modal{ width: 100vw; height: 100dvh; border: 0; border-radius: 0; }
    html[data-tv][data-aparelho] .precs-tvamp-head{ gap: var(--space-2); padding: var(--space-3) var(--space-3) var(--space-3) var(--space-4); }
    html[data-tv][data-aparelho] .precs-tvamp-head .precs-prefs-close{ display: inline-flex; width: 40px; height: 40px; align-items: center; justify-content: center; }
    html[data-tv][data-aparelho] .precs-tvamp-dicas{ display: none; }
    html[data-tv][data-aparelho] .precs-tvamp-body{ overflow-y: auto; overflow-x: hidden; padding: var(--space-3); }
    html[data-tv][data-aparelho] .precs-tvamp-topo{ grid-template-columns: minmax(0, 1fr); justify-items: center; text-align: center; gap: var(--space-3); --tv-rosca: clamp(96px, 36vw, 160px); }
    html[data-tv][data-aparelho] .precs-tvamp-num{ min-width: 0; max-width: 100%; }
    html[data-tv][data-aparelho] .precs-tvamp-ritmo{ width: 100%; }
    html[data-tv][data-aparelho] .precs-tvamp-kpis{ grid-template-columns: repeat(2, minmax(0, 1fr)); }

    /* (1.1.146) O credor da ligação em curso, dentro do modal de modelos. */
    .precs-wa-tpl-credor{ display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2) var(--space-3);
      padding: var(--space-2) var(--space-3); margin-bottom: var(--space-3);
      border: 1px solid var(--border-color); border-left: 3px solid var(--precs-gold); border-radius: var(--radius-inner);
      background: var(--bg-tertiary); }
    .precs-wa-tpl-credor-rot{ font-family: var(--font-rotulo); font-size: var(--fs-1); font-weight: 700; letter-spacing: var(--ls-caps);
      text-transform: uppercase; color: var(--text-muted); }
    .precs-wa-tpl-credor b{ font-family: var(--font-corpo); font-size: var(--fs-4); color: var(--text-primary); }
    .precs-wa-tpl-credor-usar{ margin-left: auto; font-family: var(--font-acao); font-size: var(--fs-2); font-weight: 600;
      padding: var(--space-1) var(--space-3); border: 1px solid var(--border-color); border-radius: var(--radius-pill);
      background: var(--bg-secondary); color: var(--precs-gold-title); cursor: pointer; }
    .precs-wa-tpl-credor-usar:hover{ border-color: var(--precs-gold); }

    /* (1.1.150) os dois botões do credor da ligação (primeiro nome / nome completo) */
    .precs-wa-tpl-credor-btns{ margin-left: auto; display: inline-flex; gap: var(--space-2); flex-wrap: wrap; }
    .precs-wa-tpl-credor-btns .precs-wa-tpl-credor-usar{ margin-left: 0; }
