/* CFTV-RTSP — folha única, sem framework e sem build.
   A CSP proíbe style inline (`style="..."` e `<style>`), então TODO estilo vive aqui; o JavaScript
   só troca classes e variáveis CSS via CSSOM, que a CSP não bloqueia. */

/* Paleta da marca SRV CLOUD: preto, vermelho, azul.

   O vermelho fica reservado à IDENTIDADE (logotipo, nome, detalhe do topo) e o azul continua
   sendo a cor de AÇÃO. Não é preciosismo: num painel de vigilância, vermelho já quer dizer
   "algo está errado" — botão vermelho por decoração faria o operador ler alarme onde não há, e
   pior, diluiria o vermelho de verdade quando ele aparecesse. Por isso `--erro` é um vermelho
   mais claro e menos saturado que `--marca-vermelho`: os dois convivem sem se confundir. */
:root {
  color-scheme: dark;
  --marca-azul: #2f7ee6;      /* contorno da nuvem */
  --marca-ciano: #38b6f5;     /* as setas de subida/descida */
  --marca-vermelho: #e5202a;  /* a palavra CLOUD */
  --bg: #12151a;
  --bg-2: #1a1f27;
  --bg-3: #232a35;
  --linha: #2e3744;
  --txt: #e6eaf0;
  --txt-2: #97a3b4;
  --acento: var(--marca-azul);
  --sobre-acento: #06121f;    /* texto POR CIMA do azul de ação */
  --ok: #3fb950;
  --alerta: #d29922;
  --erro: #f05d5d;
  --raio: 8px;
  --raio-grande: 14px; /* só o módulo de Orçamento — cartões maiores pedem um raio mais visível */
  --fonte: system-ui, "Segoe UI", Roboto, sans-serif;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--txt);
  font: 14px/1.5 var(--fonte);
}

a { color: var(--acento); }
button, input, select, textarea { font: inherit; color: inherit; }

/* Ícones em SVG (`icones.js`): traço puro, sem preenchimento — herdam `currentColor`, então o
   MESMO ícone serve para texto normal, hover azul ou nota de alerta âmbar sem precisar de uma
   variante por cor. Substituem Font Awesome (pedido do usuário): a CSP deste app não abre
   `style-src`/`script-src` para CDN nenhum (nem para um webfont de ícones hospedado fora), e
   vendorizar um pacote inteiro de ícones só por um menu seria peso desproporcional ao ganho —
   mesmo raciocínio que já vale para a fonte do login (F3.5, 13/09) e para o hls.js (só quando
   preciso). */
.ic {
  width: 18px;
  height: 18px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
  flex-shrink: 0;
}

/* ------------------------------------------------------------------ login */
/* F3.5 (13/09/2026): visual replicado fielmente de uma referência HTML entregue pelo usuário —
   cartão com campos em "pílula" (ícone + input), botão de mostrar/ocultar senha, nuvens em
   contorno no fundo, rodapé com divisor+nuvem+slogan. A referência usava a fonte Google "Inter"
   e um `<style>`/`<script>` inline — os dois são impossíveis aqui: a CSP do projeto não abre
   `style-src`/`script-src` além de 'self' (nem Google Fonts, nem inline), então a fonte fica na
   pilha do sistema (`--fonte`, já usada no resto do app) e todo CSS/JS mora nos arquivos de sempre
   (`app.css`, `login.js`) — o visual é o mesmo, só a fonte muda de família. */

.login-wrap {
  min-height: 100vh;
  display: grid;
  place-items: center;
  padding: 32px 20px;
  position: relative;
}

/* Fundo decorativo (aria-hidden no HTML): nuvens em contorno + brilho suave, na paleta da marca.
   O vermelho fica de fora de propósito — aqui é ambientação, não identidade nem alarme. */
.login-fundo {
  position: fixed;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  background:
    radial-gradient(1100px 700px at 78% 38%, rgba(47, 126, 230, .14), transparent 62%),
    radial-gradient(900px 620px at 12% 88%, rgba(56, 182, 245, .10), transparent 64%);
}
.login-fundo svg { position: absolute; inset: 0; width: 100%; height: 100%; }
.login-fundo .nuvem { fill: none; stroke: var(--marca-azul); stroke-width: 11; stroke-linejoin: round; }
.login-fundo .nuvem-1 { opacity: .5; }
.login-fundo .nuvem-2 { opacity: .28; stroke: var(--marca-ciano); }
.login-fundo .nuvem-3 { opacity: .22; }

.card {
  position: relative;
  z-index: 1;
  background: linear-gradient(180deg, var(--bg-2), var(--bg));
  border: 1px solid var(--linha);
  border-radius: 16px;
  padding: 36px 34px 28px;
  width: 100%;
  max-width: 440px;
  box-shadow: 0 30px 70px rgba(0, 0, 0, .5);
}

.card h1 { margin: 0 0 4px; font-size: 20px; }
.card .sub { margin: 0 0 20px; color: var(--txt-2); font-size: 13px; }

.tagline { margin: 18px 0 26px; text-align: center; font-size: 14.5px; line-height: 1.45; color: var(--txt-2); }

label { display: block; margin: 14px 0 6px; color: var(--txt-2); font-size: 13px; }

/* Campo em "pílula": ícone + input (+ botão de olho, na senha) num único contêiner com borda —
   troca a borda simples do resto do app só aqui, para bater com a referência do usuário. */
.campo-grupo { margin-bottom: 6px; }
.campo-grupo label { margin: 0 0 8px; }

.entrada {
  display: flex;
  align-items: center;
  gap: 10px;
  background: var(--bg);
  border: 1px solid var(--linha);
  border-radius: 10px;
  padding: 0 12px;
  height: 48px;
  transition: border-color .15s, box-shadow .15s;
}
.entrada:focus-within { border-color: var(--acento); box-shadow: 0 0 0 3px rgba(47, 126, 230, .18); }
.entrada svg.icone { width: 19px; height: 19px; flex: 0 0 auto; color: var(--txt-2); }
/* `.card` na frente: a regra geral de `input[type=…]`, mais abaixo, tem a mesma especificidade e,
   por vir depois, desenhava uma segunda caixa (e um segundo anel de foco) dentro da pílula */
.card .entrada input {
  flex: 1;
  min-width: 0;
  height: 100%;
  padding: 0;
  background: none;
  border: 0;
  border-radius: 0;
  outline: none;
  font: inherit;
  font-size: 14.5px;
  color: var(--txt);
}

.olho {
  background: none;
  border: 0;
  padding: 4px;
  cursor: pointer;
  color: var(--txt-2);
  display: grid;
  place-items: center;
  border-radius: 6px;
  flex: 0 0 auto;
}
.olho:hover { color: var(--txt); }
.olho:focus-visible { outline: 2px solid var(--acento); outline-offset: 2px; }
.olho svg { width: 19px; height: 19px; }
.olho .ic-ocultar { display: none; }
.olho.mostrando .ic-mostrar { display: none; }
.olho.mostrando .ic-ocultar { display: block; }

.card .btn.largo {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  height: 50px;
  font-size: 15px;
}
.card .btn.largo svg { width: 18px; height: 18px; flex: 0 0 auto; }

.quem-entra { margin: 0 0 16px; font-size: 13px; color: var(--txt-2); }
.quem-entra strong { color: var(--txt); }

/* "Manter conectado" (26/09/2026): o interruptor de Configurações (`.interruptor`, mais abaixo),
   com o aviso de por quanto tempo aparecendo só quando está ligado */
label.interruptor.lembrar { margin: 16px 0 0; font-size: 13.5px; }
.lembrar-aviso {
  margin: 10px 0 0; padding: 9px 11px; border: 1px solid rgba(47, 126, 230, .35); border-radius: 9px;
  background: rgba(47, 126, 230, .08); color: var(--txt-2); font-size: 12.5px; line-height: 1.5;
}
.lembrar-aviso:empty { display: none; }
.quem-entra-lembrar {
  display: inline-block; margin-left: 4px; padding: 1px 8px; border-radius: 999px;
  background: rgba(47, 126, 230, .14); color: var(--acento); font-size: 11.5px;
}
.quem-entra-lembrar:empty { display: none; }

.link {
  background: none;
  border: 0;
  padding: 0;
  color: var(--acento);
  cursor: pointer;
  font: inherit;
  text-decoration: underline;
}
.link:hover { filter: brightness(1.2); }
.link:focus-visible { outline: 2px solid var(--acento); outline-offset: 2px; }

.rodape-login { margin-top: 26px; text-align: center; }
.divisor { display: flex; align-items: center; gap: 12px; margin-bottom: 14px; }
.divisor hr { flex: 1; border: 0; border-top: 1px solid var(--linha); margin: 0; }
.divisor .icone-nuvem { width: 22px; height: 22px; color: var(--acento); flex: 0 0 auto; }
.marca-nome { font-size: 12.5px; font-weight: 600; letter-spacing: .2em; color: var(--acento); margin: 0 0 4px; }
.slogan { font-size: 13px; color: var(--txt-2); margin: 0; }

@media (max-width: 480px) {
  .card { padding: 26px 20px 22px; border-radius: 12px; }
  .marca-login img { width: 140px; }
}

input[type="text"], input[type="password"], input[type="number"], select, textarea {
  width: 100%;
  padding: 9px 11px;
  background: var(--bg);
  border: 1px solid var(--linha);
  border-radius: 6px;
}

input:focus, select:focus, textarea:focus {
  outline: 2px solid var(--acento);
  outline-offset: -1px;
  border-color: transparent;
}

.btn {
  padding: 9px 16px;
  background: var(--acento);
  color: var(--sobre-acento);
  border: 0;
  border-radius: 6px;
  cursor: pointer;
  font-weight: 600;
}

.btn:hover { filter: brightness(1.1); }
.btn:disabled { opacity: .5; cursor: default; }
.btn.secundario { background: var(--bg-3); color: var(--txt); }
.btn.perigo { background: var(--erro); color: #1a0808; }
.btn.largo { width: 100%; margin-top: 20px; }
.btn.pequeno { padding: 5px 10px; font-size: 13px; font-weight: 500; }

.aviso {
  margin-top: 16px;
  padding: 10px 12px;
  border-radius: 6px;
  background: rgba(240, 93, 93, .12);
  border: 1px solid rgba(240, 93, 93, .4);
  font-size: 13px;
}

.aviso.ok { background: rgba(63, 185, 80, .12); border-color: rgba(63, 185, 80, .4); }
.aviso.info { background: rgba(47, 126, 230, .14); border-color: rgba(47, 126, 230, .45); }
.aviso:empty { display: none; }

/* ------------------------------------------------------------------ toasts (avisos flutuantes) */

.toasts {
  position: fixed;
  right: 16px;
  bottom: 16px;
  z-index: 500;
  display: flex;
  flex-direction: column-reverse;
  gap: 8px;
  max-width: min(360px, calc(100vw - 32px));
  pointer-events: none;
}

.toast {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  border-radius: 6px;
  background: var(--erro);
  color: #1a0808;
  font-size: 13px;
  line-height: 1.35;
  box-shadow: 0 6px 18px rgba(0, 0, 0, .35);
  animation: toast-entra .15s ease-out;
  pointer-events: auto;
}

.toast.ok { background: var(--ok); }
.toast.alerta { background: var(--alerta); }
.toast.info { background: var(--marca-ciano); }

.toast span { flex: 1; }

.toast-fechar {
  background: transparent;
  border: none;
  color: inherit;
  font-size: 17px;
  line-height: 1;
  padding: 0 2px;
  cursor: pointer;
  opacity: .7;
}
.toast-fechar:hover { opacity: 1; }

/* mensagem repetida (mesmo toast, novo clique): um pisca curto, em vez de empilhar outra caixa */
.toast-repete { animation: toast-repete .3s ease-out; }

@keyframes toast-entra {
  from { opacity: 0; transform: translateY(8px); }
  to { opacity: 1; transform: none; }
}

@keyframes toast-repete {
  0%, 100% { transform: none; }
  30% { transform: scale(1.03); }
}

/* ------------------------------------------------------------------ shell */
/* "Console admin" (10/10/2026, pedido do usuário): o menu principal saiu da barra de cima e virou
   uma barra LATERAL à esquerda, com botão para recolher (só os ícones). A barra de cima ficou fina
   e guarda só o caminho da tela atual e o menu da conta, que continua no canto superior direito
   (pedido de 26/09). O logotipo foi para o alto da lateral.

   O filete vermelho da marca (identidade, nunca estado) passou do cabeçalho para o alto do shell
   inteiro: com a lateral, o "alto da tela" é a largura toda, não só a barra de cima. */
.shell {
  --lateral-w: 232px;
  display: grid;
  grid-template-columns: var(--lateral-w) minmax(0, 1fr);
  height: 100vh;
  border-top: 2px solid var(--marca-vermelho);
}

/* ⛔ Lição de 19/09/2026 (celular): item de grid sem `min-width: 0` usa o tamanho mínimo do
   CONTEÚDO como piso da coluna — o menu horizontal de antes deixava a página inteira com ~645 px de
   largura mínima. A coluna da direita continua precisando disso (e de `min-height: 0`, para o
   `main` rolar por dentro em vez de esticar a página). */
.area {
  display: grid;
  grid-template-rows: auto minmax(0, 1fr);
  min-width: 0;
  min-height: 0;
}

/* ---- barra lateral */
aside.lateral {
  display: flex;
  flex-direction: column;
  min-width: 0;
  min-height: 0;
  overflow: hidden;
  background: var(--bg-2);
  border-right: 1px solid var(--linha);
}

/* Logotipo à esquerda e o botão de recolher à direita, no alto da lateral (referência do usuário,
   10/10/2026: "um símbolo de recolher na parte superior"). */
.marca { display: flex; align-items: center; justify-content: space-between; gap: 8px; flex: 0 0 auto; padding: 12px 14px 6px 18px; }

/* O logotipo INTEIRO (nuvem + "SRV" + "CLOUD"), a mesma arte do cartão de login — nunca um texto
   digitado ao lado dele: o logotipo já É o nome. A arte é quase quadrada (325×354), por isso a
   altura manda. `max-width` + `object-fit: contain` são a rede de segurança para um logotipo
   enviado pelo administrador com proporção muito larga: encolhe, nunca corta nem distorce. */
.marca-logo { height: 64px; max-width: 100%; width: auto; object-fit: contain; display: block; }

/* Recolhida, a lateral só comporta um ícone: o favicon oficial da entrega da marca (fundo sólido,
   feito para tamanho pequeno), ou o favicon enviado em Configurações (`marca.js`). A palavra do
   logotipo inteiro a 40 px viraria borrão — o mesmo motivo do favicon ser só o símbolo. */
.marca-icone { display: none; width: 40px; height: 40px; border-radius: 10px; object-fit: contain; }

/* No login há ainda mais espaço para o mesmo logotipo, em tamanho de cartaz. A arte tem 325 px de
   largura e aparece com 180: sobra resolução para tela densa. */
.marca-login { display: flex; justify-content: center; margin: 0 0 20px; }
.marca-login img { width: 180px; height: auto; display: block; }

/* A lista rola por dentro quando não cabe (Full HD a 125 % dá ~710 px de altura); o logotipo e o
   botão de recolher ficam sempre à vista. */
nav.menu {
  display: flex;
  flex-direction: column;
  gap: 2px;
  flex: 1 1 auto;
  min-height: 0;
  padding: 4px 10px 10px;
  overflow-x: hidden;
  overflow-y: auto;
}

/* Títulos de seção (Monitoramento, Comercial, Cadastro, Sistema): doze itens numa coluna só se lê
   melhor em blocos. Recolhida, o título vira um filete entre os blocos. */
.menu-secao {
  padding: 12px 10px 4px;
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--txt-2);
  white-space: nowrap;
}
.menu-secao:first-child { padding-top: 6px; }

/* Indicador de hover/página atual em AZUL (--acento), nunca vermelho: o vermelho é da identidade
   da marca e um hover vermelho no app inteiro diluiria o vermelho de alarme (decisão confirmada com
   o usuário em 17/09/2026). Na barra de cima o indicador era uma faixa EMBAIXO do item; numa
   coluna ele vira uma faixa à ESQUERDA — o mesmo que o menu do celular já fazia desde 20/09. */
nav.menu a {
  position: relative;
  display: flex;
  align-items: center;
  gap: 11px;
  flex: 0 0 auto;
  height: 36px;
  padding: 0 10px;
  border-radius: 8px;
  color: var(--txt-2);
  text-decoration: none;
  white-space: nowrap;
  font-size: 13.5px;
  font-weight: 500;
}
nav.menu a .ic { width: 18px; height: 18px; }
.menu-rotulo { overflow: hidden; text-overflow: ellipsis; }
nav.menu a:hover { color: var(--txt); background: var(--bg-3); }
nav.menu a:focus-visible { outline: 2px solid var(--acento); outline-offset: -2px; }
nav.menu a.ativo { color: var(--acento); font-weight: 650; background: rgba(47, 126, 230, .14); }
nav.menu a.ativo::before {
  content: '';
  position: absolute;
  left: -10px;
  top: 7px;
  bottom: 7px;
  width: 3px;
  border-radius: 0 3px 3px 0;
  background: var(--acento);
}

/* Botão de recolher: só o símbolo «, quadrado, ao lado do logotipo. O símbolo só GIRA por classe
   (`.recolhido` vira »): nenhum nó é trocado dentro do próprio clique (lição do defeito de 20/09,
   ver `app.js`). */
.lateral-recolhe {
  display: grid;
  place-items: center;
  flex: 0 0 auto;
  width: 30px;
  height: 30px;
  padding: 0;
  background: var(--bg-3);
  border: 1px solid var(--linha);
  border-radius: 7px;
  color: var(--txt-2);
  cursor: pointer;
}
.lateral-recolhe:hover { color: var(--acento); border-color: var(--acento); }
.lateral-recolhe:focus-visible { outline: 2px solid var(--acento); outline-offset: 2px; }
.lateral-recolhe .ic { width: 16px; height: 16px; transition: transform .18s; }
/* No primeiro acesso não há menu: sem itens, recolher não teria o que recolher */
.shell.sem-menu .lateral-recolhe, .shell.sem-menu .menu-alterna { display: none; }

/* ---- recolhida (só fora do celular: no celular a lateral é uma gaveta, sempre larga) */
@media (min-width: 601px) {
  .shell.recolhido { --lateral-w: 64px; }
  .shell.pronto { transition: grid-template-columns .18s ease; }
  .shell.recolhido .marca-logo { display: none; }
  .shell.recolhido .lateral .marca-icone { display: block; } /* só o da lateral: o da barra de cima é do celular */
  .shell.recolhido nav.menu a { justify-content: center; gap: 0; padding: 0; }
  .shell.recolhido .menu-rotulo { display: none; }
  .shell.recolhido .menu-secao { height: 1px; margin: 9px 6px; padding: 0; overflow: hidden; color: transparent; background: var(--linha); }
  .shell.recolhido .menu-secao:first-child { display: none; }
  /* recolhida não há largura para os dois lado a lado: o ícone da marca em cima, o » logo abaixo */
  .shell.recolhido .marca { flex-direction: column; justify-content: center; gap: 10px; padding: 12px 0 6px; }
  .shell.recolhido .lateral-recolhe .ic { transform: rotate(180deg); }
}

/* ---- barra de cima */
header.topo {
  display: flex;
  align-items: center;
  gap: 12px;
  height: 56px;
  min-width: 0;
  padding: 0 16px;
  background: var(--bg-2);
  border-bottom: 1px solid var(--linha);
}

/* Onde estou: "Cadastro › DVRs". Ajuda principalmente com a lateral recolhida, que só mostra ícones. */
.topo-titulo { display: flex; align-items: center; gap: 8px; min-width: 0; font-size: 13px; color: var(--txt-2); white-space: nowrap; }
.topo-titulo .ic { width: 17px; height: 17px; color: var(--acento); }
.topo-titulo .topo-sep { width: 13px; height: 13px; color: var(--txt-2); opacity: .7; }
.topo-titulo strong { overflow: hidden; color: var(--txt); font-weight: 600; text-overflow: ellipsis; }
.topo-icone { display: none; width: 32px; height: 32px; border-radius: 8px; flex: 0 0 auto; }

/* Botão "sanduíche": só no celular, onde abre a lateral como gaveta (ver a media query abaixo). */
.menu-alterna {
  display: none;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  padding: 0;
  background: none;
  border: 1px solid var(--linha);
  border-radius: 8px;
  color: var(--txt);
  cursor: pointer;
  flex: 0 0 auto;
}
.menu-alterna:hover { border-color: var(--acento); color: var(--acento); }
.menu-alterna:focus-visible { outline: 2px solid var(--acento); outline-offset: 2px; }
.menu-alterna .ic { width: 20px; height: 20px; }
/* Os dois ícones ficam sempre no DOM (`app.js`) — só a classe decide qual aparece, igual ao olho de
   mostrar/ocultar senha do login. Nunca `replaceChildren` aqui: trocar o nó que acabou de ser
   clicado no meio do próprio clique foi a causa de um defeito real (ver comentário em `app.js`). */
.menu-alterna .ic-menu-fechar { display: none; }
.menu-alterna.aberto .ic-menu-abrir { display: none; }
.menu-alterna.aberto .ic-menu-fechar { display: block; }

.usuario { position: relative; display: flex; align-items: center; margin-left: auto; min-width: 0; }

