/* Dashboard 2.0 — tokens + shell + componentes.
   Fonte: ../spec-design-system.md. Não duplicar valores fora daqui —
   páginas novas só consomem estas variáveis/classes. */

/* Tipografia única do Lucri DS V1 (1.MANUAL DA MARCA/index.html, sucessor
   do SYSTEM-DESIGNER-LUCRI.md): Inter em tudo, título e corpo. Substitui a
   migração anterior pro Instrument Sans (2026-09, mesma semana) — o SDS
   antigo foi superado pelo V1 code-first antes de rodar uma semana.
   @import aqui (não <link> por página) carrega em TODAS as 17 páginas de
   uma vez sem precisar editar cada HTML. */
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap');

:root {
  color-scheme: light;
  /* Superfície/tinta — realinhado ao visual da v1 (legacy/index.html): fundo
     "pearl" mais quente/escuro que o antigo off-white quase branco, pra
     cards se destacarem de verdade contra o fundo em vez de se fundir nele. */
  --page:        #e9e9e3;
  --surface:     #ffffff;
  --text-1:      #141414;
  --text-2:      #6b6b6b;
  --muted:       #ababab;
  --grid:        #d6d6d0;
  --baseline:    #bfbfb9;
  --border:      #d6d6d0;
  /* Lucri DS V1: card em repouso continua sem sombra (só borda) — mas
     dropdown/menu/tooltip/toast ganham --shadow-md, e hover de card
     interativo ganha --shadow-sm (equivalente ao --shadow-xs do V1).
     Valores literais do V1 (rgba sobre --night #010116). */
  --shadow-sm:   0 1px 2px rgba(1,1,22,.06);
  --shadow-md:   0 8px 24px rgba(1,1,22,.10);

  /* paleta categórica genérica — só páginas neutras (Home/Ajustes/Calculadora) */
  --c1: #2a78d6; --c2: #008300; --c3: #e87ba4; --c4: #eda100;
  --c5: #1baf7a; --c6: #eb6834; --c7: #4a3aa7; --c8: #e34948;

  /* marca oficial Lucri — usada só pra ação primária de UI (nav ativo, botão
     principal, seleção), nunca série de gráfico. Trocado do verde-limão
     "iris" (#c6f135, era a assinatura da v1) pro verde "Vivo Verde" #00EB85
     em 2026-09, testado antes isolado em instagram.html e depois adotado
     pro app inteiro. --lucri-iris manteve o nome histórico (renomear a
     variável tocaria ~20 usos em style.css sem ganho real) mas o hex por
     trás agora é o verde novo. Texto sempre --brand-accent-text (ink
     escuro): o verde é claro demais (L≈83% em OKLCH) pra passar contraste
     com texto branco — ver checagem abaixo. */
  --lucri-iris: #00EB85; --lucri-night: #141414;

  /* Escala "Vivo Verde" — gerada em OKLCH (não na ferramenta
     camaraux.com.br/ferramentas/gerador-paleta-cores desta vez: o
     algoritmo "Complementares" de lá, usado na escala Vivo Lima abaixo,
     deriva os tons escuros girando o matiz — pro lima isso ficou dentro da
     família oliva/amarelo por coincidência, mas pro verde (#00EB85, H≈154°)
     o giro completo saía azul e depois roxo/vinho nos tons 600-950, o que
     quebra a cara de "verde mais escuro". O algoritmo "Escala de
     luminosidade" da mesma ferramenta resolve a rotação de matiz mas
     também reposiciona a cor-base pro degrau mais próximo da sua
     luminosidade real (nesse caso ela caiu no 600, não no 500) — quebraria
     a regra de "500 = cor de marca, idêntica" da seção 6 do spec. Solução:
     gerado à mão com a mesma forma da curva L/C do Vivo Lima (proporção de
     luminosidade/chroma de cada degrau relativa ao 500 do lima, aplicada em
     cima do L/C real do #00EB85), H fixo em 154°, com --lucri-iris FORÇADO
     no degrau 500 — ver docs/spec-design-system.md Seção 2 pro
     detalhamento e a checagem de contraste. */
  --vivo-verde-50:  #dbe3dd; --vivo-verde-100: #cde2d3; --vivo-verde-200: #b3e2c1;
  --vivo-verde-300: #8ae5a9; --vivo-verde-400: #49e98f; --vivo-verde-500: #00eb85;
  --vivo-verde-600: #03be6b; --vivo-verde-700: #109654; --vivo-verde-800: #056f3c;
  --vivo-verde-900: #0c4627; --vivo-verde-950: #092514;

  --lucri-iris-hover: var(--vivo-verde-400); --lucri-iris-deep: var(--vivo-verde-600);
  --brand-accent: var(--lucri-iris);
  --brand-accent-text: var(--lucri-night);

  /* Acento complementar "Vivo Ênfase" — mesma ferramenta/geração da escala
     lima acima (algoritmo complementary já calcula isso; só 2 pontos foram
     capturados até agora, não uma rampa completa 50-950 — não interpolar
     valores intermediários à mão, gerar na ferramenta se precisar). Validado
     com docs/validate_palette.js: #0f78ae contra branco 4.86:1 (PASS texto),
     contra --surface escuro 3.58:1 (PASS elemento de UI, não texto pequeno);
     #100d53 contra branco 17.4:1 (PASS), contra --surface escuro 1.00:1
     (FAIL — some no dark mode, só serve no claro ou como tinta em cima do
     próprio --vivo-enfase/--brand-accent). Registrados mas SEM CONSUMIDOR
     ainda — nenhum componente usa isso hoje, ver spec-design-system.md pra
     onde isso pode entrar. */
  --vivo-enfase: #0f78ae;
  --vivo-enfase-ink: #100d53;

  /* {color.blue} "Céu Azul" do Design System Lucri v1.0 — só foco/link/
     citação, nunca CTA. Primeiro consumidor: outline de foco de input
     (login.css), que até 2026-09 usava --brand-accent (verde) por engano,
     misturando o papel de "ação" com o de "foco". */
  --focus-ring: #00D0F5;

  /* Status alinhado ao Lucri DS V1: --good/--critical batem 1:1 com
     .trend.good/.trend.bad do V1 (docs.css) — o V1 não tem vermelho, "ruim"
     é laranja escuro. --warning/--serious não têm valor exato no V1 (só
     uma cor de alerta, sem escala de 3 níveis) — aproximados reaproveitando
     os próprios degraus da escala --orange-* (500/700), gravidade crescente
     até --critical (800), nada inventado fora da paleta do V1. */
  --good: #00673B; --warning: #E8622C; --serious: #B54C22; --critical: #903D1B;

  /* cor de marca só p/ badge/ícone — nunca série de gráfico */
  --ig: #e1306c; --yt: #ff0000; --tt: #ff0050; --gads: #4285F4;

  --space-1: 4px; --space-2: 8px; --space-3: 12px; --space-4: 16px; --space-5: 24px; --space-6: 32px;
  /* Raio do Lucri DS V1: --radius-sm agora é a role "input/box utilitário"
     (--r-md do V1, 12px — não "controle pill", ver mudança de botões
     utilitários abaixo). --radius-md (card) já batia com --r-lg (16px),
     sem mudança. --radius-lg (login.css: shell/showcase) sem token
     equivalente no V1, mantido no valor histórico. */
  --radius-sm: 12px; --radius-md: 16px; --radius-lg: 28px; --radius-pill: 9999px;
  /* raio fixo (não escala com o tamanho da caixa) pra bolha de ícone de
     rede/KPI — --radius-sm vira círculo em caixas de 20-28px (raio ≥ 50%
     da caixa), então essas bolhas usam seu próprio token, igual em toda
     página, pra nunca virar círculo por acidente. */
  --radius-badge: 6px;

  /* sidebar sempre-dark — hex exato da v1 (era um roxo-acinzentado próprio) */
  --sidebar-bg: #0f0f0f;
  --sidebar-text: rgba(255,255,255,.45);
  --sidebar-w: 232px;
  --topbar-h: 64px;

  /* badge de rede — mesma família da sidebar, mas sempre contrastando com --page */
  --badge-bg: var(--sidebar-bg);
}

