/* Fase 6.0 — UI/UX refresh (visual only). Todo seletor consumido por JS
   (frontend/js/*.js) foi preservado; ver
   reports/phase-6.0-ui-refresh/CLAUDE/01_BASELINE_AND_DOM_CONTRACT.md para o
   mapeamento completo. Nenhuma regra funcional, nenhum dado, nenhum contrato
   de API foi alterado por este arquivo. */

:root {
  /* Superfícies */
  --bg: #f6f7fb;
  --surface: #ffffff;
  --surface-sunken: #f1f2f6;
  --border: #e6e8f0;
  --border-strong: #d7dae5;

  /* Texto
     FRONTEND-FOUNDATION-SHELL-01 — --text-faint corrigido de #8b90a0
     (contraste 3.18:1 sobre branco, abaixo do mínimo WCAG AA de 4.5:1 para
     texto normal) para #6b6e88 (4.99:1 sobre branco, 4.66:1 sobre --bg).
     Nenhum outro texto auxiliar mudou de token, só o valor deste. */
  --text: #10121a;
  --text-muted: #5b6072;
  --text-faint: #6b6e88;

  /* Marca / accent único — laranja que remete à Shopee (mercado de origem
     dos dados), sem reproduzir logotipo/wordmark/assets da marca. */
  --accent: #ee4d2d;
  --accent-hover: #d5431f;
  --accent-soft: #fdece6;
  --accent-contrast: #ffffff;

  /* Semântico financeiro */
  --success: #15803d;
  --success-bg: #ecfdf3;
  --danger: #b91c1c;
  --danger-bg: #fef2f2;
  --warning: #b45309;
  --warning-bg: #fffbeb;
  --neutral-dot: #7a7f8f;

  /* Estado "em processamento" — FRONTEND-FOUNDATION-SHELL-01. Antes,
     .state-loading reutilizava --accent-soft/--accent (cor de marca como
     estado semântico); a regra de cor da fundação proíbe isso. Cinza-azulado
     neutro, nunca ligado a marca/erro/sucesso/atenção. Contraste: #686b85
     sobre --loading-soft (#f1f2f6) = 4.66:1 (AA), sobre branco = 5.21:1. */
  --loading: #686b85;
  --loading-soft: #f1f2f6;

  /* Sidebar (única superfície escura do produto) */
  --sidebar-bg: #0f1222;
  --sidebar-bg-alt: #171b30;
  --sidebar-text: #aab0c6;
  --sidebar-text-active: #ffffff;
  --sidebar-border: #232742;

  /* Marca secundária — FRONTEND-FOUNDATION-SHELL-01 (direção V1.1: Financial
     Intelligence). Bronze usado SOMENTE em marca/seleção/ação primária,
     escopado nesta carta ao App Shell (estado ativo da sidebar). --accent
     (laranja) continua sendo a cor de CTA/estado usada pelo resto do
     produto (KPIs, filtros, tabelas) — essa migração mais ampla é
     propositalmente uma carta futura, não desta fundação.
     Contraste medido: #8a6116 sobre branco = 5.52:1; sobre --bg = 5.16:1;
     texto bronze sobre --brand-bronze-soft (14% sobre branco) = 4.57:1.
     Todos passam AA (4.5:1) — valor aprovado congelado sem ajuste. */
  --brand-navy: var(--sidebar-bg);
  --brand-bronze: #8a6116;
  --brand-bronze-soft: rgba(138, 97, 22, 0.14);

  --radius-sm: 6px;
  --radius: 10px;
  --radius-lg: 14px;
  --shadow-sm: 0 1px 2px rgba(15, 18, 34, 0.06);
  --shadow-md: 0 4px 16px rgba(15, 18, 34, 0.08);

  /* UX-01A — escala de espaçamento. Introduzida para os componentes que
     esta subfase toca (sidebar/grupos, kpi-grid); o restante do CSS
     continua com valores ad hoc até ser tocado pelas próprias subfases
     (nenhuma substituição global agressiva nesta carta). */
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 24px;
  --space-6: 32px;

  /* FRONTEND-FOUNDATION-SHELL-01 — 232px → 204px (direção V1.1, validada
     visualmente no protótipo: labels/ícones continuam legíveis, Conta
     continua clara). */
  --sidebar-width: 204px;
  --topbar-height: 68px;
  --mobile-topbar-height: 52px;
  --drawer-width: 248px;

  /* Foco — formaliza o nome pedido pela fundação; mesmo valor/comportamento
     de :focus-visible já em uso, nenhuma mudança visual. */
  --focus-ring: var(--accent);

  font-family: -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
}

/* ==========================================================================
   FRONTEND-CONSOLIDATION-01 — aliases semânticos dos tokens acima (carta
   "DESIGN VISUAL"/"design system centralizado"). Nenhum valor de cor muda;
   componentes novos desta carta usam estes nomes, o CSS pré-existente segue
   usando os originais (que apontam para o mesmo lugar). --info é o único
   token genuinamente novo (informação neutra, sem julgamento — ex.:
   contagem de cliques).
   ========================================================================== */
:root {
  --background: var(--bg);
  --surface-secondary: var(--surface-sunken);
  --text-primary: var(--text);
  --text-secondary: var(--text-muted);
  --brand: var(--accent);
  --brand-hover: var(--accent-hover);
  --info: #2563eb;
  --info-bg: #eff6ff;

  /* FRONTEND-FOUNDATION-SHELL-01 — aliases "-soft" pedidos pela fundação de
     design tokens, apontando para os "-bg" já existentes (mesmo valor,
     nenhuma duplicação). --surface-subtle idem para --surface-sunken. */
  --surface-subtle: var(--surface-sunken);
  --success-soft: var(--success-bg);
  --danger-soft: var(--danger-bg);
  --warning-soft: var(--warning-bg);
  --info-soft: var(--info-bg);
}

/* UX-01A — hierarquia tipográfica formalizada (sem fonte nova, só
   documentando o mapeamento já existente + reforçando peso/tamanho onde a
   fundação visual toca). Nenhum destes seletores é novo, exceto
   .sidebar-group-title:
     PAGE TITLE       -> .app-topbar-title h1
     SECTION TITLE    -> .panel-header h2
     KPI LABEL        -> .kpi-label
     KPI VALUE        -> .kpi-value
     SECONDARY TEXT   -> .kpi-sub, .app-topbar-title .subtitle
     TABLE HEADER     -> .data-table th
     BODY             -> body (font-size base do documento)
     MUTED HELP TEXT  -> .panel-note, .period-readout, .text-faint */

* { box-sizing: border-box; }

html, body { height: 100%; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-size: 16px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

a, button, select, input { font-family: inherit; font-size: inherit; }

:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 2px; }

h1, h2, h3, p, dl, dd { margin: 0; }

/* ==========================================================================
   App shell — grid de 2 colunas / 3 linhas. #app-shell fica "achatado" via
   display:contents: seus filhos (.app-sidebar, .app-topbar), produzidos por
   frontend/js/nav.js, viram itens diretos deste grid, junto com main#app e
   footer.footer (irmãos de #app-shell no HTML). Escopado a "não é a página
   de login" porque login.html usa um layout centralizado independente.
   ========================================================================== */

body:not(.login-body) {
  display: grid;
  /* FRONTEND-CONSOLIDATION-01 — minmax(0, 1fr), não 1fr puro: mesma
     correção já usada no grid mobile (UX-01B hotfix) abaixo. Um track "1fr"
     sozinho tem mínimo automático = min-content dos descendentes; tabelas
     densas (.table-scroll .data-table { min-width: max-content }) são
     largas o bastante para inflar essa coluna além do viewport em 1024px,
     mesmo com overflow-x:auto no wrapper. */
  grid-template-columns: var(--sidebar-width) minmax(0, 1fr);
  grid-template-rows: var(--topbar-height) 1fr auto;
  min-height: 100vh;
  /* FRONTEND-FOUNDATION-SHELL-01 — a regra genérica `html, body { height:
     100% }` (acima) travava a ALTURA REAL do body em 100vh mesmo quando o
     conteúdo (main#app) era mais alto que isso; o grid "vazava" visualmente
     via overflow do viewport, mas a caixa do body — e portanto a área de
     contenção da sidebar sticky — nunca crescia. Resultado: em qualquer
     página mais alta que a tela, a sidebar chegava ao fim da sua própria
     caixa de 100vh e "descolava", saindo de tela ao rolar (o bug relatado:
     sidebar não persistente). `height: auto` aqui (mais específico que
     `body`, então vence) deixa o body crescer com o conteúdo de verdade;
     `min-height: 100vh` continua garantindo o piso em páginas curtas. */
  height: auto;
}

#app-shell { display: contents; }

.app-sidebar {
  grid-column: 1;
  grid-row: 1 / -1;
  /* FRONTEND-FOUNDATION-SHELL-01 — sidebar persistente: antes ela crescia
     junto com o grid inteiro (altura = conteúdo da página) e saía de tela
     ao rolar qualquer página mais longa que a viewport. sticky+top:0+
     height:100vh prende a sidebar à viewport sem duplicar scroll (ela não
     tem overflow próprio; se a navegação um dia crescer mais que a tela,
     isso é decisão de outra carta). */
  position: sticky;
  top: 0;
  align-self: start;
  height: 100vh;
  background: var(--sidebar-bg);
  border-right: 1px solid var(--sidebar-border);
  display: flex;
  flex-direction: column;
  padding: 20px 14px;
  gap: var(--space-1);
}

.sidebar-brand { padding: 6px 10px 18px; display: flex; flex-direction: column; gap: 8px; }
/* A logo foi desenhada para fundo claro (wordmark "Analytics" em navy
   escuro) — um selo branco garante contraste sobre a sidebar escura, sem
   precisar de uma segunda versão do arquivo. */
/* FRONTEND-IMPLEMENTATION-01.1 — o arquivo logo.webp tem ~1024px de altura
   mas o conteúdo visível (marca + wordmark) ocupa só a faixa central
   (linhas ~326–674 de 1024, medido via canvas), o resto é espaço vazio
   embutido no próprio asset. Sem recortar (não podemos gerar/alterar o
   arquivo de marca), width:100% herdava toda essa altura vazia e o selo
   branco virava um retângulo enorme dominando a sidebar. Fix: container
   com altura fixa + overflow:hidden + align-items:center recorta
   visualmente (sem tocar o arquivo) só a faixa com conteúdo real. */
.sidebar-logo-wrap {
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  background: #fff;
  border-radius: var(--radius-sm);
  padding: 0 10px;
  width: fit-content;
  height: 32px;
}
.sidebar-logo { display: block; width: 140px; max-width: none; height: auto; flex: none; }
.sidebar-brand-tagline { color: var(--sidebar-text); font-size: 11.5px; }

.sidebar-nav { display: flex; flex-direction: column; gap: var(--space-5); }
.sidebar-group { display: flex; flex-direction: column; gap: 2px; }
.sidebar-group-title {
  padding: 0 12px var(--space-1);
  color: var(--sidebar-text);
  opacity: 0.6;
  font-size: 10.5px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.07em;
}
.sidebar-link {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 12px;
  border-radius: var(--radius-sm);
  color: var(--sidebar-text);
  text-decoration: none;
  font-weight: 600;
  font-size: 13.5px;
  transition: background-color 0.12s ease, color 0.12s ease;
}
.sidebar-link .nav-icon { flex: none; opacity: 0.85; width: 16px; height: 16px; }
.sidebar-link:hover { background: var(--sidebar-bg-alt); color: #fff; }
/* FRONTEND-FOUNDATION-SHELL-01 — estado ativo em bronze (direção V1.1):
   linha esquerda + fundo sutil + peso maior, SEM bloco sólido e sem trocar
   a cor do texto para bronze (--sidebar-text-active já é branco, que é o
   que a carta pede — "não usar texto branco sobre bronze" refere-se a um
   preenchimento sólido de bronze, que este padrão não usa: o fundo aqui é
   --brand-bronze-soft a 14%, ainda dominado pelo navy da sidebar). */
.sidebar-link.active {
  background: var(--brand-bronze-soft);
  border-left: 3px solid var(--brand-bronze);
  padding-left: 9px;
  margin-left: -3px;
  color: var(--sidebar-text-active);
  font-weight: 700;
}
.sidebar-link.active .nav-icon { opacity: 1; }

.sidebar-account {
  display: grid;
  grid-template-columns: 9px minmax(0, 1fr);
  align-items: center;
  gap: 10px;
  margin-top: auto;
  padding: 12px;
  border: 1px solid var(--sidebar-border);
  border-radius: var(--radius);
  background: var(--sidebar-bg-alt);
  color: var(--sidebar-text-active);
  text-decoration: none;
}
.sidebar-account:hover { border-color: #3a4067; }
.sidebar-account-copy { display: flex; min-width: 0; flex-direction: column; }
.sidebar-account-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 13px; }
.sidebar-account-status { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--sidebar-text); font-size: 12px; }
.sidebar-account-dot { width: 9px; height: 9px; border-radius: 50%; background: var(--neutral-dot); box-shadow: 0 0 0 3px rgba(122, 127, 143, 0.16); }
.sidebar-account[data-tone="connected"] .sidebar-account-dot { background: #22c55e; box-shadow: 0 0 0 3px rgba(34, 197, 94, 0.16); }
.sidebar-account[data-tone="pending"] .sidebar-account-dot { background: #f59e0b; box-shadow: 0 0 0 3px rgba(245, 158, 11, 0.16); }

.app-topbar {
  grid-column: 2;
  grid-row: 1;
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 0 32px;
  background: var(--surface);
  border-bottom: 1px solid var(--border);
}
.app-topbar-title h1 { font-size: 20px; font-weight: 750; letter-spacing: -0.02em; }
.app-topbar-title .subtitle { margin-top: 1px; color: var(--text-muted); font-size: 13px; }

.logout-button {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  border: 1px solid var(--border-strong);
  background: var(--surface);
  border-radius: var(--radius-sm);
  padding: 7px 13px;
  cursor: pointer;
  color: var(--text-muted);
  font-weight: 600;
}
.logout-button:hover { color: var(--danger); border-color: var(--danger); background: var(--danger-bg); }

main#app { grid-column: 2; grid-row: 2; padding: 24px 32px 12px; max-width: 1360px; width: 100%; }
.footer { grid-column: 2; grid-row: 3; padding: 16px 32px 32px; color: var(--text-faint); font-size: 11.5px; max-width: 1360px; }

/* ==========================================================================
   FRONTEND-FOUNDATION-SHELL-01 — Mobile shell (novo: não existia nenhuma
   regra responsiva neste arquivo antes desta carta).

   Topbar = ações globais / Conta (hambúrguer abre navegação, avatar é link
   direto para /account.html). Drawer = navegação (mesma sidebar, agora um
   painel deslizante). Direção V1.1: largura do drawer ~248px, backdrop
   rgba(18,19,34,0.35), sem blur pesado.
   ========================================================================== */

.mobile-topbar {
  display: none;
  align-items: center;
  justify-content: space-between;
  height: var(--mobile-topbar-height);
  padding: 0 14px;
  background: var(--sidebar-bg);
  border-bottom: 1px solid var(--sidebar-border);
}
.mobile-menu-button,
.mobile-topbar-avatar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border-radius: var(--radius-sm);
  border: none;
  background: transparent;
  color: var(--sidebar-text-active);
  text-decoration: none;
  cursor: pointer;
}
.mobile-menu-button:hover { background: var(--sidebar-bg-alt); }
/* FRONTEND-IMPLEMENTATION-01.1 (bug real de QA) — o ícone de usuário sozinho
   (18px, traço fino, sem preenchimento) ficava perceptível apenas de perto;
   numa screenshot real ele se confundia com o fundo navy. Um selo circular
   dá ao controle de Conta um contorno reconhecível à direita da topbar sem
   depender de foto/avatar remoto (continua sendo o ícone neutro de usuário
   já usado no projeto, só ganha um fundo). */
.mobile-topbar-avatar {
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.12);
  border: 1px solid rgba(255, 255, 255, 0.22);
}
.mobile-topbar-avatar:hover { background: rgba(255, 255, 255, 0.2); }
/* Mesmo problema e mesma solução do .sidebar-logo-wrap acima: o asset tem
   espaço vazio embutido: sem recorte visual, espremer a imagem inteira em
   height:20px deixava o conteúdo real da logo ilegível (~7px de altura). */
.mobile-topbar-logo {
  display: inline-flex;
  align-items: center;
  overflow: hidden;
  background: #fff;
  border-radius: var(--radius-sm);
  padding: 4px 8px;
  height: 22px;
}
.mobile-topbar-logo img { display: block; width: 92px; max-width: none; height: auto; flex: none; }

.sidebar-backdrop {
  display: none;
  position: fixed;
  inset: 0;
  background: rgba(18, 19, 34, 0.35);
  z-index: 55;
}
.sidebar-backdrop.is-open { display: block; }

@media (max-width: 860px) {
  /* minmax(0, 1fr), não 1fr puro — mesma correção documentada no hotfix
     UX-01B mais abaixo neste arquivo (mantida aqui: esta regra agora é a
     dona da definição do grid mobile). */
  body:not(.login-body) {
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: var(--mobile-topbar-height) auto 1fr auto;
  }

  .mobile-topbar { display: flex; }

  /* A sidebar vira drawer: sai do fluxo do grid (position:fixed), some por
     padrão (translateX) e desliza para dentro só com .is-open. */
  .app-sidebar {
    position: fixed;
    top: 0;
    left: 0;
    bottom: 0;
    height: 100%;
    width: var(--drawer-width);
    max-width: 82vw;
    z-index: 60;
    transform: translateX(-100%);
    transition: transform 0.2s ease;
  }
  .app-sidebar.is-open { transform: translateX(0); }

  /* Redundante com o avatar da topbar (mesma função: acesso a Conta) —
     removido só no drawer mobile. No desktop o rodapé da sidebar continua,
     porque lá ele não duplica nada. */
  .sidebar-account { display: none; }

  /* Valores de padding/placement idênticos aos que o hotfix UX-01B já usava
     para estes 3 seletores — só o grid-row muda (uma linha a mais no topo,
     para o mobile-topbar), nada de espaçamento foi redesenhado aqui. */
  .app-topbar { grid-column: 1; grid-row: 2; padding: 14px 16px; flex-direction: column; align-items: flex-start; gap: 10px; max-width: none; }
  main#app { grid-column: 1; grid-row: 3; padding: 16px 16px 48px; max-width: none; }
  .footer { grid-column: 1; grid-row: 4; padding: 0 16px 32px; max-width: none; }
}

