﻿/* ==========================================================================
   SGI PRO — Estilos da biblioteca de componentes base (F3)
   Todos os componentes Components/Ui. Tudo via tokens --sgsi-*. WCAG 2.1 AA:
   foco visível, alvos >= 44px onde aplicável, contraste calibrado pelos tokens.
   Respeita prefers-reduced-motion.
   ========================================================================== */

/* ---- utilitários de rotação de ícone (setas) ---- */
.sgsi-rot-90 { transform: rotate(90deg); }
.sgsi-rot-180 { transform: rotate(180deg); }
.sgsi-rot-270 { transform: rotate(270deg); }

/* ---- utilitários de texto atenuado ----
   Texto secundário inline nas páginas (célula de apoio, legendas, sublinhas).
   As classes já eram usadas por ~40 call-sites mas nunca tinham sido definidas
   (caíam na cor herdada). Cor via token → acompanha o dark mode. */
.sgsi-texto-suave { color: var(--sgsi-color-text-muted); }
.sgsi-text-muted { color: var(--sgsi-color-text-muted); } /* alias legado — migrar os call-sites para .sgsi-texto-suave */

/* ---- utilitários de TAMANHO de texto (os dois degraus pequenos da escala) ----
   Existem porque o call-site que não os tem escreve `style="font-size:.85rem"` — e .85rem
   NÃO é degrau da escala (sgsi-tokens.css: xs .75 / sm .875 / md 1 / lg 1.125 / xl 1.375 /
   2xl 1.75). Cada tamanho inventado à mão é um valor que o dark mode e o zoom do navegador
   continuam respeitando, mas que NINGUÉM mais consegue ajustar em um lugar só. Use estes
   com .sgsi-texto-suave quando o texto também for secundário. */
.sgsi-texto-sm { font-size: var(--sgsi-font-size-sm); }
.sgsi-texto-xs { font-size: var(--sgsi-font-size-xs); }

/* ---- input/textarea monoespaçado (JSON, chave, token colado) ----
   Acompanha `form-control`, NUNCA o substitui: quem dá borda, raio, padding, foco e o
   estado inválido é o form-control do Bootstrap, como em todo campo do produto. Aqui fica
   só o que é próprio do conteúdo — fonte mono e o degrau `sm` da escala —, porque um campo
   de credencial colada precisa que o usuário distinga l/1/I/O/0 ao conferir o que colou. */
.sgsi-campo-mono { font-family: var(--sgsi-font-mono, ui-monospace, SFMono-Regular, Menlo, monospace); font-size: var(--sgsi-font-size-sm); }

/* ==========================================================================
   BADGE
   ========================================================================== */
.sgsi-badge {
    display: inline-flex;
    align-items: center;
    gap: var(--sgsi-space-1);
    padding: 0.2rem 0.55rem;
    font-size: var(--sgsi-font-size-xs);
    font-weight: var(--sgsi-font-weight-semibold);
    line-height: 1.4;
    border-radius: var(--sgsi-radius-pill);
    border: 1px solid transparent;
    white-space: nowrap;
}
.sgsi-badge__ponto {
    width: 0.5rem;
    height: 0.5rem;
    border-radius: 50%;
    background: currentColor;
    flex: 0 0 auto;
}
.sgsi-badge--neutro  { color: var(--sgsi-color-text-muted); background: var(--sgsi-color-surface-2); border-color: var(--sgsi-color-border); }
.sgsi-badge--sucesso { color: var(--sgsi-color-success); background: var(--sgsi-color-success-bg); }
.sgsi-badge--aviso   { color: var(--sgsi-color-warning); background: var(--sgsi-color-warning-bg); }
.sgsi-badge--perigo  { color: var(--sgsi-color-danger);  background: var(--sgsi-color-danger-bg); }
.sgsi-badge--info    { color: var(--sgsi-color-info);    background: var(--sgsi-color-info-bg); }
.sgsi-badge--marca   { color: var(--sgsi-color-on-brand); background: var(--sgsi-color-brand); }
/* PERIGO SÓLIDO — o degrau ACIMA do perigo tingido, para quando a tela precisa separar dois
   níveis vermelhos no mesmo eixo (Alto × Crítico no registro de riscos). A diferença é de
   FUNDO CHEIO contra fundo claro, e não de tom de vermelho: sobrevive a daltonismo, a
   monitor ruim e ao print em preto e branco que o auditor leva para a reunião. O par
   texto/fundo é o mesmo do mapa de calor (`text-on-accent` sobre `danger`) — nos dois temas
   passa de 6:1, enquanto dois vermelhos vizinhos ficavam a ~1,3:1 entre si. */
.sgsi-badge--perigo-solido { color: var(--sgsi-color-text-on-accent); background: var(--sgsi-color-danger); border-color: var(--sgsi-color-danger); }

/* ==========================================================================
   SKELETON
   ========================================================================== */
.sgsi-skel {
    display: block;
    background: linear-gradient(
        90deg,
        var(--sgsi-color-surface-2) 25%,
        var(--sgsi-color-surface-3) 37%,
        var(--sgsi-color-surface-2) 63%);
    background-size: 400% 100%;
    animation: sgsi-skel-shimmer 1.4s ease infinite;
    border-radius: var(--sgsi-radius-sm);
}
.sgsi-skel--bloco { width: 100%; height: 1rem; }
.sgsi-skel--linha { margin-top: var(--sgsi-space-2); }
.sgsi-skel--circulo { width: 2.5rem; height: 2.5rem; border-radius: 50%; }
@keyframes sgsi-skel-shimmer {
    0% { background-position: 100% 50%; }
    100% { background-position: 0 50%; }
}

/* ==========================================================================
   EMPTY STATE
   ========================================================================== */
.sgsi-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: var(--sgsi-space-2);
    padding: var(--sgsi-space-7) var(--sgsi-space-4);
    color: var(--sgsi-color-text-muted);
}
.sgsi-empty__icone {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 4rem;
    height: 4rem;
    border-radius: 50%;
    background: var(--sgsi-color-surface-2);
    color: var(--sgsi-color-text-subtle);
    margin-bottom: var(--sgsi-space-2);
}
.sgsi-empty__titulo {
    margin: 0;
    font-size: var(--sgsi-font-size-lg);
    font-weight: var(--sgsi-font-weight-semibold);
    color: var(--sgsi-color-text);
}
.sgsi-empty__descricao { margin: 0; max-width: 32rem; }
.sgsi-empty__acao { margin-top: var(--sgsi-space-3); }

/* ==========================================================================
   BOTÃO CARREGANDO
   ========================================================================== */
.sgsi-btn__spinner { margin-right: var(--sgsi-space-2); }
.btn .sgsi-btn__rotulo { vertical-align: middle; }
.btn svg + .sgsi-btn__rotulo { margin-left: var(--sgsi-space-2); }

/* Micro-interação premium: transição suave + leve elevação no hover dos botões
   de ação primária/contornada (affordance de clicável). */
.btn { transition: background-color var(--sgsi-transition-fast), border-color var(--sgsi-transition-fast), color var(--sgsi-transition-fast), box-shadow var(--sgsi-transition-fast); }
.btn-primary:hover, .btn-outline-primary:hover { box-shadow: var(--sgsi-shadow-sm); }

/* ==========================================================================
   BOTOES CONTORNADOS — O TOKEN DA MARCA NAO CHEGAVA ATE ELES (DS-921, 27/08)
   ==========================================================================
   MEDIDO NO NAVEGADOR: no tema claro, "Exportar PDF" e "Fazer upgrade" saiam em
   rgb(13,110,253) — o azul de FABRICA do Bootstrap — sobre o fundo rgb(244,246,249),
   contraste 4.16:1. O minimo AA para texto de 16px e 4.5:1. O "Atualizar", em
   rgb(108,117,125), dava 4.33:1.

   A CAUSA, e nao o sintoma: sgsi-tokens.css:229 JA sobrescreve `--bs-primary` para
   `var(--sgsi-color-brand)` (#0b3d6b claro / #4f9fe0 escuro). Mas o Bootstrap compilado
   nao le essa variavel nos botoes contornados — `.btn-outline-primary` declara a cor
   LITERAL:

       .btn-outline-primary{--bs-btn-color:#0d6efd;--bs-btn-border-color:#0d6efd; ...}

   Ou seja: o conserto estava na CAMADA COMPARTILHADA (o token) e estes consumidores
   ficaram de fora dela. Eram 7 usos de `btn-outline-primary` e 67 de
   `btn-outline-secondary` — 74 botoes do produto fora da marca, incluindo os "Fazer
   upgrade" da /minha-assinatura, que sao os que recebem dinheiro.

   O CONSERTO E REAPONTAR AS VARIAVEIS DO PROPRIO BOTAO, uma vez, aqui — e nao trocar a
   classe em 74 telas. Como os tokens do DS ja viram com o tema, isto vale nos dois sem
   nenhuma regra duplicada em [data-bs-theme="dark"].

   O ROXO DO :hover: com fundo da marca, o texto passa a `--sgsi-color-on-brand`, que o
   DS define como o par legivel de cada tema (#ffffff no claro, #07172a no escuro) — o
   `#fff` fixo do Bootstrap ficaria ilegivel sobre o azul claro do tema escuro.

   O SECUNDARIO nao ganha `--bs-secondary` (que segue o #6c757d de fabrica e reprovaria
   igual): usa `--sgsi-color-text-muted`, que o proprio sgsi-tokens.css documenta como
   ">= 5:1 sobre surface (AA com folga)" nos dois temas. */
/* ==========================================================================
   BOTAO PRIMARIO SOLIDO — O IRMAO QUE FICOU DE FORA DO DS-921 (30/08)
   ==========================================================================
   O conserto de 27/08 alcancou `.btn-outline-primary` e NAO o `.btn-primary`. E o
   solido e o que mais aparece: "Salvar", "Confirmar", "Ativar norma", "Fazer
   upgrade" — todo CTA do produto. Eles saiam em #0d6efd, o azul de FABRICA do
   Bootstrap, e nao no navy #0b3d6b da marca. O usuario ve um SaaS que parece
   template, que e exatamente a leitura que o dono relatou ("a UX esta bem fraquinha").

   MESMA CAUSA JA DIAGNOSTICADA no bloco acima: `sgsi-tokens.css:229` sobrescreve
   `--bs-primary`, mas o Bootstrap COMPILADO nao le essa variavel nos botoes — ele
   declara a cor LITERAL em `--bs-btn-bg`. Sobrescrever o token da paleta nunca ia
   alcancar estes consumidores.

   E O CONSERTO DE 27/08 PAROU NO IRMAO ERRADO: quem escreveu media o CONTRASTE (o
   contornado reprovava AA), e o solido passava no contraste — texto branco sobre
   azul forte — entao nao entrou na varredura. Passar no contraste nao e vestir a
   marca. A catraca da epoca congelou as variantes contornadas e deixou a solida
   fora do inventario, que e como este defeito sobreviveu tres dias no ar.

   `--bs-btn-focus-shadow-rgb` entra junto: sem ele o halo de foco continua azul
   Bootstrap sobre um botao navy, e o descasamento aparece justamente para quem
   navega por teclado. */
.btn-primary {
    --bs-btn-bg: var(--sgsi-color-brand);
    --bs-btn-border-color: var(--sgsi-color-brand);
    --bs-btn-color: var(--sgsi-color-on-brand);
    --bs-btn-hover-bg: var(--sgsi-color-brand-hover);
    --bs-btn-hover-border-color: var(--sgsi-color-brand-hover);
    --bs-btn-hover-color: var(--sgsi-color-on-brand);
    --bs-btn-active-bg: var(--sgsi-color-brand-active);
    --bs-btn-active-border-color: var(--sgsi-color-brand-active);
    --bs-btn-active-color: var(--sgsi-color-on-brand);
    --bs-btn-disabled-bg: var(--sgsi-color-brand);
    --bs-btn-disabled-border-color: var(--sgsi-color-brand);
    --bs-btn-disabled-color: var(--sgsi-color-on-brand);
    --bs-btn-focus-shadow-rgb: var(--sgsi-color-brand-rgb);
}

.btn-outline-primary {
    --bs-btn-color: var(--sgsi-color-brand);
    --bs-btn-border-color: var(--sgsi-color-brand);
    --bs-btn-hover-color: var(--sgsi-color-on-brand);
    --bs-btn-hover-bg: var(--sgsi-color-brand);
    --bs-btn-hover-border-color: var(--sgsi-color-brand);
    --bs-btn-active-color: var(--sgsi-color-on-brand);
    --bs-btn-active-bg: var(--sgsi-color-brand-active);
    --bs-btn-active-border-color: var(--sgsi-color-brand-active);
    --bs-btn-disabled-color: var(--sgsi-color-brand);
    --bs-btn-disabled-border-color: var(--sgsi-color-brand);
    --bs-btn-focus-shadow-rgb: var(--sgsi-color-brand-rgb);
}

/* ---- OS IRMAOS SOLIDOS DE ESTADO: btn-danger E btn-success (30/08) -----------------------
   O bloco `.btn-primary` acima consertou o solido da MARCA. Varredura pelo NEGATIVO nos
   .razor — quem usa variante solida e NAO tem `--bs-btn-bg` reapontado aqui — devolveu
   exatamente dois: `btn-danger` (2 usos) e `btn-success` (1). Sao poucos, e e justamente por
   isso que ficariam de fora de novo: o conserto anterior olhou para o que aparecia MUITO.

   Mesma causa dos outros dois blocos: o Bootstrap compilado crava `--bs-btn-bg:#dc3545` /
   `#198754` LITERAL. Como esses hex nao viram com o tema, no tema ESCURO eles pintavam o
   vermelho e o verde de FABRICA sobre a superficie escura, fora da paleta que o resto da tela
   usa — a mesma familia de defeito que a tabela de contraste do bloco abaixo documenta.

   O par de texto e `--sgsi-color-text-on-accent`, exatamente o que os blocos contornados ja
   usam no :hover, quando eles tambem passam a ter o fundo PINTADO da cor de estado — nao e
   escolha nova, e a mesma que o DS ja documenta como o par legivel de cada tema.

   O :hover usa `color-mix` na direcao da cor de TEXTO do tema porque e o unico jeito de o
   escurecimento funcionar nos dois: no claro o texto e escuro (o botao escurece), no escuro o
   texto e claro (o botao clareia) — que e a mesma direcao que `--sgsi-color-brand-hover` toma
   a mao nos tokens. `color-mix` ja e usado em MainLayout/DetalheCompliance nesta base.

   SEM `--bs-btn-focus-shadow-rgb` DE PROPOSITO, e isto e uma limitacao conhecida: so a marca
   tem token `-rgb` no sgsi-tokens.css, e criar `--sgsi-color-danger-rgb` exigiria mexer na
   fonte canonica de tokens, que nao pertence a esta passagem. O halo de foco desses dois
   segue no azul do Bootstrap. */
.btn-danger {
    --bs-btn-bg: var(--sgsi-color-danger);
    --bs-btn-border-color: var(--sgsi-color-danger);
    --bs-btn-color: var(--sgsi-color-text-on-accent);
    --bs-btn-hover-bg: color-mix(in srgb, var(--sgsi-color-danger) 85%, var(--sgsi-color-text));
    --bs-btn-hover-border-color: color-mix(in srgb, var(--sgsi-color-danger) 85%, var(--sgsi-color-text));
    --bs-btn-hover-color: var(--sgsi-color-text-on-accent);
    --bs-btn-active-bg: color-mix(in srgb, var(--sgsi-color-danger) 75%, var(--sgsi-color-text));
    --bs-btn-active-border-color: color-mix(in srgb, var(--sgsi-color-danger) 75%, var(--sgsi-color-text));
    --bs-btn-active-color: var(--sgsi-color-text-on-accent);
    --bs-btn-disabled-bg: var(--sgsi-color-danger);
    --bs-btn-disabled-border-color: var(--sgsi-color-danger);
    --bs-btn-disabled-color: var(--sgsi-color-text-on-accent);
}

.btn-success {
    --bs-btn-bg: var(--sgsi-color-success);
    --bs-btn-border-color: var(--sgsi-color-success);
    --bs-btn-color: var(--sgsi-color-text-on-accent);
    --bs-btn-hover-bg: color-mix(in srgb, var(--sgsi-color-success) 85%, var(--sgsi-color-text));
    --bs-btn-hover-border-color: color-mix(in srgb, var(--sgsi-color-success) 85%, var(--sgsi-color-text));
    --bs-btn-hover-color: var(--sgsi-color-text-on-accent);
    --bs-btn-active-bg: color-mix(in srgb, var(--sgsi-color-success) 75%, var(--sgsi-color-text));
    --bs-btn-active-border-color: color-mix(in srgb, var(--sgsi-color-success) 75%, var(--sgsi-color-text));
    --bs-btn-active-color: var(--sgsi-color-text-on-accent);
    --bs-btn-disabled-bg: var(--sgsi-color-success);
    --bs-btn-disabled-border-color: var(--sgsi-color-success);
    --bs-btn-disabled-color: var(--sgsi-color-text-on-accent);
}

/* AS QUATRO VARIANTES DE ESTADO — e aqui o buraco era MUITO maior (DS-921, 2a medicao).
   A regua nova (DesignSystemTokensGuardrailTests) acusou danger/info/success/warning, que o primeiro
   conserto nao tinha visto. Razoes de contraste CALCULADAS sobre o fundo do tema CLARO (#f4f6f9):

       variante   cor de fabrica   razao      token do DS   razao
       warning    #ffc107          1.51:1     #8a5a00       5.47:1
       info       #0dcaf0          1.81:1     #0f5e8f       6.43:1
       danger     #dc3545          4.18:1     #b3261e       6.04:1
       success    #198754          4.18:1     #1b7a3e       4.97:1

   O amarelo a 1.51:1 e o ciano a 1.81:1 nao sao "abaixo do limiar": sao ILEGIVEIS — amarelo de
   fabrica sobre um fundo quase branco. No tema ESCURO o retrato inverte (danger e success e que
   reprovam, a 3.99:1), o que confirma que a cor FIXA nunca ia servir aos dois temas: e o token que
   tem de virar com o tema, e ele ja virava — so nao chegava ate o botao.

   O :hover usa --sgsi-color-text-on-accent (#ffffff no claro, #07172a no escuro) porque com o fundo
   pintado da cor de estado o texto precisa do par legivel de CADA tema; o `#fff` fixo do Bootstrap
   ficaria ilegivel sobre o amarelo claro e o vermelho claro do tema escuro. */
.btn-outline-danger {
    --bs-btn-color: var(--sgsi-color-danger);
    --bs-btn-border-color: var(--sgsi-color-danger);
    --bs-btn-hover-color: var(--sgsi-color-text-on-accent);
    --bs-btn-hover-bg: var(--sgsi-color-danger);
    --bs-btn-hover-border-color: var(--sgsi-color-danger);
    --bs-btn-active-color: var(--sgsi-color-text-on-accent);
    --bs-btn-active-bg: var(--sgsi-color-danger);
    --bs-btn-active-border-color: var(--sgsi-color-danger);
    --bs-btn-disabled-color: var(--sgsi-color-danger);
    --bs-btn-disabled-border-color: var(--sgsi-color-danger);
}

.btn-outline-success {
    --bs-btn-color: var(--sgsi-color-success);
    --bs-btn-border-color: var(--sgsi-color-success);
    --bs-btn-hover-color: var(--sgsi-color-text-on-accent);
    --bs-btn-hover-bg: var(--sgsi-color-success);
    --bs-btn-hover-border-color: var(--sgsi-color-success);
    --bs-btn-active-color: var(--sgsi-color-text-on-accent);
    --bs-btn-active-bg: var(--sgsi-color-success);
    --bs-btn-active-border-color: var(--sgsi-color-success);
    --bs-btn-disabled-color: var(--sgsi-color-success);
    --bs-btn-disabled-border-color: var(--sgsi-color-success);
}

.btn-outline-warning {
    --bs-btn-color: var(--sgsi-color-warning);
    --bs-btn-border-color: var(--sgsi-color-warning);
    --bs-btn-hover-color: var(--sgsi-color-text-on-accent);
    --bs-btn-hover-bg: var(--sgsi-color-warning);
    --bs-btn-hover-border-color: var(--sgsi-color-warning);
    --bs-btn-active-color: var(--sgsi-color-text-on-accent);
    --bs-btn-active-bg: var(--sgsi-color-warning);
    --bs-btn-active-border-color: var(--sgsi-color-warning);
    --bs-btn-disabled-color: var(--sgsi-color-warning);
    --bs-btn-disabled-border-color: var(--sgsi-color-warning);
}

.btn-outline-info {
    --bs-btn-color: var(--sgsi-color-info);
    --bs-btn-border-color: var(--sgsi-color-info);
    --bs-btn-hover-color: var(--sgsi-color-text-on-accent);
    --bs-btn-hover-bg: var(--sgsi-color-info);
    --bs-btn-hover-border-color: var(--sgsi-color-info);
    --bs-btn-active-color: var(--sgsi-color-text-on-accent);
    --bs-btn-active-bg: var(--sgsi-color-info);
    --bs-btn-active-border-color: var(--sgsi-color-info);
    --bs-btn-disabled-color: var(--sgsi-color-info);
    --bs-btn-disabled-border-color: var(--sgsi-color-info);
}

.btn-outline-secondary {
    --bs-btn-color: var(--sgsi-color-text-muted);
    --bs-btn-border-color: var(--sgsi-color-border-strong);
    --bs-btn-hover-color: var(--sgsi-color-text);
    --bs-btn-hover-bg: var(--sgsi-color-surface-hover);
    --bs-btn-hover-border-color: var(--sgsi-color-text-muted);
    --bs-btn-active-color: var(--sgsi-color-text);
    --bs-btn-active-bg: var(--sgsi-color-surface-hover);
    --bs-btn-active-border-color: var(--sgsi-color-text-muted);
    --bs-btn-disabled-color: var(--sgsi-color-text-subtle);
    --bs-btn-disabled-border-color: var(--sgsi-color-border);
}

/* ==========================================================================
   CARD
   ========================================================================== */
/* ---- DENSIDADE DO CARTAO (30/08) --------------------------------------------
   MEDIDO, depois de o dono dizer "os cards gigantes": o corpo usa 1.5rem (24px) e o
   cabecalho 1rem/1.5rem, sobre uma raiz de 16px. Sao ~88px de CROMO VERTICAL antes de
   qualquer conteudo, num produto cuja tela util e uma tabela de controles. Dashboards
   densos (Linear, Stripe, Datadog) e os concorrentes diretos (Vanta, Drata) trabalham
   com 12-16px e fonte base de 13-14px.

   E havia TRES variantes de cartao, TODAS de cor (acento marca/sucesso/perigo) e
   NENHUMA de densidade — entao os 1.056 usos de SgsiCard herdavam o mesmo padding,
   inclusive os que carregam UMA metrica.

   O PADDING VIRA TOKEN E O PADRAO NAO MUDA nesta passagem. Trocar 24px por 16px em
   1.056 usos sem ver o resultado seria o erro que esta base ja registrou duas vezes:
   concluir pela leitura do codigo em vez de medir o que a tela mostra. Com o token, a
   mudanca global vira UMA linha — aplicavel depois da verificacao no navegador e das
   medidas por tela que a auditoria de UX esta levantando.

   `--compacto` fica disponivel desde ja para a tela que precisar. */
.sgsi-card {
    --sgsi-card-padding: var(--sgsi-space-5);
    --sgsi-card-padding-cab-y: var(--sgsi-space-4);
    --sgsi-card-padding-cab-x: var(--sgsi-space-5);

    background: var(--sgsi-color-surface);
    border: 1px solid var(--sgsi-color-border);
    border-radius: var(--sgsi-radius-lg);
    box-shadow: var(--sgsi-shadow-sm);
    overflow: hidden;
}

/* Densidade alta: 1rem no corpo e 0.75rem/1rem no cabecalho — 40px de cromo, contra 88px.
   Para painel de metrica, lista e qualquer tela onde o dado importa mais que a moldura. */
.sgsi-card--compacto {
    --sgsi-card-padding: var(--sgsi-space-4);
    --sgsi-card-padding-cab-y: var(--sgsi-space-3);
    --sgsi-card-padding-cab-x: var(--sgsi-space-4);
}

/* ---- Faixa de acento no cartão (BAI-1099/BAI-1100) --------------------------
   POR QUE ESTAS TRÊS REGRAS MORAM AQUI, E NÃO NO CSS ISOLADO DE CADA PÁGINA.
   O acento é aplicado ao SgsiCard por `Classe="…"`, e CSS isolado NÃO alcança
   componente filho: o compilador Razor carimba o atributo de escopo (b-xxxxx) nos
   elementos do markup DA PÁGINA, e o <section class="sgsi-card @Classe"> pertence ao
   escopo do SgsiCard. O seletor `.sgsi-comece-feito[b-mgkvheciqv]` gerado a partir de
   ComeceAqui.razor.css não casava com elemento nenhum — a borda simplesmente nunca
   pintava, em silêncio, e a mesma armadilha tinha pegado PainelProntidao.razor.css.
   `::deep` também não resolvia nestes dois casos: ele precisa de um ANCESTRAL no markup
   da própria página, e os cartões são filhos diretos do ChildContent do SgsiPagina.
   Modificador do componente pertence à folha do componente — é a única casa em que ele
   funciona, e assim serve a qualquer página que precise do mesmo acento.

   Ordem importa: mesma especificidade de `.sgsi-card`, então a faixa tem de vir DEPOIS
   dele para vencer o `border` de 1px. */
.sgsi-card--acento-marca { border-left: 4px solid var(--sgsi-color-brand); }
.sgsi-card--acento-sucesso { border-left: 4px solid var(--sgsi-color-success); }
.sgsi-card--acento-perigo { border-left: 4px solid var(--sgsi-color-danger); }

/* ---- EIXO DE ELEVAÇÃO: o cartão RECUADO (revisão visual 01/09, §2.2) --------------------
   ── O DEFEITO ──
   Nas 51 telas-índice o bloco que FILTRA e o bloco que MOSTRA são duas lajes brancas com a
   mesma moldura, a mesma sombra e o mesmo peso visual. Não há hierarquia entre a ferramenta
   e o conteúdo: é a tradução exata de "tudo grita igual", e o olho não sabe onde pousar ao
   abrir a tela. O dono descreveu a família inteira como "distribuição nas telas não
   alinhadas"; esta é a metade que não se resolve movendo caixa de lugar.

   ── A REGRA ──
   Elevação é um EIXO, não um enfeite: quem sobe é o conteúdo, quem recua é o controle. O
   recuado troca a superfície branca pela `--sgsi-color-surface-2` (o token que o próprio
   sgsi-tokens.css já documenta como "superfície recuada", e que tem par no tema escuro) e
   ZERA a sombra. A borda fica: sem ela o bloco perderia o contorno contra o fundo da app,
   que também é acinzentado — recuar não é sumir.

   ── POR QUE OS TRÊS SELETORES JUNTOS ──
   `.sgsi-card--recuado` é o modificador nomeado, que o SgsiBarraFiltros emite e que qualquer
   bloco recuado futuro pode usar. As outras duas são as classes do cartão de filtro que já
   existiam: `.sgsi-filtros-card` (a barra canônica, 50 telas) e `.sgsi-risco-filtros-card`
   (o gabarito legado, 3 telas ainda sem migrar). Listá-las aqui é o que faz a regra alcançar
   as 53 telas SEM abrir 53 arquivos — e é justamente o que o documento pede: regra que
   precisa ser repetida em cada tela já nasce divergindo.

   ── ORDEM IMPORTA, PELO MESMO MOTIVO DA FAIXA DE ACENTO ACIMA ──
   Especificidade IDÊNTICA à de `.sgsi-card` (uma classe). Este bloco só vence o
   `background`/`box-shadow` de lá porque vem DEPOIS na folha. Movido para cima, ele
   continuaria compilando, continuaria casando o elemento e não pintaria nada — o modo de
   falhar mais silencioso que existe em CSS, e a razão de a catraca
   EixoDeElevacaoDoCartaoDeFiltroTests medir a POSIÇÃO e não só a existência da regra. */
.sgsi-card--recuado,
.sgsi-filtros-card,
.sgsi-risco-filtros-card {
    background: var(--sgsi-color-surface-recuada);
    box-shadow: none;
}
/* QUEBRA DE LINHA NO CABEÇALHO (28/09): título e ações lado a lado, sem wrap, faziam um card com
   duas ações longas estourar a largura no celular — em 375 px o 2º botão do enquadramento da
   serventia ficava cortado pela borda do card. Com wrap, as ações descem para baixo do título SÓ
   quando não cabem; onde cabem (desktop), nada muda. */