@media (prefers-color-scheme: dark) {
  :root:where(:not([data-theme="light"])) {
    color-scheme: dark;
    --page:     #0d0d0d;
    --surface:  #1a1a19;
    --text-1:   #ffffff;
    --text-2:   #c3c2b7;
    --grid:     #2c2c2a;
    --baseline: #383835;
    --border:   rgba(255,255,255,.10);
    --c1: #3987e5; --c3: #d55181; --c4: #c98500; --c5: #199e70; --c6: #d95926; --c7: #9085e9; --c8: #e66767;
    --badge-bg: #2c2b3a;
    /* Status no dark: os tons escuros do light (green-900/orange-700/800)
       ficam ilegíveis sobre --surface #1a1a19. --good usa --green-on-dark
       do V1 (validado); warning/serious/critical convergem pro degrau mais
       claro da escala laranja (orange-500) — o V1 não define variante
       "on-dark" pro laranja, essa é a aproximação mais segura disponível. */
    --good: #2AE8A4; --warning: #E8622C; --serious: #E8622C; --critical: #E8622C;
  }
}
:root[data-theme="dark"] {
  color-scheme: dark;
  --page:     #0d0d0d;
  --surface:  #1a1a19;
  --text-1:   #ffffff;
  --text-2:   #c3c2b7;
  --grid:     #2c2c2a;
  --baseline: #383835;
  --border:   rgba(255,255,255,.10);
  --c1: #3987e5; --c3: #d55181; --c4: #c98500; --c5: #199e70; --c6: #d95926; --c7: #9085e9; --c8: #e66767;
  --badge-bg: #2c2b3a;
  --good: #2AE8A4; --warning: #E8622C; --serious: #E8622C; --critical: #E8622C;
}

* { box-sizing: border-box; }
html, body { height: 100%; }
body {
  margin: 0;
  background: var(--page);
  color: var(--text-1);
  font-family: "Inter", -apple-system, system-ui, "Segoe UI", sans-serif;
}

/* ---------- shell layout ---------- */
.shell { display: flex; min-height: 100vh; }

/* Trava de hover/deep da sidebar (existia até 2026-09, pedido explícito)
   removida na troca de marca pra verde: ela congelava o hex escolhido à
   mão pro CTA "Gerar relatório" ANTES da escala Vivo Lima existir — não
   havia "hex pré-escala" equivalente pro verde novo pra preservar, então
   a sidebar agora herda --lucri-iris-hover/-deep normalmente do :root
   como o resto do app. Se o CTA da sidebar precisar de um tom próprio de
   novo, é uma decisão de produto separada, não retomar esta trava sem
   perguntar antes. */
.sidebar {
  width: var(--sidebar-w); flex-shrink: 0; background: var(--sidebar-bg);
  padding: var(--space-5) var(--space-4);
  display: flex; flex-direction: column; gap: var(--space-6);
  position: sticky; top: 0; height: 100vh;
  /* 18 links de nav já não cabem em 100vh numa tela normal — rola em vez
     de cortar/sobrepor o footer. Scrollbar fina, sem cor nova (branco
     translúcido, igual ao resto do tratamento da sidebar escura). */
  overflow-y: auto;
  scrollbar-width: thin;
  scrollbar-color: rgba(255,255,255,.18) transparent;
}
.sidebar::-webkit-scrollbar { width: 6px; }
.sidebar::-webkit-scrollbar-thumb { background: rgba(255,255,255,.18); border-radius: 3px; }
.sidebar::-webkit-scrollbar-track { background: transparent; }
.sidebar .brand { display: flex; align-items: center; gap: 10px; padding: 0 var(--space-2); }
.sidebar .brand img { width: 28px; height: 28px; border-radius: 10px; }
/* Wordmark "Lucri" — Inter, Lucri DS V1 (era Fraunces itálica no clima
   "Cirrus", depois Instrument Sans por uma semana, migrado 2026-09). */