/* ==========================================================================
   Login (layout independente, fora do grid do app shell)
   ========================================================================== */

.login-body {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 100vh;
  background:
    radial-gradient(1200px 600px at 15% -10%, #eef0fd 0%, transparent 60%),
    var(--bg);
}
.login-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-md);
  padding: 36px 32px;
  width: 100%;
  max-width: 360px;
}
.login-card h1 { line-height: 0; }
.login-logo { display: block; width: 100%; max-width: 220px; height: auto; }
.login-card .subtitle { margin: 10px 0 22px; color: var(--text-muted); font-size: 12.5px; }
.login-card form { display: flex; flex-direction: column; gap: 8px; }
.login-card label { font-size: 12.5px; color: var(--text-muted); font-weight: 600; }
.login-card input {
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  padding: 10px 12px;
  font-size: 14px;
}
.login-card input:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

/* AUTH-PASSWORD-UX-01 — .password-field vira o item do flex column no lugar
   do <input> direto (por isso precisa de width:100% explícito no input:
   ele deixa de ser esticado automaticamente pelo align-items:stretch do
   pai). Botão de olho posicionado absoluto dentro do campo; reseta os
   mesmos estilos de `.login-card button` que `.link-button` já precisa
   resetar (mesmo precedente, ver comentário acima de .link-button). */
.password-field { position: relative; }
.password-field input { width: 100%; box-sizing: border-box; padding-right: 38px; }
/* AUTH-PASSWORD-RECOVERY-CANARY-FIX-01 — canário visual real reportou o
   ícone (antes um emoji, que ignora `color` porque renderiza como glyph
   colorido do sistema) praticamente invisível sem hover. passwordToggle.js
   agora injeta um SVG de contorno (stroke: currentColor), então `color` e
   `opacity` abaixo controlam a aparência de verdade em qualquer estado —
   nunca dependente de :hover para ficar visível. */
.password-toggle {
  position: absolute; top: 50%; right: 4px; transform: translateY(-50%);
  width: 28px; height: 28px; margin-top: 0 !important; padding: 0 !important;
  border: none !important; background: none !important; color: var(--text-muted);
  opacity: 1; display: flex; align-items: center; justify-content: center;
  line-height: 1; border-radius: var(--radius-sm); cursor: pointer;
}
.password-toggle:hover { background: var(--bg-subtle, var(--surface)) !important; color: var(--text); }
.password-toggle:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; color: var(--text); }

/* AUTH-PASSWORD-RECOVERY-CANARY-FIX-01 — estado de sucesso do "Esqueci
   minha senha", visualmente separado do formulário (canário real: usuário
   reportou falta de clareza depois do envio). Mesmo par de tokens já usado
   por .freshness-indicator[data-tone="ok"] para "tudo certo". */
.login-success-box {
  background: var(--success-bg); border: 1px solid #bbf7d0; border-radius: var(--radius-sm);
  padding: 16px; margin-top: 4px;
}
.login-success-box .subtitle { color: var(--success); font-weight: 700; margin: 0 0 8px; }
.login-card button {
  margin-top: 10px;
  border: none;
  background: var(--accent);
  color: #fff;
  border-radius: var(--radius-sm);
  padding: 11px;
  font-weight: 700;
  cursor: pointer;
  transition: background-color 0.12s ease;
}
.login-card button:hover { background: var(--accent-hover); }
.login-error { color: var(--danger); background: var(--danger-bg); border-radius: var(--radius-sm); padding: 9px 11px; margin-top: 16px; font-size: 13px; }
.login-hint { margin-top: 18px; color: var(--text-faint); font-size: 11.5px; }
/* SUBSCRIPTION-BACK-NAVIGATION-UX-01 — block (não inline-block): toda outra
   página só tem UM .login-back por vez (login.html, auth-callback.html),
   então o visual delas não muda; subscription.html é a primeira com dois
   (o link de volta e o botão "Sair da conta"), e inline-block deixava os
   dois espremidos na mesma linha em vez de empilhados. */
.login-back { display: block; margin-top: 16px; color: var(--text-muted); font-size: 12px; font-weight: 650; text-decoration: none; }
.login-back:hover { color: var(--accent); text-decoration: underline; text-underline-offset: 3px; }

/* AUTH-FOUNDATION-SUPABASE-01 — botão do Google fica FORA de <form>
   (nunca envia o form de email/senha por engano) mas ainda dentro de
   .login-card, então reseta explicitamente o visual "primário" que
   `.login-card button` aplicaria por padrão — mesmo precedente de
   .onboarding-actions button.integration-row-action:not(...). */
.google-signin-button {
  width: 100%; margin-top: 0; border: 1px solid var(--border-strong) !important;
  background: var(--surface) !important; color: var(--text) !important;
  border-radius: var(--radius-sm); padding: 11px; font-size: 14px; font-weight: 650; cursor: pointer;
}
.google-signin-button:hover { background: var(--bg-subtle, var(--surface)); }
.login-divider { display: flex; align-items: center; gap: 10px; margin: 16px 0; color: var(--text-faint); font-size: 11.5px; }
.login-divider::before, .login-divider::after { content: ''; flex: 1; height: 1px; background: var(--border); }

/* COMMERCIAL-TRIAL-GATE-01 — .login-back como <button> (subscription.html
   "Sair da conta"), nunca só <a>: reseta os defaults nativos de <button> E
   sobrescreve `.login-card button` (visual primário/vermelho aplicado a
   QUALQUER <button> dentro do cartão) para herdar o visual sutil de link
   que .login-back já tem como <a> em login.html/signup.html. Precisa do
   seletor composto (não só `.link-button`) para vencer a especificidade de
   `.login-card button`, que já combina elemento+classe. */
.link-button {
  background: none; border: none; color: var(--text-muted); font: inherit; font-weight: 650; padding: 0; cursor: pointer;
}
.link-button:hover { background: none; color: var(--accent); text-decoration: underline; text-underline-offset: 3px; }
/* SUBSCRIPTION-BACK-NAVIGATION-UX-01 — canário visual real: `.link-button`
   sozinho (0,1,0) nunca vencia `.login-card button` (0,1,1) — só o
   margin-top aplicava; background/border/color/padding/font-weight
   continuavam vindo do botão vermelho "primário", que é exatamente o
   visual que Cancelar/Reativar assinatura NUNCA deveriam ter (mesmo
   precedente do reset em .onboarding-actions button.integration-row-action,
   acima). Precisa do mesmo seletor composto para vencer a especificidade. */
.login-card button.link-button { margin-top: 16px; background: none; border: none; color: var(--text-muted); padding: 0; font-weight: 650; text-decoration: none; }
.login-card button.link-button:hover { background: none; color: var(--accent); text-decoration: underline; text-underline-offset: 3px; }

/* POST-TRIAL-COMMERCIAL-OVERLAY-01 — backdrop translúcido + blur LEVE
   (carta: "dashboard ainda perceptível", nunca escondido). z-index alto o
   bastante para ficar acima de qualquer sidebar/topbar/chart desta app
   (nenhum outro elemento usa acima de poucas centenas hoje). */
.commercial-lock-backdrop {
  position: fixed; inset: 0; z-index: 9999;
  background: rgba(15, 18, 34, 0.35);
  backdrop-filter: blur(3px); -webkit-backdrop-filter: blur(3px);
  display: flex; align-items: center; justify-content: center;
  padding: var(--space-4);
}
.commercial-lock-card {
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-lg); box-shadow: var(--shadow-md);
  width: 100%; max-width: 460px; max-height: calc(100vh - 32px); overflow-y: auto;
  padding: 28px 26px;
}
.commercial-lock-card h2 { font-size: 17px; margin: 0 0 8px; }
.commercial-lock-card p { font-size: 13.5px; color: var(--text-muted); margin: 0 0 16px; line-height: 1.5; }
.commercial-lock-feedback-label { font-size: 12.5px; font-weight: 650; color: var(--text); margin-bottom: 8px; }
.commercial-lock-feedback-options { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 4px; }
.commercial-lock-feedback-options button {
  border: 1px solid var(--border-strong); background: var(--surface); color: var(--text);
  border-radius: var(--radius-sm); padding: 8px 12px; font-size: 12.5px; font-weight: 600; cursor: pointer;
}
.commercial-lock-feedback-options button:hover:not(:disabled) { border-color: var(--accent); color: var(--accent); }
.commercial-lock-feedback-options button:disabled { opacity: 0.55; cursor: default; }
.commercial-lock-feedback-options button.commercial-lock-feedback-selected { background: var(--accent-soft); border-color: var(--accent); color: var(--accent); }
.commercial-lock-feedback-thanks { font-size: 12.5px; color: var(--success); font-weight: 600; margin: 4px 0 0; }
.commercial-lock-divider { border: none; border-top: 1px solid var(--border); margin: 20px 0; }
.commercial-lock-plan { display: flex; align-items: baseline; gap: 8px; margin-bottom: 10px; }
.commercial-lock-plan-name { font-size: 15px; font-weight: 700; color: var(--text); }
.commercial-lock-plan-price { font-size: 15px; font-weight: 700; color: var(--accent); }
.commercial-lock-benefits { list-style: none; margin: 0 0 18px; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.commercial-lock-benefits li { font-size: 12.5px; color: var(--text-muted); }
.commercial-lock-cta {
  width: 100%; border: none; background: var(--accent); color: #fff; border-radius: var(--radius-sm);
  padding: 12px; font-size: 14px; font-weight: 650; cursor: pointer;
}
.commercial-lock-cta:hover:not(:disabled) { background: var(--accent-hover); }
.commercial-lock-cta:disabled { opacity: 0.7; cursor: default; }
.commercial-lock-interest-note { font-size: 12.5px; color: var(--success); font-weight: 600; margin-top: 10px; text-align: center; }
.commercial-lock-logout { display: block; margin: 16px auto 0; }

/* SELF-SERVICE-ONBOARDING-01 — assistente de onboarding: mesmo cartão de
   login (.login-card), só um pouco mais largo para caber o resumo da
   Etapa 3 e as ações da Etapa 4 sem apertar. */
.onboarding-card { max-width: 440px; }
.onboarding-checklist { list-style: none; margin: 0 0 4px; padding: 0; display: flex; flex-direction: column; gap: 8px; }
.onboarding-checklist li { font-size: 13px; }
.onboarding-checklist-done { color: var(--success); font-weight: 600; }
.onboarding-checklist-pending { color: var(--text-faint); }
.onboarding-actions { display: flex; flex-direction: column; gap: 8px; margin-top: 16px; }
.onboarding-actions .integration-row-action { width: 100%; text-align: center; box-sizing: border-box; margin-top: 0; }
/* .login-card button já força fundo/cor sólidos em QUALQUER <button> do
   cartão (pensado para o único botão de login/signup) — aqui precisamos
   diferenciar a ação primária (Continuar) da secundária (Verificar
   novamente/Agora não), então a secundária reseta explicitamente para o
   visual "outline" que .integration-row-action já usa fora do login-card. */
.onboarding-actions button.integration-row-action:not(.integration-row-action-primary) {
  background: var(--surface); color: var(--text); border: 1px solid var(--border-strong); font-weight: 650;
}

/* ==========================================================================
   Filtros / estado
   ========================================================================== */

.filter-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 16px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 14px 18px;
  margin-bottom: 10px;
}
.filter-label {
  color: var(--text-muted);
  font-size: 12px;
  font-weight: 750;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.filter-presets { display: flex; flex-wrap: wrap; gap: 6px; }
.filter-presets button {
  border: 1px solid var(--border);
  background: var(--surface-sunken);
  border-radius: 999px;
  padding: 6px 13px;
  cursor: pointer;
  color: var(--text);
  font-weight: 500;
  transition: background-color 0.12s ease, color 0.12s ease, border-color 0.12s ease;
}
.filter-presets button:hover { border-color: var(--border-strong); }
.filter-presets button.active { background: var(--accent); border-color: var(--accent); color: #fff; }
.filter-custom, .filter-status { display: flex; align-items: center; gap: 6px; }
.filter-custom label, .filter-status label { color: var(--text-muted); font-size: 12.5px; font-weight: 600; }
.filter-custom input, .filter-status select {
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  padding: 6px 9px;
  background: var(--surface);
  color: var(--text);
}
.filter-custom button {
  border: 1px solid var(--accent);
  background: var(--accent-soft);
  color: var(--accent);
  border-radius: var(--radius-sm);
  padding: 6px 13px;
  cursor: pointer;
  font-weight: 600;
}
.filter-custom button:hover { background: var(--accent); color: #fff; }
.filter-compare { display: flex; align-items: center; gap: 6px; color: var(--text-muted); margin-left: auto; font-size: 13px; }

.period-readout { color: var(--text-muted); font-size: 13px; margin: 10px 2px 20px; font-weight: 600; }

/* P1B — indicador de frescor de dados (GET /api/data-freshness). Nunca
   bloqueia a página: fica oculto quando a própria checagem falha. */
.freshness-indicator {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  max-width: 720px;
  margin: -10px 0 20px;
  padding: 10px 13px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--text-muted);
  box-shadow: var(--shadow-sm);
}
.freshness-indicator[hidden] { display: none; }
.freshness-dot { width: 9px; height: 9px; margin-top: 6px; flex: none; border-radius: 50%; background: var(--neutral-dot); }
.freshness-copy { display: flex; flex-direction: column; gap: 1px; font-size: 13px; line-height: 1.45; }
.freshness-copy strong { color: var(--text); font-size: 13.5px; }
.freshness-indicator[data-tone="ok"] { border-color: #bbf7d0; background: var(--success-bg); }
.freshness-indicator[data-tone="ok"] .freshness-dot { background: var(--success); }
/* IMPLEMENTATION-02-OVERVIEW-V1.1 — "info"/UPDATING usava --accent (cor de
   marca) para um estado de loading, mesma regra de cor já corrigida em
   .state-loading (FRONTEND-FOUNDATION-SHELL-01): loading é sempre neutro,
   nunca a cor de marca. */
.freshness-indicator[data-tone="info"] { border-color: var(--border-strong); background: var(--loading-soft); }
.freshness-indicator[data-tone="info"] .freshness-dot { background: var(--loading); }
.freshness-indicator[data-tone="warn"] { border-color: #fde68a; background: var(--warning-bg); }
.freshness-indicator[data-tone="warn"] .freshness-dot { background: var(--warning); }
.freshness-indicator[data-tone="error"] { border-color: #fecaca; background: var(--danger-bg); }
.freshness-indicator[data-tone="error"] .freshness-dot { background: var(--danger); }

/* P3D — comparação com o período anterior (seção 6/10 da carta). O painel
   de resumo reaproveita kpiCard()/.kpi-delta (mesmo componente já usado na
   Visão Geral/Vendas) — só o grid é novo. .comparison-delta é a versão
   compacta da mesma convenção de cor (up/down/neutral), usada por linha de
   ranking e no drawer de detalhe; cor nunca é a única pista, o texto
   sempre traz o sinal por escrito. */
.comparison-panel {
  max-width: 900px;
  margin: -10px 0 20px;
  padding: 14px 16px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  box-shadow: var(--shadow-sm);
}
.comparison-panel[hidden] { display: none; }
.comparison-period { margin-bottom: 10px; }
.comparison-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 10px; }
.comparison-grid .kpi-card { margin-bottom: 0; }

.comparison-delta { display: block; margin-top: 3px; font-size: 11.5px; font-weight: 700; color: var(--text-faint); }
.comparison-delta.up { color: var(--success); }
.comparison-delta.down { color: var(--danger); }

.performance-detail-comparison-title { margin-top: 16px; }
.performance-detail-comparison dd.up { color: var(--success); }
.performance-detail-comparison dd.down { color: var(--danger); }
.performance-detail-comparison dd.neutral { color: var(--text-faint); font-weight: 500; }

.state-banner { padding: 13px 16px; border-radius: var(--radius); margin-bottom: 20px; border: 1px solid transparent; font-weight: 600; }
/* FRONTEND-FOUNDATION-SHELL-01 — "carregando" não é mais a cor de marca
   (regra de cor: marca ≠ estado semântico). Nenhuma outra .state-* mudou. */
.state-loading { background: var(--loading-soft); color: var(--loading); }
.state-error { background: var(--danger-bg); border-color: #fecaca; color: var(--danger); }
.state-warning { background: var(--warning-bg); border-color: #fde68a; color: var(--warning); }
.state-error:not([hidden]) { display: flex; align-items: center; justify-content: space-between; gap: 14px; }
.state-error button {
  flex: none;
  border: 1px solid currentColor;
  border-radius: var(--radius-sm);
  background: transparent;
  color: inherit;
  padding: 7px 11px;
  cursor: pointer;
  font-weight: 700;
}
.state-error button:hover { background: rgba(185, 28, 28, 0.06); }
.state-empty { background: var(--surface); border: 1px dashed var(--border-strong); color: var(--text-muted); }

/* BETA onboarding hotfix — conta ainda não conectada à Shopee
   (ACCOUNT_NOT_CONNECTED). Distinto de state-error: não é uma falha, é um
   próximo passo esperado do onboarding. */
.state-connect { background: var(--accent-soft); border: 1px solid var(--accent); color: var(--text); }
.state-connect-title { margin: 0 0 4px; font-weight: 700; }
.state-connect-text { margin: 0 0 12px; color: var(--text-muted); font-weight: 400; }
.state-connect-text:last-child { margin-bottom: 0; }
.state-connect-cta {
  display: inline-block; background: var(--accent); color: var(--accent-contrast);
  padding: 8px 16px; border-radius: var(--radius-sm); text-decoration: none; font-weight: 600;
}
.state-connect-cta:hover { background: var(--accent-hover); }

/* SELF-SERVICE-ONBOARDING-01, correção de UX — card de setup na Visão
   Geral, com uma linha por fonte (Shopee/Meta) em vez de um único CTA. */
.setup-card-sources { display: flex; flex-wrap: wrap; gap: 12px; margin-bottom: 4px; }
.setup-card-source {
  display: flex; align-items: center; gap: 10px; background: var(--surface);
  border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 10px 14px;
}
.setup-card-source-name { font-weight: 700; }
.setup-card-source-status { color: var(--text-faint); font-size: 12.5px; }
.setup-card-secondary { margin-top: 12px; font-size: 12.5px; }

/* ==========================================================================
   KPIs — hero é uma variante explícita (`kpiCard({ variant: 'hero' })`,
   UX-01A), não mais implícita por posição no DOM. Os cards que já
   apareciam em destaque (Comissão líquida na Visão Geral, Total de
   cliques em Cliques, Total vendido no Relatório mensal, o KPI único de
   Produtos) continuam exatamente com a mesma aparência — só a regra que
   decide "qual é hero" deixou de depender de `:first-child`.
   ========================================================================== */

.kpi-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: var(--space-3);
  margin-bottom: var(--space-5);
}
.kpi-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-sm);
  padding: var(--space-4) 18px;
}
.kpi-label { color: var(--text-muted); font-size: 11.5px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; }
.kpi-value { font-size: 23px; font-weight: 700; margin-top: 6px; letter-spacing: -0.01em; font-variant-numeric: tabular-nums; }
.kpi-sub { font-size: 12px; color: var(--text-faint); margin-top: 3px; }
.kpi-delta { font-size: 12px; font-weight: 600; margin-top: 8px; }
.kpi-delta.up { color: var(--success); }
.kpi-delta.down { color: var(--danger); }
.kpi-delta.neutral { color: var(--text-faint); }

/* FRONTEND-CONSOLIDATION-01 — cor do VALOR quando representa um resultado
   financeiro real (Resultado após mídia, ROI), nunca aplicada a ROAS/spend/
   contagens (carta: "ROAS não define cor de rentabilidade"). */
.kpi-value-positive { color: var(--success); }
.kpi-value-negative { color: var(--danger); }

/* FASE 02G — composição da Comissão Total (Shopee/Mercado Livre) dentro do
   MESMO card, linhas secundárias e compactas — nunca um novo KPI/card. */
.kpi-commission-breakdown { margin-top: 8px; display: flex; flex-direction: column; gap: 3px; }
.kpi-commission-breakdown-row { display: flex; justify-content: space-between; gap: 10px; font-size: 12px; color: var(--text-muted); }
.kpi-commission-breakdown-row span:last-child { font-variant-numeric: tabular-nums; font-weight: 600; }

/* Agrupamento de KPIs com rótulo de seção discreto acima. */
.kpi-group { margin-bottom: var(--space-5); }
.kpi-group-title {
  color: var(--text-faint);
  font-size: 11px;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  margin-bottom: var(--space-2);
}
.kpi-group .kpi-grid { margin-bottom: 0; }

/* FRONTEND-CONSOLIDATION-01 — hero deixou de ser um banner de largura
   total em gradiente (carta "DESIGN VISUAL": "evitar grandes banners
   laranja... todos os KPIs devem usar cards compactos e equivalentes;
   Comissão pode ter peso tipográfico maior, mas não ocupar uma linha
   inteira"). Mesmo card branco/borda/sombra de .kpi-card — só o valor
   ganha mais peso, e um traço de --brand à esquerda como único acento de
   cor (nunca 100% da superfície). */
.kpi-card-hero {
  position: relative;
  border-left: 3px solid var(--brand);
  padding-left: calc(18px - 2px);
}
.kpi-card-hero .kpi-value { font-size: 28px; }

/* Compatibilidade — .kpi-card-hero deixou de ocupar a linha inteira por
   padrão; quem realmente precisa disso (nenhuma página nova) pode aplicar
   .kpi-card-hero-full explicitamente. */
.kpi-card-hero-full { grid-column: 1 / -1; }

/* ==========================================================================
   PRODUCT-UX-02 — Visão Geral: Comissão como hero isolado (seção 4),
   destaques "O que está funcionando" (seção 9) e seletor de métrica do
   gráfico de evolução (seção 11). O hero reaproveita exatamente
   .kpi-card-hero (mesmo componente/estilo de Análise de vendas) — só
   ganhou uma seção própria em vez de dividir o grid com os 3 secundários,
   para que a diferença de hierarquia fique clara mesmo antes de ler o
   valor (carta, "hierarquia, não 4 cards idênticos").
   ========================================================================== */

.hero-section { margin-bottom: var(--space-3); }
.hero-section .kpi-card-hero { grid-column: auto; }

.kpi-grid-secondary { grid-template-columns: repeat(3, 1fr); }

.highlights-panel { padding: 20px 22px; }
.highlights-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: var(--space-3);
}
.highlight-card {
  background: var(--surface-sunken);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 16px 18px;
  transition: border-color 0.15s ease, transform 0.15s ease;
}
.highlight-card:hover { border-color: var(--border-strong); transform: translateY(-1px); }
.highlight-name {
  font-size: 18px;
  font-weight: 700;
  margin-top: 6px;
  letter-spacing: -0.005em;
  overflow-wrap: anywhere;
}
.highlight-link { display: inline-block; margin-top: 10px; }
.highlight-empty-text { color: var(--text-faint); font-size: 12.5px; margin-top: 8px; line-height: 1.5; }

.chart-metric-tabs { display: flex; gap: 6px; }
.chart-metric-tabs button {
  border: 1px solid var(--border);
  background: var(--surface);
  border-radius: 999px;
  padding: 5px 13px;
  cursor: pointer;
  color: var(--text-muted);
  font-weight: 600;
  font-size: 12.5px;
  transition: background-color 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}
.chart-metric-tabs button:hover { border-color: var(--border-strong); color: var(--text); }
.chart-metric-tabs button.active { background: var(--accent); border-color: var(--accent); color: #fff; }

/* Checkbox de comparação desabilitado (período inclui T-0, seção 5/6) —
   discreto, sem banner: só reduz opacidade e troca o cursor. O `title`
   (tooltip nativo) explica o motivo sob demanda. */
.filter-compare:has(input:disabled) { opacity: 0.55; cursor: not-allowed; }

/* ==========================================================================
   Painéis / cards de conteúdo
   ========================================================================== */

.panel {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-sm);
  padding: 18px 20px;
  margin-bottom: 20px;
}
.panel-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 14px; gap: 12px; }
.panel-header h2, .panel-header h3 { font-size: 14.5px; font-weight: 700; }
.panel-header select { border: 1px solid var(--border-strong); border-radius: var(--radius-sm); padding: 5px 9px; background: var(--surface); }
.panel-note { color: var(--text-faint); font-size: 11.5px; margin-top: 10px; line-height: 1.5; }
.panel-row { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; }
.panel-half { margin-bottom: 0; }
.panel-link { font-size: 12.5px; color: var(--accent); text-decoration: none; font-weight: 600; }
.panel-link:hover { text-decoration: underline; }

.context-note {
  display: flex;
  flex-direction: column;
  gap: 3px;
  margin: -8px 0 20px;
  padding: 13px 16px;
  border-left: 3px solid var(--accent);
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
  background: var(--accent-soft);
  color: var(--text-muted);
  font-size: 13px;
  line-height: 1.5;
}
.context-note strong { color: var(--text); }

/* ==========================================================================
   PRODUCT-FRONTEND-META-01 — módulo Tráfego Pago (Meta Ads, empty-state) e
   demais páginas novas desta carta (Sincronizações, Integrações, Conta).
   Reaproveita tokens/superfícies já existentes (--surface, --border,
   --accent, .kpi-label, .panel) — nenhuma cor, sombra ou raio novo.
   ========================================================================== */

/* Empty-state de página inteira (Visão Meta / meta.html) — mesma linguagem
   de .state-connect, mas centralizado e sem depender de um estado de
   carregamento de dados (esta página nunca busca dados). */
.meta-empty-state {
  max-width: 640px;
  margin: 40px auto;
  padding: 40px 32px;
  text-align: center;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
}
.meta-empty-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 52px;
  height: 52px;
  border-radius: 50%;
  background: var(--accent-soft);
  color: var(--accent);
  margin-bottom: 18px;
}
.meta-empty-state h1 { font-size: 22px; font-weight: 750; letter-spacing: -0.01em; }
.meta-empty-state p { margin-top: 10px; color: var(--text-muted); font-size: 14px; line-height: 1.55; }
.meta-empty-cta {
  display: inline-block;
  margin-top: 18px;
  background: var(--accent);
  color: var(--accent-contrast);
  padding: 10px 20px;
  border-radius: var(--radius-sm);
  text-decoration: none;
  font-weight: 650;
  font-size: 13.5px;
}
.meta-empty-cta:hover { background: var(--accent-hover); }
.meta-empty-note { margin-top: 22px; color: var(--text-faint); font-size: 11.5px; }

