:root{
  /* Anchored on the animal: the tan is the brand, and green/amber/red stay
     reserved for what a status actually means. Reusing the brand colour for
     "connected" would make the two impossible to tell apart at a glance. */
  --brand:#c9986a; --brand-ink:#2a1d10; --brand-soft:rgba(201,152,106,.14);
  --bg:#101219; --panel:#171a22; --panel-2:#1e222c; --panel-3:#252a36;
  --line:#2a2f3b; --line-soft:#212632;
  --ink:#e9ebf1; --ink-dim:#b6bcc9; --muted:#8a92a3;
  --ok:#4ade80; --ok-soft:rgba(74,222,128,.12);
  --warn:#f0b429; --warn-soft:rgba(240,180,41,.12);
  --danger:#f2686d; --danger-soft:rgba(242,104,109,.12);
  /* --radius para superfícies (cartão, janela, aviso); --radius-sm para
     controles (botão, campo, item de menu). Eram 7, 8 e 9px lado a lado. */
  --radius:10px; --radius-sm:8px;
  --sidebar:236px;
  /* O padrão (revisão de UI, 23/10/2026): espaços e tamanhos de texto numa
     escala só. Uma tela nova usa estes, e não números escritos à mão; eram
     doze tamanhos de letra diferentes espalhados pelos templates. */
  --s-1:4px; --s-2:8px; --s-3:12px; --s-4:16px; --s-5:24px; --s-6:32px;
  --t-xs:12px; --t-sm:13px; --t-md:15px; --t-lg:20px; --t-xl:27px;
  --info:#7aa7ff; --info-soft:rgba(122,167,255,.12);
  /* A borda de um campo: --line some contra o fundo dele (1,19:1), e um
     limite de controle precisa de 3:1. */
  --line-strong:#6b7385;
  /* Cada tom de estado com uma borda e um texto só. O texto (-ink) é o tom
     claro, legível sobre o fundo -soft; antes cada componente tinha o seu. */
  --ok-ink:#6ee79a; --warn-ink:#f5c455; --danger-ink:#f58a8e;
  --ok-line:rgba(74,222,128,.3); --warn-line:rgba(240,180,41,.3);
  --danger-line:rgba(242,104,109,.3); --brand-line:rgba(201,152,106,.3);
  --info-line:rgba(122,167,255,.3);
  /* As séries dos gráficos, na ordem em que se usam, mais a do período
     comparado e a do "não informado". Os gráficos do Go usam os mesmos. */
  --viz-1:#3987e5; --viz-2:#d95926; --viz-3:#199e70; --viz-4:#9085e9;
  --viz-compare:#8a92a3; --viz-na:#5d6474;
  /* Durações: a resposta a um toque, uma entrada, um desenho. */
  --dur-fast:.12s; --dur:.2s; --dur-slow:.6s;
  /* As camadas, de baixo para cima: o que gruda no alto ao rolar, a dica
     aberta, o aviso do canto e a barra de progresso. */
  --z-sticky:20; --z-pop:40; --z-toast:900; --z-progress:1000;
  /* O QR precisa de fundo claro para a câmera ler, mesmo no tema escuro. */
  --qr-bg:#fff;
  /* Native widgets — checkboxes, selects, scrollbars — render light unless
     told otherwise, which reads as a bug on a dark page. */
  color-scheme:dark;
  accent-color:var(--brand);
}
*{box-sizing:border-box}
/* The UA stylesheet hides [hidden] with a plain display:none, which any
   inline display wins against — so an element with style="display:flex"
   stays visible however many times you set .hidden = true. */
[hidden]{display:none !important}
html,body{height:100%}
body{margin:0;background:var(--bg);color:var(--ink);
     font:14px/1.55 -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Inter,sans-serif;
     -webkit-font-smoothing:antialiased}
a{color:inherit;text-decoration:none}
/* Um link no meio de uma frase precisa se ver: sem cor própria, só o
   sublinhado o separa do texto. Botões e cartões com cara de link ficam de
   fora. */
/* :where, sem peso: um link com estilo próprio (a.drill, .tabs a) vence. */
:where(p,li,td.text) a:where(:not(.btn,.card,.banner,.tag)){text-decoration:underline;text-underline-offset:2px}
::selection{background:var(--brand);color:var(--brand-ink)}

/* O foco do teclado, um só em toda a aplicação: cada navegador desenhava o
   seu, e no mesmo formulário apareciam três estilos de anel. Campos têm o
   deles (borda e halo), mais abaixo. */
:is(a,summary,[tabindex]):focus-visible,.btn:focus-visible,.dialog-close:focus-visible{
  outline:2px solid var(--brand);outline-offset:2px}
/* Só para leitor de tela: some da vista, não da leitura. */
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;
         clip:rect(0 0 0 0);white-space:nowrap;border:0}
/* O atalho para pular a barra lateral: aparece só quando recebe o foco. */
.skip{position:absolute;left:var(--s-2);top:var(--s-2);z-index:var(--z-progress);
      padding:var(--s-2) var(--s-3);border-radius:var(--radius-sm);
      background:var(--brand);color:var(--brand-ink);font-weight:650;transform:translateY(-200%)}
.skip:focus{transform:none}
main:focus{outline:none}
.nowrap{white-space:nowrap}

/* ---------- shell ---------- */
.shell{display:grid;grid-template-columns:var(--sidebar) 1fr;min-height:100%}
aside{background:var(--panel);border-right:1px solid var(--line);
      display:flex;flex-direction:column;position:sticky;top:0;height:100vh}
.brand{display:flex;align-items:center;gap:var(--s-2);padding:var(--s-4)}
.brand .name{font-weight:650;letter-spacing:-.3px;line-height:1.1}
.brand .name small{display:block;font-weight:400;font-size:var(--t-xs);color:var(--muted);
                   letter-spacing:.3px;line-height:1.3;margin-top:2px}
nav{padding:var(--s-1) var(--s-2);display:flex;flex-direction:column;gap:2px;overflow-y:auto;flex:1}
nav .group{padding:var(--s-4) var(--s-3) var(--s-1)}
nav a{display:flex;align-items:center;gap:var(--s-2);padding:var(--s-2) var(--s-3);border-radius:var(--radius-sm);
      color:var(--ink-dim);font-weight:500}
/* O anel por dentro: a lista rola, e o de fora era cortado nas bordas. */
nav a:focus-visible{outline-offset:-2px}
nav a:hover{background:var(--panel-2);color:var(--ink)}
nav a.on{background:var(--brand-soft);color:var(--brand)}
/* O sino dos avisos, ao lado da marca. */
.aside-top{display:flex;align-items:center;justify-content:space-between;padding-right:var(--s-2)}
/* A marca cede espaço ao sino; o slogan quebra em duas linhas em vez de
   sair cortado no meio ("Do anúncio à venda n…" não dizia nada). */
.aside-top .brand{flex:1;min-width:0;padding-right:var(--s-1)}
.aside-top .brand .name{min-width:0}
/* No celular a barra de cima tem o sino e o Menu: o slogan sai dela. */
@media (max-width:720px){.aside-top .brand .name small{display:none}}
.logo-mark{display:block;flex:none}
.bell{position:relative;flex:none;display:inline-flex;align-items:center;justify-content:center;
      width:32px;height:32px;border-radius:var(--radius-sm);color:var(--ink-dim)}
.bell:hover{background:var(--panel-2);color:var(--ink)}
.bell.on{background:var(--brand-soft);color:var(--brand)}
.bell svg{width:19px;height:19px}
/* Texto escuro sobre o vermelho: o branco dava 3:1 nesse tamanho. */
.bell-badge{position:absolute;top:-3px;right:-4px;min-width:18px;height:18px;padding:0 5px;border-radius:99px;
            display:inline-flex;align-items:center;justify-content:center;font-size:var(--t-xs);font-weight:700;
            line-height:1;background:var(--danger);color:var(--bg);border:2px solid var(--panel);
            font-variant-numeric:tabular-nums}
nav a svg{flex:none;opacity:.85}
nav a .pip{margin-left:auto;width:7px;height:7px;border-radius:50%;flex:none}
.pip.up{background:var(--ok);box-shadow:0 0 0 3px var(--ok-soft)}
.pip.down{background:var(--danger);box-shadow:0 0 0 3px var(--danger-soft)}
.pip.waiting{background:var(--warn);box-shadow:0 0 0 3px var(--warn-soft)}
.who{border-top:1px solid var(--line);padding:var(--s-3);display:flex;
     align-items:center;gap:var(--s-2)}
.who .avatar{width:30px;height:30px;border-radius:50%;background:var(--panel-3);
             display:grid;place-items:center;font-size:var(--t-xs);font-weight:650;
             color:var(--brand);flex:none}
.who .id{min-width:0;flex:1}
.who .id b{display:block;font-size:var(--t-xs);font-weight:600;overflow:hidden;
           text-overflow:ellipsis;white-space:nowrap}
.who .id span{font-size:var(--t-xs);color:var(--muted)}
.who .id .who-link{display:block;font-size:var(--t-xs);color:var(--muted)}
.who .id .who-link.on{color:var(--brand)}
/* A versão embaixo da conta, pequena: é para conferir, não para ler. */
.app-version{padding:0 var(--s-3) var(--s-3);font-size:var(--t-xs)}

main{min-width:0;padding:var(--s-6) var(--s-6) calc(2 * var(--s-6));max-width:1240px}

/* ---------- type ---------- */
h1{font-size:var(--t-lg);margin:0;letter-spacing:-.4px;font-weight:650}
/* O rótulo em caixa alta: cabeçalho de tabela, grupo do menu, título de
   seção, nome de um total. Eram cinco medidas para a mesma peça; agora é
   uma, e .eyebrow (ou .kicker) a põe em qualquer outro elemento. */
.eyebrow,.kicker,th,nav .group,h2,.stat .label,.form-section h3,details.card > summary{
  font-size:var(--t-xs);text-transform:uppercase;letter-spacing:.7px;font-weight:650;color:var(--muted)}
/* The page header keeps the title and its controls on one baseline; the
   title alone dropping half a line is the kind of thing nobody reports and
   everybody notices. */
.page-head{display:flex;align-items:center;gap:var(--s-3);flex-wrap:wrap;margin:0 0 var(--s-5)}
/* O cabeçalho colado no que vem logo embaixo (abas, faixa de totais). */
.page-head.tight{margin-bottom:var(--s-3)}
.page-head .count{color:var(--muted);font-size:var(--t-sm);font-weight:400}
.page-head form{margin:0}
.lede{color:var(--muted);margin:0 0 var(--s-5);font-size:var(--t-sm);max-width:70ch}
/* A ajuda de um campo: colada nele, embaixo. O link sublinhado, que no meio
   de texto cinza não se vê. */
.help{color:var(--muted);font-size:var(--t-xs);margin:var(--s-1) 0 0;line-height:1.45}
.help a{text-decoration:underline;text-underline-offset:2px}
/* A ajuda solta, um parágrafo antes do que explica: o respiro é embaixo. */
.help.block{margin:0 0 var(--s-3)}
h2{margin:var(--s-6) 0 var(--s-3)}
.card h2{margin-top:0}
/* O título de uma seção com uma ação ao lado dele, na mesma linha. */
.section-head{display:flex;align-items:center;justify-content:space-between;gap:var(--s-3);
              flex-wrap:wrap;margin:var(--s-6) 0 var(--s-3)}
.section-head h2{margin:0}
.card .section-head{margin-top:0}

/* ---------- tooltip ---------- */
/* Focusable, not hover-only: a hint reachable only by mouse is missing for
   anyone on a keyboard, and the text lives in the DOM so a screen reader
   finds it too. */
/* O marcador e a dica zeram tudo que herda do contexto. Dentro de um <th>
   valem text-transform:uppercase e letter-spacing, e as duas atravessavam:
   a mesma dica saía em caixa alta e espaçada no painel e na lista, e normal
   no título de instâncias. Uma dica tem de ler igual onde quer que esteja. */
.tip{position:relative;display:inline-flex;align-items:center;
     justify-content:center;width:15px;height:15px;margin-left:var(--s-1);
     border:1px solid var(--line-strong);border-radius:50%;color:var(--muted);
     font-size:var(--t-xs);font-weight:700;cursor:help;vertical-align:middle;
     user-select:none;text-transform:none;letter-spacing:normal}
.tip:hover,.tip:focus-visible{color:var(--ink);border-color:var(--muted)}
/* O círculo continua de 15px; o alvo do toque, não: 31px em volta dele. */
.tip::after{content:"";position:absolute;inset:-8px}
/* fixed, não absolute: as tabelas ficam em .scroll{overflow-x:auto}, e um
   ancestral com overflow recorta descendente posicionado. O CSS não permite
   liberar só o eixo vertical — overflow-y:visible vira auto quando o outro
   eixo é auto — então a dica sai do container. O script calcula a posição;
   sem ele a dica aparece sobre o próprio gatilho, visível e não cortada. */
/* white-space e overflow-wrap junto do resto: a dica é um descendente do
   que a dispara, e num <th> (nowrap) o texto saía inteiro numa linha, para
   fora da caixa. O mesmo vale para td.num e qualquer .nowrap. */
.tip > span{position:fixed;right:8px;width:max(230px,min(280px,60vw));
            text-transform:none;letter-spacing:normal;font-style:normal;
            word-spacing:normal;text-indent:0;
            white-space:normal;overflow-wrap:break-word;
            padding:var(--s-2) var(--s-3);border-radius:var(--radius-sm);background:var(--panel);
            border:1px solid var(--line);color:var(--ink);font-size:var(--t-xs);
            font-weight:400;line-height:1.55;text-align:left;
            box-shadow:0 10px 28px rgba(0,0,0,.4);z-index:var(--z-pop);
            opacity:0;visibility:hidden;transition:opacity var(--dur-fast) ease}
/* right:8px enquanto escondida: no lugar natural, a dica do canto direito
   passava da tela e fazia a página rolar de lado no celular. O script põe o
   left ao abrir, que vence o right. */
.tip:hover > span,.tip:focus > span,.tip:focus-within > span{
  opacity:1;visibility:visible}
/* O cartão da dica aberta sobe acima dos vizinhos. Enquanto a animação de
   entrada dele roda, o cartão é uma camada própria, e sem isto o vizinho
   de baixo pintava por cima de uma dica aberta nesse meio segundo. Sobe só
   até abaixo do que gruda no alto: com 31, o cartão passava por cima do
   índice de seções enquanto se rolava com o mouse sobre um "?". */
.card:has(.tip:hover),.card:has(.tip:focus-within){position:relative;z-index:calc(var(--z-sticky) - 1)}

/* ---------- copiar ---------- */
/* Um <button>, não um <span> com onclick: chega pelo teclado, responde a
   Enter e é anunciado como algo acionável. */
.copy{background:none;border:0;padding:0;color:var(--ink);cursor:pointer;
      border-bottom:1px dashed var(--line);border-radius:0;
      text-align:left;white-space:normal;word-break:break-all;font:inherit}
/* Um id curto numa tabela fica inteiro; o do clique, longo, continua
   quebrando onde precisar. */
.copy.nowrap{white-space:nowrap;word-break:normal}
.copy:hover{color:var(--brand);border-bottom-color:var(--brand)}
.copy.done{color:var(--ok);border-bottom-color:transparent}
/* Copiar como ação principal (o link de pagamento, o código Pix): o
   comportamento é o do .copy, a aparência a do botão que fica ao lado. Sem
   isto, "Copiar link" saía como texto sublinhado entre dois botões. */
button.copy.as-button{background:var(--brand);color:var(--brand-ink);border:0;border-radius:var(--radius-sm);
  padding:9px 16px;font-weight:650;text-align:center;white-space:nowrap;word-break:normal}
button.copy.as-button.ghost{background:transparent;border:1px solid var(--line-strong);color:var(--ink);padding:8px 15px}
button.copy.as-button.small{padding:6px 12px;font-size:var(--t-xs)}
button.copy.as-button.ghost.small{padding:5px 11px}
button.copy.as-button:hover{color:var(--brand-ink);border-bottom-color:transparent}
button.copy.as-button.ghost:hover{color:var(--ink);background:var(--panel-2)}
/* Texto escuro sobre o verde: o branco dava 1,7:1, ilegível. */
button.copy.as-button.done{background:var(--ok);color:var(--bg)}
@media (prefers-reduced-motion:reduce){.tip > span{transition:none}}

/* ---------- surfaces ---------- */
/* Cartão e janela com o mesmo respiro (--s-4): um aviso, um cartão e uma
   janela abertos juntos alinham o texto na mesma coluna. */
.card{background:var(--panel);border:1px solid var(--line);
      border-radius:var(--radius);padding:var(--s-4)}
/* Os botões no pé de um cartão, à direita, como numa janela. */
.card-actions{display:flex;gap:var(--s-2);justify-content:flex-end;flex-wrap:wrap;align-items:center;
              margin-top:var(--s-4)}
.card-actions form{margin:0}
/* O cartão do que não tem volta (encerrar, excluir tudo): a borda diz antes
   do botão. */
.card.danger-zone{border-color:var(--danger-line)}
.card.danger-zone h2{color:var(--danger-ink)}

/* A confirmação: um card no meio da tela, com o fundo escurecido. */
.confirm-dialog{background:var(--panel);border:1px solid var(--line);
           border-radius:var(--radius);padding:var(--s-4);color:var(--ink);
           max-width:min(440px,calc(100vw - 32px));font:inherit}
.confirm-dialog::backdrop{background:rgba(0,0,0,.6)}
.confirm-dialog p{margin:0 0 var(--s-4);line-height:1.5}
.confirm-actions{display:flex;gap:var(--s-2);justify-content:flex-end}
/* O botão que confirma fica vermelho quando o que se confirma destrói
   alguma coisa, e a tela diz qual é o caso. Texto escuro: o branco sobre
   esse vermelho dava 3:1. */
.confirm-dialog.destructive #confirm-yes{background:var(--danger);border-color:var(--danger);color:var(--bg)}
.grid{display:grid;gap:var(--s-3)}
.cols-4{grid-template-columns:repeat(auto-fit,minmax(190px,1fr))}
/* Seis números em duas linhas de três, como os totais da aba Vendas. */
.cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}
/* min(): numa tela de 320px sobram menos de 320 para a coluna, e o mínimo
   fixo fazia a página rolar de lado. */