.sidebar .brand span { color: #fff; font-weight: 700; font-size: 18px; font-family: "Inter", sans-serif; }

.nav-group { display: flex; flex-direction: column; gap: 2px; }
.nav-group .group-label {
  font-size: 11px; text-transform: uppercase; letter-spacing: .04em;
  color: var(--sidebar-text); padding: 0 var(--space-2); margin-bottom: 6px;
}
.nav-item {
  display: flex; align-items: center; gap: 10px; padding: 9px 14px;
  border-radius: var(--radius-pill); font-size: 13px; font-weight: 500;
  color: var(--sidebar-text); text-decoration: none; cursor: pointer;
  transition: background .12s ease, color .12s ease;
}
.nav-item:hover { background: rgba(255,255,255,.06); color: #fff; }
.nav-item.active { background: var(--brand-accent); color: var(--brand-accent-text); }
.nav-item .ic { width: 18px; height: 18px; display: flex; align-items: center; justify-content: center; flex-shrink: 0; }
.nav-item .ic img { width: 16px; height: 16px; border-radius: 4px; object-fit: cover; }
.nav-item .ic svg { width: 18px; height: 18px; }
.nav-item .count {
  margin-left: auto; background: rgba(255,255,255,.12); color: #fff;
  font-size: 11px; border-radius: 999px; padding: 1px 7px;
}
.nav-item .soon {
  margin-left: auto; font-size: 9px; font-weight: 700; text-transform: uppercase;
  letter-spacing: .03em; color: var(--sidebar-text); background: rgba(255,255,255,.08);
  border-radius: var(--radius-pill); padding: 2px 7px; flex-shrink: 0;
}
.nav-item.disabled { cursor: default; opacity: .65; }
.nav-item.disabled:hover { background: transparent; color: var(--sidebar-text); }
.sidebar .footer { margin-top: auto; }
/* Único CTA da sidebar (fecha o ciclo de valor: dado -> relatório entregável
   pro cliente) — precisa se destacar do estado ativo de navegação (mesmo
   lima, mas .nav-item.active é pill lisa sem ícone/sombra). Ícone (mesmo svg
   do item "Relatório" do nav, reforça o link semântico) + sombra própria dão
   peso de botão, não de mais um item de lista. */
.sidebar .plan-btn {
  width: 100%; border: none; background: var(--brand-accent); color: var(--brand-accent-text); font-weight: 600;
  font-size: 13px; padding: 11px; border-radius: var(--radius-pill); cursor: pointer;
  display: flex; align-items: center; justify-content: center; gap: 8px;
  box-sizing: border-box; text-align: center; text-decoration: none;
}
.sidebar .plan-btn:hover { background: var(--lucri-iris-hover); }
.sidebar .plan-btn svg { flex-shrink: 0; }

/* ---------- user-chip (rodapé da sidebar) ---------- */
.user-chip {
  position: relative; width: 100%; display: flex; align-items: center; gap: 9px;
  padding: 8px; margin-bottom: var(--space-2); border: none; border-radius: var(--radius-pill);
  background: transparent; cursor: pointer; text-align: left; font: inherit;
}
.user-chip:hover, .user-chip.open { background: rgba(255,255,255,.06); }
.user-chip .avatar {
  width: 30px; height: 30px; border-radius: 50%; background: var(--brand-accent); flex-shrink: 0;
  display: flex; align-items: center; justify-content: center; color: var(--brand-accent-text); font-size: 12px; font-weight: 700;
}
.user-chip .chip-text { flex: 1; min-width: 0; }
.user-chip .name { font-size: 13px; font-weight: 600; color: #fff; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.user-chip .role { font-size: 11px; color: var(--sidebar-text); }
.user-chip .chip-caret { color: var(--sidebar-text); flex-shrink: 0; transition: transform .12s ease; }
.user-chip.open .chip-caret { transform: rotate(180deg); }

.user-menu {
  display: none; position: absolute; left: 0; right: 0; bottom: calc(100% + 6px); z-index: 30;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-sm);
  box-shadow: var(--shadow-md); padding: 6px; flex-direction: column; gap: 2px;
}
.user-chip.open .user-menu { display: flex; }
.user-menu-item {
  display: block; width: 100%; padding: 8px 10px; border: none; background: transparent;
  border-radius: 6px; font: inherit; font-size: 13px; font-weight: 500; color: var(--text-1);
  text-decoration: none; text-align: left; cursor: pointer; box-sizing: border-box;
}
.user-menu-item:hover { background: var(--page); }
.user-menu-item.danger { color: var(--critical); }

.main { flex: 1; min-width: 0; display: flex; flex-direction: column; }

/* ---------- sidebar mobile (drawer) ----------
   Sem isso a sidebar (largura fixa --sidebar-w) nunca saía do fluxo flex
   do .shell em telas estreitas — sobrava pouco espaço pro .main e todo
   texto/gráfico da página cortava na borda direita. position:fixed tira
   a sidebar do fluxo (o .main volta a ocupar 100%) e ela vira um drawer
   que desliza por cima, aberto pelo botão hambúrguer injetado em
   shell.js (mesmo HTML de topbar em toda página, sem duplicar em 16
   arquivos). */
.sidebar-backdrop { display: none; position: fixed; inset: 0; z-index: 150; background: rgba(0,0,0,.5); }
.sidebar-backdrop.open { display: block; }
.icon-btn.menu-toggle { display: none; }
@media (max-width: 900px) {
  .sidebar { position: fixed; top: 0; left: 0; z-index: 151; transform: translateX(-100%); transition: transform .2s ease; box-shadow: var(--shadow-md); }
  .sidebar.open { transform: translateX(0); }
  .icon-btn.menu-toggle { display: flex; }
}

.topbar {
  height: var(--topbar-h); flex-shrink: 0; display: flex; align-items: center;
  justify-content: space-between; padding: 0 var(--space-5); gap: var(--space-4);
  border-bottom: 1px solid var(--grid);
}
.topbar .search {
  display: flex; align-items: center; gap: 8px; background: var(--surface);
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  padding: 8px 12px; font-size: 13px; color: var(--text-2); width: 260px;
  cursor: pointer; transition: border-color .12s ease;
}
.topbar .search:hover { border-color: var(--muted); }
.topbar .search svg { width: 15px; height: 15px; flex-shrink: 0; }
.topbar .search .cmd-kbd {
  margin-left: auto; font-size: 11px; font-family: inherit; color: var(--text-2);
  border: 1px solid var(--border); border-radius: 4px; padding: 1px 5px;
}

/* ---------- command bar (⌘K) ---------- */
.cmd-overlay {
  display: none; position: fixed; inset: 0; z-index: 200;
  background: rgba(0,0,0,.4); padding-top: 14vh;
}
.cmd-overlay.open { display: block; }
.cmd-panel {
  width: min(560px, calc(100vw - 48px)); margin: 0 auto;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-md);
  box-shadow: var(--shadow-md); overflow: hidden;
}
.cmd-input-row { display: flex; align-items: center; gap: 10px; padding: 12px 16px; border-bottom: 1px solid var(--grid); color: var(--text-2); }
.cmd-input { flex: 1; border: none; outline: none; background: transparent; font: inherit; font-size: 14px; color: var(--text-1); }
.cmd-esc { font-size: 11px; color: var(--text-2); border: 1px solid var(--border); border-radius: 4px; padding: 1px 6px; }
.cmd-list { max-height: 320px; overflow-y: auto; padding: 6px; }
.cmd-group { font-size: 10.5px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase; color: var(--text-2); padding: 8px 10px 4px; }
.cmd-item { padding: 8px 10px; border-radius: var(--radius-sm); font-size: 13.5px; color: var(--text-1); cursor: pointer; }
.cmd-item.active { background: var(--brand-accent); color: var(--brand-accent-text); }
.cmd-empty { padding: 20px 10px; text-align: center; font-size: 13px; color: var(--text-2); }
.topbar .actions { display: flex; align-items: center; gap: var(--space-3); }

/* ---------- seletor de período (topbar) — ver period.js ---------- */
/* display:flex (não bloco com filhos inline soltos) — sem isso, "Dados até
   DD/MM/AAAA" e o botão de período quebravam linha um independente do
   outro quando o topbar ficava apertado (ex.: depois que o filtro de
   campanha entrou do lado, em Meta/Google Ads), com o texto indo pra uma
   linha sozinho e o botão caindo pra a linha de baixo — os dois ficavam
   fora de simetria com os outros controles do topbar. Como uma unidade
   flex, ou cabem os dois juntos na linha, ou o par inteiro quebra junto. */
.period-picker { position: relative; display: flex; align-items: center; }
/* fica escondido abaixo de 900px de propósito — não entrar em conflito com
   o flex-wrap do .topbar documentado logo abaixo (achado testando em
   390px); "dados até" é reforço de desktop, não essencial no mobile. */
.dp-freshness { font-size: 11px; font-weight: 600; color: var(--text-2); margin-right: 8px; white-space: nowrap; }
@media (max-width: 900px) { .dp-freshness { display: none; } }
.date-trigger-btn {
  display: flex; align-items: center; gap: 8px; min-width: 190px;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-pill);
  padding: 8px 12px; font: inherit; font-size: 13px; font-weight: 600; color: var(--text-1);
  cursor: pointer; text-align: left; transition: border-color .15s;
}
.date-trigger-btn:hover, .date-trigger-btn.open { border-color: var(--brand-accent); }
.date-trigger-btn .lbl { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.date-trigger-btn .chevron { font-size: 10px; color: var(--muted); transition: transform .15s; }
.date-trigger-btn.open .chevron { transform: rotate(180deg); }

/* .search (largura fixa 260px, regra lá em cima) + .date-trigger-btn
   (min-width 190px, regra logo acima) + .actions não cabem numa linha só
   abaixo de ~430px — antes disso a .topbar inteira estourava
   horizontalmente (scrollWidth > viewport, achado testando em 390px).
   flex-wrap deixa quem não cabe descer pra 2ª linha em vez de empurrar a
   página inteira de lado; .topbar não é sticky, então não tem sobreposição
   com o conteúdo abaixo. Precisa vir DEPOIS das regras-base de
   .search/.date-trigger-btn (mesma especificidade — quem vem depois no
   arquivo vence, media query não muda isso). */
@media (max-width: 900px) {
  .topbar {
    height: auto; min-height: var(--topbar-h); flex-wrap: wrap;
    padding: 10px var(--space-3); row-gap: 8px;
  }
  .topbar .search { width: auto; flex: 1 1 140px; }
  .date-trigger-btn { min-width: 0; flex: 1 1 140px; }
  .topbar .actions { margin-left: auto; }
}

.dp-overlay { display: none; position: fixed; inset: 0; z-index: 40; }
.dp-overlay.open { display: block; }
.dp-panel {
  /* position:fixed (não absolute) de propósito: o pai `.dp-overlay` é
     position:fixed (cobre a tela inteira, cortina pra fechar clicando
     fora), o que vira o containing block de qualquer descendente
     absolute — sem isso, top/left aqui contavam % da tela inteira, não
     do botão. Coordenadas reais vêm do JS em dpToggle() (period.js). */
  position: fixed; top: 0; left: 0; z-index: 41;
  width: min(680px, calc(100vw - 48px));
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-md);
  box-shadow: var(--shadow-md); display: grid; grid-template-columns: 180px 1fr; overflow: hidden;
}
.dp-presets { padding: var(--space-3) var(--space-2); border-right: 1px solid var(--border); overflow-y: auto; max-height: 420px; }
.dp-preset-section { font-size: 10px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); padding: 8px 8px 4px; }
.dp-preset-btn {
  width: 100%; display: flex; align-items: center; gap: 8px; padding: 8px 10px;
  border: 0; border-radius: var(--radius-pill); background: none; color: var(--text-1);
  font: inherit; font-size: 13px; font-weight: 600; cursor: pointer; text-align: left; transition: background .12s;
}
.dp-preset-btn:hover { background: var(--page); }
.dp-preset-btn.active { background: var(--brand-accent); color: var(--brand-accent-text); }
.dp-preset-dot { width: 7px; height: 7px; border-radius: 50%; border: 1.5px solid currentColor; flex-shrink: 0; position: relative; }
.dp-preset-btn.active .dp-preset-dot::after { content: ''; position: absolute; inset: 2px; border-radius: 50%; background: var(--brand-accent-text); }

