/**
 * Extensões ao Bootstrap 5.3: os tokens de tema (:root) e tudo que o
 * framework não cobre — sidebar, topbar, kanban, timeline, avatar, cartão
 * de estatística, estado vazio — mais o punhado de variantes de cor que o
 * Bootstrap não define por padrão (btn-ghost-*, mais alguns alias de
 * nome). Convenção do painel (ver PADROES-UI.md): botão de ação de tabela
 * usa ghost colorido por severidade — Detalhar/Editar cinza, Desativar
 * amarelo, Ativar verde, Excluir vermelho.
 *
 * Carrega DEPOIS do Bootstrap (ver cascata em cada layout): toda classe
 * daqui que tenha o mesmo nome de uma classe do Bootstrap (.btn, .card,
 * .table, .badge, .form-control, .list-group, .pagination) VENCE por ordem
 * de origem, na mesma especificidade — é assim que a identidade visual do
 * painel (compacta, tokens próprios) sobrevive por cima de um framework
 * genérico sem precisar de !important em lugar nenhum.
 *
 * Os TOKENS vivem aqui, não em painel.css, DE PROPÓSITO: `erro.php` é o
 * único layout que não carrega painel.css (não pode depender de nada que
 * possa ter sido a causa do erro), mas os quatro layouts carregam esta
 * folha — sem os tokens aqui, a página de erro renderizaria sem cor, sem
 * raio, sem espaçamento nenhum.
 */

:root {
  /* Sidebar — fixa, não muda no tema escuro (a sidebar já nasce escura).
     Os tons são os do AdminLTE 4 (_variables-dark.scss dele): cinza neutro
     #343a40 no fundo — que é o --bs-secondary-bg do Bootstrap no tema
     escuro, exatamente o que o `bg-body-secondary` da sidebar dele resolve
     —, texto #c2c7d0 e realce translúcido de 10%. O painel era azul-marinho
     (#1a2332), que tinha dois problemas: coincidia com o --bg-surface do
     tema escuro (sidebar e cartão viravam a mesma cor, separados só pela
     borda) e o realce de 4% mal aparecia. */
  --sidebar-bg: #343a40;
  --sidebar-hover: rgba(255, 255, 255, 0.1);
  --sidebar-active: rgba(255, 255, 255, 0.1);
  --sidebar-text: #c2c7d0;
  --sidebar-text-hover: #ffffff;
  --sidebar-text-active: #ffffff;
  --sidebar-border: #495057;
  --sidebar-w: 250px;
  /* Faixa do modo rail. Existia em três comentários (painel.js, PADROES-UI)
     como "a faixa de 64px" e em NENHUMA regra: recolher escondia os rótulos
     mas a barra continuava com a largura cheia, e .main/.topbar seguiam
     deslocados — o botão de recolher não devolvia espaço nenhum. */
  --sidebar-w-rail: 64px;
  /* O MIOLO do módulo aberto. É o gancho que o AdminLTE chama de
     --lte-sidebar-submenu-bg (ele deixa `transparent`); aqui vale um tom
     acima do fundo, para o bloco em uso se destacar dos módulos fechados.
     Trocar a cor de TODOS os módulos é editar esta linha; para uma cor por
     módulo, ver ModuleManifest::cor() e os [data-cor] mais abaixo. */
  --sidebar-submenu-bg: rgba(255, 255, 255, 0.05);
  /* Acento do módulo (item aceso). Branco = módulo sem cor própria, que dá
     exatamente o rgba(255,255,255,.1) do AdminLTE; um [data-cor] mais abaixo
     na árvore troca o triplet e o realce inteiro acompanha. */
  --sidebar-cor-rgb: 255, 255, 255;

  /* Marca — fixa; --primary-lt redefine no escuro (ver [data-theme=dark]). */
  --primary: #667eea;
  --primary-lt: rgba(102, 126, 234, 0.06);
  --primary-dk: #576bc7;

  /* Marca da OTIMIZER, fabricante do painel — não confundir com --primary
     (cor do PAINEL, potencialmente white-label por instalação). Fixa nos
     dois temas: a assinatura de quem construiu o sistema não muda com a
     preferência de tema do usuário nem com a marca do cliente. Os dois hex
     foram lidos da arte de referência enviada pela Otimizer; ajustar aqui
     é o único ponto a tocar se o manual de marca corrigir o tom exato. */
  --otimizer-petrol: #0d3b54;
  --otimizer-laranja: #f9591b;

  /* Superfícies, bordas, texto — todas redefinem no escuro. */
  --body-bg: #f5f7fb;
  --bg-surface: #ffffff;
  --bg-surface-secondary: #f9fafb;
  --border-color: #e6e7eb;
  --border-color-light: #eff0f3;
  --border-translucent: rgba(4, 32, 69, 0.08);
  --text: #1e2633;
  --text-secondary: #626d7d;
  --text-muted: #7e8896;
  --text-disabled: #c0c7cf;

  /* Paleta sólida — mesmo hex nos dois temas. */
  --blue: #066fd1;
  --azure: #4299e1;
  --green: #2fb344;
  --lime: #74b816;
  --yellow: #f59f00;
  --orange: #f76707;
  --red: #d63939;
  --pink: #d6336c;
  --purple: #ae3ec9;
  --indigo: #4263eb;
  --cyan: #17a2b8;

  /* Triplets RGB da mesma paleta — mesmo padrão do --bs-primary-rgb logo
     abaixo. Existem para montar rgba() com alfa variável, que é o que a cor
     de módulo na barra lateral precisa: a paleta tênue (--blue-lt e
     companhia) é 6% calculada sobre cartão BRANCO e desaparece sobre o
     #343a40 da sidebar. */
  --blue-rgb: 6, 111, 209;
  --azure-rgb: 66, 153, 225;
  --green-rgb: 47, 179, 68;
  --lime-rgb: 116, 184, 22;
  --yellow-rgb: 245, 159, 0;
  --orange-rgb: 247, 103, 7;
  --red-rgb: 214, 57, 57;
  --pink-rgb: 214, 51, 108;
  --purple-rgb: 174, 62, 201;
  --indigo-rgb: 66, 99, 235;
  --cyan-rgb: 23, 162, 184;

  /* Paleta tênue — opacidade 0.5 no claro; redefine no escuro. */
  --green-lt: rgba(47, 179, 68, 0.5);
  --red-lt: rgba(214, 57, 57, 0.5);
  --yellow-lt: rgba(245, 159, 0, 0.5);
  --blue-lt: rgba(6, 111, 209, 0.5);
  --azure-lt: rgba(66, 153, 225, 0.5);
  --purple-lt: rgba(174, 62, 201, 0.5);
  --cyan-lt: rgba(23, 162, 184, 0.5);
  --orange-lt: rgba(247, 103, 7, 0.5);

  /* Raio e espaçamento — fixos. */
  --radius: 6px;
  --radius-sm: 4px;
  --radius-lg: 8px;
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 24px;
  --space-6: 32px;
  --space-7: 48px;
  --space-8: 64px;

  /* Sombra — redefine no escuro. */
  --shadow: rgba(30, 38, 51, 0.04) 0 2px 4px 0;
  --shadow-card: 0 0 0 1px var(--border-translucent), rgba(30, 38, 51, 0.04) 0 2px 4px 0;

  /* Tipografia — fixa. */
  --font: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  --font-mono: 'SF Mono', Monaco, Consolas, 'Liberation Mono', monospace;
  --font-size: 0.875rem;
  --line-height: 1.4286;
  --font-weight-normal: 400;
  --font-weight-medium: 500;
  --font-weight-bold: 600;

  /* Ponte para os componentes NATIVOS do Bootstrap que este painel não
     reestiliza por completo (Modal, Dropdown, Offcanvas, Tooltip) — sem
     isto eles ficariam na cor padrão do Bootstrap (azul #0d6efd) em vez da
     marca do painel. As variáveis próprias acima continuam sendo a fonte
     de verdade para tudo que É reestilizado (o resto desta folha). */
  --bs-primary: var(--primary);
  --bs-primary-rgb: 102, 126, 234;
  --bs-body-bg: var(--body-bg);
  --bs-body-color: var(--text);
  --bs-border-color: var(--border-color);
  --bs-border-radius: var(--radius-sm);
  --bs-border-radius-lg: var(--radius-lg);
  --bs-link-color: var(--primary);
  --bs-link-color-rgb: 102, 126, 234;
  --bs-link-hover-color: var(--primary-dk);
  --bs-link-hover-color-rgb: 87, 107, 199;
  --bs-secondary-color: var(--text-secondary);
  --bs-emphasis-color: var(--text);
}

[data-theme=dark] {
  --body-bg: #0f1623;
  --bg-surface: #1a2332;
  --bg-surface-secondary: #141d2b;
  --border-color: rgba(255, 255, 255, 0.08);
  --border-color-light: rgba(255, 255, 255, 0.05);
  --border-translucent: rgba(255, 255, 255, 0.08);
  --text: #e6ebf2;
  --text-secondary: #b3bccb;
  --text-muted: #8a93a3;
  --text-disabled: #5a6473;
  --primary-lt: rgba(102, 126, 234, 0.6);
  --green-lt: rgba(47, 179, 68, 0.6);
  --red-lt: rgba(214, 57, 57, 0.6);
  --yellow-lt: rgba(245, 159, 0, 0.6);
  --blue-lt: rgba(6, 111, 209, 0.6);
  --azure-lt: rgba(66, 153, 225, 0.6);
  --purple-lt: rgba(174, 62, 201, 0.6);
  --cyan-lt: rgba(23, 162, 184, 0.6);
  --orange-lt: rgba(247, 103, 7, 0.6);
  --shadow: rgba(0, 0, 0, 0.4) 0 2px 4px 0;
  --shadow-card: 0 0 0 1px var(--border-translucent), rgba(0, 0, 0, 0.3) 0 2px 4px 0;
}

body {
  font-family: var(--font);
  font-size: var(--font-size);
  font-weight: var(--font-weight-normal);
  line-height: var(--line-height);
  color: var(--text);
  background: var(--body-bg);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

/* --- Ponte Font Awesome ----------------------------------------------------
 *
 * Ícones são Font Awesome (helper icone(), em helpers.php, devolve <i
 * class="icon fa-solid fa-...">). Um glifo de fonte dimensiona por
 * `font-size`, não por `width`/`height` — sem esta ponte todo ícone do
 * painel cairia no tamanho do TEXTO ao redor (14px), com o menu, os
 * cartões de estatística e os estados vazios encolhendo de uma vez.
 *
 * `width: 1.25em` é o fixed-width do próprio Font Awesome (.fa-fw): sem ele
 * cada glifo tem a largura natural do desenho, e os rótulos do menu
 * ficariam em colunas diferentes conforme o ícone de cada item.
 */
i.icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.25em;
  line-height: 1;
  flex-shrink: 0;
  vertical-align: -0.125em;
}

