/* ─────────────────────────────────────────────────────────────────────────
   Fontes servidas localmente. Nenhuma chamada a CDN externo: em painel de
   segurança isso evitaria vazar referer a cada acesso e quebraria em rede
   fechada. IBM Plex — SIL Open Font License 1.1 (fonts/LICENSE-IBMPlex.txt).
   ───────────────────────────────────────────────────────────────────────── */

@font-face {
  font-family: 'IBM Plex Sans'; font-style: normal; font-weight: 400;
  font-display: swap;
  src: url('/ui/fonts/ibm-plex-sans-latin-400-normal.woff2') format('woff2');
}
@font-face {
  font-family: 'IBM Plex Sans'; font-style: normal; font-weight: 500;
  font-display: swap;
  src: url('/ui/fonts/ibm-plex-sans-latin-500-normal.woff2') format('woff2');
}
@font-face {
  font-family: 'IBM Plex Sans Condensed'; font-style: normal; font-weight: 600;
  font-display: swap;
  src: url('/ui/fonts/ibm-plex-sans-condensed-latin-600-normal.woff2') format('woff2');
}
@font-face {
  font-family: 'IBM Plex Mono'; font-style: normal; font-weight: 400;
  font-display: swap;
  src: url('/ui/fonts/ibm-plex-mono-latin-400-normal.woff2') format('woff2');
}
@font-face {
  font-family: 'IBM Plex Mono'; font-style: normal; font-weight: 500;
  font-display: swap;
  src: url('/ui/fonts/ibm-plex-mono-latin-500-normal.woff2') format('woff2');
}

/* ─────────────────────────────────────────────────────────────────────────
   breachscope — sistema de tokens

   Dois temas irmãos:
     Névoa e Tempestade  → painel do tenant, landing, docs, relatório
     Torre de Controle   → painel superadmin (data-theme="operator")

   A ESCALA DE RISCO NÃO MUDA ENTRE OS TEMAS. Severo é severo em qualquer
   tela; só o contraste é ajustado para fundo claro ou escuro. Mudar a cor
   de gravidade conforme a página criaria uma armadilha, não um sistema.

   TRÊS EIXOS, QUE NUNCA COMPARTILHAM TINTA
   ────────────────────────────────────────
   1. RISCO      (--risk-*) consequência medida num finding. Exclusivo:
                 nenhum estado de sistema veste essas tintas.
   2. EXECUÇÃO   (--exec-*) estado da coleta. Petróleo, verde e grafite —
                 nenhum vermelho. Falha de coleta é LACUNA DE MEDIÇÃO, não
                 nível de risco, e se distingue por FORMA (hachura,
                 tracejado), não por hue.
   3. INTERFACE  (--destructive, --caution) intenção de um controle: o que
                 apaga, o que exige cautela de configuração.

   Não existem mais os apelidos --danger / --warn / --info. Eles apontavam
   para a escala de risco e faziam um scan com falha vestir a tinta de uma
   vulnerabilidade crítica. Cada ponto de uso agora declara seu eixo.
   ───────────────────────────────────────────────────────────────────────── */