.dp-cal-wrap { padding: var(--space-4) var(--space-5); }
.dp-cal-months { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-5); }
.dp-cal-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 10px; }
.dp-cal-title { font-size: 13px; font-weight: 700; color: var(--text-1); text-transform: capitalize; }
.dp-cal-nav {
  width: 26px; height: 26px; border-radius: var(--radius-pill); border: 1px solid var(--border);
  background: var(--page); color: var(--text-1); cursor: pointer; font-size: 12px; font-weight: 700;
  display: flex; align-items: center; justify-content: center;
}
.dp-cal-nav.hidden { visibility: hidden; }
.dp-days-head { display: grid; grid-template-columns: repeat(7,1fr); gap: 2px; margin-bottom: 4px; }
.dp-days-head span { text-align: center; font-size: 11px; font-weight: 700; color: var(--text-2); padding: 4px 0; }
.dp-days { display: grid; grid-template-columns: repeat(7,1fr); gap: 2px; }
.dp-day {
  position: relative;
  min-height: 30px; border: 0; border-radius: var(--radius-pill); background: transparent; color: var(--text-1);
  font: inherit; font-size: 12.5px; font-weight: 600; cursor: pointer; transition: background .1s;
  display: flex; align-items: center; justify-content: center;
}
.dp-day:hover:not(.dp-day-empty) { background: var(--page); }
.dp-day-empty { visibility: hidden; pointer-events: none; }
.dp-day-in-range { background: var(--grid); border-radius: 0; }
.dp-day-start, .dp-day-end { background: var(--brand-accent) !important; color: var(--brand-accent-text) !important; border-radius: var(--radius-pill) !important; }
.dp-day-today::after {
  content: ''; position: absolute; bottom: 4px; left: 50%; width: 4px; height: 4px;
  border-radius: 50%; background: var(--brand-accent); transform: translateX(-50%);
}
.dp-day-today.dp-day-start::after, .dp-day-today.dp-day-end::after { background: var(--brand-accent-text); }

