/* ─────────────────────────────────────────────────────────────────────────────
   LEDGER — componentes do Painel do Licenciado
   Plano: docs/PLANO_PAINEL_UX_UI.md §5 a §10

   Ordem de carga: hub.css (herdado) → tokens.css (retoken) → ESTE ARQUIVO.
   Tudo aqui usa os tokens de tokens.css; nada de valor fixo inventado.

   CUIDADO — login.html e verificar.html carregam ESTE arquivo SEM o tokens.css.
   Por isso:
     · as regras que atingem elementos das telas públicas (.btn, .card, .topbar,
       main, .sidebar…) estão escopadas em `.app`, classe que só o painel tem;
     · o bloco "Login / verificação" no fim do arquivo continua escrito com os
       tokens do hub, exatamente como antes.

   Sem <style> e sem style="" (CSP estrita): estado vem de classe e de atributo
   (hidden, aria-pressed, data-label).
   ───────────────────────────────────────────────────────────────────────────── */

/* ═══ 1. Sidebar ══════════════════════════════════════════════════════════════ */

.app .sidebar { padding-bottom: var(--sp-2); }

/* Logo direto em 28px: a caixa branca do hub vira mancha no tema escuro. */
.app .side-brand {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  padding: var(--sp-4) var(--sp-3) var(--sp-3);
}
.side-brand__mark { width: 28px; height: 28px; flex-shrink: 0; display: block; }
.side-brand__mark img { width: 100%; height: 100%; object-fit: contain; display: block; }
.side-brand__text { display: flex; flex-direction: column; min-width: 0; }
.app .side-title {
  font-size: var(--fs-sm);
  font-weight: var(--fw-semibold);
  line-height: var(--lh-tight);
  letter-spacing: -.01em;
  color: var(--text);
}
.app .side-sub { font-size: var(--fs-2xs); color: var(--muted-2); }

/* ── Seletor de licença: o workspace mora no canto superior esquerdo ───────── */
.lic-switch { padding: 0 var(--sp-3) var(--sp-3); }
.lic-switch__label {
  display: block;
  font-size: var(--fs-2xs);
  font-weight: var(--fw-semibold);
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--muted-2);
  margin-bottom: var(--sp-1);
}
.lic-switch__control { position: relative; display: block; }
.lic-switch__select {
  appearance: none;
  -webkit-appearance: none;
  width: 100%;
  height: var(--ctl-h);
  padding: 0 var(--sp-6) 0 var(--sp-2);
  background: var(--surface);
  color: var(--text);
  border: 1px solid var(--border-strong);
  border-radius: var(--r-sm);
  font-family: inherit;
  font-size: var(--fs-sm);
  font-weight: var(--fw-medium);
  text-overflow: ellipsis;
}
.lic-switch__select:hover { border-color: var(--muted-2); }
/* Chevron em SVG inline (o data-URI do hub tinha o traço fixo e não seguia o tema). */
.lic-switch__chev {
  position: absolute;
  right: var(--sp-2);
  top: 50%;
  margin-top: -7px;
  width: 14px;
  height: 14px;
  color: var(--muted-2);
  pointer-events: none;
}
.lic-switch__meta {
  margin-top: var(--sp-1);
  font-size: var(--fs-2xs);
  color: var(--muted-2);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.lic-switch__meta:empty { display: none; }

/* ── Navegação ────────────────────────────────────────────────────────────── */
.app .side-nav { padding: 0 var(--sp-3); gap: 2px; }
.app .side-nav button {
  height: var(--ctl-h);
  gap: var(--sp-2);
  padding: 0 var(--sp-2);
  border-radius: var(--r-sm);
  font-size: var(--fs-sm);
  font-weight: var(--fw-medium);
  letter-spacing: 0;
  color: var(--muted);
}
.app .side-nav button svg { width: 16px; height: 16px; opacity: 1; }
.app .side-nav button:hover { background: var(--surface-3); color: var(--text); }
.app .side-nav button:hover svg { transform: none; }
.app .side-nav button.active {
  background: var(--accent-soft);
  color: var(--accent-ink);
  font-weight: var(--fw-semibold);
}
.app .side-nav button.active svg { color: var(--accent-ink); }
.app .side-nav button.active::before {
  left: calc(-1 * var(--sp-3));
  width: 2px;
  height: 20px;
  border-radius: 0 2px 2px 0;
  background: var(--accent);
}
.app .side-nav button .nav-count {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 18px;
  min-width: 18px;
  padding: 0 5px;
  border-radius: var(--pill);
  background: var(--surface-3);
  border: 1px solid var(--border);
  color: var(--muted);
  font-size: var(--fs-2xs);
  font-weight: var(--fw-semibold);
}
.app .side-nav button .nav-count[hidden] { display: none; }
.app .side-nav button .nav-count.is-danger {
  background: var(--danger-soft);
  border-color: var(--danger-border);
  color: var(--danger-ink);
}
.app .side-nav button.active .nav-count {
  background: var(--surface);
  border-color: var(--accent-border);
  color: var(--accent-ink);
}

/* ── Bloco de conta (substitui o logo repetido) ───────────────────────────── */
.side-account {
  margin: 0 var(--sp-3);
  padding-top: var(--sp-3);
  border-top: 1px solid var(--hairline);
}
.side-account__email {
  font-size: var(--fs-xs);
  color: var(--muted);
  margin-bottom: var(--sp-2);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.side-account__email:empty { display: none; }
.side-account__actions { display: flex; align-items: center; gap: var(--sp-1); }
.side-account__btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-1);
  height: var(--ctl-h-sm);
  padding: 0 var(--sp-2);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  color: var(--muted);
  font-family: inherit;
  font-size: var(--fs-xs);
  font-weight: var(--fw-semibold);
}
.side-account__btn:hover { color: var(--text); border-color: var(--border-strong); }
.side-account__btn svg { width: 15px; height: 15px; flex-shrink: 0; }
.side-account__btn--wide { flex: 1; }

/* ═══ 2. Topbar, main, rodapé ═════════════════════════════════════════════════ */

/* 52px, sólida, sem título duplicado: título + contexto à esquerda, ações à direita. */
.app .topbar {
  height: var(--topbar-h);
  min-height: var(--topbar-h);
  padding: 0 var(--page-pad);
  gap: var(--sp-4);
  border-bottom: 1px solid var(--border);
}
.app .topbar .left { gap: var(--sp-3); align-items: baseline; overflow: hidden; }
.app .page-title {
  font-size: var(--fs-xl);
  font-weight: var(--fw-semibold);
  letter-spacing: -.015em;
  white-space: nowrap;
}
.page-context {
  font-size: var(--fs-sm);
  color: var(--muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.page-context:empty { display: none; }
.topbar-actions { display: flex; align-items: center; gap: var(--sp-2); }
.topbar-actions:empty { display: none; }

.app main { padding: var(--sp-5) var(--page-pad) var(--sp-6); }
.app main > section { display: flex; flex-direction: column; gap: var(--sp-4); }

.sec-lead { font-size: var(--fs-sm); color: var(--muted); }
.sec-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-4);
  flex-wrap: wrap;
}
.sec-bar__meter { flex: 0 1 260px; min-width: 200px; }
.sec-bar__meter:empty { display: none; }
.note-slot:empty { display: none; }

.banner-slot {
  width: 100%;
  max-width: var(--maxw);
  margin: 0 auto;
  padding: var(--sp-4) var(--page-pad) 0;
}
.banner-slot:empty { display: none; }

/* Cartão: só borda, sem sombra (a escada de elevação começa no popover). */
.app .card {
  margin: 0;
  padding: var(--sp-5);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r);
  box-shadow: none;
}
.app .card-head { align-items: flex-start; gap: var(--sp-4); margin-bottom: var(--sp-4); }
.app .card-head h2 {
  font-size: var(--fs-lg);
  font-weight: var(--fw-semibold);
  letter-spacing: -.01em;
  margin: 0;
}
.app .card .desc, .app .card-head .desc {
  font-size: var(--fs-xs);
  color: var(--muted);
  margin: 2px 0 0;
}