.cols-2{grid-template-columns:repeat(auto-fit,minmax(min(320px,100%),1fr))}
/* A variação contra o período anterior, ao lado do número e não embaixo:
   lida junto com ele é uma frase só — "142, dezoito por cento acima". */
.stat .value{font-size:var(--t-xl);font-weight:650;margin-top:var(--s-2);letter-spacing:-.8px;
             font-variant-numeric:tabular-nums;display:flex;align-items:baseline;gap:var(--s-2);flex-wrap:wrap}
.stat .hint{color:var(--muted);font-size:var(--t-xs);margin-top:var(--s-1)}
.trend{font-size:var(--t-xs);font-weight:650;letter-spacing:0}
.trend.good{color:var(--ok)}
.trend.bad{color:var(--danger)}
.trend.flat{color:var(--muted)}

/* ---------- tables ---------- */
table{width:100%;border-collapse:collapse}
/* Cabeçalho numa linha: quebrado, o "?" da dica caía sozinho embaixo do
   nome da coluna. Numa tela estreita a tabela rola de lado, como já rolava. */
th{text-align:left;padding:var(--s-2) var(--s-3);border-bottom:1px solid var(--line);
   white-space:nowrap}
td{padding:var(--s-3);border-bottom:1px solid var(--line-soft);vertical-align:middle}
/* Números, dinheiro e datas numa linha só. Sem isso a coluna do nome, que é
   longa, espremia as outras até "R$" ficar numa linha e "35,15" na seguinte.
   E à direita, com o cabeçalho junto: as casas se alinham e se comparam de
   cima a baixo. */
td.num{white-space:nowrap;font-variant-numeric:tabular-nums}
th.num,td.num{text-align:right}
/* A coluna dos botões de uma linha, encostada à direita. */
th.row-actions,td.row-actions{width:1%;white-space:nowrap;text-align:right}
td.row-actions form{margin:0}
/* Mais de um botão na coluna: lado a lado, sem quebrar, alinhados ao fim. */
td.row-actions .actions{display:inline-flex;gap:var(--s-2);align-items:center;justify-content:flex-end}
tr:last-child td{border-bottom:0}
/* O realce de linha faz duas coisas: avisa que a linha navega, e ajuda a
   seguir uma linha longa de ponta a ponta. Numa tabela de rótulo e valor
   não faz nem uma nem outra — e como o rótulo ali não tem recuo à
   esquerda, a faixa cola no texto e parece defeito, não destaque. */
tbody tr:hover{background:var(--panel-2)}
.kv tbody tr:hover{background:transparent}
/* The whole row navigates. The visible button stays: a row that only
   responds to a click nobody can see is a trap. */
tbody tr[data-href]{cursor:pointer}

/* Key/value tables. The label column was sizing itself to the content, so
   "Clicado em" wrapped onto two lines while "LID" had room to spare. */
.kv td:first-child{width:172px;color:var(--muted);white-space:nowrap;
                   vertical-align:top}
.kv td{padding:var(--s-2) var(--s-3) var(--s-2) 0;border-bottom:1px solid var(--line-soft)}
.kv tr:last-child td{border-bottom:0}
.kv .break{word-break:break-all;font-size:var(--t-xs);line-height:1.5}
/* O valor quebra onde precisar: um e-mail longo empurrava a página para o
   lado no celular. */
.kv td:last-child{overflow-wrap:anywhere}
/* No celular o rótulo de 172px deixava ~130px para o valor: ele cede e
   quebra. */
@media (max-width:560px){.kv td:first-child{width:40%;white-space:normal}}
/* A conta de um valor: números à direita, e o total em destaque. */
.kv.money td.num{text-align:right;font-variant-numeric:tabular-nums}
.kv.money tr.total td{font-weight:650;border-top:1px solid var(--line)}

/* Forms stop stretching to the full width of a wide screen: a text field
   a thousand pixels long is harder to read, not easier. */
.form-narrow{max-width:560px}

/* Busy state. A submit that reaches the server takes as long as it takes;
   without a signal the operator clicks again, and a second click on
   "Reprocessar" or "Enviar teste" is a second round trip nobody wanted. */
button[data-busy]{position:relative;color:transparent!important}
button[data-busy]::after{content:"";position:absolute;inset:0;margin:auto;
  width:14px;height:14px;border-radius:50%;
  border:2px solid currentColor;border-top-color:transparent;
  color:var(--brand-ink);animation:spin var(--dur-slow) linear infinite}
button.ghost[data-busy]::after,button.danger[data-busy]::after{color:var(--ink)}
@keyframes spin{to{transform:rotate(360deg)}}
@media (prefers-reduced-motion:reduce){
  button[data-busy]::after{animation:none;border-top-color:currentColor;opacity:.5}
}
/* Um formulário já enviado não aceita um segundo clique; os outros botões
   dele esmaecem para dizer que esperam o primeiro. */
form[data-sending] button{pointer-events:none}
form[data-sending] button:not([data-busy]){opacity:.5}

/* A página seguinte está a caminho. O navegador mantém a anterior parada
   até ela chegar, e sem sinal nenhum a tela parece travada: a barra no
   topo diz que algo anda. */
.progress{position:fixed;top:0;left:0;z-index:var(--z-progress);height:3px;width:0;
          background:var(--brand);box-shadow:0 0 8px var(--brand);opacity:0;pointer-events:none}
.progress.on{opacity:1;animation:progress 12s cubic-bezier(.08,.7,.2,1) forwards}
@keyframes progress{from{width:0}to{width:92%}}

/* O esqueleto: o dado que ainda não chegou ocupa o lugar e o formato do
   componente que vai mostrá-lo, e brilha. */
.sk{display:block;border-radius:var(--radius-sm);background:linear-gradient(100deg,var(--panel-2) 30%,var(--panel-3) 50%,var(--panel-2) 70%);
    background-size:250% 100%;animation:shimmer 1.3s linear infinite}
.sk-line{height:11px;margin:7px 0}
.sk-value{height:30px;width:55%;margin:10px 0 12px}
/* A altura de uma linha do h1 (20px × 1,55): o cabeçalho não pula quando a
   página chega. */
.sk-title{height:31px;width:170px}
.sk-control{height:40px;width:150px}
.sk-chart{height:280px}
.sk-row{display:grid;grid-template-columns:2fr 1fr 1fr 1fr;gap:var(--s-4);padding:var(--s-3) 0;border-bottom:1px solid var(--line-soft)}
.sk-row:last-child{border-bottom:0}
.sk-row .sk{height:12px}
.sk-tabs{display:flex;gap:var(--s-1);margin:0 0 var(--s-4)}
.sk-tabs .sk{height:30px;width:90px}
@keyframes shimmer{from{background-position:120% 50%}to{background-position:-120% 50%}}

/* O filtro trocado na mesma tela: cada componente fica onde está, e só o
   que vai mudar vira esqueleto. Rótulo, título, cabeçalho de tabela e o
   próprio filtro continuam legíveis, porque não vão mudar. */
main.loading :is(.card.stat .value,.card.stat .hint,tbody td,.chart,.donut,.hbar-cell,.bar-cell,.aud-split,.count){
  color:transparent!important;border-radius:var(--radius-sm);
  background:linear-gradient(100deg,var(--panel-2) 30%,var(--panel-3) 50%,var(--panel-2) 70%) content-box;
  background-size:250% 100%;animation:shimmer 1.3s linear infinite}
main.loading :is(.card.stat .value,.card.stat .hint,tbody td,.chart,.donut,.hbar-cell,.bar-cell,.aud-split,.count) *{visibility:hidden}
main.loading .card.stat .value{width:max-content;min-width:5ch;max-width:100%}
/* Texto corrido e célula de tabela viram uma linha fina no meio, como
   linha de texto, e não um bloco da altura da célula. */
main.loading :is(.card.stat .hint,tbody td){background-size:250% 12px;background-repeat:no-repeat}
/* A caixa de seleção não é dado: fica como está. */
main.loading tbody td:has(input[type=checkbox]){background:none;animation:none}
main.loading tbody td:has(input[type=checkbox]) *{visibility:visible}
main.loading :is(a,button,select,input){pointer-events:none}

/* A janela de formulário: criar ou editar sem sair da lista. Sem script
   ela não vira sobreposta, e a que o servidor manda aberta aparece no
   fluxo da página, com o formulário à vista. */
dialog.form-dialog{background:var(--panel);border:1px solid var(--line);border-radius:var(--radius);
  padding:var(--s-4);color:var(--ink);font:inherit;width:min(640px,calc(100vw - 32px));
  max-height:calc(100vh - 48px);overflow:auto}
dialog.form-dialog::backdrop{background:rgba(0,0,0,.6)}
dialog.form-dialog[open]:not(:modal){position:static;margin:0 0 var(--s-4);width:auto;max-height:none}
.form-dialog-head{display:flex;justify-content:space-between;align-items:center;gap:var(--s-3);margin-bottom:var(--s-4)}
/* O título da janela é o título dela, e não um rótulo de seção: o h2
   comum da página é pequeno, cinza e em caixa alta. */
.form-dialog-head h2{margin:0;font-size:var(--t-lg);font-weight:650;text-transform:none;letter-spacing:-.2px;color:var(--ink)}
.dialog-close{font-size:var(--t-lg);line-height:1;color:var(--muted);text-decoration:none;
              display:inline-flex;align-items:center;justify-content:center;
              min-width:36px;min-height:36px;border-radius:var(--radius-sm);margin:-6px -8px -6px 0}
.dialog-close:hover{color:var(--ink);background:var(--panel-2)}
/* Entra de leve: sem isto a janela e o fundo escuro aparecem de uma vez. */
dialog.form-dialog:modal{animation:dialog-in var(--dur) ease-out}
dialog.form-dialog:modal::backdrop{animation:backdrop-in var(--dur) ease-out}
@keyframes dialog-in{from{opacity:0;transform:translateY(8px) scale(.985)}}
@keyframes backdrop-in{from{opacity:0}}
@media (prefers-reduced-motion:reduce){
  dialog.form-dialog:modal,dialog.form-dialog:modal::backdrop{animation:none}
}
.form-dialog-actions{display:flex;gap:var(--s-2);justify-content:flex-end;margin-top:var(--s-2)}

/* A operação demorada cobre a tela: nada mais se clica até ela acabar. */
.busy-dialog{background:var(--panel);border:1px solid var(--line);border-radius:var(--radius);
             padding:var(--s-4);color:var(--ink);font:inherit;text-align:center;
             max-width:min(400px,calc(100vw - 32px))}
.busy-dialog::backdrop{background:rgba(0,0,0,.65)}
.busy-dialog .spinner{display:block;width:28px;height:28px;margin:var(--s-2) auto var(--s-3);border-radius:50%;
  border:3px solid var(--brand);border-top-color:transparent;animation:spin var(--dur-slow) linear infinite}
.busy-dialog strong{display:block;font-size:var(--t-md);margin-bottom:var(--s-2)}
.busy-dialog p{margin:0;font-size:var(--t-sm);line-height:1.5}

/* O resultado de uma ação chega no canto, à vista de onde quer que se
   tenha clicado: o aviso no alto da página ficava fora da tela de quem
   clicou no fim dela. O sucesso some sozinho; o erro fica até ser lido. */
.toasts{position:fixed;right:var(--s-4);bottom:var(--s-4);z-index:var(--z-toast);display:flex;flex-direction:column;
        gap:var(--s-2);width:min(420px,calc(100vw - 32px))}
.toasts .banner{margin:0;padding-right:40px;position:relative;
                box-shadow:0 10px 30px rgba(0,0,0,.45);animation:toast-in var(--dur) ease-out}
.toasts .banner.ok{background:linear-gradient(var(--ok-soft),var(--ok-soft)),var(--panel)}
.toasts .banner.bad{background:linear-gradient(var(--danger-soft),var(--danger-soft)),var(--panel)}
.toasts .banner.warn{background:linear-gradient(var(--warn-soft),var(--warn-soft)),var(--panel)}
.toasts .banner.leaving{opacity:0;transform:translateY(8px);transition:opacity var(--dur),transform var(--dur)}
.toast-close{position:absolute;top:6px;right:6px;background:none;border:0;color:inherit;
             font-size:var(--t-lg);line-height:1;padding:var(--s-1) var(--s-2);cursor:pointer;opacity:.7}
.toast-close:hover{opacity:1;background:none}
@keyframes toast-in{from{opacity:0;transform:translateY(8px)}}
/* ---------- a entrada dos números ---------- */
/* O que se mede aparece com movimento curto, uma vez, quando a página
   chega: a linha do gráfico se desenha como o tempo corre, a rosca gira
   até o lugar, as barras crescem do zero e os cards sobem em sequência.
   Curto de propósito: uma tela de trabalho reaberta vinte vezes por dia
   não pode fazer esperar. */
@keyframes enter-rise{from{opacity:0;transform:translateY(6px)}}
@keyframes enter-fade{from{opacity:0}}
@keyframes enter-grow{from{transform:scaleX(0)}}
@keyframes enter-draw{from{clip-path:inset(0 100% 0 0)}to{clip-path:inset(0 0 0 0)}}
@keyframes enter-turn{from{opacity:0;transform:rotate(-25deg) scale(.92)}}
/* backwards, e nunca both ou forwards: terminada, a animação tem de sair
   de cena. Com o preenchimento para a frente o navegador trata o elemento
   como transformado para sempre — ele vira uma camada própria e a
   referência das posições fixas dentro dele. Num cartão isso escondia a
   dica do "?": ela era posicionada pela janela e desenhada pelo cartão,
   fora do lugar, e o cartão seguinte pintava por cima. */
.chart-draw{animation:enter-draw var(--dur-slow) cubic-bezier(.3,.7,.3,1) backwards}
.chart-fill{animation:enter-fade var(--dur-slow) var(--dur) ease-out backwards}
.donut svg{animation:enter-turn var(--dur-slow) cubic-bezier(.3,.7,.3,1) backwards}
.hbar,.aud .track{transform-origin:left center;animation:enter-grow var(--dur-slow) cubic-bezier(.3,.7,.3,1) backwards}
.card.stat{animation:enter-rise var(--dur) ease-out backwards}
.grid > .card.stat:nth-child(2){animation-delay:.04s}
.grid > .card.stat:nth-child(3){animation-delay:.08s}
.grid > .card.stat:nth-child(4){animation-delay:.12s}
.grid > .card.stat:nth-child(n+5){animation-delay:.16s}
@media (prefers-reduced-motion:reduce){
  .chart-draw,.chart-fill,.donut svg,.hbar,.aud .track,.card.stat{animation:none}
  .progress.on{animation:none;width:60%}
  .sk,main.loading :is(.card.stat .value,.card.stat .hint,tbody td,.chart,.donut,.hbar-cell,.bar-cell,.aud-split,.count),
  .toasts .banner{animation:none}
  .busy-dialog .spinner{animation:none;border-top-color:var(--brand);opacity:.6}
}
.scroll{overflow-x:auto}

/* ---------- bits ---------- */
.tag{display:inline-flex;align-items:center;gap:var(--s-1);padding:2px var(--s-2);border-radius:99px;
     font-size:var(--t-xs);font-weight:650;border:1px solid transparent;white-space:nowrap}
.tag::before{content:"";width:6px;height:6px;border-radius:50%;background:currentColor}
/* Marcada aqui e não enviada: cor própria, para a lista separar de
     relance a conversão que foi ao Meta da que não tinha como ir. Nem
     verde, que diria entregue, nem vermelha, que diria falha. */
.tag.local{background:var(--brand-soft);color:var(--brand);border-color:var(--brand-line)}
/* Um papel, não um estado: sem o ponto, que nos outros selos diz "está
   assim agora". */
.tag.role{background:var(--panel-2);color:var(--ink-dim);border-color:var(--line)}
.tag.role::before{display:none}
.tag.role.admin{background:var(--brand-soft);color:var(--brand);border-color:var(--brand-line)}
/* Os tons pelo que querem dizer, e não por onde nasceram: as telas de
   pagamento e de janela reaproveitavam os nomes do envio ao Meta (sent,
   pending, failed). Os nomes antigos seguem valendo, no mesmo seletor, até
   cada tela mudar; uma tela nova usa só ok/warn/err/neutral/info. */
.tag.ok,.tag.sent,.tag.fresh{background:var(--ok-soft);color:var(--ok);border-color:var(--ok-line)}
.tag.warn,.tag.pending,.tag.closing{background:var(--warn-soft);color:var(--warn);border-color:var(--warn-line)}
.tag.err,.tag.failed,.tag.expired{background:var(--danger-soft);color:var(--danger);border-color:var(--danger-line)}
.tag.neutral,.tag.no_referral,.tag.closed{background:var(--panel-2);color:var(--muted);border-color:var(--line)}
.tag.info{background:var(--info-soft);color:var(--info);border-color:var(--info-line)}

input,select,button,textarea{font:inherit}
/* A borda em --line-strong: com --line o campo sumia contra o cartão. O
   11px do lado é o 12 da escala menos a borda; a altura vem de height. */
input,select,textarea{background:var(--panel-2);border:1px solid var(--line-strong);color:var(--ink);
             padding:var(--s-2) 11px;border-radius:var(--radius-sm);width:100%;transition:border-color var(--dur-fast)}
textarea{display:block;min-height:80px;resize:vertical;line-height:1.5}
input:hover,select:hover,textarea:hover{border-color:var(--muted)}
input:focus,select:focus,textarea:focus{outline:none;border-color:var(--brand);
                         box-shadow:0 0 0 3px var(--brand-soft)}
/* One height for every field and button in a row. A select drew about
   four pixels shorter than a text input beside it, and the retention box
   on the settings screen sat visibly lower than the two selects next to it. */
input:not([type=checkbox]):not([type=radio]),select{height:40px}
/* Rádio e caixa do mesmo tamanho: lado a lado no mesmo formulário, um saía
   com 13px e o outro com 15. */
