/* ==========================================================================
   CX Analytics — sistema visual
   ==========================================================================
   Alinhado ao padrão do time de Produtos (produtos.eqi.life), a partir das telas
   de referência: Início, Follow Up, Operacional, Oportunidades, Solicitações,
   Internacional e Calculadoras.

   O QUE DEFINE O PADRÃO, em ordem de importância:

   1. NEUTROS MORNOS, não cinza-frio. O fundo é um off-white bege (#F7F6F1) e o
      texto secundário tem viés cáqui (#6F6A5B), não cinza-azulado. Trocar só o
      verde e manter cinza neutro é o que faz um site "parecer que recebeu umas
      cores novas" em vez de pertencer ao ecossistema.
   2. VERDE ESCURO É TINTA DE TEXTO, não de fundo. Título, ícone e rótulo ativo
      são verde-escuro sobre claro. Fundo verde aparece em três lugares só:
      botão primário, barra de ação contextual e o item selecionado do segmented
      control. NÃO em cabeçalho de card nem em cabeçalho de tabela.
   3. SAGE (#DCE5DB) É O "SELECIONADO". Item ativo da sidebar, aba ativa dentro
      de card, faixa de hero. Sempre com texto verde-escuro.
   4. BORDA EM VEZ DE SOMBRA. Card é branco com 1px morno. Sombra só no que
      flutua (dropdown, modal).
   5. HIERARQUIA POR PESO E COR, não por caixa colorida. Título 600 verde-escuro,
      subtítulo 400 mudo, logo abaixo. Não há faixa colorida separando um do outro.

   Toda classe que os templates já usavam continua existindo — a migração é de
   ESTILO, não de marcação, justamente porque editar
   por `replace` de string em template com texto duplicado já quebrou três
   layouts sem `check` nem HTTP 200 acusarem.
   ========================================================================== */

/* --------------------------------------------------------------------------
   Fonte — DM Sans, servida localmente
   --------------------------------------------------------------------------
   Arquivo local e não CDN de propósito: o container não tem saída garantida
   para fonts.gstatic.com, e fonte que falha em produção derruba a identidade
   inteira para o stack do sistema.

   Variável de 400 a 700 num arquivo só (`font-weight: 400 700`), então os
   pesos 500/600 que este CSS usa são interpolados sem baixar mais nada.
   `latin` cobre todo o português (ç, ã, õ, á, é, í, ó, ú vivem em U+00C0-00FF);
   `latin-ext` entra para nome próprio estrangeiro.
   -------------------------------------------------------------------------- */
@font-face {
  font-family: 'DM Sans';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url("../fonts/dmsans-latin.6c1e961057d2.woff2") format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'DM Sans';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url("../fonts/dmsans-latin-ext.b9209b52c467.woff2") format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
    U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
    U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* --------------------------------------------------------------------------
   Tokens
   -------------------------------------------------------------------------- */
:root {
  /* Verde da marca. A escala antiga ia até um mint saturado (#00C796) que não
     existe no padrão de Produtos; aqui ela termina num verde-médio sóbrio, e o
     peso vem do tom escuro, não da saturação. */
  --brand-50: #F2F5F1;
  --brand-100: #E4EDE5;
  --brand-200: #C9DBCC;
  --brand-300: #A3C1AA;
  --brand-400: #5C9478;
  --brand-500: #3E7A5E;
  --brand-600: #1E5540;
  --brand-700: #123A2C;
  --brand-800: #0F3328;
  --brand-900: #0B2620;
  --brand-950: #071A15;

  /* Sage — a cor do "selecionado". Item ativo da sidebar, aba ativa, faixa de
     hero. Nunca carrega texto branco: o contraste com verde-escuro é o efeito. */
  --sage-100: #E7EEE6;
  --sage-200: #DCE5DB;
  --sage-300: #CBD9C9;

  /* Neutros MORNOS. O viés bege é o que casa com o padrão de Produtos — cinza
     neutro no mesmo layout lê como "outro produto". */
  --warm-50: #FAF9F5;
  --warm-100: #F7F6F1;
  --warm-150: #F4F3ED;
  --warm-200: #EFEDE5;
  --warm-300: #E6E3DA;
  --warm-400: #D8D4C8;

  --bg-app: var(--warm-100);
  --bg-sidebar: var(--warm-50);
  --bg-surface: #FFFFFF;
  --bg-inset: var(--warm-150);
  --bg-hover: var(--warm-100);

  --border-subtle: var(--warm-300);
  --border-strong: var(--warm-400);

  /* Título em verde-escuro e corpo em quase-preto esverdeado: os dois papéis são
     distintos no padrão de referência, e usar a mesma cor nos dois achata a
     hierarquia que o material constrói só com peso e tom. */
  --text-title: #10352A;
  --text-primary: #23302A;
  --text-secondary: #6F6A5B;
  --text-tertiary: #948E7C;
  --text-on-dark: #FFFFFF;
  --text-on-dark-muted: rgba(255, 255, 255, 0.68);

  --accent: var(--brand-500);
  /* Mantido por compatibilidade: `--panel-header-bg` era o verde da faixa de
     cabeçalho, que deixou de existir. Aponta para a superfície do card para que
     qualquer regra remanescente não pinte uma faixa escura de volta. */
  --panel-header-bg: var(--bg-surface);

  --good: #1E7A52;
  --good-bg: #E7F1E9;
  --good-border: #C8DFD0;
  --bad: #B4423A;
  --bad-bg: #F8EBE8;
  --bad-border: #EBCFC9;
  --warn: #B07B22;
  --warn-text: #7A5A22;
  --warn-bg: #FBEEDA;
  --warn-border: #F0DCBB;
  --info: #2C5F8A;
  --info-bg: #E8EFF6;
  --info-border: #CFDEEC;

  --radius-sm: 8px;
  --radius-md: 12px;
  --radius-lg: 16px;
  --radius-pill: 999px;

  /* Card é borda, não sombra. Sombra existe só para o que FLUTUA — e aí é
     generosa, para o painel descolar do fundo morno. */
  --shadow-card: 0 1px 2px rgba(16, 53, 42, 0.03);
  --shadow-pop: 0 4px 6px -2px rgba(16, 53, 42, 0.06), 0 12px 28px -8px rgba(16, 53, 42, 0.16);
  --shadow-modal: 0 24px 64px -12px rgba(11, 38, 32, 0.28);

  /* 252px e não 236: a sidebar virou a ÚNICA navegação por página, então rótulo
     truncado ali não tem mais uma faixa de abas no topo para compensar — e
     "Estratégia de campan…" é um item de menu que não diz para onde vai. */
  --sidebar-w: 252px;
  --sidebar-w-collapsed: 68px;
  --content-max: 1440px;

  /* Compat: nomes que o CSS antigo expunha. Mantidos para nenhuma regra órfã
     cair em `unset` e pintar preto. */
  --sidebar-bg: var(--bg-sidebar);
  --sidebar-text: var(--text-title);
  --sidebar-text-muted: var(--text-secondary);
  --sidebar-hover-bg: var(--warm-200);
  --sidebar-active-bg: var(--sage-200);
  --sidebar-active-text: var(--text-title);
  --sidebar-border: var(--border-subtle);

  /* ------------------------------------------------------------------------
     Cores dos GRÁFICOS
     ------------------------------------------------------------------------
     Existem como variável, e não como hex dentro do JS, porque o Chart.js
     desenha em canvas: o canvas não herda nada de CSS, então uma cor fixa no JS
     ficaria clara no tema escuro sem nenhum erro em lugar nenhum — gráfico com
     grade branca sobre fundo escuro não derruba `check` nem muda o HTTP 200.

     Cada arquivo de gráfico lê estas variáveis com um helper LOCAL, de três
     linhas, e não por um módulo compartilhado:
     compartilhar helper de JS entre telas quebrou os gráficos em 05/08/2026 com
     causa nunca identificada. Todo `cor()` no JS leva um fallback em hex, então
     variável ausente degrada para a cor do tema claro em vez de para preto.
     ------------------------------------------------------------------------ */
  --chart-grid: #EBE9E1;
  --chart-tick: #6F6A5B;
  --chart-label: #23302A;
  --chart-muted: #948E7C;

  /* Série 1 é a mais escura e 6 a mais clara: a ordem é a rampa, e trocar a
     ordem inverte a leitura de qualquer gráfico empilhado. */
  --chart-1: #123A2C;
  --chart-2: #2E6B50;
  --chart-3: #3E7A5E;
  --chart-4: #5C9478;
  --chart-5: #AFC7B5;
  --chart-6: #8AA396;

  --chart-good: #1E7A52;
  --chart-bad: #B4423A;
  --chart-bad-claro: #DDAFA9;
  --chart-warn: #B07B22;
  --chart-amber: #C1852A;

  --chart-fill: rgba(18, 58, 44, 0.12);
  --chart-fill-forte: rgba(62, 122, 94, 0.55);
  --chart-fill-bad: rgba(180, 66, 58, 0.12);
  --chart-fill-suave: rgba(18, 58, 44, 0.08);

  --focus-ring: rgba(62, 122, 94, 0.16);

  /* ------------------------------------------------------------------------
     Ícones em `data:` URI — o `url()` INTEIRO na variável
     ------------------------------------------------------------------------
     Um data URI é uma string opaca: não existe forma de pôr `var(--cor)` dentro
     do SVG, então a cor do traço fica escrita ali (`%23` é o `#` escapado).

     Guardar o `url()` completo num token é o que mantém a regra "no tema escuro
     só os tokens mudam". A alternativa era repetir cada `background-image` nos
     dois blocos escuros — seis regras de componente duplicadas duas vezes, que
     é exatamente a segunda folha de estilo em paralelo que este arquivo evita.
     ------------------------------------------------------------------------ */
  --icone-ok: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%231E7A52' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cpath d='M8.5 12.5l2.5 2.5 4.5-5'/%3E%3C/svg%3E");
  --icone-atencao: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%237A5A22' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M10.3 3.8 1.8 18a2 2 0 0 0 1.7 3h17a2 2 0 0 0 1.7-3L13.7 3.8a2 2 0 0 0-3.4 0Z'/%3E%3Cpath d='M12 9v4M12 17h.01'/%3E%3C/svg%3E");
  --icone-info: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%232C5F8A' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cpath d='M12 16v-5M12 8h.01'/%3E%3C/svg%3E");
  --icone-vazio: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23948E7C' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M22 12h-6l-2 3h-4l-2-3H2'/%3E%3Cpath d='M5.45 5.11 2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.45-6.89A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11z'/%3E%3C/svg%3E");
  --icone-chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none' stroke='%236F6A5B' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 8l4 4 4-4'/%3E%3C/svg%3E");
  --icone-chevron-forte: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none' stroke='%2310352A' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 8l4 4 4-4'/%3E%3C/svg%3E");
}

:root {
  color-scheme: light;
}

/* ==========================================================================
   TEMA ESCURO
   ==========================================================================
   Só os TOKENS são redefinidos — nenhuma regra de componente aparece aqui. Foi
   possível porque o tema claro já não tem cor solta: cada card, borda e texto
   sai de uma variável. Componente redefinido no bloco escuro seria uma segunda
   folha de estilo a manter em paralelo, e as duas sairiam de sincronia na
   primeira mudança de layout.

   Escuro MORNO e esverdeado, não preto azulado: o claro é bege, e um escuro
   neutro-frio ao lado dele lê como outro produto. Mesma razão pela qual os
   neutros claros têm viés cáqui.

   Duas portas de entrada, nesta ordem de precedência:
     1. `@media (prefers-color-scheme: dark)` sob `:root:not([data-tema="claro"])`
        — segue o sistema quando o usuário não escolheu nada;
     2. `:root[data-tema="escuro"]` — a escolha explícita no botão vence sempre,
        nos dois sentidos.
   O `:not([data-tema="claro"])` da primeira é o que permite forçar CLARO dentro
   de um sistema em escuro: sem ele, a media query venceria e o botão só
   funcionaria em uma direção.
   ========================================================================== */
@media (prefers-color-scheme: dark) {
  :root:not([data-tema="claro"]) {
    color-scheme: dark;

    --warm-50: #1B201C;
    --warm-100: #171B18;
    --warm-150: #202520;
    --warm-200: #262C27;
    --warm-300: #2E352F;
    --warm-400: #414A42;

    --bg-app: #131715;
    --bg-sidebar: #171B18;
    --bg-surface: #1C211D;
    --bg-inset: #232823;
    --bg-hover: #262C27;

    --border-subtle: #2C332D;
    --border-strong: #3C443D;

    --text-title: #E9F0EA;
    --text-primary: #D3DBD5;
    --text-secondary: #9BA49C;
    --text-tertiary: #79827A;
    --text-on-dark: #0E1410;
    --text-on-dark-muted: rgba(14, 20, 16, 0.66);

    /* A escala inverte: no claro o peso vem do tom ESCURO; no escuro, do CLARO.
       Manter #123A2C como "brand-700" aqui pintaria botão primário quase
       invisível sobre o fundo. */
    --brand-100: #1E2A22;
    --brand-200: #2A3A2F;
    --brand-300: #3E5A48;
    --brand-400: #5C9478;
    --brand-500: #6FB894;
    --brand-600: #57A883;
    --brand-700: #4C9B74;
    --brand-800: #3E8A66;
    --brand-900: #2E6B50;

    --sage-100: #202B24;
    --sage-200: #2A3A2F;
    --sage-300: #38493D;

    --good: #58BF8C;
    --good-bg: #1A2A21;
    --good-border: #2C4535;
    --bad: #E3837A;
    --bad-bg: #2C1E1C;
    --bad-border: #4A2E2A;
    --warn: #D9A34A;
    --warn-text: #E4C083;
    --warn-bg: #2A2317;
    --warn-border: #453A22;
    --info: #7FB3DF;
    --info-bg: #1A2430;
    --info-border: #2A3A4A;

    --shadow-card: 0 1px 2px rgba(0, 0, 0, 0.28);
    --shadow-pop: 0 4px 6px -2px rgba(0, 0, 0, 0.32), 0 12px 28px -8px rgba(0, 0, 0, 0.5);
    --shadow-modal: 0 24px 64px -12px rgba(0, 0, 0, 0.62);

    /* Gráficos: a rampa também inverte — série clara sobre fundo escuro. */
    --chart-grid: #2C332D;
    --chart-tick: #9BA49C;
    --chart-label: #E9F0EA;
    --chart-muted: #79827A;

    --chart-1: #7FC7A3;
    --chart-2: #5CAE86;
    --chart-3: #4C9B74;
    --chart-4: #3E8A66;
    --chart-5: #2C6249;
    --chart-6: #6E9A85;

    --chart-good: #58BF8C;
    --chart-bad: #E3837A;
    --chart-bad-claro: #7A4640;
    --chart-warn: #D9A34A;
    --chart-amber: #D9A34A;

    --chart-fill: rgba(127, 199, 163, 0.14);
    --chart-fill-forte: rgba(92, 174, 134, 0.5);
    --chart-fill-bad: rgba(227, 131, 122, 0.14);
    --chart-fill-suave: rgba(127, 199, 163, 0.08);
    --focus-ring: rgba(111, 184, 148, 0.20);

    /* Icones de traco claro. O SVG e string opaca, entao o token guarda o
       url() inteiro — ver o comentario na definicao do tema claro. */
    --icone-ok: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2358BF8C' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cpath d='M8.5 12.5l2.5 2.5 4.5-5'/%3E%3C/svg%3E");
    --icone-atencao: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23E4C083' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M10.3 3.8 1.8 18a2 2 0 0 0 1.7 3h17a2 2 0 0 0 1.7-3L13.7 3.8a2 2 0 0 0-3.4 0Z'/%3E%3Cpath d='M12 9v4M12 17h.01'/%3E%3C/svg%3E");
    --icone-info: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%237FB3DF' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cpath d='M12 16v-5M12 8h.01'/%3E%3C/svg%3E");
    --icone-vazio: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2379827A' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M22 12h-6l-2 3h-4l-2-3H2'/%3E%3Cpath d='M5.45 5.11 2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.45-6.89A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11z'/%3E%3C/svg%3E");
    --icone-chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none' stroke='%239BA49C' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 8l4 4 4-4'/%3E%3C/svg%3E");
    --icone-chevron-forte: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none' stroke='%23E9F0EA' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 8l4 4 4-4'/%3E%3C/svg%3E");

  }
}

/* Escolha explícita no botão. Bloco IDÊNTICO ao de cima, e a duplicação é
   intencional: `@media` e seletor de atributo não se combinam numa regra só, e
   as duas portas precisam produzir exatamente a mesma paleta. Alterar uma sem a
   outra deixa o tema do sistema diferente do tema do botão — o tipo de
   divergência que só aparece na máquina de quem tem o sistema em escuro. */
:root[data-tema="escuro"] {
  color-scheme: dark;

  --warm-50: #1B201C;
  --warm-100: #171B18;
  --warm-150: #202520;
  --warm-200: #262C27;
  --warm-300: #2E352F;
  --warm-400: #414A42;

  --bg-app: #131715;
  --bg-sidebar: #171B18;
  --bg-surface: #1C211D;
  --bg-inset: #232823;
  --bg-hover: #262C27;

  --border-subtle: #2C332D;
  --border-strong: #3C443D;

  --text-title: #E9F0EA;
  --text-primary: #D3DBD5;
  --text-secondary: #9BA49C;
  --text-tertiary: #79827A;
  --text-on-dark: #0E1410;
  --text-on-dark-muted: rgba(14, 20, 16, 0.66);

  --brand-100: #1E2A22;
  --brand-200: #2A3A2F;
  --brand-300: #3E5A48;
  --brand-400: #5C9478;
  --brand-500: #6FB894;
  --brand-600: #57A883;
  --brand-700: #4C9B74;
  --brand-800: #3E8A66;
  --brand-900: #2E6B50;

  --sage-100: #202B24;
  --sage-200: #2A3A2F;
  --sage-300: #38493D;

  --good: #58BF8C;
  --good-bg: #1A2A21;
  --good-border: #2C4535;
  --bad: #E3837A;
  --bad-bg: #2C1E1C;
  --bad-border: #4A2E2A;
  --warn: #D9A34A;
  --warn-text: #E4C083;
  --warn-bg: #2A2317;
  --warn-border: #453A22;
  --info: #7FB3DF;
  --info-bg: #1A2430;
  --info-border: #2A3A4A;

  --shadow-card: 0 1px 2px rgba(0, 0, 0, 0.28);
  --shadow-pop: 0 4px 6px -2px rgba(0, 0, 0, 0.32), 0 12px 28px -8px rgba(0, 0, 0, 0.5);
  --shadow-modal: 0 24px 64px -12px rgba(0, 0, 0, 0.62);

  --chart-grid: #2C332D;
  --chart-tick: #9BA49C;
  --chart-label: #E9F0EA;
  --chart-muted: #79827A;

  --chart-1: #7FC7A3;
  --chart-2: #5CAE86;
  --chart-3: #4C9B74;
  --chart-4: #3E8A66;
  --chart-5: #2C6249;
  --chart-6: #6E9A85;

  --chart-good: #58BF8C;
  --chart-bad: #E3837A;
  --chart-bad-claro: #7A4640;
  --chart-warn: #D9A34A;
  --chart-amber: #D9A34A;

  --chart-fill: rgba(127, 199, 163, 0.14);
  --chart-fill-forte: rgba(92, 174, 134, 0.5);
  --chart-fill-bad: rgba(227, 131, 122, 0.14);
  --chart-fill-suave: rgba(127, 199, 163, 0.08);
  --focus-ring: rgba(111, 184, 148, 0.20);

  /* Icones de traco claro. O SVG e string opaca, entao o token guarda o
     url() inteiro — ver o comentario na definicao do tema claro. */
  --icone-ok: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2358BF8C' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cpath d='M8.5 12.5l2.5 2.5 4.5-5'/%3E%3C/svg%3E");
  --icone-atencao: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23E4C083' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M10.3 3.8 1.8 18a2 2 0 0 0 1.7 3h17a2 2 0 0 0 1.7-3L13.7 3.8a2 2 0 0 0-3.4 0Z'/%3E%3Cpath d='M12 9v4M12 17h.01'/%3E%3C/svg%3E");
  --icone-info: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%237FB3DF' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cpath d='M12 16v-5M12 8h.01'/%3E%3C/svg%3E");
  --icone-vazio: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2379827A' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M22 12h-6l-2 3h-4l-2-3H2'/%3E%3Cpath d='M5.45 5.11 2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.45-6.89A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11z'/%3E%3C/svg%3E");
  --icone-chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none' stroke='%239BA49C' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 8l4 4 4-4'/%3E%3C/svg%3E");
  --icone-chevron-forte: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none' stroke='%23E9F0EA' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 8l4 4 4-4'/%3E%3C/svg%3E");

}

* {
  box-sizing: border-box;
}

/* --------------------------------------------------------------------------
   Rodinha de carregamento
   --------------------------------------------------------------------------
   Aparece no item clicado enquanto a página nova não pinta. Existe porque
   clicar numa aba não dava retorno nenhum até a resposta chegar, e em tela com
   consulta pesada isso é meio segundo parecendo que o clique não pegou — a
   reação natural é clicar de novo.

   Anel de borda em vez de SVG animado: não precisa de marcação nova em lugar
   nenhum, e um `::before`/`::after` posicionado não empurra o texto do item.
   -------------------------------------------------------------------------- */
@keyframes cx-girar {
  to { transform: rotate(360deg); }
}

/* Na sidebar a rodinha entra na faixa de indentação que já existe (os subitens
   têm 40px de padding à esquerda), então ela NÃO desloca o rótulo — item que
   pula de lugar no clique parece defeito, não carregamento. */
.sidebar-subitem.is-carregando {
  background: var(--warm-200);
}

/* `top: 15px` em vez de `50%`: o subitem pode ter duas linhas agora, e centrado
   na altura total a rodinha desceria para o meio do bloco em vez de ficar ao lado
   da PRIMEIRA linha do rótulo. */
.sidebar-subitem.is-carregando::before {
  content: '';
  position: absolute;
  left: 16px;
  top: 14px;
  width: 13px;
  height: 13px;
  border: 1.6px solid var(--warm-400);
  border-top-color: var(--brand-600);
  border-radius: 50%;
  animation: cx-girar 0.6s linear infinite;
}

/* Na aba e na pill de período a rodinha entra depois do texto: ali há espaço
   sobrando à direita e a caixa é inline, então não há faixa livre à esquerda
   para ocupar sem empurrar nada. */
.subabas-item.is-carregando::after,
.periodo-pill.is-carregando::after {
  content: '';
  display: inline-block;
  width: 12px;
  height: 12px;
  margin-left: 8px;
  vertical-align: -2px;
  border: 1.6px solid var(--warm-400);
  border-top-color: var(--brand-600);
  border-radius: 50%;
  animation: cx-girar 0.6s linear infinite;
}

/* Botão de formulário enquanto o envio está em curso (ligado por `layout.js`). Reusa o
   mesmo anel das abas em vez de um indicador próprio: dois jeitos de dizer "ocupado" na
   mesma tela fazem o segundo parecer outra coisa.

   `opacity` além da rodinha porque o botão também fica `disabled`, e um botão desabilitado
   que continua com a aparência de clicável convida ao segundo clique — que é exatamente o
   que este estado existe para evitar. */
.btn.is-enviando {
  opacity: 0.72;
  cursor: progress;
}

.btn.is-enviando::after {
  content: '';
  display: inline-block;
  width: 12px;
  height: 12px;
  margin-left: 8px;
  border: 1.6px solid var(--warm-400);
  border-top-color: var(--brand-600);
  border-radius: 50%;
  animation: cx-girar 0.6s linear infinite;
}

/* No botão primário (fundo verde escuro chapado) o anel morno desaparece — mesma correção
   que a aba ativa precisa, logo abaixo. */
.btn--primario.is-enviando::after,
.filtros-aplicar.is-enviando::after {
  border-color: var(--text-on-dark-muted);
  border-top-color: var(--text-on-dark);
}

/* Na aba ativa (fundo verde escuro) o anel morno desaparece. */
.subabas-item.active.is-carregando::after {
  border-color: rgba(255, 255, 255, 0.32);
  border-top-color: #FFFFFF;
}

/* Respeita quem desligou animação no sistema: a rodinha para de girar e vira um
   anel estático, que ainda comunica "ocupado" sem movimento. */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }

  .sidebar-subitem.is-carregando::before,
  .subabas-item.is-carregando::after,
  .periodo-pill.is-carregando::after {
    animation: none !important;
    border-top-color: var(--brand-600);
  }
}