/* Rodapé do app: UMA linha ao fim do fluxo. Nunca position: fixed. */
.appfoot {
  margin: auto auto 0;
  width: 100%;
  max-width: var(--maxw);
  min-height: 32px;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--sp-2);
  padding: 0 var(--page-pad) var(--sp-4);
  font-size: var(--fs-xs);
  color: var(--muted);
}
/* Nas páginas de acesso o conteúdo é uma coluna centralizada, então um rodapé
   alinhado à esquerda fica descolado do resto. No painel ele acompanha a
   largura do conteúdo e continua à esquerda. */
.pubpage .appfoot {
  justify-content: center;
  text-align: center;
  margin-inline: auto;
  padding-top: var(--sp-6);
}
.appfoot a { color: var(--muted); font-weight: var(--fw-regular); }
.appfoot a:hover { color: var(--text); text-decoration: underline; }
.appfoot__sep { color: var(--muted-3); }
.appfoot__btn {
  padding: 0;
  border: none;
  background: none;
  font: inherit;
  color: var(--muted);
  text-decoration: underline;
  text-underline-offset: 2px;
}
.appfoot__btn:hover { color: var(--text); }

/* ═══ 3. Botões ═══════════════════════════════════════════════════════════════ */

.app .btn {
  height: var(--ctl-h);
  padding: 0 var(--sp-3);
  border-radius: var(--r-sm);
  font-size: var(--fs-sm);
  font-weight: var(--fw-semibold);
  letter-spacing: 0;
  box-shadow: none;
}
.app .btn:hover { filter: none; background: var(--accent-hover); }
.app .btn svg { width: 15px; height: 15px; }
.app .btn.tiny { height: var(--ctl-h-sm); padding: 0 var(--sp-2); font-size: var(--fs-xs); }
.app .btn.secondary { background: var(--surface); color: var(--text); border-color: var(--border-strong); }
.app .btn.secondary:hover { background: var(--surface-2); border-color: var(--muted-2); }
.app .btn.ghost { background: transparent; color: var(--muted); border-color: var(--border); }
.app .btn.ghost:hover { background: var(--surface-2); color: var(--text); }
.app .btn.danger { background: var(--surface); color: var(--danger-ink); border-color: var(--danger-border); }
.app .btn.danger:hover { background: var(--danger-soft); border-color: var(--danger); filter: none; }

/* Variantes BEM (usadas pelo modal). Vermelho sólido só na confirmação final. */
.btn--primary { background: var(--accent); color: #fff; border-color: transparent; }
.btn--primary:hover { background: var(--accent-hover); }
.btn--secondary { background: var(--surface); color: var(--text); border-color: var(--border-strong); }
.btn--secondary:hover { background: var(--surface-2); border-color: var(--muted-2); }
.btn--ghost { background: transparent; color: var(--muted); border-color: transparent; }
.btn--ghost:hover { background: var(--surface-2); color: var(--text); }
.btn--danger { background: var(--surface); color: var(--danger-ink); border-color: var(--danger-border); }
.btn--danger:hover { background: var(--danger-soft); border-color: var(--danger); }
.btn--danger-solid { background: var(--danger-solid); color: #fff; border-color: transparent; }
.btn--danger-solid:hover { background: var(--danger-solid); filter: brightness(.93); }

.btn.is-busy { position: relative; color: transparent; pointer-events: none; }
.btn.is-busy > * { visibility: hidden; }
.btn.is-busy::after {
  content: "";
  position: absolute;
  width: 14px;
  height: 14px;
  border: 2px solid var(--border-strong);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: panel-spin .6s linear infinite;
}
.btn--primary.is-busy::after,
.btn--danger-solid.is-busy::after {
  border-color: rgba(255, 255, 255, .38);
  border-top-color: #fff;
}
@keyframes panel-spin { to { transform: rotate(360deg); } }

/* ═══ 4. Cartão de métrica ════════════════════════════════════════════════════ */

.metric-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: var(--sp-3);
}
.metric-row:empty { display: none; }

.metric {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--sp-1);
  min-width: 0;
  padding: var(--sp-4);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r);
  overflow: hidden;
  text-align: left;
  font-family: inherit;
  color: inherit;
}
/* Excesso de estado vira trilho de 2px no topo — nunca ícone colorido. */
.metric::before {
  content: "";
  position: absolute;
  inset: 0 0 auto;
  height: 2px;
  background: transparent;
}
.metric.is-ok::before { background: var(--ok); }
.metric.is-warn::before { background: var(--warn); }
.metric.is-danger::before { background: var(--danger); }

.metric-label {
  font-size: var(--fs-2xs);
  font-weight: var(--fw-semibold);
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--muted-2);
}
/* O slot grande é do dado: palavra e data nunca ocupam o lugar do número. */
.metric-value {
  display: flex;
  align-items: baseline;
  gap: var(--sp-1);
  font-size: var(--fs-3xl);
  font-weight: var(--fw-bold);
  line-height: 1;
  letter-spacing: -.02em;
  color: var(--text);
}
.metric-unit {
  font-size: var(--fs-sm);
  font-weight: var(--fw-medium);
  letter-spacing: 0;
  color: var(--muted);
}
.metric-meta {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  flex-wrap: wrap;
  min-height: 20px;
  font-size: var(--fs-xs);
  color: var(--muted);
}
.metric-meter {
  height: 4px;
  margin-top: var(--sp-1);
  border-radius: var(--pill);
  background: var(--surface-3);
  overflow: hidden;
}
.metric-meter > * { display: block; height: 100%; background: var(--accent); border-radius: inherit; }
.metric-meter.is-warn > * { background: var(--warn); }
.metric-meter.is-danger > * { background: var(--danger); }
.metric-meter.is-ok > * { background: var(--ok); }

/* Só métrica clicável (que filtra a tabela) ganha realce. */
.metric--action { cursor: pointer; width: 100%; transition: background .14s, border-color .14s; }
.metric--action:hover { background: var(--surface-2); border-color: var(--border-strong); }
.metric--action[aria-pressed="true"] { background: var(--accent-soft); border-color: var(--accent-border); }

/* Compatibilidade: métrica embrulhada em coluna (grid de 12 do hub ou wrapper). */
.bento > * > .metric,
.metric-row > * > .metric { width: 100%; height: 100%; }

/* ═══ 5. Chips de estado ══════════════════════════════════════════════════════ */
/* A cor mora no ponto; o texto fica legível. Forma redundante para daltônicos. */

