/* Painel administrativo. Sem framework: o projeto nao tem toolchain de frontend, e
   introduzir um passo de build para um painel interno custaria mais do que entrega. */

:root {
  --fundo: #0f1216;
  --superficie: #171b21;
  --superficie-2: #1e242c;
  --borda: #2a323d;
  --texto: #e6eaf0;
  --texto-fraco: #93a1b1;
  --acento: #4c9aff;
  --ok: #35c07f;
  --alerta: #e0a038;
  --erro: #e2564a;
  --recuperando: #7b8ff5;
  --desconhecido: #6b7684;
}

* { box-sizing: border-box; }

/* O atributo `hidden` precisa VENCER as regras de layout.
 *
 * A folha do navegador aplica `[hidden] { display: none }`, mas ela e de origem UA e
 * perde para qualquer regra de autor. Como `.login` e `.painel` declaram
 * `display: grid`, o `hidden` nunca teve efeito nesses dois — os dois containers
 * renderizavam ao mesmo tempo, e o painel aparecia abaixo do formulario de login.
 *
 * Isto NAO esconde nada permanentemente: e o contrario disso. Devolve ao atributo o
 * significado que ele deveria ter, para que a visibilidade continue sendo decidida em
 * um lugar so — `setAutenticado()`, em js/app.js — e nao pela ordem das regras. Um
 * seletor de atributo com `!important` e a forma que a propria especificacao sugere
 * ao autor que declara `display` em elemento que pode ser ocultado. */
[hidden] { display: none !important; }

body {
  margin: 0;
  background: var(--fundo);
  color: var(--texto);
  font: 15px/1.5 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
}

/* --- Login --- */
.login { display: grid; place-items: center; min-height: 100vh; }
.cartao {
  background: var(--superficie);
  border: 1px solid var(--borda);
  border-radius: 12px;
  padding: 32px;
  width: min(360px, 90vw);
  display: grid;
  gap: 14px;
}
.cartao h1 { margin: 0; font-size: 22px; }
.cartao .sub { margin: 0 0 8px; color: var(--texto-fraco); font-size: 14px; }

label { display: grid; gap: 6px; font-size: 13px; color: var(--texto-fraco); }

input, select, textarea {
  background: var(--superficie-2);
  border: 1px solid var(--borda);
  color: var(--texto);
  border-radius: 7px;
  padding: 9px 11px;
  font: inherit;
  width: 100%;
}
input:focus, select:focus, textarea:focus, button:focus-visible {
  outline: 2px solid var(--acento);
  outline-offset: 1px;
}