.sgsi-card__cab {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--sgsi-space-3);
    padding: var(--sgsi-card-padding-cab-y) var(--sgsi-card-padding-cab-x);
    border-bottom: 1px solid var(--sgsi-color-border);
}
.sgsi-card__cab-titulo { display: flex; align-items: center; gap: var(--sgsi-space-2); min-width: 0; flex-wrap: wrap; }
/* MED-402 — o wrapper existe SÓ para carregar o id do aria-labelledby do card (o slot
   Cabecalho não tinha nenhum elemento com esse id e a referência ficava quebrada).
   `display: contents` mantém os filhos como itens diretos do flex acima: o layout dos três
   call-sites (BuscaGlobal, SecoesManual, PaginaApetiteRisco) fica idêntico. */
.sgsi-card__cab-custom { display: contents; }
.sgsi-card__icone { color: var(--sgsi-color-brand); display: inline-flex; }
.sgsi-card__titulo {
    margin: 0;
    font-size: var(--sgsi-font-size-lg);
    font-weight: var(--sgsi-font-weight-semibold);
}
.sgsi-card__subtitulo {
    margin: 0;
    flex-basis: 100%;
    font-size: var(--sgsi-font-size-sm);
    color: var(--sgsi-color-text-muted);
}
.sgsi-card__acoes { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sgsi-space-2); flex: 0 1 auto; max-width: 100%; }
.sgsi-card__corpo { padding: var(--sgsi-card-padding); }
.sgsi-card__corpo--flush { padding: 0; }
.sgsi-card__rodape {
    padding: var(--sgsi-space-3) var(--sgsi-space-5);
    border-top: 1px solid var(--sgsi-color-border);
    background: var(--sgsi-color-surface-2);
}

/* ==========================================================================
   BREADCRUMB (reaproveita o estilo do shell se houver; estilo standalone aqui)
   ========================================================================== */
.sgsi-breadcrumb ol {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--sgsi-space-2);
    margin: 0;
    padding: 0;
    list-style: none;
    font-size: var(--sgsi-font-size-sm);
}
.sgsi-breadcrumb li { display: flex; align-items: center; gap: var(--sgsi-space-2); }
.sgsi-breadcrumb li + li::before {
    content: "/";
    color: var(--sgsi-color-text-subtle);
}
.sgsi-breadcrumb a { color: var(--sgsi-color-text-muted); }
.sgsi-breadcrumb a:hover { color: var(--sgsi-color-accent); text-decoration: underline; }
.sgsi-breadcrumb [aria-current="page"] { color: var(--sgsi-color-text); font-weight: var(--sgsi-font-weight-medium); }

/* ==========================================================================
   PAGINADOR
   ========================================================================== */
.sgsi-paginador {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: var(--sgsi-space-3);
}
.sgsi-paginador__resumo { font-size: var(--sgsi-font-size-sm); color: var(--sgsi-color-text-muted); }
.sgsi-paginador__lista { display: flex; align-items: center; gap: var(--sgsi-space-1); margin: 0; padding: 0; list-style: none; }
.sgsi-paginador__btn {
    min-width: 2.25rem;
    height: 2.25rem;
    padding: 0 var(--sgsi-space-2);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: 1px solid var(--sgsi-color-border);
    border-radius: var(--sgsi-radius-md);
    background: var(--sgsi-color-surface);
    color: var(--sgsi-color-text);
    font-size: var(--sgsi-font-size-sm);
    cursor: pointer;
    transition: background var(--sgsi-transition-fast), border-color var(--sgsi-transition-fast);
}
.sgsi-paginador__btn:hover:not(:disabled) { background: var(--sgsi-color-surface-2); border-color: var(--sgsi-color-border-strong); }
.sgsi-paginador__btn:disabled { opacity: 0.5; cursor: not-allowed; }
.sgsi-paginador__btn--atual {
    background: var(--sgsi-color-brand);
    border-color: var(--sgsi-color-brand);
    color: var(--sgsi-color-on-brand);
    font-weight: var(--sgsi-font-weight-semibold);
}
.sgsi-paginador__elipse { padding: 0 var(--sgsi-space-1); color: var(--sgsi-color-text-subtle); }

/* ==========================================================================
   TOAST
   ========================================================================== */
.sgsi-toast-host {
    position: fixed;
    top: calc(var(--sgsi-topbar-height) + var(--sgsi-space-3));
    right: var(--sgsi-space-4);
    z-index: var(--sgsi-z-toast);
    display: flex;
    flex-direction: column;
    gap: var(--sgsi-space-2);
    max-width: min(24rem, calc(100vw - 2 * var(--sgsi-space-4)));
    pointer-events: none;
}
.sgsi-toast {
    pointer-events: auto;
    display: flex;
    align-items: flex-start;
    gap: var(--sgsi-space-3);
    padding: var(--sgsi-space-3) var(--sgsi-space-4);
    background: var(--sgsi-color-surface);
    border: 1px solid var(--sgsi-color-border);
    border-left-width: 4px;
    border-radius: var(--sgsi-radius-md);
    box-shadow: var(--sgsi-shadow-md);
    animation: sgsi-toast-in var(--sgsi-transition) ease;
}
@keyframes sgsi-toast-in {
    from { opacity: 0; transform: translateY(-0.5rem); }
    to { opacity: 1; transform: translateY(0); }
}
.sgsi-toast__icone { flex: 0 0 auto; margin-top: 0.1rem; }
.sgsi-toast__corpo { flex: 1 1 auto; min-width: 0; }
.sgsi-toast__titulo { margin: 0 0 0.1rem; font-weight: var(--sgsi-font-weight-semibold); font-size: var(--sgsi-font-size-sm); }
.sgsi-toast__msg { margin: 0; font-size: var(--sgsi-font-size-sm); color: var(--sgsi-color-text-muted); overflow-wrap: anywhere; }
.sgsi-toast__fechar {
    flex: 0 0 auto;
    border: 0;
    background: transparent;
    color: var(--sgsi-color-text-subtle);
    font-size: 1.25rem;
    line-height: 1;
    cursor: pointer;
    padding: 0 var(--sgsi-space-1);
}
.sgsi-toast__fechar:hover { color: var(--sgsi-color-text); }
.sgsi-toast--sucesso { border-left-color: var(--sgsi-color-success); }
.sgsi-toast--sucesso .sgsi-toast__icone { color: var(--sgsi-color-success); }
.sgsi-toast--erro { border-left-color: var(--sgsi-color-danger); }
.sgsi-toast--erro .sgsi-toast__icone { color: var(--sgsi-color-danger); }
.sgsi-toast--aviso { border-left-color: var(--sgsi-color-warning); }
.sgsi-toast--aviso .sgsi-toast__icone { color: var(--sgsi-color-warning); }
.sgsi-toast--info { border-left-color: var(--sgsi-color-info); }
.sgsi-toast--info .sgsi-toast__icone { color: var(--sgsi-color-info); }

/* ==========================================================================
   MODAL (<dialog> nativo)
   ========================================================================== */
.sgsi-modal {
    padding: 0;
    border: 1px solid var(--sgsi-color-border);
    border-radius: var(--sgsi-radius-lg);
    background: var(--sgsi-color-surface);
    color: var(--sgsi-color-text);
    box-shadow: var(--sgsi-shadow-lg);
    width: min(100%, 34rem);
    max-width: calc(100vw - 2 * var(--sgsi-space-4));
    max-height: calc(100vh - 2 * var(--sgsi-space-6));
}
.sgsi-modal--sm { width: min(100%, 26rem); }
/* O `md` é o padrão do SgsiModal (Tamanho="md") e repete de propósito a largura da
   regra base: sem esta linha a classe `.sgsi-modal--md` existia no DOM de ~290 modais
   sem regra nenhuma, e quem fosse ajustar a largura média procuraria o seletor, não
   acharia, e concluiria que o tamanho médio não é ajustável por aqui. */
.sgsi-modal--md { width: min(100%, 34rem); }
.sgsi-modal--lg { width: min(100%, 52rem); }
.sgsi-modal--xl { width: min(100%, 64rem); }
.sgsi-modal::backdrop { background: var(--sgsi-color-backdrop); backdrop-filter: blur(2px); }
.sgsi-modal[open] { animation: sgsi-modal-in var(--sgsi-transition) ease; }
@keyframes sgsi-modal-in {
    from { opacity: 0; transform: translateY(0.5rem) scale(0.99); }
    to { opacity: 1; transform: translateY(0) scale(1); }
}
.sgsi-modal__cab {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sgsi-space-3);
    padding: var(--sgsi-space-4) var(--sgsi-space-5);
    border-bottom: 1px solid var(--sgsi-color-border);
}
.sgsi-modal__titulo { margin: 0; font-size: var(--sgsi-font-size-lg); font-weight: var(--sgsi-font-weight-semibold); }
.sgsi-modal__fechar {
    border: 0;
    background: transparent;
    color: var(--sgsi-color-text-subtle);
    font-size: 1.5rem;
    line-height: 1;
    cursor: pointer;
    padding: 0 var(--sgsi-space-1);
}
.sgsi-modal__fechar:hover { color: var(--sgsi-color-text); }
.sgsi-modal__corpo { padding: var(--sgsi-space-5); overflow-y: auto; }
.sgsi-modal__rodape {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: var(--sgsi-space-2);
    padding: var(--sgsi-space-3) var(--sgsi-space-5);
    border-top: 1px solid var(--sgsi-color-border);
    background: var(--sgsi-color-surface-2);
}
.sgsi-confirm__msg { margin: 0; }
.sgsi-confirm__detalhe {
    margin-top: var(--sgsi-space-3);
    padding: var(--sgsi-space-2) var(--sgsi-space-3);
    background: var(--sgsi-color-surface-2);
    border-radius: var(--sgsi-radius-md);
    font-weight: var(--sgsi-font-weight-medium);
}

/* ==========================================================================
   FORM / FIELD
   ========================================================================== */
.sgsi-form { display: flex; flex-direction: column; gap: var(--sgsi-space-4); }
.sgsi-form__acoes {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: var(--sgsi-space-2);
    margin-top: var(--sgsi-space-2);
}
/* ── O RODAPÉ DO FORMULÁRIO NÃO ROLA COM O CORPO DO MODAL (auditoria UX 20/09) ──
   O SgsiForm renderiza as ações DENTRO do EditForm, que vive em `.sgsi-modal__corpo`
   (overflow-y:auto); só 44 dos 295 modais usam o <Rodape> fixo. Medido em 13 capturas a 860px:
   Salvar/Cancelar fora da dobra em todo cadastro de 8+ campos. Sticky no fundo do scrollport, com
   as margens negativas devolvendo o padding do corpo para que a barra encoste nas bordas — o
   mesmo desenho visual do `.sgsi-modal__rodape`. Fora de modal nada muda. */
.sgsi-modal__corpo .sgsi-form__acoes {
    position: sticky;
    bottom: calc(-1 * var(--sgsi-space-5));
    z-index: 1;
    margin: var(--sgsi-space-2) calc(-1 * var(--sgsi-space-5)) calc(-1 * var(--sgsi-space-5));
    padding: var(--sgsi-space-3) var(--sgsi-space-5);
    background: var(--sgsi-color-surface);
    border-top: 1px solid var(--sgsi-color-border);
}
.sgsi-field { display: flex; flex-direction: column; gap: var(--sgsi-space-1); position: relative; }
.sgsi-field__label {
    font-size: var(--sgsi-font-size-sm);
    font-weight: var(--sgsi-font-weight-medium);
    color: var(--sgsi-color-text);
}
.sgsi-field__obrig { color: var(--sgsi-color-danger); margin-left: 0.15rem; }
.sgsi-field__dica { margin: 0; font-size: var(--sgsi-font-size-xs); color: var(--sgsi-color-text-muted); }

/* ── "COMO PREENCHER" (16/09) — guia de preenchimento dentro do próprio campo ──
   Letra em font-size-sm/md e NÃO no xs da dica: quem abre este painel é quem está parado diante do
   campo, muitas vezes lendo devagar. Cores só por token — o tema escuro redefine os tokens, então
   nada aqui precisa de regra própria para o escuro.

   O GATILHO MORA NA LINHA DO RÓTULO, NÃO NUMA LINHA PRÓPRIA (auditoria UX 20/09). O <summary> de
   44px de altura entre o rótulo e o controle custava ~120-155px por campo nas capturas, e num
   modal de 8 campos o botão de salvar saía da dobra. Agora ele é um "?" de 1.75rem posicionado no
   canto direito da linha do rótulo (`.sgsi-field` é `position:relative`); o <details> fechado não
   tem altura em fluxo, e a margem negativa cancela o gap do campo que sobraria. Aberto, o painel
   desce em fluxo entre o rótulo e o controle — o mesmo lugar de antes. 28px de alvo cumprem o
   mínimo AA (WCAG 2.5.8, 24px); o 44px AAA de antes era o que roubava a linha. `:has()` cobre os
   ~250 controles montados à mão (label + GuiaDeCampo crus) que não passam pelo SgsiField. */
.sgsi-field__guia { margin: 0; }
.sgsi-field__guia:not([open]) { margin-top: calc(-1 * var(--sgsi-space-1)); }
.sgsi-field--com-guia > .sgsi-field__label,
.sgsi-field:has(> .sgsi-field__guia) > .sgsi-field__label { padding-right: 2rem; }
.sgsi-field__guia-abrir {
    position: absolute;
    top: 0;
    right: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.75rem;
    height: 1.75rem;
    margin-top: -0.25rem;
    list-style: none;
    cursor: pointer;
    color: var(--sgsi-color-brand);
    border-radius: var(--sgsi-radius-sm);
}
.sgsi-field__guia[open] > .sgsi-field__guia-abrir { background: var(--sgsi-color-surface-2); }
.sgsi-field__guia-abrir::-webkit-details-marker { display: none; }
.sgsi-field__guia-abrir:hover { background: var(--sgsi-color-surface-2); }
.sgsi-field__guia-abrir:focus-visible { outline: 2px solid var(--sgsi-color-brand); outline-offset: 2px; }
.sgsi-field__guia-corpo {
    margin-top: var(--sgsi-space-1);
    padding: var(--sgsi-space-3);
    background: var(--sgsi-color-surface-2);
    border: 1px solid var(--sgsi-color-border);
    border-left: 3px solid var(--sgsi-color-brand);
    border-radius: var(--sgsi-radius-md);
    font-size: var(--sgsi-font-size-md);
    line-height: 1.55;
    color: var(--sgsi-color-text);
}
.sgsi-field__guia-corpo p { margin: 0 0 var(--sgsi-space-2); }
.sgsi-field__guia-corpo p:last-child { margin-bottom: 0; }
.sgsi-field__guia-corpo strong { display: block; font-size: var(--sgsi-font-size-sm); color: var(--sgsi-color-text-muted); }

/* ── BARRA DO ROTEIRO (16/09; uma linha desde 20/09) — a jornada acompanha o usuário ──
   Fica acima do conteúdo, sem roubar a cena: fundo recuado, borda de marca à esquerda e UMA linha
   de ~40px (contagem + trilho + "Próxima etapa: X" + os dois links). A versão anterior tinha quatro
   linhas de prosa e botões de 44px: ~133px em toda página, medido nas capturas de 20/09, com um
   primário próprio disputando com o da tela. O texto do que falta abre por um toggle, lembrado no
   navegador. Em tela estreita o passo quebra para a linha de baixo em vez de espremer. */
.sgsi-roteiro {
    display: flex;
    flex-direction: column;
    gap: var(--sgsi-space-1);
    margin-bottom: var(--sgsi-space-2);
    padding: var(--sgsi-space-1) var(--sgsi-space-3);
    background: var(--sgsi-color-surface-2);
    border: 1px solid var(--sgsi-color-border);
    border-left: 4px solid var(--sgsi-color-brand);
    border-radius: var(--sgsi-radius-md);
    color: var(--sgsi-color-text);
}
.sgsi-roteiro__linha {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--sgsi-space-1) var(--sgsi-space-3);
    min-height: 2rem;
}
.sgsi-roteiro__progresso { display: inline-flex; align-items: center; gap: var(--sgsi-space-2); flex: 0 0 auto; }
.sgsi-roteiro__contagem { font-size: var(--sgsi-font-size-xs); color: var(--sgsi-color-text-muted); white-space: nowrap; }
.sgsi-roteiro__trilho {
    display: block;
    width: 5rem;
    height: 4px;
    background: var(--sgsi-color-border);
    border-radius: 999px;
    overflow: hidden;
}
.sgsi-roteiro__preenchido { display: block; height: 100%; background: var(--sgsi-color-brand); }
.sgsi-roteiro__passo {
    flex: 1 1 12rem;
    min-width: 0;
    margin: 0;
    font-size: var(--sgsi-font-size-sm);
    line-height: 1.4;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.sgsi-roteiro__modulo { font-weight: 600; margin-inline-start: var(--sgsi-space-1); }
.sgsi-roteiro__falta { margin: 0 0 var(--sgsi-space-1); font-size: var(--sgsi-font-size-sm); color: var(--sgsi-color-text-muted); }
.sgsi-roteiro__acoes { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sgsi-space-1); }
.sgsi-roteiro__alternar {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.75rem;
    height: 1.75rem;
    border: 0;
    background: transparent;
    color: var(--sgsi-color-text-muted);
    border-radius: var(--sgsi-radius-sm);
    cursor: pointer;
    transition: transform var(--sgsi-transition-fast), background var(--sgsi-transition-fast);
}
.sgsi-roteiro__alternar:hover { background: var(--sgsi-color-surface); color: var(--sgsi-color-text); }
.sgsi-roteiro__alternar:focus-visible { outline: var(--sgsi-focus-ring-width) solid var(--sgsi-color-brand); outline-offset: 2px; }
.sgsi-roteiro__alternar[aria-expanded="true"] { transform: rotate(180deg); }
@media (max-width: 600px) {
    .sgsi-roteiro__passo { flex-basis: 100%; white-space: normal; }
}
.sgsi-field__erro .validation-message,
.sgsi-field__erro .invalid-feedback {
    display: block;
    margin-top: 0.1rem;
    font-size: var(--sgsi-font-size-xs);
    color: var(--sgsi-color-danger);
}
.sgsi-field .invalid { border-color: var(--sgsi-color-danger); }

/* ==========================================================================
   LARGURA SEMÂNTICA DE CAMPO — o segundo eixo (revisão visual 01/09, §2.3/§2.4)
   ==========================================================================

   ── O DEFEITO ──
   O produto tem UM eixo de largura: a coluna da grade. Ela responde "quanto espaço o campo
   ocupa no layout" e não tem como responder "quanto se espera que o usuário escreva" — a
   mesma coluna de `.sgsi-form-grade` hospeda um CNPJ e a justificativa de um risco. Sem o
   segundo eixo, todo controle estica até o fim da coluna, e o MESMO dado sai com largura
   diferente em cada tela: 547 campos, 53 nomes de propriedade repetidos, 178 arquivos.
   Largura é dica visual; dar 384px a um campo de data (a MEDIANA medida em 156 deles) não
   é só feio, é enganoso — promete texto livre onde só cabem dez caracteres.

   ── COMO O EIXO FUNCIONA ──
   As classes `.sgsi-largura-*` NÃO carimbam largura: elas só apontam a custom property
   `--sgsi-campo-largura`. Quem CONSOME são os invólucros de controle abaixo. Isso é o que
   deixa a mesma classe servir em três alturas diferentes da árvore, com um mental model só:
     · no SgsiField  (`<SgsiField Classe="sgsi-largura-data">`) → recorta o CONTROLE e deixa
       o rótulo e a dica livres para ocupar a coluna inteira (rótulo espremido a 9rem quebra
       em três linhas e o conserto viraria um defeito novo);
     · no item da barra de filtros ou no `.sgsi-campo` avulso → recorta a célula;
     · direto no `<input class="form-control sgsi-largura-codigo">` → recorta o controle.
   Um `fieldset` com a classe recorta todos os campos de dentro de uma vez: a custom property
   é herdada, e é isso que faz disto um EIXO e não cinco utilitários soltos.

   ── SÃO MAX-WIDTHS, E ISSO NÃO É DETALHE ──
   `width` fixo daria ao campo um PISO: dentro de uma coluna estreita ele deixaria de caber e
   a tela voltaria a rolar na horizontal — exatamente a família de defeito que a §2.1b acabou
   de tirar de 17 grades. `max-width` só encolhe: o campo continua acompanhando a coluna
   quando a coluna é menor que o degrau.

   ── ADITIVO POR CONSTRUÇÃO ──
   O padrão `--sgsi-campo-largura: 100%` (sgsi-tokens.css) faz TODOS os consumidores abaixo
   nascerem inertes: `max-width: 100%` é o comportamento de hoje. Nenhuma tela muda até
   escolher um degrau. Foi a mesma decisão da `.sgsi-grade` na §2.1 e pela mesma razão —
   quais dos 547 campos ficam melhores em qual degrau é pergunta de tela, e não foi medida.
   ========================================================================== */
.sgsi-field__controle,
.sgsi-filtros__item,
.sgsi-campo,
input.form-control,
select.form-select {
    max-width: var(--sgsi-campo-largura);
}
/* O <textarea> fica FORA do eixo de propósito. Ele é o controle de "texto longo" por
   definição — nenhum degrau menor faz sentido nele —, e `max-width` limitaria o ARRASTO do
   canto de redimensionar, que é do usuário e não do design system. Herdar a custom property
   de um fieldset marcado `.sgsi-largura-codigo` espremeria a justificativa de um risco a
   9rem: o eixo tem de alcançar o campo curto sem estragar o campo longo que mora ao lado. */

.sgsi-largura-codigo       { --sgsi-campo-largura: var(--sgsi-campo-largura-codigo); }
.sgsi-largura-data         { --sgsi-campo-largura: var(--sgsi-campo-largura-data); }
.sgsi-largura-valor        { --sgsi-campo-largura: var(--sgsi-campo-largura-valor); }
.sgsi-largura-texto-curto  { --sgsi-campo-largura: var(--sgsi-campo-largura-texto-curto); }
.sgsi-largura-texto-longo  { --sgsi-campo-largura: var(--sgsi-campo-largura-texto-longo); }

/* ---- §2.4 DATA E NÚMERO NÃO SÃO TEXTO LIVRE ---------------------------------------------
   Os dois únicos tipos de input cujo conteúdo máximo o NAVEGADOR conhece: `date` desenha
   "dd/mm/aaaa" mais o ícone do seletor nativo e nunca mais que isso; `number` aceita dígitos
   e um separador. Todo o resto é texto, e texto depende do domínio — por isso só estes dois
   ganham teto por TIPO, sem a tela pedir. São 241 campos em 146 arquivos, e nenhum deles
   precisou ser aberto.

   VENCE O EIXO SEMÂNTICO DE PROPÓSITO (0-2-1 contra os 0-1-1 da regra acima): pôr
   `.sgsi-largura-texto-longo` num campo de data é justamente o engano que a regra existe
   para impedir — data não vira texto livre por decisão de tela. Para uma data que precise
   de outro teto, o caminho é mudar o degrau `--sgsi-campo-largura-data` no design system,
   onde a mudança vale para as 241 de uma vez.

   `.form-control` no seletor (e não só `[type=date]`) mantém o alcance dentro do produto:
   um input sem a classe do design system não passa por aqui — e não deveria passar, porque
   ele também não recebe nenhuma das outras regras de campo. */
input.form-control[type="date"] { max-width: var(--sgsi-campo-largura-data); }
input.form-control[type="number"] { max-width: var(--sgsi-campo-largura-valor); }

/* ==========================================================================
   PÁGINA (wrapper)
   ========================================================================== */
.sgsi-pagina { display: flex; flex-direction: column; gap: var(--sgsi-space-4); }
.sgsi-pagina__breadcrumb { margin-bottom: calc(-1 * var(--sgsi-space-2)); }
.sgsi-pagina__cab {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--sgsi-space-4);
    flex-wrap: wrap;
}
.sgsi-pagina__cab-texto { min-width: 0; }
.sgsi-pagina__titulo { margin: 0; font-size: var(--sgsi-font-size-2xl); font-weight: var(--sgsi-font-weight-bold); }
/* Descrição em NO MÁXIMO DUAS LINHAS (auditoria UX 20/09): dez telas de detalhe passavam a
   `Descricao` livre da entidade (até 4.000 caracteres) para cá, e o cabeçalho virava um parágrafo
   que empurrava a barra de ações e os cartões. O texto integral fica no `title` (SgsiPagina) e no
   cartão da ficha; o cabeçalho diz o que identifica a tela. */
.sgsi-pagina__descricao {
    margin: var(--sgsi-space-1) 0 0;
    color: var(--sgsi-color-text-muted);
    max-width: 60ch;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
.sgsi-pagina__acoes { display: flex; align-items: center; gap: var(--sgsi-space-2); flex-wrap: wrap; }
.sgsi-pagina__corpo { display: flex; flex-direction: column; gap: var(--sgsi-space-5); }

/* ── MENU "MAIS AÇÕES" (auditoria UX 20/09) ──
   <details> nativo posicionado como menu: o gatilho tem a cara de um botão secundário de contorno
   (mesmos tokens do .btn-outline-secondary), e o painel abre à direita, por cima do conteúdo. Os
   itens são SgsiBotao comuns que a folha redesenha como linhas de menu — largura inteira, sem
   moldura, destrutivos em vermelho. O sgsi-shell.js fecha ao clicar fora, ao escolher um item e
   no ESC. */
.sgsi-menu-acoes { position: relative; display: inline-block; }
.sgsi-menu-acoes__gatilho {
    display: inline-flex;
    align-items: center;
    gap: var(--sgsi-space-1);
    min-height: 2.375rem;
    padding: var(--sgsi-space-1) var(--sgsi-space-3);
    list-style: none;
    cursor: pointer;
    font-size: var(--sgsi-font-size-sm);
    font-weight: var(--sgsi-font-weight-medium);
    color: var(--sgsi-color-text);
    background: var(--sgsi-color-surface);
    border: 1px solid var(--sgsi-color-border-strong, var(--sgsi-color-border));
    border-radius: var(--sgsi-radius-md);
    user-select: none;
}
.sgsi-menu-acoes__gatilho--sm { min-height: 1.9rem; padding: 0 var(--sgsi-space-2); font-size: var(--sgsi-font-size-xs); }
.sgsi-menu-acoes__gatilho::-webkit-details-marker { display: none; }
.sgsi-menu-acoes__gatilho:hover { background: var(--sgsi-color-surface-2); }
.sgsi-menu-acoes__gatilho:focus-visible { outline: var(--sgsi-focus-ring-width) solid var(--sgsi-color-brand); outline-offset: 2px; }
.sgsi-menu-acoes[open] > .sgsi-menu-acoes__gatilho { background: var(--sgsi-color-surface-2); }
.sgsi-menu-acoes__painel {
    position: absolute;
    right: 0;
    top: calc(100% + 4px);
    z-index: 30;
    min-width: 14rem;
    padding: var(--sgsi-space-1) 0;
    background: var(--sgsi-color-surface);
    border: 1px solid var(--sgsi-color-border);
    border-radius: var(--sgsi-radius-md);
    box-shadow: var(--sgsi-shadow-lg);
    display: flex;
    flex-direction: column;
}
.sgsi-menu-acoes__painel .btn {
    display: flex;
    width: 100%;
    justify-content: flex-start;
    gap: var(--sgsi-space-2);
    border: 0;
    border-radius: 0;
    text-align: left;
    color: var(--sgsi-color-text);
    background: transparent;
    padding: var(--sgsi-space-2) var(--sgsi-space-3);
    font-size: var(--sgsi-font-size-sm);
    white-space: nowrap;
}
.sgsi-menu-acoes__painel .btn:hover:not(:disabled) { background: var(--sgsi-color-surface-2); color: var(--sgsi-color-text); }
.sgsi-menu-acoes__painel .btn:disabled { color: var(--sgsi-color-text-subtle); }
.sgsi-menu-acoes__painel .btn-danger,
.sgsi-menu-acoes__painel .btn-outline-danger { color: var(--sgsi-color-danger); }
.sgsi-menu-acoes__painel .btn-danger:hover:not(:disabled),
.sgsi-menu-acoes__painel .btn-outline-danger:hover:not(:disabled) { background: var(--sgsi-color-danger-bg); color: var(--sgsi-color-danger); }
.sgsi-menu-acoes__separador { margin: var(--sgsi-space-1) 0; border: 0; border-top: 1px solid var(--sgsi-color-border); }

/* ==========================================================================
   GRADE DE SEÇÕES — a utilidade que faltava, e que já existia dez vezes
   ==========================================================================

   ── O DEFEITO (01/09) ──
   `.sgsi-pagina__corpo` é uma COLUNA de flex: todo filho direto ocupa a largura
   inteira e empilha, sempre. Em 103 das 146 telas há dois ou mais `SgsiCard`
   ali dentro, e o resultado é a queixa literal do dono: "cards que não ficam do
   lado do outro e criam uma lista imensa". A caixa de conteúdo tem 1.136px a
   1440px de viewport — largura de sobra para duas colunas, desperdiçada.

   ── POR QUE ISTO NÃO É UMA REGRA NOVA ──
   O produto JÁ resolve isto, dez vezes, em particular: .sgsi-risco-stats,
   .sgsi-stat-linha, .sgsi-apetite-grid, .sgsi-mapa-grade, .sgsi-trust__grade,
   .sgsi-medidores, .sgsi-seletor-cliente__grade,
   .sgsi-lista-codigos e .sgsi-form-grade são todas o MESMO
   `repeat(auto-fit, minmax(X, 1fr))` — com X em dez valores diferentes
   (9rem, 14rem, 16rem, 16rem, 20rem, 180px, 200px, 280px, 300px, 320px).
   Dez autores, dez larguras, nenhuma promovida a geral. Não falta a ideia:
   falta o lugar onde ela mora uma vez só. É a mesma família da segunda lista
   que diverge em silêncio.

   ── POR QUE ADITIVA, E NÃO NO CORPO DA PÁGINA ──
   A correção "óbvia" seria dar `display: grid` ao `.sgsi-pagina__corpo`. Ela
   mexeria nas 146 telas de uma vez, incluindo as 53 que NÃO têm par de cartões
   (nada a emparelhar) e as que já embrulham o próprio conteúdo numa das dez
   grades acima — grade dentro de grade. Quantas das 93 restantes ficam MELHOR
   em duas colunas é pergunta de tela, não de folha de estilo, e não foi medida:
   por isso a utilidade é aditiva e a tela opta.

   ── align-items: start NÃO É DETALHE ──
   Sem ele, o grid estica todo cartão até a altura do mais alto, e um cartão de
   três linhas ao lado de um de trinta vira um bloco vazio gigante. É a outra
   metade da queixa do dono ("cards com tamanhos imensos") e ela NASCERIA aqui
   se esta linha faltasse: o conserto criaria o defeito que veio consertar.

   ── MEDIDA PADRÃO ──
   `min(..., 100%)` NÃO É ENFEITE — é o conserto que a dissecação de 30/08 provou
   no dashboard e que esta utilidade quase nasceu sem. Com `minmax(20rem, 1fr)`
   seco a trilha tem PISO RÍGIDO de 320px: somado ao padding do corpo da página, a
   tela passa a rolar NA HORIZONTAL abaixo de ~352px de viewport (iPhone SE de 1ª
   geração, tela externa de dobrável). Rolagem lateral é o pior sintoma possível.
   `min()` deixa a trilha encolher junto com o contêiner, sem uma única @media.

   `--sgsi-grade-min` (definido em sgsi-tokens.css) governa quando a grade desiste e
   volta a empilhar. O padrão 20rem (320px) vem da mediana das dez larguras acima, e a queda para
   coluna única é automática — nada de media query, que é o que faz as dez
   versões atuais divergirem no ponto de quebra.
   ========================================================================== */
.sgsi-grade {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(var(--sgsi-grade-min), 100%), 1fr));
    gap: var(--sgsi-space-5);
    align-items: start;
}

