/* ui/static/mailhub.css — o que é DO PAINEL. ADMIN-ANALYTICS §9.3, §9.7, §10.
 *
 * Ordem de carga (§9.1):
 *   1. vendor/braz-ui/tokens.css      gerado por brand_root_css()
 *   2. vendor/braz-ui/fonts.css       @font-face auto-hospedado
 *   3. vendor/braz-ui/braz-ui.css     componentes .bz-*
 *   4. vendor/braz-ui/admin-nav.css   navegação .gnav-*
 *   5. patch/braz-ui-light.css        as correções de contraste (§9.4)
 *   6. static/mailhub.css             ESTE arquivo
 *
 * TRÊS REGRAS DURAS, verificadas por teste e não por revisão
 * (`tests/unit/test_brand_vendor.py`):
 *   1. ZERO HEX CRU fora de comentário. Toda cor é `var(--token)` ou
 *      `rgba(var(--…-rgb), α)`. É isto que faz DD-7 ser verdade: trocar
 *      `tokens.css` e o logo reveste a interface inteira.
 *   2. `--text-3` NÃO APARECE NESTE ARQUIVO. 3,52:1 no claro reprova AA para
 *      texto normal, e o §9.2 o proíbe em qualquer dado. Em vez de arbitrar
 *      caso a caso, ele simplesmente não existe aqui.
 *   3. Nenhum `height` fixo em linha, cartão ou KPI (SC 1.4.4 / 1.4.12: a tela
 *      tem de sobreviver a 200% de zoom e ao espaçamento de texto).
 *
 * Prefixo `mh-` em tudo. Componente `bz-` que precise mudar muda PRIMEIRO na
 * plataforma (§9.1, política de divergência de uma direção só) — as poucas
 * exceções abaixo estão marcadas com o motivo e a cláusula que as obriga.
 */

/* As fontes auto-hospedadas vêm por `<link>`, não por `@import`.
 *
 * O `fonts.css` é GERADO pelo sync (ele é quem sabe o nome exato de cada arquivo
 * em `fonts/`) e mora em `vendor/braz-ui/`, que o `paneld` serve na mesma raiz
 * `/estatico/`. A ordem de folhas do `paneld` (`panel/app.py::_stylesheets`) o
 * carrega logo depois de `tokens.css`: um `<link>` paralelo começa a baixar a
 * fonte bem antes de um `@import` serializado dentro deste arquivo.
 *
 * O `@import` que existia aqui desde a Leva 2a foi REMOVIDO na Leva 3, quando o
 * `<link>` já estava no ar. Os dois juntos não baixavam duas vezes (mesma URL),
 * mas mantinham dois caminhos para a mesma coisa. `test_brand_vendor.py` afirma
 * que pelo menos um existe — cair no `system-ui` é a falha mais silenciosa
 * possível numa identidade, então ela tem teste. */

/* ========================================================================= *
 * 0. Tokens do painel — geometria e tipografia. NENHUMA COR NOVA.
 * ========================================================================= */
:root {
  --mh-max: 1150px;                 /* §9.7 */
  --mh-gutter: 16px;                /* §9.7: gutter no celular */
  --mh-radius: 16px;
  --mh-radius-sm: 10px;
  --mh-radius-kpi: 14px;            /* o raio do KPI no mockup aprovado */
  --mh-pill: 999px;
  --mh-gap: 14px;
  --mh-head-offset: 96px;           /* §10 SC 2.4.11: cabeçalho fixo */
  --mh-hair: 1px solid var(--border-soft);
  --mh-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  --mh-label-font: var(--brand-font-detail);
  --mh-tap: 24px;                   /* §10 SC 2.5.8: alvo mínimo */
}

/* O gutter de 16 px é a medida do CELULAR (§9.7). No mockup aprovado a casca
 * respira 28 px assim que a tela passa de 760 px, e a diferença é visível: com
 * 16 px o conteúdo encosta na moldura do navegador e o painel parece uma página
 * de administração genérica. Medido lado a lado com
 * `docs/mockup/painel-aprovado.html` no QA visual. */
@media (min-width: 761px) {
  :root { --mh-gutter: 28px; }
}

/* ========================================================================= *
 * 1. Casca da página
 * ========================================================================= */
/* `border-box` global. A plataforma nunca precisou disto porque o reset dela vem
 * do `<head>` de cada página; o `braz-ui.css` só o declara num componente
 * (`braz-ui.css:351`). Sem esta regra, `.mh-field input` com `width:100%` mais
 * 28 px de padding fica 28 px mais largo que o container e o DOCUMENTO ganha
 * rolagem horizontal — medido em 390 px e em 320 px, e é exatamente o que o
 * SC 1.4.10 proíbe. Foi o navegador que achou; nenhuma leitura de CSS acharia. */
*, *::before, *::after { box-sizing: border-box; }

html {
  color-scheme: light;
  /* SC 2.4.11 — o cabeçalho é fixo; sem isto o `Tab` leva o foco para baixo
     dele na última linha de uma tabela longa. */
  scroll-padding-top: var(--mh-head-offset);
}
html[data-theme="dark"] { color-scheme: dark; }