input[type=checkbox],input[type=radio]{width:16px;height:16px;margin:0;cursor:pointer}
/* Alone in a cell, a checkbox sat on the text baseline, a few pixels above
   the name beside it. As a block it centres with the row. */
td > input[type=checkbox],th > input[type=checkbox]{display:block}
/* A seta desenhada aqui, e não a do sistema: a do Chrome encostava na
   borda direita, sem o respiro que o texto tem do lado esquerdo. O traço
   %238a92a3 é o --muted: dentro de um data: não há como ler a variável. */
select{cursor:pointer;-webkit-appearance:none;appearance:none;padding-right:36px;
       background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath d='M2.5 4.5 6 8l3.5-3.5' fill='none' stroke='%238a92a3' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
       background-repeat:no-repeat;background-position:right 13px center;background-size:12px}
select[multiple]{background-image:none;padding-right:11px}
/* O exemplo dentro do campo em --muted (5:1 sobre o fundo dele). Ele nunca
   é a única informação: "opcional" vai na label ou na ajuda. */
input::placeholder,textarea::placeholder{color:var(--muted);opacity:1}
/* Desabilitado não pode parecer editável: sem fundo, borda tracejada. */
input:disabled,select:disabled,textarea:disabled{background:transparent;color:var(--ink-dim);
  border-style:dashed;border-color:var(--line-strong);cursor:not-allowed}
label{display:block;font-size:var(--t-xs);color:var(--muted);margin-bottom:var(--s-1);font-weight:500}
/* Obrigatório: o asterisco vem da classe, na label, para que ligar e
   desligar a exigência (um campo que só vale para Purchase, os dados de
   entrega que só valem com o envio ligado) mude as duas coisas juntas. */
label.req::after{content:" *";color:var(--danger);font-weight:650}
/* A borda vermelha só depois que a pessoa mexeu no campo: um formulário
   aberto não começa acusando o que ainda não foi preenchido. O servidor,
   quando recusa, marca o campo com aria-invalid. */
input:user-invalid,select:user-invalid,textarea:user-invalid,
:is(input,select,textarea)[aria-invalid=true]{border-color:var(--danger)}
.field-error{color:var(--danger);font-size:var(--t-xs);margin-top:var(--s-1)}
.field{margin-bottom:var(--s-4)}
/* Larguras de campo fora da linha cheia: o que cabe no conteúdo (um
   seletor ao lado do título), um número curto, um texto médio. */
.fit{width:auto;max-width:260px}
.w-sm{width:100%;max-width:120px}
.w-md{width:100%;max-width:280px}

/* 9px + 9px + a linha de 14px × 1,55 dá os 40px de um campo: botão e campo
   lado a lado ficam da mesma altura. */
button{background:var(--brand);color:var(--brand-ink);border:0;padding:9px 16px;
       border-radius:var(--radius-sm);font-weight:650;cursor:pointer;transition:filter var(--dur-fast)}
button:hover{filter:brightness(1.07)}
button:active{filter:brightness(.95)}
button:focus-visible{outline:2px solid var(--brand);outline-offset:2px}
/* A borda da variante não pode mudar a altura: o botão contornado ficava
   dois pixels mais alto que o cheio, e quem colocava os dois lado a lado
   descobria isso no olho. O padding devolve o que a borda tomou. */
button.ghost,button.danger{padding:8px 15px}
button.ghost{background:transparent;border:1px solid var(--line-strong);color:var(--ink)}
button.ghost:hover{background:var(--panel-2);filter:none}
button.danger{background:transparent;border:1px solid var(--danger-line);color:var(--danger)}
button.danger:hover{background:var(--danger-soft);filter:none}
button:disabled{opacity:.4;cursor:not-allowed;filter:none}
/* A link that looks like a button.
   Nesting <button> inside <a> is invalid HTML, and inside a form it is
   actively harmful: the button defaults to type=submit, so clicking it
   submits the surrounding form instead of following the link. */
.btn{display:inline-flex;align-items:center;justify-content:center;
     background:var(--brand);color:var(--brand-ink);padding:9px 16px;
     border-radius:var(--radius-sm);font-weight:650;white-space:nowrap;transition:filter var(--dur-fast)}
.btn:hover{filter:brightness(1.07)}
/* A mesma compensação da borda do button.ghost: sem ela o link contornado
   saía dois pixels mais alto que o botão ao lado. */
.btn.ghost{background:transparent;border:1px solid var(--line-strong);color:var(--ink);padding:8px 15px}
.btn.ghost:hover{background:var(--panel-2);filter:none}
/* Revogar e excluir ficam vermelhos em qualquer botão: o .btn.ghost vinha
   depois do .danger e o deixava neutro. */
.btn.ghost.danger{border-color:var(--danger-line);color:var(--danger)}
.btn.ghost.danger:hover{background:var(--danger-soft)}
/* O botão que ocupa a largura toda, como a saída de uma página de erro; e
   uma pilha de blocos com o mesmo respiro entre eles. */
.btn.block{display:flex;width:100%}
.stack-gap > * + *{margin-top:var(--s-2)}
/* A volta para a tela de cima: do tamanho de um toque, não da linha. */
a.back{display:inline-flex;align-items:center;min-height:32px;margin-bottom:var(--s-1)}
/* Um texto sem espaço (e-mail, endereço) quebra onde precisar em vez de
   alargar a tabela para fora da tela. */
.wrap{overflow-wrap:anywhere}

.row{display:flex;gap:var(--s-3);align-items:flex-end;flex-wrap:wrap}
/* Um botão ao lado de campos tem a altura dos campos. Sem isto ele ficava
   mais alto e mais alto do que o alinhamento pela base sugeria, e três
   telas resolviam isso empurrando o botão com margem à mão. Vale também
   para o link com cara de botão. */
.row > :is(button,.btn):not(.small,.link){height:40px}
/* Ação ocasional, que não deve pesar mais que o texto ao lado dela. Um
   tamanho só, cheio ou contornado, botão ou link; o contornado devolve no
   padding o pixel da borda. */
button.small,.btn.small{padding:6px 12px;font-size:var(--t-xs)}
:is(button,.btn).small:is(.ghost,.danger){padding:5px 11px}
.muted{color:var(--muted)}
.mono{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:var(--t-xs)}

/* O aviso tem o mesmo respiro lateral do cartão: o texto dos dois alinha. */
.banner{padding:var(--s-3) var(--s-4);border-radius:var(--radius);margin-bottom:var(--s-4);font-size:var(--t-sm);
        border:1px solid var(--line);background:var(--panel);line-height:1.5}
.banner.warn{background:var(--warn-soft);border-color:var(--warn-line);color:var(--warn-ink)}
.banner.bad{background:var(--danger-soft);border-color:var(--danger-line);color:var(--danger-ink)}
.banner.ok{background:var(--ok-soft);border-color:var(--ok-line);color:var(--ok-ink)}
.banner a{text-decoration:underline;text-underline-offset:2px}
/* Um estado sabido, que só precisa continuar à vista: uma linha, menor. */
.banner.slim{padding:var(--s-2) var(--s-3);font-size:var(--t-xs)}

/* Chart hover layer. */
.chart svg{cursor:crosshair}
/* Rótulos dos eixos em HTML: dentro do SVG eles esticavam junto com ele.
   Os do eixo y ficam numa calha de 44px à esquerda do SVG. Antes a calha
   era de 44 unidades de 1000 dentro dele, o que num celular dava 13px para
   rótulos de 36px, e eles caíam em cima da linha. */
/* A altura da caixa é exatamente a do SVG. Sem padding vertical: um top:%
   resolve contra a caixa de padding, então qualquer acréscimo em cima ou
   embaixo desalinha os rótulos de novo. O espaço até a legenda é margem,
   que não conta. O padding à esquerda não mexe na altura. */
.chart-plot{position:relative;margin-bottom:20px;padding-left:44px}
/* A largura que conta é a do gráfico, não a da tela: os quatro dos
   relatórios são estreitos num monitor largo. Abaixo de 420px, um rótulo
   sim, outro não — as pontas ficam. */
.chart-area{position:relative;container-type:inline-size}
@container (max-width:420px){.chart-x.minor{display:none}}
.chart-y,.chart-x{position:absolute;color:var(--muted);font-size:var(--t-xs);
                  line-height:1;pointer-events:none;white-space:nowrap}
.chart-y{left:0;width:36px;text-align:right;transform:translateY(-50%)}
.chart-x{bottom:-4px;transform:translateX(-50%)}
/* O primeiro e o último não podem sair do card, então ancoram pela borda em
   vez de pelo centro. */
.chart-x:first-of-type{transform:none}
.chart-x:last-of-type{transform:translateX(-100%)}
.chart-guide,.chart-marker{transition:opacity var(--dur-fast) linear}

/* Nos relatórios os gráficos ficam dois a dois, mais baixos que o do
   painel: quatro de 240px empurravam a página inteira para baixo. Em três
   colunas sobrava um sozinho embaixo. */
.multiples{grid-template-columns:repeat(2,minmax(0,1fr))}
.multiples .chart svg{height:180px}

/* ---------- comparar com ---------- */
/* Botões lado a lado, como abas: a escolha à vista, sem abrir lista. */
.compare-bar{display:flex;align-items:center;gap:var(--s-2);flex-wrap:wrap;margin:0 0 var(--s-3)}
.seg-control{display:inline-flex;flex-wrap:wrap;border:1px solid var(--line);
             border-radius:var(--radius-sm);padding:3px;gap:2px;background:var(--panel)}
.seg-control a,.seg-control.radio label > span{display:flex;align-items:center;min-height:32px;padding:0 var(--s-3);border-radius:calc(var(--radius-sm) - 2px);
               font-size:var(--t-sm);color:var(--ink-dim);white-space:nowrap}
.seg-control a:hover,.seg-control.radio label:hover > span{background:var(--panel-2);color:var(--ink)}
.seg-control a.on,.seg-control.radio input:checked + span{background:var(--brand-soft);color:var(--brand);font-weight:600}
/* A mesma peça como escolha de formulário: um rádio por opção, escondido,
   e o texto dele com a cara do segmento. Sem script e sem perder o teclado:
   as setas trocam a opção, e o foco aparece no texto. */
.seg-control.radio label{margin:0;font-size:inherit;font-weight:inherit;cursor:pointer}
.seg-control.radio input{position:absolute;opacity:0;width:1px;height:1px;margin:0;pointer-events:none}
.seg-control.radio input:focus-visible + span{outline:2px solid var(--brand);outline-offset:1px}
.compare-date{display:inline-flex;flex-wrap:wrap;gap:var(--s-2);align-items:center}

/* ---------- tabelas que ordenam ---------- */
/* O cabeçalho é um botão, com a cara de cabeçalho; a seta diz a ordem. */
/* A altura de um toque, e não a da letra em caixa alta (12 a 16px). */
button.sort,a.sort{background:none;border:0;padding:0;color:inherit;font:inherit;
            text-transform:inherit;letter-spacing:inherit;cursor:pointer;border-radius:3px;
            display:inline-flex;align-items:center;min-height:32px}
button.sort:hover,a.sort:hover{color:var(--ink);filter:none}
a.sort{text-decoration:none}
th[aria-sort=descending] .sort::after{content:" ↓";color:var(--brand)}
th[aria-sort=ascending] .sort::after{content:" ↑";color:var(--brand)}

/* ---------- índice de seções ---------- */
/* Preso no alto da página longa, com fundo, para os links não passarem por
   cima do conteúdo; num celular rola de lado em vez de quebrar em linhas. */
.section-nav{position:sticky;top:0;z-index:var(--z-sticky);display:flex;gap:var(--s-1);overflow-x:auto;
             background:var(--bg);padding:var(--s-2) 0;margin:0 0 var(--s-1);
             border-bottom:1px solid var(--line-soft);scrollbar-width:none}
.section-nav a{padding:var(--s-1) var(--s-3);border-radius:99px;font-size:var(--t-xs);color:var(--ink-dim);
               white-space:nowrap}
/* O índice rola de lado: o anel de fora seria cortado. */
.section-nav a:focus-visible{outline-offset:-2px}
.section-nav a:hover{background:var(--panel-2);color:var(--ink)}
.section-nav a.on{background:var(--brand-soft);color:var(--brand)}
h2[id]{scroll-margin-top:56px}

/* ---------- uma campanha só ---------- */
/* O filtro da campanha não cresce até o nome mais longo do Gerenciador:
   "Black Friday — Conversas — Mulheres 25-44 — Teste B" empurrava o botão
   de atualizar para a linha de baixo. */
select.campaign-field{width:auto;max-width:260px;text-overflow:ellipsis}
/* O aviso de que a página é de uma campanha: a cor da marca, e não a de
   alerta, porque não há nada errado — é uma escolha, e ela se desfaz ali. */
.focus-bar{display:flex;align-items:center;justify-content:space-between;gap:var(--s-3);
           flex-wrap:wrap;margin:0 0 var(--s-4);padding:var(--s-3) var(--s-4);border-radius:var(--radius);
           background:var(--brand-soft);border:1px solid var(--brand-line)}
.focus-bar .focus-what{min-width:0;flex:1 1 320px}
.focus-bar strong{font-size:var(--t-md)}
.focus-kicker{display:block;font-size:var(--t-xs);text-transform:uppercase;letter-spacing:.7px;
              color:var(--brand);font-weight:650;margin-bottom:2px}
.focus-actions{display:flex;gap:var(--s-2);flex-wrap:wrap}
/* Um nome que abre um recorte: sublinhado discreto, que diz "leva a algum
   lugar" sem virar a tabela num mar de links azuis. */
a.drill{text-decoration:underline;text-decoration-color:var(--line);text-underline-offset:3px}
a.drill:hover{text-decoration-color:currentColor}

/* ---------- resumo comparado ---------- */
/* As datas no cabeçalho ficam como se escrevem: em caixa alta, "até
   12h06" virava "ATÉ 12H06". */
.versus th.when{text-transform:none;letter-spacing:0;font-size:var(--t-xs)}
.versus td.label{white-space:nowrap}
.versus th.pair,.versus td.pair{width:26%;min-width:110px}
.versus .pbar{display:block;height:6px;border-radius:0 3px 3px 0;min-width:0}
.versus .pbar + .pbar{margin-top:3px}
.versus .pbar.now{background:var(--viz-1)}
.versus .pbar.before{background:var(--viz-compare)}
.versus td.before{color:var(--ink-dim)}
/* Numa tela estreita as barras saem: o número ao lado diz o mesmo, e elas
   empurravam os valores para fora da tela. */
@media (max-width:820px){.versus .pair{display:none}}
.sub{font-size:var(--t-xs);color:var(--muted);font-weight:400}

/* ---------- atendimento ---------- */
/* A hora fora do expediente fica esmaecida, e não some: uma fila às 22h é
   um argumento para abrir mais tarde, e sumir com ela esconde o argumento.
   Esmaecida pela cor, não por opacity, que a deixava abaixo de 3:1. */
tr.closed td{color:var(--muted)}
.tag.closed::before{display:none}
/* A barra tem trilho de largura fixa: sem ele, a coluna mudaria de largura
   conforme a hora mais cheia, e as linhas deixariam de se comparar de
   relance. */
.hbar-cell{display:flex;align-items:center;justify-content:flex-end;gap:var(--s-2)}
.hbar-track{display:block;width:70px;height:6px;border-radius:3px;
            background:var(--panel-2);flex:none;overflow:hidden}
.hbar{display:block;height:100%;border-radius:3px;background:var(--viz-1)}
/* Quem ficou sem resposta é o número que move alguém, então ele é o único
   colorido da tabela. */
.shortfall{color:var(--danger)}
@media (max-width:820px){.hbar-track{display:none}}

/* O caminho do painel para os relatórios: um card inteiro clicável. */
.card.more{display:flex;align-items:center;justify-content:space-between;gap:var(--s-3);
           margin-top:var(--s-3);transition:border-color var(--dur-fast),background var(--dur-fast)}
.card.more strong{display:block;margin-bottom:2px}
.card.more .muted{font-size:var(--t-sm)}
.card.more .arrow{font-size:var(--t-lg);color:var(--muted)}
.card.more:hover{border-color:var(--panel-3);background:var(--panel-2)}
.card.more:hover .arrow{color:var(--brand)}

.chart-tip{position:absolute;pointer-events:none;z-index:5;
           background:var(--panel-3);border:1px solid var(--line);
           border-radius:var(--radius-sm);padding:var(--s-2) var(--s-3);font-size:var(--t-xs);
           box-shadow:0 8px 24px rgba(0,0,0,.45);min-width:132px;
           transform:translate(-50%,-100%)}
.chart-tip strong{display:block;margin-bottom:var(--s-1);font-size:var(--t-xs)}
.chart-tip-rows{display:grid;gap:var(--s-1)}
.chart-tip-row{display:flex;align-items:center;gap:var(--s-2);
               justify-content:space-between}
.chart-tip-row .k{display:flex;align-items:center;gap:var(--s-2);color:var(--ink-dim)}
.chart-tip-row .swatch{width:8px;height:8px;border-radius:2px;flex:none}
.chart-tip-row .v{font-weight:650;font-variant-numeric:tabular-nums}
.chart-tip-note{display:block;margin-top:var(--s-1);font-size:var(--t-xs)}

.pager{display:flex;gap:var(--s-2);align-items:center;justify-content:space-between;
       padding:var(--s-3) 0 0;color:var(--muted);font-size:var(--t-sm)}
.pager a,.pager span.off{padding:6px 12px;border:1px solid var(--line-strong);border-radius:var(--radius-sm)}
.pager a:hover{background:var(--panel-2);color:var(--ink)}
/* A página que não existe: um <span aria-disabled> no lugar do link, para
   o Tab não parar nele. O a.off fica até cada lista trocar. */
.pager .off{opacity:.5;pointer-events:none;border-style:dashed}

details summary{cursor:pointer;color:var(--muted);padding:var(--s-1) 0;font-weight:500}
/* A folded card keeps the weight of the heading it replaced, so the page
   still reads as a list of sections rather than a list of links. */
