/* ============================================================
   Koonfy — Design system do app (identidade da landing)
   Inter Tight · verde da logo #50EA5F→#05BF91 · tinta #0F1F15
   Botões pill, cards 20px, sombras verdes suaves
   ============================================================ */

:root {
  /* superfícies */
  --bg: #fbfdf9;
  --bg2: #f4f7f2;
  --card: #ffffff;
  --glass: rgba(255, 255, 255, .88);
  --border: #e6f0ea;
  --border2: #d7eee3;

  /* texto */
  --text: #0f1f15;
  --text2: #3a4a3e;
  /* Cinzas de apoio, escurecidos até passarem de 4,5:1 sobre o card branco.
     Nos valores antigos (#7b8a79 = 3,65 e #93a092 = 2,73) rótulos inteiros do
     produto ficavam quase invisíveis: "Geral" e "Atendimento" no menu, a versão
     no rodapé, os dias do calendário, os subtítulos dos cartões. Continuam
     lendo como texto secundário — só que legíveis. */
  --muted: #667563;
  --faint: #63715f;

  /* MARCA — as cores saem do ARQUIVO da logo, não de estimativa. Amostrando
     koonfy-logo.png: #50ea5f no canto superior esquerdo e #05bf91 no inferior
     direito. O verde antigo (#34d399) tinha matiz ~165°, que puxa para o
     azul-esverdeado; o da logo é ~140°, verde puro. Lado a lado, o app e a
     marca pareciam de empresas diferentes.
     O --verde-deep é escurecido de propósito além do gradiente: ele é usado em
     TEXTO sobre fundo claro, e o verde da logo sozinho não alcança 4.5:1. */
  --verde: #50ea5f;
  --verde-esc: #2ed378;
  /* O BOTÃO usa um verde mais fechado que a marca. O verde da logo é claro
     demais para uma área grande e chapada com texto branco em cima — funciona
     no símbolo e no "fy", não num bloco de 200px. É a mesma família de cor,
     um par de passos abaixo. Editável em Admin → Personalização. */
  --btn-verde: #19a95a;
  --btn-verde-hover: #14904c;
  /* Cor do TEXTO dos botões secundários (os vazados). Era --verde-deep
     (#178048), um verde mais fechado que o do botão cheio: lado a lado no
     mesmo cartão, "Copiar link" e "Enviar no WhatsApp" pareciam de dois
     produtos. Agora é o MESMO verde do botão principal. */
  --btn-ink: var(--btn-verde);
  /* MENU LATERAL — tokens próprios para o item ativo e os contadores.
     Antes isto vinha de --verde e --ink-on-verde, que também pintam chips e
     selos pelo app inteiro: mudar o menu mexia em coisa que ninguém pediu.
     Editáveis em Admin → Personalização. */
  --menu-ativo: var(--verde);
  --menu-tinta: var(--ink-on-verde);
  --menu-brilho: rgba(46, 211, 120, .35);
  /* Texto DENTRO do botão principal. Token próprio, separado do
     --ink-on-verde (que é a tinta escura usada sobre o verde CLARO em chips e
     selos): aqui o fundo é escuro e o texto é branco. */
  --btn-tinta: #ffffff;
  --verde-med: #21b866;
  --verde-deep: #178048;
  --ink-on-verde: #04331a;
  --grad: linear-gradient(135deg, #50ea5f, #05bf91);
  --brand: var(--verde-esc);
  --brand-dark: var(--verde-deep);
  --brand-bg: #eafbf0;
  --brand-border: #bfeccf;

  /* sidebar clara (branca, ícones/textos cinza — como o mockup do disparo) */
  --sidebar: #ffffff;
  --sidebar-hover: #f4f7f2;
  --sidebar-text: #5f6d5d;
  --tinta: #0f1f15;

  /* semáforo */
  --red: #e5484d;
  --red-ink: #d1373c;   /* o vermelho quando é TEXTO sobre fundo claro */
  --red-bg: #fef1f1;
  --red-border: #f6c6c8;
  --amber: #e79009;
  --amber-bg: #fff8e9;
  --amber-border: #f6dfa9;
  --blue: #53bdeb;
  --blue-ink: #2361d8;
  --blue-bg: #eef6fe;
  --blue-border: #c6dffb;

  /* Altura do topo = a barra em si MAIS o recorte da tela. Sem o recorte, a
     conta dá os mesmos 62px de sempre. */
  --topbar-h: calc(62px + env(safe-area-inset-top, 0px));

  /* geometria & sombra */
  --radius: 20px;
  --radius-sm: 14px;
  --shadow-xs: 0 1px 2px rgba(15, 31, 21, .05);
  --shadow-sm: 0 2px 8px rgba(15, 31, 21, .05);
  --shadow: 0 14px 34px -8px rgba(20, 60, 20, .14);
  --shadow-lg: 0 30px 70px -16px rgba(20, 60, 20, .22);
  --glow: 0 8px 24px rgba(46, 211, 120, .35);
  --ring: 0 0 0 3px rgba(46, 211, 120, .25);

  /* A MESMA FONTE DA VITRINE. O painel usava Inter Tight (mais estreita) e a
     vitrine, Inter — com as duas abertas lado a lado dava para ver a troca. */
  --font: 'Inter', 'Inter Tight', 'Segoe UI', system-ui, sans-serif;
  /* Escala da vitrine, para o painel falar a mesma língua. */
  --t-rotulo: 11px;   --ls-rotulo: .032em;
  --t-corpo: 13.5px;
  --t-titulo: 22px;   --ls-titulo: -.01em;
  --t-titulo-sec: 15px;
  --ease: cubic-bezier(.22, .8, .3, 1);
}

* { box-sizing: border-box; }
html, body { height: 100%; }
body {
  margin: 0; font-family: var(--font); font-size: 13.5px; line-height: 1.55;
  color: var(--text); background: var(--bg);
  -webkit-font-smoothing: antialiased; text-rendering: optimizeLegibility;
}

.hidden { display: none !important; }
.muted { color: var(--muted); }
.err { color: var(--red); min-height: 1.2em; margin: 8px 0 0; font-size: 13px; }
.lead { margin: 0 0 6px; }
code {
  background: var(--brand-bg); border: 1px solid var(--border2); border-radius: 8px;
  padding: 1px 8px; font-size: .87em; color: var(--verde-deep);
  font-family: 'SF Mono', 'Cascadia Code', Consolas, monospace;
}
a { color: var(--verde-deep); text-decoration: none; }
a:hover { color: var(--verde-deep); text-decoration: underline; }

/* O título é grande e LEVE: quem grita é o tamanho, não o peso — é a
   assinatura da vitrine, e ela cabe igualmente bem numa tela de trabalho. */
h1 { font-size: var(--t-titulo); font-weight: 500; letter-spacing: var(--ls-titulo); margin: 0 0 4px; }
h2 { font-size: var(--t-titulo-sec); font-weight: 500; letter-spacing: -.01em; margin: 0 0 12px; }
h3, h4 { font-weight: 500; letter-spacing: -.01em; }

::selection { background: rgba(46, 211, 120, .3); }
:focus-visible { outline: 2px solid var(--verde-esc); outline-offset: 2px; border-radius: 8px; }

* { scrollbar-width: thin; scrollbar-color: #c3dccb transparent; }
::-webkit-scrollbar { width: 8px; height: 8px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: #c3dccb; border-radius: 20px; border: 2px solid transparent; background-clip: content-box; }
::-webkit-scrollbar-thumb:hover { background: #a3c6ae; border: 2px solid transparent; background-clip: content-box; }

.page { padding: 26px 32px 48px; overflow-y: auto; height: calc(100vh - var(--topbar-h)); height: calc(100dvh - var(--topbar-h)); }
.page-head { margin-bottom: 22px; }
.page-head h1 { font-size: 22px; }
.page-head p { margin: 3px 0 0; color: var(--muted); font-size: 13px; font-weight: 500; }
#view > .page, #view > .inbox { animation: fadeUp .3s var(--ease) both; }
@keyframes fadeUp { from { opacity: 0; transform: translateY(10px); } }

/* ---------- marca ---------- */
.brand { display: flex; align-items: center; gap: 11px; }
.brand-mark {
  width: 38px; height: 38px; flex-shrink: 0; border-radius: 12px;
  background: var(--verde);
  display: flex; align-items: center; justify-content: center; color: var(--ink-on-verde);
  box-shadow: 0 6px 16px rgba(46, 211, 120, .4); overflow: hidden;
}
.brand-mark svg { width: 21px; height: 21px; }
.brand-mark img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* a logo já é um ícone próprio — sem fundo/brilho verde atrás dela */
.brand-mark:has(img) { background: transparent; box-shadow: none; }
.brand-text { display: flex; flex-direction: column; line-height: 1.15; }
/* A palavra segue a MARCA: o K do logotipo é um geométrico pesado, então o
   nome ao lado usa o peso máximo da Inter Tight e um respiro entre as letras.
   Com -.03em as letras encostavam e o conjunto ficava mais leve que o símbolo,
   o que fazia os dois parecerem de marcas diferentes. */
/* A MARCA ESCRITA é uma imagem-máscara: a palavra assume a cor do lugar
   onde está (clara na barra escura, escura no login claro) e some a
   necessidade de pintar o "fy" à parte. */
/* A palavra DESCE 11,5% da própria altura para ficar na linha do ícone: o rabo
   do y ocupa 22,5% da imagem, e centrar a CAIXA deixa o corpo das letras ACIMA
   do centro do ícone. Em porcentagem, a correção vale em qualquer
   tamanho, porque translateY(%) se mede pela altura do elemento. */
.brand-name { display: block; width: 104px; height: 26px; background: currentColor;
  transform: translateY(11.5%);
  -webkit-mask: url(/assets/koonfy-marca.webp) left center/contain no-repeat;
  mask: url(/assets/koonfy-marca.webp) left center/contain no-repeat; }
/* O "fy" usa o MESMO verde do Loader (#2ED378 = --verde-esc) e da logo. Já
   esteve em --verde-deep por contraste, mas aí a palavra Koonfy aparecia com
   três verdes diferentes entre o splash, a landing e o painel — e a marca
   precisa ser a mesma em todo lugar. */
.brand-sub { font-size: 9.5px; text-transform: uppercase; letter-spacing: 1.4px; color: var(--faint); font-weight: 500; }

/* ---------- login ---------- */
.login-wrap {
  display: flex; align-items: center; justify-content: center; min-height: 100vh; min-height: 100dvh; padding: 20px;
  background: linear-gradient(180deg, var(--bg) 0%, var(--brand-bg) 100%);
}
.login-card {
  /* `max-width` porque 400px fixos só cabem em tela grande. Hoje o cartão
     encolhe por ser item de flex, mas basta um filho com largura mínima para
     a conta estourar e sobrar branco ao lado. */
  width: 400px; max-width: 100%; padding: 40px 38px 30px; display: flex; flex-direction: column; gap: 13px;
  background: var(--card); border: 1px solid var(--border2); border-radius: 26px;
  box-shadow: 0 30px 80px rgba(20, 60, 20, .16);
  animation: cardIn .5s var(--ease) both;
}
@keyframes cardIn { from { opacity: 0; transform: translateY(18px); } }
.login-brand { margin-bottom: 14px; }
.login-card h1 { font-size: 23px; margin: 0; letter-spacing: -.03em; }
/* Código de indicação preenchido pelo link de afiliado: visível, porém travado */
.login-card input.locked {
  background: var(--brand-bg); border-color: var(--brand-border);
  color: var(--verde-deep); font-weight: 500; letter-spacing: .06em;
  cursor: not-allowed;
}
.login-card input.locked:focus { box-shadow: none; border-color: var(--brand-border); }
.ref-locked {
  display: flex; align-items: center; gap: 6px;
  font-size: 11.5px; font-weight: 600; color: var(--verde-deep);
}
.ref-locked::before {
  content: ''; width: 11px; height: 11px; flex-shrink: 0;
  background: currentColor;
  -webkit-mask: var(--lock-ic) center/contain no-repeat;
  mask: var(--lock-ic) center/contain no-repeat;
}
:root { --lock-ic: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.4' stroke-linecap='round'%3E%3Crect x='4' y='10.5' width='16' height='11' rx='2.5'/%3E%3Cpath d='M8 10.5V7a4 4 0 0 1 8 0v3.5'/%3E%3C/svg%3E"); }
.login-card .brand-name { color: var(--text); }
.hint { font-size: 12.5px; color: var(--muted); margin: 4px 0 0; text-align: center; font-weight: 500; }

/* ---------- shell ---------- */
#app { display: flex; height: 100vh; height: 100dvh; }
.sidebar {
  width: 252px; flex-shrink: 0; display: flex; flex-direction: column;
  background: var(--sidebar); border-right: 1px solid var(--border2);
  color: var(--sidebar-text); padding: 18px 12px 12px;
}
.sidebar .brand { padding: 2px 8px 16px; border-bottom: 1px solid var(--border); }
.sidebar .brand-name { color: var(--tinta); }
.sidebar .sidebar .brand-sub { color: #93a092; }
.sidebar nav { display: flex; flex-direction: column; gap: 2px; margin-top: 12px; flex: 1; overflow-y: auto; padding-bottom: 8px; }
/* Rótulo de utilidade: 11px, caixa alta e tracking positivo — lê como
   marca de interface, não como frase. Igual ao da vitrine. */
.nav-label {
  font-size: var(--t-rotulo); font-weight: 500; letter-spacing: var(--ls-rotulo);
  text-transform: uppercase; color: var(--muted); padding: 18px 14px 7px;
}
.nav-item {
  display: flex; align-items: center; gap: 11px; padding: 8.5px 13px; border-radius: 10px;
  color: var(--sidebar-text); text-decoration: none; font-size: 13px; font-weight: 500;
  position: relative; transition: background .15s, color .15s;
}
.nav-item svg { width: 17px; height: 17px; flex-shrink: 0; opacity: .85; transition: opacity .15s; }
.nav-item:hover { background: var(--sidebar-hover); color: var(--tinta); text-decoration: none; }
.nav-item:hover svg { opacity: 1; }
.nav-item.active {
  background: var(--menu-ativo); color: var(--menu-tinta); font-weight: 500;
  box-shadow: 0 6px 18px var(--menu-brilho);
}
.nav-item.active svg { color: var(--menu-tinta); opacity: 1; }
.badge {
  margin-left: auto; background: var(--menu-ativo); color: var(--menu-tinta); border-radius: 20px;
  font-size: 10px; padding: 1px 7px; font-weight: 500;
}
.nav-item.active .badge { background: var(--menu-tinta); color: var(--menu-ativo); }
.sidebar-foot { padding: 12px 8px 4px; border-top: 1px solid var(--border); }
/* SUPORTE no pé da barra. Mesmo desenho dos itens do menu — é um link de
   navegação como os outros —, mas discreto: não é uma tela do produto, é a
   saída para quando o produto não resolve. Dar a ele o mesmo peso das
   funcionalidades convidaria a clicar antes de tentar. */
.nav-suporte {
  display: flex; align-items: center; gap: 11px; padding: 8.5px 13px; margin-bottom: 8px;
  border-radius: 10px; color: var(--faint); text-decoration: none;
  font-size: 12.5px; font-weight: 500; transition: background .15s, color .15s;
}
.nav-suporte svg { width: 16px; height: 16px; flex-shrink: 0; }
.nav-suporte:hover { background: var(--sidebar-hover); color: var(--sidebar-text); text-decoration: none; }
.version { font-size: 10.5px; color: var(--faint); font-weight: 600; }

.shell { flex: 1; min-width: 0; display: flex; flex-direction: column; }
main#view { flex: 1; min-height: 0; }

/* ---------- topbar ---------- */
/* A altura do topo é VARIÁVEL porque ela cresce com o recorte da tela (notch,
   ilha dinâmica, barra de status do PWA). Quem desconta o topo para calcular a
   própria altura usa a mesma variável, então nada fica fora de lugar quando o
   recorte existe. */
.topbar {
  height: var(--topbar-h); flex-shrink: 0; box-sizing: border-box;
  padding-top: env(safe-area-inset-top, 0px);
  background: var(--glass);
  backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--border2);
  display: flex; align-items: center; gap: 18px; padding-left: 24px; padding-right: 24px;
  position: relative; z-index: 100;   /* acima do #view p/ o dropdown de notificações ficar na frente */
}
.topbar h2 { margin: 0; font-size: 15px; font-weight: 500; flex: 1; letter-spacing: -.02em; }
/* Mesma máscara da marca da barra lateral, e por isso a mesma imagem: dois
   desenhos diferentes da mesma palavra apareceriam como duas marcas. Menor,
   porque aqui ela divide a linha com a busca e os botões. Nasce escondida — só
   o `@media` do celular a mostra. */
.tb-marca {
  display: none; flex: none; width: 82px; height: 21px; background: currentColor;
  color: var(--text);
  -webkit-mask: url(/assets/koonfy-marca.webp) left center/contain no-repeat;
  mask: url(/assets/koonfy-marca.webp) left center/contain no-repeat;
}
.tb-right { display: flex; align-items: center; gap: 12px; }

/* ---- Seletor da conta do WhatsApp (canais) ---- */
.ch-wrap { position: relative; }
.ch-dot { width: 7px; height: 7px; border-radius: 50%; flex: 0 0 auto; }
.ch-dot.on  { background: var(--verde); box-shadow: 0 0 0 3px color-mix(in srgb, var(--verde) 22%, transparent); }
.ch-dot.off { background: var(--border2); }
.ch-badge {
  min-width: 17px; height: 17px; padding: 0 5px; border-radius: 99px;
  background: var(--verde-esc); color: #fff; font: inherit; font-weight: 500; font-size: 11px;
  line-height: 17px; text-align: center;
}
.ch-menu {
  position: absolute; top: calc(100% + 8px); right: 0; z-index: 60;
  width: 268px; padding: 6px;
  background: var(--card); border: 1px solid var(--border2); border-radius: 13px;
  box-shadow: var(--shadow-lg);
}
.ch-menu.hidden { display: none; }
.ch-menu-head {
  padding: 8px 10px 6px; color: var(--muted);
  font: inherit; font-weight: 500; font-size: 11px; letter-spacing: .08em; text-transform: uppercase;
}
.ch-menu-sep { height: 1px; margin: 5px 4px; background: var(--border); }
/* Sair encerra a sessão: vermelho, como todo destrutivo do painel. O ícone
   acompanha, senão só o texto muda de cor e a linha fica desalinhada do resto. */
.ch-item.ch-sair b { color: var(--red); }
.ch-item.ch-sair svg { color: var(--red); }
.ch-item.ch-sair:hover { background: var(--red-bg); }
.ch-item {
  display: flex; align-items: center; gap: 9px; width: 100%;
  padding: 8px 10px; border: 0; border-radius: 9px;
  background: none; color: var(--text); text-align: left;
  font: inherit; font-weight: 600; font-size: 13px; cursor: pointer;
}
.ch-item:hover { background: var(--sidebar-hover); }
.ch-item.sel { background: var(--brand-bg); }
.ch-item-txt { flex: 1; min-width: 0; }
.ch-item-txt b { display: block; font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ch-item-txt em { display: block; margin-top: 2px; font-size: 11.5px; font-weight: 500; font-style: normal; color: var(--muted); }
@media (max-width: 860px) { .ch-menu { width: 250px; } }
/* O avatar virou botão: abre o seletor de conta de WhatsApp */
.tb-user {
  display: flex; align-items: center; gap: 9px;
  padding: 4px 10px 4px 4px; border: 1px solid transparent; border-radius: 99px;
  background: none; font: inherit; font-size: 13px; font-weight: 500; color: var(--text2);
  cursor: pointer; transition: background .15s, border-color .15s;
}
.tb-user:hover { background: var(--bg2); border-color: var(--border2); }
.tb-user[aria-expanded="true"] { background: var(--bg2); border-color: var(--verde); }
.tb-who { display: flex; flex-direction: column; align-items: flex-start; line-height: 1.25; min-width: 0; }
.tb-who b { font-weight: 500; font-size: 13px; color: var(--text2); max-width: 150px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tb-who em {
  display: flex; align-items: center; gap: 4px;
  font-size: 11px; font-weight: 600; font-style: normal; color: var(--verde-deep);
  max-width: 150px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
:root[data-theme="dark"] .tb-who em { color: var(--verde); }
.tb-caret { color: var(--muted); flex-shrink: 0; transition: transform .18s; }
.tb-user[aria-expanded="true"] .tb-caret { transform: rotate(180deg); }
.ch-lim { margin-left: auto; font-weight: 500; text-transform: none; letter-spacing: 0; color: var(--muted); }
.ch-empty { margin: 4px 10px 8px; font-size: 12.5px; font-weight: 500; color: var(--muted); }
.ch-item.add b { color: var(--verde-deep); }
:root[data-theme="dark"] .ch-item.add b { color: var(--verde); }
.ch-item.add svg { color: var(--verde-deep); }
:root[data-theme="dark"] .ch-item.add svg { color: var(--verde); }
@media (max-width: 860px) { .tb-who { display: none; } }

/* Filtro de conta nas listas (contatos e funil) */
.ct-tools { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-bottom: 12px; }
.ct-tools > input { flex: 1; min-width: 220px; }
.scope-pick { display: flex; align-items: center; gap: 7px; flex-wrap: wrap; }
.scope-lbl { display: inline-flex; align-items: center; gap: 5px; font-size: 11.5px; font-weight: 500; color: var(--muted); text-transform: uppercase; letter-spacing: .05em; }
.scope-btn {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 6px 12px; border: 1px solid var(--border2); border-radius: 99px;
  background: var(--card); color: var(--text2);
  font: inherit; font-weight: 500; font-size: 12.5px; cursor: pointer;
  transition: border-color .15s, background .15s, color .15s;
}
.scope-btn:hover { border-color: var(--verde); }
.scope-btn.on { background: var(--brand-bg); border-color: var(--brand-border); color: var(--verde-deep); }
:root[data-theme="dark"] .scope-btn.on { color: var(--verde); }
.scope-btn b { font-weight: 500; opacity: .75; }
.ch-tag {
  display: inline-block; padding: 2px 9px; border-radius: 99px;
  background: var(--bg2); border: 1px solid var(--border);
  font-size: 11px; font-weight: 500; color: var(--muted); white-space: nowrap;
}
#fn-scope:not(:empty) { margin-bottom: 16px; }
.tb-avatar {
  width: 33px; height: 33px; border-radius: 50%; background: var(--verde);
  color: var(--ink-on-verde); display: flex; align-items: center; justify-content: center;
  font-weight: 500; font-size: 12.5px;
  box-shadow: 0 0 0 2px #fff, 0 0 0 3.5px var(--border2);
}
.status-chip {
  display: inline-flex; align-items: center; gap: 7px; font-size: 12px; font-weight: 500;
  padding: 6px 14px; border-radius: 9px; cursor: pointer; border: 1px solid var(--border2);
  background: var(--card); color: var(--muted); transition: box-shadow .15s, transform .15s;
}
.status-chip:hover { box-shadow: var(--shadow-sm); transform: translateY(-1px); }
.status-chip i { width: 7px; height: 7px; border-radius: 50%; background: var(--faint); }
.status-chip.on { background: var(--brand-bg); border-color: var(--brand-border); color: var(--verde-deep); }
.status-chip.on i { background: var(--verde-esc); box-shadow: 0 0 0 3px rgba(16, 185, 129, .2); }
.status-chip.warn { background: var(--amber-bg); border-color: var(--amber-border); color: #b26205; }
.status-chip.warn i { background: var(--amber); animation: pulseDot 1.8s infinite; }
@keyframes pulseDot { 50% { opacity: .45; } }

/* ---------- forms ---------- */
label { display: flex; flex-direction: column; gap: 6px; font-size: 12.5px; font-weight: 500; color: var(--text2); }
input, textarea, select {
  background: var(--card); border: 1px solid var(--border2); color: var(--text);
  border-radius: var(--radius-sm); padding: 9.5px 14px; font: inherit; width: 100%;
  transition: border-color .15s, box-shadow .15s;
}
input::placeholder, textarea::placeholder { color: #6b7a69; font-weight: 500; }
input:hover, textarea:hover, select:hover { border-color: #b9d8c4; }
input:focus, textarea:focus, select:focus {
  outline: none; border-color: var(--verde-esc);
  box-shadow: var(--ring);
}
textarea { resize: vertical; min-height: 70px; }
select {
  appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%237b8a79' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 12px center; padding-right: 34px;
}

/* ---------- botões (pill, como a landing) ---------- */
/* Botões: pill, peso moderado, sombra discreta — sóbrio e profissional */
.btn {
  background: var(--card); color: var(--btn-ink); border: 1px solid var(--border2);
  border-radius: 10px; padding: 9px 18px; font: inherit; font-weight: 650; font-size: 13px;
  letter-spacing: .005em;
  cursor: pointer; white-space: nowrap; transition: background .18s var(--ease), border-color .18s var(--ease), color .18s var(--ease), box-shadow .18s var(--ease);
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
}
.btn:hover { border-color: var(--btn-verde); color: var(--btn-ink); background: var(--brand-bg); }
/* TINTA ESCURA no botão verde, e não branco.
   Branco sobre o verde da marca dá contraste de 2,19:1 — menos da metade do
   mínimo legível (4,5:1). Para o branco funcionar, o verde teria que ir até
   #098443, um tom apagado que jogaria fora a cor da logo. A tinta escura sobre
   o MESMO verde dá 6,43:1: a marca fica intacta e o texto fica nítido, no
   claro e no escuro. É o botão mais usado do produto; ilegível ali é caro. */
/* BOTÃO PRINCIPAL — verde da logo (#2ED378, o mesmo do Loader) com texto
   BRANCO, claro e escuro. Já usou tinta escura por contraste; a decisão do
   produto é o branco, que é como a marca se apresenta. O hover ESCURECE (e não
   clareia, como fazia com a tinta escura) porque com texto branco escurecer é
   o que ganha legibilidade no momento do clique. */
.btn.primary {
  background: var(--btn-verde); border-color: var(--btn-verde); color: var(--btn-tinta);
  box-shadow: 0 1px 2px rgba(16, 116, 82, .25), 0 4px 12px rgba(25, 169, 90, .22);
}
.btn.primary:hover {
  background: var(--btn-verde-hover); border-color: var(--btn-verde-hover);
  box-shadow: 0 2px 4px rgba(16, 116, 82, .3), 0 6px 16px rgba(25, 169, 90, .32);
  color: var(--btn-tinta);
}
.btn.primary:disabled { background: var(--btn-verde); border-color: var(--btn-verde); color: var(--btn-tinta); }
.btn.primary svg { color: currentColor; }
.btn.danger { color: var(--red-ink); }
.btn.danger:hover { background: var(--red-bg); border-color: var(--red-border); color: var(--red-ink); }
.btn.ghost { background: transparent; border-color: transparent; }
.btn.ghost:hover { background: var(--brand-bg); border-color: transparent; }
.btn.small { padding: 5.5px 13px; font-size: 12px; border-radius: 8px; }
.btn.block { width: 100%; padding: 12px; font-size: 14.5px; border-radius: 11px; }
.btn:disabled { opacity: .5; cursor: default; transform: none; }
.btn:active { transform: translateY(0) scale(.985); }
/* O botão SÓLIDO usa um vermelho um passo mais fechado que o `--red` do
   semáforo: com #e5484d, o branco em cima dava 3,91:1 e não passava. Em
   #d93a3f dá 4,54:1. O `--red` de texto e de borda continua o mesmo — muda só
   o preenchimento, onde há texto branco por cima. */
.btn.danger-solid {
  background: #d93a3f; border-color: #d93a3f; color: #fff;
  box-shadow: 0 1px 2px rgba(160, 40, 45, .25), 0 4px 12px rgba(229, 72, 77, .2);
}
.btn.danger-solid:hover { background: #c62a30; border-color: #c62a30; color: #fff; }
.btn.lg { padding: 13px 32px; font-size: 15px; }

.row { display: flex; gap: 10px; align-items: end; flex-wrap: wrap; }
.row > * { flex: 1; min-width: 140px; }
.row > .btn, .row > .no-grow { flex: 0 0 auto; min-width: 0; }

/* ---------- cards ---------- */
.card {
  background: var(--card); border: 1px solid var(--border); border-radius: var(--radius);
  padding: 24px; margin-bottom: 16px; box-shadow: var(--shadow-xs);
  transition: box-shadow .25s var(--ease);
}
.card h2 { display: flex; align-items: center; gap: 10px; margin-bottom: 14px; }
.card h2 .ic {
  color: var(--verde-esc); flex-shrink: 0;
  width: 34px; height: 34px; padding: 7px; border-radius: 12px;
  background: var(--brand-bg);
}

/* ícones SVG inline */
.ic { vertical-align: -3px; flex-shrink: 0; }
.chat-empty .ce-ic .ic { color: #b9d3bf; }
.empty-state .big .ic { color: #b9d3bf; }
details.log summary .ic { color: var(--muted); }
.msg .st.fail .ic { vertical-align: -2px; }

/* cabeçalho de boas-vindas (dashboard) */
.hero-head {
  display: flex; align-items: flex-end; justify-content: space-between; gap: 20px; flex-wrap: wrap;
  margin-bottom: 24px; padding: 4px 2px 0;
}
.hero-head h1 { font-size: 26px; margin: 8px 0 3px; color: var(--text); letter-spacing: -.03em; font-weight: 500; }
.hero-head p { color: var(--muted); font-size: 13.5px; margin: 0; font-weight: 500; }
.hh-date {
  display: inline-flex; align-items: center; gap: 7px;
  font-size: 11px; font-weight: 500; letter-spacing: .08em; text-transform: uppercase;
  color: var(--verde-deep); background: var(--card); border: 1px solid var(--border2);
  padding: 5px 14px; border-radius: 99px; box-shadow: 0 4px 14px rgba(20, 60, 20, .06);
}
.hh-actions { display: flex; gap: 10px; flex-wrap: wrap; }

/* KPIs */
.grid-cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(185px, 1fr)); gap: 15px; margin-bottom: 16px; }
.stat {
  position: relative; display: flex; flex-direction: column; gap: 2px;
  background: var(--card); border: 1px solid var(--border); border-radius: var(--radius);
  padding: 20px; box-shadow: var(--shadow-xs);
  transition: box-shadow .25s var(--ease), transform .25s var(--ease), border-color .25s;
}
.stat:hover { box-shadow: var(--shadow); transform: translateY(-4px); border-color: var(--border2); }
/* KPIs de venda são clicáveis (levam ao Pagamentos) sem parecer link */
a.stat { text-decoration: none; color: inherit; }
.stat-ico {
  position: absolute; top: 16px; right: 16px;
  width: 34px; height: 34px; border-radius: 12px; margin: 0;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--brand-bg); color: var(--verde-esc);
}
.stat-ico .ic { color: inherit; }
.stat .num {
  font-size: 28px; font-weight: 500; letter-spacing: -.03em; line-height: 1.1;
  color: var(--text); font-variant-numeric: tabular-nums; margin-top: 2px;
  /* O ícone é absoluto no canto: sem esta faixa reservada, um valor grande
     passava por baixo dele e ficava tapado. O `curto()` encolhe o número e
     isto garante que nem um caso extremo encoste no ícone. */
  padding-right: 36px; min-width: 0;
  /* Em tela estreita o valor quebrava entre "R$" e o número, virando duas
     linhas dentro do cartão. Ele é curto o bastante para caber numa só. */
  white-space: nowrap;
}
.stat .num.bad { color: var(--red); }
.stat .lbl {
  color: var(--muted); font-size: 11px; font-weight: 500;
  text-transform: uppercase; letter-spacing: .07em; order: -1;
  padding-right: 36px; min-width: 0;
}
.stat .spark { margin-top: 10px; display: block; }

.kpi-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 15px; margin-bottom: 16px; }
.kpi {
  background: var(--card); border: 1px solid var(--border); border-radius: var(--radius);
  padding: 19px 20px 14px; box-shadow: var(--shadow-xs);
  transition: box-shadow .25s, transform .25s, border-color .25s;
}
.kpi:hover { box-shadow: var(--shadow); transform: translateY(-3px); border-color: var(--border2); }
.kpi-top { display: flex; justify-content: space-between; align-items: center; margin-bottom: 7px; }
.kpi .lbl { font-size: 11px; font-weight: 500; color: var(--muted); text-transform: uppercase; letter-spacing: .07em; }
.kpi .val { font-size: 28px; font-weight: 500; letter-spacing: -.03em; font-variant-numeric: tabular-nums; }
.kpi .spark { margin-top: 8px; display: block; }
.delta { font-size: 11px; font-weight: 500; padding: 2.5px 9px; border-radius: 99px; font-variant-numeric: tabular-nums; }
.delta.up { background: var(--brand-bg); color: var(--verde-deep); }
.delta.down { background: var(--red-bg); color: var(--red); }
.delta.flat { background: var(--bg2); color: var(--muted); }

/* gráficos */
.chart-card svg text { font-family: var(--font); }
.legend { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; color: var(--muted); font-weight: 500; margin-left: 14px; }
.legend i { width: 9px; height: 9px; border-radius: 3px; display: inline-block; }
.two-col { display: grid; grid-template-columns: 1fr; gap: 16px; }
@media (min-width: 1080px) { .two-col { grid-template-columns: 1.6fr 1fr; } .two-col.even { grid-template-columns: 1fr 1fr; } }

.hbars { display: flex; align-items: flex-end; gap: 4px; height: 120px; padding-top: 8px; }
.hbars .hb { flex: 1; background: linear-gradient(180deg, var(--verde), var(--verde-esc)); border-radius: 6px 6px 3px 3px; opacity: .9; min-height: 3px; transition: opacity .15s, filter .15s; }
.hbars .hb:hover { opacity: 1; filter: brightness(1.05); }
.hbars-x { display: flex; justify-content: space-between; font-size: 10.5px; color: var(--faint); margin-top: 6px; font-weight: 600; }

.hrow { display: flex; align-items: center; gap: 12px; margin: 11px 0; }
.hrow .hl { width: 96px; font-size: 12.5px; color: var(--text2); font-weight: 500; flex-shrink: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.hrow .track { flex: 1; height: 9px; background: #e0f2ea; border-radius: 99px; overflow: hidden; }
.hrow .fill { height: 100%; border-radius: 99px; background: linear-gradient(90deg, var(--verde), var(--verde-esc)); transition: width .5s var(--ease); }
.hrow .hv { width: 74px; text-align: right; font-size: 12.5px; font-weight: 500; flex-shrink: 0; font-variant-numeric: tabular-nums; }

pre.out {
  background: var(--tinta); color: #b9d0c8; border: 1px solid #243831; border-radius: 14px;
  padding: 14px; font-size: 12px; line-height: 1.6; overflow: auto; max-height: 320px;
  white-space: pre-wrap; word-break: break-all;
  font-family: 'SF Mono', 'Cascadia Code', Consolas, monospace;
}
.check-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 9px; font-size: 13.5px; }
.check-list li { display: flex; gap: 9px; align-items: center; font-weight: 600; }
.ok-dot { color: var(--verde-deep); }
.bad-dot { color: var(--red); }

/* ---------- tabelas ---------- */
table { width: 100%; border-collapse: collapse; }
th, td { text-align: left; padding: 12px; border-bottom: 1px solid #eef6ef; font-size: 13px; vertical-align: middle; }
td { color: var(--text2); font-weight: 500; }
td b { color: var(--text); font-weight: 500; }
th {
  color: var(--faint); font-weight: 500; font-size: 10.5px; text-transform: uppercase; letter-spacing: .08em;
  background: transparent; border-bottom: 1px solid var(--border2); padding: 9px 12px;
}
tbody tr { transition: background .12s; }
tbody tr:hover td { background: #f7fbf7; }
tbody tr:last-child td { border-bottom: none; }

.tag {
  display: inline-block; background: var(--blue-bg); color: var(--blue-ink); border: 1px solid var(--blue-border);
  border-radius: 99px; padding: 1px 9px; font-size: 11px; font-weight: 500; margin: 1px 3px 1px 0;
}
.pill {
  display: inline-flex; align-items: center; gap: 6px; border: 1px solid var(--border2);
  border-radius: 99px; padding: 3px 11px; font-size: 11.5px; font-weight: 500; color: var(--muted);
  background: var(--card);
}
.pill::before { content: ''; width: 6px; height: 6px; border-radius: 50%; background: var(--faint); }
.pill.APPROVED, .pill.done, .pill.read { color: var(--verde-deep); border-color: var(--brand-border); background: var(--brand-bg); }
.pill.APPROVED::before, .pill.done::before, .pill.read::before { background: var(--verde-esc); }
/* #b26205 sobre o tint âmbar dava 4,28:1 — um passo mais fechado resolve. */
.pill.PENDING, .pill.running, .pill.pending { color: #9a5504; border-color: var(--amber-border); background: var(--amber-bg); }
.pill.PENDING::before, .pill.running::before, .pill.pending::before { background: var(--amber); }
.pill.REJECTED, .pill.failed { color: var(--red); border-color: var(--red-border); background: var(--red-bg); }
.pill.REJECTED::before, .pill.failed::before { background: var(--red); }
.pill.sent, .pill.delivered, .pill.accepted { color: var(--blue-ink); border-color: var(--blue-border); background: var(--blue-bg); }
.pill.sent::before, .pill.delivered::before, .pill.accepted::before { background: var(--blue-ink); }

.progress { height: 9px; background: #e0f2ea; border-radius: 99px; overflow: hidden; min-width: 90px; }
.progress i { display: block; height: 100%; background: linear-gradient(90deg, var(--verde), var(--verde-esc)); border-radius: 99px; transition: width .4s var(--ease); }

/* ---------- inbox ---------- */
.inbox { display: flex; height: calc(100vh - var(--topbar-h)); height: calc(100dvh - var(--topbar-h)); }
.conv-list { width: 332px; flex-shrink: 0; border-right: 1px solid var(--border2); display: flex; flex-direction: column; background: var(--card); }
.conv-head { padding: 16px 14px 12px; border-bottom: 1px solid var(--border); }
.conv-head input { margin-top: 10px; background: var(--bg); border-color: transparent; border-radius: 10px; }
.conv-head input:hover { border-color: var(--border2); }
.conv-head input:focus { background: var(--card); border-color: var(--verde-esc); box-shadow: var(--ring); }
.conv-scroll { overflow-y: auto; flex: 1; padding: 7px; }
.conv-item {
  display: flex; gap: 11px; padding: 10px 11px; cursor: pointer; align-items: center;
  border-radius: 16px; margin-bottom: 2px; transition: background .15s, box-shadow .15s;
  border: 1px solid transparent;
}
.conv-item:hover { background: #f4faf4; }
.conv-item.active { background: #f2fce9; border-color: var(--brand-border); box-shadow: 0 4px 14px rgba(110, 200, 80, .14); }
.avatar {
  width: 38px; height: 38px; border-radius: 50%; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  font-weight: 500; font-size: 13px; color: var(--verde-deep);
}
.conv-meta { flex: 1; min-width: 0; }
.conv-meta .name { font-weight: 500; display: flex; justify-content: space-between; gap: 6px; font-size: 13.5px; color: var(--text); }
.conv-meta .name time { color: var(--faint); font-size: 11px; font-weight: 600; flex-shrink: 0; }
.conv-meta .prev { color: var(--muted); font-size: 12.5px; font-weight: 500; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; margin-top: 1px; display: flex; gap: 6px; align-items: center; }
.conv-meta .prev .badge { margin-left: auto; }

.chat { flex: 1; display: flex; flex-direction: column; min-width: 0; background: #e9f5ef; }
.chat-empty { flex: 1; display: flex; align-items: center; justify-content: center; flex-direction: column; gap: 10px; color: var(--muted); text-align: center; font-weight: 600; }
.chat-empty > div:first-child { font-size: 46px; opacity: .5; }
.chat-head {
  padding: 11px 18px; border-bottom: 1px solid var(--border2); display: flex; align-items: center; gap: 12px;
  background: var(--glass); backdrop-filter: blur(8px);
}
.chat-head .info { flex: 1; min-width: 0; }
.chat-head .info b { display: block; font-size: 14px; font-weight: 500; }
.chat-head .info span { font-size: 12px; color: var(--muted); font-weight: 600; }
.chat-scroll {
  flex: 1; overflow-y: auto; padding: 22px 26px; display: flex; flex-direction: column; gap: 3px;
  background: #e9f5ef;
}
/* O balão acompanha o texto em vez de esticar até um teto largo: `fit-content`
   com `max-width` faz a mensagem curta ficar curta. Antes, a caixa reservava
   62% da largura mesmo para "ok", e o espaço vazio à direita era o que mais
   incomodava. O respiro interno também foi apertado: 9px de altura por linha
   somavam muito numa conversa longa. */
.msg {
  width: fit-content; max-width: min(58%, 430px);
  padding: 7px 11px 5px; border-radius: 14px; position: relative;
  word-wrap: break-word; overflow-wrap: anywhere; white-space: pre-wrap;
  font-size: 13.5px; line-height: 1.42;
  animation: msgIn .3s cubic-bezier(.2, 1.2, .4, 1) both; box-shadow: 0 1px 2px rgba(0, 0, 0, .07);
  font-weight: 500; color: var(--text);
}
@keyframes msgIn { from { opacity: 0; transform: scale(.94) translateY(8px); } }
.msg.in { background: var(--card); align-self: flex-start; border-bottom-left-radius: 4px; }
.msg.out { background: #d1fae5; align-self: flex-end; border-bottom-right-radius: 4px; }
/* A hora fica na MESMA linha do fim do texto quando cabe, como no WhatsApp:
   uma linha inteira so para o horario era altura desperdicada em toda
   mensagem. */
.msg .meta { display: flex; gap: 5px; justify-content: flex-end; align-items: center; font-size: 10px; color: var(--muted); margin-top: 1px; font-weight: 600; float: right; margin-left: 10px; }
.msg .st { letter-spacing: -1px; font-weight: 500; color: var(--faint); }
.msg .st.read { color: var(--blue); }
.msg .st.fail { color: var(--red); cursor: help; letter-spacing: 0; }
.msg img, .msg video { max-width: min(300px, 72vw); border-radius: 10px; display: block; margin-bottom: 3px; }

.msg .doc { display: inline-flex; gap: 8px; align-items: center; font-weight: 500; }
.msg.tail { margin-bottom: 7px; }
.msg:not(.tail) .meta { display: none; }
/* ---- LINK DENTRO DO BALÃO ----
   Sublinhado, e não só colorido: no balão verde de saída a cor sozinha quase
   não separa o link do texto, e quem enxerga pouca diferença de tom não veria
   que ali tem algo para clicar. O `break-word` é o que impede um link longo de
   esticar o balão até estourar a largura da conversa. */
.msg-link {
  color: var(--verde-deep); text-decoration: underline;
  text-underline-offset: 2px; word-break: break-word;
}
.msg-link:hover { text-decoration-thickness: 2px; }
.msg.out .msg-link { color: #065f46; }
:root[data-theme="dark"] .msg-link { color: var(--verde-esc); }

.msg.in:not(.tail) { border-bottom-left-radius: 14px; }
.msg.out:not(.tail) { border-bottom-right-radius: 14px; }

.date-sep { display: flex; justify-content: center; margin: 14px 0 8px; }
.date-sep span {
  background: var(--glass); border: 1px solid var(--border); border-radius: 99px;
  padding: 3px 13px; font-size: 10.5px; font-weight: 500; color: var(--muted);
  text-transform: uppercase; letter-spacing: .06em; box-shadow: var(--shadow-xs);
}

.composer { border-top: 1px solid var(--border2); padding: 12px 18px 14px; display: flex; flex-direction: column; gap: 9px; background: var(--card); }
.composer .tools { display: flex; gap: 7px; flex-wrap: wrap; align-items: center; }
.composer .tools .btn { padding: 5px 13px; font-size: 12px; }
.composer .line { display: flex; gap: 10px; align-items: flex-end; }
.composer textarea { min-height: 46px; max-height: 150px; border-radius: 14px; padding: 12px 18px; }
.composer select { width: auto; max-width: 220px; font-size: 12.5px; padding: 6px 30px 6px 12px; border-radius: 9px; }
.send-btn {
  width: 46px; height: 46px; padding: 0 !important; border-radius: 14px !important;
  font-size: 16px; display: flex; align-items: center; justify-content: center; flex-shrink: 0;
}

/* ---------- kanban ---------- */
.kanban { display: flex; gap: 14px; overflow-x: auto; padding-bottom: 16px; align-items: flex-start; }
.kcol {
  min-width: 254px; width: 254px; flex-shrink: 0;
  background: #f1f8f2; border: 1px solid var(--border); border-radius: var(--radius);
  transition: border-color .2s, box-shadow .2s;
}
.kcol h3 {
  margin: 0; padding: 13px 15px 10px; font-size: 10.5px; font-weight: 500;
  display: flex; justify-content: space-between; align-items: center;
  color: var(--muted); text-transform: uppercase; letter-spacing: .08em;
}
.kcol h3 span:first-child { display: flex; align-items: center; gap: 8px; }
.kcol h3 span:first-child::before { content: ''; width: 8px; height: 8px; border-radius: 50%; background: var(--verde-esc); }
.kcol h3 span:last-child {
  background: var(--card); border: 1px solid var(--border); border-radius: 99px;
  padding: 0 9px; font-size: 10.5px; color: var(--muted); font-variant-numeric: tabular-nums;
}
.kcol .kbody { padding: 9px; display: flex; flex-direction: column; gap: 9px; min-height: 60px; }
.kcol.drag-over { border-color: var(--verde-esc); box-shadow: 0 0 0 3px rgba(46, 211, 120, .2); }
.kcard {
  background: var(--card); border: 1px solid var(--border); border-radius: 16px; padding: 12px 13px;
  cursor: grab; box-shadow: var(--shadow-xs); transition: box-shadow .2s, transform .2s, border-color .2s;
}
.kcard:hover { box-shadow: 0 10px 26px rgba(20, 60, 20, .12); border-color: var(--border2); transform: translateY(-3px); }
.kcard:active { cursor: grabbing; }
.kcard b { display: block; font-size: 13px; font-weight: 500; }
.kcard .sub { color: var(--muted); font-size: 11.5px; margin: 3px 0 4px; font-weight: 600; }
.kcard.dragging { opacity: .45; transform: rotate(1.5deg) scale(.98); }

/* ---------- modal / toast ---------- */
.modal-back {
  position: fixed; inset: 0; z-index: 300; padding: 20px;
  background: rgba(15, 31, 21, .45); backdrop-filter: blur(5px);
  display: flex; align-items: center; justify-content: center; animation: fadeIn .15s ease both;
}
@keyframes fadeIn { from { opacity: 0; } }
.modal {
  position: relative;
  background: var(--card); border: 1px solid var(--border); border-radius: var(--radius); padding: 24px;
  width: 100%; max-width: 500px; max-height: 88vh; overflow-y: auto;
  display: flex; flex-direction: column; gap: 13px;
  box-shadow: var(--shadow-lg); animation: modalIn .28s cubic-bezier(.2, 1.2, .4, 1) both;
}
@keyframes modalIn { from { opacity: 0; transform: translateY(16px) scale(.96); } }
/* mesma escala do resto do app: h2 global 15px, ícone 34px como no .card */
.modal h2 { margin: 0; font-size: 15px; display: flex; align-items: center; gap: 10px; font-weight: 500; letter-spacing: -.015em; }
.modal h2 .ic {
  color: var(--verde-esc); width: 34px; height: 34px; padding: 7px; border-radius: 12px;
  background: var(--brand-bg);
}
.modal-x {
  position: absolute; top: 16px; right: 16px; background: none; border: none;
  color: var(--faint); cursor: pointer; padding: 7px; border-radius: 50%; display: flex;
  transition: background .12s, color .12s;
}
.modal-x:hover { background: var(--bg2); color: var(--text); }

/* ---------------- CONFIRMAÇÃO DE UMA AÇÃO QUE ACABOU ----------------
   O mesmo visto desenhado da confirmação de pagamento. Um toast diz "salvo" e
   some pelo canto; disparar uma campanha manda mensagem para milhares de
   pessoas e não dá para desfazer — a diferença entre as duas coisas precisa
   aparecer na tela.

   Ele FECHA SOZINHO: é um aviso, não uma pergunta, e obrigar um clique para
   confirmar o que já aconteceu é atrito puro. */
.feito { align-items: center; text-align: center; gap: 0; padding: 34px 26px 30px; }
.feito .selo { width: 84px; height: 84px; }
.feito svg { width: 100%; height: 100%; fill: none; stroke-linecap: round; stroke-linejoin: round; }
.feito .anel { stroke: var(--border); stroke-width: 3; }
/* 277 é o perímetro do círculo de raio 44: o traço nasce recolhido e se fecha
   em volta do visto. */
.feito .risco {
  stroke: var(--verde-esc); stroke-width: 3; stroke-dasharray: 277; stroke-dashoffset: 277;
  transform: rotate(-90deg); transform-origin: 50% 50%;
  animation: fechar .55s cubic-bezier(.2, .7, .3, 1) .05s forwards;
}
.feito .visto {
  stroke: var(--verde-esc); stroke-width: 5; stroke-dasharray: 56; stroke-dashoffset: 56;
  animation: riscar .32s cubic-bezier(.25, .9, .3, 1) .5s forwards;
}
@keyframes fechar { to { stroke-dashoffset: 0; } }
@keyframes riscar { to { stroke-dashoffset: 0; } }
.feito b { display: block; margin-top: 16px; font-size: 17px; font-weight: 600; letter-spacing: -.01em; }
.feito span { display: block; margin-top: 5px; font-size: 13px; color: var(--muted); }
/* Quem pediu menos movimento continua tendo a MESMA informação: o visto
   aparece pronto. A confirmação não é enfeite que se possa suprimir. */
@media (prefers-reduced-motion: reduce) {
  .feito .risco, .feito .visto { animation: none; stroke-dashoffset: 0; }
}

/* De quem é o evento, e o código quando existe. A tela é de todo o SaaS: uma
   falha sem dono obriga a abrir o JSON para saber quem ela atingiu. */
.log-conta {
  font-size: 11px; font-weight: 600; padding: 2px 7px; border-radius: 999px;
  background: var(--bg2); color: var(--muted); white-space: nowrap;
}
.log-cod {
  font-size: 11px; font-weight: 600; padding: 2px 7px; border-radius: 999px;
  background: var(--brand-bg); color: var(--verde-deep); white-space: nowrap;
}
.log-item.ruim .log-cod { background: rgba(229, 72, 77, .12); color: var(--red); }
/* A contagem dentro da aba: número pequeno, sem competir com o rótulo. */
.log-cont { font-size: 11px; opacity: .7; font-variant-numeric: tabular-nums; }

/* De qual dinheiro é a linha. Os dois nunca se somam — o valor da venda é do
   cliente, e o que é seu ali é a taxa —, e sem a marca a tabela vira uma pilha
   de números que parecem todos seus. */
.fin-org {
  font-size: 10.5px; font-weight: 700; padding: 1px 6px; border-radius: 999px;
  margin-left: 6px; letter-spacing: .02em; white-space: nowrap;
}
.fin-org.koonfy { background: var(--brand-bg); color: var(--verde-deep); }
.fin-org.cliente { background: var(--bg2); color: var(--muted); }

/* ---------------- PLATAFORMA EM MANUTENÇÃO ----------------
   Cobre a tela inteira: nada por trás funciona, e deixar o painel visível para
   recusar clique a clique é pior do que dizer de uma vez. */
#manutencao {
  position: fixed; inset: 0; z-index: 900; background: var(--bg);
  display: grid; place-items: center; padding: 24px;
}
.man-cartao {
  max-width: 460px; text-align: center;
  display: flex; flex-direction: column; align-items: center; gap: 4px;
}
.man-ic {
  width: 62px; height: 62px; border-radius: 18px; display: grid; place-items: center;
  background: var(--brand-bg); color: var(--verde-deep); margin-bottom: 14px;
}
.man-cartao h1 { margin: 0; font-size: 24px; font-weight: 600; letter-spacing: -.02em; }
.man-cartao p { margin: 10px 0 0; color: var(--muted); font-size: 14.5px; line-height: 1.55; }
/* O botão é o ÚNICO caminho da tela, e leva o brilho por isso. */
.man-btn { margin-top: 24px; min-width: 260px; }
.man-desde { margin-top: 16px; font-size: 12px; color: var(--faint); }

#toast-root { position: fixed; bottom: 20px; right: 20px; display: flex; flex-direction: column; gap: 9px; z-index: 400; }
.toast {
  background: var(--card); color: var(--text); border: 1px solid var(--border2);
  border-radius: 18px; padding: 13px 17px; font-size: 13px; font-weight: 500; max-width: 360px;
  box-shadow: 0 20px 50px rgba(20, 60, 20, .2); animation: toastIn .32s cubic-bezier(.2, 1.2, .4, 1) both;
  display: flex; gap: 10px; align-items: flex-start;
}
.toast .ic { color: var(--verde-esc); flex-shrink: 0; margin-top: 1px; }
.toast.error { border-color: var(--red-border); }
.toast.error .ic { color: var(--red); }
@keyframes toastIn { from { transform: translateY(16px) scale(.95); opacity: 0; } }

/* ---------- logs ---------- */
/* ---- Webhook & Logs ----
   O evento fala primeiro em português; o JSON continua disponível, mas atrás
   de um link discreto, porque é o detalhe de quem foi investigar. */
.log-item {
  border: 1px solid var(--border); border-radius: 16px; margin-bottom: 8px;
  background: var(--card); box-shadow: var(--shadow-xs); padding: 13px 16px;
}
.log-item.ruim { border-color: var(--red-border); background: var(--red-bg); }
.log-top { display: flex; align-items: center; gap: 10px; }
.log-top b { font-size: 13.5px; font-weight: 500; letter-spacing: -.01em; }
.log-ic { display: inline-flex; color: var(--muted); flex: none; }
.log-item.ruim .log-ic { color: var(--red); }
.log-quando { margin-left: auto; font-size: 11.5px; white-space: nowrap; }
.log-desc { margin: 5px 0 0 25px; font-size: 12.5px; color: var(--text2); line-height: 1.5; }
.log-cru { margin: 8px 0 0 25px; }
.log-cru summary {
  cursor: pointer; font-size: 11.5px; font-weight: 500; color: var(--muted);
  list-style: none; display: inline-flex; align-items: center; gap: 5px;
}
.log-cru summary::-webkit-details-marker { display: none; }
.log-cru summary::before { content: '▸'; font-size: 10px; }
.log-cru[open] summary::before { content: '▾'; }
.log-cru summary:hover { color: var(--verde-deep); }
.log-cru .out { margin-top: 8px; }
@media (max-width: 620px) {
  .log-top { flex-wrap: wrap; }
  .log-quando { margin-left: 25px; width: 100%; }
  .log-desc, .log-cru { margin-left: 0; }
}

details.log { border: 1px solid var(--border); border-radius: 16px; margin-bottom: 8px; background: var(--card); box-shadow: var(--shadow-xs); }
details.log:hover { border-color: var(--border2); }
details.log[open] { border-color: var(--brand-border); }
details.log summary { padding: 12px 16px; cursor: pointer; font-size: 13px; font-weight: 600; display: flex; gap: 10px; align-items: center; list-style: none; }
details.log summary::-webkit-details-marker { display: none; }
details.log summary::after { content: '▾'; margin-left: 4px; color: var(--faint); transition: transform .2s; }
details.log[open] summary::after { transform: rotate(180deg); }
details.log pre { margin: 0; border: 0; border-radius: 0 0 16px 16px; }

.copy-box { display: flex; gap: 8px; align-items: center; }
.copy-box code { flex: 1; padding: 9px 13px; overflow: auto; white-space: nowrap; font-size: 12.5px; }

.empty-state { text-align: center; padding: 48px 20px; color: var(--muted); font-weight: 500; }
.empty-state .big { font-size: 40px; opacity: .7; margin-bottom: 10px; }
.empty-state b { color: var(--text); font-size: 15px; font-weight: 500; }

/* ---------- polimento UX ---------- */
.skel {
  height: 13px; border-radius: 99px; margin: 11px 0;
  background: linear-gradient(90deg, #e8f3ec 25%, #f5faf5 50%, #e8f3ec 75%);
  background-size: 200% 100%; animation: shimmer 1.2s infinite;
}
@keyframes shimmer { to { background-position: -200% 0; } }

.avatar.sm { width: 30px; height: 30px; font-size: 11px; }
.cell-user { display: flex; align-items: center; gap: 10px; }

.tabs { display: flex; gap: 6px; margin-bottom: 20px; overflow-x: auto; background: var(--bg2); border-radius: 13px; padding: 5px; width: max-content; max-width: 100%; }
.tabs button {
  padding: 9px 20px; border: none; background: transparent; font: inherit; font-weight: 500; font-size: 13px;
  color: #5a6b57; border-radius: 9px; cursor: pointer; white-space: nowrap;
  transition: all .25s;
}
.tabs button:hover { color: var(--text); }
.tabs button.active { background: var(--card); color: var(--text); box-shadow: 0 2px 10px rgba(0, 0, 0, .09); }
.tabpane { display: none; }
.tabpane.show { display: block; animation: fadeUp .25s var(--ease) both; }

.tb-search { position: relative; display: none; align-items: center; width: 320px; }
@media (min-width: 840px) { .tb-search { display: flex; } }
.tb-search > .ic { position: absolute; left: 14px; color: var(--faint); pointer-events: none; }
.tb-search input {
  padding: 8px 14px 8px 36px; font-size: 13px; background: var(--bg);
  border-color: transparent; border-radius: 10px;
}
.tb-search input:hover { border-color: var(--border2); }
.tb-search input:focus { background: var(--card); border-color: var(--verde-esc); box-shadow: var(--ring); }
.tb-results {
  position: absolute; top: 46px; left: 0; right: 0; background: var(--card); border: 1px solid var(--border2);
  border-radius: 18px; box-shadow: var(--shadow-lg); z-index: 60; max-height: 320px; overflow-y: auto; padding: 6px;
}
.tb-res { display: flex; gap: 10px; padding: 8px 11px; cursor: pointer; align-items: center; border-radius: 12px; }
.tb-res:hover { background: var(--brand-bg); }

/* ---------- conexão WhatsApp (Embedded Signup) ---------- */
.wa-connect-hero { text-align: center; padding: 50px 24px; }
.wa-connect-hero .wa-hero-ic {
  width: 72px; height: 72px; border-radius: 22px; margin: 0 auto 16px;
  background: #25D366; color: #fff;   /* verde oficial do WhatsApp */
  display: flex; align-items: center; justify-content: center;
  box-shadow: 0 16px 38px rgba(37, 211, 102, .38);
}
.wa-connect-hero h2 { font-size: 20px; letter-spacing: -.03em; }
.wa-status { display: grid; grid-template-columns: 1fr 1fr; gap: 4px 32px; }
@media (max-width: 720px) { .wa-status { grid-template-columns: 1fr; } }
.wa-row {
  display: flex; justify-content: space-between; align-items: center; gap: 12px;
  padding: 10px 0; border-bottom: 1px solid #eef6ef; font-size: 13px;
}
.wa-row span { color: var(--muted); font-weight: 600; }
.wa-row b { text-align: right; word-break: break-all; font-weight: 500; }

/* UM CARREGANDO, NO LUGAR DOS OITO PASSOS.
   A lista de passos servia para diagnosticar e fazia o tempo parecer maior:
   sete linhas paradas, com nomes que não significam nada para quem conecta
   ("Assinar app na WABA"), viram sete perguntas. O detalhe mudou de lugar —
   vai inteiro para o log do Admin, que é onde o suporte procura. */
.es-load { display: flex; align-items: center; gap: 14px; margin-top: 12px; min-height: 44px; }
.es-spin {
  width: 26px; height: 26px; flex-shrink: 0; border-radius: 50%;
  border: 3px solid var(--border2); border-top-color: var(--verde-esc);
  animation: esGira .8s linear infinite;
}
/* Parou de girar porque falhou — o círculo vira um aviso, e não some. Sumir
   deixaria a frase de erro solta, sem nada dizendo de onde ela veio. */
.es-spin.falhou { animation: none; border-color: var(--red); border-top-color: var(--red); opacity: .5; }
.es-spin.pronto { animation: none; border-color: var(--verde-esc); }
@keyframes esGira { to { transform: rotate(360deg); } }
/* Quem prefere menos movimento não precisa de um círculo girando sem parar
   para saber que algo está acontecendo: o texto ao lado já diz. */
@media (prefers-reduced-motion: reduce) {
  .es-spin { animation: none; border-top-color: var(--verde-esc); }
}
#es-msg.err { color: var(--red); font-weight: 500; }

details.adv summary { cursor: pointer; list-style: none; display: flex; align-items: center; }
details.adv summary::-webkit-details-marker { display: none; }
details.adv summary h2 { margin: 0; }
details.adv summary::after { content: '+'; margin-left: auto; font-size: 20px; color: var(--faint); }
details.adv[open] summary::after { content: '–'; }

/* ---------- botão de ícone genérico ---------- */
.icon-btn {
  background: none; border: none; color: var(--faint); cursor: pointer;
  padding: 5px; border-radius: 8px; display: inline-flex; align-items: center; justify-content: center;
  transition: background .12s, color .12s;
}
.icon-btn:hover { background: var(--bg2); color: var(--text); }
.icon-btn.danger:hover { background: var(--red-bg); color: var(--red); }
.icon-btn:disabled { opacity: .35; cursor: default; }

/* ---------- métricas (hero) ---------- */
.metric-hero { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 14px; margin-bottom: 16px; }
.mh-card {
  background: var(--card); border: 1px solid var(--border); border-radius: var(--radius);
  padding: 18px; box-shadow: var(--shadow-xs); position: relative; overflow: hidden;
  transition: box-shadow .2s, transform .2s, border-color .2s;
}
.mh-card:hover { box-shadow: var(--shadow); transform: translateY(-3px); border-color: var(--border2); }
.mh-card.hi { background: linear-gradient(150deg, var(--brand-bg), var(--card)); border-color: var(--brand-border); }
.mh-ic {
  width: 40px; height: 40px; border-radius: 12px; display: inline-flex; align-items: center; justify-content: center;
  background: var(--brand-bg); color: var(--verde-esc); margin-bottom: 12px;
}
.mh-val { font-size: 26px; font-weight: 500; letter-spacing: -.03em; color: var(--text); line-height: 1.1; }
.mh-lbl { font-size: 12px; color: var(--muted); font-weight: 600; margin-top: 3px; }

/* ---------- chat interno ---------- */
.team-me, .team-member {
  display: flex; align-items: center; gap: 10px; padding: 9px 11px; border-radius: 14px; margin-bottom: 2px;
}
.team-me { background: var(--brand-bg); border: 1px solid var(--brand-border); margin-bottom: 8px; }
.team-member:hover { background: var(--bg); }
.team-grp { font-size: 10.5px; font-weight: 500; text-transform: uppercase; letter-spacing: .1em; color: var(--faint); padding: 14px 12px 6px; }
.team-item { position: relative; }
.team-item .icon-btn.tiny { position: absolute; right: 8px; top: 50%; transform: translateY(-50%); opacity: 0; padding: 4px; }
.team-item:hover .icon-btn.tiny { opacity: 1; }
.team-chan-ic {
  width: 38px; height: 38px; border-radius: 11px; flex-shrink: 0; display: flex; align-items: center; justify-content: center;
  background: var(--brand-bg); color: var(--verde-deep);
}
.tmsg { display: flex; flex-direction: column; max-width: 74%; margin-bottom: 10px; }
.tmsg.mine { align-self: flex-end; align-items: flex-end; }
.tmsg-from { font-size: 11px; font-weight: 500; color: var(--verde-esc); margin: 0 0 3px 12px; }
.tmsg-bub {
  background: var(--card); border: 1px solid var(--border); border-radius: 14px 14px 14px 5px; padding: 9px 13px;
  font-size: 13.5px; font-weight: 500; color: var(--text); box-shadow: 0 2px 6px rgba(0,0,0,.05); position: relative;
}
.tmsg.mine .tmsg-bub { background: #d1fae5; border-color: #bfeed4; border-radius: 14px 14px 5px 14px; }
.tmsg-bub time { display: block; font-size: 10px; color: var(--muted); margin-top: 4px; text-align: right; font-weight: 600; }

/* ---------- flow builder: lista ---------- */
.flow-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 16px; }
.flow-card {
  background: var(--card); border: 1px solid var(--border); border-radius: var(--radius);
  padding: 18px; box-shadow: var(--shadow-xs); transition: box-shadow .2s, transform .2s, border-color .2s;
}
.flow-card:hover { box-shadow: var(--shadow); transform: translateY(-3px); border-color: var(--border2); }
.flow-card.off { opacity: .62; }
.flow-card-top { display: flex; align-items: center; justify-content: space-between; margin-bottom: 12px; }
.flow-badge {
  display: inline-flex; align-items: center; gap: 6px; font-size: 11px; font-weight: 500;
  color: var(--verde-esc); background: var(--brand-bg); border: 1px solid var(--brand-border);
  padding: 4px 10px; border-radius: 99px;
}
.flow-name { font-size: 15.5px; font-weight: 500; color: var(--text); }
.flow-meta { font-size: 12px; color: var(--muted); font-weight: 600; margin-top: 10px; display: flex; align-items: center; gap: 6px; }
/* A LIXEIRA SAÍA DO CARD. Os quatro botões somavam mais que a largura
   disponível e nenhum encolhia: `flex: 1` cresce, mas sem `min-width: 0` o item
   nunca fica menor que o próprio conteúdo, e a sobra vazava pela direita — a
   lixeira, sendo a última, ficava do lado de fora da borda arredondada.
   Agora eles encolhem até o rótulo cortar, e se ainda não couber a linha quebra
   em vez de estourar. */
.flow-actions { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 14px; }
.flow-actions .btn { flex: 1 1 auto; min-width: 0; overflow: hidden; }
.flow-actions .btn.danger { flex: 0 0 auto; }

/* toggle switch */
/* O INTERRUPTOR TEM TAMANHO FIXO, e precisa dizer isso por escrito.
   `.row > * { flex: 1; min-width: 140px }` alcança TODO filho direto de uma
   linha, e só `.btn` e `.no-grow` estavam de fora. Um `flex-shrink: 0` sozinho
   não segura: ele impede encolher, e o que estica é o `flex-grow`. Dentro de
   uma `.row` o interruptor virava uma barra verde de ponta a ponta, com a
   bolinha parada na esquerda — parecia um medidor, não uma chave.
   `flex: none` cobre grow e shrink de uma vez, e o `min-width: 0` desfaz os
   140px herdados. */
.toggle {
  width: 40px; height: 22px; border-radius: 99px; border: none; background: #cdd8ce; cursor: pointer;
  position: relative; padding: 0; transition: background .2s;
  flex: none; min-width: 0;
}
.toggle span { position: absolute; top: 2px; left: 2px; width: 18px; height: 18px; border-radius: 50%; background: var(--card); box-shadow: 0 1px 3px rgba(0,0,0,.25); transition: transform .2s; }
.toggle.on { background: var(--btn-verde); }
.toggle.on span { transform: translateX(18px); }
/* Rótulo de botão que vira só-ícone no celular. É um <i> por ser inline e
   curto no HTML; o itálico não é intencional. */
.blbl { font-style: normal; }

/* ---------- flow builder: canvas arrasta-e-solta (v2) ---------- */
.fb2 { display: flex; flex-direction: column; height: calc(100vh - var(--topbar-h)); height: calc(100dvh - var(--topbar-h)); }
.fb2-top {
  display: flex; align-items: center; gap: 12px; padding: 11px 20px; flex-shrink: 0;
  background: var(--glass); backdrop-filter: blur(8px); border-bottom: 1px solid var(--border2);
}
.fb-tb-spacer { flex: 1; }
.fb2-name {
  font-size: 16px; font-weight: 500; letter-spacing: -.02em; border: 1px solid transparent; border-radius: 10px;
  padding: 7px 12px; background: transparent; box-shadow: none; max-width: 260px; width: auto;
}
.fb2-name:hover { background: var(--bg); }
.fb2-name:focus { background: var(--card); border-color: var(--verde-esc); box-shadow: var(--ring); }
.fb2-pill { font-size: 12px; font-weight: 500; padding: 4px 12px; border-radius: 99px; background: var(--bg2); color: var(--muted); }
.fb2-pill.on { background: var(--brand-bg); color: var(--verde-deep); }
.fb2-save { font-size: 12px; font-weight: 600; color: var(--faint); }

.fb2-body { flex: 1; display: flex; min-height: 0; position: relative; }
/* Paleta no padrão do app: rótulos como a sidebar, itens como linhas de lista */
.fb2-palette {
  width: 224px; flex-shrink: 0; border-right: 1px solid var(--border2); background: var(--card);
  padding: 12px 10px 18px; overflow-y: auto;
}
.fb2-pgroup {
  font-size: 10px; font-weight: 500; text-transform: uppercase; letter-spacing: 1.4px;
  color: var(--faint); padding: 16px 8px 7px;
}
.fb2-pgroup:first-child { padding-top: 4px; }
.fb2-pitem {
  display: flex; align-items: center; gap: 10px; padding: 7px 8px; border-radius: 10px; cursor: grab;
  font-size: 13px; font-weight: 650; color: var(--text2); user-select: none;
  border: 1px solid transparent;
  transition: background .14s, border-color .14s, color .14s;
}
.fb2-pitem:hover { background: var(--brand-bg); border-color: var(--brand-border); color: var(--verde-deep); }
.fb2-pitem:active { cursor: grabbing; }
.fb2-pitem .fb-n-ic { width: 28px; height: 28px; border-radius: 8px; }

.fb2-canvas {
  flex: 1; position: relative; overflow: hidden; cursor: grab; touch-action: none;
  background:
    radial-gradient(circle, rgba(15,31,21,.06) 1.1px, transparent 1.1px) 0 0 / 22px 22px,
    linear-gradient(180deg, #fbfdf9, #f1f6f1);
}
.fb2-canvas:active { cursor: grabbing; }
.fb-world { position: absolute; top: 0; left: 0; transform-origin: 0 0; will-change: transform; }
.fb-edges { position: absolute; top: 0; left: 0; overflow: visible; pointer-events: none; }
.fb-edge { fill: none; stroke: var(--verde-esc); stroke-width: 2.4; }
.fb-edge.no { stroke: #d0d5dd; }
.fb-edge-hit { fill: none; stroke: transparent; stroke-width: 16; pointer-events: stroke; cursor: pointer; }
.fb-edge-hit:hover + .fb-edge { stroke: var(--red); stroke-dasharray: 5 4; }
/* O VERDE AQUI É O DA MARCA, e não o `--verde` cru. `--verde` (#50ea5f) é um
   lima usado em realce e degradê; o verde do produto é `--brand` (#2ed378), o
   mesmo da `.fb-edge` já traçada. Com os dois no mesmo canvas, a linha que
   você está arrastando tinha uma cor e a que acabou de soltar tinha outra. */
.fb-edge-temp { fill: none; stroke: var(--brand); stroke-width: 2.4; stroke-dasharray: 5 5; }

.fb-n {
  position: absolute; background: var(--card); border: 1px solid var(--border2); border-radius: 16px;
  box-shadow: var(--shadow-sm); padding: 13px 15px; cursor: grab; user-select: none;
  transition: box-shadow .15s, border-color .15s;
}
.fb-n:hover { box-shadow: var(--shadow); }
.fb-n:hover .fb-n-gear { opacity: 1; }
.fb-n.sel { border-color: var(--verde-esc); box-shadow: 0 0 0 2px var(--verde-esc), var(--shadow); }
.fb-n.trig { background: linear-gradient(160deg, var(--amber-bg), var(--card)); border-color: var(--amber-border); }
.fb-n.type-condition { min-height: 92px; }
.fb-n-hd { display: flex; align-items: center; gap: 10px; }
.fb-n-tt { flex: 1; min-width: 0; line-height: 1.15; }
.fb-n-tt b { font-size: 13.5px; font-weight: 500; display: block; }
.fb-n-tt span { font-size: 10.5px; font-weight: 500; color: var(--faint); text-transform: uppercase; letter-spacing: .05em; }
.fb-n-gear { color: var(--faint); opacity: 0; transition: opacity .15s; flex-shrink: 0; }
.fb-n-ic {
  width: 32px; height: 32px; border-radius: 9px; display: inline-flex; align-items: center; justify-content: center;
  flex-shrink: 0;
}
.fb-n-prev { font-size: 11.5px; color: var(--muted); font-weight: 500; margin-top: 8px; line-height: 1.4; max-height: 32px; overflow: hidden; }

/* ---------- A BOLHA DO WHATSAPP DENTRO DO NÓ ----------
   O mesmo desenho da prévia do Template, em escala de card. As cores são as do
   WhatsApp e NÃO seguem o tema do painel: um balão verde-claro no modo escuro
   continua sendo o que o cliente vai ver, e é essa a pergunta que o card
   responde. Por isso os valores aqui são fixos, e não var(--algo). */
.fb-wa { margin-top: 9px; }
/* COM SAÍDA POR OPÇÃO, os rótulos das portas ficam na borda direita do card.
   Sem este recuo o balão passa por baixo deles e as duas coisas viram uma
   mancha só — justamente no nó mais cheio, que é onde ler importa mais. */
/* O balão não recua mais 72px: aquele espaço existia para os rótulos das
   saídas, que sumiram quando a bolinha passou a sair do próprio botão. */
.fb-wa-bolha {
  background: #d9fdd3; border-radius: 8px 8px 8px 2px; padding: 7px 8px 6px;
  font-size: 11.5px; line-height: 1.42; color: #0b141a;
  box-shadow: 0 1px 1px rgba(11, 20, 26, .13);
}
.fb-wa-tx { white-space: pre-wrap; word-break: break-word; max-height: 46px; overflow: hidden; }
.fb-wa-vazio { color: #7d8a91; font-style: italic; }
.fb-wa-ft { color: #667781; font-size: 10px; margin-top: 4px; }
/* o mesmo realce de variável da prévia grande */
.fb-wa .wa-var { background: #c3f0cf; color: #056b3e; border-radius: 3px; padding: 0 2px; font-weight: 600; }

/* BOTÕES: hairline e azul iOS, como no aparelho de verdade. O balão é o
   contexto — o botão precisa parecer o botão do WhatsApp, não o do painel. */
.fb-wa-btns { margin: 6px -8px -6px; border-top: .5px solid rgba(11, 20, 26, .14); }
.fb-wa-btn {
  display: flex; align-items: center; justify-content: center; gap: 5px;
  padding: 6px 6px; color: #027eb5; font-weight: 500; font-size: 11px;
  white-space: nowrap; overflow: hidden;
}
.fb-wa-btn + .fb-wa-btn { border-top: .5px solid rgba(11, 20, 26, .14); }
.fb-wa-btn svg { width: 12px; height: 12px; flex: none; }
.fb-wa-btn span { overflow: hidden; text-overflow: ellipsis; }

/* ---- O BOTÃO É O PONTO DE PARTIDA DO CAMINHO ----
   A bolinha agora nasce dele, e não de uma coluna ao lado. O respiro à direita
   é o lugar dela: sem isso ela cairia sobre o texto do próprio botão. */
.fb-wa-btn[data-branch] { padding-right: 16px; cursor: crosshair; }
.fb-wa-btn[data-branch]:hover { background: rgba(2, 126, 181, .07); }
/* O card inteiro é arrastável; o botão precisa ganhar o gesto de volta para
   dar para puxar o fio a partir dele. */
.fb-wa-btn[data-branch] { position: relative; }

/* O BOTÃO DE LINK NÃO TEM SAÍDA, e o desenho diz isso: ele abre o navegador e
   a conversa acaba ali. Sem a marca, a pessoa procuraria a bolinha dele. */
.fb-wa-btn.sem-saida { color: #667781; }
.fb-wa-btn.sem-saida::after {
  content: 'sem retorno'; margin-left: 4px; font-size: 8.5px; font-weight: 500;
  color: #8f9da8; letter-spacing: .02em;
}

/* MÍDIA: a moldura que o WhatsApp põe antes da legenda. */
.fb-wa-mid {
  height: 54px; margin: -2px -3px 6px; border-radius: 6px;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px;
  background: linear-gradient(160deg, #e9edf0, #d6dde1); color: #8895a0;
  font-size: 9.5px; font-weight: 600; letter-spacing: .01em;
}
.fb-wa-mid.esc { background: linear-gradient(160deg, #3b444c, #232a30); color: #cfd8dd; }

/* TEMPLATE: o nome do modelo é o que decide se a mensagem sai, então ele
   aparece como etiqueta, e não perdido no meio do texto. */
.fb-wa-tpl {
  display: inline-flex; align-items: center; gap: 4px; margin-bottom: 5px;
  background: rgba(11, 20, 26, .07); border-radius: 4px; padding: 2px 6px;
  font-size: 9.5px; font-weight: 600; color: #3b4a54; max-width: 100%;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.fb-wa-tpl svg { flex: none; }

/* PIX: o cartão de pagamento que chega na conversa. */
.fb-wa-pix {
  display: flex; align-items: center; gap: 7px; margin-top: 6px;
  background: rgba(11, 20, 26, .05); border-radius: 6px; padding: 6px 7px;
}
.fb-wa-pix-ic { color: #0b8f5a; display: flex; flex: none; }
.fb-wa-pix-tx { min-width: 0; line-height: 1.25; }
.fb-wa-pix-tx b { display: block; font-size: 10.5px; font-weight: 600; color: #0b141a; }
.fb-wa-pix-tx em { font-style: normal; font-size: 9.5px; color: #667781; }

/* IA: o texto do balão é o PROMPT, não a resposta. Sem dizer isso, quem monta
   o fluxo acha que o cliente vai receber as instruções do agente. */
.fb-wa-ia {
  margin-top: 6px; font-size: 9.5px; color: #667781; font-style: italic;
  display: flex; align-items: center; gap: 4px;
}
.fb-wa-ia svg { flex: none; }
.fb-port {
  position: absolute; width: 13px; height: 13px; border-radius: 50%; background: var(--card);
  border: 2.5px solid var(--verde-esc); z-index: 2; cursor: crosshair; transition: transform .12s;
}
.fb-port:hover { transform: scale(1.35); }
.fb-port.in { left: -7px; top: 33px; }
.fb-port.out { right: -7px; top: 33px; background: var(--verde-esc); }
.fb-port.out.yes { top: 29px; border-color: var(--verde-esc); background: var(--verde-esc); }
.fb-port.out.no { top: 59px; border-color: #98a2b3; background: #98a2b3; }
.fb-port em { position: absolute; right: 16px; top: -5px; font-size: 9.5px; font-weight: 500; font-style: normal; color: var(--muted); background: var(--card); padding: 0 3px; border-radius: 4px; }

/* Saída de cada botão/item: um caminho por opção. O `top` de cada uma vem
   inline do renderNodes(), calculado pela posição da opção na lista. */
.fb-port.out.opt { border-color: var(--brand); background: var(--brand); }
.fb-port.out.opt em {
  right: 17px; top: -4px; max-width: 96px; overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; color: var(--verde-deep); font-size: 9px;
  border: 1px solid color-mix(in srgb, var(--brand) 35%, transparent);
}

.fb2-zoom {
  position: absolute; left: 16px; bottom: 16px; display: flex; flex-direction: column; align-items: center; gap: 2px;
  background: var(--card); border: 1px solid var(--border2); border-radius: 12px; padding: 5px; box-shadow: var(--shadow-sm);
}
.fb2-zoom span { font-size: 10px; font-weight: 500; color: var(--muted); padding: 2px 0; }
.fb2-mini {
  position: absolute; right: 16px; bottom: 16px; width: 184px; height: 120px;
  background: var(--glass); border: 1px solid var(--border2); border-radius: 12px; box-shadow: var(--shadow-sm);
  overflow: hidden;
}
.fb2-mini i { position: absolute; border-radius: 2px; opacity: .55; }

/* Abas da página Integrações (Webhooks / Nuvemshop) */
.int-tabs { margin-bottom: 16px; }
.int-tabs button { display: inline-flex; align-items: center; gap: 6px; }

/* Cards da integração Nuvemshop — layout próprio (não usa .row, que estica
   todos os filhos e deformava o ícone e as pills). Largura total, como as
   demais abas do app. */
.ns-hd { display: flex; align-items: center; gap: 12px; margin-bottom: 18px; }
.ns-ic {
  flex: 0 0 auto; width: 40px; height: 40px; border-radius: 11px;
  background: var(--brand-bg); color: var(--verde-deep);
  display: flex; align-items: center; justify-content: center;
}
.ns-hd-txt { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.ns-hd-txt b { font-size: 14.5px; }
.ns-hd-txt span { font-size: 12.5px; color: var(--muted); line-height: 1.45; }
.ns-hd > .pill { flex: 0 0 auto; align-self: flex-start; }

.ns-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 14px; }
.ns-field { margin-top: 16px; }
.ns-field label { margin: 0; }
.ns-lbl { display: block; font-size: 11.5px; font-weight: 500; color: var(--muted); margin-bottom: 6px; }
.ns-actions { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; margin-top: 18px; }
.ns-nota { font-size: 12px; color: var(--muted); }
.ns-var {
  font-size: 11.5px; background: var(--bg); border: 1px solid var(--border);
  border-radius: 7px; padding: 3px 8px; color: var(--text2);
}

/* Passo a passo de como conectar a loja */
.ns-steps { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 14px; }
.ns-step {
  display: flex; align-items: flex-start; gap: 11px;
  background: var(--bg); border: 1px solid var(--border); border-radius: 12px; padding: 14px;
}
.ns-step-n {
  flex: 0 0 auto; width: 24px; height: 24px; border-radius: 50%;
  background: var(--brand-bg); color: var(--verde-deep);
  display: flex; align-items: center; justify-content: center;
  font-size: 12px; font-weight: 500;
}
.ns-step > div { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.ns-step b { font-size: 13px; font-weight: 500; color: var(--text); }
.ns-step span { font-size: 12px; color: var(--muted); line-height: 1.45; }

/* Dica do canvas vazio (automação nova, antes do gatilho) */
.fb2-hint {
  position: absolute; inset: 0; z-index: 2; pointer-events: none;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 8px;
  text-align: center; padding: 24px; color: var(--muted);
}
.fb2-hint .ic { color: var(--brand); opacity: .5; }
.fb2-hint b { font-size: 15px; color: var(--text); }
.fb2-hint span { font-size: 13px; max-width: 320px; line-height: 1.5; }

.fb2-inspector {
  position: absolute; top: 0; right: 0; bottom: 0; width: 320px; z-index: 5;
  border-left: 1px solid var(--border2); background: var(--card); padding: 20px; overflow-y: auto;
  display: flex; flex-direction: column; gap: 12px;
  transform: translateX(100%); transition: transform .22s var(--ease); box-shadow: -8px 0 30px -12px rgba(20,60,20,.2);
}
.fb2-inspector.open { transform: none; }
.fb-insp-hd { display: flex; align-items: center; gap: 9px; }
.fb-insp-hd b { font-size: 14.5px; font-weight: 500; }
.fb-insp-desc { font-size: 12px; color: var(--muted); margin: -4px 0 4px; }

.fb-linkbox { display: flex; gap: 8px; align-items: center; background: var(--bg); border: 1px solid var(--border); border-radius: 12px; padding: 8px 10px; }
.fb-linkbox code { flex: 1; overflow: auto; white-space: nowrap; font-size: 11.5px; background: none; border: none; padding: 0; }
.fb-btnmode { display: flex; gap: 2px; background: var(--bg2); border-radius: 10px; padding: 3px; }
.fb-btnmode button { flex: 1; border: none; background: transparent; padding: 7px; border-radius: 8px; font: inherit; font-weight: 500; font-size: 12px; color: var(--muted); cursor: pointer; transition: all .18s; }
.fb-btnmode button.on { background: var(--card); color: var(--text); box-shadow: var(--shadow-xs); }
.fb-btns, .fb-headers { display: flex; flex-direction: column; gap: 7px; }
.fb-btn-row { display: flex; gap: 7px; align-items: center; }
.fb-btn-row input { flex: 1; }
.fb-sub { font-size: 11px; font-weight: 500; text-transform: uppercase; letter-spacing: .06em; color: var(--faint); }
.node-menu { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.node-opt {
  display: flex; flex-direction: column; align-items: flex-start; gap: 8px; padding: 16px; cursor: pointer;
  background: var(--card); border: 1px solid var(--border2); border-radius: 14px; font: inherit; text-align: left;
  transition: all .15s;
}
.node-opt:hover { border-color: var(--verde-esc); background: var(--brand-bg); transform: translateY(-2px); }
.node-opt b { font-size: 13.5px; }
@media (max-width: 720px) { .fb2-palette { display: none; } .fb2-inspector { width: 100%; } }

/* ---------------------------------------------------------------------------
   FORMULÁRIO EM DUAS COLUNAS (cadastro de tester)
   Grade de verdade, e não `flex` por linha: com `flex` cada linha decidia
   sozinha onde quebrar, e as colunas não se alinhavam entre si. A grade é uma
   régua só para o formulário inteiro.
   Numa tela estreita vira uma coluna — dois campos lado a lado em 360px
   deixam o rótulo "Quantas pessoas vão atender" em três linhas.
   --------------------------------------------------------------------------- */
.tst-form { display: grid; grid-template-columns: 1fr 1fr; gap: 12px 14px; }
.tst-form > label { margin: 0; min-width: 0; }
@media (max-width: 760px) { .tst-form { grid-template-columns: 1fr; } }

/* ---------- dropdown customizado (substitui todo <select>) ---------- */
.ecsel { position: relative; }
.ecsel-btn {
  width: 100%; display: flex; align-items: center; justify-content: space-between; gap: 8px;
  background: var(--card); border: 1px solid var(--border2); color: var(--text); border-radius: var(--radius-sm);
  padding: 9.5px 14px; font: inherit; font-weight: 600; cursor: pointer; text-align: left;
  transition: border-color .15s, box-shadow .15s; box-shadow: var(--shadow-xs);
}
.ecsel-btn span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ecsel-btn:hover { border-color: #b9d8c4; }
.ecsel.open .ecsel-btn { border-color: var(--verde-esc); box-shadow: var(--ring); }
/* mesmo caso do placeholder dos inputs: a 2,08:1 o rótulo do seletor não era
   lido. Continua mais fraco que o valor escolhido, e agora legível. */
.ecsel-btn.ph span { color: #6b7a69; font-weight: 500; }
:root[data-theme="dark"] .ecsel-btn.ph span,
:root[data-theme="dark"] input::placeholder,
:root[data-theme="dark"] textarea::placeholder { color: #8b9a97; }
.ecsel-chev { color: var(--muted); transition: transform .18s; flex-shrink: 0; }
.ecsel.open .ecsel-chev { transform: rotate(180deg); }
.ecsel-menu {
  position: absolute; top: calc(100% + 5px); left: 0; right: 0; z-index: 70; min-width: 100%;
  background: var(--card); border: 1px solid var(--border2); border-radius: 13px; padding: 5px;
  box-shadow: var(--shadow-lg); display: none; max-height: 280px; overflow-y: auto;
  animation: ecselIn .14s var(--ease);
}
@keyframes ecselIn { from { opacity: 0; transform: translateY(-4px); } }
.ecsel.open .ecsel-menu { display: block; }
.ecsel.up .ecsel-menu { top: auto; bottom: calc(100% + 5px); animation: ecselUp .14s var(--ease); }
@keyframes ecselUp { from { opacity: 0; transform: translateY(4px); } }
.ecsel-opt {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  padding: 9px 11px; border-radius: 9px; font-size: 13.5px; font-weight: 600; color: var(--text2); cursor: pointer;
  white-space: nowrap;
}
.ecsel-opt:hover { background: var(--bg); color: var(--text); }
.ecsel-opt.on { color: var(--verde-deep); background: var(--brand-bg); }
.ecsel-chk { color: var(--verde-esc); flex-shrink: 0; }
/* compacto (tabelas, toolbar) */
.ecsel.sm { display: inline-block; min-width: 132px; }
.ecsel.sm .ecsel-btn { padding: 5.5px 11px; font-size: 12.5px; border-radius: 8px; }
.ecsel.sm .ecsel-menu { font-size: 12.5px; }
.ecsel.sm .ecsel-opt { padding: 7px 10px; font-size: 12.5px; }

/* ---------- editor de template/campanha (página) + preview celular ---------- */
/* páginas com preview (Modelos, Campanhas, Pagamentos) usam a TELA INTEIRA,
   como as demais abas — o preview lateral ganha mais espaço */
.editor-page { max-width: none; }
.tpl-editor { display: grid; grid-template-columns: minmax(0, 1fr) 360px; gap: 28px; align-items: start; }
.tpl-form { display: flex; flex-direction: column; gap: 16px; min-width: 0; }
.tpl-form .card { margin: 0; }
.tpl-preview { position: sticky; top: 20px; }
.tpl-preview-lbl { font-size: 11px; font-weight: 500; text-transform: uppercase; letter-spacing: .08em; color: var(--faint); text-align: center; margin-bottom: 10px; }
.tpl-btns-head { display: flex; align-items: center; justify-content: space-between; margin-top: 4px; }
.tpl-btn-row { display: flex; flex-direction: column; gap: 6px; padding: 8px; border: 1px solid var(--border); border-radius: 12px; margin-bottom: 7px; background: var(--bg); }
.tpl-btn-line { display: flex; gap: 6px; align-items: center; }
.tpl-btn-line select { flex: 0 0 130px; }
.tpl-btn-line .ecsel { flex: 0 0 140px; }
.tpl-btn-line .ecsel.sm { min-width: 0; }
.tpl-btn-line input { flex: 1; }

/* ===== celular realista (iPhone + WhatsApp) ===== */
/* O APARELHO. É o render da vitrine (o mesmo da seção "No seu bolso"), e não
   um telefone desenhado em CSS: dois telefones diferentes no mesmo produto
   fazem a tela parecer montada por duas pessoas que não se falaram.
   A proporção sai do arquivo — 720x1472 —, e a área de tela dele começa a
   6,2% de cada lado e 3% em cima e embaixo. */
.ph-device {
  --ph-w: 300px;
  width: var(--ph-w); aspect-ratio: 720 / 1472; margin: 0 auto; position: relative;
  font-family: -apple-system, 'SF Pro Display', 'Segoe UI', system-ui, sans-serif;
  filter: drop-shadow(0 30px 60px rgba(15, 31, 21, .35));
}
.ph-mock { position: absolute; inset: 0; width: 100%; height: 100%; z-index: 1; pointer-events: none; }
/* A TELA vai POR CIMA do render, dentro da área de vidro dele — do mesmo jeito
   que a vitrine faz com as notificações. Por baixo, o que apareceria seria a
   tela de bloqueio que já vem desenhada no arquivo. A moldura, a ilha e o
   brilho da borda continuam sendo do render. */
.ph-screen {
  position: absolute; left: 6.2%; right: 6.2%; top: 3%; bottom: 3%;
  border-radius: calc(var(--ph-w) * .115); overflow: hidden;
  background: #d9dbd3; display: flex; flex-direction: column; z-index: 2;
}
/* WhatsApp iOS (base: WhatsApp UI Kit iOS do Figma) — barras claras, azul #007AFF */
.ph-status {
  height: 44px; padding: 0 22px 0 28px; display: flex; align-items: flex-end; justify-content: space-between;
  padding-bottom: 5px; background: #f6f6f6; color: #000; flex-shrink: 0;
}
.ph-time { font-size: 14px; font-weight: 500; letter-spacing: .2px; font-variant-numeric: tabular-nums; }
.ph-sys { display: flex; align-items: center; gap: 5px; }
.wa-top {
  background: #f6f6f6; color: #000; padding: 4px 10px 8px; display: flex; align-items: center; gap: 8px;
  flex-shrink: 0; border-bottom: .5px solid rgba(60, 60, 67, .29);
}
.wa-back { flex-shrink: 0; color: #007aff; }
.wa-av {
  width: 36px; height: 36px; border-radius: 50%; flex-shrink: 0; display: flex; align-items: center; justify-content: center;
  background: linear-gradient(150deg, #25d366, #128c7e); color: #fff; font-weight: 500; font-size: 13px;
  overflow: hidden;
}
.wa-av img { width: 100%; height: 100%; object-fit: cover; display: block; }
.wa-top-info { flex: 1; min-width: 0; line-height: 1.15; }
.wa-top-info b { font-size: 15px; font-weight: 600; display: flex; align-items: center; gap: 4px; white-space: nowrap; overflow: hidden; }
.wa-verified { flex-shrink: 0; }
.wa-top-info span { font-size: 11.5px; color: #8e8e93; }
.wa-hicon { flex-shrink: 0; color: #007aff; }
.wa-chat {
  flex: 1; overflow-y: auto; scrollbar-width: none; padding: 14px 10px; display: flex; flex-direction: column; gap: 6px;
  background-color: #efe9e2;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='56' height='56' viewBox='0 0 56 56'%3E%3Cg fill='none' stroke='%23d5cabb' stroke-width='1' stroke-opacity='.6'%3E%3Cpath d='M8 10c2-3 6-3 8 0M40 6l3 4M14 34l4 3M44 30c-3 1-3 5 0 6M26 46l2-4'/%3E%3Ccircle cx='34' cy='20' r='2.5'/%3E%3Ccircle cx='10' cy='46' r='2'/%3E%3C/g%3E%3C/svg%3E");
}
.wa-daychip {
  align-self: center; background: var(--glass); color: #8e8e93; font-size: 10.5px; font-weight: 600;
  padding: 4px 11px; border-radius: 8px; box-shadow: 0 1px 1px rgba(0, 0, 0, .05); margin-bottom: 2px;
  text-transform: uppercase; letter-spacing: .03em;
}
/* cartão da mensagem: bolha + botões presos (estilo template iOS) */
.wa-card {
  align-self: flex-start; max-width: 86%; margin-left: 8px; position: relative; flex-shrink: 0;
  background: var(--card); border-radius: 13px; border-top-left-radius: 4px;
  box-shadow: 0 1px .5px rgba(11, 20, 26, .13); overflow: hidden;
}
.wa-daychip { flex-shrink: 0; }
.wa-card::before {
  content: ''; position: absolute; top: 0; left: -8px; width: 8px; height: 13px;
  background: var(--card); clip-path: polygon(100% 0, 0 0, 100% 100%);
}
.wa-msg { padding: 6px 8px 5px; font-size: 14.5px; line-height: 1.38; color: #0b141a; }
.wa-hd { font-weight: 500; margin: 2px 1px 4px; word-wrap: break-word; font-size: 14.5px; }
.wa-bd { white-space: pre-wrap; word-wrap: break-word; padding: 0 1px; }
.wa-ph { color: #7d8a91; }   /* placeholder do mockup — cinza WhatsApp, legível */
.wa-var { background: #d9f2e4; color: var(--verde-deep); border-radius: 4px; padding: 0 3px; font-weight: 600; }
.wa-ft { color: #8696a0; font-size: 12px; margin-top: 5px; padding: 0 1px; }
.wa-time { float: right; font-size: 10.5px; color: #8696a0; margin: 6px 0 0 8px; }
/* cabeçalho de mídia (imagem/vídeo) — sangra até as bordas do cartão */
.wa-mhd { margin: 3px 3px 6px; border-radius: 10px; overflow: hidden; position: relative; background: #dfe3e6; }
.wa-mhd img, .wa-mhd video { display: block; width: 100%; height: 128px; object-fit: cover; }
.wa-mhd-ph {
  height: 118px; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 6px;
  color: #93a1ab; font-size: 12px; font-weight: 600; background: linear-gradient(160deg, #e9edf0, #d8dee2);
}
.wa-mhd-ph.dark { background: linear-gradient(160deg, #3b444c, #21282e); color: #cfd8dd; }
.wa-play {
  width: 42px; height: 42px; border-radius: 50%; background: rgba(11, 20, 26, .55); color: #fff;
  display: flex; align-items: center; justify-content: center; backdrop-filter: blur(2px);
}
.wa-play svg { margin-left: 3px; }
.wa-play.ov { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); }
/* cabeçalho documento (PDF) */
.wa-doc {
  margin: 3px 3px 6px; border-radius: 10px; background: #f5f6f6; border: .5px solid rgba(60, 60, 67, .12);
  display: flex; align-items: center; gap: 9px; padding: 9px 10px;
}
.wa-doc-ic {
  width: 34px; height: 34px; border-radius: 8px; background: #ee4023; color: #fff; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
}
.wa-doc-tx { min-width: 0; line-height: 1.2; }
.wa-doc-tx b { display: block; font-size: 12.5px; font-weight: 600; color: #0b141a; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.wa-doc-tx span { font-size: 10.5px; color: #8696a0; }
/* botões do template: linhas com hairline, texto azul iOS */
.wa-btns { border-top: .5px solid rgba(60, 60, 67, .18); }
.wa-btn {
  padding: 10.5px 8px; text-align: center; color: #007aff; font-weight: 500; font-size: 14.5px;
  display: flex; align-items: center; justify-content: center; gap: 7px;
}
.wa-btn + .wa-btn { border-top: .5px solid rgba(60, 60, 67, .18); }
/* barra de digitação iOS */
.wa-input {
  flex-shrink: 0; background: #f6f6f6; padding: 6px 10px 8px; display: flex; align-items: center; gap: 10px;
  border-top: .5px solid rgba(60, 60, 67, .29); color: #54656f;
}
.wa-plus { flex-shrink: 0; }
.wa-bar {
  flex: 1; background: var(--card); border: .5px solid rgba(60, 60, 67, .25); border-radius: 18px; min-height: 34px;
  display: flex; align-items: center; gap: 8px; padding: 0 9px; color: #8e8e93;
}
.wa-ph2 { flex: 1; font-size: 14px; color: #b0b6bb; }
.wa-in-ic { flex-shrink: 0; }
.ph-home {
  height: 5px; width: 110px; border-radius: 3px; background: #0b141a; opacity: .9;
  margin: 6px auto 7px; flex-shrink: 0;
}
@media (max-width: 820px) { .tpl-editor { grid-template-columns: 1fr; } .tpl-preview { display: none; } }

/* ---------- tipografia display (mesma da vitrine) ---------- */
h1, h2 { letter-spacing: var(--ls-titulo); }
/* Números continuam sendo o dado mais importante da tela, mas em peso 500:
   o tamanho já os destaca, e o 800 empastelava as casas decimais. */
.stat .num, .kpi .val, .mh-val, .big-num, .bignum, .preco {
  font-weight: 500; letter-spacing: -.02em; font-variant-numeric: tabular-nums;
}
.stat .num { font-size: 32px; }
.kpi .val { font-size: 30px; }
.big-num { font-size: 30px; font-weight: 500; letter-spacing: -.02em; font-variant-numeric: tabular-nums; }
.big-num.sm { font-size: 22px; }
.hero-head h1 { font-size: 28px; letter-spacing: -.015em; font-weight: 500; }
.page-head h1 { letter-spacing: var(--ls-titulo); }

/* segmented control (período / tipo de gráfico) */
.seg { display: inline-flex; background: var(--bg2); border-radius: 11px; padding: 4px; gap: 2px; }
.seg button {
  border: none; background: transparent; padding: 7px 14px; border-radius: 8px;
  font: inherit; font-weight: 500; font-size: 12px; color: #5a6b57; cursor: pointer; transition: all .2s;
}
.seg button:hover { color: var(--text); }
.seg button.on { background: var(--card); color: var(--text); box-shadow: 0 2px 8px rgba(0,0,0,.09); }

/* tiles de ação rápida (referência: Depositar/Transferir/…) */
.dash-tiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(130px, 1fr)); gap: 12px; margin-bottom: 16px; }
.tile {
  display: flex; flex-direction: column; align-items: center; gap: 9px; padding: 18px 10px 14px;
  background: var(--card); border: 1px solid var(--border); border-radius: 16px; text-decoration: none;
  color: var(--text); transition: transform .18s, box-shadow .18s, border-color .18s;
}
.tile:hover { transform: translateY(-3px); box-shadow: var(--shadow); border-color: var(--border2); text-decoration: none; color: var(--text); }
.tile-ic {
  width: 42px; height: 42px; border-radius: 13px; display: flex; align-items: center; justify-content: center;
  background: var(--brand-bg); color: var(--verde-deep);
}
.tile b { font-size: 12.5px; font-weight: 500; }

.dash-kpis { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 14px; margin-bottom: 16px; }

/* donut + legenda com barras (referência: Meios de Pagamento) */
.donut-wrap { display: flex; flex-direction: column; align-items: center; gap: 16px; }
.donut-leg { width: 100%; display: flex; flex-direction: column; gap: 10px; }
.dl-row { display: grid; grid-template-columns: 1fr auto; gap: 3px 10px; align-items: center; font-size: 13px; }
.dl-name { display: flex; align-items: center; gap: 8px; font-weight: 500; color: var(--text2); }
.dl-name i { width: 10px; height: 10px; border-radius: 3px; flex-shrink: 0; }
.dl-row b { font-variant-numeric: tabular-nums; font-weight: 500; }
.dl-track { grid-column: 1 / -1; height: 6px; background: var(--bg2); border-radius: 99px; overflow: hidden; }
.dl-track div { height: 100%; border-radius: 99px; transition: width .5s var(--ease); }

/* ---------- FUNIL DE VENDAS (trapézios empilhados) ----------
   Substitui as barras horizontais: elas davam os números certos mas não
   pareciam um funil. A silhueta é o que faz a pessoa ver de relance onde o
   lead trava. Cada etapa é um trapézio recortado por clip-path, um pouco mais
   estreito que o de cima. */
.funil { display: flex; flex-direction: column; align-items: center; padding: 6px 0 2px; }
/* Os trapézios quase se tocam: é isso que faz o conjunto ler como UM funil
   em vez de seis caixas soltas. */
.fn-etapa { position: relative; cursor: pointer; margin-bottom: 3px; }
.fn-forma {
  position: relative; min-height: 62px; padding: 10px 26px;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 1px;
  color: #fff; text-align: center;
  transition: transform .22s var(--ease), filter .22s var(--ease);
}
.fn-etapa:hover .fn-forma { transform: scale(1.035); filter: brightness(1.06); }
.fn-etapa.aberta .fn-forma { transform: scale(1.035); filter: brightness(1.06); }
.fn-nome {
  font-size: 10.5px; font-weight: 500; letter-spacing: .08em; text-transform: uppercase;
  opacity: .92; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.fn-num {
  font-size: 21px; font-weight: 500; letter-spacing: -.03em; line-height: 1.1;
  font-variant-numeric: tabular-nums; text-shadow: 0 1px 2px rgba(0, 0, 0, .18);
}
.fn-taxa { font-size: 10px; font-weight: 500; opacity: .82; }
/* A queda fica FORA do trapézio: dentro, ela competia com o número e o
   trapézio estreito cortava o texto. */
.fn-queda {
  position: absolute; top: 50%; right: -8px; transform: translate(100%, -50%);
  font-size: 10.5px; font-weight: 500; color: var(--red-ink);
  background: var(--card); border: 1px solid var(--red-border, #f3c9c9); border-radius: 7px;
  padding: 1px 6px; box-shadow: var(--shadow-xs); white-space: nowrap;
}
/* Detalhe da etapa: fechado por padrão, abre no clique. Usa grid 0fr → 1fr
   para animar a altura sem precisar saber o tamanho do conteúdo.
   O conteúdo vai dentro de UM wrapper (.fn-det-in) de propósito: com vários
   filhos diretos, o 0fr zera só a primeira linha e as outras ficam em auto —
   era por isso que o detalhe fechado ainda ocupava ~70px e abria um buraco
   entre os trapézios. */
.fn-detalhe {
  display: grid; grid-template-rows: 0fr; overflow: hidden;
  transition: grid-template-rows .24s var(--ease), margin-top .24s var(--ease);
}
.fn-detalhe > .fn-det-in { min-height: 0; overflow: hidden; }
.fn-etapa.aberta .fn-detalhe { grid-template-rows: 1fr; margin-top: 8px; }
.fn-det-linha {
  display: flex; justify-content: space-between; align-items: baseline; gap: 12px;
  padding: 7px 13px; font-size: 12.5px; color: var(--text2);
  background: var(--bg2); border: 1px solid var(--border); border-radius: 10px; margin-bottom: 5px;
}
.fn-det-linha b { font-weight: 500; color: var(--text); font-variant-numeric: tabular-nums; }
.fn-det-linha b.ok { color: var(--verde-deep); }
.fn-det-nota { font-size: 11.5px; color: var(--muted); text-align: center; line-height: 1.5; }
.fn-det-nota b { color: var(--text2); font-weight: 500; }

@media (max-width: 560px) {
  .fn-forma { min-height: 54px; padding: 8px 16px; }
  .fn-num { font-size: 18px; }
  .fn-nome { font-size: 9.5px; letter-spacing: .05em; }
  /* Em tela estreita não há espaço à direita do trapézio: a queda vira uma
     etiqueta sobreposta ao canto, em vez de sair da tela. */
  .fn-queda { right: 2px; transform: translate(0, -50%); font-size: 9.5px; }
}

/* ---------- sugestões (funil) ---------- */
.sug-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 12px; }
.sug {
  display: flex; gap: 12px; padding: 14px 15px; border-radius: 14px;
  background: var(--bg); border: 1px solid var(--border);
}
.sug.warn { background: #fff8e9; border-color: #f6dfa9; }
.sug.ok { background: var(--brand-bg); border-color: var(--brand-border); }
.sug-ic {
  width: 34px; height: 34px; border-radius: 10px; flex-shrink: 0;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--card); color: var(--verde-deep); border: 1px solid var(--border);
}
.sug.warn .sug-ic { color: #b26205; border-color: #f6dfa9; }
.sug-tx { min-width: 0; }
.sug-tx b { font-size: 13.5px; font-weight: 500; display: block; }
.sug-tx p { font-size: 12.5px; color: var(--text2); font-weight: 500; margin: 3px 0 0; line-height: 1.45; }
.sug-act { display: inline-block; font-size: 12.5px; font-weight: 500; margin-top: 7px; }

/* ---------- pixels / CAPI / UTM / origem ---------- */
.capi-box { background: var(--bg); border: 1px solid var(--border); border-radius: 12px; padding: 12px 13px; margin-top: 4px; }
.capi-head { display: flex; align-items: center; gap: 7px; font-size: 13px; font-weight: 500; color: var(--text2); }
.capi-head svg { color: var(--verde-deep); }
.capi-tag { font-size: 10px; font-weight: 500; text-transform: uppercase; letter-spacing: .05em; background: var(--brand-bg); color: var(--verde-deep); border: 1px solid var(--brand-border); padding: 1px 7px; border-radius: 20px; }
.utm-box { border: 1px solid var(--border); border-radius: 12px; padding: 4px 13px; background: var(--bg); }
.utm-box summary { cursor: pointer; padding: 9px 0; font-size: 13px; font-weight: 500; color: var(--text2); display: flex; align-items: center; gap: 7px; list-style: none; }
.utm-box summary::-webkit-details-marker { display: none; }
.utm-box summary svg { color: var(--verde-deep); }
.utm-box[open] summary { border-bottom: 1px solid var(--border); }
.utm-box > .row:last-child { margin-bottom: 12px; }
.src-badge {
  display: inline-flex; align-items: center; gap: 3px; font-size: 10px; font-weight: 500; margin-left: 6px;
  background: var(--violet-bg); color: #7c3aed; border: 1px solid rgba(124,58,237,.25); padding: 1px 6px; border-radius: 20px; vertical-align: 1px;
}
.src-card { background: linear-gradient(150deg, var(--violet-bg), var(--card)); border: 1px solid rgba(124,58,237,.22); border-radius: 12px; padding: 12px 14px; }
.src-card-h { font-size: 12.5px; font-weight: 500; color: #7c3aed; display: flex; align-items: center; gap: 7px; margin-bottom: 8px; }
.src-line { display: flex; justify-content: space-between; gap: 12px; font-size: 12.5px; padding: 3px 0; }
.src-line span { color: var(--muted); flex-shrink: 0; }
.src-line b, .src-line a { text-align: right; word-break: break-word; font-weight: 500; }

/* ---------- links rastreáveis ---------- */
.linkrow { display: flex; align-items: center; gap: 4px; margin-top: 3px; }
.linkrow code { font-size: 11.5px; }
.lk-kpis { display: grid; grid-template-columns: repeat(auto-fit, minmax(128px, 1fr)); gap: 10px; }
.lk-kpis > div { background: var(--bg); border: 1px solid var(--border); border-radius: 14px; padding: 12px; text-align: center; }
.lk-kpis b { font-size: 20px; font-weight: 500; display: block; }
.lk-kpis span { font-size: 11px; font-weight: 500; color: var(--muted); text-transform: uppercase; letter-spacing: .05em; }
/* formulário de link em página + barra de metadados */
.form-2col { display: grid; grid-template-columns: minmax(0, 1.65fr) minmax(0, 1fr); gap: 16px; align-items: start; }
@media (max-width: 900px) { .form-2col { grid-template-columns: 1fr; } }
.lk-side .lk-tips { margin: 0; padding-left: 18px; display: flex; flex-direction: column; gap: 11px; }
.lk-side .lk-tips li { font-size: 12.5px; color: var(--muted); line-height: 1.55; }
.lk-side .lk-tips b { color: var(--text2); font-weight: 500; }
.lk-meta { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-bottom: 16px; }
.lk-meta-arrow { color: var(--faint); display: inline-flex; }
.utm-chips { display: inline-flex; gap: 6px; flex-wrap: wrap; }
.utm-chip { font-size: 11px; font-weight: 600; color: var(--muted); background: var(--bg); border: 1px solid var(--border); border-radius: 7px; padding: 2px 8px; }
.utm-chip b { color: var(--text2); font-weight: 500; }
.flow-hist { display: flex; flex-direction: column; gap: 6px; max-height: 260px; overflow-y: auto; }

/* ---------- página de pixels ---------- */
.px-editor { border: 1.5px solid var(--brand-border); box-shadow: 0 12px 30px -14px rgba(16, 140, 100, .3); animation: fadeUp .2s var(--ease) both; }
.px-guide .pxg-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: 14px; }
.px-guide .pxg-grid > div { background: var(--bg); border: 1px solid var(--border); border-radius: 13px; padding: 13px 14px; }
.px-guide .pxg-grid b { display: flex; align-items: center; gap: 7px; font-size: 13px; margin-bottom: 6px; }
.px-guide .pxg-grid b svg { color: var(--verde-deep); }
.px-guide .pxg-grid p { margin: 0; font-size: 12px; color: var(--muted); line-height: 1.5; }
/* card-atalho (leva a outra página) */
.link-card { display: flex; align-items: center; gap: 15px; text-decoration: none; color: inherit; cursor: pointer; }
.link-card:hover { border-color: var(--brand-border); box-shadow: var(--shadow-sm); transform: translateY(-1px); }
.link-card .lc-ic { flex: none; width: 46px; height: 46px; border-radius: 13px; background: var(--brand-bg); color: var(--verde-deep); display: grid; place-items: center; }
.link-card .lc-arrow { color: var(--faint); flex: none; }
.link-card:hover .lc-arrow { color: var(--verde-esc); }

/* ---------- assinatura & carteira (SaaS) ---------- */
.warn-card { display: flex; align-items: center; gap: 10px; background: var(--amber-bg, #fff7e6); border-color: var(--amber-border, #f3dfb2); color: #7a5410; font-size: 13.5px; }
.warn-card .ic { color: var(--amber, #e79c0d); flex: none; }
.pill.warn { color: #b26205; border-color: var(--amber-border); background: var(--amber-bg); }
.pill.warn::before { background: var(--amber); }
.bill-status { display: flex; align-items: center; gap: 18px; flex-wrap: wrap; }
.bill-status .bs-main { flex: 1; min-width: 220px; }
.plans-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(215px, 1fr)); gap: 14px; }
.plan {
  display: flex; flex-direction: column; gap: 10px; padding: 20px 18px;
  background: var(--bg); border: 1.5px solid var(--border); border-radius: 16px;
  transition: border-color .2s, box-shadow .2s, transform .2s;
}
.plan:hover { border-color: var(--brand-border); box-shadow: var(--shadow-sm); transform: translateY(-2px); }
/* O `#fff` no fim do gradiente não seguia o tema: no escuro o cartão do plano
   atual ia de verde-escuro a BRANCO, com o texto claro por cima — ilegível.
   `--card` é branco no claro e escuro no escuro, então o degradê funciona nos
   dois sem regra extra. */
.plan.current { border-color: var(--verde-esc); background: linear-gradient(160deg, var(--brand-bg), var(--card)); }
.plan .pl-name { font-size: 14px; font-weight: 500; }
.plan .pl-price { font-size: 26px; font-weight: 500; letter-spacing: -.03em; color: var(--verde-deep); }
.plan .pl-price span { font-size: 12.5px; font-weight: 500; color: var(--muted); letter-spacing: 0; }
.plan .pl-feats { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; flex: 1; }
.plan .pl-feats li { font-size: 12.5px; color: var(--text2); font-weight: 600; display: flex; align-items: center; gap: 7px; }
.plan .pl-feats .ic { color: var(--verde-esc); flex: none; }
.pay-card { border: 1.5px solid var(--brand-border); box-shadow: 0 14px 34px -16px rgba(16, 140, 100, .35); }
/* O cartão do Pix aparece em dois lugares de larguras bem diferentes: a tela
   de Assinatura (larga) e o modal de recarga (500px, ~410px úteis). Lá dentro,
   190px de QR deixavam ~200px para o texto, e tudo quebrava. Com um piso de
   250px na coluna de texto ela desce inteira para baixo do QR quando não cabe,
   em vez de espremer. Não é media query porque quem é estreito é o CONTÊINER,
   não a janela. */
.pay-grid { display: flex; gap: 18px; align-items: flex-start; flex-wrap: wrap; justify-content: center; }
.pay-info { flex: 1 1 250px; min-width: 0; }
.pay-acoes { display: flex; flex-wrap: wrap; gap: 8px; }
.pay-acoes .btn { flex: 1 1 140px; }
/* O copia-e-cola é longo e feio: o caminho normal é o botão de copiar, e o
   código fica guardado para quem precisa colar à mão. */
.pay-codigo { margin-top: 12px; }
.pay-codigo summary { cursor: pointer; font-size: 12.5px; font-weight: 500; color: var(--text2); }
.pay-codigo summary:hover { color: var(--verde-deep); }
.pay-codigo textarea {
  margin-top: 8px; font-size: 11.5px; line-height: 1.45; font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  word-break: break-all; resize: vertical;
}
.pay-qr { flex: none; width: 190px; }
.pay-qr img { width: 190px; height: 190px; border-radius: 14px; border: 1px solid var(--border); background: var(--card); }
.pay-qr-ph { width: 190px; height: 190px; border-radius: 14px; border: 1.5px dashed var(--border2); display: grid; place-items: center; color: var(--faint); }

/* ---- Contratar unidades extras (conexões WhatsApp, links) ---- */
.extra-buy {
  margin-top: 14px; padding: 14px; border-radius: 14px;
  border: 1.5px solid var(--brand-border); background: linear-gradient(150deg, var(--brand-bg), transparent);
}
.extra-buy-head { display: flex; align-items: center; gap: 10px; color: var(--verde-deep); margin-bottom: 12px; }
.extra-buy-head b { display: block; font-size: 14px; color: var(--text); }
.extra-buy-head em { display: block; font-style: normal; font-size: 12px; color: var(--muted); margin-top: 2px; }
.extra-buy-row { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.qty { display: inline-flex; align-items: stretch; border: 1px solid var(--border2); border-radius: 11px; overflow: hidden; background: var(--card); }
.qty-b {
  width: 38px; border: 0; background: transparent; color: var(--verde-deep);
  font-size: 19px; line-height: 1; cursor: pointer; padding: 0;
}
.qty-b:hover { background: var(--brand-bg); }
.qty-i {
  width: 56px; border: 0; border-left: 1px solid var(--border2); border-right: 1px solid var(--border2);
  text-align: center; font-weight: 500; font-size: 15px; background: transparent; color: var(--text);
  padding: 9px 0; margin: 0; border-radius: 0; -moz-appearance: textfield;
}
.qty-i:focus { outline: 0; box-shadow: none; }
.qty-i::-webkit-outer-spin-button, .qty-i::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.extra-total { line-height: 1.15; }
.extra-total b { font-size: 19px; color: var(--verde-deep); }
.extra-total em { display: block; font-style: normal; font-size: 11px; color: var(--muted); }
/* Duas colunas, não quatro. Com minmax(140px) as quatro opções cabiam lado a
   lado num modal estreito, e aí "Cartão de crédito" quebrava em três linhas:
   cada opção ficava com 150px de altura. */
.pay-methods { display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); gap: 8px; }
.pay-method {
  /* `label` global é uma coluna; aqui o ícone fica AO LADO do rótulo, senão
     ele empilha em cima e a opção vira uma torre alta e estranha. */
  display: flex; flex-direction: row; align-items: center; gap: 10px; cursor: pointer; margin: 0;
  border: 1.5px solid var(--border2); border-radius: 12px; padding: 11px 12px; background: var(--card);
}
.pay-method > span:not(.pay-ic) { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.pay-method:hover { border-color: var(--brand-border); }
.pay-method:has(input:checked) { border-color: var(--btn-verde); background: var(--brand-bg); }
.pay-method input { margin: 0; flex: none; accent-color: var(--btn-verde); }
.pay-method b { display: block; font-size: 13.5px; }
/* aviso de conexão cancelada, na lista de conexões */
.ch-cancel-note {
  margin-top: 6px; font-size: 11.5px; line-height: 1.45;
  color: var(--red); background: rgba(220, 38, 38, .07);
  border-left: 2px solid var(--red); border-radius: 0 8px 8px 0; padding: 6px 9px;
}
.ch-cancel-note b { color: inherit; }
.linkish {
  background: none; border: 0; padding: 0; margin-left: 4px;
  color: var(--verde-deep); font: inherit; font-weight: 500; cursor: pointer; text-decoration: underline;
}
/* caixa de consequências antes de uma exclusão definitiva */
.danger-box {
  border: 1.5px solid var(--red); background: rgba(220, 38, 38, .06);
  border-radius: 12px; padding: 13px 15px; font-size: 12.5px; line-height: 1.55;
}
.danger-box > b { display: block; color: var(--red); margin-bottom: 7px; }
.danger-box ul { margin: 0 0 8px; padding-left: 20px; }
.danger-box li { margin-bottom: 3px; }
.danger-box p { margin: 0; color: var(--muted); }
.pay-method em { display: block; font-style: normal; font-size: 11px; color: var(--muted); margin-top: 1px; }
.wallet-bal {
  display: flex; align-items: baseline; justify-content: space-between; gap: 10px;
  background: linear-gradient(150deg, var(--brand-bg), var(--card)); border: 1px solid var(--brand-border);
  border-radius: 14px; padding: 14px 16px;
}
.wallet-bal span { font-size: 12px; font-weight: 500; color: var(--muted); text-transform: uppercase; letter-spacing: .05em; }
.wallet-bal b { font-size: 24px; font-weight: 500; color: var(--verde-deep); letter-spacing: -.02em; }
.tx-list { display: flex; flex-direction: column; max-height: 240px; overflow-y: auto; }
.tx { display: flex; align-items: center; gap: 10px; padding: 8px 2px; border-bottom: 1px solid var(--bg2); font-size: 13px; }
.tx:last-child { border-bottom: none; }
.tx .tx-lbl { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 600; }
.tx .tx-in { color: var(--verde-deep); }
.tx .tx-out { color: var(--red); }
label.chk { display: flex; flex-direction: row; align-items: center; gap: 11px; font-size: 13px; font-weight: 600; color: var(--text2); cursor: pointer; }
/* Todo checkbox .chk vira um TOGGLE (interruptor) — sem tocar no HTML/JS.
   O input nativo é escondido e o ::before/::after desenham a pista + o botão. */
label.chk input[type="checkbox"] {
  appearance: none; -webkit-appearance: none;
  position: relative; flex: none; margin: 0; cursor: pointer;
  width: 40px; height: 23px; border-radius: 99px;
  background: var(--border2); transition: background .2s var(--ease);
}
label.chk input[type="checkbox"]::after {
  content: ""; position: absolute; top: 2px; left: 2px;
  width: 19px; height: 19px; border-radius: 50%;
  background: #fff; box-shadow: 0 1px 3px rgba(0, 0, 0, .3);
  transition: transform .2s var(--ease);
}
label.chk input[type="checkbox"]:checked { background: var(--verde-esc); }
label.chk input[type="checkbox"]:checked::after { transform: translateX(17px); }
label.chk input[type="checkbox"]:focus-visible { outline: none; box-shadow: var(--ring); }
label.chk input[type="checkbox"]:disabled { opacity: .5; cursor: not-allowed; }
:root[data-theme="dark"] label.chk input[type="checkbox"]::after { background: #e9f1ef; }
/* linha de método de pagamento no Checkout Builder (toggle + título + hint) */
.epk-payrow { align-items: flex-start; padding: 11px 0; border-bottom: 1px solid var(--border); }
.epk-payrow:first-of-type { padding-top: 2px; }
.epk-payrow span { display: flex; flex-direction: column; }
.epk-payrow span b { font-size: 13.5px; color: var(--text); }
.epk-payrow span em { font-style: normal; font-size: 11.5px; color: var(--muted); margin-top: 2px; }
.epk-payrow.off span em a { color: var(--verde-esc); font-weight: 500; }

/* ---------- mapa 3D do Brasil ---------- */
.geo-box { display: grid; grid-template-columns: minmax(0, 1.55fr) minmax(0, 1fr); gap: 22px; align-items: start; }
@media (max-width: 860px) { .geo-box { grid-template-columns: 1fr; } }
.geo-map { position: relative; }
/* MAPA DE CALOR. A COR de cada estado vem da rampa em app.js (GEO_RAMPA: azul →
   verde → lima → ouro) e é escrita direto no SVG, porque depende do dado. O que
   mora aqui é o que depende do TEMA: a placa, as divisas, a parede e o estado
   sem lead nenhum.
   A opacidade (22% a 92%) continua vindo junto da cor, e é ela que faz a mesma
   rampa servir aos dois temas — no claro o fraco quase some no branco, no
   escuro quase some na placa. */
:root {
  /* O ESTADO SEM LEAD é NEUTRO, e de propósito não é a ponta fria da rampa: a
     ponta fria significa "poucos", e nenhum não é poucos. Um cinza levíssimo
     diz "não há dado aqui" sem entrar na escala. */
  --geo-vazio-cor: #64748b;
  --geo-hover: var(--verde-deep);   /* #0b815a */
  /* divisas ESCURAS no claro / CLARAS no escuro — a linha separa por contraste
     com o preenchimento, então inverte junto com o tema. */
  --geo-sep: #161b1d;
  --geo-wall: #a7b0b4;              /* lateral da placa 3D: cinza neutro, sem verde */
  --geo-label: var(--text);
  --geo-label-off: var(--muted);    /* --faint caía para 2.2:1 sobre o estado vazio */
  --geo-halo: rgba(255, 255, 255, .9);
  /* A PLACA. No claro ela é chapada, como sempre foi — o branco do card não
     pede degradê. As três paradas existem para o escuro. */
  --geo-placa-1: var(--card);
  --geo-placa-2: var(--card);
  --geo-placa-3: var(--card);
  --geo-vazio: .10;                 /* opacidade do estado sem lead */
}
:root[data-theme="dark"] {
  --geo-hover: var(--verde-deep);   /* vira #6ee7b7 no escuro */
  --geo-halo: rgba(9, 13, 10, .88);
  /* A PLACA NO ESCURO É O MESMO PRETO GRADIENTE DOS CARDS (--card-grad, 160deg).
     Antes era o --card chapado, com 7% de verde por cima em CADA estado. E 7%
     de #50ea5f sobre #141a18 não dá um verde discreto: dá #18291d, verde musgo.
     Como o mapa de uma conta nova está todo vazio, o país inteiro nascia dessa
     cor — e o verde, que devia significar "aqui tem lead", não significava nada.
     Agora o estado vazio não recebe tinta (--geo-vazio: 0) e quem aparece é a
     placa. O verde voltou a ter um sentido só. */
  --geo-placa-1: #151a1b;
  --geo-placa-2: #121516;
  --geo-placa-3: #0e1112;
  --geo-vazio: 0;
  /* A divisa era BRANCO PURO — escolha certa quando o fundo era o musgo, porque
     ali a linha precisava furar um meio-tom. Sobre a placa preta o mesmo branco
     vira uma grade acesa, mais visível que o próprio dado. Mesma luz, com força
     de linha e não de traço: 2,65:1 sobre a placa, o bastante para desenhar as
     divisas sem competir com os estados acesos. */
  --geo-sep: rgba(255, 255, 255, .30);
  /* A parede é o que faz a placa parecer ERGUIDA do card, e não recortada nele:
     com a placa e o card na mesma luminância (1,08:1), o relevo é a única coisa
     que separa os dois. A #4b5458 de antes foi medida contra o musgo e agora
     pesava mais que o mapa; a #2e3639 sumia a 1,54:1. Esta fica em 1,87:1. */
  --geo-wall: #394347;
}

/* O viewBox é ~1185x971 e o mapa renderiza a ~440px de altura => escala ~0.45.
   Fonte e traços são definidos em unidades do viewBox, então precisam ser
   ~2.2x maiores do que o tamanho desejado em tela. */
.geo-map svg { max-height: 440px; display: block; margin: 0 auto; overflow: visible; shape-rendering: geometricPrecision; }
/* Tooltip que segue o cursor: nome do estado + nº de leads. */
.geo-tip {
  position: absolute; left: 0; top: 0; z-index: 6; pointer-events: none;
  transform: translate(-50%, calc(-100% - 12px));
  background: var(--card); border: 1px solid var(--border2); border-radius: 11px;
  padding: 7px 12px; box-shadow: var(--shadow); white-space: nowrap;
  display: flex; flex-direction: column; gap: 1px;
  opacity: 0; transition: opacity .12s var(--ease);
}
.geo-tip.on { opacity: 1; }
.geo-tip b { font-size: 13px; font-weight: 500; color: var(--text); }
.geo-tip i { font-style: normal; font-size: 12px; font-weight: 500; color: var(--geo-hover); }
/* setinha apontando para o estado */
.geo-tip::after {
  content: ""; position: absolute; left: 50%; top: 100%; transform: translateX(-50%);
  border: 6px solid transparent; border-top-color: var(--card);
}
/* Parede da extrusão: cor chapada, sem traço — as divisas internas somem e o
   país lê como uma placa única erguida do card. */
.geo-wall use { fill: var(--geo-wall); stroke: none; }
/* Base opaca: isola as faces semitransparentes da parede que fica atrás.
   Sem ela a cor da parede vaza e suja o verde de todos os estados. */
.geo-base use { fill: url(#geo-placa); stroke: none; }
/* ESTADO SEM LEAD. O JS não manda mais tinta nele — quem pinta é aqui, porque
   a resposta depende do tema: no claro um verde bem apagado, no escuro nada,
   deixando a placa aparecer. */
.geo-tile:not(.hot) use { fill: var(--geo-vazio-cor); fill-opacity: var(--geo-vazio); }
.geo-tile { cursor: default; transition: opacity .16s ease; }
.geo-tile use { transition: fill-opacity .16s ease, stroke .16s ease, stroke-width .16s ease; }
.geo-map svg:hover .geo-tile:not(:hover) { opacity: .38; }
.geo-tile:hover use { stroke: var(--geo-hover); stroke-width: 4.2; }
.geo-lead { stroke: var(--geo-label-off); stroke-width: 2.3; pointer-events: none; }
/* 25 unidades ≈ 11px em tela. O halo separa a sigla do preenchimento em
   qualquer intensidade (paint-order desenha o contorno antes do miolo);
   fica fino de propósito, senão engrossa a letra e desfaz o peso 600. */
.geo-uf {
  font: 600 25px 'Inter Tight', sans-serif;
  letter-spacing: .01em;
  fill: var(--geo-label);
  pointer-events: none;
  paint-order: stroke fill;
  stroke: var(--geo-halo);
  stroke-width: 3.4;
  stroke-linejoin: round;
}
.geo-uf.off { fill: var(--geo-label-off); }
/* No escuro a rampa é invertida: os estados fortes ficam verde CLARO, então a
   sigla precisa virar escura (com halo claro) a partir de ~65% da intensidade (limiar que maximiza o pior contraste).
   No claro isso não acontece — mesmo o fill mais forte mantém 7.4:1 com a
   sigla escura, então não há troca. */
:root[data-theme="dark"] .geo-uf.strong { fill: var(--ink-on-verde); stroke: rgba(233, 244, 238, .82); }
/* O número herda a cor da sigla de propósito: sobre o verde mais forte, um tom
   apagado caía para ~1.6:1 de contraste. A hierarquia vem de peso e tamanho,
   que já bastam — e não abaixo de ~9px, ou vira ruído na escala do mapa. */
/* A FAIXA DA LEGENDA. Fininha e no rodapé do mapa: ela é uma nota de rodapé do
   desenho, não um elemento da tela. O número da ponta é o máximo, que é o que
   dá ESCALA — sem ele "mais" é um advérbio sem tamanho. */
.geo-legenda {
  display: flex; align-items: center; gap: 9px;
  margin: 10px auto 0; max-width: 420px;
  font-size: 11px; font-weight: 500; color: var(--muted);
}
.geo-legenda i { flex: 1; height: 7px; border-radius: 99px; display: block; }
.geo-legenda b {
  font-weight: 500; color: var(--text2); font-variant-numeric: tabular-nums;
  padding-left: 2px; border-left: 1px solid var(--border); margin-left: 2px;
}
.geo-empty { text-align: center; font-size: 12.5px; margin: 8px 0 0; }
.geo-side { display: flex; flex-direction: column; gap: 16px; }
.geo-block { background: var(--bg); border: 1px solid var(--border); border-radius: 14px; padding: 14px 15px; }
.geo-block .fb-sub { margin-bottom: 8px; }

/* ---------- exemplos de variáveis do template (exigência da Meta) ---------- */
.var-ex-box { background: var(--bg); border: 1px solid var(--border); border-radius: 14px; padding: 13px 14px; }
.var-ex-head { display: flex; align-items: center; gap: 7px; font-size: 12.5px; font-weight: 500; color: var(--text2); }
.var-ex-head .ic { color: var(--verde-esc); }

/* ---------- público da campanha (chips multi-seleção + alcance) ---------- */
.aud-chips { display: flex; flex-wrap: wrap; gap: 7px; margin-top: 8px; }
.aud-chip {
  font: inherit; font-size: 12.5px; font-weight: 650; color: var(--text2); cursor: pointer;
  background: var(--card); border: 1.5px solid var(--border2); border-radius: 8px; padding: 6px 14px;
  display: inline-flex; align-items: center; gap: 7px;
  transition: border-color .15s, background .15s, color .15s;
}
.aud-chip b { font-weight: 500; color: var(--faint); }
.aud-chip:hover { border-color: var(--verde-esc); }
.aud-chip.on { background: var(--brand-bg); border-color: var(--verde-esc); color: var(--verde-deep); }
.aud-chip.on b { color: var(--verde-deep); }
.reach-pill {
  display: inline-flex; align-items: center; gap: 7px; white-space: nowrap;
  background: var(--brand-bg); border: 1px solid var(--brand-border); color: var(--verde-deep);
  border-radius: 9px; padding: 8px 16px; font-size: 12.5px; font-weight: 650;
}
.reach-pill b { font-weight: 500; }
.reach-pill.empty { background: var(--amber-bg); border-color: var(--amber-border); color: #b26205; }

/* ---------- variáveis dinâmicas do disparo (sistema + webhook) ---------- */
.cvar-row { display: flex; gap: 10px; align-items: flex-end; margin-top: 8px; }
.cvar-wh {
  display: flex; gap: 10px; align-items: flex-end; margin: 8px 0 2px;
  background: var(--bg); border: 1px dashed var(--border2); border-radius: 12px; padding: 10px 12px;
}
.cvar-wh label { flex: 1; min-width: 0; }

/* editor de botões opcionais do nó "Enviar texto" */
.fb-sec { margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--border); }
.fb-btn-row { display: flex; align-items: center; gap: 7px; margin-bottom: 7px; }
.fb-btn-row input { flex: 1; min-width: 0; }

/* variáveis disponíveis no gatilho webhook (Flow Builder) */
.fb-vars { margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--border); }
.fb-var-chips { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 7px; }
.fb-var-chips code {
  background: var(--brand-bg); color: var(--verde-deep); border: 1px solid var(--brand-border);
  border-radius: 7px; padding: 3px 8px; font-size: 12px; font-weight: 600; cursor: pointer;
}
.fb-var-chips code:hover { background: var(--verde-esc); color: #fff; border-color: var(--verde-esc); }

/* ---------- janela de 24h + atendimento ---------- */
.chat-head-actions { display: flex; gap: 7px; align-items: center; flex-wrap: wrap; }

/* barra do header: indicador da janela + cronômetros */
.sess-bar {
  display: flex; align-items: center; gap: 16px; flex-wrap: wrap;
  padding: 9px 18px; border-bottom: 1px solid var(--border);
  background: var(--brand-bg); font-size: 12.5px;
}
.sess-bar.warn { background: var(--amber-bg); }
.sess-bar.crit, .sess-bar.off { background: var(--red-bg); }
.sess-bar.done { background: var(--bg2); }
.sess-chip { display: flex; align-items: center; gap: 9px; }
.sess-dot { width: 9px; height: 9px; border-radius: 50%; flex-shrink: 0; background: var(--verde-esc); box-shadow: 0 0 0 3px rgba(16, 185, 129, .18); }
.sess-bar.warn .sess-dot { background: var(--amber); box-shadow: 0 0 0 3px rgba(231, 156, 13, .18); }
.sess-bar.crit .sess-dot { background: var(--red); box-shadow: 0 0 0 3px rgba(229, 72, 77, .18); animation: sessPulse 1.4s ease-in-out infinite; }
.sess-bar.off .sess-dot { background: var(--red); box-shadow: none; }
.sess-bar.done .sess-dot { background: var(--faint); box-shadow: none; }
@keyframes sessPulse { 0%, 100% { opacity: 1; } 50% { opacity: .35; } }
.sess-chip b { display: block; font-size: 12.5px; font-weight: 500; color: var(--text); line-height: 1.25; }
.sess-chip span:not(.sess-dot) { font-size: 11.5px; color: var(--muted); font-weight: 600; }
.sess-timers { display: flex; gap: 18px; margin-left: auto; flex-wrap: wrap; }
.sess-timers > div { display: flex; flex-direction: column; line-height: 1.25; }
.sess-timers span { font-size: 10.5px; text-transform: uppercase; letter-spacing: .05em; color: var(--muted); font-weight: 500; }
.sess-timers b { font-size: 13.5px; font-weight: 500; color: var(--text); font-variant-numeric: tabular-nums; }
.sess-closed { display: flex; align-items: center; gap: 6px; margin-left: auto; color: var(--muted); font-weight: 600; }

/* aviso no composer quando bloqueado */
.sess-notice {
  display: flex; align-items: center; gap: 11px; margin-bottom: 11px;
  background: var(--bg2); border: 1px solid var(--border); border-radius: 12px;
  padding: 11px 13px; font-size: 12.5px; color: var(--text2); line-height: 1.45;
}
.sess-notice.expired { background: var(--red-bg); border-color: var(--red-border); }
/* só o ícone de alerta do aviso; o do botão herda a cor do texto (currentColor) */
.sess-notice > .ic { flex-shrink: 0; color: var(--muted); }
.sess-notice.expired > .ic { color: var(--red); }
.sess-notice > div { flex: 1; min-width: 0; }
.composer.locked textarea { background: var(--bg2); cursor: not-allowed; color: var(--faint); }
.composer.locked .tools .btn:disabled, .composer.locked .send-btn:disabled { opacity: .4; cursor: not-allowed; }

/* marcadores na lista de conversas */
.conv-tag {
  display: inline-flex; align-items: center; gap: 4px; margin-top: 4px;
  font-size: 10.5px; font-weight: 500; border-radius: 6px; padding: 2px 7px;
  background: var(--bg2); color: var(--muted);
}
.conv-tag.warn { background: var(--amber-bg); color: #b26205; }
.conv-tag.crit, .conv-tag.off { background: var(--red-bg); color: var(--red); }
.conv-tag.done { background: var(--brand-bg); color: var(--verde-deep); }
.conv-item.is-expired .conv-meta .name span, .conv-item.is-done .conv-meta .name span { opacity: .72; }

/* indicadores no dashboard */
.svc-kpis { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 12px; }
.svc-kpi {
  display: flex; flex-direction: column; gap: 2px; text-decoration: none;
  background: var(--bg); border: 1px solid var(--border); border-radius: 14px; padding: 14px 15px;
  transition: border-color .18s, box-shadow .18s;
}
.svc-kpi:hover { border-color: var(--verde-esc); box-shadow: var(--shadow-sm); text-decoration: none; }
.svc-kpi .svc-ic { color: var(--muted); margin-bottom: 4px; }
.svc-kpi b { font-size: 26px; font-weight: 500; letter-spacing: -.04em; color: var(--text); font-variant-numeric: tabular-nums; }
.svc-kpi span:not(.svc-ic) { font-size: 12px; font-weight: 650; color: var(--muted); }
.svc-kpi.warn .svc-ic { color: var(--amber); }
.svc-kpi.crit .svc-ic { color: var(--red); }
.svc-kpi.ok .svc-ic { color: var(--verde-esc); }

@media (max-width: 860px) {
  .sess-bar { padding: 8px 12px; gap: 10px; }
  .sess-timers { margin-left: 0; width: 100%; gap: 14px; justify-content: space-between; }
  .sess-closed { margin-left: 0; width: 100%; }
  .sess-notice { flex-wrap: wrap; }
  .sess-notice .btn { width: 100%; }
}

/* Inbox em coluna única no mobile: a lista ocupa a tela e o chat abre por cima
   (com botão de voltar). No desktop/tablet nada muda. */
.chat-back { display: none; }
@media (max-width: 720px) {
  /* A conversa é uma CAMADA por cima da lista, e não uma troca de display: só
     assim o gesto de voltar pode acompanhar o dedo. Fora da tela ela continua
     montada (o arrasto precisa de algo para mover), mas sem receber toque. */
  .inbox { position: relative; overflow: hidden; }
  .conv-list {
    width: 100%; flex-shrink: 1; border-right: none;
    transition: transform .26s var(--ease);
  }
  .inbox .chat {
    position: absolute; inset: 0; width: 100%; z-index: 5;
    background: var(--card);          /* opaco: a lista não pode vazar por baixo */
    transform: translateX(100%); pointer-events: none;
    transition: transform .26s var(--ease);
  }
  .inbox.chat-open .chat {
    transform: none; pointer-events: auto;
    box-shadow: -10px 0 26px rgba(0, 0, 0, .10);
  }
  /* a lista anda um pouco junto, como no WhatsApp: dá noção de profundidade */
  .inbox.chat-open .conv-list { transform: translateX(-22%); }
  /* enquanto o dedo manda, quem posiciona é o JS — transição só atrapalharia */
  .inbox.arrastando .chat, .inbox.arrastando .conv-list { transition: none; }
  .chat-back { display: inline-flex; }
  .chat-head { padding: 10px 12px; gap: 9px; flex-wrap: wrap; }
  .chat-head-actions { width: 100%; }
  .chat-head-actions .btn { flex: 1; }
  .composer { padding: 10px 12px 12px; }
}

/* ---------- atendentes ---------- */
.ag-av {
  border-radius: 50%; flex-shrink: 0; overflow: hidden; display: inline-flex; align-items: center; justify-content: center;
  background: linear-gradient(150deg, #25d366, #128c7e); color: #fff; font-weight: 500;
}
.ag-av img { width: 100%; height: 100%; object-fit: cover; }
.ag-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 14px; }
.ag-card { display: flex; flex-direction: column; gap: 12px; }
.ag-card.inactive { opacity: .62; }
.ag-head { display: flex; align-items: center; gap: 12px; }
.ag-name { font-size: 14.5px; display: flex; align-items: center; gap: 7px; }
.ag-info { display: flex; flex-direction: column; gap: 3px; font-size: 12.5px; color: var(--text2); }
.ag-info .ic { color: var(--faint); }
.ag-perms { display: flex; flex-wrap: wrap; gap: 5px; }
.pill.sm { font-size: 10px; padding: 1px 7px; }
.ag-actions { display: flex; gap: 6px; flex-wrap: wrap; margin-top: auto; align-items: center; }
.pres-dot { width: 9px; height: 9px; border-radius: 50%; display: inline-block; flex-shrink: 0; }
.pres-dot.ok { background: var(--verde-esc); box-shadow: 0 0 0 3px rgba(16,185,129,.18); }
.pres-dot.warn { background: var(--amber); }
.pres-dot.pending { background: #e0a800; }
.pres-dot.off { background: var(--faint); }

/* editor de atendente (modal) */
.ag-modal { max-width: 640px; }
.ag-form-top { display: flex; gap: 16px; align-items: flex-start; margin-bottom: 12px; }
.ag-photo-pick { display: flex; flex-direction: column; align-items: center; gap: 6px; cursor: pointer; font-size: 11px; color: var(--muted); font-weight: 500; }
.ag-photo-pick em { font-style: normal; display: flex; align-items: center; gap: 3px; }
.ag-perm-head { display: flex; align-items: center; justify-content: space-between; margin: 16px 0 8px; }
.ag-preset { flex-direction: row; align-items: center; gap: 8px; font-size: 12px; }
.ag-preset .ecsel { min-width: 160px; }
.ag-perm-grid { border: 1px solid var(--border); border-radius: 12px; overflow: hidden; max-height: 320px; overflow-y: auto; }
.ag-perm-top { display: flex; align-items: center; justify-content: space-between; padding: 9px 12px; background: var(--bg); border-bottom: 1px solid var(--bg2); font-size: 11.5px; }
.ag-perm-top .btn { padding: 3px 10px; }
.ag-perm-item { border-bottom: 1px solid var(--bg2); padding: 9px 12px; }
.ag-perm-item:last-child { border-bottom: none; }
.ag-perm-item.on { background: var(--brand-bg); }
.ag-perm-line { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.ag-perm-line b { font-size: 13px; font-weight: 650; }
.ag-perm-acts { display: flex; gap: 6px; margin-top: 8px; }
.act-pill {
  font: inherit; font-size: 11.5px; font-weight: 650; cursor: pointer;
  border: 1px solid var(--border2); background: var(--card); color: var(--muted);
  border-radius: 7px; padding: 3px 12px; transition: all .14s;
}
.act-pill.on { background: var(--verde-esc); border-color: var(--verde-esc); color: #fff; }

/* logs */
.log-list { display: flex; flex-direction: column; }
.log-row { display: flex; align-items: center; gap: 11px; padding: 9px 2px; border-bottom: 1px solid var(--bg2); font-size: 13px; }
.log-row:last-child { border-bottom: none; }
.log-ic { width: 30px; height: 30px; border-radius: 8px; background: var(--bg2); color: var(--muted); display: flex; align-items: center; justify-content: center; flex-shrink: 0; }

/* status do atendente no chat interno */
.my-status { display: flex; flex-wrap: wrap; gap: 5px; margin-bottom: 10px; }
.stbtn {
  display: inline-flex; align-items: center; gap: 5px; font: inherit; font-size: 11.5px; font-weight: 650;
  border: 1px solid var(--border2); background: var(--card); color: var(--text2); border-radius: 8px; padding: 4px 9px; cursor: pointer;
}
.stbtn.on { border-color: var(--verde-esc); background: var(--brand-bg); color: var(--verde-deep); }
.team-dm-av { position: relative; display: inline-block; flex-shrink: 0; }
.team-dm-av .pres-dot { position: absolute; right: -1px; bottom: -1px; border: 2px solid #fff; width: 11px; height: 11px; }
.assign-chip { display: inline-flex; align-items: center; gap: 6px; background: var(--bg2); border-radius: 999px; padding: 2px 10px 2px 2px; font-size: 12px; font-weight: 650; color: var(--text2); }

/* listas do dashboard (agenda + ranking) */
.dash-ev-list { display: flex; flex-direction: column; gap: 6px; }
.dash-ev { display: flex; align-items: center; gap: 10px; padding: 7px 10px; border-radius: 9px; background: var(--bg); border-left: 3px solid var(--evc); cursor: pointer; text-decoration: none; }
.dash-ev:hover { background: var(--brand-bg); text-decoration: none; }
.dash-ev b { font-size: 12px; font-variant-numeric: tabular-nums; color: var(--text); }
.dash-ev span { font-size: 12.5px; color: var(--text2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rank-list { display: flex; flex-direction: column; gap: 4px; }
.rank-row { display: flex; align-items: center; gap: 10px; padding: 6px 4px; border-bottom: 1px solid var(--bg2); }
.rank-row:last-child { border-bottom: none; }
.rank-pos { font-weight: 500; color: var(--muted); width: 24px; font-size: 13px; }

/* ---------- agendamentos / calendário ---------- */
.sched-toolbar { display: flex; align-items: center; gap: 8px; padding: 10px 14px; }
.sched-cal { padding: 0; overflow: hidden; }
.sc-dow { display: grid; grid-template-columns: repeat(7, 1fr); background: var(--bg); border-bottom: 1px solid var(--border); }
.sc-dow span { padding: 8px; text-align: center; font-size: 10.5px; font-weight: 500; text-transform: uppercase; letter-spacing: .05em; color: var(--muted); }
.sc-grid { display: grid; grid-template-columns: repeat(7, 1fr); grid-auto-rows: minmax(96px, 1fr); }
.sc-cell { border-right: 1px solid var(--bg2); border-bottom: 1px solid var(--bg2); padding: 5px 6px; cursor: pointer; min-height: 96px; transition: background .12s; }
.sc-cell:hover { background: var(--brand-bg); }
.sc-cell.out { background: #fafbfa; }
.sc-cell.out .sc-daynum { color: var(--faint); }
.sc-cell.today { background: var(--brand-bg); }
.sc-cell.today .sc-daynum { background: var(--verde-esc); color: var(--ink-on-verde); }
.sc-daynum { display: inline-flex; align-items: center; justify-content: center; min-width: 22px; height: 22px; border-radius: 7px; font-size: 12px; font-weight: 500; }
.sc-cell-evs { display: flex; flex-direction: column; gap: 3px; margin-top: 3px; }
.sc-drop { background: var(--brand-bg) !important; box-shadow: inset 0 0 0 2px var(--verde-esc); }
.sc-ev {
  font-size: 11px; font-weight: 600; color: #fff; border-radius: 6px; padding: 2px 7px; cursor: pointer;
  background: var(--evc); overflow: hidden; white-space: nowrap; text-overflow: ellipsis;
  border-left: 3px solid rgba(0,0,0,.18);
}
.sc-ev b { font-weight: 500; }
.sc-ev.done { opacity: .55; text-decoration: line-through; }
.sc-ev.late { box-shadow: 0 0 0 1.5px var(--red); }
.sc-ev-sub { opacity: .85; margin-left: 4px; }
.sc-more { font-size: 10.5px; color: var(--muted); font-weight: 500; padding-left: 4px; }

/* grade semana/dia */
.sc-tg { position: relative; }
.sc-tg-head { display: grid; grid-template-columns: 48px repeat(var(--cols), 1fr); border-bottom: 1px solid var(--border); position: sticky; top: 0; background: var(--card); z-index: 3; }
.sc-tg-head span { padding: 7px 4px; text-align: center; font-size: 11px; font-weight: 500; color: var(--muted); text-transform: capitalize; }
.sc-tg-head span b { display: block; font-size: 15px; color: var(--text); }
.sc-tg-head span.today b { color: var(--verde-deep); }
.sc-tg-body { position: relative; max-height: 62vh; overflow-y: auto; }
.sc-tg-row { display: grid; grid-template-columns: 48px repeat(var(--cols), 1fr); height: 48px; }
.sc-tg-hour { font-size: 10.5px; color: var(--faint); text-align: right; padding: 2px 6px 0 0; border-right: 1px solid var(--bg2); }
.sc-tg-cell { border-right: 1px solid var(--bg2); border-bottom: 1px solid var(--bg2); cursor: pointer; }
.sc-tg-cell:hover { background: var(--brand-bg); }
.sc-tg-layer { position: absolute; inset: 0; pointer-events: none; }
.sc-tg-ev {
  position: absolute; pointer-events: auto; background: var(--evc); color: #fff; border-radius: 7px;
  font-size: 11px; padding: 3px 7px; overflow: hidden; cursor: pointer; box-shadow: 0 2px 6px rgba(0,0,0,.12);
  border-left: 3px solid rgba(0,0,0,.2);
}
.sc-tg-ev.done { opacity: .55; }

/* modal de agendamento */
.sc-modal { max-width: 560px; }
.sc-colors { display: flex; gap: 8px; margin-top: 6px; }
.sc-color { width: 26px; height: 26px; border-radius: 8px; cursor: pointer; border: 2px solid transparent; }
.sc-color.on { border-color: var(--text); box-shadow: 0 0 0 2px #fff inset; }
.sc-reminders { display: flex; flex-wrap: wrap; gap: 8px 14px; margin-top: 6px; }
.sc-reminders .chk { font-size: 12.5px; }

@media (max-width: 760px) {
  .sched-page .seg { display: none; }
  .sc-grid { grid-auto-rows: minmax(64px, 1fr); }
  .sc-cell { min-height: 64px; }
  .ag-perm-row { grid-template-columns: 1.3fr repeat(4, 1fr); font-size: 11px; }
}

/* ---------- opt-in & opt-out ---------- */
.co-kpis { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 12px; margin-bottom: 18px; }
.co-kpis .svc-kpi { cursor: default; }
.co-kpis .svc-kpi:hover { border-color: var(--border); box-shadow: none; }

.kw-chips { display: flex; flex-wrap: wrap; gap: 7px; }
.kw-chip {
  display: inline-flex; align-items: center; gap: 3px; padding: 5px 6px 5px 12px;
  background: var(--bg); border: 1.5px solid var(--border2); border-radius: 8px;
  font-size: 12.5px; font-weight: 500; color: var(--text2); letter-spacing: .02em;
}
.kw-chip .icon-btn { padding: 2px; color: var(--faint); }
.kw-chip .icon-btn:hover { color: var(--red); background: transparent; }

.co-filters { display: flex; gap: 10px; align-items: flex-end; flex-wrap: wrap; }
.co-filters > label { flex: 0 1 auto; }
.co-table th { white-space: nowrap; }
.co-table td { vertical-align: top; font-size: 12.5px; }
.co-table td .pill { margin-top: 3px; }
.pill.off { color: var(--red); border-color: var(--red-border); background: var(--red-bg); }
.pill.off::before { background: var(--red); }

@media (max-width: 980px) {
  .co-filters > label, .co-filters > .btn { flex: 1 1 100%; min-width: 0 !important; }
}

/* ---------- pesquisa de satisfação (aba Finalização) ---------- */
.sv-grid { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 24px; align-items: start; }
.sv-form { display: flex; flex-direction: column; gap: 16px; min-width: 0; }
.sv-form .card { margin: 0; }
.sv-note { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; }
.sv-note input { flex: 1; min-width: 0; }
.sv-num {
  width: 24px; height: 24px; border-radius: 7px; flex-shrink: 0;
  background: var(--brand-bg); color: var(--verde-deep);
  display: flex; align-items: center; justify-content: center;
  font-size: 11.5px; font-weight: 500;
}
.sv-count { font-size: 11px; font-weight: 500; color: var(--faint); flex-shrink: 0; font-variant-numeric: tabular-nums; }
.sv-count.over { color: var(--red); }

/* folha inferior da mensagem de LISTA no preview */
.wa-sheet {
  align-self: stretch; margin: 6px 8px 0; background: var(--card); border-radius: 12px;
  overflow: hidden; box-shadow: 0 1px .5px rgba(11, 20, 26, .13); flex-shrink: 0;
}
.wa-sheet-h {
  padding: 8px 12px; font-size: 11px; font-weight: 500; color: #667781;
  text-transform: uppercase; letter-spacing: .05em; border-bottom: .5px solid rgba(60, 60, 67, .18);
}
.wa-sheet-row {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  padding: 10px 12px; font-size: 14px; color: #0b141a;
}
.wa-sheet-row + .wa-sheet-row { border-top: .5px solid rgba(60, 60, 67, .12); }
.wa-sheet-row i {
  width: 17px; height: 17px; border-radius: 50%; flex-shrink: 0;
  border: 1.5px solid #b8c2c7;
}

@media (max-width: 980px) {
  .sv-grid { grid-template-columns: 1fr; }
  .sv-grid .tpl-preview { display: none; }
}

/* ============================================================
   TELA DE LIGAÇÃO — desenho da tela de chamada do iPhone
   ============================================================
   Fundo preto com a foto do contato desfocada, nome no primeiro
   terço, botões circulares foscos e as duas ações irreversíveis
   (atender e recusar) nas pontas opostas da linha de baixo.
   ============================================================ */
.call-overlay {
  position: fixed; inset: 0; z-index: 500;
  background: #000;
  color: #fff; display: flex; flex-direction: column; align-items: center;
  padding: calc(58px + env(safe-area-inset-top, 0px)) 22px calc(46px + env(safe-area-inset-bottom, 0px));
  animation: fadeUp .25s var(--ease) both;
  overflow: hidden;
}
/* A FOTO do contato, ampliada e desfocada. `scale` porque o desfoque come as
   bordas: sem ela sobra uma moldura clara em volta da tela. */
.call-fundo {
  position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover;
  filter: blur(42px) saturate(1.25); transform: scale(1.35); opacity: .55;
}
/* O VÉU. Escurece de baixo para cima: embaixo ficam os botões, e botão sobre
   foto clara é botão que some. Em cima fica o nome, que precisa de contraste
   constante — daí o gradiente não zerar em lugar nenhum. */
.call-veu {
  position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(0,0,0,.55) 0%, rgba(0,0,0,.25) 34%, rgba(0,0,0,.82) 100%);
}
/* O conteudo sobe por cima da foto e do veu, que sao absolutos. O botao de
   minimizar fica de FORA desta regra: ele tem posicionamento proprio no canto,
   e um `position: relative` aqui o devolvia para o fluxo — ele ia parar
   centralizado em cima do nome do contato. */
.call-overlay > *:not(.call-fundo):not(.call-veu):not(.call-min) { position: relative; z-index: 1; }
.call-overlay .call-min { z-index: 2; }

/* ---- identificação, no primeiro terço ---- */
.call-id { text-align: center; }
.call-overlay h2 {
  font-size: clamp(28px, 7vw, 36px); font-weight: 400; letter-spacing: -.02em;
  color: #fff; margin: 0; line-height: 1.15;
}
/* O cinza do iOS para texto secundário sobre fundo escuro. Mais claro que
   isso vira um segundo título; mais escuro some sobre a foto. */
.call-status { font-size: 17px; color: rgba(235,235,245,.62); min-height: 24px; margin: 6px 0 0; font-weight: 400; }
#call-timer { font-variant-numeric: tabular-nums; font-weight: 400; }
.call-selo {
  display: inline-flex; align-items: center; gap: 5px; margin-top: 14px;
  padding: 5px 11px; border-radius: 999px;
  background: rgba(255,255,255,.12); backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px);
  font-size: 11.5px; font-weight: 500; color: rgba(235,235,245,.78);
}
.call-selo .ic { color: inherit; }

/* ---- o retrato ---- */
.call-center { flex: 1; display: flex; align-items: center; justify-content: center; }
.call-av {
  width: min(150px, 38vw); aspect-ratio: 1; border-radius: 50%;
  display: flex; align-items: center; justify-content: center; overflow: hidden;
  background: linear-gradient(150deg, #4a4a4f, #2c2c2e); color: #fff;
  font-size: clamp(38px, 10vw, 52px); font-weight: 400; position: relative;
  box-shadow: 0 20px 60px rgba(0,0,0,.5);
}
.call-av img { width: 100%; height: 100%; object-fit: cover; }
/* As ondas do toque. Duas, defasadas: uma só parece um erro de renderização,
   três viram enfeite. */
.call-av.ring::before, .call-av.ring::after {
  content: ''; position: absolute; inset: -14px; border-radius: 50%;
  border: 2px solid rgba(255,255,255,.35); animation: callRing 1.8s ease-out infinite;
}
.call-av.ring::after { animation-delay: .9s; }
@keyframes callRing { 0% { transform: scale(.88); opacity: 1; } 100% { transform: scale(1.4); opacity: 0; } }

/* ---- botões ---- */
.call-actions { display: flex; gap: 40px; align-items: flex-start; justify-content: center; width: 100%; max-width: 420px; }
/* Atender e recusar vão para as PONTAS. Lado a lado, um tremor na mão
   desliga na cara do cliente. */
.call-actions.atender { justify-content: space-between; padding: 0 12px; }
.call-act { display: flex; flex-direction: column; align-items: center; gap: 9px; font-size: 12px; color: rgba(235,235,245,.72); font-weight: 500; }
.call-btn {
  width: 72px; height: 72px; border-radius: 50%; border: none; cursor: pointer;
  display: flex; align-items: center; justify-content: center; color: #fff;
  transition: transform .15s, background .2s;
}
.call-btn:active { transform: scale(.9); }
/* O 'material' do iOS: translúcido com desfoque atrás. Sobre uma foto clara,
   um botão chapado sumiria; com o desfoque ele continua legível e ainda
   deixa a foto aparecer. */
.call-btn.fosco {
  background: rgba(255,255,255,.16); backdrop-filter: blur(22px); -webkit-backdrop-filter: blur(22px);
}
.call-btn.fosco.on { background: #fff; color: #000; }
.call-btn.green { background: #34c759; box-shadow: 0 10px 30px rgba(52,199,89,.4); }
.call-btn.red { background: #ff3b30; box-shadow: 0 10px 30px rgba(255,59,48,.35); }
.call-btn.dark { background: rgba(255,255,255,.16); backdrop-filter: blur(22px); -webkit-backdrop-filter: blur(22px); }
.call-btn.dark.on { background: #fff; color: #000; }
.call-btn.pulse { animation: callBtnPulse 1.5s ease-in-out infinite; }
@keyframes callBtnPulse { 0%,100% { box-shadow: 0 0 0 0 rgba(52,199,89,.5); } 50% { box-shadow: 0 0 0 18px rgba(52,199,89,0); } }
@media (prefers-reduced-motion: reduce) {
  .call-btn.pulse { animation: none; }
  .call-av.ring::before, .call-av.ring::after { animation: none; opacity: 0; }
}
/* ---------- webhook: modo escuta (aguardando evento real) ---------- */
.wh-wait { text-align: center; padding: 40px 24px; }
.wh-wait-anim {
  width: 72px; height: 72px; border-radius: 50%; margin: 0 auto 14px; position: relative;
  background: var(--brand-bg); color: var(--verde-deep); display: flex; align-items: center; justify-content: center;
}
.wh-wait-anim.off { background: var(--bg2); color: var(--faint); }
.wh-pulse { position: absolute; inset: -8px; border-radius: 50%; border: 2px solid var(--verde-esc); opacity: .5; animation: callRing 1.8s ease-out infinite; }
.wh-wait-clock { font-size: 34px; font-weight: 500; letter-spacing: -.03em; font-variant-numeric: tabular-nums; color: var(--verde-deep); margin-top: 8px; }
.wh-wait-clock.crit { color: var(--red); }

/* ---------- webhooks + mapeamento de campos ---------- */
.wh-card { display: flex; flex-direction: column; gap: 12px; }
.wh-ic { width: 40px; height: 40px; border-radius: 11px; background: var(--brand-bg); color: var(--verde-deep); display: flex; align-items: center; justify-content: center; flex-shrink: 0; }
.wh-url .linkrow { margin-top: 3px; }
.linkrow { display: flex; align-items: center; gap: 8px; background: var(--bg); border: 1px solid var(--border); border-radius: 10px; padding: 7px 10px; }
.linkrow code { flex: 1; min-width: 0; overflow-x: auto; white-space: nowrap; font-size: 12px; color: var(--text2); }
.wh-meta { display: flex; align-items: center; flex-wrap: wrap; gap: 7px; }
.wm-card { max-width: 720px; }
.wm-head { padding-bottom: 14px; border-bottom: 1px solid var(--border); margin-bottom: 18px; }
.wm-fields { display: flex; flex-direction: column; gap: 18px; }
.wm-field .wm-label { display: flex; align-items: center; gap: 8px; font-size: 14px; font-weight: 500; margin-bottom: 7px; }
.wm-field .wm-label .ic { color: var(--muted); }
.wm-req { color: var(--red); font-weight: 500; }
.wm-sample { margin-top: 6px; font-size: 12px; color: var(--muted); }
.wm-sample code { background: var(--bg2); border-radius: 5px; padding: 1px 5px; color: var(--verde-deep); font-weight: 600; }
.wm-sample b { color: var(--text); }
.wm-custom { margin-top: 22px; padding-top: 18px; border-top: 1px solid var(--border); }
.wm-crow { display: flex; align-items: center; gap: 8px; margin-top: 8px; }
.wm-crow input { flex: 1; }
.wm-crow .ecsel { flex: 1.2; }
.wm-eq { color: var(--faint); font-weight: 500; }
.wm-note { margin-top: 18px; background: var(--bg); border: 1px solid var(--border); border-radius: 12px; padding: 12px 14px; font-size: 12.5px; color: var(--muted); display: flex; gap: 9px; align-items: flex-start; }
.wm-note .ic { color: var(--faint); flex-shrink: 0; margin-top: 1px; }
.wm-warn { background: var(--amber-bg); border: 1px solid var(--amber-border); border-radius: 12px; padding: 14px; font-size: 13px; color: #7a5410; }
.wm-warn .ic { color: var(--amber); }
.wm-actions { display: flex; justify-content: flex-end; gap: 10px; margin-top: 16px; max-width: 720px; }

/* ---------- foto do perfil conectado ---------- */
.conn-id { display: flex; gap: 13px; align-items: center; margin: 2px 0 14px; }
.pf-avatar.sm { width: 52px; height: 52px; font-size: 17px; }
.pf-photo-row { display: flex; gap: 16px; align-items: center; margin-bottom: 16px; }
.pf-avatar {
  width: 72px; height: 72px; border-radius: 50%; flex-shrink: 0; overflow: hidden;
  background: linear-gradient(150deg, #25d366, #128c7e); color: #fff; font-weight: 500; font-size: 22px;
  display: flex; align-items: center; justify-content: center;
  box-shadow: 0 6px 18px rgba(16, 140, 100, .28);
}
.pf-avatar img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* ---------- responsivo ---------- */
@media (max-width: 960px) {
  .sidebar { width: 64px; padding: 16px 8px 12px; }
  .sidebar .brand-text, .nav-item span, .nav-label, .version { display: none; }
  .sidebar .brand { justify-content: center; padding-bottom: 14px; }
  .nav-item { justify-content: center; padding: 10px 6px; border-radius: 10px; }
  /* `.nav-item .badge`, e NÃO `.badge` solto. Aqui a sidebar encolheu para só
     ícones, e o contador precisa subir para o canto do ícone — mas a regra sem
     dono pegava TODA `.badge` da tela, e a lista de conversas usa a mesma
     classe. O resultado: o `position:absolute` procurava um ancestral
     posicionado, achava o `.inbox`, e as não lidas das SEIS conversas iam
     todas para o mesmo ponto, empilhadas no topo à direita — em cima do botão
     "+ Nova". O `margin: 0` ainda matava o `margin-left: auto` que é o que
     encosta o contador na direita da linha.
     Valia de 960px para baixo, então pegava tablet e janela estreita também. */
  .nav-item .badge { position: absolute; top: 2px; right: 2px; margin: 0; padding: 0 5px; }
  .page { padding: 18px 16px 34px; }
  .msg { max-width: min(78%, 400px); }
  .tb-user #who { display: none; }
}

/* A lista estreita é coisa de TABLET. Estava solta no bloco de 1000px, que vem
   depois do bloco do celular no arquivo e por isso ganhava dele: no telefone a
   lista ficava com 262px em vez de ocupar a tela. */
@media (min-width: 721px) and (max-width: 1000px) {
  .conv-list { width: 262px; }
}

/* ===================== Notificações (PWA) ===================== */
.notif-wrap { position: relative; }
.notif-bell {
  position: relative; width: 40px; height: 40px; border-radius: 12px;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--bg2); border: 1px solid var(--border); color: var(--text2);
  cursor: pointer; transition: background .15s, color .15s, box-shadow .15s;
}
.notif-bell:hover { background: var(--brand-bg); color: var(--brand-dark); box-shadow: var(--shadow-xs); }
.notif-dot {
  position: absolute; top: -5px; right: -5px; min-width: 18px; height: 18px; padding: 0 5px;
  border-radius: 999px; background: var(--red); color: #fff; font-size: 10.5px; font-weight: 500;
  display: inline-flex; align-items: center; justify-content: center; border: 2px solid var(--card);
}
.notif-panel {
  position: absolute; top: 50px; right: 0; width: min(360px, 92vw);
  background: var(--card); border: 1px solid var(--border); border-radius: var(--radius-sm);
  box-shadow: var(--shadow-lg); z-index: 60; overflow: hidden; animation: notifPop .16s ease;
}
@keyframes notifPop { from { opacity: 0; transform: translateY(-6px); } to { opacity: 1; transform: none; } }
.notif-hd { display: flex; align-items: center; justify-content: space-between; padding: 13px 15px; border-bottom: 1px solid var(--border); }
.notif-hd b { font-size: 14.5px; }
.notif-acts { display: flex; gap: 6px; }
.notif-list { max-height: min(60vh, 440px); overflow-y: auto; }
.notif-item { display: flex; gap: 11px; padding: 12px 15px; cursor: pointer; border-bottom: 1px solid var(--bg2); transition: background .12s; }
.notif-item:hover { background: var(--bg2); }
.notif-item.unread { background: var(--brand-bg); }
.notif-item.unread:hover { background: #e2f9ee; }
.notif-ic { width: 34px; height: 34px; border-radius: 10px; flex-shrink: 0; display: flex; align-items: center; justify-content: center; background: var(--bg2); color: var(--text2); }
.notif-ic.type-message { background: var(--brand-bg); color: var(--brand-dark); }
.notif-ic.type-call { background: var(--blue-bg); color: var(--blue-ink); }
.notif-ic.type-attendance { background: #f3edff; color: #6b3fd6; }
.notif-ic.type-reminder { background: var(--amber-bg); color: var(--amber); }
.notif-tx { min-width: 0; flex: 1; display: flex; flex-direction: column; gap: 1px; }
.notif-tx b { font-size: 13px; color: var(--text); }
.notif-tx span { font-size: 12px; color: var(--text2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.notif-tx em { font-size: 11px; color: var(--faint); font-style: normal; margin-top: 2px; }
.notif-empty { padding: 34px 16px; text-align: center; color: var(--muted); font-size: 13px; }

/* Configurações → Notificações */
.notif-perm { font-size: 11px; font-weight: 500; padding: 2px 9px; border-radius: 999px; vertical-align: middle; margin-left: 6px; }
.notif-perm.ok { background: var(--brand-bg); color: var(--brand-dark); }
.notif-perm.warn { background: var(--amber-bg); color: var(--amber); }
.notif-perm.bad { background: var(--red-bg); color: var(--red); }
.notif-sub { font-size: 12px; text-transform: uppercase; letter-spacing: .5px; color: var(--muted); margin: 18px 0 8px; font-weight: 500; }
.notif-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px 16px; }
.notif-chk { align-items: flex-start; }
.notif-chk span { display: flex; flex-direction: column; }
.notif-chk span em { font-style: normal; font-size: 11.5px; color: var(--muted); margin-top: 1px; }
@media (max-width: 700px) { .notif-grid { grid-template-columns: 1fr; } }

/* ============================================================
   MODO ESCURO — paleta estilo Simplify (fundo quase preto + verde)
   Ativado por [data-theme="dark"] no <html>. Como o app usa variáveis,
   basta sobrescrevê-las; abaixo só as exceções com cor fixa.
   ============================================================ */
:root[data-theme="dark"] {
  color-scheme: dark;
  /* O FUNDO É UM GRADIENTE, não uma cor: um halo verde bem fraco no alto e
     à esquerda, escurecendo até o preto embaixo. É o que dá o mesmo ar da
     vitrine e da referência — sem isso a tela fica de um preto plano que
     achata os cards. */
  --fundo-halo: radial-gradient(1200px 620px at 12% -6%, rgba(46,211,120,.10), transparent 62%),
                radial-gradient(900px 520px at 88% 4%, rgba(46,211,120,.05), transparent 60%),
                linear-gradient(180deg, #0c100e 0%, #070908 46%, #050706 100%);
  /* Superfícies na MATIZ DA MARCA (h~165), não em oliva (h110-120).
     O oliva é o que lia como "musgo" no escuro: mesma dessaturação, mas o
     matiz puxava para amarelo. Luminâncias preservadas — só o matiz girou. */
  /* Carbono, o mesmo da vitrine: a tela é quase preta e cada superfície sobe
     um degrau. O brilho verde do fundo mora no gradiente do corpo, logo
     abaixo — chapar tudo aqui deixaria a tela sem profundidade. */
  --bg: #070908;
  --bg2: #0e1211;
  --card: #141a18;
  --glass: rgba(12, 16, 15, .82);
  --border: #222a28;
  --border2: #283431;

  --text: #e9f1ef;
  --text2: #b5c2bf;
  --muted: #98a9a5;   /* legibilidade AA sobre os cards escuros */
  --faint: #7c8b87;   /* era #6d786c (3.5:1) — agora ~4.8:1 */

  --brand-bg: #232f2c;      /* tint na matiz da marca, bem dessaturado */
  --brand-border: #30403c;

  --sidebar: #0b0e0d;
  --sidebar-hover: #141a19;
  --sidebar-text: #96a5a1;
  --tinta: #e9f1ef;

  --red-bg: #2a1315;   --red-border: #4a2024;
  /* O vermelho de TEXTO inverte com o tema: no claro precisa fechar para ser
     lido sobre branco (#d1373c); no escuro precisa ABRIR, porque #d1373c sobre
     o card quase preto cai para 3,53:1. */
  --red-ink: #f2696d;
  --amber: #fbbf24;    /* amarelo forte no escuro (era laranja) */
  --amber-bg: #2b2410; --amber-border: #6b5518;
  --blue-bg: #0f1e2b;  --blue-border: #1d3a52; --blue-ink: #7cc4f5;

  --shadow-xs: 0 1px 2px rgba(0, 0, 0, .4);
  --shadow-sm: 0 2px 8px rgba(0, 0, 0, .45);
  --shadow: 0 16px 40px -10px rgba(0, 0, 0, .6);
  --shadow-lg: 0 30px 70px -16px rgba(0, 0, 0, .7);
  --glow: 0 8px 24px rgba(46, 211, 120, .22);
}

/* Exceções que usavam gradiente/branco fixo */
/* O LOGIN/CADASTRO fica SEMPRE no tema claro, mesmo com o app em modo escuro:
   é a primeira tela que a pessoa vê, antes de existir preferência salva, e o
   card branco é a identidade da marca. Redefinimos os tokens no próprio
   .login-wrap, então tudo dentro dele herda os valores claros. */
:root[data-theme="dark"] .login-wrap {
  --bg: #fbfdf9;
  --bg2: #f4f7f2;
  --card: #ffffff;
  --border: #e6f0ea;
  --border2: #d7eee3;
  --text: #0f1f15;
  --text2: #3a4a3e;
  /* Cinzas de apoio, escurecidos até passarem de 4,5:1 sobre o card branco.
     Nos valores antigos (#7b8a79 = 3,65 e #93a092 = 2,73) rótulos inteiros do
     produto ficavam quase invisíveis: "Geral" e "Atendimento" no menu, a versão
     no rodapé, os dias do calendário, os subtítulos dos cartões. Continuam
     lendo como texto secundário — só que legíveis. */
  --muted: #667563;
  --faint: #63715f;
  --brand-bg: #eafbf0;
  --brand-border: #bfeccf;
  /* o verde do modo escuro é claro demais para fundo branco */
  --verde: #50ea5f;
  --verde-esc: #2ed378;
  --verde-deep: #178048;
  --brand: #2ed378;
  --brand-dark: #178048;
  --shadow-xs: 0 1px 2px rgba(15, 31, 21, .05);
  --shadow-sm: 0 2px 8px rgba(15, 31, 21, .05);
  background: linear-gradient(180deg, #fcfef9 0%, #ecfdf5 100%);
  color: var(--text);
}
:root[data-theme="dark"] .mh-card.hi { background: linear-gradient(150deg, #202527 0%, #131617 58%, #0a0b0c 100%); border-color: #262c2d; }
:root[data-theme="dark"] .mh-card.hi .mh-ic { background: rgba(255, 255, 255, .1) !important; color: #eef3f1; border-color: rgba(255, 255, 255, .12); }
:root[data-theme="dark"] .fb-n.trig { background: linear-gradient(160deg, #241f10, #191610); }
:root[data-theme="dark"] .tabs button.active { box-shadow: 0 2px 10px rgba(0, 0, 0, .5); }
:root[data-theme="dark"] .toggle span { background: #e9f1ef; }
/* barras de rolagem escuras */
:root[data-theme="dark"] ::-webkit-scrollbar { width: 10px; height: 10px; }
:root[data-theme="dark"] ::-webkit-scrollbar-thumb { background: #2a3331; border-radius: 8px; }
:root[data-theme="dark"] ::-webkit-scrollbar-track { background: transparent; }

/* seletor de aparência (Configurações) */
.seg-theme { display: inline-flex; gap: 6px; background: var(--bg2); border: 1px solid var(--border); padding: 4px; border-radius: 12px; }
.seg-theme button { display: inline-flex; align-items: center; gap: 7px; border: 0; background: transparent; color: var(--text2); font: inherit; font-weight: 500; font-size: 13px; padding: 8px 16px; border-radius: 9px; cursor: pointer; transition: background .15s, color .15s; }
.seg-theme button.on { background: var(--card); color: var(--text); box-shadow: var(--shadow-xs); }
.seg-theme button.on svg { color: var(--verde-esc); }

/* botão de tema no topbar */
.theme-btn { width: 40px; height: 40px; border-radius: 12px; display: inline-flex; align-items: center; justify-content: center; background: var(--bg2); border: 1px solid var(--border); color: var(--text2); cursor: pointer; transition: background .15s, color .15s; }
.theme-btn:hover { background: var(--brand-bg); color: var(--brand-dark); }

/* ---- MODO ESCURO: verdes de texto/ícone → claros (legibilidade) ---- */
:root[data-theme="dark"] {
  /* tokens de verde usados como COR de texto/ícone (feitos p/ fundo claro) → claros */
  --verde-deep: #6ee7b7;
  --brand-dark: #6ee7b7;
}
/* botões secundários: texto verde-escuro fixo → claro */
:root[data-theme="dark"] .btn:not(.primary):not(.danger):not(.danger-solid) { color: #eaf6f2; }
/* ícones dos cards do dashboard e afins → branco */
:root[data-theme="dark"] .tile-ic,
:root[data-theme="dark"] .stat-ico,
:root[data-theme="dark"] .lc-ic,
:root[data-theme="dark"] .mh-ic,
:root[data-theme="dark"] .capi-head,
:root[data-theme="dark"] .tile-ic svg,
:root[data-theme="dark"] .stat-ico svg { color: #ffffff; stroke: currentColor; }
/* selos de ícone (badges) com o mesmo gradiente cinza/preto — SEM o .svc-ic,
   que é apenas um ícone dentro dos KPIs (não um selo, pra não virar barra) */
:root[data-theme="dark"] .tile-ic,
:root[data-theme="dark"] .stat-ico,
:root[data-theme="dark"] .lc-ic,
:root[data-theme="dark"] .mh-ic,
:root[data-theme="dark"] .notif-ic.type-message {
  background: linear-gradient(150deg, #202527, #131617) !important;
  border: 1px solid #313839;
}
/* textos com destaque verde → claros */
:root[data-theme="dark"] .hh-date { color: #d9f2ea; }
:root[data-theme="dark"] .pill.done { color: #d9f2ea; }
/* Texto branco nos botões sólidos, nos dois temas. */
:root[data-theme="dark"] .btn.danger,
:root[data-theme="dark"] .btn.danger-solid,
:root[data-theme="dark"] .btn.primary { color: #ffffff; }

/* ---- MODO ESCURO: hover dos botões reforça o VERDE (não branco) ---- */
:root[data-theme="dark"] .btn:not(.primary):not(.danger):not(.danger-solid):hover {
  color: var(--verde);
  border-color: var(--verde);
  background: var(--brand-bg);
}
:root[data-theme="dark"] .btn:not(.primary):not(.danger):not(.danger-solid):hover svg { color: var(--verde); }

/* ---- MODO ESCURO: hover de linha da tabela → fundo um pouco mais forte (não branco) ---- */
:root[data-theme="dark"] tbody tr:hover td { background: #202a27; }

/* ---- MODO ESCURO: bolhas de conversa ----
   .msg/.tmsg-bub tinham fundo claro cravado (#d1fae5) e texto oliva escuro sem
   contraparte no escuro: o texto caía para 1.3:1 (ilegível) e o oliva era o que
   lia como musgo no chat. Fundo agora é esmeralda escura da marca. */
:root[data-theme="dark"] .msg.out,
:root[data-theme="dark"] .tmsg.mine .tmsg-bub { background: #163b2f; border-color: #1e5240; }
/* hover da lista de conversas: #f4faf4 é quase branco e piscava no escuro */
:root[data-theme="dark"] .conv-item:hover { background: var(--sidebar-hover); }

/* ===================== Pagamentos ===================== */
/* gráfico de recebimentos (14 dias) */
.ep-chart { display: flex; align-items: flex-end; gap: 6px; height: 150px; padding-top: 8px; }
.ep-bar-w { flex: 1; display: flex; flex-direction: column; align-items: center; gap: 5px; height: 100%; justify-content: flex-end; min-width: 0; }
.ep-bar { width: 100%; max-width: 34px; border-radius: 7px 7px 3px 3px; background: linear-gradient(180deg, #50ea5f, var(--verde-esc)); transition: height .3s var(--ease); }
.ep-bar-w span { font-size: 10px; color: var(--faint); font-weight: 500; }

/* detalhe da cobrança (QR + copia e cola) */
.ep-detail { display: flex; gap: 18px; margin-top: 14px; align-items: flex-start; }
.ep-qr { width: 168px; height: 168px; flex-shrink: 0; border-radius: 14px; border: 1px solid var(--border2); background: #fff; padding: 8px; }
.ep-detail-info { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.ep-copy { display: flex; gap: 6px; margin-top: 4px; }
.ep-copy input { flex: 1; min-width: 0; font-size: 12px; padding: 8px 10px; overflow: hidden; text-overflow: ellipsis; }
@media (max-width: 620px) { .ep-detail { flex-direction: column; align-items: center; } }

/* ---------- Checkout Builder (aba Checkout do Pagamentos) ---------- */
.epk-grid { display: grid; grid-template-columns: minmax(0, 1fr) 460px; gap: 22px; align-items: start; }
@media (max-width: 900px) { .epk-grid { grid-template-columns: 1fr; } .epk-prevwrap { max-width: 380px; margin: 0 auto; width: 100%; } }

.epk-upload {
  display: flex; align-items: center; gap: 12px; margin-top: 4px; padding: 10px 12px;
  border: 1.5px dashed var(--border2); border-radius: 12px; cursor: pointer;
  transition: border-color .15s, background .15s;
}
.epk-upload:hover { border-color: var(--verde); background: var(--verde-05, rgba(16, 185, 129, .05)); }
.epk-thumb {
  flex-shrink: 0; border-radius: 9px; background: var(--bg2) center/cover no-repeat;
  display: flex; align-items: center; justify-content: center; color: var(--faint);
  border: 1px solid var(--border2); overflow: hidden;
}
.epk-thumb.has { color: transparent; }
.epk-thumb.has svg { display: none; }
.epk-thumb-banner { width: 96px; height: 40px; }
.epk-thumb-logo { width: 46px; height: 46px; border-radius: 12px; }
.epk-upmeta { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.epk-upmeta b { font-size: 13px; }
.epk-upmeta .muted { font-size: 11.5px; }

.epk-colors { display: flex; align-items: center; gap: 8px; margin-top: 6px; flex-wrap: wrap; }
.epk-swatch {
  width: 30px; height: 30px; border-radius: 50%; border: 2.5px solid transparent; cursor: pointer;
  padding: 0; outline: 2px solid transparent; transition: transform .12s, outline-color .12s;
}
.epk-swatch:hover { transform: scale(1.12); }
.epk-swatch.on { outline-color: var(--verde); outline-offset: 2px; }
#epk-colorpick { width: 34px; height: 34px; padding: 2px; border: 1px solid var(--border2); border-radius: 9px; background: var(--card); cursor: pointer; }

/* moldura de navegador da prévia */
.epk-prevwrap { position: sticky; top: 14px; }
.epk-browser { border: 1px solid var(--border2); border-radius: 14px; overflow: hidden; box-shadow: var(--shadow2, 0 12px 34px -18px rgba(0, 0, 0, .25)); background: var(--card); }
.epk-bbar { display: flex; align-items: center; gap: 5px; padding: 9px 12px; background: var(--bg2); border-bottom: 1px solid var(--border2); }
.epk-bbar i { width: 9px; height: 9px; border-radius: 50%; background: var(--border2); }
.epk-bbar i:nth-child(1) { background: #f87171; } .epk-bbar i:nth-child(2) { background: #fbbf24; } .epk-bbar i:nth-child(3) { background: var(--verde); }
.epk-bbar span { flex: 1; text-align: center; font-size: 10.5px; color: var(--faint); background: var(--card); border-radius: 6px; padding: 3px 8px; margin-left: 6px; }

/* réplica fiel da página /pay/:id — modelo card em 2 colunas (ref. Figma "Checkout Page") */
.epk-page { background: #eef1f6; color: #1a2233; max-height: 620px; overflow-y: auto; position: relative; font-family: -apple-system, 'Segoe UI', Roboto, sans-serif; padding: 12px; }
.epk2-topbar { display: flex; align-items: center; justify-content: space-between; margin-bottom: 12px; }
.epk2-brand { display: flex; align-items: center; gap: 8px; }
.epk2-brand img { width: 26px; height: 26px; border-radius: 6px; object-fit: cover; background: #fff; }
.epk2-brand .ph { width: 26px; height: 26px; border-radius: 6px; display: flex; align-items: center; justify-content: center; background: var(--epkc, #2ed378); color: #fff; font-weight: 500; font-size: 12px; }
.epk2-brand b { font-size: 11px; font-weight: 500; display: block; }
.epk2-brand small { font-size: 8.5px; color: #6b7488; }
.epk2-secure { font-size: 8.5px; font-weight: 600; color: #4b5568; background: #fff; border: 1px solid #e7eaf0; padding: 4px 8px; border-radius: 99px; }

.epk2-grid { display: grid; grid-template-columns: minmax(0, 1fr) 150px; gap: 10px; align-items: start; }
.epk2-main, .epk2-summary { background: #fff; border: 1px solid #e7eaf0; border-radius: 11px; box-shadow: 0 2px 6px rgba(20,30,55,.05); }
.epk2-main { padding: 11px 13px; }

.epk2-steps { display: flex; align-items: center; margin-bottom: 10px; }
.epk2-stp { display: flex; align-items: center; gap: 4px; font-size: 8px; font-weight: 600; color: #97a0b3; }
.epk2-stp i { width: 15px; height: 15px; border-radius: 50%; font-style: normal; font-size: 8px; font-weight: 500; display: flex; align-items: center; justify-content: center; background: #eef1f6; color: #97a0b3; border: 1.5px solid #e2e6ee; }
.epk2-stp.cur { color: #1a2233; } .epk2-stp.cur i { background: var(--epkc, #2ed378); border-color: var(--epkc, #2ed378); color: #fff; }
.epk2-stp.done i { background: color-mix(in srgb, var(--epkc, #2ed378) 15%, #fff); border-color: color-mix(in srgb, var(--epkc, #2ed378) 45%, #fff); color: var(--epkc, #2ed378); }
.epk2-stpsep { flex: 1; height: 1.5px; background: #e2e6ee; margin: 0 6px; }
.epk2-stpsep.done { background: color-mix(in srgb, var(--epkc, #2ed378) 45%, #fff); }

.epk2-mtitle { font-size: 12px; font-weight: 500; }
.epk2-msub { font-size: 8.5px; color: #6b7488; margin-bottom: 9px; }
.epk2-fld { margin-bottom: 6px; }
.epk2-fld small { display: block; font-size: 8px; font-weight: 500; color: #33405c; margin-bottom: 2px; }
.epk2-fld span { display: block; font-size: 9.5px; color: #aab2c2; border: 1px solid #e7eaf0; border-radius: 6px; padding: 6px 8px; background: #fbfcfe; }
.epk2-fld span.filled { color: #1a2233; }
.epk2-chip { display: flex; align-items: center; font-size: 9px; color: #33405c; background: #f6f8fb; border: 1px solid #e7eaf0; border-radius: 7px; padding: 6px 9px; margin-bottom: 9px; }
.epk2-qrwrap { display: flex; gap: 10px; align-items: center; }
.epk2-qrframe { flex: none; padding: 6px; border: 1px solid #e7eaf0; border-radius: 9px; background: #fff; }
.epk2-qrframe svg { width: 60px; height: 60px; display: block; color: #1a2233; }
.epk2-qrside b { font-size: 10px; display: block; margin-bottom: 4px; }
.epk2-qrside span { font-size: 8.5px; color: #6b7488; display: block; line-height: 1.5; }
.epk2-orlbl { display: flex; align-items: center; gap: 8px; font-size: 7px; font-weight: 500; letter-spacing: .5px; color: #97a0b3; margin: 11px 0 7px; }
.epk2-orlbl::before, .epk2-orlbl::after { content: ''; flex: 1; height: 1px; background: #e7eaf0; }
.epk2-copy { font-size: 8px; color: #33405c; background: #f8f9fc; border: 1px solid #e7eaf0; border-radius: 6px; padding: 7px 9px; font-family: ui-monospace, monospace; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

.epk2-sumhead { font-size: 8px; font-weight: 500; letter-spacing: .3px; text-transform: uppercase; color: #97a0b3; padding: 9px 11px 0; }
.epk2-prod { display: flex; gap: 8px; padding: 7px 11px 9px; border-bottom: 1px solid #e7eaf0; }
.epk2-thumb { width: 34px; height: 34px; border-radius: 8px; object-fit: cover; flex: none; }
.epk2-thumb.ph { display: flex; align-items: center; justify-content: center; background: color-mix(in srgb, var(--epkc, #2ed378) 12%, #fff); color: var(--epkc, #2ed378); font-weight: 500; font-size: 13px; }
.epk2-pinfo { min-width: 0; align-self: center; }
.epk2-pinfo b { font-size: 9.5px; font-weight: 500; line-height: 1.25; display: block; }
.epk2-pinfo span { font-size: 8px; color: #6b7488; display: block; margin-top: 2px; line-height: 1.35; }
.epk2-rows { padding: 8px 11px; }
.epk2-row { display: flex; justify-content: space-between; font-size: 9px; color: #4b5568; padding: 2px 0; }
.epk2-row.total { font-size: 11px; font-weight: 500; color: #1a2233; border-top: 1px dashed #e7eaf0; margin-top: 4px; padding-top: 6px; }
.epk2-btn { margin: 0 11px; text-align: center; font-size: 9.5px; font-weight: 600; color: #fff; padding: 8px; border-radius: 7px; background: var(--epkc, #2ed378); }
.epk2-note { font-size: 7.5px; color: #97a0b3; text-align: center; padding: 6px 11px 11px; }
.epk2-wait { margin: 0 11px 11px; display: flex; align-items: center; justify-content: center; gap: 5px; font-size: 8.5px; font-weight: 600; color: var(--epkc, #2ed378); border: 1px solid color-mix(in srgb, var(--epkc, #2ed378) 30%, #fff); background: color-mix(in srgb, var(--epkc, #2ed378) 6%, #fff); border-radius: 7px; padding: 8px; }
.epk2-wait i { width: 6px; height: 6px; border-radius: 50%; background: var(--epkc, #2ed378); }
.epk2-support { text-align: center; font-size: 8px; color: #97a0b3; margin-top: 8px; }

/* página do builder: passos do fluxo + tabs da prévia */
/* página do builder: passos do fluxo + tabs da prévia */
.epk-flowsteps div { display: flex; gap: 11px; align-items: flex-start; margin-top: 10px; }
.epk-flowsteps i { flex: none; width: 24px; height: 24px; border-radius: 50%; background: var(--bgt, #ecfdf5); color: var(--verde-esc); font-style: normal; font-weight: 500; font-size: 12px; display: flex; align-items: center; justify-content: center; }
.epk-flowsteps span { font-size: 13px; color: var(--muted); line-height: 1.5; }
.epk-prevtabs { margin-bottom: 10px; justify-content: center; display: flex; }

/* modo escuro: só a moldura escurece — a página em si permanece clara */
:root[data-theme="dark"] .epk-upload:hover { background: rgba(46, 211, 120, .07); }
:root[data-theme="dark"] .epk-page { background: #fff; }
/* relatório: volume por cliente (admin) */
/* ---- Lista de conexões WhatsApp (Configurações) ---- */
.ch-list { display: flex; flex-direction: column; gap: 8px; }
.ch-row {
  display: flex; align-items: center; gap: 10px;
  padding: 11px 13px; background: var(--bg); border: 1px solid var(--border); border-radius: 12px;
}
.ch-row.sel { border-color: var(--verde); background: var(--brand-bg); }
.ch-row > div b { font-size: 13.5px; font-weight: 500; }
@media (max-width: 560px) { .ch-row { flex-wrap: wrap; } .ch-row > div { flex: 1 0 70%; } }

/* ---- Prazos de liquidação (só leitura — vêm da adquirente) ---- */
.settle-box { margin-top: 14px; padding: 14px; background: var(--bg); border: 1px solid var(--border); border-radius: 12px; }
.settle-head {
  display: flex; align-items: center; gap: 7px; margin-bottom: 12px; color: var(--text);
  font: inherit; font-weight: 500; font-size: 13px; letter-spacing: -.01em;
}
.settle-tag {
  margin-left: auto; padding: 3px 9px; border-radius: 99px;
  background: var(--bg2); border: 1px solid var(--border2); color: var(--muted);
  font: inherit; font-weight: 500; font-size: 10.5px; letter-spacing: .04em; text-transform: uppercase;
}
.settle-rows { display: grid; grid-template-columns: repeat(auto-fit, minmax(215px, 1fr)); gap: 10px; }
.settle-row {
  display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap;
  padding: 10px 12px; background: var(--card); border: 1px solid var(--border); border-radius: 10px;
}
.settle-row span { font-size: 12.5px; font-weight: 500; color: var(--muted); }
.settle-row b { font-size: 16px; font-weight: 500; letter-spacing: -.02em; color: var(--verde-deep); }
.settle-row em { flex: 1 0 100%; font-size: 11.5px; font-weight: 500; font-style: normal; color: var(--muted); }
:root[data-theme="dark"] .settle-row b { color: var(--verde); }

/* ---- Papel do modelo (cobrança x confirmação) ---- */
.role-box { margin-top: 14px; padding: 13px; background: var(--bg); border: 1px solid var(--border); border-radius: 12px; }
.role-head {
  display: flex; align-items: center; gap: 7px; margin-bottom: 11px; color: var(--text);
  font: inherit; font-weight: 500; font-size: 13px; letter-spacing: -.01em;
}
.role-hint { margin-left: auto; font-weight: 500; font-size: 11.5px; color: var(--muted); }
.var-chips { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 10px; }
.var-chip {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 4px 10px; border: 1px solid var(--border2); border-radius: 99px;
  background: var(--card); color: var(--text2);
  font: inherit; font-weight: 600; font-size: 11.5px; cursor: pointer;
  transition: border-color .15s, color .15s;
}
.var-chip:hover { border-color: var(--verde); color: var(--verde-deep); }
.var-chip b { color: var(--verde-deep); font-weight: 500; }
:root[data-theme="dark"] .var-chip b, :root[data-theme="dark"] .var-chip:hover { color: var(--verde); }

/* ---- Escolha do modelo enviado (Pagamentos → Mensagens) ---- */
.tplpick { padding: 13px; margin-bottom: 10px; background: var(--bg); border: 1px solid var(--border); border-radius: 12px; }
.tplpick:last-child { margin-bottom: 0; }
.tplpick.vazio { border-style: dashed; }
.tplpick-head { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; font-size: 13px; color: var(--text); }
.tplpick-head b { font-weight: 500; }
.tplpick-body {
  margin: 10px 0 0; padding: 9px 11px; border-radius: 9px;
  background: var(--card); border: 1px solid var(--border);
  font-size: 12px; font-weight: 500; color: var(--muted); white-space: pre-wrap;
}

/* ---- Carteira: disponível x a liberar ---- */
.wallet-split { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 12px; }
.wal-box { padding: 14px; background: var(--bg); border: 1px solid var(--border); border-radius: 12px; }
.wal-box.hi { background: var(--brand-bg); border-color: var(--brand-border); }
.wal-lbl { display: block; font-size: 11.5px; font-weight: 500; color: var(--muted); }
.wal-val { display: block; margin: 5px 0 3px; font-size: 22px; font-weight: 500; letter-spacing: -.02em; color: var(--text); }
.wal-box.hi .wal-val { color: var(--verde-deep); }
.wal-sub { display: block; font-size: 11.5px; font-weight: 500; color: var(--muted); }

/* ---- Consumo x limites (tela de Assinatura) ---- */
.use-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); gap: 12px; }
.use-item { padding: 13px; background: var(--bg); border: 1px solid var(--border); border-radius: 12px; }
.use-top { display: flex; align-items: baseline; gap: 8px; font-size: 12.5px; font-weight: 500; color: var(--muted); }
.use-top span { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.use-top b { color: var(--text); font-size: 13px; font-weight: 500; white-space: nowrap; }
.use-bar { height: 6px; margin: 9px 0 7px; background: var(--border); border-radius: 99px; overflow: hidden; }
.use-bar i { display: block; height: 100%; background: var(--verde); border-radius: 99px; transition: width .35s ease; }
.use-item.warn .use-bar i { background: var(--amber, #d99a2b); }
.use-item.full { border-color: color-mix(in srgb, var(--red, #d3564b) 45%, var(--border)); }
.use-item.full .use-bar i { background: var(--red, #d3564b); }
.use-sub { font-size: 11.5px; font-weight: 500; color: var(--muted); }

.extra-grid { display: flex; flex-direction: column; gap: 10px; }
.extra-item {
  display: flex; align-items: center; gap: 10px;
  padding: 12px 13px; background: var(--bg); border: 1px solid var(--border); border-radius: 12px;
}
.extra-qty { width: 62px; flex: 0 0 auto; text-align: center; }
.pl-btns { display: flex; gap: 8px; }
.pl-btns .btn { flex: 1; }
.pl-feats .pl-lim { color: var(--muted); }
.pl-feats .pl-lim b { color: var(--text); }
@media (max-width: 560px) { .extra-item { flex-wrap: wrap; } .extra-item > div { flex: 1 0 100%; } }

/* ---- Limites de plano (Admin SaaS) ---- */
.lim-box { margin-top: 14px; padding: 14px; background: var(--bg); border: 1px solid var(--border); border-radius: 12px; }
.lim-head {
  display: flex; align-items: center; gap: 7px; margin-bottom: 12px; color: var(--text);
  font: inherit; font-weight: 500; font-size: 13px; letter-spacing: -.01em;
}
.lim-hint { margin-left: auto; font: inherit; font-weight: 500; font-size: 11.5px; color: var(--muted); }
.lim-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(165px, 1fr)); gap: 10px 12px; }
.lim-grid label { margin: 0; }
.lim-extra { font-size: 11px; font-weight: 500; font-style: normal; color: var(--verde-esc); }
:root[data-theme="dark"] .lim-extra { color: var(--verde); }

.plan-row { padding: 14px 0; border-bottom: 1px solid var(--border); }
.plan-row:last-child { border-bottom: 0; padding-bottom: 0; }
.plan-head { display: flex; align-items: center; gap: 10px; }
.plan-lims { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 10px; }
.plan-edit { margin-top: 4px; }
.plan-edit.hidden { display: none; }

/* ---- Painel único de taxas (Pix In/Out + cartão) ---- */
.fee-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(215px, 1fr)); gap: 14px; }
.fee-col { padding: 14px; background: var(--bg); border: 1px solid var(--border); border-radius: 12px; }
.fee-col label { margin: 0; }
.fee-col .hint { margin: 9px 0 0; }
.fee-tag {
  display: inline-flex; align-items: center; gap: 6px; margin-bottom: 11px;
  padding: 4px 9px; border-radius: 99px;
  font: inherit; font-weight: 500; font-size: 11px; letter-spacing: .05em; text-transform: uppercase;
}
.fee-tag.in  { background: color-mix(in srgb, var(--verde) 16%, transparent); color: var(--verde-esc); }
.fee-tag.out { background: color-mix(in srgb, var(--muted) 16%, transparent); color: var(--muted); }
.fee-sep { height: 1px; margin: 18px 0 14px; background: var(--border); }
/* no escuro o verde escuro some no fundo quase preto — usa o verde claro da marca */
:root[data-theme="dark"] .fee-tag.in { color: var(--verde); }

.ep-volrow { display: flex; align-items: center; gap: 12px; padding: 7px 0; }
.ep-volrow > span { width: 160px; flex-shrink: 0; font-weight: 500; font-size: 13px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ep-volrow > b { width: 110px; text-align: right; flex-shrink: 0; font-size: 13px; }
.ep-volbar { flex: 1; height: 12px; background: var(--bg2); border-radius: 99px; overflow: hidden; }
.ep-volbar i { display: block; height: 100%; border-radius: 99px; background: linear-gradient(90deg, #50ea5f, var(--verde-esc)); }

/* ============================================================
   MODO ESCURO — fundo preto→cinza (app + sidebar) e TODOS os
   cards com o mesmo gradiente do card destacado (.mh-card.hi).
   ============================================================ */
:root[data-theme="dark"] {
  --card-grad: linear-gradient(160deg, #151a1b 0%, #121516 62%, #0e1112 100%);
}
/* fundo do aplicativo (preto com gradiente para cinza, fixo ao rolar) */
:root[data-theme="dark"] body {
  background: linear-gradient(160deg, #15191b 0%, #0a0c0d 52%, #050607 100%);
  background-attachment: fixed;
}
/* menu lateral (preto → cinza) */
:root[data-theme="dark"] .sidebar {
  background: linear-gradient(185deg, #171b1d 0%, #0b0d0e 55%, #070809 100%);
  border-right-color: #23282a;
}
/* TODOS os cards iguais ao destacado */
:root[data-theme="dark"] .card,
:root[data-theme="dark"] .mh-card,
:root[data-theme="dark"] .mh-card.hi,
:root[data-theme="dark"] .stat,
:root[data-theme="dark"] .tile,
:root[data-theme="dark"] .link-card,
:root[data-theme="dark"] .svc-kpi,
:root[data-theme="dark"] .kpi-mini,
:root[data-theme="dark"] details.log,
:root[data-theme="dark"] .coex-visual,
:root[data-theme="dark"] .notif-panel {
  background: var(--card-grad);
  border-color: #2e3537;
}
/* cards de aviso mantêm o tom semântico (âmbar/vermelho) */
:root[data-theme="dark"] .card[style*="amber"],
:root[data-theme="dark"] .card.err { background: var(--amber-bg); }
:root[data-theme="dark"] .card.err { background: var(--red-bg); }

/* ---- Ajuste fino do dark: menu ativo disfarçado + widgets internos pretos/cinza ---- */
/* item ativo do menu lateral: sem o verde chapado — fundo sutil + acento verde */
:root[data-theme="dark"] .nav-item.active {
  /* color-mix tira a cor escolhida pelo admin e a dilui no fundo: o item ativo
     continua discreto no escuro, mas seguindo a MESMA cor do claro. */
  background: color-mix(in srgb, var(--menu-ativo) 12%, transparent);
  color: #eafdf4;
  box-shadow: inset 3px 0 0 0 var(--menu-ativo);
}
:root[data-theme="dark"] .nav-item.active svg { color: var(--menu-ativo); opacity: 1; }
:root[data-theme="dark"] .nav-item.active .badge { background: var(--menu-ativo); color: var(--menu-tinta); }
/* widgets internos (KPIs de Agendamentos etc.) mais escuros = insets recuados */
:root[data-theme="dark"] .svc-kpi {
  background: linear-gradient(150deg, #141819 0%, #0b0d0e 100%);
  border-color: #262c2d;
}
:root[data-theme="dark"] .svc-kpi:hover { border-color: var(--verde-esc); }

/* ---- Correções finas do dark ---- */
/* linhas de tabela: o #eef6ef (quase branco) vira linha sutil escura */
:root[data-theme="dark"] th,
:root[data-theme="dark"] td { border-bottom-color: rgba(255, 255, 255, .06); }
/* svc-ic dentro dos KPIs volta a ser só um ícone (sem barra/fundo/borda) */
:root[data-theme="dark"] .svc-kpi .svc-ic {
  background: none !important; border: 0 !important; width: auto; display: inline-flex; margin-bottom: 4px;
}
/* Carteira: o gradiente terminava em BRANCO e escondia o valor — agora escuro */
:root[data-theme="dark"] .wallet-bal {
  background: linear-gradient(150deg, #171c1e, #101314) !important;
  border-color: #2a3132;
}
:root[data-theme="dark"] .wallet-bal b { color: var(--verde-deep); }
/* selos/gradiente do card destacado seguem o --card-grad (já suavizado) */
:root[data-theme="dark"] .notif-ic.type-message { background: var(--card-grad) !important; }

/* ---- Alertas âmbar: amarelo forte e legível no modo escuro ---- */
:root[data-theme="dark"] .status-chip.warn,
:root[data-theme="dark"] .pill.PENDING,
:root[data-theme="dark"] .pill.running,
:root[data-theme="dark"] .pill.pending,
:root[data-theme="dark"] .pill.warn,
:root[data-theme="dark"] .warn-card,
:root[data-theme="dark"] .wm-warn,
:root[data-theme="dark"] .reach-pill.empty,
:root[data-theme="dark"] .conv-tag.warn,
:root[data-theme="dark"] .sess-bar.warn {
  color: #fcd34d !important;
}
:root[data-theme="dark"] .warn-card .ic,
:root[data-theme="dark"] .svc-kpi.warn .svc-ic { color: #fbbf24 !important; }
/* cards de aviso genéricos (Gateway/AppID não configurado): só o título em amarelo forte */
:root[data-theme="dark"] .card[style*="amber"] > b,
:root[data-theme="dark"] .card[style*="amber"] b:first-child { color: #fcd34d; }

/* ===================== Admin SaaS — gráficos & KPIs ===================== */
.kpi-strip { display: grid; grid-template-columns: repeat(auto-fit, minmax(158px, 1fr)); gap: 12px; margin-bottom: 16px; }
.kpi-mini { background: var(--card); border: 1px solid var(--border); border-radius: 14px; padding: 12px 14px; display: flex; flex-direction: column; gap: 1px; box-shadow: var(--shadow-xs); }
.kpi-mini > span { font-size: 11px; color: var(--muted); font-weight: 500; text-transform: uppercase; letter-spacing: .04em; }
.kpi-mini b { font-size: 21px; font-weight: 500; letter-spacing: -.03em; color: var(--text); line-height: 1.2; }
.kpi-mini em { font-size: 11px; color: var(--faint); font-style: normal; }
.kpi-mini.up b { color: var(--verde-esc); }
.kpi-mini.down b { color: var(--red); }

.bar-chart { display: flex; align-items: flex-end; gap: 7px; height: 190px; padding-top: 10px; }
.bar-chart.sm { height: 128px; }
.bar-col { flex: 1; min-width: 0; display: flex; flex-direction: column; align-items: center; gap: 6px; height: 100%; justify-content: flex-end; }
.bar-stack { width: 100%; max-width: 40px; height: 100%; display: flex; flex-direction: column; justify-content: flex-end; border-radius: 7px 7px 0 0; overflow: hidden; background: rgba(128, 138, 128, .10); }
.bar-seg { width: 100%; transition: height .45s var(--ease); }
.seg-first { background: linear-gradient(180deg, #50ea5f, var(--verde-esc)); }
.seg-renewal { background: linear-gradient(180deg, #67d3ee, #2c9fd6); }
.seg-topup { background: linear-gradient(180deg, #f6cc6a, #e79009); }
.seg-acct { background: linear-gradient(180deg, #a58cff, #6d54e0); }
.bar-x { font-size: 10.5px; color: var(--faint); font-weight: 500; }
.bar-col:hover .bar-stack { filter: brightness(1.14); }

.chart-legend { display: flex; gap: 12px; flex-wrap: wrap; }
.chart-legend span { display: inline-flex; align-items: center; gap: 5px; font-size: 11.5px; color: var(--muted); font-weight: 600; }
.chart-legend i { width: 10px; height: 10px; border-radius: 3px; }
.lg-first { background: var(--verde-esc); }
.lg-renewal { background: #2c9fd6; }
.lg-topup { background: #e79009; }

/* ===================== Pagamentos — editor do modelo de cobrança ===================== */
.ep-varchips { display: flex; flex-wrap: wrap; gap: 7px; margin-bottom: 9px; }
.ep-chip {
  display: inline-flex; align-items: center; gap: 6px; background: var(--brand-bg);
  border: 1px solid var(--brand-border); color: var(--brand-dark); border-radius: 10px;
  padding: 5px 10px; font: inherit; font-size: 12px; font-weight: 500; cursor: pointer;
  transition: filter .15s, border-color .15s;
}
.ep-chip em { font-style: normal; font-weight: 600; color: var(--muted); font-size: 11px; }
.ep-chip:hover { filter: brightness(1.08); border-color: var(--verde-esc); }
/* prévia estilo WhatsApp (fundo de conversa) */
.ep-msg-bubble {
  background: #e5ddd5; background-image: linear-gradient(135deg, #efe9e2, #e3dccf);
  border: 1px solid var(--border); border-radius: 14px; padding: 16px; margin-top: 6px;
  display: flex; justify-content: flex-end;
}
.ep-msg-preview {
  background: #dcf8c6; color: #0f1f15; border-radius: 12px 4px 12px 12px;
  padding: 10px 13px; font-size: 13.5px; line-height: 1.5; max-width: 480px;
  box-shadow: 0 1px 1px rgba(0, 0, 0, .12); white-space: normal; word-break: break-word;
}
.ep-msg-preview .muted { color: #5a6b5f; }

/* ============================================================
   CORREÇÕES DE LEGIBILIDADE — MODO ESCURO
   (auditoria de contraste WCAG: nada abaixo de 4.5:1 no texto)
   ============================================================ */

/* --- 1. PREVIEWS SÃO "ILHAS CLARAS" ---------------------------------
   Os mockups replicam UIs REAIS que são claras (WhatsApp e a página de
   checkout). Eles não podem herdar os tokens do tema escuro, senão o
   balão fica escuro e o texto — que é preto por definição — some.      */
:root[data-theme="dark"] .ph-device,
:root[data-theme="dark"] .epk-page,
:root[data-theme="dark"] .epk-browser {
  --card: #ffffff;
  --glass: rgba(255, 255, 255, .9);
  --border2: #e7eaf0;
  --border: #e7eaf0;
  --faint: #6b7488;
  --muted: #6b7488;
  --text: #1a2233;
  --text2: #33405c;
  --tinta: #1a2233;
  --bg2: #f1f3f8;
  color-scheme: light;
}

/* --- 2. RESTOS DO TEMA CLARO ---------------------------------------- */
/* chat (Conversas e Chat interno): o fundo continuava verde-menta claro
   com texto quase branco por cima = ilegível */
:root[data-theme="dark"] .chat,
:root[data-theme="dark"] .chat-scroll { background: #0d1110; }
:root[data-theme="dark"] .conv-item.active { background: var(--brand-bg); }
:root[data-theme="dark"] .kcol { background: var(--card); }
:root[data-theme="dark"] .sc-cell.out { background: #0c0f0e; }
/* saída de JSON (Configurações/Logs): usava var(--tinta), que no escuro
   é CLARA — resultava em texto claro sobre fundo claro (1.4:1) */
:root[data-theme="dark"] pre.out {
  background: #0c100f; color: #d0e1dc; border-color: var(--border2);
}

/* --- 3. CONTRASTE DE TEXTO ------------------------------------------ */
:root[data-theme="dark"] .tabs button { color: #95a4a0; }        /* aba inativa: 3.3 -> 4.9 */
/* :not(.today) preserva o branco sobre o verde do dia atual */
:root[data-theme="dark"] .sc-cell:not(.today) .sc-daynum { color: var(--text2); }
:root[data-theme="dark"] .kcol h3,
:root[data-theme="dark"] .kcol h3 span { color: var(--text); }
:root[data-theme="dark"] .conv-meta .prev { color: var(--text2); }
:root[data-theme="dark"] .team-grp { color: #95a4a0; }
/* iniciais dos avatares (fundo colorido gerado por contato) */
.avatar, .avatar.sm, span.avatar { color: var(--ink-on-verde); }
/* número dentro da barra do funil: reforça a sombra p/ ler no gradiente */
.fn3-count { text-shadow: 0 1px 3px rgba(0, 0, 0, .55); }

/* segmentados (períodos do dashboard, semana/dia da agenda, abas do consent) */
:root[data-theme="dark"] .seg button { color: #95a4a0; }
/* etiqueta de gatilho do Flow Builder */
:root[data-theme="dark"] .flow-badge { color: var(--verde); }
/* textos secundários do mockup do WhatsApp: mantém a cara do app real,
   só escurece o cinza o suficiente para leitura confortável */
.ph-device .wa-time, .ph-device .wa-ft { color: #667781; }
.ph-device .wa-daychip { color: #5f6b73; }
.ph-device .wa-top-info span { color: #5c6b73; }
/* dia atual na agenda: verde mais profundo p/ o branco ficar legível (2.5 -> 5.5) */
:root[data-theme="dark"] .sc-cell.today .sc-daynum { background: var(--verde-esc); color: var(--ink-on-verde); }
:root[data-theme="dark"] .bad-dot { color: #f87171; }

/* ============================================================
   RESPONSIVO — TABLET / MOBILE
   O topo era a causa da rolagem horizontal em TODAS as telas:
   .tb-right (status + sino + tema + avatar + Sair) não encolhia.
   ============================================================ */
@media (max-width: 900px) {
  .topbar { gap: 10px; padding: 0 14px; }
  /* A MARCA ENTRA E O NOME DA TELA SAI. Ver o comentário no index.html: com a
     gaveta fechada, esta é a única Koonfy visível no celular. */
  .tb-marca { display: block; }
  .topbar h2 { display: none; }
  .tb-right { gap: 7px; min-width: 0; }
  .tb-user #who { display: none; }              /* mantém só o avatar */
  .status-chip { padding: 6px 9px; font-size: 0; gap: 0; }   /* vira só o pontinho de status */
  .status-chip i { margin: 0; }
  .status-chip svg { display: none; }
}
@media (max-width: 620px) {
  .page { padding: 16px 14px 40px; }
  .page-head { margin-bottom: 16px; }
  .page-head h1 { font-size: 18px; }
  .page-head.row { flex-wrap: wrap; gap: 10px; }
  .topbar { padding: 0 10px; gap: 8px; }
  .tb-avatar { width: 29px; height: 29px; }
  /* "Sair" vira ícone-texto compacto */
  .tb-right > .btn.small { padding: 6px 9px; font-size: 11.5px; }
  /* tabelas rolam dentro do card em vez de esticar a página */
  .card table { display: block; width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch; }
  .card table thead, .card table tbody { display: table; width: max-content; min-width: 100%; }
  .card table tr { display: table-row; }
  /* grades de métricas empilham */
  .metric-hero, .dash-kpis, .dash-tiles { grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); }
  .row { flex-wrap: wrap; }
  .row > label, .row > .fld { min-width: 0; }
  .modal { max-width: calc(100vw - 24px); }
  .tabs { overflow-x: auto; scrollbar-width: none; }
  .tabs::-webkit-scrollbar { display: none; }
  /* A PÁGINA NÃO ROLA PARA O LADO. Num app de tela cheia isso nunca é
     recurso: é sempre um elemento que passou da largura, e o que a pessoa vê
     ao deslizar é o branco do fundo.

     `.page` PRECISA estar aqui, e não só a raiz: ele rola na vertical, e um
     elemento com `overflow-y: auto` ganha `overflow-x: auto` automaticamente.
     Foi por isso que o guarda só na raiz não pegou o arrasto do carrossel — o
     documento estava certinho e quem rolava era o `.page`.

     Isto é uma REDE, não o conserto: quando algo passa da largura, o certo é
     achar o elemento. `clip` e não `hidden` de propósito — `hidden` criaria
     um container de rolagem e quebraria `position: sticky` no topo das
     tabelas. O que precisa rolar de lado (tabela larga, faixa de abas) rola
     DENTRO do próprio quadro, e isto não encosta nelas. */
  html, body { overflow-x: clip; }
  .page { overflow-x: clip; }
  /* E o `main#view` junto, que é o único container por onde TODA tela passa.
     O guarda estava só no `.page`, e nem toda tela usa `.page` — a Conversas
     monta direto num `.inbox`. Cobrindo o pai, fica coberta também a tela que
     ainda não existe. */
  main#view { overflow-x: clip; }
}
/* nada pode estourar a largura da tela */
#app, .shell, main#view { max-width: 100vw; }
.login-wrap { max-width: 100%; overflow-x: clip; }
.shell, main#view { min-width: 0; }

/* ============================================================
   CHECKOUT BUILDER — editor dedicado (mesmo padrão do Flow Builder)
   topo fixo · seções à esquerda · edição no centro · prévia à direita
   ============================================================ */
.ck2 { display: flex; flex-direction: column; height: calc(100vh - var(--topbar-h)); height: calc(100dvh - var(--topbar-h)); }
.ck2-top {
  display: flex; align-items: center; gap: 12px; padding: 11px 20px; flex-shrink: 0;
  background: var(--glass); backdrop-filter: blur(8px); border-bottom: 1px solid var(--border2);
}
.ck2-title b { display: block; font-size: 16px; font-weight: 500; letter-spacing: -.02em; line-height: 1.15; }
.ck2-title span { font-size: 11.5px; color: var(--muted); font-weight: 600; }
.ck2-saved { font-size: 12px; font-weight: 500; color: var(--verde-esc); opacity: 0; transition: opacity .2s; }
.ck2-saved.on { opacity: 1; }
.ck2-body { flex: 1; display: flex; min-height: 0; }

/* coluna 1 — seções */
.ck2-nav {
  width: 226px; flex-shrink: 0; border-right: 1px solid var(--border2);
  background: var(--card); padding: 12px 10px 18px; overflow-y: auto;
}
.ck2-navgrp { font-size: 10px; font-weight: 500; text-transform: uppercase; letter-spacing: 1.4px; color: var(--faint); padding: 4px 8px 8px; }
.ck2-navitem {
  width: 100%; display: flex; align-items: center; gap: 11px; text-align: left;
  padding: 9px 11px; border-radius: 10px; border: 1px solid transparent; background: transparent;
  font: inherit; cursor: pointer; color: var(--text2); margin-bottom: 3px; transition: background .15s, color .15s;
}
.ck2-navitem:hover { background: var(--bg2); color: var(--text); }
.ck2-navitem.on { background: var(--brand-bg); border-color: var(--brand-border); color: var(--text); }
.ck2-navic { display: flex; color: var(--verde-esc); flex-shrink: 0; }
.ck2-navtxt { min-width: 0; }
.ck2-navtxt b { display: block; font-size: 13px; font-weight: 500; }
.ck2-navtxt small { display: block; font-size: 11px; color: var(--muted); margin-top: 1px; }

/* coluna 2 — edição */
.ck2-edit { flex: 1; min-width: 0; overflow-y: auto; padding: 26px 28px 40px; }
.ck2-sec { max-width: 560px; }
.ck2-sechead { margin-bottom: 20px; }
.ck2-sechead h2 { display: flex; align-items: center; gap: 9px; font-size: 19px; font-weight: 500; letter-spacing: -.02em; }
.ck2-sechead p { margin: 4px 0 0; color: var(--muted); font-size: 13px; }

/* coluna 3 — prévia */
.ck2-prev {
  width: 500px; flex-shrink: 0; border-left: 1px solid var(--border2); background: var(--bg2);
  display: flex; flex-direction: column; min-height: 0; padding: 12px 16px 14px;
}
.ck2-prevbar { display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-shrink: 0; margin-bottom: 10px; flex-wrap: wrap; }
.ck2-seg button { font-size: 11.5px; padding: 6px 11px; display: inline-flex; align-items: center; gap: 5px; }
.ck2-stage { flex: 1; min-height: 0; overflow-y: auto; display: flex; justify-content: center; }
.ck2-stage .epk-browser { width: 100%; align-self: flex-start; transition: max-width .28s var(--ease); }
/* alternância desktop/celular: estreita a moldura como um device real */
.ck2-stage.mobile .epk-browser { max-width: 300px; }
.ck2-stage.mobile .epk2-grid { grid-template-columns: 1fr; }
.ck2-stage.mobile .epk2-summary { order: -1; }
.ck2-prevnote { text-align: center; font-size: 11px; color: var(--faint); margin-top: 9px; flex-shrink: 0; }

@media (max-width: 1180px) { .ck2-prev { width: 400px; } }
@media (max-width: 1000px) {
  .ck2-body { flex-direction: column; overflow-y: auto; }
  .ck2-nav { width: 100%; display: flex; gap: 6px; overflow-x: auto; border-right: 0; border-bottom: 1px solid var(--border2); padding: 10px; }
  .ck2-navgrp { display: none; }
  .ck2-navitem { width: auto; flex-shrink: 0; margin: 0; }
  .ck2-navtxt small { display: none; }
  .ck2-prev { width: 100%; border-left: 0; border-top: 1px solid var(--border2); }
  .ck2-edit { overflow: visible; padding: 20px 16px 28px; }
}
/* miniatura do checkout: como o texto é reduzido, escurece os cinzas
   secundários para manter a leitura confortável dentro da prévia */
.epk2-stp, .epk2-sumhead, .epk2-note, .epk2-support { color: #5b6478; }
.epk2-stp i { background: #e2e6ee; color: #5b6478; }
.epk2-fld span { color: #6b7488; }
.epk2-msub, .epk2-qrside span, .epk2-row { color: #4a5468; }
.epk2-brand small { color: #5b6478; }

/* ============================================================
   CHECKOUT BUILDER v2 — formato Kiwify:
   canvas central com a página + painel direito Componentes/Configurações
   ============================================================ */
.ckb { display: flex; flex-direction: column; height: calc(100vh - var(--topbar-h)); height: calc(100dvh - var(--topbar-h)); }
.ckb-top {
  display: flex; align-items: center; gap: 12px; padding: 10px 18px; flex-shrink: 0; flex-wrap: wrap;
  background: var(--glass); backdrop-filter: blur(8px); border-bottom: 1px solid var(--border2);
}
.ckb-name b { display: block; font-size: 15.5px; font-weight: 500; letter-spacing: -.02em; line-height: 1.15; }
.ckb-name span { font-size: 11px; color: var(--muted); font-weight: 600; }
.ckb-devices { display: flex; gap: 3px; background: var(--bg2); padding: 4px; border-radius: 11px; }
.ckb-devices .icon-btn { border-radius: 8px; color: var(--muted); }
.ckb-devices .icon-btn.on { background: var(--card); color: var(--verde-esc); box-shadow: 0 1px 4px rgba(0, 0, 0, .12); }
.ckb-status { display: inline-flex; align-items: center; gap: 7px; font-size: 12.5px; font-weight: 500; color: var(--verde-esc); }
.ckb-status i { width: 8px; height: 8px; border-radius: 99px; background: var(--verde-esc); }
.ckb-body { flex: 1; display: flex; min-height: 0; }

/* canvas central (a página sendo montada) */
.ckb-stagewrap {
  flex: 1; min-width: 0; overflow-y: auto; background: var(--bg2);
  display: flex; flex-direction: column; align-items: center; gap: 12px; padding: 16px 22px 34px;
}
.ckb-stepseg { flex-shrink: 0; }
.ckb-stage { width: 100%; max-width: 880px; transition: max-width .28s var(--ease); }
.ckb-stage .epk-browser { width: 100%; }
.ckb-stage.mobile { max-width: 320px; }
.ckb-stage.mobile .epk2-grid { grid-template-columns: 1fr; }   /* form primeiro, resumo depois (ordem do DOM) */

/* painel direito */
.ckb-side {
  width: 306px; flex-shrink: 0; border-left: 1px solid var(--border2); background: var(--card);
  display: flex; flex-direction: column; min-height: 0;
}
.ckb-tabs { display: flex; border-bottom: 1px solid var(--border2); flex-shrink: 0; }
.ckb-tabs button {
  flex: 1; padding: 13px 8px; font: inherit; font-weight: 500; font-size: 13px; cursor: pointer;
  background: none; border: 0; border-bottom: 2px solid transparent; color: var(--muted); transition: color .15s;
}
.ckb-tabs button.on { color: var(--text); border-bottom-color: var(--verde); }
.ckb-panel { flex: 1; overflow-y: auto; padding: 14px; }
.ckb-grp { font-size: 10px; font-weight: 500; text-transform: uppercase; letter-spacing: 1.3px; color: var(--faint); margin: 2px 2px 10px; }
.ckb-comps { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.ckb-comp {
  border: 1px solid var(--border2); border-radius: 12px; background: var(--card);
  padding: 16px 8px 13px; display: flex; flex-direction: column; align-items: center; gap: 8px;
  font: inherit; color: var(--text2); cursor: pointer; transition: border-color .15s, color .15s, box-shadow .15s;
}
.ckb-comp:hover { border-color: var(--verde); color: var(--text); box-shadow: var(--shadow-sm); }
.ckb-comp .ic { color: var(--verde-esc); display: flex; }
.ckb-comp b { font-size: 12.5px; font-weight: 500; }
.ckb-back {
  display: inline-flex; align-items: center; gap: 6px; margin: 0 0 12px; padding: 0;
  background: none; border: 0; font: inherit; font-weight: 500; font-size: 12.5px;
  color: var(--verde-esc); cursor: pointer;
}
.ckb-sechead { margin-bottom: 14px; }
.ckb-sechead h2 { display: flex; align-items: center; gap: 8px; font-size: 15px; font-weight: 500; letter-spacing: -.01em; }
.ckb-sechead p { margin: 3px 0 0; color: var(--muted); font-size: 12px; }

@media (max-width: 980px) {
  .ckb-body { flex-direction: column; overflow-y: auto; }
  .ckb-stagewrap { overflow: visible; }
  .ckb-side { width: 100%; border-left: 0; border-top: 1px solid var(--border2); }
}

/* prévia: capa do banner no resumo (mesma posição da página real) */
.epk2-cover { width: 100%; height: 56px; object-fit: cover; display: block; border-bottom: 1px solid #e7eaf0; border-radius: 11px 11px 0 0; }
.epk2-summary { overflow: hidden; }
/* tipografia unificada (Inter Tight = mesma do Koonfy) */
.epk-page { font-family: 'Inter Tight', -apple-system, 'Segoe UI', Roboto, sans-serif; }

/* Checkout Builder = página FOCADA: some a sidebar e o topo do app */
#app.builder-mode .sidebar, #app.builder-mode .topbar { display: none; }
#app.builder-mode .ckb { height: 100vh; height: 100dvh; }
.ckb-brand { gap: 9px; }
.ckb-brand .brand-mark { width: 34px; height: 34px; border-radius: 9px; overflow: hidden; }
.ckb-brand .brand-mark img { width: 100%; height: 100%; object-fit: cover; }
.ckb-brand .brand-name { font-size: 17px; letter-spacing: -.03em; }

/* ============================================================
   TRACKING — cards de métricas, conexões e funil
   ============================================================ */
.trk-cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(155px, 1fr)); gap: 10px; margin-top: 6px; }
.trk-card { background: var(--bg2); border: 1px solid var(--border); border-radius: 13px; padding: 12px 14px; }
.trk-card span { display: block; font-size: 11px; font-weight: 500; text-transform: uppercase; letter-spacing: .05em; color: var(--faint); }
.trk-card b { display: block; font-size: 18px; font-weight: 500; letter-spacing: -.02em; margin-top: 3px; font-variant-numeric: tabular-nums; }
.trk-card small { display: block; font-size: 11px; color: var(--muted); margin-top: 2px; }
:root[data-theme="dark"] .trk-card { background: rgba(255, 255, 255, .03); }

.trk-conns { display: grid; grid-template-columns: repeat(auto-fill, minmax(340px, 1fr)); gap: 14px; }
.trk-conn { margin-bottom: 0; }
.trk-connstats { display: flex; flex-wrap: wrap; gap: 6px 14px; margin-top: 10px; font-size: 11.5px; font-weight: 600; color: var(--muted); }
.trk-connstats .ok { color: var(--verde-esc); }
.trk-connstats .err2 { color: #f87171; }

.trk-funnel { margin-top: 8px; }
.trk-frow { display: grid; grid-template-columns: 110px 1fr 70px 70px; align-items: center; gap: 12px; padding: 6px 0; }
.trk-fname { font-size: 13px; font-weight: 500; }
.trk-fbar { height: 14px; background: var(--bg2); border-radius: 99px; overflow: hidden; }
.trk-fbar i { display: block; height: 100%; border-radius: 99px; background: linear-gradient(90deg, #50ea5f, var(--verde-esc)); }
.trk-frow > b { text-align: right; font-variant-numeric: tabular-nums; }
.trk-frate { font-size: 12px; font-weight: 500; color: var(--muted); }
.pill-ok { font-size: 11px; font-weight: 500; padding: 3px 9px; border-radius: 99px; background: var(--bgt, #ecfdf5); color: var(--verde-esc); }
:root[data-theme="dark"] .pill-ok { background: rgba(46, 211, 120, .12); }
@media (max-width: 620px) { .trk-frow { grid-template-columns: 84px 1fr 54px 54px; gap: 8px; } }

/* ===== Checkout Builder: blocos, ordem arrastável e uploads por dispositivo ===== */
.ckb-devgrp { display: flex; align-items: center; gap: 7px; font-size: 10.5px; font-weight: 500; text-transform: uppercase; letter-spacing: 1.1px; color: var(--faint); margin-top: 4px; }
.ckb-devgrp svg { color: var(--verde-esc); }

/* lista de ordem (drag & drop) */
.ckb-order { display: flex; flex-direction: column; gap: 6px; }
.ckb-orow {
  display: flex; align-items: center; gap: 9px; padding: 9px 10px; cursor: grab;
  border: 1px solid var(--border2); border-radius: 10px; background: var(--card);
  transition: border-color .15s, box-shadow .15s, opacity .15s;
}
.ckb-orow:hover { border-color: var(--verde); }
.ckb-orow.dragging { opacity: .45; cursor: grabbing; }
.ckb-orow.drop-before { box-shadow: 0 -3px 0 -1px var(--verde); }
.ckb-orow.drop-after { box-shadow: 0 3px 0 -1px var(--verde); }
.ckb-grip { color: var(--faint); display: flex; flex: none; }
.ckb-oic { color: var(--verde-esc); display: flex; flex: none; }
.ckb-otxt { flex: 1; min-width: 0; }
.ckb-otxt b { display: block; font-size: 12.5px; font-weight: 500; }
.ckb-otxt small { display: block; font-size: 10.5px; color: var(--muted); }
.ckb-odot { width: 8px; height: 8px; border-radius: 99px; background: var(--border2); flex: none; }
.ckb-odot.on { background: var(--verde-esc); }

/* editores de lista (vantagens / FAQ) */
.epk-item { display: flex; gap: 7px; margin-bottom: 7px; }
.epk-item input { flex: 1; min-width: 0; }
.epk-faqrow { border: 1px solid var(--border2); border-radius: 10px; padding: 9px; margin-bottom: 8px; }
.epk-faqrow textarea { margin-top: 7px; width: 100%; }

/* blocos na prévia */
/* A PRÉVIA REPETE A CAIXA DO CHECKOUT: mesma proporção (3:1 no computador,
   16:9 no celular) e, no celular, a mesma folga de 10% de cada lado. Um
   `max-height` aqui mostraria um recorte que a página real não faz, e o
   lojista só descobriria depois de publicar. */
/* A MOLDURA DA PRÉVIA TEM RECUO PRÓPRIO (12px na `.epk-page`), e a tela do
   cliente não tem. Medindo o banner dentro dele, a folga saía proporcionalmente
   maior do que a de verdade: 74% da largura na prévia contra 80% no checkout.
   O banner sai do recuo com margem negativa e refaz a folga em PORCENTAGEM,
   que é como o checkout calcula — aí a relação entre banner e tela é a mesma
   nos dois lugares. Os números: 2,4% no computador (24px de 1000) e 10% no
   celular, os mesmos do pay.html. */
.epk2-bannerwrap { margin: 0 -12px 9px; padding: 0 2.4%; }
.epk2-bannerwrap.mob { padding: 0 10%; }
.epk2-headbanner { width: 100%; display: block; aspect-ratio: 3 / 1; object-fit: cover; border-radius: 9px; }
.epk2-bannerwrap.mob .epk2-headbanner { aspect-ratio: 16 / 9; }
.epk2-col { display: flex; flex-direction: column; gap: 8px; min-width: 0; }
.epk2-blk { background: #fff; border: 1px solid #e7eaf0; border-radius: 10px; padding: 9px 11px; font-size: 9px; color: #4a5468; line-height: 1.5; }
.epk2-blkt { display: block; font-size: 10px; font-weight: 500; color: #1a2233; margin-bottom: 6px; }
/* `--tmr` cai em `--epkc` (a cor de destaque do checkout) quando o lojista não
   escolheu cor para o cronômetro — o mesmo encadeamento do checkout público,
   para a prévia não mentir. */
.epk2-timer {
  display: flex; align-items: center; justify-content: center; gap: 7px; font-weight: 600; color: #33405c;
  background: color-mix(in srgb, var(--w, var(--epkc, #2ed378)) 8%, #fff); border-color: color-mix(in srgb, var(--w, var(--epkc, #2ed378)) 25%, #fff); }
.epk2-timer svg { color: var(--w, var(--epkc, #2ed378)); flex: none; }
.epk2-clock { display: flex; align-items: flex-start; gap: 2px; }
.epk2-clock i { display: flex; flex-direction: column; align-items: center; gap: 1px; font-style: normal; }
.epk2-clock i b { background: var(--w, var(--epkc, #2ed378)); color: #fff; font-weight: 600; padding: 2px 5px; border-radius: 4px; font-size: 9px; min-width: 20px; text-align: center; }
.epk2-clock i em { font-style: normal; font-size: 6px; letter-spacing: .05em; color: #8b93a3; }
.epk2-clock s { text-decoration: none; color: var(--w, var(--epkc, #2ed378)); font-weight: 600; font-size: 9px; padding-top: 2px; }

/* O swatch "usar a cor de destaque": xadrez claro para dizer "nenhuma cor
   própria", com o ícone por cima. Sem ele a única forma de desfazer uma cor
   escolhida seria acertar o hexadecimal da marca no olho. */
.epk-swatch-auto {
  display: inline-flex; align-items: center; justify-content: center; color: #6b7280;
  background: repeating-conic-gradient(#e9edf2 0% 25%, #fff 0% 50%) 50% / 9px 9px;
}
/* Âmbar é o padrão do AVISO, e não a cor de destaque — o mesmo encadeamento de
   `pay.html`. Por isso o fallback aqui é a cor antiga do bloco. */
.epk2-notice { display: flex; gap: 6px; align-items: flex-start;
  color: var(--w, #8a6412);
  background: color-mix(in srgb, var(--w, #d9a520) 11%, #fff);
  border-color: color-mix(in srgb, var(--w, #d9a520) 32%, #fff); }
.epk2-notice svg { color: var(--w, #b8860b); flex: none; }
.epk2-bitem { display: flex; gap: 6px; align-items: flex-start; margin-bottom: 4px; }
.epk2-bitem svg { color: var(--w, var(--epkc, #2ed378)); flex: none; margin-top: 1px; }
.epk2-testi { display: flex; gap: 8px; }
.epk2-testi .av { width: 24px; height: 24px; border-radius: 50%; flex: none; display: flex; align-items: center; justify-content: center;
  background: color-mix(in srgb, var(--w, var(--epkc, #2ed378)) 13%, #fff); color: var(--w, var(--epkc, #2ed378)); font-weight: 500; font-size: 11px; }
/* Estrela dourada é convenção; só sai do dourado se o lojista mandar. */
.epk2-testi .st { color: var(--w, #f5a524); font-size: 8px; letter-spacing: .5px; }
.epk2-testi p { font-style: italic; margin: 2px 0 3px; }
.epk2-testi b { font-size: 9px; }
.epk2-guar { display: flex; gap: 9px; align-items: center; }
.epk2-guar svg { color: var(--w, var(--epkc, #2ed378)); flex: none; }
.epk2-guar b { display: block; font-size: 10px; color: #1a2233; }
.epk2-guar span { display: block; }
.epk2-faq { display: flex; justify-content: space-between; gap: 8px; padding: 5px 0; border-bottom: 1px solid #eef1f6; font-weight: 600; color: #33405c; }
.epk2-faq:last-child { border-bottom: 0; }
.epk2-faq em { color: var(--w, var(--epkc, #2ed378)); font-style: normal; font-weight: 500; }
.epk2-badges { display: flex; gap: 6px; justify-content: center; margin-top: 9px; flex-wrap: wrap; }
.epk2-badges span { display: inline-flex; align-items: center; gap: 4px; font-size: 8px; font-weight: 600; color: #55607a;
  background: #fff; border: 1px solid #e7eaf0; padding: 4px 7px; border-radius: 6px; }
.epk2-badges svg { color: var(--epkc, #2ed378); }
/* nome editável do checkout no header do Checkout Builder */
.ckb-cname {
  display: block; border: 1px solid transparent; background: transparent; font: inherit;
  font-size: 11.5px; font-weight: 600; color: var(--muted); padding: 1px 5px;
  border-radius: 6px; width: 150px; margin-top: 1px;
}
.ckb-cname:hover { border-color: var(--border2); }
.ckb-cname:focus { border-color: var(--verde); color: var(--text); outline: none; background: var(--card); }

/* ===== CANVAS ARRASTA-E-SOLTA do Checkout Builder ===== */
/* cada bloco da prévia é um alvo posicionável */
.epk2-drop { position: relative; border-radius: 10px; cursor: grab; transition: box-shadow .12s, opacity .12s; }
.epk2-drop:hover { box-shadow: 0 0 0 1.5px color-mix(in srgb, var(--epkc, #2ed378) 55%, transparent); }
.epk2-drop.dragging { opacity: .4; cursor: grabbing; }
.epk2-drop.fixed { cursor: grab; }
/* linha indicando onde o widget vai cair */
.epk2-drop.over-before::before, .epk2-drop.over-after::after {
  content: ''; position: absolute; left: 0; right: 0; height: 3px; border-radius: 3px;
  background: var(--epkc, #2ed378); box-shadow: 0 0 0 3px color-mix(in srgb, var(--epkc, #2ed378) 25%, transparent);
}
.epk2-drop.over-before::before { top: -5px; }
.epk2-drop.over-after::after { bottom: -5px; }
/* alça (aparece no hover) */
.epk2-handle {
  position: absolute; top: 4px; left: -3px; z-index: 2; display: flex; opacity: 0;
  background: var(--epkc, #2ed378); color: #fff; border-radius: 5px; padding: 2px 3px;
  transition: opacity .12s; pointer-events: none;
}
.epk2-drop:hover .epk2-handle { opacity: 1; }
/* widget desligado: "fantasma" mostrando onde ele ficaria */
.epk2-drop.off { opacity: .85; }
/* BOTÃO DE TIRAR DO CHECKOUT. Aparece ao passar o mouse pelo bloco: sempre
   visível viraria um "x" em cada cartão, e o canvas é para olhar o checkout,
   não os controles. No toque não há hover, então ali ele fica sempre à vista. */
.epk2-drop { position: relative; }
.epk2-x {
  position: absolute; top: 6px; right: 6px; z-index: 3;
  width: 22px; height: 22px; padding: 0; border-radius: 7px; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  border: 1px solid #f1c9c9; background: #fff; color: #d64545;
  opacity: 0; transition: opacity .13s, background .13s;
}
.epk2-drop:hover > .epk2-x, .epk2-timerbar:hover > .epk2-x { opacity: 1; }
.epk2-x:hover { background: #fdeaea; }
@media (hover: none) { .epk2-x { opacity: .85; } }

/* Canvas vazio: a faixa diz o que fazer e é alvo de solta, para quem arrasta
   não precisar acertar a lista. */
.epk2-solta {
  display: flex; align-items: center; justify-content: center; gap: 6px;
  padding: 18px 12px; border-radius: 10px; margin-top: 8px;
  border: 1.5px dashed #cdd5e0; color: #7b8698; font-size: 9.5px; font-weight: 600;
}
#epk-canvas.dropping .epk2-solta { border-color: var(--epkc, #2ed378); color: var(--epkc, #2ed378); }

/* A faixa do cronômetro na prévia — o mesmo lugar que ela ocupa no checkout. */
.epk2-timerbar {
  position: relative; display: flex; align-items: center; justify-content: center; gap: 6px;
  padding: 7px 10px; font-size: 9px; font-weight: 600; color: #33405c;
  background: color-mix(in srgb, var(--w, var(--epkc, #2ed378)) 13%, #fff);
  border-bottom: 1px solid color-mix(in srgb, var(--w, var(--epkc, #2ed378)) 32%, #fff);
}
.epk2-timerbar svg { color: var(--w, var(--epkc, #2ed378)); flex: none; }
.epk2-timerbar > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.epk2-timerbar b {
  background: var(--w, var(--epkc, #2ed378)); color: #fff; font-weight: 600;
  padding: 2px 5px; border-radius: 4px; font-size: 9px; flex: none;
}
.epk2-timerbar s { text-decoration: none; color: var(--w, var(--epkc, #2ed378)); font-weight: 600; flex: none; }

/* canvas em modo "recebendo" */
.epk2-col.dropping { outline: 2px dashed color-mix(in srgb, var(--epkc, #2ed378) 45%, transparent); outline-offset: 4px; border-radius: 12px; }
/* item da paleta arrastável */
.ckb-comp.drag { cursor: grab; }
.ckb-comp.drag:active { cursor: grabbing; }

/* ============================================================
   MOBILE — menu em gaveta e áreas de toque confortáveis
   ============================================================ */
.nav-toggle { display: none; }
.nav-backdrop { display: none; }

@media (max-width: 820px) {
  /* a sidebar sai do fluxo: o conteúdo passa a usar a LARGURA INTEIRA */
  .sidebar {
    position: fixed; top: 0; left: 0; bottom: 0; z-index: 210; width: 252px;
    transform: translateX(-100%); transition: transform .26s var(--ease);
    box-shadow: 0 0 40px rgba(0, 0, 0, .28); overflow-y: auto;
  }
  #app.nav-open .sidebar { transform: none; }
  .nav-backdrop {
    display: block; position: fixed; inset: 0; z-index: 200; background: rgba(6, 10, 8, .5);
    opacity: 0; pointer-events: none; transition: opacity .26s;
    -webkit-backdrop-filter: blur(2px); backdrop-filter: blur(2px);
  }
  #app.nav-open .nav-backdrop { opacity: 1; pointer-events: auto; }
  /* na gaveta os rótulos voltam a aparecer (não é mais um trilho de ícones) */
  .sidebar .nav-label, .sidebar .nav-item span, .sidebar .brand-text { display: block; }
  .sidebar .nav-item { justify-content: flex-start; padding: 11px 14px; }

  .nav-toggle {
    display: inline-flex; align-items: center; justify-content: center;
    width: 40px; height: 40px; flex: none; border-radius: 11px; cursor: pointer;
    border: 1px solid var(--border2); background: var(--card); color: var(--text2);
  }
  .nav-toggle:active { background: var(--bg2); }

  /* ---- áreas de toque: mínimo confortável de 40px ---- */
  .btn { min-height: 42px; }
  .btn.small { min-height: 38px; padding: 8px 13px; }
  .icon-btn { min-width: 38px; min-height: 38px; }
  .icon-btn.tiny { min-width: 32px; min-height: 32px; }
  /* O dropdown do app acompanha o corpo dos campos: no celular o input sobe
     para 16px (evita o zoom do iOS) e, sem isto, um select ao lado de um input
     no mesmo formulário ficava com letra visivelmente menor. */
  .ecsel-btn { min-height: 42px; font-size: 16px; }
  /* Checkbox e radio ficam DE FORA: os .chk são interruptores desenhados em
     40x23, e um min-height de campo de formulário os esmagava num oval de
     40x42. O alvo de toque deles é a label inteira, que já tem 42px. */
  input:not([type="checkbox"]):not([type="radio"]), select, textarea {
    min-height: 42px; font-size: 16px;   /* 16px evita zoom no iOS */
  }
  /* Sem o min-height do input a linha encolhia para 26px. É a LABEL que
     precisa do alvo confortável, não o desenho do interruptor. */
  label.chk { min-height: 40px; }
  /* mesmo desenho do .toggle, para os dois interruptores do app combinarem */
  label.chk input[type="checkbox"] { width: 46px; height: 26px; }
  label.chk input[type="checkbox"]::after { width: 20px; height: 20px; top: 3px; left: 3px; }
  label.chk input[type="checkbox"]:checked::after { transform: translateX(20px); }
  textarea { min-height: 76px; }
  /* O interruptor não precisa CRESCER para ser fácil de acertar. A 51x31 ele
     virava um borrão ao lado de um texto de 13px; aqui o desenho fica discreto
     (46x26) e quem ganha os 44px de alvo é um ::after invisível por cima. */
  .toggle { width: 46px; height: 26px; }
  .toggle span { width: 20px; height: 20px; top: 3px; left: 3px; }
  .toggle.on span { transform: translateX(20px); }
  .toggle::after { content: ''; position: absolute; inset: -9px -4px; }
  .tabs button, .seg button { min-height: 38px; }
  .nav-item { min-height: 44px; }
  /* linhas de tabela com alvo maior */
  td .btn.small, td .icon-btn { min-height: 34px; min-width: 34px; }

  /* ---- a CONVERSA é o conteúdo; os atalhos são acessório ----
     Medido em 375x812: das 750px do .chat, as mensagens ficavam com 125px (17%)
     porque o cabeçalho de ações (83px) e a barra do composer (87px) quebravam
     em duas/três linhas, e o aviso de janela ocupava 145px. Sem rótulo os dois
     grupos viram uma fileira só de ícones, e tudo que sobra vai para o
     .chat-scroll, que é flex:1. */
  .chat-head-actions .blbl, .composer .tools .blbl { display: none; }
  /* .btn é flex:1 por padrão; sem rótulo os quatro viravam caixas largas e
     vazias ocupando a linha inteira. Só-ícone = tamanho do ícone. */
  .chat-head-actions .btn.small, .composer .tools .btn.small { padding: 8px 11px; flex: none; }
  .sess-notice .btn.small { flex: none; }
  /* uma fileira só: se não couber, rola de lado em vez de empilhar */
  .chat-head-actions, .composer .tools {
    flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; gap: 6px;
  }
  .chat-head-actions::-webkit-scrollbar, .composer .tools::-webkit-scrollbar { display: none; }
  .chat-head { padding: 8px 12px; gap: 9px; }
  .chat-head-actions .assign-chip { flex-shrink: 0; }
  .composer { padding: 9px 12px 11px; gap: 7px; }
  /* o balão pode usar a largura: a 62% um código Pix virava uma coluna de 5 linhas */
  .chat-scroll { padding: 12px 12px; }
  .msg { max-width: 80%; }
  /* No celular o aviso fica com o título e o botão de saída; a explicação
     inteira (4 linhas) come mais tela do que a conversa e se repete a cada
     abertura. No desktop continua completa. */
  .sess-notice {
    padding: 8px 10px; gap: 8px; margin-bottom: 7px; font-size: 12px; line-height: 1.3;
  }
  .sess-notice .sn-body { display: none; }
  .sess-notice > .ic { display: none; }   /* o título já diz o que é */
  /* O botão vinha ocupando a faixa inteira (330px) só porque sobrava linha.
     `max-content` o deixa do tamanho do próprio rótulo. */
  .sess-notice .btn.small {
    flex: none; width: max-content; min-height: 32px; padding: 6px 11px; font-size: 11.5px;
  }
  .composer select, .composer .ecsel-btn { max-width: 150px; }
  /* A caixa de escrever nasce com UMA linha e cresce só se a mensagem crescer.
     A regra geral de textarea no celular é 76px (bom para um formulário, caro
     aqui: o placeholder ocupava duas linhas antes mesmo de digitar). */
  /* `height` e não só `min-height`: sem o atributo rows o textarea nasce com
     duas linhas (71px) e a altura intrínseca ganha do mínimo. */
  .composer textarea { height: 42px; min-height: 42px; max-height: 104px; padding: 10px 14px; border-radius: 12px; }
  .composer .send-btn { min-height: 42px; width: 42px; padding: 0; border-radius: 12px; }
  .composer .line { gap: 8px; }

  /* Título de card com selo ao lado: o `flex:1` inline do h2 dá basis 0, então
     ele encolhia até quebrar em três linhas em vez de mandar o selo para
     baixo. Com um piso de 55% o selo grande desce e o pequeno continua ao
     lado. */
  .row > h2 { min-width: 55%; }
  /* Quando o selo é filho do próprio h2 (e não irmão), o título quebrava em
     duas linhas para caber ao lado dele. Deixando o h2 quebrar, o selo desce. */
  .card > h2 { flex-wrap: wrap; }
}

/* telas bem estreitas: respiro e empilhamento extra */
@media (max-width: 480px) {
  /* Os botões do cabeçalho dividem UMA faixa em vez de virarem dois blocos de
     75px empilhados. Com três ou mais eles quebram para a linha de baixo
     sozinhos, então continua legível quando a tela tem muitas ações. */
  /* Continua em linha e quebrando: o título leva a primeira (min-width:100%,
     porque o `style="flex:1"` inline dele venceria um flex-basis daqui) e os
     botões dividem a seguinte. Em coluna, um flex-basis viraria ALTURA. */
  .page-head.row { flex-direction: row; flex-wrap: wrap; align-items: center; gap: 8px; }
  /* `> div` e não `> div:first-child`: em toda tela que tem "Voltar" o
     primeiro filho é o botão, o seletor não casava, e o título dividia a
     linha com ele — uma palavra por linha, por cima do botão. A div de
     título é a única div direta destes cabeçalhos. */
  .page-head.row > div { min-width: 100%; }
  .page-head.row > .btn, .page-head.row > .btn.primary { flex: 1 1 140px; width: auto; min-width: 0; }
  /* A URL na linha dela. Com os botões ao lado sobravam 110px para o
     endereço e aparecia "http:// 12" — um link que não dá para conferir é um
     link que ninguém copia com confiança. */
  .copy-box { flex-wrap: wrap; }
  .copy-box code { flex: 1 0 100%; overflow: hidden; text-overflow: ellipsis; }
  .modal { padding: 18px 16px; }
  .metric-hero { grid-template-columns: 1fr 1fr; }
  .dash-kpis { grid-template-columns: 1fr 1fr; }

  /* ---- os atalhos são atalhos, não a tela ----
     A 150px de coluna cabiam dois por linha: três atalhos viravam duas
     fileiras de 104px (219px no total) antes de qualquer número aparecer.
     Numa fileira de três, com ícone e respiro menores, são 76px. */
  .dash-tiles { grid-template-columns: repeat(3, 1fr); gap: 8px; margin-bottom: 12px; }
  .tile { padding: 10px 4px 9px; gap: 5px; border-radius: 13px; }
  .tile-ic { width: 32px; height: 32px; border-radius: 10px; }
  .tile-ic svg { width: 16px; height: 16px; }
  .tile b { font-size: 10.5px; line-height: 1.15; text-align: center; }

  /* O número a 28px empurrava "QUANTIDADE DE VENDAS" para fora do cartão. */
  .stat { padding: 13px 14px; }
  .stat .num { font-size: 21px; padding-right: 30px; }
  .stat .lbl { padding-right: 30px; }
  .stat-ico { top: 11px; right: 11px; width: 28px; height: 28px; border-radius: 10px; }
  .stat .lbl { font-size: 10px; letter-spacing: .04em; padding-right: 32px; }
  .row > label { flex: 1 1 100% !important; }
  .ckb-comps { grid-template-columns: 1fr 1fr; }
}

/* IA ligada na conversa: o botão fica verde para dizer, de relance, quem está
   respondendo — a pessoa ou o agente. */
/* INTERRUPTOR DA IA no cabeçalho da conversa.
   Era um botão pequeno que só mudava de rótulo; no meio do atendimento é o
   ESTADO que precisa ser lido de relance, não o texto. Vira um switch com
   trilho e bolinha, verde quando a IA está respondendo. */
.ia-switch {
  display: inline-flex; align-items: center; gap: 7px; flex: none;
  padding: 5.5px 10px; border-radius: 999px; cursor: pointer;
  border: 1px solid var(--border); background: var(--card); color: var(--muted);
  font-size: 12px; font-weight: 500; text-decoration: none;
  transition: background .18s, border-color .18s, color .18s;
}
.ia-switch:hover { border-color: var(--border2); }
.ia-switch.on { background: var(--brand-bg); border-color: var(--brand-border); color: var(--verde-deep); }
.ia-switch.off { opacity: .75; }
.ia-track {
  width: 30px; height: 17px; border-radius: 999px; flex: none; position: relative;
  background: var(--border2); transition: background .18s;
}
.ia-switch.on .ia-track { background: var(--verde-esc); }
.ia-knob {
  position: absolute; top: 2px; left: 2px; width: 13px; height: 13px; border-radius: 50%;
  background: #fff; box-shadow: 0 1px 3px rgba(0, 0, 0, .28); transition: transform .18s var(--ease);
}
.ia-switch.on .ia-knob { transform: translateX(13px); }
.ia-switch.off .ia-track { display: none; }
.ia-canais { display: grid; gap: 10px; }
.ia-canais .chk span, .mod-lista .chk span { display: flex; flex-direction: column; gap: 2px; }
.mod-lista .chk { align-items: flex-start; }
.mod-lista .chk em { font-style: normal; font-size: 11.5px; color: var(--muted); }
.ia-canais .chk em { font-style: normal; font-size: 11.5px; color: var(--muted); }

/* ---- Cadastro em etapas ---- */
.reg-trilha { display: flex; gap: 6px; margin: 0 0 18px; }
.reg-trilha span {
  flex: 1; display: flex; align-items: center; gap: 7px; min-width: 0;
  font-size: 11.5px; font-weight: 500; color: var(--faint);
  padding-top: 9px; border-top: 2.5px solid var(--border);
  transition: color .2s, border-color .2s;
}
.reg-trilha span i {
  font-style: normal; width: 18px; height: 18px; border-radius: 50%; flex: none;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--bg2); color: var(--faint); font-size: 10px; font-weight: 500;
}
.reg-trilha span.agora { color: var(--text); border-top-color: var(--verde-esc); }
.reg-trilha span.agora i { background: var(--verde-esc); color: #fff; }
.reg-trilha span.feito { color: var(--verde-deep); border-top-color: var(--verde-esc); }
.reg-trilha span.feito i { background: var(--brand-bg); color: var(--verde-deep); }
.reg-botoes { display: flex; gap: 10px; align-items: stretch; }
.reg-botoes .btn.block { flex: 1; }
/* O "pular" é uma saída legítima, não um erro: discreto, mas alcançável. */
#reg-pular { margin-top: 10px; }

/* Gráficos do Tracking: um por linha em telas estreitas, dois a dois quando há
   espaço. minmax(0,...) porque um SVG com width:100% não encolhe abaixo do
   conteúdo sem isso, e a coluna estouraria a grade. */
.trk-graficos { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(320px, 100%), 1fr)); gap: 22px; }
.trk-graficos > div { min-width: 0; }
.trk-graficos h3 {
  font-size: 13px; font-weight: 500; color: var(--text2); margin: 0 0 8px;
  letter-spacing: -.01em;
}
.trk-leg { display: flex; flex-wrap: wrap; gap: 14px; margin-top: 6px; }
.trk-leg span { display: inline-flex; align-items: center; gap: 6px; font-size: 11.5px; font-weight: 600; color: var(--muted); }
.trk-leg i { width: 10px; height: 10px; border-radius: 3px; flex: none; }

/* Selo de como a conexão de tracking entrega o evento */
.trk-mode {
  display: inline-block; margin-left: 7px; padding: 2px 8px; border-radius: 99px;
  background: var(--bg2); border: 1px solid var(--border);
  font-size: 10px; font-weight: 500; letter-spacing: .04em; text-transform: uppercase;
  color: var(--muted); vertical-align: middle;
}
.trk-mode.srv { background: var(--brand-bg); border-color: var(--brand-border); color: var(--verde-deep); }
:root[data-theme="dark"] .trk-mode.srv { color: var(--verde); }

/* Validade do token do Meta Ads (renovação a cada 60 dias) */
.meta-token { margin-top: 14px; padding: 14px 16px; border-radius: 14px; border: 1px solid var(--border); background: var(--bg2); }
.meta-token.ok   { border-color: var(--brand-border); background: var(--brand-bg); }
.meta-token.warn { border-color: var(--amber-border); background: var(--amber-bg); }
.meta-token.crit { border-color: var(--red-border); background: var(--red-bg); }
.mt-head { display: flex; align-items: center; gap: 8px; font-size: 13.5px; font-weight: 500; letter-spacing: -.01em; color: var(--text); }
.meta-token.ok   .mt-head { color: var(--verde-deep); }
.meta-token.warn .mt-head { color: #b26205; }
.meta-token.crit .mt-head { color: var(--red); }
:root[data-theme="dark"] .meta-token.ok .mt-head { color: var(--verde); }
.mt-bar { height: 6px; margin: 10px 0 9px; border-radius: 99px; background: color-mix(in srgb, var(--text) 12%, transparent); overflow: hidden; }
.mt-bar i { display: block; height: 100%; border-radius: 99px; transition: width .4s var(--ease); }
.meta-token.ok   .mt-bar i { background: var(--verde-esc); }
.meta-token.warn .mt-bar i { background: var(--amber); }
.meta-token.crit .mt-bar i { background: var(--red); }
.mt-txt { margin: 0; font-size: 12.5px; font-weight: 500; line-height: 1.5; color: var(--text2); }

/* ===========================================================================
   APP NATIVO (iOS / Android) — só entra em vigor dentro do app das lojas.
   O <html> recebe .ec-native (e .ec-ios / .ec-android) pelo native.js, então
   nada aqui afeta o painel no navegador.
   =========================================================================== */

/* Notch, ilha dinâmica e barra de gestos: o conteúdo tem que começar abaixo
   do recorte e terminar acima da barra inferior. viewport-fit=cover já está
   no <meta>, o que habilita as variáveis env(). */
.ec-native .topbar {
  padding-top: calc(env(safe-area-inset-top, 0px) + 8px);
}
.ec-native .sidebar {
  padding-top: calc(env(safe-area-inset-top, 0px) + 14px);
  padding-bottom: env(safe-area-inset-bottom, 0px);
}
.ec-native main#view {
  padding-bottom: env(safe-area-inset-bottom, 0px);
}

/* Barra de digitação: sobe junto com o teclado. --ec-keyboard é atualizado
   pelo native.js nos eventos keyboardWillShow/Hide. */
.ec-native .composer {
  padding-bottom: calc(14px + env(safe-area-inset-bottom, 0px));
}
.ec-native.kb-open .composer {
  padding-bottom: 14px;
  transform: translateY(calc(-1 * var(--ec-keyboard, 0px)));
  transition: transform .18s var(--ease, ease);
}

/* A tela de login também respeita o recorte. */
.ec-native .login-wrap {
  padding-top: calc(env(safe-area-inset-top, 0px) + 18px);
  padding-bottom: calc(env(safe-area-inset-bottom, 0px) + 18px);
}

/* Seleção de texto por toque longo e realce azul de toque atrapalham numa
   interface de app; texto de mensagens e campos seguem selecionáveis. */
.ec-native {
  -webkit-tap-highlight-color: transparent;
}
.ec-native body {
  -webkit-user-select: none;
  user-select: none;
  overscroll-behavior-y: none;   /* sem "puxar para atualizar" acidental */
}
.ec-native input,
.ec-native textarea,
.ec-native .bubble,
.ec-native [contenteditable="true"] {
  -webkit-user-select: text;
  user-select: text;
}

/* Bloco de ação destrutiva (excluir conta) — separado visualmente do resto
   das configurações para não ser clicado sem intenção. */
.danger-card { border-color: color-mix(in srgb, var(--red) 35%, var(--border)); }
.danger-card h2 { color: var(--red); }
.btn.danger.no-grow { border-color: color-mix(in srgb, var(--red) 45%, var(--border)); }
.btn.danger:hover { background: color-mix(in srgb, var(--red) 10%, transparent); }

/* Aviso no rodapé do menu enxuto do celular, explicando onde estão as telas
   que só fazem sentido em tela grande. Alternado por app.js (isMobileLayout). */
.nav-hint {
  margin: 0 0 9px; padding: 9px 11px;
  font-size: 11.5px; line-height: 1.45; color: var(--faint);
  background: var(--bg2); border-radius: 9px;
}

/* ===========================================================================
   BARRA DE NAVEGAÇÃO DO RODAPÉ (celular)
   Substitui a gaveta lateral: quatro destinos ao alcance do polegar e um
   botão "Mais" que abre o restante numa folha. Só existe no celular —
   buildTabbar() alterna .hidden conforme isMobileLayout().
   =========================================================================== */
.tabbar {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 190;
  display: flex; align-items: stretch;
  background: var(--card); border-top: 1px solid var(--border);
  padding-bottom: env(safe-area-inset-bottom, 0px);   /* barra de gestos do iPhone */
  box-shadow: 0 -6px 22px rgba(6, 10, 8, .07);
}
.tabbar-item {
  flex: 1; min-width: 0;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px;
  padding: 9px 4px 8px; position: relative;
  background: none; border: 0; cursor: pointer;
  color: var(--faint); font-size: 10.5px; font-weight: 600;
  text-decoration: none; -webkit-tap-highlight-color: transparent;
  transition: color .16s;
}
.tabbar-item svg { width: 21px; height: 21px; flex: none; }
.tabbar-item span { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%; }
.tabbar-item.on { color: var(--verde-esc); }
.tabbar-item:active { opacity: .6; }
/* traço no topo do destino ativo — âncora visual sem ocupar altura */
.tabbar-item.on::before {
  content: ''; position: absolute; top: 0; left: 50%; transform: translateX(-50%);
  width: 26px; height: 2.5px; border-radius: 0 0 3px 3px; background: var(--verde-esc);
}
.tabbar-dot {
  position: absolute; top: 5px; left: 50%; margin-left: 3px;
  min-width: 16px; height: 16px; padding: 0 4px;
  display: flex; align-items: center; justify-content: center;
  background: var(--red); color: #fff; font-size: 9.5px; font-weight: 500;
  border-radius: 99px; border: 2px solid var(--card);
}

/* A folga para a barra de baixo é definida mais adiante, no bloco de área
   segura: ela precisa ir em QUEM ROLA (`.page`), e não no `main#view`, que não
   rola. As duas regras que ficavam aqui foram substituídas por aquelas. */
/* Com a barra no rodapé, a gaveta e o hambúrguer perdem a função. */
body.has-tabbar .nav-toggle { display: none; }
body.has-tabbar .sidebar, body.has-tabbar .nav-backdrop { display: none; }

/* ---- Folha "Mais" ---- */
.sheet-back {
  position: fixed; inset: 0; z-index: 195; background: rgba(6, 10, 8, .5);
  -webkit-backdrop-filter: blur(2px); backdrop-filter: blur(2px);
}
.more-sheet {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 196;
  background: var(--card); border-radius: 20px 20px 0 0;
  padding: 10px 18px calc(22px + env(safe-area-inset-bottom, 0px));
  box-shadow: 0 -10px 40px rgba(6, 10, 8, .3);
  animation: sheet-up .22s var(--ease, ease);
}
@keyframes sheet-up { from { transform: translateY(100%); } to { transform: none; } }
.sheet-grip { width: 38px; height: 4px; border-radius: 99px; background: var(--border2); margin: 0 auto 12px; }
.more-sheet h3 { margin: 0 0 14px; font-size: 15px; color: var(--tinta, var(--text)); }
.sheet-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; }
.sheet-item {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 7px;
  padding: 16px 8px; border-radius: 14px; background: var(--bg2);
  color: var(--text2); font-size: 11.5px; font-weight: 600; text-align: center;
  text-decoration: none; -webkit-tap-highlight-color: transparent;
}
.sheet-item svg { width: 22px; height: 22px; }
.sheet-item:active { background: var(--border2); }

/* ---------------------------------------------------------------------------
   SALDO DA CARTEIRA NO CABEÇALHO
   Valor sempre à vista e depósito a um toque. O "+" usa o gradiente da marca
   (--verde → --verde-deep) para se ler como ação principal, não como ícone.
   --------------------------------------------------------------------------- */
/* O raio acompanha os outros widgets do cabeçalho (chip de status, botões):
   arredondado o bastante para não ficar duro, longe da pílula que destoava. */
.tb-wallet {
  display: none; align-items: center; gap: 6px; flex: none;
  padding: 3px 3px 3px 10px; border-radius: 9px;
  background: var(--bg2); border: 1px solid var(--border);
}
.tb-wallet:not(.hidden) { display: flex; }
.tb-wallet-val {
  font-size: 12.5px; font-weight: 500; color: var(--tinta, var(--text));
  text-decoration: none; letter-spacing: -.01em; white-space: nowrap;
}
.tb-wallet-add {
  width: 26px; height: 26px; flex: none;
  display: inline-flex; align-items: center; justify-content: center;
  border: 0; border-radius: 7px; cursor: pointer; color: #fff;
  background: var(--btn-verde); color: var(--btn-tinta);
  box-shadow: 0 2px 8px color-mix(in srgb, var(--btn-verde) 45%, transparent);
  -webkit-tap-highlight-color: transparent;
  transition: transform .14s var(--ease, ease), box-shadow .14s;
}
.tb-wallet-add:active { transform: scale(.9); box-shadow: none; }
/* A CARTEIRA DO TOPO VALE EM TODA TELA, e não só no celular.
   Ela chegou a sair no computador para não repetir o número da caixa verde da
   lateral, mas as duas não fazem a mesma coisa: a da lateral é a vitrine do
   saldo, esta é o atalho que segue a pessoa em qualquer página — e é daqui que
   ela saca sem voltar para o Dashboard. O que saiu do topo foi o botão "Sair",
   que virou item do menu do perfil; é esse espaço que dá lugar a saldo grande. */

/* ---------------------------------------------------------------------------
   CARTEIRA NA BARRA LATERAL (computador)
   Fica logo abaixo da marca, com o fundo do BOTÃO BRILHANTE — a mesma faixa de
   luz que atravessa o "Começar agora" da vitrine. O saldo sozinho é consulta e
   não mereceria esse destaque; o que o justifica é o SAQUE ao lado, que é
   ação, e é a ação que o lojista mais procura depois de vender.
   No celular esta caixa não existe: lá a carteira mora na barra de cima.
   --------------------------------------------------------------------------- */
.sb-wallet {
  display: none; align-items: center; gap: 8px; margin: 0 14px 4px;
  padding: 9px 9px 9px 13px; border-radius: 10px; color: #fff;
  background: linear-gradient(45deg, #1c834a, #1c834a, #2ed378, #1c834a, #1c834a);
  background-size: 200% 200%; animation: brilhoPassar 5s ease-in-out infinite;
  box-shadow: 0 3px 12px rgba(28, 131, 74, .28);
}
.sb-wallet:not(.hidden) { display: flex; }
/* O saldo é um LINK (leva para a carteira e o extrato), e por isso precisa se
   defender das regras globais de `a`: `a:hover` pinta de verde-escuro e
   sublinha. Sobre o gradiente verde, o verde-escuro some e o sublinhado corta o
   número no meio. Aqui o texto é branco nos quatro estados, e o sublinhado nunca
   aparece — o alvo de clique já é a caixa inteira, não precisa da dica. */
.sb-wallet-val,
.sb-wallet-val:hover,
.sb-wallet-val:focus,
.sb-wallet-val:active,
.sb-wallet-val:visited {
  flex: 1; min-width: 0; text-decoration: none; color: #fff; line-height: 1.15;
}
.sb-wallet-val:hover .sb-wallet-lbl, .sb-wallet-val:hover .sb-wallet-num { color: #fff; }
.sb-wallet-lbl { display: block; font-size: 10px; font-weight: 500; opacity: .82; letter-spacing: .02em; color: #fff; }
.sb-wallet-num, .sb-wallet-val b {
  display: block; font-size: 15px; font-weight: 700; letter-spacing: -.02em; color: #fff;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* O botão precisa se destacar SOBRE o gradiente — por isso vidro, e não outra
   cor: qualquer cor chapada brigaria com a faixa de luz passando por baixo. */
.sb-wallet-btn {
  width: 32px; height: 32px; flex: none; cursor: pointer; color: #fff;
  display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid rgba(255, 255, 255, .34); border-radius: 9px;
  background: rgba(255, 255, 255, .16);
  -webkit-tap-highlight-color: transparent;
  transition: background .15s, transform .14s;
}
.sb-wallet-btn:hover { background: rgba(255, 255, 255, .28); }
.sb-wallet-btn:active { transform: scale(.92); }
/* Quem pediu menos movimento não precisa de uma faixa de luz atravessando o
   saldo o dia inteiro — o fundo fica, a animação sai. */
@media (prefers-reduced-motion: reduce) { .sb-wallet { animation: none; } }
/* A partir de 960px a barra lateral encolhe para 64px e só mostra ícones — é o
   mesmo ponto em que `.brand-text` some. A caixa de saldo não cabe nessa faixa,
   e nem precisa: dali para baixo a carteira mora na barra de cima. Este número
   TEM de acompanhar o `@media (max-width: 960px)` da sidebar; se um mudar sem o
   outro, sobra uma caixa verde espremida ao lado dos ícones. */
@media (max-width: 960px) { .sb-wallet, .sb-wallet:not(.hidden) { display: none; } }

/* Numa tela bem estreita o cabeçalho não comporta tudo: o chip de status do
   WhatsApp sai (a mesma informação está no Dashboard e em Configurações) para
   o saldo caber sem espremer os outros botões. */
@media (max-width: 430px) {
  body.has-tabbar #tb-status { display: none; }
  body.has-tabbar .theme-btn { display: none; }
}
/* Toggles de funcionalidade do plano (Admin SaaS) */
.feat-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(215px, 1fr)); gap: 9px 14px; }
.feat-row { margin: 0; font-size: 12.5px; font-weight: 600; color: var(--text2); }

/* Linha da conta de WhatsApp: o bloco de texto abre o "renomear" */
.ch-row-main { flex: 1; min-width: 0; cursor: pointer; border-radius: 9px; padding: 2px 6px; margin: -2px -6px; transition: background .15s; }
.ch-row-main:hover { background: color-mix(in srgb, var(--verde) 10%, transparent); }
.ch-row-main:focus-visible { outline: 2px solid var(--verde-esc); outline-offset: 1px; }

/* Modal de opt-in das notificações (mostrado no login) */
.notif-perks { display: flex; flex-direction: column; gap: 8px; padding: 12px 14px; background: var(--bg2); border: 1px solid var(--border); border-radius: 12px; }
.notif-perks > div { display: flex; align-items: center; gap: 9px; font-size: 13px; font-weight: 600; color: var(--text2); }
.notif-perks svg { color: var(--verde-esc); flex-shrink: 0; }

/* Editor de etapas do Pipeline (fica dentro da própria aba) */
.pipe-cfg { margin-bottom: 14px; }
.pipe-rows { display: flex; flex-direction: column; gap: 8px; }
.pipe-row { display: flex; align-items: center; gap: 8px; }
.pipe-row input { flex: 1; margin: 0; }
.pipe-row .btn { padding: 7px 10px; line-height: 1; }
.pipe-row .btn[disabled] { opacity: .35; pointer-events: none; }
.pipe-num {
  width: 24px; height: 24px; flex: none; border-radius: 7px;
  display: grid; place-items: center;
  background: var(--bg2); color: var(--muted);
  font-size: 12px; font-weight: 500;
}

/* ---------------------------------------------------------------------------
   DEPÓSITO NA CARTEIRA
   Dez atalhos em duas fileiras de cinco. Grade fixa em vez de flex: as colunas
   ficam do mesmo tamanho e os valores alinham na vertical, que é o que permite
   comparar as opções de relance.
   --------------------------------------------------------------------------- */
.dep-chips {
  display: grid; grid-template-columns: repeat(5, 1fr);
  gap: 7px; margin-top: 9px;
}
.dep-chip {
  padding: 9px 4px; border-radius: 9px; cursor: pointer;
  border: 1px solid var(--border); background: var(--bg2); color: var(--text);
  font: inherit; font-size: 12.5px; font-weight: 500; white-space: nowrap;
  transition: border-color .12s, background .12s, transform .1s;
}
.dep-chip:hover { border-color: var(--btn-verde); background: var(--bg); }
.dep-chip:active { transform: scale(.96); }
.dep-chip.on { border-color: var(--btn-verde); background: var(--btn-verde); color: var(--btn-tinta); }

/* Numa tela estreita cinco colunas espremem o valor: viram duas fileiras de… */
@media (max-width: 460px) {
  .dep-chips { grid-template-columns: repeat(4, 1fr); }
}

/* Recarga automática: bloco recolhido até ser ligado, para não competir com a
   ação principal (depositar agora). */
.auto-topup {
  margin-top: 16px; padding: 12px; border-radius: 12px;
  border: 1px dashed var(--border); background: var(--bg2);
  transition: border-color .15s, background .15s;
}
.auto-topup.on { border-style: solid; border-color: var(--verde); }
.auto-head { align-items: flex-start; gap: 9px; }
.auto-head b { display: block; font-size: 13.5px; }
.auto-head em { display: block; margin-top: 2px; font-size: 12px; color: var(--muted); font-style: normal; }
.pay-method.off { opacity: .55; }
.pay-method.off input { cursor: not-allowed; }


/* ---------------------------------------------------------------------------
   POP-UP DE DEPÓSITO
   Uma coluna, como no resto do app. A altura maior evita a rolagem quando a
   recarga automática está aberta.
   --------------------------------------------------------------------------- */
.modal-dep { max-height: 94vh; }
.modal-dep .auto-topup { padding: 11px; }
.pay-methods.compact .pay-method { padding: 9px 11px; }
.pay-methods.compact .pay-method b { font-size: 13px; }
.pay-methods.compact .pay-method em { font-size: 11.5px; }

/* Ícone do meio de pagamento no lugar do seletor redondo: o Pix e o cartão se
   reconhecem pelo símbolo antes de a pessoa ler o rótulo. O input continua ali
   para o teclado e o leitor de tela, só não é mais o que se vê.
   Só onde EXISTE ícone: as outras listas de pagamento continuam com o seletor
   redondo, que ali é a única marca do que está escolhido. */
.pay-method:has(.pay-ic) { position: relative; }
.pay-method:has(.pay-ic) input { position: absolute; opacity: 0; pointer-events: none; }
.pay-ic {
  width: 34px; height: 34px; flex: none; border-radius: 10px;
  display: grid; place-items: center;
  background: var(--bg2); color: var(--muted);
  transition: background .14s, color .14s;
}
.pay-method:has(input:checked) .pay-ic { background: var(--verde); color: #fff; }
.pay-method:focus-within { border-color: var(--verde-esc); box-shadow: var(--ring); }

/* ---------------------------------------------------------------------------
   CADASTRO: perfil da empresa
   Dois campos curtos lado a lado; abaixo de 420px o formulário já é estreito
   demais e eles empilham.
   --------------------------------------------------------------------------- */
#reg-perfil { display: flex; flex-direction: column; gap: 12px; }
/* Um campo por linha no cadastro. Em duas colunas, a célula do WhatsApp ficava
   com metade do cartão e ainda tinha que abrigar o seletor de país (108px
   fixos) mais o número: sobrava uma caixinha de dois dígitos para o telefone. */
.reg-cols { display: grid; grid-template-columns: 1fr; gap: 12px; }

/* Segmento, tamanho e objetivo na linha da conta, no Admin SaaS */
.acc-perfil { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 5px; }
.acc-perfil .pill { font-size: 10.5px; padding: 2px 7px; }

/* ---------------------------------------------------------------------------
   ADMIN → MARKETING
   Lista de templates e prévia do disparo.
   --------------------------------------------------------------------------- */
.mkt-list { display: flex; flex-direction: column; gap: 8px; }
.mkt-item {
  display: flex; align-items: center; gap: 10px;
  border: 1px solid var(--border); border-radius: 12px; padding: 11px 13px; background: var(--card);
}
.mkt-item:hover { border-color: var(--border2); }
.mkt-tags { display: flex; gap: 5px; margin: 4px 0 2px; }
.mkt-tags .pill { font-size: 10.5px; padding: 2px 7px; }
.mkt-prev { font-size: 12px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mkt-preview {
  margin-top: 12px; padding: 13px 15px; border-radius: 12px;
  border: 1px dashed var(--verde); background: var(--brand-bg);
}
.mkt-prev-head { font-size: 12px; font-weight: 500; color: var(--verde-deep); margin-bottom: 8px; }
.mkt-preview p { margin: 4px 0 8px; font-size: 13.5px; line-height: 1.55; white-space: pre-wrap; }

/* ---------------------------------------------------------------------------
   TELEFONE COM PAÍS
   Bandeira e código à esquerda, número à direita, como um campo só.
   --------------------------------------------------------------------------- */
.fone-linha { display: flex; gap: 8px; align-items: stretch; }
.fone-linha .ecsel.fone-pais { flex: 0 0 108px; }
.fone-linha .ecsel.fone-pais .ecsel-btn { padding-left: 11px; padding-right: 9px; }
.fone-linha input { flex: 1; min-width: 0; }

/* ---------------------------------------------------------------------------
   ESCOLHA DE PLANO (conta ainda sem assinatura)
   Uma decisão por tela: os cards ficam lado a lado para comparar de relance.
   --------------------------------------------------------------------------- */
.planos-page { max-width: 1040px; }
.planos-head { text-align: center; margin: 8px 0 26px; }
.planos-head h1 { font-size: 27px; letter-spacing: -.03em; margin: 0 0 6px; }
.planos-head p { color: var(--muted); margin: 0; font-size: 14px; }

/* Os cartões seguem a linguagem do resto do app (.card / .mh-card): mesmo
   raio, mesma borda, mesma sombra, e o destaque com o gradiente da marca —
   antes eram três caixas soltas que não pareciam da mesma tela. */
.planos-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 16px; align-items: stretch; }
.plano-card {
  position: relative; display: flex; flex-direction: column;
  background: var(--card); border: 1px solid var(--border); border-radius: var(--radius);
  padding: 22px; box-shadow: var(--shadow-xs);
  transition: border-color .18s, box-shadow .18s, transform .18s;
}
.plano-card:hover { border-color: var(--verde-esc); box-shadow: var(--shadow); transform: translateY(-3px); }
/* Destaque: mesmo tratamento do .mh-card.hi, para o cartão pertencer ao app. */
.plano-card.hi { background: linear-gradient(150deg, var(--brand-bg), var(--card)); border-color: var(--brand-border); }
.plano-tag {
  position: absolute; top: -10px; left: 22px; padding: 3px 11px; border-radius: 999px;
  background: var(--grad); color: #fff; font-size: 10.5px; font-weight: 500;
  letter-spacing: .05em; text-transform: uppercase; box-shadow: 0 3px 10px rgba(46, 211, 120, .35);
}
.plano-card h3 { margin: 0; font-size: 15px; font-weight: 500; letter-spacing: .04em; text-transform: uppercase; color: var(--muted); }
.plano-preco { margin: 8px 0 0; display: flex; align-items: baseline; gap: 7px; flex-wrap: wrap; }
/* O preço usa o mesmo tratamento dos números grandes do painel (.mh-val). */
.plano-preco b { font-size: 32px; font-weight: 500; letter-spacing: -.045em; font-variant-numeric: tabular-nums; color: var(--text); }
.plano-preco em { font-style: normal; font-size: 12.5px; font-weight: 600; color: var(--muted); }
.plano-equiv { margin-top: 4px; font-size: 12px; color: var(--muted); }
.plano-equiv b { color: var(--verde-deep); font-weight: 500; }
.plano-itens { list-style: none; margin: 18px 0 0; padding: 18px 0 0; border-top: 1px solid var(--border); display: flex; flex-direction: column; gap: 9px; }
.plano-itens li { display: flex; align-items: flex-start; gap: 9px; font-size: 13px; color: var(--text2); line-height: 1.45; }
.plano-itens .ic { color: var(--verde-esc); flex: none; margin-top: 3px; }
.plano-sec { margin: 18px 0 8px; font-size: 10.5px; font-weight: 500; letter-spacing: .07em; text-transform: uppercase; color: var(--faint); }
.plano-mods { display: flex; flex-wrap: wrap; gap: 5px; margin-bottom: 18px; }
.plano-mods .pill { font-size: 10.5px; padding: 3px 9px; font-weight: 500; }
/* O botão gruda no rodapé do cartão: com listas de tamanhos diferentes, os
   botões ficavam em alturas diferentes e a grade parecia torta. */
.plano-card .btn { margin-top: auto; }

/* Esperando o pagamento cair, depois de abrir o checkout. */
.aguardando { max-width: 520px; margin: 0 auto; text-align: center; }
.aguardando .row { justify-content: center; }

/* Diagnóstico do app da Meta: uma linha por achado, ícone alinhado ao texto. */
.meta-diag { display: flex; flex-direction: column; gap: 7px; margin-top: 8px; }
.meta-diag > div { display: flex; gap: 7px; align-items: flex-start; font-size: 12.5px; line-height: 1.5; }
.meta-diag .ic { flex: none; margin-top: 2px; }

/* Barra do CTR: a proporcao vista de relance, sem precisar ler o numero. */
.ctr-bar { height: 7px; border-radius: 99px; background: var(--bg2); overflow: hidden; margin-top: 8px; }
.ctr-bar i { display: block; height: 100%; border-radius: 99px; background: linear-gradient(90deg, var(--verde), var(--verde-esc)); }

/* ---------------------------------------------------------------------------
   DESEMPENHO DOS BOTÕES
   Três números no topo (quantos passaram, quantos clicaram, CTR) e uma linha
   por botão com barra. A barra existe porque comparar dois números soltos numa
   tabela obriga a fazer a conta de cabeça; a barra responde de relance qual
   opção ganhou. O número exato fica no `title`, para quem precisa dele.
   --------------------------------------------------------------------------- */
.ctr-topo { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; margin-top: 12px; }
.ctr-kpi {
  background: var(--bg2); border: 1px solid var(--border); border-radius: 11px; padding: 10px 12px;
}
.ctr-kpi span { display: block; font-size: 19px; font-weight: 600; letter-spacing: -.02em; color: var(--text); }
.ctr-kpi em { display: block; font-style: normal; font-size: 11px; color: var(--muted); line-height: 1.3; margin-top: 2px; }
.ctr-kpi.forte { border-color: var(--brand-border); background: var(--brand-bg); }
.ctr-kpi.forte span { color: var(--verde-deep); }

.ctr-opt {
  display: flex; align-items: center; gap: 10px; padding: 7px 0;
  border-bottom: 1px solid var(--border); font-size: 13px; cursor: default;
}
.ctr-opt:last-child { border-bottom: 0; }
.ctr-opt:hover { background: var(--bg2); }
.ctr-opt-nm { flex: 0 0 34%; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ctr-opt-bar { flex: 1; height: 8px; border-radius: 99px; background: var(--bg2); overflow: hidden; min-width: 40px; }
.ctr-opt-bar i { display: block; height: 100%; border-radius: 99px; background: linear-gradient(90deg, var(--verde), var(--verde-esc)); }
.ctr-opt-pct { flex: 0 0 46px; text-align: right; font-weight: 600; }
.ctr-opt-qt { flex: 0 0 44px; text-align: right; font-size: 12px; color: var(--muted); }
/* Quem recebeu e não tocou em nada é informação, não conquista: cinza. */
.ctr-opt-sobra { color: var(--muted); }
.ctr-opt-sobra .ctr-opt-bar i { background: var(--border2); }
@media (max-width: 560px) {
  .ctr-topo { grid-template-columns: 1fr; }
  .ctr-opt-nm { flex: 0 0 40%; }
}

/* ===================== MENSAGEM DE VOZ =====================
   O <audio controls> do navegador é uma barra cinza de 300px que ignora o
   tema e destoa de tudo. Aqui ele fica escondido, tocando por trás, e o que
   aparece é botão, onda e tempo restante. */
.voz { display: flex; align-items: center; gap: 10px; min-width: 210px; padding: 2px 0; }
.voz audio { display: none; }
.voz-play {
  width: 34px; height: 34px; flex: none; border-radius: 50%; border: none; cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--verde-esc); color: #fff; padding-left: 2px;   /* o triângulo pesa à esquerda */
  transition: transform .15s, background .15s;
}
.voz-play:hover { background: var(--verde-deep); }
.voz-play:active { transform: scale(.93); }
.voz.tocando .voz-play { padding-left: 0; }
/* Tocando, o triângulo vira pausa sem trocar de ícone: duas barras por cima. */
.voz.tocando .voz-play svg { opacity: 0; }
.voz.tocando .voz-play::after {
  content: ''; position: absolute; width: 11px; height: 13px;
  border-left: 3.5px solid #fff; border-right: 3.5px solid #fff;
}
.voz-play { position: relative; }

.voz-onda {
  position: relative; flex: 1; min-width: 0; height: 26px; cursor: pointer;
  display: flex; align-items: center; gap: 2px; overflow: hidden;
}
.voz-onda i {
  flex: 1; min-width: 2px; border-radius: 99px; background: var(--border2);
  transition: background .2s;
}
/* A parte tocada fica verde. São DUAS ondas empilhadas: a de baixo cinza,
   a de cima verde, recortada por clip-path na porcentagem tocada. Tentei antes
   com mix-blend-mode e o resultado dependia do tema; recorte é exato nos dois. */
.voz-prog {
  position: absolute; inset: 0; display: flex; align-items: center; gap: 2px;
  pointer-events: none; clip-path: inset(0 100% 0 0);
  transition: clip-path .1s linear;
}
.voz-prog i { background: var(--verde-esc); }
.msg.out .voz-prog i { background: var(--verde-deep); }

.voz-tempo {
  flex: none; font-size: 11px; font-weight: 500; color: var(--muted);
  font-variant-numeric: tabular-nums; min-width: 34px; text-align: right;
}
.msg.out .voz-onda i { background: rgba(6, 95, 70, .22); }
.msg.out .voz-tempo { color: var(--verde-deep); }
/* Mensagem de voz gravada no microfone ganha o microfone; áudio anexado, não. */
.voz.is-voz .voz-play::before {
  content: ''; position: absolute; right: -1px; bottom: -1px;
  width: 12px; height: 12px; border-radius: 50%; background: var(--card);
  box-shadow: inset 0 0 0 1.5px var(--verde-esc);
}
@media (max-width: 720px) {
  .voz { min-width: 0; gap: 8px; }
  .voz-play { width: 31px; height: 31px; }
  .voz-onda { height: 23px; }
}

/* ===================== ENVIO NO ESTILO WHATSAPP =====================
   A mensagem sai de onde foi escrita: o balão nasce embaixo, perto do campo
   de texto, e sobe para o seu lugar na conversa. Enviada e recebida usam a
   mesma ideia, cada uma ancorada no seu lado. */
.msg.out { animation: balaoSai .3s cubic-bezier(.2, 1, .3, 1) both; transform-origin: bottom right; }
.msg.in  { animation: balaoChega .3s cubic-bezier(.2, 1, .3, 1) both; transform-origin: bottom left; }
@keyframes balaoSai   { from { opacity: 0; transform: translateY(26px) scale(.9); } }
@keyframes balaoChega { from { opacity: 0; transform: translateY(16px) scale(.92); } }

/* O balão que acabou de sair do campo de texto vem de mais longe e de baixo,
   para o olho seguir o caminho do texto até a conversa. */
.msg.subindo { animation: balaoDoCampo .42s cubic-bezier(.16, .9, .3, 1) both; }
@keyframes balaoDoCampo {
  from { opacity: 0; transform: translateY(64px) scale(.82); }
  60%  { opacity: 1; }
}

/* Reloginho de "ainda indo". Pulsa de leve para não parecer um ✓ travado. */
.st.pend { display: inline-flex; align-items: center; opacity: .75; animation: pendPulsa 1.4s ease-in-out infinite; }
@keyframes pendPulsa { 50% { opacity: .35; } }

@media (prefers-reduced-motion: reduce) {
  .msg, .msg.in, .msg.out, .msg.subindo { animation: none; }
  .st.pend { animation: none; }
}

/* ===================== BOTÕES DO CHAT =====================
   Ferramentas do campo de mensagem no formato do WhatsApp: ícone redondo, sem
   caixa nem rótulo, o nome no tooltip. Eram pílulas com borda e texto, que
   ocupavam duas linhas inteiras acima do campo. */
.composer .tools .btn.small {
  width: 38px; height: 38px; padding: 0; border-radius: 50%;
  border: none; background: transparent; box-shadow: none;
  color: var(--muted); display: inline-flex; align-items: center; justify-content: center;
  transition: background .16s, color .16s, transform .12s;
}
.composer .tools .btn.small .blbl { display: none; }
.composer .tools .btn.small svg { width: 20px; height: 20px; }
.composer .tools .btn.small:hover:not(:disabled) { background: var(--bg2); color: var(--verde-esc); }
.composer .tools .btn.small:active:not(:disabled) { transform: scale(.9); }
/* Cobrança é a ação de dinheiro: fica verde para não se perder entre as outras */
.composer .tools #tool-pay { color: var(--verde-esc); }

/* Enviar: círculo cheio, como o do WhatsApp */
.send-btn { border-radius: 50% !important; }

/* ===================== COBRANÇA EM ETAPAS =====================
   O modal da cobrança é o mais cheio do app: produto, checkout, valor,
   descrição, destinatário e ainda o texto da mensagem. Nos 500px do modal
   comum isso vira uma coluna interminável, então aqui ele é largo e o
   conteúdo se divide em duas colunas — que voltam a ser uma no celular. */
.modal.cob { max-width: 880px; }
.modal.cob .ep-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px 14px; }
.modal.cob .ep-grid label { display: block; margin: 0; }
.modal.cob .ep-etapa { display: flex; flex-direction: column; gap: 12px; }
.modal.cob .ep-etapa.hidden { display: none; }

.ep-trilha { display: flex; gap: 8px; }
.ep-trilha span {
  flex: 1; display: flex; align-items: center; gap: 9px;
  font-size: 12.5px; font-weight: 500; color: var(--faint);
  padding: 9px 12px; border-radius: 12px; background: var(--bg2);
  border: 1px solid transparent; transition: color .18s, background .18s, border-color .18s;
}
.ep-trilha span i {
  font-style: normal; width: 21px; height: 21px; flex: none; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--border2); color: var(--card); font-size: 11px; font-weight: 500;
}
.ep-trilha span.on { color: var(--verde-deep); background: var(--brand-bg); border-color: var(--brand-border); }
.ep-trilha span.on i { background: var(--verde-esc); color: #fff; }

.ep-para {
  display: flex; align-items: center; gap: 8px; font-size: 13px; color: var(--text2);
  background: var(--bg2); border-radius: 11px; padding: 10px 13px;
}
.ep-para svg { color: var(--verde-esc); flex: none; }

.ep-msg-cols { display: grid; grid-template-columns: 1fr 1fr; gap: 18px; align-items: start; }
.ep-msg { width: 100%; min-height: 170px; font-family: inherit; font-size: 13.5px; line-height: 1.5; resize: vertical; }
.ep-vars { display: flex; flex-wrap: wrap; gap: 6px; }
.ep-var {
  border: 1px dashed var(--brand-border); background: var(--brand-bg); color: var(--verde-deep);
  border-radius: 8px; padding: 5px 10px; font-size: 12px; font-weight: 500;
  font-family: ui-monospace, Menlo, Consolas, monospace; cursor: pointer;
  transition: background .14s, transform .1s;
}
.ep-var:hover { background: var(--card); }
.ep-var:active { transform: scale(.94); }

/* A prévia é o balão de verdade do chat, no fundo do chat, para não haver
   surpresa entre o que se escreve aqui e o que chega no WhatsApp. */
.ep-preview {
  background: var(--bg2); border: 1px solid var(--border); border-radius: 14px;
  padding: 14px; display: flex; justify-content: flex-end; max-height: 340px; overflow-y: auto;
}
.ep-preview .msg { max-width: 100%; animation: none; }
.ep-preview-wrap { display: flex; flex-direction: column; gap: 6px; }
.modal.cob .ep-acoes { align-items: center; gap: 8px; }

@media (max-width: 760px) {
  /* No celular o modal ocupa a tela: com 6 campos e um textarea, meia tela
     com fundo escurecido em volta não ajuda ninguém. */
  .modal-back:has(.modal.cob) { padding: 0; }
  .modal.cob {
    max-width: none; width: 100%; height: 100%; max-height: 100%;
    border-radius: 0; border: none; padding: 18px 16px 16px;
  }
  .modal.cob .ep-grid, .modal.cob .ep-msg-cols { grid-template-columns: 1fr; }
  .ep-trilha span { font-size: 11.5px; padding: 8px 10px; gap: 7px; }
  .ep-preview { max-height: 200px; }
  .modal.cob .ep-acoes {
    position: sticky; bottom: 0; background: var(--card);
    margin: 0 -16px -16px; padding: 10px 16px 14px; border-top: 1px solid var(--border);
  }
  /* Três botões não cabem em 375px — "Gerar e enviar" saía cortado pela borda.
     Cancelar sai: o X do topo e o toque fora já fecham, e o que não pode ficar
     ilegível é justamente o botão que conclui. */
  .modal.cob .ep-acoes > span { display: none; }
  .modal.cob .ep-acoes .btn:not(#ep-nc-voltar):not(.primary) { display: none; }
  .modal.cob .ep-acoes .btn { flex: 1; justify-content: center; }
  .modal.cob .ep-acoes #ep-nc-voltar { flex: 0 0 auto; }
}

/* ===================== PAGAMENTOS · SAQUE =====================
   Os dois tempos do dinheiro lado a lado. O disponível é o número que a pessoa
   veio ver, então ele é o maior e o único colorido; o pendente fica ao lado
   com a data da próxima liberação, que é a pergunta seguinte. */
.sq-cards { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; margin-bottom: 14px; }
.sq-card {
  background: var(--card); border: 1px solid var(--border); border-radius: var(--radius);
  padding: 18px 20px; display: flex; flex-direction: column; gap: 5px;
}
.sq-card.ok { border-color: var(--brand-border); background: var(--brand-bg); }
.sq-card.neg { border-color: var(--red-border); background: var(--red-bg); }
.sq-lbl {
  display: flex; align-items: center; gap: 7px; font-size: 10.5px; font-weight: 500;
  text-transform: uppercase; letter-spacing: .06em; color: var(--muted);
}
.sq-val { font-size: 27px; font-weight: 500; letter-spacing: -.02em; line-height: 1.1; }
.sq-card.ok .sq-val { color: var(--verde-deep); }
.sq-card.neg .sq-val { color: var(--red); }
.sq-hint { font-size: 12px; color: var(--muted); }

/* ---------------------------------------------------------------------------
   POP-UP DE SAQUE (botão de carteira)
   O conteúdo mora dentro de um `#sq-modal` porque ele é trocado inteiro quando
   o saldo chega — e um wrapper não herda o `gap` do `.modal`, então ele repete
   o mesmo espaçamento aqui. Os cartões de saldo entram menores: num pop-up de
   500px, os 27px da tela de Pagamentos brigariam com os campos logo abaixo.
   --------------------------------------------------------------------------- */
.modal-sq #sq-modal { display: flex; flex-direction: column; gap: 13px; }
.modal-sq .sq-cards { gap: 10px; margin-bottom: 0; }
.modal-sq .sq-card { padding: 12px 14px; gap: 3px; }
.modal-sq .sq-val { font-size: 21px; }
.modal-sq label { margin: 0; }

@media (max-width: 760px) {
  .sq-cards { grid-template-columns: 1fr; gap: 10px; }
  .sq-val { font-size: 23px; }
  /* A coluna do VALOR não pode sair da tela: é o número que a pessoa veio ver.
     Fonte e respiro menores fazem as três colunas caberem em 375px sem rolagem
     lateral dentro do cartão. */
  #ep-box table { font-size: 11.5px; }
  #ep-box table th, #ep-box table td { padding: 8px 6px; }
  #ep-box table td:last-child, #ep-box table th:last-child { white-space: nowrap; }
  /* A regra geral do celular manda as tabelas do card rolarem na horizontal
     (`width: max-content`). Aqui isso escondia o VALOR atrás da rolagem. Nestas
     três tabelas o texto do meio quebra e a coluna do dinheiro fica sempre à
     vista, que é o ponto da tela. */
  #ep-box table thead, #ep-box table tbody { width: 100%; min-width: 0; }
  #ep-box table { overflow-x: visible; }
  #ep-box table td { white-space: normal; word-break: break-word; }
}

/* ===================== AFILIAÇÃO =====================
   A tela vende uma coisa só: o link. O desenho segue essa ordem — a oferta e o
   link dividem a primeira dobra, com a oferta em fundo escuro (é o único bloco
   escuro do painel, e por isso o olho vai nele primeiro) e o link em cartão
   claro ao lado, pronto para copiar. */
.aff-top {
  display: grid; grid-template-columns: 1.05fr 1fr; gap: 14px; margin-bottom: 14px;
  align-items: stretch;
}
.aff-oferta {
  position: relative; overflow: hidden;
  border-radius: var(--radius); padding: 22px 24px;
  background: linear-gradient(145deg, #17b06a 0%, #0f8a58 42%, #0a6144 100%);
  color: #eefbf4;
  display: flex; flex-direction: column; justify-content: center; gap: 14px;
}
/* brilho discreto no canto, para o bloco não ficar chapado */
.aff-oferta::after {
  content: ''; position: absolute; right: -60px; top: -60px; width: 200px; height: 200px;
  border-radius: 50%; background: rgba(80, 234, 95, .3); filter: blur(30px); pointer-events: none;
}
.aff-tag {
  display: inline-flex; align-items: center; gap: 6px; align-self: flex-start;
  padding: 4px 11px; border-radius: 999px; font-size: 10.5px; font-weight: 500;
  letter-spacing: .07em; text-transform: uppercase;
  background: rgba(255, 255, 255, .16); border: 1px solid rgba(255, 255, 255, .24); color: #eafaf1;
}
.aff-nums { display: flex; align-items: center; gap: 18px; flex-wrap: wrap; }
.aff-num { display: flex; flex-direction: column; gap: 2px; }
/* O número é o argumento: tamanho grande, peso 800 e o "%" menor colado nele. */
.aff-num b {
  display: flex; align-items: baseline; gap: 1px;
  font-size: 44px; font-weight: 500; letter-spacing: -.045em; line-height: 1; color: #fff;
  font-variant-numeric: tabular-nums;
}
.aff-num b i { font-style: normal; font-size: 20px; font-weight: 500; opacity: .85; }
.aff-num span { font-size: 12.5px; color: #cdeedd; }
.aff-num span b { font-weight: 500; color: #fff; font-size: 12.5px; display: inline; }
.aff-mais { font-size: 22px; font-weight: 300; color: rgba(255, 255, 255, .38); }
.aff-recorrente {
  display: flex; align-items: flex-start; gap: 9px; margin: 0;
  font-size: 12.5px; line-height: 1.5; color: #d8f3e6;
  padding-top: 13px; border-top: 1px solid rgba(255, 255, 255, .16);
}
.aff-recorrente svg { flex: none; margin-top: 1px; color: #9dfbb4; }
.aff-recorrente b { color: #fff; font-weight: 500; }

.aff-link-box {
  background: var(--card); border: 1px solid var(--border); border-radius: var(--radius);
  padding: 20px 22px; box-shadow: var(--shadow-xs);
  display: flex; flex-direction: column; justify-content: center; gap: 11px;
}
.aff-lbl {
  display: flex; align-items: center; gap: 7px;
  font-size: 10.5px; font-weight: 500; letter-spacing: .07em; text-transform: uppercase; color: var(--faint);
}
.aff-lbl svg { color: var(--verde-esc); }
.aff-link {
  background: var(--bg2); border: 1px solid var(--border); border-radius: 12px;
  padding: 12px 14px; overflow: hidden;
}
.aff-link code {
  font-size: 13px; font-weight: 600; color: var(--text); word-break: break-all;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
}
.aff-acoes { display: flex; gap: 9px; flex-wrap: wrap; }
.aff-acoes .btn { flex: 1 1 150px; justify-content: center; }
.aff-cod { margin: 0; font-size: 12px; color: var(--muted); line-height: 1.5; }
.aff-cod b { color: var(--text); font-weight: 500; letter-spacing: .04em; }

/* Placar: o que já aconteceu. O dinheiro ganho é o único em destaque. */
.aff-placar { display: grid; grid-template-columns: repeat(4, 1fr); gap: 12px; margin-bottom: 14px; }
.aff-placar-i {
  background: var(--card); border: 1px solid var(--border); border-radius: var(--radius);
  padding: 15px 17px; display: flex; flex-direction: column; gap: 7px;
}
.aff-placar-i.hi { background: linear-gradient(150deg, var(--brand-bg), var(--card)); border-color: var(--brand-border); }
.aff-placar-lbl {
  display: flex; align-items: center; gap: 6px;
  font-size: 11px; font-weight: 500; color: var(--muted);
}
.aff-placar-lbl svg { color: var(--verde-esc); flex: none; }
.aff-placar-i b {
  font-size: 22px; font-weight: 500; letter-spacing: -.035em; color: var(--text);
  font-variant-numeric: tabular-nums; line-height: 1;
}
.aff-placar-i.hi b { color: var(--verde-deep); }

/* Simulação: o número que faz a pessoa querer indicar, com o preço REAL do
   plano publicado — nada inventado. */
.aff-sim-linha { display: flex; align-items: center; gap: 16px; margin: 18px 0 16px; }
.aff-range { flex: 1; min-width: 0; accent-color: var(--verde-esc); height: 4px; cursor: pointer; }
.aff-sim-qtd { flex: none; font-size: 12.5px; color: var(--muted); font-weight: 600; white-space: nowrap; }
.aff-sim-qtd b {
  font-size: 17px; font-weight: 500; color: var(--text); margin-right: 4px;
  font-variant-numeric: tabular-nums;
}
.aff-sim-out { display: grid; grid-template-columns: repeat(3, 1fr); gap: 11px; }
.aff-sim-box {
  background: var(--bg2); border: 1px solid var(--border); border-radius: 13px;
  padding: 13px 15px; display: flex; flex-direction: column; gap: 5px;
}
.aff-sim-box.hi { background: linear-gradient(150deg, var(--brand-bg), var(--card)); border-color: var(--brand-border); }
.aff-sim-box span { font-size: 11.5px; font-weight: 600; color: var(--muted); }
.aff-sim-box b {
  font-size: 20px; font-weight: 500; letter-spacing: -.035em; color: var(--text);
  font-variant-numeric: tabular-nums;
}
.aff-sim-box.hi b { color: var(--verde-deep); }

/* Lista de indicados: linha com avatar, como no resto do app. */
.aff-lista { display: flex; flex-direction: column; gap: 2px; }
.aff-ref { display: flex; align-items: center; gap: 11px; padding: 9px 2px; border-bottom: 1px solid var(--border); }
.aff-ref:last-child { border-bottom: none; }
.aff-ref-av {
  flex: none; width: 34px; height: 34px; border-radius: 50%;
  background: var(--brand-bg); color: var(--verde-deep);
  display: grid; place-items: center; font-size: 12px; font-weight: 500;
}
.aff-ref-tx { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.aff-ref-tx b { font-size: 13.5px; font-weight: 500; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.aff-ref-tx span { font-size: 11.5px; color: var(--muted); }

/* Vazio que CONVIDA em vez de só informar: sem indicados, o passo seguinte é
   copiar o link, então ele está ali. */
.aff-vazio { text-align: center; padding: 26px 18px 8px; display: flex; flex-direction: column; align-items: center; gap: 9px; }
.aff-vazio-ic {
  width: 54px; height: 54px; border-radius: 50%; display: grid; place-items: center;
  background: var(--brand-bg); color: var(--verde-esc); margin-bottom: 2px;
}
.aff-vazio b { font-size: 15px; font-weight: 500; color: var(--text); }
.aff-vazio p { margin: 0 0 6px; font-size: 12.5px; color: var(--muted); line-height: 1.55; max-width: 330px; }

@media (max-width: 900px) {
  .aff-top { grid-template-columns: 1fr; }
}
@media (max-width: 760px) {
  .aff-placar { grid-template-columns: 1fr 1fr; gap: 9px; }
  .aff-placar-i { padding: 12px 14px; }
  .aff-placar-i b { font-size: 19px; }
  .aff-oferta { padding: 18px; }
  .aff-num b { font-size: 36px; }
  .aff-num b i { font-size: 17px; }
  .aff-sim-out { grid-template-columns: 1fr; }
  .aff-sim-linha { flex-direction: column; align-items: stretch; gap: 9px; }
  .aff-sim-qtd { text-align: center; }
  .aff-acoes .btn { flex: 1 1 100%; }
}

/* ===================== RELATÓRIO DA CAMPANHA ===================== */
/* Seis etapas: enviadas, entregues, lidas, clicaram, responderam, falhas.
   `auto-fit` e não uma contagem fixa — com cinco colunas travadas a sexta
   caía sozinha numa segunda linha, e a órfã era "Falhas", que passava a
   parecer um bloco à parte em vez do fim do funil. */
.rc-funil { display: grid; grid-template-columns: repeat(auto-fit, minmax(148px, 1fr)); gap: 12px; margin-bottom: 14px; }
.rc-et {
  background: var(--card); border: 1px solid var(--border); border-radius: var(--radius);
  padding: 15px 17px; display: flex; flex-direction: column; gap: 2px; position: relative;
}
.rc-et.bad { border-color: var(--red-border); background: var(--red-bg); }
.rc-et-ic { color: var(--verde-esc); display: flex; margin-bottom: 4px; }
.rc-et.bad .rc-et-ic { color: var(--red); }
.rc-et b { font-size: 24px; font-weight: 500; letter-spacing: -.02em; line-height: 1.1; }
.rc-et.bad b { color: var(--red); }
.rc-et-lb { font-size: 11.5px; font-weight: 600; color: var(--muted); }
/* A taxa fica no canto: é leitura secundária, o número absoluto é o principal. */
.rc-et-pc {
  position: absolute; top: 13px; right: 14px; font-size: 11.5px; font-weight: 500;
  color: var(--verde-deep); background: var(--brand-bg); border-radius: 7px; padding: 3px 7px;
}
/* Barra proporcional na tabela: a ordem da coluna escolhida vira desenho, e o
   estado que se destaca aparece antes de ler qualquer número. */
.rc-bar { height: 7px; border-radius: 99px; background: var(--bg2); overflow: hidden; }
.rc-bar i { display: block; height: 100%; border-radius: 99px; background: var(--verde-esc); }

@media (max-width: 900px) { .rc-funil { grid-template-columns: repeat(3, 1fr); } }
@media (max-width: 560px) {
  .rc-funil { grid-template-columns: 1fr 1fr; gap: 9px; }
  .rc-et { padding: 12px 13px; }
  .rc-et b { font-size: 20px; }
}
/* mapa sem a coluna lateral do Dashboard: ocupa a largura do cartão */
.geo-map.geo-solo { grid-column: 1 / -1; width: 100%; max-width: 760px; margin: 0 auto; }

/* ===================== GRAVAR MENSAGEM DE VOZ ===================== */
.mic-btn { background: var(--card) !important; color: var(--muted) !important; border: 1px solid var(--border) !important; }
.mic-btn:hover { color: var(--verde-deep) !important; border-color: var(--brand-border) !important; }
/* Gravando, o botão vira o vermelho de "parar": é o mesmo botão, e sem a troca
   de cor ninguém entende que tocar de novo ENVIA. */
.mic-btn.rec { background: var(--red) !important; color: #fff !important; border-color: var(--red) !important; }
.composer .line.gravando textarea { opacity: .35; pointer-events: none; }
#mic-hud {
  display: flex; align-items: center; gap: 10px; flex: 1; min-width: 0;
  background: var(--red-bg); border: 1px solid var(--red-border); border-radius: 14px;
  padding: 0 14px; height: 46px; font-size: 13px; font-weight: 500; color: var(--red);
  font-variant-numeric: tabular-nums;
}
.mic-dot {
  width: 9px; height: 9px; border-radius: 50%; background: var(--red); flex: none;
  animation: micPulso 1.1s ease-in-out infinite;
}
@keyframes micPulso { 50% { opacity: .25; } }
@media (prefers-reduced-motion: reduce) { .mic-dot { animation: none; } }
.mic-cancel {
  margin-left: auto; background: none; border: none; cursor: pointer;
  color: var(--muted); font-size: 12.5px; font-weight: 500; padding: 6px 4px;
}
.mic-cancel:hover { color: var(--red); text-decoration: underline; }
/* Gravando, o campo some e o cronômetro ocupa o lugar dele. */
.composer .line.gravando textarea { display: none; }

/* ===================== MARCA NO ADMIN ===================== */
.marca-linha { display: flex; align-items: center; gap: 16px; }
/* Xadrez atrás da prévia: é como se enxerga se a logo tem fundo transparente
   de verdade. Sobre o branco do card, um fundo branco opaco parece transparente
   — e foi exatamente esse engano que deixou a logo com cantos pretos passar. */
.marca-prev {
  width: 82px; height: 82px; flex: none; border-radius: 16px; overflow: hidden;
  border: 1px solid var(--border); display: flex; align-items: center; justify-content: center;
  background-color: var(--card);
  background-image:
    linear-gradient(45deg, var(--bg2) 25%, transparent 25%, transparent 75%, var(--bg2) 75%),
    linear-gradient(45deg, var(--bg2) 25%, transparent 25%, transparent 75%, var(--bg2) 75%);
  background-size: 14px 14px;
  background-position: 0 0, 7px 7px;
}
.marca-prev img { max-width: 74%; max-height: 74%; display: block; border-radius: 12px; }
@media (max-width: 560px) {
  .marca-linha { flex-direction: column; align-items: flex-start; gap: 12px; }
}

/* ===================== CHAMADA MINIMIZADA ===================== */
/* MINIMIZAR — canto superior ESQUERDO, com rótulo.
   Estava como um ícone translúcido de 30px no canto direito, encostado no
   texto da criptografia: ninguém achava. Agora é uma pastilha com fundo
   sólido, texto e área de toque de 40px de altura. */
.call-min {
  position: absolute; left: 18px; top: 18px; z-index: 2;
  display: inline-flex; align-items: center; gap: 8px;
  height: 40px; padding: 0 16px 0 13px; border-radius: 99px;
  background: rgba(255, 255, 255, .16); border: 1px solid rgba(255, 255, 255, .28);
  color: #fff; font: inherit; font-size: 13px; font-weight: 500; cursor: pointer;
  backdrop-filter: blur(6px);
  transition: background .15s, transform .1s, border-color .15s;
}
.call-min:hover { background: rgba(255, 255, 255, .3); border-color: rgba(255, 255, 255, .5); }
.call-min:active { transform: scale(.96); }
.call-min svg { flex: none; }
@media (max-width: 560px) {
  .call-min { left: 12px; top: calc(12px + env(safe-area-inset-top, 0px)); }
  /* O rótulo FICA no celular. Sem ele restava um círculo com um traço dentro,
     em cima de um fundo escuro: ninguém liga isso a "minimizar" no meio de uma
     ligação tocando. Ele encolhe, mas continua dizendo o que faz. */
  .call-min { padding: 0 14px 0 11px; font-size: 12px; }
  .call-min span { display: inline; }
}

/* A pastilha fica ACIMA de tudo e some do caminho do conteúdo. `position:
   fixed` com left/top escritos pelo arrasto — sem transform, para o cálculo do
   limite da tela bater com o que se vê. */
.call-mini {
  position: fixed; right: 18px; bottom: 18px; z-index: 350;
  display: flex; align-items: center; gap: 10px;
  background: var(--card); border: 1px solid var(--border);
  border-radius: 16px; padding: 9px 11px; box-shadow: var(--shadow-lg);
  cursor: grab; user-select: none; touch-action: none;
  animation: miniIn .22s cubic-bezier(.2, 1.2, .4, 1) both;
}
@keyframes miniIn { from { opacity: 0; transform: scale(.9); } }
.call-mini.arrastando { cursor: grabbing; box-shadow: 0 24px 60px -12px rgba(0, 0, 0, .4); }
.call-mini-av {
  width: 36px; height: 36px; flex: none; border-radius: 50%;
  background: var(--verde-esc); color: var(--ink-on-verde);
  display: flex; align-items: center; justify-content: center;
  font-weight: 500; font-size: 13px;
}
.call-mini-tx { display: flex; flex-direction: column; min-width: 0; max-width: 150px; }
.call-mini-tx b { font-size: 13px; font-weight: 500; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.call-mini-tx span { font-size: 11.5px; color: var(--muted); font-weight: 600; }
.call-mini-tx i { font-style: normal; font-variant-numeric: tabular-nums; color: var(--verde-deep); }
.call-mini-btn {
  width: 32px; height: 32px; flex: none; border-radius: 50%; border: none; cursor: pointer;
  background: var(--bg2); color: var(--text2);
  display: flex; align-items: center; justify-content: center; transition: background .15s, transform .1s;
}
.call-mini-btn svg { width: 16px; height: 16px; }
.call-mini-btn:hover { background: var(--border); }
.call-mini-btn:active { transform: scale(.92); }
.call-mini-btn.red { background: #d93a3f; color: #fff; }
.call-mini-btn.red:hover { background: #c62a30; }
.call-mini-btn.ghost { background: transparent; color: var(--muted); }
/* Atender também pela barra reduzida: com a chamada minimizada, o único jeito
   de atender era abrir o painel de novo — passos a mais nos poucos segundos
   que a ligação toca. O verde é o mesmo do botão grande. */
.call-mini-btn.green { background: #21c063; color: #fff; animation: callBtnPulse 1.4s ease-in-out infinite; }
.call-mini-btn.green:hover { background: #1aa855; }

@media (max-width: 820px) {
  /* No celular não há espaço para uma janela flutuando sobre o conteúdo: a
     chamada vira uma barra no topo, como a faixa verde do WhatsApp. Não
     arrasta — não há para onde. */
  .call-mini {
    left: 0 !important; right: 0 !important; top: 0 !important; bottom: auto !important;
    border-radius: 0; border: none; border-bottom: 1px solid var(--border);
    padding: 9px 12px; cursor: default;
    padding-top: calc(9px + env(safe-area-inset-top, 0px));
  }
  .call-mini-tx { max-width: none; flex: 1; }

  /* A barra EMPURRA o app para baixo em vez de deitar por cima dele.
     Minimizar existe para continuar usando o Koonfy durante a ligação; com a
     barra tapando o cabeçalho, sumiam o seletor de canal, a busca e as
     notificações — ou seja, minimizar tirava justamente o que ela deveria
     devolver. A altura vai numa variável porque o cabeçalho e as telas de
     altura cheia (inbox, .page) precisam descontar o mesmo valor. */
  body.em-chamada { --call-bar-h: calc(57px + env(safe-area-inset-top, 0px)); }
  body.em-chamada .topbar { margin-top: var(--call-bar-h); }
  body.em-chamada .page,
  body.em-chamada .inbox { height: calc(100dvh - var(--topbar-h) - var(--call-bar-h)); }
  body.em-chamada .sidebar { top: var(--call-bar-h); }
}

/* ===================== BOTÕES DENTRO DA MENSAGEM =====================
   Os botões que o lead recebeu, desenhados como ele os vê no WhatsApp: em
   baixo do texto, separados por uma linha, um por linha. Antes vinham
   amassados no texto como "[Sim] [Não]" e não dava para conferir um disparo. */
.msg.com-btns { padding-bottom: 0; }
.msg-btns { display: flex; flex-direction: column; margin: 6px -11px 0; }
.msg-btn {
  display: block; text-align: center; padding: 8px 10px;
  font-size: 12.5px; font-weight: 600; color: var(--verde-deep);
  border-top: 1px solid var(--border2);
}
.msg.out .msg-btn { border-top-color: rgba(6, 95, 70, .18); }
:root[data-theme="dark"] .msg-btn { color: var(--verde); }
/* a hora fica acima dos botões, como no WhatsApp */
.msg.com-btns .meta { float: none; justify-content: flex-end; margin-left: 0; }

/* ===========================================================================
   PWA INSTALADO PELO NAVEGADOR — área segura e rolagem
   ===========================================================================
   Havia regra de área segura só para `.ec-native`, que é o app das LOJAS. O
   PWA instalado pelo navegador não recebe essa classe, então rodava sem
   nenhuma proteção: o topo entrava embaixo do relógio/notch e a barra de baixo
   ficava atrás da barra de gestos do iPhone.

   `display-mode: standalone` é o que identifica um PWA aberto fora do
   navegador — vale tanto no iOS quanto no Android.
   =========================================================================== */
@media (display-mode: standalone) {
  /* A barra de gestos come a parte de baixo: os itens sobem acima dela. */
  .tabbar { padding-bottom: max(env(safe-area-inset-bottom, 0px), 6px); }

  /* Nas laterais, o recorte só existe em tela deitada — daí o `max` com 0. */
  .topbar { padding-left: max(24px, env(safe-area-inset-left, 0px)); padding-right: max(24px, env(safe-area-inset-right, 0px)); }
}

/* ---------------------------------------------------------------------------
   ROLAGEM ELÁSTICA
   No celular, puxar além do fim faz a página inteira deslizar e aparece uma
   faixa vazia por baixo do rodapé fixo — a sensação de que ele "não está
   preso". Prendendo a rolagem no contêiner que realmente rola, o elástico
   acontece DENTRO dele e as barras fixas não se mexem.
   --------------------------------------------------------------------------- */
html, body { overscroll-behavior: none; }
body { background: var(--bg); }
.page, .chat-scroll, .conv-list, main#view {
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
}

/* ---------------------------------------------------------------------------
   FOLGA PARA A BARRA DE BAIXO
   A folga estava em `main#view`, que NÃO é quem rola — quem rola é `.page`,
   e ela tem altura própria que vai até o fim da janela, ou seja, passa por
   baixo da barra fixa. O resultado era o último bloco de cada tela escondido
   atrás dos ícones: aconteceu em Assinatura, Opt-in, Agente de IA e Logs.
   A reserva vai em quem rola de verdade.
   --------------------------------------------------------------------------- */
body.has-tabbar {
  --tabbar-h: calc(58px + max(env(safe-area-inset-bottom, 0px), 4px));
}
body.has-tabbar .page { padding-bottom: calc(24px + var(--tabbar-h)); }
body.has-tabbar main#view { padding-bottom: 0; }
/* A conversa NÃO leva margem: a `.inbox` logo abaixo já encurta pela altura da
   barra, e somar a margem descontava a mesma coisa duas vezes — sobrava um vão
   morto de ~66px entre o campo de digitação e os ícones. */
body.has-tabbar .composer { margin-bottom: 0; }
/* Telas de altura fixa (conversa, construtores) encurtam em vez de ganhar
   padding — senão o rodapé delas ficaria fora da vista. */
body.has-tabbar .inbox,
body.has-tabbar .fb2,
body.has-tabbar .ck2,
body.has-tabbar .ckb { height: calc(100dvh - var(--topbar-h) - var(--tabbar-h)); }

/* ===================== COBRAR NO CELULAR =====================
   Tela de uma coisa só. O campo de valor é o maior elemento da tela porque é
   o único que sempre precisa ser preenchido — e é digitado com o cliente
   esperando na frente. */
.cel-valor { display: block; margin: 0 0 14px; }
.cel-valor > span {
  display: block; font-size: 11.5px; font-weight: 500; color: var(--muted);
  text-transform: uppercase; letter-spacing: .06em; margin-bottom: 8px;
}
.cel-valor-in { display: flex; align-items: center; gap: 8px; }
.cel-valor-in i {
  font-style: normal; font-size: 22px; font-weight: 500; color: var(--muted); flex: none;
}
.cel-valor-in input {
  flex: 1; min-width: 0; font-size: 34px !important; font-weight: 500;
  letter-spacing: -.02em; padding: 10px 14px; height: auto;
  font-variant-numeric: tabular-nums;
}
/* Atalhos de produto: o preço já entra no campo, sem digitar. */
.cel-prods { display: flex; gap: 8px; overflow-x: auto; padding-bottom: 4px; margin-top: 6px; scrollbar-width: none; }
.cel-prods::-webkit-scrollbar { display: none; }
.cel-prod {
  flex: none; display: flex; flex-direction: column; gap: 2px; text-align: left;
  padding: 9px 13px; border-radius: 12px; cursor: pointer;
  background: var(--card); border: 1px solid var(--border); font: inherit;
}
.cel-prod b { font-size: 12.5px; font-weight: 500; color: var(--text); }
.cel-prod span { font-size: 12px; font-weight: 500; color: var(--verde-deep); }
.cel-prod.on { border-color: var(--verde-esc); background: var(--brand-bg); }

.cel-pronto { border-color: var(--brand-border); }
.cel-ok {
  display: flex; align-items: center; gap: 9px; margin-bottom: 12px;
  color: var(--verde-deep); font-size: 14.5px; font-weight: 500;
}
.cel-qr {
  display: block; width: 190px; height: 190px; margin: 0 auto 14px;
  border-radius: 12px; background: #fff; padding: 8px;
}
.cel-cob .btn.block, .cel-pronto .btn.block { justify-content: center; }

/* ===================== ESCOLHA DO ADQUIRENTE ===================== */
.gw-picker { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.gw-opt {
  display: block; position: relative; margin: 0; cursor: pointer;
  padding: 14px 16px; border-radius: var(--radius-sm);
  border: 1px solid var(--border); background: var(--card);
  transition: border-color .15s, background .15s;
}
.gw-opt:hover { border-color: var(--brand-border); }
.gw-opt.on { border-color: var(--verde-esc); background: var(--brand-bg); }
.gw-opt input { position: absolute; opacity: 0; pointer-events: none; }
.gw-opt b { display: block; font-size: 14px; font-weight: 500; margin-bottom: 4px; }
.gw-opt span { display: block; font-size: 12.5px; color: var(--muted); line-height: 1.5; }
.gw-opt i { display: inline-block; margin-top: 9px; font-style: normal; }
@media (max-width: 760px) { .gw-picker { grid-template-columns: 1fr; } }

/* ---------- cobrança: dados do pagador (adquirente que exige) ---------- */
.ep-pagador { margin-top: 14px; padding: 13px 14px; border-radius: 12px; background: var(--bg2); border: 1px solid var(--border); }
.ep-pagador-top { display: flex; gap: 9px; align-items: flex-start; font-size: 12.5px; color: var(--muted); line-height: 1.5; margin-bottom: 12px; }
.ep-pagador-top svg { flex: none; margin-top: 2px; }
.ep-pagador input.bad { border-color: var(--red); }
.ep-pagador-erro { display: none; margin-top: 8px; font-size: 12.5px; font-weight: 600; color: var(--red-ink, var(--red)); }
.ep-pagador-erro.show { display: block; }
/* Aviso no lugar do "Pix copia e cola" quando o código ainda não existe: sem
   ele o espaço ficava vazio e parecia falha da cobrança. */

/* ---------- Admin → Personalização (cores da marca) ---------- */
.tema-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(270px, 1fr)); gap: 14px; }
.tema-campo label { display: block; font-size: 12.5px; font-weight: 500; color: var(--text); margin-bottom: 6px; }
.tema-ajuda { display: block; font-size: 11.5px; font-weight: 500; color: var(--muted); margin-top: 2px; }
.tema-input { display: flex; gap: 8px; align-items: center; }
/* O seletor nativo vem com moldura própria em cada sistema; aqui ele fica do
   tamanho de um botão e com o mesmo raio dos campos ao lado. */
.tema-input input[type="color"] {
  flex: none; width: 42px; height: 38px; padding: 3px; cursor: pointer;
  border: 1px solid var(--border); border-radius: 10px; background: var(--card);
}
.tema-input input[type="text"], .tema-input input:not([type]) { flex: 1; min-width: 0; text-transform: uppercase; font-variant-numeric: tabular-nums; }
.tema-input input.bad { border-color: var(--red); }
.tema-previa {
  margin-top: 18px; padding: 16px 18px; border-radius: 14px;
  background: var(--bg2); border: 1px solid var(--border);
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
}
.tema-previa-rot {
  font-size: 10px; font-weight: 500; letter-spacing: .08em; text-transform: uppercase;
  color: var(--faint); margin-right: 4px;
}
.tema-funil { display: flex; flex-wrap: wrap; gap: 12px; }
.tema-fcor { display: flex; flex-direction: column; align-items: center; gap: 4px; }
.tema-fcor input[type="color"] {
  width: 46px; height: 40px; padding: 3px; cursor: pointer;
  border: 1px solid var(--border); border-radius: 10px; background: var(--card);
}
.tema-fcor span { font-size: 10.5px; font-weight: 500; color: var(--muted); }
.tema-funil-previa .fn-etapa { margin-bottom: 2px; }

/* ---------- KYC do Koonpay: prévia das fotos ---------- */
/* Altura fixa e `contain`: documento é retrato ou paisagem conforme a pessoa
   segurou o celular, e `cover` cortaria justamente a borda onde estão os dados
   que o admin precisa ler. Melhor sobrar moldura do que faltar documento. */
.kyc-prev {
  min-height: 132px; border-radius: 10px; border: 1px dashed var(--border2);
  background: var(--bg); display: flex; flex-direction: column;
  align-items: center; justify-content: center; padding: 8px; text-align: center;
}
.kyc-prev img {
  max-width: 100%; max-height: 150px; object-fit: contain;
  border-radius: 7px; display: block;
}
/* No ADMIN a foto é o objeto da análise, e não uma miniatura: ela precisa ser
   grande o bastante para ler um documento sem abrir em outra aba. */
.kyc-foto {
  width: 100%; border-radius: 12px; border: 1px solid var(--border2);
  background: var(--bg); display: block; max-height: 460px; object-fit: contain;
}
.kyc-fila-vazia { text-align: center; padding: 30px 16px; }

/* ---------- SELETOR DE PERÍODO (gráficos) ----------
   Os atalhos de dias continuam à mão porque são o uso de todo dia; mês, ano e
   intervalo livre ficam atrás de um botão, a um clique. */
.per { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.per-btn {
  display: inline-flex; align-items: center; gap: 7px;
  height: 34px; padding: 0 12px; border-radius: 10px; cursor: pointer;
  background: var(--card); border: 1px solid var(--border); color: var(--text2);
  font: inherit; font-size: 12.5px; font-weight: 500;
  transition: border-color .15s, background .15s, color .15s;
}
.per-btn:hover { border-color: var(--border2); }
.per-btn.on { background: var(--brand-bg); border-color: var(--brand-border); color: var(--verde-deep); }
.per-btn svg { flex: none; opacity: .8; }
.per-sec {
  margin: 18px 0 8px; font-size: 10.5px; font-weight: 500;
  letter-spacing: .07em; text-transform: uppercase; color: var(--faint);
}
.per-meses { display: flex; flex-wrap: wrap; gap: 6px; }
.per-chip {
  padding: 6px 13px; border-radius: 999px; cursor: pointer;
  background: var(--bg2); border: 1px solid var(--border); color: var(--text2);
  font: inherit; font-size: 12.5px; font-weight: 500; text-transform: capitalize;
  transition: background .15s, border-color .15s, color .15s;
}
.per-chip:hover { background: var(--brand-bg); border-color: var(--brand-border); color: var(--verde-deep); }
@media (max-width: 560px) {
  .per { width: 100%; }
  .per .seg { flex: 1; }
  .per-btn { flex: 1; justify-content: center; }
}

/* O Checkout Builder usava a classe da marca só para herdar o peso do
   texto. Com a marca virando imagem, ele precisa do seu próprio estilo. */
.ckb-titulo { font-weight: 500; font-size: 20px; letter-spacing: -.015em; }
.ckb-titulo i { color: var(--verde-esc); font-style: normal; }


/* O halo do escuro fica no corpo e não rola com a página: a impressão é de
   uma sala iluminada por trás da interface, e não de um papel pintado. */
:root[data-theme="dark"] body {
  background: var(--fundo-halo) fixed;
}
:root[data-theme="dark"] .page, :root[data-theme="dark"] .inbox {
  background: transparent;
}


/* ---------- botão brilhante (Admin SaaS → Personalização) ---------- */
/* A prévia do botão que a página pública usa. A faixa de luz atravessa porque
   o gradiente é o dobro do botão: o que anda é a POSIÇÃO dele. */
.btn-brilho {
  border: 0; cursor: pointer; font: 500 15px/1.2 var(--font); color: #fff;
  padding: 13px 26px; border-radius: 4px;
  background: linear-gradient(45deg, #1c834a, #1c834a, #2ed378, #1c834a, #1c834a);
  background-size: 200% 200%; animation: brilhoPassar 5s ease-in-out infinite;
}
/* ---------------------------------------------------------------------------
   ERRO NO FLOW BUILDER — A BORDA ACUSA, O COMPONENTE FICA COMO ESTÁ
   Mesma faixa de luz do botão brilhante verde, em vermelho. É BORDA e só: o
   balão continua com a cor dele, e os botões com a cor deles. Pintar o
   componente inteiro de vermelho esconderia justamente o que a pessoa precisa
   olhar para entender o erro.
   O truque é um degradê no FUNDO do elemento externo, com o miolo por cima
   opaco — assim a moldura anima e o conteúdo não.
   --------------------------------------------------------------------------- */
.fb-erro {
  position: relative; border-radius: 14px; padding: 2px;
  background: linear-gradient(45deg, #b42318, #b42318, #ff6b5e, #b42318, #b42318);
  background-size: 200% 200%; animation: brilhoPassar 3.2s ease-in-out infinite;
}
/* UM FILHO SÓ. Aplicado direto num `<details>`, o `> *` pegava o resumo, cada
   rótulo e o parágrafo, e cada um ganhava fundo próprio — a moldura saía
   listrada em vez de contínua. Por isso quem recebe a classe é sempre um
   invólucro com um único filho dentro. */
.fb-erro > * { position: relative; border-radius: 12px; background: var(--card); display: block; }
.fb-erro > .utm-box { padding: 10px 12px; }
@media (prefers-reduced-motion: reduce) { .fb-erro { animation: none; } }

/* A mensagem fica colada no que está errado, e diz o que fazer. */
.fb-erro-msg {
  display: flex; align-items: flex-start; gap: 7px;
  margin-top: 7px; padding: 8px 10px; border-radius: 9px;
  background: var(--red-bg); border: 1px solid var(--red-border);
  font-size: 11.5px; line-height: 1.45; color: var(--red);
}
.fb-erro-msg svg { flex: none; margin-top: 1px; }
.fb-erro-msg b { font-weight: 600; }
.fb-erro-msg button {
  margin-top: 5px; padding: 5px 9px; border-radius: 7px; cursor: pointer;
  border: 1px solid var(--red-border); background: var(--card); color: var(--red);
  font-size: 11px; font-weight: 600;
}
.fb-erro-msg button:hover { background: var(--red-bg); }

/* O card do nó com problema ganha a mesma moldura, no canvas. */
.fb-n.tem-erro { box-shadow: 0 0 0 2px #b42318, 0 8px 22px -12px rgba(180, 35, 24, .5); }

@keyframes brilhoPassar {
  0% { background-position: 0% 50% } 50% { background-position: 100% 50% } 100% { background-position: 0% 50% }
}
/* Linha de interruptor: caixa + rótulo, alinhados pelo texto. */
.sw-row { display: flex; align-items: center; gap: 10px; font-size: 13.5px; cursor: pointer; }
.sw-row input { accent-color: var(--verde-esc); width: 16px; height: 16px; flex: none; }
.sw-row i { font-style: normal; font-size: 12.5px; }
@media (prefers-reduced-motion: reduce) { .btn-brilho { animation: none } }


/* ---------- escolha do botão, no Checkout Builder ---------- */
.epk-btnkind { display: flex; gap: 10px; }
.epk-bk {
  flex: 1; display: flex; align-items: center; justify-content: center; gap: 9px;
  padding: 11px; border: 1.5px solid var(--border); border-radius: 11px;
  background: var(--bg2); font: 500 13px/1 var(--font); color: var(--text2); cursor: pointer;
  transition: border-color .15s, color .15s;
}
.epk-bk.on { border-color: var(--verde-esc); color: var(--text); }
.epk-bk-demo { width: 26px; height: 14px; border-radius: 4px; flex: none; background: var(--c, #2ed378); }
/* O exemplo brilhante roda a mesma animação do botão real, para a escolha ser
   feita vendo o efeito e não lendo a palavra "brilhante". */
.epk-bk-demo.brilha {
  background: linear-gradient(45deg, color-mix(in srgb, var(--c) 55%, #000), color-mix(in srgb, var(--c) 55%, #000),
              var(--c), color-mix(in srgb, var(--c) 55%, #000), color-mix(in srgb, var(--c) 55%, #000));
  background-size: 200% 200%; animation: brilhoPassar 5s ease-in-out infinite;
}
@media (prefers-reduced-motion: reduce) { .epk-bk-demo.brilha { animation: none } }


/* ---------- a porta de entrada usa o botão da vitrine ---------- */
/* A tela de login é a emenda entre a página de vendas e o produto: o botão
   ali é o mesmo "Começar agora", montado no Admin (Personalização → Botão
   brilhante) e servido em /tema.css. Dentro do app os botões continuam
   chapados: animação em cada salvar viraria ruído numa tela de trabalho. */
/* A TELA DE MANUTENÇÃO ENTRA AQUI JUNTO: é a mesma situação — porta de
   entrada, botão único —, e sem esta linha ele saía chapado justamente onde é
   o único caminho da tela. */
#login .btn.primary, #manutencao .btn.primary {
  background: var(--btn-grad, var(--btn-verde));
  background-size: 200% 200%;
  border-color: transparent;
  box-shadow: none;
  animation: brilhoPassar 5s ease-in-out infinite;
}
#login .btn.primary:hover,
#manutencao .btn.primary:hover { background: var(--btn-grad, var(--btn-verde-hover)); opacity: .93; }
@media (prefers-reduced-motion: reduce) {
  #login .btn.primary, #manutencao .btn.primary { animation: none }
}


/* ---------- o dia no painel, e o texto do botao de cobrar ---------- */
/* No painel a pergunta e "e hoje?": o lugar dos atalhos de dias e ocupado pela
   DATA, que nao e botao — nao ha o que clicar ali, so o que ler. */
.per-hoje {
  display: inline-flex; align-items: center; gap: 7px;
  background: var(--bg2); border: 1px solid var(--border); border-radius: 10px;
  padding: 8px 13px; font-size: 13px; font-weight: 500; color: var(--text);
  white-space: nowrap;
}
.per-hoje svg { color: var(--verde-esc); flex: none; }

/* O rotulo do botao de pagar, na tela de cobranca. A regra fica embaixo do
   campo e vira contagem regressiva enquanto se digita. */
.ep-botao-campo { margin-top: 12px; }
.ep-botao-regra {
  margin-top: 6px; font-size: 12px; line-height: 1.5; color: var(--muted);
  display: flex; align-items: flex-start; gap: 6px;
}
.ep-botao-regra svg { flex: none; margin-top: 2px; }
.ep-botao-regra b { color: var(--text2); font-weight: 500; }
.ep-botao-regra.perto b { color: var(--amber-ink, #b45309); }


/* ==========================================================================
   MODAIS NO CELULAR

   Tres coisas empurravam o conteudo para fora da caixa, e nenhuma delas tinha
   ponto de quebra:

   · .row obrigava cada filho a 140px de largura minima. Duas datas lado a
     lado pediam 290px, e a caixa oferece 287 num aparelho de 375 — o par
     estourava por tres pixels e a linha inteira vazava;
   · a caixa tinha 20px de respiro de cada lado, o que num aparelho estreito
     e um quinto da largura util gasto em margem.

   A regra e a mesma nos tres casos: no estreito, uma coluna. Duas colunas de
   150px nao sao duas colunas, sao duas ilegiveis.
   ========================================================================== */
@media (max-width: 620px) {
  .modal-back { padding: 12px; }
  .modal { padding: 18px 16px; max-height: 92vh; }
  /* O minimo de 140px era o que fazia o par de datas vazar. Solto, cada campo
     ocupa o que couber e a linha quebra sozinha quando precisa. */
  .row > * { min-width: 0; }
  .row { gap: 12px; }
  /* Nenhum modal rola para o lado: o que nao couber quebra ou encolhe. */
  .modal, .modal * { max-width: 100%; }
  .modal img, .modal svg, .modal canvas { height: auto; }
}

/* ============================================================
   TABELA QUE VIRA CARTÃO NO CELULAR

   Cinco colunas em 375px rolam de lado dentro do card: o dado está lá, mas
   ler exige arrastar para um lado e de volta, e o cabeçalho fica para trás.
   Aqui cada linha vira um bloco e o rótulo da coluna (o `data-r` do td)
   aparece ao lado do valor. No computador nada muda.

   Os seletores incluem `.card` e miram `table.tab-mob` de propósito: o
   tratamento geral de tabela no celular (`.card table thead`) tem peso maior
   que `.tab-mob thead` e ganharia, mesmo estando antes no arquivo.
   ============================================================ */
@media (max-width: 820px) {
  .card table.tab-mob thead { display: none; }
  .card table.tab-mob,
  .card table.tab-mob tbody,
  .card table.tab-mob tr,
  .card table.tab-mob td { display: block; width: 100%; min-width: 0; }
  .card table.tab-mob tr {
    border: 1px solid var(--border2); border-radius: 12px;
    padding: 12px 14px; margin-bottom: 10px; background: var(--card);
  }
  .card table.tab-mob tr:last-child { margin-bottom: 0; }
  .card table.tab-mob td {
    border: 0; padding: 5px 0; text-align: left !important;
    display: flex; align-items: baseline; justify-content: space-between; gap: 14px;
  }
  /* O rótulo vem do próprio td, então a coluna nunca se perde do valor. */
  .card table.tab-mob td[data-r]::before {
    content: attr(data-r); color: var(--text3); font-size: 12px;
    letter-spacing: .03em; text-transform: uppercase; flex: none;
  }
  /* A primeira célula é o título do cartão: ocupa a linha inteira. */
  .card table.tab-mob td:first-child {
    display: block; padding-top: 0; padding-bottom: 8px;
    margin-bottom: 6px; border-bottom: 1px solid var(--border);
  }
  /* E o título não leva etiqueta. Sendo bloco, o rótulo colava no valor
     ("CONTAPadaria do Zé") — e pôr `data-r` na primeira coluna é o que
     qualquer um faz, já que todas as outras levam. */
  .card table.tab-mob td:first-child::before { content: none; }
  /* Célula sem rótulo e sem conteúdo (a coluna dos botões) não vira linha. */
  .card table.tab-mob td:empty { display: none; }
  /* Sem largura mínima, o container não precisa rolar. */
  .tab-mob-wrap { overflow-x: visible !important; }
}


/* ============================================================
   BANNERS DA DASHBOARD (carrossel)

   Uma faixa de avisos no topo da dashboard. A ilusão de 3D vem de uma peça
   que ATRAVESSA a borda do cartão: o fundo colorido fica num elemento que
   recorta (para o gradiente respeitar o canto), e a peça fica FORA desse
   recorte. Sem essa separação, ou o gradiente vaza dos cantos ou a peça é
   cortada na borda — e aí o objeto parece colado num retângulo.
   ============================================================ */
.bnr-wrap { position: relative; margin: 0 0 20px; }
/* A JANELA PRECISA CONTER O TRILHO — e conter é `overflow`, não `clip-path`.

   Os dois escondem o slide vizinho, mas escondem coisas diferentes:
   `overflow` contém o LAYOUT, `clip-path` só recorta a PINTURA. Com
   `clip-path`, o trilho de cinco slides continuava ocupando cinco larguras de
   tela: a página ficava arrastável para o lado e o que aparecia lá era o
   fundo, branco, porque a arte dos vizinhos estava recortada. Medido no
   celular: `.page` com 375 de largura visível e 667 de conteúdo.

   O `overflow: hidden` volta, e a peça 3D continua atravessando a borda do
   cartão porque o recorte acontece no PADDING BOX: os 48px de padding são a
   folga por onde ela sai, e a margem negativa do mesmo tamanho devolve o
   espaço para o carrossel não ficar 96px mais alto do que precisa. */
.bnr-janela { overflow: hidden; padding: 48px 0; margin: -48px 0; }
/* O trilho anda de um slide por vez. `translate3d` para a animação não
   engasgar em celular mais fraco. */
.bnr-trilho { display: flex; transition: transform .5s cubic-bezier(.22,1,.36,1); }
.bnr {
  position: relative; flex: 0 0 100%; min-width: 100%;
  /* Cada slide também recorta as próprias laterais. A janela sozinha não
     resolve: a peça do vizinho é girada, e o retângulo dela entrava 2px
     para dentro do quadro (medido: 30 contra 28). São dois pixels de arte
     alheia colados na borda esquerda o tempo todo. */
  clip-path: inset(-48px 0px);
  /* A ALTURA é fixa por faixa de tela: com altura automática o carrossel
     pula de tamanho a cada troca de slide, porque cada texto tem um
     comprimento. */
  height: 234px;
}
/* A FOLGA é por onde a peça sai do cartão. A de BAIXO é maior: o cartão
   ganha ar embaixo em vez de terminar numa listra colada, e a peça que sai
   por ali tem para onde ir. */
:root { --bnr-folga: 18px; --bnr-folga-base: 42px; }
.bnr-fundo {
  position: absolute; inset: var(--bnr-folga) 0 var(--bnr-folga-base); border-radius: 16px; overflow: hidden;
  /* SEM SOMBRA. Era ela a faixa cinza embaixo do cartão — medida, não
     suposta: o tom da faixa ficava entre o fundo da página e um cinza de
     teste. E nenhum outro cartão da Koonfy tem sombra: missões, números e
     atalhos são chapados com um fio de borda. Um borrão difuso embaixo de um
     cartão preto, numa página clara e chapada, não lê como profundidade —
     lê como uma segunda faixa colada. Quem sustenta o cartão aqui é o fio de
     borda e a peça que atravessa a borda de baixo. */
  background: #0b1a12;   /* o que aparece enquanto a arte carrega */
}
/* A BORDA. Um fio claro por cima da arte fecha o contorno do cartão: sem ele
   a arte escura simplesmente acaba, e o fim de uma imagem parece corte. Vem
   de um pseudo-elemento porque `box-shadow: inset` ficaria por baixo do
   <img> de fundo, que é filho. */
.bnr-fundo::after {
  content: ''; position: absolute; inset: 0; border-radius: inherit;
  border: 1px solid rgba(255, 255, 255, .10); pointer-events: none;
}
.bnr-bg { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
/* O VÉU. Escurece só o lado do texto, e some antes da metade: a arte fica
   inteira à direita, onde a peça 3D flutua. */
.bnr-veu {
  position: absolute; inset: 0;
  background: linear-gradient(90deg, rgba(6,20,13,.88) 0%, rgba(6,20,13,.72) 34%, rgba(6,20,13,0) 68%);
}
/* O brilho decorativo saiu: a arte de fundo já traz a própria luz, e dois
   focos brigando deixavam a direita lavada. */
.bnr-txt {
  position: absolute; inset: var(--bnr-folga) 0 var(--bnr-folga-base); z-index: 2;
  display: flex; flex-direction: column; justify-content: center; gap: 8px;
  padding: 0 clamp(20px, 4vw, 38px); max-width: 62%;
}
.bnr-tag {
  font-size: 11px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase;
  color: rgba(255,255,255,.82);
}
.bnr-txt h3 { margin: 0; font-size: clamp(17px, 2.2vw, 23px); line-height: 1.2; color: #fff; letter-spacing: -.02em; }
.bnr-txt p { margin: 0; font-size: 13.5px; line-height: 1.45; color: rgba(255,255,255,.86); }
.bnr-btn {
  align-self: flex-start; margin-top: 4px; border: 0; cursor: pointer;
  background: #fff; color: #10241a; font: 600 13px/1 inherit;
  padding: 10px 16px; border-radius: 9px; text-decoration: none;
  display: inline-flex; align-items: center; gap: 7px; transition: transform .15s;
}
.bnr-btn:hover { transform: translateY(-1px); }

/* A PEÇA QUE SAI DO CARTÃO. Fora do `.bnr-fundo`, então não é recortada. */
/* Medida pela ALTURA: cada arte tem uma proporção, e fixar a largura fazia as
   mais altas passarem da janela — que corta. Assim todas atravessam a borda
   do cartão e param dentro da janela. */
.bnr-3d {
  position: absolute; z-index: 3; right: 4%; top: 7px;
  height: 200px; width: auto; pointer-events: none;
  filter: drop-shadow(0 12px 20px rgba(0,0,0,.30));
  transform: rotate(-8deg);
  animation: bnrFlutua 6s ease-in-out infinite;
}
/* Uma segunda peça, menor, saindo pelo TOPO: duas alturas diferentes vendem
   a profundidade melhor que uma só. */
/* A segunda peça sai pela BASE, no lado oposto: duas alturas e dois sentidos
   vendem a profundidade melhor que um objeto só. */
.bnr-3d.mini {
  right: 30%; top: auto; bottom: 2px; width: 78px;
  transform: rotate(14deg); animation-delay: -3s; opacity: .92;
}
/* A PEÇA QUE POUSA NO CENTRO DA ARTE.

   Duas artes têm um centro de verdade — o miolo das ondas na Ligação e o alvo
   no Tracking — e ali a peça no canto ficava do LADO do assunto em vez de
   dentro dele. Com o foco, o telefone senta no meio das ondas e a mira no meio
   do alvo: a arte e o objeto viram uma imagem só, em vez de dois desenhos
   dividindo o mesmo cartão.

   O ponto vem em % do ARQUIVO do fundo (src/bannersarte.js). Como o fundo é
   `object-fit: cover` e o cartão é muito mais largo que a arte, o corte é só em
   cima e embaixo: a coordenada X do arquivo vale como X do cartão, e o Y, que
   nas duas fica em ~49%, cai no meio da faixa visível de qualquer jeito.

   `right: auto` NÃO é enfeite: sem ele a regra de cima continua valendo e o
   elemento fica preso pelos DOIS lados, esticado em vez de posicionado. */
.bnr-3d.focada {
  left: var(--foco-x); top: var(--foco-y); right: auto; bottom: auto;
  transform: translate(-50%, -50%) rotate(-6deg);
}

@keyframes bnrFlutua {
  0%, 100% { translate: 0 0; }
  50% { translate: 0 -9px; }
}

.bnr-pontos { display: flex; gap: 7px; justify-content: center; margin-top: 12px; }
.bnr-pontos button {
  width: 7px; height: 7px; padding: 0; border: 0; border-radius: 50%;
  background: var(--border2); cursor: pointer; transition: all .25s;
}
.bnr-pontos button.on { width: 22px; border-radius: 4px; background: var(--verde-deep); }

/* ---- TABLET: o texto cede espaço, a peça encolhe ---- */
@media (max-width: 900px) {
  :root { --bnr-folga: 14px; --bnr-folga-base: 36px; }
  /* Dois pixels de folga com o texto mais longo dos exemplos e pouco: quando o
     conteudo passar a ser escrito no Admin, uma frase maior estouraria. */
  .bnr { height: 228px; }
  .bnr-txt { max-width: 66%; }
  .bnr-3d { height: 198px; width: auto; right: 3%; }
  .bnr-3d.mini { width: 64px; right: 28%; }
}

/* ---- CELULAR ----
   A peça grande sai da direita e vira uma marca d'água no canto: com 375px
   de largura ela e o texto disputariam o mesmo espaço, e quem perde é o
   texto, que é o que a pessoa precisa ler. A segunda peça some: duas peças
   numa tela estreita viram sujeira. */
@media (max-width: 620px) {
  /* FOLGA ZERO. Ela existia para a peça sair do cartão; sem peça saindo,
     ela é só uma listra clara colada num cartão escuro — a "divisória" que
     aparecia na tela do celular. O cartão passa a ocupar o slide inteiro e
     não sobra faixa nenhuma. */
  :root { --bnr-folga: 0px; --bnr-folga-base: 0px; }
  /* No celular o banner NAO encosta nas bordas da tela: coladas nos cantos as
     laterais somem e o cartao vira uma faixa presa, sem forma. O respiro
     tambem separa o carrossel do resto da tela, que rola por baixo dele. */
  .bnr-wrap { margin-left: 14px; margin-right: 14px; }
  /* Mais alto no celular: com a largura do texto reduzida para nao bater na
     peca, a mesma frase ocupa quatro linhas em vez de duas — e o cartao
     precisa caber o texto, nao o contrario. */
  .bnr { height: 212px; }
  /* Com a peça menor, o texto recupera largura e a frase volta a caber em
     três linhas em vez de quatro. */
  .bnr-txt { max-width: 64%; padding: 0 18px; }
  .bnr-txt h3 { font-size: 16px; }
  .bnr-txt p { font-size: 12.5px; }
  /* Numa tela estreita a peça e o texto disputam o mesmo espaço, e quem
     perde é o texto — que é o que a pessoa precisa ler. Ela vira marca
     d'água no canto, e a segunda some: duas peças em 375px viram sujeira. */
  /* TEMPERO, NÃO ASSUNTO. Com 150px de altura a peça ocupava metade da
     largura do cartão e virava o assunto do banner. Em 118 ela acompanha o
     texto em vez de disputar com ele, e continua saindo pela direita e por
     baixo — que é o que dá o volume. */
  /* DENTRO DO CARTÃO, ao lado do texto e do botão, centrada na vertical.
     Numa tela de 375px o objeto que atravessa a borda não tem para onde ir:
     ou é cortado pelo carrossel, ou cai em cima do vizinho, ou obriga a uma
     faixa clara embaixo. Aqui ela é ilustração, e ilustração mora dentro. */
  .bnr-3d {
    /* Medida pela LARGURA aqui, ao contrário das telas grandes. Lá o que não
       pode passar é a altura, porque a peça atravessa a borda; aqui o que não
       pode passar é a largura, porque do lado esquerdo está o texto. Com
       altura fixa a peça mais larga chegava a 105 e encostava na frase.
       Medido nos cinco banners: 0 a 19px de sobra; agora 9 no pior caso. */
    width: 96px; height: auto; right: 10px; top: 50%; bottom: auto;
    transform: translateY(-50%); opacity: .96;
    filter: drop-shadow(0 8px 16px rgba(0,0,0,.28));
    /* FLUTUA IGUAL AO COMPUTADOR, no lugar do celular.
       Eu tinha parado a animação aqui achando que, sem borda para atravessar,
       ela viraria tremor. Não vira: o que dá vida ao objeto é ele não estar
       preso ao cartão, e isso vale dentro também — o cartão e a peça são
       planos diferentes, e só o de cima se mexe.
       A centragem continua sendo `transform: translateY(-50%)`, e a animação
       usa a propriedade `translate`, que é OUTRA e se compõe com ela (o
       navegador aplica translate antes de transform). Por isso a peça sobe e
       desce sem sair do meio — animar `transform` aqui apagaria a centragem e
       jogaria a peça para baixo. */
    animation: bnrFlutua 6s ease-in-out infinite;
  }
  /* A PEÇA FOCADA TAMBÉM NO CELULAR — é o mesmo desenho, e é isso que faz o
     banner ser o mesmo nos dois lugares. Só o tamanho muda, porque a tela é
     estreita; o ponto onde ela pousa é o mesmo. */
  .bnr-3d.focada {
    left: var(--foco-x); top: var(--foco-y); right: auto; bottom: auto;
    transform: translate(-50%, -50%);
  }
  .bnr-3d.mini { display: none; }
  .bnr-wrap { margin-bottom: 16px; }
}

@media (prefers-reduced-motion: reduce) {
  .bnr-trilho { transition: none; }
  .bnr-3d { animation: none; }
}




/* ============================================================
   RELATORIO AO VIVO DO DISPARO — as duas pecas que o app ainda
   nao tinha. O resto do relatorio usa os componentes de sempre.
   Ficam AQUI, e nao numa folha propria, porque a pagina publica
   do link de acompanhamento carrega esta folha: assim ela sai
   identica ao painel, com o mesmo tema claro e escuro.
   ============================================================ */

/* O SELO AO VIVO. Um numero que muda sozinho nao avisa que mudou: quem esta
   olhando o relatorio nao ve o instante. O ponto piscando diz "isto esta
   acontecendo agora" sem precisar de texto. */
.bi-vivo {
  display: inline-flex; align-items: center; gap: 7px; flex-shrink: 0;
  padding: 6px 12px; border-radius: 999px;
  background: var(--brand-bg); color: var(--verde-deep);
  font-size: 11.5px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase;
}
.bi-vivo i { width: 8px; height: 8px; border-radius: 50%; background: var(--verde-esc); animation: biPulso 1.6s ease-in-out infinite; }
.bi-vivo.fim { background: var(--bg2); color: var(--muted); }
.bi-vivo.fim i { background: var(--muted); animation: none; }
@keyframes biPulso {
  0%, 100% { opacity: 1; box-shadow: 0 0 0 0 rgba(46, 211, 120, .5); }
  50% { opacity: .55; box-shadow: 0 0 0 7px rgba(46, 211, 120, 0); }
}
@media (prefers-reduced-motion: reduce) { .bi-vivo i { animation: none } }

/* O BALAO DA RESPOSTA. E fala do cliente, e no app inteiro fala de cliente
   tem forma de balao — no chat, na previa do template, no checkout. Uma
   celula de tabela com texto solto aqui pareceria outro produto. */
.bi-resp {
  display: block; max-width: 420px; padding: 8px 11px;
  border-radius: 12px 12px 12px 3px; background: var(--bg2);
  font-size: 12.5px; line-height: 1.45; color: var(--text);
}
.bi-resp time { display: block; margin-top: 3px; font-size: 11px; color: var(--muted); }


/* ============================================================
   EDITOR DOS BANNERS (painel da plataforma)
   Um cartao por banner, na ordem em que aparecem no carrossel.
   O desligado fica APAGADO e nao escondido: campanha que acabou
   costuma voltar, e o que some da tela some da cabeca.
   ============================================================ */
.bnr-edit {
  border: 1px solid var(--border); border-radius: 12px;
  padding: 14px 16px 16px; margin-bottom: 12px; background: var(--card);
  transition: opacity .2s, border-color .2s;
}
.bnr-edit.off { opacity: .55; border-style: dashed; }
.bnr-edit label { margin-top: 10px; }
.bnr-edit .row > label { margin-top: 10px; }
.bnr-edit textarea { resize: vertical; min-height: 54px; }


/* ===========================================================================
   HUB DE INTEGRAÇÕES (Admin SaaS → Integrações)
   ---------------------------------------------------------------------------
   A aba era uma pilha vertical de cartões de configuração, e achar a Nuvemshop
   no meio dela era rolar até reconhecer o título. Uma marca se reconhece pelo
   DESENHO dela, não pelo nome escrito em corpo 14 — então a aba passou a abrir
   por uma grade de logos, e o painel de configuração aparece embaixo só depois
   de escolhido.

   O LADRILHO É UM BOTÃO, e não um cartão decorativo: tem estado (aria-pressed),
   foco visível pelo teclado e alvo grande o suficiente para o dedo. Grade de
   140px porque um logo de 32px com nome e status abaixo não cabe em menos sem
   quebrar o nome no meio da palavra.
   =========================================================================== */
.int-hub {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
  gap: 10px; margin-bottom: 18px;
}
.int-tile {
  display: flex; flex-direction: column; align-items: center; gap: 7px;
  padding: 16px 10px 13px; text-align: center; cursor: pointer;
  background: var(--card); border: 1px solid var(--border); border-radius: 12px;
  transition: border-color .16s, box-shadow .16s, transform .16s;
  font: inherit; color: inherit;
}
.int-tile:hover { border-color: var(--border2); box-shadow: var(--shadow); transform: translateY(-2px); }
.int-tile:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
/* O selecionado fica com a borda da marca E um fundo de apoio: só a borda some
   para quem enxerga pouco contraste, e a pessoa perde de vista o que abriu. */
.int-tile[aria-pressed="true"] {
  border-color: var(--brand); background: var(--brand-bg);
}
.int-tile img, .int-tile .int-mono, .int-tile .int-ic {
  width: 32px; height: 32px; border-radius: 7px; flex: none; object-fit: contain;
}
/* MONOGRAMA — o que aparece quando não temos o logo da marca. Não é uma
   tentativa de imitar a identidade de ninguém: são as iniciais num quadrado
   neutro, e some sozinho no dia em que o arquivo certo for colocado na pasta. */
.int-mono {
  display: flex; align-items: center; justify-content: center;
  background: var(--bg2); color: var(--muted); border: 1px solid var(--border);
  font-size: 12px; font-weight: 700; letter-spacing: .5px;
}
.int-ic { display: flex; align-items: center; justify-content: center; color: var(--muted); }
.int-tile b { font-size: 12.5px; line-height: 1.25; font-weight: 600; }
.int-tile .int-sub { font-size: 11px; color: var(--muted); line-height: 1.3; }
/* O status é um ponto, e não um texto: em doze ladrilhos, doze etiquetas
   escritas viram ruído e nenhuma é lida. */
.int-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--border2); flex: none; }
.int-dot.on { background: var(--brand); }
.int-dot.meio { background: var(--amber); }
.int-st { display: flex; align-items: center; gap: 5px; font-size: 10.5px; color: var(--muted); }
/* Os ATALHOS levam para outra aba e não configuram nada aqui. Ficam mais
   apagados de propósito: pareceriam integrações desligadas se tivessem o mesmo
   peso visual dos ladrilhos de verdade. */
.int-tile.atalho { border-style: dashed; }
.int-tile.atalho b { font-weight: 500; color: var(--muted); }
@media (max-width: 820px) {
  .int-hub { grid-template-columns: repeat(auto-fill, minmax(108px, 1fr)); gap: 8px; }
  .int-tile { padding: 13px 7px 11px; }
}