.app-sidebar i.icon.nav-icon { font-size: 17px; }
.sidebar-toggle i.icon,
.tb-btn i.icon { font-size: 17px; }
.empty-state-icon i.icon { font-size: 21px; }
.stat-icon i.icon { font-size: 19px; }
.stat-change i.icon { font-size: 11px; }
.pagination .page-link i.icon,
.alert-dismissible .btn-close i.icon { font-size: 11px; }
i.icon.nav-arrow,
i.icon.quadro-ajuda-seta { font-size: 11px; width: 1em; }
.temperatura i.icon { font-size: 12px; width: 1em; }
.input-affix .affix-btn i.icon { font-size: 16px; }

/* Ícone maior no PRIMEIRO nível do menu (19px contra os 17px do submenu) —
   separa visualmente módulo de item de módulo, sobretudo no modo rail, onde
   só o ícone aparece. São DOIS seletores por caso porque o primeiro nível
   tem duas formas: item folha (<a> direto no <li>) e módulo com submenu
   (<summary> dentro do <details>). E são dois ELEMENTOS por forma porque
   icone_ou_inicial() devolve ora <i class="icon">, ora <svg class="icon
   icon-inicial"> — módulo sem ícone declarado entra pela inicial do nome. */
.app-sidebar .sidebar-menu > .nav-item > .nav-link > i.icon.nav-icon,
.app-sidebar .sidebar-menu > .nav-item > .nav-tree > .nav-link > i.icon.nav-icon {
  font-size: 19px;
}
.app-sidebar .sidebar-menu > .nav-item > .nav-link > svg.icon.nav-icon,
.app-sidebar .sidebar-menu > .nav-item > .nav-tree > .nav-link > svg.icon.nav-icon {
  width: 22px;
  height: 22px;
}
.icon-inicial text {
  font-family: inherit;
  letter-spacing: -0.02em;
}

/* --- Skip link -------------------------------------------------------------
 * Primeiro elemento focável da página, invisível até receber foco pelo
 * Tab — sem ele, quem navega por teclado atravessa o menu lateral inteiro
 * a cada troca de tela. */
.skip-link {
  position: fixed; top: 8px; left: 8px; z-index: 200;
  padding: 8px 14px; background: var(--primary); color: #fff;
  border-radius: var(--radius); font-weight: var(--font-weight-medium);
  text-decoration: none; transform: translateY(-200%);
  transition: transform 150ms ease;
}
.skip-link:focus,
.skip-link:focus-visible {
  transform: translateY(0);
  outline: 2px solid var(--primary); outline-offset: 2px;
}

/* --- Barra lateral (marcação do AdminLTE 4, sobre o Bootstrap) ---------
 *
 * A sidebar do AdminLTE 4 não tem vocabulário próprio de lista: ela é
 * `<ul class="nav sidebar-menu flex-column">` com `.nav-item`/`.nav-link` do
 * PRÓPRIO Bootstrap, e submenu é outro `<ul class="nav nav-treeview">`. É por
 * isso que "colocar o menu no formato Bootstrap" e "seguir o AdminLTE" são,
 * aqui, a mesma coisa — e é o que permite este bloco encolher tanto: quase
 * tudo que a casca anterior desenhava à mão (cor, padding, tamanho de fonte,
 * estado desabilitado) agora vem do framework.
 *
 * O grupo continua sendo <details>/<summary> nativo — ver o comentário longo
 * em parciais/sidebar.php. Resumo: o AdminLTE abre e fecha por JavaScript
 * (`.menu-open`), e um menu JS-driven já derrubou a navegação do painel três
 * vezes. O estado é o atributo [open], não uma classe.
 */
.app-sidebar {
  position: fixed; left: 0; top: 0; bottom: 0;
  width: var(--sidebar-w); background: var(--sidebar-bg);
  z-index: 100; display: flex; flex-direction: column; overflow: visible;
  transition: width 220ms cubic-bezier(0.2, 0, 0, 1);
}

.sidebar-brand {
  height: 56px; padding: 0 8px; display: flex; align-items: center;
  justify-content: center; gap: 10px;
  border-bottom: 1px solid var(--sidebar-border); flex-shrink: 0;
}
/* Desvio deliberado da proporção "ícone pequeno numa faixa alta": a marca
   do painel pede mais destaque, então o padding lateral encolhe e a altura
   da imagem cresce quase até preencher a faixa.
   .brand-image/.brand-image-rail são CONTÊINERES em volta da parcial
   marca-otimizer (sempre Otimizer, nunca a do cliente — ver sidebar.php) só
   para centralizar e fazer o toggle normal/rail; o tamanho de verdade vem
   de `altura` na chamada da parcial. */
.sidebar-brand .brand-link { display: flex; align-items: center; gap: 10px; text-decoration: none; min-width: 0; }
.sidebar-brand .brand-image,
.sidebar-brand .brand-image-rail { display: flex; align-items: center; justify-content: center; flex-shrink: 0; }
.sidebar-brand .brand-image { height: 40px; }
.sidebar-brand .brand-image-rail { display: none; height: 36px; width: 36px; }
body.sidebar-rail .sidebar-brand .brand-image { display: none; }
body.sidebar-rail .sidebar-brand .brand-image-rail { display: flex; }

.sidebar-wrapper { flex: 1; overflow-y: auto; padding: 8px 0; }
.sidebar-footer {
  border-top: 1px solid var(--sidebar-border); padding: 8px; flex-shrink: 0;
  text-align: center; font-size: 11px; color: var(--sidebar-text);
  display: flex; flex-direction: column; align-items: center; gap: 4px;
}
.sidebar-footer .sidebar-footer-linha { display: flex; align-items: center; gap: 6px; }
body.sidebar-rail .sidebar-footer { display: none; }

/* Aviso de menu vazio (instalação que ainda não importou o SQL, ou perfil sem
   nenhum módulo). Classe própria em vez de style="" cravado na view. */
.app-sidebar .nav-aviso {
  padding: 8px 12px; font-size: 12px; color: var(--sidebar-text); list-style: none;
}

/* DENSIDADE E COR PELAS CUSTOM PROPERTIES DO PRÓPRIO BOOTSTRAP.
 *
 * O AdminLTE não escreve `padding` no .nav-link da sidebar: ele mexe nas
 * variáveis do Bootstrap (é assim que o `.compact-mode` dele funciona). Aqui
 * igual — e de quebra some um defeito silencioso: essas variáveis nascem na
 * regra `.nav` do Bootstrap, e o menu antigo não tinha ancestral `.nav`
 * nenhum, então `.nav-link` do framework emitia `padding` inválido e
 * `.nav-link.disabled` caía em `color: unset` (herdava, em vez de apagar).
 *
 * O seletor é `.app-sidebar .nav`, e NÃO `.app-sidebar` sozinho: a regra
 * `.nav{--bs-nav-link-padding-x:1rem;…}` do Bootstrap dispara em TODO .nav,
 * inclusive no <ul class="nav nav-treeview"> de dentro. Declarado só no
 * <aside>, o valor herdado seria sobrescrito localmente no submenu e os
 * subitens voltariam ao 1rem do framework — com o primeiro nível certo. Ou
 * seja: o pior tipo de defeito, o que parece funcionar. */
.app-sidebar .nav {
  --bs-nav-link-padding-y: .375rem;
  --bs-nav-link-padding-x: .75rem;
  --bs-nav-link-font-size: 13px;
  --bs-nav-link-font-weight: var(--font-weight-normal);
  --bs-nav-link-color: var(--sidebar-text);
  --bs-nav-link-hover-color: var(--sidebar-text-hover);
  --bs-nav-link-disabled-color: var(--text-disabled);
  flex-wrap: nowrap;
}
.app-sidebar .sidebar-menu { padding: 0 8px; }
.app-sidebar .nav-item { max-width: 100%; }

/* Só o que o Bootstrap NÃO traz: padding, font-size, color e font-weight
   vêm das variáveis acima e não se repetem aqui. */