body {
  margin: 0;
  background: var(--surface-base);
  color: var(--text-1);
  font-family: var(--brand-font-body);
  font-size: 0.95rem;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

h1, h2, h3, h4 {
  font-family: var(--brand-font-display);
  font-weight: 400;
  color: var(--text-strong);
  margin: 0;
  text-wrap: balance;
}
h1 { font-size: 1.7rem; line-height: 1.15; }
h2 { font-size: 1.25rem; line-height: 1.2; }
h3 { font-size: 1.12rem; line-height: 1.25; }
p { margin: 0; }
a { color: var(--accent-ink); }

/* Link de pular blocos: PRIMEIRO foco da página (§10 SC 2.4.1). Fora da tela
   até receber foco — nunca `display:none`, que o tiraria da ordem de tabulação. */
.mh-skip {
  position: absolute;
  left: var(--mh-gutter);
  top: 0;
  z-index: 60;
  transform: translateY(-140%);
  padding: 10px 16px;
  border-radius: 0 0 var(--mh-radius-sm) var(--mh-radius-sm);
  background: var(--surface-2);
  color: var(--accent-ink);
  border: var(--mh-hair);
  border-top: 0;
  text-decoration: none;
  font-family: var(--mh-label-font);
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}
.mh-skip:focus-visible { transform: translateY(0); }

/* Texto só para leitor de tela (legenda de tabela, rótulo de região). */
.mh-sr {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.mh-topbar {
  position: sticky;
  top: 0;
  z-index: 40;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 12px var(--mh-gutter);
  background: var(--surface-2);
  border-bottom: var(--mh-hair);
  /* Rede de segurança: se o conteúdo não couber, ele QUEBRA em duas linhas em
     vez de se sobrepor. Sem isto, `white-space: nowrap` no «Mail Hub» impedia o
     bloco do logo de encolher e ele passava por cima da sessão — visto em 390 px
     no navegador, não no CSS. */
  flex-wrap: wrap;
}
.mh-logo { display: inline-flex; align-items: center; gap: 10px; min-width: 0; flex-shrink: 1; }
/* O arquivo vendorizado já é a variante PETRÓLEO (para fundo claro): nenhum
   `filter` aqui — filtro de cor é exatamente o que quebra ao trocar de marca. */
.mh-logo img { height: 26px; width: auto; display: block; }
.mh-logo span {
  font-family: var(--mh-label-font);
  font-size: 0.66rem;
  font-weight: 600;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--text-2);
  white-space: nowrap;
  /* O filete entre a marca e o nome do produto, como no mockup aprovado: é ele
     que diz «BRAZ SCHOOL» e «Mail Hub» são duas coisas, e não um nome só. */
  padding-left: 12px;
  border-left: var(--mh-hair);
}
.mh-who {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-size: 0.78rem;
  color: var(--text-2);
  min-width: 0;
}
.mh-who-dot {
  display: grid;
  place-items: center;
  min-width: 28px;
  padding: 4px;
  aspect-ratio: 1;
  border-radius: var(--mh-pill);
  background: rgba(var(--brand-accent-rgb), 0.14);
  color: var(--accent-ink);
  font-family: var(--mh-label-font);
  font-size: 0.62rem;
  font-weight: 600;
  letter-spacing: 0.06em;
}

.mh-main {
  max-width: var(--mh-max);
  margin: 0 auto;
  padding: 18px var(--mh-gutter) 34px;
}

.mh-foot {
  margin-top: 26px;
  padding-top: 14px;
  border-top: var(--mh-hair);
  font-size: 0.78rem;
  color: var(--text-2);
}

/* No celular o «Mail Hub» ao lado do logo é redundante — o endereço na barra do
   navegador já diz onde você está — e é o que empurra a sessão para fora. O
   mockup aprovado faz o mesmo abaixo de 760 px. O RÓTULO DA SESSÃO fica: é ele
   que diz se você está numa sessão de leitura ou de operação (§3.3). */
@media (max-width: 560px) {
  .mh-logo span { display: none; }
}

/* §9.3 — o painel não tem sino. A barra da plataforma encurta a pista no
   celular para não passar por baixo do sino global (`admin-nav.css:70-75`);
   aqui isso só desperdiçaria 44 px de largura. */
@media (max-width: 768px) {
  .gnav { margin-right: 0; }
}
/* A barra do vendor rola na horizontal; no painel ela é a navegação principal,
   então ganha rótulo de região e foco próprio (SC 1.4.10). */
.gnav { scroll-padding-inline: var(--mh-gutter); }

/* ========================================================================= *
 * 2. Cabeçalho de tela e ferramentas (SC 3.2.6: mesmo canto em toda tela)
 * ========================================================================= */
.mh-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 14px;
  flex-wrap: wrap;
  margin-bottom: 18px;
}
/* O título da tela cresce com a largura, como no mockup aprovado. Sem o `clamp`
 * ele ficava em 1,7 rem no desktop — MENOR que o veredito da tela `Hoje`, e uma
 * hierarquia invertida é a primeira coisa que o olho percebe sem saber nomear. */
.mh-head h1 { margin-top: 6px; font-size: clamp(1.7rem, 3vw, 2.3rem); line-height: 1.1; }
.mh-tools { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }

.mh-tbtn {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  min-height: 32px;
  padding: 7px 12px;
  border-radius: var(--mh-pill);
  border: var(--mh-hair);
  background: var(--surface-2);
  color: var(--text-1);
  font: inherit;
  font-size: 0.78rem;
  cursor: pointer;
  /* Metade das ferramentas é `<a>` (navegação) e metade é `<button>` (ação): sem
     esta linha as duas metades ficavam com cara diferente na MESMA fileira, o
     sublinhado do link cortando a pílula. A distinção de link continua feita pela
     forma (pílula com contorno) e pelo foco — o sublinhado é para link dentro de
     frase, não para botão de barra de ferramentas. */
  text-decoration: none;
}
.mh-tbtn:hover { color: var(--accent-ink); border-color: rgba(var(--brand-accent-rgb), 0.45); }
.mh-tbtn svg { width: 14px; height: 14px; flex: 0 0 auto; }

/* Chips de período: BOTÕES, e o caminho único — nada de seleção por arrasto
   (§10 SC 2.5.7). `aria-pressed` carrega o estado; a cor não é o único sinal. */
.mh-periods {
  display: inline-flex;
  /* `wrap`, e não `nowrap`: a 200% de zoom com o espaçamento de texto do
     SC 1.4.12, os cinco filtros da tela Registro somam 629 px numa pista de
     606 px e empurravam o DOCUMENTO para 646 px — rolagem horizontal, que é o
     SC 1.4.10 reprovado. Medido no Chromium, não estimado: é o defeito que a
     suíte de zoom da Leva 3 achou na primeira execução. Envolver custa uma
     segunda linha de pílulas; rolar horizontalmente custa a norma. */
  flex-wrap: wrap;
  gap: 4px;
  padding: 4px;
  border-radius: var(--mh-pill);
  border: var(--mh-hair);
  background: var(--surface-2);
  max-width: 100%;
}
.mh-periods button {
  min-width: var(--mh-tap);
  min-height: var(--mh-tap);
  padding: 5px 11px;
  border: 0;
  border-radius: var(--mh-pill);
  background: transparent;
  color: var(--text-2);
  font: inherit;
  font-size: 0.78rem;
  cursor: pointer;
}
.mh-periods button[aria-pressed="true"] {
  background: rgba(var(--brand-accent-rgb), 0.14);
  color: var(--accent-ink);
  box-shadow: inset 0 0 0 1px var(--accent-ink);
  font-weight: 500;
}

/* Eyebrow: o `.bz-eyebrow` do vendor é 0,72 rem / peso 400. O §9.5 fixa o
   rótulo do painel em Clash 600 / 0,64 rem / ls .24em — mesma família, densidade
   de painel. Modificador, não reescrita. */
.mh-eyebrow {
  font-family: var(--mh-label-font);
  font-size: 0.64rem;
  font-weight: 600;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--accent-ink);
}
.mh-label {
  font-family: var(--mh-label-font);
  font-size: 0.64rem;
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--text-2);
}
.mh-meta { font-size: 0.8rem; color: var(--text-2); }

/* ========================================================================= *
 * 3. Grade
 * ========================================================================= */
.mh-stack { display: flex; flex-direction: column; gap: var(--mh-gap); min-width: 0; }
.mh-grid { display: grid; gap: var(--mh-gap); }
.mh-grid--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.mh-grid--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
/* `auto-fit`, e não `repeat(4, …)`: a tela `Fila` tem CINCO KPIs, e com quatro
 * trilhos fixos o quinto caía sozinho numa segunda fileira com três quartos de
 * vazio ao lado. Com trilho mínimo de 200 px, quatro continuam quatro (1150/4 =
 * 287) e cinco também cabem na mesma linha. */
