/* ════════════════════════════════════════════════════════════════════
   InfraMINA · Contratos e Remotas

   Dois módulos num arquivo só, pelo mesmo motivo que juntou os dois de
   correias: eles falam a mesma língua visual. Nenhum dos dois inventa
   linguagem — o que está abaixo é o mundo "Permissão de Trabalho" de
   DESIGN.md aplicado a duas telas que ainda não existiam. Régua no lugar de
   caixa, rótulo em condensada versal, valor em monoespaçada tabular, raio
   zero.

   Carregado DEPOIS de styles.css, de interface-polish.css e de correias.css.
   Isso importa: as regras daqui estão escopadas em `.app` (0,2,0) para ter o
   mesmo peso das regras de console que vêm de styles.css, e a ordem desempata.

   SUPERFÍCIE. Os dois são edição em tela, e a consolidação de 2026-08-31 é
   explícita: edição em tela usa console; impressão, PDF e registro fechado
   usam papel. A tela inteira é `--console-*` e a virada para papel acontece
   no `@media print` no fim do arquivo, nunca no meio das regras de tela.

   COR. Continuam existindo dois motivos para uma cor aparecer: classe de
   risco da operação e o ato de autorizar. Aqui a conta é:

     · contrato VENCIDO é classe de risco, e a cor é obrigatória. Numa mina,
       contrato vencido não significa serviço parado — significa serviço
       continuando sem cobertura contratual, e é o pior dos casos desta tela;
     · contrato A VENCER é atenção: a renovação de um contrato de serviço
       passa por cotação, jurídico e assinatura das duas partes, e leva meses;
     · INTERTRAVAMENTO de segurança faltando é classe de risco pela razão mais
       direta que existe nesta folha: é a chave de emergência de uma correia;
     · SEM VIGÊNCIA INFORMADA não é risco, é cadastro incompleto. Recebe a
       mesma matéria da linha divergente da malha — hachura e régua pesada —,
       nunca tinta. Cadastro incompleto não é acidente, e pintá-lo de vermelho
       gastaria a cor que o contrato vencido precisa;
     · ocupação de cartão, linha selecionada, aba ativa, coluna do valor
       vigente e contrato encerrado se distinguem por peso de régua, por
       matéria e por posição. Sem tinta.

   CONVENÇÃO DE MARCAÇÃO que a integração precisa seguir:
     · numa célula de rótulo/valor (`.contratos-resumo-item`,
       `.remotas-resumo-item`), o PRIMEIRO elemento é o rótulo e o seguinte é
       o valor. A folha veste por posição, não por classe extra;
     · toda tabela larga (`.contratos-tabela`, `.remota-pontos`) vai dentro de
       um `.table-wrap`, que é quem rola de lado. A página nunca rola;
     · a situação do contrato e a conferência do intertravamento vão também
       ESCRITAS dentro do próprio elemento. Impressora de mina é preto e
       branco e daltonismo não pode esconder a mensagem;
     · o medidor de ocupação do cartão nunca aparece sozinho: os números
       ("40 de 56 pontos") vêm ao lado, porque barra sem número é estimativa.
   ════════════════════════════════════════════════════════════════════ */