details.card > summary{padding:0}
details.card[open] > summary{margin-bottom:var(--s-3)}
/* Só o título do próprio bloco: um details aberto dentro de outro (o
   seletor de tags dentro da barra de filtros) não herda a margem, que o
   descia 12px abaixo dos vizinhos. */
details[open] > summary{margin-bottom:var(--s-3);color:var(--ink)}
.chips{display:flex;gap:var(--s-2);flex-wrap:wrap}

/* ---------- narrow screens ---------- */
.menu-toggle{display:none}
@media (max-width:820px){
  .multiples{grid-template-columns:1fr}
  /* A barra só na altura dela: numa página mais curta que a tela, a grade
     dividia a sobra entre as duas linhas, e a barra ganhava uma faixa
     vazia embaixo do menu. */
  .shell{grid-template-columns:1fr;grid-template-rows:auto 1fr}
  aside{position:static;height:auto;border-right:0;border-bottom:1px solid var(--line)}
  nav{flex-direction:row;flex-wrap:wrap;padding:0 var(--s-3) var(--s-3)}
  nav .group{display:none}
  main{padding:var(--s-5) var(--s-4) calc(2 * var(--s-6))}
  /* O menu recolhido: a marca e um botão, numa linha. Aberto, os links, a
     conta e a versão voltam embaixo dela. Eram quase 200px no alto de toda
     tela, antes de qualquer conteúdo. */
  .aside-top{gap:var(--s-2);padding-right:var(--s-3)}
  aside.collapsible .menu-toggle{display:inline-flex;align-items:center;gap:var(--s-2);
                                 padding:7px 12px;font-size:var(--t-sm)}
  /* O ponto da conexão no botão tem o tamanho do da barra: fora dela a
     regra de tamanho não valia, e ele saía um quadrado sem cor. */
  .menu-toggle .pip{width:7px;height:7px;border-radius:50%;flex:none}
  aside.collapsible:not(.open) > :not(.aside-top){display:none}
}

/* ---------- números no celular ---------- */
/* Dois cards por linha: um por linha, os oito do painel ocupavam 2.300px. O
   número encolhe para caber em meia tela. */
@media (max-width:560px){
  .cols-4,.cols-3{grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--s-2)}
  .cols-4 .card.stat,.cols-3 .card.stat{padding:var(--s-3)}
  .stat .value{font-size:var(--t-lg);letter-spacing:-.5px;gap:var(--s-1)}
}

/* ---------- tabelas que viram blocos no celular ---------- */
/* Uma tabela larga rolava de lado dentro do cartão, e o que ficava fora da
   tela era justamente o número que se procurava ou o botão. Com .stack,
   cada linha vira um bloco: a primeira célula é o título, as outras dizem
   a coluna delas (data-label) à esquerda e o valor à direita. */
@media (max-width:560px){
  table.stack thead{display:none}
  table.stack, table.stack tbody, table.stack tfoot, table.stack tr{display:block;width:100%}
  table.stack tr{padding:10px 0;border-bottom:1px solid var(--line-soft)}
  table.stack tr:last-child{border-bottom:0}
  table.stack td{display:grid;grid-template-columns:auto 1fr;column-gap:12px;justify-items:end;
                 align-items:baseline;padding:3px 0;border:0;text-align:right;white-space:normal;
                 overflow-wrap:anywhere;min-width:0}
  /* A última célula (as ações) ocupa a linha: telas que a estreitam no
     computador, com width:1% e nowrap, a jogavam para fora do bloco. */
  table.stack td:last-child{width:auto;white-space:normal}
  /* O nome da coluna ocupa a altura toda à esquerda; o valor e o que vem
     embaixo dele (a variação) empilham à direita. */
  table.stack td[data-label]::before{content:attr(data-label);grid-row:span 4;justify-self:start;
                                     color:var(--muted);font-size:var(--t-xs);font-weight:400;text-align:left}
  table.stack td:not([data-label]){display:flex;justify-content:flex-end;gap:6px}
  /* justify-items volta ao normal: o Chrome já alinha blocos por ele, e o
     "end" das outras células jogava o nome embaixo do e-mail para a
     direita. */
  table.stack td:first-child{display:block;justify-items:normal;text-align:left;padding-bottom:6px}
  /* No título do bloco o nome da coluna vai numa linha própria, em cima:
     inline, ele grudava no valor ("EsperouAté 5min"). */
  table.stack td:first-child[data-label]::before{display:block;margin-bottom:2px}
  /* Uma frase (o que precisa de atenção, o que o registro diz) se lê
     inteira, à esquerda, sem nome de coluna. */
  table.stack td.text{display:block;justify-items:normal;text-align:left}
  table.stack td:empty{display:none}
  table.stack tbody tr:hover{background:transparent}
  /* O comparativo: o nome em cima, e agora, antes e a variação lado a lado.
     Empilhados, eram quatro linhas por número. */
  table.versus tbody tr{display:grid;grid-template-columns:repeat(2,minmax(0,1fr)) auto;gap:2px 12px;padding:9px 0}
  table.versus td.label{grid-column:1/-1;padding:0}
  table.versus td.pair{display:none}
  table.versus tbody td[data-label]{display:block;text-align:left;justify-items:start;padding:0}
  table.versus tbody td[data-label]::before{display:block;font-size:var(--t-xs);margin-bottom:1px}
  table.versus tbody td[data-label="Variação"]{text-align:right}
  /* Tabela de números (.pairs): dois valores por linha, o nome da coluna em
     cima de cada um. Um por linha, uma campanha ocupava a tela inteira. */
  table.stack.pairs tbody tr{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:6px 12px}
  table.stack.pairs tbody td{display:block;text-align:left;justify-items:start;padding:0}
  table.stack.pairs tbody td[data-label]::before{display:block;font-size:var(--t-xs);margin-bottom:1px}
  table.stack.pairs tbody td:first-child,table.stack.pairs tbody td:not([data-label]){grid-column:1/-1}
  table.stack.pairs tbody td:not([data-label]){justify-content:flex-start}
}
/* ---------- alvos de toque no celular ---------- */
@media (max-width:560px){
  input[type=checkbox],input[type=radio]{width:20px;height:20px}
  .section-nav a{padding:8px 13px}
  details > summary,details.card > summary{padding:8px 0}
  .card.scroll:has(> table.stack){overflow-x:visible}
}

/* ---------- centred pages (login, recovery) ---------- */
/* ---------- o código de 6 dígitos ---------- */
/* Um quadrado por dígito: lido de relance, conferido contra o app sem
   contar casas. O campo de verdade continua lá, escondido, e é ele que o
   formulário envia; sem script, é ele que aparece. */
/* As caixas dividem a largura que houver, até 46px cada: com largura fixa
   as seis passavam da borda do cartão num celular de 390px. */
.otp{display:flex;gap:var(--s-2);justify-content:flex-start}
.otp input{flex:1 1 0;min-width:0;max-width:46px;height:54px;padding:0;text-align:center;
           font-size:var(--t-xl);font-weight:600;font-variant-numeric:tabular-nums;caret-color:var(--brand)}
.otp-real{position:absolute;width:1px;height:1px;opacity:0;pointer-events:none}
.otp-switch{background:none;border:0;padding:0;margin-top:var(--s-2);color:var(--muted);font-size:var(--t-xs);
            text-decoration:underline;text-underline-offset:2px;cursor:pointer}
.otp-switch:hover{color:var(--ink);background:none}
@media (max-width:380px){.otp{gap:var(--s-1)}.otp input{height:50px;font-size:var(--t-lg)}}
.auth{min-height:100vh;display:grid;place-items:center;padding:var(--s-5)}
.auth .box{width:100%;max-width:368px}
.auth .mark{display:flex;flex-direction:column;align-items:center;gap:var(--s-3);margin-bottom:var(--s-5)}
.auth .mark b{font-size:var(--t-lg);letter-spacing:-.3px}
.auth .mark span{font-size:var(--t-xs);color:var(--muted)}

/* ---------- padrão de componentes (revisão de UI, 23/10/2026) ----------
   Cada peça uma vez, aqui; a página /ui mostra todas. Uma tela nova monta
   com elas e não escreve estilo. */

/* Cabeçalho: o título à esquerda e a ação principal sempre à direita, no
   mesmo lugar em toda tela. No celular a ação fica na linha do título. */
.page-head .actions{margin-left:auto;display:flex;gap:var(--s-2);align-items:center;flex-wrap:wrap}
.page-head .actions form{margin:0}
.page-head .sub a{color:inherit;text-decoration:underline;text-underline-offset:2px}
.page-head .sub{flex-basis:100%;color:var(--muted);font-size:var(--t-sm);margin:0}
/* A linha de baixo do título fica perto dele pelo vão da linha, e não por
   margem negativa; o mesmo para a barra que vem logo depois do cabeçalho. */
.page-head:has(> .sub){row-gap:var(--s-1)}
.page-head:has(+ .compare-bar, + .focus-bar, + .alerts-more){margin-bottom:var(--s-3)}

/* Abas de uma área com telas irmãs, como Campanhas: rolam de lado no
   celular em vez de quebrar em duas linhas. */
.tabs{display:flex;gap:var(--s-1);overflow-x:auto;border-bottom:1px solid var(--line-soft);
  margin:0 0 var(--s-4);scrollbar-width:none}
.tabs::-webkit-scrollbar{display:none}
.tabs a{flex:none;padding:var(--s-2) var(--s-3);color:var(--muted);font-size:var(--t-sm);font-weight:500;
  text-decoration:none;border-bottom:2px solid transparent;margin-bottom:-1px}
/* As abas rolam de lado: o anel de fora seria cortado. */
.tabs a:focus-visible{outline-offset:-2px}
.tabs a:hover{color:var(--ink)}
.tabs a.on{color:var(--brand);border-bottom-color:var(--brand)}

/* Botão com cara de link: a navegação, que não é a ação da tela. */
.btn.link,button.link{background:none;border:0;padding:0;color:var(--brand);font-weight:500;height:auto}
.btn.link:hover,button.link:hover{text-decoration:underline;text-underline-offset:2px;filter:none}

/* Lista em cards: cada item é um link inteiro, com título, situação,
   valor e duas linhas de detalhe. */
.items{display:grid;gap:var(--s-3);grid-template-columns:repeat(auto-fill,minmax(min(280px,100%),1fr))}
.card.item{display:flex;flex-direction:column;gap:var(--s-2);color:inherit;text-decoration:none;
  padding:var(--s-4);transition:border-color var(--dur-fast),background var(--dur-fast);min-width:0}