/* Cartões densos e pequenos (contadores, atalhos): cabem três ou quatro. */
.sgsi-grade--estreita { --sgsi-grade-min: 14rem; }

/* Blocos com tabela ou formulário dentro: duas colunas no desktop, uma antes. */
.sgsi-grade--larga { --sgsi-grade-min: 28rem; }

/* Um filho que atravessa a grade inteira (um resumo que encima duas colunas).
   `1 / -1` e não `span 2`: com auto-fit o número de colunas varia com a
   largura, e `span 2` num viewport de uma coluna só criaria uma segunda coluna
   fantasma. */
.sgsi-grade__inteira { grid-column: 1 / -1; }

/* ---- Painel de uma aba da ficha (auditoria UX 20/09, L1.3) ----
   Os cartões que saíram da grade da ficha para uma aba empilham em coluna, com o mesmo
   respiro da página; quem tinha `sgsi-grade__inteira` continua inteiro (a coluna é única). */
.sgsi-ficha-aba { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--sgsi-space-4); }
/* Âncora de um item dentro da ficha (auditoria UX 20/09, §6.3 — a lista de comunicação aponta para o
   cartão do item): a margem de rolagem evita que o cabeçalho fixo cubra o alvo. */
.sgsi-ancora-item { scroll-margin-top: 5rem; }
/* Bloco recolhível de página (auditoria UX 20/09, §6.2/§6.4): o cartão de normas da Conformidade e a prévia
   da ativação de norma nascem fechados quando não têm o que acrescentar. */
.sgsi-detalhes { border: 1px solid var(--sgsi-color-border); border-radius: var(--sgsi-radius-md); background: var(--sgsi-color-surface); }
.sgsi-detalhes > .sgsi-detalhes__resumo { cursor: pointer; padding: var(--sgsi-space-3) var(--sgsi-space-4); font-weight: 600; color: var(--sgsi-color-text); list-style: none; display: flex; align-items: center; gap: var(--sgsi-space-2); }
.sgsi-detalhes > .sgsi-detalhes__resumo::before { content: "▸"; font-size: var(--sgsi-font-size-sm); color: var(--sgsi-color-text-muted); transition: transform var(--sgsi-transition-fast); }
.sgsi-detalhes[open] > .sgsi-detalhes__resumo::before { transform: rotate(90deg); }
.sgsi-detalhes > .sgsi-detalhes__resumo::-webkit-details-marker { display: none; }
.sgsi-detalhes > :not(summary) { padding: 0 var(--sgsi-space-4) var(--sgsi-space-4); }
/* Modal EMBUTIDO numa página de criação (auditoria UX 20/09, L3.3): o formulário do modal como seção. */
.sgsi-modal-embutido { display: flex; flex-direction: column; gap: var(--sgsi-space-4); background: var(--sgsi-color-surface); border: 1px solid var(--sgsi-color-border); border-radius: var(--sgsi-radius-md); padding: var(--sgsi-space-5); max-width: 64rem; }
.sgsi-modal-embutido__titulo { margin: 0; font-size: var(--sgsi-font-size-lg); font-weight: 600; color: var(--sgsi-color-text); }
.sgsi-modal-embutido__corpo { padding: 0; }
/* Filtro dos itens de uma avaliação (Gap/Maturidade — L3.2). */
.sgsi-filtro-itens { display: flex; align-items: center; gap: var(--sgsi-space-3); flex-wrap: wrap; margin-bottom: var(--sgsi-space-3); }
.sgsi-filtro-itens__busca { max-width: 20rem; }
/* Aviso de código sugerido (L3.4). */
.sgsi-codigo-sugerido { margin: calc(-1 * var(--sgsi-space-2)) 0 0; }
/* Lista curta de registros (chips de vínculo) dentro de um modal. */
.sgsi-lista-simples { list-style: none; margin: 0 0 var(--sgsi-space-3); padding: 0; display: flex; flex-wrap: wrap; gap: var(--sgsi-space-2); }
/* Nome do papel visível no cabeçalho da matriz RASCI (era só tooltip). */
.sgsi-rasci-matriz__papel-nome { display: block; font-weight: 400; font-size: var(--sgsi-font-size-xs); color: var(--sgsi-color-text-muted); white-space: normal; }
.sgsi-ficha-aba > .sgsi-grade__inteira { grid-column: auto; }

/* Subseção: título de bloco DENTRO da página ou de um card (h2/h3). Mesma
   tipografia do .sgsi-card__titulo; o respiro vertical entre seções vem do gap
   do .sgsi-pagina__corpo (quando fora dele, os call-sites adicionam margin-top
   inline). O margin-bottom espelha o do reboot (h2 = .5rem) para não deslocar
   layouts existentes. */
.sgsi-subsecao {
    margin: 0 0 var(--sgsi-space-2);
    font-size: var(--sgsi-font-size-lg);
    font-weight: var(--sgsi-font-weight-semibold);
    line-height: var(--sgsi-line-height-tight);
    color: var(--sgsi-color-text);
}

/* ==========================================================================
   DATA GRID
   ========================================================================== */
.sgsi-grid { display: flex; flex-direction: column; gap: var(--sgsi-space-3); }
.sgsi-grid__toolbar { display: flex; align-items: center; gap: var(--sgsi-space-3); }
.sgsi-grid__busca { position: relative; flex: 1 1 18rem; max-width: 24rem; }
.sgsi-grid__busca-icone {
    position: absolute;
    left: var(--sgsi-space-3);
    top: 50%;
    transform: translateY(-50%);
    color: var(--sgsi-color-text-subtle);
    pointer-events: none;
}
.sgsi-grid__busca-input { padding-left: 2.25rem; }

.sgsi-grid__viewport {
    position: relative;
    /* Até 1199px (e fallback p/ navegador sem overflow:clip): scroll-container
       horizontal — a tabela larga rola aqui dentro em vez de estourar a viewport
       do aparelho. Trade-off consciente (o MESMO da .sgsi-tabela-wrap): nesta
       faixa o thead sticky NÃO engata, porque o sticky referencia este container,
       que nunca rola na vertical. De 1200px para cima a media query abaixo troca
       por overflow:clip e o sticky engata no scroll da PÁGINA (Onda 4-G1). */
    overflow-x: auto;
    border: 1px solid var(--sgsi-color-border);
    border-radius: var(--sgsi-radius-lg);
    background: var(--sgsi-color-surface);
}
/* Desktop largo: overflow:clip recorta os cantos seguindo o border-radius (idêntico
   ao hidden no paint) mas, pela spec CSS Overflow 3, NÃO cria scroll-container —
   o thead sticky volta a referenciar o scroll da página e engata sob a topbar
   (verificado em navegador real: th trava exatamente na borda inferior dela).
   Dois assassinos do sticky precisam morrer JUNTOS:
   1) este viewport (overflow-x:auto);
   2) o .sgsi-card hospedeiro (overflow:hidden) — hidden também é scroll-container
      (só programático) e, sozinho, mantinha o sticky natimorto. A regra :has()
      troca por clip SÓ nos cards que hospedam grid: recorte visual idêntico
      (mesmo raio), sem risco de scroll fantasma via scrollIntoView/focus; nenhum
      card contém float (BFC do hidden não faz falta — zero float no Web).
   Degradação graciosa: sem clip (pré-baseline-2022) a declaração é descartada e
   vale o overflow-x:auto acima (comportamento antigo, nunca visible — que
   vazaria os cantos); sem :has() (Firefox <121) a regra inteira é descartada e
   o card segue hidden (sem sticky, visual intacto).
   POR QUE 1200px e não o 769px original: clip sem scroll-container faz a coluna
   que não cabe ficar INALCANÇÁVEL — sem barra, sem arrasto e sem teclado. De
   769px a 1199px (notebook pequeno, iPad deitado, Windows a 125% de escala) a
   grade não cabe no card e o consultor em campo perdia colunas inteiras; o
   celular a 390px continuava rolando, o que escondia o defeito. O thead sticky é
   conforto e só se paga onde a grade cabe — abaixo de 1200px a rolagem manda. O
   `top` do thead desta família acompanha ESTE MESMO breakpoint (Onda 4-G1
   adiante): top>0 dentro do viewport-scroll-container afundaria o th sobre o
   tbody em repouso, então os dois breakpoints não podem divergir. */
@media (min-width: 1200px) {
    .sgsi-grid__viewport { overflow: clip; }
    .sgsi-card:has(.sgsi-grid) { overflow: clip; }
}
.sgsi-grid__tabela { width: 100%; border-collapse: collapse; font-size: var(--sgsi-font-size-sm); }
.sgsi-grid__th {
    text-align: left;
    font-weight: var(--sgsi-font-weight-semibold);
    color: var(--sgsi-color-text-muted);
    text-transform: uppercase;
    letter-spacing: var(--sgsi-letter-spacing-caps);
    font-size: var(--sgsi-font-size-xs);
    padding: var(--sgsi-space-3) var(--sgsi-space-4);
    /* FONTE ÚNICA do fundo do cabeçalho do grid — e ele é OBRIGATORIAMENTE opaco: o bloco de
       sticky lá embaixo prende este <th> no topo, e um fundo translúcido deixaria as linhas do
       tbody passarem por baixo dele ao rolar. Até 02/09 o sticky redeclarava `surface` e vencia
       esta linha por especificidade; agora a cor mora só aqui. */
    background: var(--sgsi-color-surface-2);
    border-bottom: 1px solid var(--sgsi-color-border);
    white-space: nowrap;
}
.sgsi-grid__th--centro, .sgsi-grid__td--centro { text-align: center; }
.sgsi-grid__th--fim, .sgsi-grid__td--fim { text-align: right; }
.sgsi-grid__th--ordenavel { padding: 0; }
.sgsi-grid__ordenar {
    display: inline-flex;
    align-items: center;
    gap: var(--sgsi-space-1);
    width: 100%;
    padding: var(--sgsi-space-3) var(--sgsi-space-4);
    border: 0;
    background: transparent;
    color: inherit;
    font: inherit;
    text-transform: inherit;
    letter-spacing: inherit;
    cursor: pointer;
}
.sgsi-grid__th--centro .sgsi-grid__ordenar { justify-content: center; }
.sgsi-grid__th--fim .sgsi-grid__ordenar { justify-content: flex-end; }
.sgsi-grid__ordenar:hover { color: var(--sgsi-color-text); background: var(--sgsi-color-surface-3); }
.sgsi-grid__seta { display: inline-flex; }

.sgsi-grid__td {
    padding: var(--sgsi-space-3) var(--sgsi-space-4);
    border-bottom: 1px solid var(--sgsi-color-border);
    color: var(--sgsi-color-text);
    vertical-align: middle;
    transition: background-color var(--sgsi-transition-fast);
}
.sgsi-grid__linha:last-child .sgsi-grid__td,
.sgsi-grid__linha-skel:last-child .sgsi-grid__td { border-bottom: 0; }

/* ---- Orçamento de largura da grade (auditoria UX 20/09, L1.10) ----
   A coluna de identidade (código + título, `Truncar="true"` na SgsiColuna) reclama 40% da
   tabela e corta em reticências o que não cabe — `max-width: 0` é o que permite ao layout
   automático encolhê-la em vez de estourar o cartão; as colunas com `Largura` fixa (status,
   datas, ações) ficam inteiras. Cada linha interna da célula (título, subtítulo) trunca por si. */
.sgsi-grid__td--truncar { width: 40%; max-width: 0; }
.sgsi-grid__td--truncar,
.sgsi-grid__td--truncar > * { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ---- .sgsi-tabela: sub-tabelas das páginas Detalhe (class="table sgsi-tabela") ----
   ~25 telas usam esta classe para tabelas internas que NÃO passam pelo SgsiDataGrid.
   A classe era REFERENCIADA mas nunca foi definida no CSS → caíam no .table cru do
   Bootstrap, destoando do grid polido. Espelha .sgsi-grid (cabeçalho maiúsculo muted,
   bordas/padding por token, hover). Tudo via tokens --sgsi-* → coerente no dark mode.
   Seletores com 3 elementos > a especificidade do .table do Bootstrap, vencendo-o. */
.sgsi-tabela { width: 100%; border-collapse: collapse; font-size: var(--sgsi-font-size-sm); }
.sgsi-tabela > thead > tr > th {
    text-align: left;
    font-weight: var(--sgsi-font-weight-semibold);
    color: var(--sgsi-color-text-muted);
    text-transform: uppercase;
    letter-spacing: var(--sgsi-letter-spacing-caps);
    font-size: var(--sgsi-font-size-xs);
    padding: var(--sgsi-space-3) var(--sgsi-space-4);
    /* FONTE ÚNICA do fundo, e opaco por exigência do sticky (mesma nota de .sgsi-grid__th):
       o bloco de sticky redeclarava `surface` com seletor IDÊNTICO e vencia por ordem. */
    background: var(--sgsi-color-surface-2);
    border-bottom: 1px solid var(--sgsi-color-border);
    white-space: nowrap;
}
.sgsi-tabela > tbody > tr > td {
    padding: var(--sgsi-space-3) var(--sgsi-space-4);
    border-bottom: 1px solid var(--sgsi-color-border);
    color: var(--sgsi-color-text);
    vertical-align: middle;
    transition: background-color var(--sgsi-transition-fast);
}
.sgsi-tabela > tbody > tr:last-child > td { border-bottom: 0; }
.sgsi-tabela > tbody > tr:hover > td { background: var(--sgsi-color-surface-2); }
.sgsi-tabela th.sgsi-tabela__centro, .sgsi-tabela td.sgsi-tabela__centro { text-align: center; }
.sgsi-tabela th.sgsi-tabela__fim, .sgsi-tabela td.sgsi-tabela__fim { text-align: right; }
/* Coluna de ação em linha (ex.: "Detalhes" do registro de requisitos da serventia): o botão com
   ícone quebrava em duas linhas — ícone em cima, texto embaixo — e dobrava a altura de cada linha
   (medido no navegador em 28/09). A coluna encolhe ao conteúdo e o botão não quebra. */
.sgsi-tabela th.sgsi-tabela__acoes, .sgsi-tabela td.sgsi-tabela__acoes { white-space: nowrap; width: 1%; }

/* ==========================================================================
   CÉLULA TRUNCADA — o ritmo da linha (revisão visual 01/09, §2.6)
   ==========================================================================

   ── O DEFEITO ──
   Zero truncamento em qualquer célula das 98 páginas com tabela. Uma célula com texto longo
   estica a linha em quatro vezes: a altura vai de 41px a 169px na MESMA tabela. A grade
   perde o ritmo e a leitura em diagonal — que é como um consultor varre uma tabela — deixa
   de funcionar; e quando a linha cresce, a página que mostrava 25 registros mostra três,
   justamente na tela em que a pessoa está procurando um PADRÃO entre eles.

   ── POR QUE A REGRA VIVE NUM <span> DENTRO DA CÉLULA, E NÃO NA <td> ──
   Este é o ponto que decide se a regra funciona ou é enfeite. Com `table-layout: auto` — que
   é o layout de TODAS as tabelas do produto hoje, e cuja troca é a §2.5, deliberadamente
   fora desta leva — o navegador DESCARTA `max-width` na `<td>`: a coluna é dimensionada pela
   contribuição de conteúdo das células, e a `td` não é uma caixa que se possa limitar. Uma
   classe de truncamento aplicada à `td` compilaria, casaria o elemento e não recortaria
   nada. Num elemento de bloco DENTRO da célula, `max-width` vale: ele passa a ser a
   contribuição máxima daquela coluna, a coluna para de crescer e o texto reticencia. É por
   isso que a utilidade é um componente (Ui/SgsiCelulaTruncada) e não uma classe de coluna —
   e é por isso que ela funciona ANTES da §2.5, sem depender dela.

   ── O TEXTO INTEIRO CONTINUA ALCANÇÁVEL, E ISSO É REQUISITO, NÃO CORTESIA ──
   O aparo é VISUAL: o texto permanece inteiro no DOM, então o leitor de tela lê tudo —
   `text-overflow` não suprime conteúdo, só decide o que a caixa pinta. O que faltaria ao
   usuário com mouse é o resto da frase, e é para ele que o componente carimba o `title`.
   Truncar sem devolver o texto é esconder informação e seria um defeito pior que o ritmo
   quebrado — a catraca CelulaTruncadaDevolveOTextoInteiroTests existe por isso.

   ── ALTURA PREVISÍVEL É EM LINHAS, NÃO EM PIXELS ──
   O modificador `--linhas` limita o conteúdo a `--sgsi-celula-linhas` LINHAS DE TEXTO, e a
   folha crava a `line-height` no lugar de herdá-la. O que isso garante é o teto em linhas: a
   célula não estica a linha da tabela por causa de um dado longo, seja qual for o dado.

   O QUE ELE NÃO GARANTE, E A PRIMEIRA REDAÇÃO AFIRMAVA (corrigido em 02/09): a altura em
   PIXELS. `--sgsi-line-height` é `1.5` SEM UNIDADE, então a conta é
   `linhas × entrelinha × FONT-SIZE` — e o font-size continua herdado do contexto da célula.
   O contra-exemplo mora no próprio produto e é o caso que originou esta regra:
   `.sgsi-outbox-erro` define `font-size: var(--sgsi-font-size-sm)`, então duas células com
   `Linhas=3` medem alturas diferentes conforme a coluna. Cravar o font-size aqui tornaria a
   frase verdadeira e QUEBRARIA esse uso legítimo — a correção é a frase, não o CSS. Um piso
   de altura (`height` na td) NÃO serviria: o toggle global de densidade compacta corta o
   padding da célula para 0.3rem, e um piso desfaria em silêncio a densidade que o usuário
   escolheu no topbar.

   O produto já resolveu isto UMA vez, em particular: `.sgsi-outbox-erro` (30/08) é este
   mesmo clamp de 3 linhas, com `title` no call-site, escrito só para a coluna "Último erro".
   Ele fica onde está — a utilidade não migra call-site nesta leva —, mas é o décimo-primeiro
   caso da família que o documento descreve: a ideia existia, faltava o lugar onde ela mora
   uma vez só.
   ========================================================================== */
.sgsi-celula-truncada {
    display: block;
    max-width: var(--sgsi-celula-largura);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Dois degraus, pelo mesmo motivo dos degraus de campo: sem eles cada tela inventa um
   número e a coluna "Título" sai com largura diferente em cada índice. */
.sgsi-celula-truncada--estreita { --sgsi-celula-largura: 12rem; }
.sgsi-celula-truncada--larga    { --sgsi-celula-largura: 40rem; }

/* Teto por LINHAS, para o texto que perde sentido cortado na primeira (mensagem de erro,
   observação). `white-space: normal` desfaz o nowrap do bloco acima — sem isso o clamp
   nunca teria uma segunda linha para contar. `-webkit-line-clamp` continua sendo a grafia
   que os navegadores implementam; `line-clamp` ao lado é a padronizada, para quando virar. */
.sgsi-celula-truncada--linhas {
    display: -webkit-box;
    -webkit-line-clamp: var(--sgsi-celula-linhas);
    line-clamp: var(--sgsi-celula-linhas);
    -webkit-box-orient: vertical;
    white-space: normal;
    overflow-wrap: anywhere;
    line-height: var(--sgsi-line-height);
}

/* ---- .sgsi-tabela-wrap: container de responsividade do SgsiTabela ----
   Todo SgsiTabela renderiza a <table> dentro deste div. Abaixo do breakpoint
   tablet ele vira scroll-container horizontal: a tabela larga rola dentro dele
   em vez de estourar a viewport do celular (~55 usos em 38 páginas). No desktop
   fica SEM overflow DE PROPÓSITO: overflow-x:auto tornaria o div um
   scroll-container e desengataria o thead sticky do scroll da página (o sticky
   passa a referenciar o container mais próximo, que não rola na vertical).
   Trade-off consciente: mobile/tablet = rolagem horizontal (sem sticky);
   desktop = thead sticky sob a topbar (veja Onda 4-G1 adiante). Call-sites que
   já se envolvem em .table-responsive geram wrapper duplo — inofensivo. */
/* ── A COLUNA FICAVA INALCANCAVEL DE 769px PARA CIMA (04/09) ──────────────────
   Esta familia tinha rolagem SO ate 768px e `clip` a partir de 769px. Como o
   `th` desta tabela e `white-space: nowrap` (ver .sgsi-tabela > thead > tr > th),
   ela NAO PODE encolher abaixo da soma dos rotulos — entao, num laptop de
   1366px, a coluna que nao coubesse ficava recortada pelo cartao SEM barra, sem
   arrasto e sem teclado. O veredito ja estava escrito nesta folha, na
   justificativa do DataGrid: `clip` sem scroll-container torna a coluna
   INALCANCAVEL. A regra foi aplicada ao grid e nao a esta familia.

   Medido em 04/09: 79 <SgsiTabela> no produto, 56 sem nenhum ancestral rolavel,
   e 23 delas declaram 6+ colunas — incluindo o detalhe da SoA (7), a equipe (7)
   e as chaves de API (8). A coluna de ACOES, quando existe, e a ultima: era a
   primeira a cair fora.

   Agora as duas familias usam o MESMO limite (1200px), que e onde a largura
   sobra de fato. Os quatro @media desta familia se movem juntos — a propria
   folha avisa, no bloco do sticky, que eles nao podem divergir: `top > 0` dentro
   de um scroll-container afunda o th sobre o tbody em repouso. */
@media (max-width: 1199px) {
    .sgsi-tabela-wrap { overflow-x: auto; }
}
@media (min-width: 1200px) {
    /* O 2º assassino do sticky (mesmo diagnóstico do DATA GRID, provado em
       navegador): o .sgsi-card hospedeiro usa overflow:hidden, que TAMBÉM é
       scroll-container e mata o sticky do thead. clip recorta os cantos igual
       ao hidden mas não cria scrolling box. Sem :has() (Firefox <121) a regra é
       descartada inteira → card segue hidden (sem sticky, visual intacto). */
    .sgsi-card:has(.sgsi-tabela),
    .sgsi-card:has(.sgsi-est-tabela) { overflow: clip; }
}
.sgsi-grid__linha:hover .sgsi-grid__td { background: var(--sgsi-color-surface-2); }
.sgsi-grid__linha--clicavel { cursor: pointer; }
.sgsi-grid__linha--clicavel:focus-visible {
    outline: var(--sgsi-focus-ring-width) solid var(--sgsi-color-focus-ring);
    outline-offset: calc(-1 * var(--sgsi-focus-ring-width));
}

.sgsi-grid__erro {
    display: flex;
    align-items: center;
    gap: var(--sgsi-space-3);
    padding: var(--sgsi-space-5);
    color: var(--sgsi-color-danger);
}
.sgsi-grid__erro > div { flex: 1 1 auto; }
.sgsi-grid__erro-icone { flex: 0 0 auto; }
.sgsi-grid__erro-titulo { margin: 0; font-weight: var(--sgsi-font-weight-semibold); }
.sgsi-grid__erro-msg { margin: 0; font-size: var(--sgsi-font-size-sm); color: var(--sgsi-color-text-muted); }

/* BAI-831: o rodapé passou a hospedar a contagem ("1–25 de 226 registros") ao lado do paginador —
   e a contagem aparece também quando há uma página só, onde o paginador não existe. */
.sgsi-grid__rodape {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--sgsi-space-2);
    padding: 0 var(--sgsi-space-1);
}
.sgsi-grid__contagem { margin: 0; font-size: var(--sgsi-font-size-sm); color: var(--sgsi-color-text-muted); }

/* ==========================================================================
   MOVIMENTO REDUZIDO
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
    .sgsi-skel { animation: none; }
    .sgsi-toast, .sgsi-modal[open] { animation: none; }
}

/* ==========================================================================
   F1 — AUTENTICAÇÃO (login) + SELETOR DE TENANT
   ========================================================================== */

/* ----- Layout de autenticação (LayoutAuth) ----- */
.sgsi-auth {
    min-height: 100vh;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: var(--sgsi-space-5);
    background:
        radial-gradient(1200px 600px at 50% -10%,
            rgba(var(--sgsi-color-brand-rgb), 0.10), transparent 60%),
        var(--sgsi-color-bg);
}
.sgsi-auth__main {
    width: 100%;
    max-width: 26rem;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--sgsi-space-5);
}
.sgsi-auth__main:focus { outline: none; }
.sgsi-auth__brand {
    display: inline-flex;
    align-items: center;
    gap: var(--sgsi-space-3);
    color: var(--sgsi-color-text);
}
.sgsi-auth__brand-mark {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.75rem;
    height: 2.75rem;
    border-radius: var(--sgsi-radius-md);
    background: var(--sgsi-color-brand);
    color: var(--sgsi-color-on-brand);
}
/* ---- O WORDMARK NAO DISPUTA O OLHO COM O TITULO DA TELA (30/08) --------------------------
   Estava em `xl` (1.375rem/22px) — MAIOR que o `.sgsi-auth-card__titulo` em `lg` (18px). Nas
   telas de aquisicao (login, criar conta, aceitar convite) o maior texto da pagina era a
   palavra "SGI PRO", e a frase que diz ao visitante o que ele esta fazendo ficava 2px acima
   do corpo. A marca ja tem o quadrado de 2,75rem em cor de marca como ancora; nao precisa
   ganhar do titulo tambem. Ver o par desta regra em `.sgsi-auth-card__titulo`. */
.sgsi-auth__brand-name { font-size: var(--sgsi-font-size-lg); letter-spacing: 0.02em; }
.sgsi-auth__rodape {
    margin: 0;
    font-size: var(--sgsi-font-size-xs);
    color: var(--sgsi-color-text-muted);
    text-align: center;
}

.sgsi-auth__confianca {
    margin: 0.5rem 0 0;
    display: flex;
    gap: 0.4rem;
    justify-content: center;
    align-items: center;
    font-size: var(--sgsi-font-size-xs);
    color: var(--sgsi-color-text-muted);
}

.sgsi-auth__confianca a {
    color: var(--sgsi-color-text-muted);
    text-decoration: none;
}

.sgsi-auth__confianca a:hover,
.sgsi-auth__confianca a:focus-visible {
    color: var(--sgsi-color-text);
    text-decoration: underline;
}