.mh-grid--4 { grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); }
/* `align-items: start`: sem isto o cartão do gráfico estica até a altura da
   coluna vizinha e deixa um vazio de 200 px embaixo da figura — visto num
   screenshot de 1280 px. Altura vem do conteúdo, nunca do vizinho. */
.mh-grid--main { grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr); align-items: start; }

@media (max-width: 900px) {
  .mh-grid--3, .mh-grid--main { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 640px) {
  .mh-grid--2, .mh-grid--4 { grid-template-columns: minmax(0, 1fr); }
}

/* Duas colunas para uma pilha de cartões de alturas muito diferentes (a tela
 * Saúde: cinco grupos, de 2 a 11 itens cada). Antes disto ela tinha 4 900 px de
 * altura em 1280 px com a metade direita vazia, e o mockup aprovado a desenha em
 * duas colunas.
 *
 * É GRADE de duas colunas com a distribuição feita no template, e **não**
 * `column-count`. Tentei `column-count: 2` primeiro, e ele mediu mal: com
 * `break-inside: avoid` e um cartão de 2 900 px no meio, o Chromium fechou a
 * primeira coluna cedo e deixou 1 000 px de vazio embaixo dela. Quem sabe
 * equilibrar aqui é quem conhece o PESO de cada grupo — o número de itens —, e
 * isso o template sabe antes de renderizar. `align-items: start` impede que uma
 * coluna curta estique até a altura da outra. */
.mh-cols {
  display: grid;
  gap: var(--mh-gap);
  grid-template-columns: minmax(0, 1fr);
  align-items: start;
}
@media (min-width: 1000px) {
  .mh-cols { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* ========================================================================= *
 * 4. Veredito — a resposta de 10 segundos (§6.1). UMA frase, nunca duas.
 * ========================================================================= */
.mh-verdict {
  display: flex;
  align-items: flex-start;
  gap: 14px;
  padding: 18px 20px;
  border-radius: var(--mh-radius);
  background: var(--surface-2);
  border: var(--mh-hair);
  border-left: 3px solid var(--text-2);
}
/* O teto é 2,1 rem, e não 2,4: o veredito é a frase mais importante da tela, mas
 * não é o título dela. Com 2,4 rem ele passava o `<h1>` e a página perdia o topo
 * da hierarquia — medido contra o mockup aprovado no QA visual. */
.mh-verdict h2 {
  font-size: clamp(1.5rem, 1.2rem + 1.2vw, 2.1rem);
  line-height: 1.15;
  text-wrap: balance;
}
.mh-verdict p { color: var(--text-2); margin-top: 6px; font-size: 0.92rem; }
.mh-verdict-icon {
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  margin-top: 4px;
  border-radius: var(--mh-pill);
  background: rgba(var(--ink-rgb), 0.06);
  color: var(--text-2);
}
.mh-verdict-icon svg { width: 18px; height: 18px; }

.mh-verdict--ok { border-left-color: var(--status-excellent-ink); }
.mh-verdict--ok .mh-verdict-icon {
  background: rgba(var(--status-excellent-rgb), 0.12);
  color: var(--status-excellent-ink);
}
.mh-verdict--att { border-left-color: var(--status-attention-ink); }
.mh-verdict--att .mh-verdict-icon {
  background: rgba(var(--status-attention-rgb), 0.12);
  color: var(--status-attention-ink);
}
.mh-verdict--crit { border-left-color: var(--status-critical-ink); }
.mh-verdict--crit .mh-verdict-icon {
  background: rgba(var(--status-critical-rgb), 0.12);
  color: var(--status-critical-ink);
}

/* Cartão de ação (dentro de `.bz-card`): chip, título, uma frase, um caminho. */
.mh-act { display: flex; flex-direction: column; gap: 8px; }
.mh-act p { font-size: 0.9rem; color: var(--text-2); }
.mh-act > .mh-chip { align-self: flex-start; }
.mh-act-go { margin-top: 8px; }

/* ========================================================================= *
 * 5. `.mh-kpi` — modelado em `.exe-kpi` (admin_executive.css). Número em serif:
 *    é a assinatura da marca no painel (§9.5).
 * ========================================================================= */
.mh-kpi {
  background: var(--surface-2);
  border: var(--mh-hair);
  border-radius: var(--mh-radius-kpi);
  padding: 14px 16px;
  min-width: 0;
}
.mh-kpi-label {
  font-family: var(--mh-label-font);
  font-size: 0.62rem;
  font-weight: 600;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--text-2);
}
.mh-kpi-value {
  font-family: var(--brand-font-display);
  font-size: 2rem;
  line-height: 1.05;
  color: var(--text-strong);
  margin-top: 6px;
  font-variant-numeric: tabular-nums;
}
.mh-kpi-value small {
  font-family: var(--brand-font-body);
  font-size: 0.8rem;
  color: var(--text-2);
  margin-left: 4px;
}
/* A comparação traz SEMPRE a palavra («subiu», «caiu»), nunca só seta ou cor
   (§7.3 e SC 1.4.1). O menor tamanho permitido em dado é 0,78 rem (§9.5). */
.mh-kpi-delta {
  margin-top: 6px;
  font-size: 0.78rem;
  color: var(--text-2);
  display: flex;
  align-items: center;
  gap: 5px;
  flex-wrap: wrap;
}
.mh-kpi--good { border-top: 3px solid var(--status-excellent-ink); }
.mh-kpi--warn { border-top: 3px solid var(--status-attention-ink); }
.mh-kpi--crit { border-top: 3px solid var(--status-critical-ink); }
.mh-kpi--gold { border-color: rgba(var(--brand-accent-rgb), 0.4); }

/* ========================================================================= *
 * 6. `.mh-chip` — ÍCONE + PALAVRA + COR, sempre os três (SC 1.4.1). A forma do
 *    ícone difere por classe; a cor nunca é o único portador.
 * ========================================================================= */
.mh-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.mh-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 10px;
  border-radius: var(--mh-pill);
  font-size: 0.78rem;
  font-weight: 500;
  white-space: nowrap;
  background: rgba(var(--ink-rgb), 0.06);
  color: var(--text-2);
}
.mh-chip svg { width: 13px; height: 13px; flex: 0 0 auto; }
.mh-chip--ok {
  background: rgba(var(--status-excellent-rgb), 0.1);
  color: var(--status-excellent-ink);
}
.mh-chip--att {
  background: rgba(var(--status-attention-rgb), 0.12);
  color: var(--status-attention-ink);
}
.mh-chip--crit {
  background: rgba(var(--status-critical-rgb), 0.1);
  color: var(--status-critical-ink);
}
.mh-chip--info {
  background: rgba(var(--status-progress-rgb), 0.08);
  color: var(--status-progress-ink);
}
.mh-chip--soft { background: rgba(var(--ink-rgb), 0.06); color: var(--text-2); }
.mh-chip--tight { padding: 2px 8px; }

/* ========================================================================= *
 * 7. `.mh-figure` — o contrato de acessibilidade do §9.6 em CSS: o SVG, a frase
 *    de resumo e a tabela. Nenhum gráfico do painel existe sem os três.
 * ========================================================================= */
.mh-figure { margin: 0; min-width: 0; }
.mh-chart { display: block; width: 100%; height: auto; }
/* A linha que vem ANTES do desenho, quando o número já responde sozinho: no
 * aquecimento é «Semana 3 de 6 · hoje 1.402 de 1.800», e no mockup aprovado ela
 * é o que se lê primeiro — a escada de nós só confirma. O trecho em `<b>` sai em
 * serif, que é a assinatura de número da marca (§9.5). */
.mh-figure-nota { margin-top: 8px; font-size: 0.92rem; color: var(--text-2); }
.mh-figure-nota b {
  font-family: var(--brand-font-display);
  font-weight: 400;
  font-size: 1.25rem;
  color: var(--text-strong);
}
.mh-figure figcaption {
  margin-top: 8px;
  font-size: 0.86rem;
  color: var(--text-1);
}
.mh-figure details { margin-top: 8px; }
.mh-figure summary {
  cursor: pointer;
  font-size: 0.8rem;
  color: var(--accent-ink);
  min-height: var(--mh-tap);
  display: flex;
  align-items: center;
}
.mh-figure-table {
  margin-top: 8px;
  max-height: 240px;
  overflow: auto;
}
.mh-figure-table > table { min-width: 0; }

/* Legenda: quadradinho de cor MAIS a palavra; o traço (contínuo, tracejado,
   pontilhado) repete a distinção dentro do gráfico (§9.6). */
.mh-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin-top: 8px;
  font-size: 0.78rem;
  color: var(--text-2);
}
.mh-legend span { display: inline-flex; align-items: center; gap: 6px; }
.mh-legend i { width: 10px; height: 10px; border-radius: 2px; display: inline-block; }
.mh-legend-sent { background: var(--status-excellent-ink); }
.mh-legend-deferred { background: var(--status-attention-ink); }
.mh-legend-bounced { background: var(--status-critical-ink); }
.mh-legend-rejected { background: var(--accent-ink); }
.mh-legend-quota { background: var(--status-progress-ink); }
/* Série de UMA cor usa o dourado como fill — e então precisa do contorno de
   1 px em `--accent-ink` para chegar aos 3:1 do SC 1.4.11 (§9.2, regra 2). */
