/* =============================================================================
   Portal Byteminas — tokens de design e estilos base
   =============================================================================

   Estes custom properties são a fonte da verdade da identidade visual. Quando
   o Tailwind entrar, o `tailwind.config.js` vai referenciá-los em vez de
   duplicar valores — então trocar uma cor aqui continua trocando em todo lugar.

   Três temas: Claro, Escuro e Grafite. Claro por padrão, escuro por
   preferência do sistema, com override manual via `data-theme` no <html>
   (persistido em localStorage por theme.js).

   O tema Marinho foi removido: os dois escuros disputavam o mesmo papel e o
   azul-marinho em tela cheia lia como azul aberto, não como superfície. O
   Grafite ocupa o lugar dele com cinza neutro, sem viés de matiz — e é ele
   que dá o ar sóbrio que o Marinho prometia.
   ========================================================================== */

:root {
  color-scheme: light dark;

  /* --- Superfícies ---------------------------------------------------------
     Três níveis e não mais quatro tons soltos: `--surface` é o papel (cartão,
     tabela, campo), `--surface-2` é o levantado discreto (cabeçalho de tabela,
     hover, blocos dentro de cartão) e `--bg` é o fundo da página. A hierarquia
     é dada pela borda e pelo espaço, não por saltos de luminosidade. */
  --bg: #f5f5f7;
  --surface: #ffffff;
  --surface-2: #fafafa;
  --field: #ffffff;
  --sidebar: #fbfbfd;

  /* Aliases dos nomes antigos — nenhum template precisou mudar por causa de
     cor. `--surface-sunken` era o fundo da página e `--surface-raised` o
     levantado; os dois continuam valendo. */
  --surface-sunken: var(--bg);
  --surface-raised: var(--surface-2);

  /* --- Traços ---
     Duas espessuras de linha: `--hairline` separa dentro de um mesmo bloco
     (linhas de tabela, divisórias de cartão) e `--border` desenha a borda do
     bloco. `--border-strong` é só para controle de formulário, que precisa se
     anunciar como clicável. */
  --hairline: #eeeef1;
  --border: #e6e6ea;
  --border-strong: #d2d2d7;

  /* --- Texto --- */
  --text: #1d1d1f;
  --text-muted: #6e6e73;
  --text-subtle: #8e8e93;
  --text-2: var(--text-muted);
  --text-3: var(--text-subtle);

  /* --- Ação ---
     Azul institucional clareado: mantém a marca azul e passa em contraste
     sobre branco (4,8:1), onde o Deep Blue #002F7A pesava demais para links
     e estados ativos espalhados pela tela. */
  --brand: #1a6be3;
  --brand-hover: #0f57c4;
  --brand-contrast: #ffffff;
  --brand-subtle: #e8f1fd;
  --accent: var(--brand);

  /* Fundo da caixinha da marca. Fica de fora dos blocos de tema escuro de
     propósito: o logo tem fundo próprio na identidade e o B azul-marinho
     precisa de um claro atrás dele. */
  --brand-mark: #f2f7ff;

  /* --- Estados --- */
  --success: #1a7f45;
  --success-subtle: #e6f4ec;
  --warning: #96690a;
  --warning-subtle: #fbf1de;
  --danger: #c9271f;
  --danger-subtle: #fbeceb;

  /* --- Métricas ---
     Raio maior nos blocos (cartão, tabela) e menor nos controles: é o que dá
     o ar de superfície contínua sem arredondar botão a ponto de virar pílula. */
  --radius: 10px;
  --radius-lg: 16px;
  --radius-pill: 999px;

  /* Sombra quase imperceptível: quem separa os planos é a borda; a sombra só
     tira o cartão do fundo. */
  --shadow-sm: 0 1px 2px rgb(0 0 0 / 5%);
  --shadow: 0 1px 2px rgb(0 0 0 / 4%), 0 6px 20px rgb(0 0 0 / 5%);

  /* --- Tipografia ---
     A interface inteira é sans neutra do sistema: nos 13-14px dos rótulos ela
     é a mais legível disponível e não custa download nenhum.

     Rajdhani (--font-display) ficou reservada à marca — o wordmark BYTEMINAS
     e a chamada da tela de entrada. Share Tech Mono (--font-mono) continua com
     o dado técnico: segredo do 2FA, códigos de recuperação, IPs, slugs. */
  --font-display: "Rajdhani", "Segoe UI", system-ui, sans-serif;
  --font-sans: -apple-system, BlinkMacSystemFont, "SF Pro Text", "Segoe UI",
    system-ui, "Helvetica Neue", Helvetica, Arial, sans-serif;
  --font-mono: "Share Tech Mono", ui-monospace, SFMono-Regular, "Cascadia Mono",
    Consolas, monospace;
}

/* Paletas dos temas escuros, com os valores num lugar só.
   ---------------------------------------------------------------------------
   São dois: Escuro (quase-preto levemente frio, o tom do site institucional)
   e Grafite (cinza neutro puro, sem matiz). A diferença entre eles é
   proposital e mensurável: o Escuro tem um resto de azul nas superfícies, o
   Grafite não tem matiz nenhum — é ele que lê como "sóbrio" em vez de "noite".

   Cada paleta é escrita uma vez aqui e apenas referenciada lá embaixo. Isso
   não é preciosismo: com as cores escritas direto nas regras, uma edição já
   rendeu um tema pela metade. Trocar uma cor aqui troca em todo caminho que
   leva até ela. */
:root {
  /* --- Escuro --- */
  --dark-bg: #0e0e11;
  --dark-surface: #17171b;
  --dark-surface-2: #1e1e23;
  --dark-field: #1c1c21;
  --dark-sidebar: #131316;
  --dark-hairline: #232329;
  --dark-border: #2a2a31;
  --dark-border-strong: #3a3a43;

  --dark-text: #f2f2f5;
  --dark-text-muted: #a3a3ad;
  --dark-text-subtle: #7c7c86;

  /* Nos dois escuros o azul de ação sumiria contra o fundo: quem assume é o
     mesmo azul clareado, que mantém a marca e passa em contraste. */
  --dark-brand: #5e9bf5;
  --dark-brand-hover: #85b4f8;
  --dark-brand-contrast: #0b1220;
  --dark-brand-subtle: #14283f;

  --dark-success: #4cc98a;
  --dark-success-subtle: #12291f;
  --dark-warning: #e5b23c;
  --dark-warning-subtle: #2b2313;
  --dark-danger: #ff6b60;
  --dark-danger-subtle: #331917;

  --dark-shadow-sm: 0 1px 2px rgb(0 0 0 / 45%);
  --dark-shadow: 0 1px 2px rgb(0 0 0 / 50%), 0 8px 24px rgb(0 0 0 / 35%);

  /* --- Grafite ---
     Cinzas neutros: nenhum canal domina, então a tela não puxa nem para o
     azul nem para o sépia. O azul aparece só onde há ação. */
  --graf-bg: #1c1c1c;
  --graf-surface: #262626;
  --graf-surface-2: #2e2e2e;
  --graf-field: #2b2b2b;
  --graf-sidebar: #212121;
  --graf-hairline: #333333;
  --graf-border: #393939;
  --graf-border-strong: #4a4a4a;

  --graf-text: #ededed;
  --graf-text-muted: #a8a8a8;
  --graf-text-subtle: #878787;

  --graf-brand: #5b9dff;
  --graf-brand-hover: #7db1ff;
  --graf-brand-contrast: #12161c;
  --graf-brand-subtle: #2f3742;

  --graf-success: #63c58f;
  --graf-success-subtle: #243029;
  --graf-warning: #d9ab55;
  --graf-warning-subtle: #332d20;
  --graf-danger: #f07a70;
  --graf-danger-subtle: #3a2725;

  --graf-shadow-sm: 0 1px 2px rgb(0 0 0 / 40%);
  --graf-shadow: 0 1px 2px rgb(0 0 0 / 45%), 0 8px 24px rgb(0 0 0 / 30%);
}