/* ----- Cartão de login ----- */
.sgsi-auth-card {
    width: 100%;
    background: var(--sgsi-color-surface);
    border: 1px solid var(--sgsi-color-border);
    border-radius: var(--sgsi-radius-lg);
    box-shadow: var(--sgsi-shadow-md);
    padding: var(--sgsi-space-6);
    display: flex;
    flex-direction: column;
    gap: var(--sgsi-space-5);
}
.sgsi-auth-card__cab { display: flex; flex-direction: column; gap: var(--sgsi-space-2); }
/* O h1 da tela de aquisicao sobe para `xl`/bold: era `lg` (18px) sem peso declarado — 2px
   acima do corpo (16px) e 4px acima do rotulo de campo (14px), num contexto em que TUDO e
   novo para o visitante e nada indicava por onde comecar a ler. Continua abaixo do `2xl` do
   `.sgsi-pagina__titulo` de proposito: o cartao de auth e mais estreito, e 28px nele quebraria
   linha em "Crie a conta da sua empresa". */
.sgsi-auth-card__titulo { margin: 0; font-size: var(--sgsi-font-size-xl); font-weight: var(--sgsi-font-weight-bold); color: var(--sgsi-color-text); }
.sgsi-auth-card__sub { margin: 0; font-size: var(--sgsi-font-size-sm); color: var(--sgsi-color-text-muted); }
/* Variante alinhada ao fim: usada pelo "Esqueci minha senha" dentro do form de login, onde a
   convenção é o link acompanhar a borda do campo de senha em vez de centralizar. */
.sgsi-auth-card__sub--fim { text-align: end; }
.sgsi-auth-card__form { display: flex; flex-direction: column; gap: var(--sgsi-space-4); }

/* Gate de reaceite de termos (/aceitar-termos) — reusa o cartão de auth. */
.sgsi-termos { display: flex; flex-direction: column; gap: var(--sgsi-space-4); }
.sgsi-termos__versao { margin: 0; font-size: var(--sgsi-font-size-sm); color: var(--sgsi-color-text); }
.sgsi-termos__anterior { color: var(--sgsi-color-text-muted); margin-inline-start: var(--sgsi-space-2); }
.sgsi-termos__lista { margin: 0; padding-inline-start: var(--sgsi-space-5); display: flex; flex-direction: column; gap: var(--sgsi-space-1); color: var(--sgsi-color-text); }
.sgsi-termos__aceite { display: flex; align-items: flex-start; gap: var(--sgsi-space-2); font-size: var(--sgsi-font-size-sm); color: var(--sgsi-color-text); cursor: pointer; }
.sgsi-termos__aceite input { margin-top: 0.2em; flex: 0 0 auto; }
.sgsi-termos__acoes { display: flex; align-items: center; justify-content: space-between; gap: var(--sgsi-space-3); flex-wrap: wrap; }
.sgsi-termos__sair { margin: 0; }
.sgsi-termos__link { background: none; border: 0; padding: 0; color: var(--sgsi-color-text-muted); font-size: var(--sgsi-font-size-sm); cursor: pointer; display: inline-flex; align-items: center; gap: var(--sgsi-space-1); }
.sgsi-termos__link:hover { color: var(--sgsi-color-text); text-decoration: underline; }

/* Eliminação de conta (/encerrar-conta) — zona de perigo + estado pendente. */
.sgsi-eliminacao__zona-perigo,
.sgsi-eliminacao__pendente { display: flex; flex-direction: column; gap: var(--sgsi-space-3); }
.sgsi-eliminacao__form { display: flex; flex-direction: column; gap: var(--sgsi-space-3); margin-top: var(--sgsi-space-2); }
.sgsi-eliminacao__form label { display: flex; flex-direction: column; gap: var(--sgsi-space-1); font-size: var(--sgsi-font-size-sm); }
.sgsi-eliminacao__form input[type="password"],
.sgsi-eliminacao__form input[type="text"] {
    padding: var(--sgsi-space-2); border: 1px solid var(--sgsi-color-border); border-radius: var(--sgsi-radius-sm);
    background: var(--sgsi-color-surface); color: var(--sgsi-color-text); max-width: 22rem;
}
.sgsi-eliminacao__ciente { flex-direction: row !important; align-items: flex-start; gap: var(--sgsi-space-2) !important; }
.sgsi-eliminacao__ciente input { margin-top: 0.2em; flex: 0 0 auto; }

/* Painel de evidências automáticas (/prontidao/evidencias). */
.sgsi-evid__resumo { display: flex; flex-wrap: wrap; gap: var(--sgsi-space-3); margin-bottom: var(--sgsi-space-4); }
/* O RAIO ERA `md` (8px) enquanto as outras duas familias de cartao de numero usam `lg` (12px)
   — ver o bloco "TRES FAMILIAS DE CARTAO DE NUMERO" perto de .sgsi-stat. Duas curvaturas
   diferentes para o mesmo objeto e o que faz o produto parecer montado por peca solta. */
