/* ============================================================
   AlfaMonitor Web — softened design system
   Catppuccin Mocha/Latte · Geist (UI) + JetBrains Mono (data)
   ============================================================ */

:root {
  /* dark — Catppuccin Mocha, softened */
  --crust:#0f0f17; --mantle:#16161f; --base:#1c1c27;
  --surface:#21212e; --surface2:#2a2a3a;
  --line:#2c2c3c; --line-soft:#24242f;
  --s2:#585b70;
  --ov0:#6c7086; --ov1:#838aa3; --ov2:#9aa0b8;
  --sub0:#aab0c8; --sub1:#c2c7dd; --text:#dfe3f2;

  --mauve:#cba6f7; --mauve-ink:#1c1c27;
  --blue:#89b4fa; --green:#a6e3a1; --peach:#fab387;
  --yellow:#f9e2af; --red:#f38ba8; --lavender:#b4befe; --teal:#94e2d5;

  --shadow-card:0 1px 2px rgba(0,0,0,.28), 0 8px 24px -12px rgba(0,0,0,.5);
  --shadow-pop:0 18px 50px -12px rgba(0,0,0,.6);
  --r-card:16px; --r-tile:13px; --r-pill:11px; --r-input:9px;

  --font-ui:"Geist","Geist Fallback",system-ui,-apple-system,"Segoe UI",sans-serif;
  --font-mono:"JetBrains Mono",ui-monospace,"SFMono-Regular",monospace;

  --maxw:1280px;
}

[data-theme="light"] {
  /* light — Catppuccin Latte, softened */
  --crust:#e8eaf0; --mantle:#eef0f6; --base:#ffffff;
  --surface:#f7f8fc; --surface2:#eef0f7;
  --line:#dfe2ec; --line-soft:#e8ebf3;
  --s2:#9ca0b8;
  --ov0:#8c8fa1; --ov1:#6e7186; --ov2:#5c5f72;
  --sub0:#565969; --sub1:#494c5c; --text:#3a3c4e;

  --mauve:#8839ef; --mauve-ink:#ffffff;
  --blue:#1e66f5; --green:#2fa33b; --peach:#e8650b;
  --yellow:#c98a08; --red:#d20f39; --lavender:#7287fd; --teal:#179299;

  --shadow-card:0 1px 2px rgba(76,79,105,.07), 0 10px 28px -16px rgba(76,79,105,.28);
  --shadow-pop:0 20px 56px -16px rgba(76,79,105,.32);
}

* { box-sizing:border-box; }
html, body { margin:0; height:100%; }
body {
  font-family:var(--font-ui);
  background:var(--crust); color:var(--text);
  -webkit-font-smoothing:antialiased; text-rendering:optimizeLegibility;
  font-size:14px; line-height:1.5;
}
.mono { font-family:var(--font-mono); font-variant-numeric:tabular-nums; }
.num  { font-variant-numeric:tabular-nums; }
a { color:inherit; text-decoration:none; }
button { font-family:inherit; }
::selection { background:color-mix(in srgb,var(--mauve) 32%,transparent); }

/* ============================================================
   APP SHELL
   ============================================================ */
.app { min-height:100%; display:flex; flex-direction:column; }

.topbar {
  position:sticky; top:0; z-index:30; height:62px;
  background:color-mix(in srgb,var(--mantle) 86%,transparent);
  backdrop-filter:blur(14px); -webkit-backdrop-filter:blur(14px);
  border-bottom:1px solid var(--line);
}
.topbar-inner {
  max-width:var(--maxw); margin:0 auto; height:100%;
  display:flex; align-items:center; gap:10px; padding:0 22px;
}
.brand { display:flex; align-items:center; gap:11px; flex:0 0 auto; }
.brand .mark {
  width:30px; height:30px; border-radius:8px; flex:0 0 auto; display:block; object-fit:contain;
  box-shadow:0 2px 10px -3px rgba(0,0,0,.5);
}
.brand .bname { font-family:"Righteous", var(--font-ui); font-size:18px; font-weight:400; letter-spacing:.5px; text-transform:uppercase; }
.brand .bname b { color:var(--text); font-weight:400; }
.brand .bname span { color:var(--ov1); font-weight:400; }

.tabs {
  display:flex; gap:3px; flex:1 1 auto; margin-left:6px; min-width:0;
  overflow-x:auto; scrollbar-width:none; -ms-overflow-style:none;
}
.tabs::-webkit-scrollbar { display:none; }
.tabs button {
  border:0; background:transparent; color:var(--ov1); cursor:pointer; flex:0 0 auto;
  font-size:13px; font-weight:500; padding:8px 11px; border-radius:10px;
  display:flex; align-items:center; gap:6px; transition:.16s ease; white-space:nowrap;
}
.tabs button svg { width:15px; height:15px; opacity:.85; }
.tabs button:hover { color:var(--sub0); background:color-mix(in srgb,var(--surface2) 60%,transparent); }
.tabs button.on { color:var(--lavender); background:color-mix(in srgb,var(--mauve) 16%,transparent); font-weight:600; }
[data-theme="light"] .tabs button.on { color:var(--mauve); }

.topbar .spacer { flex:1 1 auto; }

/* global search: botão-ícone que abre um painel com o campo de busca */
.gsearch-wrap { position:relative; flex:0 0 auto; }
.gsearch-panel {
  position:absolute; top:calc(100% + 8px); right:0; z-index:70; width:min(320px,86vw);
  background:var(--base); border:1px solid var(--line); border-radius:12px;
  box-shadow:var(--shadow-pop); padding:9px; display:flex; align-items:center;
}
.gsearch-panel[hidden] { display:none; }
.gsearch-panel svg { position:absolute; left:19px; top:50%; transform:translateY(-50%); width:14px; height:14px; color:var(--ov0); pointer-events:none; }
.gsearch-panel span { position:absolute; left:9px; top:0; bottom:0; display:flex; align-items:center; }
.gsearch-panel input {
  width:100%; font:inherit; font-size:13px; color:var(--text);
  background:var(--mantle); border:1px solid var(--line);
  border-radius:9px; padding:9px 34px 9px 34px; outline:none; transition:.16s ease;
}
.gsearch-panel input::placeholder { color:var(--ov0); }
.gsearch-panel input:focus { border-color:var(--mauve); box-shadow:0 0 0 3px color-mix(in srgb,var(--mauve) 16%,transparent); }
.gsearch-panel kbd {
  position:absolute; right:18px; top:50%; transform:translateY(-50%); font-family:var(--font-mono); font-size:10.5px; color:var(--ov0);
  border:1px solid var(--line); border-radius:5px; padding:1px 5px; background:var(--mantle); line-height:1.4;
}

.iconbtn {
  width:34px; height:34px; border-radius:9px; border:1px solid var(--line);
  background:var(--surface); color:var(--ov1); cursor:pointer; flex:0 0 auto;
  display:grid; place-items:center; transition:.16s ease;
}
.iconbtn:hover { color:var(--text); border-color:var(--s2); }
.iconbtn svg { width:16px; height:16px; }

/* Chip de usuário: botão só com o avatar (igual ao protótipo); nome/cargo/sair
   ficam num painel que abre ao clicar, em vez de sempre visíveis na barra. */
.userchip-wrap { position:relative; flex:0 0 auto; }
.userchip {
  width:32px; height:32px; border-radius:50%; border:1px solid var(--line); cursor:pointer;
  background:var(--surface2); color:var(--sub0); display:grid; place-items:center;
  font-size:12px; font-weight:600; padding:0; font-family:inherit;
}
.user-menu {
  position:absolute; right:0; top:calc(100% + 8px); z-index:70; min-width:190px;
  background:var(--base); border:1px solid var(--line); border-radius:12px;
  box-shadow:var(--shadow-pop); padding:11px 13px;
}
.user-menu[hidden] { display:none; }
.user-menu .um-head { display:flex; align-items:center; gap:8px; margin-bottom:10px; }
.user-menu .uname { font-size:13px; font-weight:600; color:var(--sub1); }
.user-menu .urole {
  font-size:9.5px; font-weight:700; letter-spacing:.6px; color:var(--mauve);
  border:1px solid color-mix(in srgb,var(--mauve) 40%,transparent); border-radius:5px;
  padding:1px 6px; background:color-mix(in srgb,var(--mauve) 12%,transparent);
}
/* Instalar na tela inicial (ver #installbtn/#installios no page_shell). */
.um-install {
  width:100%; font:inherit; font-size:13px; font-weight:600; color:var(--mauve); cursor:pointer;
  background:color-mix(in srgb,var(--mauve) 12%,transparent);
  border:1px solid color-mix(in srgb,var(--mauve) 40%,transparent);
  border-radius:9px; padding:8px 14px; margin-bottom:8px; transition:.16s ease;
}
.um-install:hover { background:color-mix(in srgb,var(--mauve) 20%,transparent); }
.um-install[hidden], .um-ios[hidden] { display:none; }
.um-ios {
  font-size:12px; line-height:1.45; color:var(--ov1);
  border:1px solid var(--line); border-radius:9px; padding:8px 10px; margin-bottom:8px;
}
.um-ios b { color:var(--sub0); font-weight:600; }

.logout {
  width:100%; font:inherit; font-size:13px; font-weight:500; color:var(--ov1); cursor:pointer;
  background:transparent; border:1px solid var(--line); border-radius:9px; padding:7px 14px; transition:.16s ease;
}
.logout:hover { color:var(--red); border-color:color-mix(in srgb,var(--red) 45%,transparent); }

/* mobile menu button */
.menubtn { display:none; }

/* ============================================================
   PAGE
   ============================================================ */
.page { flex:1 1 auto; }
.wrap { max-width:var(--maxw); margin:0 auto; padding:26px 26px 64px; }

.pagehead { display:flex; align-items:center; gap:14px; flex-wrap:wrap; margin-bottom:8px; }
.pagehead .ph-back {
  display:inline-flex; align-items:center; gap:6px; color:var(--ov1); font-size:13px;
  cursor:pointer; padding:5px 10px; border-radius:8px; transition:.16s ease; white-space:nowrap;
}
.pagehead .ph-back:hover { color:var(--lavender); background:color-mix(in srgb,var(--surface2) 60%,transparent); }
.pagehead .ph-back svg { width:14px; height:14px; }
.updated { display:flex; align-items:center; gap:8px; font-size:12.5px; color:var(--ov0); white-space:nowrap; }
.updated .live {
  width:7px; height:7px; border-radius:50%; background:var(--green); position:relative; flex:0 0 auto;
}
.updated .live::after {
  content:""; position:absolute; inset:0; border-radius:50%; background:var(--green);
}
@media (prefers-reduced-motion:no-preference) {
  .updated .live::after { animation:ampulse 2.4s ease-out infinite; }
}
@keyframes ampulse { 0%{transform:scale(1);opacity:.55} 100%{transform:scale(3.4);opacity:0} }
.updated b { color:var(--sub0); font-weight:600; }

/* título de tela (Clientes, Rede, Incidentes, ...) */
.screen-title { font-size:22px; font-weight:700; letter-spacing:-.4px; color:var(--text); margin:4px 0 6px; }
.ov-hint { font-size:12.5px; color:var(--ov1); max-width:760px; margin:0 0 18px; line-height:1.5; }

/* tag pequena (fonte de um cliente, etc.) */
.pill { display:inline-flex; align-items:center; padding:2px 9px; border-radius:999px; background:var(--surface2); color:var(--ov1); font-size:11px; font-weight:600; margin-right:4px; white-space:nowrap; }

/* tabela de clientes (aba Clientes) */
.cli-table { width:100%; border-collapse:separate; border-spacing:0; background:var(--base); border:1px solid var(--line); border-radius:var(--r-card); box-shadow:var(--shadow-card); overflow:hidden; }
.cli-table th { text-align:right; font-size:10px; font-weight:700; letter-spacing:.5px; text-transform:uppercase; color:var(--ov0); padding:15px 14px 10px; white-space:nowrap; }
.cli-table th.lt, .cli-table td.lt { text-align:left; }
.cli-table th:first-child, .cli-table td:first-child { padding-left:18px; }
.cli-table th:last-child, .cli-table td:last-child { padding-right:18px; }
.cli-table td { text-align:right; font-size:12.5px; padding:10px 14px; color:var(--sub1); border-top:1px solid var(--line-soft); font-variant-numeric:tabular-nums; }
.cli-row { cursor:pointer; transition:.12s ease; }
.cli-row:hover { background:var(--surface); }
.cli-row td:first-child { display:flex; align-items:center; gap:9px; font-weight:600; color:var(--text); }
.cli-letter td { background:var(--surface); font-size:11px; font-weight:700; letter-spacing:.6px; color:var(--ov0); padding:6px 18px; border-top:none; text-transform:uppercase; text-align:left; }
.cli-az { position:fixed; right:18px; top:50%; transform:translateY(-50%); display:flex; flex-direction:column; gap:1px; z-index:5; }
.cli-az-l { font-size:10px; color:var(--ov0); text-align:center; padding:2px 5px; border-radius:4px; }
.cli-az-l:hover { background:var(--surface2); color:var(--text); }
@media (max-width:1180px) { .cli-az { display:none; } }
.cli-pager { display:flex; align-items:center; justify-content:center; gap:14px; margin-top:16px; font-size:12.5px; color:var(--ov1); }
.cli-pager span[aria-disabled] { opacity:.4; pointer-events:none; }

/* hub do cliente */
.hub-hero { display:flex; align-items:center; gap:12px; margin:6px 0 16px; }
.hub-hero .dot { width:11px; height:11px; border-radius:50%; flex:0 0 auto; }
.hub-hero-tt { flex:1 1 auto; }
.hub-hero-tt .screen-title { margin:0 0 4px; }
.hub-hero-tt .sub { font-size:12.5px; color:var(--ov1); display:flex; align-items:center; gap:8px; }
.hub-status { font-size:12px; font-weight:700; padding:6px 14px; border-radius:var(--r-pill); white-space:nowrap; }
.hub-status.ok { background:color-mix(in srgb,var(--green) 16%,transparent); color:var(--green); }
.hub-status.warn { background:color-mix(in srgb,var(--yellow) 16%,transparent); color:var(--yellow); }
.hub-status.crit { background:color-mix(in srgb,var(--red) 16%,transparent); color:var(--red); }
/* "off" = nada a avaliar agora (fonte fora do ar, sonda calada, cliente vazio).
   Cinza de propósito: não é um "tudo ok" verde que ninguém verificou. */
.hub-status.off { background:var(--surface2); color:var(--ov1); }
.hub-card { background:var(--base); border:1px solid var(--line); border-radius:var(--r-card); box-shadow:var(--shadow-card); padding:16px; margin-bottom:22px; }
.hub-card .inc-summary { margin-bottom:0; }
.hubtabs { display:flex; gap:4px; border-bottom:1px solid var(--line); margin-bottom:18px; }
.hubtab { font:inherit; font-size:13px; font-weight:600; color:var(--ov1); background:transparent; border:0; cursor:pointer; padding:10px 4px; margin-right:22px; border-bottom:2px solid transparent; transition:.14s ease; }
.hubtab:hover { color:var(--sub0); }
.hubtab.on { color:var(--mauve); border-bottom-color:var(--mauve); }
.hubpane[hidden] { display:none; }
.hub-hours { display:flex; align-items:center; justify-content:space-between; gap:14px; background:var(--base); border:1px solid var(--line); border-radius:var(--r-card); box-shadow:var(--shadow-card); padding:16px 18px; max-width:520px; }

/* Tela "Sem cliente vinculado" (/clients/unlinked) */
.unl-h { margin:0 0 12px; font-size:12px; font-weight:700; letter-spacing:1.4px; text-transform:uppercase; color:var(--ov2); }
.unl-list { background:var(--base); border:1px solid var(--line); border-radius:var(--r-card); box-shadow:var(--shadow-card); overflow:hidden; margin-bottom:24px; }
.unl-row { display:flex; align-items:center; gap:14px; padding:11px 18px; box-shadow:inset 0 -1px 0 var(--line-soft); }
.unl-row:last-child { box-shadow:none; }
.unl-name { flex:1 1 auto; min-width:0; }
.unl-name b { display:block; font-size:13px; font-weight:600; }
.unl-name span { display:block; font-size:11.5px; color:var(--ov0); }
.unl-row select {
  font:inherit; font-size:12.5px; color:var(--text); background:var(--mantle);
  border:1px solid var(--line); border-radius:8px; padding:7px 9px;
}

/* aba Incidentes: uma linha por queda/recuperação */
.inc-list { display:flex; flex-direction:column; gap:8px; margin-top:14px; }

.inc-row { display:flex; align-items:center; gap:14px; background:var(--base); border:1px solid var(--line); border-radius:var(--r-tile); box-shadow:var(--shadow-card); padding:12px 14px; position:relative; overflow:hidden; }
.inc-row.muted { opacity:.6; }
.inc-accent { position:absolute; left:0; top:0; bottom:0; width:3px; }
.inc-accent.crit { background:var(--red); }
.inc-accent.warn { background:var(--yellow); }
.inc-accent.ok { background:var(--green); }
.inc-tag { font-size:10px; font-weight:700; letter-spacing:.5px; text-transform:uppercase; color:var(--ov1); background:var(--surface2); border-radius:6px; padding:4px 8px; flex:0 0 auto; white-space:nowrap; }
.inc-main { flex:1 1 220px; min-width:0; display:flex; flex-direction:column; gap:2px; }
.inc-main b { font-size:13.5px; color:var(--text); }
.inc-sub { font-size:11.5px; color:var(--ov1); }
.inc-state { font-size:12.5px; color:var(--sub0); white-space:nowrap; flex:0 0 auto; }
.inc-since { font-size:11.5px; color:var(--ov0); white-space:nowrap; flex:0 0 auto; }