a.card.item:hover{border-color:var(--panel-3);background:var(--panel-2)}
.item-top{display:flex;justify-content:space-between;align-items:center;gap:var(--s-2);min-width:0}
.item-head{min-width:0}
.item-title{font-weight:650;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.item-sub{display:block;font-size:var(--t-xs);color:var(--muted);min-width:0;overflow:hidden;text-overflow:ellipsis}
.item-value{font-size:var(--t-lg);font-weight:650;letter-spacing:-.4px;font-variant-numeric:tabular-nums}
.item-facts{display:grid;grid-template-columns:auto minmax(0,1fr);gap:2px var(--s-2);font-size:var(--t-xs);margin:0}
.item-facts dt{color:var(--muted)}
.item-facts dd{margin:0;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.item-foot{display:flex;justify-content:space-between;align-items:center;gap:var(--s-2);
  border-top:1px solid var(--line-soft);padding-top:var(--s-2);font-size:var(--t-xs);color:var(--muted)}
.item-foot .go{margin-left:auto;color:var(--brand);font-weight:600}
.item-foot .actions{display:flex;gap:var(--s-2);align-items:center;flex-wrap:wrap;margin-left:auto}
.item-foot form{margin:0}
/* O texto de um card que explica, em vez de resumir: corre em linhas. */
.item-text{font-size:var(--t-sm);color:var(--muted);line-height:1.5;margin:0}
/* O ícone de um card de destino, como uma integração. */
.item-icon{display:inline-flex;flex:none;width:40px;height:40px;align-items:center;justify-content:center;
  border-radius:var(--radius);background:var(--brand-soft);color:var(--brand)}
.item-icon svg{width:24px;height:24px}

/* Ícones em linha, como as formas de pagamento de uma venda. */
.icons{display:inline-flex;gap:var(--s-2);align-items:center;color:var(--muted)}
.icons svg,.method svg{width:18px;height:18px;stroke:currentColor;fill:none;stroke-width:1.75;stroke-linecap:round;stroke-linejoin:round}
/* O ícone com o nome ao lado, na coluna Forma da lista de vendas. */
.method{display:inline-flex;gap:6px;align-items:center;white-space:nowrap}
.method svg{color:var(--muted);flex:none}
.methods{display:flex;flex-direction:column;gap:2px}

/* Uma opção de rádio ou de caixa de marcar, com o texto ao lado; e o grupo
   delas, sem a moldura do fieldset. */
label.choice{display:flex;gap:var(--s-2);align-items:center;min-height:32px;font-weight:400}
label.choice input{width:auto;margin:0}
label.choice .item-sub{margin-top:2px}
/* A opção com duas linhas (o nome e uma explicação): a caixa fica na altura
   da primeira, e não no meio das duas. */
label.choice.top{align-items:flex-start}
label.choice.top input{margin-top:3px}
.row.variant{margin-bottom:var(--s-2);flex-wrap:nowrap}
.row.variant input:first-child{flex:2 1 160px}
.row.variant input:last-child{flex:1 1 110px}
.form-dialog .row > .field{flex:1 1 120px;margin-bottom:var(--s-3)}
/* Formulário de configuração: campos lado a lado que quebram no celular,
   sem sobra de margem no fim do cartão, e o botão de salvar afastado. */
.row.fields > .field{flex:1 1 130px}
.form-narrow > :last-child,.form-narrow > .row:last-child > .field{margin-bottom:0}
.grid-fields{display:grid;grid-template-columns:repeat(auto-fill,minmax(88px,1fr));gap:var(--s-2) var(--s-3);margin-top:var(--s-3)}
.grid-fields .field{margin:0}
.copy-row{display:flex;gap:var(--s-2);align-items:center}
.copy-row code{flex:1;min-width:0;word-break:break-all;font-size:var(--t-xs)}
.form-actions{margin-top:var(--s-4);display:flex;flex-wrap:wrap;gap:var(--s-2);align-items:center}
/* Código de exemplo para copiar ou ler, e uma lista curta de regras. */
.code-block{white-space:pre-wrap;margin:0 0 var(--s-3);padding:var(--s-3);background:var(--panel-2);border-radius:var(--radius-sm);overflow-wrap:anywhere}
/* Um valor curto para copiar ou ditar (um token, um código de pareamento):
   em destaque, numa caixa, quebrando onde precisar. */
.code-box{display:block;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:var(--t-md);
          letter-spacing:.5px;padding:var(--s-3);background:var(--panel-2);border:1px solid var(--line);
          border-radius:var(--radius-sm);overflow-wrap:anywhere;margin:0 0 var(--s-3)}
/* O QR para a câmera: fundo claro e margem branca, que o leitor precisa. */
.qr{display:inline-block;background:var(--qr-bg);padding:var(--s-3);border-radius:var(--radius-sm);line-height:0}
.qr img,.qr svg{display:block;width:220px;height:220px;max-width:100%}
.rules{margin:0;padding-left:18px;line-height:1.6}
.card > .field:last-child{margin-bottom:0}
fieldset.field{border:0;padding:0;margin:0 0 var(--s-3);min-width:0}
fieldset.field legend{font-weight:600;margin-bottom:var(--s-1);padding:0}

/* A ação que destrói, dentro de uma janela: separada do salvar. */
.dialog-danger,.dialog-more{border-top:1px solid var(--line-soft);margin-top:var(--s-4);padding-top:var(--s-3);
  display:flex;flex-wrap:wrap;gap:var(--s-2);align-items:center}
.dialog-danger form,.dialog-more form{margin:0}
.dialog-more h3,.dialog-danger h3{flex-basis:100%;margin:0;font-size:var(--t-sm);color:var(--muted);font-weight:600}
.help.bad{color:var(--danger)}
.help.warn{color:var(--warn)}
/* Peças de texto: link sublinhado no meio de uma frase, um valor bom ou
   ruim, um formulário de um botão só na linha do texto. */
a.u{text-decoration:underline;text-underline-offset:2px}
strong.good,.value.good{color:var(--ok)}
strong.bad,.value.bad{color:var(--danger)}
form.inline{display:inline-block;margin:0 0 0 var(--s-2)}
/* Uma grade de números logo abaixo de outra, e a nota de rodapé dela. */
.next-grid{margin-top:var(--s-3)}
.help.after-grid{margin:var(--s-2) 0 0}
.alerts-more{display:block;margin:0 0 var(--s-4)}

/* Estado vazio: o que vai aparecer ali e o botão para começar. */
.empty{text-align:center;padding:var(--s-6) var(--s-4)}
.empty p{color:var(--muted);margin:0 0 var(--s-4)}

/* Barra de filtros: aplica ao escolher. No celular fica recolhida atrás de
   um botão "Filtros", para a lista aparecer sem rolar. */
.filters{margin:0 0 var(--s-4)}
.filters > summary{display:none}
.filters-body{display:flex;flex-wrap:wrap;gap:var(--s-2) var(--s-3);align-items:flex-end}
.filters-body .field{margin:0;flex:1 1 150px;min-width:0;max-width:240px}
/* A busca com o botão ao lado, numa linha só; e vale por duas colunas na
   barra, porque é onde se digita. */
.filters-body .field.search{flex:2 1 280px;max-width:none}
.filters-body .field.search .row{flex-wrap:nowrap}
.filters-body .field.search input{flex:1;min-width:0}
/* O intervalo de datas: as duas datas e o Aplicar numa linha só. */
.filters-body .field.range{max-width:none;flex:2 1 400px}
.filters-body .field.range .row{flex-wrap:nowrap;align-items:center;gap:var(--s-2)}
.filters-body .field.range input{flex:1;min-width:138px}

/* Faixa de totais: lado a lado no computador; no celular rola de lado, e
   os números não empurram a lista para baixo da dobra. */
.stat-strip{display:grid;gap:var(--s-2);grid-template-columns:repeat(auto-fit,minmax(150px,1fr));margin:0 0 var(--s-5)}
.stat-strip .card.stat{padding:var(--s-3) var(--s-4)}
.stat-strip .stat .value{font-size:var(--t-lg)}

/* O que é técnico (identificadores do clique, do anúncio, do WhatsApp)
   fica recolhido: serve para conferir, não para trabalhar. */
details.tech{margin-top:var(--s-4);border-top:1px solid var(--line-soft);padding-top:var(--s-3)}
details.tech > summary{cursor:pointer;color:var(--muted);font-size:var(--t-xs);list-style:revert}
details.tech[open] > summary{margin-bottom:var(--s-2)}

/* Cabeçalho de um registro (contato, venda): foto, nome e uma linha de
   detalhe, e as ações à direita. No celular as ações descem para baixo do
   nome, que não pode ser espremido até quebrar em duas linhas. */
.entity-head{display:flex;align-items:center;gap:var(--s-3) var(--s-4);flex-wrap:wrap;margin:var(--s-3) 0 var(--s-5)}
.entity-head .who-is{flex:1 1 240px;min-width:0}
.entity-head .actions{display:flex;gap:var(--s-2);flex-wrap:wrap}
@media (max-width:560px){.entity-head .actions{flex-basis:100%}.entity-head .actions > *{flex:1}}

/* O que só cabe numa largura: a tabela no computador, os cards no
   celular; e a coluna que sai no tablet. */
.narrow-only{display:none}
@media (max-width:640px){.wide-only{display:none !important}.narrow-only{display:grid}}
@media (min-width:641px) and (max-width:1000px){.mid-hide{display:none}}

/* Uma pessoa numa lista: a foto, ou a inicial, e o nome. */
.person{display:flex;align-items:center;gap:var(--s-2);min-width:0}
.avatar-sm{width:28px;height:28px;border-radius:50%;flex:none;background:var(--panel-2);object-fit:cover;
  display:grid;place-items:center;font-size:var(--t-xs);font-weight:650;color:var(--brand)}

.avatar-lg{width:52px;height:52px;border-radius:50%;flex:none;background:var(--panel-2);object-fit:cover;
  display:grid;place-items:center;font-size:var(--t-lg);font-weight:650;color:var(--brand)}
.entity-head h1 .tag{vertical-align:middle;margin-left:var(--s-1)}

/* Quem está esperando resposta: âmbar, não vermelho. Vermelho é o que não
   tem conserto; esperar tem. */
.waiting{font-size:var(--t-xs);color:var(--warn)}

/* Um aviso que é um atalho: o aviso inteiro é o link. */
a.banner.attention{display:block;text-decoration:none}
a.banner.attention:hover{filter:brightness(1.08)}

/* O tamanho da página fica na paginação, e não no topo. */
.pager .per-page{display:flex;align-items:center;gap:var(--s-2);margin:0}
.pager .per-page label{margin:0;white-space:nowrap}
.pager .per-page select{width:auto}

/* Texto que não pode empurrar a página para o lado: e-mails, ids, links. */
.wrap-any{overflow-wrap:anywhere;min-width:0}

@media (max-width:720px){
  .filters > summary{display:inline-flex;align-items:center;gap:var(--s-2);cursor:pointer;list-style:none;
    padding:8px 15px;border:1px solid var(--line-strong);border-radius:var(--radius-sm);font-weight:500}
  .filters > summary::-webkit-details-marker{display:none}
  .filters:not([open]) > .filters-body{display:none}
  .filters[open] > summary{margin-bottom:var(--s-3)}
  .stat-strip{display:flex;overflow-x:auto;scroll-snap-type:x mandatory;padding-bottom:var(--s-1)}
  .stat-strip .card.stat{flex:0 0 46%;scroll-snap-align:start}
}


/* ---------- listas que crescem num formulário ---------- */
/* O produto (e o que vier depois): seções com título dentro da janela,
   linhas que se acrescentam, removem e arrastam, o "R$" grudado no campo
   de valor e os botões presos no rodapé da janela, à vista com rolagem. */
.form-section{padding-bottom:var(--s-3);margin-bottom:var(--s-4);border-bottom:1px solid var(--line)}
.form-section:has(+ .form-dialog-actions){border-bottom:0;margin-bottom:0}
.form-section h3{display:flex;align-items:center;gap:var(--s-2);margin:0 0 var(--s-3)}
.prefixed{position:relative;display:flex;align-items:center;min-width:0}
.prefixed > span{position:absolute;left:10px;color:var(--muted);font-size:var(--t-sm);pointer-events:none}
.prefixed > input{padding-left:32px;width:100%}
.repeat{display:flex;flex-direction:column;gap:var(--s-2);margin-bottom:var(--s-2)}
.repeat-row,.repeat-head{display:grid;gap:var(--s-2);align-items:center}
.repeat-head{font-size:var(--t-xs);font-weight:600;color:var(--muted);margin-bottom:var(--s-1)}
.variant-cols{grid-template-columns:24px minmax(0,1fr) 150px 36px}
.deduction-cols{grid-template-columns:110px 130px minmax(0,1fr) 36px}
.repeat-row .product-preview{grid-column:2 / -1;margin:-2px 0 4px}
.product-preview{font-size:var(--t-xs);color:var(--muted);margin:var(--s-1) 0 0}
.repeat-move{background:none;border:0;color:var(--muted);padding:0;width:24px;height:36px;cursor:grab;
             touch-action:none;letter-spacing:-3px;border-radius:var(--radius-sm)}
.repeat-move:hover,.repeat-move:focus-visible{color:var(--ink);background:var(--panel-2);filter:none}
.repeat-remove{background:none;border:0;color:var(--muted);width:36px;height:36px;padding:0;border-radius:var(--radius-sm);
               display:inline-flex;align-items:center;justify-content:center}
.repeat-remove:hover{color:var(--danger);background:var(--danger-soft);filter:none}
.repeat-row.dragging{opacity:.55}
/* Preso ao pé da janela: as margens negativas desfazem o padding dela
   (--s-4), para a faixa ir de borda a borda. */
.form-dialog-actions.sticky{position:sticky;bottom:calc(-1 * var(--s-4));z-index:1;
                            margin:var(--s-3) calc(-1 * var(--s-4)) calc(-1 * var(--s-4));
                            padding:var(--s-3) var(--s-4);background:var(--panel);border-top:1px solid var(--line)}
dialog.form-dialog[open]:not(:modal) .form-dialog-actions.sticky{position:static}
@media (max-width:560px){
  .variant-cols{grid-template-columns:24px minmax(0,1fr) 112px 36px}
  .deduction-cols{grid-template-columns:96px minmax(0,1fr) 36px}
  .deduction-cols > [name=deduction_to]{grid-column:1 / 3}
  .repeat-head.deduction-cols{display:none}
  .repeat-row.deduction-cols{padding-bottom:var(--s-2);border-bottom:1px dashed var(--line)}
}

/* "Registrar venda" na aba Vendas: quem é o contato no alto da janela, e
   os achados da busca como linhas clicáveis. */
.register-who{display:flex;align-items:center;gap:var(--s-2);padding:var(--s-2) var(--s-3);margin:0 0 var(--s-4);
              background:var(--panel-2);border-radius:var(--radius)}
.register-who > div{flex:1;min-width:0}
.register-who .item-sub{display:block}
.register-search .row{display:flex;gap:var(--s-2);flex-wrap:nowrap}
.register-search .row input{flex:1;min-width:0}
.register-found{display:flex;flex-direction:column;margin-top:var(--s-3);border:1px solid var(--line);border-radius:var(--radius)}
.register-found .person{display:flex;align-items:center;gap:var(--s-2);padding:var(--s-2) var(--s-3);text-decoration:none;color:var(--ink)}
.register-found .person + .person{border-top:1px solid var(--line)}
.register-found .person > span:nth-child(2){flex:1;min-width:0}
.register-found .person .item-sub{display:block}
.register-found .person:hover{background:var(--panel-2)}
label.choice.inline{display:inline-flex;margin-right:var(--s-4)}

/* Configurações: os atalhos para o que se configura em outras telas. */
.settings-links{list-style:none;margin:0;padding:0}
.settings-links li{padding:var(--s-2) 0;border-top:1px solid var(--line)}
.settings-links li:first-child{border-top:0;padding-top:0}
.settings-links a{font-weight:600}
.settings-links .item-sub{display:block}
.value.warn,strong.warn{color:var(--warn)}
.item-sub .good{color:var(--ok)}
.item-sub .bad{color:var(--danger)}
/* O retorno embaixo da receita: verde a partir de 1x, vermelho abaixo. */
.roas{font-size:var(--t-xs);color:var(--muted)}
.roas.good{color:var(--ok)}
.roas.bad{color:var(--danger)}
/* Os tons de um número pequeno numa tabela: o custo, o retorno, a taxa. */
.sub.good,.tone.good{color:var(--ok)}
.sub.bad,.tone.bad{color:var(--danger)}
.sub.warn,.tone.warn{color:var(--warn)}

/* ---------- legenda e medidor ---------- */
/* A legenda de um gráfico em HTML: cada série com a amostra do traço que
   ela tem no desenho (linha cheia, tracejada, área). A cor vem da série,
   por uma variável: style="--c:var(--viz-2)". */
.legend{display:flex;flex-wrap:wrap;gap:var(--s-1) var(--s-4);margin:var(--s-2) 0 0;padding:0;list-style:none;
        font-size:var(--t-xs);color:var(--ink-dim)}
.legend-key{display:inline-flex;align-items:center;gap:var(--s-2)}
.legend-swatch{flex:none;display:inline-block;width:14px;height:10px;border-radius:2px;background:var(--c,var(--viz-1))}
.legend-swatch.line{height:0;border-radius:0;background:none;border-top:2px solid var(--c,var(--viz-1))}
.legend-swatch.dash{height:0;border-radius:0;background:none;border-top:2px dashed var(--c,var(--viz-compare))}
.legend-swatch.box{width:10px;background:none;border:2px solid var(--c,var(--viz-1))}
/* Uma barra de quanto já foi usado (cota, prazo, limite): o trilho e a
   parte cheia, no tom do que ela quer dizer. A largura vem no style. */
.meter{display:block;height:6px;border-radius:3px;background:var(--panel-3);overflow:hidden}
.meter > span{display:block;height:100%;border-radius:3px;background:var(--viz-1)}
.meter > span.ok{background:var(--ok)}
.meter > span.warn{background:var(--warn)}
.meter > span.bad{background:var(--danger)}

/* ---------- CSS de cada área ----------
   Daqui para baixo, uma seção por área do produto. Regra que só uma tela
   usa vai na seção da área dela; peça de uso geral vai acima, no padrão. */

/* ---------- área: identidade ---------- */
/* Só as telas de identidade (login, usuários, plataforma) escrevem aqui. */
/* As telas de entrada: o título é o h1 da página, na medida que a marca
   tinha; o botão ocupa o cartão; o link de baixo, centrado e sublinhado. */
.auth .mark .auth-title{font-size:var(--t-lg);letter-spacing:-.3px;margin:0;text-align:center}
.auth .mark span{text-align:center}
.auth form > button{width:100%}
.auth form > button + .help{margin-top:var(--s-3)}
.auth-foot{text-align:center;margin:var(--s-4) 0 0;font-size:var(--t-sm)}
.auth-foot a{color:var(--muted)}
.auth .card > p:first-child,.form-narrow > p:first-child{margin-top:0}
/* O campo do código de 6 dígitos, sem script (com script vira caixas). */
.code-input{letter-spacing:4px;font-size:var(--t-lg)}
.row.fields > .field.code-field{flex:0 0 180px}
/* Num formulário em linha, o campo encosta no botão: a margem de baixo do
   .field descia o botão abaixo da caixa. */
form.row.fields > .field{margin-bottom:0}
/* O que aparece uma vez só (link do convite, token, códigos): um rótulo
   por valor, com respiro entre eles, e o cartão afastado do que vem. */
.secret{margin-bottom:var(--s-4)}
.secret h3.eyebrow{margin:0 0 var(--s-1)}
.secret .copy + h3.eyebrow,.secret .copy + .help{margin-top:var(--s-3)}
.secret .copy + .help + h3.eyebrow{margin-top:var(--s-3)}
.recovery-codes{display:grid;grid-template-columns:repeat(auto-fill,minmax(120px,1fr));gap:var(--s-2);font-size:var(--t-md)}
.two-factor-qr{text-align:center;margin-bottom:var(--s-3)}
/* As ações de uma conta, uma embaixo da outra, cada uma do tamanho dela. */
.action-list{display:flex;flex-direction:column;gap:var(--s-2);align-items:flex-start;margin-top:var(--s-4)}
.action-list form{margin:0}
/* As garantias da autorização no tom do texto, e não apagadas. */
.oauth-rules{color:var(--ink-dim);margin-bottom:var(--s-2)}
/* O "Ordenar por" do relatório da plataforma, só no celular. */
.report-sort{margin-bottom:var(--s-3)}
.report-sort .field{margin:0}
tfoot tr.total td{border-top:1px solid var(--line)}

/* ---------- área: contatos ---------- */
/* Só as telas de contatos (lista, ficha, campos) escrevem aqui. */
/* Também o filtro de período (period.html), a janela de ações da aba
   Campanhas (window.html), Avisos, Atendimento, Link do cliente e o
   Horário de atendimento, que são telas desta área. */

/* Ficha: o cartão das outras conversas da pessoa, com o respiro de um
   cartão comum; e os dois cartões do cadastro, sem um h2 "Dados" por cima,
   com o respiro de uma seção. */
.card.others{margin-bottom:var(--s-4)}
/* O nome do número com o lápis: clicado, abre o campo de renomear. */
details.rename{flex:1;min-width:0}
details.rename>summary{list-style:none;cursor:pointer;display:inline-flex;gap:8px;align-items:center;
  color:var(--ink);padding:0;margin:0}
details.rename[open]>summary{margin:0}
.number-card .item-top{align-items:flex-start}
details.rename>summary::-webkit-details-marker{display:none}
details.rename>summary svg{width:15px;height:15px;stroke:var(--muted);fill:none;stroke-width:1.75;stroke-linecap:round;stroke-linejoin:round;flex:none}
details.rename>summary:hover svg,details.rename[open]>summary svg{stroke:var(--ok)}
.rename-form{display:flex;gap:8px;margin-top:10px}
.rename-form input[name=name]{flex:1;min-width:0}
/* A conversa aberta, entre as da pessoa: borda e fundo verdes. */
.card.others tr.current{outline:2px solid var(--ok);outline-offset:-2px;border-radius:8px;
  background:var(--ok-soft);padding-left:12px;padding-right:12px}
/* Os selos do Lead e da janela, numa linha logo abaixo do nome. */
.who-is .chips{margin:var(--s-1) 0}
.contact-data{margin-top:var(--s-6)}
.help.clicks-title{margin:var(--s-5) 0 var(--s-2)}
/* A janela do cadastro: os campos curtos (UF, país, CEP, número) e a rua,
   que pede o dobro. O resto é o .field de sempre dentro do .row. */
.form-dialog .row > .field.short{flex:0 1 110px}
.form-dialog .row > .field.wide{flex:2 1 200px}
.form-more{margin:var(--s-3) 0}
.form-more > summary{color:var(--muted);font-size:var(--t-sm);cursor:pointer}
.form-more > .row:first-of-type{margin-top:var(--s-3)}
/* O botão principal primeiro no código, que é o que o Enter num campo
   aciona, e por último na tela, como em toda janela. */
.form-dialog-actions.primary-first{flex-direction:row-reverse;justify-content:flex-start}
/* O clique que não pode ser escolhido: cinza pela cor, e não por opacity,
   que derrubava o contraste do texto. */
label.choice.off{color:var(--muted);cursor:not-allowed}
label.choice .tag{margin-left:var(--s-1)}
/* Histórico de eventos: os detalhes e as ações, um embaixo do outro. */
.event-more summary{font-size:var(--t-xs);color:var(--muted);cursor:pointer}
.event-more .help{margin-top:var(--s-2)}
.event-more .code-block{margin:var(--s-1) 0 0}
.event-more form{margin-top:var(--s-2)}
/* Zona de risco: o texto ocupa a linha, o botão fica ao lado ou embaixo. */
.danger-row{align-items:center}
.danger-row > div{flex:1 1 240px}

/* As tags de contatos (spec "Tags de contatos", etapa 1). Uma paleta fixa
   de oito cores, separada das de estado: verde aqui é uma etiqueta que
   alguém escolheu, não "deu certo". O texto é o tom claro, que passa de
   7:1 sobre o fundo -soft no tema escuro; a borda segue o tom, a 35%. */
:root{
  --tag-cinza:#b6bcc9;    --tag-cinza-soft:rgba(182,188,201,.12);  --tag-cinza-line:rgba(182,188,201,.35);
  --tag-vermelho:#f58a8e; --tag-vermelho-soft:rgba(242,104,109,.14); --tag-vermelho-line:rgba(242,104,109,.4);
  --tag-laranja:#f5a46b;  --tag-laranja-soft:rgba(240,140,70,.14); --tag-laranja-line:rgba(240,140,70,.4);
  --tag-amarelo:#f5d36b;  --tag-amarelo-soft:rgba(240,200,60,.13); --tag-amarelo-line:rgba(240,200,60,.4);
  --tag-verde:#7ee0a4;    --tag-verde-soft:rgba(74,222,128,.12);   --tag-verde-line:rgba(74,222,128,.35);
  --tag-azul:#93b9ff;     --tag-azul-soft:rgba(122,167,255,.14);   --tag-azul-line:rgba(122,167,255,.4);
  --tag-roxo:#c0b4f7;     --tag-roxo-soft:rgba(160,140,240,.15);   --tag-roxo-line:rgba(160,140,240,.4);
  --tag-rosa:#f5a3cf;     --tag-rosa-soft:rgba(240,130,190,.14);   --tag-rosa-line:rgba(240,130,190,.4);
}
/* O selo é o .tag, sem o ponto: o ponto diz "está assim agora", e uma tag
   não é um estado. */
.tag[class*="cor-"]::before{display:none}
.tag.cor-cinza{background:var(--tag-cinza-soft);color:var(--tag-cinza);border-color:var(--tag-cinza-line)}
.tag.cor-vermelho{background:var(--tag-vermelho-soft);color:var(--tag-vermelho);border-color:var(--tag-vermelho-line)}
.tag.cor-laranja{background:var(--tag-laranja-soft);color:var(--tag-laranja);border-color:var(--tag-laranja-line)}
.tag.cor-amarelo{background:var(--tag-amarelo-soft);color:var(--tag-amarelo);border-color:var(--tag-amarelo-line)}
.tag.cor-verde{background:var(--tag-verde-soft);color:var(--tag-verde);border-color:var(--tag-verde-line)}
.tag.cor-azul{background:var(--tag-azul-soft);color:var(--tag-azul);border-color:var(--tag-azul-line)}
.tag.cor-roxo{background:var(--tag-roxo-soft);color:var(--tag-roxo);border-color:var(--tag-roxo-line)}
.tag.cor-rosa{background:var(--tag-rosa-soft);color:var(--tag-rosa);border-color:var(--tag-rosa-line)}
.tag.more::before{display:none}
/* Na linha da lista, embaixo do nome; no card do celular, numa linha só. */
.person-tags{gap:var(--s-1);margin-top:var(--s-1)}
.contact-list td .person-tags{padding-left:36px}
/* Na ficha: cada selo com o × que o tira, e o "Adicionar tag" ao lado. O ×
   tem 24px de alvo dentro do selo, sem mudar a altura dele. */
.who-is .person-tags{align-items:center;margin:var(--s-1) 0}
.tag-chip{margin:0;display:inline-flex}
.tag-x{all:unset;box-sizing:border-box;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;
       width:24px;height:20px;margin:-2px calc(-1 * var(--s-2)) -2px 0;border-radius:99px;font-size:var(--t-md);line-height:1;opacity:.8}
.tag-x:hover{opacity:1;background:rgba(255,255,255,.08)}
.tag-x:focus-visible{outline:2px solid var(--brand);outline-offset:1px}
/* O "Adicionar tag" abre a busca numa caixa sob o botão, por cima da
   página, sem descer o resto do cabeçalho; no celular, na linha de baixo. */
.tag-add{position:relative}
.tag-add > summary{list-style:none;cursor:pointer;width:max-content;margin:0}
.tag-add > summary::-webkit-details-marker{display:none}
.tag-add-form{display:flex;gap:var(--s-2);align-items:center;margin:0;position:absolute;left:0;top:calc(100% + var(--s-1));
  z-index:var(--z-pop);width:340px;padding:var(--s-2);border:1px solid var(--line-strong);border-radius:var(--radius);
  background:var(--panel);box-shadow:0 10px 28px rgba(0,0,0,.4)}
.tag-add-form input{flex:1;min-width:0}
@media (max-width:640px){
  .tag-add[open]{flex-basis:100%}
  .tag-add-form{position:static;width:auto;margin-top:var(--s-2);padding:0;border:0;background:none;box-shadow:none}
}
/* O histórico das tags: uma linha por mudança, a mais nova em cima. */
.tag-history{list-style:none;margin:0;padding:0;display:grid;gap:var(--s-2)}
.tag-history li{color:var(--ink-dim);font-size:var(--t-sm)}
/* A paleta na janela: cada cor é o próprio selo, e a marcada ganha o anel. */
.tag-palette{display:flex;flex-wrap:wrap;gap:var(--s-2);border:0;padding:0;margin:0 0 var(--s-4)}
/* A legenda "Cor" com o jeito dos rótulos dos campos ("Nome"), e não o de
   um título. */
.tag-palette legend{width:100%;font-size:var(--t-xs);color:var(--muted);font-weight:500;margin-bottom:var(--s-1)}
.swatch{position:relative;display:inline-flex;align-items:center;margin:0;cursor:pointer}
.swatch input{position:absolute;left:0;top:0;opacity:0;width:1px;height:1px}
.swatch .tag{font-size:var(--t-sm);padding:var(--s-1) var(--s-3)}
.swatch input:checked + .tag{box-shadow:0 0 0 2px var(--ink)}
.swatch input:focus-visible + .tag{outline:2px solid var(--brand);outline-offset:2px}
/* O filtro de tags: fechado parece um select, com o que escolheu; aberto,
   ocupa a linha com o "tem" e o "não tem" lado a lado. */
.tag-filter-field > .label{display:block;font-size:var(--t-xs);color:var(--muted);margin-bottom:var(--s-1);font-weight:500}
.tag-filter{position:relative}
.tag-filter > summary{list-style:none;cursor:pointer;height:40px;display:flex;align-items:center;margin:0;font-weight:400;color:var(--ink);
  padding:0 36px 0 11px;border:1px solid var(--line-strong);border-radius:var(--radius-sm);background:var(--panel-2);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;position:relative}
.tag-filter > summary::-webkit-details-marker{display:none}
/* Aberto, o botão fica onde estava: a margem do título de um details
   aberto desceria o seletor e a barra junto. */
:is(.tag-filter,.tag-add)[open] > summary{margin-bottom:0}
.tag-filter > summary::after{content:"";position:absolute;right:13px;top:50%;width:6px;height:6px;margin-top:-5px;
  border-right:1.6px solid var(--muted);border-bottom:1.6px solid var(--muted);transform:rotate(45deg)}
.tag-filter > summary:hover{border-color:var(--muted)}
.tag-filter > summary:focus-visible{outline:none;border-color:var(--brand);box-shadow:0 0 0 3px var(--brand-soft)}
.tag-filter[data-active="1"] > summary{color:var(--ink);border-color:var(--brand-line)}
/* Aberto, a lista desce por cima da página, como a de um select, e não
   empurra a barra: uma caixa por tag, e o Aplicar embaixo. */
.tag-filter-body{position:absolute;left:0;top:calc(100% + var(--s-1));z-index:var(--z-pop);min-width:100%;width:max-content;max-width:min(320px,calc(100vw - 32px));
  display:grid;gap:var(--s-2);padding:var(--s-2);border:1px solid var(--line-strong);border-radius:var(--radius);
  background:var(--panel);box-shadow:0 10px 28px rgba(0,0,0,.4)}
.tag-filter-list{display:grid;max-height:280px;overflow:auto}
.tag-filter-list label.choice{display:flex;align-items:center;gap:var(--s-2);margin:0;padding:var(--s-1) var(--s-2);border-radius:var(--radius-sm);cursor:pointer}
.tag-filter-list label.choice:hover{background:var(--panel-2)}
.tag-filter-actions{display:flex;justify-content:flex-end;padding-top:var(--s-2);border-top:1px solid var(--line-soft)}
/* Os filtros salvos (etapa 3 das tags): atalhos numa linha acima da lista,
   que quebra em quantas precisar. Um nome comprido é cortado com "…" dentro
   do atalho, e a página nunca rola de lado por causa dele. */
.saved-filters{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:var(--s-2) var(--s-4);
  margin:0 0 var(--s-3);min-width:0}
.saved-filter-list{display:flex;flex-wrap:wrap;align-items:center;gap:var(--s-2);min-width:0;max-width:100%}
.saved-filter-list .eyebrow{margin:0 var(--s-1) 0 0}
.saved-filter-actions{display:flex;flex-wrap:wrap;gap:var(--s-2);align-items:center}
.filter-chip{display:inline-flex;align-items:center;gap:var(--s-1);max-width:100%;min-width:0;min-height:32px;padding:0 var(--s-3);
  border:1px solid var(--line);border-radius:99px;background:var(--panel);color:var(--ink-dim);font-size:var(--t-sm);text-decoration:none}
.filter-chip > span:first-child{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}
.filter-chip:hover{border-color:var(--brand);color:var(--ink)}
.filter-chip:focus-visible{outline:2px solid var(--brand);outline-offset:1px}
.filter-chip.on{background:var(--brand-soft);border-color:var(--brand-line);color:var(--brand);font-weight:600}
.filter-chip-warn{display:inline-flex;align-items:center;justify-content:center;flex:none;width:16px;height:16px;border-radius:99px;
  background:var(--warn-soft);color:var(--warn);font-size:var(--t-xs);font-weight:700}
/* A janela de editar: uma linha por filtro, o nome para renomear e o
   Excluir ao lado. */
.saved-filter-edit{list-style:none;margin:0 0 var(--s-4);padding:0;display:grid;gap:var(--s-3)}
.saved-filter-edit li{display:flex;flex-wrap:wrap;align-items:center;gap:var(--s-2)}
.saved-filter-edit li .item-sub{flex-basis:100%}
.saved-filter-rename{display:flex;gap:var(--s-2);align-items:center;flex:1 1 220px;min-width:0;margin:0}
.saved-filter-rename input[name="name"]{flex:1;min-width:0}
/* A seleção da lista e as ações em massa (etapa 2 das tags). Tudo só com
   o script, que acende .bulk-on: sem ele as caixas não aparecem, e a lista
   é a de sempre. */
.contacts-bulk:not(.bulk-on) :is(.pick,.bulk-head){display:none}
.contact-list :is(th,td).pick{width:1%;padding-right:0}
/* A caixa ocupa a célula inteira: um clique perto dela marca, e não abre a
   ficha (a linha inteira é um link). */
.contact-list .pick label{display:flex;align-items:center;justify-content:center;min-width:28px;min-height:28px;margin:0;cursor:pointer}
.bulk-head{display:flex;flex-wrap:wrap;align-items:center;gap:var(--s-2) var(--s-4);margin:0 0 var(--s-3);font-size:var(--t-sm)}
.bulk-head label.choice{margin:0}
/* No computador a caixa da página fica no cabeçalho da tabela; a linha de
   cima só aparece com o convite para o filtro inteiro. */
@media (min-width:641px){.bulk-head > label.choice{display:none}.bulk-head:not(:has(.bulk-all:not([hidden]))){display:none}}
.bulk-all{color:var(--ink-dim);min-width:0}
/* No celular a caixa fica no canto do card, por cima, fora do link. */
.contact-pick{position:relative;min-width:0;display:grid}
.contact-pick > .pick{position:absolute;left:var(--s-2);top:var(--s-3);z-index:1;display:flex;margin:0;padding:var(--s-2);cursor:pointer}
.bulk-on .contact-pick > a.card.item{padding-left:44px}
/* A barra: colada embaixo enquanto a lista rola, na largura da lista — e
   não da janela, que no computador passaria por cima do menu. Quebra em
   duas linhas no celular, em vez de passar da borda. */
.bulk-bar{position:sticky;bottom:var(--s-3);z-index:var(--z-sticky);display:flex;flex-wrap:wrap;align-items:center;
  justify-content:space-between;gap:var(--s-2) var(--s-3);margin-top:var(--s-3);padding:var(--s-3) var(--s-4);
  background:var(--panel-2);border:1px solid var(--brand-line);border-radius:var(--radius);box-shadow:0 10px 30px rgba(0,0,0,.45)}
.bulk-bar.static{position:static;box-shadow:none}
.bulk-count{font-variant-numeric:tabular-nums}
.bulk-actions{display:flex;flex-wrap:wrap;gap:var(--s-2);align-items:center}
.bulk-actions button.link{font-size:var(--t-xs);padding:0 var(--s-1)}
/* A janela: a frase com a tag no meio, e o botão que destrói vermelho
   cheio, com texto escuro, como o sim da confirmação destrutiva. */
.win-sub.bulk-scope{margin:calc(-1 * var(--s-3)) 0 var(--s-4)}
.bulk-question{line-height:1.6}
.bulk-body > .banner{margin-bottom:var(--s-3)}
button.destructive{background:var(--danger);color:var(--bg)}

/* Link do cliente. */
.share-card{margin-bottom:var(--s-4)}
.share-new{max-width:560px}
.share-link{word-break:break-all;text-align:left}

/* O período personalizado: as duas datas, o "até" e o botão quebram de
   linha no celular, em vez de passar da borda. */
.period-range{display:flex;flex-wrap:wrap;gap:var(--s-2);align-items:center}
.period-range input[type=date]{width:auto}
@media (max-width:560px){
  .period-range{flex-basis:100%}
  .period-range input[type=date]{flex:1 1 130px;min-width:0}
  .period-range button{flex-basis:100%}
}

/* A janela de ações da aba Campanhas: a largura e o respiro são os do
   form-dialog. Abre já com o esqueleto, e escurece enquanto um pedido
   está indo. */
dialog.row-window[aria-busy=true] .row-window-body{opacity:.55;pointer-events:none;transition:opacity var(--dur-fast) var(--dur-fast)}
.win-loading{display:grid;gap:var(--s-3)}
.win-sub{margin:var(--s-1) 0 0;color:var(--muted);font-size:var(--t-sm)}
.win-sub strong{color:var(--ink-dim)}
.row-window .form-dialog-head{align-items:flex-start}

/* Avisos: um cartão por fila, com o número grande à esquerda. A borda diz
   que o aviso é grave, além da cor do número e do selo. */
.alert-page{max-width:820px}
.alert-list{display:grid;gap:var(--s-3)}
.alert-card{display:grid;grid-template-columns:auto 1fr auto;gap:var(--s-1) var(--s-4);align-items:center}
.alert-card .n{font-size:var(--t-xl);font-weight:650;min-width:2ch;text-align:right;font-variant-numeric:tabular-nums;
               grid-row:span 2;color:var(--warn)}
.alert-card.bad{border-color:var(--danger-line)}
.alert-card.bad .n{color:var(--danger)}
.alert-card strong{font-size:var(--t-md)}
.alert-card p{margin:0;color:var(--ink-dim);font-size:var(--t-sm);grid-column:2}
.alert-card .btn{grid-row:span 2;grid-column:3}
.alerts-clear{margin:var(--s-1) 0 0;font-size:var(--t-sm)}
@media (max-width:560px){
  .alert-card{grid-template-columns:auto 1fr}
  .alert-card .btn{grid-column:1/-1;grid-row:auto;justify-self:start;margin-top:var(--s-2)}
}

/* Atendimento: os números das tabelas ficam à esquerda, sob o título, e a
   barra da taxa acompanha, em vez de ir para a outra ponta da célula. */
.hbar-cell.start{justify-content:flex-start}

/* Horário de atendimento: um dia por linha, o nome à esquerda e as duas
   horas alinhadas entre si. Em grade, e não em flex, porque os nomes têm
   larguras diferentes e soltos deixavam as horas em degrau. */
.hours-card{max-width:760px}
.hours-card + .hours-card{margin-top:var(--s-4)}
.hours-card .field{margin-bottom:0}
.hours-grid{display:grid;gap:var(--s-2)}
.hours-row{display:grid;grid-template-columns:130px auto 24px auto;align-items:center;gap:var(--s-2)}
/* A caixa do dia com 32px de alvo: o rótulo media 19px. */
.hours-row .day{display:flex;align-items:center;gap:var(--s-2);margin:0;min-height:32px;cursor:pointer}
.hours-row .day input{width:auto;margin:0}
.hours-row input[type=time]{width:auto}
.hours-row .until-label{color:var(--muted);font-size:var(--t-xs);text-align:center}
/* O dia desmarcado esmaece as horas: elas continuam lá para quando for
   reaberto, mas não se parecem com um horário em vigor. */
.hours-row:has(input[type=checkbox]:not(:checked)) input[type=time]{opacity:.45}
/* No celular o dia vai numa linha e as duas horas embaixo, dividindo a
   largura: lado a lado com o nome, elas passavam da borda do cartão. */
@media (max-width:640px){
  .hours-grid{gap:var(--s-3)}
  .hours-row{grid-template-columns:minmax(0,1fr) 24px minmax(0,1fr);row-gap:var(--s-2)}
  .hours-row .day{grid-column:1 / -1}
  .hours-row input[type=time]{width:100%;min-width:0}
}

/* A importação por planilha (etapa 4 das tags): os passos no alto, os
   campos da ficha em grade, as tags escolhidas e a caixa da declaração. */
.import-flow > .card + .card{margin-top:var(--s-4)}
.import-flow .stat-strip .card{margin:0}
.import-steps{display:flex;flex-wrap:wrap;gap:var(--s-1) var(--s-3);list-style:none;padding:0;margin:0 0 var(--s-4);
  counter-reset:step;font-size:var(--t-xs);color:var(--muted)}
.import-steps li{counter-increment:step}
.import-steps li::before{content:counter(step) ". "}
.import-steps li[aria-current]{color:var(--ink);font-weight:600}
.import-map{display:grid;grid-template-columns:repeat(auto-fill,minmax(200px,1fr));gap:0 var(--s-3)}
.import-map select{width:100%;min-width:0}
.import-tags{display:flex;flex-wrap:wrap;gap:var(--s-1) var(--s-4)}
.import-file{overflow-wrap:anywhere}
.import-preview td{white-space:nowrap}
.import-flow .field > select,.import-flow .field > input:not([type=checkbox]){max-width:420px}
.import-flow .import-map .field > select{max-width:none}
.import-declare .choice{font-weight:400}
.import-declare .item-sub{display:block}
.import-progress .meter{margin:var(--s-3) 0}
input[type=file]{height:auto;padding:var(--s-2) 0;max-width:100%;color:var(--muted)}
/* O botão do arquivo com o jeito dos botões fantasma, e não o cinza do
   navegador. */
input[type=file]::file-selector-button{font:inherit;font-weight:600;color:var(--ink);background:transparent;cursor:pointer;
  border:1px solid var(--line-strong);border-radius:var(--radius-sm);padding:var(--s-2) var(--s-3);margin-right:var(--s-3)}
input[type=file]::file-selector-button:hover{border-color:var(--muted)}

/* ---------- área: painel e relatórios ---------- */
/* Só as telas do painel, dos relatórios e do atendimento escrevem aqui. */

/* O SVG do gráfico: bloco, e o traço da borda pode passar do viewBox. */
.chart-svg{display:block;overflow:visible}
/* O link de um card de total: alvo de toque de verdade, e não uma palavra
   de 13px de altura colada na dica. */
.stat-link{display:inline-block;padding:var(--s-1) 0;color:var(--ink-dim);
           text-decoration:underline;text-underline-offset:2px}
.stat-link:hover{color:var(--ink)}

/* Os relatórios descem a barra de comparar e a de campanha logo abaixo do
   título, sem margem negativa: o respiro do .page-head já é da escala. */
.focus-bar .help{margin-top:var(--s-1)}

/* Do clique ao lead / à venda: o número no tamanho do valor dos cards, e a
   barra da janela de 7 dias ao lado. */
.median{display:flex;justify-content:space-between;align-items:baseline;gap:var(--s-3);flex-wrap:wrap}
.median .stat .value{margin-top:0}
.median-window{flex:1;min-width:220px}
.median-window .help{margin-top:var(--s-2)}

/* A segunda linha do nome com selos ao lado: o .item-sub vira linha
   flexível, com o mesmo respiro entre o selo e o texto. */
.item-sub.row-meta{display:flex;flex-wrap:wrap;gap:var(--s-2);align-items:center;margin-top:var(--s-1)}

/* ---------- público e roscas ---------- */
/* Barras dos recortes de público: finas, ponta arredondada só no fim, e 2px
   de fundo separando os pedaços de uma barra empilhada. Azul e laranja são
   as duas primeiras cores da paleta validada contra o fundo do painel,
   inclusive simulando daltonismo; cinza é o que o Meta não soube dizer. */
.aud .viz-1{background:var(--viz-1)}
.aud .viz-2{background:var(--viz-2)}
.aud .viz-na{background:var(--viz-na)}
.aud th.bar-cell,.aud td.bar-cell{width:34%;min-width:150px}
.aud .track{display:flex;gap:2px;height:14px}
.aud .seg{height:100%;flex:0 1 auto;min-width:2px}
.aud .seg:last-child{border-radius:0 4px 4px 0}
.aud .seg:hover,.aud .seg:focus-visible{filter:brightness(1.18)}
.aud .split{font-size:var(--t-xs);color:var(--muted);margin-top:var(--s-1)}
.aud .legend{margin:0 0 var(--s-3)}
.aud td.label{white-space:nowrap}
.aud td.label .legend-swatch{margin-right:var(--s-2)}
.aud .share th.bar-cell,.aud .share td.bar-cell{width:44%;min-width:110px}
@media (max-width:820px){
  .aud th.bar-cell,.aud td.bar-cell{min-width:110px;width:auto}
}
/* No celular a barra ocupa a linha inteira, embaixo do nome da faixa: como
   célula de um bloco ela encolhia até sumir. O justify-items volta ao
   normal pelo mesmo motivo da primeira célula: o Chrome alinha blocos por
   ele, e o "end" das outras células encolhia a barra a seis pixels. */
@media (max-width:560px){
  .aud table.stack td.bar-cell{display:block;justify-items:normal;width:auto;min-width:0;
                               padding:2px 0 var(--s-2);text-align:left}
  .aud table.stack td.label{white-space:normal}
}
/* A melhor conversão da tabela, marcada no número e não na cor da linha:
   a linha inteira pintada competia com as barras. */
.aud .best{color:var(--ok);font-weight:650}
/* A rosca ao lado da tabela que a explica, quando as duas cabem; quando
   não, em cima dela e no meio. A tabela pede 380px: com menos, a coluna do
   gasto era cortada pela rolagem do card, e o valor saía "R$ 1.94". */
.aud-split{display:flex;gap:var(--s-5);align-items:center;justify-content:center;flex-wrap:wrap}
.aud-split > .scroll{flex:1 1 380px;min-width:0}
/* A rosca é um componente do chart.html: o estilo dela mora aqui, e não
   na página que a usou primeiro. */
.donut{margin:0;flex:none}
.donut svg{display:block}
.donut .arc{transition:filter var(--dur-fast)}
.donut .arc:hover{filter:brightness(1.2)}
/* O miolo é só leitura: não pode tomar o ponteiro de quem mira o anel. */
.donut text{pointer-events:none}
.donut-total{fill:var(--ink);font-size:var(--t-lg);font-weight:650}
.donut-unit{fill:var(--muted);font-size:var(--t-xs)}
@media (prefers-reduced-motion:reduce){.donut .arc{transition:none}}
/* A dica das barras de público vive solta no body, presa à tela, e por
   cima do índice de seções, que também é preso. */
.chart-tip.aud-tip{position:fixed;z-index:var(--z-pop)}

/* ---------- relatório do cliente ---------- */
/* A página do cliente usa o .auth do layout, que é a caixa centrada do
   login: aqui ela vira uma página larga, de cima para baixo. */
.auth:has(> .client-report){display:block;place-items:normal;min-height:0;
  padding:var(--s-6) var(--s-4);max-width:1080px;margin:0 auto}
.client-head{display:flex;gap:var(--s-3);align-items:flex-start;justify-content:space-between;flex-wrap:wrap;margin-bottom:var(--s-2)}
.client-head h1{margin:0}
.client-head p{margin:var(--s-1) 0 0}
.client-periods{margin:var(--s-3) 0 var(--s-4)}
.client-foot{margin-top:var(--s-5);font-size:var(--t-xs);color:var(--muted);display:flex;gap:var(--s-2);align-items:center}
.client-gone{max-width:480px;margin:12vh auto 0;text-align:center}
.client-gone h1{margin-top:0}
.client-gone p{margin-bottom:0}
@media print{
  .no-print{display:none !important}
  .auth:has(> .client-report){padding:0;max-width:none}
  .client-report .card{break-inside:avoid}
}

/* ---------- área: campanhas ---------- */
/* Só as telas de campanhas (e as abas irmãs dela) escrevem aqui. */
/* Campanhas: a árvore. O conjunto recua debaixo da campanha, e o anúncio
   debaixo do conjunto. O recuo é no nome, e não na linha, para as colunas
   de número continuarem alinhadas de cima a baixo. */
.tree-filters{display:flex;gap:var(--s-2);align-items:center;flex-wrap:wrap}
.tree td.item{min-width:330px;max-width:380px}
.tree tr.lvl-adset td.item{padding-left:var(--s-6)}
.tree tr.lvl-ad td.item{padding-left:calc(var(--s-6) + var(--s-5))}
.tree tr.lvl-campaign td{border-top:1px solid var(--line)}
.tree tr.lvl-ad td{color:var(--ink-dim)}
.tree td{vertical-align:top;padding-top:var(--s-3);padding-bottom:var(--s-3)}
/* A primeira coluna fica parada quando a tabela rola de lado: sem ela, um
   custo lá na direita não diz de que campanha é. A sombra à esquerda cobre
   o respiro do cartão (sem ela, o que rolava por baixo da coluna aparecia
   nessa faixa), e a linha à direita separa a coluna parada das que andam. */
.tree th:first-child,.tree td.item{position:sticky;left:0;z-index:2;background:var(--panel);
                                   box-shadow:inset -1px 0 0 var(--line)}
.tree th:first-child::before,.tree td.item::before{content:"";position:absolute;top:0;bottom:0;right:100%;
                                                   width:var(--s-5);background:inherit}
.tree tbody tr:hover td.item{background:var(--panel-2)}
/* A coluna parada é uma camada própria (z-index 2), e a dica aberta numa
   linha ficava embaixo da coluna da linha seguinte: a célula com a dica
   aberta sobe um degrau. */
.tree td.item:has(.tip:hover,.tip:focus-within){z-index:3}
/* No tablet a coluna parada não pode comer a tela: com 330px fixos, a 600px
   sobravam uns 200 para rolar vinte e quatro colunas. */
@media (max-width:1000px){.tree td.item{min-width:min(330px,45vw)}}
/* A linha do nome: a seta, o nome com o estado embaixo, e as ações à
   direita, sempre no mesmo lugar. */
.item-row{display:flex;align-items:flex-start;gap:var(--s-2)}
.item-main{flex:1;min-width:0}
.more-nums{display:none}
.ad-thumb{width:36px;height:36px;border-radius:var(--radius-sm);object-fit:cover;flex:none;background:var(--line)}
/* A linha de baixo do nome na árvore (criativo, público): numa linha só e
   cortada, para a linha da tabela não crescer. Não é o .item-sub do
   padrão, que quebra. */
.tree-sub{font-size:var(--t-xs);color:var(--muted);margin-top:var(--s-1);overflow:hidden;text-overflow:ellipsis;
          white-space:nowrap;max-width:46ch}
.item-main .name{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;
                 overflow-wrap:anywhere;line-height:1.35}
.item-acts{display:flex;gap:2px;flex:none;margin:calc(-1 * var(--s-1)) calc(-1 * var(--s-1)) 0 0}
/* A seta com 24px, o mínimo de um alvo de toque; o anel é o --brand, como
   em todo o resto (o all:unset tira o do navegador). */
.tree .twist,.tree .twist-gap{flex:none;width:24px;height:24px}
.tree .twist{all:unset;box-sizing:border-box;cursor:pointer;display:inline-flex;width:24px;height:24px;flex:none;
             align-items:center;justify-content:center;color:var(--muted);border-radius:var(--radius-sm)}
.tree .twist:hover{color:var(--ink);background:var(--panel-3)}
.tree .twist:focus-visible{outline:2px solid var(--brand);outline-offset:1px}
.tree .twist svg{transition:transform var(--dur-fast)}
.tree .twist[aria-expanded="true"] svg{transform:rotate(90deg)}
@media (prefers-reduced-motion:reduce){.tree .twist svg{transition:none}}
.tree .diverge{display:grid;gap:2px;justify-items:start}
.tree .diverge + .diverge{margin-top:var(--s-2)}
.tree .diverge .tag{white-space:nowrap}
.tree .state{font-size:var(--t-xs);margin-top:var(--s-1);display:flex;flex-wrap:wrap;gap:var(--s-1) var(--s-2);
             align-items:center;color:var(--muted)}
/* A verba é o que mais se mexe na linha, e mexe-se nela mesma: o valor é
   o botão. */
.budget-chip{display:inline-flex;align-items:center;gap:var(--s-1);padding:2px var(--s-2);border-radius:99px;
             border:1px solid var(--line);color:var(--ink);text-decoration:none;font-weight:500;
             font-variant-numeric:tabular-nums;white-space:nowrap}
.budget-chip svg{color:var(--muted)}
.budget-chip:hover{border-color:var(--brand);background:var(--brand-soft)}
.budget-chip:hover svg{color:var(--brand)}
.budget-chip:focus-visible{outline:2px solid var(--brand);outline-offset:1px}
.icon-btn{all:unset;box-sizing:border-box;cursor:pointer;display:inline-flex;width:28px;height:28px;
          align-items:center;justify-content:center;border-radius:var(--radius-sm);color:var(--muted)}
.icon-btn:hover{color:var(--ink);background:var(--panel-3)}
.icon-btn:focus-visible{outline:2px solid var(--brand);outline-offset:1px}
/* Os dois lados da comparação: uma borda entre os grupos e o nome de cada
   um em cima, para ninguém ler um custo na régua errada. O nome do grupo é
   um th como os outros. */
.tree th.group{text-align:left}
.tree .edge{border-left:1px solid var(--line)}
/* O menu da linha abre por cima de tudo (popover), e não dentro da tabela:
   dentro, a borda do cartão, que rola de lado, cortava as últimas ações. */
.row-pop{position:fixed;inset:auto;margin:0;padding:var(--s-1);min-width:190px;background:var(--panel-2);color:var(--ink);
         border:1px solid var(--line);border-radius:var(--radius);box-shadow:0 12px 32px rgba(0,0,0,.45);font-size:var(--t-sm)}
.row-pop a{display:flex;align-items:center;gap:var(--s-2);padding:var(--s-2) var(--s-3);border-radius:var(--radius-sm);
           color:var(--ink);text-decoration:none;white-space:nowrap}
.row-pop a:hover{background:var(--panel-3)}
/* O fundo do foco quase não se distingue do menu (1,1:1): o anel diz qual
   ação está escolhida, e uma delas é Excluir. */
.row-pop a:focus-visible{background:var(--panel-3);outline:2px solid var(--brand);outline-offset:-2px}
.row-pop a svg{color:var(--muted);flex:none}
.row-pop a.danger,.row-pop a.danger svg{color:var(--danger)}
.row-pop hr{border:0;border-top:1px solid var(--line);margin:var(--s-1) 0}
/* Onde o navegador não tem popover, o menu fica à vista dentro da linha. */
.row-pop:not([popover]){position:static;box-shadow:none}
/* O resumo do que está na lista, antes dela. */
.tree-sum{margin:0 0 var(--s-4)}
.tree-sum .recs{display:flex;flex-wrap:wrap;gap:var(--s-2);margin-top:var(--s-2)}
.tree-sum .recs a{text-decoration:none}
.tree-sum .recs + .hint{margin-top:var(--s-2)}
.tree-sum .value.none{font-size:var(--t-md);letter-spacing:0;color:var(--ink-dim)}
/* A barra da tabela: o que muda o que se vê à esquerda, e para onde mais
   ir à direita. */
.tree-bar{display:flex;flex-wrap:wrap;gap:var(--s-2);align-items:center;margin:0 0 var(--s-3)}
.tree-bar .spacer{flex:1}
.col-pick[open]{flex-basis:100%;order:9}
.col-pick{font-size:var(--t-sm)}
.col-pick summary{list-style:none;width:max-content;cursor:pointer}
.col-pick summary::-webkit-details-marker{display:none}
.col-pick[open] summary{background:var(--panel-2)}
/* Um grupo por lado, na ordem da tabela, cada um com o nome dele: "Leads"
   existe dos dois lados. */
.col-pick-list{display:grid;gap:var(--s-3);padding:var(--s-3);border:1px solid var(--line);border-radius:var(--radius);
               background:var(--panel);margin-top:var(--s-2)}
.col-pick-list fieldset{border:0;margin:0;padding:0;min-width:0;display:flex;flex-wrap:wrap;gap:var(--s-2) var(--s-4)}
.col-pick-list legend{padding:0;margin-bottom:var(--s-2)}
.col-pick-list label{display:inline-flex;gap:var(--s-2);align-items:center;font-weight:400;margin:0}
.col-pick-list input{width:auto}
/* Vinte e quatro colunas: com o respiro padrão a divergência, que é a
   coluna da decisão, ficava fora da tela num notebook. */
.tree th,.tree td{padding-left:var(--s-2);padding-right:var(--s-2)}
/* No celular cada linha vira um cartão: o nome em cima, e os números em
   duas colunas, o nome de cada um em cima do valor. O que não tem valor
   (o travessão) some: eram dezesseis linhas por item, a maioria vazia. O
   recuo dos níveis é por dentro da linha, e não pela margem, que a
   empurrava para fora da tela. A borda entre os grupos sai: empilhada,
   ela virava um risco solto à esquerda. */
@media (max-width:560px){
  .tree .edge{border-left:0}
  .tree th:first-child,.tree td.item{position:static;max-width:none;min-width:0;box-shadow:none;background:none}
  .tree th:first-child::before,.tree td.item::before{display:none}
  .tree tbody tr{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--s-2) var(--s-4);padding:var(--s-3) 0}
  .tree tbody tr[hidden]{display:none}
  .tree tbody td{padding:0}
  .tree tbody td.item{grid-column:1/-1;padding:0 0 var(--s-1)}
  .tree tr.lvl-adset td.item,.tree tr.lvl-ad td.item{padding-left:0}
  .tree tr.lvl-adset{padding-left:var(--s-4)}
  .tree tr.lvl-ad{padding-left:var(--s-6)}
  .tree tbody td[data-label]{display:block;text-align:left;justify-items:start}
  .tree tbody td[data-label]::before{display:block;font-size:var(--t-xs);margin-bottom:1px}
  .tree tbody td[data-col="diverge"],.tree tbody td[data-col="rec"]{grid-column:1/-1}
  .tree tbody td:has(> .muted:only-child){display:none}
  .tree tbody td[hidden]{display:none}
  .tree .diverge{grid-template-columns:auto 1fr;align-items:center;column-gap:var(--s-2)}
  /* Os alvos do dedo: abrir o ramo, pausar, o menu e a verba eram de 18 a
     28px, as ações principais da aba. */
  .tree .twist,.tree .twist-gap{width:32px;height:32px}
  .icon-btn{width:36px;height:36px}
  .budget-chip{padding:var(--s-1) var(--s-3)}
  /* Os botões quebram linha em vez de rolar para o lado: rolando, o
     último ficava cortado e parecia não existir. */
  .tree-bar{flex-wrap:wrap}
  .tree-bar .spacer{display:none}
  /* No celular, cada linha mostra o que decide a verba — gasto, conversas,
     leads, vendas, a divergência e a recomendação — e o resto abre no
     botão da linha. Com os vinte números abertos, quatro linhas davam
     três telas de rolagem. */
  .tree .more-nums{display:inline-flex;margin-top:var(--s-2)}
  .tree tbody tr:not(.all-nums) td[data-col]:not([data-col="spend"]):not([data-col="convs"]):not([data-col="leads"]):not([data-col="sales"]):not([data-col="diverge"]):not([data-col="rec"]){display:none}
  .col-pick[open]{flex-basis:auto;order:0}
}

/* Campanha (o item): a linha de metadados embaixo do nome, no cabeçalho e
   nas linhas dos filhos; o nome é outro que o .item-head do padrão. */
.item-meta{display:flex;gap:var(--s-2);flex-wrap:wrap;align-items:center}
td .item-meta{margin-top:var(--s-1)}
.item-rec p{margin:0 0 var(--s-2)}
.item-rec p:last-child{margin-bottom:0}
.item-targets{margin-top:var(--s-4)}
.item-targets form{margin-top:var(--s-3)}
.item-targets .field{margin:0}
.item-pick{display:flex;gap:var(--s-4);flex-wrap:wrap;align-items:center;margin:0 0 var(--s-4)}
.item-lede{margin-bottom:var(--s-3)}
/* Os dois lados do comparativo como linhas de grupo: à vista também no
   celular, onde o thead some. */
.item-versus tr.group th{padding-top:var(--s-5);text-align:left}
.item-versus tbody:first-of-type tr.group th{padding-top:var(--s-2)}
.item-days-card{margin-top:var(--s-3)}
.item-days-card .legend{margin:0 0 var(--s-3)}
.item-days tr.side-now td:first-child{box-shadow:inset 3px 0 0 var(--viz-1)}
.item-days tr.side-before td:first-child{box-shadow:inset 3px 0 0 var(--viz-compare)}
.item-days .mark{font-size:var(--t-xs);color:var(--muted);margin-top:2px}
.item-about{display:flex;gap:var(--s-4);align-items:flex-start;margin-bottom:var(--s-4)}
.item-about img{border-radius:var(--radius-sm);object-fit:cover;flex:none;background:var(--line)}
.item-about p{margin:var(--s-1) 0 0}
.item-about p.preview{margin-top:var(--s-3)}
.item-body{white-space:pre-line;max-height:7.5em;overflow:auto;font-size:var(--t-sm)}
/* No celular, o dia a dia fica tabela, e rola de lado com o dia parado:
   empilhado, eram sete linhas por dia. */
@media (max-width:560px){
  .item-days th,.item-days td{padding:var(--s-2);font-size:var(--t-xs);white-space:nowrap}
  .item-days th:first-child,.item-days td:first-child{position:sticky;left:0;background:var(--panel);z-index:1}
  .item-pick{gap:var(--s-2)}
  table.item-versus tbody tr.group{display:block;padding:0}
  table.item-versus tr.group th{display:block;padding:var(--s-4) 0 0}
}

/* Ajustar verba. A grade quebra em 1000px: a 861px o main tem uns 560, e
   as duas colunas mínimas (260 + 320) passavam da tela. */
.budget-grid{display:grid;grid-template-columns:minmax(260px,5fr) minmax(320px,7fr);gap:var(--s-4);align-items:start;max-width:1040px}
@media (max-width:1000px){.budget-grid{grid-template-columns:1fr}}
.budget-notice{max-width:1040px}
.budget-now .amount{font-size:var(--t-xl);font-weight:650;line-height:1.1;margin:2px 0}
.budget-now .unit{color:var(--muted);font-size:var(--t-sm);margin:0}
.budget-now .none{margin:0}
.budget-kicker{margin:0 0 var(--s-1)}
.budget-facts{margin:var(--s-4) 0 0;padding:var(--s-3) 0 0;border-top:1px solid var(--line-soft);list-style:none;display:grid;
              gap:var(--s-3);color:var(--ink-dim);font-size:var(--t-sm)}
.budget-facts li{display:grid;gap:2px}
.budget-steps{display:flex;gap:var(--s-2);align-items:center;margin:0 0 var(--s-4);padding:0;list-style:none;
              font-size:var(--t-xs);color:var(--muted)}
.budget-steps .step{display:inline-flex;gap:var(--s-1);align-items:center}
.budget-steps .n{display:inline-flex;width:20px;height:20px;border-radius:50%;align-items:center;justify-content:center;
                 border:1px solid var(--line);font-size:var(--t-xs);font-weight:650}
.budget-steps .on{color:var(--ink);font-weight:600}
.budget-steps .on .n{background:var(--brand-soft);border-color:transparent;color:var(--brand)}
.budget-steps .bar{flex:0 0 var(--s-5);height:1px;background:var(--line)}
.budget-main > p{margin:0 0 var(--s-2)}
.budget-main > p:last-child{margin-bottom:0}
.amount-row{display:flex;gap:var(--s-3);align-items:center;flex-wrap:wrap}
.amount-row input{max-width:170px;font-size:var(--t-md);font-variant-numeric:tabular-nums}
.budget-preview{margin:var(--s-3) 0 0;padding:var(--s-3) var(--s-4);border:1px solid var(--line);border-radius:var(--radius);
                background:var(--panel-2)}
.budget-preview.confirm{margin:0 0 var(--s-2)}
.budget-preview .move,.budget-move{display:flex;align-items:baseline;gap:var(--s-3);flex-wrap:wrap;font-size:var(--t-lg);
                                   font-weight:650;margin:0}
.budget-preview .arrow,.budget-move .arrow{color:var(--muted);font-weight:400}
.budget-preview .pct,.budget-move .pct{font-size:var(--t-sm);font-weight:600;color:var(--muted)}
.budget-preview .hint{font-size:var(--t-xs);color:var(--muted);margin:var(--s-1) 0 0}
.budget-preview.over{border-color:var(--warn-line)}
.budget-preview.over .hint{color:var(--warn)}
.shortcuts{display:flex;gap:var(--s-2);flex-wrap:wrap;align-items:center;margin:0 0 var(--s-1);font-size:var(--t-xs)}
/* O que o ajuste contraria: o aviso comum, com o título e a caixa que
   aceita o risco dentro. */
.budget-warn h3{margin:0 0 var(--s-1);font-size:var(--t-sm)}
.budget-warn p{margin:0}
.budget-warn .sub{margin-top:var(--s-1)}
.budget-warn label.choice{margin-top:var(--s-2);font-weight:600}
.budget-actions{flex-wrap:wrap;margin-top:var(--s-4)}
.budget-foot{margin-top:var(--s-4)}
/* Na janela: uma coluna só, a verba de hoje numa faixa em cima, e o resto
   do que se sabe do item recolhido, para a decisão caber sem rolar. */
.budget-grid.in-window{grid-template-columns:1fr;gap:var(--s-4);max-width:none}
.in-window .budget-now{display:flex;flex-wrap:wrap;align-items:center;gap:var(--s-1) var(--s-4);padding:var(--s-3) var(--s-4);
                       border:1px solid var(--line);border-radius:var(--radius);background:var(--panel-2)}
.in-window .budget-now .budget-kicker{margin:0;flex-basis:100%}
.in-window .budget-now .amount{font-size:var(--t-lg);margin:0}
.in-window .budget-now .unit{flex:1}
.in-window .budget-now .rec{font-size:var(--t-xs);color:var(--muted);display:inline-flex;gap:var(--s-1);align-items:center}
.in-window .budget-more{flex-basis:100%;font-size:var(--t-sm)}
.in-window .budget-more summary{cursor:pointer;color:var(--muted);width:max-content}
.in-window .budget-facts{margin-top:var(--s-3);padding-top:var(--s-3)}
.in-window .budget-steps{margin-bottom:var(--s-3)}

/* Pausar, retomar, duplicar, arquivar e excluir: o texto do que vai
   acontecer e o botão, na janela ou na página. */
.action-notice,.card.action-body{max-width:640px}
.action-body > h2:first-child{margin-top:0}
.action-body > p{margin:0 0 var(--s-2)}
.action-body > p:last-child{margin-bottom:0}
.action-body form{margin-top:var(--s-4)}
.action-body .form-dialog-actions{flex-wrap:wrap}
/* O texto de baixo de uma linha de histórico que pode ser longo, como a
   recusa do Meta: quebra, numa largura só para as três tabelas. */
.sub.wrap{max-width:48ch;white-space:normal}
.sub.wrap:not(:first-child){margin-top:var(--s-1)}
.lede.tight{margin-bottom:var(--s-3)}
.help.after-form{margin-top:var(--s-3)}

/* Contas. */
.acct-grid{display:grid;gap:var(--s-3);grid-template-columns:repeat(auto-fill,minmax(min(320px,100%),1fr))}
.acct-head{display:flex;gap:var(--s-2);align-items:flex-start}
.acct-name{flex:1;min-width:0}
.acct .banner{margin:var(--s-3) 0 0}
.acct dl{display:grid;grid-template-columns:auto 1fr;gap:var(--s-1) var(--s-3);margin:var(--s-3) 0 0;font-size:var(--t-sm)}
.acct dt{color:var(--muted)}
.acct dd{margin:0;text-align:right;font-variant-numeric:tabular-nums}
.acct details{margin-top:var(--s-3);font-size:var(--t-sm)}
.acct table{width:100%;margin-top:var(--s-1)}
.acct-foot{margin:var(--s-3) 0 0}
table.coverage{width:100%;border-collapse:collapse;font-size:var(--t-sm)}
table.coverage td{padding:var(--s-1) var(--s-2) var(--s-1) 0;vertical-align:middle}
table.coverage td.cov-bar{width:45%}

/* Desgaste. */
.fatigue-ad{display:flex;gap:var(--s-3);align-items:center;min-width:220px}
.fatigue-ad img{width:44px;height:44px;border-radius:var(--radius-sm);object-fit:cover;flex:none;background:var(--line)}
.fatigue-name{min-width:0}
.fatigue .was{color:var(--muted)}
.fatigue .worse{color:var(--danger);font-weight:600}

/* Automações: a lista de regras. O aviso de que tudo só simula é o
   .banner.warn, na largura do texto. */
.rule-list{display:grid;gap:var(--s-3)}
.rule-card{display:grid;grid-template-columns:1fr auto;gap:var(--s-1) var(--s-4);align-items:start}
.rule-card h3{margin:0;font-size:var(--t-md)}
.rule-card h3 a{color:var(--ink);text-decoration:none}
.rule-card h3 a:hover{text-decoration:underline}
.rule-card .sentence{margin:0;color:var(--ink-dim);font-size:var(--t-sm);grid-column:1/-1}
.rule-card .meta{margin:0;color:var(--muted);font-size:var(--t-xs);grid-column:1/-1;display:flex;flex-wrap:wrap;gap:var(--s-1) var(--s-4)}
.stage-note{max-width:820px}
/* A regra. */
.rule-sentence{font-size:var(--t-md);line-height:1.5;margin:0 0 var(--s-3);max-width:820px}
.rule-facts{margin:0 0 var(--s-4);padding:0;list-style:none;display:grid;gap:var(--s-1);color:var(--ink-dim);font-size:var(--t-sm)}
.rule-actions{display:flex;gap:var(--s-2);flex-wrap:wrap;align-items:center;margin:0 0 var(--s-5)}
.rule-actions form{margin:0}
/* O formulário da regra. */
.rule-form{max-width:860px;display:grid;gap:var(--s-4)}
.rule-form > .field{margin:0}
.rule-wide{max-width:860px}
.rule-live{position:sticky;top:0;z-index:5;background:var(--bg);padding:var(--s-3) 0;margin:0 0 var(--s-1);
           border-bottom:1px solid var(--line-soft)}
.rule-live p{margin:0;font-size:var(--t-md);line-height:1.5;max-width:860px}
.rule-live .kicker{display:block;margin-bottom:2px}
.rule-form [data-show]:not(.on){display:none}
.rule-fields{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:var(--s-3)}
.rule-fields.spaced{margin-top:var(--s-4)}
.rule-fields .help.full{grid-column:1/-1}
.cond{display:grid;grid-template-columns:minmax(0,1.6fr) 96px minmax(0,1fr) auto;gap:var(--s-2);align-items:center;margin:0 0 var(--s-2)}
.cond .upper{display:none}
.cond.between{grid-template-columns:minmax(0,1.6fr) 96px minmax(0,1fr) minmax(0,1fr) auto}
.cond.between .upper{display:block}
/* O × com alvo de 32px e o anel do foco: o all:unset tirava os dois. */
.cond .remove{all:unset;box-sizing:border-box;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;
              min-width:32px;height:32px;color:var(--muted);font-size:var(--t-lg);line-height:1;border-radius:var(--radius-sm)}
.cond .remove:hover{color:var(--ink);background:var(--panel-2)}
.cond .remove:focus-visible{outline:2px solid var(--brand);outline-offset:1px}
#cond-limit{margin-left:var(--s-2)}
/* Escolher um a um: uma lista que rola, não a grade do .items. */
.pick-list{max-height:280px;overflow:auto;border:1px solid var(--line);border-radius:var(--radius-sm);padding:var(--s-1) var(--s-3)}
.pick-list label.choice{padding:var(--s-1) 0;margin:0}
.pick-list .item-sub{white-space:normal}
.pick-list > .muted{margin:var(--s-2) 0}
@media (max-width:560px){
  .cond,.cond.between{grid-template-columns:1fr 1fr}
  .cond select:first-child{grid-column:1/-1}
  .cond .remove{min-width:40px;height:40px}
}

/* ---------- área: vendas ---------- */
/* Só as telas de vendas, produtos, cobranças e carnê escrevem aqui. */
/* Nova venda: sem produto escolhido, nada dos termos da venda (charges.js
   põe a classe). Por classe, e não por hidden, para não brigar com o
   data-shown-when. */
form.no-product [data-needs-product]{display:none}
/* A ficha da venda: o valor no cabeçalho, no tamanho do card da lista. */
.sale-amount{font-size:var(--t-lg);font-weight:650;letter-spacing:-.4px;font-variant-numeric:tabular-nums}
.pay-id{font-size:var(--t-xs)}
/* O salvar da conta do Mercado Pago, preso no rodapé da página longa. */
.form-actions.sticky{position:sticky;bottom:0;z-index:var(--z-sticky);display:flex;gap:var(--s-3);align-items:center;
  justify-content:flex-end;flex-wrap:wrap;background:var(--bg);border-top:1px solid var(--line);padding:var(--s-3) 0}
.form-actions.sticky .help{margin:0}
/* Cobranças e carnês do contato: um cartão por cobrança ou carnê. */
.charge-list{display:grid;gap:var(--s-3)}
@media (min-width:960px){.charge-list{grid-template-columns:1fr 1fr}}
.charge{display:flex;flex-direction:column;gap:var(--s-2)}
.charge-top{display:flex;justify-content:space-between;align-items:baseline;gap:var(--s-3)}
.charge-what{min-width:0;overflow-wrap:anywhere}
.charge-amount{font-weight:650;white-space:nowrap}
.charge-unit{font-weight:400;font-size:var(--t-xs)}
.charge-meta{display:flex;gap:var(--s-2);align-items:center;flex-wrap:wrap;font-size:var(--t-sm)}
.charge-detail{margin:0;font-size:var(--t-xs)}
.charge-detail .copy{margin-left:var(--s-1)}
.charge-actions{display:flex;gap:var(--s-2);flex-wrap:wrap;align-items:center}
.charge-actions form{margin:0}
.charge-foot{margin:0;font-size:var(--t-xs)}
/* As ações de uma parcela, em grupos que quebram linha; no celular, a
   parcela vira bloco (table.stack) e as ações ficam embaixo, à esquerda. */
.installment-pix{display:flex;gap:var(--s-2);flex-wrap:wrap;align-items:center}
.installment-pix form,.reissue{margin:0}
.installment-actions > * + *{margin-top:var(--s-2)}
@media (max-width:560px){
  table.stack td.installment-actions{display:block;text-align:left}
  table.stack td.installment-actions:not(:has(*)){display:none}
}
.plan-schedule{margin:0 0 var(--s-3)}
/* As páginas de quem paga (pagamento e carnê): uma coluna, sem menu, no
   .auth do layout, que sem isto seria a caixa centrada do login. */
.auth:has(> .checkout){display:block;place-items:normal;min-height:0;padding:var(--s-6) var(--s-4)}
.checkout{max-width:600px;margin:0 auto}
.checkout .card p{margin:0}
.checkout-gone{max-width:480px;margin:12vh auto 0;text-align:center}
.checkout-gone h1{margin-top:0}
.checkout-gone p + p,.checkout-gone h1 + p{margin-top:var(--s-2)}
.checkout-head h1{margin:0 0 var(--s-1)}
.checkout-head .eyebrow{margin:0 0 var(--s-1)}
.checkout-head > p:last-child{margin:0 0 var(--s-4)}
.checkout-total{font-size:var(--t-lg);font-weight:600;margin:0 0 var(--s-1)}
.checkout-foot{margin-top:var(--s-4);font-size:var(--t-xs);color:var(--muted)}
.checkout .code-box{font-size:var(--t-xs);padding:var(--s-2) var(--s-3);margin:0;word-break:break-all}
.carne-list{display:grid;gap:var(--s-3)}
.carne-item{display:flex;flex-direction:column;gap:var(--s-2)}
.carne-top{display:flex;justify-content:space-between;align-items:baseline;gap:var(--s-3)}
.carne-key{margin-top:var(--s-3)}
.pay-choose{display:grid;gap:var(--s-3)}
.pay-option{display:flex;justify-content:space-between;align-items:center;width:100%;padding:var(--s-3) var(--s-4);font-size:var(--t-md)}
.pay-change{margin-bottom:var(--s-3)}
#status:empty{display:none}
/* O Pix: o QR para ler de outro aparelho e o copia-e-cola para quem abriu
   o link no próprio celular. No celular, o copia-e-cola vem primeiro. */
.pix-pay{display:flex;flex-direction:column;gap:var(--s-4);text-align:center}
.pix-scan,.pix-copy{display:flex;flex-direction:column;gap:var(--s-3);align-items:center}
.pix-copy{align-items:stretch}
.pix-copy .code-box{text-align:left;max-height:96px;overflow:auto}
.pix-copy .copy.as-button{width:100%}
@media (max-width:560px){.pix-copy{order:-1}}
/* O formulário do Mercado Pago é desenhado nesta página, e as regras de
   campo do Capivara (o padding dos inputs) esticavam os radios dele em
   ovais. Dentro dele, os campos ficam como o Mercado Pago os desenha. */
#pay input[type="radio"],#pay input[type="checkbox"]{padding:0;min-height:0}

/* ---------- área: integrações e whatsapp ---------- */
/* Só as telas de integrações, números e WhatsApp escrevem aqui. */
/* O cartão de um número (Números e Diagnóstico): cada peça abaixo do
   cabeçalho com o mesmo respiro, e o texto do estado mais perto dele. */
.number-card > :not(:first-child){margin-top:var(--s-3)}
.number-card > p{margin-bottom:0}
.number-card > .help,.number-card > form + form{margin-top:var(--s-2)}
.number-card > .mono + .help{margin-top:var(--s-1)}
.number-card > .banner{margin-bottom:0}
.number-qr{text-align:center}
/* Parear de novo de um lado e Excluir do outro, separados do conteúdo. */
.card-actions.split{justify-content:space-between;border-top:1px solid var(--line);padding-top:var(--s-3)}
/* Configurações da plataforma: o servidor mais largo que a porta, e o campo
   com o botão ao lado sem a margem de baixo, para os dois alinharem. */
.row.fields > .field.wide{flex:2 1 180px}
.row.with-button > .field{margin-bottom:0}