:root {
  /* base — névoa marítima */
  --bg:        #EDF0F0;
  --surface:   #FBFCFC;
  --surface-2: #F4F7F7;
  --border:    #D9E0E0;
  --border-s:  #C3CDCD;
  --text:      #0E2A2E;
  /* era #5A6A6C (4,94:1 sobre --bg) — WCAG AA já passava, mas com pouca
     folga; escurecido ~10% pra ~5,8:1 sem mudança perceptível. */
  --muted:     #515F61;

  /* interface — petróleo */
  --accent:    #12525C;
  --accent-d:  #0D3A42;
  --accent-t:  #DCEBEC;
  --on-accent: #FBFCFC;

  /* latão: marca o que foi coletado por sensor dentro da rede do cliente,
     e no painel do operador o que pertence a um tenant. É o diferenciador
     do produto — a única coisa que usa esta tinta. */
  --tenant:    #87682E;
  --tenant-bg: #F9F5ED;

  /* ── eixo 1 · RISCO — meteorológico, exclusivo de severidade ──────────
     calm=Low · watch=Medium · alert=High · severe=Critical
     extreme=exploração ativa confirmada (CISA KEV). Extreme é uma MARCA
     sobre qualquer nível, não um sexto nível. Info não é risco: usa
     --muted. */
  --risk-calm:    #4E7F8A;
  --risk-watch:   #D9A227;
  --risk-alert:   #D2662C;
  --risk-severe:  #B03A2E;
  --risk-extreme: #6B2145;

  /* texto sobre fundo claro — cinco tintas distintas, todas ≥4,5:1 */
  --risk-calm-t:    #2C4C54;
  --risk-watch-t:   #8A6410;
  --risk-alert-t:   #A8471B;
  --risk-severe-t:  #B03A2E;
  --risk-extreme-t: #6B2145;

  /* tinta clara de risco (fundo de badge) */
  --risk-calm-bg:    #E3ECEE;
  --risk-watch-bg:   #FAEEDA;
  --risk-alert-bg:   #FAE7DC;
  --risk-severe-bg:  #F8E4E1;
  --risk-extreme-bg: #F5DCE5;

  /* ── eixo 2 · EXECUÇÃO — estado de coleta, sem tinta de risco ─────────
     na fila   → grafite, borda tracejada
     executando→ petróleo
     concluído → verde
     falhou    → grafite + hachura: ausência de leitura, não gravidade */
  --exec-queued:     #5A6A6C;
  --exec-queued-bg:  #EEF1F1;
  --exec-running:    #12525C;
  --exec-running-bg: #DCEBEC;
  /* era #2E7A59 (4,62:1 sobre --exec-ok-bg) — já passava WCAG AA, com
     pouca folga; escurecido ~10% pra ~5,5:1. Mantido igual a --positive
     de propósito (ver eixo 3 abaixo). */
  --exec-ok:         #296D50;
  --exec-ok-bg:      #EAF4EF;
  --exec-failed:     #5A6A6C;
  --exec-failed-bg:  #E9EDED;
  --exec-hatch:      rgba(90,106,108,.22);

  /* ── eixo 3 · INTERFACE — intenção de um controle ─────────────────────
     destructive: apaga, revoga, cancela. Granada, mais escuro que severe,
                  e nunca aparece numa coluna de severidade.
     caution:     configuração faltando ou cobertura incompleta por escolha
                  do usuário — o que ele pode corrigir antes de disparar.
     positive:    confirmação de uma ação da interface.
     Alguns destes coincidem em hex com tintas de outro eixo (caution com
     risk-watch, positive com exec-ok). São tokens independentes de propósito,
     não apelidos: nunca aparecem no mesmo contexto de leitura, e cada ponto
     de uso continua obrigado a declarar de qual eixo está falando. */
  --destructive:    #8C2F26;
  --destructive-bg: #F7E6E3;
  --caution:        #8A6410;
  --caution-bg:     #FAEEDA;
  --positive:       #296D50;
  --positive-bg:    #EAF4EF;

  /* Mapa de código — o canvas tem chão próprio (Torre de Controle) mesmo
     dentro do painel claro, então usa as tintas de risco do tema escuro.
     A legenda da página lê destes mesmos tokens: antes ela anunciava duas
     cores que o grafo não desenhava. */
  --map-bg:       #0B1E22;
  --map-node:     #5A7A80;
  --map-external: #7FB2AE;
  --map-clean:    #5FA98A;

  /* Modo suporte (impersonação). Fica DELIBERADAMENTE fora dos dois temas:
     a barra precisa parecer estrangeira à interface, porque o operador está
     vendo o painel de outra pessoa. Único uso desta tinta. */
  --impersonation:    #7A4A0C;
  --on-impersonation: #FDF3E0;

  /* sobreposições — escuras sobre fundo claro */
  --hover:    rgba(14,42,46,.035);
  --hover-s:  rgba(14,42,46,.06);
  --scrim:    rgba(14,42,46,.55);
  --shadow:   0 6px 20px rgba(14,42,46,.10);
  --shadow-raw: rgba(14,42,46,.14);

  /* tipografia */
  --sans: 'IBM Plex Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  --cond: 'IBM Plex Sans Condensed', 'IBM Plex Sans', sans-serif;
  --mono: 'IBM Plex Mono', SFMono-Regular, Consolas, monospace;

  /* Escala por PAPEL, não por valor. Antes havia oito tamanhos literais
     (9 a 15px) espalhados em 117 declarações contra 10 referências a
     token — ou seja, a escala existia no arquivo e não na interface.
     11px é piso: EPSS, KEV, saúde de scanner e mensagem de erro moravam
     a 10px, e é justamente onde a evidência é lida. */
  --fs-micro: 11px;   /* badge, rótulo, metadado — piso */
  --fs-meta:  12px;   /* texto secundário denso */
  --fs-sm:    13px;   /* célula de tabela, corpo denso */
  --fs-body:  15px;   /* corpo */
  --fs-title: 20px;   /* título de bloco */
  --fs-stat:  26px;   /* numeral de tile */
  --fs-disp:  29px;   /* display / título de página */
  /* Pendente: sobram ~25 declarações a 14px, mais 16/17/18px em títulos
     pequenos. E --fs-meta (12) e --fs-sm (13) continuam sendo dois degraus
     a 1px de distância, o que ainda é hierarquia rasa. Colapsar isso mexe
     em ~190 pontos de uso dos painéis logados, que não dá para conferir
     por render headless — precisa de uma passada visual autenticada. */

  /* forma e ritmo */
  --radius:   7px;
  --radius-c: 10px;
  --sp-1: 4px;  --sp-2: 8px;  --sp-3: 12px;
  --sp-4: 16px; --sp-6: 24px; --sp-8: 32px;

  /* ── motion ────────────────────────────────────────────────────────────
     Vocabulário único de duração/curva pra toda a interface. Existia
     transition inline com valor literal em ~40 pontos (.15s, .2s, .8s
     sem critério) — cada um decidindo sozinho o que "rápido" significa.
     Curva de saída (ease-out) em tudo que ENTRA na tela ou responde a um
     clique: começa rápido, resolve suave, não balança. Nada de bounce/
     elastic — isso é vocabulário de app de consumo, não de console de
     operação onde a leitura tem que ser confiável antes de bonita. */
  --dur-fast: 120ms;   /* hover, foco, feedback de clique */
  --dur-base: 200ms;   /* abrir/fechar menu, trocar de estado */
  --dur-slow: 360ms;   /* entrada de página, troca de tema */
  --ease-out:    cubic-bezier(.16,1,.3,1);
  --ease-in-out: cubic-bezier(.65,0,.35,1);
}

