/*
 * CRUD global (#86): estrutura visual comum das telas de cadastro — toolbar,
 * formulario em grade de ancoragem, grade de consulta, mensagens e escala por
 * degraus. Complementa shell.css (que cuida da shell/janelas e define as
 * variaveis --shell-*). Nada aqui e especifico de uma tela.
 *
 * Revisao visual (#194): grade sem gradeado vertical (linhas horizontais),
 * toolbar com icones e rotulos que somem (em vez de truncar) em janela
 * estreita, estados de campo (foco/erro/readonly/obrigatorio) e mensagens com
 * acento semantico. Nenhum seletor/contrato usado pelo crud.js foi alterado.
 */

/* ---------- Tabela da grade de consulta ---------- */
.painel-corpo table {
    border-collapse: collapse;
    width: 100%;
    font-size: 13px;
}

/* Cabecalho fixo ao rolar: no legado o grid e um objeto a parte, com scroll
   proprio, e os titulos das colunas nunca somem. `sticky` prende o `th` ao topo
   do ANCESTRAL QUE ROLA, seja ele o `.grade-scroll` das telas de cadastro ou o
   proprio `.painel-corpo` nas telas que montam a tabela a mao — por isso vale
   para todos os grids de uma vez, sem tocar em cada template.

   O z-index e necessario porque celulas de linha pintariam por cima do
   cabecalho ao passarem sob ele. */
.painel-corpo thead th {
    position: sticky;
    top: 0;
    z-index: 2;
}

/* Duas sombras, cada uma resolvendo um artefato do cabecalho grudado:

   1) `inset 0 -1px` — com `border-collapse: collapse` a borda pertence a TABELA,
      nao a celula: ao grudar, o `th` leva o fundo mas deixa a borda para tras e o
      cabecalho fica sangrando sobre as linhas. A sombra interna desenha a mesma
      linha por dentro da celula, que acompanha o elemento grudado.

   2) `0 -12px` (para CIMA, na cor do proprio cabecalho) — quando quem rola e o
      `.painel-corpo`, o topo do scrollport fica DEPOIS do seu padding, entao o
      `th` gruda 12px abaixo da borda e as linhas apareciam nessa faixa, por cima
      do cabecalho. Esta sombra pinta a faixa. Dentro de um `.grade-scroll` ela e
      recortada pelo proprio `overflow`, entao nao atrapalha. */
.painel-corpo thead th {
    border-bottom: 0;
    box-shadow:
        inset 0 -1px 0 var(--shell-borda-forte),
        0 calc(-1 * var(--painel-padding-topo, 12px)) 0 var(--shell-superficie-2);
}

/* ---------- Grid como objeto proprio, com scroll independente ----------
   Espelha o legado: a tela nao rola; quem rola e o grid. Titulo, toolbar e
   mensagens ficam ancorados no topo e so as LINHAS deslizam.

   Depende da cadeia de altura ja existente: .janela (flex column, min-height:0)
   -> .painel-corpo (flex:1) -> este conteudo (height:100%) -> .grade-scroll
   (flex:1). O `min-height: 0` em cada degrau e o que impede o item flex de
   crescer alem do pai — sem ele o scroll volta a nascer no .painel-corpo. */
.painel-corpo > .painel-conteudo.com-grade {
    display: flex;
    flex-direction: column;
    height: 100%;
    min-height: 0;
}

.painel-conteudo.com-grade .grade-scroll {
    flex: 1;
    min-height: 0;
    overflow: auto;
}

/* Variante do grid de selecao (#132): embutido em containers de altura variavel
   (subtela modal, tela cheia), entao nao da para "preencher o resto" — o teto e
   por max-height. Mantem as acoes logo abaixo do grid sempre alcancaveis.
   Sobrescrevivel por tela via --grade-altura-max. */
.grade-scroll-limitado {
    overflow: auto;
    max-height: var(--grade-altura-max, 46vh);
}

/* Linhas horizontais apenas: leitura em faixas, sem o gradeado completo que
   pesava a tela. O cabecalho distingue por fundo + borda inferior forte. */
.painel-corpo th, .painel-corpo td {
    border-bottom: 1px solid var(--shell-borda);
    padding: 6px 10px;
    text-align: left;
}

.painel-corpo th {
    background: var(--shell-superficie-2);
    border-bottom: 1px solid var(--shell-borda-forte);
    font-size: 11px;
    font-weight: 650;
    text-transform: uppercase;
    color: var(--shell-texto-suave);
    white-space: nowrap;
}

/* Colunas numericas (ID, codigos, valores): alinhar a direita com algarismos
   tabulares. Opt-in por classe nas celulas/cabecalhos das telas. */
.painel-corpo th.col-num, .painel-corpo td.col-num {
    text-align: right;
    font-variant-numeric: tabular-nums;
}

.painel-corpo button { cursor: pointer; }

