@font-face{font-family:'FSAldrin';src:url('/brand/fonts/FSAldrin.woff2') format('woff2'),url('/brand/fonts/FSAldrin.woff') format('woff');font-weight:400;font-display:swap}
:root{
  --accent:#0050c3; --accent-hover:#003fa0; --accent-soft:#e6eefb; --accent-ring:rgba(0,80,195,.26); --accent-contrast:#fff;
  --accent-2:#1eb85a; --accent-2-soft:#e6f7ec; --accent-2-ring:rgba(30,184,90,.26); --brand-teal:#0050c3; --brand-salmon:#0050c3; --brand-salmon-strong:#003fa0; --brand-salmon-deep:#00306f;
  --bg:#f5f6f8; --surface:#ffffff; --surface-2:#fafbfc; --surface-3:#f0f2f5; --border:#e3e6ea; --border-strong:#d0d5db;
  --text:#171a1d; --text-soft:#5b6470; --text-faint:#8a93a0;
  --success:#15803d; --success-soft:#e7f6ec; --warning:#b45309; --warning-soft:#fdf1e1;
  --danger:#b91c1c; --danger-soft:#fbe9e9; --info:#e4600d; --info-soft:#fce9dd; --ia:#0f766e; --ia-soft:#dcf2ef;
  --skel-bg:#e4e7eb; --skel-glare:rgba(255,255,255,.75);
  --shadow-sm:0 1px 2px rgba(20,25,30,.06); --shadow-md:0 4px 16px rgba(20,25,30,.10); --shadow-lg:0 16px 48px rgba(20,25,30,.18);
  --radius-sm:6px; --radius-md:10px; --radius-lg:14px;
  --chart-1:#d6604a; --chart-2:#2f8fd0; --chart-3:#e4a013; --chart-4:#3fa06a; --chart-5:#8a5cd6; --chart-6:#e2679e; --chart-7:#e4600d; --chart-8:#64748b;
  --font-brand:'FSAldrin',-apple-system,"Segoe UI",Roboto,sans-serif;
  --font-ui: -apple-system,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;
  --font-mono: ui-monospace,SFMono-Regular,Menlo,Consolas,"Liberation Mono",monospace;
}
@media (prefers-color-scheme: dark){
  :root{
    --accent:#6ea8f0; --accent-hover:#8bbcf6; --accent-soft:#12233d; --accent-ring:rgba(110,168,240,.28); --accent-contrast:#0a1a30;
    --accent-2:#4ade80; --accent-2-soft:#12331f; --accent-2-ring:rgba(74,222,128,.28); --brand-teal:#6ea8f0; --brand-salmon:#6ea8f0; --brand-salmon-strong:#003fa0; --brand-salmon-deep:#00306f;
    --bg:#121417; --surface:#1b1e22; --surface-2:#212429; --surface-3:#272b31; --border:#2b2f35; --border-strong:#383d45;
    --text:#eef0f2; --text-soft:#a7afba; --text-faint:#727a86;
    --success:#22c55e; --success-soft:#12291a; --warning:#f59e0b; --warning-soft:#2b2011;
    --danger:#f87171; --danger-soft:#2c1717; --info:#ff9e8f; --info-soft:#2c1a15; --ia:#5eead4; --ia-soft:#0f2320;
    --skel-bg:#2c3138; --skel-glare:rgba(255,255,255,.07);
    --shadow-sm:0 1px 2px rgba(0,0,0,.3); --shadow-md:0 4px 16px rgba(0,0,0,.4); --shadow-lg:0 16px 48px rgba(0,0,0,.55);
    --chart-1:#ff8d7f; --chart-2:#5aa9e6; --chart-3:#f5c451; --chart-4:#5cc98d; --chart-5:#b98cf0; --chart-6:#f07fb0; --chart-7:#fb923c; --chart-8:#94a3b8;
  }
}
:root[data-theme="dark"]{
  --accent:#6ea8f0; --accent-hover:#8bbcf6; --accent-soft:#12233d; --accent-ring:rgba(110,168,240,.28); --accent-contrast:#0a1a30;
  --accent-2:#4ade80; --accent-2-soft:#12331f; --accent-2-ring:rgba(74,222,128,.28); --brand-teal:#6ea8f0; --brand-salmon:#6ea8f0; --brand-salmon-strong:#003fa0; --brand-salmon-deep:#00306f;
  --bg:#121417; --surface:#1b1e22; --surface-2:#212429; --surface-3:#272b31; --border:#2b2f35; --border-strong:#383d45;
  --text:#eef0f2; --text-soft:#a7afba; --text-faint:#727a86;
  --success:#22c55e; --success-soft:#12291a; --warning:#f59e0b; --warning-soft:#2b2011;
  --danger:#f87171; --danger-soft:#2c1717; --info:#ff9e8f; --info-soft:#2c1a15;
  --skel-bg:#2c3138; --skel-glare:rgba(255,255,255,.07);
  --shadow-sm:0 1px 2px rgba(0,0,0,.3); --shadow-md:0 4px 16px rgba(0,0,0,.4); --shadow-lg:0 16px 48px rgba(0,0,0,.55);
  --chart-1:#ff8d7f; --chart-2:#5aa9e6; --chart-3:#f5c451; --chart-4:#5cc98d; --chart-5:#b98cf0; --chart-6:#f07fb0; --chart-7:#fb923c; --chart-8:#94a3b8;
}
:root[data-theme="light"]{
  --accent:#0050c3; --accent-hover:#003fa0; --accent-soft:#e6eefb; --accent-ring:rgba(0,80,195,.26); --accent-contrast:#fff;
  --accent-2:#1eb85a; --accent-2-soft:#e6f7ec; --accent-2-ring:rgba(30,184,90,.26); --brand-teal:#0050c3; --brand-salmon:#0050c3; --brand-salmon-strong:#003fa0; --brand-salmon-deep:#00306f;
  --bg:#f5f6f8; --surface:#ffffff; --surface-2:#fafbfc; --surface-3:#f0f2f5; --border:#e3e6ea; --border-strong:#d0d5db;
  --text:#171a1d; --text-soft:#5b6470; --text-faint:#8a93a0;
  --success:#15803d; --success-soft:#e7f6ec; --warning:#b45309; --warning-soft:#fdf1e1;
  --danger:#b91c1c; --danger-soft:#fbe9e9; --info:#e4600d; --info-soft:#fce9dd; --ia:#0f766e; --ia-soft:#dcf2ef;
  --skel-bg:#e4e7eb; --skel-glare:rgba(255,255,255,.75);
  --chart-1:#d6604a; --chart-2:#2f8fd0; --chart-3:#e4a013; --chart-4:#3fa06a; --chart-5:#8a5cd6; --chart-6:#e2679e; --chart-7:#e4600d; --chart-8:#64748b;
}
*{box-sizing:border-box}
html,body,#root{height:100%}
body{margin:0;background:var(--bg);color:var(--text);font-family:var(--font-ui);font-size:14px;line-height:1.45;-webkit-font-smoothing:antialiased}
body,#root{overflow-x:hidden}
h1,h2,h3,h4{margin:0;text-wrap:balance;font-weight:700;letter-spacing:-.01em}
p{margin:0}
a{color:var(--accent)}
button{font-family:inherit;cursor:pointer}
input,select,textarea{font-family:inherit;font-size:13px}
:focus-visible{outline:2px solid var(--accent);outline-offset:1px}
::-webkit-scrollbar{width:10px;height:10px}
::-webkit-scrollbar-thumb{background:var(--border-strong);border-radius:8px}
::-webkit-scrollbar-track{background:transparent}
.tabular{font-variant-numeric:tabular-nums}
.mono{font-family:var(--font-mono)}
/* Trecho ```monoespaçado``` de mensagem do WhatsApp renderizado no chat (ver waFormat). */
.wa-mono{font-family:var(--font-mono);font-size:.92em;background:var(--surface-2);border:1px solid var(--border);border-radius:5px;padding:0 4px;white-space:pre-wrap}

/* layout */
.flex{display:flex} .flex-col{display:flex;flex-direction:column} .items-center{align-items:center} .items-start{align-items:flex-start}
.justify-between{justify-content:space-between} .justify-end{justify-content:flex-end} .justify-center{justify-content:center}
.flex-wrap{flex-wrap:wrap} .flex-1{flex:1 1 auto} .flex-none{flex:none}
.grid{display:grid}
.gap-1{gap:4px} .gap-2{gap:8px} .gap-3{gap:12px} .gap-4{gap:16px} .gap-5{gap:20px} .gap-6{gap:24px}
.g1{gap:4px}.g2{gap:8px}.g3{gap:12px}

/* spacing */
.p-0{padding:0}.p-2{padding:8px}.p-3{padding:12px}.p-4{padding:16px}.p-5{padding:20px}.p-6{padding:24px}
.px-2{padding-left:8px;padding-right:8px}.px-3{padding-left:12px;padding-right:12px}.px-4{padding-left:16px;padding-right:16px}
.py-1{padding-top:4px;padding-bottom:4px}.py-2{padding-top:8px;padding-bottom:8px}.py-3{padding-top:12px;padding-bottom:12px}
.mt-1{margin-top:4px}.mt-2{margin-top:8px}.mt-3{margin-top:12px}.mt-4{margin-top:16px}.mt-6{margin-top:24px}
.mb-1{margin-bottom:4px}.mb-2{margin-bottom:8px}.mb-3{margin-bottom:12px}.mb-4{margin-bottom:16px}

/* text */
.text-xs{font-size:11px}.text-sm{font-size:12.5px}.text-base{font-size:14px}.text-lg{font-size:16px}.text-xl{font-size:20px}.text-2xl{font-size:26px}
.font-medium{font-weight:500}.font-semibold{font-weight:600}.font-bold{font-weight:700}
.text-soft{color:var(--text-soft)}.text-faint{color:var(--text-faint)}.text-accent{color:var(--accent)}
.text-success{color:var(--success)}.text-danger{color:var(--danger)}.text-warning{color:var(--warning)}.text-info{color:var(--info)}
.uppercase{text-transform:uppercase;letter-spacing:.06em}
.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.overflow-hidden{overflow:hidden;min-width:0}

/* surfaces */
.card{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-lg);box-shadow:var(--shadow-sm)}
/* Lista de itens agrupada num único contorno (linhas separadas por um fio, sem espaço entre elas) —
   pra quando uma pilha de .card com gap fica repetitiva demais (ex: Regras de Aprovação). Reaproveitar
   sempre que precisar de uma lista de linhas clicáveis dentro de um único bloco, em vez de empilhar
   .card + gap de novo. */
.list-group{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-lg);box-shadow:var(--shadow-sm);overflow:hidden}
.list-group-item{padding:14px 16px;border-bottom:1px solid var(--border);transition:.1s}
.list-group-item:last-child{border-bottom:none}
.list-group-item:hover{background:var(--surface-2)}
.surface-2{background:var(--surface-2)}
.rounded-sm{border-radius:var(--radius-sm)}.rounded-md{border-radius:var(--radius-md)}.rounded-lg{border-radius:var(--radius-lg)}
.rounded-full{border-radius:999px}
.border{border:1px solid var(--border)}
.border-t{border-top:1px solid var(--border)}.border-b{border-bottom:1px solid var(--border)}

/* buttons */
.btn{display:inline-flex;align-items:center;gap:7px;padding:8px 14px;border-radius:var(--radius-sm);border:1px solid var(--border-strong);background:var(--surface);color:var(--text);font-size:13px;font-weight:600;transition:.12s;white-space:nowrap}
.btn:hover{border-color:var(--text-faint)}
.btn:disabled{opacity:.45;cursor:not-allowed}
.btn-primary{background:var(--accent);border-color:var(--accent);color:var(--accent-contrast)}
.btn-primary:hover{background:var(--accent-hover);border-color:var(--accent-hover)}
.btn-danger{background:transparent;border-color:var(--danger);color:var(--danger)}
.btn-danger:hover{background:var(--danger-soft)}
.btn-ghost{background:transparent;border-color:transparent}
.btn-ghost:hover{background:var(--surface-2)}
.btn-sm{padding:5px 10px;font-size:12px;border-radius:7px}
/* Usar SEMPRE junto com .btn (class="btn btn-icon"): botão só-ícone que herda a ALTURA exata do .btn,
   pra o "3 pontinhos" e afins ficarem do mesmo tamanho dos inputs/botões ao lado (padrão do projeto). */
.btn-icon{padding-left:9px;padding-right:9px;gap:0}
.btn-block{width:100%;justify-content:center}
.btn-flex{flex:1;justify-content:center}

/* inputs */
.field{display:flex;flex-direction:column;gap:5px}
.label{font-size:12px;font-weight:600;color:var(--text-soft)}
.label .req{color:var(--danger)}
.input,.select,.textarea{width:100%;padding:9px 11px;border:1px solid var(--border-strong);border-radius:8px;background:var(--surface);color:var(--text)}
.input:focus,.select:focus,.textarea:focus{border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-ring)}
.textarea{resize:vertical;min-height:64px}
/* Prefixo "R$" fixo dentro de um campo de valor (ver valorComToggleFieldHtml) — span posicionado sobre
   o input, que ganha padding-left extra pra não sobrepor o texto digitado. */
.input-currency-wrap{position:relative}
.input-currency-wrap .input{padding-left:32px}
.input-currency-prefix{position:absolute;left:11px;top:50%;transform:translateY(-50%);color:var(--text-faint);font-size:13px;pointer-events:none}
/* Destaque de campo com erro assíncrono (ex: duplicidade de CPF/CNPJ) — reaproveitar em qualquer
   input que precise sinalizar erro sem esperar o submit do form. */
.input-invalid,.input-invalid:focus{border-color:var(--danger)}
/* Linha com botão de ação que só aparece no hover (ex: copiar documento na ficha do Lead) — mesma
   ideia de .flow-node-actions, generalizada pra qualquer linha de valor único. */
.hover-reveal-action{opacity:0;transition:.12s}
.hover-reveal-row:hover .hover-reveal-action,.hover-reveal-action:focus{opacity:1}
/* Rótulo sobreposto à borda do input (padrão "outlined label") — pra campos compactos lado a lado
   onde um <label> normal acima ocuparia linha demais (ex: linha de Campo do board). Reaproveitar
   sempre que precisar de rótulo permanente num input estreito, em vez de um placeholder que some. */
.field-overlap{position:relative}
.field-overlap>label{position:absolute;top:-7px;left:9px;padding:0 5px;background:var(--surface);border-radius:3px;font-size:10.5px;font-weight:600;color:var(--text-faint);line-height:1;pointer-events:none;white-space:nowrap}
.hint{font-size:11.5px;color:var(--text-faint)}
.checkline{display:flex;align-items:center;gap:8px;font-size:13px}
/* Cartões de escolha única (ver choiceCardsHtml) — a alternativa com acabamento ao <select> seco quando
   cada opção merece título + descrição da consequência. Grade de 2 (empilha no estreito), estado
   selecionado com borda/fundo de acento e o tique no canto. Componente único, reaproveitável. */
.choice-cards{display:grid;grid-template-columns:1fr 1fr;gap:10px}
.choice-card{display:flex;flex-direction:column;gap:5px;text-align:left;padding:12px 13px;border:1px solid var(--border-strong);border-radius:var(--radius-md);background:var(--surface);cursor:pointer;transition:.12s}
.choice-card:hover{border-color:var(--accent)}
.choice-card.selected{border-color:var(--accent);background:var(--accent-soft);box-shadow:0 0 0 3px var(--accent-ring)}
.choice-card-head{display:flex;align-items:center;gap:8px}
.choice-card-icon{display:inline-flex;color:var(--text-soft)}
.choice-card.selected .choice-card-icon{color:var(--accent)}
.choice-card-title{font-size:13px;font-weight:700;color:var(--text)}
.choice-card-head-right{margin-left:auto;display:inline-flex;align-items:center;gap:6px}
.choice-card-check{display:inline-flex;color:var(--accent);opacity:0;transition:.12s}
.choice-card.selected .choice-card-check{opacity:1}
.choice-card-desc{font-size:11.5px;color:var(--text-faint);line-height:1.4}
@media(max-width:520px){.choice-cards{grid-template-columns:1fr}}
/* Painel que agrupa campos relacionados dentro de um formulário, com borda e fundo próprios pra dar
   acabamento em bloco (em vez de campos soltos empilhados). .field-panel-divider separa uma seção
   dependente (ex: aparece só quando o toggle acima está ligado). Componente único, reaproveitável. */
.field-panel{border:1px solid var(--border);border-radius:var(--radius-md);background:var(--surface-2);padding:12px;display:flex;flex-direction:column;gap:11px}
.field-panel-divider{border-top:1px solid var(--border);padding-top:11px;display:flex;flex-direction:column;gap:8px}
.panel-toggle{display:flex;align-items:flex-start;gap:10px;cursor:pointer}
.panel-toggle>.switch{margin-top:1px;flex:none}
.panel-toggle-title{display:block;font-size:13px;font-weight:600;color:var(--text);margin-bottom:2px}
/* Editor de expediente por empresa (ver openEmpresaDrawer / empresaExpedienteHtml). Uma linha por dia da
   semana: abre-fecha e um intervalo de almoço opcional. .is-off dá o estado apagado (dia fechado / almoço
   desligado / expediente inteiro desligado) sem esconder, pra o usuário ver o que ativaria. */
.exp-dia{display:flex;align-items:center;gap:8px;flex-wrap:wrap;padding:6px 0;border-top:1px solid var(--border)}
.exp-dia-toggle{display:flex;align-items:center;gap:6px;font-size:13px;font-weight:600;min-width:104px;cursor:pointer}
.exp-dia-campos{display:flex;align-items:center;gap:6px;flex-wrap:wrap}
.exp-dia-campos .input{width:auto;padding:5px 7px}
.exp-sep{font-size:12px;color:var(--text-faint)}
.exp-lunch-toggle{display:flex;align-items:center;gap:5px;font-size:12px;color:var(--text-soft);cursor:pointer;margin-left:4px}
.exp-lunch-campos{display:flex;align-items:center;gap:6px}
.exp-dia.is-off .exp-dia-campos,.exp-lunch-campos.is-off,.exp-editor.is-off .exp-body{opacity:.4;pointer-events:none}
.exp-feriado{display:flex;align-items:center;gap:6px;margin-top:4px}
.exp-feriado .input{width:auto}
.checkline input{width:16px;height:16px;accent-color:var(--accent)}
/* Item GERAL 1: ao marcar um checkbox, o texto da própria label fica na cor de destaque. Vale só pros
   checkboxes (não pros toggles .switch, cujo texto fica FORA do <label>). :has(> input:checked) cobre tanto
   .checkline quanto os labels inline soltos que embrulham um checkbox + texto (checkbox como filho direto). */
label:not(.switch):has(> input[type="checkbox"]:checked){color:var(--accent)}

/* combobox */
.combo{position:relative}
.combo .input{padding-right:30px}
.clear-btn{position:absolute;right:5px;top:50%;transform:translateY(-50%);width:22px;height:22px;border:none;background:transparent;color:var(--text-faint);display:none;align-items:center;justify-content:center;border-radius:5px;cursor:pointer;padding:0}
.clear-btn:hover{background:var(--surface-2);color:var(--text)}
.combo-list{position:absolute;left:0;right:0;top:calc(100% + 4px);max-height:212px;overflow:auto;background:var(--surface);border:1px solid var(--border-strong);border-radius:8px;box-shadow:var(--shadow-md);z-index:60;display:none}
.combo-list.open{display:block}
.combo-opt{padding:8px 11px;font-size:13px;cursor:pointer}
.combo-opt:hover,.combo-opt.hi{background:var(--accent-soft)}
.combo-empty{padding:10px 11px;font-size:12.5px;color:var(--text-faint)}
/* Tag picker (ver tagPickerHtml/wireTagPicker): chips selecionados + combo de busca abaixo, pra
   substituir lista de checkbox em campos de etiqueta/multi-seleção — mesmo .combo/.combo-list de
   busca já usado nos campos de referência única, só que o clique acrescenta um chip em vez de
   preencher um valor único. */
.tag-picker-chips{display:flex;flex-wrap:wrap;gap:4px;min-height:26px;margin-bottom:6px}

/* badges */
.badge{display:inline-flex;align-items:center;gap:5px;padding:3px 9px;border-radius:999px;font-size:11.5px;font-weight:700}
.badge-dot{width:6px;height:6px;border-radius:50%;background:currentColor}
/* Estado "removendo" do badge de etiqueta (ver wireAtdTagsRemove): o ponto sólido vira um anel girando
   (mesma animação spin do spinner de tela cheia, ver .spinner) em vez de travar a UI com modal/loading
   geral — só esse pontinho fica ocupado até a requisição terminar. */
.badge-dot.spinning{width:7px;height:7px;background:transparent;border:1.5px solid currentColor;border-top-color:transparent;animation:spin .6s linear infinite}
/* Variante "flat com ponto" (docs/components/badges-small-flat-with-dot.html): chip de canto menos
   arredondado, fundo é a cor da etiqueta bem diluída na superfície atual (color-mix, funciona em claro
   e escuro sem precisar de duas paletas), texto na mesma cor só que misturada com --text pra sempre
   ficar legível mesmo se a cor escolhida for muito escura/clara. Usada só pelas etiquetas de Leads —
   os demais badges do app (Configurado, Aprovado...) continuam na variante pill de sempre. */
.badge-flat{border-radius:6px;padding:1px 6px;font-size:9px;font-weight:500;white-space:nowrap;flex:none;margin:0 1px}
/* Variante MAIOR e em CAIXA ALTA da etiqueta chapada (.badge-flat) — mesmo visual/cor, só texto maior e
   uppercase. Usada na página Cérebro da IA → Etiquetas pra listar as etiquetas formatadas, uma por linha. */
.badge-flat.badge-flat-lg{font-size:12px;font-weight:700;letter-spacing:.03em;text-transform:uppercase;padding:4px 10px;border-radius:7px}
/* Badge de TAG (setor/etiqueta/categoria, via tagBadgeHtml): sempre CAIXA ALTA e numa única linha nas duas
   variantes (small e -lg). Quando o container aperta, o TEXTO trunca com reticências (só oculta se necessário),
   nunca vaza nem quebra a linha; tamanho fluido (encolhe até o limite do espaço). Ver diretriz BADGES. */
.badge-flat.tag-badge{text-transform:uppercase;letter-spacing:.02em;min-width:0;max-width:100%;flex:0 1 auto}
.badge-flat.tag-badge .tag-badge-text{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}
/* docs/components/badges-with-border-and-remove-button.html: badge com contorno (ring) na própria
   cor + um X pequeno embutido no fim, área de clique maior que o ícone via ::after absoluto (mesma
   técnica do componente de referência: hit-area maior que o botão visível, sem aumentar o badge). */
.badge-removable{position:relative;padding-right:3px}
.badge-remove{position:relative;display:inline-flex;align-items:center;justify-content:center;width:13px;height:13px;border-radius:3px;border:none;background:transparent;color:inherit;opacity:.6;cursor:pointer;padding:0;margin-left:1px}
.badge-remove::after{content:'';position:absolute;inset:-4px}
.badge-remove:hover{opacity:1;background:color-mix(in srgb, currentColor 22%, transparent)}
.board-color-dot{display:inline-block;width:7px;height:7px;border-radius:50%;margin-right:5px;flex:none;vertical-align:middle}
/* .nav-item/.actions-dropdown-item já são flex com gap próprio (menu lateral e dropdown de ações) — a
   margin-right do dot por cima disso somava um espaço maior que o normal entre o dot e o texto do board
   (ex: "Tarefas"), fora do padrão dos outros itens do menu (ícone + label só com o gap do flex). */
.nav-item .board-color-dot,.actions-dropdown-item .board-color-dot{margin-right:0}
/* Listagem de Leads: só as 2 primeiras etiquetas aparecem inteiras, a 3ª some num degradê da
   esquerda pra direita e uma badge com a contagem restante sobrepõe um pouco o final dela — em vez
   de cortar a lista sem indicação nenhuma de que há mais etiquetas. */
.lead-tags-row{display:flex;align-items:center;flex-wrap:nowrap;overflow:hidden}
.lead-tag-fade{-webkit-mask-image:linear-gradient(to right,#000 30%,transparent 88%);mask-image:linear-gradient(to right,#000 30%,transparent 88%);margin-right:-13px}
.lead-tags-more{position:relative;z-index:1;flex:none;font-size:11px;font-weight:700;color:var(--text-faint);background:var(--surface-2);border:1px solid var(--border);border-radius:999px;padding:2px 7px}
.lead-verified-badge{display:inline-flex;align-items:center;justify-content:center;flex:none}
.b-success{background:var(--success-soft);color:var(--success)}
.b-warning{background:var(--warning-soft);color:var(--warning)}
.b-danger{background:var(--danger-soft);color:var(--danger)}
.b-info{background:var(--info-soft);color:var(--info)}
.b-neutral{background:var(--surface-2);color:var(--text-soft);border:1px solid var(--border)}
.b-accent{background:var(--accent-soft);color:var(--accent)}

/* table */
.table-wrap{overflow-x:auto;border:1px solid var(--border);border-radius:var(--radius-lg);background:var(--surface)}
table{width:100%;border-collapse:collapse;}
thead th{position:sticky;top:0;background:var(--surface-2);text-align:left;font-size:11px;text-transform:uppercase;letter-spacing:.05em;color:var(--text-faint);font-weight:700;padding:10px 14px;border-bottom:1px solid var(--border)}
tbody td{padding:11px 14px;border-bottom:1px solid var(--border);font-size:13px;vertical-align:middle}
tbody tr:last-child td{border-bottom:none}
tbody tr:hover{background:var(--surface-2)}
tbody tr:has([data-view],[data-edit]) td:not(:has(a,button,input,select,textarea,.switch)){cursor:pointer}
.row-actions{display:flex;gap:4px;justify-content:flex-end}
/* VISOR DE JSON — conteúdo lido como código, hoje a resposta bruta do bureau (Consultas Cadastrais).
   Rola DENTRO do próprio bloco: JSON tem linha longa por natureza, e um <pre> sem overflow próprio faria a
   página inteira rolar de lado. As cores marcam o PAPEL do token (chave, texto, número, literal), então
   qualquer outro conteúdo em código reaproveita este mesmo componente em vez de criar um parecido. */
.jsonview{margin:0;max-height:min(60vh,520px);overflow:auto;background:var(--surface-2);border:1px solid var(--border);border-radius:8px;padding:12px 14px;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:12.5px;line-height:1.6;color:var(--text);white-space:pre;tab-size:2}
.jsonview .jk{color:var(--accent);font-weight:600}
.jsonview .js{color:var(--success)}
.jsonview .jn{color:var(--warning)}
.jsonview .jb{color:var(--danger)}
/* Linha compacta (cfg.rowClass) — pra tabelas cujo conteúdo é só texto curto + botões de ícone na
   coluna Ações (ex: Setores, Categorias de Entidades): o padding padrão de 11px sobra porque a altura
   real já é dada pelos botões de ~28px, não pelo texto. Reaproveitável em qualquer outra listagem com o
   mesmo perfil — não é exclusivo de Entidades. */
tbody tr.tr-compact td{padding:6px 14px}
@media (max-width:760px){
  .table-wrap:not(.matrix-wrap){border:none;background:transparent;box-shadow:none;overflow-x:visible}
  .table-wrap:not(.matrix-wrap) table{display:block;min-width:0;width:100%}
  .table-wrap:not(.matrix-wrap) thead{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0)}
  .table-wrap:not(.matrix-wrap) tbody{display:flex;flex-direction:column;gap:10px}
  .table-wrap:not(.matrix-wrap) tr{display:flex;flex-direction:column;background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-lg);padding:4px 14px;box-shadow:var(--shadow-sm)}
  .table-wrap:not(.matrix-wrap) tr:hover{background:var(--surface)}
  .table-wrap:not(.matrix-wrap) td{display:flex;align-items:center;justify-content:space-between;gap:14px;padding:9px 0;border-bottom:1px solid var(--border);text-align:right;white-space:normal}
  .table-wrap:not(.matrix-wrap) td:last-child{border-bottom:none}
  .table-wrap:not(.matrix-wrap) td[colspan]{display:block;text-align:left;padding:9px 0}
  .table-wrap:not(.matrix-wrap) td::before{content:attr(data-label);font-size:10.5px;font-weight:700;text-transform:uppercase;letter-spacing:.05em;color:var(--text-faint);text-align:left;flex:none}
  .table-wrap:not(.matrix-wrap) td:not([data-label])::before{content:none}
  .table-wrap:not(.matrix-wrap) td input,.table-wrap:not(.matrix-wrap) td .select{width:auto;max-width:170px}
  /* A faixa de revalidação NÃO é um registro: no mobile, onde cada linha vira cartão, ela abre mão do
     cartão (borda/raio/sombra) e vira uma tarja fina acima da pilha — senão pareceria mais um item. */
  .table-wrap:not(.matrix-wrap) tr.tbl-reval-row{background:transparent;border:none;border-radius:0;box-shadow:none;padding:0}
  .table-wrap:not(.matrix-wrap) tr.tbl-reval-row>td{padding:6px 12px;border-radius:var(--radius-md, 8px)}
}

/* toggle switch */
.switch{position:relative;display:inline-block;width:38px;height:22px;flex:none}
.switch input{opacity:0;width:0;height:0;position:absolute}
.switch-track{position:absolute;inset:0;background:var(--border-strong);border-radius:999px;cursor:pointer;transition:.15s}
.switch-track::before{content:'';position:absolute;left:3px;top:3px;width:16px;height:16px;background:#fff;border-radius:50%;transition:.15s;box-shadow:var(--shadow-sm)}
.switch input:checked+.switch-track{background:var(--success)}
.switch input:checked+.switch-track.switch-track-info{background:var(--info)}
.switch input:checked+.switch-track.switch-track-danger{background:var(--danger)}
/* Variante onde o estado DESLIGADO é o que precisa chamar atenção (ex: membro bloqueado) — inverso do
   padrão normal (checked=verde), só usado no toggle Ativo de Administradores → Usuários. */
.switch input:not(:checked)+.switch-track.switch-track-off-danger{background:var(--danger)}
.switch input:checked+.switch-track::before{transform:translateX(16px)}
.switch input:focus-visible+.switch-track{outline:2px solid var(--accent);outline-offset:2px}
.switch input:disabled+.switch-track{opacity:.4;cursor:default;pointer-events:none}
.switch.sm{width:28px;height:16px}
.switch.sm .switch-track::before{width:10px;height:10px}
.switch.sm input:checked+.switch-track::before{transform:translateX(12px)}
/* Lista chave→valor pra resumos de confirmação (ex: confirmar lançamento de ajuste de saldo) */
.summary-list{display:flex;flex-direction:column;border:1px solid var(--border);border-radius:10px;overflow:hidden}
.summary-row{display:flex;justify-content:space-between;align-items:center;gap:12px;padding:8px 12px;font-size:12.5px}
.summary-row:not(:last-child){border-bottom:1px solid var(--border)}
.summary-row>span{color:var(--text-faint)}
.summary-row>b{color:var(--text);font-weight:600;text-align:right}
/* Diff antigo → novo de uma edição pendente (Aprovações) */
.appr-diff{display:inline-flex;align-items:center;gap:6px;flex-wrap:wrap;justify-content:flex-end}
.appr-diff-old{color:var(--text-faint);text-decoration:line-through;font-weight:500}
.appr-diff-new{color:var(--text);font-weight:700}
.appr-diff-arrow{color:var(--text-faint);flex:none}

/* data table pager */
.dt-toolbar{display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;gap:10px;margin-bottom:10px}
.dt-toolbar-bottom{margin-bottom:0;margin-top:10px}
/* Rodapé de paginação dentro da tabela (item GERAL 6): linha de <tfoot> na última linha, fundo neutro como o
   thead, sem borda inferior nem hover (tfoot não é alvo do tbody tr:hover). */
.dt-foot-cell{padding:8px 14px;border-top:1px solid var(--border);background:var(--surface-2)}
.dt-foot-pager{display:flex;justify-content:flex-end;align-items:center;gap:14px;flex-wrap:wrap}
/* Controle "Colunas exibidas" da tabela (cfg.columnToggle) — painel de checkboxes ancorado sob o botão. */
.dt-cols-panel{position:absolute;top:calc(100% + 4px);right:0;z-index:30;background:var(--surface);border:1px solid var(--border);border-radius:8px;box-shadow:0 6px 20px rgba(0,0,0,.12);padding:6px;min-width:190px;max-height:300px;overflow:auto}
.dt-col-opt{display:flex;align-items:center;gap:8px;padding:6px 8px;border-radius:6px;cursor:pointer;font-size:13px;white-space:nowrap}
.dt-col-opt:hover{background:var(--surface-2)}
/* Cabeçalho de coluna ordenável (cfg.sortKey + cfg.onSort) — rótulo + ícone de sort (referência flowbite
   "Table with sortable rows"). Herda a tipografia do <th>; o ícone fica esmaecido, e acende no accent
   quando é a coluna ativa. */
.dt-sort{display:inline-flex;align-items:center;gap:5px;background:none;border:none;padding:0;margin:0;cursor:pointer;color:inherit;font:inherit;font-weight:inherit;letter-spacing:inherit;text-transform:inherit}
.dt-sort .dt-sort-ic{display:inline-flex;color:var(--text-faint)}
.dt-sort:hover{color:var(--accent)}
.dt-sort.active,.dt-sort.active .dt-sort-ic{color:var(--accent)}
/* Cabeçalho INTEGRADO à tabela (faixa cinza acima das colunas, NÃO um card separado — pedido do usuário):
   .tbl-shell envolve header + tabela numa borda/raio só; .tbl-headbar é a faixa cinza (surface-2, mesma cor
   do thead) colada no topo das colunas, com duas linhas — linha 1 = paginação (esq) + Personalizar colunas
   (dir); linha 2 = busca (esq) + filtros (dir). Fiel a docs/flow/table-header.html (header no topo da mesma
   card da tabela). Inputs em tamanho small. Empilha no mobile. */
.tbl-shell{border:1px solid var(--border);border-radius:var(--radius-lg);background:var(--surface);box-shadow:var(--shadow-sm);margin-bottom:16px}
.tbl-headbar{background:var(--surface-2);border-radius:var(--radius-lg) var(--radius-lg) 0 0;border-bottom:1px solid var(--border);padding:10px 14px;display:flex;flex-direction:column;gap:8px}
.tbl-headbar-row{display:flex;justify-content:space-between;align-items:center;gap:10px;flex-wrap:wrap}
.tbl-headbar-search{flex:1 1 260px;min-width:0}
/* Desktop: filtros ficam ao lado da busca, com largura natural (justo o conteúdo). Só em telas menores
   (<=760px, ver media query abaixo) eles descem pra própria linha e aí se dividem por igual pra preencher
   100% da largura — 4 por linha viram 4x25%, 2 por linha viram 2x50% (item DESPESAS 2). */
.tbl-headbar-filters{display:flex;align-items:center;gap:6px;flex-wrap:wrap;justify-content:flex-end}
.tbl-shell .table-wrap{border:none;border-radius:0}
/* Rodapé da tabela (item DESPESAS 3): mesma faixa cinza do header, com a paginação repetida embaixo. */
.tbl-footbar{background:var(--surface-2);border-top:1px solid var(--border);border-radius:0 0 var(--radius-lg) var(--radius-lg);padding:10px 14px;display:flex;justify-content:space-between;align-items:center;gap:10px;flex-wrap:wrap}
.tbl-pageinfo{display:flex;align-items:center;gap:10px;flex-wrap:wrap;color:var(--text-soft);font-size:13px}
.tbl-pageinfo .tabular{color:var(--text)}
/* Dropdown de filtro (Empresa/Status/Tipo/Período). Botão ocupa 100% da célula; painel posicionado via JS
   (positionDespFilterMenu) com position:fixed e z-index alto pra ficar SEMPRE acima do menu lateral (z 90)
   e clampado dentro da viewport, nunca cortado nem atrás de outro elemento (item DESPESAS 1). No mobile o
   painel nem abre: vira modal de tela cheia (openDespFilterModal, item DESPESAS 4). */
.tbl-filter{position:relative;flex:0 1 auto;min-width:0}
.tbl-filter-btn{display:inline-flex;align-items:center;gap:6px;width:100%;white-space:nowrap}
.tbl-filter-btn.on{border-color:var(--accent);color:var(--accent)}
/* No desktop o rótulo trunca em ~160px pra um valor selecionado longo não esticar o botão; no mobile
   (media query) o botão preenche a célula e o rótulo pode usar todo o espaço. */
.tbl-filter-lbl{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;text-align:left;max-width:160px}
.tbl-filter-menu{position:fixed;z-index:150;background:var(--surface);border:1px solid var(--border);border-radius:10px;box-shadow:var(--shadow-md);padding:4px;min-width:190px;max-height:min(60vh,360px);overflow:auto}
.tbl-filter:not(.open) .tbl-filter-menu{display:none}
.tbl-filter-opt{display:flex;align-items:center;gap:8px;width:100%;padding:7px 9px;border:none;background:transparent;border-radius:7px;color:var(--text);cursor:pointer;text-align:left;font-size:13px;white-space:nowrap}
.tbl-filter-opt:hover{background:var(--surface-2)}
.tbl-filter-opt.active{background:var(--accent-soft);color:var(--accent);font-weight:600}
/* Dropdown de Período (item DESPESAS 4): mini-formulário compacto (rádios + inputs de data De/Até). */
.tbl-period-menu{min-width:220px;padding:10px}
.tbl-period-lbl{font-size:12px;font-weight:600;color:var(--text-soft);margin-bottom:6px}
.tbl-period-opt{display:flex;align-items:center;gap:8px;padding:5px 4px;border-radius:6px;cursor:pointer;font-size:13px;color:var(--text)}
.tbl-period-opt:hover{background:var(--surface-2)}
.tbl-period-opt input{margin:0}
.tbl-period-opt-desc{margin-left:auto;font-size:11px;color:var(--text-soft);white-space:nowrap}
.tbl-period-custom{margin-top:8px;padding-top:8px;border-top:1px solid var(--border);display:flex;flex-direction:column;gap:6px}
.tbl-period-custom .field-inline{display:flex;align-items:center;gap:8px}
.tbl-period-custom .field-inline label{font-size:12px;color:var(--text-soft);width:28px;flex:none}
.tbl-period-custom .field-inline .input{flex:1;min-width:0}
.tbl-period-clear{margin-top:8px;font-size:12px}
/* Filtro em modal (mobile): as opções ocupam a largura inteira, uma por linha, alvo de toque confortável. */
.tbl-filter-modal-opts{display:flex;flex-direction:column;gap:2px}
.tbl-filter-modal-opts .tbl-filter-opt{padding:11px 10px;font-size:14px}
.tbl-filter-modal .tbl-period-opt{padding:9px 4px;font-size:14px}
/* Telas menores (<=760px, mesmo ponto do modo modal): filtros descem pra linha própria, largura cheia,
   dividindo-se por igual (flex:1) — o rótulo deixa de truncar e usa o espaço da célula (item DESPESAS 2). */
@media (max-width:760px){
  .tbl-headbar-filters{width:100%;justify-content:stretch}
  .tbl-filter{flex:1 1 130px}
  .tbl-filter-lbl{max-width:none}
}
/* Input em tamanho small (busca do header + inputs de data do Período). */
.input-sm{padding-top:6px;padding-bottom:6px;font-size:13px}
.combo .input-sm{padding-top:6px;padding-bottom:6px;font-size:13px}
.filters-row{display:grid;gap:12px}
.filters-row-2{grid-template-columns:repeat(2,1fr)}
.filters-row-3{grid-template-columns:repeat(3,1fr)}
@media (max-width:760px){.filters-row-2,.filters-row-3{grid-template-columns:1fr}}
/* Formulário em 2 colunas no corpo (página de criar Pedido): coluna maior (itens) + lateral (cadastrais). */
.ped-form-2col{display:grid;grid-template-columns:minmax(0,1fr) 340px;gap:20px;align-items:start}
/* Colapsa pra 1 coluna cedo (≤1080): os itens do pedido são a área primária e precisam de largura; abaixo disso
   a coluna lateral (cliente/empresa) some pra baixo e os itens ocupam a página inteira. */
@media (max-width:1080px){.ped-form-2col{grid-template-columns:1fr}}
/* Faixa persistente de conexão caída (item GERAL 2) — no topo do conteúdo, empurra pra baixo (nunca esconde
   o cabeçalho). Vermelha e larga de propósito: o cache mascara o offline, isto deixa explícito. */
.connection-banner{display:flex;align-items:center;justify-content:center;gap:10px;padding:8px 14px;background:var(--danger,#c0392b);color:#fff;font-size:13px;flex-wrap:wrap;text-align:center}
.connection-banner-ic{display:inline-flex;flex:none}
.connection-banner .btn{background:rgba(255,255,255,.18);color:#fff;border-color:rgba(255,255,255,.45);flex:none}
.connection-banner .btn:hover{background:rgba(255,255,255,.28)}
/* Estado de erro de carregamento de um bloco/lista/aba (renderLoadError). Quando a causa é conexão,
   repete o diagnóstico da faixa (internet x servidor); caso contrário, a mensagem específica. */
.load-error{display:flex;align-items:center;gap:10px;padding:12px 14px;color:var(--text-faint);font-size:13px;flex-wrap:wrap}
.load-error-ic{flex:none;display:inline-flex;color:var(--danger)}
.load-error-txt{flex:1;min-width:150px}
.load-error-title{font-weight:600;color:var(--text)}
.load-error-desc{font-size:12px;margin-top:2px}
.load-error-btn{flex:none}
.file-dropzone{border:2px dashed var(--border-strong);border-radius:var(--radius-lg);padding:26px 16px;text-align:center;cursor:pointer;transition:.15s;background:var(--surface-2);margin-bottom:14px}
.file-dropzone:hover,.file-dropzone.dragover{border-color:var(--accent);background:var(--accent-soft)}
.file-dropzone-inner{display:flex;flex-direction:column;align-items:center}
.file-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(170px,1fr));gap:12px}
/* Itens do pedido (PEDIDOS 5): um card só, cabeçalho de colunas uma vez, linhas sem borda própria, e o
   "Adicionar item" no mesmo card. A mesma grade vale pro cabeçalho e pra cada linha; item de catálogo ocupa
   as 2 primeiras colunas (Produto+Descrição) escondendo a descrição repetida (PEDIDOS 3). */
.ped-items-card{border:1px solid var(--border);border-radius:8px;overflow:hidden;container-type:inline-size;container-name:peditems}
/* Cabeçalho e linhas do pedido numa grade de colunas alinhadas: Item | Qtd | Preço un. | Total | (remover).
   A mesma grade vale pro cabeçalho e pra cada linha, então os números batem coluna a coluna entre as linhas. */
.ped-item-grid{display:grid;grid-template-columns:minmax(0,1fr) 84px 116px 92px 30px;gap:10px;align-items:center}
.ped-item-head{padding:9px 14px;background:var(--surface-2);border-bottom:1px solid var(--border)}
.ped-item-head .label{margin:0;font-size:10px}
.ped-item-head .c{text-align:center}
.ped-item-head .r{text-align:right}
.ped-item-row{padding:11px 14px;border-bottom:1px solid var(--border);align-items:flex-start}
.ped-item-row:last-child{border-bottom:0}
.ped-item-main{display:flex;gap:11px;min-width:0;align-items:flex-start}
.ped-item-thumb{width:42px;height:42px;border-radius:9px;flex:none;display:grid;place-items:center;font-size:19px;background:var(--surface-3);border:1px solid var(--border);overflow:hidden;color:var(--text-faint)}
.ped-item-thumb img{width:100%;height:100%;object-fit:cover}
.ped-item-info{min-width:0;flex:1}
.ped-item-name{font-weight:600;font-size:13.5px;line-height:1.3;overflow:hidden;text-overflow:ellipsis}
.ped-item-sku{font-size:11px;color:var(--text-faint);font-variant-numeric:tabular-nums;letter-spacing:.01em}
.ped-item-attrs{display:flex;align-items:center;gap:6px;margin-top:5px;flex-wrap:wrap}
.ped-attr-pill{display:inline-flex;align-items:center;gap:5px;font-size:11.5px;color:var(--text-soft);background:var(--surface-3);padding:2px 8px;border-radius:999px}
.ped-attr-dot{width:11px;height:11px;border-radius:50%;border:1px solid var(--border-strong);flex:none}
.ped-item-total{font-weight:700;font-size:14.5px;text-align:right;font-variant-numeric:tabular-nums}
.ped-ci-total{padding-top:8px}
.ped-item-neg{font-size:10px;margin-top:3px;text-align:right;font-weight:600}
.ped-qty{display:flex;align-items:center;border:1px solid var(--border-strong);border-radius:var(--radius-sm);overflow:hidden;height:31px;width:100%}
.ped-qty button{width:24px;height:100%;border:none;background:var(--surface);color:var(--text-soft);font-size:15px;font-weight:600;flex:none;cursor:pointer}
.ped-qty button:hover{background:var(--surface-3);color:var(--text)}
.ped-qty input{width:100%;min-width:0;height:100%;border:none;border-left:1px solid var(--border);border-right:1px solid var(--border);text-align:center;background:var(--surface);color:var(--text);font-size:13px;font-weight:600;font-variant-numeric:tabular-nums}
.ped-qty input:focus{outline:none}
.ped-price-field{display:flex;align-items:center;gap:4px;border:1px solid var(--border-strong);border-radius:var(--radius-sm);padding:0 8px;height:31px;background:var(--surface)}
.ped-price-field:focus-within{border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-ring)}
.ped-price-field .cur{font-size:11px;color:var(--text-faint);flex:none}
.ped-price-field input{width:100%;min-width:0;border:none;background:transparent;text-align:right;font-size:13px;font-weight:600;color:var(--text);font-variant-numeric:tabular-nums;padding:0}
.ped-price-field input:focus{outline:none;box-shadow:none}
.ped-item-del{height:31px;width:30px;flex:none;display:inline-flex;align-items:center;justify-content:center}
.ped-item-text{padding:7px 0;font-size:14px}
/* Seletor de variação fiel ao protótipo (openVariantSheet): tabs Unitário/Grade, swatches grandes de cor,
   caixa de resolução (estoque/preço), grade B2B. Componente único, usado pelo Pedido e pelo Carrinho. */
.pvs{min-width:min(540px,86vw);max-width:min(560px,92vw)}
.pvs-head{display:flex;gap:13px;align-items:flex-start;margin-bottom:4px}
.pvs-hero{width:54px;height:54px;border-radius:12px;flex:none;display:grid;place-items:center;font-size:24px;background:var(--surface-3);border:1px solid var(--border);overflow:hidden;color:var(--text-faint)}
.pvs-hero img{width:100%;height:100%;object-fit:cover}
.pvs-title{font-weight:700;font-size:16px;line-height:1.25}
.pvs-sub{font-size:12px;color:var(--text-faint);margin-top:2px;display:flex;gap:7px;align-items:center;flex-wrap:wrap}
.pvs-tabs{display:inline-flex;background:var(--surface-3);border-radius:999px;padding:3px;gap:2px;margin-top:10px}
.pvs-tab{border:none;background:transparent;color:var(--text-soft);font-size:12.5px;font-weight:650;padding:6px 15px;border-radius:999px;transition:.12s;cursor:pointer}
.pvs-tab.on{background:var(--surface);color:var(--text);box-shadow:var(--shadow-sm)}
.pvs-body{margin-top:6px}
.pvs-axis{margin-top:16px}
.pvs-axis-name{font-size:12px;font-weight:700;color:var(--text-soft);margin-bottom:9px}
.pvs-sw-row{display:flex;flex-wrap:wrap;gap:10px}
.pvs-sw-cell{display:flex;flex-direction:column;align-items:center;gap:4px;width:44px}
.pvs-sw{position:relative;width:40px;height:40px;border-radius:11px;border:2px solid var(--border);cursor:pointer;transition:.12s;box-shadow:inset 0 0 0 2px var(--surface)}
.pvs-sw:hover{transform:translateY(-1px)}
.pvs-sw.sel{border-color:var(--accent);box-shadow:inset 0 0 0 2px var(--surface),0 0 0 3px var(--accent-ring)}
.pvs-sw.blocked{opacity:.32;cursor:not-allowed;pointer-events:none}
.pvs-sw.blocked::after{content:"";position:absolute;inset:0;border-radius:9px;background:repeating-linear-gradient(45deg,transparent,transparent 4px,rgba(0,0,0,.3) 4px,rgba(0,0,0,.3) 6px)}
.pvs-sw .chk{position:absolute;inset:0;display:none;place-items:center;color:#fff;filter:drop-shadow(0 1px 1px rgba(0,0,0,.7))}
.pvs-sw.sel .chk{display:grid}
.pvs-sw-cap{font-size:10.5px;color:var(--text-faint);text-align:center;line-height:1.2;width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.pvs-chip{padding:7px 14px;border-radius:999px;border:1.5px solid var(--border-strong);background:var(--surface);font-size:13px;font-weight:600;color:var(--text-soft);transition:.12s;cursor:pointer;display:inline-flex;align-items:center;gap:6px}
.pvs-chip:hover{border-color:var(--text-faint)}
.pvs-chip.sel{border-color:var(--accent);background:var(--accent-soft);color:var(--accent)}
.pvs-chip.blocked{opacity:.35;text-decoration:line-through;cursor:not-allowed;pointer-events:none}
.pvs-chip .mod{opacity:.6;font-size:11px;font-weight:600}
.pvs-resolve{margin-top:18px;border:1px solid var(--border);border-radius:var(--radius-md);overflow:hidden}
.pvs-rrow{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:10px 14px;border-bottom:1px solid var(--border)}
.pvs-rrow:last-child{border-bottom:none}
.pvs-rrow .k{font-size:12px;color:var(--text-faint)}
.pvs-rrow .v{font-weight:650;font-size:13.5px}
.pvs-price{font-size:21px;font-weight:750;letter-spacing:-.01em}
.pvs-price-strike{color:var(--text-faint);text-decoration:line-through;font-size:13px;font-weight:500;margin-right:8px}
.pvs-foot{display:flex;align-items:center;gap:12px;margin-top:18px}
.pvs-qty{display:inline-flex;align-items:center;border:1px solid var(--border-strong);border-radius:var(--radius-sm);overflow:hidden;height:36px}
.pvs-qty button{width:34px;height:100%;border:none;background:var(--surface);color:var(--text);font-size:17px;font-weight:600;cursor:pointer}
.pvs-qty button:hover{background:var(--surface-3)}
.pvs-qty input{width:52px;height:36px;border:none;border-left:1px solid var(--border);border-right:1px solid var(--border);text-align:center;background:var(--surface);color:var(--text);font-size:14px;font-weight:650;font-variant-numeric:tabular-nums}
.pvs-qty input:focus{outline:none}
.pvs-grade-scroll{overflow:auto;max-height:52vh;margin-top:14px;border:1px solid var(--border);border-radius:var(--radius-md)}
table.pvs-grade{border-collapse:separate;border-spacing:0;width:100%;min-width:100%}
table.pvs-grade th,table.pvs-grade td{border-bottom:1px solid var(--border);border-right:1px solid var(--border);text-align:center}
table.pvs-grade thead th{background:var(--surface-2);padding:8px 6px;font-size:11.5px;font-weight:700;color:var(--text-soft);position:sticky;top:0;z-index:1;white-space:nowrap}
table.pvs-grade tbody th{background:var(--surface-2);padding:7px 10px;text-align:left;font-weight:600;font-size:12.5px;white-space:nowrap;position:sticky;left:0}
table.pvs-grade td:last-child,table.pvs-grade th:last-child{border-right:none}
table.pvs-grade tbody tr:last-child th,table.pvs-grade tbody tr:last-child td{border-bottom:none}
.pvs-cell{padding:4px}
.pvs-cell input{width:46px;height:32px;border:1px solid transparent;border-radius:6px;text-align:center;background:transparent;color:var(--text);font-size:13px;font-weight:600;font-variant-numeric:tabular-nums}
.pvs-cell input:hover{border-color:var(--border)}
.pvs-cell input:focus{outline:none;border-color:var(--accent);background:var(--surface);box-shadow:0 0 0 2px var(--accent-ring)}
.pvs-cell input.has{background:var(--accent-soft);color:var(--accent)}
.pvs-cell .atp{font-size:9.5px;color:var(--text-faint);line-height:1;margin-top:1px}
.pvs-cell.blocked{background:repeating-linear-gradient(45deg,transparent,transparent 5px,var(--surface-3) 5px,var(--surface-3) 9px)}
/* Stepper +/- por célula da grade B2B (item PEDIDOS 2) e busca compacta no canto do cabeçalho. */
.pvs-stepper{display:inline-flex;align-items:center;gap:2px}
.pvs-stepper button{width:20px;height:28px;flex:none;border:1px solid var(--border);background:var(--surface);border-radius:5px;color:var(--text-soft);font-size:15px;line-height:1;cursor:pointer;display:flex;align-items:center;justify-content:center;padding:0}
.pvs-stepper button:hover{border-color:var(--border-strong);color:var(--text)}
.pvs-stepper input{width:40px}
.pvs-grade-search input{width:100%;min-width:104px;height:26px;font-size:12px;padding:2px 8px;border:1px solid var(--border);border-radius:6px;background:var(--surface);color:var(--text);font-weight:500}
.pvs-summary{display:flex;flex-wrap:wrap;gap:16px;align-items:center;margin-top:14px;padding:11px 14px;border-radius:var(--radius-md);background:var(--surface-2);border:1px solid var(--border)}
.pvs-gs .n{font-size:18px;font-weight:750;line-height:1;font-variant-numeric:tabular-nums}
.pvs-gs .l{font-size:11px;color:var(--text-faint);margin-top:3px}
/* Painel de contexto do cliente no cadastro de pedido (fiel ao protótipo). */
.ped-cust-card{border:1px solid var(--border);border-radius:var(--radius-md);padding:12px;display:flex;gap:11px;align-items:center;margin-top:12px;background:var(--surface-2)}
.ped-cust-avatar{width:40px;height:40px;border-radius:50%;background:linear-gradient(135deg,var(--accent),var(--accent-2));color:var(--accent-contrast);display:grid;place-items:center;font-weight:700;font-size:15px;flex:none}
.ped-cust-facts{display:grid;grid-template-columns:1fr 1fr;gap:8px;margin-top:12px}
.ped-fact{background:var(--surface-2);border:1px solid var(--border);border-radius:var(--radius-sm);padding:8px 10px}
.ped-fact .l{font-size:10.5px;color:var(--text-faint);text-transform:uppercase;letter-spacing:.04em}
.ped-fact .v{font-size:13.5px;font-weight:700;margin-top:2px;font-variant-numeric:tabular-nums}
/* Controle segmentado do tipo de cliente (Entidade | Lead | Avulso), fiel ao protótipo. */
.ped-seg{display:inline-flex;background:var(--surface-3);border-radius:8px;padding:3px;gap:2px;width:100%}
.ped-seg button{flex:1;border:none;background:transparent;color:var(--text-soft);font-size:12.5px;font-weight:650;padding:7px 4px;border-radius:6px;transition:.12s;cursor:pointer}
.ped-seg button.on{background:var(--surface);color:var(--text);box-shadow:var(--shadow-sm)}
/* Barra de rascunhos do painel Novo Pedido (PEDIDOS 3 / Fatia 4): 1 pílula por empresa com rascunho aberto,
   + "Novo". Alternar troca de rascunho; a empresa trava assim que o rascunho tem itens. */
.ped-draft-bar{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin:0 0 14px;padding:9px 12px;background:var(--surface-2);border:1px solid var(--border);border-radius:10px}
.ped-draft-bar .lbl{font-size:11.5px;color:var(--text-faint);margin-right:2px}
.ped-draft-pill{display:inline-flex;align-items:center;gap:7px;padding:6px 12px;border-radius:20px;font-size:12.5px;font-weight:600;border:1px solid var(--border-strong);background:var(--surface);color:var(--text-soft);cursor:pointer;transition:.12s}
.ped-draft-pill:hover{border-color:var(--accent);color:var(--text)}
.ped-draft-pill.on{background:var(--accent-soft);border-color:var(--accent);color:var(--accent)}
.ped-draft-pill .cnt{font-size:11px;padding:1px 7px;border-radius:10px;background:var(--surface-3);color:var(--text-soft)}
.ped-draft-pill.on .cnt{background:var(--accent);color:var(--accent-contrast)}
.ped-draft-pill.novo{border-style:dashed}
.ped-draft-pill.alheio:not(.on){border-style:dotted;opacity:.85}
/* Opção rica do dropdown de busca do catálogo: thumbnail + estoque + selo de variação (reusa .combo-list). */
.ped-search-opt{display:flex;align-items:center;gap:11px;padding:9px 11px;cursor:pointer}
.ped-search-opt:hover,.ped-search-opt.hi{background:var(--accent-soft)}
.ped-search-thumb{width:40px;height:40px;border-radius:8px;flex:none;display:grid;place-items:center;font-size:17px;background:var(--surface-3);border:1px solid var(--border);overflow:hidden;color:var(--text-faint)}
.ped-search-thumb img{width:100%;height:100%;object-fit:cover}
/* Container query (não viewport): o card de itens fica estreito quando a página está em 2 colunas ou no drawer,
   mesmo com a janela larga. Abaixo de ~600px de card, as colunas viram um empilhamento em 2 faixas:
   item em cima (largura cheia) e os controles (qtd/preço/total/remover) numa faixa embaixo. */
@container peditems (max-width:600px){
  .ped-item-head{display:none}
  .ped-item-grid{grid-template-columns:104px minmax(0,1fr) auto auto;grid-template-areas:"main main main main" "qty price total del";row-gap:11px;column-gap:10px;align-items:center}
  .ped-ci-main{grid-area:main}.ped-ci-qty{grid-area:qty}.ped-ci-price{grid-area:price}.ped-ci-total{grid-area:total;padding-left:4px;padding-top:0}.ped-ci-del{grid-area:del;justify-self:end}
}
.file-card{border:1px solid var(--border);border-radius:var(--radius-lg);padding:12px;display:flex;flex-direction:column;gap:6px;background:var(--surface);transition:.15s}
.file-card:hover{box-shadow:var(--shadow-sm);border-color:var(--file-color, var(--border-strong))}
.file-card-icon{width:38px;height:38px;border-radius:9px;display:flex;align-items:center;justify-content:center;flex:none;position:relative}
.file-card-type-badge{position:absolute;bottom:-4px;right:-5px;background:var(--surface);border:1px solid var(--border);border-radius:4px;padding:0 3px;font-size:8px;font-weight:800;letter-spacing:.02em;color:var(--text-faint);line-height:1.4}
.file-card-name{font-size:12.5px;font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;margin-top:2px}
.file-card-meta{font-size:11px;color:var(--text-faint)}
.file-progress-bar{height:5px;border-radius:3px;background:var(--border);overflow:hidden;margin-top:2px}
.file-progress-fill{height:100%;background:var(--accent);transition:width .1s linear}
/* Player de mensagem de voz (messageBubbleHtml/audioPlayerHtml) — botão redondo de play/pause +
   barra de progresso clicável (mesmo componente .file-progress-bar/.file-progress-fill de upload e
   subtarefa) + tempo decorrido/total. width:200px trava um tamanho mínimo legível pra bolha do chat
   não ficar espremendo o player quando o texto ao redor é curto. */
.audio-player{display:flex;align-items:center;gap:8px;width:200px;max-width:100%}
.audio-player-toggle{flex:none;border-radius:50%;width:30px;height:30px;background:var(--accent);color:var(--accent-contrast);border:none}
.audio-player-toggle:hover{background:var(--accent)}
.audio-player-track{flex:1;padding:8px 0;cursor:pointer}
.audio-player-time{flex:none;font-variant-numeric:tabular-nums;white-space:nowrap}
/* Gatilho de áudio na bolha (audioTriggerHtml) — no chat principal a bolha vira só um botão que sobe o
   áudio pro player fixo do rodapé (audioDockHtml/wireAudioDock); a reprodução acontece lá, não aqui. O
   chat flutuante continua com o .audio-player inline de sempre. .active = é o áudio carregado no player
   fixo agora; enquanto ele toca, o gatilho reflete o progresso (barras tocadas + dot + tempo), igual ao
   dock, pra dar o feedback de "este é o que está tocando" também no corpo do chat. */
.audio-trigger{display:inline-flex;align-items:center;gap:8px;width:200px;max-width:100%;background:transparent;border:none;padding:2px 0;cursor:pointer;text-align:left;color:inherit}
.audio-trigger-ic{flex:none;display:inline-flex;align-items:center;justify-content:center;width:28px;height:28px;border-radius:50%;background:var(--accent);color:var(--accent-contrast)}
.audio-trigger-wave{flex:1;position:relative;display:flex;align-items:center;justify-content:flex-start;gap:2px;height:22px;min-width:0}
.audio-trigger-dot{position:absolute;top:50%;left:0;width:9px;height:9px;border-radius:50%;background:var(--accent);transform:translate(-50%,-50%);pointer-events:none;display:none;box-shadow:0 0 0 1.5px var(--surface)}
.audio-trigger.active .audio-trigger-dot{display:block}
.audio-trigger-label{flex:none;font-size:12px;color:var(--text-faint);font-variant-numeric:tabular-nums}
.audio-trigger.active .audio-trigger-label{color:var(--accent);font-weight:600}
/* Transcrição de áudio: atalho compacto na linha da hora (ícone + prévia até 20 chars) e painel de texto
   completo, oculto por padrão e revelado ao clicar no atalho. Ver audioTranscriptionShortcutInline/
   audioTranscriptionTextHtml em public/index.html. Spacing enxuto de propósito (sem margem sobrando). */
.atd-msg-timerow{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
/* Horário da mensagem, agora FORA da bolha (messageBubbleHtml) — discreto, abaixo dela, alinhado ao lado do
   remetente (text-align inline). margin pequena pra encostar na bolha sem grudar. */
.atd-msg-time{margin-top:2px;line-height:1.2;opacity:.85}
/* Marcador de atraso (mensagem recuperada de queda): compacto, INLINE na frente da hora, na mesma linha (some
   junto com a hora quando o agrupamento do mesmo minuto a esconde, pra não repetir o atraso em cada bolha do
   lote). Só o resumo do atraso na tela; a frase longa ("respondida antes, reveja o contexto") vai no title, e a
   explicação do lote já é dada uma vez pela nota-sistema do backend (server/leadMessages.js). Vermelho quando
   houve resposta no escuro. */
.atd-msg-delay{display:inline-flex;align-items:center;gap:4px;max-width:100%;font-size:11px;line-height:1.25;color:var(--warning);cursor:help}
.atd-msg-delay svg{flex:none}
.atd-msg-delay span{min-width:0;overflow-wrap:anywhere}
.atd-msg-delay-blind{color:var(--danger,#c0392b);font-weight:600}
.audio-transcribe-link{display:inline-flex;align-items:center;gap:5px;max-width:100%;min-width:0;margin-left:auto;background:transparent;border:none;padding:0;cursor:pointer;color:var(--accent);font-size:12px;line-height:1.2;font-family:inherit}
.audio-transcribe-link:hover .audio-transcribe-preview{text-decoration:underline}
.audio-transcribe-preview{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0;font-style:italic;color:var(--text-faint);font-size: 11px;}
.audio-transcribe-ic{flex:none;display:inline-flex;align-items:center}
.atd-msg-transcription{margin-top:4px;padding-top:4px;border-top:1px solid var(--border);word-break:break-word}
/* Barra da waveform (compartilhada por gatilho e dock): traço fino e totalmente arredondado no estilo da
   mensagem de voz do WhatsApp. Não-tocada num cinza claro (mais claro que --text-faint puro, pedido do
   usuário); tocada na cor de destaque. */
.aw-bar{flex:none;width:2px;border-radius:999px;background:color-mix(in srgb, var(--text-faint) 38%, transparent)}
.aw-bar.played{background:var(--accent)}
/* Player fixo do rodapé (audioDockHtml) — pinado entre a lista de mensagens e o composer, sempre visível.
   Uma superfície de reprodução única pra todos os áudios do chat, com setas anterior/próximo, velocidade e
   waveform clicável no estilo da mensagem de voz do WhatsApp. */
.audio-dock{margin:8px 0;border:1px solid var(--border);border-radius:12px;background:var(--surface-2);padding:8px 10px}
.audio-dock-row{display:flex;align-items:center;gap:8px}
.audio-dock-toggle{flex:none;border-radius:50%;width:34px;height:34px;background:var(--accent);color:var(--accent-contrast);border:none;display:flex;align-items:center;justify-content:center}
.audio-dock-nav{flex:none;width:28px;height:28px;border-radius:50%;border:none;background:transparent;color:var(--text)}
.audio-dock-nav:hover:not(:disabled){background:var(--surface)}
.audio-dock-nav:disabled{opacity:.35;cursor:default}
.audio-dock-wave{flex:1;position:relative;display:flex;align-items:center;justify-content:flex-start;gap:2px;height:34px;cursor:pointer;min-width:0;touch-action:none}
.audio-dock-dot{position:absolute;top:50%;width:12px;height:12px;border-radius:50%;background:var(--accent);transform:translate(-50%,-50%);pointer-events:none;box-shadow:0 0 0 2px var(--surface-2)}
.audio-dock-rate{flex:none;font-size:12px;font-weight:600;font-variant-numeric:tabular-nums;border:1px solid var(--border);background:var(--surface);color:var(--text);border-radius:999px;padding:3px 10px;min-width:44px}
.audio-dock-close{flex:none;width:26px;height:26px;border:none;background:transparent;color:var(--text-faint);display:flex;align-items:center;justify-content:center}
.audio-dock-close:hover{color:var(--text)}
.audio-dock-meta{display:flex;align-items:center;justify-content:space-between;font-size:11px;color:var(--text-faint);font-variant-numeric:tabular-nums;margin-top:4px;padding:0 2px}
/* Subtítulo sincronizado da transcrição, no espaço livre da meta row (entre tempo decorrido e horário de
   envio). Ocupa a folga (flex:1), texto centralizado e pode quebrar em 1-2 linhas conforme a frase. */
.audio-dock-transcript{flex:1;min-width:0;margin:0 10px;font-size:12px;line-height:1.35;color:var(--text);text-align:center;overflow-wrap:anywhere;max-height:3.6em;overflow-y:auto}
/* Borda animada da bolha cujo áudio está tocando agora (syncAudioTriggers liga/desliga .audio-playing). Um
   segmento de luz percorre o contorno em loop, esmaecendo no começo e no fim (degradê nas duas pontas via
   conic-gradient com transparências). Feito num ::after mascarado só na faixa da borda, sem cobrir o texto. */
@property --atd-audio-angle{syntax:'<angle>';initial-value:0deg;inherits:false}
.atd-msg-bubble.audio-playing{position:relative}
/* Mesma borda de luz animada é reaproveitada pela mensagem em ENVIO (item CONVERSAS 4): a bolha nasce com o
   contorno percorrido enquanto o POST não confirma; ao aceitar (ou ao adotar a mensagem real), a classe sai. */
.atd-msg-bubble.audio-playing::after,.atd-msg-bubble-sending::after{content:'';position:absolute;inset:0;border-radius:inherit;padding:1.5px;pointer-events:none;z-index:1;background:conic-gradient(from var(--atd-audio-angle),transparent 0deg,transparent 210deg,color-mix(in srgb, var(--accent) 55%, transparent) 300deg,var(--accent) 340deg,transparent 360deg);-webkit-mask:linear-gradient(#000 0 0) content-box,linear-gradient(#000 0 0);-webkit-mask-composite:xor;mask:linear-gradient(#000 0 0) content-box,linear-gradient(#000 0 0);mask-composite:exclude;animation:atdAudioBorder 2.6s linear infinite}
/* No envio a volta é mais rápida (dá a sensação de "carregando"); o áudio segue nos 2,6s de sempre. */
.atd-msg-bubble-sending::after{animation-duration:1.3s}
@keyframes atdAudioBorder{to{--atd-audio-angle:360deg}}
@media (prefers-reduced-motion:reduce){.atd-msg-bubble.audio-playing::after,.atd-msg-bubble-sending::after{animation-duration:6s}}
.spin-icon{animation:spin .8s linear infinite}
@media (prefers-reduced-motion: reduce){.spin-icon{animation-duration:2.2s}}
.kanban-boards-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:14px}
.kanban-board-card{border:1px solid var(--border);border-radius:var(--radius-lg);padding:16px;background:var(--surface);cursor:pointer;transition:.15s}
.kanban-board-card:hover{box-shadow:var(--shadow-sm);border-color:var(--border-strong)}
.kanban-board-wrap{display:flex;gap:14px;overflow-x:auto;padding-bottom:8px;align-items:stretch}
.kanban-column{flex:0 0 270px;width:270px;background:var(--surface-2);border:1px solid var(--border);border-radius:var(--radius-lg);padding:12px;display:flex;flex-direction:column}
.kanban-column-head{display:flex;align-items:center;gap:8px;margin-bottom:10px}
.kanban-column-dot{width:9px;height:9px;border-radius:50%;flex:none}
.kanban-column-count{margin-left:auto;font-size:11px;color:var(--text-faint);background:var(--surface);border:1px solid var(--border);border-radius:20px;padding:1px 7px}
/* flex:1 faz a coluna mais curta esticar até a altura da mais alta (herdada do align-items:stretch
   do .kanban-board-wrap) sem deixar vão em branco: o espaço extra vai pro corpo da coluna, então o
   botão "Adicionar cartão" (irmão logo abaixo) fica sempre alinhado na mesma linha em todas as colunas. */
.kanban-column-body{display:flex;flex-direction:column;gap:8px;min-height:40px;flex:1}
.kanban-column-body.dragover{background:var(--accent-soft);border-radius:8px}
/* Some durante o drag-over pra não sobrepor o cartão sendo arrastado por cima do texto/ícone da dica. */
.kanban-column-body.dragover .kanban-empty-hint,.kanban-column-body.dragover .kanban-drag-hint{display:none}
/* pointer-events:none nas duas dicas: sem isso, soltar o card bem em cima do texto/ícone da dica
   mira o drop nesse elemento filho (sem listener de drop nenhum) em vez de borbulhar de forma
   confiável pro data-stage-drop pai — dragenter/dragleave entre pai e filho tem timing inconsistente
   entre navegadores (o filho "rouba" o alvo do evento mesmo com o pai escutando dragover/drop), então
   às vezes o drop simplesmente não acontecia. Com pointer-events:none a dica nunca é alvo de mouse/drag
   nenhum, todo evento vai direto pro data-stage-drop por baixo, sem corrida nenhuma.
   display:none em .dragover (abaixo) continua útil pra sumir com a dica assim que o arraste começa. */
.kanban-empty-hint,.kanban-drag-hint{pointer-events:none}
.kanban-empty-hint{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:flex-end;gap:6px;padding:6px 4px 2px;text-align:center}
.kanban-empty-hint-text{font-size:12px;font-weight:700;color:var(--text-soft)}
.kanban-empty-hint-sub{font-size:10.5px;font-weight:500;color:var(--text-faint);max-width:170px;line-height:1.4}
.kanban-empty-arrow{color:var(--border-strong)}
.kanban-drag-hint{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8px;padding:14px 8px;text-align:center;border:1px dashed var(--border-strong);border-radius:10px}
.kanban-drag-hint-icon{width:32px;height:32px;border-radius:50%;background:var(--surface-2);color:var(--text-faint);display:flex;align-items:center;justify-content:center;flex:none}
.kanban-drag-hint-text{font-size:11.5px;font-weight:600;color:var(--text-faint);max-width:150px;line-height:1.4}
/* Dica de arrastar troca o ícone por dispositivo: cursor pra desktop (mouse), mãozinha pra touch —
   os dois ficam no DOM e o CSS decide qual mostrar, sem checar user agent em JS. */
.kanban-drag-hint-icon-mobile{display:none}
@media (hover:none),(pointer:coarse){
  .kanban-drag-hint-icon-desktop{display:none}
  .kanban-drag-hint-icon-mobile{display:block}
}
.kanban-card{border:1px solid var(--border);border-left:3px solid var(--accent);border-radius:8px;padding:8px 9px;background:color-mix(in srgb, var(--stage-color, var(--border)) 5%, var(--surface));cursor:grab;transition:.15s;position:relative}
.kanban-card:hover{box-shadow:var(--shadow-sm)}
.kanban-card[draggable="false"]{cursor:default;user-select:none}
body.kanban-dragging{user-select:none}
.kanban-card-hover-actions{display:none;border-top:1px solid var(--border);margin-top:6px;padding-top:4px;gap:2px;justify-content:space-around}
.kanban-card:hover .kanban-card-hover-actions{display:flex}
.kanban-card-hover-link{display:flex;align-items:center;gap:3px;font-size:10.5px;font-weight:700;color:var(--text-faint);background:transparent;border:none;padding:3px 5px;border-radius:5px;cursor:pointer}
.kanban-card-hover-link:hover{color:var(--accent);background:var(--accent-soft)}
.kanban-card-hover-link.danger:hover{color:var(--danger);background:var(--danger-soft)}
/* Linha expansível de tabela (dataTable cfg.rowDetail): clicar a linha abre uma linha-detalhe abaixo com
   uma barra de ações. Reaproveita o botão .kanban-card-hover-link (mesmo propósito: ação rápida icone+texto),
   só num container próprio, sempre visível (a linha já está aberta) e com alvo um pouco maior pra tabela. */
tr.dt-clickable{cursor:pointer}
tr.dt-row-open>td{background:var(--surface-2)}
tr.dt-detail-row>td{background:var(--surface-2);padding:8px 12px;border-top:none}
.dt-detail-actions{display:flex;flex-wrap:wrap;gap:6px;align-items:center}
.dt-detail-actions .kanban-card-hover-link{font-size:12px;padding:5px 9px;border:1px solid var(--border)}
/* Faixa "Verificando atualizações": PRIMEIRA LINHA da tabela, acima dos registros que já estavam em memória
   (ver setListRevalidando). Não é esqueleto — o conteúdo continua legível embaixo; isto só avisa que uma
   conferência está em curso. Discreta de propósito: o normal é ela viver poucos décimos de segundo. */
tr.tbl-reval-row>td{background:var(--surface-2);border-top:none;padding:5px 12px;font-size:11.5px;font-weight:600;color:var(--text-faint);letter-spacing:.02em}
tr.tbl-reval-row>td>span{display:inline-flex;align-items:center;gap:6px}
tr.tbl-reval-row.err>td{background:var(--danger-soft);color:var(--danger)}
.tbl-reval-retry{background:transparent;border:none;padding:0 0 0 4px;font:inherit;color:inherit;text-decoration:underline;cursor:pointer}
/* Mesma faixa, no formato da lista de conversas do Atendimento (que é uma pilha de blocos, não uma tabela):
   mesmo fundo, mesma tipografia e o mesmo miolo (revalBandInnerHtml), só sem o <tr>/<td>. */
.atd-reval{background:var(--surface-2);padding:5px 12px;font-size:11.5px;font-weight:600;color:var(--text-faint);letter-spacing:.02em}
.atd-reval>span{display:inline-flex;align-items:center;gap:6px}
.atd-reval.err{background:var(--danger-soft);color:var(--danger)}
.kanban-card.dragging{opacity:.4}
.kanban-column.dragging{opacity:.4}
.kanban-column-head{cursor:grab}
.kanban-card-title{font-size:12.5px;font-weight:600;margin-bottom:4px;line-height:1.3}
.kanban-card-blocked{font-size:10px;margin-bottom:4px;display:inline-flex;align-items:center;gap:3px;padding:1px 6px}
.kanban-card-fields{display:flex;flex-direction:column;gap:1px;margin-bottom:4px}
.kanban-card-field{font-size:10.5px;color:var(--text-soft)}
.kanban-card-field b{color:var(--text-faint);font-weight:600}
.kanban-card-tags{display:flex;flex-wrap:wrap;gap:3px;margin-bottom:4px}
.kanban-card-tag{font-size:10px;background:var(--accent-soft);color:var(--accent);border-radius:20px;padding:1px 7px}
.kanban-card-foot{display:flex;align-items:center;gap:6px;margin-top:2px}
.kanban-card-owner{width:20px;height:20px;border-radius:50%;background:var(--accent-soft);color:var(--accent);font-size:9.5px;font-weight:700;display:flex;align-items:center;justify-content:center;flex:none}
.kanban-card-owner-wrap{display:flex;align-items:center;overflow:visible;flex:none}
.kanban-card-owner-wrap .admin-avatar-stack .admin-avatar{width:20px;height:20px;font-size:8.5px}
.kanban-card-meta{display:flex;align-items:center;gap:6px;justify-content:flex-end;flex:1 1 auto;min-width:0}
.kanban-card-badge{font-size:10px;color:var(--text-faint);display:flex;align-items:center;gap:2px;white-space:nowrap}
/* flex:0 1 40% mede a fatia de 40% contra .kanban-card-meta, não contra o footer inteiro — e por isso
   .kanban-card-meta precisa do flex:1 1 auto acima: sem ele, seu tamanho seria só o do próprio conteúdo
   (indefinido), e a porcentagem do filho não teria uma base real pra calcular em cima. Com o grow, meta
   passa a valer exatamente "o espaço que sobra depois do avatar" (a largura do footer menos
   .kanban-card-owner-wrap), e o justify-content:flex-end mantém o grupo (barra + arquivos + vencimento)
   coladinho na borda direita do card, sem gap entre eles — layout que já existia antes e o admin preferia.
   Nada aqui quebra linha (nem foot nem meta têm flex-wrap), a barra só encolhe (shrink:1) se precisar. */
.kanban-card-progress{gap:4px;flex:0 1 40%;min-width:0}
.kanban-card-progress b{font-weight:700;color:var(--text-faint);flex:none}
.kanban-card-progress .file-progress-bar{display:block;flex:1 1 auto;min-width:10px;height:6px;margin-top:0}
.kanban-card-progress .file-progress-fill{display:block;height:100%;background:var(--text-soft)}
.kanban-card-due{font-size:10px;color:var(--text-faint);display:flex;align-items:center;gap:2px;white-space:nowrap}
.kanban-card-due.overdue{color:var(--danger)}
.kanban-add-card-btn{width:100%;border:1px dashed var(--border-strong);border-radius:8px;padding:8px;background:transparent;color:var(--text-faint);font-size:12.5px;display:flex;align-items:center;justify-content:center;gap:5px;cursor:pointer;transition:.15s}
.kanban-add-card-btn:hover{background:var(--accent-soft);color:var(--accent);border-color:var(--accent)}
.kanban-column-new-stage{background:transparent;border:1px dashed var(--border-strong);border-radius:8px;align-items:stretch}
.kanban-add-stage-btn{position:sticky;top:16px;height:44px}
.kfinished-timeline-item{display:flex;gap:10px}
.kfinished-timeline-date{width:96px;flex:none;font-size:11px;color:var(--text-faint);text-align:right;padding-top:1px;white-space:nowrap}
.kfinished-timeline-rail{display:flex;flex-direction:column;align-items:center;width:8px;flex:none}
.kfinished-timeline-dot{width:8px;height:8px;border-radius:50%;flex:none;margin-top:4px}
.kfinished-timeline-rail::after{content:'';flex:1;width:1px;background:var(--border);margin-top:3px}
.kfinished-timeline-item:last-child .kfinished-timeline-rail::after{display:none}
.kfinished-timeline-body{flex:1;padding-bottom:10px;font-size:12px;display:flex;flex-direction:column;gap:2px}
.kfinished-timeline-item:last-child .kfinished-timeline-body{padding-bottom:0}
.kfinished-timeline-done{color:var(--text-faint);font-size:11px}
.kanban-tab-btn{display:inline-flex;align-items:center;gap:3px;padding:8px 12px;font-size:13px;font-weight:600;color:var(--text-faint);border:none;background:transparent;border-bottom:2px solid transparent;border-radius:6px 6px 0 0;cursor:pointer}
.kanban-tab-btn:not(.active):hover{color:var(--text)}
.kanban-tab-btn.active{color:var(--accent);border-bottom-color:var(--accent)}
.atd-scope-tab-btn.active{color:var(--accent-contrast);background:var(--accent);border-bottom-color:var(--accent)}
/* Abas horizontais: quando há mais abas do que cabem, NÃO rola (barra de rolagem é feia); em vez disso, as
   que não cabem colapsam num botão "⋯" que abre um dropdown com as ocultas (ver applyTabsOverflow no JS).
   Por isso overflow:hidden + nowrap: o JS mede e esconde as excedentes. (A .vmenu-nav lateral usa outra
   estratégia no mobile: colapsa num seletor emp-switch, ver .vmenu-more e buildVmenuMore.) */
.kcard-tabs-nav{overflow:hidden;flex-wrap:nowrap}
.kcard-tabs-nav .kanban-tab-btn{flex:none;white-space:nowrap}
@media (max-width:480px){.kcard-tabs-nav .kanban-tab-btn{padding:8px 8px;font-size:12px}}
/* Overflow por menu "⋯" (componente genérico de abas, item CONEXÕES 2 refeito). O botão vira o último item
   da barra; o dropdown lista as abas ocultas, cada uma disparando o clique da aba real (reusa o handler). */
.tabs-hidden{display:none !important}
.tabs-more{position:relative;flex:none;display:flex;align-items:center}
.tabs-more-btn{display:flex;align-items:center;gap:4px;flex:none;border:none;background:transparent;color:var(--text-soft);cursor:pointer;padding:8px 10px;border-radius:8px;font-weight:600;font-size:13.5px;line-height:1}
.tabs-more-btn:hover{background:var(--surface-2);color:var(--text)}
.tabs-more.has-active-hidden .tabs-more-btn{color:var(--accent)}
.tabs-more-menu{position:absolute;top:calc(100% + 4px);right:0;z-index:60;min-width:180px;max-width:min(320px,80vw);background:var(--surface);border:1px solid var(--border);border-radius:10px;box-shadow:var(--shadow-md);padding:4px;max-height:min(60vh,340px);overflow-y:auto;display:none}
.tabs-more.open .tabs-more-menu{display:block}
.tabs-more-item{display:flex;align-items:center;gap:8px;width:100%;text-align:left;padding:8px 10px;border:none;background:transparent;border-radius:7px;color:var(--text);cursor:pointer;white-space:nowrap;font-size:13.5px;font-weight:500}
.tabs-more-item:hover{background:var(--surface-2)}
.tabs-more-item.active{color:var(--accent);background:var(--accent-soft);font-weight:600}
/* rótulo cresce e empurra o badge (contador) pra direita; badge mantém a formatação do componente inline. */
.tabs-more-item-label{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis}
.tabs-more-item>.notif-count-badge{margin-left:auto;flex:none}
/* Menu vertical secundário (um "sub-menu" à esquerda do conteúdo): coluna do menu e conteúdo dentro de
   um único card com divisória — modelo container+coluna (ref. shadcn/mail). Componente compartilhado,
   usado em Configurações e na página de detalhe do Lead. No mobile a coluna vira uma faixa horizontal
   rolável no topo, pra não comer a largura do conteúdo.
   Variante .vmenu-flat: quando o conteúdo da aba é um único card, achata-o dentro do painel pra ficar um
   card só de verdade (Lead). Sem a variante, o conteúdo pode ter seus próprios cards de seção
   (Configurações), que aparecem como sub-cards dentro do painel. */
.vmenu-panel{display:flex;align-items:stretch;background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-lg);box-shadow:var(--shadow-sm);overflow:hidden}
.vmenu-nav{flex:none;width:216px;display:flex;flex-direction:column;gap:2px;padding:12px;border-right:1px solid var(--border);background:var(--surface-2)}
.vmenu-nav-item{display:flex;align-items:center;gap:10px;padding:10px 12px;border-radius:8px;background:transparent;border:none;color:var(--text-soft);cursor:pointer;font-size:13.5px;font-weight:500;text-align:left;width:100%;white-space:nowrap}
.vmenu-nav-item:hover{background:var(--surface);color:var(--text)}
.vmenu-nav-item.active{background:var(--accent-soft);color:var(--accent);font-weight:600}
.vmenu-nav-item>[data-lead-tab-badge],.vmenu-nav-item>[data-config-tab-badge],.vmenu-nav-item>[data-entity-tab-badge],.vmenu-nav-item>[data-ia-tab-badge],.vmenu-nav-item>[data-conx-tab-badge]{margin-left:auto}
/* Ponto de ATENÇÃO numa aba lateral: "tem algo aqui que precisa de você". Vive na família .vmenu porque o
   problema não é de uma tela só, é do modelo de navegação por abas, que por desenho mostra uma aba e esconde
   o estado das outras. Cor do danger, a mesma do alerta do sistema, senão a aba discorda do alerta.
   buildVmenuMore o clona para o seletor colapsado, senão ele desapareceria justamente no telefone. */
.vmenu-nav-dot{width:6px;height:6px;border-radius:50%;background:var(--danger);flex:none;margin-left:auto}
.vmenu-nav-dot+[data-conx-tab-badge],.vmenu-nav-dot+[data-lead-tab-badge]{margin-left:6px}
.emp-switch-opt>.vmenu-nav-dot{margin-left:auto}
.vmenu-body{flex:1;min-width:0;padding:18px}
/* Seletor de empresa estilo "perfil" (referência flowbite "Stacked layout with multiple navbars", o
   seletor com avatar + nome + linha secundária + setas cima/baixo). O gatilho mostra a empresa atual;
   clicar abre um dropdown ancorado com a lista de empresas. No topo de uma .vmenu-nav; reaproveitável por
   qualquer alternador de escopo do menu lateral. Avatar reusa .avatar/initials (componente único). */
.emp-switch{position:relative;margin-bottom:12px}
.emp-switch-trigger{display:flex;align-items:center;gap:10px;width:100%;padding:8px 10px;border:1px solid var(--border);border-radius:10px;background:var(--surface);color:var(--text);cursor:pointer;text-align:left;transition:border-color .12s,box-shadow .12s}
.emp-switch-trigger:hover{border-color:var(--border-strong)}
.emp-switch.open .emp-switch-trigger{border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-ring)}
.emp-switch-meta{flex:1;min-width:0;display:flex;flex-direction:column}
.emp-switch-name{font-size:13px;font-weight:600;color:var(--text);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.emp-switch-sub{font-size:11.5px;color:var(--text-faint);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.emp-switch-caret{flex:none;color:var(--text-faint);display:flex;transition:transform .12s}
.emp-switch.open .emp-switch-caret{color:var(--accent)}
/* Aberto, o menu cresce pra caber o conteúdo (min = largura do gatilho, teto = 340px/80vw) e transborda
   sobre o corpo à direita — assim os nomes completos aparecem mesmo com o gatilho estreito de 216px. */
.emp-switch-menu{position:absolute;top:calc(100% + 4px);left:0;z-index:60;min-width:100%;width:max-content;max-width:min(340px,80vw);background:var(--surface);border:1px solid var(--border);border-radius:10px;box-shadow:var(--shadow-md);padding:4px;max-height:300px;overflow-y:auto;overflow-x:hidden}
.emp-switch:not(.open) .emp-switch-menu{display:none}
.emp-switch-opt{display:flex;align-items:flex-start;gap:10px;width:100%;padding:7px 8px;border:none;background:transparent;border-radius:7px;color:var(--text);cursor:pointer;text-align:left}
.emp-switch-opt:hover{background:var(--surface-2)}
.emp-switch-opt.active{background:var(--accent-soft)}
.emp-switch-opt.active .emp-switch-name,.emp-switch-opt.active .emp-switch-sub{color:var(--accent)}
/* Dentro do dropdown os nomes aparecem por inteiro (quebram linha se preciso); o gatilho segue truncando. */
.emp-switch-menu .emp-switch-name,.emp-switch-menu .emp-switch-sub{white-space:normal;overflow:visible;text-overflow:clip}
/* no modo flat o próprio corpo dá o respiro (18px), e um card imediato do conteúdo perde borda/sombra E o
   padding próprio — assim conteúdo em card (Informações do Lead) e conteúdo "cru" (tabela do Financeiro da
   Entidade) ficam com o mesmo respiro, sem card dentro de card e sem colar na divisória. */
.vmenu-flat .vmenu-body>.card{border:0;box-shadow:none;background:transparent;border-radius:0;padding:0}
/* o painel ocupa a altura toda da área de conteúdo: min-height = espaço visível disponível, e ainda
   cresce quando o conteúdo é mais alto (a área de conteúdo é que rola). Escopo via :has, só nas páginas
   que de fato têm um .vmenu-panel — as demais mantêm o fluxo em bloco normal. */
.content:has(> .vmenu-panel){display:flex;flex-direction:column}
/* flex-shrink:0 é essencial: o painel tem overflow:hidden, então seu tamanho mínimo automático viraria 0
   e ele seria espremido até o viewport, cortando conteúdo alto. Sem encolher, ele cresce com o conteúdo e
   a própria área de conteúdo (#content, overflow-y:auto) rola. */
.content:has(> .vmenu-panel) .vmenu-panel{flex:1 0 auto}
/* .vmenu-more: seletor de abas estilo emp-switch (só a aba ativa aparece; clicar abre a lista). No DESKTOP
   não existe (a lista vertical aparece inteira na coluna lateral); o JS (buildVmenuMore) o injeta sempre,
   mas o CSS só o revela no mobile/tablet, onde os itens da lista são escondidos. */
.vmenu-more{display:none}
/* badge (contador) de uma aba dentro do dropdown do seletor lateral: flutua à direita, como nas outras abas. */
.vmenu-more .emp-switch-opt>.notif-count-badge{margin-left:auto;align-self:center;flex:none}
@media (max-width:720px){
  .vmenu-panel{flex-direction:column}
  /* A coluna lateral vira uma faixa: no tablet o seletor de empresa e o seletor de abas ficam na MESMA
     linha, divididos (cada um cresce pra metade; sozinho ocupa a linha toda). No celular empilham (≤480). */
  .vmenu-nav{width:100%;flex-direction:row;flex-wrap:wrap;gap:8px;align-items:flex-start;border-right:none;border-bottom:1px solid var(--border)}
  .vmenu-nav>.vmenu-nav-item{display:none}
  .vmenu-nav>.vmenu-more{display:block}
  /* .vmenu-more tem também a classe .emp-switch, então esta regra cobre o seletor de empresa E o de abas. */
  .vmenu-nav>.emp-switch{flex:1 1 calc(50% - 4px);min-width:0;margin-bottom:0}
}
@media (max-width:480px){
  .vmenu-nav>.emp-switch{flex:1 1 100%}
}
/* docs/components/progress-bars-panels.html adaptado ao design system do app: navegação em passos
   numerados (bolinha 01/02, check quando o passo fica pra trás, chevron conectando) dentro de um
   container com borda própria — clique livre entre os passos, não é wizard travado (todos os campos
   continuam no mesmo <form>, só a exibição alterna). */
.steps-nav{display:flex;align-items:center;padding:12px 16px;border:1px solid var(--border);border-radius:var(--radius-lg);background:var(--surface-2)}
.steps-nav-item{display:flex;align-items:center;gap:8px;background:none;border:none;padding:0;cursor:pointer;font:inherit}
.steps-nav-circle{width:26px;height:26px;border-radius:50%;flex:none;display:flex;align-items:center;justify-content:center;font-size:11px;font-weight:700;border:2px solid var(--border-strong);color:var(--text-faint);transition:.15s}
.steps-nav-label{font-size:12.5px;font-weight:600;color:var(--text-faint);white-space:nowrap}
.steps-nav-item.current .steps-nav-circle{border-color:var(--accent);color:var(--accent)}
.steps-nav-item.current .steps-nav-label{color:var(--accent)}
.steps-nav-item.done .steps-nav-circle{background:var(--accent);border-color:var(--accent);color:#fff}
.steps-nav-item.done .steps-nav-label{color:var(--text-soft)}
.steps-nav-connector{flex:1;display:flex;align-items:center;justify-content:center;color:var(--text-faint);margin:0 6px}
.subtask-due{width:132px}
/* Uma linha por subtarefa (check + título + metadados à direita), em vez da tabela de 2 linhas
   de antes — mesmo padrão visual de list-row usado no restante do app (borda, radius, hover). */
.subtask-new-row{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.subtask-new-row .input{flex:1;min-width:160px}
.subtask-list{display:flex;flex-direction:column;gap:8px}
.subtask-row{display:flex;align-items:center;flex-wrap:wrap;gap:10px;border:1px solid var(--border);border-radius:var(--radius-lg);padding:8px 12px;background:var(--surface);transition:.15s}
.subtask-row:hover{box-shadow:var(--shadow-sm);border-color:var(--border-strong)}
/* Linha sendo arrastada (ver wireKanbanSubtaskDragReorder) vira um "buraco" limpo em vez de só ficar
   translúcida com o conteúdo por baixo — mesmo padrão de contorno pontilhado já usado em dropzone/hint
   do app (.file-dropzone, .kanban-drag-hint), só que aqui marcando de onde a subtarefa saiu. O clone
   que segue o mouse é outro elemento (.subtask-drag-ghost, via setDragImage), então o conteúdo original
   pode sumir daqui sem perder a referência visual do que está sendo movido. O handle (:not abaixo) fica
   de fora: ele É o elemento draggable de verdade (fonte nativa do drag), e escondê-lo no meio do próprio
   dragstart faz o Chrome cancelar o drag na hora (dragend dispara ~3ms depois, sem dragover/drop nenhum
   — bug real medido, não só suposição) por achar que a fonte do arrasto sumiu da tela. */
.subtask-row.dragging{border:3px dashed var(--border-strong);background:var(--surface-2);box-shadow:none}
.subtask-row.dragging>*:not(.subtask-drag-handle){visibility:hidden}
/* Clone que segue o cursor (setDragImage, ver wireKanbanSubtaskDragReorder) — mesmo espírito do "Mover N
   conversas" do Gmail: um pill compacto com ícone + título, longe da lista real, só pra dar feedback de
   arrasto sem repetir a linha inteira (metadados, avatar, botões) grudada no mouse. */
.subtask-drag-ghost{position:fixed;top:-1000px;left:-1000px;display:inline-flex;align-items:center;gap:8px;padding:8px 14px;border-radius:999px;background:var(--surface);border:1px solid var(--border-strong);box-shadow:var(--shadow-lg);font-size:13px;font-weight:600;color:var(--text);white-space:nowrap}
.subtask-drag-ghost svg{flex:none;color:var(--accent)}
/* Handle de arrastar no estilo Gmail (reordenar labels): some por padrão, só aparece (e some espaço)
   quando o mouse passa em cima da linha. Só a opacidade é animada — width/margin mudam instantâneos
   junto do :hover, nunca em transição — porque um mousedown+drag em sequência rápida (hover na linha e
   já arrastar o handle) podia cair fora do alvo enquanto ele ainda estava no meio da animação de width
   0→14px, fazendo o drag simplesmente não iniciar (bug real reportado, não só do automation de teste).
   Reaproveita .drag-handle (cor/cursor grab) já usado nas outras listas de arrastar do app (Menu,
   colunas de Lançamentos), só adiciona o comportamento de hover-reveal, que é específico daqui (ver
   Diretriz de componentes visuais). */
.subtask-drag-handle{width:0;opacity:0;overflow:hidden;transition:opacity .15s ease}
.subtask-row:hover .subtask-drag-handle{width:14px;opacity:1;margin-right:2px}
.subtask-row-title{flex:1;min-width:0;font-size:13.5px;font-weight:500;display:flex;align-items:center;gap:2px}
.subtask-row-title>span:first-child{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.subtask-row-title.is-done{color:var(--text-faint)}
.subtask-row-title.is-done>span:first-child{text-decoration:line-through}
.subtask-row-meta{display:flex;align-items:center;gap:10px;flex:none;color:var(--text-faint);font-size:12px}
.subtask-row-due{display:flex;align-items:center;gap:4px;white-space:nowrap}
.subtask-row-due.is-overdue{color:var(--danger);font-weight:600}
.notif-bell{position:relative}
.notif-badge{position:absolute;top:-3px;right:-3px;background:var(--danger);color:#fff;font-size:9.5px;font-weight:700;border-radius:20px;min-width:14px;height:14px;display:flex;align-items:center;justify-content:center;padding:0 3px}
.status-dot{position:absolute;top:1px;right:1px;width:9px;height:9px;border-radius:50%;background:var(--success);border:2px solid var(--surface)}
.status-dot.offline{background:var(--danger)}
.notif-panel{position:absolute;top:44px;right:0;width:320px;max-height:420px;overflow-y:auto;background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-lg);box-shadow:var(--shadow-md);z-index:40}
.notif-item{padding:7px 12px;border-bottom:1px solid var(--border);cursor:pointer;transition:.1s}
.notif-item:not(.unread){background:var(--bg)}
.notif-item:not(.unread) .notif-item-title{color:var(--text-soft);font-weight:500}
.notif-item:hover{background:var(--surface-2)}
.notif-item.unread{background:var(--surface)}
.notif-item:last-child{border-bottom:none}
.notif-item-desc{font-size:10px}
.notif-item-resolved,.notif-page-item.notif-item-resolved{cursor:default}
.notif-item-title .badge{font-size:9px;border-radius:4px;text-transform:uppercase}
.notif-panel-foot{padding:8px}
.notif-unread-dot{display:inline-block;width:7px;height:7px;border-radius:50%;background:var(--danger);margin-right:5px;vertical-align:middle;flex:none}
.notif-see-more-btn{border:none;background:transparent;text-align:center;justify-content:center}
.notif-see-more-btn:hover{background:var(--surface-2)}
/* Popup de notificação nova, canto inferior esquerdo — reaproveita o cartão .notif-item (mesma
   marcação/cores do painel do sino), só troca o container flutuante. */
.notif-toast-wrap{position:fixed;left:16px;bottom:16px;z-index:300;display:flex;flex-direction:column-reverse;gap:8px;width:320px;max-width:calc(100vw - 32px)}
.notif-toast{position:relative;background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-lg);box-shadow:var(--shadow-lg);overflow:hidden;animation:fade .2s ease}
.notif-toast .notif-item{border-bottom:none}
.notif-toast-close{position:absolute;top:6px;right:6px}
/* inline-flex (não inline-block): quando o menu está numa barra de botões que estica os filhos (ex.
   #page-head-actions), o gatilho .btn .btn-icon (sem altura fixa) estica junto e fica do mesmo tamanho
   dos .btn ao lado. Em linha de tabela o gatilho é .icon-btn (altura fixa 30px), então não estica. */
.actions-dropdown{position:relative;display:inline-flex}
.actions-dropdown-menu{position:fixed;min-width:180px;background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-lg);box-shadow:var(--shadow-md);z-index:150;padding:4px;display:flex;flex-direction:column;gap:1px}
.actions-dropdown-item{display:flex;align-items:center;gap:8px;padding:8px 10px;border-radius:7px;font-size:13px;cursor:pointer;background:none;border:none;text-align:left;width:100%;color:var(--text)}
.actions-dropdown-item:hover{background:var(--surface-2)}
/* Variante compacta só do menu de inserir nó no meio de uma conexão do Flow (lista mais longa de
   tipos de nó que os outros usos de .actions-dropdown-menu no app) — modificador em cima das mesmas
   classes/marcação compartilhadas, não um componente paralelo (ver Diretriz de componentes visuais). */
.actions-dropdown-menu.flow-insert-menu{padding:1px;gap:0}
.actions-dropdown-menu.flow-insert-menu .actions-dropdown-item{padding:3px 6px;gap:5px;font-size:12px}
.actions-dropdown-item.danger{color:var(--danger)}
.actions-dropdown-item:disabled{opacity:.4;cursor:default;pointer-events:none}
tr.row-locked-pending{color:var(--text-faint)}
.actions-dropdown-header{display:flex;align-items:center;gap:8px;padding:6px 10px 9px;margin-bottom:3px;font-size:12.5px;font-weight:700;color:var(--text-faint);border-bottom:1px solid var(--border);pointer-events:none}
/* Divisória entre grupos de itens do dropdown de ações (ver atendimentoBannerMenuItemsHtml). */
.actions-dropdown-divider{height:1px;background:var(--border);margin:5px 8px}
.notif-page-item{padding:9px 14px;border:1px solid var(--border);border-radius:10px;cursor:pointer;transition:.1s}
.notif-page-item:not(.unread){background:var(--bg)}
.notif-page-item:not(.unread) .notif-item-title{color:var(--text-soft);font-weight:500}
.notif-page-item:hover{background:var(--surface-2)}
.notif-page-item.unread{background:var(--surface)}
.dt-toolbar .select{width:auto;padding:5px 8px;font-size:12.5px}
.dt-pagebtn{width:26px;height:26px;border-radius:6px;border:1px solid var(--border-strong);background:var(--surface);color:var(--text-soft);display:inline-flex;align-items:center;justify-content:center}
.dt-pagebtn:hover:not(:disabled){background:var(--surface-2);color:var(--text)}
.dt-pagebtn:disabled{opacity:.4;cursor:not-allowed}

/* app shell */
#app{display:flex;height:100%;width:100%}
/* Escala global em resoluções muito grandes: como todo o layout é em px, num monitor grande de alta
   resolução as fontes e elementos ficam minúsculos. zoom na raiz escala fontes E elementos juntos, sem
   overflow horizontal (por isso #app é 100%, não 100vw — vw ignora o zoom e estouraria). As media queries
   olham o viewport REAL, não o valor com zoom, então os breakpoints do menu (abaixo) não são afetados. */
@media (min-width:2100px){ html{zoom:1.15} }
@media (min-width:2560px){ html{zoom:1.30} }
@media (min-width:3000px){ html{zoom:1.45} }
@media (min-width:3400px){ html{zoom:1.60} }
.sidebar{width:246px;flex:none;background:var(--surface);border-right:1px solid var(--border);display:flex;flex-direction:column;height:100%}
.brand{display:flex;align-items:center;gap:10px;padding:18px 16px;border-bottom:1px solid var(--border)}
.brand-mark{width:32px;height:32px;border-radius:9px;overflow:hidden;flex:none;display:flex;align-items:center;justify-content:center}
.brand-mark img{width:100%;height:100%;display:block}
.brand-name{font-weight:700;font-size:15px;line-height:1.2;font-family:var(--font-brand);letter-spacing:.2px}
.brand-sub{font-size:11px;color:var(--text-faint)}
.nav{flex:1;overflow-y:auto;padding:10px}
.nav-group{margin-bottom:2px}
.nav-item{display:flex;align-items:center;gap:10px;padding:9px 11px;border-radius:8px;color:var(--text-soft);font-size:13px;font-weight:600;cursor:pointer;position:relative}
.nav-item:hover{background:var(--surface-2);color:var(--text)}
.nav-item.active{background:var(--accent-soft);color:var(--accent)}
.nav-item .chev{margin-left:auto;transition:.15s}
.nav-item .chev.open{transform:rotate(90deg)}
.nav-sub{padding-left:30px;display:none}
.nav-sub.open{display:block}
.nav-sub .nav-item{padding:7px 11px;font-size:12.5px;font-weight:500}
.nav-parent-label{font-size:10.5px;text-transform:uppercase;letter-spacing:.08em;color:var(--text-faint);padding:14px 11px 6px}
.sidebar-foot{padding:12px;border-top:1px solid var(--border)}
.user-chip{display:flex;align-items:center;gap:9px;padding:8px;border-radius:9px}
.user-chip:hover{background:var(--surface-2)}
.avatar{width:30px;height:30px;border-radius:50%;background:var(--accent-soft);color:var(--accent);display:flex;align-items:center;justify-content:center;font-weight:700;font-size:12px;flex:none}
.color-swatch-field{display:flex;align-items:center;gap:12px;background:var(--surface-2);border:1px solid var(--border);border-radius:10px;padding:10px 12px}
.color-swatch-input{-webkit-appearance:none;appearance:none;width:42px;height:42px;flex:none;border:none;padding:0;cursor:pointer;background:none;border-radius:50%;box-shadow:0 0 0 2px var(--border),0 1px 4px rgba(0,0,0,.3);transition:box-shadow .15s,transform .15s}
.color-swatch-input:hover{box-shadow:0 0 0 2px var(--accent),0 2px 8px rgba(0,0,0,.35);transform:scale(1.05)}
.color-swatch-input::-webkit-color-swatch-wrapper{padding:0;border-radius:50%}
/* Avatar sem foto vira o próprio trigger do color picker: input type=color transparente cobrindo
   o círculo inteiro, sem alterar nada do visual do avatar — só um anel no hover avisa que é clicável. */
.avatar-color-wrap{position:relative;flex:none;border-radius:50%;transition:box-shadow .15s}
.avatar-color-wrap:has(.avatar-color-input):hover{box-shadow:0 0 0 2px var(--accent)}
.avatar-color-input{position:absolute;inset:0;width:100%;height:100%;opacity:0;border:none;padding:0;margin:0;cursor:pointer;-webkit-appearance:none;appearance:none}
.color-swatch-input::-webkit-color-swatch{border:none;border-radius:50%}
.color-swatch-input::-moz-color-swatch{border:none;border-radius:50%}
/* Versão compacta do swatch (ex: formulário de setor) — mesmo componente, com a MESMA altura de um .input
   (37px, box-sizing border-box) pra alinhar com o campo ao lado; chip menor, centralizado. */
.color-swatch-sm{gap:9px;padding:0 11px;height:37px}
.color-swatch-sm .color-swatch-input{width:24px;height:24px}

/* menu compacto: sidebar vira coluna só de ícones. Grupos com submenu (Tarefas/Despesas/etc) não
   expandem mais inline nesse modo — viram um dropdown flutuante posicionado via getBoundingClientRect,
   porque um <div> dentro de .nav (que tem overflow-y:auto) fica com overflow-x clipado e um flyout
   absoluto ali dentro nunca apareceria. Ver renderNav() e wireCompactNavGroups(). */
.sidebar.compact{width:68px}
.sidebar.compact .brand{padding:18px 8px;justify-content:center}
.sidebar.compact .brand-text{display:none}
.sidebar.compact .nav-item{justify-content:center;padding:9px 6px}
.sidebar.compact .nav-item:hover{box-shadow:var(--shadow-sm)}
.sidebar.compact .nav-item>span{display:none}
.sidebar.compact .nav-item>span.notif-count-badge{display:flex}
.sidebar.compact .nav-item>span.nav-alert-icon{display:flex}
.sidebar.compact .nav-item>span.notif-unread-dot{display:block}
/* No menu compacto, badge/alerta/bolinha ficam sobre o canto superior direito do ÍCONE (não na borda
   da coluna) — "sobrepondo o final do ícone". Ícone é 22px centralizado, então o canto fica em
   (centro + 11px, centro - 11px); transform centra o overlay exatamente ali, sobrepondo. */
.sidebar.compact .nav-item>.notif-count-badge,
.sidebar.compact .nav-item>.nav-alert-icon,
.sidebar.compact .nav-item>.notif-unread-dot{position:absolute;left:calc(50% + 11px);top:calc(50% - 11px);right:auto;bottom:auto;margin:0;transform:translate(-50%,-50%)}
.sidebar.compact .nav-parent-label{display:none}
.sidebar.compact .user-chip{justify-content:center;padding:8px 4px}
.sidebar.compact .user-chip>.flex-1,.sidebar.compact .user-chip>svg{display:none}
/* Preview do menu compacto = uma EXTENSÃO do próprio ícone, não um tooltip separado flutuando do lado.
   Encosta sem vão (left = rect.right exato, ver wireCompactNavHoverTips) e com o canto esquerdo reto (só
   o direito arredondado) pra colar visualmente na quina do ícone — que por sua vez perde o arredondado do
   lado direito enquanto o preview está aberto (.nav-compact-tip-source), assim os dois juntos formam UM
   pill só, não dois elementos encostados. Carrega a MESMA box-shadow do ícone em hover (.sidebar.compact
   .nav-item:hover) pra sombra correr contínua do ícone até o fim do rótulo, em vez de parar na quina do
   ícone — como --shadow-sm não tem deslocamento horizontal, as duas metades emendam sem costura embaixo.
   Não repete o ícone (só o rótulo e eventuais badges) porque o ícone já está visível no botão de origem.
   Reaproveita as cores/estado de .nav-item/.nav-item.active — só sobrescreve o que é exclusivo de flutuar. */
.nav-hover-tip{position:fixed;display:none;white-space:nowrap;z-index:140;pointer-events:none;border-radius:0 8px 8px 0;padding-left:8px;box-shadow:var(--shadow-sm)}
.nav-hover-tip.nav-item:not(.active){background:var(--surface-2);color:var(--text)}
.nav-item.nav-compact-tip-source{border-top-right-radius:0;border-bottom-right-radius:0}

.main{flex:1;display:flex;flex-direction:column;min-width:0;height:100%}
.topbar{height:58px;flex:none;border-bottom:1px solid var(--border);display:flex;align-items:center;gap:10px;justify-content:space-between;padding:0 22px;background:var(--surface)}
.topbar.compact{padding-left:0}
/* Faixa fina embaixo do header: mostra que os dados do módulo estão sendo reconsultados em segundo
   plano (ver refreshDataOnModuleChange) — some sozinha quando o fetch termina e a tela é redesenhada. */
.topbar-loading-bar{height:2px;flex:none;position:relative;overflow:hidden}
.topbar-loading-bar span{position:absolute;top:0;bottom:0;left:-35%;width:35%;background:var(--accent);border-radius:2px;opacity:0}
.topbar-loading-bar.active span{opacity:1;animation:topbarLoadingSlide 1.1s ease-in-out infinite}
@keyframes topbarLoadingSlide{0%{left:-35%}100%{left:135%}}
.crumb-trail{display:flex;align-items:center;font-size:12.5px;overflow:hidden;min-width:0}
.crumb-pill{padding:5px 10px;border-radius:8px;background:var(--surface-2);border:1px solid var(--border);color:var(--text-soft);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:220px}
.crumb-pill[data-crumb-nav]{cursor:pointer;transition:.12s}
.crumb-pill[data-crumb-nav]:hover{background:var(--surface);border-color:var(--border-strong)}
.crumb-pill.active{background:var(--accent-soft);border-color:var(--accent);color:var(--accent);font-weight:700}
.crumb-divider{width:14px;height:1px;background:var(--border-strong);flex:none}
.content{flex:1;overflow-y:auto;padding:26px 30px 60px}
.content.atd-flush{padding:0;overflow:hidden;display:flex}
.preview-bar{flex:none;background:var(--warning-soft);color:var(--warning);font-size:12.5px;font-weight:600;padding:8px 22px;display:flex;align-items:center;gap:8px;border-bottom:1px solid var(--border)}
.preview-bar .btn{margin-left:auto;padding:4px 10px;font-size:12px}
.drag-row{display:flex;align-items:center;gap:8px;padding:8px 8px;border:1px solid var(--border);border-radius:8px;margin-bottom:6px;background:var(--surface)}
.drag-row.dragging{opacity:.4}
[data-val-row].dragging{opacity:.4}
.drag-handle{color:var(--text-faint);display:flex;cursor:grab;flex:none;user-select:none;-webkit-user-select:none}
.drag-handle:active{cursor:grabbing}
/* Sem isso, o ícone SVG dentro do handle recebe o mousedown (não o <span> pai) — o navegador não acha
   ancestral arrastável a tempo e cai pra seleção de texto nativa, que "pisca" ao arrastar o mouse sobre
   a linha e nunca dispara dragstart. pointer-events:none garante que o handle inteiro seja sempre o alvo. */
.drag-handle svg{pointer-events:none}
.page-head{display:flex;align-items:flex-start;justify-content:space-between;gap:16px;margin-bottom:20px;flex-wrap:wrap}
.page-title{font-size:21px}
.page-desc{color:var(--text-soft);font-size:13px;margin-top:3px}
button.menu-btn{display:none;flex:none}
.nav-scrim{position:fixed;inset:0;background:rgba(15,17,20,.44);z-index:85}
/* Faixa 901–1199px: o menu vira um rail compacto FIXO (68px) que empurra o conteúdo só 68px; expandir
   abre o menu completo SOBRE o conteúdo (overlay flutuante com scrim), sem recomprimir os módulos.
   Acima de 1200px vale a preferência do usuário (rail em fluxo normal); em até 900px vale o menu mobile
   (hambúrguer) já existente. effectiveSidebarCompact()/navOverlayBand() decidem qual classe a sidebar leva. */
@media (min-width:901px) and (max-width:1199px){
  .sidebar{position:fixed;top:0;left:0;z-index:90;height:100%;box-shadow:var(--shadow-sm)}
  .sidebar:not(.compact){box-shadow:var(--shadow-lg)}
  .main{margin-left:68px}
}
@media (max-width:900px){
  button.menu-btn{display:inline-flex}
  #toggle-compact-btn,#expand-menu-btn{display:none}
  .sidebar{position:fixed;top:0;left:0;z-index:90;transform:translateX(-100%);transition:transform .2s ease}
  .sidebar.open{transform:translateX(0);box-shadow:var(--shadow-lg)}
  .topbar{padding:0 14px}
  .content{padding:18px 16px 48px}
  .page-title{font-size:19px}
  .qs{right:14px;bottom:14px}
}
@media (min-width:901px){
  .nav-scrim{display:none}
}

/* ============================= ATENDIMENTO (inbox de conversas) ============================= */
.atd-shell{display:flex;height:100%;width:100%;min-height:0;position:relative}
.atd-list{width:300px;flex:none;border-right:1px solid var(--border);display:flex;flex-direction:column;overflow:hidden}
.atd-list .notif-count-badge { min-width: 14px; height: 14px; padding: 2px 2px; margin-top: 3px; }
.atd-list-search{flex:none;padding:12px;border-bottom:1px solid var(--border)}
/* Seletor de canais (item 3): mesmo recuo lateral da busca; o próprio picker reaproveita as classes
   .admin-picker* (mesmo visual do seletor de administradores). */
.atd-channel-selector{flex:none;padding:8px 12px 10px;border-bottom:1px solid var(--border);user-select:none;-webkit-user-select:none}
.atd-channel-exibindo{margin-top:6px}
/* Lista de conversas e abas Fila/Meus/Todos não são texto pra copiar — bloqueia a seleção pra o clique
   (abrir conversa / trocar de aba) não virar "arrastar e selecionar" sem querer. O input de busca
   (.atd-list-search, fora daqui) continua selecionável normalmente. */
.atd-list-items{flex:1;overflow-y:auto;user-select:none;-webkit-user-select:none}
.atd-list-filters{user-select:none;-webkit-user-select:none}
/* Legenda da seção logo abaixo das abas (ATD_SCOPE_CAPTION) — faixa discreta na cor de destaque, maiúsculas.
   Fica no topo do scroll da lista, acompanha o conteúdo (não é sticky de propósito, é rótulo do escopo). */
.text-center{text-align:center}
/* Fixada logo abaixo das abas (sticky no topo da lista rolável), na cor de destaque cheia, centralizada —
   não rola junto com os leads (item CONVERSAS 17). */
.atd-scope-caption{position:sticky;top:0;z-index:2;font-size:11px;font-weight:700;letter-spacing:.6px;text-transform:uppercase;color:var(--accent-contrast);background:var(--accent);padding:6px 12px;border-bottom:1px solid var(--border)}
/* Rodapé de fila (atendimentoFilaWaitStats) — abaixo da lista, separado por linha, nudge de "tem gente esperando". */
.atd-fila-footer{padding:10px 12px;border-top:1px solid var(--border);line-height:1.4}
.atd-item{display:flex;align-items:center;gap:10px;padding:10px 12px;cursor:pointer;border-bottom:1px solid var(--border);border-left:3px solid transparent}
.atd-item-bot{border-left-color:var(--accent);background:color-mix(in srgb, var(--accent) 6%, transparent)}
.atd-item:hover{background:var(--surface-2)}
.atd-item.active{background:var(--accent-soft)}
/* Conversa não lida na coluna esquerda em fundo branco pra saltar do fundo cinza da lista (CONVERSAS 9);
   hover e ativa (mais específicas) continuam vencendo. */
.atd-item-unread{background:var(--surface)}
/* Badges dentro do item da lista em tamanho reduzido (CONVERSAS 12). */
.atd-item .badge{font-size:10px;padding:2px 7px;gap:3px}
.atd-item .avatar{width:38px;height:38px;font-size:14px;flex:none;overflow:hidden}
.atd-chat-header .avatar{width:36px;height:36px;font-size:13px;overflow:hidden;cursor:pointer}
.atd-info .avatar{width:64px;height:64px;font-size:22px;overflow:hidden}
/* Bolha de mensagem (messageBubbleHtml) — só a cor de fundo (bubbleBg) e o alinhamento mine/theirs
   continuam inline (genuinamente dinâmicos por mensagem); formato/espaçamento é sempre o mesmo. */
.atd-msg-avatar{width:26px;height:26px;font-size:10px;flex:none;overflow:hidden}
/* Visualizador de protocolos (aba Conversas da ficha do Lead): timeline somente-leitura, sem o menu "..." de
   ação por mensagem (não é o inbox, só visualização). As bolhas e a mídia clicável continuam iguais. */
.conversa-readonly [data-actions-toggle^="msg-"]{display:none}
/* Variante "sem avatar": ícone (WhatsApp do "Enviado pelo celular") solto, sem o círculo de fundo do
   .avatar, só centralizado no mesmo espaço de 26px. Ver messageBubbleHtml. */
.atd-msg-avatar-plain{display:flex;align-items:center;justify-content:center}
.atd-msg-bubble{border-radius:10px;padding:8px 10px;border:1px solid var(--border);min-width:0;position:relative}
/* Chip de reação sobreposto à borda da bolha (estilo WhatsApp): fica no canto inferior do lado OPOSTO à
   hora, meio pra fora da bolha, com o fundo na cor do chat pra parecer recortado sobre a borda. */
.atd-msg-reaction-chip{position:absolute;bottom:-10px;display:none;gap:3px;flex-wrap:wrap;z-index:1}
.atd-msg-reaction-chip.side-left{left:8px}
.atd-msg-reaction-chip.side-right{right:8px}
.atd-msg-reaction-chip .atd-reaction-pill{background:var(--bg);border:1px solid var(--border);border-radius:11px;padding:0 5px;font-size:12px;line-height:19px;box-shadow:0 1px 2px rgba(0,0,0,.08)}
.atd-msg-content{white-space:pre-wrap;margin:0}
.atd-msg-content a{color:var(--accent);text-decoration:underline;word-break:break-all}
/* Bloco de citação de uma resposta (swipe-reply, item CONVERSAS 1): barrinha à esquerda + quem + prévia de
   uma linha, dentro da bolha, acima do texto (padrão WhatsApp). Clicar rola até a mensagem original. */
.atd-msg-quote{display:flex;flex-direction:column;gap:1px;border-left:3px solid var(--accent);background:color-mix(in srgb,var(--accent) 8%,transparent);border-radius:4px;padding:3px 8px;margin-bottom:4px;cursor:pointer;min-width:0;max-width:100%}
.atd-msg-quote:hover{background:color-mix(in srgb,var(--accent) 15%,transparent)}
.atd-msg-quote-who{font-size:.72rem;font-weight:600;color:var(--accent);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.atd-msg-quote-text{font-size:.78rem;color:var(--text-soft,#8a94a6);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.atd-msg-quote-text.muted{font-style:italic}
/* Chip "respondendo a ..." (swipe-reply de saída, item CONVERSAS 1). Mesmo vocabulário visual da citação da
   bolha (barrinha + quem + prévia). Agora é uma FAIXA flush dentro da caixa do composer (Fatia 2), não mais
   um cartão solto — encosta nas bordas e separa do textarea por uma linha, pra caixa parecer uma peça só. */
.atd-reply-chip{display:flex;align-items:center;gap:8px;padding:7px 10px 7px 12px;background:color-mix(in srgb,var(--accent) 7%,var(--surface));border-bottom:1px solid var(--border)}
.atd-reply-chip-bar{width:3px;align-self:stretch;border-radius:3px;background:var(--accent);flex:none}
.atd-reply-chip-body{flex:1;min-width:0}
.atd-reply-chip-who{font-size:.72rem;font-weight:600;color:var(--accent);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.atd-reply-chip-text{font-size:.8rem;color:var(--text-soft,#8a94a6);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.atd-reply-chip-x{flex:none}
/* ===== Composer de Conversas — shell estrutural (Fatia 2) =====
   Caixa única (rail de modo + faixa de citação + textarea + barra de ação) com anel de foco, no lugar dos
   elementos soltos de antes. Reaproveita os tokens do projeto (accent terracota; nota interna = --warning
   âmbar). Só markup/CSS: os controles e comportamentos são os mesmos (resposta pronta, Sugerir IA, enviar,
   encerrar), só reorganizados. O palette "/" e o emoji/anexo ficam pra Fatia 3+. */
.atd-composer{border:1.5px solid var(--border-strong);border-radius:12px;background:var(--surface);overflow:hidden;transition:border-color .15s,box-shadow .15s}
.atd-composer.focus{border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-ring)}
.atd-composer.internal{border-color:color-mix(in srgb,var(--warning) 55%,var(--border-strong))}
.atd-composer.internal.focus{border:1.5px dashed var(--border-strong);border-color:var(--warning);box-shadow:0 0 0 3px var(--warning-soft)}
.atd-c-rail{display:flex;align-items:center;gap:10px;padding:7px 10px 7px 12px;border-bottom:1px solid var(--border);background:var(--surface-2);min-height:40px;flex-wrap:wrap}
/* Controle segmentado (.seg/.seg-btn): escolha entre 2-4 opções que trocam o QUE a área mostra ou faz, sem
   sair dela — o modo do composer (Responder | Nota interna) e o filtro da grade de variantes (Todas |
   Materializadas | Bloqueadas). Nasceu como .atd-c-seg no composer e virou genérico no primeiro segundo uso,
   pra não ter dois desenhos concorrentes de controle segmentado. A regra por data-mode continua valendo só
   onde esse atributo existe, que é o composer. */
.seg{display:inline-flex;background:var(--bg);border:1px solid var(--border);border-radius:8px;padding:2px;gap:2px}
.seg-btn{border:none;background:none;font-size:12px;font-weight:600;color:var(--text-soft);padding:4px 10px;border-radius:6px;display:inline-flex;align-items:center;gap:5px;cursor:pointer;transition:.13s;font-family:inherit}
.seg-btn.on{background:var(--surface);color:var(--accent);box-shadow:0 1px 2px rgba(0,0,0,.1);border: 1px solid var(--accent)}
.seg-btn.on[data-mode="note"]{color:var(--warning);border: 1px solid var(--warning)}
.seg-btn:disabled{opacity:.4;cursor:not-allowed}
.atd-c-rail-note{display:inline-flex;align-items:center;gap:6px;font-size:11.5px;color:var(--text-faint);min-width:0}
.atd-c-rail-note svg{flex:none}
.atd-composer.internal .atd-c-rail-note{color:var(--warning)}
/* Atalho "Assumir e responder" no trilho do composer (ver renderLeadComposerMode) — link discreto com a cor de acento. */
.atd-c-rail-link{display:inline-flex;align-items:center;gap:4px;font:inherit;color:var(--accent);background:none;border:none;padding:0;cursor:pointer;font-weight:600}
.atd-c-rail-link:hover{text-decoration:underline}
/* Nota interna: o texto digitado sai na mesma cor âmbar do aviso "Só a equipe vê..." (CONVERSAS 6). */
.atd-composer.internal .atd-c-ta{color:var(--warning)}
.atd-composer.internal .atd-c-ta::placeholder{color:color-mix(in srgb,var(--warning) 55%,transparent)}
.atd-c-rail-hint{margin-left:auto;display:inline-flex;align-items:center;gap:5px;font-size:11.5px;color:var(--text-faint);white-space:nowrap}
/* Popover de emoji (fidelidade ao protótipo) — grade compacta ancorada acima da barra de ação. */
.atd-c-emoji-pop{position:absolute;bottom:52px;left:10px;z-index:50;display:none;grid-template-columns:repeat(7,1fr);gap:2px;padding:8px;background:var(--surface);border:1px solid var(--border-strong);border-radius:11px;box-shadow:var(--shadow-md)}
.atd-c-emoji-pop.show{display:grid;animation:atdPalPop .12s ease}
.atd-c-emoji-pop button{border:none;background:none;font-size:19px;line-height:1;padding:4px;border-radius:7px;cursor:pointer}
.atd-c-emoji-pop button:hover{background:var(--surface-2)}
/* Menu do split-send (▾): Enviar depois / Enviar e encerrar juntos, como no protótipo. */
.atd-c-send-menu{position:absolute;bottom:52px;right:8px;z-index:50;display:none;min-width:220px;padding:5px;background:var(--surface);border:1px solid var(--border-strong);border-radius:11px;box-shadow:var(--shadow-md)}
.atd-c-send-menu.show{display:block;animation:atdPalPop .12s ease}
.atd-c-send-menu button{display:flex;align-items:flex-start;gap:9px;width:100%;border:none;background:none;color:var(--text);text-align:left;padding:8px 9px;border-radius:8px;cursor:pointer}
.atd-c-send-menu button:hover{background:var(--surface-2)}
.atd-c-send-menu button .mi-ic{color:var(--text-soft);display:inline-flex;margin-top:1px;flex:none}
.atd-c-send-menu button b{font-size:13px;font-weight:600;display:block}
.atd-c-send-menu button small{font-size:11px;color:var(--text-faint)}
/* Picker de arquivo (Fatia B do anexo): lista os arquivos JÁ HOSPEDADOS do lead (aba Arquivos + mídia
   recebida no chat) pra enviar por REFERÊNCIA, sem novo upload. Componente novo por PROPÓSITO (escolher-
   pra-enviar, não gerenciar), mas reusa os átomos do palette (.atd-pal-item/.atd-pal-ic/.atd-pal-t/-s) e o
   ícone-por-tipo (entityFileTypeMeta) — nada de .file-card clonado. */
/* Lista do clipe 📎 reaproveita o INVÓLUCRO do palette de comandos (.atd-pal + head/list/foot/group/item),
   pra ter o mesmo formato e visual (pedido do usuário). Único acréscimo: o campo de busca no cabeçalho, que
   o palette não tem (lá a busca vem do "/" no composer). */
.atd-c-file-q{flex:1;min-width:0;border:1px solid var(--border);background:var(--surface-2);border-radius:7px;padding:4px 9px;color:var(--text);font-size:12.5px;font-family:inherit;outline:none}
.atd-c-file-q:focus{border-color:var(--accent)}
/* Arrastar-pra-enviar (Fatia D do anexo): card de arquivo/botão de arquivo do chat vira "pegável" só quando
   há um composer pra receber (leadFilesCfg/loadLeadChatFiles gatam pela presença da caixa). O próprio composer
   acende .atd-c-dropok enquanto um arquivo hospedado paira sobre ele — reforça que soltar ali reenvia por
   referência, sem novo upload. */
.fb-draggable{cursor:grab}
.fb-draggable:active{cursor:grabbing}
.fb-dragging{opacity:.5}
/* Zona de soltar (Fatia E2): a CONVERSA INTEIRA (#lead-conversas-root) recebe o arquivo arrastado, não só o
   composer. O overlay tem pointer-events:none pra nunca roubar o dragover dos filhos (evita flicker). */
.lead-conversas-root{position:relative}
/* Translúcida + blur suave no chat por trás (CONVERSAS): o overlay deixa o conteúdo aparecer suavemente
   enquanto o backdrop-filter borra o que está atrás dele. */
.lead-conversas-dropzone{position:absolute;inset:0;z-index:60;display:none;place-items:center;pointer-events:none;border-radius:12px;background:color-mix(in srgb,var(--accent) 12%,transparent);backdrop-filter:blur(3px);-webkit-backdrop-filter:blur(3px);outline:2px dashed var(--accent);outline-offset:-8px}
/* No Atendimento a zona de soltar ocupa TODA a coluna central (CONVERSAS 2.3): cancela o padding:16px do
   .atd-chat-body com inset negativo, chegando às bordas e ao topo da coluna sem margem, e sem cantos
   arredondados (full-bleed). Na aba Conversas do Lead Detail segue no inset:0 do card. */
.atd-chat-body .lead-conversas-dropzone{inset:-16px;border-radius:0;outline-offset:-2px}
.lead-conversas-root.drop-active .lead-conversas-dropzone{display:grid}
/* Seta do "solte para enviar" sobe e desce suavemente enquanto se arrasta (CONVERSAS 2.1); a bandeja
   fica parada, só o corpo da seta (.lcd-arrow-up) se move. */
.lcd-arrow{color:var(--accent)}
.lcd-arrow .lcd-arrow-up{animation:lcdArrowBob 1.15s ease-in-out infinite}
@keyframes lcdArrowBob{0%,100%{transform:translateY(1.5px)}50%{transform:translateY(-2.5px)}}
@media (prefers-reduced-motion:reduce){.lcd-arrow .lcd-arrow-up{animation:none}}
/* Clone do arquivo arrastado, abaixo do texto (CONVERSAS 2.2): moldura de superfície levemente inclinada,
   "segurando" o próprio elemento (card/botão de arquivo) que está sendo arrastado. */
.lcd-preview{margin-top:6px;pointer-events:none;max-width:min(300px,78vw);background:var(--surface);border:1px solid var(--border);border-radius:10px;box-shadow:var(--shadow-md);padding:3px 7px;transform:rotate(-1.4deg)}
.lcd-preview:empty{display:none}
.lcd-preview>*{cursor:default;width:100%}
.lcd-inner{display:flex;flex-direction:column;align-items:center;gap:8px;color:var(--accent);font-weight:600;font-size:14px;background:var(--surface);padding:16px 22px;border-radius:12px;box-shadow:var(--shadow-md)}
.file-card-sent{margin-top:2px}
.file-card-sent .badge{padding:1px 7px;font-size:10px;gap:3px}
.atd-c-ta{width:100%;border:none;background:none;color:var(--text);font-family:inherit;font-size:14px;line-height:1.5;resize:none;padding:11px 12px 6px;min-height:52px;max-height:180px;overflow-y:auto;outline:none;display:block}
.atd-c-ta::placeholder{color:var(--text-faint)}
.atd-c-abar{display:flex;align-items:center;gap:8px;padding:7px 8px 8px;border-top:1px solid var(--border);flex-wrap:wrap}
.atd-c-tool{position:relative;width:34px;height:34px;flex:none;border:1px solid transparent;border-radius:9px;background:none;color:var(--text-soft);display:grid;place-items:center;transition:.13s;cursor:pointer}
.atd-c-tool:hover{background:var(--surface-2);color:var(--accent)}
.atd-c-tool:disabled{opacity:.45;cursor:not-allowed}
/* Selo ⌘K no botão "/" (fidelidade ao protótipo): anuncia o atalho global do palette. */
.atd-c-kbd{position:absolute;bottom:-3px;right:-3px;font-size:8px;font-weight:700;line-height:1.6;background:var(--accent);color:var(--accent-contrast);border-radius:4px;padding:0 3px;font-family:ui-monospace,Menlo,Consolas,monospace}
.atd-c-abar-spacer{flex:1 1 8px}
/* Split-send (fidelidade ao protótipo "Composer VEXXIO"): Enviar + caret colados num controle só, com raio
   externo, sombra e divisor interno. Estilo dedicado (não reusa .btn) pra bater a proporção exata do protótipo,
   na cor de marca do app (terracota via --accent), não no teal do protótipo. */
.atd-c-send-split{display:inline-flex;border-radius:10px;overflow:hidden;box-shadow:var(--shadow-md)}
.atd-c-send-main{border:none;background:var(--accent);color:var(--accent-contrast);font-weight:700;font-size:13.5px;letter-spacing:.01em;padding:0 16px;height:38px;display:inline-flex;align-items:center;gap:7px;cursor:pointer;transition:background .13s}
.atd-c-send-main:hover{background:var(--accent-hover)}
.atd-c-send-main:disabled{opacity:.55;cursor:not-allowed}
.atd-c-send-caret{border:none;background:var(--accent);color:var(--accent-contrast);width:32px;height:38px;display:grid;place-items:center;cursor:pointer;transition:background .13s;border-left:1px solid color-mix(in srgb,#000 16%,var(--accent))}
.atd-c-send-caret:hover{background:var(--accent-hover)}
.atd-composer.internal .atd-c-send-main,.atd-composer.internal .atd-c-send-caret{background:var(--warning);color:#fff}
.atd-composer.internal .atd-c-send-main:hover,.atd-composer.internal .atd-c-send-caret:hover{filter:brightness(.94)}
.atd-composer.internal .atd-c-send-caret{border-left-color:color-mix(in srgb,#000 16%,var(--warning))}
/* Chip "N envios agendados" — faixa clicável no topo da caixa que abre a lista pra cancelar (Enviar depois). */
.atd-c-scheduled{display:flex;align-items:center;gap:7px;padding:6px 10px 6px 12px;border-bottom:1px solid var(--border);background:var(--surface-2);font-size:12px;color:var(--text-soft);cursor:pointer}
.atd-c-scheduled:hover{background:var(--bg)}
/* Aviso de fluxo conduzindo: aparece no topo do composer (só no modo Responder) quando um fluxo de
   chatbot ainda está conduzindo a conversa — enviar uma mensagem vai interromper/pausar esse fluxo. Só
   avisa; a confirmação de fato acontece no clique de enviar (ver wireLeadConversasComposer). Tinta da IA
   (--ia), mesmo idioma visual do bloco "Fluxo ativo" e da nota de IA no cabeçalho. */
.atd-c-flow-notice{display:flex;align-items:center;gap:7px;padding:7px 10px 7px 12px;border-bottom:1px solid var(--border);background:var(--ia-soft);color:var(--ia);font-size:11.5px;font-weight:600}
.atd-c-flow-notice svg{flex:none}
.atd-c-flow-notice b{font-weight:700}
.atd-c-sched-ic{color:var(--accent);display:inline-flex;flex:none}
@media (max-width:560px){
  .atd-c-abar #lead-conversas-send{flex:1}
}
/* ===== Command palette do composer (Fatia 3) =====
   Painel que flutua ACIMA da caixa quando se digita "/" (ou clica no "/"). v1 traz só o provedor de
   Respostas Prontas (substitui o antigo combo "Inserir resposta pronta"); Fatias 4/5 registram Fluxos e
   Ações no mesmo motor. Reaproveita os tokens do projeto; item selecionado usa o accent. */
.atd-pal{position:absolute;left:0;right:0;bottom:calc(100% + 8px);max-width:560px;background:var(--surface);border:1px solid var(--border-strong);border-radius:12px;box-shadow:var(--shadow-md);z-index:60;display:none;overflow:hidden}
.atd-pal.show{display:block;animation:atdPalPop .14s ease}
.atd-pal-head{display:flex;align-items:center;gap:8px;padding:9px 13px;border-bottom:1px solid var(--border);color:var(--text-faint);font-size:12px}
.atd-pal-q{font-weight:600;color:var(--accent)}
.atd-pal-esc{margin-left:auto;font-size:10.5px;background:var(--surface-2);border:1px solid var(--border);border-radius:5px;padding:1px 6px;color:var(--text-soft)}
.atd-pal-list{max-height:320px;overflow-y:auto;padding:5px}
.atd-pal-group{font-size:10.5px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--text-faint);padding:9px 10px 4px}
.atd-pal-item{display:flex;align-items:center;gap:11px;padding:8px 10px;border-radius:9px;cursor:pointer;position:relative}
.atd-pal-ic{width:30px;height:30px;border-radius:8px;flex:none;display:grid;place-items:center;background:var(--surface-2);color:var(--text-soft)}
.atd-pal-item.g-resposta .atd-pal-ic{background:var(--accent-soft);color:var(--accent)}
.atd-pal-item.g-bot .atd-pal-ic{background:color-mix(in srgb,#6366f1 16%,var(--surface));color:#6366f1}
.atd-pal-item.g-acao .atd-pal-ic{background:var(--warning-soft);color:var(--warning)}
.atd-pal-body{min-width:0;flex:1}
.atd-pal-t{display:block;font-size:13.5px;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.atd-pal-s{display:block;font-size:12px;color:var(--text-faint);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.atd-pal-cmd{font-family:ui-monospace,Menlo,Consolas,monospace;font-size:11px;color:var(--text-soft);background:var(--surface-2);border:1px solid var(--border);border-radius:5px;padding:1px 6px;flex:none}
.atd-pal-check{flex:none;font-size:11px;font-weight:700;color:var(--accent);background:var(--accent-soft);border-radius:5px;padding:1px 7px}
.atd-pal-crumbs{display:inline-flex;align-items:center;gap:5px;flex-wrap:wrap}
.atd-pal-crumb{cursor:pointer;color:var(--text-faint);border-radius:4px}
.atd-pal-crumb:hover{color:var(--accent)}
.atd-pal-crumb.cur{color:var(--text-soft);font-weight:600;cursor:default}
.atd-pal-crumb-sep{color:var(--text-faint);opacity:.55}
.atd-pal-item.sel{background:var(--accent-soft)}
.atd-pal-item.sel::before{content:"";position:absolute;left:0;top:7px;bottom:7px;width:3px;border-radius:3px;background:var(--accent)}
.atd-pal-empty{padding:24px 14px;text-align:center;color:var(--text-faint);font-size:13px}
.atd-pal-foot{display:flex;gap:14px;align-items:center;padding:7px 13px;border-top:1px solid var(--border);font-size:11px;color:var(--text-faint);flex-wrap:wrap}
.atd-pal-foot kbd{font-family:ui-monospace,Menlo,Consolas,monospace;background:var(--surface-2);border:1px solid var(--border);border-radius:4px;padding:0 5px;color:var(--text-soft);font-size:10.5px}
/* Lista compacta de arquivos da lateral do chat (Atendimento): exibição própria e simplificada (pedido do
   usuário), no mesmo formato da listagem de comandos/ações — reusa os átomos do palette (.atd-pal-item/-ic/
   -body/-t) num formato de lista estática, sem upload nem botões de baixar/excluir. Subtítulo em duas
   colunas: seção (módulo) + tamanho à esquerda, DD/MM/AA HH:mm à direita. A ficha completa do Lead (aba
   Arquivos) segue com o gerenciador completo (dropzone + fileBrowserHtml). */
.atd-file-list{margin:0 -14px}/* anula o padding lateral do .atd-panebody (14px) pra o hover ir de borda a borda */
.atd-file-item{width:100%;text-align:left;border:none;border-radius:0;background:none;font-family:inherit;padding-left:18px;padding-right:18px}
.atd-file-item+.atd-file-item{border-top:1px solid var(--border)}/* separador entre as linhas */
.atd-file-item:hover{background:var(--surface-2)}
.atd-file-sub{display:flex;align-items:center;justify-content:space-between;gap:8px;margin-top:1px}
.atd-file-meta{font-size:11.5px;color:var(--text-faint);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:0}
.atd-file-date{font-size:11px;color:var(--text-faint);flex:none;font-variant-numeric:tabular-nums}
/* ===== Carrinho de Compras (Fatia 1) — takeover da coluna direita do Atendimento. Reaproveita os átomos
   do palette (.atd-pal-item/-ic/-body/-t/-s) pras linhas de resultado e de item; o resto é próprio do
   carrinho. Fiel ao protótipo aprovado, com os tokens reais do app (claro/escuro). ===== */
.atd-cart-pill{display:inline-flex;align-items:center;gap:7px;border:1px solid var(--border-strong);background:var(--surface);color:var(--text);border-radius:999px;padding:5px 11px 5px 9px;font-size:12.5px;font-weight:700;cursor:pointer}
.atd-cart-pill:hover{border-color:var(--accent);color:var(--accent)}
.atd-cart-pill svg{width:17px;height:17px}
.atd-cart-pill-badge{background:var(--accent);color:var(--accent-contrast);border-radius:999px;font-size:11px;min-width:18px;height:18px;padding:0 5px;display:grid;place-items:center;font-weight:700}
.atd-cart-pill-total{color:var(--text-soft);font-weight:600;font-variant-numeric:tabular-nums}
.atd-cart{display:flex;flex-direction:column;height:100%;animation:atdCartIn .22s cubic-bezier(.4,0,.2,1)}
@keyframes atdCartIn{from{opacity:0;transform:translateX(10px)}to{opacity:1;transform:none}}
@media (prefers-reduced-motion:reduce){.atd-cart{animation:none}}
/* Enquanto o carrinho ocupa o painel direito, zera o padding do .atd-info pra o carrinho ir de ponta a
   ponta (aproveita mais espaço lateral, CONVERSAS); os paddings internos do carrinho é que espaçam. */
.atd-info.atd-cart-open{padding:0}
.atd-cart-head{display:flex;align-items:center;gap:10px;padding:10px 10px 10px 6px;border-bottom:1px solid var(--border);flex:none}
.atd-cart-back{width:34px;height:34px;border-radius:9px;border:1px solid transparent;background:none;color:var(--text-soft);display:grid;place-items:center;flex:none;cursor:pointer}
.atd-cart-back:hover{background:var(--surface-2);color:var(--text)}
.atd-cart-back svg{width:19px;height:19px}
.atd-cart-titles{min-width:0;flex:1}
.atd-cart-titles .t{font-size:14px;font-weight:600}
.atd-cart-titles .s{font-size:11.5px;color:var(--text-faint);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.atd-cart-count{font-size:11px;font-weight:700;color:var(--accent);background:var(--accent-soft);border-radius:999px;padding:3px 10px;flex:none}
.atd-cart-search{padding:11px 12px 8px;flex:none}
.atd-cart-search-wrap{display:flex;align-items:center;gap:8px;border:1px solid var(--border);background:var(--surface-2);border-radius:10px;padding:8px 11px}
.atd-cart-search-wrap:focus-within{border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-ring)}
.atd-cart-search-wrap svg{width:16px;height:16px;color:var(--text-faint);flex:none}
.atd-cart-search-wrap input{flex:1;border:none;background:none;outline:none;color:var(--text);font-size:13px;font-family:inherit}
.atd-cart-search-wrap input::placeholder{color:var(--text-faint)}
.atd-cart-results{flex:none;max-height:44%;overflow-y:auto;padding:0 6px;border-bottom:1px solid var(--border)}
.atd-cart-results-meta{font-size:10px;font-weight:700;letter-spacing:.05em;text-transform:uppercase;color:var(--text-faint);padding:6px 8px 4px}
.atd-cart-add{width:28px;height:28px;border-radius:8px;border:1px solid var(--border-strong);background:var(--surface);color:var(--accent);display:grid;place-items:center;flex:none;cursor:pointer}
.atd-cart-add:hover{background:var(--accent);color:var(--accent-contrast);border-color:transparent}
.atd-cart-add svg{width:15px;height:15px}
.atd-cart-price{text-align:right;flex:none}
.atd-cart-price .v{font-size:13px;font-weight:700;font-variant-numeric:tabular-nums}
.atd-cart-price .u{font-size:10.5px;color:var(--text-faint)}
.atd-cart-stock{font-weight:600;color:var(--success)}
.atd-cart-stock.low{color:var(--warning)}
.atd-cart-scroll{flex:1;overflow-y:auto;padding:4px 6px 8px;min-height:0}
.atd-cart-grouplabel{font-size:10px;font-weight:700;letter-spacing:.05em;text-transform:uppercase;color:var(--text-faint);padding:8px 8px 3px;display:flex;align-items:center;justify-content:space-between;gap:8px}
/* Botão "esvaziar" à direita do "N itens no carrinho" (item CONVERSAS 6). */
.atd-cart-clear{display:inline-flex;align-items:center;gap:4px;border:none;background:transparent;color:var(--text-faint);font-size:10px;font-weight:700;letter-spacing:.05em;text-transform:uppercase;cursor:pointer;padding:2px 5px;border-radius:5px}
.atd-cart-clear:hover{color:var(--danger);background:var(--danger-soft)}
.atd-cart-right{display:flex;align-items:center;gap:10px;flex:none}
.atd-cart-stepper{display:inline-flex;align-items:center;border:1px solid var(--border-strong);border-radius:9px;overflow:hidden;background:var(--surface);flex:none}
.atd-cart-stepper button{width:26px;height:28px;border:none;background:none;color:var(--text-soft);display:grid;place-items:center;cursor:pointer}
.atd-cart-stepper button:hover{background:var(--surface-2);color:var(--accent)}
.atd-cart-stepper svg{width:13px;height:13px}
.atd-cart-qty{min-width:30px;text-align:center;font-size:12.5px;font-weight:700;font-variant-numeric:tabular-nums}
.atd-cart-line{text-align:right;font-size:13px;font-weight:700;font-variant-numeric:tabular-nums;flex:none}
/* Linha do item do carrinho em 2 linhas: L1 = SKU + nome (trunca); L2 = valor unit · qtd · total (não quebra). */
.atd-cart-item2{display:flex;align-items:center;gap:11px;padding:8px 10px;border-radius:9px;position:relative}
.atd-cart-item2:hover{background:var(--surface-2)}
.atd-cart-info{flex:1;min-width:0;display:flex;flex-direction:column;gap:3px}
.atd-cart-l1{display:flex;align-items:center;gap:6px;min-width:0}
.atd-cart-sku{font-size:11px;font-weight:700;color:var(--text-faint);flex:none;font-variant-numeric:tabular-nums}
.atd-cart-name{font-size:13px;font-weight:600;color:var(--text);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:0;flex:1}
.atd-cart-l2{display:flex;align-items:center;justify-content:space-between;gap:8px;flex-wrap:nowrap;white-space:nowrap}
.atd-cart-unit{font-size:12px;color:var(--text-soft);white-space:nowrap;flex:none;display:inline-flex;align-items:center;gap:5px}
.atd-cart-qtyin{border:none;background:none;outline:none;color:var(--text);font-size:12.5px;font-weight:700;text-align:center;font-variant-numeric:tabular-nums;padding:0 2px;font-family:inherit;min-width:2ch;-moz-appearance:textfield}
.atd-cart-qtyin::-webkit-outer-spin-button,.atd-cart-qtyin::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}
.atd-cart-warn{font-size:11px;font-weight:600;color:var(--danger)}
.atd-cart-del{width:28px;height:28px;border-radius:8px;border:1px solid transparent;background:none;color:var(--text-faint);display:grid;place-items:center;opacity:0;flex:none;cursor:pointer;align-self:flex-start}
.atd-pal-item:hover .atd-cart-del,.atd-cart-item2:hover .atd-cart-del{opacity:1}
.atd-cart-del:hover{background:var(--danger-soft);color:var(--danger)}
.atd-cart-del svg{width:15px;height:15px}
.atd-oc{font-size:10px;font-weight:700;border-radius:999px;padding:1px 7px}
.atd-oc.cliente{background:var(--success-soft);color:var(--success)}
.atd-oc.ia{background:var(--info-soft);color:var(--info)}
.atd-was{color:var(--text-faint);text-decoration:line-through;font-size:11px;font-variant-numeric:tabular-nums}
.atd-off{color:var(--success);font-weight:700;font-size:10.5px;background:var(--success-soft);border-radius:5px;padding:0 5px}
.atd-cart-foot{border-top:1px solid var(--border);background:var(--surface-2);padding:11px 14px 13px;flex:none}
.atd-cart-trow{display:flex;justify-content:space-between;font-size:12.5px;color:var(--text-soft);padding:2px 0;font-variant-numeric:tabular-nums}
.atd-cart-trow .lnk{color:var(--accent);font-weight:600;cursor:pointer;font-size:11.5px}
.atd-cart-trow.disc{color:var(--success)}
.atd-cart-totalrow{display:flex;justify-content:space-between;align-items:baseline;margin-top:7px;padding-top:9px;border-top:1px dashed var(--border-strong)}
.atd-cart-totalrow .l{font-size:12px;font-weight:700;color:var(--text-soft);text-transform:uppercase;letter-spacing:.04em}
.atd-cart-totalrow .v{font-size:21px;font-weight:800;font-variant-numeric:tabular-nums}
.atd-cart-actions{display:grid;grid-template-columns:1fr 1fr;gap:8px;margin-top:12px}
.atd-cart-act{display:inline-flex;align-items:center;justify-content:center;gap:7px;border-radius:10px;padding:9px 12px;font-size:12.5px;font-weight:700;border:1px solid var(--border-strong);background:var(--surface);color:var(--text);cursor:pointer}
.atd-cart-act:hover{border-color:var(--text-faint)}
.atd-cart-act svg{width:15px;height:15px}
.atd-cart-act.primary{grid-column:1/-1;background:var(--accent);color:var(--accent-contrast);border-color:transparent}
.atd-cart-act.primary:hover{background:var(--accent-hover)}
.atd-cart-empty{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;gap:8px;padding:26px;color:var(--text-faint)}
.atd-cart-empty .eic{width:50px;height:50px;border-radius:14px;background:var(--surface-2);border:1px solid var(--border);display:grid;place-items:center}
.atd-cart-empty .eic svg{width:24px;height:24px}
.atd-cart-empty .et{font-size:14px;font-weight:700;color:var(--text-soft)}
.atd-cart-empty .es{font-size:12.5px;max-width:230px}
.atd-cart-entry{border:1px solid var(--border);border-radius:13px;overflow:hidden;background:var(--surface-2)}
.atd-cart-entry>button{width:100%;border:none;background:none;text-align:left;display:flex;align-items:center;gap:12px;padding:12px 13px;color:var(--text);cursor:pointer}
.atd-cart-entry>button:hover{background:var(--surface)}
.atd-cart-entry .ce-ic{width:38px;height:38px;border-radius:10px;background:var(--accent-soft);color:var(--accent);display:grid;place-items:center;flex:none}
.atd-cart-entry .ce-ic svg{width:20px;height:20px}
.atd-cart-entry .ce-b{flex:1;min-width:0}
.atd-cart-entry .ce-t{font-size:13.5px;font-weight:700}
.atd-cart-entry .ce-s{font-size:12px;color:var(--text-faint)}
.atd-cart-entry .ce-amt{font-weight:800;font-size:13.5px;font-variant-numeric:tabular-nums}
.atd-cart-entry .ce-chev{color:var(--text-faint);flex:none}
.atd-cart-empresa{padding:16px}
.atd-cart-empresa .lbl{font-size:12.5px;color:var(--text-soft);margin-bottom:8px}
.atd-cart-empresa select{width:100%;border:1px solid var(--border);background:var(--surface);color:var(--text);border-radius:9px;padding:9px 11px;font-size:13px;font-family:inherit}
.atd-c-slash{font-weight:700;font-size:16px;color:var(--accent);font-family:ui-monospace,Menlo,Consolas,monospace}
.atd-c-slash:hover{background:var(--accent-soft)}
.atd-c-fieldhint{padding:0 12px 7px;font-size:11.5px;color:var(--text-soft)}
.atd-c-fieldhint code{font-family:ui-monospace,Menlo,Consolas,monospace;font-size:11px;background:var(--accent-soft);color:var(--accent);padding:1px 5px;border-radius:5px}
@keyframes atdPalPop{from{opacity:0;transform:translateY(6px) scale(.985)}to{opacity:1;transform:none}}
/* ===== Cmd-K global (Fatia 6) — o mesmo vocabulário do palette do composer, num overlay centralizado que
   abre de qualquer tela (Ctrl/⌘ K). Reaproveita as classes .atd-pal-* pros itens; só o invólucro é próprio. */
.cmdk-overlay{position:fixed;inset:0;z-index:200;display:none;background:rgba(8,12,16,.5);align-items:flex-start;justify-content:center;padding:12vh 16px 16px}
.cmdk-overlay.show{display:flex;animation:atdPalPop .12s ease}
.cmdk{width:100%;max-width:560px;max-height:70vh;display:flex;flex-direction:column;background:var(--surface);border:1px solid var(--border-strong);border-radius:14px;box-shadow:0 24px 70px rgba(0,0,0,.45);overflow:hidden}
.cmdk-inp{display:flex;align-items:center;gap:10px;padding:13px 15px;border-bottom:1px solid var(--border)}
.cmdk-inp .cmdk-ic{color:var(--text-faint);display:inline-flex;flex:none}
.cmdk-inp input{flex:1;min-width:0;border:none;background:none;outline:none;color:var(--text);font-size:15px;font-family:inherit}
.cmdk-inp input::placeholder{color:var(--text-faint)}
.cmdk-inp .cmdk-esc{flex:none;font-size:10.5px;font-family:ui-monospace,Menlo,Consolas,monospace;background:var(--surface-2);border:1px solid var(--border);border-radius:5px;padding:2px 6px;color:var(--text-soft)}
.cmdk-list{overflow-y:auto;padding:6px}
/* Avatar do lead nos resultados de Atendimento do Cmd-K (preenche o mesmo quadradinho do .atd-pal-ic). */
.cmdk-ava{width:30px;height:30px;border-radius:8px;object-fit:cover;display:block}
/* Realce breve ao "rolar até a original" (quando o usuário clica numa citação). */
.atd-msg-bubble.atd-msg-flash{animation:atdMsgFlash 1.5s ease}
@keyframes atdMsgFlash{0%,100%{box-shadow:0 0 0 0 transparent}25%{box-shadow:0 0 0 3px var(--accent-ring,rgba(59,130,246,.4))}}
/* Views por tipo de mensagem do WhatsApp (imagem/vídeo/sticker inline, cards de localização/contato/
   enquete/pedido/chamada) — ver messageBubbleHtml/messageBodyHtml. Card genérico reaproveitado por todos
   os tipos "sem mídia" pra ficarem visualmente iguais. */
/* Prévia de mídia com CAIXA DE TAMANHO FIXO (aspect-ratio reserva a altura antes mesmo da src assinada
   carregar) — sem isso a bolha nascia com altura ~0 e crescia ao carregar a imagem/vídeo, bagunçando o
   scrollToBottom e às vezes escondendo a última mensagem. object-fit:cover mascara o conteúdo na prévia
   (o cheio abre ao clicar); fundo surface-2 é o placeholder enquanto a src não chegou. */
.atd-msg-image,.atd-msg-video{width:240px;max-width:100%;aspect-ratio:4/3;object-fit:cover;background:var(--surface-2);border-radius:8px;display:block;cursor:pointer}
/* Imagem exibida a partir da miniatura embutida do WhatsApp (baixa resolução): fica no tamanho NATURAL da
   miniatura, teto 240x220, sem corte (contain) — não estica além do real (item CONVERSAS 2, evita o borrado
   "estourado"). O arquivo cheio e nítido abre ao clicar. Especificidade dupla vence a base acima. */
.atd-msg-image.atd-msg-media-thumb{width:auto;height:auto;max-width:240px;max-height:220px;aspect-ratio:auto;object-fit:contain;background:transparent}
/* Vídeo com dimensões reais já conhecidas (medidas do poster/miniatura ou do metadata, ver wireConversaMedia):
   sai da caixa 4/3 recortada e assume a PROPORÇÃO REAL do vídeo, sem cortar bordas — vertical fica vertical,
   panorâmico fica panorâmico. A largura exata é calculada em JS (respeita max-width 240 / max-height 240);
   object-fit:contain é só rede de segurança se a largura inline e a proporção divergirem. */
.atd-msg-video.atd-msg-media-real{aspect-ratio:auto;object-fit:contain;background:var(--surface-2);max-height:240px}
.atd-msg-sticker{width:120px;height:120px;object-fit:contain;display:block}
/* Sticker (item CONVERSAS 8): sem bolha, como no WhatsApp — fundo transparente (vence o inline via
   !important), sem borda nem padding. O selo de nome e o chip de reação seguem funcionando. */
.atd-msg-bubble-sticker{background:transparent !important;border:none;padding:0}
.atd-msg-media-loading{width:200px;max-width:100%;height:120px;border-radius:8px;background:var(--surface-2);display:flex;flex-direction:column;gap:8px;align-items:center;justify-content:center;color:var(--text-faint)}
/* Mensagem apagada pelo contato (tombstone): selo discreto em itálico, cinza, com ícone de proibido. */
.atd-msg-revoked{display:flex;align-items:center;gap:5px;color:var(--text-faint);font-style:italic;font-size:.85rem}
.atd-msg-revoked>summary{display:flex;align-items:center;gap:5px;cursor:pointer;list-style:none}
.atd-msg-revoked>summary::-webkit-details-marker{display:none}
.atd-msg-revoked-hint{font-style:normal;font-size:.72rem;color:var(--accent);text-decoration:underline}
/* "ver original" da apagada agora abre um modal (item CONVERSAS 9): o tombstone vira um botão sem cara de
   botão, mantendo o visual do selo (flex/itálico/cinza herdados de .atd-msg-revoked). */
button.atd-msg-revoked-link{background:none;border:0;padding:0;font:inherit;text-align:left;cursor:pointer}
.atd-msg-revoked-selo{display:inline-flex;align-items:center;gap:5px}
/* Selo "editada" (mensagem editada pelo contato): discreto, cinza, abaixo do texto novo. */
.atd-msg-edited-tag{display:inline-flex;align-items:center;gap:3px;margin-top:3px;font-size:.7rem;color:var(--text-faint);font-style:italic}
details.atd-msg-edited-tag>summary{display:inline-flex;align-items:center;gap:3px;cursor:pointer;list-style:none}
details.atd-msg-edited-tag>summary::-webkit-details-marker{display:none}
/* "ver original" clicável (abre o modal de timeline): botão sem cara de botão, alinhado ao selo. */
button.atd-msg-edited-link{background:none;border:0;padding:0;font:inherit;cursor:pointer}
/* Modal da timeline de edições. */
.modal-edithist{max-width:480px;width:92vw}
.edithist{display:flex;flex-direction:column;gap:10px;max-height:70vh}
.edithist-head{display:flex;align-items:center;gap:8px}
.edithist-title{flex:1;font-weight:600;display:inline-flex;align-items:center;gap:5px}
.edithist-list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:8px;overflow-y:auto}
.edithist-item{border:1px solid var(--border);border-left:3px solid var(--border);border-radius:8px;padding:8px 10px;background:var(--surface)}
.edithist-item.edithist-atual{border-left-color:var(--accent);background:var(--surface-2)}
/* Linha final "Apagada" na timeline da mensagem apagada (item CONVERSAS 9). */
.edithist-item.edithist-deleted{border-left-color:var(--danger,#c0392b)}
.edithist-item.edithist-deleted .edithist-rotulo{color:var(--danger,#c0392b)}
.edithist-meta{display:flex;align-items:baseline;gap:8px;margin-bottom:3px}
.edithist-rotulo{font-size:.72rem;font-weight:600;text-transform:uppercase;letter-spacing:.02em;color:var(--text-faint)}
.edithist-item.edithist-atual .edithist-rotulo{color:var(--accent)}
.edithist-quando{font-size:.72rem;color:var(--text-faint)}
.edithist-texto{font-size:.9rem;color:var(--text);white-space:pre-wrap;word-break:break-word}
.atd-typed-card{border:1px solid var(--border);border-radius:8px;padding:8px;margin-top:4px;display:flex;flex-direction:column;gap:3px;background:var(--surface)}
.atd-linkpreview{flex-direction:row;align-items:stretch;gap:8px;text-decoration:none;color:inherit;overflow:hidden}
.atd-linkpreview:hover{border-color:var(--accent)}
.atd-linkpreview-thumb{width:52px;height:52px;flex:none;object-fit:cover;border-radius:6px;background:var(--surface-2)}
.atd-linkpreview-body{min-width:0;display:flex;flex-direction:column;justify-content:center;gap:2px}
.atd-linkpreview-title{font-size:.8rem;font-weight:600;line-height:1.25;overflow:hidden;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical}
.atd-linkpreview-desc{font-size:.72rem;color:var(--text-faint);line-height:1.25;overflow:hidden;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical}
.atd-linkpreview-host{font-size:.68rem;color:var(--accent);text-transform:lowercase}
.atd-poll-opt{border:1px solid var(--border);border-radius:6px;padding:4px 8px;font-size:12px;margin-top:3px}
.atd-item-body{flex:1;min-width:0}
.atd-item-top{display:flex;align-items:center;justify-content:space-between;gap:6px}
.atd-item-preview{display:flex;align-items:center;gap:6px}
.atd-chat{flex:1;display:flex;flex-direction:column;min-width:0}
.atd-chat-header{flex:none;display:flex;align-items:center;gap:10px;padding:12px 16px;border-bottom:1px solid var(--border)}
/* Presença do contato no cabeçalho do chat (online/digitando/visto por último) — vazio quando não sabemos. */
#lead-presence-indicator{font-size:11px;line-height:1.2;min-height:13px;color:var(--text-faint)}
#lead-presence-indicator[data-state="online"],#lead-presence-indicator[data-state="typing"],#lead-presence-indicator[data-state="recording"]{color:var(--success)}
/* Balão "digitando" na thread (3 pontinhos animados), mostrado enquanto o contato está compondo (presença
   typing/recording, ver setLeadTypingBubble). Vive dentro da mesma .atd-msg-bubble.atd-msg-bubble-theirs das
   mensagens recebidas, então herda cor/raio/padding do balão; só o conteúdo (os pontos) é próprio. */
#lead-typing-bubble{animation:atdTypingIn .18s ease-out}
@keyframes atdTypingIn{from{opacity:0;transform:translateY(3px)}to{opacity:1;transform:translateY(0)}}
.atd-typing-dots{display:inline-flex;align-items:center;gap:4px;padding:3px 2px}
.atd-typing-dots span{width:7px;height:7px;border-radius:50%;background:var(--text-faint);display:inline-block;animation:atdTypingBounce 1.2s infinite ease-in-out}
.atd-typing-dots span:nth-child(2){animation-delay:.15s}
.atd-typing-dots span:nth-child(3){animation-delay:.3s}
@keyframes atdTypingBounce{0%,60%,100%{transform:translateY(0);opacity:.35}30%{transform:translateY(-4px);opacity:1}}
@media (prefers-reduced-motion:reduce){.atd-typing-dots span{animation-duration:2.4s}#lead-typing-bubble{animation:none}}
.atd-chat-body{flex:1;min-height:0;display:flex;flex-direction:column;padding:16px}
/* leadConversasHtml()/loadLeadConversas() são as mesmas usadas na aba Conversas do Lead Detail (ver
   public/index.html, MÓDULO: LEADS - CONVERSAS) — aqui só se adapta a apresentação (cartão sem borda,
   lista de mensagens ocupando a altura toda) via CSS escopado neste container, sem duplicar HTML/JS.
   O teto de 420px é o default da aba Conversas do Lead Detail (que fica lado a lado com outro conteúdo,
   não pode crescer à vontade) — precisa estar aqui como regra normal, não mais inline no elemento
   (leadConversasHtml), porque um style="" inline bate qualquer seletor de classe/id do stylesheet e a
   regra de override abaixo (.atd-chat-body #lead-conversas-messages) nunca conseguia vencer. */
/* Aviso de falha de sincronização no card do WhatsApp (Config -> Mensagens) e banner destacado de
   instabilidade na aba Conversas do Lead — mesmo propósito (instabilidade + convite a re-sincronizar),
   estilos irmãos com base na cor --warning. Ver syncFailureText/leadConversasResyncBannerHtml. */
.wa-sync-warn{display:flex;align-items:flex-start;gap:6px;margin:0 0 10px;padding:8px 10px;border-radius:8px;background:var(--warning-soft);color:var(--warning);border:1px solid var(--warning);font-size:12px;line-height:1.4}
.wa-sync-warn svg{flex:none;margin-top:1px}
/* Botão de gerar outro QR Code, CENTRADO SOBRE o código expirado (ver baileysSessionCardHtml). Ele só
   aparece quando o servidor pausou a geração depois de dois códigos sem leitura, e o QR embaixo fica em
   opacidade 12%: o alvo do clique é a própria coisa que expirou, que é onde a pessoa já está olhando. Área
   de clique redonda e generosa (56px) porque o gesto é "recarregar isto aqui", não "achar um botão". */
.baileys-qr-reload{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);width:56px;height:56px;padding:0;border-radius:50%;display:flex;align-items:center;justify-content:center;box-shadow:0 2px 10px rgba(0,0,0,.18)}
.baileys-qr-reload svg{flex:none}
.baileys-qr-reload:hover{transform:translate(-50%,-50%) scale(1.06)}
.baileys-qr-reload:active{transform:translate(-50%,-50%) scale(.97)}
/* Barra de progresso da sincronização de histórico (Fatia 1, ver baileysSyncBarHtml). Reaproveita o padrão
   visual da barra do QR (trilho fino + preenchimento no accent). A variante indeterminada anima enquanto o
   Baileys ainda não informa o percentual do bootstrap. */
.wa-sync{margin:2px 0 0}
.wa-sync-track{height:5px;border-radius:5px;background:var(--border);overflow:hidden}
.wa-sync-fill{height:100%;background:var(--accent);border-radius:5px;width:0;transition:width .4s ease}
/* Sincronização que já percorreu várias conversas sem NADA voltar: a barra continua andando (ela mede
   pedidos), então só o texto avisando não basta — barra cheia na cor normal é lida como progresso bom. */
.wa-sync-fill--warn{background:var(--warning)}
.wa-sync-fill--indeterminate{width:35%;border-radius:5px;animation:wa-sync-indeterminate 1.2s ease-in-out infinite}
@keyframes wa-sync-indeterminate{0%{margin-left:-35%}100%{margin-left:100%}}
.wa-sync-label{display:flex;align-items:center;gap:5px;margin-top:5px;font-size:11.5px;color:var(--text-faint)}
.wa-sync-label svg{flex:none}
.wa-resync-banner{display:flex;align-items:flex-start;gap:10px;margin:0 0 12px;padding:10px 12px;border-radius:10px;background:var(--warning-soft);border:1px solid var(--warning)}
.wa-resync-banner .wa-resync-ic{color:var(--warning);flex:none;margin-top:1px}
.wa-resync-banner .wa-resync-body{flex:1;font-size:12.5px;line-height:1.45}
.wa-resync-banner .wa-resync-title{font-weight:600;color:var(--warning);margin-bottom:2px}
.wa-resync-banner .wa-resync-actions{margin-top:8px}
/* Variante de ERRO: recebimento confirmado morto (sessão precisa reparear) — re-sincronizar não recupera,
   então o banner troca de cor e de mensagem (ver leadChatIntegrity.needsRepair / loadLeadConversasResyncBanner). */
.wa-resync-banner--error{background:var(--danger-soft);border-color:var(--danger)}
.wa-resync-banner--error .wa-resync-ic{color:var(--danger)}
.wa-resync-banner--error .wa-resync-title{color:var(--danger)}
#lead-conversas-messages{max-height:420px;overflow-y:auto}
.atd-chat-body .card{border:none;box-shadow:none;background:transparent;padding:0;display:flex;flex-direction:column;height:100%;min-height:0}
.atd-chat-body #lead-conversas-messages{max-height:none;flex:1;padding-right:12px; padding-bottom: 10px}
/* Só no Atendimento: .atd-chat-body .card já zera o padding:16px do .card.p-4 (ver regra acima), então
   sem isso o avatar das mensagens "minhas" (à direita, ver messageBubbleHtml) ficava colado na barra de
   scroll — na aba Conversas do Lead Detail isso não acontece (o .card ali mantém o padding normal). */
/* Composer (fundo var(--surface), opaco) herdava o padding:16px do .atd-chat-body nas laterais/embaixo
   — como o container pai é transparente (ver .atd-chat-body .card acima), sobrava uma faixa cinza/escura
   do fundo da página em volta da caixa branca do composer, em vez dele ir colado nas bordas. Margem
   negativa cancela o padding herdado nesses 3 lados e devolve o mesmo respiro como padding próprio, então
   o fundo opaco passa a preencher até a borda real da coluna (o topo não muda, ali o design já pretende a
   quebra visual entre mensagens e composer via border-top, não o preenchimento até a borda). */
/* Base do composer (antes inline no template): fixo no rodapé, fundo opaco. Default var(--surface) serve
   pra aba Conversas do Lead Detail (dentro de card branco); no Atendimento vira var(--bg), ver override abaixo. */
.lead-conversas-composer{padding-top:10px;position:sticky;bottom:0;background:var(--surface)}
/* No Atendimento o fundo do composer acompanha o fundo do chat central (CONVERSAS 13), pra caixa se fundir
   com a área de mensagens em vez de virar uma faixa branca destacada. */
.atd-chat-body .lead-conversas-composer{margin:0 -16px -16px;padding-left:16px;padding-right:16px;padding-bottom:16px;background:var(--bg)}
/* Só no Atendimento: o banner do atendimento em curso vira uma faixa contínua colada no topo e nas
   laterais da coluna de chat, logo abaixo do cabeçalho (nome do lead) — a mesma ideia de margem negativa
   do composer, cancelando o respiro de 16px do .atd-chat-body nesses 3 lados. Sem bordas de topo/lateral
   nem cantos arredondados, pra não sobrar a moldura de cartão solto que havia antes. Escopado ao inbox de
   Atendimento: na aba Conversas do Lead Detail o mesmo banner mantém o respiro de cartão normal. */
.atd-chat-body #lead-conversas-attendance-banner .atd-banner-surface{margin-top:-16px;margin-left:-16px;margin-right:-16px;border-top:none;border-left:none;border-right:none;border-radius:0}
/* Trilho visível do scroll de conversas (id compartilhado entre Lead Detail e o inbox de Atendimento,
   ver comentário acima) — além da barrinha cinza padrão (::-webkit-scrollbar-thumb, global no topo do
   arquivo), um contêiner mais claro com borda suave marca visualmente a extensão total da lista, não só
   a posição do polegar dentro dela. Escopado neste id (não é uma mudança global de scrollbar). */
#lead-conversas-messages::-webkit-scrollbar-track{background:var(--surface-2);border:1px solid var(--border);border-radius:8px;margin:2px 0}
#lead-conversas-messages::-webkit-scrollbar-thumb{border-radius:8px}
.atd-list-filters{border-bottom:1px solid var(--accent)}
.atd-empty-meus{padding:20px 20px 24px;text-align:center}
.atd-empty-meus-arrow{color:var(--accent);display:flex;justify-content:flex-start;padding-left:10px;margin-bottom:2px}
/* .icon-btn-plain (display:inline-flex) vem depois desta regra no stylesheet e tem a mesma especificidade
   (1 classe), então vencia no desktop e deixava a seta visível sem nenhum efeito prático (só existe pra
   fechar a coluna de chat no layout mobile, ver media query abaixo) — seletor com 2 classes força a
   prioridade certa. */
.atd-chat-header .atd-back-btn{display:none}
/* Painel em coluna flex de altura definida (herda a altura do .atd-shell): a zona de identidade fica
   flex:none no topo e o accordion (.atd-acc) ocupa todo o resto até o bottom, com scroll interno na seção
   aberta — por isso overflow:hidden aqui (o scroll não é mais do painel inteiro, é de dentro de cada
   seção). */
.atd-info{width:300px;flex:none;border-left:1px solid var(--border);overflow:hidden;display:none;flex-direction:column;padding:18px;background:var(--surface)}
.atd-info.open{display:flex}
/* Foto do lead na coluna direita ganha uma borda clarinha pra se destacar do fundo branco do painel (CONVERSAS 7). */
.atd-info .avatar-img{border:1px solid var(--border)}
/* Tela estreita demais pra uma 3ª coluna sem espremer o chat (item CONVERSAS 7): a info abre como drawer
   flutuante ancorado à direita, por cima do chat, em vez de não abrir. Ancorado no .atd-shell (position:relative). */
.atd-info.atd-info-overlay{position:absolute;top:0;right:0;bottom:0;width:min(550px,92%);z-index:60;box-shadow:-6px 0 24px rgba(0,0,0,.28)}
/* Fundo escurecido do painel quando ele está sobreposto (modal, telas < 1200px): dá foco ao painel e permite
   fechar clicando fora. Ancorado no .atd-shell (position:relative), fica ATRÁS do drawer (z-index menor). No
   mobile (< 900px) o painel é tela cheia e o scrim não aparece (só é ligado no modo drawer, ver atdToggleInfoScrim). */
.atd-info-scrim{position:absolute;inset:0;background:rgba(0,0,0,.32);z-index:55;display:none}
.atd-info-scrim.open{display:block}
/* Rodapé de ações da conversa sem responsável (renderLeadConversasFooterActions) — antes inline. */
.atd-footer-actions{padding:28px 16px;border-top:1px solid var(--border)}
/* Layout de "somente visualização" dos protocolos (renderLeadConversasProtocolos) — antes inline. */
.atd-proto-layout{display:flex;gap:14px;align-items:flex-start}
.atd-proto-list{flex:0 0 240px;max-width:240px;max-height:62vh;overflow:auto}
.atd-proto-pane{flex:1;min-width:0}
.atd-proto-msgs{max-height:60vh;overflow:auto}
.atd-proto-btn{flex-direction:column;align-items:flex-start;gap:3px;height:auto;padding:8px 10px}
.atd-proto-btn-line{display:flex;align-items:center;gap:6px;width:100%}
.atd-proto-btn-line b{font-size:13px}
/* Combo de adicionar etiqueta (dropdown de busca) logo abaixo da linha de etiquetas do idhead. */
.atd-tags-pick-wrap{margin-top:6px}

/* ===================== PAINEL DE CONTEXTO DO LEAD — redesign (fiel ao protótipo) =====================
   Separa as três camadas que o accordion empilhava numa coluna estreita: identidade FIXA no topo
   (.atd-idhead), rail vertical de abas à esquerda (.atd-rail) e um corpo de conteúdo (.atd-ctx-pane) que
   ocupa toda a altura restante. Modo "Expandir" (.atd-info.expanded) revela os rótulos do rail e alarga
   o conteúdo. Tokens de cor/raio/sombra são os reais do app; o accent teal do protótipo mapeia pro accent
   da marca (salmão), e o card de IA usa o par --ia/--ia-soft (teal), coerente com o resto do sistema. */
.atd-info.atd-ctx{padding:0}
/* identidade fixa no topo, com leve tint accent */
.atd-idhead{flex:none;padding:14px 14px 12px;border-bottom:1px solid var(--border);background:linear-gradient(180deg,var(--accent-soft),transparent)}
.atd-idhead .row1{display:flex;align-items:center;gap:8px}
.atd-idhead .row1 h3{font-size:13px;font-weight:700;letter-spacing:.02em;text-transform:uppercase;color:var(--text-soft);flex:1;margin:0}
.atd-idbody{display:flex;gap:12px;align-items:center;margin-top:12px}
.atd-info .atd-idbody .avatar{width:52px;height:52px;font-size:17px;position:relative;overflow:visible}
.atd-info .atd-idbody .avatar .avatar-img{border-radius:50%;overflow:hidden}
.atd-idbody .atd-verified{position:absolute;right:-2px;bottom:-2px;width:19px;height:19px;border-radius:50%;background:var(--success);border:2.5px solid var(--surface);display:grid;place-items:center;color:#fff}
.atd-idmeta{min-width:0;flex:1}
.atd-idmeta .nm{font-weight:700;font-size:15.5px;display:flex;align-items:center;gap:6px;line-height:1.2}
.atd-idmeta .ph{color:var(--text-soft);font-size:12.5px;margin-top:2px;font-variant-numeric:tabular-nums}
.atd-idmeta .prof{color:var(--accent);font-size:12px;font-weight:600;margin-top:5px;display:inline-flex;gap:4px;align-items:center;text-decoration:none;background:none;border:0;padding:0;cursor:pointer}
.atd-tagrow{display:flex;flex-wrap:wrap;gap:6px;margin-top:12px;align-items:center}
.atd-tagrow .flex{gap:6px}
/* corpo: rail + pane */
.atd-ctx-split{flex:1;display:flex;min-height:0}
.atd-rail{flex:none;width:56px;border-right:1px solid var(--border);background:var(--surface-2);display:flex;flex-direction:column;gap:2px;padding:8px 6px;overflow:auto}
.atd-info.expanded .atd-rail{width:172px;padding:8px}
.atd-railbtn{position:relative;border:0;background:transparent;color:var(--text-soft);border-radius:10px;height:44px;display:flex;align-items:center;gap:11px;padding:0;justify-content:center;transition:.15s;width:100%;cursor:pointer}
.atd-info.expanded .atd-railbtn{justify-content:flex-start;padding:0 11px}
.atd-railbtn .lbl{display:none;font-size:12.5px;font-weight:600;white-space:nowrap}
.atd-info.expanded .atd-railbtn .lbl{display:block}
.atd-railbtn:hover{background:var(--surface);color:var(--text)}
.atd-railbtn.active{background:var(--accent-soft);color:var(--accent)}
.atd-railbtn.active::before{content:"";position:absolute;left:-6px;top:9px;bottom:9px;width:3px;border-radius:3px;background:var(--accent)}
.atd-railbtn .ic{flex:none;display:grid;place-items:center}
.atd-railbadge{position:absolute;top:5px;right:7px;min-width:16px;height:16px;padding:0 4px;border-radius:9px;background:var(--border-strong);color:var(--text);font-size:10px;font-weight:700;display:grid;place-items:center;font-variant-numeric:tabular-nums}
.atd-info.expanded .atd-railbadge{position:static;margin-left:auto}
.atd-railbtn.active .atd-railbadge{background:var(--accent);color:var(--surface)}
.atd-railbadge.warn{background:var(--danger);color:#fff}
.atd-railbadge[hidden]{display:none}
.atd-railattn{position:absolute;top:7px;right:9px;width:8px;height:8px;border-radius:50%;background:var(--danger);border:2px solid var(--surface-2)}
.atd-info.expanded .atd-railattn{right:auto;left:26px;top:11px}
.atd-railattn[hidden]{display:none}
/* pane de conteúdo */
.atd-ctx-pane{flex:1;min-width:0;display:flex;flex-direction:column}
.atd-panebody{flex:1;overflow:auto;padding:14px}
/* Painel de contexto COLAPSADO (CONVERSAS 3): só o rail de ícones fica visível. Some idbody/etiquetas/pane e
   o [X]; no topo sobra só o botão de expandir. Largura = a do rail. Vale no modo coluna (desktop); no
   overlay/mobile o [X] fecha de vez (a lógica no JS decide). */
.atd-info.collapsed{width:57px!important;min-width:57px}
.atd-info.collapsed .atd-idbody,
.atd-info.collapsed .atd-tagrow,
.atd-info.collapsed .atd-tags-pick-wrap,
.atd-info.collapsed .atd-ctx-pane,
.atd-info.collapsed #atd-info-close,
.atd-info.collapsed .atd-idhead .row1 h3{display:none}
.atd-info.collapsed .atd-idhead{padding:8px 6px;border-bottom:none;background:none}
.atd-info.collapsed .atd-idhead .row1{justify-content:center}
.atd-info.collapsed .atd-rail{border-right:none;width:100%}
.atd-info.collapsed .atd-railbtn{cursor:pointer}
.atd-panebody::-webkit-scrollbar{width:9px}
.atd-panebody::-webkit-scrollbar-thumb{background:var(--border-strong);border-radius:8px}
/* pills de status */
.atd-cpill{font-size:10.5px;font-weight:700;padding:2px 8px;border-radius:999px;letter-spacing:.02em;display:inline-block}
.atd-cpill.ok{background:var(--success-soft);color:var(--success)}
.atd-cpill.warn{background:var(--warning-soft);color:var(--warning)}
.atd-cpill.dang{background:var(--danger-soft);color:var(--danger)}
.atd-cpill.info{background:var(--info-soft);color:var(--info)}
.atd-cpill.mut{background:var(--surface-2);color:var(--text-faint);border:1px solid var(--border)}
/* item de lista genérico do pane */
.atd-cli{display:flex;gap:11px;align-items:center;padding:11px;border:1px solid var(--border);border-radius:var(--radius-md);background:var(--surface);margin-bottom:9px;transition:.15s;width:100%;text-align:left}
button.atd-cli{cursor:pointer;color:var(--text);font-family:inherit}
.atd-cli:hover{border-color:var(--border-strong);box-shadow:var(--shadow-sm)}
.atd-cli .lead{width:34px;height:34px;border-radius:9px;display:grid;place-items:center;flex:none;background:var(--surface-2);color:var(--text-soft);font-weight:700}
.atd-cli .g{flex:1;min-width:0}
.atd-cli .g .t1{font-weight:600;font-size:13px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.atd-cli .g .t2{color:var(--text-faint);font-size:11.5px;margin-top:1px}
.atd-cli .amt{font-weight:700;font-size:13px;font-variant-numeric:tabular-nums;text-align:right}
/* KPIs do Resumo */
.atd-kpis{display:grid;grid-template-columns:1fr 1fr;gap:10px;margin-bottom:14px}
.atd-kpi{border:1px solid var(--border);border-radius:var(--radius-md);padding:11px 12px;background:var(--surface-2)}
.atd-kpi .k{font-size:11px;color:var(--text-faint);font-weight:600;display:flex;align-items:center;gap:5px}
.atd-kpi .v{font-size:19px;font-weight:800;margin-top:5px;font-variant-numeric:tabular-nums;letter-spacing:-.02em}
.atd-kpi .v small{font-size:12px;font-weight:600;color:var(--text-faint)}
.atd-kpi.alert{border-color:var(--danger);background:var(--danger-soft)}
.atd-kpi.alert .v{color:var(--danger)}
/* card de IA (teal, par --ia) */
.atd-aicard{border:1px solid var(--ia-soft);border-radius:var(--radius-md);padding:13px;background:linear-gradient(135deg,var(--ia-soft),transparent)}
.atd-aicard .h{display:flex;align-items:center;gap:7px;font-size:11.5px;font-weight:700;color:var(--ia);text-transform:uppercase;letter-spacing:.06em;margin-bottom:8px}
.atd-aicard p{font-size:13px;color:var(--text);line-height:1.55;margin:0}
.atd-aicard p b{font-weight:700}
.atd-sectlabel{font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.08em;color:var(--text-faint);margin:16px 0 9px}
.atd-sectlabel:first-child{margin-top:0}
/* grade de arquivos/mídias */
.atd-filegrid{display:grid;grid-template-columns:repeat(3,1fr);gap:9px}
.atd-info.expanded .atd-filegrid{grid-template-columns:repeat(5,1fr)}
.atd-thumb{aspect-ratio:1;border-radius:var(--radius-md);border:1px solid var(--border);background:var(--surface-2);display:grid;place-items:center;color:var(--text-faint);position:relative;overflow:hidden}
.atd-thumb .ext{font-size:10px;font-weight:700;position:absolute;bottom:5px;left:6px;background:var(--surface);border:1px solid var(--border);padding:1px 5px;border-radius:5px}
/* cartão do carrinho em destaque */
.atd-cartcard{border:1px solid var(--accent);border-radius:var(--radius-lg);overflow:hidden}
.atd-cartcard .top{display:flex;align-items:center;gap:11px;padding:13px;background:var(--accent-soft)}
.atd-cartcard .top .ic{width:40px;height:40px;border-radius:11px;background:var(--accent);color:var(--accent-contrast);display:grid;place-items:center;flex:none}
.atd-cartcard .top .g{flex:1;min-width:0}
.atd-cartcard .top .g .t1{font-weight:700;font-size:14px}
.atd-cartcard .top .g .t2{font-size:12px;color:var(--text-soft)}
.atd-cartline{display:flex;justify-content:space-between;gap:10px;padding:10px 13px;border-top:1px solid var(--border);font-size:13px}
.atd-cartline .q{color:var(--text-faint);font-variant-numeric:tabular-nums;white-space:nowrap}
.atd-cartline b{font-variant-numeric:tabular-nums}
.atd-carttot{display:flex;justify-content:space-between;padding:12px 13px;border-top:1px solid var(--border-strong);font-weight:800;font-size:14px;background:var(--surface-2);font-variant-numeric:tabular-nums}
/* botão largo do pane */
.atd-ctx-btn{display:inline-flex;align-items:center;justify-content:center;gap:7px;width:100%;padding:11px;border:0;border-radius:var(--radius-md);background:var(--accent);color:var(--accent-contrast);font-weight:700;font-size:13px;margin-top:12px;transition:.15s;cursor:pointer;font-family:inherit}
.atd-ctx-btn:hover{background:var(--accent-hover)}
.atd-ctx-btn.sec{background:var(--surface);color:var(--text);border:1px solid var(--border)}
.atd-ctx-btn.sec:hover{border-color:var(--border-strong)}
/* coluna direita do .atd-cli (pill de status + valor), como no protótipo */
.atd-cli-r{flex:none;display:flex;flex-direction:column;align-items:flex-end;gap:4px;text-align:right}
/* compositor e cartões de nota (aba Notas) — fiéis a .note/.noteinput do protótipo */
.atd-note{border:1px solid var(--border);border-radius:var(--radius-md);padding:11px 12px;background:var(--surface-2);margin-bottom:9px}
.atd-note .m{font-size:11px;color:var(--text-faint);display:flex;gap:6px;align-items:center;margin-bottom:5px}
.atd-note p{font-size:13px;line-height:1.5;margin:0;white-space:pre-wrap}
.atd-noteinput{border:1px dashed var(--border-strong);border-radius:var(--radius-md);padding:11px 12px;color:var(--text-faint);font-size:12.5px;display:flex;align-items:center;gap:8px;cursor:text;width:100%;text-align:left;background:transparent;font-family:inherit;margin-bottom:12px}
.atd-noteinput:hover{border-color:var(--accent);color:var(--accent)}
.atd-note-form{margin-bottom:12px}
.atd-note-form textarea{width:100%;min-height:64px;resize:vertical;border:1px solid var(--border-strong);border-radius:var(--radius-md);padding:9px 11px;font-family:inherit;font-size:13px;background:var(--surface);color:var(--text)}
.atd-note-form textarea:focus{outline:none;border-color:var(--accent)}
/* miniaturas de mídia do chat clicáveis */
button.atd-thumb{cursor:pointer;font-family:inherit;color:var(--text-faint)}
button.atd-thumb:hover{border-color:var(--border-strong)}

/* Divisória arrastável entre as colunas (largura ajustável, ver wireAtdResizeHandle) — a de Informações
   só existe de fato (largura>0/clicável) quando o painel está aberto, ver .open abaixo. */
.atd-resize-handle{width:5px;flex:none;cursor:col-resize;background:transparent}
.atd-resize-handle:hover,.atd-resize-handle.dragging{background:var(--accent)}
.atd-resize-handle.atd-resize-info{display:none}
.atd-resize-handle.atd-resize-info.open{display:block}
/* Sino animado da aba Fila quando a contagem passa de 1 (ver atendimentoFilterChipsHtml) — balanço em
   CSS puro, sem depender de nenhum arquivo externo (gif/lottie baixado). */
/* Ciclo de 6s (não 1.2s): o balanço em si ocupa só os ~12% iniciais (~0.7s), o resto do tempo fica
   parado — dá o efeito "toca e espera ~5s pra tocar de novo" com 1 única animação em loop, sem timer em
   JS. Mesma lógica pro pulso do texto (atd-fila-text-pulse), com o mesmo período pra ficar sincronizado. */
@keyframes atd-bell-ring{0%,100%{transform:rotate(0)}2%{transform:rotate(14deg)}4%{transform:rotate(-12deg)}6%{transform:rotate(9deg)}8%{transform:rotate(-7deg)}10%{transform:rotate(4deg)}12%,100%{transform:rotate(0)}}
@keyframes atd-fila-text-pulse{0%,100%{transform:scale(1)}6%{transform:scale(1.1)}12%,100%{transform:scale(1)}}
.atd-fila-alert-icon{display:inline-flex;align-items:center;margin-top:-1px;transform-origin:50% 15%;color:var(--accent)}
.atd-fila-alert-text{display:inline-block;color:var(--accent)}
.atd-scope-tab-btn:not(.active) .atd-fila-alert-icon{animation:atd-bell-ring 6s ease-in-out infinite}
.atd-scope-tab-btn:not(.active) .atd-fila-alert-text{animation:atd-fila-text-pulse 6s ease-in-out infinite}
.atd-scope-tab-btn.active .atd-fila-alert-icon,.atd-scope-tab-btn.active .atd-fila-alert-text{color:inherit}
@media (max-width:900px){
  .atd-list{width:100%!important;border-right:none}
  .atd-chat{display:none}
  .atd-shell.chat-open .atd-list{display:none}
  .atd-shell.chat-open .atd-chat{display:flex}
  .atd-chat-header .atd-back-btn{display:inline-flex}
  .atd-info.open{position:fixed;inset:0;z-index:95;width:auto!important;border-left:none}
  .atd-resize-handle{display:none!important}
}
/* Banner informativo compartilhado entre o inbox de Atendimento e o widget flutuante (lead bloqueado,
   atendimento em aberto, automação pausada) — mesmo propósito (aviso contextual acima da conversa),
   variando só a cor (atd-banner-warning/success) e o layout: a maioria é 1 linha (.atd-banner, flex
   space-between), a de atendimento aberto é um bloco (usa .flex-col em vez de .atd-banner) porque tem
   os controles de posse dentro. .fcw-banner-margin é só o respiro lateral que o widget precisa (painel
   estreito, sem padding próprio no host do banner) — não faz parte da cor/formato do componente em si. */
.atd-banner-surface{border:1px solid var(--border);border-radius:8px;padding:8px 10px;font-size:12px}
.atd-banner{display:flex;align-items:center;justify-content:space-between;gap:8px}
.atd-banner-warning{background:color-mix(in srgb, var(--warning,#c99a2e) 14%, var(--surface))}
.atd-banner-success{background:color-mix(in srgb, var(--success,#2e9e5b) 12%, var(--surface))}
.fcw-banner-margin{margin:8px 12px 0}
/* ---- Cabeçalho do atendimento redesenhado (3 zonas: identidade / posse / ações) ----
   Reusa a casca .atd-banner-surface (por causa do override edge-to-edge em .atd-chat-body),
   mas zera o padding e a cor de fundo: o estado agora é comunicado por uma faixa fina no topo
   (.atd-hdr-stripe) e por um pill (.atd-hdr-status), não pela tinta do bloco inteiro. */
.atd-hdr{padding:0;overflow:hidden;background:var(--surface)}
.atd-hdr-stripe{height:3px}
.atd-hdr-open .atd-hdr-stripe{background:linear-gradient(90deg,var(--success),color-mix(in srgb,var(--success) 35%,transparent))}
.atd-hdr-ia .atd-hdr-stripe{background:linear-gradient(90deg,var(--ia),color-mix(in srgb,var(--ia) 35%,transparent))}
.atd-hdr-queue .atd-hdr-stripe{background:linear-gradient(90deg,var(--warning),color-mix(in srgb,var(--warning) 30%,transparent))}
.atd-hdr-closed .atd-hdr-stripe{background:var(--border-strong)}
/* corpo em duas linhas: (1) identidade + ações, (2) posse. Evita a ação órfã numa linha solta e mantém
   os controles alinhados como um sistema só. .atd-hdr-line é a linha de cima (space-between via margin). */
.atd-hdr-body{display:flex;flex-direction:column;align-items:flex-start;gap:10px;padding:12px}
.atd-hdr-line{display:flex;align-items:center;gap:12px;flex-wrap:wrap;width:100%}
/* zona A — identidade */
.atd-hdr-id{display:flex;align-items:center;gap:10px;min-width:0}
.atd-hdr-proto{font-size:15px;font-weight:700;letter-spacing:-.01em;font-variant-numeric:tabular-nums;color:var(--text)}
.atd-hdr-status{display:inline-flex;align-items:center;gap:6px;font-size:11px;font-weight:700;letter-spacing:.03em;text-transform:uppercase;padding:3px 9px;border-radius:100px;white-space:nowrap}
.atd-hdr-status .atd-hdr-dot{width:6px;height:6px;border-radius:50%;background:currentColor}
.atd-hdr-status.open{background:var(--success-soft);color:var(--success)}
.atd-hdr-status.ia{background:var(--ia-soft);color:var(--ia)}
.atd-hdr-status.queue{background:var(--warning-soft);color:var(--warning)}
.atd-hdr-status.closed{background:var(--surface-2);color:var(--text-faint);border:1px solid var(--border)}
.atd-hdr-since{font-size:12px;color:var(--text-faint);white-space:nowrap}
/* zona B — posse (Setor · Responsável · Fluxo ativo). UM cluster só (grupo de segmentos que dividem uma
   borda única, com divisória entre eles) — não três cartões soltos. Ocupa a largura toda da linha (cada
   segmento flex:1) e, quando a tela aperta, o grupo inteiro passa a empilhar na vertical (a divisória
   vira horizontal), continuando um bloco único. Cada segmento empilha o rótulo EM CIMA do valor; o de
   setor traz um ponto com a cor do setor atual. */
.atd-own{display:flex;align-items:stretch;width:100%;border:1px solid var(--border);border-radius:8px;background:var(--surface-2);overflow:hidden}
.atd-own-seg{flex:1;min-width:0;display:flex;flex-direction:column;justify-content:center;gap:3px;padding:6px 12px;min-height:44px}
.atd-own-seg+.atd-own-seg{border-left:1px solid var(--border)}
.atd-own-label{font-size:9px;letter-spacing:.06em;text-transform:uppercase;color:var(--text-faint);font-weight:700;line-height:1}
.atd-own-val{display:flex;align-items:center;gap:6px;min-width:0}
.atd-own-dot{width:8px;height:8px;border-radius:50%;flex:none;box-shadow:inset 0 0 0 1px rgba(0,0,0,.08)}
/* Fluxo ativo é só leitura (não há o que escolher aqui): texto simples, truncado com reticências, e um
   tom apagado quando não há fluxo em andamento ("Nenhum"). */
.atd-own-flow{font-size:12.5px;font-weight:600;color:var(--text);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:0}
.atd-own-flow.atd-own-flow-empty{color:var(--text-faint);font-weight:500}
.atd-own .admin-picker{max-width:100%;min-width:0}
.atd-own .admin-picker-trigger{border:none;background:transparent;min-height:0;padding:0;min-width:0;max-width:100%}
/* Setor (CONVERSAS 1): dropdown com cor ocupando a largura toda do segmento, gatilho clicável (ponto de
   cor + nome truncado), igual em espírito ao picker de Responsável ao lado. */
.atd-own .sector-picker{width:100%}
.atd-own .sector-picker .admin-picker-trigger{width:100%;display:flex;align-items:center;gap:6px;cursor:pointer}
/* [X] flutuante pra parar o fluxo ativo (CONVERSAS 3): canto superior direito do segmento Fluxo ativo. */
.atd-own-seg-flow{position:relative}
.atd-own-seg-flow .atd-own-val{padding-right:22px}
.atd-own-flow-x{position:absolute;top:6px;right:6px;width:18px;height:18px;display:flex;align-items:center;justify-content:center;padding:0;border:none;border-radius:50%;background:color-mix(in srgb,var(--text) 8%,transparent);color:var(--text-faint);cursor:pointer;line-height:0}
.atd-own-flow-x:hover{background:var(--danger-soft);color:var(--danger)}
/* Nome do responsável não quebra linha e trunca com reticências quando não cabe (item CONVERSAS 2), igual
   ao Fluxo ativo ao lado. */
.atd-own .admin-picker-name{font-size:12.5px;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:0}
/* Responsável "aguardando" enquanto a IA conduz (CONVERSAS 10): avatar + nome do responsável lembrado + tag. */
.atd-own-ia-wait{display:flex;align-items:center;gap:6px;min-width:0}
.atd-own-wait-tag{font-size:9px;font-weight:700;letter-spacing:.04em;text-transform:uppercase;color:var(--ia);background:var(--ia-soft);border-radius:5px;padding:1px 6px;flex:none}
/* zona C — ações (primária em destaque + menu de secundárias/recuo). Fica à direita da linha de cima
   (margin-left:auto, alinhada mesmo quando quebra); primária e kebab compartilham a MESMA altura (40px,
   igual ao cluster de posse) e o kebab é quadrado, pra não ter "cada um de um tamanho". */
.atd-hdr-actions{display:flex;align-items:center;gap:8px;margin-left:auto}
.atd-hdr-kebab{width:30px;height:30px;padding:0;justify-content:center}
/* Gatilho do dropdown "Passar conversa" (CONVERSAS 11) — ação primária do cabeçalho. */
.atd-hdr-handoff{display:inline-flex;align-items:center;gap:6px}
/* nota da IA conduzindo — faixa inferior sutil */
.atd-hdr-ia-note{display:flex;align-items:center;gap:6px;padding:9px 12px;border-top:1px solid var(--border);background:var(--ia-soft);color:var(--ia);font-size:12px;font-weight:600}
/* aviso "Automação pausada" (CONVERSAS 4): faixa inferior do cabeçalho, colada aos controles (abaixo dos
   botões), em vez de um card solto flutuando abaixo. Tom de aviso, com o botão Retomar à direita. */
.atd-hdr-pause{display:flex;align-items:center;justify-content:space-between;gap:10px;flex-wrap:wrap;padding:9px 12px;border-top:1px solid var(--border);background:var(--warning-soft);color:var(--warning)}
.atd-hdr-pause .text-sm{display:flex;align-items:center;gap:6px;font-weight:600}
/* responsivo: abaixo de 620px as zonas empilham; a ação primária ocupa a linha e o cluster de posse
   inteiro passa a empilhar na vertical (divisória vira horizontal), continuando um grupo único. */
@media (max-width:620px){
  .atd-hdr-id,.atd-hdr-actions{width:100%}
  .atd-hdr-actions .atd-hdr-handoff{flex:1;justify-content:center}
  .atd-hdr-actions .actions-dropdown{flex:1}
  .atd-hdr-kebab{flex:none}
  .atd-own{flex-direction:column}
  .atd-own-seg+.atd-own-seg{border-left:none;border-top:1px solid var(--border)}
}
/* Linha do divisor de dia/atendimento na timeline (dayDividerHtml/attendanceDividerHtml) — 2 por
   divisor, uma de cada lado do texto central. */
.atd-divider-line{flex:1;height:1px;background:var(--border)}
/* Cabeçalho flutuante de data (item CONVERSAS 3): pílula que gruda no topo da área de rolagem e mostra o
   dia da parte visível da conversa. Aparece ao rolar e some sozinha quando o scroll para (classe .visible,
   controlada por updateFloatingDay). margin-bottom negativa colapsa a própria altura pra flutuar SOBRE as
   bolhas sem empurrar o conteúdo; pointer-events:none pra não capturar cliques. */
.atd-floating-day{position:sticky;top:6px;z-index:5;align-self:center;pointer-events:none;margin-bottom:-30px;opacity:0;transition:opacity .18s ease}
.atd-floating-day.visible{opacity:1}
.atd-floating-day span{display:inline-block;background:var(--surface);border:1px solid var(--border);border-radius:20px;padding:3px 12px;font-size:11px;font-weight:600;color:var(--text-faint);box-shadow:var(--shadow-sm)}
/* Evento de sistema (systemEventHtml/systemEventGroupHtml) — linha discreta sem fundo/borda, tipo
   "fulano entrou no canal" do Slack/Intercom, pra não competir visualmente com mensagens reais. Rajadas
   de 3+ eventos seguidos sem mensagem real no meio colapsam num resumo expansível (<details>, sem JS de
   wiring: o navegador já cuida do estado aberto/fechado sozinho). Uma rajada inteira (agrupada ou não,
   ver conversaTimelineHtml) vira 1 único filho direto de #lead-conversas-messages/.fcw-messages
   (.atd-sysevent-run) — o gap:8px do container da lista de mensagens passa a respirar só ENTRE rajadas/
   mensagens reais, nunca dentro da própria rajada, que fica compacta (sem gap interno). */
.atd-sysevent-run{display:flex;flex-direction:column}
.atd-sysevent{display:flex;align-items:flex-start;justify-content:center;gap:4px;font-size:11px;color:var(--text-faint);padding:1px 0;text-align:center}
/* Ícone não encolhe e alinha com a PRIMEIRA linha do texto (não centralizado verticalmente), pra não ficar
   flutuando/perdido quando a nota é longa e quebra em 2+ linhas (ex: nota de recuperação de mensagens). */
.atd-sysevent > svg{flex:none;margin-top:1px}
/* Corpo da linha num único item flex: badge de etiqueta e link de tarefa (trilha de ações, ver
   OCC_RENDERERS) fluem inline no texto em vez de virarem itens flex soltos e desalinhados. */
.atd-sysevent-body{min-width:0}
.atd-sysevent-body .badge{vertical-align:baseline;font-size:10px}
.atd-sysevent-link{color:var(--accent);text-decoration:underline;cursor:pointer}
/* Linha de evento-sistema no feed de atividade unificado da aba Ocorrências (feedSystemLineHtml) — discreta
   e alinhada à esquerda, ao contrário da variante centralizada do chat (.atd-sysevent). */
.occ-feed-sysline{display:flex;align-items:flex-start;gap:6px;font-size:12px;color:var(--text-faint);padding:2px}
.occ-feed-sysline > svg{flex:none;margin-top:2px}
.occ-feed-sysline .badge{vertical-align:baseline;font-size:10px}
.occ-feed-sysline .atd-sysevent-link{color:var(--accent);text-decoration:underline;cursor:pointer}
/* "desfazer" de uma ação reversível da trilha, no feed de atividade (feedSystemLineHtml) */
.occ-undo-btn{background:none;border:none;padding:0;margin-left:4px;color:var(--accent);cursor:pointer;font-size:11px;display:inline-flex;align-items:center;gap:2px;vertical-align:baseline}
.occ-undo-btn:hover{text-decoration:underline}
.atd-sysevent-group-summary{display:flex;align-items:center;justify-content:center;gap:4px;font-size:11px;color:var(--text-faint);padding:1px 0;text-align:center;cursor:pointer;list-style:none}
.atd-sysevent-group-summary::-webkit-details-marker{display:none}
.atd-sysevent-group[open] .atd-sysevent-group-summary{color:var(--text)}
.atd-sysevent-group-items{padding-top:1px}

/* Widget flutuante de conversa (ver MÓDULO: WIDGET FLUTUANTE DE CONVERSA) — host fica fixo no canto
   inferior direito, mesma distância de baixo e da direita do .qs (bottom/right:20px). Quando o .qs
   (login rápido) também estiver visível no mesmo canto, syncFloatingChatWidgetPosition() empurra o
   widget pra cima dele em runtime — a maioria dos ambientes não tem quick-switch configurado, então o
   padrão fica coladinho no canto. */
#chat-widget-host{position:fixed;right:20px;bottom:20px;z-index:97;transition:bottom .15s ease}
/* Stack de avatares do rodapé (ver fcwStackHtml/MÓDULO: WIDGET FLUTUANTE DE CONVERSA) — até 3 avatares
   sobrepostos (margin-left negativo, ordem de empilhamento via z-index inline por slot), num pill que
   lembra os "chat heads" do Messenger/Intercom. .fcw-stack-avatar usa 2px de borda na cor da própria
   superfície (não var(--border)) só pra separar visualmente um avatar do outro por baixo dele, não é
   uma borda "de verdade". */
.fcw-stack{position:relative;display:flex;align-items:center;gap:6px;background:var(--surface);border:1px solid var(--border-strong);border-radius:999px;padding:6px 12px 6px 6px;box-shadow:var(--shadow-lg);cursor:default}
.fcw-stack-avatars{position:relative;display:flex;align-items:center}
.fcw-stack-avatar{position:relative;width:44px;height:44px;border-radius:50%;border:2px solid var(--surface);background:var(--surface-2);padding:0;cursor:pointer;margin-left:-14px;overflow:visible}
.fcw-stack-avatar:first-child{margin-left:0}
.fcw-stack-avatar .avatar{width:100%;height:100%;font-size:14px;border-radius:50%;overflow:hidden;display:flex}
.fcw-stack-avatar:hover{filter:brightness(1.08)}
.fcw-stack-extra{border:none;background:transparent;color:var(--text-soft);font-size:12.5px;font-weight:700;cursor:pointer;padding:0 2px;white-space:nowrap}
.fcw-stack-extra:hover{color:var(--text)}
.fcw-head .avatar{width:34px;height:34px;font-size:13px;overflow:hidden}
.fcw-panel{position:relative;width:360px;max-width:calc(100vw - 32px);height:500px;max-height:calc(100vh - 120px);display:flex;flex-direction:column;background:var(--surface);border:1px solid var(--border-strong);border-radius:var(--radius-lg);box-shadow:var(--shadow-lg);overflow:hidden}
/* Redimensionar: alças invisíveis ao longo de TODA a borda esquerda e superior (o painel é ancorado no
   canto inferior-direito pelo host, então arrastar pra cima/esquerda aumenta altura/largura). A borda
   esquerda inteira ajusta a largura, a superior inteira a altura, e só o canto superior-esquerdo as duas
   ao mesmo tempo. Sem ícone no canto. Ao passar o mouse numa alça (ou durante o arraste), a borda do
   painel vira tracejada mais escura como feedback. Escondidas no mobile (widget é o stack compacto). */
.fcw-resize-edge{position:absolute;z-index:6;touch-action:none}
.fcw-resize-edge-left{top:0;left:0;width:6px;height:100%;cursor:ew-resize}
.fcw-resize-edge-top{top:0;left:0;width:100%;height:6px;cursor:ns-resize}
.fcw-resize-edge-corner{top:0;left:0;width:14px;height:14px;z-index:7;cursor:nwse-resize}
.fcw-panel:has(.fcw-resize-edge:hover),.fcw-panel.fcw-resizing{border-style:dashed;border-color:var(--text-soft)}
@media (max-width:900px){.fcw-resize-edge{display:none}}
.fcw-head{flex:none;display:flex;align-items:center;gap:6px;padding:10px 12px;border-bottom:1px solid var(--border)}
.fcw-messages{flex:1;min-height:0;overflow-y:auto;display:flex;flex-direction:column;gap:8px;padding:12px}
.fcw-composer{flex:none;display:flex;align-items:flex-end;gap:8px;padding:10px 12px;border-top:1px solid var(--border)}
.fcw-composer .textarea{flex:1;resize:none;max-height:80px;min-height:38px}
/* Botão de enviar e o novo botão de ações do composer (floatingChatComposerActionsHtml) alinhados com a
   altura mínima do textarea (38px, ver acima) — sem isso ficavam com os 30px padrão de .icon-btn,
   visivelmente mais baixos que o campo de texto ao lado. */
.fcw-composer .icon-btn,.fcw-send-btn{width:38px;height:38px}
.fcw-send-btn{background:var(--accent);color:var(--accent-contrast);border-color:var(--accent);flex:none}
.fcw-send-btn:hover{background:var(--accent-hover)}
/* Confirmação de fechar o widget (ver wireFloatingChatPanel) — cobre o painel inteiro por cima das
   mensagens em vez de usar o modal global (openModal): o aviso é sobre ESTA janela especificamente,
   então fica contido dentro dela mesma. */
.fcw-close-confirm{position:absolute;inset:0;z-index:2;background:var(--surface);display:flex;flex-direction:column;align-items:center;justify-content:center;gap:12px;padding:24px;text-align:center}
/* Arrastar um arquivo por cima do widget inteiro (bolha ou painel, ver wireFloatingChatWidgetDropzone)
   vira um dropzone de upload, reaproveitando o mesmo .file-dropzone/.file-dropzone-inner da Central de
   Documentos (CLAUDE.md: componente único e compartilhado) — só o container muda, não o padrão visual.
   pointer-events:none porque quem escuta dragenter/dragleave/drop é o host (#chat-widget-host), não o
   overlay; ele existe só pra pintar por cima enquanto a classe .fcw-dragover estiver no host. */
.fcw-drop-overlay{display:none;position:absolute;inset:0;z-index:5;padding:4px;pointer-events:none}
.fcw-drop-overlay .file-dropzone{width:100%;height:100%;margin:0;display:flex;align-items:center;justify-content:center}
#chat-widget-host.fcw-dragover .fcw-drop-overlay{display:block}
@media (max-width:900px){
  #chat-widget-host{right:14px;bottom:14px}
}

/* stat cards */
.stat-card{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-lg);padding:16px 18px;display:flex;flex-direction:column;gap:10px;box-shadow:var(--shadow-sm)}
.stat-top{display:flex;align-items:center;justify-content:space-between}
.stat-icon{width:34px;height:34px;border-radius:9px;display:flex;align-items:center;justify-content:center}
.stat-value{font-size:24px;font-weight:800;letter-spacing:-.02em}
.stat-label{font-size:12px;color:var(--text-soft);font-weight:600}
.stat-trend{font-size:11.5px;font-weight:700;display:flex;align-items:center;gap:3px}

/* drawer */
.scrim{position:fixed;inset:0;background:rgba(15,17,20,.7);z-index:100;animation:fade .15s ease}
.scrim-drawer{background:rgba(15,17,20,.5)}
@keyframes fade{from{opacity:0}to{opacity:1}}
.drawer{position:fixed;top:0;right:0;height:100%;width:460px;max-width:94vw;background:var(--surface);z-index:101;box-shadow:var(--shadow-lg);display:flex;flex-direction:column;animation:slidein .18s cubic-bezier(.2,.9,.3,1)}
/* Drawer "elevado" (openDrawer elevated:true): sobe acima do modal (scrim 102 / modal 103) pra um drawer
   aberto de DENTRO de um modal aparecer por cima, não escondido atrás — ex: Exportar CSV a partir do modal
   de Respostas do Fluxo. Fechar o drawer volta pro modal, que continua montado por baixo. */
.scrim.scrim-elevated{z-index:104}
.drawer.drawer-elevated{z-index:105}
@keyframes slidein{from{transform:translateX(24px);opacity:.5}to{transform:translateX(0);opacity:1}}
/* headerTabs (ver openDrawer/renderDrawerLayer): parâmetro opcional que move só os BOTÕES de uma
   navegação por abas pro header do drawer, deixando o conteúdo de cada aba onde já estava (dentro de
   .drawer-body, ver flowDrawerTabsBodyHtml) — drawer sem headerTabs continua exatamente igual de antes,
   .drawer-head-top sozinho reproduz o mesmo layout de título+ações numa única linha. */
.drawer-head{padding:18px 20px;border-bottom:1px solid var(--border);display:flex;flex-direction:column;gap:12px;flex:none}
/* header com abas: as abas encostam na borda inferior do head, então zera o padding de baixo */
.drawer-head:has(.drawer-head-tabs){padding-bottom:0}
.drawer-head-top{display:flex;align-items:center;justify-content:space-between}
.drawer-head-tabs{display:flex;gap:4px}
.drawer-body{flex:1;overflow-y:auto;padding:20px}
.drawer-foot{padding:16px 20px;border-top:1px solid var(--border);display:flex;justify-content:flex-end;gap:8px;flex:none}
.drawer-foot .btn{flex:1;justify-content:center}
/* Conferência de pedido (renderPedidoRevisaoDetailPage): dados/checks/itens à esquerda em wizard de 2
   etapas, PDF fixo à direita, pra bater o que foi lido contra o documento sem trocar de janela. Página
   no corpo do site (não drawer). Empilha no vertical em tela estreita. */
.revisao-split{display:flex;gap:18px;align-items:flex-start}
.revisao-doc-col{flex:1 1 48%;min-width:0;position:sticky;top:0}
.revisao-info-col{flex:1 1 52%;min-width:0;display:flex;flex-direction:column;gap:16px}
.revisao-doc-frame{width:100%;height:74vh;border:1px solid var(--border);border-radius:10px;background:var(--surface);overflow:hidden;display:flex;align-items:center;justify-content:center}
.revisao-doc-frame iframe{width:100%;height:100%;border:0}
.revisao-doc-frame img{max-width:100%;max-height:100%;object-fit:contain}
/* Stepper de 2 etapas (Conferências → Revisão): replica docs/components/progress-bars-panels.html
   — barra segmentada com separador em seta/chevron SVG de altura cheia na borda direita de cada passo.
   Cores adaptadas aos tokens de tema do app (o componente original é dark/indigo fixo). */
.revisao-steps{display:flex;flex-direction:column;border:1px solid var(--border);border-radius:8px;overflow:hidden;margin-bottom:16px}
.revisao-steps>.revisao-step:not(:last-child){border-bottom:1px solid var(--border)}
.revisao-step{position:relative;display:flex;align-items:center}
.revisao-step-link{display:flex;align-items:center;width:100%;padding:16px 24px;min-width:0}
.revisao-step.done .revisao-step-link{cursor:pointer}
.revisao-step-num{box-sizing:border-box;flex:none;display:inline-flex;align-items:center;justify-content:center;width:40px;height:40px;border-radius:50%;font-size:13.5px;font-weight:600;transition:border-color .2s,background .2s,color .2s}
.revisao-step.upcoming .revisao-step-num{border:2px solid var(--border);color:var(--text-faint)}
.revisao-step.active .revisao-step-num{border:2px solid var(--accent);color:var(--accent)}
.revisao-step.done .revisao-step-num{background:var(--accent);color:var(--accent-contrast)}
.revisao-step.done .revisao-step-num svg{width:22px;height:22px}
.revisao-step-tt{display:flex;flex-direction:column;line-height:1.25;min-width:0;margin-left:16px}
.revisao-step-title{font-size:13.5px;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.revisao-step-sub{font-size:11.5px;font-weight:500;color:var(--text-faint);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.revisao-step.upcoming .revisao-step-title{color:var(--text-faint)}
.revisao-step.active .revisao-step-title{color:var(--accent)}
.revisao-step.done .revisao-step-title{color:var(--text)}
.revisao-step-arrow{display:none}
@media(min-width:768px){
  .revisao-steps{flex-direction:row}
  .revisao-steps>.revisao-step:not(:last-child){border-bottom:0}
  .revisao-step{flex:1}
  .revisao-step-arrow{display:block;position:absolute;top:0;right:0;width:20px;height:100%;pointer-events:none}
  .revisao-step-arrow svg{width:100%;height:100%;color:var(--border)}
}
@media(max-width:820px){.revisao-split{flex-direction:column}.revisao-doc-col{position:static;width:100%}.revisao-doc-frame{height:48vh}}

/* modal */
.modal{position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);width:380px;max-width:90vw;max-height:90vh;overflow-y:auto;background:var(--surface);border-radius:var(--radius-lg);box-shadow:var(--shadow-lg);z-index:103;padding:20px}
.modal-scrim{z-index:102}
.modal-lg{width:auto;max-width:95vw;max-height:92vh;overflow:auto}
/* Visualizador de mídia (itens 6 e 7): modal grande com imagem (zoom) ou PDF embutido + barra de ações. */
.modal.modal-media{width:92vw;max-width:1100px;height:90vh;max-height:90vh;padding:0;overflow:hidden;display:flex;flex-direction:column}
/* Imagem: largura acompanha a foto (altura manda, 90vh), com um mínimo só pra caber a barra de ações — evita
   o vazio lateral que a largura fixa deixava em fotos estreitas/retrato. PDF continua com a largura fixa. */
.modal.modal-media.modal-media-fit{width:auto;min-width:min(440px,92vw);max-width:min(1100px,92vw)}
.media-viewer{display:flex;flex-direction:column;height:100%}
.media-viewer-bar{display:flex;align-items:center;gap:8px;padding:10px 12px;border-bottom:1px solid var(--border);flex:none}
.media-viewer-imgwrap{flex:1;overflow:auto;display:flex;align-items:center;justify-content:center;background:var(--surface-2,#111);padding:8px}
.media-viewer-img{max-width:100%;max-height:100%;object-fit:contain;cursor:zoom-in}
.media-viewer-img.zoomed{max-width:none;max-height:none}
.media-viewer-pdf{flex:1;width:100%;border:0;background:#fff}
/* Visualizador de JSON (modal "ver JSON" do simulador de Fluxos): payload mandado pra IA + resposta crua,
   com realce de sintaxe. Cores derivadas dos tokens do tema (funcionam em claro e escuro). */
.json-view{background:var(--surface-2);border:1px solid var(--border);border-radius:8px;padding:12px 14px;margin:0;overflow:auto;max-height:46vh;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:12px;line-height:1.55;white-space:pre;tab-size:2}
.json-view .jk{color:var(--info)}
.json-view .js{color:var(--success)}
.json-view .jn{color:var(--warning)}
.json-view .jb{color:var(--danger)}
.json-view .jz{color:var(--text-faint)}
/* Modal curto (título + 1-2 combos + botões) que precisa deixar o dropdown do .combo escapar: o
   overflow-y:auto do .modal vira container de recorte (força overflow-x:auto junto) e corta a .combo-list
   position:absolute que desce abaixo do campo. Só usar em modal cujo conteúdo nunca é alto o bastante pra
   precisar de rolagem própria — senão volta o clip. */
.modal.modal-overflow-visible{overflow:visible}
/* backdrop animado para modais de alerta/confirmação (stat-icon + mensagem curta, sem campos):
   overlay escuro padrão (.scrim) + as mesmas formas subindo da tela de Login (.login-shape), só
   reaproveitando a keyframe loginShapeFloat já existente em vez de inventar uma nova. */
.modal-scrim-alert{overflow:hidden}
.modal-scrim-alert .scrim-shape{position:absolute;bottom:-150px;display:block;background:rgba(255,255,255,.16);border-radius:6px;animation:loginShapeFloat 22s linear infinite}
.modal-scrim-alert .scrim-shape:nth-child(1){left:6%;width:22px;height:22px;animation-delay:0s;animation-duration:20s}
.modal-scrim-alert .scrim-shape:nth-child(2){left:16%;width:14px;height:14px;animation-delay:2.5s;animation-duration:14s}
.modal-scrim-alert .scrim-shape:nth-child(3){left:28%;width:30px;height:30px;animation-delay:5s;animation-duration:24s}
.modal-scrim-alert .scrim-shape:nth-child(4){left:42%;width:58px;height:58px;animation-delay:0s;animation-duration:28s;border-radius:14px}
.modal-scrim-alert .scrim-shape:nth-child(5){left:56%;width:18px;height:18px;animation-delay:7s;animation-duration:16s}
.modal-scrim-alert .scrim-shape:nth-child(1){left:6%;width:22px;height:22px;animation-delay:11s;animation-duration:16s}
.modal-scrim-alert .scrim-shape:nth-child(6){left:66%;width:76px;height:76px;animation-delay:3s;animation-duration:32s;border-radius:18px}
.modal-scrim-alert .scrim-shape:nth-child(7){left:78%;width:24px;height:24px;animation-delay:10s;animation-duration:18s}
.modal-scrim-alert .scrim-shape:nth-child(8){left:88%;width:38px;height:38px;animation-delay:1s;animation-duration:26s}
.modal-scrim-alert .scrim-shape:nth-child(9){left:22%;width:16px;height:16px;animation-delay:12s;animation-duration:15s}
.modal-scrim-alert .scrim-shape:nth-child(10){left:50%;width:26px;height:26px;animation-delay:14s;animation-duration:21s}
@media (prefers-reduced-motion: reduce){.modal-scrim-alert .scrim-shape{animation:none;display:none}}

/* loading / error overlays (sempre acima de drawers e modais comuns) */
.loading-scrim{z-index:200}
.loading-modal{z-index:201;width:280px;text-align:center;display:flex;flex-direction:column;align-items:center;padding:30px 22px}
.spinner{width:32px;height:32px;border:3px solid var(--border-strong);border-top-color:var(--accent);border-radius:50%;animation:spin .8s linear infinite}
@keyframes spin{to{transform:rotate(360deg)}}
.icon-spin{animation:spin .6s linear infinite}
/* Spinner miúdo do tique "enviando" (item CONVERSAS 4): mesmo componente .spinner, tamanho de tique. */
.atd-msg-sending-spin{display:inline-block;width:11px;height:11px;border:1.5px solid var(--border-strong);border-top-color:var(--accent);border-radius:50%;animation:spin .8s linear infinite;vertical-align:middle}
@media (prefers-reduced-motion: reduce){.spinner{animation-duration:2.2s}}
.error-modal{z-index:202;background:var(--danger);color:#fff}
.error-modal .btn{background:rgba(255,255,255,.14);border-color:rgba(255,255,255,.3);color:#fff}
.error-modal .btn:hover{background:rgba(255,255,255,.24)}

/* ---- skeleton de carregamento (placeholder) ----------------------------------------------------------
   Componente ÚNICO de "o conteúdo ainda está vindo", no lugar do texto "Carregando...": blocos cinzas com
   a FORMA aproximada do que vai aparecer (linha de texto, avatar, miniatura, célula de tabela, bolha de
   mensagem), na linha do Flowbite Skeleton, com um brilho varrendo da esquerda pra direita (shimmer).
   Marcação sempre gerada pelos helpers skel*() do JS — nunca escrever .sk na mão numa tela, senão volta a
   ter N variantes divergentes do mesmo placeholder (ver diretriz de componentes únicos no CLAUDE.md).
   .skel = contêiner (role=status, com rótulo pra leitor de tela); .sk = um bloco. */
.skel{position:relative}
.sk{display:block;position:relative;overflow:hidden;background:var(--skel-bg);border-radius:var(--radius-sm);flex:none}
.sk::after{content:"";position:absolute;inset:0;transform:translateX(-100%);background:linear-gradient(90deg,transparent,var(--skel-glare),transparent);animation:skShimmer 1.6s infinite}
@keyframes skShimmer{100%{transform:translateX(100%)}}
/* Linha de texto: pílula, como o "rounded-full" da referência. .lg = título, .sm = legenda/metadado. */
.sk-line{height:9px;border-radius:999px;width:100%}
.sk-line.lg{height:12px}
.sk-line.sm{height:7px}
.sk-circle{border-radius:50%}
/* Área de imagem/mídia: bloco alto com o ícone da referência centralizado (z-index pra ficar acima do brilho). */
.sk-img{display:flex;align-items:center;justify-content:center;border-radius:var(--radius-md);color:var(--text-faint)}
.sk-img>svg{position:relative;z-index:1;opacity:.45}
.sk-rows{display:flex;flex-direction:column;gap:9px}
.sk-row{display:flex;align-items:center;gap:10px}
/* Coluna de texto que ocupa o resto da linha (ao lado de um avatar/miniatura). */
.sk-grow{flex:1 1 auto;min-width:0;display:flex;flex-direction:column;gap:7px}
/* Item de lista com divisória, como o "List placeholder" da referência. */
.sk-item{display:flex;align-items:center;gap:11px;padding:11px 0;border-bottom:1px solid var(--border)}
.sk-item:last-child{border-bottom:none}
.sk-card{border:1px solid var(--border);border-radius:var(--radius-lg);background:var(--surface);padding:14px}
/* Barras do "Widget placeholder" (gráfico): alturas variadas, arredondadas só no topo. */
.sk-bars{display:flex;align-items:flex-end;gap:12px;height:150px}
.sk-bars>.sk{flex:1 1 0;border-radius:var(--radius-sm) var(--radius-sm) 0 0}
/* Bolha de mensagem do chat: mesma geometria das bolhas reais (uma ponta reta, alternando o lado). */
.sk-bubble{border-radius:12px;max-width:72%}
.sk-bubble.in{border-bottom-left-radius:3px}
.sk-bubble.out{border-bottom-right-radius:3px;margin-left:auto}
/* Movimento reduzido: o brilho para, o bloco cinza continua marcando o lugar do conteúdo. */
@media (prefers-reduced-motion: reduce){.sk::after{animation:none;opacity:0}}

/* accordion */
.accordion{border:1px solid var(--border);border-radius:10px;overflow:hidden;margin-bottom:14px}
.accordion-head{display:flex;align-items:center;justify-content:space-between;padding:11px 14px;cursor:pointer;background:var(--surface-2);font-size:13px;font-weight:700}
.accordion-body{padding:14px;display:none;border-top:1px solid var(--border)}
.accordion-body.open{display:block}
.accordion-head .chev{transition:.15s}
.accordion-head[aria-expanded="true"] .chev{transform:rotate(90deg)}

/* tabs */
.tabs{display:flex;gap:4px;border-bottom:1px solid var(--border);margin-bottom:16px}
.tab{padding:9px 4px;margin-right:18px;font-size:13px;font-weight:600;color:var(--text-faint);border-bottom:2px solid transparent;cursor:pointer}
.tab.active{color:var(--accent);border-color:var(--accent)}

/* login: 2 colunas — formulário à esquerda (tema claro/escuro normal), branding animado à direita */
/* Login sempre no tema claro, independente do tema do app/SO — redeclara as variáveis claras
   (mesmos valores de :root[data-theme="light"]) no container, sobrescrevendo o que vem de :root. */
.login-wrap{position:fixed;inset:0;display:flex;
  --accent:#0050c3;--accent-hover:#003fa0;--accent-soft:#e6eefb;--accent-ring:rgba(0,80,195,.26);--accent-contrast:#fff;
  --accent-2:#1eb85a;--accent-2-soft:#e6f7ec;--accent-2-ring:rgba(30,184,90,.26);--brand-teal:#0050c3;--brand-salmon:#0050c3;--brand-salmon-strong:#003fa0;--brand-salmon-deep:#00306f;
  --bg:#f5f6f8;--surface:#ffffff;--surface-2:#fafbfc;--border:#e3e6ea;--border-strong:#d0d5db;
  --text:#171a1d;--text-soft:#5b6470;--text-faint:#8a93a0;
  --success:#15803d;--success-soft:#e7f6ec;--warning:#b45309;--warning-soft:#fdf1e1;
  --danger:#b91c1c;--danger-soft:#fbe9e9;--info:#e4600d;--info-soft:#fce9dd;
  --shadow-sm:0 1px 2px rgba(20,25,30,.06);--shadow-md:0 4px 16px rgba(20,25,30,.10);--shadow-lg:0 16px 48px rgba(20,25,30,.18);
  background:var(--bg);color:var(--text)}
.login-left{flex:0 0 55%;display:flex;align-items:center;justify-content:center;padding:32px}
.login-card{width:378px;max-width:100%;position:relative}
/* ===== Recusa do servidor, animada sobre o card (ver mostrarAnimacaoDeErro em private/app-login.html) =====
   Cobre o CARD, não a tela: o que foi recusado foi o formulário, e escurecer a página inteira por 3,4s
   trataria "senha errada" como incidente. O véu é leve e a caixa não intercepta clique nenhum
   (pointer-events:none no overlay inteiro) — quem já percebeu o erro volta a digitar durante a animação,
   sem esperar ela acabar. A mensagem de texto continua sendo quem informa: isto aqui é ênfase.
   O véu sai de var(--bg), e não de um cinza escrito na mão, porque .login-wrap redeclara a paleta CLARA
   acima (o login é sempre claro, de propósito): lendo o token, o véu acompanha o card sem precisar saber
   dessa decisão — e continuaria certo se um dia o login passar a seguir o tema. */
.login-anim{position:absolute;inset:0;z-index:3;display:flex;align-items:center;justify-content:center;
  pointer-events:none;background:color-mix(in srgb, var(--bg) 62%, transparent);border-radius:var(--radius-lg);
  animation:loginAnimEntra .18s ease-out}
.login-anim-box{width:132px;height:132px}
.login-anim-box svg{display:block;width:100%;height:100%}
@keyframes loginAnimEntra{from{opacity:0}to{opacity:1}}
/* Saída suave: some junto quando o quadro final chega, em vez de piscar pra fora. */
.login-anim.saindo{animation:loginAnimSai .22s ease-in forwards}
@keyframes loginAnimSai{from{opacity:1}to{opacity:0}}
@media (prefers-reduced-motion:reduce){
  /* Quem pediu menos movimento não recebe a animação (o JS nem carrega o player); a regra fica aqui como
     segunda tranca, pra o caso de o overlay ter sido montado antes da preferência ser lida. */
  .login-anim{display:none}
}
.login-mark{width:46px;height:46px;border-radius:13px;overflow:hidden;margin-bottom:16px}
.login-mark img{width:100%;height:100%;display:block}
.login-logo{margin-bottom:16px}
.login-logo img{height:34px;width:auto;display:block}
/* Ação secundária do card de login ("Esqueci minha senha", "Voltar ao login"): texto, não botão. Duas
   caixas iguais empilhadas fariam a pessoa parar pra ler qual é a de entrar. */
.login-link{background:none;border:0;padding:4px;cursor:pointer;color:var(--accent);font:inherit;font-size:13.5px;text-decoration:none}
.login-link:hover{text-decoration:underline}
.login-right{flex:0 0 45%;position:relative;overflow:hidden;display:flex;flex-direction:column;justify-content:center;padding:60px;background:linear-gradient(150deg, var(--brand-salmon-deep) 0%, var(--brand-salmon-strong) 55%, var(--brand-salmon) 100%)}
.login-right-brand{position:absolute;top:36px;left:44px;z-index:2;display:flex;align-items:center;gap:10px;color:#fff;font-weight:800;font-size:19px;font-family:var(--font-brand);letter-spacing:.3px}
.login-right-brand span{width:36px;height:36px;border-radius:10px;overflow:hidden;display:flex}
.login-right-brand span img{width:100%;height:100%;display:block}
.login-right-content{position:relative;z-index:2;max-width:440px}
.login-right-content h2{color:#fff;font-size:32px;font-weight:800;line-height:1.28;margin:0}
.login-right-content p{color:rgba(255,255,255,.72);font-size:14.5px;margin-top:14px;line-height:1.6}
/* Console do operador: só a CASCA é própria (barra de topo e a linha rótulo/valor da ficha). Tudo o que
   está dentro dela reaproveita os componentes do app — .stat-card, .table-wrap, .card, .badge, .btn, os
   esqueletos — porque um ajuste visual precisa valer nos dois lugares com uma mudança só. */
.op-console{min-height:100%;padding:0 clamp(14px,3vw,28px) 28px}
.op-head{display:flex;align-items:center;justify-content:space-between;gap:16px;flex-wrap:wrap;padding:14px 0}
.op-head-brand{display:flex;align-items:center;gap:8px;font-family:var(--font-brand);font-size:17px;color:var(--text)}
.op-head-right{display:flex;align-items:center;gap:12px}
.op-body{padding-top:2px}
.op-kv{display:flex;gap:16px;justify-content:space-between;align-items:baseline;padding:7px 0;border-bottom:1px solid var(--border)}
.op-kv:last-child{border-bottom:none}
.op-row{cursor:pointer}
.op-row:hover{background:var(--accent-soft)}
/* Faixa de acesso de suporte: mesma estrutura da faixa de conexão, outra cor. Âmbar e não vermelho porque
   não é falha, é uma condição temporária que o cliente precisa enxergar enquanto durar. */
.suporte-banner{background:var(--warning);color:#1a1206}
.suporte-banner-motivo{opacity:.85;font-style:italic}
@media (max-width:640px){.op-kv{flex-direction:column;gap:2px}}
.login-shapes{position:absolute;inset:0;overflow:hidden;z-index:1}
.login-shape{position:absolute;bottom:-150px;display:block;background:rgba(255,255,255,.16);border-radius:6px;animation:loginShapeFloat 22s linear infinite}
.login-shape:nth-child(1){left:6%;width:22px;height:22px;animation-delay:0s;animation-duration:20s}
.login-shape:nth-child(2){left:16%;width:14px;height:14px;animation-delay:2.5s;animation-duration:14s}
.login-shape:nth-child(3){left:28%;width:30px;height:30px;animation-delay:5s;animation-duration:24s}
.login-shape:nth-child(4){left:42%;width:58px;height:58px;animation-delay:0s;animation-duration:28s;border-radius:14px}
.login-shape:nth-child(5){left:56%;width:18px;height:18px;animation-delay:7s;animation-duration:16s}
.login-shape:nth-child(6){left:66%;width:76px;height:76px;animation-delay:3s;animation-duration:32s;border-radius:18px}
.login-shape:nth-child(7){left:78%;width:24px;height:24px;animation-delay:10s;animation-duration:18s}
.login-shape:nth-child(8){left:88%;width:38px;height:38px;animation-delay:1s;animation-duration:26s}
.login-shape:nth-child(9){left:22%;width:16px;height:16px;animation-delay:12s;animation-duration:15s}
.login-shape:nth-child(10){left:50%;width:26px;height:26px;animation-delay:14s;animation-duration:21s}
@keyframes loginShapeFloat{0%{transform:translateY(0) rotate(0deg);opacity:0}8%{opacity:.5}92%{opacity:.5}100%{transform:translateY(-115vh) rotate(720deg);opacity:0}}
@media (prefers-reduced-motion: reduce){.login-shape{animation:none;display:none}}
@media (max-width: 860px){.login-right{display:none}.login-left{flex:1}}

/* quick switch floating */
.qs{position:fixed;bottom:20px;right:20px;z-index:99;font-size:12.5px}
.qs-panel{background:var(--surface);border:1px solid var(--border-strong);border-radius:14px;box-shadow:var(--shadow-lg);padding:12px;width:230px}
.qs-pill{display:flex;align-items:center;gap:8px;background:var(--text);color:var(--bg);padding:9px 14px;border-radius:999px;box-shadow:var(--shadow-md);font-weight:700;cursor:pointer}

/* toast */
.toast-wrap{position:fixed;top:16px;right:16px;z-index:300;display:flex;flex-direction:column;gap:8px}
.toast{background:var(--text);color:var(--bg);padding:11px 16px;border-radius:10px;font-size:13px;font-weight:600;box-shadow:var(--shadow-lg);display:flex;align-items:center;gap:9px;animation:fade .15s ease;max-width:320px}
.toast.err{background:var(--danger)}
.toast.has-body{align-items:flex-start}
.toast-body{display:flex;flex-direction:column;gap:2px}
.toast-title{font-weight:700;font-size:13px}
.toast-desc{font-weight:500;font-size:12.5px;opacity:.85}
.toast-action{flex:none;margin-left:4px;background:transparent;border:1px solid currentColor;color:inherit;border-radius:7px;padding:5px 11px;font-size:12.5px;font-weight:700;cursor:pointer;opacity:.9}
.toast-action:hover{opacity:1;background:rgba(255,255,255,.12)}

/* empty state */
.empty{display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;padding:52px 20px;color:var(--text-faint)}
.empty svg{opacity:.5;margin-bottom:12px}
.empty .pulse-icon-circle svg{opacity:1}
.empty-title{font-weight:700;color:var(--text-soft);font-size:14px;margin-bottom:4px}

/* Ícone grande circular com pulso animado (halo em anel se expandindo) — usado em heros de estado
   "tudo certo/vazio" que merecem mais destaque que o .empty padrão (ícone de 40px opaco). currentColor
   no anel deixa a cor a cargo de quem usa (background/color via style inline, ver vaultLockedHeroHtml
   e atendimentoFilaEmptyHeroHtml). */
.pulse-icon-circle{width:88px;height:88px;border-radius:50%;display:flex;align-items:center;justify-content:center;margin-bottom:18px;animation:pulseRingHalo 2.4s ease-in-out infinite}
@keyframes pulseRingHalo{
  0%{box-shadow:0 0 0 0 color-mix(in srgb, currentColor 40%, transparent)}
  70%{box-shadow:0 0 0 20px color-mix(in srgb, currentColor 0%, transparent)}
  100%{box-shadow:0 0 0 0 color-mix(in srgb, currentColor 0%, transparent)}
}

/* cofre de senhas: tela de "protegido" (bloqueado) */
.vault-locked-hero{display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;padding:64px 20px}

.pixrow,.obsrow,.commrow,.leadmetarow{display:grid;gap:8px;align-items:end}
.pixrow .select,.pixrow .input,.obsrow .select,.obsrow .input,.commrow .select,.commrow .input,.autom-cond-row .select,.autom-cond-row .input,.leadmetarow .input{height:38px;padding-top:0;padding-bottom:0}
.pixrow .icon-btn,.obsrow .icon-btn,.commrow .icon-btn,.autom-cond-row .icon-btn,.leadmetarow .icon-btn{width:38px;height:38px;flex:none}
.autom-cond-row{display:grid;gap:8px;align-items:center}
.icon-btn{display:inline-flex;align-items:center;justify-content:center;width:30px;height:30px;border-radius:7px;border:1px solid var(--border-strong);background:var(--surface);color:var(--text-soft)}
.icon-btn:hover{background:var(--surface-2);color:var(--text)}
.icon-btn:disabled{opacity:.4;cursor:default;pointer-events:none}
#toggle-compact-btn,#expand-menu-btn{border:none;background:transparent}
#toggle-compact-btn:hover,#expand-menu-btn:hover{background:var(--surface-2)}
.icon-flip-x{transform:scaleX(-1)}
.icon-btn-plain{display:inline-flex;align-items:center;justify-content:center;gap:4px;width:auto;min-width:26px;/*height:36px;*/padding:0 6px;border-radius:8px;border:none;background:transparent;color:var(--text-soft);cursor:pointer;font-size:12px}
.icon-btn-plain:hover{background:var(--surface-2);color:var(--text)}
/* Linha de controles inline (botão/select/input lado a lado) com altura e alinhamento uniformes —
   reaproveitar sempre que houver esse padrão em vez de deixar cada um com sua altura intrínseca. */
.controls-row{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.controls-row .select,.controls-row .input{height:34px;padding-top:0;padding-bottom:0}
.controls-row .btn{height:34px;padding-top:0;padding-bottom:0}
.controls-row .icon-btn{width:34px;height:34px}
.admin-picker{position:relative;display:inline-block}
.admin-picker-trigger{display:flex;align-items:center;gap:6px;border:1px solid var(--border);border-radius:8px;padding:4px 8px;background:var(--surface);cursor:pointer;min-height:34px}
.admin-picker-trigger:hover{background:var(--surface-2)}
.admin-picker-trigger.trigger-multi{border:none;background:transparent;padding:2px;min-height:auto}
.admin-picker-trigger.trigger-multi:hover{background:transparent}
.admin-avatar{display:inline-flex;align-items:center;justify-content:center;border-radius:50%;background:var(--accent-soft);color:var(--accent);border:1px solid var(--accent);font-weight:700;flex:none}
.admin-avatar-stack{display:flex}
.admin-avatar-stack .admin-avatar{margin-left:-8px;border:1px solid var(--border-strong)}
.admin-avatar-stack .admin-avatar:first-child{margin-left:0}
.admin-avatar-add{background:var(--surface-2);color:var(--text-soft);border:1px solid var(--border-strong)}
.admin-avatar-stack .admin-avatar-add{border:1px solid var(--border-strong)}
/* Conteúdo do avatar (ver avatarContentHtml): foto ou círculo de cor de identidade cobrindo 100% do
   wrapper. O CSS de layout fica na classe, só a cor personalizada (background/color) vai inline. */
.avatar-img{width:100%;height:100%;border-radius:50%;object-fit:cover}
.avatar-fill{width:100%;height:100%;border-radius:50%;display:flex;align-items:center;justify-content:center}
/* Quando o avatar tem cor/foto próprias, o preenchimento cobre o círculo inteiro e a borda de destaque
   (--accent) do admin-avatar vira uma moldura que briga com a cor de identidade — some nesse caso. */
.admin-avatar:has(.avatar-fill),.admin-avatar:has(.avatar-img){border-color:transparent}
.admin-picker-empty{display:flex;align-items:center;gap:4px;font-size:12px;color:var(--text-faint)}
.admin-picker-name{font-size:12.5px;font-weight:600}
.admin-picker-panel{min-width:200px;max-height:240px;overflow-y:auto;background:var(--surface);border:1px solid var(--border);border-radius:10px;box-shadow:var(--shadow-md);z-index:200;padding:4px}
.admin-picker-row{display:flex;align-items:center;gap:8px;padding:6px 8px;border-radius:7px;cursor:pointer;font-size:13px}
.admin-picker-row:hover{background:var(--surface-2)}
.admin-picker-row.selected{background:var(--accent-soft)}
.admin-picker-row-name{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.admin-picker-check{color:var(--accent);display:flex;flex:none}
.notif-count-badge{min-width:15px;height:15px;padding:2px 5px;border-radius:4px;background:var(--danger);color:#fff;font-size:9px;font-weight:700;display:inline-flex;align-items:center;justify-content:center;line-height:1}
.notif-count-badge.zero{background:var(--surface-2);color:var(--text-faint);border:1px solid var(--border)}
.notif-count-badge.overlay{position:absolute;top:-3px;right:-3px}
.notif-count-badge.inline{background:transparent;color:inherit;border:1px solid currentColor}
.nav-alert-icon{color:var(--danger);display:flex;flex:none}
.nav-alert-icon.overlay{position:absolute;top:-3px;right:-3px}
.nav-alert-icon.inline{margin-left:auto}
/* Ícone do menu Atendimento quando há conversas não lidas (DB.atendimentoBadgeCount): cor de destaque
   e, a cada 6s, "redesenha" os traços do SVG via stroke-dashoffset — chama atenção sem piscar o tempo
   todo. dasharray 100 cobre o perímetro do ícone (comment). Respeita prefers-reduced-motion. */
.nav-icon-redraw{color:var(--accent)}
.nav-icon-redraw path,.nav-icon-redraw rect,.nav-icon-redraw circle{stroke-dasharray:100;animation:navIconRedraw 6s ease-in-out infinite}
@keyframes navIconRedraw{0%{stroke-dashoffset:100}14%{stroke-dashoffset:0}100%{stroke-dashoffset:0}}
/* Logo depois que o ícone termina de se redesenhar (14% do ciclo de 6s ≈ 0,84s), o badge de contagem
   pisca 2 vezes com ~300ms entre cada — mesmo ciclo/duração da animação do ícone, então as duas ficam
   sincronizadas (ambas começam quando o menu é renderizado). */
.nav-atd-active .notif-count-badge{animation:navBadgeBlink 6s ease-in-out infinite}
@keyframes navBadgeBlink{0%,14%{opacity:1}15.5%{opacity:0}17.5%{opacity:1}22.5%{opacity:0}24.5%{opacity:1}100%{opacity:1}}
@media (prefers-reduced-motion: reduce){.nav-icon-redraw path,.nav-icon-redraw rect,.nav-icon-redraw circle{animation:none}.nav-atd-active .notif-count-badge{animation:none}}
.divider{height:1px;background:var(--border);border:none;margin:16px 0}
/* Separador vertical discreto pra agrupar botões dentro de uma linha horizontal (.controls-row) —
   sem isso não existia um divisor vertical no projeto, só o .divider horizontal acima. */
.divider-v{width:1px;height:20px;background:var(--border);flex:none}
.grid-2{display:grid;grid-template-columns:1fr 1fr;gap:16px}
.grid-3{display:grid;grid-template-columns:repeat(3,1fr);gap:16px}
.grid-4{display:grid;grid-template-columns:repeat(4,1fr);gap:16px}
/* Filho de grid tem min-width:auto por padrão, o que impede encolher abaixo do min-content do conteúdo.
   Um SVG de gráfico (ApexCharts, min-content ~445px) então estoura a coluna e é cortado no mobile
   (body{overflow-x:hidden} clipa, sem scroll). min-width:0 libera o encolhimento pra caber no viewport;
   em desktop, onde há espaço, não muda nada. Corrige gráficos cortados em Relatórios (Financeiro,
   Representantes, Comissões) e em qualquer outro grid que venha a conter gráfico. */
.grid-2>*,.grid-3>*,.grid-4>*{min-width:0}
@media (max-width:1080px){.grid-3,.grid-4{grid-template-columns:repeat(2,1fr)}}
@media (max-width:720px){.grid-2,.grid-3,.grid-4{grid-template-columns:1fr}}
/* Grade de rótulo+valor (ficha somente-leitura). Diferente de .grid-2/3/4, o número de colunas não vem de
   media query e sim do espaço disponível (auto-fill), porque estes blocos vivem DENTRO de colunas de largura
   variável — um .grid-3 num trilho de 320px daria três colunas de 90px. Os filhos são o .field/.label de
   sempre, então rótulo fica em cima do valor: par rótulo-à-esquerda/valor-à-direita esticado por 1300px de
   viewport deixa de ler como par. */
.field-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(170px,1fr));gap:12px 20px}
.field-grid>*{min-width:0}
.field-grid .fv{font-size:12.5px;color:var(--text);overflow-wrap:anywhere}
.field-grid .label{font-size:10.5px;font-weight:700;letter-spacing:.04em;text-transform:uppercase;color:var(--text-faint)}
@media (max-width:720px){
  .home-stats-grid{grid-template-columns:repeat(2,1fr);gap:10px}
  .home-stats-grid .stat-card{padding:12px 14px;gap:6px}
  .home-stats-grid .stat-icon{width:26px;height:26px;border-radius:7px}
  .home-stats-grid .stat-value{font-size:18px}
  .home-stats-grid .stat-label{font-size:11px}
}
.section-title{font-size:14px;font-weight:700;margin-bottom:10px;display:flex;align-items:center;gap:7px}
/* ===== Matriz de variantes do produto (Fatia 1): chips de valores oferecidos + grade derivada ===== */
.pm-block{border:1px solid var(--border);border-radius:10px;padding:12px 14px;background:var(--surface)}
.pm-block .pm-h{display:flex;align-items:center;gap:8px;margin-bottom:9px}
.pm-block .pm-h .pm-n{font-size:13px;font-weight:700}
.pm-block .pm-h .pm-n .pm-tag{font-size:10.5px;font-weight:600;color:var(--text-faint);text-transform:uppercase;letter-spacing:.04em;margin-left:6px}
.pm-all{margin-left:auto;border:1px solid var(--border);background:var(--surface-2);color:var(--text-soft);border-radius:7px;padding:3px 9px;font-size:11.5px;cursor:pointer;font-family:inherit}
.pm-all:hover{color:var(--accent);border-color:var(--accent)}
.pm-chips{display:flex;flex-wrap:wrap;gap:7px}
.pm-chip{display:inline-flex;align-items:center;gap:7px;border:1px solid var(--border-strong);background:var(--surface);color:var(--text-faint);border-radius:999px;padding:5px 11px 5px 9px;font-size:12.5px;font-weight:600;cursor:pointer;transition:.12s}
.pm-chip:hover{border-color:var(--accent)}
.pm-chip.on{border-color:var(--accent);background:var(--accent-soft);color:var(--text)}
.pm-chip .pm-sw{width:14px;height:14px;border-radius:50%;flex:none;border:1px solid rgba(0,0,0,.18);box-shadow:inset 0 0 0 1px rgba(255,255,255,.15)}
.pm-chip:not(.on) .pm-sw{opacity:.4}
.pm-chip .pm-mod{font-size:10.5px;font-weight:700;color:var(--accent);background:var(--accent-soft);border-radius:5px;padding:0 5px}
.pm-summary{display:flex;align-items:center;gap:12px;flex-wrap:wrap;background:var(--surface-2);border:1px solid var(--border);border-radius:10px;padding:10px 14px}
.pm-summary .pm-big{font-size:22px;font-weight:800;font-variant-numeric:tabular-nums;line-height:1}
.pm-summary .pm-f{font-size:12.5px;color:var(--text-soft)}
.pm-summary .pm-f b{color:var(--text);font-variant-numeric:tabular-nums}
.pm-summary .pm-blk{color:var(--warning);font-weight:600}
.pm-grid-wrap{overflow-x:auto;border:1px solid var(--border);border-radius:10px}
.pm-grid{border-collapse:collapse;width:100%;min-width:760px;font-size:13px}
.pm-grid th{position:sticky;top:0;background:var(--surface-2);text-align:left;font-size:11px;font-weight:700;letter-spacing:.04em;text-transform:uppercase;color:var(--text-faint);padding:9px 10px;border-bottom:1px solid var(--border);white-space:nowrap}
.pm-grid td{padding:8px 10px;border-bottom:1px solid var(--border);vertical-align:middle}
.pm-grid tr:last-child td{border-bottom:none}
.pm-grid tbody tr:hover:not(.pm-row-blk){background:var(--surface-2)}
.pm-grid tr.pm-row-blk{opacity:.55}
.pm-grid .num{text-align:right;font-variant-numeric:tabular-nums}
.pm-combo{display:flex;align-items:center;gap:8px}
.pm-combo .pm-sw{width:12px;height:12px;border-radius:50%;flex:none;border:1px solid rgba(0,0,0,.18)}
.pm-sku{font-family:ui-monospace,Menlo,Consolas,monospace;font-size:12px}
.pm-flag{display:inline-flex;align-items:center;gap:4px;font-size:10.5px;font-weight:700;color:var(--warning);background:color-mix(in srgb,var(--warning) 15%,transparent);border-radius:5px;padding:1px 6px;cursor:help}
.pm-badge{display:inline-flex;align-items:center;gap:4px;font-size:10.5px;font-weight:700;padding:2px 7px;border-radius:999px}
.pm-badge.virtual{color:var(--text-faint);background:var(--surface-3)}
.pm-badge.saved{color:var(--success);background:color-mix(in srgb,var(--success) 14%,transparent)}
/* Célula editável da matriz (Fatia 2) */
.pm-grid .pm-check{width:34px;text-align:center}
.pm-cellinput{width:100%;border:1px solid transparent;background:transparent;color:var(--text);font-family:inherit;font-size:13px;border-radius:6px;padding:5px 7px;transition:.1s}
.pm-cellinput:hover{border-color:var(--border)}
.pm-cellinput:focus{outline:none;border-color:var(--accent);background:var(--surface);box-shadow:0 0 0 3px var(--accent-ring)}
.pm-cellinput.sku{font-family:ui-monospace,Menlo,Consolas,monospace;font-size:12px;max-width:170px}
.pm-cellinput.num{text-align:right;font-variant-numeric:tabular-nums}
.pm-price{position:relative;max-width:130px}
.pm-price .pm-rs{position:absolute;left:8px;top:50%;transform:translateY(-50%);font-size:11px;color:var(--text-faint);pointer-events:none}
.pm-price .pm-cellinput{padding-left:22px}
.pm-price.ovr .pm-cellinput{color:var(--accent);font-weight:700}
.pm-price .pm-dot{position:absolute;right:1px;top:3px;width:6px;height:6px;border-radius:50%;background:var(--accent);display:none}
.pm-price.ovr .pm-dot{display:block}
.pm-toggle{position:relative;width:36px;height:20px;border-radius:999px;background:var(--border-strong);cursor:pointer;border:none;flex:none;transition:.15s}
.pm-toggle::after{content:"";position:absolute;top:2px;left:2px;width:16px;height:16px;border-radius:50%;background:#fff;transition:.15s;box-shadow:0 1px 2px rgba(0,0,0,.3)}
.pm-toggle.on{background:var(--success)}
.pm-toggle.on::after{left:18px}
.pm-grid tr.pm-inactive td:not(.pm-check):not(.pm-combo-td){opacity:.45}
.pm-bulk{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-bottom:10px}
.pm-bulk .pm-lbl{font-size:11px;font-weight:700;letter-spacing:.05em;text-transform:uppercase;color:var(--text-faint)}
.pm-l2{font-size:11px;color:var(--text-faint);margin-top:1px;display:flex;align-items:center;gap:6px}
.pm-stock{display:inline-flex;align-items:center;gap:7px;justify-content:flex-end}
.pm-stock-vals{display:inline-flex;flex-direction:column;align-items:flex-end;line-height:1.12}
.pm-stock-n{font-variant-numeric:tabular-nums;font-weight:600}
.pm-stock-n.low{color:var(--danger)}
.pm-stock-min{font-size:10px;color:var(--text-faint);font-weight:500}
button.pm-stock-btn{border:1px solid transparent;background:transparent;cursor:pointer;font-family:inherit;color:inherit;border-radius:7px;padding:3px 7px;transition:.1s}
button.pm-stock-btn:hover{border-color:var(--border-strong);background:var(--surface)}
.pm-stock-ic{color:var(--text-faint);display:inline-flex}
button.pm-stock-btn:hover .pm-stock-ic{color:var(--accent)}
/* Fotos (Fatia 4): galeria do produto + miniaturas de variante/listagem */
.pg-gallery{display:flex;flex-wrap:wrap;gap:12px}
.pg-thumb{position:relative;width:120px;height:120px;border-radius:10px;overflow:hidden;border:1px solid var(--border);background:var(--surface-2)}
.pg-thumb img{width:100%;height:100%;object-fit:cover;display:block}
.pg-thumb .pg-capa{position:absolute;top:6px;left:6px;background:var(--accent);color:#fff;font-size:10px;font-weight:700;padding:1px 7px;border-radius:999px;letter-spacing:.03em}
.pg-thumb .pg-acts{position:absolute;inset:auto 0 0 0;display:flex;gap:4px;justify-content:center;padding:6px;background:linear-gradient(to top,rgba(0,0,0,.62),transparent);opacity:0;transition:.12s}
.pg-thumb:hover .pg-acts{opacity:1}
.pg-thumb .pg-acts button{border:none;background:rgba(255,255,255,.92);color:#111;border-radius:6px;padding:3px 8px;font-size:11px;font-weight:600;cursor:pointer}
.pg-thumb .pg-acts button:hover{background:#fff}
.pm-vthumb{width:34px;height:34px;border-radius:8px;object-fit:cover;border:1px solid var(--border);background:var(--surface-2);flex:0 0 auto;cursor:pointer;display:block}
/* Placeholder de foto da variante: borda tracejada + ícone esmaecido (fiel ao protótipo, coluna Foto própria).
   NÃO reusar a classe utilitária global `.empty` (empty-state com padding:52px) — ela estica o thumb e some o
   ícone; por isso o modificador é `.ph`. */
.pm-vthumb.ph{display:inline-flex;align-items:center;justify-content:center;color:var(--text-faint);border-style:dashed;border-color:var(--border-strong)}
.pm-vthumb.ph svg{flex:none}
.pm-vthumb.ro{cursor:default}
.pm-grid .pm-col-img{width:46px}
.pm-grid .pm-img-td{width:46px}
.prod-thumb{width:34px;height:34px;border-radius:7px;object-fit:cover;border:1px solid var(--border);background:var(--surface-2);flex:0 0 auto;display:block}
.prod-thumb.ph{display:inline-flex;align-items:center;justify-content:center;color:var(--text-faint)}
.pm-lil{border:1px solid var(--border-strong);background:transparent;color:var(--text-faint);border-radius:999px;padding:1px 8px;font-size:10.5px;font-weight:600;cursor:pointer;transition:.1s;display:inline-flex;align-items:center;gap:4px}
.pm-lil:hover{border-color:var(--accent);color:var(--text)}
.pm-lil.on{border-color:var(--success);color:var(--success);background:color-mix(in srgb,var(--success) 12%,transparent)}
.pm-regra-link{font-size:11px;color:var(--accent);text-decoration:underline;cursor:pointer;margin-left:6px}
.pg-thumb[draggable=true]{cursor:grab}
.pg-thumb.pg-drag{opacity:.4}
.pg-thumb.pg-over{outline:2px dashed var(--accent);outline-offset:2px}
.pm-eixord{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin-bottom:2px}
.pm-eixord-lbl{font-size:11px;font-weight:700;letter-spacing:.04em;text-transform:uppercase;color:var(--text-faint)}
.pm-eixord-chips{display:flex;gap:8px;flex-wrap:wrap}
.pm-eixord-chip{display:inline-flex;align-items:center;gap:6px;border:1px solid var(--border-strong);background:var(--surface);border-radius:8px;padding:4px 10px;font-size:12.5px;font-weight:600;cursor:grab}
.pm-eixord-chip:hover{border-color:var(--accent)}
.pm-eixord-chip.pg-drag{opacity:.4}
.pm-eixord-chip .pm-grip{color:var(--text-faint);font-size:12px;letter-spacing:-2px}
/* Eixos de variação como pílulas (fiel ao protótipo): caixa de check + nome + "N valores"; pressionada em
   cor de marca. O <input> real fica escondido dentro do <label> pra activeEixos()/checkboxGroupValues e o
   wiring de change continuarem valendo sem tocar na lógica de salvar. */
.pm-axisrow{display:flex;flex-wrap:wrap;gap:8px}
.pm-axis{display:inline-flex;align-items:center;gap:8px;border:1px solid var(--border-strong);background:var(--surface);color:var(--text);border-radius:10px;padding:8px 12px;font-size:13px;font-weight:600;cursor:pointer;user-select:none;transition:.12s}
.pm-axis:hover{border-color:var(--accent)}
.pm-axis input{position:absolute;opacity:0;width:0;height:0;pointer-events:none}
.pm-axis-check{width:16px;height:16px;border-radius:5px;border:1.5px solid var(--border-strong);display:grid;place-items:center;flex:none;transition:.12s;color:transparent}
.pm-axis-check svg{width:12px;height:12px}
.pm-axis-count{font-size:11px;font-weight:600;color:var(--text-faint)}
/* O <input> real é invisível (position:absolute;opacity:0), então quem navega por teclado não veria onde
   está: o anel de foco é desenhado na PÍLULA, que é o controle que a pessoa enxerga. */
.pm-axis:has(input:focus-visible){outline:2px solid var(--accent);outline-offset:2px}
.pm-axis:has(input:checked){border-color:var(--accent);background:var(--accent-soft);color:var(--accent)}
.pm-axis:has(input:checked) .pm-axis-check{background:var(--accent);border-color:var(--accent);color:var(--accent-contrast)}
.pm-axis:has(input:checked) .pm-axis-count{color:var(--accent)}
/* Legenda da grade (fiel ao protótipo): explica virtual/materializada/override/bloqueada abaixo da tabela. */
.pm-legend{display:flex;flex-wrap:wrap;gap:16px;font-size:12px;color:var(--text-soft);margin-top:12px}
.pm-leg-it{display:inline-flex;align-items:center;gap:6px}
.pm-leg-k{width:11px;height:11px;border-radius:3px;flex:none;background:var(--accent)}
/* Coluna GTIN/EAN editável na linha (mesma célula-input do SKU, sem monoespaço largo demais). */
.pm-cellinput.pm-gtin{max-width:150px}
.disabled-note{display:flex;align-items:center;gap:8px;background:var(--surface-2);border:1px dashed var(--border-strong);border-radius:10px;padding:12px 14px;color:var(--text-faint);font-size:12.5px}
.perm-matrix td,.perm-matrix th{text-align:center}
.perm-matrix td:last-child,.perm-matrix th:last-child{text-align:left}
.perm-matrix th:not(:last-child),.perm-matrix td:not(:last-child){width:44px;padding-left:4px;padding-right:4px}
.perm-matrix input[type=checkbox]{width:16px;height:16px;accent-color:var(--accent)}
.perm-cb-all-row td{background:var(--surface-2);border-bottom:2px solid var(--border-strong);font-weight:600}
.perm-matrix .perm-special-row td{padding-top:2px;padding-bottom:6px}
.perm-matrix .perm-group-row td{font-size:11px;text-transform:uppercase;letter-spacing:.05em;color:var(--text-faint);font-weight:700;background:var(--surface-2)}

/* ---- Editor de Fluxos de Chatbot (Drawflow) — segue as mesmas variáveis do resto do app, em vez do
   visual padrão da lib, pra parecer parte do sistema e não um widget colado por fora. ---- */
#chatbot-flow-canvas-wrap{position:relative;cursor:grab}
#chatbot-flow-canvas-wrap.flow-panning{cursor:grabbing}
#chatbot-flow-canvas-wrap.flow-panning *:not(.input):not(.output){cursor:grabbing!important}
#chatbot-flow-canvas{position:relative;background:var(--surface-2);background-image:radial-gradient(var(--border-strong) 1px, transparent 1px);background-size:18px 18px}
/* --flow-node-color: identidade visual por tipo (ver FLOW_NODE_TYPES/addNode em public/index.html —
   o "tipo" já vira uma classe CSS no próprio nó via Drawflow addNode(className)), reaproveitando as
   mesmas variáveis semânticas do resto do app (--info/--warning/--danger) em vez de cores novas soltas. */
#chatbot-flow-canvas .drawflow-node{--flow-node-color:var(--accent);background:var(--surface);border:1px solid var(--flow-node-color);border-radius:12px;box-shadow:0 1px 3px rgba(0,0,0,.08);padding:0;min-width:180px;color:var(--text);cursor:grab}
/* Gatilho/Executar Manualmente: os 2 nós fixos do fluxo (FLOW_NODE_TYPES, fixed:true) — só dá pra
   ligar/desligar (data.ativo), nunca excluir (ver flowNodeActionsHtml/protectFixedTriggerNodes), por
   isso ficam numa cor neutra própria, fora da paleta de cores dos demais tipos. */
#chatbot-flow-canvas .drawflow-node.trigger,#chatbot-flow-canvas .drawflow-node.manualTrigger{--flow-node-color:#000}
#chatbot-flow-canvas .drawflow-node.text,#chatbot-flow-canvas .drawflow-node.buttonMessage,#chatbot-flow-canvas .drawflow-node.textCapture,#chatbot-flow-canvas .drawflow-node.sendTemplate{--flow-node-color:#4281FF}
#chatbot-flow-canvas .drawflow-node.delay{--flow-node-color:#475569}
#chatbot-flow-canvas .drawflow-node.condition{--flow-node-color:#ff8a00}
#chatbot-flow-canvas .drawflow-node.action{--flow-node-color:var(--danger)}
#chatbot-flow-canvas .drawflow-node.consulta{--flow-node-color:var(--info)}
#chatbot-flow-canvas .drawflow-node.aiAgent{--flow-node-color:#0f5c5b}
#chatbot-flow-canvas .drawflow-node.transferAtendimento{--flow-node-color:#7c3aed}
#chatbot-flow-canvas .drawflow-node.endSession{--flow-node-color:#475569}
#chatbot-flow-canvas .drawflow-node.selected{border-color:var(--flow-node-color);box-shadow:0 0 0 2px color-mix(in srgb, var(--flow-node-color) 25%, transparent)}
/* Botão "x" nativo do Drawflow (aparece sobre nó/conexão selecionado por clique direito) — a exclusão já
   tem caminho próprio (tecla Delete, ver protectFixedTriggerNodes), esse "x" solto só ficava competindo
   visualmente sem função clara pro usuário. */
#chatbot-flow-canvas .drawflow-delete{display:none}
/* Borda já sai colorida na cor do tipo (--flow-node-color, herdada da regra base acima), mesmo sem
   hover; no hover só engrossa via box-shadow (não border-width, que mudaria o box e deslocaria o
   layout) — mesmo truque do halo de .selected acima, só que mais fino pra diferenciar hover de seleção. */
#chatbot-flow-canvas .drawflow-node:not(.selected):hover{box-shadow:0 0 0 1px var(--flow-node-color)}
/* .input colide de propósito com a classe genérica de campo de formulário (.input{width:100%;padding:9px 11px}
   na linha ~123) — mesmo nome, contextos diferentes. Sem zerar padding aqui, o box-sizing:border-box
   força a bolinha a crescer até caber o padding herdado (26x22 em vez de 14x14), só nela — .output não
   colide com nada, por isso só a de entrada ficava maior.
   top/left/right: o drawflow.min.css base vem com valores pensados pro node de demonstração da lib
   (padding:15px, outra largura) — aqui zeram tudo (cai na posição estática do próprio flex) e
   margin-left:-7px (metade da largura de 14px) puxa a bolinha pra ficar centrada EM CIMA da borda do
   card (metade dentro, metade fora), não flutuando solta ao lado dela (conferido via
   getBoundingClientRect: sem isso sobrava ~12px de vão entre a bolinha e a borda). flex-shrink:0 evita
   o flex do node (.drawflow-node{display:flex}) espremer a bolinha em vez de só encolher o conteúdo. */
/* --flow-port-size controla width/height/margin-left juntos por uma única variável — nunca dois
   valores literais separados, pra width e height não poderem divergir entre si (aspect-ratio:1/1 é o
   reforço extra: trava a bolinha em quadrado mesmo se o layout flex do node arredondar os dois eixos de
   forma diferente ao reflow, o que acontecia visivelmente ao arrastar o card de lugar). */
#chatbot-flow-canvas .drawflow-node .input,#chatbot-flow-canvas .drawflow-node .output{--flow-port-size:14px;width:var(--flow-port-size);height:var(--flow-port-size);aspect-ratio:1/1;padding:0;box-sizing:border-box;flex-shrink:0;position:relative;top:0;left:auto;right:auto;margin-left:calc(var(--flow-port-size) / -2);background:var(--surface);border:2px solid var(--flow-node-color)}
/* Bolinha preenchida (hover ou vínculo ativo, ver .linked abaixo): cor sólida var(--accent), a mesma
   do path (linha ~697) — sem degrade (tentado antes, tanto na borda quanto no preenchimento, mas saía
   invertido visualmente) e sem --flow-node-color aqui, só a cor da linha mesmo. Sem borda + bolinha 2px
   maior (via --flow-port-size) sinaliza o estado ativo; margin-left recalcula sozinho (mesma variável)
   pra crescer centrada em cima da borda do card, não só pra um lado. */
#chatbot-flow-canvas .drawflow-node .output:hover,
#chatbot-flow-canvas .drawflow-node .input:hover{--flow-port-size:16px;background:var(--accent);border:none}
/* Vínculo ativo (tem pelo menos 1 conexão) preenche a bolinha permanentemente, não só no hover — ver
   updateChatbotFlowPortLinkedStates, chamada depois de toda mutação do grafo (criar/mover nó, criar/
   remover conexão, desfazer/refazer) porque o Drawflow não marca isso sozinho em lugar nenhum do DOM. */
#chatbot-flow-canvas .drawflow-node .output.linked,
#chatbot-flow-canvas .drawflow-node .input.linked{--flow-port-size:16px;background:var(--accent);border:none}
/* marker-end (item FLUXOS 2): setinha na PONTA DE ENTRADA de cada conexão, logo antes da bolinha do nó
   destino. Só na entrada porque a conexão sempre vai da saída (output) pro input, então marker-end é sempre
   a ponta que chega no nó de baixo — nunca a de saída (marker-start, não usado). O <marker> é definido uma
   vez num <defs> escondido dentro do editor (ver renderChatbotFlowEditor) e referenciado por id; refX puxa
   a ponta ~8px pra trás pra não ficar por baixo da bolinha. */
#chatbot-flow-canvas .connection .main-path{stroke:var(--accent);stroke-width:2px;marker-end:url(#flow-conn-arrow)}
#chatbot-flow-canvas .connection .point{stroke:var(--accent);fill:var(--surface)}
/* Linha de preview enquanto o usuário arrasta a partir de uma porta de ENTRADA (ver
   wireChatbotFlowReverseConnect) — o Drawflow nativo só desenha esse feedback ao arrastar a partir da
   saída. Pra ficar com o MESMO estilo (curva e traço) da conexão real e do preview nativo, o path
   ganha as mesmas classes "connection"/"main-path" que o Drawflow usa (ver drawConnection na lib),
   herdando a regra de cima em vez de duplicar stroke/width numa regra própria.
/* Ícones de (+) inserir nó / (lixeira) excluir vínculo, cada um num ponto diferente ao longo da curva
   de uma conexão existente, ao passar o mouse nela — ver wireChatbotFlowConnectionHover. Ficam em
   #flow-connection-hover-layer dentro de #overlay-host (direto em document.body, junto de
   drawer/modal/actions-dropdown), não dentro do canvas: como .drawflow tem transform (pan/zoom),
   position:fixed DENTRO dele viraria relativo a ele em vez da viewport — fora, os pt.x/pt.y calculados
   via getScreenCTM (já em coordenada de tela) valem direto. Dois botões soltos (não uma pílula com os
   dois juntos) pra ficarem distribuídos na linha, cada um seguindo seu próprio ponto do path. */
/* Fica na cor do próprio path (var(--accent), mesma do stroke da conexão) em repouso, com fundo neutro
   — no hover inverte/preenche: fundo vira a cor cheia e o ícone vira branco. data-flow-conn-del (lixeira)
   segue a mesma lógica só que em var(--danger), nunca a mesma cor do botão de inserir. */
/* --fz (setado inline por botão, ver showOverlay em wireChatbotFlowConnectionHover) é o zoom ATUAL do
   canvas — sem isso os botões ficavam do mesmo tamanho de tela sempre, desproporcionais quando o resto
   do fluxo encolhe/cresce com o zoom. scale() (não width/height) porque redimensiona ícone+borda+padding
   juntos a partir do mesmo box de 24px, sem precisar recalcular cada propriedade separada. */
.flow-conn-action-btn{position:fixed;transform:translate(-50%,-50%) scale(var(--fz,1));z-index:160;width:24px;height:24px;box-shadow:0 1px 4px rgba(0,0,0,.3);transition:transform .12s ease,box-shadow .12s ease,background .12s ease,color .12s ease;border-color:var(--accent);color:var(--accent)}
.flow-conn-action-btn:hover{transform:translate(-50%,-50%) scale(calc(var(--fz,1) * 1.18));box-shadow:0 2px 8px rgba(0,0,0,.4);background:var(--accent);color:var(--accent-contrast)}
.flow-conn-action-btn[data-flow-conn-del]{border-color:var(--danger);color:var(--danger)}
.flow-conn-action-btn[data-flow-conn-del]:hover{background:var(--danger);color:#fff}
.flow-node-card{position:relative;padding:10px 12px;font-size:12.5px;max-width:220px}
.flow-node-card-off{opacity:.55}
.flow-node-actions{position:absolute;top:-14px;right:6px;display:flex;gap:4px;opacity:0;transition:.12s;pointer-events:none}
.drawflow-node:hover .flow-node-actions,.drawflow-node.selected .flow-node-actions{opacity:1;pointer-events:auto}
.flow-node-actions .icon-btn{width:24px;height:24px;background:var(--surface);box-shadow:0 1px 4px rgba(0,0,0,.2)}
.flow-node-actions .icon-btn[data-flow-node-info].active{background:var(--info);color:#fff;border-color:var(--info)}
.flow-node-card .flow-node-title{display:flex;align-items:center;gap:6px;font-weight:700;font-size:12px;margin-bottom:3px;color:var(--flow-node-color)}
/* Badge de gatilho desligado (trigger/manualTrigger com data.ativo===false) — fica ABAIXO do título
   (não mais inline nele), outline vermelho (não preenchido, pra não competir visualmente com o
   .flow-node-card-off já esmaecendo o card inteiro) com ícone de "desconectado". */
.flow-node-off-badge{display:inline-flex;align-items:center;gap:4px;font-size:10.5px;font-weight:700;color:var(--danger);border:1px solid var(--danger);border-radius:999px;padding:2px 8px;margin-bottom:6px}
/* Footer de documentação livre do nó (toggle pelo ícone de info em .flow-node-actions) — paleta clara/
   neutra e discreta de propósito (var(--surface-2)/var(--text-faint), mesmo par usado em qualquer nota
   secundária do app), não a cor de destaque var(--info) usada antes: é uma anotação de bastidor pro
   time, não devia competir visualmente com o conteúdo real do nó. Fonte pequena (9px) e padding/
   line-height enxutos pelo mesmo motivo — ocupa o mínimo de espaço no card. Sangra até a borda do
   card (margin negativo cancelando o padding lateral/inferior de 12px/10px do .flow-node-card, ver
   regra acima) em vez de ficar recuado como o resto do conteúdo — sempre o ÚLTIMO elemento do card, então
   o raio de baixo (11px = 12px do .drawflow-node menos a borda de 1px, pra encaixar sem sobrar friso)
   fecha a esquina com o cantinho arredondado do nó por baixo dele. Some/aparece sem afetar o resto do
   card (position normal, empurra a altura do nó — Drawflow remede a conexão sozinho, ver
   chatbotFlowRedrawAllConnections). */
.flow-node-doc-footer{margin:5px -12px -10px -12px;padding:5px 12px;border-radius:0 0 11px 11px;background:var(--surface-2);color:var(--text-faint);font-size:9px;line-height:1.25;white-space:pre-wrap}
/* drawflow.min.css tem a regra ".drawflow svg{position:absolute}" pensada só pro svg de conexões que a
   própria lib desenha — como é um seletor descendente genérico, ela também pega qualquer <svg> dentro
   do conteúdo custom do nó (nosso ícone de título), tirando ele do fluxo do flex e empilhando por cima
   do texto. #chatbot-flow-canvas dá especificidade suficiente pra vencer sem precisar de !important. */
#chatbot-flow-canvas .flow-node-card svg{position:static;flex:none}
.flow-node-card .flow-node-body{color:var(--text-soft);font-size:11.5px;line-height:1.5;word-break:break-word}
.flow-node-card .flow-node-options{display:flex;flex-direction:column;gap:5px;margin-top:6px}
.flow-node-card .flow-node-option{padding:6px 10px;border-radius:8px;background:var(--surface-2);border:1px solid var(--border)}
/* Card do nó Condição — visual dedicado (não usa flow-node-title/flow-node-body genéricos): descrição
   livre (editada via textarea no drawer, ver openFlowConditionDrawer), badge "Se: <resumo>", e as duas
   linhas de saída fixas (sempre a mesma altura, texto estático) que servem de referência pra alinhar as
   bolinhas output_1/output_2 — ver syncFlowNodePortRows. Nunca ficam sobrepostas: cada uma alinha com
   sua própria linha. */
.flow-condition-desc{font-size:11.5px;color:var(--text-soft);margin-bottom:8px;cursor:pointer;line-height:1.4;overflow:hidden;text-overflow:ellipsis;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical}
.flow-condition-desc:hover{color:var(--flow-node-color)}
.flow-condition-se-row{display:flex;align-items:center;gap:8px;border:1px solid var(--border);border-radius:8px;padding:6px 10px;margin-bottom:10px;cursor:pointer;background:var(--surface-2)}
.flow-condition-se-row:hover{border-color:var(--flow-node-color)}
.flow-condition-se-badge{flex:none;font-size:9.5px;font-weight:800;text-transform:uppercase;letter-spacing:.02em;color:var(--text-faint);background:var(--surface);border:1px solid var(--border);border-radius:999px;padding:2px 8px}
.flow-condition-se-text{font-size:11.5px;color:var(--text-soft);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.flow-condition-outcome-row{display:flex;align-items:center;justify-content:space-between;gap:8px;border:1px solid var(--border);border-radius:8px;padding:7px 10px;margin-bottom:8px;font-size:11.5px;cursor:pointer}
.flow-condition-outcome-row:hover{border-color:var(--border-strong)}
.flow-condition-outcome-yes{color:var(--success)}
.flow-condition-outcome-no{color:var(--danger)}
.flow-condition-outcome-icon{width:16px;height:16px;border-radius:50%;display:flex;align-items:center;justify-content:center;flex:none;color:#fff}
.flow-condition-outcome-yes .flow-condition-outcome-icon{background:var(--success)}
.flow-condition-outcome-no .flow-condition-outcome-icon{background:var(--danger)}
.flow-condition-configure-btn{width:100%;justify-content:center;margin-bottom:8px}
.flow-condition-warning{font-size:11px;line-height:1.4;background:var(--warning-soft);color:var(--warning);border-radius:8px;padding:8px 10px;display:flex;gap:6px;align-items:flex-start}
.flow-condition-warning svg{flex:none;margin-top:1px}
/* Drawflow, por padrão, centraliza .output_1/.output_2/... empilhados no meio do nó inteiro (ver
   syncFlowNodePortRows) — sem relação nenhuma com o conteúdo. Tanto no nó Condição (Atende/Não atende)
   quanto no de Mensagem com Botões (uma saída por opção "N) Label") cada saída precisa ficar na altura
   exata da sua própria linha, nunca uma sobre a outra, então aqui vira position:absolute (a JS calcula
   e escreve o `top` de cada uma) em vez do empilhamento automático. */
#chatbot-flow-canvas .drawflow-node.condition .outputs,
#chatbot-flow-canvas .drawflow-node.buttonMessage .outputs,
#chatbot-flow-canvas .drawflow-node.consulta .outputs{position:static;height:auto}
#chatbot-flow-canvas .drawflow-node.condition .output,
#chatbot-flow-canvas .drawflow-node.buttonMessage .output,
#chatbot-flow-canvas .drawflow-node.consulta .output{position:absolute;right:-7px;left:auto;margin:0}
.flow-palette-item{display:flex;align-items:center;gap:8px;padding:9px 10px;border:1px solid var(--border);border-radius:10px;background:var(--surface);cursor:grab;font-size:12.5px;font-weight:600;user-select:none}
.flow-palette-item:hover{border-color:currentColor}
.flow-palette-item-label{display:flex;flex-direction:column;gap:1px;min-width:0}
.flow-palette-item-hint{font-size:10px;font-weight:500;color:var(--text-faint)}
/* Barra de ferramentas do editor (topo) e barra flutuante de zoom/tela cheia (rodapé do canvas) —
   layout pedido explicitamente pra imitar a referência visual do editor de fluxo (undo/redo + salvar +
   alerta de não-salvo à esquerda, nome do fluxo à direita; tela cheia + zoom centralizados no rodapé). */
.flow-toolbar{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:8px 12px;margin-bottom:12px;background:var(--surface);border:1px solid var(--border);border-radius:12px;flex-wrap:wrap}
.flow-toolbar-left,.flow-toolbar-right{display:flex;align-items:center;gap:6px}
.flow-toolbar-sep{width:1px;height:22px;background:var(--border);margin:0 2px;flex:none}
.flow-toolbar-alert{display:flex;align-items:center;gap:5px;color:var(--warning);font-size:12.5px;font-weight:600;margin-left:4px}
.flow-toolbar-name{font-weight:700;font-size:13.5px}
.icon-btn:disabled{opacity:.4;cursor:not-allowed}
.icon-btn:disabled:hover{background:var(--surface);color:var(--text-soft)}
.flow-footer{position:absolute;left:50%;bottom:12px;transform:translateX(-50%);z-index:5;display:flex;gap:4px}
.flow-footer .icon-btn{width:28px;height:28px;background:var(--surface);box-shadow:0 1px 4px rgba(0,0,0,.2)}
/* Agendamentos (calendário) */
.agenda-legend{display:flex;flex-wrap:wrap;gap:14px;margin-bottom:12px;font-size:12.5px;color:var(--text-soft)}
.agenda-legend-item{display:inline-flex;align-items:center;gap:6px}
.agenda-dot{width:8px;height:8px;border-radius:50%;display:inline-block;flex:none}
.agenda-layout{display:grid;grid-template-columns:minmax(0,1.4fr) minmax(0,1fr);gap:16px;align-items:start}
@media (max-width:820px){.agenda-layout{grid-template-columns:1fr}}
.agenda-cal{padding:12px}
.agenda-cal-head{display:flex;align-items:center;justify-content:space-between;margin-bottom:8px}
.agenda-cal-title{font-weight:700;font-size:14.5px}
.agenda-grid{display:grid;grid-template-columns:repeat(7,1fr);gap:4px}
.agenda-weekday{text-align:center;font-size:11px;font-weight:600;color:var(--text-soft);padding:4px 0}
.agenda-days .agenda-cell{min-height:56px;border:1px solid var(--border);border-radius:8px;padding:5px 6px;display:flex;flex-direction:column;gap:4px;position:relative}
.agenda-cell-empty{border:none;background:transparent}
.agenda-cell.has-items{cursor:pointer;border-color:var(--accent)}
.agenda-cell.has-items:hover{background:var(--accent-soft)}
.agenda-cell.selected{background:var(--accent-soft);border-color:var(--accent);box-shadow:0 0 0 1px var(--accent) inset}
.agenda-cell.today .agenda-daynum{color:var(--accent);font-weight:800}
.agenda-daynum{font-size:12.5px;font-weight:600}
.agenda-dots{display:flex;align-items:center;gap:3px;flex-wrap:wrap}
.agenda-more{font-size:10px;color:var(--text-soft);font-weight:600}
.agenda-list{padding:12px}
.agenda-item{display:flex;align-items:center;gap:10px;padding:8px 4px;border-top:1px solid var(--border)}
.agenda-item:first-of-type{border-top:none}
.agenda-item-icon{width:30px;height:30px;border-radius:8px;display:flex;align-items:center;justify-content:center;flex:none}
.agenda-item-body{flex:1;min-width:0}
.agenda-item-title{font-size:13px;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.agenda-item-actions{display:flex;gap:6px;flex:none}

/* ===== Ficha de Crédito (aba Crédito do Lead e da Entidade, loadCreditoTab) =====
   Duas colunas com papéis diferentes, não duas colunas por simetria: a ESQUERDA responde "posso vender a
   prazo, e sob quais condições" (veredito, score, restrições, dossiê, grupo) e a DIREITA responde "de onde
   isso veio e o que fazer com o dado" (consultas feitas, custo, divergências com o cadastro, histórico do
   score). O trilho cai pra baixo do conteúdo principal antes de ficar estreito demais pra o par
   rótulo+valor, e nunca antes da decisão estar inteira na tela. */
.cred-cols{display:grid;grid-template-columns:minmax(0,1.55fr) minmax(300px,.95fr);gap:16px;align-items:start}
.cred-col{display:flex;flex-direction:column;gap:16px;min-width:0;container-type:inline-size;container-name:credcol}
/* CONTAINER QUERY, e não media query, porque aqui a largura do viewport MENTE: esta tela mora dentro da ficha
   do Lead, que já perdeu o menu lateral (240px) e o trilho de abas da ficha (~200px). Medido: viewport de
   1280px sobra 710px de conteúdo. Um `@media (max-width:1180px)` deixaria as duas colunas de pé com 394px na
   principal, e o hero quebrava dentro dela. Quem decide é o espaço real do bloco. */
.cred-wrap{container-type:inline-size;container-name:cred}
@container cred (max-width:770px){.cred-cols{grid-template-columns:1fr}}
/* Sem suporte a @container (navegador antigo), cai numa coluna cedo: é o arranjo que funciona em qualquer
   largura, e perder uma coluna é melhor que espremer duas. */
@supports not (container-type:inline-size){
  @media (max-width:1500px){.cred-cols{grid-template-columns:1fr}}
}
/* O hero: veredito de um lado, score do outro, divididos por uma linha e não por um gap — os dois são a
   MESMA resposta (o veredito é o que a régua fez com o score), então separá-los em dois cards diria que são
   dois assuntos. */
.cred-hero{display:grid;grid-template-columns:minmax(0,1.4fr) minmax(0,1fr)}
.cred-hero>div{padding:18px 20px;min-width:0}
.cred-hero>div+div{border-left:1px solid var(--border);background:var(--surface-2);border-radius:0 var(--radius-lg) var(--radius-lg) 0}
@container credcol (max-width:540px){
  .cred-hero{grid-template-columns:1fr}
  .cred-hero>div+div{border-left:0;border-top:1px solid var(--border);border-radius:0 0 var(--radius-lg) var(--radius-lg)}
}
@supports not (container-type:inline-size){
  @media (max-width:1100px){
    .cred-hero{grid-template-columns:1fr}
    .cred-hero>div+div{border-left:0;border-top:1px solid var(--border);border-radius:0 0 var(--radius-lg) var(--radius-lg)}
  }
}
.cred-disc{width:42px;height:42px;border-radius:12px;display:flex;align-items:center;justify-content:center;flex:none}
.cred-verdict{font-size:19px;font-weight:700;letter-spacing:-.015em;line-height:1.2}
.cred-score-num{font-size:40px;font-weight:800;letter-spacing:-.035em;line-height:1;font-variant-numeric:tabular-nums}
/* Fato operacional em pílula (bloqueio, prazo máximo, entrada mínima, limite). É a saída da régua: o que
   muda na venda por causa deste veredito. Antes era uma lista de linhas cinzas de 11px. */
.cred-pill{display:inline-flex;align-items:center;gap:6px;padding:4px 10px;border-radius:999px;background:var(--surface-2);border:1px solid var(--border);font-size:11.5px;color:var(--text-soft);line-height:1.35}
.cred-hero>div+div .cred-pill{background:var(--surface)}
.cred-pill b{color:var(--text);font-weight:700}
/* Faixa de estado (vencida, liberação excepcional, sem restrição). Cor vem inline por estado. */
.cred-strip{display:flex;align-items:flex-start;gap:8px;padding:9px 11px;border-radius:var(--radius-md);font-size:12px;line-height:1.45;border:1px solid transparent}
.cred-strip svg{flex:none;margin-top:1px}
/* Linhas de lista dentro de card (restrição, membro do grupo, consulta do histórico, retrato). Uma regra só
   pra todas, em vez do style="padding:6px 0;border-top:..." repetido em cada template. */
.cred-rows>li,.cred-rows>div{padding:9px 0;border-top:1px solid var(--border);list-style:none}
.cred-rows>li:first-child,.cred-rows>div:first-child{border-top:0}
.cred-rows{margin:0;padding:0}
/* Título do grupo de campos ("Preencher 2 campos em branco" / "4 campos em que as fontes divergem").
   As regras de .cred-diff (a linha com valor riscado e caixa de marcar) saíram junto com o desenho que as
   usava: riscar o valor do cadastro afirmava que ele estava errado, e isso era falso na metade dos campos.
   Ver .cred-field/.cred-opt no fim deste arquivo. */
.cred-diff-h{font-size:10.5px;font-weight:700;letter-spacing:.04em;text-transform:uppercase;color:var(--text-faint);padding:10px 0 2px}
/* Trilha do retrato: bolinha de faixa + linha vertical ligando os pontos. */
.cred-dot{width:9px;height:9px;border-radius:50%;flex:none;margin-top:5px}
/* O acordeão dentro das colunas de crédito: fundo de superfície (a coluna vive sobre o --bg da página) e sem
   a margem inferior própria, porque quem separa os cards ali é o gap do flex. */
.cred-col .accordion{background:var(--surface);margin-bottom:0;box-shadow:var(--shadow-sm)}
.cred-col .accordion-body{padding:12px 14px}
/* Um campo do enriquecimento = um fieldset com as opções de origem. legend/fieldset nativos porque o leitor
   de tela anuncia "Telefone, grupo" antes das opções, que é exatamente a estrutura da decisão. */
.cred-field{border:0;margin:0;padding:8px 0 4px;border-top:1px solid var(--border)}
.cred-field:first-of-type{border-top:0}
.cred-field legend{padding:0 0 4px}
.cred-opt{display:flex;align-items:flex-start;gap:9px;padding:5px 8px;border-radius:7px;cursor:pointer;border:1px solid transparent;line-height:1.35}
.cred-opt:hover{background:var(--surface-2)}
/* A escolhida fica visível sem procurar a bolinha — com três opções empilhadas, o radio sozinho some. */
.cred-opt.is-on{background:var(--surface-2);border-color:var(--border)}
.cred-opt.is-on b{color:var(--text)}
.cred-opt input{margin-top:2px;flex:none;width:15px;height:15px;accent-color:var(--accent)}
.cred-opt b{font-weight:700;overflow-wrap:anywhere}
@media (pointer:coarse){.cred-opt{padding:9px 8px}.cred-opt input{width:18px;height:18px}}

/* ===== Ficha de registro: faixa de estado, seção de formulário e grade de 12 colunas =====
   Nasceu na ficha de Produto (renderProdutoDetailPage), mas nada aqui é de Produto: são as três peças que
   faltavam pra qualquer ficha do sistema parar de empilhar campo solto numa coluna só. Pedido e Entidade
   são os próximos usos naturais. */

/* A faixa de estado responde "como este registro está" ANTES do formulário. Os números já eram calculados,
   só moravam cada um dentro de uma aba diferente — a faixa é o lugar onde eles viram uma resposta. Divisor
   entre células, não gap: são fatias da MESMA resposta, e cards separados diriam que são assuntos distintos
   (mesma escolha do hero da ficha de Crédito). */
.rec-strip{display:flex;align-items:stretch;flex-wrap:wrap;background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-lg);box-shadow:var(--shadow-sm);margin-bottom:14px;overflow:hidden}
.rec-cell{padding:12px 18px;min-width:0;flex:1 1 150px;border-left:1px solid var(--border)}
.rec-cell:first-child{border-left:0}
.rec-k{font-size:10px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--text-faint)}
.rec-v{font-size:19px;font-weight:800;letter-spacing:-.02em;font-variant-numeric:tabular-nums;line-height:1.25;margin-top:2px}
.rec-v small{font-size:12px;font-weight:600;color:var(--text-faint);letter-spacing:0}
.rec-v.soft{font-size:15px;font-weight:700;color:var(--text-faint)}
.rec-sub{font-size:11px;color:var(--text-faint);margin-top:1px;overflow-wrap:anywhere}
/* A célula de pendências é a única com fundo próprio: ela não informa, ela PEDE ação. */
.rec-cell.todo{background:var(--warning-soft);flex:1 1 250px}
.rec-cell.todo .rec-k{color:var(--warning)}
.rec-gap{display:inline-flex;align-items:center;gap:5px;font-size:11.5px;font-weight:600;color:var(--warning);background:var(--surface);border:1px solid color-mix(in srgb,var(--warning) 35%,transparent);border-radius:999px;padding:2px 9px;margin:4px 4px 0 0;cursor:pointer;font-family:inherit;line-height:1.4}
.rec-gap:hover{background:var(--warning-soft);border-color:var(--warning)}
.rec-gap svg{flex:none}
/* Capa/avatar do registro no cabeçalho da página (pageHead avatarHtml). É a MESMA tag que a miniatura da
   listagem (produtoCapaThumb, só trocando a classe), então herda o modificador `.ph` de "ainda não tem foto":
   tracejado, como todo placeholder de imagem do sistema. Com foto, a própria <img> leva a classe. */
.rec-cover{width:56px;height:56px;border-radius:12px;flex:none;border:1px solid var(--border);background:var(--surface-2);display:flex;align-items:center;justify-content:center;color:var(--text-faint);overflow:hidden;object-fit:cover}
.rec-cover.ph{border-style:dashed;border-color:var(--border-strong)}
.rec-badges{display:flex;gap:6px;flex-wrap:wrap;margin-top:6px}

/* Seção de formulário: título + ícone + fundo, o que um <label> solto nunca conseguiu ser. O aside da direita
   é pra a legenda curta que explica o grupo inteiro (e não cada campo). */
.fsec{border:1px solid var(--border);border-radius:var(--radius-md);background:var(--surface);overflow:hidden}
.fsec-h{display:flex;align-items:center;gap:9px;padding:11px 14px;background:var(--surface-2);border-bottom:1px solid var(--border)}
.fsec-h .t{font-size:12.5px;font-weight:700}
.fsec-h>svg{color:var(--text-faint);flex:none}
.fsec-h .aside{margin-left:auto;font-size:11.5px;color:var(--text-faint);text-align:right;min-width:0}
.fsec-b{padding:14px}
/* Duas colunas com PAPÉIS distintos (o que o registro é × onde ele circula), não duas colunas por simetria.
   Container query, não media query: a ficha já perdeu o menu do app e o trilho de abas, então a largura do
   viewport mente sobre o espaço real — medido, um viewport de 1280px deixa 746px de corpo. */
.fsec-wrap{container-type:inline-size;container-name:fsec}
.fsec-cols{display:grid;grid-template-columns:minmax(0,1.25fr) minmax(290px,.85fr);gap:14px;align-items:start}
.fsec-col{display:flex;flex-direction:column;gap:14px;min-width:0}
@container fsec (max-width:820px){.fsec-cols{grid-template-columns:1fr}}
@supports not (container-type:inline-size){
  @media (max-width:1500px){.fsec-cols{grid-template-columns:1fr}}
}

/* Grade de 12 colunas: a largura do campo passa a vir do DADO que ele guarda, não de um flex:1 que estica o
   que estiver por último. Medido antes: "Nome do produto" com 1360px pra 13 caracteres e "Categoria" com
   126px, o único campo da tela cujo texto não cabia. */
.g12{display:grid;grid-template-columns:repeat(12,1fr);gap:12px}
.g12>*{min-width:0}
.g12>.c2{grid-column:span 2}.g12>.c3{grid-column:span 3}.g12>.c4{grid-column:span 4}.g12>.c5{grid-column:span 5}
.g12>.c6{grid-column:span 6}.g12>.c7{grid-column:span 7}.g12>.c8{grid-column:span 8}.g12>.c9{grid-column:span 9}.g12>.c12{grid-column:span 12}
/* Abaixo de 560px a grade de 12 vira pilha: campo de 3 colunas num corpo de 340px daria 70px. */
@media (max-width:560px){.g12>[class*="c"]{grid-column:span 12}}
/* Valor DERIVADO (margem, cubagem): tem a altura e o alinhamento de um campo, mas contorno tracejado porque
   não se digita nele. Sem isso, um readonly parece campo quebrado. */
.fval{background:var(--surface-2);color:var(--text-soft);display:flex;align-items:center;gap:7px;padding:9px 11px;border:1px dashed var(--border-strong);border-radius:8px;font-size:13px;min-height:37px;overflow-wrap:anywhere}
.fval b{color:var(--text);font-variant-numeric:tabular-nums;font-weight:700}
.fval>svg{flex:none;color:var(--text-faint)}
.fval.on{background:var(--accent-soft);border-style:solid;border-color:transparent;color:var(--text)}
.fval.on>svg{color:var(--accent)}
/* Linha de empresa marcável: o checkbox solto em linha não dizia de qual empresa era o quadradinho quando os
   nomes têm 40 caracteres. */
.emp-pick{display:flex;align-items:center;gap:9px;padding:8px 10px;border:1px solid var(--border);border-radius:8px;font-size:13px;background:var(--surface);cursor:pointer;margin-bottom:6px}
.emp-pick:last-child{margin-bottom:0}
.emp-pick:hover{border-color:var(--border-strong)}
.emp-pick.on{border-color:var(--accent);background:var(--accent-soft)}
.emp-pick input{width:15px;height:15px;accent-color:var(--accent);flex:none}
.emp-pick-av{width:24px;height:24px;border-radius:6px;background:var(--surface-2);color:var(--text-faint);font-size:10.5px;font-weight:800;display:flex;align-items:center;justify-content:center;flex:none}
.emp-pick.on .emp-pick-av{background:var(--accent);color:var(--accent-contrast)}
.emp-pick-nome{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
@media (pointer:coarse){.emp-pick{padding:11px 10px}.emp-pick input{width:18px;height:18px}}

/* Passo numerado. A numeração aqui é informação, não enfeite: escolher os eixos, curar os valores e
   gerenciar a grade é uma sequência de verdade — o passo 3 não existe antes do 1. */
.fstep{display:flex;align-items:center;gap:10px;margin-bottom:10px;flex-wrap:wrap}
.fstep-n{width:22px;height:22px;border-radius:7px;background:var(--accent-soft);color:var(--accent);font-size:11.5px;font-weight:800;display:flex;align-items:center;justify-content:center;flex:none;font-family:var(--font-mono)}
.fstep-t{font-size:13px;font-weight:700}
.fstep-d{font-size:11.5px;color:var(--text-faint);margin-left:auto;text-align:right;min-width:0}

/* Estado vazio com ação (emptyState com o 4º argumento). O vazio que não oferece a saída obriga a pessoa a
   adivinhar onde fica a tela que resolve. */
.empty-actions{display:flex;gap:8px;justify-content:center;flex-wrap:wrap;margin-top:14px}
.empty-boxed{border:1px dashed var(--border-strong);border-radius:var(--radius-md);background:var(--surface-2)}
.empty-boxed .empty{padding:34px 20px}
.empty .empty-desc{max-width:52ch;margin:0 auto;line-height:1.5}

/* ===== Ficha de Produto: fotos, estoque e canais ===== */
/* A capa é maior que as outras porque ela É diferente: é a foto que vai pra listagem, pro carrinho e pras
   integrações. Antes as fotos tinham todas o mesmo tamanho e só um selo minúsculo dizia qual era a capa. */
.pg-thumb.pg-cover{width:168px;height:168px}
/* "Adicionar" como último tile da fila, do tamanho de uma miniatura — no lugar da faixa tracejada de largura
   inteira, que ocupava mais espaço que as próprias fotos. A faixa grande continua sendo o certo quando NÃO
   há foto nenhuma (aí ela é o estado vazio, não um botão). */
.pg-add{width:120px;height:120px;border:2px dashed var(--border-strong);border-radius:10px;background:var(--surface-2);display:flex;flex-direction:column;align-items:center;justify-content:center;gap:6px;color:var(--text-faint);font-size:11.5px;font-weight:600;cursor:pointer;text-align:center;padding:8px;line-height:1.25;font-family:inherit;transition:.15s}
.pg-add:hover,.pg-add.dragover{border-color:var(--accent);background:var(--accent-soft);color:var(--accent)}
.pg-add svg{flex:none}

/* Saldo como número grande: a pergunta da aba Estoque é "quanto tem", e ela merece o tamanho de um veredito. */
.st-hero{display:flex;align-items:center;gap:18px;flex-wrap:wrap;padding:16px 18px;border:1px solid var(--border);border-radius:var(--radius-md);background:var(--surface)}
.st-num{font-size:40px;font-weight:800;letter-spacing:-.035em;line-height:1;font-variant-numeric:tabular-nums}
.st-num.low{color:var(--danger)}
/* Medidor do mínimo: a barra existe pra dizer o quanto falta, não pra enfeitar — some quando não há mínimo. */
.st-meter{height:6px;border-radius:4px;background:var(--surface-2);border:1px solid var(--border);overflow:hidden;margin-top:9px;max-width:230px}
.st-meter i{display:block;height:100%;background:var(--success);border-radius:3px}
.st-meter i.low{background:var(--danger)}

/* Um cartão por canal, com a identidade da plataforma: a linha de 6 campos num grid de 3 colunas não dizia
   onde terminava um canal e começava o outro. */
.ch-card{border:1px solid var(--border);border-radius:var(--radius-md);background:var(--surface);padding:13px 14px;display:flex;flex-direction:column;gap:11px}
.ch-head{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.ch-logo{width:30px;height:30px;border-radius:8px;display:flex;align-items:center;justify-content:center;font-size:11px;font-weight:800;flex:none;background:var(--accent-soft);color:var(--accent)}
.ch-name{font-size:13.5px;font-weight:700;min-width:0;overflow:hidden;text-overflow:ellipsis}
.ch-card.off{opacity:.72}

/* Trilha do histórico de estoque: bolinha de sinal + linhas separadas por um fio. Mesma forma das listas da
   ficha de Crédito (.cred-rows), que é onde o padrão nasceu. */
.hist-row{display:flex;align-items:flex-start;gap:10px;padding:9px 0;border-top:1px solid var(--border)}
.hist-row:first-child{border-top:0}
.hist-dot{width:9px;height:9px;border-radius:50%;flex:none;margin-top:5px}
.hist-main{flex:1;min-width:0}
.hist-delta{text-align:right;white-space:nowrap;font-variant-numeric:tabular-nums}
/* ============================ POLÍTICA DE CRÉDITO — construtor de régua ============================
   A régua é um catálogo de 15 condições x 7 efeitos, e a tela mostrava TODOS os campos de TODAS as regras
   ao mesmo tempo (5 regras = 105 selects em "Não considerar"). Aqui uma regra fechada é uma FRASE legível
   ("SE cobrança vencida ha mais de 30 dias ENTÃO negar"), e aberta mostra só o que ela de fato usa — o resto
   entra por um menu. Os quatro primeiros componentes abaixo (.seg, .pill-toggle, .tokenbox, .add-dashed) são
   genéricos de propósito: nascem aqui, mas nada neles fala de crédito, então o próximo módulo que precisar
   de escolha única em barra, multi-seleção curta ou multi-seleção longa reaproveita em vez de inventar. */

/* Escolha ÚNICA entre 2-4 opções, em barra. O tom do estado ativo vem de duas variáveis locais setadas no
   HTML (--seg-tone/--seg-soft), então veredito aprovado/análise/negado colore verde/âmbar/vermelho sem uma
   regra CSS por tom — e um seg de outro módulo funciona no accent sem tocar aqui. */
.seg{display:flex;background:var(--surface-2);border:1px solid var(--border-strong);border-radius:9px;padding:3px;gap:3px}
.seg-opt{flex:1;border:0;background:transparent;color:var(--text-soft);font-size:12.5px;font-weight:700;padding:8px 6px;border-radius:6px;cursor:pointer;display:flex;align-items:center;justify-content:center;gap:6px;transition:.12s;font-family:inherit;min-width:0}
.seg-opt:hover{color:var(--text)}
.seg-opt.on{background:var(--seg-soft,var(--accent-soft));color:var(--seg-tone,var(--accent))}
.seg-opt>span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

/* Multi-seleção CURTA (até ~8 opções conhecidas): mostra todas, alterna no clique. Preferida ao token
   quando ver o que NÃO está marcado importa tanto quanto o que está — é o caso das formas de pagamento,
   onde "o que continua liberado" é metade da leitura. */
.pill-group{display:flex;flex-wrap:wrap;gap:7px}
.pill-toggle{display:inline-flex;align-items:center;gap:6px;font-size:12px;font-weight:600;padding:6px 11px;border-radius:999px;border:1px solid var(--border-strong);background:var(--surface);color:var(--text-soft);cursor:pointer;transition:.12s;font-family:inherit}
.pill-toggle:hover{border-color:var(--text-faint);color:var(--text)}
.pill-toggle.on{background:var(--pill-soft,var(--accent-soft));border-color:var(--pill-tone,var(--accent));color:var(--pill-tone,var(--accent))}

/* Multi-seleção LONGA (dezenas de opções): chips DENTRO do campo + busca, irmão compacto do tag-picker
   (.tag-picker-chips, que põe os chips abaixo e é o certo quando há espaço). Reaproveita .combo/.combo-list
   pro dropdown e .badge/.badge-removable pro chip: o que este bloco acrescenta é só o container. */
.tokenbox{display:flex;flex-wrap:wrap;align-items:center;gap:6px;min-height:40px;padding:6px 30px 6px 8px;border:1px solid var(--border-strong);border-radius:8px;background:var(--surface);cursor:text}
.tokenbox:focus-within{border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-ring)}
.tokenbox .badge{max-width:100%}
.tokenbox .badge .token-text{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.token-input{flex:1;min-width:80px;border:0;background:transparent;color:var(--text);font-size:12.5px;padding:4px 2px;outline:none;font-family:inherit}
.token-input::placeholder{color:var(--text-faint)}
.tokenbox-caret{position:absolute;right:10px;top:19px;color:var(--text-faint);pointer-events:none}

/* Ação de ACRESCENTAR um item a uma lista que o usuário monta (condição, efeito, regra). Tracejado porque
   marca um lugar vazio que pode ser preenchido, diferente de .btn, que executa algo que já existe. */
.add-dashed{width:100%;border:1px dashed var(--border-strong);background:transparent;color:var(--text-soft);border-radius:9px;padding:9px;font-size:12.5px;font-weight:600;cursor:pointer;display:flex;align-items:center;justify-content:center;gap:7px;transition:.12s;font-family:inherit}
.add-dashed:hover{border-color:var(--accent);color:var(--accent);background:var(--accent-soft)}
.add-dashed.lg{padding:15px;font-size:13px;border-width:1.5px;border-radius:var(--radius-lg)}

/* Barra de ÂNCORAS (não é wizard): a página continua inteira e rolável, isto só leva até a seção. Um wizard
   aqui seria erro de leitura — configuração é revisitada pra ajustar um detalhe, e "Próximo/Próximo" a cada
   visita é atrito, além de esconder a régua toda, que é justamente o que se quer ver de uma vez. */
.jumpnav{position:sticky;top:0;z-index:9;display:flex;align-items:center;gap:4px;flex-wrap:wrap;background:color-mix(in srgb,var(--bg) 88%,transparent);backdrop-filter:blur(8px);border-bottom:1px solid var(--border);padding:10px 0;margin-bottom:20px}
.jumpnav a{display:inline-flex;align-items:center;gap:7px;padding:6px 13px;border-radius:999px;font-size:12.5px;font-weight:600;color:var(--text-soft);text-decoration:none;transition:.12s}
.jumpnav a:hover{background:var(--surface-2);color:var(--text)}
.jumpnav a.active{background:var(--accent-soft);color:var(--accent)}
.jumpnav .jump-count{font-size:11px;background:var(--surface-3);color:var(--text-faint);border-radius:999px;padding:0 6px;font-variant-numeric:tabular-nums}
.jumpnav a.active .jump-count{background:color-mix(in srgb,var(--accent) 22%,transparent);color:var(--accent)}

/* --- Card de regra --- */
.pol-rule{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-lg);box-shadow:var(--shadow-sm);margin-bottom:12px}
.pol-rule.open{border-color:var(--border-strong)}
.pol-rule.sortable-ghost{opacity:.35}
.pol-rule-head{display:flex;align-items:center;gap:12px;padding:13px 15px}
.pol-rule.open .pol-rule-head{background:var(--surface-2);border-radius:var(--radius-lg) var(--radius-lg) 0 0}
.pol-rule-toggle{flex:1;display:flex;align-items:center;gap:12px;background:transparent;border:0;padding:0;cursor:pointer;text-align:left;color:inherit;font-family:inherit;min-width:0}
/* A ORDEM é a lógica da régua (a primeira regra que casa vence), então o número não é enfeite: é o que a
   pessoa confere ao arrastar. Tabular pra não dançar entre 9 e 10. */
.pol-rule-num{width:30px;height:30px;border-radius:8px;background:var(--surface-3);border:1px solid var(--border);color:var(--text-soft);display:flex;align-items:center;justify-content:center;font-weight:700;font-size:14px;flex:none;font-variant-numeric:tabular-nums}
.pol-rule.open .pol-rule-num{background:var(--accent-soft);color:var(--accent)}
.pol-rule-meta{flex:1;min-width:0}
/* display:block é o que FAZ o truncamento existir: são <span> dentro de um <button>, e em elemento inline o
   text-overflow:ellipsis é ignorado — o nome comprido então empurrava o card e a página inteira ganhava
   rolagem lateral no celular. */
.pol-rule-name{display:block;font-size:14px;font-weight:700;margin-bottom:3px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.pol-rule-resumo{font-size:12.5px;color:var(--text-soft);display:flex;align-items:center;gap:6px;flex-wrap:wrap}
.pol-rule-actions{display:flex;align-items:center;gap:1px;flex:none}
.pol-rule-chev{color:var(--text-faint);transition:transform .15s;flex:none}
.pol-rule.open .pol-rule-chev{transform:rotate(180deg)}
.pol-drag{display:flex;align-items:center;justify-content:center;width:20px;color:var(--text-faint);cursor:grab;flex:none;touch-action:none}
.pol-drag:active{cursor:grabbing}
.pol-drag:hover{color:var(--text-soft)}
/* Trecho da condição no resumo da regra fechada. Fundo próprio (não .badge) porque são vários numa linha só,
   e o pill arredondado nessa densidade vira ruído. */
.pol-chip{display:inline-flex;align-items:center;gap:4px;font-size:11.5px;color:var(--text-soft);background:var(--surface-2);border:1px solid var(--border);border-radius:6px;padding:1px 7px;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.pol-arrow{color:var(--text-faint);flex:none;display:inline-flex}

/* Corpo: Quando | Então lado a lado. Duas colunas porque a regra É uma frase de duas metades, e lê-la de
   uma vez é o ponto — empilhado, a segunda metade fica fora da tela. O nome fica FORA desse grid (faixa
   própria): dentro dele, mesmo ocupando as duas colunas, ele contaria como .pol-panel e daria à coluna
   seguinte a borda esquerda que separa Quando de Então. */
.pol-rule-nome{border-top:1px solid var(--border);padding:14px 18px}
.pol-rule-body{border-top:1px solid var(--border);display:grid;grid-template-columns:1fr 1fr}
.pol-panel{padding:16px 18px;min-width:0}
.pol-panel+.pol-panel{border-left:1px solid var(--border)}
.pol-panel-h{display:flex;align-items:center;gap:8px;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.05em;color:var(--text-faint);margin-bottom:13px}
.pol-panel-ic{width:20px;height:20px;border-radius:5px;display:flex;align-items:center;justify-content:center;flex:none;background:var(--surface-3);border:1px solid var(--border);color:var(--text-soft)}
.pol-panel-h.is-quando .pol-panel-ic{background:var(--accent-soft);color:var(--accent)}
.pol-cond{background:var(--surface-2);border:1px solid var(--border);border-radius:10px;padding:11px 12px;margin-bottom:9px;position:relative}
.pol-cond-top{display:flex;align-items:flex-start;gap:8px;margin-bottom:7px}
.pol-cond-titles{flex:1;min-width:0}
.pol-cond-grupo{font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.04em;color:var(--accent);display:block;margin-bottom:1px}
.pol-cond-label{font-size:13px;font-weight:600;line-height:1.3}
.pol-cond-x{flex:none;width:22px;height:22px;border:0;background:transparent;color:var(--text-faint);border-radius:5px;cursor:pointer;display:flex;align-items:center;justify-content:center;padding:0}
.pol-cond-x:hover{background:var(--danger-soft);color:var(--danger)}
.pol-cond .select,.pol-cond .input{padding:7px 10px;font-size:12.5px}
.pol-cond .hint{display:block;margin-top:5px}
.pol-cond-prefix{display:flex;align-items:center;gap:8px}
.pol-cond-prefix>.pol-cond-un{color:var(--text-faint);font-size:12.5px;flex:none}
/* "(qualquer um deles)" / "(todas as marcadas)": a mesma caixa de multi-seleção quer dizer OU numa condição
   e E num efeito, e essa é a diferença entre a regra que a pessoa quis e a que ela escreveu. */
.pol-cond-nuance{font-weight:400;color:var(--text-faint)}
/* Amostra do catálogo ainda disponível, ao lado do botão de adicionar. Some no estreito: ali o rótulo do
   botão já ocupa a linha, e a dica passaria a empurrar em vez de ajudar. */
.pol-add-hint{color:var(--text-faint);font-weight:500;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}
/* Resultado de prévia/simulação: número que a pessoa pediu e vai usar para decidir, então tem fundo próprio
   em vez de virar mais uma linha de texto solta embaixo do formulário. */
.pol-callout{background:var(--accent-soft);border:1px solid color-mix(in srgb,var(--accent) 35%,var(--border));border-radius:10px;padding:11px 14px;font-size:12.5px;color:var(--text-soft);display:flex;gap:9px;align-items:flex-start}
.pol-callout>svg{color:var(--accent);flex:none;margin-top:1px}
.pol-callout b{color:var(--accent)}
.pol-empty-panel{font-size:12.5px;color:var(--text-faint);padding:8px 0 12px;line-height:1.5}

/* Menu de adicionar condição/efeito. position:fixed + portal no body porque ele é posicionado pelo Floating
   UI e precisa poder escapar do card sem ser recortado pelo overflow de ancestral nenhum. */
.pol-menu{position:fixed;top:0;left:0;width:330px;max-width:calc(100vw - 24px);max-height:min(60vh,420px);overflow:auto;background:var(--surface);border:1px solid var(--border-strong);border-radius:11px;box-shadow:var(--shadow-md);padding:7px;z-index:1200}
.pol-menu-group{font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.05em;color:var(--text-faint);padding:9px 10px 4px;display:flex;align-items:center;gap:6px}
.pol-menu-item{display:flex;align-items:flex-start;gap:9px;padding:8px 10px;border-radius:7px;cursor:pointer;width:100%;border:0;background:transparent;color:inherit;text-align:left;font-family:inherit;font-size:13px}
.pol-menu-item:hover,.pol-menu-item.hi{background:var(--surface-2)}
.pol-menu-ic{color:var(--text-faint);flex:none;margin-top:1px}
.pol-menu-desc{font-size:11px;color:var(--text-faint);line-height:1.35;margin-top:1px}
.pol-menu-empty{padding:10px;font-size:12.5px;color:var(--text-faint)}

/* Faixa-resumo do topo: o estado da régua num olhar (quantas regras, o que acontece quando nenhuma casa,
   monitoramento ligado ou não, validade). Não reusa .stat-card porque aquele é métrica de negócio com
   ícone grande; aqui é ESTADO DE CONFIGURAÇÃO, denso e sem ícone. */
.pol-summary{display:grid;grid-template-columns:repeat(4,1fr);gap:12px;margin-bottom:18px}
.pol-sm{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-md);padding:12px 14px;display:flex;flex-direction:column;gap:2px;min-width:0}
.pol-sm-lbl{font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.04em;color:var(--text-faint)}
.pol-sm-val{font-size:17px;font-weight:700;display:flex;align-items:center;gap:7px;font-variant-numeric:tabular-nums;min-width:0}
.pol-sm-val>.pol-sm-txt{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.pol-sm-un{font-size:13px;font-weight:600;color:var(--text-faint)}
.pol-dot{width:8px;height:8px;border-radius:50%;flex:none}
.pol-section{margin-bottom:24px;scroll-margin-top:60px}
.pol-section-h{display:flex;align-items:center;gap:9px;margin-bottom:12px;flex-wrap:wrap}
.pol-section-h h2{font-size:14px;font-weight:700;margin:0}
.pol-section-ic{width:26px;height:26px;border-radius:7px;background:var(--surface-3);border:1px solid var(--border);color:var(--text-soft);display:flex;align-items:center;justify-content:center;flex:none}
.pol-section-sub{font-size:12px;color:var(--text-faint)}
.pol-mon-previa{margin-top:12px}

@media (max-width:1080px){.pol-summary{grid-template-columns:repeat(2,1fr)}}
@media (max-width:860px){
  .pol-rule-body{grid-template-columns:1fr}
  .pol-panel+.pol-panel{border-left:0;border-top:1px solid var(--border)}
}
@media (max-width:640px){
  .pol-summary{grid-template-columns:1fr 1fr;gap:9px}
  .pol-sm-val{font-size:15px}
  .pol-rule-head{gap:9px;padding:11px 12px}
  .pol-panel{padding:14px}
  /* Arrastar não existe sem atrito em toque; as setas continuam sendo o caminho principal de reordenar. */
  .pol-drag{display:none}
  /* No celular o resumo inteiro empilharia 4 linhas por regra e a lista deixaria de ser varrível. Fica o que
     decide a venda (o veredito) e os avisos de regra malformada; o detalhe das condições está a um toque,
     dentro da regra. */
  .pol-rule-resumo .pol-chip:not(.pol-chip-warn),.pol-rule-resumo .pol-arrow{display:none}
  /* Numa barra de 3 opções em ~200px, o ícone rouba a largura do rótulo e "Em análise" vira "Em aná…".
     Entre ver o desenho e ler a palavra, a palavra é que decide. */
  .seg-opt{padding:8px 4px;gap:4px;font-size:12px}
  .seg-opt>svg{display:none}
}
@media (prefers-reduced-motion:reduce){
  .seg-opt,.pill-toggle,.add-dashed,.pol-rule-chev,.jumpnav a{transition:none}
}
/* Faixa de instância desatualizada (dev only, ver server/instancia.js). Âmbar e não vermelho: não é falha
   do sistema, é o processo estar velho em relação ao disco — e o remédio é reiniciar, não socorrer. */
.instancia-banner{background:var(--warning);color:#1a1206}
.instancia-banner .btn{background:rgba(255,255,255,.9);border-color:rgba(0,0,0,.2);color:#1a1206}

/* ===== CONEXÕES: ficha de fornecedor ==================================================================
   A tela de Conexões não tinha UMA classe própria: era .card + utilitários + estilo inline, e a divisória
   do rodapé de ações aparecia literalmente dez vezes no index.html, uma por renderizador de categoria.
   Este bloco é o CSS do componente único (conexaoCardHtml), e a regra que ele carrega é a de sempre: o que
   já existe no design system é reaproveitado (.card, .badge/.b-*, .btn/.btn-danger, .switch, .wa-sync-warn,
   .notif-count-badge), e aqui só entra o que é genuinamente novo, a FICHA.

   Por que ficha e não linha: uma conexão é um contrato com um fornecedor, então o card responde quatro
   perguntas na mesma superfície, quem é, está de pé, o que sabe fazer e quanto custa. A faixa de estado na
   borda esquerda é o que faz "precisa de você" ser lido antes de qualquer texto, de longe e no periférico. */
.conx-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(272px,1fr));gap:12px;align-items:start}

.conx-sheet{position:relative;display:flex;flex-direction:column;gap:10px;padding:13px 15px 12px 17px;overflow:hidden}
/* A faixa é ::before para não gastar um elemento e para nunca ser empurrada pelo conteúdo. Verde é o
   silêncio: conexão saudável não precisa gritar, então a faixa some visualmente contra a borda do card. */
.conx-sheet::before{content:"";position:absolute;left:0;top:0;bottom:0;width:3px;background:var(--success);opacity:.55}
.conx-sheet.is-erro::before{background:var(--danger);opacity:1}
.conx-sheet.is-atencao::before{background:var(--warning);opacity:1}
.conx-sheet.is-off::before{background:var(--text-faint);opacity:.7}
.conx-sheet.is-erro{border-color:color-mix(in srgb,var(--danger) 34%,var(--border))}

.conx-top{display:flex;align-items:flex-start;gap:10px}
/* Ladrilho de identidade: iniciais do fornecedor. Não é <img> de propósito, pela mesma razão do disco de
   iniciais do e-mail, é justamente quando a imagem não carrega que se precisa saber de quem é a conexão. */
.conx-ident{flex:none;width:34px;height:34px;border-radius:9px;display:grid;place-items:center;font-size:12px;font-weight:700;letter-spacing:-.02em;background:var(--surface-3);color:var(--text-soft);border:1px solid var(--border)}
.conx-id{flex:1;min-width:0}
.conx-nome{font-size:13.5px;font-weight:650;letter-spacing:-.01em;display:flex;align-items:center;gap:6px;flex-wrap:wrap;min-width:0}
.conx-sub{font-size:11px;color:var(--text-faint);margin-top:2px;display:flex;align-items:center;gap:5px;flex-wrap:wrap}
.conx-sub .conx-escopo-danger{color:var(--danger)}

.conx-body{display:flex;flex-direction:column;gap:8px;min-width:0}
/* .wa-sync-warn traz margin-bottom de 10px do uso dela no card do Baileys, onde ela é solta. Aqui o
   espaçamento é do gap do flex, então a margem própria viraria espaço dobrado. */
.conx-body>.wa-sync-warn{margin:0}
.conx-caps{display:flex;flex-wrap:wrap;gap:4px}
.conx-cap{font-size:10px;font-weight:600;padding:2px 7px;border-radius:5px;background:var(--surface-3);color:var(--text-soft);white-space:nowrap}
.conx-cap.conx-cap-mais{background:transparent;color:var(--text-faint);border:1px dashed var(--border)}

/* Métricas vivas. Divide o mesmo vocabulário do .stat-card (rótulo miúdo em caixa alta sobre número
   tabular), sem a moldura, porque aqui elas moram DENTRO de um card e não são o card. */
.conx-live{display:flex;flex-wrap:wrap;gap:3px 16px;padding-top:8px;border-top:1px solid var(--border)}
.conx-live-u{display:flex;flex-direction:column;gap:1px;min-width:0}
.conx-live-k{font-family:var(--font-mono);font-size:9.5px;letter-spacing:.07em;text-transform:uppercase;color:var(--text-faint);white-space:nowrap}
.conx-live-v{font-size:12.5px;font-weight:650;font-variant-numeric:tabular-nums}
.conx-live-v.is-warn{color:var(--warning)}
.conx-live-v.is-erro{color:var(--danger)}
.conx-live-v.is-faint{color:var(--text-faint);font-weight:600}

/* Barra de consultas liberadas: o número que o Master vai atrás, clicável, virando a porta do painel. */
.conx-fnbar{display:flex;align-items:center;gap:8px;width:100%;text-align:left;font-family:inherit;font-size:11.5px;color:var(--text-soft);background:var(--surface-2);border:1px solid var(--border);border-radius:8px;padding:6px 9px;cursor:pointer;transition:.12s}
.conx-fnbar:hover{border-color:var(--accent);color:var(--accent)}
.conx-fnbar-bar{flex:1;min-width:40px;height:5px;border-radius:999px;background:var(--surface-3);overflow:hidden}
.conx-fnbar-bar>span{display:block;height:100%;background:var(--accent);border-radius:999px}
.conx-fnbar-n{font-family:var(--font-mono);font-size:10.5px;font-variant-numeric:tabular-nums;white-space:nowrap}

/* Painel "Consultas liberadas" (o que a barra acima abre). Cada linha é uma DECISÃO, não um item de listagem:
   o switch vem primeiro porque é o que se vai mexer, e o preço fica à direita, em fonte tabular, porque a
   pergunta que essa tela responde é "quanto custa cada uma destas". A linha desligada perde cor mas não sai da
   lista — é ela que o Master procura quando quer liberar algo. */
.fnlib-list{display:flex;flex-direction:column;border:1px solid var(--border);border-radius:10px;overflow:hidden}
.fnlib-row{display:grid;grid-template-columns:auto 1fr auto auto;align-items:center;gap:12px;padding:10px 12px;background:var(--surface)}
.fnlib-row+.fnlib-row{border-top:1px solid var(--border)}
.fnlib-row.is-off{background:var(--surface-2)}
.fnlib-row.is-off .fnlib-id,.fnlib-row.is-off .fnlib-custo{opacity:.55}
.fnlib-id{min-width:0}
.fnlib-nome{display:flex;align-items:center;gap:6px;flex-wrap:wrap;font-size:13px;font-weight:650}
.fnlib-meta{font-size:11.5px;color:var(--text-soft);margin-top:2px}
.fnlib-custo{font-family:var(--font-mono);font-size:12.5px;font-weight:650;font-variant-numeric:tabular-nums;white-space:nowrap}
.fnlib-teto{display:flex;align-items:center;gap:5px;white-space:nowrap;margin:0}
.fnlib-teto>input{width:66px;text-align:right}
.fnlib-rename{white-space:nowrap;text-decoration:none}
.fnlib-rotulo{max-width:250px}
.fnlib-top{display:flex;align-items:center;justify-content:space-between;gap:10px;flex-wrap:wrap}
.fnlib-resumo{font-size:12.5px;color:var(--text-soft)}
@media (max-width:640px){
  .fnlib-row{grid-template-columns:auto 1fr;row-gap:7px}
  .fnlib-custo,.fnlib-teto{grid-column:2}
}

/* Barra de ações. Substitui a string inline repetida dez vezes; .conx-acoes-sp empurra o resto para a
   direita e é o que era `style="margin-left:auto"` em cada botão Editar. */
.conx-acoes{display:flex;align-items:center;gap:6px;flex-wrap:wrap;padding-top:10px;border-top:1px solid var(--border);margin-top:auto}
.conx-acoes-sp{margin-left:auto}
.conx-acoes .conx-resultado{font-size:12px;min-width:0}

/* Cabeçalho de seção por categoria, com contador e o fio até a borda. */
.conx-secao{display:flex;align-items:center;gap:9px;margin:16px 0 10px}
.conx-secao:first-child{margin-top:0}
.conx-secao-t{font-size:11px;font-weight:700;letter-spacing:.09em;text-transform:uppercase;color:var(--text-soft)}
.conx-secao-c{font-family:var(--font-mono);font-size:10.5px;color:var(--text-faint)}
.conx-secao-fio{flex:1;height:1px;background:var(--border)}

/* Barra de ferramentas do corpo: busca + fichas de estado. */
.conx-toolbar{display:flex;flex-wrap:wrap;gap:8px;align-items:center;margin-bottom:14px}
.conx-chip{font-size:11.5px;font-weight:600;padding:4px 10px;border-radius:999px;cursor:pointer;border:1px solid var(--border);background:var(--surface);color:var(--text-soft);font-family:inherit;white-space:nowrap}
.conx-chip:hover{border-color:var(--border-strong);color:var(--text)}
.conx-chip.active{background:var(--accent-soft);border-color:color-mix(in srgb,var(--accent) 40%,var(--border));color:var(--accent)}

@media (max-width:900px){
  /* Uma coluna antes do que a grade pediria: dentro da .vmenu-body de 305px úteis no telefone, duas
     colunas de 272px não cabem, e deixar o auto-fill decidir gera uma coluna espremida. */
  .conx-grid{grid-template-columns:1fr}
}
@media (max-width:480px){
  .conx-live{gap:3px 12px}
  .conx-acoes .conx-acoes-sp{margin-left:0}
}