/* prefers-reduced-motion é checado no ponto de uso (cada @keyframes abaixo
   já tem seu media query irmão) — não existe um "desligar tudo" central
   porque skeleton/spinner precisam continuar comunicando "carregando" de
   alguma forma, só que sem movimento full-throttle. */

/* ── Torre de Controle — superadmin ─────────────────────────────────────── */
[data-theme="operator"] {
  --bg:        #0B1E22;
  --surface:   #12292E;
  --surface-2: #163137;
  --border:    #1D3A40;
  --border-s:  #2A4A50;
  --text:      #E8EFEF;
  --muted:     #8FA3A5;

  --accent:    #7FB2AE;
  --accent-d:  #9AC5C1;
  --accent-t:  #16343A;
  --on-accent: #04242C;

  --tenant:    #C79A4E;
  --tenant-bg: #33290F;

  /* mesma escala, contraste ajustado para fundo escuro */
  --risk-calm-t:    #8FB6BF;
  --risk-watch-t:   #E5BC5E;
  --risk-alert-t:   #E58B57;
  --risk-severe-t:  #EA6E60;
  --risk-extreme-t: #D2789C;

  --risk-calm-bg:    #1B3A42;
  --risk-watch-bg:   #3A2E14;
  --risk-alert-bg:   #3D2417;
  --risk-severe-bg:  #3A1C18;
  --risk-extreme-bg: #351623;

  --exec-queued:     #8FA3A5;
  --exec-queued-bg:  #173035;
  --exec-running:    #7FB2AE;
  --exec-running-bg: #16343A;
  /* era #5FA98A (4,90:1 sobre --exec-ok-bg) — já passava WCAG AA;
     clareado ~10% pra ~5,5:1 de folga extra. */
  --exec-ok:         #6FB195;
  --exec-ok-bg:      #14332A;
  --exec-failed:     #8FA3A5;
  --exec-failed-bg:  #1A3238;
  --exec-hatch:      rgba(143,163,165,.20);

  --destructive:    #E58B7F;
  --destructive-bg: #3A1C18;
  --caution:        #E5BC5E;
  --caution-bg:     #3A2E14;
  --positive:       #6FB195;
  --positive-bg:    #14332A;

  --hover:   rgba(232,239,239,.04);
  --hover-s: rgba(232,239,239,.08);
  --scrim:   rgba(0,0,0,.6);
  --shadow:  0 8px 26px rgba(0,0,0,.45);
  --shadow-raw: rgba(0,0,0,.45);
}

/* ── Sala de Situação — 3º tema, opcional no painel do cliente ───────────
   Mesma ideia de "quarto escuro de monitoramento" da Torre de Controle,
   mas com identidade própria: a Torre é petróleo/latão (o hue do produto);
   a Sala de Situação puxa pro azul elétrico de parede de NOC — deliberado
   ficar longe de verde, porque verde-ácido-sobre-preto é o clichê que o
   projeto já decidiu evitar (ver CLAUDE.md) E porque colidiria com o
   ciano de --risk-calm. Escala de risco INTACTA — mesmos tokens de
   severidade da Torre de Controle, só o fundo e o accent são outra tinta.
   Todos os pares abaixo conferidos ≥ 4,5:1 (WCAG AA) contra --bg/--surface. */