/* Celular (≤600px, mesmo corte do resto do app): a lateral fixa comeria um terço da tela. Ela vira
   uma gaveta que entra pela esquerda por cima do conteúdo, aberta pelo sanduíche da barra de cima
   (`montarLateral()` em `app.js`, que também fecha ao navegar, com Esc ou tocando fora). Na gaveta
   ela é sempre larga, mesmo que no computador a pessoa a deixe recolhida.
   A gaveta e o fundo escurecido começam ABAIXO da barra de cima (2 px do filete + 56 px da barra):
   cobrindo a barra, a gaveta tampava o próprio sanduíche, e o "X" de fechar ficava embaixo dela
   (achado pela verificação de 10/10, tocando no X por coordenada). */
@media (max-width: 600px) {
  .shell { grid-template-columns: minmax(0, 1fr); }
  .menu-alterna { display: flex; }
  .topo-icone { display: block; }
  .topo-titulo .topo-secao, .topo-titulo .topo-sep { display: none; }
  .lateral-recolhe { display: none; }

  aside.lateral {
    position: fixed;
    top: 58px;
    bottom: 0;
    left: 0;
    z-index: 70;
    width: 270px;
    max-width: 85vw;
    box-shadow: 12px 0 28px rgba(0, 0, 0, .45);
    transform: translateX(-100%);
    visibility: hidden; /* fechada, a gaveta sai também da ordem do Tab */
    transition: transform .2s ease, visibility 0s linear .2s;
  }
  aside.lateral.aberto { transform: none; visibility: visible; transition: transform .2s ease; }
  /* o fundo escurecido é do próprio shell: tocar nele é tocar "fora" e fecha a gaveta */
  .shell.menu-aberto::after { content: ''; position: fixed; inset: 58px 0 0; z-index: 65; background: rgba(0, 0, 0, .5); }

  nav.menu a { height: 44px; } /* alvo de toque */
}

@media (prefers-reduced-motion: reduce) {
  .shell.pronto, aside.lateral, aside.lateral.aberto, .lateral-recolhe .ic { transition: none; }
}

main { overflow: auto; padding: 16px; }
main.sem-scroll { overflow: hidden; padding: 8px; }

h2 { margin: 0 0 14px; font-size: 17px; font-weight: 600; }
.barra { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; margin-bottom: 12px; }
.espaco { flex: 1; }

/* Dentro da barra os campos são controles, não formulário: largura pelo conteúdo. Sem isto eles
   herdam width:100% e a barra come um terço da tela — que é espaço de vídeo. */
.barra label { display: inline; margin: 0; }
.barra input, .barra select, .barra button { width: auto; padding: 5px 9px; }
.barra select { max-width: 200px; }

/* ------------------------------------------------------------------ grade */

/* Flex em coluna, e não `grid-template-rows: auto 1fr`: com o grid a contagem de linhas tinha que
   bater com a de filhos, e acrescentar uma barra (a de grupo/gravador) jogou o `1fr` na barra
   errada — controles no meio da tela e câmeras espremidas no rodapé. Assim as barras ocupam o que
   precisam e a grade fica com o resto, qualquer que seja o número de barras. */
.grade-tela { display: flex; flex-direction: column; gap: 8px; height: 100%; }
.grade-tela > .grade { flex: 1 1 auto; min-height: 0; }
.grade-tela > .barra { flex: 0 0 auto; }

.grade {
  display: grid;
  gap: 6px;
  height: 100%;
  min-height: 0;
}

.grade.l1 { grid-template-columns: 1fr; }
.grade.l2x2 { grid-template-columns: repeat(2, 1fr); grid-template-rows: repeat(2, 1fr); }
.grade.l3x3 { grid-template-columns: repeat(3, 1fr); grid-template-rows: repeat(3, 1fr); }
.grade.l4x4 { grid-template-columns: repeat(4, 1fr); grid-template-rows: repeat(4, 1fr); }

.grade.l1-5 { grid-template-columns: repeat(3, 1fr); grid-template-rows: repeat(3, 1fr); }
.grade.l1-5 > .tile:first-child { grid-column: span 2; grid-row: span 2; }

.grade.l1-7 { grid-template-columns: repeat(4, 1fr); grid-template-rows: repeat(4, 1fr); }
.grade.l1-7 > .tile:first-child { grid-column: span 3; grid-row: span 3; }

.tile {
  position: relative;
  background: #000;
  border: 1px solid var(--linha);
  border-radius: 6px;
  overflow: hidden;
  min-height: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}

.tile.foco { outline: 2px solid var(--acento); outline-offset: -2px; }

/* A imagem e o que fica por cima dela (ações, mensagem, cortina) moram numa moldura própria
   (25/09/2026). Fora da grade do Ao vivo ela ocupa o tile inteiro e o rótulo continua sobreposto,
   como sempre foi (ficha de Canais); na grade, o rótulo vira cabeçalho fora da imagem. */
.tile-quadro {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}

.tile video, .tile canvas.congelado {
  width: 100%;
  height: 100%;
  object-fit: contain;
  display: block;
  transform-origin: var(--zoom-x, 50%) var(--zoom-y, 50%);
  transform: scale(var(--zoom, 1));
  transition: opacity .18s ease;
}

.tile video.entrando { opacity: 0; }
.tile canvas.congelado { position: absolute; inset: 0; filter: grayscale(.6) brightness(.7); }

/* A faixa de identificação fica no TOPO: o OSD do próprio DVR (nome da câmera e data/hora) é
   desenhado no rodapé da imagem, e sobrepor os dois deixava os dois ilegíveis. */
.tile .rotulo {
  position: absolute;
  top: 6px; left: 6px; right: 6px;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 4px 9px;
  border-radius: 6px;
  font-size: 12px;
  background: rgba(0, 0, 0, .62);
  pointer-events: none;
  z-index: 2;
}
.tile .rotulo .relogio { display: none; }

.tile .rotulo .nome { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tile .rotulo .fluxo { color: var(--txt-2); font-size: 11px; white-space: nowrap; }
.tile .rotulo .estado-txt { color: var(--txt-2); font-size: 11px; white-space: nowrap; }

.ponto { width: 7px; height: 7px; border-radius: 50%; background: var(--txt-2); }
.ponto.ok { background: var(--ok); }
.ponto.conectando { background: var(--alerta); animation: pulsa 1s infinite; }
.ponto.instavel { background: var(--alerta); }
.ponto.offline { background: var(--erro); }

@keyframes pulsa { 50% { opacity: .25; } }

.tile .acoes {
  position: absolute;
  top: 6px; right: 6px;
  display: none;
  gap: 4px;
}

.tile:hover .acoes, .tile:focus-within .acoes { display: flex; }

.tile .acoes button {
  width: 26px; height: 26px;
  border: 0;
  border-radius: 5px;
  background: rgba(0, 0, 0, .65);
  color: var(--txt);
  cursor: pointer;
  font-size: 13px;
  line-height: 1;
  display: grid;
  place-items: center;
  padding: 0;
}
.tile .acoes button .ic { width: 15px; height: 15px; }

.tile .acoes button:hover { background: var(--acento); color: var(--sobre-acento); }

.tile .vazio { color: var(--txt-2); font-size: 13px; }

.tile .mensagem {
  position: absolute;
  inset: auto 8px 28px 8px;
  padding: 6px 8px;
  border-radius: 6px;
  background: rgba(0, 0, 0, .75);
  font-size: 12px;
  text-align: center;
}

/* Cortina: enquanto ela está aí, o tile NÃO fala com o gravador — nenhuma conexão, nenhum byte
   de upload do cliente. Clicar é o pedido explícito de ver ao vivo. */
.tile .cortina {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
  align-items: center;
  justify-content: center;
  border: 0;
  background: var(--bg-2);
  color: var(--txt-2);
  cursor: pointer;
  font: inherit;
}

.tile .cortina:hover { background: var(--bg-3); color: var(--txt); }
.tile .cortina .play { font-size: 26px; line-height: 1; color: var(--acento); }
.tile .cortina .legenda { font-size: 12px; }
.tile .cortina[hidden] { display: none; }

.barra .sep {
  width: 1px;
  align-self: stretch;
  margin: 0 4px;
  background: var(--linha);
}

.btn.secundario.ativo { background: var(--acento); color: var(--sobre-acento); }

/* ------------------------------------------------------------------ tabelas e formulários */

table { width: 100%; border-collapse: collapse; font-size: 13px; }
th, td { padding: 8px 10px; text-align: left; border-bottom: 1px solid var(--linha); }
th { color: var(--txt-2); font-weight: 600; }
tbody tr:hover { background: var(--bg-2); }
td.acoes-col { text-align: right; white-space: nowrap; }

.painel {
  background: var(--bg-2);
  border: 1px solid var(--linha);
  border-radius: var(--raio);
  padding: 16px;
  margin-bottom: 16px;
}

.painel h3 { margin: 0 0 12px; font-size: 15px; }
.grade-form { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 0 14px; }
.linha-botoes { display: flex; gap: 8px; margin-top: 16px; flex-wrap: wrap; }

.tag {
  display: inline-block;
  padding: 2px 8px;
  border-radius: 999px;
  font-size: 11px;
  background: var(--bg-3);
  color: var(--txt-2);
}

.tag.ok { background: rgba(63, 185, 80, .18); color: var(--ok); }
.tag.alerta { background: rgba(210, 153, 34, .18); color: var(--alerta); }
.tag.erro { background: rgba(240, 93, 93, .18); color: var(--erro); }

.cartoes { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 12px; }

.cartao {
  background: var(--bg-2);
  border: 1px solid var(--linha);
  border-radius: var(--raio);
  padding: 14px;
  transition: transform .15s ease, border-color .15s ease, background-color .15s ease;
}
.cartao:hover { transform: translateY(-2px); border-color: var(--acento); background: var(--bg-3); }

.cartao .rot { color: var(--txt-2); font-size: 12px; }
.cartao .val { font-size: 22px; font-weight: 600; margin-top: 4px; }

/* Central de eventos dos DVRs (F-SAUDE, 19/09/2026): um cartão por gravador, borda de acento por
   estado — vermelha só quando o dispositivo está de fato fora do ar, nunca por alerta em aberto
   (senão qualquer câmera mascarada pintaria o cartão inteiro de erro, e o "offline" real, que é o
   que precisa saltar aos olhos, se perderia no meio). */
.cartoes-dvr { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 12px; margin-bottom: 16px; }
.cartao-dvr {
  background: var(--bg-2);
  border: 1px solid var(--linha);
  border-left: 3px solid var(--ok);
  border-radius: var(--raio-grande);
  padding: 13px 15px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  text-align: left;
  cursor: pointer;
  font: inherit;
  color: inherit;
  transition: transform .15s ease, background-color .15s ease, border-color .15s ease;
}
/* leve "levante" ao passar o mouse — pedido do usuário, mesmo efeito da referência (.dvr:hover) */
.cartao-dvr:hover { border-color: var(--acento); background: var(--bg-3); transform: translateY(-2px); }
.cartao-dvr.offline:hover { border-color: var(--erro); }
.cartao-dvr.ativo { box-shadow: 0 0 0 1px var(--acento); border-color: var(--acento); }
.cartao-dvr.offline { border-left-color: var(--erro); }
.cartao-dvr-topo { display: flex; justify-content: space-between; align-items: center; gap: 8px; }
.cartao-dvr-chips { display: flex; flex-wrap: wrap; gap: 10px; padding-top: 7px; border-top: 1px solid var(--linha); }
.cartao-dvr-chip { display: flex; align-items: flex-start; gap: 5px; font-size: 11px; color: var(--txt-2); line-height: 1.4; }
.cartao-dvr-chip .pt { margin-top: 4px; }

.selecao { max-height: 340px; overflow: auto; border: 1px solid var(--linha); border-radius: 6px; }
.selecao label { display: flex; gap: 8px; align-items: center; margin: 0; padding: 7px 10px; cursor: pointer; }
.selecao label:hover { background: var(--bg-3); }
.selecao input[type="checkbox"] { width: auto; }
.selecao .linha-item { display: flex; gap: 9px; align-items: center; padding: 8px 10px; border-bottom: 1px solid var(--linha); font-size: 12.5px; }
.selecao .linha-item:last-child { border-bottom: none; }
.selecao .linha-item .ic { width: 15px; height: 15px; color: var(--txt-2); flex-shrink: 0; }
.grupo-dvrs { margin-top: 6px; }

.dica { color: var(--txt-2); font-size: 12px; margin-top: 6px; }
.mono { font-family: Consolas, "Courier New", monospace; font-size: 12px; }
.centro { text-align: center; color: var(--txt-2); padding: 30px; }

/* ------------------------------------------------------------------ agenda de gravação */

.linha-titulo { display: flex; align-items: center; gap: 8px; margin-bottom: 10px; }
.linha-titulo h3 { margin: 0; }
.resumo-grupo { display: flex; align-items: center; gap: 5px; flex-wrap: wrap; margin-bottom: 12px; }
.cartoes-grupo { display: grid; grid-template-columns: repeat(auto-fit, minmax(420px, 1fr)); gap: 14px; }

/* grade editável: 1 coluna de rótulo + 24 horas */
.matriz, .mini-matriz {
  display: grid;
  grid-template-columns: 42px repeat(24, 1fr);
  gap: 2px;
  margin: 12px 0;
  user-select: none;
  touch-action: none;
}

.matriz .dia, .mini-matriz .mini-dia {
  font-size: 11px;
  color: var(--txt-2);
  display: flex;
  align-items: center;
}

.matriz .hora { font-size: 10px; color: var(--txt-2); text-align: left; }

.matriz .cel {
  height: 22px;
  border-radius: 3px;
  cursor: crosshair;
  background: var(--bg-3);
}

.matriz .cel:hover { outline: 1px solid var(--acento); }
.mini-matriz .mini-cel { height: 11px; border-radius: 2px; background: var(--bg-3); }

.m-off { background: var(--bg-3) !important; }
.m-cont { background: var(--acento) !important; }
.m-mov { background: var(--alerta) !important; }

.pincel { display: flex; align-items: center; gap: 7px; flex-wrap: wrap; margin: 10px 0; }

.btn-modo {
  padding: 5px 12px;
  border: 1px solid var(--linha);
  border-radius: 999px;
  color: var(--txt);
  cursor: pointer;
  font-size: 12px;
  opacity: .55;
}

.btn-modo.ativo { opacity: 1; border-color: var(--txt); font-weight: 600; }
.btn-modo.m-cont, .btn-modo.m-mov { color: var(--sobre-acento); }

.legenda-modos { display: flex; gap: 16px; flex-wrap: wrap; font-size: 12px; color: var(--txt-2); }
.item-legenda { display: flex; align-items: center; gap: 6px; }
.item-legenda .mini-cel { width: 16px; display: inline-block; }

/* ------------------------------------------------------------------ primeiro acesso */

.assistente {
  max-width: 720px;
  margin: 24px auto;
  background: var(--bg-2);
  border: 1px solid var(--linha);
  border-radius: var(--raio);
  padding: 28px 32px 32px;
}

.assistente h2 { margin: 0 0 6px; font-size: 19px; }

.passos {
  display: flex;
  gap: 8px;
  list-style: none;
  margin: 0 0 24px;
  padding: 0;
  font-size: 12px;
  counter-reset: passo;
}

.passos li {
  flex: 1;
  padding: 8px 10px 8px 32px;
  position: relative;
  border-radius: 6px;
  background: var(--bg-3);
  color: var(--txt-2);
  counter-increment: passo;
}

.passos li::before {
  content: counter(passo);
  position: absolute;
  left: 9px; top: 50%;
  transform: translateY(-50%);
  width: 17px; height: 17px;
  border-radius: 50%;
  background: var(--linha);
  color: var(--txt-2);
  display: grid;
  place-items: center;
  font-size: 11px;
  font-weight: 600;
}

.passos li.atual { background: rgba(47, 126, 230, .16); color: var(--txt); }
.passos li.atual::before { background: var(--acento); color: var(--sobre-acento); }
.passos li.feito { color: var(--ok); }
.passos li.feito::before { content: "✓"; background: rgba(63, 185, 80, .25); color: var(--ok); }

.qr-linha { display: flex; gap: 28px; align-items: flex-start; flex-wrap: wrap; margin-top: 18px; }
.qr-linha > div { flex: 1; min-width: 260px; }

.qr {
  width: 208px; height: 208px;
  background: #fff;
  border-radius: 8px;
  padding: 10px;
  flex: none;
}

.chave {
  font-size: 15px;
  letter-spacing: 1px;
  background: var(--bg);
  border: 1px solid var(--linha);
  border-radius: 6px;
  padding: 9px 11px;
  margin: 6px 0 14px;
  user-select: all;
}

.codigos {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
  gap: 8px;
  margin: 16px 0;
}

.codigos span {
  background: var(--bg);
  border: 1px solid var(--linha);
  border-radius: 6px;
  padding: 9px;
  text-align: center;
  font-size: 14px;
  letter-spacing: 1px;
  user-select: all;
}

.confirma { display: flex; align-items: center; gap: 9px; margin: 18px 0 0; cursor: pointer; }
.confirma input { width: auto; }

/* ------------------------------------------------------------------ gravações (Fase 3 / F3.2) */

/* F3.2: três colunas — árvore de câmeras fixa | vídeo+timeline | ferramentas. Mesmo padrão
   responsivo de Canais (colapsa para 1 coluna ≤980px, ver media query no fim do arquivo). */
.grav-tela {
  display: grid;
  grid-template-columns: 240px 1fr 260px;
  gap: 12px;
  height: 100%;
  min-height: 0;
}

.grav-sidebar-esq, .grav-sidebar-dir { min-height: 0; overflow-y: auto; }
.grav-sidebar-dir { display: flex; flex-direction: column; gap: 12px; }
.grav-central { display: grid; grid-template-rows: auto 1fr auto auto; gap: 8px; min-height: 0; min-width: 0; }

.painel-lateral {
  background: var(--bg-2);
  border: 1px solid var(--linha);
  border-radius: var(--raio);
  padding: 10px 12px;
}
.painel-lateral h4 { margin: 0 0 8px; font-size: 12.5px; color: var(--txt-2); text-transform: uppercase; letter-spacing: .03em; }
.grav-sidebar-esq.painel-lateral { height: 100%; display: flex; flex-direction: column; }
.grav-sidebar-esq .arvore-canais { flex: 1; min-height: 0; }

.player-video {
  position: relative; /* ancora a camada de carregamento */
  background: #000;
  border: 1px solid var(--linha);
  border-radius: var(--raio);
  min-height: 0;
  display: flex;
}

/* Camada de carregamento (F3.2.1): com a gravacao 100% na nuvem, cada troca de trecho tem uma
   espera real (medido: 3,2 s so para o primeiro byte do B2). Sem este aviso o quadro parado nao se
   distingue de um travamento — foi exatamente o que o operador relatou. */
.player-carregando {
  position: absolute;
  inset: auto 0 0 0;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 8px 10px;
  background: rgba(0, 0, 0, .72);
  color: var(--txt);
  font-size: 13px;
}

/* `display:flex` acima venceria o `[hidden]` nativo — mesmo cuidado que `.tile .cortina[hidden]`. */
.player-carregando[hidden] { display: none; }

.player-carregando .crono { color: var(--txt-2); font-variant-numeric: tabular-nums; }

.player-carregando .girando {
  width: 14px;
  height: 14px;
  border: 2px solid rgba(255, 255, 255, .25);
  border-top-color: var(--acento);
  border-radius: 50%;
  animation: girar 1s linear infinite;
}

@keyframes girar { to { transform: rotate(360deg); } }

/* Quem configurou o sistema para reduzir animacao nao deve ganhar um disco girando na tela. */
@media (prefers-reduced-motion: reduce) {
  .player-carregando .girando { animation: none; border-top-color: rgba(255, 255, 255, .25); }
}

/* Dois <video> convivem aqui (F3.3): o que toca e o que esquenta o próximo trecho em segundo
   plano. `position:absolute` empilha os dois no mesmo lugar (em vez do lado a lado que o
   `display:flex` do pai daria).
   ⛔ DEFEITO CORRIGIDO (F3.4b, 13/09/2026): o `.oculto` nascia com `display:none` — o comentário
   antigo aqui dizia "esconder não pausa o buffering", e é falso num navegador de verdade (só não
   apareceu na verificação automatizada porque ela rodava em Chrome/Edge HEADLESS, que não aplica
   a mesma heurística). Com `display:none` o elemento sai do render tree por completo; o Chrome
   real trata isso como "fora da tela" e SUSPENDE o download depois da metadata para economizar
   dado — o oculto nunca passava de HAVE_METADATA, e a troca caía sempre no caminho de "aguardando
   dados" mesmo com o link livre (o usuário testou com a VPN desligada e banda cheia: mesmo
   comportamento — a banda nunca foi o problema). A correção é opacidade zero, não `display:none`:
   o elemento continua ocupando espaço e sendo "visível" para essa heurística, só não aparece nem
   recebe clique. */
/* ⚠️ Revertido no mesmo dia (20/09/2026): tentamos `object-fit: cover` para acabar com a faixa
   preta lateral, mas `cover` corta o que sobra da dimensão OPOSTA quando a proporção não bate —
   nesta câmera, cortou exatamente o carimbo de data/hora (topo) e o nome da câmera (rodapé), que
   o DVR grava DENTRO do próprio quadro de vídeo. Num sistema de vigilância esse carimbo é prova,
   não decoração — perdê-lo pra ganhar um painel sem borda preta é a troca errada. Volta a
   `contain`: a imagem NUNCA é cortada, só encolhe com uma faixa preta fina quando a proporção não
   bate exatamente com a do painel. */
.player-video video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; }
.player-video video.oculto { opacity: 0; pointer-events: none; z-index: 0; }
.player-video video.ativo { z-index: 1; }

