
    /* ===================== POLIMENTO DO MENU PRINCIPAL ===================== */
    /* (1) Entrada em cascata das colunas da home + itens internos. */
    @keyframes precsHomeIn { from { opacity:0; transform:translateY(10px); } to { opacity:1; transform:translateY(0); } }
    .precs-campaigns-grid > .panel { animation: precsHomeIn .42s var(--ease-2) both; }
    .precs-campaigns-grid > .panel:nth-child(1){ animation-delay:.02s; }
    .precs-campaigns-grid > .panel:nth-child(2){ animation-delay:.09s; }
    .precs-campaigns-grid > .panel:nth-child(3){ animation-delay:.16s; }
    /* PRECS (1.1.4) — `backwards`, e NÃO `both`. Com `both`, a animação de entrada segue
       DONA de opacity e transform depois de terminar (é o fill forwards), e valor animado
       vence declaração comum de CSS por mais específica que ela seja. O efeito é que duas
       regras deste mesmo arquivo nunca funcionaram: o `opacity: .4` das campanhas apagadas
       enquanto uma está sendo selecionada, e o `translateY(-2px)` do hover do card. Medido:
       com `both`, getComputedStyle do item apagado devolvia opacity 1.
       `backwards` mantém o que interessa — o estado inicial durante o animation-delay, que
       é o que faz o escalonamento — e devolve as propriedades ao CSS quando acaba. */
    .campaign-list .campaign-item,
    .precs-ultima-lead-corpo .precs-hist-item { animation: precsHomeIn .34s var(--ease-2) backwards; }
    .campaign-list .campaign-item:nth-child(1),
    .precs-ultima-lead-corpo .precs-hist-item:nth-child(1){ animation-delay:.14s; }
    .campaign-list .campaign-item:nth-child(2),
    .precs-ultima-lead-corpo .precs-hist-item:nth-child(2){ animation-delay:.20s; }
    .campaign-list .campaign-item:nth-child(3),
    .precs-ultima-lead-corpo .precs-hist-item:nth-child(3){ animation-delay:.26s; }
    .campaign-list .campaign-item:nth-child(4),
    .precs-ultima-lead-corpo .precs-hist-item:nth-child(4){ animation-delay:.32s; }
    .campaign-list .campaign-item:nth-child(n+5),
    .precs-ultima-lead-corpo .precs-hist-item:nth-child(n+5){ animation-delay:.38s; }

    /* PRECS — entrada escalonada das qualificações (TPA), reusando o mesmo
       keyframe. Dá fluidez quando o painel de qualificação aparece. */
    /* O alvo do stagger é o .qualification-slot (filho direto da lista); o
       .qualification-item deixou de ser filho direto ao ganhar o wrapper. */
    .qualification-list .qualification-slot { animation: precsHomeIn .30s var(--ease-2) both; }
    .qualification-list .qualification-slot:nth-child(1){ animation-delay:.03s; }
    .qualification-list .qualification-slot:nth-child(2){ animation-delay:.06s; }
    .qualification-list .qualification-slot:nth-child(3){ animation-delay:.09s; }
    .qualification-list .qualification-slot:nth-child(4){ animation-delay:.12s; }
    .qualification-list .qualification-slot:nth-child(5){ animation-delay:.15s; }
    .qualification-list .qualification-slot:nth-child(6){ animation-delay:.18s; }
    .qualification-list .qualification-slot:nth-child(n+7){ animation-delay:.21s; }

    /* (2) Hover mais rico nos itens recentes: leve realce + acento dourado à esquerda. */
    .precs-hist-item { transition: background-color var(--dur-1) ease, box-shadow var(--dur-1) ease; }
    .precs-ultima-lead-corpo .precs-hist-item:hover {
      background: color-mix(in srgb, var(--precs-gold,#B49552) 10%, transparent);
      box-shadow: inset 3px 0 0 var(--precs-gold,#B49552);
    }

    /* (3) O anel de foco dourado já é global (:focus-visible acima). Aqui só o
       realce dourado sutil no cabeçalho da coluna de campanhas (ação principal). */
    .precs-campaigns-col .panel-header { color: var(--precs-gold,#B49552); }

    /* ===================== TIPOGRAFIA DA MARCA (1.0.8) =====================
       Sora (títulos), Poppins (corpo/H2), Montserrat (subtítulos/labels),
       Manrope (botões/CTAs). JetBrains Mono segue nos números/protocolos. */
    /* (1.1.6) .manual-header-title entrou na lista. Era o último título de 1,5rem/700 do
       painel herdando Poppins, então a Discagem Manual abria com um tipo diferente do
       resto — e é justamente a tela onde o operador digita o número, ou seja, onde ele
       para e lê. Não custa peso novo: já é 700, e o <link> do Google Fonts baixa
       Sora 600;700. Quem acrescentar mais um seletor aqui precisa conferir isso, senão o
       teste-fontes.js reprova (ele lê o getComputedStyle de todo elemento e compara com os
       pesos que o <link> de fato pede). */
    .precs-welcome-greet, .campaign-header-name, #active-campaign-name,
    .manual-header-title {
      font-family: var(--font-titulo); letter-spacing: -0.01em;
    }
    /* O telefone da ligação é um <h2> de verdade e o tamanho dele vinha num style
       inline no markup — único tamanho de tipo do projeto definido fora do CSS. */
    #call-phone-campaign { font-size: 1.25rem; }
    .panel-header, .precs-col-titulo, .og-head, .detail-label, .precs-prefs-label,
    .hist-th, .precs-tempos-titulo, .precs-welcome-sub {
      font-family: var(--font-rotulo);
    }
    /* PRECS (1.1.0) — a lista de CTAs cobria 5 seletores e deixava sete botões de
       fora, herdando Poppins do body: o ✕ e o "Apagar" do modal de frases, o ✕ de
       Preferências, o "i" de ajuda da qualificação, o botão de vincular negócio no
       manual, o "Fechar" da barra de DTMF e o ícone do modo manual. Todos são ação,
       então todos são Manrope. O sintoma era discreto e por isso durou: dois botões
       lado a lado no mesmo modal com desenho de letra diferente. */
    .btn, .btn-3cplus, .precs-theme-btn, .mode-btn, .dial-btn,
    .precs-prefs-close, .precs-frases-x, .precs-frases-del, .qual-info-btn,
    .precs-mvinc-btn, .precs-dtmf-bar-x, .btn-icon-manual {
      font-family: var(--font-acao); letter-spacing: 0.01em;
    }
    /* ====================================================================== */
    /* (6) Microinteração de confirmação: ao enviar a qualificação, o botão pisca
       verde com um "✓ Enviada!" antes do painel desvanecer. */
    /* PRECS — texto do flash "✓ Enviada!" era #fff sobre o verde --st-call: 1,90:1 no
       tema precs e 2,56:1 no claro, ou seja, ilegível justamente na confirmação que o
       operador vê a CADA ligação. Trocado por texto escuro, que passa em todos os temas
       (7,3:1 no claro, 13,4:1 no contraste) porque --st-call é sempre um verde claro. */
    .precs-ok-flash { background: var(--st-call) !important; border-color: var(--st-call) !important; color:#0F1115 !important; animation: precsOkPulse .4s ease; }
    @keyframes precsOkPulse { 0%{ transform:scale(1) } 40%{ transform:scale(1.03) } 100%{ transform:scale(1) } }
    @media (prefers-reduced-motion: reduce){ .precs-ok-flash { animation: none; } }

    @media (prefers-reduced-motion: reduce) {
      .precs-campaigns-grid > .panel,
      .campaign-list .campaign-item,
      .qualification-list .qualification-slot,
      .qual-checklist .qc-task,
      .precs-ultima-lead-corpo .precs-hist-item { animation: none; }
      /* checklist abre/fecha e marca sem transição (aparece instantânea) */
      .qual-checklist,
      .qc-check, .qc-check .qc-ring, .qc-check .qc-tick { transition: none; }
      /* pulso de confirmação do check também respeita reduced-motion */
      .qc-task.done .qc-check .qc-ic { animation: none; }
    }
    /* ====================================================================== */

    /* ===================== POLIMENTO VISUAL (1.0.6) ===================== */
    /* SCROLLBAR (definição única) — fina e discreta, para as áreas que rolam por
       dentro: mailing, Meu Desempenho, histórico de anotações. Este é o ÚNICO lugar
       que estiliza a scrollbar global; havia um segundo bloco antes deste no arquivo
       que nunca teve efeito e foi removido em 1.1.0. Ajuste aqui. */
    * { scrollbar-width: thin; scrollbar-color: var(--border-color) transparent; }
    ::-webkit-scrollbar { width: 9px; height: 9px; }
    ::-webkit-scrollbar-track { background: transparent; }
    ::-webkit-scrollbar-thumb { background: var(--border-color); border-radius: var(--radius-sm); border: 2px solid transparent; background-clip: padding-box; }
    ::-webkit-scrollbar-thumb:hover { background: var(--precs-gold, var(--accent-3cplus, #B49552)); background-clip: padding-box; }
    /* PRECS — faz o Chrome renderizar scrollbar nativa e controles em modo escuro
       nos temas escuros (antes a barra saía clara). No claro, mantém claro. */
    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"] { color-scheme: dark; }
    html[data-luz="claro"] { color-scheme: light; }

    /* PRECS (1.1.0) — TRANSIÇÃO NA TROCA DE TEMA. Trocar entre os 3 temas era um corte
       seco: 40 tokens de cor mudavam no mesmo frame e a tela dava um estalo. Escolher
       tema é a customização mais visível do produto, e merece acabamento.
       A classe é posta e retirada por precsSetTema (busque `precs-trocando-tema` no
       script do fim do arquivo) para que isto NÃO valha no primeiro paint nem em
       regime — ver o comentário de lá. O seletor universal é aceitável justamente
       porque só vive ~260ms.
       `background-color` e não `background`: o shorthand engoliria os gradientes
       (faixa de boas-vindas, botão do modo manual) e eles piscariam do zero. */
    html.precs-trocando-tema, html.precs-trocando-tema * {
      transition: background-color .22s ease, color .22s ease,
                  border-color .22s ease, fill .22s ease, stroke .22s ease !important;
    }
    @media (prefers-reduced-motion: reduce) {
      html.precs-trocando-tema, html.precs-trocando-tema * { transition: none !important; }
    }

    /* ====================================================================== */
    /* (1.1.39) A TROCA DE TEMA COMO CRUZAMENTO DE IMAGENS (View Transition)   */
    /* ====================================================================== */
    /* A regra acima continua existindo como plano B (ver `precsTrocaDeTema` no index.html).
       Quando o navegador tem View Transition — o Chrome do painel tem —, quem cruza são
       DUAS FOTOS da tela, e não N elementos interpolando cor cada um por conta.

       Por que isso importa em número, e não só em teoria: com o modo WhatsApp aberto (40
       conversas, 80 mensagens na thread) a página passa de ~870 para ~2600 nós, e o seletor
       universal media 66,7ms por quadro. O mesmo cenário pelo cruzamento de imagens mede
       16,7ms — o custo deixou de depender do tamanho da tela e passou a depender só do
       compositor, que é onde animação deve viver.

       O TETO É O MONITOR. Página nenhuma passa da taxa de atualização da tela: o ganho aqui
       é sair de ~15 quadros por segundo e passar a entregar o que a máquina der (60Hz, 120Hz,
       144Hz), sem quadro perdido no meio.

       A CURVA: `ease-out` com a saída um pouco mais curta que a entrada. O tema novo aparece
       ganhando presença enquanto o antigo se apaga mais rápido, o que evita o meio-do-caminho
       leitoso das duas imagens a 50% — que é o que faz um cross-fade parecer sujo. */
    ::view-transition-old(root){
      animation: precsTemaSai 200ms var(--ease-3) both;
    }
    ::view-transition-new(root){
      animation: precsTemaEntra 320ms cubic-bezier(0,0,.2,1) both;
    }
    @keyframes precsTemaSai{  from{ opacity: 1; } to{ opacity: 0; } }
    @keyframes precsTemaEntra{ from{ opacity: 0; } to{ opacity: 1; } }
    /* O grupo padrão do `root` também anima tamanho e posição; aqui nada muda de geometria,
       e deixar o grupo animando só adiciona trabalho ao compositor. */
    ::view-transition-group(root){ animation-duration: 320ms; }
    @media (prefers-reduced-motion: reduce){
      ::view-transition-old(root), ::view-transition-new(root),
      ::view-transition-group(root){ animation: none !important; }
    }

    /* Ícones SVG dos títulos (no lugar de emoji): herdam a cor do título e
       renderizam iguais em qualquer navegador/SO. */
    .ph-ico { width: 16px; height: 16px; vertical-align: -3px; margin-right: 6px; stroke: currentColor; fill: none; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; flex: 0 0 auto; }

    /* Skeleton do card da lead (usa .precs-skel-bar, que já tem shimmer) */
    .precs-skel-card { background: var(--lead-surface); border: 1px solid var(--lead-border); border-radius: var(--radius-card); padding: var(--space-5) var(--space-6); }

    /* PRECS (6.1) — aqui existia uma SEGUNDA declaração de .precs-avatar, rotulada
       "Avatar com iniciais no card da lead": 40px, fundo em gradiente dourado e texto
       #1a1a1a. Ela era resto de um desenho anterior, porque o card da lead não mostra
       mais avatar nenhum. Como vinha DEPOIS da declaração viva (linha ~1624) e com a
       mesma especificidade, ela vencia em width, height e background — e, por estar
       depois de .precs-avatar-ini também, invertia as cores das iniciais: dourado
       chapado com texto escuro, em vez de dourado sobre fundo tingido.
       Efeito de remover: o avatar do topo volta aos 36px com o anel dourado, e as
       iniciais (operador sem foto cadastrada, que é a maioria em 10/08) voltam a ser
       douradas sobre fundo tingido. Nada mais no arquivo usa a versão de 40px. */

    /* Estados vazios amigáveis */
    .precs-empty { display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; padding: 2.5rem var(--space-6); color: var(--text-muted); gap: var(--space-1); }
    .precs-empty-ic { width: 34px; height: 34px; stroke: var(--text-muted); fill: none; stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; opacity: .7; margin-bottom: var(--space-1); }
    .precs-empty-t { font-size: .9rem; font-weight: 600; color: var(--text-secondary); }
    .precs-empty-s { font-size: .78rem; }
    /* PRECS (1.1.0) — entrada suave do estado vazio. O que aparece antes dele é o
       skeleton, que PULSA; a troca de um elemento animado por um estático no mesmo
       frame lia como corte. Só opacidade, sem deslocamento: o vazio não deve chamar
       mais atenção que o conteúdo chamaria. */
    /* (1.1.6) Passou de `.22s ease` para a curva canônica de entrada do projeto,
       cubic-bezier(.16,1,.3,1), e para .28s porque com .22s a curva não tem onde acontecer.
       Motivo de mexer num detalhe destes: .precs-empty é o padrão mais repetido do painel
       (28 pontos de chamada no app.js) e era o único que entrava com uma curva diferente de
       todo o resto — o operador não sabe nomear isso, mas percebe que "um card aparece de
       um jeito e o outro de outro". Continua sendo só opacidade: o vazio não deve chamar
       mais atenção que o conteúdo chamaria. */
    .precs-empty { animation: precsEmptyIn .28s var(--ease-2) both; }
    @keyframes precsEmptyIn { from { opacity: 0; } to { opacity: 1; } }
    @media (prefers-reduced-motion: reduce) { .precs-empty { animation: none; } }

    /* PRECS (1.1.0) — AVISO INLINE, irmão menor do .precs-empty. São dois padrões
       diferentes de propósito: .precs-empty é o painel (ícone de 34px, título,
       subtítulo, 2,5rem de respiro) e serve quando o vazio OCUPA o card; este é uma
       linha de texto para quando o vazio acontece DENTRO de uma tabela ou lista densa,
       onde o painel ficaria desproporcional. Existia sem nome: eram oito pontos
       espalhados usando .precs-empty-s solta com padding inline diferente em cada um
       (.4rem 0, .5rem 0, 1rem) e dois deles repetindo color:var(--accent-red) à mão. */
    .precs-empty-inline { font-size: .78rem; color: var(--text-muted); padding: var(--space-2) var(--space-3); }
    .precs-empty-inline.erro { color: var(--accent-red); }

    /* Tooltips customizados (dourado) — qualquer elemento com data-tip */
    /* (1.1.45) `:focus-visible` entrou ao lado de `:hover` aqui e nas duas regras abaixo: a
       dica só existia para o ponteiro, então quem navega por Tab não tinha como ler o que o
       controle faz. `:focus-visible` e não `:focus` de propósito — no clique o balão não deve
       aparecer, porque o mouse já teve o dele pelo `:hover` e um segundo balão preso depois
       do clique é ruído. É o mesmo critério do balão em JS (`precsTipBind`). */
    [data-tip] { position: relative; }
    [data-tip]:hover::after,
    [data-tip]:focus-visible::after {
      content: attr(data-tip); position: absolute; bottom: calc(100% + 8px); left: 50%; transform: translateX(-50%);
      background: var(--bg-tertiary); color: var(--text-primary); border: 1px solid var(--precs-gold, var(--border-color));
      padding: var(--space-1) var(--space-2); border-radius: var(--radius-sm); font-size: .72rem; font-weight: 600; white-space: nowrap; z-index: 10000;
      box-shadow: var(--shadow); pointer-events: none; animation: precsTipEntra .18s ease;
    }
    /* Botões no topo do header (Preferências, modo WhatsApp): o tooltip precisa abrir
       para BAIXO, senão fica acima do botão e é cortado pela borda da tela/header —
       foi exatamente o relato do botão do WhatsApp em 24/08/2026 ("ficou meio comido"):
       a regra cobria só a engrenagem, e o botão novo herdou o padrão para cima. */
    #precs-prefs-btn[data-tip]:hover::after,
    #precs-wa-btn[data-tip]:hover::after,
    #precs-prefs-btn[data-tip]:focus-visible::after,
    #precs-wa-btn[data-tip]:focus-visible::after {
      bottom: auto; top: calc(100% + 8px);
    }
    /* (1.1.10) A CENTRALIZAÇÃO SOBREVIVE À ANIMAÇÃO DE ENTRADA.
       `pmFade` (compartilhada com os modais) anima `transform: translateY(4px) -> translateY(0)`,
       e essa propriedade SUBSTITUI o `translateX(-50%)` que centraliza o balão — durante os
       180ms da animação ele aparecia deslocado meia-largura para a direita e escorregava para o
       lugar. Foi o relato "o tooltip começa num lugar e depois vai para outro". Keyframes
       próprios, que carregam a translação horizontal nos dois quadros, resolvem sem tocar na
       pmFade dos modais.
       Sobrou para o botão de Preferências, que é quem ainda usa `data-tip`: o resto do painel
       migrou para `data-tipv` (ver o bind no init do app.js), que vive no body com
       position:fixed e por isso não é cortado por ancestral com overflow — que era o defeito do
       balão do "Integração". */
    @keyframes precsTipEntra {
      from { opacity: 0; transform: translateX(-50%) translateY(4px); }
      to   { opacity: 1; transform: translateX(-50%) translateY(0); }
    }

    /* ====================================================================== */
    /* (1.1.10) FOTO DO OPERADOR EM TAMANHO GRANDE                            */
    /* ---------------------------------------------------------------------- */
    /*  O avatar clicável ganha só um convite discreto: cursor de mão e um leve realce do anel
        da faixa. Nada de escala no hover — este elemento fica ao lado do nome no header, e
        crescer ali empurraria o layout do cabeçalho a cada passada de mouse. */
    .precs-avatar-abre { cursor: pointer; transition: box-shadow var(--dur-1) ease, filter var(--dur-1) ease; }
    .precs-avatar-abre:hover { filter: brightness(1.06); }
    .precs-avatar-abre:hover, .precs-avatar-abre:focus-visible {
      box-shadow: 0 0 0 3px color-mix(in srgb, var(--precs-faixa-cor, var(--precs-gold, #B49552)) 45%, transparent);
    }
    .precs-foto-overlay {
      position: fixed; inset: 0; z-index: 10050;
      display: none; align-items: center; justify-content: center;
      background: color-mix(in srgb, #000 72%, transparent);
      backdrop-filter: blur(3px);
      opacity: 0; transition: opacity .18s ease;
      cursor: zoom-out;
    }
    .precs-foto-overlay.open { display: flex; opacity: 1; }
    .precs-foto-overlay.closing { opacity: 0; }
    .precs-foto-modal {
      margin: 0; display: flex; flex-direction: column; align-items: center; gap: var(--space-3);
      animation: precsFotoEntra .22s var(--ease-1);
    }
    .precs-foto-modal img {
      /* `contain` e não `cover`: a foto original não é necessariamente quadrada, e cortar o
         rosto de quem mandou retrato seria o oposto do ponto deste recurso. */
      max-width: min(74vw, 560px); max-height: 74vh; object-fit: contain;
      border-radius: var(--radius-card);
      border: 2px solid var(--precs-faixa-cor, var(--precs-gold, #B49552));
      box-shadow: var(--shadow-lg);
      background: var(--bg-secondary);
    }
    .precs-foto-modal figcaption {
      font-family: 'Manrope','Poppins',sans-serif; font-size: .82rem; font-weight: 600;
      letter-spacing: .02em; color: #F3F3F3;
      /* Cor fixa clara de propósito: o véu é escuro nos 5 estados de cor, então o token de
         texto do tema claro ficaria ilegível justamente aqui. */
      text-shadow: 0 1px 2px rgba(0,0,0,.6);
    }
    @keyframes precsFotoEntra {
      from { opacity: 0; transform: scale(.94); }
      to   { opacity: 1; transform: scale(1); }
    }
    @media (prefers-reduced-motion: reduce) {
      .precs-foto-overlay { transition: none; }
      .precs-foto-modal { animation: none; }
      .precs-avatar-abre { transition: none; }
    }

    /* Anel de foco dourado consistente para navegação por teclado (a11y) */
    :focus-visible {
      outline: 2px solid var(--precs-gold, var(--accent-blue));
      outline-offset: 2px; border-radius: var(--radius-sm);
    }
    /* mouse não dispara :focus-visible, então o clique fica limpo */

    /* Transição suave da COR DE ESTADO da campanha (ocioso→chamada→TPA), em vez
       de trocar seco. A faixa e o rótulo animam a cor. */
    /* A `transition` que ficava aqui foi removida em 1.1.0: a definição da própria
       .precs-state-bar (mais abaixo, junto de --precs-cor-estado) declara
       `transition: background .4s ease`, mesma especificidade e depois no arquivo,
       então esta perdia inteira e a transição real sempre foi a de lá. Se quiser
       animar box-shadow na barra, acrescente na regra de baixo, não aqui. */
    /* Micro-animação: flash rápido na barra de estado ao CONECTAR a ligação. */
    @keyframes precsConectouFlash { 0% { filter: brightness(1.85); } 100% { filter: brightness(1); } }
    .precs-state-bar.precs-conectou { animation: precsConectouFlash .55s ease-out 1; }
    @media (prefers-reduced-motion: reduce) { .precs-state-bar.precs-conectou { animation: none; } }

    /* PRECS (1.1.2) — PULSO EM TODA TROCA DE ESTADO.
       O flash acima existia só para "conectada". Nas outras transições (entrar em
       TPA, sair para ocioso, entrar em manual) a faixa mudava de cor com uma
       transição de 400ms, e quem estivesse com os olhos no card do negócio ou na
       lista de qualificações simplesmente não via a mudança acontecer: ao voltar o
       olhar, a cor já era outra e não havia como saber QUANDO virou.
       É deliberadamente mais fraco que o precsConectouFlash: atender é o momento
       mais importante do ciclo e continua com o sinal mais forte. Este aqui só
       avisa "mudou", sem competir.
       As duas classes são mutuamente exclusivas no app.js, então nunca disputam a
       propriedade `animation`. */
    @keyframes precsTrocaEstado {
      0%   { filter: brightness(1.35); }
      100% { filter: brightness(1); }
    }
    .precs-state-bar.precs-troca { animation: precsTrocaEstado .4s ease-out 1; }
    @media (prefers-reduced-motion: reduce) { .precs-state-bar.precs-troca { animation: none; } }
    #campaign-header-status { transition: color .35s ease; }
    #campaign-active-section { transition: box-shadow .35s ease; }

    /* Botões e cards com micro-hover coerente (leve realce, sem exagero) */
    .btn { transition: background-color .18s ease, box-shadow .18s ease, transform .12s ease; }
    .btn:active { transform: translateY(1px); }

    /* Lote 3 — feedback tátil (:active) e anel de foco dourado nos controles que
       ainda usavam só o outline global: segmentos de Tema/Fonte, cards de modo,
       botão Ligar e o toggle manual. Puramente aditivo. */
    .mode-btn, .dial-btn, .precs-seg button, .btn-icon-manual {
      transition: background-color .18s ease, box-shadow .18s ease, transform .12s ease, color .18s ease;
    }
    .mode-btn:active, .dial-btn:active:not(:disabled),
    .precs-seg button:active, .btn-icon-manual:active { transform: translateY(1px); }
    /* (1.1.10) O ANEL DE FOCO VOLTOU A SER UM SÓ, e este bloco era o pior dos quatro.
       `outline:none` + box-shadow entregava 1px sólido mais uma faixa a 12–20% de alfa (o
       valor de --precs-gold-light em todos os temas), contra os 2px sólidos com folga que o
       padrão global de :focus-visible já dá. E cobria justamente os controles mais usados por
       teclado: seletor de modo, discar e o botão de manual. WCAG 2.2 SC 2.4.11 pede 2px de
       perímetro. O box-shadow fica como HALO POR FORA do outline: os dois somam em vez de um
       substituir o outro, então o realce dourado continua e o traço volta a existir. */
    .mode-btn:focus-visible, .dial-btn:focus-visible,
    .precs-seg button:focus-visible, .btn-icon-manual:focus-visible {
      outline: 2px solid var(--precs-gold, var(--accent-3cplus));
      outline-offset: 2px;
      box-shadow: 0 0 0 5px var(--precs-gold-light, rgba(180,149,82,.35));
    }
    @media (prefers-reduced-motion: reduce) {
      .mode-btn:active, .dial-btn:active, .precs-seg button:active, .btn-icon-manual:active { transform: none; }
    }

    /* Badge Pipedrive (últimas leads): ganha vida no hover */
    .precs-pipe-link { transition: transform .14s ease, box-shadow .18s ease, filter .18s ease; }
    .precs-pipe-link:hover { transform: translateY(-1px); filter: brightness(1.08); box-shadow: 0 3px 10px rgba(40,167,69,.35); }
    .precs-pipe-link:active { transform: translateY(0); }
    /* Botão de copiar telefone e pílula de qualificação: micro-hover coerente */
    .precs-hist-item .precs-tel-btn { transition: color var(--dur-1) ease, background-color var(--dur-1) ease, transform .12s ease; }
    .precs-hist-item .precs-tel-btn:hover { color: var(--precs-gold, var(--accent-3cplus, #B49552)); transform: translateY(-1px); }

    /* ===== TPA (qualificação) ===== */
    .qualification-item { position: relative; overflow: hidden; }
    /* PRECS — filete de cor à esquerda por qualificação (usa --qual-cor, a mesma
       cor da etiqueta). Ajuda a bater o olho e achar a opção certa no tempo do
       TPA. Discreto quando inativo, cheio no hover/selecionado. */
    .qualification-item::before {
      content: ''; position: absolute; left: 0; top: 0; bottom: 0; width: 4px;
      background: var(--qual-cor, var(--accent-blue));
      opacity: .5; transition: opacity .18s ease;
    }
    .qualification-item:hover::before,
    .qualification-item.selected::before { opacity: 1; }
    /* PRECS — badge do atalho de teclado (1 a 9). O CSS já existia mas o render nunca
       emitia o elemento, então o atalho funcionava e ninguém sabia que existia.
       Mudou de `position:absolute; right:12px` para chip em FLUXO, logo após o radio:
       naquela posição à direita ele ficava POR CIMA do botão "i" de ajuda, que é filho
       flex ancorado no fim da linha. À esquerda também lê melhor, como "aperte 4 para
       esta". Texto escuro no estado selecionado porque o fundo passa a ser a cor da
       qualificação: branco sobre o amarelo #eab308 dava 1,92:1. */
    /* (1.1.45) A APARÊNCIA DO BADGE VIROU UMA CLASSE SÓ, `.precs-tecla`.
       O desenho nasceu aqui para as teclas 1 a 9 e provou que funciona: é o único atalho do
       painel que o operador descobre sozinho. Agora que existem outras teclas (T, N, Esc, ?),
       elas usam a MESMA caixinha, para o operador aprender uma vez que caixinha = tecla e
       generalizar. `.qual-key` continua existindo como classe adicional nos itens de
       qualificação, porque só lá vale a inversão de tinta da regra logo abaixo — o fundo do
       item selecionado é a cor da qualificação, o que não acontece em nenhum outro badge. */
    .precs-tecla, .qual-key {
      flex: 0 0 auto;
      min-width: 18px; height: 18px; padding: 0 3px; border-radius: 5px;
      display: inline-flex; align-items: center; justify-content: center;
      font-size: .66rem; font-weight: 700; font-family: 'JetBrains Mono', monospace;
      color: var(--text-muted); background: var(--bg-tertiary); border: 1px solid var(--border-color);
      transition: color var(--dur-1) ease, background-color var(--dur-1) ease, border-color var(--dur-1) ease;
    }
    /* (1.1.10) A TINTA VEM DERIVADA, não cravada.
       Era `color:#0F1115` fixo sobre um fundo que é a COR DA QUALIFICAÇÃO. Funciona para as
       cores médias e falha nas pontas: Mudo e Caixa Postal são pretas, e o número desaparecia
       ao selecionar — nos três temas. Quem calcula agora é precsCorTextoContraste, no render,
       e o resultado chega em --qual-key-txt. O fallback continua escuro porque a maioria das
       cores da tabela é média-clara. */
    .qualification-item.selected .qual-key {
      color: var(--qual-key-txt, #0F1115);
      background: var(--qual-cor-anel, var(--qual-cor, var(--accent-blue)));
      border-color: transparent;
    }
    @media (prefers-reduced-motion: reduce) { .precs-tecla, .qual-key { transition: none; } }

    /* (1.1.45) A LISTA DE ATALHOS (tela do "?").
       O que está apagado é o que não vale no estado atual, e ele leva um rótulo dizendo ONDE
       vale — "no TPA", "em chamada". Apagar sem dizer por que transformaria a lista em enigma.
       A opacidade fica em .45 e não mais baixa porque o texto ainda tem de ser LEGÍVEL: é
       informação útil ("existe, mas não agora"), não item desabilitado a ser ignorado. */
    .precs-atalhos-lista { display: flex; flex-direction: column; gap: var(--space-2); }
    .precs-atalho {
      display: flex; align-items: flex-start; gap: var(--space-3);
      padding: var(--space-2) var(--space-3);
      background: var(--bg-primary); border: 1px solid var(--panel-fio, var(--border-color));
      border-radius: var(--radius-inner);
    }
    .precs-atalho.apagado { opacity: .45; }
    .precs-atalho .precs-tecla { margin-top: 2px; }
    .precs-atalho-txt { display: flex; flex-direction: column; gap: 2px; flex: 1; min-width: 0; }
    .precs-atalho-txt b { font-size: .82rem; font-weight: 600; color: var(--text-primary); }
    .precs-atalho-txt i { font-size: .72rem; font-style: normal; color: var(--text-muted); }
    .precs-atalho-onde {
      flex: 0 0 auto; align-self: center;
      font-size: .66rem; font-weight: 700; text-transform: uppercase;
      letter-spacing: var(--ls-caps); color: var(--text-muted);
    }
    /* realce mais forte do selecionado (fácil de conferir antes de enviar).
       Usa --qual-cor-anel pelo mesmo motivo da regra equivalente lá acima: é esta que
       vence (tem !important), então sem trocar aqui o preto continuaria invisível. */
    .qualification-item.selected {
      border-color: var(--qual-cor-anel, var(--qual-cor, var(--accent-blue))) !important;
      box-shadow: 0 0 0 1px var(--qual-cor-anel, var(--qual-cor, var(--accent-blue))) inset,
                  0 2px 10px color-mix(in srgb, var(--qual-cor-anel, var(--qual-cor, #294ace)) 30%, transparent);
    }
    /* ênfase discreta no botão Enviar SÓ quando há qualificação escolhida */
    #send-qualification-btn-campaign:not(:disabled) { animation: precsSendPulse 1.8s ease-in-out infinite; }
    @keyframes precsSendPulse { 0%,100%{ box-shadow: 0 0 0 0 rgba(41,74,206,0); } 50%{ box-shadow: 0 0 0 4px var(--accent-blue-light, rgba(41,74,206,.18)); } }

    /* ===== Chamada ativa ===== */
    /* ponto "ao vivo" pulsando junto da duração */
    #call-duration-campaign::before {
      content: ''; display: inline-block; width: 8px; height: 8px; border-radius: 50%;
      background: var(--accent-green, #22c55e); margin-right: 6px; vertical-align: middle;
      animation: precsLive 1.4s ease-in-out infinite;
    }
    @keyframes precsLive { 0%,100%{ opacity: 1; box-shadow: 0 0 0 0 rgba(34,197,94,.5); } 50%{ opacity: .5; box-shadow: 0 0 0 5px rgba(34,197,94,0); } }
    #hangup-btn { box-shadow: var(--elev-1) color-mix(in srgb, var(--accent-red) 28%, transparent); }
    #hangup-btn:hover { box-shadow: 0 4px 16px color-mix(in srgb, var(--accent-red) 42%, transparent); }

    /* ===== Menu ===== */
    /* opacity entrou na lista em 1.1.4: com o fill-mode corrigido, as campanhas apagadas
       de fato mudam de opacidade e sem transição isso viraria um corte seco. */
    .campaign-item { transition: border-color .16s ease, background-color .16s ease, transform .12s ease, box-shadow .16s ease, opacity .18s ease; }
    /* PRECS (1.1.4) — o hover ganhou o FILETE DOURADO à esquerda, o mesmo realce que a
       coluna "últimas leads" usa (.precs-hist-item:hover, algumas linhas abaixo): as duas
       listas da home ficam com o mesmo idioma de "este aqui está sob o cursor", em vez de
       só o card de campanha trocar de cor de fundo. O filete é inset box-shadow de
       propósito — ele acompanha a curva do card sem depender de raio de pseudo-elemento,
       que foi justamente o que vazava a borda no selo "última usada". */
    .campaign-item:hover:not(.precs-campanha-entrando) {
      border-color: var(--precs-gold, var(--accent-3cplus));
      background: var(--bg-tertiary);
      box-shadow: inset 3px 0 0 var(--precs-gold, #B49552), var(--shadow);
    }
    .campaign-arrow { transition: transform var(--dur-2) var(--ease-1), color var(--dur-2) ease, background-color var(--dur-2) ease, border-color var(--dur-2) ease; }
    /* o círculo se acende em ouro: tinta de fundo, contorno e seta na cor da marca.
       Usa --precs-gold-light (translúcido) em vez do ouro cheio porque no tema claro o
       ouro é escuro (#856828) e a seta em cima dele ficaria escuro sobre escuro.
       translateX menor que o antigo (8px): num alvo circular com contorno, 8px empurrava
       o círculo contra o padding direito do card. */
    .campaign-item:hover .campaign-arrow {
      transform: translateX(3px);
      color: var(--precs-gold, var(--accent-3cplus));
      background: var(--precs-gold-light, var(--accent-blue-light));
      border-color: var(--precs-gold, var(--accent-3cplus));
    }
    /* respiro no hover: recuo com margem negativa para o realce não ficar colado.
       Todos os itens têm a MESMA altura de realce (padding uniforme no render). */
    .precs-hist-item { transition: background-color var(--dur-1) ease, box-shadow var(--dur-1) ease; border-radius: var(--radius-inner); margin-left: -.7rem; margin-right: -.7rem; }
    /* hover unificado (mesmo realce da coluna "últimas leads"): dourado 10% +
       filete dourado à esquerda. Antes esta lista usava 8% e sem filete. */
    .precs-hist-item:hover {
      background: color-mix(in srgb, var(--precs-gold, #B49552) 10%, transparent);
      box-shadow: inset 3px 0 0 var(--precs-gold, #B49552);
    }
    /* o primeiro item não encosta no cabeçalho do card (evita o "apertado") */
    .precs-ultima-lead-corpo { padding-top: var(--space-2); }
    .precs-ultima-lead-corpo .precs-hist-item:first-child { border-top: none; }

    /* PRECS — rótulo "Modo Manual" como BADGE âmbar preenchido. Antes era só
       texto na cor --accent-manual: no claro contrastava com o fundo branco, mas
       nos temas escuros o laranja sobre grafite quase não se destacava do resto.
       O badge com fundo tintado + borda lê forte nos 3 temas. */
    .precs-manual-badge {
      display: inline-flex; align-items: center; gap: var(--space-2);
      margin-bottom: var(--space-4); padding: var(--space-1) var(--space-3);
      border-radius: var(--radius-pill);
      background: color-mix(in srgb, var(--accent-manual, #F59336) 16%, var(--bg-secondary));
      border: 1px solid color-mix(in srgb, var(--accent-manual, #F59336) 55%, transparent);
      color: var(--accent-manual, #F59336);
      font-weight: 700; font-size: .8rem; letter-spacing: .01em;
      font-family: 'Montserrat', 'Poppins', sans-serif;
    }
    .precs-manual-badge-ico { display: inline-flex; }

    /* ===== Teclado numérico (discagem manual) ===== */
    /* PRECS — botão "Ligar" travado enquanto não há negócio vinculado (Fase 3) */
    #dial-btn-campaign:disabled, #dial-btn-campaign.precs-btn-travado {
      opacity: .5; cursor: not-allowed; filter: grayscale(.25);
    }

    /* PRECS — box de vínculo obrigatório da discagem manual (temático) */
    #manual-vinculo-box {
      background: var(--bg-secondary); border: 1px solid var(--border-color);
      border-radius: var(--radius-card); padding: var(--space-4) var(--space-4); margin-bottom: var(--space-4);
    }
    /* A linha de busca agora é irmã dos dois estados (ver index.html). Quando existe o
       chip do negócio vinculado acima dela, ganha um separador para não parecer parte
       do chip; sem vínculo, encosta no alerta como antes. */
    #manual-com-vinculo:not([style*="none"]) + #manual-busca-linha {
      margin-top: var(--space-3); padding-top: var(--space-3);
      border-top: 1px dashed var(--border-color);
    }
    .precs-mvinc-lbl {
      font-size: .72rem; text-transform: uppercase; letter-spacing: var(--ls-caps);
      color: var(--precs-gold, #B49552); font-weight: 700; margin-bottom: var(--space-2);
      font-family: 'Montserrat', 'Poppins', sans-serif;
    }
    /* campo de texto padrão do discador (herda as cores do tema, some o bug do
       texto invisível no PRECS/escuro) */
    .precs-field {
      width: 100%; padding: var(--space-3) var(--space-4);
      background: var(--bg-primary); color: var(--text-primary);
      border: 1px solid var(--border-color); border-radius: var(--radius-inner);
      font-family: 'Manrope', 'Poppins', sans-serif; font-size: .9rem;
      transition: border-color var(--dur-2), box-shadow var(--dur-2);
    }
    .precs-field::placeholder { color: var(--text-muted); opacity: 1; }
    .precs-field:focus {
      outline: none; border-color: var(--precs-gold, #B49552);
      box-shadow: 0 0 0 3px var(--precs-gold-light, rgba(180,149,82,.16));
    }
    .precs-mvinc-btn {
      width: auto; padding: var(--space-3) var(--space-5); white-space: nowrap;
      /* (1.1.42) `#fff` cravado sobre o azul de ação — invisível no Zebrado, onde esse azul é
         claro. Ver a nota do `.precs-integracao-btn` no estilo.css. */
      background: var(--accent-blue); color: var(--on-accent-blue); border: none;
      border-radius: var(--radius-inner); font-weight: 700; cursor: pointer;
      font-family: 'Manrope', 'Poppins', sans-serif;
      box-shadow: var(--elev-1) color-mix(in srgb, var(--accent-blue) 30%, transparent);
      transition: filter var(--dur-1), transform .12s, box-shadow var(--dur-1);
    }
    .precs-mvinc-btn:hover { filter: brightness(1.08); }
    .precs-mvinc-btn:active { transform: translateY(1px); }
    .precs-mvinc-hint { font-size: .74rem; color: var(--text-muted); margin-top: var(--space-2); }
    /* dropdown de resultados da busca por termo */
    .precs-mvinc-results {
      margin-top: var(--space-2); border: 1px solid var(--border-color); border-radius: var(--radius-inner);
      overflow: hidden; max-height: 240px; overflow-y: auto; background: var(--bg-primary);
    }
    .precs-mvinc-op {
      display: block; width: 100%; text-align: left; background: none; border: none;
      border-bottom: 1px solid var(--border-color); padding: var(--space-2) var(--space-3); cursor: pointer;
      color: var(--text-primary); transition: background var(--dur-1);
    }
    .precs-mvinc-op:last-child { border-bottom: none; }
    .precs-mvinc-op:hover { background: color-mix(in srgb, var(--precs-gold,#B49552) 12%, transparent); }
    .precs-mvinc-op-tit { font-weight: 600; font-size: .85rem; }
    .precs-mvinc-op-sub { font-size: .74rem; color: var(--text-muted); margin-top: var(--space-0); }
    /* chip do negócio vinculado */
    .precs-mvinc-linked {
      align-items: center; justify-content: space-between; gap: var(--space-2);
      padding: var(--space-2) var(--space-3); border: 1px solid var(--lead-border, var(--border-color));
      border-radius: var(--radius-inner); background: var(--precs-gold-light, rgba(180,149,82,.08));
      font-size: .82rem; color: var(--text-primary);
    }

    /* PRECS — estados do box de vínculo: alerta (sem negócio) e ok (vinculado) */
    #manual-vinculo-box.mvinc-alerta {
      border-color: color-mix(in srgb, var(--accent-red,#EF4444) 55%, transparent);
      border-left: 3px solid var(--accent-red,#EF4444);
      background: color-mix(in srgb, var(--accent-red,#EF4444) 9%, var(--bg-secondary));
    }
    #manual-vinculo-box.mvinc-ok {
      border-color: color-mix(in srgb, #28a745 45%, transparent);
      border-left: 3px solid #28a745;
      background: color-mix(in srgb, #28a745 7%, var(--bg-secondary));
    }
    .mvinc-alerta-head {
      display: flex; align-items: flex-start; gap: var(--space-2); margin-bottom: var(--space-3);
      color: var(--accent-red,#EF4444);
    }
    .mvinc-alerta-ico { flex: none; display: inline-flex; margin-top: .05rem; }
    .mvinc-alerta-tit {
      font-weight: 700; font-size: .9rem; line-height: 1.2;
      font-family: 'Montserrat','Poppins',sans-serif;
    }
    .mvinc-alerta-sub { font-size: .75rem; color: var(--text-secondary); margin-top: var(--space-0); line-height: 1.35; }

    /* PRECS — modal de confirmação reutilizável (precsConfirmar) */
    .precs-confirm-overlay {
      /* (1.1.11) 10000 deixava a confirmacao ATRAS da ficha ao vivo (10045) e da barra da escuta
         (10040): em 18/08/2026 o modal "Escutar a ligacao ao vivo" apareceu por tras do popover
         que o tinha aberto. A confirmacao e a caixa que pede DECISAO, entao ela precisa estar
         acima de tudo que pode ter aberto ela — 10060 fica acima de todos os overlays desta
         versao (foto 10050, audio 10050, ficha 10045, escuta 10040). */
      display: none; position: fixed; inset: 0; z-index: 10060;
      background: rgba(0,0,0,.55); backdrop-filter: blur(2px);
      align-items: center; justify-content: center; padding: 5vh 5vw;
    }
    .precs-confirm-overlay.open { display: flex; }
    /* saída animada (padrão único de fechamento) */
    .precs-confirm-overlay.closing { animation: precsOverlayOut .18s ease forwards; }
    .precs-confirm-overlay.closing .precs-confirm-modal { animation: precsModalOut .18s var(--ease-3) forwards; }
    @media (prefers-reduced-motion: reduce) {
      .precs-confirm-overlay.closing, .precs-confirm-overlay.closing .precs-confirm-modal { animation: none; }
    }
    .precs-confirm-modal {
      width: min(420px, 94vw); background: var(--bg-secondary);
      border: 1px solid var(--border-color); border-radius: var(--radius-card);
      box-shadow: var(--shadow-lg); padding: var(--space-6) var(--space-6) var(--space-5);
      text-align: center; animation: pmEntra .22s ease;
    }
    .precs-confirm-ico {
      width: 52px; height: 52px; border-radius: 50%; margin: 0 auto var(--space-3);
      display: flex; align-items: center; justify-content: center;
      color: var(--precs-gold,#B49552);
      background: color-mix(in srgb, var(--precs-gold,#B49552) 16%, transparent);
    }
    .precs-confirm-ico.perigo {
      color: var(--accent-red,#EF4444);
      background: color-mix(in srgb, var(--accent-red,#EF4444) 15%, transparent);
    }
    .precs-confirm-tit {
      font-weight: 700; font-size: 1rem; color: var(--text-primary); line-height: 1.3;
      font-family: 'Poppins','Manrope',sans-serif;
    }
    .precs-confirm-msg { font-size: .84rem; color: var(--text-secondary); margin-top: var(--space-2); line-height: 1.45; }
    /* PRECS (1.1.10) — campo de senha do precsPedirSenha (reentrada na 3C sem sair do
       atendimento). Mora aqui, e não numa casca própria, porque é o MESMO modal: título,
       ícone e botões são os do precsConfirmar, e só o campo é novo. O rótulo fica alinhado
       à esquerda enquanto o resto do modal é centralizado — campo de formulário com rótulo
       centralizado engana o olho sobre onde clicar. */
    .precs-confirm-rot {
      display: block; text-align: left; margin-top: var(--space-4); margin-bottom: var(--space-1);
      font-size: .74rem; font-weight: 600; letter-spacing: .02em;
      color: var(--text-secondary); font-family: 'Manrope','Poppins',sans-serif;
    }
    .precs-confirm-input {
      width: 100%; padding: var(--space-3) var(--space-4);
      background: var(--bg-tertiary); color: var(--text-primary);
      border: 1px solid var(--border-color); border-radius: var(--radius-inner);
      font-size: .95rem; letter-spacing: .08em; font-family: 'Manrope','Poppins',sans-serif;
      transition: border-color var(--dur-1), box-shadow var(--dur-1);
    }
    .precs-confirm-input:focus {
      outline: none; border-color: var(--precs-gold,#B49552);
      box-shadow: 0 0 0 3px var(--precs-gold-light, rgba(180,149,82,.16));
    }
    /* O erro de senha aparece ACIMA do campo e em vermelho de acento: o operador está no
       meio de um atendimento e precisa saber, num relance, que a tentativa anterior não
       passou (senão ele digita a mesma senha de novo). */
    .precs-confirm-erro {
      margin-top: var(--space-3); padding: var(--space-2) var(--space-3);
      border-radius: var(--radius-inner); text-align: left; font-size: .8rem;
      color: var(--accent-red,#EF4444);
      background: color-mix(in srgb, var(--accent-red,#EF4444) 12%, transparent);
      border: 1px solid color-mix(in srgb, var(--accent-red,#EF4444) 34%, transparent);
    }
    .precs-confirm-acoes { display: flex; gap: var(--space-2); margin-top: var(--space-5); }
    /* PRECS (1.1.0) — alinhado à forma canônica do .btn: raio --radius-inner e peso
       600. Antes tinha raio 10px e peso 700, ou seja, o mesmo papel (confirmar uma
       ação) desenhado de três maneiras diferentes conforme onde aparecia. */
    .precs-confirm-btn {
      flex: 1; padding: var(--space-3) var(--space-4); border-radius: var(--radius-inner); font-weight: 600;
      font-size: .9rem; cursor: pointer; font-family: 'Manrope','Poppins',sans-serif;
      transition: filter var(--dur-1), transform .12s, background-color var(--dur-1);
    }
    .precs-confirm-btn:active { transform: translateY(1px); }
    .precs-confirm-btn.cancel { background: var(--bg-tertiary); color: var(--text-primary); border: 1px solid var(--border-color); }
    .precs-confirm-btn.cancel:hover { background: var(--bg-primary); }
    .precs-confirm-btn.ok { background: var(--precs-gold,#B49552); color: #1f1b12; border: 1px solid transparent; }
    .precs-confirm-btn.ok.perigo { background: var(--accent-red,#EF4444); color: #fff; }
    .precs-confirm-btn.ok:hover { filter: brightness(1.08); }
    @media (prefers-reduced-motion: reduce){ .precs-confirm-modal { animation: none; } }

    /* ==================================================================== */
    /* PRECS 1.0.9 — polimento visual (Blocos A/B/C/D)                       */
    /* ==================================================================== */

    /* A — realce no hover dos CTAs principais, na cor do TEMA (azul no claro/
       escuro/contraste, dourado no Precs) — antes era dourado fixo, que destoava
       nos temas azuis. --accent-blue já vira dourado no tema Precs. */
    .btn-primary:hover:not(:disabled),
    #dial-btn-campaign:hover:not(:disabled) {
      box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent-blue) 62%, #fff) inset, var(--shadow);
    }
    /* A — títulos de painel no dourado de títulos da marca (só no tema Precs) */
    html[data-theme="precs"] .panel-header,
    html[data-theme="precs"] .precs-campaigns-col .panel-header,
    html[data-theme="precs"] .precs-tempos-titulo {
      color: var(--precs-gold-title, #D3B26B);
    }

    /* B1 — "Chamando…": reticências animadas no rótulo de estado */
    #campaign-header-status .precs-dots::after {
      content: '…';
    }
    #campaign-header-status.precs-chamando .precs-dots::after {
      content: ''; display: inline-block; width: 1.1em; text-align: left;
      animation: precsDots 1.4s steps(1, end) infinite;
    }
    @keyframes precsDots { 0%{content:''} 25%{content:'.'} 50%{content:'..'} 75%{content:'...'} 100%{content:''} }
    /* anel âmbar pulsando ao redor do número enquanto chama */
    .precs-ring-chamando { position: relative; }
    .precs-ring-chamando::after {
      content: ''; position: absolute; inset: -5px -9px; border-radius: var(--radius-card);
      border: 2px solid var(--st-manual, #f59e0b); opacity: 0;
      animation: precsRing 1.6s ease-out infinite; pointer-events: none;
    }
    @keyframes precsRing {
      0% { opacity: .5; transform: scale(.98); }
      70% { opacity: 0; transform: scale(1.04); }
      100% { opacity: 0; }
    }

    /* B2 — ponto "ao vivo" durante a chamada conectada */
    .precs-aovivo { display: inline-flex; align-items: center; gap: var(--space-1); font-size: .68rem;
      font-weight: 700; color: var(--st-call, #22c55e); text-transform: uppercase; letter-spacing: var(--ls-caps); margin-left: var(--space-2); }
    .precs-aovivo .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--st-call, #22c55e);
      animation: precsAoVivoDot 1.3s ease-in-out infinite; }
    @keyframes precsAoVivoDot { 0%,100%{ opacity: 1; transform: scale(1); } 50%{ opacity: .35; transform: scale(.75); } }

    /* B3 — a legenda dos "Tempos da sessão" saiu em 1.1.4 junto com o markup dela
       (busque .precs-tempos-legenda no comentário do bloco #precs-tempos): os cards
       abaixo do termômetro já trazem ponto colorido + nome de cada estado. */
    .precs-thermo-seg { cursor: default; }
    /* PRECS — tooltip que SEGUE O CURSOR. Nasceu só para o termômetro (por isso se
       chamava .precs-thermo-tip) e em 1.1.2 virou o tooltip dos gráficos também,
       daí o nome genérico.
       É `position: fixed` e vive no <body> de propósito: o [data-tip] em CSS, que o
       resto do painel usa, é `position:absolute` dentro do próprio elemento e por
       isso é cortado por qualquer ancestral com overflow — que é exatamente o caso
       das barras, dentro do corpo rolável do modal de estatísticas. Aqui nenhum
       recorte de card ou modal alcança. */
    .precs-tip {
      /* (1.1.15 · 9ª volta) ACIMA DA BARRA DE ESCUTA. Defeito relatado em 20/08, com print: o
         balão do botão "Ver a tela" aparecia ATRÁS do card de "ouvindo ao vivo", ou seja, atrás
         do próprio botão que o disparou. A barra é `z-index:10040` (ela precisa ficar sobre o
         espelho, que é modal) e o balão era 10001 — ele nasceu antes da barra existir.
         Balão é sempre a camada mais alta da tela por natureza: ele explica o que está embaixo
         dele, então nada pode ficar na frente. */
      position: fixed; z-index: 10100; pointer-events: none;
      transform: translate(-50%, -100%);
      background: var(--bg-secondary); color: var(--text-primary);
      border: 1px solid var(--border-color); border-radius: var(--radius-inner);
      padding: var(--space-1) var(--space-2); font-size: .72rem; font-weight: 600;
      box-shadow: var(--shadow-lg);
      opacity: 0; transition: opacity .12s ease;
      /* (1.1.78) O BALÃO QUEBRA LINHA, E TEM LARGURA MÁXIMA.

         Era `white-space: nowrap` sem `max-width` nenhum: todo balão saía numa linha só, de
         qualquer comprimento. O do chip de CPC passa de 340 caracteres e virava uma faixa mais
         larga que a janela. O Pedro pediu por nome em 14/09/2026: "olhe os tooltips gigantes,
         vê se dá pra reduzir ou alterar".

         `42ch` é a medida de leitura confortável para texto curto, e os `92vw` seguram o caso
         do celular. O texto que continuar longo agora vira parágrafo em vez de régua.

         DE QUEBRA, O BALÃO PASSA A FICAR ONDE DEVE: o clamp horizontal de `precsTipBind`
         depende de `offsetWidth`, então balão largo era empurrado para o meio da tela, longe
         do que ele explica.

         Sem `line-height` declarado de propósito: não existe token `--lh-*` no projeto, e
         cravar um valor aqui sobe o contador da catraca sem ter para onde apontar. */
      max-width: min(42ch, 92vw); white-space: normal; text-wrap: pretty;
    }
    .precs-tip.on { opacity: 1; }

    /* C1 — etiquetas do Pipe: borda interna sutil + botão "+N" */
    .precs-etiqueta { box-shadow: inset 0 0 0 1px rgba(0,0,0,.12); }
    .precs-etiq-mais { cursor: pointer; background: transparent !important; box-shadow: none !important;
      border: 1px dashed var(--lead-border, var(--border-color)) !important; color: var(--lead-label, var(--text-secondary)) !important; }

    /* C2 — histórico: zebra striping (linhas alternadas) */
    .hist-tr:nth-child(even) { background: color-mix(in srgb, var(--bg-secondary) 45%, transparent); }

    /* D — toasts: barra lateral na cor do tipo */
    .toast { border-left: 3px solid var(--text-muted); position: relative; overflow: hidden; }
    .toast.success { border-left-color: var(--toast-ok); }
    .toast.error   { border-left-color: var(--toast-err); }
    .toast.warning { border-left-color: var(--toast-warn); }
    .toast.info    { border-left-color: var(--toast-info); }
    /* barrinha de auto-fechamento (3s, igual ao timeout do showToast) */
    .toast::after {
      content: ''; position: absolute; left: 0; bottom: 0; height: 2px; width: 100%;
      background: var(--text-muted); opacity: .6; transform-origin: left;
      animation: precsToastBar 3s linear forwards;
    }
    .toast.success::after { background: var(--toast-ok); }
    .toast.error::after   { background: var(--toast-err); }
    .toast.warning::after { background: var(--toast-warn); }
    .toast.info::after    { background: var(--toast-info); }
    @keyframes precsToastBar { from { transform: scaleX(1); } to { transform: scaleX(0); } }
    @media (prefers-reduced-motion: reduce) { .toast::after { animation: none; opacity: 0; } }
    /* PRECS (1.1.0) — SAÍDA do toast. Era `el.style.animation = 'slideIn ... reverse'`
       aplicado inline pelo app.js, e estilo inline vence a regra de movimento reduzido
       logo abaixo: a entrada respeitava a preferência e a saída não. Virou classe. */
    .toast.toast-saindo { animation: slideIn var(--dur-3) ease reverse; }
    /* guarda de motion na ENTRADA e na SAÍDA de toast, e nos modais */
    @media (prefers-reduced-motion: reduce) {
      .toast, .toast.toast-saindo,
      .precs-stats-modal, .precs-prefs-modal, #precs-meudia-card { animation: none; }
    }

    @media (prefers-reduced-motion: reduce) {
      .precs-ring-chamando::after, .precs-aovivo .dot,
      #campaign-header-status.precs-chamando .precs-dots::after { animation: none; }
    }

    /* PRECS (1.1.0) — SPLASH sob movimento reduzido. O #precs-splash carrega
       `transition:opacity .45s` num style INLINE, e tem que ser inline mesmo: ele
       precisa pintar no primeiro frame, antes de este CSS ser parseado, senão volta o
       flash de boot que ele existe para cobrir. Por isso o `!important` aqui — é o
       único jeito de uma folha de estilo vencer o atributo style. O splash passa a
       sumir de uma vez em vez de desvanecer, que é o comportamento pedido. */
    @media (prefers-reduced-motion: reduce) {
      #precs-splash { transition: none !important; }
    }

    /* Overlay de "Saindo da campanha…": cobre a seção, bloqueia cliques e mostra
       o loader da marca enquanto o agent/logout da 3C responde (pode demorar). */
    .precs-leave-overlay {
      position: absolute; inset: 0; z-index: 50;
      display: flex; align-items: center; justify-content: center;
      background: color-mix(in srgb, var(--bg-primary) 78%, transparent);
      /* O raio acompanha o do .panel que esta camada cobre: com 16px contra os 12px
         do card, sobrava uma meia-lua do fundo nos quatro cantos. */
      backdrop-filter: blur(2px); border-radius: var(--radius-card);
      animation: pmFade .18s ease;
    }

    /* PRECS — loader de TELA CHEIA (entrar/sair de campanha) */
    .precs-loader-tela {
      position: fixed; inset: 0; z-index: 10000; display: none;
      align-items: center; justify-content: center;
      background: color-mix(in srgb, var(--bg-primary) 82%, transparent);
      backdrop-filter: blur(3px); animation: pmFade .18s ease;
    }
    .precs-loader-tela.on { display: flex; }

    /* PRECS — banner de nova versão (temático, com pulso) */
    .precs-update-bar {
      grid-column: 1/-1; width: 100%; box-sizing: border-box; margin: 0 0 var(--space-4);
      display: flex; align-items: center; gap: var(--space-4); padding: var(--space-3) var(--space-4);
      border-radius: var(--radius-card); box-shadow: var(--shadow);
      border: 1px solid color-mix(in srgb, var(--accent-blue) 45%, transparent);
      border-left: 3px solid var(--accent-blue);
      background: linear-gradient(135deg,
        color-mix(in srgb, var(--accent-blue) 14%, transparent),
        color-mix(in srgb, var(--accent-blue) 4%, transparent));
      animation: precsUpdateIn .25s ease;
    }
    .precs-update-ico {
      flex: none; width: 38px; height: 38px; border-radius: 50%;
      display: flex; align-items: center; justify-content: center;
      color: var(--accent-blue);
      background: color-mix(in srgb, var(--accent-blue) 16%, transparent);
      box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--accent-blue) 26%, transparent);
      animation: precsUpdateSpin 2.8s ease-in-out infinite;
    }
    .precs-update-ico svg { display: block; }
    .precs-update-txt { min-width: 0; flex: 1; }
    .precs-update-tit { font-weight: 700; font-size: .9rem; color: var(--text-primary);
      font-family: 'Poppins','Manrope',sans-serif; line-height: 1.2; }
    .precs-update-sub { font-size: .78rem; color: var(--text-secondary); margin-top: var(--space-0); line-height: 1.35; }
    .precs-update-btn {
      flex: none; white-space: nowrap; cursor: pointer;
      /* (1.1.42) Idem: este é o botão que TODO MUNDO vê quando sobe versão, e no Zebrado ele
         saía sem rótulo legível. */
      background: var(--accent-blue); color: var(--on-accent-blue); border: none;
      /* Raio, peso e tamanho seguem o .btn-sm; era 9px/700/.82rem. */
      border-radius: var(--radius-inner); padding: var(--space-2) var(--space-4); font-weight: 600; font-size: .8rem;
      font-family: 'Manrope','Poppins',sans-serif;
      box-shadow: var(--elev-1) color-mix(in srgb, var(--accent-blue) 40%, transparent);
      transition: filter var(--dur-1), transform .12s; animation: precsUpdateBtn 2s ease-in-out infinite;
    }
    .precs-update-btn:hover { filter: brightness(1.08); }
    .precs-update-btn:active { transform: translateY(1px); }
    @keyframes precsUpdateIn { from{ opacity:0; transform:translateY(-6px); } to{ opacity:1; transform:translateY(0); } }
    @keyframes precsUpdateSpin { 0%,70%,100%{ transform:rotate(0); } 80%{ transform:rotate(-22deg); } 90%{ transform:rotate(12deg); } }
    @keyframes precsUpdateBtn {
      0%,100%{ box-shadow:0 2px 10px color-mix(in srgb, var(--accent-blue) 40%, transparent); }
      50%{ box-shadow:0 2px 18px color-mix(in srgb, var(--accent-blue) 72%, transparent); }
    }
    @media (prefers-reduced-motion: reduce){
      .precs-update-bar, .precs-update-ico, .precs-update-btn, .precs-loader-tela { animation: none; }
    }
    /* em telas estreitas empilha: texto em cima, botão ocupa a largura */
    @media (max-width: 520px){
      .precs-update-bar { flex-wrap: wrap; }
      .precs-update-btn { flex: 1 0 100%; }
    }
    .precs-keypad { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--space-2); margin-top: var(--space-4); }
    .precs-keypad button {
      min-height: 56px; padding: var(--space-3) 0; font-size: 1.2rem; font-weight: 600; font-family: 'JetBrains Mono', monospace;
      color: var(--text-primary); background: var(--bg-tertiary); border: 1px solid var(--border-color);
      border-radius: var(--radius-inner); cursor: pointer;
      display: flex; align-items: center; justify-content: center;
      transition: background-color .14s ease, transform .1s ease, border-color .14s ease;
    }
    .precs-keypad button {
      box-shadow: 0 1px 2px rgba(0,0,0,.18);   /* leve profundidade */
    }
    .precs-keypad button:hover {
      background: var(--bg-primary); border-color: var(--precs-gold, var(--accent-3cplus));
      transform: translateY(-1px); box-shadow: 0 3px 8px rgba(0,0,0,.22);
    }
    .precs-keypad button:active {
      transform: scale(.94);
      background: color-mix(in srgb, var(--precs-gold, var(--accent-3cplus)) 20%, var(--bg-tertiary));
      border-color: var(--precs-gold, var(--accent-3cplus));
      color: var(--precs-gold-hi, var(--text-primary));
      box-shadow: 0 1px 2px rgba(0,0,0,.18);
    }
    /* teclas de ação (C / apagar) diferenciadas dos dígitos */
    .precs-keypad .precs-keypad-aux { font-size: .95rem; color: var(--text-muted); background: var(--bg-secondary); }
    .precs-keypad .precs-keypad-aux:hover { color: var(--text-primary); }
    /* entrada suave do teclado ao abrir o modo manual, com leve escalonamento */
    .precs-keypad button { animation: precsHomeIn .26s var(--ease-2) both; }
    .precs-keypad button:nth-child(1){ animation-delay:.02s } .precs-keypad button:nth-child(2){ animation-delay:.04s }
    .precs-keypad button:nth-child(3){ animation-delay:.06s } .precs-keypad button:nth-child(4){ animation-delay:.08s }
    .precs-keypad button:nth-child(5){ animation-delay:.10s } .precs-keypad button:nth-child(6){ animation-delay:.12s }
    .precs-keypad button:nth-child(7){ animation-delay:.14s } .precs-keypad button:nth-child(8){ animation-delay:.16s }
    .precs-keypad button:nth-child(9){ animation-delay:.18s } .precs-keypad button:nth-child(10){ animation-delay:.20s }
    .precs-keypad button:nth-child(11){ animation-delay:.22s } .precs-keypad button:nth-child(12){ animation-delay:.24s }
    @media (prefers-reduced-motion: reduce){ .precs-keypad button { animation: none; } }

    /* ===== PRECS — FOCO POR TECLADO (:focus-visible). Acessibilidade e navegação
       sem mouse: anel dourado da marca, coerente nos 3 temas. Só aparece na
       navegação por teclado (Tab), não no clique do mouse. ===== */
    .precs-keypad button:focus-visible,
    .qualification-item:focus-visible,
    .btn:focus-visible,
    .precs-mvinc-btn:focus-visible,
    .precs-tel-btn:focus-visible,
    .precs-integracao-btn:focus-visible,
    /* (1.1.57) O `.precs-stats-btn` entra aqui, e a ausencia dele era um furo de verdade: ele
       era o UNICO botao do cabecalho do card sem anel de foco por teclado. O motivo e
       mecanico e vale registrar — a lista pega `.btn:focus-visible`, e este botao nao tem a
       classe `.btn`; ele nasceu com classe propria e ficou de fora sem ninguem notar. */
    .precs-stats-btn:focus-visible {
      /* (1.1.10) Mesmo conserto do bloco de .mode-btn: 2px sólidos em vez de 1px + faixa
         translúcida. Este é o mais grave dos quatro pelo alcance — cobre o teclado numérico,
         os ITENS DE QUALIFICAÇÃO (que o operador escolhe por teclado no TPA, com foco
         automático no primeiro) e todos os `.btn` do painel. */
      outline: 2px solid var(--precs-gold, var(--accent-3cplus));
      outline-offset: 2px;
      box-shadow: 0 0 0 5px var(--precs-gold-light, rgba(180,149,82,.35));
      border-color: var(--precs-gold, var(--accent-3cplus));
    }

    /* Botão Desligar: ação destrutiva/urgente — no hover preenche de vermelho
       sólido (mais peso visual que só o fundo suave anterior). */
    /* (1.1.10) `color:#fff` daqui dava 3,76:1 sobre o vermelho sólido — o mesmo defeito do
       estado de repouso do #hangup-btn, e escondido num segundo lugar. Achado porque o teste
       de par renderizado passou a medir :hover. Tinta escura, igual ao repouso. */
    .btn-danger:hover {
      background: var(--accent-red);
      color: var(--on-accent-red);
      border-color: var(--accent-red);
    }
    /* PRECS (1.1.57) — TENTEI NEUTRALIZAR O "SAIR" EM REPOUSO E FOI REVERTIDO NA MESMA LEVA.
       O argumento era de economia de sinal: o vermelho dele era a cor mais saturada da tela, o
       expediente todo, num botao de uso diario unico, competindo com o `Desconectado` e com os
       vermelhos de erro.
       O RELATO DERRUBOU O ARGUMENTO: "o botao de Sair tem q ter o vermelho se n ele fica muito
       escondido" (Pedro, 04/09/2026). E ele esta certo sobre o que importa mais — sair e uma
       acao de consequencia (derruba a sessao da 3C e o SIP), e uma acao de consequencia
       ESCONDIDA e pior do que um vermelho a mais na tela. Achar rapido vale mais que a
       economia de cor.
       Fica registrado para nao ser tentado de novo: o vermelho do Sair e deliberado. */
    @media (prefers-reduced-motion: reduce) {
      #send-qualification-btn-campaign:not(:disabled), #call-duration-campaign::before { animation: none; }
    }

    /* ===== Botão "Ver estatísticas" (cabeçalho do Meu Desempenho) =====
       Mesma família dourada dos demais botões PRECS: pill soft-gold, Manrope,
       raio 9, realce no hover. Antes destoava (raio 6, transparente, menor). */
    /* PRECS (1.1.57) — ELE NAO ERA ARIAL, ERA PEQUENO DEMAIS. O relato foi "parece um Arial
       feio" (Pedro, 04/09/2026), e a primeira coisa que medi foi a familia: `Manrope` 700, que
       e exatamente a doutrina de botao deste projeto. O problema e a ESCALA — `.7rem` sao
       11,2px de CSS, e o `zoom: 0.85` do painel entrega 9,5px NA TELA. Abaixo de ~10px
       qualquer tipografia perde o desenho das letras e vira "fonte de sistema" para o olho.
       Vai para `.76rem`, que e o mesmo do `.precs-campt-btn` — o botao que nasceu em 1.1.32
       da MESMA queixa ("botao minusculo") e que serve de modelo para o resto deste bloco.
       Medido depois: 10,3px na tela.
       E o `letter-spacing` sai de `.3px` para o token: px fixo nao acompanha o corpo da
       fonte, entao ele aperta no grande e afasta no pequeno. E o argumento que criou o
       `--ls-caps` na 1.1.10, e vale igual aqui. */
    .precs-stats-btn {
      display: inline-flex; align-items: center; gap: var(--space-1);
      font-family: var(--font-acao);
      font-size: .76rem; font-weight: 700; letter-spacing: var(--ls-caps); cursor: pointer;
      color: var(--accent-blue);
      background: color-mix(in srgb, var(--accent-blue) 10%, transparent);
      border: 1px solid color-mix(in srgb, var(--accent-blue) 45%, transparent);
      border-radius: var(--radius-inner); padding: var(--space-1) var(--space-3); text-transform: none;
      transition: background-color var(--dur-1) ease, color var(--dur-1) ease, border-color var(--dur-1), transform .12s;
    }
    .precs-stats-btn:hover {
      /* (1.1.42) O hover invertia para azul cheio com `#fff` cravado: no Zebrado o rótulo
         sumia justamente ao passar o mouse. */
      background: var(--accent-blue); color: var(--on-accent-blue);
      border-color: var(--accent-blue);
    }
    .precs-stats-btn:active { transform: translateY(1px); }
    /* (1.1.57) A GUARDA DE MOVIMENTO, que faltava. Este botao tinha `transition` de quatro
       propriedades e um `translateY` no `:active` rodando mesmo com movimento reduzido — era
       o unico do cabecalho sem bloco. O modelo aqui e o `.precs-campt-btn`, que e o unico do
       grupo que desliga as DUAS coisas (a transicao e o transform), e nao so a transicao. */
    @media (prefers-reduced-motion: reduce) {
      .precs-stats-btn { transition: none; }
      .precs-stats-btn:active { transform: none; }
    }

    /* ===== Modal de Estatísticas detalhadas ===== */
    /* ============ PRECS (1.1.6) — RESUMO DA SESSÃO (card de print) ============ */
    /* Mesma mecânica de overlay dos outros três modais (display none/flex + .closing).
       O que é diferente aqui, e é a razão do bloco existir: o CARD é o produto, não o
       modal. Ele precisa ficar bonito RECORTADO da tela, sem o resto da interface em
       volta, então tem fundo, borda e assinatura próprios em vez de encostar no fundo do
       overlay. Largura fixa em 420px de propósito: o print vai para o WhatsApp, onde a
       imagem é reduzida, e um card largo viraria letra ilegível no celular de quem lê. */
    .precs-resumo-overlay {
      display: none; position: fixed; inset: 0; z-index: 9999;
      background: rgba(0,0,0,.6); backdrop-filter: blur(2px);
      align-items: center; justify-content: center; padding: 2vh 2vw; overflow: auto;
    }
    .precs-resumo-overlay.open { display: flex; }
    .precs-resumo-overlay.closing { animation: precsOverlayOut var(--dur-2) ease forwards; }
    .precs-resumo-overlay.closing .precs-resumo-modal { animation: precsModalOut var(--dur-2) var(--ease-3) forwards; }
    @media (prefers-reduced-motion: reduce) {
      .precs-resumo-overlay.closing, .precs-resumo-overlay.closing .precs-resumo-modal { animation: none; }
    }
    .precs-resumo-modal {
      display: flex; flex-direction: column; align-items: center; gap: var(--space-3);
      animation: pmEntra var(--dur-3) var(--ease-2);
    }
    @media (prefers-reduced-motion: reduce) { .precs-resumo-modal { animation: none; } }

    .precs-resumo-card {
      width: 420px; max-width: 92vw; box-sizing: border-box;
      padding: var(--space-6) var(--space-6) var(--space-5);
      background: var(--bg-secondary);
      border: 1px solid color-mix(in srgb, var(--precs-gold) 34%, var(--border-color));
      border-radius: var(--radius-card);
      box-shadow: var(--elev-3) rgba(0,0,0,.45);
      font-family: 'Poppins','Manrope',sans-serif;
    }
    /* filete dourado no topo: é a assinatura da marca no artefato */
    .precs-resumo-card { position: relative; overflow: hidden; }
    .precs-resumo-card::before {
      content: ''; position: absolute; inset: 0 0 auto 0; height: 3px;
      background: linear-gradient(90deg, var(--precs-gold), var(--precs-gold-hi), var(--precs-gold));
    }
    .precs-resumo-topo { display: flex; align-items: center; gap: var(--space-3); }
    .precs-resumo-quem { min-width: 0; }
    .precs-resumo-nome {
      font-family: 'Sora','Poppins',sans-serif; font-weight: 700; font-size: 1.05rem;
      color: var(--text-primary); line-height: 1.2;
      overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    }
    .precs-resumo-sub {
      font-family: 'Montserrat','Poppins',sans-serif; font-size: .68rem; font-weight: 600;
      text-transform: uppercase; letter-spacing: var(--ls-caps); color: var(--text-muted);
      margin-top: var(--space-0); line-height: 1.35;
    }
    /* A faixa ganha LINHA PRÓPRIA. Ela era um irmão do texto dentro de um .precs-resumo-sub
       com display:flex, e o nó de texto virava um item flex anônimo cujo tamanho base é o
       do texto SEM quebra: o item media a linha inteira, quebrava em duas, e empurrava a
       faixa para o canto direito, longe do nome. Em linha própria a faixa fica onde deve
       (embaixo da identidade), o subtítulo pode quebrar à vontade, e nome de operador longo
       com campanha de nome longo não desmonta mais o cabeçalho do cartão. */
    .precs-resumo-faixa { margin-top: var(--space-2); line-height: 0; }
    .precs-resumo-faixa:empty { display: none; }
    .precs-resumo-div { height: 1px; background: var(--border-color); margin: var(--space-5) 0; }

    /* ESTADO EM DESTAQUE — o bloco principal do cartão.
       (1.1.6, revisado) Aqui havia uma fila de quatro chips (atendidas, falado, média,
       sessão). Saiu porque o caso de uso do cartão é o print do OCIOSO, e nesse instante os
       números de desempenho são zero POR CONSTRUÇÃO: o cartão saía "0 ATENDIDAS · 0min
       FALADO" e lia como "não fiz nada", quando a mensagem que o operador quer mandar é
       "não me deram nada". O que ele precisa mostrar é em que estado está e há quanto tempo.
       A cor sai de --re-cor, escrita no style pelo render: a cor do estado, ou o vermelho do
       alarme, que vence a do estado porque no alarme é o alarme que é a informação. */
    .precs-resumo-estado {
      position: relative; overflow: hidden;
      padding: var(--space-3) var(--space-4);
      border-radius: var(--radius-inner);
      background: var(--bg-tertiary);
      border: 1px solid var(--re-cor, var(--border-color));
    }
    /* véu da cor do estado sobre o fundo do chip, em vez de color-mix no background: assim o
       mesmo valor serve para borda, marcador e véu, sem três declarações para manter juntas */
    .precs-resumo-estado::after {
      content: ''; position: absolute; inset: 0; background: var(--re-cor, transparent);
      opacity: .12; pointer-events: none;
    }
    .precs-resumo-estado-lbl {
      position: relative; z-index: 1;
      display: flex; align-items: center; gap: var(--space-2);
      font-family: 'Montserrat','Poppins',sans-serif; font-size: .66rem; font-weight: 700;
      text-transform: uppercase; letter-spacing: var(--ls-caps); color: var(--re-cor, var(--text-muted));
    }
    .precs-resumo-estado-lbl::before {
      content: ''; width: 10px; height: 10px; border-radius: 50%; flex: 0 0 auto;
      background: var(--re-cor, var(--text-muted));
    }
    .precs-resumo-estado-val {
      position: relative; z-index: 1; margin-top: var(--space-1); margin-left: 18px;
      font-family: 'JetBrains Mono', monospace; font-weight: 700; font-size: 1.6rem;
      line-height: 1.05; color: var(--text-primary);
    }
    /* no alarme o próprio número vira vermelho, igual ao cronômetro do painel */
    .precs-resumo-estado-grave { border-width: 2px; }
    .precs-resumo-estado-grave .precs-resumo-estado-val { color: var(--re-cor); }

    .precs-resumo-secao {
      display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-2);
      font-family: 'Montserrat','Poppins',sans-serif; font-size: .62rem; font-weight: 700;
      text-transform: uppercase; letter-spacing: var(--ls-caps); color: var(--text-muted);
      margin-bottom: var(--space-2);
    }
    /* o total da sessão vive no cabeçalho da seção, como no painel ("Total 04:41"), e não
       como um chip de desempenho */
    .precs-resumo-secao-tot { font-family: 'JetBrains Mono', monospace; font-weight: 600; letter-spacing: 0; }
    /* termômetro próprio, e não o do painel: aqui ele é estático e sem tooltip */
    .precs-resumo-termo { display: flex; height: 16px; border-radius: var(--radius-pill);
      overflow: hidden; background: var(--bg-tertiary); border: 1px solid var(--border-color); }
    .precs-resumo-termo i { display: block; height: 100%; }
    .precs-resumo-legs { display: flex; flex-wrap: wrap; gap: var(--space-1) var(--space-3); margin-top: var(--space-3); }
    .precs-resumo-leg {
      display: inline-flex; align-items: center; gap: var(--space-2);
      font-size: .72rem; color: var(--text-secondary);
    }
    .precs-resumo-leg b { color: var(--text-primary); font-family: 'JetBrains Mono', monospace; font-weight: 600; }
    .precs-resumo-leg-dot { width: 9px; height: 9px; border-radius: 50%; flex: 0 0 auto;
      box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--text-primary) 25%, transparent); }

    .precs-resumo-pe {
      display: flex; align-items: center; justify-content: space-between;
      margin-top: var(--space-5); padding-top: var(--space-3);
      border-top: 1px solid var(--border-color);
      font-family: 'Montserrat','Poppins',sans-serif; font-size: .6rem; font-weight: 600;
      text-transform: uppercase; letter-spacing: var(--ls-caps); color: var(--text-muted);
    }
    .precs-resumo-pe span:first-child { color: var(--precs-gold); }

    /* Ações e dica ficam FORA do card, para não entrarem no print. */
    .precs-resumo-acoes { display: flex; gap: var(--space-2); }
    /* OURO FIXO #B49552, e não var(--precs-gold): este botão também está sobre o overlay,
       fora do tema. Com o token, no PRECS Claro o fundo virava o bronze de TEXTO (#7A6320)
       e o rótulo #1a1a1a em cima dava 3,01:1 — no brilho suave, 2,47:1. O ouro da marca com
       o mesmo rótulo dá 6,10:1. É o mesmo motivo do .precs-resumo-btn-sec: o bronze existe
       para ser LETRA sobre superfície clara, e usá-lo como FUNDO inverte o papel dele. */
    .precs-resumo-btn {
      font-family: 'Manrope','Poppins',sans-serif; font-size: .8rem; font-weight: 700;
      display: inline-flex; align-items: center; gap: var(--space-2);
      padding: var(--space-2) var(--space-4); border-radius: var(--radius-pill);
      cursor: pointer; color: #1a1a1a; background: #B49552;
      border: 1px solid #8E7440;
      transition: filter var(--dur-1) ease, transform .12s ease;
    }
    .precs-resumo-btn:hover { filter: brightness(1.08); transform: translateY(-1px); }
    .precs-resumo-btn:active { transform: translateY(0); }
    /* VALORES FIXOS, NÃO TOKENS, e este é o ponto todo da regra: este botão fica SOBRE o
       overlay escuro (rgba(0,0,0,.6)), não sobre uma superfície do tema. Ele usava
       --text-secondary e --border-color, que no tema claro valem um marrom escuro e um bege
       claríssimo: o resultado era texto escuro em fundo escuro com borda que não aparecia,
       ou seja, um botão invisível. O mesmo raciocínio já estava aplicado em
       .precs-resumo-dica logo abaixo; aqui tinha passado. Regra geral para este bloco:
       o que está DENTRO do cartão usa token (o cartão tem fundo do tema); o que está FORA,
       sobre o overlay, usa valor fixo claro. */
    .precs-resumo-btn-sec {
      color: #E7E9EE; background: rgba(255,255,255,.10);
      border-color: rgba(255,255,255,.28);
    }
    .precs-resumo-btn-sec:hover { background: rgba(255,255,255,.18); }
    @media (prefers-reduced-motion: reduce) { .precs-resumo-btn { transition: none; } }
    .precs-resumo-dica {
      max-width: 420px; text-align: center; font-size: .72rem; color: #C9CDD6;
      line-height: 1.45;
    }
    .precs-resumo-dica strong { color: #FFFFFF; font-family: 'JetBrains Mono', monospace; }


    /* ======================================================================
       PRECS (1.1.18) — MODO WHATSAPP
       O inbox do operador: conversas à esquerda, thread à direita, compositor
       embaixo. TUDO em token dos temas — o balão próprio é OURO e não o verde
       do WhatsApp, porque a identidade da casa é o ouro; o verde fica para os
       acentos que já significam "positivo" no resto do painel. Os cinco temas
       (claro, claro suave, claro clássico, precs, contraste) saem de graça por
       construção, e as sondas do teste de contraste medem os pares novos.
       ====================================================================== */


/* ======================================================================
   PRECS — A MARCA DO AMBIENTE DE TESTE (homologação)
   ----------------------------------------------------------------------
   Só existe quando o deploy publicou para o bucket de homologação, porque
   só ali o index.html carrega `window.PRECS_AMBIENTE='hml'` e o
   `precsMarcarAmbiente()` cria o elemento. Em produção nada disto chega ao
   DOM — e há teste travando justamente essa metade.

   MOLDURA E SELO, E NÃO UMA FAIXA NO TOPO. Faixa empurra o conteúdo, e o
   painel tem testes que medem geometria. Isto é `position:fixed` com
   `pointer-events:none`: não ocupa espaço no fluxo, não intercepta clique,
   e mesmo assim é impossível não ver.

   AS CORES SÃO LITERAIS DE PROPÓSITO, e é a única vez que isso vale no
   projeto. Não são token porque não pertencem a tema nenhum: elas têm de
   ser as MESMAS nos três temas, senão a marca do ambiente mudaria junto
   com a preferência do operador — e o âmbar foi escolhido por estar fora
   da paleta da marca e fora das cores de estado, para não ser lido como
   "atenção" de uma ligação.
   ====================================================================== */

.precs-amb {
  position: fixed;
  inset: 0;
  z-index: 9998;              /* abaixo dos modais; a moldura não disputa foco */
  pointer-events: none;       /* nada aqui recebe clique */
  border: 3px solid #FFB020;
}

.precs-amb-selo {
  position: absolute;
  right: 0;
  bottom: 0;
  background: #FFB020;
  color: #131315;             /* ~11:1 sobre o âmbar, passa em qualquer tema */
  font-family: var(--font-acao);
  font-size: var(--fs-3);
  font-weight: 700;
  letter-spacing: 0.08em;
  padding: 0.25rem 0.625rem;
  border-radius: var(--radius-sm) 0 0 0;
  pointer-events: none;
}

/* Em aparelho, o selo encolhe. O criterio e `html[data-aparelho]` e NAO um @media de
   largura: o projeto tem uma fonte unica para isso (`precsAplicarAparelho`, com o numero
   em PRECS_APARELHO_LARG/ALT), e repetir o limiar no CSS cria uma segunda verdade que
   sai de sincronia calada. Ha teste travando exatamente isto, e foi ele que me pegou. */
html[data-aparelho] .precs-amb-selo {
  font-size: var(--fs-2);
  padding: 0.1875rem 0.5rem;
}