.app-sidebar .nav-link {
  display: flex; align-items: center; gap: 10px;
  border-radius: var(--radius); margin-bottom: 2px; min-height: 32px;
  cursor: pointer; text-decoration: none; position: relative;
  transition: background-color 120ms, color 120ms;
}
.app-sidebar .nav-link .nav-text {
  flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.app-sidebar .nav-link:hover { background: var(--sidebar-hover); text-decoration: none; }
.app-sidebar .nav-link:focus-visible { outline: 2px solid var(--primary); outline-offset: -2px; }
.app-sidebar .nav-link.active {
  color: var(--sidebar-text-active); font-weight: var(--font-weight-medium);
  /* Um rgba() só, dois comportamentos: sem [data-cor] o triplet é branco
     (o rgba(255,255,255,.1) do AdminLTE); com cor de módulo, é a cor dele. */
  background: rgba(var(--sidebar-cor-rgb), .14);
}
.app-sidebar .nav-link.disabled { cursor: default; }
.app-sidebar .nav-link .badge { margin-left: auto; font-size: 10px; font-weight: 600; padding: 1px 6px; border-radius: 3px; line-height: 1.6; }

/* Ícone: coluna fixa de 1.5rem (AdminLTE), o que alinha todos os rótulos.
   Regras pareadas para os DOIS elementos, porque icone_ou_inicial() devolve
   ora <i class="icon">, ora <svg class="icon icon-inicial"> — módulo sem
   ícone declarado entra pela inicial do nome. */
.app-sidebar .nav-icon { min-width: 1.5rem; max-width: 1.5rem; }
.app-sidebar svg.icon.nav-icon { width: 18px; height: 18px; opacity: .55; }
.app-sidebar .nav-link:hover svg.icon.nav-icon,
.app-sidebar .nav-link.active svg.icon.nav-icon { opacity: .9; }

.app-sidebar .nav-tree { display: block; }
.app-sidebar summary.nav-link { list-style: none; }
.app-sidebar summary.nav-link::-webkit-details-marker { display: none; }
.app-sidebar .nav-arrow { margin-left: auto; opacity: .55; flex-shrink: 0;
  transition: transform 200ms cubic-bezier(0.2, 0, 0, 1), opacity 120ms; }
.app-sidebar .nav-link:hover .nav-arrow { opacity: .9; }
.app-sidebar .nav-tree[open] > summary.nav-link .nav-arrow { transform: rotate(90deg); opacity: 1; }

/* Submenu: UM <ul>, não mais .nav-sub + .nav-sub-inner. Os dois existiam por
   causa do colapso via grid-template-rows, que o <details> tornou
   desnecessário (conteúdo fechado nem chega a ser renderizado). O recuo de
   cada nível continua saindo de graça do padding acumulado — profundidade
   arbitrária, sem patch nenhum. */
.app-sidebar .nav-treeview { position: relative; padding: 2px 0 4px 20px; }
.app-sidebar .nav-treeview::before {
  content: ""; position: absolute; left: 15px; top: 2px; bottom: 4px;
  width: 1px; background: var(--sidebar-border);
}

/* O INTERIOR DO MÓDULO ABERTO — o pedido: fundo diferente dos demais.
 *
 * É o gancho que o AdminLTE chama de --lte-sidebar-submenu-bg (lá ele fica
 * `transparent`, aqui ganha cor). O cabeçalho do módulo entra junto, pra que
 * cabeçalho e miolo leiam como UM bloco: sem isso os subitens do módulo em
 * uso ficavam no mesmo fundo neutro dos módulos fechados, sem nenhuma pista
 * de que pertencem ao bloco aberto.
 *
 * Só o PRIMEIRO nível: aplicar em todo .nav-treeview empilharia a opacidade a
 * cada aninhamento, e o terceiro nível sairia quase branco. Subgrupo herda o
 * tom visualmente por estar dentro do bloco. */
.app-sidebar .sidebar-menu > .nav-item > .nav-tree[open] > summary.nav-link {
  background: var(--sidebar-submenu-bg);
  border-radius: var(--radius) var(--radius) 0 0;
  color: var(--sidebar-text-hover); margin-bottom: 0;
}
.app-sidebar .sidebar-menu > .nav-item > .nav-tree[open] > .nav-treeview {
  background: var(--sidebar-submenu-bg);
  border-radius: 0 0 var(--radius) var(--radius);
  margin-bottom: 2px;
}

/* Cor por módulo (ModuleManifest::cor()). Os nomes são os da paleta que o
   painel já tem (--blue, --green, …), não um segundo vocabulário.
   A paleta tênue (--blue-lt e companhia) NÃO serve aqui: ela é 6% calculada
   sobre cartão BRANCO e some sobre o #343a40 da barra; e como a sidebar não
   reage a [data-theme], nunca chegaria à variante de 16% do tema escuro. Daí
   o triplet RGB com alfa próprio.
   Toda entrada de CoresDeModulo::CORES precisa de uma regra aqui —
   bin/verificar.php cobra as duas pontas, como já faz com o Font Awesome. */
.app-sidebar [data-cor="blue"]   { --sidebar-cor-rgb: var(--blue-rgb);   --sidebar-submenu-bg: rgba(var(--blue-rgb), .16); }
.app-sidebar [data-cor="azure"]  { --sidebar-cor-rgb: var(--azure-rgb);  --sidebar-submenu-bg: rgba(var(--azure-rgb), .16); }
.app-sidebar [data-cor="indigo"] { --sidebar-cor-rgb: var(--indigo-rgb); --sidebar-submenu-bg: rgba(var(--indigo-rgb), .16); }
.app-sidebar [data-cor="purple"] { --sidebar-cor-rgb: var(--purple-rgb); --sidebar-submenu-bg: rgba(var(--purple-rgb), .16); }
.app-sidebar [data-cor="pink"]   { --sidebar-cor-rgb: var(--pink-rgb);   --sidebar-submenu-bg: rgba(var(--pink-rgb), .16); }
.app-sidebar [data-cor="red"]    { --sidebar-cor-rgb: var(--red-rgb);    --sidebar-submenu-bg: rgba(var(--red-rgb), .16); }
.app-sidebar [data-cor="orange"] { --sidebar-cor-rgb: var(--orange-rgb); --sidebar-submenu-bg: rgba(var(--orange-rgb), .16); }
.app-sidebar [data-cor="yellow"] { --sidebar-cor-rgb: var(--yellow-rgb); --sidebar-submenu-bg: rgba(var(--yellow-rgb), .16); }
.app-sidebar [data-cor="lime"]   { --sidebar-cor-rgb: var(--lime-rgb);   --sidebar-submenu-bg: rgba(var(--lime-rgb), .16); }
.app-sidebar [data-cor="green"]  { --sidebar-cor-rgb: var(--green-rgb);  --sidebar-submenu-bg: rgba(var(--green-rgb), .16); }
.app-sidebar [data-cor="cyan"]   { --sidebar-cor-rgb: var(--cyan-rgb);   --sidebar-submenu-bg: rgba(var(--cyan-rgb), .16); }

@media (min-width: 769px) {
  /* MODO RAIL. Até esta versão ele nunca estreitou nada: .sidebar ficava com
     a largura cheia e a única regra `body.sidebar-rail` com width morava
     dentro do @media (max-width: 768px), devolvendo o valor cheio. Recolher
     escondia o rótulo e não devolvia um pixel de tela. A "faixa de 64px" que
     painel.js e PADROES-UI.md citavam não existia no CSS.

     As três regras de geometria moram AQUI DENTRO por especificidade: media
     query não soma nada, então `body.sidebar-rail .main` (0,2,0) escrito
     fora venceria `@media (max-width:768px){.main{margin-left:0}}` (0,1,0) e
     empurraria o conteúdo do celular 64px para a direita, atrás do drawer. */
  body.sidebar-rail .app-sidebar { width: var(--sidebar-w-rail); overflow: visible; }
  body.sidebar-rail .main        { margin-left: var(--sidebar-w-rail); }
  body.sidebar-rail .topbar      { left: var(--sidebar-w-rail); }

  body.sidebar-rail .app-sidebar .nav { --bs-nav-link-padding-x: .5rem; }
  body.sidebar-rail .app-sidebar .nav-link { justify-content: center; gap: 0; }
  body.sidebar-rail .app-sidebar .nav-text,
  body.sidebar-rail .app-sidebar .nav-arrow,
  body.sidebar-rail .app-sidebar .badge { display: none; }
  body.sidebar-rail .app-sidebar .nav-treeview { display: none; }
  body.sidebar-rail .app-sidebar .nav-aviso { display: none; }

  /* Recolhida, a barra só mostra o ícone, e o realce translúcido some a um
     metro do monitor: o item em uso precisa GRITAR. Usa o MESMO acento do
     módulo, com alfa mais forte — sem cor declarada o triplet é branco e sai
     um chip claro; com cor, sai o chip da cor do módulo. (Antes era #fff
     cravado, que brigava com a cor do módulo e perdia: a regra do bloco
     aberto é mais específica, então o branco simplesmente não aparecia.)
     A especificidade é deliberadamente alta pelo mesmo motivo — precisa
     vencer a regra do miolo, que tem seis classes. */
  body.sidebar-rail .app-sidebar .sidebar-menu > .nav-item > .nav-tree[open] > summary.nav-link,
  body.sidebar-rail .app-sidebar .sidebar-menu .nav-link.active {
    background: rgba(var(--sidebar-cor-rgb), .3);
    color: var(--sidebar-text-active);
    border-radius: var(--radius);
    margin-bottom: 2px;
  }
  body.sidebar-rail .app-sidebar .nav-link.active .icon,
  body.sidebar-rail .app-sidebar .nav-tree[open] > summary.nav-link .icon { opacity: 1; }

  body.sidebar-rail .sidebar-toggle svg,
  body.sidebar-rail .sidebar-toggle i.icon { transform: rotate(180deg); }
  .sidebar-toggle svg,
  .sidebar-toggle i.icon { transition: transform 200ms ease; }
}

/* Drawer mobile: backdrop + sidebar deslizando por transform, JS próprio
   (painel.js) monta/desmonta o backdrop e alterna .app-sidebar.open. */
@media (max-width: 768px) {
  .app-sidebar { transform: translateX(-100%); transition: transform 220ms ease; will-change: transform; }
  .app-sidebar.open { transform: translateX(0); }
}
.sidebar-backdrop {
  position: fixed; inset: 0; background: rgba(15, 23, 42, .4);
  backdrop-filter: blur(2px); -webkit-backdrop-filter: blur(2px);
  z-index: 95; opacity: 1; transition: opacity 180ms ease;
}
.sidebar-backdrop[hidden] { display: none; }
/* Trava o scroll da página atrás do drawer mobile aberto. */
body.sidebar-open { overflow: hidden; }
@media (min-width: 769px) {
  .sidebar-backdrop { display: none !important; }
}

.sidebar-toggle {
  display: inline-flex; width: 34px; height: 34px; border: none;
  background: transparent; border-radius: var(--radius-sm);
  align-items: center; justify-content: center; cursor: pointer;
  color: var(--text-secondary); transition: background 120ms, color 120ms;
}
.sidebar-toggle:hover { background: var(--body-bg); color: var(--text); }

/* --- Área de conteúdo (irmã da sidebar fixa) --------------------------
 * margin-left abre espaço para a sidebar fixa (252px); padding-top, para
 * a topbar fixa (56px) — as duas são position:fixed, então não empurram
 * o fluxo normal sozinhas. */
.main {
  margin-left: var(--sidebar-w);
  padding-top: 56px;
  min-height: 100vh;
  transition: margin-left 220ms cubic-bezier(0.2, 0, 0, 1);
}
@media (max-width: 768px) {
  .main { margin-left: 0; }
}
@media print {
  .main { margin-left: 0 !important; padding: 0 !important; }
}

/* --- Topbar ---------------------------------------------------------- */
.topbar {
  position: fixed; top: 0; left: var(--sidebar-w); right: 0; height: 56px;
  background: rgba(255, 255, 255, .85); backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--border-color);
  display: flex; align-items: center; justify-content: space-between;
  padding: 0 24px; z-index: 90;
  transition: left 220ms cubic-bezier(0.2, 0, 0, 1);
}
/* Mesmo cinza neutro da sidebar, um degrau mais escuro: #212529 é o
   --bs-body-bg do Bootstrap no tema escuro, que é o fundo do .app-header do
   AdminLTE. Era rgba(20,29,43,.85), azulado, destoando da barra lateral. */
[data-theme=dark] .topbar { background: rgba(33, 37, 41, .85); }
.topbar-left,
.topbar-right { display: flex; align-items: center; gap: 4px; }

.breadcrumb { display: flex; align-items: center; gap: var(--space-1); font-size: 13px; color: var(--text-muted); margin: 0; }
.breadcrumb .current { color: var(--text); font-weight: var(--font-weight-medium); }
.breadcrumb .sep { color: var(--text-disabled); }
.breadcrumb a { color: inherit; text-decoration: none; transition: color 100ms; }
.breadcrumb a:hover { color: var(--primary); text-decoration: underline; text-underline-offset: 2px; }

.tb-btn {
  width: 32px; height: 32px; border: none; background: transparent;
  border-radius: var(--radius-sm); display: flex; align-items: center;
  justify-content: center; cursor: pointer; color: var(--text-secondary);
  transition: background 120ms, color 120ms; position: relative;
}
.tb-btn:hover { background: var(--body-bg); color: var(--text); }

.theme-toggle .theme-icon-light { display: none; }
.theme-toggle .theme-icon-dark { display: block; }
[data-theme=dark] .theme-toggle .theme-icon-light { display: block; }
[data-theme=dark] .theme-toggle .theme-icon-dark { display: none; }

.tb-avatar {
  width: 32px; height: 32px; border-radius: 50%; border: none;
  background: linear-gradient(135deg, var(--primary), var(--primary-dk));
  display: flex; align-items: center; justify-content: center;
  font: inherit; font-size: 12px; font-weight: 600; color: #fff;
  margin-left: 6px; cursor: pointer; padding: 0; transition: transform 120ms;
}
.tb-avatar:hover { transform: scale(1.06); }