/* aba Rede: um bloco por cliente, alvos dentro. Colapsado por padrão (como
   .dgroup/.ccard) — com dezenas/centenas de clientes de rede, tudo expandido
   de cara não escala. */
.rede-list { margin-top:22px; display:flex; flex-direction:column; gap:16px; }
.rede-client { background:var(--base); border:1px solid var(--line); border-radius:var(--r-card); box-shadow:var(--shadow-card); padding:16px; }
.rede-client-h { display:flex; align-items:center; gap:10px; margin-bottom:14px; cursor:pointer; }
.rede-client-h .dot { width:10px; height:10px; border-radius:50%; flex:0 0 auto; }
/* Identidade do cliente (nome + contagem + tarja): é o bloco elástico do
   cabeçalho — ele encolhe e quebra em duas linhas quando a tela aperta, para
   que Hub/sino/seta continuem à direita e dentro da tela. Soltos no flex do pai,
   esses três decidiam a quebra pelo tamanho natural e empurravam as ações pra
   fora (a tarja "sonda offline há X" tem 135px sozinha). */
.rede-client-h .rc-id { display:flex; align-items:center; flex-wrap:wrap; gap:4px 10px;
  min-width:0; flex:1 1 auto; }
.rede-client-h b { font-size:15px; color:var(--text); }
.rede-client-h .scount { font-size:12px; color:var(--ov0); }
.rede-client-h .chev { color:var(--ov1); display:flex; flex:0 0 auto; transition:transform .2s ease; }
.rede-client-h .chev svg { width:16px; height:16px; display:block; }
.rede-client.collapsed .rede-client-h { margin-bottom:0; }
.rede-client.collapsed .chev { transform:rotate(-90deg); }
.rede-client.collapsed .rede-client-b { display:none; }

/* section label */
.section { margin:30px 0 14px; display:flex; align-items:center; gap:12px; scroll-margin-top:84px; }
.section:first-of-type { margin-top:20px; }
.section h2 {
  margin:0; font-size:12px; font-weight:700; letter-spacing:1.4px; text-transform:uppercase; color:var(--ov2); white-space:nowrap;
}
.section .scount {
  font-size:11.5px; font-weight:600; color:var(--ov0); background:var(--surface);
  border:1px solid var(--line); border-radius:999px; padding:2px 9px; font-variant-numeric:tabular-nums;
}
.section .sline { flex:1 1 auto; height:1px; background:var(--line-soft); }

/* ============================================================
   SUMMARY STAT TILES
   ============================================================ */
.stats { display:grid; grid-template-columns:repeat(auto-fit,minmax(180px,1fr)); gap:14px; margin-top:18px; }
.stat {
  background:var(--base); border:1px solid var(--line); border-radius:var(--r-card);
  padding:18px 20px; box-shadow:var(--shadow-card); display:flex; align-items:center; gap:16px;
}
.stat .sicon {
  width:44px; height:44px; border-radius:12px; flex:0 0 auto; display:grid; place-items:center;
}
.stat .sicon svg { width:21px; height:21px; }
.stat .sv { font-size:26px; font-weight:700; letter-spacing:-.5px; line-height:1.05; font-variant-numeric:tabular-nums; }
.stat .sl { font-size:12.5px; color:var(--ov1); margin-top:2px; }
.tint-green { background:color-mix(in srgb,var(--green) 15%,transparent); color:var(--green); }
.tint-blue  { background:color-mix(in srgb,var(--blue) 15%,transparent); color:var(--blue); }
.tint-mauve { background:color-mix(in srgb,var(--mauve) 15%,transparent); color:var(--mauve); }
.tint-peach { background:color-mix(in srgb,var(--peach) 15%,transparent); color:var(--peach); }
.tint-teal  { background:color-mix(in srgb,var(--teal) 15%,transparent); color:var(--teal); }
.tint-red   { background:color-mix(in srgb,var(--red) 15%,transparent); color:var(--red); }
.tint-lavender { background:color-mix(in srgb,var(--lavender) 15%,transparent); color:var(--lavender); }
/* cinza neutro — "sem dados"/sonda offline (não é alarme, é ausência de dado). */
.tint-slate { background:color-mix(in srgb,var(--ov0) 18%,transparent); color:var(--ov0); }

/* ============================================================
   CARDS GRID
   ============================================================ */
.grid-servers { display:grid; grid-template-columns:repeat(auto-fill,minmax(300px,1fr)); gap:16px; }
.grid-monitors { display:grid; grid-template-columns:repeat(auto-fill,minmax(300px,1fr)); gap:12px; }
.grid-sources { display:grid; grid-template-columns:repeat(auto-fill,minmax(280px,1fr)); gap:16px; }

/* Canais de câmera de um DVR (dentro de um .dgroup na aba Rede/Hub) */
.grid-cameras { display:grid; grid-template-columns:repeat(auto-fill,minmax(160px,1fr)); gap:12px; padding:12px; }
.camcard { display:block; text-decoration:none; color:inherit; border-radius:var(--r-tile); overflow:hidden; background:var(--surface); border:1px solid var(--line); transition:border-color .16s ease; }
.camcard:hover { border-color:var(--s2); }
.camthumb { display:block; aspect-ratio:16/9; background:var(--mantle); overflow:hidden; }
.camthumb img { width:100%; height:100%; object-fit:cover; display:block; }
.camname { display:flex; align-items:center; gap:6px; padding:8px 10px; font-size:12.5px; font-weight:600; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }

.card {
  background:var(--base); border:1px solid var(--line); border-radius:var(--r-card);
  box-shadow:var(--shadow-card); overflow:hidden; position:relative; transition:border-color .16s ease, transform .16s ease;
}
.card.link { cursor:pointer; }
.card.link:hover { border-color:var(--s2); transform:translateY(-2px); }
.card .accent { position:absolute; left:0; top:0; bottom:0; width:3px; }
.acc-ok { background:var(--green); } .acc-warn { background:var(--yellow); } .acc-crit { background:var(--red); }
.acc-off { background:var(--ov0); }

.card-h { display:flex; align-items:center; gap:11px; padding:16px 18px 12px; }
.card-h .dot { width:9px; height:9px; border-radius:50%; flex:0 0 auto; }
.dot.ok { background:var(--green); box-shadow:0 0 0 3px color-mix(in srgb,var(--green) 18%,transparent); }
.dot.warn { background:var(--yellow); box-shadow:0 0 0 3px color-mix(in srgb,var(--yellow) 18%,transparent); }
.dot.crit { background:var(--red); box-shadow:0 0 0 3px color-mix(in srgb,var(--red) 18%,transparent); }
/* "Sem dados": quem checava parou de reportar (ex.: sonda fechada) — cinza,
   sem halo, pra não passar nem saúde nem alarme. */
