/* F2-T02 — acréscimos à folha extraída das telas aprovadas (app.css). Sem estilo inline nas páginas (CSP style-src 'self'). */
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}
a.brand{text-decoration:none}
.theme{margin:0} .theme button{opacity:1}
.sair{margin:0}
.btn{text-decoration:none;display:inline-block} .btn.sm{padding:6px 10px;font-size:.75rem}
.btn.p{background:var(--accent);color:var(--accent-fg);border-color:var(--accent)}
a.stat{text-decoration:none}
.empilha{display:grid;gap:8px}
.alertas{list-style:none;margin:0;padding:0;display:grid;gap:8px}
.alertas .stat{margin:0;align-items:flex-start;gap:12px}.alertas .stat>span:first-child{min-width:0;overflow-wrap:anywhere}.alertas .stat b{font-family:var(--body);font-size:1rem}.alertas .stat .note{flex:none;white-space:nowrap}
@media (max-width:1100px){.topbar .ctx{flex-wrap:nowrap;min-width:0}.topbar .ctx>.chip:not(.troca){display:none}.chip.troca{min-width:0}.chip.troca select{max-width:170px}} /* janela enquadrada: o "Sair" quebrava para 2ª linha abaixo do cliente (dono 05/10); a revenda segue no menu */
@media (max-width:640px){.topbar .ctx{flex-wrap:wrap}} /* celular: a barra volta a quebrar linha (com nowrap o tema/avatar/Sair esticavam a página para 610 px num aparelho de 390) */
.cota{justify-content:space-between;margin-bottom:8px}
/* login (desenho = login do portal Cogn.IA, foto do dono 01/10) */
main.publico{padding:28px 16px}
.login{max-width:480px;margin:0 auto;text-align:center}
.brand.grande{font-size:3.4rem;letter-spacing:-2px;color:var(--fg);margin-bottom:26px}
.login-card{padding:28px 26px;text-align:left}
.login-titulo{text-align:center;font-weight:800;letter-spacing:.02em;text-transform:uppercase;font-size:1.05rem}
.centro{text-align:center}
.login .sub{margin:6px 0 18px}
.form-col{display:grid;gap:12px}
input.grande{padding:14px 16px;font-size:1rem}
.btn.entrar{width:100%;padding:15px;font-size:1rem;text-transform:uppercase;letter-spacing:.06em;font-weight:800;margin-top:2px}
.rodape-marca{margin-top:26px;display:flex;gap:10px;justify-content:center;align-items:baseline}
.rodape-marca .brand{font-size:1.4rem;letter-spacing:-1px;color:var(--mut)}
.rodape-marca .brand span{color:var(--accent-2)}
/* câmeras: filtros */
.filtros{display:flex;flex-wrap:wrap;gap:12px;align-items:center;margin-bottom:12px}
.chips{border:0;margin:0;padding:0;display:flex;flex-wrap:wrap;gap:8px}
.chip-f{display:inline-flex;align-items:center;gap:6px;margin:0;padding:7px 12px;border:1px solid var(--line2);border-radius:var(--r-sm);background:var(--panel3);color:var(--fg);font-family:var(--display);font-size:.8rem;font-weight:600;letter-spacing:.02em;text-transform:none;cursor:pointer;position:relative}
.chip-f input{position:absolute;opacity:0;inset:0;width:100%;height:100%;margin:0;cursor:pointer}
.chip-f:has(input:checked){background:var(--accent);color:var(--accent-fg);border-color:var(--accent)}
.chip-f:has(input:focus-visible){outline:2px solid var(--accent);outline-offset:2px}
.field.busca{margin-left:auto;width:240px;max-width:100%}
.rodape-tabela{margin:10px 0 0}
.empty .btn{margin-top:4px}
/* nova câmera */
.modos{border:0;margin:0 0 14px;padding:0;display:grid;gap:8px}
.modos legend{font-family:var(--display);font-size:.74rem;color:var(--mut);letter-spacing:.06em;text-transform:uppercase;margin-bottom:6px;padding:0}
.modo{display:flex;gap:10px;align-items:flex-start;margin:0;padding:10px 12px;border:1px solid var(--line2);border-radius:var(--r-sm);background:var(--panel2);color:var(--fg);text-transform:none;letter-spacing:0;font-family:var(--body);font-size:.86rem;cursor:pointer}
.modo input{width:auto;margin-top:4px}
.modo small{display:block;color:var(--mut);font-size:.78rem;margin-top:2px}
.modo:has(input:checked){border-color:var(--accent);background:var(--accent-s)}
.modo:has(input:focus-visible){outline:2px solid var(--accent);outline-offset:2px}
.modo.off{cursor:not-allowed;border-style:dashed}
.modo.off .pill{margin-left:6px}
.dvr,.p2p,.hik,.existente{border:1px solid var(--line2);border-radius:var(--r-sm);margin:0 0 14px;padding:10px 12px}
.dvr legend,.p2p legend,.hik legend,.existente legend{font-family:var(--display);font-size:.74rem;color:var(--mut);letter-spacing:.06em;text-transform:uppercase;padding:0 6px}
.dvr,.p2p,.hik,.existente{display:none} form:has(input[name=modo][value=pull_ip]:checked) .dvr{display:block}  /* sem JS também: o fieldset aparece só com o modo marcado */
form:has(input[name=modo][value=p2p]:checked) .p2p,form:has(input[name=modo][value=existente]:checked) .existente{display:block}
/* Nova câmera IP: com um equipamento escolhido em "Usar o usuário e a senha de:", usuário/senha (e a busca de canais, que precisa deles) somem; o servidor também os ignora (sem JS) */
.dvr:has(#n-dvr-cred option:not([value=""]):checked) .f-digita,.dvr:has(#n-dvr-cred option:not([value=""]):checked) .desc-acao{display:none}
form:has(input[name=modo][value=hik]:checked) .hik{display:block}
/* F1-T02f anexo: o assistente Hik-Connect (conta -> aparelhos -> canais com miniatura). No modo Hik-Connect o nome é por canal (nos campos do assistente): Nome e Local do formulário somem. */
form:has(input[name=modo][value=hik]:checked) .f-nome,form:has(input[name=modo][value=hik]:checked) .f-local{display:none}
.hik[hidden]{display:none !important} .hik-nova{margin:4px 0 8px} .hik-nova summary{cursor:pointer;color:var(--fg);font-family:var(--display);font-size:.82rem;padding:6px 0}
#hik-lista{margin-top:10px} #hik-lista .msg,#hik-contas .msg{color:var(--fg)}  /* aviso em tinta (contraste nos 2 temas); a cor está na borda e no fundo */
.hik-aparelho{border:1px solid var(--line2);border-radius:var(--r-sm);background:var(--panel2);margin:8px 0;padding:8px 10px}
.hik-canais{display:grid;gap:8px;margin-top:8px}
.hik-canal{display:flex;flex-wrap:wrap;gap:8px 12px;align-items:center;padding:6px;border:1px solid var(--line2);border-radius:var(--r-sm);background:var(--panel)}
.hik-canal[data-ja-cadastrada]{opacity:.85}
.hik-thumb{position:relative;display:inline-flex;align-items:center;justify-content:center;width:96px;height:54px;flex:none;border-radius:4px;background:var(--bg);border:1px solid var(--line2);overflow:hidden}
.hik-thumb-n{display:none;color:var(--fg);font-family:var(--display);font-size:1.1rem} .hik-img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
.hik-img.sem-imagem{visibility:hidden} .hik-img.sem-imagem+.hik-thumb-n{display:inline}  /* o número do canal só aparece quando a miniatura falhou */
.hik-canal .chk{display:inline-flex;align-items:center;gap:6px;margin:0;color:var(--fg);text-transform:none;letter-spacing:0;font-family:var(--body);font-size:.86rem}
.hik-canal .chk input{width:auto} .hik-nome{flex:1 1 160px;min-width:0}
#resultado .msg.e{color:var(--fg)}  /* a recusa da Nova câmera em tinta: o vermelho sobre o fundo translúcido dava 3,81:1 no tema claro */ [data-lote-resumo],[data-lote-puladas]{color:var(--fg);font-weight:600}  /* F2-T18: "N câmeras criadas: …" em tinta (contraste nos 2 temas); a cor está na borda e no fundo */ .lote-estado .row{display:inline-flex;vertical-align:middle} .hik-resultado{list-style:none;margin:8px 0;padding:0;display:grid;gap:6px} .hik-resultado li{padding:6px 8px;border:1px solid var(--line2);border-radius:var(--r-sm);background:var(--panel2)}
/* F1-T02e: busca de canais do DVR (botão só com JS; cronômetro; a grade reaproveita .hik-canal/.hik-thumb). Só tokens existentes. */
.desc-acao{margin:8px 0} .desc-acao[hidden]{display:none !important} .desc-acao .btn:disabled{opacity:1;color:var(--mut);background:var(--panel3);border-style:dashed;cursor:not-allowed} /* inativo legível (como .minha): o 50% de opacidade dava 2,84:1 depois do cadastro; o fundo fixo vence o .btn:hover (3,8:1 sob o ponteiro, achado do Codex) */ .desc-res{margin:8px 0 14px} .desc-busca{margin:8px 0}
.desc-busca[data-desc-estado=buscando]{display:flex;flex-wrap:wrap;gap:8px;align-items:center;color:var(--fg)}
.desc-spin{width:14px;height:14px;border:2px solid var(--line2);border-top-color:var(--accent);border-radius:50%;display:inline-block;animation:desc-gira 1s linear infinite}
@keyframes desc-gira{to{transform:rotate(360deg)}}
@media (prefers-reduced-motion:reduce){.desc-spin{animation:none}}
.desc-feito #desc-res,.desc-feito .desc-acao{display:none} .desc-grade-ativa #n-criar{display:none} .desc-grade .sub{color:var(--fg)}
/* F2-T07: Equipamentos (lista + edição inline) e Gerenciar câmera. Só tokens existentes. */
#equipamentos-cliente>.msg,#equipamentos-cliente>.card,#gerencia-camera>.msg,#gerencia-camera>.mono,#gerencia-camera>.acoes-usuario{margin-top:12px}
#gerencia-camera{margin-top:16px} .form-eq{align-items:flex-end} .form-eq .field{min-width:150px} .form-eq input,.form-eq select{width:100%}
#tabela-equipamentos td .note{margin-top:2px} #tabela-equipamentos .acoes-usuario{min-width:220px}
#equipamentos-cliente .pill.crit{color:var(--fg)} #equipamentos-cliente .pill.crit .dot{color:var(--crit)}  /* "inalcançável" em tinta (< 4,5:1 com o vermelho do token), como o "falhou" da Biblioteca */
#equipamentos-cliente>.msg,#gerencia-camera>.msg{color:var(--fg)}  /* como em #licencas-cliente: o vermelho/verde do token sobre o fundo translúcido dá < 4,5:1 no tema claro; o aviso se distingue pela borda e pelo fundo */
.acao{margin-top:12px}
.urlbox{padding:11px;background:var(--bg);border-radius:var(--r-sm);border:1px solid var(--line2);margin:12px 0 4px;user-select:all}
h2.sec{margin-top:18px;font-size:1.05rem}
.receptor-ve{margin-top:8px}
.card .msg{margin-top:8px}
.det{display:grid;grid-template-columns:max-content 1fr;gap:6px 18px;margin:0 0 10px}
.det dt{color:var(--mut)} .det dd{margin:0}
.kpis{display:flex;gap:12px;flex-wrap:wrap;margin-bottom:12px}
.kpi-b{flex:1;min-width:90px;padding:10px 12px;border:1px solid var(--line);border-radius:var(--r-sm);background:var(--panel2)}
.kpi-b b{display:block;font-family:var(--display);font-size:1.7rem;line-height:1.1;font-variant-numeric:tabular-nums}
.kpi-b span{color:var(--mut);font-size:.8rem}
.sec-h{margin:22px 0 10px;font-size:1.05rem}
.sec-lista{margin-top:16px}
.sel-cliente select{width:auto;min-width:180px}
::placeholder{color:var(--mut);opacity:1}
/* "sem flash": sem JS, sem @import de fonte externa */

/* ---- CONTRASTE (P3 do card, WCAG AA): ajustes sobre os tokens das telas aprovadas que ficavam abaixo de 4,5:1 / 3:1 ----
   medidos no navegador por cerebro/web-prova (razão da cor computada contra o pior pixel do fundo). Mudanças e motivo:
   claro: --mut2 (rótulos), --warn/--ok (texto sobre o fundo translúcido da pílula), --top-mut (chip no degradê marinho);
   escuro: --accent (botão primário #008896 com texto branco dava 4,23:1), brilho do fundo (#477ac0 -> #365f99: texto sobre ele < 4,5:1),
   item ativo do menu em teal. Identidade preservada (mesmos matizes). */
:root{--mut2:#566b79;--warn:#7a4f0a;--ok:#17703c;--top-mut:#d3e2e8;--brand-ia:var(--accent-2)}
.brand.grande span,.rodape-marca .brand span{color:var(--brand-ia)}
.publico .note,.publico .eyebrow,.publico .sub,.rodape-marca .brand{color:var(--fg)}
@media (prefers-color-scheme: dark){
  :root:not([data-theme="light"]){--accent:#00788a;--brand-ia:var(--teal);--fundo:radial-gradient(ellipse at 74% 110%,#365f99 0,transparent 54%),linear-gradient(145deg,#071523 20%,#071725 46%,#103e70 100%)}
  :root:not([data-theme="light"]) nav.rail a.on{color:var(--teal)}
}
:root[data-theme="dark"]{--accent:#00788a;--brand-ia:var(--teal);--fundo:radial-gradient(ellipse at 74% 110%,#365f99 0,transparent 54%),linear-gradient(145deg,#071523 20%,#071725 46%,#103e70 100%)}
:root[data-theme="dark"] nav.rail a.on{color:var(--teal)}
.lic-card{grid-column:1/-1}
/* tela Câmera (F2-T03): player, estados, timeline do dia, fotos */
#camera{display:grid;gap:16px}
.player{aspect-ratio:16/9;max-width:100%;background:#05070a;border-radius:var(--r);position:relative;overflow:hidden;border:1px solid var(--line2)}
.player video{width:100%;height:100%;display:block;object-fit:contain;background:#05070a}
.player .estado{position:absolute;top:10px;left:10px;background:rgba(0,0,0,.72);color:#fff;padding:5px 10px;border-radius:5px;font-size:.78rem;font-family:var(--display);letter-spacing:.03em}
.player .estado[data-estado="online"]{color:#ff8a8d}
.player .estado[data-estado="offline"],.player .estado[data-estado="sem_codec"],.player .estado[data-estado="sem_permissao"]{background:rgba(120,20,25,.9)}
.player .osd{position:absolute;left:10px;bottom:48px;background:rgba(0,0,0,.72);color:#fff;padding:4px 9px;border-radius:5px;font-size:.82rem;letter-spacing:.02em;word-break:normal;pointer-events:none}
.player-barra{margin:12px 0;gap:10px;flex-wrap:wrap}
/* Botão SD/HD no canto da imagem (F2-T03d): texto = qualidade ATUAL; fundo escuro translúcido + texto branco como os outros overlays (contraste >= 4,5:1 sobre quadro claro, nos 2 temas) */
.qual{padding:3px 9px;border-radius:5px;border:1px solid rgba(255,255,255,.5);background:rgba(0,0,0,.72);color:#fff;font:600 .78rem var(--display),sans-serif;letter-spacing:.04em;cursor:pointer}
.qual:hover,.qual:focus-visible{background:rgba(0,0,0,.9);outline:2px solid #fff;outline-offset:1px}
.qual:disabled{cursor:not-allowed;color:#d6e2ee;opacity:1}
.player .qual{position:absolute;top:10px;right:10px;z-index:2}
.tile .ferr .qual{padding:1px 6px;font-size:.72rem;line-height:1.3}
@media (max-width:700px){.player .qual{min-width:44px;min-height:44px}} /* alvo de toque >= 44x44 no celular (a tela Câmera) */
.msg-foto{margin-top:8px}
.dia-nav{gap:12px;align-items:center;flex-wrap:wrap;margin-bottom:34px} /* folga para o rótulo da hora do cursor, que sobe da barra */
.tl{position:relative;height:44px;background:var(--panel2);border:1px solid var(--line2);border-radius:var(--r-sm);overflow:visible;cursor:crosshair;touch-action:pan-y;user-select:none}
.tl .trecho{position:absolute;top:6px;bottom:6px;min-width:6px;padding:0;border:0;border-radius:4px;background:var(--accent);cursor:pointer}
.tl .trecho:hover,.tl .trecho:focus-visible{background:var(--accent-2);outline:2px solid var(--fg);outline-offset:1px}
.tl .buraco{position:absolute;top:14px;bottom:14px;background:var(--crit);opacity:.55;border-radius:3px}
.tl .tl-cursor{position:absolute;top:0;bottom:0;width:2px;margin-left:-1px;background:var(--fg);pointer-events:none;z-index:2}
.tl .tl-hora{position:absolute;bottom:calc(100% + 6px);padding:2px 7px;border-radius:4px;background:var(--fg);color:var(--panel);font-family:var(--mono);font-size:.75rem;white-space:nowrap;pointer-events:none;z-index:3}
.tl .tl-pos{position:absolute;top:-3px;bottom:-3px;width:3px;margin-left:-1.5px;border-radius:2px;background:var(--warn);pointer-events:none;z-index:2}
.tl-eixo{display:flex;justify-content:space-between;font-size:.7rem;color:var(--mut);margin-top:4px}
/* movimento pelos eventos do DVR (F1-T09): faixas na barra de gravação (só desenho: o ponteiro segue para o trecho gravado), botões e legenda */
:root{--mov:#9a4f00}
@media (prefers-color-scheme: dark){:root:not([data-theme="light"]){--mov:#ffc15a}}
:root[data-theme="dark"]{--mov:#ffc15a}
.tl .trecho{bottom:14px} /* a pista do movimento fica ABAIXO do trecho (não sobre ele): a faixa só encosta no fundo da barra, contra o qual tem >= 3:1 nos 2 temas */
.tl .mov{position:absolute;bottom:3px;height:8px;background:var(--mov);pointer-events:none;z-index:1} /* sem largura mínima: a largura é a duração real */
/* MARCADOR do início da faixa (visibilidade de faixa curta): um tique em triângulo ACIMA da barra, de outra forma e outra cor (a do texto, --fg), fora da pista que representa a duração: não se confunde com extensão da faixa */
.tl .mov-marca{position:absolute;top:-8px;width:0;height:0;margin-left:-4px;border-left:4px solid transparent;border-right:4px solid transparent;border-top:7px solid var(--fg);pointer-events:none;z-index:1}
.mov-nav{gap:10px;align-items:center;flex-wrap:wrap;margin-top:10px}
.mov-chave{display:inline-block;width:18px;height:9px;border-radius:2px;background:var(--mov);vertical-align:middle}
.trechos{list-style:none;margin:10px 0 0;padding:0;display:grid;gap:6px;font-family:var(--mono);font-size:.8rem}
.fotos-lista{list-style:none;margin:8px 0 0;padding:0;display:grid;gap:6px}
.fotos-lista li{display:flex;gap:10px;align-items:center}

/* F2-T02b: revenda = telas do cliente com o cliente escolhido no topo */
.chip.troca{display:inline-flex;align-items:center;gap:6px;padding:3px 6px 3px 11px}
.chip.troca label{margin:0;font-family:var(--body);font-size:.78rem;letter-spacing:0;text-transform:none;color:var(--top-mut)}
.chip.troca select{width:auto;max-width:220px;padding:3px 8px;border:0;border-radius:999px;background:rgba(255,255,255,.14);color:var(--top-fg);font-size:.78rem;font-weight:600}
.chip.troca select option{color:#14354c;background:#fff}
.tbl.rola{max-height:68vh;overflow:auto}
.tbl.rola thead th{position:sticky;top:0;z-index:2;background:var(--panel)}
.tbl.rola tr.grupo th{position:static;background:var(--panel2);color:var(--fg);font-size:.8rem;letter-spacing:.02em;text-transform:none;padding:10px 8px;border-top:1px solid var(--line2)}
.novo-cli{display:flex;flex-wrap:wrap;gap:8px;align-items:center} .novo-cli input{width:240px;max-width:100%} .novo-cli .msg{flex-basis:100%}
.btn.p:hover{background:#07386a}
:root[data-theme="dark"] .btn.p:hover{background:#066975}
@media (prefers-color-scheme: dark){:root:not([data-theme="light"]) .btn.p:hover{background:#066975}}
.codigobox{font-size:1.7rem;letter-spacing:.22em;text-align:center;padding:16px;border:1px solid var(--line2);border-radius:var(--r-sm);background:var(--bg);font-family:var(--display);font-weight:700;margin:12px 0 4px;user-select:all}
.login-card a{color:var(--fg);text-decoration:underline}

/* F2-T02b-2 (E19): "+ Nova câmera" como painel lateral sobre a tela Câmeras. Só tokens dos dois temas. */
.drawer-fundo{position:fixed;inset:0;z-index:40;background:rgba(7,21,35,.55)}
.drawer{position:fixed;top:0;right:0;bottom:0;z-index:41;width:min(560px,100vw);overflow-y:auto;padding:18px;
  background:var(--panel);color:var(--fg);border-left:1px solid var(--line2);box-shadow:var(--shadow)}
.drawer[hidden],.drawer-fundo[hidden]{display:none}
.drawer-cab{display:flex;gap:12px;align-items:flex-start;justify-content:space-between;margin-bottom:16px}
.drawer-cab .sub{color:var(--mut);font-size:.84rem;margin-top:2px}
.drawer .grid{grid-template-columns:1fr}

/* F2-T04b: Biblioteca (cota em barra, confirmação inline de apagar) e form "Salvar trecho" na tela Câmera. Só tokens existentes. */
.cota-bib{justify-content:space-between;margin-bottom:8px;gap:10px}
.cota-barra{display:block;width:100%;height:10px;appearance:none;-webkit-appearance:none;border:0;border-radius:5px;overflow:hidden;background:var(--line2)}
.cota-barra::-webkit-progress-bar{background:var(--line2)} .cota-barra::-webkit-progress-value{background:var(--accent)} .cota-barra::-moz-progress-bar{background:var(--accent)}
#biblioteca>.msg,#biblioteca>.card{margin-top:16px}
details.confirma summary{list-style:none;display:inline-block} details.confirma summary::-webkit-details-marker{display:none}
.confirma .pergunta{display:flex;gap:8px;align-items:center;flex-wrap:wrap;margin-top:6px}
.form-salvar{margin:12px 0 0} .msg-salvar{margin-top:8px} .msg-salvar .msg{margin-top:0}
@media (max-width:700px){.form-salvar input{min-height:44px}} /* alvo de toque >= 44 px nos campos do "Salvar trecho" no celular (F2-T10) */
#biblioteca .pill.crit{color:var(--fg)} #biblioteca .pill.crit .dot{color:var(--crit)}  /* texto do "falhou" em tinta: o vermelho do token sobre o fundo translúcido dava < 4,5:1 */
.filtros-trilha .field{min-width:150px} .filtros-trilha input,.filtros-trilha select{width:100%}
tr.mais td{text-align:center;padding:14px 8px}
#suporte-motivo{max-width:640px;margin-top:16px}
#tabela-trilha td.mono{white-space:nowrap}

/* F3-T01: ações por usuário e matriz de permissões do painel lateral. Só tokens existentes. */
.acoes-usuario{display:flex;gap:6px;align-items:flex-start;flex-wrap:wrap}
.acoes-usuario details.confirma{flex-basis:100%}
.btn.d:hover{background:var(--crit-s)}
#matriz-permissoes th[scope=row]{font-weight:600;font-size:.86rem;letter-spacing:0;text-transform:none;color:var(--fg);font-family:var(--body)}
#matriz-permissoes td{text-align:center} #matriz-permissoes thead th:not(:first-child){text-align:center}
#matriz-permissoes input[type=checkbox]{width:18px;height:18px;accent-color:var(--accent)}
/* ---- Disponibilidade (F3-T03): barras de 7 dias em CSS puro (a CSP não admite style inline: a altura é CLASSE h0..h10, a cor é ok/w/c/n; o texto do bloco está no <span class="sr-only"> e no title) */
#tabela-disponibilidade th[scope=row]{font-weight:600;font-size:.86rem;letter-spacing:0;text-transform:none;color:var(--fg);font-family:var(--body)}
#tabela-disponibilidade td,#tabela-disponibilidade tbody tr:first-child th{vertical-align:middle}
#tabela-disponibilidade tr.quedas td{padding-top:0}
#tabela-disponibilidade summary{cursor:pointer;color:var(--fg);font-size:.82rem;padding:4px 0}
#tabela-disponibilidade summary:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.lista-quedas{list-style:none;margin:6px 0 4px;padding:0;display:grid;gap:4px;font-size:.84rem}
.dias{display:flex;gap:3px;align-items:flex-end;height:30px;width:104px;list-style:none;margin:0;padding:0}
.dias li{flex:1;min-width:10px;border-radius:2px 2px 0 0;background:var(--ok)}
.dias li.w{background:var(--warn)} .dias li.c{background:var(--crit)}
.dias li.n{background:transparent;border:1px dashed var(--mut);height:20%}
.dias li.h0{height:20%} .dias li.h1{height:10%} .dias li.h2{height:20%} .dias li.h3{height:30%} .dias li.h4{height:40%} .dias li.h5{height:50%}
.dias li.h6{height:60%} .dias li.h7{height:70%} .dias li.h8{height:80%} .dias li.h9{height:90%} .dias li.h10{height:100%}

/* ---- Mosaico (F3-T05): grade de tiles (até 16), lista lateral. Sem estilo inline (CSP): a grade vem de data-layout. Overlays sobre o vídeo = fundo escuro
   translúcido com texto branco, como o .estado da tela Câmera (contraste >= 4,5:1 mesmo sobre quadro claro). */
#mosaico{display:grid;gap:14px}
.tiles{display:grid;gap:6px;background:#05070a;padding:6px;border-radius:var(--r);border:1px solid var(--line2);box-shadow:var(--shadow)}
.tiles[data-layout="1x1"]{grid-template-columns:minmax(0,1fr)}
.tiles[data-layout="2x2"]{grid-template-columns:repeat(2,minmax(0,1fr))}
.tiles[data-layout="3x3"],.tiles[data-layout="1+5"]{grid-template-columns:repeat(3,minmax(0,1fr))}
.tiles[data-layout="4x4"],.tiles[data-layout="1+7"]{grid-template-columns:repeat(4,minmax(0,1fr))}
.tiles[data-layout="1+5"] .tile:first-child{grid-column:span 2;grid-row:span 2;aspect-ratio:auto}
.tiles[data-layout="1+7"] .tile:first-child{grid-column:span 3;grid-row:span 3;aspect-ratio:auto}
.tile{aspect-ratio:16/9;background:#0b1016;position:relative;border-radius:6px;overflow:hidden;min-width:0;font-family:var(--mono);font-size:.72rem;color:#fff}
.tile video{position:absolute;inset:0;width:100%;height:100%;object-fit:contain;background:#05070a}
.tile .lbl{position:absolute;left:6px;right:96px;top:6px;z-index:2;max-width:max-content;padding:3px 7px;border-radius:5px;background:rgba(0,0,0,.72);color:#fff;font-size:.7rem}
.tile .lbl .nm{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.tile .rel{position:absolute;right:6px;bottom:6px;z-index:2;padding:3px 7px;border-radius:5px;background:rgba(0,0,0,.72);color:#fff;font-size:.7rem;white-space:nowrap}
.tile .rel:empty{display:none}
.tile .vaga{position:absolute;inset:0;width:100%;height:100%;border:1px dashed #8aa0b4;border-radius:6px;background:transparent;color:#d6e2ee;font:inherit;cursor:pointer}
.tile .vaga:hover,.tile .vaga:focus-visible{background:rgba(255,255,255,.07);outline:2px solid #fff;outline-offset:-3px}
.tile .est{position:absolute;left:6px;bottom:6px;z-index:2;max-width:calc(100% - 84px);padding:3px 8px;border-radius:5px;background:rgba(0,0,0,.72);color:#fff;font-size:.7rem}
.tile .est[data-estado="online"]{border-left:3px solid #ff5a5f}
.tile .est[data-estado="offline"],.tile .est[data-estado="sem_codec"],.tile .est[data-estado="sem_permissao"]{background:rgba(120,20,25,.9);color:#fff}
.tile .ferr{position:absolute;right:6px;top:6px;z-index:2;display:flex;gap:4px}
.tile .ferr .btn.sm{padding:1px 6px;font-size:.72rem;line-height:1.3}
.tile.sel{outline:3px solid var(--teal);outline-offset:-3px}
.tile.alvo{outline:3px dashed #fff;outline-offset:-3px}
.tiles:fullscreen{width:100vw;height:100vh;box-sizing:border-box;align-content:stretch;grid-auto-rows:minmax(0,1fr);border:0;border-radius:0;box-shadow:none}
.tiles:fullscreen .tile{aspect-ratio:auto}
/* Anexo F3-T05 (06/10): duplo clique no tile o AMPLIA na área do mosaico (os outros somem do layout, o <video> é o mesmo nó); `touch-action:manipulation` = o toque duplo não dá zoom no navegador */
.tile{touch-action:manipulation;-webkit-user-select:none;user-select:none}
.tile:focus-visible{outline:3px solid #fff;outline-offset:-3px}
.tiles[data-ampliado] .tile:not(.ampliado){display:none}
.tiles[data-ampliado] .tile.ampliado{grid-column:1/-1;grid-row:auto;aspect-ratio:16/9}
.tiles:fullscreen[data-ampliado] .tile.ampliado{aspect-ratio:auto}
.tile .voltar{position:absolute;right:6px;top:52px;z-index:3;min-width:44px;min-height:44px;padding:0 14px;border:1px solid #fff;border-radius:6px;background:#0b1016;color:#fff;font:inherit;font-size:.8rem;cursor:pointer}
.tile .voltar:hover{background:#1d2a36}
.tile .voltar:focus-visible{outline:3px solid #fff;outline-offset:2px}
.camlist{background:var(--panel);border:1px solid var(--line);border-radius:var(--r);box-shadow:var(--shadow);padding:12px;display:flex;flex-direction:column;gap:8px}
.cams{list-style:none;margin:0;padding:0;display:grid;gap:4px;max-height:560px;overflow:auto}
.cams li[hidden]{display:none}
button.cam{display:flex;gap:10px;align-items:center;width:100%;text-align:left;padding:8px;border-radius:var(--r-sm);cursor:grab;border:1px solid transparent;background:transparent;color:var(--fg);font:inherit}
button.cam:hover,button.cam:focus-visible{background:var(--panel2);border-color:var(--line2)}
button.cam:focus-visible{outline:2px solid var(--accent);outline-offset:1px}
button.cam[data-vaga]{border-color:var(--accent)}
.cam .th{width:54px;height:34px;border-radius:4px;background:linear-gradient(135deg,#223b4a,#0b1016);flex:none;border:1px solid var(--line2)}
.cam .th.off{background:#0b1016}
.cam-txt{display:grid;gap:3px;min-width:0}
.cam .nm{font-size:.8rem;font-weight:500;line-height:1.2}
.cam .id{font-size:.7rem;color:var(--mut)}
.cam .uso{font-size:.7rem;font-weight:600;color:var(--fg)}
.layouts{list-style:none;margin:12px 0 0;padding:0;display:grid;gap:8px}
.layouts li{display:flex;gap:10px;align-items:center;flex-wrap:wrap}
.layouts li .nm{font-weight:600;min-width:120px}
#m-salvar{align-items:flex-end;gap:10px;flex-wrap:wrap}
#m-msg{margin:0}

/* ---- Área do cliente final em UMA tela (F2-T02c): barra lateral "Minhas câmeras" + visualização (uma câmera ou mosaico). Só tokens existentes; sem estilo inline (CSP).
   Celular (<= 480 px): a lista vira faixa rolável acima do vídeo e todo botão tem >= 44 px (a barra da linha do tempo é um apontador, não um botão). */
.app.sem-menu{grid-template-columns:1fr}
.minha{display:grid;grid-template-columns:280px minmax(0,1fr);gap:16px;align-items:start}
.lateral{position:sticky;top:70px;max-height:calc(100vh - 90px);overflow:auto}
.lateral .cams{max-height:none}
.lat-tit{font-family:var(--display);font-size:1.05rem;margin:0}
button.cam.on{border-color:var(--accent-2);box-shadow:inset 0 0 0 1px var(--accent-2)} /* a seleção é só a borda: o fundo não muda, e o contraste da pílula de estado também não */
.vista-col{display:grid;gap:14px;min-width:0}
.modos-vista{display:flex;gap:8px;flex-wrap:wrap}
.btn.mv{min-height:44px}
.btn.mv[aria-pressed="true"]{background:var(--accent);border-color:var(--accent);color:var(--accent-fg)}
.vista,.minha #camera{display:grid;gap:16px;min-width:0;grid-template-columns:minmax(0,1fr)} /* a coluna encolhe: o min-content do conteúdo não alarga a página no celular */
.cam-cab{display:flex;align-items:baseline;justify-content:space-between;gap:12px;flex-wrap:wrap}
.cam-h{font-family:var(--display);font-size:1.15rem;margin:0}
.minha .tile video{cursor:pointer}
.player:fullscreen{width:100vw;height:100vh;max-width:none;aspect-ratio:auto;border:0;border-radius:0}
@media (max-width:900px){.minha{grid-template-columns:minmax(0,1fr)}.lateral{position:static;max-height:none}}
@media (max-width:480px){
  .lateral{padding:10px}
  .lateral .cams{display:flex;overflow-x:auto;gap:8px;padding-bottom:6px}
  .lateral .cams li{flex:0 0 auto;min-width:170px}
  .minha .btn,.minha .btn.sm,.minha button.cam,.minha summary.btn{min-height:44px;min-width:44px}
  .btn.mv[data-modo="3x3"],.btn.mv[data-modo="4x4"]{display:none}
  .minha .tile .ferr .btn.sm{padding:0}
  .minha .tile .ferr .qual{min-width:44px;min-height:44px;padding:0} /* o SD/HD do F2-T03d no tile: 34 px no celular (prova t02c) */
}
.minha .btn:disabled{opacity:1;color:var(--mut);border-style:dashed;cursor:not-allowed} /* inativo legível: o 50% de opacidade dava < 4,5:1 */
@media (max-width:480px){.sem-menu .topbar button,.sem-menu .topbar .btn{min-height:44px;min-width:44px}.sem-menu .topbar .chip{display:none}} /* celular: logo, tema e Sair (o desenho aprovado) */

/* ---- E23 (dono 04/10): o mosaico do cliente final OCUPA a área útil (altura da janela, da barra lateral à borda), fundo escuro, sem cartão nem título; tiles colados com só
   nome (esq.), data/hora (dir.) e ✕; comandos numa barra compacta no topo. Referência: docs/fundacao/uiux/referencias/monuv_mosaico_2x2.png. No celular segue o empilhado acima. */
@media (min-width:901px){
  main:has(.minha:not([data-modo="uma"])){padding:0}
  .minha:not([data-modo="uma"]){gap:0;height:calc(100vh - 57px);align-items:stretch}
  .minha:not([data-modo="uma"]) .lateral{position:static;height:100%;max-height:none;border-radius:0;border-width:0 1px 0 0;box-shadow:none}
  .minha:not([data-modo="uma"]) .vista-col{position:relative;display:flex;flex-direction:column;gap:0;background:#05070a;height:100%;min-height:0}
  .minha:not([data-modo="uma"]) #modos{background:#0b1016;padding:8px;gap:8px;border-bottom:1px solid #1d2a36;flex:none}
  .minha:not([data-modo="uma"]) .vista,.minha:not([data-modo="uma"]) #mosaico{display:contents}
  .minha:not([data-modo="uma"]) .cam-cab{position:absolute;top:8px;right:8px;z-index:3}
  .minha:not([data-modo="uma"]) .cam-h{display:none}
  .minha:not([data-modo="uma"]) #m-msg{position:absolute;bottom:12px;left:50%;transform:translateX(-50%);z-index:5;margin:0}
  .minha:not([data-modo="uma"]) .tiles{flex:1;min-height:0;gap:1px;padding:0;border:0;border-radius:0;box-shadow:none;background:#1d2a36;grid-auto-rows:minmax(0,1fr)}
  .minha:not([data-modo="uma"]) .tile{aspect-ratio:auto;border-radius:0;container-type:inline-size}
  .minha:not([data-modo="uma"]) .tiles[data-ampliado] .tile.ampliado{aspect-ratio:auto}
  .minha:not([data-modo="uma"]) .tile .lbl{left:0;top:0;right:200px;border-radius:0 0 5px 0}
  .minha:not([data-modo="uma"]) .tile .rel{top:6px;right:84px;bottom:auto} /* à esquerda do SD/HD + ✕ (F2-T03d): com 40px o relógio ficava POR BAIXO do botão (texto branco sobre o vídeo cinza: 3,95:1) */
  .minha:not([data-modo="uma"]) .tile .ferr{top:4px;right:4px}
  .minha:not([data-modo="uma"]) .tile .lbl .nm{white-space:normal;overflow:visible;text-overflow:clip;overflow-wrap:anywhere} /* o nome INTEIRO: quebra em linhas em vez de reticências (Codex r1 B1) */
  @container (max-width:330px){ /* tile estreito (4×4 em janela pequena): nome (quebrando) e ✕ no alto, data/hora no pé do tile, nada recortado nem sobreposto */
    .minha:not([data-modo="uma"]) .tile .lbl{right:88px}
    .minha:not([data-modo="uma"]) .tile .rel{top:auto;bottom:0;left:0;right:auto;border-radius:0 5px 0 0}
  }
  .minha:not([data-modo="uma"]) .tile .ferr button[aria-label^="Trocar"]{display:none}
  .minha:not([data-modo="uma"]) .tile .est[data-estado="online"]{display:none}
  .minha:not([data-modo="uma"]) .tile video{object-fit:contain} /* nunca recorta o campo de visão: faixas pretas no tile, como todo VMS */
}

/* ---- F3-T05b: o Mosaico da REVENDA usa o MESMO leiaute do cliente final (acima): `.minha` com data-modo != uma. Só muda o lado da lista (à direita, como na referência da
   Monuv) e a barra de comandos (grades, "Gerenciar mosaico" como menu suspenso <details>, Tela cheia). */
.minha.lista-dir{grid-template-columns:minmax(0,1fr) 280px}
.menu-ger{position:relative}
.menu-ger>summary{list-style:none}
.menu-ger>summary::-webkit-details-marker{display:none}
.menu-ger[open]>summary{background:var(--accent);border-color:var(--accent);color:var(--accent-fg)}
.menu-painel{position:absolute;top:calc(100% + 6px);left:0;z-index:8;width:min(420px,90vw);max-height:70vh;overflow:auto;background:var(--panel);color:var(--fg);border:1px solid var(--line2);border-radius:var(--r);box-shadow:var(--shadow);padding:14px;display:grid;gap:10px}
.menu-painel .note{margin:0}
@media (max-width:900px){.minha.lista-dir{grid-template-columns:minmax(0,1fr)}}
.minha .eyebrow{color:var(--mut)} /* 10,5 px em caixa alta: --mut2 dava 4,44:1 no claro */
@media (min-width:901px){
  .minha.lista-dir:not([data-modo="uma"]) .lateral{border-width:0 0 0 1px}
  .minha:not([data-modo="uma"]) #modos{align-items:center}
  .minha:not([data-modo="uma"]) #modos .chip-f{padding:5px 10px}
  .minha:not([data-modo="uma"]) #m-msg{background:var(--panel)} /* o aviso flutua sobre a grade escura: fundo opaco, senão o texto verde/vermelho do aviso perde o contraste (2,1:1 medido) */
  @container (max-width:150px){ /* tile muito estreito (4×4 com menu e lista a 901 px): a data/hora quebra em 2 linhas no pé do tile em vez de passar da borda */
    .minha:not([data-modo="uma"]) .tile .rel{white-space:normal;max-width:100%}
    .minha:not([data-modo="uma"]) .tile .lbl{top:28px;right:0} /* ✕ sozinho na 1ª linha; o nome ganha a largura inteira (um nome real de ~34 letras vira 3 linhas, não 8) */
  }
}
@media (max-width:480px){.chip.troca{max-width:100%}.chip.troca select{max-width:120px}} /* celular: o chip do cliente escolhido (revenda) alargava a página para 427 px e a faixa de câmeras da tela Câmera passava da borda */

/* ---- F3-T05c: Mosaico GERAL da revenda (`/mosaico`): lista lateral agrupada por cliente (grupo recolhível, caixa de marca para a ronda) e a barra da ronda. Só tokens existentes. */
.gr{display:grid;gap:2px}
.gr[hidden]{display:none}
.gr-cab{display:flex;align-items:center;gap:6px;position:sticky;top:0;z-index:1;background:var(--panel)}
.gr-tit{flex:1;min-width:0;text-align:left;background:transparent;border:0;border-bottom:1px solid var(--line);color:var(--fg);font-family:var(--display);font-size:.8rem;font-weight:700;padding:8px 4px;cursor:pointer}
.gr-tit::before{content:"\25BE";display:inline-block;width:1.3em;color:var(--mut)}
.gr-tit[aria-expanded="false"]::before{content:"\25B8"}
.gr-tit:focus-visible,.marca:focus-visible,.gr-marca:focus-visible{outline:2px solid var(--accent);outline-offset:1px}
.gr-cams{list-style:none;margin:0;padding:0 0 6px;display:grid;gap:4px}
.gr[data-recolhido="true"] .gr-cams{display:none}
.cams[data-busca] .gr[data-recolhido="true"] .gr-cams{display:grid}
.gr-cams>li{display:flex;align-items:center;gap:4px}
.gr-cams>li button.cam{flex:1;min-width:0;width:auto}
.marca,.gr-marca{width:18px;height:18px;flex:none;margin:0;accent-color:var(--accent);cursor:pointer}
.ronda-barra{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.ronda-barra[hidden]{display:none}
.ronda-barra .mono{color:var(--fg);font-size:.8rem}
.menu-painel select{width:100%}
.minha[data-ronda] #m-lista .cam{cursor:not-allowed}
.minha[data-ronda] .tile .ferr,.minha[data-ronda] .tile .vaga{display:none}

/* F4-T01: Licenças do cliente (formulário em linha; selects dentro da confirmação inline). Só tokens existentes. */
.form-linha{display:flex;flex-wrap:wrap;gap:12px;align-items:flex-end} .form-linha input[type=number]{width:110px} #licencas-cliente>.msg,#licencas-cliente>.card,#licencas-cliente>.grid{margin-top:16px} #licencas-cliente .pergunta select{max-width:220px}
#licencas-cliente>.msg{color:var(--fg)}  /* o vermelho/verde do token sobre o fundo translúcido dava < 4,5:1 no tema claro: texto em tinta, o aviso se distingue pela borda e pelo fundo */

/* F4-T05: "entrar como" — a faixa avisa que a Cogn.IA age no nome de uma revenda. Cores literais (valem nos 2 temas): fundo âmbar #ffd166 com tinta
   #1c1400 = 13,2:1 (o botão Sair é o inverso). Fica fixa sob o topo (a grade ganha uma linha). */
.app.com-faixa{grid-template-rows:auto auto 1fr}
.faixa-revenda{grid-column:1/-1;position:sticky;top:0;z-index:40;display:flex;flex-wrap:wrap;gap:12px;align-items:center;justify-content:center;min-height:44px;padding:8px 18px;background:#ffd166;color:#1c1400;border-bottom:3px solid #1c1400;font-size:.95rem}
.faixa-revenda b{font-weight:800}
.faixa-revenda form{margin:0}
.faixa-revenda .btn,.faixa-revenda .btn:hover{background:#1c1400;color:#ffd166;border-color:#1c1400}
.faixa-revenda .btn:focus-visible{outline:2px solid #1c1400;outline-offset:2px}
.com-faixa .topbar{top:44px}
.com-faixa nav.rail{top:97px;max-height:calc(100vh - 97px)}
.painel-cognia .tbl{position:relative} .painel-cognia .tbl td form{display:inline;margin:0}
.nova-revenda{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:12px;align-items:end}
/* F1-T08: selo de bitrate acima do teto / gravação suspensa. Texto em tinta (--fg) sobre o fundo do cartão; o aviso se distingue pelo ponto e pela borda — o laranja/vermelho do token sobre fundo translúcido dá < 4,5:1 no tema claro */
.selos{margin-top:6px;display:flex;flex-wrap:wrap;gap:6px} td .selos{margin-top:4px}
.pill.selo-teto{color:var(--fg);background:var(--panel2);border-color:var(--warn);font-weight:600} .pill.selo-teto .dot{color:var(--warn)} .pill.selo-susp{border-color:var(--crit)} .pill.selo-susp .dot{color:var(--crit)}
#aviso-gravacao-suspensa,#aviso-acima-do-teto{color:var(--fg)}
.uso-mes{justify-content:space-between} .uso-mes-form{display:flex;gap:8px;align-items:center} .uso-mes-form select{width:auto;min-width:200px}
.tbl .num{text-align:right;font-variant-numeric:tabular-nums}

/* ---- F2-T02e: a BARRA DE CÂMERAS da revenda (`_lista_cameras.html`), a mesma na tela Câmera e nos Mosaicos: filtro de estado (1.000 câmeras medidas em prova_f2t02e.py: abre em < 1 s sem virtualizar)
   e no celular ela fica ABAIXO do player (lista vertical rolável; a faixa horizontal é do cliente final). */
.lateral[data-componente] .chips{display:flex;gap:6px;flex-wrap:wrap;border:0;padding:0;margin:0}
.lateral[data-componente] .cams{overflow-x:hidden}
@media (max-width:480px){
  .lateral[data-componente] .cams{display:grid;overflow-x:hidden;overflow-y:auto;max-height:60vh;padding-bottom:0}
  .lateral[data-componente] .cams li{min-width:0}
}

/* ---- F2-T02e (dono 05/10): o PLAYER é o protagonista. (a) barra de câmeras à direita (280 px) RECOLHÍVEL por botão na própria barra (vira uma tira de 44 px); (b) o MENU lateral
   nasce RECOLHIDO nas telas de vídeo (Câmera, Mosaico, Mapa: classe `rail-video` no .app, decidida em rotas.TELAS_DE_VIDEO): só ícones, dica no hover/foco, botão para expandir. */
.lat-cab{display:flex;align-items:center;justify-content:space-between;gap:8px}
.lat-mini{font-family:var(--display);font-size:.8rem;font-weight:700;color:var(--fg)}
.lat-corpo{display:flex;flex-direction:column;gap:8px;min-height:0}
.lateral[data-recolhida] .lat-corpo,.lateral[data-recolhida] .lat-mini{display:none}
.lateral[data-recolhida]{padding:8px 6px;align-items:center}
.minha.lista-dir:has(.lateral[data-recolhida]){grid-template-columns:minmax(0,1fr) 44px}
@media (max-width:900px){.minha.lista-dir:has(.lateral[data-recolhida]){grid-template-columns:minmax(0,1fr)}}
.minha[data-modo="uma"] #camera .card{padding:12px} /* o vídeo ganha a largura que o cartão gastava */
.rail-btn{width:100%;margin:0 0 8px;padding:7px 10px;border-radius:var(--r-sm);border:1px solid var(--line2);background:var(--panel2);color:var(--fg);font:inherit;font-size:.82rem;cursor:pointer}
.rail-btn:focus-visible{outline:2px solid var(--accent);outline-offset:1px}
@media (min-width:861px){
  .app.rail-video:not(.rail-aberto){grid-template-columns:64px 1fr}
  .app.rail-video:not(.rail-aberto) nav.rail{padding:10px 8px;overflow:visible}
  .app.rail-video:not(.rail-aberto) nav.rail a{font-size:0;justify-content:center;padding:9px 0;position:relative}
  .app.rail-video:not(.rail-aberto) nav.rail .eyebrow{display:none}
  .app.rail-video:not(.rail-aberto) nav.rail a:hover::after,.app.rail-video:not(.rail-aberto) nav.rail a:focus-visible::after{content:attr(data-dica);position:absolute;left:calc(100% + 10px);top:50%;transform:translateY(-50%);background:var(--panel);color:var(--fg);border:1px solid var(--line2);border-radius:var(--r-sm);padding:5px 9px;font-size:.8rem;font-weight:500;white-space:nowrap;z-index:30;box-shadow:var(--shadow)}
}
main:has(.minha[data-modo="uma"]){padding:14px} /* tela Câmera: o player é o protagonista, a margem é mínima */
.minha[data-modo="uma"].lista-dir{gap:12px}
@media (max-width:480px){.lateral[data-componente] .gr-tit{min-height:44px}} /* celular: alvo de toque >= 44 px */
/* F4-T05C (Usuários da Cogn.IA): a recusa (.msg.e) em vermelho sobre o fundo translúcido dava 4,06:1 no claro e 2,72:1 no escuro; texto em tinta, a recusa se distingue pela borda e pelo fundo (a mesma saída da tela Licenças) */
.usuarios-cognia .msg.e,.drawer-cognia .msg.e{color:var(--fg)}

/* F2-T08 — página do CLIENTE e página da REVENDA: uma página por entidade, com abas. Só classes (a CSP não admite style em linha); alvos >= 44 px em qualquer largura. */
.migalhas{font-size:.84rem;color:var(--mut);margin:0 0 10px} .migalhas a{color:var(--link-txt);text-decoration:underline}
.cli-cab{align-items:center;gap:12px} .cli-pills{display:flex;gap:8px;flex-wrap:wrap;margin-right:auto}
.abas-ent{display:flex;gap:4px;flex-wrap:wrap;border-bottom:1px solid var(--line);margin:0 0 16px}
.abas-ent a{min-height:44px;display:inline-flex;align-items:center;padding:0 16px;color:var(--mut);text-decoration:none;font-family:var(--display);font-weight:500;font-size:.88rem;border-bottom:3px solid transparent;margin-bottom:-1px}
.abas-ent a:hover{color:var(--fg)} .abas-ent a[aria-selected="true"]{color:var(--fg);font-weight:600;border-bottom-color:var(--teal)}
.aba-cab{margin-bottom:10px} .aba-cab h2{margin:0}
.cli-cab .btn,.rev-cab .btn,.aba-corpo .btn,.aba-corpo .btn.sm,.aba-corpo summary.btn{min-height:44px;min-width:44px;display:inline-flex;align-items:center;justify-content:center}
.aba-corpo input,.aba-corpo select,.aba-corpo textarea{min-height:44px}
.aba-corpo input[type=checkbox],.aba-corpo input[type=radio]{min-height:0;width:20px;height:20px}
.aba-corpo .tbl .btn.sm{min-height:44px}
#aviso-sujo{display:flex;gap:12px;align-items:center;flex-wrap:wrap;margin-bottom:12px} #aviso-sujo[hidden]{display:none}
.cli-grade{display:grid;grid-template-columns:minmax(0,3fr) minmax(0,2fr);gap:16px;align-items:start}
.campos{display:grid;gap:12px;margin:8px 0} .campos.c2{grid-template-columns:repeat(2,minmax(0,1fr))} .campos.c4{grid-template-columns:repeat(4,minmax(0,1fr))}
.campos .c-2{grid-column:span 2} .campos .c-todo{grid-column:1/-1}
.sec-sub{margin:16px 0 4px;color:var(--mut);text-transform:uppercase;letter-spacing:.08em;font-size:.72rem}
.contatos{display:grid;gap:8px;margin:6px 0}
.contato{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1.4fr) minmax(0,1.2fr) 44px;gap:8px;align-items:center}
.acao-cli{margin-top:12px} .erro-campo{display:block;color:var(--crit);font-size:.78rem;margin-top:4px}
input[aria-invalid="true"],select[aria-invalid="true"],textarea[aria-invalid="true"]{border-color:var(--crit)}
.uf{text-transform:uppercase} .apagar-cli{margin-top:16px}
/* Observações do cliente: a textarea não herdava a regra `input,select{width:100%}` do app.css (ficava na largura padrão do navegador, estreita): largura toda do formulário e ~4 linhas (F2-T02f anexo). */
.cli-form textarea{display:block;box-sizing:border-box;font:inherit;line-height:1.5;width:100%;min-height:calc(4 * 1.5em + 20px);padding:9px 11px;border:1px solid var(--line2);border-radius:var(--r-sm);background:var(--bg);color:var(--fg);resize:vertical}
.cli-form textarea:focus-visible{outline:2px solid var(--accent)}
.cli-pino{display:block;width:26px;height:26px;border-radius:50% 50% 50% 0;transform:rotate(-45deg);background:var(--accent);border:3px solid var(--panel);box-shadow:0 1px 5px rgba(0,0,0,.5)}
.leaflet-marker-icon.cli-pino-icone{background:none;border:0;overflow:visible}
.leaflet-marker-icon.cli-pino-icone:focus-visible .cli-pino{outline:3px solid var(--fg);outline-offset:2px}
.rev-cab{align-items:center;gap:12px} .rev-kpis{margin-bottom:16px}
.checks{display:flex;gap:20px;flex-wrap:wrap;margin:8px 0} .checks label{display:flex;align-items:center;gap:8px;min-height:44px;text-transform:none;letter-spacing:0;font-size:.86rem;color:var(--fg);margin:0}
.roteiro{margin-top:12px;padding:12px 14px;border:1px solid var(--warn);border-radius:var(--r-sm);background:var(--warn-s);font-size:.84rem;line-height:1.55}
.busca-linha{display:flex;gap:12px;align-items:flex-end;flex-wrap:wrap;margin-bottom:10px} .busca-linha .field{flex:1 1 240px;max-width:420px}
@media (max-width:1000px){.cli-grade{grid-template-columns:1fr}}
@media (max-width:700px){.campos.c2,.campos.c4{grid-template-columns:1fr}.campos .c-2,.campos .c-todo{grid-column:auto}
  .contato{grid-template-columns:minmax(0,1fr) 44px}.contato input{grid-column:1}.contato button{grid-column:2;grid-row:1/4;align-self:stretch}}
.migalhas a,.aba-corpo td a:not(.btn){display:inline-flex;align-items:center;min-height:44px}
@media (max-width:700px){.painel-cognia .acoes-usuario .btn,.painel-cognia .acoes-usuario summary.btn{min-height:44px;min-width:44px;display:inline-flex;align-items:center;justify-content:center}}

/* F2-T08: textos de estado nas páginas novas com >= 4,5:1 nos 2 temas (o --ok/--warn/--crit do tema claro dão 3,6 a 4,4 sobre o fundo do selo; no escuro os mesmos tokens já passam) */
:root{--ok-txt:#12693a;--warn-txt:#80520a;--crit-txt:#a52a1e;--link-txt:var(--accent)}
@media (prefers-color-scheme: dark){:root:not([data-theme="light"]){--ok-txt:var(--ok);--warn-txt:var(--warn);--crit-txt:var(--crit);--link-txt:var(--teal)}}
:root[data-theme="dark"]{--ok-txt:var(--ok);--warn-txt:var(--warn);--crit-txt:var(--crit);--link-txt:var(--teal)}
.cli-cab .pill.ok,.rev-cab .pill.ok,.aba-corpo .pill.ok{color:var(--ok-txt)} .cli-cab .pill.warn,.rev-cab .pill.warn,.aba-corpo .pill.warn{color:var(--warn-txt)}
.aba-corpo .pill.crit{color:var(--crit-txt)} #aviso-sujo.msg.e,#aviso-pagina.msg.e,.aba-corpo .msg.e{color:var(--crit-txt)} #aviso-pagina.msg.o{color:var(--ok-txt)}  /* o verde do token a 4,47:1 sobre o fundo translúcido (tema claro) caía abaixo de 4,5 quando a página cresceu (caixa Observações maior); o token -txt é o mesmo do crit */ .erro-campo{color:var(--crit-txt)}
.aba-corpo .roteiro{color:var(--fg)} .aba-corpo .roteiro b{color:var(--warn-txt)}
.entrar-rev{display:flex;gap:8px;flex-wrap:wrap;align-items:center;max-width:100%} .entrar-rev input{flex:1 1 220px;min-width:0;width:auto}
/* F2-T08: no celular a trilha do grid encolhe (o seletor de cliente do topo tem largura mínima de ~600 px e alargava a página inteira: rolagem lateral medida 628 px em 390) */
@media (max-width:860px){.app{grid-template-columns:minmax(0,1fr)}.topbar{flex-wrap:wrap}.topbar .ctx{margin-left:0;min-width:0;max-width:100%}.topbar .chip.troca{max-width:100%;flex-wrap:wrap}.topbar .chip.troca select,.topbar .chip.troca input{min-width:0;max-width:100%}}
.rev-cab input{min-height:44px}

/* ---- F2-T02f (dono 05/10): UMA tela de câmeras da revenda — submenu de abas (Câmera única · Mosaico · Mapa; alvo >= 44 px) e a mesma lista à direita nas três vistas. Só tokens existentes. */
.abas-cab{display:flex;align-items:center;gap:16px;flex-wrap:wrap}
.abas-cab h1,.abas-tit{margin:0;font-family:var(--display);font-size:1.25rem;font-weight:700}
.abas{display:flex;gap:4px;padding:4px;border-radius:10px;border:1px solid var(--line2);background:var(--panel)}
.abas a{min-height:44px;min-width:44px;box-sizing:border-box;display:flex;align-items:center;justify-content:center;padding:0 16px;border-radius:7px;border:1px solid transparent;color:var(--fg);font-weight:600;font-size:.9rem;text-decoration:none}
.abas a:hover{background:var(--panel2)}
.abas a[aria-selected="true"]{background:var(--accent);border-color:var(--accent);color:var(--accent-fg)}
.abas a:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.cam .inst{font-weight:700;color:var(--fg)} /* "N quedas/h": o motivo do "Instável" em texto, na tinta normal (a cor nunca é o único sinal) */
@media (min-width:901px){
  .minha[data-modo="grade"] .abas-cab{flex:none;padding:8px;background:#0b1016;border-bottom:1px solid #1d2a36}
  .minha[data-modo="grade"] .abas-cab h1{color:#e6edf3} /* a coluna do Mosaico é escura nos 2 temas */
}
@media (max-width:480px){ /* celular: alvos >= 44 px na tela única (chips da lista/mapa e o zoom do Leaflet) */
  .minha .chip-f{min-height:44px;box-sizing:border-box;display:inline-flex;align-items:center}
  .minha .leaflet-bar.leaflet-control-zoom a{width:44px;height:44px;line-height:44px}
}

/* Contas Hik-Connect (F1-T02f anexo 07/10): "Testar" e "Excluir" na mesma célula; o Excluir bloqueado (conta com câmera) segue legível: o 50% de opacidade dava < 4,5:1 */
.acoes-conta{display:flex;flex-direction:column;gap:8px;align-items:flex-start} .acoes-conta .row{flex-wrap:wrap;align-items:center} #tabela-contas .btn:disabled{opacity:1;color:var(--mut);border-style:dashed;cursor:not-allowed}
.tbl-contas{position:relative} /* o .sr-only (absoluto) das células rolaria a PÁGINA a 390 px: ancorado no .tbl, o overflow o recorta */
#tabela-contas .pill.crit{color:var(--fg)} #tabela-contas .pill.crit .dot{color:var(--crit)}  /* "login recusado" em tinta (o vermelho do token dava 4,27:1 no tema claro), como o equipamento inalcançável */
#tabela-contas .pill.warn{color:var(--fg)} #tabela-contas .pill.warn .dot{color:var(--warn)}

/* ---- Clientes em mestre-detalhe (dono 08/10): barra de clientes à DIREITA, cadastro no meio. A barra vem antes no DOM: desktop = coluna 2 do grid; <= 900 px = bloco acima do conteúdo
   (busca + adicionar + lista rolável curta). Só tokens dos dois temas; texto secundário em --mut (>= 4,5:1 nos dois). */
.cli-md{display:grid;grid-template-columns:minmax(0,1fr) 300px;gap:16px;align-items:start}
.cli-barra{grid-column:2;grid-row:1;position:sticky;top:70px;display:grid;gap:12px;max-height:calc(100vh - 90px);overflow:hidden;grid-template-rows:auto auto auto minmax(0,1fr) auto}
.cli-centro{grid-column:1;grid-row:1;min-width:0}
.cli-busca{display:flex;gap:8px;align-items:center} .cli-busca input{flex:1 1 auto;min-width:0;min-height:44px}
.cli-busca .btn,.cli-add>summary{min-height:44px;display:inline-flex;align-items:center;justify-content:center}
.cli-add>summary{list-style:none;width:100%;cursor:pointer} .cli-add>summary::-webkit-details-marker{display:none}
.cli-novo{display:grid;gap:8px;margin-top:10px} .cli-novo input{min-height:44px} .cli-novo .btn{min-height:44px}
.cli-lista{list-style:none;margin:0;padding:0;display:grid;gap:4px;overflow-y:auto;min-height:0;align-content:start}
.cli-lista li[hidden]{display:none}
.cli-item{display:grid;gap:2px;padding:9px 11px;min-height:44px;border:1px solid transparent;border-radius:var(--r-sm);color:var(--fg);text-decoration:none}
.cli-item:hover{background:var(--panel2);border-color:var(--line2)}
.cli-item:focus-visible{outline:2px solid var(--accent-2);outline-offset:1px}
.cli-item[aria-current="page"]{background:var(--accent-s);border-color:var(--accent-2);box-shadow:inset 3px 0 0 var(--accent-2)}
.cli-nome{font-weight:600;overflow-wrap:anywhere}
.cli-res{color:var(--mut);font-size:.8rem}
.cli-nada{margin:0}
.cli-vazio{margin-bottom:16px}
@media (max-width:900px){
  .cli-md{grid-template-columns:minmax(0,1fr)}
  .cli-barra,.cli-centro{grid-column:1}
  .cli-barra{grid-row:1;position:static;max-height:none;overflow:visible}
  .cli-centro{grid-row:2}
  .cli-lista{max-height:220px}
}
/* o texto do botão destrutivo (Revogar, Apagar...) nas abas do cliente, tema escuro: com a barra de clientes à direita o brilho do fundo mudou de lugar e o --crit (#ff6b6b) caiu a 4,28:1 sobre o botão; #ff8a8a dá >= 5:1 */
/* tema claro, mesma causa: --crit (#c0392b) sobre o fundo/hover do botão dava 4,27:1 e a nota --mut (#526a79) sobre o fundo da tabela 4,48:1; tintas de texto do tema (--crit-txt, --silver) dão >= 5:1 */
.aba-corpo .btn.d{color:var(--crit-txt)} #tabela-equipamentos td .note{color:var(--silver)}
:root[data-theme="dark"] .aba-corpo .btn.d{color:#ff8a8a}
@media (prefers-color-scheme: dark){:root:not([data-theme="light"]) .aba-corpo .btn.d{color:#ff8a8a}}

/* ---- APP-T02 C: Cognia Feed (aba "Cognia Feed" do cliente e "Minha revenda > Cognia Feed"). Só tokens do portal; texto de estado em tinta (--ok-txt/--warn-txt) nos 2 temas. */
.feed-cab{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:12px;margin-bottom:8px}
.feed-grade{align-items:start;margin-bottom:16px}
.feed-uma{grid-template-columns:minmax(0,1fr)}  /* a aba do cliente é estreita (a barra de clientes fica à direita): uma seção embaixo da outra */
.feed-pagina .card{margin-bottom:16px} .feed-grade .card{margin-bottom:0}
.feed-pagina .pill.ok{color:var(--ok-txt)} .feed-pagina .pill.warn{color:var(--warn-txt)} .feed-pagina .msg.e{color:var(--crit-txt)}
.feed-pagina input,.feed-pagina select,.feed-pagina .btn{min-height:44px} .feed-pagina .btn{display:inline-flex;align-items:center;justify-content:center;min-width:44px}
.feed-contadores{border-top:1px solid var(--line);margin-top:16px;padding-top:14px} .feed-contadores .grid{margin:10px 0}
.feed-num{background:var(--panel2);border-radius:var(--r-sm);padding:12px;display:flex;flex-direction:column;gap:2px}
.feed-num .num{font-size:1.5rem;font-weight:600;font-family:var(--display)} .feed-num .num.warn{color:var(--warn-txt)}
.feed-dl{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px 16px;margin:0 0 12px} .feed-dl dt{color:var(--mut)} .feed-dl dd{margin:0;font-weight:500;overflow-wrap:anywhere}
.feed-convite summary{cursor:pointer;list-style:none} .feed-convite summary::-webkit-details-marker{display:none}
.feed-form{margin-top:12px;max-width:420px}
.feed-pagina .btn:disabled,.aba-corpo .feed-grade .btn:disabled{opacity:1;cursor:not-allowed;color:var(--fg);background:var(--panel2);border-style:dashed}  /* desabilitado, mas legível (4,5:1) nos 2 temas */
.feed-codigo{display:flex;flex-direction:column;gap:8px;margin-top:14px;color:var(--fg)} .feed-codigo .codigobox{display:block;margin:0;font-size:1.45rem;letter-spacing:.14em;white-space:nowrap;overflow-x:auto} .feed-codigo-tit{font-weight:600}
.feed-tabela form{margin:0} .feed-tabela td.warn{color:var(--warn-txt)} .feed-sem-local{margin:8px 0}
@media (max-width:560px){.feed-dl{grid-template-columns:1fr}}