/* --- Dropdown nativo do Bootstrap (menu do usuário, "mais opções") -------
 * Sem isto o menu sai no tamanho padrão do Bootstrap, destoando da
 * densidade compacta do resto do painel (painel.css, .form-control/
 * .form-select). display:flex + gap alinha ícone e texto quando o item
 * tem ícone (ex.: Excluir no menu de três pontinhos), sem afetar os itens
 * só-texto que já existiam (Meu perfil, Sair). */
.dropdown-menu { font-size: .8125rem; }
.dropdown-item { padding: .375rem .75rem; display: flex; align-items: center; gap: .5rem; }
.dropdown-item i.icon { font-size: .8125rem; }

.page-wrapper { padding: 20px 24px 40px; }
@media (max-width: 768px) {
  .page-wrapper { padding: 12px; }
}

/* --- Barra de ações fixa do topo de uma tela de detalhe ----------------
 * Renderizada pelo LAYOUT (painel.php ▸ $barraFixaTopo), FORA do
 * .page-wrapper e logo abaixo da topbar — não dentro do fluxo normal do
 * conteúdo, que tem padding próprio. position: sticky gruda embaixo da
 * topbar (fixed, 56px, z-index 90) assim que a rolagem a alcança — sem JS,
 * sem duplicar o cabeçalho da página. Colada sem padding próprio (o
 * afastamento é só do que vem DEPOIS, dentro do page-wrapper — ver
 * .page-wrapper's primeiro filho, tratado à parte). */
.barra-fixa-topo {
  position: sticky; top: 56px; z-index: 80;
  display: flex; align-items: center; justify-content: space-between;
  flex-wrap: wrap; gap: 12px;
  background: var(--bg-surface); border-bottom: 1px solid var(--border-color-light);
  box-shadow: var(--shadow);
  padding: 10px 24px;
}
.barra-fixa-topo__nome { font-size: 15px; font-weight: var(--font-weight-bold); color: var(--text); line-height: 1.3; }
/* Segunda linha genérica — CNPJ do lead, cliente/lead vinculado ao negócio... */
.barra-fixa-topo__subtitulo { font-size: 12px; color: var(--text-secondary); }
/* .barra-fixa-topo__acoes só precisa do .btn-list (já tem display:flex,
   gap e wrap) — sem regra própria, pra não duplicar a mesma declaração. */

@media print {
  .sidebar, .topbar, .footer, .skip-link, .sidebar-backdrop,
  .menu-popover, .breadcrumb { display: none !important; }
  .page-wrapper { padding: 0 !important; max-width: none !important; }
  .card, .invoice { box-shadow: none !important; border: none !important; page-break-inside: avoid; }
}

/* --- Cabeçalho de página ----------------------------------------------- */
.page-header { margin-bottom: 20px; }
.page-title { font-size: 18px; font-weight: 600; line-height: 1.3; color: var(--text); margin: 0; }
.page-subtitle { font-size: 12.5px; color: var(--text-muted); margin-top: 2px; }
.btn-list { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }

/* --- Marca da Otimizer (parcial marca-otimizer.php) ---------------------
 * A arte vendorizada (public/assets/img/marca/) é um PNG branco — o recorte
 * exato do vetor original, sem cor. tom="inverso" usa esse PNG direto num
 * <img>; qualquer outro tom tinge o MESMO recorte por mask-image (o alfa do
 * PNG vira a máscara), então a geometria nunca é redesenhada. O @supports
 * é obrigatório: sem ele, um navegador sem mask-image pintaria um
 * RETÂNGULO SÓLIDO na cor de fundo em vez de sumir com a marca — por isso
 * só a largura/altura (que não desenham nada sozinhas) ficam fora do bloco,
 * e toda regra de `background-color` fica dentro.
 */
.marca-otimizer { display: inline-block; flex-shrink: 0; }
span.marca-otimizer { height: var(--marca-altura, 20px); }
.marca-otimizer--horizontal { width: calc(var(--marca-altura, 20px) * 4.09); }
.marca-otimizer--simbolo { width: var(--marca-altura, 20px); }
@supports (mask-image: url('')) or (-webkit-mask-image: url('')) {
  span.marca-otimizer {
    -webkit-mask: var(--marca-arte) center / contain no-repeat;
            mask: var(--marca-arte) center / contain no-repeat;
  }
  .marca-otimizer--petrol { background-color: var(--otimizer-petrol); }
  .marca-otimizer--laranja { background-color: var(--otimizer-laranja); }
  .marca-otimizer--atual { background-color: currentColor; }
}


/* --- Página de autenticação ----------------------------------------------
 * Duas colunas: formulário PRIMEIRO no DOM (ordem de Tab/leitor de tela
 * chega ao campo de e-mail antes de qualquer link de propaganda), vitrine
 * da Otimizer depois. Abaixo de 992px a vitrine sai da tela — decoração não
 * compete por espaço com o formulário no celular.
 */
.auth-split { display: flex; min-height: 100vh; }
.auth-split-form {
  flex: 0 0 clamp(380px, 42%, 560px);
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  background: var(--bg-surface); padding: 24px;
}
.auth-card { width: 100%; max-width: 400px; }
.auth-split-vitrine { flex: 1 1 auto; }
@media (max-width: 991.98px) {
  .auth-split-vitrine { display: none; }
  .auth-split-form { flex: 1 1 auto; }
}

.auth-brand { display: flex; align-items: center; gap: 10px; margin-bottom: 24px; }
/* Arte colorida (450×162), plana — sem mask-image, então a altura sozinha
   já basta pro navegador escalar mantendo a proporção. */
.auth-brand-otimizer { height: 72px; width: auto; }
.auth-title { font-size: 20px; font-weight: 600; color: var(--text); margin-bottom: 4px; letter-spacing: -0.3px; }
.auth-subtitle { font-size: 13px; color: var(--text-muted); margin-bottom: 24px; }
.auth-actions { display: flex; align-items: center; justify-content: space-between; margin: 16px 0; font-size: 12.5px; }
.auth-actions a { color: var(--primary); font-weight: var(--font-weight-medium); }
/* margin-top bem maior que o gap interno (4px): "Desenvolvido por Otimizer"
   e a versão ficam coladas uma na outra, só o bloco inteiro desce, longe do
   formulário — pedido do usuário. */
.auth-footer { text-align: center; font-size: 12.5px; color: var(--text-muted); margin-top: 48px; display: flex; flex-direction: column; gap: 4px; align-items: center; }
.auth-footer a { color: var(--primary); font-weight: var(--font-weight-medium); }
.auth-footer .marca-otimizer { vertical-align: -3px; margin-right: 4px; }

/* --- Vitrine da Otimizer (parcial otimizer-vitrine.php, coluna direita do
   login) --------------------------------------------------------------- */