.chip {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-1);
  height: 20px;
  padding: 0 var(--sp-2);
  border: 1px solid var(--border);
  border-radius: var(--pill);
  background: var(--surface-2);
  color: var(--text-2);
  font-family: var(--sans);
  font-size: var(--fs-2xs);
  font-weight: var(--fw-semibold);
  white-space: nowrap;
  vertical-align: middle;
}
.chip::before {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--muted-2);
  flex-shrink: 0;
}
.chip--ok      { background: var(--ok-soft);      border-color: var(--ok-border);      color: var(--ok-ink); }
.chip--ok::before      { background: var(--ok); }
.chip--warn    { background: var(--warn-soft);    border-color: var(--warn-border);    color: var(--warn-ink); }
.chip--warn::before    { background: var(--warn); }
.chip--danger  { background: var(--danger-soft);  border-color: var(--danger-border);  color: var(--danger-ink); }
.chip--danger::before  { background: var(--danger); }
.chip--info    { background: var(--info-soft);    border-color: var(--info-border);    color: var(--info-ink); }
.chip--info::before    { background: var(--info); }
.chip--neutral { background: var(--neutral-soft); border-color: var(--neutral-border); color: var(--neutral-ink); }
/* ponto OCO: "sem leitura" se distingue sem depender de cor */
.chip--neutral::before { width: 7px; height: 7px; background: transparent; border: 1.5px solid currentColor; }
/* único fundo sólido colorido de toda a interface — por isso funciona */
.chip--critical { background: var(--danger-solid); border-color: var(--danger-solid); color: #fff; }
.chip--critical::before { display: none; }
.chip--lg { height: 24px; padding: 0 var(--sp-3); font-size: var(--fs-xs); }

/* ═══ 6. Tabela de dados ══════════════════════════════════════════════════════ */

.data-table {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r);
}
/* overflow visível de propósito: menu de linha não pode ser cortado. */
.data-table__scroll { overflow: visible; }
.data-table table {
  width: 100%;
  table-layout: fixed;
  border-collapse: separate;
  border-spacing: 0;
  font-size: var(--fs-sm);
}
.data-table th {
  position: sticky;
  top: var(--topbar-h);
  z-index: 2;
  height: 32px;
  padding: 0 var(--sp-3);
  text-align: left;
  background: var(--surface-2);
  color: var(--muted);
  font-size: var(--fs-2xs);
  font-weight: var(--fw-semibold);
  letter-spacing: .08em;
  text-transform: uppercase;
  white-space: nowrap;
  border-bottom: 1px solid var(--border);
}
.data-table thead tr:first-child th:first-child { border-top-left-radius: var(--r); }
.data-table thead tr:first-child th:last-child { border-top-right-radius: var(--r); }
.data-table td {
  height: var(--row-h);
  padding: 0 var(--sp-3);
  color: var(--text-2);
  vertical-align: middle;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  border-bottom: 1px solid var(--hairline);
}
.data-table tbody tr:last-child td { border-bottom: none; }
/* sem zebra: divisor + hover bastam e mantêm leitura de documento */
.data-table tbody tr:hover td { background: var(--surface-2); }

.data-table td.is-num, .data-table th.is-num { text-align: right; }
.data-table td.is-id {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums slashed-zero;
  color: var(--text);
}
.data-table td.is-text { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.data-table td.is-shrink, .data-table th.is-shrink { width: 1%; white-space: nowrap; }
.data-table td.is-actions, .data-table th.is-actions {
  text-align: right;
  overflow: visible;
  padding-right: var(--sp-2);
}
.data-table td .chip { vertical-align: middle; }
.data-table td .empty-state { border: none; background: none; padding: var(--sp-8) var(--sp-4); }

/* larguras da tabela de Números (table-layout: fixed + colgroup) */
.data-table .c-phone   { width: 17ch; }
.data-table .c-install { width: auto; }
.data-table .c-status  { width: 15ch; }
.data-table .c-quality { width: 13ch; }
.data-table .c-scan    { width: 15ch; }
.data-table .c-actions { width: 56px; }

.data-table__bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  flex-wrap: wrap;
  padding: var(--sp-2) var(--sp-3);
  background: var(--surface-2);
  border-top: 1px solid var(--border);
  border-radius: 0 0 var(--r) var(--r);
  font-size: var(--fs-xs);
  color: var(--muted);
}
.data-table__bar:empty { display: none; }

/* ═══ 7. Filtro segmentado, busca, barra de ferramentas ═══════════════════════ */

.toolbar { display: flex; align-items: center; gap: var(--sp-3); flex-wrap: wrap; }

.search { position: relative; display: flex; align-items: center; flex: 1 1 260px; max-width: 380px; }
.search > svg {
  position: absolute;
  left: var(--sp-2);
  width: 15px;
  height: 15px;
  color: var(--muted-2);
  pointer-events: none;
}
.search__input {
  width: 100%;
  height: var(--ctl-h);
  padding: 0 var(--sp-3) 0 var(--sp-8);
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--r-sm);
  color: var(--text);
  font-family: inherit;
  font-size: var(--fs-sm);
}
.search__input::placeholder { color: var(--muted-2); }
.search__input:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--ring); }

.seg {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  padding: 2px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  max-width: 100%;
  overflow-x: auto;
}
.seg button, .seg__btn {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-1);
  height: 28px;
  padding: 0 var(--sp-3);
  background: transparent;
  border: 1px solid transparent;
  border-radius: var(--r-xs);
  color: var(--muted);
  font-family: inherit;
  font-size: var(--fs-sm);
  font-weight: var(--fw-medium);
  white-space: nowrap;
}
.seg button:hover { color: var(--text); }
.seg button[aria-pressed="true"] {
  background: var(--surface);
  border-color: var(--border);
  color: var(--text);
  font-weight: var(--fw-semibold);
  box-shadow: var(--el-1);
}
.seg__count { font-size: var(--fs-2xs); font-variant-numeric: tabular-nums; color: var(--muted-2); }
.seg__count:empty { display: none; }

/* ═══ 8. Estados vazios ═══════════════════════════════════════════════════════ */
/* grid-column: 1/-1 — sem isso o vazio fica espremido numa célula de 280px. */

.empty-state {
  grid-column: 1 / -1;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: var(--sp-2);
  padding: var(--sp-10) var(--sp-6);
  background: var(--surface);
  border: 1px dashed var(--border-strong);
  border-radius: var(--r);
  color: var(--muted);
}
.empty-state__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  color: var(--muted-2);
}
.empty-state__icon svg { width: 18px; height: 18px; }
.empty-state__title { font-size: var(--fs-lg); font-weight: var(--fw-semibold); color: var(--text); }
.empty-state__desc { font-size: var(--fs-sm); color: var(--muted); max-width: 52ch; }
.empty-state .btn { margin-top: var(--sp-2); }
/* vazio que é boa notícia, não falta de dado */
.empty-state--ok { background: var(--ok-soft); border-style: solid; border-color: var(--ok-border); }
.empty-state--ok .empty-state__icon { background: var(--surface); border-color: var(--ok-border); color: var(--ok); }
.empty-state--ok .empty-state__title,
.empty-state--ok .empty-state__desc { color: var(--ok-ink); }

/* ═══ 9. Callout e banner ═════════════════════════════════════════════════════ */
/* Callout: fato permanente sobre os dados da seção. Banner: estado que muda o
   que se pode fazer. Confirmação de ação é toast — nunca estes dois. */

.callout {
  display: flex;
  gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4);
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-left-width: 3px;
  border-radius: var(--r-sm);
  color: var(--text-2);
  font-size: var(--fs-sm);
  line-height: var(--lh-ui);
}
.callout > svg { width: 16px; height: 16px; flex-shrink: 0; margin-top: 2px; color: var(--muted-2); }
.callout p + p { margin-top: var(--sp-1); }
.callout ul { margin: var(--sp-1) 0 0; padding-left: var(--sp-4); display: grid; gap: 2px; }
.callout__title { display: block; font-weight: var(--fw-semibold); margin-bottom: 2px; }
.callout--warn   { background: var(--warn-soft);   border-color: var(--warn-border);   border-left-color: var(--warn);   color: var(--warn-ink); }
.callout--danger { background: var(--danger-soft); border-color: var(--danger-border); border-left-color: var(--danger); color: var(--danger-ink); }
.callout--info   { background: var(--info-soft);   border-color: var(--info-border);   border-left-color: var(--info);   color: var(--info-ink); }
.callout--warn > svg   { color: var(--warn); }
.callout--danger > svg { color: var(--danger); }
.callout--info > svg   { color: var(--info); }

.banner {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  width: 100%;
  padding: var(--sp-3) var(--sp-4);
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  color: var(--text-2);
  font-size: var(--fs-sm);
}
.banner > svg { width: 18px; height: 18px; flex-shrink: 0; }
.banner__text { flex: 1; min-width: 0; }
.banner__title { display: block; font-weight: var(--fw-semibold); }
.banner .btn { flex-shrink: 0; }
.banner--warn   { background: var(--warn-soft);   border-color: var(--warn-border);   color: var(--warn-ink); }
.banner--danger { background: var(--danger-soft); border-color: var(--danger-border); color: var(--danger-ink); }
.banner--warn > svg   { color: var(--warn); }
.banner--danger > svg { color: var(--danger); }