button {
  background: var(--acento);
  color: #04131f;
  border: 0;
  border-radius: 7px;
  padding: 9px 15px;
  font: inherit;
  font-weight: 600;
  cursor: pointer;
}
button:disabled { opacity: .5; cursor: not-allowed; }
button.secundario { background: var(--superficie-2); color: var(--texto); border: 1px solid var(--borda); }
button.perigo { background: var(--erro); color: #fff; }
button.link { background: none; color: var(--texto-fraco); padding: 0; font-weight: 400; text-decoration: underline; }

/* --- Estrutura ---------------------------------------------------------------

   A barra lateral e uma COLUNA DE LARGURA FIXA, e o conteudo ocupa o resto. Duas
   armadilhas que ja morderam aqui e que os comentarios abaixo existem para evitar
   que voltem:

   1. Os links do menu sao montados por JavaScript dentro de `#menu`, e nao mais como
      filhos diretos da barra. Um `<a>` e INLINE por padrao, e padding vertical em
      elemento inline NAO empurra a linha — os itens se sobrepunham uns aos outros.
      Por isso `#menu` e flex-column e cada `a` e `block`.

   2. Com a coluna estreita e rotulos longos ("Usuarios e Permissoes"), o texto
      transbordava a coluna e caia POR CIMA do conteudo principal. `min-width: 0` na
      barra e quebra de palavra no link resolvem: o rotulo quebra em duas linhas, que
      e melhor que sumir com reticencias — a navegacao nao pode esconder para onde
      leva.
*/
.painel {
  display: grid;
  grid-template-columns: 248px minmax(0, 1fr);
  min-height: 100vh;
}
.lateral {
  background: var(--superficie);
  border-right: 1px solid var(--borda);
  padding: 20px 0 18px;
  display: flex;
  flex-direction: column;
  min-width: 0;
  /* A barra acompanha a rolagem: numa tabela longa de auditoria, perder a navegacao
     de vista obriga a rolar de volta ao topo so para trocar de tela. */
  position: sticky;
  top: 0;
  align-self: start;
  height: 100vh;
}
.marca {
  font-weight: 700;
  padding: 0 20px 20px;
  font-size: 17px;
  letter-spacing: .01em;
}

#menu {
  display: flex;
  flex-direction: column;
  gap: 2px;
  /* Com muitas secoes numa janela baixa, o menu rola sozinho em vez de empurrar o
     rodape para fora da tela. */
  overflow-y: auto;
  min-height: 0;
}
.lateral a {
  display: block;
  color: var(--texto-fraco);
  text-decoration: none;
  padding: 9px 18px;
  border-left: 3px solid transparent;
  font-size: 14px;
  line-height: 1.35;
  overflow-wrap: anywhere;
}
.lateral a:hover { color: var(--texto); background: var(--superficie-2); }
.lateral a.ativo {
  color: var(--texto);
  border-left-color: var(--acento);
  background: var(--superficie-2);
  font-weight: 600;
}
.lateral .legenda { padding: 0 18px; margin: 8px 0 0; font-size: 12px; }

/* Rodape da barra: quem esta logado, atalho para a propria conta, e sair. */
.rodape {
  margin-top: auto;
  padding: 14px 18px 0;
  border-top: 1px solid var(--borda);
  font-size: 13px;
  color: var(--texto-fraco);
  display: grid;
  gap: 4px;
}
.rodape #quem {
  color: var(--texto);
  font-weight: 600;
  overflow-wrap: anywhere;
}
.rodape a {
  padding: 6px 0;
  border-left: 0;
  font-size: 13px;
}
.rodape a:hover { background: none; text-decoration: underline; }
.rodape a.ativo { background: none; border-left: 0; }
.rodape .link { justify-self: start; margin-top: 2px; }

main {
  padding: 28px 32px 48px;
  min-width: 0;
  /* Teto de leitura em telas muito largas. Tabela de auditoria com 1800 px de linha
     nao fica mais legivel, fica mais dificil de varrer com o olho. */
  max-width: 1680px;
}

/* Cabecalho da tela, separado do conteudo por uma regra. As telas montam `h2` e o
   subtitulo como primeiros filhos de `main` (helper `cabecalho()` em js/ui.js). */
h2 { margin: 0 0 6px; font-size: 21px; letter-spacing: .01em; }
h3 { margin: 26px 0 12px; font-size: 15px; }
main > h3:first-of-type { margin-top: 0; }
.legenda { color: var(--texto-fraco); font-size: 14px; margin: 0 0 20px; }
main > .legenda:first-of-type {
  margin: 0 0 24px;
  padding-bottom: 18px;
  border-bottom: 1px solid var(--borda);
}

/* --- Tabelas --- */
.tabela-wrap { overflow-x: auto; border: 1px solid var(--borda); border-radius: 10px; }
table { border-collapse: collapse; width: 100%; font-size: 14px; }
th, td { text-align: left; padding: 10px 13px; border-bottom: 1px solid var(--borda); }
th { color: var(--texto-fraco); font-weight: 600; font-size: 12px; text-transform: uppercase; letter-spacing: .04em; }
tbody tr:last-child td { border-bottom: 0; }
tbody tr:hover { background: var(--superficie); }

/* --- Estado de câmera --- */
.estado { display: inline-flex; align-items: center; gap: 6px; font-weight: 600; font-size: 13px; }
.estado::before { content: ""; width: 8px; height: 8px; border-radius: 50%; background: currentColor; }
.estado-ONLINE { color: var(--ok); }
.estado-DEGRADED { color: var(--alerta); }
.estado-OFFLINE { color: var(--erro); }
.estado-RECOVERING { color: var(--recuperando); }
.estado-UNKNOWN { color: var(--desconhecido); }