[data-theme="situation"] {
  --bg:        #070B14;
  --surface:   #0E1524;
  --surface-2: #131B2E;
  --border:    #1C2540;
  --border-s:  #2A365A;
  --text:      #E7ECF5;
  --muted:     #8CA0BE;

  --accent:    #3E8FD9;
  --accent-d:  #5DA8EA;
  --accent-t:  #16233D;
  --on-accent: #051019;

  /* mesmo latão da Torre de Controle — o marcador de procedência é
     identidade de produto, não de tema; só ele fica constante entre os
     dois temas escuros. */
  --tenant:    #D9A24E;
  --tenant-bg: #2E2413;

  /* risco: herdado da Torre de Controle. Fundo daqui é mais escuro que o
     dela (#070B14 vs #0B1E22), então a margem de contraste só aumenta —
     não precisou recalcular os pares texto/fundo do badge, que continuam
     os mesmos dois tokens medidos um contra o outro. */
  --risk-calm-t:    #8FB6BF;
  --risk-watch-t:   #E5BC5E;
  --risk-alert-t:   #E58B57;
  --risk-severe-t:  #EA6E60;
  --risk-extreme-t: #D2789C;

  --risk-calm-bg:    #1B3A42;
  --risk-watch-bg:   #3A2E14;
  --risk-alert-bg:   #3D2417;
  --risk-severe-bg:  #3A1C18;
  --risk-extreme-bg: #351623;

  --exec-queued:     #8CA0BE;
  --exec-queued-bg:  #131B2E;
  --exec-running:    #3E8FD9;
  --exec-running-bg: #16233D;
  --exec-ok:         #6FB195;
  --exec-ok-bg:      #10241D;
  --exec-failed:     #8CA0BE;
  --exec-failed-bg:  #161E30;
  --exec-hatch:      rgba(140,160,190,.20);

  --destructive:    #E58B7F;
  --destructive-bg: #3A1C18;
  --caution:        #E5BC5E;
  --caution-bg:     #3A2E14;
  --positive:       #6FB195;
  --positive-bg:    #10241D;

  --hover:   rgba(231,236,245,.04);
  --hover-s: rgba(231,236,245,.08);
  --scrim:   rgba(0,0,0,.65);
  --shadow:  0 8px 28px rgba(0,0,0,.5);
  --shadow-raw: rgba(0,0,0,.5);
}

/* ── Dado tabular ────────────────────────────────────────────────────────
   O gesto tipográfico da direção A: a face condensada, que existia no
   projeto e era usada uma única vez, vira a assinatura de todo cabeçalho
   de tabela e rótulo. Número é sempre mono, tabular e alinhado à direita —
   antes não havia um único `tabular-nums` em nenhuma superfície de dado,
   então colunas de contagem não alinhavam entre linhas. */
.mono { font-family: var(--mono); font-variant-numeric: tabular-nums; }
th.num, td.num, .num {
  text-align: right;
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
}
.lbl-cond {
  font-family: var(--cond);
  font-weight: 600;
  letter-spacing: .07em;
  text-transform: uppercase;
}

/* ── Severidade — uma definição, todas as telas ──────────────────────────
   A invariante do produto diz que severo é severo em qualquer tela. Isso
   estava escrito como comentário e repetido à mão em index.html e
   report.html; agora é estrutura. Extreme não entra aqui: é a marca de
   exploração ativa confirmada (KEV), não um sexto grau. */
/* O nome do nível é rótulo, não medida: vai em condensada. Mono fica
   reservado a número e identificador (CVE, alvo, hash). */
.badge[class*="sev-badge-"] { font-family: var(--cond); font-size: var(--fs-micro);
  font-weight: 600; letter-spacing: .05em; text-transform: uppercase; }
.sev-badge-Critical, .sev-badge-critical { background: var(--risk-severe-bg); color: var(--risk-severe-t); }
.sev-badge-High,     .sev-badge-high     { background: var(--risk-alert-bg);  color: var(--risk-alert-t); }
.sev-badge-Medium,   .sev-badge-medium   { background: var(--risk-watch-bg);  color: var(--risk-watch-t); }
.sev-badge-Low,      .sev-badge-low      { background: var(--risk-calm-bg);   color: var(--risk-calm-t); }
.sev-badge-Info,     .sev-badge-info     { background: var(--surface-2);      color: var(--muted); }