.otimizer-vitrine {
  position: relative; height: 100%; overflow: hidden;
  display: flex; flex-direction: column; justify-content: space-between;
  padding: 56px 48px; color: #fff;
  background:
    repeating-linear-gradient(45deg, rgba(255, 255, 255, .035) 0 2px, transparent 2px 28px),
    linear-gradient(160deg, var(--otimizer-petrol) 0%, #082635 100%);
}
.otimizer-vitrine .vitrine-marca { margin-bottom: 40px; }
.otimizer-vitrine h2 { font-size: 30px; font-weight: 700; line-height: 1.25; margin-bottom: 12px; letter-spacing: -0.4px; }
.otimizer-vitrine .vitrine-subtitulo { font-size: 15px; color: rgba(255, 255, 255, .72); max-width: 420px; margin-bottom: 40px; }
.otimizer-vitrine .vitrine-destaques { display: flex; flex-direction: column; gap: 18px; margin-bottom: auto; }
.otimizer-vitrine .vitrine-destaque { display: flex; align-items: flex-start; gap: 14px; }
.otimizer-vitrine .vitrine-destaque .icon {
  width: 36px; height: 36px; flex-shrink: 0; border-radius: 9px;
  background: rgba(255, 255, 255, .12); display: flex; align-items: center; justify-content: center;
  font-size: 15px;
}
.otimizer-vitrine .vitrine-destaque strong { display: block; font-size: 14px; font-weight: 600; }
.otimizer-vitrine .vitrine-destaque span { font-size: 13px; color: rgba(255, 255, 255, .65); }
.otimizer-vitrine .vitrine-cta {
  display: inline-flex; align-items: center; gap: 8px; align-self: flex-start;
  background: var(--otimizer-laranja); color: #fff; font-weight: 600; font-size: 14px;
  padding: 10px 20px; border-radius: var(--radius); text-decoration: none; margin-top: 32px;
  transition: filter 150ms;
}
.otimizer-vitrine .vitrine-cta:hover { filter: brightness(1.08); color: #fff; }
.otimizer-vitrine .vitrine-rodape {
  display: flex; flex-wrap: wrap; gap: 4px 16px; font-size: 12.5px;
  color: rgba(255, 255, 255, .55); padding-top: 24px; border-top: 1px solid rgba(255, 255, 255, .12);
}
.otimizer-vitrine .vitrine-rodape a { color: rgba(255, 255, 255, .8); text-decoration: none; }
.otimizer-vitrine .vitrine-rodape a:hover { color: #fff; }

/* --- Cartão ------------------------------------------------------------ */
.card {
  background: var(--bg-surface); border: 1px solid var(--border-color);
  border-radius: var(--radius-lg); box-shadow: var(--shadow);
  transition: box-shadow 150ms;
}
.card-header {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--space-4); padding: 12px 16px;
  border-bottom: 1px solid var(--border-color-light); min-height: 44px;
}
.card-title { font-size: 13px; font-weight: var(--font-weight-bold); color: var(--text); }
.card-body { padding: 16px; }
.card-body.p-0 { padding: 0; }
.card-footer { padding: 10px 16px; border-top: 1px solid var(--border-color-light); }
.card-sm .card-body { padding: .75rem 1rem; }
/* Slot direito do cabeçalho: badge de situação, botão pequeno ou frase de
   apoio. margin-left:auto garante a borda direita mesmo quando o header
   tem só este filho. */
.card-actions { display: flex; align-items: center; gap: var(--space-2); margin-left: auto; }

/* --- Botão --------------------------------------------------------------
 * .btn do Bootstrap tem ~38px de altura e padding generoso — o painel usa
 * 32px, pensado para telas com muito registro por página. Nomes de classe
 * batem com o Bootstrap (btn-primary/-success/-warning/-danger); o
 * conteúdo é nosso, sobrescrevendo por ordem de cascata. */
.btn {
  display: inline-flex; align-items: center; gap: 5px; height: 32px;
  padding: 0 12px; border-radius: var(--radius-sm); font: inherit;
  font-size: 12.5px; font-weight: var(--font-weight-medium); cursor: pointer;
  border: 1px solid transparent;
  transition: background 120ms, border-color 120ms, color 120ms, box-shadow 120ms;
  line-height: 1; white-space: nowrap;
}
.btn svg { width: 14px; height: 14px; }
.btn[aria-busy=true] { pointer-events: none; opacity: .85; }
.btn-icon { width: 32px; padding: 0; justify-content: center; }
.btn-icon.btn-sm { width: 28px; }

.btn-primary { background: var(--primary); color: #fff; border-color: var(--primary-dk); }
.btn-primary:hover { background: var(--primary-dk); }
.btn-success { background: var(--green); color: #fff; border-color: #1a8a32; }
.btn-success:hover { background: #1a8a32; }
.btn-warning { background: var(--yellow); color: #fff; border-color: #c97f00; }
.btn-warning:hover { background: #c97f00; }
.btn-danger { background: var(--red); color: #fff; border-color: #a82b2b; }
.btn-danger:hover { background: #a82b2b; }

.btn-ghost { background: transparent; color: var(--text-secondary); border-color: transparent; box-shadow: none; }
.btn-ghost:hover { background: var(--bg-surface-secondary); color: var(--text); }
.btn-ghost-secondary { background: transparent; color: var(--text-secondary); border-color: transparent; box-shadow: none; }
.btn-ghost-secondary:hover { background: var(--bg-surface-secondary); color: var(--text); }
.btn-ghost-warning { background: transparent; color: var(--yellow); border-color: transparent; box-shadow: none; }
.btn-ghost-warning:hover { background: var(--yellow-lt); }
.btn-ghost-success { background: transparent; color: var(--green); border-color: transparent; box-shadow: none; }
.btn-ghost-success:hover { background: var(--green-lt); }
.btn-ghost-danger { background: transparent; color: var(--red); border-color: transparent; box-shadow: none; }
.btn-ghost-danger:hover { background: var(--red-lt); }

.btn-outline-secondary { background: var(--bg-surface); color: var(--text-secondary); border-color: var(--border-color); box-shadow: var(--shadow); }
.btn-outline-secondary:hover { background: var(--bg-surface-secondary); color: var(--text); }
.btn-outline-primary { background: var(--bg-surface); color: var(--primary); border-color: var(--primary); box-shadow: var(--shadow); }
.btn-outline-primary:hover { background: var(--primary-lt); color: var(--primary); }
.btn-outline-success { background: var(--bg-surface); color: var(--green); border-color: var(--green); box-shadow: var(--shadow); }
.btn-outline-success:hover { background: var(--green-lt); color: var(--green); }
.btn-outline-danger { background: var(--bg-surface); color: var(--red); border-color: var(--red); box-shadow: var(--shadow); }
.btn-outline-danger:hover { background: var(--red-lt); color: var(--red); }
.btn-outline-warning { background: var(--bg-surface); color: var(--yellow); border-color: var(--yellow); box-shadow: var(--shadow); }
.btn-outline-warning:hover { background: var(--yellow-lt); color: var(--yellow); }

.btn-group .btn { border-radius: 0; margin-right: -1px; }
.btn-group .btn:hover,
.btn-group .btn.active { z-index: 1; }
.btn-group .btn:first-child { border-top-left-radius: var(--radius-sm); border-bottom-left-radius: var(--radius-sm); }
.btn-group .btn:last-child { border-top-right-radius: var(--radius-sm); border-bottom-right-radius: var(--radius-sm); margin-right: 0; }
.btn-group .btn.active { background: var(--primary-lt); color: var(--primary); border-color: var(--primary); }

/* --- Tabela -------------------------------------------------------------
 * O `table.` no seletor é deliberado: dá especificidade extra sobre a
 * regra de densidade do painel.css (mesma especificidade, carrega antes),
 * então o padrão vence por ordem de origem se este prefixo sumir. */
table.table { width: 100%; border-collapse: collapse; font-size: 13px; }
table.table th {
  text-align: left; padding: 8px 16px; font-size: 11px;
  font-weight: var(--font-weight-bold); text-transform: uppercase;
  letter-spacing: .3px; color: var(--text-muted);
  background: var(--bg-surface-secondary); border-bottom: 1px solid var(--border-color);
}
table.table td { padding: 8px 16px; border-bottom: 1px solid var(--border-color-light); color: var(--text-secondary); vertical-align: middle; }
table.table tr:last-child td { border-bottom: none; }
table.table tbody tr { transition: background 80ms; }
table.table tbody tr:hover { background: var(--bg-surface-secondary); }
table.table-sm > :not(caption) > * > * { padding: .25rem .5rem; }
table.table-transparent th,
table.table-transparent td { background: transparent; }
table.table-transparent tbody tr:hover { background: transparent; }

/* --- Formulário ----------------------------------------------------------
 * form-control/form-select/form-check reescritos por completo — check/
 * radio sem depender da imagem SVG de fundo que o Bootstrap usa (evita
 * fetch de data-URI a cada estado, e o anel de foco fica no mesmo tom das
 * demais bordas do painel). */
.form-label { display: block; font-size: 12px; font-weight: var(--font-weight-medium); color: var(--text); margin-bottom: 6px; }
.form-label .required { color: var(--red); margin-left: 2px; }

.form-control,
.form-select {
  display: block; width: 100%; height: 36px; padding: 0 12px;
  font: inherit; font-size: 13px; color: var(--text);
  background: var(--bg-surface); border: 1px solid var(--border-color);
  border-radius: var(--radius-sm); outline: none;
  transition: border-color 150ms, box-shadow 150ms;
}
.form-control::placeholder { color: var(--text-disabled); }
.form-control:hover:not(:focus):not(:disabled),
.form-select:hover:not(:focus):not(:disabled) { border-color: var(--text-muted); }
.form-control:focus,
.form-select:focus { border-color: var(--primary); box-shadow: 0 0 0 3px var(--primary-lt); }
.form-control:disabled,
.form-select:disabled { background: var(--bg-surface-secondary); color: var(--text-muted); cursor: not-allowed; }
.form-control.is-invalid { border-color: var(--red); }
.form-control.is-invalid:focus { box-shadow: 0 0 0 3px var(--red-lt); }
.form-control[readonly] { background: var(--bg-surface-secondary); color: var(--text-secondary); }

textarea.form-control { height: auto; min-height: 90px; padding: 8px 12px; resize: vertical; line-height: 1.5; }

.form-select {
  appearance: none; -webkit-appearance: none; padding-right: 32px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12' fill='none' stroke='%239ba5b1' stroke-width='1.5'%3E%3Cpath d='M3 5l3 3 3-3'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 10px center; cursor: pointer;
}

.form-control-sm,
.form-select-sm { height: 28px; padding: 0 8px; font-size: 12.5px; }

.form-check { display: flex; align-items: center; gap: var(--space-2); font-size: 13px; color: var(--text); cursor: pointer; padding: 4px 0; }
.form-check input[type=checkbox],
.form-check input[type=radio] {
  appearance: none; -webkit-appearance: none; width: 16px; height: 16px; margin: 0;
  border: 1.5px solid var(--border-color); border-radius: var(--radius-sm);
  background: var(--bg-surface); cursor: pointer;
  transition: background 120ms, border-color 120ms; flex-shrink: 0; position: relative;
}
.form-check input[type=radio] { border-radius: 50%; }
.form-check input:hover { border-color: var(--primary); }
.form-check input:checked { background: var(--primary); border-color: var(--primary); }
.form-check input[type=checkbox]:checked::after {
  content: ""; position: absolute; top: 50%; left: 50%;
  transform: translate(-50%, -55%) rotate(45deg);
  width: 4px; height: 8px; border-right: 1.5px solid #fff; border-bottom: 1.5px solid #fff;
}
.form-check input[type=radio]:checked::after {
  content: ""; position: absolute; top: 50%; left: 50%;
  transform: translate(-50%, -50%); width: 6px; height: 6px;
  border-radius: 50%; background: #fff;
}
.form-check input:focus-visible { box-shadow: 0 0 0 3px var(--primary-lt); }
.form-check:has(> .form-check-description) { flex-wrap: wrap; align-items: flex-start; }
.form-check-description { flex-basis: 100%; padding-left: 24px; font-size: 11.5px; color: var(--text-muted); }
.form-check-inline { display: inline-flex; margin-right: var(--space-3); }
.form-group { display: block; margin-bottom: 16px; }
.form-hint { font-size: 11.5px; color: var(--text-muted); margin-top: 4px; }
.form-error { font-size: 11.5px; color: var(--red); margin-top: 4px; }
.card-subtitle { font-size: 11.5px; color: var(--text-muted); font-weight: var(--font-weight-normal); margin-top: 1px; }

/* Sufixo/prefixo ESTÁTICO de campo (texto, não botão) — diferente de
   .input-affix .affix-btn (ação clicável) logo acima. */
.input-affix .affix {
  display: flex; align-items: center; padding: 0 12px;
  font-size: 12.5px; color: var(--text-muted); background: var(--bg-surface-secondary);
  white-space: nowrap; border-left: 1px solid var(--border-color);
}
.input-affix .affix.prefix { border-left: 0; border-right: 1px solid var(--border-color); }

/* Interruptor liga/desliga (checkbox estilizado como toggle). */
.switch { position: relative; display: inline-flex; align-items: center; cursor: pointer; gap: 10px; }
.switch input { position: absolute; opacity: 0; pointer-events: none; }
.switch .track {
  width: 36px; height: 20px; background: var(--border-color); border-radius: 999px;
  position: relative; transition: background 150ms; flex-shrink: 0;
}
.switch .track::before {
  content: ""; position: absolute; left: 2px; top: 2px; width: 16px; height: 16px;
  background: #fff; border-radius: 50%; box-shadow: 0 1px 3px rgba(0, 0, 0, .16);
  transition: transform 150ms;
}
.switch input:checked + .track { background: var(--primary); }
.switch input:checked + .track::before { transform: translateX(16px); }
.switch input:focus-visible + .track { box-shadow: 0 0 0 3px var(--primary-lt); }
.switch .switch-label { font-size: 13px; color: var(--text); }

/* Grupo de input com ícone à esquerda — o ícone fica fixo, input cresce.
   Mesmo molde de .input-affix logo abaixo (borda/fundo/raio no CONTÊINER,
   não no <input> sozinho): sem isso o ícone ficava com fundo mas sem
   borda nenhuma, e o input perdia a borda esquerda sem nada visível no
   lugar — a caixa de e-mail do login não bem casava com o olho da senha.
   :has(.input-icon) escopa o tratamento a ESTE padrão: .input-group
   também é nome nativo do Bootstrap (ex.: parcial('comercial-totais'), com
   .input-group-text), que já resolve a própria borda pelos filhos e não
   pode ganhar um contêiner bordado por cima. */
.input-group { position: relative; display: flex; align-items: center; width: 100%; }
.input-group:has(.input-icon) {
  border: 1px solid var(--border-color); border-radius: var(--radius-sm);
  background: var(--bg-surface); overflow: hidden;
  transition: border-color 150ms, box-shadow 150ms;
}
.input-icon {
  display: flex; align-items: center; justify-content: center; padding: 0 12px;
  background: var(--bg-surface-secondary); color: var(--text-muted); flex-shrink: 0;
  border-right: 1px solid var(--border-color);
}
.input-group:has(.input-icon) .form-control { flex: 1; border: 0; border-radius: 0; padding-left: 12px; min-width: 0; }
.input-group:has(.input-icon) .form-control:focus { box-shadow: none; }
.input-group:has(.input-icon):focus-within { border-color: var(--primary); box-shadow: 0 0 0 3px var(--primary-lt); }

/* Botão dentro de .input-affix (ex.: mostrar/ocultar senha). */
.input-affix {
  display: flex; align-items: center;
  border: 1px solid var(--border-color); border-radius: var(--radius-sm);
  background: var(--bg-surface); overflow: hidden;
  transition: border-color 150ms, box-shadow 150ms;
}
.input-affix .form-control { flex: 1; border: 0; border-radius: 0; min-width: 0; }
.input-affix .form-control:focus { box-shadow: none; }
.input-affix .affix-btn {
  display: flex; align-items: center; justify-content: center;
  padding: 0 12px; border: none; border-left: 1px solid var(--border-color);
  background: var(--bg-surface-secondary); color: var(--text-muted);
  font: inherit; cursor: pointer; transition: color 100ms, background 100ms;
  height: inherit;
}
.input-affix .affix-btn:hover { color: var(--text); background: var(--body-bg); }

/* --- Badge --------------------------------------------------------------- */
.badge { display: inline-flex; align-items: center; padding: 2px 8px; border-radius: 999px; font-size: 11px; font-weight: var(--font-weight-medium); line-height: 1.6; }
/* !important em toda utilitária de fundo E cor daqui pra baixo — molde do
 * Bootstrap real (.bg-primary etc. já nascem !important lá, ver
 * bootstrap.min.css). Sem isso, `avatar bg-success-lt` saía com o gradiente
 * de marca do `.avatar` (que TAMBÉM declara `background`, mesma
 * especificidade de classe única): no CSS antigo cada um vinha de um
 * ARQUIVO diferente (gentelella.css vs. extensoes.css, que carregava depois
 * e por isso vencia); os dois caindo no mesmo arquivo inverteu quem vence
 * por ordem de declaração — e uma utilitária que perde pro componente que
 * ela deveria colorir não é utilitária. Achado renderizando a tela de
 * conclusão do instalador. O `color` tinha o MESMO problema e ficou de fora
 * daquele conserto: `.avatar` também declara `color: #fff` (mesma
 * especificidade), então as iniciais de `avatar_usuario()` saíam brancas
 * sobre o fundo claro do `-lt` — invisíveis no tema claro (o escuro
 * escondia o bug, porque lá o fundo `-lt` é escuro o bastante pro branco
 * continuar legível). Achado renderizando a faixa de projeto e a guia
 * Equipe. */
.bg-primary-lt { background: var(--primary-lt) !important; color: var(--primary) !important; }
.bg-success-lt { background: var(--green-lt) !important; color: var(--green) !important; }
.bg-secondary-lt { background: var(--bg-surface-secondary) !important; color: var(--text-secondary) !important; }
.bg-danger-lt { background: var(--red-lt) !important; color: var(--red) !important; }
.bg-warning-lt { background: var(--yellow-lt) !important; color: #b45309 !important; }
.bg-info-lt { background: var(--blue-lt) !important; color: var(--blue) !important; }
.bg-purple-lt { background: var(--purple-lt) !important; color: var(--purple) !important; }
.bg-cyan-lt { background: var(--cyan-lt) !important; color: var(--cyan) !important; }
.bg-orange-lt { background: var(--orange-lt) !important; color: var(--orange) !important; }

.bg-primary   { background: var(--primary) !important; }
.bg-blue      { background: var(--blue) !important; }
.bg-azure     { background: var(--azure) !important; }
.bg-indigo    { background: var(--indigo) !important; }
.bg-purple    { background: var(--purple) !important; }
.bg-pink      { background: var(--pink) !important; }
.bg-red       { background: var(--red) !important; }
.bg-orange    { background: var(--orange) !important; }
.bg-yellow    { background: var(--yellow) !important; }
.bg-lime      { background: var(--lime) !important; }
.bg-green     { background: var(--green) !important; }
.bg-cyan      { background: var(--cyan) !important; }
.bg-secondary { background: var(--text-secondary) !important; }
.bg-success   { background: var(--green) !important; }
.bg-danger    { background: var(--red) !important; }
.bg-warning   { background: var(--yellow) !important; }
.bg-info      { background: var(--blue) !important; }
.bg-transparent { background: transparent !important; }
.bg-body-tertiary { background: var(--bg-surface-secondary) !important; }

/* --- Alerta --------------------------------------------------------------
 * Sem dismiss embutido do Bootstrap: .btn-close aqui é nosso, glifo "x"
 * via Font Awesome (ver flash.php), fechado por painel.js
 * (data-fechar-alerta), não data-bs-dismiss. */
.alert { position: relative; display: flex; align-items: flex-start; gap: 8px; padding: 12px 40px 12px 14px; border: 1px solid; border-radius: var(--radius); font-size: 13px; line-height: 1.45; }
.alert-danger { color: var(--red); border-color: rgba(214, 57, 57, .2); background: var(--red-lt); }
.alert-success { color: var(--green); border-color: rgba(47, 179, 68, .2); background: var(--green-lt); }
.alert-warning { color: #b45309; border-color: rgba(245, 159, 0, .2); background: var(--yellow-lt); }
.alert-info { color: var(--blue); border-color: rgba(6, 111, 209, .2); background: var(--blue-lt); }
.alert-title { font-size: 13px; font-weight: var(--font-weight-bold); color: inherit; margin: 0 0 4px; }
.alert-dismissible .btn-close {
  position: absolute; top: 8px; right: 8px;
  width: 24px; height: 24px; padding: 0;
  display: flex; align-items: center; justify-content: center;
  background: transparent; border: none; border-radius: var(--radius-sm);
  color: currentColor; opacity: .6; cursor: pointer;
}
.alert-dismissible .btn-close:hover { opacity: 1; background: rgba(0, 0, 0, .06); }
.alert .alert-icon { width: 16px; height: 16px; flex-shrink: 0; margin-top: 1px; }
.alert .alert-body { flex: 1; }

/* --- Barra de progresso --------------------------------------------------- */
.progress { height: 8px; background: var(--bg-surface-secondary); border-radius: 999px; overflow: hidden; display: flex; }
.progress-sm { height: 5px; }
.progress-bar { height: 100%; background: var(--primary); border-radius: 999px; transition: width 200ms ease; }

/* --- Avatar --------------------------------------------------------------- */
.avatar {
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 50%; font-weight: var(--font-weight-bold); color: #fff;
  background: linear-gradient(135deg, var(--primary), var(--primary-dk));
  flex-shrink: 0; position: relative; text-transform: uppercase;
  font-size: 11px; line-height: 1; width: 32px; height: 32px; overflow: hidden;
}
.avatar.avatar-image { background: var(--bg-surface-secondary); overflow: hidden; }
.avatar.avatar-image img,
.avatar.avatar-image svg { width: 100%; height: 100%; object-fit: cover; }
.avatar-rounded { border-radius: 50%; }
.avatar-xs { width: 20px; height: 20px; font-size: 8.5px; }
.avatar-sm { width: 26px; height: 26px; font-size: 10px; }
.avatar-md { width: 32px; height: 32px; font-size: 11px; }
.avatar-xl { width: 64px; height: 64px; font-size: 20px; }
.avatars { display: flex; }
.avatar-stack .avatar { border: 2px solid var(--bg-surface); margin-left: -8px; }
.avatar-stack .avatar:first-child { margin-left: 0; }
.avatar-stack .avatar.more { background: var(--bg-surface-secondary); color: var(--text-secondary); }

/* --- Estado vazio --------------------------------------------------------- */
.empty-state {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  text-align: center; padding: 48px 24px; color: var(--text-muted); gap: 6px;
}
.empty-state-icon {
  width: 48px; height: 48px; border-radius: 50%; background: var(--bg-surface-secondary);
  color: var(--text-muted); display: flex; align-items: center; justify-content: center;
  margin-bottom: 8px;
}
.empty-state-title { font-size: 14px; font-weight: var(--font-weight-medium); color: var(--text); }
.empty-state-text { font-size: 12.5px; max-width: 320px; line-height: 1.5; }
.empty-state-actions { margin-top: 12px; display: flex; gap: var(--space-2); }
/* Número grande das páginas de erro (404, 403...) — cenário, não informação;
   o título e a mensagem abaixo dele é que dizem o que houve. */
.empty-state-header { font-size: 3.5rem; font-weight: var(--font-weight-bold); line-height: 1; color: var(--text-disabled); margin-bottom: 8px; }

/* --- Cartão de estatística -------------------------------------------------- */
.stat { display: flex; align-items: center; gap: 14px; padding: 16px; }
.stat-icon { width: 40px; height: 40px; border-radius: var(--radius); display: flex; align-items: center; justify-content: center; flex-shrink: 0; }
.stat-icon.teal { background: var(--primary-lt); color: var(--primary); }
.stat-icon.blue { background: var(--blue-lt); color: var(--blue); }
.stat-icon.green { background: var(--green-lt); color: var(--green); }
.stat-icon.yellow { background: var(--yellow-lt); color: var(--yellow); }
.stat-icon.red { background: var(--red-lt); color: var(--red); }
.stat-icon.purple { background: var(--purple-lt); color: var(--purple); }
.stat-content { flex: 1; min-width: 0; }
.stat-label { font-size: 11.5px; color: var(--text-muted); font-weight: var(--font-weight-medium); text-transform: uppercase; letter-spacing: .3px; line-height: 1.3; }
.stat-value-row { display: flex; align-items: baseline; gap: var(--space-2); }
.stat-value { font-size: 22px; font-weight: 600; letter-spacing: -0.5px; line-height: 1.2; }
.stat-change { font-size: 11px; font-weight: var(--font-weight-bold); display: inline-flex; align-items: center; gap: 1px; }
.stat-change.up { color: var(--green); }
.stat-change.down { color: var(--red); }
.stat-subtext { font-size: 11px; color: var(--text-muted); margin-top: 2px; }
.stat-spark { display: flex; align-items: flex-end; gap: 2px; height: 28px; flex-shrink: 0; }
.stat-spark .bar { width: 4px; border-radius: 2px; background: var(--primary); opacity: .25; transition: height .3s ease; }
.stat-spark .bar:nth-child(odd) { opacity: .4; }
.stat-spark .bar:last-child { opacity: .8; }
.detail-stats .stat-block .label { font-size: 11px; font-weight: var(--font-weight-medium); color: var(--text-muted); text-transform: uppercase; letter-spacing: .3px; margin-bottom: 4px; }
.detail-stats .stat-block .value { font-size: 18px; font-weight: var(--font-weight-bold); color: var(--text); margin-bottom: 6px; }
.detail-stats .stat-block .progress-thin { margin-top: 4px; }

/* --- Indicador inline de situação ------------------------------------------- */
.status { display: inline-flex; align-items: center; gap: var(--space-1); font-size: 11.5px; font-weight: var(--font-weight-medium); }
.status::before { content: ""; width: 6px; height: 6px; border-radius: 50%; flex-shrink: 0; }
.status-green { color: var(--green); }
.status-green::before { background: var(--green); }
.status-yellow { color: #b45309; }
.status-yellow::before { background: var(--yellow); }
.status-blue { color: var(--blue); }
.status-blue::before { background: var(--blue); }
.status-red { color: var(--red); }
.status-red::before { background: var(--red); }

/* --- Timeline (CRM, Chamados, Projetos) ------------------------------------- */
.timeline { position: relative; padding-left: 24px; }
.timeline::before { content: ""; position: absolute; left: 7px; top: 6px; bottom: 6px; width: 2px; background: var(--border-color); border-radius: 2px; }
.timeline-item { position: relative; padding-bottom: 18px; }
.timeline-item:last-child { padding-bottom: 0; }
.timeline-item::before { content: ""; position: absolute; left: -22px; top: 4px; width: 12px; height: 12px; border-radius: 50%; background: var(--bg-surface); border: 2px solid var(--border-color); }
.timeline-item.is-primary::before { border-color: var(--primary); background: var(--primary); }
.timeline-item.is-green::before { border-color: var(--green); background: var(--green); }
.timeline-item.is-yellow::before { border-color: var(--yellow); background: var(--yellow); }
.timeline-item.is-red::before { border-color: var(--red); background: var(--red); }
.timeline-item.is-blue::before { border-color: var(--blue); background: var(--blue); }
.timeline-item .ti-time { font-size: 11px; color: var(--text-muted); margin-bottom: 2px; }
.timeline-item .ti-title { font-size: 13px; font-weight: var(--font-weight-medium); color: var(--text); }
.timeline-item .ti-desc { font-size: 12.5px; color: var(--text-secondary); margin-top: 2px; line-height: 1.5; }

/* --- Leitura de HTML rico já sanitizado (HtmlRico::sanitizar) --------------
   Onde o texto do Quill é exibido de volta, cru (nunca por e() — a formatação
   viraria texto escapado na tela). Vídeo com proporção fixa, mesmo tamanho
   do editor (tema-painel.css); parágrafo/lista sem sobra de margem no fim. */
.html-rico > :last-child { margin-bottom: 0; }
.html-rico blockquote { border-left: 3px solid var(--border-color); padding-left: 12px; color: var(--text-secondary); margin-left: 0; }
.html-rico iframe { width: 100%; max-width: 480px; aspect-ratio: 16 / 9; border: 0; }

/* --- Lista como conteúdo de card --------------------------------------------
 * .list-group do Bootstrap tem borda/raio próprios, pensados para uso
 * solto — dentro de um .card (única forma como este painel usa) isso vira
 * canto arredondado dentro de canto arredondado. -flush encosta na
 * parede; -transparent solta cada item como pílula, para lista que
 * funciona como navegação lateral. */
.list-group { display: flex; flex-direction: column; border: 1px solid var(--border-color); border-radius: var(--radius); overflow: hidden; }
.list-group-item {
  display: flex; align-items: center; gap: var(--space-3);
  padding: 10px 14px; background: var(--bg-surface); border-bottom: 1px solid var(--border-color-light);
  text-decoration: none; color: var(--text); font: inherit; font-size: 13px;
  cursor: pointer; transition: background 100ms, color 100ms; text-align: left; width: 100%;
}
.list-group-item:last-child { border-bottom: none; }
.list-group-item.active { background: var(--primary-lt); color: var(--primary); font-weight: var(--font-weight-medium); }
.list-group-flush { border: 0; border-radius: 0; }
.list-group-item-action { color: var(--text); text-align: inherit; width: 100%; }
.list-group-item-action:hover { background: var(--bg-surface-secondary); color: var(--text); text-decoration: none; }
.list-group-transparent { border: 0; border-radius: 0; background: transparent; gap: 2px; }
.list-group-transparent .list-group-item { background: transparent; border-bottom: 0; border-radius: var(--radius-sm); padding: 8px 10px; }
.list-group-transparent .list-group-item:hover { background: var(--bg-surface-secondary); }
.list-group-transparent .list-group-item.active { background: var(--primary-lt); color: var(--primary); }

/* --- Paginação (parciais/paginacao.php) -------------------------------------
 * Filhos DIRETOS (.page-link), não a lista ul>li.page-item>a do Bootstrap
 * — mais simples para o servidor montar, e o wrapper .page-item não traria
 * nada que o flex do pai já não resolva. Estado desabilitado vira <span>,
 * não <a href>: link sem destino de verdade não é o jeito certo de
 * desabilitar. */
.pagination { display: flex; align-items: center; gap: var(--space-1); list-style: none; padding: 12px 16px; border-top: 1px solid var(--border-color-light); margin: 0; }
.pagination .page-link {
  min-width: 28px; height: 28px; padding: 0 8px;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 12px; font-weight: var(--font-weight-medium); color: var(--text-secondary);
  background: var(--bg-surface); border: 1px solid var(--border-color);
  border-radius: var(--radius-sm); text-decoration: none;
  transition: background 100ms, color 100ms, border-color 100ms;
}
.pagination .page-link:hover { background: var(--bg-surface-secondary); color: var(--text); text-decoration: none; }
.pagination .page-link.active { background: var(--primary); color: #fff; border-color: var(--primary-dk); }
.pagination .page-link.disabled { color: var(--text-disabled); cursor: not-allowed; }

/* --- Filtro (<details> nativo, não collapse do Bootstrap) -------------------
 * O <summary> é só o rótulo acessível do disclosure (visually-hidden);
 * quem abre/fecha de verdade é o botão "Filtro" do cabeçalho, via
 * data-abrir-details em painel.js. */
#filtros > summary { list-style: none; }
#filtros > summary::-webkit-details-marker { display: none; }

/* --- Abas (parciais/abas-navegacao.php e afins) -----------------------------
 * Mecanismo próprio (data-abas/data-aba OU rota própria por caminho), não
 * Bootstrap tabs — ver PADROES-UI.md seção Abas. */
.tabs-underline {
  display: flex; border-bottom: 1px solid var(--border-color-light); gap: var(--space-1);
  overflow-x: auto; min-width: 0; scrollbar-width: thin;
}
.tabs-underline .tab {
  padding: 9px 14px 11px; background: transparent; border: none;
  border-bottom: 3px solid transparent; border-radius: var(--radius) var(--radius) 0 0;
  font: inherit; font-size: 13px; font-weight: var(--font-weight-medium); color: var(--text-muted);
  cursor: pointer; transition: color 100ms, border-color 100ms, background-color 100ms;
  margin-bottom: -1px; flex-shrink: 0;
}
.tabs-underline .tab:hover { color: var(--text); background: var(--bg-surface-secondary); }
.tabs-underline .tab.active {
  color: var(--primary); font-weight: var(--font-weight-bold);
  border-bottom-color: var(--primary); background: var(--primary-lt);
}
.tabs-underline a.tab:hover { text-decoration: none; }

/* --- Datagrid (par rótulo+valor em grade) ----------------------------------- */
.datagrid { display: grid; grid-template-columns: repeat(auto-fit, minmax(110px, 1fr)); gap: 12px 16px; }
.datagrid-item { min-width: 0; }
.datagrid-title { font-size: 12px; color: var(--text-muted); margin-bottom: 2px; }
.datagrid-content { font-size: 14px; font-weight: var(--font-weight-medium); color: var(--text); }

/* --- Quadro de instruções (parciais/ajuda.php) -------------------------------
 * Um .card cuja moldura é um <details>: aberto por padrão, fechável por
 * quem já conhece a tela — estado do navegador, sem JavaScript. */
.quadro-ajuda > summary { list-style: none; cursor: pointer; user-select: none; }
.quadro-ajuda > summary::-webkit-details-marker { display: none; }
.quadro-ajuda .quadro-ajuda-seta { color: var(--text-muted); transition: transform 150ms; }
.quadro-ajuda[open] .quadro-ajuda-seta { transform: rotate(90deg); }
.quadro-ajuda dt { color: var(--text); font-weight: var(--font-weight-medium); }
.quadro-ajuda dd:last-child { margin-bottom: 0; }

/* --- Rodapé de página -------------------------------------------------------- */
.footer {
  display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap;
  gap: 4px 16px; padding: 14px 24px; margin-top: auto;
  border-top: 1px solid var(--border-color-light);
  font-size: 12.5px; color: var(--text-muted);
}
.footer a { color: var(--text-secondary); text-decoration: none; }
.footer a:hover { color: var(--primary); }
/* O rodapé gruda no pé mesmo em tela curta: <main> vira coluna flex e
   .page-wrapper estica — margin-top:auto do .footer faz o resto. */
body[data-shell="admin"] .main { display: flex; flex-direction: column; min-height: 100vh; }
body[data-shell="admin"] .page-wrapper { flex: 1 1 auto; width: 100%; }

/* --- Kanban (CRM, Projetos, Chamados) ----------------------------------------
 * N colunas, todas na mesma linha, com rolagem horizontal quando não
 * couberem — o número de colunas é dinâmico (etapas/funil/situações
 * configuráveis por módulo). */
.kanban-board { display: flex; align-items: flex-start; gap: var(--space-4); overflow-x: auto; padding-bottom: 8px; }
.kanban-board > .kanban-column {
  /* Base da coluna: fundo/raio/padding/min-height/flex-column (empilha
     cabeçalho, corpo e rodapé) — e por cima, a variante de rolagem
     horizontal deste painel (largura fixa em vez de fração do grid, fundo
     um tom mais forte pra se destacar da página). */
  background: var(--bg-surface-secondary); border-radius: var(--radius-lg);
  padding: 8px; min-height: 200px;
  display: flex; flex-direction: column; gap: var(--space-2);
  flex: 0 0 280px; max-width: 320px;
  background: var(--bg-surface); border: 1px solid var(--border-color);
}
.kanban-column-head { display: flex; align-items: center; gap: var(--space-2); padding: 6px 8px; }
.kanban-column-head .title { font-size: 13px; font-weight: var(--font-weight-bold); color: var(--text); }
.kanban-column-head .dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; }
.kanban-column-head .count { font-size: 11px; color: var(--text-muted); background: var(--bg-surface); padding: 1px 8px; border-radius: 10px; font-weight: var(--font-weight-medium); }
.kanban-column-body {
  display: flex; flex-direction: column; gap: var(--space-2);
  min-height: 3rem; padding: 4px 0; border-radius: var(--radius);
  transition: background 100ms;
}
.kanban-add {
  margin-left: auto; width: 22px; height: 22px; border: none; background: transparent;
  border-radius: var(--radius-sm); font: inherit; font-size: 16px; color: var(--text-muted);
  cursor: pointer; display: flex; align-items: center; justify-content: center; line-height: 1;
}
.kanban-add:hover { background: var(--bg-surface); color: var(--text); }
.kanban-page { max-width: none !important; padding-bottom: 24px !important; }

.kanban-card {
  background: var(--bg-surface); border: 1px solid var(--border-color);
  border-radius: var(--radius); padding: 12px; cursor: grab;
  transition: border-color 120ms, box-shadow 120ms, transform 120ms, opacity 120ms;
  user-select: none;
}
.kanban-card:hover { border-color: var(--primary); box-shadow: 0 2px 8px rgba(15, 23, 42, .06); }
.kanban-card.dragging { opacity: .5; transform: rotate(1deg); cursor: grabbing; }
.kanban-card.arrastando { opacity: .5; }
.kanban-column-body.drop-target { background: var(--primary-lt); outline: 2px dashed var(--primary); outline-offset: -4px; }
.kanban-card-labels { display: flex; flex-wrap: wrap; gap: var(--space-1); margin-bottom: 8px; }
.kanban-card-title { font-size: 13px; font-weight: var(--font-weight-medium); color: var(--text); line-height: 1.4; margin-bottom: 4px; }
.kanban-card-desc {
  font-size: 12px; color: var(--text-muted); line-height: 1.45;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden; margin-bottom: 8px;
}
.kanban-card-foot { display: flex; align-items: center; justify-content: space-between; gap: var(--space-2); }
.kanban-card-meta { display: flex; align-items: center; gap: var(--space-1); font-size: 11px; color: var(--text-muted); }
.kanban-card-avatars { display: flex; align-items: center; }

/* Quem trabalha o negócio + há quanto tempo foi mexido pela última vez —
   ver docblock em src/Modulos/Crm/views/index.php (kanban). */
.kanban-card-interacao {
  display: flex; align-items: center; gap: var(--space-2);
  margin-top: var(--space-2); padding-top: var(--space-2);
  border-top: 1px dashed var(--border-color);
  font-size: 11px; color: var(--text-muted);
}

.kanban-label {
  font-size: 10px; font-weight: var(--font-weight-bold); padding: 1px 6px;
  border-radius: 3px; background: var(--primary-lt); color: var(--primary);
  text-transform: uppercase; letter-spacing: .3px;
}
.kanban-label-purple { background: var(--purple-lt); color: var(--purple); }
.kanban-label-blue { background: var(--blue-lt); color: var(--blue); }
.kanban-label-green { background: var(--green-lt); color: var(--green); }
.kanban-label-red { background: var(--red-lt); color: var(--red); }
.kanban-label-yellow { background: var(--yellow-lt); color: #b45309; }

.kanban-avatar {
  width: 22px; height: 22px; border-radius: 50%; background: var(--primary); color: #fff;
  font-size: 9.5px; font-weight: var(--font-weight-bold); display: inline-flex;
  align-items: center; justify-content: center; border: 2px solid var(--bg-surface); flex-shrink: 0;
}
.kanban-avatar + .kanban-avatar { margin-left: -6px; }

/* Coluna sem cartão nenhum — painel.js mostra/esconde durante o arrasto. */
.kanban-coluna-vazia { padding: 1rem; text-align: center; font-size: 12px; color: var(--text-muted); border: 1px dashed var(--border-color); border-radius: var(--radius-sm); }

/* --- Funil de vendas (dashboard do CRM) --------------------------------------
 * Trapézios de verdade, um empilhado sobre o outro — largura do topo e da
 * base vêm do servidor (--funil-topo/--funil-base, em %, calculadas em
 * dashboard.php); clip-path desenha o trapézio a partir das duas. */
.funil-vendas { display: flex; flex-direction: column; align-items: center; gap: 3px; max-width: 640px; margin: 0 auto; }
.funil-etapa {
  --funil-topo: 100%; --funil-base: 100%;
  width: 100%; min-height: 54px; display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: 8px; padding: 8px 20px;
  color: #fff; font-size: 13px; text-align: center;
  clip-path: polygon(
    calc((100% - var(--funil-topo)) / 2) 0%,
    calc(100% - (100% - var(--funil-topo)) / 2) 0%,
    calc(100% - (100% - var(--funil-base)) / 2) 100%,
    calc((100% - var(--funil-base)) / 2) 100%
  );
}
.funil-etapa .rotulo { font-weight: var(--font-weight-medium); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.funil-etapa .valor { font-variant-numeric: tabular-nums; white-space: nowrap; opacity: .9; }

/* --- Barra de etapas do negócio / situação da OS ----------------------------- */
.etapas-progresso { display: flex; align-items: flex-start; gap: 0; overflow-x: auto; padding: 4px 0 8px; }
.etapas-progresso .etapa { flex: 1 1 0; min-width: 110px; position: relative; text-align: center; padding: 0 8px; opacity: .55; }
.etapas-progresso .etapa.done,
.etapas-progresso .etapa.active { opacity: 1; }
.etapas-progresso .etapa .ponto {
  width: 12px; height: 12px; border-radius: 50%; background: var(--border-color);
  border: 2px solid var(--bg-surface); box-shadow: 0 0 0 1px var(--border-color);
  margin: 0 auto 6px; position: relative; z-index: 1;
}
.etapas-progresso .etapa.done .ponto { background: var(--primary); box-shadow: 0 0 0 1px var(--primary); }
.etapas-progresso .etapa.active .ponto { background: var(--primary); box-shadow: 0 0 0 3px var(--primary-lt), 0 0 0 1px var(--primary); }
.etapas-progresso .etapa.ganho .ponto { background: var(--green); box-shadow: 0 0 0 1px var(--green); }
.etapas-progresso .etapa.perdido .ponto { background: var(--red); box-shadow: 0 0 0 1px var(--red); }
.etapas-progresso .etapa + .etapa::before {
  content: ""; position: absolute; top: 5px; right: calc(50% + 14px); left: calc(-50% + 14px);
  height: 2px; background: var(--border-color);
}
.etapas-progresso .etapa.done + .etapa.done::before,
.etapas-progresso .etapa.done + .etapa.active::before,
.etapas-progresso .etapa.done + .etapa.ganho::before,
.etapas-progresso .etapa.done + .etapa.perdido::before { background: var(--primary); }
.etapas-progresso .etapa .titulo { font-size: 12.5px; font-weight: var(--font-weight-medium); color: var(--text); }
.etapas-progresso .etapa .sub { font-size: 11px; color: var(--text-muted); }

/* --- Temperatura (chamas 1–5 nos cartões do CRM) ----------------------------- */
.temperatura { display: inline-flex; align-items: center; gap: 1px; color: var(--text-disabled); }
.temperatura .aceso { color: var(--orange); }

/* --- Cartão de projeto (Projetos ▸ Lista, visão "blocos") -------------------- */
/* `cursor: pointer` do molde original NÃO entra: o cartão aqui não é um
   link único (tem botões de ação próprios dentro — Detalhar/Editar), então
   um cursor de clique na área vazia seria uma affordance falsa. */
.project-card {
  display: flex; flex-direction: column; gap: 10px; padding: 1rem;
  background: var(--bg-surface); border: 1px solid var(--border-color);
  border-radius: var(--radius); box-shadow: var(--shadow);
  transition: border-color 120ms, box-shadow 120ms;
}
.project-card .top { display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: 1rem; }
.project-card .title { font-size: 14px; font-weight: var(--font-weight-medium); color: var(--text); margin-bottom: 0.25rem; }
.project-card .client { font-size: 12px; color: var(--text-secondary); }
.project-card .footer-row {
  display: flex; align-items: center; justify-content: space-between;
  font-size: 12px; color: var(--text-secondary); padding-top: 0.75rem;
  border-top: 1px solid var(--border-color-light); margin-top: auto;
}
.project-card .footer-row .avatar-stack { display: flex; align-items: center; }

/* --- Drag and drop de etapas (Projetos ▸ Configurações) ---------------------- */
.etapa-item { transition: background-color 0.15s ease, opacity 0.15s ease; border-radius: 0.25rem; padding: 0.5rem; margin: 0 -0.5rem; }
.etapa-item:not(:first-child) { margin-top: 0.75rem; padding-top: 1rem; }
.etapa-item[draggable="true"] { cursor: grab; }
.etapa-item[draggable="true"]:active { cursor: grabbing; }
.etapa-item.drag-over { background-color: var(--primary-lt); opacity: 0.7; }
.etapa-item .fa-grip-vertical { cursor: grab; transition: opacity 0.15s ease; opacity: 0.5; }
.etapa-item .fa-grip-vertical:hover { opacity: 0.8; }
.etapa-item[draggable="true"] .fa-grip-vertical { opacity: 0.8; }
/* Altura fixa deliberada: ~5-6 etapas visíveis antes de rolar. */
.etapas-lista-rolavel { max-height: 500px; overflow-y: auto; }

/* --- Caixa de gráfico gerado no servidor (burndown) --------------------------
 * O <svg> usa height="100%", que só resolve com altura no pai. */
.chart { position: relative; width: 100%; height: 12rem; }
.chart-lg { height: 20rem; }

/* --- Integrações (Sistema ▸ Integrações) -------------------------------- */
.integration { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); padding: 14px; background: var(--bg-surface-secondary); border-radius: var(--radius); }
.integration .logo { width: 36px; height: 36px; border-radius: var(--radius); display: inline-flex; align-items: center; justify-content: center; font-size: 12px; font-weight: var(--font-weight-bold); flex-shrink: 0; }
.integration .title { font-size: 13px; font-weight: var(--font-weight-medium); color: var(--text); }
.integration .desc { font-size: 11.5px; color: var(--text-muted); margin-top: 1px; }
.integrations-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: var(--space-3); }

/* --- Lista de atividade recente (dashboards) ----------------------------- */
.activity-list { list-style: none; padding: 0; margin: 0; }
.activity-item { display: flex; gap: 10px; padding: 10px 0; border-bottom: 1px solid var(--border-color-light); }
.activity-item:last-child { border-bottom: none; }
.activity-avatar { width: 28px; height: 28px; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 10px; font-weight: 600; color: #fff; flex-shrink: 0; }
.activity-body { flex: 1; font-size: 12.5px; color: var(--text-secondary); line-height: 1.45; }
.activity-time { font-size: 11px; color: var(--text-muted); white-space: nowrap; margin-top: 1px; }

/* --- Utilitários sem equivalente no Bootstrap ----------------------------
 * O Bootstrap tem sizing utilities (w-25/50/75/100/auto), mas não este
 * truque de tabela: width:1% força a coluna a encolher ao conteúdo (as
 * outras, sem width, absorvem o espaço que sobra) — nowrap evita que o
 * conteúdo quebre linha e a coluna colapse com ele. Usado pela coluna de
 * ações no fim de toda listagem do painel. */
.w-1 { width: 1%; white-space: nowrap; }

/* .row-cards: alias semântico para "grade de cartões sempre com respiro nos
 * dois eixos" — em vez de exigir lembrar de somar `g-3` toda vez. Redefine
 * as MESMAS custom properties que `.g-3` do Bootstrap usa (--bs-gutter-x/-y),
 * não `gap`/`column-gap`: o `.row` real do Bootstrap distribui o respiro por
 * margem negativa + padding dos `.col-*`, então uma grade paralela baseada em
 * `gap` não teria efeito nenhum aqui. Nunca leva `g-3` junto (regra do
 * PADROES-UI.md) — os dois fariam a mesma coisa. */
.row.row-cards { --bs-gutter-x: 1rem; --bs-gutter-y: 1rem; }