/* ═══ 10. Menu de ações por linha ═════════════════════════════════════════════ */
/* Fechado por [hidden] (padrão do modal.js); .is-open também é aceito. */

.row-menu { position: relative; display: inline-flex; }
.row-menu__btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  background: transparent;
  border: 1px solid transparent;
  border-radius: var(--r-sm);
  color: var(--muted);
}
.row-menu__btn:hover { background: var(--surface-3); border-color: var(--border); color: var(--text); }
.row-menu__btn svg { width: 16px; height: 16px; }
.row-menu__list {
  position: absolute;
  top: calc(100% + 4px);
  right: 0;
  z-index: 40;
  min-width: 220px;
  display: flex;
  flex-direction: column;
  gap: 1px;
  margin: 0;
  padding: var(--sp-1);
  list-style: none;
  text-align: left;
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--r-sm);
  box-shadow: var(--el-3);
}
.row-menu__list[hidden] { display: none; }
.row-menu.is-open .row-menu__list { display: flex; }
.row-menu__item {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  width: 100%;
  height: var(--ctl-h);
  padding: 0 var(--sp-2);
  background: none;
  border: none;
  border-radius: var(--r-xs);
  color: var(--text-2);
  font-family: inherit;
  font-size: var(--fs-sm);
  font-weight: var(--fw-medium);
  text-align: left;
  white-space: nowrap;
}
.row-menu__item svg { width: 15px; height: 15px; flex-shrink: 0; }
.row-menu__item:hover:not(:disabled) { background: var(--surface-2); color: var(--text); }
.row-menu__item:disabled { color: var(--muted-3); cursor: not-allowed; }
.row-menu__item--danger { color: var(--danger-ink); }
.row-menu__item--danger:hover:not(:disabled) { background: var(--danger-soft); color: var(--danger-ink); }

/* ═══ 11. Linha de instalação / domínio ═══════════════════════════════════════ */
/* Largura total com micro-colunas alinhadas: comparáveis entre si, o que a
   grade de cartões impedia. */

.install-list { display: flex; flex-direction: column; gap: var(--sp-2); }
.install-row {
  display: flex;
  align-items: center;
  gap: var(--sp-4);
  padding: var(--sp-3) var(--sp-4);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r);
}
.install-row:hover { border-color: var(--border-strong); }
.install-row__domain {
  flex: 1 1 240px;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  flex-wrap: wrap;
  font-family: var(--mono);
  font-size: var(--fs-sm);
  font-weight: var(--fw-semibold);
  color: var(--text);
  overflow-wrap: anywhere;
}
/* ATENÇÃO: `.install-row` é reusado pela lista de Domínios, que tem outras
   colunas (Usado por / Ações) e conteúdo de largura variável — chips, botão.
   Por isso o padrão aqui é flex, do tamanho do conteúdo. A grade fixa vale
   SÓ dentro de #installList (regra abaixo). */
.install-row__meta {
  display: flex;
  align-items: center;
  gap: var(--sp-6);
  flex-wrap: wrap;
  flex-shrink: 0;
}
.install-row__col { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.install-row__col > :first-child {
  font-size: var(--fs-2xs);
  font-weight: var(--fw-semibold);
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--muted-2);
}
.install-row__col > :last-child {
  font-size: var(--fs-sm);
  color: var(--text-2);
  font-variant-numeric: tabular-nums;
}

/* Instalações: grade de largura FIXA. Com colunas do tamanho do conteúdo, um
   endereço longo (00n3h154-3101.brs.devtunnels.ms) empurrava todos os rótulos
   e cada linha alinhava num ponto diferente. As larguras cabem o maior rótulo
   traduzido — "CANAIS META" / "Meta channels" / "Canales Meta". */
#installList .install-row__meta {
  display: grid;
  grid-template-columns: 76px 104px 108px 96px minmax(150px, 232px);
  gap: var(--sp-5);
  flex-wrap: nowrap;
}
/* truncar só aqui: na lista de Domínios a célula tem chips, e cortar esconderia
   informação em vez de organizá-la */
#installList .install-row__col > :last-child {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Abaixo do desktop a grade fixa não cabe: as métricas viram um bloco que
   quebra sozinho, e o cartão passa a empilhar domínio em cima dos dados. */
@media (max-width: 1100px) {
  .install-row { flex-wrap: wrap; }
  #installList .install-row__meta {
    grid-template-columns: repeat(auto-fit, minmax(96px, 1fr));
    gap: var(--sp-4) var(--sp-5);
    width: 100%;
  }
}
@media (max-width: 560px) {
  #installList .install-row__meta { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* ═══ 12. Linha do tempo (Atividade) ══════════════════════════════════════════ */

.timeline { display: flex; flex-direction: column; gap: var(--sp-5); }
.timeline__day { display: flex; flex-direction: column; }
.timeline__day > :first-child {
  padding-bottom: var(--sp-2);
  margin-bottom: var(--sp-1);
  border-bottom: 1px solid var(--hairline);
  font-size: var(--fs-2xs);
  font-weight: var(--fw-semibold);
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--muted-2);
}
.timeline__item {
  display: flex;
  align-items: baseline;
  gap: var(--sp-3);
  flex-wrap: wrap;
  padding: var(--sp-2) 0;
  border-bottom: 1px solid var(--hairline);
  font-size: var(--fs-sm);
  color: var(--text-2);
}
.timeline__item:last-child { border-bottom: none; }
.timeline__dot {
  flex: 0 0 auto;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--muted-3);
  align-self: center;
}
.timeline__dot.is-ok { background: var(--ok); }
.timeline__dot.is-warn { background: var(--warn); }
.timeline__dot.is-danger { background: var(--danger); }
.timeline__dot.is-info { background: var(--info); }
.timeline__item time {
  flex: 0 0 auto;
  min-width: 68px;
  color: var(--muted-2);
  font-size: var(--fs-xs);
  font-variant-numeric: tabular-nums;
}

/* ═══ 13. Chave da licença, pares chave/valor, proveniência ═══════════════════ */

.key-box {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  flex-wrap: wrap;
  padding: var(--sp-1) var(--sp-2);
  background: var(--inset);
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
}
.key-box__label {
  font-size: var(--fs-2xs);
  font-weight: var(--fw-semibold);
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--muted-2);
}
.key-box__value {
  font-family: var(--mono);
  font-size: var(--fs-sm);
  font-weight: var(--fw-medium);
  color: var(--text);
  word-break: break-all;
}

.kv { display: grid; }
.kv-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--sp-4);
  padding: var(--sp-2) 0;
  border-bottom: 1px solid var(--hairline);
}
.kv-row:last-child { border-bottom: none; }
.kv-row .k { font-size: var(--fs-sm); color: var(--muted); }
.kv-row .v {
  font-size: var(--fs-sm);
  font-weight: var(--fw-medium);
  color: var(--text);
  text-align: right;
  word-break: break-word;
}

/* Dizer quando e de onde o dado veio é o gesto corporativo mais barato que existe. */
.provenance {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  margin-top: var(--sp-3);
  font-size: var(--fs-xs);
  color: var(--muted-2);
}
.provenance svg { width: 14px; height: 14px; flex-shrink: 0; }
.provenance:empty { display: none; }

/* ═══ 14. Modal (<dialog> nativo) ═════════════════════════════════════════════ */

.modal {
  /* O reset `* { margin: 0 }` do hub.css zera o `margin: auto` que a folha do
     navegador usa para centralizar o <dialog> modal — sem isto ele cola no canto. */
  margin: auto;
  width: min(440px, calc(100vw - 2 * var(--sp-4)));
  max-width: none;
  padding: 0;
  background: var(--surface);
  color: var(--text);
  border: 1px solid var(--border-strong);
  border-radius: var(--r-xl);
  box-shadow: var(--el-3);
}
.modal--wide { width: min(560px, calc(100vw - 2 * var(--sp-4))); }
/* valor literal: ::backdrop não herda variável em todos os motores */
.modal::backdrop { background: rgba(16, 24, 40, .48); }
:root[data-theme="dark"] .modal::backdrop { background: rgba(2, 4, 8, .66); }