.sgsi-evid__stat { display: flex; flex-direction: column; align-items: center; min-width: 6rem; padding: var(--sgsi-space-3) var(--sgsi-space-4); border: 1px solid var(--sgsi-color-border); border-radius: var(--sgsi-radius-lg); background: var(--sgsi-color-surface); }
.sgsi-evid__stat-valor { font-size: var(--sgsi-font-size-lg); font-weight: 700; font-variant-numeric: tabular-nums; }
.sgsi-evid__stat-rotulo { font-size: var(--sgsi-font-size-sm); color: var(--sgsi-color-text-muted); }
.sgsi-evid__stat--ok .sgsi-evid__stat-valor { color: var(--sgsi-color-success, #15803d); }
.sgsi-evid__stat--erro .sgsi-evid__stat-valor { color: var(--sgsi-color-danger, #b91c1c); }
.sgsi-evid__stat--indeterminado .sgsi-evid__stat-valor { color: var(--sgsi-color-text-muted); }
.sgsi-evid__lista { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--sgsi-space-4); }
.sgsi-evid__item { display: flex; flex-direction: column; gap: var(--sgsi-space-1); padding-bottom: var(--sgsi-space-3); border-bottom: 1px solid var(--sgsi-color-border); }
.sgsi-evid__cab { display: flex; align-items: center; gap: var(--sgsi-space-2); flex-wrap: wrap; }
.sgsi-evid__badge { font-size: var(--sgsi-font-size-xs); font-weight: 700; padding: 0.1em 0.5em; border-radius: var(--sgsi-radius-sm); text-transform: uppercase; }
.sgsi-evid__badge--ok { background: #dcfce7; color: #15803d; }
.sgsi-evid__badge--erro { background: #fee2e2; color: #b91c1c; }
.sgsi-evid__badge--indeterminado { background: var(--sgsi-color-surface-2); color: var(--sgsi-color-text-muted); }
.sgsi-evid__badge--na { background: var(--sgsi-color-surface-2); color: var(--sgsi-color-text-muted); }
.sgsi-evid__stale { font-size: var(--sgsi-font-size-xs); color: var(--sgsi-color-danger, #b91c1c); font-style: italic; }
.sgsi-evid__detalhe { margin: 0; font-size: var(--sgsi-font-size-sm); color: var(--sgsi-color-text); }
.sgsi-evid__creditos { display: flex; flex-wrap: wrap; gap: var(--sgsi-space-1); }
.sgsi-evid__chip { font-size: var(--sgsi-font-size-xs); padding: 0.1em 0.5em; border: 1px solid var(--sgsi-color-border); border-radius: var(--sgsi-radius-sm); color: var(--sgsi-color-text-muted); }
.sgsi-evid__meta { margin: 0; font-size: var(--sgsi-font-size-xs); color: var(--sgsi-color-text-muted); }

/* Respondedor de DDQ (Copiloto de IA — /ddq) */
.sgsi-ddq__contagem { margin: var(--sgsi-space-2) 0 0; font-size: var(--sgsi-font-size-sm); color: var(--sgsi-color-text-muted); }
.sgsi-ddq__alerta { margin-left: var(--sgsi-space-2); color: var(--sgsi-color-warning, #b45309); }
.sgsi-ddq__ctx-acoes { margin-bottom: var(--sgsi-space-3); }
.sgsi-ddq__gerar { display: flex; flex-wrap: wrap; gap: var(--sgsi-space-3); align-items: center; margin: var(--sgsi-space-4) 0; }
.sgsi-ddq__upsell { border-left: 3px solid var(--sgsi-color-warning, #b45309); }
.sgsi-ddq__resultados { display: flex; flex-direction: column; gap: var(--sgsi-space-4); }
.sgsi-ddq__item { display: flex; flex-direction: column; gap: var(--sgsi-space-2); padding-bottom: var(--sgsi-space-3); border-bottom: 1px solid var(--sgsi-color-border); }
.sgsi-ddq__item--erro { opacity: 0.9; }
.sgsi-ddq__pergunta { margin: 0; font-weight: 600; color: var(--sgsi-color-text); }
.sgsi-ddq__item-erro { margin: 0; font-size: var(--sgsi-font-size-sm); color: var(--sgsi-color-danger, #b91c1c); }
.sgsi-ddq__resposta { width: 100%; }
.sgsi-ddq__aviso { margin: var(--sgsi-space-3) 0 0; font-size: var(--sgsi-font-size-xs); color: var(--sgsi-color-text-muted); font-style: italic; }
/* BAI-665 — as tres saidas do resultado pago (copiar, salvar, exportar). */
.sgsi-ddq__botoes { display: flex; flex-wrap: wrap; gap: var(--sgsi-space-3); align-items: center; margin-top: var(--sgsi-space-3); }

/* BAI-808 — catalogo de temporalidade com selecao MULTIPLA (era um item por vez). */
.sgsi-catalogo__topo { display: flex; flex-wrap: wrap; gap: var(--sgsi-space-3); align-items: center; margin-bottom: var(--sgsi-space-2); }
.sgsi-catalogo__contagem { font-size: var(--sgsi-font-size-sm); color: var(--sgsi-color-text-muted); margin-right: auto; }
.sgsi-catalogo__lista { list-style: none; margin: 0; padding: 0; max-height: 22rem; overflow-y: auto; border: 1px solid var(--sgsi-color-border); border-radius: var(--sgsi-radius-md); }
.sgsi-catalogo__item + .sgsi-catalogo__item { border-top: 1px solid var(--sgsi-color-border); }
.sgsi-catalogo__rotulo { display: flex; gap: var(--sgsi-space-3); align-items: flex-start; padding: var(--sgsi-space-3); cursor: pointer; }
.sgsi-catalogo__rotulo:hover { background: var(--sgsi-color-surface-hover, rgba(0,0,0,.03)); }
.sgsi-catalogo__meta { display: block; font-size: var(--sgsi-font-size-xs); color: var(--sgsi-color-text-muted); margin-top: var(--sgsi-space-1); }
.sgsi-catalogo__pii { color: var(--sgsi-color-warning, #b45309); }
.sgsi-catalogo__falhas { margin: 0; padding-left: var(--sgsi-space-4); font-size: var(--sgsi-font-size-sm); }

/* Trilha de auditoria (God Mode — /centro-comando/auditoria) */
.sgsi-trilha__integ { border-left: 3px solid var(--sgsi-color-border); }
.sgsi-trilha__integ--ok { border-left-color: var(--sgsi-color-success, #15803d); }
.sgsi-trilha__integ--quebra { border-left-color: var(--sgsi-color-danger, #b91c1c); }
.sgsi-trilha__integ-conteudo { display: flex; gap: var(--sgsi-space-3); align-items: flex-start; }
.sgsi-trilha__integ-titulo { margin: 0; font-weight: 700; }
.sgsi-trilha__integ--ok .sgsi-trilha__integ-titulo { color: var(--sgsi-color-success, #15803d); }
.sgsi-trilha__integ--quebra .sgsi-trilha__integ-titulo { color: var(--sgsi-color-danger, #b91c1c); }
.sgsi-trilha__integ-msg { margin: var(--sgsi-space-1) 0 0; font-size: var(--sgsi-font-size-sm); color: var(--sgsi-color-text-muted); }
/* A RESSALVA do selo de integridade (04/09). Ela aparece no ramo VERDE — quando a cadeia confere
   mas o checkpoint NAO foi para testemunha externa — e por isso NAO pode ter o tom apagado do
   texto ao lado: no cinza do .integ-msg, o auditor le "trilha integra" e passa reto pela unica
   frase que qualifica a afirmacao. Mesmo raciocinio do .sgsi-ia__aviso--critico. */
.sgsi-trilha__integ-ressalva {
    display: block;
    margin-top: var(--sgsi-space-1);
    font-size: var(--sgsi-font-size-sm);
    font-weight: 600;
    color: var(--sgsi-color-warning);
}
.sgsi-trilha__filtros { display: flex; flex-wrap: wrap; gap: var(--sgsi-space-3); align-items: flex-end; }
.sgsi-trilha__filtros > div { flex: 1 1 12rem; }
.sgsi-trilha__filtros-acao { flex: 0 0 auto; }
.sgsi-trilha__tabela-wrap { overflow-x: auto; }
.sgsi-trilha__num { text-align: right; font-variant-numeric: tabular-nums; }
.sgsi-trilha__quando { white-space: nowrap; font-variant-numeric: tabular-nums; }
.sgsi-trilha__tipo { font-size: var(--sgsi-font-size-sm); }
.sgsi-trilha__ator { font-size: var(--sgsi-font-size-sm); color: var(--sgsi-color-text-muted); }
.sgsi-trilha__resumo { cursor: pointer; font-size: var(--sgsi-font-size-xs); color: var(--sgsi-color-accent); }
.sgsi-trilha__json { margin: var(--sgsi-space-2) 0 0; padding: var(--sgsi-space-2); background: var(--sgsi-color-surface-2); border-radius: var(--sgsi-radius-sm); font-size: var(--sgsi-font-size-xs); white-space: pre-wrap; word-break: break-all; max-width: 40rem; }
.sgsi-trilha__paginacao { display: flex; gap: var(--sgsi-space-3); align-items: center; justify-content: center; padding: var(--sgsi-space-3); }
.sgsi-trilha__pagina-rotulo { font-size: var(--sgsi-font-size-sm); color: var(--sgsi-color-text-muted); font-variant-numeric: tabular-nums; }

/* Motores: disparo manual (God Mode) */
.sgsi-motores-botoes { display: flex; flex-wrap: wrap; gap: var(--sgsi-space-2); }
.sgsi-motores-resultado { margin: var(--sgsi-space-3) 0 0; padding: var(--sgsi-space-3); background: var(--sgsi-color-surface-2); border-radius: var(--sgsi-radius-sm); font-size: var(--sgsi-font-size-xs); white-space: pre-wrap; word-break: break-word; }

/* Chips de normas ativas (God Mode — desativar norma) */
/* ── O TEXTO DA NORMA SAÍA PELA BORDA DIREITA DO CARTÃO (03/09) ──
   MEDIDO na folha real, com o cartão em 26rem: a badge de "ISO/IEC 27001:2022 - Sistema de
   Gestão de Segurança da Informação" media 395px e sua borda direita caía em 436px, contra 432px
   do cartão — que computa `overflow-x: hidden` e portanto RECORTA. O que o dono vê é o corte
   cru no meio da palavra ("...Segurança da"), sem reticência e sem nada dizendo que falta texto.

   Mecanismo: `.sgsi-badge` é `white-space: nowrap` (correto para o que a badge quase sempre é —
   um selo de uma ou duas palavras), e o chip é item de um flex container com `min-width: auto`,
   que o proíbe de encolher abaixo do próprio conteúdo. Largura intrínseca > largura disponível,
   sem elipse e sem quebra = transbordo recortado.

   Escolhi QUEBRAR, não truncar: o nome da norma é a informação inteira do cartão "Normas
   ativas"; uma elipse aqui esconderia justamente o que distingue 27001 de 27017 de 27018, e a
   badge não tem `title` para devolver o resto (o `title` que existe é do botão "x", e diz outra
   coisa). Quebrar custa uma segunda linha e não custa informação nenhuma.
   O seletor é `.sgsi-norma-chip > .sgsi-badge` (0,2,0): mexe SÓ nas badges de norma e deixa a
   base `nowrap` intacta para as ~centenas de badges de status do resto do produto, onde a quebra
   é que seria o defeito. */
.sgsi-normas-chips { display: flex; flex-wrap: wrap; gap: var(--sgsi-space-2); }
.sgsi-norma-chip { display: inline-flex; align-items: center; gap: var(--sgsi-space-1); max-width: 100%; min-width: 0; }
.sgsi-norma-chip > .sgsi-badge {
    white-space: normal;
    overflow-wrap: anywhere;
    text-align: start;
    min-width: 0;
}
.sgsi-norma-chip__x { display: inline-flex; align-items: center; justify-content: center; width: 1.4rem; height: 1.4rem; padding: 0; border: none; border-radius: var(--sgsi-radius-sm); background: transparent; color: var(--sgsi-color-text-muted); cursor: pointer; }
.sgsi-norma-chip__x:hover { background: var(--sgsi-color-danger-bg); color: var(--sgsi-color-danger, #b91c1c); }
.sgsi-auth-card__submit {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--sgsi-space-2);
    margin-top: var(--sgsi-space-2);
}

/* ----- Linha de ações dentro de uma célula de grid -----------------------------
   Utilitário GENÉRICO: vários botões pequenos numa célula da tabela, que quebram
   para a linha de baixo em telas estreitas em vez de estourar a coluna.
   É genérico de propósito — a versão por-feature (.sgsi-usuario-acoes, em
   ListaUsuarios) foi escrita no .razor e NUNCA no CSS, então aquela linha de
   botões renderiza sem gap nem wrap até hoje. Toda célula com 2+ ações usa esta. */
.sgsi-acoes-linha {
    display: flex;
    flex-wrap: wrap;
    gap: var(--sgsi-space-2);
    align-items: center;
    justify-content: center;
}
/* Modificador para a célula alinhada à DIREITA (`sgsi-grid__td--fim`): sem ele o call-site
   pegava emprestada a `.sgsi-pagina__acoes`, que é a toolbar do CABEÇALHO DA PÁGINA e alinha
   ao início — os botões saíam à esquerda de uma coluna cujo <th> está à direita, e o olho
   procurava as ações debaixo da palavra "Ações" sem encontrá-las. Continua quebrando linha:
   `nowrap` numa coluna estreita não some com o problema, empurra-o para o overflow. */
.sgsi-acoes-linha--fim { justify-content: flex-end; }

/* ----- Alerta inline (feedback contextual: erro, aviso, informação, sucesso) ----- */
.sgsi-alert {
    display: flex;
    align-items: flex-start;
    gap: var(--sgsi-space-3);
    padding: var(--sgsi-space-3) var(--sgsi-space-4);
    border-radius: var(--sgsi-radius-md);
    font-size: var(--sgsi-font-size-sm);
    border: 1px solid transparent;
}
.sgsi-alert__icone { flex: 0 0 auto; display: inline-flex; margin-top: 0.1em; }
/* Variantes semânticas: texto/borda no tom pleno + fundo suave do mesmo par de
   tokens. Contraste AA verificado nos DOIS temas (texto sobre o fundo suave):
   danger 4.9:1 / warning 5.2:1 / info 6.0:1 / success 4.7:1 no claro;
   todos >= 7.9:1 no escuro. */
.sgsi-alert--danger {
    color: var(--sgsi-color-danger);
    background: var(--sgsi-color-danger-bg);
    border-color: var(--sgsi-color-danger);
}
.sgsi-alert--warning {
    color: var(--sgsi-color-warning);
    background: var(--sgsi-color-warning-bg);
    border-color: var(--sgsi-color-warning);
}
.sgsi-alert--info {
    color: var(--sgsi-color-info);
    background: var(--sgsi-color-info-bg);
    border-color: var(--sgsi-color-info);
}
.sgsi-alert--success {
    color: var(--sgsi-color-success);
    background: var(--sgsi-color-success-bg);
    border-color: var(--sgsi-color-success);
}

/* ----- Seletor de tenant (topbar) ----- */
.sgsi-seletor-tenant { position: relative; }
.sgsi-seletor-tenant__btn {
    display: inline-flex;
    align-items: center;
    gap: var(--sgsi-space-2);
    max-width: 16rem;
    padding: var(--sgsi-space-2) var(--sgsi-space-3);
    background: var(--sgsi-color-surface-2);
    border: 1px solid var(--sgsi-color-border);
    border-radius: var(--sgsi-radius-md);
    color: var(--sgsi-color-text);
    cursor: pointer;
}
.sgsi-seletor-tenant__btn:hover { background: var(--sgsi-color-surface-3); }
.sgsi-seletor-tenant__btn:focus-visible {
    outline: var(--sgsi-focus-ring-width) solid var(--sgsi-color-focus-ring);
    outline-offset: var(--sgsi-focus-ring-offset);
}
.sgsi-seletor-tenant__icone { flex: 0 0 auto; display: inline-flex; color: var(--sgsi-color-text-muted); }
.sgsi-seletor-tenant__rotulo {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    line-height: var(--sgsi-line-height-tight);
    min-width: 0;
}
.sgsi-seletor-tenant__cap {
    font-size: var(--sgsi-font-size-xs);
    color: var(--sgsi-color-text-muted);
    text-transform: uppercase;
    letter-spacing: var(--sgsi-letter-spacing-caps);
}
.sgsi-seletor-tenant__valor {
    font-size: var(--sgsi-font-size-sm);
    font-weight: var(--sgsi-font-weight-medium);
    max-width: 11rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.sgsi-seletor-tenant__caret { flex: 0 0 auto; color: var(--sgsi-color-text-muted); }
.sgsi-seletor-tenant__menu {
    position: absolute;
    top: calc(100% + var(--sgsi-space-2));
    right: 0;
    z-index: 50;
    min-width: 15rem;
    max-height: 60vh;
    overflow-y: auto;
    padding: var(--sgsi-space-2);
    background: var(--sgsi-color-surface);
    border: 1px solid var(--sgsi-color-border);
    border-radius: var(--sgsi-radius-md);
    box-shadow: var(--sgsi-shadow-lg);
    display: flex;
    flex-direction: column;
    gap: 0.125rem;
}
.sgsi-seletor-tenant__item {
    display: flex;
    align-items: center;
    gap: var(--sgsi-space-2);
    width: 100%;
    padding: var(--sgsi-space-2) var(--sgsi-space-3);
    background: transparent;
    border: 0;
    border-radius: var(--sgsi-radius-sm);
    color: var(--sgsi-color-text);
    text-align: left;
    cursor: pointer;
}
.sgsi-seletor-tenant__item:hover { background: var(--sgsi-color-surface-2); }
.sgsi-seletor-tenant__item:focus-visible {
    outline: var(--sgsi-focus-ring-width) solid var(--sgsi-color-focus-ring);
    outline-offset: calc(-1 * var(--sgsi-focus-ring-width));
}
.sgsi-seletor-tenant__item[aria-checked="true"] { font-weight: var(--sgsi-font-weight-semibold); }
.sgsi-seletor-tenant__check {
    flex: 0 0 auto;
    display: inline-flex;
    width: 1rem;
    color: var(--sgsi-color-success);
}
.sgsi-seletor-tenant__item-nome {
    flex: 1 1 auto;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* ----- Tela de seleção de cliente (pós-login) ----- */
.sgsi-seletor-cliente__grade {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(15rem, 100%), 1fr));
    gap: var(--sgsi-space-4);
}
.sgsi-seletor-cliente__card {
    display: flex;
    align-items: center;
    gap: var(--sgsi-space-3);
    padding: var(--sgsi-space-4);
    background: var(--sgsi-color-surface);
    border: 1px solid var(--sgsi-color-border);
    border-radius: var(--sgsi-radius-md);
    color: var(--sgsi-color-text);
    text-align: left;
    cursor: pointer;
    transition: border-color 120ms ease, box-shadow 120ms ease;
}
.sgsi-seletor-cliente__card:hover {
    border-color: var(--sgsi-color-brand);
    box-shadow: var(--sgsi-shadow-sm);
}
.sgsi-seletor-cliente__card:focus-visible {
    outline: var(--sgsi-focus-ring-width) solid var(--sgsi-color-focus-ring);
    outline-offset: var(--sgsi-focus-ring-offset);
}
.sgsi-seletor-cliente__card-icone {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.5rem;
    height: 2.5rem;
    border-radius: var(--sgsi-radius-md);
    background: var(--sgsi-color-surface-3);
    color: var(--sgsi-color-brand);
}
.sgsi-seletor-cliente__card-nome {
    flex: 1 1 auto;
    font-weight: var(--sgsi-font-weight-medium);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.sgsi-seletor-cliente__card-seta { flex: 0 0 auto; color: var(--sgsi-color-text-muted); }

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

/* ==========================================================================
   F4 — Feature RISCOS (gabarito). Tudo via tokens; dark mode herda
   automaticamente (as variáveis trocam por [data-bs-theme]).
   ========================================================================== */

/* ----- Form grid responsivo (modais) ----- */
.sgsi-form-grid {
    display: grid;
    grid-template-columns: repeat(12, 1fr);
    gap: var(--sgsi-space-4);
}
.sgsi-form-grid > .sgsi-field { grid-column: span 12; margin-bottom: 0; }

/* CONJUNTO COMPLETO 1–12, e a completude é o ponto. Existiam apenas 4, 6, 8 e 12: um
   `sgsi-col-5` escrito numa tela não gerava erro nenhum — o campo simplesmente ficava com a
   largura padrão (span 12) e o formulário saía com o layout errado, em silêncio. Sete usos
   estavam nessa condição (col-1, col-2, col-5, col-7 em modais de Impactos, Análise Crítica,
   Competências e Mudanças). HTML não reclama de classe inexistente; só a completude do conjunto
   impede a próxima ocorrência.
   Mobile-first: TUDO empilha (span 12) abaixo de 640px — numa coluna estreita, dividir o grid
   produz campo ilegível; a largura declarada só passa a valer quando há espaço para ela. */
.sgsi-col-1, .sgsi-col-2, .sgsi-col-3, .sgsi-col-4,
.sgsi-col-5, .sgsi-col-6, .sgsi-col-7, .sgsi-col-8,
.sgsi-col-9, .sgsi-col-10, .sgsi-col-11, .sgsi-col-12 { grid-column: span 12 !important; }
@media (min-width: 640px) {
    .sgsi-col-1  { grid-column: span 1 !important; }
    .sgsi-col-2  { grid-column: span 2 !important; }
    .sgsi-col-3  { grid-column: span 3 !important; }
    .sgsi-col-4  { grid-column: span 4 !important; }
    .sgsi-col-5  { grid-column: span 5 !important; }
    .sgsi-col-6  { grid-column: span 6 !important; }
    .sgsi-col-7  { grid-column: span 7 !important; }
    .sgsi-col-8  { grid-column: span 8 !important; }
    .sgsi-col-9  { grid-column: span 9 !important; }
    .sgsi-col-10 { grid-column: span 10 !important; }
    .sgsi-col-11 { grid-column: span 11 !important; }
}

.sgsi-modal__intro {
    color: var(--sgsi-color-text-muted);
    font-size: var(--sgsi-font-size-sm);
    margin-bottom: var(--sgsi-space-4);
}

/* ----- Cards de estatística -----
   MÍNIMO DE 150px, NÃO 180px (auditoria UX 20/09): a coluna útil a 1280px é 952px (1280 − 280 da
   barra − 48 de padding) e cinco cartões de 180px pedem 964px — o quinto caía sozinho na segunda
   linha em nove telas da varredura (Notificações, Incidentes, Mudanças, Turmas, Objetivos,
   Análises críticas, Auditorias, Workflows, SoA). Com 150px cabem seis a 1280 e o gap de 12px
   aperta a faixa sem colar os cartões. A MARGEM INFERIOR SAIU quando a faixa é filha direta do
   corpo da página: o `gap` do `.sgsi-pagina__corpo` já separa, e os dois somados eram 48px de
   vazio entre os KPIs e os filtros. */
.sgsi-risco-stats {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(150px, 100%), 1fr));
    gap: var(--sgsi-space-3);
    margin-bottom: var(--sgsi-space-5);
}
/* Utilidades de espaçamento vertical (auditoria UX 20/09, L0.6): `sgsi-mt-2` era usada e não existia. */
.sgsi-mt-2 { margin-top: var(--sgsi-space-2); }
/* ---- Seção recolhível de formulário (SgsiSecaoFormulario, auditoria UX 20/09 §4.3) ---- */
.sgsi-form-secao { grid-column: 1 / -1; border-top: 1px solid var(--sgsi-color-border); padding-top: var(--sgsi-space-3); }
.sgsi-form-secao__titulo { display: flex; align-items: center; gap: var(--sgsi-space-2); cursor: pointer; list-style: none; font-weight: 600; font-size: var(--sgsi-font-size-sm); color: var(--sgsi-color-text); }
.sgsi-form-secao__titulo::-webkit-details-marker { display: none; }
.sgsi-form-secao__titulo svg { transition: transform .15s ease; }
.sgsi-form-secao[open] > .sgsi-form-secao__titulo svg { transform: rotate(180deg); }
.sgsi-form-secao__titulo:focus-visible { outline: 2px solid var(--sgsi-color-brand); outline-offset: 2px; border-radius: var(--sgsi-radius-sm); }
.sgsi-form-secao__sub { font-weight: 400; color: var(--sgsi-color-text-muted); }
.sgsi-form-secao__corpo { margin-top: var(--sgsi-space-3); }
/* Região da aba ativa (SgsiTabs.Painel, auditoria UX 20/09 §6.7): focável, sem moldura própria. */
.sgsi-tabs__painel { margin-top: var(--sgsi-space-4); outline: none; }
.sgsi-tabs__painel:focus-visible { outline: 2px solid var(--sgsi-color-brand); outline-offset: 2px; border-radius: var(--sgsi-radius-sm); }
/* ---- Vínculo entre registros e pessoa (auditoria UX 20/09, §3.7) ---- */
.sgsi-link-registro { display: inline-flex; align-items: center; gap: var(--sgsi-space-1); max-width: 100%; padding: 0.1rem 0.5rem; border: 1px solid var(--sgsi-color-border); border-radius: var(--sgsi-radius-pill, 999px); background: var(--sgsi-color-surface); color: var(--sgsi-color-text); font-size: var(--sgsi-font-size-sm); line-height: 1.4; text-decoration: none; vertical-align: middle; }
a.sgsi-link-registro:hover, a.sgsi-link-registro:focus-visible { border-color: var(--sgsi-color-brand); color: var(--sgsi-color-brand); text-decoration: none; }
.sgsi-link-registro--inerte { color: var(--sgsi-color-text-muted); }
.sgsi-link-registro__codigo { font-family: var(--sgsi-font-mono, ui-monospace, monospace); font-size: var(--sgsi-font-size-xs); font-weight: 600; white-space: nowrap; }
.sgsi-link-registro__nome { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 24ch; }
.sgsi-pessoa { display: inline-flex; align-items: center; gap: var(--sgsi-space-1); }
.sgsi-pessoa__nome { overflow-wrap: anywhere; }
/* Estado inicial do resumo (auditoria UX 20/09): uma frase no lugar de uma fileira de zeros. */
.sgsi-risco-stats__inicial { margin: 0; font-size: var(--sgsi-font-size-sm); color: var(--sgsi-color-text-muted); }
.sgsi-pagina__corpo > .sgsi-risco-stats,
.sgsi-pagina__corpo > .sgsi-stat-linha { margin-bottom: 0; }
/* ---- CARTAO DE NUMERO: HORIZONTAL, NAO EMPILHADO (30/08) ---------------------------------
   MEDIDO pela dissecacao: 131px de altura para exibir UM numero inteiro. A soma era
   16 (padding) + 36 (icone 2.25rem) + 4 (margin do icone) + 4 (gap) + 28 (valor 1.75rem)
   + 4 (gap) + 21 (rotulo) + 16 (padding) + 2 (bordas).

   O QUE INFLAVA NAO ERA O PADDING — era o BLOCO DE ICONE empilhado ACIMA do numero. Um
   icone decorativo consumindo 40px de ALTURA numa faixa cujo unico dado e um inteiro.

   Consequencia medida em tela cheia de 1366x768 (a resolucao de trabalho da maioria):
     · /documentos    — 505px de cromo antes da 1a linha; 2 linhas visiveis, ZERO num Chrome com abas
     · /clientes      — a grade comeca a 623px; 2 das 25 linhas pedidas cabem
     · /riscos        — 2 linhas; ZERO com abas
     · /governanca/saude — 677px de 728 antes do primeiro dado de diagnostico
     · dashboard      — nenhum dos 10 cartoes de dominio aparece sem rolar

   HORIZONTAL resolve os cinco de uma vez: icone 1.75rem A ESQUERDA, valor e rotulo empilhados
   a direita. ~64px de altura contra 131px — a faixa de KPI de toda tela-indice devolve ~67px
   de area util, e a lista volta para cima da dobra.

   O ICONE NAO SAI, e isso e deliberado: ele e o que distingue as quatro ou cinco metricas de
   relance numa faixa. O que muda e o EIXO — ele para de empurrar o dado para baixo. */
/* GRID, e nao flex com wrapper: o markup de `SgsiCartaoMetrica` tem os TRES elementos como
   irmaos diretos (icone, valor, rotulo), e ele e o canonico que substituiu 45 copias
   por-modulo. Um `<div>` intermediario obrigaria a mexer no componente e nos 17 call-sites que
   escrevem a marcacao a mao — e a versao antiga ficaria meio-consertada nesse meio-tempo.
   Com grid, o icone ocupa a coluna 1 nas DUAS linhas e o par valor/rotulo empilha na coluna 2,
   sem uma linha de markup nova. */
.sgsi-risco-stat {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    align-items: center;
    column-gap: var(--sgsi-space-2);
    padding: var(--sgsi-space-2) var(--sgsi-space-3);
    background: var(--sgsi-color-surface);
    border: 1px solid var(--sgsi-color-border);
    border-radius: var(--sgsi-radius-lg);
    box-shadow: var(--sgsi-shadow-sm);
    color: inherit;
    text-decoration: none;
    text-align: left;
    font: inherit;
}
/* O CARTÃO PODE SER LINK OU BOTÃO (auditoria UX 20/09): um KPI que só ocupa altura e não leva a
   nada é o que a varredura chamou de "número morto". Com `Href`/`OnClick` o SgsiCartaoMetrica vira
   <a>/<button> com a MESMA aparência, e `--ativo` marca o recorte aplicado (o KPI que filtrou a
   grade). Só o interativo ganha hover e foco; o estático continua inerte, sem fingir clique. */
.sgsi-risco-stat--interativo { cursor: pointer; transition: border-color var(--sgsi-transition-fast), box-shadow var(--sgsi-transition-fast); }
.sgsi-risco-stat--interativo:hover { border-color: var(--sgsi-color-brand); box-shadow: var(--sgsi-shadow-md); text-decoration: none; color: inherit; }
.sgsi-risco-stat--interativo:focus-visible { outline: var(--sgsi-focus-ring-width) solid var(--sgsi-color-brand); outline-offset: 2px; }
.sgsi-risco-stat--ativo { border-color: var(--sgsi-color-brand); box-shadow: inset 3px 0 0 0 var(--sgsi-color-brand); }

.sgsi-risco-stat__icone { grid-row: 1 / span 2; grid-column: 1; }
.sgsi-risco-stat__valor  { grid-column: 2; align-self: end; }
.sgsi-risco-stat__rotulo { grid-column: 2; align-self: start; }

/* O ESTADO DE ERRO do SgsiPainelMetricas tem SO icone + rotulo (sem valor). Sem esta regra o
   rotulo cairia na linha 2 e o cartao ficaria com a metade de cima vazia. `:only-of-type` casa
   exatamente esse caso: rotulo sem valor irmao. */
.sgsi-risco-stat__rotulo:only-of-type { grid-row: 1 / span 2; align-self: center; }

.sgsi-risco-stat__icone {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.5rem; height: 1.5rem;
    flex: 0 0 auto;
    border-radius: var(--sgsi-radius-md);
}
.sgsi-risco-stat__icone--marca   { background: var(--sgsi-color-brand);      color: var(--sgsi-color-text-on-accent); }
.sgsi-risco-stat__icone--sucesso { background: var(--sgsi-color-success-bg); color: var(--sgsi-color-success); }
.sgsi-risco-stat__icone--aviso   { background: var(--sgsi-color-warning-bg); color: var(--sgsi-color-warning); }
.sgsi-risco-stat__icone--perigo  { background: var(--sgsi-color-danger-bg);  color: var(--sgsi-color-danger); }
.sgsi-risco-stat__icone--info    { background: var(--sgsi-color-info-bg);    color: var(--sgsi-color-info); }
.sgsi-risco-stat__icone--neutro  { background: var(--sgsi-color-surface-2);  color: var(--sgsi-color-text-muted); }
/* `tabular-nums`: sem ele os digitos tem largura PROPORCIONAL, e um KPI que vai de 8 para 11
   muda a largura do texto — o numero "dança" a cada atualizacao do painel. A familia
   `.sgsi-evid__stat` ja tinha isto desde sempre; as outras duas nao, e era a unica coisa que
   distinguia as tres de verdade aos olhos de quem fica olhando o painel. */
.sgsi-risco-stat__valor  { font-size: var(--sgsi-font-size-lg); font-weight: 700; color: var(--sgsi-color-text); line-height: 1.1; font-variant-numeric: tabular-nums; }
.sgsi-risco-stat__rotulo { font-size: var(--sgsi-font-size-xs); color: var(--sgsi-color-text-muted); line-height: 1.25; }



/* ----- Cartão de número SEM ícone (`sgsi-stat`) -----------------------------------------
   Variante enxuta do cartão acima, para telas que exibem só número + rótulo. Estava sendo
   usada em 34 lugares — portal do AUDITOR EXTERNO, Equipe e outras — e NÃO EXISTIA NO CSS:
   `valor` e `rotulo` são <span>, portanto inline, e sem regra saíam COLADOS na mesma linha,
   sem tamanho nem cor. A primeira tela que um auditor externo vê é justamente uma dessas.
   Herda deliberadamente os mesmos tokens de `.sgsi-risco-stat` (fundo, borda, raio, sombra e
   a escala 2xl/sm) — duas famílias de cartão de número com aparências diferentes seriam pior
   que uma sem estilo. `auto-fit` com mínimo de 180px: 2 cartões ocupam a linha inteira em
   telas largas e empilham sozinhos no celular, sem media query. */
.sgsi-stat-linha {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(180px, 100%), 1fr));
    gap: var(--sgsi-space-4);
    margin-bottom: var(--sgsi-space-5);
}
/* ---- TRES FAMILIAS DE CARTAO DE NUMERO, TRES MEDIDAS DIFERENTES (30/08) ------------------
   O `.sgsi-risco-stat` foi para 0.75rem/1rem de padding e valor `xl` no conserto de densidade
   desta mesma passagem. As DUAS IRMAS ficaram para tras — o padrao dominante desta base: o
   conserto fecha o caso que o achado nomeava e deixa o irmao de fora.

   O QUE ESTAVA DESCASADO, medido nas declaracoes: tres paddings (1rem / 1rem / 0.75rem), dois
   raios (lg 12px / md 8px) e dois tamanhos de valor (1.75rem no `.sgsi-stat`, 1.375rem nas
   outras). O `.sgsi-stat` e o cartao que o portal do AUDITOR EXTERNO mostra na primeira tela:
   um numero em 28px ao lado de um irmao em 22px, na mesma sessao, e o tipo de descasamento que
   um avaliador enxerga antes de olhar o dado.

   O 2xl SAI TAMBEM POR HIERARQUIA: `--sgsi-font-size-2xl` (1.75rem/700) e exatamente a medida
   do `.sgsi-pagina__titulo`. Numa tela-indice com 4 KPIs, o h1 da pagina disputava o olho com
   quatro numeros no mesmo peso e tamanho, e nada vencia. `xl` mantem o valor como o maior
   elemento DENTRO do cartao — que e onde a hierarquia do KPI importa — e devolve o titulo da
   pagina ao topo da escala. */
.sgsi-stat {
    display: flex;
    flex-direction: column;
    gap: var(--sgsi-space-1);
    padding: var(--sgsi-space-3) var(--sgsi-space-4);
    background: var(--sgsi-color-surface);
    border: 1px solid var(--sgsi-color-border);
    border-radius: var(--sgsi-radius-lg);
    box-shadow: var(--sgsi-shadow-sm);
}
.sgsi-stat__valor  { font-size: var(--sgsi-font-size-lg); font-weight: 700; color: var(--sgsi-color-text); line-height: 1.1; font-variant-numeric: tabular-nums; }
.sgsi-stat__rotulo { font-size: var(--sgsi-font-size-sm); color: var(--sgsi-color-text-muted); }

/* ----- Picker com busca (seleção de vínculo em modal) ------------------------------------
   O plano quer PROPAGAR este picker aos ~243 modais que hoje pedem GUID colado à mão — e ele
   estava sem uma única regra: a lista saía como <ul> nu com marcadores, e cada item como botão
   padrão do navegador, com código e rótulo colados. Não se propaga um componente que não
   renderiza; escrever o CSS é pré-requisito daquele item, não um extra.
   Altura máxima com rolagem PRÓPRIA na lista: sem ela, um catálogo de 93 controles empurra o
   rodapé do modal para fora da tela e o botão de fechar fica inalcançável. */
.sgsi-picker { display: flex; flex-direction: column; gap: var(--sgsi-space-3); }
.sgsi-picker__busca { position: relative; }
.sgsi-picker__lista {
    list-style: none;
    margin: 0;
    padding: 0;
    max-height: 22rem;
    overflow-y: auto;
    border: 1px solid var(--sgsi-color-border);
    border-radius: var(--sgsi-radius-md);
}
.sgsi-picker__lista > li + li { border-top: 1px solid var(--sgsi-color-border); }
.sgsi-picker__item {
    display: flex;
    align-items: baseline;
    gap: var(--sgsi-space-3);
    width: 100%;
    padding: var(--sgsi-space-3) var(--sgsi-space-4);
    background: transparent;
    border: none;
    text-align: start;
    cursor: pointer;
    color: var(--sgsi-color-text);
}
/* :focus-visible junto de :hover — o picker é navegável por teclado (role="listbox"), e
   destacar só no mouse deixaria quem usa Tab sem saber onde está. */
.sgsi-picker__item:hover,
.sgsi-picker__item:focus-visible { background: var(--sgsi-color-surface-2); }
.sgsi-picker__codigo {
    flex: 0 0 auto;
    font-variant-numeric: tabular-nums;
    font-weight: 600;
    color: var(--sgsi-color-brand);
}
.sgsi-picker__rotulo { flex: 1 1 auto; }

/* Norma de origem do item, à direita da linha. O catálogo do Anexo A é MULTI-NORMA e chega a
   241 controles num tenant com as cinco normas que geram SoA: sem esta coluna, dois controles
   de normas diferentes com código e título parecidos ficam indistinguíveis, e o vínculo entra
   no relatório apontando para a norma errada. Fica discreto (secundário, menor) porque é
   procedência, não conteúdo — quem escolhe lê o título, e confere a norma. */
.sgsi-picker__norma {
    flex: 0 0 auto;
    margin-inline-start: auto;
    color: var(--sgsi-color-text-muted);
    font-size: var(--sgsi-font-size-sm);
    white-space: nowrap;
}

/* Aviso de lista truncada ("exibindo N de M — use a busca"). Sem regra ele saía com o mesmo
   tamanho e peso dos itens e colado na lista, lido como se fosse mais um resultado. Fica menor,
   secundário e afastado: é meta-informação sobre a lista, não conteúdo dela. */
.sgsi-picker__aviso {
    margin: var(--sgsi-space-2) 0 0;
    color: var(--sgsi-color-text-muted);
    font-size: var(--sgsi-font-size-sm);
    line-height: 1.4;
}

/* ----- Busca global (/busca) -------------------------------------------------------------
   A tela INTEIRA estava sem estilo: 13 classes usadas, nenhuma definida. O ícone de lupa
   ficava ANTES do campo em vez de dentro dele, a lista de resultados saía com marcadores de
   <ul> e cada resultado tinha código e título colados. É a tela que o usuário abre quando já
   não sabe onde procurar — a primeira em que a falta de acabamento pesa.
   `padding-inline-start` no input (e não `left` fixo) mantém o ícone correto em RTL. */
.sgsi-busca-form  { display: flex; flex-direction: column; gap: var(--sgsi-space-3); }
.sgsi-busca-campo { display: flex; flex-direction: column; gap: var(--sgsi-space-2); }
.sgsi-busca-linha { position: relative; display: flex; gap: var(--sgsi-space-3); align-items: center; }
.sgsi-busca-icone {
    position: absolute;
    inset-inline-start: var(--sgsi-space-3);
    display: inline-flex;
    color: var(--sgsi-color-text-muted);
    pointer-events: none; /* o clique tem de cair no input, não no ícone */
}
.sgsi-busca-input { flex: 1 1 auto; padding-inline-start: 2.5rem; }
.sgsi-busca-resumo {
    font-size: var(--sgsi-font-size-sm);
    color: var(--sgsi-color-text-muted);
    margin: var(--sgsi-space-3) 0;
}
.sgsi-busca-lista { list-style: none; margin: 0; padding: 0; }
.sgsi-busca-item + .sgsi-busca-item { border-top: 1px solid var(--sgsi-color-border); }
.sgsi-busca-item__link {
    display: flex;
    align-items: baseline;
    gap: var(--sgsi-space-3);
    padding: var(--sgsi-space-3) var(--sgsi-space-2);
    text-decoration: none;
    color: var(--sgsi-color-text);
}
.sgsi-busca-item__link:hover,
.sgsi-busca-item__link:focus-visible { background: var(--sgsi-color-surface-2); }
.sgsi-busca-item__codigo {
    flex: 0 0 auto;
    font-variant-numeric: tabular-nums;
    font-weight: 600;
    color: var(--sgsi-color-brand);
}
.sgsi-busca-item__titulo { flex: 1 1 auto; }

/* Texto de ajuda sob um campo — irmão de .sgsi-field__dica, que já existe. */
.sgsi-field__ajuda { font-size: var(--sgsi-font-size-sm); color: var(--sgsi-color-text-muted); }

/* ----- Campo avulso (fora do SgsiField/SgsiForm) -----------------------------------------
   Invólucro simples para os poucos modais que montam o campo à mão. NÃO recebe estilo de
   rótulo nem de input: aqueles vieram de `sgsi-rotulo`/`sgsi-input`, que não existiam no CSS —
   os inputs saíam com a aparência PADRÃO DO NAVEGADOR, destoando de todo o resto do app. A
   correção foi migrar os call-sites para `sgsi-field__label` e `form-control` (as peças que já
   existem), e NÃO escrever regras novas para as inventadas: duas famílias concorrentes de
   input seria repetir o defeito do `sgsi-alerta` × `sgsi-alert`. Aqui fica só o que não tinha
   equivalente — o empilhamento e a mensagem de erro. */
.sgsi-campo { display: flex; flex-direction: column; gap: var(--sgsi-space-2); }
.sgsi-campo + .sgsi-campo { margin-top: var(--sgsi-space-4); }
.sgsi-campo__erro { margin: var(--sgsi-space-2) 0 0; font-size: var(--sgsi-font-size-sm); color: var(--sgsi-color-danger); }
.sgsi-checkbox { display: flex; align-items: center; gap: var(--sgsi-space-2); }

/* ----- Matriz RASCI (atividades × papéis) -------------------------------------------------
   Tela-núcleo do produto e a que MAIS sofria com a falta de CSS: a matriz é larga por
   natureza (uma coluna por papel) e o invólucro não tinha `overflow-x`. Sem ele a tabela
   ESTOURA o cartão e empurra a largura da PÁGINA — o usuário perde a rolagem horizontal e as
   últimas colunas ficam inalcançáveis. É também a tela cuja versão em PDF acabou de ganhar a
   desambiguação por norma; ter o papel correto e a tela quebrada seria contraditório.
   A 1ª coluna é `position: sticky`: rolando para a direita, o nome da atividade permanece —
   sem isso, no meio da matriz o usuário vê uma grade de letras sem saber a que linha pertencem. */
.sgsi-rasci-matriz-wrap { overflow-x: auto; }
.sgsi-rasci-matriz__atividade {
    position: sticky;
    inset-inline-start: 0;
    z-index: 1;
    background: var(--sgsi-color-surface);
    min-width: 16rem;
    text-align: start;
    vertical-align: top;
}
.sgsi-rasci-matriz__papel { min-width: 4.5rem; text-align: center; white-space: nowrap; }
.sgsi-rasci-matriz__celula { text-align: center; vertical-align: middle; }
.sgsi-rasci-matriz__link {
    display: flex;
    flex-direction: column;
    gap: var(--sgsi-space-1);
    width: 100%;
    padding: 0;
    background: transparent;
    border: none;
    text-align: start;
    cursor: pointer;
    color: inherit;
}
.sgsi-rasci-matriz__link:hover .sgsi-risco-titulo,
.sgsi-rasci-matriz__link:focus-visible .sgsi-risco-titulo { text-decoration: underline; }
.sgsi-rasci-matriz__meta { display: flex; flex-wrap: wrap; gap: var(--sgsi-space-1); margin-top: var(--sgsi-space-1); }
.sgsi-rasci-matriz__linha--inativa { opacity: 0.55; }
/* A CÉLULA CLICÁVEL É UM <button> E NÃO TINHA REGRA NENHUMA (corrigido em 29/07).
   Sem reset do chrome nativo, CADA célula da matriz renderizava como botão cinza padrão do
   sistema operacional — fundo em degradê, borda 3D, fonte do SO — dentro de uma tabela do
   design system. Na matriz RASCI, que é o artefato que o auditor lê linha a linha.
   Só o `__vazia` (o "+") tinha estilo; o bloco e os modificadores, não.
   O R/A/S/C/I colorido vem do <SgsiBadge> dentro do botão — por isso aqui não há cor por
   variante: o botão é só o alvo de clique, e duplicar a cor criaria duas fontes da verdade. */
.sgsi-rasci-celula {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 2.25rem;
    min-height: 2.25rem;
    padding: var(--sgsi-space-1);
    background: none;
    border: 1px solid transparent;
    border-radius: var(--sgsi-radius-sm);
    color: inherit;
    font: inherit;
    cursor: pointer;
}
.sgsi-rasci-celula:hover { background: var(--sgsi-color-surface-2); }
.sgsi-rasci-celula:focus-visible { outline: 2px solid var(--sgsi-color-brand); outline-offset: 1px; }
.sgsi-rasci-celula__vazia { color: var(--sgsi-color-text-subtle); font-weight: 600; }
.sgsi-rasci-legenda { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sgsi-space-3); margin-top: var(--sgsi-space-4); font-size: var(--sgsi-font-size-sm); }
.sgsi-rasci-legenda__item { display: inline-flex; align-items: center; gap: var(--sgsi-space-1); }
.sgsi-rasci-aviso { font-size: var(--sgsi-font-size-sm); color: var(--sgsi-color-text-muted); }

/* ====== LOTE 2 — famílias transversais sem regra ==========================================
   Continuação da varredura: classes usadas em várias telas que renderizavam sem estilo.
   Cada bloco diz o que estava torto, não só o que faz. */

/* O ÍCONE — a classe mais usada do produto e a que não tinha regra (29/07).
   Está no <svg> de TODO ícone (Ui/Icone.razor). A cor não estava quebrada: o elemento traz
   fill="currentColor" e width/height inline. O que faltava é o que só o CSS resolve:
   • vertical-align — o svg é inline e senta na LINHA DE BASE, ficando ~2px abaixo do texto
     ao lado. Em botão e em item de menu isso aparece como ícone "caído".
   • flex-shrink — dentro de flex (todo botão com ícone + rótulo é flex), o svg ENCOLHE
     quando o texto é longo, e o ícone deforma em vez de o texto truncar. */
.sgsi-icone { flex-shrink: 0; vertical-align: -0.125em; }

/* Coluna de AÇÕES / centralizada em tabela (18 + 2 usos). Sem regra a coluna de ações
   participava da distribuição de largura como qualquer outra e ESTICAVA, roubando espaço das
   colunas de conteúdo. `width: 1%` + `nowrap` é o idioma para "só o necessário". */
.sgsi-col-acoes  { width: 1%; white-space: nowrap; text-align: center; }
.sgsi-col-centro { text-align: center; }
/* Explícita para documentar a INTENÇÃO (start já é o padrão): 22 usos que não quebravam nada,
   mas cuja ausência no CSS fazia parecer que a classe fazia algo. */
.sgsi-grid__th--inicio, .sgsi-grid__td--inicio { text-align: start; }

/* Área do CONTROLE dentro de um .sgsi-field (40 usos). `.sgsi-field` já é flex-column, então
   a div funcionava — mas em campo de LEITURA (um <span> com o valor) a altura ficava menor que
   a de um input, desalinhando a linha do formulário quando os dois convivem lado a lado. */
.sgsi-field__controle { display: flex; align-items: center; min-height: 2.25rem; }

/* Checkbox/opções em formulário. */
.sgsi-form-check       { display: flex; align-items: center; gap: var(--sgsi-space-2); }
.sgsi-form__inline-check { display: flex; align-items: center; gap: var(--sgsi-space-2); }
.sgsi-check            { display: flex; align-items: flex-start; gap: var(--sgsi-space-2); }
.sgsi-check-lista      { display: flex; flex-direction: column; gap: var(--sgsi-space-2); }
.sgsi-fieldset         { border: none; margin: 0; padding: 0; min-width: 0; }
.sgsi-form-grade       { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(14rem, 100%), 1fr)); gap: var(--sgsi-space-4); }
.sgsi-form-acoes       { display: flex; flex-wrap: wrap; gap: var(--sgsi-space-2); margin-top: var(--sgsi-space-4); }
.sgsi-form-acoes-linha { display: flex; flex-wrap: wrap; gap: var(--sgsi-space-2); align-items: center; }

/* Linha de tabela que leva a um detalhe. O cursor é o ÚNICO aviso de que a linha é clicável —
   sem ele o usuário não descobre a navegação. Realce também no :focus-within, para quem chega
   pelo teclado no link/botão de dentro da linha. */
.sgsi-linha-acionavel, .sgsi-linha-clicavel { cursor: pointer; }
.sgsi-linha-acionavel:hover, .sgsi-linha-clicavel:hover,
.sgsi-linha-acionavel:focus-within, .sgsi-linha-clicavel:focus-within { background: var(--sgsi-color-surface-2); }

/* Separador "ou" das alternativas de login (SSO / social). Sem regra o <span> ficava solto no
   fluxo, sem as linhas laterais — parecendo texto perdido entre os blocos. */
.sgsi-auth-card__ou {
    display: flex;
    align-items: center;
    gap: var(--sgsi-space-3);
    margin: var(--sgsi-space-4) 0;
    color: var(--sgsi-color-text-muted);
    font-size: var(--sgsi-font-size-sm);
}
.sgsi-auth-card__ou::before, .sgsi-auth-card__ou::after {
    content: "";
    flex: 1 1 auto;
    border-top: 1px solid var(--sgsi-color-border);
}
.sgsi-auth-card__sso, .sgsi-auth-card__social { display: flex; flex-direction: column; gap: var(--sgsi-space-2); }

/* 2FA e segredos. `sgsi-lista-codigos` são os códigos de recuperação de uso único: fonte
   MONOESPAÇADA e `user-select: all` porque o usuário precisa copiá-los sem errar um caractere —
   errar aqui é perder o acesso à conta. Mesma razão no segredo TOTP e na chave de API. */
.sgsi-lista-codigos {
    list-style: none;
    margin: var(--sgsi-space-3) 0;
    padding: 0;
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(9rem, 100%), 1fr));
    gap: var(--sgsi-space-2);
    font-family: var(--sgsi-font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
}
.sgsi-lista-codigos > li {
    padding: var(--sgsi-space-2);
    background: var(--sgsi-color-surface-2);
    border-radius: var(--sgsi-radius-sm);
    text-align: center;
    user-select: all;
}
.sgsi-2fa-qr { display: block; }
.sgsi-2fa-segredo, .sgsi-segredo__valor {
    font-family: var(--sgsi-font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
    word-break: break-all;
    user-select: all;
}
.sgsi-segredo {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--sgsi-space-2);
    padding: var(--sgsi-space-3);
    background: var(--sgsi-color-surface-2);
    border-radius: var(--sgsi-radius-md);
}

/* ====== LOTE 3 — seções de páginas de detalhe ============================================= */

/* Seletor de tenant do CONSULTOR MULTI-CLIENTE. O destrave do bloqueador nº 1 (o consultor
   negado em toda rota de tenant) foi entregue com estas três classes sem regra: a busca colada
   na lista, o "carregar mais" com cara de botão nativo e o vazio sem respiro. É o componente
   que ~55-60% do MRR usa em TODA navegação — a peça mais cara para estar sem acabamento. */
.sgsi-seletor-tenant__busca { padding: var(--sgsi-space-2); border-bottom: 1px solid var(--sgsi-color-border); }
.sgsi-seletor-tenant__vazio {
    padding: var(--sgsi-space-4);
    text-align: center;
    color: var(--sgsi-color-text-muted);
    font-size: var(--sgsi-font-size-sm);
}
.sgsi-seletor-tenant__mais {
    width: 100%;
    padding: var(--sgsi-space-2);
    background: transparent;
    border: none;
    border-top: 1px solid var(--sgsi-color-border);
    color: var(--sgsi-color-brand);
    font-size: var(--sgsi-font-size-sm);
    cursor: pointer;
}
.sgsi-seletor-tenant__mais:hover,
.sgsi-seletor-tenant__mais:focus-visible { background: var(--sgsi-color-surface-2); }

/* Abas de detalhe (Estimativas): título à esquerda, ação à direita, na MESMA linha. Sem regra
   o botão caía para baixo do título, em toda aba. */
.sgsi-est-aba-toolbar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--sgsi-space-3);
    margin-bottom: var(--sgsi-space-3);
}
.sgsi-est-aba-titulo { margin: 0; font-size: var(--sgsi-font-size-lg); }
.sgsi-est-aba-corpo  { display: flex; flex-direction: column; gap: var(--sgsi-space-3); }
.sgsi-est-acoes      { white-space: nowrap; }

/* Lista de dados cadastrais em <dl> — mesmo defeito do sgsi-kv: sem regra, <dd> herda o recuo
   do navegador e o valor aparece indentado numa linha própria. */
.sgsi-perfil-dl { margin: 0; }
.sgsi-perfil-dl__item {
    display: flex;
    flex-wrap: wrap;
    gap: var(--sgsi-space-2);
    padding: var(--sgsi-space-2) 0;
    border-bottom: 1px solid var(--sgsi-color-border);
}
.sgsi-perfil-dl__item:last-child { border-bottom: none; }
.sgsi-perfil-dl__item > dt { flex: 0 0 12rem; margin: 0; font-weight: 600; color: var(--sgsi-color-text-muted); }
.sgsi-perfil-dl__item > dd { flex: 1 1 16rem; margin: 0; }

/* Fases e marcos do plano de implementação: cartões empilhados com cabeçalho em duas pontas. */
.sgsi-plano-fases, .sgsi-plano-marcos { display: flex; flex-direction: column; gap: var(--sgsi-space-4); }
.sgsi-plano-fase, .sgsi-plano-marco {
    padding: var(--sgsi-space-4);
    background: var(--sgsi-color-surface);
    border: 1px solid var(--sgsi-color-border);
    border-radius: var(--sgsi-radius-lg);
}
.sgsi-plano-fase__cab, .sgsi-plano-marco__info {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--sgsi-space-3);
}
.sgsi-plano-fase__titulo, .sgsi-plano-marco__titulo { margin: 0; font-size: var(--sgsi-font-size-md); }
.sgsi-plano-fase__acoes, .sgsi-plano-marco__acoes { display: flex; flex-wrap: wrap; gap: var(--sgsi-space-2); }
.sgsi-plano-fase__vazio { color: var(--sgsi-color-text-muted); font-size: var(--sgsi-font-size-sm); }

/* Partes interessadas (contexto, cl. 4.2). */
.sgsi-parte {
    padding: var(--sgsi-space-4);
    background: var(--sgsi-color-surface);
    border: 1px solid var(--sgsi-color-border);
    border-radius: var(--sgsi-radius-lg);
    margin-bottom: var(--sgsi-space-3);
}
.sgsi-parte__cab { display: flex; flex-wrap: wrap; align-items: flex-start; justify-content: space-between; gap: var(--sgsi-space-3); }
.sgsi-parte__badges { display: flex; flex-wrap: wrap; gap: var(--sgsi-space-2); }
.sgsi-parte__acoes  { display: flex; flex-wrap: wrap; gap: var(--sgsi-space-2); }
.sgsi-parte__exp, .sgsi-parte__req { margin-top: var(--sgsi-space-3); }
.sgsi-parte__req-cab { font-weight: 600; color: var(--sgsi-color-text-muted); font-size: var(--sgsi-font-size-sm); }

/* Manual do SGI. `sgsi-manual-codigo` é referência de cláusula: tabular-nums mantém a coluna
   de números alinhada, que é o que um auditor percorre com o dedo. */
.sgsi-manual-secoes  { display: flex; flex-direction: column; gap: var(--sgsi-space-3); }
/* Também usada como <ul> (a lista dos Manuais já criados, um por norma, em /manual): o reset de
   marcador e recuo mora aqui para o mesmo bloco servir a <div> e a <ul> sem uma segunda classe.
   A lista é semanticamente uma lista; o bullet ao lado de um nome de norma em negrito é ruído. */
.sgsi-manual-linhas  { display: flex; flex-direction: column; gap: var(--sgsi-space-2); list-style: none; margin: 0; padding: 0; }
.sgsi-manual-detalhe { display: flex; flex-direction: column; gap: var(--sgsi-space-2); }
.sgsi-manual-codigo  { font-variant-numeric: tabular-nums; font-weight: 600; color: var(--sgsi-color-brand); }
.sgsi-manual-captura-aviso { color: var(--sgsi-color-text-muted); font-size: var(--sgsi-font-size-sm); }

/* FAIXA DE SELOS DE NORMA — o desenho de "este item serve a N normas", em UM lugar (30/08).
   O produto carrega 12 normas e a mesma faixa de selos aparece na lista de templates, na de
   estimativas e no cabeçalho dos módulos temáticos. Estava cravada com nome de UMA feature
   (`sgsi-template-normas`), então toda tela nova ou repetia a regra com outro nome ou importava
   um seletor que mente sobre o dono. `sgsi-selos-norma` é o nome do PADRÃO; o antigo fica como
   apelido para não mexer nas telas de template. */
.sgsi-selos-norma,
.sgsi-template-normas { display: flex; flex-wrap: wrap; gap: var(--sgsi-space-2); }
.sgsi-template-subtitulo { color: var(--sgsi-color-text-muted); font-size: var(--sgsi-font-size-sm); }
.sgsi-template-conteudo, .sgsi-template-conteudo-preview {
    white-space: pre-wrap;
    word-break: break-word;
    font-family: var(--sgsi-font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
    font-size: var(--sgsi-font-size-sm);
}
.sgsi-template-conteudo-preview {
    max-height: 24rem;
    overflow-y: auto;
    padding: var(--sgsi-space-3);
    background: var(--sgsi-color-surface-2);
    border-radius: var(--sgsi-radius-md);
}

/* Impactos de mudança (linhas dinâmicas dentro de modal). */
.sgsi-impactos-secao { margin-bottom: var(--sgsi-space-4); }
.sgsi-impactos-secao__cab { display: flex; align-items: center; justify-content: space-between; gap: var(--sgsi-space-3); }
.sgsi-impactos-secao__titulo { margin: 0; font-size: var(--sgsi-font-size-md); }
.sgsi-impactos-linha { display: flex; flex-wrap: wrap; gap: var(--sgsi-space-2); align-items: flex-end; }
.sgsi-impactos-remover { display: flex; align-items: flex-end; }

/* Cobertura do Anexo A + textos longos de detalhe. */
.sgsi-anexoa-cobertura { display: flex; flex-wrap: wrap; gap: var(--sgsi-space-4); }
.sgsi-anexoa-cobertura__item { display: flex; flex-direction: column; gap: var(--sgsi-space-1); }
.sgsi-anexoa-cobertura__valor { font-size: var(--sgsi-font-size-lg); font-weight: 700; }
.sgsi-anexoa-descricao, .sgsi-notif-descricao { white-space: pre-wrap; word-break: break-word; }

/* Miudezas de uma tela só, todas com o mesmo sintoma: elemento inline/bloco sem espaçamento. */
.sgsi-consentimento-validade__linha { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--sgsi-space-3); }
.sgsi-comece-progresso { display: flex; flex-direction: column; gap: var(--sgsi-space-2); }
.sgsi-confirm__detalhe-item { display: flex; gap: var(--sgsi-space-2); font-size: var(--sgsi-font-size-sm); }
.sgsi-cr-vinculo { display: flex; flex-wrap: wrap; gap: var(--sgsi-space-2); align-items: center; }
.sgsi-gap-item-cabecalho { display: flex; flex-wrap: wrap; gap: var(--sgsi-space-2); align-items: baseline; }
/* `.sgsi-hub-gestao` REMOVIDA em 03/09. Ela punha `display:grid` num <section> cujos tres
   filhos sao <h2> + <p> + <ul> — o titulo virava uma coluna, o paragrafo outra, e os sete
   cartoes ficavam espremidos numa terceira, com dois tercos da largura vazios. Era esse o
   defeito que o dono fotografou no Centro de Comando. A grade certa mora agora no CSS
   isolado da propria pagina (`.sgsi-cc-hub`) e governa a <ul>, que e o conjunto de fato
   repetido. Sem consumidor, a regra so criava a ilusao de que o hub estava resolvido. */
.sgsi-sig-item__resposta { display: flex; flex-wrap: wrap; gap: var(--sgsi-space-3); align-items: center; }
.sgsi-sig-item__obs { margin-top: var(--sgsi-space-2); font-size: var(--sgsi-font-size-sm); color: var(--sgsi-color-text-muted); }
.sgsi-vinculo { display: flex; flex-wrap: wrap; gap: var(--sgsi-space-2); align-items: center; }
.sgsi-vinculo__acoes { display: flex; gap: var(--sgsi-space-2); }
/* O VALOR do vínculo não tinha regra (29/07): o bloco e o __acoes tinham, ele não. Sem o
   estado vazio distinguível, "nenhum vínculo" ficava indistinguível de um vínculo com nome
   curto — e vínculo é o que liga indicador a controle/risco/objetivo na evidência. */
.sgsi-vinculo__valor { min-width: 0; overflow-wrap: anywhere; }
.sgsi-vinculo__valor--vazio { color: var(--sgsi-color-text-subtle); font-style: italic; }
.sgsi-vinculos-sep { color: var(--sgsi-color-text-subtle); }
/* A MENSAGEM DE ERRO É LONGA JUSTAMENTE NA HORA EM QUE A TELA IMPORTA (30/08): quem abre a
   fila de veneno é o operador com o outbox entupido, e aí o "último erro" costuma ser um
   stack trace de centenas de caracteres. Com `pre-wrap` e sem teto, UMA linha da grade
   passava de 150px e a página de 25 eventos mostrava três — o operador rola procurando o
   padrão entre as falhas e nunca vê duas ao mesmo tempo. O texto continua INTEIRO no DOM
   (só é aparado visualmente) e o `title` do call-site entrega o resto ao passar o mouse. */
.sgsi-outbox-erro {
    display: -webkit-box;
    -webkit-line-clamp: 3;
    line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
    white-space: pre-wrap;
    word-break: break-word;
    font-size: var(--sgsi-font-size-sm);
    color: var(--sgsi-color-danger);
}
.sgsi-trilha__integ-icone { display: inline-flex; color: var(--sgsi-color-text-muted); }
.sgsi-progress__rotulo { font-size: var(--sgsi-font-size-sm); color: var(--sgsi-color-text-muted); }
.sgsi-ameaca-item__saas { font-size: var(--sgsi-font-size-xs); color: var(--sgsi-color-text-muted); }
.sgsi-ameaca-picker__filtro--busca { flex: 1 1 14rem; }
.sgsi-topbar__toggle { display: inline-flex; align-items: center; justify-content: center; background: transparent; border: none; color: inherit; cursor: pointer; }

/* Página de erro: as classes existiam como ganchos e o conteúdo vinha com estilo INLINE. Aqui
   só o LAYOUT (centralização e respiro) sai do inline para a folha — o resto do inline segue
   como está, para não mexer no visual sem necessidade. */
.sgsi-error-page { display: flex; flex-direction: column; align-items: center; padding: var(--sgsi-space-6) var(--sgsi-space-4); }
.sgsi-error-page__illustration { width: 100%; max-width: 300px; }
.sgsi-error-page__content { max-width: 34rem; text-align: center; display: flex; flex-direction: column; align-items: center; gap: var(--sgsi-space-4); }
/* SgsiPaginaDeErro (auditoria UX 20/09, §6.1): o que era `style=` inline nas três páginas de erro. */
.sgsi-error-page__svg { width: 100%; height: auto; display: block; margin: 0 auto; }
.sgsi-error-page__codigo { font-family: var(--sgsi-font-sans); font-size: 48px; font-weight: 700; }
.sgsi-error-page__titulo { margin: 0; font-weight: 700; letter-spacing: -0.03em; color: var(--sgsi-color-text); }
.sgsi-error-page__texto { margin: 0; color: var(--sgsi-color-text-muted); font-size: var(--sgsi-font-size-lg); }
.sgsi-error-page__ref { margin: 0; color: var(--sgsi-color-text-muted); font-size: var(--sgsi-font-size-sm); }
.sgsi-error-page__ref code { font-family: var(--sgsi-font-mono); font-weight: 600; color: var(--sgsi-color-text); }
.sgsi-error-page__illustration--brand, .sgsi-error-page__illustration--warning, .sgsi-error-page__illustration--danger { color: inherit; }

/* Confirmação de descarte do SgsiModal (dirty-guard). Vinha com estilo INLINE e uma nota no
   componente dizendo que a promoção para classes ficava "para a onda de páginas/CSS" — é esta.
   Promovido porque inline não responde a tema, não é sobrescrevível por página e obriga quem
   lê o componente a decorar tokens. As regras são as MESMAS que estavam no atributo `style`:
   nenhuma decisão visual nova foi tomada aqui. */
.sgsi-modal__confirma-descarte {
    position: absolute;
    inset: 0;
    z-index: 10;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--sgsi-color-backdrop);
    border-radius: inherit;
}
.sgsi-modal__confirma-descarte-caixa {
    background: var(--sgsi-color-surface);
    border: 1px solid var(--sgsi-color-border);
    border-radius: var(--sgsi-radius-lg);
    box-shadow: var(--sgsi-shadow-lg);
    padding: var(--sgsi-space-5);
    margin: var(--sgsi-space-4);
    max-width: 26rem;
    text-align: center;
}
.sgsi-modal__confirma-descarte-texto  { margin: 0 0 var(--sgsi-space-4); }
.sgsi-modal__confirma-descarte-acoes  { display: flex; justify-content: center; gap: var(--sgsi-space-2); }

/* Linha de ações de uma célula da tabela de usuários. A classe existia no .razor e nunca no
   CSS: os botões saíam grudados, sem gap nem quebra. Aponta para o mesmo comportamento do
   utilitário genérico .sgsi-acoes-linha — mantida como alias até a migração do call-site. */
.sgsi-usuario-acoes {
    display: flex;
    flex-wrap: wrap;
    gap: var(--sgsi-space-2);
    align-items: center;
    justify-content: center;
}

/* ----- Filtros ----- */
/* Nome neutro: o cartão de filtros é usado por ~46 telas de TODOS os módulos;
   o prefixo -risco- é legado a migrar nos call-sites (mesma regra p/ ambos). */
.sgsi-filtros-card,
.sgsi-risco-filtros-card { margin-bottom: var(--sgsi-space-4); }
.sgsi-risco-filtros {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(200px, 100%), 1fr));
    gap: var(--sgsi-space-4);
    padding: var(--sgsi-space-4);
}
.sgsi-risco-filtro { display: flex; flex-direction: column; gap: var(--sgsi-space-1); }

/* ----- Células da lista ----- */
.sgsi-risco-codigo { font-family: var(--sgsi-font-mono, monospace); font-size: var(--sgsi-font-size-sm); color: var(--sgsi-color-text-muted); }
.sgsi-risco-titulo { font-weight: 600; color: var(--sgsi-color-text); }
.sgsi-risco-dono   { font-size: var(--sgsi-font-size-xs); color: var(--sgsi-color-text-subtle); }

/* ----- Detalhe ----- */
.sgsi-risco-detalhe {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(280px, 100%), 1fr));
    gap: var(--sgsi-space-4);
    align-items: start;
}
/* ESCAPE DE LARGURA (23/09). A grade acima é de colunas estreitas (mín. 280px), e um filho que
   hospeda TABELA nasce recortado ali dentro — sem rolagem, o usuário simplesmente não vê as
   últimas colunas. Este modificador dá a linha inteira ao filho, sem tirar a grade de duas
   colunas do resto. O detalhe de documento já tinha o recurso com nome próprio; agora ele existe
   no detalhe genérico, e nasce com consumidor: a matriz de responsabilidade de nuvem. */
.sgsi-risco-detalhe__largo { grid-column: 1 / -1; }
/* Lista chave→valor em <dl>: rótulo acima, valor abaixo, um par por <div>. Esta é a ÚNICA
   versão do componente — havia uma segunda, de duas colunas, cujas larguras fixas viravam
   ALTURA depois que esta definiu a direção em coluna, esticando um cartão de quatro linhas
   por mais de mil pixels. Ao acrescentar um par, use <div><dt>rótulo</dt><dd>valor</dd></div>. */
.sgsi-kv { margin: 0; display: flex; flex-direction: column; gap: var(--sgsi-space-3); }
.sgsi-kv > div { display: flex; flex-direction: column; gap: 2px; }
.sgsi-kv dt { font-size: var(--sgsi-font-size-xs); text-transform: uppercase; letter-spacing: .04em; color: var(--sgsi-color-text-subtle); margin: 0; }
.sgsi-kv dd { margin: 0; color: var(--sgsi-color-text); }
.sgsi-kv__sub { color: var(--sgsi-color-text-muted); font-size: var(--sgsi-font-size-sm); }
.sgsi-risco-controles { margin: 0; padding-left: var(--sgsi-space-5); display: flex; flex-direction: column; gap: var(--sgsi-space-1); }
.sgsi-risco-controles code { font-size: var(--sgsi-font-size-xs); color: var(--sgsi-color-text-muted); }

/* ── CHIPS DE SELEÇÃO (30/08) ──
   `.sgsi-risco-controles` acima é a LISTA de leitura: um <ul> em coluna, com o recuo do
   marcador. Os modais de associação reusavam essa classe para a fita de itens JÁ
   SELECIONADOS — que são botões de remover, não itens de leitura —, e o resultado era uma
   coluna de botões esticados: dez controles do Anexo A empurravam ~350px de formulário para
   baixo, inclusive o botão de salvar, dentro de um modal que já rola. Chip é fita que QUEBRA
   LINHA; sem recuo, porque não há marcador nenhum a alinhar. */
.sgsi-chips { margin: 0; padding-left: 0; list-style: none; display: flex; flex-wrap: wrap; gap: var(--sgsi-space-2); align-items: center; }

/* ----- Ações decorrentes da análise crítica (cl. 9.3.3) ----- */
.sgsi-acoes-decorrentes { margin: 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: var(--sgsi-space-3); }
.sgsi-acao-item {
    padding: var(--sgsi-space-3) var(--sgsi-space-4);
    border: 1px solid var(--sgsi-color-border);
    border-radius: var(--sgsi-radius-md);
    background: var(--sgsi-color-surface);
    display: flex; flex-direction: column; gap: var(--sgsi-space-1);
}
.sgsi-acao-item__cabeca { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--sgsi-space-2); }
.sgsi-acao-item__id { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sgsi-space-2); }
.sgsi-acao-item__botoes { display: flex; flex-wrap: wrap; gap: var(--sgsi-space-1); }
.sgsi-acao-item__desc { margin: 0; color: var(--sgsi-color-text); }
.sgsi-acao-item__vinculo {
    display: inline-flex; align-items: center; gap: 2px;
    font-size: var(--sgsi-font-size-sm); color: var(--sgsi-color-text-muted); text-decoration: none;
}
.sgsi-acao-item__vinculo:hover { text-decoration: underline; }

/* ----- Prévia / avaliação ----- */
.sgsi-risco-previa {
    margin-top: var(--sgsi-space-4);
    display: flex; align-items: center; gap: var(--sgsi-space-2);
    color: var(--sgsi-color-text-muted); font-size: var(--sgsi-font-size-sm);
}

/* ----- Alerta DPO ----- */
.sgsi-risco-alerta-dpo {
    display: flex; align-items: flex-start; gap: var(--sgsi-space-2);
    padding: var(--sgsi-space-3) var(--sgsi-space-4);
    background: var(--sgsi-color-warning-bg);
    color: var(--sgsi-color-warning);
    border-radius: var(--sgsi-radius-md);
    margin-bottom: var(--sgsi-space-4);
    font-size: var(--sgsi-font-size-sm);
}
.sgsi-field__check { display: flex; align-items: center; gap: var(--sgsi-space-2); cursor: pointer; }

/* ----- Input com ação acoplada (ex.: campo + botão "Catálogo") ----- */
.sgsi-input-acao { display: flex; gap: var(--sgsi-space-2); align-items: stretch; }
.sgsi-input-acao > .form-control { flex: 1 1 auto; min-width: 0; }
.sgsi-input-acao > .btn { flex: 0 0 auto; white-space: nowrap; }

/* ----- Apetite ao risco (cards por categoria) ----- */
.sgsi-apetite-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(300px, 100%), 1fr));
    gap: var(--sgsi-space-4);
    align-items: start;
}
.sgsi-apetite-card__cab { display: flex; align-items: center; justify-content: space-between; gap: var(--sgsi-space-2); width: 100%; }
.sgsi-apetite-card__just { color: var(--sgsi-color-text-muted); font-size: var(--sgsi-font-size-sm); }
.sgsi-apetite-card .sgsi-card__rodape { display: flex; flex-wrap: wrap; gap: var(--sgsi-space-2); justify-content: flex-end; }

/* ----- Catálogo de ameaças do SGI PRO (picker) ----- */
.sgsi-ameaca-picker { display: flex; flex-direction: column; gap: var(--sgsi-space-4); }
.sgsi-ameaca-picker__filtros {
    display: grid;
    /* Duas colunas EXPLÍCITAS (não repeat/auto-fit), e por isso trata-se aqui e não na
       varredura do piso rígido. Dois problemas na mesma linha:
       · `minmax(180px, ...)` é piso rígido — mesmo defeito das dezesseis irmãs.
       · `2fr` seco tem mínimo automático `auto`: um nome de ameaça longo alarga a
         coluna além do contêiner e a rolagem lateral volta por outro caminho.
       `minmax(0, 2fr)` é o idioma que desarma o mínimo automático. */
    grid-template-columns: minmax(min(180px, 100%), 1fr) minmax(0, 2fr);
    gap: var(--sgsi-space-4);
}
.sgsi-ameaca-picker__filtro { display: flex; flex-direction: column; gap: var(--sgsi-space-1); }
.sgsi-ameaca-lista {
    margin: 0; padding: 0; list-style: none;
    display: flex; flex-direction: column; gap: var(--sgsi-space-2);
    max-height: 22rem; overflow-y: auto;
}
.sgsi-ameaca-item {
    display: flex; flex-direction: column; gap: var(--sgsi-space-1);
    width: 100%; text-align: left;
    padding: var(--sgsi-space-3) var(--sgsi-space-4);
    border: 1px solid var(--sgsi-color-border);
    border-radius: var(--sgsi-radius-md);
    background: var(--sgsi-color-surface);
    cursor: pointer;
}
.sgsi-ameaca-item:hover { border-color: var(--sgsi-color-brand); }
.sgsi-ameaca-item.is-sel { border-color: var(--sgsi-color-brand); box-shadow: 0 0 0 2px var(--sgsi-color-brand-bg); }
.sgsi-ameaca-item__cab { display: flex; align-items: center; flex-wrap: wrap; gap: var(--sgsi-space-2); }
.sgsi-ameaca-item__codigo { font-family: var(--sgsi-font-mono, monospace); font-size: var(--sgsi-font-size-sm); color: var(--sgsi-color-text-muted); }
.sgsi-ameaca-item__nome { font-weight: 600; color: var(--sgsi-color-text); }
.sgsi-ameaca-item__tipo { margin-left: auto; }
.sgsi-ameaca-item__desc { margin: 0; font-size: var(--sgsi-font-size-sm); color: var(--sgsi-color-text-muted); }
.sgsi-ameaca-item__meta {
    display: flex; flex-wrap: wrap; gap: var(--sgsi-space-3);
    font-size: var(--sgsi-font-size-xs); color: var(--sgsi-color-text-subtle);
}

/* ----- Sugerir risco do ativo ----- */
.sgsi-sugerir-risco__origem { display: flex; align-items: center; gap: var(--sgsi-space-2); margin-bottom: var(--sgsi-space-3); }

/* ----- Mapa de calor ----- */
.sgsi-mapa-grade {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(320px, 100%), 1fr));
    gap: var(--sgsi-space-4);
    margin-bottom: var(--sgsi-space-4);
}
/* ── A MATRIZ NÃO ERA UMA MATRIZ: 5 CÉLULAS EMPILHADAS NUMA COLUNA (03/09) ──
   MEDIDO na folha real a 1600x900: as cinco células da linha P=1 tinham o MESMO `left` (163px) e
   `top` DIFERENTE (6228, 6345, 6462, 6579, 6696) — uma coluna, não uma linha —, e a tabela de uma
   matriz 5x5 fechava 2.968px de ALTURA. É o print do dono: blocos coloridos gigantes, soltos,
   sem parecer grade.

   A causa NÃO é a largura da coluna. É `display: inline-flex` num `<td>`. Um filho de
   `display: table-row` que não seja `table-cell` dispara a correção de tabela do CSS: o
   navegador embrulha ele E TODOS OS IRMÃOS CONSECUTIVOS numa ÚNICA célula anônima. Os cinco
   `<td>` da linha viraram cinco caixas inline-flex dentro de uma célula só; como cada uma tem
   `width: 100%`, cada uma ocupa a largura inteira dessa célula e cai numa linha própria. Com
   `table-layout: fixed`, essa célula anônima ainda herda a largura de UMA das 6 colunas do
   cabeçalho (~117px), e o `aspect-ratio: 1/1` transforma os 117px de largura em 117px de altura
   — 5 blocos de 117px por linha da matriz, 5 linhas.

   O conserto devolve `display: table-cell` ao `<td>` (regra `td.sgsi-mapa-cel` abaixo) e, com
   isso, a matriz volta a ser tabela — inclusive para o leitor de tela, que também tinha perdido
   as células. `aspect-ratio` NÃO se aplica a caixa interna de tabela, então o quadrado passa a
   vir de duas medidas que combinam: a coluna nasce de `max-width` no <table> (com
   `table-layout: fixed`, largura de coluna = (largura da tabela − 7 × border-spacing) / 6) e a
   altura vem do mesmo `--sgsi-mapa-lado`. Em 4rem: 6 × 64 + 7 × 3 = 405px de tabela e 64px de
   coluna. O `width: 100%` fica para que a matriz encolha em cartão estreito — abaixo de ~405px
   de espaço a célula fica um retângulo um pouco mais alto que largo, e continua uma grade. */
.sgsi-mapa {
    --sgsi-mapa-lado: 4rem;
    width: 100%;
    max-width: calc(6 * var(--sgsi-mapa-lado) + 7 * 3px);
    border-collapse: separate;
    border-spacing: 3px;
    table-layout: fixed;
}
.sgsi-mapa__th, .sgsi-mapa__canto {
    font-size: var(--sgsi-font-size-xs);
    color: var(--sgsi-color-text-muted);
    text-align: center;
    font-weight: 600;
    padding: var(--sgsi-space-1);
}
/* A classe tem DOIS papéis no markup e por isso duas formas. Aqui fica a do AMOSTRADOR da
   legenda, que é um <span> solto: fora de tabela, `inline-flex` é o que faz width/height valerem
   num inline, e a legenda depende disso (`.sgsi-mapa-legenda .sgsi-mapa-cel`, 1.25rem). */
.sgsi-mapa-cel {
    aspect-ratio: 1 / 1;
    display: inline-flex; align-items: center; justify-content: center;
    width: 100%;
    border-radius: var(--sgsi-radius-sm);
    font-weight: 700;
    color: var(--sgsi-color-text-on-accent);
    position: relative;
}
/* E aqui a da CÉLULA da matriz. O seletor de TIPO (0,1,1) é de propósito: ele separa os dois
   papéis pelo que o elemento É, sem depender de uma classe modificadora que o call-site teria de
   lembrar de escrever — e perde de propósito para `.sgsi-mapa-legenda .sgsi-mapa-cel` (0,2,0),
   que continua mandando na legenda. `aspect-ratio` e `align-items/justify-content` são inertes em
   caixa de tabela; quem centraliza é o par text-align/vertical-align. */
td.sgsi-mapa-cel {
    display: table-cell;
    width: auto;
    height: var(--sgsi-mapa-lado, 4rem);
    padding: 0;
    text-align: center;
    vertical-align: middle;
}
.sgsi-mapa-cel--baixo    { background: var(--sgsi-color-success); }
.sgsi-mapa-cel--moderado { background: var(--sgsi-color-warning); }
/* ── ALTO × CRÍTICO PRECISAM SER DOIS QUADRADOS, NÃO UM (30/08) ──
   Antes: os dois níveis mais altos eram o MESMO `--sgsi-color-danger`, o de cima cheio e o de
   baixo com `opacity: .85` — cerca de 1,3:1 entre si, ou seja, indistinguíveis lado a lado.
   E a opacidade apagava junto o NÚMERO dentro da célula, derrubando o contraste do texto que
   o `.sgsi-mapa-cel` calibra em `text-on-accent`.
   Agora "alto" desloca a MATIZ na direção do âmbar (o degrau de baixo, `--sgsi-color-warning`)
   e "crítico" fica com o vermelho puro. Só a matiz não bastaria: os dois tokens são cores de
   TEXTO (escuras por construção, para servirem sobre fundo claro), então têm luminância quase
   igual e nenhum ajuste de mistura os separa em preto-e-branco — é por isso que o crítico
   ganha também um anel interno claro, marca que NÃO depende de cor e sobrevive ao daltonismo
   e ao print monocromático que o auditor leva para a reunião. O anel entra a 3px para caber
   DENTRO do `--ocupada` (outline a -2px) sem disputar a borda com ele. */
.sgsi-mapa-cel--alto     { background: color-mix(in srgb, var(--sgsi-color-danger) 55%, var(--sgsi-color-warning)); }
.sgsi-mapa-cel--critico  {
    background: var(--sgsi-color-danger);
    box-shadow: inset 0 0 0 3px var(--sgsi-color-danger), inset 0 0 0 4px var(--sgsi-color-text-on-accent);
}
/* ── A CÉLULA VAZIA PRECISA DE CONTORNO, NÃO SÓ DE FUNDO (03/09) ──
   MEDIDO: `--na` pinta rgb(238,241,246) e o cartão que a hospeda pinta rgb(255,255,255) — cerca
   de 1,1:1 entre os dois. As células sem risco sumiam, e com elas a GRADE: o que sobrava na tela
   eram quadrados coloridos soltos, sem eixo para lê-los. O contorno é o que faz a matriz existir
   como matriz mesmo quando quase nada está preenchido, que é o estado de todo cliente novo — o
   caso do avaliador que abre a tela pela primeira vez.
   A ESCOLHA DO TOKEN FOI MEDIDA, não escolhida pelo nome. Razão de contraste contra o fundo da
   própria célula, calculada na página nos DOIS temas (claro / escuro):
       --sgsi-color-border          1,23 : 1   /  1,29 : 1   → some junto com o fundo
       --sgsi-color-border-strong   1,68 : 1   /  1,73 : 1   → melhora e ainda não separa
       --sgsi-color-text-subtle     4,49 : 1   /  4,75 : 1   → passa os 3:1 da WCAG 1.4.11
   Ficou o `text-subtle`: o contorno aqui não é enfeite de borda, é a GRADE — é ele que informa
   onde estão as células que ninguém preencheu, e por baixo de 3:1 ele não informa nada. Não
   destoa por ser forte: a célula OCUPADA já usa `outline` em `--sgsi-color-text`, que mede
   14,5:1, e esta linha de 1px continua muito mais leve que aquela.
   Nenhuma cor nova — o token já existe em sgsi-tokens.css, declarado nos dois temas.
   `border` e não `box-shadow`/`outline` porque esses dois já estão ocupados por `--critico`
   (anel interno) e `--ocupada` (contorno de célula preenchida), e empilhar três mecanismos de
   contorno no mesmo lugar é como o `--alto`/`--critico` viraram indistinguíveis. */
.sgsi-mapa-cel--na       { background: var(--sgsi-color-surface-2); border: 1px solid var(--sgsi-color-text-subtle); }
.sgsi-mapa-cel--ocupada { outline: 2px solid var(--sgsi-color-text); outline-offset: -2px; }
.sgsi-mapa-cel__qtd { font-size: var(--sgsi-font-size-md); }
.sgsi-mapa-legenda { display: flex; flex-wrap: wrap; gap: var(--sgsi-space-4); padding: var(--sgsi-space-3); }
.sgsi-mapa-legenda__item { display: inline-flex; align-items: center; gap: var(--sgsi-space-2); font-size: var(--sgsi-font-size-sm); color: var(--sgsi-color-text-muted); }
.sgsi-mapa-legenda .sgsi-mapa-cel { width: 1.25rem; height: 1.25rem; aspect-ratio: auto; }

/* A CÉLULA OCUPADA DA MATRIZ INERENTE É UM LINK (30/08). O <a> preenche o <td> inteiro de
   propósito: o alvo de clique é a CÉLULA (o quadrado colorido que o consultor mira), não os
   dígitos no meio dela. `color: inherit` mantém o texto sobre o calor (--sgsi-color-text-on-accent
   vem do .sgsi-mapa-cel); pintar de link azul sobre o vermelho de "crítico" seria o pior par de
   contraste da tela. O anel de foco usa os tokens da casa e entra PARA DENTRO (offset negativo)
   porque a matriz tem border-spacing de 3px — um anel para fora seria comido pela célula vizinha. */
.sgsi-mapa-cel__link {
    display: flex;
    align-items: center;
    justify-content: center;
    /* `align-self: stretch` era o que esticava o <a> quando o <td> era um flex container. Com o
       <td> de volta a `table-cell` (ver o bloco da matriz acima) o align-self fica inerte e quem
       estica é `height: 100%` — a porcentagem resolve contra a altura definida da célula. Sem
       isso o alvo de clique encolhia para a altura do dígito no meio do quadrado, que é o
       contrário do que este bloco existe para garantir. */
    align-self: stretch;
    height: 100%;
    width: 100%;
    color: inherit;
    text-decoration: none;
    border-radius: inherit;
}
.sgsi-mapa-cel__link:hover,
.sgsi-mapa-cel__link:focus-visible { text-decoration: underline; }
.sgsi-mapa-cel__link:focus-visible {
    outline: var(--sgsi-focus-ring-width) solid var(--sgsi-color-focus-ring);
    outline-offset: calc(-1 * var(--sgsi-focus-ring-width));
}

/* A CLASSE EXISTIA NO MARKUP E NÃO NO CSS (30/08) — dois call-sites em MapaCalorRiscos.razor
   pediam `sgsi-mapa-legenda-card` e nenhuma regra respondia. Classe fantasma não quebra nada, só
   não faz nada: as duas faixas continuavam com o padding canônico de 1,5rem em cada lado para
   carregar UMA frase e quatro quadradinhos, e somadas às duas matrizes o mapa não cabia em 768px.
   Redefine o TOKEN, e não `.sgsi-card__corpo`: assim `--flush` (que zera por seletor próprio)
   continua zerando aqui. E o modo compacto GLOBAL vence esta regra de propósito — o seletor dele
   (`[data-sgsi-densidade="compacto"] .sgsi-card`) tem especificidade maior, e quem escolheu a
   densidade da sessão inteira manda mais que o ajuste de uma tela. */
.sgsi-mapa-legenda-card {
    --sgsi-card-padding: var(--sgsi-space-2) var(--sgsi-space-4);
}

/* ==========================================================================
   QUESTIONÁRIO SIG-LITE (Fornecedores)
   ========================================================================== */
.sgsi-sig-grupo {
    border: 1px solid var(--sgsi-color-border);
    border-radius: var(--sgsi-radius-md);
    padding: var(--sgsi-space-3) var(--sgsi-space-4) var(--sgsi-space-4);
    margin: 0 0 var(--sgsi-space-4);
}
.sgsi-sig-grupo__titulo {
    display: inline-flex;
    align-items: center;
    gap: var(--sgsi-space-2);
    padding: 0 var(--sgsi-space-2);
    font-size: var(--sgsi-font-size-sm);
    font-weight: var(--sgsi-font-weight-semibold);
    color: var(--sgsi-color-text);
    width: auto;
}
.sgsi-sig-item {
    padding: var(--sgsi-space-3) 0;
    border-top: 1px solid var(--sgsi-color-border);
}
.sgsi-sig-item:first-of-type { border-top: 0; }
.sgsi-sig-item__pergunta {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--sgsi-space-2);
    margin-bottom: var(--sgsi-space-2);
}
.sgsi-sig-item__campos {
    display: grid;
    grid-template-columns: minmax(10rem, 16rem) 1fr;
    gap: var(--sgsi-space-2);
}
@media (max-width: 640px) { /* mobile — breakpoint canônico (#49) */
    .sgsi-sig-item__campos { grid-template-columns: 1fr; }
}
.sgsi-sig-contador { margin-right: auto; }

/* ---- célula de arquivo de evidência (SoA / E3): nome clicável + tamanho ---- */
.sgsi-evidencia-arquivo { display: flex; align-items: center; gap: var(--sgsi-space-2); flex-wrap: wrap; }
.sgsi-evidencia-arquivo .btn-link { display: inline-flex; align-items: center; gap: var(--sgsi-space-1); text-align: start; }

/* ============================================================================
   SgsiTabs (Onda 2-C3): barra de abas acessível (role=tablist/tab + teclado).
   Unifica os padrões ad-hoc (sgsi-recursos-aba / sgsi-compliance-aba) num só.
   ============================================================================ */
.sgsi-tabs {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem;
    margin-bottom: 1rem;
    border-bottom: 1px solid var(--sgsi-color-border);
    padding-bottom: 0.6rem;
}

.sgsi-tabs__aba {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.35rem 0.75rem;
    border: 1px solid var(--sgsi-color-border);
    border-radius: var(--sgsi-radius-pill);
    background: transparent;
    color: var(--sgsi-color-text-muted);
    font-size: 0.85rem;
    font-weight: var(--sgsi-font-weight-semibold);
    cursor: pointer;
    transition: background-color 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}

/* O realce de passagem do mouse vale para as abas INATIVAS. Na aba ativa o fundo já é a cor da
   marca; pintar o texto com essa mesma cor deixava rótulo e fundo idênticos — contraste 1:1 — e
   o nome da aba simplesmente sumia enquanto o ponteiro estivesse sobre ela. O `:not()` exclui a
   ativa antes de a cor ser aplicada, em vez de tentar desfazê-la depois. */
.sgsi-tabs__aba:not(.sgsi-tabs__aba--ativa):hover {
    border-color: var(--sgsi-color-brand);
    color: var(--sgsi-color-brand);
}

.sgsi-tabs__aba:focus-visible {
    outline: var(--sgsi-focus-ring-width) solid var(--sgsi-color-brand);
    outline-offset: var(--sgsi-focus-ring-offset);
}

.sgsi-tabs__aba--ativa {
    background: var(--sgsi-color-brand);
    border-color: var(--sgsi-color-brand);
    color: var(--sgsi-color-on-brand);
}

.sgsi-tabs__contador {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 1.4em;
    padding: 0 0.4em;
    border-radius: var(--sgsi-radius-pill);
    background: var(--sgsi-color-bg-subtle);
    color: inherit;
    font-size: 0.78rem;
    font-weight: var(--sgsi-font-weight-semibold);
}

.sgsi-tabs__aba--ativa .sgsi-tabs__contador {
    background: rgba(255, 255, 255, 0.25);
}

/* ============================================================================
   Onda 5-H1: feedback de :active (pressionar) — micro-resposta tátil consistente
   nos controles. Respeita prefers-reduced-motion (sem transform).
   ============================================================================ */
.btn:active:not(:disabled),
.sgsi-icon-btn:active:not(:disabled),
.sgsi-tabs__aba:active,
.sgsi-nav-link:active,
.sgsi-usermenu__item:active {
    transform: translateY(1px);
}

@media (prefers-reduced-motion: reduce) {
    .btn:active:not(:disabled),
    .sgsi-icon-btn:active:not(:disabled),
    .sgsi-tabs__aba:active,
    .sgsi-nav-link:active,
    .sgsi-usermenu__item:active {
        transform: none;
    }
}

/* ============================================================================
   Onda 4-G1: cabeçalho de tabela STICKY — em tabelas longas, o thead fica colado
   ao topo do container de rolagem (o usuário não perde os rótulos das colunas).
   O fundo opaco evita que o conteúdo apareça por baixo ao rolar.

   • Famílias .sgsi-tabela/.sgsi-est-tabela: rolam com a PÁGINA, que tem a
     topbar sticky opaca por cima (z-index var(--sgsi-z-topbar), 1030) — com
     top:0 o th grudava ATRÁS dela (sticky natimorto). O offset usa o token
     --sgsi-topbar-height (o mesmo que o MainLayout consome para a altura da
     topbar — já unificado num só ponto). MESMA disciplina do grid: abaixo de
     1200px o .sgsi-tabela-wrap vira scroll-container (overflow-x:auto) e top>0
     afundaria o th sobre o tbody em repouso — offset só em min-width:1200px.
     ESTE NÚMERO ERA 769px ATÉ 04/09, e mudou junto com o overflow: naquela
     faixa o cartão recortava a tabela SEM barra de rolagem, e a última coluna
     (a de ações, quando existe) ficava inalcançável no laptop;
     e o .sgsi-card hospedeiro precisa de overflow:clip no desktop (hidden
     também é scroll-container e mataria o sticky — ver seção do wrap).
   • Família .sgsi-grid__tabela: de 1200px para cima o .sgsi-grid__viewport e o
     .sgsi-card hospedeiro usam overflow:clip (veja a seção DATA GRID) — nenhum
     dos dois é scroll-container e o sticky engata no scroll da página, com o
     mesmo offset da topbar das outras famílias. Abaixo de 1200px o viewport
     volta a ser scroll-container (overflow-x:auto) para a grade larga poder
     rolar: o sticky não engata — e o top PRECISA ficar 0 nessa faixa: qualquer
     top>0 dentro de um scroll-container que não rola na vertical DESLOCA o th
     sobre o tbody já em repouso (comportamento de spec, verificado em navegador
     real: th afundava ~3.5rem sem nenhum scroll). Por isso o offset da topbar
     DESTA família entra só via media query min-width: 1200px — o mesmo
     breakpoint do clip, e os dois não podem divergir (o 769px que valia aqui
     deixava a grade sem rolagem entre 769px e 1199px).
   • z-index 2: acima do conteúdo posicionado das células; muito abaixo da
     topbar (1030) e dos overlays.

   ONDE O OFFSET MORA HOJE (03/09): os dois raciocínios de breakpoint acima continuam válidos,
   mas o VALOR deixou de ser escrito no <th>. Ele vem de duas custom properties herdadas
   (--sgsi-th-sticky-top e --sgsi-th-sticky-top-grid), declaradas logo abaixo. O motivo está no
   bloco seguinte: a faixa de viewport nunca foi a única condição — o scrollport também depende
   de QUEM ENVOLVE a tabela, e isso um literal no <th> não consegue perguntar.
   ============================================================================ */
/* ── O FUNDO DO <th> VOLTOU A TER UMA FONTE SÓ (02/09) ──
   Este bloco declarava `background: var(--sgsi-color-surface)` e, com isso, APAGAVA o tom de
   cabeçalho que o DS declara 1.600 linhas acima: `.sgsi-grid__th` (surface-2) perdia por
   especificidade para `.sgsi-grid__tabela > thead > tr > th` (0,1,0 contra 0,1,3), e
   `.sgsi-tabela > thead > tr > th` perdia por ORDEM para o seletor idêntico daqui. Os tokens
   diferem de verdade — #ffffff contra #eef1f6 no claro, #13202e contra #1a2a3a no escuro —,
   então o cabeçalho de TODA grade e sub-tabela do produto renderizava da mesma cor do corpo do
   cartão, separado do conteúdo só pelo border-bottom de 1px.
   O sticky exige fundo OPACO; não exige ESTA cor. Por isso o background saiu daqui e ficou uma
   declaração só por família, na regra de origem: `.sgsi-tabela > thead > tr > th` e
   `.sgsi-grid__th`. Duas fontes para a mesma propriedade é o que produziu o defeito.
   `.sgsi-est-tabela` é a exceção e ganha regra PRÓPRIA logo abaixo: ela nunca declarou tom de
   cabeçalho em lugar nenhum, então aqui não há regressão a desfazer — tingi-la seria decisão de
   design nova, não conserto, e o sticky dela continua precisando de opacidade. */
/* ── O OFFSET DA TOPBAR VIROU HERANÇA, E NÃO MAIS UM LITERAL NO <th> (03/09) ──
   MEDIDO em navegador a 1600x900, com a folha real: um `.sgsi-tabela` dentro de
   `.table-responsive` punha o <th> a 56px ABAIXO do topo do scrollport COM A ROLAGEM EM ZERO
   (`th.getBoundingClientRect().top - scrollport.top === 56`), e o mesmo dentro de
   `.sgsi-rasci-matriz-wrap`. É o cabeçalho desenhado POR CIMA da primeira linha de dados, com
   uma faixa vazia acima — o print do dono. O controle (a mesma tabela sem wrapper de rolagem)
   media 0. `overflow-x: auto` computa `overflow-y: auto` junto (medido: os dois vêm "auto"),
   então TODO wrapper de rolagem horizontal é também um scrollport vertical, e o sticky passa a
   se medir por ele — onde não existe topbar nenhuma para compensar.

   O `top` do <th> era um LITERAL (`var(--sgsi-topbar-height)`) escrito dentro de uma media
   query. Literal não se intercepta: para isentar um contexto era preciso escrever, à mão, o par
   (wrapper × família de tabela) — e omissão de par não aparece em diff. Eram 6 telas com
   `.table-responsive` (15 usos) e a Matriz RASCI, e nenhuma delas estava na lista, porque a
   lista não existia.

   Agora o <th> lê uma CUSTOM PROPERTY HERDADA. Quem decide o offset é o :root (por faixa de
   viewport); qualquer ancestral pode zerá-la para toda a sua subárvore, e a herança alcança
   QUALQUER família de tabela, presente ou futura, em QUALQUER profundidade — uma declaração por
   wrapper, em vez de uma por par. É a forma difícil de quebrar por quem chegar depois: uma
   tabela nova dentro de um wrapper já isentado nasce correta sem ninguém lembrar dela.

   As DUAS propriedades existem porque as duas famílias trocam de contexto em breakpoints
   diferentes (769px para .sgsi-tabela/.sgsi-est-tabela, 1200px para .sgsi-grid__tabela — o
   mesmo do overflow:clip do viewport). Fundi-las mudaria o comportamento de uma das duas.
   A catraca CabecalhoStickyNaoAfundaEmContainerDeRolagemTests prende o par. */
:root {
    --sgsi-th-sticky-top: 0px;
    --sgsi-th-sticky-top-grid: 0px;
}
@media (min-width: 1200px) {
    /* Desktop LARGO: wrap sem overflow e card com clip → sticky engata no scroll
       da página; offset compensa a topbar sticky opaca.
       MOVIDO DE 769px PARA 1200px EM 04/09, junto com o overflow da
       .sgsi-tabela-wrap — os dois nao podem divergir, e a faixa 769–1199 passou a
       ser scrollport para a coluna deixar de ficar inalcancavel. */
    :root { --sgsi-th-sticky-top: var(--sgsi-topbar-height, 3.5rem); }
}
@media (min-width: 1200px) {
    /* Mesmo breakpoint do overflow:clip do .sgsi-grid__viewport — os dois não podem divergir. */
    :root { --sgsi-th-sticky-top-grid: var(--sgsi-topbar-height, 3.5rem); }
}

/* CONTÊINERES DE ROLAGEM CONHECIDOS — o offset da topbar NÃO vale dentro deles.
   A lista é TODO seletor da folha que declara `overflow*: auto|scroll`, e não só os que
   hospedam tabela hoje: onde não há <th> a declaração é inerte, e o dia em que houver ela já
   está certa. A catraca compara os dois conjuntos e reprova se um scrollport novo entrar na
   folha sem entrar aqui. `.table-responsive` é do Bootstrap (não é declarado nesta folha) e
   entra na lista pelos 15 call-sites em 6 páginas.
   Por que o valor volta a ZERO e não a outro número: nesses contextos o scrollport é o próprio
   wrapper, cujo topo já é o topo visível do conteúdo — não há nada por cima para compensar. */
.table-responsive,
.sgsi-modal__corpo,
.sgsi-catalogo__lista,
.sgsi-trilha__tabela-wrap,
.sgsi-seletor-tenant__menu,
.sgsi-picker__lista,
.sgsi-rasci-matriz-wrap,
.sgsi-template-conteudo-preview,
.sgsi-ameaca-lista,
.sgsi-cmdk__lista,
.sgsi-doc-corpo {
    --sgsi-th-sticky-top: 0px;
    --sgsi-th-sticky-top-grid: 0px;
}
/* Os dois wrappers que só são scrollport ABAIXO do seu breakpoint. Nessas faixas o :root já
   entrega 0px, então estas duas regras não mudam pixel nenhum hoje — elas existem para que a
   isenção esteja escrita no MESMO lugar que a catraca lê, e para não quebrar o sticky legítimo
   ACIMA do breakpoint (que é o que uma isenção incondicional faria). */
@media (max-width: 1199px) {
    .sgsi-tabela-wrap { --sgsi-th-sticky-top: 0px; --sgsi-th-sticky-top-grid: 0px; }
}
@media (max-width: 1199px) {
    .sgsi-grid__viewport { --sgsi-th-sticky-top: 0px; --sgsi-th-sticky-top-grid: 0px; }
}
/* SEM :has() O CARTÃO CONTINUA `overflow: hidden` — e hidden é scroll-container.
   O comentário desta seção afirmava, para esse caso, "card segue hidden (sem sticky, visual
   intacto)". A primeira metade é verdade; a segunda NÃO: com `top` > 0 dentro de um
   scroll-container que não rola na vertical, o th afunda em repouso — é exatamente o defeito
   medido acima. A troca hidden→clip depende de `:has()`, então o offset só pode valer onde
   `:has()` existe. Vem DEPOIS das media queries de propósito: mesma especificidade, vence por
   ordem. NÃO MEDIDO (não tenho Firefox <121 aqui) — é dedução do mecanismo já medido no
   `.table-responsive`, e o pior caso é perder o conforto do sticky, nunca afundar o cabeçalho. */
@supports not selector(:has(*)) {
    :root { --sgsi-th-sticky-top: 0px; --sgsi-th-sticky-top-grid: 0px; }
}

.sgsi-tabela > thead > tr > th,
.sgsi-est-tabela > thead > tr > th {
    position: sticky;
    top: var(--sgsi-th-sticky-top, 0px);
    z-index: 2;
}
.sgsi-est-tabela > thead > tr > th { background: var(--sgsi-color-surface); }

/* Sem `background` aqui pelo mesmo motivo do bloco acima: o tom opaco do cabeçalho do grid vem
   de `.sgsi-grid__th`, e TODO <th> desta tabela o recebe (SgsiDataGrid.razor:50-53 é o único
   laço de cabeçalho, e os 12 cabeçalhos escritos à mão que usam a classe vivem todos dentro de
   um `.sgsi-grid__tabela` — varrido em 02/09). */
.sgsi-grid__tabela > thead > tr > th {
    position: sticky;
    top: var(--sgsi-th-sticky-top-grid, 0px);
    z-index: 2;
}

/* Dentro de modal o scroll é o do .sgsi-modal__corpo (overflow-y:auto) e NÃO há
   topbar por cima — o offset da topbar deixaria o th flutuando 3.5rem abaixo do
   topo do corpo ao rolar (ex.: ModalImportarRiscos/Ativos).
   A isenção MUDOU DE MECANISMO (03/09): era um par de seletores `.sgsi-modal <família>` com
   `top: 0` — uma linha por família, que o autor da próxima família teria de lembrar de
   escrever. Hoje `.sgsi-modal__corpo` está na lista de contêineres de rolagem acima e zera as
   custom properties para tudo que estiver dentro dele, de qualquer família e a qualquer
   profundidade. Uma fonte só para o mesmo fato. */

/* ============================================================================
   SgsiCommandPalette (Onda 5): paleta de comandos ⌘K — overlay + caixa de busca.
   ============================================================================ */
.sgsi-cmdk {
    position: fixed;
    inset: 0;
    z-index: 1100;
    display: flex;
    justify-content: center;
    align-items: flex-start;
    padding-top: 12vh;
    background: rgba(0, 0, 0, 0.45);
}

.sgsi-cmdk__painel {
    width: min(40rem, 92vw);
    max-height: 70vh;
    display: flex;
    flex-direction: column;
    background: var(--sgsi-color-surface);
    border: 1px solid var(--sgsi-color-border);
    border-radius: var(--sgsi-radius-lg);
    box-shadow: var(--sgsi-shadow-lg);
    overflow: hidden;
}

.sgsi-cmdk__busca {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.75rem 1rem;
    border-bottom: 1px solid var(--sgsi-color-border);
}

.sgsi-cmdk__busca-icone { color: var(--sgsi-color-text-muted); display: inline-flex; }

.sgsi-cmdk__input {
    flex: 1;
    border: 0;
    background: transparent;
    color: var(--sgsi-color-text);
    font-size: 1rem;
    outline: none;
}

.sgsi-cmdk__hint {
    font-size: 0.7rem;
    color: var(--sgsi-color-text-muted);
    border: 1px solid var(--sgsi-color-border);
    border-radius: var(--sgsi-radius-sm);
    padding: 0.1rem 0.35rem;
}

.sgsi-cmdk__lista {
    list-style: none;
    margin: 0;
    padding: 0.4rem;
    overflow-y: auto;
}

.sgsi-cmdk__op {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    padding: 0.55rem 0.7rem;
    border-radius: var(--sgsi-radius-md);
    cursor: pointer;
    color: var(--sgsi-color-text);
}

.sgsi-cmdk__op--sel { background: var(--sgsi-color-brand); color: var(--sgsi-color-on-brand); }

.sgsi-cmdk__op-icone { display: inline-flex; opacity: 0.85; }
.sgsi-cmdk__op-rotulo { flex: 1; font-weight: var(--sgsi-font-weight-medium); }
.sgsi-cmdk__op-grupo { font-size: 0.78rem; color: var(--sgsi-color-text-muted); }
.sgsi-cmdk__op--sel .sgsi-cmdk__op-grupo { color: inherit; opacity: 0.85; }

.sgsi-cmdk__vazio { padding: 1rem; text-align: center; color: var(--sgsi-color-text-muted); }

/* ============================================================================
   Onda 5: DENSIDADE compacta — [data-sgsi-densidade="compacto"] no <html> reduz o
   padding das áreas DENSAS p/ caber mais por tela. Escopo alvo (não global) p/ não
   quebrar layouts. Toggle no topbar (sgsi-densidade.js).

   O ESCOPO ERA "tabelas + KPIs" e ISSO ERA O DEFEITO — ver o bloco de 30/08 mais abaixo:
   o cromo que come a tela é o dos CONTAINERS (cartão, corpo de página, modal, formulário),
   não o da célula. Ao acrescentar alvo aqui, acrescente também na catraca
   DensidadeEHierarquiaVisualGuardrailTests, que fixa o conjunto mínimo.
   ============================================================================ */
[data-sgsi-densidade="compacto"] .sgsi-tabela > tbody > tr > td,
[data-sgsi-densidade="compacto"] .sgsi-tabela > thead > tr > th,
[data-sgsi-densidade="compacto"] .sgsi-grid__tabela > tbody > tr > td,
[data-sgsi-densidade="compacto"] .sgsi-grid__tabela > thead > tr > th,
[data-sgsi-densidade="compacto"] .sgsi-est-tabela > tbody > tr > td,
[data-sgsi-densidade="compacto"] .sgsi-est-tabela > thead > tr > th {
    padding-top: 0.3rem;
    padding-bottom: 0.3rem;
}

[data-sgsi-densidade="compacto"] .sgsi-risco-stat,
[data-sgsi-densidade="compacto"] .sgsi-stat,
[data-sgsi-densidade="compacto"] .sgsi-evid__stat {
    padding: 0.55rem 0.75rem;
}

/* ---- O MODO COMPACTO NAO ALCANCAVA O CROMO DOS CARTOES (30/08) ---------------------------
   O ESCOPO INTEIRO do compacto eram as tres reguas de tabela acima e UMA das tres familias de
   cartao de numero. Nada mais: nem cartao, nem corpo de pagina, nem modal, nem formulario.

   O QUE ISSO CAUSAVA, medido em 1366x768: no dashboard, os 10 cartoes de dominio sao ~85% da
   altura da tela e nao mudavam um pixel — o usuario clicava no controle de densidade na tela
   MAIS densa do produto e ganhava ~15px (so a faixa de KPI encolhia). Uma alavanca rotulada
   que nao alcanca a fonte do problema e pior que nenhuma: ela ensina que o produto nao tem
   jeito. O mesmo vale para a pagina principal do God Mode e para /governanca/saude.

   POR QUE REDEFINIR OS TOKENS DO CARTAO, e nao carimbar `padding` em `.sgsi-card__cab` e
   `.sgsi-card__corpo`: o `.sgsi-card` ja expoe `--sgsi-card-padding{,-cab-y,-cab-x}`, e
   `.sgsi-card__corpo--flush` (padding: 0) depende de vencer o corpo por seletor proprio.
   Sobrescrevendo o TOKEN, o `--flush` continua zerado e qualquer pagina que ja ajuste esses
   tokens segue mandando no seu proprio escopo. Os valores sao exatamente os do modificador
   `.sgsi-card--compacto` que ja existia e quase ninguem aplicava — o compacto passa a ser a
   forma GLOBAL de ligar o que o modificador fazia por cartao.

   O `.sgsi-card__rodape` entra a mao porque escreve o padding literal, sem passar pelos
   tokens — e o irmao que ficaria de fora se a regra parasse no cabecalho e no corpo. */
[data-sgsi-densidade="compacto"] .sgsi-card {
    --sgsi-card-padding: var(--sgsi-space-4);
    --sgsi-card-padding-cab-y: var(--sgsi-space-3);
    --sgsi-card-padding-cab-x: var(--sgsi-space-4);
}

[data-sgsi-densidade="compacto"] .sgsi-card__rodape {
    padding: var(--sgsi-space-2) var(--sgsi-space-4);
}

/* O respiro ENTRE blocos tambem conta: com 4 secoes numa pagina de detalhe, o gap de 24px do
   corpo custa 72px de rolagem que o compacto nao tocava. */
[data-sgsi-densidade="compacto"] .sgsi-pagina__corpo {
    gap: var(--sgsi-space-4);
}

[data-sgsi-densidade="compacto"] .sgsi-modal__corpo {
    padding: var(--sgsi-space-4);
}

[data-sgsi-densidade="compacto"] .sgsi-form {
    gap: var(--sgsi-space-3);
}

[data-sgsi-densidade="compacto"] .sgsi-kv {
    gap: var(--sgsi-space-2);
}

/* ============================================================================
   Onda 5-H1: animação de SAÍDA do toast (fade-out + desliza) — par da entrada
   sgsi-toast-in. O componente segura a remoção até a animação terminar. Sob
   prefers-reduced-motion a regra existente (.sgsi-toast { animation: none })
   já neutraliza o movimento.
   ============================================================================ */
.sgsi-toast--saindo {
    animation: sgsi-toast-out 0.24s ease forwards;
    pointer-events: none;
}

@keyframes sgsi-toast-out {
    to {
        opacity: 0;
        transform: translateX(0.75rem);
    }
}

/* Form Fieldset */
.sgsi-form-fieldset { border: none; padding: 0; margin: 0; min-width: 0; }

/* ── Responsividade (onda mobile) ─────────────────────────────────────────── */

/* Colunas de SgsiDataGrid marcadas com OcultarNoMobile somem abaixo de 640px,
   deixando o grid legível no celular (a coluna-chave + as ações permanecem). */
@media (max-width: 640px) {
    .sgsi-grid__col--mobile-oculta {
        display: none;
    }
}

/* ==========================================================================
   SgsiProgressBar (#43) — barra de progresso para operações longas (>2s).
   ========================================================================== */
.sgsi-progress {
    display: flex;
    flex-direction: column;
    gap: var(--sgsi-space-1);
    width: 100%;
}
.sgsi-progress__cab {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--sgsi-space-2);
    font-size: var(--sgsi-font-size-sm);
    color: var(--sgsi-color-text-muted);
}
.sgsi-progress__pct {
    font-variant-numeric: tabular-nums;
    font-weight: var(--sgsi-font-weight-semibold);
    color: var(--sgsi-color-text);
}
.sgsi-progress__trilho {
    position: relative;
    overflow: hidden;
    height: 0.5rem;
    border-radius: var(--sgsi-radius-pill, 99px);
    background: var(--sgsi-color-surface-3, var(--sgsi-color-border));
}
.sgsi-progress__barra {
    height: 100%;
    border-radius: inherit;
    background: var(--sgsi-color-brand);
    transition: width 0.25s ease;
}
/* Modo indeterminado: bloco menor deslizando continuamente. */
.sgsi-progress--indeterminado .sgsi-progress__barra {
    width: 35%;
    animation: sgsi-progress-desliza 1.1s ease-in-out infinite;
}
@keyframes sgsi-progress-desliza {
    0%   { transform: translateX(-120%); }
    100% { transform: translateX(320%); }
}
@media (prefers-reduced-motion: reduce) {
    .sgsi-progress--indeterminado .sgsi-progress__barra {
        animation-duration: 2.4s;
    }
    .sgsi-progress__barra { transition: none; }
}