/* Grade de KPIs "bloqueados" — mesmo componente .kpi-card em espírito
   (label + valor), mas o valor vira um convite, nunca um número inventado. */
.meta-preview-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: var(--space-3);
  margin-top: 24px;
  text-align: left;
}
.meta-preview-card {
  background: var(--surface-sunken);
  border: 1px dashed var(--border-strong);
  border-radius: var(--radius);
  padding: 14px 16px;
}
.meta-preview-locked {
  display: block;
  margin-top: 6px;
  color: var(--text-faint);
  font-size: 13px;
  font-weight: 600;
}
.meta-dashboard-panel .meta-preview-grid { margin-top: 0; }

/* Tabela preparada (Campanhas Meta) — cabeçalho real, sem nenhuma linha de
   dado inventada; o convite para conectar substitui o corpo da tabela. */
.meta-table-panel .table-scroll { margin-bottom: 0; }
.meta-table-prepared { opacity: 0.55; }
.meta-table-prepared tbody { display: none; }
.meta-table-empty {
  padding: 28px 20px;
  text-align: center;
  border-top: 1px solid var(--border);
  margin-top: -1px;
}
.meta-table-empty p { color: var(--text-muted); font-size: 13px; line-height: 1.55; max-width: 480px; margin: 0 auto; }
.meta-table-empty p:first-child { color: var(--text); }
.meta-table-empty .meta-empty-cta { margin-top: 14px; }

/* Atribuição — diagrama conceitual Campanha/AdSet/Ad -> Sub ID -> Produto/
   Pedido (carta: "mostrar conceito", nenhuma associação real ainda). */
.attribution-diagram {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 20px;
  padding: 24px 8px;
}
.attribution-column { display: flex; flex-direction: column; gap: 8px; }
.attribution-column-label {
  color: var(--text-faint);
  font-size: 11.5px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  margin-bottom: 2px;
}
.attribution-node {
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface-sunken);
  padding: 10px 14px;
  font-size: 13px;
  font-weight: 650;
}
.attribution-bridge { display: flex; flex-direction: column; align-items: center; gap: 6px; }
.attribution-bridge-line { width: 100%; min-width: 40px; border-top: 2px dashed var(--accent); }
.attribution-bridge-label {
  font-size: 11px;
  font-weight: 700;
  color: var(--accent);
  background: var(--accent-soft);
  border-radius: 999px;
  padding: 3px 10px;
  white-space: nowrap;
}
.attribution-methods { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-3); }
.attribution-method-card {
  background: var(--surface-sunken);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 16px;
}
.attribution-method-badge {
  display: inline-block;
  font-size: 11.5px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--accent);
  margin-bottom: 8px;
}
.attribution-method-card p { color: var(--text-muted); font-size: 13px; line-height: 1.5; }

/* META-ATTRIBUTION-01 — dashboard funcional: formulário de nova associação,
   fallback manual de 5 slots, botão-link e barra de cobertura. Reaproveita
   os mesmos tokens/inputs/botões nativos já usados por integrations.js
   (select simples, button simples) — nenhum componente de formulário novo. */
.attribution-mapping-form {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-3);
}
.attribution-mapping-form select { min-width: 180px; }
.link-button {
  background: none;
  border: none;
  padding: 0;
  color: var(--accent);
  font-size: inherit;
  font-weight: 600;
  cursor: pointer;
  text-decoration: underline;
}
.link-button:hover { color: var(--accent-hover); }
.attribution-subid-manual-form {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
  gap: var(--space-3);
  margin-top: var(--space-3);
}
.attribution-subid-manual-form input {
  padding: 8px 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  font-size: 13px;
}
.attribution-subid-manual-form button { grid-column: 1 / -1; }
.attribution-coverage {
  margin-top: var(--space-3);
  font-size: 13px;
  color: var(--text-muted);
}
.attribution-coverage-bar {
  height: 6px;
  border-radius: 999px;
  background: var(--surface-sunken);
  overflow: hidden;
  margin-top: 6px;
}
.attribution-coverage-bar-fill { height: 100%; background: var(--accent); }

/* Sincronizações — reaproveita o vocabulário de tom já usado pelo
   freshness-indicator (ok/info/warn/error), num cartão de página inteira em
   vez de uma linha compacta. */
.sync-status-body { display: flex; align-items: flex-start; gap: 12px; }
.sync-status-dot {
  flex: none;
  width: 11px;
  height: 11px;
  margin-top: 3px;
  border-radius: 50%;
  background: var(--neutral-dot);
}
.sync-status-panel[data-tone="ok"] .sync-status-dot { background: var(--success); }
.sync-status-panel[data-tone="info"] .sync-status-dot { background: var(--accent); }
.sync-status-panel[data-tone="warn"] .sync-status-dot { background: var(--warning); }
.sync-status-panel[data-tone="error"] .sync-status-dot { background: var(--danger); }
.sync-status-copy { display: flex; flex-direction: column; gap: 3px; }
.sync-status-copy strong { font-size: 15px; }
.sync-status-copy span { color: var(--text-muted); font-size: 13px; }

/* Integrações — lista simples, uma linha por fonte de dados. */
.integration-list { display: flex; flex-direction: column; gap: var(--space-3); margin-bottom: var(--space-5); }
.integration-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-sm);
  padding: 16px 20px;
}
.integration-row-main { display: flex; flex-direction: column; gap: 3px; }
.integration-row-name { font-weight: 700; font-size: 14.5px; }
.integration-row-status { font-size: 12.5px; color: var(--success); font-weight: 600; }
.integration-row-status-pending { color: var(--text-faint); }
.integration-row-action {
  flex: none;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  padding: 8px 16px;
  color: var(--text);
  text-decoration: none;
  font-weight: 650;
  font-size: 13px;
}
.integration-row-action:hover { border-color: var(--text-faint); }
.integration-row-action-primary { background: var(--accent); border-color: var(--accent); color: var(--accent-contrast); }
.integration-row-action-primary:hover { background: var(--accent-hover); border-color: var(--accent-hover); }

/* P3B — Performance Explorer. A leitura segue summary -> ranking ->
   detalhe sem criar uma segunda linguagem visual para o produto. */
