  /* Paleta do Figma "N1 Traffic Hawk New" (node 49:154).
     Os NOMES das variáveis são os antigos de propósito: o resto do arquivo
     depende deles, então trocar só os VALORES migra a folha inteira de uma vez.
     Tipografia do projeto é Poppins em tudo — se aparecer outra família em
     qualquer lugar, é engano. */
  :root{
    --bg:#090A0C;
    --nav:#1C1F26;
    --panel:#111318;
    --card:#17191E;
    --card-2:#1A1D24;        /* "surface": superfícies sobre painel */
    --bot-card:#1B1D20;
    --line:rgb(255 255 255 / .08);
    --line-2:#2A2E37;
    --ink:#F5F6F7;
    --ink-2:#8A8F99;         /* muted */
    --ink-3:#64748B;         /* slate-dim */
    --slate:#94A3B8;
    --slate-lit:#CBD5E1;
    --blue:#3086FF;
    --green:#3DDC84;
    --green-deep:#0FBC5F;
    --amber:#FBBF24;
    /* vermelho segue reservado ao que é ruim (bots, bloqueio), não é mais a
       cor de acento da interface — esse papel passou pro azul */
    --accent:#F0443E;
    --accent-soft:#FF6B5E;
    --accent-ink:#200705;
    --on-accent:#FFFFFF;
    --accent-2:#A8262D;
    /* Textura diagonal POR CIMA do degradê, nos painéis translúcidos
       (boas-vindas, Fontes de Tráfego, Requisições ao Vivo). O painel de
       Sites usa só o degradê, sem a textura. */
    --stripes:repeating-linear-gradient(45deg,transparent 0 14px,rgb(255 255 255 / .035) 14px 22px);
    --panel-grad:linear-gradient(to right,rgb(0 0 0 / .5),rgb(26 29 36 / .5));
    --r-xl:28px;
    --r-lg:22px;
    --r-md:16px;
    --r-full:999px;
    --font:'Poppins',system-ui,-apple-system,sans-serif;

    /* Escala do design.
       O Figma é um canvas de 2000px com 1872 de conteúdo (64 de recuo de cada
       lado). Antes eu multiplicava tudo por 0.8 fixo "pra virar tamanho web",
       e o resultado era uma tela 20% menor que o design em QUALQUER largura —
       faixa 24px em vez de 30, aba 16 em vez de 20, número da fonte 19 em vez
       de 24. Agora o fator acompanha o espaço real: em 1872px de conteúdo a
       faixa superior sai 1:1 com o Figma, e abaixo disso encolhe inteira e
       junto, como o visualizador do Figma faz, em vez de refluir com tipo
       miúdo. O piso de .62 é onde as media queries de empilhamento assumem.

       O divisor é 1872px, COM unidade: comprimento ÷ comprimento dá número
       puro, que é o que multiplica os tamanhos. Dividir por 1872 sem unidade
       devolve um comprimento, e aí todo calc(54px * var(--k)) vira px² — ou
       seja, inválido, e a propriedade inteira cai fora. */
    /* usa o MESMO recuo que o body e a topbar (--recuo, publicado pelo
       fitOverview). Com a formula antiga aqui o fator ficava fora de sincronia
       com a largura real do conteudo e a coluna do Canvas saia desproporcional. */
    --k-tela:clamp(.62,calc((100vw - 2 * var(--recuo,clamp(16px,3vw,44px))) / 1872px),1);
    --k:var(--k-tela);
  }

  *{box-sizing:border-box}
  html,body{margin:0;padding:0}
  /* Fundo liso, como no design. A grade quadriculada saiu: no Figma a textura
     não é global — ela aparece só nos painéis translúcidos, via --stripes.
     O .notch continua herdando o fundo da página para simular o recorte, e
     com cor chapada isso fica exato em vez de depender do alinhamento da grade. */
  body,.notch,.notch::before,.notch::after{
    background-color:var(--bg);
    background-image:none;
  }
  body{
    color:var(--ink);
    font-family:var(--font);
    font-size:14px;
    line-height:1.4;
    min-height:100vh;
    /* --recuo vem do fitOverview: é onde o conteúdo já renderizado começa.
       A topbar usa o mesmo valor, então a marca nasce alinhada com os cards
       em qualquer largura. O clamp fica de reserva pro primeiro paint e pras
       faixas onde o canvas não é escalado. */
    padding:92px var(--recuo,clamp(16px,3vw,44px)) 44px;
  }

  .shell{margin:0 auto}
  /* A Overview é um canvas de 1872px escalado por zoom (fitOverview no JS),
     igual ao visualizador do Figma. Dentro dele o fator é sempre 1: as
     medidas do CSS são as do Figma e quem encolhe é o zoom, não cada valor.
     Sem isto o --k do :root (que olha a 100vw) escalaria de novo por cima do
     zoom e o conteúdo sairia reduzido duas vezes. */
  /* --zf e o fator de zoom aplicado pelo fitOverview. O piso divide 9px por
     ele, entao max(valor-do-figma, piso) nunca pinta abaixo de 9px e nunca
     passa do valor de projeto quando o zoom e 1. */
  #view-overview{margin-inline:auto;--k:1;--zf:1;--piso-tipo:calc(9px / var(--zf))}

  /* ---------- top bar ---------- */
  /* Faixa sólida, como no design (49:155): a nav é um bloco #1C1F26 e a aba
     ativa é um RECORTE nela — o notch é preenchido com a cor da página, de
     modo que a aba parece vazada até o fundo. Nada de blur aqui. */
  .topbar{
    position:fixed;top:0;left:0;right:0;z-index:20;
    display:flex;align-items:center;gap:20px;
    /* design: 88px de altura com 12 de recuo no topo */
    height:max(64px,calc(88px * var(--k)));padding:calc(12px * var(--k)) var(--recuo,clamp(16px,3vw,44px)) 0;
    background:var(--nav);
    border-bottom-color:transparent;
    box-shadow:none;
  }
  .topbar.is-scrolled{
    background:var(--nav);
    box-shadow:0 10px 28px -16px rgb(0 0 0 / .65);
  }
  .brand{display:flex;align-items:center;gap:10px;min-width:150px}
  .brand-mark{
    width:max(32px,calc(50px * var(--k)));height:max(32px,calc(50px * var(--k)));border-radius:10px;
    object-fit:contain;object-position:left center;display:block;
  }
  /* filete vertical entre a marca e o nome (68:1793) */
  .vrule{width:1px;height:calc(34px * var(--k));background:rgb(255 255 255 / .5);border-radius:1px;flex:none}
  .brand-name{font-weight:300;font-size:max(16px,calc(24px * var(--k)));letter-spacing:0;white-space:nowrap}

  /* Nav (49:155) — medidas do Figma a 0.8 (o design é um canvas de 2000px;
     0.8 traz para tamanho natural de web sem distorcer as proporções).
     As duas constantes que o JS também usa vêm daqui e são lidas por
     getComputedStyle, para CSS e script nunca divergirem:
       gap        16 → 13px   (--nav-gap)
       ativa     347 → 278px  (--nav-ativa-w, o compartimento de CADA aba)
     sem overflow:hidden: o recorte desliza e precisa passar por fora. */
  .nav{
    --nav-gap:13px;
    --nav-ativa-w:278px;
    position:relative;display:flex;align-items:center;gap:var(--nav-gap);
    /* A altura vem da CAIXA DE CONTEUDO da topbar, nao de um calc proprio: a
       barra tem piso de 78px e a nav tinha piso de 61, entao os dois paravam
       de escalar em pontos diferentes e sobrava uma fresta de ~3px do fundo da
       barra aparecendo por baixo do recorte. Com 100% o recorte encosta
       sempre na borda de baixo (a topbar nao tem recuo inferior). */
    flex:1;justify-content:center;height:100%;align-self:stretch;
  }
  /* As três medidas da nav são escritas pelo dashboard.js (ajustaEscalaNav),
     em px literal: o JS as lê de volta com parseFloat, e propriedade custom
     não registrada volta como texto — um calc() aqui devolveria NaN e o
     recorte pararia no canto esquerdo. Os valores abaixo são só o ponto de
     partida, para o primeiro paint. */
  .nav-notch{
    position:absolute;left:0;top:0;height:100%;width:var(--nav-ativa-w);
    display:block;pointer-events:none;
    transition:transform .38s cubic-bezier(.22,.61,.36,1);
  }
  /* antes de medirmos, fica invisível — senão pisca no canto esquerdo no
     primeiro paint, antes de o script saber onde é a aba ativa */
  .nav-notch:not([style*="translate"]){opacity:0}
  .nav.no-anim .nav-pill,
  .nav.no-anim .nav-notch{transition:none}
  .nav-pill{
    position:relative;z-index:1;
    display:inline-flex;align-items:center;justify-content:center;gap:8px;
    height:max(38px,calc(54px * var(--k)));padding:0 max(20px,calc(32px * var(--k)));border-radius:var(--r-full);
    border:0;background:transparent;box-shadow:none;
    color:var(--ink-2);
    font:inherit;font-size:max(13px,calc(20px * var(--k)));font-weight:500;cursor:pointer;white-space:nowrap;
    transition:color .25s ease;
  }
  .nav-pill svg{width:max(17px,calc(26px * var(--k)));height:max(17px,calc(26px * var(--k)));flex:none}
  .nav-pill:hover{color:var(--ink)}
  .nav-pill.active{color:var(--ink);background:transparent}
  /* COMPARTIMENTO FIXO. No Figma só a aba ativa tem a largura do recorte e as
     vizinhas são empurradas — trocar de aba desloca as outras três em até
     159px. Aqui TODAS as abas recebem o mesmo compartimento, então a fileira
     não se mexe nunca: o recorte apenas desliza de um compartimento para o
     outro. A largura sai do mediNav (o recorte de 347 do design não cabe
     quatro vezes na barra) e o SVG tem preserveAspectRatio="none", então ele
     acompanha o compartimento em vez de o contrário.
     A classe é escrita pelo JS, e só quando ele decide que o recorte cabe:
     assim os modos compacto e mobile continuam com as larguras naturais. */
  .nav.com-recorte .nav-pill{width:var(--nav-ativa-w);flex:none}
  /* durante a medição as abas precisam voltar à largura natural, senão
     offsetWidth devolve o compartimento e a conta se realimenta */
  .nav.medindo .nav-pill{width:auto}
  /* Faixa intermediária (~950–1250px, e notebooks de 1366): o recorte de 278px
     não cabe junto com marca + seletor + ações, e travar a largura da nav
     empurrava o seletor de sites para fora da tela. Aqui a nav volta a
     encolher, a aba ativa vira pílula e o recorte sai de cena.
     Quem decide é mediNav(), medindo o espaço real — não um breakpoint fixo,
     porque a largura depende do tamanho dos rótulos. */
  /* overflow:hidden é a trava de segurança: sem ela as abas vazavam para fora
     da caixa da nav e ficavam POR CIMA do seletor de sites, comendo o clique.
     O recorte está escondido neste modo, então não há o que recortar. */
  .nav.sem-recorte{flex:1;min-width:0;overflow:hidden}
  .nav.sem-recorte .nav-notch{display:none}
  .nav.sem-recorte .nav-pill{padding:0 14px;font-size:14px;min-width:0}
  .nav.sem-recorte .nav-pill svg{width:18px;height:18px}
  .nav.sem-recorte .nav-pill .label{overflow:hidden;text-overflow:ellipsis}
  .nav.sem-recorte .nav-pill.active{
    width:auto;margin:0;background:var(--card-2);
  }
  /* mais estreito ainda: só os ícones. O nome continua acessível pelo
     aria-label do botão. */
  .nav.so-icones .nav-pill{padding:0 11px;gap:0}
  .nav.so-icones .nav-pill .label{display:none}

  .top-actions{display:flex;align-items:center;gap:8px}
  .date-filter{position:relative;z-index:35}
  .date-filter-btn{
    display:inline-flex;align-items:center;justify-content:center;gap:7px;
    width:max(36px,calc(54px * var(--k)));height:max(36px,calc(54px * var(--k)));
    padding:0;border-radius:var(--r-full);
    border:1px solid var(--line);background:linear-gradient(180deg,rgb(255 255 255 / .06),rgb(255 255 255 / 0));
    color:var(--ink-2);font:inherit;font-size:12px;font-weight:700;cursor:pointer;
  }
  /* no design (51:609) o período é só o ícone de calendário. O rótulo continua
     no DOM porque o JS escreve nele e o leitor de tela o anuncia — some só da
     pintura. */
  .date-filter-btn #dateFilterLabel{
    position:absolute;width:1px;height:1px;overflow:hidden;
    clip-path:inset(50%);white-space:nowrap;
  }
  .date-filter-btn:hover{border-color:var(--line-2);color:var(--ink)}
  .date-filter-btn[aria-expanded="true"]{border-color:var(--blue);background:var(--blue);color:#fff;box-shadow:0 0 0 3px rgb(48 134 255 / .18)}
  .date-filter-btn svg{width:max(15px,calc(24px * var(--k)));height:max(15px,calc(24px * var(--k)));stroke:currentColor;fill:none;stroke-width:1.7}
  .date-filter-popover{
    position:absolute;top:calc(100% + 10px);right:0;width:300px;padding:14px;
    border:1px solid var(--line-2);border-radius:16px;
    background:var(--card-2);
    box-shadow:0 24px 50px -20px rgb(0 0 0 / .8);
  }
  .date-presets{display:grid;grid-template-columns:repeat(4,1fr);gap:6px}
  .date-presets button,.date-cancel,.date-apply{
    border:1px solid var(--line);border-radius:9px;padding:7px 6px;
    background:var(--card-2);color:var(--ink-2);font:inherit;font-size:11px;cursor:pointer;
  }
  .date-presets button:hover{border-color:var(--line-2);color:var(--ink)}
  .date-presets button.active{background:var(--blue);border-color:var(--blue);color:#fff}
  .date-calendar-head{display:flex;align-items:center;justify-content:space-between;margin:14px 0 10px;color:var(--ink);font-size:12px}
  .date-month-nav{width:27px;height:27px;border:1px solid var(--line);border-radius:8px;background:var(--card-2);color:var(--ink-2);font-size:20px;line-height:1;cursor:pointer}
  .date-month-nav:hover{border-color:var(--line-2);color:var(--ink)}
  .date-weekdays,.date-calendar-grid{display:grid;grid-template-columns:repeat(7,1fr);gap:3px}
  .date-weekdays{color:var(--ink-3);font-size:9px;text-align:center;text-transform:uppercase;letter-spacing:.04em}
  .date-calendar-grid{margin-top:4px}
  .date-calendar-grid>span{height:28px}
  .date-calendar-day{
    height:28px;border:0;border-radius:7px;background:transparent;color:var(--ink-2);
    font:inherit;font-size:11px;cursor:pointer;
  }
  .date-calendar-day:hover{background:rgb(48 134 255 / .32);color:#fff}
  .date-calendar-day.today{box-shadow:inset 0 0 0 1px var(--blue)}
  .date-calendar-day.available{background:rgb(48 134 255 / .16);color:var(--slate-lit)}
  .date-calendar-day.selected{background:var(--blue);color:#fff;font-weight:700}
  .date-calendar-day.in-range{background:rgb(48 134 255 / .38);color:#fff;border-radius:0}
  .date-calendar-day.selected.in-range{border-radius:7px}
  .date-calendar-summary{min-height:17px;margin-top:8px;color:var(--ink-3);font-size:10px;text-align:center}
  .date-filter-error{min-height:16px;margin-top:7px;color:#FF8075;font-size:11px}
  .date-filter-actions{display:flex;justify-content:flex-end;gap:7px;margin-top:2px}
  .date-apply{background:var(--blue);border-color:var(--blue);color:#fff;font-weight:700}
  .date-apply:hover{filter:brightness(1.12)}
  .date-cancel{background:transparent}
  /* design .round-btn: 54x54, fundo --panel */
  .iconbtn{
    width:max(36px,calc(54px * var(--k)));height:max(36px,calc(54px * var(--k)));border-radius:var(--r-full);
    border:1px solid var(--line);
    background:linear-gradient(180deg,rgb(255 255 255 / .06),rgb(255 255 255 / 0));
    box-shadow:inset 0 1px 0 rgb(255 255 255 / .07);
    display:grid;place-items:center;cursor:pointer;color:var(--ink-2);
    transition:border-color .08s,color .08s;
    flex:none;
  }
  .iconbtn:hover{border-color:var(--line-2);color:var(--ink)}
  .iconbtn svg{width:max(15px,calc(24px * var(--k)));height:max(15px,calc(24px * var(--k)));stroke:currentColor;fill:none;stroke-width:1.7}
  .user-menu{position:relative}
  .user-dd{
    position:absolute;top:calc(100% + 8px);right:0;z-index:60;
    min-width:150px;padding:6px;border-radius:12px;
    background:#1B1B1A;border:1px solid var(--line-2);
    box-shadow:0 18px 40px -18px rgb(0 0 0 / .9);
  }
  .user-dd-item{
    width:100%;display:flex;align-items:center;gap:9px;
    background:none;border:0;border-radius:8px;padding:9px 10px;
    color:var(--ink-2);font:inherit;font-size:12.5px;cursor:pointer;text-align:left;
  }
  .user-dd-item:hover{background:var(--card-2);color:var(--ink)}
  .user-dd-item svg{width:15px;height:15px;stroke:currentColor;fill:none;stroke-width:1.8;flex:none}
  /* design 49:180: círculo BRANCO com as iniciais em preto, 54px */
  .avatar{
    width:max(36px,calc(54px * var(--k)));height:max(36px,calc(54px * var(--k)));border-radius:var(--r-full);
    background:#fff;
    box-shadow:0 6px 14px -6px rgb(0 0 0 / .5);
    display:grid;place-items:center;
    border:0;padding:0;cursor:pointer;font:inherit;
    font-size:max(12px,calc(20px * var(--k)));font-weight:400;color:#000;
  }

  /* Botão "Logs" (43:198): quadrado só com o ícone, que se alarga no hover e
     revela a palavra. O rótulo vem de ::after — no markup o botão tem apenas
     o ícone e um aria-label, então quem lê tela continua ouvindo "Logs".
     (No Figma os nomes das variantes estão trocados: a chamada "hover" é a de
     repouso e a "Default" é a de hover.) */
  /* design .sq-btn: 44x44, raio 8, fundo --surface, ícone preenchido */
  .logs-btn{
    width:calc(44px * var(--k));height:calc(44px * var(--k));padding:0;border-radius:8px;
    display:inline-flex;align-items:center;justify-content:center;overflow:hidden;
    border:0;background:var(--card-2);color:var(--ink);
    font:inherit;font-size:12px;font-weight:400;cursor:pointer;flex:none;
    transition:width .26s cubic-bezier(.22,.61,.36,1),background-color .2s ease,color .2s ease;
  }
  .logs-btn::after{
    content:"Logs";
    /* line-height 1 deixava a caixa com exatos 12px e a perna do "g" caía
       fora, aparada pelo overflow:hidden do botão */
    font:400 12px/1.7 'Poppins',sans-serif;white-space:nowrap;
    max-width:0;margin-left:0;opacity:0;overflow:hidden;
    transition:max-width .26s cubic-bezier(.22,.61,.36,1),
               margin-left .26s cubic-bezier(.22,.61,.36,1),
               opacity .18s ease;
  }
  .logs-btn:hover{width:68px;background:#FFFFFF;color:#373737}
  .logs-btn:hover::after{max-width:40px;margin-left:7px;opacity:1}
  @media (prefers-reduced-motion:reduce){
    .logs-btn,.logs-btn::after{transition:none}
  }
  /* o ícone do Figma é um path preenchido (viewBox 56), não um traçado */
  .logs-btn svg{width:calc(24px * var(--k));height:calc(24px * var(--k));fill:currentColor;stroke:none;flex:none}
  .filterbtn svg{width:15px;height:15px;stroke:currentColor;fill:none;stroke-width:1.8}

  /* ---------- layout ---------- */
  /* faixa de boas-vindas (49:189) — a textura diagonal vai POR CIMA do
     degradê, por isso --stripes vem antes de --panel-grad na lista */
  .welcome{
    width:100%;border-radius:12px;padding:7px 20px;margin-bottom:16px;
    display:flex;flex-direction:column;align-items:flex-start;
    background-image:var(--stripes),var(--panel-grad);
  }
  .welcome p{font-weight:500;font-size:calc(30px * var(--k));color:var(--ink);line-height:1.35;margin:0}

  /* Proporções do design (49:192): a faixa de 1872px se divide em
     430 (Visitantes) | 1026 (Fontes) | 368 (Bot Radar), com vãos de 24.
     Em fr isso é 430 | 501+501+vão | 368 — as Fontes ocupam as colunas 2 e 3.
     Antes era repeat(3,1fr)+330px fixo, que dava 438|858|432: o card de
     Fontes saía 170px estreito demais e o do Radar 64 largo demais. */
  .grid{
    display:grid;gap:calc(24px * var(--k));
    grid-template-columns:430fr 501fr 501fr 368fr;
    /* a faixa de métricas tem altura fixa no design (.metrics, 322px); sem
       isso a linha crescia com o conteúdo e os cards de fonte saíam com 184
       de altura em vez de 100 */
    grid-template-rows:calc(322px * var(--k)) auto;
  }
  /* item de grade nasce com min-height:auto, ou seja, nunca encolhe abaixo do
     próprio conteúdo — a trilha de 322px era ignorada e os três cards saíam
     com 422. Com min-height:0 eles obedecem a trilha e as grades internas
     (.sources em repeat(6,1fr)) repartem a altura, que é como o Figma chega
     nos 100px de cada card de fonte.
     O seletor parte de .main, não de .grid: .main é display:contents, então os
     cards viram itens da grade sem deixar de ser filhos dele no DOM. */
  .main > .card.live,
  .main > .card.fontes,
  .main > .card.bots{min-height:0}
  /* .metrics tem 322 e os dois cards da direita 316, encostados no topo */
  .main > .card.fontes,
  .main > .card.bots{height:calc(316px * var(--k));align-self:start}
  .fontes-body,.sources{min-height:0}
  .main{display:contents}

  .card{
    position:relative;
    background:
      var(--card) padding-box,
      linear-gradient(180deg,rgb(255 255 255 / .14),rgb(255 255 255 / .03) 45%,rgb(255 255 255 / 0)) border-box;
    border:1px solid transparent;
    border-radius:var(--r-xl);
    padding:14px;
    min-width:0;
    box-shadow:0 24px 48px -24px rgb(0 0 0 / .55);
  }
  .card::before{
    content:"";position:absolute;inset:0;border-radius:inherit;
    background:radial-gradient(120% 55% at 50% 0%,rgb(255 255 255 / .05),transparent 60%);
    pointer-events:none;
  }
  /* título à esquerda, botão de Logs à direita, na mesma linha — como o
     .v-head do design (70:2140). O canto recortado saiu junto com o .notch. */
  .card-head{
    display:flex;align-items:center;justify-content:space-between;gap:10px;
    margin-bottom:10px;min-height:38px;
  }
  .card-title{font-size:calc(24px * var(--k));color:#fff;font-weight:600;letter-spacing:-.025em;line-height:1.33}
  /* no design o título das Fontes é leve (400) e o de Visitantes é 600 */
  .fontes .card-title{font-weight:400;letter-spacing:0}
  .iconbtn.sm{width:30px;height:30px}
  .iconbtn.sm svg{width:13px;height:13px}
  .iconbtn.solid{
    background:linear-gradient(180deg,#FFFFFF,#D9D9D2);border-color:#FFFFFF;color:#111;
    box-shadow:inset 0 1px 0 #FFF,0 8px 16px -8px rgb(0 0 0 / .6);
  }
  .iconbtn.solid:hover{color:#111;opacity:.9}
  .iconbtn.dark{
    background:linear-gradient(180deg,#2A2A28,#1C1C1A);border-color:rgb(255 255 255 / .08);color:var(--ink);
    box-shadow:inset 0 1px 0 rgb(255 255 255 / .09);
  }
  .iconbtn.dark:hover{background:linear-gradient(180deg,#323230,#232321);color:var(--ink)}
  .iconbtn.syncing svg{animation:syncspin .35s linear infinite}
  @keyframes syncspin{to{transform:rotate(360deg)}}
  .bump{animation:rtBump .2s ease}
  @keyframes rtBump{from{opacity:.3}to{opacity:1}}

  /* ---------- seletor de site (canvas) ---------- */
  .site-sel{position:relative}
  .site-sel-dd{z-index:30}
  .site-sel-btn{
    display:flex;align-items:center;gap:9px;
    height:max(36px,calc(54px * var(--k)));padding:0 max(16px,calc(18px * var(--k)));border-radius:var(--r-full);
    border:1px solid var(--line-2);
    background:rgb(24 24 23 / .92);backdrop-filter:blur(8px);
    color:#D3D3D3;font:inherit;font-size:max(13px,calc(20px * var(--k)));font-weight:500;cursor:pointer;
    box-shadow:0 14px 30px -14px rgb(0 0 0 / .7);
    white-space:nowrap;
  }
  .site-sel-btn svg{width:max(12px,calc(24px * var(--k)));height:max(12px,calc(24px * var(--k)));stroke:var(--ink-3);fill:none;stroke-width:2;flex:none}
  .site-sel-dd{
    position:absolute;top:calc(100% + 8px);left:50%;translate:-50%;
    width:320px;max-height:380px;
    display:flex;flex-direction:column;gap:8px;
    padding:12px;border-radius:16px;
    background:
      linear-gradient(180deg,rgb(31 31 30 / .97),rgb(20 20 19 / .97)) padding-box,
      linear-gradient(180deg,rgb(255 255 255 / .12),rgb(255 255 255 / .02)) border-box;
    border:1px solid transparent;
    box-shadow:0 24px 50px -20px rgb(0 0 0 / .8);
  }
  .site-sel-dd .login-inp{margin-top:0}
  .site-sel-list{overflow-y:auto;min-height:0;display:flex;flex-direction:column;gap:2px}
  .site-sel-list::-webkit-scrollbar{width:8px}
  .site-sel-list::-webkit-scrollbar-thumb{background:#2A2A28;border-radius:8px}
  .site-opt{
    display:flex;align-items:center;gap:10px;
    text-align:left;padding:8px 10px;border-radius:10px;border:none;background:none;
    color:var(--ink-2);font:inherit;font-size:12.5px;cursor:pointer;
    transition:background .08s,color .08s;
  }
  .site-opt:hover{background:var(--card-2);color:var(--ink)}
  .site-opt.on{background:#1F232B;color:var(--ink);font-weight:700}
  .so-logo{
    width:28px;height:28px;border-radius:8px;flex:none;
    background:var(--panel);display:grid;place-items:center;overflow:hidden;
  }
  .so-logo img{max-width:80%;max-height:70%;object-fit:contain}
  .so-letter{font-weight:800;font-size:12px;color:var(--ink-2)}
  .so-name{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  /* contagem em azul, como no design (.site-opt .num). O vermelho ali fica
     reservado ao site sem tráfego — ver .so-n.off */
  .so-n{font-size:12px;font-weight:700;color:var(--blue)}
  .so-n.off{color:var(--accent)}
  @media (prefers-reduced-motion:no-preference){
    .site-sel-dd{animation:ddIn .08s cubic-bezier(.2,.7,.3,1)}
    @keyframes ddIn{from{opacity:0;transform:translateY(-8px) scale(.97)}to{opacity:1;transform:none}}
    .site-sel-list .site-opt{animation:optIn .08s cubic-bezier(.2,.7,.3,1) both;animation-delay:calc(.008s * var(--oi,0))}
    @keyframes optIn{from{opacity:0;transform:translateX(-6px)}to{opacity:1;transform:none}}
  }
  .site{cursor:pointer}

  /* canto recortado: aba na cor do fundo + duas curvas invertidas */
  .card.notched{position:relative}
  .notch{
    position:absolute;top:-1px;right:-1px;z-index:2;
    display:flex;gap:6px;
    padding:0 0 10px 10px;
    border-bottom-left-radius:20px;
  }
  .notch .iconbtn{width:32px;height:32px}
  .notch .iconbtn svg{width:14px;height:14px}
  .notch::before,.notch::after{
    content:"";position:absolute;width:16px;height:16px;
    -webkit-mask:radial-gradient(circle 16px at 0 100%, transparent 15px, #000 15.5px);
    mask:radial-gradient(circle 16px at 0 100%, transparent 15px, #000 15.5px);
  }
  .notch::before{top:0;right:100%}
  .notch::after{top:100%;right:0}

  .fig{font-variant-numeric:tabular-nums;letter-spacing:-.02em}

  /* ---------- visitantes ativos ---------- */
  .card.live,.card.fontes{border-radius:calc(22px * var(--k));padding:calc(16px * var(--k)) calc(24px * var(--k))}
  .card.live{border-radius:calc(20px * var(--k));padding:calc(10px * var(--k)) calc(16px * var(--k))}
  .card.live{display:flex;flex-direction:column}
  /* fundo do card de Visitantes (70:2137). O blur fica no VÍDEO, não no véu:
     como backdrop-filter o desfoque criava um halo na borda. O scale(1.06)
     evita que o desfoque revele a borda transparente do próprio quadro. */
  .card.live{position:relative;overflow:hidden;isolation:isolate}
  .live-vid{position:absolute;inset:0;z-index:0;pointer-events:none;overflow:hidden}
  .live-vid video{
    width:100%;height:100%;object-fit:cover;display:block;
    filter:blur(4px);transform:scale(1.06);
  }
  .live-veil{position:absolute;inset:0;z-index:0;background:rgb(0 0 0 / .8);pointer-events:none}
  /* tudo que é conteúdo sobe acima do vídeo */
  .card.live > *:not(.live-vid):not(.live-veil){position:relative;z-index:1}

  .live-row{display:flex;align-items:center;gap:14px;margin-top:0}
  .live-num{
    font-size:calc(60px * var(--k));font-weight:800;line-height:1;letter-spacing:-.025em;
    filter:drop-shadow(0 2px 6px rgb(255 255 255 / .15));
  }
  /* pill "Ao vivo" (70:2144): vidro esverdeado com halo e ponto pulsante */
  .live-tag{
    display:inline-flex;align-items:center;gap:8px;
    padding:calc(5px * var(--k)) calc(13px * var(--k));border-radius:9999px;
    background:rgb(16 185 129 / .1);border:1px solid rgb(52 211 153 / .25);
    box-shadow:0 0 14px -2px rgb(16 185 129 / .35);
    color:#6EE7B7;font-size:calc(14px * var(--k));font-weight:600;letter-spacing:.35px;white-space:nowrap;
  }
  /* dois círculos sobrepostos: o de baixo fica parado, o de cima expande */
  .live-tag .ping{position:relative;width:9px;height:9px;flex:none}
  .live-tag .ping i{
    position:absolute;inset:0;border-radius:9999px;background:#34D399;
    box-shadow:0 0 8px 0 rgb(52 211 153 / .9);
  }
  .live-dot{width:7px;height:7px;border-radius:50%;background:var(--green);flex:none}
  /* o design (70:2137) não tem gráfico neste card: título, número e o painel
     de totais, e só. O sparkline empurrava o card de 322 para 350 de altura e
     desalinhava a faixa inteira. Segue no DOM porque o Canvas o reaproveita. */
  #view-overview .live-chart{display:none}
  .live-chart{height:40px;margin:6px 0 6px}
  .live-chart svg{display:block;width:100%;height:100%}
  @media (prefers-reduced-motion:no-preference){
    .live-tag .ping i:first-child{opacity:.75;animation:ping 2s cubic-bezier(0,0,.2,1) infinite}
    @keyframes ping{75%,100%{transform:scale(2.2);opacity:0}}
    .live-dot{animation:pulse 1s ease-out infinite}
    @keyframes pulse{
      0%{box-shadow:0 0 0 0 rgb(61 220 132 / .5)}
      70%{box-shadow:0 0 0 7px rgb(61 220 132 / 0)}
      100%{box-shadow:0 0 0 0 rgb(61 220 132 / 0)}
    }
  }
  .live-time{
    margin-left:auto;align-self:center;
    font-size:max(calc(14px * var(--k)),var(--piso-tipo,0px));color:var(--slate);white-space:nowrap;
  }
  .live-time b{color:#fff;font-weight:700}
  /* painel de totais: caixa clara (--panel) embrulhando a escura (--card-2) */
  .mini-stats{
    display:flex;gap:0;
    margin-top:auto;
    background:var(--panel);border-radius:14px;padding:8px;
    box-shadow:0 10px 24px 0 rgb(0 0 0 / .16);
    min-width:0;
  }
  .mini-stats > .ms{
    flex:1 0 0;min-width:0;
    background:var(--card-2);padding:7px 12px;
    display:flex;align-items:center;gap:12px;
  }
  .mini-stats > .ms:first-child{border-radius:8px 0 0 8px}
  .mini-stats > .ms:last-child{border-radius:0 8px 8px 0}
  .ms + .ms{border-left:1px solid rgb(255 255 255 / .06)}
  .ms-col{display:flex;flex-direction:column;gap:3px;min-width:0}
  /* nunca quebra no meio da palavra: o overflow-wrap:anywhere partia
     "PAGEVIEWS HOJE" em "PAGEVIE / WS HOJE" assim que a caixa apertava, e a
     linha extra ainda empurrava o card e estourava a coluna */
  .ms-l{
    font-size:max(calc(12px * var(--k)),var(--piso-tipo,0px));color:var(--slate);text-transform:uppercase;
    letter-spacing:.06em;font-weight:700;line-height:1.2;
    white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
  }
  .ms b{
    font-size:calc(30px * var(--k));font-weight:800;line-height:1.2;letter-spacing:-.025em;color:#fff;
    filter:drop-shadow(0 0 5px rgb(56 189 248 / .25));
  }
  .ms b.accent{color:#fff}
  .cs-hora{color:var(--ink-3)}
  .cs-hora b{color:var(--ink-2)}
  .ms b.down{color:var(--accent)}

  /* ---------- active campaign (red) ---------- */
  /* marcador vertical luminoso — aparece em quase todo card do design */
  .marker{width:4px;border-radius:999px;flex:none;align-self:stretch}
  .marker-green{background:var(--green);box-shadow:0 0 8px 1px var(--green)}
  .marker-blue {background:var(--blue); box-shadow:0 0 8px 1px var(--blue)}
  .marker-red  {background:var(--accent);box-shadow:0 0 8px 1px var(--accent)}

  /* ---------- Bot Radar (49:291) ----------
     O card inteiro é o radar: vídeo ao fundo, cabeçalho flutuando em cima e
     o painel de totais ancorado embaixo. clip-path junto do overflow porque
     o vídeo é camada composta e o raio sozinho deixa franja no canto. */
  .card.bots{
    position:relative;overflow:hidden;clip-path:inset(0 round calc(22px * var(--k)));
    background:var(--bot-card);
    border-radius:calc(22px * var(--k));
    grid-column:4;grid-row:1;
    display:flex;flex-direction:column;justify-content:space-between;
    padding:14px;color:#fff;
    box-shadow:0 18px 42px 0 rgb(0 0 0 / .33);
  }
  .card.bots::before{content:none}
  .bots-vid{
    position:absolute;left:50%;top:0;transform:translateX(-50%);
    width:150%;height:100%;object-fit:cover;display:block;pointer-events:none;
  }
  .bots-head{position:relative;z-index:1;display:flex;align-items:center;justify-content:space-between;gap:8px}
  .bots-chip{
    height:calc(44px * var(--k));border-radius:8px;background:var(--card-2);
    display:inline-flex;align-items:center;gap:8px;padding:0 calc(13px * var(--k));
    font-size:calc(16px * var(--k));font-weight:400;color:#fff;white-space:nowrap;
  }
  /* o chip do design (49:291) traz só "Bot Radar" — o total já está no painel
     de baixo, repeti-lo no cabeçalho não existe no Figma */
  .bots-chip b{display:none}
  .bots-ico{width:22px;height:22px;fill:#FFFFFF;flex:none}
  /* o botão de logs some do fluxo do .notch e vira um quadrado sobre o vídeo */
  .bots-logs{position:static}

  .splitbar{display:flex;gap:3px;height:14px;margin-top:auto}
  .splitbar[hidden]{display:none}
  .splitbar .seg{border-radius:var(--r-full)}
  .splitbar .seg.block{background:var(--accent)}
  .splitbar .seg.allow{background:var(--green)}

  /* painel de totais (49:302): caixa clara sobre caixa escura, como no design */
  .bots-totals{
    position:relative;z-index:1;
    background:var(--panel);border-radius:14px;padding:8px;
    box-shadow:0 10px 24px 0 rgb(0 0 0 / .16);
  }
  .bots-totals .inner{
    background:var(--card-2);border-radius:8px;padding:8px 12px;
    display:flex;flex-direction:column;gap:8px;
  }
  .bots-totals .row{display:flex;align-items:center;gap:calc(8px * var(--k));min-height:calc(20px * var(--k))}
  .bots-totals .k{font-size:max(calc(12px * var(--k)),var(--piso-tipo,0px));color:var(--ink-2);white-space:nowrap}
  .bots-totals .v{font-weight:700;font-size:calc(16px * var(--k));color:#fff}
  /* design 49:302: o número herda a cor do marcador da linha */
  .bots-totals .row:has(.marker-red) .v{color:var(--accent)}
  .bots-totals .row:has(.marker-green) .v{color:var(--green-deep)}
  /* design mostra só o número absoluto em Bloqueados/Permitidos */
  .bots-totals .p{display:none}
  .bots-totals .hr{height:1px;background:rgb(255 255 255 / .08)}

  .fontes{grid-column:2 / 4;grid-row:1}

  /* ---------- fontes de tráfego ---------- */
  .fontes{display:flex;flex-direction:column}
  /* .sources-card do Figma: bloco das fontes e coluna de métricas lado a lado,
     com space-between; a coluna tem a altura inteira do card (284). */
  .fontes-body{flex:1;display:flex;justify-content:space-between;gap:calc(48px * var(--k));min-height:0;margin-top:0}
  .fontes-col{flex:1;min-width:0;display:flex;flex-direction:column;gap:calc(16px * var(--k))}
  /* .summary: 194 de largura, 3 cartões de altura igual e vão de 16 */
  .resumo{
    width:calc(194px * var(--k));flex:none;align-self:stretch;
    display:flex;flex-direction:column;gap:calc(16px * var(--k));
  }
  .resumo > .src{flex:1 0 0;min-height:1px;display:flex}
  .sources{
    width:100%;flex:1;min-width:0;
    display:grid;grid-template-columns:repeat(2,minmax(0,1fr));
    grid-template-rows:repeat(2,minmax(0,1fr));
    /* 2 linhas de 100px + vão de 16 = 216, exatamente o bloco do Figma */
    height:calc(216px * var(--k));align-self:start;
    gap:calc(16px * var(--k));margin-top:0;
  }
  /* 2x2: Facebook · Direto na primeira coluna, Google · Instagram na segunda.
     A posição explícita some porque a grade agora é simétrica — os três blocos
     de métrica saíram daqui e viraram a coluna .resumo. */
  .src{display:flex;min-width:0}
  /* Card de fonte (49:220/245/257/267). Composição do design, de baixo pra cima:
       1. blobs da marca, no CANTO SUPERIOR ESQUERDO (atrás do texto, não do logo)
       2. véu preto a 50%
       3. logo da marca, grande, à direita
       4. fade que apaga o logo da esquerda pra direita
     clip-path além do overflow: os blobs viram camada composta e o raio
     sozinho deixa franja clara nos cantos no Chrome. */
  .src-card{
    flex:1;min-width:0;
    position:relative;overflow:hidden;clip-path:inset(0 round calc(20px * var(--k)));
    display:flex;flex-direction:column;justify-content:center;gap:calc(12px * var(--k));
    padding:0 calc(16px * var(--k));border-radius:calc(20px * var(--k));
    background-color:var(--card);
    background-image:var(--blobs,none);
    background-repeat:no-repeat;
    color:#FFF;
    box-shadow:0 6px 14px -8px rgb(0 0 0 / .5);
  }
  /* véu de 50%, como no design */
  .src-card::before{
    content:"";position:absolute;inset:0;pointer-events:none;z-index:1;
    background:rgb(0 0 0 / .5);
  }
  /* fade: some com o logo indo pra direita. No Figma vai de left:205 a 362
     num card de 360 — ou seja, começa a 57% da largura. */
  .src-card::after{
    content:"";position:absolute;inset:0;pointer-events:none;z-index:3;
    background:linear-gradient(to right,rgb(0 0 0 / 0) 57%,#000 100%);
  }
  /* No Figma o logo ocupa de 68% a 100% da largura do card (360px de card,
     logo em left:245 com 114 de largura) e transborda ~16% da altura. Ancorar
     pela ESQUERDA em 66% reproduz isso em qualquer largura e garante que o
     texto da esquerda nunca fique por baixo. */
  .src-logo{
    position:absolute;left:66%;right:auto;top:50%;transform:translateY(-50%);
    width:auto;height:116%;max-width:none;max-height:none;
    object-fit:contain;display:block;
    pointer-events:none;z-index:2;
  }

  /* blobs por marca — cores exatas do Figma */
  .src-card.g{--blobs:
    radial-gradient(38% 60% at 6% 4%,  #3DDC84 0%,rgb(61 220 132 / 0) 70%),
    radial-gradient(42% 66% at 22% -6%,#FCCC00 0%,rgb(252 204 0 / 0) 70%),
    radial-gradient(40% 64% at 20% 30%,#3086FF 0%,rgb(48 134 255 / 0) 70%)}
  .src-card.ig{--blobs:
    radial-gradient(40% 62% at 4% 22%, #FFCD0A 0%,rgb(255 205 10 / 0) 70%),
    radial-gradient(38% 58% at 24% -4%,#CE1E88 0%,rgb(206 30 136 / 0) 70%)}
  .src-card.dir{--blobs:
    radial-gradient(40% 62% at 4% 22%, #E7C7A3 0%,rgb(231 199 163 / 0) 70%),
    radial-gradient(38% 58% at 24% -4%,#7C30FF 0%,rgb(124 48 255 / 0) 70%)}
  .src-card.fb{--blobs:
    radial-gradient(40% 62% at 4% 22%, #FFFFFF 0%,rgb(255 255 255 / 0) 70%),
    radial-gradient(38% 58% at 24% -4%,#3086FF 0%,rgb(48 134 255 / 0) 70%)}
  /* acima do véu e do blob */
  .src-top,.src-row{position:relative;z-index:2}
  .src-card{height:100%;min-height:0}
  .src-card b,.src-pct{line-height:1.15}
  .src-top{display:flex;align-items:center;gap:calc(8px * var(--k));min-width:0}
  /* design 49:220 — nome e números no MESMO corpo (24px) e leves (400). Era
     12/700 no nome e 15/800 no número, o que dava um card com hierarquia
     invertida em relação ao Figma. */
  .src-name{font-size:calc(24px * var(--k));font-weight:400;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .src-card b{font-size:calc(24px * var(--k));font-weight:400;letter-spacing:0}
  .src-row{display:flex;align-items:center;gap:calc(16px * var(--k));min-width:0}
  /* o design não tem ícone de pessoa antes do número (49:220..267) */
  .src-user{display:none}
  .src-user svg{width:100%;height:100%;display:block}
  .src-sep{width:1.5px;height:calc(22px * var(--k));background:#fff;border-radius:1px;flex:none}
  .src-pct{font-size:calc(24px * var(--k));font-weight:400;color:#fff;letter-spacing:0}
  /* ---- resumo: Impressões / Cliques / Tempo médio (49:380) ----
     Não são cards de marca: faixa de cabeçalho em cima, valores centrados e
     um "tick" azul rente à borda de baixo. No Figma o tick fica em top:82.33
     num card de 84, então quase só o brilho aparece — é assim mesmo, não é
     corte acidental. */
  .src-card.imp,.src-card.clk,.src-card.tmp{
    --blobs:none;
    background-color:var(--panel);
    padding:0;gap:6px;
    justify-content:flex-start;align-items:center;
    box-shadow:0 10px 24px 0 rgb(0 0 0 / .16);
  }
  .src-card.imp::before,.src-card.clk::before,.src-card.tmp::before{background:none}
  /* o tick entra no lugar do fade */
  .src-card.imp::after,.src-card.clk::after,.src-card.tmp::after{
    content:"";position:absolute;left:50%;transform:translateX(-50%);
    top:auto;bottom:-2px;inset:auto auto -2px 50%;
    width:calc(58px * var(--k));height:calc(4px * var(--k));border-radius:999px;
    background:var(--blue);box-shadow:0 0 8px 1px var(--blue);
  }
  /* design .summary-card: faixa de 33px no topo, rótulo 14px, valores 16px */
  .src-card.imp .src-top,.src-card.clk .src-top,.src-card.tmp .src-top{
    width:100%;height:calc(33px * var(--k));flex:none;
    background:var(--card-2);border-radius:8px 8px 0 0;
    display:flex;align-items:center;justify-content:center;gap:8px;padding:0 12px;
  }
  .src-card.imp .src-name,.src-card.clk .src-name,.src-card.tmp .src-name{
    /* o --txt-2 do Figma e #F7F8FA, quase branco — nao um cinza apagado */
    font-size:max(calc(14px * var(--k)),var(--piso-tipo,0px));font-weight:400;color:var(--ink);
  }
  .src-card.imp .src-wm,.src-card.clk .src-wm,.src-card.tmp .src-wm{
    position:static;width:calc(20px * var(--k));height:calc(20px * var(--k));flex:none;
    fill:var(--ink);opacity:.9;transform:none;
  }
  .src-card.tmp .src-wm{fill:none;stroke:var(--ink)}
  .src-card.imp .src-row,.src-card.clk .src-row,.src-card.tmp .src-row{
    flex:1;display:flex;align-items:center;justify-content:center;gap:calc(12px * var(--k));padding:0 10px;
  }
  .src-card.imp b,.src-card.clk b,.src-card.tmp b,
  .src-card.imp .src-pct,.src-card.clk .src-pct,.src-card.tmp .src-pct{
    font-size:max(calc(16px * var(--k)),var(--piso-tipo,0px));font-weight:400;color:var(--ink);
    /* uma linha só: com dados reais ("1m 41s | 10.308 sessões") o texto é mais
       largo que o do mock do Figma e quebrava em duas linhas, estourando o
       cartão de 84px */
    white-space:nowrap;min-width:0;overflow:hidden;text-overflow:ellipsis;
  }
  /* o cartão de Tempo médio é o mais comprido dos três; um passo a menos de
     corpo evita o corte sem destoar dos vizinhos */
  .src-card.tmp b,.src-card.tmp .src-pct{font-size:max(calc(14px * var(--k)),var(--piso-tipo,0px))}
  .src-card.oth{--blobs:none}
  /* .summary-card do Figma: fundo --panel chapado e sombra descendente.
     Estava com um degradê marrom e um filete branco por dentro. */
  .src-card.imp,.src-card.clk,.src-card.tmp{
    background:var(--panel);
    box-shadow:0 10px 24px 0 rgb(0 0 0 / .16);
  }
  .src-card.imp .src-wm,.src-card.clk .src-wm{fill:rgb(255 255 255 / .07)}
  .src-card.tmp .src-wm{fill:none;stroke:rgb(255 255 255 / .10)}

  /* Blocos de FONTE (Facebook, Direto, Google, Instagram): marca d'agua e
     texto maiores. So estes — os de metrica ao lado tem 50px de altura e
     nao comportam. */
  .src-card.fb .src-wm,.src-card.dir .src-wm,
  .src-card.g  .src-wm,.src-card.ig  .src-wm{
    width:96px;height:96px;right:-16px;bottom:-24px;
  }
  .src-card.fb,.src-card.dir,.src-card.g,.src-card.ig{gap:calc(12px * var(--k))}
  /* design 49:220 — nome, número e porcentagem no mesmo corpo de 24px e peso
     400. As três regras abaixo existiam com 13.5/19/16 e anulavam a base. */
  .src-card.fb .src-name,.src-card.dir .src-name,
  .src-card.g  .src-name,.src-card.ig  .src-name{font-size:calc(24px * var(--k))}
  .src-card.fb b,.src-card.dir b,.src-card.g b,.src-card.ig b{font-size:calc(24px * var(--k))}
  .src-card.fb .src-pct,.src-card.dir .src-pct,
  .src-card.g  .src-pct,.src-card.ig  .src-pct{font-size:calc(24px * var(--k))}
  .src-card.fb .src-user,.src-card.dir .src-user,
  .src-card.g  .src-user,.src-card.ig  .src-user{width:16px;height:16px}
  .src-card.fb .src-sep,.src-card.dir .src-sep,
  .src-card.g  .src-sep,.src-card.ig  .src-sep{height:calc(26px * var(--k))}

  /* Tempo na pagina: ocupa as 3 colunas na linha de baixo. O grid preenche
     por coluna (grid-auto-flow:column), entao um setimo bloco solto abriria
     uma 4a coluna e desalinharia os seis de cima — dai a faixa. */

  /* ---------- sales trends ---------- */
  .trend{grid-column:1 / 4;grid-row:2}
  .sites{
    display:grid;gap:calc(24px * var(--k));
    /* 5 por linha e vão de 24 — o Figma monta 1380px de painel assim */
    grid-template-columns:repeat(5,minmax(0,1fr));
    overflow-y:auto;overscroll-behavior:contain;
    /* overflow-y:auto sozinho já força overflow-x a virar auto também (regra
       do spec: um eixo non-visible converte o outro pra auto) — os cards
       encostados na borda da grade tinham o próprio crescimento do hover
       (.site:hover{scale}) e o brilho do .beam cortados nessa borda. O
       padding dá um colchão pro overflow antes do corte; a margin negativa
       cancela esse colchão pra grade não mudar de posição/tamanho. */
    padding:10px;margin:calc(24px * var(--k) - 10px) -10px -10px -10px;
  }
  .sites::-webkit-scrollbar{width:8px}
  .sites::-webkit-scrollbar-thumb{background:#2A2A28;border-radius:8px}
  .sites::-webkit-scrollbar-track{background:transparent}
  /* design .search-bar: barra de largura TOTAL no topo do painel, raio 12,
     recuo 12/16 — não a pílula estreita de 260px que estava aqui */
  .site-search{
    display:flex;align-items:center;gap:calc(10px * var(--k));
    padding:calc(12px * var(--k)) calc(16px * var(--k));border-radius:12px;
    border:1px solid var(--line);
    background:var(--card);
    width:100%;
  }
  .site-search svg{width:calc(20px * var(--k));height:calc(20px * var(--k));stroke:var(--ink-3);fill:none;flex:none}
  .site-search input{
    background:none;border:none;outline:none;font:inherit;font-size:calc(14px * var(--k));
    color:var(--ink);width:100%;padding:0;
  }
  .site-search input::placeholder{color:var(--ink-2)}
  .sites-empty{
    grid-column:1 / -1;padding:26px 0;text-align:center;
    font-size:12.5px;color:var(--ink-3);display:none;
  }
  /* Card de site (51:613). Overflow VISÍVEL de propósito: é o que deixa o
     brilho do feixe escapar da borda no hover. Quem recorta a marca d'água
     é o .wm-clip. */
  .site{
    /* design 61:1060: altura fixa de 371, recuo 16 e vão 24 entre os blocos.
       O aspect-ratio 4/5 fazia a altura seguir a largura da coluna, então o
       card mudava de proporção a cada breakpoint. */
    height:calc(371px * var(--k));
    position:relative;
    display:flex;flex-direction:column;gap:calc(16px * var(--k));
    padding:calc(16px * var(--k));border-radius:14px;
    background:var(--card);
    border:0;
    transition:scale .28s cubic-bezier(.22,.61,.36,1);
  }
  /* Usa a propriedade `scale` isolada, e não transform: o card roda a animação
     de entrada `rise`, que tem fill-mode:both e portanto continua aplicando
     `transform:none` depois de terminar — uma animação vence a cascata normal
     e engoliria um transform:scale() do hover. `scale` é propriedade separada
     e não entra nesse conflito.
     Como não afeta o layout, o card cresce sem empurrar os vizinhos; o z-index
     impede que eles passem por cima dele ao crescer. */
  .site:hover{scale:1.022;z-index:3}

  .site .wm-clip{position:absolute;inset:0;border-radius:14px;overflow:hidden;pointer-events:none}
  /* Medidas exatas do Figma: caixa de 250x250 em (40,170), recortada pelo
     .wm-clip — ela é mais LARGA que o card (243), então sangra pela direita
     de propósito. Estava em porcentagem (68% de largura), o que dava 184px e
     uma marca bem menor e mais alta que a do design. Como nossos arquivos são
     wordmarks e não marcas quadradas, a imagem é centrada na caixa com
     object-fit: a pegada e a posição batem, mesmo com o desenho sendo largo. */
  .site .watermark{
    position:absolute;
    left:calc(40px * var(--k));top:calc(170px * var(--k));
    width:calc(250px * var(--k));height:calc(250px * var(--k));
    opacity:.05;
  }
  .site .watermark img{width:100%;height:100%;object-fit:contain;display:block}

  /* ---- feixe de luz percorrendo a borda no hover ----
     stroke-dasharray num retângulo arredondado faz o traço andar em velocidade
     constante ao longo do contorno real, inclusive nos cantos. Um
     conic-gradient giratório varreria por ângulo e ficaria irregular num card
     alto e estreito como este.
     pathLength=1000 normaliza o perímetro: 250/750 é sempre 25% do contorno,
     qualquer que seja o tamanho do card. */
  .site .beam{
    position:absolute;inset:0;width:100%;height:100%;pointer-events:none;z-index:2;
    /* svg tem overflow:hidden por padrão — sem isso o drop-shadow (o glow que
       precisa de espaço FORA da caixa do rect) era cortado rente à borda do
       card, sobrando só o traço fino e sem o brilho escapando. */
    overflow:visible;
    /* a saída é mais demorada que a entrada — a luz "se apaga" em vez de
       desligar. Esta regra vale quando o mouse SAI; a de :hover, ao entrar. */
    opacity:0;transition:opacity 1.1s cubic-bezier(.33,0,.25,1);
    filter:drop-shadow(0 0 4px rgb(48 134 255 / .85)) drop-shadow(0 0 9px rgb(124 48 255 / .5));
  }
  .site .beam rect{
    width:calc(100% - 1.5px);height:calc(100% - 1.5px);
    fill:none;stroke:url(#beamGrad);stroke-width:1.5;stroke-linecap:round;
    stroke-dasharray:250 750;
    animation:beamrun 7s linear infinite;
  }
  .site:hover .beam{opacity:1;transition:opacity .8s cubic-bezier(.33,0,.25,1)}
  @keyframes beamrun{to{stroke-dashoffset:-1000}}
  @media (prefers-reduced-motion:reduce){
    .site{transition:none}
    .site:hover{transform:none}
    .site .beam rect{animation:none;stroke-dasharray:none;opacity:.55}
  }
  /* Card de site (61:1060). No Figma: linha de logo (52px) + nome da marca,
     domínio embaixo, filete e a lista de métricas — tudo com as medidas
     abaixo. Antes o logo tinha 64 de altura e ocupava a linha sozinho. */
  .site-logo-row{
    height:calc(52px * var(--k));width:100%;
    display:flex;align-items:center;gap:calc(10px * var(--k));
  }
  /* Só o SÍMBOLO da marca, sem badge/anel ao redor — o nome por extenso já
     vem escrito ao lado em .site-marca. */
  .site-logo{
    width:calc(36px * var(--k));height:calc(36px * var(--k));flex:none;
    display:flex;align-items:center;justify-content:center;
  }
  .site-logo img{
    width:100%;height:100%;object-fit:contain;
  }
  .site-marca{
    flex:1;min-width:0;margin:0;
    font-weight:800;font-size:max(calc(15px * var(--k)),var(--piso-tipo,0px));color:var(--ink);
    white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
  }
  .site-hr{width:100%;height:1px;background:rgb(255 255 255 / .08);flex:none}
  /* barrinha vertical com glow — não é mais um pill em volta do texto, só um
     marcador fino antes do domínio (como o .bar-site .marker do replay.css).
     Sempre aparece: verde quando o site é rastreado na borda (Worker, conta
     100% das visitas), âmbar quando não é (a contagem pode ter buracos). */
  .edge-dot{
    display:inline-block;flex:none;width:3px;height:calc(14px * var(--k));
    border-radius:var(--r-full);background:var(--green);
    box-shadow:0 0 6px rgb(61 220 132 / .8);
  }
  .edge-dot.off{
    background:var(--amber);
    box-shadow:0 0 6px rgb(251 191 36 / .8);
  }
  .site-name{
    display:flex;align-items:center;gap:calc(8px * var(--k));
    font-size:calc(16px * var(--k));font-weight:400;color:var(--ink);
    white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
  }
  .site-stats{margin-top:auto;display:grid;gap:calc(16px * var(--k))}
  .site-stats div{display:flex;justify-content:space-between;align-items:baseline;gap:6px}
  /* rótulo em caixa normal e branco, como no design — era 9.5px, maiúsculas e
     cinza, o que deixava o card com peso visual bem diferente do Figma */
  .site-stats span{font-size:calc(16px * var(--k));color:#fff;text-transform:none;letter-spacing:0}
  .site-stats b{font-size:calc(18px * var(--k));font-weight:700;color:var(--ink)}
  .site-stats b.sb{color:var(--accent)}

  /* ---------- right rail ---------- */
  .rail{
    grid-column:4;grid-row:2;
    display:flex;flex-direction:column;gap:16px;
    height:0;min-height:100%;
  }
  .rail .card{flex:1;display:flex;flex-direction:column;min-height:0}
  .logs{flex:1;overflow-y:auto;min-height:0;scrollbar-width:thin;scrollbar-color:#3a3a37 transparent}
  .logs::-webkit-scrollbar{width:8px}
  .logs::-webkit-scrollbar-thumb{background:#3a3a37;border-radius:8px}
  .logs::-webkit-scrollbar-thumb:hover{background:#4a4a47}
  .logs::-webkit-scrollbar-track{background:transparent}
  .rail-head{
    display:flex;align-items:center;justify-content:space-between;
    gap:10px;
    margin-bottom:14px;
  }
  .rail-head .card-title{color:var(--ink-2)}

  .live-count{display:inline-flex;align-items:center;gap:8px;font-size:max(14px,var(--piso-tipo,14px));font-weight:700;color:var(--ink);margin-right:auto}
  /* Botão ao vivo do feed (51:780): sem moldura, só o símbolo. O ANEL gira e
     o símbolo central fica parado; pausado, o anel congela onde estava e a cor
     vai para âmbar. */
  .feed-pause{
    flex:none;width:30px;height:30px;padding:0;border:0;background:none;
    color:var(--green);cursor:pointer;
    display:flex;align-items:center;justify-content:center;
    transition:color .25s ease;
  }
  .feed-pause svg{width:30px;height:30px;display:block}
  .feed-pause path,.feed-pause rect{fill:currentColor}
  /* transform-box:view-box faz o 10px 10px ser o centro do viewBox, e não o
     centro da caixa do próprio traço — sem isso o anel gira descentralizado */
  .feed-pause .ring{
    transform-box:view-box;transform-origin:10px 10px;
    animation:ringspin 11s linear infinite;
  }
  @keyframes ringspin{to{transform:rotate(360deg)}}
  .feed-pause .ico-play{display:none}
  .feed-pause.paused{color:var(--amber)}
  .feed-pause.paused .ring{animation-play-state:paused}
  .feed-pause.paused .ico-pause{display:none}
  .feed-pause.paused .ico-play{display:block}
  /* o anel de foco padrão vira um retângulo branco horroroso em volta do
     ícone; mantemos o foco visível só no teclado, pelo :focus-visible geral */
  .feed-pause:focus{outline:none}
  @media (prefers-reduced-motion:reduce){.feed-pause .ring{animation:none}}
  /* o marcador do cabeçalho acompanha o botão e vira âmbar quando pausado */
  .rail-head .live-dot{transition:background-color .25s ease,box-shadow .25s ease}
  .card:has(.feed-pause.paused) .rail-head .live-dot{background:var(--amber);box-shadow:0 0 8px 1px var(--amber)}

  #hawk-toast{
    position:fixed;left:50%;bottom:28px;transform:translateX(-50%) translateY(20px);
    background:var(--card-2);color:var(--ink);border:1px solid var(--line-2);
    padding:10px 16px;border-radius:var(--r-full);font-size:12.5px;
    box-shadow:0 12px 30px -12px rgb(0 0 0 / .6);
    opacity:0;pointer-events:none;transition:opacity .2s,transform .2s;z-index:9999;
  }
  #hawk-toast.show{opacity:1;transform:translateX(-50%) translateY(0)}

  .live-badge{
    display:inline-flex;align-items:center;gap:6px;
    margin-left:10px;padding:3px 10px;border-radius:var(--r-full);
    background:rgb(61 220 132 / .14);color:var(--green);
    font-size:10.5px;font-weight:700;letter-spacing:.04em;text-transform:uppercase;
  }
  .live-badge .live-dot{width:7px;height:7px;border-radius:50%;background:var(--green);animation:pulse 1s ease-out infinite}

  /* ---------- Sessões Ao Vivo ---------- */
  #view-sessoes-ao-vivo .card{padding:14px}
  #sessoesVivoList{display:flex;flex-direction:column;gap:8px;overflow-y:auto;overscroll-behavior:contain}
  /* ================= SESSÕES AO VIVO (design: #viewSessoes) =================
     Lista em colunas ocupando a largura toda, em vez de cartões empilhados. */
  .sv-panel{
    width:100%;min-height:60vh;border-radius:22px;padding:24px;overflow:hidden;
    display:flex;flex-direction:column;gap:18px;
    background-image:var(--stripes),var(--panel-grad);
    box-shadow:0 18px 42px 0 rgb(0 0 0 / .33);
  }
  .sv-head{display:flex;align-items:center;justify-content:space-between;gap:16px;flex:none}
  .sv-head .status{display:flex;align-items:center;gap:12px}
  .sv-head .status .marker{height:20px;align-self:auto}
  .sv-head .status .title{margin:0;font-weight:500;font-size:19px;color:var(--ink);white-space:nowrap}
  .sv-head .status .count{
    display:flex;align-items:center;gap:8px;height:27px;padding:0 11px;border-radius:999px;
    background:rgb(61 220 132 / .12);font-weight:700;font-size:max(14px,var(--piso-tipo,14px));color:var(--green);
  }
  .sv-head .status .count s{
    width:7px;height:7px;border-radius:999px;background:var(--green);text-decoration:none;
    animation:svpulse 1.8s ease-in-out infinite;
  }
  @keyframes svpulse{
    0%,100%{opacity:1;box-shadow:0 0 0 0 rgb(61 220 132 / .55)}
    50%{opacity:.55;box-shadow:0 0 0 6px rgb(61 220 132 / 0)}
  }
  .sv-head .hint{margin:0;font-size:12.5px;color:var(--ink-3);white-space:nowrap}

  .sv-cols,.sv-row{display:flex;align-items:center;gap:16px;width:100%}
  /* espelha a geometria da linha: o calc(100% - 8px) cobre o padding-right
     do .sv-list e a borda transparente cobre a borda do .sv-row — sem isso o
     cabecalho ficava 9px a direita das celulas */
  .sv-cols{flex:none;padding:0 16px;height:20px;width:calc(100% - 8px);border:1px solid transparent}
  .sv-cols span{
    font-size:10px;font-weight:500;letter-spacing:.09em;text-transform:uppercase;
    color:var(--ink-3);white-space:nowrap;
    /* mesmo contrato das celulas: sem isto, "Pagina atual" transbordava a
       propria coluna e era pintado por cima de "Origem" */
    overflow:hidden;text-overflow:ellipsis;
  }
  .c-ico {width:40px;flex:none}
  /* flex:0 1 auto (e nao flex:none): as tres colunas de texto cedem largura
     juntas. Antes so a .c-url era flexivel e ela colapsava para 0-12px entre
     821 e 1080px, sumindo com a URL de todas as linhas. */
  .c-site{width:clamp(160px,18vw,300px);flex:0 1 auto;min-width:0}
  .c-loc {width:clamp(120px,14vw,250px);flex:0 1 auto;min-width:0}
  .c-url {flex:1 1 120px;min-width:0}
  .c-ref {width:clamp(120px,12vw,200px);flex:none;min-width:0}
  .c-pag {width:80px;flex:none;text-align:center}
  .c-time{width:96px;flex:none;text-align:right}
  .c-live{width:92px;flex:none;display:flex;justify-content:flex-end}

  .sv-list{
    flex:1 0 0;min-height:1px;width:100%;
    display:flex;flex-direction:column;gap:10px;
    overflow-y:auto;overflow-x:hidden;padding-right:8px;
  }
  .sv-list::-webkit-scrollbar{width:6px}
  .sv-list::-webkit-scrollbar-thumb{background:var(--line-2);border-radius:999px}
  .sv-list::-webkit-scrollbar-track{background:transparent}

  .sv-row{
    height:70px;flex:none;padding:0 16px;border-radius:14px;
    background:var(--card);border:1px solid transparent;cursor:pointer;
    transition:background-color .16s ease,border-color .16s ease;
  }
  .sv-row:hover{background:#1F232B;border-color:#2C313B}
  /* só as sessões que acabaram de aparecer animam a entrada */
  @keyframes svin{from{opacity:0;transform:translateY(-10px)}to{opacity:1;transform:none}}
  .sv-row.is-new{animation:svin .5s cubic-bezier(.22,.61,.36,1)}
  /* realce quando a sessão avança de página: a linha "pisca" em azul e volta
     ao fundo normal, para o olho perceber o que mudou numa lista que atualiza
     sozinha a cada 8s */
  @keyframes svhop{0%{background:rgb(48 134 255 / .16)}100%{background:var(--card)}}
  .sv-row.hop{animation:svhop 1.1s ease}
  @media (prefers-reduced-motion:reduce){
    .sv-row.is-new{animation:none}
    .sv-head .status .count s,.sv-badge s{animation:none}
  }

  .sv-row .dev{
    width:40px;height:40px;border-radius:12px;flex:none;
    display:flex;align-items:center;justify-content:center;
    background:linear-gradient(180deg,#22262F,#191C22);color:var(--slate-lit);
    box-shadow:inset 0 1px 0 rgb(255 255 255 / .07);
  }
  .sv-row .dev svg{width:19px;height:19px}
  .sv-site{display:flex;align-items:center;gap:10px;min-width:0;width:clamp(160px,18vw,300px);flex:none}
  .sv-site .lg{width:28px;height:28px;flex:none}
  .sv-site .lg img{width:100%;height:100%;object-fit:contain;display:block}
  .sv-site .dm{
    font-weight:600;font-size:14px;line-height:1.2;color:var(--slate-lit);text-transform:lowercase;
    white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
  }
  .sv-a{display:block;font-weight:500;font-size:13px;line-height:1.25;color:var(--ink);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .sv-b{display:block;font-weight:400;font-size:11px;line-height:1.35;color:var(--ink-3);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;margin-top:2px}
  .sv-url{font-size:12.5px;color:var(--slate);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .sv-ref{display:flex;align-items:center;gap:8px;min-width:0}
  .sv-ref i{width:8px;height:8px;border-radius:999px;flex:none}
  .sv-ref span{font-size:12.5px;color:var(--slate);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .sv-pag{font-weight:700;font-size:15px;color:var(--ink)}
  .sv-time{font-weight:700;font-size:15px;color:var(--ink);font-variant-numeric:tabular-nums}
  .sv-badge{
    display:flex;align-items:center;gap:6px;height:24px;padding:0 9px;border-radius:999px;
    background:rgb(61 220 132 / .14);color:var(--green);
    font-size:max(9.5px,var(--piso-tipo,9.5px));font-weight:700;letter-spacing:.08em;text-transform:uppercase;white-space:nowrap;
  }
  .sv-badge s{
    width:6px;height:6px;border-radius:999px;background:var(--green);text-decoration:none;
    animation:svpulse 1.8s ease-in-out infinite;
  }
  .sv-empty{padding:60px 0;text-align:center;font-size:14px;color:var(--ink-3)}
  .logs{display:flex;flex-direction:column;gap:10px}
  .log{
    display:flex;align-items:center;gap:10px;flex-wrap:wrap;
    padding:10px 2px;border-top:1px solid rgb(255 255 255 / .05);
  }
  .log:first-child{border-top:none}

  /* ---- Requisição no formato do design (51:778) ----
     Cada requisição é um cartão próprio: cabeçalho (origem + horário + play),
     caixa de rota (site, pílula de status, referer, caminho) e, embaixo de um
     filete, a linha de meta com IP e user-agent. Vale só para as linhas que o
     feed ao vivo monta com `rota:true`; os modais seguem no formato antigo. */
  .logs .log:has(.log-route){
    display:block;padding:14px;border:0;border-radius:12px;
    background:var(--card);
  }
  .log-top{display:flex;align-items:flex-start;justify-content:space-between;gap:10px}
  .log-origin{display:flex;align-items:center;gap:10px;min-width:0}
  .log-who{min-width:0}
  .log:has(.log-route) .log-loc{font-size:max(13px,var(--piso-tipo,13px));font-weight:500;color:#F1F5F9;line-height:1.4}
  .log-when{font-size:max(10.5px,var(--piso-tipo,10.5px));color:var(--ink-3);line-height:1.5;white-space:nowrap}
  .log-route{
    background:var(--panel);border-radius:8px;padding:9px 10px;margin-top:10px;
    display:flex;flex-direction:column;gap:5px;min-width:0;
  }
  .log-line1{display:flex;align-items:flex-start;justify-content:space-between;gap:8px}
  .log-site{display:flex;align-items:center;gap:7px;min-width:0}
  .log-site-mark{width:18px;height:18px;flex:none}
  .log-site-mark img{width:100%;height:100%;object-fit:contain;display:block}
  .log-site p{
    margin:0;font-weight:600;font-size:max(13px,var(--piso-tipo,13px));line-height:1.2;color:var(--slate-lit);
    text-transform:lowercase;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
  }
  .log-pill{
    flex:none;border-radius:4px;padding:2px 6px;
    font-size:max(9.5px,var(--piso-tipo,9.5px));line-height:1.5;font-weight:500;letter-spacing:.02em;text-transform:uppercase;
    background:rgb(245 158 11 / .15);border:1px solid rgb(245 158 11 / .3);color:var(--amber);
  }
  .log-pill.ok{background:rgb(61 220 132 / .14);border-color:rgb(61 220 132 / .32);color:var(--green)}
  .log-pill.bad{background:rgb(240 68 62 / .14);border-color:rgb(240 68 62 / .35);color:#FF7A74}
  .log-ref{font-size:max(10.5px,var(--piso-tipo,10.5px));line-height:1.5;color:var(--slate)}
  .log-ref b{font-weight:400;color:var(--slate-lit)}
  .log-path{font-size:max(10.5px,var(--piso-tipo,10.5px));line-height:1.5;color:var(--ink-3);word-break:break-all}
  .log-metarow{
    margin-top:10px;padding-top:8px;border-top:1px solid rgb(38 49 67 / .5);
    display:flex;align-items:center;gap:8px;min-width:0;
  }
  .log-ip{
    background:var(--panel);border-radius:4px;padding:3px 7px;flex:none;
    font-size:max(10.5px,var(--piso-tipo,10.5px));line-height:1.5;color:var(--slate-lit);
  }
  .log-dot{width:3px;height:3px;border-radius:50%;background:var(--ink-3);flex:none}
  .log-ua{font-size:max(10.5px,var(--piso-tipo,10.5px));line-height:1.5;color:var(--slate);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .log-ico{
    width:30px;height:30px;border-radius:9px;flex:none;
    display:grid;place-items:center;color:#FFF;
    box-shadow:inset 0 1px 0 rgb(255 255 255 / .22);
  }
  .log-ico svg{width:14px;height:14px}
  .log-ico.fb{background:#1877F2}
  .log-ico.web{background:var(--card-2);color:var(--ink-2)}
  .log-ico.bot{background:linear-gradient(180deg,#F0443E,#A5140C)}
  .log-txt{min-width:0;flex:1}
  .log-loc{font-size:max(12.5px,var(--piso-tipo,12.5px));font-weight:600}
  .log-url{font-size:11px;color:var(--ink-3);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .log-meta{display:flex;align-items:center;gap:8px;flex:none}
  .log-time-row{flex:1 1 100%;display:flex;justify-content:flex-end;margin-top:2px}
  .log-time{font-size:10.5px;color:var(--ink-3);white-space:nowrap}
  .log-rec{
    flex:none;width:22px;height:22px;padding:0;border:1px solid var(--line-2);
    border-radius:var(--r-full);background:var(--card-2);color:var(--ink-2);
    cursor:pointer;display:flex;align-items:center;justify-content:center;
    transition:color .12s,border-color .12s,background .12s,opacity .12s;
  }
  .log-rec svg{width:11px;height:11px;display:block}
  .log-rec:hover{color:var(--green);border-color:rgb(61 220 132 / .5);background:rgb(61 220 132 / .12)}
  .log-rec.loading{opacity:.4;pointer-events:none}
  .log-block{
    font-size:max(9.5px,var(--piso-tipo,9.5px));font-weight:700;letter-spacing:.06em;text-transform:uppercase;
    color:#FF7A74;background:rgb(240 68 62 / .14);
    border:1px solid rgb(240 68 62 / .35);
    padding:3px 7px;border-radius:7px;
  }

  /* linha de detalhe das requisições ao vivo (IP, UA, referrer, status) */
  .log-detail{
    display:flex;flex-wrap:wrap;align-items:center;gap:4px 6px;
    margin-top:3px;font-size:10px;color:var(--ink-3);line-height:1.25;
  }
  .log-detail .ld-sep{opacity:.5}
  .log-detail .ld-ip{
    font-family:var(--mono, ui-monospace, SFMono-Regular, Menlo, monospace);
    color:var(--ink-2);font-size:10.5px;
  }
  .log-detail .ld-ua{font-style:italic}
  .log-detail .ld-ref{max-width:140px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .log-detail .ld-status{color:#FF7A74;font-weight:700}
  .log-loc .ld-src{
    display:inline-block;font-size:max(9.5px,var(--piso-tipo,9.5px));font-weight:700;letter-spacing:.06em;
    text-transform:uppercase;padding:2px 6px;border-radius:6px;margin-right:6px;
    vertical-align:1px;
  }
  .log-loc .ld-src-direto{
    color:#E8A33A;background:rgb(232 163 58 / .14);border:1px solid rgb(232 163 58 / .35);
  }
  .log-loc .ld-note{font-size:max(10px,var(--piso-tipo,10px));font-weight:400;color:var(--ink-3);font-style:italic}

  /* ---------- canvas (funil) ---------- */
  [hidden]{display:none!important}
  #view-gravacoes{overflow:hidden}
  /* a margem negativa fazia o Canvas sangrar até a borda da tela (era o
     layout antigo, de canvas infinito). Agora ele segue a mesma coluna das
     outras abas — só o recuo de baixo sai, pro funil aproveitar a altura. */
  #view-canvas{margin:0 0 -44px;position:relative}
  /* Canvas do Figma (.canvas-ws): coluna de 478 e o funil ao lado, ambos em
     fluxo. Era uma barra de 218px em position:absolute FLUTUANDO por cima do
     funil — daí os cards miúdos e o palco escondido atrás dela. */
  /* Quadro fixo de 1872 x 1384, nas medidas do Figma. O JS encaixa por largura
     E altura com zoom (fitCanvas), entao aqui tudo e 1:1 com o design: coluna
     de 478, vao de 24, cards de 300/656/288. */
  #view-canvas{
    display:grid;
    grid-template-columns:478px minmax(0,1fr);
    grid-template-rows:auto minmax(0,1fr);
    gap:24px;
    align-items:stretch;
    --k:1;
  }
  /* valor de partida (evita pisca antes do primeiro ajuste); o ajustaTrilho
     no JS reescreve --k com a altura medida */
  .canvas-side{overflow:visible;min-height:0}
  #view-canvas > .welcome{grid-column:1 / -1}
  .canvas-side{
    position:static;width:auto;z-index:10;
    display:flex;flex-direction:column;gap:calc(24px * var(--k));
    box-sizing:border-box;
  }
  /* alturas do rail no Figma */
  /* itens de coluna flex encolhem por padrão: com o trilho rolando, os três
     cards eram comprimidos e o painel de totais do Visitantes sumia */
  .canvas-side > .card{flex:none}
  #view-canvas .card.live  {height:300px}
  #view-canvas .card.fontes{height:656px;padding:8px 24px}
  #view-canvas .card.bots  {height:288px}
  /* no rail as quatro fontes empilham (430x82 cada) e o resumo fica embaixo */
  #view-canvas .fontes-body{flex-direction:column;gap:calc(16px * var(--k))}
  #view-canvas .fontes-col{flex:none;width:100%}
  #view-canvas .sources{
    grid-template-columns:minmax(0,1fr);
    grid-template-rows:repeat(4,minmax(0,1fr));
    height:calc(370px * var(--k));gap:calc(12px * var(--k));
  }
  #view-canvas .src-name,
  #view-canvas .src-card b,
  #view-canvas .src-pct{font-size:calc(18px * var(--k))}
  #view-canvas .src-card.fb .src-name,#view-canvas .src-card.dir .src-name,
  #view-canvas .src-card.g  .src-name,#view-canvas .src-card.ig  .src-name,
  #view-canvas .src-card.fb b,#view-canvas .src-card.dir b,
  #view-canvas .src-card.g  b,#view-canvas .src-card.ig  b,
  #view-canvas .src-card.fb .src-pct,#view-canvas .src-card.dir .src-pct,
  #view-canvas .src-card.g  .src-pct,#view-canvas .src-card.ig  .src-pct{font-size:calc(18px * var(--k))}
  /* .rail-summary: 430x200, dois cartões de 94 (sem Tempo médio) */
  #view-canvas .resumo{
    width:100%;flex-direction:column;align-self:auto;
    height:calc(200px * var(--k));gap:calc(12px * var(--k));
  }
  #view-canvas .resumo > .src{flex:1 0 0}
  .canvas-side::-webkit-scrollbar{display:none}
  .cs-card{
    flex:none;
    background:
      linear-gradient(180deg,rgb(31 31 30 / .94),rgb(20 20 19 / .94)) padding-box,
      linear-gradient(180deg,rgb(255 255 255 / .12),rgb(255 255 255 / .02)) border-box;
    border:1px solid transparent;border-radius:18px;
    padding:17px;
    box-shadow:0 18px 36px -18px rgb(0 0 0 / .7);
    backdrop-filter:blur(8px);
  }
  .cs-card[data-log]{cursor:pointer}
  .cs-src{transition:translate .08s,filter .08s,box-shadow .08s}
  .cs-src:hover{
    translate:3px 0;
    filter:brightness(1.12);
    box-shadow:inset 0 1px 0 rgb(255 255 255 / .22),0 8px 18px -8px rgb(0 0 0 / .6);
  }
  .cs-title{
    font-size:12px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;
    color:var(--ink-2);margin-bottom:12px;
  }
  .cs-live{display:flex;align-items:center;gap:12px}
  .cs-live b{font-size:38px;font-weight:800;line-height:1}
  .cs-chart{height:64px;margin-top:12px}
  .cs-chart svg{display:block;width:100%;height:100%}
  .cs-mini{display:flex;gap:12px;margin-top:10px;font-size:11.5px;color:var(--ink-3);flex-wrap:wrap}
  .cs-mini b{color:var(--ink);font-size:12.5px}
  .cs-mini .down{color:var(--accent);font-weight:700}
  .cs-srcs{display:flex;flex-direction:column;gap:7px}
  /* Rail do Canvas: os mesmos cards de fonte da Overview, só mais baixos
     (o design chama isso de .rail-srcs — "76 em vez de 100: quatro cards
     empilhados não cabem na altura original"). Mesma composição: blob da
     marca à esquerda, véu, logo grande à direita e fade. */
  .cs-src{
    display:flex;align-items:center;gap:9px;
    position:relative;overflow:hidden;clip-path:inset(0 round 11px);
    padding:14px 12px;border-radius:11px;color:#FFF;
    font-size:13px;font-weight:700;
    background-color:var(--card);
    background-image:var(--blobs,none);
    background-repeat:no-repeat;
  }
  .cs-src::before{content:"";position:absolute;inset:0;pointer-events:none;z-index:1;background:rgb(0 0 0 / .5)}
  .cs-src::after{
    content:"";position:absolute;inset:0;pointer-events:none;z-index:3;
    background:linear-gradient(to right,rgb(0 0 0 / 0) 57%,#000 100%);
  }
  .cs-src > *{position:relative;z-index:4}
  .cs-wm{
    position:absolute;left:auto;right:-4%;bottom:auto;top:50%;transform:translateY(-50%);
    width:auto;height:112%;z-index:2;
    fill:rgb(255 255 255 / .9);
    pointer-events:none;
  }
  /* o logo real substitui o desenho monocromático nas quatro marcas */
  /* card do rail é curto e estreito: com a altura da Overview o logo cobria o
     percentual. Ancorado a 74% e em 84% da altura, o texto fica livre. */
  .cs-logo{
    position:absolute;left:74%;right:auto;top:50%;transform:translateY(-50%);
    width:auto;height:84%;max-width:none;max-height:none;
    object-fit:contain;display:block;pointer-events:none;z-index:2;
  }
  .cs-src::after{background:linear-gradient(to right,rgb(0 0 0 / 0) 50%,#000 100%)}
  .cs-src.dk .cs-wm{fill:rgb(255 255 255 / .06)}
  .cs-src b{margin-left:auto;font-size:13.5px}
  .cs-src em{font-style:normal;font-size:11.5px;color:rgb(255 255 255 / .75)}
  /* mesmas cores de blob da Overview */
  .cs-src.g{--blobs:
    radial-gradient(38% 60% at 6% 4%,  #3DDC84 0%,rgb(61 220 132 / 0) 70%),
    radial-gradient(42% 66% at 22% -6%,#FCCC00 0%,rgb(252 204 0 / 0) 70%),
    radial-gradient(40% 64% at 20% 30%,#3086FF 0%,rgb(48 134 255 / 0) 70%)}
  .cs-src.ig{--blobs:
    radial-gradient(40% 62% at 4% 22%, #FFCD0A 0%,rgb(255 205 10 / 0) 70%),
    radial-gradient(38% 58% at 24% -4%,#CE1E88 0%,rgb(206 30 136 / 0) 70%)}
  .cs-src.dir{--blobs:
    radial-gradient(40% 62% at 4% 22%, #E7C7A3 0%,rgb(231 199 163 / 0) 70%),
    radial-gradient(38% 58% at 24% -4%,#7C30FF 0%,rgb(124 48 255 / 0) 70%)}
  .cs-src.fb{--blobs:
    radial-gradient(40% 62% at 4% 22%, #FFFFFF 0%,rgb(255 255 255 / 0) 70%),
    radial-gradient(38% 58% at 24% -4%,#3086FF 0%,rgb(48 134 255 / 0) 70%)}
  .cs-src.dk{--blobs:none;background-color:var(--card-2)}
  .cs-src.dk::before{background:none}
  .cs-src.dk::after{background:none}
  .cs-split{display:flex;justify-content:space-between;gap:10px;font-size:11px;color:var(--ink-2);margin-top:10px}
  .cs-split b{color:var(--ink);font-size:12px}
  @media (prefers-reduced-motion:no-preference){
    .cs-card{animation:csIn .2s cubic-bezier(.2,.7,.3,1) both}
    .cs-card:nth-child(2){animation-delay:.04s}
    .cs-card:nth-child(3){animation-delay:.08s}
    @keyframes csIn{from{opacity:0;transform:translateX(-18px)}to{opacity:1;transform:none}}
  }
  /* O Canvas era full-bleed (padding zerado), herança da barra lateral
     flutuante. Com o layout do Figma — faixa de titulo + trilho + funil em
     fluxo — ele usa o mesmo recuo do resto do app, senão o trilho cola na
     borda e a faixa fica escondida sob a topbar fixa. */
  body.canvas-mode .shell{max-width:none}
  /* altura medida a partir da topbar real e do recuo do body, senão a barra
     .fn-ctrl (ancorada no rodapé) cai fora da tela — media 1318px numa
     viewport de 1300 */
  .canvas-wrap{
    overflow:hidden;height:100%;min-height:360px;
    cursor:grab;touch-action:none;
  }
  .canvas-wrap.panning{cursor:grabbing}
  /* travado: nada de arrastar nem de cursor sugerindo que dá */
  .canvas-wrap.travado{cursor:default}
  .canvas-wrap.travado .fnode{cursor:default}
  /* O .funnel do Figma não tem fundo nenhum — o funil flutua sobre a cor da
     página. Aqui havia uma grade de pontos e duas lavagens de cor (azul no
     canto de cima, roxo no de baixo) que não existem no design. */
  .canvas-wrap{background:var(--bg)}
  /* .funnel-stage do Figma: palco fixo de 1360x580 centrado na área, e não
     um canvas infinito ancorado no canto — era daí os nós saírem pela direita
     ("Clique no anúncio" ficava fora da tela). O pan/zoom continua valendo. */
  .fcanvas{
    position:relative;transform-origin:0 0;
    width:1360px;height:580px;flex:none;
  }
  /* sem centralizar por flex: quem posiciona o palco é o transform do
     enquadrar (applyView). As duas coisas juntas se somavam e jogavam o
     funil pro rodapé da área. */
  #fsvg{position:absolute;inset:0;width:100%;height:100%}
  .flow-dot{filter:drop-shadow(0 0 5px currentColor)}
  @media (prefers-reduced-motion:reduce){.flow-dot{display:none}}
  @media (prefers-reduced-motion:no-preference){
    .fcanvas.entering .fnode{animation:nodeIn .2s cubic-bezier(.2,.7,.3,1) both}
    @keyframes nodeIn{
      from{opacity:0;transform:scale(.7) translateY(14px)}
      to{opacity:1;transform:none}
    }
    .fcanvas.entering .flow-dot{animation:dotIn .1s .2s both}
    @keyframes dotIn{from{opacity:0}to{opacity:1}}
  }

  /* .fn-node do Figma: mesma textura diagonal dos painéis, sem moldura */
  .fnode{
    position:absolute;z-index:2;cursor:grab;user-select:none;touch-action:none;
    display:flex;align-items:center;gap:14px;
    padding:12px 16px;border-radius:12px;
    background-image:var(--stripes),var(--panel-grad);
    background-color:var(--card);
    border:0;
    box-shadow:0 10px 26px rgb(0 0 0 / .45);
    transition:box-shadow .08s;
  }
  .fnode:hover{box-shadow:0 16px 32px -16px rgb(0 0 0 / .7),0 0 30px -10px var(--node-c)}

  /* ---- anel de luz varrendo a borda quando o nó recebe número novo ----
     (design: fnFill). A faixa é uma máscara de 300% que desliza da direita
     para a esquerda, então a luz "preenche" o contorno em vez de piscar. */
  .fn-ring{
    position:absolute;inset:0;border-radius:12px;pointer-events:none;z-index:3;
    border:1.8px solid var(--node-c);
    filter:drop-shadow(0 0 6px var(--node-c));
    opacity:0;
    --faixa:linear-gradient(90deg,transparent 0 31%,#000 35% 65%,transparent 69% 100%);
    -webkit-mask-image:var(--faixa);        mask-image:var(--faixa);
    -webkit-mask-size:300% 100%;            mask-size:300% 100%;
    -webkit-mask-repeat:no-repeat;          mask-repeat:no-repeat;
    -webkit-mask-position:100% 0;           mask-position:100% 0;
  }
  .fnode.lit .fn-ring{animation:fnFill 1.9s cubic-bezier(.4,0,.45,1)}
  @keyframes fnFill{
    0%  {opacity:1;-webkit-mask-position:100% 0;mask-position:100% 0}
    100%{opacity:1;-webkit-mask-position:0% 0;  mask-position:0% 0}
  }
  @media (prefers-reduced-motion:reduce){
    .fnode.lit .fn-ring{animation:none}
  }
  .fnode.dragging{cursor:grabbing;z-index:5}
  .fnode::before,.fnode::after{
    content:"";position:absolute;top:50%;translate:0 -50%;
    width:7px;height:7px;border-radius:50%;
    background:var(--node-c);
  }
  .fnode::before{left:-3.5px}
  .fnode::after{right:-3.5px}
  .n-fb::before,.n-dir::before,.n-g::before,.n-ig::before{display:none}
  .n-bounce::after,.n-clique::after,.n-filtrados::after{display:none}
  /* "ícone solto, sem pastilha atrás" (.ico-free do Figma): o quadrado
     colorido não existe no design */
  .fnode-ico{
    width:34px;height:34px;border-radius:0;flex:none;
    display:grid;place-items:center;color:var(--node-c);
    background:none;box-shadow:none;
  }
  /* .ico-free do Figma: 34 na linha, 38 na coluna, e a imagem preenche a
     caixa (as quatro origens usam a logo real da marca, como no design) */
  .fnode-ico svg,.fnode-ico img{width:100%;height:100%;object-fit:contain;display:block}
  .fnode.vert .fnode-ico{width:38px;height:38px}
  .fnode-txt{display:grid;gap:2px;text-align:left}
  .fnode[style*="width"]{box-sizing:border-box}
  .fnode.vert{
    flex-direction:column;gap:8px;
    padding:14px 18px;text-align:center;
  }
  .fnode.vert{flex-direction:column;align-items:center;justify-content:center;gap:9px;padding:18px 20px}
  .fnode.vert .fnode-txt{text-align:center;justify-items:center;gap:2px}
  .fnode.vert .fnode-ico{width:38px;height:38px;border-radius:11px}
  .fnode.vert .fnode-ico svg{width:18px;height:18px}
  .fnode-page{
    display:flex;flex-direction:column;gap:5px;align-items:flex-start;
    width:60px;height:44px;border-radius:10px;flex:none;
    background:var(--card-2);padding:7px;
    box-shadow:inset 0 1px 0 rgb(255 255 255 / .08);
  }
  .fnode-page i{width:100%;height:17px;border-radius:4px;background:var(--node-c);opacity:.28}
  .fnode-page u{width:55%;height:6px;border-radius:3px;background:var(--node-c)}
  .fnode.vert b{font-size:18px}
  /* .fn-node do Figma: rótulo 12/700 com espaçamento .6, valor 23/700 e
     legenda 11/400 — era 9.5/16/9, um terço menor que o design */
  /* O funil e um palco de tamanho FIXO (1360x580, medida do Figma) que o
     enquadrar escala por transform. Por isso a tipografia dele usa os valores
     absolutos do design e NAO multiplica por --k: multiplicar duas vezes
     deixava o rotulo em 7,7px a 1280 (a auditoria pegou 23 elementos abaixo
     de 9px), alem de desalinhar o texto do tamanho fixo do no. */
  .fnode-name{
    font-size:12px;font-weight:700;letter-spacing:.6px;text-transform:uppercase;
    color:var(--slate-lit);white-space:nowrap;line-height:1.5;
  }
  .fnode b{font-size:23px;font-weight:700;line-height:1.15}
  .fnode-hint{
    display:block;margin-top:5px;
    font-size:11px;font-weight:400;color:var(--ink-3);
    white-space:nowrap;letter-spacing:.02em;
  }

  .n-fb{--node-c:#1877F2;--node-g:linear-gradient(180deg,#2E86F5,#1B63D6)}
  .n-dir{--node-c:#F59E0B;--node-g:linear-gradient(180deg,#F5A623,#D97E0F)}
  .n-g{--node-c:#3086FF;--node-g:linear-gradient(180deg,#5B93F2,#3A6FD8)}
  .n-ig{--node-c:#CE1E88;--node-g:linear-gradient(180deg,#E8437C,#C22762)}
  .n-bots{--node-c:#8A8F99;--node-g:linear-gradient(180deg,#4A4A48,#333331)}
  .n-landing{--node-c:#F0443E;--node-g:linear-gradient(180deg,#F0443E,#A5140C)}
  .n-eng{--node-c:#3DDC84;--node-g:linear-gradient(180deg,#3DDC84,#0FBC5F)}
  .n-bounce{--node-c:#8A8F99;--node-g:linear-gradient(180deg,#4A4A48,#333331)}
  .n-anuncio{--node-c:#F0443E;--node-g:linear-gradient(180deg,#F0443E,#A5140C)}
  .n-clique{--node-c:#3DDC84;--node-g:linear-gradient(180deg,#3DDC84,#0FBC5F)}
  .n-filtrados{--node-c:#F0443E;--node-g:linear-gradient(180deg,#F0443E,#A5140C)}

  /* ---------- modal de logs ---------- */
  .modal-veil{
    position:fixed;inset:0;z-index:60;
    background:rgb(0 0 0 / .55);
    backdrop-filter:blur(6px);
    display:flex;align-items:center;justify-content:center;
    padding:24px;
  }
  .modal{
    position:relative;
    width:min(540px,100%);
    max-height:min(620px,88vh);
    display:flex;flex-direction:column;
    background:
      var(--card) padding-box,
      linear-gradient(180deg,rgb(255 255 255 / .14),rgb(255 255 255 / .03)) border-box;
    border:1px solid transparent;border-radius:var(--r-xl);
    padding:22px;
    box-shadow:0 40px 90px -30px rgb(0 0 0 / .85);
  }
  @media (prefers-reduced-motion:no-preference){
    .modal{animation:modalIn .12s cubic-bezier(.2,.7,.3,1)}
    @keyframes modalIn{from{opacity:0;transform:translateY(16px) scale(.97)}to{opacity:1;transform:none}}
  }
  .modal-x{
    position:absolute;top:16px;right:16px;
    width:32px;height:32px;border-radius:var(--r-full);
    border:1px solid var(--line);background:none;cursor:pointer;
    display:grid;place-items:center;color:var(--ink-2);
  }
  .modal-x:hover{color:var(--ink);border-color:var(--line-2)}
  .modal-x svg{width:13px;height:13px}
  .modal-tit{font-size:16px;font-weight:700;padding-right:44px}
  .modal-sub{font-size:12px;color:var(--ink-3);margin-top:3px}
  /* A aba de visitantes carrega tres KPIs, distribuicao e 30 sessoes —
     nao cabe nos 540px do modal de log simples. A classe entra so nela pra
     nao esticar os modais de bots e fontes, que continuam listas curtas. */
  .modal.wide{width:min(860px,100%);max-height:min(760px,92vh)}

  .ses-stats{margin-top:14px;display:flex;flex-direction:column;gap:12px}
  .ses-kpis{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:10px}
  .ses-kpi{
    position:relative;padding:12px 14px;border-radius:12px;
    background:var(--card-2);
    border:1px solid rgb(255 255 255 / .06);
  }
  .ses-kpi .k-lbl{font-size:11px;font-weight:700;color:var(--muted);text-transform:uppercase;letter-spacing:.06em}
  .ses-kpi .k-val{font-size:26px;font-weight:800;letter-spacing:-.02em;line-height:1.15;margin-top:4px}
  .ses-kpi .k-sub{font-size:11.5px;color:var(--muted);margin-top:2px}
  .ses-kpi.viva .k-val{color:var(--green)}
  .k-dot{
    position:absolute;top:12px;right:14px;width:8px;height:8px;border-radius:50%;
    background:var(--green);box-shadow:0 0 0 0 rgb(61 220 132 / .55);animation:pulseDot .8s infinite;
  }
  @keyframes pulseDot{70%{box-shadow:0 0 0 9px rgb(61 220 132 / 0)}100%{box-shadow:0 0 0 0 rgb(61 220 132 / 0)}}

  .ses-dist{display:flex;flex-direction:column;gap:6px}
  .ses-dist-tit{font-size:11px;font-weight:700;color:var(--muted);text-transform:uppercase;letter-spacing:.06em}
  .dist-row{display:flex;align-items:center;gap:10px}
  .dist-lbl{font-size:11.5px;color:var(--muted);width:56px;flex:none;text-align:right}
  .dist-bar{flex:1;height:8px;border-radius:6px;background:#232321;overflow:hidden}
  /* display:block e obrigatorio: span e inline e ignora width — a barra
     ficaria sempre vazia, com o trilho parecendo o proprio preenchimento */
  .dist-fill{display:block;height:100%;border-radius:6px;background:linear-gradient(90deg,#3086FF,#7C30FF);transition:width .12s}
  .dist-n{font-size:11.5px;color:var(--muted);width:56px;flex:none}

  .ses-listtit{font-size:11px;font-weight:700;color:var(--muted);text-transform:uppercase;letter-spacing:.06em;margin-top:2px}
  .log-piso{
    font-size:10px;font-weight:700;border-radius:4px;padding:2px 6px;
    background:rgb(255 255 255 / .07);color:var(--muted);
  }

  /* Linha de sessao: quatro niveis de informacao em vez dos dois do log
     simples — duracao, link, parametros e origem. Grid proprio porque o
     .log so tem espaco para titulo + subtitulo. */
  .ses-row{
    display:flex;align-items:flex-start;gap:12px;
    padding:12px 4px;border-bottom:1px solid rgb(255 255 255 / .05);
  }
  .ses-row:last-child{border-bottom:0}
  .ses-row .log-ico{margin-top:2px;flex:none}
  .ses-main{flex:1;min-width:0;display:flex;flex-direction:column;gap:4px}
  .ses-l1{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
  .ses-l1 b{font-size:15px;font-weight:800;letter-spacing:-.01em}
  .ses-pags,.ses-fonte{
    font-size:10.5px;font-weight:700;border-radius:4px;padding:2px 7px;
    background:rgb(255 255 255 / .07);color:var(--muted);
  }
  /* quebra no meio do caminho, nao so no fim: URL longa sem espacos nao
     quebraria sozinha e estouraria a largura */
  .ses-link{font-size:12px;color:var(--muted);word-break:break-all;line-height:1.35}
  .ses-chips{display:flex;flex-wrap:wrap;gap:5px;margin-top:1px}
  .ses-chip{
    display:inline-flex;align-items:center;gap:5px;
    font-size:10.5px;font-family:var(--mono,ui-monospace,monospace);
    border-radius:5px;padding:2px 7px;
    background:rgb(240 68 62 / .12);color:#FF7A74;
    border:1px solid rgb(240 68 62 / .3);
    max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
  }
  .ses-chip i{font-style:normal;opacity:.6;font-size:max(9.5px,var(--piso-tipo,9.5px));text-transform:uppercase;letter-spacing:.04em}
  .ses-chip.mais{background:rgb(255 255 255 / .06);color:var(--muted);border-color:transparent}
  .ses-l3{display:flex;gap:10px;flex-wrap:wrap;font-size:11px;color:var(--muted);margin-top:1px}
  .ses-ip{font-family:var(--mono,ui-monospace,monospace);opacity:.7}
  .ses-meta{display:flex;align-items:center;gap:8px;flex:none;padding-top:3px}

  .modal-logs{flex:1;min-height:0;overflow-y:auto;margin-top:10px}
  .modal-logs::-webkit-scrollbar{width:8px}
  .modal-logs::-webkit-scrollbar-thumb{background:#2A2A28;border-radius:8px}
  .log-ico.g{background:linear-gradient(180deg,#5B93F2,#3A6FD8);font-weight:800;font-size:13px}
  .log-ico.ig{background:linear-gradient(180deg,#E8437C,#C22762)}
  .log-allow{
    font-size:max(9.5px,var(--piso-tipo,9.5px));font-weight:700;letter-spacing:.06em;text-transform:uppercase;
    color:var(--green);background:rgb(61 220 132 / .12);
    border:1px solid rgb(61 220 132 / .3);
    padding:3px 7px;border-radius:7px;
  }

  /* ---------- login / dados reais ---------- */
  .login-inp{
    width:100%;margin-top:10px;padding:11px 14px;border-radius:12px;
    border:1px solid var(--line-2);background:var(--card-2);color:var(--ink);
    font:inherit;font-size:13px;outline:none;
  }
  .login-skip{
    width:100%;margin-top:10px;background:none;border:none;cursor:pointer;
    font:inherit;font-size:11px;color:var(--ink-3);
  }
  .login-skip:hover{color:var(--ink-2)}
  .site-fallback{
    width:40px;height:40px;border-radius:11px;
    display:grid;place-items:center;
    background:var(--card-2);color:var(--ink);font-weight:800;font-size:17px;
  }
  .site-fallback-empty{
    position:relative;
    border:1px solid rgb(255 255 255 / .16);
    background:linear-gradient(145deg,#252A33,#171A20);
    box-shadow:inset 0 1px 0 rgb(255 255 255 / .08);
  }
  .site-fallback-empty::before{
    content:"";width:16px;height:16px;border:1px solid rgb(255 255 255 / .3);
    border-radius:50%;
  }
  .site-fallback-empty::after{
    content:"";position:absolute;width:12px;height:1px;
    background:rgb(255 255 255 / .28);transform:rotate(-35deg);
  }

  /* ---------- loading / skeletons ---------- */
  /* Enquanto a API responde, todo lugar que vai receber um número real vira
     um bloco de shimmer em vez do travessão "—" estático. Assim o dashboard
     não dá a sensação de bugado/flick quando o dado real chega: cada bloco
     transita de "carregando" -> valor, nunca de mock -> real. */
  @keyframes hawkShimmer{
    0%{background-position:200% 0}
    100%{background-position:-200% 0}
  }
  body.hawk-loading [data-bind].hawk-skel,
  .hawk-skel-fig{
    color:transparent!important;
    background:linear-gradient(90deg,
      rgb(255 255 255 / .07) 25%,
      rgb(255 255 255 / .16) 50%,
      rgb(255 255 255 / .07) 75%);
    background-size:200% 100%;
    animation:hawkShimmer 1.4s linear infinite;
    border-radius:5px;
    user-select:none;
  }
  /* traços do sparkline decorativos: diminui até o dado real chegar */
  body.hawk-loading .spark-svg.hawk-skel .sp-line,
  body.hawk-loading .spark-svg.hawk-skel .sp-area,
  body.hawk-loading .spark-svg.hawk-skel .sp-dot{
    opacity:.18;
    transition:opacity .1s;
  }
  /* splitbar de bots: deixa o comprimento real aparecer só com o dado */
  body.hawk-loading .splitbar.hawk-skel .seg{
    background:linear-gradient(90deg,
      rgb(255 255 255 / .06) 25%,
      rgb(255 255 255 / .12) 50%,
      rgb(255 255 255 / .06) 75%);
    background-size:200% 100%;
    animation:hawkShimmer 1.4s linear infinite;
    border:none;
    box-shadow:none;
  }
  /* card de site skeleton */
  .site.hawk-skel .site-logo,
  .site.hawk-skel .site-name,
  .site.hawk-skel .site-stats div{
    position:relative;
    overflow:hidden;
  }
  .site.hawk-skel .site-logo img,
  .site.hawk-skel .site-fallback{display:none}
  .site.hawk-skel .site-logo::before{
    content:"";display:block;width:100%;height:100%;border-radius:8px;
    background:linear-gradient(90deg,#222220 25%,#2e2e2b 50%,#222220 75%);
    background-size:200% 100%;animation:hawkShimmer 1.4s linear infinite;
  }
  .site.hawk-skel .site-name::before{
    content:"";display:block;width:70%;height:11px;border-radius:5px;
    background:linear-gradient(90deg,#222220 25%,#2e2e2b 50%,#222220 75%);
    background-size:200% 100%;animation:hawkShimmer 1.4s linear infinite;
  }
  .site.hawk-skel .site-stats div span{display:none}
  .site.hawk-skel .site-stats div b{
    color:transparent!important;
    background:linear-gradient(90deg,#222220 25%,#2e2e2b 50%,#222220 75%);
    background-size:200% 100%;animation:hawkShimmer 1.4s linear infinite;
    border-radius:5px;display:inline-block;width:38px;text-align:right;
  }
  .site.hawk-skel .site-name{border-bottom-color:rgb(255 255 255 / .04)}
  /* linha de log skeleton */
  .log.hawk-skel .log-ico{
    background:linear-gradient(90deg,#222220 25%,#2e2e2b 50%,#222220 75%);
    background-size:200% 100%;animation:hawkShimmer 1.4s linear infinite;
  }
  .log.hawk-skel .log-ico svg{display:none}
  .log.hawk-skel .log-loc,
  .log.hawk-skel .log-url,
  .log.hawk-skel .log-time{
    color:transparent!important;border:none;background:none;
  }
  .log.hawk-skel .log-loc::before,
  .log.hawk-skel .log-url::before{
    content:"";display:block;border-radius:5px;
    background:linear-gradient(90deg,#222220 25%,#2e2e2b 50%,#222220 75%);
    background-size:200% 100%;animation:hawkShimmer 1.4s linear infinite;
  }
  .log.hawk-skel .log-loc::before{width:90px;height:11px}
  .log.hawk-skel .log-url::before{width:140px;height:10px;margin-top:4px}
  .log.hawk-skel .log-block{display:none}
  .log.hawk-skel .log-time::before{
    content:"";display:block;width:28px;height:10px;border-radius:5px;
    background:linear-gradient(90deg,#222220 25%,#2e2e2b 50%,#222220 75%);
    background-size:200% 100%;animation:hawkShimmer 1.4s linear infinite;
  }
  @media (prefers-reduced-motion:reduce){
    .hawk-skel-fig,body.hawk-loading [data-bind].hawk-skel,
    .site.hawk-skel *,.log.hawk-skel *{
      animation:none;background:rgb(255 255 255 / .08);
    }
  }

  /* ---------- misc ---------- */
  /* anel de foco em azul: o vermelho passou a significar erro/bloqueio, e um
     contorno vermelho em campo focado lia como validação falhando */
  :focus-visible{outline:2px solid var(--blue);outline-offset:2px;border-radius:6px}
  button{-webkit-tap-highlight-color:transparent}

  @media (prefers-reduced-motion:no-preference){
    .card{animation:rise .14s cubic-bezier(.2,.7,.3,1) both}
    .card.live{animation-delay:.02s}
    .fontes{animation-delay:.04s}
    .card.bots{animation-delay:.06s}
    .trend{animation-delay:0s}
    .rail .card{animation-delay:.08s}
    .site{
      animation:rise .08s ease-out both;
      animation-delay:0s;
    }
    .logs .log{animation:rise .08s cubic-bezier(.2,.7,.3,1) both;animation-delay:calc(.06s + .01s*var(--li,0))}
    /* entrada de uma requisição nova (51:778) — sem realce de cor, só o
       movimento. Sobrepõe o `rise` da carga inicial nas linhas recém-chegadas. */
    @keyframes reqin{
      from{opacity:0;transform:translateY(-12px) scale(.985)}
      to  {opacity:1;transform:none}
    }
    .logs .log.is-new{animation:reqin .55s cubic-bezier(.22,.61,.36,1);animation-delay:0s}
    @keyframes rise{from{opacity:0;transform:translateY(16px) scale(.98)}to{opacity:1;transform:none}}
  }

  @media (max-width:1120px){
    /* aqui a grade empilha: as alturas do canvas do Figma saem de cena e tudo
       volta a crescer com o conteúdo */
    .grid{grid-template-columns:repeat(2,minmax(0,1fr));grid-template-rows:auto}
    .main > .card.fontes,
    .main > .card.bots{height:auto;align-self:auto}
    .sources{height:auto;align-self:auto}
    .card.bots{grid-column:auto;grid-row:auto}
    .fontes{grid-column:auto;grid-row:auto}
    .trend{grid-column:1 / -1;grid-row:auto}
    .rail{grid-column:1 / -1;grid-row:auto;height:auto;min-height:0}
    .rail .card{flex:none}
    .logs{overflow-y:visible}
    .sites{grid-template-columns:repeat(4,minmax(0,1fr))}
    /* O #view-overview fixa --k:1 porque acima de 1120 ele e um canvas de 1872
       escalado por zoom. Daqui pra baixo o fitOverview DESLIGA o zoom, e o
       --k:1 passava a significar "desenhe em tamanho de projeto numa tela bem
       menor": o texto dos cards de fonte saia a 24px num card de 154px e era
       comido pelo overflow. Aqui ele volta a acompanhar a largura da tela. */
    #view-overview{--k:var(--k-tela)}
    /* A coluna de métricas ao lado das fontes só cabe enquanto o card tem a
       largura do Figma. Abaixo de 1120 o card de fonte encolhia até a
       porcentagem (e depois o próprio número) começar DEPOIS da borda direita
       e ser 100% comida pelo overflow:hidden do card. Empilhar o bloco resolve
       na raiz; as duas linhas do .resumo impedem que ele colapse ao virar
       item de coluna. */
    .fontes-body{flex-direction:column;gap:calc(16px * var(--k))}
    .resumo{width:100%;height:auto}
    .resumo > .src{flex:none;min-height:calc(84px * var(--k))}
  }
  /* Sessoes vira cartao ja em 1000px, nao em 820. Entre 821 e 980 a tabela
     nao cabe: as colunas sao todas de largura rigida, a linha transbordava
     na horizontal e o selo "Ao vivo" era cortado pela lista. O layout de
     cartao abaixo ja existia — so estava tarde demais. */
  @media (max-width:1000px){
    .sv-cols{display:none}
    .sv-row{height:auto;flex-wrap:wrap;gap:8px 10px;padding:12px;align-items:center}
    .sv-row .dev{width:34px;height:34px;border-radius:10px;order:0}
    .sv-row .dev svg{width:16px;height:16px}
    .sv-site{width:auto;flex:1 1 auto;min-width:0;order:1}
    .c-live{width:auto;order:2}
    .c-loc,.c-url,.c-ref{width:100%;flex:1 1 100%;min-width:0;order:3}
    .c-pag,.c-time{width:auto;order:4;text-align:left}
    .c-pag::before{content:"páginas ";font-size:10px;color:var(--ink-3);font-weight:400}
    .c-time::before{content:"na página ";font-size:10px;color:var(--ink-3);font-weight:400}
    .sv-pag,.sv-time{font-size:13px}
  }
  @media (max-width:820px){
    .sites{grid-template-columns:repeat(2,minmax(0,1fr))}
    .sources{grid-template-columns:repeat(2,minmax(0,1fr));grid-template-rows:auto;grid-auto-flow:row}
    .sources > .src{grid-area:auto !important}
    .src-card{height:60px}
    /* Card estreito (2 colunas): com 116% de altura o logo avançava por cima
       do número. Recua a âncora para 78% e reduz a altura — o texto volta a
       ter a metade esquerda só para ele. */
    .src-logo{left:78%;height:88%}
    .src-card::after{background:linear-gradient(to right,rgb(0 0 0 / 0) 52%,#000 100%)}

    /* Sessões: a tabela em colunas não cabe num telefone. Vira cartão — o
       cabeçalho de colunas some e cada linha empilha as informações, com o
       site e o selo "ao vivo" na primeira faixa. */
    .sv-panel{padding:16px;border-radius:16px}
    .sv-head{flex-direction:column;align-items:flex-start;gap:6px}
    .sv-head .hint{white-space:normal;font-size:11.5px}

    .site-search{width:100%}
    .nav{justify-content:flex-start}
  }
  /* ---------- header tablet/phone ---------- */
  @media (max-width:900px){
    /* A topbar mobile virou grade de TRÊS linhas (marca+ações, abas, seletor
       de sites) e passou a medir 197px, mas o recuo do body continuou nos 154
       de antes: a faixa de título ficava 43px por baixo dela. O JS já publica
       a altura real em --topbar-height; aqui só faltava consumir. */
    body{padding-top:var(--topbar-height,197px)}
    .topbar{
      display:grid;
      grid-template-columns:minmax(0,1fr) auto;
      align-items:center;
      gap:10px;
      height:auto;
      /* mesmo recuo lateral do body, senão a marca desalinha dos cards
         (a 768px dava 28 aqui contra 23 no body) */
      padding:12px var(--recuo,clamp(16px,3vw,44px));
      background:var(--nav);
      border-bottom:1px solid rgb(255 255 255 / .06);
    }
    .brand{min-width:0;gap:9px}
    .brand-name{font-size:clamp(15px,2.5vw,18px);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
    .vrule{display:none}
    .top-actions{grid-column:2;grid-row:1;gap:6px}
    .top-actions .iconbtn,.avatar{width:34px;height:34px}
    .date-filter-btn{width:34px;padding:0;justify-content:center}
    .date-filter-btn span{display:none}
    /* o recorte é um desenho de 278px pensado para a nav larga; no grid de
       três colunas ele não cabe, então a aba ativa volta a ser uma pílula */
    .nav-notch{display:none}
    /* a .nav ocupa UMA linha da topbar e quebra internamente em duas (4 abas
       em 3 colunas). O seletor de sites vem na linha seguinte — antes ele era
       filho da .nav e herdava o grid dela, agora precisa da própria linha. */
    .nav{
      grid-column:1 / -1;
      grid-row:2;
      display:grid;
      grid-template-columns:repeat(3,minmax(0,1fr));
      gap:7px;
      width:100%;
      height:auto;
      justify-content:initial;
    }
    .nav-pill{
      justify-content:center;
      min-width:0;
      height:auto;
      padding:9px 10px;
      font-size:12.5px;
      border-radius:var(--r-full);
    }
    .nav-pill svg{width:15px;height:15px}
    .nav-pill.active{
      width:auto;margin:0;
      background:var(--card-2);
    }
    .site-sel{
      grid-column:1 / -1;
      grid-row:3;
      justify-self:stretch;
    }
    .site-sel-btn{width:100%;justify-content:center;padding:10px 14px}
    .site-sel-dd{left:0;right:0;translate:0;width:auto}
    body.canvas-mode .canvas-wrap{height:100vh}
    .canvas-side{bottom:18px}
  }
  @media (max-width:560px){
    .grid{grid-template-columns:1fr}
  }

  /* ---------- telefone: conteúdo prioritário, sem canvas desktop espremido ---------- */
  @media (max-width:600px){
    html,body{max-width:100%;overflow-x:clip}
    body{
      /* mesmo caso da regra de 900px: este shorthand sobrescrevia o recuo e
         deixava 37,6px do título atrás da topbar */
      padding:var(--topbar-height,192px) 12px 28px;
      background-size:32px 32px,32px 32px,32px 32px,32px 32px,32px 32px;
    }
    .topbar{
      display:grid;
      grid-template-columns:minmax(0,1fr) auto;
      gap:10px;
      height:auto;
      padding:10px 12px;
      background:var(--nav);
      border-bottom:1px solid rgb(255 255 255 / .06);
    }
    .brand{min-width:0;gap:8px}
    .brand-mark{width:30px;height:30px;border-radius:9px}
    .brand-name{font-size:15px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
    .top-actions{grid-column:2;grid-row:1;gap:6px}
    /* avatar continua visível: é o único caminho para o logout */
    .top-actions .iconbtn:not(#syncBtn){display:none}
    .top-actions .iconbtn{width:38px;height:38px}
    .date-filter-btn{width:38px;height:38px}
    .date-filter-popover{position:fixed;top:calc(var(--topbar-height, 154px) + 8px);left:12px;right:12px;width:auto}
    .nav{
      grid-column:1 / -1;
      grid-row:2;
      display:grid;
      grid-template-columns:repeat(3,minmax(0,1fr));
      gap:7px;
      width:100%;
    }
    .nav-pill{
      justify-content:center;
      min-width:0;
      padding:9px 6px;
      font-size:12px;
    }
    .nav-pill svg{display:none}
    .site-sel{grid-column:1 / -1;justify-self:stretch}
    .site-sel-btn{width:100%;justify-content:center;padding:10px 14px}
    .site-sel-dd{
      position:fixed;
      top:142px;
      left:12px;
      right:12px;
      translate:none;
      width:auto;
      max-height:min(62vh,480px);
    }

    #view-overview > .grid{grid-template-columns:minmax(0,1fr)!important;gap:12px}
    .card{border-radius:22px;padding:13px}
    .card.bots,.fontes,.trend,.rail{grid-column:auto!important;grid-row:auto!important}
    .notch{top:0;right:0}
    .logs-btn{padding:8px 12px}
    .live-num{font-size:54px}
    .live-chart{height:46px}
    .mini-stats{gap:8px}
    .ms{padding-right:8px}
    .ms + .ms{padding-left:8px}
    .ms-l{font-size:clamp(8px,2.35vw,10px);letter-spacing:.04em}
    .ms b{font-size:18px}
    .sources{gap:8px}
    .src-card{height:68px}
    .src-name{font-size:12px}
    .src-row b{font-size:18px}
    .fontes-body{gap:10px}
    .trend-head{flex-wrap:wrap}
    .site-search{margin-top:10px}
    .sites{grid-template-columns:repeat(2,minmax(0,1fr));gap:9px;margin-top:10px}
    .site{min-height:0}
    .site-name{font-size:12px}
    .site-stats{grid-template-columns:1fr 1fr;gap:7px}
    .site-stats div:nth-child(n+3){display:none}

    #view-canvas,body.canvas-mode #view-canvas{margin:0 -12px -28px}
    .canvas-wrap,body.canvas-mode .canvas-wrap{height:calc(100vh - 132px);min-height:540px}
    .canvas-side{
      left:12px;right:12px;top:calc(var(--topbar-height, 154px) + 10px);bottom:auto;width:auto;
      flex-direction:row;overflow-x:auto;overflow-y:hidden;gap:8px;
      padding-top:0;padding-bottom:4px;
    }
    .cs-card{width:min(76vw,260px);max-height:205px}
    .canvas-controls{right:12px;bottom:12px}
    .canvas-controls .filterbtn{width:40px;height:40px}

    .modal-veil{align-items:flex-end;padding:0}
    .modal,.modal.wide{
      width:100%;
      max-height:88vh;
      border-radius:22px 22px 0 0;
      padding:20px 14px 14px;
    }
    .ses-kpis{grid-template-columns:1fr;gap:8px}
    .ses-row{padding:10px 0}
    .ses-meta{display:none}
  }

  /* Abaixo de 820 o trilho de 478 não deixa largura útil pro funil: os nós
     começavam a sair pela direita e a barra de zoom saía da tela. Aqui o
     Canvas empilha — trilho em cima, funil embaixo com altura própria. */
  @media (max-width:820px){
    #view-canvas{
      grid-template-columns:minmax(0,1fr);
      grid-template-rows:auto auto auto;
      height:auto;
    }
    .canvas-side{overflow:visible;max-height:none}
    .canvas-wrap{height:min(62vh,520px);min-height:340px}
  }

  /* Piso de legibilidade no trilho do Canvas. A coluna encolhe uniformemente
     pra caber sem rolagem, e nessa escala os rótulos de 12px do Figma caíam
     para 8,3px. Estes três são os menores da tela; travar em 9px custa menos
     de 1px de altura por linha e não desfaz o ajuste. */
  #view-canvas .ms-l,
  #view-canvas .bots-totals .k{font-size:max(9px,calc(12px * var(--k)))}

  /* Trilho estreito: os dois blocos de total passam a empilhar. Lado a lado,
     com o piso de 9px do rótulo, "PAGEVIEWS HOJE" não cabe em meia coluna de
     ~230px — era o que forçava a quebra de linha e estourava o card. */
  @media (max-width:1200px){
    #view-canvas .mini-stats{flex-direction:column;gap:calc(6px * var(--k))}
    #view-canvas .mini-stats > .ms{border-radius:8px}
    #view-canvas .ms + .ms{border-left:0;border-top:1px solid rgb(255 255 255 / .06)}
  }

  /* ---------- barra do canvas (.fn-ctrl do Figma) ---------- */
  .fn-ctrl{
    position:absolute;left:50%;transform:translateX(-50%);bottom:calc(26px * var(--k));z-index:6;
    display:flex;align-items:center;gap:calc(8px * var(--k));
    padding:calc(10px * var(--k)) calc(13px * var(--k));
    background:rgb(17 19 24 / .88);border:1px solid #262A33;border-radius:18px;
    box-shadow:0 12px 30px rgb(0 0 0 / .45);
    backdrop-filter:blur(8px);
  }
  .fn-ctrl button{
    width:calc(40px * var(--k));height:calc(40px * var(--k));
    border:0;border-radius:11px;background:transparent;color:var(--slate);
    display:flex;align-items:center;justify-content:center;cursor:pointer;padding:0;
    transition:background-color .15s ease,color .15s ease;
  }
  .fn-ctrl button svg{width:calc(22px * var(--k));height:calc(22px * var(--k))}
  .fn-ctrl button:hover{background:#1E222B;color:#fff}
  .fn-ctrl button.on{color:var(--blue)}
  .fn-ctrl .pct{
    min-width:calc(65px * var(--k));text-align:center;
    font-size:calc(14px * var(--k));color:var(--slate-lit);
    font-variant-numeric:tabular-nums;
  }
  .fn-ctrl .div{width:1px;height:calc(25px * var(--k));background:#2A2E37;margin:0 3px;flex:none}
  /* o design não tem gráfico no card de Visitantes em nenhuma das duas telas */
  #view-canvas .live-chart{display:none}

  /* ---- avatar da requisição no feed (67:1695) ----
     A logo da marca aparece solta, sem pastilha colorida atrás (é o
     .avatar-img do Figma). O fundo colorido fica só para o bot, que no
     design é o .bot-mark: vermelho translúcido com o glifo ">_". */
  .log-ico{background:none;box-shadow:none;overflow:hidden}
  .log-ico img{width:100%;height:100%;object-fit:contain;display:block}
  .log-ico.fb,.log-ico.ig,.log-ico.g,.log-ico.web{background:none}
  .log-ico.bot{
    background:rgb(240 68 62 / .13);border:1px solid rgb(240 68 62 / .3);
    font:700 max(13px,var(--piso-tipo,13px))/1 var(--font);color:#FF7A74;
  }