.player-video .vazio {
  margin: auto;
  color: var(--txt-2);
  font-size: 13px;
}

.linha-timeline { display: flex; align-items: center; gap: 10px; }
.rotulo-dia { min-width: 110px; color: var(--txt); font-size: 13px; text-align: center; }

/* o nome do canal (gravador + numero + nome) nao cabe no limite geral da barra */
.barra select#gravacoes_canal { max-width: 340px; }

/* Quem rola é este container; `.timeline` cresce por dentro dele conforme o zoom (largura em %,
   sempre relativa ao próprio `.timeline`, então a posição de cada segmento continua correta em
   qualquer nível — só a régua de pixels por baixo fica mais generosa). */
.timeline-scroll {
  flex: 1;
  min-width: 0; /* sem isto o flex item nao encolhe e a tela ganha rolagem horizontal geral */
  overflow-x: auto;
  overflow-y: hidden;
  border-radius: 6px;
}

.zoom-controles { display: flex; align-items: center; gap: 4px; }
.zoom-label { min-width: 34px; text-align: center; font-variant-numeric: tabular-nums; }

.timeline {
  position: relative;
  width: 100%;
  height: 46px;
  background: var(--bg-2);
  border: 1px solid var(--linha);
  border-radius: 6px;
  cursor: pointer;
  overflow: hidden;
}

.timeline .seg {
  position: absolute;
  top: 6px;
  bottom: 6px;
  border-radius: 2px;
  min-width: 2px;
}

.timeline .seg.continuous { background: var(--acento); }
/* 'motion' aqui é o TIPO (função `tipoDe()` no JS) — cobre o trigger real do anel (`ring`) e os
   vestigiais `motion`/`manual`, nunca o valor literal do banco sozinho. */
.timeline .seg.motion { background: var(--alerta); }
/* Anel rodando sem proteção de evento por perto (F3.2.11, 20/09/2026) — mesmo trigger de
   movimento, mas SEM um evento real confirmado nesse trecho: é só o buffer local, seria purgado em
   `ring_hours` se ninguém tivesse mexido perto. Tom mais fraco (mesma opacidade da margem de
   pré/pós-roll) pra bater visualmente com a faixa fina de eventos, que só marca onde há movimento
   de verdade — antes as duas cores eram idênticas e pareciam duas fontes discordando. */
.timeline .seg.motion-fraco { background: rgba(210, 153, 34, .35); }

/* Faixa própria, sobre os segmentos: o segmento é o arquivo que existe, o evento é o instante
   que interessa. Sobrepostos, respondem "gravou o dia todo, mexeu só nestes momentos". */
.timeline .mov {
  position: absolute;
  top: 0;
  height: 5px;
  min-width: 2px;
  border-radius: 0 0 2px 2px;
  background: var(--alerta);
  cursor: pointer;
}
.timeline .mov:hover { height: 8px; }
/* Margem de pré/pós-roll (F3.2.3, 20/09/2026): mesma cor do evento, bem mais translúcida — marca
   visualmente até onde a proteção contra purga vai de verdade (`db/repo/motion.py::janela_do_evento`),
   sem se confundir com o instante denso em que o DVR de fato viu movimento. */
.timeline .mov.mov-margem { height: 4px; background: rgba(210, 153, 34, .35); }
.timeline .mov.mov-margem:hover { height: 7px; }
/* Só sobra listra tracejada aqui — o caso que É um problema de verdade: sem arquivo local E sem
   cópia no B2, perda real. "Local-só-até-caber-a-subida" (F2.6c/F2.6d) deixou de ter visual
   próprio (18/09/2026): vira 'continuous'/'motion' normal, porque o operador precisa ver o TIPO
   contratado, não onde o byte mora agora. */
.timeline .seg.missing { background: repeating-linear-gradient(45deg, var(--erro), var(--erro) 3px, transparent 3px, transparent 6px); opacity: .5; }
.timeline .seg.writing { background: var(--ok); }

.timeline .agora {
  position: absolute;
  top: 0; bottom: 0;
  width: 2px;
  background: #fff;
  pointer-events: none;
}