/* Links dentro da grade (ID, codigos): cor informativa do tema no lugar do
   azul default do navegador; linha selecionada re-tinge para branco. */
.painel-corpo td a {
    color: var(--shell-info);
    text-decoration-color: var(--shell-info-borda);
}

.painel-corpo td a:hover { text-decoration-color: currentColor; }

/* ---------- Formulario: CAPA em cima + ABAS embaixo (#172, como o legado) ----------
   Duas zonas com layouts distintos, espelhando o cadastro do legado:

   1) CAPA (`.form-capa` e as linhas soltas antes das secoes): cabecalho SEMPRE
      visivel, denso, com o label a ESQUERDA do campo. Grade alinhada por colunas.
   2) ABAS (`.form-secao`, viram abas pelo crud.js): conteudo secundario, com o
      label EM CIMA do campo — mais informacao sem rolar a tela.

   Larguras por classe: campo-p estreito | campo-m medio | campo-g largo |
   campo-total linha inteira. As classes pos-* antigas seguem como apelidos. */
.form-linha {
    display: flex;
    flex-wrap: wrap;
    gap: 8px 18px;
    margin-bottom: 8px;
    max-width: var(--form-largura, 860px);
}

/* Linha que termina com o botao da acao, no lugar de uma faixa .painel-acoes so
   para ele. Alinha pela BASE porque nesta zona o label fica em cima do campo: o
   botao precisa acompanhar a altura do input, nao a do conjunto label+input. */
.form-linha-acao {
    align-items: flex-end;
}

.form-linha-acao > .botao {
    /* Nao estica junto com os campos flex, e nao encolhe abaixo do rotulo. */
    flex: 0 0 auto;
    height: var(--controle-altura, 30px);
}

/* Texto de apoio curto (uma linha): instrucao ou estado de leitura rapida. Nao e
   mensagem semantica — para isso existem .mensagem-*. */
.ajuda-curta {
    margin: 0 0 8px;
    font-size: 12px;
    color: var(--shell-texto-suave);
}

.ajuda-curta strong { color: var(--shell-texto); font-weight: 650; }

/* Campo da CAPA (default): label a esquerda, denso. */
.form-campo {
    display: flex;
    align-items: center;
    gap: 8px;
    flex: 1 1 240px;
    min-width: 0;
}