.dp-footer { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); margin-top: var(--space-3); padding-top: var(--space-3); border-top: 1px solid var(--border); }
.dp-selected-label { font-size: 13px; font-weight: 700; }
.dp-selected-sub { font-size: 11px; color: var(--text-2); margin-top: 2px; }
.dp-actions { display: flex; gap: 8px; }
.dp-btn {
  height: 34px; padding: 0 14px; border-radius: var(--radius-pill); border: 1px solid var(--border);
  background: var(--page); color: var(--text-1); font: inherit; font-size: 13px; font-weight: 700; cursor: pointer;
}
.dp-btn-primary { border-color: transparent; background: var(--brand-accent); color: var(--brand-accent-text); }
@media (max-width: 900px) {
  .dp-panel { grid-template-columns: 1fr; position: fixed; left: 24px; right: 24px; top: 74px; width: auto; }
  .dp-presets { border-right: none; border-bottom: 1px solid var(--border); max-height: none; display: flex; flex-wrap: wrap; }
}
.icon-btn {
  width: 34px; height: 34px; border-radius: var(--radius-pill); border: 1px solid var(--border);
  background: var(--surface); display: flex; align-items: center; justify-content: center;
  cursor: pointer; color: var(--text-2);
}
.icon-btn svg { width: 16px; height: 16px; }
.icon-btn.spinning svg { animation: icon-spin .7s linear infinite; }
.icon-btn.done { border-color: var(--good); color: var(--good); }
@keyframes icon-spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }
.user-chip { display: flex; align-items: center; gap: 8px; }
.user-chip .avatar { width: 32px; height: 32px; border-radius: 50%; background: var(--brand-accent); }
.user-chip .name { font-size: 13px; font-weight: 600; }
.user-chip .role { font-size: 11px; color: var(--text-2); }

/* min-width:0 pelo mesmo motivo do .main (linha acima): .content é item
   de um flex column (.main) — sem isso, um filho largo (ex.: gráfico com
   min-width, ver .chart-scroll) empurra a página inteira de lado no
   mobile em vez de rolar contido dentro do próprio card. Achado testando
   comparativo.html em 390px — texto do page-head/ajustes-hint cortava na
   borda mesmo com a tabela já tendo .table-scroll. */
.content { padding: var(--space-5); flex: 1; min-width: 0; }
/* Título de página/headline — Inter 700, tracking -0.02em (perto do
   -0.025em de .display/.display-xl do Lucri DS V1; tamanho do dashboard
   mantido, o V1 não define uma role de "título de página densa", só
   marketing). Era a frase-herói serifada do clima "Cirrus", migrado 2026-09. */
.headline-serif { font-family: "Inter", sans-serif; font-weight: 700; letter-spacing: -0.02em; }
.content h1 { font-size: 26px; font-weight: 700; margin: 0; font-family: "Inter", sans-serif; letter-spacing: -0.02em; }
.content-head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-4); margin-bottom: var(--space-5); flex-wrap: wrap; }

/* Seletor de janela dos KPIs "(Xd)" da Home — mesmo padrão visual dos presets
   do date-picker (.dp-preset-btn/.active), só que sempre visível na página
   em vez de dentro de um popover. */