body {
  margin: 0;
  font-family: 'DM Sans', -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  font-size: 14px;
  line-height: 1.5;
  background: var(--bg-app);
  color: var(--text-primary);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

a {
  color: inherit;
  text-decoration: none;
}

code {
  font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
  font-size: 0.92em;
  background: var(--bg-inset);
  border: 1px solid var(--border-subtle);
  border-radius: 5px;
  padding: 1px 5px;
}

/* Foco visível e na cor da marca em tudo que é focável. O padrão do navegador é
   um anel azul, que é a única cor fora da paleta que aparecia no site. */
:focus-visible {
  outline: 2px solid var(--brand-500);
  outline-offset: 2px;
}

.app-shell {
  display: flex;
  min-height: 100vh;
}

/* ==========================================================================
   Sidebar
   ==========================================================================
   Invertida em relação à versão anterior: era um bloco verde-escuro sólido com
   texto branco; agora é off-white com tinta verde-escura, como no material.

   As páginas da área moram AQUI (grupo colapsável), não numa subnav horizontal.
   É a mudança estrutural que mais aproxima do ecossistema: em Produtos, "onde
   estou" é sempre a sidebar, e aba dentro da tela fica reservada para sub-visão
   do mesmo conteúdo.
   ========================================================================== */
.sidebar {
  width: var(--sidebar-w);
  flex-shrink: 0;
  background: var(--bg-sidebar);
  border-right: 1px solid var(--border-subtle);
  display: flex;
  flex-direction: column;
  padding: 14px 14px 12px;
  transition: width 0.16s ease;
  position: sticky;
  top: 0;
  height: 100vh;
  overflow-y: auto;
  overflow-x: hidden;
  /* Barra de rolagem fina e morna — a padrão do Windows é um cinza-azulado que
     corta o tom bege da coluna inteira. */
  scrollbar-width: thin;
  scrollbar-color: var(--warm-400) transparent;
}

.sidebar::-webkit-scrollbar { width: 8px; }
.sidebar::-webkit-scrollbar-track { background: transparent; }
.sidebar::-webkit-scrollbar-thumb {
  background: var(--warm-400);
  border-radius: var(--radius-pill);
  border: 2px solid var(--bg-sidebar);
}

.sidebar-brand {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 6px 10px 16px;
}

.sidebar-brand-mark {
  color: var(--text-title);
  display: flex;
  align-items: center;
}

/* Logo real da EQI (core/_logo_eqi.html). O SVG usa fill="currentColor", então
   herda a cor do contexto e não precisa de duas versões do arquivo. Altura fixa
   e largura automática: o viewBox é 80x42 e travar a largura distorceria. */
.sidebar-brand-mark .eqi-logo {
  height: 20px;
  width: auto;
  display: block;
}

.topbar-logo .eqi-logo {
  height: 22px;
  width: auto;
  display: block;
}

.sidebar-brand-text {
  display: flex;
  flex-direction: column;
  line-height: 1.25;
  min-width: 0;
}

.sidebar-brand-name {
  font-size: 0.875rem;
  font-weight: 600;
  color: var(--text-title);
  letter-spacing: -0.005em;
}

.sidebar-brand-sub {
  font-size: 0.72rem;
  color: var(--text-secondary);
}

.sidebar-nav {
  display: flex;
  flex-direction: column;
  gap: 2px;
  flex: 1;
}

/* Rótulo de grupo: no material é caixa normal e discreto ("Planejamento"), não
   versalete espaçado. Uppercase somava um segundo nível de ênfase a um elemento
   cuja função é justamente não competir com os itens. */
.sidebar-group-label {
  font-size: 0.75rem;
  font-weight: 500;
  color: var(--text-secondary);
  padding: 12px 10px 6px;
  white-space: nowrap;
}

.sidebar-group-label--muted {
  color: var(--text-tertiary);
}

.sidebar-divider {
  height: 1px;
  background: var(--border-subtle);
  margin: 10px 2px;
  flex-shrink: 0;
}

/* Item simples (Administração, Reportar problema, área em breve) */
.sidebar-item,
.sidebar-link,
.sidebar-area-item {
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 9px 10px;
  border-radius: var(--radius-sm);
  font-size: 0.875rem;
  color: var(--text-title);
  transition: background-color 0.12s ease;
  width: 100%;
  text-align: left;
}

.sidebar-item:hover,
.sidebar-link:hover,
.sidebar-area-item:hover {
  background: var(--warm-200);
}

.sidebar-icon {
  width: 17px;
  height: 17px;
  flex-shrink: 0;
  color: var(--text-title);
  opacity: 0.85;
}

/* Rótulo QUEBRA LINHA em vez de truncar. "Customer Marketi…" e "Estratégia de
   campan…" não dizem para onde o item leva, e no menu da navegação isso é o
   defeito mais caro possível: quem não reconhece o item não clica. Duas linhas
   com entrelinha apertada custam 18px e resolvem. */
.sidebar-label {
  min-width: 0;
  line-height: 1.3;
  overflow-wrap: break-word;
}

/* Recolhida, a coluna tem 68px e o rótulo está escondido — mas o `white-space`
   precisa voltar a `nowrap` para o item não tentar quebrar durante a transição
   de largura e pular de altura. */
.app-shell.sidebar-collapsed .sidebar-label {
  white-space: nowrap;
}

/* Grupo de área — <details>/<summary>, sem JS.
   Escolha deliberada: compartilhar helper de JS entre
   telas quebrou os gráficos em 05/08 com causa nunca identificada, e o menu de
   navegação é o último lugar onde vale gastar risco de JS. `open` vem do
   servidor quando a área é a da URL, então a árvore já chega aberta na página
   certa, sem flash. */
.sidebar-grupo {
  border-radius: var(--radius-sm);
}

.sidebar-grupo-summary {
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 9px 10px;
  border-radius: var(--radius-sm);
  font-size: 0.875rem;
  font-weight: 500;
  color: var(--text-title);
  cursor: pointer;
  list-style: none;
  transition: background-color 0.12s ease;
}

.sidebar-grupo-summary::-webkit-details-marker {
  display: none;
}

.sidebar-grupo-summary:hover {
  background: var(--warm-200);
}

/* Grupo que contém a página atual: o próprio cabeçalho fica marcado, senão a
   área ativa só se distingue rolando até o subitem — e com a árvore de outra
   área também aberta, não se distingue de jeito nenhum. */
.sidebar-grupo--ativo > .sidebar-grupo-summary {
  color: var(--text-title);
  font-weight: 600;
}

.sidebar-chevron {
  width: 14px;
  height: 14px;
  margin-left: auto;
  flex-shrink: 0;
  color: var(--text-secondary);
  transition: transform 0.16s ease;
}

.sidebar-grupo[open] > .sidebar-grupo-summary .sidebar-chevron {
  transform: rotate(90deg);
}

/* Sublista: os subitens do material não têm ícone e ficam indentados na altura
   do rótulo do pai, alinhados entre si. */
.sidebar-sublista {
  display: flex;
  flex-direction: column;
  gap: 1px;
  padding: 2px 0 6px;
}

/* Subitem também quebra em vez de truncar, pelo mesmo motivo do rótulo do grupo.
   `position: relative` fica aqui (e não numa regra solta) porque a rodinha de
   carregamento é um `::before` absoluto ancorado neste elemento. */
.sidebar-subitem {
  display: block;
  position: relative;
  padding: 8px 10px 8px 40px;
  border-radius: var(--radius-sm);
  font-size: 0.85rem;
  line-height: 1.35;
  color: var(--text-primary);
  overflow-wrap: break-word;
  transition: background-color 0.12s ease, color 0.12s ease;
}

.sidebar-subitem:hover {
  background: var(--warm-200);
  color: var(--text-title);
}

.sidebar-subitem.active {
  background: var(--sage-200);
  color: var(--text-title);
  font-weight: 600;
}

/* Área travada ("Em breve") */
.sidebar-item.disabled,
.sidebar-area-item.disabled {
  color: var(--text-tertiary);
  cursor: default;
}

.sidebar-item.disabled:hover,
.sidebar-area-item.disabled:hover {
  background: transparent;
}

.sidebar-item.disabled .sidebar-icon,
.sidebar-area-item.disabled .sidebar-icon {
  color: var(--text-tertiary);
  opacity: 0.7;
}

.sidebar-footer {
  padding-top: 8px;
  margin-top: 8px;
  border-top: 1px solid var(--border-subtle);
  display: flex;
  flex-direction: column;
  gap: 1px;
  flex-shrink: 0;
}

/* Logout é POST porque a LogoutView do Django não aceita GET desde a 5.0 — e
   porque link de logout em GET é disparável por imagem forjada de terceiro. O
   <form> precisa não interferir no layout da coluna. */
.sidebar-form {
  display: contents;
}

.sidebar-item--botao {
  border: none;
  background: none;
  font: inherit;
  cursor: pointer;
}

/* Cartão do usuário: caixa morna com o identificador em duas linhas e o botão
   de tema à direita, como no rodapé da sidebar de referência. */
.sidebar-user {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 8px;
  padding: 9px 10px;
  background: var(--warm-200);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
}

.sidebar-user-info {
  display: flex;
  flex-direction: column;
  min-width: 0;
  flex: 1;
  line-height: 1.3;
}

.sidebar-user-name {
  font-size: 0.8rem;
  font-weight: 500;
  color: var(--text-title);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.sidebar-user-email {
  font-size: 0.72rem;
  color: var(--text-secondary);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Avatar: some no padrão novo (o material não tem), mas a classe fica definida
   para não virar marcação sem estilo se alguém reintroduzir. */
.sidebar-user-avatar {
  display: none;
}

/* --------------------------------------------------------------------------
   Switch de tema — sol / trilha / lua
   --------------------------------------------------------------------------
   `role="switch"` com `aria-checked` no <button>, e não um checkbox escondido:
   o estado é lido por leitor de tela sem precisar de <label> pareado, e o CSS
   se pendura no próprio atributo — então a posição do botão nunca sai de
   sincronia com o estado anunciado, porque os dois leem a mesma fonte.

   Os dois ícones ficam FORA da trilha, como no material: o lado ativo acende e
   o outro fica mudo, então dá para saber qual tema está valendo sem interpretar
   para que lado a bolinha foi.
   -------------------------------------------------------------------------- */
.tema-switch {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-shrink: 0;
  padding: 2px;
  border: none;
  background: none;
  cursor: pointer;
  border-radius: var(--radius-sm);
}

.tema-switch svg {
  width: 13px;
  height: 13px;
  flex-shrink: 0;
  color: var(--text-tertiary);
  transition: color 0.18s ease;
}

/* O ícone do tema VIGENTE acende. */
.tema-switch[aria-checked="false"] .tema-switch-sol,
.tema-switch[aria-checked="true"] .tema-switch-lua {
  color: var(--text-title);
}

.tema-switch-trilha {
  position: relative;
  width: 32px;
  height: 18px;
  flex-shrink: 0;
  border-radius: var(--radius-pill);
  background: var(--warm-300);
  border: 1px solid var(--border-subtle);
  transition: background-color 0.18s ease, border-color 0.18s ease;
}

.tema-switch[aria-checked="true"] .tema-switch-trilha {
  background: var(--brand-900);
  border-color: var(--brand-800);
}

.tema-switch-botao {
  position: absolute;
  top: 1px;
  left: 1px;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: var(--bg-surface);
  box-shadow: 0 1px 2px rgba(16, 53, 42, 0.28);
  transition: transform 0.18s ease, background-color 0.18s ease;
}

/* 14px de deslocamento: 32 (trilha) − 2 (bordas) − 14 (bolinha) − 2 (folga) */
.tema-switch[aria-checked="true"] .tema-switch-botao {
  transform: translateX(14px);
  background: var(--brand-500);
}

.tema-switch:hover .tema-switch-trilha {
  border-color: var(--border-strong);
}

/* Estado recolhido
   --------------------------------------------------------------------------
   Todo o bloco vive dentro de `min-width: 721px` de propósito. No mobile a
   sidebar já vira uma faixa empilhada de largura cheia, e "recolher" ali não
   significa nada — a primeira versão desfazia isso lá embaixo com
   `display: revert`, que é ARMADILHA: `revert` volta ao valor do NAVEGADOR, não
   ao valor anterior da cascata. `.sidebar-brand-text` é `display: flex` aqui,
   e o revert dele daria `inline`, empilhando o nome e o subtítulo na mesma
   linha. Escopar por largura não tem esse problema porque a regra nem existe
   fora da faixa. */
@media (min-width: 721px) {
  .app-shell.sidebar-collapsed .sidebar {
    width: var(--sidebar-w-collapsed);
    padding-left: 10px;
    padding-right: 10px;
  }

  .app-shell.sidebar-collapsed .sidebar-label,
  .app-shell.sidebar-collapsed .sidebar-brand-text,
  .app-shell.sidebar-collapsed .sidebar-group-label,
  .app-shell.sidebar-collapsed .sidebar-area-rotulo,
  .app-shell.sidebar-collapsed .sidebar-area-check,
  .app-shell.sidebar-collapsed .sidebar-chevron,
  .app-shell.sidebar-collapsed .sidebar-sublista,
  .app-shell.sidebar-collapsed .sidebar-divider,
  .app-shell.sidebar-collapsed .sidebar-user-info,
  .app-shell.sidebar-collapsed .tema-switch {
    display: none;
  }

  /* Recolhida, o cartão do usuário viraria uma caixa vazia de 40px. */
  .app-shell.sidebar-collapsed .sidebar-user {
    display: none;
  }

  .app-shell.sidebar-collapsed .sidebar-item,
  .app-shell.sidebar-collapsed .sidebar-link,
  .app-shell.sidebar-collapsed .sidebar-grupo-summary,
  .app-shell.sidebar-collapsed .sidebar-area-item {
    justify-content: center;
    padding-left: 8px;
    padding-right: 8px;
  }
}

/* ==========================================================================
   Área principal, topbar e conteúdo
   ==========================================================================
   A topbar do material não é uma barra: é o cabeçalho da PÁGINA, sem fundo
   próprio e sem borda inferior — botão de recolher à esquerda, título grande
   com subtítulo mudo embaixo, logo da EQI à direita.
   ========================================================================== */
.app-main {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-width: 0;
}

/* Texto só para leitor de tela: fora da tela mas dentro da árvore de
   acessibilidade. `display: none` e `visibility: hidden` o removeriam dela
   também, que é o oposto do objetivo. */
.sr-apenas {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* --------------------------------------------------------------------------
   Cabeçalho fixo ao rolar
   --------------------------------------------------------------------------
   O invólucro é que é `sticky`, não a `.topbar`: a topbar tem largura máxima e
   margem automática (para alinhar com a coluna de conteúdo), e um elemento com
   largura limitada grudado no topo deixaria o conteúdo passando POR TRÁS dele
   nas laterais. O invólucro ocupa a largura toda e carrega o fundo; a topbar
   segue centralizada dentro dele.

   Nas telas longas — o Relatório N3 tem 560 linhas de marcação e a Estratégia
   585 — depois de duas rolagens não havia nada em tela dizendo qual página era.
   A borda inferior só aparece quando há conteúdo passando por baixo
   (`.is-rolado`, do layout.js), senão a linha fica sobrando no topo da página
   parada. */
.topbar-wrap {
  position: sticky;
  top: 0;
  z-index: 30;
  background: var(--bg-app);
  border-bottom: 1px solid transparent;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

.topbar-wrap.is-rolado {
  border-bottom-color: var(--border-subtle);
  box-shadow: 0 4px 12px -8px rgba(16, 53, 42, 0.35);
}


/* TRÊS COLUNAS, e as laterais têm largura IGUAL por construção (`1fr` cada). É isso que
   coloca a pílula de sub-abas no meio EXATO da faixa, e não no meio do vão entre o título e
   as ações — com flex + spacer o centro se deslocava conforme o título mudava de tamanho de
   uma tela para a outra.

   `minmax(0, 1fr)` e não `1fr`: `1fr` sozinho tem mínimo `auto`, então um título longo faria
   a coluna da esquerda crescer além da metade e a simetria iria embora justamente na tela em
   que ela mais aparece.

   SÃO 3 FILHOS DIRETOS PARA 3 COLUNAS. Um quarto filho cai numa segunda linha da grade
      sem erro nenhum — é o tipo de quebra que `check` e HTTP 200 não acusam, e por isso a
      auditoria de HTML conta os filhos contra as colunas.

   `align-items: start` preserva o alinhamento de hoje (botão e ações no topo, junto da
   primeira linha do título); só a pílula se centra, pelo `align-self` dela. */
.topbar {
  flex-shrink: 0;
  display: grid;
  /* `minmax(0, auto)` no meio, não `auto`: `auto` cresce sem limite e esmaga a
     coluna do título — com a 4ª sub-aba, "Estratégia de campanha" passou a quebrar
     em duas linhas. Assim as abas rolam (ver `.topbar-subabas`) e o título fica. */
  grid-template-columns: minmax(0, 1fr) minmax(0, auto) minmax(0, 1fr);
  align-items: start;
  gap: 14px;
  width: 100%;
  max-width: var(--content-max);
  margin: 0 auto;
  padding: 22px 28px 18px;
  background: transparent;
}

/* COLUNA EXPLÍCITA EM CADA GRUPO, e isto não é redundância. Nas 18 telas sem sub-aba o
   filho do meio é `display: none` pelo `:empty` — e um item escondido SAI da grade, então o
   posicionamento automático jogava o grupo da direita na coluna 2 (a `auto`, estreita) e ele
   parava no MEIO da tela, com o vão sobrando à direita. Aconteceu de verdade.

   Com a coluna declarada, a posição de cada grupo deixa de depender de quantos filhos
   existem — que é a única forma de as telas com e sem sub-aba terem o mesmo cabeçalho. */
.topbar-left {
  grid-column: 1;
  display: flex;
  align-items: flex-start;
  gap: 14px;
  min-width: 0;
}

.topbar-right {
  grid-column: 3;
  display: flex;
  align-items: flex-start;
  justify-content: flex-end;
  gap: 14px;
  min-width: 0;
}

/* O BLOCO DAS SUB-ABAS FICA DEPOIS DE `.topbar-left`/`.topbar-right`, e a ORDEM É A
   REGRA, não arrumação. A media query dele reatribui `.topbar-right` para a coluna 2 em
   tela estreita; com a mesma especificidade, quem vence a cascata é a regra MAIS ABAIXO
   no arquivo. Com este bloco acima, o `grid-column: 3` incondicional anulava a
   reatribuição e a grade criava uma terceira coluna implícita, empurrando o logo para
   fora da faixa — só numa janela de largura específica, e sem `check`, HTTP 200 ou a
   auditoria de classes acusarem nada. */
/* Sub-abas NA LINHA DO TÍTULO, dentro da `.topbar` que gruda.

   `:empty` é o que impede um `gap` sobrando nas 18 telas sem sub-aba. A `.topbar` é flex
      com `gap: 14px`, e um filho vazio ainda conta como filho — o vão apareceria entre o
      título e as ações sem nada dentro. Depende de o template não deixar espaço em branco
      dentro do span; está anotado lá também, porque quem reindentar o `base.html` quebra
      isto sem nenhum sintoma além do vão. */
.topbar-subabas {
  /* Rola em vez de empurrar o título. `min-width: 0` é o que permite o
     encolhimento dentro do grid — sem ele o item nunca fica menor que o
     conteúdo e o `minmax(0, auto)` acima não tem efeito. */
  min-width: 0;
  overflow-x: auto;
  scrollbar-width: none;
  grid-column: 2;
  display: flex;
  min-width: 0;
  /* Centraliza contra o bloco do título, em vez de encostar no topo como o
     `align-items: start` da grade faria. */
  align-self: center;
}

/* Em tela estreita as três colunas não cabem: título e ações espremeriam a pílula até ela
   rolar dentro de si mesma. Aí ela desce para uma segunda linha da grade, ocupando a largura
   toda e centralizada — continua no meio, só que sozinha.

   NÃO É O 1024px DAS OUTRAS REGRAS: o ponto de quebra aqui é a soma de título + pílula +
      ações, que estoura ANTES do ponto em que o padding muda. Usar o mesmo número por
      simetria deixaria uma faixa de larguras com as três colunas espremidas.

   SUBIU DE 1120px PARA 1560px EM 20/08/2026, quando a 4ª sub-aba ("Produtos") entrou.
      Medido em captura de tela a 1440px de janela: com 3 abas cabia; com 4, sobravam ~342px
      para o título e "Estratégia de campanha" quebrava em duas linhas. Tentei antes dar
      prioridade à coluna do título (`max-content`) e o efeito foi pior — a 4ª aba ficava
      ESCONDIDA atrás da pílula de status, ou seja um item de navegação que ninguém
      descobre. Descer a faixa de abas para a segunda linha é o comportamento que esta
      media query já foi desenhada para dar; só o número estava velho.

   1440px é a largura de janela mais comum num notebook de trabalho, então o ponto tem de
      ficar ACIMA dela — 1560px deixa margem para a barra de rolagem e para o zoom em 110%. */
@media (max-width: 1560px) {
  .topbar {
    grid-template-columns: minmax(0, 1fr) auto;
  }

  /* A coluna 3 DEIXA DE EXISTIR aqui. Sem reatribuir, o `grid-column: 3` do grupo da
     direita faria a grade criar uma terceira coluna implícita e empurrar o logo para fora
     da faixa — de novo sem erro nenhum, só torto. */
  .topbar-right {
    grid-column: 2;
  }

  .topbar-subabas {
    grid-column: 1 / -1;
    grid-row: 2;
    justify-self: center;
    margin-top: 4px;
  }
}

.topbar-subabas:empty {
  display: none;
}

/* A margem que separava as sub-abas do conteúdo não existe mais: aqui elas estão DENTRO da
   linha do cabeçalho, e margem inferior aumentaria a altura do bloco grudado. */
.topbar-subabas .subabas {
  margin-bottom: 0;
}

/* Versão compacta: na linha do título a pílula divide espaço com o próprio título e com as
   ações, então ela encolhe. Fora do cabeçalho (se algum dia voltar a ter faixa própria) a
   medida original continua valendo. */
.topbar-subabas .subabas-item {
  padding: 6px 12px;
  font-size: 0.8rem;
}

.sidebar-toggle {
  width: 32px;
  height: 32px;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-sm);
  background: var(--bg-surface);
  color: var(--text-secondary);
  cursor: pointer;
  /* Alinha o botão com a primeira linha do título, não com o bloco inteiro:
     com subtítulo presente o bloco tem duas linhas e o botão centralizado
     ficava na altura do subtítulo. */
  margin-top: 4px;
  transition: background-color 0.12s ease, border-color 0.12s ease;
}

.sidebar-toggle svg {
  width: 16px;
  height: 16px;
}

.sidebar-toggle:hover {
  background: var(--bg-inset);
  border-color: var(--border-strong);
  color: var(--text-title);
}

/* A seta vira de lado quando a coluna está recolhida: o botão passa a apontar para
   onde a ação leva. Sem isso o mesmo ícone servia para "recolher" e "expandir", e
   nada na tela dizia qual dos dois o clique ia fazer. O rótulo e o `aria-label`
   trocam junto, no layout.js — ícone girado sem rótulo novo só ajuda quem vê. */
.sidebar-toggle svg {
  transition: transform 0.18s ease;
}

.app-shell.sidebar-collapsed .sidebar-toggle svg {
  transform: rotate(180deg);
}

/* Retorno tátil de clique. 1px é o suficiente para o botão parecer que afundou;
   mais que isso vira animação. */
.btn:active,
.btn-print:active,
.login-btn:active,
.login-sso:active,
.sidebar-toggle:active,
.subabas-item:active,
.toggle-btn:active {
  transform: translateY(1px);
}

.topbar-heading {
  display: flex;
  flex-direction: column;
  min-width: 0;
  gap: 1px;
}

.topbar-title {
  font-weight: 600;
  font-size: 1.6rem;
  line-height: 1.15;
  letter-spacing: -0.02em;
  color: var(--text-title);
}

.topbar-subtitle {
  font-size: 0.85rem;
  color: var(--text-secondary);
}

.topbar-actions {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 4px;
  flex-shrink: 0;
}

.topbar-link {
  font-size: 0.82rem;
  color: var(--text-secondary);
  padding: 6px 10px;
  border-radius: var(--radius-sm);
  white-space: nowrap;
}

.topbar-link:hover {
  background: var(--warm-200);
  color: var(--text-title);
}

.topbar-logo {
  color: var(--text-title);
  display: flex;
  align-items: center;
  margin-top: 2px;
  flex-shrink: 0;
}

.content {
  flex: 1;
  width: 100%;
  max-width: var(--content-max);
  margin: 0 auto;
  padding: 0 28px 40px;
  counter-reset: secao;
}

/* --------------------------------------------------------------------------
   Barra de ferramentas da página (descrição + filtros)
   --------------------------------------------------------------------------
   O que era `.content-header` com sobrescrita, h1 e subtítulo virou só a linha
   de contexto e ação: o título subiu para a topbar, onde o material o coloca.
   Manter os dois lugares imprimia o nome da página duas vezes na mesma tela.
   -------------------------------------------------------------------------- */
.content-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
  gap: 12px;
  margin-bottom: 20px;
  min-height: 36px;
}

.content-header h1 {
  margin: 0 0 2px;
  font-size: 1.15rem;
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--text-title);
}

.content-eyebrow {
  display: block;
  font-size: 0.72rem;
  font-weight: 500;
  color: var(--text-tertiary);
  margin-bottom: 2px;
}

.content-header .subtitle {
  margin: 0;
  color: var(--text-secondary);
  font-size: 0.875rem;
  max-width: 78ch;
}

.content-header-actions {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  position: relative;
}

/* SEMPRE À DIREITA, inclusive quando o bloco desce para a própria linha (24/08/2026).

   O `.content-header` é `space-between` e distribui POR LINHA. Enquanto legenda e ações
   cabem juntas, o `space-between` já joga as ações para a direita; quando a legenda ocupa
   a linha inteira, as ações descem sozinhas e o `space-between` as deixa no COMEÇO. O
   resultado é uma barra que troca de lado conforme o comprimento da legenda e a largura da
   janela — medido: à esquerda em 1440px, à direita em 1180px, na mesma tela.

   `margin-left: auto` resolve porque margem automática consome o espaço livre ANTES de o
   `justify-content` entrar, então vale igual nos dois casos. É modificador e não mudança
   na classe base: as outras telas que usam `.content-header-actions` têm barras curtas que
   nunca descem de linha, e mexer na base para consertar esta arriscaria o layout delas sem
   sintoma nenhum aqui. */
.content-header-actions--fim {
  margin-left: auto;
}

/* Filtros e Período ANDAM JUNTOS quando a barra quebra.

   São o par mais próximo dela — os dois respondem "qual recorte desta tela" — e eram o
   único conteúdo da barra antes de os recortes globais entrarem. Sem este agrupamento a
   quebra caía ENTRE os dois e o Período ficava sozinho numa linha, que foi o que a captura
   em 1180px mostrou. Agrupados, a barra quebra no único lugar que faz sentido: recortes
   numa linha, filtros e período na outra. */
.toolbar-periodo {
  display: flex;
  align-items: center;
  gap: 10px;
}

/* --------------------------------------------------------------------------
   Título de seção
   --------------------------------------------------------------------------
   No material ("Pendências", "Seguindo", "Oportunidades Abertas") é texto
   verde-escuro semibold, sem régua e sem versalete. A linha horizontal que a
   versão anterior desenhava até o fim da tela era o elemento mais pesado da
   página, competindo com os próprios cards.
   -------------------------------------------------------------------------- */
.section-divider {
  display: flex;
  align-items: baseline;
  gap: 10px;
  margin: 30px 0 14px;
}

.section-divider:first-child {
  margin-top: 0;
}

.section-divider span {
  font-size: 1.05rem;
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--text-title);
  white-space: nowrap;
}

/* Numeração da seção, como o "01 HIGHLIGHTS" do N3. Contador em vez de número
   escrito à mão: inserir uma seção no meio renumera sozinho, e número fora de
   ordem num relatório é pior que não ter numeração. */
.section-divider--numerada {
  counter-increment: secao;
}

.section-divider--numerada::before {
  content: counter(secao, decimal-leading-zero);
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--text-tertiary);
  letter-spacing: 0.04em;
}