.mh-legend-single {
  background: var(--brand-accent);
  box-shadow: inset 0 0 0 1px var(--accent-ink);
}

/* ------------------------------------------------------------------------- *
 * 7b. Camada de cor dos gráficos — o par do `src/mailhub/panel/svg.py`.
 *
 * O `svg.py` emite CLASSE, nunca `fill="var(--token)"` e nunca `style=` inline:
 * `var()` em atributo de apresentação não é confiável em todo navegador, e
 * `style=` inline é proibido pelo plano de testes (§11.1,
 * `test_paneld_render.py`). O efeito é o do §9.6 — token resolvido em runtime,
 * sem CDN — por um caminho que passa nos dois.
 *
 * CONTRATO COM O `svg.py`: se uma classe `mh-fill-*`, `mh-line-*`, `mh-band-*`
 * ou `mh-c-*` sair daqui, o gráfico fica preto. `test_panel_svg.py` afirma que
 * toda classe emitida está declarada neste arquivo.
 * ------------------------------------------------------------------------- */
.mh-chart text {
  font-family: var(--brand-font-body);
  font-variant-numeric: tabular-nums;
}
/* Rótulo de eixo: `--text-2` (6,04:1). NUNCA `--text-3` (§9.2, regra 1). */
.mh-chart .mh-c-axis { fill: var(--text-2); }
.mh-chart .mh-c-end { fill: var(--text-strong); }
.mh-chart .mh-c-big {
  fill: var(--text-strong);
  font-family: var(--brand-font-display);
}
/* Eixo e grade são DECORATIVOS (§9.2): 1,29:1 é aceitável porque nenhuma
   informação depende deles — os números estão nos rótulos e na tabela. */
.mh-chart .mh-c-grid { stroke: rgba(var(--ink-rgb), 0.12); fill: none; }
.mh-chart .mh-c-track { stroke: rgba(var(--ink-rgb), 0.12); fill: none; }
.mh-chart .mh-c-trackbar { fill: rgba(var(--ink-rgb), 0.06); }
/* A linha de meta precisa ser LIDA, então sai do decorativo e vai para
   `--text-2`. Declarada depois de `.mh-c-grid` de propósito: o `svg.py` emite as
   duas classes no mesmo elemento. */
.mh-chart .mh-c-target { stroke: var(--text-2); }
.mh-chart .mh-c-line { fill: none; }
.mh-chart .mh-c-arc { fill: none; }
.mh-chart .mh-c-needle { fill: none; stroke-linecap: round; }
/* Traço é o SEGUNDO portador da distinção entre séries (SC 1.4.1). */
.mh-chart .mh-c-dashed { stroke-dasharray: 6 3; }
.mh-chart .mh-c-dotted { stroke-dasharray: 2 3; }

.mh-chart .mh-fill-sent { fill: var(--status-excellent-ink); }
.mh-chart .mh-fill-deferred { fill: var(--status-attention-ink); }
.mh-chart .mh-fill-bounced { fill: var(--status-critical-ink); }
.mh-chart .mh-fill-rejected { fill: var(--accent-ink); }
.mh-chart .mh-fill-quota { fill: var(--status-progress-ink); }
/* Série única: dourado como preenchimento + contorno de 1 px em `--accent-ink`,
   que é o que leva os 1,72:1 do dourado aos 3:1 do SC 1.4.11 (§9.2, regra 2). */
.mh-chart .mh-fill-single {
  fill: var(--brand-accent);
  stroke: var(--accent-ink);
  stroke-width: 1;
}

.mh-chart .mh-line-sent { stroke: var(--status-excellent-ink); }
.mh-chart .mh-line-deferred { stroke: var(--status-attention-ink); }
.mh-chart .mh-line-bounced { stroke: var(--status-critical-ink); }
.mh-chart .mh-line-rejected { stroke: var(--accent-ink); }
.mh-chart .mh-line-quota { stroke: var(--status-progress-ink); }
.mh-chart .mh-line-single { stroke: var(--accent-ink); }