@media screen, print {
  /* ────────────────────────────────────────────────────────────────
     1. CONTRATOS
     ──────────────────────────────────────────────────────────────── */

  .app .contratos-module {
    display: grid;
    gap: var(--sp-4);
    /* Item de grade nasce com `min-width: auto` e não encolhe abaixo do
       próprio conteúdo: sem isto a tabela larga empurra o módulo para fora da
       tela, e como o `body` esconde o transbordo o resultado não é barra de
       rolagem — é conteúdo cortado, que ninguém percebe. */
    min-width: 0;
    max-width: 100%;
  }

  /* ── A faixa de totais ──
     O vão de 1px entre as células é a régua: o fundo da faixa é a linha e cada
     célula tapa o próprio pedaço. É o mesmo arranjo da faixa de correias, e é
     o que dá seis células separadas com uma borda só. */
  .app .contratos-resumo,
  .app .remotas-resumo {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(160px, 100%), 1fr));
    gap: var(--rule-hair);
    border: var(--rule-hair) solid var(--console-line);
    background: var(--console-line);
  }
  .app .contratos-resumo-item,
  .app .remotas-resumo-item {
    min-width: 0;
    padding: var(--sp-3) var(--sp-4);
    background: var(--console-panel);
  }
  .app .contratos-resumo-item > span,
  .app .remotas-resumo-item > span {
    display: block;
    color: var(--console-muted);
    font-family: var(--font-label);
    font-stretch: var(--stretch-label);
    font-size: var(--t-label);
    font-weight: 700;
    letter-spacing: var(--track-label);
    text-transform: uppercase;
  }
  .app .contratos-resumo-item > strong,
  .app .remotas-resumo-item > strong {
    display: block;
    margin-top: var(--sp-1);
    color: var(--console-text);
    font-family: var(--font-value);
    font-size: var(--t-value);
    font-variant-numeric: tabular-nums;
    line-height: var(--lh-value);
  }
  /* Cadastro sem vigência: pendência, e não risco. Hachura e régua, como a
     linha divergente da malha. A régua é `box-shadow` interno porque a faixa
     se separa por vão de 1px, e uma borda aqui roubaria esse vão. */
  .app .contratos-resumo-item.atencao {
    background-image: var(--hatch);
    box-shadow: inset 0 calc(-1 * var(--rule-body)) 0 var(--console-line-strong);
  }
  /* Contrato vencido é a única célula da faixa que ganha tinta. */
  .app .contratos-resumo-item.grave {
    box-shadow: inset 0 calc(-1 * var(--rule-body)) 0 var(--danger);
  }
  .app .contratos-resumo-item.grave > strong {
    color: var(--danger);
  }

  /* ── A faixa de alerta ──
     Ela diz QUAL contrato, e não quantos: a contagem já está na faixa de
     totais, e quem lê precisa do número do contrato para ir atrás dele hoje.
     Cada item é uma régua na lateral — a única vertical da tela, para que o
     olho encontre o bloco sem precisar de fundo colorido atrás do texto. */
  .app .contratos-alerta {
    display: grid;
    gap: var(--sp-3);
    padding: var(--sp-4);
    border: var(--rule-hair) solid var(--console-line);
    background: var(--console-panel);
  }
  .app .contratos-alerta h2 {
    margin: 0;
    color: var(--console-text);
    font-family: var(--font-label);
    font-stretch: var(--stretch-label);
    font-size: var(--t-label);
    font-weight: 700;
    letter-spacing: var(--track-label);
    text-transform: uppercase;
  }
  .app .contratos-alerta ul {
    display: grid;
    gap: var(--rule-hair);
    margin: 0;
    padding: 0;
    list-style: none;
  }
  .app .contratos-alerta li {
    display: flex;
    flex-wrap: wrap;
    gap: var(--sp-2) var(--sp-4);
    align-items: baseline;
    padding: var(--sp-3);
    border-inline-start: var(--rule-heavy) solid var(--console-line-strong);
    background: var(--console-panel-2);
  }
  .app .contratos-alerta li.vencido {
    border-inline-start-color: var(--danger);
  }
  .app .contratos-alerta li.a-vencer {
    border-inline-start-color: var(--warning);
  }
  .app .contratos-alerta li > span {
    flex: 1 1 12ch;
    color: var(--console-muted);
    font-size: var(--t-sm);
  }
  .app .contratos-alerta li > strong {
    color: var(--console-text);
    font-family: var(--font-value);
    font-size: var(--t-sm);
    font-variant-numeric: tabular-nums;
  }
  .app .contratos-alerta > p {
    margin: 0;
    color: var(--console-muted);
    font-size: var(--t-sm);
    line-height: var(--lh-body);
    max-width: var(--measure);
  }

  /* O número do contrato dentro da faixa é um botão: abre a ficha. Ele mantém
     a monoespaçada do registro porque é o registro que se está apontando. */
  .app .contrato-atalho {
    min-height: 32px;
    padding: 0;
    border: 0;
    background: transparent;
    color: var(--console-text);
    font-family: var(--font-value);
    font-size: var(--t-value);
    font-variant-numeric: tabular-nums;
    text-decoration: underline;
    text-underline-offset: 3px;
    cursor: pointer;
  }
  .app .contrato-atalho:hover {
    color: var(--console-line-strong);
  }

  /* ── Busca, filtro e o botão de cadastrar ── */
  .app .contratos-barra {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(220px, 100%), 1fr));
    gap: var(--sp-3);
    align-items: end;
  }
  .app .contratos-barra > .btn {
    /* O botão acompanha a linha de base dos campos, e não a altura deles. */
    align-self: end;
    min-height: 44px;
  }

  /* ── Formulário de cadastro ──
     O mesmo formulário serve ao contrato e ao termo aditivo, porque o que se
     cadastra é a mesma coisa com um campo a mais. Duas colunas no desktop; o
     que precisa de linha inteira pede `.contratos-campo-largo`. */
  .app .contratos-form {
    display: grid;
    gap: var(--sp-4);
    padding: var(--sp-4);
    border: var(--rule-hair) solid var(--console-line);
    border-top: var(--rule-heavy) solid var(--console-line-strong);
    background: var(--console-panel);
    min-width: 0;
  }
  .app .contratos-form > header {
    display: grid;
    gap: var(--sp-1);
  }
  .app .contratos-form h2 {
    margin: 0;
    color: var(--console-text);
    font-family: var(--font-label);
    font-stretch: var(--stretch-label);
    font-size: var(--t-section);
    font-weight: 700;
    letter-spacing: var(--track-label);
    text-transform: uppercase;
  }
  .app .contratos-form > header p {
    margin: 0;
    max-width: var(--measure);
    color: var(--console-muted);
    font-size: var(--t-sm);
    line-height: var(--lh-body);
  }
  .app .contratos-form-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(240px, 100%), 1fr));
    gap: var(--sp-3) var(--sp-4);
    align-items: start;
    min-width: 0;
  }
  .app .contratos-campo-largo {
    grid-column: 1 / -1;
  }
  .app .contratos-form small {
    display: block;
    margin-top: var(--sp-1);
    color: var(--console-muted);
    font-size: var(--t-micro);
    line-height: var(--lh-body);
  }

  /* ── Os erros do cadastro ──
     Vêm todos de uma vez, e por isso são uma lista e não um aviso solto: quem
     preencheu dezesseis campos corrige tudo numa passada. Aqui a régua é
     vermelha porque o cadastro recusado É bloqueio: sem ele, o contrato não
     entra no sistema. */
  .app .contratos-form-erros {
    display: grid;
    gap: var(--sp-2);
    margin: 0;
    padding: var(--sp-3) var(--sp-4);
    border-inline-start: var(--rule-heavy) solid var(--danger);
    background: var(--console-panel-2);
    list-style: none;
  }
  .app .contratos-form-erros li {
    color: var(--console-text);
    font-size: var(--t-sm);
    line-height: var(--lh-body);
  }
  .app .contratos-form-acoes {
    display: flex;
    flex-wrap: wrap;
    gap: var(--sp-3);
    align-items: center;
  }
  .app .contratos-form-acoes > span {
    flex: 1 1 24ch;
    color: var(--console-muted);
    font-size: var(--t-micro);
    line-height: var(--lh-body);
  }

  /* ── A tabela da carteira ──
     Mesmo arranjo da tabela da malha: cabeçalho preso ao topo com régua
     desenhada por dentro (`border` em célula presa escorrega com a rolagem,
     `box-shadow` interno não) e `td` em monoespaçada tabular, porque `td` é
     registro de valor por definição neste sistema. */
  .app .contratos-tabela {
    width: 100%;
    border-collapse: collapse;
  }
  .app .contratos-tabela th {
    position: sticky;
    top: 0;
    z-index: 2;
    padding: var(--sp-2) var(--sp-3);
    background: var(--console-panel-2);
    box-shadow: inset 0 calc(-1 * var(--rule-body)) 0 var(--console-line-strong);
    color: var(--console-muted);
    font-family: var(--font-label);
    font-stretch: var(--stretch-label);
    font-size: var(--t-label);
    font-weight: 700;
    letter-spacing: var(--track-label);
    text-align: left;
    text-transform: uppercase;
    white-space: nowrap;
  }
  .app .contratos-tabela td {
    padding: var(--sp-2) var(--sp-3);
    border-bottom: var(--rule-hair) solid var(--console-line);
    color: var(--console-text);
    font-family: var(--font-value);
    font-size: var(--t-sm);
    font-variant-numeric: tabular-nums;
    vertical-align: top;
  }
  /* O número antigo entra sob o número de hoje, menor: é a mesma identidade,
     não outra coluna. */
  .app .contratos-tabela td small {
    display: block;
    margin-top: 2px;
    color: var(--console-muted);
    font-family: var(--font-label);
    font-size: var(--t-micro);
  }
  /* Dinheiro alinhado à direita é o que deixa 143.530.932,83 e 1.000.000,00
     comparáveis num relance. */
  .app .contrato-valor {
    text-align: right;
    white-space: nowrap;
  }

  /* ── A linha é um controle ──
     Clicar na linha abre a ficha do contrato. Isso precisa estar dito antes do
     clique: sem o cursor e sem a régua da linha selecionada, a tabela parece
     só uma tabela e a ficha abaixo dela parece ter aparecido sozinha. */
  .app .contrato-linha {
    cursor: pointer;
    transition: background-color var(--dur) var(--ease);
  }
  .app .contrato-linha:hover > td {
    background: var(--console-panel-2);
  }
  .app .contrato-linha.selecionada > td {
    background: var(--console-panel-2);
    border-bottom-color: var(--console-line-strong);
    box-shadow: inset var(--rule-heavy) 0 0 var(--console-line-strong);
  }
  /* Contrato vencido: a régua da lateral é a tinta que ele tem direito de
     usar, e a palavra "Vencido" continua escrita na coluna de situação. */
  .app .contrato-linha.vencido > td:first-child {
    box-shadow: inset var(--rule-heavy) 0 0 var(--danger);
  }
  /* Cadastro sem vigência informada: matéria, não tinta. */
  .app .contrato-linha.semVigencia > td {
    background-image: var(--hatch);
  }
  .app .contrato-linha.encerrado > td {
    color: var(--console-muted);
  }

  /* ── A situação, escrita ──
     O rótulo é o registro. A cor entra sobre ele apenas nos dois casos de
     risco; nos outros três é régua e letra. */
  .app .contrato-situacao {
    display: inline-block;
    padding: 2px var(--sp-2);
    border: var(--rule-hair) solid var(--console-line);
    color: var(--console-text);
    font-family: var(--font-label);
    font-stretch: var(--stretch-label);
    font-size: var(--t-micro);
    font-weight: 700;
    letter-spacing: var(--track-label);
    text-transform: uppercase;
    white-space: nowrap;
  }
  .app .contrato-situacao.vencido {
    border-color: var(--danger);
    background: var(--danger);
    color: var(--on-danger);
  }
  .app .contrato-situacao.aVencer {
    border-color: var(--warning);
    background: var(--warning);
    color: var(--on-warning);
  }
  .app .contrato-situacao.semVigencia {
    background-image: var(--hatch);
    border-color: var(--console-line-strong);
  }
  .app .contrato-situacao.encerrado {
    border-style: dashed;
    color: var(--console-muted);
  }

  /* ── A ficha do contrato ──
     É a resposta que a pasta de arquivos em PDF nunca deu, e por isso ela
     mostra SEMPRE os dois lados: o que está valendo e o que o papel original
     dizia. A distinção entre as duas colunas é peso de régua, não tinta — a
     coluna que manda tem a régua pesada no topo. */
  .app .contrato-ficha {
    display: grid;
    gap: var(--sp-4);
    padding: var(--sp-4);
    border: var(--rule-hair) solid var(--console-line);
    border-top: var(--rule-heavy) solid var(--console-line-strong);
    background: var(--console-panel);
    min-width: 0;
  }
  .app .contrato-ficha-head {
    display: flex;
    flex-wrap: wrap;
    gap: var(--sp-3) var(--sp-4);
    align-items: start;
    justify-content: space-between;
    padding-bottom: var(--sp-3);
    border-bottom: var(--rule-hair) solid var(--console-line);
  }
  .app .contrato-ficha-head h2 {
    margin: 0;
    color: var(--console-text);
    font-family: var(--font-label);
    font-stretch: var(--stretch-label);
    font-size: var(--t-section);
    font-weight: 700;
    letter-spacing: var(--track-label);
    text-transform: uppercase;
  }
  .app .contrato-ficha-head p {
    margin: var(--sp-1) 0 0;
    color: var(--console-muted);
    font-size: var(--t-sm);
    line-height: var(--lh-body);
  }
  .app .contrato-antigos {
    max-width: var(--measure);
  }
  .app .contrato-objeto {
    margin: 0;
    max-width: var(--measure);
    color: var(--console-text);
    font-size: var(--t-sm);
    line-height: var(--lh-body);
  }

  .app .contrato-comparacao {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(260px, 100%), 1fr));
    gap: var(--rule-hair);
    border: var(--rule-hair) solid var(--console-line);
    background: var(--console-line);
  }
  .app .contrato-coluna {
    min-width: 0;
    padding: var(--sp-3) var(--sp-4);
    background: var(--console-panel-2);
  }
  /* A coluna do que está valendo é a que manda: régua pesada no topo. */
  .app .contrato-coluna.vigente {
    box-shadow: inset 0 var(--rule-heavy) 0 var(--console-line-strong);
  }
  /* A do papel original continua verdade, mas não é o que está valendo: letra
     apagada e hachura, a mesma matéria do registro que não decide. */
  .app .contrato-coluna.original {
    background-image: var(--hatch);
  }
  .app .contrato-coluna h3 {
    margin: 0 0 var(--sp-3);
    color: var(--console-muted);
    font-family: var(--font-label);
    font-stretch: var(--stretch-label);
    font-size: var(--t-label);
    font-weight: 700;
    letter-spacing: var(--track-label);
    text-transform: uppercase;
  }
  /* Rótulo e valor em régua: o rótulo à esquerda, o valor à direita, uma linha
     de fio entre cada par. É a linha da ficha de dimensionamento, e é assim
     que se confere um documento que alguém assina. */
  .app .contrato-coluna dl {
    display: grid;
    grid-template-columns: minmax(0, auto) minmax(0, 1fr);
    gap: 0;
    margin: 0;
  }
  .app .contrato-coluna dt,
  .app .contrato-coluna dd {
    padding: var(--sp-2) 0;
    border-top: var(--rule-hair) solid var(--console-line);
    margin: 0;
  }
  .app .contrato-coluna dt {
    color: var(--console-muted);
    font-family: var(--font-label);
    font-stretch: var(--stretch-label);
    font-size: var(--t-label);
    font-weight: 700;
    letter-spacing: var(--track-label);
    text-transform: uppercase;
  }
  .app .contrato-coluna dd {
    color: var(--console-text);
    font-family: var(--font-value);
    font-size: var(--t-value);
    font-variant-numeric: tabular-nums;
    text-align: right;
  }
  .app .contrato-conta {
    margin: 0;
    max-width: var(--measure);
    color: var(--console-muted);
    font-size: var(--t-sm);
    line-height: var(--lh-body);
  }

  /* ── A linha do tempo dos termos aditivos ──
     Sete arquivos em PDF, na ordem em que foram assinados, e o último com a
     régua pesada: é ele que está mandando. A numeração vem do HTML (`<ol>`),
     porque o número do termo é o número do documento, não uma contagem. */
  .app .contrato-aditivos {
    display: grid;
    gap: var(--rule-hair);
    margin: 0;
    padding: 0;
    list-style: none;
    border: var(--rule-hair) solid var(--console-line);
    background: var(--console-line);
  }
  .app .contrato-aditivos li {
    display: grid;
    gap: var(--sp-1);
    padding: var(--sp-3);
    background: var(--console-panel-2);
    border-inline-start: var(--rule-heavy) solid transparent;
  }
  .app .contrato-aditivos li.vigente {
    border-inline-start-color: var(--console-line-strong);
  }
  .app .contrato-aditivos header {
    display: flex;
    flex-wrap: wrap;
    gap: var(--sp-2) var(--sp-4);
    align-items: baseline;
    justify-content: space-between;
  }
  .app .contrato-aditivos strong {
    color: var(--console-text);
    font-family: var(--font-label);
    font-stretch: var(--stretch-label);
    font-size: var(--t-label);
    font-weight: 700;
    letter-spacing: var(--track-label);
    text-transform: uppercase;
  }
  .app .contrato-aditivos header span {
    color: var(--console-muted);
    font-family: var(--font-value);
    font-size: var(--t-micro);
    font-variant-numeric: tabular-nums;
  }
  .app .contrato-aditivos p {
    margin: 0;
    max-width: var(--measure);
    color: var(--console-text);
    font-family: var(--font-value);
    font-size: var(--t-sm);
    font-variant-numeric: tabular-nums;
    line-height: var(--lh-body);
  }
  .app .contrato-aditivo-objeto {
    font-family: var(--font-text);
    color: var(--console-muted);
  }
  .app .contrato-sem-aditivo,
  .app .contrato-observacao {
    margin: 0;
    max-width: var(--measure);
    color: var(--console-muted);
    font-size: var(--t-sm);
    line-height: var(--lh-body);
  }

  /* ── O anexo ──
     O contrato assinado é o documento; o cadastro é o índice dele. O link
     aparece com o nome do arquivo porque é isso que alguém confere antes de
     abrir vinte e cinco megabytes na rede do subsolo. */
  .app .contrato-anexo {
    display: flex;
    flex-wrap: wrap;
    gap: var(--sp-2) var(--sp-3);
    align-items: baseline;
    margin: 0;
    padding: var(--sp-3);
    border: var(--rule-hair) solid var(--console-line);
    background: var(--console-panel-2);
    font-size: var(--t-sm);
  }
  .app .contrato-anexo.vazio {
    background-image: var(--hatch);
    color: var(--console-muted);
  }
  .app .contrato-anexo a {
    color: var(--console-text);
    font-family: var(--font-value);
    text-underline-offset: 3px;
  }
  .app .contrato-anexo span {
    color: var(--console-muted);
    font-family: var(--font-value);
    font-size: var(--t-micro);
    font-variant-numeric: tabular-nums;
  }
  .app .contrato-acoes {
    display: flex;
    flex-wrap: wrap;
    gap: var(--sp-3);
    padding-top: var(--sp-3);
    border-top: var(--rule-hair) solid var(--console-line);
  }

  /* ── Leitura do documento (07/10/2026) ── */
  .app .contratos-form-ler {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--sp-2) var(--sp-3);
    margin-top: var(--sp-2);
  }
  .app .contratos-form-ler small,
  .app .contrato-leitura-nota {
    color: var(--console-muted);
    font-size: var(--t-sm);
    line-height: var(--lh-body);
  }
  .app .contrato-lido {
    margin-left: var(--sp-1);
    padding: 0 var(--sp-1);
    border-radius: var(--radius);
    background: var(--stamp-tint-2);
    color: var(--console-text);
    font-size: var(--t-micro);
    font-weight: 600;
    letter-spacing: 0;
    text-transform: none;
    white-space: nowrap;
  }
  .app .contrato-leitura,
  .app .contrato-leitura-status {
    display: grid;
    gap: var(--sp-2);
    margin: 0;
    padding: var(--sp-3) var(--sp-4);
    border-top: var(--rule-heavy) solid var(--stamp-void);
    background: var(--console-panel-2);
    color: var(--console-text);
    line-height: var(--lh-body);
  }
  .app .contrato-leitura p,
  .app .contrato-leitura h3 {
    margin: 0;
  }
  .app .contrato-leitura-antes-depois ul,
  .app .contrato-leitura-avisos ul,
  .app .contrato-clausulas ul {
    margin: var(--sp-1) 0 0;
    padding-left: var(--sp-5);
  }
  .app .contrato-leitura-aviso {
    color: var(--risk-attention-edge);
  }
  .app .contrato-leitura-opcao {
    display: inline-flex;
    align-items: center;
    gap: var(--sp-2);
    min-height: 44px;
  }
  .app .contrato-leitura-opcao input {
    width: 20px;
    height: 20px;
  }
  .app .contrato-anexos {
    display: grid;
    gap: var(--sp-2);
    padding: var(--sp-3);
    border: var(--rule-hair) solid var(--console-line);
  }
  .app .contrato-anexos h3 {
    margin: 0;
    font-size: var(--t-body);
  }
  .app .contrato-anexos ul {
    margin: 0;
    padding-left: var(--sp-5);
  }
  .app .contrato-anexos li span {
    margin-left: var(--sp-2);
    color: var(--console-muted);
    font-family: var(--font-value);
    font-size: var(--t-micro);
  }
  .app .contrato-anexos-acoes {
    display: flex;
    flex-wrap: wrap;
    gap: var(--sp-2);
  }
  .app .contrato-clausulas > summary {
    min-height: 44px;
    cursor: pointer;
    font-weight: 700;
  }
  .app .contrato-clausula-tema {
    margin: var(--sp-3) 0 0;
  }
  .app .contratos-achados ul {
    display: grid;
    gap: var(--sp-2);
    margin: 0;
    padding: 0;
    list-style: none;
  }
  .app .contratos-achados p {
    margin: var(--sp-1) 0 0;
    color: var(--console-muted);
    font-size: var(--t-sm);
  }

  /* ── Por contratada ──
     Uma linha por empresa, da que mais pesa para a que menos pesa. */
  .app .contratos-empresas {
    display: grid;
    gap: var(--sp-3);
    min-width: 0;
  }
  .app .contratos-empresas h2 {
    margin: 0;
    color: var(--console-text);
    font-family: var(--font-label);
    font-stretch: var(--stretch-label);
    font-size: var(--t-label);
    font-weight: 700;
    letter-spacing: var(--track-label);
    text-transform: uppercase;
  }

  /* ────────────────────────────────────────────────────────────────
     2. REMOTAS
     ──────────────────────────────────────────────────────────────── */

  .app .remotas-module {
    display: grid;
    gap: var(--sp-4);
    min-width: 0;
    max-width: 100%;
  }

  /* ── Busca de ponto ──
     Na planilha era preciso abrir aba por aba para achar um endereço. A frase
     ao lado do campo não é enfeite: ela diz o que a busca alcança, que é a
     diferença entre procurar e adivinhar. */
  .app .remotas-busca {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(260px, 100%), 1fr));
    gap: var(--sp-3) var(--sp-4);
    align-items: end;
  }
  .app .remotas-busca-resultado {
    margin: 0;
    max-width: var(--measure);
    color: var(--console-muted);
    font-size: var(--t-sm);
    line-height: var(--lh-body);
  }

  /* As abas das remotas reaproveitam `.rotas-aba` de correias.css: é a mesma
     aba, e duplicar a regra aqui faria as duas divergirem na primeira
     correção. Só o contêiner é desta folha. */
  .app .remota-lista-abas {
    display: flex;
    flex-wrap: nowrap;
    gap: var(--sp-1);
    overflow-x: auto;
    border-bottom: var(--rule-hair) solid var(--console-line);
  }

  .app .remota-cabecalho {
    display: flex;
    flex-wrap: wrap;
    gap: var(--sp-3) var(--sp-4);
    align-items: baseline;
    justify-content: space-between;
    padding-bottom: var(--sp-3);
    border-bottom: var(--rule-body) solid var(--console-line-strong);
  }
  .app .remota-cabecalho h2 {
    margin: 0;
    color: var(--console-text);
    font-family: var(--font-label);
    font-stretch: var(--stretch-label);
    font-size: var(--t-section);
    font-weight: 700;
    letter-spacing: var(--track-label);
    text-transform: uppercase;
  }
  .app .remota-cabecalho p {
    margin: var(--sp-1) 0 0;
    color: var(--console-muted);
    font-size: var(--t-sm);
  }
  .app .remota-cabecalho-meta {
    display: flex;
    gap: var(--sp-4);
    color: var(--console-muted);
    font-family: var(--font-value);
    font-size: var(--t-micro);
    font-variant-numeric: tabular-nums;
  }

  /* ── O cartão ──
     Cada cartão ocupa um slot e tem um número fixo de pontos. Quantos sobram é
     a pergunta que decide se um prolongamento cabe sem hardware novo no
     escopo, e por isso o número vem antes da barra na leitura. */
  .app .remota-cartao {
    display: grid;
    gap: var(--sp-3);
    padding: var(--sp-4);
    border: var(--rule-hair) solid var(--console-line);
    border-top: var(--rule-heavy) solid var(--console-line-strong);
    background: var(--console-panel);
    min-width: 0;
  }
  .app .remota-cartao-head {
    display: flex;
    flex-wrap: wrap;
    gap: var(--sp-3) var(--sp-4);
    align-items: start;
    justify-content: space-between;
  }
  .app .remota-cartao-head h3 {
    margin: 0;
    color: var(--console-text);
    font-family: var(--font-value);
    font-size: var(--t-value);
    font-variant-numeric: tabular-nums;
  }
  .app .remota-cartao-head p {
    margin: var(--sp-1) 0 0;
    color: var(--console-muted);
    font-size: var(--t-sm);
  }
  .app .remota-ocupacao-numeros {
    display: grid;
    gap: 2px;
    text-align: right;
  }
  .app .remota-ocupacao-numeros span {
    color: var(--console-muted);
    font-family: var(--font-label);
    font-stretch: var(--stretch-label);
    font-size: var(--t-label);
    letter-spacing: var(--track-label);
    text-transform: uppercase;
  }
  .app .remota-ocupacao-numeros strong {
    color: var(--console-text);
    font-family: var(--font-value);
    font-size: var(--t-value);
    font-variant-numeric: tabular-nums;
  }
  /* O medidor é matéria, não tinta: cartão cheio não é acidente nem bloqueio,
     é um fato de projeto. Os números ao lado é que são o registro — a barra
     sozinha seria estimativa. */
  .app .remota-ocupacao {
    height: var(--rule-band);
    border: var(--rule-hair) solid var(--console-line);
    background-image: var(--hatch);
  }
  .app .remota-ocupacao > i {
    display: block;
    height: 100%;
    background: var(--console-line-strong);
  }

  /* ── A tabela de pontos ── */
  .app .remota-pontos {
    width: 100%;
    border-collapse: collapse;
  }
  .app .remota-pontos th {
    position: sticky;
    top: 0;
    z-index: 2;
    padding: var(--sp-2) var(--sp-3);
    background: var(--console-panel-2);
    box-shadow: inset 0 calc(-1 * var(--rule-body)) 0 var(--console-line-strong);
    color: var(--console-muted);
    font-family: var(--font-label);
    font-stretch: var(--stretch-label);
    font-size: var(--t-label);
    font-weight: 700;
    letter-spacing: var(--track-label);
    text-align: left;
    text-transform: uppercase;
    white-space: nowrap;
  }
  .app .remota-pontos td {
    padding: var(--sp-1) var(--sp-3);
    border-bottom: var(--rule-hair) solid var(--console-line);
    color: var(--console-text);
    font-family: var(--font-value);
    font-size: var(--t-micro);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
  }
  /* O endereço do controlador e a variável são o que se procura; ficam com o
     peso que o resto da linha não tem. */
  .app .remota-endereco,
  .app .remota-variavel {
    font-weight: 700;
  }
  /* Ponto livre é oportunidade, não pendência: hachura e letra apagada dizem
     "aqui cabe algo" sem chamar atenção de alarme. */
  .app .remota-ponto.livre > td {
    background-image: var(--hatch);
    color: var(--console-muted);
  }

  /* ── Equipamentos atendidos e o intertravamento ──
     A relação de entradas e saídas é o que o sistema tem; não necessariamente
     o que está na régua de bornes. Por isso a conferência diz "não
     encontrado", e não "não existe". */
  .app .remota-equipamentos {
    display: grid;
    gap: var(--sp-3);
    min-width: 0;
  }
  .app .remota-equipamentos h2 {
    margin: 0;
    color: var(--console-text);
    font-family: var(--font-label);
    font-stretch: var(--stretch-label);
    font-size: var(--t-label);
    font-weight: 700;
    letter-spacing: var(--track-label);
    text-transform: uppercase;
  }
  .app .remota-equipamento-lista {
    display: flex;
    flex-wrap: wrap;
    gap: var(--rule-hair);
    border: var(--rule-hair) solid var(--console-line);
    background: var(--console-line);
  }
  .app .remota-equipamento {
    display: grid;
    gap: 2px;
    flex: 1 1 14ch;
    min-height: 44px;
    padding: var(--sp-2) var(--sp-3);
    border: 0;
    background: var(--console-panel);
    color: var(--console-text);
    text-align: left;
    cursor: pointer;
    transition: background-color var(--dur) var(--ease);
  }
  .app .remota-equipamento strong {
    font-family: var(--font-value);
    font-size: var(--t-sm);
    font-variant-numeric: tabular-nums;
  }
  .app .remota-equipamento small {
    color: var(--console-muted);
    font-size: var(--t-micro);
  }
  .app .remota-equipamento:hover {
    background: var(--console-panel-2);
  }
  /* O equipamento aberto se distingue por régua, nunca por tinta: a aba ativa
     em laranja é um dos erros catalogados em DESIGN.md. */
  .app .remota-equipamento.active {
    background: var(--console-panel-2);
    box-shadow: inset 0 calc(-1 * var(--rule-heavy)) 0 var(--console-line-strong);
  }
  /* Falta ligação de item crítico de segurança. Aqui a tinta é obrigatória: é
     chave de emergência de correia, e a régua vermelha aparece antes de
     alguém abrir a conferência. */
  .app .remota-equipamento.incompleto {
    box-shadow: inset var(--rule-heavy) 0 0 var(--danger);
  }

  .app .intertravamento {
    display: grid;
    gap: var(--sp-3);
    padding: var(--sp-4);
    border: var(--rule-hair) solid var(--console-line);
    border-top: var(--rule-heavy) solid var(--console-line-strong);
    background: var(--console-panel);
  }
  .app .intertravamento h3 {
    margin: 0;
    color: var(--console-text);
    font-family: var(--font-value);
    font-size: var(--t-value);
    font-variant-numeric: tabular-nums;
  }
  .app .intertravamento header p {
    margin: var(--sp-1) 0 0;
    color: var(--console-muted);
    font-size: var(--t-sm);
  }
  .app .intertravamento-lista {
    display: grid;
    gap: var(--rule-hair);
    margin: 0;
    padding: 0;
    list-style: none;
    border: var(--rule-hair) solid var(--console-line);
    background: var(--console-line);
  }
  .app .intertravamento-item {
    display: flex;
    flex-wrap: wrap;
    gap: var(--sp-2) var(--sp-4);
    align-items: baseline;
    justify-content: space-between;
    padding: var(--sp-2) var(--sp-3);
    background: var(--console-panel-2);
    border-inline-start: var(--rule-heavy) solid transparent;
    font-size: var(--t-sm);
  }
  .app .intertravamento-item small {
    margin-inline-start: var(--sp-2);
    color: var(--console-muted);
    font-family: var(--font-label);
    font-stretch: var(--stretch-label);
    font-size: var(--t-micro);
    letter-spacing: var(--track-label);
    text-transform: uppercase;
  }
  .app .intertravamento-item strong {
    font-family: var(--font-value);
    font-size: var(--t-sm);
    font-variant-numeric: tabular-nums;
  }
  .app .intertravamento-item.atendido {
    border-inline-start-color: var(--success);
  }
  .app .intertravamento-item.faltando {
    border-inline-start-color: var(--danger);
  }
  .app .intertravamento-item.faltando strong {
    color: var(--danger);
  }
  .app .intertravamento-alerta {
    margin: 0;
    max-width: var(--measure);
    padding: var(--sp-3);
    border-inline-start: var(--rule-heavy) solid var(--danger);
    background: var(--console-panel-2);
    color: var(--console-text);
    font-size: var(--t-sm);
    line-height: var(--lh-body);
  }

  /* ────────────────────────────────────────────────────────────────
     3. CELULAR
     A mesma tela atende o escritório e a galeria. No celular a sangria
     aperta e a tabela é quem rola — a página, nunca.
     ──────────────────────────────────────────────────────────────── */

  @media (max-width: 720px) {
    .app .contratos-resumo-item,
    .app .remotas-resumo-item,
    .app .contratos-alerta,
    .app .contratos-form,
    .app .contrato-ficha,
    .app .remota-cartao,
    .app .intertravamento {
      padding-inline: var(--sp-3);
    }
    .app .contrato-coluna {
      padding-inline: var(--sp-3);
    }
    /* Rótulo e valor deixam de ser duas colunas e passam a ser duas linhas:
       em 320px, "Encerramento" e a data disputando a mesma linha quebram no
       meio da palavra. */
    .app .contrato-coluna dl {
      grid-template-columns: minmax(0, 1fr);
    }
    .app .contrato-coluna dt {
      padding-bottom: 0;
    }
    .app .contrato-coluna dd {
      border-top: 0;
      padding-top: 2px;
      text-align: left;
    }
    .app .contrato-ficha-head,
    .app .remota-cabecalho {
      flex-direction: column;
      align-items: start;
    }
    .app .remota-ocupacao-numeros {
      text-align: left;
    }
    .app .contratos-barra > .btn,
    .app .contrato-acoes > .btn {
      width: 100%;
    }
  }
}

