@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&family=Sora:wght@600;700;800&display=swap');

/* Tokens e componentes da identidade VSystems. */

/* ===========================================================================
   TOKENS DE TEMA — todo valor de cor do app sai daqui. O tema é escolhido
   trocando data-bs-theme no <html> (ver core/theme.ts + anti-flash no
   index.html); dark é o default e mantém o visual original do app.
   =========================================================================== */
html[data-bs-theme="dark"] {
  color-scheme: dark;
  /* Bootstrap: cor de marca sobrescrita via variável nativa, não trocada. */
  --bs-primary: #5b5ee6;
  --bs-primary-rgb: 91, 94, 230;
  --bs-body-bg: #101318;
  --bs-body-color: #e8eaf1;
  --bs-tertiary-bg: #252d38;
  --bs-border-color: rgba(255, 255, 255, .10);
  --bs-emphasis-color: #fff;
  --bs-secondary-color: #98a2b3;
  /* Tokens do app */
  --app-bg: #101318;
  --app-content: #131922;
  --app-surface: #1c2430;
  --app-surface-2: #242e3c;
  --app-sidebar: #10151e;
  --app-topbar: #171e28;
  --app-border: #303b4a;
  --app-border-soft: rgba(255, 255, 255, .06);
  --app-border-strong: rgba(255, 255, 255, .20);
  --app-text: #e8eaf1;
  /* Corpo de texto do markdown: um passo abaixo do texto normal, para o
     negrito (que é --app-ink) ter de quem se destacar. Com os dois em
     quase-branco, **negrito** era indistinguível do resto. */
  --app-text-soft: #c3cbdc;
  --app-text-muted: #a3afc1;
  --app-text-faint: #8894aa;
  --app-ink: #fff;
  --app-accent: #5b5ee6;
  --app-accent-soft: #a5b4fc;
  --app-grad-1: #a5b4fc;
  --app-grad-2: #c084fc;
  --app-hover: rgba(255, 255, 255, .05);
  --app-hover-strong: rgba(255, 255, 255, .08);
  --app-field: rgba(255, 255, 255, .05);
  --app-code-inline: rgba(255, 255, 255, .12);
  --app-code-bg: rgba(0, 0, 0, .35);
  --app-scrim: #05060c;
  --app-tint-1: rgba(99, 102, 241, .06);
  --app-tint-2: rgba(139, 92, 246, .05);
  --app-sheen: linear-gradient(180deg, rgba(255, 255, 255, .04), rgba(255, 255, 255, 0) 55%);
  --app-shadow-card: 0 2px 4px #0000000d, 0 8px 24px -20px #00000066;
  --app-shadow-pop: 0 10px 30px -12px rgba(0, 0, 0, .6);
  --app-option-bg: #10131c;
  --app-scroll: rgba(255, 255, 255, .12);
  --app-scroll-hover: rgba(255, 255, 255, .22);
  /* Pílulas de status (Pedidos do robô e afins): fundo translúcido + texto
     pastel no escuro; no claro o texto escurece pra manter contraste. */
  --pill-neutral-bg: rgba(255, 255, 255, .07);
  --pill-neutral-fg: #cbd5e1;
  --pill-green-bg: rgba(52, 211, 153, .14);
  --pill-green-fg: #6ee7b7;
  --pill-amber-bg: rgba(251, 191, 36, .14);
  --pill-amber-fg: #fcd34d;
  --pill-amber-fg-soft: #fde68a;
  --pill-red-bg: rgba(248, 113, 113, .14);
  --pill-red-fg: #fca5a5;
  /* Trilho de etapas do pedido. Precisa de token próprio porque é uma linha de
     2px: a borda comum (--app-border) some nessa espessura, e o verde
     translúcido que funciona no escuro fica lavado sobre branco. */
  --app-trilho: rgba(255, 255, 255, .16);
  --app-trilho-ok: #34d399;
  /* OPACO, não translúcido. É o verde a 18% já achatado contra --app-surface:
     mesma aparência, mas o trilho não atravessa a bola por dentro — com alpha,
     z-index não adianta, porque dá para ver através. */
  --app-marco-ok-bg: #1a3b3a;
}
html[data-bs-theme="light"] {
  color-scheme: light;
  --bs-primary: #5b5ee6;
  --bs-primary-rgb: 91, 94, 230;
  --bs-body-bg: #f4f5f7;
  --bs-body-color: #1e2432;
  --bs-tertiary-bg: #f2f5f9;
  --bs-border-color: rgba(15, 23, 42, .12);
  --bs-emphasis-color: #17202c;
  --bs-secondary-color: #5b6675;
  /* Claro com hierarquia: fundo levemente frio, cartão branco COM elevação e
     borda visível — sem isso tudo virava um bloco cinza só. */
  --app-bg: #f4f5f7;
  --app-content: #f4f5f7;
  --app-surface: #ffffff;
  --app-surface-2: #f8f9fa;
  --app-sidebar: #101b2d;
  --app-topbar: #ffffff;
  --app-border: #dfe3e8;
  --app-border-soft: #eceef1;
  --app-border-strong: #bec5ce;
  --app-text: #202630;
  --app-text-soft: #404a59;
  --app-text-muted: #566170;
  --app-text-faint: #5b6675;
  --app-ink: #17202c;
  --app-accent: #5b5ee6;
  --app-accent-soft: #4053a4; /* a5b4fc é ilegível sobre branco */
  --app-grad-1: #4053a4;
  --app-grad-2: #9333ea;
  --app-hover: rgba(15, 23, 42, .045);
  --app-hover-strong: rgba(15, 23, 42, .07);
  --app-field: #ffffff;
  --app-code-inline: rgba(15, 23, 42, .08);
  --app-code-bg: rgba(15, 23, 42, .05);
  --app-scrim: #0f172a;
  /* Os tints são o que tira o claro do "cinza chapado": o mesmo wash indigo
     que o escuro tem, só que sobre branco precisa de mais opacidade pra
     aparecer. */
  --app-tint-1: rgba(64, 83, 164, .065);
  --app-tint-2: rgba(64, 83, 164, .025);
  --app-sheen: linear-gradient(transparent, transparent);
  /* Sombra difusa e comprida no lugar de borda dura: é ela que separa cartão
     de fundo no claro — a borda ficou quase invisível de propósito. */
  /* Elevação um pouco mais presente: é ela que separa o cartão do fundo no
     claro (no escuro esse papel é do contraste de cor). */
  --app-shadow-card: 0 1px 3px rgba(24, 42, 70, .04), 0 5px 16px -10px rgba(24, 42, 70, .14);
  --app-shadow-pop: 0 18px 54px -14px rgba(23, 39, 64, .24), 0 2px 8px rgba(23, 39, 64, .06);
  --app-option-bg: #ffffff;
  --app-scroll: rgba(15, 23, 42, .18);
  --app-scroll-hover: rgba(15, 23, 42, .30);
  --pill-neutral-bg: rgba(15, 23, 42, .07);
  --pill-neutral-fg: #334155;
  --pill-green-bg: rgba(16, 185, 129, .12);
  --pill-green-fg: #047857;
  --pill-amber-bg: rgba(217, 119, 6, .12);
  --pill-amber-fg: #92400e;
  --pill-amber-fg-soft: #b45309;
  --pill-red-bg: rgba(220, 38, 38, .10);
  --pill-red-fg: #b91c1c;
  /* Bem mais opaco que no escuro: 2px de linha sobre branco precisa disso para
     existir, e o verde desce para o tom 600, que é o legível sobre claro. */
  --app-trilho: rgba(15, 23, 42, .16);
  --app-trilho-ok: #059669;
  /* Mesmo motivo do escuro: o verde a 14% achatado contra o branco. */
  --app-marco-ok-bg: #dcf0ea;
}