.explorer-toolbar {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 16px;
}
.explorer-toolbar .view-tabs { margin-bottom: 0; }
.view-tabs button:disabled { opacity: 0.45; cursor: not-allowed; }
.explorer-sort { display: flex; align-items: center; gap: 9px; color: var(--text-muted); font-size: 13px; font-weight: 650; }
.explorer-sort select {
  min-height: 40px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--text);
  padding: 7px 34px 7px 10px;
}
.performance-summary {
  display: grid;
  grid-template-columns: minmax(210px, 0.7fr) minmax(0, 2fr);
  gap: 24px;
  padding: 22px;
  margin-bottom: 20px;
  border: 1px solid var(--sidebar-border);
  border-radius: var(--radius-lg);
  background: var(--sidebar-bg);
  color: var(--sidebar-text-active);
  box-shadow: var(--shadow-md);
}
.performance-summary[hidden], .performance-ranking-panel[hidden] { display: none; }
.eyebrow { color: var(--text-muted); font-size: 11px; font-weight: 800; letter-spacing: 0.07em; text-transform: uppercase; }
.performance-summary .eyebrow { color: var(--sidebar-text); }
.performance-summary-heading h2 { margin-top: 4px; font-size: 22px; line-height: 1.2; letter-spacing: -0.02em; }
.performance-summary-heading > p:last-child { margin-top: 10px; color: var(--sidebar-text); font-size: 13px; }
.performance-decision-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px; }
.performance-decision-card {
  min-width: 0;
  padding: 15px;
  border: 1px solid var(--sidebar-border);
  border-radius: var(--radius);
  background: var(--sidebar-bg-alt);
}
.performance-decision-label { color: var(--sidebar-text); font-size: 11px; font-weight: 750; text-transform: uppercase; letter-spacing: 0.04em; }
.performance-decision-name { margin-top: 8px; overflow-wrap: anywhere; font-size: 17px; line-height: 1.25; }
.performance-decision-value { margin-top: 5px; color: #fdba74; font-size: 13px; font-weight: 750; }
.performance-highlights { padding: 0; overflow: hidden; }
.performance-highlights[hidden] { display: none; }
.performance-highlights-header { padding: 18px 20px 14px; margin: 0; border-bottom: 1px solid var(--border); }
.performance-highlights-header h2 { margin-top: 2px; font-size: 18px; }
.performance-highlights-list {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 0;
  margin: 0;
  padding: 0;
  list-style: none;
}
.performance-highlight-card { min-width: 0; border-right: 1px solid var(--border); border-bottom: 3px solid var(--border); }
.performance-highlight-card.positive { border-bottom-color: var(--success); }
.performance-highlight-card.negative { border-bottom-color: var(--danger); }
.performance-highlight-content {
  display: flex;
  width: 100%;
  min-height: 168px;
  flex-direction: column;
  align-items: flex-start;
  gap: 7px;
  padding: 17px 18px;
  border: 0;
  background: var(--surface);
  color: var(--text);
  text-align: left;
  font: inherit;
}
button.performance-highlight-content { cursor: pointer; }
button.performance-highlight-content:hover,
button.performance-highlight-content:focus-visible { background: var(--accent-soft); outline: 2px solid var(--accent); outline-offset: -2px; }
.performance-highlight-label { color: var(--text-muted); font-size: 11px; font-weight: 800; letter-spacing: 0.04em; text-transform: uppercase; }
.performance-highlight-title { overflow-wrap: anywhere; font-size: 14px; line-height: 1.45; }
.performance-highlight-detail { overflow-wrap: anywhere; color: var(--text-muted); font-size: 12px; line-height: 1.45; }
.performance-highlight-action { margin-top: auto; color: var(--accent); font-size: 12px; font-weight: 750; }
.performance-ranking-panel { padding: 0; overflow: hidden; }
.performance-ranking-header { padding: 18px 20px 14px; margin: 0; border-bottom: 1px solid var(--border); }
.performance-ranking-header h2 { margin-top: 2px; font-size: 18px; }
.result-count { color: var(--text-muted); font-size: 12px; font-weight: 650; }
.performance-list { margin: 0; padding: 0; list-style: none; }
.performance-list-item {
  display: grid;
  grid-template-columns: 42px minmax(180px, 1fr) minmax(150px, 0.5fr) minmax(220px, 0.7fr) auto;
  align-items: center;
  gap: 16px;
  min-width: 0;
  padding: 15px 20px;
  border-bottom: 1px solid var(--border);
}
.performance-list-item:last-child { border-bottom: 0; }
.performance-list-item:hover { background: var(--surface-sunken); }
.performance-rank { color: var(--text-faint); font-size: 12px; font-weight: 800; font-variant-numeric: tabular-nums; }
.performance-identity { display: flex; min-width: 0; flex-direction: column; gap: 3px; }
.performance-name { overflow-wrap: anywhere; font-size: 14px; line-height: 1.35; }
.performance-id { overflow: hidden; color: var(--text-faint); font-size: 11px; text-overflow: ellipsis; white-space: nowrap; }
.performance-primary-value { display: flex; flex-direction: column; align-items: flex-end; gap: 2px; text-align: right; }
.performance-primary-value span { color: var(--text-muted); font-size: 11px; }
.performance-primary-value strong { font-size: 16px; font-variant-numeric: tabular-nums; }
.performance-supporting { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
.performance-supporting div { min-width: 0; text-align: right; }
.performance-supporting dt { color: var(--text-faint); font-size: 10.5px; }
.performance-supporting dd { margin-top: 2px; font-size: 12.5px; font-weight: 700; font-variant-numeric: tabular-nums; }
.performance-detail-button {
  min-height: 36px;
  padding: 7px 11px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--accent);
  cursor: pointer;
  font-size: 12px;
  font-weight: 700;
}
.performance-detail-button:hover, .performance-detail-button:focus-visible { border-color: var(--accent); background: var(--accent-soft); }
.performance-detail-name { overflow-wrap: anywhere; font-size: 20px; font-weight: 750; line-height: 1.25; }
.performance-detail-id { margin-top: 5px; overflow-wrap: anywhere; color: var(--text-faint); font-size: 12px; }
.performance-detail-metrics { margin-top: 22px; }
.performance-detail-metrics dd { overflow-wrap: anywhere; font-variant-numeric: tabular-nums; }
.performance-boundary { margin-top: 0; }

.back-link { display: inline-block; font-size: 12.5px; color: var(--text-faint); text-decoration: none; margin: -6px 0 14px; }
.back-link:hover { color: var(--accent); text-decoration: underline; }

/* BR-02/03 — formulário de Conectar Shopee (Configurações). */
.connect-shopee-form { display: flex; flex-direction: column; gap: 10px; }
.connect-shopee-form button { align-self: flex-start; margin-top: 4px; }

.chart-container { width: 100%; }
.chart-bar { fill: var(--accent); }
.chart-gridline { stroke: var(--border); stroke-width: 1; shape-rendering: crispEdges; }
.chart-axis-label { font-size: 9.5px; fill: var(--text-faint); }
.chart-empty { color: var(--text-faint); text-align: center; padding: 36px 0; font-size: 13px; }

/* ==========================================================================
   PRODUCT-UX-02D — "Evolução no período" (Visão Geral): renderer novo de
   linha + área sutil (frontend/js/lineAreaChart.js). Isolado do bar chart
   acima (.chart-bar/.chart-gridline/.chart-axis-label/.chart-empty
   continuam servindo ambos sem conflito — nenhuma regra aqui os altera).
   ========================================================================== */

.chart-selection-readout {
  display: flex;
  align-items: baseline;
  gap: 10px;
  margin-bottom: 10px;
}
.chart-selection-date { color: var(--text-muted); font-size: 12.5px; font-weight: 600; }
.chart-selection-value { color: var(--text); font-size: 19px; font-weight: 700; font-variant-numeric: tabular-nums; }

.line-area-chart { overflow: visible; }
.chart-area { fill: var(--accent); fill-opacity: 0.12; stroke: none; }
.chart-line { fill: none; stroke: var(--accent); stroke-width: 2.25; stroke-linejoin: round; stroke-linecap: round; }
.chart-guide {
  stroke: var(--border-strong);
  stroke-width: 1;
  pointer-events: none;
}
.chart-dot {
  fill: var(--accent);
  stroke: var(--surface);
  stroke-width: 2;
  pointer-events: none;
}
.chart-hit-layer { cursor: pointer; touch-action: pan-y; }

@media (prefers-reduced-motion: reduce) {
  .chart-guide, .chart-dot { transition: none !important; }
}

/* V1 Beta, seções 8/10/21 — o gráfico de evolução é o elemento visual mais
   importante de Visão Geral/Vendas/Cliques: mais respiro ao redor dele do
   que os demais painéis. */
.panel-chart-main { padding: 24px 26px 20px; }
.panel-chart-main .panel-header { margin-bottom: 20px; }

.click-upload-row { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; margin-top: 6px; }
.click-upload-row input[type="file"] { flex: 1 1 260px; min-width: 0; font-size: 12.5px; color: var(--text-muted); }
.click-upload-row button {
  border: none; border-radius: var(--radius-sm); background: var(--accent); color: #fff;
  padding: 8px 18px; font-weight: 600; font-size: 13px; cursor: pointer;
}
.click-upload-row button:disabled { background: var(--border-strong); color: var(--text-faint); cursor: not-allowed; }
.click-import-result { margin-top: 12px; padding: 10px 14px; border-radius: var(--radius-sm); font-size: 12.5px; line-height: 1.6; }
.click-import-result.success { background: var(--accent-soft); color: var(--accent); }
.click-import-result.error { background: var(--danger-bg); color: var(--danger); }

.status-body { display: flex; align-items: center; gap: 24px; }
.status-pending { stroke: var(--warning); }
.status-completed { stroke: var(--success); }
.status-cancelled { stroke: var(--danger); }
.status-other { stroke: var(--neutral-dot); }

/* ==========================================================================
   Tabelas
   ========================================================================== */

.table-scroll { width: 100%; max-width: 100%; overflow-x: auto; overscroll-behavior-inline: contain; }
.table-scroll:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; border-radius: var(--radius-sm); }
.table-scroll .data-table { min-width: max-content; }
.data-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.data-table th, .data-table td { padding: 10px 10px; border-bottom: 1px solid var(--border); text-align: left; }
.data-table th {
  color: var(--text-muted);
  font-weight: 700;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  border-bottom: 1px solid var(--border-strong);
}
.data-table tbody tr:hover { background: var(--surface-sunken); }
.data-table .num { text-align: right; font-variant-numeric: tabular-nums; }
/* Mesma regra de tom de .kpi-value-positive/negative, aplicada a uma
   célula de tabela (Resultado/ROI) — nunca a ROAS. */
.data-table .num.positive { color: var(--success); font-weight: 700; }
.data-table .num.negative { color: var(--danger); font-weight: 700; }

/* FRONTEND-CONSOLIDATION-01C — carta "PERFORMANCE REPROVADA": tabelas
   densas viravam "dump de banco". .table-compact aperta o espaçamento das
   tabelas de decisão (Produtos/Canais/Sub IDs) que agora têm poucas
   colunas por design, não por espremer texto. */
.table-compact th, .table-compact td { padding: 9px 10px; font-size: 12.5px; }

/* Nomes de produto longos nunca quebram o layout da tabela — corta só
   visualmente (title carrega o texto completo), nunca no DOM. */
.truncate-cell { max-width: 320px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Nome (campanha/produto/canal/Sub ID) em destaque à esquerda, status/
   contexto como legenda discreta abaixo — reduz colunas sem perder
   informação (carta: "menos decoração, mais hierarquia"). */
.entity-cell { display: flex; flex-direction: column; gap: 2px; }
.entity-cell-name { font-weight: 650; color: var(--text); }
.entity-cell-meta { font-size: 11.5px; color: var(--text-faint); }
.entity-cell-meta.shared-note { font-style: italic; }

/* Estado financeiro da campanha (Rentável/Prejuízo/Sem conversão/Sem
   associação) — texto + ponto de cor, nunca um badge grande (carta: "sem
   transformar em badges exagerados"). Reaproveita a linguagem visual já
   usada por .status-dot (Pedidos). */
.finance-state { display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px; font-weight: 600; white-space: nowrap; }
.finance-state-dot { width: 7px; height: 7px; border-radius: 50%; flex: none; }
.finance-state-profitable .finance-state-dot { background: var(--success); }
.finance-state-profitable { color: var(--success); }
.finance-state-loss .finance-state-dot { background: var(--danger); }
.finance-state-loss { color: var(--danger); }
.finance-state-no-conversion .finance-state-dot { background: var(--warning); }
.finance-state-no-conversion { color: var(--warning); }
.finance-state-unmapped .finance-state-dot { background: var(--neutral-dot); }
.finance-state-unmapped { color: var(--text-faint); }

/* Cobertura de atribuição — elemento compacto e independente, nunca
   dentro do grid de KPIs financeiros (carta: "não como KPI financeiro
   principal"). */
.coverage-compact-panel {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 12px 16px;
  margin-bottom: var(--space-3);
}
.coverage-compact-panel[hidden] { display: none; }

/* CONSOLIDATION-01B — "Vínculos de atribuição": painel-resumo compacto
   logo ANTES dos filtros/tabela de Mídia Paga (carta: vincular Campanha<->
   Sub ID é função central, precisa ser percebida "em segundos", nunca
   escondida atrás de scroll/coluna distante). Informativo, nunca um alert
   vermelho grande. */
.linking-summary-panel { display: flex; align-items: center; justify-content: space-between; gap: var(--space-4); flex-wrap: wrap; }
.linking-summary-main { flex: 1; min-width: 240px; }
.linking-summary-main .panel-header { margin-bottom: 6px; }
.linking-summary-stats { display: flex; flex-wrap: wrap; gap: 6px 20px; font-size: 14px; color: var(--text); line-height: 1.6; }
.linking-summary-stats strong { font-weight: 700; }
.linking-summary-stat { display: inline-flex; align-items: center; gap: 7px; }
/* CONSOLIDATION-01C — indicador pequeno e discreto, nunca um alert
   vermelho grande: verde/neutro quando não há pendência, âmbar só quando
   há campanhas sem vínculo. */
.linking-summary-dot { width: 7px; height: 7px; border-radius: 50%; flex: none; }
.linking-summary-dot-ok { background: var(--success); }
.linking-summary-dot-pending { background: var(--warning); }

/* Botão pequeno/discreto para a ação de vínculo na tabela — substitui o
   link sublinhado (carta "REFINAMENTO 2": ação visível sem poluir a
   tabela). */
.table-action-chip {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  border: 1px solid var(--border-strong);
  background: var(--surface);
  border-radius: 999px;
  padding: 4px 10px;
  font-size: 11.5px;
  font-weight: 650;
  color: var(--text);
  cursor: pointer;
  white-space: nowrap;
}
.table-action-chip:hover { border-color: var(--accent); color: var(--accent); }

/* Coluna "Vínculos" da tabela de campanhas — sempre a 2ª coluna, nunca no
   fim da tabela nem escondida atrás de scroll horizontal (carta). */
.linking-cell { display: flex; flex-direction: column; align-items: flex-start; gap: 6px; }
.linking-cell-count { font-size: 12.5px; font-weight: 650; color: var(--text); }
.linking-cell-count.linking-cell-count-empty { color: var(--text-faint); font-weight: 500; }
.linking-cell-chips { display: flex; flex-wrap: wrap; gap: 4px; max-width: 220px; }
.subid-chip {
  display: inline-block;
  max-width: 150px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  background: var(--surface-sunken);
  border-radius: 999px;
  padding: 2px 8px;
  font-size: 11px;
  color: var(--text-muted);
}
.linking-cell-more { font-size: 11px; color: var(--text-faint); align-self: center; }

/* "Campanha" e "Vínculos" ficam sticky nas duas primeiras colunas — a ação
   de vincular nunca deve exigir rolagem horizontal para ser descoberta.
   Larguras fixas (não auto) são necessárias para o `left` da 2ª coluna ser
   previsível. */
.linking-table th:nth-child(1), .linking-table td:nth-child(1) {
  position: sticky; left: 0; z-index: 1; background: var(--surface);
  min-width: 200px; max-width: 200px;
}
.linking-table th:nth-child(2), .linking-table td:nth-child(2) {
  position: sticky; left: 200px; z-index: 1; background: var(--surface);
  min-width: 210px; max-width: 210px;
  box-shadow: 2px 0 4px rgba(15, 18, 34, 0.06);
}
.linking-table thead th:nth-child(1), .linking-table thead th:nth-child(2) { z-index: 2; background: var(--surface-sunken); }
.linking-table tbody tr:hover td:nth-child(1), .linking-table tbody tr:hover td:nth-child(2) { background: var(--surface-sunken); }

/* Drawer "Gerenciar vínculos" (visão focada em campanhas sem Sub ID) —
   mesma linguagem de .attention-item, em formato de cartão por ser mais
   denso (spend + cliques + CTA). */
.manage-links-list { list-style: none; margin: 12px 0 0; padding: 0; display: flex; flex-direction: column; gap: var(--space-3); }
.manage-links-item {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 12px 14px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  flex-wrap: wrap;
}
.manage-links-item-name { font-weight: 650; }
.manage-links-item-meta { color: var(--text-faint); font-size: 12px; margin-top: 2px; }
.manage-links-item-status { color: var(--text-faint); font-size: 12.5px; margin-right: var(--space-3); }

/* Checklist multi-seleção de Sub IDs (drawer de detalhe) — cada opção é um
   checkbox + RAW completo + origem, nunca "1: X | 2: Y". */
.subid-checklist { list-style: none; margin: 10px 0; padding: 0; max-height: 220px; overflow-y: auto; border: 1px solid var(--border); border-radius: var(--radius-sm); }
.subid-checklist-item { border-bottom: 1px solid var(--border); }
.subid-checklist-item:last-child { border-bottom: 0; }
.subid-checklist-item label { display: flex; align-items: center; gap: 10px; padding: 9px 12px; cursor: pointer; }
.subid-checklist-item label:hover { background: var(--surface-sunken); }
.subid-checklist-item input[type="checkbox"] { flex: none; }
.subid-checklist-item-text { display: flex; flex-direction: column; min-width: 0; }
.subid-checklist-item-raw { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 13px; }
.subid-checklist-item-origin { font-size: 11.5px; color: var(--text-faint); }
/* META-MAPPING-DOUBLE-SUBMIT-UX-FIX-01 — estado "selecionado" discreto
   (fundo leve + borda esquerda de destaque), nunca chamativo. */
.subid-checklist-item-selected { background: var(--accent-soft); }
.subid-checklist-item-selected label { border-left: 3px solid var(--accent); padding-left: 9px; }
.subid-checklist-item input[type="checkbox"]:disabled { cursor: not-allowed; opacity: 0.6; }
.drawer-add-result-item { font-size: 12.5px; margin-top: 6px; padding: 6px 9px; border-radius: var(--radius-sm); }
.drawer-add-result-item.success { background: var(--success-bg); color: var(--success); }
.drawer-add-result-item.error { background: var(--danger-bg); color: var(--danger); }
.drawer-panel-wide { width: min(620px, 100%); }

/* META-MAPPING-DOUBLE-SUBMIT-UX-FIX-01 — spinner CSS puro (sem lib nova)
   para "Adicionando…"; :disabled já esmaece o botão via estilo nativo do
   browser, aqui só o spinner + evita cursor de clique. */
#drawer-add-selected.is-saving { cursor: default; position: relative; padding-left: 30px; }
#drawer-add-selected.is-saving::before {
  content: ''; position: absolute; left: 12px; top: 50%; width: 13px; height: 13px; margin-top: -6.5px;
  border: 2px solid rgba(255, 255, 255, 0.5); border-top-color: #fff; border-radius: 50%;
  animation: drawer-spin 0.7s linear infinite;
}
@keyframes drawer-spin { to { transform: rotate(360deg); } }

/* Segmented control "Analisar por" (Performance) e filtros de seleção
   simples (status/atribuição/resultado em Mídia Paga, origem em
   Performance) — mesmos inputs nativos já usados em toda a aplicação. */
.filter-select-group { display: flex; align-items: center; gap: 6px; }
.filter-select-group label { color: var(--text-muted); font-size: 12.5px; font-weight: 600; white-space: nowrap; }
.filter-select-group select {
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  padding: 6px 9px;
  background: var(--surface);
  color: var(--text);
}
.filter-search input {
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  padding: 6px 10px;
  background: var(--surface);
  color: var(--text);
  min-width: 200px;
}

/* "Onde estou ganhando" / "Onde estou perdendo" (Visão Geral) — grid de
   cartões compactos, mesma linguagem visual de .highlight-card. */
.insight-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: var(--space-3);
}
.insight-card {
  background: var(--surface-sunken);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 14px 16px;
}
.insight-card-title { font-size: 11px; font-weight: 800; color: var(--text-faint); text-transform: uppercase; letter-spacing: 0.05em; }
.insight-card-name { font-size: 16px; font-weight: 700; margin-top: 6px; overflow-wrap: anywhere; }
.insight-card-sub { font-size: 12.5px; color: var(--text-muted); margin-top: 3px; }
.insight-card-empty { color: var(--text-faint); font-size: 12.5px; margin-top: 6px; line-height: 1.5; }
.attention-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0; }
.attention-item {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  padding: 10px 0;
  border-bottom: 1px solid var(--border);
  font-size: 13px;
}
.attention-item:last-child { border-bottom: 0; }
.attention-item-name { font-weight: 600; overflow-wrap: anywhere; }
.attention-item-detail { color: var(--text-faint); font-size: 12px; white-space: nowrap; }