@media print {
  /* Busca, filtro, formulário e botão são ferramenta de tela. No papel eles
     ocupariam a folha dizendo ao leitor para clicar em coisa nenhuma. */
  .app .contratos-barra,
  .app .contratos-form,
  .app .contrato-acoes,
  .app .contratos-module .btn,
  .app .remotas-module .btn,
  .app .remotas-busca,
  .app .remota-lista-abas,
  .app .remota-equipamento-lista {
    display: none;
  }

  /* A tinta de tela não existe em impressora de mina, que é preto e branco. O
     que era cor vira régua pesada, e a palavra que o HTML já escreve ("Vencido",
     "A vencer", "não encontrado") continua sendo o registro. */
  .app .contratos-resumo-item,
  .app .contrato-coluna,
  .app .remota-cartao,
  .app .contrato-ficha,
  .app .contratos-alerta,
  .app .intertravamento {
    background: transparent;
    background-image: none;
    color: var(--ink);
    border-color: var(--ink);
  }
  .app .contratos-tabela th,
  .app .remota-pontos th {
    position: static;
    box-shadow: none;
    background: var(--stock-2);
    color: var(--ink);
    border-bottom: var(--rule-body) solid var(--ink);
    text-align: left;
    -webkit-print-color-adjust: exact;
    print-color-adjust: exact;
  }
  .app .contratos-tabela td,
  .app .remota-pontos td {
    color: var(--ink);
    border-bottom-color: var(--rule-hair-ink);
  }
  .app .contrato-situacao {
    background: transparent;
    color: var(--ink);
    border: var(--rule-body) solid var(--ink);
  }
  .app .contratos-alerta li.vencido,
  .app .intertravamento-item.faltando,
  .app .intertravamento-alerta {
    border-inline-start-color: var(--risk-blocked-band);
  }
  .app .contratos-alerta li.a-vencer {
    border-inline-start-color: var(--risk-attention-band);
  }
  .app .intertravamento-item.atendido {
    border-inline-start-color: var(--risk-clear-band);
  }
  /* O ponto livre perde a hachura e fica com a régua: hachura em impressora de
     mina vira mancha, e mancha sobre uma tabela de endereços é ruído. */
  .app .remota-ponto.livre > td,
  .app .contrato-linha.semVigencia > td {
    background-image: none;
    border-bottom: var(--rule-body) solid var(--ink);
  }

  /* O quadro que rola em tela precisa se abrir na folha: um `max-height` que
     sobreviva à impressão corta a tabela na primeira página e esconde o resto
     sem avisar. */
  .app .table-wrap:has(.contratos-tabela),
  .app .table-wrap:has(.remota-pontos) {
    max-height: none;
    overflow: visible;
  }

  /* Nada de bloco partido ao meio pela quebra de página: uma ficha de contrato
     ou um cartão de remota cortado entre duas folhas é o defeito que faz
     alguém conferir a página errada. */
  .app .contrato-ficha,
  .app .contrato-comparacao,
  .app .contrato-coluna,
  .app .contrato-aditivos li,
  .app .contrato-anexo,
  .app .remota-cartao,
  .app .intertravamento,
  .app .intertravamento-item,
  .app .contratos-alerta li {
    break-inside: avoid;
  }
  .app .contrato-ficha-head,
  .app .remota-cabecalho,
  .app .contratos-empresas h2,
  .app .remota-cartao-head {
    break-after: avoid;
  }
  /* A tabela pode atravessar páginas, mas o cabeçalho a acompanha. */
  .app .contratos-tabela thead,
  .app .remota-pontos thead {
    display: table-header-group;
  }
}