html, body, #root { height: 100%; }
body {
  background: var(--app-bg);
  color: var(--app-text);
  font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  -webkit-font-smoothing: antialiased;
}

/* Troca de tema com transição suave — a classe é posta pelo themeStore só
   durante o toggle (~260ms); transition permanente causava jank em charts. */
html.theme-switching, html.theme-switching *, html.theme-switching *::before, html.theme-switching *::after {
  transition: background-color .2s ease, color .2s ease, border-color .2s ease, fill .2s ease !important;
}

/* Acessibilidade + polish: anel de foco só para navegação por teclado.
   Campos de texto ficam de fora — eles têm o próprio realce de borda no foco. */
:focus-visible:not(input):not(textarea):not(select) {
  outline: 2px solid rgba(129, 140, 248, .55);
  outline-offset: 2px;
}
input:focus, textarea:focus, select:focus { outline: none; }
::selection { background: rgba(99, 102, 241, .35); }

/* SEM @layer aqui de propósito: regra de cascata do CSS diz que uma declaração
   sem layer SEMPRE ganha de uma com layer, não importa a especificidade — um
   @layer components{} nessas classes fazia .btn.btn-primary (specificity 0,1,0)
   perder pro reset de <button> do próprio Bootstrap (`button{background-color:
   transparent}`, sem layer, specificity 0,0,1). Resultado ao vivo: todo botão
   .btn.btn-primary/.btn.btn-outline-secondary do app sem cor de fundo nenhuma. */
/* App profissional: superfícies SÓLIDAS com leve profundidade */
.app-panel { background: var(--app-sheen), var(--app-surface); border: 1px solid var(--app-border); box-shadow: var(--app-shadow-card); transition: border-color .15s ease, box-shadow .15s ease, transform .15s ease; }
/* app-card (não .card): .card já é do Bootstrap, com padding/borda próprios
   — usar o mesmo nome faria as duas cascatearem de forma imprevisível. */