/* FASE 02G — "Onde estou perdendo" em R$: Investido/Comissão/Resultado
   compactos por item, substituindo o antigo detalhe único (ROI/cliques).
   Empilha nome + linha de estatísticas (em vez do baseline lado-a-lado de
   .attention-item) — .loss-item-stats quebra linha sozinha no mobile, sem
   virar tabela horizontal. */
.loss-item { flex-direction: column; align-items: stretch; justify-content: flex-start; gap: 8px; }
.loss-item-name { font-weight: 600; overflow-wrap: anywhere; }
.loss-item-stats { display: flex; flex-wrap: wrap; gap: 16px; }
.loss-stat { display: flex; flex-direction: column; gap: 2px; }
.loss-stat-label { font-size: 10.5px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; color: var(--text-faint); }
.loss-stat-value { font-size: 13px; font-weight: 700; font-variant-numeric: tabular-nums; }

.status-dot { display: inline-block; width: 8px; height: 8px; border-radius: 50%; margin-right: 7px; }
.status-dot-pending { background: var(--warning); }
.status-dot-completed { background: var(--success); }
.status-dot-cancelled { background: var(--danger); }
.status-dot-other { background: var(--neutral-dot); }

.unsupported-list { padding-left: 18px; color: var(--text-muted); font-size: 12.5px; }
.unsupported-list li { margin-bottom: 5px; }

.clickable-row { cursor: pointer; }
.clickable-row:hover { background: var(--accent-soft) !important; }
.not-attributable { color: var(--text-faint); font-style: italic; font-size: 12px; }

/* Fase 6.1 — nome do produto como identificação principal do pedido; o
   order_id técnico vira um detalhe secundário, discreto, abaixo do nome. */
.order-product { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
.order-product-name { font-weight: 600; color: var(--text); }
.order-product-extra { font-size: 11.5px; color: var(--text-muted); background: var(--surface-sunken); border-radius: 999px; padding: 1px 8px; white-space: nowrap; }
.order-id-secondary { margin-top: 2px; font-size: 11px; color: var(--text-faint); }
.order-id-secondary code { font-size: 11px; }

.pagination { display: flex; align-items: center; gap: 14px; margin-top: 14px; justify-content: flex-end; }
.pagination button {
  border: 1px solid var(--border-strong);
  background: var(--surface);
  border-radius: var(--radius-sm);
  padding: 6px 13px;
  cursor: pointer;
  font-weight: 600;
}
.pagination button:hover:not(:disabled) { border-color: var(--accent); color: var(--accent); }
.pagination button:disabled { opacity: 0.4; cursor: not-allowed; }
.pagination span { color: var(--text-muted); font-size: 12.5px; }

/* FRONTEND-CONSOLIDATION-01C — paginação client-side numerada
   (frontend/js/pagination.js), distinta de .pagination (Pedidos, server-
   side prev/next) para não arriscar regressão ali. Nunca mais de ~5
   páginas na prática (teto de 100 itens / pageSize mínimo de 20). */
.performance-pagination { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 12px; margin-top: 14px; }
.pagination-readout { color: var(--text-muted); font-size: 12.5px; }
.pagination-pages { display: flex; align-items: center; gap: 4px; }
.pagination-pages button {
  border: 1px solid var(--border-strong);
  background: var(--surface);
  border-radius: var(--radius-sm);
  min-width: 30px;
  padding: 5px 8px;
  cursor: pointer;
  font-weight: 600;
  font-size: 12.5px;
  color: var(--text-muted);
}
.pagination-pages button:hover:not(:disabled) { border-color: var(--accent); color: var(--accent); }
.pagination-pages button:disabled { opacity: 0.35; cursor: not-allowed; }
.pagination-pages button.active { background: var(--accent); border-color: var(--accent); color: #fff; }
.pagination-ellipsis { padding: 0 4px; color: var(--text-faint); font-size: 12.5px; }
.pagination-size { display: flex; align-items: center; gap: 6px; font-size: 12.5px; color: var(--text-muted); }
.pagination-size button {
  border: 1px solid var(--border-strong);
  background: var(--surface);
  border-radius: var(--radius-sm);
  padding: 4px 9px;
  cursor: pointer;
  font-weight: 600;
  font-size: 12px;
  color: var(--text-muted);
}
.pagination-size button.active { background: var(--accent); border-color: var(--accent); color: #fff; }

/* Nota "Top 100 do período" — quando o total real excede o teto retornado
   pelo endpoint (carta: "não afirmar que todos os produtos estão
   carregados se só vieram 100"). */
.truncation-note { color: var(--text-faint); font-size: 11.5px; margin-top: 8px; line-height: 1.5; }

.sortable-header { cursor: pointer; user-select: none; }
.sortable-header.active { color: var(--accent); }

/* ==========================================================================
   Drawer de detalhe do pedido
   ========================================================================== */

.drawer { position: fixed; inset: 0; z-index: 50; }
.drawer-backdrop { position: absolute; inset: 0; background: rgba(15, 18, 34, 0.45); }
.drawer-panel {
  position: absolute; top: 0; right: 0; bottom: 0;
  width: min(460px, 100%);
  background: var(--surface);
  box-shadow: -8px 0 24px rgba(15, 18, 34, 0.14);
  display: flex; flex-direction: column;
  overflow-y: auto;
}
.drawer-header { display: flex; justify-content: space-between; align-items: center; padding: 18px 22px; border-bottom: 1px solid var(--border); }
.drawer-header h2 { font-size: 15px; font-weight: 700; }
.drawer-header button { border: none; background: none; font-size: 17px; cursor: pointer; color: var(--text-muted); border-radius: var(--radius-sm); padding: 4px 8px; }
.drawer-header button:hover { background: var(--surface-sunken); color: var(--text); }
.drawer-body { padding: 18px 22px; }
.drawer-meta { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 6px 14px; margin-bottom: 18px; font-size: 13px; }
.drawer-meta dt { color: var(--text-muted); }
/* FRONTEND-IMPLEMENTATION-01.1 (bug real de QA) — sem min-width:0 +
   overflow-wrap, um valor real sem espaços (ex.: e-mail de conta Google
   longo) força a coluna 1fr a crescer além do container e estoura a
   largura da página inteira em telas estreitas — o texto auxiliar do
   painel (.panel-note), mais abaixo no mesmo .panel, aparecia cortado na
   lateral como sintoma colateral desse overflow, não de um problema no
   próprio parágrafo. */
.drawer-meta dd { font-weight: 600; min-width: 0; overflow-wrap: break-word; }

/* ==========================================================================
   Responsivo — sidebar vira barra horizontal, sem alterar nenhum
   comportamento (mesmo DOM, mesmos links, mesmo onclick de logout).
   ========================================================================== */

/* ==========================================================================
   SUBID-02 — abas "Geral" / "Por Sub ID" dentro de Análise de vendas.
   Reaproveita a mesma linguagem visual de .filter-presets (pílulas),
   distinta por escopo (troca de visão, não filtro de período).
   ========================================================================== */

.view-tabs { display: flex; gap: 6px; margin-bottom: 16px; }
.view-tabs button {
  border: 1px solid var(--border);
  background: var(--surface);
  border-radius: 999px;
  padding: 7px 16px;
  cursor: pointer;
  color: var(--text-muted);
  font-weight: 600;
  transition: background-color 0.12s ease, color 0.12s ease, border-color 0.12s ease;
}
.view-tabs button:hover { border-color: var(--border-strong); color: var(--text); }
.view-tabs button.active { background: var(--accent); border-color: var(--accent); color: #fff; }

.coverage-banner { padding: 10px 16px; border-radius: var(--radius); margin-bottom: 16px; font-size: 12.5px; line-height: 1.5; }
.coverage-complete { background: var(--surface-sunken); color: var(--text-muted); }
.coverage-partial { background: var(--warning-bg); color: var(--warning); }
.coverage-none { background: var(--surface); border: 1px dashed var(--border-strong); color: var(--text-muted); }

.subid-attribution-note, .channel-attribution-note { color: var(--text-muted); font-size: 13px; margin-bottom: 16px; line-height: 1.5; }
.subid-attribution-note details { margin-top: 4px; }
.subid-attribution-note summary { cursor: pointer; color: var(--accent); font-weight: 600; }
.subid-attribution-note summary:hover { text-decoration: underline; }
.subid-attribution-note .subid-tooltip-body { margin-top: 6px; color: var(--text-faint); }

@media (max-width: 860px) {
  /* FRONTEND-FOUNDATION-SHELL-01 — o shell mobile (grid, sidebar/drawer,
     topbar, sidebar-account) usado a virar HORIZONTAL (UX-01B/PRODUCT-UX-02)
     foi substituído pelo padrão hambúrguer + drawer + avatar (direção
     V1.1), definido logo acima, mais perto do resto do CSS do shell. Este
     bloco mantém as regras de mobile que são conteúdo de página (abaixo),
     que continuam exatamente como estavam — nenhuma delas foi tocada. */

  .drawer-panel { width: 100%; }
  .panel-row { grid-template-columns: minmax(0, 1fr); }
  .status-body { flex-direction: column; align-items: flex-start; }
  .filter-compare { margin-left: 0; }
  /* UX-01B hotfix — .filter-custom não quebrava linha: 2 inputs de data +
     2 labels + botão em uma única linha flex ultrapassavam a viewport
     mesmo com .filter-bar já quebrando seus próprios itens. */
  .filter-custom { flex-wrap: wrap; }
  .kpi-grid-secondary { grid-template-columns: 1fr 1fr; }
  .kpi-grid-secondary .kpi-card:last-child { grid-column: 1 / -1; }
  .kpi-card-hero .kpi-value { font-size: 28px; }

  /* PRODUCT-UX-02, seção 7 — descoberta horizontal no mobile: o afiliado
     não deve precisar "adivinhar" que a tabela continua para a direita
     (achado real do beta, incidente citado na carta). Técnica CSS pura
     (sem JS, sem seta, sem banner): dois gradientes "presos" ao conteúdo
     (background-attachment: local) cobrem a borda enquanto há mais para
     rolar e desaparecem quando o scroll chega ao fim; dois gradientes fixos
     por cima dão a sombra visível. Aplica-se só onde a tabela já rola
     (overflow-x:auto abaixo, inalterado). */
  .table-scroll {
    background-image:
      linear-gradient(to right, var(--surface) 30%, rgba(255, 255, 255, 0)),
      linear-gradient(to right, rgba(255, 255, 255, 0), var(--surface) 70%),
      linear-gradient(to right, rgba(15, 18, 34, 0.10), rgba(15, 18, 34, 0)),
      linear-gradient(to left, rgba(15, 18, 34, 0.10), rgba(15, 18, 34, 0));
    background-position: left, right, left, right;
    background-repeat: no-repeat;
    background-color: var(--surface);
    background-size: 24px 100%, 24px 100%, 10px 100%, 10px 100%;
    background-attachment: local, local, scroll, scroll;
  }
  .explorer-toolbar { align-items: stretch; flex-direction: column; }
  .explorer-sort { justify-content: space-between; }
  .performance-summary { grid-template-columns: 1fr; }
  .performance-list-item { grid-template-columns: 36px minmax(150px, 1fr) minmax(140px, 0.6fr) auto; }
  .performance-supporting { grid-column: 2 / -1; }
  .comparison-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }

  /* PRODUCT-FRONTEND-META-01 — diagrama de atribuição empilha em coluna
     única abaixo de 860px; a ponte "Sub ID" vira um separador horizontal
     entre as duas colunas em vez de uma coluna central. */
  .attribution-diagram { grid-template-columns: 1fr; justify-items: center; text-align: center; }
  .attribution-bridge { flex-direction: row; width: 100%; max-width: 220px; }
  .attribution-bridge-line { min-width: 0; }
  .attribution-methods { grid-template-columns: 1fr; }

  /* CONSOLIDATION-01B — abaixo de 860px, "Campanha" + "Vínculos" sticky
     (410px) já ocupariam quase toda a largura útil sem sobrar espaço para
     rolar até o resto da tabela. A ação de vincular continua visível sem
     rolagem (são as 2 primeiras colunas por padrão); só a fixação some. */
  .linking-table th:nth-child(1), .linking-table td:nth-child(1),
  .linking-table th:nth-child(2), .linking-table td:nth-child(2) {
    position: static; box-shadow: none; min-width: 160px; max-width: none;
  }
  .linking-summary-panel { flex-direction: column; align-items: stretch; }
  .linking-summary-panel .integration-row-action { width: 100%; text-align: center; }
}

@media (max-width: 640px) {
  /* FRONTEND-FOUNDATION-SHELL-01 — as 3 regras que existiam aqui para
     .app-sidebar/.sidebar-logo-wrap/.sidebar-logo pertenciam ao padrão
     antigo de sidebar-virada-barra-horizontal (sticky, logo encolhida para
     o favicon); não fazem sentido para o drawer off-canvas (que já cobre
     toda largura/altura necessárias). Removidas. .app-topbar/.logout-button
     abaixo continuam — são ajuste de toque/espaçamento do header da
     página, não do shell em si. */
  .app-topbar { padding: 12px 16px 10px; gap: 6px; }
  .app-topbar-title .subtitle { max-width: 30rem; }
  .logout-button { min-height: 40px; }

  /* PRAZELI-DESIGN-01 — freshness is account-wide, not period-dependent
     (see loadFreshness()/loadAll() in app.js/performance.js), so it never
     needed to wait behind the period filter bar in the first place. main#app
     becomes a column flex container here only so #freshness-indicator can
     move to the very top via `order` — every other child keeps its existing
     relative order (unset order defaults to 0, preserving current DOM
     sequence), so no filter, state banner, or content section is hidden,
     collapsed, or reachable any differently than before; only freshness's
     position changes. Its own -10px top margin (base rule) assumed it
     always sat directly under .period-readout; now that it leads the page,
     that negative margin is reset to a small positive one instead. */
  main#app { display: flex; flex-direction: column; }
  #freshness-indicator { order: -1; margin: 0 0 12px; }

  .filter-bar { align-items: stretch; padding: 13px; gap: 10px; margin-bottom: 8px; }
  .period-readout { margin: 8px 2px 14px; }
  .filter-label { width: 100%; }
  .filter-presets { flex-wrap: nowrap; overflow-x: auto; padding-bottom: 3px; scroll-snap-type: x proximity; }
  .filter-presets button { min-height: 40px; white-space: nowrap; scroll-snap-align: start; }
  .filter-custom { display: grid; grid-template-columns: auto minmax(0, 1fr); width: 100%; gap: 8px; }
  .filter-custom input { width: 100%; min-height: 40px; }
  .filter-custom button { grid-column: 1 / -1; min-height: 42px; }
  .filter-status { justify-content: space-between; width: 100%; }
  .filter-status select { min-height: 42px; max-width: 62%; }
  .filter-compare { min-height: 40px; }
  .kpi-grid-secondary { grid-template-columns: 1fr; }
  .kpi-grid-secondary .kpi-card:last-child { grid-column: auto; }
  .panel { padding: 16px; }
  .panel-chart-main { padding: 18px 16px 16px; }
  .panel-header { align-items: flex-start; flex-direction: column; }
  .chart-metric-tabs { max-width: 100%; overflow-x: auto; }
  .view-tabs { max-width: 100%; overflow-x: auto; padding-bottom: 3px; }
  .view-tabs button { min-height: 42px; white-space: nowrap; }
  .pagination { justify-content: space-between; gap: 8px; }
  .pagination button { min-height: 42px; }
  .state-error:not([hidden]) { align-items: flex-start; flex-direction: column; }
  .state-error button { min-height: 40px; }
  .explorer-toolbar .view-tabs { display: grid; grid-template-columns: repeat(3, 1fr); width: 100%; }
  .explorer-toolbar .view-tabs button { min-width: 0; padding-inline: 8px; }
  .explorer-sort { align-items: stretch; flex-direction: column; gap: 5px; }
  .explorer-sort select { width: 100%; }
  .performance-summary { gap: 16px; padding: 18px 16px; }
  .performance-summary-heading h2 { font-size: 20px; }
  .performance-decision-grid { grid-template-columns: 1fr; }
  .performance-decision-card { padding: 13px 14px; }
  .performance-highlights-list { grid-template-columns: 1fr; }
  .performance-highlight-card { border-right: 0; }
  .performance-highlight-content { min-height: 0; padding: 15px 16px; }
  .performance-ranking-header { align-items: flex-start; padding: 16px; }
  .performance-list-item { grid-template-columns: 28px minmax(0, 1fr); gap: 10px; padding: 15px 16px; }
  .performance-primary-value { grid-column: 2; align-items: flex-start; text-align: left; }
  .performance-supporting { grid-column: 2; text-align: left; }
  .comparison-panel { padding: 13px 14px; }
  .comparison-grid { grid-template-columns: 1fr; }
  .performance-supporting div { text-align: left; }
  .performance-detail-button { grid-column: 2; justify-self: start; }

  /* PRODUCT-FRONTEND-META-01 */
  .meta-empty-state { margin: 20px auto; padding: 28px 20px; }
  .meta-preview-grid { grid-template-columns: 1fr 1fr; }
  .integration-row { flex-direction: column; align-items: stretch; text-align: center; }
  .integration-row-main { align-items: center; }
  .integration-row-action { text-align: center; }

  /* FRONTEND-CONSOLIDATION-01C — carta "PERFORMANCE MOBILE": nunca uma
     tabela horizontal gigante no celular. Cada <tr> vira um cartão
     compacto (CSS puro, mesmo DOM/mesma renderização de desktop — sem
     segunda fonte de verdade); cada <td> exige um atributo data-label no
     JS para o rótulo aparecer via ::before. A 1ª coluna (nome do
     registro) não leva rótulo, funciona como título do cartão. */
  .record-list-mobile.table-scroll { overflow-x: visible; }
  /* A tabela some do algoritmo de layout de tabela (senão o <table> calcula
     largura de coluna a partir do conteúdo, ignorando os <tr> virarem
     grid) — sem isso o min-width:max-content de .table-scroll .data-table
     ainda força a tabela a ficar larguíssima mesmo com as linhas em grid. */
  .record-list-mobile .data-table { display: block; min-width: 0; width: 100%; }
  .record-list-mobile thead { display: none; }
  .record-list-mobile tbody { display: flex; flex-direction: column; gap: 10px; }
  .record-list-mobile tr {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 8px 14px;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 12px 14px;
  }
  .record-list-mobile td { display: block; padding: 0; border-bottom: 0; }
  .record-list-mobile td:first-child { grid-column: 1 / -1; font-weight: 700; font-size: 14px; overflow-wrap: anywhere; white-space: normal; max-width: none; }
  .record-list-mobile td.num { text-align: left; }
  .record-list-mobile td[data-label]::before {
    content: attr(data-label);
    display: block;
    color: var(--text-faint);
    font-size: 10.5px;
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    margin-bottom: 2px;
  }
  .performance-pagination { justify-content: center; }
}

/* Respeita a preferência do sistema — nenhuma transição/animação desta
   carta (hover de card, troca de tab/métrica) reforça mudança de estado
   quando o usuário pediu para reduzir movimento (carta, seção 14). */
@media (prefers-reduced-motion: reduce) {
  * { transition-duration: 0.001ms !important; animation-duration: 0.001ms !important; }
}

/* ==========================================================================
   IMPLEMENTATION-02-OVERVIEW-V1.1 — Visão Geral V1.1.
   Tudo abaixo é escopado a body.page-overview (só existe em index.html):
   .filter-presets/.filter-bar/.kpi-grid-secondary são compartilhados com
   Performance/Mídia Paga/etc. e não podem mudar de aparência lá. Classes
   inteiramente novas (.kpi-card-featured, .kpi-row-compact, .insights-
   columns, .detail-links) não precisam do escopo por não existirem em
   nenhuma outra página, mas ficam aqui juntas por organização.
   ========================================================================== */

.page-overview .period-controls { display: flex; align-items: flex-start; flex-wrap: wrap; gap: 8px; flex: 1; min-width: 0; }

/* Ativo em bronze com sublinhado discreto — nunca o bloco laranja sólido
   (carta: "sem grande botão preenchido"). Sobrescreve só dentro da Visão
   Geral; Performance/Mídia Paga continuam com o preset ativo em --accent. */
.page-overview .filter-presets button.active {
  background: var(--brand-bronze-soft);
  border-color: transparent;
  border-bottom: 2px solid var(--brand-bronze);
  color: var(--brand-bronze);
  font-weight: 700;
}

.page-overview .filter-more { position: relative; }
.filter-more-toggle {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  border: 1px solid var(--border);
  background: var(--surface-sunken);
  border-radius: 999px;
  padding: 6px 13px;
  cursor: pointer;
  color: var(--text);
  font-weight: 500;
}
.filter-more-toggle:hover { border-color: var(--border-strong); }
.filter-more-toggle.active {
  background: var(--brand-bronze-soft);
  border-color: transparent;
  border-bottom: 2px solid var(--brand-bronze);
  color: var(--brand-bronze);
  font-weight: 700;
}
.filter-more-caret { font-size: 10px; }
.filter-more-popover {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  z-index: 20;
  min-width: 320px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-md);
  padding: 14px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.filter-more-popover[hidden] { display: none; }
.filter-more-presets button.active {
  background: var(--brand-bronze-soft);
  border-color: transparent;
  border-bottom: 2px solid var(--brand-bronze);
  color: var(--brand-bronze);
  font-weight: 700;
}

/* Resultado após mídia — único card com destaque (carta: "leve sombra;
   detalhe bronze; valor com maior presença"). Classe própria, não reaproveita
   .kpi-card-hero (que outras páginas usam com --brand/laranja). */
.kpi-card-featured {
  position: relative;
  border-left: 3px solid var(--brand-bronze);
  padding-left: calc(18px - 2px);
  box-shadow: var(--shadow-md);
}
.kpi-card-featured .kpi-value { font-size: 28px; }

/* Linha secundária compacta (ROAS/Pedidos atribuídos/CPA) — separadores,
   não 3 cartões com borda/sombra própria (carta: "não usar três novos
   cards"). */
.kpi-row-compact {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 20px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 12px 18px;
  margin-bottom: var(--space-3);
}
.kpi-row-item { display: flex; align-items: baseline; gap: 8px; padding-right: 20px; border-right: 1px solid var(--border); }
.kpi-row-item:last-child { border-right: none; padding-right: 0; }
.kpi-row-label { color: var(--text-muted); font-size: 11.5px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.03em; white-space: nowrap; }
.kpi-row-value { font-size: 15px; font-weight: 700; font-variant-numeric: tabular-nums; white-space: nowrap; }

/* Gráfico "Evolução no período" — linha navy/neutra em vez de laranja
   (carta: "sem bronze como linha principal" — navy é a escolha neutra que
   sobra; laranja continua em uso normal no resto do produto, escopado
   só a este gráfico via #daily-chart). */
#daily-chart .chart-area { fill: var(--brand-navy); fill-opacity: 0.08; }
#daily-chart .chart-line { stroke: var(--brand-navy); }
#daily-chart .chart-dot { fill: var(--brand-navy); }
#daily-chart .chart-guide { stroke: var(--border-strong); }

/* Onde estou ganhando | Onde estou perdendo lado a lado no desktop. */
.insights-columns { display: grid; grid-template-columns: 1fr; gap: var(--space-3); }

.detail-links { display: flex; flex-wrap: wrap; gap: 20px; margin: -6px 0 var(--space-3); }
.detail-link { font-size: 12.5px; font-weight: 600; color: var(--accent); text-decoration: none; }
.detail-link:hover { text-decoration: underline; }

@media (min-width: 861px) {
  .insights-columns { grid-template-columns: 1fr 1fr; }
  .insights-columns .panel { margin-bottom: 0; }
}

@media (max-width: 860px) {
  .page-overview .period-controls { width: 100%; }
  .filter-more-popover { left: 0; right: 0; min-width: 0; }
  .filter-more-toggle { min-height: 40px; }
  .kpi-row-compact { gap: 14px; padding: 12px 14px; }
  .kpi-row-item { padding-right: 14px; }
}

@media (max-width: 640px) {
  .kpi-row-compact { flex-direction: column; align-items: stretch; gap: 10px; }
  .kpi-row-item { border-right: none; border-bottom: 1px solid var(--border); padding: 0 0 10px; justify-content: space-between; }
  .kpi-row-item:last-child { border-bottom: none; padding-bottom: 0; }
  /* Dentro do popover "Mais" (poucos itens, largura já limitada ao próprio
     popover), quebra de linha lê melhor que o scroll horizontal que
     .filter-presets usa nas páginas com filtros extensos. */
  .filter-more-presets { flex-wrap: wrap; overflow-x: visible; }
  .filter-more-presets button { min-height: 40px; }
  /* BUG REAL (QA) — .period-controls (flex:1, encolhe livremente porque
     .filter-presets tem overflow-x:auto) disputava a mesma linha com
     .filter-compare, comprimindo os presets e cortando "Ontem" visualmente.
     Cada um ganha a própria linha cheia. */
  .page-overview .filter-bar { flex-direction: column; align-items: stretch; }
  .page-overview .period-controls { width: 100%; }
}

/* ==========================================================================
   IMPLEMENTATION-02.1-OVERVIEW-V1.1 — 4 ajustes visuais pontuais sobre a
   V1.1 já implementada (nenhuma lógica/HTML tocado, só apresentação).
   Tudo escopado a body.page-overview, #apply-custom ou #primary-kpi-section
   (todos exclusivos de index.html) — .filter-custom button,
   .chart-metric-tabs, .freshness-indicator e .coverage-compact-panel são
   compartilhados com Performance/Mídia Paga/Operação e continuam com a
   aparência antiga lá.
   ========================================================================== */

/* BLOCKER A — Aplicar (personalizado) e seletor do gráfico usavam
   --accent/laranja (resquício da apresentação antiga). Bronze com estados
   de hover/focus/disabled — nunca danger/success/warning: Aplicar não é
   ação destrutiva nem semântica. Mesmo contraste já validado na Foundation
   (bronze ⇄ branco = 5.52:1, simétrico para texto-sobre-fundo ou o
   inverso — ambos acima de AA 4.5:1). */
body.page-overview #apply-custom {
  border: 1px solid var(--brand-bronze);
  background: var(--brand-bronze-soft);
  color: var(--brand-bronze);
}
body.page-overview #apply-custom:hover { background: var(--brand-bronze); color: #fff; }
body.page-overview #apply-custom:focus-visible { outline: 2px solid var(--brand-bronze); outline-offset: 2px; }
body.page-overview #apply-custom:disabled { opacity: 0.55; cursor: not-allowed; }

/* Seletor do gráfico: mesmo padrão bronze discreto já usado pelos presets
   de período desta página (consistência interna) — fundo sutil + linha
   inferior, não um preenchimento pesado (carta: "não transformar em CTA
   primário"). */
body.page-overview .chart-metric-tabs button.active {
  background: var(--brand-bronze-soft);
  border-color: transparent;
  border-bottom: 2px solid var(--brand-bronze);
  color: var(--brand-bronze);
  font-weight: 700;
}

/* BLOCKER B — freshness deixa de ser um card/banner de largura total e
   vira uma linha compacta de metainformação (mesmo texto/lógica/estados —
   só a apresentação). O indicador colorido (dot) continua semântico por
   tom; o card grande é que some. */
body.page-overview .freshness-indicator {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  max-width: none;
  margin: 2px 0 16px;
  padding: 0;
  border: none;
  border-radius: 0;
  background: none;
  box-shadow: none;
  color: var(--text-muted);
}
body.page-overview .freshness-dot { margin-top: 0; }
body.page-overview .freshness-copy { flex-direction: row; gap: 5px; align-items: baseline; font-size: 12.5px; }
body.page-overview .freshness-copy strong { font-size: 12.5px; font-weight: 650; }
body.page-overview .freshness-copy span::before { content: '· '; }

/* BLOCKER C — cobertura de atribuição é metadata dos KPIs secundários, não
   um painel próprio (compartilha classe com Mídia Paga/Operação, que
   continuam com o card). Mesmo texto/valor/cálculo, só deixa de ter
   card/borda/sombra. */
body.page-overview .coverage-compact-panel {
  background: none;
  border: none;
  border-radius: 0;
  box-shadow: none;
  padding: 0;
  margin: -6px 0 var(--space-3);
  color: var(--text-muted);
  font-size: 12.5px;
}

/* BLOCKER D — .kpi-grid (compartilhado) usa auto-fit, que em larguras
   intermediárias (~1024–1200px de viewport) encaixa 3 dos 4 cards numa
   linha e deixa o 4º sozinho — quebra visual, não intencional. Breakpoints
   explícitos só para #primary-kpi-section (exclusivo da Visão Geral):
   4 colunas quando a área de conteúdo cabe confortavelmente os 4 cards,
   2×2 na faixa intermediária, 1 coluna no mobile (comportamento padrão do
   auto-fit da base, já correto, não precisa de regra própria). */
@media (min-width: 861px) and (max-width: 1239px) {
  #primary-kpi-section { grid-template-columns: repeat(2, 1fr); }
}
@media (min-width: 1240px) {
  #primary-kpi-section { grid-template-columns: repeat(4, 1fr); }
}

.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* ==========================================================================
   IMPLEMENTATION-03-PAID-MEDIA-V1.1 — Mídia Paga V1.1.
   Escopado a body.page-paid-media (só existe em paid-media.html):
   .filter-presets/.filter-bar/#apply-custom/.coverage-compact-panel/
   .table-action-chip/.pagination-pages/.pagination-size são compartilhados
   com Visão Geral/Performance/Operação e não podem mudar de aparência lá.
   Classes inteiramente novas (.table-toolbar, .campaign-expand-*,
   .row-expand-*, .table-action-chip-warning, .linking-summary-panel-pending)
   não precisam do escopo por não existirem em nenhuma outra página, mas
   ficam aqui juntas por organização. Nenhum HTML/JS de outra página, nenhum
   cálculo, nenhuma fórmula muda nesta seção.
   ========================================================================== */

.page-paid-media .period-controls { display: flex; align-items: flex-start; flex-wrap: wrap; gap: 8px; flex: 1; min-width: 0; }

.page-paid-media .filter-presets button.active {
  background: var(--brand-bronze-soft);
  border-color: transparent;
  border-bottom: 2px solid var(--brand-bronze);
  color: var(--brand-bronze);
  font-weight: 700;
}
.page-paid-media .filter-more { position: relative; }
.page-paid-media .filter-more-toggle.active,
.page-paid-media .filter-more-presets button.active {
  background: var(--brand-bronze-soft);
  border-color: transparent;
  border-bottom: 2px solid var(--brand-bronze);
  color: var(--brand-bronze);
  font-weight: 700;
}
body.page-paid-media #apply-custom {
  border: 1px solid var(--brand-bronze);
  background: var(--brand-bronze-soft);
  color: var(--brand-bronze);
}
body.page-paid-media #apply-custom:hover { background: var(--brand-bronze); color: #fff; }
body.page-paid-media #apply-custom:focus-visible { outline: 2px solid var(--brand-bronze); outline-offset: 2px; }
body.page-paid-media #apply-custom:disabled { opacity: 0.55; cursor: not-allowed; }

/* Cobertura de atribuição como metadata dos KPIs secundários, não um painel
   próprio (mesmo texto/cálculo de sempre — carta "SECUNDÁRIOS": "coverage
   não possui card/container próprio"). */
body.page-paid-media .coverage-compact-panel {
  background: none;
  border: none;
  border-radius: 0;
  box-shadow: none;
  padding: 0;
  margin: -6px 0 var(--space-3);
  color: var(--text-muted);
  font-size: 12.5px;
}

/* Faixa "Vínculos de atribuição" — ATENÇÃO/âmbar, nunca danger/bronze/card
   pesado (carta "SEMÂNTICA DA FAIXA"). Sem pendência (0 sem vínculo) o
   painel permanece neutro — o âmbar é só para quando existe algo a revisar. */
body.page-paid-media .linking-summary-panel { box-shadow: none; }
body.page-paid-media .linking-summary-panel.linking-summary-panel-pending {
  border-color: transparent;
  border-left: 3px solid var(--warning);
  background: var(--warning-soft);
}

/* Ação de vínculo dentro da tabela: neutra por padrão; só ganha o tom de
   atenção quando a campanha não tem NENHUM Sub ID (carta: "cor warning/
   atenção; não brand bronze — não fazer parecer CTA principal"). */
body.page-paid-media .table-action-chip:hover { border-color: var(--brand-bronze); color: var(--brand-bronze); }
body.page-paid-media .table-action-chip-warning { border-color: var(--warning); color: var(--warning); }
body.page-paid-media .table-action-chip-warning:hover { background: var(--warning-soft); border-color: var(--warning); color: var(--warning); }

body.page-paid-media .pagination-pages button.active,
body.page-paid-media .pagination-size button.active {
  background: var(--brand-bronze); border-color: var(--brand-bronze);
}
body.page-paid-media .pagination-pages button:hover:not(:disabled),
body.page-paid-media .pagination-size button:hover:not(:disabled) { border-color: var(--brand-bronze); color: var(--brand-bronze); }

/* Toolbar da tabela (busca + selects) — visualmente parte do painel da
   tabela, não um segundo header de página (carta "TABLE TOOLBAR"). */
.table-toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
  margin-bottom: 14px;
  padding-bottom: 14px;
  border-bottom: 1px solid var(--border);
}
.table-toolbar .filter-search { flex: 1; min-width: 200px; }
.table-toolbar .filter-search input { width: 100%; }