.modal__form { display: flex; flex-direction: column; max-height: min(86vh, 760px); }
.modal__head { display: flex; gap: var(--sp-3); padding: var(--sp-5) var(--sp-5) var(--sp-3); }
.modal__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  flex-shrink: 0;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  color: var(--muted);
}
.modal__icon svg { width: 18px; height: 18px; }
.modal__icon--danger  { background: var(--danger-soft); border-color: var(--danger-border); color: var(--danger-ink); }
.modal__icon--warn    { background: var(--warn-soft);   border-color: var(--warn-border);   color: var(--warn-ink); }
.modal__icon--info    { background: var(--info-soft);   border-color: var(--info-border);   color: var(--info-ink); }
.modal__icon--success { background: var(--ok-soft);     border-color: var(--ok-border);     color: var(--ok-ink); }
.modal__title { font-size: var(--fs-lg); font-weight: var(--fw-semibold); letter-spacing: -.01em; }
.modal__sub { margin-top: 2px; font-size: var(--fs-sm); color: var(--muted); }

.modal__body {
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
  padding: 0 var(--sp-5) var(--sp-4);
  overflow-y: auto;
}
.modal__foot {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: var(--sp-2);
  flex-wrap: wrap;
  padding: var(--sp-3) var(--sp-5) var(--sp-5);
  border-top: 1px solid var(--hairline);
}
/* o modal não fecha ao enviar: o erro aparece dentro dele */
.modal__error {
  flex: 1 1 100%;
  order: -1;
  padding: var(--sp-2) var(--sp-3);
  background: var(--danger-soft);
  border: 1px solid var(--danger-border);
  border-radius: var(--r-sm);
  color: var(--danger-ink);
  font-size: var(--fs-sm);
}
.modal__error[hidden] { display: none; }

/* resumo do que será afetado */
.summary {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--sp-2) var(--sp-4);
  padding: var(--sp-3);
  background: var(--inset);
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  font-size: var(--fs-sm);
}
.summary > div { display: contents; }
.summary dt { color: var(--muted); }
.summary dd {
  text-align: right;
  color: var(--text);
  font-weight: var(--fw-medium);
  overflow-wrap: anywhere;
}
.summary dd.mono { font-family: var(--mono); }

.modal .field { display: flex; flex-direction: column; gap: var(--sp-1); margin: 0; }
.modal .field > label, .modal .field__label {
  display: block;
  margin: 0;
  font-size: var(--fs-sm);
  font-weight: var(--fw-semibold);
  color: var(--text-2);
}
.modal .field input {
  width: 100%;
  height: var(--ctl-h);
  padding: 0 var(--sp-3);
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--r-sm);
  color: var(--text);
  font-family: inherit;
  font-size: var(--fs-sm);
}
.modal .field input.mono { font-family: var(--mono); }
.modal .field input:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--ring); }
.modal .hint { font-size: var(--fs-xs); color: var(--muted); }
.modal .error { font-size: var(--fs-xs); font-weight: var(--fw-medium); color: var(--danger-ink); }
.modal .error[hidden] { display: none; }
.modal .field.is-invalid input { border-color: var(--danger); box-shadow: 0 0 0 3px var(--danger-soft); }

/* grupo de rádio: é assim que o usuário escolhe QUAL domínio sai */
.modal .radio {
  display: flex;
  align-items: flex-start;
  gap: var(--sp-2);
  padding: var(--sp-2);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  cursor: pointer;
}
.modal .radio:hover { background: var(--surface-2); }
.modal .radio input { width: auto; height: auto; margin-top: 3px; accent-color: var(--accent); }
.modal .radio__label { display: block; font-size: var(--fs-sm); font-weight: var(--fw-medium); color: var(--text); }
.modal .radio__hint { display: block; font-size: var(--fs-xs); color: var(--muted); }
.modal .field .radio + .radio { margin-top: var(--sp-1); }

/* ═══ 15. Toast ═══════════════════════════════════════════════════════════════ */
/* Só confirmação de ação bem-sucedida. Sobreposto: não empurra layout.
   Sobrescreve o .toast do hub (fixo, centralizado e com opacity: 0). */

.toast-stack {
  position: fixed;
  right: var(--sp-5);
  bottom: var(--sp-5);
  left: auto;
  z-index: 200;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: var(--sp-2);
  max-width: min(380px, calc(100vw - 2 * var(--sp-4)));
  pointer-events: none;
}
.toast {
  position: static;
  left: auto;
  bottom: auto;
  transform: none;
  opacity: 1;
  pointer-events: auto;
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  max-width: 100%;
  padding: var(--sp-2) var(--sp-2) var(--sp-2) var(--sp-3);
  background: var(--surface);
  color: var(--text);
  border: 1px solid var(--border-strong);
  border-left: 3px solid var(--ok);
  border-radius: var(--r-sm);
  box-shadow: var(--el-3);
  font-size: var(--fs-sm);
  font-weight: var(--fw-medium);
  transition: opacity .16s, transform .16s;
  animation: toast-in .16s ease-out;
}
.toast--success { border-left-color: var(--ok); }
.toast--warn { border-left-color: var(--warn); }
.toast__icon { display: inline-flex; flex-shrink: 0; color: var(--ok); }
.toast--warn .toast__icon { color: var(--warn); }
.toast__icon svg { width: 16px; height: 16px; }
.toast__msg { flex: 1; min-width: 0; }
.toast__action {
  flex-shrink: 0;
  height: 26px;
  padding: 0 var(--sp-2);
  background: var(--surface-2);
  border: 1px solid var(--border-strong);
  border-radius: var(--r-xs);
  color: var(--accent-ink);
  font-family: inherit;
  font-size: var(--fs-xs);
  font-weight: var(--fw-semibold);
}
.toast__action:hover { background: var(--surface-3); }
.toast__close {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  padding: 0;
  background: none;
  border: none;
  border-radius: var(--r-xs);
  color: var(--muted-2);
}
.toast__close:hover { color: var(--text); background: var(--surface-2); }
.toast__close svg { width: 14px; height: 14px; }
.toast.is-leaving { opacity: 0; transform: translateY(6px); }
@keyframes toast-in { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }

/* ═══ 16. Login / verificação ═════════════════════════════════════════════════ */
/* Telas públicas: carregam hub.css + ESTE arquivo, SEM o tokens.css. Este bloco
   usa de propósito só variáveis que existem no hub — trocar por --sp-x, --fs-x
   ou --ctl-h aqui derrubaria o layout do login (variável inexistente invalida a
   declaração inteira). */

.auth-note {
  font-size: .76rem;
  color: var(--muted);
  line-height: 1.5;
  margin-top: 1rem;
  text-align: left;
}
.auth-form { display: grid; gap: .6rem; text-align: left; }
.auth-form label { font-size: .74rem; font-weight: 600; color: var(--text-2); }
.auth-form input {
  width: 100%;
  padding: .65rem .8rem;
  border-radius: var(--r-sm);
  border: 1px solid var(--border-strong);
  background: var(--surface-2);
  color: var(--text);
}
.auth-form input:focus { border-color: var(--signal); }
.otp-input {
  font-family: var(--mono);
  font-size: 1.3rem !important;
  font-weight: 700;
  letter-spacing: .35em;
  text-align: center;
}
.auth-sep {
  display: flex;
  align-items: center;
  gap: .7rem;
  margin: 1.1rem 0 .9rem;
  color: var(--muted-3);
  font-size: .7rem;
  text-transform: uppercase;
  letter-spacing: .1em;
  font-weight: 700;
}
.auth-sep::before, .auth-sep::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--hairline);
}
.login-foot .brand-logo {
  height: 26px;
  margin: 0 auto .6rem;
  display: block;
}