/* ==========================================================================
   Botões
   ==========================================================================
   Sistema explícito, com as classes antigas mapeadas nele. Antes cada botão
   tinha estilo próprio no lugar onde nasceu: `.filtros-aplicar` era verde
   chapado, `.btn-print` era outlined com raio diferente, `.login-btn` tinha um
   terceiro tom de verde. Três botões primários com três verdes na mesma
   identidade é o sintoma de "recebeu umas cores" que este trabalho corrige.
   ========================================================================== */
.btn,
.filtros-aplicar,
.btn-print,
.login-btn,
.login-sso {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 9px 16px;
  border-radius: var(--radius-sm);
  border: 1px solid transparent;
  font-family: inherit;
  font-size: 0.85rem;
  font-weight: 500;
  line-height: 1.2;
  white-space: nowrap;
  cursor: pointer;
  transition: background-color 0.12s ease, border-color 0.12s ease, color 0.12s ease;
}

.btn svg,
.btn-print svg {
  width: 15px;
  height: 15px;
  flex-shrink: 0;
}

/* Primário — verde escuro chapado ("Gerar Ordem", "+ Nova Oportunidade",
   "Entendi, vamos começar" no material). */
.btn--primario,
.filtros-aplicar,
.login-btn {
  background: var(--brand-700);
  border-color: var(--brand-700);
  color: var(--text-on-dark);
  font-weight: 500;
}

.btn--primario:hover,
.filtros-aplicar:hover,
.login-btn:hover {
  background: var(--brand-800);
  border-color: var(--brand-800);
}

/* Secundário — branco com borda ("Bloqueios", "Dashboard de Assembléias"). */
.btn--secundario,
.btn-print,
.login-sso {
  background: var(--bg-surface);
  border-color: var(--border-subtle);
  color: var(--text-title);
}

.btn--secundario:hover,
.btn-print:hover,
.login-sso:hover {
  background: var(--bg-inset);
  border-color: var(--border-strong);
  color: var(--text-title);
}

/* As três variantes abaixo (`--suave`, `--icone`, `--link`), mais `.campo` e
   `.input`, AINDA NÃO SÃO USADAS por nenhum template. Estão aqui porque são os
   objetos que o material de referência usa e que este painel vai precisar quando
   ganhar tela de operação (formulário, ação em linha de tabela) — e derivar o
   estilo de novo na hora produziria um quarto verde de botão, que é o problema
   que este arquivo acabou de consertar.
   Não são load-bearing: apagar não muda nenhuma tela de hoje. */

/* Suave — sage chapado ("Conferir"). Ação afirmativa que não é a principal
   da tela. */
.btn--suave {
  background: var(--sage-200);
  border-color: var(--sage-200);
  color: var(--text-title);
}

.btn--suave:hover {
  background: var(--sage-300);
  border-color: var(--sage-300);
}

/* Ícone só — quadrado, como os botões de recarregar e limpar do material. */
.btn--icone {
  width: 34px;
  height: 34px;
  padding: 0;
  background: var(--bg-surface);
  border-color: var(--border-subtle);
  color: var(--text-secondary);
}

.btn--icone:hover {
  background: var(--bg-inset);
  border-color: var(--border-strong);
  color: var(--text-title);
}

/* Link — texto verde com seta ("Ver ativos →"). */
.btn--link {
  padding: 4px 2px;
  background: none;
  border-color: transparent;
  color: var(--brand-600);
  font-weight: 500;
}

.btn--link:hover {
  color: var(--brand-800);
  text-decoration: underline;
  text-underline-offset: 3px;
}

.btn:disabled,
.btn-print:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.btn--full {
  width: 100%;
}

/* ==========================================================================
   Campos de formulário
   ==========================================================================
   Altura 38px, raio 8px, borda morna, foco em verde com halo — o mesmo em
   input, select e textarea, para os filtros das telas de dashboard parecerem os
   mesmos controles das telas de operação do material.
   ========================================================================== */
.campo {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.campo-label,
.filtro-campo-label {
  font-size: 0.78rem;
  font-weight: 500;
  color: var(--text-secondary);
}

.campo input,
.campo select,
.campo textarea,
.input,
.filtro-campo select,
.login-field input {
  width: 100%;
  padding: 9px 12px;
  font-family: inherit;
  font-size: 0.875rem;
  color: var(--text-primary);
  background: var(--bg-surface);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-sm);
  transition: border-color 0.12s ease, box-shadow 0.12s ease;
}

.campo input::placeholder,
.input::placeholder,
.campo textarea::placeholder {
  color: var(--text-tertiary);
}

.campo input:focus,
.campo select:focus,
.campo textarea:focus,
.input:focus,
.filtro-campo select:focus,
.login-field input:focus {
  outline: none;
  border-color: var(--brand-500);
  box-shadow: 0 0 0 3px var(--focus-ring);
}

/* Chevron próprio no select: o nativo do Windows é um triângulo cinza-azulado
   com fundo próprio, o único controle da tela que não seguia a paleta. */
.campo select,
.filtro-campo select,
select.input {
  appearance: none;
  -webkit-appearance: none;
  padding-right: 32px;
  background-image: var(--icone-chevron);
  background-repeat: no-repeat;
  background-position: right 9px center;
  background-size: 15px 15px;
  cursor: pointer;
}

/* --------------------------------------------------------------------------
   Pills de filtro (período, filtros, chips)
   --------------------------------------------------------------------------
   No material são botões brancos com borda e chevron, à esquerda da barra, com
   a ação primária à direita. É o mesmo objeto do "Fechamento ⌄" da tela de
   Oportunidades.
   -------------------------------------------------------------------------- */
.periodo-pill,
.filtros-pill {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  height: 36px;
  padding: 0 12px;
  border: 1px solid var(--border-subtle);
  background: var(--bg-surface);
  border-radius: var(--radius-sm);
  font-size: 0.85rem;
  color: var(--text-secondary);
  white-space: nowrap;
  transition: border-color 0.12s ease, background-color 0.12s ease;
}