/* Coluna de expandir — largura mínima, alinhada à direita, chevron gira
   quando a linha está aberta (mesmo ▾ já usado por "Mais"). */
.campaign-expand-col { width: 36px; text-align: center; }
.row-expand-toggle {
  border: none;
  background: none;
  cursor: pointer;
  color: var(--text-muted);
  padding: 6px;
  border-radius: var(--radius-sm);
  line-height: 1;
}
.row-expand-toggle:hover { background: var(--surface-sunken); color: var(--text); }
.row-expand-caret { display: inline-block; font-size: 11px; transition: transform 0.15s ease; }
.campaign-row.is-expanded .row-expand-caret { transform: rotate(-180deg); }

/* Linha expandida — surface sutil, nunca card/sombra/segunda tabela dentro
   da tabela (carta "EXPANDED ROW — DESKTOP"). Continua claramente presa à
   linha da campanha acima (sem borda superior própria). */
.campaign-expanded-row td { background: var(--surface-sunken); padding: 16px 18px; border-bottom: 1px solid var(--border); }
.campaign-expand-grid { display: grid; grid-template-columns: 1.3fr 1.3fr 1fr; gap: 20px; }
.campaign-expand-title { font-size: 11px; font-weight: 800; text-transform: uppercase; letter-spacing: 0.06em; color: var(--text-faint); margin-bottom: 8px; }
.campaign-expand-stats { display: grid; grid-template-columns: repeat(2, 1fr); gap: 8px 16px; }
.campaign-expand-stats > div { display: flex; flex-direction: column; gap: 2px; }
.campaign-expand-stats dt { font-size: 11px; color: var(--text-faint); }
.campaign-expand-stats dd { font-size: 13.5px; font-weight: 650; font-variant-numeric: tabular-nums; }
.campaign-expand-subids { display: flex; flex-wrap: wrap; gap: 5px; }
/* IMPLEMENTATION-03.1-FIX — carta "PASSO 5": .subid-chip (reaproveitado da
   prévia truncada da célula "Sub IDs" da tabela) trunca com ellipsis a
   150px — correto na prévia compacta, mas errado aqui: a lista expandida
   existe justamente para mostrar o Sub ID completo. Escopado só a este
   container (a prévia truncada em .linking-cell-chips continua igual). */
.campaign-expand-subids .subid-chip {
  max-width: none;
  overflow: visible;
  text-overflow: clip;
  white-space: normal;
  overflow-wrap: anywhere;
}
.campaign-expand-action { display: flex; flex-direction: column; align-items: flex-start; }
.campaign-expand-action .integration-row-action { margin-top: 2px; }

@media (max-width: 860px) {
  .page-paid-media .period-controls { width: 100%; }
  .table-toolbar { flex-direction: column; align-items: stretch; }
  .table-toolbar .filter-search { min-width: 0; }
  .campaign-expand-grid { grid-template-columns: 1fr; gap: 16px; }
}