.selo {
  display: inline-block;
  background: var(--superficie-2);
  border: 1px solid var(--borda);
  border-radius: 999px;
  padding: 1px 9px;
  font-size: 12px;
  color: var(--texto-fraco);
}
.selo.on { color: var(--ok); border-color: var(--ok); }
.selo.off { color: var(--desconhecido); }
.selo.aviso { color: var(--alerta); border-color: var(--alerta); }

/* Qualificador do estado: diz POR QUE, em tom deliberadamente neutro. Uma câmera fora
   do perfil está entregando vídeo, e não pode competir visualmente com uma caída. */
.qualificador {
  margin-left: 8px;
  color: var(--texto-fraco);
  font-size: 12px;
  font-weight: 400;
}

/* Medido x estimado. Não é decoração: separa o que o media plane confirma do que nós
   inferimos do tíquete (AD-10). */
.medicao {
  display: inline-block;
  margin-left: 7px;
  padding: 0 6px;
  border-radius: 4px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .03em;
  text-transform: uppercase;
  border: 1px solid var(--borda);
  color: var(--texto-fraco);
}
.medicao.medido { color: var(--ok); border-color: var(--ok); }
.medicao.estimado { color: var(--alerta); border-color: var(--alerta); }
.medicao.ausente { color: var(--desconhecido); }

/* --- Cartões e grades --- */
/* `auto-fill` com minimo de 220 px: em 1920 rende 6-7 cartoes por linha sem
   esticar nenhum, e em 1280 rende 4. O `min-width: 0` em `.metrica` logo abaixo e
   o que impede um cartao com texto longo de estourar a coluna — `minmax` aninhado
   nao existe em CSS e invalidaria a regra inteira. */
.grade { display: grid; gap: 16px; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); margin: 0 0 24px; }
.metrica { min-width: 0; overflow-wrap: anywhere; }
.metrica { background: var(--superficie); border: 1px solid var(--borda); border-radius: 10px; padding: 15px 17px; }
.metrica .n { font-size: 26px; font-weight: 700; }
.metrica .r { color: var(--texto-fraco); font-size: 13px; }

.barra { display: flex; gap: 10px; align-items: center; margin-bottom: 16px; flex-wrap: wrap; }
.barra .espaco { flex: 1; }