.periodo-pill svg,
.filtros-pill svg {
  width: 15px;
  height: 15px;
  flex-shrink: 0;
  color: var(--text-secondary);
}

.periodo-pill strong {
  color: var(--text-title);
  font-weight: 600;
}

.periodo-pill--form {
  cursor: pointer;
  gap: 6px;
}

.periodo-pill--form:hover,
.filtros-pill:hover {
  border-color: var(--border-strong);
}

.periodo-pill--form label {
  cursor: pointer;
}

/* O select dentro da pill é o conteúdo dela, não um campo: sem borda, sem
   fundo, herdando a caixa. O chevron vem do próprio select (regra acima), então
   a pill não desenha um segundo. */
.periodo-pill--form select {
  appearance: none;
  -webkit-appearance: none;
  border: none;
  background: transparent;
  font: inherit;
  font-weight: 600;
  color: var(--text-title);
  cursor: pointer;
  padding: 0 20px 0 2px;
  outline: none;
  background-image: var(--icone-chevron-forte);
  background-repeat: no-repeat;
  background-position: right 0 center;
  background-size: 14px 14px;
}

.estrategia-toolbar {
  display: flex;
  align-items: center;
  /* `wrap` porque os recortes globais entraram nesta barra e ela deixou de caber numa
     linha em notebook. Sem ele os botoes seriam espremidos ate ficarem ilegiveis. */
  flex-wrap: wrap;
  /* `flex-END` E NAO `flex-start`, e a diferenca so aparece quando a barra QUEBRA: o
     `.content-header` e `space-between`, entao enquanto tudo cabe numa linha o bloco
     inteiro ja vai para a direita e este valor nao muda nada. Quando quebra, a barra passa
     a ocupar a largura toda — e sem o `flex-end` os controles ficariam colados a esquerda
     enquanto a linha de cima continua alinhada a direita, que foi exatamente o
     desalinhamento que o `width: 100%` do `.toolbar-recortes` produzia. */
  justify-content: flex-end;
  gap: 10px;
}

/* Recortes GLOBAIS na barra de topo (24/08/2026).

   Eles vivem ao lado de Período e Filtros porque são a mesma categoria de decisão: "o que
   alimenta esta tela". Antes ficavam no cabeçalho de cinco painéis, ao lado do seletor
   LOCAL de visão e com peso visual idêntico — e clicar num deles mexia na tela inteira sem
   nada avisando.

   SEM `width: 100%`, e a ausência é a correção: com ele o bloco reivindicava a linha
   inteira e descia sozinho, deixando Filtros e Período na linha de cima. Os três são a
   mesma decisão e ficam na mesma linha; quem cuida do notebook estreito é o `flex-wrap`
   do `.estrategia-toolbar`, que só quebra quando de fato não cabe.

   O rótulo "Recorte" à esquerda diz o que são os botões sem depender de o leitor inferir —
   é o que distingue este grupo do seletor local de visão, que não tem rótulo. */
.toolbar-recortes {
  display: flex;
  align-items: center;
  gap: 8px;
}

/* ALTURA EXPLÍCITA, E SÓ DENTRO DA BARRA. As pilhas de Período e Filtros declaram
   `height: 36px`; o `.seg-group` não declara nada e sai por soma de padding com
   line-height — dá ~35px, e o valor MUDA com a fonte que o navegador conseguiu carregar.
   Três objetos vizinhos com um pixel de diferença é o que se lê como desalinhado sem dar
   para nomear o motivo.

   Escopado à barra de propósito: o mesmo `.seg-group` serve o recorte por produto, que
   vive num cabeçalho de painel ao lado de controles menores e ficaria alto demais lá. */
.toolbar-recortes .seg-group {
  height: 36px;
}

/* A `line-height` EXPLÍCITA é o que faz os 36px acima serem alcançáveis em vez de
   apertados. A conta fecha exata:

       36px = 1px de borda x2  +  3px de padding do grupo x2  +  28px do link
       28px = 5px de padding do link x2  +  18px de line-height

   Sem ela o link herda a `line-height` do corpo (~1,5 de 0,78rem = 18,7px) e a soma dá
   36,7px dentro de uma caixa de 36 — o texto encosta na borda, e o quanto encosta MUDA com
   a fonte que o navegador conseguiu carregar. A DM Sans é servida por nós, mas o fallback
   existe justamente para o caso de ela não chegar. */
.toolbar-recortes .seg-link {
  line-height: 18px;
}

.toolbar-recortes-label {
  font-size: 0.74rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--text-tertiary);
}

.filtros-toggle {
  font: inherit;
  font-size: 0.85rem;
  cursor: pointer;
}

.filtros-toggle:hover,
.filtros-toggle.is-open {
  border-color: var(--brand-500);
  color: var(--text-title);
}

.filtros-badge {
  background: var(--sage-200);
  color: var(--text-title);
  border-radius: var(--radius-pill);
  padding: 1px 8px;
  font-size: 0.72rem;
  font-weight: 600;
}

.filter-chip {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  border: 1px solid var(--border-subtle);
  background: var(--bg-surface);
  border-radius: var(--radius-sm);
  padding: 5px 10px;
  font-size: 0.78rem;
  color: var(--text-secondary);
}

.filter-chip strong {
  color: var(--text-title);
  font-weight: 600;
}

/* Painel flutuante de filtros */
.filtros-panel {
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  z-index: 50;
  width: min(700px, 92vw);
  background: var(--bg-surface);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-pop);
  padding: 18px;
  text-align: left;
}

.filtros-panel-header {
  font-size: 0.95rem;
  font-weight: 600;
  color: var(--text-title);
  margin-bottom: 14px;
}

.filtros-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 14px;
}

@media (max-width: 720px) {
  .filtros-grid { grid-template-columns: 1fr 1fr; }
}

.filtro-campo {
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-width: 0;
}

.filtros-panel-acoes {
  display: flex;
  justify-content: flex-end;
  align-items: center;
  gap: 14px;
  margin-top: 18px;
  padding-top: 14px;
  border-top: 1px solid var(--border-subtle);
}

.filtros-limpar {
  font-size: 0.85rem;
  color: var(--text-secondary);
}

.filtros-limpar:hover {
  color: var(--text-title);
  text-decoration: underline;
  text-underline-offset: 3px;
}

.table-filters {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 12px;
}

.table-filters-label {
  font-size: 0.875rem;
  font-weight: 600;
  color: var(--text-title);
  margin-right: auto;
}

/* ==========================================================================
   Segmented control (abas dentro de card e alternadores de visão)
   ==========================================================================
   Dois formatos no material, e os dois estão aqui:
   · `.subabas`     — recipiente branco com a aba ativa em verde escuro, no nível
                      da PÁGINA ("Início | Ativos | Relatórios" do Follow Up).
   · `.toggle-group`— linha sem recipiente, ativa em branco sobre fundo morno, no
                      nível do PAINEL ("Internas | Quebrando | Recebendo").
   A segunda existe porque vive DENTRO de um card branco, e um segundo recipiente
   branco ali cria caixa dentro de caixa.
   ========================================================================== */
.subabas {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 6px;
  background: var(--bg-surface);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-card);
}

.subabas-item {
  padding: 8px 15px;
  border: none;
  border-radius: var(--radius-sm);
  background: transparent;
  font-family: inherit;
  font-size: 0.85rem;
  font-weight: 500;
  color: var(--text-title);
  cursor: pointer;
  white-space: nowrap;
  transition: background-color 0.12s ease, color 0.12s ease;
}

.subabas-item:hover {
  background: var(--warm-150);
}

.subabas-item.active {
  background: var(--brand-800);
  color: var(--text-on-dark);
}

.subabas-item.active:hover {
  background: var(--brand-900);
}

/* Sub-abas — sub-visões da página atual.
   --------------------------------------------------------------------------
   Ocupa o espaço logo abaixo do título, que antes era a faixa com as 7 páginas
   da área. Aquela faixa saiu porque repetia exatamente a lista da sidebar: dois
   controles com as mesmas opções, e o espaço mais valioso da tela gasto
   repetindo o menu.

   Rolagem interna e não quebra de linha: se um dia uma página tiver muitas
   sub-visões, a pílula rola dentro dela mesma e o corpo da página nunca rola na
   horizontal. */
.subabas {
  display: flex;
  max-width: 100%;
  margin-bottom: 20px;
  overflow-x: auto;
  scrollbar-width: none;
}

.subabas::-webkit-scrollbar { display: none; }

.subabas-item {
  flex-shrink: 0;
  text-decoration: none;
}

.subabas-item.disabled {
  color: var(--text-tertiary);
  cursor: default;
  pointer-events: none;
}

.toggle-group {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  padding: 3px;
  background: var(--bg-inset);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-sm);
}

.toggle-btn {
  border: none;
  background: transparent;
  color: var(--text-secondary);
  font-family: inherit;
  font-size: 0.78rem;
  font-weight: 500;
  padding: 5px 12px;
  border-radius: 6px;
  cursor: pointer;
  white-space: nowrap;
  transition: background-color 0.12s ease, color 0.12s ease;
}

.toggle-btn:hover {
  color: var(--text-title);
}

.toggle-btn.active {
  background: var(--bg-surface);
  color: var(--text-title);
  font-weight: 600;
  box-shadow: var(--shadow-card);
}

/* Seletor que troca o CONJUNTO DE DADOS, não a visão — hoje o recorte jornada ×
   campanha dos painéis de "Desempenho por recorte". São links: a troca acontece no
   servidor, porque o recorte refaz o ranking inteiro.

   Forma idêntica à do `.toggle-group`, de propósito: os dois convivem no mesmo
   cabeçalho, e desenhar um deles diferente sugeriria que fazem coisas de naturezas
   distintas — quando, para quem usa, os dois são "escolha o recorte".

   CLASSE PRÓPRIA E NÃO `.toggle-btn`: o `initToggles` pega TODOS os `.toggle-btn`
      dentro de um `[data-toggle]`, então reaproveitar a classe faria os dois grupos
      disputarem o mesmo estado e clicar em "Jornadas" esconderia o bloco do ranking.
      Nenhum token novo aqui — a diferença para o toggle é só `text-decoration`. */
.seg-group {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  padding: 3px;
  background: var(--bg-inset);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-sm);
}

.seg-link {
  color: var(--text-secondary);
  font-size: 0.78rem;
  font-weight: 500;
  text-decoration: none;
  padding: 5px 12px;
  border-radius: 6px;
  white-space: nowrap;
  transition: background-color 0.12s ease, color 0.12s ease;
}

.seg-link:hover {
  color: var(--text-title);
}

.seg-link.active {
  background: var(--bg-surface);
  color: var(--text-title);
  font-weight: 600;
  box-shadow: var(--shadow-card);
}

/* ==========================================================================
   Cards (painéis)
   ==========================================================================
   Um card é: superfície branca, 1px morno, raio 12, sem faixa colorida. O
   cabeçalho é título verde-escuro semibold e, embaixo, nota muda — o par
   "Direcionamento / Nenhuma métrica disponível no momento" do material.

   `.panel-header--light` era a variante clara; agora TODO cabeçalho é claro e a
   classe sobrevive como apelido sem efeito, para os 48 usos nos templates não
   precisarem de edição.
   ========================================================================== */
.panel {
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  background: var(--bg-surface);
  box-shadow: var(--shadow-card);
  overflow: hidden;
}

.panel-header {
  background: transparent;
  color: var(--text-title);
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  flex-wrap: wrap;
  gap: 6px 12px;
  padding: 16px 18px 0;
  font-size: 0.875rem;
}

/* Apelido histórico — o estilo já é este. Mantido para os templates não
   mudarem; a regra em branco documenta que a diferença deixou de existir. */
.panel-header--light {
  background: transparent;
  color: var(--text-title);
  padding: 16px 18px 0;
}

.panel-header-title {
  font-weight: 600;
  font-size: 0.95rem;
  line-height: 1.35;
  letter-spacing: -0.005em;
  color: var(--text-title);
}

/* Agrupa título + selo num único filho direto do cabeçalho. Necessário porque
   `.panel-header` é `space-between`: com três filhos, o do meio flutua no vão. */
.panel-header-title-row {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  min-width: 0;
}

/* A nota do cabeçalho fica EMBAIXO do título, não na outra ponta da linha.
   --------------------------------------------------------------------------
   `.panel-header` é `space-between`, então a nota — que é irmã do título no DOM —
   ia para a borda direita do card. Num painel largo isso jogava
   "Fonte: Marketing Cloud + Salesforce + Produtos + BTG" a 900px do "ROI de
   produtos" que ela explica, e o par título/legenda deixava de se ler como par.

   No material os dois são sempre uma coluna: título, e a legenda muda logo
   abaixo ("Direcionamento" / "Nenhuma métrica disponível no momento").

   `flex-basis: 100%` força a nota para a própria linha e `order: 3` a mantém
   depois de tudo — assim os controles do cabeçalho (toggle-group, selos)
   continuam na LINHA DO TÍTULO, à direita, que é onde eles devem ficar. */
.panel-header-note {
  color: var(--text-secondary);
  font-size: 0.8rem;
  font-weight: 400;
  line-height: 1.45;
}

/* `>` (filho DIRETO) e não descendente: há cabeçalho em que a nota vive DENTRO do
   `.panel-header-title-row`, ao lado do título (o painel de Highlights da Digital usa
   as duas formas no mesmo cabeçalho). Ali ela é um complemento na mesma linha e
   empurrá-la para baixo separaria o par que o agrupamento existe para juntar. */
.panel-header > .panel-header-note {
  flex: 1 0 100%;
  order: 3;
  margin-top: 1px;
}

.panel-header-chip {
  background: var(--bg-inset);
  border: 1px solid var(--border-subtle);
  color: var(--text-secondary);
  border-radius: var(--radius-pill);
  padding: 2px 9px;
  font-size: 0.74rem;
}

.panel-body {
  padding: 14px 18px 18px;
}

.panel-footer {
  padding: 0 18px 16px;
  font-size: 0.78rem;
  line-height: 1.5;
  color: var(--text-secondary);
}

/* Nota logo abaixo do título, ainda fora do corpo. Alinhada com o padding do
   cabeçalho para formar uma coluna só de texto com ele. */
.panel-subcaption {
  display: block;
  padding: 4px 18px 0;
  font-size: 0.8rem;
  line-height: 1.5;
  color: var(--text-secondary);
}

.panel-subcaption-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 10px;
  margin-bottom: 10px;
}

.panel-subcaption-row .panel-subcaption {
  padding: 0;
}

.panel--wide {
  margin-bottom: 18px;
}

/* Painel de abertura do Relatório N3 e dos Highlights da Digital. Era verde
   chapado com números brancos; virou sage, que é como o material marca faixa de
   destaque (o hero da tela de Operacional). O número segue grande e agora em
   verde-escuro sobre claro — mais legível que branco sobre verde. */
.panel--destaque {
  background: var(--sage-100);
  border-color: var(--sage-300);
}

.panel--destaque .panel-header,
.panel--destaque .panel-header--light {
  color: var(--text-title);
}

.panel--destaque .panel-body {
  background: transparent;
  color: var(--text-title);
}

.panel--destaque .stat-label {
  color: var(--text-secondary);
}

.panel--destaque .stat-value,
.panel--destaque .stat-value--lg {
  color: var(--text-title);
}

.panel--destaque .panel-header-note {
  color: var(--text-secondary);
}

/* Divisória entre os números. `:not(:first-child)` em vez de borda à direita
   para não sobrar um traço solto no fim da linha quando ela quebra. */
.panel--destaque .n3-kpi:not(:first-child) {
  border-left: 1px solid var(--sage-300);
  padding-left: 28px;
}

/* Chart.js com maintainAspectRatio:false precisa de um contêiner com altura
   explícita — sem isso o canvas cresce sem parar (canvas herda a altura do pai,
   pai herda a altura do canvas). Todo <canvas> deve ficar dentro disto. */
.chart-box {
  position: relative;
  width: 100%;
}

/* --------------------------------------------------------------------------
   Grades de painéis
   -------------------------------------------------------------------------- */
.panel-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: 16px;
}

/* Grids de 3 e 4 cards de KPI das telas da EQI Digital. Colunas fixas (não
   `auto-fit`) para o número de cards ser o que o painel decidiu, e colapso
   explícito no mobile. */
.panel-grid--3col { grid-template-columns: repeat(3, minmax(0, 1fr)); margin-bottom: 18px; }
.panel-grid--4col { grid-template-columns: repeat(4, minmax(0, 1fr)); margin-bottom: 18px; }

@media (max-width: 1100px) {
  .panel-grid--4col { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 780px) {
  .panel-grid--3col,
  .panel-grid--4col { grid-template-columns: 1fr; }
}

.panel-grid--2col {
  grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
  margin-bottom: 18px;
}

/* Painel ímpar sozinho na última linha ocupa as duas colunas. Sem isto ele fica
   em MEIA largura com um vão vazio do lado. A regra depende da posição, não da
   quantidade, então continua correta quando um painel não renderiza. */
.panel-grid--2col > .panel:last-child:nth-child(odd) {
  grid-column: 1 / -1;
}

/* Painel de MEIA largura, com um filho só. Não serve usar `--2col`: ele é
   `auto-fit`, que colapsa a coluna vazia e devolve o filho único à largura
   cheia. Aqui as duas colunas são explícitas. `minmax(0, 1fr)` e não
   `minmax(320px, ...)`: com 320px fixo as duas exigiriam 640px e estourariam a
   tela estreita. */
.panel-grid--metade {
  grid-template-columns: repeat(2, minmax(0, 1fr));
  margin-bottom: 18px;
}
@media (max-width: 900px) {
  .panel-grid--metade { grid-template-columns: 1fr; }
}

/* Grade dos gráficos mês a mês: 2 por linha (1 no mobile), sem auto-fit —
   evita espremer os 5 numa linha só em telas largas. */
.mensal-grid {
  grid-template-columns: repeat(2, minmax(0, 1fr));
  margin-bottom: 18px;
}
@media (max-width: 760px) {
  .mensal-grid { grid-template-columns: 1fr; }
}

/* ==========================================================================
   KPIs e blocos de número
   ========================================================================== */
.stat-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
  gap: 14px;
  margin-bottom: 18px;
}

.stat-box,
.engajamento-card,
.lead-time-card {
  background: var(--bg-surface);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-card);
  padding: 14px 16px;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

/* Cards dentro de um painel não repetem a sombra do painel — caixa com sombra
   dentro de caixa com sombra é o que faz uma tela parecer empilhada. */
.panel-body .stat-box,
.panel-body .engajamento-card,
.panel-body .lead-time-card {
  box-shadow: none;
}

.stat-label {
  font-size: 0.8rem;
  color: var(--text-secondary);
}

.stat-value {
  font-size: 1.35rem;
  font-weight: 600;
  letter-spacing: -0.02em;
  color: var(--text-title);
  font-variant-numeric: tabular-nums;
}

.stat-value--lg {
  font-size: 1.75rem;
  font-weight: 600;
  letter-spacing: -0.025em;
  color: var(--text-title);
  font-variant-numeric: tabular-nums;
}

.stat-delta {
  font-size: 0.78rem;
  font-weight: 500;
}

.stat-delta.delta-bom { color: var(--good); }
.stat-delta.delta-mau { color: var(--bad); }