.mh-chart .mh-band-sent { fill: rgba(var(--status-excellent-rgb), 0.08); }
.mh-chart .mh-band-deferred { fill: rgba(var(--status-attention-rgb), 0.08); }
.mh-chart .mh-band-bounced { fill: rgba(var(--status-critical-rgb), 0.08); }
.mh-chart .mh-band-rejected { fill: rgba(var(--brand-accent-rgb), 0.1); }
.mh-chart .mh-band-quota { fill: rgba(var(--status-progress-rgb), 0.08); }
.mh-chart .mh-band-single { fill: rgba(var(--brand-accent-rgb), 0.12); }

/* Stepper do aquecimento: «os nós que acendem em dourado» (§9.3). A forma
   distingue — nó vazado, nó cheio, nó cheio com anel — e não só a cor. */
.mh-chart .mh-c-rail { stroke: rgba(var(--ink-rgb), 0.14); }
.mh-chart .mh-c-rail.is-done { stroke: var(--accent-ink); }
.mh-chart .mh-c-node { fill: var(--surface-2); stroke: rgba(var(--ink-rgb), 0.22); }
.mh-chart .mh-c-node.is-done,
.mh-chart .mh-c-node.is-current { fill: var(--brand-accent); stroke: var(--accent-ink); }
.mh-chart .mh-c-ring { fill: rgba(var(--brand-accent-rgb), 0.18); stroke: none; }

/* Sparkline: mora numa célula de tabela, então não estica. */
.mh-spark { display: inline-block; vertical-align: middle; }

/* ========================================================================= *
 * 8. `.mh-term` — glossário que abre NO LUGAR. Nunca tooltip só de hover,
 *    nunca `title=` como rótulo único (SC 1.4.13).
 * ========================================================================= */
/* Alvo medido: 66×23 px, meio pixel abaixo dos 24 do SC 2.5.8 — e **é conforme**
   pela exceção «inline»: o alvo está dentro de uma frase e o tamanho dele é
   determinado pelo `line-height` do texto que não é alvo. Crescer 1 px empurraria
   a linha da frase, que é justamente o que a exceção existe para evitar. Os
   alvos que NÃO são inline (botão de ferramenta, chip de período, `summary`)
   usam `var(--mh-tap)` e passam com folga. */
.mh-term {
  font: inherit;
  color: inherit;
  background: none;
  border: 0;
  padding: 0;
  cursor: help;
  border-bottom: 1px dotted var(--accent-ink);
}
.mh-term-def {
  display: block;
  margin-top: 6px;
  padding: 8px 10px;
  border-radius: var(--mh-radius-sm);
  background: rgba(var(--brand-accent-rgb), 0.08);
  font-size: 0.82rem;
  color: var(--text-1);
}

/* ========================================================================= *
 * 9. `.mh-danger-note` — «isto não tem botão aqui» (§6.10). O comando pronto
 *    para copiar e a consequência escrita, lado a lado.
 * ========================================================================= */
.mh-danger-note {
  border: 1px dashed rgba(var(--status-critical-rgb), 0.45);
  border-radius: var(--mh-radius-sm);
  padding: 14px 16px;
  background: rgba(var(--status-critical-rgb), 0.03);
}
.mh-danger-note b { color: var(--status-critical-ink); font-weight: 600; }
.mh-danger-note p { font-size: 0.86rem; color: var(--text-2); margin-top: 4px; }

/* Bloco de comando. O fundo é `rgb(var(--ink-rgb))` e não um hex de petróleo:
   no claro a tinta É o petróleo, então o terminal fica escuro sobre a página
   clara sem uma única cor nova — e sem hex cru. */
.mh-cmd {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 8px;
  padding: 8px 10px;
  border-radius: var(--mh-radius-sm);
  background: rgb(var(--ink-rgb));
  color: var(--surface-2);
  font-family: var(--mh-mono);
  font-size: 0.78rem;
  overflow-x: auto;
}
.mh-cmd code { font: inherit; color: inherit; background: none; white-space: pre; }
.mh-cmd button {
  margin-left: auto;
  flex: 0 0 auto;
  min-height: var(--mh-tap);
  padding: 4px 10px;
  border-radius: var(--mh-pill);
  /* `--surface-rgb` e `--ink-rgb` trocam de lado juntos quando o tema vira, e o
     fundo deste bloco é `rgb(var(--ink-rgb))`: a borda fica sempre no contraste
     certo, nos dois temas, sem uma cor nova. */
  border: 1px solid rgba(var(--surface-rgb), 0.35);
  background: transparent;
  color: var(--surface-2);
  font: inherit;
  font-size: 0.72rem;
  cursor: pointer;
}
/* O anel de foco do patch usa `--surface-2` como separador interno; dentro do
   bloco escuro isso desaparece. Aqui o separador vira a própria tinta. */
.mh-cmd button:focus-visible { box-shadow: 0 0 0 1px rgb(var(--ink-rgb)); }

/* Variante de BLOCO do mesmo componente: o «Retrato para o Claude» (§6.9) é um
   texto de muitas linhas, e não um comando de uma. `pre-wrap` em vez de `pre`
   porque a alternativa é rolagem horizontal dentro do bloco, e o §10 (SC 1.4.10)
   já proíbe isso no documento — repeti-lo num filho seria trocar de lugar o
   mesmo defeito.

   ⚠️ SEM teto de altura, desde 2026-10-01 (§8.6). Havia um `max-height: 340px`
   com `overflow: auto`, e em `hoje-1280.png` ele cortava o retrato exatamente na
   primeira linha de «Alertas ativos»: a tela mostrava dois cartões de alerta e o
   texto ao lado parecia listar um só. O conteúdo estava inteiro e rolava dentro
   da caixa, o que é ainda pior — a contradição só aparecia para quem NÃO rolasse,
   que é todo mundo que olha a tela de relance (e toda foto da tela).

   O tamanho já tem teto onde ele é verdade: `snapshot.MAX_BYTES` (6 KiB) corta o
   texto na origem e **escreve** que cortou. Teto de pixel não corta texto: ele
   esconde. */
.mh-cmd--bloco {
  align-items: flex-start;
}
.mh-cmd--bloco code { white-space: pre-wrap; word-break: break-word; }
/* `static`, e não `sticky`: o grude existia para o botão acompanhar a rolagem
   DENTRO da caixa, e a caixa não rola mais. Preso ao documento, ele passaria a
   deslizar por cima do próprio texto. */
.mh-cmd--bloco button { position: static; }

/* ========================================================================= *
 * 10. Listas do painel
 * ========================================================================= */