/* Sem escolha salva, o sistema decide — e no escuro entra o Escuro. O
   `:not([data-theme])` é o que muda com três temas: qualquer escolha explícita
   (inclusive Grafite) tem de tirar a preferência do sistema do caminho.

   O theme.js grava a escolha e resolve o resto antes da primeira pintura;
   esta regra é a rede para quem estiver com JavaScript desligado. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme]) {
    --bg: var(--dark-bg);
    --surface: var(--dark-surface);
    --surface-2: var(--dark-surface-2);
    --field: var(--dark-field);
    --sidebar: var(--dark-sidebar);
    --hairline: var(--dark-hairline);
    --border: var(--dark-border);
    --border-strong: var(--dark-border-strong);

    --text: var(--dark-text);
    --text-muted: var(--dark-text-muted);
    --text-subtle: var(--dark-text-subtle);

    --brand: var(--dark-brand);
    --brand-hover: var(--dark-brand-hover);
    --brand-contrast: var(--dark-brand-contrast);
    --brand-subtle: var(--dark-brand-subtle);

    --success: var(--dark-success);
    --success-subtle: var(--dark-success-subtle);
    --warning: var(--dark-warning);
    --warning-subtle: var(--dark-warning-subtle);
    --danger: var(--dark-danger);
    --danger-subtle: var(--dark-danger-subtle);

    --shadow-sm: var(--dark-shadow-sm);
    --shadow: var(--dark-shadow);
  }
}

/* Escolhas explícitas — depois da media query para vencerem.

   O `color-scheme` vai junto em cada uma. Sem ele o `light dark` do topo
   continuaria deixando o sistema decidir, e quem escolhesse um tema escuro
   com o Windows no claro ganharia barra de rolagem e campos nativos claros
   sobre a página escura. */
:root[data-theme="light"] {
  color-scheme: light;
}

:root[data-theme="dark"],
:root[data-theme="grafite"] {
  color-scheme: dark;
}

:root[data-theme="dark"] {
  --bg: var(--dark-bg);
  --surface: var(--dark-surface);
  --surface-2: var(--dark-surface-2);
  --field: var(--dark-field);
  --sidebar: var(--dark-sidebar);
  --hairline: var(--dark-hairline);
  --border: var(--dark-border);
  --border-strong: var(--dark-border-strong);

  --text: var(--dark-text);
  --text-muted: var(--dark-text-muted);
  --text-subtle: var(--dark-text-subtle);

  --brand: var(--dark-brand);
  --brand-hover: var(--dark-brand-hover);
  --brand-contrast: var(--dark-brand-contrast);
  --brand-subtle: var(--dark-brand-subtle);

  --success: var(--dark-success);
  --success-subtle: var(--dark-success-subtle);
  --warning: var(--dark-warning);
  --warning-subtle: var(--dark-warning-subtle);
  --danger: var(--dark-danger);
  --danger-subtle: var(--dark-danger-subtle);

  --shadow-sm: var(--dark-shadow-sm);
  --shadow: var(--dark-shadow);
}

:root[data-theme="grafite"] {
  --bg: var(--graf-bg);
  --surface: var(--graf-surface);
  --surface-2: var(--graf-surface-2);
  --field: var(--graf-field);
  --sidebar: var(--graf-sidebar);
  --hairline: var(--graf-hairline);
  --border: var(--graf-border);
  --border-strong: var(--graf-border-strong);

  --text: var(--graf-text);
  --text-muted: var(--graf-text-muted);
  --text-subtle: var(--graf-text-subtle);

  --brand: var(--graf-brand);
  --brand-hover: var(--graf-brand-hover);
  --brand-contrast: var(--graf-brand-contrast);
  --brand-subtle: var(--graf-brand-subtle);

  --success: var(--graf-success);
  --success-subtle: var(--graf-success-subtle);
  --warning: var(--graf-warning);
  --warning-subtle: var(--graf-warning-subtle);
  --danger: var(--graf-danger);
  --danger-subtle: var(--graf-danger-subtle);

  --shadow-sm: var(--graf-shadow-sm);
  --shadow: var(--graf-shadow);
}

/* ---------------------------------------------------------------------------
   Reset enxuto
   --------------------------------------------------------------------------- */

*,
*::before,
*::after {
  box-sizing: border-box;
}

body {
  margin: 0;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-sans);
  font-size: 15px;
  line-height: 1.5;
  letter-spacing: -0.005em;
  -webkit-font-smoothing: antialiased;
}

a {
  color: var(--brand);
  text-decoration: none;
}

a:hover {
  color: var(--brand-hover);
  text-decoration: underline;
}

/* Foco sempre visível — acessibilidade e navegação por teclado. */
:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 2px;
  border-radius: 6px;
}

::selection {
  background: var(--brand-subtle);
}

/* Transição só onde muda de estado. Um `*` com transition faria a troca de
   tema animar a página inteira, e o que se vê é um rastro, não um fade. */
a,
button,
summary,
.menu__link,
.sidebar__acao,
.table tbody tr,
.check-list label,
.combo__opcao,
.theme-seg__opt {
  transition:
    background-color 0.18s ease,
    border-color 0.18s ease,
    color 0.18s ease,
    box-shadow 0.18s ease;
}

@media (prefers-reduced-motion: reduce) {
  * {
    transition: none !important;
    animation: none !important;
  }
}

/* ---------------------------------------------------------------------------
   Sistema tipográfico
   ---------------------------------------------------------------------------

   Uma família para tudo que se lê e uma para a marca. Títulos se distinguem
   por tamanho, peso e `letter-spacing` negativo — não por trocar de fonte.
   Quanto maior o corpo, mais fechado o tracking: é o que dá o ar assentado
   dos títulos grandes sem recorrer a uma display condensada. */

h1,
h2,
h3,
h4,
h5,
h6 {
  font-family: var(--font-sans);
  font-weight: 600;
  line-height: 1.2;
  letter-spacing: -0.02em;
}

/* ---------------------------------------------------------------------------
   Layout
   --------------------------------------------------------------------------- */

.container {
  width: 100%;
  max-width: 64rem;
  margin-inline: auto;
  padding-inline: 1.25rem;
}

.container--wide {
  max-width: 84rem;
}

/* A marca é o único lugar da interface onde a display aparece. */
.brand {
  display: inline-flex;
  align-items: center;
  gap: 0.625rem;
  font-family: var(--font-display);
  font-size: 1.125rem;
  font-weight: 700;
  /* Caixa alta como na prancha. O respiro entre letras não é enfeite: em
     caixa alta as hastes de Rajdhani ficam paralelas e sem ele "BYTEMINAS"
     vira um bloco só. */
  text-transform: uppercase;
  letter-spacing: 0.06em;
  line-height: 1;
  color: var(--text);
}

.brand:hover {
  text-decoration: none;
  color: var(--text);
  opacity: 0.8;
}

/* O símbolo entra por background-image, não por <img>: a marca é decorativa
   ao lado do nome, e assim quem lê por leitor de tela ouve "Byteminas" uma
   vez só.

   A caixinha é clara nos três temas (--brand-mark). Clarear o próprio logo
   para o tema escuro foi tentado antes e o B ficava lavado: o degradê dele
   tem seis paradas, e subir todas de tom achata o relevo que é a graça da
   marca. Melhor dar um claro atrás e deixar o logo intacto. */
.brand__mark {
  flex: 0 0 auto;
  width: 1.875rem;
  height: 1.875rem;
  border: 1px solid var(--border);
  border-radius: 8px;
  background-color: var(--brand-mark);
  background-image: url("../img/bm-logo.3a44f34d21c7.svg");
  background-repeat: no-repeat;
  background-position: center;
  /* Largura, e não altura: o logo é deitado (1,95:1) e é a largura que
     encosta nas bordas primeiro. */
  background-size: 1.25rem auto;
}

/* Casca de duas colunas: menu lateral + conteúdo.
   Logado, a casca é travada na altura da janela e o scroll acontece DENTRO do
   <main>, não no documento. É isso que permite ao iframe do relatório ocupar
   exatamente a altura que sobra, sem depender de `vh` chutado — e o menu fica
   sempre à vista, sem `position: sticky`. */