/* Mensagem em caixa — usada pelo login e como fallback de aviso no painel. */
.notice {
  display: flex;
  align-items: flex-start;
  gap: .6rem;
  padding: .8rem .95rem;
  border-radius: var(--r-sm);
  font-size: .82rem;
  border: 1px solid var(--border);
  background: var(--surface-2);
  color: var(--text-2);
  margin-bottom: 1rem;
}
.notice svg { width: 16px; height: 16px; flex-shrink: 0; margin-top: 1px; }
.notice.ok { background: var(--ok-soft); border-color: var(--ok-border); color: var(--ok-ink); }
.notice.warn { background: var(--warn-soft); border-color: var(--warn-border); color: var(--warn-ink); }
.notice.danger { background: var(--danger-soft); border-color: var(--danger-border); color: var(--danger-ink); }
.notice.hidden { display: none; }

.hidden { display: none !important; }

/* ═══ 17. Responsivo — breakpoints unificados: 1200 / 900 / 720 / 560 ═════════ */

@media (max-width: 1200px) {
  .app .topbar { padding: 0 var(--sp-4); }
  .app main { padding: var(--sp-4) var(--sp-4) var(--sp-6); }
  .banner-slot { padding: var(--sp-4) var(--sp-4) 0; }
  .appfoot { padding: 0 var(--sp-4) var(--sp-4); }
}

/* Tablet: a sidebar vira barra superior — mas os rótulos CONTINUAM visíveis
   (o hub os esconde e sobram cinco ícones anônimos). */
@media (max-width: 900px) {
  .app .layout { flex-direction: column; }
  .app .sidebar {
    position: sticky;
    top: 0;
    z-index: 30;
    width: 100%;
    height: auto;
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--sp-2);
    padding: var(--sp-2) var(--sp-4);
    border-right: none;
    border-bottom: 1px solid var(--border);
  }
  .app .side-brand { padding: 0; }
  .app .side-brand__text { display: none; }
  .app .lic-switch { flex: 1 1 200px; max-width: 300px; padding: 0; }
  .app .lic-switch__label, .app .lic-switch__meta { display: none; }
  .app .side-nav {
    flex-direction: row;
    margin-left: auto;
    padding: 0;
    gap: var(--sp-1);
    overflow-x: auto;
  }
  .app .side-nav button { flex-shrink: 0; }
  .app .side-nav button .lbl { display: block; }
  .app .side-nav button .nav-count { display: inline-flex; }
  .app .side-nav button .nav-count[hidden] { display: none; }
  .app .side-nav button.active::before { display: none; }
  .app .side-spacer { display: none; }
  .app .side-account { margin: 0; padding: 0; border-top: none; }
  .app .side-account__email { display: none; }
  /* nada de duas barras grudadas: a topbar rola junto com o conteúdo */
  .app .topbar { position: static; }
  .data-table th { top: 0; }
}

@media (max-width: 720px) {
  .metric-row { grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); }
  .toolbar { flex-direction: column; align-items: stretch; }
  .search { max-width: none; }
  .install-row { flex-direction: column; align-items: stretch; gap: var(--sp-3); }
  .install-row__meta { gap: var(--sp-5); }

  /* A tabela vira lista empilhada. O rótulo vem de data-label (atributo, não
     estilo inline — compatível com a CSP). */
  .data-table--stack table,
  .data-table--stack tbody,
  .data-table--stack tr,
  .data-table--stack td { display: block; width: auto; }
  .data-table--stack thead, .data-table--stack colgroup, .data-table--stack caption { display: none; }
  .data-table--stack table { table-layout: auto; }
  .data-table--stack tr { padding: var(--sp-3); border-bottom: 1px solid var(--hairline); }
  .data-table--stack tbody tr:last-child { border-bottom: none; }
  .data-table--stack tbody tr:hover td { background: transparent; }
  .data-table--stack td {
    height: auto;
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--sp-3);
    padding: 3px 0;
    border-bottom: none;
    white-space: normal;
    overflow: visible;
    text-overflow: clip;
  }
  .data-table--stack td[data-label]::before {
    content: attr(data-label);
    flex: 0 0 auto;
    font-size: var(--fs-2xs);
    font-weight: var(--fw-semibold);
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--muted-2);
  }
  .data-table--stack td.is-actions { justify-content: flex-end; padding-top: var(--sp-2); }
  .data-table--stack td.is-actions::before { content: none; }
  .data-table--stack td.is-text { white-space: normal; overflow-wrap: anywhere; }
}

/* Celular: a navegação vira barra inferior fixa; licença e conta ficam no topo. */
@media (max-width: 560px) {
  .app .sidebar {
    position: static;
    display: grid;
    grid-template-columns: 1fr auto;
    align-items: center;
    gap: var(--sp-2);
    width: 100%;
    height: auto;
    padding: var(--sp-2) var(--sp-3);
    background: var(--surface);
    border: none;
    border-bottom: 1px solid var(--border);
    box-shadow: none;
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
    overflow: visible;
  }
  .app .side-brand { display: flex; padding: 0; grid-column: 1; grid-row: 1; }
  .app .side-brand__text { display: flex; }
  .app .lic-switch { grid-column: 1 / -1; grid-row: 2; max-width: none; }
  .app .side-account { grid-column: 2; grid-row: 1; justify-self: end; }

  .app .side-nav {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    top: auto;
    z-index: 40;
    display: flex;
    flex-direction: row;
    justify-content: space-around;
    align-items: stretch;
    gap: 0;
    margin: 0;
    padding: var(--sp-1) var(--sp-1) calc(var(--sp-1) + env(safe-area-inset-bottom));
    background: var(--surface);
    border-top: 1px solid var(--border);
    box-shadow: var(--el-3);
    overflow: visible;
  }
  .app .side-nav button {
    flex: 1 1 0;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 2px;
    height: auto;
    min-width: 0;
    padding: var(--sp-1) 2px;
  }
  .app .side-nav button svg { width: 20px; height: 20px; }
  .app .side-nav button .lbl {
    display: block;
    flex: 0 0 auto;
    font-size: var(--fs-2xs);
    text-align: center;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 100%;
  }
  .app .side-nav button .nav-count {
    position: absolute;
    top: 0;
    left: 50%;
    margin-left: 4px;
    height: 16px;
    min-width: 16px;
  }
  .app .content { padding-bottom: 0; }

  .app .topbar {
    height: auto;
    min-height: 0;
    flex-direction: column;
    align-items: stretch;
    gap: var(--sp-2);
    padding: var(--sp-3);
  }
  .app .topbar .left { flex-direction: column; align-items: flex-start; gap: 0; }
  .app .page-title { white-space: normal; }
  .page-context { white-space: normal; }
  .app .topbar .right { justify-content: flex-start; flex-wrap: wrap; gap: var(--sp-2); }
  .app main { padding: var(--sp-4) var(--sp-3) var(--sp-5); }
  .app .card { padding: var(--sp-4); }
  .app .card-head { flex-direction: column; }
  .banner-slot { padding: var(--sp-3) var(--sp-3) 0; }

  /* não ficar sob a barra de navegação inferior */
  .appfoot {
    padding: 0 var(--sp-3) calc(var(--sp-4) + 58px + env(safe-area-inset-bottom));
    gap: var(--sp-1) var(--sp-2);
  }

  /* modal vira folha inferior */
  .modal, .modal--wide {
    width: 100%;
    max-width: 100%;
    margin: auto auto 0;
    border-radius: var(--r-xl) var(--r-xl) 0 0;
    border-bottom: none;
  }
  .modal__form { max-height: 88vh; }
  .modal__head { padding: var(--sp-4) var(--sp-4) var(--sp-3); }
  .modal__body { padding: 0 var(--sp-4) var(--sp-4); }
  .modal__foot {
    flex-direction: column-reverse;
    align-items: stretch;
    padding: var(--sp-3) var(--sp-4) calc(var(--sp-4) + env(safe-area-inset-bottom));
  }
  .modal__foot .btn { width: 100%; }

  /* toast: inferior centralizado, acima da barra de navegação */
  .toast-stack {
    left: var(--sp-3);
    right: var(--sp-3);
    bottom: calc(58px + var(--sp-3) + env(safe-area-inset-bottom));
    align-items: stretch;
    max-width: none;
  }

  /* 16px evita o zoom automático do iOS ao focar um campo */
  .search__input, .lic-switch__select, .modal .field input { font-size: 16px; }
}