/* «O que mudou desde ontem» — o bloco que o dono de fato lê (§6.1). */
.mh-diffs { list-style: none; margin: 10px 0 0; padding: 0; }
.mh-diffs li {
  display: flex;
  gap: 10px;
  align-items: flex-start;
  padding: 8px 0;
  border-bottom: 1px solid rgba(var(--ink-rgb), 0.06);
  font-size: 0.9rem;
}
.mh-diffs li:last-child { border-bottom: 0; }
.mh-diff-word {
  flex: 0 0 auto;
  margin-top: 2px;
  padding: 3px 7px;
  border-radius: 5px;
  font-family: var(--mh-label-font);
  font-size: 0.6rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  background: rgba(var(--ink-rgb), 0.06);
  color: var(--text-2);
}
.mh-diff-word--up {
  background: rgba(var(--status-progress-rgb), 0.08);
  color: var(--status-progress-ink);
}
.mh-diff-word--down {
  background: rgba(var(--status-attention-rgb), 0.12);
  color: var(--status-attention-ink);
}
.mh-diff-word--better {
  background: rgba(var(--status-excellent-rgb), 0.1);
  color: var(--status-excellent-ink);
}

/* Linha do tempo: alertas, auditoria, verificações e backups juntos (§6.7). */
.mh-timeline { list-style: none; margin: 10px 0 0; padding: 0; }
.mh-timeline li {
  display: grid;
  grid-template-columns: 92px minmax(0, 1fr) auto;
  gap: 10px;
  align-items: center;
  padding: 9px 0;
  border-bottom: 1px solid rgba(var(--ink-rgb), 0.06);
  font-size: 0.88rem;
  scroll-margin-top: var(--mh-head-offset);
}
.mh-timeline li:last-child { border-bottom: 0; }
.mh-timeline time {
  font-size: 0.8rem;
  color: var(--text-2);
  font-variant-numeric: tabular-nums;
}
@media (max-width: 640px) {
  .mh-timeline li { grid-template-columns: minmax(0, 1fr) auto; }
  .mh-timeline time { grid-column: 1 / -1; }
}

/* Saúde: item, o que fazer, e o link — sempre na mesma ordem (§6.6). */
.mh-health { list-style: none; margin: 10px 0 0; padding: 0; }
.mh-health li {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  gap: 12px;
  align-items: start;
  padding: 11px 0;
  border-bottom: 1px solid rgba(var(--ink-rgb), 0.06);
  scroll-margin-top: var(--mh-head-offset);
}
.mh-health li:last-child { border-bottom: 0; }
.mh-health b { font-weight: 500; color: var(--text-strong); font-size: 0.92rem; }
.mh-health p { font-size: 0.84rem; color: var(--text-2); margin-top: 2px; }
.mh-health a { font-size: 0.8rem; white-space: nowrap; }
@media (max-width: 640px) {
  .mh-health li { grid-template-columns: auto minmax(0, 1fr); }
  .mh-health a { grid-column: 2; }
}

/* ========================================================================= *
 * 11. Cartão de problema — as 4 partes sempre na mesma ordem (§6.3):
 *     o que aconteceu · o que significa · o que fazer · onde resolver.
 *     Reusa `.qe-*` do vendor, que já codifica QUEM RESOLVE pela cor.
 * ========================================================================= */
.mh-problem {
  background: var(--surface-2);
  border: var(--mh-hair);
  border-radius: var(--mh-radius);
  padding: 18px 20px;
  display: grid;
  grid-template-columns: minmax(0, 1fr) 220px;
  gap: 18px;
}
/* O rótulo de QUEM RESOLVE. O `.qe-label` do vendor é 0,82 rem em texto corrido
 * (ele nasceu numa ficha de aluna, onde é um rótulo de campo); aqui ele é o
 * carimbo de categoria do cartão, e o mockup aprovado o desenha como os outros
 * rótulos do painel — Clash, caixa alta, entrelinha larga. Modificador ESCOPADO
 * no componente do painel: o vendor fica intacto (§9.1), e as cores por classe
 * (`.qe-lead/.qe-infra/.qe-soft`) continuam vindo do patch de contraste (§9.4). */
.mh-problem .qe-label {
  font-family: var(--mh-label-font);
  font-size: 0.62rem;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
}
.mh-problem h3 { margin-top: 2px; font-size: 1.2rem; }
.mh-problem-mean { color: var(--text-2); font-size: 0.92rem; margin-top: 4px; }
.mh-problem ol { margin: 10px 0 0; padding-left: 20px; font-size: 0.9rem; }
.mh-problem ol li { margin-top: 4px; }
.mh-problem-side {
  display: flex;
  flex-direction: column;
  gap: 8px;
  align-items: flex-start;
  border-left: var(--mh-hair);
  padding-left: 18px;
}
@media (max-width: 760px) {
  .mh-problem { grid-template-columns: minmax(0, 1fr); }
  .mh-problem-side {
    border-left: 0;
    padding-left: 0;
    border-top: var(--mh-hair);
    padding-top: 12px;
  }
}
/* Resposta crua do provedor — sempre mascarada na origem (§3.5). */
.mh-raw { margin-top: 10px; }
.mh-raw summary {
  cursor: pointer;
  font-size: 0.8rem;
  color: var(--accent-ink);
  min-height: var(--mh-tap);
  display: flex;
  align-items: center;
}
.mh-raw pre {
  margin: 8px 0 0;
  padding: 10px 12px;
  border-radius: var(--mh-radius-sm);
  background: rgba(var(--ink-rgb), 0.04);
  font-family: var(--mh-mono);
  font-size: 0.76rem;
  white-space: pre-wrap;
  word-break: break-word;
  color: var(--text-1);
}

/* ========================================================================= *
 * 12. Credenciais (§6.5)
 * ========================================================================= */
.mh-cred-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 8px;
}
.mh-cred-rows {
  display: grid;
  grid-template-columns: 110px minmax(0, 1fr);
  gap: 6px 12px;
  margin: 10px 0 0;
  font-size: 0.86rem;
}
.mh-cred-rows dt { color: var(--text-2); }
.mh-cred-rows dd { margin: 0; color: var(--text-1); min-width: 0; overflow-wrap: anywhere; }
.mh-cred-acts { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 14px; }

/* Barra de cota: o fill dourado do `.bz-progress` do vendor não tem contorno, e
   o §9.2 (regra 2) exige 1 px em `--accent-ink` para os 3:1 do SC 1.4.11.
   Modificador do painel — o vendor fica intacto. */
.bz-progress.mh-goldfill > span { box-shadow: inset 0 0 0 1px var(--accent-ink); }

/* ========================================================================= *
 * 13. Tabelas — densidade e refluxo
 * ========================================================================= */