body:has(.sidebar) {
  height: 100dvh;
  overflow: hidden;
}

.shell {
  flex: 1;
  min-height: 0;
  display: flex;
}

/* Largura fixa, e não `max-content`: a largura automática media o item mais
   longo, e o item ativo fica em negrito — alguns pixels mais largo que ele
   mesmo em peso normal. Bastava trocar de relatório para o menu mudar de
   largura e a página inteira se deslocar junto, porque o iframe ocupa o que
   sobra. 250px acomoda o ícone, o rótulo e o respiro do item ativo. */
.sidebar {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  width: 15.625rem;
  background: var(--sidebar);
  /* A "moldura" que separa menu e conteúdo — o mesmo papel que a borda do
     quadro do Power BI cumpria antes, agora no lugar certo. */
  border-right: 1px solid var(--border);
  overflow: hidden;
}

/* A coluna inteira rola como um bloco só, e o bloco da conta fica ancorado no
   fim dela por `margin-top: auto`. A alternativa — nav com scroll próprio e
   conta fixa embaixo — colapsava a nav para poucos pixels em janela baixa,
   porque o bloco da conta é alto e não encolhe. */
.sidebar__nav {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  overflow-y: auto;
  padding: 0 0.625rem 0.75rem;
}

.site-main {
  flex: 1;
  min-width: 0;
  padding: 2.25rem 2rem 4rem;
}

body:has(.sidebar) .site-main {
  overflow-y: auto;
}

/* Sem coluna de leitura: o conteúdo ocupa a largura toda da área ao lado do
   menu, em toda tela (pedido do Luiz, 2026-09-15 — as laterais vazias do
   desktop eram área útil perdida). Havia um teto de 72,5rem centralizado. */

/* Página cheia (relatório incorporado): sem padding nenhum e sem scroll
   próprio — o conteúdo encosta na borda do menu e vai até o fim da janela. A
   moldura já é a borda do menu; uma segunda faixa em volta só tira área útil. */
.site-main--cheio {
  display: flex;
  flex-direction: column;
  min-height: 0;
  padding: 0;
}

/* Mensagens e avisos ainda precisam de respiro — só eles. */
.site-main--cheio > .messages,
.site-main--cheio > .alert {
  margin: 0.75rem 0.75rem 0;
}

body:has(.sidebar) .site-main--cheio {
  overflow: hidden;
}

/* --- Marca, empresa e conta, no menu --- */

.sidebar__marca {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  min-height: 3.5rem;
  padding: 0.75rem 1rem;
  border-bottom: 1px solid var(--hairline);
}

.sidebar__empresa {
  flex: 0 0 auto;
  margin: 0;
  padding: 0.875rem 1rem 0.75rem;
  color: var(--text);
  font-size: 0.875rem;
  font-weight: 600;
  letter-spacing: -0.01em;
  overflow-wrap: anywhere;
}

/* Rótulo de seção do menu. Existe para dar nome ao bloco sem gastar uma linha
   de peso — daí o corpo pequeno em caixa alta e a cor mais apagada da escala. */
.sidebar__secao {
  margin: 0;
  padding: 0.875rem 1rem 0.125rem;
  color: var(--text-subtle);
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.sidebar__conta {
  flex: 0 0 auto;
  /* Empurra o bloco para o fim da coluna quando sobra altura, e o deixa
     seguir o fluxo (rolando junto) quando não sobra. */
  margin-top: auto;
  padding: 0.75rem 0.625rem;
  border-top: 1px solid var(--hairline);
}

.sidebar__conta form {
  margin: 0;
}

/* Identidade de quem entrou: iniciais, nome e e-mail. O e-mail estava só no
   `title` antes — invisível para quem não passa o mouse, e é o dado que
   confirma em qual conta a pessoa está. */
.sidebar__perfil {
  display: flex;
  align-items: center;
  gap: 0.625rem;
  padding: 0.375rem 0.5rem 0.625rem;
}

.sidebar__avatar {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 1.875rem;
  height: 1.875rem;
  border-radius: 50%;
  background: var(--brand-subtle);
  color: var(--brand);
  font-size: 0.75rem;
  font-weight: 600;
  text-transform: uppercase;
}

.sidebar__usuario {
  min-width: 0;
  margin: 0;
}

.sidebar__usuario strong {
  display: block;
  font-size: 0.8125rem;
  font-weight: 600;
  color: var(--text);
  overflow-wrap: anywhere;
}

.sidebar__usuario span {
  display: block;
  font-size: 0.6875rem;
  color: var(--text-subtle);
  overflow-wrap: anywhere;
}

/* Tempo até a sessão cair (`sessao.js`). Números tabulares: o relógio muda
   todo segundo e não pode tremer a linha. */
.sidebar__sessao {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.125rem 0.5rem;
  margin-top: 0.25rem;
  font-size: 0.6875rem;
  font-variant-numeric: tabular-nums;
  color: var(--text-subtle);
}

.sidebar__sessao span {
  display: inline;
}

/* Últimos 5 minutos: a cor avisa antes de a sessão cair. */
.sidebar__sessao--aviso {
  font-weight: 600;
  color: var(--warning);
}

.sidebar__sessao-renovar {
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  font-weight: 600;
  color: var(--brand);
  text-decoration: underline;
  cursor: pointer;
}

/* 36px de alvo, e não 28: é o piso confortável para um item de menu tocado
   no celular, e no desktop o respiro extra é o que separa uma lista de links
   de uma pilha de texto. */
.sidebar__acao {
  display: flex;
  align-items: center;
  gap: 0.625rem;
  width: 100%;
  min-height: 2.25rem;
  padding: 0.5rem 0.625rem;
  border: 0;
  border-radius: var(--radius);
  background: transparent;
  color: var(--text-muted);
  font: inherit;
  font-size: 0.84375rem;
  text-align: left;
  cursor: pointer;
}

.sidebar__acao:hover {
  background: var(--surface-2);
  color: var(--text);
  text-decoration: none;
}

.sidebar__acao--sair {
  color: var(--danger);
  font-weight: 600;
}

.sidebar__acao--sair:hover {
  background: var(--danger-subtle);
  color: var(--danger);
}

.sidebar__creditos {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.125rem;
  margin: 0.875rem 0 0.125rem;
  padding-inline: 0.75rem;
  color: var(--text-subtle);
  font-size: 0.6875rem;
  text-align: center;
  overflow-wrap: anywhere;
}

.sidebar__creditos a {
  color: var(--text-subtle);
}

.sidebar__creditos a:hover {
  color: var(--brand);
}

/* --- Seletor de tema ---

   Segmented control em vez do botão que ciclava. Com três opções, um botão
   único obriga a pessoa a passar pelo tema que não quer para chegar no que
   quer — e o rótulo tinha de explicar em qual dos dois escuros ela estava.
   Aqui os três estados são visíveis e um clique basta.

   Quem tiver JavaScript desligado não vê os botões marcados, mas eles não são
   a única forma de ter um tema: sem escolha salva o sistema decide. */
.theme-seg {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 2px;
  padding: 2px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface-2);
}

.theme-seg__opt {
  min-height: 2rem;
  padding: 0.375rem 0.5rem;
  border: 0;
  border-radius: calc(var(--radius) - 4px);
  background: transparent;
  color: var(--text-subtle);
  font: inherit;
  font-size: 0.78125rem;
  font-weight: 600;
  cursor: pointer;
}

.theme-seg__opt:hover {
  color: var(--text-muted);
}

.theme-seg__opt[aria-pressed="true"] {
  background: var(--surface);
  color: var(--text);
  box-shadow: var(--shadow-sm);
}

/* O botão que abre o menu no celular. No computador a coluna está sempre à
   vista, e ele não existe. */
.sidebar__alternar {
  display: none;
}

.sidebar__alternar svg {
  width: 1.125rem;
  height: 1.125rem;
}