.timeline .marcas {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

.timeline .marcas span {
  position: absolute;
  top: 2px;
  color: var(--txt-2);
  font-size: 10px;
}

.rotulo-canal { color: var(--txt); font-size: 13px; font-weight: 600; }

/* barra de transporte própria (F3.2): troca os controles nativos do <video>, que não expõem
   velocidade de forma consistente entre navegadores. Sem controle de volume — o áudio já vem
   desligado por política (-an / audio_enabled=0). */
.transporte { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.transporte .velocidades { display: flex; gap: 3px; }

/* balão de hover da linha do tempo (F3.2): só texto (horário + eventos próximos) — uma miniatura de
   verdade exigiria um recurso novo de backend (sprite-sheet) e, para trechos só-na-nuvem, egress a
   cada passada do mouse. Posição fixa no viewport, ao lado do cursor. */
.hover-dica {
  position: fixed;
  z-index: 40;
  background: var(--bg-2);
  border: 1px solid var(--linha);
  border-radius: 6px;
  padding: 4px 8px;
  font-size: 12px;
  color: var(--txt);
  pointer-events: none;
  white-space: nowrap;
  box-shadow: 0 6px 16px rgba(0, 0, 0, .3);
}

/* faixa de seleção do "Recortar clipe" (F3.2) — mesma régua percentual dos segmentos */
.timeline .faixa-recorte {
  position: absolute;
  top: 0;
  bottom: 0;
  background: rgba(255, 255, 255, .18);
  border-left: 2px solid #fff;
  border-right: 2px solid #fff;
  pointer-events: none;
}

.filtro-tipo { display: flex; flex-direction: column; gap: 4px; }
.filtro-tipo label { display: flex; align-items: center; gap: 8px; font-size: 13px; cursor: pointer; }
.filtro-tipo input { width: auto; }

.legenda-cores { display: flex; flex-wrap: wrap; align-items: center; gap: 4px; margin-top: 10px; }
.legenda-cores .amostra { display: inline-block; width: 12px; height: 8px; border-radius: 2px; }
.legenda-cores .amostra.continuous { background: var(--acento); }
.legenda-cores .amostra.motion { background: var(--alerta); }
.legenda-cores .amostra.motion-fraco { background: rgba(210, 153, 34, .35); }
.legenda-cores .amostra.mov-margem { background: rgba(210, 153, 34, .35); border: 1px solid rgba(210, 153, 34, .5); }

/* Filtro por tipo (F3.2): esconde por `data-filtro`, gravado em cada `.seg` ao desenhar o dia. */
.timeline[data-oculta~="continuous"] .seg[data-filtro="continuous"] { display: none; }
.timeline[data-oculta~="motion"] .seg[data-filtro="motion"] { display: none; }

.campo-hora { margin-top: 10px; }
.campo-hora label { display: block; font-size: 12px; color: var(--txt-2); margin-bottom: 4px; }
.campo-hora-linha { display: flex; gap: 6px; align-items: center; }
.campo-hora-linha input[type="time"] { flex: 1; min-width: 0; }
.campo-hora-linha .btn { flex: 0 0 auto; padding: 6px 8px; }
.campo-hora-linha .btn .ic { display: block; }

/* Relógio de ponteiros (F3.2.7, 20/09/2026) — diálogo de "Ir para o instante" com o mesmo espírito
   visual do seletor nativo do Android/iOS em pt-BR: 24h, 2 coroas (1-12 por fora, 13-23/00 por
   dentro). Construído em SVG puro (sem lib — a CSP não abre exceção nem se quiséssemos). */
.dlg-relogio { width: min(320px, 92vw); text-align: center; }
.rel-digital { display: flex; justify-content: center; align-items: baseline; gap: 4px;
  font-size: 28px; font-variant-numeric: tabular-nums; margin: 4px 0 10px; }
.rel-digital > span { color: var(--txt-2); }
.rel-digito {
  background: none; border: none; color: var(--txt-2); font: inherit; cursor: pointer;
  padding: 2px 6px; border-radius: var(--raio);
}
.rel-digito.ativo { color: var(--txt); background: var(--acento); }
.rel-svg { width: 100%; max-width: 260px; height: auto; touch-action: none; cursor: pointer; }
.rel-mostrador { fill: var(--bg); stroke: var(--linha); }
.rel-ponteiro { stroke: var(--acento); stroke-width: 2; }
.rel-ponta { fill: var(--acento); }
.rel-centro { fill: var(--acento); }
.rel-sel { fill: var(--acento); }
.rel-txt { fill: var(--txt); font-size: 15px; pointer-events: none; user-select: none; }
.rel-txt.int { fill: var(--txt-2); font-size: 13px; }
.rel-txt.sel { fill: var(--sobre-acento); }

.ferramentas-botoes { display: flex; flex-direction: column; gap: 6px; }
.ferramentas-botoes .btn { width: 100%; }

.lista-exports { display: flex; flex-direction: column; gap: 6px; margin-top: 8px; }
.export-linha { display: flex; flex-direction: column; gap: 3px; font-size: 12px; padding: 6px 8px; background: var(--bg); border: 1px solid var(--linha); border-radius: 6px; }
.export-linha .periodo { color: var(--txt-2); }
.export-linha .tag { align-self: flex-start; padding: 1px 7px; border-radius: 4px; font-size: 11px; background: var(--bg-3); }
.export-linha .tag.done { background: rgba(63, 178, 127, .18); color: #7bd6a8; }
.export-linha .tag.failed, .export-linha .tag.expired { background: rgba(221, 91, 79, .15); color: #f0a29a; }
.export-linha .tag.running { background: rgba(47, 126, 230, .18); color: var(--acento); }
.export-linha a { color: var(--acento); font-size: 12px; }

/* Barra de progresso da exportacao (F3.2.2): exportar um dia inteiro sao centenas de idas ao B2 e
   pode levar horas — "processando..." imovel esse tempo todo le como travado. */
.progresso-exp {
  position: relative;
  display: block;
  height: 16px;
  border-radius: 4px;
  background: var(--bg-3);
  overflow: hidden;
}

.progresso-exp .barra {
  position: absolute;
  inset: 0 auto 0 0;
  background: rgba(47, 126, 230, .35);
  transition: width .4s linear;
}

.progresso-exp .rotulo {
  position: relative;
  display: block;
  text-align: center;
  font-size: 11px;
  line-height: 16px;
  color: var(--txt);
}

/* O download do arquivo pronto e o desfecho de tudo: merece peso de botao, nao de link solto. */
.baixar-export {
  align-self: flex-start;
  padding: 3px 9px;
  border: 1px solid var(--acento);
  border-radius: 5px;
  text-decoration: none;
}

/* ---------------- árvore de câmeras / calendário — agora persistentes, não num modal ---------------- */

.arvore-canais.lista-canais { max-height: none; height: 100%; overflow-y: auto; }
.grav-sidebar-dir .calendario { min-height: 0; }

/* ---------------- exclusão de gravação (modal) ---------------- */

dialog.dlg-largo { max-width: 780px; }

.seletor { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; margin-top: 8px; }
.seletor > div { min-width: 0; }

.lista-canais { max-height: 320px; }

/* O gravador é uma gaveta: com muitos DVRs, a lista aberta vira uma parede de câmeras. */
.grupo-dvr {
  display: flex;
  gap: 8px;
  align-items: center;
  width: 100%;
  padding: 9px 10px;
  background: none;
  border: 0;
  border-top: 1px solid var(--linha);
  color: var(--txt);
  cursor: pointer;
  text-align: left;
  font-size: 13px;
}
.grupo-dvr:first-child { border-top: 0; }
.grupo-dvr:hover { background: var(--bg-3); }
.grupo-dvr.aberto { background: var(--bg-3); }
.grupo-dvr .seta { color: var(--txt-2); font-size: 10px; min-width: 10px; }
.grupo-dvr .nome { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.grupo-dvr .conta { margin: 0; margin-left: auto; white-space: nowrap; }
.grupo-dvr.tem-escolha:not(.aberto) .conta { color: var(--acento); }
.grupo-dvr + .item-canal { margin-top: 2px; }
.lista-canais .item-canal { padding-left: 28px; }

.item-canal {
  display: flex;
  gap: 9px;
  align-items: center;
  width: 100%;
  padding: 8px 10px;
  background: none;
  border: 0;
  border-radius: 6px;
  color: var(--txt);
  cursor: pointer;
  text-align: left;
}

.item-canal:hover { background: var(--bg-3); }
.item-canal.ativo { background: rgba(47, 126, 230, .18); }
.item-canal .num { color: var(--txt-2); font-size: 11px; min-width: 34px; }
.item-canal .nome { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.calendario {
  background: var(--bg);
  border: 1px solid var(--linha);
  border-radius: 6px;
  padding: 12px;
  min-height: 320px;
}

.cal-topo { display: flex; align-items: center; justify-content: space-between; margin-bottom: 10px; }
.cal-topo strong { font-size: 14px; }

.cal-grade { display: grid; grid-template-columns: repeat(7, 1fr); gap: 4px; }
.cal-cab { text-align: center; color: var(--txt-2); font-size: 11px; padding-bottom: 4px; }

.cal-dia {
  aspect-ratio: 1;
  border: 1px solid transparent;
  border-radius: 6px;
  background: var(--bg-3);
  color: var(--txt-2);
  font-size: 12px;
  cursor: pointer;
  padding: 0;
}

.cal-dia:disabled { opacity: .35; cursor: default; }
.cal-dia.tem { background: rgba(47, 126, 230, .22); color: var(--txt); font-weight: 600; }
.cal-dia.tem:hover { background: rgba(47, 126, 230, .38); }
.cal-dia.sel { border-color: var(--acento); }

.legenda { display: flex; align-items: center; gap: 7px; margin-top: 12px; }
.cal-dia.amostra { width: 15px; height: 15px; aspect-ratio: auto; flex: none; }

dialog {
  background: var(--bg-2);
  color: var(--txt);
  border: 1px solid var(--linha);
  border-radius: var(--raio);
  padding: 20px;
  max-width: 460px;
  width: 92%;
}

dialog::backdrop { background: rgba(0, 0, 0, .6); }

/* --- foto de perfil e sub-paineis (Configuracoes / Planos) ------------------------------- */

.avatar {
  width: 26px;
  height: 26px;
  border-radius: 50%;
  object-fit: cover;
  border: 1px solid var(--linha);
  vertical-align: middle;
  margin-right: 6px;
}

.avatar-grande {
  width: 96px;
  height: 96px;
  border-radius: 50%;
  object-fit: cover;
  border: 1px solid var(--linha);
  background: var(--bg-1);
}

/* Configurações › Identidade visual: preview do logo/favicon enviados. Fundo claro fixo — o
   logotipo pode ter traço escuro (o padrão da marca tem traço azul sobre transparência) e
   sumiria contra o tema escuro do app; um retângulo claro mostra a arte do jeito que ela vai
   aparecer numa aba/janela de SO, que também costuma ser clara. */
.marca-preview {
  max-width: 160px;
  max-height: 70px;
  object-fit: contain;
  background: #fff;
  border: 1px solid var(--linha);
  border-radius: 6px;
  padding: 6px;
}
.marca-preview.pequeno { max-width: 48px; max-height: 48px; }
.marca-campo { align-items: center; }

/* O grupo de gravacao dentro do bloco do cliente: recuado para a hierarquia
   "cliente -> grupo de gravacao -> cameras" ficar visivel sem legenda. */
.sub-painel {
  border-left: 3px solid var(--linha);
  padding: 10px 0 10px 14px;
  margin: 14px 0;
}

.sub-painel .barra { margin-bottom: 8px; }

details.sub-painel > summary {
  cursor: pointer;
  font-weight: 600;
  user-select: none;
}

details.sub-painel > summary:focus-visible { outline: 2px solid var(--acento); }

details.sub-painel[open] > summary { margin-bottom: 10px; }

.esmaecido { opacity: .55; }

/* ------------------------------------------------------------------ Canais (lista + ficha) */

.canais-filtros .chip {
  padding: 5px 12px;
  border-radius: 999px;
  border: 1px solid var(--linha);
  background: var(--bg-2);
  color: var(--txt-2);
  font-size: 13px;
  cursor: pointer;
}
.canais-filtros .chip:hover { color: var(--txt); border-color: var(--txt-2); }
.canais-filtros .chip[aria-pressed="true"] {
  background: var(--acento);
  border-color: var(--acento);
  color: var(--sobre-acento);
  font-weight: 500;
}

.canais-corpo {
  display: grid;
  grid-template-columns: 340px 1fr;
  gap: 14px;
  align-items: start;
}

/* --- lista --- */
.canais-lista {
  background: var(--bg-2);
  border: 1px solid var(--linha);
  border-radius: var(--raio);
  overflow: hidden;
}
.canais-contagem { margin: 0; padding: 12px 14px 8px; }
.canais-vazio { padding: 22px 16px; color: var(--txt-2); font-size: 13px; line-height: 1.5; }

.dvr-cont { border-top: 1px solid var(--linha); }
.dvr-cont:first-of-type { border-top: 0; }
.dvr-cont > summary {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 11px 14px;
  cursor: pointer;
  list-style: none;
  user-select: none;
}
.dvr-cont > summary::-webkit-details-marker { display: none; }
.dvr-cont > summary:hover { background: var(--bg-3); }
.dvr-cont > summary:focus-visible { outline: 2px solid var(--acento); outline-offset: -2px; }
.dvr-nome { font-size: 14px; font-weight: 600; letter-spacing: -.01em; }
.dvr-meta {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 12px;
  color: var(--txt-2);
  flex-wrap: wrap;
}
.dvr-pontos { display: inline-flex; gap: 3px; }
.dvr-noar { color: var(--ok); }
.dvr-alerta { color: var(--erro); }
.dvr-caret {
  margin-left: auto;
  color: var(--txt-2);
  transition: transform .15s;
}
.dvr-cont[open] > summary .dvr-caret { transform: rotate(180deg); }

.dvr-canais { padding: 2px 0 6px; background: var(--bg); }
.canal-item {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  text-align: left;
  padding: 8px 14px 8px 11px;
  background: none;
  border: 0;
  border-left: 3px solid transparent;
  cursor: pointer;
  color: var(--txt);
}
.canal-item:hover { background: var(--bg-2); }
.canal-item[aria-selected="true"] {
  background: var(--bg-3);
  border-left-color: var(--acento);
}
.canal-txt { min-width: 0; flex: 1; }
.canal-nm {
  display: block;
  font-size: 13.5px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.canal-sb { display: block; font-size: 11.5px; color: var(--txt-2); margin-top: 1px; }
.canal-qd { font-size: 11.5px; color: var(--txt-2); white-space: nowrap; }

.pt {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  flex: 0 0 auto;
  display: block;
  background: var(--txt-2);
}
.pt.ok { background: var(--ok); }
.pt.erro { background: var(--erro); }
.pt.idle { background: #48515f; }
.pt.off { background: #333b46; }

/* --- ficha --- */
.canais-ficha {
  background: var(--bg-2);
  border: 1px solid var(--linha);
  border-radius: var(--raio);
  overflow: hidden;
  min-height: 300px;
}
.ficha-vazia {
  padding: 60px 24px;
  text-align: center;
  color: var(--txt-2);
  font-size: 13px;
}
.ficha-topo {
  display: flex;
  align-items: flex-start;
  gap: 16px;
  padding: 18px 20px;
  border-bottom: 1px solid var(--linha);
  flex-wrap: wrap;
}
.ficha-nome { margin: 0; font-size: 19px; font-weight: 600; letter-spacing: -.015em; }
.ficha-onde { margin: 4px 0 0; font-size: 12.5px; color: var(--txt-2); }
.ficha-acoes { margin-left: auto; display: flex; gap: 8px; flex-wrap: wrap; }

/* tempo real */
.ficha-vivo { padding: 16px 20px; border-bottom: 1px solid var(--linha); }
.vivo-cabeca {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 12px;
  flex-wrap: wrap;
}
.vivo-selo {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-size: 13px;
  font-weight: 500;
}
.vivo-selo i {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--txt-2);
  display: block;
}
.vivo-selo.ok i { background: var(--ok); box-shadow: 0 0 0 3px rgba(63, 185, 80, .18); }
.vivo-selo.erro { color: var(--erro); }
.vivo-selo.erro i { background: var(--erro); box-shadow: 0 0 0 3px rgba(240, 93, 93, .18); }
.vivo-cartoes {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(130px, 1fr));
  gap: 1px;
  background: var(--linha);
  border: 1px solid var(--linha);
  border-radius: 6px;
  overflow: hidden;
}
.vivo-cartao { background: var(--bg-2); padding: 10px 12px; }
.vivo-cartao .rot { display: block; font-size: 11.5px; color: var(--txt-2); }
.vivo-cartao .val { display: block; font-size: 16px; font-weight: 600; margin-top: 3px; }
.vivo-cartao .val.erro { color: var(--erro); }

/* faixa 24h */
.ficha-faixa { padding: 16px 20px; border-bottom: 1px solid var(--linha); }
.faixa-cabeca { display: flex; align-items: baseline; gap: 10px; }
.faixa-cabeca b { font-size: 13.5px; }
.faixa-pct { font-size: 12px; color: var(--txt-2); }
.faixa-pct.alerta { color: var(--alerta); }
.faixa-trilho { display: flex; align-items: center; gap: 10px; margin-top: 8px; }
.faixa-rot { width: 68px; flex: 0 0 auto; font-size: 11.5px; color: var(--txt-2); }
.faixa-barra { flex: 1; display: flex; gap: 1px; height: 18px; }
.faixa-barra.fina { height: 6px; }
.faixa-barra i { flex: 1; border-radius: 1px; background: var(--linha); }
.faixa-barra i.rec { background: var(--ok); }
.faixa-barra.fina i { background: transparent; }
.faixa-barra.fina i.mov { background: var(--acento); }
.faixa-eixo {
  display: flex;
  justify-content: space-between;
  margin: 5px 0 0 78px;
  font-size: 10.5px;
  color: var(--txt-2);
}
.faixa-sem { padding: 20px 0; }
.faixa-sem b { font-size: 13.5px; }

/* fatos */
.ficha-fatos {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 1px;
  margin: 0;
  background: var(--linha);
  border-bottom: 1px solid var(--linha);
}
.ficha-fatos .fato { background: var(--bg-2); padding: 12px 20px; }
.ficha-fatos dt { font-size: 11.5px; color: var(--txt-2); margin-bottom: 3px; }
.ficha-fatos dd {
  margin: 0;
  font-size: 13.5px;
  font-weight: 500;
  display: flex;
  align-items: center;
  gap: 7px;
}
.pip { width: 7px; height: 7px; border-radius: 50%; flex: 0 0 auto; display: block; }
.pip.ok { background: var(--ok); }
.pip.alerta { background: var(--alerta); }
.pip.idle { background: #48515f; }

/* aviso contextual */
.ficha-box {
  display: flex;
  gap: 12px;
  align-items: flex-start;
  padding: 14px 20px;
  background: rgba(210, 153, 34, .08);
}
.ficha-box.grave { background: rgba(240, 93, 93, .08); }
.ficha-box-barra {
  width: 4px;
  align-self: stretch;
  border-radius: 2px;
  background: var(--alerta);
  flex: 0 0 auto;
}
.ficha-box.grave .ficha-box-barra { background: var(--erro); }
.ficha-box-txt { flex: 1; }
.ficha-box-txt b { display: block; font-size: 13.5px; margin-bottom: 2px; }
.ficha-box-txt p { margin: 0; font-size: 12.5px; color: var(--txt-2); line-height: 1.5; }
.ficha-box .btn { flex: 0 0 auto; align-self: center; }

/* preview ao vivo embutido na ficha, com os cartões de tempo real ao lado — não abaixo, para não
   sobrar espaço vazio à direita do vídeo */
.ficha-linha-vivo {
  display: flex;
  gap: 20px;
  align-items: flex-start;
  padding: 16px 20px;
  border-bottom: 1px solid var(--linha);
  flex-wrap: wrap;
}
.ficha-preview { flex: 1 1 340px; max-width: 440px; }
.ficha-preview:empty { display: none; }
.ficha-vivo-col { flex: 1 1 260px; min-width: 220px; }
.ficha-vivo-col .ficha-vivo { padding: 0; border-bottom: none; }
.preview-quadro {
  aspect-ratio: 16 / 9;
  border-radius: 6px;
  overflow: hidden;
}
.preview-quadro > .tile { width: 100%; height: 100%; }
.preview-barra {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-top: 8px;
  flex-wrap: wrap;
}
.preview-streams { display: flex; gap: 6px; margin-left: auto; }
.preview-streams .btn[aria-pressed="true"] {
  background: var(--acento);
  border-color: var(--acento);
  color: var(--sobre-acento);
}

/* configuração declarada pelo gravador */
.ficha-gravador { padding: 16px 20px; border-bottom: 1px solid var(--linha); }
.gravador-cab {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 8px;
}
.gravador-cab b { font-size: 13.5px; }
.ficha-gravador .rolagem-x { overflow-x: auto; }
.ficha-gravador table { min-width: 520px; }
.ficha-gravador .dica { margin-top: 8px; }

@media (max-width: 980px) {
  .canais-corpo { grid-template-columns: 1fr; }
  .canais-lista { max-height: 420px; overflow: auto; }
  .preview-quadro { max-width: none; }

  .grav-tela { grid-template-columns: 1fr; }
  .grav-sidebar-esq.painel-lateral { height: auto; }
  .arvore-canais.lista-canais { max-height: 260px; }
}

/* Celular (≤600px, simulação de acesso do cliente via IP na mesma Wi-Fi, 19/09/2026): a árvore, o
   vídeo e as ferramentas já empilham em 1 coluna desde 980px — falta o que só aperta de verdade em
   largura de toque. O rótulo do canal (gravador + canal + nome) pode passar de 300px sozinho e
   estourava a `.barra`; ganha linha própria acima da navegação de dia. O zoom da timeline saía do
   lado da régua e a espremia — desce para uma linha abaixo, régua com a largura toda (o zoom em si
   já resolve precisão de toque, não precisa dividir espaço com os botões). */
@media (max-width: 600px) {
  /* ⛔ DEFEITO CORRIGIDO (achado na mesma simulação de celular): `.grav-tela{height:100%}` +
     `.grav-central{grid-template-rows:auto 1fr auto auto}` pressupõem uma tela larga o bastante
     para que árvore+vídeo+ferramentas caibam lado a lado na altura do viewport. Empilhados em 1
     coluna num celular (câmeras + vídeo + timeline + calendário + exportações, tudo em pé), o
     conteúdo real passa longe da altura disponível — a faixa "auto 1fr auto auto" então ESPREME
     as linhas em vez de simplesmente rolar, e a linha do zoom da timeline literalmente ficava por
     CIMA do painel "Data e hora" seguinte (dois blocos ocupando a mesma faixa vertical). A correção
     é deixar as três seções crescerem pelo conteúdo (`height:auto`, sem `1fr`) e dar ao vídeo uma
     altura própria por proporção (`aspect-ratio`), já que ele não pode mais depender de "o que
     sobrar" de um container sem altura definida. */
  .grav-tela { height: auto; }
  .grav-central { grid-template-rows: auto auto auto auto; height: auto; }
  .player-video { min-height: 0; aspect-ratio: 16 / 9; }

  .grav-sidebar-esq.painel-lateral { height: auto; }
  .arvore-canais.lista-canais { max-height: 220px; }

  .barra { row-gap: 6px; }
  .rotulo-canal { flex-basis: 100%; order: -1; white-space: normal; }

  .linha-timeline { flex-direction: column; align-items: stretch; gap: 6px; }
  .zoom-controles { justify-content: center; }

  .transporte { justify-content: center; }
  .transporte .velocidades { flex-wrap: wrap; justify-content: center; }

  /* ⛔ DEFEITO CORRIGIDO (relato do usuário: "no celular é complicado selecionar com o dedo o
     trecho... a faixa grossa costuma estar por cima da numeração dos horários"). No desktop os
     46px de altura cabem tudo porque ninguém tenta LER o número por cima da cor — o mouse já sabe
     onde clicou. `.marcas span` (as horas "00","03"...) e `.seg` sempre dividiram o mesmo espaço
     vertical (span começa em top:2px com ~11px de texto, `.seg` começa em top:6px): o `.seg`, por
     ser adicionado DEPOIS no DOM, pinta por cima da metade de baixo de cada número sempre que há
     gravação naquele horário — exatamente onde o dedo mais precisa do número como referência pra
     mirar. Corrigido só aqui (celular): timeline mais alta, com uma faixa PRÓPRIA reservada pros
     números no topo, antes de qualquer cor começar — não é mais possível sobrepor. */
  .timeline { height: 64px; }
  .timeline .mov { top: 17px; height: 6px; }
  .timeline .mov.mov-margem { height: 5px; }
  .timeline .seg { top: 24px; }
}

/* --------------------------------------------------------------------------------- Orçamento */
/* Layout fiel a uma referência visual do usuário (17/09/2026): cartões mais arredondados que o
   resto do app (`--raio-grande`, só usado aqui — o resto do app segue com `--raio`) e blocos tipo
   painel/KPI. Cores continuam 100% dos tokens existentes (nada de paleta nova); o único ponto onde
   a referência original usava vermelho de interação (hover do menu) foi trocado por azul — decisão
   confirmada com o usuário, ver nota em `nav.menu a` acima. */

.col-estreita { width: 90px; }

.orc-cabecalho { display: flex; justify-content: space-between; align-items: flex-start; gap: 24px; flex-wrap: wrap; margin-bottom: 14px; }
.orc-titulo-bloco { flex: 1; min-width: 280px; }
.orc-titulo { display: flex; align-items: center; gap: 12px; margin: 0 0 6px; font-size: 20px; font-weight: 800; letter-spacing: -.01em; }
.orc-selo {
  width: 34px; height: 34px; border-radius: 10px; flex-shrink: 0;
  background: rgba(47, 126, 230, .18); color: var(--acento);
  display: flex; align-items: center; justify-content: center;
}
.orc-selo .ic { width: 19px; height: 19px; }
.orc-titulo-bloco > .dica { font-size: 12.5px; max-width: 74ch; margin-top: 0; }

.orc-retencao { flex-shrink: 0; min-width: 300px; margin-bottom: 0; padding: 12px 16px; }
.orc-subtitulo { display: flex; align-items: center; gap: 8px; margin: 0 0 10px; font-size: 13.5px; font-weight: 700; }
.orc-subtitulo .ic { color: var(--acento); width: 17px; height: 17px; }

.orc-acoes { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; margin-bottom: 14px; }

/* Cada botão abre um diálogo modal (não expande conteúdo na página) — é isso que mantém a tela
   compacta independente de quantos canais já foram descritos em cada formulário. */
.orc-acao {
  display: flex; align-items: center; gap: 14px; width: 100%; min-height: 58px; padding: 0 18px;
  background: var(--bg-2); border: 1px solid var(--linha); border-radius: var(--raio-grande);
  color: var(--txt); font-weight: 700; font-size: 14px; cursor: pointer;
}
.orc-acao:hover { border-color: var(--acento); }
.orc-acao:focus-visible { outline: 2px solid var(--acento); outline-offset: 2px; }
.orc-acao > .ic:first-child { width: 22px; height: 22px; color: var(--acento); flex-shrink: 0; }
.orc-acao span { flex: 1; text-align: left; }
.orc-acao small { display: block; margin-top: 2px; color: var(--txt-2); font-weight: 500; font-size: 12px; }
.orc-acao-seta { color: var(--txt-2); }

.orc-acao.primaria { background: var(--acento); border-color: var(--acento); color: var(--sobre-acento); }
.orc-acao.primaria:hover { filter: brightness(1.08); }
.orc-acao.primaria > .ic:first-child, .orc-acao.primaria .orc-acao-seta { color: var(--sobre-acento); }
.orc-acao.primaria small { color: rgba(6, 18, 31, .65); }

.orc-canais-cab { display: flex; align-items: center; gap: 12px; margin-bottom: 10px; }
.orc-tabela-wrap { overflow-x: auto; }
.orc-canais-cab h3 { display: flex; align-items: center; gap: 10px; margin: 0; font-size: 16px; }
.orc-canais-cab h3 .ic { color: var(--acento); width: 20px; height: 20px; }
.orc-contagem { font-size: 12px; padding: 3px 10px; border-radius: 999px; background: rgba(47, 126, 230, .18); color: var(--acento); font-weight: 600; }

.orc-modo-cel { display: flex; align-items: center; gap: 8px; }
.orc-modo-ponto { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; background: var(--ok); }
.orc-modo-ponto.movimento { background: var(--acento); }
.orc-modo-ponto.variavel { background: var(--alerta); }

.orc-remover {
  display: inline-flex; align-items: center; gap: 6px; height: 32px; padding: 0 11px;
  background: none; border: 1px solid rgba(240, 93, 93, .4); border-radius: 6px;
  color: var(--erro); font-weight: 600; font-size: 12.5px; cursor: pointer;
}
.orc-remover:hover { background: rgba(240, 93, 93, .12); border-color: var(--erro); }
.orc-remover .ic { width: 14px; height: 14px; }

.orc-grade-inferior { display: grid; grid-template-columns: 1.05fr 1.05fr .9fr; gap: 12px; align-items: stretch; margin-top: 12px; }

.orc-notas { display: flex; flex-direction: column; gap: 10px; padding: 14px 16px; }
.orc-nota { display: flex; gap: 10px; margin: 0; font-size: 12.5px; line-height: 1.5; color: var(--txt); }
.orc-nota .ic { margin-top: 2px; color: var(--acento); width: 16px; height: 16px; }
.orc-nota.alerta .ic { color: var(--alerta); }
.orc-nota b { color: var(--txt); font-weight: 700; }

.orc-resumo { overflow: hidden; display: flex; flex-direction: column; padding: 0; }
.orc-resumo > h3 { margin: 0; padding: 12px 16px; background: var(--bg-3); border-bottom: 1px solid var(--linha); display: flex; align-items: center; gap: 9px; font-size: 14px; }
.orc-resumo > h3 .ic { color: var(--ok); width: 18px; height: 18px; }
.orc-resumo-lista { padding: 10px; display: flex; flex-direction: column; gap: 8px; flex: 1; }

.orc-kpi { display: flex; align-items: center; gap: 12px; padding: 10px 12px; border-radius: var(--raio-grande); background: var(--bg-3); border: 1px solid var(--linha); transition: transform .15s ease, border-color .15s ease, box-shadow .15s ease; }
.orc-kpi:hover { transform: translateY(-2px); border-color: var(--acento); box-shadow: 0 6px 16px rgba(0, 0, 0, .22); }
.orc-kpi-icone { width: 34px; height: 34px; border-radius: 9px; background: var(--bg); color: var(--txt-2); display: flex; align-items: center; justify-content: center; flex-shrink: 0; }
.orc-kpi-icone .ic { width: 18px; height: 18px; }
.orc-kpi-rotulo { font-size: 12px; color: var(--txt-2); }
.orc-kpi-valor { font-size: 18px; font-weight: 700; margin-top: 1px; }

/* O valor sugerido ao cliente é o número que fecha o orçamento — merece mais destaque que os
   outros dois KPIs, não só uma cor de fundo diferente. Texto em BRANCO (não `--sobre-acento`, que
   é escuro demais sobre o gradiente). O ícone chegou a ficar VERMELHO (13/09→17/09: "vermelho só
   identidade"), mas o usuário não gostou do resultado — fica branco, igual ao texto. */
.orc-kpi.destaque {
  background: linear-gradient(135deg, var(--marca-azul) 0%, #0f3f9c 100%);
  border-color: transparent;
  padding: 14px 16px;
  box-shadow: 0 10px 28px rgba(47, 126, 230, .35);
}
.orc-kpi.destaque:hover { border-color: transparent; box-shadow: 0 14px 34px rgba(47, 126, 230, .48); }
.orc-kpi.destaque .orc-kpi-icone { width: 38px; height: 38px; background: rgba(255, 255, 255, .16); color: #fff; }
.orc-kpi.destaque .orc-kpi-icone .ic { width: 20px; height: 20px; }
.orc-kpi.destaque .orc-kpi-rotulo { color: rgba(255, 255, 255, .82); }
.orc-kpi.destaque .orc-kpi-valor { color: #fff; font-size: 23px; }

.orc-resumo-acoes { padding: 0 10px 10px; }
.orc-resumo-acoes .btn { display: flex; align-items: center; justify-content: center; gap: 8px; margin-top: 2px; }

.orc-rodape { display: flex; align-items: flex-start; gap: 12px; margin-top: 12px; padding: 10px 16px; }
.orc-rodape .ic { color: var(--acento); width: 18px; height: 18px; margin-top: 1px; flex-shrink: 0; }
.orc-rodape p { margin: 0; flex: 1; font-size: 12px; line-height: 1.55; color: var(--txt-2); }
.orc-rodape .orc-carimbo { font-size: 12px; color: var(--txt-2); white-space: nowrap; }

@media (max-width: 1200px) {
  .orc-grade-inferior { grid-template-columns: 1fr 1fr; }
  .orc-resumo { grid-column: 1 / -1; }
  .orc-resumo-lista { flex-direction: row; flex-wrap: wrap; }
  .orc-kpi { flex: 1; min-width: 230px; }
}

@media (max-width: 900px) {
  .orc-cabecalho { flex-direction: column; }
  .orc-acoes { grid-template-columns: 1fr; }
  .orc-grade-inferior { grid-template-columns: 1fr; }
}

/* ------------------------------------------------------------ proposta (exportação em HTML) */
/* F-ORCAMENTO.7 (17/09/2026): proposta comercial exportável a partir do Orçamento, visual fiel a
   uma referência HTML entregue pelo usuário — folha A4 clara, de propósito diferente do resto do
   app: é um documento para o CLIENTE ver e assinar, não uma tela de operação, então não segue o
   tema escuro. A fonte da referência (Google "Plus Jakarta Sans") e o `<style>`/`onclick` inline
   são impossíveis aqui pela mesma CSP de sempre (`style-src`/`script-src 'self'`) — fica na pilha
   do sistema (`--fonte`) e tudo mora em `proposta.js`. O logotipo é o MESMO `<img class="marca-
   logo">` do topo/login (nunca o PNG embutido na referência): é a identidade real da empresa, e
   respeita a customização de `aplicarMarca()` (M2, 13/09) se houver uma enviada. O vermelho da
   marca aqui é o mesmo filete estático de identidade do resto do app (topo/rodapé do login) —
   nunca um estado de interação, a mesma regra de sempre. */

body.proposta { background: #e9edf3; color: #16233c; color-scheme: light; }

.pp-toolbar {
  position: sticky; top: 0; z-index: 10;
  display: flex; align-items: center; justify-content: center; gap: 16px; flex-wrap: wrap;
  padding: 14px; background: #16233c;
}
.pp-toolbar-dica { color: #9fb0c8; font-size: 12.5px; }

.pp-sheet {
  width: 210mm; min-height: 297mm; margin: 24px auto; padding: 16mm 16mm 14mm;
  background: #fff; color: #16233c; box-shadow: 0 6px 24px rgba(15, 23, 42, .14);
  font-size: 13.5px; line-height: 1.55;
}
.pp-num { font-variant-numeric: tabular-nums; }

.pp-vazio { max-width: 480px; margin: 60px auto; text-align: center; color: #16233c; }
.pp-vazio .btn { display: inline-block; margin-top: 10px; text-decoration: none; }

.pp-head { display: flex; justify-content: space-between; align-items: center; gap: 24px; padding-bottom: 16px; border-bottom: 3px solid var(--marca-vermelho); }
/* Mesma proporção do logotipo da tela de login (`.marca-login img`): a arte é quase quadrada (não
   uma faixa larga e baixa), então dimensionar pela LARGURA é o que faz aparecer por inteiro e
   reconhecível; uma altura fixa pequena espremia a mesma arte numa faixa estreita e ficava
   irreconhecível. É um ARQUIVO diferente do logo do topo/login (ver comentário em `proposta.js`):
   o `SRV` desta versão é preto, para fundo claro. */
.pp-logo { width: 180px; height: auto; object-fit: contain; display: block; }
.pp-doc-title { text-align: right; }
.pp-eyebrow { font-size: 11px; font-weight: 700; letter-spacing: .04em; color: #0f3f9c; }
.pp-doc-title h1 { margin: 4px 0 0; font-size: 21px; font-weight: 800; color: #16233c; }

.pp-meta { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; margin-top: 18px; }
.pp-meta-box { border: 1px solid #dfe5ee; border-radius: 10px; padding: 14px 16px; }
.pp-meta-box h2 { margin: 0 0 8px; font-size: 11px; font-weight: 700; letter-spacing: .03em; color: #4d5d78; }
.pp-meta-row { display: flex; justify-content: space-between; gap: 12px; padding: 3px 0; font-size: 13px; }
.pp-meta-row span:first-child { color: #4d5d78; }
.pp-meta-row span:last-child { font-weight: 600; text-align: right; }

.pp-section { margin: 26px 0 10px; font-size: 14px; font-weight: 700; color: #16233c; display: flex; align-items: center; gap: 8px; }
.pp-bar { width: 4px; height: 14px; background: var(--marca-azul); border-radius: 2px; flex-shrink: 0; }

.pp-lede { margin: 0 0 14px; color: #4d5d78; font-size: 13px; }

.pp-tabela { width: 100%; border-collapse: collapse; }
.pp-tabela thead th { text-align: left; font-size: 11px; font-weight: 700; letter-spacing: .02em; color: #4d5d78; padding: 8px 10px; background: #f4f7fb; border-bottom: 1px solid #dfe5ee; }
.pp-tabela thead th.r { text-align: right; }
.pp-tabela tbody td { padding: 10px 10px; border-bottom: 1px solid #dfe5ee; font-size: 13px; vertical-align: top; }
.pp-tabela tbody td.r { text-align: right; }
.pp-tabela tbody tr { break-inside: avoid; }
.pp-tabela thead { display: table-header-group; }
.pp-ch-name { font-weight: 700; }
.pp-ch-sub { font-size: 11.5px; color: #4d5d78; margin-top: 2px; }
.pp-pill { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; font-weight: 600; color: #16233c; }
.pp-dot { width: 7px; height: 7px; border-radius: 50%; flex-shrink: 0; }
.pp-dot-ok { background: #22b573; }
.pp-dot-acento { background: var(--marca-azul); }
.pp-dot-alerta { background: #d29922; }

.pp-stat-row { display: flex; gap: 14px; margin-top: 14px; flex-wrap: wrap; }
.pp-stat { flex: 1; min-width: 160px; border: 1px solid #dfe5ee; border-radius: 10px; padding: 12px 14px; }
.pp-label { font-size: 11.5px; color: #4d5d78; }
.pp-value { font-size: 18px; font-weight: 700; margin-top: 2px; }

.pp-price-box {
  margin-top: 22px; border-radius: 12px; padding: 20px 24px;
  background: linear-gradient(135deg, var(--marca-azul) 0%, #0f3f9c 100%);
  color: #fff; display: flex; justify-content: space-between; align-items: center; gap: 16px; flex-wrap: wrap;
}
.pp-price-label { font-size: 13px; color: #dbe8ff; }
.pp-price-cadence { font-size: 12px; color: #bcd4ff; margin-top: 2px; }
.pp-price-value { font-size: 32px; font-weight: 800; }

.pp-notes ul { margin: 10px 0 0; padding-left: 18px; }
.pp-notes li { margin-bottom: 6px; font-size: 12px; color: #4d5d78; }

.pp-sign { display: flex; gap: 40px; margin-top: 46px; flex-wrap: wrap; }
.pp-sign-line { flex: 1; min-width: 200px; text-align: center; font-size: 13px; color: #16233c; }
.pp-rule { border-top: 1px solid #16233c; margin-bottom: 6px; }
.pp-role { font-size: 12px; color: #4d5d78; margin-top: 2px; }

.pp-foot { display: flex; justify-content: space-between; align-items: center; margin-top: 28px; padding-top: 12px; border-top: 1px solid #dfe5ee; font-size: 10.5px; color: #8695ac; }

@media print {
  .pp-toolbar { display: none; }
  body.proposta { background: #fff; }
  .pp-sheet { box-shadow: none; margin: 0; width: auto; min-height: 0; }
  @page { size: A4; margin: 14mm 16mm; }
}

@media (max-width: 900px) {
  .pp-sheet { width: auto; padding: 20px; }
  .pp-meta { grid-template-columns: 1fr; }
  .pp-head { flex-direction: column; }
  .pp-doc-title { text-align: left; }
  .pp-stat-row { flex-direction: column; }
}

/* ------------------------------------------------------------ Incidentes dos DVRs (F-SAUDE, redesenho 19/09/2026) */
/* Layout fiel a uma referência visual + HTML entregues pelo usuário: KPIs, categorias em grade,
   cartões de status por DVR, linha do tempo de 24h e feed recente — no lugar da lista linear que
   crescia sem fim abaixo dos cartões. A referência usava Font Awesome + Google Fonts via CDN; a
   CSP deste app não abre `script-src`/`style-src` para nenhum CDN (mesmo limite já documentado no
   Orçamento e no login), então os ícones vêm de `icones.js` (SVG por traço) e a fonte da pilha do
   sistema. O "drawer" lateral da segunda referência virou um `<dialog>` modal: é o mesmo padrão de
   detalhe que o resto do app já usa (`ui.js::perguntar`), evitando reinventar animação de painel
   deslizante para o mesmo resultado (ver detalhe de um incidente ao clicar na linha). */

.inc-cabecalho { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; flex-wrap: wrap; margin-bottom: 14px; }
.inc-titulo-bloco { display: flex; gap: 14px; align-items: flex-start; flex: 1; min-width: 260px; }
.inc-selo { width: 40px; height: 40px; border-radius: 11px; flex-shrink: 0; background: rgba(47, 126, 230, .18); color: var(--acento); display: flex; align-items: center; justify-content: center; }
.inc-selo .ic { width: 20px; height: 20px; }
.inc-titulo-bloco h2 { margin: 0 0 3px; }
.inc-ao-vivo { display: flex; align-items: center; gap: 7px; margin-top: 6px; font-size: 11.5px; color: var(--txt-2); }
.inc-pulso { width: 7px; height: 7px; border-radius: 50%; background: var(--ok); position: relative; flex: 0 0 auto; }
.inc-pulso::after { content: ""; position: absolute; inset: -4px; border-radius: 50%; border: 1px solid var(--ok); animation: pulsa-anel 2s infinite; }
@keyframes pulsa-anel { from { transform: scale(1); opacity: .8; } to { transform: scale(2.4); opacity: 0; } }
@media (prefers-reduced-motion: reduce) { .inc-pulso::after { animation: none; opacity: 0; } }

.inc-filtros { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
/* Pílula com ícone + controle — mesmo espírito da referência do usuário. O `<select>`/`<input>`
   herda `width:100%` da regra genérica do projeto (linha ~201); aqui ela vira "100% do CAMPO", que
   é o efeito certo, porque quem tem largura própria é o `.inc-filtro-campo`, não o controle solto —
   sem isso, `width:100%` deixava cada filtro tomar a linha do flex inteira e empilhava tudo em
   coluna, sem nenhuma pílula (era exatamente o "vertical, sem formatação" relatado pelo usuário). */
.inc-filtro-campo {
  position: relative;
  display: flex;
  align-items: center;
  height: 36px;
  min-width: 150px;
  background: var(--bg-2);
  border: 1px solid var(--linha);
  border-radius: 999px;
}
.inc-filtro-campo:focus-within { border-color: var(--acento); }
.inc-filtro-campo > .ic { position: absolute; left: 12px; width: 15px; height: 15px; color: var(--txt-2); pointer-events: none; }
.inc-filtro-campo select, .inc-filtro-campo input {
  width: 100%;
  height: 100%;
  padding: 0 12px 0 34px;
  font-size: 12.5px;
  background: transparent;
  color: var(--txt);
  border: 0;
  border-radius: 999px;
}
.inc-filtro-campo input:focus, .inc-filtro-campo select:focus { outline: none; }
/* O POPUP do <select> é desenhado pelo SO/navegador, não por este CSS — mas Chrome/Edge decidem se
   ele sai claro ou escuro a partir do `color-scheme` computado do próprio elemento, não só do
   herdado em `:root`, e um `background:transparent` no controle às vezes faz esse cálculo falhar
   (achado ao usuário reportar "letras escuras sobre fundo claro" ao abrir este dropdown — a barra
   fechada já vinha certa, só o popup não). `color-scheme:dark` explícito aqui + `<option>` com
   cor própria (suportado por todos os navegadores, mesmo sem poder estilizar o resto do popup)
   cobre os dois ângulos do mesmo defeito. */
.inc-filtro-campo select { color-scheme: dark; }
.inc-filtro-campo select option { background: var(--bg-2); color: var(--txt); }
.inc-filtro-campo input[type="search"] { width: 190px; }
.inc-limpar { display: inline-flex; align-items: center; gap: 6px; height: 32px; padding: 0 11px; background: transparent; border: 1px dashed var(--linha); color: var(--txt-2); font-size: 11.5px; }
.inc-limpar:hover { color: var(--txt); border-color: var(--acento); }
.inc-limpar .ic { width: 13px; height: 13px; }
/* `display` no seletor de classe empataria em especificidade com o `[hidden]` da UA e venceria por
   ordem de origem — mesmo cuidado já documentado em `.tile .cortina[hidden]`/`.player-carregando[hidden]`. */
.inc-limpar[hidden], .inc-mais[hidden] { display: none; }

.inc-kpis { display: grid; grid-template-columns: repeat(4, 1fr); gap: 12px; margin-bottom: 14px; }
.inc-kpi { display: flex; align-items: center; gap: 13px; padding: 14px 16px; background: linear-gradient(145deg, var(--bg-2), var(--bg)); border: 1px solid var(--linha); border-radius: var(--raio-grande); }
.inc-kpi-icone { width: 42px; height: 42px; border-radius: 50%; flex-shrink: 0; display: flex; align-items: center; justify-content: center; }
.inc-kpi-icone .ic { width: 19px; height: 19px; }
.inc-kpi:nth-child(1) .inc-kpi-icone { background: rgba(47, 126, 230, .22); color: var(--acento); }
.inc-kpi:nth-child(2) .inc-kpi-icone { background: rgba(240, 93, 93, .22); color: var(--erro); }
.inc-kpi:nth-child(3) .inc-kpi-icone { background: rgba(210, 153, 34, .22); color: var(--alerta); }
.inc-kpi:nth-child(4) .inc-kpi-icone { background: rgba(63, 185, 80, .22); color: var(--ok); }
.inc-kpi-rotulo { font-size: 11.5px; color: var(--txt-2); }
.inc-kpi-valor { font-size: 24px; font-weight: 700; margin-top: 2px; font-variant-numeric: tabular-nums; }

.inc-grid { display: grid; grid-template-columns: 1.15fr 1fr; gap: 14px; margin-bottom: 14px; }
.inc-painel { background: linear-gradient(145deg, var(--bg-2), var(--bg)); border: 1px solid var(--linha); border-radius: var(--raio-grande); padding: 16px; }
.inc-painel-cab { display: flex; align-items: center; gap: 10px; margin-bottom: 13px; }
.inc-painel-cab .ic { color: var(--acento); width: 17px; height: 17px; flex-shrink: 0; }
.inc-painel-cab h3 { margin: 0; font-size: 14px; }
.inc-painel-cab p { margin: 2px 0 0; font-size: 11px; color: var(--txt-2); }

/* ------------------------------------------------------------------------------------------- *
 * Design system de módulo, GENÉRICO (F-VISUAL, 20/09/2026): cópia deliberada — NÃO renomeação —
 * do padrão visual de Incidentes (cabeçalho/filtros/KPI/painel), para uso por QUALQUER outro
 * módulo (Grupos, Planos, DVRs, Canais, Agenda, Usuários, Configurações, Orçamento, Gravações).
 * Incidentes (`saude.js`) continua lendo exclusivamente as classes `inc-*` acima — pedido
 * explícito do usuário para não mexer numa tela já ajustada — por isso as regras abaixo duplicam
 * a definição em vez de generalizar o seletor original. */
.modulo-cabecalho { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; flex-wrap: wrap; margin-bottom: 14px; }
.modulo-titulo-bloco { display: flex; gap: 14px; align-items: flex-start; flex: 1; min-width: 260px; }
.modulo-selo { width: 40px; height: 40px; border-radius: 11px; flex-shrink: 0; background: rgba(47, 126, 230, .18); color: var(--acento); display: flex; align-items: center; justify-content: center; }
.modulo-selo .ic { width: 20px; height: 20px; }
.modulo-titulo-bloco h2 { margin: 0 0 3px; }
.modulo-ao-vivo { display: flex; align-items: center; gap: 7px; margin-top: 6px; font-size: 11.5px; color: var(--txt-2); }
.modulo-pulso { width: 7px; height: 7px; border-radius: 50%; background: var(--ok); position: relative; flex: 0 0 auto; }
.modulo-pulso::after { content: ""; position: absolute; inset: -4px; border-radius: 50%; border: 1px solid var(--ok); animation: pulsa-anel-modulo 2s infinite; }
@keyframes pulsa-anel-modulo { from { transform: scale(1); opacity: .8; } to { transform: scale(2.4); opacity: 0; } }
@media (prefers-reduced-motion: reduce) { .modulo-pulso::after { animation: none; opacity: 0; } }

.filtros-pilula { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
.filtro-campo {
  position: relative;
  display: flex;
  align-items: center;
  height: 36px;
  min-width: 150px;
  background: var(--bg-2);
  border: 1px solid var(--linha);
  border-radius: 999px;
}
.filtro-campo:focus-within { border-color: var(--acento); }
.filtro-campo > .ic { position: absolute; left: 12px; width: 15px; height: 15px; color: var(--txt-2); pointer-events: none; }
.filtro-campo select, .filtro-campo input {
  width: 100%;
  height: 100%;
  padding: 0 12px 0 34px;
  font-size: 12.5px;
  background: transparent;
  color: var(--txt);
  border: 0;
  border-radius: 999px;
}
.filtro-campo input:focus, .filtro-campo select:focus { outline: none; }
.filtro-campo select { color-scheme: dark; }
.filtro-campo select option { background: var(--bg-2); color: var(--txt); }
.filtro-campo input[type="search"] { width: 190px; }
.limpar-filtros { display: inline-flex; align-items: center; gap: 6px; height: 32px; padding: 0 11px; background: transparent; border: 1px dashed var(--linha); color: var(--txt-2); font-size: 11.5px; }
.limpar-filtros:hover { color: var(--txt); border-color: var(--acento); }
.limpar-filtros .ic { width: 13px; height: 13px; }
.limpar-filtros[hidden] { display: none; }

.kpis { display: grid; grid-template-columns: repeat(4, 1fr); gap: 12px; margin-bottom: 14px; }
.kpis.kpis-5 { grid-template-columns: repeat(5, 1fr); }
@media (max-width: 1100px) { .kpis.kpis-5 { grid-template-columns: repeat(3, 1fr); } }
@media (max-width: 620px) { .kpis.kpis-5 { grid-template-columns: 1fr; } }
.kpi { display: flex; align-items: center; gap: 13px; padding: 14px 16px; background: linear-gradient(145deg, var(--bg-2), var(--bg)); border: 1px solid var(--linha); border-radius: var(--raio-grande); }
/* ícone dos indicadores: círculo de 52 px com brilho suave (mesmo desenho dos DVRs, 28/09/2026) */
.kpi-icone { width: 52px; height: 52px; border-radius: 50%; flex-shrink: 0; display: flex; align-items: center; justify-content: center; }
.kpi-icone .ic { width: 22px; height: 22px; }
.kpi:nth-child(1) .kpi-icone { background: rgba(47, 126, 230, .17); color: var(--acento); box-shadow: 0 0 12px rgba(47, 126, 230, .14); }
.kpi:nth-child(2) .kpi-icone { background: rgba(240, 93, 93, .17); color: var(--erro); box-shadow: 0 0 12px rgba(240, 93, 93, .14); }
.kpi:nth-child(3) .kpi-icone { background: rgba(210, 153, 34, .17); color: var(--alerta); box-shadow: 0 0 12px rgba(210, 153, 34, .14); }
.kpi:nth-child(4) .kpi-icone { background: rgba(63, 185, 80, .17); color: var(--ok); box-shadow: 0 0 12px rgba(63, 185, 80, .14); }
.kpi:nth-child(5) .kpi-icone { background: rgba(56, 182, 245, .17); color: var(--marca-ciano); box-shadow: 0 0 12px rgba(56, 182, 245, .14); }
/* cor por SIGNIFICADO (vence a cor por posição acima): k-azul, k-verde, k-vermelho, k-amarelo, k-ciano, k-roxo */
.kpi.k-azul .kpi-icone { background: rgba(47, 126, 230, .17); color: var(--acento); box-shadow: 0 0 12px rgba(47, 126, 230, .14); }
.kpi.k-verde .kpi-icone { background: rgba(63, 185, 80, .17); color: var(--ok); box-shadow: 0 0 12px rgba(63, 185, 80, .14); }
.kpi.k-vermelho .kpi-icone { background: rgba(240, 93, 93, .17); color: var(--erro); box-shadow: 0 0 12px rgba(240, 93, 93, .14); }
.kpi.k-amarelo .kpi-icone { background: rgba(210, 153, 34, .17); color: var(--alerta); box-shadow: 0 0 12px rgba(210, 153, 34, .14); }
.kpi.k-ciano .kpi-icone { background: rgba(56, 182, 245, .17); color: var(--marca-ciano); box-shadow: 0 0 12px rgba(56, 182, 245, .14); }
.kpi.k-roxo .kpi-icone { background: rgba(163, 113, 247, .17); color: #a371f7; box-shadow: 0 0 12px rgba(163, 113, 247, .14); }
.kpi-rotulo { font-size: 11.5px; color: var(--txt-2); }
.kpi-valor { font-size: 24px; font-weight: 700; margin-top: 2px; font-variant-numeric: tabular-nums; }
.kpi-valor.ok { color: var(--ok); }
.kpi { transition: transform .15s ease, border-color .15s ease, background-color .15s ease; }
.kpi:hover { transform: translateY(-2px); border-color: var(--acento); }

/* Grade de cartões clicáveis genérica (Grupos, Planos, DVRs, ...) — número de colunas por tela via
   `style.gridTemplateColumns` inline (mesmo padrão que `.inc-categorias`/`.inc-dvrs` já usavam,
   só que parametrizável em vez de fixo em 2/4). */
.grade-cartoes { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; }
@media (max-width: 900px) { .grade-cartoes { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 620px) { .grade-cartoes { grid-template-columns: 1fr; } }

.painel-cab { display: flex; align-items: center; gap: 10px; margin-bottom: 13px; }
.painel-cab .ic { color: var(--acento); width: 17px; height: 17px; flex-shrink: 0; }
.painel-cab h3 { margin: 0; font-size: 14px; }
.painel-cab p { margin: 2px 0 0; font-size: 11px; color: var(--txt-2); }

.inc-categorias { display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px; }
.inc-cat {
  all: unset; box-sizing: border-box; display: block; width: 100%; cursor: pointer; font: inherit; color: inherit;
  position: relative; padding: 12px 12px 12px 15px; border-radius: 9px; background: var(--bg-3);
  border: 1px solid var(--linha);
  transition: transform .15s ease, background-color .15s ease, border-color .15s ease;
}
/* leve "levante" ao passar o mouse — pedido do usuário, mesmo efeito da referência (.cat:hover) */
.inc-cat:hover { border-color: var(--sev, var(--acento)); background: var(--bg-2); transform: translateY(-2px); }
.inc-cat.ativo { box-shadow: 0 0 0 1px var(--sev, var(--acento)); border-color: var(--sev, var(--acento)); }
.inc-cat::before { content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 3px; border-radius: 9px 0 0 9px; background: var(--sev, var(--acento)); }
.inc-cat-nome { display: flex; align-items: center; gap: 6px; font-size: 11px; color: var(--txt-2); }
.inc-cat-nome .ic { width: 14px; height: 14px; color: var(--sev, var(--acento)); }
.inc-cat-num { font-size: 19px; font-weight: 700; margin: 8px 0 6px; }
.inc-cat-badge { font-size: 9.5px; padding: 3px 8px; border-radius: 999px; background: var(--sev-bg, var(--bg)); color: var(--sev-fg, var(--txt-2)); }

.inc-dvrs { display: grid; grid-template-columns: repeat(2, 1fr); gap: 10px; }

.inc-linha { margin-bottom: 14px; }
.inc-linha-legenda { margin-left: auto; display: flex; gap: 14px; font-size: 10.5px; color: var(--txt-2); }
.inc-linha-legenda span { display: inline-flex; align-items: center; gap: 5px; }
.inc-trilho { position: relative; height: 22px; background: var(--bg); border: 1px solid var(--linha); border-radius: 4px; display: flex; gap: 2px; padding: 2px 6px; }
.inc-marca { height: 100%; flex: 1; border-radius: 1px; background: var(--bg-3); cursor: default; }
.inc-marca.critico { background: var(--erro); }
.inc-marca.atencao { background: var(--alerta); }
.inc-marca.info { background: var(--marca-ciano); }
.inc-agora { position: absolute; top: -3px; bottom: -3px; width: 2px; background: var(--txt); opacity: .7; }
.inc-eixo { display: flex; justify-content: space-between; color: var(--txt-2); font-size: 10px; margin-top: 7px; }

.inc-recente { display: grid; grid-template-columns: 1fr 260px; gap: 12px; align-items: start; }
.inc-tabela-wrap { overflow-x: auto; }
.inc-linha-tab { cursor: pointer; }
.inc-linha-tab:hover { background: var(--bg-3); }
.inc-sev-dot { width: 8px; height: 8px; border-radius: 50%; display: inline-block; margin-right: 6px; background: var(--txt-2); }
.inc-sev-dot.critico { background: var(--erro); }
.inc-sev-dot.atencao { background: var(--alerta); }
.inc-sev-dot.info { background: var(--marca-ciano); }
.inc-sev-dot.normal { background: var(--ok); }
.inc-tipo-cel { display: flex; align-items: center; gap: 7px; }
.inc-tipo-cel .ic { width: 15px; height: 15px; color: var(--txt-2); flex-shrink: 0; }

.inc-legenda-lateral { padding: 3px; }
.inc-legenda-lateral h3 { margin: 0 0 10px; font-size: 13px; }
.inc-legenda-item { display: flex; gap: 9px; align-items: flex-start; font-size: 12px; margin: 10px 0; color: var(--txt-2); }
.inc-legenda-item .inc-sev-dot { margin-top: 4px; }
.inc-legenda-item b { display: block; color: var(--txt); }
.inc-legenda-info { display: flex; gap: 8px; border-top: 1px solid var(--linha); margin-top: 12px; padding-top: 12px; font-size: 11px; color: var(--txt-2); line-height: 1.5; }
.inc-legenda-info .ic { flex-shrink: 0; width: 15px; height: 15px; margin-top: 1px; }

.inc-mais { display: flex; align-items: center; gap: 7px; margin-left: auto; padding: 7px 13px; font-size: 11.5px; background: transparent; border: 1px solid var(--acento); color: var(--acento); border-radius: 6px; }
.inc-mais:hover { background: rgba(47, 126, 230, .12); }
.inc-mais .ic { width: 13px; height: 13px; }

/* diálogo de detalhe (substitui o drawer da referência — ver nota no topo da seção) */
dialog.inc-detalhe { max-width: 440px; }
.inc-det-cab { display: flex; align-items: center; gap: 9px; margin: 0 0 14px; font-size: 15px; }
.inc-det-cab .ic { color: var(--acento); width: 18px; height: 18px; }
.inc-det-linha { display: flex; justify-content: space-between; align-items: center; gap: 12px; padding: 9px 0; border-bottom: 1px solid var(--linha); font-size: 13px; }
.inc-det-linha span:first-child { color: var(--txt-2); }
.inc-det-linha b { font-weight: 600; text-align: right; }
.inc-det-desc { margin: 14px 0 0; font-size: 12.5px; line-height: 1.6; color: var(--txt); background: var(--bg); border: 1px solid var(--linha); border-radius: 8px; padding: 11px 12px; }
.inc-det-resolvido { margin: 14px 0 0; color: var(--ok); font-size: 12.5px; display: flex; gap: 8px; align-items: center; }

@media (max-width: 1050px) {
  .inc-grid { grid-template-columns: 1fr; }
  .inc-kpis { grid-template-columns: repeat(2, 1fr); }
  .inc-categorias { grid-template-columns: repeat(2, 1fr); }
  .inc-dvrs { grid-template-columns: 1fr; }
  .inc-recente { grid-template-columns: 1fr; }
}
@media (max-width: 620px) {
  .inc-kpis { grid-template-columns: 1fr; }
  .inc-categorias { grid-template-columns: 1fr; }
  .inc-filtro-campo, .inc-filtro-campo input[type="search"] { width: 100%; }
}

/* diálogo de detalhe GENÉRICO, para os demais módulos (cópia deliberada, ver nota acima) */
dialog.dlg-detalhe { max-width: 440px; }
dialog.dlg-pergunta { max-width: 420px; }
/* confirmação de identidade e formulários curtos dentro de um diálogo (Usuários, menu da conta) */
.det-sub { margin: 16px 0 8px; font-size: 13px; font-weight: 700; }
.det-campos { display: grid; gap: 10px; }
.det-campos label { margin-top: 0; }
.det-cab { display: flex; align-items: center; gap: 9px; margin: 0 0 14px; font-size: 15px; }
.det-cab .ic { color: var(--acento); width: 18px; height: 18px; }
.det-cab.perigo .ic { color: var(--erro); }
.det-linha { display: flex; justify-content: space-between; align-items: center; gap: 12px; padding: 9px 0; border-bottom: 1px solid var(--linha); font-size: 13px; }
.det-linha span:first-child { color: var(--txt-2); }
.det-linha b { font-weight: 600; text-align: right; }
.det-desc { margin: 14px 0 0; font-size: 12.5px; line-height: 1.6; color: var(--txt); background: var(--bg); border: 1px solid var(--linha); border-radius: 8px; padding: 11px 12px; }
.det-resolvido { margin: 14px 0 0; color: var(--ok); font-size: 12.5px; display: flex; gap: 8px; align-items: center; }
@media (max-width: 1050px) {
  .kpis { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 620px) {
  .kpis { grid-template-columns: 1fr; }
  .filtro-campo, .filtro-campo input[type="search"] { width: 100%; }
}

/* Enquanto o player salta até o instante pedido dentro de um arquivo de nuvem (que vem desde o
   começo do segmento), a camada cobre o vídeo inteiro: sem isso o operador assistiria ao trecho
   ANTERIOR ao que escolheu. */
.player-carregando.cobrir { inset: 0; background: #000; }

/* Arrastar até o instante (22/09/2026): o gesto horizontal na barra é nosso (arrasto), o vertical
   continua rolando a página. Sem `touch-action` o navegador do celular tomaria o gesto para si.
   Quem decide a direção de cada toque é `gravacoes.js` (23/09): vertical nunca vira arrasto, e se o
   navegador não rolar a página sozinho a partir daqui, o próprio código rola. */
.timeline { touch-action: pan-y; user-select: none; -webkit-user-select: none; }
.timeline.arrastando { cursor: ew-resize; }
.timeline .cursor-arrasto {
  position: absolute;
  top: 0; bottom: 0;
  width: 2px;
  margin-left: -1px;
  background: var(--acento);
  box-shadow: 0 0 0 1px rgba(0, 0, 0, .45);
  pointer-events: none;
  z-index: 5;
}
.timeline .cursor-arrasto.cancela { background: var(--txt-2); }
.hover-dica.arrasto { font-size: 15px; font-weight: 600; padding: 6px 10px; font-variant-numeric: tabular-nums; }

/* ================================================================== Configurações (25/09/2026)
   Redesenho a partir de uma referência do usuário; desde 26/09 em três abas por assunto — "Nuvem e
   custos", "Sistema e backup" e "Identidade visual" —, cada uma com a largura inteira, porque o
   custo por cliente cresce com a carteira. Tudo com prefixo `cfg-`: botões contornados, interruptor
   e o "olho" nos campos de senha valem SÓ aqui, para não mudar em silêncio as outras telas. */
.cfg-abas {
  display: flex; gap: 4px; width: fit-content; max-width: 100%; margin: 0 0 16px; padding: 4px;
  overflow-x: auto; background: linear-gradient(160deg, var(--bg-2), var(--bg));
  border: 1px solid var(--linha); border-radius: 12px;
}
.cfg-aba {
  position: relative; display: inline-flex; align-items: center; gap: 8px; flex: 0 0 auto;
  padding: 8px 16px; border: 0; border-radius: 9px; background: transparent; color: var(--txt-2);
  font: inherit; font-size: 13.5px; font-weight: 600; white-space: nowrap; cursor: pointer;
  transition: background-color .15s ease, color .15s ease;
}
.cfg-aba .ic { width: 17px; height: 17px; flex: 0 0 auto; }
.cfg-aba:hover { background: var(--bg-3); color: var(--txt); }
.cfg-aba[aria-selected="true"] { background: var(--acento); color: #fff; }
.cfg-aba:focus-visible { outline: 2px solid var(--acento); outline-offset: 2px; }
/* algo pedindo atenção lá dentro (infraestrutura, backup), visível com a aba fechada */
.cfg-aba-ponto {
  width: 8px; height: 8px; flex: 0 0 auto; border-radius: 50%;
  background: var(--alerta); box-shadow: 0 0 0 2px var(--bg-2);
}
.cfg-aba-ponto.erro { background: var(--erro); }
.cfg-painel { display: flex; flex-direction: column; gap: 16px; min-width: 0; }
.cfg-painel[hidden] { display: none; }
/* Nuvem e custos: a lista de clientes (que cresce) à esquerda, a conexão (fixa) à direita */
.cfg-nuvem { display: grid; grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr); gap: 16px; align-items: start; }
/* Sistema e backup: lado a lado */
.cfg-duas { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px; align-items: start; }
@media (max-width: 1180px) {
  .cfg-nuvem, .cfg-duas { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 600px) {
  /* as três abas cabem sem rolar: ícone em cima, nome embaixo */
  .cfg-abas { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); width: 100%; }
  .cfg-aba { flex-direction: column; gap: 4px; padding: 8px 4px; font-size: 12px; white-space: normal; text-align: center; }
  .cfg-aba-ponto { position: absolute; top: 6px; right: 8px; }
}

.cfg-card {
  background: linear-gradient(160deg, var(--bg-2), var(--bg));
  border: 1px solid var(--linha);
  border-radius: var(--raio-grande);
  padding: 18px 20px 20px;
  min-width: 0;
  transition: border-color .15s ease;
}
.cfg-card:hover { border-color: #3a4656; }
.cfg-card [hidden] { display: none !important; }
.cfg-cab { display: flex; align-items: flex-start; gap: 14px; margin-bottom: 12px; }
.cfg-cab-icone { color: var(--acento); flex: 0 0 auto; }
.cfg-cab-icone .ic { width: 30px; height: 30px; }
.cfg-cab-texto { flex: 1; min-width: 0; }
.cfg-cab-texto h3 { margin: 0; font-size: 16px; font-weight: 700; }
.cfg-cab-texto p { margin: 4px 0 0; font-size: 12px; line-height: 1.5; color: var(--txt-2); }
.cfg-sub { margin: 16px 0 0; font-size: 13.5px; font-weight: 700; }
.cfg-card label { margin: 11px 0 5px; font-size: 12.5px; }
.cfg-card .dica { line-height: 1.5; }
.cfg-nota { margin: 4px 0 0; font-size: 11.5px; }

/* selo de estado no canto do cartão (Infraestrutura: Operacional / Atenção / Fora do ar) */
.cfg-selo-status {
  display: inline-flex; align-items: center; gap: 6px; flex: 0 0 auto;
  padding: 4px 10px; border-radius: 999px; font-size: 11.5px; font-weight: 600; white-space: nowrap;
  background: rgba(63, 185, 80, .14); color: var(--ok); border: 1px solid rgba(63, 185, 80, .35);
}
.cfg-selo-status .ic { width: 14px; height: 14px; }
.cfg-selo-status.alerta { background: rgba(210, 153, 34, .14); color: var(--alerta); border-color: rgba(210, 153, 34, .4); }
.cfg-selo-status.erro { background: rgba(240, 93, 93, .14); color: var(--erro); border-color: rgba(240, 93, 93, .4); }

/* formulário em duas colunas; `.largo` ocupa a linha inteira */
.cfg-form { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 12px; }
.cfg-form > .largo { grid-column: 1 / -1; }
.cfg-form.cfg-host-porta { grid-template-columns: minmax(0, 1fr) 110px; }
@media (max-width: 480px) {
  .cfg-form { grid-template-columns: minmax(0, 1fr); }
  .cfg-form.cfg-host-porta { grid-template-columns: minmax(0, 1fr) 90px; }
}

/* campo de senha com o "olho" do login (mesmos estados .ic-mostrar/.ic-ocultar de `.olho`) */
.campo-senha { position: relative; }
.campo-senha input { padding-right: 40px; }
.campo-senha .olho { position: absolute; right: 6px; top: 50%; transform: translateY(-50%); }
.campo-senha .olho svg { width: 17px; height: 17px; }

/* interruptor (liga/desliga): a caixa de marcar de sempre, só desenhada como chave */
label.interruptor {
  display: flex; align-items: center; gap: 10px; width: fit-content;
  margin: 16px 0 4px; color: var(--txt); font-size: 13px; cursor: pointer;
}
.interruptor input {
  appearance: none; -webkit-appearance: none; margin: 0; flex: 0 0 auto;
  position: relative; width: 38px; height: 22px; border-radius: 999px; cursor: pointer;
  background: var(--bg-3); border: 1px solid var(--linha);
  transition: background-color .15s ease, border-color .15s ease;
}
.interruptor input::before {
  content: ""; position: absolute; top: 2px; left: 2px; width: 16px; height: 16px;
  border-radius: 50%; background: var(--txt-2); transition: transform .15s ease, background-color .15s ease;
}
.interruptor input:checked { background: var(--acento); border-color: var(--acento); }
.interruptor input:checked::before { transform: translateX(16px); background: #fff; }
.interruptor input:focus-visible { outline: 2px solid var(--acento); outline-offset: 2px; }

/* botões desta tela: primário com texto branco, secundário e perigo contornados */
.cfg-card .btn { border: 1px solid transparent; border-radius: 7px; padding: 7px 13px; font-size: 13px; }
.cfg-card .btn.pequeno { padding: 5px 10px; font-size: 12.5px; }
.cfg-card .btn:not(.secundario):not(.perigo) { color: #fff; }
.cfg-card .btn.secundario { background: transparent; border-color: #3a4656; color: var(--txt); }
.cfg-card .btn.secundario:hover { filter: none; border-color: var(--acento); background: rgba(47, 126, 230, .08); }
.cfg-card .btn.perigo { background: transparent; border-color: rgba(240, 93, 93, .55); color: var(--erro); }
.cfg-card .btn.perigo:hover { filter: none; background: rgba(240, 93, 93, .1); }
.btn.com-icone { display: inline-flex; align-items: center; gap: 7px; }
.btn.com-icone .ic { width: 15px; height: 15px; }
.cfg-link {
  background: none; border: 0; padding: 0; flex: 0 0 auto; cursor: pointer;
  color: var(--acento); font: inherit; font-size: 12px; text-decoration: underline;
}

/* seletor de arquivo nativo, no tom da tela (e no diálogo "Minha foto", `conta.js`) */
.cfg-arquivo, .conta-arquivo { width: 100%; max-width: 100%; font-size: 12px; color: var(--txt-2); }
.cfg-arquivo::file-selector-button, .conta-arquivo::file-selector-button {
  margin-right: 10px; padding: 6px 12px; border-radius: 6px; cursor: pointer;
  border: 1px solid #3a4656; background: var(--bg-3); color: var(--txt); font: inherit; font-size: 12px;
}
.cfg-arquivo::file-selector-button:hover,
.conta-arquivo::file-selector-button:hover { border-color: var(--acento); }

/* Identidade visual: nome, logotipo e favicon lado a lado (a aba tem a largura inteira) */
.cfg-linha-campo { display: flex; gap: 10px; }
.cfg-linha-campo input { flex: 1; min-width: 0; }
.cfg-marca { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 0 20px; }
.cfg-marca-item { min-width: 0; }
.cfg-marca-item + .cfg-marca-item { border-left: 1px solid var(--linha); padding-left: 20px; }
@media (max-width: 1100px) {
  .cfg-marca { grid-template-columns: minmax(0, 1fr); gap: 4px; }
  .cfg-marca-item + .cfg-marca-item { border-left: 0; padding-left: 0; border-top: 1px solid var(--linha); padding-top: 4px; }
}
.cfg-marca-corpo { display: flex; gap: 12px; align-items: flex-start; }
.cfg-marca-acoes { flex: 1; min-width: 0; }
.cfg-marca-acoes .linha-botoes { margin-top: 8px; }
/* prévia no fundo ESCURO: é onde o logotipo aparece (menu lateral e login) */
.cfg-previa {
  width: 64px; height: 64px; flex: 0 0 auto; border-radius: 12px; overflow: hidden;
  display: grid; place-items: center; background: var(--bg); border: 1px solid var(--linha);
}
.cfg-previa.favicon { width: 48px; height: 48px; border-radius: 10px; }
.cfg-previa img { max-width: 86%; max-height: 86%; object-fit: contain; }
.cfg-previa-vazio { display: grid; place-items: center; color: var(--acento); }
.cfg-previa-vazio .ic { width: 30px; height: 30px; }
.cfg-previa.favicon .cfg-previa-vazio .ic { width: 24px; height: 24px; }

/* estado do backup: verde (ok), âmbar (último ok, mas a tentativa seguinte falhou), vermelho */
.cfg-estado {
  display: flex; gap: 10px; align-items: flex-start; margin-top: 14px; padding: 11px 13px;
  border: 1px solid var(--linha); border-radius: 9px; font-size: 12px; line-height: 1.5;
}
.cfg-estado > .ic { width: 18px; height: 18px; flex: 0 0 auto; margin-top: 1px; color: var(--txt-2); }
.cfg-estado-texto { flex: 1; min-width: 0; overflow-wrap: anywhere; }
.cfg-estado .cfg-link { align-self: flex-end; }
.cfg-estado.ok { background: rgba(63, 185, 80, .08); border-color: rgba(63, 185, 80, .4); }
.cfg-estado.ok > .ic { color: var(--ok); }
.cfg-estado.alerta { background: rgba(210, 153, 34, .08); border-color: rgba(210, 153, 34, .45); }
.cfg-estado.alerta > .ic { color: var(--alerta); }
.cfg-estado.erro { background: rgba(240, 93, 93, .08); border-color: rgba(240, 93, 93, .5); color: #ffc2c2; }
.cfg-estado.erro > .ic { color: var(--erro); }

/* Infraestrutura: quatro cartões pequenos + tabela de componentes */
.cfg-minis { display: grid; grid-template-columns: repeat(auto-fit, minmax(135px, 1fr)); gap: 8px; }
.cfg-mini { min-width: 0; padding: 10px 11px; border: 1px solid var(--linha); border-radius: 9px; background: rgba(0, 0, 0, .14); }
.cfg-mini-rot { font-size: 11px; line-height: 1.3; min-height: 2.6em; color: var(--txt-2); }
.cfg-mini-val { display: flex; align-items: center; gap: 6px; margin-top: 4px; font-size: 16px; font-weight: 700; font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }
.cfg-mini-val .ic { width: 16px; height: 16px; flex: 0 0 auto; }
.cfg-mini-val.ok { color: var(--ok); }
.cfg-mini-val.erro { color: var(--erro); }
.cfg-mini-val.pequeno { font-size: 12.5px; }
.cfg-tabela { margin-top: 8px; border: 1px solid var(--linha); border-radius: 9px; overflow: hidden; }
.cfg-tabela table { font-size: 12px; }
.cfg-tabela th { font-size: 11.5px; background: rgba(0, 0, 0, .18); }
.cfg-tabela tr:last-child td { border-bottom: 0; }
.cfg-tabela td.dica { margin: 0; font-size: 11.5px; overflow-wrap: anywhere; }
.cfg-status { display: inline-flex; align-items: center; gap: 5px; font-weight: 600; }
.cfg-status .ic { width: 14px; height: 14px; }
.cfg-status.ok { color: var(--ok); }
.cfg-status.erro { color: var(--erro); }

/* Uso do B2: quatro números na largura inteira */
.cfg-uso .cfg-cab, .cfg-custo-clientes .cfg-cab { align-items: center; }
.cfg-uso .cfg-cab-icone .ic, .cfg-custo-clientes .cfg-cab-icone .ic { width: 24px; height: 24px; }
.cfg-uso > .dica { margin: 12px 0 0; }
.cfg-rapidas-grade { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 12px; }
.cfg-rapida {
  display: flex; gap: 12px; min-width: 0; padding: 14px; border: 1px solid var(--linha);
  border-radius: 11px; background: rgba(0, 0, 0, .14);
  transition: transform .15s ease, border-color .15s ease;
}
.cfg-rapida:hover { transform: translateY(-2px); border-color: var(--acento); }
.cfg-rapida-icone { color: var(--acento); flex: 0 0 auto; }
.cfg-rapida-icone .ic { width: 24px; height: 24px; }
.cfg-rapida-corpo { flex: 1; min-width: 0; }
.cfg-rapida-rot { font-size: 11.5px; color: var(--txt-2); }
.cfg-rapida-val { margin: 4px 0 6px; font-size: 19px; font-weight: 700; font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }
.cfg-rapida-val.ok { color: var(--ok); }
.cfg-rapida-sub { font-size: 11px; line-height: 1.5; color: var(--txt-2); }
.cfg-barra { height: 5px; margin: 2px 0 7px; border-radius: 999px; background: var(--bg-3); overflow: hidden; }
.cfg-barra > span { display: block; height: 100%; border-radius: inherit; background: var(--acento); }
@media (max-width: 1100px) { .cfg-rapidas-grade { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 520px) { .cfg-rapidas-grade { grid-template-columns: minmax(0, 1fr); } }

/* Custo por cliente: tabela que cresce para baixo, com filtro e "mostrar todos" */
.cfg-busca { flex: 0 1 220px; }
.cfg-busca input[type="search"] { width: 100%; }
.cfg-clientes { margin-top: 0; }
.cfg-clientes table { font-size: 12.5px; }
.cfg-clientes .cfg-num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.cfg-clientes .cfg-num.forte { font-weight: 700; color: var(--txt); }
.cfg-clientes td.cfg-cliente { max-width: 0; width: 34%; overflow: hidden; font-weight: 600; text-overflow: ellipsis; white-space: nowrap; }
.cfg-clientes tbody tr:hover td { background: rgba(47, 126, 230, .06); }
.cfg-clientes tfoot td { border-top: 1px solid var(--linha); border-bottom: 0; background: rgba(0, 0, 0, .18); font-weight: 700; }
.cfg-part { width: 20%; white-space: nowrap; text-align: right; }
.cfg-part .cfg-barra { display: inline-block; width: calc(100% - 52px); max-width: 120px; margin: 0 8px 0 0; vertical-align: middle; }
.cfg-part > span { display: inline-block; min-width: 40px; color: var(--txt-2); font-variant-numeric: tabular-nums; }
.cfg-clientes-pe .cfg-link { margin-top: 10px; }
@media (max-width: 560px) {
  /* no celular sai o que é detalhe (arquivos, participação); nome, volume e custo ficam */
  .cfg-clientes .opc { display: none; }
  .cfg-clientes td.cfg-cliente { width: auto; }
  .cfg-custo-clientes .cfg-cab { flex-wrap: wrap; }
  .cfg-busca { flex-basis: 100%; }
}

/* ================================================================== menu da conta (26/09/2026)
   Nome e foto no canto superior direito abrem "Conta e segurança", "Minha foto" e "Sair"
   (`conta.js`). Prefixo `conta-`. */
.conta-gatilho {
  display: inline-flex; align-items: center; gap: 9px; max-width: 250px; height: 42px; padding: 0 10px 0 4px;
  border: 1px solid transparent; border-radius: 999px; background: transparent; color: var(--txt);
  font: inherit; font-size: 13px; cursor: pointer;
}
.conta-gatilho:hover, .usuario.aberto .conta-gatilho { background: var(--bg-3); border-color: var(--linha); }
.conta-gatilho:focus-visible { outline: 2px solid var(--acento); outline-offset: 2px; }
.conta-nome { overflow: hidden; font-weight: 600; text-overflow: ellipsis; white-space: nowrap; }
.conta-seta { flex: 0 0 auto; width: 14px; height: 14px; color: var(--txt-2); transform: rotate(90deg); transition: transform .15s; }
.usuario.aberto .conta-seta { transform: rotate(-90deg); }
/* a foto, ou as iniciais quando não há */
.conta-avatar {
  display: grid; place-items: center; flex: 0 0 auto; width: 34px; height: 34px; overflow: hidden;
  border: 1px solid var(--linha); border-radius: 50%; background: linear-gradient(145deg, #2a3d5c, #1b2434);
}
.conta-avatar img { width: 100%; height: 100%; object-fit: cover; }
.conta-iniciais { font-size: 12.5px; font-weight: 700; color: #cfe0ff; letter-spacing: .02em; }
.conta-avatar.grande { width: 46px; height: 46px; }
.conta-avatar.grande .conta-iniciais { font-size: 16px; }
.conta-avatar.enorme { width: 96px; height: 96px; }
.conta-avatar.enorme .conta-iniciais { font-size: 30px; }

.conta-menu {
  position: absolute; top: calc(100% + 8px); right: 0; z-index: 60; width: 280px; padding: 8px;
  background: var(--bg-2); border: 1px solid var(--linha); border-radius: 12px;
  box-shadow: 0 16px 36px rgba(0, 0, 0, .5);
}
.conta-menu[hidden] { display: none; }
.conta-cab {
  display: flex; align-items: center; gap: 12px; margin-bottom: 6px; padding: 8px 8px 12px;
  border-bottom: 1px solid var(--linha);
}
.conta-cab-texto { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.conta-cab-texto strong { overflow: hidden; color: var(--txt); text-overflow: ellipsis; white-space: nowrap; }
.conta-cab-texto .dica { margin: 0; font-size: 12px; }
.conta-cab-texto .dica:empty { display: none; }
.conta-papel {
  align-self: flex-start; margin-top: 3px; padding: 1px 8px; border-radius: 999px;
  background: rgba(210, 153, 34, .14); color: var(--alerta); font-size: 10.5px;
}
.conta-item {
  display: flex; align-items: center; gap: 10px; width: 100%; padding: 9px 10px; border: 0; border-radius: 8px;
  background: transparent; color: var(--txt); font: inherit; font-size: 13px; text-align: left; cursor: pointer;
}
.conta-item .ic { width: 17px; height: 17px; color: var(--txt-2); }
.conta-item:hover, .conta-item:focus-visible { background: var(--bg-3); outline: none; }
.conta-item:hover .ic, .conta-item:focus-visible .ic { color: var(--acento); }
.conta-sep { margin: 6px 0; border: 0; border-top: 1px solid var(--linha); }
/* o que é do sistema, não da conta (só administrador) */
.conta-secao { padding: 4px 10px 2px; font-size: 10.5px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--txt-2); }

/* os diálogos da conta */
dialog.dlg-conta { max-width: 460px; }
.det-sub.primeiro { margin-top: 0; }
.conta-2fa { display: flex; align-items: flex-start; gap: 8px; margin: 0; }
.conta-2fa .ic { flex: 0 0 auto; width: 16px; height: 16px; margin-top: 2px; color: var(--acento); }
.conta-foto { display: flex; align-items: center; gap: 18px; margin-bottom: 10px; }
.conta-foto-lado { flex: 1; min-width: 0; }
.conta-foto-lado .dica { margin: 8px 0 0; }
/* Avisos por e-mail: formulário em duas colunas, mais largo que os outros diálogos da conta */
dialog.dlg-email { max-width: 640px; }
.conta-form { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 12px; }
.conta-form > .largo { grid-column: 1 / -1; }
.conta-form.conta-host-porta { grid-template-columns: minmax(0, 1fr) 110px; }
.dlg-email label.interruptor { margin-top: 14px; }
.conta-detalhes { margin: 8px 0 4px; font-size: 12.5px; }
.conta-detalhes summary { color: var(--acento); cursor: pointer; }
.conta-detalhes .dica { margin: 6px 0 0; line-height: 1.5; }
@media (max-width: 600px) {
  .conta-nome { display: none; }
  .conta-gatilho { padding: 0 6px 0 4px; }
  .conta-foto { flex-direction: column; align-items: flex-start; }
  .conta-form { grid-template-columns: minmax(0, 1fr); }
  .conta-form.conta-host-porta { grid-template-columns: minmax(0, 1fr) 90px; }
}

/* ================================================================== Ao vivo (25/09/2026)
   Redesenho a partir de uma referência do usuário: filtros no topo, ferramentas, a grade com o
   cabeçalho de cada câmera FORA da imagem e a imagem esticada até a borda (sem faixa preta), a
   lista de câmeras e o PTZ à direita e a linha do tempo de hoje embaixo. Prefixo `av-`. */
.av-tela { display: flex; flex-direction: column; gap: 8px; height: 100%; min-height: 0; }
.av-filtros, .av-ferramentas, .av-painel {
  background: linear-gradient(160deg, var(--bg-2), var(--bg));
  border: 1px solid var(--linha);
  border-radius: 12px;
}
/* compactos (25/09): cada pixel de altura aqui é altura a menos para o vídeo */
.av-filtros { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; padding: 7px 12px; }
.av-campo { display: flex; align-items: center; gap: 8px; }
.av-campo label { margin: 0; font-size: 12px; color: var(--txt-2); }
.av-campo select { width: 230px; height: 34px; padding: 0 10px; }
.av-busca {
  display: flex; align-items: center; gap: 8px; height: 34px; margin: 0; padding: 0 10px;
  min-width: 230px; border: 1px solid var(--linha); border-radius: 7px; background: var(--bg); cursor: text;
}
.av-busca:focus-within { border-color: var(--acento); }
.av-busca .ic { width: 16px; height: 16px; color: var(--txt-2); flex: 0 0 auto; }
.av-busca input { flex: 1; min-width: 0; padding: 0; border: 0; background: none; color: var(--txt); font: inherit; outline: none; }
.av-aviso-escolha { align-self: center; margin: 0; }
.av-relogio {
  display: flex; align-items: center; gap: 8px; height: 34px; padding: 0 12px;
  border: 1px solid var(--linha); border-radius: 7px; background: var(--bg);
  font-size: 13px; font-variant-numeric: tabular-nums; white-space: nowrap;
}
.av-relogio .ic { width: 16px; height: 16px; color: var(--acento); }
.av-selo-vivo {
  display: inline-flex; align-items: center; gap: 7px; height: 34px; padding: 0 12px;
  border: 1px solid var(--linha); border-radius: 7px; background: var(--bg-3);
  color: var(--txt-2); font-size: 12.5px; font-weight: 600; white-space: nowrap;
}
.av-selo-ponto { width: 8px; height: 8px; border-radius: 50%; background: var(--txt-2); }
.av-selo-vivo.ativo { background: rgba(63, 185, 80, .14); color: var(--ok); border-color: rgba(63, 185, 80, .4); }
.av-selo-vivo.ativo .av-selo-ponto { background: var(--ok); animation: pulsa 1.6s infinite; }

.av-corpo { display: flex; gap: 8px; flex: 1 1 auto; min-height: 0; }
.av-principal { display: flex; flex-direction: column; gap: 8px; flex: 1 1 auto; min-width: 0; min-height: 0; }
.av-lateral { display: flex; flex-direction: column; gap: 8px; flex: 0 0 290px; min-height: 0; }
/* o palco ocupa a altura que sobra; a grade dentro dele tem o tamanho em 16:9 calculado em
   `grade.js` (ajustarPalco) e fica centralizada — nunca um quadro achatado */
.av-palco { display: flex; align-items: center; justify-content: center; flex: 1 1 0; min-height: 0; overflow: hidden; }
.av-palco > .grade { flex: 0 0 auto; }
.av-palco:fullscreen { background: var(--bg); padding: 8px; }

/* barra de ferramentas */
.av-ferramentas { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; padding: 6px 8px; }
.av-grupo-bt { display: flex; gap: 6px; }
.av-botao {
  display: inline-flex; align-items: center; gap: 7px; height: 32px; padding: 0 12px;
  border: 1px solid #3a4656; border-radius: 7px; background: transparent; color: var(--txt);
  font: inherit; font-size: 12.5px; white-space: nowrap; cursor: pointer; list-style: none;
}
.av-botao::-webkit-details-marker { display: none; }
.av-botao:hover { border-color: var(--acento); background: rgba(47, 126, 230, .08); }
.av-botao .ic { width: 16px; height: 16px; }
.av-botao.so-icone { width: 32px; padding: 0; justify-content: center; }
.av-botao.so-icone.pequeno { width: 28px; height: 28px; margin-left: 4px; }
.av-botao.anterior .ic { transform: rotate(180deg); }
.av-botao[disabled] { opacity: .45; pointer-events: none; }
.av-segmentos { display: flex; overflow: hidden; border: 1px solid #3a4656; border-radius: 8px; }
.av-seg {
  height: 32px; padding: 0 14px; border: 0; border-right: 1px solid #3a4656;
  background: transparent; color: var(--txt); font: inherit; font-size: 12.5px; cursor: pointer;
}
.av-seg:last-child { border-right: 0; }
.av-seg:hover { background: rgba(47, 126, 230, .1); }
.av-seg.ativo { background: var(--acento); color: #fff; font-weight: 600; }
.av-seg[disabled] { opacity: .45; pointer-events: none; }
.av-paginas { display: flex; align-items: center; gap: 6px; }
.av-pagina { min-width: 34px; text-align: center; font-size: 12px; color: var(--txt-2); font-variant-numeric: tabular-nums; }

/* menus suspensos: <details> nativo */
.av-menu { position: relative; }
.av-menu > summary { user-select: none; }
.av-menu[open] > summary { border-color: var(--acento); }
.av-menu-corpo {
  position: absolute; right: 0; top: calc(100% + 6px); z-index: 30; min-width: 260px; padding: 8px;
  background: var(--bg-2); border: 1px solid var(--linha); border-radius: 10px;
  box-shadow: 0 14px 30px rgba(0, 0, 0, .45);
}
.av-menu-lista { display: flex; flex-direction: column; gap: 2px; }
.av-menu-lista hr { width: 100%; margin: 6px 0; border: 0; border-top: 1px solid var(--linha); }
.av-menu-item {
  padding: 8px 10px; border: 0; border-radius: 6px; background: transparent; color: var(--txt);
  font: inherit; font-size: 13px; text-align: left; cursor: pointer;
}
.av-menu-item:hover { background: var(--bg-3); }
.av-menu-item.ativo { color: var(--acento); font-weight: 600; }
.av-menu-item.perigo { color: var(--erro); }
.av-menu-item[disabled] { opacity: .45; cursor: default; }
.av-menu-lista label.interruptor { margin: 8px 4px 4px; }
.av-menu-lista .dica { margin: 0 4px 6px 52px; }

/* a grade do Ao vivo: cabeçalho fora da imagem, ações no canto de baixo */
.av-grade { gap: 8px; }
/* `container-type`: o cabeçalho decide o que mostrar pela largura do PRÓPRIO quadro (abaixo) */
.av-grade .tile {
  flex-direction: column; align-items: stretch; background: var(--bg-2); border-radius: 10px;
  container-type: inline-size;
}
.av-grade .tile > .vazio { margin: auto; }
/* a altura vem de `ajustarPalco` (grade.js), que usa o MESMO número na conta do 16:9 */
.av-grade .tile .rotulo {
  position: static; flex: 0 0 auto; height: var(--av-rotulo, 30px); padding: 0 10px; border-radius: 0;
  background: linear-gradient(180deg, #1c2330, #161b24); border-bottom: 1px solid var(--linha); font-size: 12.5px;
}
.av-grade .tile .rotulo .nome { font-weight: 700; }
.av-grade .tile .rotulo .estado-txt { padding: 2px 8px; border-radius: 999px; background: var(--bg-3); font-size: 10.5px; }
.av-grade .tile .rotulo .estado-txt:empty, .av-grade .tile .rotulo .fluxo:empty { display: none; }
.av-grade.compacta .tile .rotulo { gap: 6px; padding: 0 8px; font-size: 11.5px; }
.av-grade.compacta .tile .rotulo .estado-txt { padding: 1px 6px; font-size: 10px; }
.av-grade.compacta .tile .acoes { bottom: 6px; right: 6px; gap: 4px; }
.av-grade.compacta .tile .acoes button { width: 26px; height: 26px; }
/* o quadro em destaque ocupa k×k células; k vem do arranjo escolhido em `ajustarPalco` */
.av-grade.l1-5 > .tile:first-child { grid-column: span var(--av-destaque, 2); grid-row: span var(--av-destaque, 2); }
.av-grade.l1-7 > .tile:first-child { grid-column: span var(--av-destaque, 3); grid-row: span var(--av-destaque, 3); }
.av-grade .tile .rotulo .ponto.ok ~ .estado-txt { color: var(--ok); background: rgba(63, 185, 80, .14); }
.av-grade .tile .rotulo .ponto.offline ~ .estado-txt { color: var(--erro); background: rgba(240, 93, 93, .14); }
.av-grade .tile .rotulo .ponto.instavel ~ .estado-txt,
.av-grade .tile .rotulo .ponto.conectando ~ .estado-txt { color: var(--alerta); background: rgba(210, 153, 34, .14); }
.av-grade .tile .rotulo .relogio {
  display: inline; flex: 0 0 auto; margin-left: auto; color: var(--txt-2); font-size: 11px;
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
/* o NOME tem prioridade: quem sai primeiro é o que se repete (o fluxo, a data, a hora — o relógio
   do topo já mostra os dois); o estado sai por último, e o ponto colorido continua dizendo ele.
   Fica DEPOIS das regras do cabeçalho: @container não soma especificidade, vence a última regra. */
@container (max-width: 440px) { .av-grade .tile .rotulo .fluxo { display: none; } }
@container (max-width: 360px) { .av-grade .tile .rotulo .rel-data { display: none; } }
@container (max-width: 240px) { .av-grade .tile .rotulo .relogio { display: none; } }
@container (max-width: 170px) { .av-grade .tile .rotulo .estado-txt { display: none; } }
.av-grade .tile .tile-quadro { position: relative; inset: auto; flex: 1 1 auto; min-height: 0; background: #000; }
.av-grade .tile .acoes { top: auto; bottom: 8px; right: 8px; }
.av-grade .tile.selecionado .acoes { display: flex; }
.av-grade .tile .acoes button {
  width: 30px; height: 30px; border-radius: 7px;
  background: rgba(10, 14, 20, .72); border: 1px solid rgba(255, 255, 255, .12);
}
.av-grade .tile .mensagem { inset: auto 8px 46px 8px; }
.av-grade .tile.selecionado { border-color: var(--acento); box-shadow: 0 0 0 1px var(--acento); }
/* imagem até a borda, sem faixa preta — esticada, nunca recortada (o carimbo do DVR é prova) */
.av-grade.preencher .tile video,
.av-grade.preencher .tile canvas.congelado { object-fit: fill; }
@media (hover: none) { .av-grade .tile .acoes { display: flex; } }

/* painéis da direita e de baixo */
.av-painel { padding: 10px 12px; min-height: 0; }
.av-painel-cab { display: flex; align-items: center; gap: 8px; margin-bottom: 10px; }
.av-painel-cab h3 { margin: 0; font-size: 14px; font-weight: 700; }
.av-painel-cab > .ic { width: 18px; height: 18px; color: var(--acento); flex: 0 0 auto; }
.av-contagem { margin-left: auto; font-size: 11.5px; color: var(--txt-2); }

.av-cameras { display: flex; flex-direction: column; flex: 1 1 auto; min-height: 160px; }
.av-cam-lista { flex: 1 1 auto; min-height: 0; margin: 0; padding: 0; overflow: auto; list-style: none; }
.av-cam {
  display: flex; align-items: center; gap: 10px; width: 100%; padding: 8px; border: 0; border-radius: 8px;
  background: transparent; color: var(--txt); font: inherit; text-align: left; cursor: pointer;
}
.av-cam:hover { background: var(--bg-3); }
.av-cam-lista li.selecionada .av-cam { background: rgba(47, 126, 230, .14); box-shadow: inset 3px 0 0 var(--acento); }
.av-cam .ponto { flex: 0 0 auto; width: 9px; height: 9px; }
.av-cam-texto { display: flex; flex-direction: column; flex: 1; min-width: 0; }
.av-cam-nome { overflow: hidden; font-size: 12.5px; font-weight: 600; text-overflow: ellipsis; white-space: nowrap; }
.av-cam-sub { overflow: hidden; font-size: 10.5px; color: var(--txt-2); text-overflow: ellipsis; white-space: nowrap; }
.av-chip { flex: 0 0 auto; padding: 2px 8px; border-radius: 999px; background: var(--bg-3); color: var(--txt-2); font-size: 10.5px; white-space: nowrap; }
.av-chip.ok { background: rgba(63, 185, 80, .14); color: var(--ok); }
.av-chip.offline { background: rgba(240, 93, 93, .14); color: var(--erro); }
.av-chip.instavel, .av-chip.conectando { background: rgba(210, 153, 34, .14); color: var(--alerta); }
.av-cam-vazia { padding: 8px; }

/* PTZ: manter pressionado move, soltar para */
.av-ptz { flex: 0 0 auto; }
.av-ptz[hidden] { display: none; }
.av-ptz-alvo { max-width: 60%; margin-left: auto; overflow: hidden; font-size: 11.5px; color: var(--txt-2); text-overflow: ellipsis; white-space: nowrap; }
.av-ptz-corpo.inativo > :not(.av-ptz-msg) { opacity: .4; pointer-events: none; }
.av-ptz-linha { display: flex; align-items: center; gap: 14px; }
.av-ptz-pad {
  display: grid; grid-template-columns: repeat(3, 32px); grid-template-rows: repeat(3, 32px); gap: 2px;
  padding: 6px; border: 1px solid var(--linha); border-radius: 50%;
  background: radial-gradient(circle, var(--bg-3), var(--bg));
}
.av-ptz-bt {
  display: grid; place-items: center; width: 32px; height: 32px; padding: 0;
  border: 1px solid transparent; border-radius: 8px; background: transparent; color: var(--txt);
  cursor: pointer; touch-action: none; user-select: none;
}
.av-ptz-bt:hover { background: rgba(47, 126, 230, .14); }
.av-ptz-bt.ativo { background: var(--acento); color: #fff; }
.av-ptz-bt .ic { width: 16px; height: 16px; transform: rotate(var(--giro, 0deg)); }
.av-ptz-centro { display: grid; place-items: center; color: var(--acento); }
.av-ptz-centro .ic { width: 16px; height: 16px; }
.av-ptz-lado { display: flex; flex-direction: column; gap: 8px; flex: 1; min-width: 0; }
.av-ptz-par { display: flex; align-items: center; gap: 4px; }
.av-ptz-par .av-ptz-bt { width: 34px; height: 30px; border-color: #3a4656; }
.av-ptz-rot { display: block; min-width: 38px; margin: 0; font-size: 11.5px; color: var(--txt-2); }
.av-ptz-corpo > label.av-ptz-rot { margin: 10px 0 2px; }
.av-ptz-corpo input[type="range"] { width: 100%; accent-color: var(--acento); }
.av-ptz-preset { display: flex; gap: 6px; margin-top: 8px; }
.av-ptz-preset select { flex: 1; min-width: 0; height: 34px; padding: 0 10px; }
.av-ptz-msg { min-height: 1em; margin: 6px 0 0; }
.av-ptz > .dica { margin: 6px 0 0; font-size: 11px; }

/* linha do tempo de hoje da câmera escolhida */
.av-linha { flex: 0 0 auto; }
.av-linha .av-painel-cab { flex-wrap: wrap; margin-bottom: 6px; }
.av-linha.recolhida .av-painel-cab { margin-bottom: 0; }
.av-linha.recolhida .av-tl-marcas, .av-linha.recolhida .av-tl-barra { display: none; }
.av-recolher .ic { transform: rotate(90deg); }
.av-linha.recolhida .av-recolher .ic { transform: rotate(-90deg); }
.av-linha .av-painel-cab .dica { margin: 0; }
.av-tl-camera { font-size: 12.5px; font-weight: 600; }
.av-tl-dia {
  display: inline-flex; align-items: center; gap: 6px; padding: 3px 9px;
  border: 1px solid var(--linha); border-radius: 6px; font-size: 12px; font-variant-numeric: tabular-nums;
}
.av-tl-dia .ic { width: 14px; height: 14px; color: var(--txt-2); }
.av-tl-marcas { position: relative; height: 15px; margin-bottom: 3px; font-size: 10.5px; color: var(--txt-2); font-variant-numeric: tabular-nums; }
.av-tl-marcas span { position: absolute; top: 0; }
.av-tl-barra {
  position: relative; height: 24px; overflow: hidden; cursor: pointer;
  border: 1px solid var(--linha); border-radius: 6px; background: var(--bg);
}
.av-tl-seg { position: absolute; top: 6px; bottom: 3px; border-radius: 2px; }
.av-tl-seg.cont, .av-tl-cor.cont { background: var(--acento); }
.av-tl-seg.mov, .av-tl-cor.mov { background: var(--alerta); }
.av-tl-seg.fraco, .av-tl-cor.fraco { background: rgba(210, 153, 34, .35); }
.av-tl-seg.perdido { background: repeating-linear-gradient(45deg, var(--erro), var(--erro) 3px, transparent 3px, transparent 6px); opacity: .5; }
.av-tl-evt { position: absolute; top: 0; height: 4px; min-width: 2px; border-radius: 0 0 2px 2px; background: var(--alerta); }
.av-tl-cor.evt { background: var(--alerta); height: 4px; border-radius: 2px; }
.av-tl-agulha { position: absolute; top: 0; bottom: 0; width: 2px; background: #fff; box-shadow: 0 0 0 1px rgba(47, 126, 230, .8); pointer-events: none; }
.av-tl-legendas { display: flex; flex-wrap: wrap; gap: 14px; margin-right: 6px; font-size: 11.5px; color: var(--txt-2); }
.av-tl-leg { display: inline-flex; align-items: center; gap: 6px; }
.av-tl-cor { display: inline-block; width: 10px; height: 10px; border-radius: 50%; }

.av-menu.ligado > summary { border-color: var(--acento); color: var(--acento); }

@media (max-width: 1200px) { .av-lateral { flex-basis: 250px; } }
/* notebook de 1280–1366 px: as barras quebravam em duas linhas e tiravam ~75 px da grade. Os menus
   (Vistas, Rotação, Exibição) ficam só com o ícone — o nome continua na dica e no leitor de tela —
   e a legenda da linha do tempo perde o complemento. As ações principais mantêm o texto. */
@media (max-width: 1360px) {
  .av-menu > summary.av-botao { width: 32px; padding: 0; justify-content: center; }
  .av-menu > summary.av-botao > span { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }
  .av-tl-leg-extra { display: none; }
}
/* tablet e celular: tudo empilhado, a página rola (a grade deixa de dividir a altura da tela) */
@media (max-width: 900px) {
  main.sem-scroll { overflow: auto; }
  .av-tela { height: auto; }
  .av-corpo { flex-direction: column; }
  .av-lateral { flex: 0 0 auto; }
  .av-palco { flex: 0 0 auto; overflow: visible; }
  .av-cameras { max-height: 360px; }
}
@media (max-width: 600px) {
  .av-filtros { align-items: stretch; }
  .av-filtros .espaco { display: none; }
  .av-campo, .av-busca { width: 100%; min-width: 0; }
  .av-campo select { flex: 1; width: auto; min-width: 0; }
  .av-grade .tile .rotulo .relogio, .av-grade .tile .rotulo .fluxo { display: none; }
  .av-tl-marcas span:nth-child(even) { display: none; } /* de 4 em 4 horas: 12 rótulos não cabem */
}

/* ============================================================================================
   DVRs — redesenho de 28/09/2026 (modelo do usuário): indicadores coloridos com subtítulo,
   barra de filtros em cartão, lista ou grade, ordenação, paginação e o menu "⋮".
   Prefixo próprio (dvr-): as regras compartilhadas (.kpi, .filtro-campo) só ganham
   modificadores aqui, nunca mudam para as outras telas.
   ============================================================================================ */

/* indicadores: a cor diz o que o número é (a regra geral colore pela POSIÇÃO do cartão) */
.dvr-kpis .kpi { padding: 16px 18px; }
.dvr-kpi-textos { flex: 1; min-width: 0; }
.dvr-kpi-sub { font-size: 11.5px; color: var(--txt-2); margin-top: 1px; }
.dvr-kpi-barra { height: 6px; margin-top: 7px; border-radius: 999px; background: var(--bg-3); overflow: hidden; }
.dvr-kpi-barra > span { display: block; height: 100%; border-radius: inherit; background: linear-gradient(90deg, var(--acento), var(--marca-ciano)); }

/* barra de filtros */
.dvr-filtros {
  display: flex; flex-wrap: wrap; align-items: center; gap: 10px;
  padding: 10px; margin-bottom: 14px;
  background: var(--bg-2); border: 1px solid var(--linha); border-radius: var(--raio-grande);
}
.dvr-busca { flex: 1 1 260px; height: 44px; background: var(--bg); border-radius: 10px; }
.dvr-busca input[type="search"] { width: 100%; font-size: 13px; border-radius: 10px; }
.dvr-filtro {
  display: flex; align-items: center; gap: 10px; margin: 0;
  height: 44px; padding: 0 12px; min-width: 150px;
  background: var(--bg); border: 1px solid var(--linha); border-radius: 10px; cursor: pointer;
}
.dvr-filtro:focus-within { border-color: var(--acento); }
.dvr-filtro > .ic { width: 16px; height: 16px; color: var(--txt-2); flex-shrink: 0; }
.dvr-filtro-textos { display: flex; flex-direction: column; flex: 1; min-width: 0; line-height: 1.15; }
.dvr-filtro-textos small { font-size: 10.5px; color: var(--txt-2); }
.dvr-filtro select {
  width: 100%; padding: 1px 0 0; font-size: 13px; color: var(--txt);
  background: transparent; border: 0; border-radius: 0; cursor: pointer; color-scheme: dark;
}
.dvr-filtro select:focus { outline: none; }
.dvr-filtro select option { background: var(--bg-2); color: var(--txt); }
.dvr-vistas { display: flex; gap: 6px; margin-left: auto; }
.dvr-vista {
  width: 44px; height: 44px; display: flex; align-items: center; justify-content: center;
  background: var(--bg); border: 1px solid var(--linha); border-radius: 10px; color: var(--txt-2); cursor: pointer;
}
.dvr-vista:hover { border-color: var(--acento); color: var(--txt); }
.dvr-vista.ativo { background: var(--acento); border-color: var(--acento); color: #fff; }

/* a caixa da lista/grade + rodapé */
.dvr-caixa { background: var(--bg-2); border: 1px solid var(--linha); border-radius: var(--raio-grande); overflow: hidden; }
.dvr-rolagem { overflow-x: auto; }
.dvr-tabela { width: 100%; border-collapse: collapse; font-size: 13.5px; }
.dvr-tabela th {
  padding: 13px 16px; font-size: 12.5px; font-weight: 600; color: var(--txt-2); white-space: nowrap;
  background: rgba(255, 255, 255, .02); border-bottom: 1px solid var(--linha);
}
.dvr-tabela td { padding: 12px 16px; border-bottom: 1px solid var(--linha); vertical-align: middle; }
.dvr-tabela tbody tr:last-child td { border-bottom: 0; }
.dvr-tabela tbody tr { transition: background-color .15s ease; }
.dvr-tabela tbody tr:hover { background: rgba(47, 126, 230, .06); }
.dvr-ordena {
  display: inline-flex; align-items: center; gap: 6px; padding: 0;
  background: none; border: 0; color: inherit; font: inherit; cursor: pointer;
}
.dvr-ordena:hover, .dvr-ordena.ativo { color: var(--txt); }
.dvr-seta { font-size: 11px; opacity: .7; }
.dvr-ordena.ativo .dvr-seta { color: var(--acento); opacity: 1; }
.dvr-th-acoes, .dvr-td-acoes { text-align: right; }
.dvr-ip { font-size: 12.5px; white-space: nowrap; }

.dvr-nome { display: flex; align-items: center; gap: 12px; min-width: 0; }
.dvr-nome-bloco { min-width: 0; }
.dvr-nome-texto { font-weight: 600; font-size: 14px; overflow-wrap: anywhere; }
.dvr-thumb {
  width: 62px; height: 44px; flex-shrink: 0; display: flex; align-items: center; justify-content: center;
  background: linear-gradient(160deg, #2d3644, #151a21); border: 1px solid var(--linha); border-radius: 8px;
  color: #a9b8cc;
}
.dvr-thumb .ic { width: 36px; height: 36px; stroke-width: 1.3; }
.dvr-status { display: flex; align-items: center; flex-wrap: wrap; gap: 5px; margin-top: 3px; font-size: 12px; color: var(--txt-2); }
.dvr-ponto { width: 8px; height: 8px; border-radius: 50%; background: var(--txt-2); flex-shrink: 0; }
.dvr-status-rot { font-weight: 600; }
.dvr-status.online .dvr-ponto { background: var(--ok); box-shadow: 0 0 0 3px rgba(63, 185, 80, .18); }
.dvr-status.online .dvr-status-rot { color: var(--ok); }
.dvr-status.offline .dvr-ponto { background: var(--erro); box-shadow: 0 0 0 3px rgba(240, 93, 93, .18); }
.dvr-status.offline .dvr-status-rot { color: var(--erro); }
.dvr-alertas { margin-top: 5px; }
.dvr-link {
  padding: 0; background: none; border: 0; color: var(--acento); font: inherit; font-size: 12px;
  text-decoration: underline; cursor: pointer;
}
.dvr-com-icone { display: inline-flex; align-items: center; gap: 8px; white-space: nowrap; }
.dvr-com-icone .ic { width: 16px; height: 16px; color: var(--txt-2); }

/* ações: botões contornados + o menu "⋮" */
.dvr-acoes { display: inline-flex; align-items: center; justify-content: flex-end; gap: 8px; }
.dvr-acao {
  display: inline-flex; align-items: center; gap: 7px; height: 34px; padding: 0 12px;
  background: var(--bg); border: 1px solid var(--linha); border-radius: 8px;
  color: var(--txt); font: inherit; font-size: 13px; font-weight: 500; white-space: nowrap; cursor: pointer;
  transition: border-color .15s ease, background-color .15s ease;
}
.dvr-acao:hover { border-color: var(--acento); background: var(--bg-3); }
.dvr-acao .ic { width: 15px; height: 15px; }
.dvr-acao.so-icone { width: 34px; padding: 0; justify-content: center; }
summary.dvr-acao { list-style: none; }
summary.dvr-acao::-webkit-details-marker { display: none; }
.dvr-menu[open] > summary { border-color: var(--acento); }
.dvr-menu-corpo {
  position: fixed; z-index: 60; min-width: 190px; padding: 6px;
  display: flex; flex-direction: column; gap: 2px;
  background: var(--bg-2); border: 1px solid var(--linha); border-radius: 10px;
  box-shadow: 0 14px 34px rgba(0, 0, 0, .5);
}
.dvr-menu-corpo hr { width: 100%; margin: 4px 0; border: 0; border-top: 1px solid var(--linha); }
.dvr-menu-item {
  display: flex; align-items: center; gap: 9px; width: 100%; padding: 8px 10px; text-align: left;
  background: none; border: 0; border-radius: 6px; color: var(--txt); font: inherit; font-size: 13px; cursor: pointer;
}
.dvr-menu-item:hover, .dvr-menu-item:focus-visible { background: var(--bg-3); outline: none; }
.dvr-menu-item .ic { width: 15px; height: 15px; color: var(--txt-2); }
.dvr-menu-item.perigo, .dvr-menu-item.perigo .ic { color: var(--erro); }

/* grade de cartões (sem transform no hover: um ancestral transformado prenderia o menu fixo) */
.dvr-grade { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 12px; padding: 14px; }
.dvr-cartao {
  display: flex; flex-direction: column; gap: 12px; padding: 14px;
  background: var(--bg); border: 1px solid var(--linha); border-radius: 12px;
  transition: border-color .15s ease, box-shadow .15s ease;
}
.dvr-cartao:hover { border-color: var(--acento); box-shadow: 0 6px 20px rgba(0, 0, 0, .3); }
.dvr-cartao-dados { display: grid; grid-template-columns: auto 1fr; gap: 7px 12px; margin: 0; font-size: 12.5px; }
.dvr-cartao-dados dt { color: var(--txt-2); }
.dvr-cartao-dados dd { margin: 0; text-align: right; overflow-wrap: anywhere; }
.dvr-cartao .dvr-acoes { padding-top: 12px; border-top: 1px solid var(--linha); }

.dvr-vazio { padding: 40px 16px; text-align: center; color: var(--txt-2); }
.dvr-vazio .ic { width: 42px; height: 42px; stroke-width: 1.3; }
.dvr-vazio p { margin: 8px 0 12px; }

.dvr-rodape {
  display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 12px;
  padding: 12px 16px; border-top: 1px solid var(--linha); font-size: 12.5px; color: var(--txt-2);
}
.dvr-paginas { display: flex; align-items: center; gap: 6px; }
.dvr-pag {
  min-width: 34px; height: 34px; padding: 0 8px; display: inline-flex; align-items: center; justify-content: center;
  background: var(--bg); border: 1px solid var(--linha); border-radius: 8px; color: var(--txt); font: inherit; cursor: pointer;
}
.dvr-pag:hover:not(:disabled) { border-color: var(--acento); }
.dvr-pag.ativa { background: var(--acento); border-color: var(--acento); color: #fff; font-weight: 600; }
.dvr-pag:disabled { opacity: .4; cursor: default; }
.dvr-por-pagina { margin: 0 0 0 6px; }
.dvr-por-pagina select { width: auto; height: 34px; padding: 0 8px; font-size: 13px; }

@media (max-width: 1100px) {
  .dvr-tabela .opc { display: none; }
}
@media (max-width: 620px) {
  /* 5 cartões um embaixo do outro viravam uma torre: 2 por linha, o último na largura toda */
  .kpis.kpis-5.dvr-kpis { grid-template-columns: repeat(2, 1fr); gap: 8px; }
  .dvr-kpis .kpi:last-child { grid-column: 1 / -1; }
  .dvr-kpis .kpi { padding: 12px; gap: 10px; }
  .dvr-kpis .kpi-icone { width: 38px; height: 38px; }
  .dvr-kpis .kpi-icone .ic { width: 18px; height: 18px; }
  .dvr-kpis .kpi-valor { font-size: 20px; }
}
@media (max-width: 600px) {
  .dvr-filtros { gap: 8px; }
  .dvr-busca, .dvr-filtro { flex: 1 1 100%; }
  .dvr-vistas { display: none; } /* no celular é sempre a grade (dvrs.js) */
  .dvr-grade { grid-template-columns: 1fr; padding: 10px; }
  .dvr-rodape { justify-content: center; }
}

/* ==========================================================================
   Planos e contratos — redesenho de 03/10/2026 ("muito confusa"): indicadores, três abas
   (Contratos, Catálogo de planos, Preço e margem) e, em Contratos, a lista de clientes com a
   situação de cada um ao lado da ficha do escolhido. Prefixo próprio (pln-); as abas reaproveitam
   o desenho das de Configurações (.cfg-aba).
   ========================================================================== */
.pln-tela { display: flex; flex-direction: column; min-width: 0; }
.pln-tela .aviso { margin-top: 12px; }
.pln-tela .aviso.alerta { background: rgba(210, 153, 34, .12); border-color: rgba(210, 153, 34, .45); }
.pln-painel { display: flex; flex-direction: column; gap: 16px; min-width: 0; }
.pln-painel[hidden] { display: none; }
.pln-painel > .painel { margin: 0; }

/* Contratos: lista de clientes | ficha */
.pln-contratos { display: grid; grid-template-columns: minmax(260px, 320px) minmax(0, 1fr); gap: 16px; align-items: start; }
.pln-lista { margin: 0; padding: 12px; position: sticky; top: 0; max-height: calc(100vh - 150px); overflow-y: auto; }
.pln-lista h4 { margin: 2px 4px 10px; font-size: 12.5px; color: var(--txt-2); text-transform: uppercase; letter-spacing: .03em; }
.pln-busca { width: 100%; margin-bottom: 10px; }
.pln-busca input[type="search"] { width: 100%; }
.pln-lista-itens { display: flex; flex-direction: column; gap: 6px; }
.pln-cliente {
  display: flex; flex-direction: column; align-items: stretch; gap: 3px; width: 100%;
  padding: 10px 12px; text-align: left; font: inherit; color: var(--txt); cursor: pointer;
  background: var(--bg); border: 1px solid var(--linha); border-left: 3px solid transparent;
  border-radius: var(--raio); transition: border-color .15s ease, background-color .15s ease;
}
.pln-cliente:hover { border-color: var(--acento); }
.pln-cliente[aria-pressed="true"] { background: rgba(47, 126, 230, .1); border-color: var(--acento); border-left-color: var(--acento); }
.pln-cliente:focus-visible { outline: 2px solid var(--acento); outline-offset: 2px; }
.pln-cliente[hidden] { display: none; }
.pln-cliente-linha { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.pln-cliente-linha strong { font-size: 14px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pln-cliente-linha .tag { flex: 0 0 auto; }
.pln-cliente .dica { margin: 0; }
.pln-cliente-plano { font-size: 12px; color: var(--ok); }

.pln-ficha { margin: 0; min-width: 0; }
.pln-ficha-vazia { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 6px; min-height: 260px; text-align: center; }
.pln-ficha-vazia > .ic { width: 34px; height: 34px; color: var(--txt-2); margin-bottom: 6px; }
.pln-ficha-vazia .dica { max-width: 380px; }
.pln-ficha-cab { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; margin-bottom: 14px; }
.pln-ficha-cab h3 { margin: 0; font-size: 19px; }
.pln-ficha-cab .dica { margin: 4px 0 0; display: block; }

/* pares rótulo/valor (ficha do cliente e cartão do grupo) */
.pln-dados { display: grid; grid-template-columns: repeat(auto-fit, minmax(130px, 1fr)); gap: 1px; margin: 0; background: var(--linha); border: 1px solid var(--linha); border-radius: var(--raio); overflow: hidden; }
.pln-dados > div { background: var(--bg); padding: 9px 12px; min-width: 0; }
.pln-dados dt { font-size: 11.5px; color: var(--txt-2); }
.pln-dados dd { margin: 3px 0 0; font-size: 15px; font-weight: 600; font-variant-numeric: tabular-nums; }
.pln-dados dd.ok { color: var(--ok); }

.pln-pendencias { display: flex; flex-direction: column; gap: 10px; margin-top: 14px; }
.pln-pendencia {
  display: flex; align-items: center; gap: 12px; padding: 12px 14px; border-radius: var(--raio);
  background: var(--bg); border: 1px solid var(--linha); border-left: 3px solid var(--txt-2);
}
.pln-pendencia > .ic { width: 20px; height: 20px; flex: 0 0 auto; color: var(--txt-2); }
.pln-pendencia.alerta { border-left-color: var(--alerta); background: rgba(210, 153, 34, .07); }
.pln-pendencia.alerta > .ic { color: var(--alerta); }
.pln-pendencia.erro { border-left-color: var(--erro); background: rgba(240, 93, 93, .07); }
.pln-pendencia.erro > .ic { color: var(--erro); }
.pln-pendencia-texto { display: flex; flex-direction: column; gap: 3px; flex: 1; min-width: 0; font-size: 13px; }
.pln-pendencia-texto span { color: var(--txt-2); line-height: 1.45; }
.pln-pendencia .btn { flex: 0 0 auto; }

.pln-grupos { margin-top: 18px; display: flex; flex-direction: column; gap: 12px; }
.pln-grupos h4 { margin: 0; font-size: 12.5px; color: var(--txt-2); text-transform: uppercase; letter-spacing: .03em; }
.pln-grupo { padding: 14px; border: 1px solid var(--linha); border-radius: var(--raio-grande); background: linear-gradient(145deg, var(--bg-2), var(--bg)); }
.pln-grupo.pendente { border-color: rgba(210, 153, 34, .5); }
.pln-grupo-cab { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 12px; }
.pln-grupo-titulo { display: flex; align-items: center; gap: 10px; min-width: 0; }
.pln-grupo-titulo > .ic { width: 20px; height: 20px; color: var(--acento); flex: 0 0 auto; }
.pln-grupo-titulo strong { display: block; font-size: 14.5px; }
.pln-grupo-titulo .dica { margin: 2px 0 0; display: block; }
.pln-grupo-corpo { display: grid; grid-template-columns: minmax(220px, 280px) minmax(0, 1fr); gap: 14px; align-items: end; }
.pln-grupo-plano label { font-weight: 600; }
.pln-grupo-plano select { width: 100%; }
.pln-cameras { margin-top: 12px; }
.pln-cameras summary { cursor: pointer; font-size: 13px; color: var(--txt-2); }
.pln-cameras summary:hover { color: var(--txt); }
.pln-cameras[open] summary { margin-bottom: 8px; }
.pln-rolagem { overflow-x: auto; }
.pln-tela .tag + .tag { margin-left: 4px; }

/* Catálogo */
.pln-grade-planos { display: grid; grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); gap: 12px; }
.pln-plano {
  display: flex; flex-direction: column; gap: 6px; padding: 16px; border: 1px solid var(--linha);
  border-radius: var(--raio-grande); background: linear-gradient(145deg, var(--bg-2), var(--bg));
  transition: border-color .15s ease;
}
.pln-plano:hover { border-color: var(--acento); }
.pln-plano.desativado { opacity: .55; }
.pln-plano-topo { display: flex; gap: 6px; flex-wrap: wrap; }
.pln-plano-dias { display: flex; align-items: baseline; gap: 6px; margin-top: 4px; }
.pln-plano-dias b { font-size: 34px; line-height: 1; font-variant-numeric: tabular-nums; }
.pln-plano-dias span { color: var(--txt-2); font-size: 14px; }
.pln-plano-nome { font-size: 14px; }
.pln-plano .dica { margin: 0; }
.pln-plano .linha-botoes { margin-top: auto; padding-top: 8px; }
.pln-notas { margin: 0; padding-left: 18px; display: flex; flex-direction: column; gap: 8px; font-size: 13px; color: var(--txt-2); line-height: 1.5; }

/* Preço e margem */
.pln-duas { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px; align-items: start; }
.pln-duas > .painel { margin: 0; }

@media (max-width: 1100px) {
  .pln-duas { grid-template-columns: minmax(0, 1fr); }
  .pln-grupo-corpo { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 900px) {
  .pln-contratos { grid-template-columns: minmax(0, 1fr); }
  .pln-lista { position: static; max-height: 340px; }
}
@media (max-width: 620px) {
  .kpis.kpis-5.pln-kpis { grid-template-columns: repeat(2, 1fr); gap: 8px; }
  .pln-kpis .kpi:last-child { grid-column: 1 / -1; }
  .pln-kpis .kpi { padding: 12px; gap: 10px; }
  .pln-kpis .kpi-icone { width: 38px; height: 38px; }
  .pln-kpis .kpi-icone .ic { width: 18px; height: 18px; }
  .pln-kpis .kpi-valor { font-size: 18px; }
  .pln-pendencia { flex-wrap: wrap; }
  .pln-pendencia .btn { width: 100%; justify-content: center; }
  .pln-ficha-cab { flex-direction: column; }
}