/* ==========================================================================
   SgsiAssistenteIa (Tier 3) — botão + painel do Copiloto de IA.
   ========================================================================== */
.sgsi-ia {
    display: flex;
    flex-direction: column;
    gap: var(--sgsi-space-2);
}
.sgsi-ia__spark {
    margin-right: var(--sgsi-space-1);
}
.sgsi-ia__upsell {
    font-size: var(--sgsi-font-size-sm);
    color: var(--sgsi-color-text-muted);
    margin: 0;
}
.sgsi-ia__resultado {
    display: flex;
    flex-direction: column;
    gap: var(--sgsi-space-2);
    padding: var(--sgsi-space-3);
    border: 1px solid var(--sgsi-color-border);
    border-radius: var(--sgsi-radius-md);
    background: var(--sgsi-color-surface-2, var(--sgsi-color-surface));
}
.sgsi-ia__texto {
    width: 100%;
    resize: vertical;
    font-family: inherit;
}
.sgsi-ia__aviso {
    font-size: var(--sgsi-font-size-xs);
    color: var(--sgsi-color-text-muted);
    margin: 0;
}
/* Âncora anti-alucinação: a IA afirmou conformidade sem evidência que a sustente. Precisa LER como
   alerta — no tom apagado do aviso comum, o consultor passa reto e assina uma conformidade sem lastro. */