.sidebar__alternar-fechar,
.sidebar[data-menu-aberto] .sidebar__alternar-abrir {
  display: none;
}

.sidebar[data-menu-aberto] .sidebar__alternar-fechar {
  display: block;
}

/* Abaixo de 60rem a casca volta ao fluxo normal do documento: numa tela
   estreita, travar a altura só criaria dois scrolls concorrentes.

   E a coluna do menu vira gaveta. Empilhada em cima do conteúdo, ela ocupava
   a primeira tela inteira do celular, e a página só começava depois de uma
   rolagem. Entre três desenhos lado a lado, o Luiz escolheu o botão flutuante
   (2026-09-17): sem faixa no topo — como no computador, o conteúdo começa no
   primeiro pixel — e o botão no canto de baixo, onde o polegar alcança. A
   gaveta é a mesma coluna: marca, empresa, menu e conta. */
@media (max-width: 60rem) {
  body:has(.sidebar) {
    height: auto;
    overflow: visible;
  }

  .shell {
    flex-direction: column;
  }

  /* Fechada, a coluna não ocupa espaço: tudo dentro dela é fixo na tela. */
  .sidebar {
    width: auto;
    border-right: 0;
    overflow: visible;
  }

  .sidebar__marca,
  .sidebar__nav {
    position: fixed;
    left: 0;
    z-index: 41;
    width: min(20rem, 86vw);
    background: var(--sidebar);
    border-right: 1px solid var(--border);
    transform: translateX(-100%);
    visibility: hidden;
    transition: transform 0.2s ease, visibility 0.2s;
  }

  .sidebar__marca {
    top: 0;
    height: 3.5rem;
  }

  .sidebar__nav {
    top: 3.5rem;
    bottom: 0;
  }

  .sidebar[data-menu-aberto] .sidebar__marca,
  .sidebar[data-menu-aberto] .sidebar__nav {
    transform: none;
    visibility: visible;
  }

  /* O fundo escurecido é do próprio aside, e tocar nele fecha (menu.js). */
  .sidebar[data-menu-aberto]::after {
    content: "";
    position: fixed;
    inset: 0;
    z-index: 40;
    background: rgb(0 0 0 / 40%);
  }

  body:has(.sidebar[data-menu-aberto]) {
    overflow: hidden;
  }

  .sidebar__alternar {
    position: fixed;
    right: 1rem;
    bottom: calc(1rem + env(safe-area-inset-bottom));
    z-index: 42;
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    min-height: 3rem;
    padding: 0 1.25rem 0 1rem;
    border: 0;
    border-radius: var(--radius-pill);
    background: var(--text);
    color: var(--bg);
    box-shadow: 0 6px 20px rgb(0 0 0 / 25%);
    font: inherit;
    font-size: 0.875rem;
    font-weight: 600;
    cursor: pointer;
  }

  /* Os últimos 5 minutos da sessão: o aviso mora na gaveta, que no celular
     vive fechada. O botão toma a cor dele (sessao.js), para ninguém perder o
     que digitou. */
  .sidebar__alternar--aviso {
    background: var(--warning);
  }

  /* A folga de baixo é a do botão: o fim da página rola para cima dele. */
  .site-main {
    padding: 1.5rem 1.125rem 5.5rem;
  }

  body:has(.sidebar) .site-main,
  body:has(.sidebar) .site-main--cheio {
    overflow: visible;
  }
}

/* --- Menu lateral --- */

.menu__list,
.menu__sublist {
  list-style: none;
  margin: 0;
  padding: 0;
}

.menu__item + .menu__item {
  margin-top: 2px;
}

.menu__item--separado {
  margin-top: 0.75rem;
  padding-top: 0.75rem;
  border-top: 1px solid var(--hairline);
}

/* O grupo é um <summary>: some o marcador nativo (que varia entre
   navegadores) e entra a seta própria, girada por CSS conforme o estado. */
.menu__group {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  min-height: 2.375rem;
  padding: 0.5625rem 0.625rem;
  border-radius: var(--radius);
  color: var(--text-muted);
  font-size: 0.875rem;
  font-weight: 500;
  letter-spacing: -0.01em;
  cursor: pointer;
  list-style: none;
}

.menu__group::-webkit-details-marker {
  display: none;
}

/* Ícone e título andam juntos de um lado; a seta fica no outro. */
.menu__rotulo {
  display: flex;
  align-items: center;
  gap: 0.625rem;
  min-width: 0;
}

/* Grupo era rótulo de seção em caixa alta miúda. Agora que tem ícone e mora
   ao lado de itens em caixa normal, ele se lê como o que é: algo que abre. */

/* Portal e Gestão são começos de caminho — o mesmo corpo, com mais peso. */
.menu__group--topo {
  font-weight: 600;
}

/* Grupo da empresa acompanha o corpo dos irmãos dentro do Portal. */
.menu__sublist .menu__group {
  min-height: 2.25rem;
  font-size: 0.84375rem;
}

.menu__group:hover {
  background: var(--surface-2);
  color: var(--text-muted);
}

.menu__group::after {
  content: "";
  flex: 0 0 auto;
  width: 0.375rem;
  height: 0.375rem;
  border-right: 1.5px solid currentColor;
  border-bottom: 1.5px solid currentColor;
  /* Fechado aponta para a direita; aberto, para baixo. */
  transform: rotate(-45deg);
  transition: transform 0.18s ease;
}

.menu__grupo[open] > .menu__group::after {
  transform: rotate(45deg);
}

.menu__sublist {
  margin: 2px 0 0.25rem 0.75rem;
  padding-left: 0.625rem;
  border-left: 1px solid var(--hairline);
}

/* Dentro do Portal a árvore da empresa já começa um nível adentro; o segundo
   nível recua menos, senão o título perde metade da largura da coluna. */
.menu__sublist .menu__sublist {
  margin-left: 0.4375rem;
  padding-left: 0.5rem;
}

.menu__link {
  display: flex;
  align-items: center;
  gap: 0.625rem;
  min-height: 2.375rem;
  padding: 0.5625rem 0.625rem;
  border-radius: var(--radius);
  color: var(--text-muted);
  font-size: 0.875rem;
}

/* Dentro de um grupo o item já está indentado e sob uma linha-guia: pode ser
   um passo menor sem perder o alvo de toque. */
.menu__sublist .menu__link {
  min-height: 2.25rem;
  font-size: 0.84375rem;
}

.menu__link:hover {
  background: var(--surface-2);
  color: var(--text);
  text-decoration: none;
}

.menu__link--ativo {
  background: var(--brand-subtle);
  color: var(--brand);
  font-weight: 600;
}

/* Ícone do item de menu. O SVG vem inline no template (Lucide), com
   `stroke: currentColor` — então ele acompanha a cor do estado sem regra
   extra: apagado no repouso, azul no ativo. */
.menu__icone {
  flex: 0 0 auto;
  width: 17px;
  height: 17px;
  opacity: 0.6;
}

.menu__link--ativo .menu__icone,
.menu__link:hover .menu__icone {
  opacity: 1;
}

/* --- Cabeçalho de página --- */

.page-header {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: 0.75rem 1.25rem;
  margin-bottom: 1.5rem;
}

.page-header__title {
  margin: 0;
  font-size: 1.75rem;
  font-weight: 600;
  letter-spacing: -0.024em;
}

.page-header .muted {
  margin: 0;
  font-size: 0.9375rem;
}

/* Na página de relatório o título só orienta — quem manda é o quadro abaixo. */
.page-header--compacto {
  margin-bottom: 0.5rem;
  padding-inline: 0.25rem;
}

.page-header--compacto .page-header__title {
  font-size: 1.0625rem;
  letter-spacing: -0.014em;
}

/* --- Barra de ferramentas ---

   Os filtros passaram a morar num quadro próprio, e não soltos sobre o fundo:
   viraram um bloco só, que se lê como "o recorte da tela" antes de a pessoa
   chegar nos dados. */
.toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.625rem;
  margin-bottom: 1.25rem;
  padding: 0.75rem;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 14px;
  box-shadow: var(--shadow-sm);
}

.toolbar .field__input {
  width: auto;
  min-width: 15rem;
  flex: 1 1 15rem;
  min-height: 2.5rem;
  padding: 0.5625rem 0.8125rem;
}

/* Com busca, quem participa do flex é o invólucro; o campo dentro dele volta a
   ocupar a largura toda, senão encolhe para o tamanho do texto. */
.toolbar .combo {
  min-width: 15rem;
  flex: 1 1 15rem;
}

.toolbar .combo .field__input {
  width: 100%;
  min-width: 0;
}

.toolbar .field__label {
  margin: 0;
  padding-left: 0.25rem;
  font-size: 0.8125rem;
  color: var(--text-muted);
}

.toolbar .button {
  min-height: 2.5rem;
  padding: 0.5625rem 1rem;
}

/* Empurra o que vier depois para a direita da barra. */
.toolbar__separador {
  flex: 1 1 0;
  min-width: 0;
}

/* --- Tabelas --- */

.table-wrapper {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow);
  overflow-x: auto;
}

/* Dentro de um cartão a tabela não repete a moldura: o cartão já é o bloco. */
.card > .table-wrapper {
  border: 0;
  border-radius: 0;
  box-shadow: none;
}

.table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.875rem;
}

/* Densidade compacta: mais linhas na tela sem encostar o texto na régua. */
.table th,
.table td {
  padding: 0.625rem 1.25rem;
  text-align: left;
  border-bottom: 1px solid var(--hairline);
  vertical-align: middle;
}

.table thead th {
  background: var(--surface-2);
  border-bottom: 1px solid var(--border);
  color: var(--text-subtle);
  font-size: 0.71875rem;
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  white-space: nowrap;
}

.table tbody tr:last-child td {
  border-bottom: 0;
}

.table tbody tr:hover {
  background: var(--surface-2);
}

.table strong {
  font-weight: 600;
}

/* Prefixo `.table` para vencer o `text-align: left` de `.table td`, que é
   mais específico; sozinha a classe perdia e os números saíam à esquerda. */
.table .table__num {
  text-align: right;
  font-variant-numeric: tabular-nums;
}

.table__destino {
  max-width: 18rem;
}

.table__actions {
  white-space: nowrap;
  text-align: right;
}

.table__actions a,
.table__actions form {
  display: inline-block;
  font-size: 0.84375rem;
  font-weight: 500;
}

.table__actions a + a {
  margin-left: 0.875rem;
}

.table__vazio {
  padding-block: 2.5rem;
  color: var(--text-subtle);
  text-align: center;
}

.link-danger,
.link-danger:hover {
  color: var(--danger);
}

/* --- Pills de status --- */

.pill {
  display: inline-flex;
  align-items: center;
  padding: 0.25rem 0.625rem;
  border-radius: var(--radius-pill);
  font-size: 0.78125rem;
  font-weight: 600;
  white-space: nowrap;
  background: var(--surface-2);
  border: 1px solid var(--border);
  color: var(--text-muted);
}

/* Fundo de token, e não `color-mix` sobre a cor do estado: a mistura com
   transparente muda de resultado conforme a superfície atrás, e nas linhas
   de tabela em hover a pílula mudava de cor junto. */
.pill--active {
  background: var(--success-subtle);
  border-color: transparent;
  color: var(--success);
}

.pill--inactive,
.pill--pending {
  background: var(--warning-subtle);
  border-color: transparent;
  color: var(--warning);
}

.pill--suspended {
  background: var(--danger-subtle);
  border-color: transparent;
  color: var(--danger);
}

.pill--restrito {
  background: var(--brand-subtle);
  border-color: transparent;
  color: var(--brand);
}

/* --- Indicadores numéricos --- */

.stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(11.875rem, 1fr));
  gap: 0.875rem;
  margin-bottom: 1.25rem;
}

/* Empilhamento de quadros com respiro uniforme. `.card` não tem margem própria
   (nem deve: em formulário ele é único na tela), então numa tela de painel os
   quadros ficavam encostados. Aqui o espaço é do contêiner, uma vez só, e
   nenhum bloco precisa saber quem vem antes ou depois. */
.pilha {
  display: grid;
  /* `minmax(0, …)`: sem ele a coluna cresce até a tabela mais larga e a página
     inteira rola de lado no celular; assim a tabela rola dentro do cartão. */
  grid-template-columns: minmax(0, 1fr);
  gap: 1.25rem;
}

/* Dentro da pilha o espaçamento é o gap; a margem própria somaria. */
.pilha > .stats {
  margin-bottom: 0;
}

.stat {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  padding: 1.375rem;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
}

/* O rótulo vem antes do número na leitura, então vem antes no DOM também —
   `column-reverse` ou `order` seriam uma ordem visual que o leitor de tela
   não recebe. */
.stat__label {
  color: var(--text-subtle);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  text-transform: uppercase;
}

.stat__value {
  font-size: 2.25rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.035em;
  line-height: 1;
}

/* Indicador que também é porta: o número diz quanto, o clique leva à lista.
   Sem cor de link nem sublinhado — o cartão inteiro é o alvo, e a borda que
   acende no hover já diz isso sem pintar o texto de azul. */
a.stat {
  color: inherit;
  text-decoration: none;
}

a.stat:hover {
  border-color: var(--brand);
}

a.stat:hover .stat__value {
  color: var(--brand);
}

/* Data com hora não cabe no corpo de 2.25rem, e o que se quer dela é ler. */
.stat__value--data {
  font-size: 1.375rem;
  letter-spacing: -0.02em;
}

/* Indicador que é estado, e não número: a etiqueta e, discreta ao lado, a
   ação que muda esse estado. */
.stat__estado {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  min-height: 2.25rem;
}

.stat__estado a {
  color: var(--text-subtle);
  font-size: 0.8125rem;
  text-decoration: none;
}

.stat__estado a:hover {
  color: var(--brand);
  text-decoration: underline;
}

/* --- Atalhos --- Retomada do que já foi aberto: título e quando foi. */

.atalhos {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(11.25rem, 1fr));
  gap: 0.75rem;
}

.atalho {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  padding: 0.875rem 1rem;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  color: inherit;
  text-decoration: none;
}

.atalho:hover {
  border-color: var(--brand);
  color: var(--brand);
}

.atalho__titulo {
  font-weight: 600;
  font-size: 0.9375rem;
}

.atalho__quando {
  color: var(--text-subtle);
  font-size: 0.78125rem;
}

/* Linha de contexto abaixo do número: variação, denominador, o que for. */
.stat__nota {
  color: var(--text-subtle);
  font-size: 0.8125rem;
}

.stat__nota--positiva {
  color: var(--success);
  font-weight: 500;
}

.stat__nota--atencao {
  color: var(--warning);
  font-weight: 500;
}

/* --- Formulários e mensagens --- */

.card--form {
  max-width: 47.5rem;
}

.form-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.625rem;
  margin-top: 1.625rem;
  padding-top: 1.375rem;
  border-top: 1px solid var(--hairline);
}

/* Ação destrutiva encostada na direita: separada no espaço das ações que a
   pessoa veio fazer, para não ser clicada por vizinhança. */
.form-actions__separador {
  flex: 1 1 0;
  min-width: 0;
}

.field__help {
  margin: 0.4375rem 0 0;
  color: var(--text-subtle);
  font-size: 0.78125rem;
}

.field__req {
  color: var(--danger);
}

.messages {
  margin-bottom: 1.25rem;
}

.paginacao {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  margin-top: 1rem;
  font-size: 0.8125rem;
}

/* Colada no rodapé da tabela, a paginação deixa de ser um bloco solto e passa
   a pertencer ao quadro que ela pagina. A tabela perde o arredondado de baixo
   junto — senão os cantos curvos dela ficavam sobre os cantos retos da faixa. */
.table-wrapper:has(+ .paginacao) {
  border-bottom-left-radius: 0;
  border-bottom-right-radius: 0;
}