/* --- Diálogo --- */
dialog {
  background: var(--superficie);
  color: var(--texto);
  border: 1px solid var(--borda);
  border-radius: 12px;
  padding: 0;
  width: min(620px, 94vw);
}
dialog::backdrop { background: #000a; }
.dialogo-cabeca { padding: 18px 22px; border-bottom: 1px solid var(--borda); font-weight: 600; }
.dialogo-corpo { padding: 20px 22px; display: grid; gap: 14px; max-height: 68vh; overflow-y: auto; }
.dialogo-pe { padding: 15px 22px; border-top: 1px solid var(--borda); display: flex; gap: 10px; justify-content: flex-end; }
.dupla { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
fieldset { border: 1px solid var(--borda); border-radius: 9px; padding: 14px; display: grid; gap: 12px; }
legend { color: var(--texto-fraco); font-size: 12px; padding: 0 6px; text-transform: uppercase; letter-spacing: .04em; }

/* --- Mensagens --- */
.nota { border-left: 3px solid var(--acento); background: var(--superficie); padding: 12px 15px; border-radius: 0 8px 8px 0; font-size: 14px; }
.nota.aviso { border-left-color: var(--alerta); }
.nota.ruim { border-left-color: var(--erro); }
.nota.bom { border-left-color: var(--ok); }
.erro { color: var(--erro); font-size: 13px; margin: 0; min-height: 18px; }

.avisos { position: fixed; right: 18px; bottom: 18px; display: grid; gap: 8px; z-index: 50; }
.aviso-item {
  background: var(--superficie-2);
  border: 1px solid var(--borda);
  border-left: 3px solid var(--acento);
  border-radius: 8px;
  padding: 11px 15px;
  font-size: 14px;
  max-width: 380px;
}
.aviso-item.ruim { border-left-color: var(--erro); }
.aviso-item.bom { border-left-color: var(--ok); }
.aviso-item.aviso { border-left-color: var(--alerta); }

/* --- Não implementado --- */
.pendente { max-width: 620px; }
.pendente h3 { margin: 0 0 8px; font-size: 16px; }
.pendente ul { margin: 10px 0 0; padding-left: 20px; color: var(--texto-fraco); font-size: 14px; }
.pendente code { background: var(--superficie-2); padding: 1px 5px; border-radius: 4px; font-size: 13px; }

/* --- Integração: cada tipo de valor tem uma aparência própria -----------------
 *
 * Não é decoração. Um administrador que nunca viu o código precisa distinguir, de
 * relance, o que ele cola num site do que ele chama de um servidor, e o que jamais
 * pode aparecer numa página. Tudo em monoespaçado e cinza obriga a ler cada linha
 * para descobrir o que é. */

.valor { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 13px; }

/* URL pública: vai para o navegador do espectador. */
.v-url {
  display: inline-block; padding: 3px 8px; border-radius: 6px;
  background: rgba(53,192,127,.10); border: 1px solid var(--ok); color: var(--ok);
  overflow-wrap: anywhere;
}
/* Endpoint de API: chamado por um SERVIDOR, com credencial. */
.v-endpoint {
  display: inline-flex; align-items: center; gap: 8px; padding: 3px 8px;
  border-radius: 6px; background: rgba(76,154,255,.10);
  border: 1px solid var(--acento); color: var(--acento); overflow-wrap: anywhere;
}
.v-metodo {
  font-size: 11px; font-weight: 700; letter-spacing: .04em;
  background: var(--acento); color: #04131f; padding: 0 6px; border-radius: 4px;
}
/* Identificador: opaco, copia-se como está. */
.v-id {
  display: inline-block; padding: 3px 8px; border-radius: 6px;
  background: var(--superficie-2); border: 1px solid var(--borda);
  color: var(--texto); overflow-wrap: anywhere;
}
/* Segredo: nunca carrega valor. A caixa existe para dizer onde ele NÃO está. */
.v-segredo {
  display: inline-block; padding: 3px 8px; border-radius: 6px;
  background: rgba(226,86,74,.10); border: 1px dashed var(--erro); color: var(--erro);
}

.exemplo {
  position: relative; background: var(--superficie-2); border: 1px solid var(--borda);
  border-radius: 8px; padding: 12px 14px; margin: 0;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 12.5px; line-height: 1.55; white-space: pre; overflow-x: auto;
}
.exemplo-cabeca {
  display: flex; align-items: center; gap: 10px; margin: 0 0 6px;
  font-size: 12px; color: var(--texto-fraco);
}
.exemplo-cabeca .espaco { flex: 1; }

.campo-linha {
  display: grid; grid-template-columns: 190px minmax(0, 1fr);
  gap: 6px 14px; align-items: start; padding: 7px 0;
  border-bottom: 1px solid var(--borda); font-size: 14px;
}
.campo-linha:last-child { border-bottom: 0; }
.campo-linha > .rot { color: var(--texto-fraco); font-size: 13px; }

.fluxo {
  display: grid; gap: 6px; margin: 0; padding: 12px 14px;
  background: var(--superficie-2); border: 1px solid var(--borda); border-radius: 8px;
  font-size: 13px;
}
.fluxo .passo { display: grid; grid-template-columns: 22px minmax(0,1fr); gap: 10px; }
.fluxo .n {
  width: 22px; height: 22px; border-radius: 50%; display: grid; place-items: center;
  background: var(--acento); color: #04131f; font-size: 12px; font-weight: 700;
}
.fluxo .seta { color: var(--texto-fraco); padding-left: 8px; }

/* --- Player administrativo --- */
.palco { background: #000; border-radius: 10px; overflow: hidden; aspect-ratio: 16/9; display: grid; place-items: center; }
.palco video { width: 100%; height: 100%; object-fit: contain; background: #000; }
.diag { font-size: 13px; color: var(--texto-fraco); display: grid; gap: 4px; margin-top: 12px; }
.diag b { color: var(--texto); font-weight: 600; }
.detalhes { display: grid; grid-template-columns: auto 1fr; gap: 5px 16px; font-size: 14px; }
.detalhes dt { color: var(--texto-fraco); }
.detalhes dd { margin: 0; }
.vazio { color: var(--texto-fraco); padding: 34px; text-align: center; }

/* --- Ritmo vertical e barras de controle ------------------------------------- */

/* Barras com muitos controles (filtros de camera, sessao e auditoria) precisam
   quebrar em telas estreitas; sem isto os seletores saem da area visivel. */
.barra {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
  row-gap: 10px;
  margin: 0 0 18px;
}
/* Nenhum filho de `.barra` carrega margem propria: num container flex alinhado ao
   centro, uma margem vertical de um item desloca ele sozinho e a linha perde o
   alinhamento — foi o que fazia o "atualizado ha N s" do Dashboard sair do lugar. */
.barra > * { margin-top: 0; margin-bottom: 0; }
.barra .legenda { margin: 0; }
.barra select, .barra input { width: auto; min-width: 150px; }
.barra input[type="search"] { min-width: 200px; }

/* Os controles de filtro sao formulario, e nao texto: a altura precisa bater com a
   dos botoes ao lado, ou a linha fica serrilhada. */
.barra select, .barra input, .barra button { min-height: 38px; }

/* Seccoes dentro de uma tela (Diagnostico, Sistema) respiram entre si. */
main section { margin-bottom: 30px; }
main section:last-child { margin-bottom: 0; }

/* `code` aparece em tabela (permissoes, acoes de auditoria, nomes de worker) e nao
   so dentro de `.pendente`. */
td code, .nota code, label code, .diag code {
  background: var(--superficie-2);
  padding: 1px 5px;
  border-radius: 4px;
  font-size: 13px;
}

/* Rotulo de permissao no formulario de papel: caixa em cima, texto ao lado, e a
   descricao quebrando normalmente em vez de esticar o dialogo. */
fieldset label span { min-width: 0; }

/* --- Tabelas em tela cheia ---------------------------------------------------- */

/* O cabecalho gruda no topo ao rolar uma trilha de auditoria longa: sem isso, a
   partir da linha 30 nao se sabe mais qual coluna e qual. */
.tabela-wrap { max-height: none; }
thead th {
  position: sticky;
  top: 0;
  background: var(--superficie);
  z-index: 1;
}

/* --- Telas menores ------------------------------------------------------------ */

/* Abaixo de 960 px a coluna fixa deixa de caber: a navegacao vira uma faixa
   horizontal rolavel no topo. Nenhuma informacao e escondida — ela muda de eixo. */
@media (max-width: 960px) {
  .painel { grid-template-columns: 1fr; }
  .lateral {
    position: static;
    height: auto;
    border-right: 0;
    border-bottom: 1px solid var(--borda);
    padding: 14px 0 10px;
  }
  .marca { padding: 0 16px 12px; }
  #menu {
    flex-direction: row;
    overflow-x: auto;
    gap: 4px;
    padding: 0 12px;
  }
  .lateral a {
    border-left: 0;
    border-bottom: 3px solid transparent;
    white-space: nowrap;
    border-radius: 6px 6px 0 0;
  }
  .lateral a.ativo { border-left: 0; border-bottom-color: var(--acento); }
  .rodape {
    margin-top: 10px;
    padding: 10px 16px 0;
    grid-auto-flow: column;
    justify-content: start;
    align-items: center;
    gap: 14px;
  }
  main { padding: 20px 16px 40px; }
  .grade { grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); }
}

@media (max-width: 560px) {
  .dupla { grid-template-columns: 1fr; }
  main { padding: 16px 12px 32px; }
}
