/* ============================================================
   console.css — o design system v4, aplicado ao Pergor Portal.

   FONTE DA VERDADE: `DESIGN.md` do pacote `new-portal-design.zip`
   (10_Projects/DesignSystem na vault). Nao inventar token nem
   contrariar a spec — se esta folha e o DESIGN.md divergirem, e
   bug de um dos dois, nao licenca para improvisar.

   Como esta folha nasceu: extracao POR COMPONENTE do CSS de
   `mockups-v4.html` (DESIGN.md §13 manda copiar por componente,
   nunca em bloco — 31% das classes de la estao mortas). O script
   que fez o corte esta em scratchpad/extrair_css.py e a lista do
   que foi descartado, em scratchpad/descartados.txt.

   O QUE FOI DESCARTADO, e por que:
     · `.lp-*`, `.shot-*`   landing page — o Portal nao a tem
     · `.mail*`             caixa de e-mail — tela que nao existe aqui
     · `.nt*`, `.note*`     notificacoes e anotacoes — idem
     · `.cfunil`, `.indic*`, `.bloco-*`, `.sw-grid`, `.par*`,
       `.check*`, `.tabs`, `.grafico`, `.page-head`, `.periodo`,
       `.rank*`, `.breakdown`  familias mortas da v3 (DESIGN.md §13)
     · `.moldura`, `.chrome`   moldura de janela: decisao propria —
       barra de URL falsa numa pagina real imita navegador dentro do
       navegador e cheira a phishing. E artefato de apresentacao.

   O QUE FOI RESGATADO da lista de "mortas" do DESIGN.md, de
   proposito: toda a familia de Conversas da v3 (`.conv-*`,
   `.chat-*`, `.msg`, `.ficha*`, `.pend`, `.hist*`, `.grid2`,
   `.dado`, `.aviso-parada`, `.doclist`, `.aprov*`). Ela esta
   morta no mockup do Will porque a v4 nao tem tela de conversas —
   mas o Pergor TEM, e o JP pediu para manter o formato dela.

   ARMADILHA JA PAGA: `.switch` (o toggle de Configuracoes) quase
   sumiu porque `.sw` — prefixo do morto `.sw-grid` — casava com
   ele. Ha uma lista de salvo-conduto no extrator por isso.

   O que esta folha NAO veste: a tela de Relatorio da visita, o
   player, a transcricao, os dialogos de captura e a administracao.
   Essas ficam em `relatorio.css`, que carrega DEPOIS desta.
   ============================================================ */

/* ═══ ÍNDICE DOS CORTES `@media (max-width: …)` DESTA FOLHA ══════════════
   1745  em Conversas o Contato sai da terceira coluna e desce para baixo da
         conversa; a ficha da visita perde a coluna dela
   1180  a barra vira trilho de 64px (GAVETA_ATE no portal.js)
    900  tabelas viram lista de cartões (visitas, contas, pessoas, cérebro)
    860  o trilho vira gaveta (TRILHO_DE = 861 no portal.js); grades a 1 coluna;
         Conversas vira lista-vira-tela (`#conv-fila.na-conversa`)
    700  a contagem da triagem de negócios some
    560  o campo da meta e o diálogo de gravação empilham
   [03/09] O 620 foi dobrado no 560: o diálogo de gravação cortava 60px antes
   do campo da meta sem razão escrita. 900 e 860 seguem separados porque o
   bloco do Cérebro está com outro trabalho em voo; a faixa 861–900 (tabela
   em cartões sobre trilho de ícones) continua sendo dívida anotada.
   Corte novo entra AQUI antes de entrar na folha — `test_foco_e_breakpoints`
   reprova o que não estiver listado. */

/* ============================================================
   Console FinKash v4 — inventário completo de telas
   Mesmos tokens do DESIGN-v3.md (§2) do mockups-v3.html.
   O que muda: o shell adota o layout do kit Venture — topbar com
   busca global, e o seletor de equipe no rodapé da sidebar — e o
   conjunto de telas cobre todo o inventário visível nos previews.
   Conteúdo FinKash, em continuidade com v1, v2 e v3.
   ============================================================ */
/* ============================================================
   Console FinKash v3 — mockups de demonstração
   Tokens e regras conforme DESIGN-v3.md · Mesmo conteúdo do
   mockups.html (v1) e do mockups-v2.html, para comparação direta
   ============================================================ */
:root {
  color-scheme: light;
  /* Cores publicadas de destaque para tarefas de hoje. */
  --task-today-tint: #FFF8DD;
  --task-today-border: #D5A029;
  --task-today-tag-border: #F2D777;
  --task-today-ink: #886514;


  /* Escala neutra (DESIGN-v3.md §2) */
  --neutral-100: #000000;
  --neutral-90:  #36383B;
  --neutral-80:  #6D7076;  /* apenas sobre branco */
  --neutral-75:  #5D5F64;  /* fora do branco */
  --neutral-50:  #E1E5EF;
  --neutral-40:  #E8ECF3;
  --neutral-30:  #F0F2F7;
  --neutral-0:   #FFFFFF;

  /* Superfícies */
  /* [03/09] BRANCO, a pedido do JP — e era o valor canonico: o #EEEDEE foi
     amostrado por engano de um banner do ThemeForest (ver pergor.css) e o
     canvas do sistema ja era branco desde 27/08; esta folha guardava a copia
     velha. Sobre branco a separacao do cartao e SO a borda de 1px
     (--neutral-50, 1,26:1), como o DESIGN.md manda: borda OU contraste de
     superficie, nunca os dois somados. */
  --canvas:     #FFFFFF;
  --surface-50: #F9F9F9;
  --surface-0:  #FFFFFF;

  /* Acentos: tinta de fundo + tinta escura de texto (§2 e §11) */
  --blue-tint:   #EDF2FE;  --blue-ink:   #2A5EF2;
  --green-tint:  #EEF5F0;  --green-ink:  #42774E;
  --amber-tint:  #FBF4EC;  --amber-ink:  #946022;
  --olive-tint:  #F7F7E8;  --olive-ink:  #726E13;
  --red-tint:    #F7EDED;  --red-ink:    #AF4B4B;
  --violet-tint: #F4EDF7;  --violet-ink: #8655B5;

  /* Identidade da empresa aparece como co-brand, sem substituir Pergor. */
  --marca-acento: #0F5B6B;

  /* Sombra só para camadas que flutuam de fato (§5).
     Cards em repouso não recebem sombra nenhuma. */
  --shadow-float: 0 8px 24px rgba(0, 0, 0, .06);
  --shadow-modal: 0 24px 64px rgba(0, 0, 0, .12);

  /* Raios (§5) */
  --r-card:  12px;
  --r-panel: 10px;
  --r-input: 8px;
  --r-badge: 6px;
  --r-pill:  999px;

  /* Movimento: 120–200ms (§9) */
  --t: 160ms ease-out;

  --font: 'Inter', -apple-system, 'Segoe UI', system-ui, sans-serif;
}
* { box-sizing: border-box; margin: 0; padding: 0; }
html, body { min-height: 100%; }
body {
  font-family: var(--font);
  background: var(--canvas);
  color: var(--neutral-90);
  font-size: 14px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}
/* Títulos em medium (500) — nunca bold (§3) */
h1, h2, h3, h4 {
  font-weight: 500;
  color: var(--neutral-100);
  letter-spacing: -.015em;
  line-height: 1.15;
  text-wrap: balance;
}
h1 { letter-spacing: -.022em; }
b, strong { font-weight: 600; }
a { color: var(--blue-ink); }
button { font: inherit; cursor: pointer; }
/* Foco: 2px preto com offset de 2px — a única borda de 2px do sistema (§11) */
:focus-visible { outline: 2px solid var(--neutral-100); outline-offset: 2px; }
.num { font-variant-numeric: tabular-nums; letter-spacing: -.01em; }
.muted { color: var(--neutral-75); }
.spacer { flex: 1; }
.row { display: flex; gap: 12px; align-items: center; flex-wrap: wrap; }
/* [29/08] DUAS GRAFIAS, UMA REGRA. A folha definia só `.sr`; a marcação usa
   `.sr-only` em quatro lugares — e o portão de classes órfãs tinha uma exceção
   AFIRMANDO que `.sr-only` era "o utilitário definido como .sr", o que nunca
   foi verdade. Consequência medida no navegador: o "Abrir" do cabeçalho da
   tabela de Contatos estava VISÍVEL, 28×15px, e foi ao ar assim. Exceção que
   descreve o que deveria existir é cobertura para o que não existe — segunda
   vez que este teste erra pelo mesmo motivo. */
/* Ancorar textos acessíveis evita que sua posição estática dentro de listas
   roláveis aumente a altura do documento, mesmo quando recortados pelo clip. */
.sr, .sr-only { position: absolute; top: 0; left: 0; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
/* Label: 12–13px medium, SEM caixa alta (§3) */
.label { font-size: 12px; font-weight: 500; letter-spacing: 0; }
/* Eyebrow: o único uso de caixa alta do sistema (§3) */
.eyebrow {
  font-size: 11px; font-weight: 500; letter-spacing: .06em;
  text-transform: uppercase; color: var(--neutral-75);
}
/* ===== Shell ===== */
.app-shell { min-height: 100vh; display: grid; grid-template-columns: 252px minmax(0, 1fr); }
.app-shell.collapsed, html.sidebar-collapsed .app-shell { grid-template-columns: 64px minmax(0, 1fr); }
/* Sidebar clara: surface-50 separada do conteúdo por borda de 1px (§4) */
.sidebar {
  position: sticky; top: 0; height: 100vh; z-index: 20;
  display: flex; flex-direction: column;
  background: var(--surface-50); color: var(--neutral-90);
  border-right: 1px solid var(--neutral-50); overflow: hidden;
}
.side-brand {
  min-height: 64px; display: grid; grid-template-columns: 28px 1fr 28px;
  align-items: center; gap: 10px; padding: 16px 14px;
}
.brand-mark { width: 28px; height: 28px; display: block; border-radius: 7px; }
.brand-copy b { display: block; font-size: 14px; font-weight: 600; color: var(--neutral-100); letter-spacing: -.01em; }
.brand-copy > span { display: flex; align-items: center; gap: 5px; margin-top: 1px; font-size: 11px; color: var(--neutral-75); }
.company-brand-accent { display: none; width: 7px; height: 7px; flex: none; border-radius: var(--r-pill); background: var(--marca-acento); }
.company-brand.is-personalized .company-brand-accent { display: block; }
.side-toggle {
  width: 28px; height: 28px; border-radius: var(--r-input); line-height: 1; font-size: 15px;
  border: 1px solid var(--neutral-50); background: var(--surface-0); color: var(--neutral-75);
  display: grid; place-items: center; transition: background var(--t), border-color var(--t), color var(--t);
}
.side-toggle:hover { background: var(--neutral-30); border-color: var(--neutral-90); color: var(--neutral-100); }
.side-nav { flex: 1; overflow-y: auto; padding: 6px 10px 16px; display: flex; flex-direction: column; gap: 2px; }
.nav-group { margin: 20px 0 6px; padding: 0 8px; }
.side-nav a, .side-nav .nav, .nav-disabled, .side-status, .side-user, .side-logout {
  display: flex; align-items: center; gap: 10px;
  min-height: 38px; padding: 8px 10px; border-radius: var(--r-input);
  color: var(--neutral-90); text-decoration: none; font-size: 14px;
  border: 1px solid transparent; background: transparent; text-align: left; width: 100%;
  transition: background var(--t), border-color var(--t), color var(--t);
}
.side-nav a:hover, .side-nav .nav:hover, .side-status:hover, .side-user:hover, .side-logout:hover {
  background: var(--neutral-30); color: var(--neutral-100);
}
/* Item ativo: superfície branca + borda, como no kit de referência */
.side-nav a.active, .side-nav .nav.active {
  background: var(--surface-0); border-color: var(--neutral-50);
  color: var(--neutral-100); font-weight: 500;
}
.nav-ico { width: 18px; height: 18px; flex: none; display: grid; place-items: center; color: var(--neutral-75); }
.side-nav a.active .nav-ico, .side-nav .nav.active .nav-ico { color: var(--neutral-100); }
.nav-ico svg { width: 16px; height: 16px; }
.nav-label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.nav-tag {
  flex: none; background: var(--olive-tint); color: var(--olive-ink);
  border-radius: var(--r-badge); padding: 2px 7px; font-size: 11px; font-weight: 500;
}
.side-footer { border-top: 1px solid var(--neutral-50); padding: 10px; display: flex; flex-direction: column; gap: 2px; }
/* Ponto de status: cor + o próprio texto ao lado (§11) */
.status-dot { width: 8px; height: 8px; border-radius: var(--r-pill); background: var(--green-ink); display: block; }
.avatar {
  width: 28px; height: 28px; flex: none; border-radius: var(--r-pill);
  background: var(--neutral-30); color: var(--neutral-90);
  display: grid; place-items: center; font-size: 11px; font-weight: 600; letter-spacing: .01em;
}
.avatar.lista { width: 32px; height: 32px; font-size: 12px; }
/* Contatos precisam ser reconhecíveis pela foto na fila e na carteira.
   O mesmo tamanho vale para as iniciais quando o WhatsApp não fornece foto. */
.avatar.lista[data-avatar-contato] {
  width: 48px; height: 48px; flex: 0 0 48px; font-size: 14px;
}
.avatar-whatsapp {
  --avatar-url: none;
  position: relative; overflow: hidden; isolation: isolate;
}
.avatar-whatsapp::after {
  content: ""; position: absolute; inset: 0; z-index: 1;
  background-image: var(--avatar-url); background-position: center;
  background-repeat: no-repeat; background-size: cover;
}
/* [13/09] O HERO DA FICHA DO CONTATO. A mesma foto da fila de Conversas, em
   tamanho de ficha: quem abre a pessoa precisa reconhecê-la antes de ler.
   `flex-wrap` em vez de mais um corte de largura — a 390 o bloco de texto
   desce para baixo da foto sozinho, e o índice de cortes fica como está. */
.ficha-hero { display: flex; align-items: center; gap: 12px; margin-top: 10px; flex-wrap: wrap; }
.ficha-hero .avatar.lista[data-avatar-contato] { width: 64px; height: 64px; flex: 0 0 64px; font-size: 18px; }
.ficha-hero-txt { min-width: 0; display: flex; flex-direction: column; gap: 2px; }
/* A linha do cargo vira campo no mesmo lugar: sem salto de layout entre ler e
   editar, o `align-items` segura o botão junto do campo. */
.ficha-cargo { margin: 0; display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  font-size: 13.5px; color: var(--neutral-90); }
.ficha-cargo .field { max-width: 240px; flex: 1 1 160px; }
.ficha-fonte { margin: 0; font-size: 12px; color: var(--neutral-80); }
/* O trecho que justifica o cargo sugerido: gaveta NATIVA (`<details>`), irmã da
   linha do cargo. Fechada por padrão — quem confia na sugestão confirma sem ler,
   quem desconfia abre. `anywhere` porque é fala transcrita e pode vir sem
   espaço onde quebrar; nenhum corte de largura novo. */
.ficha-trecho { font-size: 12px; color: var(--neutral-80); }
.ficha-trecho > summary { cursor: pointer; }
.ficha-trecho blockquote { margin: 4px 0 0; padding-left: 8px;
  border-left: 2px solid var(--neutral-50); overflow-wrap: anywhere; }
/* A `.relacao` nasceu numa coluna de ficha de visita, onde o conteúdo é curto.
   Aqui ela carrega e-mail inteiro, selo de estágio e contagem de mensagens: a
   390 o rótulo fixo de 74px mais os selos espremiam o `<b>` e o texto vazava
   da própria caixa (medido: scrollWidth 220 sobre clientWidth 203, o e-mail
   passando por cima do selo). Os selos descem de linha em vez de empurrar, e
   `anywhere` só entra em quem não tem espaço para quebrar — e-mail e site. */
#accounts-list .relacao { flex-wrap: wrap; }
#accounts-list .relacao b { overflow-wrap: anywhere; min-width: 10ch; }
.app-shell.collapsed .side-brand, html.sidebar-collapsed .side-brand { grid-template-columns: 1fr; justify-items: center; padding: 16px 8px; }
.app-shell.collapsed .brand-copy, html.sidebar-collapsed .brand-copy,
.app-shell.collapsed .nav-label, html.sidebar-collapsed .nav-label,
.app-shell.collapsed .nav-group, html.sidebar-collapsed .nav-group,
.app-shell.collapsed .nav-tag, html.sidebar-collapsed .nav-tag { display: none; }
.app-shell.collapsed .side-nav a, html.sidebar-collapsed .side-nav a,
.app-shell.collapsed .side-nav .nav, html.sidebar-collapsed .side-nav .nav,
.app-shell.collapsed .nav-disabled,
.app-shell.collapsed .side-status,
.app-shell.collapsed .side-user,
.app-shell.collapsed .side-logout { justify-content: center; padding: 10px; }
/* ===== Workspace ===== */
.workspace { min-width: 0; }
main { padding: 32px 32px 64px; width: 100%; max-width: 1440px; margin-inline: auto; }
.visits-inicio { display: grid; grid-template-columns: minmax(0,1.1fr) minmax(0,1fr); gap: clamp(24px,4vw,64px); width: 100%; max-width: 1320px; margin: 24px auto; align-items: center; container-type: inline-size; container-name: visitas-inicio; }
.visits-inicio-convite { min-width: 0; }
.visits-inicio-icone { display: grid; place-items: center; width: 64px; height: 64px; margin-bottom: 24px; border-radius: var(--r-panel); background: var(--blue-tint); color: var(--blue-ink); }
.visits-inicio-icone svg { width: 30px; height: 30px; fill: none; stroke: currentColor; stroke-width: 1.6; stroke-linecap: round; }
.visits-inicio h2 { font-size: clamp(26px,2.1vw,36px); font-weight: 650; line-height: 1.2; margin: 12px 0 16px; }
.visits-inicio-descricao { font-size: 16px; line-height: 1.65; max-width: 52ch; color: var(--neutral-80); }
.visits-inicio-acoes { display: flex; flex-wrap: wrap; gap: 12px; margin: 24px 0 16px; }
.visits-inicio-acoes :where(.btn) { min-height: 44px; }
.visits-inicio-nota { font-size: 13px; line-height: 1.6; color: var(--neutral-75); max-width: 55ch; }
.visits-inicio-etapas { list-style: none; display: grid; gap: 18px; margin-top: 32px; padding: 24px 0 0; border-top: 1px solid var(--neutral-50); }
.visits-inicio-etapas li { display: flex; gap: 12px; align-items: flex-start; }
.visits-inicio-etapas li > span { display: grid; place-items: center; flex: 0 0 28px; height: 28px; border-radius: var(--r-pill); background: var(--neutral-30); font-size: 13px; font-weight: 600; }
.visits-inicio-etapas b { font-size: 15px; font-weight: 600; }
.visits-inicio-etapas p { font-size: 14px; color: var(--neutral-80); line-height: 1.5; margin-top: 3px; }
.visits-inicio-exemplo { min-width: 0; padding: clamp(20px,3vw,32px); border: 1px solid var(--neutral-50); border-radius: var(--r-panel); background: var(--surface-50); }
.visits-exemplo-topo { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-bottom: 24px; font-size: 12px; color: var(--neutral-75); }
.visits-exemplo-selo { display: inline-block; border-radius: var(--r-badge); padding: 6px 8px; background: var(--blue-tint); color: var(--blue-ink); font-weight: 600; letter-spacing: .03em; }
.visits-inicio-exemplo h3 { font-size: 20px; font-weight: 650; margin-bottom: 8px; }
.visits-inicio-exemplo > p { font-size: 14px; line-height: 1.6; color: var(--neutral-80); }
.visits-exemplo-conversa { margin: 24px 0; padding: 18px; border: 1px solid var(--neutral-50); border-radius: var(--r-input); background: var(--surface-0); }
.visits-exemplo-conversa > span { font-size: 11px; font-weight: 600; color: var(--neutral-75); letter-spacing: .04em; }
.visits-exemplo-conversa blockquote { margin: 10px 0 0; font-size: 16px; line-height: 1.6; }
.visits-exemplo-pontos { display: grid; gap: 12px; }
.visits-exemplo-pontos article { display: flex; gap: 12px; padding: 16px; border-radius: var(--r-input); background: var(--surface-0); }
.visits-exemplo-marca { flex: 0 0 4px; border-radius: var(--r-pill); background: var(--blue-ink); }
.visits-exemplo-pontos .interesse .visits-exemplo-marca { background: var(--green-ink); }
.visits-exemplo-pontos .objecao .visits-exemplo-marca { background: var(--amber-ink); }
.visits-exemplo-pontos .proximo .visits-exemplo-marca { background: var(--blue-ink); }
.visits-exemplo-pontos h4 { font-size: 15px; font-weight: 600; margin-bottom: 4px; }
.visits-exemplo-pontos p { font-size: 14px; line-height: 1.5; color: var(--neutral-80); }
.visits-inicio-exemplo .visits-exemplo-rodape { font-size: 12px; margin-top: 20px; }
/* A forma depende do workspace, inclusive no regime de trilho da sidebar. */
body[data-vista="visits"] #conteudo { container-type: inline-size; container-name: visitas-pagina; }
@container visitas-pagina (max-width: 850px) {
  .visits-inicio { grid-template-columns: minmax(0,1fr); margin-block: 8px; gap: 28px; }
}
@container visitas-pagina (max-width: 440px) {
  .visits-inicio-acoes { flex-direction: column; align-items: stretch; }
  .visits-inicio-acoes :where(.btn) { width: 100%; justify-content: center; }
}
/* SUPERFÍCIE DE TRABALHO NÃO TEM CAP DE LEITURA.
   O cap de 1440px existe para prosa: linha longa demais cansa quem lê. Numa
   tela de três colunas de dado vivo ele faz o contrário — sobra tela vazia à
   direita enquanto a fila e a thread ficam apertadas, que foi o que o JP
   fotografou comparando com a tela dos agregados.
   A constituição já dizia a regra em 24/08: "tela grande também é
   responsividade, com o cap de leitura ficando só em quem lê". Isto é a regra
   sendo aplicada, não uma exceção a ela. */
body[data-vista="visits"] main,
body[data-vista="tarefas"] main,
body[data-vista="accounts"] main,
body[data-vista="conversas"] main,
body[data-vista="negocios"] main { max-width: none; }
/* Zoom reduzido amplia a área de trabalho: listas usam essa largura sem JS
   que tente compensar o zoom. Leituras compostas ganham um teto maior, mas
   a sobra fica simétrica dentro do workspace, sem reposicionar a sidebar. */
body[data-vista="report"] main,
body[data-vista="deal"] main,
body[data-vista="admin"] main,
body[data-vista="cerebro"] main { max-width: 1808px; }
/* [04/09] UMA POLITICA DE LARGURA PARA O PAINEL — E ELA E POR COLUNA.
   Tres tentativas anteriores mexeram no teto de `main` (1440 em 24/08, faixas
   de 1760/2040 em 02/09, margem simetrica em 04/09) e o JP continuou vendo a
   mesma tela: "layout nao responsivo... cerca de 800px vazios a direita".
   Duas causas, uma corrigida no portal.js e a outra aqui.

   A CAUSA MORTA: `body[data-vista="home"]` nunca casava. Quem escrevia o
   atributo era `view()`, que NAO roda na carga de documento em `/` — medido no
   app real, `body` sem `data-vista`, `margin-inline` valendo 0 e o conteudo
   terminando a 263px da borda direita a 1920. Corrigido em `marcarVistaInicial`.

   A CAUSA VIVA: teto por TELA nao responde a pergunta certa. O que cansa quem
   le nao e a janela, e o comprimento da LINHA — que aqui e a largura da
   coluna de cartao. Entao o teto e calculado a partir dela:

       3 colunas x 570px + 2 vaos de 16px + 2 respiros de 32px = 1808px

   570px e o teto de coluna do Painel (a folha ja usa 382 a 1180 e 554 a 1440;
   acima de 570 o cartao vira faixa e o texto dele, prosa larga). Abaixo de
   1808 nao ha teto nenhum: o Painel usa a janela inteira, e as colunas crescem
   ate encostar no teto delas. Acima, a sobra vira margem SIMETRICA — margem,
   nao tela inacabada. A razao conteudo/janela fica em 0,94 a 1921, 0,71 a
   2560, 0,64 na janela de 2840 do zoom reduzido do JP e 0,60 a 3000: no piso
   de 0,6 da auditoria de tela de decisao ou acima, em toda largura.

   Nao ha faixa por `@media` aqui de proposito: faixa e teto de tela outra vez,
   e foi o que nao funcionou. A CONTAGEM de colunas responde ao bloco
   (`@container painel`), que e o unico jeito de a mesma janela dar a resposta
   certa com a barra aberta e com ela recolhida. */
body[data-vista="home"] main { max-width: 1808px; margin-inline: auto; }
.mobile-topbar {
  display: none; align-items: center; gap: 12px;
  padding: 12px 20px; background: var(--surface-0);
  border-bottom: 1px solid var(--neutral-50); position: sticky; top: 0; z-index: 15;
}
.mobile-topbar > span { font-size: 13px; font-weight: 500; color: var(--neutral-100); }
.mobile-topbar .company-brand {
  display: none; align-items: center; gap: 5px; min-width: 0; max-width: 45vw;
  padding-left: 10px; border-left: 1px solid var(--neutral-50);
  color: var(--neutral-75); font-size: 12px; font-weight: 500;
}
.mobile-topbar .company-brand.is-personalized { display: flex; }
.mobile-topbar .company-brand [data-company-brand-name] { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#mobile-header-status-slot { display: none; }
h1.page { font-size: 32px; }
/* ===== Cards =====
   Sobre canvas (#EEEDEE) o branco sozinho rende só 1,09:1 — fraco demais
   para contar como separação. Então aqui a borda de 1px carrega o papel e
   não há sombra. Superfícies aninhadas dentro do card usam só contraste. */
.card { background: var(--surface-0); border: 1px solid var(--neutral-50); border-radius: var(--r-card); }
.card-pad { padding: 22px; }
.card-head { display: flex; align-items: center; gap: 12px; padding: 18px 22px; border-bottom: 1px solid var(--neutral-40); }
.card-head h2 { font-size: 18px; }
/* ===== Botões (§7) — um único primário preto por região ===== */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  min-height: 40px; padding: 0 18px; border-radius: var(--r-input);
  border: 1px solid var(--neutral-100); background: var(--neutral-100); color: var(--neutral-0);
  font-size: 14px; font-weight: 500; letter-spacing: -.005em;
  transition: background var(--t), border-color var(--t), color var(--t);
}
/* Hover muda superfície e borda — sem elevação, sem mudança de tamanho (§9) */
.btn:hover { background: var(--neutral-90); border-color: var(--neutral-90); }
.btn.sec { background: var(--surface-0); color: var(--neutral-100); border-color: var(--neutral-50); }
.btn.sec:hover { background: var(--neutral-30); border-color: var(--neutral-90); }
.btn.ghost { background: transparent; border-color: transparent; color: var(--neutral-90); }
.btn.ghost:hover { background: var(--neutral-30); color: var(--neutral-100); }
.btn.danger { background: var(--surface-0); color: var(--red-ink); border-color: var(--red-ink); }
.btn.danger:hover { background: var(--red-tint); }
.btn.on-preto { background: var(--neutral-0); color: var(--neutral-100); border-color: var(--neutral-0); }
.btn.on-preto:hover { background: var(--neutral-50); border-color: var(--neutral-50); }
.btn.on-preto.sec { background: transparent; color: var(--neutral-0); border-color: var(--neutral-75); }
.btn.on-preto.sec:hover { background: var(--neutral-90); border-color: var(--neutral-90); }
.btn:disabled { background: var(--neutral-30); border-color: var(--neutral-30); color: var(--neutral-75); cursor: not-allowed; }
.btn svg { width: 16px; height: 16px; flex: none; }
.btn-circ {
  width: 32px; height: 32px; flex: none; border-radius: var(--r-pill);
  border: 1px solid var(--neutral-50); background: var(--surface-0); color: var(--neutral-90);
  display: grid; place-items: center; transition: background var(--t), border-color var(--t), color var(--t);
}
.btn-circ svg { width: 15px; height: 15px; }
.btn-circ:hover { background: var(--neutral-30); border-color: var(--neutral-90); color: var(--neutral-100); }
.btn-circ.grande { width: 40px; height: 40px; }
.btn-circ.grande svg { width: 17px; height: 17px; }
.btn-circ.solido { background: var(--neutral-100); border-color: var(--neutral-100); color: var(--neutral-0); }
.btn-circ.solido:hover { background: var(--neutral-90); border-color: var(--neutral-90); color: var(--neutral-0); }
.link-acao {
  background: none; border: 0; padding: 0; color: var(--neutral-100);
  font-size: 13px; font-weight: 500; text-decoration: underline; text-underline-offset: 3px;
  text-decoration-color: var(--neutral-50); transition: text-decoration-color var(--t);
}
.link-acao:hover { text-decoration-color: var(--neutral-100); }
/* [F3] Desabilitado tem de PARECER desabilitado. `.link-acao` crava cor e
   sublinhado, e com isso o cinza que o navegador aplica sozinho a um `button`
   desabilitado nao chegava: sem rede, "Concluir" e os chips de adiar ficavam
   pretos e sublinhados, identicos aos que gravam. Mesmo cinza de `.btn:disabled`. */
.link-acao:disabled { color: var(--neutral-75); text-decoration-color: transparent; cursor: not-allowed; }
.link-acao:disabled:hover { text-decoration-color: transparent; }
/* ===== Campos (§7) — label permanente, altura mínima 44px ===== */
.field { display: flex; flex-direction: column; gap: 6px; position: relative; }
.field > span { font-size: 13px; font-weight: 500; color: var(--neutral-90); }
.field input, .field select, select {
  width: 100%; min-height: 44px; padding: 0 12px;
  border: 1px solid var(--neutral-50); border-radius: var(--r-input);
  background: var(--surface-0); color: var(--neutral-90); font: inherit;
  transition: border-color var(--t), background var(--t);
}
.field input::placeholder { color: var(--neutral-80); }
.field input:hover, .field select:hover, select:hover { border-color: var(--neutral-90); }
.field input:focus, .field select:focus, select:focus { border-color: var(--neutral-100); }
.field input:disabled { background: var(--neutral-30); color: var(--neutral-75); cursor: not-allowed; }
.busca {
  display: flex; align-items: center; gap: 8px; min-height: 40px; padding: 0 10px 0 12px;
  background: var(--neutral-30); border: 1px solid transparent; border-radius: var(--r-input);
  transition: background var(--t), border-color var(--t);
}
.busca:hover { border-color: var(--neutral-50); }
/* [03/09] O FOCO É O CONTORNO DA REGRA GLOBAL, NO INVÓLUCRO. Sete campos
   anulavam o `outline` do input interno (certo: ele não pode desenhar um
   retângulo dentro da caixa arredondada) e deixavam só cinza-virando-cinza
   na borda como sinal — justamente nos campos onde se chega por Tab. O
   `.msg-campo` de Conversas já fazia o certo; agora `.busca`, `.kb-estagio`,
   `.orfa-campo`, `.meta-campo` e `.neg-estagio` seguem o mesmo desenho, e os
   inputs com borda própria (`.search-field`, `.kb-motivo`, `.neg-motivo`)
   simplesmente deixam a regra global de `:focus-visible` chegar.
   `tests/test_foco_e_breakpoints.py` cobra. */
.busca:focus-within { outline: 2px solid var(--neutral-100); outline-offset: 2px; background: var(--surface-0); }
.busca svg { width: 16px; height: 16px; flex: none; color: var(--neutral-75); }
.busca input { flex: 1; min-width: 0; border: 0; background: transparent; font: inherit; color: var(--neutral-90); outline: none; }
.busca input::placeholder { color: var(--neutral-80); }
.kbd {
  flex: none; background: var(--surface-0); border-radius: var(--r-badge);
  padding: 3px 7px; font-size: 11px; font-weight: 500; color: var(--neutral-75);
}
/* ===== Selos de estágio (§7) — ponto obrigatório além da cor ===== */
.badge {
  display: inline-flex; align-items: center; gap: 6px; white-space: nowrap;
  min-height: 22px; padding: 3px 10px; border-radius: var(--r-badge);
  font-size: 12px; font-weight: 500;
}
.badge i { width: 6px; height: 6px; border-radius: var(--r-pill); background: currentColor; flex: none; }
.b-lead { background: var(--violet-tint); color: var(--violet-ink); }
.b-analise { background: var(--amber-tint);  color: var(--amber-ink); }
.b-proposta { background: var(--blue-tint);   color: var(--blue-ink); }
.b-contratado { background: var(--green-tint);  color: var(--green-ink); }
.b-cancelado { background: var(--red-tint);    color: var(--red-ink); }

/* Os cinco acima sao o vocabulario do FinKash (lead, analise, proposta,
   contratado, cancelado) e vieram com o kit. O Pergor nao tem funil de
   contrato — tem VISITA, e o que ela deixou em aberto. Os quatro abaixo sao
   os estados que este produto de fato distingue, na mesma familia de tinta:

     ganho    o que fechou bem, e o "Em dia" de uma conta sem pendencia
     atencao  compromisso combinado e nao cumprido
     perda    objecao sem resposta, oportunidade sem retorno marcado
     neutro   estado sem carga: encerrada, sem leitura

   Nao renomeei os do kit: eles nao custam nada parados e apaga-los
   dificultaria conferir esta folha contra o mockup do Will. */
.b-ganho { background: var(--green-tint); color: var(--green-ink); }
.b-atencao { background: var(--amber-tint); color: var(--amber-ink); }
.b-perda { background: var(--red-tint);   color: var(--red-ink); }
.b-neutro { background: var(--surface-50); color: var(--neutral-75); }
/* Tag de categoria: mesma caixa, sem ponto (§7) */
.tag { display: inline-flex; align-items: center; min-height: 22px; padding: 3px 10px;
       border-radius: var(--r-badge); font-size: 12px; font-weight: 500; }
/* ===== Alternador de visualização (§7) — sublinhado preto de 2px =====
   [05/09] A LISTA DE ABAS ROLA NO PRÓPRIO CONTÊINER; a página nunca rola de
   lado (manual §5). Medido a 390px na Administração com o admin super — são
   CINCO abas, porque `loadAdmin` desesconde "Empresas": "Sistema" terminava
   em 407px para 390 de janela (`scrollWidth` 407 contra `clientWidth` 390) e
   a tela inteira ganhava rolagem lateral. Com quatro abas cabe (317px).

   Sem `@media` de propósito: quem decide se rola é a largura do BLOCO, e
   em repouso nada muda de lugar — as margens negativas devolvem exatamente
   o respiro que o padding acrescenta.
   · `min-width: 0` — `.vistas` é item de flex dentro de `.tela-head`, e sem
     isso ele não encolhe abaixo do `min-content` das abas: o `overflow-x`
     nunca chegaria a valer.
   · `flex: none` no botão — rótulo de duas palavras ("Minha conta") não
     quebra linha antes de rolar.
   · O `-1px` que punha o sublinhado sobre o filete do cabeçalho sai do
     botão e vai para o contêiner: um scroller corta o que passa da própria
     caixa, e cortaria justamente o sublinhado.
   · O respiro de 4px é o anel de foco (2px + 2px de offset), que também
     seria cortado nas quatro bordas; `-4px -4px -5px` devolve os 4px e
     mantém o filete no mesmo lugar (o quinto é o `-1px` de antes).
   · `scrollbar-width: none` — barra clássica entra no fluxo e levantaria o
     sublinhado uns 15px acima do filete; a de sobreposição (celular, e a
     emulação em que se mede) pintava um traço escuro por cima do filete. O
     sinal de que há mais é a aba cortada na borda direita — "Siste" a 390px —
     e `revelarAba` (portal.js) rola para dentro a aba tocada ou focada. */
.vistas {
  display: flex; gap: 4px; align-items: center;
  overflow-x: auto; overflow-y: hidden; min-width: 0; max-width: calc(100% + 8px);
  padding: 4px; margin: -4px -4px -5px; scrollbar-width: none;
}
.vistas button {
  display: inline-flex; align-items: center; gap: 7px; flex: none;
  background: none; border: 0; padding: 8px 10px 10px;
  border-bottom: 2px solid transparent; color: var(--neutral-75);
  font-size: 14px; font-weight: 500; transition: color var(--t), border-color var(--t);
}
.vistas button svg { width: 15px; height: 15px; }
.vistas button:hover { color: var(--neutral-100); }
.vistas button.active { color: var(--neutral-100); border-bottom-color: var(--neutral-100); }
/* ===== Tabelas (§7) ===== */
.tabela-wrap { overflow-x: auto; }
table { width: 100%; border-collapse: collapse; font-size: 14px; }
thead th {
  background: var(--neutral-30); color: var(--neutral-75);
  font-size: 12px; font-weight: 500; text-align: left;
  padding: 12px 16px; white-space: nowrap; position: relative;
}
thead th:first-child { border-top-left-radius: var(--r-panel); }
thead th:last-child { border-top-right-radius: var(--r-panel); }
th .ord { display: inline-flex; vertical-align: -2px; margin-left: 6px; color: var(--neutral-80); }
th .ord svg { width: 11px; height: 11px; }
tbody td { padding: 14px 16px; border-bottom: 1px solid var(--neutral-40); vertical-align: middle; color: var(--neutral-90); }
tbody tr:last-child td { border-bottom: 0; }
tbody tr.click { transition: background var(--t); }
tbody tr.click:hover { background: var(--neutral-30); cursor: pointer; }
td.num { font-variant-numeric: tabular-nums; white-space: nowrap; }
.cel-pessoa { display: flex; align-items: center; gap: 10px; min-width: 190px; }
.cel-pessoa b { display: block; font-weight: 600; color: var(--neutral-100); }
.cel-pessoa span span { display: block; font-size: 12px; color: var(--neutral-80); }
/* ===== Conversas ===== */
/* A VISTA OCUPA A JANELA, e as três regiões são declaradas em todo corte largo.
   Antes: `.chat-card { height: 664px }` e `.conv-list { max-height: 600px }` —
   medido a 1280x900, o documento tinha 1084px e a conversa parava nos 664, com
   o resto da janela em branco. E a grade caía de três colunas para duas sem
   dizer para onde ia o terceiro filho: o cartão Contato virava órfão e descia
   para a segunda linha da PRIMEIRA coluna, fora da dobra (medido em (96,841)).
   Coluna que sai muda de lugar de propósito; nunca cai de linha por acidente.

   É `height`, e não `min-height`: um piso só impede a tela de encolher, e com
   doze conversas a fila crescia até empurrar a página para fora da janela em
   vez de rolar dentro do cartão. `height` fecha os dois lados. Os 176px são o
   que fica ACIMA da grade — topbar, recuo do `main` e o título — medidos no
   navegador a 1280x900; abaixo de 861 o cabeçalho é mais alto e o número
   dobra, no bloco de 860. O `min-height` é a válvula: em janela curta demais
   a tela prefere rolar a espremer a conversa a nada. */
#conversas.view.active { display: flex; flex-direction: column; height: calc(100dvh - 176px); min-height: 420px; }
#conv-conexoes-header-slot { display: none; }
.conv-controles-mobile { display: none; }
/* Em tela larga, os controles entram na topbar e os cartões começam logo
   abaixo dela. 104px reservam topbar (64), recuo (16) e rodapé (24). */
@media (min-width: 1440px) {
  body:has(#conversas.active) #conv-conexoes-header-slot:has(#conv-conexoes:not([hidden])) { display: block; flex: none; }
  #conv-conexoes-header-slot .conv-conexao-toolbar { margin: 0; }
  body:has(#conversas.active) main { padding-top: 16px; }
  #conversas.view.active { height: calc(100dvh - 104px); }
}
#conv-fila { display: flex; flex-direction: column; flex: 1; min-height: 0; }
.conv-layout {
  display: grid; gap: 16px; flex: 1; min-height: 420px; align-items: stretch;
  grid-template-columns: minmax(340px, 380px) minmax(0, 1fr) minmax(280px, 340px);
}
.conv-list-card { overflow: hidden; display: flex; flex-direction: column; min-height: 0; }
.conv-list { flex: 1; min-height: 0; overflow-y: auto; }
.conv-contato-card { overflow-y: auto; min-height: 0; }
/* O CONTATO E UMA DOBRA, e ela nasce FECHADA onde o cartao fica DEBAIXO da
   conversa. Medido a 1536x734 com a barra aberta (a janela do JP, 1920x1080 a
   125%): a vista tem 558px, o cartao Contato media 158 e a area de mensagens
   ficava com 172px — uma bolha e meia, com rolagem propria, na tela de
   trabalho do WhatsApp. O teto de `34vh` do corte de 1745 nao era o problema:
   o problema e que o contexto de uma conversa nao pode custar metade da
   conversa. Fechada, a dobra mede a linha do cabecalho (uma linha de nome mais
   os fatos) e a thread fica com o resto.

   Quem decide `open` e o JS (`decidirDobraDoContato`), porque CSS nao controla
   o estado de `<details>`: aberto quando o Contato e a TERCEIRA COLUNA (acima
   de 1745), fechado quando ele desceu para baixo da conversa. O gesto manual
   da pessoa vale ate a proxima conversa aberta.

   O `summary` e o cabecalho do cartao: o `<h2>Contato</h2>` do template virou o
   eyebrow desta linha, e o titulo passou a ser o NOME — que e o que a pessoa
   procura. Os fatos (telefone e contagem) ficam aqui, e por isso NAO se
   repetem dentro: fechada a dobra, eles continuam na tela. */
.conv-contato > summary {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 10px;
  position: relative; padding-right: 20px; cursor: pointer; list-style: none;
}
.conv-contato > summary::-webkit-details-marker { display: none; }
.conv-contato > summary::after {
  content: ""; position: absolute; right: 4px; top: 7px; width: 7px; height: 7px;
  border-right: 1.5px solid var(--neutral-75); border-bottom: 1.5px solid var(--neutral-75);
  transform: rotate(45deg);
}
.conv-contato[open] > summary::after { transform: translateY(3px) rotate(225deg); }
.conv-contato > summary:focus-visible { outline: 2px solid var(--neutral-100); outline-offset: 2px; }
.conv-contato > summary .eyebrow { margin: 0; }
.conv-contato-nome { font-size: 16px; font-weight: 500; line-height: 1.3; color: var(--neutral-100); }
/* `normal` e nao `nowrap`: a 340px na terceira coluna "190 mensagens desde
   10/09/2026" nao cabe em linha, e reticencia aqui engoliria a data inteira.
   Quebrar e de graca; esconder o dado nao. */
.conv-contato-fatos {
  flex: 1 1 100%; font-size: 12.5px; line-height: 1.45; color: var(--neutral-80);
  font-variant-numeric: tabular-nums; white-space: normal;
}
.conv-contato[open] > summary { margin-bottom: 4px; }
/* A DOBRA "Mais opcoes" FALA O MESMO IDIOMA DO VIZINHO. Antes o summary tinha
   borda, fundo e texto a esquerda — cara de CAMPO DE FORMULARIO ao lado de um
   `.btn sec`: dois estilos de controle na mesma linha de acoes. Agora e o
   mesmo `.btn sec`, mesma altura e mesmo alinhamento.
   Aberta ela toma a linha inteira, porque o que ela revela e a confirmacao de
   apagar — tres linhas de aviso e dois botoes, que nao cabem ao lado. */
.conv-acoes { padding-top: 12px; border-top: 1px solid var(--neutral-40); }
.conv-mais > summary { list-style: none; }
.conv-mais > summary::-webkit-details-marker { display: none; }
.conv-mais[open] { flex: 1 1 100%; }
.conv-item {
  width: 100%; display: flex; gap: 14px; align-items: center; text-align: left;
  padding: 14px 16px; background: none; border: 0; border-bottom: 1px solid var(--neutral-40);
  border-left: 2px solid transparent; transition: background var(--t), border-color var(--t);
}
.conv-item:hover { background: var(--neutral-30); }
/* [31/08] O anel de foco FALTAVA, e o elemento é um `<button>` desde sempre:
   a fila era navegável por Tab e não dizia onde o Tab estava. Achado ao ligar
   a fila de conversas de verdade nesta mesma folha. */
.conv-item:focus-visible { outline: 2px solid var(--neutral-100); outline-offset: -2px; }
/* Selecionado: superfície + barra à esquerda — não é só cor (§11) */
.conv-item.sel { background: var(--neutral-30); border-left-color: var(--neutral-100); }
/* A CONVERSA OCULTA É A LINHA INTEIRA, e não uma tag.
   Pedido do JP em 11/09: "a tag está tomando muito espaço... poderia só mudar
   o fundo da referência da pessoa na fila, pra um vermelho clarinho discreto,
   que batendo o olho dá pra ver". A tinta é a que a folha já tem; nenhuma cor
   nova entra. Estas linhas só existem com o interruptor "Mostrar não
   comerciais" ligado — o vermelho separa o que voltou a aparecer do que está
   na fila de trabalho.

   VEM DEPOIS DO `.sel` DE PROPÓSITO: as duas regras têm a mesma
   especificidade, e a linha que o JP fotografou estava aberta E oculta ao
   mesmo tempo. Com a ordem invertida a conversa selecionada perde a tinta —
   justamente a que está na frente de quem olha.

   `neutral-80` sai: ele é "apenas sobre branco" (4,32:1 sobre a tinta, abaixo
   do piso de 4,5). Sobre a tinta o texto de apoio é `neutral-75` (5,57:1).
   E a cor não carrega o estado sozinha (§11): há um ponto de 6px ao lado da
   hora e o texto para leitor de tela na própria linha. */
.conv-item.nao-comercial { background: var(--red-tint); }
.conv-item.nao-comercial .prev, .conv-item.nao-comercial .hora,
  .conv-item.nao-comercial .conv-marcas .espera { color: var(--neutral-75); }
/* Hover não apaga o vermelho: a superfície fica, e o que muda é o MESMO filete
   da esquerda que o selecionado já usa. Sombra não entra — cartão em repouso
   se separa por borda OU por superfície, nunca pelas duas (§5) —, e no
   selecionado o filete continua sendo o preto do `.sel`. */
.conv-item.nao-comercial:hover { background: var(--red-tint); }
.conv-item.nao-comercial:not(.sel):hover { border-left-color: var(--red-ink); }
.conv-oculta {
  flex: none; width: 6px; height: 6px; border-radius: 50%;
  background: var(--red-ink); align-self: flex-start; margin-top: 5px;
}
/* Uma linha, com reticências, pelo mesmo motivo que a prévia: a coluna da fila
   é estreita por definição e "Carla Mendes de Albuquerque" dobrava a altura da
   linha inteira — quatro conversas ocupavam a tela toda. Reticências dizem que
   sobrou nome; recorte mudo é que seria corte de palavra. */
.conv-item .nome {
  display: block; font-size: 15px; line-height: 1.35; font-weight: 600; color: var(--neutral-100);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.conv-item .prev {
  display: block; margin-top: 3px; font-size: 13.5px; line-height: 1.4; color: var(--neutral-80);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.conv-item .hora { flex: none; align-self: flex-start; font-size: 12px; line-height: 1.35; color: var(--neutral-80); font-variant-numeric: tabular-nums; }
/* A terceira linha do item: o que CLASSIFICA a conversa (tag) e quem espera.
   Fica abaixo da prévia porque a prévia é a frase, e frase não divide linha
   com selo sem uma das duas ser cortada. */
.conv-item .conv-marcas { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-top: 7px; }
.conv-item .conv-marcas .tag { min-height: 22px; padding: 2px 8px; font-size: 12px; background: var(--surface-50); color: var(--neutral-75); }
.conv-item .conv-marcas .espera { font-size: 12.5px; color: var(--neutral-80); }
.aviso-parada {
  display: inline-flex; align-items: center; gap: 5px; margin-top: 7px;
  background: var(--amber-tint); color: var(--amber-ink);
  border-radius: var(--r-badge); padding: 3px 8px; font-size: 11.5px; font-weight: 500;
}
.aviso-parada svg { width: 12px; height: 12px; flex: none; }
/* A BUSCA E O RECORTE DA FILA — fixos no topo do cartão, porque a lista rola
   dentro dele e o que se procura não pode rolar para fora junto. `flex: none`
   para que o cartão não cresça: quem encurta é a lista, que já tem rolagem.
   Pedido do JP em 11/09 (a busca) e recorte por ritmo na mesma faixa — as duas
   perguntas sobre a mesma fila moram no mesmo lugar. */
.conv-filtro {
  flex: none; display: flex; flex-wrap: wrap; align-items: center; gap: 6px 8px;
  padding: 0 16px 10px; border-bottom: 1px solid var(--neutral-40);
}
.conv-filtros-mobile { display: none; }
/* QUEM CEDE É A BUSCA, ATÉ O PISO DE 180px — e aí a faixa QUEBRA, de propósito.
   O piso era 60px e cabia numa linha com o select, mas a busca ficava com 69px
   de campo: 38px de padding da lupa mais 12 à direita deixavam 19px de área de
   texto e o placeholder "Buscar conversa" sumia inteiro. O JP aprovou a caixa de
   busca como ela era ("a caixa de pesquisa está ok"), e um campo que não mostra
   o que se digita não é mais ela.
   COM O PISO DE 180px, no cartão de 380px (toda largura ≥ 768): a busca toma a
   linha inteira (314px; 284 a 390) e o select de 237px desce para a segunda —
   ~104px de faixa em TODA largura, contra os 105 da régua de pills que o JP
   reprovou em 12/09. Duas linhas sem régua: nenhuma rolagem lateral, nenhuma
   pill cortada na borda e a contagem visível em cada opção do select.
   O select tem a largura do CONTEÚDO porque o texto dele é o que não pode ser
   cortado — ele diz qual fila está na tela, e `<select>` corta no meio da
   palavra, sem reticências. */
.conv-filtro .search-field { flex: 1 1 180px; min-width: 0; max-width: none; }
/* 44px EM TODA LARGURA, e não só no celular (§10): a fila é tela de trabalho e
   o campo fica num cartão estreito — uma regra vale menos que um corte novo. */
.conv-filtro .search-field input { min-height: 44px; min-width: 0; }
.conv-filtro .filtro-campo { flex: none; }
.conv-filtro .filtro-campo select {
  min-height: 44px; height: 44px; width: auto; max-width: 100%;
}

/* O RITMO DA CONVERSA — CARTÕES no cabeçalho, LINHA DO TEMPO na dobra.
   [12/09] "Os indicadores ... poderia virar cards na lateral direita no próprio
   cabeçalho da conversa, para aproveitar espaço" — JP. A linha de medidas de
   28px saiu de baixo do cabeçalho: `.chat-msgs` ganha os 28px de volta.
   A dobra continua com a decisão do `open` no JS (`ritmoDaThread` com
   `contatoCabeAoLado`), como o cartão Contato. */
#conv-ritmo {
  flex: none; padding: 3px 18px 4px; border-bottom: 1px solid var(--neutral-40);
}
#conv-ritmo:empty { display: none; border-bottom: 0; padding: 0; }
/* FECHADA, A DOBRA NÃO COBRA NADA DA CONVERSA. O gatilho dela virou o cartão
   LINHA DO TEMPO do cabeçalho (12/09) e o summary saiu da vista (`.sr-only` no
   JS): fora do fluxo o summary não ocupa altura, e o padrão mais o filete daqui
   eram os últimos pixels que a dobra fechada ainda tirava de `.chat-msgs`.
   `:has` é o idioma que a folha já usa para isso (`.player:has(.mapa-gravacao)`
   em relatorio.css); aberta, o respiro e o filete voltam. */
#conv-ritmo:has(> .conv-ritmo:not([open])) { padding: 0; border-bottom: 0; }
#conv-ritmo .honest-empty.compact, #conv-ritmo .empty.compact { margin: 0; }
/* O SUMMARY NÃO É MAIS A ALÇA. Ele era a linha de medidas, virou o anúncio da
   faixa e agora é só o rótulo acessível do `<details>`: quem abre e fecha é o
   cartão LINHA DO TEMPO do cabeçalho, com `aria-expanded`. Por isso o summary
   sai da vista pelo utilitário que o sistema já tem (`.sr-only`) e não por uma
   regra nova — continua no DOM, focável e alternável pelo teclado. Saíram daqui
   a seta, o `list-style`, a trava de rolagem e as duas consultas que derrubavam
   as partes do summary: nenhuma delas tem mais o que governar. */

/* A LINHA DAS MEDIDAS QUE CAÍRAM DO CABEÇALHO, dentro da dobra — e só isso desde
   12/09. Era também a linha do summary, e aí ela precisava de `nowrap`: fechada,
   a dobra media a altura dela e duas linhas faziam a área de mensagens pular de
   altura conforme a conversa. Com o summary fora da vista a dobra fechada não
   mede nada, e a linha pode quebrar onde couber — era o que a regra do corpo já
   mandava fazer. */
.conv-ritmo-linha {
  display: flex; align-items: baseline; flex-wrap: wrap; gap: 0 12px;
  margin: 0; min-width: 0; font-size: 13px; line-height: 1.35; color: var(--neutral-80);
  font-variant-numeric: tabular-nums;
}
/* `nowrap` na parte: cortar palavra no meio é pior que derrubar a medida
   inteira, e é por isso que a queda dos cartões é por item e não por reticência. */
.conv-ritmo-parte { white-space: nowrap; }
.conv-ritmo-parte + .conv-ritmo-parte::before { content: "· "; color: var(--neutral-75); }
/* A DOBRA ABERTA É UMA ESPIADA, NÃO UMA PÁGINA. Medido a 390x844 com a dobra
   aberta à mão: a faixa mais três perguntas citadas mediam 256px e deixavam
   `.chat-msgs` com 40px — a conversa desaparecia atrás do seu próprio resumo. */
.conv-ritmo-corpo { padding-top: 8px; max-height: 190px; overflow-y: auto; }
/* O CORPO SÓ REPETE O QUE CAIU DO CABEÇALHO — as mesmas três consultas do
   container `conversa`, no sentido inverso; sem parte visível a linha não ocupa
   altura (a margem mora na parte, não no parágrafo). */
.conv-ritmo-corpo .conv-ritmo-linha .conv-ritmo-parte { display: none; margin-top: 6px; }
.conv-ritmo-corpo .conv-ritmo-linha .conv-ritmo-parte::before { content: none; }
@container conversa (max-width: 840px) { .conv-ritmo-corpo .conv-ritmo-linha .conv-ritmo-parte[data-ritmo="silencio"] { display: inline; } }
@container conversa (max-width: 760px) { .conv-ritmo-corpo .conv-ritmo-linha .conv-ritmo-parte[data-ritmo="resposta"] { display: inline; } }
@container conversa (max-width: 560px) { .conv-ritmo-corpo .conv-ritmo-linha .conv-ritmo-parte[data-ritmo="procura"] { display: inline; } }
/* A LINHA DO TEMPO DA NEGOCIAÇÃO. A altura é DAQUI e a largura é a da thread: o SVG
   não tem `viewBox` nem atributo de tamanho, e as marcas vêm em porcentagem.
   Era `viewBox="0 0 360 28"` com `max-height:40px`, e a proporção preservada
   fazia o teto de altura decidir a largura — ~120px numa thread de 824px
   (print do JP, 12/09). */
.conv-faixa { display: block; width: 100%; height: 56px; }
.conv-faixa-carreiro { stroke: var(--neutral-40); stroke-width: 1; }
.conv-faixa-mes-marca { stroke: var(--neutral-40); stroke-width: 1; }
.conv-faixa-hoje { stroke: var(--neutral-75); stroke-width: 1; stroke-dasharray: 2 2; }
.conv-faixa-mes { fill: var(--neutral-75); font-size: 10px; }
/* O EPISÓDIO É A BARRA, A LACUNA É O VAZIO e o DIA é o alvo fino no canal entre
   os dois carreiros — onde a barra não desenha. [13/09] "se você colocar o do dia
   não conseguimos ver gaps da negociação... fica muito curto prazo" — JP: a barra
   passou a carregar o volume do episódio e o dia ficou com a dica e o clique. O
   `<rect>` do balde é invisível e pega o mouse, o toque e o foco; sob o mouse ele
   aparece com fundo e CONTORNO, que é marcador além da cor (§3.5) — nada cresce e
   nada se desloca (§3.4). */
/* A MÃO SÓ ONDE O CLIQUE EXISTE: quem leva `data-dia` e responde ao clique e ao
   Enter é o DIA — a barra e o vazio são foco de leitura, com dica e nada mais.
   Cursor de mão neles prometia uma ação que o ouvinte não tem. */
.conv-faixa-dia { cursor: pointer; }
.conv-faixa-alvo { fill: transparent; }
/* A quantidade real de dias entra no SVG; este padrão cobre payloads antigos. */
.conv-faixa { --faixa-dias: 90; }
.conv-faixa-ponto { r: clamp(0.6px, calc(28cqw / var(--faixa-dias, 90)), 2.5px); }
.conv-faixa-retomada circle { fill: none; stroke-width: 2; }
/* A marca de mês atravessa a faixa de cima a baixo, e a 768 ela cai EM CIMA da
   frase da lacuna: o halo da própria superfície é o truque nativo de SVG para
   o texto ganhar da linha sem cor nova e sem sombra. */
.conv-faixa-lacuna-rotulo {
  fill: var(--neutral-75); font-size: 10px;
  paint-order: stroke; stroke: var(--surface-0); stroke-width: 3;
}
.conv-faixa-dia:hover .conv-faixa-alvo {
  fill: var(--neutral-40); stroke: var(--neutral-100); stroke-width: 1;
}
/* O FOCO DO TECLADO NÃO É O HOVER. Era o mesmo bloco, e com 1px: quem chega de
   Tab via exatamente o que o mouse mostra, num contorno da espessura do
   carreiro. A casa reserva 2px ao foco e a mais nada (regra 6) — mesmos dois
   tokens, só a espessura sobe. */
.conv-faixa-dia:focus-visible .conv-faixa-alvo,
.conv-faixa-lacuna:focus-visible .conv-faixa-alvo {
  fill: var(--neutral-40); stroke: var(--neutral-100); stroke-width: 2;
}
.conv-faixa-dia:focus, .conv-faixa-episodio:focus, .conv-faixa-lacuna:focus { outline: none; }
.conv-faixa-episodio:focus-visible .conv-faixa-ponto {
  stroke: var(--neutral-100); stroke-width: 1;
}
/* A FRASE DA LACUNA só onde ela cabe: numa thread de celular nem "12 dias sem
   contato" entra, e a duração continua inteira na dica e no cartão SILÊNCIO. */
@container conversa (max-width: 560px) { .conv-faixa-lacuna-rotulo { display: none; } }
.conv-faixa-eixo {
  display: flex; justify-content: space-between; gap: 8px; margin: 0;
  font-size: 11px; line-height: 1.3; color: var(--neutral-75);
}
.conv-faixa-legenda { white-space: nowrap; }
.conv-faixa-loja { color: var(--blue-ink); }
.conv-faixa-cliente { color: var(--amber-ink); }
/* AS PERGUNTAS SÃO CITAÇÃO. Texto de terceiro, entre aspas e com a hora ao
   lado — é o que permite conferir na thread sem adivinhar de quando é. */
.conv-ritmo-perguntas {
  margin: 8px 0 0; padding-left: 16px;
  font-size: 12.5px; line-height: 1.5; color: var(--neutral-80);
}
.conv-ritmo-perguntas .conv-ritmo-parte { color: var(--neutral-75); font-size: 11.5px; }

/* OS CARTÕES DO CABEÇALHO. Medida à direita do título, uma linha cada, e o
   cabeçalho NÃO pode crescer por causa deles: o padrão vertical do `.chat-head`
   encolheu e o `min-height` guarda a altura que ele tinha (53px medidos).
   `.eyebrow` e nenhuma classe nova de rótulo: o único caixa-alta do sistema
   (§3) já é esse. Sem sombra, sem cor nova, sem token novo. */
.conv-ritmo-cartoes {
  margin-left: auto; display: flex; flex-wrap: nowrap; align-items: stretch;
  /* `flex: none`: QUEM CEDE É O NOME, que tem reticências. Medido a 390: com os
     cartões encolhíveis, PERGUNTAS ficava com 90px para 107 de conteúdo e cortava
     "3 sem resposta" — medida pela metade é pior que nome pela metade. */
  flex: none; gap: 6px;
}
/* [13/09] "os quadros dos indicadores está muito pobre.. poderia ter uma
   estilizada" — JP. O idioma é o do `.stat` do Painel, em versão de cabeçalho:
   mesma superfície de cartão (`--surface-0`), mesma borda do cartão do sistema
   (`--neutral-50`) e `--r-panel`. Era `--surface-50` — a MESMA superfície da
   área de mensagens — mais borda: separação pelas DUAS vias somadas, e ainda
   assim o cartão parecia um pedaço da thread solto no cabeçalho. Agora a
   superfície é a do cabeçalho e quem separa é SÓ a borda (§3.7).
   44px é o alvo mínimo de toque dos dois `<button>` no celular (§4). */
.conv-ritmo-cartao {
  display: flex; flex-direction: column; justify-content: center; gap: 1px;
  min-height: 44px; padding: 6px 10px;
  border: 1px solid var(--neutral-50); border-radius: var(--r-panel);
  background: var(--surface-0); text-align: left; white-space: nowrap;
  transition: background var(--t), border-color var(--t);
}
.conv-ritmo-cartao .eyebrow { font-size: 10px; line-height: 1.2; }
.conv-ritmo-valor {
  font-size: 14px; font-weight: 500; line-height: 1.25;
  color: var(--neutral-100); font-variant-numeric: tabular-nums;
}
/* O MARCADOR DE ESTADO, no mesmo desenho do ponto do selo (`.badge i`): 6px
   redondos em `currentColor`. A tinta mora no ponto e no microtexto, nunca no
   fundo do cartão (§2), e é a MESMA dos dois carreiros da linha do tempo — a
   loja em azul e o cliente em âmbar. `alerta` é o silêncio de mais de uma
   semana; `neutro` é o equilíbrio, que não tem lado. */
.conv-ritmo-ponto {
  display: inline-block; width: 6px; height: 6px; margin-right: 6px;
  border-radius: var(--r-pill); background: currentColor; vertical-align: middle;
}
.conv-ritmo-valor [data-ponto="loja"] { color: var(--blue-ink); }
.conv-ritmo-valor [data-ponto="cliente"] { color: var(--amber-ink); }
.conv-ritmo-valor [data-ponto="alerta"] { color: var(--red-ink); }
.conv-ritmo-valor [data-ponto="neutro"] { color: var(--neutral-75); }
/* A ALÇA TEM CARA DE ALÇA: o chevron do `.stat` do Painel, ao lado do texto e
   girando com `aria-expanded` — lá quem gira é `[open]`, aqui o estado real do
   `<details>` mora no botão. Só o cartão LINHA DO TEMPO fica em linha, e o
   seletor é o ESTADO que só ele tem: pelo `data-ritmo` viraria gêmeo do seletor
   da QUEDA, e a alça nunca cai. */
.conv-ritmo-cartao[aria-expanded] { flex-direction: row; align-items: center; gap: 8px; }
.conv-ritmo-texto { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.conv-ritmo-cartao .chev {
  display: flex; align-items: center; justify-content: center; flex: none;
  width: 14px; height: 14px; color: var(--neutral-75);
  font-size: 13px; line-height: 1; transition: transform var(--t);
}
.conv-ritmo-cartao[aria-expanded="true"] .chev { transform: rotate(180deg); }
/* PERGUNTAS é `<button>` porque abre a dobra e rola até as citações — e não é
   `.btn`: o botão preto desta região continua sendo o de enviar (§7). */
button.conv-ritmo-cartao { cursor: pointer; font: inherit; }
/* Hover troca SUPERFÍCIE e BORDA, e nada desloca nem cresce (§3.4). */
button.conv-ritmo-cartao:hover { background: var(--surface-50); border-color: var(--neutral-80); }
button.conv-ritmo-cartao:focus-visible { outline: 2px solid var(--neutral-100); outline-offset: 2px; }
/* A ORDEM DA QUEDA, quando a thread encurta: silêncio > resposta > quem procura.
   PERGUNTAS e LINHA DO TEMPO nunca caem — uma pede ação hoje, a outra é a alça da
   dobra. Quem decide é a largura do CONTAINER `.chat-card` (muda com a coluna do
   Contato e com o trilho), nunca a da janela: nenhum corte novo entra na folha. O
   que cai volta INTEIRO no corpo da dobra, nas mesmas larguras.
   OS NÚMEROS SUBIRAM DE NOVO em 13/09 (820/660/510 → 840/760/560), com os
   cartões redesenhados e MEDIDOS no navegador: LINHA DO TEMPO 143, QUEM PROCURA
   111, RESPOSTA 187, SILÊNCIO 75 (era 166: o lado da última mensagem virou ponto)
   e PERGUNTAS 137, com 6 de respiro entre eles. A conta é a mesma: o que sobra
   para o NOME = container − 36 de padrão − 10 de respiro − os cartões; nos três
   novos cortes o nome nunca fica abaixo de ~112px (era ~85 com os antigos, que
   com estes cartões deixariam o nome com 19px a 661). O container é o CONTEÚDO
   do `.chat-card` (824 de caixa a 1536 = 790 de container: 2 de borda e 32 de
   padrão), e por isso os cinco cartões só cabem acima de 840 — a 1536, com a
   coluna do Contato ao lado, SILÊNCIO continua caindo para dentro da dobra.
   OS NÚMEROS SUBIRAM 120px em 12/09, que é o que o cartão LINHA DO TEMPO ocupa.
   A conta é: o que sobra para o NOME = container − 36 de padrão − 10 de respiro −
   os cartões. MEDIDO com a conversa do print (cartões de 113+107+149+166+113):
   com os cortes antigos, a 1480 e a 1536 os cinco cabiam e o nome era esmagado a
   1px — a tela deixava de dizer de quem é a conversa para caber uma medida que
   está inteira dentro da dobra. Com 820/660/510 o nome nunca fica abaixo de
   ~110px; abaixo de ~406 nem isso cabe, e aí o cabeçalho quebra em duas linhas. */
@container conversa (max-width: 840px) { .conv-ritmo-cartao[data-ritmo="silencio"] { display: none; } }
@container conversa (max-width: 760px) { .conv-ritmo-cartao[data-ritmo="resposta"] { display: none; } }
@container conversa (max-width: 560px) { .conv-ritmo-cartao[data-ritmo="procura"] { display: none; } }

/* `container-type` AQUI porque a queda dos cartões do cabeçalho responde à
   largura DA CONVERSA — que muda com a coluna do Contato, com o trilho e com a
   janela —, e um `@media` responderia pela janela inteira. */
.chat-card { display: flex; flex-direction: column; min-height: 0; container-type: inline-size; container-name: conversa; }
/* O padrão vertical caiu de 16px para 7px e o `min-height` guarda a altura de
   antes: os cartões de 38px entram sem o cabeçalho crescer um pixel.
   `flex-wrap: wrap` É O CINTO DO CABEÇALHO CHEIO, e só age onde ele transborda:
   MEDIDO a 390 com os dois botões que nunca caem (LINHA DO TEMPO e PERGUNTAS,
   112px cada), Voltar e os respiros pediam 328px numa linha de 317 — o nome tem
   `min-width: 0` e foi esmagado a ZERO antes do cabeçalho vazar 11px, ou seja, a
   tela deixava de dizer de quem é a conversa. Com o wrap, o grupo de cartões
   desce para a segunda linha (o `margin-left: auto` o mantém à direita) e o nome
   fica inteiro. Onde os itens fixos CABEM, nada quebra: medido 53px a 1280, 1536
   e 1800, igual a antes. */
.chat-head { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; padding: 7px 18px; min-height: 53px; border-bottom: 1px solid var(--neutral-40); }
/* A volta para a fila só existe onde a fila SAIU da tela (abaixo de 861). */
.conv-voltar { display: none; }
/* O NOME CEDE PRIMEIRO, com reticências — o mesmo tratamento da linha da fila
   (`.conv-item .nome`). Medido a 390 com a conversa aberta: "Imediato
   Agregados" pedia 136px e sobravam 119 ao lado do Voltar e do cartão de
   PERGUNTAS; sem isto o cabeçalho transbordava para o lado. Reticências dizem
   que sobrou nome; empurrar o cartão para fora da tela não diz nada.
   `flex: 1 1 0` porque o flex QUEBRA A LINHA ANTES DE ENCOLHER: com a base
   automática, o nome de 136px sobrava 7px sobre a linha de 1280 e derrubava os
   cartões para uma segunda fileira — 31px de cabeçalho a mais para economizar 7.
   Com base 0 ele cede primeiro, e o cabeçalho só quebra onde os itens FIXOS não
   cabem nem com o nome em zero (a 390, com os dois botões que nunca caem). */
.chat-head .nome { font-size: 14px; font-weight: 600; color: var(--neutral-100);
  flex: 1 1 0; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.chat-msgs { flex: 1; overflow-y: auto; padding: 20px 18px; display: flex; flex-direction: column; gap: 14px; background: var(--surface-50); }
/* Três tratamentos, só com superfícies — nenhuma cor envolvida */
/* O TETO DA BOLHA E EM PIXEL PORQUE 74% DE QUE? Enquanto o `main` tinha cap de
   1440px, a porcentagem tinha teto por acidente. Tirado o cap (a tela de
   trabalho usa a largura), a bolha passou a crescer sem fim: medido a 2560px,
   uma mensagem de WhatsApp ficava com 1151px de largura. `min()` mantem os dois
   regimes — a porcentagem manda no estreito, onde ela e o que impede a bolha de
   encostar nas duas bordas, e o pixel manda no largo, onde so ele sabe quanto e
   linha demais. 560px a 13.5px sao ~80 caracteres: a faixa de leitura, que vale
   para a bolha mesmo quando a tela em volta nao e de leitura. */
.msg { position: relative; max-width: min(74%, 560px); padding: 12px 34px 12px 14px; border-radius: var(--r-panel); font-size: 13.5px; }
.msg .meta {
  display: block; margin-top: 4px; font-size: 10.5px; line-height: 1;
  text-align: right; color: var(--neutral-75); font-variant-numeric: tabular-nums;
}
.msg-dia-group {
  display: flex; flex-direction: column; gap: 14px; min-width: 0;
}
.msg-data {
  position: sticky; top: 0; z-index: 2; align-self: center;
  display: flex; justify-content: center; width: 100%; pointer-events: none;
}
.msg-data span {
  padding: 5px 10px; border: 1px solid var(--neutral-40);
  border-radius: var(--r-badge); background: var(--surface-0);
  color: var(--neutral-75); font-size: 11px; font-weight: 600;
}
.msg.cliente { align-self: flex-start; background: var(--surface-0); border: 1px solid var(--neutral-50); }
.msg.copiloto { align-self: flex-start; background: var(--neutral-30); }
.msg.consultor { align-self: flex-end; background: var(--neutral-100); color: var(--neutral-0); }
.msg.consultor .meta { color: var(--neutral-50); }
.msg .autor { display: block; margin-bottom: 5px; color: var(--neutral-75); }
.msg.consultor .autor { color: var(--neutral-50); }
.msg .doc {
  display: flex; width: fit-content; align-items: center; gap: 8px; margin-bottom: 8px;
  padding: 8px 12px; border-radius: var(--r-input);
  background: var(--neutral-30); color: var(--neutral-100); text-decoration: none;
  font-size: 12.5px; font-weight: 500; transition: background var(--t);
}
.msg .doc:hover { background: var(--neutral-40); }
.msg .doc svg { width: 15px; height: 15px; }
/* Leitura de mídia guardada (contrato §4): cabeçalho curto por tipo e o
   texto lido, que é DADO de terceiro — só CSS decide a quebra de linha,
   nunca `<br>` interpolado a partir do texto. */
.msg-tipo { display: block; margin-bottom: 4px; font-size: 12px; font-weight: 600; color: var(--neutral-75); }
.msg.consultor .msg-tipo { color: var(--neutral-50); }
.msg-leitura { white-space: pre-wrap; }
/* Mídia VISÍVEL (03/09/2026): o arquivo já está guardado — o player e a
   miniatura aparecem sozinhos, sem esperar a leitura (transcrição/OCR), que é
   um relógio à parte. `.midia-play` é o único preto cheio EM REPOUSO desta
   fatia: nada de sombra, o contorno de foco é `outline`, nunca `box-shadow`. */
/* O player da mensagem de voz é o `.player` do relatório (ver `playerDeAudio`),
   dentro de uma bolha que já tem 14px de recuo: dois recuos de 14 deixavam o
   trilho com menos que os 280px para os quais a grade dele foi desenhada. O
   `.midia-play` continua sendo o botão — a thread não ganha um preto novo por
   linha — e por isso ele também precisa da área `botao` da grade. */
.msg .player { padding: 8px 10px; margin-bottom: 4px; }
.msg .player-rot { color: var(--neutral-75); }
.midia-play {
  display: inline-flex; align-items: center; justify-content: center; flex: none;
  width: 28px; height: 28px; border-radius: 50%; border: none; padding: 0;
  background: var(--neutral-100); color: var(--surface-0); cursor: pointer;
  transition: background var(--t);
}
.midia-play svg { display: block; width: 13px; height: 13px; margin-left: 1px; }
.midia-play:hover { background: var(--neutral-90); }
.midia-play:focus-visible { outline: 2px solid var(--neutral-100); outline-offset: 2px; }
.midia-imagem { display: block; width: fit-content; margin-bottom: 4px; }
.midia-imagem img { display: block; max-width: 240px; border: 1px solid var(--neutral-50); border-radius: var(--r-input); }
.midia-video { display: block; max-width: 320px; border-radius: var(--r-input); margin-bottom: 4px; }
.btn.mini { min-height: 28px; padding: 0 12px; margin-top: 6px; font-size: 12.5px; }
.chat-foot { display: flex; gap: 10px; align-items: center; padding: 14px 18px; border-top: 1px solid var(--neutral-40); }
.chat-foot .field { flex: 1; }
.chat-foot input { min-height: 40px; }
.ficha-card { overflow: hidden; }
.ficha { padding: 20px; max-height: 664px; overflow-y: auto; }
.ficha h3 { font-size: 13px; font-weight: 500; color: var(--neutral-90); padding-top: 22px; margin-bottom: 12px; border-top: 1px solid var(--neutral-40); }
.ficha h3:first-child { padding-top: 0; border-top: 0; }
.grid2 { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
.grid2 .full { grid-column: 1 / -1; }
.dado { font-size: 13px; color: var(--neutral-90); min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.dado span { display: block; font-size: 11px; color: var(--neutral-80); margin-bottom: 2px; }
.pend { background: var(--amber-tint); border-radius: var(--r-panel); padding: 14px; }
.pend .t { display: flex; align-items: center; gap: 6px; color: var(--amber-ink); margin-bottom: 8px; }
.pend .t svg { width: 14px; height: 14px; flex: none; }
.pend .i { font-size: 12.5px; color: var(--neutral-90); padding-left: 16px; position: relative; margin-top: 5px; }
.pend .i::before { content: ""; position: absolute; left: 4px; top: 7px; width: 5px; height: 5px; border-radius: var(--r-pill); background: var(--amber-ink); }
.aprovacoes { display: grid; grid-template-columns: repeat(auto-fit, minmax(88px, 1fr)); gap: 8px; }
.aprov { border: 1px solid var(--neutral-50); border-radius: var(--r-panel); padding: 12px 6px; text-align: center; }
.aprov .nm { font-size: 12px; color: var(--neutral-80); margin-bottom: 7px; }
.aprov .ok { display: inline-flex; align-items: center; gap: 4px; font-size: 11.5px; font-weight: 500; color: var(--green-ink); white-space: nowrap; }
.aprov .ok svg { width: 12px; height: 12px; }
.aprov .pd { font-size: 11.5px; font-weight: 500; color: var(--neutral-80); white-space: nowrap; }
.doclist { display: flex; flex-direction: column; }
.doclist a {
  display: flex; align-items: center; gap: 9px; padding: 10px 4px;
  border-top: 1px solid var(--neutral-40); color: var(--neutral-90);
  text-decoration: none; font-size: 12.5px; transition: color var(--t);
}
.doclist a:first-child { border-top: 0; }
.doclist a:hover { color: var(--neutral-100); text-decoration: underline; text-underline-offset: 3px; }
.doclist svg { width: 15px; height: 15px; flex: none; color: var(--neutral-80); }
.hist { display: flex; flex-direction: column; }
.hist-item { display: flex; gap: 12px; padding: 10px 0; border-bottom: 1px solid var(--neutral-40); font-size: 12.5px; color: var(--neutral-90); }
.hist-item:last-child { border-bottom: 0; }
.hist-item time { flex: none; width: 88px; color: var(--neutral-80); font-variant-numeric: tabular-nums; }
/* ===== Configurações ===== */
.cfg-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px; align-items: start; }
.cfg-item { display: flex; gap: 18px; align-items: flex-start; padding: 18px 0; border-top: 1px solid var(--neutral-40); }
.cfg-item:first-of-type { border-top: 0; padding-top: 0; }
.cfg-item > div:first-child { flex: 1; }
.cfg-item h4 { font-size: 14px; font-weight: 500; margin-bottom: 5px; }
.cfg-item p { font-size: 12.5px; color: var(--neutral-75); }
/* Toggle: preto quando ligado, e o deslocamento é o segundo indicador (§7) */
.switch { position: relative; display: inline-block; width: 44px; height: 24px; flex: none; }
.switch input { position: absolute; opacity: 0; width: 100%; height: 100%; margin: 0; cursor: pointer; }
.switch .sl { display: block; width: 44px; height: 24px; border-radius: var(--r-pill); background: var(--neutral-50); transition: background var(--t); }
.switch .sl::before {
  content: ""; position: absolute; left: 2px; top: 2px; width: 20px; height: 20px;
  border-radius: var(--r-pill); background: var(--neutral-0); transition: transform var(--t);
}
.switch input:checked + .sl { background: var(--neutral-100); }
.switch input:checked + .sl::before { transform: translateX(20px); }
.switch input:focus-visible + .sl { outline: 2px solid var(--neutral-100); outline-offset: 2px; }
.switch-estado { color: var(--neutral-75); min-width: 46px; text-align: right; }
.acc-item { border-bottom: 1px solid var(--neutral-40); }
.acc-btn {
  width: 100%; display: flex; align-items: center; gap: 12px; text-align: left;
  background: none; border: 0; padding: 16px 0; color: var(--neutral-100);
  font-size: 14px; font-weight: 500; transition: color var(--t);
}
.acc-btn:hover { color: var(--neutral-75); }
.acc-sinal { position: relative; width: 14px; height: 14px; flex: none; margin-left: auto; transition: transform var(--t); }
.acc-sinal::before, .acc-sinal::after { content: ""; position: absolute; background: var(--neutral-90); border-radius: 1px; }
.acc-sinal::before { left: 0; top: 6px; width: 14px; height: 2px; }
.acc-sinal::after { left: 6px; top: 0; width: 2px; height: 14px; transition: opacity var(--t); }
.acc-btn[aria-expanded="true"] .acc-sinal { transform: rotate(45deg); }
.acc-btn[aria-expanded="true"] .acc-sinal::after { opacity: 0; }
.acc-painel { display: grid; grid-template-rows: 0fr; transition: grid-template-rows var(--t); }
.acc-painel > div { overflow: hidden; }
.acc-item.aberto .acc-painel { grid-template-rows: 1fr; }
.acc-painel p { font-size: 13.5px; color: var(--neutral-75); padding: 0 34px 18px 0; }
/* ===== Moldura de janela (§8) — o enquadramento das capturas ===== */
/* [28/08] O palco mede a JANELA, não um número.
   Defeito que o JP viu: "o login dependendo do zoom não fica centralizado".
   O `min-height` era `660px` — pixel fixo —, então o cartão centrava dentro
   de uma caixa de 660px e não dentro da tela: medido, o centro do cartão
   ficava 128px acima do centro numa janela de 900px e 218px acima numa de
   1080px. Zoom muda a altura da janela em pixels CSS, então a mesma tela
   errava por valores diferentes a cada nível — que é exatamente a forma como
   o defeito aparece para quem usa.
   `dvh` acompanha a barra do navegador no celular; `vh` fica de reserva para
   quem não conhece a unidade. Continua sendo MIN-height: cartão mais alto que
   a janela faz o palco crescer e a página rolar, em vez de cortar o topo.

   `max-width: none` cancela o cap de 1440px que o `main` do console impõe — e
   o palco É um `<main>`. Sem isto, acima de 1440px o palco fica encostado à
   ESQUERDA e o cartão centra dentro dessa caixa, não da tela: numa janela de
   1914px o desvio é de 237px, que foi o que o JP fotografou depois de a
   correção vertical já ter entrado. O cap serve à leitura de tabela e texto
   no console; aplicado a um palco de fundo inteiro, ele descentraliza.
   A primeira verificação não pegou porque mediu 360 · 820 · 1280 · 1440 de
   largura — e o defeito só existe ACIMA do cap. Régua que para onde o defeito
   começa não é régua. */
/* Respiro SIMÉTRICO: com 56 em cima e 72 embaixo o cartão nascia 8px acima do
   centro — invisível, mas é discrepância sem motivo numa tela cuja única
   tarefa é centrar um cartão. Centrado quer dizer centrado. */
.palco { position: relative; min-height: 100vh; min-height: 100dvh; padding: 56px 20px; display: grid; place-items: center; overflow: hidden; max-width: none; }
/* A malha era uma caixa FIXA de 1200x600 centrada por `margin: auto`: num
   monitor de 1920 sobrava fundo liso nas laterais, e numa janela baixa — em
   que o cartão é mais alto que a tela e a página rola — o desenho acabava no
   meio da rolagem. O JP pediu o fundo estilizado no palco INTEIRO, as quatro
   bordas, em qualquer tamanho. Percentual acompanha o `.palco`, que já é o
   contexto deste absoluto e cresce com o conteúdo; a célula continua 56x97
   porque o <svg> perdeu o viewBox e a unidade do usuário voltou a ser o px. */
.hex-mesh { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }
.login-card { padding: 36px 32px 32px; }
.login-card .marca { display: flex; align-items: center; gap: 10px; margin-bottom: 26px; }
.login-card .marca span { font-size: 15px; font-weight: 600; color: var(--neutral-100); }
.login-card h2 { font-size: 24px; }
.login-card .sub { color: var(--neutral-75); font-size: 13.5px; margin-top: 6px; margin-bottom: 26px; }
.login-card .field { margin-bottom: 16px; }
.login-card .btn { width: 100%; min-height: 44px; }
.divisor { display: flex; align-items: center; gap: 12px; margin: 22px 0; font-size: 12px; color: var(--neutral-80); }
.divisor::before, .divisor::after { content: ""; flex: 1; height: 1px; background: var(--neutral-50); }
.login-nota { margin-top: 22px; font-size: 12px; color: var(--neutral-80); text-align: center; }
/* ===== Sobreposições — aqui a sombra é legítima (§5) ===== */
.modal-bg { position: fixed; inset: 0; z-index: 60; background: rgba(0, 0, 0, .38); display: grid; place-items: center; padding: 20px; }
.modal-bg[hidden] { display: none; }
.modal {
  width: 100%; max-width: 440px; background: var(--surface-0);
  border-radius: var(--r-card); padding: 26px; box-shadow: var(--shadow-modal);
  animation: entra var(--t) ease-out;
}
@keyframes entra { from { opacity: 0; transform: scale(.98); } to { opacity: 1; transform: scale(1); } }
.modal h3 { font-size: 19px; margin-bottom: 10px; }
.modal p { font-size: 13.5px; color: var(--neutral-75); }
.modal .acts { display: flex; gap: 10px; justify-content: flex-end; margin-top: 24px; }
/* ═══ TOAST ═══ a confirmação de toda ação do console ══════════════════════
   [04/09] Estas regras VIERAM do `pergor.css`, que o `<head>` do console não
   carrega desde a F1. Enquanto elas moravam lá, `toast()` (`portal.js`) punha
   a classe, o texto entrava no `<div id="toast">` — e ninguém via nada: umas
   45 frases de confirmação ("Tarefa criada.", "Acesso excluído.") acontecendo
   em silêncio absoluto, com o console limpo e a suíte verde.

   O que estava aqui no lugar era uma família `.toast` que elemento NENHUM do
   repositório usa: uma segunda máquina de toast, órfã. Ela saiu junto — duas
   na mesma cascata é como a primeira morreu sem ninguém notar. Quem guarda
   isso agora é `tests/test_folha_morta.py`. */
#toast {
  position: fixed; left: 50%; bottom: 28px; transform: translateX(-50%);
  background: var(--surface-inverse);
  border: 1px solid var(--border-inverse);
  color: var(--text-on-inverse);
  padding: var(--pg-espaco-3) var(--pg-espaco-4);
  border-radius: var(--pg-raio-4);
  /* 4px de deslocamento, não 50px: o §9 pede que o movimento seja discreto e
     que hover/entrada não desloquem o layout. O `translateX(-50%)` precisa
     sobreviver ao estado de entrada, por isso os dois eixos vêm juntos. */
  opacity: 0; transform: translate(-50%, 4px);
  transition: opacity var(--t), transform var(--t);
  box-shadow: var(--shadow-modal); font-weight: 500;
}
/* Vermelho só fala de falha de sistema. */
#toast.error { background: var(--pg-falha); border-color: var(--pg-falha); color: var(--neutral-0) }
/* O estado visível é preso ao `#toast`, e não a um `.show` solto como na folha
   de origem: aqui `.show` seria uma classe genérica com `!important` numa folha
   que veste o console inteiro. E o `transform` é reafirmado no eixo horizontal
   — `left: 50%` sem o `translateX(-50%)` joga a faixa meia tela para a direita;
   só o deslocamento vertical de entrada é zerado. */
#toast.show { opacity: 1 !important; transform: translateX(-50%) !important }
/* [31/08] `[hidden]` VOLTA A FUNCIONAR, e vale para o documento inteiro.

   `.btn { display: inline-flex }` e `.btn-circ { display: grid }` têm a mesma
   especificidade que o `[hidden] { display: none }` da folha do navegador — e
   vêm depois, então venciam. Medido: o `#totp-alert` do cabeçalho aparecia em
   TODA tela com o atributo `hidden` posto, e o "Carregar mais" da trilha
   também. Um botão que o código mandou esconder e que aparece afirma um
   estado que não existe.

   `.screen[hidden]` era o remendo do mesmo defeito, um caso de cada vez; foi
   substituído por esta linha. `!important` é deliberado: `hidden` é semântica
   garantida pelo navegador, e qualquer `display` que a vença por acidente é
   defeito, não escolha — é o que todo reset moderno faz. */
[hidden] { display: none !important; }
/* ===== Responsividade (§10) ===== */
/* A TERCEIRA COLUNA SO ENTRA QUANDO ELA CABE. O limiar era 1320px e estava
   errado por 360: as laterais somam 688px fixos (336 + 320 + 32 de vao), entao
   a 1340 a conversa ficava com 321px. MEDIDO: a 1320 a thread tinha 653px em
   duas colunas; vinte pixels a mais de janela derrubavam para 321, e ela so
   voltava aos 653 perto de 1680. Havia uma faixa de 360px em que ALARGAR A
   JANELA ESTREITAVA A CONVERSA — e e a faixa em que o JP trabalha, que foi o
   que ele fotografou comparando com a tela dos agregados.

   1745 e o ponto em que o que SOBRA depois das duas laterais volta a valer o
   que valia antes de a ficha entrar: 1745 - 267 (barra) - 64 (recuo) - 752
   (laterais e vãos) = 662. Coluna que entra tem de se pagar; abaixo disso a ficha
   desce para baixo, que e o que este mesmo bloco ja fazia.

   [05/09] O NUMERO ESTAVA CERTO E A REALOCACAO NAO EXISTIA. O bloco mandava
   para baixo a `.ficha-card`, classe que nenhum template escreve; em Conversas
   quem ocupava a terceira coluna era o cartao Contato, e para ele nao havia
   regra nenhuma — a grade perdia uma coluna e o `<article>` orfao caia para a
   SEGUNDA LINHA DA PRIMEIRA COLUNA, debaixo da fila e fora da dobra (medido a
   1280x900: o Contato em (96,841)). Coluna que sai muda de lugar de proposito.
   Remedir antes de baixar o limiar: a 1280 as tres colunas dao 272px de
   conversa, pior do que os 629px que as duas colunas dao na mesma janela. */
@media (max-width: 1745px) {
/* O CONTATO DESCE PARA BAIXO DA CONVERSA — e a conversa que ele contextualiza,
   e nao a fila. A fila continua inteira na coluna da esquerda (duas linhas). */
.conv-layout { grid-template-columns: minmax(340px, 380px) minmax(0, 1fr); grid-template-rows: minmax(0, 1fr) auto; }
.conv-list-card { grid-row: 1 / 3; grid-column: 1; }
.chat-card { grid-row: 1; grid-column: 2; }
.conv-contato-card { grid-row: 2; grid-column: 2; max-height: 34vh; }
.ficha-card { grid-column: 1 / -1; }
.ficha { max-height: none; }
}
@media (max-width: 1180px) {
.app-shell, .app-shell.collapsed, html.sidebar-collapsed .app-shell { grid-template-columns: 64px minmax(0, 1fr); }
.app-shell .side-brand { grid-template-columns: 1fr; justify-items: center; padding: 16px 8px; }
.app-shell .brand-copy, .app-shell .nav-label, .app-shell .nav-group, .app-shell .nav-tag { display: none; }
.app-shell .side-nav a, .app-shell .side-nav .nav, .app-shell .nav-disabled, .app-shell .side-status,
  .app-shell .side-user, .app-shell .side-logout { justify-content: center; padding: 10px; }
main { padding: 28px 32px 56px; }
.bloco-cards, .cfg-grid { grid-template-columns: 1fr; }
}
@media (max-width: 860px) {
.app-shell, .app-shell.collapsed, html.sidebar-collapsed .app-shell { display: block; }
.sidebar {
    position: fixed; left: 0; top: 0; width: 64px; height: 100vh;
    transform: translateX(-64px); transition: transform var(--t); box-shadow: var(--shadow-float);
  }
body.menu-aberto .app-shell .sidebar { transform: translateX(0); }
body.menu-aberto .app-shell .workspace { margin-left: 64px; }
.mobile-topbar { display: flex; }
main { padding: 20px 20px 48px; }
h1.page { font-size: 26px; }

  /* Alvos de toque de 44px no mobile (§10) */.btn { min-height: 44px; width: 100%; }
.row .btn, .demo-linha .btn, .modal .btn, .chat-foot .btn { width: auto; }
/* [04/09] A EXCEÇÃO DO `.mini` NÃO VALE DENTRO DE DIÁLOGO. `.btn.mini`
   (0,2,0) vence a linha acima (0,1,0) mesmo aqui dentro, e o "Remover
   participante" do `#record-dialog` media 28px de altura a 390px — no
   formulário que libera o microfone, com o dedo, em pé no cliente. Não é
   classe nova nem corte novo: é a regra de toque do §10 alcançando o único
   `.mini` que nasce dentro de um `dialog`. Fora dele o `.mini` segue em 28px,
   que é onde ele é adorno de linha de lista e o alvo é o cartão inteiro. */
dialog .btn.mini { min-height: 44px; }
/* [13/09] A MESMA ARMADILHA na ação da linha de triagem. O `.neg-pend` NÃO é
   clicável: o botão é o único alvo da linha, e é a ação principal dela — ligar
   a empresa, abrir o negócio. Medido a 390x844 com o `.mini`: 152x28px. A
   coluna da ação (152px, `justify-self: stretch`) não muda; só o piso sobe. */
.btn.neg-acao { min-height: 44px; }
/* A linha de usuário tem DOIS ou três botões curtos. Esticados e empilhados
   viram ~130px de altura por pessoa numa lista de gente — medido a 390px. E
   sem o `margin-left: auto` eles voltam a alinhar com o nome quando a linha
   quebra, em vez de flutuarem à direita sozinhos. */
.usuario-acoes .btn { width: auto; }
.usuario-acoes { margin-left: 0; }
.grid2, .aprovacoes { grid-template-columns: 1fr; }
/* LISTA VIRA TELA. No telefone os três cartões apenas empilhavam: medido a
   390x844, a conversa começava em y=702 (fora da tela) e o documento tinha
   1536px. Aqui a vista tem DOIS estados, como todo aplicativo de mensagem:
   a fila ocupa a tela, e abrir uma conversa troca a tela pela conversa, com
   a volta no cabeçalho dela. O cartão Contato acompanha a conversa — ele é o
   contexto dela, e sozinho no fim de uma rolagem não é contexto de nada. */
/* O RESERVADO ACIMA DA GRADE DOBRA AQUI. Nas larguras largas a vista começa em
   y=146; no telefone o cabeçalho e o título empurram o começo para y=190, e a
   mesma reserva jogava 78px para fora da janela — medido a 390x844: documento
   de 922 numa janela de 844. 238 é esse topo mais o recuo de baixo. */
#conversas.view.active { height: calc(100dvh - 238px); }
.conv-layout { display: flex; flex-direction: column; }
.conv-list-card, .chat-card, .conv-contato-card { grid-row: auto; grid-column: auto; }
.conv-list-card { flex: 1; }
#conv-fila .chat-card, #conv-fila .conv-contato-card { display: none; }
#conv-fila.na-conversa .conv-list-card { display: none; }
#conv-fila.na-conversa .chat-card { display: flex; flex: 1; min-height: 0; }
#conv-fila.na-conversa .conv-contato-card { display: block; flex: none; max-height: 30vh; margin-top: 16px; }
/* `width: auto` porque a regra de alvo de toque acima põe `width: 100%` em todo
   `.btn` do mobile, e um "Voltar" de borda a borda empurraria o nome da
   conversa para uma segunda linha do cabeçalho. */
/* E o piso de toque vem em `.btn.conv-voltar` (0,2,0): `.btn.mini` (0,2,0) fixa
   28px e venceria um `.conv-voltar` sozinho (0,1,0) — a mesma armadilha já
   documentada acima para `dialog .btn.mini` —, e este "Voltar" é o controle de
   navegação da tela, não adorno de linha de lista. */
.conv-voltar { display: inline-flex; width: auto; }
.btn.conv-voltar { min-height: 44px; }
.msg { max-width: 88%; }
/* [28/08] O respiro lateral era ZERO aqui, e o cartão colava nas duas bordas
   — com raio e sombra, que só existem se houver fundo em volta para eles
   caírem. Isso entra na mesma queixa do JP sobre o login: zoom AUMENTA
   encolhe a janela em pixels CSS, então um desktop de 1280 cruza este
   recorte e o cartão salta para borda a borda de um nível de zoom para o
   outro. Medido a 390px antes: cartão em x=0 com 390px de largura. */
.palco { padding: 24px 16px; }
.acc-painel p { padding-right: 8px; }
}
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after { transition-duration: .01ms !important; animation-duration: .01ms !important; }
.linha-anim { stroke-dasharray: none !important; stroke-dashoffset: 0 !important; }
}
/* ============================================================
   v4 — shell do kit Venture e componentes das telas novas
   ============================================================ */

/* ===== Topbar (novo no v4) ===== */
.topbar {
  position: sticky; top: 0; z-index: 15;
  display: flex; align-items: center; gap: 16px;
  height: 64px; padding: 0 24px;
  background: var(--surface-0); border-bottom: 1px solid var(--neutral-50);
}
.topbar .busca { flex: 1; max-width: 460px; }
.topbar .ajuda {
  display: inline-flex; align-items: center; gap: 7px;
  background: none; border: 0; color: var(--neutral-75);
  font-size: 13.5px; transition: color var(--t);
}
.topbar .ajuda:hover { color: var(--neutral-100); }
.topbar .ajuda svg { width: 16px; height: 16px; }
.conta {
  display: inline-flex; align-items: center; gap: 9px;
  background: none; border: 0; padding: 4px 8px 4px 4px; border-radius: var(--r-pill);
  color: var(--neutral-100); font-size: 13.5px; font-weight: 500;
  transition: background var(--t);
}
.conta:hover { background: var(--neutral-30); }
.conta .chev { width: 14px; height: 14px; color: var(--neutral-75); }
/* Rodapé da sidebar: seletor de equipe */
.side-team {
  display: flex; align-items: center; gap: 10px; width: 100%;
  min-height: 44px; padding: 8px 10px; border-radius: var(--r-input);
  border: 1px solid var(--neutral-50); background: var(--surface-0);
  color: var(--neutral-100); font-size: 13px; font-weight: 500;
  transition: background var(--t), border-color var(--t);
}
.side-team:hover { background: var(--neutral-30); border-color: var(--neutral-90); }
.side-team .sq {
  width: 22px; height: 22px; flex: none; border-radius: var(--r-badge);
  background: var(--neutral-100); color: var(--neutral-0);
  display: grid; place-items: center; font-size: 11px; font-weight: 600;
}
.side-team .chev { width: 14px; height: 14px; margin-left: auto; color: var(--neutral-75); }
/* [P6] CO-BRAND DA EMPRESA NO RODAPÉ — uma classe nova, interior por seletor
   de elemento (é marcação fixa do template, não um componente reusável).

   O monograma repete o PAR EXATO do `.avatar` (fundo `--neutral-30`, tinta
   `--neutral-90`, 11px/600): o acento NÃO se repete aqui, ele já tem um lugar
   na tela — o ponto ao lado da marca, no topo da barra.

   O limite visual do logo é BORDA, não outra superfície: borda OU contraste de
   fundo, nunca os dois. E é a borda que salva um PNG transparente de marca
   branca, que sobre `--surface-50` ficaria invisível. `object-fit: contain`
   porque logo de cliente é retangular com mais frequência que quadrado.

   Pesos e tamanhos: 500 e 12px/11px da escala — `700` não existe nesta casa e
   `<b>` sem `font-weight` herda 700 do navegador. */
.side-empresa {
  display: flex; align-items: center; gap: 10px; width: 100%; min-width: 0;
  min-height: 60px; padding: 8px 10px;
}
.side-empresa img, .side-empresa i {
  width: 44px; height: 44px; flex: none; border-radius: var(--r-badge);
}
.side-empresa img {
  object-fit: contain; box-sizing: border-box;
  padding: 1px; border: 1px solid var(--neutral-50);
}
.side-empresa i {
  background: var(--neutral-30); color: var(--neutral-90);
  display: grid; place-items: center;
  font-size: 19px; font-weight: 600; font-style: normal; letter-spacing: .01em;
}
.side-empresa span { display: flex; flex-direction: column; min-width: 0; }
.side-empresa b {
  font-size: 14px; font-weight: 500; color: var(--neutral-100);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.side-empresa small { font-size: 11px; color: var(--neutral-75); }
/* ===== Cabeçalho de tela com abas ===== */
.tela-head { display: flex; align-items: flex-end; gap: 20px; flex-wrap: wrap; margin-bottom: 24px; border-bottom: 1px solid var(--neutral-50); }
.tela-head h1 { font-size: 24px; padding-bottom: 12px; }
.tela-head .acoes { margin-left: auto; display: flex; gap: 10px; align-items: center; padding-bottom: 12px; }
/* O recorte do Painel reaproveita a toolbar, mas no cabeçalho ela divide a
   linha do título: a margem de uma barra entre seções deixava os controles
   16px acima da linha que eles deveriam ancorar. */
.tela-head .toolbar { margin: 0 0 12px auto; }
/* ===== Cards de métrica (Painel) ===== */
.stat-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 16px; margin-bottom: 16px; }
.stat {
  display: flex; align-items: center; gap: 14px;
  background: var(--surface-0); border: 1px solid var(--neutral-50);
  border-radius: var(--r-card); padding: 18px 20px;
  transition: background var(--t), border-color var(--t);
}
.stat .variacao { margin-top: 3px; font-size: 12px; color: var(--neutral-80); font-variant-numeric: tabular-nums; }
.stat .variacao.positiva { color: var(--green-ink); }
.stat .variacao.negativa { color: var(--red-ink); }
.stat:hover { border-color: var(--neutral-90); }
/* [03/09] O cartão do topo virou <button> porque contagem sem caminho é número
   que só serve para ser lido. [10/09] No placar do Painel ele deixou de ser
   botão e virou gaveta (`<details>`, `#stats .stat > summary` adiante): quem
   navega agora é o "Ver em visitas" do rodapé da lista, e as telas que usam
   `.stat` sem destino — Negócios, o Cérebro, a prontidão — sempre foram `<div>`.
   Nenhum `<button class="stat">` é emitido desde então; as três regras que
   vestiam o reset de botão saíram com ele. */
.stat .sub { font-size: 12px; line-height: 1.45; color: var(--neutral-80); margin-top: 3px; }
.stat .ico { width: 20px; height: 20px; flex: none; color: var(--neutral-75); }
.stat .t { font-size: 12px; color: var(--neutral-80); }
.stat .v { font-size: 22px; font-weight: 500; color: var(--neutral-100); letter-spacing: -.02em; margin-top: 2px; }
.stat .chev { width: 16px; height: 16px; margin-left: auto; color: var(--neutral-80); flex: none; }
/* ═══ O PAINEL ═════════════════════════════════════════════════════════════
   Tres regioes, na ordem em que se le: AGORA (compromissos e tarefas),
   ACONTECEU (ultimas visitas) e COMO ESTAMOS (numeros, grafico, carteira,
   perdas). Elas dividem a MESMA caixa de conteudo — a do `main` —, entao as
   bordas esquerda e direita de todas coincidem: era o "alinhamentos nao batem"
   do pedido de 04/09. O que muda de uma para outra e a contagem de colunas
   DENTRO da regiao.

   A consulta e do CONTAINER, nunca da janela (regra 3 da politica): a mesma
   janela da blocos de largura diferente com a barra lateral aberta e com ela
   recolhida, e so o bloco sabe qual dos dois esta na tela. O container e o PAI
   da grade, e nao a grade: um `@container` nunca estiliza o elemento que ele
   mesmo mede — medido em 03/09, com a consulta na propria grade, ela ficava em
   UMA coluna em qualquer largura. */
#home { container-type: inline-size; container-name: painel }

/* ── 0. O PLACAR (painel v3, fatia 1) ─────────────────────────────────────
   Quatro contagens comerciais. Tudo aqui e ESCOPADO no `#stats`: `.stat` e
   `.stat-grid` sao regras COMPARTILHADAS — vestem Negocios (`#negocios-resumo`),
   o acervo do Cerebro, a prontidao e a fila —, e mexer nelas para arrumar o
   Painel arrumaria uma tela e mudaria cinco. O id vence a classe em qualquer
   largura, entao as `@media` de `.stat-grid` que as outras telas usam nao
   alcancam mais este bloco: quem responde a largura aqui e o container.
   2 colunas a 390 (quatro numeros na dobra; eram dois), 4 quando o bloco tem
   espaco para os quatro sem cortar palavra. */
/* [07/09, F4b §4.3 (3)] NÃO HÁ GRAVAÇÃO PELO DESKTOP DO VENDEDOR, e por isso
   o botão e a instrução são o MESMO controle em duas larguras: no telefone a
   porta para o app, no computador a frase que diz onde ela fica. Os dois são
   emitidos juntos por `botaoGravarNoApp` e a folha escolhe qual aparece — a
   alternativa (decidir no JS) precisaria de um ouvinte de redimensionamento
   para uma regra que a folha resolve sozinha.

   `min-width`, e por isso FORA do índice de cortes do topo: o índice cadastra
   os `@media (max-width: …)`, que são os que reflowam a tela ao encolher.
   O `display: none` do botão é (0,2,0) e vence o `display: inline-flex` que
   `.btn` declara — a mesma armadilha que o `[hidden]` da meta já pagou. */
.gravar-no-app-nota { display: none; color: var(--neutral-75); font-size: 12.5px; }
/* No Painel COM visitas a porta tem linha própria, acima da lista: medido a
   390, o título do cartão, o botão e o "Ver todas" pedem 349px numa faixa de
   301, e os três quebram no meio da frase. `:not(:empty)` porque o slot nasce
   vazio e fica vazio para quem não grava — margem de um elemento sem conteúdo
   é um respiro que ninguém pediu. */
#painel-gravar-no-app-topo:not(:empty) { display: block; margin: 0 0 12px; }
@media (min-width: 1024px) {
  .gravar-no-app { display: none; }
  .gravar-no-app-nota { display: inline; }
}

#stats { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px }
@container painel (min-width: 720px) { #stats { gap: 16px } }
@container painel (min-width: 900px) { #stats { grid-template-columns: repeat(4, minmax(0, 1fr)) } }
/* `block` porque o tile do placar nao tem mais o quadrado de 20px na esquerda:
   o icone foi para dentro da linha do rotulo, e a linha do meio ganhou os 28px
   que o numero de um placar pede. O respiro cai de 18/20 para 14/16. Medido a
   1280: 123px de altura para os QUATRO tiles — 105 quando a legenda cabe numa
   linha, e a segunda linha aparece quando os nomes de duas empresas nao cabem
   nos 225px da coluna. Nome de cliente nao se corta para o bloco fechar. */
#stats .stat { display: block; padding: 14px 16px }
#stats .stat .v { font-size: 28px; line-height: 1.15; margin-top: 4px }
#stats .stat .sub { margin-top: 4px }
/* `flex-start` + 1px: numa caixa de linha de 18px o icone de 16 fica centrado
   quando o rotulo tem uma linha e alinhado a PRIMEIRA linha quando ele quebra
   em duas (a 390, "Objecoes sem resposta"). O traco (1.7) e a caixa de 24 sao
   os mesmos dos icones da barra; a cor e neutra de proposito — no Painel cor
   carrega estado, e um icone decorativo nao tem estado para carregar. */
#stats .stat .t { display: flex; align-items: flex-start; gap: 6px }
#stats .stat .t svg {
  width: 16px; height: 16px; flex: none; margin-top: 1px; color: var(--neutral-75);
  fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round;
}

/* ── A ESCALA v4, NO PAINEL ───────────────────────────────────────────────
   A v4 tem sete tamanhos (32 · 28 · 26 · 20 · 14 · 12,5 · 12 · 11) e a tela
   inicial usava CATORZE a 1280 e treze a 390: `.tela-head h1` em 24 e
   `.card-head h2` em 18 sao degraus que a escala nao tem, e cada um deles
   arrasta os vizinhos para tamanhos intermediarios. Sem hierarquia declarada
   o olho nao sabe o que ler primeiro, e o Painel e a primeira coisa que se ve.

   Escopado em `#home` de proposito: a troca global desses dois valores toca
   nove telas e vai numa fatia propria, declarada como tal. Aqui a mudanca
   responde por UMA tela e pode ser medida nela.

   O degrau de 26px e do CONTAINER, nao da janela (regra 3): a mesma janela da
   larguras diferentes com a barra aberta e recolhida, e nenhum @media novo
   entra na folha (o indice de cortes no topo continua valendo). */
#home .tela-head h1 { font-size: 32px; }
#home .card-head h2 { font-size: 20px; }
@container painel (max-width: 719px) {
  #home .tela-head h1 { font-size: 26px; padding-bottom: 10px; }
}

/* ── A LINHA DA DOBRA ────────────────────────────────────────────
   [painel v3, fatia 2] A LEITURA e a COBRANCA, lado a lado. Eram duas grades
   empilhadas — `.painel-agora` com a lista e `.painel-grid` com os tres
   cartoes de apoio (grafico, carteira, Pareto) — e as duas sairam: o apoio
   virou tres frases no rodape (`.apoio`), e o que sobra na dobra sao as duas
   unicas coisas que respondem "como estamos negociando" e "o que faco hoje".

   Na proposta A, `stretch` alinha os dois cartões no mesmo eixo inferior. Os
   corpos continuam fluidos e o teto da agenda impede crescimento sem limite. */
.painel-topo { display: grid; grid-template-columns: minmax(0, 1fr); gap: 16px; margin-bottom: 40px; align-items: stretch }

/* CARTAO DE LISTA: o que nao coube e DITO, e o cartao nao cresce.
   O buraco de ~400px que as pilhas de 04/09 consertavam nascia de um cartao
   curto dividindo linha com o mais alto da tela. A causa era a lista sem teto,
   nao a grade: com a lista limitada a cinco itens mais o rodape do "+N", a
   altura maxima do cartao e conhecida e a linha estica os vizinhos ate ela.
   `min-height` no corpo (e nao `height`) porque a lista vazia, o esqueleto e o
   vazio honesto tem de ocupar o mesmo lugar que a lista cheia — senao a tela
   pula de altura entre a leitura e o resultado.

   `container-type` AQUI porque a linha de agenda responde a largura do CARTAO,
   nao a da tela: o mesmo cartao mede 352px em duas colunas a 1280 e 546px a
   1440, e o selo de prazo so cabe ao lado do titulo no segundo caso. */
.cartao-lista { display: flex; flex-direction: column; container-type: inline-size; container-name: cartao }
.cartao-lista > .card-pad { flex: 1; min-height: 240px }

/* ── 2. O HEROI: COMO A EQUIPE ESTA NEGOCIANDO (painel v3, fatia 2) ───────
   Tudo aqui e escopado em `#home`: sao formas do Painel, e `.equipe`,
   `.temas` e `.vend` sao nomes curtos demais para viverem soltos na folha.
   Nenhum token novo, nenhuma cor nova.

   `card-head` SEM filete: titulo e frase-resposta sao um bloco de leitura so.
   O rodape do cartao e 14px e nao 22 porque a ultima linha do grafico e a
   tabela ja dao respiro — foi o que fez o heroi caber na dobra de 800 com o
   grafico dentro. */
#home #card-leitura .card-head { border-bottom: 0; padding-bottom: 6px }
#home #card-leitura .card-pad { padding-top: 0; padding-bottom: 14px }
#home .leitura-resposta { padding: 0 22px 14px; font-size: 14px; line-height: 1.5; color: var(--neutral-100); max-width: 64ch }

/* POR TEMA. Barra de proporcao: horizontal, ordenada, base no zero, SEM raio,
   sem grade, sem eixo, sem porcentagem. Os dois segmentos sao `flex-grow`
   puros sobre a mesma soma, entao a escala e exatamente comum e uma linha 5-0
   desenha barra inteira, sem 2px de vazio no meio.
   FORMA ANTES DE COR, e quem a garante e o cabecalho: as colunas dizem
   "Pontos fortes" e "A desenvolver" em palavras, uma vez, entao nao ha legenda
   de cor a 1280 e a linha se le com a barra apagada.
   As colunas de numero tomam a largura do CONTEUDO (`width: 1%`), nunca um
   valor fixo: com 70 visitas o numero vira tres digitos e nada e tocado. */
#home .por-tema { border-top: 1px solid var(--neutral-40); padding-top: 12px; margin-bottom: 10px }
#home .temas { width: 100%; border-collapse: collapse }
#home .temas th, #home .temas td { text-align: left; vertical-align: middle; padding: 3px 0; border: 0 }
#home .temas thead th { font-size: 12px; font-weight: 500; color: var(--neutral-75); padding: 0 0 7px }
#home .temas .h-forte, #home .temas .c-forte { text-align: right; padding-right: 10px }
#home .temas .h-desen, #home .temas .c-desen { text-align: left; padding-left: 10px }
#home .temas .h-forte, #home .temas .h-desen,
#home .temas .c-forte, #home .temas .c-desen { width: 1%; white-space: nowrap }
#home .temas tbody th { font-size: 12.5px; font-weight: 400; color: var(--neutral-90); line-height: 1.35; padding-right: 12px; width: 1%; white-space: nowrap }
/* O numero e neutro de proposito: quem carrega o estado e a barra. */
#home .temas .c-forte, #home .temas .c-desen { font-size: 12.5px; color: var(--neutral-100) }
#home .temas .zero { color: var(--neutral-80) }
#home .tema-barra { display: flex; height: 8px }
/* `flex-grow` vem no `style` de cada segmento porque e DADO, nao token: e a
   contagem daquela linha. Base e encolhimento ficam aqui, e sao eles que
   fazem os dois segmentos dividirem a largura em proporcao exata. */
#home .tema-barra i { display: block; flex-basis: 0; flex-shrink: 0; flex-grow: 0; min-width: 0 }
/* Verde e vermelho aqui sao ganho e perda DE FATO, e e a unica excecao a regra
   do juri (cor = estado de tempo ou de sistema). Ela vale so dentro deste
   bloco, e os tons sao os mesmos dos selos. */
#home .tema-barra .f { background: var(--green-ink) }
#home .tema-barra .d { background: var(--red-ink) }
#home .temas-legenda { display: none; margin: 0 0 8px; font-size: 12px; line-height: 1.45; color: var(--neutral-80) }
#home .temas-legenda .f { color: var(--green-ink); font-weight: 500 }
#home .temas-legenda .d { color: var(--red-ink); font-weight: 500 }

/* A TABELA DO HEROI. Hierarquia: cabecalho de coluna 12/500 no tom do `thead`,
   vendedor 14/500, celula 14/400. Sem marca, sem fracao, sem barra: o
   denominador esta escrito UMA vez por linha ("3 analisadas"). */
#home .equipe { width: 100%; border-collapse: collapse }
#home .equipe th, #home .equipe td { text-align: left; vertical-align: top; padding: 12px 14px 12px 0; border-top: 1px solid var(--neutral-40) }
#home .equipe thead th { font-size: 12px; font-weight: 500; color: var(--neutral-75); padding: 0 14px 8px 0; border-top: 0 }
#home .equipe tbody th { width: 104px }
#home .equipe td { font-size: 14px; color: var(--neutral-90); line-height: 1.5 }
#home .equipe td:last-child, #home .equipe thead th:last-child { padding-right: 0 }
#home .equipe q { quotes: "\201C" "\201D"; color: var(--neutral-100) }
#home .vend { background: none; border: 0; padding: 0; text-align: left; font: inherit; font-size: 14px; font-weight: 500; color: var(--neutral-100); cursor: pointer }
#home .vend span { display: block; font-size: 12px; font-weight: 400; color: var(--neutral-80); margin-top: 2px }
#home .vend:hover { text-decoration: underline; text-underline-offset: 3px; text-decoration-color: var(--neutral-50) }
/* O rotulo por celula so aparece a 390, onde a linha vira bloco e o `thead`
   sai. A 1280 ele seria a mesma palavra duas vezes na mesma linha. */
#home .cel-rotulo { display: none }
#home .equipe-mais { margin: 10px 0 0; font-size: 12px; color: var(--neutral-80) }

/* O DEGRAU DO HEROI: consulta do BLOCO, nao da janela. Abaixo de 720px de
   contêiner o cabecalho da tabela nao cabe ao lado da barra — ele sai, e a
   legenda de cor entra UMA vez, no lugar dele. */
@container painel (max-width: 719px) {
  #home .leitura-resposta { padding: 0 18px 12px }
  #home .temas-legenda { display: block }
  #home .temas thead { display: none }
  #home .por-tema { padding-top: 10px; margin-bottom: 8px }
  #home .temas tbody th, #home .temas tbody td { padding: 2px 0; line-height: 1.25 }
  #home .temas tbody th { font-size: 12px; padding-right: 8px }
  #home .temas .c-forte, #home .temas .c-desen { font-size: 12px }
  #home .temas .c-forte { padding-right: 8px }
  #home .temas .c-desen { padding-left: 8px }
  #home .equipe thead { display: none }
  #home .equipe tbody tr { display: grid; grid-template-columns: minmax(0, 1fr); gap: 8px; padding: 12px 0; border-top: 1px solid var(--neutral-40) }
  #home .equipe tbody th, #home .equipe td { display: block; width: auto; padding: 0; border: 0 }
  #home .cel-rotulo { display: block; font-size: 12px; color: var(--neutral-75) }
}

/* [painel v3, fatia 2] DINHEIRO, DE APOIO — o rodape em prosa que substituiu
   os tres cartoes. Frase, e nao cartao: contexto que se le no fim nao merece
   moldura, e tres molduras na dobra eram o que fazia a tela terminar em
   barrinha em vez de terminar em leitura. */
#home .apoio {
  margin: 24px 0 0; padding-top: 14px; border-top: 1px solid var(--neutral-50);
  font-size: 12.5px; line-height: 1.7; color: var(--neutral-80);
}
#home .apoio > span { margin-right: 6px }
#home .apoio > span[hidden] { display: none }
#home .apoio .link-acao { margin: 0 12px 0 6px }
/* O vazio honesto aqui e FRASE, nao caixa: dentro de um paragrafo de rodape a
   moldura tracejada de `.honest-empty` viraria um retangulo de 40px de respiro
   no meio da linha. O sinal de "nao consegui ler" continua inteiro — ele so
   passa a ser dito pelas palavras, que e o que uma linha de texto tem. */
#home .apoio .honest-empty {
  display: inline; padding: 0; border: 0; text-align: left;
  font-size: 12.5px; line-height: 1.7; color: var(--neutral-80);
}

/* ── PAINEL · PROPOSTA A (09/09) ─────────────────────────────────────────
   A direção aprovada pelo JP mantém a casca clara do Portal e reorganiza a
   informação da referência do Diego: síntese, cinco indicadores, perdas e
   cobranças alinhadas, vendedores e visitas recentes. A cor só classifica;
   nenhum cartão ganha sombra ou fundo colorido. */
#home .painel-barra {
  display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 16px;
  align-items: center; margin: 0 0 14px;
}
#home .painel-filtros { grid-column: 2; grid-row: 1; display: flex; justify-content: flex-end; margin: 0; }
#home .painel-filtros .toolbar { margin: 0; }

#home .painel-insight {
  grid-column: 1; grid-row: 1; display: flex; min-width: 0; min-height: 40px;
  align-items: center; gap: 8px; margin: 0; padding: 7px 10px;
  background: var(--surface-0); border: 1px solid var(--neutral-50); border-radius: var(--r-card);
}
#home .painel-insight-icone {
  display: grid; place-items: center; width: 24px; height: 24px; flex: none;
  color: var(--blue-ink); background: var(--blue-tint); border-radius: var(--r-panel);
}
#home .painel-insight-icone svg {
  width: 15px; height: 15px; fill: none; stroke: currentColor; stroke-width: 1.7;
  stroke-linecap: round; stroke-linejoin: round;
}
#home .painel-insight-copy { flex: 1; min-width: 0; }
#home .painel-insight h2 { overflow: hidden; margin: 0; color: var(--neutral-100); font-size: 14px; font-weight: 500; line-height: 1.35; text-overflow: ellipsis; white-space: nowrap; }
#home .painel-insight p { display: none; }
#home .painel-insight-acao {
  display: inline-flex; align-items: center; justify-content: center; flex: none;
  min-height: 30px; padding: 5px 10px; border: 1px solid var(--neutral-50);
  border-radius: var(--r-input); background: var(--surface-0); color: var(--neutral-100);
  font: inherit; font-size: 12px; font-weight: 500; cursor: pointer;
  transition: background var(--t), border-color var(--t);
}
#home .painel-insight-acao:hover { background: var(--neutral-30); border-color: var(--neutral-90); }
#home .painel-insight-acao:focus-visible { outline: 2px solid var(--neutral-100); outline-offset: 2px; }
@container painel (max-width: 899px) {
  #home .painel-barra { grid-template-columns: minmax(0, 1fr); gap: 8px; }
  #home .painel-filtros { grid-column: 1; grid-row: 2; }
  #home .painel-insight { grid-column: 1; grid-row: 1; }
}

/* Cinco cartões na largura que os comporta; antes disso a forma muda para
   três e depois duas colunas, sem encolher texto. */
#stats { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; margin-bottom: 22px; align-items: start; }
@container painel (min-width: 640px) { #stats { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@container painel (min-width: 900px) { #stats { grid-template-columns: repeat(5, minmax(0, 1fr)); } }
/* `start` e não `center` (10/09, pedido do JP vendo a tela): com `center` e
   `min-height: 78px`, o tile cuja legenda estava vazia ("Com intenção de
   compra", quando os nomes não cabiam) centralizava o bloco número+rótulo e
   descia uns 15px em relação aos vizinhos — quatro tiles alinhados no topo e um
   flutuando no meio. Alinhar pelo começo faz a cabeça de todos eles começar na
   mesma linha, com legenda ou sem. O `align-items: start` da própria grade é o
   par disso: com um tile aberto, os quatro fechados não esticam até a altura
   dele. A barra de cor é um item da grade do tile, então ela começa no topo
   junto com o número — é o que alinha o filete com o bloco que ele marca. */
#stats .stat {
  display: grid; grid-template-columns: 7px minmax(0, 1fr); align-items: start; gap: 11px;
  min-height: 78px; padding: 12px; border-radius: var(--r-panel);
}
#stats .stat::before {
  content: ""; width: 7px; height: 34px; border-radius: 3px; background: var(--neutral-100);
}
#stats .stat[data-placar="semPasso"]::before { background: var(--red-ink); }
#stats .stat[data-placar="objecoes"]::before { background: var(--amber-ink); }
#stats .stat[data-placar="intencao"]::before { background: var(--green-ink); }
#stats .stat[data-placar="revisar"]::before { background: var(--blue-ink); }
/* O miolo (rótulo, número, legenda) é coluna nos DOIS invólucros: no
   `<div class="stat">` sem gaveta ele é filho direto; no `<details>` (10/09)
   ele mora dentro do `<summary>`, e a regra antiga `> div` não o alcançava —
   sem coluna o `order: -1` do número morre e o rótulo sobe para cima dele
   (o verificador mediu 17px de desalinhamento entre os cinco números).
   `.stat-corpo` fica de fora de propósito: a gaveta é bloco. */
#stats div.stat > div, #stats .stat > summary > div { display: flex; flex-direction: column; min-width: 0; }
#stats .stat .t {
  gap: 0; color: var(--neutral-90); font-size: 12.5px; font-weight: 600;
  line-height: 1.35;
}
#stats .stat .t svg { display: none; }
#stats .stat .v { order: -1; margin: 0 0 2px; font-size: 22px; line-height: 1.05; }
#stats .stat .sub { margin-top: 3px; font-size: 11.5px; line-height: 1.35; }

/* ── A GAVETA DO TILE (10/09) ─────────────────────────────────────────────
   O tile que tem lista é um `<details>`, e a grade do tile continua sendo a
   mesma: a barra ocupa a coluna de 7px e o `<summary>` a segunda. O corpo é o
   terceiro item e pede `grid-column: 2` — sem isso ele cai embaixo da barra, na
   coluna de 7px, e a lista sai de lá com uma letra por linha.

   Anatomia emprestada de `#home .painel-recentes`, que já abre e fecha Últimas
   visitas: `<summary>` sem marcador nativo e o mesmo `⌄` girando 180°. Nenhuma
   animação além de `var(--t)`, e nenhum estado em JS — quem guarda o aberto é o
   elemento, e a cada pintura do `#stats` ele nasce recolhido. */
#stats .stat > summary {
  display: flex; align-items: start; gap: 10px; cursor: pointer; list-style: none;
}
#stats .stat > summary::-webkit-details-marker { display: none; }
#stats .stat > summary > div { flex: 1; }
#stats .stat > summary:focus-visible { outline: 2px solid var(--neutral-100); outline-offset: 2px; }
#stats .stat .chev {
  display: flex; align-items: center; justify-content: center; flex: none;
  width: 14px; height: 14px; margin: 0; color: var(--neutral-75);
  font-size: 13px; line-height: 1; transition: transform var(--t);
}
#stats .stat[open] .chev { transform: rotate(180deg); }
#stats .stat-corpo { grid-column: 2; margin-top: 10px; }
/* Chrome 131+, Firefox 138+ e Safari 18.4+ embrulham o conteúdo do `<details>`
   num `::details-content`: é ELE o terceiro item da grade, não o `.stat-corpo`,
   e sem esta regra ele cai na coluna de 7px (medido em 10/09: 7px de largura,
   uma letra por linha). Onde o pseudo não existe, a regra de cima vale. */
#stats .stat::details-content { grid-column: 2; }
#stats .stat-lista { list-style: none; margin: 0; padding: 0; display: grid; gap: 2px; }
/* A linha é um `<button>` de verdade porque ela NAVEGA (abre a página daquela
   visita, pelo `data-abrir-visita` que Últimas visitas já usa). 44px de alvo no
   telefone; acima disso a lista fica compacta, que é o pedido — "bem pequena".
   `break-word` e não `anywhere`: a empresa quebra no espaço e só parte a
   palavra quando ela sozinha não cabe na coluna, que a 390 tem 118px. A
   alternativa é rolagem lateral, e essa não é negociável. */
#stats .stat-linha {
  display: block; width: 100%; min-height: 44px; padding: 5px 6px; margin: 0 -6px;
  border: 0; border-radius: var(--r-input); background: none; color: inherit;
  font: inherit; text-align: left; cursor: pointer;
  transition: background var(--t);
}
#stats .stat-linha:hover { background: var(--neutral-30); }
#stats .stat-linha:focus-visible { outline: 2px solid var(--neutral-100); outline-offset: 1px; }
#stats .stat-linha-nome {
  display: block; color: var(--neutral-100); font-size: 12.5px; font-weight: 500;
  line-height: 1.3; overflow-wrap: break-word;
}
#stats .stat-linha-meta {
  display: block; color: var(--neutral-80); font-size: 11.5px; line-height: 1.35;
  overflow-wrap: break-word;
}
#stats .stat-resto { margin: 4px 0 0; color: var(--neutral-80); font-size: 11.5px; line-height: 1.35; }
#stats .stat-vazio { margin: 0; color: var(--neutral-80); font-size: 11.5px; line-height: 1.35; }
/* `.btn sec`, nunca preto: o único preto desta região continua sendo o
   "Registrar visita" da barra do Painel, e cinco botões pretos na dobra seriam
   cinco chamadas disputando a mesma atenção. */
/* Lateral de 6px e não a do `.btn`: a 390 o corpo da gaveta tem 127px, e com a
   lateral cheia "Ver em visitas" quebrava em duas linhas dentro do botão. */
#stats .stat-fila { width: 100%; margin-top: 8px; padding-left: 6px; padding-right: 6px; justify-content: center; }
@container painel (min-width: 900px) { #stats .stat-fila { min-height: 32px; padding: 5px 10px; font-size: 12px; } }

#home .painel-topo {
  display: grid; grid-template-columns: minmax(0, 1fr); gap: 18px; margin-bottom: 24px;
  align-items: stretch;
}
@container painel (min-width: 900px) {
  #home .painel-topo { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
#home .painel-bloco { display: flex; flex-direction: column; min-width: 0; }
#home .painel-section-head {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  min-height: 28px; margin: 0 0 8px;
}
#home .painel-section-head h2 { margin: 0; font-size: 20px; line-height: 1.3; font-weight: 600; }
#home .painel-section-head .link-acao { font-size: 12px; }

#home .painel-temas-card, #home .painel-cobrar-card { flex: 1; overflow: hidden; }
#home .painel-temas-card #leitura-corpo { display: flex; flex-direction: column; min-height: 100%; }
#home .painel-temas { width: 100%; }
#home .painel-tema {
  display: grid; grid-template-columns: minmax(120px, 42%) minmax(36px, 1fr) auto;
  align-items: center; gap: 12px; min-height: 42px; padding: 10px 14px;
  border-bottom: 1px solid var(--neutral-40); font-size: 14px; font-weight: 500; line-height: 1.35;
}
#home .painel-tema-barra { height: 6px; overflow: hidden; background: var(--neutral-30); border-radius: var(--r-pill); }
#home .painel-tema-barra i { display: block; height: 100%; background: var(--blue-ink); border-radius: inherit; }
#home .painel-tema-fraco .painel-tema-barra i { background: var(--red-ink); }
#home .painel-tema-numero { min-width: 42px; text-align: right; font-size: 12px; font-weight: 500; color: var(--neutral-80); white-space: nowrap; }
#home .painel-caption { margin: auto 0 0; padding: 9px 14px 11px; font-size: 12px; line-height: 1.45; color: var(--neutral-80); }

#home .painel-cobrar-card { display: flex; flex-direction: column; }
#home .painel-cobrar-card > .card-pad { flex: 1; min-height: 0; padding: 0; }
#home .painel-cobrar-card .linha-painel {
  min-height: 72px; margin: 0; padding: 12px 14px; border-radius: 0;
}
#home .painel-cobrar-card .linha-painel:first-child { border-top: 0; }
#home .painel-cobrar-card .empty, #home .painel-cobrar-card .honest-empty { margin: 18px; }
#home .painel-cobrar-card .tl-rodape { margin: 0; padding: 10px 14px; border-top: 1px solid var(--neutral-40); }

#home .painel-vendedores { margin: 0 0 24px; }
#home #vendedores-corpo { overflow: hidden; }
#home #vendedores-corpo > .empty, #home #vendedores-corpo > .honest-empty { margin: 18px; }
#home .painel-vendedor {
  display: flex; align-items: center; gap: 12px; width: 100%; min-height: 72px;
  padding: 12px 16px; border: 0; border-top: 1px solid var(--neutral-40);
  background: var(--surface-0); color: inherit; text-align: left; cursor: pointer;
  transition: background var(--t);
}
#home .painel-vendedor:first-child { border-top: 0; }
#home .painel-vendedor:hover { background: var(--surface-50); }
#home .painel-vendedor:focus-visible { outline: 2px solid var(--neutral-100); outline-offset: -3px; }
#home .painel-vendedor-avatar {
  display: grid; place-items: center; width: 36px; height: 36px; flex: none;
  border-radius: 50%; background: var(--neutral-30); color: var(--neutral-90);
  font-size: 11px; font-weight: 500;
}
#home .painel-vendedor-copy { display: flex; flex: 1; min-width: 0; flex-direction: column; gap: 2px; }
#home .painel-vendedor-copy b { font-size: 14px; line-height: 1.35; font-weight: 500; }
#home .painel-vendedor-copy > span:last-child { font-size: 12px; line-height: 1.4; color: var(--neutral-80); }
#home .painel-vendedor-meta { order: -1; font-size: 11px; line-height: 1.35; color: var(--neutral-80); }
#home .painel-vendedor > svg {
  width: 16px; height: 16px; flex: none; fill: none; stroke: var(--neutral-75);
  stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round;
}
#home .painel-vendedor-outros { color: var(--neutral-75); }

#home .painel-recentes { margin: 0 0 24px; border-top: 1px solid var(--neutral-50); }
#home .painel-recentes summary {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 16px 0; cursor: pointer; font-size: 14px; font-weight: 500; list-style: none;
}
#home .painel-recentes summary::-webkit-details-marker { display: none; }
#home .painel-recentes details[open] summary span { transform: rotate(180deg); }
#home .painel-recentes summary span { transition: transform var(--t); }
#home .painel-recentes-acoes { display: flex; align-items: center; justify-content: flex-end; gap: 12px; margin: -4px 0 10px; }
#home .painel-recentes #recent { border: 1px solid var(--neutral-50); border-radius: var(--r-card); overflow: hidden; }

@container painel (max-width: 639px) {
  #home .painel-barra { grid-template-columns: minmax(0, 1fr); gap: 8px; }
  #home .painel-filtros { grid-column: 1; grid-row: 2; }
  #home .painel-filtros, #home .painel-filtros .toolbar { width: 100%; }
  #home .painel-filtros .filtro-campo { flex: 1; min-width: 0; }
  #home .painel-filtros select { width: 100%; }
  #home .painel-insight { grid-column: 1; grid-row: 1; }
  #home .painel-insight-icone { display: none; }
  #home .painel-insight-acao { margin-left: auto; }
  #home .painel-tema { grid-template-columns: minmax(0, 1fr) auto; gap: 7px 10px; }
  #home .painel-tema-barra { grid-column: 1 / -1; grid-row: 2; }
  #home .painel-tema-numero { grid-column: 2; grid-row: 1; }
  #home .painel-vendedor-avatar { display: none; }
}

/* ── A LINHA DE AGENDA ────────────────────────────────────────────────────
   UMA forma para as duas listas do topo. Compromissos e Tarefas mostravam a
   mesma coisa de dois jeitos — selo azul com texto de prazo cru de um lado,
   bolinha cinza e prazo a direita do outro — e nenhum dos dois dizia estado.
   Agora os dois dizem: o selo e `.badge` (estado do sistema, com ponto), com a
   tinta do degrau — vencida em vermelho, hoje em ambar, o resto neutro.

   A LINHA INTEIRA ABRE. O `::after` do botao de titulo cobre a linha toda, que
   e o alvo de clique; o botao continua sendo UM so elemento focavel, com Enter
   e Espaco nativos, em vez de um `role="button"` com tecla emulada. A acao de
   concluir sobe por cima dele (`z-index`) para nao ser engolida — e por isso
   ela e um botao de verdade, e nao um segundo alvo dentro do primeiro. */
.linha-painel { position: relative; display: grid; grid-template-columns: minmax(0, 1fr) auto auto; gap: 6px 10px; align-items: start; margin: 0 -10px; padding: 11px 10px; border-top: 1px solid var(--neutral-40); border-radius: var(--r-badge) }
.linha-painel:first-child { border-top: 0 }
.linha-painel:hover { background: var(--surface-50) }
.linha-painel:focus-within { outline: 2px solid var(--neutral-100); outline-offset: -2px }
/* O selo pode carregar o prazo em PALAVRAS ("antes do plantio"): ele quebra
   dentro da propria coluna em vez de empurrar o titulo e desalinhar a lista. */
.lp-selo { grid-column: 1 / -1; justify-self: start; max-width: 100%; white-space: normal; text-align: left }
.lp-corpo { grid-column: 1; min-width: 0 }
.lp-quem { grid-column: 2; align-self: center; font-size: 12px; color: var(--neutral-80); white-space: nowrap }
/* [F3] A coluna da acao virou BOLSO: Concluir e os dois chips de adiar moram
   dentro do mesmo `<span class="lp-feito">`. Dois filhos soltos na grade
   cairiam em colunas diferentes e desalinhariam a lista inteira.
   NO ESTREITO ELE DESCE PARA A PROPRIA LINHA, como `.lp-selo` ja fazia: com
   tres alvos disputando a mesma faixa de 390px o titulo ficava com 52px e
   virava "Enviar a propo...", e o nome do responsavel encavalava a meta. */
.lp-feito { grid-column: 1 / -1; justify-self: start; position: relative; z-index: 1; display: flex; flex-wrap: wrap; gap: 4px 14px; margin-top: 4px }
/* O titulo cabe em ate DUAS linhas e a quebra e entre palavras: `line-clamp`
   corta na linha, nunca no meio da palavra. Sem teto, um titulo de tres linhas
   empurraria o quinto item para fora da altura do cartao. */
.lp-abrir { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; text-align: left; background: none; border: 0; padding: 0; font: inherit; font-size: 13.5px; font-weight: 600; color: var(--neutral-100); cursor: pointer; overflow-wrap: normal }
.lp-abrir::after { content: ""; position: absolute; inset: 0; border-radius: inherit }
.linha-painel:hover .lp-abrir { text-decoration: underline }
.lp-meta { display: block; margin-top: 3px; font-size: 12px; color: var(--neutral-80) }
/* `lp-sugestao`, e nao `sugestao`: `.sugestao` ja e o chip de achado de contato
   (linha 2482 desta folha), com `display` proprio — e como ele vem depois, a
   linha de agenda com aquela classe perdia o `display: grid` e duas sugestoes
   iam parar lado a lado, com o nome do responsavel cortado no meio. O defeito
   ja existia em `.tarefa-linha.sugestao`; morre aqui. */
.linha-painel.lp-sugestao .lp-abrir { font-weight: 500 }
/* Cartao largo: o selo sobe para a primeira coluna e os titulos passam a
   alinhar entre si, que e o que "alinhamentos nao batem" pedia. Largura fixa
   de selo de proposito — selo de largura variavel devolve o desalinhamento. */
/* 620px do CARTAO, e nao 420: abaixo disso a coluna do titulo sobrava com
   ~150px e "Responder a comparacao de preco com a concorrente" virava tres
   pontinhos — medido a 1280 e a 1440, onde o cartao mede 466 e 546. Acima,
   150 + titulo + responsavel + 72 deixa ~260px para o titulo, que e onde ele
   cabe em duas linhas. */
@container cartao (min-width: 620px) {
  /* 150px cabe "Vencida há 12 dias" numa linha so; 72px e o PISO da coluna da
     acao, e ela existe MESMO quando nao ha acao (Compromissos nao tem
     "Concluir") para o nome do responsavel cair no mesmo x nos dois cartoes.
     [F3] Piso e nao largura fixa: com Concluir + Amanha + Escolher o bolso
     passa de 72px, e travar a coluna faria os chips vazarem do cartao. */
  .linha-painel { grid-template-columns: 150px minmax(0, 1fr) auto minmax(72px, auto); gap: 4px 12px }
  .lp-selo { grid-column: 1; align-self: center }
  .lp-corpo { grid-column: 2 }
  .lp-quem { grid-column: 3 }
  .lp-feito { grid-column: 4; align-self: center; justify-self: end }
}
/* `.tl-dot` e `.tl-meta` sao da linha de tarefa do RELATORIO DA VISITA
   (`linhaTarefaDaVisita`), nao do Painel: o resto da familia dela mora em
   `relatorio.css`, mas estas duas sempre viveram aqui e a lista do Painel as
   dividia. Com a lista do Painel virando `.linha-painel`, elas ficam — sem
   dono no Painel, com dono no relatorio. */
.tl-dot { width: 8px; height: 8px; border-radius: var(--r-pill); background: var(--neutral-75); align-self: center }
.tarefa-linha.vencida .tl-dot { background: var(--red-ink) }
.tarefa-linha.sugestao .tl-dot { background: transparent; border: 1.5px solid var(--neutral-75) }
.tl-meta { display: block; font-size: 12px; color: var(--neutral-80); margin-top: 2px }
.tl-pill { display: inline-block; margin-left: 6px; padding: 1px 7px; border-radius: var(--r-badge); font-size: 11px; font-weight: 500; color: var(--neutral-80); border: 1px solid var(--neutral-50) }
.tl-rodape { margin: 10px 0 0; font-size: 12px; color: var(--neutral-80) }
/* ===== O que a análise ouviu (item 28, ui2-f3) =====
   A EVIDÊNCIA É REGISTRO, e por isso ela não pode PARECER campo: sem moldura,
   sem fundo de input, sem alvo de clique. Só a citação, recuada por um filete
   — a forma que a tipografia usa há séculos para dizer "isto é fala de
   outro". Nenhum token novo aqui: são os mesmos cinzas da linha de tarefa
   logo acima, porque este bloco é vizinho dela dentro do mesmo painel. */
.ouvido { padding: 10px 0; border-top: 1px solid var(--neutral-40) }
.ouvido:first-of-type { border-top: 0; padding-top: 0 }
.ouvido-selos { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 5px }
.ouvido b { display: block; font-size: 13.5px; font-weight: 600; color: var(--neutral-100) }
/* Titulo de duas linhas nao pode sair centralizado: `button` centraliza o
   proprio texto por padrao do navegador, e o titulo aqui e um botao (e ele que
   abre a tarefa). Medido em 390 antes de existir esta linha. */
.ouvido b .tl-tit { text-align: left }
.ouvido-fala {
  margin: 4px 0 0; padding-left: 10px; border-left: 2px solid var(--neutral-50);
  font-size: 12.5px; color: var(--neutral-80);
}
.ouvido-tempo { font-variant-numeric: tabular-nums; color: var(--neutral-75) }
/* ===== Agenda (lista de compromissos) ===== */
.agenda { display: flex; flex-direction: column; }
.ag-item { padding: 14px 0; border-top: 1px solid var(--neutral-40); }
.ag-item:first-child { border-top: 0; padding-top: 0; }
.ag-hora {
  display: inline-block; margin-bottom: 7px;
  border-radius: var(--r-badge); padding: 3px 8px;
  font-size: 11px; font-weight: 500; font-variant-numeric: tabular-nums;
}
.ag-item b { display: block; font-size: 13.5px; font-weight: 600; color: var(--neutral-100); }
.ag-item p { font-size: 12.5px; color: var(--neutral-80); margin-top: 3px; }
.bd .t { display: flex; justify-content: space-between; font-size: 12px; color: var(--neutral-80); margin-bottom: 6px; }
.bd .t b { color: var(--neutral-100); font-variant-numeric: tabular-nums; }
.bd .tr { height: 6px; border-radius: var(--r-pill); background: var(--neutral-40); overflow: hidden; }
.bd .tr span { display: block; height: 100%; background: var(--neutral-100); }
/* ===== Kanban ===== */
/* [28/08, pedido do JP] TODAS as colunas lado a lado, SEMPRE — o quadro rola
   na horizontal por dentro (padrao Trello), a pagina nunca. `auto-flow column`
   aceita 3 colunas (Tarefas) ou 6 (funil de Conversas) sem regra por caso, e
   o minimo de 260px garante cartao legivel; o 1fr estica quando sobra tela.
   A politica do vault sanciona exatamente isto: conteudo largo rola no
   proprio container. */
.kanban {
  display: grid; grid-auto-flow: column; grid-auto-columns: minmax(260px, 1fr);
  gap: 16px; align-items: start; overflow-x: auto;
  padding-bottom: 8px; /* respiro para a barra de rolagem nao colar nos cartoes */
}
.kb-col { background: var(--surface-50); border: 1px solid var(--neutral-50); border-radius: var(--r-card); padding: 14px; }
.kb-head { display: flex; align-items: center; gap: 8px; margin-bottom: 12px; }
.kb-head .dot { width: 7px; height: 7px; border-radius: var(--r-pill); flex: none; }
.kb-head b { font-size: 13.5px; font-weight: 600; color: var(--neutral-100); }
.kb-head .n { font-size: 12px; color: var(--neutral-80); }
/* Cartão de negócio dentro da coluna do funil. Reusa a anatomia do `.kb-col`
   das Tarefas de propósito: são dois quadros por estágio na mesma linguagem, e
   inventar um segundo desenho faria a mesma leitura parecer duas coisas. */
.kb-card {
  display: flex; flex-direction: column; gap: 2px;
  background: var(--surface-0); border: 1px solid var(--neutral-50);
  border-radius: var(--r-panel); padding: 10px 12px; margin-bottom: 8px;
}
.kb-card:last-child { margin-bottom: 0; }
.kb-card b { font-size: 13.5px; font-weight: 600; color: var(--neutral-100); }
.kb-card .det { font-size: 12px; color: var(--neutral-75); }
/* O estágio é um `<select>` e não um botão "avançar": o funil não é fila. De
   `Paralisado` se volta para `Negociação`, de `Declinado` se reabre — um botão
   precisaria adivinhar qual é o próximo, e não existe próximo. */
.kb-estagio {
  display: block; margin-top: 8px;
  border: 1px solid var(--neutral-50); border-radius: var(--r-input);
  background: var(--surface-0); transition: border-color var(--t);
}
.kb-estagio:focus-within { outline: 2px solid var(--neutral-100); outline-offset: 2px; }
.kb-estagio select {
  width: 100%; height: 34px; padding: 0 8px;
  border: 0; background: none; font: inherit; font-size: 12.5px;
  color: var(--neutral-90); cursor: pointer;
}
.kb-estagio select:focus { outline: none; }
/* Declinar pede o motivo ANTES de gravar. Perda sem motivo não entra no Pareto
   e some do "por que se perde" — o campo é o dado, não a fricção. */
.kb-motivo {
  display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px;
  padding-top: 8px; border-top: 1px solid var(--neutral-40);
}
.kb-motivo label { flex: 1 1 100%; }
.kb-motivo input {
  width: 100%; height: 34px; padding: 0 10px;
  border: 1px solid var(--neutral-50); border-radius: var(--r-input);
  background: var(--surface-0); font: inherit; font-size: 12.5px; color: var(--neutral-90);
}
.kb-motivo input:focus { border-color: var(--neutral-100); }
.kb-motivo .btn { flex: 1 1 auto; font-size: 12.5px; }
.kb-add {
  width: 100%; min-height: 36px; margin-bottom: 12px;
  display: flex; align-items: center; justify-content: center; gap: 7px;
  border: 1px dashed var(--neutral-50); border-radius: var(--r-input);
  background: var(--surface-0); color: var(--neutral-75); font-size: 13px; font-weight: 500;
  transition: background var(--t), border-color var(--t), color var(--t);
}
.kb-add:hover { background: var(--neutral-30); border-color: var(--neutral-90); color: var(--neutral-100); }
.kb-add svg { width: 14px; height: 14px; }
.tk {
  background: var(--surface-0); border: 1px solid var(--neutral-50);
  border-radius: var(--r-panel); padding: 14px; margin-bottom: 10px;
  transition: border-color var(--t);
}
.tk:last-child { margin-bottom: 0; }
.tk:hover { border-color: var(--neutral-90); cursor: pointer; }
.tk-tags { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; margin-bottom: 10px; }
.tk-tags .kebab { margin-left: auto; color: var(--neutral-80); }
.tk-tit { font-size: 13.5px; font-weight: 600; color: var(--neutral-100); line-height: 1.35; }
/* [13/09] A meta ganhou contato, empresa, prazo, responsavel e o link da
   conversa na mesma faixa: sem `flex-wrap` nos DOIS (o `span` e onde o
   conteudo realmente entra), a 390px isso vira rolagem lateral. */
.tk-meta { display: flex; align-items: center; flex-wrap: wrap; gap: 12px; margin-top: 10px; font-size: 11.5px; color: var(--neutral-80); }
.tk-meta span { display: inline-flex; align-items: center; flex-wrap: wrap; gap: 5px; font-variant-numeric: tabular-nums; }
.tk-meta svg { width: 13px; height: 13px; }
/* Escolher a data num toque (§7): alvos de 44px em qualquer largura, porque
   quem lê esta tela lê em pé. `flex-wrap` em vez de encolher o botão — quando
   não cabe, a linha vira duas; a palavra nunca quebra. */
.tk-prazo { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-top: 10px; }
.tk-prazo .btn { min-height: 44px; }
.tk-prazo-escolha { flex: 1 1 150px; min-width: 150px; }
.tk-foot { display: flex; align-items: center; gap: 12px; margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--neutral-40); }
.pilha { display: flex; }
.pilha .avatar { width: 22px; height: 22px; font-size: 9px; box-shadow: 0 0 0 2px var(--surface-0); margin-left: -6px; }
.pilha .avatar:first-child { margin-left: 0; }
.tk-foot .num-i { margin-left: auto; display: flex; gap: 12px; font-size: 11.5px; color: var(--neutral-80); }
.ml {
  width: 100%; text-align: left; background: none; border: 0;
  border-bottom: 1px solid var(--neutral-40); border-left: 2px solid transparent;
  padding: 14px 16px; transition: background var(--t), border-color var(--t);
}
.ml:hover { background: var(--neutral-30); }
.ml.sel { background: var(--neutral-30); border-left-color: var(--neutral-100); }
.ml .l1 { display: flex; align-items: center; gap: 8px; }
.ml .de { font-size: 13px; font-weight: 600; color: var(--neutral-100); flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ml .h { font-size: 11px; color: var(--neutral-80); flex: none; font-variant-numeric: tabular-nums; }
.ml .as { display: block; font-size: 12.5px; color: var(--neutral-90); margin-top: 4px; }
.ml .pv { display: block; font-size: 12px; color: var(--neutral-80); margin-top: 2px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ml .naolido { width: 7px; height: 7px; border-radius: var(--r-pill); background: var(--neutral-100); flex: none; }
.anexos { display: flex; gap: 10px; flex-wrap: wrap; padding: 14px 0; border-top: 1px solid var(--neutral-40); }
.anexo { display: inline-flex; align-items: center; gap: 8px; padding: 9px 12px; border: 1px solid var(--neutral-50); border-radius: var(--r-input); font-size: 12.5px; color: var(--neutral-90); text-decoration: none; transition: background var(--t); }
.anexo:hover { background: var(--neutral-30); }
.anexo svg { width: 15px; height: 15px; color: var(--neutral-80); }
/* ===== Agenda / Calendário ===== */
.cal-nav { display: flex; align-items: center; gap: 10px; margin-bottom: 16px; }
.cal-nav h2 { font-size: 18px; }
.cal { border: 1px solid var(--neutral-50); border-radius: var(--r-card); overflow: hidden; background: var(--surface-0); }
.cal-dias, .cal-grade { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); }
.cal-dias div { padding: 11px 12px; font-size: 12px; font-weight: 500; color: var(--neutral-75); background: var(--neutral-30); text-align: left; }
.cal-cel { min-height: 108px; padding: 8px 10px; border-top: 1px solid var(--neutral-40); border-left: 1px solid var(--neutral-40); }
.cal-cel:nth-child(7n+1) { border-left: 0; }
.cal-cel .d { font-size: 12px; color: var(--neutral-90); font-variant-numeric: tabular-nums; }
.cal-cel.fora .d { color: var(--neutral-80); }
.cal-cel.hoje .d { display: inline-grid; place-items: center; width: 22px; height: 22px; border-radius: var(--r-pill); background: var(--neutral-100); color: var(--neutral-0); font-weight: 500; }
.ev { display: block; margin-top: 5px; padding: 3px 7px; border-radius: 5px; font-size: 11px; font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* ===== Contatos em grade ===== */
.cg { display: grid; grid-template-columns: repeat(auto-fill, minmax(232px, 1fr)); gap: 16px; }
.cc { background: var(--surface-0); border: 1px solid var(--neutral-50); border-radius: var(--r-card); padding: 16px; transition: border-color var(--t); }
.cc:hover { border-color: var(--neutral-90); }
.cc .topo { display: flex; align-items: flex-start; gap: 10px; }
.cc .nm { font-size: 14px; font-weight: 600; color: var(--neutral-100); }
.cc .loc { display: flex; align-items: center; gap: 4px; font-size: 12px; color: var(--neutral-80); margin-top: 2px; }
.cc .loc svg { width: 12px; height: 12px; }
.cc .kebab { margin-left: auto; color: var(--neutral-80); }
.cc .tag { margin: 12px 0 10px; }
.cc .campo { display: flex; align-items: center; gap: 8px; font-size: 12.5px; color: var(--neutral-90); margin-top: 7px; }
.cc .campo svg { width: 14px; height: 14px; flex: none; color: var(--neutral-80); }
.cc .campo a { color: var(--neutral-90); text-decoration: underline; text-underline-offset: 3px; text-decoration-color: var(--neutral-50); overflow: hidden; text-overflow: ellipsis; }
.cc .acoes { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin-top: 14px; }
.cc .acoes .btn { min-height: 36px; padding: 0 10px; font-size: 12.5px; }
/* ===== Empresas / Integrações ===== */
.eg { display: grid; grid-template-columns: repeat(auto-fill, minmax(226px, 1fr)); gap: 16px; }
.ec { display: flex; flex-direction: column; background: var(--surface-0); border: 1px solid var(--neutral-50); border-radius: var(--r-card); padding: 18px; transition: border-color var(--t); }
.ec:hover { border-color: var(--neutral-90); }
.ec .topo { display: flex; align-items: flex-start; }
.ec .lg { width: 36px; height: 36px; border-radius: var(--r-panel); background: var(--neutral-30); display: grid; place-items: center; font-size: 13px; font-weight: 600; color: var(--neutral-90); }
.ec .nm { font-size: 14px; font-weight: 600; color: var(--neutral-100); margin-top: 14px; }
.ec .ram { font-size: 12.5px; color: var(--neutral-80); margin-top: 3px; }
.ec .loc { display: flex; align-items: center; gap: 5px; font-size: 12px; color: var(--neutral-80); margin-top: 12px; }
.ec .loc svg { width: 13px; height: 13px; }
.ec p.desc { font-size: 12.5px; color: var(--neutral-80); margin-top: 10px; }
.ec .btn { margin-top: auto; padding-top: 0; width: 100%; min-height: 36px; font-size: 13px; }
.ec p.desc + .btn, .ec .loc + .btn { margin-top: 16px; }

/* ===== Landing page ===== */
.lp { background: var(--surface-0); border: 1px solid var(--neutral-50); border-radius: var(--r-card); overflow: hidden; }
@media (max-width: 1180px) {
.stat-grid, .breakdown, .lp-feat { grid-template-columns: repeat(2, minmax(0, 1fr)); }
/* A grade do Painel nao esta aqui: ela consulta o proprio bloco
   (`@container painel`), nao a janela — desde 03/09. */
.lp-hero, .lp-logos, .lp-quad, .lp-rod-grid { grid-template-columns: 1fr; }
.topbar { padding: 0 20px; }
}
@media (max-width: 860px) {
/* [ui2] A TOPBAR NAO SOME MAIS NO CELULAR.

   `display: none` aqui levava embora QUATRO controles que so existem dentro
   dela: `#record` (o unico primario preto do console, e a unica porta de
   "Registrar visita" que a interface oferece), `#import`, o alerta de segundo
   fator e o selo de origem dos dados. Abaixo de 861px o produto ficava sem
   como gravar uma visita pela tela — e e no celular que a visita acontece.
   O vazio do Painel piorava a piada: mandava apertar um botao que nao existia
   naquela largura.

   O que sai no lugar e o que nao cabe: o titulo (cada view tem o seu em
   `.tela-head h1`) e a busca da barra. Sobram as acoes, que e o que se veio
   buscar. E a barra deixa de ser `sticky`: com a `.mobile-topbar` ja grudada
   em `top: 0`, duas barras fixas empilhadas comiam a altura util de um
   aparelho de 390px — e uma delas cobriria a outra. */
.topbar {
    position: static; height: auto; flex-wrap: wrap;
    gap: 10px; padding: 12px 20px;
  }
/* [07/09] O TÍTULO FICA ONDE ELE É O NÍVEL 1. `view()` marca `#title` com
   `role="heading"` em `visits`, `accounts`, `sources` e `deal` — as quatro
   vistas que abrem em `<h2>` e não têm `<h1>` próprio. Escondê-lo aqui
   deixava essas quatro SEM CABEÇALHO NENHUM no telefone: a tela não dizia
   onde a pessoa estava (só "Pergor", que é igual em todas) e o documento
   começava no segundo degrau. Nas outras oito o `<h1>` da tela existe e a
   barra continua muda, que é o que libera a dobra.
   O seletor pergunta ao PAPEL em vez de repetir a lista das quatro: quem
   manda continua sendo `VISTAS_SEM_H1_PROPRIO`, no portal.js. */
.topbar > div:first-child:not(:has(#title[role="heading"])),
.topbar .busca, .topbar .ajuda { display: none; }
/* `.topbar` na frente por ESPECIFICIDADE, nao por capricho: as regras base de
   `.header-actions` (`flex-wrap: nowrap`) e `.header-status` (o filete da
   esquerda) moram MAIS ABAIXO nesta folha, entao em empate de peso elas
   venciam este bloco. Medido a 390px antes do ajuste: o selo de origem ficava
   com 20px para 135px de texto e o horario da ultima leitura com 3px — o
   `ellipsis` salvava do estouro e apagava a informacao. */
.topbar .header-actions { width: 100%; flex-wrap: wrap; justify-content: flex-start; }
.topbar .header-status { display: none; }
#mobile-header-status-slot { display: flex; margin-left: auto; min-width: 0; }
.mobile-topbar .header-status {
  gap: 4px; padding: 0; border: 0; min-width: 0; max-width: 44vw;
  font-size: 10px; white-space: nowrap;
}
.mobile-topbar .header-status #source { max-width: 70px; }
/* [06/09] A MOLDURA COME A DOBRA DO CELULAR. Medido a 390px antes disto:
   45%-55% da primeira tela era barra, e o primeiro numero do Painel so
   aparecia a 387px. Saem os dois passageiros — "Importar", que tem a porta
   de dentro do dialogo de gravacao ("Ja tem uma gravacao pronta? Importar
   audio", o `[data-abrir-importador]` de `index.html`) e a do guia
   `/comecar`, que oferece as duas lado a lado; e o CARIMBO DE FRESCOR
   (`#updated`), que e informacao de conferencia e nao de acao. Ficam o
   primario preto ("Registrar visita", a unica porta de gravar), o alerta de
   segundo fator e o botao de atualizar, que e a acao do bloco de estado.

   `#updated`, e NAO `.header-status > span`: o irmao dele, `#source`, ja fica
   escondido na leitura normal (`applyData`) e so fala quando ha NOTICIA — o
   ambar do modo de demonstracao e o "Nao atualizei desde HH:MM" de um refresh
   que falhou (`manterLeituraAnterior`). Apaga-lo em bloco reabria no celular o
   defeito de 03/09 anotado adiante nesta folha: o aviso existia no DOM e nao
   existia na tela, e dado velho passava por dado fresco. */
.topbar .btn.sec { display: none; }
.topbar #updated { display: none; }
/* Horário e recarga ficam na faixa do símbolo, em tamanho compacto. */
.mobile-topbar #updated { display: inline; font-size: 10px; line-height: 1.2; color: var(--neutral-75); }
.mobile-topbar #refresh { width: 28px; height: 28px; }
.mobile-topbar #refresh svg { width: 13px; height: 13px; }
/* `view()` define a tela corrente e oculta o registro fora do Painel/Visitas.
   Esta regra também cobre a pintura inicial, antes de o JS executar. */
.topbar #record[hidden],
body[data-vista]:not([data-vista="home"]):not([data-vista="visits"]) .topbar #record { display: none; }
body[data-vista]:not([data-vista="home"]):not([data-vista="visits"]) .topbar .header-actions { width: auto; margin-left: auto; }
/* Números e Nova conexão abrem no menu da Fila, sem ocupar uma linha da tela. */
.conv-controles-mobile:has(#conv-conexoes:not([hidden])) { display: block; }
.conv-controles-mobile { position: relative; margin-left: auto; }
.conv-controles-mobile > summary {
  list-style: none; display: flex; align-items: center; min-height: 44px;
  padding: 0 12px; border: 1px solid var(--neutral-50);
  border-radius: var(--r-input); font-size: 13px; cursor: pointer;
}
.conv-controles-mobile > summary::-webkit-details-marker { display: none; }
.conv-controles-mobile > summary::after { content: "⌄"; margin-left: 10px; font-size: 18px; line-height: 1; }
.conv-controles-mobile > summary:focus-visible { outline: 2px solid var(--neutral-100); outline-offset: 2px; }
.conv-controles-mobile > div {
  position: absolute; z-index: 20; top: calc(100% + 6px); right: 0;
  width: min(320px, calc(100vw - 64px)); padding: 12px;
  border: 1px solid var(--neutral-50); border-radius: var(--r-card);
  background: var(--surface-0); box-shadow: var(--shadow-float);
}
.conv-controles-mobile:not([open]) > div { display: none; }
.conv-controles-mobile .conv-conexao-toolbar { flex-direction: column; align-items: stretch; margin: 0; }
.conv-controles-mobile .conv-conexao-filtro > summary { width: 100%; }
.conv-list-card { overflow: visible; }
/* No telefone, a busca e o menu ocupam uma linha. Recorte, avaliação e revisão
   ficam no pop-up, para a primeira conversa entrar logo depois da busca. */
.conv-list-card .card-head { padding: 10px 16px; }
.conv-filtro { flex-wrap: nowrap; gap: 8px; padding: 0 12px 8px; }
.conv-filtro .search-field { flex: 1 1 auto; min-width: 0; }
.conv-filtro .search-field input { height: 44px; }
.conv-filtros-mobile { display: block; position: relative; flex: none; }
.conv-filtros-mobile > summary {
  display: flex; align-items: center; min-height: 44px; padding: 0 10px;
  border: 1px solid var(--neutral-50); border-radius: var(--r-input);
  font-size: 13px; cursor: pointer; list-style: none;
}
.conv-filtros-mobile > summary::-webkit-details-marker { display: none; }
.conv-filtros-mobile > summary:focus-visible { outline: 2px solid var(--neutral-100); outline-offset: 2px; }
.conv-filtros-mobile > summary::after { content: "⌄"; margin-left: 6px; font-size: 17px; }
#conv-filtros-pendentes:not(:empty) {
  display: grid; place-items: center; min-width: 18px; height: 18px;
  margin-left: 4px; border-radius: var(--r-pill);
  background: var(--amber-tint); color: var(--amber-ink); font-size: 11px;
}
#conv-filtros-pendentes.filtro-ativo { background: var(--neutral-30); color: var(--neutral-90); }
.conv-filtros-mobile > div {
  position: absolute; z-index: 20; top: calc(100% + 6px); right: 0;
  width: min(320px, calc(100vw - 64px)); padding: 12px;
  border: 1px solid var(--neutral-50); border-radius: var(--r-card);
  background: var(--surface-0); box-shadow: var(--shadow-float);
}
.conv-filtros-mobile:not([open]) > div { display: none; }
.conv-filtros-mobile .filtro-campo { display: block; width: 100%; }
.conv-filtros-mobile .filtro-campo select { width: 100%; }
.conv-filtros-mobile .conv-fila-controles { padding: 8px 0; font-size: 12px; }
.conv-filtros-mobile .conv-fila-revisao { margin: 4px 0 0; padding: 8px; font-size: 12px; }
.conv-filtros-mobile .conv-fila-contexto { padding: 8px 0 0; font-size: 12px; }
#conversas.view.active { height: calc(100dvh - 150px); }
.stat-grid, .breakdown, .lp-feat, .lp-quad-grid, .cg, .eg, .notes-grid { grid-template-columns: 1fr; }
.cal-cel { min-height: 74px; padding: 6px; }
.cal-dias div { padding: 8px 6px; font-size: 11px; }
.ev { font-size: 10px; }
.tela-head .acoes { margin-left: 0; width: 100%; }
.tela-head .toolbar { margin-left: 0; width: 100%; }
}

/* ============================================================
   Acentos como CLASSE, nao como `style=` inline.

   O mockup escreve `style="background:var(--blue-tint);color:var(--blue-ink)"`
   em toda tag, pill de evento e ponto de coluna. Funciona, mas
   espalha estilo pelo HTML e atrapalha o dia em que a CSP apertar
   (`style-src 'unsafe-inline'` ainda esta ligado por causa do
   Leaflet; sem ele, da para tirar). Aqui viram classe.

   O par tint/ink e sempre usado JUNTO: fundo claro + texto escuro
   do mesmo acento. O DESIGN.md §11 mediu os quatro que o kit
   Venture trazia reprovando AA e escureceu so o texto — os valores
   abaixo sao os corrigidos.
   ============================================================ */
.tint-blue   { background: var(--blue-tint);   color: var(--blue-ink) }
.tint-green  { background: var(--green-tint);  color: var(--green-ink) }
.tint-amber  { background: var(--amber-tint);  color: var(--amber-ink) }
.tint-olive  { background: var(--olive-tint);  color: var(--olive-ink) }
.tint-red    { background: var(--red-tint);    color: var(--red-ink) }
.tint-violet { background: var(--violet-tint); color: var(--violet-ink) }
.tint-neutro { background: var(--neutral-30);  color: var(--neutral-75) }

/* O ponto do cabecalho de coluna do kanban e do selo. Nunca vem
   sozinho: o §11 exige marcador ALEM da cor, e quem carrega o
   estado e o texto ao lado. */
.dot-blue   { background: var(--blue-ink) }
.dot-green  { background: var(--green-ink) }
.dot-amber  { background: var(--amber-ink) }
.dot-olive  { background: var(--olive-ink) }
.dot-red    { background: var(--red-ink) }
.dot-violet { background: var(--violet-ink) }
.dot-neutro { background: var(--neutral-75) }

/* ============================================================
   Espacador da sidebar. No mockup e `<div style="flex:1">`;
   aqui e classe, pela mesma razao acima.
   ============================================================ */
.side-spacer { flex: 1 1 auto; min-height: 8px }

/* ============================================================
   Compatibilidade do shell SPA existente com a marcação v4.
   Estes ganchos preservam contratos de portal.js e do perfil Vendedor.
   ============================================================ */
.view { display: none; }
.view.active { display: block; }
.side-nav[hidden], #nav-vendedor[hidden] { display: none; }
.pular-link {
  position: fixed; left: 12px; top: 10px; z-index: 100;
  padding: 8px 12px; border-radius: var(--r-input);
  background: var(--neutral-100); color: var(--neutral-0);
  transform: translateY(-160%);
}
.pular-link:focus { transform: translateY(0); }
.side-brand a { display: grid; place-items: center; }
.side-nav .nav, #nav-vendedor .nav {
  appearance: none; display: flex; align-items: center; gap: 10px;
  min-height: 38px; width: 100%; padding: 8px 10px;
  border: 1px solid transparent; border-radius: var(--r-input);
  background: transparent; color: var(--neutral-90); text-align: left;
  font-size: 14px; transition: background var(--t), border-color var(--t), color var(--t);
}
.side-nav .nav:hover, #nav-vendedor .nav:hover { background: var(--neutral-30); color: var(--neutral-100); }
.side-nav .nav.active, #nav-vendedor .nav.active {
  background: var(--surface-0); border-color: var(--neutral-50);
  color: var(--neutral-100); font-weight: 500;
}
.side-nav .nav svg, #nav-vendedor .nav > svg, .side-team svg, .side-logout svg,
.topbar svg, .mobile-topbar svg {
  fill: none; stroke: currentColor; stroke-width: 1.8;
  stroke-linecap: round; stroke-linejoin: round;
}
#nav-vendedor {
  flex: 1; min-height: 0; overflow-y: auto; padding: 6px 10px 16px;
  flex-direction: column; gap: 2px;
}
#nav-vendedor:not([hidden]) { display: flex; }
#nav-vendedor .sidebar-label {
  margin: 18px 8px 5px; color: var(--neutral-75);
  font-size: 11px; font-weight: 500; letter-spacing: .06em; text-transform: uppercase;
}
#nav-vendedor .nav-grupo { display: flex; flex-direction: column; gap: 2px; }
#nav-vendedor .nav > svg { width: 16px; height: 16px; flex: none; color: var(--neutral-75); }
#nav-vendedor .nav.active > svg { color: var(--neutral-100); }
.side-footer { position: relative; }
.perfil-seletor-caixa { position: relative; }
.side-team .perfil-seletor__avatar {
  width: 24px; height: 24px; flex: none; border-radius: var(--r-badge);
  display: grid; place-items: center; background: var(--neutral-100); color: var(--neutral-0);
}
.side-team .perfil-seletor__avatar svg { width: 14px; height: 14px; }
.perfil-seletor__texto { display: flex; min-width: 0; flex: 1; flex-direction: column; text-align: left; line-height: 1.2; }
.perfil-seletor__texto b { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.perfil-seletor__texto small { color: var(--neutral-75); font-size: 11px; }
.perfil-seletor__chevron { width: 14px; height: 14px; margin-left: auto; }
.perfil-menu {
  position: absolute; left: 0; right: 0; bottom: calc(100% + 8px); z-index: 40;
  padding: 6px; border: 1px solid var(--neutral-50); border-radius: var(--r-panel);
  background: var(--surface-0); box-shadow: var(--shadow-float);
}
.perfil-menu__item {
  display: flex; align-items: center; gap: 8px; width: 100%; min-height: 38px;
  padding: 7px 9px; border: 0; border-radius: var(--r-input);
  background: transparent; color: var(--neutral-90); text-align: left;
}
.perfil-menu__item:hover { background: var(--neutral-30); }
.perfil-menu__icone, .perfil-menu__check { width: 16px; height: 16px; }
.perfil-menu__check { margin-left: auto; visibility: hidden; }
.perfil-menu__item[aria-checked="true"] .perfil-menu__check { visibility: visible; }
.nav-foot { display: flex; align-items: center; gap: 8px; }
.connection { display: flex; min-width: 0; flex: 1; align-items: center; gap: 8px; color: var(--neutral-75); }
.connection > i { width: 8px; height: 8px; flex: none; border-radius: var(--r-pill); background: var(--green-ink); }
.connection span { display: flex; min-width: 0; flex-direction: column; }
.connection b, .connection small { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.connection b { color: var(--neutral-100); font-size: 12px; font-weight: 500; }
.connection small { font-size: 10px; }
/* [03/09] Sair era o ÚNICO item mudo da barra expandida: os destinos e o
   rodapé falam por extenso e a ação mais irreversível da coluna (derruba a
   sessão) ficava só no ícone, com o rótulo em "só leitor de tela" — medido a
   1440px: scrollWidth 26 contra clientWidth 1, que lê como corte de texto.
   Com largura de sobra o rótulo entra; o clip fica onde faz sentido, que é
   a barra recolhida e o trilho de ícones (≤1180). */
.side-logout { width: auto; flex: none; min-height: 34px; padding: 8px 10px; gap: 8px; }
.side-logout svg { width: 16px; height: 16px; }
.app-shell.collapsed .side-logout, html.sidebar-collapsed .side-logout { width: 34px; padding: 8px; }
.app-shell.collapsed .side-logout .sidebar-item-label,
html.sidebar-collapsed .side-logout .sidebar-item-label { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }
@media (max-width: 1180px) {
  .app-shell .side-logout { width: 34px; padding: 8px; }
  .app-shell .side-logout .sidebar-item-label { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }
}
.topbar > div:first-child { flex: 1; min-width: 0; }
/* [06/09] O TITULO DA BARRA DEIXOU DE SER `<h1>`. Toda tela do Portal ja
   tem o seu em `.tela-head h1`; a barra repetia o nome do destino num
   segundo `<h1>`, e um documento com dois `<h1>` nao tem cabeca. Virou
   `<p id="title">` na marcacao — o `id` e contrato com `portal.js` e fica.
   As tres propriedades que vinham do seletor de titulo (peso, tinta e
   tracking) sao ditas aqui, porque um `<p>` nao as herda. */
/* O título fica na topbar: é a faixa constante da navegação e deixa a dobra
   livre para o conteúdo da vista. As telas que tinham somente esse título
   interno (como Conversas) não repetem uma segunda linha abaixo dela. */
.topbar #title { font-size: 20px; font-weight: 500; color: var(--neutral-100); letter-spacing: -.015em; white-space: nowrap; }
.header-actions { justify-content: flex-end; flex-wrap: nowrap; }
.header-status {
  display: flex; align-items: center; gap: 8px; min-width: 0;
  padding-left: 12px; border-left: 1px solid var(--neutral-50);
  color: var(--neutral-75); font-size: 12px;
}
.header-status #source, .header-status #updated { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* [03/09] O rótulo de origem anuncia TRÊS coisas — leitura do Server, modo
   de demonstração e falha de leitura — e `applyData` marca as duas últimas
   com `.is-indisponivel` / `.is-demo` justamente para que a falha não tenha
   a mesma cara do estado normal. As duas regras existiam no `pergor.css`,
   folha que o console não carrega: o aviso existia no DOM e não existia na
   tela. "Servidor indisponível" lia igual a "Dados do Pergor Server".

   O tracejado para indisponível é a mesma linguagem do `.honest-empty`:
   ausência de leitura, que pode chegar depois — não vermelho, porque não há
   ação do lado de cá. O âmbar para demonstração diz "isto não é dado do seu
   cliente", que é a única coisa que importa saber ali. */
.header-status #source.is-indisponivel {
  padding: 2px 8px; border: 1px dashed var(--neutral-50); border-radius: var(--r-badge);
  color: var(--neutral-75);
}
.header-status #source.is-demo {
  padding: 2px 8px; border-radius: var(--r-badge);
  color: var(--amber-ink); background: var(--amber-tint);
}
.acao-pagina__icone { display: grid; width: 16px; height: 16px; place-items: center; }
.acao-pagina__icone svg, .totp-alert svg, .refresh svg { width: 16px; height: 16px; }
.menu-fundo { display: none; }
.section-heading { display: flex; align-items: end; gap: 16px; margin-bottom: 18px; }
/* [31/08] `:not(:first-child)` — e a falta dele empurrava OITO cabeçalhos.
   A regra existe para jogar à direita um SEGUNDO elemento (um recorte, uma
   estatística). Com um filho só, esse filho é o `:last-child` e ia junto: em
   Negócios, Configurações, Integrações e Administração o título aparecia
   encostado na margem direita, com o texto abaixo dele à esquerda.
   Achado ao medir a tela nova; o defeito é de todas. */
.section-heading > :last-child:not(:first-child) { margin-left: auto; }
.section-heading p { color: var(--neutral-75); font-size: 11px; font-weight: 500; letter-spacing: .06em; text-transform: uppercase; }
/* A trilha de volta mora dentro do kicker: o link herda os 11px e o espaçamento
   dele, senão o degrau "Carteira" cresceria 2px acima do resto da linha. */
.section-heading p .link-button { font-size: inherit; letter-spacing: inherit; }
.section-heading h2 { margin-top: 3px; font-size: 20px; }
.honest-empty, .empty, .view-note { color: var(--neutral-75); line-height: 1.6; }

html.sidebar-collapsed #nav-vendedor .sidebar-item-label,
html.sidebar-collapsed #nav-vendedor .sidebar-label,
html.sidebar-collapsed .side-footer .perfil-seletor__texto,
html.sidebar-collapsed .side-footer .perfil-seletor__chevron,
html.sidebar-collapsed .side-footer .side-empresa span,
html.sidebar-collapsed .side-footer .connection span { display: none; }
html.sidebar-collapsed #nav-vendedor .nav,
html.sidebar-collapsed .side-footer .side-empresa,
html.sidebar-collapsed .side-footer .side-team { justify-content: center; padding: 8px; }
html.sidebar-collapsed .side-footer .connection { justify-content: center; }

@media (max-width: 1180px) {
  #nav-vendedor .sidebar-item-label, #nav-vendedor .sidebar-label,
  .side-footer .perfil-seletor__texto, .side-footer .perfil-seletor__chevron,
  .side-footer .side-empresa span,
  .side-footer .connection span { display: none; }
  #nav-vendedor .nav, .side-footer .side-empresa,
  .side-footer .side-team { justify-content: center; padding: 8px; }
}
@media (max-width: 860px) {
  .sidebar { width: 252px; transform: translateX(-252px); }
  body.menu-aberto .app-shell .workspace { margin-left: 0; }
  .menu-fundo {
    position: fixed; inset: 0; z-index: 19; display: block;
    background: rgba(0, 0, 0, .32);
  }
  .menu-fundo[hidden] { display: none; }
  #nav-vendedor .sidebar-item-label, #nav-vendedor .sidebar-label,
  .side-footer .perfil-seletor__texto, .side-footer .perfil-seletor__chevron,
  .side-footer .connection span { display: flex; }
  #nav-vendedor .sidebar-label { display: block; }
  #nav-vendedor .nav, .side-footer .side-team { justify-content: flex-start; padding: 8px 10px; }
  main { max-width: none; }

  /* [28/08] A GAVETA DO CELULAR NÃO É O TRILHO DE ÍCONES DO TABLET.
     Defeito que o JP fotografou: a gaveta abria com 252px de largura e só
     ícones — nenhum nome de tela. A causa é de herança, não de desenho: o
     recorte de ≤1180 transforma a barra num trilho de 64px e esconde
     `.app-shell .nav-label`; este bloco de ≤860 devolve a largura de gaveta
     e já restaurava os rótulos — mas SÓ os do `#nav-vendedor`, logo acima.
     O gestor nunca foi restaurado, então a gaveta dele abria muda, com
     252px de espaço sobrando ao lado de cada ícone.

     Os três seletores abaixo carregam `.sidebar` no meio de propósito: com
     três classes eles vencem tanto `.app-shell .nav-label` quanto
     `html.sidebar-collapsed .nav-label` — o segundo importa porque a
     preferência de recolher é PERSISTIDA, então quem recolheu a barra no
     desktop reabria o celular com a gaveta muda mesmo depois da correção. */
  .app-shell .sidebar .brand-copy,
  .app-shell .sidebar .nav-label,
  .app-shell .sidebar .nav-group,
  .app-shell .sidebar .nav-tag { display: block; }
  .app-shell .sidebar .side-footer .side-empresa span { display: flex; }
  .app-shell .sidebar .side-footer .side-empresa { justify-content: flex-start; padding: 8px 10px; }
  .app-shell .sidebar .side-brand { grid-template-columns: 28px 1fr; justify-items: stretch; padding: 16px 14px; }
  .app-shell .sidebar .side-nav a,
  .app-shell .sidebar .side-nav .nav,
  .app-shell .sidebar .nav-disabled,
  .app-shell .sidebar .side-status,
  .app-shell .sidebar .side-user { justify-content: flex-start; padding: 8px 10px; }
  /* Recolher DENTRO da gaveta devolveria exatamente o menu mudo que este
     bloco tira. Quem fecha a gaveta é o botão da topbar e o fundo escuro. */
  .app-shell .sidebar .side-toggle { display: none; }
}

/* ── TABLET (861–1180): o trilho ganha um painel que abre POR CIMA ────────
   [31/08] Defeito que o JP encontrou: nesta faixa a barra é um trilho de
   64px e NÃO ABRE. A causa está no recorte de ≤1180 lá em cima, que força
   `grid-template-columns: 64px` para `.app-shell` PURO — o mesmo valor do
   estado recolhido. O botão continua lá e troca de rótulo, mas os dois
   estados desenham a mesma coisa; não havia como o clique mudar um pixel.

   POR QUE O PAINEL FLUTUA EM VEZ DE EMPURRAR. A 900px, abrir 252px de barra
   tira 188px do conteúdo e cruza o degrau de 660px do `@container resumo`:
   os cartões se reorganizam embaixo de quem só queria ler o nome de uma
   tela. Aqui a barra continua NO FLUXO — é `sticky`, não `fixed` — e apenas
   cresce sobre o conteúdo: a coluna segue com 64px e nada se move.

   `position: fixed` AQUI É O ERRO CARO, e por isso está escrito: a barra
   sairia da grade, o `.workspace` seria reposicionado para a primeira célula
   livre — a de 64px — e o conteúdo colapsaria numa tira.

   POR QUE O TRILHO FICA, E A GAVETA DO CELULAR NÃO SERVE. No tablet o trilho
   é acesso permanente às telas; trocá-lo por hambúrguer piora o que já
   funciona. A gaveta existe no celular porque lá não há trilho nenhum — é o
   que o teste da gaveta já dizia em 28/08. */
@media (min-width: 861px) and (max-width: 1180px) {
  .app-shell .sidebar { transition: width var(--t); }
  body.menu-aberto .app-shell .sidebar { width: 252px; box-shadow: var(--shadow-float); }
  body.menu-aberto .menu-fundo {
    position: fixed; inset: 0; z-index: 19; display: block;
    background: rgba(0, 0, 0, .32);
  }
  /* O `hidden` tem de vencer o `display: block` acima: se o JS falhar em
     baixá-lo, o que sobra na tela é um retângulo preto. */
  body.menu-aberto .menu-fundo[hidden] { display: none; }

  /* Os rótulos voltam com TRÊS classes, pela mesma razão da gaveta do
     celular: `html.sidebar-collapsed .nav-label` é (0,2,1) e é PERSISTIDO —
     quem recolheu no desktop abriria aqui um painel de 252px e mudo. */
  body.menu-aberto .app-shell .sidebar .brand-copy,
  body.menu-aberto .app-shell .sidebar .nav-label,
  body.menu-aberto .app-shell .sidebar .nav-tag { display: block; }
  /* `.nav-group` NÃO entra aqui, embora o bloco do celular logo acima o
     carregue: a classe está 4x nesta folha e ZERO vezes em template ou JS —
     o gestor separa por `.side-spacer` e o vendedor por `.sidebar-label`,
     medido no navegador a 1400px. Copiar um seletor morto para uma regra
     nova é como ele vira cinco e passa a parecer intencional. */
  body.menu-aberto .app-shell .sidebar #nav-vendedor .sidebar-item-label,
  body.menu-aberto .app-shell .sidebar .side-footer .perfil-seletor__texto,
  body.menu-aberto .app-shell .sidebar .side-footer .perfil-seletor__chevron,
  body.menu-aberto .app-shell .sidebar .side-footer .connection span { display: flex; }
  body.menu-aberto .app-shell .sidebar #nav-vendedor .sidebar-label { display: block; }

  /* O respiro acompanha: centrado no trilho de 64px, à esquerda no painel. */
  body.menu-aberto .app-shell .sidebar .side-brand {
    grid-template-columns: 28px 1fr 28px; justify-items: stretch; padding: 16px 14px;
  }
  body.menu-aberto .app-shell .sidebar .side-nav a,
  body.menu-aberto .app-shell .sidebar .side-nav .nav,
  body.menu-aberto .app-shell .sidebar .nav-disabled,
  body.menu-aberto .app-shell .sidebar .side-status,
  body.menu-aberto .app-shell .sidebar .side-user,
  body.menu-aberto .app-shell .sidebar #nav-vendedor .nav,
  body.menu-aberto .app-shell .sidebar .side-footer .side-team { justify-content: flex-start; padding: 8px 10px; }
  body.menu-aberto .app-shell .sidebar .side-footer .connection { justify-content: flex-start; }
}

/* ═══ DIÁLOGOS ════════════════════════════════════════════════════════════
   REGRESSÃO CORRIGIDA EM 28/08. A F1 trocou o shell e tirou o `pergor.css`
   da cascata, mas os cinco `<dialog>` continuaram com a marcação antiga e
   ficaram SEM REGRA NENHUMA. Medido no navegador a 1280px antes da correção:
   largura 1246px (a viewport inteira, em vez de modal), padding 0, raio 0,
   sem sombra, e o botão de fechar em 4×25px — clicável por sorte.

   Nenhum teste pegou: `test_csp` olha diretiva, `test_tokens_resolvem` olha
   token, e não havia teste de layout de diálogo. Passou pelo portão da F1
   inteiro. Agora há um teste (`tests/test_dialogos.py`).

   Vocabulário v4 (DESIGN.md §7 "Modal" e §5 elevação): `surface-0`, raio de
   card, sombra de modal — sombra é legítima aqui, é camada que flutua de
   verdade. Entra com fade + escala .98→1, como o `.modal` do mockup. */
dialog {
  /* [31/08] `margin: auto` DEVOLVE A CENTRALIZAÇÃO, e a causa é o reset.
     O navegador centraliza modal com `margin: auto` na própria folha dele —
     e `* { margin: 0 }` na linha 98 zera isso, porque folha de autor sempre
     vence folha de navegador. Os CINCO diálogos do Portal abriam encostados
     no canto superior esquerdo (medido: x=6, y=4 numa janela de 1280×900).
     Nada quebra, nada fica vermelho, e ninguém suspeita do reset. */
  margin: auto;
  width: min(560px, calc(100% - 32px));
  max-height: calc(100vh - 32px);
  padding: 0;
  border: 1px solid var(--neutral-50);
  border-radius: var(--r-card);
  background: var(--surface-0);
  color: var(--neutral-90);
  box-shadow: var(--shadow-modal);
  overflow: auto;
}
/* O de gravação e o de importação carregam formulário de três campos; os
   demais são confirmação e cabem no máximo de 440px do DESIGN.md §7. */
#record-dialog, #import-dialog, #admin-user-dialog, #admin-company-dialog { width: min(610px, calc(100% - 32px)) }
#review-dialog, #correction-dialog, #view-context-dialog, #voice-profile-dialog, #user-delete-dialog, #visit-contact-company-confirm-dialog { width: min(520px, calc(100% - 32px)) }
dialog::backdrop { background: rgba(0, 0, 0, .38) }
dialog[open] { animation: entra 160ms ease-out }
@media (prefers-reduced-motion: reduce) { dialog[open] { animation: none } }

.record-shell, .review-dialog > form, .review-dialog > section { position: relative; padding: 26px }
/* Sem isto as três etapas da gravação (preparar / gravando / resultado)
   aparecem TODAS ao mesmo tempo: `hidden` perde para qualquer `display`. */
.record-stage[hidden] { display: none }
.record-stage h2 { font-size: 20px; font-weight: 500; margin: 0 0 8px }
.record-intro { display: block; font-size: 13.5px; color: var(--neutral-75); line-height: 1.55 }
.dialog-kicker {
  font-size: 11px; font-weight: 500; letter-spacing: .06em;
  text-transform: uppercase; color: var(--neutral-75); margin: 0 0 8px;
}
.dialog-note { font-size: 13px; color: var(--neutral-75); line-height: 1.55; margin: 8px 0 16px }
.voice-phrase { margin: 16px 0; padding: 14px 16px; border: 1px solid var(--neutral-50); border-radius: var(--r-input); background: var(--neutral-30) }
.voice-phrase small { display: block; margin-bottom: 6px; color: var(--neutral-75); font-size: 11px; font-weight: 600; letter-spacing: .05em; text-transform: uppercase }
.voice-phrase p { margin: 0; color: var(--neutral-90); font-size: 14px; line-height: 1.5 }
#admin-user-dialog .voice-phrase, #admin-user-dialog .dialog-actions,
#admin-company-dialog .dialog-actions { grid-column: 1 / -1; margin: 0 }
#admin-user-dialog .voice-phrase > .btn { margin-top: 10px }
/* [10/09] O cadastro de empresa entrou no mesmo molde e herda as MESMAS duas
   regras: sem `grid-column`, a barra de ações vira uma célula de meia coluna
   dentro da grade de `.record-fields`; sem o `sticky`, os treze campos rolam e
   o "Nova empresa" sai da tela a 390px. */
#admin-user-dialog .dialog-actions, #admin-company-dialog .dialog-actions {
  position: sticky; bottom: 0; z-index: 1; padding-top: 12px;
  border-top: 1px solid var(--neutral-50); background: var(--surface-0);
}
.voice-actions { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; margin-bottom: 10px }
.voice-actions .btn, .voice-actions .record-primary { width: auto }
.voice-file { display: inline-flex; align-items: center; justify-content: center; cursor: pointer }
#voice-profile-dialog audio { width: 100%; margin: 4px 0 14px }
.danger-text { color: var(--red-ink) }
.record-note {
  font-size: 12.5px; color: var(--neutral-75); line-height: 1.55;
  border: 1px solid var(--neutral-50); border-radius: var(--r-input);
  padding: 12px 14px; margin: 16px 0;
}
.record-note b { color: var(--neutral-90); font-weight: 600 }

.dialog-close {
  position: absolute; right: 14px; top: 14px;
  width: 32px; height: 32px; flex: none;
  display: grid; place-items: center;
  border: 1px solid transparent; border-radius: var(--r-input);
  background: none; color: var(--neutral-75); cursor: pointer;
  transition: background var(--t), border-color var(--t), color var(--t);
}
.dialog-close:hover { background: var(--neutral-30); border-color: var(--neutral-50); color: var(--neutral-100) }
.dialog-close svg { width: 17px; height: 17px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round }

/* Campos do formulário de captura. Duas colunas, com o terceiro campo
   ocupando a linha inteira — e coluna única abaixo de 620px. */
.record-fields { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; margin: 20px 0 16px }
.record-fields label { font-size: 13px; font-weight: 500; color: var(--neutral-90) }
.record-fields label:last-child { grid-column: 1 / -1 }
.relation-new-contact .record-fields label:last-child { grid-column: auto }
.record-fields label small { color: var(--neutral-75); font-weight: 400 }
.record-fields input, .record-fields select, .import-file-field input[type="file"], .review-dialog textarea {
  display: block; width: 100%; margin-top: 6px; min-height: 44px; padding: 0 12px;
  font: inherit; color: var(--neutral-90);
  background: var(--surface-0); border: 1px solid var(--neutral-50);
  border-radius: var(--r-input); transition: border-color var(--t);
}
.review-dialog textarea { min-height: 96px; padding: 10px 12px; line-height: 1.55; resize: vertical }
.record-fields input:hover, .record-fields select:hover, .review-dialog textarea:hover { border-color: var(--neutral-80) }
.record-fields input:focus, .record-fields select:focus, .review-dialog textarea:focus { border-color: var(--neutral-100) }
/* [05/09] "Empresa contratante" é a da sessão e só se lê: o servidor aplica
   a dela por cima de qualquer coisa que viajasse. Fundo de superfície e
   borda que não reage ao passar do mouse dizem isso antes do clique. */
.record-fields input[readonly] { background: var(--surface-50); color: var(--neutral-75); cursor: default }
.record-fields input[readonly]:hover, .record-fields input[readonly]:focus { border-color: var(--neutral-50) }
/* [03/09] Os achados da busca de EMPRESA moram na grade dos campos: ocupam a
   linha inteira logo abaixo do campo, e não uma célula ao lado dele. */
.record-fields .contato-achados { grid-column: 1 / -1; margin-top: 0 }
/* A frase do estado "nenhum vendedor cadastrado" atravessa as duas colunas:
   é explicação do campo acima, não um terceiro campo ao lado dele. */
.record-fields .dialog-note { grid-column: 1 / -1; margin: 0 }
.record-fields .contato-achados[hidden] { display: none }
.import-file-field { display: block; font-size: 13px; font-weight: 500; color: var(--neutral-90); margin: 16px 0 }
.import-file-field small { display: block; margin-top: 6px; color: var(--neutral-75); font-weight: 400 }
.import-file-field input[type="file"] { padding: 10px 12px; min-height: 0 }

/* Consentimento: caixa com filete, para o texto não se confundir com nota. */
.record-check {
  display: flex; align-items: flex-start; gap: 12px;
  border: 1px solid var(--neutral-50); border-radius: var(--r-input);
  background: var(--surface-50); padding: 14px; margin-bottom: 10px;
}
.record-check.compact { background: var(--surface-0) }
.record-check input { width: 17px; height: 17px; margin: 2px 0 0; accent-color: var(--neutral-100); flex: none }
.record-check span { font-size: 12.5px; line-height: 1.5; color: var(--neutral-75) }
.record-check b { display: block; color: var(--neutral-90); font-size: 13px; font-weight: 600; margin-bottom: 2px }

/* Onda da gravação: decorativa (aria-hidden). Uma barra focal, nunca uma
   onda global varrendo a tela — o estado real está no texto abaixo dela. */
.record-visual { display: grid; place-items: center; margin: 12px auto 16px }
.record-bars { display: flex; align-items: center; gap: 4px; height: 64px }
.record-bars i {
  display: block; width: 4px; height: 52%; border-radius: var(--r-pill);
  background: var(--neutral-50); animation: pg-onda 1.1s ease-in-out infinite;
}
.record-bars i.focal { background: var(--neutral-100) }
/* OUVINDO: a altura de cada barra passa a vir do microfone (inline, pelo
   `portal.js`), e a animação de fase sai do caminho — as duas juntas fariam a
   barra pular entre o quadro medido e o quadro animado. Sem AudioContext, ou
   sob "reduzir movimento", a classe nunca entra e vale a animação de sempre. */
.record-visual.ouvindo .record-bars i { animation: none; transition: height 90ms linear }
@keyframes pg-onda { 0%, 100% { height: 18% } 50% { height: 100% } }
@media (prefers-reduced-motion: reduce) { .record-bars i { animation: none; height: 52% } }

#record-timer {
  display: block; text-align: center; font-size: 34px; font-weight: 500;
  letter-spacing: -.02em; font-variant-numeric: tabular-nums; color: var(--neutral-100);
}
.record-status {
  display: inline-block; margin-top: 10px; padding: 3px 10px;
  border-radius: var(--r-badge); font-size: 12px; font-weight: 500;
  background: var(--red-tint); color: var(--red-ink);
}
.record-status.paused { background: var(--amber-tint); color: var(--amber-ink) }
.record-controls { display: flex; justify-content: center; gap: 8px; margin-top: 24px }
.mic-dot { width: 9px; height: 9px; border-radius: var(--r-pill); background: currentColor; flex: none }

.upload-progress {
  height: 5px; overflow: hidden; margin: 16px 0;
  border-radius: var(--r-pill); background: var(--neutral-30);
}
.upload-progress i { display: block; height: 100%; width: 38%; background: var(--neutral-100); animation: upload-moving 1.2s ease-in-out infinite }
.upload-progress.done i { width: 100%; animation: none; background: var(--green-ink) }
.upload-progress.error i { width: 100%; animation: none; background: var(--red-ink) }
@keyframes upload-moving { 50% { transform: translateX(165%) } }
@media (prefers-reduced-motion: reduce) { .upload-progress i { animation: none } }

/* Ícone de desfecho: o estado NUNCA é só a cor — o desenho do ícone muda
   (marca de conferido × cruz), como manda o DESIGN.md §11. */
.result-icon {
  width: 64px; height: 64px; margin: 0 auto 16px;
  display: grid; place-items: center;
  border: 1px solid var(--neutral-50); border-radius: var(--r-card);
}
.result-icon.success { background: var(--green-tint); border-color: var(--green-ink); color: var(--green-ink) }
.result-icon.error { background: var(--red-tint); border-color: var(--red-ink); color: var(--red-ink) }
.result-icon svg { width: 24px; height: 24px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round }

@media (max-width: 560px) {
  .record-shell, .review-dialog > form, .review-dialog > section { padding: 20px }
  .record-fields { grid-template-columns: 1fr }
  .record-controls { flex-direction: column }
  .record-controls button { width: 100%; justify-content: center }
  #visits .visits-toolbar { grid-template-columns: minmax(0, 1fr); }
}

/* ═══ F2 · FILA DE VISITAS E PAINEL DO RECORTE ════════════════════════════
   A tabela e o painel do recorte nasceram no desenho aprovado em 24/08 e
   viviam no `visitas.css`, que a F1 apagou junto com a cascata antiga. A
   MARCAÇÃO não mudou — `monthGroups()` e `painelResumo()` continuam emitindo
   as mesmas classes. O que muda aqui é só o vocabulário: preto/branco/cinza
   frio no lugar do azul-petróleo.

   Regra do DESIGN.md §7 que manda na tabela: cabeçalho em `neutral-30`,
   primeira coluna em semibold, SEM zebra (a separação é a borda de 1px),
   hover de linha em `neutral-30`. */

/* [28/08, noite] As tabelas do Portal seguem a aba "List" do kit Venture, que
   o JP mandou em print e depois estendeu à fila de Visitas: cada linha é um
   CARTÃO solto — borda arredondada inteira, respiro de 8px — e o cabeçalho é
   uma faixa cinza arredondada, separada das linhas. O cartão nasce do
   border-spacing + fundo próprio da célula, sem mudar a marcação. */
.tabela-visitas { overflow-x: auto }
.tabela-visitas .col-selecao { width: 44px; min-width: 44px; text-align: center }
.tabela-visitas .col-selecao input { width: 18px; height: 18px; accent-color: var(--neutral-100); cursor: pointer }
.tabela-visitas .com-selecao { cursor: default }
.tabela-visitas .com-selecao .lp-abrir::after { content: none }
.tabela-visitas table { width: 100%; border-collapse: separate; border-spacing: 0 8px; font-size: 14px }
.tabela-visitas thead th {
  background: var(--neutral-30); color: var(--neutral-75);
  font-size: 12px; font-weight: 500; text-align: left;
  padding: 12px 16px; white-space: nowrap;
}
.tabela-visitas thead th:first-child { border-radius: var(--r-input) 0 0 var(--r-input) }
.tabela-visitas thead th:last-child { border-radius: 0 var(--r-input) var(--r-input) 0 }
.tabela-visitas tbody td {
  padding: 13px 16px; vertical-align: middle; color: var(--neutral-90);
  background: var(--surface-0); transition: background var(--t);
  border-top: 1px solid var(--neutral-40); border-bottom: 1px solid var(--neutral-40);
}
.tabela-visitas tbody td:first-child {
  border-left: 1px solid var(--neutral-40);
  border-radius: var(--r-panel) 0 0 var(--r-panel);
}
.tabela-visitas tbody td:last-child {
  border-right: 1px solid var(--neutral-40);
  border-radius: 0 var(--r-panel) var(--r-panel) 0;
}
.visita-linha { cursor: pointer }
/* O fundo do hover mora no TD: com cartões, o fundo do TR fica atrás. */
.visita-linha:hover td { background: var(--surface-50) }
.visita-linha:focus-visible { outline: 2px solid var(--neutral-100); outline-offset: 2px }

.col-data { white-space: nowrap; font-variant-numeric: tabular-nums; color: var(--neutral-75) }
.col-cliente b { display: block; font-weight: 600; color: var(--neutral-100) }
.col-cliente span { display: block; font-size: 12px; color: var(--neutral-75); margin-top: 1px }
.col-motivo { color: var(--neutral-75); white-space: nowrap }
.col-duracao { white-space: nowrap; font-variant-numeric: tabular-nums; color: var(--neutral-75) }
/* [28/08, noite] O chevron (.col-chev) cedeu lugar à ação desenhada do kit
   (.col-acao/.linha-abrir, regras junto à lista de Contatos) — nas DUAS
   tabelas, a pedido do JP. */

/* [painel v3, fatia 4] ÚLTIMAS VISITAS — a MESMA tabela da casa com o
   modificador do Painel: filete entre as linhas, sem caixa dentro de caixa. A
   linha-cartão que o JP pediu em 28/08 continua na fila de Visitas, em
   Contatos e no Cérebro; dentro do cartão do Painel ela repetia a borda e o
   raio do cartão que a contém, e foi isso que os três juízes chamaram de
   poluído. Escopado em `#card-recentes` — nenhuma outra tela muda. */
/* O respiro que o cartão-linha trazia de graça (borda própria + 8px de
   `border-spacing`) some com o filete: ele volta como padding, alinhado aos
   22px do `.card-head`. */
#card-recentes .tabela-visitas { padding: 4px 22px 10px }
#card-recentes .tabela-visitas table { border-collapse: collapse; border-spacing: 0 }
#card-recentes .tabela-visitas thead th {
  background: none; padding: 10px 12px 10px 0; border-radius: 0;
  border-bottom: 1px solid var(--neutral-40);
}
#card-recentes .tabela-visitas tbody td {
  padding: 13px 12px 13px 0; background: none;
  border: 0; border-top: 1px solid var(--neutral-40); border-radius: 0;
}
#card-recentes .tabela-visitas tbody tr:first-child td { border-top: 0 }
#card-recentes .col-quem { color: var(--neutral-75); white-space: nowrap }
#card-recentes .col-desfecho { white-space: nowrap }
/* O nome da empresa é o alvo de teclado da linha (o `<tr>` deixou de ser
   `role="button"`). Sem o clamp de duas linhas da lista de cobrança, e sem o
   `::after` que cobre a linha inteira: dentro de um `<td>` ele se espalharia
   pelo cartão do Painel, e a linha já é clicável pela delegação. */
#card-recentes .col-cliente .lp-abrir { display: inline; -webkit-line-clamp: none; overflow: visible; font-size: 14px }
#card-recentes .col-cliente .lp-abrir::after { content: none }
/* Ponto colorido em selo neutro não distingue nada (a fatia DESIGN SYSTEM leva
   a regra para a folha inteira; aqui ela nasce escopada). */
#card-recentes .badge.b-neutro i { display: none }
@container painel (max-width: 719px) {
  /* No celular a linha vira grade — e continua sem caixa: o cartão da regra de
     900px da folha desenharia de novo a borda do `#card-recentes`. */
  #card-recentes .tabela-visitas thead { display: none }
  #card-recentes .tabela-visitas tbody tr {
    display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 2px 12px;
    padding: 12px 0; margin: 0; background: none;
    border: 0; border-top: 1px solid var(--neutral-40); border-radius: 0;
  }
  #card-recentes .tabela-visitas tbody tr:first-child { border-top: 0 }
  #card-recentes .tabela-visitas tbody td { padding: 0 }
  #card-recentes .col-data { grid-column: 2; grid-row: 1; text-align: right; font-size: 12px }
  #card-recentes .col-cliente { grid-column: 1; grid-row: 1 }
  #card-recentes .col-quem { grid-column: 1; font-size: 12px }
  #card-recentes .col-desfecho { grid-column: 1 / -1; margin-top: 4px; white-space: normal }
}

/* Fita do roteiro. Oito blocos, um por etapa: cumprida em preto, parcial em
   cinza médio, ausente no filete. É a coluna que se lê VARRENDO — por isso
   ela não pode virar texto nem depender de cor sozinha (a ALTURA muda). */
.mini-roteiro { display: flex; gap: 3px; align-items: flex-end; min-width: 96px }
.mini-roteiro i { flex: 1; height: 6px; border-radius: 1px; background: var(--neutral-50) }
.mini-roteiro i.feita { height: 12px; background: var(--neutral-100) }
.mini-roteiro i.meio { height: 9px; background: var(--neutral-80) }

/* Desfecho: pílula com filete, nunca fundo cheio — o preenchimento está
   reservado ao único botão preto da região (DESIGN.md §7). */
.desfecho {
  display: inline-flex; align-items: center; gap: 6px; white-space: nowrap;
  min-height: 22px; padding: 3px 10px; border-radius: var(--r-badge);
  font-size: 12px; font-weight: 500; border: 1px solid currentColor;
}
.desfecho::before { content: ""; width: 6px; height: 6px; border-radius: var(--r-pill); background: currentColor; flex: none }
.desfecho.ok { color: var(--green-ink); background: var(--green-tint) }
.desfecho.sem-data { color: var(--red-ink); background: var(--red-tint) }
.desfecho.neutro { color: var(--neutral-75); background: var(--surface-50) }

.tabela-rodape {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  padding: 12px 16px; border-top: 1px solid var(--neutral-50);
  font-size: 13px; color: var(--neutral-75);
}
.tabela-rodape button { margin-left: auto }

.link-button {
  background: none; border: 0; padding: 0; cursor: pointer;
  color: var(--neutral-100); font: inherit; font-size: 13px; font-weight: 500;
  text-decoration: underline; text-underline-offset: 3px;
  text-decoration-color: var(--neutral-50); transition: text-decoration-color var(--t);
}
.link-button:hover { text-decoration-color: var(--neutral-100) }

.empty, .honest-empty {
  margin: 0; padding: 40px 20px; text-align: center;
  color: var(--neutral-75); font-size: 14px; line-height: 1.6;
}
/* O vazio por AUSÊNCIA DE LEITURA se distingue do vazio por ausência de dado:
   filete tracejado, porque a informação pode chegar depois. */
.honest-empty { border: 1px dashed var(--neutral-50); border-radius: var(--r-panel) }
/* [28/08] O vazio COMPACTO existia no JS e não existia na folha. O relatório
   emite oito deles — um por etapa do roteiro sem evidência publicada — e cada
   um herdava os 40px de respiro do vazio de tela inteira: a página virava uma
   pilha de caixas tracejadas altas com uma frase curta dentro, que é como o JP
   a fotografou. Aqui o vazio é uma NOTA de linha, não uma tela. */
.honest-empty.compact {
  padding: 10px 12px; text-align: left; font-size: 13px; border-radius: var(--r-input);
}
/* [11/09] E O `.empty.compact` NAO EXISTIA — metade do par estava escrita.
   Quarenta e sete lugares do portal.js pedem `compact`, e os que pedem em
   `.empty` (compromissos da conversa, tarefas do negocio, "Nenhum numero
   conectado") herdavam os 40px CENTRADOS do vazio de tela inteira. Na coluna
   do Contato isso e uma frase centrada em duas linhas dentro de 100px de
   respiro, que foi o que o JP fotografou em 11/09 ("esta tudo jogado").
   O vazio por ausencia de DADO nao tem filete tracejado — e a unica diferenca
   em relacao ao vizinho de cima. */
.empty.compact { padding: 10px 0; text-align: left; font-size: 13px; }
/* [30/08] O VAZIO DAS FILAS DA ABA NEGÓCIOS É UMA LINHA DE STATUS, não uma
   tela. O JP fotografou o defeito: no BOM estado — órfãs resolvidas e toda
   visita já num negócio — a aba abria com duas frases cinzas soltas, centradas,
   ocupando 200px de altura para dizer que não há nada a fazer, e empurrando o
   funil (que é o que a pessoa veio ver) para baixo.

   A regra do vazio honesto continua valendo e é justamente ela que permite
   isto: `.honest-empty` (não consegui LER) segue sendo bloco, porque quem lê
   precisa parar e entender. `.empty` (li, e não há nada) é notícia boa — cabe
   numa linha, com um ponto que a marca como estado e não como parágrafo perdido.

   As duas linhas ficam coladas de propósito: juntas leem como um resumo de
   pendências, que é o que são. */
#orfas > .empty, #negocios-fila > .empty, #duplicatas > .empty {
  display: flex; align-items: center; gap: 8px;
  padding: 7px 0; margin: 0; text-align: left; font-size: 13px;
  color: var(--neutral-75);
}
#orfas > .empty::before, #negocios-fila > .empty::before, #duplicatas > .empty::before {
  content: ""; width: 6px; height: 6px; flex: none;
  border-radius: var(--r-pill); background: var(--green-ink);
}
/* A primeira abre o respiro; a que precede o funil fecha. Sem isto elas
   herdariam a margem do bloco anterior e voltariam a boiar. */
#orfas > .empty { padding-top: 4px }
#negocios-fila > .empty { padding-bottom: 16px }
/* A de duplicatas fecha a tela, então respira acima e não abaixo. */
#duplicatas > .empty { padding-top: 16px }

/* ── Painel do recorte ─────────────────────────────────────────────────── */
/* [30/08] A FILEIRA NAO PODE DEIXAR UM CARTAO SOZINHO. Com `auto-fit` a grade
   escolhia o numero de colunas pela largura do bloco e ignorava que o roteiro
   ocupa DUAS delas: em 1432px de bloco davam CINCO colunas para SEIS unidades,
   e a ultima descia para uma segunda linha sozinha — foi o que o JP fotografou.

   O conserto tem duas partes. A confianca saiu da grade (ela qualifica os
   outros cartoes, nao concorre com eles) e as colunas passaram a ser CONTADAS
   em vez de deduzidas, em degraus que sempre fecham a linha: 1 · 3 (roteiro por
   cima) · 5 (roteiro ocupando 2 das 5). Contar e o unico jeito de garantir a
   fileira, porque `auto-fit` nao sabe que um item vale por dois.

   A consulta e do CONTAINER e nao da janela (regra 3 da politica de layout): a
   mesma janela da blocos de largura diferente com a barra lateral aberta ou
   recolhida, e uma `@media` acertaria o caso errado.

   O degrau da fileira desceu de 1300 para 940 em 02/09, a pedido do JP: na
   largura em que ele trabalha (container ~1176) a grade caia no modo de 3
   colunas — roteiro por cima e as tres metricas embaixo — e ele lia isso como
   layout de celular; queria os quatro lado a lado. 940 e o menor container em
   que os quatro cabem sem cortar palavra nem transbordar: MEDIDO no navegador,
   cartao de metrica em 176px e roteiro em 369px a 949, com zero elemento cujo
   scrollWidth passasse o clientWidth. Abaixo de 940 a grade volta a 3 colunas,
   porque cinco cartoes de ~130px espremem o numero e a legenda.

   O PRECO da fileira mais cedo, dito: ate ~1330 de container o cartao do
   roteiro fica com menos de 470px de largura de CONSULTA (a caixa de conteudo,
   ja descontados os 36px de padding) e o grafico das 8 etapas DEITA — uma linha
   por etapa, a forma estreita ja desenhada para ele (regra 2 da politica), nao
   um defeito. So acima disso o roteiro tem largura para as barras em pe. Nas
   telas bem largas nada muda; das medias para baixo, a fileira troca as barras
   verticais por horizontais em vez de deixar mais um cartao sozinho. */
#visits-resumo { container-type: inline-size; container-name: resumo }
.resumo-grid {
  display: grid; grid-template-columns: minmax(0, 1fr);
  gap: 16px; margin-bottom: 20px;
}
.resumo-card {
  background: var(--surface-0); border: 1px solid var(--neutral-50);
  border-radius: var(--r-card); padding: 18px;
  display: flex; flex-direction: column;
}
.resumo-card .legenda { font-size: 12px; color: var(--neutral-80); margin: 0 0 10px }
.resumo-card .numero {
  display: block; font-size: 28px; font-weight: 500; line-height: 1;
  letter-spacing: -.02em; color: var(--neutral-100); font-variant-numeric: tabular-nums;
}

/* [28/08] BANDA DO GRÁFICO — a régua que faltava. Os cartões do resumo têm a
   mesma anatomia (título · número · legenda · gráfico · nota), mas cada
   gráfico tinha altura própria: a barra da fala ocupa 8px e o histograma de
   duração 44px. Medido do topo de cada cartão, a nota caía em 112 · 126 ·
   148 · 112 — quatro linhas diferentes numa fileira de irmãos, que é o
   desalinho que se vê antes de conseguir nomear.

   A banda fixa em 44px (a altura do maior gráfico) faz os quatro gráficos
   ocuparem a MESMA faixa vertical; a nota ancorada no rodapé por
   `margin-top: auto` fecha a fileira em baixo, mesmo quando a grade estica
   os cartões para a altura do mais alto. O gráfico centra na banda; o
   histograma se estica, porque a leitura dele é a forma da distribuição e
   ela nasce da linha de base. */
.figura {
  display: flex; align-items: center; min-height: 44px; margin: 10px 0;
}
/* Escopado no cartão de propósito: `.figura > *` sozinho empata em
   especificidade com `.histograma`/`.trilho-fala`, que vêm DEPOIS no arquivo
   e ganhariam o desempate — foi o que deixou a banda da Duração com 64px na
   primeira medição, exatamente o defeito que esta regra existe para tirar. */
.resumo-card .figura > * { flex: 1; margin: 0 }
.resumo-card .figura .rosca { flex: none }
.resumo-card .figura .histograma { align-self: stretch }

.resumo-card .nota {
  margin: 0; margin-top: auto; padding-top: 10px;
  font-size: 12.5px; color: var(--neutral-75); line-height: 1.5;
}
.resumo-card .nota b { color: var(--neutral-90); font-weight: 600 }
.resumo-roteiro { grid-column: 1 / -1; container-type: inline-size; container-name: roteiro }
@container resumo (min-width: 660px) {
  .resumo-grid { grid-template-columns: repeat(3, minmax(0, 1fr)) }
}
@container resumo (min-width: 940px) {
  .resumo-grid { grid-template-columns: repeat(5, minmax(0, 1fr)) }
  .resumo-roteiro { grid-column: span 2 }
}

/* Gráfico das 8 etapas. A magnitude chega como `--v` e é o CSS que decide se
   ela vira ALTURA (em pé) ou LARGURA (deitado) — por container query, não por
   viewport: o cartão pode ser mais estreito no desktop de três colunas do que
   no celular. É a regra 3 da política de layout responsivo do vault. */
.etapas { display: grid; grid-auto-flow: column; gap: var(--r-badge); align-items: end; min-height: 108px }
.etapas .etapa { display: flex; flex-direction: column; align-items: center; justify-content: flex-end; gap: 6px }
.etapas .etapa b { font-size: 12px; font-weight: 500; color: var(--neutral-90); font-variant-numeric: tabular-nums }
.etapas .barra {
  width: 100%; border-radius: 2px 2px 0 0; background: var(--neutral-100);
  height: calc(8px + var(--v, 0) * 68px);
}
.etapas .barra.fraca { background: var(--neutral-50) }
.etapas .etapa small {
  font-size: 11px; color: var(--neutral-75); text-align: center; line-height: 1.2;
  /* Nunca cortar palavra: regra 1 da política de layout responsivo. */
  overflow-wrap: normal; word-break: keep-all; hyphens: none;
}
/* Apertou: o gráfico DEITA — uma linha por etapa, rótulo à esquerda. Muda de
   FORMA em vez de encolher a fonte (regra 2 da política). */
@container roteiro (max-width: 470px) {
  .etapas { grid-auto-flow: row; gap: 4px; min-height: 0 }
  .etapas .etapa { display: grid; grid-template-columns: 78px 1fr 26px; align-items: center; min-height: 22px; gap: 8px }
  .etapas .etapa small { grid-area: 1 / 1; text-align: left }
  .etapas .barra { grid-area: 1 / 2; height: 12px; width: calc(4% + var(--v, 0) * 96%); border-radius: 2px }
  .etapas .etapa b { grid-area: 1 / 3; text-align: right }
}

/* Trilhos de proporção: fala do cliente e faixas de confiança. */
.trilho-fala, .trilho-conf { display: flex; height: 8px; border-radius: var(--r-pill); overflow: hidden; background: var(--neutral-40); margin: 10px 0 }
.trilho-fala i, .trilho-conf i { display: block; height: 100% }

/* [28/08] OS DOIS LADOS DA CONVERSA, PINTADOS. Pedido do JP: "a barra podia
   estar pintada mostrando o que era cliente e o que era Você, melhor que só
   escrito embaixo".

   E havia um defeito por trás do pedido: o JS emitia UM segmento só, mas a
   folha pintava `:first-child` de preto e `:last-child` de cinza — com um
   filho único as duas regras caíam no mesmo elemento, e vencia a segunda por
   vir depois. A barra ficava cinza-claro sobre trilho cinza, quase invisível,
   que é como ela aparece no print do JP. Cor por CLASSE não tem esse problema:
   o segmento diz quem ele é, em vez de depender da posição. */
.trilho-fala i.parte-cliente { background: var(--neutral-100) }
.trilho-fala i.parte-voce { background: var(--neutral-50) }

/* A legenda amarra cor a nome: §11 proíbe a cor carregar o dado sozinha, e
   sem isto a barra bicolor vira adivinhação de qual lado é quem. */
.chave-fala { display: inline-flex; align-items: center; gap: 6px; margin-right: 14px; white-space: nowrap }
.chave-fala i { width: 8px; height: 8px; flex: none; border-radius: var(--r-pill) }
.chave-fala i.parte-cliente { background: var(--neutral-100) }
.chave-fala i.parte-voce { background: var(--neutral-50) }
.trilho-conf i.alta { background: var(--neutral-100) }
.trilho-conf i.media { background: var(--neutral-80) }
.trilho-conf i.baixa { background: var(--neutral-50) }
.trilho-conf i.sem { background: var(--neutral-40) }

/* [30/08] A CONFIANCA E RODAPE DO PAINEL, NAO O QUINTO CARTAO. Ela nao responde
   "como foram as visitas" como os outros quatro — responde "quanto do que esta
   acima da para acreditar". Peer de cartao, ela competia pelo mesmo olhar e
   ainda estourava a fileira; como faixa embaixo, qualifica todos de uma vez.

   A barra NAO ocupa a largura inteira, e isso foi medido: esticada nos 1376px
   do bloco, um recorte com tudo em confianca alta virava um retangulo preto de
   ponta a ponta — o bloco de tinta mais pesado de uma tela onde ela e nota de
   rodape. Em ~340px ela ainda mostra um trecho de 5% com 17px, que era o
   motivo de tirar ela do cartao de 292px, sem gritar mais que o dado.

   Sem borda de proposito: contraste de superficie OU borda, nunca os dois
   (§5). O branco sobre o `--canvas` ja separa, e a ausencia de borda e o que
   distingue a faixa dos cartoes acima dela. */
.resumo-confianca {
  display: flex; align-items: center; gap: 16px; flex-wrap: wrap;
  background: var(--surface-0); border-radius: var(--r-panel);
  padding: 12px 16px; margin: -4px 0 20px;
}
.resumo-confianca .trilho-conf { flex: 0 1 340px; min-width: 150px; margin: 0 }
.resumo-confianca p {
  flex: 1 1 340px;
  margin: 0; font-size: 12.5px; line-height: 1.5; color: var(--neutral-80);
}
.resumo-confianca b { color: var(--neutral-90); font-weight: 600 }

/* [28/08] A `.rosca-linha` foi removida da marcação: a rosca desceu para a
   banda do gráfico e o número subiu para o lugar que ele ocupa nos irmãos.
   Duas regras disputavam essa linha — `.resumo-rosca .rosca-linha` com
   `align-items: baseline` vencia a `.rosca-linha` com `center` por ter uma
   classe a mais —, e a baseline de um SVG inline é a BORDA DE BAIXO: o
   número pendia no pé do anel em vez de centrar. O defeito não estava no
   valor de nenhuma das duas; estava em existirem duas. */
.resumo-rosca .selo { font-size: 12px; font-weight: 500; color: var(--neutral-75) }

.histograma { display: flex; align-items: flex-end; gap: 3px; height: 44px; margin: 10px 0 }
.histograma i { flex: 1; background: var(--neutral-40); border-radius: 1px 1px 0 0; min-height: 2px; transition: background var(--t) }
.histograma i.focal { background: var(--neutral-100) }
/* As barras passaram a responder (28/08): o JP perguntou "não entendi as
   barras subindo e descendo", e um gráfico que não reage não convida a
   descobrir. Escurecer sob o cursor mostra que há algo ali; a dica diz a
   faixa e quantas visitas caíram nela. O foco é alcançável por Tab, então
   quem não usa mouse chega à mesma informação. */
.histograma i:hover, .histograma i:focus-visible { background: var(--neutral-80) }
.histograma i:focus-visible { outline: 2px solid var(--neutral-100); outline-offset: 2px }

/* Termômetro de interesse: TRÊS barras, e quantas acendem é o dado — a cor
   sozinha nunca carrega o estado (DESIGN.md §11). */
.termo { display: inline-flex; align-items: center; gap: 7px; font-size: 12px; color: var(--neutral-75) }
.termo .barras { display: inline-flex; gap: 2px; align-items: flex-end }
.termo .barras i { width: 3px; height: 8px; border-radius: 1px; background: var(--neutral-50) }
.termo.alta .barras i, .termo.media .barras i:nth-child(-n+2), .termo.baixa .barras i:first-child { background: var(--neutral-100) }
.termo.alta .barras i:nth-child(2) { height: 11px }
.termo.alta .barras i:nth-child(3) { height: 14px }

@media (max-width: 900px) {
  /* Tabela vira lista: rótulo acima do valor, sem rolagem lateral (regra 4). */
  .tabela-visitas thead { display: none }
  .tabela-visitas table { border-spacing: 0 }
  /* No celular o cartão passa a morar no TR (a linha vira grade e as células
     perdem o desenho de tabela). */
  .tabela-visitas tbody tr {
    display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 4px 12px;
    padding: 14px 16px; background: var(--surface-0);
    border: 1px solid var(--neutral-40); border-radius: var(--r-panel);
    margin-bottom: 8px;
  }
  .tabela-visitas tbody td { width: auto; min-width: 0; padding: 0; border: 0; background: none; border-radius: 0 }
  /* As pontas têm regra própria no desktop (borda e raio do cartão) com
     especificidade maior que a do reset acima — precisam do próprio reset. */
  .tabela-visitas tbody td:first-child,
  .tabela-visitas tbody td:last-child { border: 0; border-radius: 0 }
  .col-data { grid-column: 2; text-align: right; font-size: 12px }
  .col-cliente { grid-column: 1; grid-row: 1 }
  .col-motivo, .col-duracao { grid-column: 1; font-size: 12.5px }
  .col-roteiro { grid-column: 1 / -1; margin-top: 6px }
  .col-desfecho { grid-column: 1 / -1; margin-top: 4px }
  /* A linha inteira é o alvo; o botão desenhado repetiria o próprio cartão. */
  .col-acao { display: none }
  .tabela-visitas .com-selecao .col-selecao { grid-column: 1; grid-row: 1; min-width: 0; width: auto; text-align: left }
  .tabela-visitas .com-selecao .col-cliente { grid-column: 1 / -1; grid-row: 2 }
}

/* Argumento recomendado dentro do cartao de objecao. O Analisador devolve, no
   mesmo item, a objecao E a prova a levar — mostrar so a objecao deixaria o
   vendedor com o problema e sem a municao. */
/* [13/09] A faixa passou a carregar tambem a CITACAO do que foi dito, que e
   texto de terceiro e nao tem teto de tamanho. Duas linhas e o corte, no mesmo
   molde de `.lp-abrir`; `overflow-wrap: normal` e o que garante que a quebra
   caia entre palavras, nunca no meio de uma. */
.tk-arg {
  margin: 6px 0 0; font-size: 12px; line-height: 1.5; color: var(--neutral-75);
  padding-left: 10px; border-left: 1px solid var(--neutral-50);
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2;
  overflow: hidden; overflow-wrap: normal;
}

/* Prévia do texto que sai no canal. `<pre>` preserva a quebra de linha do
   digest — é justamente por isso que ele transborda: a linha mais longa tem
   462px num cartão de 350px, medido a 390px de viewport.

   A regra do DESIGN.md §10 é que conteúdo largo role DENTRO do próprio
   container, nunca empurrando a página de lado. Aqui vale literalmente: o
   texto é para conferir antes de enviar, e reflowar destruiria o alinhamento
   que ele tem no canal. */
.digest-preview {
  margin-top: 16px; border: 1px solid var(--neutral-50);
  border-radius: var(--r-panel); background: var(--surface-0);
}
.digest-preview summary {
  padding: 12px 16px; cursor: pointer;
  font-size: 13px; font-weight: 500; color: var(--neutral-90);
}
.digest-preview summary:hover { color: var(--neutral-100) }
.digest-preview pre {
  margin: 0; padding: 0 16px 16px; overflow-x: auto;
  font-size: 12px; line-height: 1.6; color: var(--neutral-75);
}

/* ═══ TELA DE ACESSO ══════════════════════════════════════════════════════
   No mockup o `.login-card` vive DENTRO de uma `.moldura` — janela de
   navegador desenhada, com barra de endereço falsa — e é ela que dá a
   superfície. A moldura não veio para o produto (barra de endereço desenhada
   numa página real é a forma clássica de phishing), então o cartão precisa da
   própria superfície. Sombra aqui é legítima: é o único objeto do palco, e
   flutua sobre a malha (§5). */
.palco > .login-card {
  position: relative; z-index: 1;
  width: 100%; max-width: 440px;
  background: var(--surface-0);
  border: 1px solid var(--neutral-50);
  border-radius: var(--r-card);
  box-shadow: var(--shadow-float);
}
/* A folha do v4 mira `h2` porque no mockup a tela de acesso é uma seção entre
   treze. Como página, o título dela é `h1` — e o `h1` é que carrega o
   documento para leitor de tela. Mesma medida, os dois seletores. */
.login-card h1, .login-card h2 { font-size: 24px; font-weight: 500; letter-spacing: -.015em; }
.login-card .eyebrow { margin-bottom: 6px; }
.hex-mesh { color: var(--neutral-50); }

/* Erro de credencial. Marcador ALÉM da cor (§11): o filete grosso à esquerda
   e o texto dizem o que houve sem depender de perceber o vermelho. */
.login-error {
  margin-bottom: 18px; padding: 12px 14px;
  border: 1px solid var(--red-ink); border-left-width: 3px;
  border-radius: var(--r-input);
  background: var(--red-tint); color: var(--red-ink);
  font-size: 13px; line-height: 1.5;
}
.login-hint {
  margin-top: 18px; font-size: 12.5px; line-height: 1.55;
  color: var(--neutral-75); text-align: center;
}
.login-hint a { color: var(--neutral-90); text-decoration: underline; text-underline-offset: 3px;
  text-decoration-color: var(--neutral-50); transition: text-decoration-color var(--t); }
.login-hint a:hover { text-decoration-color: var(--neutral-100); }

/* Rodapé de políticas. Filete separando do formulário, e não caixa: o cartão
   já é a superfície, e uma segunda caixa dentro dele disputaria com o campo
   de senha a atenção de quem veio entrar. */
.login-legal {
  margin-top: 22px; padding-top: 16px;
  border-top: 1px solid var(--neutral-50);
  display: flex; flex-wrap: wrap; justify-content: center; gap: 6px 14px;
  font-size: 11.5px; line-height: 1.5;
}
.login-legal a {
  color: var(--neutral-75); text-decoration: underline; text-underline-offset: 3px;
  text-decoration-color: var(--neutral-50);
  transition: color var(--t), text-decoration-color var(--t);
}
.login-legal a:hover { color: var(--neutral-90); text-decoration-color: var(--neutral-90); }

/* ═══ PRIMEIROS PASSOS (`/comecar`) ═══════════════════════════════════════
   Irmã da tela de acesso: mesmo palco, mesmo cartão, mesma malha. O que muda
   é a largura — cinco passos com título, estado, explicação e duas ações não
   cabem nos 440px de um formulário de login sem quebrar palavra.

   O corte do desenho é `@container`, e não `@media`: o que decide se o ícone
   fica ao lado ou acima é a largura DO CARTÃO, que já é limitada por
   `max-width` antes de a janela chegar a qualquer breakpoint. Um `@media`
   aqui mediria a coisa errada — e ainda teria de entrar no índice de cortes
   do topo desta folha. */
.palco > .comecar-card { max-width: 680px; container-type: inline-size; container-name: comeco; }
.comecar-card .sub { margin-bottom: 22px; }

.passos { list-style: none; display: grid; gap: 10px; }
.passo {
  display: grid; grid-template-columns: 28px minmax(0, 1fr); gap: 12px;
  align-items: start; padding: 14px 16px;
  border: 1px solid var(--neutral-50); border-radius: var(--r-panel);
  background: var(--surface-0);
}
/* MARCADOR ALÉM DA COR (§11): o ícone e a palavra dizem o estado; a tinta
   apenas reforça. Um passo "não consegui ler" tem de ser distinguível de "a
   fazer" com a folha em escala de cinza. */
.passo-ico {
  width: 28px; height: 28px; border-radius: var(--r-pill);
  display: grid; place-items: center; flex: none;
  border: 1px solid var(--neutral-50); background: var(--neutral-30); color: var(--neutral-75);
}
.passo-ico svg { width: 15px; height: 15px; fill: none; stroke: currentColor; stroke-width: 2; }
.passo-corpo { min-width: 0; display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px; }
.passo-corpo b { font-size: 14.5px; color: var(--neutral-100); }
.passo-estado {
  font-size: 11px; font-weight: 500; letter-spacing: .06em; text-transform: uppercase;
  color: var(--neutral-75);
}
.passo-corpo .det { flex: 1 0 100%; margin: 0; font-size: 12.5px; color: var(--neutral-75); }
.passo-acoes { flex: 1 0 100%; display: flex; flex-wrap: wrap; gap: 8px; margin-top: 4px; }
/* `.login-card .btn` estica para 100% — é o botão de um formulário de login.
   Aqui são até dois por passo, e esticados viram uma coluna de blocos pretos
   e brancos que some com a leitura da lista. */
.comecar-card .passo-acoes .btn, .comecar-card .login-hint .btn {
  width: auto; min-height: 36px; padding: 0 14px; font-size: 13px; text-decoration: none;
}
/* MEDIDO A 390px: a regra acima vencia o piso de 44px do §10 e os botões dos
   passos saíam com 36 — abaixo do alvo de toque. A largura continua `auto`
   (dois botões esticados por passo viram uma coluna de blocos que some com a
   leitura da lista); o que volta é só a altura. 860 já está no índice de
   cortes do topo da folha. */
@media (max-width: 860px) {
.comecar-card .passo-acoes .btn, .comecar-card .login-hint .btn { min-height: 44px; }
}
.passo.feito { background: var(--green-tint); border-color: var(--green-tint); }
.passo.feito .passo-ico { background: var(--green-ink); border-color: var(--green-ink); color: var(--neutral-0); }
.passo.feito .passo-estado { color: var(--green-ink); }
.passo.pendente { border-color: var(--neutral-90); }
.passo.pendente .passo-ico { border-color: var(--neutral-90); color: var(--neutral-90); }
/* "Não li" NÃO usa vermelho: não houve erro do cliente nem falha dele para
   corrigir — é o Portal admitindo que não sabe. Âmbar é a tinta que o resto
   do Portal já usa para "atenção, não conclusão". */
.passo.desconhecido { background: var(--amber-tint); border-color: var(--amber-tint); }
.passo.desconhecido .passo-ico { background: var(--surface-0); border-color: var(--amber-ink); color: var(--amber-ink); }
.passo.desconhecido .passo-estado { color: var(--amber-ink); }
.comecar-card .login-hint { margin-top: 20px; }
.comecar-pronto { margin-top: 22px; display: grid; justify-items: center; gap: 10px; }
/* A frase que fecha a lista. `<b>` porque é a única afirmação da tela sobre o
   conjunto — os passos já disseram cada um o seu. */
.comecar-fim { font-size: 14px; color: var(--neutral-100); }
/* MEDIDO A 390px: o cartão fica com 358, o interior do `.login-card` com 294 e
   o passo com 262 para a grade — a coluna do texto ainda recebe 222px, que
   comporta "Cadastre quem vai gravar" numa linha. Empilhar ali só somava
   altura e soltava a bolinha verde acima do título. O empilhamento fica como
   rede de segurança para contêiner realmente estreito (barra lateral, coluna
   futura), não como o desenho do telefone. */
@container comeco (max-width: 240px) {
  .passo { grid-template-columns: minmax(0, 1fr); }
  .passo-ico { margin-bottom: 2px; }
}
/* O guia continua alcançável depois que sai do caminho do login. Rodapé da
   barra, LINHA PRÓPRIA acima do bloco de identidade: medido a 1280, dentro do
   `.nav-foot` (que é uma linha flex com nome, escopo e Sair) ele espremia os
   três e quebrava "Primeiros passos" em duas linhas. */
.link-comecar {
  display: flex; align-items: center; gap: 10px; min-height: 38px;
  margin-bottom: 4px; padding: 8px 10px;
  border-radius: var(--r-input); color: var(--neutral-75); font-size: 13px;
  white-space: nowrap; text-decoration: none;
  transition: background var(--t), color var(--t);
}
.link-comecar:hover { background: var(--neutral-30); color: var(--neutral-100); }
.link-comecar svg { width: 16px; height: 16px; flex: none; fill: none; stroke: currentColor; stroke-width: 1.7; }

/* ═══ INTEGRAÇÕES E ADMINISTRAÇÃO ═════════════════════════════════════════
   Duas telas que o v4 não redesenhou (o mockup tem "Integrações" como grade
   de cards de conexão; a nossa é uma conexão só, a Plaud, com token e
   importação). O que elas precisam é o vocabulário novo aplicado à marcação
   que já existe — não um redesenho.

   `#sources` vive atrás de `{% if features.sources %}` e só é servida com
   token Plaud configurado, então não dá para conferir no ambiente de
   demonstração. As regras vêm do que a folha antiga fazia, traduzidas. */
.admin-form label { grid-column: auto !important }
.admin-form select {
  width: 100%; min-height: 44px; padding: 0 12px; font: inherit;
  color: var(--neutral-90); background: var(--surface-0);
  border: 1px solid var(--neutral-50); border-radius: var(--r-input);
}
.admin-form select:hover { border-color: var(--neutral-80) }
.admin-form select:focus { border-color: var(--neutral-100) }
.admin-form button { grid-column: 1 / -1; justify-self: start }

/* ═══ FONTES DE REUNIÃO · PLAUD (revisão de 03/09) ════════════════════════
   O painel da conexão é o primeiro bloco da tela e o único que existe nos
   cinco estados. Ele empilha por padrão — sobrescrito, título, frase, quem
   resolve, controles — e só ganha a coluna de ações à direita quando a frase
   ainda cabe sem apertar. Nada de sombra em repouso, nada de cor nova. */
.source-connection { display: flex; flex-wrap: wrap; gap: 16px; justify-content: space-between; align-items: flex-start }
/* `:first-child` e não `> div`: `.source-actions` também é filho direto, e
   com o mesmo `flex-grow` o botão de desconectar ocupava metade do painel. */
.source-connection > div:first-child { flex: 1 1 320px; min-width: 0 }
.source-connection h3 { margin: 6px 0; font-size: 17px; font-weight: 500; color: var(--neutral-100) }
.source-connection p { color: var(--neutral-75); font-size: 14px; line-height: 1.55; max-width: 62ch }
.source-connection .badge { margin-top: 8px }
.source-connection .skeleton-card { margin-top: 12px; max-width: 62ch }
/* Quem resolve não é decoração: é a linha que transforma "está quebrado" em
   "é com fulano". Fica ao lado da frase de causa, um degrau acima dela. */
.plaud-quem-resolve { margin-top: 10px; font-size: 13px; font-weight: 500; color: var(--neutral-90) }
.source-connection .honest-empty { margin-top: 12px }
.source-actions { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 16px }
.source-connection > .source-actions { flex: 0 0 auto; margin-top: 0 }
/* Busca e atualizar na MESMA linha em toda largura: a regra geral de
   `.search-field` manda `flex-basis: 100%` em tela estreita, e o botão caía
   para a linha de baixo — dois gestos onde cabe um. */
.source-toolbar { margin-top: 24px; display: flex; align-items: center; gap: 8px; flex-wrap: nowrap }
.source-toolbar .search-field { flex: 1 1 auto; flex-basis: auto; max-width: 440px }
.source-toolbar .refresh { flex: none }
/* O bloco de gravações é filho da resposta do bloco de conexão: precisa de um
   degrau de respiro para não ler como continuação do painel de cima. */
#plaud-recordings { margin-top: 32px }
#plaud-recordings .section-heading { margin-bottom: 4px }

/* O cartão de gravação: nome e data à esquerda, UM controle à direita. A ação
   é única por cartão de propósito — grade repetida não leva botão preto, e
   não leva dois caminhos concorrentes. */
.plaud-file-acao { display: flex; align-items: center; gap: 8px; flex: none; flex-wrap: nowrap }
.plaud-file-acao .badge { white-space: nowrap }

/* Bloco de administração: recolhido, e por isso precisa de respiro próprio
   quando abre — dentro dele vive uma credencial. */
.source-admin { padding: 16px 20px }
.source-admin > summary { cursor: pointer; font-size: 14px; font-weight: 500; color: var(--neutral-100) }
.source-admin[open] > summary { margin-bottom: 16px }
.source-admin .field { max-width: 620px }
.plaud-dica { margin-top: 8px; font-size: 12.5px; color: var(--neutral-75); line-height: 1.5 }
.plaud-dica[hidden] { display: none }

/* Diálogo do destino: uma coluna por padrão, porque o campo de Empresa carrega
   a lista de resultados embaixo e uma lista dividida ao meio não se lê. */
#plaud-import-dialog { width: min(560px, calc(100vw - 32px)) }
#plaud-disconnect-dialog { width: min(440px, calc(100vw - 32px)) }
.plaud-campos { display: grid; grid-template-columns: 1fr; gap: 14px; margin: 18px 0 16px }
.plaud-campos .relation-results { max-height: 210px; overflow: auto }
.plaud-campos textarea, .plaud-campos input, .plaud-campos select { min-height: 44px }
#plaud-import-dialog .record-check { margin-bottom: 12px }

/* ≥1024: Vendedor e Cliente dividem a linha; Empresa e sua lista continuam
   inteiras. A régua é a LARGURA DO DIÁLOGO, que é o contêiner destes campos —
   a barra lateral do Portal não muda o tamanho de um modal. */
@media (min-width: 1024px) {
  .plaud-campos { grid-template-columns: 1fr 1fr }
  .plaud-campo-largo { grid-column: 1 / -1 }
}
@media (max-width: 560px) {
  /* Quando não cabe, o layout muda de forma — a fonte não encolhe, e nenhuma
     palavra quebra no meio.

     O `flex: 0 1 auto` do filho NÃO é detalhe: em coluna, o `flex-basis:
     320px` passa a valer para a ALTURA, e o bloco de conteúdo travava em
     320px com vão vazio até o botão — medido a 375 e 390px antes desta linha.

     E o seletor tem de ser `> div:first-child`, o MESMO da regra incondicional
     lá em cima. Escrito `> div`, esta regra pesa (0,1,1) contra os (0,2,1) de
     `> div:first-child` e PERDE por especificidade — a media query não chega
     a valer, e o defeito que ela descreve continua na tela. Igualadas as
     especificidades, quem decide é a ordem, e esta vem depois. */
  .source-connection { flex-direction: column; align-items: stretch }
  .source-connection > div:first-child { flex: 0 1 auto }
  .source-actions { width: 100% }
  .source-actions .btn { flex: 1 1 100%; min-height: 44px }
  .plaud-file-acao { width: 100% }
  .plaud-file-acao .btn { flex: 1 1 100%; min-height: 44px }
  /* Alvo de toque: a régua da casa é 44px em mobile, e a barra de busca e o
     botão redondo de atualizar nasciam com 40. */
  /* A busca ocupa a linha; o atualizar fica AO LADO, não embaixo. A regra
     geral de `.search-field` manda `flex-basis: 100%` em telas estreitas, o
     que empurrava o botão para a linha seguinte e dava dois gestos onde cabe
     um. */
  .source-toolbar .search-field { max-width: none }
  .plaud-file-acao { flex-wrap: wrap }
  .source-toolbar .search-field input, .source-toolbar .refresh { min-height: 44px; height: 44px }
  .source-toolbar .refresh { width: 44px; flex: none }
  .dialog-actions .secondary, #plaud-import-confirm { flex: 1 1 0; min-height: 44px }
}
/* O token vem colado de outro lugar e é longo: `<details>` para não ocupar a
   tela toda em repouso, e mono no textarea para conferir caractere a
   caractere — um `l` e um `1` errados aqui derrubam a integração inteira. */
.source-token-import { flex-basis: 100%; font-size: 13px; color: var(--neutral-75) }
.source-token-import summary { cursor: pointer; color: var(--neutral-90); font-weight: 500 }
.source-token-import textarea {
  width: 100%; margin: 8px 0; padding: 10px 12px; min-height: 88px;
  font-family: ui-monospace, "SFMono-Regular", Consolas, monospace; font-size: 12.5px;
  color: var(--neutral-90); background: var(--surface-0);
  border: 1px solid var(--neutral-50); border-radius: var(--r-input); resize: vertical;
}
.source-token-import textarea:focus { border-color: var(--neutral-100) }

.admin-list, .audit-list {
  background: var(--surface-0); border: 1px solid var(--neutral-50);
  border-radius: var(--r-card); padding: 16px; margin-top: 16px;
}

/* ═══ CORREÇÕES DE 28/08 — a família que a extração da F0 deixou de fora ═══
   Sete grupos de classes que o `portal.js` e o `index.html` emitem e que
   ficaram SEM REGRA quando o `pergor.css` saiu da cascata. O sintoma mais
   vistoso foi a "bola gigantesca" na aba Visitas: o `<svg class="rosca">` sem
   largura estica até o contêiner, e `<circle>` sem `fill` nasce PRETO — a
   rosca de 64px virou um disco preto de 224px. Medido no navegador antes da
   correção. Os outros seis grupos quebravam mais quieto: a toolbar de busca
   e filtros virava botão pelado, o esqueleto de carregamento ficava
   invisível, a contagem do recorte perdia a tipografia. */

/* Os 4 cartões de métrica lado a lado. O mockup tinha TRÊS métricas e a
   grade veio com repeat(3) — o quarto cartão quebrava para a segunda linha.
   O Pergor tem quatro: Visitas, Relatórios, Em fluxo, Oportunidades. */
.stat-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); }
@media (max-width: 1180px) { .stat-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 860px) { .stat-grid { grid-template-columns: 1fr; } }

/* A rosca de "com próximo passo". Tamanho FIXO — é um mostrador, não um
   gráfico que cresce com o cartão — e traço em vez de preenchimento:
   `.trilho` é o anel de fundo, `.arco` é a fração preenchida via
   stroke-dasharray que o portal.js calcula. */
.rosca { width: 44px; height: 44px; flex: none; }
.rosca circle { fill: none; stroke-width: 8; }
.rosca .trilho { stroke: var(--neutral-40); }
.rosca .arco { stroke: var(--neutral-100); stroke-linecap: round; }

/* Legenda genérica de gráfico: também usada no card do Painel, que não é
   `.resumo-card` — a regra escopada deixava a do gráfico sem estilo. */
.legenda { font-size: 12px; color: var(--neutral-80); margin: 0 0 10px; }

/* Toolbars gerais. */
.toolbar { display: flex; gap: 10px; margin-bottom: 16px; flex-wrap: wrap; align-items: center; }
.search-field { position: relative; flex: 1; max-width: 440px; display: flex; align-items: center; }
.search-field svg {
  position: absolute; left: 12px; width: 16px; height: 16px; pointer-events: none;
  fill: none; stroke: var(--neutral-80); stroke-width: 1.8; stroke-linecap: round;
}
.search-field input {
  width: 100%; min-height: 40px; padding: 0 12px 0 38px; font: inherit;
  color: var(--neutral-90); background: var(--neutral-30);
  border: 1px solid transparent; border-radius: var(--r-input);
  transition: background var(--t), border-color var(--t);
}
.search-field input:hover { background: var(--neutral-40); }
.search-field input:focus { background: var(--surface-0); border-color: var(--neutral-100); }

/* Grupo de filtros: pílula segmentada. O ativo é PRETO — é seleção, não é o
   botão primário da tela (o §7 fala de ação; isto é estado de recorte). */
.filters {
  display: flex; gap: 2px; padding: 3px;
  background: var(--surface-0); border: 1px solid var(--neutral-50);
  border-radius: var(--r-input); flex-wrap: wrap;
}
.filters button {
  border: 0; background: transparent; cursor: pointer; font: inherit;
  font-size: 13px; font-weight: 500; color: var(--neutral-75);
  padding: 6px 12px; border-radius: 6px;
  transition: background var(--t), color var(--t);
}
.filters button:hover { background: var(--neutral-30); color: var(--neutral-100); }
.filters button.active { background: var(--neutral-100); color: var(--neutral-0); }

/* [29/08] Campo de filtro da toolbar — hoje só o de vendedor. É `select` e não
   pill porque a equipe é lista aberta: pill serve a estado fixo, e vinte
   vendedores em pills viram uma parede. Os 40px são os dos vizinhos
   (busca e pills), medidos — sem isso a toolbar lê como duas alturas. */
.filtro-campo { display: inline-flex; }
.filtro-campo[hidden] { display: none; }
.filtro-campo select {
  /* `min-height` explícito: o `select` genérico do §7 impõe 44px de alvo de
     toque, e min-height vence height — sem isto o campo fica 4px mais alto que
     a busca e os pills ao lado, e a toolbar lê como duas alturas. Os 44px
     voltam no recorte de toque, logo abaixo. */
  height: 40px; min-height: 40px; width: auto; padding: 0 30px 0 12px;
  font: inherit; font-size: 13px; color: var(--neutral-90);
  background: var(--surface-0); border: 1px solid var(--neutral-50);
  border-radius: var(--r-input); cursor: pointer; max-width: 220px;
  transition: border-color var(--t);
}
.filtro-campo select:hover { border-color: var(--neutral-80); }
.filtro-campo select:focus-visible { outline: 2px solid var(--neutral-100); outline-offset: 2px; }

/* [10/09] Título de tela existe somente na topbar. Esta linha guarda contexto
   e contagem sem reconstruir um segundo cabeçalho dentro da vista. */
.view-context {
  display: flex; align-items: center; gap: 8px; min-height: 18px;
  margin: 0 0 10px; color: var(--neutral-75);
}
.view-context > :last-child:not(:first-child) { margin-left: auto; }
.view-context p {
  margin: 0; font-size: 11px; font-weight: 500; letter-spacing: .06em;
  text-transform: uppercase;
}
.view-context p.recorte, .view-context #accounts-count {
  font-size: 13px; font-weight: 400; letter-spacing: normal;
  text-transform: none; font-variant-numeric: tabular-nums;
}
.view-context p.recorte.stat-desconhecido { font-style: italic; }

/* Cinco controles em uma única barra no desktop. Os limites mínimos fazem a
   busca receber espaço útil sem encolher os rótulos dos quatro selects. */
#visits .visits-toolbar {
  display: grid;
  grid-template-columns: minmax(220px, 1.6fr) repeat(4, minmax(132px, 1fr));
  gap: 8px; align-items: center; margin-bottom: 16px;
}
#visits .visits-toolbar .search-field,
#visits .visits-toolbar .filtro-campo,
#visits .visits-toolbar .filtro-campo select { width: 100%; min-width: 0; max-width: none; }
#visits-bulk-actions { margin: 0 0 14px }
.visits-bulk-row, .visits-bulk-buttons { display: flex; align-items: center; gap: 12px; flex-wrap: wrap }
.visits-bulk-row { justify-content: space-between; padding: 10px 14px; border: 1px solid var(--neutral-50); border-radius: var(--r-input); background: var(--surface-0); font-size: 13px }
.visits-bulk-confirm { margin-top: 8px; padding: 14px; border: 1px solid var(--neutral-70); border-radius: var(--r-input); background: var(--surface-0); font-size: 13px }
.visits-bulk-confirm p { margin: 0 0 8px; line-height: 1.5 }
.visits-bulk-confirm ul { margin: 0 0 12px; padding-left: 20px; max-height: 180px; overflow-y: auto }
.visits-bulk-confirm li { margin: 4px 0 }

/* Contagem do recorte ("7 de 24 visitas"). */
.section-heading p.recorte {
  margin: 0; font-size: 13px; color: var(--neutral-75);
  font-variant-numeric: tabular-nums;
}
.section-heading p.recorte.stat-desconhecido { font-style: italic; }

/* Esqueleto de carregamento: pulso lento, sem brilho deslizante (§9). */
.skeleton-card {
  height: 112px; border: 1px solid var(--neutral-50);
  border-radius: var(--r-panel); background: var(--neutral-30);
  animation: pulso 1.6s ease-in-out infinite; margin-bottom: 10px;
}
@keyframes pulso { 0%, 100% { opacity: 1; } 50% { opacity: .55; } }
@media (prefers-reduced-motion: reduce) { .skeleton-card { animation: none; } }

/* Lista de cartões da Plaud (Integrações). */
.cards.list { display: grid; gap: 10px; }

/* Botão de atualizar da toolbar Plaud — mesmo desenho do .btn-circ. */
.toolbar .refresh {
  width: 40px; height: 40px; flex: none; display: grid; place-items: center;
  border: 1px solid var(--neutral-50); border-radius: var(--r-input);
  background: var(--surface-0); color: var(--neutral-90); cursor: pointer;
  transition: background var(--t), border-color var(--t);
}
.toolbar .refresh:hover { background: var(--neutral-30); border-color: var(--neutral-80); }
.toolbar .refresh svg { width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; }

@media (max-width: 860px) {
  .search-field { max-width: none; flex-basis: 100%; }
  .filters { width: 100%; }
  .filters button { flex: 1 1 auto; min-width: 0; }
  /* §10: alvo de toque de 44px no celular. */
  .filtro-campo select { height: 44px; min-height: 44px; max-width: none; flex: 1; }
  .filtro-campo { flex: 1 1 100%; }
  #visits .visits-toolbar { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  #visits .visits-toolbar .search-field { grid-column: 1 / -1; }
  #visits .visits-toolbar .filtro-campo { flex: none; }
}


/* ═══ 28/08 · VISTA LISTA DE CONTATOS (Venture/§7) ════════════════════════
   O cabeçalho ordenável é um BOTÃO dentro do <th> — o §7 pede o indicador
   `⇅` à direita do rótulo, e um span decorado não seria acionável por
   teclado. O botão herda a tipografia do cabeçalho para o th ordenável e o
   fixo lerem como a mesma linha. */
.th-ordena {
  display: inline-flex; align-items: center; gap: 6px;
  border: 0; background: none; padding: 0; cursor: pointer;
  font: inherit; color: inherit; text-transform: inherit; letter-spacing: inherit;
}
.th-ordena:hover { color: var(--neutral-100); }
.th-ordena .ord { font-size: 12px; color: var(--neutral-80); }
th[aria-sort="ascending"] .th-ordena, th[aria-sort="descending"] .th-ordena { color: var(--neutral-100); }
th[aria-sort="ascending"] .ord, th[aria-sort="descending"] .ord { color: var(--neutral-100); }

.tabela-contas th.num, .tabela-contas td.num { text-align: right; }
.tabela-contas .col-passo {
  max-width: 320px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  color: var(--neutral-75); font-size: 13px;
}
/* [06/09] A coluna PESSOAS: a mesma mecânica de corte da de próximo passo, e
   mais estreita, porque três nomes curtos cabem em 200px e o que passar disso
   deve virar reticências em vez de empurrar Visitas e Última para fora. Cor de
   texto normal (e não a de apoio do próximo passo): é a coluna que se varre. */
.tabela-contas .col-pessoas {
  max-width: 200px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  color: var(--neutral-90); font-size: 13px;
}
/* O corte mora no span dos NOMES, e não na célula: com a célula cortando, o
   pedaço que sumia era o "+2" do fim — o único que diz que há mais gente. */
.col-pessoas .pessoas-nomes {
  display: inline-block; max-width: 150px; vertical-align: bottom;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* [28/08, noite] As linhas-cartão do print do JP moram na BASE .tabela-visitas
   (o JP estendeu o padrão à fila de Visitas) — aqui ficam só as regras
   próprias da lista de Contatos. */
.conta-linha { cursor: pointer; }
.conta-linha:hover td { background: var(--surface-50); }
.conta-linha:focus-visible { outline: 2px solid var(--neutral-100); outline-offset: 2px; }

/* A ação no fim da linha, como no kit — mas um SPAN apresentacional: a linha
   inteira já é o botão (role="button" + Enter), e botão real aninhado dentro
   de controle é controle dentro de controle. O clique nele É o clique na
   linha, então ele não mente. */
.col-acao { width: 1%; white-space: nowrap; text-align: right; }
.linha-abrir {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 7px 12px; border: 1px solid var(--neutral-50); border-radius: var(--r-input);
  background: var(--surface-0); font-size: 12.5px; font-weight: 500; color: var(--neutral-90);
  transition: border-color var(--t);
}
.linha-abrir svg { width: 13px; height: 13px; fill: none; stroke: currentColor; stroke-width: 1.9; stroke-linecap: round; stroke-linejoin: round; }
.conta-linha:hover .linha-abrir { border-color: var(--neutral-80); }

/* No recorte móvel a tabela de contas segue o mesmo destino da de visitas
   (linha vira cartão, cabeçalho some — e com ele a ordenação, que no celular
   cede lugar à ordem por atenção, que é a padrão). A base já zera borda e
   padding dos td; aqui o cartão passa a morar no TR. */
@media (max-width: 900px) {
  /* O cartão no TR e o reset das células vêm da base .tabela-visitas; aqui só
     o mapeamento das colunas que são outras. */
  .tabela-contas .col-passo, .tabela-contas .col-pessoas { grid-column: 1 / -1; max-width: none; white-space: normal; }
  /* No cartão do celular a largura é a da linha inteira: o span dos nomes
     não precisa mais do corte que a coluna estreita exigia. */
  .col-pessoas .pessoas-nomes { max-width: none; white-space: normal; }
  .tabela-contas .num { text-align: left; font-size: 12.5px; }
}

/* [03/09] A tabela de PESSOAS (aba Contatos) reaproveita a moldura, o hover e
   a ação de fim de linha de `.tabela-contas`; só as colunas são outras.
   Telefone em números tabulares para os E.164 alinharem; e-mail em cinza
   médio porque é a coluna que se consulta, não a que se varre. */
.tabela-pessoas .col-empresa { color: var(--neutral-90); }
.tabela-pessoas .col-fone { white-space: nowrap; font-variant-numeric: tabular-nums; }
.tabela-pessoas .col-mail { color: var(--neutral-75); font-size: 13px; overflow-wrap: anywhere; }
@media (max-width: 900px) {
  /* No celular: empresa, telefone e e-mail descem em coluna única sob o
     nome; a contagem de visitas fica à direita do nome, como a data em
     Visitas. */
  .tabela-pessoas .col-empresa, .tabela-pessoas .col-fone, .tabela-pessoas .col-mail { grid-column: 1; font-size: 12.5px; }
  .tabela-pessoas td.num { grid-column: 2; grid-row: 1; text-align: right; }
}

/* ═══ 28/08 · TOOLTIP DE GRÁFICO (§7 "Gráficos") ══════════════════════════
   "Tooltip em card branco com sombra suave, ponto indicador e valor em
   semibold." Um único nó, reposicionado por delegação — segue o cursor no
   hover e ancora na barra no foco de teclado. */
.graf-tip {
  position: fixed; z-index: 70; pointer-events: none;
  background: var(--surface-0); border: 1px solid var(--neutral-50);
  border-radius: var(--r-input); box-shadow: var(--shadow-float);
  padding: 8px 12px; font-size: 12.5px; color: var(--neutral-75);
  display: flex; align-items: center; gap: 8px; white-space: nowrap;
}
.graf-tip[hidden] { display: none; }
.graf-tip i { width: 7px; height: 7px; border-radius: var(--r-pill); background: var(--neutral-100); flex: none; }
.graf-tip b { color: var(--neutral-100); font-weight: 600; font-variant-numeric: tabular-nums; }

/* [painel v3, fatia 2] As cores do grafico de visitas sairam com o grafico: o
   cartao "Visitas no periodo" desenhava por barra o numero que o placar ja
   conta em digito, e o placar e o dono. O `.graf-tip` acima fica: quem o usa
   agora e o hover das etapas do relatorio. */
.etapas .etapa { cursor: default; }

/* ═══ 30/08 · FILA DE ÓRFÃS (aba Negócios) ════════════════════════════════
   Visita que não virou conta. Cada item é um cartão porque cada um é uma
   DECISÃO pendente — lista corrida convida a varrer, e aqui não se varre: se
   escolhe. O motivo vem como selo, e o texto abaixo dele diz o que fazer,
   porque três motivos diferentes pedem três ações diferentes. */
/* [01/09] A FILA VIROU GRADE, pedido do JP: "queria todos esses pendentes em
   cards lado a lado, ocuparia menos espaço".

   Uma coluna era o certo enquanto a órfã era exceção rara. Com cinco na tela
   ela virou rolagem: o cartão mais alto tem título, data, explicação de duas
   linhas e a barra de ação — perto de 200px cada, e o gestor precisa ver
   QUANTAS são para decidir se resolve agora.

   `minmax(340px, 1fr)` e não um número de colunas: 340 é o piso em que
   `.orfa-acoes` ainda cabe em UMA linha (o campo pede 220 pelo seu
   `flex-basis`, e "Criar conta e vincular" pede o resto). Abaixo disso o
   flex-wrap que já existe desce o botão sozinho, sem regra nova. O `gap: 16px`
   é o mesmo de `.cg`, a grade de cartões da casa — grade nova com respiro
   próprio seria a terceira medida na mesma tela. */
/* [01/09] CARTÕES MENOS LARGOS, pedido do JP. O `1fr` esticava cada cartão até
   preencher a linha: em 1600px davam três de ~500px, e um cartão de 500px para
   um título, uma data e um botão é espaço gasto com nada.
   O teto de 460 mantém o piso de 340 que a regra abaixo já documentava — e é o
   teto, não o piso, que decide a largura numa tela grande. `justify-content:
   start` porque com teto sobra espaço à direita, e sobra alinhado. */
/* [03/09] A GRADE VIROU LISTA. A faixa era `minmax(340px, 460px)`; em 390 o
   contêiner mede 319 e o cartão saía 21px mais largo que o bloco que o contém —
   e em 1440/1280 sobrava um vão de ~300px de branco à direita da primeira
   linha, porque a grade tinha `align-items:start` com cartões de alturas
   diferentes. Pendência agora é LINHA, e linha não deixa buraco. */
.orfa-lista { display: block; }
.orfa {
  background: var(--surface-0); border: 1px solid var(--neutral-50);
  border-radius: var(--r-card); padding: 16px 18px;
}
.orfa-topo { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.orfa-topo b { font-size: 15px; font-weight: 600; color: var(--neutral-100); }
.orfa-meta { margin: 4px 0 0; font-size: 12.5px; color: var(--neutral-80); }
.orfa-explica { margin: 8px 0 0; font-size: 13px; color: var(--neutral-75); line-height: 1.5; max-width: 68ch; }

.orfa-sugestoes {
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px;
  margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--neutral-40);
}
.orfa-sugestoes .rot {
  font-size: 11px; font-weight: 500; letter-spacing: .06em;
  text-transform: uppercase; color: var(--neutral-75); margin-right: 2px;
}
/* [30/08] A candidata virou BOTÃO — ela vincula. Enquanto não vinculava era
   `<span>` de propósito: alvo que parece acionável e não faz nada é controle
   que mente. */
/* [01/09] OS ACHADOS DA BUSCA DE CONTATO, na captura. Coluna e não pills: são
   nomes de pessoas com empresa e telefone ao lado, e isso se lê descendo. Cada
   achado continua vestido por `.sugestao`, que já é o alvo escolhível da casa.

   Os dois vazios ganham respiro próprio aqui em vez de `.compact`: aquele
   modificador só tem regra para `.record-check` e `.honest-empty`, e usá-lo
   sobre `.empty` seria cobertura que não existe — o defeito que o cabeçalho de
   `test_classes_orfas` narra duas vezes. */
.contato-achados {
  display: flex; flex-direction: column; align-items: stretch;
  gap: 6px; margin-top: 8px;
}
.contato-achados .sugestao { justify-content: flex-start; text-align: left; }
.contato-achados .empty,
.contato-achados .honest-empty {
  margin: 0; padding: 8px 0 0; font-size: 12.5px; text-align: left;
}
.contato-achados .empty::before,
.contato-achados .honest-empty::before { content: none; }

.sugestao {
  display: inline-flex; align-items: baseline; gap: 8px;
  padding: 6px 12px; border-radius: var(--r-input);
  background: var(--neutral-30); font-size: 13px;
  border: 1px solid transparent; font-family: inherit; cursor: pointer;
  transition: background var(--t), border-color var(--t);
}
.sugestao:hover:not(:disabled) { background: var(--surface-0); border-color: var(--neutral-80); }
.sugestao:focus-visible { outline: 2px solid var(--neutral-100); outline-offset: 2px; }
.sugestao:disabled { opacity: .55; cursor: default; }
/* Órfã que o vínculo não resolve — ou que não tem candidata. Diz o que fazer
   em vez de deixar a linha muda. */
.orfa-sem-saida {
  margin: 12px 0 0; padding-top: 12px; border-top: 1px solid var(--neutral-40);
  font-size: 12.5px; color: var(--neutral-75); line-height: 1.5; max-width: 68ch;
}
.sugestao b { font-weight: 600; color: var(--neutral-100); }
.sugestao .det { font-size: 12px; color: var(--neutral-75); }
.sugestao .conf { font-size: 11.5px; color: var(--neutral-75); }

/* Ações da órfã — nomear e criar a conta. Fica separada das candidatas por uma
   linha porque são decisões de peso diferente: confirmar liga a uma conta que
   já existe; criar acrescenta uma.

   O CAMPO É EDITÁVEL, e não um botão com o texto digitado, porque a órfã mais
   comum é a `sem_cliente` — e ela, por definição, não tem nome digitado. Um
   botão "Criar conta · <nome>" só apareceria no caso raro, e a maioria da fila
   continuaria sem saída. Quem sabe o nome é quem abriu a visita e ouviu. */
.orfa-acoes {
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px;
  margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--neutral-40);
}
.orfa-campo {
  display: inline-flex; align-items: center; flex: 1 1 220px;
  border: 1px solid var(--neutral-50); border-radius: var(--r-input);
  background: var(--surface-0); padding: 0 12px; height: 40px;
  transition: border-color var(--t);
}
.orfa-campo:focus-within { outline: 2px solid var(--neutral-100); outline-offset: 2px; }
.orfa-campo input {
  border: 0; background: none; font: inherit; font-size: 14px;
  color: var(--neutral-90); width: 100%; padding: 0;
}
.orfa-campo input:focus { outline: none; }
.orfa-campo input:disabled { color: var(--neutral-75); }

/* O conflito da criação: o Server achou conta parecida e NÃO criou. Vem acima
   do campo porque muda o que fazer com ele — vincular numa candidata costuma
   ser a saída, e insistir no nome é a exceção. */
.orfa-conflito {
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px;
  margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--neutral-40);
}
.orfa-conflito p {
  flex: 1 1 100%; margin: 0; font-size: 12.5px; line-height: 1.5;
  color: var(--neutral-75); max-width: 68ch;
}
.orfa-conflito b { color: var(--neutral-90); font-weight: 600; }

/* ═══ 30/08 · CONTAS PARECIDAS (aba Negócios) ══════════════════════════════
   A fusão é a ÚNICA ação do produto que APAGA linha, e não tem desfazer. O
   desenho todo sai daí: os dois lados aparecem lado a lado com o que cada um
   carrega (para o lado trocado ser visível ANTES de clicar), o botão não funde
   — abre a confirmação —, e a confirmação nomeia quem some.

   O par não é uma linha de tabela de propósito. Tabela convida a varrer; aqui
   cada item é uma decisão que precisa ser lida. Mesma razão do cartão da fila
   de órfãs, logo acima nesta tela. */
.dup-lista { display: grid; gap: 10px; }
.dup {
  background: var(--surface-0); border: 1px solid var(--neutral-50);
  border-radius: var(--r-card); padding: 16px 18px;
  container-type: inline-size; container-name: dup;
}
/* Consulta do CARTÃO, não da janela: o bloco de Negócios muda de largura com a
   barra lateral aberta ou recolhida. E o degrau conta o PADDING — 460 é a caixa
   de conteúdo do cartão, que é 36px menor que ele; foi por esquecer isso que um
   degrau desta folha nasceu 60px abaixo do necessário em 30/08. */
.dup-par { display: grid; gap: 10px; grid-template-columns: minmax(0, 1fr); }
@container dup (min-width: 460px) {
  .dup-par { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
.dup-lado {
  display: flex; flex-direction: column; gap: 3px;
  padding: 10px 12px; border-radius: var(--r-panel); background: var(--neutral-30);
}
/* O lado que sai se marca no RÓTULO, e só nele. Três regras se cruzam aqui e
   sobra um caminho: acento nunca é fundo de bloco (§2); sombra só em camada que
   flutua, então listra de `box-shadow` está fora (§5 — e o portão reprovou a
   primeira tentativa); e borda de 2px em repouso também está fora (§5). Resta o
   acento como MICROTEXTO, que §2 permite — e a palavra "Sai" já carrega o
   sentido sozinha, então a cor reforça em vez de informar. */
.dup-lado.sai .rot { color: var(--red-ink); }
.dup-lado .rot {
  font-size: 11px; font-weight: 500; letter-spacing: .06em;
  text-transform: uppercase; color: var(--neutral-75);
}
.dup-lado b { font-size: 14px; font-weight: 600; color: var(--neutral-100); }
.dup-lado .det { font-size: 12px; color: var(--neutral-75); }

.dup-acoes {
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-top: 12px;
}
.dup-score {
  font-size: 12px; color: var(--neutral-75); margin-right: auto;
  font-variant-numeric: tabular-nums;
}
/* A confirmação SUBSTITUI os botões — não aparece ao lado deles. Deixar o
   "Fundir…" clicável enquanto a confirmação está aberta daria dois caminhos
   para a mesma ação irreversível, e um deles sem ler. */
.dup-confirma {
  margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--neutral-40);
}
.dup-confirma p {
  margin: 0; font-size: 13px; line-height: 1.55; color: var(--neutral-75);
  max-width: 68ch;
}
.dup-confirma b { color: var(--neutral-90); font-weight: 600; }
.dup-confirma .dup-acoes { margin-top: 12px; }

/* ═══ 31/08 · CONEXÃO DE WHATSAPP E ENVIO (Conversas) ════════════════════
   Só o que NÃO existia. A fila e a thread reusam `.conv-item`, `.chat-msgs` e
   `.msg.cliente`/`.consultor`, que esta folha já tinha do perfil Vendedor —
   escrever um segundo componente de conversa faria os dois divergirem, e a
   primeira versão desta entrega quase fez isso: ela inventou `.conv-item` e
   `.msg` próprios, que colidiriam em silêncio com os de cima. */
.conv-conexao-toolbar {
  display: flex; justify-content: flex-end; align-items: center; gap: 8px;
  margin-bottom: 16px;
}
.conv-conexao-filtro { position: relative; }
.conv-conexao-filtro > summary {
  display: flex; align-items: center; min-width: 180px; min-height: 40px;
  padding: 8px 34px 8px 12px; border: 1px solid var(--neutral-50);
  border-radius: var(--r-input); background: var(--surface-0);
  color: var(--neutral-90); font-size: 13px; cursor: pointer; list-style: none;
}
.conv-conexao-filtro > summary::-webkit-details-marker { display: none; }
.conv-conexao-filtro > summary::after {
  content: ""; position: absolute; right: 13px; width: 7px; height: 7px;
  border-right: 1.5px solid currentColor; border-bottom: 1.5px solid currentColor;
  transform: translateY(-2px) rotate(45deg);
}
.conv-conexao-filtro[open] > summary::after { transform: translateY(2px) rotate(225deg); }
.conv-conexao-filtro > summary:hover { border-color: var(--neutral-90); }
.conv-conexao-filtro > summary:focus-visible { outline: 2px solid var(--neutral-100); outline-offset: 2px; }
.conv-conexao-opcoes {
  position: absolute; z-index: 12; top: calc(100% + 6px); right: 0;
  min-width: 280px; max-width: min(360px, calc(100vw - 32px));
  display: grid; gap: 2px; padding: 8px;
  border: 1px solid var(--neutral-50); border-radius: var(--r-card);
  background: var(--surface-0); box-shadow: var(--shadow-float);
}
.conv-conexao-opcoes label {
  display: flex; align-items: center; gap: 10px; min-height: 44px;
  padding: 7px 8px; border-radius: var(--r-input); cursor: pointer;
}
.conv-conexao-opcoes label:hover { background: var(--neutral-30); }
.conv-conexao-opcoes input { width: 16px; height: 16px; flex: none; accent-color: var(--neutral-100); }
.conv-conexao-opcoes span { display: grid; min-width: 0; }
.conv-conexao-opcoes b { font-size: 13px; font-weight: 500; }
.conv-conexao-opcoes small { color: var(--neutral-75); font-size: 12px; }
/* A conexão dobrada. Só existe quando está TUDO no ar: com erro ou pareando,
   o cartão fica aberto, porque aí ele pede algo de quem olha.
   O resumo é uma linha e mantém o selo de estado — quem precisa saber que o
   número caiu não precisa abrir nada para descobrir. */
.conexao-dobra { margin-bottom: 12px; }
.conexao-dobra > summary {
  display: flex; align-items: center; gap: 10px; cursor: pointer;
  padding: 10px 14px; border: 1px solid var(--neutral-40); border-radius: var(--r-card);
  background: var(--surface-0); font-size: 13px; color: var(--neutral-75);
  transition: border-color var(--t);
}
.conexao-dobra > summary:hover { border-color: var(--neutral-50); }
.conexao-dobra > summary:focus-visible { outline: 2px solid var(--neutral-100); outline-offset: 2px; }
.conexao-dobra[open] > summary { margin-bottom: 10px; }
.conexao-lista { display: grid; gap: 10px; margin-bottom: 12px; }
.conexao {
  background: var(--surface-0); border: 1px solid var(--neutral-50);
  border-radius: var(--r-card); padding: 14px 16px;
}
.conexao-topo { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.conexao-topo b { font-size: 14.5px; font-weight: 600; color: var(--neutral-100); }
.conexao .det { margin: 4px 0 0; font-size: 12.5px; color: var(--neutral-75); }
/* O QR nasce escondido e só aparece quando alguém pede: ele é a chave do
   WhatsApp do cliente, e chave à mostra na tela é chave fotografada. */
.conexao-qr { margin-top: 12px; }
.conexao-qr img {
  display: block; width: 220px; max-width: 100%;
  border: 1px solid var(--neutral-50); border-radius: var(--r-panel);
}
/* O CÓDIGO É PARA SER DITADO EM VOZ ALTA, por telefone, para quem está com o
   aparelho na mão. Por isso é grande, com espaço entre os caracteres e em
   `tabular-nums`: a confusão entre 0/O e 1/I é o modo de falha desta tela, e
   ela não tem segunda chance — código errado só avisa depois de digitado.
   `user-select: all` para um clique selecionar tudo e ninguém copiar metade. */
.codigo-pareamento {
  margin: 4px 0 8px; font-size: 26px; font-weight: 600; letter-spacing: .18em;
  font-variant-numeric: tabular-nums; color: var(--neutral-100);
  user-select: all; word-break: keep-all;
}
/* A PROCEDÊNCIA DO DADO, acima das dez telas do perfil. Linha, não faixa: o JP
   já reprovou frase ocupando tela ("essas frases estão deixando tela zuada"),
   e uma etiqueta que incomoda é uma etiqueta que alguém apaga.

   A cor vem do `.badge` e só dele (§2: acento em selo, nunca como fundo de
   bloco). O que separa o caso fictício não é a cor — é o selo TER aparecido,
   que é forma, e por isso continua legível para quem não distingue as duas. */
.fonte-do-dado {
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px;
  margin: 0 0 16px; font-size: 12.5px; color: var(--neutral-80);
}
.fonte-do-dado .det { margin: 0; }
.fonte-do-dado.ficticia { color: var(--neutral-90); }
.conv-acoes { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-top: 12px; }

.relation-search-label { display: block; margin: 16px 0 6px; color: var(--neutral-80); font-size: 13px; }
.relation-search-toolbar { margin: 0 0 16px; }
.relation-search-toolbar .search-field { flex: 1 1 100%; min-width: 0; max-width: none; }
.relation-search-toolbar .search-field input { width: 100%; }

@media (max-width: 560px) {
  .conv-conexao-toolbar { align-items: stretch; flex-wrap: wrap; }
  .conv-conexao-filtro { flex: 1 1 180px; }
  .conv-conexao-filtro > summary { width: 100%; }
  .conv-conexao-opcoes { right: auto; left: 0; }
}

/* O envio fica FORA do `.chat-msgs`, que é o container rolável: dentro, ele
   subiria junto com as mensagens e sairia da tela numa conversa longa. */
.msg-envio {
  display: flex; gap: 8px; align-items: center;
  padding: 14px 18px; border-top: 1px solid var(--neutral-40);
}
.msg-campo {
  display: flex; flex: 1 1 auto; align-items: center;
  border: 1px solid var(--neutral-50); border-radius: var(--r-input);
  background: var(--surface-0); padding: 0 12px; height: 40px;
  transition: border-color var(--t);
}
/* O foco fica no INVÓLUCRO, com o mesmo contorno da regra global de
   `:focus-visible`: o input interno anula o `outline` para não desenhar
   retângulo dentro da caixa arredondada, e só a troca de cor da borda era
   sinal fraco justamente onde a próxima ação é mandar texto a um cliente. */
.msg-campo:focus-within { outline: 2px solid var(--neutral-100); outline-offset: 2px; }
.msg-campo input {
  width: 100%; border: 0; background: none; font: inherit; font-size: 14px;
  color: var(--neutral-90); padding: 0;
}
.msg-campo input:focus { outline: none; }

/* [painel v3, fatia 2] O Pareto de perda deixou de ser cartao com barras e
   virou UMA frase no rodape de apoio (`.apoio`): ordem e tamanho relativo so
   se leem com muitos motivos, e o Painel de uma equipe tem dois ou tres — tres
   barrinhas na dobra custam mais atencao do que a frase "Perdido no periodo:
   4 negocios, mais por preco" entrega. As classes `.perda`, `.perda-topo` e
   `.perda-trilho` sairam com elas. */

/* ═══ 30/08 · FEATURES POR PERFIL (Administração) ═════════════════════════
   Cartão por feature, e não linha de tabela, pela mesma razão da fila de
   órfãs: cada item é uma DECISÃO, e tabela convida a varrer.

   A coluna de papel é LEITURA do que o código declara, não caixa que se marca
   — por isso os papéis são selos e só o ligar/desligar é botão. Se papel fosse
   clicável, a tela viraria um segundo sistema de permissão, que é a coisa que
   o módulo `features.py` existe para não ser. */
/* ── A VISITA QUE SOBREVIVEU ──────────────────────────────────────────────
   [31/08] Fica acima de todas as views, porque a visita recuperada não
   pertence a nenhuma tela: quem recarregou pode ter caído em qualquer lugar.

   Selo de atenção, não de perda: o áudio ESTÁ aqui — o que falta é enviá-lo.
   Vermelho diria que se perdeu, e ensinaria a ignorar o aviso no dia em que
   algo de fato se perder. */
.pendente-barra { display: grid; gap: 8px; margin-bottom: 20px; }
.pendente-item {
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px;
  padding: 12px 16px; border: 1px solid var(--neutral-50);
  border-radius: var(--r-card); background: var(--surface-0);
}
.pendente-item b { font-size: 14px; }
.pendente-item .det { margin: 0; flex: 1 1 220px; min-width: 0; }

/* ── ADMINISTRAÇÃO: pessoas e trilha saem do pergor.css ───────────────────
   [31/08] `.admin-row`, `.admin-actions` e `.audit-row` tinham ZERO regras
   nesta folha — viviam só no `pergor.css` legado. A tela era metade v4 (a
   matriz de features) e metade pré-v4, que é a queixa de "visual não legal".
   As classes novas não têm par no legado: a tela deixa de depender dele.

   Sem @container e sem media query aqui de propósito: o que decide a forma é
   quanto texto cabe, e `flex-wrap` responde a isso sozinho, em qualquer
   largura de bloco. Regra que não precisa de consulta é regra que não erra a
   consulta. */
.usuario {
  display: flex; flex-wrap: wrap; align-items: flex-start; gap: 10px 16px;
  padding: 14px 16px; border: 1px solid var(--neutral-50);
  border-radius: var(--r-card); background: var(--surface-0);
}
.usuario + .usuario { margin-top: 8px; }
/* §5: separação por borda OU contraste de superfície, nunca os dois. O inativo
   já tem a borda, então o que muda é só o fundo. */
.usuario.inativo { background: var(--surface-50); }
.usuario-id { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; width: 100%; }
.usuario-id b { font-size: 15px; }
.usuario-login {
  margin: 0; font-size: 12.5px; color: var(--neutral-80);
  font-variant-numeric: tabular-nums;
}
.usuario-fatos { margin: 0; display: flex; flex-wrap: wrap; gap: 6px 20px; }
.usuario-fatos > div { min-width: 0; }
.usuario-fatos dt {
  font-size: 11px; letter-spacing: .06em; text-transform: uppercase;
  color: var(--neutral-80);
}
/* `dd` nasce com 40px de recuo no navegador; sem isto o valor foge do rótulo. */
.usuario-fatos dd { margin: 0; font-size: 13px; color: var(--neutral-90); overflow-wrap: anywhere; }
.usuario-acoes { margin-left: auto; display: flex; flex-wrap: wrap; gap: 8px; }

.trilha-filtros { margin-bottom: 12px; max-width: 420px; }
.trilha-item {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 12px;
  padding: 10px 0; border-bottom: 1px solid var(--neutral-30);
}
.trilha-item:last-child { border-bottom: 0; }
.trilha-item time {
  flex: none; width: 116px; font-size: 12px; color: var(--neutral-80);
  font-variant-numeric: tabular-nums;
}
.trilha-item b { font-size: 13px; }
.trilha-item .det { margin: 0; min-width: 0; }

.feature-resumo {
  margin: 6px 0 0; font-size: 13px; line-height: 1.5;
  color: var(--neutral-75); max-width: 68ch;
}
.feature-motivo { margin: 6px 0 0; font-size: 12.5px; color: var(--neutral-75); }
/* O selo apagado diz "este papel NÃO vê" sem precisar de uma segunda palavra.
   Presença e ausência na mesma fileira leem mais rápido que duas listas.

   [31/08] A OPACIDADE SAIU. `neutral-75` a 45% sobre `neutral-30` compõe
   #AEB0B5 e rende 1,94:1 — o nome do papel ficava ilegível, e é justamente
   ele que carrega a informação. O apagamento não se perde: o risco já
   distingue os dois estados por FORMA (§3.5), e é ele que a §11 pede quando
   a cor não pode carregar estado sozinha. Sem opacidade, 5,71:1.

   O raio virou `--r-badge`: `.badge` e `.tag` — os dois selos do sistema —
   usam esse, e a pílula ficaria uma terceira forma para o mesmo trabalho. */
.perfil-selo {
  font-size: 12px; padding: 3px 9px; border-radius: var(--r-badge);
  background: var(--neutral-30); color: var(--neutral-75);
  text-decoration: line-through;
}
.perfil-selo.tem { text-decoration: none; color: var(--neutral-90); }
/* [31/08] O papel virou CONTROLE para quem o código já permite. O selo riscado
   continua sendo selo — papel que o código recusa não ganha botão, porque a
   tela estreita e nunca alarga.

   O que separa ligado de desligado é o PREENCHIMENTO, não a cor (§11): quem
   não distingue as duas continua vendo que um está cheio e o outro vazio. */
button.perfil-selo {
  border: 1px solid var(--neutral-50); cursor: pointer; font: inherit;
  font-size: 12px; line-height: 1.4;
  transition: background var(--t), border-color var(--t), color var(--t);
}
button.perfil-selo[aria-checked="false"] { background: var(--surface-0); color: var(--neutral-75); }
button.perfil-selo[aria-checked="true"] {
  background: var(--neutral-100); border-color: var(--neutral-100); color: var(--neutral-0);
}
button.perfil-selo:disabled { opacity: .6; cursor: progress; }
button.perfil-selo:focus-visible { outline: 2px solid var(--neutral-100); outline-offset: 2px; }
.feature-travada { font-size: 12.5px; color: var(--neutral-75); }

/* ═══ 30/08 · METAS (Configurações) ════════════════════════════════════════
   Uma linha por vendedor. Definir meta é ato raro — uma vez por mês —, então
   o desenho é de formulário simples, não de painel: nome, valor, salvar. */
/* Sem folga: a borda de cada linha já separa (§5 — borda OU contraste,
   nunca os dois, e aqui nem os dois nem os dois espaços). */
.metas { display: grid; gap: 0; }
.meta-linha {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  padding: 10px 0; border-bottom: 1px solid var(--neutral-40);
}
.meta-linha:last-child { border-bottom: 0; }
.meta-nome { flex: 1 1 160px; font-size: 14px; font-weight: 500; color: var(--neutral-100); }
.meta-campo {
  display: inline-flex; align-items: center; gap: 6px;
  border: 1px solid var(--neutral-50); border-radius: var(--r-input);
  background: var(--surface-0); padding: 0 10px; height: 32px;
  transition: border-color var(--t);
}
.meta-campo:focus-within { outline: 2px solid var(--neutral-100); outline-offset: 2px; }
.meta-campo i { font-style: normal; font-size: 12.5px; color: var(--neutral-75); }
.meta-campo input {
  border: 0; background: none; font: inherit; font-size: 14px;
  color: var(--neutral-90); width: 130px; text-align: right;
  font-variant-numeric: tabular-nums; padding: 0;
}
.meta-campo input:focus { outline: none; }
@media (max-width: 560px) {
  .meta-linha { align-items: stretch; }
  .meta-nome { flex-basis: 100%; }
  .meta-campo { flex: 1; }
  .meta-campo input { width: 100%; }
}

/* [painel v3, fatia 2] A meta e uma das TRES FRASES do rodape de apoio, e nao
   mais uma faixa acima dos indicadores. O painel com moldura saiu junto com os
   cartoes de carteira e de perda: meta e o alvo contra o qual as medidas se
   leem, nao uma medida — e o que nao e medida nao abre a tela.

   `.valor` continua marcando o dinheiro (numeral tabular, tinta cheia) dentro
   do corpo da frase; o rotulo em versalete e o respiro de painel sairam, que
   e o que sobrava de cartao numa linha de prosa.

   O seletor pergunta pelo RODAPE, e nao mais pela classe `.meta-painel`: o
   `<p class="meta-painel">` do topo saiu do template, e `pintarMeta` escreve o
   `<b class="valor">` dentro do `<span id="meta-painel">` de `.apoio`, que nao
   carrega aquela classe. Enquanto o seletor citava a classe morta, o valor da
   meta nascia sem numeral tabular e a regra vestia coisa nenhuma. */
#home .apoio .valor {
  font-weight: 500; color: var(--neutral-100); font-variant-numeric: tabular-nums;
}

/* ═══ 01/09 · A MATRIZ DE FEATURES ══════════════════════════════════════════
   Modificador sobre `.tabela-visitas`, a tabela da casa — linha como cartão
   solto, cabeçalho em faixa. Contatos faz igual com `.tabela-contas`; inventar
   uma terceira tabela era o que estava errado na primeira versão. */
.tabela-features .col-tela b { font-size: 14px; font-weight: 500; color: var(--neutral-100); }
.tabela-features .col-tela .badge { margin-left: 8px; }
.tabela-features .feature-resumo { margin: 4px 0 0; max-width: 62ch; }
/* A coluna de papel é estreita e centrada: é onde o olho desce. */
.tabela-features .col-papel { width: 104px; text-align: center; vertical-align: middle; }

/* Papel que o código não permite: travessão, como o Portal escreve ausência em
   toda parte. Riscar o nome do papel dizia "removido", que é outro fato. */
.sem-acesso { color: var(--neutral-75); font-size: 15px; cursor: help; }

/* O interruptor é uma caixa, porque é assim que se lê "marcado ou não" numa
   matriz. `role="switch"` continua sendo o que ele É para quem ouve a tela. */
.interruptor {
  width: 20px; height: 20px; padding: 0; display: inline-grid; place-items: center;
  border: 1px solid var(--neutral-50); border-radius: 4px;
  background: var(--surface-0); cursor: pointer;
  transition: background var(--t), border-color var(--t);
}
.interruptor:hover { border-color: var(--neutral-90); }
.interruptor[aria-checked="true"] { background: var(--neutral-100); border-color: var(--neutral-100); }
/* O visto é FORMA, não só cor — §11 não deixa a cor carregar estado sozinha —
   e é `stroke`, não `border`: 2px de borda em repouso é do anel de foco. */
.interruptor svg { width: 13px; height: 13px; fill: none; stroke: transparent;
  stroke-width: 2.5; stroke-linecap: round; stroke-linejoin: round; }
.interruptor[aria-checked="true"] svg { stroke: var(--neutral-0); }
.interruptor:disabled { cursor: not-allowed; opacity: .5; }

/* ═══ 03/09 · TELA DE NEGÓCIOS ═════════════════════════════════════════════
   Prefixo próprio, e nunca `.kb-*`: aquele é o quadro de TAREFAS, e dois
   quadros compartilham a linguagem por TOKEN, não por classe. Reescrever
   `.kb-card` para caber aqui mudaria a outra tela por efeito colateral.

   O corpo desta tela não tem NENHUM botão preto: o preto da região já é o
   "Registrar visita" do cabeçalho global. A única exceção é o "Criar conta e
   vincular" dentro de uma linha de triagem EXPANDIDA — ali a linha é a região,
   e só uma expande de cada vez. */

/* Resumo de uma linha: o quadro, não os indicadores, abre a tela. */
.neg-resumo-enxuto {
  display: flex; align-items: center; flex-wrap: wrap; gap: 6px 10px;
  min-height: 40px; margin: 0 0 14px; padding: 0 0 10px;
  border-bottom: 1px solid var(--neutral-40);
  color: var(--neutral-80); font-size: 13px;
}
.neg-resumo-enxuto > span:first-child { color: var(--neutral-100); }
.neg-resumo-enxuto b { color: var(--neutral-100); font-weight: 600; }
.neg-resumo-separador { color: var(--neutral-80); }
.neg-entradas { margin-left: auto; white-space: nowrap; }
.neg-entradas b { margin-left: 5px; }
.neg-entradas-incertas { margin-left: auto; font-size: 12px; }
#negocios-funil { margin-bottom: 24px; }
#orfas > .empty, #duplicatas > .empty { display: none; }
#negocios-contexto { margin-top: 18px; }
.neg-indicadores { border-top: 1px solid var(--neutral-40); padding-top: 8px; }
.neg-indicadores > summary {
  cursor: pointer; list-style: none; min-height: 40px;
  display: flex; align-items: center; gap: 8px;
  color: var(--neutral-80); font-size: 13px;
}
.neg-indicadores > summary::-webkit-details-marker { display: none; }
.neg-indicadores > summary::before { content: "▸"; }
.neg-indicadores[open] > summary::before { content: "▾"; }
.neg-indicadores > summary:focus-visible { outline: 2px solid var(--neutral-100); outline-offset: 2px; }
#negocios-contexto .stat .v { line-height: 1.2; }
@media (min-width: 1181px) {
  #negocios-contexto .stat-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}
/* A leitura completa e seu aviso ficam dentro dos indicadores recolhidos. */
.neg-aviso { margin: 2px 0 0; font-size: 13px; line-height: 1.5; color: var(--neutral-80); }
.neg-resumo-pe { margin: 6px 0 18px; font-size: 12.5px; color: var(--neutral-75); }

/* TRIAGEM. Fechada, ocupa uma linha; aberta, mostra os grupos na ordem da
   decisão. O alvo tem 44px de altura mínima porque em 390 ele é o primeiro
   controle da tela. */
.neg-triagem {
  border: 1px solid var(--neutral-50); border-radius: var(--r-card);
  background: var(--surface-0); margin-bottom: 12px;
}
.neg-triagem > summary {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 11px 16px; min-height: 44px; cursor: pointer; list-style: none;
}
.neg-triagem > summary::-webkit-details-marker { display: none; }
.neg-triagem > summary::before { content: "▸"; color: var(--neutral-75); font-size: 11px; }
.neg-triagem[open] > summary::before { content: "▾"; }
.neg-triagem > summary:focus-visible { outline: 2px solid var(--neutral-100); outline-offset: -2px; }
.neg-triagem > summary b { font-size: 14px; font-weight: 600; color: var(--neutral-100); }
.neg-triagem > summary .eyebrow { margin: 0; }
.neg-triagem-n { margin-left: auto; font-size: 12px; color: var(--neutral-75); }
.neg-triagem > *:not(summary) { padding-left: 16px; padding-right: 16px; }
.neg-triagem > *:last-child { padding-bottom: 14px; }
.neg-triagem .view-note { margin-top: 0; font-size: 12.5px; }

/* Grupo rotulado. A explicação sai UMA VEZ por grupo — ela era idêntica em
   todo cartão do mesmo motivo, e o mesmo parágrafo três vezes é ruído. */
.neg-grupo { padding-top: 6px; }
.neg-grupo + .neg-grupo { margin-top: 14px; border-top: 1px solid var(--neutral-40); }
.neg-grupo h3 { font-size: 13px; font-weight: 600; color: var(--neutral-100); margin-top: 6px; }
.neg-grupo-frase {
  margin: 4px 0 8px; font-size: 12.5px; line-height: 1.5;
  color: var(--neutral-75); max-width: 72ch;
}

/* A pendência é LINHA DE LISTA DE TRABALHO, e não cartão-formulário: a ação
   fica numa COLUNA à direita, de largura fixa, igual em todas as linhas do
   grupo. Com a ação embaixo, em linha própria, cada visita media três linhas e
   nada alinhava de uma para a outra — quatro visitas ocupavam ~560px e o olho
   não achava "o que eu faço aqui" (print do JP, 13/09). A largura é FIXA de
   propósito: com `auto` a coluna andaria a cada rótulo ("Abrir negócio" x
   "Abrir outro negócio") e o alinhamento — que é o ganho todo — se perderia.

   O regime é do BLOCO, não da janela: a triagem vive dentro da barra lateral
   de três larguras, e uma media query de viewport acertaria o caso errado. */
.orfa-lista { container-type: inline-size; container-name: triagem; }
.neg-pend {
  display: grid; grid-template-columns: minmax(0, 1fr) 152px;
  align-items: center; column-gap: 10px; row-gap: 6px;
  padding: 9px 0; border-top: 1px solid var(--neutral-40);
}
.neg-grupo .neg-pend:first-of-type { border-top: 0; }
/* Bloco estreito: a linha quebra em duas (nome+selo em cima; sugestões e ação
   embaixo) — mas a ação continua à direita e na mesma coluna entre linhas. */
.neg-pend-topo { grid-column: 1 / -1; display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.neg-pend-topo b { font-size: 14px; font-weight: 600; color: var(--neutral-100); }
.neg-pend-meta { font-size: 12px; color: var(--neutral-75); }
.neg-pend-acoes { grid-column: 1; display: flex; align-items: center; flex-wrap: wrap; gap: 8px; }
.neg-visita-link { display: inline-flex; align-items: center; min-height: 32px; white-space: nowrap; }
@media (pointer: coarse) {
  .neg-visita-link { min-height: 44px; }
}
/* `-2` é a última coluna nos dois regimes (duas ou três), e `stretch` dá a
   todos os botões do grupo a mesma largura e o mesmo x. */
.neg-acao { grid-column: -2; justify-self: stretch; margin-top: 0; }
.neg-pend-expansao { grid-column: 1 / -1; }
.neg-pend-acoes .rot {
  font-size: 11px; font-weight: 500; letter-spacing: .06em;
  text-transform: uppercase; color: var(--neutral-75);
}
@container triagem (min-width: 640px) {
  /* O NOME tem piso e as candidatas cedem: sem ele a coluna das sugestões
     tomava 800px de conteúdo próprio e o nome da visita — o sujeito da linha —
     quebrava em três linhas dentro de 212px. Medido a 1536: 122px de linha
     viram 92px, e a lista inteira, 583px → 553px. */
  .neg-pend { grid-template-columns: minmax(360px, 1fr) minmax(0, auto) 152px; }
  .neg-pend-topo { grid-column: 1; }
  .neg-pend-acoes { grid-column: 2; }
}
/* Candidata além das duas primeiras: já está na linha, escondida. Revelá-la é
   `hidden = false`, e este seletor devolve o desenho de `.sugestao` — sem ele
   o `[hidden]{display:none!important}` da casa e o `display` do componente
   brigariam na volta. */
.neg-extra:not([hidden]) { display: inline-flex; }
.neg-pend-expansao:empty { display: none; }
.neg-pend-expansao > .orfa-acoes:first-child { border-top: 0; margin-top: 6px; padding-top: 0; }

/* Quatro etapas visíveis quando cabem; duas no meio, uma no telefone. */
.neg-quadro { container-type: inline-size; container-name: negquadro; }
.neg-colunas { display: grid; grid-template-columns: minmax(0, 1fr); gap: 10px; }
@container negquadro (min-width: 700px) {
  .neg-colunas { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; align-items: start; }
}
@container negquadro (min-width: 960px) {
  .neg-colunas { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}
.neg-col {
  background: var(--surface-50); border: 1px solid var(--neutral-50);
  border-radius: var(--r-card); padding: 12px 14px;
}
.neg-head {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  cursor: pointer; list-style: none; min-height: 32px;
}
.neg-head::-webkit-details-marker { display: none; }
.neg-head:focus-visible { outline: 2px solid var(--neutral-100); outline-offset: 2px; }
.neg-head .dot { width: 7px; height: 7px; border-radius: var(--r-pill); flex: none; }
.neg-head b { font-size: 13.5px; font-weight: 600; color: var(--neutral-100); }
.neg-head .n { font-size: 12px; color: var(--neutral-80); }
/* O valor da coluna em linha própria e com dígito alinhado: dois valores
   empilhados só se comparam quando as casas caem no mesmo lugar. */
.neg-col-valor {
  flex-basis: 100%; font-size: 12.5px; color: var(--neutral-80);
  font-variant-numeric: tabular-nums;
}
.neg-col-recorte {
  font-size: 10.5px; letter-spacing: .06em; text-transform: uppercase;
  color: var(--neutral-75);
}
.neg-col-corpo { display: flex; flex-direction: column; gap: 8px; margin-top: 10px; }
.neg-col-corpo .empty, .neg-col-corpo .honest-empty { padding: 12px 0; margin: 0; font-size: 12.5px; }
.neg-nota { margin: 2px 0 0; font-size: 11.5px; color: var(--neutral-75); }

/* CARTÃO — três linhas e uma hierarquia de verdade. Hover troca superfície e
   borda, não desloca nem cresce; nenhuma sombra em repouso. */
.neg-cartao {
  display: block; width: 100%; text-align: left; font: inherit;
  background: var(--surface-0); border: 1px solid var(--neutral-50);
  border-radius: var(--r-card); padding: 10px 12px;
  transition: background var(--t), border-color var(--t);
}
.neg-cartao[role="button"] { cursor: pointer; }
.neg-cartao[role="button"]:hover { background: var(--neutral-30); border-color: var(--neutral-90); }
.neg-cartao:focus-visible { outline: 2px solid var(--neutral-100); outline-offset: 2px; }
.neg-cartao-topo { display: flex; align-items: flex-start; justify-content: space-between; gap: 8px; }
.neg-cartao-topo b { font-size: 14px; font-weight: 600; color: var(--neutral-100); }
/* "63 dias aqui" tinha exatamente a mesma aparência que "3 dias aqui". O pill
   com o `<i>` de 6px é marcador de FORMA além da cor — regra 5 do manual. */
.neg-dias { flex: none; white-space: nowrap; }
.neg-valor {
  margin-top: 5px; font-size: 15px; color: var(--neutral-90);
  font-variant-numeric: tabular-nums;
}
.neg-sem-valor { margin-top: 5px; font-size: 12px; color: var(--neutral-75); }
.neg-cartao-pe { margin-top: 3px; font-size: 12px; color: var(--neutral-75); line-height: 1.45; }
/* O arrasto é o gesto do quadro; teclado e toque atualizam pelo detalhe. */
.neg-cartao[draggable="true"] { cursor: grab; }
/* O cartão arrastado é a única peça que FLUTUA (regra 7), e por isso é a única
   com sombra. O alvo sob o ponteiro troca superfície e borda — o mesmo par do
   hover (regra 4) —, não desloca nem cresce. */
.neg-cartao.arrastando { opacity: .5; cursor: grabbing; box-shadow: var(--shadow-float); }
.neg-col.recebendo,
.neg-desfecho-peca.recebendo { background: var(--neutral-30); border-color: var(--neutral-90); }

.neg-motivo {
  display: flex; flex-wrap: wrap; gap: 8px; margin-top: 8px;
  padding-top: 8px; border-top: 1px solid var(--neutral-40);
}
.neg-motivo label { flex: 1 1 100%; }
.neg-motivo input {
  width: 100%; height: 34px; padding: 0 10px; font: inherit; font-size: 13px;
  color: var(--neutral-90); background: var(--surface-0);
  border: 1px solid var(--neutral-50); border-radius: var(--r-input);
}
.neg-motivo input:focus { border-color: var(--neutral-100); }
.neg-motivo .btn { flex: 1 1 auto; font-size: 12.5px; }

/* DESFECHO. Fechado e Declinado são terminais e não competem por largura com
   as quatro colunas que são a carteira viva — mas continuam a um clique. */
.neg-desfecho { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 14px; }
.neg-desfecho-peca {
  display: flex; align-items: center; gap: 8px; padding: 8px 12px;
  background: var(--surface-50); border: 1px solid var(--neutral-50);
  border-radius: var(--r-card); font: inherit; font-size: 13px;
  color: var(--neutral-100); text-align: left; cursor: pointer;
}
.neg-desfecho-peca:hover { background: var(--neutral-30); border-color: var(--neutral-90); }
.neg-desfecho-peca:focus-visible { outline: 2px solid var(--neutral-100); outline-offset: 2px; }
.neg-desfecho-peca[aria-expanded="true"] { border-color: var(--neutral-90); }
.neg-desfecho-ver { margin-left: auto; text-decoration: underline; text-underline-offset: 3px; }
@media (pointer: coarse) { .neg-desfecho-peca { min-height: 44px; } }
.neg-desfecho-peca .dot { width: 7px; height: 7px; border-radius: var(--r-pill); flex: none; }
.neg-desfecho-peca b { font-size: 13px; font-weight: 600; color: var(--neutral-100); }
.neg-desfecho-peca .n { font-size: 12px; color: var(--neutral-80); }
.neg-desfecho-peca .neg-col-valor { flex-basis: auto; }

/* O par de contas parecidas com teto de largura: em 1280 ele ocupava 1209px
   para dois nomes e duas contagens, com dois blocos de ~570px quase vazios. Os
   dois lados precisam ser lidos COMO PAR, e par não se lê a um metro. */
.dup { max-width: 720px; }

/* A frase de "nao se resolve aqui" saiu do cartao e virou frase de GRUPO: sai
   uma vez, e nao tres. Sem borda propria, porque o grupo ja tem a dele. */
.neg-grupo-frase.orfa-sem-saida { margin: 4px 0 8px; padding-top: 0; border-top: 0; }

/* Quando alguém abre os indicadores no telefone, os cartões mantêm o respiro
   da casa sem alterar a faixa compacta que abre a tela. */
@media (max-width: 860px) {
  #negocios-contexto .stat-grid { gap: 8px; margin-bottom: 10px; }
  #negocios-contexto .stat { padding: 10px 12px; gap: 10px; }
  #negocios-contexto .stat .v { font-size: 18px; }
  #negocios-contexto .stat .sub { font-size: 11.5px; }
  #negocios .neg-aviso { font-size: 12.5px; }
  #negocios .neg-resumo-pe { margin: 4px 0 10px; }
  #negocios .view-note { font-size: 12.5px; margin-bottom: 10px; }
  /* Vendedor e ordem dividem a linha: dois seletores de 40px empilhados são
     80px gastos para dizer o que cabe em 40. */
  #negocios .toolbar .search-field { flex: 1 1 100%; max-width: none; }
  #negocios .toolbar .filtro-campo { flex: 1 1 45%; min-width: 0; }
  #negocios .toolbar .filtro-campo select { width: 100%; }
}
/* A contagem por grupo no sumário da triagem some quando não cabe na linha:
   embaixo dela ela vira uma segunda e uma terceira linha de um controle que
   está FECHADO, e o número que importa — quantas visitas — já está ao lado. */
@media (max-width: 700px) {
  .neg-triagem-n { display: none; }
}

/* Dois cartões por linha no detalhe, inclusive em tela estreita. */
@media (max-width: 860px) {
  #negocios-contexto .stat-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  #negocios-contexto .stat { flex-direction: column; align-items: flex-start; gap: 6px; }
  #negocios-contexto .stat .t { font-size: 11.5px; }
}

/* O nome do vendedor é mais longo que "Maior valor", e `<select>` corta sem
   avisar: "Todos os vende" é um controle mentindo sobre o próprio estado. */
#negocios { container-type: inline-size; container-name: negocios; }
#negocios .toolbar { flex-wrap: nowrap; min-width: 0; }
#negocios .toolbar .search-field { flex: 1 1 240px; min-width: 180px; max-width: none; }
#negocios .toolbar .filtro-campo:nth-of-type(1) { flex: 0 1 210px; min-width: 170px; }
#negocios .toolbar .filtro-campo:nth-of-type(2) { flex: 0 1 165px; min-width: 140px; }
#negocios .toolbar .filtro-campo select { width: 100%; }
/* A base de 300px é só onde a busca divide a linha com os dois seletores. Solta,
   ela some com eles: item de base zero "cabe" em qualquer sobra, e os dois
   `<select>` viraram 5px de largura em 390 — controle que não se lê nem se
   acerta com o dedo. Em ≤860 a regra de cima manda a busca ocupar a linha. */
@media (min-width: 861px) {
  #negocios .toolbar .search-field { flex: 1 1 300px; }
}

@container negocios (max-width: 599px) {
  #negocios .toolbar { flex-wrap: wrap; }
  #negocios .toolbar .search-field { flex: 1 1 100%; min-width: 0; }
  #negocios .toolbar .filtro-campo:nth-of-type(1),
  #negocios .toolbar .filtro-campo:nth-of-type(2) { flex: 1 1 160px; min-width: 0; }
}

/* Abaixo de 1180 a toolbar não cabe ao lado do título: ela quebra por dentro,
   em duas linhas, e o `align-items: flex-end` do cabeçalho joga o "Negócios"
   para a segunda — o título parecendo estar depois dos controles. A casa já
   faz isto em ≤860; a tela de Negócios precisa antes porque tem três
   controles, e não um. */
@media (max-width: 1180px) {
  #negocios .tela-head .toolbar { margin-left: 0; width: 100%; }
}
/* ===== Cérebro (03/09 · revisão de UI) =====
   O que era próprio da aba — três cartões `.ec` com quadrado de iniciais,
   métricas dentro do cartão, formulário dentro do cartão e uma lista-cartão
   que não era nem a tabela da casa nem a linha de tarefa — MORREU. No lugar,
   o que as telas irmãs já usam: `.stat-grid` para o dado (Painel),
   `.tabela-visitas` para a lista (Visitas/Contatos/Features) e `.card` para a
   operação. Sobra aqui só o que nenhuma delas tem. */

/* ── O cabeçalho da tela ──────────────────────────────────────────────────
   O Cérebro é a única das seis telas que põe TRÊS controles no `.acoes`
   (select de empresa + atualizar + "Escrever à mão"); as outras cinco põem
   um ou nenhum. Sem quebra de linha o trio não cabia a 390px e a PÁGINA
   rolava de lado (scrollWidth 497 contra clientWidth 375) — a constituição
   não deixa. O `flex-wrap` fica AQUI dentro, e não na `.tela-head .acoes`
   global: mudar o cabeçalho das seis telas para resolver o aperto de uma é
   preço que a tela apertada não tem direito de cobrar das irmãs. */
#cerebro .tela-head .acoes { flex-wrap: wrap; }
/* O botão de atualizar é o mesmo desenho de `.toolbar .refresh`, mas aqui ele
   mora no cabeçalho, não numa toolbar — o seletor da folha não o alcança. Só
   dentro do Cérebro: nenhuma outra tela tem `.refresh` fora da toolbar. */
#cerebro .tela-head .acoes .refresh {
  width: 40px; height: 40px; flex: none; display: grid; place-items: center;
  border: 1px solid var(--neutral-50); border-radius: var(--r-input);
  background: var(--surface-0); color: var(--neutral-90); cursor: pointer;
  transition: background var(--t), border-color var(--t);
}
#cerebro .tela-head .acoes .refresh:hover { background: var(--neutral-30); border-color: var(--neutral-80); }
#cerebro .tela-head .acoes .refresh svg { width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; }

/* A faixa de acervo é a `.stat-grid` do Painel. No estreito ela NÃO empilha
   quatro cartões de largura total (240px de rolagem sem ganhar uma palavra de
   leitura): fica em 2×2, sobrepondo o `1fr` que a folha aplica a toda
   `.stat-grid` em ≤860. */
.cerebro-acervo { margin-bottom: 12px; }
/* `[hidden]` precisa vencer o `display: grid` da .stat-grid: sem WhatsApp
   conectado a faixa some inteira e dá lugar ao caminho para Integrações. */
.cerebro-acervo[hidden] { display: none; }
/* A legenda do `.stat` não tem regra própria na folha (o Painel convive com o
   corpo de 14px porque as legendas dele são curtas). Aqui a do período carrega
   data, data e expurgo: a 1280 ela quebrava em três linhas e esticava a faixa
   inteira para 154px, empurrando a primeira linha de conhecimento para 454px
   do topo. 12px é o tamanho de legenda do sistema (o mesmo de `.stat .t`). */
/* E `stretch` em vez do `center` da grade do Painel: com quatro cartões de
   alturas de texto diferentes, centralizar deixava 26px de folga embaixo do
   cartão de legenda curta e a mesma folga em cima — desalinhando os quatro
   rótulos, que é justamente o que se lê primeiro. */
.cerebro-acervo .stat { align-items: stretch; padding: 14px 18px; }
.cerebro-acervo .stat .ico { margin-top: 2px; }
.cerebro-acervo .stat .sub { font-size: 12px; line-height: 1.45; color: var(--neutral-80); margin-top: 3px; }
#cerebro-acervo-aviso .honest-empty { margin-bottom: 16px; }

/* Nota de 12,5px: sobrou para a última rodada e para a frase do primeiro uso.
   O custo da extração NÃO mora mais aqui (era a letra menor da tela em cima
   do botão que gasta) — mora em `.cerebro-custo`. */
.cerebro-nota { font-size: 12.5px; color: var(--neutral-80); margin-top: 10px; }
.cerebro-checkbox { display: inline-flex; align-items: center; align-self: center; gap: 6px; font-size: 13px; color: var(--neutral-90); }

/* ── A checklist do crivo ────────────────────────────────────────────────
   A moldura é a `.cerebro-checkbox` que a aba já tem (é ela que
   `test_cerebro_campos.py` aceita como envoltório de checkbox); este
   modificador só dá o ALVO: o checkbox nativo tem 18px de caixa, e a mão
   precisa de 44 — a mesma medida em 1280 e em 390, sem uma regra por largura.
   A barra da seleção é `.toolbar` com borda (nunca sombra) e fica `sticky` no
   topo da região: aprovar quarenta pares é rolar a lista, e a decisão não
   pode sair de tela junto com o cabeçalho. */
.cerebro-marcar { justify-content: center; min-width: 44px; min-height: 44px; cursor: pointer; }
.cerebro-marcar input { width: 18px; height: 18px; cursor: pointer; }
.tabela-cerebro .col-marcar { width: 44px; text-align: center; vertical-align: middle; }
.cerebro-revisao-barra {
  position: sticky; top: 0; z-index: 2;
  margin-bottom: 12px; padding: 8px 12px;
  background: var(--surface-0); border: 1px solid var(--neutral-50);
  border-radius: var(--r-input);
}
.cerebro-revisao-barra .recorte { margin: 0; margin-right: 4px; }

/* ── A lista: modificador de `.tabela-visitas`, só as colunas são outras ── */
.tabela-cerebro .col-par b { display: block; font-size: 14px; font-weight: 500; color: var(--neutral-100); }
.tabela-cerebro .col-par .badge { margin-left: 8px; vertical-align: middle; }
/* Cópia da medida de `.tabela-features .feature-resumo`: 62ch é onde a linha
   de resposta ainda se lê de uma vez. */
.cerebro-resposta {
  margin: 4px 0 0; font-size: 13px; line-height: 1.5;
  color: var(--neutral-75); max-width: 62ch;
}
.tabela-cerebro .col-tema { width: 128px; }
.tabela-cerebro .col-origem { width: 104px; font-size: 12.5px; color: var(--neutral-75); }
/* "Vezes perguntada" é o número que o gestor procura de verdade; coluna
   numérica à direita, tabular, ordenável pelo `<th>`. */
.tabela-cerebro .col-vezes { width: 92px; font-variant-numeric: tabular-nums; }
.tabela-cerebro th.col-vezes, .tabela-cerebro td.num { text-align: right; }
/* Estreita e centrada, como a coluna de papel da matriz de features: é onde o
   olho desce procurando o que está ligado. */
.tabela-cerebro .col-estado { width: 76px; text-align: center; vertical-align: middle; }
/* Item desativado: o interruptor apagado E o selo dizem o estado. A opacidade
   saiu — `neutral-75` a 55% sobre branco não passa em AA, e "apagado" lê-se
   como "carregando", não como "desligado de propósito" (§11). */
.tabela-cerebro tr[data-cerebro-ativo="0"] .col-par b { color: var(--neutral-75); font-weight: 500; }

/* A linha em edição ocupa a largura toda com os campos DA CASA (`.field`) —
   o `.cerebro-edicao-campo`, que redesenhava a moldura por fora do sistema,
   morreu com ela. */
.cerebro-linha-edicao td { padding: 16px; }
.cerebro-linha-edicao .field { margin-bottom: 12px; }
.cerebro-linha-edicao textarea {
  font: inherit; font-size: 13px; color: var(--neutral-90);
  background: var(--surface-0); border: 1px solid var(--neutral-50);
  border-radius: var(--r-input); padding: 8px 10px; resize: vertical; width: 100%;
}
.cerebro-linha-edicao textarea:focus-visible { outline: 2px solid var(--neutral-100); outline-offset: 2px; }
.cerebro-linha-edicao > td > div { display: flex; gap: 8px; flex-wrap: wrap; }

/* ── O cartão de operação ─────────────────────────────────────────────────
   Duas faixas: a tarefa de fundo em cima, a ação com custo embaixo. */
#cerebro-operacao { margin-top: 24px; }
#cerebro-operacao h3 { font-size: 14px; color: var(--neutral-100); margin-bottom: 10px; }
#cerebro-faixa-extracao {
  margin-top: 22px; padding-top: 22px; border-top: 1px solid var(--neutral-40);
}
#cerebro-aprofundar-acoes, #cerebro-extracao-acoes { display: flex; gap: 10px; flex-wrap: wrap; margin-top: 14px; }
#cerebro-extracao-datas { display: flex; gap: 10px; flex-wrap: wrap; margin-top: 12px; }
#cerebro-extracao-datas .field { flex: 1 1 160px; min-width: 0; }
#cerebro-extracao-periodo { width: fit-content; max-width: 100%; }

/* Estado do acervo em 14px, não em nota: é a frase que motiva o pedido. */
#cerebro-aprofundar-corpo > p { font-size: 14px; color: var(--neutral-90); margin: 0; }

/* Parâmetros de robô (conversas por dia, segundos entre pedidos, teto de
   pares, grupos): define-se uma vez e não se toca mais. `<details>` fechado,
   com os valores EM VIGOR no resumo — o campo vazio que parecia "nada
   definido" quando havia algo definido era pior que campo nenhum. */
.cerebro-avancado { margin-top: 14px; }
.cerebro-avancado > summary {
  font-size: 12.5px; color: var(--neutral-80); cursor: pointer;
  list-style: none; display: inline-flex; align-items: center; gap: 6px;
  padding: 6px 0;
}
.cerebro-avancado > summary::-webkit-details-marker { display: none; }
.cerebro-avancado > summary::before {
  content: "+"; width: 16px; height: 16px; flex: none;
  display: inline-grid; place-items: center; font-size: 13px;
  border: 1px solid var(--neutral-50); border-radius: 4px; color: var(--neutral-80);
}
.cerebro-avancado[open] > summary::before { content: "−"; }
.cerebro-avancado > summary:hover { color: var(--neutral-100); }
.cerebro-avancado > summary:focus-visible { outline: 2px solid var(--neutral-100); outline-offset: 2px; }
.cerebro-avancado > div { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 10px; }
.cerebro-avancado .field { flex: 1 1 180px; min-width: 0; max-width: 260px; }

/* Barra de andamento: só existe quando o serviço mandou o TOTAL. Sem total,
   fica a frase — uma barra que inventa proporção é pior que barra nenhuma. */
.cerebro-andamento {
  height: 4px; margin-top: 10px; border-radius: 2px;
  background: var(--neutral-40); overflow: hidden;
}
.cerebro-andamento i { display: block; height: 100%; background: var(--neutral-100); }

/* O custo da extração deixa de ser a letra menor da tela: três figuras no
   formato da casa — rótulo pequeno em cima, número grande e tabular embaixo. */
.cerebro-custo { display: flex; flex-wrap: wrap; gap: 28px; margin-top: 14px; }
.cerebro-custo > div { display: flex; flex-direction: column; }
.cerebro-custo .rot { font-size: 12px; color: var(--neutral-80); }
.cerebro-custo .num {
  font-size: 22px; font-weight: 500; color: var(--neutral-100);
  letter-spacing: -.02em; font-variant-numeric: tabular-nums; margin-top: 2px;
}

@media (max-width: 900px) {
  /* A linha vira cartão pela base `.tabela-visitas`; aqui só o mapeamento das
     colunas que são outras. O interruptor e o "Editar" encostam um no outro à
     direita da pergunta, e tema/origem/vezes descem para uma linha de apoio. */
  /* A coluna de marcar entra como primeira do cartão — no estreito o `<thead>`
     some (base `.tabela-visitas`), e quem seleciona a lista inteira é o
     "Selecionar todos" da barra. */
  .tabela-cerebro tbody tr { grid-template-columns: auto minmax(0, 1fr) auto auto; }
  .tabela-cerebro .col-marcar { grid-column: 1; grid-row: 1 / span 2; width: auto; align-self: start; }
  .tabela-cerebro .col-par { grid-column: 2; grid-row: 1; }
  .cerebro-resposta { max-width: none; }
  .tabela-cerebro .col-estado { grid-column: 3; grid-row: 1; width: auto; }
  .tabela-cerebro .col-acao { display: block; grid-column: 4; grid-row: 1; width: auto; }
  .tabela-cerebro .col-tema, .tabela-cerebro .col-origem, .tabela-cerebro .col-vezes {
    grid-row: 2; font-size: 12.5px; width: auto;
  }
  .tabela-cerebro .col-tema { grid-column: 2; margin-top: 8px; }
  .tabela-cerebro .col-origem { grid-column: 3; margin-top: 8px; white-space: nowrap; }
  .tabela-cerebro td.col-vezes { grid-column: 4; margin-top: 8px; text-align: right; }
  .cerebro-linha-edicao td { grid-column: 1 / -1; padding: 0; }
}

@media (max-width: 860px) {
  /* 2×2, não quatro empilhados. */
  .stat-grid.cerebro-acervo { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .stat-grid.cerebro-acervo .stat { padding: 14px; gap: 10px; }
  /* A barra de filtros compacta: a folha põe `flex: 1 1 100%` em toda
     `.filtro-campo` no estreito — quatro linhas, 202px de cromo entre o gestor
     e a primeira resposta. Aqui a busca fica sozinha em cima e os selects
     dividem o que sobra. A base de 170px é MEDIDA, não escolhida: é a largura
     que "Qualquer origem" — o mais longo dos três rótulos — precisa para
     aparecer inteiro dentro do controle nativo (167px a 390). Com ela, a 768
     os três cabem na mesma linha; a 390 dois ficam em cima e um embaixo, que
     é o preço certo — a régua da casa não corta palavra para poupar linha. */
  /* No celular a folha estica todo `.btn` a 100% (alvo de toque). No
     cabeçalho da tela isso põe "Escrever à mão" numa TERCEIRA linha, sozinho,
     ao lado de um ícone de 40px — o `.acoes` tem de caber em duas: o select
     numa, o ícone e o botão na outra. */
  #cerebro .tela-head .acoes .btn { width: auto; }
  /* Mesmo motivo na barra da seleção: esticados a 100% (alvo de toque), o
     "Aprovar" e o "Recusar" viram uma linha cada e a barra come 176px de
     altura sobre a primeira pergunta. Lado a lado cabem em 390 — a altura de
     44px, que é o alvo, fica. */
  .cerebro-revisao-barra .btn { width: auto; }
  #cerebro-filtros .filtro-campo { flex: 1 1 170px; min-width: 0; }
  #cerebro-filtros .filtro-campo select { max-width: none; width: 100%; }
  /* Grátis antes de caro: o que gasta fica embaixo. */
  #cerebro-extracao-acoes { flex-direction: column; align-items: stretch; }
  #cerebro-extracao-acoes .btn { width: 100%; }
  .cerebro-custo { gap: 18px; }
  .cerebro-custo .num { font-size: 20px; }
}

/* ============================================================
   REVISAR INDICIOS DE NAO COMERCIAL (dialogo `#conv-nc-dialog`)
   ============================================================
   DUAS COLUNAS, E POR ID. `.relation-option` nasce com TRES
   (`auto minmax(0,1fr) auto`, relatorio.css): a terceira e o radio
   "Principal" do dialogo de visita, que aqui nao existe — sem esta regra
   sobraria uma coluna vazia comendo largura do texto. Por id porque
   `relatorio.css` carrega DEPOIS de `console.css`: regra de mesma
   especificidade perde a cascata.

   A 390 nada rola na horizontal: a coluna de texto e `minmax(0, 1fr)` e
   `overflow-wrap: anywhere` quebra o nome de empresa que vem sem espaco.
   Nenhum `@media` novo — o indice de cortes desta folha nao muda. */
#conv-nc-dialog .relation-option { grid-template-columns: auto minmax(0, 1fr); align-items: start; overflow-wrap: anywhere; }
#conv-nc-dialog .relation-option input { margin-top: 3px; }
.nc-bloco { display: grid; gap: 2px; min-width: 0; }
/* DUAS LINHAS E CORTA, no molde de `.lp-abrir`. `text-overflow: ellipsis` esta
   proibido aqui: ele corta no meio da palavra, e o motivo vem de modelo — meia
   palavra num motivo de recusa e pior que motivo nenhum. */
.nc-motivo { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; }

/* Estado inicial do WhatsApp: conectar é a ação; o exemplo nunca vira dado. */
.conv-fila-controles { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; padding: 10px 0; font-size: .875rem; }
.conv-fila-cobertura { margin-left: auto; color: var(--neutral-75); font-size: .8125rem; font-variant-numeric: tabular-nums; }
.conv-fila-revisao { display: flex; align-items: center; gap: 8px; padding: 10px 12px; margin-bottom: 8px; border-radius: var(--r-input); background: var(--amber-tint); color: var(--amber-ink); font-size: .875rem; }
.conv-fila-revisao svg { width: 18px; height: 18px; flex: none; fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }
.conv-fila-revisao .link-acao { margin-left: auto; min-height: 32px; }
.conv-fila-contexto { color: var(--neutral-75); font-size: .8125rem; padding: 0 0 10px; }
#conv-inicial[hidden], #conv-fila[hidden], #conv-conexoes[hidden] { display: none; }
.conv-inicial-conectar { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 20px; padding: 24px 0; }
.conv-inicial-conectar h2, .conv-demo h2, .conv-inicial-espera h2 { font-size: 1.375rem; }
.conv-inicial-conectar p, .conv-inicial-espera p { margin-top: 8px; font-size: 1rem; color: var(--neutral-75); }
.conv-inicial-conectar .btn { min-height: 48px; font-size: 1rem; }
.conv-demo { overflow: hidden; }
.conv-pergunta-link { border: 0; background: none; padding: 4px 0; color: var(--neutral-90); font: inherit; text-align: left; cursor: pointer; text-decoration: underline; text-underline-offset: 3px; }
.conv-pergunta-link:hover { color: var(--blue-ink); }
.conv-pergunta-link:focus-visible { outline: 2px solid var(--neutral-100); outline-offset: 2px; }
.msg-responder { position: absolute; top: 5px; right: 5px; width: 28px; height: 28px; border: 0; border-radius: var(--r-input); background: none; color: inherit; font-size: 20px; cursor: pointer; opacity: .65; }
.msg-responder:hover, .msg-responder:focus-visible { opacity: 1; outline: 1px solid currentColor; }
.msg-citacao { display: block; max-width: 100%; width: 100%; margin-bottom: 8px; padding: 8px 10px; border: 0; border-left: 3px solid var(--blue-ink); border-radius: var(--r-input); background: var(--neutral-30); color: var(--neutral-90); text-align: left; font: inherit; cursor: pointer; }
.msg-citacao strong, .msg-resposta-preview strong { display: block; font-size: 12px; color: var(--blue-ink); }
.msg-citacao span, .msg-resposta-preview span { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; margin-top: 3px; }
.msg-resposta-preview { display: flex; align-items: center; gap: 12px; padding: 10px 16px; background: var(--neutral-30); border-left: 3px solid var(--blue-ink); font-size: 13px; }
.msg-resposta-preview > div { flex: 1; min-width: 0; }
.msg-resposta-preview .btn { flex: none; width: 44px; min-height: 44px; }
.msg.evidencia-alvo { outline: 3px solid var(--blue-ink); outline-offset: 3px; }
.conv-demo-cabecalho { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 16px; padding: 24px; border-bottom: 1px solid var(--neutral-50); }
.conv-demo-selo { display: inline-block; padding: 5px 9px; margin-bottom: 12px; border-radius: var(--r-badge); background: var(--amber-tint); color: var(--amber-ink); font-size: .875rem; font-weight: 600; }
.conv-demo-cabecalho p { font-size: .875rem; color: var(--neutral-75); }
.conv-demo-layout { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); }
.conv-demo-mensagens, .conv-demo-analise { min-width: 0; padding: 24px; }
.conv-demo h3 { font-size: 1rem; font-weight: 600; margin-bottom: 20px; }
.conv-demo-mensagens { display: flex; flex-direction: column; gap: 16px; background: var(--surface-50); }
.conv-demo-mensagens h3 { margin-bottom: 4px; }
.conv-demo-balao { max-width: 88%; padding: 12px 16px; border: 1px solid var(--neutral-50); border-radius: var(--r-card); font-size: 1rem; line-height: 1.5; }
.conv-demo-balao.cliente { align-self: flex-start; background: var(--surface-0); }
.conv-demo-balao.loja { align-self: flex-end; background: var(--blue-tint); border-color: var(--blue-tint); }
.conv-demo-analise { display: grid; align-content: start; gap: 20px; }
.conv-demo-analise h3 { margin-bottom: 0; }
.conv-demo-analise article + article { border-top: 1px solid var(--neutral-50); padding-top: 20px; }
.conv-demo h4 { font-size: 1rem; font-weight: 600; margin: 8px 0; }
.conv-demo-analise p, .conv-demo blockquote { font-size: .875rem; line-height: 1.6; color: var(--neutral-75); }
.conv-demo footer { padding: 16px 24px; border-top: 1px solid var(--neutral-50); font-size: .875rem; color: var(--neutral-75); }
.conv-inicial-espera { padding: 32px; }
.conv-inicial-espera .btn { margin-top: 20px; }
.conv-conexao-erro { display: flex; align-items: center; flex-wrap: wrap; justify-content: space-between; gap: 12px; padding: 12px 16px; border: 1px solid var(--neutral-50); border-radius: var(--r-input); margin-bottom: 16px; }
@media (max-width: 860px) {
  .conv-demo-layout { grid-template-columns: minmax(0, 1fr); }
  .conv-inicial-conectar .btn { width: 100%; }
}

/* Datas usam o mesmo controle do app, mesmo fora de `.field`.
   Preservamos o calendário nativo, digitação, validação e navegação por teclado.
   O popup do calendário continua pertencendo ao navegador/sistema operacional. */
input:is([type="date"], [type="datetime-local"], [type="month"], [type="time"]) {
  display: block; width: 100%; min-width: 0; max-width: 100%;
  min-height: 44px; padding: 8px 12px;
  border: 1px solid var(--neutral-50); border-radius: var(--r-input);
  background: var(--surface-0); color: var(--neutral-90);
  font: 400 1rem/1.5 var(--font); font-variant-numeric: tabular-nums;
  color-scheme: light;
  transition: border-color var(--t), background var(--t);
}
input:is([type="date"], [type="datetime-local"], [type="month"], [type="time"]):hover:not(:disabled):not([readonly]) {
  border-color: var(--neutral-80);
}
input:is([type="date"], [type="datetime-local"], [type="month"], [type="time"]):focus-visible {
  border-color: var(--neutral-100);
  outline: 2px solid var(--neutral-100); outline-offset: 2px;
}
input:is([type="date"], [type="datetime-local"], [type="month"], [type="time"]):is(:disabled, [readonly]) {
  background: var(--neutral-30); color: var(--neutral-75);
}
input:is([type="date"], [type="datetime-local"], [type="month"], [type="time"]):disabled { cursor: not-allowed; }
input:is([type="date"], [type="datetime-local"], [type="month"], [type="time"])::-webkit-calendar-picker-indicator {
  width: 18px; height: 18px; margin-left: 8px; cursor: pointer; flex: none;
}
input:is([type="date"], [type="datetime-local"], [type="month"], [type="time"]):disabled::-webkit-calendar-picker-indicator { cursor: not-allowed; }
.filtro-campo:has(input:is([type="date"], [type="datetime-local"], [type="month"], [type="time"])) {
  min-width: 0; flex: 1 1 180px; max-width: 240px;
}
@media (max-width: 560px) {
  .filtro-campo:has(input:is([type="date"], [type="datetime-local"], [type="month"], [type="time"])) { max-width: none; }
}

/* Task list, calendar and board share the persisted task model. */
#tarefas-filtros { flex-wrap: nowrap; }
#tarefas-filtros .filtro-campo { flex: 0 1 220px; min-width: 0; max-width: 220px; }
#tarefas-filtros .filtro-campo select, #tarefas-filtros .filtro-campo input[type="date"] {
  width: 100%; min-width: 0; max-width: 100%; height: 40px; min-height: 40px;
  padding: 0 12px; font: inherit; font-size: 13px;
}
#tarefas-filtros .filtro-campo select { padding-right: 30px; }
.task-group { margin: 24px 0 32px; }
.task-group > .section-heading { padding-bottom: 12px; border-bottom: 1px solid var(--neutral-50); margin-bottom: 0; }
.task-group .section-heading h2 { font-size: 16px; }
.task-group .section-heading p { font-size: 11px; }
.task-row { display: grid; grid-template-columns: minmax(200px, 1fr) auto 160px 100px; gap: 8px 16px; align-items: center; padding: 14px 8px; border-bottom: 1px solid var(--neutral-40); }
.task-row:hover { background: var(--surface-50); }
.task-row[data-tarefa-linha] { cursor: pointer; }
.task-row[data-tarefa-linha]:focus-within { outline: 2px solid var(--blue-ink); outline-offset: -2px; }
.task-date-popover { position: fixed; inset: auto; margin: 0; width: 280px; padding: 12px; color: var(--neutral-100); background: var(--surface-0); border: 1px solid var(--neutral-50); border-radius: var(--r-input); box-shadow: var(--shadow-float); }
.task-date-popover header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px; font-size: 13px; }
.task-date-popover button { font: inherit; color: inherit; background: transparent; border: 0; border-radius: 4px; cursor: pointer; min-height: 32px; }
.task-date-popover header button { width: 32px; font-size: 22px; }
.task-calendar-grid { display: grid; grid-template-columns: repeat(7,1fr); gap: 2px; text-align: center; font-size: 12px; }
.task-calendar-grid span { color: var(--neutral-75); padding: 4px 0; }
.task-date-popover button:hover { background: var(--blue-tint); }
.task-calendar-grid button.today { outline: 1px solid var(--blue-ink); outline-offset: -1px; }
.task-calendar-grid button.selected { color: var(--surface-0); background: var(--blue-ink); }
.task-action.task-action-start { color: var(--blue-ink); background: var(--blue-tint); border-color: var(--blue-ink); }
.task-action.task-action-complete { color: var(--green-ink); background: var(--green-tint); border-color: var(--green-ink); }
.task-main { min-width: 0; }
.task-marker, .task-contact, .task-assignee, .task-origin, .task-date-visual { display: none; }
.task-title, .task-date, .task-action, .task-day { font: inherit; color: inherit; background: transparent; border: 0; cursor: pointer; }
.task-title { text-align: left; font-weight: 500; color: var(--neutral-100); line-height: 1.5; }
.task-title:hover, .task-date:hover { text-decoration: underline; }
.task-meta { color: var(--neutral-80); font-size: 12px; margin-top: 3px; overflow-wrap: anywhere; }
.task-date { text-align: left; font-size: 13px; padding: 8px; border-radius: var(--r-input); }
.task-date.no-date { color: var(--neutral-80); }
.task-action { padding: 7px 10px; border: 1px solid var(--neutral-50); border-radius: var(--r-input); font-size: 12px; }
.task-action:hover { background: var(--neutral-30); }
.task-title:disabled, .task-date:disabled, .task-action:disabled { opacity: .5; cursor: not-allowed; text-decoration: none; }
.task-actions { display: flex; gap: 6px; }
.task-details { grid-column: 1 / -1; font-size: 12px; color: var(--neutral-80); }
.task-details summary { cursor: pointer; width: fit-content; }
.task-details-icon { display: none; }
.task-details .tk-arg { margin: 10px 0; }
.task-details select { margin-top: 10px; font: inherit; max-width: 100%; }
.task-board { display: grid; grid-template-columns: repeat(3,minmax(0,1fr)); gap: 20px; margin-top: 24px; }
.task-column { min-width: 0; min-height: 180px; border-top: 3px solid var(--neutral-50); padding-top: 14px; }
.task-column:nth-child(2) { border-color: var(--blue-ink); }
.task-column:nth-child(3) { border-color: var(--green-ink); }
.task-column h2 { font-size: 15px; display: flex; justify-content: space-between; margin-bottom: 14px; }
.task-column h2 span { font-size: 12px; color: var(--neutral-80); }
.task-column .task-row { grid-template-columns: minmax(0,1fr) auto; border: 1px solid var(--neutral-50); border-radius: var(--r-input); padding: 14px; margin-bottom: 10px; gap: 12px; }
.task-column .task-main, .task-column .task-state { grid-column: 1 / -1; }
.task-column .task-state:empty { display: none; }
.task-column .task-date { padding: 0; }
.task-column [draggable="true"] { cursor: grab; }
.task-context { margin: 16px 0; color: var(--neutral-80); font-size: 13px; }
.task-context blockquote { border-left: 2px solid var(--neutral-50); padding-left: 12px; margin: 12px 0; }
.task-hint { color: var(--amber-ink); margin-top: 8px; }
.task-archive { margin-top: 24px; }
#tar-agenda .ev { display: block; width: 100%; border: 0; text-align: left; font: inherit; font-size: 11px; cursor: pointer; }
#tar-agenda .task-day { width: 28px; height: 28px; border-radius: var(--r-badge); }
#tar-agenda .task-day:hover { background: var(--neutral-30); }
/* The list has fixed visual columns; the board keeps its compact cards. */
.task-list-columns { display: grid; grid-template-columns: minmax(240px,1fr) minmax(180px,.9fr) 120px 150px 76px; gap: 0; padding: 6px 38px 6px 38px; color: var(--neutral-80); background: var(--surface-50); border: 1px solid var(--neutral-50); font-size: 10px; text-transform: uppercase; letter-spacing: .04em; }
.task-list-columns > span { padding: 0 8px; border-right: 1px solid var(--neutral-50); }
:is(#tar-quadro, #deal-task-list) { overflow-x: auto; container-type: inline-size; container-name: tarefas-lista; }
:is(#tar-quadro, #deal-task-list) .task-group { margin: 6px 0 0; border: 1px solid var(--neutral-50); }
:is(#tar-quadro, #deal-task-list) .task-group > .section-heading { padding: 4px 8px; background: var(--surface-50); border: 0; border-bottom: 1px solid var(--neutral-50); border-left: 3px solid var(--neutral-50); border-radius: 0; }
:is(#tar-quadro, #deal-task-list) .task-group > .section-heading > div { display: flex; align-items: center; gap: 12px; }
:is(#tar-quadro, #deal-task-list) .section-heading h2 { order: 0; font-size: 11px; margin: 0; }
:is(#tar-quadro, #deal-task-list) .section-heading p { order: 1; font-size: 10px; margin: 0; color: var(--neutral-80); letter-spacing: .03em; }
.task-group-toggle { display: flex; align-items: center; gap: 10px; font: inherit; color: inherit; background: transparent; border: 0; cursor: pointer; }
.task-group-toggle svg { width: 12px; height: 12px; fill: none; stroke: currentColor; stroke-width: 2; transition: transform var(--t); }
.task-group-toggle[aria-expanded="true"] svg { transform: rotate(90deg); }
.task-group-count { min-width: 22px; height: 20px; padding: 1px 5px; display: inline-grid; place-items: center; border-radius: var(--r-badge); background: var(--surface-0); color: var(--neutral-75); font-size: 11px; font-weight: 500; }
.task-group-rows[hidden] { display: none; }
:is(#tar-quadro, #deal-task-list) [data-task-group="hoje"] > .section-heading { background: var(--task-today-tint); border-color: var(--task-today-border); }
:is(#tar-quadro, #deal-task-list) [data-task-group="atrasadas"] > .section-heading { background: var(--red-tint); border-color: var(--red-ink); }
:is(#tar-quadro, #deal-task-list) [data-task-group="sem_data"] > .section-heading, :is(#tar-quadro, #deal-task-list) [data-task-group="sem_dono"] > .section-heading { background: var(--red-tint); border-color: var(--red-ink); }
:is(#tar-quadro, #deal-task-list) [data-task-group="fechadas"] > .section-heading { background: var(--green-tint); border-color: var(--green-ink); }
:is(#tar-quadro, #deal-task-list) .task-row { grid-template-columns: 30px minmax(240px,1fr) minmax(180px,.9fr) 120px 150px 76px 30px; gap: 0; padding: 4px 8px; min-height: 34px; }
:is(#tar-quadro, #deal-task-list) .task-row:last-child { border-bottom: 0; }
:is(#tar-quadro, #deal-task-list) .task-main, :is(#tar-quadro, #deal-task-list) .task-contact, :is(#tar-quadro, #deal-task-list) .task-assignee, :is(#tar-quadro, #deal-task-list) .task-date, :is(#tar-quadro, #deal-task-list) .task-actions { padding: 0 8px; border-right: 1px solid var(--neutral-40); min-height: 24px; }
:is(#tar-quadro, #deal-task-list) .task-row:nth-child(even) { background: var(--surface-50); }
:is(#tar-quadro, #deal-task-list) .task-row:hover { background: var(--blue-tint); }
:is(#tar-quadro, #deal-task-list) .task-marker { display: grid; place-items: center; width: 20px; height: 20px; border-radius: var(--r-pill); background: var(--neutral-30); color: var(--neutral-80); }
:is(#tar-quadro, #deal-task-list) .task-marker svg { width: 14px; height: 14px; }
.task-marker svg { width: 19px; height: 19px; stroke: currentColor; stroke-width: 1.8; fill: none; stroke-linecap: round; stroke-linejoin: round; }
:is(#tar-quadro, #deal-task-list) .task-marker.running { background: var(--blue-tint); color: var(--blue-ink); }
:is(#tar-quadro, #deal-task-list) .task-marker.done { background: var(--green-tint); color: var(--green-ink); }
:is(#tar-quadro, #deal-task-list) .task-marker.late { background: var(--red-tint); color: var(--red-ink); }
.task-title-wrap { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
:is(#tar-quadro, #deal-task-list) .task-title-wrap { flex-wrap: nowrap; gap: 6px; }
:is(#tar-quadro, #deal-task-list) .task-title { font-size: 12px; line-height: 24px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
:is(#tar-quadro, #deal-task-list) .task-state { flex: none; }
:is(#tar-quadro, #deal-task-list) .task-state .badge, :is(#tar-quadro, #deal-task-list) .task-state .tag { font-size: 9px; padding: 2px 4px; }
:is(#tar-quadro, #deal-task-list) .task-combined-meta { display: none; }
:is(#tar-quadro, #deal-task-list) .task-main { grid-column: auto; }
:is(#tar-quadro, #deal-task-list) .task-origin { display: none; }
:is(#tar-quadro, #deal-task-list) .task-contact { display: flex; align-items: center; gap: 6px; min-width: 0; }
:is(#tar-quadro, #deal-task-list) .task-contact > span:last-child { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
:is(#tar-quadro, #deal-task-list) .task-contact b { font-size: 11px; }
:is(#tar-quadro, #deal-task-list) .task-contact small { display: inline; font-size: 10px; margin: 0; }
:is(#tar-quadro, #deal-task-list) .task-contact small::before { content: " · "; }
.task-contact b { font-size: 13px; font-weight: 500; color: var(--neutral-90); }
.task-contact small { display: block; color: var(--neutral-80); font-size: 11px; margin-top: 2px; }
.task-contact-avatar { display: grid; place-items: center; flex: none; width: 34px; height: 34px; background: var(--violet-tint); color: var(--violet-ink); border-radius: var(--r-input); font-size: 11px; font-weight: 500; }
.task-contact-avatar .avatar.lista[data-avatar-contato] { width: 34px; height: 34px; flex: 0 0 34px; border-radius: inherit; background-color: inherit; color: inherit; font-size: inherit; }
:is(#tar-quadro, #deal-task-list) .task-contact-avatar, :is(#tar-quadro, #deal-task-list) .task-contact-avatar .avatar.lista[data-avatar-contato] { width: 24px; height: 24px; flex: 0 0 24px; font-size: 9px; }
:is(#tar-quadro, #deal-task-list) .task-assignee { display: flex; align-items: center; gap: 6px; font-size: 11px; white-space: nowrap; overflow: hidden; }
:is(#tar-quadro, #deal-task-list) .task-owner-avatar { display: none; }
.task-owner-avatar { display: grid; place-items: center; flex: none; width: 27px; height: 27px; background: var(--neutral-30); color: var(--neutral-90); border-radius: var(--r-pill); font-size: 10px; }
.task-owner-avatar.unassigned { background: var(--amber-tint); color: var(--amber-ink); }
:is(#tar-quadro, #deal-task-list) .task-date { padding: 0 8px; }
:is(#tar-quadro, #deal-task-list) .task-date-plain { display: none; }
:is(#tar-quadro, #deal-task-list) .task-date-visual { display: flex; align-items: center; padding: 3px 5px; width: fit-content; border: 1px solid transparent; border-radius: var(--r-badge); }
:is(#tar-quadro, #deal-task-list) .task-date-caption { display: flex; align-items: center; white-space: nowrap; }
:is(#tar-quadro, #deal-task-list) .task-date-caption b, :is(#tar-quadro, #deal-task-list) .task-date-caption b.task-date-formatted { font-size: 11px; text-transform: none; }
:is(#tar-quadro, #deal-task-list) .task-date-caption small { margin: 0; font-size: 10px; }
:is(#tar-quadro, #deal-task-list) .task-date-caption small::before { content: " · "; }
:is(#tar-quadro, #deal-task-list) .task-date-caption .task-date-all-day, :is(#tar-quadro, #deal-task-list) .task-date.no-date small { display: none; }
:is(#tar-quadro, #deal-task-list) .task-date:hover { text-decoration: none; }
:is(#tar-quadro, #deal-task-list) .task-date:hover .task-date-visual { background: var(--neutral-30); }
.task-date-caption b { display: block; font-size: 11px; font-weight: 500; text-transform: uppercase; }
.task-date-caption b.task-date-formatted { font-size: 14px; font-variant-numeric: tabular-nums; }
.task-date-caption small { display: block; font-size: 10px; color: var(--neutral-80); margin-top: 1px; }
:is(#tar-quadro, #deal-task-list) .task-date.running .task-date-visual { border-color: var(--blue-tint); background: var(--blue-tint); color: var(--blue-ink); }
:is(#tar-quadro, #deal-task-list) [data-task-group="hoje"] .task-date .task-date-visual { background: var(--task-today-tint); border-color: var(--task-today-tag-border); color: var(--task-today-ink); }
:is(#tar-quadro, #deal-task-list) [data-task-group="atrasadas"] .task-date .task-date-visual { background: var(--red-tint); border-color: var(--red-tint); color: var(--red-ink); }
:is(#tar-quadro, #deal-task-list) .task-date.late .task-date-visual { background: var(--red-tint); border-color: var(--red-tint); color: var(--red-ink); }
:is(#tar-quadro, #deal-task-list) .task-date.no-date .task-date-visual { border-style: dashed; }
:is(#tar-quadro, #deal-task-list) .task-details { grid-column: 7; grid-row: 1; margin: 0; justify-self: center; }
:is(#tar-quadro, #deal-task-list) .task-details summary { font-size: 14px; list-style: none; }
:is(#tar-quadro, #deal-task-list) .task-details summary::-webkit-details-marker { display: none; }
:is(#tar-quadro, #deal-task-list) .task-details-label { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }
:is(#tar-quadro, #deal-task-list) .task-details-icon { display: inline; }
:is(#tar-quadro, #deal-task-list) .task-details[open] { grid-column: 2 / -1; grid-row: 2; justify-self: stretch; padding: 8px; }
:is(#tar-quadro, #deal-task-list) .task-details[open] .task-details-label { position: static; width: auto; height: auto; clip-path: none; }
:is(#tar-quadro, #deal-task-list) .task-details[open] .task-details-icon { display: none; }
:is(#tar-quadro, #deal-task-list) .task-actions .task-action { padding: 3px 7px; font-size: 10px; line-height: 16px; }
@media (max-width: 1180px) {
  .task-list-columns { grid-template-columns: minmax(180px,1fr) minmax(180px,.9fr) 110px 150px 76px; }
  :is(#tar-quadro, #deal-task-list) .task-row { grid-template-columns: 30px minmax(180px,1fr) minmax(180px,.9fr) 110px 150px 76px 30px; }
}
@media (max-width: 860px) {
  #tarefas-filtros .filtro-campo select, #tarefas-filtros .filtro-campo input[type="date"] { height: 44px; min-height: 44px; }
  .task-board { grid-template-columns: 1fr; }
  .task-row { grid-template-columns: minmax(0,1fr) auto; gap: 8px; }
  .task-main { grid-column: 1 / -1; }
  .task-state:empty { display: none; }
  .task-date { padding-left: 0; }
  .task-state { grid-column: 1 / -1; }
}
@media (max-width: 560px) {
  #tarefas-filtros { flex-wrap: wrap; }
  #tarefas-filtros .filtro-campo { flex: 1 1 calc(50% - 5px); max-width: none; }
}
/* A lista muda de forma pela largura útil, inclusive com a sidebar aberta. */
@container tarefas-lista (max-width: 900px) {
  .task-list-columns { display: none; }
  :is(#tar-quadro, #deal-task-list) .task-group { min-width: 0; }
  :is(#tar-quadro, #deal-task-list) .task-row { grid-template-columns: 24px minmax(0,1fr) auto; gap: 10px; padding: 14px; }
  :is(#tar-quadro, #deal-task-list) .task-main { grid-column: 2; }
  :is(#tar-quadro, #deal-task-list) .task-title-wrap { flex-wrap: wrap; }
  :is(#tar-quadro, #deal-task-list) .task-title { white-space: normal; line-height: 1.5; }
  :is(#tar-quadro, #deal-task-list) .task-main, :is(#tar-quadro, #deal-task-list) .task-contact, :is(#tar-quadro, #deal-task-list) .task-assignee,
  :is(#tar-quadro, #deal-task-list) .task-date, :is(#tar-quadro, #deal-task-list) .task-actions { border-right: 0; padding: 0; }
  :is(#tar-quadro, #deal-task-list) .task-contact, :is(#tar-quadro, #deal-task-list) .task-assignee, :is(#tar-quadro, #deal-task-list) .task-date,
  :is(#tar-quadro, #deal-task-list) .task-actions { grid-column: 2 / -1; }
  :is(#tar-quadro, #deal-task-list) .task-contact > span:last-child, :is(#tar-quadro, #deal-task-list) .task-assignee { white-space: normal; }
  :is(#tar-quadro, #deal-task-list) .task-details { grid-column: 3; grid-row: 1; }
  :is(#tar-quadro, #deal-task-list) .task-actions .task-action { min-height: 44px; padding: 8px 12px; font-size: 12px; }
}
#admin-sistema { container-type: inline-size; container-name: sistema; }
.sistema-toolbar { display: flex; align-items: center; justify-content: space-between; gap: 16px; flex-wrap: wrap; margin-bottom: 20px; }
#admin-sistema h2 { font-size: 20px; font-weight: 650; margin: 0 0 6px; }
.sistema-toolbar p, .sistema-stat p, .sistema-modelo p, .sistema-atividade p { color: var(--neutral-80); font-size: 14px; }
.sistema-controles { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
#sistema-periodo { min-height: 44px; width: auto; max-width: 100%; padding: 0 12px; border: 1px solid var(--neutral-50); border-radius: 10px; background: white; font: inherit; color: inherit; }
.sistema-kpis { display: grid; grid-template-columns: repeat(4,minmax(0,1fr)); gap: 12px; margin: 12px 0 20px; }
.sistema-stat { border: 1px solid var(--neutral-50); border-top: 3px solid var(--blue-ink); border-radius: 12px; background: white; padding: 16px; min-width: 0; }
.sistema-stat.red { border-top-color: var(--red-ink); }
.sistema-stat.amber { border-top-color: var(--amber-ink); }
.sistema-stat.green { border-top-color: var(--green-ink); }
.sistema-stat > span { display: block; font-size: 15px; font-weight: 650; }
.sistema-stat > strong { display: block; font-size: 24px; line-height: 1.35; margin: 8px 0; font-variant-numeric: tabular-nums; }
.sistema-alert { background: var(--red-tint); border: 1px solid var(--neutral-50); border-radius: 10px; padding: 12px 16px; display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
.sistema-disclaimer { padding: 14px 16px; border: 1px solid var(--neutral-50); background: var(--amber-tint); border-radius: 10px; color: var(--amber-ink); font-size: 14px; line-height: 1.6; margin-bottom: 16px; }
.sistema-duas-colunas { display: grid; grid-template-columns: repeat(2,minmax(0,1fr)); gap: 16px; }
.sistema-panel { background: white; border: 1px solid var(--neutral-50); padding: 20px; border-radius: 12px; margin-bottom: 16px; min-width: 0; }
.sistema-modelo { padding: 16px 0; border-bottom: 1px solid var(--neutral-50); }
.sistema-modelo:last-child { border-bottom: 0; }
.sistema-modelo h3, .sistema-atividade h3 { font-size: 16px; font-weight: 650; margin: 0 0 4px; }
.sistema-modelo > strong { display: block; font-size: 21px; margin-bottom: 6px; }
.sistema-modelo dl { display: grid; grid-template-columns: repeat(3,minmax(0,1fr)); gap: 12px; margin: 14px 0 0; }
.sistema-modelo dt { font-size: 13px; color: var(--neutral-80); }
.sistema-modelo dd { margin: 4px 0 0; font-weight: 600; }
.sistema-dias { max-height: 380px; overflow-y: auto; }
.sistema-dia { display: grid; grid-template-columns: 90px minmax(0,1fr) 140px; align-items: center; gap: 12px; padding: 10px 0; font-size: 14px; }
.sistema-dia meter { width: 100%; height: 14px; }
.sistema-dia strong { text-align: right; font-variant-numeric: tabular-nums; }
.sistema-atividade { display: grid; grid-template-columns: minmax(0,1fr) auto auto; align-items: center; gap: 16px; padding: 14px 0; border-bottom: 1px solid var(--neutral-50); }
.sistema-atividade:last-child { border-bottom: 0; }
#admin-sistema .stat .t { font-size: 15px; font-weight: 650; }
.sistema-pipeline { margin: 16px 0 24px; border: 1px solid var(--neutral-50); border-radius: 10px; padding: 14px 16px; }
.sistema-pipeline summary { cursor: pointer; font-size: 15px; font-weight: 600; }
.sistema-pipeline[open] summary { margin-bottom: 14px; }
.sistema-uso { display: grid; grid-template-columns: minmax(0,1fr) minmax(220px,auto); align-items: center; gap: 16px; padding: 16px 0; border-bottom: 1px solid var(--neutral-50); }
.sistema-uso:last-child { border-bottom: 0; }
.sistema-uso h3 { font-size: 16px; font-weight: 650; margin-bottom: 6px; }
.sistema-uso p { font-size: 14px; color: var(--neutral-80); line-height: 1.5; }
.sistema-uso > div:last-child { text-align: right; }
.sistema-uso > div > strong { display: block; font-size: 19px; margin-bottom: 8px; }
.sistema-medicao { display: inline-block; font-size: 13px; padding: 5px 8px; border-radius: 6px; }
.sistema-medicao.medida { background: var(--green-tint); color: var(--green-ink); }
.sistema-medicao.pendente { background: var(--amber-tint); color: var(--amber-ink); }
.sistema-modelo, .sistema-detalhe-custo { container-type: inline-size; container-name: custo; }
.sistema-calculo { margin: 14px 0; }
.sistema-parcela { display: grid; grid-template-columns: minmax(0,1.2fr) minmax(0,.8fr) minmax(0,1fr) minmax(0,1fr); gap: 12px; align-items: center; padding: 12px 0; border-bottom: 1px solid var(--neutral-40); font-size: 14px; line-height: 1.5; }
.sistema-parcela > :last-child { text-align: right; font-variant-numeric: tabular-nums; }
.sistema-detalhe-custo { grid-column: 1 / -1; width: 100%; }
.sistema-detalhe-custo summary { cursor: pointer; font-size: 14px; font-weight: 600; color: var(--blue-ink); padding: 8px 0; }
.sistema-total-calculo { font-size: 16px; margin-bottom: 8px; }
@container custo (max-width: 700px) {
  .sistema-parcela { grid-template-columns: minmax(0,1fr) minmax(0,1fr); gap: 6px 12px; }
  .sistema-parcela > :first-child, .sistema-parcela > :last-child { grid-column: 1 / -1; text-align: left; }
}
@container sistema (max-width: 480px) {
  .sistema-uso { grid-template-columns: minmax(0,1fr); }
  .sistema-uso > div:last-child { text-align: left; }
}
@container sistema (max-width: 850px) { .sistema-kpis { grid-template-columns: repeat(2,minmax(0,1fr)); } .sistema-duas-colunas { grid-template-columns: minmax(0,1fr); } }
@container sistema (max-width: 480px) {
  .sistema-kpis { grid-template-columns: minmax(0,1fr); }
  .sistema-controles { width: 100%; }
  #sistema-periodo { flex: 1 1 100%; width: 100%; }
  .sistema-dia { grid-template-columns: minmax(0,1fr) auto; gap: 8px; }
  .sistema-dia meter { grid-column: 1 / -1; grid-row: 2; }
  .sistema-atividade { grid-template-columns: minmax(0,1fr); gap: 10px; }
  .sistema-modelo dl { grid-template-columns: minmax(0,1fr); }
}