.table-wrapper + .paginacao {
  margin-top: -1px;
  padding: 0.875rem 1.25rem;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 0 0 var(--radius-lg) var(--radius-lg);
}

.paginacao .button {
  min-height: 2.25rem;
  padding: 0.4375rem 0.875rem;
  font-size: 0.8125rem;
  font-weight: 500;
}

/* --- Lista de checkboxes (seleção de menus etc.) --- */

.check-list {
  display: grid;
  gap: 2px;
  max-height: 14.375rem;
  overflow-y: auto;
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 0.625rem;
  background: var(--surface-2);
}

.check-list label {
  display: flex;
  align-items: center;
  gap: 0.625rem;
  min-height: 2.5rem;
  padding: 0.5625rem 0.625rem;
  border-radius: var(--radius);
  font-size: 0.875rem;
  font-weight: 400;
  color: var(--text);
  cursor: pointer;
}

.check-list label:hover {
  background: var(--surface);
}

.check-list input[type="checkbox"] {
  accent-color: var(--brand);
  flex: 0 0 auto;
  width: 1.0625rem;
  height: 1.0625rem;
}

/* Perfis de acesso (26/09): a lista inteira à vista, agrupada por módulo. Com
   umas vinte e cinco seções, a caixa com rolagem dos menus esconderia quase
   tudo. `div.`: o Django repete a classe nas caixinhas. */
div.check-list--inteira {
  max-height: none;
  overflow: visible;
  gap: 0.75rem;
}
div.check-list--inteira > div {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(13rem, 1fr));
  gap: 2px;
}
div.check-list--inteira > div > label:first-child {
  grid-column: 1 / -1;
  min-height: 0;
  font-weight: 600;
  cursor: default;
}
div.check-list--inteira > div > label:first-child:hover {
  background: none;
}

/* --- Liga/desliga ---
   Todo sim/não do portal é o interruptor do iPhone, com as mesmas cores
   (pedidos do Luiz, 2026-09-13 e 2026-09-15): o campo de formulário da Gestão
   (`.field`) e dos módulos (`.ui-campo`), e o filtro que se liga à parte
   (`.liga-desliga`). Caixinha fica só onde é seleção, não estado: linhas da
   lista do mês, a grade do simulador, a lista de menus. Continua sendo um
   checkbox — envia, valida e é lido do mesmo jeito. */
.field > input[type="checkbox"],
.ui-campo > input[type="checkbox"],
input[type="checkbox"].liga-desliga {
  position: relative;
  flex: none;
  align-self: flex-start;
  width: 46px;
  height: 28px;
  margin: 0;
  border-radius: 999px;
  background: #e9e9eb;
  appearance: none;
  vertical-align: middle;
  cursor: pointer;
  transition: background-color 0.2s ease;
}

.field > input[type="checkbox"]::before,
.ui-campo > input[type="checkbox"]::before,
input[type="checkbox"].liga-desliga::before {
  content: "";
  position: absolute;
  top: 2px;
  left: 2px;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: #fff;
  box-shadow:
    0 3px 8px rgb(0 0 0 / 15%),
    0 1px 1px rgb(0 0 0 / 16%);
  transition: transform 0.2s ease;
}

.field > input[type="checkbox"]:checked,
.ui-campo > input[type="checkbox"]:checked,
input[type="checkbox"].liga-desliga:checked {
  background: #34c759;
}

.field > input[type="checkbox"]:checked::before,
.ui-campo > input[type="checkbox"]:checked::before,
input[type="checkbox"].liga-desliga:checked::before {
  transform: translateX(18px);
}

.field > input[type="checkbox"]:focus-visible,
.ui-campo > input[type="checkbox"]:focus-visible,
input[type="checkbox"].liga-desliga:focus-visible {
  outline: 2px solid #34c759;
  outline-offset: 2px;
}

:root[data-theme="dark"] :is(.field, .ui-campo) > input[type="checkbox"]:not(:checked),
:root[data-theme="grafite"] :is(.field, .ui-campo) > input[type="checkbox"]:not(:checked),
:root[data-theme="dark"] input[type="checkbox"].liga-desliga:not(:checked),
:root[data-theme="grafite"] input[type="checkbox"].liga-desliga:not(:checked) {
  background: #39393d;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme]) :is(.field, .ui-campo) > input[type="checkbox"]:not(:checked),
  :root:not([data-theme]) input[type="checkbox"].liga-desliga:not(:checked) {
    background: #39393d;
  }
}

/* --- Gráfico de barras (CSS puro, sem biblioteca externa) --- */

.grafico {
  display: flex;
  align-items: flex-end;
  gap: 0.3125rem;
  height: 9.375rem;
  overflow-x: auto;
}

.grafico__coluna {
  flex: 1 1 0;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  align-items: center;
  height: 100%;
  min-width: 1rem;
  gap: 0.5rem;
}

/* Barra apagada por padrão e cheia só no pico: com todas na mesma força o
   gráfico vira uma parede azul e o olho não acha o dia que importa. */
.grafico__barra {
  width: 100%;
  min-height: 3px;
  border-radius: 5px 5px 2px 2px;
  background: color-mix(in srgb, var(--brand) 34%, transparent);
}

.grafico__barra--pico {
  background: var(--brand);
}

.grafico__rotulo {
  font-size: 0.65625rem;
  color: var(--text-subtle);
  white-space: nowrap;
}

/* --- Verificação em duas etapas --- */

.auth--largo {
  max-width: 38rem;
}

.passos {
  margin: 0;
  padding-left: 1.25rem;
  display: grid;
  gap: 1.5rem;
}

.passos li {
  padding-left: 0.25rem;
}

.passos__form {
  margin-top: 0.75rem;
}

.qr {
  display: flex;
  justify-content: center;
  margin: 1rem 0 0.5rem;
  padding: 1rem;
  /* Fundo branco fixo: leitor de QR precisa do contraste padrão, e nos temas
     escuros um SVG preto sobre fundo escuro simplesmente não é lido. */
  background: #ffffff;
  border-radius: var(--radius);
}

.qr svg {
  width: 12rem;
  height: 12rem;
}

.qr__manual {
  margin-top: 0.5rem;
  font-size: 0.875rem;
}

.qr__manual summary {
  cursor: pointer;
  color: var(--text-muted);
}

.qr__segredo {
  display: inline-block;
  margin-top: 0.375rem;
  font-size: 0.9375rem;
  letter-spacing: 0.08em;
  word-break: break-all;
}

.codigos {
  list-style: none;
  margin: 0 0 1rem;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(8.75rem, 1fr));
  gap: 0.5rem;
}

.codigos code {
  display: block;
  text-align: center;
  padding: 0.6875rem;
  font-size: 0.875rem;
  letter-spacing: 0.08em;
}

/* --- Páginas de erro --- */

.erro {
  text-align: center;
}

.erro__codigo {
  margin: 0 0 0.625rem;
  font-size: 3.25rem;
  font-weight: 600;
  line-height: 1;
  color: var(--text-subtle);
  letter-spacing: -0.04em;
  font-variant-numeric: tabular-nums;
}

/* --- Placeholder de relatório --- */

.placeholder {
  text-align: center;
  padding-block: 3rem;
}

.placeholder__mark {
  font-size: 2.5rem;
  color: var(--text-subtle);
  line-height: 1;
  margin-bottom: 0.75rem;
}

.relatorio-container {
  min-height: 70vh;
}

/* O relatório ocupa tudo que sobra da casca: sem cartão, sem borda e sem
   padding em volta. A moldura visual já é a borda do menu — repeti-la aqui só
   encolheria a área útil, que é justamente o que o usuário veio ver. */
.relatorio-quadro {
  flex: 1;
  min-height: 0;
  overflow: hidden;
}

/* O iframe do powerbi-client nasce sem classe: borda e piso de altura do
   mobile vêm por aqui. */