/* ═══════════════════════════════════════════════════════════════════════════
   INTEGRAÇÃO — componentes emitidos pelo painel.js que ficaram fora do
   contrato de classes combinado entre os agentes. Escrito na consolidação.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── Cabeçalho ordenável ──────────────────────────────────────────────────
   O th vira um botão de largura total: alvo de clique inteiro, foco visível e
   a seta indicando a direção. Sem isto o cabeçalho fica com cara de link cru. */
.data-table th:has(.th-sort) { padding: 0; }

.th-sort {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  width: 100%;
  height: 36px;
  padding: 0 var(--sp-3);
  background: none;
  border: 0;
  font: inherit;
  font-size: var(--fs-2xs);
  font-weight: var(--fw-semibold);
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--muted-2);
  text-align: left;
  cursor: pointer;
  transition: color .12s ease, background .12s ease;
}
.th-sort:hover { color: var(--text-2); background: var(--surface-3); }
.th-sort svg { width: 12px; height: 12px; flex-shrink: 0; opacity: .9; }
.data-table th[aria-sort="ascending"] .th-sort,
.data-table th[aria-sort="descending"] .th-sort { color: var(--text); }
.data-table th.is-actions { text-align: right; }

/* ── Rodapé da tabela: contagem + paginação ───────────────────────────────── */
.data-table__bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  flex-wrap: wrap;
  padding: var(--sp-2) var(--sp-3);
  border-top: 1px solid var(--border);
  background: var(--surface-2);
}
.data-table__count { font-size: var(--fs-xs); color: var(--muted); }
.data-table__count b { font-weight: var(--fw-semibold); color: var(--text-2); }
.data-table__count .is-danger { color: var(--danger-ink); font-weight: var(--fw-semibold); }

.data-table__pager { display: flex; align-items: center; gap: var(--sp-1); }
.data-table__page {
  min-width: 28px; height: 28px;
  display: inline-flex; align-items: center; justify-content: center;
  padding: 0 8px;
  font-size: var(--fs-xs); font-weight: var(--fw-medium);
  color: var(--text-2);
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--r-sm);
  cursor: pointer;
}
.data-table__page:hover:not(:disabled) { background: var(--surface-2); border-color: var(--muted-2); }
.data-table__page:disabled { opacity: .45; cursor: not-allowed; }
.data-table__page[aria-current="true"] {
  background: var(--accent-soft);
  border-color: var(--accent-border);
  color: var(--accent-ink);
}
.data-table__page svg { width: 14px; height: 14px; }

/* linha de estado (vazio/erro/carregando) ocupa a tabela inteira, sem hover */
.data-table tbody tr.is-empty:hover td { background: transparent; }
.data-table tr.is-empty td { padding: 0; }

/* ── Célula de ações e grupo de chips ─────────────────────────────────────── */
.cell-actions { display: flex; align-items: center; justify-content: flex-end; gap: var(--sp-1); }
.chip-row { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }

/* ── Barra de seção (ex.: "Domínios · 2 de 3 slots") ──────────────────────── */
.sec-bar__label { font-size: var(--fs-xs); color: var(--muted); }
.sec-bar__label b { font-weight: var(--fw-semibold); color: var(--text-2); }

/* ── Timeline da Atividade ────────────────────────────────────────────────── */
.timeline__title { font-size: var(--fs-sm); font-weight: var(--fw-medium); color: var(--text); }
.timeline__meta  { font-size: var(--fs-xs); color: var(--muted); }
.timeline__meta .mono { color: var(--text-2); }

/* ── Medidor das métricas ─────────────────────────────────────────────────
   A CSP proíbe style inline, então o preenchimento não pode vir de
   `style="width:x%"`. O painel.js emite [data-fill="0..100"] e a largura sai
   das regras geradas abaixo — é verboso, mas é o único caminho sem inline. */
.metric-meter { height: 4px; border-radius: var(--pill); background: var(--surface-3); overflow: hidden; }
.metric-meter > i { display: block; height: 100%; width: 0; background: var(--ok); transition: width .2s ease; }
.metric.is-warn   .metric-meter > i { background: var(--warn); }
.metric.is-danger .metric-meter > i { background: var(--danger); }

.metric-meter[data-fill="0"] > i{width:0%}.metric-meter[data-fill="1"] > i{width:1%}.metric-meter[data-fill="2"] > i{width:2%}.metric-meter[data-fill="3"] > i{width:3%}.metric-meter[data-fill="4"] > i{width:4%}.metric-meter[data-fill="5"] > i{width:5%}.metric-meter[data-fill="6"] > i{width:6%}.metric-meter[data-fill="7"] > i{width:7%}.metric-meter[data-fill="8"] > i{width:8%}.metric-meter[data-fill="9"] > i{width:9%}
.metric-meter[data-fill="10"] > i{width:10%}.metric-meter[data-fill="11"] > i{width:11%}.metric-meter[data-fill="12"] > i{width:12%}.metric-meter[data-fill="13"] > i{width:13%}.metric-meter[data-fill="14"] > i{width:14%}.metric-meter[data-fill="15"] > i{width:15%}.metric-meter[data-fill="16"] > i{width:16%}.metric-meter[data-fill="17"] > i{width:17%}.metric-meter[data-fill="18"] > i{width:18%}.metric-meter[data-fill="19"] > i{width:19%}
.metric-meter[data-fill="20"] > i{width:20%}.metric-meter[data-fill="21"] > i{width:21%}.metric-meter[data-fill="22"] > i{width:22%}.metric-meter[data-fill="23"] > i{width:23%}.metric-meter[data-fill="24"] > i{width:24%}.metric-meter[data-fill="25"] > i{width:25%}.metric-meter[data-fill="26"] > i{width:26%}.metric-meter[data-fill="27"] > i{width:27%}.metric-meter[data-fill="28"] > i{width:28%}.metric-meter[data-fill="29"] > i{width:29%}
.metric-meter[data-fill="30"] > i{width:30%}.metric-meter[data-fill="31"] > i{width:31%}.metric-meter[data-fill="32"] > i{width:32%}.metric-meter[data-fill="33"] > i{width:33%}.metric-meter[data-fill="34"] > i{width:34%}.metric-meter[data-fill="35"] > i{width:35%}.metric-meter[data-fill="36"] > i{width:36%}.metric-meter[data-fill="37"] > i{width:37%}.metric-meter[data-fill="38"] > i{width:38%}.metric-meter[data-fill="39"] > i{width:39%}
.metric-meter[data-fill="40"] > i{width:40%}.metric-meter[data-fill="41"] > i{width:41%}.metric-meter[data-fill="42"] > i{width:42%}.metric-meter[data-fill="43"] > i{width:43%}.metric-meter[data-fill="44"] > i{width:44%}.metric-meter[data-fill="45"] > i{width:45%}.metric-meter[data-fill="46"] > i{width:46%}.metric-meter[data-fill="47"] > i{width:47%}.metric-meter[data-fill="48"] > i{width:48%}.metric-meter[data-fill="49"] > i{width:49%}
.metric-meter[data-fill="50"] > i{width:50%}.metric-meter[data-fill="51"] > i{width:51%}.metric-meter[data-fill="52"] > i{width:52%}.metric-meter[data-fill="53"] > i{width:53%}.metric-meter[data-fill="54"] > i{width:54%}.metric-meter[data-fill="55"] > i{width:55%}.metric-meter[data-fill="56"] > i{width:56%}.metric-meter[data-fill="57"] > i{width:57%}.metric-meter[data-fill="58"] > i{width:58%}.metric-meter[data-fill="59"] > i{width:59%}
.metric-meter[data-fill="60"] > i{width:60%}.metric-meter[data-fill="61"] > i{width:61%}.metric-meter[data-fill="62"] > i{width:62%}.metric-meter[data-fill="63"] > i{width:63%}.metric-meter[data-fill="64"] > i{width:64%}.metric-meter[data-fill="65"] > i{width:65%}.metric-meter[data-fill="66"] > i{width:66%}.metric-meter[data-fill="67"] > i{width:67%}.metric-meter[data-fill="68"] > i{width:68%}.metric-meter[data-fill="69"] > i{width:69%}
.metric-meter[data-fill="70"] > i{width:70%}.metric-meter[data-fill="71"] > i{width:71%}.metric-meter[data-fill="72"] > i{width:72%}.metric-meter[data-fill="73"] > i{width:73%}.metric-meter[data-fill="74"] > i{width:74%}.metric-meter[data-fill="75"] > i{width:75%}.metric-meter[data-fill="76"] > i{width:76%}.metric-meter[data-fill="77"] > i{width:77%}.metric-meter[data-fill="78"] > i{width:78%}.metric-meter[data-fill="79"] > i{width:79%}
.metric-meter[data-fill="80"] > i{width:80%}.metric-meter[data-fill="81"] > i{width:81%}.metric-meter[data-fill="82"] > i{width:82%}.metric-meter[data-fill="83"] > i{width:83%}.metric-meter[data-fill="84"] > i{width:84%}.metric-meter[data-fill="85"] > i{width:85%}.metric-meter[data-fill="86"] > i{width:86%}.metric-meter[data-fill="87"] > i{width:87%}.metric-meter[data-fill="88"] > i{width:88%}.metric-meter[data-fill="89"] > i{width:89%}
.metric-meter[data-fill="90"] > i{width:90%}.metric-meter[data-fill="91"] > i{width:91%}.metric-meter[data-fill="92"] > i{width:92%}.metric-meter[data-fill="93"] > i{width:93%}.metric-meter[data-fill="94"] > i{width:94%}.metric-meter[data-fill="95"] > i{width:95%}.metric-meter[data-fill="96"] > i{width:96%}.metric-meter[data-fill="97"] > i{width:97%}.metric-meter[data-fill="98"] > i{width:98%}.metric-meter[data-fill="99"] > i{width:99%}
.metric-meter[data-fill="100"] > i{width:100%}