/* Janela do card acumulado ("acumulado jan-ago/26"), logo abaixo do valor.

   NAO E `.stat-delta` SEM COR: o delta e uma COMPARACAO e o periodo e uma legenda do
   proprio numero. Reusar a classe faria a proxima pessoa procurar delta-bom/delta-mau
   aqui e concluir que faltou pintar. Tom secundario porque ela qualifica o valor, nao
   compete com ele. */
.stat-periodo {
  font-size: 0.74rem;
  color: var(--text-secondary);
  font-variant-numeric: tabular-nums;
}

.stat-delta-pill {
  display: inline-block;
  border-radius: var(--radius-pill);
  padding: 3px 10px;
  font-size: 0.76rem;
  font-weight: 500;
}

.stat-delta-pill.delta-bom { background: var(--good-bg); color: var(--good); }
.stat-delta-pill.delta-mau { background: var(--bad-bg); color: var(--bad); }

.stat-pair {
  display: flex;
  gap: 28px;
  margin-top: 14px;
  padding-top: 12px;
  border-top: 1px solid var(--border-subtle);
}

/* ROI de produtos */
/* `.roi-produtos-body`, `.roi-produtos-stats` e `.roi-stat-block` SAÍRAM em 19/08/2026.
   Os KPIs de ROI passaram a usar o `engajamento-card`, que é o mesmo componente do painel
   de Engajamento e já traz caixa, hover, foco e o caret — três regras a menos para manter
   em sincronia com aquele. O que sobrou aqui é só o que é específico deste painel. */

.roi-custo-caption {
  font-size: 0.78rem;
  color: var(--text-secondary);
}

/* A tabela agora fica EMBAIXO dos KPIs, em largura cheia — o `flex: 1` de quando ela dividia
   a linha com a coluna de KPIs não tem mais função, e o `min-width` de 320px só serviria
   para forçar rolagem horizontal em tela estreita. Quem rola é o `.table-scroll` de dentro. */
.roi-produtos-table-wrap {
  min-width: 0;
}

/* Saúde da base: 3 KPIs no topo */
.saude-stats {
  display: flex;
  flex-wrap: wrap;
  gap: 40px;
  margin-bottom: 20px;
}

.saude-stat {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.saude-stat-top {
  display: flex;
  align-items: baseline;
  gap: 8px;
}

.saude-stat-valor {
  font-size: 1.9rem;
  font-weight: 600;
  letter-spacing: -0.025em;
  color: var(--text-title);
  line-height: 1.05;
  font-variant-numeric: tabular-nums;
}

.saude-stat-delta {
  font-size: 0.8rem;
  font-weight: 500;
}

.saude-stat-label {
  font-size: 0.85rem;
  color: var(--text-secondary);
}

/* KPIs de status da aba Projetos */
.projeto-kpis {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 14px;
  margin-bottom: 20px;
}

@media (max-width: 860px) { .projeto-kpis { grid-template-columns: repeat(2, 1fr); } }

.projeto-kpi {
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  background: var(--bg-surface);
  box-shadow: var(--shadow-card);
  padding: 18px 16px;
  display: flex;
  flex-direction: column;
  gap: 4px;
  align-items: center;
  text-align: center;
}

/* O total era o único bloco verde chapado da tela. Sage mantém a ênfase sem
   reintroduzir a faixa escura que saiu de todo o resto do site. */
.projeto-kpi--total {
  background: var(--sage-100);
  border-color: var(--sage-300);
}

.projeto-kpi-valor {
  font-size: 2rem;
  font-weight: 600;
  letter-spacing: -0.03em;
  color: var(--text-title);
  line-height: 1.05;
  font-variant-numeric: tabular-nums;
}

.projeto-kpi--total .projeto-kpi-valor { color: var(--text-title); }

.projeto-kpi-label {
  font-size: 0.78rem;
  color: var(--text-secondary);
}

.projeto-kpi--total .projeto-kpi-label { color: var(--text-secondary); }

/* Engajamento de e-mail */
.engajamento-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
  gap: 14px;
}

.engajamento-card--alerta {
  background: var(--bad-bg);
  border-color: var(--bad-border);
}

.engajamento-card-header {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 8px;
}

.engajamento-card-title {
  font-size: 0.85rem;
  font-weight: 500;
  color: var(--text-title);
}

.engajamento-card-value {
  font-size: 1.2rem;
  font-weight: 600;
  letter-spacing: -0.02em;
  color: var(--text-title);
  font-variant-numeric: tabular-nums;
}

.engajamento-card-caption {
  font-size: 0.74rem;
  line-height: 1.45;
  color: var(--text-secondary);
}

.engajamento-card-caret {
  display: inline-block;
  font-size: 0.7rem;
  color: var(--text-secondary);
  transition: transform 0.16s ease;
}

.engajamento-card.is-open .engajamento-card-caret {
  transform: rotate(180deg);
}

/* Padrão reutilizável de CARD INTERATIVO (clicável que revela/alterna algo).
   Aplicar `card-interativo` no card; o JS marca `is-open` quando ativo. */
.card-interativo {
  cursor: pointer;
  transition: border-color 0.12s ease, background-color 0.12s ease, box-shadow 0.12s ease;
}

.card-interativo:hover {
  border-color: var(--brand-300);
  background-color: var(--warm-50);
}

.card-interativo:focus-visible {
  outline: 2px solid var(--brand-500);
  outline-offset: 1px;
}

/* Estado ATIVO: sage, a mesma cor de "selecionado" da sidebar e das abas. */
.card-interativo.is-open {
  border-color: var(--sage-300);
  background-color: var(--sage-100);
}

/* Lead times / linhas de KPI dentro de painel */
.lead-time-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 12px;
}

/* Variante para linha com POUCOS cards (2 ou 3). `.lead-time-row` usa auto-fit
   com 1fr, então com 2 cards cada um estica para meia tela e o painel fica com
   dois retângulos gigantes e vazios. O teto de largura impede o esticamento e o
   justify-content alinha à esquerda em vez de distribuir. */
.lead-time-row--compacta {
  grid-template-columns: repeat(auto-fit, minmax(190px, 260px));
  justify-content: start;
}

.lead-time-card--mau {
  background: var(--bad-bg);
  border-color: var(--bad-border);
}

.combo-headline,
.ctor-headline {
  display: flex;
  align-items: baseline;
  gap: 10px;
  margin: 4px 0 10px;
}

/* ==========================================================================
   Tabelas
   ==========================================================================
   Cabeçalho claro sobre fundo morno, rótulo mudo, sem versalete e sem zebra —
   a zebra e o `<th>` verde-escuro somavam dois padrões de listra a uma tela que
   no material é limpa. A separação vem de hairline por linha e realce no hover.
   ========================================================================== */
.data-table,
.matriz-tabela {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.85rem;
}

.data-table th,
.matriz-tabela thead th {
  position: sticky;
  top: 0;
  z-index: 1;
  background: var(--bg-inset);
  text-align: left;
  font-size: 0.76rem;
  font-weight: 600;
  color: var(--text-secondary);
  padding: 10px 12px;
  white-space: nowrap;
  border-bottom: 1px solid var(--border-subtle);
}

.data-table td,
.matriz-tabela td {
  padding: 10px 12px;
  border-bottom: 1px solid var(--warm-200);
  color: var(--text-primary);
  vertical-align: middle;
}

.data-table tbody tr:last-child td,
.matriz-tabela tbody tr:last-child td {
  border-bottom: none;
}

.data-table tbody tr,
.matriz-tabela tbody tr {
  transition: background-color 0.1s ease;
}

.data-table tbody tr:hover td,
.matriz-tabela tbody tr:hover td,
.matriz-tabela tbody tr:hover th.matriz-indicador {
  background: var(--warm-50);
}

/* Variante com valores centralizados (1ª coluna fica à esquerda) */
.data-table--centro th:not(:first-child),
.data-table--centro td:not(:first-child) {
  text-align: center;
}

/* Coluna numérica. A classe já era usada em 10 lugares nos templates e NÃO
   existia no CSS — número ficava alinhado à esquerda como texto, então dígito
   de milhar não batia com dígito de milhar na coluna. */
.data-table th.num,
.data-table td.num,
.num {
  text-align: right;
  font-variant-numeric: tabular-nums;
}

/* Rolagem horizontal por tabela. `.tablewrap` também era classe fantasma nos
   templates da EQI Digital, com o overflow escrito em `style=` inline. */
.matriz-scroll,
.tablewrap,
.n3-tabela-wrap {
  overflow-x: auto;
  scrollbar-width: thin;
  scrollbar-color: var(--warm-400) transparent;
}

.matriz-scroll::-webkit-scrollbar,
.tablewrap::-webkit-scrollbar,
.n3-tabela-wrap::-webkit-scrollbar,
.table-scroll::-webkit-scrollbar {
  height: 9px;
  width: 9px;
}

.matriz-scroll::-webkit-scrollbar-track,
.tablewrap::-webkit-scrollbar-track,
.n3-tabela-wrap::-webkit-scrollbar-track,
.table-scroll::-webkit-scrollbar-track {
  background: var(--warm-200);
  border-radius: var(--radius-pill);
}

.matriz-scroll::-webkit-scrollbar-thumb,
.tablewrap::-webkit-scrollbar-thumb,
.n3-tabela-wrap::-webkit-scrollbar-thumb,
.table-scroll::-webkit-scrollbar-thumb {
  background: var(--warm-400);
  border-radius: var(--radius-pill);
}

/* --------------------------------------------------------------------------
   Botão de copiar tabela
   --------------------------------------------------------------------------
   A caixa e o botão são criados pelo layout.js — são 31 tabelas em 12 arquivos,
   e escrever a marcação em cada uma deixaria a que fosse esquecida sem o botão,
   sem nenhum aviso.

   Só aparece no hover/foco da tabela: um botão permanente em 31 tabelas viraria
   ruído numa tela que é para ser lida, não operada.
   -------------------------------------------------------------------------- */
.tabela-caixa {
  position: relative;
}

.tabela-copiar {
  position: absolute;
  top: 5px;
  right: 5px;
  /* Acima do `th` grudado no topo (que tem z-index 1) — senão o cabeçalho da
     tabela passa por cima do botão ao rolar. */
  z-index: 4;
  padding: 3px 9px;
  border: 1px solid var(--border-subtle);
  border-radius: 6px;
  background: var(--bg-surface);
  color: var(--text-secondary);
  font-family: inherit;
  font-size: 0.72rem;
  font-weight: 500;
  line-height: 1.5;
  cursor: pointer;
  opacity: 0;
  transition: opacity 0.14s ease, border-color 0.14s ease, color 0.14s ease;
}

/* `:focus-within` junto do hover: quem navega por teclado precisa alcançar o
   botão, e com `opacity: 0` ele existe mas não é visível ao receber o foco. */
.tabela-caixa:hover .tabela-copiar,
.tabela-caixa:focus-within .tabela-copiar {
  opacity: 1;
}

.tabela-copiar:hover {
  border-color: var(--border-strong);
  color: var(--text-title);
}

.tabela-copiar.is-feito {
  opacity: 1;
  border-color: var(--good-border);
  background: var(--good-bg);
  color: var(--good);
}

/* Na impressão o botão não existe — o Relatório N3 vai impresso para a reunião. */
/* --- KPIs de produto (bignumbers da sub-aba Produtos, 20/08/2026) ------------------ */
/* ZERO TOKEN NOVO E ZERO COR LITERAL. A regra que sustenta o tema escuro é "nenhuma
   cor solta fora de :root" — token novo teria de ser declarado em três lugares (:root,
   a media query e o seletor de atributo), e esquecer um dos dois blocos escuros produz
   divergência que só aparece na máquina de quem tem o sistema em escuro.

   Componente próprio e não `stat-box`/`engajamento-card` porque estes dois são
      CLICÁVEIS (abrem o painel mês a mês) e carregam sparkline. Estes três não têm série
      mensal — são o total do período filtrado. Reusar o card interativo prometeria um
      clique que não existe, que é o defeito que o card de tendência já documenta. */
.produtos-kpis {
  display: grid;
  /* auto-fit e não auto-fill: são exatamente três e devem ocupar a largura. */
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
  gap: 12px;
  margin-bottom: 16px;
}

.produtos-kpi {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 14px 16px;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--surface);
}

.produtos-kpi--destaque { border-color: var(--brand); }

.produtos-kpi-valor {
  font-size: 1.5rem;
  font-weight: 700;
  color: var(--text-title);
  line-height: 1.15;
  /* Número longo (R$ 95.249.267,97) não pode estourar o card nem cortar. */
  overflow-wrap: anywhere;
}

.produtos-kpi--destaque .produtos-kpi-valor { color: var(--brand); }

.produtos-kpi-label {
  font-size: 0.8125rem;
  font-weight: 600;
  color: var(--text-primary);
}

.produtos-kpi-nota {
  font-size: 0.75rem;
  color: var(--text-secondary);
}

@media print {
  .tabela-copiar { display: none !important; }
}

.table-scroll {
  max-height: 280px;
  overflow-y: auto;
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-sm);
  scrollbar-width: thin;
  scrollbar-color: var(--warm-400) transparent;
}

/* Matriz Resultado × Objetivo */
.matriz-tabela {
  min-width: 620px;
}

.matriz-tabela thead th {
  text-align: center;
}

.matriz-tabela td {
  text-align: center;
  white-space: nowrap;
}

/* 1ª coluna (nome do indicador) fixa à esquerda */
.matriz-tabela th.matriz-indicador {
  position: sticky;
  left: 0;
  z-index: 2;
  text-align: left;
  font-weight: 500;
  font-size: 0.85rem;
  padding: 10px 14px;
  background: var(--bg-surface);
  color: var(--text-primary);
  border-bottom: 1px solid var(--warm-200);
}

.matriz-tabela thead th.matriz-indicador {
  z-index: 3;
  background: var(--bg-inset);
  color: var(--text-secondary);
  font-size: 0.76rem;
  font-weight: 600;
  border-bottom: 1px solid var(--border-subtle);
}

/* Linhas ainda sem fonte de dado: mudo + itálico */
.matriz-linha--pendente td,
.matriz-linha--pendente th.matriz-indicador {
  color: var(--text-tertiary);
  font-style: italic;
}

.text-mau { color: var(--bad); font-weight: 500; }
.text-bom { color: var(--good); font-weight: 500; }

/* ==========================================================================
   Selos e pills de estado
   ========================================================================== */
.badge {
  display: inline-flex;
  align-items: center;
  border-radius: var(--radius-pill);
  padding: 2px 9px;
  font-size: 0.7rem;
  font-weight: 600;
  line-height: 1.6;
  white-space: nowrap;
  border: 1px solid transparent;
}

.badge--ok,
.badge--real {
  background: var(--good-bg);
  color: var(--good);
  border-color: var(--good-border);
}

.badge--alerta {
  background: var(--bad-bg);
  color: var(--bad);
  border-color: var(--bad-border);
}

.badge--ficticio {
  background: var(--warn-bg);
  color: var(--warn-text);
  border-color: var(--warn-border);
}

/* Painel que mistura fonte real com placeholder. Cor própria (azul, fora da
   escala verde/âmbar) porque não é um meio-termo de severidade: é uma categoria
   diferente, e o leitor precisa notar que tem que olhar quais colunas são
   quais. */
.badge--parcial {
  background: var(--info-bg);
  color: var(--info);
  border-color: var(--info-border);
  cursor: help;
}

.status-pill,
.n3-status {
  display: inline-block;
  padding: 2px 10px;
  border-radius: var(--radius-pill);
  font-size: 0.74rem;
  font-weight: 500;
  white-space: nowrap;
  border: 1px solid transparent;
}

.status-pill--concluido,
.n3-status--concluido { background: var(--good-bg); color: var(--good); border-color: var(--good-border); }
.status-pill--em_andamento { background: var(--sage-200); color: var(--text-title); border-color: var(--sage-300); }
.n3-status--em_andamento { background: var(--sage-200); color: var(--text-title); border-color: var(--sage-300); }
.status-pill--parado,
.n3-status--parado { background: var(--warn-bg); color: var(--warn-text); border-color: var(--warn-border); }
.status-pill--cancelado,
.n3-status--cancelado { background: var(--bad-bg); color: var(--bad); border-color: var(--bad-border); }

.empty-tag {
  background: var(--sage-200);
  color: var(--text-title);
  border-radius: var(--radius-pill);
  padding: 3px 12px;
  font-size: 0.74rem;
  font-weight: 500;
}

/* ==========================================================================
   Avisos e estados vazios
   ==========================================================================
   Este é o componente do modal de referência ("Escolha um lugar de cada vez"):
   caixa morna sem borda gritante, ícone à esquerda, título em negrito e corpo
   mudo abaixo. Um estado vazio é RESPOSTA, não falha — por isso ele tem a forma
   de uma afirmação, e não de um vão onde algo deveria estar.

   `background-color`, NUNCA o atalho `background`, nas regras que carregam
   ícone. O atalho reseta `background-repeat`, `-position` e `-size` para os
   valores iniciais, e como as variantes vêm depois na cascata, o atalho apagava
   os longhands: o ícone voltava a `repeat` em tamanho automático e virava uma
   FILEIRA de triângulos atravessando o painel, por cima do texto.
   ========================================================================== */
.aviso,
.panel-vazio {
  color: var(--text-primary);
  font-size: 0.85rem;
  line-height: 1.55;
  margin: 4px 0 0;
  padding: 14px 16px 14px 44px;
  border-radius: var(--radius-md);
  border: 1px solid var(--sage-300);
  background-color: var(--sage-100);
  background-image: var(--icone-ok);
  background-repeat: no-repeat;
  background-position: 16px 15px;
  background-size: 17px 17px;
}

/* Variante para quando o vazio É um problema (falta fonte, falta configuração)
   — mesma caixa, cor e ícone de atenção, para não dar sinal verde a algo que
   precisa de ação. */
.aviso--atencao,
.panel-vazio--atencao {
  background-color: var(--warn-bg);
  border-color: var(--warn-border);
  color: var(--warn-text);
  background-image: var(--icone-atencao);
}

/* Variante informativa (neutra): explica sem afirmar que está tudo bem nem que
   há problema. É a forma certa para os blocos de instrução do BI CMKT. */
.aviso--info {
  background-color: var(--info-bg);
  border-color: var(--info-border);
  color: var(--text-primary);
  background-image: var(--icone-info);
}

/* Dentro do aviso os parágrafos não ganham margem própria: quando há mais de um
   (título + explicação), as margens dobravam e a caixa ficava desproporcional. */
.aviso p,
.panel-vazio p { margin: 0 0 6px; }
.aviso p:last-child,
.panel-vazio p:last-child { margin-bottom: 0; }

.aviso strong,
.panel-vazio strong {
  color: inherit;
  font-weight: 600;
}

.aviso ol,
.aviso ul,
.panel-vazio ol,
.panel-vazio ul {
  margin: 6px 0 0;
  padding-left: 20px;
}

.aviso li,
.panel-vazio li { margin-bottom: 4px; }

/* Estado vazio centralizado, com borda TRACEJADA — a forma que o material usa
   nas colunas do kanban ("Sem oportunidades") e nos blocos do Follow Up. O
   tracejado diz "aqui cabe conteúdo e não há", que é diferente do que uma caixa
   sólida diz. O ícone entra por `background-image` para não exigir marcação
   nova nos lugares que já usam a classe. */
.panel-body--empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 52px 20px 28px;
  margin: 0;
  color: var(--text-secondary);
  text-align: center;
  font-size: 0.875rem;
  background-color: var(--bg-inset);
  border: 1px dashed var(--border-strong);
  border-radius: var(--radius-md);
  background-image: var(--icone-vazio);
  background-repeat: no-repeat;
  background-position: center 20px;
  background-size: 26px 26px;
}