.sgsi-ia__aviso--critico {
    font-size: var(--sgsi-font-size-sm);
    color: var(--sgsi-color-danger);
    background: var(--sgsi-color-danger-bg);
    border-left: 3px solid var(--sgsi-color-danger);
    border-radius: var(--sgsi-radius-sm);
    padding: var(--sgsi-space-2);
    margin-top: var(--sgsi-space-2);
}
.sgsi-ia__nota {
    font-size: var(--sgsi-font-size-xs);
    color: var(--sgsi-color-text-muted);
    margin: var(--sgsi-space-1) 0 0;
}
/* Opt-in de IA (DPA, 04/09) — o bloco que explica a TRANSFERENCIA INTERNACIONAL antes do clique.
   Nasceu sem regra nenhuma: o aviso de que o conteudo sai do pais renderizava como <div> nu, com a
   mesma presenca visual de um paragrafo qualquer. Consentimento informado que nao se distingue do
   texto ao redor nao e informado — por isso ele ganha moldura e a listra de atencao. */
.sgsi-ia__optin {
    display: flex;
    flex-direction: column;
    gap: var(--sgsi-space-2);
    padding: var(--sgsi-space-3);
    background: var(--sgsi-color-warning-bg);
    border: 1px solid var(--sgsi-color-border);
    border-left: 3px solid var(--sgsi-color-warning);
    border-radius: var(--sgsi-radius-sm);
}
/* O <details> que deixa RELER o aviso depois de ativado. Discreto e recolhido de proposito: quem
   ja consentiu nao precisa do bloco inteiro ocupando a tela, mas precisa poder achar o texto —
   a revogacao e um direito, e direito que nao se encontra na tela nao se exerce. */