/* ── Utilitários usados pelo painel.js ────────────────────────────────────── */
.muted { color: var(--muted); }

/* ── Linha legal do rodapé do app ─────────────────────────────────────────── */
.appfoot__legal { color: var(--muted-2); }
.appfoot__legal .mono { font-size: var(--fs-xs); }


/* ═══════════════════════════════════════════════════════════════════════════
   SELETOR DE IDIOMA (i18n · fase I3)

   Montado pelo /js/lang-switch.js nas três páginas: na topbar do painel
   ([data-lang-slot]) e, nas telas públicas, no canto superior direito da
   .login-wrap (modificador --corner). Só tokens já existentes; nenhuma cor
   nova. Sem <style> e sem style="" — a CSP é style-src 'self'.
   ═══════════════════════════════════════════════════════════════════════════ */

.langsel { position: relative; display: inline-flex; }

/* telas públicas: canto discreto, fora do fluxo que centraliza o cartão
   (.login-wrap já é position: relative no hub.css) */
.langsel--corner {
  position: absolute;
  top: var(--sp-4);
  right: var(--sp-4);
  z-index: 3;                     /* .login-card é z-index 1 */
}

.langsel__btn {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-1);
  height: var(--ctl-h-sm);
  padding: 0 var(--sp-2);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  color: var(--muted);
  font-family: inherit;
  font-size: var(--fs-xs);
  font-weight: var(--fw-semibold);
}
.langsel__btn:hover { color: var(--text); border-color: var(--border-strong); }
.langsel__btn[aria-expanded="true"] {
  background: var(--surface-2);
  border-color: var(--border-strong);
  color: var(--text);
}
.langsel__cur { white-space: nowrap; }
.langsel__ico { width: 15px; height: 15px; flex: none; }
.langsel__chev {
  width: 13px;
  height: 13px;
  flex: none;
  color: var(--muted-2);
  transition: transform .15s ease;
}
.langsel__btn[aria-expanded="true"] .langsel__chev { transform: rotate(180deg); }

.langsel__menu {
  position: absolute;
  top: calc(100% + var(--sp-1));
  right: 0;
  z-index: 40;                    /* .topbar é z-index 30 */
  display: grid;
  gap: 2px;
  min-width: 172px;
  padding: var(--sp-1);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r);
  box-shadow: var(--el-3);
}
/* display: grid venceria o atributo hidden — sem esta linha o menu nasce aberto */
.langsel__menu[hidden] { display: none; }

.langsel__opt {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-4);
  width: 100%;
  height: var(--ctl-h);
  padding: 0 var(--sp-2);
  background: none;
  border: 0;
  border-radius: var(--r-sm);
  color: var(--text-2);
  font-family: inherit;
  font-size: var(--fs-sm);
  font-weight: var(--fw-medium);
  text-align: left;
}
.langsel__opt:hover { background: var(--surface-3); color: var(--text); }
.langsel__opt:focus-visible { background: var(--surface-3); }
.langsel__opt[aria-checked="true"] {
  color: var(--accent-ink);
  font-weight: var(--fw-semibold);
}
/* a marca ocupa o lugar mesmo apagada: sem isso o rótulo dança ao trocar idioma */
.langsel__check {
  width: 15px;
  height: 15px;
  flex: none;
  color: var(--accent-ink);
  opacity: 0;
}
.langsel__opt[aria-checked="true"] .langsel__check { opacity: 1; }

@media (max-width: 560px) {
  .langsel--corner { top: var(--sp-3); right: var(--sp-3); }
  /* na topbar empilhada o seletor abre para a esquerda do próprio botão */
  .app .langsel__menu { left: 0; right: auto; }
}

@media (prefers-reduced-motion: reduce) {
  .langsel__chev { transition: none; }
}

/* ═══ 21. Renovação dentro do painel ══════════════════════════════════════════
   Card na Visão geral com as ofertas do plano da licença. O catálogo vem do
   servidor (src/plans.ts); aqui só o layout. */

.renewal-plan { text-align: right; display: flex; flex-direction: column; gap: 2px; }
.renewal-plan__label {
  font-size: var(--fs-2xs);
  font-weight: var(--fw-semibold);
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--muted-2);
}
.renewal-plan__value { font-size: var(--fs-sm); font-weight: var(--fw-semibold); color: var(--text); }

.renewal-offers {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: var(--sp-4);
  padding: var(--sp-5);
}

.renewal-offer {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  padding: var(--sp-5);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  background: var(--surface-2);
}
/* a troca de plano é alternativa, não o caminho principal: fica visualmente
   secundária para não competir com a renovação do plano atual */
.renewal-offer--alt { background: transparent; border-style: dashed; }

.renewal-offer__kind {
  font-size: var(--fs-2xs);
  font-weight: var(--fw-semibold);
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--muted-2);
}
.renewal-offer__plan { font-size: var(--fs-md); font-weight: var(--fw-semibold); color: var(--text); }
.renewal-offer__price {
  font-size: var(--fs-2xl);
  font-weight: var(--fw-bold);
  color: var(--text);
  font-variant-numeric: tabular-nums;
  line-height: 1.1;
}
.renewal-offer__cta { margin-top: var(--sp-2); justify-content: center; }
.renewal-offer--alt .renewal-offer__cta {
  background: transparent;
  color: var(--accent-ink);
  border: 1px solid var(--accent-border);
}

.renewal-note {
  font-size: var(--fs-xs);
  color: var(--muted);
  line-height: 1.5;
  margin: 0 0 var(--sp-2);
}
.renewal-note:last-child { margin-bottom: 0; }

@media (max-width: 560px) {
  .renewal-offers { grid-template-columns: 1fr; padding: var(--sp-4); gap: var(--sp-3); }
  .renewal-plan { text-align: left; }
}