/* Unidade no CABEÇALHO, nunca na célula; numérica à direita (§9.7). */
.bz-table th.mh-num, .bz-table td.mh-num {
  text-align: right;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.bz-table tbody tr { scroll-margin-top: var(--mh-head-offset); }
/* Seleção e foco de LINHA por borda de 2 px, nunca só por tom de fundo
   (§9.2, regra 3: hover é decorativo). */
.bz-table tbody tr.is-selected > td:first-child {
  box-shadow: inset 2px 0 0 0 var(--accent-ink);
}
.mh-table--dense tbody td { padding: 7px 10px; font-size: 0.82rem; }
.mh-table--dense thead th { padding: 8px 10px; }

/* Tabela que vive numa COLUNA ESTREITA do desktop (os motivos da fila, na coluna
 * de 1 fr ao lado dos gráficos). O `min-width: 640px` do vendor existe para a
 * tabela larga da plataforma; numa coluna de 380 px ele vira texto cortado atrás
 * de uma rolagem horizontal interna — exatamente o que o QA visual proíbe. Aqui
 * ela reflui. Poucas colunas, e cada uma cabe. */
.bz-table.mh-table--fluida { min-width: 0; }

/* A tabela larga que rola precisa ser alcançável pelo teclado (SC 1.4.10): o
   `role="region"` + `aria-label` vêm do template; o `tabindex` faz o foco. */
.bz-table-scroll:focus-visible { outline: 2px solid var(--focus-ring); }

/* Abaixo de 640 px a tabela vira cartões de pares rótulo/valor. O rótulo sai do
   `data-label`, que o template copia do `<th>` — zero altura fixa, zero
   rolagem horizontal do documento. */
@media (max-width: 640px) {
  .mh-table--cards, .mh-table--cards tbody, .mh-table--cards tr, .mh-table--cards td {
    display: block;
    width: auto;
  }
  .mh-table--cards thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }
  .mh-table--cards tr {
    border: var(--mh-hair);
    border-radius: var(--mh-radius-sm);
    padding: 10px 12px;
    margin-bottom: 10px;
    background: var(--surface-2);
  }
  .mh-table--cards td {
    display: flex;
    justify-content: space-between;
    gap: 12px;
    border: 0;
    padding: 4px 0;
    text-align: left;
  }
  .mh-table--cards td::before {
    content: attr(data-label);
    flex: 0 0 auto;
    font-family: var(--mh-label-font);
    font-size: 0.6rem;
    font-weight: 600;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--text-2);
  }
  .mh-table--cards td.mh-num { text-align: right; }
  .mh-table--cards td:empty { display: none; }
  /* Sem tabela larga, sem pista de rolagem. */
  .mh-table--cards-wrap { overflow-x: visible; }
  .mh-table--cards-wrap > table { min-width: 0; }
}

/* Provedor: nome forte com o ícone à esquerda. */
.mh-provider {
  display: flex;
  align-items: center;
  gap: 8px;
  font-weight: 500;
  color: var(--text-strong);
}

/* ========================================================================= *
 * 14. Formulários. `.label-field` e `.input-dark` do vendor são dirigidos por
 *     token e funcionam no claro; o nome é legado. `.mh-field` é o alias que o
 *     painel escreve (§9.3), para que o template não carregue o nome errado.
 * ========================================================================= */
.mh-field { margin-top: 18px; }
.mh-field label, .mh-field .mh-field-label {
  display: block;
  margin-bottom: 8px;
  font-family: var(--mh-label-font);
  font-size: 0.68rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-2);
}
.mh-field input, .mh-field select, .mh-field textarea {
  width: 100%;
  font: inherit;
  font-size: 1rem;
  padding: 12px 14px;
  border-radius: 12px;
  border: 1px solid rgba(var(--ink-rgb), 0.25);
  background: var(--surface-2);
  color: var(--text-strong);
}
.mh-field-help { margin-top: 6px; font-size: 0.8rem; color: var(--text-2); }
/* Erro: `aria-describedby` + `aria-invalid` no campo (SC 3.3.1), e a mensagem
   em `--status-critical-ink` (6,47:1) — nunca em tinta de apoio. */
.mh-field-error { margin-top: 6px; font-size: 0.82rem; color: var(--status-critical-ink); }
.mh-field [aria-invalid="true"] { border-color: var(--status-critical-ink); }

/* Resumo de erros no topo, com link para cada campo (SC 3.3.1 / 3.3.3). */
.mh-errors {
  border: 1px solid rgba(var(--status-critical-rgb), 0.45);
  border-radius: var(--mh-radius-sm);
  padding: 12px 14px;
  background: rgba(var(--status-critical-rgb), 0.04);
  color: var(--text-1);
  font-size: 0.88rem;
}
.mh-errors b { color: var(--status-critical-ink); }
.mh-errors ul { margin: 6px 0 0; padding-left: 20px; }

/* Aviso na página (nunca modal — a confirmação perigosa é uma PÁGINA, §10). */
.mh-banner {
  display: flex;
  gap: 10px;
  align-items: flex-start;
  margin-top: 14px;
  padding: 12px 14px;
  border-radius: 12px;
  background: rgba(var(--status-attention-rgb), 0.1);
  color: var(--text-1);
  font-size: 0.88rem;
}
.mh-banner svg { flex: 0 0 auto; margin-top: 2px; color: var(--status-attention-ink); width: 16px; height: 16px; }
.mh-banner--info { background: rgba(var(--status-progress-rgb), 0.08); }
.mh-banner--info svg { color: var(--status-progress-ink); }

.mh-btns { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 22px; }
/* Ação destrutiva: contorno e texto em vermelho. NUNCA preenchimento vermelho —
   vermelho não é cor de fill da paleta (§9.3). */
.btn-outline-pill.mh-danger {
  border-color: var(--status-critical-ink);
  color: var(--status-critical-ink);
}
.btn-sm { padding: 8px 14px; font-size: 0.66rem; }

/* Tela de entrar: um botão só (§6.8). */
.mh-login { display: grid; place-items: center; padding: 8vh var(--mh-gutter); }
.mh-login-card {
  width: min(420px, 100%);
  background: var(--surface-2);
  border: var(--mh-hair);
  border-radius: 20px;
  padding: 34px 28px;
  text-align: center;
}
.mh-login-card img { height: 40px; width: auto; margin: 0 auto; display: block; }
.mh-login-card .mh-eyebrow { margin-top: 22px; }
.mh-login-card h1 { margin-top: 6px; font-size: 1.8rem; }
.mh-login-card p { margin-top: 8px; color: var(--text-2); font-size: 0.92rem; }
.mh-login-card .btn-gold { margin-top: 22px; width: 100%; }
/* A linha de saída: «perdeu o acesso? o Console recadastra». O painel nunca fica
 * sem saída (§6.8), e a tela diz isso em voz alta. */
/* `.mh-login-card` na frente: sem ele o `.mh-login-card p` acima (dois seletores)
   vence este (um) e a dica volta a 0,92 rem, que quebra o comando em duas linhas
   dentro de um cartão de 420 px. */
.mh-login-card .mh-login-hint { margin-top: 16px; font-size: 0.8rem; }
.mh-login-hint code { overflow-wrap: anywhere; }
/* Dentro do cartão o formulário volta a ser alinhado à esquerda: rótulo de campo
 * centralizado é ilegível, e o cartão inteiro é `text-align: center` por causa do
 * logo e do título. */