.kpi-window-toggle { display: flex; gap: 4px; background: var(--page); border: 1px solid var(--border); border-radius: var(--radius-pill); padding: 3px; }
.kpi-window-btn {
  border: 0; background: none; font: inherit; font-size: 12.5px; font-weight: 600; color: var(--text-2);
  padding: 5px 12px; border-radius: var(--radius-pill); cursor: pointer;
}
.kpi-window-btn:hover { color: var(--text-1); }
.kpi-window-btn.active { background: var(--brand-accent); color: var(--brand-accent-text); }

/* ---------- shared components ---------- */
.card {
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-md);
  box-shadow: var(--shadow-sm); padding: var(--space-4);
}
.cards-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px,1fr)); gap: var(--space-4); margin-bottom: var(--space-5); }

/* KPI hero (métrica-âncora) + coluna secundária — mesmo padrão do slide de
   plataforma no relatório: 1 número grande com delta+tendência puxa o olho
   primeiro, os outros 3 ficam menores ao lado (Stripe/Vercel: abre na
   métrica que todo mundo quer ver, sem esconder as demais). */
.kpi-hero-row { display: grid; grid-template-columns: 1.3fr 1fr; gap: var(--space-4); margin-bottom: var(--space-5); align-items: stretch; }
@media (max-width: 900px) { .kpi-hero-row { grid-template-columns: 1fr; } }
.kpi-hero-card { display: flex; flex-direction: column; }
.kpi-hero-value { font-size: 48px; font-weight: 700; line-height: 1.1; font-variant-numeric: tabular-nums; }
.kpi-hero-spark { flex: 1; min-height: 60px; padding-top: var(--space-3); }
.kpi-hero-spark svg { width: 100%; height: 100%; display: block; }
.kpi-secondary-col { display: grid; grid-template-rows: repeat(3, 1fr); gap: var(--space-4); }
.kpi-secondary-col .card { display: flex; flex-direction: column; justify-content: center; }

/* Lucri DS V1: .card fica sem sombra em repouso (só borda), igual todo o
   resto do app — só .card.interactive ganha --shadow-sm (xs) no hover.
   Hero/secundário dos 4 KPIs do topo da Home seguem essa mesma regra
   (perderam a elevação permanente que tinham no clima "Cirrus" 2026-09). */
.kpi-hero-card, .kpi-secondary-card { transition: transform .18s ease, box-shadow .18s ease; }
.kpi-hero-card:hover, .kpi-secondary-card:hover { transform: translateY(-2px); box-shadow: var(--shadow-sm); }

/* Ícone colorido por KPI, mesmo padrão visual do card de referência
   (quadrado arredondado com o ícone da métrica) — cada KPI tem sua cor
   fixa, não a paleta categórica de rede (não representa uma série). Anel
   interno (inset, currentColor a 25%) dá um pouco de relevo ao quadrado
   pastel sem precisar de cor nova — só reforça a própria cor do ícone. */
.kpi-icon {
  width: 36px; height: 36px; border-radius: var(--radius-badge); flex-shrink: 0;
  display: flex; align-items: center; justify-content: center; margin-bottom: var(--space-3);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, currentColor 25%, transparent);
}
.kpi-icon svg { width: 18px; height: 18px; }
/* Views Totais é a hero da Home (index.html). Ícone + sparkline (app.js,
   kpi-views-spark) sempre na mesma cor — usava --c1 (emprestado da paleta
   categórica), depois --vivo-enfase (2026-08, primeiro/único consumidor),
   agora --brand-accent (2026-09): os 4 sparklines de métrica única da Home
   (Views/Média/Seguidores/Posts) e os 2 gráficos de Tendência passaram a
   usar o verde da marca — são visualizações de 1 métrica só, sem série
   pra distinguir, então a cor de UI de ação serve tão bem quanto uma
   emprestada. --vivo-enfase fica registrado sem consumidor de novo. */
.kpi-icon-reach      { background: color-mix(in srgb, var(--brand-accent) 16%, transparent); color: var(--brand-accent-text); }
.kpi-icon-engagement { background: color-mix(in srgb, var(--serious) 16%, transparent); color: var(--serious); }
.kpi-icon-followers  { background: color-mix(in srgb, var(--good) 16%, transparent); color: var(--good); }
.kpi-icon-ads        { background: color-mix(in srgb, var(--c7) 16%, transparent); color: var(--c7); }
/* Ícone da hero é maior (44px/22px vs 36px/18px) — proporcional ao valor
   48px ao lado, mesma lógica de "peso combina com a métrica-âncora" do
   resto do card. */
.kpi-hero-card .kpi-icon { width: 44px; height: 44px; }
.kpi-hero-card .kpi-icon svg { width: 22px; height: 22px; }

.kpi-secondary-card { flex-direction: row !important; align-items: center; gap: var(--space-3); flex-wrap: wrap; }
.kpi-secondary-top { display: flex; align-items: flex-start; gap: var(--space-3); flex: 1; min-width: 0; }
.kpi-secondary-top .kpi-icon { margin-bottom: 0; }
.kpi-secondary-text { min-width: 0; }
.kpi-secondary-spark { width: 72px; height: 36px; flex-shrink: 0; }
.kpi-secondary-spark svg { width: 100%; height: 100%; display: block; }
@media (max-width: 1100px) { .kpi-secondary-spark { display: none; } }

/* Sparkline dos cards de KPI da Home (Views Totais/Média por Post/Seguidores
   Ganhos/Posts Publicados) — largura total do card, não uma tirinha de
   canto como .kpi-secondary-spark (esse padrão é usado nas páginas de
   métrica, layout em linha; aqui os cards empilham em coluna). */
.kpi-card-spark { width: 100%; height: 40px; margin-top: var(--space-3); }
.kpi-card-spark svg { width: 100%; height: 100%; display: block; }
.grid-2 { display: grid; grid-template-columns: 1.4fr 1fr; gap: var(--space-4); margin-bottom: var(--space-5); }
.grid-2-even { grid-template-columns: 1fr 1fr; }
@media (max-width: 1900px) { .grid-2 { grid-template-columns: 1fr; } }