.sgsi-ia__optout {
    margin-top: var(--sgsi-space-2);
    font-size: var(--sgsi-font-size-xs);
    color: var(--sgsi-color-text-muted);
}
.sgsi-ia__optout > summary {
    padding: var(--sgsi-space-1) 0;
    color: var(--sgsi-color-text-muted);
    cursor: pointer;
}

/* ---- Instrumentos jurídicos (/legal/{doc}) — EULA/DPA/Aviso Legal renderizados ----
   Coluna estreita e entrelinha generosa: é texto contratual longo, lido de ponta a ponta antes de
   um aceite vinculante. Servir o .md cru deixava a leitura a cargo do navegador. */
.sgsi-legal {
    max-width: 52rem;
    margin: 0 auto;
    padding: 2rem 1.25rem 3rem;
}
.sgsi-legal__titulo {
    font-size: var(--sgsi-font-size-xl);
    margin-bottom: var(--sgsi-space-1);
}
.sgsi-legal__versao {
    font-size: var(--sgsi-font-size-sm);
    color: var(--sgsi-color-text-muted);
    margin-bottom: var(--sgsi-space-4);
}
.sgsi-legal__corpo {
    line-height: 1.7;
}
.sgsi-legal__corpo h1,
.sgsi-legal__corpo h2,
.sgsi-legal__corpo h3 {
    margin-top: var(--sgsi-space-5);
    margin-bottom: var(--sgsi-space-2);
}
.sgsi-legal__corpo table {
    width: 100%;
    border-collapse: collapse;
    margin: var(--sgsi-space-3) 0;
}
.sgsi-legal__corpo th,
.sgsi-legal__corpo td {
    border: 1px solid var(--sgsi-color-border);
    padding: var(--sgsi-space-2);
    text-align: left;
}
.sgsi-legal__voltar {
    margin-top: var(--sgsi-space-5);
}

/* ---- Corpo de documento controlado (markdown do tenant renderizado no detalhe) ----
   Bloco PRÓPRIO, não reuso de .sgsi-legal__corpo: aquele é o instrumento jurídico do
   produto (página anônima /legal), este é o texto da política do cliente dentro do SGI.
   Mesmas regras tipográficas; a tabela rola no eixo X porque política com matriz larga
   não pode empurrar o layout do detalhe. */
.sgsi-doc-corpo {
    line-height: 1.7;
    overflow-x: auto;
}
.sgsi-doc-corpo h1,
.sgsi-doc-corpo h2,
.sgsi-doc-corpo h3 {
    margin-top: var(--sgsi-space-5);
    margin-bottom: var(--sgsi-space-2);
}
.sgsi-doc-corpo table {
    width: 100%;
    border-collapse: collapse;
    margin: var(--sgsi-space-3) 0;
}
.sgsi-doc-corpo th,
.sgsi-doc-corpo td {
    border: 1px solid var(--sgsi-color-border);
    padding: var(--sgsi-space-2);
    text-align: left;
}

/* ---- Trust page (/confianca) e status (/status-servico) — páginas públicas de confiança ----
   Desde 20/09 as duas vivem no LayoutLanding e herdam a moldura da vitrine (css/sgsi-vitrine.css:
   faixa de título, cartões .lp-cartao, grade .lp-grade). O que fica aqui é o vocabulário PRÓPRIO
   das páginas de confiança — título, subtítulo, cartão, nota — que a catraca
   InstrumentoJuridicoEAlcancavelNaConfiancaTests lê pelo nome. O contêiner centralizado, o herói
   centrado e o link "voltar ao login" saíram com o layout antigo: o cabeçalho da vitrine já leva
   ao login. */
.sgsi-trust__titulo {
    font-size: var(--sgsi-font-size-2xl, 2rem);
    font-weight: 700;
    color: var(--sgsi-color-text);
    text-wrap: balance;
    margin: 0 0 0.5rem;
}

.sgsi-trust__sub {
    color: var(--sgsi-color-text-muted);
    max-width: 46rem;
    margin: 0 auto;
    line-height: 1.6;
}

.sgsi-trust__grade {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(20rem, 100%), 1fr));
    gap: 1rem;
}

.sgsi-trust__card {
    background: var(--sgsi-color-surface);
    border: 1px solid var(--sgsi-color-border);
    border-radius: 0.75rem;
    padding: 1.25rem 1.25rem 1rem;
}

.sgsi-trust__card-titulo {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    font-size: 1.05rem;
    font-weight: 600;
    color: var(--sgsi-color-text);
    margin: 0 0 0.5rem;
}

.sgsi-trust__card p,
.sgsi-trust__card li {
    color: var(--sgsi-color-text-muted);
    line-height: 1.55;
}

.sgsi-trust__card ul {
    margin: 0.25rem 0 0;
    padding-left: 1.1rem;
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
}

.sgsi-trust__nota {
    margin-top: 0.6rem;
    font-size: var(--sgsi-font-size-sm, 0.875rem);
    color: var(--sgsi-color-text-subtle);
    font-style: italic;
}

.sgsi-trust__rodape {
    margin-top: 2rem;
    color: var(--sgsi-color-text-subtle);
    font-size: var(--sgsi-font-size-sm, 0.875rem);
}

/* ===========================================================================
   Lente "Evolução" do Painel de Saúde (BI longitudinal) — PainelEvolucaoSaude.
   Gráfico SVG da série do score + seletor de janela (pills; > teto do tier =
   bloqueado, o upsell nativo) + banner de upsell. Só tokens do design-system.
   =========================================================================== */
.sgsi-saude-tabs {
    margin-bottom: var(--sgsi-space-4);
}

.sgsi-evol {
    display: flex;
    flex-direction: column;
    gap: var(--sgsi-space-4);
}

/* ---- Seletor de janela (pills) ---- */
.sgsi-evol__seletor {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--sgsi-space-2);
}

.sgsi-evol__seletor-rotulo {
    font-size: var(--sgsi-font-size-sm);
    color: var(--sgsi-color-text-muted);
    margin-right: var(--sgsi-space-1);
}

.sgsi-evol__pill {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    padding: 0.3rem 0.75rem;
    border: 1px solid var(--sgsi-color-border);
    border-radius: var(--sgsi-radius-pill, 999px);
    background: var(--sgsi-color-surface);
    color: var(--sgsi-color-text-muted);
    font-size: var(--sgsi-font-size-sm);
    font-weight: var(--sgsi-font-weight-medium);
    cursor: pointer;
    transition: background 0.12s ease, border-color 0.12s ease, color 0.12s ease;
}

.sgsi-evol__pill:hover:not(:disabled) {
    border-color: var(--sgsi-color-brand);
    color: var(--sgsi-color-text);
}

.sgsi-evol__pill--ativa {
    background: var(--sgsi-color-brand);
    border-color: var(--sgsi-color-brand);
    color: var(--sgsi-color-on-brand);
}

.sgsi-evol__pill--bloqueada {
    opacity: 0.55;
    cursor: not-allowed;
    color: var(--sgsi-color-text-subtle);
}

.sgsi-evol__pill:focus-visible {
    outline: 2px solid var(--sgsi-color-brand);
    outline-offset: 2px;
}

/* ---- Banner de upsell ---- */
.sgsi-evol__upsell {
    display: flex;
    align-items: center;
    gap: var(--sgsi-space-3);
    padding: var(--sgsi-space-3) var(--sgsi-space-4);
    border: 1px solid var(--sgsi-color-brand);
    border-radius: var(--sgsi-radius-md);
    background: var(--sgsi-color-brand-bg);
}

.sgsi-evol__upsell-icone {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.25rem;
    height: 2.25rem;
    border-radius: var(--sgsi-radius-md);
    background: var(--sgsi-color-surface);
    color: var(--sgsi-color-brand);
    flex-shrink: 0;
}

.sgsi-evol__upsell-texto {
    display: flex;
    flex-direction: column;
    gap: 0.1rem;
    flex: 1;
    font-size: var(--sgsi-font-size-sm);
    color: var(--sgsi-color-text-muted);
}

.sgsi-evol__upsell-texto strong {
    color: var(--sgsi-color-text);
}

/* ---- Gráfico ---- */
.sgsi-evol__grafico-cab {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: var(--sgsi-space-2);
    margin-bottom: var(--sgsi-space-3);
}

.sgsi-evol__grafico-titulo {
    margin: 0;
    font-size: var(--sgsi-font-size-lg);
    font-weight: var(--sgsi-font-weight-semibold);
    color: var(--sgsi-color-text);
}

.sgsi-evol__grafico-legenda {
    font-size: var(--sgsi-font-size-xs);
    color: var(--sgsi-color-text-subtle);
    font-variant-numeric: tabular-nums;
}

.sgsi-evol__grafico {
    width: 100%;
    height: auto;
    display: block;
    overflow: visible;
}

.sgsi-evol__eixo {
    font-size: 10px;
    fill: var(--sgsi-color-text-subtle);
    font-variant-numeric: tabular-nums;
}

}

/* ── Onboarding: stepper de progresso + tela final ──────────────────────────
   Usado por /primeiros-passos (wizard do consultor) e /templates/onboarding.
   As <li> carregam só is-atual / is-feito (sem classe-base), dentro de .sgsi-stepper. */
.sgsi-stepper {
    display: flex;
    flex-wrap: wrap;
    gap: var(--sgsi-space-2);
    list-style: none;
    padding: 0;
    margin: 0 0 var(--sgsi-space-5);
}

.sgsi-stepper > li {
    flex: 1 1 6rem;
    text-align: center;
    padding: var(--sgsi-space-2) var(--sgsi-space-3);
    border: 1px solid var(--sgsi-color-border);
    border-radius: var(--sgsi-radius-md);
    background: var(--sgsi-color-surface-2);
    color: var(--sgsi-color-text-muted);
    font-size: var(--sgsi-font-size-sm);
    font-weight: var(--sgsi-font-weight-medium);
}

.sgsi-stepper > li.is-atual {
    border-color: var(--sgsi-color-brand);
    background: var(--sgsi-color-brand-bg);
    color: var(--sgsi-color-brand);
    font-weight: var(--sgsi-font-weight-semibold);
}

.sgsi-stepper > li.is-feito {
    border-color: var(--sgsi-color-success);
    color: var(--sgsi-color-success);
}

.sgsi-onboarding-pronto {
    text-align: center;
}

.sgsi-onboarding-pronto__icone {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 4rem;
    height: 4rem;
    margin-bottom: var(--sgsi-space-3);
    border-radius: var(--sgsi-radius-pill);
    background: var(--sgsi-color-brand-bg);
    color: var(--sgsi-color-brand);
}

.sgsi-onboarding-pronto__acoes {
    display: flex;
    flex-wrap: wrap;
    gap: var(--sgsi-space-3);
    justify-content: center;
    margin-top: var(--sgsi-space-4);
}

/* ==========================================================================
   COCKPIT DE ASSINATURA (/minha-assinatura) — plano vigente + medidores de uso.
   As famílias .sgsi-plano-* / .sgsi-medidor* / .sgsi-barra* eram usadas no
   markup sem NENHUMA definição (renderizavam sem estilo). A barra de progresso
   segue o visual do SgsiProgressBar (#43): trilho pill em surface-3 +
   preenchimento em brand — aqui na forma "fina" (só trilho; o rótulo/valor
   vêm do cabeçalho do medidor).
   ========================================================================== */

/* Cabeçalho do card do plano: nome/família à esquerda, badge de status à direita. */
.sgsi-plano-cab {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--sgsi-space-3);
    flex-wrap: wrap;
}
.sgsi-plano-nome {
    margin: 0;
    font-size: var(--sgsi-font-size-xl);
    font-weight: var(--sgsi-font-weight-bold);
    line-height: var(--sgsi-line-height-tight);
}
/* A linha da família do plano (p.sgsi-texto-suave) cola no nome, sem o margin do reboot. */
.sgsi-plano-cab .sgsi-texto-suave { margin: var(--sgsi-space-1) 0 0; }

/* Metadados do plano (<dl>): pares rótulo/valor lado a lado, no padrão "stat"
   (rótulo em caps discretas, valor com dígitos tabulares). */
.sgsi-plano-meta {
    display: flex;
    flex-wrap: wrap;
    gap: var(--sgsi-space-3) var(--sgsi-space-6);
    margin: var(--sgsi-space-4) 0 0;
}
.sgsi-plano-meta dt {
    font-size: var(--sgsi-font-size-xs);
    font-weight: var(--sgsi-font-weight-semibold);
    color: var(--sgsi-color-text-muted);
    text-transform: uppercase;
    letter-spacing: var(--sgsi-letter-spacing-caps);
}
.sgsi-plano-meta dd {
    margin: var(--sgsi-space-1) 0 0;
    font-weight: var(--sgsi-font-weight-medium);
    font-variant-numeric: tabular-nums;
}

/* Medidores de uso vs. limite: grade responsiva de mini-cards (assentos,
   exports/mês, gerações de IA/mês, storage…). */
.sgsi-medidores {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(16rem, 100%), 1fr));
    gap: var(--sgsi-space-4);
}
.sgsi-medidor {
    display: flex;
    flex-direction: column;
    gap: var(--sgsi-space-2);
    padding: var(--sgsi-space-3) var(--sgsi-space-4);
    background: var(--sgsi-color-surface);
    border: 1px solid var(--sgsi-color-border);
    border-radius: var(--sgsi-radius-md);
    box-shadow: var(--sgsi-shadow-xs);
}
.sgsi-medidor__cab {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--sgsi-space-2);
    flex-wrap: wrap;
}
.sgsi-medidor__rotulo {
    font-size: var(--sgsi-font-size-sm);
    font-weight: var(--sgsi-font-weight-medium);
    color: var(--sgsi-color-text-muted);
}
.sgsi-medidor__valor {
    font-size: var(--sgsi-font-size-sm);
    font-weight: var(--sgsi-font-weight-semibold);
    font-variant-numeric: tabular-nums;
    color: var(--sgsi-color-text);
    text-align: right;
}
/* Aviso de limite atingido (role=alert) sob a barra. */
.sgsi-medidor__aviso {
    margin: 0;
    font-size: var(--sgsi-font-size-xs);
    color: var(--sgsi-color-danger);
}

/* Barra de progresso fina: trilho + filho .sgsi-barra__preenchida com width inline. */
.sgsi-barra {
    position: relative;
    overflow: hidden;
    height: 0.5rem;
    border-radius: var(--sgsi-radius-pill);
    background: var(--sgsi-color-surface-3);
}
.sgsi-barra__preenchida {
    height: 100%;
    border-radius: inherit;
    background: var(--sgsi-color-brand);
    transition: width 0.25s ease;
}
/* Perto do limite (>= 80% no call-site): preenchimento em âmbar; o estouro
   (100%) é comunicado pelo .sgsi-medidor__aviso + nudge .sgsi-alert--danger. */
.sgsi-barra--alerta .sgsi-barra__preenchida { background: var(--sgsi-color-warning); }
@media (prefers-reduced-motion: reduce) {
    .sgsi-barra__preenchida { transition: none; }
}

/* ==========================================================================
   BARRA DE FILTROS (Ui/SgsiBarraFiltros + Ui/SgsiFiltroSelect)
   Componente canônico que substitui o gabarito copiado nas ~46 telas-índice
   (.sgsi-risco-filtros / .sgsi-risco-filtro — legado, remove-se ao fim da
   migração). As classes novas .sgsi-filtros__* REPRODUZEM o visual do gabarito
   pixel-a-pixel (mesmo grid auto-fit 200px, mesmos tokens) para a migração não
   mudar o layout. O cartão continua usando .sgsi-filtros-card (margin-bottom
   já definido na seção "Filtros" do módulo Riscos, acima).
   ========================================================================== */

/* Grid da barra: filtros (e itens extras) fluem em colunas responsivas. */
.sgsi-filtros {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(200px, 100%), 1fr));
    gap: var(--sgsi-space-4);
    padding: var(--sgsi-space-4);
}

/* Um filtro: label em cima + controle embaixo (espelho de .sgsi-risco-filtro). */
.sgsi-filtros__item {
    display: flex;
    flex-direction: column;
    gap: var(--sgsi-space-1);
}

/* Célula do "Limpar filtros" (só renderiza com filtro ativo): o botão alinha
   à BASE da célula — na linha dos selects, não na dos labels. */
.sgsi-filtros__acoes {
    display: flex;
    align-items: flex-end;
    justify-content: flex-start;
}

/* Botão fantasma discreto (variante Link do SgsiBotao): cor atenuada e sem
   sublinhado em repouso; cor plena + sublinhado no hover/teclado. */
.sgsi-filtros__limpar {
    display: inline-flex;
    align-items: center;
    gap: var(--sgsi-space-1);
    color: var(--sgsi-color-text-muted);
    text-decoration: none;
}
.sgsi-filtros__limpar:hover,
.sgsi-filtros__limpar:focus-visible {
    color: var(--sgsi-color-text);
    text-decoration: underline;
}

/* ── Trilha do primeiro acesso (TrilhaPrimeiroAcesso) ───────────────────────
   O fio condutor que faltava entre o cadastro e o produto. Vive no topo do
   /m/perfil, que e onde a guarda desvia o consultor recem-cadastrado — e SOME
   sozinha quando nao ha passo pendente, entao nao vira mobilia para quem ja se
   acertou.

   Por que ela nao usa .sgsi-stepper: aquele e o progresso DENTRO de uma tarefa
   (os 3 passos do wizard). Este e o percurso ENTRE tarefas, com um bloco de
   "o que fazer agora" abaixo. Compartilhar a classe faria os dois divergirem
   na primeira mudanca de qualquer um dos dois.

   O PREFIXO `sgsi-trilha` NAO E LIVRE: ele ja pertence a trilha de AUDITORIA
   (`.sgsi-trilha__integ`, em PaginaTrilhaAuditoria). Duas coisas diferentes com o
   mesmo prefixo BEM fazem o proximo a mexer achar que sao a mesma familia — por isso
   este bloco e `sgsi-primeiros-passos`, que e tambem o nome que o usuario le na tela. */
.sgsi-primeiros-passos {
    border: 1px solid var(--sgsi-color-brand);
    border-radius: var(--sgsi-radius-lg);
    background: var(--sgsi-color-brand-bg);
    padding: var(--sgsi-space-4);
    margin-bottom: var(--sgsi-space-5);
}

.sgsi-primeiros-passos__cab {
    display: flex;
    align-items: center;
    gap: var(--sgsi-space-3);
    margin-bottom: var(--sgsi-space-4);
}

.sgsi-primeiros-passos__icone {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 2.5rem;
    height: 2.5rem;
    border-radius: 50%;
    background: var(--sgsi-color-brand);
    color: var(--sgsi-color-on-brand);
}

.sgsi-primeiros-passos__titulo {
    margin: 0;
    font-size: var(--sgsi-font-size-md);
    font-weight: var(--sgsi-font-weight-semibold);
    color: var(--sgsi-color-text);
}

.sgsi-primeiros-passos__contagem {
    margin: 0;
    font-size: var(--sgsi-font-size-sm);
    color: var(--sgsi-color-text-muted);
}

.sgsi-primeiros-passos__passos {
    display: flex;
    flex-wrap: wrap;
    gap: var(--sgsi-space-2);
    list-style: none;
    padding: 0;
    margin: 0 0 var(--sgsi-space-4);
}

.sgsi-primeiros-passos__passos > li {
    display: flex;
    align-items: center;
    gap: var(--sgsi-space-2);
    flex: 1 1 8rem;
    padding: var(--sgsi-space-2) var(--sgsi-space-3);
    border: 1px solid var(--sgsi-color-border);
    border-radius: var(--sgsi-radius-md);
    background: var(--sgsi-color-surface);
    color: var(--sgsi-color-text-muted);
    font-size: var(--sgsi-font-size-sm);
}

/* A MARCA CARREGA O ESTADO SEM DEPENDER DA COR: vazia = a fazer, preenchida
   com o check = feita, anel = atual. Quem nao distingue as cores le a mesma
   coisa na forma — e o texto oculto do componente diz em palavras. */
.sgsi-primeiros-passos__marca {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 1.25rem;
    height: 1.25rem;
    border: 2px solid var(--sgsi-color-border-strong);
    border-radius: 50%;
    background: transparent;
}

/* O rotulo do passo. `min-width: 0` deixa o texto encolher dentro do flex em vez de
   empurrar a caixa para fora da tela — sem ele, um rotulo traduzido mais longo estoura
   a largura no mobile, que e onde estas caixas ja quebram em duas linhas. */
.sgsi-primeiros-passos__rotulo {
    min-width: 0;
    overflow-wrap: anywhere;
}

.sgsi-primeiros-passos__passos > li.is-feito {
    border-color: var(--sgsi-color-success);
    color: var(--sgsi-color-text);
}

/* O CHECK SUMIA NO TEMA ESCURO (09/09, auditoria pre-deploy). Isto cravava `#fff`, e o token
   `--sgsi-color-success` INVERTE entre os temas: #1b7a3e (escuro) no claro, #5fd089 (claro) no
   escuro. Branco sobre o verde claro da 1,92:1 — abaixo dos 3:1 da WCAG para elemento grafico —,
   entao a marca de passo concluido ficava quase invisivel para quem usa o tema escuro. Cor cravada
   sobre fundo tematico e sempre isto: acerta num tema por acidente e erra no outro. */
.sgsi-primeiros-passos__passos > li.is-feito .sgsi-primeiros-passos__marca {
    border-color: var(--sgsi-color-success);
    background: var(--sgsi-color-success);
    color: var(--sgsi-color-on-success);
}

.sgsi-primeiros-passos__passos > li.is-atual {
    border-color: var(--sgsi-color-brand);
    background: var(--sgsi-color-surface);
    color: var(--sgsi-color-text);
    font-weight: var(--sgsi-font-weight-semibold);
    box-shadow: 0 0 0 3px var(--sgsi-color-focus-ring);
}

.sgsi-primeiros-passos__passos > li.is-atual .sgsi-primeiros-passos__marca {
    border-color: var(--sgsi-color-brand);
}

.sgsi-primeiros-passos__atual {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--sgsi-space-3);
    padding-top: var(--sgsi-space-3);
    border-top: 1px solid var(--sgsi-color-border);
}

.sgsi-primeiros-passos__explicacao {
    flex: 1 1 18rem;
    margin: 0;
    font-size: var(--sgsi-font-size-sm);
    color: var(--sgsi-color-text);
}

.sgsi-primeiros-passos__cta {
    display: inline-flex;
    align-items: center;
    gap: var(--sgsi-space-2);
    flex: 0 0 auto;
}