.app-card  { background: var(--app-surface); border: 1px solid var(--app-border); border-radius: 14px; transition: border-color .15s ease, box-shadow .15s ease, transform .15s ease; }
/* Cards CLICÁVEIS (KPI com drill, contadores-filtro) sobem de leve no hover —
   affordance de "dá pra clicar" sem precisar de texto. */
.app-panel.app-clickable:hover, button.app-card:hover, a.app-card:hover {
  transform: translateY(-1px);
  border-color: rgba(99, 102, 241, .40);
  box-shadow: var(--app-shadow-pop);
}
/* Título de seção com régua — usado nas faixas do Painel Executivo. */
.sec-title { display: flex; align-items: center; gap: .65rem; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .09em; color: var(--app-accent-soft); margin: 0 0 .6rem; }
.sec-title::before { content: ''; width: 16px; height: 3px; border-radius: 2px; background: linear-gradient(90deg, var(--app-grad-1), var(--app-grad-2)); }
.sec-title::after { content: ''; flex: 1; height: 1px; background: var(--app-border-soft); }
/* Card de estatística com ícone */
.stat { display:flex; align-items:center; gap:.75rem; }
.stat-ic { display:grid; place-items:center; height:2.5rem; width:2.5rem; border-radius:.75rem; font-size:1.05rem; flex-shrink:0; }
.glow  { box-shadow: var(--app-shadow-pop); }
.text-grad { background: linear-gradient(90deg, var(--app-grad-1), var(--app-grad-2)); -webkit-background-clip: text; background-clip: text; color: transparent; }
/* Texto branco sobre cor de destaque sólida (avatar, chip, tile): NÃO segue o
   tema — sobre indigo/verde o texto é branco nos dois. */