.dot.off { background:var(--ov0); box-shadow:none; }
.card-h .ttl { min-width:0; flex:1 1 auto; }
.card-h .ttl .nm { font-size:14.5px; font-weight:600; letter-spacing:-.1px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.card-h .ttl .sub { font-size:11.5px; color:var(--ov0); margin-top:1px; }

.badge {
  display:inline-flex; align-items:center; gap:6px; flex:0 0 auto; white-space:nowrap;
  font-size:11px; font-weight:600; letter-spacing:.2px; padding:3px 9px 3px 8px; border-radius:var(--r-pill);
}
.badge .bd { width:6px; height:6px; border-radius:50%; }
.badge.ok { background:color-mix(in srgb,var(--green) 15%,transparent); color:var(--green); }
.badge.ok .bd { background:var(--green); }
.badge.warn { background:color-mix(in srgb,var(--yellow) 16%,transparent); color:var(--yellow); }
.badge.warn .bd { background:var(--yellow); }
.badge.crit { background:color-mix(in srgb,var(--red) 15%,transparent); color:var(--red); }
.badge.crit .bd { background:var(--red); }
.badge.neutral { background:var(--surface2); color:var(--sub0); font-weight:500; }
.badge.off { background:var(--surface2); color:var(--ov0); }
.badge.off .bd { background:var(--ov0); }

/* server metrics */
.metrics { padding:4px 18px 18px; display:flex; flex-direction:column; gap:14px; }
.metric .mtop { display:flex; align-items:baseline; justify-content:space-between; margin-bottom:7px; }
.metric .ml { font-size:12px; font-weight:500; color:var(--ov2); }
.metric .mv { font-size:14px; font-weight:700; font-variant-numeric:tabular-nums; }
.track { height:8px; border-radius:5px; background:var(--surface2); overflow:hidden; }
.track > span { display:block; height:100%; border-radius:5px; transition:width .5s cubic-bezier(.2,.7,.3,1); }
.metric .mx { font-size:11px; color:var(--ov0); margin-top:6px; font-variant-numeric:tabular-nums; }
.fill-cpu { background:var(--blue); } .fill-mem { background:var(--green); } .fill-dsk { background:var(--peach); }
.fill-warn { background:var(--yellow); } .fill-crit { background:var(--red); }
.v-cpu { color:var(--blue); } .v-mem { color:var(--green); } .v-dsk { color:var(--peach); }
.v-warn { color:var(--yellow); } .v-crit { color:var(--red); }

/* ============================================================
   MONITOR (uptime) card — COMPACTO: cabeçalho numa linha + gráfico
   ============================================================ */
.mc-h { display:flex; align-items:center; gap:8px; padding:11px 14px 4px; min-width:0; }
.mc-h .dot { width:9px; height:9px; border-radius:50%; flex:0 0 auto; }
.mc-nm { font-size:14px; font-weight:600; letter-spacing:-.1px; color:var(--text);
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis; min-width:0; flex:0 1 auto; }
.mc-tg { font-size:11.5px; color:var(--ov0); white-space:nowrap; overflow:hidden;
  text-overflow:ellipsis; min-width:0; flex:0 1 auto; }
.mc-sp { flex:1 1 auto; }
.mc-state { font-size:12.5px; font-weight:700; flex:0 0 auto; }
.mc-state.ok { color:var(--green); } .mc-state.warn { color:var(--yellow); } .mc-state.crit { color:var(--red); }
.mc-state.off { color:var(--ov0); }
.mc-stat { font-size:12.5px; font-weight:700; font-variant-numeric:tabular-nums; color:var(--sub1); flex:0 0 auto; }
.hb { display:flex; align-items:flex-end; gap:3px; height:30px; padding:6px 14px 12px; box-sizing:content-box; }
.hb i { flex:1 1 0; min-width:3px; border-radius:2px; height:60%; align-self:flex-end; transition:height .2s ease; }
.hb i.up { background:var(--green); height:100%; }
.hb i.slow { background:var(--yellow); height:78%; }
.hb i.down { background:var(--red); height:46%; }
/* Monitor "sem dados" (sonda parou de reportar): as barrinhas são histórico
   velho — cinza e achatadas, pra não parecerem "no ar agora". */
.hb.hb-off i { background:var(--ov0) !important; height:46% !important; }

/* device source mini card */
.src-body { padding:2px 18px 18px; display:flex; flex-direction:column; gap:1px; }
.src-row { display:flex; align-items:center; justify-content:space-between; padding:9px 0; }
.src-row + .src-row { border-top:1px solid var(--line-soft); }
.src-row .sk { font-size:12.5px; color:var(--ov1); }
.src-row .sv { font-size:14px; font-weight:700; font-variant-numeric:tabular-nums; }

/* ============================================================
   VIEW TOGGLE + COMPACT LIST (dashboard density)
   ============================================================ */
.vtoggle { display:flex; gap:3px; background:var(--surface); border:1px solid var(--line); border-radius:11px; padding:4px; flex:0 0 auto; }
.vtoggle button { display:inline-flex; align-items:center; gap:7px; border:0; background:transparent; color:var(--ov1);
  font:inherit; font-size:12.5px; font-weight:600; padding:6px 13px; border-radius:8px; cursor:pointer; transition:.14s ease; }
.vtoggle button svg { width:14px; height:14px; }
.vtoggle button:hover { color:var(--sub0); }
.vtoggle button.on { background:var(--surface2); color:var(--text); }

.clist { background:var(--base); border:1px solid var(--line); border-radius:var(--r-card); box-shadow:var(--shadow-card); overflow:hidden; }
.crow { display:grid; align-items:center; gap:18px; padding:11px 18px; }
.clist.srv .crow { grid-template-columns:minmax(170px,1.4fr) 1fr 1fr 1fr 64px; }
.clist.mon .crow { grid-template-columns:minmax(190px,1.6fr) 104px 1fr 64px 78px; }
/* Coluna extra do sino (só para admin — ver `SondaBells::can`), sempre a ÚLTIMA,
   na mesma largura do sino da aba Acesso (`.drow`). O `justify-self` é a rede de
   segurança: se alguma media query esconder colunas do meio, o sino ainda encosta
   na direita em vez de escorregar pro meio da linha. */
.clist.mon.bells .crow { grid-template-columns:minmax(190px,1.6fr) 104px 1fr 64px 78px 34px; }
.clist.mon.bells .crow > .bellform { justify-self:end; }
/* Lista ordenável (card do cliente, aba Monitoramento): uma coluna a MAIS na
   frente, pra alça de arrastar. Precisa vir depois das regras acima — mesma
   especificidade, ganha quem vem por último. */
.clist.mon.sortable .crow { grid-template-columns:16px minmax(190px,1.6fr) 104px 1fr 64px 78px; gap:13px; }
.clist.mon.sortable.bells .crow { grid-template-columns:16px minmax(190px,1.6fr) 104px 1fr 64px 78px 34px; }
/* `touch-action:none` é o que faz o arrasto EXISTIR no celular: sem isso o toque
   na alça vira rolagem da página e o pointermove nunca chega. */
.grip { display:flex; align-items:center; justify-content:center; color:var(--ov0);
  cursor:grab; touch-action:none; }
.grip svg { width:15px; height:15px; }
.grip:hover { color:var(--sub0); }
/* A linha arrastada não pode capturar o ponteiro: o `elementFromPoint` do JS
   precisa enxergar a linha DEBAIXO do cursor pra saber onde soltar. */
.crow.dragging { pointer-events:none; position:relative; z-index:2; border-radius:8px;
  background:var(--surface2); box-shadow:0 8px 22px rgba(0,0,0,.35); }
.crow.dragging .grip { cursor:grabbing; }
/* Seletor de ordenação no cabeçalho da seção do card (o `select` global é
   width:100%, que aqui esticaria o cabeçalho inteiro). */
.monsort-wrap { display:inline-flex; align-items:center; gap:7px; flex:none; }
.monsort-lbl { font-size:10px; font-weight:600; letter-spacing:.9px; text-transform:uppercase; color:var(--ov0); }
select.monsort { width:auto; font-size:12px; padding:5px 26px 5px 9px; background-position:right 8px center; }
.clist.src .crow { grid-template-columns:minmax(190px,1fr) 110px 90px; }
.crow.chead { background:var(--surface); padding:9px 18px; }
.crow.chead .ch { font-size:10px; font-weight:600; letter-spacing:.9px; text-transform:uppercase; color:var(--ov0); }
.crow.chead .ch.num { text-align:right; }
.crow:not(.chead) { box-shadow:inset 0 -1px 0 var(--line-soft); transition:background .12s ease; }
.crow:not(.chead):last-child { box-shadow:none; }
.crow:not(.chead):hover { background:color-mix(in srgb,var(--surface2) 45%,transparent); }
.crow.link { cursor:pointer; }
.cname { display:flex; align-items:center; gap:11px; min-width:0; }
.cname .dot { width:9px; height:9px; border-radius:50%; flex:0 0 auto; }
.cname .cmeta { min-width:0; }
.cname .cn { font-size:13px; font-weight:600; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.cname .cip { font-size:11px; color:var(--ov0); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.ccell { display:flex; flex-direction:column; gap:5px; min-width:0; }
.ccell .cv { font-size:12.5px; font-weight:700; font-variant-numeric:tabular-nums; }
.cbar { height:5px; border-radius:3px; background:var(--surface2); overflow:hidden; }
.cbar > span { display:block; height:100%; border-radius:3px; }
.cnum { text-align:right; font-size:12.5px; font-weight:600; font-variant-numeric:tabular-nums; color:var(--sub1); }
.crow .badge { justify-self:start; }
.chb { display:flex; align-items:flex-end; gap:2px; height:20px; }
.chb i { flex:1 1 0; min-width:2px; border-radius:1px; align-self:stretch; }
.chb i.up { background:var(--green); } .chb i.slow { background:var(--yellow); } .chb i.down { background:var(--red); }
.chb.chb-off i { background:var(--ov0) !important; }

/* ============================================================
   DEVICES TAB
   ============================================================ */
.src-block { margin-top:14px; }
.src-head { display:flex; align-items:center; gap:11px; margin:28px 0 12px; flex-wrap:wrap; }
.src-head .dot { width:9px; height:9px; border-radius:50%; flex:0 0 auto; }
.src-head h2 { margin:0; font-size:15px; font-weight:700; letter-spacing:.3px; white-space:nowrap; }
.src-head .ct { font-size:12.5px; color:var(--ov1); font-weight:600; white-space:nowrap; }
.src-head .srcbar { flex:1 1 auto; max-width:220px; height:5px; border-radius:3px; background:var(--surface2); overflow:hidden; }
.src-head .srcbar > span { display:block; height:100%; border-radius:3px; }
.src-head .srcbar > span.ok { background:var(--green); }
.src-head .srcbar > span.part { background:var(--yellow); }
.src-head .srcbar > span.crit { background:var(--red); }
.src-head .gc-meta { font-size:11.5px; color:var(--ov0); white-space:nowrap; margin-left:auto; }

/* abas por sistema (AlfaControl/AlfaGym…) — mesmo visual do grupo de filtros */
.sistema-tabs { display:inline-flex; gap:4px; background:var(--surface); border:1px solid var(--line);
  border-radius:11px; padding:4px; margin-top:16px; flex-wrap:wrap; }
.sistema-tabs .dfilter { padding:7px 16px; }
.sistema-section[hidden] { display:none; }

/* dashboard de acessos do sistema */
.sys-dash { margin:14px 0 6px; display:flex; flex-direction:column; gap:10px; }
.sys-dash-h { display:flex; align-items:baseline; gap:10px; flex-wrap:wrap; }
.sys-dash-h b { font-size:12.5px; font-weight:700; letter-spacing:.3px; color:var(--sub1); }
.sys-dash-h span { font-size:11px; font-weight:500; letter-spacing:.2px; color:var(--ov0); }
.acc-cards { display:grid; grid-template-columns:repeat(3,1fr); gap:12px; }
.acc-card { background:var(--base); border:1px solid var(--line); border-radius:var(--r-card);
  box-shadow:var(--shadow-card); padding:15px 17px; display:flex; flex-direction:column; gap:5px; }
.acc-win { font-size:10.5px; font-weight:700; letter-spacing:.6px; text-transform:uppercase; color:var(--ov0); }
.acc-total { font-size:27px; font-weight:700; line-height:1.05; font-variant-numeric:tabular-nums; }
.acc-sub { font-size:11px; color:var(--ov0); margin-top:-2px; }
.acc-bar { display:flex; height:6px; border-radius:3px; overflow:hidden; background:var(--surface2); margin-top:8px; }
.acc-bar .lib { background:var(--green); } .acc-bar .neg { background:var(--red); }
.acc-legend { display:flex; justify-content:space-between; gap:10px; font-size:11.5px; font-weight:600;
  font-variant-numeric:tabular-nums; margin-top:3px; }
.acc-legend .lib { color:var(--green); } .acc-legend .neg { color:var(--red); }
@media (max-width:720px){ .acc-cards { grid-template-columns:1fr; } }

/* devices toolbar */
.dtoolbar { display:flex; align-items:center; gap:10px; margin:18px 0; flex-wrap:wrap; }
.dfilters { display:flex; gap:4px; background:var(--surface); border:1px solid var(--line); border-radius:11px; padding:4px; }
.dfilter { display:inline-flex; align-items:center; gap:7px; border:0; background:transparent; color:var(--ov1);
  font:inherit; font-size:12.5px; font-weight:600; padding:6px 13px; border-radius:8px; cursor:pointer; transition:.14s ease; }
.dfilter:hover { color:var(--sub0); }
.dfilter .fc { font-size:11px; color:var(--ov0); background:var(--surface2); border-radius:999px; padding:1px 7px; }
.dfilter.on { background:var(--surface2); color:var(--text); }
.dfilter.on .fc { background:color-mix(in srgb,var(--mauve) 22%,transparent); color:var(--lavender); }
[data-theme="light"] .dfilter.on .fc { color:var(--mauve); }
/* Ordenação (Monitoramento): 4 chips de rótulo longo. Sem isto, numa tela
   estreita eles espremem o texto em várias linhas e o último vaza pra fora da
   caixa — melhor quebrar a FILA em duas linhas e manter cada chip inteiro. */
.sortfilters { flex-wrap:wrap; }
.sortfilters .dfilter { white-space:nowrap; }

/* chips de atalho (Visão geral): pills separados que rolam até a seção */
.chips { display:flex; align-items:center; gap:8px; flex-wrap:wrap; margin:14px 0 16px; }
.chip { display:inline-flex; align-items:center; gap:7px; padding:7px 14px; border-radius:var(--r-pill);
  background:var(--surface); border:1px solid var(--line); color:var(--ov1); font-size:12.5px; font-weight:600;
  text-decoration:none; cursor:pointer; transition:.14s ease; }
.chip:hover { color:var(--sub0); border-color:var(--s2); }
.chip .cc { font-size:11px; color:var(--red); background:color-mix(in srgb,var(--red) 16%,transparent); border-radius:999px; padding:1px 7px; }

.dgroup { background:var(--base); border:1px solid var(--line); border-radius:var(--r-card); box-shadow:var(--shadow-card); overflow:hidden; margin-bottom:10px; }
.dgroup-h {
  display:flex; align-items:center; gap:11px; padding:11px 16px; cursor:pointer;
  background:var(--surface); border-bottom:1px solid var(--line); transition:background .14s ease;
}
.dgroup-h:hover { background:var(--surface2); }
.dgroup-h .gn { flex:1 1 auto; min-width:0; font-size:13.5px; font-weight:600; letter-spacing:.1px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.dgroup-h .gcount { font-size:11.5px; color:var(--ov0); white-space:nowrap; flex:0 0 auto; }
.dgroup-h .gc { font-size:12px; color:var(--ov0); font-weight:500; white-space:nowrap; }
.dgroup-h .chev { color:var(--ov1); transition:transform .2s ease; display:flex; flex:0 0 auto; }
.dgroup-h .chev svg { width:16px; height:16px; display:block; }
.dgroup.collapsed .dgroup-h { border-bottom-color:transparent; }
.dgroup.collapsed .chev { transform:rotate(-90deg); }
.dgroup.collapsed .dgroup-b { display:none; }
.dgroup-h .gpct {
  font-size:11px; font-weight:700; font-variant-numeric:tabular-nums; padding:2px 9px; border-radius:999px;
  flex:0 0 auto; min-width:48px; text-align:center;
}
.gpct.ok { color:var(--green); background:color-mix(in srgb,var(--green) 14%,transparent); }
.gpct.part { color:var(--yellow); background:color-mix(in srgb,var(--yellow) 14%,transparent); }
.gpct.crit { color:var(--red); background:color-mix(in srgb,var(--red) 14%,transparent); }

.drow {
  display:grid; grid-template-columns:1fr minmax(120px,180px) 96px; align-items:center; gap:18px;
  padding:9px 16px; transition:background .12s ease;
}
.drow + .drow { border-top:1px solid var(--line-soft); }
.drow:hover { background:color-mix(in srgb,var(--surface2) 50%,transparent); }
.drow .dn { display:flex; align-items:center; gap:11px; min-width:0; }
.drow .dn .dot { width:8px; height:8px; border-radius:50%; flex:0 0 auto; }
.drow .dn .dmeta { min-width:0; }
.drow .dn .dname { font-size:13px; font-weight:500; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.drow .dn .dsub { font-size:11px; color:var(--ov0); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.drow .dhb { display:flex; align-items:flex-end; gap:2px; height:20px; }
.drow .dhb i { flex:1 1 0; min-width:2px; border-radius:1px; align-self:stretch; }
.drow .dhb i.up { background:var(--green); }
.drow .dhb i.down { background:var(--red); }
.drow .dhb i.slow { background:var(--yellow); }
.drow .dpct { text-align:right; font-size:12.5px; font-variant-numeric:tabular-nums; }
.drow .dpct b { font-weight:700; }
.drow .dpct .rms { color:var(--ov0); font-size:11.5px; }
.up-on { color:var(--green); } .up-off { color:var(--red); }

/* ============================================================
   FORM PRIMITIVES (shared)
   ============================================================ */
.field { display:flex; flex-direction:column; gap:6px; min-width:0; flex:1 1 0; }
.grow { flex:1 1 auto; }
.field > label { font-size:11px; font-weight:500; color:var(--ov1); letter-spacing:.2px; }
.fgrid { display:grid; grid-template-columns:repeat(auto-fit,minmax(150px,1fr)); gap:13px 14px; align-items:end; }
.fgrid.wide { grid-template-columns:repeat(auto-fit,minmax(180px,1fr)); }

input[type=text], input[type=number], input[type=password], input[type=time], select, textarea {
  font:inherit; font-size:13px; color:var(--text);
  background:var(--mantle); border:1px solid var(--line); border-radius:var(--r-input);
  padding:9px 11px; outline:none; width:100%; transition:.16s ease;
}
/* O seletor de horário nativo segue o tema (relógio/spinner) e não estica demais. */
input[type=time] { color-scheme:dark; font-variant-numeric:tabular-nums; }
[data-theme="light"] input[type=time] { color-scheme:light; }
[data-theme="light"] input, [data-theme="light"] select { background:var(--surface); }
input::placeholder { color:var(--ov0); }
input:focus, select:focus, textarea:focus { border-color:var(--mauve); box-shadow:0 0 0 3px color-mix(in srgb,var(--mauve) 15%,transparent); }
input.short { max-width:120px; }

/* Caixa de busca própria de tela (Clientes/Acesso/Rede) — sincronizada com a
   busca global do topo (ver .localsearch no JS). Especificidade `input.` pra
   vencer o `input[type=text]` genérico acima (mesma força, mas vem depois). */
.localsearch-wrap { position:relative; flex:1 1 240px; min-width:200px; margin-top:18px; }
.localsearch-wrap svg { position:absolute; left:12px; top:50%; transform:translateY(-50%); width:15px; height:15px; color:var(--ov1); pointer-events:none; }
input.localsearch {
  background:var(--surface); padding:10px 12px 10px 34px;
}
input.localsearch:focus { background:var(--base); }
select { -webkit-appearance:none; appearance:none; padding-right:30px; cursor:pointer;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='7' viewBox='0 0 10 7'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%238c8fa1' stroke-width='1.5' stroke-linecap='round'/%3E%3C/svg%3E");
  background-repeat:no-repeat; background-position:right 11px center; }

.btn {
  font:inherit; font-size:13px; font-weight:600; cursor:pointer; transition:.16s ease; white-space:nowrap;
  border-radius:9px; padding:9px 16px; border:1px solid var(--line); background:var(--surface2); color:var(--text);
  display:inline-flex; align-items:center; gap:7px;
}
.btn svg { width:14px; height:14px; }
.btn:hover { border-color:var(--s2); }
.btn.primary { background:var(--mauve); color:var(--mauve-ink); border-color:transparent; box-shadow:0 2px 10px -4px color-mix(in srgb,var(--mauve) 70%,transparent); }
.btn.primary:hover { filter:brightness(1.06); }
.btn.ghost { background:transparent; color:var(--sub0); }
.btn.danger { background:transparent; color:var(--red); border-color:color-mix(in srgb,var(--red) 32%,transparent); }
.btn.danger:hover { background:color-mix(in srgb,var(--red) 12%,transparent); }
.btn.sm { padding:7px 13px; font-size:12.5px; }
.hint { font-size:11.5px; color:var(--ov0); line-height:1.5; }

/* toggle switch */
.switch { width:38px; height:22px; border-radius:999px; background:var(--surface2); border:1px solid var(--line);
  position:relative; cursor:pointer; transition:.16s ease; flex:0 0 auto; }
.switch::after { content:""; position:absolute; top:2px; left:2px; width:16px; height:16px; border-radius:50%;
  background:var(--ov1); transition:.18s cubic-bezier(.3,.7,.4,1); }
.switch.on { background:var(--mauve); border-color:var(--mauve); }
.switch::after { content:""; position:absolute; top:2px; left:2px; width:16px; height:16px; border-radius:50%;
  background:var(--ov1); transition:.18s cubic-bezier(.3,.7,.4,1); box-shadow:0 1px 2px rgba(0,0,0,.3); }
.switch.on::after { left:18px; background:#fff; }
.swrow { display:inline-flex; align-items:center; gap:10px; font-size:12.5px; color:var(--sub0); cursor:pointer; user-select:none; }
.switch-grid { display:flex; flex-wrap:wrap; gap:14px 28px; margin-top:18px; padding-top:18px; border-top:1px solid var(--line-soft); }

/* Regras de alerta: cada grupo (tipos / canais / horário / agrupar / escalonar) é um
   bloco com rótulo próprio — a regra tem muitos eixos, e sem os blocos vira um paredão
   de interruptores sem hierarquia. O .switch-grid dentro do grupo dispensa a borda de
   cima (o grupo já tem a dele). */
.rule-grp { margin-top:16px; padding-top:14px; border-top:1px solid var(--line-soft); }
.rule-grp .switch-grid { margin-top:10px; padding-top:0; border-top:0; }
.rule-grp .fgrid { margin-top:10px; }
.rule-lbl { font-size:12px; font-weight:600; color:var(--txt0); display:flex; flex-wrap:wrap; align-items:baseline; gap:10px; }
.rule-lbl .hint { font-weight:400; }
.rule-ord { display:flex; align-items:center; gap:8px; flex-wrap:wrap; margin-bottom:14px; }
/* Os webhooks POR NOME, recuados sob o interruptor de "Webhooks": só aparecem quando há
   mais de um cadastrado E o canal está ligado — senão seria uma pergunta sem escolha. */
.rule-sub { flex:1 1 100%; display:flex; flex-wrap:wrap; align-items:center; gap:12px 22px;
  margin-top:4px; padding:10px 0 0 16px; border-left:2px solid var(--line-soft); }
/* A linha implícita do fim da lista: o que nenhuma regra pegar vai a todos os canais.
   Não é editável — é o comportamento do sistema, dito onde não dá pra não ver. */
.rule-fallback { display:flex; align-items:flex-start; gap:12px; padding:14px 16px; border-radius:10px;
  border:1px dashed var(--line); background:var(--surface); font-size:12.5px; color:var(--sub0); line-height:1.6; }
.rule-fallback .chip { flex:0 0 auto; }

/* ============================================================
   ADMIN — settings page
   ============================================================ */
.admin-layout { display:grid; grid-template-columns:200px 1fr; gap:26px; align-items:start; margin-top:14px; }
.admin-nav { position:sticky; top:84px; display:flex; flex-direction:column; gap:2px; }
.anav-label { font-size:10px; font-weight:700; letter-spacing:1.2px; text-transform:uppercase; color:var(--ov0); padding:4px 12px 8px; }
.anav-i { text-align:left; border:0; background:transparent; color:var(--ov1); font:inherit; font-size:13.5px; font-weight:500;
  padding:9px 13px; border-radius:9px; cursor:pointer; transition:.14s ease; border-left:2px solid transparent; }
.anav-i:hover { color:var(--sub0); background:color-mix(in srgb,var(--surface2) 55%,transparent); }
.anav-i.on { color:var(--lavender); background:color-mix(in srgb,var(--mauve) 13%,transparent); font-weight:600; }
[data-theme="light"] .anav-i.on { color:var(--mauve); }

.admin-content { min-width:0; display:flex; flex-direction:column; gap:18px; }
/* No Hub, a gerência (asets de config) segue direto o status ao vivo (a lista
   `.clist`); sem esta margem os dois cards com borda se encostam. Mesma
   separação (30px) dos divisores `.section`. */
.hubpane .admin-content { margin-top:30px; }
.aset { background:var(--base); border:1px solid var(--line); border-radius:var(--r-card); box-shadow:var(--shadow-card); overflow:hidden; scroll-margin-top:84px; }
.aset-h { display:flex; align-items:flex-start; gap:14px; padding:18px 22px; border-bottom:1px solid var(--line-soft); }
.aset-ico { width:38px; height:38px; border-radius:11px; flex:0 0 auto; display:grid; place-items:center; margin-top:1px;
  background:color-mix(in srgb,var(--mauve) 13%,transparent); color:var(--mauve); }
.aset-ico svg { width:19px; height:19px; }
.aset-t { min-width:0; }
.aset-t h3 { margin:0; font-size:15px; font-weight:600; letter-spacing:-.1px; line-height:1.3; }
.aset-t p { margin:3px 0 0; font-size:12.5px; color:var(--ov1); line-height:1.4; }
.aset-b { padding:20px 22px; display:flex; flex-direction:column; gap:13px; }
.aset-foot { display:flex; align-items:center; gap:14px; margin-top:6px; padding-top:16px; border-top:1px solid var(--line-soft); flex-wrap:wrap; }
/* botão "+ Adicionar" no cabeçalho da seção (abre o modal do form) */
.aset-h .aset-add { flex:0 0 auto; align-self:center; gap:6px; }
.aset-h .aset-add svg { width:15px; height:15px; }
/* rodapé do form dentro do modal de adicionar */
.addform-foot { display:flex; align-items:center; gap:12px; margin-top:18px; padding-top:16px; border-top:1px solid var(--line-soft); flex-wrap:wrap; }

/* thresholds */
.thr-grid { display:grid; grid-template-columns:repeat(auto-fit,minmax(190px,1fr)); gap:13px; }
.thr { background:var(--surface); border:1px solid var(--line); border-radius:var(--r-tile); padding:14px 15px; }
.thr-h { display:flex; align-items:center; gap:8px; font-size:13px; font-weight:600; margin-bottom:12px; }
.thr-key { width:9px; height:9px; border-radius:3px; flex:0 0 auto; }
.tint-blue.thr-key { background:var(--blue); } .tint-green.thr-key { background:var(--green); }
.tint-peach.thr-key { background:var(--peach); } .tint-mauve.thr-key { background:var(--mauve); }
.thr-fields { display:flex; gap:12px; }

/* alert channels */
.chan { background:var(--surface); border:1px solid var(--line); border-radius:var(--r-tile); padding:15px 16px; }
.chan-h { display:flex; align-items:center; gap:11px; margin-bottom:14px; }
.chan-h b { font-size:13.5px; font-weight:600; }
.chan-st { font-size:11px; font-weight:600; color:var(--ov0); text-transform:uppercase; letter-spacing:.4px; }

/* collapsible config card */
.ccard { background:var(--surface); border:1px solid var(--line); border-radius:var(--r-tile); overflow:hidden; transition:border-color .14s ease; }
.ccard + .ccard, .aset-b .ccard:not(:first-child) { margin-top:0; }
.aset-b > .ccard { margin:0; }
.ccard:hover { border-color:var(--s2); }
.ccard.add { border-style:dashed; }

/* Dispositivos descobertos (Hub → Infraestrutura): lista simples, cada linha
   com o aparelho à esquerda e o botão "Monitorar" à direita. */
/* Busca local (nome/MAC/IP) — mesmo visual da .localsearch, filtra as linhas. */
.disc-search-wrap { position:relative; margin-bottom:12px; }
.disc-search-wrap svg { position:absolute; left:12px; top:50%; transform:translateY(-50%);
  width:15px; height:15px; color:var(--ov1); pointer-events:none; }
input.disc-search { width:100%; background:var(--surface); padding:10px 12px 10px 34px; }
input.disc-search:focus { background:var(--base); }
.disc-empty { margin:10px 2px 0; }
.disc-list { display:flex; flex-direction:column; gap:8px; }
.disc-row { display:flex; align-items:center; gap:12px; padding:10px 12px; border:1px solid var(--line);
  border-radius:var(--r-card); background:var(--base); }
.disc-row:hover { border-color:var(--s2); }
.disc-main { display:flex; flex-direction:column; gap:2px; min-width:0; flex:1; }
.disc-name { font-weight:600; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.disc-meta { font-size:12px; color:var(--ov1); }
.disc-side { display:flex; align-items:center; gap:12px; flex-shrink:0; }
.disc-ago { font-size:12px; color:var(--ov2); white-space:nowrap; }
.disc-mon { margin:0; }
/* Selo "já monitorado" no lugar do botão Monitorar. */
.disc-badge { font-size:12px; font-weight:600; color:var(--green); white-space:nowrap;
  padding:5px 10px; border:1px solid color-mix(in srgb, var(--green) 35%, transparent);
  border-radius:8px; background:color-mix(in srgb, var(--green) 10%, transparent); }

/* Código (token) da sonda, recuperável no form de editar — pra reinstalar sem
   gerar outro. */
.token-box { margin-top:8px; }
.token-row { display:flex; gap:8px; align-items:center; margin-top:6px; }
.token-row input { flex:1; min-width:0; }
.ccard-row { display:flex; align-items:center; gap:12px; padding:13px 16px; cursor:pointer; }
.ccard-row .dot { width:9px; height:9px; border-radius:50%; flex:0 0 auto; }
.ccard-row .dot.off { background:var(--ov0); box-shadow:none; }
.ccard-row .add-ico { color:var(--mauve); display:flex; flex:0 0 auto; }
.ccard-row .add-ico svg { width:17px; height:17px; }
.ccard-id { min-width:0; flex:1 1 auto; }
.ccard-name { font-size:13.5px; font-weight:600; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.ccard-meta { font-size:11.5px; color:var(--ov0); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; margin-top:1px; }
.ccard-row .chev { color:var(--ov1); display:flex; flex:0 0 auto; transition:transform .2s ease; }
.ccard-row .chev svg { width:16px; height:16px; }
.ccard.collapsed .chev { transform:rotate(-90deg); }
.ccard.collapsed .ccard-body { display:none; }
.ccard-body { padding:4px 16px 16px; border-top:1px solid var(--line-soft); }
.ccard-body .fgrid { margin-top:16px; }
.ccard-foot { display:flex; align-items:center; gap:10px; margin-top:16px; padding-top:14px; border-top:1px solid var(--line-soft); }

/* users */
.urow { display:flex; align-items:center; gap:12px; padding:12px 16px; background:var(--surface); border:1px solid var(--line); border-radius:var(--r-tile); flex-wrap:wrap; }
.urow + .urow, .urow + .uadd { margin-top:0; }
.urow .uav { width:34px; height:34px; border-radius:50%; flex:0 0 auto; display:grid; place-items:center; font-size:12.5px; font-weight:600;
  background:color-mix(in srgb,var(--mauve) 16%,transparent); color:var(--mauve); }
.urow .you { font-size:10px; font-weight:600; color:var(--ov0); background:var(--surface2); border-radius:5px; padding:1px 6px; margin-left:6px; vertical-align:middle; }
.urow .upw { max-width:170px; }
.urow.uadd .upw { max-width:180px; }
.urow select { width:auto; max-width:140px; flex:0 0 auto; }

/* ============================================================
   RELATÓRIOS
   ============================================================ */
.grid-reports { display:grid; grid-template-columns:repeat(auto-fill,minmax(430px,1fr)); gap:16px; }
.card.rep .rep-body { padding:6px 18px 16px; display:flex; flex-direction:column; gap:16px; }
.rmetric { display:flex; flex-direction:column; gap:7px; }
.rmh { display:flex; align-items:center; gap:8px; }
.rkey { width:9px; height:9px; border-radius:3px; flex:0 0 auto; }
.rkey.key-cpu { background:var(--blue); } .rkey.key-mem { background:var(--green); } .rkey.key-dsk { background:var(--peach); }
.rmh .rlabel { font-size:12.5px; font-weight:600; }
.rmh .rstats { font-size:11.5px; color:var(--ov1); }
.rmh .rstats b { color:var(--sub1); font-weight:700; }
.spark { width:100%; height:42px; display:block; }
.spark.cpu { color:var(--blue); } .spark.mem { color:var(--green); } .spark.dsk { color:var(--peach); }
.sparkline { fill:none; stroke:currentColor; stroke-width:2; vector-effect:non-scaling-stroke; stroke-linejoin:round; stroke-linecap:round; }
.sparkfill { fill:currentColor; opacity:.13; stroke:none; }
.rfoot { display:flex; gap:10px; font-size:11px; color:var(--ov0); }

.rep-proc { border-top:1px solid var(--line-soft); }
.rep-proc-h { display:flex; align-items:center; gap:10px; padding:13px 18px; cursor:pointer; }
.rep-proc-h:hover { background:color-mix(in srgb,var(--surface2) 40%,transparent); }
.rep-proc-h .rpt { font-size:12.5px; font-weight:600; white-space:nowrap; }
.rep-proc-h .rpt-sub { font-size:11px; color:var(--ov0); white-space:nowrap; }
.rep-proc-h .chev { color:var(--ov1); display:flex; transition:transform .2s ease; }
.rep-proc-h .chev svg { width:16px; height:16px; }
.rep-proc.collapsed .chev { transform:rotate(-90deg); }
.rep-proc.collapsed .rep-proc-b { display:none; }
.rep-proc-b { padding:2px 18px 16px; display:grid; grid-template-columns:1fr 1fr; gap:16px; }
.ptbl { min-width:0; }
.ptbl-h { font-size:10px; font-weight:700; letter-spacing:.6px; text-transform:uppercase; color:var(--ov0); padding:6px 0 8px; }
.prow { display:grid; grid-template-columns:54px 56px 1fr 48px; gap:8px; align-items:center; padding:5px 0; font-size:11.5px; }
.prow + .prow { border-top:1px solid var(--line-soft); }
.ppid { color:var(--ov0); }
.puser { color:var(--ov1); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.pcmd { color:var(--sub0); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.pval { text-align:right; font-weight:700; }

.clist.rep-mon .crow { grid-template-columns:minmax(200px,1.6fr) minmax(160px,1fr) 90px; }
.vtoggle.rwin button { padding:6px 12px; }

/* export menu */
.exp-wrap { position:relative; flex:0 0 auto; }
.exp-menu { position:absolute; right:0; top:calc(100% + 6px); z-index:20; min-width:178px;
  background:var(--base); border:1px solid var(--line); border-radius:11px; box-shadow:var(--shadow-pop); padding:5px; }
.exp-menu button { display:flex; align-items:center; gap:10px; width:100%; text-align:left; border:0; background:transparent;
  color:var(--sub0); font:inherit; font-size:13px; font-weight:500; padding:9px 11px; border-radius:8px; cursor:pointer; white-space:nowrap; }
.exp-menu button svg { width:15px; height:15px; color:var(--ov1); }
.exp-menu button:hover { background:color-mix(in srgb,var(--surface2) 60%,transparent); color:var(--text); }
.exp-menu button:hover svg { color:var(--mauve); }


/* ====== Relatório analítico (documento) ====== */
.report { max-width:1120px; }
.rep-cover .rc-top { display:flex; align-items:center; gap:10px; margin-bottom:20px; }
.rep-cover .rc-top .ph-back { display:inline-flex; align-items:center; gap:6px; color:var(--ov1); font-size:13px; cursor:pointer; padding:5px 10px; border-radius:8px; transition:.16s ease; white-space:nowrap; text-decoration:none; }
.rep-cover .rc-top .ph-back:hover { color:var(--lavender); background:color-mix(in srgb,var(--surface2) 60%,transparent); }
.rep-cover .rc-top .ph-back svg { width:14px; height:14px; }
.rep-cover h1 { margin:0; font-size:27px; font-weight:700; letter-spacing:-.6px; }
.rep-cover .cover-meta { margin-top:7px; font-size:13px; color:var(--ov1); }
.rep-cover .cover-meta b { color:var(--sub1); font-weight:600; }
.rep-sec { margin-top:36px; }
.ov { color:var(--ov0); }

/* resumo executivo */
.rep-exec { background:var(--base); border:1px solid var(--line); border-radius:var(--r-card); box-shadow:var(--shadow-card); padding:22px; margin-top:18px; }
.exec-h { display:flex; align-items:flex-start; gap:16px; }
.badge.big { font-size:12px; padding:5px 12px 5px 11px; flex:0 0 auto; margin-top:2px; }
.exec-t h3 { margin:0 0 5px; font-size:16px; font-weight:600; }
.exec-t p { margin:0; font-size:13.5px; color:var(--sub0); line-height:1.6; max-width:78ch; }
.rep-exec .rep-kpi { margin:20px 0; }
.findings { border-top:1px solid var(--line-soft); padding-top:16px; }
.find-t { font-size:11px; font-weight:700; letter-spacing:.8px; text-transform:uppercase; color:var(--ov0); margin-bottom:10px; }
.find, .rec { display:flex; align-items:flex-start; gap:11px; font-size:13px; color:var(--sub0); line-height:1.55; padding:5px 0; }
.find b, .rec b { color:var(--text); font-weight:600; }
.fi { width:8px; height:8px; border-radius:50%; flex:0 0 auto; margin-top:6px; }
.fi.ok { background:var(--green); } .fi.warn { background:var(--yellow); } .fi.crit { background:var(--red); }

/* análise por servidor */
.srv-sections { display:flex; flex-direction:column; gap:16px; }
.rep-srv { background:var(--base); border:1px solid var(--line); border-radius:var(--r-card); box-shadow:var(--shadow-card); padding:20px 22px; }
.rs-h { display:flex; align-items:center; gap:12px; padding-bottom:16px; border-bottom:1px solid var(--line-soft); margin-bottom:18px; }
.rs-h .dot { width:10px; height:10px; border-radius:50%; flex:0 0 auto; }
.rs-id { flex:1 1 auto; min-width:0; }
.rs-nm { font-size:16px; font-weight:700; }
.rs-sub { font-size:11.5px; color:var(--ov0); margin-top:2px; }
.rcharts { display:grid; grid-template-columns:repeat(3,1fr); gap:18px; margin-bottom:20px; }
.rc-h { display:flex; align-items:center; gap:7px; font-size:12px; font-weight:600; margin-bottom:6px; }
.rc-h .mono { font-size:11px; font-weight:700; }

/* tabelas do relatório (compartilhado) */
.stat-table, .sla-table, .inc-table, .proc-tbl { width:100%; border-collapse:collapse; }
.stat-table th, .sla-table th, .inc-table th, .proc-tbl th { text-align:right; font-size:10px; font-weight:700; letter-spacing:.5px; text-transform:uppercase; color:var(--ov0); padding:0 10px 9px; white-space:nowrap; }
.stat-table th:first-child, .sla-table th:first-child, .inc-table th:first-child, .proc-tbl th:first-child { text-align:left; }
.stat-table td, .sla-table td, .inc-table td, .proc-tbl td { text-align:right; font-size:12.5px; padding:8px 10px; color:var(--sub1); border-top:1px solid var(--line-soft); font-variant-numeric:tabular-nums; }
.stat-table td:first-child, .sla-table td:first-child, .inc-table td:first-child, .proc-tbl td:first-child { text-align:left; }
.stat-table th:first-child, .stat-table td:first-child { padding-left:0; }
.stat-table .rk { display:flex; align-items:center; gap:8px; font-weight:600; color:var(--text); }
.stat-table .rk .rkey { width:9px; height:9px; border-radius:3px; flex:0 0 auto; }

/* blocos de info */
.rblock { margin-top:20px; }
.rb-t { font-size:11px; font-weight:700; letter-spacing:.6px; text-transform:uppercase; color:var(--ov1); margin-bottom:10px; }
.rb-t .ov { font-weight:500; letter-spacing:0; text-transform:none; }
.rb-c { font-size:13px; color:var(--sub0); line-height:1.5; }
.rb-c b { color:var(--text); }

/* tempo por faixa */
.statebar { display:flex; height:12px; border-radius:6px; overflow:hidden; background:var(--surface2); }
.statebar .sb.ok { background:var(--green); } .statebar .sb.warn { background:var(--yellow); } .statebar .sb.crit { background:var(--red); }
.state-leg { display:flex; flex-wrap:wrap; gap:8px 18px; margin-top:10px; font-size:11.5px; color:var(--ov1); }
.state-leg span { display:inline-flex; align-items:center; gap:6px; }
.state-leg .d { width:8px; height:8px; border-radius:2px; }
.state-leg .d.ok { background:var(--green); } .state-leg .d.warn { background:var(--yellow); } .state-leg .d.crit { background:var(--red); }

/* heatmap por hora */
.heat { display:grid; grid-template-columns:repeat(24,1fr); gap:3px; }
.heat .hc { height:26px; border-radius:3px; }
.heat-ax { display:flex; justify-content:space-between; margin-top:5px; font-size:10px; color:var(--ov0); font-variant-numeric:tabular-nums; }

/* processos */
.proc-grid { display:grid; grid-template-columns:1fr 1fr; gap:24px; }
.proc-tbl th { padding:0 8px 8px; } .proc-tbl td { padding:7px 8px; }
.proc-tbl th:first-child, .proc-tbl td:first-child { padding-left:0; }
.proc-tbl .pcmd { max-width:1px; width:60%; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; text-align:left; color:var(--sub0); }

/* SLA + incidentes (cards de tabela) */
.sla-table, .inc-table { background:var(--base); border:1px solid var(--line); border-radius:var(--r-card); box-shadow:var(--shadow-card); border-collapse:separate; border-spacing:0; overflow:hidden; }
.inc-table th.lt, .inc-table td.lt { text-align:left; }
.inc-table td.cause { white-space:normal; color:var(--sub0); font-size:12px; }
.sla-table th, .inc-table th { padding:15px 14px 10px; } .sla-table td, .inc-table td { padding:12px 14px; }
.sla-table th:first-child, .sla-table td:first-child, .inc-table th:first-child, .inc-table td:first-child { padding-left:18px; }
.sla-table th:last-child, .sla-table td:last-child, .inc-table th:last-child, .inc-table td:last-child { padding-right:18px; }
.m-nm { font-size:13px; font-weight:600; color:var(--text); }
.m-url { font-size:10.5px; }
.bud { white-space:nowrap; }
.budbar { height:6px; border-radius:3px; background:var(--surface2); overflow:hidden; display:inline-block; width:84px; vertical-align:middle; margin-right:9px; }
.budbar span { display:block; height:100%; border-radius:3px; }
.budbar span.ok { background:var(--green); } .budbar span.warn { background:var(--yellow); } .budbar span.crit { background:var(--red); }
.inc-summary { display:grid; grid-template-columns:repeat(auto-fit,minmax(190px,1fr)); gap:14px; margin-bottom:16px; }
.sum { background:var(--base); border:1px solid var(--line); border-radius:var(--r-tile); box-shadow:var(--shadow-card); padding:15px 17px; }
.sum-v { font-size:19px; font-weight:700; letter-spacing:-.3px; }
.sum-l { font-size:11.5px; color:var(--ov1); margin-top:4px; }
.inc-table td:first-child { display:flex; align-items:center; gap:9px; font-weight:600; color:var(--text); }
.inc-table .dot { width:8px; height:8px; border-radius:50%; flex:0 0 auto; }

/* recomendações */
.recs { background:var(--base); border:1px solid var(--line); border-radius:var(--r-card); box-shadow:var(--shadow-card); padding:16px 20px; }

/* gráfico do relatório */
.chart { width:100%; height:46px; display:block; }
.chart.cpu { color:var(--blue); } .chart.mem { color:var(--green); } .chart.dsk { color:var(--peach); }
.chart .c-line { fill:none; stroke:currentColor; stroke-width:2; vector-effect:non-scaling-stroke; stroke-linejoin:round; stroke-linecap:round; }
.chart .c-fill { fill:currentColor; opacity:.12; stroke:none; }
.chart .c-avg { stroke:var(--ov1); stroke-width:1; stroke-dasharray:5 4; vector-effect:non-scaling-stroke; opacity:.55; }
.chart .c-warn { stroke:var(--red); stroke-width:1; stroke-dasharray:2 4; vector-effect:non-scaling-stroke; opacity:.5; }
.chart .c-peak { stroke-width:1.5; vector-effect:non-scaling-stroke; opacity:.6; }
.chart .c-peak.ok { stroke:var(--green); } .chart .c-peak.warn { stroke:var(--yellow); } .chart .c-peak.crit { stroke:var(--red); }

/* dispositivos no relatório */
.rep-dev { background:var(--base); border:1px solid var(--line); border-radius:var(--r-card); box-shadow:var(--shadow-card); overflow:hidden; }
.rep-dev-sum { padding:12px 18px; font-size:13px; font-weight:700; border-bottom:1px solid var(--line-soft); }
.rep-dev-src { display:flex; align-items:center; gap:10px; padding:10px 18px; font-weight:600; font-size:12.5px; background:color-mix(in srgb,var(--surface2) 26%,transparent); border-bottom:1px solid var(--line-soft); }
.rep-dev-src .rds-num { margin-left:auto; color:var(--ov1); font-weight:700; }
.rep-dev-grp { display:flex; align-items:center; gap:10px; padding:8px 18px 8px 26px; font-size:12.5px; }
.rep-dev-grp .dot { width:8px; height:8px; border-radius:50%; flex:0 0 auto; }
.dot.part { background:var(--yellow); box-shadow:0 0 0 3px color-mix(in srgb,var(--yellow) 18%,transparent); }
.rep-dev-grp + .rep-dev-grp { border-top:1px solid var(--line-soft); }
.rep-dev-grp .rdg-num { margin-left:auto; color:var(--ov1); font-variant-numeric:tabular-nums; }
.rep-dev-grp .rdg-acc { color:var(--green); font-size:11.5px; font-variant-numeric:tabular-nums; }
.rep-dev-grp .rdg-acc + .rdg-num { margin-left:14px; }
.dev-off-list { padding:12px 18px; border-top:1px solid var(--line-soft); }
.dev-off-list .dol-h { font-size:10px; font-weight:700; letter-spacing:.6px; text-transform:uppercase; color:var(--ov0); margin-bottom:8px; }
.dev-off { font-size:12px; color:var(--sub0); padding:3px 0; }
.dev-off.more { color:var(--ov1); font-style:italic; }

/* campo de horário compacto do resumo (Config → Alertas) */
.sum-time-wrap { margin-top:14px; }
.sum-time-wrap .field { max-width:200px; }
input[type=time].short { max-width:150px; }

/* ============================================================
   EMPTY / ERROR STATES
   ============================================================ */
.estate { text-align:center; padding:48px 24px; }
.estate .eico { width:54px; height:54px; border-radius:15px; margin:0 auto 16px; display:grid; place-items:center; background:var(--surface); border:1px solid var(--line); color:var(--ov1); }
.estate .eico svg { width:26px; height:26px; }
.estate h3 { margin:0 0 6px; font-size:15px; font-weight:600; }
.estate p { margin:0 auto; max-width:360px; font-size:13px; color:var(--ov1); line-height:1.55; }
.estate.crit .eico { background:color-mix(in srgb,var(--red) 12%,transparent); border-color:color-mix(in srgb,var(--red) 30%,transparent); color:var(--red); }

/* skeleton shimmer on refresh */
.refreshing .track > span, .refreshing .hb i { animation:pulseO 1s ease-in-out infinite; }
@keyframes pulseO { 0%,100%{opacity:1} 50%{opacity:.55} }

/* ============================================================
   RESPONSIVE
   ============================================================ */
@media (max-width:860px) {
  .topbar { height:58px; }
  .topbar-inner { padding:0 16px; gap:12px; }
  .gsearch-wrap { display:none; }
  .menubtn { display:grid; }
  .wrap { padding:20px 16px 56px; }
  .drow { grid-template-columns:1fr 88px; }
  .drow .dhb { display:none; }
  /* compact lists: drop lower-priority columns on small screens */
  .clist.srv .crow { grid-template-columns:minmax(110px,1fr) 1fr 1fr; }
  .clist.srv .crow > :nth-child(4), .clist.srv .crow > :nth-child(5) { display:none; }
  .clist.mon .crow { grid-template-columns:minmax(120px,1fr) 96px 76px; }
  .clist.mon:not(.sortable) .crow > :nth-child(3), .clist.mon:not(.sortable) .crow > :nth-child(4) { display:none; }
  /* Lista ordenável: a alça é a 1ª célula e empurra todos os índices em 1 — as
     colunas que somem no celular (barras e uptime) viram a 4ª e a 5ª. Sem esta
     regra, o `nth-child` acima esconderia o estado e as barras, e o template
     largo de 6 colunas continuaria valendo (rolagem horizontal na tela). */
  .clist.mon.sortable .crow { grid-template-columns:16px minmax(120px,1fr) 96px 76px; }
  .clist.mon.sortable.bells .crow { grid-template-columns:16px minmax(120px,1fr) 96px 76px 34px; }
  .clist.mon.sortable .crow > :nth-child(4), .clist.mon.sortable .crow > :nth-child(5) { display:none; }
  /* O cabeçalho da seção é apertado no celular: o seletor fica, a palavra
     "Ordenar" sai (a lista embaixo dele já diz o que ele ordena). */
  .monsort-lbl { display:none; }
  /* Com sino: as mesmas colunas + a do sino no fim (o sino NUNCA some — é a ação
     da linha). Sem isto, a regra acima esconderia as colunas do meio enquanto o
     template de 6 colunas continuaria valendo, e o sino escorregaria pro meio. */
  .clist.mon.bells .crow { grid-template-columns:minmax(120px,1fr) 96px 76px 34px; }
  /* Lista de clientes, 1º degrau: a tabela tem 8 colunas e precisa de ~735px —
     abaixo disso a PÁGINA inteira rolava de lado. Somem primeiro as contagens de
     infra (negados, servidores, monitores, sondas), que ninguém lê num relance;
     a coluna 4 vira a borda direita (o `:last-child` do desktop encosta na 8ª,
     que agora está escondida). */
  .cli-table th:nth-child(5), .cli-table td:nth-child(5),   /* Negados hoje */
  .cli-table th:nth-child(6), .cli-table td:nth-child(6),   /* Serv.        */
  .cli-table th:nth-child(7), .cli-table td:nth-child(7),   /* Mon.         */
  .cli-table th:nth-child(8), .cli-table td:nth-child(8) { display:none; }
  .cli-table th:nth-child(4), .cli-table td:nth-child(4) { padding-right:18px; }
  .admin-layout { grid-template-columns:1fr; gap:14px; }
  .grid-reports { grid-template-columns:1fr; }
  .rep-proc-b { grid-template-columns:1fr; }
  .rcharts { grid-template-columns:1fr; gap:14px; }
  .proc-grid { grid-template-columns:1fr; gap:18px; }
  .report { max-width:none; }
  .sla-table, .inc-table, .stat-table { display:block; overflow-x:auto; white-space:nowrap; }
  .rep-cover h1 { font-size:22px; }
  .admin-nav { position:static; top:auto; flex-direction:row; gap:6px; overflow-x:auto; padding-bottom:6px; -webkit-overflow-scrolling:touch; }
  .admin-nav .anav-label { display:none; }
  .anav-i { border-left:0; white-space:nowrap; border:1px solid var(--line); }
  .anav-i.on { border-color:transparent; }
}
@media (max-width:560px) {
  .brand .bname span { display:none; }
  .stat { padding:15px 16px; gap:13px; }
  .frow2 { flex-direction:column; }
  .rede-client-h { gap:8px; }
  /* Linha de equipamento: a `.clist` corta o que passa da largura (overflow
     hidden), então numa tela estreita as colunas fixas empurravam o SINO pra
     fora — a ação da linha simplesmente sumia. Aqui cai também a coluna de
     resposta (ms), e o nome passa a poder encolher (minmax 0). */
  .crow { padding:11px 14px; gap:10px; }
  .clist.mon:not(.sortable) .crow { grid-template-columns:minmax(0,1fr) auto; }
  .clist.mon:not(.sortable).bells .crow { grid-template-columns:minmax(0,1fr) auto 30px; }
  .clist.mon:not(.sortable) .crow > :nth-child(5) { display:none; }
  /* Na ordenável, a alça é a 1ª célula: todos os índices andam em 1. */
  .clist.mon.sortable .crow { grid-template-columns:14px minmax(0,1fr) auto; gap:9px; }
  .clist.mon.sortable.bells .crow { grid-template-columns:14px minmax(0,1fr) auto 30px; gap:9px; }
  .clist.mon.sortable .crow > :nth-child(6) { display:none; }
  /* Cabeçalho de seção: no celular, o que vem no fim dele (seletor de ordenação,
     sino da sonda) não cabe ao lado do título — quebra pra linha de baixo em vez
     de esticar a página. Vale pra qualquer seção: quebrar só acontece quando não
     coube, e não caber é justamente o que gerava rolagem horizontal. */
  .section { flex-wrap:wrap; }
  select.monsort { max-width:100%; }
  /* Lista de clientes, 2º degrau (celular): sai também a FONTE — ficam as três
     colunas que se lê num relance (cliente, dispositivos, acessos de hoje). Os
     cabeçalhos deixam de ser `nowrap`: "Acessos hoje" numa linha só não cabe
     num aparelho de 320px. Nada se perde — a linha inteira é clicável e o Hub
     do cliente tem tudo. */
  .cli-table th:nth-child(2), .cli-table td:nth-child(2) { display:none; }   /* Fonte */
  .cli-table th, .cli-table td { padding-left:8px; padding-right:8px; white-space:normal; }
  /* Com a fonte do sistema aumentada, o nome do cliente e os cabeçalhos crescem e a
     tabela passa a exigir mais largura do que a tela tem (a palavra inteira é o
     mínimo). Deixar a palavra quebrar tira esse piso. */
  .cli-table th, .cli-table td { overflow-wrap:anywhere; }
  .cli-table th:first-child, .cli-table td:first-child { padding-left:14px; }
  .cli-table th:nth-child(4), .cli-table td:nth-child(4) { padding-right:14px; }
}

/* mobile slide-down nav */
.mobnav {
  display:none; position:sticky; top:58px; z-index:25;
  background:var(--mantle); border-bottom:1px solid var(--line); padding:8px 16px 12px;
  flex-direction:column; gap:4px;
}
.mobnav.show { display:flex; }
.mobnav button { text-align:left; border:0; background:transparent; color:var(--sub0); font:inherit; font-size:14px; padding:11px 12px; border-radius:9px; cursor:pointer; display:flex; align-items:center; gap:10px; }
.mobnav button svg { width:17px; height:17px; }
.mobnav button.on { background:color-mix(in srgb,var(--mauve) 14%,transparent); color:var(--lavender); }
.mobnav .msearch { position:relative; display:flex; align-items:center; flex:0 0 auto; }
.mobnav .msearch svg { position:absolute; left:13px; top:50%; transform:translateY(-50%); width:16px; height:16px; color:var(--ov1); pointer-events:none; }
.mobnav .msearch input {
  width:100%; font:inherit; font-size:14px; color:var(--text);
  background:var(--surface); border:1px solid var(--line);
  border-radius:10px; padding:10px 12px 10px 38px; outline:none; transition:.16s ease;
}
.mobnav .msearch input::placeholder { color:var(--ov0); }
.mobnav .msearch input:focus { border-color:var(--mauve); background:var(--base); box-shadow:0 0 0 3px color-mix(in srgb,var(--mauve) 16%,transparent); }

/* bottom tab bar (mobile + tablet) — navegação fixa estilo app */
.botnav {
  display:none; position:fixed; left:0; right:0; bottom:0; z-index:40;
  background:color-mix(in srgb,var(--mantle) 92%,transparent);
  backdrop-filter:blur(16px); -webkit-backdrop-filter:blur(16px);
  border-top:1px solid var(--line);
  padding:6px 6px calc(6px + env(safe-area-inset-bottom)); gap:2px;
}
.botnav button {
  flex:1 1 0; min-width:0; border:0; background:transparent; color:var(--ov1); cursor:pointer;
  display:flex; flex-direction:column; align-items:center; justify-content:center; gap:3px;
  font-size:10.5px; font-weight:600; letter-spacing:.2px; padding:7px 4px 5px;
  border-radius:12px; white-space:nowrap; transition:.15s ease;
}
.botnav button svg { width:21px; height:21px; opacity:.9; }
.botnav button.on { background:transparent; color:var(--lavender); }
.botnav button.on svg { opacity:1; }
[data-theme="light"] .botnav button.on { color:var(--mauve); }

/* Painel do "Mais" (celular): as abas que não cabem na barra de baixo. Sobe do
   rodapé, logo acima da barra. `display` é o que abre/fecha — o [hidden] sozinho
   perde pro `display:flex` dos itens. Some junto com a barra no desktop. */
.botsheet { display:none; }
.botnav .botmore.on { color:var(--lavender); }
[data-theme="light"] .botnav .botmore.on { color:var(--mauve); }
@media (max-width:700px) {
  .botsheet:not([hidden]) {
    display:flex; flex-direction:column; gap:2px;
    position:fixed; left:8px; right:8px; z-index:41;
    bottom:calc(72px + env(safe-area-inset-bottom));
    background:var(--mantle); border:1px solid var(--line); border-radius:14px;
    padding:6px; box-shadow:0 14px 40px rgba(0,0,0,.45);
  }
  .botsheet button {
    display:flex; align-items:center; gap:12px; width:100%;
    border:0; background:transparent; color:var(--sub0); cursor:pointer;
    font:inherit; font-size:14px; font-weight:600; text-align:left;
    padding:12px 14px; border-radius:10px;
  }
  .botsheet button svg { width:20px; height:20px; flex:0 0 auto; opacity:.9; }
  .botsheet button.on { background:var(--surface2); color:var(--lavender); }
  [data-theme="light"] .botsheet button.on { color:var(--mauve); }

  /* ---- Painel de FILTROS (mesma casca do "Mais") ---------------------------
     A tela de Incidentes tem QUATRO fileiras de chips; empilhadas, comem ~180px
     do celular antes de você ver o primeiro incidente. Aqui elas viram um botão
     "Filtros · N" e moram neste painel. Como o do "Mais", ele vive FORA do
     #content — o auto-refresh de 3s não o fecha na mão do usuário. */
  .filtersheet:not([hidden]) {
    display:flex; flex-direction:column; gap:14px;
    position:fixed; left:8px; right:8px; z-index:41;
    bottom:calc(72px + env(safe-area-inset-bottom));
    max-height:70vh; overflow-y:auto; -webkit-overflow-scrolling:touch;
    background:var(--mantle); border:1px solid var(--line); border-radius:14px;
    padding:14px; box-shadow:0 14px 40px rgba(0,0,0,.45);
  }
  .filtersheet .sheet-h {
    display:flex; align-items:center; justify-content:space-between;
    font-size:15px; font-weight:700; color:var(--text);
  }
  .filtersheet .sheet-x {
    border:0; background:transparent; color:var(--ov1); cursor:pointer;
    font:inherit; font-size:13px; font-weight:600; padding:6px 10px; border-radius:8px;
  }
  /* Dentro do painel os grupos empilham, cada um com o nome vindo do
     `data-fgroup` (que o Rust põe em cada `.dfilters`). */
  .filtersheet .dtoolbar { display:flex; flex-direction:column; align-items:stretch; gap:14px; margin:0; }
  .filtersheet .dfilters {
    display:flex; flex-wrap:wrap; gap:6px; background:transparent; border:0; padding:0;
  }
  .filtersheet .dfilters::before {
    content:attr(data-fgroup);
    flex:1 0 100%;
    font-size:11px; font-weight:700; letter-spacing:.6px; text-transform:uppercase;
    color:var(--ov0); margin-bottom:2px;
  }
  .filtersheet .dfilter {
    background:var(--surface); border:1px solid var(--line); border-radius:10px;
    padding:9px 14px; min-height:40px;
  }
  .filtersheet .dfilter.on { background:var(--surface2); color:var(--text); border-color:color-mix(in srgb,var(--mauve) 45%,transparent); }

  /* O gatilho, no lugar onde a fita de chips estava. */
  html:not(.embed) .dtoolbar.tosheet { display:none; }
  .filterbtn {
    display:inline-flex; align-items:center; gap:8px; margin:18px 0;
    background:var(--surface); border:1px solid var(--line); border-radius:11px;
    color:var(--sub0); cursor:pointer; font:inherit; font-size:13px; font-weight:600;
    padding:0 14px; min-height:40px;
  }
  .filterbtn svg { width:15px; height:15px; }
  .filterbtn.on { color:var(--text); border-color:color-mix(in srgb,var(--mauve) 45%,transparent); }
  .filterbtn .fbn {
    display:inline-grid; place-items:center; min-width:19px; height:19px; padding:0 5px;
    border-radius:999px; background:var(--mauve); color:var(--mauve-ink);
    font-size:11px; font-weight:700;
  }
}
.filtersheet { display:none; }   /* no desktop nem existe */

/* ============================================================
   BARRA DE TELA, PROGRESSO E TRANSIÇÃO (celular)
   ============================================================ */
.apptitle { display:none; }
@media (max-width:700px) {
  /* No celular a topbar não dizia em que tela você está: só a marca e cinco botões.
     O JS espelha aqui o título (e o "voltar") que já existem no conteúdo. */
  html:not(.embed) .apptitle:not([hidden]) {
    display:flex; align-items:center; gap:4px; min-width:0; flex:1 1 auto;
  }
  /* Com o título na topbar, a marca vira só o ícone: o nome escrito ("ALFAMONITOR")
     rouba justamente a largura de que o título precisa. E numa tela com "voltar" o
     ícone também sai — é o padrão de app (ao descer um nível, a marca dá lugar ao
     título) e é o que faz "Monitoramento" caber: sem isso sobravam 73px pra uma
     palavra que precisa de 120, e ela saía cortada em "Monitor…". */
  html:not(.embed) .brand .bname { display:none; }
  html:not(.embed) .topbar.comvoltar .brand { display:none; }
  html:not(.embed) .topbar-inner { gap:10px; }
  .appback {
    display:none; border:0; background:transparent; color:var(--sub0); cursor:pointer;
    padding:6px; border-radius:9px; place-items:center;
  }
  .appback:not([hidden]) { display:grid; }
  .appback svg { width:18px; height:18px; display:block; }
  .apptt {
    font-size:16px; font-weight:700; color:var(--text);
    white-space:nowrap; overflow:hidden; text-overflow:ellipsis; min-width:0;
  }
  /* O título e o voltar já estão na topbar — repeti-los no conteúdo é gastar
     altura de tela à toa. O resto do cabeçalho (subtítulo, "atualizado às",
     alternador de densidade) fica. */
  html:not(.embed) .pagehead .ph-back { display:none; }
  html:not(.embed) .wrap > .screen-title { display:none; }
}

/* Barra fina de progresso sob a topbar enquanto a tela nova não chega. É o que
   diferencia "toquei e não aconteceu nada" de "está vindo". Só no celular — o
   desktop continua exatamente como é hoje (lá já existe o esmaecer do #content). */
@media (max-width:700px) {
  html.navegando:not(.embed) .topbar::after {
    content:""; position:absolute; left:0; right:0; bottom:-1px; height:2px;
    background:linear-gradient(90deg, transparent, var(--mauve), transparent);
    background-size:40% 100%; background-repeat:no-repeat;
    animation:navprog 900ms ease-in-out infinite;
  }
}
@keyframes navprog {
  0% { background-position:-40% 0; }
  100% { background-position:140% 0; }
}
@media (prefers-reduced-motion:reduce) {
  html.navegando .topbar::after { animation:none; background-position:0 0; background-size:100% 100%; opacity:.5; }
}

/* Transição entre telas (View Transitions API). Só no celular: no desktop a
   navegação continua exatamente como é hoje. O respeito a prefers-reduced-motion
   é feito no JS (nem chega a iniciar a transição). */
@media (max-width:700px) {
  ::view-transition-old(root), ::view-transition-new(root) { animation-duration:180ms; }
}
/* Aparelho estreito (iPhone SE e afins): "Monitoramento" ainda passava 13px do
   botão. Fonte e respiros um pouco menores compram o espaço — é o mínimo pra ele
   caber inteiro, que é o ponto de toda esta mudança. */
/* Celular comum (~390px): "Monitoramento" cabe, mas com 2px de sobra — qualquer
   diferença de renderização da fonte no aparelho real cortaria. Fonte um ponto
   menor e sem espaçamento entre letras dão ~14px de folga. */
@media (max-width:430px) {
  .botnav button { font-size:10px; letter-spacing:0; }
}
@media (max-width:380px) {
  /* Card do cliente num aparelho bem estreito (320px): com o Hub, o sino e a seta na
     mesma linha, sobram 77px pro nome — e TODOS saem com reticências. Aqui as ações
     descem pra própria linha, e o nome fica com a largura inteira do card. */
  /* O bloco de identidade toma a linha inteira e as AÇÕES descem pra segunda — só
     assim o nome tem largura de verdade nesta tela. (A bolinha desce junto com o
     nome porque agora mora DENTRO do bloco.) Na linha delas, elas começam pela
     ESQUERDA, alinhadas com o nome — jogadas na direita, ficavam soltas no meio do
     card, longe de tudo. */
  html:not(.embed) .rede-client-h { flex-wrap:wrap; }
  html:not(.embed) .rede-client-h .rc-id { flex:1 1 100%; }
  /* A seta de expandir vai pro canto DIREITO, longe do sino: coladas, o dedo que
     ia expandir o card acabava silenciando a sonda. */
  html:not(.embed) .rede-client-h .chev { margin-left:auto; }

  /* Aparelho bem estreito: o título da topbar disputa espaço com 4 botões de ícone.
     Fonte um ponto menor e respiros menores. Título longo (a capa do relatório) ainda
     sai com reticências — o que é o comportamento normal de uma barra de app. */
  html:not(.embed) .apptt { font-size:15px; }
  html:not(.embed) .topbar-inner { gap:8px; padding-left:12px; padding-right:12px; }
  html:not(.embed) .iconbtn { width:32px; height:32px; }
  .botnav { padding-left:4px; padding-right:4px; gap:1px; }
  /* `letter-spacing:0` também é de propósito: os .2px por letra viram ~3px numa
     palavra de 13, e é justamente essa a folga que faltava. */
  .botnav button { font-size:9px; letter-spacing:0; padding-left:2px; padding-right:2px; }
  .botnav button svg { width:20px; height:20px; }
}
#content.navloading { opacity:.5; transition:opacity .12s ease; }

@media (max-width:1024px) {
  /* tela dividida é só para desktop largo */
  #splitbtn { display:none; }
}
/* Abaixo disso a barra de abas fica apertada demais mesmo rolando —
   troca pra navegação inferior estilo app. Acima, as abas do topo ficam
   sempre visíveis (rolando na horizontal se precisar), igual ao protótipo. */
@media (max-width:700px) {
  .tabs { display:none; }
  .botnav { display:flex; }
  .wrap { padding-bottom:calc(76px + env(safe-area-inset-bottom)); }
}

/* ============================================================
   TELA DIVIDIDA (2 painéis por iframe)
   ============================================================ */
/* Botão "Dividir" ativo. */
#splitbtn.on { color:var(--lavender); border-color:color-mix(in srgb,var(--mauve) 45%,transparent); background:color-mix(in srgb,var(--mauve) 16%,transparent); }
[data-theme="light"] #splitbtn.on { color:var(--mauve); }

/* Host: quando dividido, a coluna do app ocupa a viewport e o painel único some. */
body.split .app { height:100vh; overflow:hidden; }
body.split #content { display:none; }
body.split .tabs, body.split .botnav { display:none; }
.splitview { flex:1 1 auto; display:flex; min-height:0; }
.pane { flex:1 1 0; min-width:340px; min-height:0; overflow:hidden; display:flex; }
.pane iframe { flex:1 1 auto; width:100%; height:100%; border:0; display:block; }
.divider {
  flex:0 0 6px; cursor:col-resize; background:var(--line);
  transition:background .15s ease; touch-action:none;
}
.divider:hover, .divider.dragging { background:var(--mauve); }

/* Modo embed: cada painel é o app dentro de um iframe; enxuga o chrome global e
   mantém só a faixa de abas + o conteúdo. */
.embed .brand, .embed .gsearch-wrap, .embed .userchip-wrap, .embed #themebtn,
/* O sino sai do embed junto com o splitbtn: cada painel do "dividir tela" é um
   iframe com uma instância inteira do app — N painéis dariam N sinos e N pollers. */
.embed .notif-wrap,
.embed #splitbtn, .embed #menubtn, .embed .botnav,
.embed .mobnav { display:none !important; }
.embed .topbar { height:50px; }
.embed .topbar-inner { padding:0 14px; gap:8px; }
.embed .topbar .spacer { display:none; }
/* As abas ficam sempre visíveis no painel, mesmo estreito (o painel costuma ser
   < 700px, largura em que a .tabs normalmente vira navegação inferior). A
   faixa encolhe até a largura do painel e rola por dentro (sem barra) em vez
   de estourar o documento e criar uma barra horizontal feia embaixo. */
.embed .tabs { display:flex !important; flex:1 1 auto; min-width:0; margin-left:0; overflow-x:auto; scrollbar-width:none; }
.embed .tabs::-webkit-scrollbar { height:0; width:0; }
.embed .wrap { padding-bottom:26px; }
/* A rolagem vertical do painel encosta no divisor; a barra nativa "gorda" fica
   feia entre os dois. Dentro do painel, deixamos fina e no tema (sobreposta ao
   conteúdo, sem ocupar uma coluna própria). */
.embed { scrollbar-width:thin; scrollbar-color:color-mix(in srgb,var(--ov1) 55%,transparent) transparent; }
.embed::-webkit-scrollbar, .embed body::-webkit-scrollbar { width:9px; height:9px; }
.embed::-webkit-scrollbar-track, .embed body::-webkit-scrollbar-track { background:transparent; }
.embed::-webkit-scrollbar-thumb, .embed body::-webkit-scrollbar-thumb {
  background:color-mix(in srgb,var(--ov1) 45%,transparent);
  border-radius:6px; border:2px solid transparent; background-clip:padding-box;
}
.embed::-webkit-scrollbar-thumb:hover, .embed body::-webkit-scrollbar-thumb:hover {
  background:color-mix(in srgb,var(--ov1) 70%,transparent); background-clip:padding-box;
}

/* ============================================================
   PRINT (Relatórios → PDF)
   ============================================================ */
@media print {
  @page { margin:12mm; }
  .topbar, .mobnav, .botnav, .pagehead .ph-back, .rc-top .ph-back, .vtoggle, .exp-wrap, .updated .live { display:none !important; }
  body { background:#fff; }
  .wrap, .report { max-width:none; padding:0; }
  .page { overflow:visible; }
  .section { margin:18px 0 10px; break-after:avoid; }
  .card, .clist, .inc-list, .rep-exec, .recs, .rep-dev { box-shadow:none !important; break-inside:avoid; }
  .badge.big { box-shadow:none !important; }
  .updated { color:#555; }

  /* A largura do PDF (~794px) dispara o responsivo de 860px, que vira as tabelas
     em bloco rolável e as CORTA no papel. Aqui restauramos tabela normal. */
  .stat-table, .sla-table, .inc-table { display:table !important; overflow:visible !important; white-space:normal !important; }
  .rcharts { grid-template-columns:repeat(3,1fr) !important; gap:12px; }
  .proc-grid { grid-template-columns:1fr 1fr !important; gap:16px; }

  /* Tabelas mais compactas para caber na largura do papel. */
  .stat-table, .sla-table, .inc-table, .proc-tbl { font-size:10.5px; }
  .sla-table th, .sla-table td, .inc-table th, .inc-table td { padding:7px 8px; }
  .sla-table th:first-child, .sla-table td:first-child, .inc-table th:first-child, .inc-table td:first-child { padding-left:12px; }
  .sla-table th:last-child, .sla-table td:last-child, .inc-table th:last-child, .inc-table td:last-child { padding-right:12px; }
  .stat-table th, .stat-table td { padding:6px 7px; }
  .proc-tbl th, .proc-tbl td { padding:5px 6px; }
  .budbar { width:46px; margin-right:6px; }

  /* Quebra graciosa: a seção do servidor pode atravessar páginas, mas os blocos
     internos e as linhas de tabela não se partem no meio. */
  .rep-srv, .recs, .sla-table, .inc-table { break-inside:auto; }
  .rep-exec, .sum, .rcharts, .stat-table, .ptbl, .rblock, .inc-summary, .rs-h { break-inside:avoid; }
  tr { break-inside:avoid; }
}
.printing .topbar, .printing .mobnav, .printing .botnav { display:none !important; }

/* ============================================================
   Modal de detalhe do cliente (aba Dispositivos)
   ============================================================ */
/* Gatilho no cabeçalho do grupo (abre o modal). Botão de ícone discreto. */
.dgroup-h .gstats {
  width:30px; height:30px; border-radius:8px; border:1px solid transparent;
  background:transparent; color:var(--ov0); cursor:pointer; flex:0 0 auto;
  display:grid; place-items:center; transition:.14s ease; padding:0;
}
.dgroup-h .gstats:hover { color:var(--mauve); border-color:var(--line); background:var(--base); }
.dgroup-h .gstats svg { width:15px; height:15px; display:block; }

/* Link "Hub →" no cabeçalho do grupo — vai pro hub do cliente. */
.dgroup-h .hublink {
  font-size:12px; font-weight:600; color:var(--lavender); white-space:nowrap; flex:0 0 auto;
  padding:5px 10px; border-radius:8px; transition:.14s ease;
}
.dgroup-h .hublink:hover { background:color-mix(in srgb,var(--lavender) 14%,transparent); }

/* Badge de acessos liberados HOJE no cabeçalho do cliente. */
.dgroup-h .abadge {
  flex:0 0 auto; font-size:11px; font-weight:700; font-variant-numeric:tabular-nums;
  padding:2px 9px; border-radius:999px; white-space:nowrap;
  color:var(--green); background:color-mix(in srgb,var(--green) 14%,transparent);
}

/* Badge do horário de funcionamento do cliente (neutro; âmbar quando fechado). */
.dgroup-h .hbadge {
  flex:0 0 auto; font-size:11px; font-weight:600; padding:2px 9px; border-radius:999px;
  white-space:nowrap; max-width:240px; overflow:hidden; text-overflow:ellipsis;
  color:var(--sub0); background:var(--surface2);
}
.dgroup-h .hbadge.closed {
  color:var(--peach); background:color-mix(in srgb,var(--peach) 14%,transparent);
}
/* Botão de relógio (abre o editor de horário). Igual ao gstats. */
.dgroup-h .gclock {
  width:30px; height:30px; border-radius:8px; border:1px solid transparent;
  background:transparent; color:var(--ov0); cursor:pointer; flex:0 0 auto;
  display:grid; place-items:center; transition:.14s ease; padding:0;
}
.dgroup-h .gclock:hover { color:var(--mauve); border-color:var(--line); background:var(--base); }
.dgroup-h .gclock svg { width:15px; height:15px; display:block; }

/* Sino de notificar/silenciar (Dispositivos + linha de Incidentes) — form
   inline, um botão de ícone só. */
.bellform { display:inline-flex; flex:0 0 auto; }
.bell {
  width:30px; height:30px; border-radius:8px; border:1px solid transparent;
  background:transparent; color:var(--ov0); cursor:pointer; flex:0 0 auto;
  display:grid; place-items:center; transition:.14s ease; padding:0;
}
.bell:hover { color:var(--mauve); border-color:var(--line); background:var(--surface2); }
.bell svg { width:15px; height:15px; display:block; }
.bell.muted { color:var(--red); }
.bell.muted:hover { color:var(--red); border-color:color-mix(in srgb,var(--red) 30%,transparent); }

/* Editor de horário de funcionamento (modal). */
.hours-form .hours-24 { margin-bottom:4px; }
.hours-grid { display:flex; flex-direction:column; gap:8px; margin:6px 0 12px; }
.hours-grid[hidden] { display:none; }
.hrow { display:flex; align-items:center; gap:10px; flex-wrap:wrap; position:relative; }
.hrow .hday {
  flex:0 0 38px; font-size:12px; font-weight:700; color:var(--sub0);
}
.hrow .hturn { display:inline-flex; align-items:center; gap:6px; }
.hrow .hturn2[hidden] { display:none; }
.hrow .hsep { color:var(--ov1); }
/* 2º turno opcional: botão "+ 2º turno" e o "×" para remover. */
.hrow .hturn-add {
  border:0; background:transparent; color:var(--mauve); cursor:pointer;
  font-size:12px; font-weight:600; padding:4px 6px; border-radius:6px; white-space:nowrap;
}
.hrow .hturn-add[hidden] { display:none; }
.hrow .hturn-add:hover { background:var(--surface); }
.hrow .hturn-rm {
  border:0; background:transparent; color:var(--ov0); cursor:pointer;
  font-size:16px; line-height:1; padding:0 2px; margin-left:1px;
}
.hrow .hturn-rm:hover { color:var(--red); }
.hours-grid input[type=time].htime { max-width:104px; padding:6px 8px; }
/* Copiar o horário do dia para outros (botão + mini-menu de alvo). */
.hrow .hcopy-wrap { position:relative; margin-left:auto; flex:0 0 auto; }
.hrow .hcopy {
  width:28px; height:28px; border-radius:7px; border:1px solid transparent;
  background:transparent; color:var(--ov0); cursor:pointer; padding:0;
  display:grid; place-items:center; transition:.14s ease;
}
.hrow .hcopy:hover { color:var(--mauve); border-color:var(--line); background:var(--base); }
.hrow .hcopy svg { width:15px; height:15px; display:block; }
.hcopy-menu {
  position:absolute; top:calc(100% + 4px); right:0; z-index:5;
  display:flex; flex-direction:column; min-width:188px; padding:4px;
  background:var(--base); border:1px solid var(--line); border-radius:9px;
  box-shadow:var(--shadow-pop);
}
.hcopy-menu[hidden] { display:none; }
.hcopy-menu button {
  text-align:left; width:100%; padding:7px 10px; border:0; border-radius:6px;
  background:transparent; color:var(--text); font-size:12.5px; cursor:pointer;
  white-space:nowrap; transition:.12s ease;
}
.hcopy-menu button:hover { background:var(--surface); color:var(--mauve); }
.hours-hint { font-size:11.5px; color:var(--ov0); line-height:1.5; margin:0 0 14px; }
.hours-actions { display:flex; justify-content:flex-end; }

body.modal-open { overflow:hidden; }
.modal-backdrop {
  position:fixed; inset:0; z-index:60; display:none;
  align-items:center; justify-content:center; padding:20px;
  background:color-mix(in srgb,var(--crust) 68%,transparent);
  backdrop-filter:blur(8px); -webkit-backdrop-filter:blur(8px);
}
.modal-backdrop.show { display:flex; }
.modal {
  background:var(--base); border:1px solid var(--line); border-radius:var(--r-card);
  box-shadow:var(--shadow-pop); width:min(880px,94vw); max-height:90vh;
  /* Coluna flex: o cabeçalho fica fixo e SÓ o corpo rola — a barra de rolagem
     nunca encosta no header (evita a "quebra" no topo). */
  display:flex; flex-direction:column; overflow:hidden;
  outline:none;
}
.modal-h {
  flex:0 0 auto; display:flex; align-items:center; gap:11px;
  padding:16px 20px; background:var(--surface); border-bottom:1px solid var(--line);
}
.modal-h .dot { width:9px; height:9px; border-radius:50%; flex:0 0 auto; }
.modal-tt { flex:1 1 auto; min-width:0; display:flex; flex-direction:column; gap:2px; }
.modal-tt b { font-size:15.5px; font-weight:700; letter-spacing:.1px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.modal-sub { font-size:11.5px; color:var(--ov0); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.modal-x {
  width:32px; height:32px; border-radius:8px; border:1px solid var(--line);
  background:var(--base); color:var(--ov1); cursor:pointer; flex:0 0 auto;
  display:grid; place-items:center; transition:.14s ease;
}
.modal-x:hover { color:var(--text); border-color:var(--s2); }
.modal-x svg { width:16px; height:16px; }
.modal-b {
  flex:1 1 auto; min-height:0; overflow-y:auto; padding:18px 20px 22px;
  /* Barra de rolagem discreta na cor do tema (Firefox). */
  scrollbar-width:thin; scrollbar-color:var(--s2) transparent;
}
/* Barra de rolagem do corpo — Chrome/Safari/Edge. */
.modal-b::-webkit-scrollbar { width:10px; }
.modal-b::-webkit-scrollbar-track { background:transparent; }
.modal-b::-webkit-scrollbar-thumb {
  background:var(--s2); border-radius:8px;
  border:3px solid var(--base); background-clip:padding-box;
}
.modal-b::-webkit-scrollbar-thumb:hover { background:var(--ov2); background-clip:padding-box; }
.modal-b .rep-sec:first-child { margin-top:0; }
.modal-note { font-size:11.5px; color:var(--ov0); margin-top:9px; }
.modal-cap { font-size:10.5px; text-transform:uppercase; letter-spacing:.04em; color:var(--ov0); margin:12px 0 6px; }
.modal-loading { padding:48px 20px; text-align:center; color:var(--ov1); font-size:13px; }

/* Diálogo de confirmação (substitui o confirm() nativo): card compacto e centrado. */
.confirm-modal { width:min(420px,94vw); max-height:none; display:block; padding:22px 22px 18px; }
.confirm-msg { font-size:14.5px; line-height:1.5; color:var(--text); }
.confirm-acts { display:flex; justify-content:flex-end; gap:9px; margin-top:20px; }

@media (max-width:600px) {
  .modal-backdrop { padding:0; align-items:stretch; }
  .modal { width:100%; max-height:100vh; max-height:100dvh; border-radius:0; border:0; }
  .modal-h { padding:14px 16px; padding-top:calc(14px + env(safe-area-inset-top)); }
  .modal-b { padding:14px 16px calc(20px + env(safe-area-inset-bottom)); }
  /* O diálogo de confirmação continua um card centrado, não tela cheia. */
  .confirm-back { padding:20px; align-items:center; }
  .confirm-modal { width:100%; max-width:420px; border:1px solid var(--line); border-radius:var(--r-card); }
}

/* --- Central de notificações: sino + painel ------------------------------- */
/* Mesmo padrão de dropdown de .gsearch-wrap e .userchip-wrap: wrap relativo,
   painel absoluto à direita, [hidden] esconde. */
.notif-wrap { position:relative; flex:0 0 auto; }
#notifbtn { position:relative; }
/* Badge de contagem — deriva do `.chip .cc`, o único que já existia no app. */
.nbadge {
  position:absolute; top:-2px; right:-2px; min-width:16px; height:16px; padding:0 4px;
  border-radius:999px; background:var(--red); color:#fff;
  font-size:10px; font-weight:700; line-height:16px; text-align:center;
  border:2px solid var(--base); box-sizing:content-box;
}
.nbadge[hidden] { display:none; }
/* O painel do sino.
   `max-height` NÃO é uma fração da janela (era 70vh): é o espaço que existe DE VERDADE
   abaixo do sino, medido no JS a cada abertura e a cada resize (`fitNotifPanel`). Com uma
   fração fixa, a barra de rolagem aparecia dentro do painel mesmo sobrando 100px de tela.
   O valor daqui é só o ponto de partida, pro caso raro do JS não rodar. */
.notif-panel {
  position:absolute; right:0; top:calc(100% + 8px); z-index:70; width:340px; max-width:88vw;
  background:var(--base); border:1px solid var(--line); border-radius:12px;
  box-shadow:var(--shadow-pop); padding:6px; max-height:calc(100vh - 90px); overflow-y:auto;
}
.notif-panel[hidden] { display:none; }
.np-head { display:flex; align-items:center; gap:8px; padding:8px 10px 10px; }
.np-head b { font-size:13px; color:var(--sub1); }
.np-head .np-count { margin-left:auto; font-size:11px; color:var(--ov0); }
/* "Marcar todas" no próprio painel: abrir a tela cheia só pra dar baixa no que já se leu
   aqui é um passo a mais sem razão. */
.np-readall {
  flex:0 0 auto; background:transparent; border:0; padding:2px 4px; cursor:pointer;
  font:inherit; font-size:11px; font-weight:600; color:var(--blue); border-radius:6px;
}
.np-readall:hover { background:color-mix(in srgb,var(--blue) 12%,transparent); }
.np-readall:disabled { opacity:.5; cursor:default; }
.np-empty { padding:18px 10px; font-size:13px; color:var(--ov0); text-align:center; }
/* Uma linha = o link (miolo) + o botão de lida. O botão fica FORA do <a>: link dentro de
   link é HTML inválido. O `gap` entre as linhas vem do `+ .np-item` — sem ele as linhas
   se encostam e viram um bloco só. */
.np-item { display:flex; align-items:stretch; gap:2px; border-radius:9px; }
.np-item + .np-item { margin-top:3px; }
.np-item:hover { background:color-mix(in srgb,var(--surface2) 55%,transparent); }
.np-item.novo { background:color-mix(in srgb,var(--blue) 8%,transparent); }
.np-link {
  display:flex; align-items:flex-start; gap:9px; padding:9px 10px; border-radius:9px;
  text-decoration:none; color:inherit; flex:1 1 auto; min-width:0;
}
.np-dot { width:7px; height:7px; border-radius:50%; margin-top:5px; flex:0 0 auto; background:var(--ov0); }
.np-dot.crit { background:var(--red); }
.np-dot.warn { background:var(--peach); }
.np-dot.ok   { background:var(--green); }
.np-txt { display:flex; flex-direction:column; gap:2px; min-width:0; flex:1 1 auto; }
/* O TÍTULO também trunca. Sem isto, um nome de cliente comprido quebra em duas linhas, o
   item passa de 50px pra 76px, e oito deles não cabem mais no painel — era a causa real
   da barra de rolagem. */
.np-txt b { font-size:12.5px; color:var(--sub1); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.np-txt span { font-size:12px; color:var(--ov1); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.np-when { font-size:10.5px; color:var(--ov0); flex:0 0 auto; margin-top:1px; }
.np-tick {
  flex:0 0 auto; width:30px; display:grid; place-items:center; cursor:pointer;
  background:transparent; border:0; border-radius:9px; color:var(--ov0); transition:.16s ease;
}
.np-tick:hover { color:var(--green); background:color-mix(in srgb,var(--green) 12%,transparent); }
.np-tick svg { width:14px; height:14px; display:block; }
.np-tick:disabled { opacity:.4; cursor:default; }
.np-all {
  display:block; text-align:center; padding:9px; margin-top:4px; font-size:12.5px; font-weight:600;
  color:var(--blue); text-decoration:none; border-top:1px solid var(--line);
}
.np-all:hover { background:color-mix(in srgb,var(--surface2) 55%,transparent); }

/* Feed: reusa a .inc-row dos incidentes; só o link do miolo e o botão de "todas". */
.nread-all { margin:0 0 12px; }
.inc-main.nlink { text-decoration:none; color:inherit; }
.inc-main.nlink:hover b { color:var(--blue); }

/* Ações da linha do feed: lida (pessoal) + reconhecer/silenciar (equipe). */
.nacts { display:flex; align-items:center; gap:4px; flex:0 0 auto; }
.nsnooze { display:flex; gap:2px; }
.nact {
  background:transparent; border:1px solid var(--line); border-radius:7px; cursor:pointer;
  color:var(--ov1); font:inherit; font-size:11px; font-weight:600; line-height:1;
  padding:5px 6px; min-width:26px; display:grid; place-items:center; transition:.16s ease;
}
.nact:hover { color:var(--sub1); border-color:var(--ov0); background:color-mix(in srgb,var(--surface2) 60%,transparent); }
.nact.on { color:var(--peach); border-color:color-mix(in srgb,var(--peach) 45%,transparent); }
.nact svg { width:14px; height:14px; }
@media (max-width:760px) { .nsnooze { display:none; } }

/* Botão de push no rodapé do painel do sino. */
.np-push {
  display:block; width:100%; margin-top:4px; padding:9px; border-radius:9px;
  background:transparent; border:1px solid var(--line); cursor:pointer;
  font:inherit; font-size:12.5px; font-weight:600; color:var(--blue); transition:.16s ease;
}
.np-push:hover:not(:disabled) { background:color-mix(in srgb,var(--blue) 10%,transparent); }
.np-push:disabled { opacity:.6; cursor:default; }
.np-push[hidden] { display:none; }

/* ============================================================
   Vindos do Rust (antes eram dois <style> embutidos em mod.rs)

   O primeiro bloco morava no `page_shell`, DEPOIS do <link> deste arquivo — e por
   isso vencia a cascata em `.bell`, `.drow` e `.ptable` (que também são definidos
   lá em cima). Ficam no FIM do arquivo justamente para manter essa ordem: mover
   pra cima mudaria o visual. O segundo (`.hz-*`, cards da Hostinger) era injetado
   DENTRO do #content, ou seja, reparseado a cada tick de 3s do auto-refresh.
   ============================================================ */
.flash { border-radius:10px; padding:11px 14px; font-size:13px; margin:14px 0 4px; }
.flash.ok { background:color-mix(in srgb,var(--green) 14%,transparent); color:var(--green); }
.flash.err { background:color-mix(in srgb,var(--red) 14%,transparent); color:var(--red); }
.flash.warn { background:color-mix(in srgb,var(--peach) 16%,transparent); color:var(--peach); }
.chartcard { padding:16px 18px; }
.charttitle { font-size:12px; font-weight:600; letter-spacing:.4px; text-transform:uppercase; color:var(--ov1); margin-bottom:10px; }
.chartbox { height:76px; }
.chart { width:100%; height:76px; display:block; }
.chart .grid { stroke:var(--line); stroke-width:.5; }
.nochart { color:var(--ov0); font-size:13px; padding:24px 0; text-align:center; }
.ptable { width:100%; border-collapse:collapse; font-size:13px; }
.ptable th { text-align:left; color:var(--ov1); font-weight:500; padding:7px 10px; border-bottom:1px solid var(--line); font-size:11px; text-transform:uppercase; letter-spacing:.4px; }
.ptable td { padding:7px 10px; border-bottom:1px solid var(--line-soft); }
.ptable .cmd { color:var(--ov2); max-width:420px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; font-family:var(--font-mono); font-size:12px; }
.exp-menu a { display:flex; align-items:center; gap:10px; width:100%; text-align:left; color:var(--sub0);
  font-size:13px; font-weight:500; padding:9px 11px; border-radius:8px; text-decoration:none; white-space:nowrap; }
.exp-menu a svg { width:15px; height:15px; color:var(--ov1); }
.exp-menu a:hover { background:color-mix(in srgb,var(--surface2) 60%,transparent); color:var(--text); }
.exp-menu a:hover svg { color:var(--mauve); }
.bellform { margin:0; display:flex; flex:0 0 auto; }
.bell { background:transparent; border:0; cursor:pointer; color:var(--green); padding:4px;
  border-radius:7px; display:grid; place-items:center; }
.bell svg { width:16px; height:16px; }
.bell:hover { background:color-mix(in srgb,var(--surface2) 60%,transparent); }
.bell.muted { color:var(--ov0); }
.drow { grid-template-columns:1fr minmax(120px,180px) 96px 34px; }
@media (max-width:860px) { .drow { grid-template-columns:1fr 88px 34px; } }

/* Cards e listas da Hostinger (aba Visão geral). */
.hz-sec { font-size:13px; font-weight:600; color:var(--ov1); text-transform:uppercase; letter-spacing:.4px; margin:22px 0 10px; }
.hz-grid { display:grid; grid-template-columns:repeat(auto-fill,minmax(280px,1fr)); gap:14px; }
.hz-card { background:var(--base); border:1px solid var(--line); border-radius:12px; padding:14px 16px; }
.hz-cardh { display:flex; align-items:center; gap:10px; }
.hz-name { font-weight:600; font-size:14px; }
.hz-meta { display:flex; flex-wrap:wrap; gap:6px 12px; color:var(--ov1); font-size:12px; margin-top:6px; }
.hz-pill { margin-left:auto; font-size:11px; font-weight:600; padding:3px 9px; border-radius:999px; white-space:nowrap; }
.hz-pill.ok { background:color-mix(in srgb,var(--green) 16%,transparent); color:var(--green); }
.hz-pill.bad { background:color-mix(in srgb,var(--red) 16%,transparent); color:var(--red); }
.hz-pill.warn { background:color-mix(in srgb,var(--peach) 18%,transparent); color:var(--peach); }
.hz-pill.unknown { background:color-mix(in srgb,var(--ov0) 16%,transparent); color:var(--ov1); }
.hz-band { margin-top:11px; }
.hz-bandtop { display:flex; justify-content:space-between; font-size:11px; color:var(--ov1); margin-bottom:4px; }
.hz-bar { height:7px; border-radius:999px; background:var(--line); overflow:hidden; }
.hz-bar i { display:block; height:100%; border-radius:999px; background:var(--green); }
.hz-bar i.warn { background:var(--peach); }
.hz-bar i.bad { background:var(--red); }
.hz-actions { display:flex; flex-wrap:wrap; gap:8px; padding:0 18px 16px; }
.card .metrics + .hz-actions { margin-top:-2px; }
.hz-sechead { display:flex; align-items:center; gap:8px; margin:22px 0 10px; }
.hz-sechead .hz-sec { margin:0; }
.hz-count { font-size:11px; font-weight:700; color:var(--ov1); background:var(--surface2); border:1px solid var(--line); padding:1px 8px; border-radius:999px; }
.hz-list { display:grid; grid-template-columns:repeat(auto-fill,minmax(300px,1fr)); gap:10px; }
.hz-item { display:flex; align-items:center; gap:12px; padding:13px 15px; background:var(--base); border:1px solid var(--line); border-radius:12px; transition:border-color .12s, transform .12s; }
.hz-item:hover { border-color:color-mix(in srgb,var(--ov0) 40%,var(--line)); transform:translateY(-1px); }
.hz-dot { flex:none; width:9px; height:9px; border-radius:999px; box-shadow:0 0 0 3px color-mix(in srgb,currentColor 18%,transparent); }
.hz-dot.ok { color:var(--green); background:var(--green); }
.hz-dot.warn { color:var(--peach); background:var(--peach); }
.hz-dot.bad { color:var(--red); background:var(--red); }
.hz-dot.unknown { color:var(--ov0); background:var(--ov0); }
.hz-itxt { display:flex; flex-direction:column; gap:2px; min-width:0; flex:1; }
.hz-rname { font-weight:600; font-size:13px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.hz-sub { font-size:11px; color:var(--ov1); }
.hz-norenew { color:var(--red); font-weight:600; }
.hz-chip { flex:none; font-size:11px; font-weight:700; padding:4px 10px; border-radius:999px; white-space:nowrap; }
.hz-chip.ok { background:color-mix(in srgb,var(--green) 16%,transparent); color:var(--green); }
.hz-chip.warn { background:color-mix(in srgb,var(--peach) 18%,transparent); color:var(--peach); }
.hz-chip.bad { background:color-mix(in srgb,var(--red) 16%,transparent); color:var(--red); }
.hz-chip.unknown { background:color-mix(in srgb,var(--ov0) 16%,transparent); color:var(--ov1); }
.hz-empty { color:var(--ov1); font-size:13px; padding:18px; background:var(--base); border:1px solid var(--line); border-radius:12px; }

/* ============================================================
   BASE MÓVEL — o que faz o celular parar de parecer um site.

   Escopo: quase tudo mora em `html:not(.embed)`. O `.embed` é a tela dividida do
   DESKTOP (painéis em iframe estreitos) — decisão do usuário: painel estreito
   continua com cara de desktop, não vira celular.
   ============================================================ */

/* Safe-area. As metas `apple-mobile-web-app-status-bar-style: black-translucent` já
   estavam no HTML, mas eram inócuas sem o `viewport-fit=cover` (que acabou de entrar).
   Com ele, o conteúdo corre POR BAIXO do relógio/notch — a topbar tem que devolver
   esse espaço, e a barra de busca (sticky logo abaixo dela) tem que descer junto.
   Fora do iPhone, `env()` vale 0 e nada disso muda um pixel. */
.topbar {
  padding-top:env(safe-area-inset-top);
  /* A ALTURA cresce junto com a safe-area. Sem isto, o `height:62px` lá de cima
     continua valendo, o padding come o miolo por dentro (box-sizing:border-box) e a
     barra fica esmagada no iPhone com notch — o teste pegou isso: o conteúdo sobrava
     com 11px de altura. */
  height:calc(62px + env(safe-area-inset-top));
}
@media (max-width:860px) { .topbar { height:calc(58px + env(safe-area-inset-top)); } }
.mobnav { top:calc(58px + env(safe-area-inset-top)); }

@media (max-width:860px) {
  /* Celular deitado: o notch come a lateral. */
  .wrap { padding-left:max(16px, env(safe-area-inset-left)); padding-right:max(16px, env(safe-area-inset-right)); }
}

@media (max-width:700px) {
  /* 16px nos campos. Abaixo disso o iOS DÁ ZOOM sozinho ao focar o campo, a página
     "pula" e o usuário tem que fechar o zoom na mão — é o defeito que mais denuncia
     "isto é um site". O padding cai um pouco pra altura do campo não crescer junto.
     Os seletores repetem os dos overrides lá de cima (input[type=text], .unl-row
     select, select.monsort, .disc-search, .htime): sem isso, eles venceriam. */
  html:not(.embed) input[type=text], html:not(.embed) input[type=number],
  html:not(.embed) input[type=password], html:not(.embed) input[type=time],
  html:not(.embed) input[type=search], html:not(.embed) select,
  html:not(.embed) textarea, html:not(.embed) input.localsearch,
  html:not(.embed) select.monsort, html:not(.embed) input.disc-search,
  html:not(.embed) .unl-row select, html:not(.embed) .htime {
    font-size:16px;
  }
  html:not(.embed) select.monsort { padding-top:6px; padding-bottom:6px; }
  /* A grade de horário tem até 28 campos de hora: com a fonte maior eles não cabem
     mais em largura fixa. */
  html:not(.embed) .htime { max-width:none; width:100%; }

  /* Alvo de toque de 44px SEM mudar o desenho: a área clicável cresce por fora, com
     um pseudo-elemento. Os sinos têm 30px, o `.hcopy` 28px — no dedo, isso é um erro
     de mira garantido. */
  html:not(.embed) .bell, html:not(.embed) .gstats, html:not(.embed) .gclock,
  html:not(.embed) .hcopy, html:not(.embed) .np-tick, html:not(.embed) .nact,
  html:not(.embed) .hturn-rm, html:not(.embed) .hturn-add,
  html:not(.embed) .iconbtn, html:not(.embed) .userchip, html:not(.embed) .ph-back {
    position:relative;
  }
  html:not(.embed) .bell::after, html:not(.embed) .gstats::after, html:not(.embed) .gclock::after,
  html:not(.embed) .hcopy::after, html:not(.embed) .np-tick::after, html:not(.embed) .nact::after,
  html:not(.embed) .hturn-rm::after, html:not(.embed) .hturn-add::after,
  html:not(.embed) .iconbtn::after, html:not(.embed) .userchip::after, html:not(.embed) .ph-back::after {
    content:""; position:absolute; inset:-8px;
  }
  /* Respiro entre o sino e a seta de expandir o card. O sino ganhou 8px de folga
     invisível de cada lado (pra virar alvo de dedo) e, com o vão de 10px, sobrava
     ZERO de separação: o toque que ia expandir o card caía no sino e silenciava a
     sonda. Vale no mesmo corte da folga de toque (700px), senão um deixaria o outro
     sem efeito. */
  html:not(.embed) .rede-client-h .chev { margin-left:14px; }

  /* Botões e chips: altura mínima de dedo (40px). Não vale pros links de TEXTO
     dentro das linhas (`a.link` da tabela de clientes, `.nlink` das notificações):
     lá o alvo é a linha inteira, e esticar o texto quebraria o layout. */
  html:not(.embed) .btn, html:not(.embed) .btn.sm, html:not(.embed) .chip,
  html:not(.embed) .dfilter, html:not(.embed) .hubtab,
  html:not(.embed) .vtoggle button, html:not(.embed) .sistema-tabs .dfilter,
  html:not(.embed) .aset-add, html:not(.embed) .np-readall {
    min-height:40px;
  }
  /* As ações da notificação (✓ reconhecer, soneca) ficam lado a lado: com folga
     invisível elas se sobreporiam e o dedo acertaria a errada. Aqui o botão cresce
     de verdade. */
  html:not(.embed) .nact { min-width:40px; min-height:40px; }
}

/* Ponteiro grosso (dedo) — não é o mesmo que "tela pequena": um tablet grande também
   entra aqui, e um desktop com janela estreita NÃO. */
@media (pointer:coarse) {
  /* O :hover fica GRUDADO depois do toque (o navegador não tem como saber que o dedo
     saiu). São 46 regras de hover no arquivo; em vez de reescrever todas, desligamos
     as que mais incomodam — as que mexem em fundo, borda ou posição. */
  html:not(.embed) .card:hover, html:not(.embed) .crow:not(.chead):hover,
  html:not(.embed) .drow:hover, html:not(.embed) .inc-row:hover,
  html:not(.embed) .hz-item:hover, html:not(.embed) .cli-row:hover,
  html:not(.embed) .dgroup-h:hover, html:not(.embed) .np-link:hover {
    background:inherit; transform:none; border-color:inherit;
  }
}

/* Resposta ao toque. O retângulo cinza que o navegador desenha sozinho é a marca
   registrada de página web; trocamos por um "afundar" de 1,5% — é o que faz o toque
   parecer que ACONTECEU. */
html:not(.embed) * { -webkit-tap-highlight-color:transparent; }
html:not(.embed) button, html:not(.embed) a, html:not(.embed) .dfilter,
html:not(.embed) [data-toggle], html:not(.embed) [data-nav] {
  touch-action:manipulation;   /* mata o atraso de ~300ms herdado do duplo-toque */
}
@media (pointer:coarse) {
  html:not(.embed) .card:active, html:not(.embed) .crow:not(.chead):active,
  html:not(.embed) .drow:active, html:not(.embed) .inc-row:active,
  html:not(.embed) .cli-row:active, html:not(.embed) .stat:active,
  html:not(.embed) .dgroup-h:active, html:not(.embed) .rede-client-h:active,
  html:not(.embed) .botnav button:active, html:not(.embed) .dfilter:active,
  html:not(.embed) .btn:active, html:not(.embed) .hz-item:active {
    transform:scale(.985);
    transition:transform .06s ease;
  }
}
@media (prefers-reduced-motion:reduce) {
  html:not(.embed) *:active { transform:none !important; }
}

/* A rolagem para no app: sem "puxar pra atualizar" do navegador (o auto-refresh de 3s
   já faz isso) e sem a rolagem de uma lista interna arrastar a página junto. */
html:not(.embed) body { overscroll-behavior-y:contain; }

@media (max-width:700px) {
  /* Fitas que não quebravam e empurravam a página pra fora da tela:
     - os chips de filtro (a fita de tipo das Notificações tem 440px sozinha);
     - o topo do relatório (voltar + janela + Exportar);
     - o "Atualizado às … · auto-refresh a cada 3s", que era `nowrap`.
     Os chips ainda vão virar um painel de "Filtros" na próxima fase — isto aqui é o
     que impede a tela de rolar de lado ENQUANTO isso não chega. */
  html:not(.embed) .dtoolbar .dfilters { flex-wrap:wrap; }
  html:not(.embed) .rep-cover .rc-top { flex-wrap:wrap; }
  html:not(.embed) .updated { white-space:normal; }
}

@media (max-width:560px) {
  /* Card do cliente (Monitoramento): o NOME não quebra no meio. Ele dividia a linha
     com a contagem ("1 sonda(s) · 3/5") e com a tarja, sobrava uma coluna estreita e
     "Caio Farmacia" virava duas linhas. Aqui o nome fica na linha da bolinha (encolhe
     com reticências se precisar) e a contagem é que desce — o `flex:1 1 100%` nela é
     o que força a quebra. */
  html:not(.embed) .rede-client-h .rc-id > b {
    flex:1 1 auto; min-width:0;
    white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
  }
  html:not(.embed) .rede-client-h .rc-id > .scount { flex:1 1 100%; }

  /* Hero do Hub: nome + estado + "+ Vincular item" numa linha só estouravam a tela
     (o botão não quebra). Quebra em duas linhas, com o botão em largura total.
     O bloco do nome é `1 1 auto` (e não 100%): com 100% ele tomava a linha inteira e
     a bolinha de status sobrava sozinha numa linha acima — mesmo problema que o card
     do Monitoramento tinha. */
  html:not(.embed) .hub-hero { flex-wrap:wrap; }
  html:not(.embed) .hub-hero-tt { flex:1 1 auto; min-width:0; }
  html:not(.embed) .hub-hero .btn.primary { flex:1 1 100%; justify-content:center; }
}

/* ============================================================
   TABELA → CARTÃO (`.tcards`)

   No celular, cada LINHA da tabela vira um cartão e cada célula vira
   "rótulo: valor" — o rótulo sai do `data-label` que o Rust põe em cada <td>.
   A alternativa (rolar a tabela de lado) foi recusada: some com a informação
   do campo de visão e não tem cara de app.

   A primeira célula é o TÍTULO do cartão (não repete rótulo).
   `.lo` marca coluna de baixa prioridade: a tabela do relatório tem 9 colunas —
   empilhadas viram uma parede, então no celular só ficam as que se lê num relance.
   ============================================================ */
@media (max-width:700px) {
  html:not(.embed) table.tcards,
  html:not(.embed) table.tcards tbody,
  html:not(.embed) table.tcards tr,
  html:not(.embed) table.tcards td {
    display:block; width:auto;
  }
  html:not(.embed) table.tcards { border-collapse:separate; overflow:visible; white-space:normal; }
  html:not(.embed) table.tcards thead { display:none; }
  html:not(.embed) table.tcards tr {
    background:var(--base); border:1px solid var(--line); border-radius:12px;
    padding:12px 14px; margin-bottom:10px;
  }
  html:not(.embed) table.tcards td {
    display:flex; align-items:baseline; justify-content:space-between; gap:14px;
    padding:5px 0; border:0; text-align:right; white-space:normal; min-width:0;
    /* Com a fonte do sistema aumentada, rótulo e valor não cabem mais lado a lado e a
       célula empurrava a PÁGINA pra fora (foi o que sobrou de rolagem no iPhone SE).
       Deixando a célula quebrar, o valor desce pra baixo do rótulo. */
    flex-wrap:wrap; overflow-wrap:anywhere;
  }
  html:not(.embed) table.tcards td::before {
    content:attr(data-label);
    flex:0 1 auto; text-align:left; min-width:0; overflow-wrap:anywhere;
    font-size:11px; font-weight:600; letter-spacing:.5px; text-transform:uppercase;
    color:var(--ov0);
  }
  /* Título do cartão: marcado com `.tt` no Rust, e NÃO "a primeira célula" — na tabela
     de processos a primeira coluna é o PID, e um cartão chamado "1234" não diz nada
     (lá o título é o comando). */
  html:not(.embed) table.tcards td.tt {
    display:block; text-align:left; padding:0 0 9px; margin-bottom:5px;
    border-bottom:1px solid var(--line-soft);
    font-size:14px; font-weight:600; color:var(--text); white-space:normal;
  }
  html:not(.embed) table.tcards td.tt::before { display:none; }
  html:not(.embed) table.tcards td.lo, html:not(.embed) table.tcards th.lo { display:none; }
}

/* ============================================================
   TELAS DENSAS NO CELULAR

   O padrão que mais gasta tela é o mesmo em toda parte: os tiles de resumo saem UM
   POR LINHA. Os `minmax(180px)`/`minmax(190px)` do grid não cabem em dois numa tela
   de 343px úteis, então cada tile vira uma faixa de ~95px. O Hub tem DEZ — quase mil
   pixels de vazio antes do primeiro conteúdo. Aqui eles vão pra duas colunas.
   ============================================================ */
@media (max-width:560px) {
  html:not(.embed) .stats,
  html:not(.embed) .inc-summary {
    grid-template-columns:repeat(2, minmax(0,1fr));
    gap:10px;
  }
  /* Tile mais enxuto: com metade da largura, o respiro de 20px e o ícone de 44px
     empurram o número pra fora. */
  html:not(.embed) .stat { padding:14px; gap:11px; }
  html:not(.embed) .stat .sicon { width:36px; height:36px; }
  html:not(.embed) .stat .sicon svg { width:18px; height:18px; }
  html:not(.embed) .stat .sv { font-size:21px; }
  html:not(.embed) .stat .sl { font-size:11.5px; }
  html:not(.embed) .sum { padding:12px 13px; }
  html:not(.embed) .sum-v { font-size:17px; }

  /* Relatórios: o "voltar" já está na topbar (é o mesmo link) — repetido aqui, só
     gasta altura. O título fica: ele é longo e na topbar sai com reticências. */
  html:not(.embed) .rep-cover .rc-top .ph-back { display:none; }

  /* Os grids de cards pedem 300px de largura MÍNIMA por card. Num aparelho de 320px
     sobram 289 úteis — o card estourava a tela e a página rolava de lado. Uma coluna
     que aceita encolher (`minmax(0,1fr)`) resolve. */
  html:not(.embed) .grid-servers,
  html:not(.embed) .grid-monitors,
  html:not(.embed) .grid-sources,
  html:not(.embed) .hz-grid,
  html:not(.embed) .hz-list {
    grid-template-columns:minmax(0,1fr);
  }

  /* ACESSO — card do cliente recolhido.
     O cabeçalho tem NOVE peças numa linha que não quebra (contador, nome, nº de
     equipamentos, acessos de hoje, horário, estatísticas, Hub, sino, seta). O nome é
     o único que encolhe: no celular ele virava ZERO e o resto saía pela borda — como
     o card tem `overflow:hidden`, o conteúdo simplesmente sumia cortado.
     Agora o nome fica sozinho na 1ª linha (com a bolinha de contagem) e todo o resto
     desce: `flex:1 1 100%` no `.gcount` é o que força a quebra ali. */
  html:not(.embed) .dgroup-h { flex-wrap:wrap; gap:8px 10px; }
  html:not(.embed) .dgroup-h .gn { flex:1 1 auto; min-width:0; }
  html:not(.embed) .dgroup-h .gcount { flex:1 1 100%; }
  /* A seta vai pro canto direito, longe do sino (mesmo motivo do card de
     Monitoramento: a folga de toque do sino encostava nela). */
  html:not(.embed) .dgroup-h .chev { margin-left:auto; }

  /* INCIDENTES e NOTIFICAÇÕES — a linha da lista.
     Mesmo defeito, e ele APARECE quando o usuário aumenta a fonte do sistema (o
     Android multiplica até as fontes fixadas em px): a linha não quebra, tem
     `overflow:hidden`, e as peças de tamanho fixo (cliente, tipo, estado, "há 2h")
     empurram o miolo pra fora — o conteúdo some cortado em vez de vazar.
     Agora o título vem primeiro e sozinho na 1ª linha (`order:-1`), e o resto desce. */
  html:not(.embed) .inc-row { flex-wrap:wrap; gap:8px 10px; }
  html:not(.embed) .inc-main { order:-1; flex:1 1 100%; }
  html:not(.embed) .inc-row .bellform,
  html:not(.embed) .inc-row form { margin-left:auto; }
  /* A tarja com o nome do cliente não quebra: com a fonte aumentada ela passava da
     largura da linha e era cortada. Encolhe com reticências. */
  html:not(.embed) .inc-row .pill { max-width:100%; overflow:hidden; text-overflow:ellipsis; }

  /* Tiles: `auto-fit` em vez de duas colunas fixas — assim, num aparelho estreito COM
     a fonte aumentada, o próprio navegador cai pra uma coluna em vez de espremer duas
     e estourar a tela. E o conteúdo passa a poder quebrar (o piso da caixa era a
     palavra inteira: "Disponibilidade" não cabia e empurrava o tile pra fora). */
  html:not(.embed) .stats,
  html:not(.embed) .inc-summary {
    grid-template-columns:repeat(auto-fit, minmax(150px, 1fr));
  }
  html:not(.embed) .stat, html:not(.embed) .sum { min-width:0; }
  html:not(.embed) .stat .sv, html:not(.embed) .stat .sl,
  html:not(.embed) .sum-v, html:not(.embed) .sum-l { min-width:0; overflow-wrap:anywhere; }

  /* Títulos de seção eram `nowrap`: "SONDA OFFLINE · SEM DADOS" e "SERVIDORES ·
     ANÁLISE DETALHADA" não cabem num aparelho estreito COM a fonte aumentada, e
     empurravam a página inteira pra fora. */
  html:not(.embed) .section h2 { white-space:normal; overflow-wrap:anywhere; }

  /* Abas internas do Hub (Controle de acesso / Infraestrutura / Horário): três numa
     linha só não cabem com a fonte grande — rolam de lado, dentro da própria fita. */
  html:not(.embed) .hubtabs {
    overflow-x:auto; -webkit-overflow-scrolling:touch; scrollbar-width:none;
  }
  html:not(.embed) .hubtabs::-webkit-scrollbar { display:none; }
  html:not(.embed) .hubtab { flex:0 0 auto; margin-right:14px; white-space:nowrap; }

  /* Resumo executivo do relatório: o bloco de texto tinha piso de palavra inteira. */
  html:not(.embed) .exec-h { flex-wrap:wrap; }
  html:not(.embed) .exec-t { min-width:0; overflow-wrap:anywhere; }
}

@media (max-width:380px) {
  /* Aparelho estreito: com duas colunas sobram ~140px por tile, e o ícone ao LADO do
     texto não deixa espaço — o rótulo ("Rede local · alvos online") estourava a caixa
     e a página passava a rolar de lado. Aqui o ícone sobe pra cima do número. */
  html:not(.embed) .stat { flex-direction:column; align-items:flex-start; gap:8px; }
  html:not(.embed) .stat .sicon { width:30px; height:30px; border-radius:9px; }
  html:not(.embed) .stat .sicon svg { width:16px; height:16px; }
  html:not(.embed) .stat .sv { font-size:19px; }
  html:not(.embed) .stat .sl { font-size:11px; }
}

/* A FOLHA DE PAPEL tem ~794px e dispara as regras de celular — sem isto o relatório
   impresso sairia em cartões. Vem no fim do arquivo de propósito: precisa vencer o
   bloco `.tcards` acima. */
@media print {
  table.tcards, table.tcards thead, table.tcards tbody,
  table.tcards tr, table.tcards th, table.tcards td { display:revert !important; }
  table.tcards td::before { display:none !important; }
  table.tcards th.lo, table.tcards td.lo { display:table-cell !important; }
  table.tcards tr {
    background:transparent !important; border:0 !important;
    padding:0 !important; margin:0 !important;
  }
}