.form-campo > label {
    width: 78px;
    flex-shrink: 0;
    text-align: right;
    font-size: 12px;
    color: var(--shell-texto-suave);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Obrigatoriedade anunciada no label (alem da validacao): o asterisco vem do
   proprio required do campo, sem classe extra nos templates. */
.form-campo:has(> input[required]) > label::after,
.form-campo:has(> select[required]) > label::after {
    content: " *";
    color: var(--shell-erro);
}

.form-campo input,
.form-campo select {
    flex: 1;
    min-width: 0;
    box-sizing: border-box;
    border: 1px solid var(--shell-borda-forte);
    border-radius: var(--controle-raio, 4px);
    height: var(--controle-altura, 30px);
    padding: 0 9px;
    font: inherit;
    font-size: 13px;
    background: var(--shell-superficie);
    color: var(--shell-texto);
}

.form-campo input::placeholder { color: var(--shell-texto-fraco); }

/* Foco de edicao: anel discreto na cor de foco (o :focus-visible global cobre
   a navegacao por teclado; aqui e o feedback de campo ativo em qualquer foco). */
.painel-corpo input:focus,
.painel-corpo select:focus,
.painel-corpo textarea:focus {
    outline: none;
    border-color: var(--shell-foco);
    box-shadow: 0 0 0 2px var(--shell-foco-halo);
}

/* Erro por campo (progressivo, so apos interacao): alem da cor, o title/balao
   nativo identifica o problema. */
.painel-corpo input:user-invalid,
.painel-corpo select:user-invalid {
    border-color: var(--shell-erro);
}

.painel-corpo input:user-invalid:focus,
.painel-corpo select:user-invalid:focus {
    border-color: var(--shell-erro);
    box-shadow: 0 0 0 2px rgba(179, 38, 30, 0.18);
}

/* Capa em grade densa: colunas alinhadas entre as linhas, campos largos ocupam 2. */
.form-capa {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
    gap: 8px 22px;
    margin-bottom: 12px;
    padding-bottom: 12px;
    border-bottom: 1px solid var(--shell-borda);
    max-width: var(--form-largura, 860px);
}

.form-capa .form-campo { flex: initial; }              /* vira celula da grade */
/* Linhas dentro da capa dissolvem: os campos participam direto da grade (telas
   simples mantem o markup form-linha > form-campo sem reescrever). */
.form-capa .form-linha { display: contents; }
.form-capa .campo-g,
.form-capa .pos-1-2 { grid-column: span 2; }
.form-capa .campo-total,
.form-capa .pos-total { grid-column: 1 / -1; }

/* Cabecalho FIXO acima das abas (.form-cabecalho): e o desenho do FormInfo 151 do
   legado, onde os eixos e a descricao ficam sempre visiveis e as abas de tributo
   ficam embaixo. Usa o mesmo campo da aba (rotulo EM CIMA) porque e assim que o
   legado desenha aquela faixa — ao contrario da capa dos cadastros simples, que
   tem o rotulo a esquerda. */
.form-cabecalho {
    margin: 0 0 14px;
    padding-bottom: 12px;
    border-bottom: 1px solid var(--shell-borda);
}

/* Campo da ABA (dentro de .form-secao): label EM CIMA, largura natural por classe. */
.form-secao .form-campo,
.form-cabecalho .form-campo {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 4px;
    flex: 1 1 200px;
}

.form-secao .form-campo > label,
.form-cabecalho .form-campo > label {
    width: auto;
    text-align: left;
    font-size: 11px;
    font-weight: 600;
    overflow: visible;
}

.form-secao .form-campo input,
.form-secao .form-campo select,
.form-cabecalho .form-campo input,
.form-cabecalho .form-campo select { width: 100%; flex: none; height: var(--controle-altura, 30px); }

/* Textarea de EDICAO (o FieldType.AREA do legado): mesma moldura dos demais
   controles, mas sem a altura fixa de 30px — quem digita observacao precisa ver
   mais de uma linha. */
.painel-corpo .form-campo textarea {
    width: 100%;
    box-sizing: border-box;
    border: 1px solid var(--shell-borda-forte);
    border-radius: var(--controle-raio, 4px);
    padding: 6px 9px;
    font: inherit;
    font-size: 13px;
    background: var(--shell-superficie);
    color: var(--shell-texto);
    resize: vertical;
}

.form-secao .campo-p,
.form-cabecalho .campo-p { flex: 1 1 120px; }   /* estreito: CEP, UF, numero, codigo */
.form-secao .campo-m,
.form-cabecalho .campo-m { flex: 1 1 200px; }   /* medio */
.form-secao .campo-g,
.form-cabecalho .campo-g { flex: 2 1 300px; }   /* largo: logradouro, nome, e-mail */
.form-secao .campo-total,
.form-cabecalho .campo-total { flex: 1 1 100%; }

/* Apelidos das ancoragens antigas (#86) como largura em flex, telas nao migradas. */
.pos-1, .pos-2, .pos-3 { flex: 1 1 200px; }
.pos-1-2 { flex: 2 1 300px; }
.pos-total { flex: 1 1 100%; }

/* ---------- Janela apertada no tiling (#172) ----------
   Com flex-wrap os campos ja quebram sozinhos; aqui so compactamos a escala
   (fonte e altura) para caber mais em janela pequena, sem as linhas pularem de
   lugar. O container e o .painel-corpo (container-type em shell.css). */
@container (max-width: 480px) {
    .form-campo input,
    .form-campo select,
    .form-campo > label { font-size: 11px; }
    .form-campo input,
    .form-campo select { height: 28px; }
    .form-linha { gap: 8px 12px; }
    .botao { font-size: 11px; }
    .toolbar-contador { font-size: 11px; }
}

/* Janela estreita: o rotulo dos botoes da toolbar SOME e fica so o icone
   (largura estavel, tooltip/aria-label preservados) — nada de "I..."/"S..."
   truncado. Os botoes de navegacao ja sao so-icone em qualquer largura. */
@container (max-width: 860px) {
    .painel-corpo .toolbar .botao-rotulo { display: none; }
    .painel-corpo .toolbar .botao { padding: 4px 8px; }
}

/* Janela minima: a toolbar quebra linha de forma controlada (icones sempre
   alcancaveis) em vez de estourar para fora do painel. */
@container (max-width: 420px) {
    .painel-corpo .toolbar { flex-wrap: wrap; row-gap: 4px; }
}

/* ID e chave interna gerada: readonly com aparencia de somente-leitura
   (distinta do disabled, que fica atenuado). */
.painel-corpo input[readonly] {
    background: var(--shell-superficie-2);
    border-color: var(--shell-borda);
    color: var(--shell-texto-suave);
    cursor: default;
}

.painel-corpo input[readonly]:focus { box-shadow: none; border-color: var(--shell-borda-forte); }

.painel-corpo input[disabled],
.painel-corpo select[disabled] {
    background: var(--shell-superficie-2);
    border-color: var(--shell-borda);
    color: var(--shell-texto-fraco);
    opacity: 1;
}

/* Toolbar no topo da tela (padrao do legado): Incluir | Salvar | Excluir.
   Seletores com .painel-corpo para vencer a margem generica de form div. */
.painel-corpo .toolbar {
    display: flex;
    align-items: center;
    gap: 4px;
    margin: 0 0 12px;
    padding-bottom: 10px;
    border-bottom: 1px solid var(--shell-borda);
}

.painel-corpo .toolbar div { margin-bottom: 0; }

/* Botoes da toolbar: altura fixa e largura estavel (icone + rotulo; o rotulo
   some por degrau de container, nunca trunca). */
.painel-corpo .toolbar .botao {
    flex: 0 0 auto;
    min-width: 28px;
    height: 28px;
    box-sizing: border-box;
    white-space: nowrap;
}

.toolbar-sep {
    width: 1px;
    height: 18px;
    background: var(--shell-borda-forte);
    margin: 0 5px;
    flex-shrink: 0;
}

.toolbar-contador {
    margin-left: 6px;
    color: var(--shell-texto-suave);
    font-size: 12px;
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
}

/* Teto de linhas da consulta (#137): campo compacto na toolbar, ao lado do contador. */
.toolbar-limite {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    margin-left: 6px;
    color: var(--shell-texto-suave);
    font-size: 12px;
    white-space: nowrap;
}

.toolbar-limite input {
    width: 48px;
    height: 28px;
    box-sizing: border-box;
    border: 1px solid var(--shell-borda-forte);
    border-radius: var(--controle-raio, 4px);
    padding: 0 5px;
    font: inherit;
    font-size: 13px;
    text-align: right;
}

/* ---------- Botoes ---------- */
.botao {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    padding: 4px 12px;
    background: var(--shell-superficie);
    border: 1px solid var(--shell-borda-forte);
    border-radius: var(--controle-raio, 4px);
    color: var(--shell-texto);
    cursor: pointer;
    font: inherit;
    font-size: 13px;
    line-height: 1.3;
    text-decoration: none;
}

/* Icones (SVG inline nos fragments, stroke = currentColor): dimensao fixa para
   o layout nao pulsar entre estados. aria-hidden nos templates. */
.botao .icone {
    width: 15px;
    height: 15px;
    flex-shrink: 0;
}

.botao:hover:not([disabled]):not(.desabilitado) {
    background: var(--shell-superficie-2);
    border-color: var(--shell-destaque);
    color: var(--shell-destaque);
}

.botao:active:not([disabled]):not(.desabilitado) { background: var(--shell-borda); }

/* Acao principal = verde institucional da Udisoft (#125); texto grafite p/ contraste. */
.botao.primario {
    background: var(--shell-acao);
    border-color: var(--shell-acao-escura);
    color: var(--shell-acao-texto);
    font-weight: 600;
}

.botao.primario:hover:not([disabled]):not(.desabilitado) {
    background: var(--shell-acao-clara);
    border-color: var(--shell-acao-escura);
    color: var(--shell-acao-texto);
}

.botao.primario:active:not([disabled]):not(.desabilitado) { background: var(--shell-acao-escura); }

.botao.perigo {
    border-color: var(--shell-erro-borda);
    color: var(--shell-erro);
}

.botao.perigo:hover:not([disabled]):not(.desabilitado) {
    background: var(--shell-erro-fundo);
    border-color: var(--shell-erro);
    color: var(--shell-erro);
}

/* Botao inerte: <button disabled> ou ancora sem href (toolbar estatica).
   Neutro e atenuado — nao um "verde lavado" ilegivel. */
.botao[disabled], .botao.desabilitado {
    background: var(--shell-superficie);
    border-color: var(--shell-borda);
    color: #a9acb0;
    font-weight: 400;
    cursor: default;
    pointer-events: none;
}

.painel-acoes { margin-bottom: 10px; }

/* ---------- Secoes do formulario (#167) em ABAS (#172) ----------
   Agrupamento nomeado (Identificacao, Endereco, Fiscal...). O crud.js monta a
   barra de abas a partir dos titulos quando ha 2+ secoes; ve-se muita informacao
   sem rolar (como o legado). Cada secao e o painel de uma aba; a inativa fica
   [hidden]. Com 0-1 secao nao ha abas e o card discreto aparece sozinho. */
.painel-corpo .form-secao {
    margin: 0 0 12px;
    border: 1px solid var(--shell-borda);
    border-radius: var(--painel-raio, 6px);
    padding: 14px 16px;
    max-width: var(--form-largura, 860px);
    background: var(--shell-superficie);
}

/* Aba inativa some de verdade: o [hidden] que o crud.js aplica vence qualquer
   display deste stylesheet (sem isso, display:flex/grid "fura" o hidden). */
.painel-corpo .form-secao[hidden],
.painel-corpo .form-secao-titulo[hidden] { display: none; }

/* Titulos livres dentro de um card de secao (ex.: Certificado Digital usa <h3>
   sem a classe de titulo de aba): mesma escala compacta do padrao. */
.painel-corpo .form-secao h3 {
    margin: 0 0 12px;
    font-size: 13px;
    font-weight: 650;
}

/* Upload dentro de um campo: o input de arquivo tem miolo proprio do navegador;
   altura natural com padding leve alinha com os demais controles. */
.form-campo input[type="file"] {
    height: auto;
    min-height: var(--controle-altura, 30px);
    padding: 3px 8px;
}

/* Dentro do painel a largura ja e limitada pelo card; nao re-limitar a linha. */
.painel-corpo .form-secao .form-linha { max-width: none; margin-bottom: 12px; }
.painel-corpo .form-secao .form-linha:last-child { margin-bottom: 0; }

/* ---------- Interruptor de bloco de tributo (#209, Fase 4) ----------
   Abre as abas ICMS / ICMS-ST / Interestadual da Tributacao. Marcado = a regra
   TRATA aquele tributo; desmarcado = nao ha linha no bloco, e o XML sai sem o
   grupo. E o unico jeito de a tela distinguir "nao trata ST" de "trata ST com
   aliquota zero", que sao afirmacoes diferentes.

   Fica antes dos campos e os APAGA quando desmarcado (:has, sem JS). Apagar e
   nao desabilitar: campo desabilitado nao e enviado nem preservado, e quem
   desmarca por engano perderia o que digitou. O servidor ja ignora os campos do
   bloco desmarcado, entao a dica visual basta. */
.painel-corpo .bloco-interruptor {
    display: flex;
    align-items: center;
    gap: 8px;
    margin: 0 0 12px;
    padding-bottom: 10px;
    border-bottom: 1px solid var(--shell-borda);
    font-size: 12px;
    font-weight: 650;
}

/* O input de bloco NAO herda o flex:1 e a altura de 30px de .form-campo input:
   um checkbox esticado na largura do card seria ilegivel como controle. */
.painel-corpo .bloco-interruptor input[type="checkbox"] {
    flex: 0 0 auto;
    width: auto;
    height: auto;
    min-width: 0;
    margin: 0;
    padding: 0;
}

/* Campos do bloco desligado: visiveis (o usuario ve o que ha para preencher) e
   apagados, para nao competirem com o resto da tela.

   O alvo e o .bloco-grupo, NAO a .form-secao: a aba "ICMS" do legado (FormInfo 151)
   hospeda ICMS e ICMS-ST lado a lado, cada um com o seu proprio interruptor. Preso
   a secao, desligar a ST apagaria tambem os campos do ICMS proprio. */
.painel-corpo .bloco-grupo:has(.bloco-interruptor input:not(:checked)) .form-linha,
.painel-corpo .bloco-grupo:has(.bloco-interruptor input:not(:checked)) .ajuda-curta {
    opacity: 0.5;
    pointer-events: none;
}

/* Titulo do grupo dentro de uma aba que hospeda mais de um bloco. */
.painel-corpo .bloco-titulo {
    margin: 18px 0 8px;
    font-size: 12px;
    font-weight: 650;
    color: var(--shell-texto);
}

.painel-corpo .bloco-grupo:first-of-type .bloco-titulo { margin-top: 0; }

.painel-corpo .form-secao-titulo {
    margin: 0 0 10px;
    font-size: 12px;
    font-weight: 650;
    color: var(--shell-texto);
    display: flex;
    align-items: center;
    gap: 6px;
}

/* Barra de abas (montada pelo crud.js). Fica colada no topo do painel ativo. */
.painel-corpo .form-abas {
    display: flex;
    flex-wrap: wrap;
    gap: 2px;
    margin: 0 0 -1px;
    max-width: var(--form-largura, 860px);
}

.painel-corpo .form-aba {
    background: var(--shell-fundo);
    border: 1px solid var(--shell-borda);
    border-bottom-color: transparent;
    border-radius: 6px 6px 0 0;
    padding: 6px 16px;
    font: inherit;
    font-size: 12px;
    color: var(--shell-texto-suave);
    cursor: pointer;
    white-space: nowrap;
}

.painel-corpo .form-aba:hover:not(.ativa) {
    background: var(--shell-superficie-2);
    color: var(--shell-texto);
}

/* Aba ativa = mesma superficie do painel, "furando" a borda de cima do card,
   com o acento verde da marca no topo. */
.painel-corpo .form-aba.ativa {
    background: var(--shell-superficie);
    color: var(--shell-texto);
    font-weight: 600;
    border-bottom-color: var(--shell-superficie);
    box-shadow: inset 0 2px 0 var(--shell-acao);
}

/* Painel logo apos a barra: canto superior esquerdo reto para casar com a 1a aba. */
.painel-corpo .form-abas + .form-secao { border-top-left-radius: 0; }

/* Caixa alta so visual (#167): antecipa a normalizacao que o backend faz de
   verdade (nome/fantasia do legado). O valor submetido nao e alterado aqui. */
.form-campo input.caixa-alta { text-transform: uppercase; }

/* Texto de apoio abaixo de um campo (ex.: a regra de tamanho minimo da senha):
   informativo, nao mensagem de desfecho — por isso discreto e sem moldura. */
.form-ajuda {
    color: var(--shell-texto-fraco, #666);
    font-size: 0.85em;
    margin: 0 0 10px;
}

/* ---------- Mensagens de desfecho ----------
   Faixas com acento lateral na cor semantica: erro, sucesso, aviso e info tem
   cores proprias (a marca nao participa da semantica de estado). */
[role="alert"] {
    background: var(--shell-erro-fundo);
    border: 1px solid var(--shell-erro-borda);
    border-left: 4px solid var(--shell-erro);
    border-radius: var(--controle-raio, 4px);
    color: var(--shell-erro);
    margin: 0 0 10px;
    padding: 7px 12px;
}

.mensagem-sucesso {
    background: var(--shell-sucesso-fundo);
    border: 1px solid var(--shell-sucesso-borda);
    border-left: 4px solid var(--shell-sucesso);
    border-radius: var(--controle-raio, 4px);
    color: var(--shell-sucesso);
    margin: 0 0 10px;
    padding: 7px 12px;
}

.mensagem-aviso {
    background: var(--shell-aviso-fundo);
    border: 1px solid var(--shell-aviso-borda);
    border-left: 4px solid var(--shell-aviso);
    border-radius: var(--controle-raio, 4px);
    color: var(--shell-aviso);
    margin: 0 0 10px;
    padding: 7px 12px;
}

/* Mensagens de operacao dispensaveis (#119): clicar na faixa (ou no X do canto)
   fecha. O crud.js remove a faixa no clique; aqui e so a affordance visual. */
.mensagem-sucesso, .mensagem-aviso, [role="alert"] {
    position: relative;
    padding-right: 28px;
    cursor: pointer;
}

.mensagem-sucesso::after, .mensagem-aviso::after, [role="alert"]::after {
    content: "\00D7";
    position: absolute;
    top: 50%;
    right: 10px;
    transform: translateY(-50%);
    font-size: 15px;
    line-height: 1;
    opacity: 0.6;
}

.mensagem-sucesso:hover::after, .mensagem-aviso:hover::after, [role="alert"]:hover::after {
    opacity: 1;
}

/* ---------- Grade: clique/setas selecionam; duplo clique ou Enter abrem ---------- */
.painel-corpo .linha-registro {
    cursor: pointer;
    user-select: none;
}

.painel-corpo .linha-registro:hover td { background: var(--shell-superficie-2); }

/* Foco por teclado na linha: anel interno (o outline externo some sob as
   linhas vizinhas da tabela). */
.painel-corpo .linha-registro:focus { outline: none; }

.painel-corpo .linha-registro:focus-visible {
    outline: 2px solid var(--shell-foco);
    outline-offset: -2px;
}

.painel-corpo .linha-registro.selecionada td {
    background: var(--shell-destaque);
    color: var(--shell-primaria-texto);
}

.painel-corpo .linha-registro.selecionada a { color: var(--shell-primaria-texto); }

/* Estado vazio da grade: discreto, sem moldura. */
.painel-corpo tbody td[colspan] {
    color: var(--shell-texto-fraco);
    padding: 14px 10px;
}

/* ---------- Aba de usuarios vinculados (administracao de plataforma, #103) ---------- */
.painel-corpo .aba-usuarios {
    margin-top: 16px;
    border-top: 1px solid var(--shell-borda);
    padding-top: 10px;
}

.painel-corpo .aba-titulo {
    margin: 0 0 8px;
    font-size: 13px;
    font-weight: 600;
}

.painel-corpo .aba-acao {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 10px;
}

/* ---------- Sub-grade: grade aninhada com mini-toolbar (Incluir/Alterar/Excluir) ----------
   Mesmo molde da grade principal, so que a acao (Alterar) abre a subtela e o
   Excluir faz exclusao logica (subgrade.js). Toolbar da aba mais leve que a
   principal (sem a divisoria de baixo). */
.painel-corpo .toolbar-aba {
    margin: 0 0 8px;
    padding-bottom: 0;
    border-bottom: 0;
}

/* O form do Excluir nao gera caixa: o botao entra direto na flex da toolbar. */
.subgrade-excluir {
    display: contents;
    margin: 0;
}

/* Linha de UMA linha so, como no grid do legado. Sem isto uma celula longa
   ("5152 - Transferencia de mercadoria") quebra em quatro linhas e a altura da
   linha quadruplica, desalinhando a leitura em faixas. A largura que sobra vira
   scroll horizontal no container, nao altura. */
.painel-corpo .subgrade-linha td,
.painel-corpo table:has(.subgrade-linha) thead th {
    white-space: nowrap;
}

/* Celula muito longa corta com reticencias em vez de esticar a coluna. */
.painel-corpo .subgrade-linha td {
    max-width: 22ch;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Selecao da linha (espelho de .linha-registro da grade principal). */
.painel-corpo .subgrade-linha {
    cursor: pointer;
    user-select: none;
}

.painel-corpo .subgrade-linha:hover td { background: var(--shell-superficie-2); }

.painel-corpo .subgrade-linha:focus { outline: none; }

.painel-corpo .subgrade-linha:focus-visible {
    outline: 2px solid var(--shell-foco);
    outline-offset: -2px;
}

.painel-corpo .subgrade-linha.selecionada td {
    background: var(--shell-destaque);
    color: var(--shell-primaria-texto);
}

/* ---------- Grade de permissoes (#109): coluna de selecao + indicador de liberado ---------- */
.painel-corpo .grade-permissoes .col-sel { width: 32px; text-align: center; }

/* Checkbox nao estica a celula (o input:100% do formulario nao vale na grade). */
.painel-corpo .grade-permissoes input[type="checkbox"] { width: auto; margin: 0; }

.painel-corpo .acesso-sim { color: var(--shell-sucesso); font-weight: 700; }
.painel-corpo .acesso-nao { color: var(--shell-texto-suave); }

/* ==========================================================================
   GEOMETRIA DO FORMULARIO LEGADO (.tela-legado / .capa-legado)
   ==========================================================================
   Reproducao da tela do udisoft-erp em pixel, e nao so em composicao: e o que
   a regra de fidelidade de docs/architecture/plano-classe-fiscal.md passou a
   exigir depois que "mesma composicao, outra escala" se mostrou insuficiente
   para quem opera as duas telas lado a lado.

   Os numeros NAO sao escolha de design: saem do @FormInfo (largura e altura da
   area util) e do @Bind (top/left/right/width de cada campo) das entidades
   legadas. Quem for conferir compara com a anotacao, nao com o gosto.

   O modelo do legado, medido:
     - area util de largura fixa, campos ancorados por pixel, margem de 4 a
       esquerda e 5 a direita;
     - espaco de 8px entre campos vizinhos da mesma linha;
     - passo de 46px por linha quando o rotulo fica EM CIMA (15 de rotulo + 3
       de respiro + 24 de controle + 4 de margem) e de 24px quando o rotulo
       fica A ESQUERDA, na mesma linha do controle.

   Largura fixa nao e descuido de responsividade: e o ponto. Quando a janela
   nao comporta, o container rola na horizontal em vez de reempacotar os campos
   — reempacotar mudaria a quantidade de campos por linha, que e justamente o
   que se esta copiando. */

.tela-legado {
    width: var(--tela-largura, 794px);
    box-sizing: border-box;
    padding: 4px 0 0;
}

/* A margem lateral do legado (4 a esquerda, 5 a direita) mora na LINHA, nao no
   container: assim o primeiro campo cai em x = 4 esteja a linha solta no
   cabecalho ou dentro do cartao de uma aba, sem depender do aninhamento. */
.painel-corpo .tela-legado .form-linha,
.painel-corpo .tela-legado > .form-cabecalho > .form-linha {
    padding: 0 5px 0 4px;
}

/* O pai rola; a tela nao encolhe. */
.tela-legado-area { overflow-x: auto; }

/* Linha do legado: campos lado a lado, larguras fixas, SEM quebra. */
.painel-corpo .tela-legado .form-linha {
    display: flex;
    flex-wrap: nowrap;
    align-items: flex-start;
    gap: 0 8px;
    margin: 0 0 4px;
    max-width: none;
}

/* Campo do legado: largura vem do style inline (o `width` do @Bind), nunca de
   classe de tamanho — duas telas com a mesma classe teriam larguras diferentes
   no legado. */
.painel-corpo .tela-legado .form-campo {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    flex: 0 0 auto;
    gap: 3px;
}

.painel-corpo .tela-legado .form-campo > label {
    width: auto;
    height: 15px;
    line-height: 15px;
    text-align: left;
    font-size: 11px;
    font-weight: 650;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
}

.painel-corpo .tela-legado .form-campo input,
.painel-corpo .tela-legado .form-campo select {
    width: 100%;
    flex: none;
    height: 24px;
    font-size: 12px;
    padding: 0 6px;
}

.painel-corpo .tela-legado .form-campo textarea {
    font-size: 12px;
}

/* A aba do legado e uma FAIXA sob a barra de abas, nao um cartao com respiro
   lateral: o padding de 16 do cartao deslocaria a grade inteira e nenhum campo
   cairia no seu `left`. Some o padding lateral, somem as bordas laterais e o
   arredondamento; fica o respiro vertical e as bordas de cima e de baixo. */
.painel-corpo .tela-legado .form-secao {
    padding-left: 0;
    padding-right: 0;
    border-left: 0;
    border-right: 0;
    border-radius: 0;
    max-width: none;
}

/* Altura da pagina de aba: a do legado (@FormInfo height 506, menos o cabecalho
   que termina em 144 e a barra de abas). Fixa porque no legado e fixa — trocar de
   aba nao muda o tamanho da janela, e sem isto o painel pula a cada clique. Quando
   a aba tem mais campos que a do legado, ela cresce; nenhuma encolhe. */
.painel-corpo .tela-legado .form-secao { min-height: 336px; }

/* O que nao e linha de campos tambem respeita a margem de 4 do legado. */
.painel-corpo .tela-legado .form-secao-titulo,
.painel-corpo .tela-legado .bloco-interruptor,
.painel-corpo .tela-legado .bloco-titulo,
.painel-corpo .tela-legado .ajuda-curta {
    padding-left: 4px;
    padding-right: 5px;
}

/* Faixa do interruptor de bloco dentro da tela legada: o legado nao a tem (la
   nao existe "bloco ausente"), entao ela ocupa uma faixa propria de 22px, sem
   consumir uma linha de campos. */
.painel-corpo .tela-legado .bloco-interruptor {
    height: 22px;
    margin: 0 0 4px;
    padding: 0;
    border-bottom: 0;
    font-size: 11px;
}

.painel-corpo .tela-legado .bloco-titulo {
    height: 18px;
    margin: 10px 0 2px;
    font-size: 11px;
}

.painel-corpo .tela-legado .ajuda-curta {
    margin: 0 0 4px;
    font-size: 11px;
}

/* ---------- Capa com rotulo A ESQUERDA (FormInfo 142 e irmaos) ----------
   Nas telas de cadastro simples o legado poe o rotulo na MESMA linha do campo
   (top == ltop), com largura propria de rotulo. A capa comum do Udisys e uma
   grade densa responsiva; aqui ela vira a faixa do legado.

   PASSO ENTRE LINHAS: o legado usa 24 cravados (top 0, 24, 48 no FormInfo 142),
   que e o proprio controle encostando no de baixo, sem respiro nenhum. Aqui o
   passo e `--capa-passo` MAIS os 24 do controle — divergencia consciente, pedida
   depois de ver a tela montada: a faixa do legado e densa demais para a fonte e a
   altura de controle desta stack.

   O espaco mora no `row-gap` do container, e nao numa margem por linha, porque a
   primeira linha (ID e Status) vem do fragment global e NAO esta dentro de uma
   `.form-linha` — com margem por linha ela ficaria colada na de baixo e o passo
   sairia diferente do resto. */
.form-capa.capa-legado {
    display: block;
    grid-template-columns: none;
    max-width: none;
    width: var(--tela-largura, 780px);
    box-sizing: border-box;
    padding: 4px 6px 8px 4px;
    gap: var(--capa-passo, 8px) 0;
}

.form-capa.capa-legado .form-linha {
    display: flex;
    flex-wrap: nowrap;
    align-items: center;
    justify-content: space-between;
    gap: 0;
    margin: 0;
    max-width: none;
}

.form-capa.capa-legado .form-campo {
    display: flex;
    flex-direction: row;
    align-items: center;
    flex: 0 0 auto;
    gap: 0;
}

/* Rotulo com largura propria (o `lwidth` do @Bind) e alinhamento proprio
   (`lalign`): no legado o rotulo da direita e alinhado a DIREITA, encostando no
   campo. As duas larguras vem do style inline de cada campo. */
.form-capa.capa-legado .form-campo > label {
    flex: 0 0 auto;
    font-size: 12px;
    font-weight: 600;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
}

.form-capa.capa-legado .form-campo input,
.form-capa.capa-legado .form-campo select {
    flex: 0 0 auto;
    height: 24px;
    font-size: 12px;
    padding: 0 6px;
}

/* ID e Status vem do fragment global, sem style inline: as larguras deles sao
   as do @Bind da entidade legada (rotulo 72 / campo 148 no ID; rotulo 48
   alinhado a direita / campo 148 no Status). */
.form-capa.capa-legado {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
    align-content: flex-start;
}

.form-capa.capa-legado > .form-linha { flex: 0 0 100%; }

.form-capa.capa-legado > .form-campo > label { width: 72px; }
.form-capa.capa-legado > .form-campo > input,
.form-capa.capa-legado > .form-campo > select { width: 148px; }

/* 56 = os 48 de `lwidth` do @Bind mais os 8 que separam rotulo e campo. Com
   box-sizing: border-box o texto ocupa os 48 e a caixa comeca no x do legado. */
.form-capa.capa-legado > .form-campo:nth-child(2) > label {
    width: 56px;
    text-align: right;
    padding-right: 8px;
}

/* Larguras de area util, uma por @FormInfo — o numero e o `width` da anotacao.
   Novas telas legadas acrescentam a sua aqui em vez de espalhar pixel em style. */
.tela-780 { --tela-largura: 780px; }   /* FormInfo 142, Classe Fiscal */
.tela-794 { --tela-largura: 794px; }   /* FormInfo 151, Tributacao   */

/* As abas da tela de capa legada acompanham a largura da capa: no legado a janela
   tem UMA largura (o @FormInfo), e capa e abas vivem dentro dela. */
.form-capa.tela-780 ~ .form-secao { max-width: 780px; }
.form-capa.tela-794 ~ .form-secao { max-width: 794px; }