.panel-body--empty p { margin: 0; }

/* O painel vazio recebe o estado dentro do corpo, então o corpo não pode ter
   padding próprio nem borda de card duplicada. */
.panel--empty .panel-body--empty {
  margin: 0 18px 18px;
}

/* Alertas do mês — cartões de severidade. Mesma linguagem do aviso: caixa
   morna, título negrito, corpo mudo. */
.alerts-section {
  margin-top: 26px;
}

.alerts-title {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  font-size: 1.05rem;
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--text-title);
  margin: 0 0 14px;
}

.alerts-periodo {
  font-size: 0.85rem;
  font-weight: 400;
  color: var(--text-secondary);
}

.alerts-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
  gap: 14px;
}

.alert-card {
  border-radius: var(--radius-md);
  padding: 14px 16px;
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-size: 0.82rem;
  line-height: 1.5;
  border: 1px solid transparent;
}

.alert-card strong {
  font-size: 0.875rem;
  font-weight: 600;
  color: var(--text-title);
}

.alert-card span {
  color: var(--text-secondary);
}

.alert-card--critico,
.alert-card--alta {
  background: var(--bad-bg);
  border-color: var(--bad-border);
}

.alert-card--critico strong,
.alert-card--alta strong {
  color: var(--bad);
}

.alert-card--atencao {
  background: var(--warn-bg);
  border-color: var(--warn-border);
}

.alert-card--atencao strong {
  color: var(--warn-text);
}

/* ==========================================================================
   Indicador de frescor dos dados (topbar)
   ==========================================================================
   Estado vem de FonteDados.situacao no model; aqui é só a forma. O ponto de cor
   nunca aparece sozinho: sempre acompanha texto ("falhou há 2 horas", "sem
   integração"), para não depender de percepção de cor.
   ========================================================================== */
.frescor {
  position: relative;
}

.frescor-resumo {
  display: flex;
  align-items: center;
  gap: 8px;
  height: 32px;
  padding: 0 11px;
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-sm);
  background: var(--bg-surface);
  font-size: 0.8rem;
  color: var(--text-secondary);
  cursor: pointer;
  list-style: none;
  white-space: nowrap;
}

.frescor-resumo::-webkit-details-marker {
  display: none;
}

.frescor-resumo:hover {
  background: var(--bg-inset);
  border-color: var(--border-strong);
  color: var(--text-title);
}

.frescor[open] .frescor-resumo {
  background: var(--bg-inset);
  border-color: var(--brand-300);
  color: var(--text-title);
}

.frescor-caret {
  width: 12px;
  height: 12px;
  transition: transform 0.16s ease;
}

.frescor[open] .frescor-caret {
  transform: rotate(180deg);
}

.frescor-dot {
  width: 7px;
  height: 7px;
  border-radius: var(--radius-pill);
  flex-shrink: 0;
  background: var(--text-tertiary);
}

.frescor-dot--ok { background: var(--good); }
.frescor-dot--atrasada { background: var(--warn); }
.frescor-dot--erro { background: var(--bad); }
.frescor-dot--rodando { background: var(--brand-400); }
.frescor-dot--nao_configurada { background: var(--warm-400); }

.frescor-painel {
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  z-index: 40;
  width: 350px;
  padding: 14px 16px 12px;
  background: var(--bg-surface);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-pop);
}

.frescor-painel-titulo {
  font-size: 0.78rem;
  font-weight: 600;
  color: var(--text-title);
  margin-bottom: 10px;
}

.frescor-lista {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.frescor-item {
  display: grid;
  grid-template-columns: 7px auto 1fr auto;
  grid-template-areas:
    "dot nome pontilhado valor"
    ".   nota nota        nota";
  align-items: center;
  gap: 0 8px;
  font-size: 0.82rem;
}

.frescor-item .frescor-dot { grid-area: dot; }

.frescor-nome {
  grid-area: nome;
  color: var(--text-title);
  font-weight: 500;
}

.frescor-pontilhado {
  grid-area: pontilhado;
  border-bottom: 1px dotted var(--border-strong);
  transform: translateY(-2px);
}

.frescor-valor {
  grid-area: valor;
  color: var(--text-primary);
  font-variant-numeric: tabular-nums;
}

.frescor-nota {
  grid-area: nota;
  font-size: 0.72rem;
  color: var(--text-secondary);
  margin-top: 1px;
}

.frescor-painel-rodape {
  margin-top: 12px;
  padding-top: 10px;
  border-top: 1px solid var(--border-subtle);
  font-size: 0.72rem;
  line-height: 1.5;
  color: var(--text-secondary);
}

@media (max-width: 860px) {
  .frescor-resumo-texto { display: none; }
  .frescor-painel { width: min(330px, calc(100vw - 32px)); }
}

/* ==========================================================================
   Funis
   ========================================================================== */
/* Funil comercial: barra horizontal, largura proporcional ao valor. NÃO usa
   forma de funil de propósito: afunilar carrega implicação de sequência estrita,
   e os três desfechos (ganhas / em andamento / perdidas) são paralelos e
   excludentes, não etapas. */
.funilc-secao {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

/* Espaço + linha separam as duas seções: progressão é sequência, desfecho não. */
.funilc-secao--desfecho {
  margin-top: 24px;
  padding-top: 20px;
  border-top: 1px dashed var(--border-strong);
}

.funilc-secao-titulo {
  display: flex;
  align-items: baseline;
  gap: 10px;
  font-size: 0.875rem;
  font-weight: 600;
  color: var(--text-title);
  margin-bottom: 6px;
}

.funilc-secao-base {
  font-size: 0.78rem;
  font-weight: 400;
  color: var(--text-secondary);
}

.funilc-linha {
  display: grid;
  grid-template-columns: 120px 1fr 64px 48px;
  align-items: center;
  gap: 10px;
}

.funilc-rotulo {
  font-size: 0.85rem;
  color: var(--text-primary);
}

.funilc-trilha {
  background: var(--warm-200);
  border-radius: var(--radius-sm);
  height: 22px;
  overflow: hidden;
}

.funilc-barra {
  height: 100%;
  border-radius: var(--radius-sm);
  transition: width 0.2s ease;
}

/* Progressão em tom de marca; desfecho em cor semântica (bom / neutro / ruim). */
.funilc-barra--geradas { background: var(--brand-700); }
.funilc-barra--qualificadas { background: var(--brand-500); }
.funilc-barra--ganhas { background: var(--good); }
.funilc-barra--andamento { background: var(--brand-300); }
.funilc-barra--perdidas { background: var(--bad); }

.funilc-valor {
  font-size: 0.875rem;
  font-weight: 600;
  text-align: right;
  color: var(--text-title);
  font-variant-numeric: tabular-nums;
}

.funilc-pct {
  font-size: 0.8rem;
  color: var(--text-secondary);
  text-align: right;
  font-variant-numeric: tabular-nums;
}

.funilc-nota {
  font-size: 0.78rem;
  line-height: 1.5;
  color: var(--text-secondary);
}

@media (max-width: 640px) {
  .funilc-linha { grid-template-columns: 92px 1fr 56px 42px; gap: 6px; }
}

/* Funil de cross-sell: 4 etapas em sequência, tom clareando conforme afunila.
   Rampa de um verde só — a antiga terminava num mint saturado que não existe na
   paleta de Produtos. */
.funilc-barra--impactados { background: var(--chart-1); }
.funilc-barra--abriram    { background: var(--chart-2); }
.funilc-barra--clicaram   { background: var(--chart-4); }
.funilc-barra--adquiriram { background: var(--chart-5); }

/* As linhas ficam DIRETO neste bloco, sem `.funilc-secao` (aqui é uma sequência
   só, não duas seções como no comercial) — então o espaçamento entre linhas tem
   de vir daqui. */
.funilc--cross {
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.funilc-linha--cross {
  /* Primeira coluna igual à do funil comercial para os dois alinharem na mesma
     tela; a barra fica em 1fr e ocupa a largura do painel. */
  grid-template-columns: 120px 1fr 64px 56px 62px;
}

/* Barra mais alta e em forma de pílula: com 4 etapas e espaçamento maior, barra
   fina fica frágil. O trilho ganha um tom mais suave para o retângulo de fundo
   pesar menos que a própria barra. */
.funilc--cross .funilc-trilha {
  height: 26px;
  border-radius: var(--radius-pill);
  background: var(--warm-200);
}

.funilc--cross .funilc-barra { border-radius: var(--radius-pill); }
.funilc--cross .funilc-rotulo { font-size: 0.85rem; font-weight: 500; }
.funilc--cross .funilc-valor { font-size: 0.92rem; }
.funilc--cross .funilc-nota { margin-top: 4px; }

.funilc-linha--cabecalho {
  font-size: 0.7rem;
  font-weight: 600;
  color: var(--text-secondary);
  padding-bottom: 2px;
}

/* Cabeçalho não precisa da altura da barra — sem isso ele herda os 26px. */
.funilc-linha--cabecalho .funilc-trilha { height: auto; background: none; }

.cross-sell-body {
  display: flex;
  gap: 28px;
  flex-wrap: wrap;
  align-items: flex-start;
  padding-top: 6px;
  padding-bottom: 10px;
}

/* O gráfico lateral (`cross-sell-chart`) não é renderizado hoje, então o funil é
   o único filho deste flex. `min-width: 0` deixa ele encolher no responsivo em
   vez de estourar. */
.cross-sell-body .funilc {
  flex: 1;
  min-width: 0;
}

.cross-sell-chart {
  flex: 1;
  min-width: 280px;
}

/* Funil vertical legado (EtapaFunil), ainda usado pelo cross-sell antigo */
.funil {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.funil-linha {
  display: flex;
  align-items: center;
  gap: 14px;
}

.funil-rotulo {
  flex-shrink: 0;
  width: 110px;
  text-align: right;
  font-weight: 600;
  font-size: 0.82rem;
  color: var(--text-primary);
}

.funil-forma-col {
  flex: 1;
  min-width: 0;
}

.funil-segmento {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  min-height: 46px;
  color: var(--text-on-dark);
  font-size: 0.82rem;
  border-radius: 4px;
}

.funil-segmento--escuro {
  color: var(--text-title);
}

.funil-valor { font-weight: 600; }
.funil-percentual { font-size: 0.76rem; opacity: 0.85; }

.funil--compacto .funil-rotulo { width: 90px; font-size: 0.78rem; }
.funil--compacto .funil-segmento { min-height: 40px; font-size: 0.78rem; }

/* Taxa de cliques (CTOR) */
.ctor-body {
  display: flex;
  gap: 28px;
  flex-wrap: wrap;
}

.ctor-ranking,
.ctor-mes {
  flex: 1;
  min-width: 280px;
}

/* Alcance & saúde da base (gauge) */
.saude-body {
  display: flex;
  align-items: center;
  gap: 16px;
  flex-wrap: wrap;
}

.saude-gauge {
  position: relative;
  flex-shrink: 0;
  width: 180px;
  height: 140px;
}

.saude-linha-box {
  flex: 1;
  min-width: 220px;
  height: 140px;
}

.saude-valor {
  position: absolute;
  left: 50%;
  bottom: 6px;
  transform: translateX(-50%);
  font-size: 1.3rem;
  font-weight: 600;
  color: var(--text-title);
}

/* ==========================================================================
   Tela inicial
   ========================================================================== */
/* "20 de 21": o "de 21" é contexto, não número — mesmo tamanho deixaria os dois
   competindo e a leitura viraria "vinte e vinte e um". */
.stat-value-de {
  font-size: 0.85rem;
  font-weight: 400;
  color: var(--text-secondary);
  letter-spacing: 0;
}

/* Linha-espinha da narrativa do mês. Corpo maior que texto de apoio porque é
   uma frase para ser LIDA, não uma legenda. */
.inicio-narrativa {
  margin: 0 0 18px;
  font-size: 0.95rem;
  line-height: 1.6;
  color: var(--text-primary);
  max-width: 92ch;
}

.inicio-narrativa strong {
  font-weight: 600;
}

/* Número à esquerda e curva à direita, na mesma linha: o card fica com metade da
   altura de um bloco empilhado, e são muitos cards nesta tela. */
.inicio-destaque {
  display: flex;
  align-items: center;
  gap: 18px;
  flex-wrap: wrap;
}

.inicio-destaque-numero {
  display: flex;
  flex-direction: column;
  gap: 3px;
  min-width: 0;
}

/* `min-width` no gráfico: sem ele o flex encolhe o canvas até uns poucos pixels
   quando o valor formatado é longo, e a curva desaparece sem nenhum aviso. */
.inicio-destaque-spark {
  flex: 1;
  min-width: 130px;
}

.inicio-destaque-meta {
  font-size: 0.76rem;
  color: var(--text-secondary);
}

/* Situação da fonte: o ponto de cor nunca vem sozinho — sempre com o rótulo ao
   lado, para a leitura não depender de percepção de cor. */
.fonte-situacao {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  white-space: nowrap;
}

/* Atalhos por área. Linha inteira clicável, com a seta na borda — alvo grande é
   mais fácil de acertar que o texto do rótulo. */
.inicio-atalhos {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.inicio-atalho {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 9px 12px;
  border-radius: var(--radius-sm);
  font-size: 0.875rem;
  color: var(--text-title);
  transition: background-color 0.12s ease;
}

.inicio-atalho svg {
  width: 15px;
  height: 15px;
  flex-shrink: 0;
  color: var(--text-tertiary);
  transition: transform 0.14s ease, color 0.14s ease;
}

.inicio-atalho:hover {
  background: var(--bg-inset);
}

.inicio-atalho:hover svg {
  color: var(--brand-600);
  transform: translateX(2px);
}

/* Ressalvas e pendências: <dl> porque é literalmente uma lista de definições —
   título curto, explicação embaixo. Duas colunas em tela larga; empilha antes de
   a coluna ficar estreita o suficiente para o texto virar uma tira. */
.inicio-ressalvas {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
  gap: 16px 28px;
  margin: 0;
}

@media (max-width: 720px) {
  .inicio-ressalvas { grid-template-columns: 1fr; }
}

.inicio-ressalva dt {
  font-size: 0.875rem;
  font-weight: 600;
  color: var(--text-title);
  margin-bottom: 3px;
}

.inicio-ressalva dd {
  margin: 0;
  font-size: 0.84rem;
  line-height: 1.55;
  color: var(--text-secondary);
}

.inicio-detalhe {
  margin-top: 20px;
  padding-top: 16px;
  border-top: 1px solid var(--border-subtle);
}

.inicio-detalhe summary {
  font-size: 0.875rem;
  font-weight: 500;
  color: var(--text-title);
  cursor: pointer;
  list-style: none;
  display: flex;
  align-items: center;
  gap: 7px;
}

.inicio-detalhe summary::-webkit-details-marker { display: none; }

/* Triângulo próprio, girando ao abrir. O marcador nativo do navegador é a única
   forma da tela que não segue a paleta. */
.inicio-detalhe summary::before {
  content: '';
  width: 0;
  height: 0;
  border-left: 5px solid currentColor;
  border-top: 4px solid transparent;
  border-bottom: 4px solid transparent;
  transition: transform 0.16s ease;
}

.inicio-detalhe[open] summary::before {
  transform: rotate(90deg);
}

.inicio-detalhe-corpo {
  margin-top: 12px;
  display: flex;
  flex-direction: column;
  gap: 9px;
}

.inicio-detalhe-corpo p {
  display: flex;
  align-items: baseline;
  gap: 9px;
  margin: 0;
  font-size: 0.84rem;
  line-height: 1.55;
  color: var(--text-secondary);
}

.inicio-detalhe-corpo .badge {
  flex-shrink: 0;
}

/* ==========================================================================
   Relatório N3
   ==========================================================================
   A tela é uma sequência de tabelas densas (é um relatório para reunião, não um
   dashboard de navegação), então o que precisa de estilo aqui é: linha de KPI,
   scroll horizontal por tabela e a marcação visual de coluna fictícia.
   ========================================================================== */
.n3-kpis {
  display: flex;
  flex-wrap: wrap;
  gap: 28px;
}

.n3-kpi {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.n3-tabela-wrap {
  margin-top: 14px;
}

.n3-tabela-wrap--topo {
  margin-top: 0;
}

.n3-nota {
  font-size: 0.78rem;
  line-height: 1.55;
  color: var(--text-secondary);
}

.n3-nota--solta {
  margin: 12px 0 0;
}

/* Marca de "mês em andamento" no cabeçalho de coluna da Cobertura de base.
   Usa os tokens de aviso que já existem — nenhum token novo, nenhuma cor literal, então
   os dois blocos de tema escuro continuam valendo sem nada duplicado.
   `text-transform` e não texto em maiúscula no template: o rótulo aparece em duas telas
   e escrevê-lo duas vezes deixaria as duas livres para divergir. */
/* Cards de mês da Cobertura de base — clicar expande o mês em semanas.
   Tokens existentes só; o "selecionado" é sage com texto verde-escuro, que é a regra 3 do
   padrão de Produtos. Sem cor literal, então os dois blocos de tema escuro seguem valendo. */
.mes-cards {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 16px;
}

.mes-card {
  flex: 1 1 96px;
  min-width: 96px;
  display: flex;
  flex-direction: column;
  gap: 1px;
  padding: 9px 11px;
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-sm);
  background: var(--bg-surface);
  text-decoration: none;
  color: inherit;
  transition: border-color 0.12s ease, background 0.12s ease;
}

a.mes-card:hover,
a.mes-card:focus-visible {
  border-color: var(--brand-500);
  background: var(--bg-hover);
}

.mes-card.is-ativo {
  background: var(--sage-200);
  border-color: var(--sage-300);
}

/* Mês sem grão semanal: mesmo formato, sem afordância de clique. Esconder o mês faria a
   faixa ter menos meses que o gráfico logo acima, o que lê como dado faltando. */
.mes-card--inerte {
  opacity: 0.62;
  cursor: default;
}

.mes-card-rotulo {
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--text-secondary);
}

.mes-card.is-ativo .mes-card-rotulo,
.mes-card.is-ativo .mes-card-valor,
.mes-card.is-ativo .mes-card-sub,
.mes-card.is-ativo .mes-card-acao {
  color: var(--text-title);
}

.mes-card-valor {
  font-size: 1.05rem;
  font-weight: 700;
  color: var(--text-title);
  line-height: 1.2;
}

.mes-card-sub {
  font-size: 0.68rem;
  color: var(--text-tertiary);
}

.mes-card-acao {
  margin-top: 3px;
  font-size: 0.66rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--brand-500);
}

.mes-card--inerte .mes-card-acao {
  color: var(--text-tertiary);
}

/* Bloco semanal expandido. Recuo à esquerda com uma faixa sage para ele ler como
   DETALHE do mês selecionado, e não como um painel irmão do de cima. */
.semanal-bloco {
  margin-top: 16px;
  padding: 16px 0 4px 16px;
  border-left: 3px solid var(--sage-300);
}

.semanal-cabecalho {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 10px;
  margin-bottom: 12px;
}

.semanal-titulo {
  font-size: 0.95rem;
  font-weight: 700;
  color: var(--text-title);
}

.semanal-base {
  font-size: 0.78rem;
  color: var(--text-secondary);
}

/* Tabela longa cortada em 10 linhas, com "+ ver as outras N". CSS PURO — checkbox + label.
   Numa tela que desenha gráfico, `display: none` alternado por `:checked` não tem o risco
   que um handler de JS tem. Reutilizável: basta o trio `.tabela-limite` /
   `.tabela-limite-check` / `.tabela-limite-alvo` na tabela. */
.tabela-limite {
  display: flex;
  flex-direction: column;
}

/* NÃO usar `hidden` nem `display: none` aqui: os dois tiram o input da ordem de foco e o
   controle some para quem navega por teclado. Escondido visualmente, continua focável. */
.tabela-limite-check {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
}

/* `nth-child(n+11)` conta as linhas do CORPO, então o cabeçalho (que vive no `thead`)
      nunca entra na conta e permanece visível. Se alguém mover o cabeçalho para dentro do
      `tbody`, o corte passa a esconder a linha errada. */
.tabela-limite-check:not(:checked) ~ * .tabela-limite-alvo tbody tr:nth-child(n+11),
.tabela-limite-check:not(:checked) ~ .tabela-limite-alvo tbody tr:nth-child(n+11) {
  display: none;
}

.tabela-limite-botao {
  align-self: flex-start;
  margin-top: 10px;
  padding: 6px 12px;
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-sm);
  background: var(--bg-surface);
  color: var(--brand-500);
  font-size: 0.78rem;
  font-weight: 600;
  cursor: pointer;
  user-select: none;
  transition: border-color 0.12s ease, background 0.12s ease;
}

.tabela-limite-botao::before {
  content: '+';
  margin-right: 6px;
  font-weight: 700;
}

.tabela-limite-check:checked ~ .tabela-limite-botao::before {
  content: '−';
}

.tabela-limite-botao:hover {
  border-color: var(--brand-500);
  background: var(--bg-hover);
}

/* O foco do teclado vai para o input escondido, então o contorno precisa aparecer no
   `label` — senão quem navega por Tab não vê onde está. */
.tabela-limite-check:focus-visible ~ .tabela-limite-botao {
  outline: 2px solid var(--brand-500);
  outline-offset: 2px;
}

.tabela-limite-check:checked ~ .tabela-limite-botao .tabela-limite-mais,
.tabela-limite-check:not(:checked) ~ .tabela-limite-botao .tabela-limite-menos {
  display: none;
}

.tag-parcial {
  display: inline-block;
  margin-left: 5px;
  padding: 1px 6px;
  border-radius: 999px;
  background: var(--warn-bg);
  color: var(--warn-text);
  border: 1px solid var(--warn-border);
  font-size: 0.62rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: lowercase;
  vertical-align: middle;
}

.n3-destaque {
  margin: 0 0 12px;
  font-size: 0.875rem;
  font-weight: 500;
  color: var(--brand-600);
}

.n3-linha-total td {
  background: var(--sage-100);
  font-weight: 600;
  color: var(--text-title);
}

/* Linha de APOIO: as contagens que formam o percentual da linha de cima. Menor
   e em cor secundária de propósito — o número de capa continua sendo o
   percentual, e estas existem para o cálculo poder ser conferido na tela
   (137.430 ÷ 152.691 = 90%) sem competir com ele pela atenção. */
.n3-linha-apoio td {
  font-size: 0.8rem;
  color: var(--text-secondary);
}

.n3-linha-apoio:first-of-type td {
  border-top: 1px solid var(--border-subtle);
}

/* Coluna sem fonte real: mudo e em itálico. O selo do painel diz que ele é
   fictício, mas não distingue QUAL coluna é — numa tabela com envios reais ao
   lado de custo inventado, essa distinção é o que evita alguém citar o número
   errado. */
.n3-col-ficticia,
.n3-col-vazia {
  color: var(--text-tertiary);
  font-style: italic;
}

.n3-subtitulo {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  margin: 24px 0 0;
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--text-title);
}

.n3-subtitulo-contagem {
  font-size: 0.72rem;
  font-weight: 500;
  color: var(--text-secondary);
  background: var(--bg-inset);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-pill);
  padding: 1px 8px;
}