.relatorio-frame,
.relatorio-quadro > iframe {
  display: block;
  width: 100%;
  height: 100%;
  /* Piso para quando não houver altura definida no pai — o layout empilhado
     do mobile, onde a casca volta ao fluxo normal do documento. */
  min-height: 32rem;
  border: 0;
}

@media (max-width: 60rem) {
  .relatorio-frame,
  .relatorio-quadro > iframe {
    height: 75vh;
  }
}

.site-footer {
  background: transparent;
  border-top: 0;
  padding-block: 1.5rem;
  color: var(--text-subtle);
  font-size: 0.75rem;
}

.site-footer__inner {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 1rem;
  align-items: center;
  justify-content: center;
}

.site-footer a {
  color: var(--text-subtle);
}

.site-footer a:hover {
  color: var(--brand);
}

/* ---------------------------------------------------------------------------
   Componentes
   --------------------------------------------------------------------------- */

.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow);
  padding: 1.625rem;
}

.card__title {
  margin: 0 0 0.25rem;
  font-size: 1.125rem;
  font-weight: 600;
  letter-spacing: -0.018em;
}

/* Título de cartão que é o título da tela (login, erro) pede outro corpo. */
.auth .card__title {
  font-size: 1.625rem;
  letter-spacing: -0.022em;
}

.card__lead {
  margin: 0 0 1.125rem;
  color: var(--text-muted);
  font-size: 0.875rem;
  text-wrap: pretty;
}

.auth .card__lead {
  margin-bottom: 1.625rem;
  font-size: 0.9375rem;
}

.badge {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  padding: 0.25rem 0.625rem;
  border-radius: var(--radius-pill);
  background: var(--brand-subtle);
  color: var(--brand);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  text-transform: uppercase;
}

.status-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 0;
}

.status-list li {
  display: flex;
  align-items: baseline;
  gap: 0.6875rem;
  padding: 0.75rem 0;
  border-bottom: 1px solid var(--hairline);
}

.status-list li:last-child {
  border-bottom: 0;
}

.status-list__marker {
  flex: none;
  width: 1.25rem;
  color: var(--success);
  font-weight: 700;
}

.status-list__marker--pending {
  color: var(--text-subtle);
}

.muted {
  color: var(--text-muted);
}

code {
  font-family: var(--font-mono);
  font-size: 0.8125rem;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 0.125rem 0.4375rem;
  color: var(--text-muted);
}

/* --- Autenticação --- */

.auth {
  max-width: 25rem;
  margin-inline: auto;
}

.auth .card {
  padding: 2rem;
  border-radius: 18px;
}

.auth__note {
  margin: 1.375rem 0 0;
  padding-top: 1.125rem;
  border-top: 1px solid var(--hairline);
  color: var(--text-subtle);
  font-size: 0.8125rem;
}

/* Sem cabeçalho, o cartão sozinho encostado no topo fica órfão: nas telas de
   entrada o <main> centraliza na altura que sobrar entre topo e rodapé.
   Só aqui — nas telas internas o conteúdo começa no topo, como sempre. */
.site-main--auth {
  display: flex;
  flex-direction: column;
  justify-content: center;
}

/* Telas como a de erro e a de ativação do 2FA também aparecem para quem já
   está dentro. Aí existe menu ao lado, a tela deixa de ser porta de entrada e
   o conteúdo volta a começar no topo, como no resto do portal. */
body:has(.sidebar) .site-main--auth {
  justify-content: flex-start;
}

/* A marca acima do cartão, e não dentro dele: assim ela pertence à página e
   o cartão continua sendo só o formulário. */
.auth--marca {
  text-align: center;
}

/* Logo e chamada ficaram fora do redesign por decisão do Luiz: a marca grande
   na porta de entrada é de agosto e continua valendo. O resto da tela — cartão,
   campos, botão — segue o redesign. */
.auth__logo {
  display: block;
  /* Largura, e não altura: o logo é deitado (1,95:1). O teto em % segura o
     logo dentro da tela quando a coluna encolhe no celular. */
  width: 12rem;
  max-width: 70%;
  height: auto;
  margin: 0 auto 0.875rem;
}

.auth__chamada {
  margin: 0 0 1.5rem;
  font-family: var(--font-display);
  font-size: 1rem;
  font-weight: 700;
  line-height: 1.35;
  text-transform: uppercase;
  /* Em caixa alta o Rajdhani precisa de respiro entre as letras — mesmo
     motivo do .brand. */
  letter-spacing: 0.1em;
  color: var(--text-muted);
}

/* O cartão volta a ser alinhado à esquerda: quem centraliza é a página. */
.auth--marca .card {
  text-align: left;
}

/* O título é a exceção. Com o logo e o nome da marca centralizados logo
   acima, um título preso à esquerda quebra o eixo que a tela inteira segue —
   e o eixo só volta lá embaixo, no link do rodapé do cartão. */
.auth--marca .card__title,
.auth--marca .card__lead {
  text-align: center;
}

/* Com uma linha só, centralizado lê melhor que preso à esquerda. */
.auth__note--centro {
  text-align: center;
}

/* --- Formulários --- */

.field {
  margin-bottom: 1.125rem;
}

.field__label {
  display: block;
  margin-bottom: 0.375rem;
  font-size: 0.8125rem;
  font-weight: 600;
  color: var(--text);
}

/* 44px de altura: o alvo de toque confortável, e o corpo em que um campo
   preenchido continua legível sem zoom no celular. */
.field__input {
  width: 100%;
  min-height: 2.625rem;
  padding: 0.625rem 0.8125rem;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius);
  background: var(--field);
  color: var(--text);
  font: inherit;
  font-size: 0.90625rem;
}

.field__input::placeholder {
  color: var(--text-subtle);
}

/* Anel de foco em vez de outline duplo: o `outline` de 2px somado à borda
   engordava o campo em 2px e empurrava a linha seguinte do formulário. */
.field__input:focus {
  border-color: var(--brand);
  box-shadow: 0 0 0 3px var(--brand-subtle);
  outline: none;
}

.field__input:disabled {
  opacity: 0.55;
  cursor: not-allowed;
}

/* Estado de erro visível antes de a pessoa ler a mensagem. */
.field__input[aria-invalid="true"],
.field--erro .field__input {
  border-color: var(--danger);
  box-shadow: 0 0 0 3px var(--danger-subtle);
}

/* Sem a seta nativa, a seta é desenhada aqui — senão o select fica igual a
   um campo de texto e não se anuncia como lista. Dois gradientes, e não um
   SVG em data URI: assim a cor vem de token e acompanha o tema. O múltiplo
   fica de fora porque não abre para baixo; ele é uma caixa com rolagem. */
select.field__input {
  appearance: none;
  -webkit-appearance: none;
  padding-right: 1.875rem;
  cursor: pointer;
}

select.field__input:not([multiple]) {
  background-image:
    linear-gradient(45deg, transparent 50%, var(--text-subtle) 50%),
    linear-gradient(135deg, var(--text-subtle) 50%, transparent 50%);
  background-position:
    calc(100% - 1.0625rem) 50%,
    calc(100% - 0.75rem) 50%;
  background-size: 0.3125rem 0.3125rem;
  background-repeat: no-repeat;
}

.field__error {
  margin: 0.4375rem 0 0;
  color: var(--danger);
  font-size: 0.8125rem;
  font-weight: 500;
}

/* --- Seletor com busca ---

   Montado por selects.js sobre o <select> da página, que continua no DOM
   (escondido) e continua sendo quem envia o valor. Uma lista de 40 empresas
   não se percorre com o olho: nela o que resolve é digitar três letras. */

.combo {
  position: relative;
  width: 100%;
}

.combo__nativo {
  display: none;
}

.combo__campo {
  /* Nome longo (ou vários, na seleção múltipla) é cortado com reticências em
     vez de esticar a barra de filtros; o title tem a lista inteira. */
  text-overflow: ellipsis;
  cursor: text;
}