.stat-label { font-size: 12px; font-weight: 500; color: var(--text-2); margin-bottom: 4px; display:flex; align-items:center; gap:6px; }
.stat-value { font-size: 40px; font-weight: 700; line-height: 1.1; }
.stat-value-row { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
.stat-delta {
  font-size: 12px; font-weight: 600; line-height: 1.4;
  display: inline-flex; align-items: center; gap: 4px; margin-top: 8px;
  padding: 2px 8px; border-radius: var(--radius-pill);
}
.stat-delta:empty { display: none; }
.stat-delta.up   { background: color-mix(in srgb, var(--good) 14%, transparent);     color: var(--good); }
.stat-delta.down { background: color-mix(in srgb, var(--critical) 14%, transparent); color: var(--critical); }
.stat-sub { font-size: 12px; color: var(--text-2); margin-top: 2px; }

.card h2 { font-size: 18px; font-weight: 600; margin: 0 0 var(--space-3); }
/* flex-wrap: título + filtro(s)/badge à direita não cabem lado a lado em
   telas estreitas em vários cards (ex. "Posts lançados" + select de rede em
   editar-dados.html) — sem wrap isso empurrava a página inteira de lado no
   mobile em vez de só descer o filtro pra 2ª linha. */
.card-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: var(--space-3); flex-wrap: wrap; gap: var(--space-2); }

.legend { display: flex; gap: var(--space-4); flex-wrap: wrap; font-size: 12px; }
.legend .item { display: flex; align-items: center; gap: 6px; color: var(--text-2); }
.legend .sw { width: 10px; height: 10px; border-radius: 2px; flex-shrink: 0; }
.legend-spaced { margin-top: var(--space-2); }
.legend-column { flex-direction: column; gap: var(--space-2); }

.section-title { font-size: 18px; font-weight: 600; margin: var(--space-5) 0 var(--space-3); display: flex; align-items: center; gap: var(--space-2); }
.section-title-sub { font-size: 12px; font-weight: 600; color: var(--text-2); }

/* Ícone de título de seção/card — substitui os emoji antigos (💰📊📈🏆🕐)
   por SVG na cor do texto (currentColor), igual ao resto do sistema de
   ícones (regra #4 do design system: identidade nunca via cor de texto). */
.section-title .ic, .card-head h2 .ic {
  display: inline-flex; width: 18px; height: 18px; flex-shrink: 0;
  color: var(--text-1); vertical-align: -3px;
}
.section-title .ic svg, .card-head h2 .ic svg { width: 100%; height: 100%; }

/* ---------- chip "🗓️ Mês atual" no topo da Home (estilo v1) ---------- */
.period-chip {
  display: inline-flex; align-items: center; gap: 6px; font-size: 13px; font-weight: 600;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-pill);
  padding: 6px 14px; color: var(--text-1);
}
.period-chip span { color: var(--text-2); font-weight: 500; }

.spacer { flex: 1; }

/* ---------- tooltip compartilhado por todo gráfico SVG (charts.js) ---------- */
.chart-tooltip {
  position: fixed; z-index: 1000; pointer-events: none;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius-sm); box-shadow: var(--shadow-md);
  overflow: hidden; font-size: 12px; color: var(--text-1);
  opacity: 0; transform: translate(-50%, calc(-100% - 10px));
  transition: opacity .1s ease; white-space: nowrap;
}
.chart-tooltip.visible { opacity: 1; }
.chart-tooltip-title {
  font-weight: 600; color: var(--text-1); font-size: 12px;
  padding: 7px 12px; border-bottom: 1px solid var(--grid);
}
.chart-tooltip-row {
  display: flex; align-items: center; gap: 14px; justify-content: space-between;
  padding: 5px 12px;
}
.chart-tooltip-row:not(:only-of-type):not(:last-child) { border-bottom: 1px dashed var(--grid); }
.chart-tooltip:not(:has(.chart-tooltip-title)) .chart-tooltip-row:first-of-type { padding-top: 8px; }
.chart-tooltip .chart-tooltip-row:last-of-type { padding-bottom: 8px; }
.chart-tooltip-key { width: 10px; height: 3px; border-radius: var(--radius-pill); flex-shrink: 0; }
.chart-tooltip-label { color: var(--text-2); }
.chart-tooltip-value { font-weight: 700; font-variant-numeric: tabular-nums; }

/* ---------- estados de hover dos gráficos ---------- */
.chart-axis-label { font-size: 10px; fill: var(--muted); }
.chart-gridline { stroke: var(--grid); stroke-width: 1; }
.chart-bar { cursor: pointer; transition: opacity .12s ease; }
.chart-bar:hover, .chart-bar.hovered { opacity: .82; }
.chart-point { cursor: pointer; transition: r .12s ease; }
.chart-point:hover { r: 5; }
.donut-seg { cursor: pointer; transition: opacity .12s ease; }
.donut-seg.dimmed { opacity: .35; }
.chart-hit { fill: transparent; cursor: crosshair; }
.chart-crosshair { stroke: var(--baseline); stroke-width: 1; pointer-events: none; }

table { width: 100%; border-collapse: collapse; font-size: 13px; }
table th, table td { text-align: left; padding: 10px 8px; border-bottom: 1px solid var(--grid); }
table th { color: var(--text-2); font-weight: 600; font-size: 12px; }
table th.num, table td.num { text-align: right; }
table td.num { font-variant-numeric: tabular-nums; }
table tr:last-child td { border-bottom: none; }
table tbody tr:nth-child(odd) { background: color-mix(in srgb, var(--grid) 35%, transparent); }
table tbody tr { transition: background-color .12s ease; }
table tbody tr:hover { background: color-mix(in srgb, var(--grid) 55%, transparent); }