.mh-login-card form.mh-form-esq,
.mh-login-card .mh-esq { text-align: left; }
.mh-login-card details { margin-top: 18px; text-align: left; }
.mh-login-card summary {
  cursor: pointer;
  font-size: 0.82rem;
  color: var(--accent-ink);
  min-height: var(--mh-tap);
  display: flex;
  align-items: center;
}
.mh-login-card .btn-outline-pill { margin-top: 16px; width: 100%; }

/* ========================================================================= *
 * 14b. Barra de cota: a LARGURA como classe (§3.4 — a CSP não tem
 *      `unsafe-inline`, então `style="width:78%"` simplesmente não carrega).
 *      Passo de 5: invisível numa barra de 200 px, e o número exato fica escrito
 *      ao lado em texto, que é o que um leitor de tela lê de verdade.
 * ========================================================================= */
.mh-bar-0   { width: 0; }
.mh-bar-5   { width: 5%; }
.mh-bar-10  { width: 10%; }
.mh-bar-15  { width: 15%; }
.mh-bar-20  { width: 20%; }
.mh-bar-25  { width: 25%; }
.mh-bar-30  { width: 30%; }
.mh-bar-35  { width: 35%; }
.mh-bar-40  { width: 40%; }
.mh-bar-45  { width: 45%; }
.mh-bar-50  { width: 50%; }
.mh-bar-55  { width: 55%; }
.mh-bar-60  { width: 60%; }
.mh-bar-65  { width: 65%; }
.mh-bar-70  { width: 70%; }
.mh-bar-75  { width: 75%; }
.mh-bar-80  { width: 80%; }
.mh-bar-85  { width: 85%; }
.mh-bar-90  { width: 90%; }
.mh-bar-95  { width: 95%; }
.mh-bar-100 { width: 100%; }

/* ========================================================================= *
 * 14c. Densidade (§9.7). Confortável por padrão — o dono usa isto algumas vezes
 *      por semana (DD-8), não 8 h por dia. A preferência vive em `localStorage`,
 *      e o `mh-ui.js` a aplica em `<html data-density="dense">`. O BOTÃO nasce
 *      com `hidden` e é o JS que o revela: um controle que não faz nada sem
 *      JavaScript é pior que controle nenhum.
 * ========================================================================= */
html[data-density="dense"] .bz-table tbody td { padding: 7px 10px; font-size: 0.82rem; }
html[data-density="dense"] .bz-table thead th { padding: 8px 10px; }
html[data-density="dense"] .mh-cred-rows { gap: 4px 12px; font-size: 0.82rem; }
html[data-density="dense"] .mh-stack { gap: calc(var(--mh-gap) * 0.7); }
/* A fileira de AÇÃO do cabeçalho de uma tela (Saúde, Apps). Nome próprio, e não
 * `.mh-tools`: `.mh-tools` é o canto fixo das três ferramentas (SC 3.2.6), e
 * misturar ação com ferramenta faria o «mesmo canto em todas as telas» deixar de
 * ser verdade. */
.mh-acoes { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.mh-tbtn[aria-disabled="true"] { color: var(--text-2); cursor: default; }

.mh-tbtn[aria-pressed="true"] {
  border-color: rgba(var(--brand-accent-rgb), 0.55);
  color: var(--accent-ink);
}

/* ========================================================================= *
 * 14d. A página de confirmação (§6.8) e a senha mostrada uma vez (§3.4).
 *
 *      O nome é `.mh-narrow`, e nunca o nome que o §9.3 proíbe («mh-confirm»):
 *      `test_brand_vendor.py` afirma a ausência daquele nome no arquivo INTEIRO,
 *      comentário incluído — é o que impede a regra de voltar pela porta dos
 *      fundos. Ela existe para que ninguém traga de volta um componente de
 *      DIÁLOGO: a confirmação perigosa é uma página (§10 — sem modal no v1, então
 *      não há foco preso a gerir). O que está aqui é utilidade de LAYOUT: coluna
 *      estreita, porque uma decisão perigosa não se lê em 1150 px de largura.
 * ========================================================================= */
.mh-narrow { width: min(620px, 100%); }
.mh-narrow ul { margin: 12px 0 0; padding-left: 20px; font-size: 0.94rem; }
.mh-narrow ul li { margin-top: 6px; color: var(--text-1); }
.mh-secret {
  margin-top: 18px;
  border: 1px solid rgba(var(--brand-accent-rgb), 0.45);
  border-radius: var(--mh-radius-sm);
  padding: 14px 16px;
  background: rgba(var(--brand-accent-rgb), 0.06);
}
.mh-secret-label {
  font-family: var(--mh-label-font);
  font-size: 0.64rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-2);
}
.mh-secret .mh-cmd { margin-top: 8px; }
.mh-secret .mh-cmd code { font-size: 0.95rem; letter-spacing: 0.04em; }

/* ========================================================================= *
 * 15. Movimento reduzido — ESTENDE o bloco do vendor (§10), não reescreve.
 *     Como não há auto-refresh nem contador (DD-8), sobra quase nada.
 * ========================================================================= */
@media (prefers-reduced-motion: reduce) {
  .mh-tbtn, .mh-skip { transition: none; }
  .bz-skeleton::after { animation: none; }
  html { scroll-behavior: auto; }
  /* E o resto do vendor, que tem transição em `.gnav-item`, `.bz-card`,
     `.btn-gold` e `.btn-outline-pill` (`admin-nav.css:48`, `braz-ui.css:76,93,
     106,181,324,337,356`). O bloco do vendor desliga a aurora e o `.reveal`, que
     é o que a página institucional usa — e nada do que o PAINEL usa.
     Zerar a duração em vez de `transition: none` é de propósito: `none` apaga a
     declaração e um seletor mais específico a traz de volta; duração zero
     sobrevive à cascata. Medido no Chromium: sem esta regra, `.gnav-item`
     continuava com 0,2 s de transição sob `prefers-reduced-motion: reduce`. */
  *, *::before, *::after {
    animation-duration: 0s !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0s !important;
    scroll-behavior: auto !important;
  }
}

/* ========================================================================= *
 * 16. Impressão (§10) — o dono vai levar a tela Saúde para uma conversa.
 *     A navegação e os botões saem; os `<details>` dos gráficos abrem, então a
 *     TABELA de cada figura é impressa junto com o SVG; o link mostra a URL.
 * ========================================================================= */
@media print {
  .mh-topbar, .gnav, .mh-tools, .mh-skip, .mh-cmd button, .mh-btns { display: none; }
  body { background: var(--surface-2); }
  .mh-main { max-width: none; padding: 0; }
  .mh-figure details { display: block; }
  .mh-figure details > summary { display: none; }
  .mh-figure-table { max-height: none; overflow: visible; }
  .mh-problem, .mh-kpi, .bz-card { break-inside: avoid; }
  a[href^="http"]::after { content: " (" attr(href) ")"; font-size: 0.8em; color: var(--text-2); }
}