.combo__lista {
  position: absolute;
  z-index: 30;
  top: calc(100% + 0.375rem);
  right: 0;
  left: 0;
  max-height: 16rem;
  margin: 0;
  padding: 0.25rem;
  overflow-y: auto;
  list-style: none;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 12px;
  box-shadow: var(--shadow);
}

.combo__opcao {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  min-height: 2.25rem;
  padding: 0.5rem 0.625rem;
  border-radius: calc(var(--radius) - 3px);
  font-size: 0.875rem;
  cursor: pointer;
}

/* O `display: flex` acima vence a regra [hidden] do navegador: sem isto a
   opção filtrada continuaria visível. */
.combo__opcao[hidden] {
  display: none;
}

/* --brand-subtle, e não --surface-2: no tema claro o levantado é quase branco
   e o realce desaparecia contra a lista. */
.combo__opcao--realce {
  background: var(--brand-subtle);
}

.combo__opcao[aria-selected="true"] {
  color: var(--brand);
  font-weight: 600;
}

.combo__opcao[aria-selected="true"]::after {
  content: "✓";
}

.combo__vazio {
  padding: 0.5rem 0.625rem;
  color: var(--text-muted);
  font-size: 0.875rem;
}

/* "Mostrando 100 de 917 — refine a busca." — só em lista longa. */
.combo__resumo {
  padding: 0.5rem 0.625rem;
  border-bottom: 1px solid var(--border);
  color: var(--text-muted);
  font-size: 0.75rem;
}

/* "Não informar" e afins: escolha possível, mas não uma das opções. */
.combo__opcao--vazia {
  color: var(--text-muted);
}

/* --- Botões ---

   Três níveis, e a diferença entre eles é de peso visual, não de cor:
   primário é preenchido, secundário tem borda, e o de link não tem nem uma
   nem outra. Só o destrutivo muda de cor — e mesmo ele começa discreto,
   com a cor no texto, e só preenche no hover, quando a intenção é clara. */
.button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  min-height: 2.5rem;
  padding: 0.5625rem 1.0625rem;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--text);
  font: inherit;
  font-size: 0.875rem;
  font-weight: 600;
  letter-spacing: -0.008em;
  cursor: pointer;
}

.button:hover {
  background: var(--surface-2);
  color: var(--text);
  text-decoration: none;
}

.button:active {
  transform: translateY(0.5px);
}

.button:disabled,
.button[aria-disabled="true"] {
  opacity: 0.5;
  cursor: not-allowed;
}

.button--primary {
  width: 100%;
  border-color: var(--brand);
  background: var(--brand);
  color: var(--brand-contrast);
}

.button--primary:hover {
  background: var(--brand-hover);
  border-color: var(--brand-hover);
  color: var(--brand-contrast);
}

/* O botão primário ocupa a largura toda no login; nas telas de gestão ele
   convive com outros e precisa voltar ao tamanho natural. */
.button--auto {
  width: auto;
}

.button--danger {
  border-color: var(--border-strong);
  background: var(--surface);
  color: var(--danger);
}

.button--danger:hover {
  border-color: var(--danger);
  background: var(--danger);
  color: #fff;
}

.button--link {
  border-color: transparent;
  background: transparent;
  color: var(--text-muted);
  padding: 0.4375rem 0.75rem;
  font-weight: 500;
  font-size: 0.8125rem;
}

.button--link:hover {
  background: var(--surface-2);
  color: var(--text);
}

/* --- Alertas ---

   Fundo de token em vez de `color-mix` com transparente: sobre o cartão e
   sobre o fundo da página a mistura dava dois resultados diferentes, e o
   aviso mudava de tom conforme onde caía.

   Em coluna: há aviso com mais de um parágrafo (o do formulário de relatório
   tem três, e o de erro de formulário tem um por erro), e em linha eles
   viravam colunas lado a lado. */
.alert {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  margin-bottom: 1.25rem;
  padding: 0.875rem 1rem;
  border: 1px solid transparent;
  border-radius: 12px;
  font-size: 0.84375rem;
  line-height: 1.55;
  color: var(--text);
}

.alert p {
  margin: 0;
  text-wrap: pretty;
}

/* O X do aviso, no canto: em coluna flex ele empurraria o texto: por isso
   fora do fluxo, com o recuo à direita reservado no próprio aviso. Só a pilha
   de mensagens o tem — ver `avisos.js`. */
.messages .alert {
  position: relative;
  padding-right: 2.5rem;
}

.alert__fechar {
  position: absolute;
  top: 0.375rem;
  right: 0.5rem;
  display: flex;
  width: 1.75rem;
  height: 1.75rem;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: 0;
  border-radius: 999px;
  background: none;
  color: inherit;
  font-size: 1.125rem;
  line-height: 1;
  opacity: 0.6;
  cursor: pointer;
}

.alert__fechar:hover {
  opacity: 1;
  background: color-mix(in srgb, currentColor 12%, transparent);
}

/* Some sem salto: a saída é só opacidade, e o espaço vai junto quando o
   elemento sai do DOM. */
.alert--saindo {
  opacity: 0;
  transition: opacity 0.3s ease;
}

.alert--danger,
.alert--error {
  background: var(--danger-subtle);
  border-color: color-mix(in srgb, var(--danger) 28%, transparent);
}

.alert--info,
.alert--debug {
  background: var(--brand-subtle);
  border-color: color-mix(in srgb, var(--brand) 24%, transparent);
}

.alert--success {
  background: var(--success-subtle);
  border-color: color-mix(in srgb, var(--success) 28%, transparent);
}

.alert--warning {
  background: var(--warning-subtle);
  border-color: color-mix(in srgb, var(--warning) 28%, transparent);
}

/* --- Lista de dados --- */

.datalist {
  margin: 0 0 1.5rem;
}

.datalist__row {
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem 1rem;
  padding: 0.8125rem 0;
  border-bottom: 1px solid var(--hairline);
}

.datalist__row:last-child {
  border-bottom: 0;
}

.datalist dt {
  flex: 0 0 9.375rem;
  color: var(--text-muted);
  font-size: 0.84375rem;
}

.datalist dd {
  margin: 0;
  font-size: 0.90625rem;
  font-weight: 500;
}

@media (max-width: 40rem) {
  .card {
    padding: 1.25rem;
  }

  .auth .card {
    padding: 1.5rem;
  }

  .datalist dt {
    flex-basis: 100%;
  }
}

/* --------------------------------------------------------------------------
   Seletor de ícone do item de menu (Luiz, 01/10/2026): o botão com o ícone
   escolhido e a janela com os do Lucide (static/icones/, seletor-icone.js).
   -------------------------------------------------------------------------- */

.seletor-icone {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
}

.seletor-icone__previa {
  width: 1.25rem;
  height: 1.25rem;
}

/* `.button` define display e venceria o [hidden] do navegador. */
.seletor-icone [hidden] {
  display: none;
}

.seletor-icone__janela {
  width: min(46rem, calc(100vw - 2rem));
  max-height: min(40rem, calc(100vh - 2rem));
  padding: 1rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--surface);
  color: var(--text);
  box-shadow: var(--shadow);
}

.seletor-icone__janela::backdrop {
  background: rgb(0 0 0 / 35%);
}

.seletor-icone__topo {
  display: flex;
  gap: 0.5rem;
}

.seletor-icone__busca {
  flex: 1;
}

.seletor-icone__grade {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(2.75rem, 1fr));
  gap: 0.25rem;
  max-height: 26rem;
  overflow-y: auto;
}

.seletor-icone__opcao {
  display: grid;
  place-items: center;
  aspect-ratio: 1;
  border: 1px solid transparent;
  border-radius: var(--radius);
  background: none;
  color: var(--text);
  cursor: pointer;
}

.seletor-icone__opcao svg {
  width: 1.375rem;
  height: 1.375rem;
}

.seletor-icone__opcao:hover,
.seletor-icone__opcao:focus-visible {
  border-color: var(--border-strong);
  background: var(--brand-subtle);
}

.seletor-icone__opcao[aria-pressed="true"] {
  border-color: var(--brand);
  color: var(--brand);
}