@media (max-width: 640px) {
  .page-paid-media .filter-bar { flex-direction: column; align-items: stretch; }
  .page-paid-media .period-controls { width: 100%; }
  .filter-more-presets { flex-wrap: wrap; overflow-x: visible; }
  .filter-more-presets button { min-height: 40px; }

  /* MOBILE — ESTRUTURA DA LISTAGEM (carta): sem scroll horizontal como
     experiência primária. Cada campanha vira um cartão empilhado; a linha
     expandida some do fluxo em tabela e reaparece como bloco dentro do
     próprio cartão. */
  .meta-table-panel .table-scroll { overflow-x: visible; border: none; }
  .linking-table thead { display: none; }
  .linking-table, .linking-table tbody, .linking-table tr, .linking-table td { display: block; width: 100%; }
  /* IMPLEMENTATION-03.1-FIX — causa raiz medida do blocker mobile: .table-scroll
     .data-table (regra compartilhada, base.css, especificidade 0,2,0) força
     min-width:max-content para permitir scroll horizontal no desktop.
     width:100% sozinho NUNCA vence min-width (min-width é um piso), e um
     seletor de especificidade 0,1,0 (".linking-table" sozinho) também não
     vence 0,2,0 — a ordem da media query não pesa nisso, só especificidade
     (medido: min-width computado continuava "max-content" mesmo dentro
     deste bloco até este seletor ganhar a mesma especificidade do original).
     Sem isso, a tabela mantém sua largura intrínseca (~1050px+ quando uma
     campanha com muitos Sub IDs está expandida, porque max-content soma
     TODO o conteúdo, inclusive linhas não expandidas) e, com
     overflow-x:visible logo acima, esse excesso simplesmente sangra para
     fora da viewport em vez de rolar OU encolher — os valores "somem"
     porque justify-content:space-between os empurra para a ponta direita
     de uma linha ~1050px de largura, muito além dos 390px visíveis (mesmo
     padrão já resolvido em .record-list-mobile .data-table, ver comentário
     FRONTEND-CONSOLIDATION-01C acima). Medido via getBoundingClientRect/
     scrollWidth antes e depois; nenhuma suposição. */
  .table-scroll .linking-table { min-width: 0; }
  .linking-table th:nth-child(1), .linking-table td:nth-child(1),
  .linking-table th:nth-child(2), .linking-table td:nth-child(2) {
    position: static; min-width: 0; max-width: none; box-shadow: none;
  }
  .campaign-row {
    border: 1px solid var(--border);
    border-radius: var(--radius);
    margin-bottom: 10px;
    background: var(--surface);
    overflow: hidden;
  }
  .campaign-row td { border-bottom: none; padding: 8px 14px; }
  .campaign-row td[data-label] { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; }
  .campaign-row td[data-label]::before { content: attr(data-label); font-size: 11px; font-weight: 700; color: var(--text-faint); text-transform: uppercase; letter-spacing: 0.03em; flex: none; }
  .campaign-row td[data-label="Campanha"] { padding-top: 12px; }
  .campaign-row td[data-label="Campanha"]::before { display: none; }
  .campaign-row td[data-label="Campanha"] .entity-cell { width: 100%; }
  .campaign-row td.num { font-variant-numeric: tabular-nums; }
  .campaign-expand-col { width: auto; padding: 4px 6px 10px; text-align: center; }
  .row-expand-toggle { width: 100%; display: flex; align-items: center; justify-content: center; border-top: 1px solid var(--border); border-radius: 0; padding: 8px; }
  .campaign-expanded-row td { border-bottom: none; padding: 14px; }
}

/* NOMES LONGOS (carta): truncamento com ellipsis + conteúdo completo
   acessível via title (tooltip nativo) — leitores de tela continuam lendo o
   nome inteiro normalmente (a truncagem é só visual, o texto não sai do
   DOM). Exclusivo de .entity-cell-name em Mídia Paga (não usado em nenhuma
   outra página). */
body.page-paid-media .entity-cell-name {
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 100%;
}
@media (max-width: 640px) {
  body.page-paid-media .entity-cell-name { white-space: normal; overflow: visible; text-overflow: clip; }
}

/* ==========================================================================
   IMPLEMENTATION-04-PERFORMANCE-V1.1 — Performance V1.1.
   Escopado a body.page-performance (só existe em performance.html):
   .filter-presets/.view-tabs/.filter-custom button/.pagination-*/.link-button/
   .state-connect/.truncate-cell são compartilhados com outras páginas e não
   podem mudar de aparência lá. --accent (laranja legado) NÃO é alterado
   globalmente; aqui só deixa de aparecer nos controles desta página.
   Nenhum cálculo, endpoint ou regra de dados muda nesta seção.
   ========================================================================== */

body.page-performance .period-controls { display: flex; align-items: flex-start; flex-wrap: wrap; gap: 8px; flex: 1; min-width: 0; }
body.page-performance .filter-more { position: relative; }
body.page-performance .filter-presets button.active,
body.page-performance .filter-more-toggle.active,
body.page-performance .filter-more-presets button.active {
  background: var(--brand-bronze-soft);
  border-color: transparent;
  border-bottom: 2px solid var(--brand-bronze);
  color: var(--brand-bronze);
  font-weight: 700;
}
body.page-performance #apply-custom {
  border: 1px solid var(--brand-bronze);
  background: var(--brand-bronze-soft);
  color: var(--brand-bronze);
}
body.page-performance #apply-custom:hover { background: var(--brand-bronze); color: #fff; }
body.page-performance #apply-custom:focus-visible,
body.page-performance .filter-presets button:focus-visible,
body.page-performance .filter-more-toggle:focus-visible { outline: 2px solid var(--brand-bronze); outline-offset: 2px; }

/* Tabs = navegação principal da página: linha horizontal com sublinhado
   bronze no ativo, nunca 3 botões sólidos/cards. */
body.page-performance .view-tabs {
  gap: 2px;
  margin: 0 0 var(--space-4);
  border-bottom: 1px solid var(--border);
}
body.page-performance .view-tabs button {
  border: none;
  border-bottom: 2px solid transparent;
  border-radius: 0;
  background: none;
  margin-bottom: -1px;
  padding: 10px 16px;
  min-height: 44px;
  color: var(--text-muted);
  font-weight: 600;
}
body.page-performance .view-tabs button:hover { color: var(--text); border-color: transparent; border-bottom-color: var(--border-strong); }
body.page-performance .view-tabs button.active {
  background: none;
  border-bottom-color: var(--brand-bronze);
  color: var(--brand-bronze);
  font-weight: 700;
}
body.page-performance .view-tabs button:focus-visible { outline: 2px solid var(--brand-bronze); outline-offset: -2px; border-radius: var(--radius-sm); }

/* KPIs: até 2 cards principais + linha compacta (ver renderKpiGroups). */
body.page-performance #kpi-section { grid-template-columns: repeat(2, minmax(0, 1fr)); }
body.page-performance #kpi-secondary-section[hidden] { display: none; }
body.page-performance .kpi-group .kpi-grid { margin-bottom: var(--space-3); }

/* Estado "conecte a Shopee" — informativo, não erro; bronze em vez do
   laranja legado. */
body.page-performance .state-connect { background: var(--brand-bronze-soft); border-color: transparent; border-left: 3px solid var(--brand-bronze); }
body.page-performance .state-connect-cta { background: var(--brand-bronze); }
body.page-performance .state-connect-cta:hover { background: var(--brand-bronze); filter: brightness(0.92); }

body.page-performance .pagination-pages button.active,
body.page-performance .pagination-size button.active { background: var(--brand-bronze); border-color: var(--brand-bronze); }
body.page-performance .pagination-pages button:hover:not(:disabled),
body.page-performance .pagination-size button:hover:not(:disabled) { border-color: var(--brand-bronze); color: var(--brand-bronze); }

body.page-performance .link-button { color: var(--brand-bronze); font-weight: 600; }
body.page-performance .link-button:hover { color: var(--brand-bronze); filter: brightness(0.85); }
body.page-performance .link-button:focus-visible { outline: 2px solid var(--brand-bronze); outline-offset: 2px; border-radius: 2px; }

/* TABELAS — nome/Sub ID à esquerda, números à direita. .table-scroll
   .data-table { min-width: max-content } (base) é o que fez a Mídia Paga
   estourar o viewport com conteúdo longo (03.1); aqui as tabelas têm 4-6
   colunas e sempre cabem, então o piso vale 0 em TODAS as larguras
   (especificidade 0,3,1 vence o 0,2,0 da base, não depende de ordem). */
body.page-performance .table-scroll .data-table { min-width: 0; }
body.page-performance .data-table { table-layout: auto; }

/* Nome de produto/canal: ocupa a largura que sobra e trunca com ellipsis;
   texto completo continua no DOM (leitor de tela) e no title. */
body.page-performance .perf-name-cell { width: 100%; max-width: 0; }
body.page-performance .perf-name { display: block; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Sub ID: identificador operacional — texto normal (não badge/negrito),
   quebra em vez de truncar, nunca alarga a tabela. */
body.page-performance .perf-subid-cell { max-width: 380px; }
body.page-performance .perf-subid { display: block; min-width: 0; overflow-wrap: anywhere; word-break: break-word; font-weight: 500; }
body.page-performance .data-table th { white-space: nowrap; }
body.page-performance .perf-action-col,
body.page-performance .perf-action-cell { width: 1%; white-space: nowrap; text-align: right; }

body.page-performance #subid-detail-raw { overflow-wrap: anywhere; word-break: break-word; }

/* Larguras intermediárias (tablet/desktop estreito): o nome ganha até 2 linhas
   em vez de ellipsis de linha única. */
@media (min-width: 641px) and (max-width: 1100px) {
  body.page-performance .perf-name {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    white-space: normal;
    overflow-wrap: anywhere;
  }
}

@media (max-width: 860px) {
  body.page-performance .period-controls { width: 100%; }
}

@media (max-width: 640px) {
  body.page-performance .filter-bar { flex-direction: column; align-items: stretch; }
  body.page-performance .period-controls { width: 100%; }
  body.page-performance .view-tabs { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); overflow-x: visible; }
  body.page-performance .view-tabs button { min-width: 0; padding-inline: 6px; }
  body.page-performance #kpi-section { grid-template-columns: 1fr; }

  /* Linha → cartão (mesmo padrão .record-list-mobile já usado aqui): produto
     é a primeira leitura, até 2 linhas; métricas abaixo em grade. */
  body.page-performance .record-list-mobile td { min-width: 0; }
  body.page-performance .perf-name-cell { width: auto; max-width: none; }
  body.page-performance .perf-name {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    white-space: normal;
    overflow-wrap: anywhere;
  }
  body.page-performance .record-list-mobile tr { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  body.page-performance #performance-table[data-mode="products"] tr,
  body.page-performance #performance-table[data-mode="channels"] tr { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  body.page-performance .perf-subid-cell { max-width: none; }
  body.page-performance .perf-subid { font-weight: 600; }
  body.page-performance .record-list-mobile td.perf-action-cell { grid-column: 1 / -1; width: auto; text-align: left; }
  body.page-performance .perf-action-cell .link-button { min-height: 40px; display: inline-flex; align-items: center; }
  body.page-performance .table-toolbar { gap: 8px; }
  body.page-performance .table-toolbar input[type="search"],
  body.page-performance .table-toolbar select { min-height: 40px; }
}

/* .filter-select-group define display:flex, o que anulava o atributo hidden
   do filtro "Origem" (exclusivo do modo Sub IDs). */
body.page-performance .filter-select-group[hidden] { display: none; }

/* ==========================================================================
   IMPLEMENTATION-05-OPERATION-V1.1 — Operação V1.1.
   Escopado a body.page-operations (só existe em operations.html):
   .integration-row-*, .filter-presets, .table-toolbar, .status-dot-*,
   .panel-link e .click-import-result são compartilhados com outras páginas e
   não podem mudar de aparência lá. --accent (laranja legado) NÃO é alterado
   globalmente. Estados operacionais usam tokens semânticos (success/
   warning/danger/loading); bronze só em ação/seleção/foco, nunca como status.
   Nenhuma API, sync, polling ou regra de dados muda nesta seção.
   ========================================================================== */

body.page-operations .ops-section { margin-bottom: var(--space-3); }
body.page-operations .ops-section .panel-header { margin-bottom: 10px; }

/* Fontes de dados — cartões baixos, 2 colunas quando cabem. */
body.page-operations .ops-source-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-3);
}
body.page-operations .ops-source-card {
  display: flex;
  flex-direction: column;
  gap: 8px;
  min-width: 0;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 14px 18px;
}
body.page-operations .ops-source-head { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 4px 12px; }
body.page-operations .ops-source-head h3 { margin: 0; }
body.page-operations .ops-source-fresh { margin: 0; color: var(--text-muted); font-size: 12.5px; line-height: 1.5; overflow-wrap: anywhere; min-height: 1.5em; }
body.page-operations .ops-source-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: auto; }

/* Estado de conexão: texto SEMPRE presente (não depende só de cor) + ponto. */
body.page-operations .integration-row-status { display: inline-flex; align-items: center; gap: 6px; font-weight: 650; color: var(--loading); }
body.page-operations .integration-row-status::before { content: ""; width: 8px; height: 8px; border-radius: 50%; background: currentColor; flex: none; }
body.page-operations .integration-row-status[data-tone="ok"] { color: var(--success); }
body.page-operations .integration-row-status[data-tone="pending"] { color: var(--text-muted); }
body.page-operations .integration-row-status[data-tone="warn"] { color: var(--warning); }
body.page-operations .integration-row-status[data-tone="error"] { color: var(--danger); }
body.page-operations .integration-row-status[data-tone="neutral"] { color: var(--loading); }