.badge {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 3px 9px; border-radius: var(--radius-pill);
  font-size: 12px; font-weight: 600; line-height: 1.4;
  white-space: nowrap;
}
.badge::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: currentColor; }
.badge.neutral  { background: color-mix(in srgb, var(--text-2) 12%, transparent); color: var(--text-2); }
.badge.good     { background: color-mix(in srgb, var(--good) 14%, transparent);    color: var(--good); }
.badge.warning  { background: color-mix(in srgb, var(--warning) 16%, transparent); color: var(--warning); }
.badge.serious  { background: color-mix(in srgb, var(--serious) 16%, transparent); color: var(--serious); }
.badge.critical { background: color-mix(in srgb, var(--critical) 16%, transparent); color: var(--critical); }
.net-cell { display: flex; align-items: center; gap: 10px; }
.net-icon {
  width: 28px; height: 28px; border-radius: var(--radius-badge);
  background: var(--badge-bg); color: #fff;
  display: flex; align-items: center; justify-content: center; flex-shrink: 0;
}
.net-icon svg { display: block; }

.rate-cell { display: flex; align-items: center; gap: 8px; justify-content: flex-end; }
.rate-cell .bar-track { width: 56px; height: 6px; border-radius: var(--radius-pill); background: var(--grid); overflow: hidden; }
.rate-cell .bar-fill { height: 100%; border-radius: var(--radius-pill); }

.donut-wrap { display: flex; align-items: center; gap: var(--space-5); }
.donut-chart-center { flex: 1; display: flex; justify-content: center; min-width: 0; }
/* Card do donut pareado numa grid align-items:stretch (ex. chart-row-2)
   ao lado de um card mais alto (gráfico de barra) estica em altura, mas
   sem isso o donut-wrap ficava com sua altura natural colado no topo,
   sobrando um vão vazio embaixo. Centraliza o conteúdo no espaço esticado,
   título (.card-head) continua fixo no topo. */
.card:has(> .donut-wrap) { display: flex; flex-direction: column; }
.card:has(> .donut-wrap) > .donut-wrap { flex: 1; }

.fol-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px,1fr)); gap: var(--space-4); }
.fol-card { display: flex; flex-direction: column; gap: 4px; }
.fol-platform { display: flex; align-items: center; gap: 8px; font-size: 13px; font-weight: 600; color: var(--text-2); margin-bottom: 6px; }
.fol-platform .net-icon { width: 22px; height: 22px; }
.fol-video-label { font-size: 11px; color: var(--text-2); margin-top: 2px; }

/* ---------- toast + confirm dialog compartilhados (shell.js) ----------
   Substituem alert()/confirm() nativos do navegador (feios, fora do tema,
   travam a aba) nas páginas que fazem excluir/salvar (Seguidores,
   Instagram, Editar Dados, Relatório). Injetado 1x por shell.js, não
   precisa de HTML próprio em cada página. */
.toast-stack {
  position: fixed; bottom: var(--space-5); right: var(--space-5); z-index: 300;
  display: flex; flex-direction: column-reverse; gap: var(--space-2);
  pointer-events: none;
}
.toast {
  pointer-events: auto;
  display: flex; align-items: center; gap: 10px;
  background: var(--surface); border: 1px solid var(--border); border-left: 3px solid var(--text-2);
  border-radius: var(--radius-sm); box-shadow: var(--shadow-md);
  padding: 12px 16px; font-size: 13px; font-weight: 500; color: var(--text-1);
  max-width: 360px;
  animation: toast-in .18s ease;
}
.toast.ok  { border-left-color: var(--good); }
.toast.err { border-left-color: var(--critical); }
.toast.leaving { animation: toast-out .15s ease forwards; }
@keyframes toast-in { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: translateY(0); } }
@keyframes toast-out { to { opacity: 0; transform: translateY(6px); } }

.confirm-overlay {
  display: none; position: fixed; inset: 0; z-index: 250;
  background: rgba(0,0,0,.4); align-items: center; justify-content: center;
}
.confirm-overlay.open { display: flex; }
.confirm-panel {
  width: min(360px, calc(100vw - 48px));
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-md);
  box-shadow: var(--shadow-md); padding: var(--space-5);
}
.confirm-panel p { margin: 0 0 var(--space-4); font-size: 14px; color: var(--text-1); line-height: 1.5; }
.confirm-actions { display: flex; justify-content: flex-end; gap: var(--space-2); }
.confirm-btn {
  border: 1px solid var(--border); background: var(--page); color: var(--text-1);
  font: inherit; font-size: 13px; font-weight: 600; padding: 8px 16px;
  border-radius: var(--radius-pill); cursor: pointer;
}
.confirm-btn.danger { border-color: transparent; background: var(--critical); color: #fff; }

/* ---------- badge de sincronização (topbar, shell.js) ---------- */
.sync-badge {
  display: flex; align-items: center; gap: 6px; font-size: 12px; color: var(--text-2);
  border: 1px solid var(--border); border-radius: var(--radius-pill); padding: 6px 12px;
  background: var(--surface); cursor: pointer; text-decoration: none;
  flex-shrink: 0; white-space: nowrap;
}
.sync-badge .dot { width: 7px; height: 7px; border-radius: 50%; background: var(--muted); flex-shrink: 0; }
.sync-badge .dot.live { background: var(--good); }
.sync-badge .dot.stale { background: var(--critical); }
@media (max-width: 900px) { .sync-badge span { display: none; } .sync-badge { padding: 8px; } }

/* ---------- botão de exportar tabela (CSV, shell.js/lucriExportTable) ---------- */
.export-btn {
  display: inline-flex; align-items: center; gap: 6px; border: 1px solid var(--border);
  background: var(--surface); color: var(--text-2); font: inherit; font-size: 11.5px; font-weight: 600;
  padding: 5px 10px; border-radius: var(--radius-pill); cursor: pointer;
}
.export-btn:hover { color: var(--text-1); border-color: var(--muted); }
.export-btn svg { width: 13px; height: 13px; }

/* ---------- badge de alerta de anomalia (Seguidores, seguidores.js) ---------- */
.anomaly-flag {
  display: inline-flex; align-items: center; gap: 4px; font-size: 11px; font-weight: 700;
  color: var(--critical); background: color-mix(in srgb, var(--critical) 14%, transparent);
  border-radius: var(--radius-pill); padding: 2px 8px; margin-left: 6px; cursor: help;
}