.n3-subtitulo-nota {
  font-size: 0.74rem;
  font-weight: 400;
  color: var(--text-secondary);
}

.n3-motivo {
  font-size: 0.76rem;
  color: var(--text-secondary);
  white-space: nowrap;
}

/* Captação negativa: cliente que converteu e depois sacou. O sinal é
   informação, não erro — precisa saltar aos olhos numa tabela cheia de valores
   positivos. */
.n3-negativo {
  color: var(--bad);
  font-weight: 600;
}

/* ==========================================================================
   Responsivo
   ========================================================================== */
@media (max-width: 1024px) {
  .content { padding: 0 20px 32px; }
  .topbar { padding: 18px 20px 16px; }
}

@media (max-width: 860px) {
  .topbar-title { font-size: 1.35rem; }
}

@media (max-width: 720px) {
  .app-shell {
    flex-direction: column;
  }

  .sidebar {
    width: 100% !important;
    height: auto;
    position: static;
    max-height: none;
    border-right: none;
    border-bottom: 1px solid var(--border-subtle);
    padding-bottom: 10px;
  }

  /* Nada a desfazer aqui: o bloco de "recolhido" está escopado em
     `min-width: 721px`, então nesta faixa ele nem entra na cascata. O botão de
     recolher sai de cena porque não teria efeito. */
  .sidebar-toggle { display: none; }

  .content-header { align-items: flex-start; }
  .projeto-kpis { grid-template-columns: repeat(2, 1fr); }
  .n3-kpis { gap: 20px; }
  .panel--destaque .n3-kpi:not(:first-child) { border-left: none; padding-left: 0; }
}

/* ==========================================================================
   ÁREA DE GESTÃO (/gestao/) — administração da própria aplicação
   ==========================================================================

   NENHUMA COR LITERAL AQUI. Toda cor sai de token de `:root`, que é a regra que
   sustenta o tema escuro deste arquivo: o escuro é redefinição de token, sem uma única
   regra de componente duplicada. Um `#hex` nesta seção quebraria o tema escuro da área de
   gestão SEM ERRO NENHUM — `check` limpo, HTTP 200, e a tela pintada na paleta clara com o
   tema escuro ligado.

   Também não há token novo: a área é construída inteira sobre os 91 que já existiam. Token
   novo teria de ser declarado em três lugares (`:root`, a media query e o seletor de
   atributo), e esquecer um dos dois blocos escuros produz divergência que só aparece na
   máquina de quem tem o sistema em escuro.
   ========================================================================== */

/* --- Mensagens de retorno (framework de messages) ------------------------- */
/* Fica no base.html, então vale nas 20 telas. Sem isto, uma mensagem enfileirada por uma
   ação que redireciona para tela de indicador se perderia calada. */
.mensagens {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-bottom: 18px;
}

.mensagem {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 12px 14px;
  border-radius: var(--radius-md);
  border: 1px solid var(--info-border);
  background: var(--info-bg);
  color: var(--text-primary);
  font-size: 0.88rem;
  line-height: 1.55;
}

.mensagem-icone {
  flex-shrink: 0;
  width: 18px;
  height: 18px;
  margin-top: 1px;
  background-image: var(--icone-info);
  background-repeat: no-repeat;
  background-size: contain;
}

.mensagem--success {
  border-color: var(--good-border);
  background: var(--good-bg);
}

.mensagem--success .mensagem-icone { background-image: var(--icone-ok); }

.mensagem--warning {
  border-color: var(--warn-border);
  background: var(--warn-bg);
}

.mensagem--warning .mensagem-icone { background-image: var(--icone-atencao); }

.mensagem--error {
  border-color: var(--bad-border);
  background: var(--bad-bg);
}

.mensagem--error .mensagem-icone { background-image: var(--icone-atencao); }

.mensagem-texto { flex: 1; }

/* --- Alertas da visão geral ---------------------------------------------- */
.adm-alertas {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-bottom: 20px;
}

.adm-alerta {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 14px 16px;
  background: var(--bg-surface);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-card);
}

/* A faixa lateral é o que dá severidade sem pintar o card inteiro. Card colorido inteiro
   competiria com os selos de estado que já existem na mesma tela. */
.adm-alerta-marca {
  flex-shrink: 0;
  width: 3px;
  align-self: stretch;
  min-height: 34px;
  border-radius: var(--radius-pill);
  background: var(--text-tertiary);
}

.adm-alerta--critico .adm-alerta-marca { background: var(--bad); }
.adm-alerta--atencao .adm-alerta-marca { background: var(--warn); }
.adm-alerta--informativo .adm-alerta-marca { background: var(--info); }

.adm-alerta-corpo { flex: 1; min-width: 0; }

.adm-alerta-titulo {
  margin: 0 0 4px;
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--text-title);
}

.adm-alerta-detalhe {
  margin: 0;
  font-size: 0.82rem;
  line-height: 1.6;
  color: var(--text-secondary);
}

.adm-alerta .btn { flex-shrink: 0; }

/* --- Tabelas da gestão --------------------------------------------------- */
.adm-celula-nota {
  font-size: 0.8rem;
  color: var(--text-secondary);
  max-width: 420px;
}

.adm-col-acao {
  width: 1%;
  white-space: nowrap;
  text-align: right;
}

.adm-linha-inativa { opacity: 0.62; }

/* Linha de detalhe logo abaixo da linha principal: o erro completo da fonte e a cauda da
   saída da rotina. Fundo diferente para não parecer uma linha de dado. */
.adm-linha-erro > td,
.adm-linha-saida > td {
  background: var(--bg-inset);
  font-size: 0.8rem;
  color: var(--text-secondary);
}

.adm-linha-erro > td { color: var(--bad); }

.adm-pessoa {
  display: flex;
  flex-direction: column;
  gap: 1px;
  text-decoration: none;
}

.adm-pessoa-nome {
  font-weight: 600;
  color: var(--text-title);
}

.adm-pessoa:hover .adm-pessoa-nome { color: var(--brand-600); }

.adm-pessoa-email {
  font-size: 0.76rem;
  color: var(--text-tertiary);
}

.adm-nivel {
  font-size: 0.72rem;
  color: var(--text-tertiary);
  white-space: nowrap;
}

.adm-nota {
  margin: 12px 0 0;
  font-size: 0.8rem;
  line-height: 1.65;
  color: var(--text-secondary);
}

.adm-nota-inline {
  font-size: 0.72rem;
  color: var(--text-tertiary);
}

.adm-subtitulo {
  margin: 16px 0 8px;
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--text-secondary);
}

.adm-areas {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin: 0;
  font-size: 0.84rem;
  color: var(--text-primary);
}

/* --- Menu de ações por linha (details/summary, zero JS) ------------------- */
/* Sem `position: relative`: o painel abre no fluxo (ver o comentário dele), então não há
   nada para posicionar em relação a.
   Coluna flex com `align-items: flex-end` para alinhar botão e painel à direita da célula de
   ação. `margin-left: auto` no `<summary>` não serviria: ele é `inline-flex` (por
   `.adm-menu-botao`), e margem automática não empurra caixa de nível inline. */
.adm-menu {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
}

.adm-menu-botao {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  border-radius: var(--radius-sm);
  color: var(--text-secondary);
  cursor: pointer;
  list-style: none;
}

.adm-menu-botao::-webkit-details-marker { display: none; }

.adm-menu-botao:hover {
  background: var(--bg-hover);
  color: var(--text-title);
}

.adm-menu-botao svg { width: 16px; height: 16px; }

/* O PAINEL ABRE NO FLUXO, NÃO FLUTUANDO, e a razão é uma regra de CSS que morde em
   silêncio: `position: absolute` é recortado pelo ancestral mais próximo com `overflow`
   diferente de `visible`, e toda tabela daqui está dentro de `.tablewrap`, que tem
   `overflow-x: auto`.

   O detalhe que fecha o caso: pela especificação, quando um eixo é diferente de `visible`, o
   `visible` do outro eixo passa a computar como `auto`. Ou seja, `.tablewrap` recorta os DOIS
   eixos — e recorta MESMO QUANDO A TABELA NÃO ROLA, porque `overflow: auto` sempre estabelece
   contexto de recorte. Um menu flutuante ali apareceria cortado pela borda do painel, e o
   sintoma não teria nada a ver com a causa aparente (a tabela cabe na tela, então ninguém
   suspeitaria de rolagem).

   As saídas seriam: tirar o `overflow-x` da tabela (e aí tabela larga estoura a página),
   `position: fixed` com cálculo de posição em JS (o projeto evita JS na navegação por
   decisão registrada), ou abrir no fluxo. A terceira é a única que não troca um problema por
   outro: a linha cresce enquanto o menu está aberto, e nada pode recortá-lo.

   Continua com sombra porque ele ainda LÊ como camada sobreposta — é o princípio "borda em
   vez de sombra; sombra só no que se destaca do plano". */
.adm-menu-painel {
  display: flex;
  flex-direction: column;
  width: max-content;
  min-width: 190px;
  /* O alinhamento à direita vem do `align-items: flex-end` do `.adm-menu`. */
  margin: 6px 0 2px;
  padding: 6px;
  text-align: left;
  /* A célula de ação é `white-space: nowrap` (para o botão não quebrar); herdado aqui, ele
     impediria a nota explicativa de quebrar linha. */
  white-space: normal;
  background: var(--bg-surface);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-pop);
}

.adm-menu-painel a,
.adm-menu-botao-linha {
  display: block;
  width: 100%;
  padding: 7px 10px;
  border: none;
  border-radius: var(--radius-sm);
  background: none;
  font-family: inherit;
  font-size: 0.83rem;
  text-align: left;
  text-decoration: none;
  color: var(--text-primary);
  cursor: pointer;
}

.adm-menu-painel a:hover,
.adm-menu-botao-linha:hover {
  background: var(--bg-hover);
  color: var(--text-title);
}

.adm-menu-perigo { color: var(--bad); }

.adm-menu-perigo:hover {
  background: var(--bad-bg);
  color: var(--bad);
}

.adm-menu-nota {
  display: block;
  padding: 7px 10px;
  font-size: 0.76rem;
  line-height: 1.55;
  color: var(--text-tertiary);
  white-space: normal;
}

.adm-menu-painel form { display: contents; }

/* --- Paginação ----------------------------------------------------------- */
.adm-paginacao {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 14px;
  margin-top: 16px;
  padding-top: 14px;
  border-top: 1px solid var(--border-subtle);
}

.adm-paginacao-posicao {
  font-size: 0.8rem;
  color: var(--text-secondary);
}

/* Estado inativo dos botões de página e da rotina bloqueada. `pointer-events: none` porque
   eles são `<span>`, não `<a>`: sem isto o cursor viraria de mão sobre algo que não clica. */
.adm-paginacao-inativo {
  opacity: 0.45;
  pointer-events: none;
}

/* --- Ficha (lista de definição) ------------------------------------------ */
.adm-ficha {
  display: grid;
  grid-template-columns: minmax(140px, auto) 1fr;
  gap: 8px 16px;
  margin: 0;
  font-size: 0.85rem;
}

.adm-ficha dt {
  color: var(--text-secondary);
  font-weight: 500;
}

.adm-ficha dd {
  margin: 0;
  color: var(--text-primary);
}

/* --- Matriz de permissões (leitura) ------------------------------------- */
/* Lista e não tabela cruzada: a maioria dos módulos usa 1 ou 2 das 5 ações, então 60% das
   células de uma tabela ficariam vazias — e célula vazia numa matriz de permissão é ambígua
   entre "não concedido" e "não existe". */
.perm-lista {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.perm-item {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 8px 12px;
  padding: 7px 0;
  border-bottom: 1px solid var(--border-subtle);
}

.perm-item:last-child { border-bottom: none; }

.perm-item--vazio { opacity: 0.6; }

.perm-modulo {
  flex: 0 0 auto;
  min-width: 190px;
  font-size: 0.84rem;
  font-weight: 500;
  color: var(--text-title);
}

.perm-acoes {
  display: flex;
  flex-wrap: wrap;
  gap: 5px;
}

.perm-acao {
  padding: 2px 8px;
  border-radius: var(--radius-pill);
  border: 1px dashed var(--border-strong);
  font-size: 0.7rem;
  font-weight: 500;
  color: var(--text-tertiary);
}

/* Concedido = sage com texto verde escuro, o "selecionado" do padrão do time de Produtos.
   A borda passa de tracejada a sólida: a distinção não depende só de cor. */
.perm-acao--sim {
  border-style: solid;
  border-color: var(--sage-300);
  background: var(--sage-200);
  color: var(--text-title);
  font-weight: 600;
}

.perm-nada {
  font-size: 0.72rem;
  font-style: italic;
  color: var(--text-tertiary);
}

/* --- Matriz de permissões (edição) -------------------------------------- */
.adm-matriz-edicao {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 14px;
}

.adm-matriz-modulo {
  margin: 0;
  padding: 14px 16px;
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  background: var(--bg-surface);
}

.adm-matriz-legenda {
  padding: 0 4px;
  font-size: 0.84rem;
  font-weight: 600;
  color: var(--text-title);
}

.adm-matriz-descricao {
  margin: 4px 0 10px;
  font-size: 0.76rem;
  line-height: 1.55;
  color: var(--text-secondary);
}

.adm-matriz-acoes {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 14px;
}

/* --- Caixas de seleção -------------------------------------------------- */
.adm-caixas-lista {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 18px;
}

.adm-caixa {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-size: 0.84rem;
  color: var(--text-primary);
  cursor: pointer;
}

.adm-caixa input[type="checkbox"] {
  width: 15px;
  height: 15px;
  accent-color: var(--brand-600);
  cursor: pointer;
}

/* --- Formulários -------------------------------------------------------- */
.adm-formulario { max-width: 720px; }

.adm-formulario--largo { max-width: 100%; }

.adm-form-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 16px;
  margin-bottom: 16px;
}

.adm-form-grid--largo { grid-template-columns: 1fr; }

.adm-form-caixas {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-bottom: 16px;
}

.adm-form-acoes {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px;
  margin-top: 18px;
  padding-top: 16px;
  border-top: 1px solid var(--border-subtle);
}

/* Estados do campo. `.campo` e `.campo-label` já existiam; ajuda e erro não, e a ausência
   do erro era o problema: um formulário que recusa o envio sem dizer o motivo é
   indistinguível de botão quebrado. */
.campo-ajuda {
  font-size: 0.74rem;
  line-height: 1.55;
  color: var(--text-tertiary);
}

.campo-erro {
  font-size: 0.76rem;
  font-weight: 500;
  color: var(--bad);
}

.campo--erro input,
.campo--erro select,
.campo--erro textarea {
  border-color: var(--bad-border);
}

.campo-obrigatorio {
  color: var(--bad);
  margin-left: 2px;
}

.campo--caixa { flex-direction: row; }

.campo-caixa-label {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 0.85rem;
  color: var(--text-primary);
  cursor: pointer;
}

.campo-caixa-label input[type="checkbox"] {
  width: 15px;
  height: 15px;
  accent-color: var(--brand-600);
}

/* Cabeçalho do painel de filtro em LINHA (título + contagem). O `.filtros-panel-header`
   original é um bloco de texto simples e continua sendo — daí o modificador em vez de
   mudar a regra base, que é usada pela tela de Estratégia de campanha. */
.filtros-panel-header--linha {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
}

.filtros-panel-titulo {
  font-size: 0.95rem;
  font-weight: 600;
  color: var(--text-title);
}

/* --- Perfis -------------------------------------------------------------- */
.adm-perfil-resumo {
  padding: 12px 0;
  border-bottom: 1px solid var(--border-subtle);
}

.adm-perfil-resumo:last-child { border-bottom: none; }

.adm-perfil-cabecalho {
  display: flex;
  align-items: baseline;
  gap: 10px;
  margin-bottom: 4px;
}

.adm-perfil-nome {
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--text-title);
}

.adm-perfil-descricao {
  margin: 0 0 8px;
  font-size: 0.78rem;
  line-height: 1.55;
  color: var(--text-secondary);
}

