﻿/* ==================================================================
   CORTEX V2 — DESIGN SYSTEM
   Este arquivo é a fonte da verdade. O styleguide e o produto
   carregam ELE, não uma cópia — mudou aqui, mudou nos dois.
   Regra do projeto: qualquer ajuste feito numa tela volta para cá
   antes de ser considerado pronto.
   ================================================================== */
/* ══════════════════════════════════════════════════════════════════
   CORTEX V2 — TOKENS
   Cor: SEMPRE por token, sem exceção.
   Raio: por token no tamanho padrão do componente. Variante de
   tamanho escala o raio junto — botão pequeno com o canto do
   botão grande fica desproporcional — e esse valor fica declarado
   na própria variante.
   Espaço ENTRE blocos: sempre pela escala abaixo.
   Espaço DENTRO de um componente (padding de botão, altura de
   trilho, recuo de submenu) pertence ao componente e fica declarado
   nele — são medidas de desenho, não de layout, e forçá-las na
   escala só produziria componente torto.
   ══════════════════════════════════════════════════════════════════ */
:root{
  /* ── superfície ── */
  --bg:#05070D;
  --surface:rgba(255,255,255,.04);      /* card de vidro */
  --surface-hover:rgba(255,255,255,.06);
  --surface-inner:#171920;              /* card dentro de card */
  --surface-sunken:rgba(0,0,0,.30);     /* campo, área rebaixada */
  --surface-float:rgba(16,18,23,.94);   /* modal, menu, aviso */

  /* ── colunas da estrutura ──
     Únicas larguras fixas permitidas no sistema, e só porque coluna
     de navegação com largura elástica faz o conteúdo dançar a cada
     item que entra. Trocam de valor nos pontos de quebra. */
  --nav-larg:236px;

  /* quanto de escuro entra por cima da imagem de fundo */
  --fundo-veu:.80;

  /* O card de vidro em versao OPACA. Serve para peça que precisa
     esconder o que passa por baixo dela — coluna presa de tabela é o
     caso. Não foi escolhida a olho: é o composto medido da imagem de
     fundo mais o véu mais o branco de 4% do vidro. Se o fundo ou o
     véu mudarem, este valor precisa ser medido de novo, senão a peça
     volta a aparecer como uma faixa colada por cima. */
  --surface-op:#0f1f26;
  --border:rgba(255,255,255,.10);
  --border-strong:rgba(0,219,233,.30);  /* borda em foco/hover */

  /* ── texto ── */
  --text:#dce2f6;
  --muted:#b9cacb;

  /* ── marca e ação ── */
  --cyan:#00dbe9;
  --cyan-bright:#00f0ff;

  /* ── semântica: UMA cor por significado ── */
  --positive:#00E08A;
  --negative:#ff4d3d;
  --warning:#ffc060;
  --negative-bg:#e0392b;   /* preenchimento sólido: pastilha de contador */

  /* ── espaçamento: seis valores, nada fora disso ── */
  --s1:4px; --s2:8px; --s3:12px; --s4:16px; --s5:24px; --s6:32px;

  /* ── ALTURA DA LINHA PRINCIPAL ──────────────────────────────────
     UM número, e os três cartões da fileira o obedecem: relatório,
     custo por fonte e posicionamentos. Nenhum deles cresce por ter
     mais dado — quem tem conteúdo demais rola por dentro.

     A conta, e não um número escolhido a olho:

       48px  respiro do cartão, em cima e embaixo
       82px  cabeçalho — título 13 + controles 40 + fio e respiros
      544px  tabela: o cabeçalho grudado (57) mais DOZE linhas
             inteiras de 41px, menos o espaçamento que sobra no fim

     Doze linhas são DEZ CAMPANHAS. A faixa de plataforma ocupa linha
     como qualquer outra, e com Meta e TikTok no recorte são duas —
     pedir dez campanhas é pedir doze linhas. Com uma plataforma só,
     sobram onze campanhas; agrupado por outra dimensão, doze.

     O `62vh` não é enfeite: é o que faz o teto de 682px valer em
     janela de 877px para cima. Com o 43vh de antes, esta altura só
     apareceria em tela de 1265px, e num monitor comum a fileira
     ficaria menor sem ninguém entender por quê.

     Em `vh` com teto, e não em pixels fixos: a proporção precisa
     acompanhar a tela de quem olha, e num monitor baixo a fileira
     inteira não pode empurrar o resto da página para fora. */
  --linha-1:min(calc(62vh + 130px), 668px);

  /* ── ALTURA DA SEGUNDA FILEIRA ──────────────────────────────────
     Mesma ideia, outro número: gráfico e performance por criativo.

     Era 483px, caiu para 338, subiu vinte por cento, ganhou mais uma
     linha de criativos e foi ajustada para a caixa cair justa — 418.
     O gráfico não precisava dos 483: a linha de custo ocupa a mesma
     forma em 335px de altura, e o que sobrava não era respiro, era vão.

     O NÚMERO CAI NA LINHA, e não é redondo. A caixa de criativos vale
     315px, que é o cabeçalho grudado (50) mais oito linhas de 33,4 e
     três de folga. Assim o corte na linha inteira quase não tem o que
     cortar: sobram 3px em vez de 17, e a distância até a borda de baixo
     do cartão cai de 41 para 27 — dos quais 24 são o respiro do cartão,
     que é igual nos quatro lados e não se mexe.

     Isso só vale porque a tabela miúda passou a ter UM passo só: a
     faixa de plataforma era 4px mais alta que a linha de dado, e com
     dois passos a caixa nunca cai exata num múltiplo.

       48px  respiro do cartão
       35px  cabeçalho do gráfico  (título e legenda numa linha)
       55px  cabeçalho de criativos (a linha tem um botão de 34px)

     Cada bloco tira o seu do total, e por isso são dois `calc` com
     números diferentes: os dois cartões têm a mesma altura, e não o
     mesmo miolo. */
  --linha-2:min(calc(38vh + 111px), 426px);

  /* ── cantos: quatro valores ── */
  --r-sm:8px;    /* item dentro de lista: opção, chip, célula */
  --r-md:14px;   /* controle: botão, campo, seletor, item de nav */
  --r-lg:16px;   /* superfície: card, menu, modal, calendário */
  --r-pill:999px;

  /* ── sombras: três ── */
  --sh-card:0 8px 32px rgba(0,0,0,.35);
  --sh-drop:0 12px 40px rgba(0,0,0,.45);
  --sh-modal:0 20px 60px rgba(0,0,0,.50);

  /* ── tipografia: uma sans + uma mono ── */
  --sans:'Inter',-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;
  --mono:'JetBrains Mono',ui-monospace,'Cascadia Mono',Consolas,monospace;
}

*{box-sizing:border-box}

/* O atributo `hidden` do HTML é aplicado pelo navegador com prioridade
   baixíssima, então QUALQUER classe que declare display o vence — e o
   elemento continua na tela mesmo marcado como escondido. Aconteceu
   com o resumo dos checkouts, que tem display:flex e ficava visível no
   modo Campanhas. Esta linha faz `hidden` significar escondido. */
[hidden]{display:none !important}
body{margin:0;background:var(--bg);color:var(--text);font:400 14px/1.5 var(--sans);-webkit-font-smoothing:antialiased}



/* ══════════ SUPERFÍCIE DE VIDRO — a assinatura do Cortex ══════════ */
.glass{position:relative;overflow:hidden;background:var(--surface);
  backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);
  border:1px solid var(--border);border-radius:var(--r-lg);
  box-shadow:var(--sh-card),inset 0 1px 0 rgba(255,255,255,.10),inset 0 -1px 0 rgba(255,255,255,.03);
  transition:all .2s}
.glass::before,.menu::before,.modal::before,.toast::before,.state-ic::before,
.sel-pop::before,.cal-pop::before{
  content:'';position:absolute;top:0;left:0;right:0;height:1px;pointer-events:none;
  background:linear-gradient(90deg,transparent,rgba(255,255,255,var(--rim-top,.35)),transparent)}
.glass::after,.menu::after,.modal::after,.toast::after,.state-ic::after,
.sel-pop::after,.cal-pop::after{
  content:'';position:absolute;top:0;left:0;width:1px;height:100%;pointer-events:none;
  background:linear-gradient(180deg,rgba(255,255,255,var(--rim-left,.30)),transparent,rgba(255,255,255,.08))}

.glass>*,.menu>*,.modal>*,.toast>*,.sel-pop>*,.cal-pop>*{position:relative;z-index:1}
.glass:hover{background:var(--surface-hover);border-color:var(--border-strong)}
.glass.static:hover{background:var(--surface);border-color:var(--border)}
.pad{padding:var(--s5)}
/* Moldura SEM preenchimento. Para quando o que está dentro já traz a
   própria superfície (a sidebar, por exemplo). Vidro dentro de vidro
   soma as duas transparências e o resultado clareia — é por isso que
   card dentro de card usa --surface-inner, que é opaco. */
.frame{border:1px solid var(--border);border-radius:var(--r-lg);
  overflow:hidden;box-shadow:var(--sh-card)}

/* ══════════ TIPOGRAFIA ══════════ */
.t-page{font:800 clamp(32px,2.8vw,52px)/1.05 var(--sans);letter-spacing:-.02em;margin:0}
/* Título de tela: o maior texto que aparece no produto. O .t-page
   acima dele existe só para capa de documento, como o deste guia. */
.t-tela,.topbar h1{font:800 34px/1.1 var(--sans);letter-spacing:-.02em;margin:0}
.t-sec{font:800 22px/1.2 var(--sans);letter-spacing:-.01em;margin:0}
.t-card{font:700 15px/1.3 var(--sans);margin:0}
.t-label{font:700 10px/1 var(--mono);text-transform:uppercase;letter-spacing:.10em;color:var(--muted)}
.t-num{font:800 clamp(26px,2.4vw,38px)/1 var(--mono);font-variant-numeric:tabular-nums}
.t-body{font:400 14px/1.5 var(--sans)}
.t-hint{font:400 11.5px/1.4 var(--sans);color:var(--muted)}

/* ══════════════════════════════════════════════════════════════════
   BOTÃO — a mesma peça de vidro do card, em tamanho de controle
   Borda sólida discreta + duas linhas de luz (topo e esquerda),
   idênticas às da superfície de vidro. No hover, um halo ciano se
   abre dos dois lados, um pouco mais forte na esquerda, que é de
   onde a luz do sistema vem.
   ══════════════════════════════════════════════════════════════════ */
.btn{
  /* cada variante troca só estas variáveis */
  --surf-a:rgba(255,255,255,.07);    /* topo da superfície */
  --surf-b:rgba(255,255,255,.02);    /* base da superfície */
  --edge:var(--border);              /* cor da borda */
  --edge-on:rgba(0,219,233,.30);     /* borda no hover */
  --halo-l:rgba(0,219,233,.09);      /* brilho da esquerda */
  --halo-r:rgba(0,219,233,.07);      /* brilho da direita */
  --cast:rgba(0,0,0,.30);            /* sombra de profundidade */

  position:relative;overflow:hidden;
  display:inline-flex;align-items:center;justify-content:center;
  gap:var(--s2);white-space:nowrap;cursor:pointer;
  font:700 13px/1 var(--sans);color:var(--text);
  padding:13px 22px;min-height:42px;
  border:1px solid var(--edge);border-radius:var(--r-md);
  /* 1 · linha de luz no topo · 2 · linha de luz na esquerda · 3 · superfície */
  background:
    linear-gradient(90deg,transparent,rgba(255,255,255,.35),transparent) 50% 0/100% 1px no-repeat,
    linear-gradient(180deg,rgba(255,255,255,.30),transparent 70%) 0 50%/1px 100% no-repeat,
    linear-gradient(180deg,var(--surf-a),var(--surf-b));
  backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);
  box-shadow:0 4px 14px var(--cast),
             inset 0 1px 0 rgba(255,255,255,.10),
             inset 0 -1px 0 rgba(255,255,255,.03);
  transition:box-shadow .25s ease,border-color .25s ease,transform .12s;
}
.btn:hover:not(:disabled){
  transform:translateY(-1px);
  --surf-a:rgba(255,255,255,.11);--edge:var(--edge-on);
  box-shadow:0 5px 15px var(--cast),
             inset 0 1px 0 rgba(255,255,255,.14),
             inset 0 -1px 0 rgba(255,255,255,.03),
             /* halo curto de propósito: com 8px de deslocamento e 17px
                de desfoque ele chegava a 25px fora do botão e era
                cortado pelo card em volta, que tem overflow:hidden.
                Todo botão vai viver dentro de um card. */
             -4px 3px 11px var(--halo-l),
              4px 3px 11px var(--halo-r);
}
.btn:active:not(:disabled){
  transform:translateY(1px);
  box-shadow:0 2px 6px var(--cast),inset 0 2px 5px rgba(0,0,0,.30),
             -3px 2px 8px var(--halo-l),3px 2px 8px var(--halo-r);
}
.btn:focus-visible{outline:none;box-shadow:0 0 0 3px rgba(0,219,233,.35),0 4px 14px var(--cast)}

/* ── PRIMÁRIO — vidro levemente tingido e brilho já ligado.
      A hierarquia vem da luz acesa, não de uma cor diferente. ── */
.btn--primary{
  --surf-a:rgba(0,219,233,.14);--surf-b:rgba(0,219,233,.03);
  --edge:rgba(0,219,233,.28);--edge-on:rgba(0,219,233,.50);
  --halo-l:rgba(0,219,233,.14);--halo-r:rgba(0,219,233,.10);
  color:#eafeff;
  box-shadow:0 4px 14px var(--cast),
             inset 0 1px 0 rgba(255,255,255,.12),
             inset 0 -1px 0 rgba(255,255,255,.03),
             -5px 4px 11px rgba(0,219,233,.05),
              5px 4px 11px rgba(0,219,233,.04);
}
.btn--primary:hover:not(:disabled){--surf-a:rgba(0,219,233,.20)}

/* ── DESTRUTIVO ── */
.btn--danger{
  --surf-a:rgba(255,77,61,.10);--surf-b:rgba(255,77,61,.02);
  --edge:rgba(255,77,61,.26);--edge-on:rgba(255,77,61,.50);
  --halo-l:rgba(255,77,61,.12);--halo-r:rgba(224,57,43,.13);
  color:var(--negative);
}

/* ── FANTASMA — sem vidro, sem borda, sem halo ── */
.btn--ghost{background:none;border-color:transparent;backdrop-filter:none;
  -webkit-backdrop-filter:none;box-shadow:none;color:var(--muted)}
.btn--ghost:hover:not(:disabled){color:var(--text);background:rgba(255,255,255,.06);
  box-shadow:none;transform:none;border-color:transparent}

.btn--sm{padding:9px 15px;min-height:34px;font-size:12px;border-radius:11px}
.btn--lg{padding:16px 28px;min-height:52px;font-size:14.5px;border-radius:16px}
.btn--icon{padding:0;width:42px;height:42px;border-radius:12px}
.btn--sm.btn--icon{width:34px;height:34px;border-radius:10px}
.btn--block{width:100%}

.btn:disabled{opacity:.38;cursor:not-allowed;box-shadow:none;transform:none}

/* ── VIDRO DENTRO DE VIDRO NAO DESFOCA DE NOVO ───────────────────
   `backdrop-filter` amostra o que esta ATRAS do elemento. Quando o pai
   ja e vidro — a barra de topo, o card, o modal —, o que esta atras do
   filho e o resultado JA desfocado do pai. Desfocar de novo nao
   acrescenta nada e cria uma superficie opaca de aresta reta: aparecia
   como uma mancha escura quadrada por tras do botao arredondado.

   O botao continua sendo vidro; ele so para de tentar refazer o
   desfoque que o recipiente ja fez. A moldura, o degrade e o halo — que
   sao o que da a hierarquia — ficam intactos. */
.topbar .btn,.glass .btn,.modal .btn{backdrop-filter:none;-webkit-backdrop-filter:none}

/* E NEM LEVANTA NO HOVER, PELO MESMO MOTIVO.
   `transform` promove o elemento a uma camada propria de composicao.
   Dentro de um pai com `backdrop-filter`, o navegador passa a desenhar
   o fundo desfocado ATRAS dessa camada como um retangulo do tamanho
   dela — de aresta reta, ignorando o canto arredondado. Era o retangulo
   que aparecia so ao passar o mouse.

   O que se perde e um pixel de elevacao. O que se mantem e o que o guia
   chama de hierarquia: a moldura acendendo e o halo se abrindo. Fora de
   peca de vidro o botao continua levantando. */
.topbar .btn:hover:not(:disabled),
.glass .btn:hover:not(:disabled),
.modal .btn:hover:not(:disabled),
.topbar .btn:active:not(:disabled),
.glass .btn:active:not(:disabled),
.modal .btn:active:not(:disabled){transform:none}
.spin{width:14px;height:14px;border:2px solid rgba(255,255,255,.25);border-top-color:currentColor;
  border-radius:50%;animation:sp .7s linear infinite;flex:none}

/* alvo de toque de 44px no celular */
@media (max-width:640px){
  .btn{min-height:44px;padding:14px 22px}
  .btn--sm{min-height:38px}
  .btn--icon{width:44px;height:44px}
}
.spin{width:14px;height:14px;border:2px solid rgba(255,255,255,.25);border-top-color:currentColor;
  border-radius:50%;animation:sp .7s linear infinite;flex:none}
@keyframes sp{to{transform:rotate(360deg)}}

/* ══════════ CAMPO ══════════ */
.field{display:flex;flex-direction:column;gap:6px;min-width:0}
.input{font:500 13px var(--sans);padding:11px 13px;border-radius:var(--r-md);
  background:linear-gradient(180deg,rgba(0,0,0,.36),rgba(0,0,0,.24));
  border:1px solid var(--border);color:var(--text);
  outline:none;width:100%;
  /* rebaixado: a luz entra por cima e acende a aresta de baixo */
  box-shadow:inset 0 2px 4px rgba(0,0,0,.38),inset 0 -1px 0 rgba(255,255,255,.06);
  transition:border-color .2s,box-shadow .2s}
.input::placeholder{color:var(--muted);opacity:.55}
.input:focus{border-color:var(--cyan);
  box-shadow:inset 0 2px 4px rgba(0,0,0,.38),inset 0 -1px 0 rgba(255,255,255,.06),
             0 0 0 3px rgba(0,219,233,.14),
             -7px 5px 15px rgba(0,219,233,.10),7px 5px 15px rgba(0,219,233,.07)}
.input:disabled{opacity:.45;cursor:not-allowed}
.input.is-error{border-color:var(--negative)}
.err-msg{font:500 11.5px var(--sans);color:var(--negative)}

/* ══════════ SELETOR ════════════════════════════════════
   Substitui o <select>. A lista de um <select> é desenhada pelo
   sistema operacional, fora da página: no Windows ela vem branca,
   com a fonte do sistema, sem raio e sem vidro. Nenhum CSS alcança
   aquilo. A única saída é montar o controle inteiro.
   O botão é uma peça REBAIXADA, igual ao campo de texto: você vai
   preencher. A lista é uma peça FLUTUANTE, igual ao menu. */
.sel{position:relative;min-width:0}
.sel-btn{display:flex;align-items:center;gap:10px;width:100%;text-align:left;
  font:500 13px var(--sans);padding:11px 13px;border-radius:var(--r-md);
  background:linear-gradient(180deg,rgba(0,0,0,.36),rgba(0,0,0,.24));
  border:1px solid var(--border);color:var(--text);cursor:pointer;outline:none;
  box-shadow:inset 0 2px 4px rgba(0,0,0,.38),inset 0 -1px 0 rgba(255,255,255,.06);
  transition:border-color .2s,box-shadow .2s}