/* ── Estado de execução — uma definição, três páginas ────────────────────
   Antes cada página redeclarava estes quatro badges com literais rgba()
   próprios. A forma faz o trabalho que a cor não deve fazer: a fila é
   tracejada, a falha é hachurada. */
.status-succeeded { background: var(--exec-ok-bg);      color: var(--exec-ok); }
.status-running   { background: var(--exec-running-bg); color: var(--exec-running); }
.status-queued    { background: var(--exec-queued-bg);  color: var(--exec-queued);
                    border: 1px dashed var(--border-s); }
.status-failed    { background: var(--exec-failed-bg);  color: var(--exec-failed);
                    background-image: repeating-linear-gradient(135deg,
                      transparent 0 4px, var(--exec-hatch) 4px 5px);
                    font-weight: 600; }

/* ── Procedência: coletado dentro do perímetro do cliente ────────────────
   O sensor remoto é a razão de existir do produto. Até aqui isso não tinha
   nenhuma expressão visual. */
.prov-sensor {
  color: var(--tenant);
  border-left: 2px solid var(--tenant);
  padding-left: 6px;
}

/* ── Skeleton loading ────────────────────────────────────────────────────── */
.skeleton {
  background: linear-gradient(
    90deg,
    var(--surface-2) 25%,
    var(--border)    50%,
    var(--surface-2) 75%
  );
  background-size: 200% 100%;
  animation: sk-shimmer 1.4s ease-in-out infinite;
  border-radius: 4px;
  display: inline-block;
}
@keyframes sk-shimmer {
  0%   { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}
@media (prefers-reduced-motion: reduce) {
  .skeleton { animation: none; background: var(--surface-2); }
}

/* ── Vocabulário de entrada/saída ─────────────────────────────────────────
   Um punhado de gestos, reaproveitados em toda a interface em vez de cada
   página inventar o seu. Todos com curva de saída (--ease-out): a leitura
   de dado tem que assentar rápido, não flutuar. */
@keyframes bs-fade-up {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: translateY(0); }
}
@keyframes bs-fade-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}
@keyframes bs-pop-in {
  from { opacity: 0; transform: scale(.97); }
  to   { opacity: 1; transform: scale(1); }
}
@keyframes bs-scan-sweep {
  0%   { transform: translateX(-100%); }
  100% { transform: translateX(100%); }
}

/* Entrada de bloco de conteúdo — página, card, linha de tabela nova.
   Aplicar via classe; --bs-delay controla o escalonamento (stagger). */
.bs-enter {
  animation: bs-fade-up var(--dur-slow) var(--ease-out) both;
  animation-delay: var(--bs-delay, 0ms);
}
.bs-enter-fade {
  animation: bs-fade-in var(--dur-base) var(--ease-out) both;
  animation-delay: var(--bs-delay, 0ms);
}
/* Overlay que abre por cima do conteúdo (dropdown, modal, popover) — não
   sobe da tela, aparece já no lugar, só resolve escala. Confundir com
   bs-enter faria menu de contexto "voar" de baixo, gesto que pertence a
   toast/notificação, não a controle de navegação. */
.bs-pop {
  animation: bs-pop-in var(--dur-base) var(--ease-out) both;
  transform-origin: var(--bs-pop-origin, top center);
}

@media (prefers-reduced-motion: reduce) {
  .bs-enter, .bs-enter-fade, .bs-pop {
    animation-duration: .01ms !important;
    animation-delay: 0ms !important;
  }
}

/* ── Indicador "ao vivo" ───────────────────────────────────────────────
   Usa a tinta de --exec-running, o mesmo token do eixo de execução — só
   aparece quando existe de fato um job com status=running vindo da API.
   Não é decoração: é a única pulsação da interface amarrada a um estado
   real, e some sozinha quando não há nada rodando. */
.live-badge {
  display: inline-flex; align-items: center; gap: 6px;
  font-family: var(--cond); font-size: var(--fs-micro); font-weight: 600;
  letter-spacing: .05em; text-transform: uppercase;
  color: var(--exec-running); background: var(--exec-running-bg);
  padding: 4px 10px 4px 8px; border-radius: 12px;
}
.live-dot {
  width: 7px; height: 7px; border-radius: 50%; background: var(--exec-running);
  animation: bs-pulse 1.6s var(--ease-in-out) infinite;
}
@keyframes bs-pulse {
  0%, 100% { transform: scale(1);    opacity: 1; }
  50%      { transform: scale(1.5);  opacity: .45; }
}
@media (prefers-reduced-motion: reduce) {
  .live-dot { animation: none; }
}