/* --- Rotinas ------------------------------------------------------------ */
.adm-rotinas {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 14px;
}

.adm-rotina {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 14px 16px;
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  background: var(--bg-surface);
}

.adm-rotina-topo {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
}

.adm-rotina-nome {
  font-size: 0.88rem;
  font-weight: 600;
  color: var(--text-title);
}

.adm-rotina-descricao {
  flex: 1;
  margin: 0;
  font-size: 0.78rem;
  line-height: 1.6;
  color: var(--text-secondary);
}

/* `align-self: flex-start` para o botão não esticar na largura do card — botão de largura
   total lê como ação primária da tela, e aqui há vários lado a lado. */
.adm-rotina .btn { align-self: flex-start; }

.adm-saida > summary {
  cursor: pointer;
  font-size: 0.78rem;
  color: var(--brand-600);
}

.adm-saida-texto {
  max-height: 320px;
  margin: 8px 0 0;
  padding: 10px 12px;
  overflow: auto;
  background: var(--bg-inset);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-sm);
  font-size: 0.74rem;
  line-height: 1.55;
  color: var(--text-primary);
  /* `pre-wrap` e não `pre`: a saída do ETL tem linhas longas, e `pre` faria o painel inteiro
     rolar na horizontal — o `overflow-x` do contêiner não alcança o corpo da página, mas a
     tabela em volta esticaria. */
  white-space: pre-wrap;
  word-break: break-word;
}

/* --- Áreas (configurações) ---------------------------------------------- */
.adm-area-bloco {
  padding: 14px 0;
  border-bottom: 1px solid var(--border-subtle);
}

.adm-area-bloco:last-of-type { border-bottom: none; }

.adm-area-cabecalho {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
  margin-bottom: 10px;
}

.adm-area-nome {
  font-size: 0.92rem;
  font-weight: 600;
  color: var(--text-title);
}

.adm-area-cabecalho form { display: contents; }

/* --- Confirmação e erro ------------------------------------------------- */
.adm-confirmar,
.adm-erro { max-width: 620px; }

.adm-consequencias {
  margin: 0;
  padding-left: 20px;
  font-size: 0.86rem;
  line-height: 1.7;
  color: var(--text-primary);
}

.adm-consequencias li { margin-bottom: 6px; }

.adm-confirmar-acoes {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px;
  margin-top: 22px;
  padding-top: 18px;
  border-top: 1px solid var(--border-subtle);
}

.adm-confirmar-form { display: contents; }

.adm-acoes-linha {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px;
  margin-top: 12px;
}

.adm-acoes-linha form { display: contents; }

.adm-acao-perigo { color: var(--bad); }

/* Botão destrutivo. NÃO é o estilo primário: nas telas de confirmação o "Cancelar" é o
   botão sólido, para que quem chega por engano e clica no que parece o principal saia sem
   fazer nada. */
.btn--perigo {
  background: var(--bad-bg);
  border-color: var(--bad-border);
  color: var(--bad);
}

.btn--perigo:hover {
  background: var(--bad);
  border-color: var(--bad);
  color: var(--text-on-dark);
}

/* --- Trilha de auditoria ------------------------------------------------- */
.trilha {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
}

.trilha-item {
  display: flex;
  gap: 12px;
  padding: 11px 0;
  border-bottom: 1px solid var(--border-subtle);
}

.trilha-item:last-child { border-bottom: none; }

.trilha-marca {
  flex-shrink: 0;
  width: 7px;
  height: 7px;
  margin-top: 6px;
  border-radius: var(--radius-pill);
  background: var(--brand-400);
}

.trilha-item--falha .trilha-marca,
.trilha-item--login_falho .trilha-marca,
.trilha-item--negado .trilha-marca { background: var(--bad); }

.trilha-item--login .trilha-marca { background: var(--good); }
.trilha-item--logout .trilha-marca { background: var(--text-tertiary); }
.trilha-item--excluir .trilha-marca { background: var(--warn); }

.trilha-corpo { flex: 1; min-width: 0; }

.trilha-frase {
  margin: 0 0 3px;
  font-size: 0.86rem;
  line-height: 1.5;
  color: var(--text-primary);
}

.trilha-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 5px 10px;
  margin: 0;
  font-size: 0.74rem;
  color: var(--text-tertiary);
}

.trilha-recurso,
.trilha-ip { white-space: nowrap; }

.trilha-ip { font-variant-numeric: tabular-nums; }

.trilha-diff {
  list-style: none;
  margin: 8px 0 0;
  padding: 8px 10px;
  background: var(--bg-inset);
  border-radius: var(--radius-sm);
  font-size: 0.76rem;
}

.trilha-diff li {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 6px;
  padding: 2px 0;
}

.trilha-diff-campo {
  min-width: 130px;
  font-weight: 600;
  color: var(--text-secondary);
}

.trilha-diff-de {
  color: var(--text-tertiary);
  text-decoration: line-through;
}

.trilha-diff-seta { color: var(--text-tertiary); }

.trilha-diff-para {
  font-weight: 500;
  color: var(--text-title);
}

/* --- Item externo da sidebar (Django admin) ----------------------------- */
.sidebar-subitem--externo {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 6px;
}

.sidebar-subitem--externo svg {
  flex-shrink: 0;
  width: 13px;
  height: 13px;
  opacity: 0.7;
}

/* --- Responsividade da gestão ------------------------------------------- */
/* O CORPO DA PÁGINA NUNCA ROLA NA HORIZONTAL. Toda tabela larga já está dentro de
   `.tablewrap`, que tem `overflow-x: auto` — o que este bloco resolve é o que NÃO é
   tabela: grid de duas colunas, ficha em duas colunas, e a linha de ações do alerta. */
@media (max-width: 900px) {
  /* O alerta empilha: com o botão ao lado, o texto ficava em coluna de ~120px. */
  .adm-alerta { flex-wrap: wrap; }
  .adm-alerta .btn { margin-left: 15px; }

  .adm-matriz-edicao,
  .adm-rotinas { grid-template-columns: 1fr; }
}

@media (max-width: 720px) {
  /* Ficha em uma coluna: com `minmax(140px, auto)` o valor ficava sem espaço no celular. */
  .adm-ficha { grid-template-columns: 1fr; gap: 2px 0; }
  .adm-ficha dt { margin-top: 8px; }

  /* O rótulo do módulo tinha `min-width: 190px`, o que forçava a linha a estourar a largura
     da tela antes de quebrar. Aqui ele solta e as ações vão para a linha de baixo. */
  .perm-modulo { min-width: 0; flex: 1 0 100%; }

  .adm-form-grid { grid-template-columns: 1fr; }

  /* No celular a célula de ação é estreita, e `min-width: 190px` no painel esticaria a
     tabela inteira (forçando rolagem horizontal por causa de um menu). Em relação à
     viewport ele cabe. */
  .adm-menu-painel { min-width: min(190px, 62vw); }

  .adm-confirmar-acoes,
  .adm-form-acoes { flex-direction: column; align-items: stretch; }

  .adm-confirmar-acoes .btn,
  .adm-form-acoes .btn { width: 100%; }
}

/* A fração que produz cada taxa, na linha de baixo do card.
 *
 * SUBSTITUIU UM `title` NATIVO, que foi a primeira tentativa e não serviu: o tooltip do
 *    navegador só aparece depois de ~1s parado, não existe em toque, e o único sinal de que
 *    havia algo ali era um pontilhado. A informação existia e ninguém via — o que, num
 *    painel que é apresentado, é o mesmo que não existir.
 *
 * Menor e em texto secundário: ela é apoio do número grande, não concorrente dele. */
.saude-stat-fracao {
  font-size: 0.72rem;
  color: var(--text-secondary);
  font-variant-numeric: tabular-nums;
}

/* ==========================================================================
   Troca local de conteúdo (layout.js)
   ========================================================================== */
/* O miolo esmaece enquanto a resposta do filtro não chega. Sem nenhum sinal, uma troca que
 * leva meio segundo parece que o clique não pegou e o reflexo é clicar de novo — é o mesmo
 * motivo da rodinha nos itens de navegação.
 *
 * ESMAECE, NÃO BLOQUEIA. `pointer-events: none` era o caminho óbvio para impedir dois
 *    cliques seguidos, e está errado: pedido que travasse deixaria a tela inerte sem saída.
 *    Quem cuida do clique repetido é o `AbortController` do layout.js — o pedido mais novo
 *    cancela o anterior.
 *
 * Nenhuma cor aqui, de propósito: opacidade atravessa os dois temas sem precisar de token,
 * e token novo teria de ser declarado nos três lugares (`:root`, a media query e o seletor
 * de atributo). */
.content.is-trocando {
  opacity: 0.55;
  transition: opacity 120ms ease-out;
}

@media (prefers-reduced-motion: reduce) {
  .content.is-trocando { transition: none; }
}

/* ==========================================================================
   Impressão (o Relatório N3 é levado impresso para a reunião de N3)
   ========================================================================== */
/* =============================================================================
   CASES DE EQI MOMENTS — galeria de cards com foto (18/08/2026)
   =============================================================================

   É O PRIMEIRO COMPONENTE NOVO DESDE 12/08, e as três áreas de protótipo anteriores
   foram construídas com ZERO CSS novo de propósito. Este entra porque um card com foto
   enquadrada no topo não existe no sistema: `panel` é caixa de conteúdo, `lead-time-card`
   é KPI com sparkline e `projeto-kpi` é número com rótulo. Reaproveitar qualquer um dos
   três exigiria sobrescrever padding, altura e overflow — ou seja, escrever o mesmo CSS
   com o nome errado.

   ZERO COR LITERAL e ZERO TOKEN NOVO: tudo sai dos tokens que já existem. Token novo
      teria de ser declarado em TRÊS lugares (`:root`, a media query de escuro e o seletor
      de atributo), e esquecer um dos dois blocos escuros produz divergência que só aparece
      na máquina de quem tem o sistema em escuro.

   FICA ANTES DO BLOCO DE IMPRESSÃO, como todo acréscimo a este arquivo.
   ========================================================================== */

/* Resumo da galeria: uma LINHA acima dos cards, não um painel.
   Um painel só para "2 cases" era uma barra quase vazia empurrando a galeria para baixo — e
      numa galeria o conteúdo é o card, não o contador dele. */
.galeria-resumo {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  margin: 0 0 6px;
  font-size: 0.85rem;
  color: var(--text-secondary);
}

.cases-grid {
  display: grid;
  /* `auto-fill` com minmão de 280px: 3 colunas em tela cheia, 2 no notebook, 1 no celular,
     sem media query. NÃO é coluna fixa como `.projeto-kpis` (que declara 5 e exige 5
     filhos) — a galeria tem N cards e N muda a cada cadastro. */
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 16px;
  margin-bottom: 4px;
}

.case-card {
  display: flex;
  flex-direction: column;
  background: var(--bg-surface);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-lg);
  /* Borda em vez de sombra — princípio 4 do padrão do time de Produtos. Sombra só no que
     flutua (dropdown, modal), e um card de galeria não flutua. */
  overflow: hidden;
  transition: border-color 0.15s ease, transform 0.15s ease;
}

.case-card:hover {
  border-color: var(--border-strong);
  transform: translateY(-2px);
}

/* A moldura da foto. `aspect-ratio` E `overflow: hidden` NO CONTÊINER, com a imagem em
   `object-fit: cover`: sem isso, foto retrato e foto paisagem dariam cards de alturas
   diferentes e a grade viraria escada. O card é de conteúdo cadastrado por gente, então a
   proporção da imagem é imprevisível por construção. */
.case-card-foto {
  position: relative;
  aspect-ratio: 16 / 9;
  background: var(--bg-inset);
  border-bottom: 1px solid var(--border-subtle);
  overflow: hidden;
}

.case-card-foto img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* Estado sem foto: a INICIAL do título sobre o fundo interno.
   Não é um ícone genérico de "imagem faltando", e a diferença é de leitura: ícone de
      imagem quebrada diz "algo deu errado", e aqui não deu — o campo é opcional. A inicial
      dá âncora visual e ainda diferencia um card do outro na grade. */
.case-card-inicial {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 2.6rem;
  font-weight: 700;
  color: var(--brand-300);
  background: var(--bg-inset);
  user-select: none;
}

.case-card-corpo {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 14px 16px 16px;
  flex: 1;
}

/* O eyebrow do slide: ESCRITÓRIO · ASSESSOR · AuC. Verde, caixa alta, pequeno — é a única
   coisa que copio literalmente do material da área, porque é como eles leem o case. */
.case-card-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 8px;
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--accent);
}

.case-card-meta span:not(:last-child)::after {
  content: '·';
  margin-left: 8px;
  color: var(--text-tertiary);
}

.case-card-titulo {
  font-size: 1rem;
  font-weight: 600;
  line-height: 1.35;
  color: var(--text-title);
  margin: 0;
}

/* O trecho da história. TRUNCA EM 4 LINHAS COM `-webkit-line-clamp`, e o card TEM de ter
   para onde levar (o botão Conferir): truncar sem destino publica meia história, que num
   relatório apresentado é pior que não publicar. */
.case-card-resumo {
  font-size: 0.85rem;
  line-height: 1.5;
  color: var(--text-secondary);
  margin: 0;
  display: -webkit-box;
  -webkit-line-clamp: 4;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.case-card-rodape {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: auto;
  padding-top: 4px;
}

.case-card-presente {
  font-size: 0.78rem;
  color: var(--text-tertiary);
  margin: 0;
}

/* --- detalhe do case ------------------------------------------------------ */

.case-detalhe {
  display: grid;
  grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr);
  gap: 18px;
  align-items: start;
}

@media (max-width: 900px) {
  .case-detalhe { grid-template-columns: 1fr; }
}

.case-detalhe-foto {
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-lg);
  overflow: hidden;
  background: var(--bg-inset);
}

.case-detalhe-foto img {
  width: 100%;
  height: auto;
  display: block;
}

/* A história no detalhe NÃO trunca, e a medida de linha é limitada de propósito: texto
   corrido em coluna de 900px passa de 120 caracteres por linha e o olho perde a linha ao
   voltar. */
.case-historia {
  font-size: 0.95rem;
  line-height: 1.65;
  color: var(--text-primary);
  max-width: 62ch;
  white-space: pre-line;
}

.case-ficha {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 8px 14px;
  margin: 0;
  font-size: 0.88rem;
}

.case-ficha dt {
  color: var(--text-secondary);
  font-weight: 500;
}

.case-ficha dd {
  margin: 0;
  color: var(--text-title);
  font-weight: 600;
}

.case-assinatura {
  font-size: 0.78rem;
  color: var(--text-tertiary);
  border-top: 1px solid var(--border-subtle);
  padding-top: 10px;
  margin-top: 4px;
}

/* Ressalvas dos KPIs do painel de ROI. Texto NA TELA e não tooltip do selo — o `title`
   nativo só aparece depois de ~1s parado e não existe em toque, e este projeto já registrou
   esse fracasso na Saúde da base. Zero token novo, como o resto do arquivo. */
.roi-ressalvas {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-top: 10px;
  padding-top: 10px;
  border-top: 1px solid var(--border-subtle);
}

.roi-ressalva {
  margin: 0;
  font-size: 0.78rem;
  line-height: 1.5;
  color: var(--text-secondary);
  /* Limita a medida de leitura: parágrafo de ressalva atravessando um painel largo vira
     uma linha de 200 caracteres, que é onde o olho se perde e a pessoa desiste. */
  max-width: 92ch;
}

/* ===================================================================================
   CARGA DE PLANILHA — sub-aba "Produtos" da Estratégia de campanha (18/08/2026)

   Zero token novo e zero cor literal, como o resto do arquivo: tudo sai dos tokens que
   já existiam. Token novo teria de ser declarado em TRÊS lugares (`:root`, a media query
   de escuro e o seletor de atributo), e esquecer um dos dois blocos escuros produz
   divergência que só aparece na máquina de quem tem o sistema em escuro.
   =================================================================================== */

/* Resumo em pares rótulo/valor. `auto-fill` e não `auto-fit`: com `auto-fit` os três
   itens da tela de confirmação esticariam para um terço da largura cada, e o resumo
   viraria três colunas gigantes de texto curto. */
.carga-resumo {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: 14px 24px;
  margin: 0 0 18px;
}

.carga-resumo-item dt {
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-tertiary);
  margin-bottom: 3px;
}

.carga-resumo-item dd {
  margin: 0;
  font-size: 0.95rem;
  font-weight: 600;
  color: var(--text-title);
}

/* O detalhe vai numa LINHA PRÓPRIA e em peso normal: ele qualifica o número ("por COD
   BTG", "soma da planilha inteira") e, na mesma linha e no mesmo peso, competiria com o
   valor pela atenção — que é justamente o que o número não pode perder. */
.carga-resumo-detalhe {
  display: block;
  font-size: 0.76rem;
  font-weight: 400;
  color: var(--text-secondary);
  margin-top: 2px;
}

.dropzone {
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin-top: 4px;
}

/* O INPUT É ESCONDIDO SEM SAIR DA ORDEM DE FOCO. `display: none` e
   `visibility: hidden` tirariam o campo do alcance do teclado, e a tela ficaria
   operável só no mouse — sem nenhum sintoma visual para quem testa com mouse. */
.dropzone-input {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.dropzone-alvo {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  padding: 28px 20px;
  text-align: center;
  cursor: pointer;
  border: 2px dashed var(--border-strong);
  border-radius: var(--radius-lg);
  background: var(--bg-inset);
  transition: background 0.15s ease, border-color 0.15s ease;
}

.dropzone-alvo:hover {
  border-color: var(--brand-500);
  background: var(--bg-hover);
}

/* O anel de foco fica no ALVO e não no input (que é invisível), senão navegar por teclado
   até o campo não mostraria nada na tela. */
.dropzone-input:focus-visible + .dropzone-alvo {
  outline: 2px solid var(--brand-600);
  outline-offset: 2px;
}

/* Estado de arrasto. Classe posta pelo JS — sem JS ela nunca aparece, e o resto continua
   funcionando pelo clique no label. */
.dropzone-alvo.is-arrastando {
  border-color: var(--brand-600);
  border-style: solid;
  background: var(--sage-100);
}

.dropzone-icone {
  width: 34px;
  height: 34px;
  background: var(--icone-vazio) center / contain no-repeat;
  opacity: 0.8;
}

.dropzone-titulo {
  font-size: 0.98rem;
  font-weight: 600;
  color: var(--text-title);
}

.dropzone-ajuda {
  font-size: 0.8rem;
  color: var(--text-secondary);
  max-width: 46ch;
  line-height: 1.45;
}

/* O nome do arquivo escolhido. Nasce `hidden` e o JS o revela — sem JS o navegador já
   mostra o nome no próprio controle, então não há informação perdida. */
.dropzone-arquivo {
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--brand-700);
  background: var(--sage-100);
  border-radius: var(--radius-pill);
  padding: 3px 12px;
  margin-top: 4px;
}

.dropzone-acoes {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px;
}

.dropzone-aviso {
  font-size: 0.8rem;
  color: var(--text-secondary);
  flex: 1 1 260px;
  line-height: 1.45;
}

@media print {
  .sidebar,
  .topbar,
  .subabas,
  .btn-print,
  .content-header-actions,
  .frescor {
    display: none !important;
  }

  body { background: #FFFFFF; }
  .app-main { margin: 0 !important; }
  .content { max-width: none; padding: 0; }
  .panel {
    break-inside: avoid;
    box-shadow: none;
    border-color: #CCC8BC;
  }
  .data-table th,
  .matriz-tabela thead th { background: #F2F1EB !important; }
}