.text-on-accent { color: #fff !important; }

/* Navegação lateral do app */
.side-link { display: flex; align-items: center; gap: .7rem; padding: .58rem .85rem; border-radius: 10px; color: var(--app-text-muted); font-size: .9rem; transition: .15s; cursor: pointer; }
.side-link:hover { background: var(--app-hover); color: var(--app-ink); }
.side-link.active { background: rgba(99,102,241,.16); color: var(--app-ink); box-shadow: inset 3px 0 0 #6366f1; }
.side-section { font-size: .68rem; letter-spacing: .08em; text-transform: uppercase; color: var(--app-text-faint); padding: 0 .85rem; margin: 1rem 0 .35rem; }

/* Modo admin (plataforma): accent diferente para diferenciar do cliente */
.admin-mode .side-link.active { background: rgba(16,185,129,.15); box-shadow: inset 3px 0 0 #10b981; }

/* ===== Login ===============================================================
   Tudo em token pra funcionar nos dois temas sem entrada na camada de
   compatibilidade. As marcas-d'água são decorativas: ficam em z-index 0
   (o conteúdo dos painéis sobe pra 1) e nunca capturam clique. */
/* Fundo ÚNICO na raiz — os dois painéis são transparentes, senão a troca de
   cor no meio da tela cria uma emenda vertical visível. */
/* Degraus de cor da onda, do fundo (roxo) até a frente (verde-água).
   No claro descem para os tons 600/700 — o néon do escuro some sobre branco. */
html[data-bs-theme="dark"] .login-fundo {
  --onda-1: #c084fc; --onda-2: #a78bfa; --onda-3: #818cf8; --onda-4: #818cf8;
  --onda-5: #60a5fa; --onda-6: #22d3ee; --onda-7: #2dd4bf;
  background: var(--app-sidebar);
}
html[data-bs-theme="light"] .login-fundo {
  --onda-1: #9333ea; --onda-2: #7c3aed; --onda-3: #4f46e5; --onda-4: #4f46e5;
  --onda-5: #2563eb; --onda-6: #0891b2; --onda-7: #0d9488;
  /* Branco puro deixava a onda boiando; o degradê dá chão pra ela sem sujar
     o topo, onde ficam o título e o cartão. */
  background: linear-gradient(180deg, #ffffff 0%, #f7f8fd 42%, #eaedf8 100%);
}
.login-hero, .login-lado-form { position: relative; overflow: hidden; }
.login-hero > *, .login-lado-form > * { position: relative; z-index: 1; }
.login-marca { position: absolute; z-index: 0 !important; pointer-events: none; user-select: none; }
/* Onda de rede neural cobrindo a TELA INTEIRA, atrás de tudo (o cartão de
   login é opaco e flutua por cima). preserveAspectRatio=slice ancorado na
   base faz a onda sempre encostar no rodapé, em qualquer resolução. */
.login-neuro { inset: 0; height: 100%; width: 100%; }
/* Cada linha da onda sobe/desce; o atraso progressivo cria a onda viajando. */
.login-neuro .onda-linha { animation: ondaFlutua 7s ease-in-out infinite; }
@keyframes ondaFlutua { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-13px); } }
/* Brilho varrendo o destaque do título da esquerda pra direita: uma faixa
   clara no meio do degradê, que desliza via background-position. O shorthand
   de background reseta o clip, então ele é redeclarado aqui. No claro a faixa
   não pode ser branca (sumiria no fundo), então desce pro lilás. */
.brilho-varre {
  background: linear-gradient(105deg, var(--app-grad-1) 0%, var(--app-grad-2) 42%, var(--varre-flash, rgba(255, 255, 255, .95)) 50%, var(--app-grad-2) 58%, var(--app-grad-1) 100%);
  background-size: 300% 100%;
  -webkit-background-clip: text;
  background-clip: text;
  animation: brilhoVarre 4.8s linear infinite;
}
html[data-bs-theme="light"] .brilho-varre { --varre-flash: #a5b4fc; }
@keyframes brilhoVarre { from { background-position: 200% 0; } to { background-position: -100% 0; } }
@media (prefers-reduced-motion: reduce) {
  .login-neuro .onda-linha, .brilho-varre { animation: none; }
}
/* Fio de accent no topo do cartão — mesmo degradê da régua .sec-title. */
.login-card { position: relative; overflow: hidden; }
.login-card::before {
  content: ''; position: absolute; top: 0; left: 0; right: 0; height: 2px;
  background: linear-gradient(90deg, transparent 5%, var(--app-grad-1), var(--app-grad-2), transparent 95%);
  opacity: .8;
}
/* Campo com ícone à esquerda (e botão de mostrar senha à direita). */
.login-campo { position: relative; }
.login-campo .login-campo-ic {
  position: absolute; left: .85rem; top: 50%; transform: translateY(-50%);
  color: var(--app-text-faint); pointer-events: none;
}
.login-campo .form-control {
  padding: .7rem 1rem .7rem 2.55rem;
  background: var(--app-field); border: 1px solid var(--app-border);
  border-radius: .75rem; font-size: .9rem; color: var(--app-text);
}
.login-campo .form-control:focus {
  background: var(--app-field);
  border-color: rgba(129, 140, 248, .6);
  box-shadow: 0 0 0 3px rgba(129, 140, 248, .12);
}
.login-campo .login-olho {
  position: absolute; right: .5rem; top: 50%; transform: translateY(-50%);
  display: grid; place-items: center; height: 1.9rem; width: 1.9rem;
  border: 0; border-radius: .5rem; background: transparent;
  color: var(--app-text-faint); transition: .15s;
}
.login-campo .login-olho:hover { color: var(--app-text); background: var(--app-hover); }
/* Selos do rodapé do hero */
.login-chip {
  display: inline-flex; align-items: center; gap: .45rem;
  padding: .38rem .75rem; border-radius: 999px;
  border: 1px solid var(--app-border); background: var(--app-hover);
  font-size: .72rem; color: var(--app-text-muted); white-space: nowrap;
}
.login-chip svg { color: var(--app-accent-soft); }

::-webkit-scrollbar { width: 9px; height: 9px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--app-scroll); border-radius: 8px; }
::-webkit-scrollbar-thumb:hover { background: var(--app-scroll-hover); }

/* Modais com entrada suave (reutilizável em qualquer componente) */
@keyframes modalIn { from { opacity: 0; transform: translateY(10px) scale(.985); } to { opacity: 1; transform: none; } }
.modal-card { animation: modalIn .18s ease-out; }
@keyframes backdropIn { from { opacity: 0; } to { opacity: 1; } }
/* app-modal-backdrop (não .modal-backdrop): esse É o nome interno real do
   backdrop do Bootstrap/react-bootstrap — reusar o nome faria os dois
   backdrops (o customizado das telas antigas e o do <Modal> novo) colidirem. */
.app-modal-backdrop { animation: backdropIn .15s ease-out; }

/* Overlay único da pilha do drill (substitui os backdrops do Bootstrap, um
   por modal): fica sempre logo abaixo do modal do topo — z-index vem inline
   do Dashboard — e escurece igual com qualquer quantidade de níveis. */
.drill-overlay { position: fixed; inset: 0; background: var(--app-scrim); opacity: .5; }

/* Tela de trás EMBAÇADA quando há modal aberto (pedido do Pedro).
   O blur vai no PRÓPRIO app (#root) — não no backdrop com backdrop-filter,
   que dependia da composição de camadas do navegador e falhava/piscava com
   modais empilhados. Os modais são portais direto no <body>, fora do #root,
   então ficam nítidos. Funciona igual com 1 ou 4 modais empilhados: um
   blur só, sem re-borrar a cada nível. */
body:has(.modal.show) #root { filter: blur(2px); }
/* Backdrop: só escurece (o embaçado vem do #root acima). */
.modal-backdrop { background-color: var(--app-scrim); }
.modal-backdrop.show { opacity: .5; }
/* Modais EMPILHADOS (card → drill → drill mais fundo, chega a 3-4): os
   backdrops seguintes escurecem bem menos, senão a pilha vira breu. */
.modal-backdrop.show ~ .modal-backdrop.show { opacity: .25; }

/* Modais abrem INSTANTÂNEOS (pedido do Pedro): sem fade nem slide de
   entrada — anula o transition/transform do .fade do Bootstrap. */
.modal.fade, .modal-backdrop.fade { transition: none !important; }
.modal.fade .modal-dialog { transform: none; transition: none; }
.modal.show .modal-dialog { transform: none; }
/* Pilha card→drill do Dashboard: o card continua MONTADO por baixo (fechar o
   drill volta pra ele sem refazer busca) e fica VISÍVEL recuado atrás — como
   folhas empilhadas. O blur é o que evita a "sopa de texto" dos dois modais
   legíveis um sobre o outro; escala + subida dão a profundidade. */
/* .modal.show .modal-dialog{transform:none} acima (2 classes) tem mais
   especificidade que .modal-recuado sozinho (1 classe) e ganharia, anulando
   o recuo — por isso repete o seletor completo aqui. */
.modal.show .modal-recuado {
  transform: scale(.93) translateY(-14px);
  /* brightness no lugar de opacity: opacidade deixava o modal transparente
     (dava pra ver a página através dele); escurecer mantém ele sólido. */
  filter: blur(6px) brightness(.55);
  pointer-events: none;
}
/* No claro, escurecer .55 vira cinza sujo — o modal recuado só embaça. */
html[data-bs-theme="light"] .modal.show .modal-recuado { filter: blur(6px) brightness(.9) saturate(.95); }

/* Topo e conteúdo (mais arejado) */
.app-topbar { background: var(--app-topbar); backdrop-filter: blur(10px); }
.app-content { background: var(--app-content); }

/* Entrada suave do conteúdo de cada página */
@keyframes pageIn { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
.app-content > * { animation: pageIn .22s ease-out; }

/* Markdown das respostas dos agentes e "digitando..." — global porque tanto
   a tela de Chat quanto a bolinha flutuante (ChatWidget, sempre montada)
   precisam, e o ChatWidget não pode depender do <style> local da tela de Chat. */
.md > *:first-child { margin-top: 0; }
.md > *:last-child { margin-bottom: 0; }
.md { color: var(--app-text-soft); }
.md p { margin: 0 0 .5rem; line-height: 1.55; }
.md ul, .md ol { margin: .25rem 0 .6rem; padding-left: 1.3rem; }
.md ul { list-style: disc; }
.md ol { list-style: decimal; }
.md li { margin: .15rem 0; }
.md strong, .md b { color: var(--app-ink); font-weight: 700; }
.md em { font-style: italic; }
.md a { color: var(--app-accent-soft); text-decoration: underline; }
.md code { background: var(--app-code-inline); padding: .1rem .35rem; border-radius: .3rem; font-size: .85em; }
.md pre { background: var(--app-code-bg); padding: .6rem .8rem; border-radius: .6rem; overflow-x: auto; margin: .4rem 0; }
.md pre code { background: none; padding: 0; }
.md h1, .md h2, .md h3 { color: var(--app-ink); font-weight: 600; margin: .5rem 0 .3rem; font-size: 1em; }
/* Tabela do markdown: o agente responde com tabela com frequência, e ela
   precisa se ler como tabela — cabeçalho destacado, linhas alternadas e, se
   for larga demais, rolagem PRÓPRIA (display:block) em vez de estourar a
   largura da bolha e empurrar a conversa inteira. */
.md table { display: block; overflow-x: auto; max-width: 100%; border-collapse: collapse;
            margin: .5rem 0; font-size: .875em; }
.md th, .md td { border: 1px solid var(--app-border); padding: .35rem .6rem; white-space: nowrap; }
.md thead th { background: var(--app-surface-2); color: var(--app-ink); font-weight: 600;
               text-align: left; position: sticky; top: 0; }
.md tbody tr:nth-child(even) td { background: var(--app-hover); }
/* Coluna de número alinhada à direita não existe no markdown; o alinhamento
   por dois-pontos (|---:|) vira text-align inline e é respeitado. */
.md td[align="right"], .md th[align="right"] { text-align: right; font-variant-numeric: tabular-nums; }
.md blockquote { border-left: 3px solid var(--app-border-strong); padding-left: .7rem; color: var(--app-text-muted); margin: .4rem 0; }
.typing-dot { width: .45rem; height: .45rem; border-radius: 9999px; background: #818cf8; display: inline-block; animation: typing 1.1s infinite ease-in-out; }
@keyframes typing { 0%, 60%, 100% { transform: translateY(0); opacity: .4; } 30% { transform: translateY(-.28rem); opacity: 1; } }

/* Split lista/conversa do Inbox: altura fixa só no desktop (≥lg); no celular
   o grid empilha e a altura fixa causava rolagem dupla. */
@media (min-width: 992px) { .inbox-split { height: calc(100vh - 16rem); } }
/* Opções nativas usam as cores do tema para manter a legibilidade. */
select option { background-color: var(--app-option-bg); color: var(--app-text); }

/* Formulários "compactos" (.form-label/.form-control) e cards de KPI (.kpi*) — antes cada
   tela (Admin, Agenda, Perfis, Usuários) tinha uma cópia própria num <style>
   local, cada uma com um visual levemente diferente. Definição única aqui;
   as telas só usam. */
/* Datas/horas nativas: o ícone do picker vinha preto (invisível no escuro).
   Só no dark — no claro o color-scheme já entrega o ícone escuro certo. */
html[data-bs-theme="dark"] .form-control::-webkit-calendar-picker-indicator { filter: invert(.7); }
.kpi { display: flex; align-items: center; gap: .8rem; }
.kpi-ic { display: grid; place-items: center; height: 2.6rem; width: 2.6rem; border-radius: .85rem; font-size: 1.15rem; flex-shrink: 0; }
.kpi-l { font-size: .7rem; color: var(--app-text-muted); font-weight: 500; margin-bottom: .1rem; }
.kpi-v { font-size: 1.5rem; font-weight: 800; color: var(--app-ink); line-height: 1.1; letter-spacing: -.01em; }

/* Kit visual da tela de Relatórios (e reutilizável): abas segmentadas, chips
   de seleção, cards clicáveis, tabela de resultado e editor SQL. Tudo em cima
   dos tokens de tema (app e pill), então funciona nos dois temas sem override. */
.seg-tabs { display: inline-flex; gap: .25rem; padding: .3rem; border-radius: 1rem; background: var(--app-field); border: 1px solid var(--app-border-soft); }
.seg-tab { display: flex; align-items: center; gap: .5rem; border: 0; border-radius: .75rem; padding: .5rem .95rem; font-size: .85rem; font-weight: 500; color: var(--app-text-muted); background: transparent; transition: color .15s, background .15s, box-shadow .15s; white-space: nowrap; }
.seg-tab:hover { color: var(--app-ink); background: var(--app-hover); }
/* Aba ativa em pílula de acento sólida: identidade visível nos dois temas —
   a pílula branca sumia no claro (branco sobre branco). */
.seg-tab.active { color: #fff; background: var(--app-accent); box-shadow: 0 6px 16px -8px rgba(99, 102, 241, .7); }
.seg-tab .seg-count { font-size: .68rem; font-weight: 600; padding: .05rem .45rem; border-radius: 999px; background: var(--app-hover-strong); color: var(--app-text-muted); }
.seg-tab.active .seg-count { background: rgba(255, 255, 255, .22); color: #fff; }

/* Chip de seleção (colunas, agrupamentos, dias, canais...): estado neutro,
   ligado (indigo) e ligado-verde (agrupamento/canal). */
.chip-toggle { border: 1px solid transparent; border-radius: 999px; padding: .28rem .75rem; font-size: .75rem; background: var(--app-hover); color: var(--app-text-muted); transition: background .15s, color .15s, border-color .15s, transform .1s; }
.chip-toggle:hover { background: var(--app-hover-strong); color: var(--app-ink); transform: translateY(-1px); }
.chip-toggle.on { background: rgba(99, 102, 241, .16); color: var(--app-accent-soft); border-color: rgba(99, 102, 241, .35); }
.chip-toggle.on-green { background: var(--pill-green-bg); color: var(--pill-green-fg); border-color: rgba(52, 211, 153, .3); }

/* Card clicável (modelos prontos, exemplos de consulta): levanta no hover. */
.tile-click { display: block; width: 100%; text-align: start; border: 1px solid var(--app-border-soft); border-radius: .9rem; background: var(--app-hover); padding: .8rem; transition: transform .15s, border-color .15s, background .15s, box-shadow .15s; }
.tile-click:hover { transform: translateY(-2px); border-color: rgba(99, 102, 241, .35); background: var(--app-hover-strong); box-shadow: var(--app-shadow-pop); }
.tile-click.sel { border-color: rgba(99, 102, 241, .6); background: rgba(99, 102, 241, .10); }

/* Selo de ícone com degradê da marca — cabeçalhos e estados vazios. */
/* Preenchido de verdade (não só um tint): o selo da página é o ponto de marca
   mais visível da tela — no claro o tint quase sumia. */
.icon-badge { display: grid; place-items: center; border-radius: .9rem; background: linear-gradient(135deg, #6366f1, #9333ea); color: #fff; box-shadow: 0 8px 20px -10px rgba(99, 102, 241, .65); flex-shrink: 0; }

/* Tabela de resultado: cabeçalho fixo, zebra sutil, linha acesa no hover,
   rodapé de total com tinta da marca. */
/* O terminal do ERP mantém fundo escuro nos dois temas. */
.log-terminal {
  background: #0e1119;
  border: 1px solid rgba(255, 255, 255, .10);
  color: #86efac;
}
.log-terminal::selection, .log-terminal ::selection { background: rgba(134, 239, 172, .25); }

.rel-table { width: 100%; font-size: .875rem; border-collapse: separate; border-spacing: 0; }
.rel-table thead th { position: sticky; top: 0; z-index: 1; background: var(--app-surface); font-size: .68rem; font-weight: 600; text-transform: uppercase; letter-spacing: .06em; color: var(--app-text-faint); padding: .35rem .6rem .5rem; border-bottom: 1px solid var(--app-border); }
.rel-table tbody td { padding: .55rem .6rem; border-bottom: 1px solid var(--app-border-soft); }
.rel-table tbody tr:nth-child(even) td { background: var(--app-field); }
.rel-table tbody tr:hover td { background: var(--app-hover-strong); }
.rel-table tr.rel-subtotal td { background: var(--app-tint-2); font-size: .75rem; font-weight: 600; }
.rel-table tfoot td { padding: .6rem; background: var(--app-tint-1); font-weight: 700; border-top: 2px solid rgba(99, 102, 241, .35); }

/* Editor SQL: cara de terminal, foco com anel da marca. */
.sql-editor { width: 100%; border-radius: .8rem; background: var(--app-code-bg); color: var(--app-text); border: 1px solid var(--app-border-soft); padding: .8rem 1rem; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: .85rem; line-height: 1.6; outline: none; resize: vertical; transition: border-color .15s, box-shadow .15s; }
.sql-editor::placeholder { color: var(--app-text-faint); }
.sql-editor:focus { border-color: rgba(129, 140, 248, .6); box-shadow: 0 0 0 3px rgba(129, 140, 248, .12); }

/* Régua de meses do filtro de período: clique num mês ou arraste por vários. */
.mes-seg { flex: 1 1 0; min-width: 0; border: 1px solid transparent; border-radius: .5rem; padding: .4rem 0; font-size: .68rem; text-align: center; background: var(--app-hover); color: var(--app-text-muted); cursor: pointer; transition: background .1s, color .1s, border-color .1s; }
.mes-seg:hover { background: var(--app-hover-strong); color: var(--app-ink); }
.mes-seg.on { background: rgba(99, 102, 241, .22); color: var(--app-accent-soft); border-color: rgba(99, 102, 241, .35); }

/* Tecla de atalho (Ctrl ⏎) — dica visual, não decoração. */
.kbd { font-family: ui-monospace, monospace; font-size: .62rem; padding: .1rem .4rem; border-radius: .4rem; border: 1px solid var(--app-border); border-bottom-width: 2px; background: var(--app-field); color: var(--app-text-muted); }

/* ===========================================================================
   APEXCHARTS NO TEMA CLARO — os 8 arquivos de gráfico têm foreColor/tooltip
   dark hardcoded nas options; recolorir o SVG vivo por CSS evita editar cada
   um e dispensa remount no toggle. fill/stroke do Apex são ATRIBUTOS
   presentacionais SVG — CSS de autor ganha deles sem !important; legenda e
   tooltip usam estilo inline/classe própria, daí o !important pontual.
   =========================================================================== */
html[data-bs-theme="light"] .apexcharts-text,
html[data-bs-theme="light"] .apexcharts-xaxis-label,
html[data-bs-theme="light"] .apexcharts-yaxis-label,
html[data-bs-theme="light"] .apexcharts-datalabel-label,
html[data-bs-theme="light"] .apexcharts-datalabel-value { fill: #5a6577; }
html[data-bs-theme="light"] .apexcharts-legend-text { color: #475569 !important; }
html[data-bs-theme="light"] .apexcharts-gridline { stroke: rgba(15, 23, 42, .08); }
html[data-bs-theme="light"] .apexcharts-grid-borders line { stroke: rgba(15, 23, 42, .08); }
html[data-bs-theme="light"] .apexcharts-tooltip.apexcharts-theme-dark {
  background: #fff !important;
  color: #1e2432 !important;
  border: 1px solid rgba(15, 23, 42, .10) !important;
  box-shadow: 0 10px 30px -12px rgba(15, 23, 42, .30);
}
html[data-bs-theme="light"] .apexcharts-tooltip-title {
  background: #f4f5fa !important;
  border-color: rgba(15, 23, 42, .08) !important;
  /* O CSS do Apex (theme-dark) pinta o título de branco com mais
     especificidade que a herança do container — sobre a faixa clara o texto
     ficava invisível. */
  color: #1e2432 !important;
}
/* Barra horizontal esconde o título do tooltip (o nome vai na linha do
   valor), mas o Apex deixa a faixa vazia no lugar — some com ela. */
.apexcharts-tooltip-title:empty { display: none; }
/* Separadores entre fatias/retângulos que as options pintam com o fundo
   escuro (#0e1119) — no claro o "vão" é branco. */
/* Séries dos gráficos em cartão .app-panel (Dashboard e afins): os tons 400
   escolhidos pro fundo escuro ficam lavados sobre branco. Escurecer o desenho
   inteiro um passo aproxima do tom 600 sem reescrever cada cor daquelas telas.
   O BI (cartões .app-card) fica de fora: lá a paleta já troca com o tema. */
html[data-bs-theme="light"] .app-panel .apexcharts-svg { filter: brightness(.84) saturate(1.12); }
html[data-bs-theme="light"] .apexcharts-pie-area { stroke: #ffffff; }
html[data-bs-theme="light"] .apexcharts-treemap-rect { stroke: #ffffff; }
/* Rótulos que as options pintam de branco (pensados pro tema escuro).
   Vale pro canvas inteiro, não só .apexcharts-datalabels: o treemap põe o
   rótulo em outro grupo SVG e ficava branco sobre célula clara. */
html[data-bs-theme="light"] .apexcharts-canvas text[fill="#fff"],
html[data-bs-theme="light"] .apexcharts-canvas text[fill="#f5f5f7"] { fill: #1e2432; }
/* A sombra (dropShadow SVG) dos rótulos serve pra descolar texto claro do
   fundo escuro; sobre fundo claro ela vira um borrão cinza — some. */
html[data-bs-theme="light"] .apexcharts-canvas text { filter: none; }

/* ---------------------------------------------------------------------------
   Modal com cara de JANELA da aplicação.

   A faixa colorida no cabeçalho ficou feia: o modal parecia um aviso, não uma
   tela. Aqui ele vira o que já existe no resto do app — barra de título sólida
   em cima (mesmo tom da topbar), área de conteúdo abaixo, borda e sombra de
   painel. A cor da seção sobra só no quadradinho do ícone.
   --------------------------------------------------------------------------- */
.app-janela {
  background: var(--app-content) !important;
  border: 1px solid var(--app-border) !important;
  border-radius: 12px !important;
  box-shadow: var(--app-shadow-pop) !important;
  overflow: hidden;
}
.app-janela .modal-header {
  /* Sheen no topo é o que dá volume de "chapa" à barra de título — sem ele a
     faixa fica chapada e o modal volta a parecer uma caixa de aviso. */
  background: var(--app-sheen), var(--app-surface);
  border-bottom: 1px solid var(--app-border) !important;
  padding: 18px 24px;
  align-items: center;
}
/* O X fica alinhado ao TÍTULO, não ao meio da barra alta. */
.app-janela .modal-header .btn-close { align-self: center; margin: 0; }
/* A janela de segundo nível (parâmetros, SQL, alçada) é um passo abaixo na
   hierarquia: mesma barra, um pouco mais baixa. */
.app-janela.app-janela-2 .modal-header { padding: 15px 20px; }
/* A barra de título é a "pegada" da janela: some com o arredondamento que o
   Bootstrap põe nela, senão sobra um canto claro dentro da borda. */
.app-janela .modal-header { border-radius: 0 !important; }
.app-janela .modal-body { background: var(--app-content); }
.app-janela .modal-footer {
  background: var(--app-surface);
  border-top: 1px solid var(--app-border) !important;
  border-radius: 0 !important;
}
/* Em tela cheia (notebook) a janela ocupa tudo: sem borda nem canto. */
.modal-fullscreen .app-janela,
.modal-fullscreen-lg-down .app-janela { border-radius: 0 !important; border: 0 !important; }

/* Modal de alerta: mais largo para caber a tabela de itens */
.modal-alerta { max-width: min(1200px, 94vw) !important; }

/* ---------------------------------------------------------------------------
   Caixa alta por padrão. O WinThor guarda cadastro em MAIÚSCULO; quando a tela
   deixa digitar em caixa mista, o mesmo cliente aparece escrito de dois jeitos
   (aqui e no ERP) e ninguém entende por que o relatório não bate.
   Fora da regra: e-mail, senha, URL e o que estiver marcado com
   `.caixa-normal` — nesses o valor É sensível a caixa.
   O `text-transform` é só o que se VÊ; o valor gravado é normalizado no
   servidor, no serializer do cadastro.
   ------------------------------------------------------------------------- */
.form-control { text-transform: uppercase; }
.form-control[type=email], .form-control[type=password], .form-control[type=url],
.form-control[type=search], .caixa-normal, .caixa-normal .form-control {
  text-transform: none;
}
.form-control::placeholder { text-transform: none; }