.sel-btn:hover{border-color:rgba(255,255,255,.18)}
.sel-val{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.sel-val.vazio{color:var(--muted)}
.sel-chev{flex:none;opacity:.5;transition:transform .2s,opacity .2s}
.sel.aberto .sel-chev{transform:rotate(180deg);opacity:.9}
.sel.aberto>.sel-btn,.sel-btn:focus-visible{border-color:var(--cyan);
  box-shadow:inset 0 2px 4px rgba(0,0,0,.38),inset 0 -1px 0 rgba(255,255,255,.06),
             0 0 0 3px rgba(0,219,233,.14)}
.sel-btn:disabled{opacity:.45;cursor:not-allowed}

/* A lista usa a receita de sobreposição — mesma do menu e do modal. */
@keyframes selAbre{from{opacity:0;transform:translateY(-5px)}to{opacity:1;transform:none}}
/* Todo item de lista respira. Sem folga entre eles, o realce do
   mouse encosta no do item escolhido e os dois viram um bloco só. */
.sel-rol{max-height:264px;overflow-y:auto;overflow-x:hidden;
  display:flex;flex-direction:column;gap:var(--s1)}
.sel-opt{display:flex;align-items:center;gap:10px;padding:9px 11px;border-radius:var(--r-sm);
  font:500 13px var(--sans);color:var(--text);cursor:pointer;white-space:nowrap}
.sel-opt:hover,.sel-opt.foco{background:rgba(255,255,255,.06)}
.sel-opt .marca{margin-left:auto;opacity:0;color:var(--cyan);font-size:12px;flex:none}
.sel-opt.on{color:var(--cyan)}
.sel-opt.on .marca{opacity:1}
.sel-vazio{padding:14px 11px;font:500 12px var(--sans);color:var(--muted);text-align:center}
.sel-busca{margin:2px 2px 6px;position:relative}
.sel-busca input{width:100%;font:500 12.5px var(--sans);padding:8px 10px;border-radius:var(--r-sm);
  background:var(--surface-sunken);border:1px solid var(--border);color:var(--text);outline:none}
.sel-busca input:focus{border-color:var(--cyan)}

/* ══════════ CALENDÁRIO ════════════════════════════════
   Substitui <input type="date">, que abre o calendário do navegador
   — diferente em cada um deles, e nenhum parecido com o produto.
   Sempre intervalo, nunca data solta: num painel de tráfego você
   nunca olha um dia, olha um período. */

.cal-corpo{display:flex;align-items:stretch}
.cal-atalhos{display:flex;flex-direction:column;gap:var(--s1);padding:12px 10px;
  flex:0 1 132px;min-width:0;
  border-right:1px solid var(--border)}
.cal-atalho{text-align:left;padding:7px 10px;border-radius:var(--r-sm);border:0;background:none;
  font:600 12px var(--sans);color:var(--muted);cursor:pointer;white-space:nowrap}
.cal-atalho:hover{background:rgba(255,255,255,.06);color:var(--text)}
.cal-atalho.on{color:var(--cyan);background:rgba(0,219,233,.10)}
.cal-mes{flex:1;padding:12px 14px 14px;min-width:0}
.cal-topo{display:flex;align-items:center;justify-content:space-between;margin-bottom:10px}
.cal-titulo{font:700 12.5px var(--sans);color:var(--text);text-transform:capitalize}
.cal-seta{width:26px;height:26px;border-radius:var(--r-sm);display:grid;place-items:center;border:0;
  background:none;color:var(--muted);cursor:pointer}
.cal-seta:hover{background:rgba(255,255,255,.07);color:var(--text)}
.cal-seta:disabled{opacity:.25;cursor:not-allowed;background:none}
.cal-grade{display:grid;grid-template-columns:repeat(7,1fr);gap:2px 0}
.cal-ds{font:700 9.5px/1 var(--mono);text-transform:uppercase;letter-spacing:.06em;
  color:var(--muted);text-align:center;padding:0 0 8px}
.cal-d{height:32px;display:grid;place-items:center;position:relative;border:0;background:none;
  font:600 12px var(--mono);font-variant-numeric:tabular-nums;color:var(--text);cursor:pointer;
  border-radius:var(--r-sm)}
.cal-d:hover:not(:disabled){background:rgba(255,255,255,.09)}
.cal-d.fora{color:var(--muted);opacity:.3}
.cal-d:disabled{opacity:.2;cursor:not-allowed}
/* dentro do intervalo: faixa contínua, sem raio, para os dias se
   emendarem e o período virar um bloco só */
.cal-d.dentro{background:rgba(0,219,233,.11);border-radius:0}
.cal-d.ponta{background:var(--cyan);color:#04141a;font-weight:800}
.cal-d.ponta.ini{border-radius:var(--r-sm) 0 0 var(--r-sm)}
.cal-d.ponta.fim{border-radius:0 var(--r-sm) var(--r-sm) 0}
.cal-d.ponta.ini.fim{border-radius:var(--r-sm)}
.cal-d.hoje::after{content:'';position:absolute;bottom:4px;left:50%;transform:translateX(-50%);
  width:3px;height:3px;border-radius:50%;background:currentColor;opacity:.8}
.cal-rodape{display:flex;align-items:center;justify-content:space-between;gap:10px;
  padding:10px 14px;border-top:1px solid var(--border)}
.cal-leitura{font:600 11px var(--mono);color:var(--muted);font-variant-numeric:tabular-nums}

/* ══════════ BARRA DE ROLAGEM ════════════════════════════
   Também é peça do sistema operacional. No Windows ela vem cinza
   clara e larga, e fura o visual em qualquer lista com rolagem.

   SÓ APARECE COM O MOUSE NO BLOCO. Parada, ela é um risco claro
   permanente na beirada de todo cartão que rola — e são muitos. Some
   quando ninguém está mexendo, e aparece por transição quando o
   ponteiro entra no bloco.

   O LUGAR DELA CONTINUA RESERVADO. Escondê-la com `scrollbar-width:
   none` devolveria os 11px ao conteúdo, e a tabela mudaria de largura
   quando o mouse entrasse. Some a cor, não o espaço.

   UMA cor animada para os dois motores. `--sb` é registrada, e por
   isso pode ser interpolada; o padrão (`scrollbar-color`) e o
   pseudo-elemento do WebKit leem a mesma variável. Sem registro, a
   transição não teria o que interpolar e a barra piscaria. */
@property --sb{syntax:'<color>';inherits:true;initial-value:transparent}

*{scrollbar-width:thin;scrollbar-color:var(--sb) transparent}
::-webkit-scrollbar{width:11px;height:11px}
::-webkit-scrollbar-track{background:transparent}
::-webkit-scrollbar-thumb{background:var(--sb);border-radius:8px;
  border:3px solid transparent;background-clip:padding-box}
::-webkit-scrollbar-corner{background:transparent}

/* Quem rola nesta tela. Enumerado, e não `*:hover`: com o coringa,
   passar o mouse em qualquer coisa acenderia junto a barra de todos os
   pais que rolam, e três barras acendem onde só uma interessa.

   Cada um zera a própria variável. `--sb` é herdada — precisa ser,
   para o pseudo-elemento do WebKit enxergá-la —, e sem o zero o valor
   do pai aceso desceria para o filho: com o mouse na tabela, a barra
   da página acenderia junto. */
.table-wrap,.sel-rol,#barras-pos,.rosca-bloco .centrado-v,.modal-body,
.conteudo{--sb:transparent;transition:--sb .22s ease}
.table-wrap:hover,.sel-rol:hover,#barras-pos:hover,
.rosca-bloco .centrado-v:hover,.modal-body:hover,
.conteudo:hover{--sb:rgba(255,255,255,.20)}

/* ACENDE UMA SÓ, a de dentro. `:hover` vale para o elemento e para
   todos os pais dele, então o mouse numa tabela acendia a barra da
   tabela E a da página junto. `:has` apaga a de fora enquanto o
   ponteiro estiver dentro de outra que rola. */
.conteudo:hover:has(.table-wrap:hover),
.conteudo:hover:has(.sel-rol:hover),
.conteudo:hover:has(#barras-pos:hover),
.conteudo:hover:has(.rosca-bloco .centrado-v:hover),
.conteudo:hover:has(.modal-body:hover){--sb:transparent}

/* ══════════ CHAVE ══════════════════════════════════════
   Contorno, não caixa cheia. Desligada ela é só a moldura; ligada,
   a moldura acende em ciano. O botão é a única peça sólida e é ele
   que se move — o olho segue o movimento, que é mais rápido de ler
   que mudança de cor.
   Por dentro é um <input type="checkbox"> de verdade, escondido: o
   desenho é todo nosso, mas o teclado, o foco e o leitor de tela
   continuam funcionando de graça. */
.toggle{position:relative;display:inline-block;flex:none;
  width:48px;height:27px;cursor:pointer;vertical-align:middle}
.toggle input{position:absolute;opacity:0;width:0;height:0;margin:0}
/* A pista é vidro: superfície translúcida, desfoque do que está
   atrás e as duas linhas de luz por dentro. Aqui elas são sombras
   internas, não pseudo-elementos — numa peça totalmente arredondada
   a sombra interna acompanha a curva sozinha, e foi a falta disso
   que deixou a moldura cônica com cara de mal acabada nos botões. */
.toggle-tr{position:absolute;inset:0;border-radius:var(--r-pill);
  border:1.5px solid rgba(255,255,255,.16);
  background:linear-gradient(180deg,rgba(255,255,255,.07),rgba(255,255,255,.02));
  backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);
  /* rebaixado: sem fio de luz no topo. A luz entra e acende só a
     aresta de baixo — o trilho é um sulco onde o botão corre. */
  box-shadow:inset 0 2px 5px rgba(0,0,0,.28),
             inset 0 -1px 0 rgba(255,255,255,.07);
  transition:border-color .4s cubic-bezier(.175,.885,.32,1.275),
             background .3s ease, box-shadow .3s ease}
.toggle-tr::before{content:'';position:absolute;left:3.5px;top:3.5px;width:17px;height:17px;
  border-radius:50%;
  background:linear-gradient(180deg,#eef0f1,#bcbfc2);
  box-shadow:0 1px 3px rgba(0,0,0,.55),inset 0 1px 0 rgba(255,255,255,.6);
  transition:transform .4s cubic-bezier(.23,1,.32,1),background .3s ease}
.toggle:hover .toggle-tr{border-color:rgba(255,255,255,.26)}

.toggle input:checked+.toggle-tr{border-color:rgba(0,219,233,.42);
  background:linear-gradient(180deg,rgba(0,219,233,.16),rgba(0,219,233,.04));
  box-shadow:inset 0 2px 5px rgba(0,0,0,.20),
             inset 0 -1px 0 rgba(255,255,255,.09),
             0 0 9px rgba(0,219,233,.14)}
.toggle input:checked+.toggle-tr::before{transform:translateX(21px);
  background:linear-gradient(180deg,#ffffff,#d6f7fa)}

.toggle input:focus-visible+.toggle-tr{border-color:rgba(0,219,233,.55);
  box-shadow:inset 0 2px 5px rgba(0,0,0,.22),0 0 0 3px rgba(0,219,233,.18)}
.toggle input:disabled+.toggle-tr{opacity:.4}
.toggle input:disabled{cursor:not-allowed}
.toggle:has(input:disabled){cursor:not-allowed}

/* aguardando resposta do outro lado: âmbar pulsando, e a chave não
   aceita clique — o estado real ainda não é conhecido */
.toggle.aguardando{cursor:wait}
.toggle.aguardando .toggle-tr{border-color:rgba(255,192,96,.42);
  background:linear-gradient(180deg,rgba(255,192,96,.14),rgba(255,192,96,.03));
  box-shadow:inset 0 2px 5px rgba(0,0,0,.22),
             inset 0 -1px 0 rgba(255,255,255,.07),
             0 0 9px rgba(255,192,96,.12)}
.toggle.aguardando .toggle-tr::before{background:var(--warning);
  animation:tgPulsa 1.1s ease-in-out infinite}
.toggle.aguardando input{pointer-events:none}

/* Variante pequena, para dentro de linha de tabela. NÃO basta trocar
   largura e altura por fora: o botão tem tamanho próprio e a distância
   que ele corre é calculada a partir do trilho. Mudar só a caixa faz
   o botão sair do trilho.
   Conta: trilho 36×20 menos 1,5px de borda de cada lado dá 33×17 por
   dentro; botão de 13px com 2px de folga sobra 16px de corrida. */
.toggle--sm{width:36px;height:20px}
.toggle--sm .toggle-tr::before{width:13px;height:13px;left:2px;top:2px}
.toggle--sm input:checked+.toggle-tr::before{transform:translateX(16px)}
@keyframes tgPulsa{0%,100%{opacity:1}50%{opacity:.45}}

/* ══════════ NAVEGAÇÃO ══════════ */
.nav{width:var(--nav-larg);flex:none;display:flex;flex-direction:column;
  background:linear-gradient(180deg,rgba(255,255,255,.04),rgba(255,255,255,.015));
  border-right:1px solid var(--border);
  backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px)}
.nav-logo{padding:var(--s5) var(--s4) var(--s4);display:flex;align-items:center;gap:10px;
  font:800 15px/1 var(--sans);letter-spacing:-.01em}
.nav-logo .mark{width:26px;height:26px;border-radius:var(--r-sm);flex:none;
  background:linear-gradient(140deg,#7fe9f2,var(--cyan));
  box-shadow:inset 0 1px 0 rgba(255,255,255,.35),-3px 2px 9px rgba(0,219,233,.20)}
.nav-body{flex:1;padding:0 10px;display:flex;flex-direction:column;gap:var(--s1)}
.nav-group{font:700 9.5px/1 var(--mono);text-transform:uppercase;letter-spacing:.12em;
  color:var(--muted);opacity:.65;padding:18px 12px 8px}
/* Serve a <a>, a <div> e a <button>: por isso zera fundo, borda,
   sublinhado e alinhamento de texto aqui, e nao com style= em cada
   tela. Era o style= inline que segurava o sublinhado, e ele sumiu
   quando o menu passou a ser injetado. */
.nav-item{display:flex;align-items:center;gap:11px;padding:11px 13px;border-radius:var(--r-md);
  color:var(--muted);font:600 13px var(--sans);cursor:pointer;position:relative;
  width:100%;text-align:left;text-decoration:none;
  border:0;background:none;background-clip:padding-box;
  transition:color .15s,background .15s}
.nav-item svg{flex:none;opacity:.85}
.nav-item:hover,.nav-item.is-hover{color:var(--text);background:rgba(255,255,255,.06)}
/* Item de menu e peça pequena: sem fio de luz, sem borda e sem brilho
   externo. Luz demais em elemento pequeno vira sujeira nas arestas —
   o marcador aqui é a barra ciano de 2px e o fundo levemente tingido. */
.nav-item.active{color:var(--cyan);
  background:linear-gradient(90deg,rgba(0,219,233,.16) 0%,rgba(0,219,233,.142) 9%,rgba(0,219,233,.120) 19%,rgba(0,219,233,.097) 29%,rgba(0,219,233,.075) 39%,rgba(0,219,233,.056) 48%,rgba(0,219,233,.040) 57%,rgba(0,219,233,.027) 65%,rgba(0,219,233,.018) 72%,rgba(0,219,233,.011) 79%,rgba(0,219,233,.0065) 85%,rgba(0,219,233,.0035) 90%,rgba(0,219,233,.0015) 94%,rgba(0,219,233,.0005) 97%,rgba(0,219,233,0) 100%);
  box-shadow:inset 2px 0 0 var(--cyan)}
.nav-item.active svg{opacity:1}
/* ── CONTADOR — pastilha sem borda ──────────────────────────────────
   Peça pequena demais para receber tratamento de vidro: sem borda,
   sem linha de luz, sem sombra. Só um preenchimento tingido e o
   número. Vermelho exige ação, âmbar apenas avisa. */
.nav-badge{margin-left:auto;font:700 10px/1 var(--mono);padding:4px 7px;
  border-radius:var(--r-pill);font-variant-numeric:tabular-nums;
  background:var(--negative-bg);color:#fff}
/* No âmbar o texto vira escuro: branco sobre amarelo não tem contraste. */
.nav-badge.soft{background:#f5b13c;color:#241604}

.nav-chev{margin-left:auto;opacity:.5;display:flex;transition:transform .2s}
.nav-item.open .nav-chev{transform:rotate(90deg);opacity:.9}
/* Fechado nao ocupa lugar. Abre pelo `.open` do proprio item pai, que
   e a mesma classe que ja girava a seta — sem estado novo para manter. */
.nav-sub{display:none;flex-direction:column;gap:var(--s1);margin:2px 0 6px 22px;padding-left:12px;
  border-left:1px solid var(--border)}
.nav-item.open+.nav-sub{display:flex}
/* Tela que ainda nao existe: visivel e apagada. Some, e ninguem sabe
   que vai existir; fica clicavel, e leva a lugar nenhum. */
/* NÃO EXISTE ITEM DE MENU APAGADO. Existiu — `.is-off` — para a tela
   que ainda não tinha página, e foi retirado com os três itens que o
   usavam. Item apagado é um lugar onde a pessoa clica, nada acontece, e
   ela fica sem saber se quebrou ou se ainda não existe; e ocupa o
   primeiro lugar onde se procura quando se está perdido.

   No menu entra o que abre. O que falta mora na lista de trabalho. */
.nav-sub a{padding:8px 12px;border-radius:var(--r-sm);color:var(--muted);
  font:500 12.5px var(--sans);text-decoration:none;position:relative}
.nav-sub a:hover{color:var(--text);background:rgba(255,255,255,.05)}
.nav-sub a.active{color:var(--cyan)}
.nav-sub a.active::before{content:'';position:absolute;left:-13px;top:50%;transform:translateY(-50%);
  width:2px;height:14px;border-radius:2px;background:var(--cyan);box-shadow:0 0 8px rgba(0,219,233,.5)}
.nav-foot{padding:12px 10px 14px;border-top:1px solid var(--border);display:flex;flex-direction:column;gap:var(--s1)}
.nav-user{display:flex;align-items:center;gap:11px;padding:9px 12px;border-radius:var(--r-md);cursor:pointer}
.nav-user:hover{background:rgba(255,255,255,.06)}
.nav-avatar{width:28px;height:28px;border-radius:50%;flex:none;display:grid;place-items:center;
  font:800 11px var(--sans);color:#04141a;
  background:linear-gradient(140deg,var(--cyan),#7fd6ff);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.45)}
.nav-user-name{font:700 12.5px/1.2 var(--sans);color:var(--text)}
.nav-user-sub{font:500 10.5px/1.2 var(--mono);color:var(--muted)}
.rail{width:72px;flex:none;display:flex;flex-direction:column;align-items:center;gap:4px;
  padding:16px 0;background:linear-gradient(180deg,rgba(255,255,255,.04),rgba(255,255,255,.015));
  border-right:1px solid var(--border)}
.rail-item{width:46px;height:46px;border-radius:var(--r-md);display:grid;place-items:center;
  color:var(--muted);cursor:pointer;position:relative;border:0;background-clip:padding-box}
.rail-item:hover{color:var(--text);background:rgba(255,255,255,.06)}
.rail-item.active{color:var(--cyan);
  background:linear-gradient(180deg,rgba(0,219,233,.17) 0%,rgba(0,219,233,.13) 16%,rgba(0,219,233,.095) 30%,rgba(0,219,233,.065) 43%,rgba(0,219,233,.042) 55%,rgba(0,219,233,.025) 66%,rgba(0,219,233,.014) 76%,rgba(0,219,233,.007) 84%,rgba(0,219,233,.003) 91%,rgba(0,219,233,.001) 96%,rgba(0,219,233,0) 100%)}
.rail-item .dot-badge{position:absolute;top:8px;right:8px;width:7px;height:7px;border-radius:50%;
  background:var(--negative);box-shadow:0 0 0 2px var(--bg)}

/* ══════════ ABAS ══════════ */
.tabs{display:flex;gap:var(--s5);border-bottom:1px solid var(--border)}
.tab{padding:12px 0;font:600 13px var(--sans);color:var(--muted);background:none;border:0;
  border-bottom:2px solid transparent;cursor:pointer;transition:.15s;margin-bottom:-1px}
.tab:hover{color:var(--text)}
.tab.active{color:var(--cyan);border-bottom-color:var(--cyan)}

/* pílulas de período */
/* Sulco fechado: o que está dentro nunca escapa. Sem isto, o realce
   da opção ativa vaza para fora do recipiente e mancha o que estiver
   ao lado — na barra de topo isso aparece na hora. */
.pills{display:inline-flex;gap:2px;padding:3px;overflow:hidden;
  background:linear-gradient(180deg,rgba(0,0,0,.34),rgba(0,0,0,.22));
  border:1px solid var(--border);border-radius:var(--r-md);
  box-shadow:inset 0 2px 4px rgba(0,0,0,.34)}
.pill{padding:7px 14px;font:700 12px var(--sans);color:var(--muted);background:none;border:0;
  border-radius:var(--r-sm);cursor:pointer;transition:.15s}
.pill:hover:not(:disabled){color:var(--text)}
/* Desabilitada continua visível: o dono precisa saber que o controle
   existe, só não serve para o que está na tela agora. */
.pill:disabled{opacity:.35;cursor:not-allowed}
/* O fio de luz aqui é sombra interna, não camada de fundo: camada de
   fundo pinta por baixo da borda e concentra alfa no canto
   arredondado, que é o que produzia a pontinha marcada. Pelo mesmo
   motivo o preenchimento pára na borda, com background-clip.
   E nada de halo para fora: a peça vive dentro de um sulco. */
.pill.active{color:#eafeff;
  background:linear-gradient(180deg,rgba(0,219,233,.20),rgba(0,219,233,.05));
  background-clip:padding-box;
  border:1px solid rgba(0,219,233,.30);padding:6px 13px;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.14),
             inset 0 -1px 0 rgba(255,255,255,.03),
             0 2px 5px rgba(0,0,0,.26)}

/* chip de filtro ativo */
.chip{display:inline-flex;align-items:center;gap:var(--s2);padding:6px 8px 6px 12px;
  font:600 12px var(--sans);border:1px solid var(--border-strong);
  border-radius:var(--r-pill);color:var(--cyan);overflow:hidden;
  background:
    linear-gradient(90deg,transparent,rgba(255,255,255,.30),transparent) 50% 0/100% 1px no-repeat,
    linear-gradient(180deg,rgba(0,219,233,.16),rgba(0,219,233,.05));
  backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.10)}
.chip button{background:none;border:0;color:inherit;cursor:pointer;opacity:.7;font-size:14px;line-height:1;padding:0 2px}
.chip button:hover{opacity:1}

/* ══════════ BADGE ══════════ */
.badge{display:inline-flex;align-items:center;gap:6px;font:700 10px/1 var(--mono);
  text-transform:uppercase;letter-spacing:.06em;padding:5px 10px;border-radius:var(--r-pill);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.10)}
.badge .dot{width:6px;height:6px;border-radius:50%;background:currentColor;flex:none}
.badge--on{background:rgba(0,224,138,.14);color:var(--positive);border:1px solid rgba(0,224,138,.30)}
.badge--off{background:rgba(255,255,255,.06);color:var(--muted);border:1px solid var(--border)}
.badge--warn{background:rgba(255,192,96,.14);color:var(--warning);border:1px solid rgba(255,192,96,.30)}
.badge--err{background:rgba(224,57,43,.24);color:var(--negative);border:1px solid rgba(255,77,61,.30)}

/* ══════════ KPI ══════════ */
.kpi-row{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:clamp(14px,1.4vw,24px)}
/* Cartão DEITADO: ícone à esquerda, rótulo e valor empilhados ao lado
   dele, e a linha de apoio como rodapé atravessando as duas colunas.

   A grade de duas colunas é o que põe rótulo e valor colados. Em
   coluna única o ícone empurraria os dois para baixo e o cartão
   cresceria sem ganhar nada.

   O ícone não informa o que o rótulo não diga — ele existe para o
   olho achar o cartão certo sem ler o rótulo de todos. */
.kpi{padding:clamp(16px,1.5vw,22px);display:grid;gap:2px var(--s3);
  grid-template-columns:38px minmax(0,1fr)}
.kpi:hover{transform:translateY(-2px);border-color:rgba(0,219,233,.35)}
.kpi-ic{display:grid;place-items:center;width:38px;height:38px;
  grid-row:1/3;align-self:start;border-radius:11px;color:var(--cyan);
  background:rgba(0,219,233,.10);border:1px solid rgba(0,219,233,.20)}
.kpi>.t-label{align-self:end}
/* A linha de apoio atravessa as duas colunas e encosta na borda: é
   rodapé do cartão, e não continuação do valor. */
.kpi>.row{grid-column:1/-1;margin-top:var(--s3)}
/* O rótulo do KPI é maior que o rótulo padrão: aqui ele é o nome da
   métrica, a informação que você procura, e não uma etiqueta de apoio
   como num campo de formulário. O afastamento entre letras cai de
   0,10 para 0,05em — caixa alta grande precisa de menos, e com o
   valor original ficaria esparramada. */
.kpi .t-label{font-size:13px;letter-spacing:.07em;color:var(--muted)}
/* ── ROAS E LUCRO GANHAM A FAIXA DA TABELA ───────────────
   Mesma régua, mesma cor, mesmo `faixaRoas`. São os dois cartões que
   respondem "está indo bem?" — os outros respondem "quanto?", e
   quanto não é bom nem ruim sozinho: custo alto pode ser ótimo.

   ── O VIDRO INTEIRO PEGA A COR, E NÃO SÓ O FUNDO ──────────
   A peça de vidro do sistema tem quatro partes: superfície, borda, fio
   de luz no topo e fio na aresta esquerda. Tingir só a superfície
   deixa uma mancha colorida dentro de uma moldura branca — lê como
   fundo sujo, e não como peça colorida. Aqui as QUATRO recebem a cor,
   mais um halo de fora, que é a mesma receita do hover do botão.

   A DILUIÇÃO DO FUNDO É MENOR QUE NA LINHA, e não por capricho. A
   linha assenta sobre fundo opaco; o cartão é vidro sobre o céu, que
   é quase preto — medido, com os .34 da linha o verde daria #035037,
   praticamente preto. Quem carrega a cor aqui é a moldura, não o
   miolo: assim o número grande continua sobre fundo escuro, que é
   onde ele se lê melhor. */
.kpi.is-good{background:linear-gradient(rgba(0,224,138,.16),rgba(0,224,138,.16)),var(--surface);
  border-color:rgba(0,224,138,.50);
  box-shadow:var(--sh-card),inset 0 1px 0 rgba(0,224,138,.30),
             inset 0 -1px 0 rgba(0,224,138,.10),0 0 20px rgba(0,224,138,.13)}
.kpi.is-ok{background:linear-gradient(rgba(0,224,138,.09),rgba(0,224,138,.09)),var(--surface);
  border-color:rgba(0,224,138,.32);
  box-shadow:var(--sh-card),inset 0 1px 0 rgba(0,224,138,.20),
             inset 0 -1px 0 rgba(0,224,138,.07),0 0 18px rgba(0,224,138,.08)}
.kpi.is-warn{background:linear-gradient(rgba(255,192,96,.14),rgba(255,192,96,.14)),var(--surface);
  border-color:rgba(255,192,96,.46);
  box-shadow:var(--sh-card),inset 0 1px 0 rgba(255,192,96,.28),
             inset 0 -1px 0 rgba(255,192,96,.09),0 0 20px rgba(255,192,96,.12)}
.kpi.is-bad{background:linear-gradient(rgba(255,77,61,.16),rgba(255,77,61,.16)),var(--surface);
  border-color:rgba(255,77,61,.48);
  box-shadow:var(--sh-card),inset 0 1px 0 rgba(255,77,61,.28),
             inset 0 -1px 0 rgba(255,77,61,.09),0 0 20px rgba(255,77,61,.13)}

/* Os dois fios de luz do vidro são pseudo-elementos, e por isso
   precisam ser repintados um a um — `box-shadow` não os alcança. */
.kpi.is-good::before{background:linear-gradient(90deg,transparent,rgba(0,224,138,.70),transparent)}
.kpi.is-good::after {background:linear-gradient(180deg,rgba(0,224,138,.55),transparent,rgba(0,224,138,.14))}
.kpi.is-ok::before  {background:linear-gradient(90deg,transparent,rgba(0,224,138,.45),transparent)}
.kpi.is-ok::after   {background:linear-gradient(180deg,rgba(0,224,138,.36),transparent,rgba(0,224,138,.10))}
.kpi.is-warn::before{background:linear-gradient(90deg,transparent,rgba(255,192,96,.66),transparent)}
.kpi.is-warn::after {background:linear-gradient(180deg,rgba(255,192,96,.52),transparent,rgba(255,192,96,.13))}
.kpi.is-bad::before {background:linear-gradient(90deg,transparent,rgba(255,77,61,.66),transparent)}
.kpi.is-bad::after  {background:linear-gradient(180deg,rgba(255,77,61,.52),transparent,rgba(255,77,61,.13))}

/* O ícone acompanha a faixa. Ciano num cartão vermelho seria a marca
   discutindo com o estado, e o estado tem que ganhar. */
.kpi.is-good .kpi-ic{color:var(--positive);background:rgba(0,224,138,.14);border-color:rgba(0,224,138,.34)}
.kpi.is-ok   .kpi-ic{color:var(--positive);background:rgba(0,224,138,.10);border-color:rgba(0,224,138,.22)}
.kpi.is-warn .kpi-ic{color:var(--warning); background:rgba(255,192,96,.14);border-color:rgba(255,192,96,.32)}
.kpi.is-bad  .kpi-ic{color:var(--negative);background:rgba(255,77,61,.14); border-color:rgba(255,77,61,.32)}

/* No hover o halo abre, como no botão do sistema — só que na cor da
   faixa em vez do ciano da marca. */
.kpi.is-good:hover{border-color:rgba(0,224,138,.70);
  box-shadow:var(--sh-card),inset 0 1px 0 rgba(0,224,138,.38),
             inset 0 -1px 0 rgba(0,224,138,.12),0 0 30px rgba(0,224,138,.22)}
.kpi.is-ok:hover{border-color:rgba(0,224,138,.46);
  box-shadow:var(--sh-card),inset 0 1px 0 rgba(0,224,138,.26),
             inset 0 -1px 0 rgba(0,224,138,.08),0 0 26px rgba(0,224,138,.14)}
.kpi.is-warn:hover{border-color:rgba(255,192,96,.64);
  box-shadow:var(--sh-card),inset 0 1px 0 rgba(255,192,96,.36),
             inset 0 -1px 0 rgba(255,192,96,.11),0 0 30px rgba(255,192,96,.20)}
.kpi.is-bad:hover{border-color:rgba(255,77,61,.66);
  box-shadow:var(--sh-card),inset 0 1px 0 rgba(255,77,61,.36),
             inset 0 -1px 0 rgba(255,77,61,.11),0 0 30px rgba(255,77,61,.22)}

.kpi-val{font:800 clamp(21px,1.7vw,28px)/1.1 var(--mono);font-variant-numeric:tabular-nums;margin:4px 0 0}
.kpi-delta{font:700 11px/1 var(--mono)}
.pos{color:var(--positive)} .neg{color:var(--negative)} .warn{color:var(--warning)}

/* ══════════ TABELA ══════════ */
.table-wrap{overflow-x:auto}
/* ── DENSIDADE DA TABELA ─────────────────────────────────────────
   Medida na ALTURA, e não no gosto. Numa tabela de oito linhas o
   respiro somava 562px, dos quais 344 eram só o miolo das células.
   Cortando a célula de 12 para 8, o respiro entre linhas de 6 para 5,
   o cabeçalho de coluna de 12 para 9 e o total dele de 16 para 14,5,
   a mesma tabela passa a caber em 461px — dezoito por cento menos,
   sem perder uma linha nem uma coluna.

   A largura não mudou: os cortes de coluna medidos continuam valendo
   como estavam. */
table{width:100%;border-collapse:separate;border-spacing:0 5px;font-size:13px}

/* ── QUEM FICA COM A SOBRA DE LARGURA ──────────────────────────────
   A tabela ocupa a largura toda, e o navegador reparte o que sobra
   entre as colunas na proporção do conteúdo delas. Numa tela larga isso
   dá o pior resultado possível: a coluna de endereço, que tem o texto
   mais comprido, fica com quase toda a sobra — 210px de URL dentro de
   uma coluna de 970 — e abre um vão de oitocentos pixels no meio da
   linha. Os dados ficam nas duas pontas e o olho tem de atravessar o
   vazio para ligar um ao outro.

   A regra: por padrão a coluna CABE NO CONTEÚDO (`width:1%` é o jeito
   de dizer "o mínimo possível" numa tabela), e só quem está marcado
   como `.tb-larga` divide a sobra. Marca-se o que cresce de verdade —
   nome e endereço —, e o resto encosta.

   Não é `table-layout:fixed`: aí as larguras deixariam de responder ao
   conteúdo e um nome comprido cortaria em vez de empurrar.

   Vale só nas tabelas de CADASTRO (`#tk-corpo`), e não em toda tabela
   do produto: a do relatório tem quinze colunas de número e uma régua
   de larguras que já foi acertada na tela. Regra global aqui mexeria
   nela sem ninguém ter pedido. */
#tk-corpo tbody td,#tk-corpo thead th{width:1%}
#tk-corpo tbody td.tb-larga,#tk-corpo thead th.tb-larga{width:auto}
/* Endereço comprido corta em reticências em vez de empurrar a tabela
   para fora da tela. O nome não corta: é por ele que se procura. */
#tk-corpo tbody td.tb-larga--corta{max-width:0;overflow:hidden;
  text-overflow:ellipsis;white-space:nowrap}
/* Rótulo em 13px e total em 14,5px. O afastamento entre letras cai de
   0,10 para 0,06em: caixa alta pequena precisa de muito afastamento
   para ser legível, caixa alta grande precisa de pouco — a mesma
   inversão do rótulo do KPI e do título de tela. */
thead th{font:700 13px/1 var(--mono);text-transform:uppercase;letter-spacing:.06em;color:var(--muted);
  text-align:left;padding:9px 15px;white-space:nowrap;position:sticky;top:0}
thead th.num{text-align:right}

/* ── o cabeçalho é UMA peça de vidro, não uma fileira de peças ────
   A receita é a do botão: superfície em degradê de branco, fio de luz
   no topo e fio na aresta esquerda.

   O que não pode existir aqui é sombra projetada por célula. Sombra
   externa é desenhada PARA FORA da caixa, então a sombra de cada
   célula escurecia a borda da vizinha — e cada divisa virava uma
   listra vertical. Era o que aparecia como "marcas nas divisas".

   Os fios de luz são sombra INTERNA e não camada de fundo: camada de
   fundo reinicia em cada célula e o fio acende e apaga coluna por
   coluna. Como sombra interna ele atravessa a faixa inteira, porque
   as células são vizinhas sem espaço horizontal entre elas.

   Também não há backdrop-filter: a base tem de ser opaca por causa da
   coluna presa, e sobre base opaca o desfoque não teria o que
   desfocar. O vidro aqui é o desenho da luz, não o desfoque.

   A elevação vem do degradê mais os fios mais os 6px de folga que o
   border-spacing deixa entre o cabeçalho e a primeira linha. */
thead th{
  background:linear-gradient(180deg,rgba(255,255,255,.085),rgba(255,255,255,.02)),
             var(--surface-op);
  /* O aro de borda existe, igual ao do card e do botão — mas só nas
     ARESTAS EXTERNAS da faixa. Borda em cada célula encostaria na da
     vizinha e cada divisa viraria uma linha dupla, que é o mesmo
     defeito da sombra por célula. Então: topo e base em todas, e
     esquerda e direita só nas pontas. */
  border-top:1px solid var(--border);
  border-bottom:1px solid var(--border);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.12),
             inset 0 -1px 0 rgba(255,255,255,.04)}
thead th:first-child{border-left:1px solid var(--border);
  border-radius:var(--r-md) 0 0 var(--r-md);
  box-shadow:inset 1px 0 0 rgba(255,255,255,.10),
             inset 0 1px 0 rgba(255,255,255,.12),
             inset 0 -1px 0 rgba(255,255,255,.04)}
thead th:last-child{border-right:1px solid var(--border);
  border-radius:0 var(--r-md) var(--r-md) 0;
  box-shadow:inset -1px 0 0 rgba(255,255,255,.05),
             inset 0 1px 0 rgba(255,255,255,.12),
             inset 0 -1px 0 rgba(255,255,255,.04)}
/* O hover NÃO acende a borda: cada célula só tem topo e base, então
   acender uma acenderia um pedaço do aro no meio da faixa, como se o
   contorno tivesse quebrado. O hover acende apenas a superfície. */

/* Hover da coluna ordenável: a superfície acende, igual ao botão. */
thead th.sortable:hover{
  background:linear-gradient(180deg,rgba(255,255,255,.13),rgba(255,255,255,.03)),
             var(--surface-op)}
thead th.sortable{cursor:pointer;user-select:none}
thead th.sortable:hover{color:var(--text)}
/* A linha e OPACA, e nao translúcida. Sobre uma foto de fundo,
   linha translúcida deixa o texto disputando com a imagem — e a
   coluna presa, que precisa de fundo opaco por definição, nunca
   conseguiria acompanhar a cor da linha. */
/* A linha é a mesma base do card mais 3,5% de branco: lê como
   levemente elevada em relação ao card, que é o que ela é. */
tbody tr{background:linear-gradient(rgba(255,255,255,.035),rgba(255,255,255,.035)),var(--surface-op);
  transition:.12s}
tbody td{padding:8px 14px;border:0;background:inherit;white-space:nowrap}
tbody td:first-child{border-radius:var(--r-sm) 0 0 var(--r-sm)}
tbody td:last-child{border-radius:0 var(--r-sm) var(--r-sm) 0}
tbody td.num{text-align:right;font-family:var(--mono);font-variant-numeric:tabular-nums}
/* Nome longo trunca em vez de empurrar a tabela. Nome de campanha
   real passa de 45 caracteres com facilidade. */
/* ── O ESPAÇO DA MOEDA JÁ VEM RESERVADO ──────────────────────────
   Em real cada valor fica quatro caracteres mais longo que em dólar —
   "$ 208,53" contra "R$ 1.084,38". A coluna é medida pelo conteúdo,
   então trocar a moeda reorganizava a tabela inteira: coluna mudava de
   largura, alguma sumia por falta de espaço, e o olho perdia o lugar.

   A reserva é na CÉLULA, e não num embrulho em volta do número. Já foi
   tentado embrulhar o valor num `<span>` dentro do formatador, e
   quebrou a tela: o mesmo formatador alimenta o eixo do gráfico, que é
   `<text>` de SVG, e o centro da rosca, que é escrito por
   `textContent`. Marcação nesses dois lugares não é marcação.

   `12ch` é exato, e não um chute com folga: a fonte é monoespaçada com
   `tabular-nums`, então todo caractere tem a mesma largura. Doze cobre
   até `R$ 99.999,99`.

   Vale para TODA coluna de número das duas tabelas, e não só para as
   de dinheiro. Distinguir uma da outra em CSS exigiria marcar a célula
   no JS, e a coluna de contagem ganhar a mesma largura da de dinheiro
   deixa a grade mais regular, não menos.

   A rosca e as barras ficam de fora de propósito: vivem em cartão de
   duzentos pixels e já se adaptam sozinhas — reservar lá custaria uma
   coluna que não existe. */
#tabela td.num,#tabela th.num,
#tb-criativos td.num,#tb-criativos th.num{min-width:12ch}

.tb-txt{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}

/* ── O NOME DA LINHA É BRANCO ────────────────────────────────────
   Branco puro, e não o `--text` do sistema (#dce2f6, que puxa para o
   azul). É o único texto da tabela que ganha isso, e por um motivo:
   ele é o RÓTULO da linha — diz de quem são todos os números ao lado.
   É também o texto mais longo da linha, e o que mais sente o fundo
   tingido: sobre o verde cheio o `--text` cai para 5,80 de contraste,
   e o branco sobe para 6,86.

   Exceção declarada, e não cor nova solta no sistema: vale para o nome
   da linha e para nada mais. A linha FILHA continua em `--text`, e
   isso vira hierarquia — pai branco, filho um ponto abaixo. */
.tb-nome>.tb-txt{color:#fff}

/* Realce por sombra interna, e não troca de fundo: assim a cor de
   resultado da linha não se apaga quando o mouse passa. É a solução
   mais inteligente do sistema antigo e veio igual.
   Branco, e não ciano: sobre linha já tingida de verde ou vermelho,
   um realce colorido brigaria com a cor que está ali para informar. */
tbody tr:hover td{box-shadow:inset 0 0 0 999px rgba(255,255,255,.06)}

/* Resultado tinge a LINHA INTEIRA, sem barra na ponta. É o verde e o
   vermelho do sistema sobre a base opaca. A camada por cima da base
   opaca é o que permite à célula presa herdar exatamente o mesmo
   valor.

   ── COR FORTE, E O NÚMERO CLAREIA JUNTO ────────────────────
   A diluição saiu de .18/.20 para .34/.38 — o verde vai de 68% para
   81% de saturação, e o vermelho de 22% para 39%, que é onde ele
   deixa de parecer marrom.

   Isso tem um preço, e ele é medido: o número de lucro é verde ou
   vermelho, e sobre uma linha da MESMA cor o contraste despenca. Com
   #00E08A sobre o verde novo dá 4,29 — abaixo do mínimo de 4,5. E o
   vermelho já estava fora ANTES de eu mexer: #ff4d3d sobre a linha
   vermelha antiga dava 4,11.

   Por isso o número tem uma versão clara para linha tingida, e só
   para ela: #2bf0a2 dá 5,03 sobre o verde, #ffa196 dá 5,17 sobre o
   vermelho. A cor continua dizendo a mesma coisa, e passa a ser
   legível — o que não era.

   ── QUATRO FAIXAS, E NÃO DUAS ──────────────────────────────
   A cor sai do ROAS: abaixo de 1 vermelho, até 1,2 amarelo, até 1,5
   verde fraco, daí para cima o verde cheio. "Deu lucro" e "não deu" é
   a pergunta de ontem; a de hoje é quanto.

   Todas medidas, e todas passam o mínimo de contraste com o texto que
   fica em cima:

     < 1,0    #6a302e  39% sat   número #ffa196  5,17
     1,0–1,2  #574f37  22% sat   número #ffd08a  5,66
     1,2–1,5  #0c4138  68% sat   número #00E08A  6,51
     ≥ 1,5    #096048  81% sat   número #2bf0a2  5,03 */
tbody tr.is-good{background:linear-gradient(rgba(0,224,138,.34),rgba(0,224,138,.34)),var(--surface-op)}
tbody tr.is-ok  {background:linear-gradient(rgba(0,224,138,.18),rgba(0,224,138,.18)),var(--surface-op)}
tbody tr.is-warn{background:linear-gradient(rgba(255,192,96,.30),rgba(255,192,96,.30)),var(--surface-op)}
tbody tr.is-bad {background:linear-gradient(rgba(255,77,61,.38),rgba(255,77,61,.38)),var(--surface-op)}
/* O número clareia junto com o fundo, e só onde precisa. No verde
   fraco o `--positive` já passa, então ele fica. */
tbody tr.is-good td.pos{color:#2bf0a2}
tbody tr.is-warn td.pos{color:#ffd08a}
tbody tr.is-bad  td.neg{color:#ffa196}

/* ══════════ SOBREPOSIÇÃO ══════════════════════════════════════════
   Mesma receita de vidro do card — mesmos fios de luz, mesma borda,
   mesmas sombras internas. A ÚNICA diferença permitida é o fundo:
   essas peças flutuam sobre conteúdo, e um fundo translúcido como o
   do card deixaria o texto de baixo atravessar. Por isso um fundo
   opaco, blur maior e sombra projetada mais profunda — é só a
   distância em relação à página que muda, não a linguagem. */
.menu,.modal,.toast,.sel-pop,.cal-pop{position:relative;overflow:hidden;
  border:1px solid var(--border);background:var(--surface-float);
  backdrop-filter:blur(16px);-webkit-backdrop-filter:blur(16px);
  box-shadow:var(--sh-drop),inset 0 1px 0 rgba(255,255,255,.10),
             inset 0 -1px 0 rgba(255,255,255,.03)}
.menu{border-radius:var(--r-lg);padding:6px;min-width:min(220px,86vw);
  display:flex;flex-direction:column;gap:var(--s1)}
.menu-item{display:flex;align-items:center;gap:var(--s3);padding:9px 12px;border-radius:var(--r-sm);
  font:500 13px var(--sans);color:var(--text);cursor:pointer;position:relative}
.menu-item:hover{background:rgba(255,255,255,.06)}
.menu-item.active{color:var(--cyan)}
/* 2px, igual à barra do sidebar e à do submenu. Marcador de
   "você está aqui" tem uma espessura só no sistema inteiro. */
.menu-item.active::before{content:'';position:absolute;left:0;top:50%;transform:translateY(-50%);
  width:2px;height:16px;border-radius:2px;background:var(--cyan)}

.modal{border-radius:var(--r-lg);width:100%;max-width:520px;
  backdrop-filter:blur(18px);-webkit-backdrop-filter:blur(18px);
  box-shadow:var(--sh-modal),inset 0 1px 0 rgba(255,255,255,.10),
             inset 0 -1px 0 rgba(255,255,255,.03)}
.modal-head{padding:var(--s5) var(--s5) var(--s4);border-bottom:1px solid var(--border);
  display:flex;align-items:center;justify-content:space-between;gap:var(--s4)}
.modal-body{padding:var(--s5)}
.modal-foot{padding:var(--s4) var(--s5);border-top:1px solid var(--border);display:flex;justify-content:flex-end;gap:var(--s2)}

.toast{display:flex;align-items:flex-start;gap:var(--s3);padding:14px 16px;
  border-radius:var(--r-md);max-width:400px}
.toast--ok{border-left:3px solid var(--positive)}
.toast--err{border-left:3px solid var(--negative)}
.toast--warn{border-left:3px solid var(--warning)}
/* Onde existe a barra colorida, o fio de luz da esquerda sai: dois
   marcadores empilhados na mesma aresta sujam um ao outro. */
.toast--ok::after,.toast--err::after,.toast--warn::after{display:none}

/* A lista do seletor e o calendário são presos à JANELA, não ao
   card. Todo card de vidro tem overflow:hidden — sem isso os fios
   de luz vazam do canto arredondado — e qualquer lista aberta
   dentro dele sairia cortada. Por isso o JS pendura essas duas
   peças no fim da página e calcula a posição na mão. É a mesma
   armadilha que derruba dropdown dentro de tabela com rolagem. */
.sel-pop{position:fixed;z-index:200;padding:6px;border-radius:var(--r-lg);
  display:none;box-shadow:var(--sh-modal),inset 0 1px 0 rgba(255,255,255,.10),
  inset 0 -1px 0 rgba(255,255,255,.03)}
.sel-pop.aberto{display:block;animation:selAbre .14s ease}
.cal-pop{width:min(430px,92vw);padding:0}

/* ══════════ ESTADOS ══════════ */
.state{display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;
  padding:48px 24px;gap:10px;min-height:220px}
/* O ícone fica dentro de uma peça de vidro elevada, a mesma do card.
   Aqui cabe: com 46px ela ainda tem aresta reta suficiente para os
   fios de luz aparecerem inteiros. */
.state-ic{position:relative;overflow:hidden;flex:none;
  width:46px;height:46px;border-radius:var(--r-lg);display:grid;place-items:center;
  background:var(--surface);border:1px solid var(--border);
  backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);
  color:var(--muted);font-size:18px;line-height:1;
  box-shadow:0 3px 10px rgba(0,0,0,.30),
             inset 0 1px 0 rgba(255,255,255,.10),
             inset 0 -1px 0 rgba(255,255,255,.03)}
/* Variante pequena, para dentro de card de criativo. Existe aqui em
   vez de ser redimensionada por fora: componente do sistema não se
   ajusta com estilo inline. */
.state-ic--sm{width:38px;height:38px;font-size:14px}
.state-t{font:700 14px/1.3 var(--sans);color:var(--text)}
.state-d{font:400 12.5px/1.5 var(--sans);color:var(--muted);max-width:40ch;margin:0}
/* ══════════ MÉTRICA MIÚDA ═══════════════════════════════
   Par rótulo em cima, valor embaixo, para quando cabem vários lado a
   lado dentro de um card — criativo, resumo de linha. É o KPI sem o
   card em volta: mesmo rótulo em mono minúsculo, mesmo valor em mono
   tabular. */
.mini{display:inline-flex;flex-direction:column;gap:5px;min-width:0}
.mini-rot{font:700 10px/1 var(--mono);text-transform:uppercase;
  letter-spacing:.10em;color:var(--muted)}
.mini-val{font:700 13px/1 var(--mono);font-variant-numeric:tabular-nums}

.sk{background:linear-gradient(90deg,rgba(255,255,255,.04) 0%,rgba(255,255,255,.10) 50%,rgba(255,255,255,.04) 100%);
  background-size:200% 100%;animation:shim 1.4s ease-in-out infinite;border-radius:6px}
@keyframes shim{0%{background-position:200% 0}100%{background-position:-200% 0}}

/* ══════════ UTILITÁRIOS ══════════ */

.row{display:flex;flex-wrap:wrap;gap:var(--s3);align-items:center}
.grid2{display:grid;grid-template-columns:repeat(auto-fit,minmax(300px,1fr));gap:var(--s4)}
/* ── AS DUAS LINHAS DA TELA ──────────────────────────────────────
   Primeira: relatório com 70% e as duas roscas dividindo os 30% que
   sobram. Segunda: gráfico e criativos, 60/40 — o gráfico pede
   largura, e a tabela pede o que a soma das colunas dela pede.

   As roscas têm a MESMA ALTURA do relatório. Isso só é possível
   porque a tabela de relatórios ganhou teto: sem ele, um dia com
   quarenta campanhas abertas faria dois retângulos de vidro de
   milhares de pixels com um anel de duzentos dentro.

   O conteúdo delas encosta no topo, e o espaço que sobra fica vazio
   embaixo — é o preço de ter as três alturas batendo, e é o que o
   dono escolheu ao pedir alinhamento.

   minmax(0,…) em toda coluna, e não fr puro: sem isso uma tabela
   dentro empurra a coluna além da célula em vez de rolar por dentro,
   e o grid inteiro estoura para a direita. É a armadilha clássica de
   grid com tabela. */
.grid-tela{display:grid;gap:var(--s4);align-items:stretch;
  grid-template-columns:minmax(0,70fr) minmax(0,30fr)}
.grid-par{display:grid;gap:var(--s4);align-items:stretch;
  grid-template-columns:minmax(0,60fr) minmax(0,40fr)}
/* Par lado a lado: mesma altura (stretch, dito por extenso porque
   é requisito e não acaso) e conteúdo encostado no TOPO.

   Centrado, o cartão com duas linhas de tabela põe o anel numa altura
   e o de seis põe noutra — os cartões ficam do mesmo tamanho e os
   anéis desalinhados entre si, que é pior do que os dois torto do
   mesmo jeito. Encostados no topo, anéis, cabeçalhos de tabela e
   primeiras linhas caem todos na mesma altura. */
/* grid-template-rows:1fr, e não `auto`: com auto a única fileira
   mede o conteúdo, sobra espaço em baixo do grid e os cartões param
   antes da altura do relatório. */
.duplo{display:grid;gap:var(--s4);min-height:0;align-items:stretch;
  grid-template-rows:1fr;
  grid-template-columns:repeat(2,minmax(0,1fr))}
.duplo .centrado-v{justify-content:flex-start}
.grid-tela>section,.grid-par>section,.duplo>section{
  display:flex;flex-direction:column;min-width:0;min-height:0}
.centrado-v{flex:1;display:flex;flex-direction:column;justify-content:center;
  min-width:0;min-height:0}

/* ── A LINHA PRINCIPAL NÃO MEDE O CONTEÚDO ───────────────────────
   `grid-auto-rows` com altura definida, e não fileira automática: com
   automática a fileira mede o mais alto dos três cartões, e bastava o
   bloco de posicionamentos ganhar duas barras para esticar o relatório
   e o custo por fonte junto.

   Definida, é o contrário: a fileira manda, e quem tem conteúdo demais
   rola por dentro. É a regra do painel, e não um ajuste deste bloco. */
.grid-tela{grid-auto-rows:var(--linha-1)}

/* Nada de centrar o que sobra: não sobra mais nada. O anel cresce até
   ocupar o vão, e o que antes era margem automática virava exatamente
   o vazio que este painel não pode ter. */
.rosca-bloco .centrado-v{justify-content:flex-start;overflow-y:auto}

/* ── A LINHA INTEIRA TEM UMA ALTURA SÓ ───────────────────────────
   Ela está em `--linha-1`, lá no topo do arquivo, e vale para os três
   cartões da fileira. A tabela não tem mais altura própria: ela fica
   com o que sobra do cartão depois do cabeçalho.

   Assim o dado deixa de mandar no layout. Nenhum dos três muda de
   altura por ter mais linha, mais plataforma ou mais posicionamento —
   quem tem conteúdo demais rola por dentro. Um painel em que os blocos
   mudam de lugar conforme o dado obriga a procurar tudo de novo a cada
   troca de filtro, e era o que acontecia: o bloco de posicionamentos
   crescia e esticava o relatório e o custo por fonte junto.

   Altura DERIVADA da fileira, e não `flex:1`. Com flex:1 a tabela fica
   com o que sobra quando o cartão tem altura definida — e some quando
   ele não tem, porque a base zero não devolve nada. O cartão perde a
   altura definida em tela estreita, onde a fileira volta a medir
   conteúdo, e aí a tabela sumiria. Derivada, ela vale o mesmo nos dois
   casos: a fileira menos o respiro do cartão (48) e o cabeçalho (82). */
#tabela{height:calc(var(--linha-1) - 130px);overflow:auto}

/* A ROLAGEM COMEÇA COLADA NO TOPO.

   Aqui havia encaixe de rolagem (`scroll-snap`), para a linha não se
   partir também durante o movimento. SAIU, e a troca foi consciente: o
   encaixe precisa saber a altura do cabeçalho grudado para aceitar o
   topo como posição válida, e qualquer erro nessa medida faz a tabela
   ABRIR JÁ ROLADA — um defeito que aparece toda vez que a tela carrega,
   para consertar um que aparece só com o dedo no meio da lista.

   O que importa é a tabela parada, e disso quem cuida é
   `fecharNaLinha`: a caixa fecha no fim da última linha inteira. */

/* ── A SEGUNDA FILEIRA, PELA MESMA REGRA ─────────────────────────
   Gráfico e criativos saem de `--linha-2`, cada um descontando o
   próprio cabeçalho. Antes a altura da fileira era a da tabela de
   criativos, e o gráfico ficava com o que sobrasse.

   O GRÁFICO PRECISA DE ALTURA VINDA DO CSS, e não de medir o container
   na hora de desenhar. Medindo, ele dependia de QUANDO era desenhado:
   no primeiro desenho a medida vinha pequena e ele caía num valor de
   reserva de 220px dentro de um espaço de 400, deixando 90px de vão em
   cima e 90 embaixo; ao trocar o período, a segunda medida vinha certa
   e ele preenchia. O mesmo dado desenhava de dois tamanhos conforme o
   que tivesse acontecido antes.

   Por isso `#grafico` também perdeu o `centrado-v`: com `flex:1` a base
   zero venceria a altura declarada, e centralizar era justamente o que
   repartia o vão em dois. Agora não há vão para repartir.

   `flex:none` nos dois pelo mesmo motivo: quem manda é a altura
   declarada, e não o que sobrar da caixa. A fileira definida em
   `grid-auto-rows` é a garantia de fora — nem o cabeçalho quebrando em
   duas linhas estica a fileira. */
#grafico{flex:none;height:calc(var(--linha-2) - 83px)}
#tb-criativos{flex:none;height:calc(var(--linha-2) - 111px);
  min-height:0;overflow:auto}
.grid-par{grid-auto-rows:var(--linha-2)}

/* Abaixo de 1900 a coluna de 30% dá cartões de 216px, e neles não
   cabe nem a rosca com uma coluna de tabela — medido, não chutado. */
/* Empilhado, cada cartão ganha a fileira dele — e continua com a mesma
   altura, porque `grid-auto-rows` vale para as duas fileiras. */
@media (max-width:1899px){
  .grid-tela{grid-template-columns:1fr}
}
/* A tabela de criativos precisa de 404px para as quatro colunas que
   ela nunca solta. Abaixo de 1300 a coluna de 40% não os tem. */
@media (max-width:1299px){
  .grid-par{grid-template-columns:1fr}
}
/* O par também empilha, e aí cada um dos dois quer a fileira inteira.
   Sem isto os dois dividiriam a altura de UMA fileira e ficariam com
   metade cada. O relatório continua com a altura dele pela tabela. */
@media (max-width:759px){
  .grid-tela{grid-auto-rows:auto}
  .duplo{grid-template-columns:1fr;grid-template-rows:none;
    grid-auto-rows:var(--linha-1)}
}

code{font:500 12px var(--mono);background:rgba(255,255,255,.06);padding:2px 6px;border-radius:4px;color:var(--cyan-bright)}

/* ══════════ ESTRUTURA DE TELA ═══════════════════════════════════
   Sidebar fixa à esquerda, barra de topo grudada no alto e o
   conteúdo rolando por baixo. Largura total, sem limite máximo —
   decisão do dono, que trabalha em ultrawide. */
.app{display:flex;min-height:100vh}
.app-nav{flex:none;position:sticky;top:0;height:100vh;z-index:30}
.app-main{flex:1;min-width:0;display:flex;flex-direction:column}
.topbar{position:sticky;top:0;z-index:25;display:flex;align-items:center;
  gap:var(--s3) var(--s4);flex-wrap:wrap;
  padding:var(--s3) clamp(16px,2vw,28px);min-height:64px;
  border-bottom:1px solid var(--border);
  /* A barra de topo é vidro, não tampa: usa a mesma superfície
     translúcida do card, para o céu continuar por trás dela. O
     desfoque é maior que o do card porque aqui passa conteúdo
     rolando por baixo, e sem ele o texto de baixo atravessa o de
     cima. */
  background:linear-gradient(180deg,rgba(255,255,255,.055),rgba(255,255,255,.015));
  backdrop-filter:blur(20px) saturate(118%);
  -webkit-backdrop-filter:blur(20px) saturate(118%)}
/* Sans, e não mono. A mono existe para número que se compara em
   coluna, onde dígito de largura fixa é o que impede a linha de
   dançar. Aqui é uma frase solta que ninguém alinha com nada. */
.topbar-sub{font:500 11.5px/1.4 var(--sans);color:var(--muted);display:block;margin-top:4px}
/* Uma linha só, sempre. Os controles encolhem até o limite e, se
   ainda assim não couberem, a faixa rola na horizontal — quebrar em
   duas linhas empurra o conteúdo para baixo e faz a barra de topo
   mudar de altura conforme a largura da tela. */
.topbar-fim{margin-left:auto;display:flex;align-items:center;
  gap:var(--s2);flex-wrap:nowrap;justify-content:flex-end;
  min-width:0;overflow-x:auto;scrollbar-width:none}
.topbar-fim::-webkit-scrollbar{height:0}
.topbar-fim .pills{flex:none}
.topbar-fim .sel-btn{padding-left:11px;padding-right:11px}
/* separa período de recorte: são duas perguntas diferentes */
.topbar-sep{width:1px;align-self:stretch;margin:2px 4px;flex:none;
  background:var(--border)}
.conteudo{padding:clamp(16px,2vw,28px);display:flex;flex-direction:column;gap:var(--s5)}
.bloco-t{font:700 13px/1 var(--sans);margin:0 0 var(--s3);
  display:flex;align-items:center;gap:var(--s3);flex-wrap:wrap}
.bloco-t .t-hint{font-weight:400}

/* ══════════ GRÁFICO ═════════════════════════════════════════════
   SVG desenhado à mão, sem biblioteca: são duas linhas e barras.
   Biblioteca de gráfico traz a própria tipografia, os próprios
   tooltips e a própria paleta — e aí o painel volta a ter dois
   design systems, que foi o problema do sistema antigo. */
.gr{position:relative;width:100%}
.gr svg{display:block;width:100%;height:auto;overflow:visible}
.gr-eixo{font:600 9.5px var(--mono);fill:var(--muted)}
.gr-malha{stroke:rgba(255,255,255,.06);stroke-width:1}
.gr-leg{display:flex;align-items:center;gap:var(--s4);flex-wrap:wrap;
  font:600 11px var(--sans);color:var(--muted)}
.gr-leg span{display:inline-flex;align-items:center;gap:7px}
.gr-leg i{width:10px;height:3px;border-radius:2px;display:inline-block}
/* Sem transform de deslocamento: quem posiciona é o JS, que mede o
   balão e o mantém dentro do gráfico. Com translate negativo ele sai
   pela borda do cartão — que corta — e a leitura desaparece
   justamente no ponto mais alto e nas duas pontas, que é onde mais
   se quer ler. */
.gr-tip{position:absolute;pointer-events:none;z-index:5;left:0;top:0;
  padding:9px 11px;border-radius:var(--r-md);
  background:var(--surface-float);border:1px solid var(--border);
  box-shadow:var(--sh-drop);white-space:nowrap;opacity:0;transition:opacity .12s}
.gr-tip.on{opacity:1}
.gr-tip b{display:block;font:700 10px/1 var(--mono);color:var(--muted);
  text-transform:uppercase;letter-spacing:.06em;margin-bottom:7px}
.gr-tip u{display:flex;justify-content:space-between;gap:16px;text-decoration:none;
  font:600 11.5px/1.7 var(--mono);font-variant-numeric:tabular-nums}
.gr-vazio{display:grid;place-items:center;min-height:180px;color:var(--muted);
  font:500 12.5px var(--sans)}

/* ══════════ ROSCA ═══════════════════════════════════════════════
   Reparte um total entre poucas partes. O buraco do meio não é
   enfeite: é onde mora o total, que é o número que a pessoa procura
   primeiro. Sem ele, sobra um gráfico que obriga a somar de cabeça.

   O anel é feito de tracejado (stroke-dasharray) sobre um círculo,
   não de fatias desenhadas à mão. Um arco por parte, deslocado pelo
   que veio antes — sem trigonometria e sem emenda entre pedaços.

   O texto do meio é HTML por cima, não <text> dentro do SVG: dentro
   do SVG ele escalaria junto com o desenho e a tipografia sairia do
   sistema em telas pequenas.

   Ela se molda: a rosca ocupa uma fatia da largura e a legenda toma
   o resto; quando não cabem lado a lado, a legenda desce. */
/* Rosca centrada em cima, números embaixo. Lado a lado, a rosca
   competia por largura com a tabela e as duas ficavam apertadas;
   empilhadas, cada uma usa a largura inteira do cartão — a rosca
   ganha diâmetro e a tabela ganha coluna. */
/* GRID e não flex, e por um motivo prático: `minmax(0,1fr) auto` dá ao
   anel uma altura DEFINIDA — o que sobrou depois da tabela — e altura
   definida é o que faz `height:100%` e a proporção do anel valerem.
   Em coluna de flex a base zero vence a altura declarada, e o anel
   voltava ao tamanho de antes, empurrando a tabela para fora. */
.rosca-wrap{display:grid;grid-template-rows:minmax(0,1fr) auto;
  justify-items:center;gap:var(--s4);height:100%;min-height:0}
/* ── O BLOCO DA ROSCA SE MEDE PELO PRÓPRIO CARTÃO ──────────────
   E não pela janela. O mesmo bloco vive num cartão de 15% da tela e
   num cartão de metade dela — media query olharia a janela e daria a
   mesma resposta para os dois. Container query pergunta ao cartão.

   É a forma correta da regra que o guia já tinha: o componente se
   molda ao espaço que recebe.

   inline-size, e NÃO size. `container-type:size` confina as duas
   dimensões, e confinar a altura faz o cartão ser medido COMO SE NÃO
   TIVESSE CONTEÚDO: a altura colapsa, o overflow:hidden do vidro
   corta tudo, e sobra um cartão vazio com o título. Aconteceu aqui.
   Com inline-size a largura vira referência para o container query e
   a altura continua saindo do conteúdo. */
.rosca-bloco{container-type:inline-size;container-name:rosca}

/* A ROSCA É QUADRADA SEMPRE, E POR ISSO MEDIDA PELA LARGURA.

   Ela já foi `height:100%` com teto de largura, para crescer junto com
   o cartão. Isso quebrou quando a fileira subiu para 668px: sobrava
   altura de sobra, a caixa virava 320 por 467 — e o disco de vidro do
   meio, que é posicionado em PORCENTAGEM da caixa, virava uma elipse
   dentro de um anel redondo.

   O anel é o único bloco da tela cuja proporção é o próprio conteúdo:
   círculo não estica. Se sobra altura no cartão, o vão é o preço de
   manter o círculo redondo — e é o preço certo.

   O teto de 320px existe para o anel não virar o assunto do cartão num
   monitor largo; `align-self:center` põe o que sobra em cima e embaixo
   em partes iguais, em vez de tudo no pé. */
.rosca{position:relative;width:min(100%,320px);aspect-ratio:1;
  align-self:center}
.rosca svg{display:block;width:100%;height:100%;transform:rotate(-90deg)}
.rosca circle{fill:none}
/* O sulco onde o anel assenta. Claro, e não rebaixado escuro como os
   campos: aqui ele aparece nos VÃOS entre as fatias, e escuro cada
   vão virava uma cunha preta atravessando o desenho. */
.rosca .rosca-trilho{stroke:rgba(255,255,255,.07)}
/* Fio de luz nas duas bordas do anel. Em peça curva o fio não pode
   ser pseudo-elemento — é um contorno fino, que é o equivalente do
   sistema para borda arredondada. O de dentro é mais fraco: a luz vem
   de cima e a borda interna pega de raspão. */
.rosca .rosca-fio{stroke:rgba(255,255,255,.16);stroke-width:.7}
.rosca .rosca-fio--dentro{stroke:rgba(255,255,255,.07)}

/* O disco de vidro no meio do anel — mesma receita do cartão: fundo
   translúcido, desfoque do que passa atrás e fios de luz internos.
   É ele que faz o buraco parecer parte da peça em vez de um furo. */
.rosca-vidro{position:absolute;border-radius:50%;
  background:var(--surface);backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.11),
             inset 0 -1px 0 rgba(255,255,255,.03),
             0 2px 10px rgba(0,0,0,.28)}
.rosca-centro{position:absolute;inset:0;display:grid;place-content:center;
  text-align:center;line-height:1.3;pointer-events:none}
/* Sem tamanho aqui: quem define é o JS, que mede o buraco do anel e o
   comprimento do valor. Um clamp por viewport não serve — o mesmo
   anel vive em cartões de larguras diferentes, e o mesmo cartão
   mostra "$ 73,34" num dia e "$ 12.087,45" no outro. */
.rosca-centro b{display:block;font:800 16px/1.15 var(--mono);color:var(--text);
  font-variant-numeric:tabular-nums}
.rosca-centro span{font:700 9px var(--mono);color:var(--muted);
  text-transform:uppercase;letter-spacing:.08em}

/* Abaixo da rosca vai uma TABELA, não uma legenda solta — os números
   alinham por coluna em vez de ficarem em texto corrido, e a largura
   do cartão vira informação em vez de vão. A bolinha de cor mora na
   célula do nome: sem ela não haveria como ligar arco a plataforma e
   a rosca viraria enfeite. */
.rosca-wrap>.table-wrap{width:100%;min-width:0}
/* "Meta" e "TikTok" não precisam dos 150px que um nome de campanha
   precisa — e são esses 50px que fazem as outras colunas caberem sem
   rolagem lateral. */
/* Larga o bastante para a marca com o nome, que aí é a própria
   identificação da linha. */
.rosca-wrap thead th:first-child,
.rosca-wrap tbody td:first-child{width:96px;max-width:96px}
/* Menores aqui que na faixa: a coluna é estreita, e cada pixel de
   altura da marca custa até cinco de largura. A proporção entre as
   duas é a mesma da faixa — letra de 8,6px nas duas —, porque quem
   muda é a escala, e não a regra.

   Aqui a célula é flex, então `vertical-align` não vale de nada e a
   margem negativa precisa ser dos dois lados: a linha volta a ter a
   altura que tinha, e a nota sobra para dentro do respiro da célula. */
.rosca-wrap .logo-nome[src*="meta"]{height:9px;margin-top:0}
.rosca-wrap .logo-nome[src*="tiktok"]{height:16.5px;margin-block:-2.5px}

/* ── a tabela perde coluna conforme o cartão aperta ────────────
   Medido contra o texto de cada coluna: as quatro pedem 400px, três
   pedem 310, duas pedem 256 e uma pede 180. Abaixo de cada número,
   sai a coluna menos decisiva que restou.

   A ordem de saída é receita, depois ROAS, depois gasto — e o LUCRO
   nunca sai. Receita sem custo ao lado não decide nada; ROAS se
   deduz; gasto também está no meio da rosca. Lucro é a resposta.

   Rolar de lado seria a alternativa, e é pior: num cartão de 200px a
   pessoa rolaria uma tabela dentro de um bloco dentro de uma página. */
@container rosca (max-width:405px){
  .rosca-wrap thead th:nth-child(3),
  .rosca-wrap tbody td:nth-child(3){display:none}
}
@container rosca (max-width:315px){
  .rosca-wrap thead th:nth-child(4),
  .rosca-wrap tbody td:nth-child(4){display:none}
}
@container rosca (max-width:261px){
  .rosca-wrap thead th:nth-child(2),
  .rosca-wrap tbody td:nth-child(2){display:none}
  /* A coluna de nome NÃO encolhe mais neste degrau. Ela já está no
     exato da marca: a arte do TikTok pede 56px, a bolinha de cor 9, o
     vão entre elas 9 e o respiro da célula 18 — 92 dos 96 que ela
     tem. Os 4px que sobram não compram coluna nenhuma. */
}

/* ── a tabela de criativos, pelo mesmo caminho ──────────────────
   As nove colunas pedem 669px. Num cartão de 30% da tela isso só
   cabe em monitor muito largo, então ela também solta coluna
   conforme aperta — medido: 630px sem Chk, 570 sem Cliques, 480 sem
   Receita, 404 sem Upsell.

   A ordem de saída vai do funil para o dinheiro. Checkouts e cliques
   são meio de caminho e têm a tabela de relatórios inteira para
   contar essa história; receita sozinha não decide sem o custo ao
   lado; a repartição do upsell tem bloco próprio. Gasto, ROAS e
   lucro ficam até o fim, porque respondem "esse criativo se paga?". */
.cri-bloco{container-type:inline-size;container-name:criativos}
@container criativos (max-width:668px){
  #tb-criativos thead th:nth-child(3),
  #tb-criativos tbody td:nth-child(3){display:none}
}
@container criativos (max-width:629px){
  #tb-criativos thead th:nth-child(2),
  #tb-criativos tbody td:nth-child(2){display:none}
}
@container criativos (max-width:569px){
  #tb-criativos thead th:nth-child(6),
  #tb-criativos tbody td:nth-child(6){display:none}
}
@container criativos (max-width:479px){
  #tb-criativos thead th:nth-child(7),
  #tb-criativos tbody td:nth-child(7){display:none}
}
@container criativos (max-width:403px){
  #tb-criativos thead th:nth-child(4),
  #tb-criativos tbody td:nth-child(4){display:none}
}

/* ── BARRA DE POSICIONAMENTO ─────────────────────────────────────
   Barra, e não fatia, para seis partes ordenadas: 2,9% num anel é um
   risco que não dá para ler nem comparar, e a barra ainda alinha
   nome e valor numa coluna só.

   ── PAGINAÇÃO DE MÉTRICA ─────────────────────────────────────
   Três linhas no cabeçalho, no mesmo eixo: os PONTOS em cima, dizendo
   quantas páginas há e onde se está; as SETAS ladeando o título; e a
   LEGENDA embaixo, com a métrica que está na tela.

   As setas ladeiam o título e não a legenda: seta cola no que ela
   move, e o que se move é a página inteira do bloco. Presa a um rótulo
   pequeno no meio do cartão, ela viraria enfeite de rótulo.

   Os pontos existem porque seta sozinha não diz quantas páginas há nem
   onde se está — e sem isso dar a volta no fim vira desorientação em
   vez de atalho. Vão em cima porque são o índice: dizem onde se está
   antes de o olho chegar no conteúdo.

   Cabe: medido de 1280 a 2560px de tela, o pior caso é 1920px — cartão
   de 234px, 186 de área útil para 68 de setas mais 106 de título.
   Sobram 12. Abaixo de 1900 a coluna deixa de ser 30% da tela e sobra
   folga de sobra. */
.pag-topo{display:flex;align-items:center;gap:var(--s1);width:100%}
/* O título toma o vão inteiro e centra dentro dele: é o vão que
   centra, e não uma margem calculada — assim as setas ficam presas às
   pontas e o título não anda quando a métrica muda de nome. */
.pag-topo>.bloco-t{flex:1;min-width:0;margin:0;display:block;text-align:center;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* A seta É o botão do sistema, e não um desenho próprio: mesma peça de
   vidro, mesmo halo no hover, ícone centrado pelo próprio botão. Só o
   tamanho muda, e por um motivo medido — 34px não cabem ao lado do
   título no cartão mais estreito. */
.pag-seta{flex:none;width:30px;height:30px;border-radius:10px;padding:0}
.pag-nome{display:block;text-align:center;
  font:800 11px var(--mono);letter-spacing:.08em;
  text-transform:uppercase;color:var(--cyan);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* Centra por `justify-content`, e não por `align-items:center` no
   cabeçalho. O cabeçalho estica os filhos de propósito — é o que faz o
   fio de baixo atravessar o cartão inteiro —, e a linha de pontos é
   filha dele: mandar cada filho centrar na largura toda seria mexer no
   cabeçalho para resolver o problema de um filho. */
.pag-pontos{display:flex;justify-content:center;gap:4px}
.pag-ponto{width:4px;height:4px;border-radius:50%;background:var(--border)}
.pag-ponto.on{background:var(--cyan)}


/* ── GRUPO DE PLATAFORMA ──────────────────────────────────────
   Cabeçalho de grupo, e não título de bloco: ele separa duas
   repartições dentro do mesmo cartão. O fio em cima faz a separação;
   o primeiro não leva fio nem respiro, porque não há nada antes dele
   para separar. */
.bar-grupo{display:flex;align-items:center;gap:var(--s2);
  margin:var(--s4) 0 var(--s3);padding-top:var(--s3);
  border-top:1px solid var(--border)}
.bar-grupo:first-child{margin-top:0;padding-top:0;border-top:0}
.bar-grupo-n{font:800 12.5px var(--sans);color:var(--text);letter-spacing:-.01em}
/* "5 de 6": só aparece quando o teto cortou, e É o "Ver todos" do
   bloco. Discreto porque é ressalva, mas clicável porque é a saída —
   botão em linha própria custava 46px de altura, e essa altura sairia
   das barras. Aqui a ressalva e a saída são a mesma coisa, no lugar
   onde o corte é anunciado.

   Cabe na linha que já existe: 16px de caixa dentro de uma linha de
   19, que é a altura da marca da plataforma ao lado. */
.bar-grupo-c{display:inline-flex;align-items:center;gap:4px;
  padding:1px 6px;border-radius:var(--r-pill);
  font:600 10px var(--mono);color:var(--muted);letter-spacing:.03em;
  background:var(--surface);border:1px solid var(--border);
  cursor:pointer;transition:color .15s,border-color .15s}
.bar-grupo-c:hover{color:var(--cyan);border-color:rgba(0,219,233,.34)}
.bar-grupo-c svg{opacity:.75}
.bar-grupo-v{margin-left:auto;font:800 12.5px var(--mono);color:var(--text);
  font-variant-numeric:tabular-nums}

/* Com duas plataformas o bloco passa de seis barras para doze, e a
   altura dele é a do vizinho — então o que não couber rola por
   dentro. Afinar a barra caberia mais, e seria pior: a barra grossa é
   o que faz a diferença entre 9,9% e 5,8% ser visível. */
/* `flex:none` com altura declarada, e não `flex:1`. Com flex:1 a base
   zero vence a altura, e aí `fecharNaLinha` escrevia uma altura que o
   layout ignorava — a barra continuava cortada no fim. Mesma armadilha
   que o gráfico tinha. */
.rola-y{flex:none;overflow-y:auto;min-height:0}
#barras-pos{height:calc(var(--linha-1) - 132px)}

.bar-linha{display:grid;grid-template-columns:minmax(0,1fr) auto;
  align-items:baseline;gap:4px var(--s3);margin-bottom:11px}
.bar-linha:last-child{margin-bottom:0}
.bar-rot{font:600 12.5px var(--sans);color:var(--text);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.bar-pct{font:700 12.5px var(--mono);color:var(--text);font-variant-numeric:tabular-nums}
/* Barra grossa de propósito. Fina, ela lia como régua de progresso;
   grossa, ela vira a própria medida — e a diferença entre 9,9% e
   5,8% passa a ser visível sem precisar do número ao lado, que é o
   que a barra tem de melhor sobre a fatia. */
.bar-trilho{grid-column:1/-1;height:12px;border-radius:var(--r-pill);
  background:var(--surface-sunken);overflow:hidden;
  box-shadow:inset 0 1px 2px rgba(0,0,0,.35)}
.bar-trilho i{display:block;height:100%;border-radius:var(--r-pill);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.22)}

/* ══════════ MODAL DE TELA ═══════════════════════════════════════
   Para quando um bloco precisa de espaço que a tela não tem — a
   tabela de relatórios com quarenta campanhas abertas, por exemplo.

   O bloco NÃO é redesenhado dentro do modal: o cartão inteiro é
   MOVIDO para cá e devolvido ao fechar. É o mesmo nó do DOM, com os
   mesmos ouvintes, os mesmos filtros aplicados e a mesma ordenação.
   Redesenhar seria abrir um segundo caminho para a mesma tabela, e
   segundo caminho é a doença que este projeto existe para curar.

   Por isso o cartão perde a própria pele aqui dentro: o modal já é a
   superfície de vidro, e vidro dentro de vidro empilha duas bordas e
   dois fios de luz na mesma aresta. */
.modal-fundo{position:fixed;inset:0;z-index:200;display:grid;place-items:center;
  padding:clamp(10px,2.5vw,36px);background:rgba(4,6,10,.72);
  backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px)}
.modal--tela{max-width:min(1680px,100%);max-height:92vh;
  display:flex;flex-direction:column;min-height:0}
.modal--tela .modal-body{padding:0;flex:1;min-height:0;display:flex;flex-direction:column}
.modal--tela .modal-body>section{background:none;border:0;box-shadow:none;
  border-radius:0;flex:1;min-height:0;display:flex;flex-direction:column}
.modal--tela .modal-body>section::before,
.modal--tela .modal-body>section::after{display:none}
/* Dentro do modal o bloco usa a altura que tiver, em vez da que ele
   tem na tela — o motivo de existir o modal é justamente esse.

   POR `id`, e não só pela classe. Cada bloco declara a própria altura
   num seletor de `id` (`#tabela`, `#tb-criativos`, `#barras-pos`), e
   `id` vence classe: a regra do modal era ignorada e a tabela abria em
   tela cheia do mesmo tamanho de antes, com o resto do modal vazio. */
.modal--tela .table-wrap{height:auto;max-height:none;flex:1;min-height:0}
.modal--tela #tabela,
.modal--tela #tb-criativos,
.modal--tela #barras-pos{height:auto;max-height:none;flex:1;min-height:0}

/* O TÍTULO de dentro sai, e o cabeçalho FICA. São dois "Performance
   por criativo" empilhados quando o bloco entra aqui, porque o modal
   já põe o nome no topo. Mas o cabeçalho carrega os controles — modo,
   agrupar, filtrar, busca, densidade, e as setas da paginação —, e sem
   eles a tela cheia vira uma tabela que não se mexe. */
.modal--tela .modal-body>section>.bloco-cab>.bloco-t,
.modal--tela .pag-topo>.bloco-t{display:none}
/* Bloco que não é tabela também solta a altura aqui, e encosta no topo:
   centrado num container que rola, o começo dele ficaria fora de
   alcance quando a lista passa da tela. */
.modal--tela .centrado-v{justify-content:flex-start}
/* "Ver todos" some aqui dentro. O cartão é movido inteiro, e o botão
   vem junto — dentro da tela cheia ele é a porta para o cômodo em que
   já se está. Some pelo CSS, e não sendo tirado do DOM: o cartão volta
   para o lugar com o botão intacto, sem ninguém precisar recolocá-lo. */
.modal--tela .btn-todos{display:none}

/* ══════════ PASSO E FUNIL ═══════════════════════════════════════
   Um passo é rótulo em cima, número embaixo, e a fração do passo
   anterior colada no número. Só o absoluto obriga a dividir de
   cabeça — e é dividindo de cabeça que se decide errado: "3 vendas"
   parece pouco, "3 dos 5 que aceitaram" é outra conversa.

   A área é rebaixada, não elevada: o passo é leitura, não algo em
   que se clica. Elevado ele pediria clique e não teria o que
   responder.

   A grade se molda sozinha (auto-fit): seis passos numa tela larga,
   três em duas linhas no tablet, dois no celular — sem media query
   e sem número de colunas escrito à mão em lugar nenhum. */
.passo{display:flex;flex-direction:column;gap:6px;min-width:0;
  padding:11px 13px;border-radius:var(--r-md);
  background:var(--surface-sunken);border:1px solid var(--border)}
.passo-rot{font:700 9.5px/1 var(--mono);color:var(--muted);
  text-transform:uppercase;letter-spacing:.07em;white-space:nowrap;
  overflow:hidden;text-overflow:ellipsis}
.passo-val{display:flex;align-items:baseline;gap:7px;flex-wrap:wrap;
  font:800 17px/1.1 var(--mono);color:var(--text);font-variant-numeric:tabular-nums}
.passo-val em{font:700 11px var(--mono);font-style:normal;color:var(--muted)}

.ups-topo{display:grid;gap:var(--s3);
  grid-template-columns:repeat(auto-fit,minmax(126px,1fr))}
/* O resumo é mais forte que os passos de cada oferta: ele responde
   "o upsell está pagando?", que é a pergunta antes das outras. */
.ups-topo{margin-bottom:var(--s5)}
.ups-topo .passo-val{font-size:20px}

/* Nome de produto e de oferta são longos. A coluna estreita do resto
   das tabelas miúdas cortava "HEALTHREPORT-BR" em "HEAL…" e apagava o
   nome do degrau inteiro. */
#upsell thead th:first-child,
#upsell tbody td:first-child{width:clamp(200px,21vw,360px);
  max-width:clamp(200px,21vw,360px)}
/* Segunda linha da célula de nome: etiqueta e preço do degrau. Eles
   são atributo do CADASTRO e não mudam com o período — por isso não
   viram coluna, que numa tabela onde tudo responde ao filtro se leria
   como se eles também respondessem. */
.tb-sub{display:block;margin-top:2px;font:500 10.5px var(--mono);color:var(--muted);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;text-transform:uppercase;
  letter-spacing:.05em}
/* Duas linhas na célula pedem alinhamento pelo topo, senão o caret
   das linhas de cima flutua no meio do bloco de texto. */
#upsell .tb-nome{align-items:flex-start}
.rosca-cor{flex:none;width:9px;height:9px;border-radius:3px}

/* rodapé de tabela: o total mora com os dados, não numa caixa à parte */
tfoot td{padding:14px 16px;font:700 12.5px var(--mono);color:var(--text);
  border-top:1px solid var(--border);font-variant-numeric:tabular-nums}
tfoot td.num{text-align:right}

/* ══════════════════════════════════════════════════════════════════
   RESPONSIVO
   Três larguras, e cada uma muda o LAYOUT — não só encolhe:

     ≥ 1180px   computador   sidebar aberta, 236px
     760–1179   tablet       sidebar vira trilho de ícones, 68px
     < 760px    celular      sidebar vira barra inferior fixa

   O corte de 1180 não é redondo por acaso: é onde a sidebar de 236px
   mais a tabela de dez colunas param de caber sem espremer número.
   ══════════════════════════════════════════════════════════════════ */

/* ── TABLET ─────────────────────────────────────────────────────── */
@media (max-width:1179px){
  :root{--nav-larg:68px}
  .app-nav{width:var(--nav-larg)}
  /* fica só a marca: o nome não cabe em 68px */
  .nav-logo{justify-content:center;padding:var(--s4) 0;font-size:0}
  .nav-logo .mark{margin:0}
  .nav-body,.nav-foot{padding-left:8px;padding-right:8px;align-items:center}
  .nav-group{display:none}
  .nav-item{justify-content:center;padding:12px 0;gap:0}
  .nav-item>svg{flex:none}
  /* o texto some, mas continua no HTML para o leitor de tela */
  .nav-item{font-size:0}
  .nav-chev{display:none}
  .nav-sub{display:none}
  .nav-item.active{box-shadow:inset 2px 0 0 var(--cyan)}
  .nav-user-name,.nav-user-sub{display:none}
  .nav-user{justify-content:center;padding:9px 0}
  /* o contador vira ponto: número em 68px de largura não cabe */
  .nav-badge{position:absolute;top:6px;right:12px;margin:0;
    width:8px;height:8px;padding:0;font-size:0;line-height:0;overflow:hidden}
}

/* ── CELULAR ────────────────────────────────────────────────────── */
@media (max-width:759px){
  .app{display:block}
  .app-nav{position:fixed;left:0;right:0;bottom:0;top:auto;
    width:100%;height:auto;z-index:50}
  :root{--nav-larg:100%}
  .nav{flex-direction:row;border-right:0;
    border-top:1px solid var(--border);
    background:linear-gradient(180deg,rgba(255,255,255,.05),rgba(255,255,255,.02));
    backdrop-filter:blur(20px) saturate(118%);-webkit-backdrop-filter:blur(20px) saturate(118%);
    padding-bottom:env(safe-area-inset-bottom)}
  .nav-logo,.nav-foot,.nav-group,.nav-sub,.nav-chev{display:none}
  .nav-body{flex-direction:row;justify-content:space-around;
    padding:6px 4px;gap:0;flex:1}
  .nav-item{flex:1;min-width:0;justify-content:center;padding:11px 0;
    border-radius:var(--r-sm);position:relative}
  .nav-item.active{box-shadow:none;
    background:linear-gradient(180deg,rgba(0,219,233,.16),rgba(0,219,233,0))}
  .nav-badge{top:4px;right:calc(50% - 16px)}

  .t-tela,.topbar h1{font-size:24px}
  .topbar{min-height:56px;padding:var(--s2) var(--s3);flex-wrap:wrap;gap:var(--s2)}

  .topbar-fim{width:100%;margin-left:0;overflow-x:auto;flex-wrap:nowrap;
    padding-bottom:2px;-webkit-overflow-scrolling:touch}
  .topbar-fim>*{flex:none}
  .topbar-sep{display:none}
  .topbar-fim::-webkit-scrollbar{height:0}

  .conteudo{padding:var(--s3);gap:var(--s4);padding-bottom:96px}
  .kpi-row{grid-template-columns:repeat(2,1fr);gap:var(--s2)}
  .kpi{padding:var(--s3)}
  .kpi-val{font-size:20px}
  .grid2{grid-template-columns:1fr}

  /* ── TABELA VIRA CARTÃO ───────────────────────────────────────
     Dez colunas num celular só existem em duas formas: rolagem
     horizontal, onde você perde de vista a coluna do nome, ou fonte
     de 8px. As duas são inúteis para decidir. Aqui cada linha vira
     um bloco com rótulo ao lado do número. */
  .table-wrap table,
  .table-wrap tbody,
  .table-wrap tr,
  .table-wrap td{display:block;width:100%}
  .table-wrap thead{display:none}
  .table-wrap tbody tr{
    background:var(--surface);border:1px solid var(--border);
    border-radius:var(--r-lg);margin-bottom:var(--s2);padding:var(--s3)}
  /* O lucro continua pintando a linha no celular. A regra de cima tem
     a MESMA força das de cor e vem depois, então apagava as duas em
     silêncio — o sinal mais importante da tabela sumia justamente na
     tela onde há menos números à vista. */
  .table-wrap tbody tr.is-good{
    background:linear-gradient(rgba(0,224,138,.34),rgba(0,224,138,.34)),var(--surface-op)}
  .table-wrap tbody tr.is-ok{
    background:linear-gradient(rgba(0,224,138,.18),rgba(0,224,138,.18)),var(--surface-op)}
  .table-wrap tbody tr.is-warn{
    background:linear-gradient(rgba(255,192,96,.30),rgba(255,192,96,.30)),var(--surface-op)}
  .table-wrap tbody tr.is-bad{
    background:linear-gradient(rgba(255,77,61,.38),rgba(255,77,61,.38)),var(--surface-op)}
  .table-wrap tbody tr:hover td{box-shadow:none}
  .table-wrap tbody td{
    display:flex;align-items:center;justify-content:space-between;gap:var(--s4);
    padding:7px 0;border:0;text-align:right;border-radius:0}
  .table-wrap tbody td::before{
    content:attr(data-rot);flex:none;text-align:left;
    font:700 10px/1 var(--mono);text-transform:uppercase;letter-spacing:.08em;
    color:var(--muted)}
  /* a primeira célula é o título do cartão, não um par rótulo/valor */
  .table-wrap tbody td:first-child{
    justify-content:flex-start;text-align:left;font-weight:700;
    padding:0 0 10px;margin-bottom:6px;border-bottom:1px solid var(--border)}
  .table-wrap tbody td:first-child::before{display:none}
  .table-wrap tfoot{display:block}
  .table-wrap tfoot tr{display:block;border-top:1px solid var(--border);padding-top:var(--s3)}
  .table-wrap tfoot td{display:flex;justify-content:space-between;padding:6px 0;border:0}
  .table-wrap tfoot td::before{content:attr(data-rot);
    font:700 10px/1 var(--mono);text-transform:uppercase;letter-spacing:.08em;color:var(--muted)}
  .table-wrap tfoot td:first-child::before{display:none}

  .cal-corpo{flex-direction:column}
  .cal-atalhos{flex-direction:row;flex-wrap:wrap;border-right:0;
    border-bottom:1px solid var(--border);min-width:0}
  .modal{max-width:100%}
  .bloco-t{font-size:12.5px}
}

/* ── celular estreito ───────────────────────────────────────────── */
@media (max-width:400px){
  .kpi-row{grid-template-columns:1fr}
}

/* ══════════ FUNDO ══════════════════════════════════
   Imagem única, presa à janela. Substituiu o campo de estrelas e os
   brilhos em degradê, e o motivo é técnico: degradê grande atrás de
   vidro sempre estoura. O backdrop-filter espalha o que está claro e
   reamostra uma superfície que já andava em degraus de cor. Foto não
   tem esse problema — ela já vem com variação em cada pixel, que é
   exatamente o que faltava.

   Injetado por cortex.js em toda tela, para não existirem cópias
   desta marcação espalhadas pelos arquivos.

   O véu escuro por cima não é enfeite: a imagem é clara e cheia de
   detalhe, e sem ele nem o texto se lê nem o vidro dos cards
   aparece. Fica em --fundo-veu, um número só para calibrar.
   ════════════════════════════════════════════════════════════════ */
.ceu{position:fixed;inset:0;z-index:-1;pointer-events:none;
  background:var(--bg) url('../img/fundo.webp') center/cover no-repeat}
.ceu::after{content:'';position:absolute;inset:0;
  background:rgba(5,7,13,var(--fundo-veu))}

/* Celular carrega a versão de 1280px: 105 KB no lugar de 297 KB, e
   na tela dele a diferença não aparece. */
@media (max-width:759px){
  .ceu{background-image:url('../img/fundo-p.webp')}
}


/* ══════════ TABELA DE RELATÓRIOS ════════════════════════════════
   Dezoito colunas não cabem em tela nenhuma, então três coisas
   resolvem juntas: o total mora no cabeçalho da coluna, a primeira
   coluna fica presa na esquerda ao rolar, e existe um seletor de
   densidade que esconde o que não é essencial. */
/* Cabeçalho de bloco: o título em cima, os controles embaixo — e um
   fio separando do conteúdo. Todo bloco da tela usa este mesmo
   cabeçalho, senão dois cartões lado a lado começam em alturas
   diferentes e a tela perde o alinhamento.

   Em duas linhas de propósito: com tudo na mesma fileira o título
   vira mais um botão no meio dela, e a leitura começa pelo lugar
   errado. */
.bloco-cab{display:flex;flex-direction:column;align-items:stretch;gap:var(--s2);
  margin-bottom:var(--s3);padding-bottom:var(--s2);
  border-bottom:1px solid var(--border)}
.bloco-cab>.bloco-t{margin:0}
.tb-ctrl{display:flex;align-items:center;gap:var(--s3);flex-wrap:wrap}
.tb-ctrl>.tb-dir{margin-left:auto;display:flex;align-items:center;gap:var(--s2);flex-wrap:wrap}
.tb-nome{display:flex;align-items:center;gap:9px;min-width:0}
.tb-txt{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.tb-caret{width:19px;height:19px;flex:none;display:grid;place-items:center;border:0;
  background:none;color:var(--muted);cursor:pointer;border-radius:var(--r-sm);
  transition:transform .18s,color .15s,background .15s}
.tb-caret:hover{color:var(--text);background:rgba(255,255,255,.09)}
.tb-caret.aberto{transform:rotate(90deg);color:var(--cyan)}
.tb-caret.folha{visibility:hidden;cursor:default}

/* ── TABELA MIÚDA ────────────────────────────────────────────────
   A mesma tabela, em bloco de apoio: linha fina, tipo menor, total
   do cabeçalho sem peso. A tabela cheia dentro de um cartão de
   apoio compete com a tabela principal da tela, e duas tabelas
   disputando atenção é o mesmo que nenhuma.

   O total continua lá, só que discreto — é ele que garante que o
   cabeçalho bate com a soma das linhas, e essa garantia não se
   abre mão por estética.

   A linha NÃO é tingida de verde e vermelho aqui. Numa tela onde a
   tabela principal usa tinta de linha para dizer lucro, repetir a
   tinta num bloco de apoio faz as duas gritarem no mesmo tom. Aqui
   só o número do lucro tem cor. */
.table-wrap--miuda thead th{padding:9px 9px;font-size:11px}
.table-wrap--miuda thead th .tb-tot{margin-top:4px;font:700 12px var(--mono)}
.table-wrap--miuda tbody td{padding:7px 9px;font-size:12px}
.table-wrap--miuda tbody td.num{font-size:12px}
/* ── TODA LINHA COM A MESMA ALTURA ─────────────────────────────
   A faixa de plataforma usa 11px de respiro em cima e o texto um ponto
   maior, então ficava 4px mais alta que a linha de dado. Com dois
   passos diferentes, a caixa da tabela nunca cai exata num múltiplo:
   quem fecha na linha inteira sobra ora 3px, ora 30, conforme quantas
   faixas o recorte trouxe — e essa sobra vira vão no pé do cartão.

   Aqui os respiros compensam a diferença de texto: 7 em cima e 5
   embaixo mais o fio de 1px dão a mesma caixa da linha de dado. Um
   passo só, e a sobra deixa de depender do filtro. */
.table-wrap--miuda tbody tr.tb-plat td{padding:7px 9px 5px}
.table-wrap--miuda thead th:first-child,
.table-wrap--miuda tbody td:first-child{
  width:clamp(110px,8vw,150px);max-width:clamp(110px,8vw,150px)}

/* O total no cabeçalho, e não no rodapé: com rolagem vertical o
   rodapé sai da tela justamente quando você está lendo as linhas. */
thead th .tb-tot{display:block;margin-top:4px;text-transform:none;letter-spacing:0;
  font:800 14.5px var(--mono);color:var(--text);font-variant-numeric:tabular-nums}
thead th.num .tb-tot{text-align:right}
/* A contagem da primeira coluna não é total de métrica — é quantas
   linhas a tabela está mostrando. Menor e em cor fraca, para não
   disputar com os números que se comparam de verdade. */
thead th .tb-cont{font:700 12px var(--mono);color:var(--muted)}

/* Primeira coluna presa: sem isso você rola dezoito colunas e perde
   de vista de quem é o número que está lendo. */
/* Presa na esquerda, com largura própria — senão num table de
   width:100% o nome come metade da tela. */
/* ── QUEM FICA POR CIMA DE QUEM ──────────────────────────────────
   Duas coisas grudam ao mesmo tempo: o cabeçalho no topo e a primeira
   coluna na esquerda. Com o mesmo z-index, as linhas do corpo passam
   POR CIMA do cabeçalho ao rolar — foi o que aconteceu: "Hora"
   aparecia cortado atrás da primeira linha.

   A ordem é: canto do cabeçalho (4) > resto do cabeçalho (3) >
   primeira coluna do corpo (2) > demais células. O canto precisa ser
   o maior porque ele gruda nos DOIS sentidos e cruza com os outros
   dois grudados. */
thead th:first-child,tbody td:first-child{position:sticky;left:0;
  width:clamp(210px,19vw,330px);max-width:clamp(210px,19vw,330px)}
/* A ORDEM destas três linhas importa tanto quanto os números: a regra
   combinada acima vale para cabeçalho e corpo, e se ela vier depois
   devolve o canto para o mesmo nível do corpo. Foi o que aconteceu na
   primeira tentativa — o canto continuou sendo engolido. */
tbody td:first-child{z-index:2}
thead th{z-index:3}
thead th:first-child{z-index:4}
/* No CORPO a célula presa herda o fundo da própria linha, para nunca
   ficar de uma cor enquanto a linha fica de outra. No cabeçalho isso
   não serve: o `tr` do cabeçalho não tem fundo, e herdar dele deixava
   a célula transparente — era por isso que a faixa começava depois
   de "Campanha". */
tbody td:first-child{background:inherit}

tbody tr.filho td{font-size:12.5px}

/* ── faixa de plataforma ────────────────────────────────────
   Divide a tabela por plataforma e carrega o subtotal dela. Substituiu
   a etiqueta que ficava repetida em cada linha: dizer "Meta" quarenta
   vezes gasta espaço para informar o que a divisão já informa.

   NÃO leva cor de resultado, mesmo tendo lucro ou prejuízo: verde e
   vermelho aqui competiriam com as linhas de dado, que são o que
   precisa ser comparado. A faixa é rótulo, não é concorrente.
   E não tem plataforma colorida de propósito: o nome basta, e pintar
   cada uma inventaria significado para cor num sistema onde cor já
   quer dizer lucro, prejuízo e ação. */
tbody tr.tb-plat{background:none}
tbody tr.tb-plat:hover td{box-shadow:none}
/* Compacta de propósito. O respiro de cima separa a faixa do bloco
   anterior; o de baixo não precisa fazer nada, porque o fio já
   separa. Nome e contagem passaram a dividir a mesma linha —
   empilhados eles somavam duas alturas de texto num rótulo que é só
   uma etiqueta. */
tbody tr.tb-plat td{padding:11px 15px 5px;
  font:800 12px var(--mono);font-variant-numeric:tabular-nums;
  color:var(--text);border-bottom:1px solid var(--border)}
tbody tr.tb-plat td:first-child{background:none;box-shadow:none}
/* ── MARCA DA PLATAFORMA ───────────────────────────────
   A marca com o nome, onde há largura. Substitui o texto, então
   carrega o nome no alt — e por ser branca, acompanha a cor do texto
   em vez de disputar com ele.

   CADA MARCA TEM A SUA ALTURA, e o que se iguala é a ALTURA DA LETRA.
   Medido no próprio desenho, varrendo o arquivo por faixas: na arte da
   Meta a palavra ocupa 96% da altura; na do TikTok, 52% — a nota sobe
   bem acima das letras e a sombra desce abaixo delas.

   Então nem altura nem largura de arquivo servem de medida:
     mesma ALTURA de arquivo → a palavra Meta sai 82% maior;
     mesma LARGURA de arquivo → a palavra TikTok sai 31% menor.
   Os dois erros já foram cometidos aqui, um depois do outro. Quem
   iguala o que a pessoa lê é a letra: 10,1px nas duas.

   A margem negativa devolve à linha a altura que a nota do TikTok
   toma a mais. Sem ela a faixa inteira cresceria por causa de um
   rabo de nota, e a nota tem onde sobrar — o respiro de cima da
   faixa é maior que ela. */
.logo-nome{width:auto;display:inline-block;object-fit:contain}
.logo-nome[src*="meta"]{height:10.5px;vertical-align:0}
.logo-nome[src*="tiktok"]{height:19px;vertical-align:-3.5px;margin-top:-4px}
/* AS MARCAS DE CHECKOUT vêm das alturas de `.int-marca`, reduzidas pelo
   mesmo fator: 10,5 ÷ 15,6 = 0,673 na Meta, e 19 ÷ 28,6 = 0,664 no
   TikTok. As duas medidas de Integrações já foram feitas letra a letra,
   e encolher tudo pelo mesmo fator preserva a igualdade que elas
   estabeleceram — remedir cada arte de novo aqui só teria como resultado
   chegar no mesmo número por um caminho mais longo.

   Estas três são wordmark puro: a tinta ocupa de 93% a 100% do arquivo,
   com a sobra repartida em cima e embaixo (Hotmart 49/48 de 1398,
   CartPanda 8/8 de 416, Kiwify zero). Por isso alinham pelo meio, e não
   por um deslocamento medido como o rabo da nota do TikTok exige. */
.logo-nome[src*="kiwify"]{height:10.1px;vertical-align:middle}
.logo-nome[src*="cartpanda"]{height:12.6px;vertical-align:middle}
.logo-nome[src*="hotmart"]{height:17.5px;vertical-align:middle}

/* Quando o nome digitado NÃO é a marca — "Meta — conta do México" — a
   arte acompanha em vez de substituir, e o nome vem depois dela. */
.tb-marca-nome{margin-left:8px}

/* Em linha, e não `display:flex` na célula: flex num `td` tira a
   célula do layout de tabela, e a primeira coluna é presa — ela
   perderia o alinhamento com as de baixo. */
.tb-plat-nome{display:inline;font:800 12.5px var(--sans);letter-spacing:-.01em}
.tb-plat-n{display:inline;margin-left:8px;
  font:600 10px var(--mono);color:var(--muted);letter-spacing:.04em}

/* Recuo por nível da árvore, um passo de 24px por nível. Fica no
   sistema em vez de padding inline porque é medida de desenho do
   componente, não de layout da tela.

   A especificidade aqui precisa ser maior que a de `tr.filho`, senão
   um recuo fixo aplicado a toda linha filha vence estas regras e
   todos os níveis abaixo do primeiro empilham no mesmo lugar. Foi o
   que aconteceu, e é por isso que o seletor repete `tbody tr`. */
tbody tr td[data-nivel="1"]{padding-left:38px}
tbody tr td[data-nivel="2"]{padding-left:62px}
tbody tr td[data-nivel="3"]{padding-left:86px}
tbody tr td[data-nivel="4"]{padding-left:110px}
tbody tr td[data-nivel="5"]{padding-left:134px}

/* ══════════ GAVETA ════════════════════════════════════
   Painel que abre em FLUXO, empurrando o que está abaixo, e não
   flutuando por cima. O card tem overflow:hidden para os fios de luz
   não vazarem do canto arredondado, e um painel absoluto sairia
   cortado. Em fluxo ele também funciona no celular sem cálculo de
   posição.

   É peça REBAIXADA: quem abre uma gaveta vai preencher ou escolher
   alguma coisa dentro dela. Usada pelo construtor de agrupamento e
   pelos templates. */
.gaveta{display:none;margin-bottom:var(--s4);padding:var(--s4);
  border-radius:var(--r-md);background:var(--surface-sunken);
  border:1px solid var(--border);
  box-shadow:inset 0 2px 5px rgba(0,0,0,.28)}
.gaveta.aberto{display:block;animation:gvAbre .16s ease}
@keyframes gvAbre{from{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:none}}
.gv-bloco{margin-bottom:var(--s4)}
.gv-linha{display:flex;flex-wrap:wrap;gap:var(--s2);margin-top:var(--s3)}

/* Nível escolhido: peça elevada, porque é escolha ativa. */
.gb-chip{display:inline-flex;align-items:center;gap:8px;
  padding:7px 9px 7px 12px;border-radius:var(--r-sm);
  font:700 12px var(--sans);color:var(--cyan);
  background:linear-gradient(180deg,rgba(0,219,233,.16),rgba(0,219,233,.04));
  background-clip:padding-box;border:1px solid rgba(0,219,233,.30);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.12)}
.gb-chip button{background:none;border:0;color:inherit;cursor:pointer;
  opacity:.65;font-size:14px;line-height:1;padding:0 1px}
.gb-chip button:hover{opacity:1}

/* Campo disponível: peça rasa, porque ainda não é escolha. */
.gb-add{padding:7px 12px;border-radius:var(--r-sm);cursor:pointer;
  font:600 12px var(--sans);color:var(--muted);
  background:rgba(255,255,255,.04);border:1px solid var(--border);
  transition:color .15s,background .15s,border-color .15s}
.gb-add:hover{color:var(--text);background:rgba(255,255,255,.08);
  border-color:rgba(255,255,255,.18)}
.gb-add:disabled{opacity:.35;cursor:not-allowed}
/* O ponto âmbar na dimensão que não é dado real neste recorte. Marca no
   momento da ESCOLHA, e não só na tabela depois: aviso que chega depois
   da escolha já chegou tarde, porque a leitura errada aconteceu no
   caminho. Ponto, e não pastilha — âmbar aqui adverte, e pastilha
   competiria com a cor de resultado do resto do produto. */
.gb-falso{display:inline-block;margin-left:6px;width:5px;height:5px;
  border-radius:50%;background:var(--warning);vertical-align:middle;
  font-size:0;line-height:0}

.gv-pe{display:flex;align-items:center;justify-content:space-between;
  gap:var(--s3);flex-wrap:wrap;padding-top:var(--s3);
  border-top:1px solid var(--border)}

/* ══════════ FILTRO ════════════════════════════════════
   Um campo por dimensão, em grade que se reorganiza sozinha: duas ou
   três colunas em tela larga, uma no celular — quem decide é a grade,
   e não um número fixo de colunas.

   A lista de valores tem altura máxima e rola. "Dia" num período de
   noventa dias são noventa valores, e sem teto a gaveta empurraria a
   tabela para fora da tela. */
.ft-grade{display:grid;grid-template-columns:repeat(auto-fit,minmax(250px,1fr));
  gap:var(--s4) var(--s5)}
.ft-campo{min-width:0}
.ft-campo .input{margin-top:8px}
/* Campo de lista usa o SELETOR do sistema, em modo de múltipla
   escolha — e não uma nuvem de botões solta. Dezessete campos com os
   valores todos à mostra viram uma parede; fechado, cada campo ocupa
   uma linha e o rótulo resume o que está escolhido. */
.ft-campo .sel{margin-top:8px}

/* ══════════ CHECKOUTS ═════════════════════════════════
   Lista de evento, e não de agregado: cada linha é um carrinho aberto.
   Usa a mesma tabela do relatório — mesmo cabeçalho de vidro, mesma
   linha opaca, mesmas faixas de plataforma. O que muda é o conteúdo. */
.chk-pais{display:inline-flex;align-items:center;gap:7px}
.chk-sigla{font:700 10px/1 var(--mono);letter-spacing:.08em;color:var(--muted);
  padding:3px 5px;border-radius:4px;background:rgba(255,255,255,.07)}
.chk-ip{font:500 11.5px var(--mono);color:var(--muted)}
.chk-sim{font:800 11.5px var(--mono);color:var(--positive)}
.chk-nao{color:var(--muted)}
/* A hora é a coluna que se lê primeiro numa lista ordenada por tempo. */
.chk-hora{font:700 12.5px var(--mono);color:var(--cyan);font-variant-numeric:tabular-nums}

/* ══════════ TEMPLATES ═════════════════════════════════
   Lista de visões salvas. Cada item mostra o nome e, embaixo, o que
   ele guarda — sem isso o dono precisa carregar para descobrir o que
   é, e um template que você não sabe o que faz não é atalho. */
.tpl-lista{display:flex;flex-direction:column;gap:var(--s2);margin-top:var(--s3)}
.tpl-item{display:flex;align-items:center;gap:var(--s3);
  padding:10px 12px;border-radius:var(--r-sm);
  background:rgba(255,255,255,.04);border:1px solid var(--border)}
.tpl-item:hover{background:rgba(255,255,255,.07);border-color:rgba(255,255,255,.18)}
.tpl-txt{flex:1;min-width:0}
.tpl-nome{display:block;font:700 12.5px var(--sans);color:var(--text);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.tpl-resumo{display:block;margin-top:3px;font:500 10.5px var(--mono);color:var(--muted);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.tpl-acoes{display:flex;align-items:center;gap:6px;flex:none}
.tpl-vazio{padding:16px 12px;text-align:center;
  font:500 12px var(--sans);color:var(--muted)}
.tpl-salvar{display:flex;gap:var(--s2);align-items:flex-end;flex-wrap:wrap}
.tpl-salvar .field{flex:1 1 200px;min-width:0}

#gb-abrir strong{font-weight:800}
/* O recuo NÃO mora aqui: quem recua é a regra por nível, logo acima.
   Um valor fixo nesta regra vence as de nível e achata a árvore. */
tbody tr.filho td:first-child{color:var(--muted)}
tbody tr.filho td:first-child .tb-txt{color:var(--text)}

@media (max-width:759px){
  /* No modo cartão nada é sticky: cada linha já é um bloco. */
  thead th:first-child,tbody td:first-child{position:static}
  /* No modo cartão o recuo por nível não serve: cada linha já é um
     bloco, e o aninhamento aparece como margem do bloco inteiro. */
  .table-wrap tbody tr td[data-nivel]{padding-left:0}
  .table-wrap tbody tr.filho{margin-left:var(--s4)}
}

/* Contagem de degraus ao lado do nome do produto no funil de upsell.
   Mora na célula do nome porque é sobre a linha, e não uma métrica —
   como métrica ela pediria coluna própria e uma coluna inteira para
   dizer "2" seria desperdício de largura. */
.ups-n-degraus{flex:none;font:700 10px var(--mono);color:var(--muted)}

/* Na lista de checkouts, o que o evento rendeu de frente quando houve
   upsell. Segunda linha porque a resposta principal é o total — a
   repartição é conferência, e conferência não disputa o olhar com o
   número que se procura. */
.chk-up{display:block;margin-top:2px;font:500 10px var(--mono);color:var(--muted)}

/* ══════════ INTEGRAÇÕES ═══════════════════════════════════════════
   Grade de cartões, um por provedor — a mesma peça de vidro do resto
   do painel, com o mesmo respiro e os mesmos fios de luz. Não é
   catálogo para navegar: o dono já sabe o que usa, e a tela existe
   para ele colar a credencial e sair.

   `auto-fit` com piso de 300px, e não um número fixo de colunas: o
   cartão precisa caber um campo de colar sem quebrar a linha, e 300 é
   o que dá isso. Numa tela larga dão cinco ou seis; num note, três.
   Coluna fixa faria o campo espremer em vez de a grade recolher. */
.int-grade{display:grid;gap:clamp(14px,1.4vw,24px);
  grid-template-columns:repeat(auto-fit,minmax(300px,1fr))}

/* O cartão é `.glass.pad` — com hover, porque aqui se clica. */
.int-card{display:flex;flex-direction:column;gap:var(--s4);min-width:0}

/* ── A MARCA, NA PRÓPRIA LINHA ────────────────────────────────────
   Sozinha em cima, como assinatura do cartão. Altura reservada para
   a mais alta, para as marcas se alinharem entre cartões vizinhos
   mesmo tendo tamanhos diferentes. */
.int-topo{display:flex;align-items:center;justify-content:space-between;
  gap:var(--s3);min-height:26px}
.int-marca{width:auto;display:block;object-fit:contain;flex:none}
.int-marca-par{display:flex;align-items:center;gap:9px;min-width:0}
/* ── MEDIDA PELA ALTURA DA LETRA ──────────────────────────────────
   Mesma regra da faixa de plataforma do Overview, e pelo mesmo motivo:
   as artes não têm a mesma proporção, e igualar a altura do ARQUIVO
   faz uma marca parecer o dobro da outra. Medido varrendo cada desenho
   por faixas — quanto da altura do arquivo é letra:

     kiwify 100%   meta 96%   cartpanda 80%   hotmart 57%   tiktok 52%

   As alturas saem dessa conta, todas para letra de 15px. */
.int-marca[src*="kiwify"]{height:15px}
.int-marca[src*="meta"]{height:15.6px}
.int-marca[src*="cartpanda"]{height:18.7px}
.int-marca[src*="hotmart"]{height:26px}
.int-marca[src*="tiktok"]{height:28.6px}
/* O Resend não é logotipo, é símbolo quadrado: fica na altura de um
   ícone, e o nome vai escrito ao lado como em qualquer um sem marca. */
.int-marca[src*="resend"]{height:24px}
/* Sem arte, o nome escrito resolve. Desenho inventado para tapar
   buraco vira dívida que ninguém lembra de pagar. */
.int-nome{font:800 15px var(--sans);letter-spacing:-.01em;color:#fff}

.int-para{font:400 12.5px/1.45 var(--sans);color:var(--muted);
  display:block;min-height:2.9em}

/* Estado é ponto e palavra, e não pastilha: pastilha pede cor de
   fundo, e cor de fundo neste sistema já quer dizer lucro e prejuízo. */
.int-estado{display:inline-flex;align-items:center;gap:6px;flex:none;
  font:700 10px var(--mono);text-transform:uppercase;letter-spacing:.08em;
  color:var(--muted)}
.int-estado::before{content:'';width:6px;height:6px;border-radius:50%;
  background:var(--warning)}
.int-estado.pos{color:var(--positive)}
.int-estado.pos::before{background:var(--positive)}
/* Vermelho para o que ja falhou; ponto apagado para o que so ainda nao
   aconteceu. Sem os dois, todo estado que nao e "pronto" vira ambar —
   e ai "aguardando" e "vencido" ficam com a mesma cara. */
.int-estado.neg::before{background:var(--negative)}
.int-estado--n::before{background:var(--muted);opacity:.6}

/* O pé do cartão: apelido à esquerda, ação à direita. Empurrado para
   baixo por `margin-top:auto` — os cartões têm alturas de cabeçalho
   diferentes, e sem isso os botões ficariam desalinhados na fileira. */
.int-pe{margin-top:auto;display:flex;align-items:center;
  justify-content:space-between;gap:var(--s3)}
.int-apelido{font:600 12px var(--sans);color:var(--muted);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}

/* Dentro do modal os campos empilham com respiro entre eles. */
.int-modal-corpo{display:flex;flex-direction:column;gap:var(--s4)}
.int-campo{display:flex;flex-direction:column;gap:6px;min-width:0}

/* ── O SEGREDO SALVO NÃO VOLTA PARA UM CAMPO ─────────────────────
   Depois de salvo, o lugar do valor deixa de ser `<input>` e vira
   texto morto com os quatro primeiros caracteres. Um input com o
   segredo dentro vaza pelo HTML, pelo preenchimento automático do
   navegador e por qualquer extensão instalada — e "trocar" LIMPA o
   campo em vez de revelar o que está lá. */
.int-posto{display:flex;align-items:center;gap:var(--s2);
  min-height:41px;padding:0 5px 0 13px;border-radius:var(--r-md);
  background:var(--surface-sunken);border:1px solid var(--border);
  box-shadow:inset 0 2px 4px rgba(0,0,0,.28)}
.int-posto code{flex:1;min-width:0;background:none;padding:0;
  color:var(--muted);font:500 13px var(--mono);letter-spacing:.10em}

/* Falta credencial: fio âmbar na aresta de cima, e não fundo tingido.
   Tingir o cartão inteiro competiria com o verde e o vermelho da
   tabela, que neste sistema já querem dizer lucro e prejuízo. */
.int-card--falta{box-shadow:inset 0 2px 0 var(--warning),var(--sh-card),
  inset 0 -1px 0 rgba(255,255,255,.03)}

/* ══════════ WHATSAPP ═══════════════════════════════════════════════
   Duas colunas, como o WhatsApp Web: conversas à esquerda, a aberta à
   direita. A gramática é a que todo atendente já tem no dedo — copiar
   ela é o que faz a tela não precisar ser aprendida.

   O QUE NÃO SE COPIA É A PELE. O WhatsApp Web é balão verde-claro
   sobre bege; aqui é o vidro escuro do Cortex. Trazer a cor deles para
   dentro deste painel criaria uma ilha com dois design systems — que é
   exatamente a doença do sistema antigo.

   A tela ocupa a altura da janela menos a barra de topo: caixa de
   entrada é lugar onde se fica, e não bloco que se rola junto com o
   resto da página. */
.wa-tela{display:grid;grid-template-columns:clamp(300px,26vw,380px) minmax(0,1fr);
  height:calc(100vh - 64px - 2 * clamp(16px,2vw,28px));min-height:520px;overflow:hidden}

/* ── A LISTA ─────────────────────────────────────────────────────── */
.wa-lado{display:flex;flex-direction:column;min-height:0;
  border-right:1px solid var(--border);background:rgba(0,0,0,.16)}
.wa-lado-topo{display:flex;flex-direction:column;gap:var(--s3);
  padding:var(--s4);border-bottom:1px solid var(--border)}
.wa-lista{flex:1;min-height:0;overflow-y:auto}
.wa-vazio{padding:var(--s5);font:400 12.5px var(--sans);color:var(--muted)}

/* A linha inteira é o alvo do clique, e não só o nome: alvo pequeno
   numa lista que se percorre o dia todo cansa a mão. */
.wa-item{position:relative;border-bottom:1px solid var(--border);transition:background .14s}
.wa-item:hover,.wa-item.com-menu{background:rgba(255,255,255,.04)}
/* O botao que abre ocupa a linha inteira: alvo pequeno numa lista que se
   percorre o dia todo cansa a mao. Ele deixa a direita livre para a seta
   das acoes, que so aparece no hover. */
.wa-item-abrir{display:flex;gap:var(--s3);width:100%;text-align:left;cursor:pointer;
  padding:11px 30px 11px var(--s4);background:none;border:0;color:inherit;font:inherit}

/* ── AS ACOES DA LINHA ────────────────────────────────────────────
   Marcar como nao lida, fixar e arquivar aparecem so com o mouse em
   cima. Quatro botoes visiveis por linha virariam ruido numa lista que
   se percorre o dia todo — e o que se faz nela quase sempre e abrir. */
.wa-mais{position:absolute;top:9px;right:6px;display:grid;place-items:center;
  width:22px;height:22px;padding:0;border:0;border-radius:var(--r-sm);cursor:pointer;
  color:var(--muted);background:none;opacity:0;transition:opacity .14s,color .14s}
.wa-item:hover .wa-mais,.wa-item.com-menu .wa-mais,.wa-mais:focus-visible{opacity:1}
.wa-mais:hover{color:var(--text);background:rgba(255,255,255,.08)}

/* O menu sai do fluxo para nao empurrar as linhas de baixo enquanto
   esta aberto — lista que muda de altura ao passar o mouse e um alvo
   que foge do cursor. */
.wa-menu{position:absolute;top:28px;right:8px;z-index:3;min-width:186px;
  display:flex;flex-direction:column;padding:5px;border-radius:var(--r-md);
  background:var(--surface-float);border:1px solid var(--border);box-shadow:var(--sh-drop)}
/* Sem espaco embaixo, abre para cima. Quem decide e a regua, no JS. */
.wa-menu--acima{top:auto;bottom:28px}
.wa-acao{padding:8px 10px;border:0;border-radius:var(--r-sm);cursor:pointer;
  text-align:left;white-space:nowrap;font:500 12.5px var(--sans);color:var(--text);
  background:none;transition:background .12s}
.wa-acao:hover:not(:disabled){background:rgba(255,255,255,.07)}
/* Acao que nao cabe nesta conversa fica apagada e explica no title, em
   vez de sumir: item que aparece e some conforme a linha faz o menu
   mudar de tamanho e de ordem a cada hover. */
.wa-acao:disabled{color:var(--muted);opacity:.45;cursor:not-allowed}
/* A conversa aberta leva barra ciano na esquerda, a mesma marca de
   "você está aqui" do item de menu. */
.wa-item.on{background:rgba(0,219,233,.07);box-shadow:inset 2px 0 0 var(--cyan)}
.wa-item.on:hover{background:rgba(0,219,233,.10)}

.wa-av{flex:none;display:grid;place-items:center;width:42px;height:42px;
  border-radius:50%;font:800 13px var(--mono);color:var(--cyan);
  background:rgba(0,219,233,.10);border:1px solid rgba(0,219,233,.22)}
.wa-av--g{width:38px;height:38px;font-size:12px}

.wa-item-txt{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}
.wa-item-topo,.wa-item-baixo{display:flex;align-items:baseline;gap:var(--s2)}
.wa-item-nome{flex:1;min-width:0;font:700 13.5px var(--sans);color:#fff;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.wa-fixada{font-size:10px;margin-right:4px}
.wa-item-hora{flex:none;font:600 10.5px var(--mono);color:var(--muted)}
/* Hora em ciano quando há não lida: o olho pega a coluna da direita
   inteira de uma vez, em vez de procurar bolinha por linha. */
.wa-item-hora--n{color:var(--cyan)}
.wa-item-prev{flex:1;min-width:0;font:400 12px var(--sans);color:var(--muted);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.wa-nao-lidas{flex:none;min-width:19px;height:19px;padding:0 6px;border-radius:var(--r-pill);
  display:grid;place-items:center;font:800 10.5px var(--mono);
  color:#04231c;background:var(--positive)}
.wa-etiqueta{font:700 9.5px var(--mono);text-transform:uppercase;letter-spacing:.07em;
  color:var(--muted);opacity:.75}

/* ── A CONVERSA ──────────────────────────────────────────────────── */
.wa-painel{display:flex;flex-direction:column;min-height:0;min-width:0}
.wa-nenhuma{margin:auto;text-align:center;padding:var(--s6)}
.wa-conversa{display:flex;flex-direction:column;min-height:0;height:100%}
.wa-quem{display:flex;align-items:center;gap:var(--s3);flex:none;
  padding:var(--s3) var(--s4);border-bottom:1px solid var(--border);
  background:rgba(0,0,0,.14)}
.wa-quem-txt{display:flex;flex-direction:column;gap:1px;min-width:0}
.wa-quem-txt b{font:700 14px var(--sans);color:#fff}
.wa-quem-txt span{font:500 11.5px var(--mono);color:var(--muted)}

.wa-fluxo{flex:1;min-height:0;overflow-y:auto;padding:var(--s4) var(--s5);
  display:flex;flex-direction:column;gap:5px}

/* Separador de dia e aviso de sistema usam a mesma peça: os dois são
   fala do sistema no meio da fala das pessoas. */
.wa-dia{align-self:center;margin:var(--s3) 0}
.wa-dia span{display:inline-block;padding:4px 11px;border-radius:var(--r-pill);
  font:600 10.5px var(--mono);text-transform:uppercase;letter-spacing:.06em;
  color:var(--muted);background:var(--surface-sunken);border:1px solid var(--border)}

.wa-linha{display:flex;max-width:100%}
.wa-linha--eu{justify-content:flex-end}

/* O BALÃO É A PEÇA DE VIDRO DO SISTEMA, em tamanho de fala. O meu leva
   um toque de ciano — a cor da marca, que aqui quer dizer "fui eu" — e
   canto quadrado do lado de quem falou, que é a convenção que todo
   mundo já lê sem pensar. */
.wa-balao{position:relative;max-width:min(560px,74%);display:flex;flex-direction:column;gap:4px;
  padding:8px 12px 6px;border-radius:var(--r-md);
  background:var(--surface);border:1px solid var(--border);border-bottom-left-radius:4px}
.wa-balao--eu{background:linear-gradient(rgba(0,219,233,.10),rgba(0,219,233,.10)),var(--surface);
  border-color:rgba(0,219,233,.22);border-bottom-left-radius:var(--r-md);border-bottom-right-radius:4px}
/* Falha não é balão vermelho: a mensagem continua sendo a mensagem, e
   o que falhou foi o envio. Fio na aresta, como no cartão de
   integração sem credencial. */
.wa-balao--falhou{border-color:rgba(255,77,61,.42);box-shadow:inset 2px 0 0 var(--negative)}

/* ── REAGIR ──────────────────────────────────────────────────────
   A REAÇÃO FICA PRESA NA MENSAGEM, montada na aresta de baixo do
   balão. Antes ela virava uma linha própria no meio da conversa: além
   de empurrar tudo para baixo, separava a reação daquilo que foi
   reagido — via-se "❤️" sem saber a quê.

   Ela sai do fluxo (`position:absolute`) porque não é conteúdo do
   balão: é uma marca colada nele. Dentro do fluxo, ela mudaria a
   largura do balão e faria a mensagem se remontar. O balão que tem
   reação ganha uma tira de respiro embaixo para ela pousar sem cobrir
   a última linha do texto. */
.wa-balao--reagido{margin-bottom:11px}
.wa-selo{position:absolute;left:9px;bottom:-11px;display:flex;align-items:center;gap:3px;
  padding:1px 6px;border-radius:var(--r-pill);cursor:pointer;font-size:12px;line-height:1.5;
  background:var(--surface-float);border:1px solid var(--border);box-shadow:var(--sh-card)}
/* No meu balão o selo pousa do outro lado, para não colidir com a hora
   e o tique — que no meu ficam à direita. */
.wa-balao--eu .wa-selo{left:auto;right:9px}
.wa-selo:hover{border-color:rgba(255,255,255,.22)}
.wa-selo span{display:inline-flex;align-items:center;gap:2px}
.wa-selo b{font:800 9.5px var(--mono);color:var(--muted)}

/* O gatilho só aparece com o mouse em cima do balão: um botão visível
   por mensagem encheria a conversa de enfeite. Fica FORA do balão,
   ao lado, onde não disputa espaço com o texto. */
.wa-reagir{position:absolute;top:50%;transform:translateY(-50%);
  right:-30px;display:grid;place-items:center;width:24px;height:24px;padding:0;
  border:0;border-radius:50%;cursor:pointer;color:var(--muted);background:none;
  opacity:0;transition:opacity .14s,color .14s}
.wa-balao--eu .wa-reagir{right:auto;left:-30px}
.wa-balao:hover .wa-reagir,.wa-reagir:focus-visible{opacity:1}
.wa-reagir:hover{color:var(--cyan)}

/* Os seis do WhatsApp, na mesma ordem. Flutua acima do balão para não
   empurrar a conversa enquanto se escolhe. */
.wa-emojis{position:absolute;bottom:calc(100% + 6px);left:0;z-index:2;
  display:flex;gap:2px;padding:4px 6px;border-radius:var(--r-pill);
  background:var(--surface-float);border:1px solid var(--border);box-shadow:var(--sh-drop)}
.wa-balao--eu .wa-emojis{left:auto;right:0}
/* Sem espaco acima, abre para baixo. Quem decide e a regua, no JS. */
.wa-emojis--abaixo{bottom:auto;top:calc(100% + 6px)}
.wa-emoji{display:grid;place-items:center;width:30px;height:30px;padding:0;border:0;
  border-radius:50%;cursor:pointer;font-size:17px;line-height:1;background:none;
  transition:background .12s,transform .12s}
.wa-emoji:hover{background:rgba(255,255,255,.08);transform:scale(1.18)}
/* O que eu já mandei vem marcado — clicar nele de novo tira a reação. */
.wa-emoji.on{background:rgba(0,219,233,.16);box-shadow:inset 0 0 0 1px rgba(0,219,233,.34)}

/* O X empurrado para a ponta pelo `auto`, e não por largura fixa no
   bloco do nome: nome comprido continua usando o espaço que sobra. */
.wa-fechar{margin-left:auto;flex:none}

.wa-txt{font:400 13.5px/1.45 var(--sans);color:var(--text);white-space:pre-wrap;
  overflow-wrap:anywhere}
.wa-desconhecido{color:var(--muted);font-style:italic}
.wa-modelo{font:700 9.5px var(--mono);text-transform:uppercase;letter-spacing:.07em;
  color:var(--cyan);opacity:.85}
.wa-meta{align-self:flex-end;display:flex;align-items:center;gap:5px;
  font:600 10px var(--mono);color:var(--muted)}
.wa-tique{display:inline-flex;color:var(--muted)}
.wa-tique--lida{color:var(--cyan)}
.wa-tique--erro{color:var(--negative)}

/* ── AS MÍDIAS ───────────────────────────────────────────────────
   Cada tipo tem forma própria, e nenhum vira "[anexo]". Tipo que a
   tela não desenha é atendente respondendo sem saber o que recebeu. */
.wa-ic{flex:none;color:var(--cyan);opacity:.9}
.wa-midia{display:flex;align-items:center;gap:9px;min-width:0;
  padding:7px 10px;border-radius:var(--r-sm);background:var(--surface-sunken)}
.wa-midia-n{flex:1;min-width:0;font:500 12.5px var(--sans);color:var(--text);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.wa-dur{flex:none;font:600 10.5px var(--mono);color:var(--muted)}

.wa-doc{display:flex;align-items:center;gap:10px;min-width:0;
  padding:9px 11px;border-radius:var(--r-sm);background:var(--surface-sunken)}
.wa-doc-txt{display:flex;flex-direction:column;gap:1px;min-width:0}
.wa-doc-txt b{font:600 12.5px var(--sans);color:var(--text);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.wa-doc-txt span{font:500 10.5px var(--mono);color:var(--muted)}

/* Áudio: botão, onda e duração. A onda é desenho, e não análise do
   som — mas ela dá a forma da peça, que é o que o protótipo prova. */
.wa-audio{display:flex;align-items:center;gap:10px;min-width:0;
  padding:5px 10px 5px 5px;border-radius:var(--r-pill);background:var(--surface-sunken)}
.wa-play{flex:none;display:grid;place-items:center;width:30px;height:30px;border:0;
  border-radius:50%;cursor:pointer;color:var(--cyan);background:rgba(0,219,233,.14)}
.wa-play:hover{background:rgba(0,219,233,.24)}
.wa-onda{flex:1;min-width:80px;height:24px;display:flex;align-items:center;gap:2px}
.wa-onda i{flex:1;border-radius:1px;background:var(--muted);opacity:.5}
/* Já ouvido: a onda acende, como no WhatsApp. */
.wa-audio--ouvido .wa-onda i{background:var(--cyan);opacity:.55}

.wa-fig{font-size:52px;line-height:1}
/* Resposta a botão de modelo: o que o cliente escolheu, e não o que
   ele digitou. Vale mostrar diferente porque é clique, não texto. */
.wa-botao{display:inline-block;padding:5px 12px;border-radius:var(--r-pill);
  font:700 12px var(--sans);color:var(--cyan);
  background:rgba(0,219,233,.10);border:1px solid rgba(0,219,233,.26)}

/* ── ESCREVER ────────────────────────────────────────────────────── */
.wa-escrever{flex:none;display:flex;align-items:flex-end;gap:var(--s2);
  padding:var(--s3) var(--s4);border-top:1px solid var(--border);
  background:rgba(0,0,0,.14)}
/* O campo cresce com o texto até um teto, e só aí rola — igual ao
   WhatsApp Web. Altura fixa obrigaria a escrever mensagem longa numa
   fresta. */
.wa-campo{flex:1;min-width:0;resize:none;max-height:132px;line-height:1.45;
  padding:11px 13px}

/* Respostas rápidas: menu que só aparece quando se digita "/". Menu
   fixo ocuparia espaço o dia todo para servir uma vez por conversa. */
.wa-rapidas{flex:none;max-height:190px;overflow-y:auto;
  border-top:1px solid var(--border);background:var(--surface-float)}
.wa-rapida{display:flex;align-items:baseline;gap:var(--s3);width:100%;text-align:left;
  padding:9px var(--s4);background:none;border:0;cursor:pointer}
.wa-rapida:hover{background:rgba(255,255,255,.05)}
.wa-rapida code{flex:none;background:none;padding:0;color:var(--cyan);
  font:700 11.5px var(--mono)}
.wa-rapida span{flex:1;min-width:0;font:400 12.5px var(--sans);color:var(--muted);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

/* Numa tela estreita a lista e a conversa não cabem lado a lado. A
   conversa fica com o que sobra, porque é onde se trabalha. */
@media (max-width:899px){
  .wa-tela{grid-template-columns:1fr;grid-template-rows:minmax(0,240px) minmax(0,1fr)}
  .wa-lado{border-right:0;border-bottom:1px solid var(--border)}
}

/* ══════════ AVISO — caixa de recado dentro de um bloco ════════════
   O `.toast` fala de algo que ACABOU de acontecer e some sozinho. Esta
   peca fala de algo que a pessoa precisa saber ANTES de agir, e fica.

   Nasceu para o modal do cadastro: e ali que se conta a armadilha antes
   de o campo ser preenchido, e nao depois de salvar errado. */
.aviso{display:flex;gap:var(--s3);padding:12px 14px;border-radius:var(--r-md);
  font:400 12px/1.55 var(--sans);color:var(--text);
  background:var(--surface-sunken);border:1px solid var(--border)}
.aviso svg{flex:none;margin-top:1px}
.aviso b{display:block;font:700 12.5px var(--sans);margin-bottom:3px}
.aviso ul{margin:6px 0 0;padding-left:16px}
.aviso li{margin:3px 0}
/* Ciano explica, ambar adverte, vermelho impede. A mesma escala do
   resto do produto — sem inventar cor de recado. */
.aviso--info{border-color:rgba(0,219,233,.28)}
.aviso--info svg,.aviso--info b{color:var(--cyan)}
.aviso--atencao{border-color:rgba(255,192,96,.30);background:rgba(255,192,96,.07)}
.aviso--atencao svg,.aviso--atencao b{color:var(--warning)}
.aviso--erro{border-color:rgba(255,77,61,.32);background:rgba(255,77,61,.08)}
.aviso--erro svg,.aviso--erro b{color:var(--negative)}

/* ══════════ TRACKER — CADASTROS ═══════════════════════════════════
   Cadastro e INVENTARIO: lista do que existe, para conferir e comparar.
   Isso e tabela, e a tabela do sistema resolve inteira — cabecalho de
   vidro, linha com hover, coluna de numero, corte com reticencias.

   O que NAO cabe numa linha e o que precisa ser copiado para fora: o
   CNAME, o script da pagina, a URL de postback. Esses moram no modal,
   junto do formulario e do aviso que explica onde colar. */

/* O valor com o botao de copiar. Copiar existe porque digitar CNAME ou
   token na mao erra, e o erro so aparece horas depois — quando o DNS
   nao propaga e ninguem sabe por que. */
.tk-copia{display:flex;align-items:center;gap:var(--s2);min-width:0}
.tk-copia code{flex:1;min-width:0;padding:9px 11px;border-radius:var(--r-sm);
  font:500 11.5px/1.5 var(--mono);color:var(--text);
  background:rgba(0,0,0,.30);border:1px solid var(--border);
  overflow-x:auto;white-space:pre;scrollbar-width:none}
.tk-copia code::-webkit-scrollbar{display:none}

/* Endereco dentro da celula: e para conferir, e nao para ler. */
.tk-url{color:var(--cyan);text-decoration:none;opacity:.8;
  font:500 12px var(--mono)}
.tk-url:hover{opacity:1;text-decoration:underline}

/* A COLUNA DE ACOES NAO CRESCE: ela e igual em todas as linhas, entao
   qualquer largura a mais e espaco morto. Onde ela vem PRIMEIRO — como
   na lista de dominios, que tem sete colunas — ela alinha a esquerda,
   porque acao no fim de uma tabela larga exige rolar de lado para
   alcancar. */
td.tk-acao,th.tk-acao{width:1%;white-space:nowrap;text-align:right}
tr>td.tk-acao:first-child,tr>th.tk-acao:first-child{text-align:left}
/* O grupo de acoes usa o `.row` do sistema; daqui sai so o aperto,
   porque numa celula de tabela o respiro padrao empurraria a coluna. */
td.tk-acao>.row{gap:var(--s2);flex-wrap:nowrap}

/* Segunda linha dentro da celula, para o vencimento andar junto do
   estado: separados, da para ler "emitido" e nao ver que vence semana
   que vem — e certificado vencido derruba o dominio sem avisar. */
.tb-sub.warn{color:var(--warning)}

/* Barra de busca acima da tabela. Uma so, que filtra enquanto se
   digita — o RedTrack usa varios campos com botao Aplicar, que faz
   sentido em lista de milhares; aqui a lista cabe na tela e um campo
   que responde na hora e menos trabalho. */
.tk-busca{max-width:340px}

/* Cadastro de formulario longo — oferta, canal de trafego — nao cabe na
   largura de um modal de confirmacao. Campo espremido faz a pessoa
   rolar de lado para ler o proprio valor que digitou.

   A ALTURA E TETO NO MODAL INTEIRO, e nao no miolo. Limitar so o corpo
   deixava cabecalho e rodape somarem por fora, e em tela baixa o
   rodape com Salvar ficava embaixo da dobra — cortado, como estava.

   Mesma receita do `.modal--tela`: teto no todo, coluna flex, e o miolo
   com `flex:1` + `min-height:0` para poder encolher. Sem o min-height
   o conteudo impoe a altura dele e o teto nao vale de nada. */
.modal--largo{max-width:720px;max-height:88vh;
  display:flex;flex-direction:column;min-height:0}
.modal--largo .modal-body{flex:1;min-height:0;overflow-y:auto}

/* Duas colunas onde os campos sao curtos e andam juntos — id e chave,
   moeda e valor. Um por linha desperdicaria a largura que o modal
   largo acabou de ganhar. */
.tk-par2{display:grid;grid-template-columns:1fr 1fr;gap:var(--s4)}
@media (max-width:560px){ .tk-par2{grid-template-columns:1fr} }

/* Secao do formulario. Formulario de vinte campos sem divisao e uma
   parede — a divisao e o que deixa achar onde parou.

   DOIS ERROS QUE ESTAVAM AQUI, e apareciam como "elemento se
   sobrepondo" e "vao enorme":

   1. sem `gap`, os filhos empilhavam COLADOS: o aviso encostava no
      rotulo do primeiro campo.
   2. com `margin`, o respiro SOMAVA ao gap que o `.int-modal-corpo` ja
      da entre os filhos — dois respiros no mesmo lugar.

   Agora o respiro entre secoes e so o do pai, e o de dentro e so o
   `gap` daqui. Um lugar para cada coisa. */
.tk-secao{display:flex;flex-direction:column;gap:var(--s4)}
/* A linha separadora so aparece onde a secao tem titulo — divisoria
   entre dois grupos sem nome nao divide nada, so risca a tela. */
.tk-secao--div{padding-top:var(--s5);border-top:1px solid var(--border)}

/* ── PEÇAS DO FORMULÁRIO DO TRACKER ────────────────────────────────
   A PALETA DE MACROS responde "o que posso colocar aqui?" sem
   documentação. É ela que evita inventar nome que não existe e
   descobrir semanas depois que a coluna do relatório está vazia — e é,
   de quebra, o inventário do que se captura de cada clique. */
.tk-macros{display:flex;flex-direction:column;gap:var(--s3);margin-top:var(--s2);
  max-height:190px;overflow-y:auto;padding:var(--s3);border-radius:var(--r-sm);
  background:var(--surface-sunken);border:1px solid var(--border)}
.tk-macro-g{display:flex;flex-wrap:wrap;align-items:center;gap:5px}
.tk-macro-g>.t-label{width:100%;margin-bottom:2px}
.tk-macro{padding:3px 8px;border-radius:var(--r-pill);cursor:pointer;
  font:600 10.5px var(--mono);color:var(--muted);
  background:rgba(255,255,255,.04);border:1px solid var(--border);
  transition:color .12s,border-color .12s,background .12s}
.tk-macro:hover{color:var(--cyan);border-color:rgba(0,219,233,.34);
  background:rgba(0,219,233,.09)}

/* Chave com rótulo ao lado, para o que liga e desliga. */
.tk-chave{display:flex;align-items:center;gap:var(--s3);cursor:pointer}
.tk-chave>span:last-child{font:500 12.5px var(--sans);color:var(--text)}

/* Valor que não se edita — tipo de registro DNS, por exemplo. Fica com
   cara de campo para não parecer que sumiu, mas sem caixa de digitação:
   campo editável que não aceita edição é convite a tentar. */
.tk-fixo{display:block;padding:11px 13px;border-radius:var(--r-md);
  font:600 12px var(--mono);color:var(--text);
  background:rgba(0,0,0,.22);border:1px dashed var(--border)}
/* O valor que ainda vai existir. Descreve de onde ele sai em vez de
   ficar vazio — caixa vazia parece campo esperando digitação, e este
   não aceita. Em texto normal, porque é frase e não valor. */
.tk-fixo--vazio{font:400 12px var(--sans);color:var(--muted)}

/* Os pixels que a oferta dispara: chave por linha, com o que identifica
   cada um embaixo do nome. Lista de caixas sem o ID obrigaria a abrir
   outra tela para saber qual é qual. */
.tk-pixels{display:flex;flex-direction:column;gap:var(--s2)}
.tk-pixel{display:flex;align-items:center;gap:var(--s3);cursor:pointer;
  padding:10px 12px;border-radius:var(--r-sm);
  background:var(--surface-sunken);border:1px solid var(--border)}
.tk-pixel>span:last-child{display:flex;flex-direction:column;gap:1px;min-width:0}
.tk-pixel b{font:700 12.5px var(--sans);color:var(--text)}

.tk-campos{display:flex;flex-direction:column;gap:var(--s4)}
/* As abas do modal sao as `.tabs` do sistema — pilula e escolha entre
   recortes do MESMO conteudo, aba e troca de conteudo. So o respiro
   embaixo e daqui. */
.tk-abas-modal{margin-bottom:var(--s4)}
/* O rotulo com marca de obrigatorio vira linha flex: sem isso a marca
   herda o letter-spacing do rotulo e cola na ultima letra dele. */
.int-campo>.t-label{display:flex;align-items:baseline;gap:7px}
.tk-obrig{font:700 8.5px var(--mono);text-transform:uppercase;letter-spacing:.06em;
  color:var(--warning);opacity:.75}
/* Seletor dentro de celula de tabela: a altura do campo cheio
   empurraria a linha para o dobro. */
.sel--sm .sel-btn{padding:6px 9px;font-size:12px}

/* ── O EDITOR DE FUNIL ─────────────────────────────────────────────
   A parte mais densa da campanha. Cada funil e um caminho inteiro, e a
   caixa em volta existe para dizer onde um termina e o outro comeca —
   sem ela, dois funis viram uma lista so e o peso perde o dono. */
.tk-funis{display:flex;flex-direction:column;gap:var(--s4)}
/* O FUNIL E PECA DE VIDRO, e nao superficie afundada. Afundado e para
   o que RECEBE conteudo — campo, caixa de codigo, bloco de instrucao.
   O funil e um objeto que se manipula: clona, remove, arrasta peso. No
   sistema, objeto que se manipula e vidro.

   O `.glass` completo traz `overflow:hidden`, que cortaria a lista do
   seletor quando ela abrisse para fora do cartao — por isso aqui entra
   a superficie e a moldura do vidro, sem o corte. Os fios de luz vem do
   `::before` e `::after`, como em toda peca de vidro. */
.tk-funil{position:relative;display:flex;flex-direction:column;gap:var(--s4);
  padding:var(--s4);border-radius:var(--r-md);
  background:var(--surface);
  backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);
  border:1px solid var(--border);
  box-shadow:var(--sh-card),inset 0 1px 0 rgba(255,255,255,.10),
             inset 0 -1px 0 rgba(255,255,255,.03)}
.tk-funil::before{content:'';position:absolute;top:0;left:0;right:0;height:1px;
  pointer-events:none;border-radius:var(--r-md) var(--r-md) 0 0;
  background:linear-gradient(90deg,transparent,rgba(255,255,255,.30),transparent)}
.tk-funil::after{content:'';position:absolute;top:0;left:0;width:1px;height:100%;
  pointer-events:none;
  background:linear-gradient(180deg,rgba(255,255,255,.26),transparent,rgba(255,255,255,.07))}
/* Alinha pela BASE do campo: o peso tem rotulo em cima e o apelido nao,
   entao alinhar pelo topo deixaria os dois campos em alturas
   diferentes. */
.tk-funil-topo{display:flex;align-items:flex-end;gap:var(--s3);
  flex-wrap:wrap;padding-bottom:15px}
.tk-funil-topo>.input{flex:1;min-width:120px}
.tk-funil-n{font:700 10px var(--mono);text-transform:uppercase;letter-spacing:.08em;
  color:var(--muted);padding-bottom:12px;flex:none}

/* PESO E PORCENTAGEM ANDAM JUNTOS. Peso nao e porcentagem: tres funis
   com peso 100 dao um terco cada. Quem nao sabe disso escreve 100, 50 e
   50 achando que fez 50/25/25, e so descobre pelo relatorio. A fatia ao
   lado do campo e o que dispensa a explicacao.

   A FATIA FICA FORA DO FLUXO. Dentro dele, ela somava altura embaixo do
   campo e empurrava a linha inteira — cada elemento parava numa altura
   diferente, e a fileira ficava serrilhada. Absoluta, ela aparece sob o
   campo sem participar do alinhamento, e a linha volta a alinhar pelo
   proprio campo. */
/* O espaco da fatia e da LINHA, e nao do campo. Se o proprio bloco do
   peso ficasse mais alto, com `align-items:flex-end` ele empurraria o
   campo dele para CIMA dos vizinhos — que e o inverso do que se quer. */
.tk-peso{position:relative;display:flex;flex-direction:column;gap:5px;
  flex:none;width:104px}
.tk-peso .input{width:100%}
.tk-fatia{position:absolute;left:0;top:calc(100% + 3px);
  font:700 10px var(--mono);color:var(--cyan);opacity:.85}

/* Uma etapa do funil: rotulo, os itens, e os botoes de acrescentar. */
.tk-etapa{display:flex;flex-direction:column;gap:var(--s2);
  padding-left:var(--s3);border-left:2px solid var(--border)}
/* O botao de acrescentar fica do tamanho dele, no canto. Num flex de
   coluna o filho estica por padrao, e o botao virava uma faixa da
   largura inteira — parecia area de soltar arquivo, e nao um botao.
   As linhas de item continuam esticando, que e o certo para elas. */
.tk-etapa>.btn{align-self:flex-start}
.tk-item{display:flex;align-items:flex-end;gap:var(--s3);padding-bottom:15px}
.tk-item>.sel{flex:1;min-width:0}
.tk-item .tk-peso{width:92px}
/* O numero da linha desce ate a base do campo, junto com o resto. */
.tk-item-n{font:700 11px var(--mono);color:var(--muted);flex:none;
  padding-bottom:11px;width:14px;text-align:right}

/* O BOTAO ACOMPANHA A ALTURA DO CAMPO AO LADO. O `.btn--sm` tem 34px e
   o campo tem 41: alinhados pela base, o botao fica com uma sobra em
   cima e nenhuma embaixo, e a fileira parece torta mesmo estando
   alinhada. Aqui ele iguala o campo, e o respiro fica igual dos dois
   lados. */
.tk-funil-topo>.btn,.tk-item>.btn{min-height:41px}
.tk-funil-topo>.btn--icon,.tk-item>.btn--icon{width:41px;height:41px}
/* Botao pequeno tem 34px e o campo tem 41: `flex-end` ja alinha os dois
   pela base, entao nao ha o que compensar aqui. */

@media (max-width:560px){
  .tk-funil-topo>.input{min-width:100%}
  .tk-item{flex-wrap:wrap}
  .tk-item>.sel{min-width:100%}
}

/* ── MODAL DE DUAS COLUNAS ─────────────────────────────────────────
   Montar campanha e ir e voltar entre o funil e o dominio dezenas de
   vezes. Em abas, cada volta obriga a lembrar o que ficou do outro
   lado; lado a lado, os dois ficam a vista ao mesmo tempo.

   A coluna do funil e um pouco mais larga porque e ela que tem seletor,
   peso e botao na mesma linha — a de configuracao e so campo empilhado. */
.modal--duplo{max-width:min(1480px,96vw)}
.tk-duplo{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1.15fr);
  gap:var(--s5);align-items:start}
.tk-col{display:flex;flex-direction:column;gap:var(--s5);min-width:0}
/* A coluna da direita ganha um fio a esquerda, e nao uma caixa: caixa
   dentro de modal empilharia vidro sobre vidro. */
.tk-col:last-child{padding-left:var(--s5);border-left:1px solid var(--border)}

/* Numa tela estreita as duas viram uma, e a divisoria some junto —
   fio horizontal entre blocos empilhados nao divide nada. */
@media (max-width:900px){
  .tk-duplo{grid-template-columns:1fr}
  .tk-col:last-child{padding-left:0;border-left:0;
    padding-top:var(--s5);border-top:1px solid var(--border)}
}

/* O icone de reemitir mora DENTRO da coluna do certificado, ao lado do
   estado que ele muda — acao que so serve a uma coluna fica na coluna
   que ela mexe, e ai nao e preciso adivinhar sobre o que ela age.

   So aparece com o mouse na linha: um icone por linha, visivel o tempo
   todo, viraria ruido numa tabela de sete colunas. */
.tk-cert{display:inline-flex;align-items:center;gap:var(--s2)}
.tk-refazer{opacity:0;transition:opacity .14s}
tbody tr:hover .tk-refazer,.tk-refazer:focus-visible{opacity:1}

/* ── WORKSPACE ─────────────────────────────────────────────────────
   Um cartao por operacao. Sem isso, quem monta o funil do Melasma ve as
   paginas do HealthReport no meio e precisa ler nome por nome.

   O cartao aparece mesmo VAZIO: gaveta vazia e convite para preencher,
   e escondida faria parecer que o workspace nao existe. */
/* O ESPAÇO ENTRE AS GAVETAS. Faltava: os cartões eram irmãos soltos num
   bloco sem regra nenhuma, e saíam encostados um no outro — duas peças
   de vidro coladas leem como uma peça só, e aí a divisão por campanha,
   que é a razão de existir do cartão, para de aparecer. */
#tk-corpo{display:flex;flex-direction:column;gap:var(--s5)}

.tk-ws{display:flex;flex-direction:column;gap:var(--s4)}
/* A gaveta vazia: a constatação e o convite na mesma linha. Empilhados
   eles somariam duas alturas de texto para dizer que não há nada — e o
   que não tem nada é o que menos merece altura na tela. */
.tk-gaveta-vazia{display:flex;align-items:center;gap:var(--s3);flex-wrap:wrap}
/* O RESPIRO TEM UM DONO SO. O `.bloco-cab` traz margem embaixo e o
   cartao traz `gap`: os dois somavam, e o cabecalho da gaveta ficava
   descolado da tabela enquanto os tipos la dentro ficavam grudados. Aqui
   o `gap` manda, e a margem zera. */
.tk-ws>.bloco-cab{margin-bottom:0}
/* A cor e so um marcador de identidade, do tamanho de um ponto: nome de
   workspace se le, cor se reconhece de canto de olho. */
.tk-ws-cor{width:9px;height:9px;border-radius:50%;flex:none;
  background:var(--c);box-shadow:0 0 8px color-mix(in srgb,var(--c) 55%,transparent)}
/* A primeira faixa de tipo vem colada no cabecalho da tabela, que ja e
   uma barra fechada — o respiro de 11px que separa uma faixa da faixa
   anterior nao tem o que separar no topo. */
.tk-ws tbody tr.tb-plat:first-child td{padding-top:2px}

/* ══════════ ENTRADA ═════════════════════════════════════════════
   A tela de login. Não tem menu, não tem barra de topo e não tem
   conteúdo — é a única do produto que existe para quem ainda não é
   ninguém, e qualquer coisa a mais na tela é coisa a mais para ler
   antes de fazer o que veio fazer.

   A caixa é o `.glass` de sempre. Peça nova aqui seria peça sem
   irmãos: uma superfície que só existe numa tela é uma superfície que
   ninguém mantém junto com o resto. */
.entrada{min-height:100vh;display:grid;place-items:center;padding:var(--s5)}
/* Largura de LEITURA, e não de tela. Um formulário de dois campos
   esticado em 1400px faz o olho viajar do rótulo até o campo. */
.entrada-caixa{width:100%;max-width:394px}
.entrada-marca{display:flex;align-items:center;gap:var(--s3)}
.entrada-marca h1{font:800 21px/1 var(--sans);letter-spacing:-.02em;margin:0}
/* O mesmo ponto de identidade da gaveta, no tamanho de sempre: nome se
   lê, cor se reconhece de canto de olho. */
.entrada-ponto{width:9px;height:9px;border-radius:50%;flex:none;
  background:var(--cyan);box-shadow:0 0 10px rgba(0,219,233,.55)}
.entrada-diz{margin:var(--s2) 0 var(--s5)}
.entrada form{display:flex;flex-direction:column;gap:var(--s4)}
/* O botão ocupa a largura toda porque é a única ação da tela. Botão
   pequeno num canto obrigaria a procurar o que fazer a seguir. */
.entrada form .btn{justify-content:center;padding:12px}
.entrada-pe{margin:var(--s5) 0 0}

/* Enquanto a sessão está sendo conferida, o corpo não aparece. Sem
   isto, o painel inteiro desenha e some meio segundo depois, e a tela
   mente sobre o que a pessoa pode ver. `visibility` e não `display`:
   esconder por display força um recálculo de layout inteiro quando
   volta, e a tela pisca de novo na volta. */
html[data-checando] body{visibility:hidden}