/* Ações: neutras por padrão; primária em bronze (ação), foco visível. */
body.page-operations .integration-row-action { min-height: 36px; display: inline-flex; align-items: center; background: var(--surface); }
body.page-operations .integration-row-action:hover { border-color: var(--brand-bronze); color: var(--brand-bronze); }
body.page-operations .integration-row-action-primary { background: var(--brand-bronze); border-color: var(--brand-bronze); color: #fff; }
body.page-operations .integration-row-action-primary:hover { background: var(--brand-bronze); border-color: var(--brand-bronze); color: #fff; filter: brightness(0.92); }
body.page-operations .integration-row-action:focus-visible,
body.page-operations .filter-presets button:focus-visible,
body.page-operations .panel-link:focus-visible,
body.page-operations #shopee-connect-button:focus-visible { outline: 2px solid var(--brand-bronze); outline-offset: 2px; }
body.page-operations #shopee-connect-button { background: var(--brand-bronze); border: 1px solid var(--brand-bronze); color: #fff; border-radius: var(--radius-sm); padding: 8px 16px; font-weight: 650; cursor: pointer; }
body.page-operations .panel-link { color: var(--brand-bronze); }
body.page-operations .click-import-result.success { background: var(--success-bg); color: var(--success); }

/* Status geral + pedidos importados — faixa compacta, não 4 KPIs. */
body.page-operations .ops-health { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 12px 24px; padding: 12px 18px; margin-bottom: var(--space-3); box-shadow: none; }
body.page-operations .ops-health-main { display: flex; align-items: flex-start; gap: 10px; min-width: 0; }
body.page-operations .ops-health-dot { width: 10px; height: 10px; margin-top: 5px; border-radius: 50%; background: var(--loading); flex: none; }
body.page-operations .ops-health-main[data-tone="ok"] .ops-health-dot { background: var(--success); }
body.page-operations .ops-health-main[data-tone="info"] .ops-health-dot { background: var(--loading); }
body.page-operations .ops-health-main[data-tone="warn"] .ops-health-dot { background: var(--warning); }
body.page-operations .ops-health-main[data-tone="error"] .ops-health-dot { background: var(--danger); }
body.page-operations .ops-health-copy { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
body.page-operations .ops-health-kicker { color: var(--text-muted); font-size: 11.5px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; }
body.page-operations .ops-health-copy strong { font-size: 14.5px; }
body.page-operations .ops-health-copy span:last-child { color: var(--text-muted); font-size: 12.5px; }
body.page-operations .ops-health-copy span:last-child:empty { display: none; }
body.page-operations .ops-health-metric { display: flex; align-items: baseline; gap: 8px; }

/* Pedidos recentes — toolbar dentro do painel, presets em bronze. */
body.page-operations .filter-presets button.active {
  background: var(--brand-bronze-soft);
  border-color: transparent;
  border-bottom: 2px solid var(--brand-bronze);
  color: var(--brand-bronze);
  font-weight: 700;
}
body.page-operations .table-toolbar .filter-search { min-width: 200px; }
body.page-operations .table-scroll .data-table { min-width: 0; }
body.page-operations .ops-col-status { white-space: nowrap; }
body.page-operations .ops-col-date { white-space: nowrap; }
body.page-operations .ops-col-product { width: 100%; max-width: 0; }
body.page-operations .ops-name { display: block; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Status de pedido: só "Concluído" ganha cor semântica; pendente/cancelado/
   não pago ficam neutros (não reinterpretar como erro). O texto do status
   continua sempre visível. */
body.page-operations .ops-orders .status-dot-pending,
body.page-operations .ops-orders .status-dot-cancelled,
body.page-operations .ops-orders .status-dot-other { background: var(--text-faint); }

@media (min-width: 641px) and (max-width: 1100px) {
  body.page-operations .ops-name {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    white-space: normal;
    overflow-wrap: anywhere;
  }
}

@media (max-width: 860px) {
  body.page-operations .table-toolbar { flex-direction: column; align-items: stretch; }
  body.page-operations .table-toolbar .filter-search { min-width: 0; }
}

@media (max-width: 640px) {
  body.page-operations .ops-source-grid { grid-template-columns: 1fr; }
  body.page-operations .ops-health { align-items: flex-start; }
  body.page-operations .ops-health-metric { width: 100%; justify-content: space-between; border-top: 1px solid var(--border); padding-top: 10px; }
  body.page-operations .integration-row-action,
  body.page-operations .filter-presets button,
  body.page-operations .table-toolbar input[type="search"],
  body.page-operations .table-toolbar select { min-height: 40px; }
  body.page-operations .filter-presets { flex-wrap: wrap; }

  /* Linha de pedido vira cartão: produto (até 2 linhas) primeiro, depois
     Data/Status/Comissão com rótulo. Sem scroll horizontal. */
  body.page-operations .ops-orders.table-scroll { overflow-x: visible; }
  body.page-operations .ops-orders .data-table { display: block; width: 100%; }
  body.page-operations .ops-orders thead { display: none; }
  body.page-operations .ops-orders tbody { display: flex; flex-direction: column; gap: 10px; }
  body.page-operations .ops-orders tr {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 8px 14px;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 12px 14px;
  }
  body.page-operations .ops-orders td { display: block; min-width: 0; padding: 0; border-bottom: 0; }
  body.page-operations .ops-orders td.ops-col-product { grid-column: 1 / -1; order: -1; width: auto; max-width: none; font-weight: 700; font-size: 14px; }
  body.page-operations .ops-orders td.num { grid-column: 1 / -1; text-align: left; }
  body.page-operations .ops-orders td[data-label]::before {
    content: attr(data-label);
    display: block;
    color: var(--text-faint);
    font-size: 10.5px;
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    margin-bottom: 2px;
  }
  body.page-operations .ops-name {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    white-space: normal;
    overflow-wrap: anywhere;
  }
}

/* ==========================================================================
   IMPLEMENTATION-06-ACCOUNT-SUBSCRIPTION-V1.1 — Conta + Assinatura V1.1.
   Escopado a body.page-account e body.page-subscription (só existem em
   account.html/subscription.html): .drawer-meta, .panel-link, .link-button e
   .panel-note são compartilhados com outras páginas e não podem mudar de
   aparência lá. --accent (laranja legado) NÃO é alterado globalmente. Bronze
   só em ação/foco; estados comerciais usam tokens semânticos (success/
   warning/loading) e SEMPRE têm texto. Nenhuma lógica de Auth/Billing muda.
   ========================================================================== */

body.page-account .account-stack,
body.page-subscription .subscription-stack {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  max-width: 720px;
  min-width: 0;
}
body.page-account .account-stack .panel,
body.page-subscription .subscription-stack .panel { margin-bottom: 0; min-width: 0; }

/* Estado comercial / conexão: ponto + texto (nunca só cor). */
body.page-account .account-status,
body.page-subscription .account-status {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-size: 13px;
  font-weight: 650;
  color: var(--loading);
}
body.page-account .account-status::before,
body.page-subscription .account-status::before {
  content: "";
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: currentColor;
  flex: none;
}
body.page-account .account-status[data-tone="ok"],
body.page-subscription .account-status[data-tone="ok"] { color: var(--success); }
body.page-account .account-status[data-tone="warn"],
body.page-subscription .account-status[data-tone="warn"] { color: var(--warning); }
body.page-account .account-status[data-tone="info"],
body.page-subscription .account-status[data-tone="info"] { color: var(--loading); }
body.page-account .account-status[data-tone="pending"],
body.page-subscription .account-status[data-tone="pending"],
body.page-account .account-status[data-tone="neutral"],
body.page-subscription .account-status[data-tone="neutral"] { color: var(--text-muted); }

/* CONTA — identidade compacta (nome em destaque, sem card vazio). */
body.page-account .account-person { display: flex; align-items: center; gap: 16px; min-width: 0; }
body.page-account .account-avatar {
  flex: none;
  display: grid;
  place-items: center;
  width: 52px;
  height: 52px;
  border-radius: 50%;
  background: var(--brand-navy);
  color: #fff;
  font-size: 20px;
  font-weight: 700;
}
body.page-account .account-meta { margin: 0; grid-template-columns: minmax(0, 1fr); gap: 2px; min-width: 0; flex: 1; }
body.page-account .account-meta dt { font-size: 11.5px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; color: var(--text-muted); }
body.page-account .account-meta dd { font-size: 18px; font-weight: 700; overflow-wrap: anywhere; }

/* CONTA — fonte de dados: só o estado resumido + caminho para gerenciar. */
body.page-account .account-source-row { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 4px 12px; }
body.page-account .account-source-name { font-size: 14.5px; }
body.page-account .account-source .panel-note,
body.page-account .account-subscription .panel-note { margin-top: 10px; }
body.page-account .panel-note a,
body.page-account .panel-link { color: var(--brand-bronze); font-weight: 600; }
body.page-account .panel-link { display: inline-block; margin-top: 12px; min-height: 24px; }
body.page-account .panel-note a:focus-visible,
body.page-account .panel-link:focus-visible { outline: 2px solid var(--brand-bronze); outline-offset: 2px; border-radius: 2px; }
body.page-account .account-subscription .drawer-meta { align-items: center; }
body.page-account .account-subscription .drawer-meta dd { overflow-wrap: anywhere; }

/* ASSINATURA — plano atual → estado/validade → ação → auxiliar. */
body.page-subscription .subscription-panel { padding: 22px 24px; }
body.page-subscription .subscription-eyebrow { margin: 0 0 6px; font-size: 11.5px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em; color: var(--text-muted); }
body.page-subscription .subscription-plan { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 12px; margin-bottom: 18px; }
body.page-subscription .subscription-plan-name { font-size: 26px; font-weight: 700; letter-spacing: -0.01em; }
body.page-subscription .subscription-plan-price { font-size: 16px; font-weight: 600; color: var(--text-muted); font-variant-numeric: tabular-nums; }
body.page-subscription .subscription-status-block { display: flex; flex-direction: column; align-items: flex-start; gap: 6px; padding-top: 16px; border-top: 1px solid var(--border); }
body.page-subscription .subscription-headline { margin: 0; font-size: 17px; font-weight: 700; }
body.page-subscription .subscription-panel .panel-note { margin: 8px 0 0; overflow-wrap: anywhere; }
body.page-subscription .subscription-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 12px 20px; margin-top: 18px; }
body.page-subscription .subscription-actions:empty,
body.page-subscription .subscription-actions:not(:has(button:not([hidden]))) { display: none; }

/* Ação principal (reativar) em bronze; cancelar é ação destrutiva
   SECUNDÁRIA — texto discreto, nunca um botão vermelho grande; a cor de
   perigo só aparece no hover/foco da confirmação. */
body.page-subscription .subscription-action-primary {
  min-height: 44px;
  padding: 0 20px;
  border-radius: var(--radius-sm);
  background: var(--brand-bronze);
  color: #fff;
  font-weight: 650;
  text-decoration: none;
}
body.page-subscription .subscription-action-primary:hover { background: var(--brand-bronze); color: #fff; filter: brightness(0.92); }
body.page-subscription .subscription-action-quiet {
  min-height: 44px;
  padding: 0 4px;
  color: var(--text-muted);
  font-weight: 600;
  font-size: 13px;
  text-decoration: underline;
  text-underline-offset: 3px;
}
body.page-subscription .subscription-action-quiet:hover { color: var(--danger); }
body.page-subscription .subscription-aux { padding: 0 4px; }
body.page-subscription .subscription-action-secondary {
  min-height: 44px;
  padding: 0 18px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--text);
  font-weight: 650;
  text-decoration: none;
}
body.page-subscription .subscription-action-secondary:hover { border-color: var(--brand-bronze); color: var(--brand-bronze); background: var(--surface); }
body.page-subscription .link-button:disabled { opacity: 0.55; cursor: not-allowed; }
body.page-subscription .link-button:focus-visible { outline: 2px solid var(--brand-bronze); outline-offset: 2px; }

@media (max-width: 640px) {
  body.page-subscription .subscription-panel { padding: 18px 16px; }
  body.page-subscription .subscription-plan-name { font-size: 24px; }
  body.page-subscription .subscription-actions { flex-direction: column; align-items: stretch; }
  body.page-subscription .subscription-action-primary { width: 100%; }
  body.page-subscription .subscription-action-quiet { align-self: center; }
  body.page-subscription .subscription-action-secondary { width: 100%; }
  body.page-account .panel-link { min-height: 40px; display: inline-flex; align-items: center; }
}

/* ==========================================================================
   IMPLEMENTATION-07-AUTH-ENTRY-V1.1 — Entrada / autenticação V1.1.
   Escopado a body.login-body (login, signup, reset-password, auth-callback,
   onboarding: as páginas pré-auth/primeira entrada) e às classes exclusivas
   do overlay comercial (.commercial-lock-*). .login-card button, .link-button,
   .integration-row-action-primary e .click-import-result são compartilhados
   com o app autenticado e NÃO mudam lá. --accent (laranja legado) NÃO é
   alterado globalmente. Bronze só em ação/foco; erro = danger, loading =
   neutro. Nenhuma lógica de Auth/sessão/redirect/comercial muda aqui.
   ========================================================================== */

body.login-body {
  box-sizing: border-box;
  min-height: 100vh;
  padding: 24px 16px;
  background:
    radial-gradient(900px 480px at 50% -12%, rgba(16, 18, 26, 0.07) 0%, transparent 65%),
    var(--bg);
}
body.login-body .login-card {
  max-width: 400px;
  padding: 36px 32px 30px;
  border-top: 3px solid var(--brand-navy);
  box-shadow: var(--shadow-md);
}
body.login-body .login-card.onboarding-card { max-width: 440px; }
/* O asset da logo tem respiro transparente embutido (acima/abaixo/esquerda); compensa para o título e o cartão ficarem próximos da marca. */
body.login-body .login-logo { max-width: 200px; margin: -26px 0 -22px -12px; }

/* Título / contexto (só login.html usa estas classes). */
body.login-body .login-card .login-title { margin: 14px 0 6px; font-size: 17px; font-weight: 700; color: var(--text); }
body.login-body .login-card .login-context { margin: 0 0 22px; font-size: 13px; line-height: 1.5; color: var(--text-muted); }

/* Campos: alvo de toque de 44px, foco bronze. */
body.login-body .login-card input { min-height: 44px; box-sizing: border-box; }
body.login-body .login-card input:focus-visible { outline: 2px solid var(--brand-bronze); outline-offset: 1px; }
body.login-body .password-toggle:focus-visible { outline: 2px solid var(--brand-bronze); outline-offset: 1px; }

/* CTA Google: primeiro, largo e com peso — o caminho principal quando existe
   (o atributo hidden precisa continuar valendo: display:flex o anularia). */
body.login-body .google-signin-button {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  min-height: 48px;
  border: 1.5px solid var(--brand-navy) !important;
  color: var(--brand-navy) !important;
  background: var(--surface) !important;
  font-size: 15px;
  font-weight: 700;
}
body.login-body .google-signin-button[hidden] { display: none; }
/* Idem para o divisor "ou": sem Google disponível ele não deve aparecer sozinho. */
body.login-body .login-divider[hidden] { display: none; }
body.login-body .google-signin-button::before {
  content: "";
  flex: none;
  width: 18px;
  height: 18px;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 48 48'%3E%3Cpath fill='%23EA4335' d='M24 9.5c3.5 0 6.6 1.2 9.1 3.6l6.8-6.8C35.9 2.4 30.4 0 24 0 14.6 0 6.5 5.4 2.6 13.2l7.9 6.1C12.4 13.6 17.7 9.5 24 9.5z'/%3E%3Cpath fill='%234285F4' d='M46.5 24.5c0-1.6-.1-3.1-.4-4.5H24v9h12.7c-.6 3-2.3 5.5-4.8 7.2l7.6 5.9c4.4-4.1 7-10.1 7-17.6z'/%3E%3Cpath fill='%23FBBC05' d='M10.5 28.7A14.5 14.5 0 0 1 9.5 24c0-1.6.3-3.2.8-4.7l-7.9-6.1A24 24 0 0 0 0 24c0 3.9.9 7.5 2.6 10.8l7.9-6.1z'/%3E%3Cpath fill='%2334A853' d='M24 48c6.5 0 11.9-2.1 15.9-5.8l-7.6-5.9c-2.1 1.4-4.9 2.3-8.3 2.3-6.3 0-11.6-4.1-13.5-9.8l-7.9 6.1C6.5 42.6 14.6 48 24 48z'/%3E%3C/svg%3E") center / contain no-repeat;
}
body.login-body .google-signin-button:hover { background: var(--surface-sunken) !important; }
body.login-body .google-signin-button:focus-visible { outline: 2px solid var(--brand-bronze); outline-offset: 2px; }
body.login-body .google-signin-button:disabled { opacity: 0.6; cursor: not-allowed; }

/* Ação de envio (Entrar/Criar conta/...) em bronze, nunca laranja legado. */
body.login-body .login-card button[type="submit"] {
  min-height: 46px;
  background: var(--brand-bronze);
  color: #fff;
  font-size: 14.5px;
}
body.login-body .login-card button[type="submit"]:hover:not(:disabled) { background: var(--brand-bronze); filter: brightness(0.92); }
body.login-body .login-card button[type="submit"]:focus-visible { outline: 2px solid var(--brand-bronze); outline-offset: 2px; }
body.login-body .login-card button[type="submit"]:disabled { opacity: 0.6; cursor: not-allowed; }

/* Erro real de autenticação: danger com marca lateral, sem detalhe técnico. */
body.login-body .login-error { border-left: 3px solid var(--danger); font-weight: 500; line-height: 1.45; }

/* Links de apoio: bronze + foco visível, alvo de toque generoso. */
body.login-body .login-hint { font-size: 12.5px; }
body.login-body .login-hint a,
body.login-body .login-back { color: var(--brand-bronze); font-weight: 650; }
body.login-body .login-back { display: inline-flex; align-items: center; min-height: 40px; margin-top: 8px; font-size: 12.5px; }
body.login-body .login-back:hover { color: var(--brand-bronze); }
body.login-body .login-hint a:focus-visible,
body.login-body .login-back:focus-visible { outline: 2px solid var(--brand-bronze); outline-offset: 2px; border-radius: 2px; }
body.login-body .login-card button.link-button:hover { color: var(--brand-bronze); }

/* Onboarding (primeira entrada real): ação primária bronze; sucesso com tokens
   semânticos, não com o laranja legado. */
body.login-body .integration-row-action-primary { background: var(--brand-bronze); border-color: var(--brand-bronze); color: #fff; }
body.login-body .integration-row-action-primary:hover { background: var(--brand-bronze); border-color: var(--brand-bronze); filter: brightness(0.92); }
body.login-body .integration-row-action { min-height: 44px; display: inline-flex; align-items: center; justify-content: center; }
body.login-body .integration-row-action:focus-visible { outline: 2px solid var(--brand-bronze); outline-offset: 2px; }
body.login-body .click-import-result.success { background: var(--success-bg); color: var(--success); }

/* Overlay comercial pós-trial (classes exclusivas): CTA e seleção em bronze;
   o preço deixa de ser laranja (não é status nem ação). */
.commercial-lock-cta { background: var(--brand-bronze); min-height: 46px; }
.commercial-lock-cta:hover:not(:disabled) { background: var(--brand-bronze); filter: brightness(0.92); }
.commercial-lock-cta:focus-visible,
.commercial-lock-feedback-options button:focus-visible,
.commercial-lock-logout:focus-visible { outline: 2px solid var(--brand-bronze); outline-offset: 2px; }
.commercial-lock-plan-price { color: var(--text); }
.commercial-lock-card .commercial-lock-logout { color: var(--text-muted); font-size: 13px; min-height: 40px; text-decoration: underline; text-underline-offset: 3px; }
.commercial-lock-card .commercial-lock-logout:hover { color: var(--text); }
.commercial-lock-feedback-options button { min-height: 40px; }
.commercial-lock-feedback-options button:hover:not(:disabled) { border-color: var(--brand-bronze); color: var(--brand-bronze); }
.commercial-lock-feedback-options button.commercial-lock-feedback-selected { background: var(--brand-bronze-soft); border-color: var(--brand-bronze); color: var(--brand-bronze); }

@media (max-width: 480px) {
  body.login-body { padding: 16px 12px; }
  body.login-body .login-card { padding: 28px 20px 22px; }
  body.login-body .login-card .login-context { margin-bottom: 18px; }
  .commercial-lock-card { padding: 22px 18px; }
}

/* ==========================================================================
   IMPLEMENTATION-07.1-RELEASE-CLEANUP — Mídia Paga: overflow horizontal da
   PÁGINA em ~1024px. Causa raiz medida no candidate real: o span .sr-only
   ("Detalhes", th.campaign-expand-col) é position:absolute e TODOS os seus
   ancestrais eram position:static (inclusive o .table-scroll, que só tem
   overflow-x:auto — overflow sozinho NÃO cria containing block para
   descendentes absolutos). O bloco de contenção virava a viewport e o
   elemento ficava na posição estática dentro da tabela (x≈1029, além dos
   1009px visíveis), ampliando o scrollWidth do documento em ~20px mesmo com
   a tabela rolando por dentro (803/699). position:relative no próprio
   .table-scroll faz o .sr-only ser contido e recortado por ele. O texto
   continua no DOM e acessível (nenhum display:none / visibility). Escopado a
   body.page-paid-media: as outras páginas não têm .sr-only em tabela.
   ========================================================================== */

body.page-paid-media .table-scroll { position: relative; }

/* ==========================================================================
   AUTO-REFRESH-20M — bloco informativo "Dados Shopee" (Visão Geral). Sem botão: a atualização é
   automática e global. Reaproveita os tokens existentes; sem identidade nova. Estados via
   [data-state]/[data-tone]. Não declara display no elemento raiz, então o atributo [hidden] vale.
   ========================================================================== */
.auto-refresh {
  max-width: 720px;
  margin: -6px 0 20px;
  padding: 10px 13px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  box-shadow: var(--shadow-sm);
  font-size: 13px;
  line-height: 1.45;
  color: var(--text-muted);
}
.auto-refresh > span { display: block; overflow-wrap: anywhere; }
.auto-refresh-title { color: var(--text); font-size: 13.5px; font-weight: 700; }
.auto-refresh-message { margin-top: 2px; color: var(--text); font-weight: 600; }
.auto-refresh-message:empty { margin-top: 0; }
.auto-refresh[data-tone="ok"] .auto-refresh-message { color: var(--success); }
.auto-refresh-info { margin-top: 2px; font-size: 12.5px; }
@media (max-width: 560px) {
  .auto-refresh { margin-top: 0; }
}
