/* ════════════════════════════════════════════════════════════════════
   InfraMINA · Correias — Rotas de Inspeção e Avaliação de Correia

   Dois submódulos novos, um arquivo só, porque eles compartilham a mesma
   gramática: régua no lugar de caixa, rótulo em condensada versal, valor em
   Fira Mono tabular, raio zero. Nada aqui inventa linguagem visual — o que
   está escrito abaixo é o mundo "Permissão de Trabalho" de DESIGN.md aplicado
   a duas telas que ainda não existiam.

   Carregado DEPOIS de styles.css e de interface-polish.css. Isso importa: as
   regras deste arquivo 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. É o mesmo
   arranjo do bloco "Biblioteca de Atividades" em interface-polish.css.

   SUPERFÍCIE. Os dois submódulos 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. Por isso a tela inteira é `--console-*` e a
   virada para papel acontece no `@media print` no fim do arquivo, não 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. A situação de um item inspecionado
   e o veredito de uma avaliação SÃO classe de risco — ali a cor é obrigatória,
   e vem de `--success` / `--warning` / `--danger`, que viram sozinhas com o
   contexto, com a letra em `--on-success` / `--on-warning` / `--on-danger`.
   Fora disso não há cor: aba ativa, cadastro divergente, rota vencida e campo
   calculado se distinguem por peso de régua e por matéria (hachura), nunca por
   tinta. A aba ativa em laranja foi um dos erros catalogados em DESIGN.md e
   não volta aqui.

   CONVENÇÃO DE MARCAÇÃO que a integração precisa seguir:
     · numa célula de rótulo/valor (`.rotas-resumo-item`, `.tc-detalhe-campo`,
       `.ficha-linha`), o PRIMEIRO elemento é o rótulo e os seguintes são o
       valor e a unidade. A folha veste por posição, não por classe extra;
     · toda tabela larga (`.malha-tabela`, `.ficha-perfil`) vai dentro de um
       `.table-wrap`, que é quem rola de lado. A página nunca rola;
     · as seções da ficha são numeradas pelo CSS: o `<h2>` traz só o nome;
     · a situação e o veredito vão também ESCRITOS dentro do próprio elemento.
       Impressora de mina é preto e branco e daltonismo não pode esconder a
       mensagem — a mesma regra da folha impressa.
   ════════════════════════════════════════════════════════════════════ */

@media screen, print {
  /* ────────────────────────────────────────────────────────────────
     1. ROTAS DE INSPEÇÃO
     ──────────────────────────────────────────────────────────────── */

  .app .rotas-module,
  .app .ficha-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 uma tabela larga empurra o módulo inteiro
       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 planta dos dois módulos ──
     Os dois têm o mesmo desenho: uma coluna que manda — a tabela da malha, o
     documento da ficha — e uma coluna estreita ao lado, que é a ficha do
     transportador num caso e a lista de fichas no outro.

     Enquanto as duas não couberem inteiras lado a lado, a estreita vira uma
     FAIXA em cima. Não é preferência: a tag de um transportador tem oito
     caracteres em monoespaçada, e numa coluna espremida a 120px ela quebra no
     meio — uma tag partida é uma tag que ninguém confere no rádio.

     Por que uma consulta de largura e não o `auto-fit` que o resto do arquivo
     usa: `auto-fit` reparte o espaço em fatias IGUAIS, e aqui as duas fatias
     não são iguais nem deveriam ser. O corte em 1024px é a soma do que cada
     lado precisa para continuar legível — cerca de 240px de lista, o vão, e
     uns 620px de documento — numa tela que ainda gasta `--sidebar` com a
     barra lateral do sistema. */
  .app .malha-corpo {
    display: grid;
    gap: var(--sp-4);
    min-width: 0;
  }
  .app .rotas-conteudo,
  .app .malha-corpo > *,
  .app .ficha-module > * {
    min-width: 0;
  }
  /* O painel da aba. Um vão só entre os blocos da aba, e conteúdo alinhado ao
     topo: numa aba curta, como a de rotas sem rota nenhuma, o `stretch` que a
     grade dá de fábrica esticaria o bloco vazio pela altura da tela. */
  .app .rotas-conteudo {
    display: grid;
    align-content: start;
    gap: var(--sp-5);
  }

  @media (min-width: 1024px) {
    .app .malha-corpo {
      grid-template-columns: minmax(0, 1fr) minmax(0, 20rem);
      align-items: start;
    }
    .app .ficha-module {
      grid-template-columns: minmax(0, 15rem) minmax(0, 1fr);
      align-items: start;
    }
  }

  /* ── Cabeçalho de seção ──
     Toda aba abre com o mesmo bloco: o que esta tela é, uma frase dizendo
     para que ela serve e, quando existe, a ação que ela oferece. A régua de
     corpo embaixo separa o cabeçalho do conteúdo sem transformá-lo em mais
     uma caixa — o módulo já tem caixas demais para o que é, no fundo, uma
     linha de título. */
  .app .rotas-head {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    justify-content: space-between;
    gap: var(--sp-3) var(--sp-5);
    padding-bottom: var(--sp-3);
    border-bottom: var(--rule-body) solid var(--console-line-strong);
  }
  .app .rotas-head > div {
    min-width: 0;
  }
  .app .rotas-head :is(h2, h3) {
    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);
    line-height: var(--lh-tight);
    text-transform: uppercase;
  }
  .app .rotas-head p {
    margin: var(--sp-1) 0 0;
    max-width: var(--measure);
    color: var(--console-muted);
    font-size: var(--t-sm);
    line-height: var(--lh-body);
  }
  .app .rotas-head .btn {
    flex: 0 0 auto;
  }

  /* ── Abas do submódulo ──
     Quem está aqui se diz por peso de régua: a aba ativa ganha uma régua
     pesada na tinta do texto, as outras ficam sem régua e com tinta de apoio.
     A tinta do carimbo não entra — ela é o ato de autorizar, não o endereço
     em que a pessoa está. */
  .app .rotas-abas {
    display: flex;
    gap: 0;
    overflow-x: auto;
    overscroll-behavior-inline: contain;
    scrollbar-width: thin;
    border-bottom: var(--rule-hair) solid var(--console-line);
  }
  .app .rotas-aba {
    flex: 0 0 auto;
    /* A inspeção é feita no subsolo, no celular: o piso de toque vale aqui
       mesmo no desktop, porque a mesma tela atende os dois. */
    min-height: 44px;
    /* A régua da aba deita SOBRE a régua de fio do contêiner, em vez de
       empilhar duas linhas de espessuras diferentes. */
    margin-bottom: calc(-1 * var(--rule-hair));
    padding: var(--sp-3) var(--sp-4);
    border: 0;
    border-bottom: var(--rule-heavy) solid transparent;
    background: transparent;
    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;
    white-space: nowrap;
    cursor: pointer;
    transition:
      color var(--dur) var(--ease),
      border-color var(--dur) var(--ease);
  }
  .app .rotas-aba:hover {
    color: var(--console-text);
    border-bottom-color: var(--console-line);
  }
  /* Três formas de dizer "ativa", porque a integração pode escolher qualquer
     uma delas e nenhuma é mais correta que as outras. */
  .app .rotas-aba.active,
  .app .rotas-aba[aria-selected='true'],
  .app .rotas-aba[aria-current] {
    color: var(--console-text);
    border-bottom-color: var(--console-text);
  }

  /* ── Faixa de totais ──
     Não é uma grade de cartões: é UM bloco com células regradas, como o bloco
     de identificação da folha impressa. O que separa as células é a régua que
     aparece pelo vão de 1px, não uma borda por caixa. */
  .app .rotas-resumo {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(150px, 100%), 1fr));
    gap: var(--rule-hair);
    border: var(--rule-hair) solid var(--console-line);
    background: var(--console-line);
  }
  .app .rotas-resumo-item {
    min-width: 0;
    padding: var(--sp-3) var(--sp-4);
    background: var(--console-panel);
  }
  /* O total de "cadastro a conferir" chega com a classe `.atencao`, e ela NÃO
     é classe de risco: nenhuma correia parou porque a planilha de origem
     trazia dois valores para o mesmo equipamento. É a mesma pendência da
     linha divergente da tabela e recebe a mesma matéria — hachura e régua —,
     nunca tinta. A régua é `box-shadow` interno porque a faixa de totais se
     separa por vão de 1px: uma borda aqui roubaria esse vão. */
  .app .rotas-resumo-item.atencao {
    background-image: var(--hatch);
    box-shadow: inset 0 calc(-1 * var(--rule-body)) 0 var(--console-line-strong);
  }

  /* ── Filtros do cadastro ── */
  .app .malha-filtros {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(190px, 100%), 1fr));
    gap: var(--sp-3);
    align-items: end;
    padding-bottom: var(--sp-4);
    border-bottom: var(--rule-hair) solid var(--console-line);
  }
  .app .malha-filtros > * {
    min-width: 0;
  }

  /* ── Tabela do cadastro ──
     O cabeçalho fica preso no topo porque a malha tem mais de cem
     transportadores: rolar cinquenta linhas e não saber mais qual coluna é a
     potência é como ler a planilha de onde estes dados vieram.
     Para grudar, o cabeçalho precisa de um contêiner que role, e é o
     `.table-wrap` que recebe a altura máxima. Onde `:has()` não existir, o
     cabeçalho simplesmente rola junto — a tabela continua inteira. */
  .app .table-wrap:has(.malha-tabela) {
    max-height: min(62vh, 560px);
    overflow: auto;
    overscroll-behavior: contain;
  }
  .app .malha-tabela {
    width: 100%;
    border-collapse: collapse;
  }
  .app .malha-tabela th {
    position: sticky;
    top: 0;
    z-index: 2;
    background: var(--console-panel-2);
    /* Régua desenhada por dentro: `border` em célula presa ao topo escorrega
       com a rolagem, `box-shadow` interno não. */
    box-shadow: inset 0 calc(-1 * var(--rule-body)) 0 var(--console-line-strong);
    white-space: nowrap;
  }
  /* `td` é registro de valor por definição neste sistema: o que alguém
     respondeu sai em monoespaçada tabular, para as colunas de comprimento,
     potência e inclinação alinharem casa por casa. */
  .app .malha-tabela td {
    font-family: var(--font-value);
    font-variant-numeric: tabular-nums;
  }
  /* Opcional, para as colunas numéricas: alinhamento à direita é o que deixa
     473 e 74 comparáveis num relance. */
  .app .malha-tabela :is(th, td).malha-num {
    text-align: right;
    white-space: nowrap;
  }

  /* ── A linha é um controle ──
     Clicar na linha ABRE a ficha do transportador. Isso precisa estar dito
     antes do clique, senão a tabela parece só uma tabela e a ficha ao lado
     parece não ter como ser aberta. O anel de foco é `outline` e não a sombra
     de `--ring`: `box-shadow` não se desenha em `<tr>` de tabela com bordas
     colapsadas, e quem chega aqui pelo teclado é justamente quem mais precisa
     enxergar onde está. */
  .app .malha-linha {
    cursor: pointer;
  }
  .app .malha-linha:hover > td {
    background-color: var(--console-panel-2);
  }
  .app .malha-linha:focus-visible {
    outline: var(--rule-body) solid var(--console-text);
    outline-offset: calc(-1 * var(--rule-body));
  }

  /* ── O registro que a planilha trazia em duas versões ──
     Não é erro de operação: é pendência de conferência em campo. Por isso não
     recebe tinta de risco nenhuma — recebe a matéria do conflito, que é a
     hachura, e uma régua pesada embaixo. Quem olha vê que aquela linha pede
     alguma coisa; ninguém acha que a correia parou. */
  .app .malha-linha.divergente > td {
    background-image: var(--hatch);
    border-bottom: var(--rule-body) solid var(--console-line-strong);
  }

  /* ── A linha aberta ──
     "Selecionada" não é risco nem autorização: é endereço, a mesma categoria
     da aba ativa. Por isso se diz com a régua mais pesada da folha na borda de
     entrada e um degrau de superfície, e não com tinta.
     A régua entra como `box-shadow` interno em vez de `border-left` para não
     empurrar as oito colunas um pixel de lado a cada troca de seleção; e o
     degrau usa `background-color`, não o atalho `background`, para não apagar
     a hachura quando a linha aberta também é a linha a conferir. */
  .app .malha-linha.ativa > td {
    background-color: var(--console-panel-2);
  }
  .app .malha-linha.ativa > td:first-child {
    box-shadow: inset var(--rule-heavy) 0 0 var(--console-text);
  }

  /* ── Marca de régua ao lado de um nome ──
     Duas coisas diferentes com a mesma forma, e de propósito. "Conferir" diz
     que o cadastro daquele equipamento tem duas versões na planilha de
     origem; "crítico" diz que aquele item do checklist é obrigatório pelo
     plano. Nenhuma das duas é a classe de risco da operação: a primeira é
     pendência de escritório, a segunda é uma propriedade do plano que existe
     ANTES de alguém inspecionar coisa alguma. Se "crítico" recebesse tinta
     vermelha, toda folha de inspeção nasceria vermelha e a palavra perderia o
     sentido exatamente onde ela precisa ter. Então: régua, não tinta.
     Existem escritas, e não só desenhadas, porque a hachura da linha e a
     posição na lista não chegam a um leitor de tela. */
  .app .malha-marca,
  .app .inspecao-critico {
    display: inline-block;
    margin-inline-start: var(--sp-2);
    padding: 0 var(--sp-1);
    border: var(--rule-hair) solid var(--console-line-strong);
    color: var(--console-muted);
    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;
    vertical-align: middle;
    white-space: nowrap;
  }

  /* ── Ficha do transportador ── */
  .app .tc-detalhe {
    display: grid;
    align-content: start;
    gap: var(--sp-4);
    min-width: 0;
  }
  /* ── Cabeçalho da ficha do transportador ──
     A tag é identificador LANÇADO, não nome de seção: sai em monoespaçada,
     como todo valor deste sistema, e é por ela que o equipamento é chamado no
     rádio e procurado no SAP. A régua de corpo embaixo é o que diz que dali
     para baixo começa o registro. */
  .app .tc-detalhe-head {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--sp-2) var(--sp-4);
    padding-bottom: var(--sp-3);
    border-bottom: var(--rule-body) solid var(--console-line-strong);
  }
  .app .tc-detalhe-head > div {
    min-width: 0;
  }
  .app .tc-detalhe-head h2 {
    margin: 0;
    color: var(--console-text);
    font-family: var(--font-value);
    font-size: var(--t-doc);
    font-variant-numeric: tabular-nums;
    line-height: var(--lh-tight);
    overflow-wrap: anywhere;
  }
  .app .tc-detalhe-head p {
    margin: var(--sp-1) 0 0;
    color: var(--console-muted);
    font-family: var(--font-label);
    font-stretch: var(--stretch-label);
    font-size: var(--t-label);
    letter-spacing: var(--track-label);
    line-height: var(--lh-body);
    text-transform: uppercase;
  }
  .app .tc-detalhe-head .btn {
    flex: 0 0 auto;
  }
  .app .tc-detalhe-grade {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(150px, 100%), 1fr));
    gap: var(--rule-hair);
    border: var(--rule-hair) solid var(--console-line);
    background: var(--console-line);
  }
  .app .tc-detalhe-campo {
    min-width: 0;
    padding: var(--sp-3);
    background: var(--console-panel);
  }

  /* Observação do cadastro: é anotação de quem levantou a malha, não campo do
     formulário. Fica recuada atrás de uma régua, que é como este sistema
     escreve à margem — e por isso não ganha caixa própria. */
  .app .tc-detalhe-nota {
    margin: 0;
    padding-inline-start: var(--sp-3);
    border-inline-start: var(--rule-body) solid var(--console-line);
    color: var(--console-muted);
    font-size: var(--t-sm);
    line-height: var(--lh-body);
  }

  /* ── Onde o transportador está no fluxo ──
     De quem recebe, para quem descarrega, e em que rotas ele entra. É a mesma
     dupla rótulo/valor do resto do módulo, só que em texto corrido: o rótulo
     pergunta em versal condensada e o parágrafo responde. */
  .app .tc-fluxo {
    padding-top: var(--sp-3);
    border-top: var(--rule-hair) solid var(--console-line);
  }
  .app .tc-fluxo > span {
    display: block;
    color: var(--console-muted);
    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;
  }
  .app .tc-fluxo > p {
    margin: var(--sp-1) 0 0;
    color: var(--console-text);
    font-size: var(--t-sm);
    line-height: var(--lh-body);
  }

  /* ── O documento incompleto, e o documento em conflito ──
     `.tc-divergencia` é o cadastro que a planilha trazia em duas versões;
     `.ficha-avisos` é a lista do que ainda falta preencher para a avaliação
     fechar. São o mesmo objeto: um registro que ainda não pode ser dado por
     bom. Nenhum dos dois é classe de risco — nada parou, nada está impedido —
     e por isso os dois recebem a matéria do inacabado, que é hachura e régua,
     e nenhuma tinta. O texto dentro é que diz o que conferir. */
  .app .tc-divergencia,
  .app .ficha-avisos {
    padding: var(--sp-3) var(--sp-4);
    border: var(--rule-hair) solid var(--console-line-strong);
    border-bottom-width: var(--rule-body);
    background-color: var(--console-panel-2);
    background-image: var(--hatch);
    color: var(--console-text);
    font-size: var(--t-sm);
    line-height: var(--lh-body);
  }
  .app .tc-divergencia strong,
  .app .ficha-avisos strong {
    display: block;
    margin-bottom: var(--sp-1);
    color: var(--console-text);
    font-family: var(--font-label);
    font-stretch: var(--stretch-label);
    font-size: var(--t-label);
    letter-spacing: var(--track-label);
    text-transform: uppercase;
  }
  /* A lista do que conferir. O marcador nativo fica: aqui ele conta itens de
     uma pendência, que é justamente para o que ele serve. Só se acerta o
     recuo, que no padrão do navegador vem em pixels fixos e não acompanha o
     ritmo de 4px do resto. */
  .app .tc-divergencia ul,
  .app .ficha-avisos ul {
    margin: var(--sp-2) 0 0;
    padding-inline-start: var(--sp-5);
  }
  .app .tc-divergencia li,
  .app .ficha-avisos li {
    padding-block: var(--sp-1);
  }

  /* ── A lista de rotas ──
     Cartões lado a lado enquanto couberem inteiros. O piso de 340px não é
     estético: abaixo disso a sequência de passos do cartão já não mostra uma
     tag sem quebrá-la, e o cartão deixa de responder à única pergunta que ele
     existe para responder — por onde essa rota passa. */
  .app .rota-lista {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(340px, 100%), 1fr));
    gap: var(--sp-4);
    min-width: 0;
  }
  /* O aviso de lista vazia não é um cartão: ele fala pela lista inteira. */
  .app .rota-lista > .empty {
    grid-column: 1 / -1;
  }

  /* ── Cartão de rota ── */
  .app .rota-cartao {
    display: grid;
    gap: var(--sp-3);
    min-width: 0;
    padding: var(--sp-4);
    border: var(--rule-hair) solid var(--console-line);
    background: var(--console-panel-2);
  }
  .app .rota-cartao-metricas {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(120px, 100%), 1fr));
    gap: var(--rule-hair);
    border-block: var(--rule-hair) solid var(--console-line);
    background: var(--console-line);
  }
  .app .rota-cartao-metricas > * {
    min-width: 0;
    padding: var(--sp-2) var(--sp-3);
    background: var(--console-panel-2);
  }

  /* ── Topo e pé do cartão ──
     No topo, o nome da rota e o vencimento; no pé, o que se pode fazer com
     ela. O pé se separa por régua de fio e não por vão: num cartão que já tem
     três blocos empilhados, mais um vão não diz nada, e a régua diz "daqui
     para baixo são botões". */
  .app .rota-cartao > header {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--sp-2) var(--sp-3);
  }
  .app .rota-cartao > header > div {
    min-width: 0;
  }
  .app .rota-cartao h3 {
    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);
    line-height: var(--lh-tight);
    text-transform: uppercase;
  }
  .app .rota-cartao > header p {
    margin: var(--sp-1) 0 0;
    color: var(--console-muted);
    font-size: var(--t-sm);
    line-height: var(--lh-body);
  }
  /* O vencimento já chega vestido por `.situacao-*`: a data de uma rota
     vencida é classe de risco da operação e a cor ali é obrigatória. O que
     falta é só onde a marca pousa — canto de cima à direita, inteira, sem
     encolher, porque "Vencida há 12 d" quebrado em duas linhas vira outra
     frase. */
  .app .rota-vencimento {
    flex: 0 0 auto;
    white-space: nowrap;
  }
  .app .rota-cartao > footer {
    display: flex;
    flex-wrap: wrap;
    gap: var(--sp-2);
    padding-top: var(--sp-3);
    border-top: var(--rule-hair) solid var(--console-line);
  }

  /* ── Sequência da rota ──
     O passo é numerado pelo CSS em vez de ligado por uma seta desenhada: a
     ordem do percurso é informação, e um número se lê no rádio e em leitor de
     tela; uma seta decorativa não. O `list-style: none` evita o marcador nativo
     duplicar essa numeração quando a integração usar `<ol>`. */
  .app .rota-sequencia {
    display: flex;
    flex-wrap: wrap;
    gap: var(--sp-2);
    margin: 0;
    padding: 0;
    counter-reset: rota-passo;
    list-style: none;
  }
  .app .rota-passo {
    display: inline-flex;
    align-items: center;
    gap: var(--sp-2);
    min-height: 32px;
    padding: var(--sp-1) var(--sp-3);
    border: var(--rule-hair) solid var(--console-line-strong);
    background: var(--console-bg);
    color: var(--console-text);
    font-family: var(--font-value);
    font-size: var(--t-sm);
  }
  .app .rota-passo::before {
    counter-increment: rota-passo;
    content: counter(rota-passo);
    padding-right: var(--sp-2);
    border-right: var(--rule-hair) solid var(--console-line);
    color: var(--console-muted);
    font-family: var(--font-label);
    font-stretch: var(--stretch-label);
    font-size: var(--t-micro);
    font-weight: 700;
    letter-spacing: var(--track-label);
  }

  /* ── A mesma sequência, em edição ──
     No cartão a sequência é uma fita de fichas que se lê de uma vez. Dentro
     do formulário cada passo vira uma linha inteira, porque ali ele não é só
     leitura: ele sobe, desce e sai. Empilhada, a ordem do percurso também
     fica evidente enquanto está sendo arrumada, que é exatamente a decisão
     que o formulário está tomando.
     A grade herda o contador da fita: numerar de novo aqui faria a lista em
     edição discordar da lista salva. */
  .app .rota-sequencia.editavel {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: var(--rule-hair);
    border: var(--rule-hair) solid var(--console-line);
    background: var(--console-line);
  }
  .app .rota-sequencia.editavel > .rota-passo {
    justify-content: space-between;
    min-height: 44px;
    border: 0;
    background: var(--console-panel);
  }
  .app .rota-sequencia.editavel > .rota-passo > span:first-of-type {
    flex: 1 1 auto;
    min-width: 0;
    overflow-wrap: anywhere;
  }
  .app .rota-sequencia.editavel > .empty {
    background: var(--console-panel);
  }
  /* Subir, descer e remover andam juntos e não cedem largura: são três alvos
     pequenos lado a lado, e se um encolher o toque cai no vizinho — e o
     vizinho, aqui, apaga um passo da rota. */
  .app .rota-passo-acoes {
    display: inline-flex;
    flex: 0 0 auto;
    gap: var(--sp-1);
  }

  /* ── Rota com inspeção vencida ──
     Vencido não tem cor. O estado muda a MATÉRIA do cartão — perde saturação,
     ganha hachura e uma régua mais pesada em volta —, e a palavra "vencida"
     vai escrita dentro. Pintar de vermelho diria "impedido", que é outra coisa:
     a rota não está impedida, ela está atrasada. */
  .app .rota-cartao.rota-vencida,
  .app .rota-vencida {
    border-color: var(--console-line-strong);
    border-top-width: var(--rule-body);
    background-image: var(--hatch);
    color: var(--console-muted);
  }

  /* ── Formulário de montagem da rota ──
     É um `.card` do sistema, e o cartão do sistema só sabe vestir o próprio
     cabeçalho: tudo que vem depois dele chega encostado na borda. Esta regra
     dá ao resto do formulário a mesma sangria do `.card-head` e nada além
     disso — nem fundo, nem borda, nem tipografia, que já vêm do cartão. */
  .app .rota-formulario {
    display: grid;
    gap: var(--sp-4);
    min-width: 0;
  }
  .app .rota-formulario > :not(.card-head) {
    margin-inline: var(--sp-5);
  }
  .app .rota-formulario > :last-child {
    margin-bottom: var(--sp-5);
  }

  /* ── Sugestão do próximo passo ──
     O fluxograma sabe o que vem depois do transportador que acabou de entrar
     na rota, e essa é a diferença entre montar uma rota e adivinhar uma rota.
     A sugestão é uma frase, e cada tag dentro dela é um botão: quem monta vai
     lendo e tocando, em vez de voltar ao seletor a cada passo. Por isso o
     botão é inline e mantém a régua e a monoespaçada do passo — ele é o passo
     que ainda não entrou. */
  .app .rota-sugestao {
    margin: 0;
    padding: var(--sp-3);
    border: var(--rule-hair) solid var(--console-line);
    background: var(--console-panel-2);
    color: var(--console-muted);
    font-size: var(--t-sm);
    line-height: var(--lh-body);
  }
  .app .rota-sugestao-btn {
    min-height: 32px;
    margin-inline: var(--sp-1);
    padding: var(--sp-1) var(--sp-2);
    border: var(--rule-hair) solid var(--console-line-strong);
    background: var(--console-bg);
    color: var(--console-text);
    font-family: var(--font-value);
    font-size: var(--t-sm);
    cursor: pointer;
    transition: border-color var(--dur) var(--ease);
  }
  .app .rota-sugestao-btn:hover {
    border-color: var(--console-text);
  }

  /* ── Checklist em campo ──
     Esta é a única tela deste módulo desenhada primeiro para o celular: ela é
     usada de pé, no subsolo, com luva. Por isso é lista empilhada e não
     tabela, e por isso todo controle aqui tem 44px de altura em qualquer
     largura — não só abaixo de 768px, como o resto do sistema. */

  /* Um transportador da rota. O bloco não tem caixa própria: ele é só o par
     cabeçalho-preso + lista de itens. E não pode ganhar uma: `overflow`,
     `transform` ou `filter` aqui criariam um novo contexto de rolagem e o
     `position: sticky` do cabeçalho deixaria de grudar, passando a rolar
     junto — que é o defeito que este bloco existe para evitar. */
  .app .inspecao-bloco {
    display: grid;
    min-width: 0;
  }
  .app .inspecao-bloco + .inspecao-bloco {
    margin-top: var(--sp-5);
  }

  .app .inspecao-tc {
    position: sticky;
    top: 0;
    z-index: 3;
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: var(--sp-2) var(--sp-4);
    padding: var(--sp-3) var(--sp-4);
    border-bottom: var(--rule-body) solid var(--console-line-strong);
    background: var(--console-bg);
  }
  /* Fica preso no topo porque, depois de doze itens rolados, a pergunta que
     volta é "estou inspecionando qual transportador mesmo?". */
  .app .inspecao-tc strong {
    color: var(--console-text);
    font-family: var(--font-value);
    font-size: var(--t-doc);
    line-height: var(--lh-tight);
  }
  .app .inspecao-tc 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 .inspecao-itens {
    display: grid;
    gap: var(--rule-hair);
    margin: 0;
    padding: 0;
    border: var(--rule-hair) solid var(--console-line);
    background: var(--console-line);
    list-style: none;
  }
  /* ── O item: três partes ──
     O que se pergunta, a resposta e a observação.
     Em tela larga a pergunta ocupa a coluna que sobra e as quatro situações
     ficam à direita, uma ao lado da outra, na mesma altura em que o olho já
     está; a observação atravessa as duas colunas, porque ela comenta o item
     inteiro e não a resposta. Abaixo de 560px tudo empilha e as quatro
     situações viram dois por dois — ver a seção 4.
     `align-items: start` porque a pergunta pode ter três linhas de descrição
     e os botões não devem descer junto com ela. */
  .app .inspecao-item {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: start;
    gap: var(--sp-2);
    column-gap: var(--sp-4);
    min-width: 0;
    min-height: 44px;
    padding: var(--sp-3) var(--sp-4);
    background: var(--console-panel);
  }
  .app .inspecao-item-texto {
    display: grid;
    grid-column: 1;
    gap: var(--sp-1);
    min-width: 0;
  }
  .app .inspecao-item-texto small {
    color: var(--console-muted);
    font-size: var(--t-sm);
    line-height: var(--lh-body);
  }
  .app .inspecao-item-acoes {
    display: flex;
    flex-wrap: wrap;
    grid-column: 2;
    justify-content: flex-end;
    gap: var(--sp-1);
  }
  .app .inspecao-observacao {
    grid-column: 1 / -1;
  }
  .app .inspecao-item > :first-child {
    color: var(--console-text);
    font-size: var(--t-body);
    line-height: var(--lh-body);
  }
  .app .inspecao-item :is(button, select, label, a) {
    min-height: 44px;
  }
  .app .inspecao-item .btn {
    min-height: 44px;
  }
  /* A caixa de marcar não cresce para 44px — quem carrega o alvo é o rótulo
     que a envolve. Uma caixa de 44px vira um quadrado enorme ao lado de uma
     linha de texto de 15px. */
  .app .inspecao-item :is(input[type='checkbox'], input[type='radio']) {
    flex: 0 0 auto;
    width: 22px;
    height: 22px;
  }

  /* ── Classe de risco do item ──
     Aqui a cor é obrigatória: conforme, atenção e crítico SÃO as três classes
     de risco da operação. Campo preenchido com a tinta da classe e letra em
     `--on-*`, nunca uma cor de letra literal — o carimbo e as classes invertem
     de claridade entre o papel e o subsolo, e a letra precisa inverter junto.
     Pendente e não aplicável não são classes de risco e por isso não têm cor:
     pendente é régua pontilhada (ainda não foi respondido) e não aplicável é
     material achatado com hachura (não há o que responder). */
  .app .situacao-conforme,
  .app .situacao-atencao,
  .app .situacao-critico,
  .app .situacao-pendente,
  .app .situacao-naoAplicavel {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--sp-2);
    padding: var(--sp-2) var(--sp-3);
    border: var(--rule-hair) solid transparent;
    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;
    text-align: center;
  }
  .app .situacao-conforme {
    border-color: var(--success);
    background: var(--success);
    color: var(--on-success);
  }
  .app .situacao-atencao {
    border-color: var(--warning);
    background: var(--warning);
    color: var(--on-warning);
  }
  .app .situacao-critico {
    border-color: var(--danger);
    background: var(--danger);
    color: var(--on-danger);
  }
  .app .situacao-pendente {
    border-style: dotted;
    border-color: var(--console-line-strong);
    background: transparent;
    color: var(--console-muted);
  }
  .app .situacao-naoAplicavel {
    border-color: var(--console-line);
    background-color: var(--console-panel-2);
    background-image: var(--hatch);
    color: var(--console-muted);
  }
  /* Dentro do checklist a marca vira botão, e botão no subsolo tem 44px. */
  .app
    .inspecao-item
    :is(.situacao-conforme, .situacao-atencao, .situacao-critico, .situacao-pendente, .situacao-naoAplicavel) {
    flex: 1 1 auto;
    min-height: 44px;
    min-width: 44px;
    cursor: pointer;
  }

  /* ── As quatro situações como botão de escolha ──
     As quatro chegam ao HTML já com a classe da própria situação — é assim
     que se sabe, antes de tocar, o que cada botão significa. Se todas
     ficassem com o campo cheio, o item teria quatro campos pintados e nenhuma
     indicação de qual foi respondido, que é a única coisa que interessa
     depois de respondido.
     Então a tinta da classe de risco não sai: ela fica na RÉGUA de cada
     botão, que é onde a classe se declara. O campo cheio passa a significar o
     que ele significa no resto do sistema — preenchido. Um botão vazio é uma
     opção; o cheio é a resposta. A diferença é de matéria, sobrevive ao preto
     e branco e não depende de enxergar cor.
     `background-color` e `background-image` separados, e não o atalho, para
     que "não aplicável" perca também a hachura enquanto é só uma opção. */
  .app .inspecao-botao:not(.ativo) {
    background-color: transparent;
    background-image: none;
    color: var(--console-text);
  }

  /* ── Histórico e estatística ── */

  /* Os dois quadros de reincidência: em que equipamento o desvio volta e que
     ponto falha mais. Ficam lado a lado enquanto couberem, porque a leitura
     é a comparação entre os dois — é dela que sai em qual equipamento a
     manutenção entra primeiro. */
  .app .historico-colunas {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr));
    gap: var(--sp-4);
    min-width: 0;
  }
  .app .historico-colunas > * {
    min-width: 0;
  }

  /* ── A linha de estatística ──
     A mesma gramática da linha da ficha: o rótulo à esquerda, o vão no meio,
     o número encostado à direita. Aqui o vão não é fila de pontos — é a
     barra. E quando não há barra, como no quadro de pontos que mais falham, a
     margem automática do número segura o alinhamento sozinha: é a razão de a
     posição do número não depender de haver ou não uma barra antes dele.
     Estas linhas moram direto dentro do `.card`, que só sabe vestir o próprio
     cabeçalho — por isso a sangria repete a do `.card-head`. */
  .app .estatistica-linha {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--sp-2) var(--sp-3);
    min-width: 0;
    padding: var(--sp-2) var(--sp-5);
    border-top: var(--rule-hair) solid var(--console-line);
  }
  /* A primeira linha vem logo abaixo do cabeçalho do cartão, que já traz a
     própria régua: sem isto o quadro abre com duas linhas coladas de
     espessuras diferentes. */
  .app .card-head + .estatistica-linha {
    border-top: 0;
  }
  .app .estatistica-linha > :first-child {
    flex: 0 1 auto;
    min-width: 0;
    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);
    overflow-wrap: anywhere;
    text-transform: uppercase;
  }
  .app .estatistica-linha > .estatistica-barra {
    flex: 1 1 var(--sp-10);
    min-width: var(--sp-8);
  }
  .app .estatistica-linha > strong {
    margin-inline-start: auto;
    color: var(--console-text);
    font-family: var(--font-value);
    font-size: var(--t-value);
    font-variant-numeric: tabular-nums;
  }

  .app .historico-lista {
    display: grid;
    gap: var(--rule-hair);
    margin: 0;
    padding: 0;
    border: var(--rule-hair) solid var(--console-line);
    background: var(--console-line);
    list-style: none;
  }
  .app .historico-item {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: baseline;
    gap: var(--sp-2) var(--sp-4);
    min-width: 0;
    padding: var(--sp-3) var(--sp-4);
    background: var(--console-panel);
  }
  .app .historico-item :is(time, small) {
    color: var(--console-muted);
    font-family: var(--font-value);
    font-size: var(--t-micro);
    font-variant-numeric: tabular-nums;
  }
  /* Data, responsável e turno vêm num `<small>` depois do nome da rota. Sem
     isto os dois correm na mesma linha e o nome da rota emenda na data. */
  .app .historico-item small {
    display: block;
    margin-top: var(--sp-1);
  }
  /* Os totais da inspeção, na coluna da direita: três valores lançados, em
     monoespaçada tabular, separados por régua de fio. Um vão sozinho não diz
     que são três medidas do MESMO registro — diz que são três coisas. */
  .app .historico-numeros {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    justify-content: flex-end;
    column-gap: var(--sp-3);
    row-gap: var(--sp-1);
    min-width: 0;
    color: var(--console-text);
    font-family: var(--font-value);
    font-size: var(--t-sm);
    font-variant-numeric: tabular-nums;
  }
  .app .historico-numeros > * + * {
    padding-inline-start: var(--sp-3);
    border-inline-start: var(--rule-hair) solid var(--console-line);
  }

  /* ── A situação geral da inspeção concluída ──
     Aqui a classe de risco chega na LINHA inteira, não numa marca dentro
     dela. Como marca, `.situacao-*` deixaria a linha em versal condensada de
     12px: a data, o nome do inspetor e o turno virariam rótulo pré-impresso e
     o registro sumiria — justamente numa lista que existe para dizer quem
     passou por onde e o que encontrou.
     Então, no corpo de um documento, a classe deixa de ser marca e vira o que
     uma classe de risco é num documento: a tarja na borda de entrada, do
     mesmo jeito que o veredito da ficha. A cor continua sendo obrigatória —
     uma inspeção que fechou em crítico É classe de risco — e continua vindo
     das tintas de tarja, cujo piso é 3:1 por ser componente não textual. */
  .app
    .historico-item:is(
      .situacao-conforme,
      .situacao-atencao,
      .situacao-critico,
      .situacao-pendente,
      .situacao-naoAplicavel
    ) {
    border: 0;
    border-inline-start: var(--rule-band) solid var(--console-line-strong);
    justify-content: start;
    font-family: var(--font-text);
    font-size: var(--t-body);
    font-weight: 400;
    letter-spacing: normal;
    text-align: start;
    text-transform: none;
  }
  .app .historico-item.situacao-conforme {
    border-inline-start-color: var(--risk-clear-edge);
  }
  .app .historico-item.situacao-atencao {
    border-inline-start-color: var(--risk-attention-edge);
  }
  .app .historico-item.situacao-critico {
    border-inline-start-color: var(--risk-blocked-edge);
  }

  /* A barra mede QUANTIDADE, não risco: o trilho e o preenchimento neutro
     ficam em régua e cinza. Quando a fatia representar uma classe de risco, a
     integração põe `.situacao-*` nela e a tinta vem de lá — por isso a fatia
     perde caixa e altura próprias aqui dentro. */
  .app .estatistica-barra {
    display: flex;
    overflow: hidden;
    height: var(--sp-3);
    border: var(--rule-hair) solid var(--console-line);
    background: var(--console-bg);
  }
  .app .estatistica-barra > * {
    min-width: 0;
    background: var(--console-line-strong);
  }
  .app
    .estatistica-barra
    :is(.situacao-conforme, .situacao-atencao, .situacao-critico, .situacao-pendente, .situacao-naoAplicavel) {
    min-height: 0;
    min-width: 0;
    padding: 0;
    border: 0;
    font-size: 0;
  }

  /* ────────────────────────────────────────────────────────────────
     2. AVALIAÇÃO DE CORREIA — a ficha
     ──────────────────────────────────────────────────────────────── */

  .app .ficha-module {
    counter-reset: ficha-secao;
  }

  /* ── A biblioteca de fichas ──
     Uma avaliação não vive sozinha: o mesmo transportador é avaliado em
     condição real, em capacidade máxima e no projeto, e o trabalho É a
     comparação entre as três. Por isso a lista fica ao lado do documento e
     não atrás de um menu — trocar de cenário precisa custar um toque.
     Em tela estreita ela vira uma faixa que rola de lado, acima do documento:
     empilhar doze fichas em coluna empurraria a ficha aberta para fora da
     primeira tela, e quem abriu esta tela veio ver a ficha. */
  .app .ficha-biblioteca {
    display: grid;
    grid-template-rows: auto minmax(0, 1fr);
    align-self: start;
    min-width: 0;
    border: var(--rule-hair) solid var(--console-line);
    background: var(--console-panel);
  }
  .app .ficha-biblioteca-head {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-2) var(--sp-3);
    padding: var(--sp-3) var(--sp-4);
    border-bottom: var(--rule-body) solid var(--console-line-strong);
    background: var(--console-panel-2);
  }
  .app .ficha-biblioteca-head > div {
    min-width: 0;
  }
  .app .ficha-biblioteca-head 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);
    line-height: var(--lh-tight);
    text-transform: uppercase;
  }
  .app .ficha-biblioteca-head p {
    margin: var(--sp-1) 0 0;
    color: var(--console-muted);
    font-size: var(--t-micro);
    line-height: var(--lh-tight);
  }
  .app .ficha-biblioteca-lista {
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: minmax(11rem, 1fr);
    gap: var(--rule-hair);
    overflow-x: auto;
    overscroll-behavior-inline: contain;
    scrollbar-width: thin;
    background: var(--console-line);
  }
  .app .ficha-biblioteca-lista > .empty {
    background: var(--console-panel);
  }
  .app .ficha-biblioteca-item {
    display: grid;
    gap: var(--sp-1);
    min-width: 0;
    min-height: 44px;
    padding: var(--sp-3) var(--sp-4);
    border: 0;
    background: var(--console-panel);
    text-align: start;
    cursor: pointer;
    transition: background-color var(--dur) var(--ease);
  }
  .app .ficha-biblioteca-item:hover {
    background: var(--console-panel-2);
  }
  /* A tag é valor lançado; o cenário e a data, rótulo do que aquela ficha é. */
  .app .ficha-biblioteca-item strong {
    color: var(--console-text);
    font-family: var(--font-value);
    font-size: var(--t-value);
    line-height: var(--lh-value);
    overflow-wrap: anywhere;
  }
  .app .ficha-biblioteca-item small {
    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;
  }
  /* A ficha aberta. Mesma tese da linha aberta da malha: endereço se diz com
     régua, não com tinta. Na faixa a régua entra por cima, porque é ali que
     está a borda de entrada quando a lista corre na horizontal; virando
     coluna, ela passa para a lateral — ver a seção 4. */
  .app .ficha-biblioteca-item.active {
    background: var(--console-panel-2);
    box-shadow: inset 0 var(--rule-heavy) 0 var(--console-text);
  }

  /* ── O documento ──
     A ficha é uma folha: blocos empilhados, um vão só entre eles, e uma
     largura que para de crescer. O limite não é estético — passando de umas
     58rem o rótulo de 12px e o valor à direita ficam tão longe um do outro
     que a fila de pontos deixa de costurar os dois, que é o serviço inteiro
     que ela presta. */
  .app .ficha-documento {
    display: grid;
    align-content: start;
    gap: var(--sp-4);
    min-width: 0;
    max-width: 58rem;
  }
  /* Equipamento, empresa e cenário: a identificação que abre a folha. Ocupa a
     largura que sobra no cabeçalho e cede o resto para os botões. */
  .app .ficha-cabecalho-campos {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(160px, 100%), 1fr));
    flex: 1 1 22rem;
    gap: var(--sp-3);
    min-width: 0;
  }
  .app .ficha-cabecalho-acoes {
    display: flex;
    flex: 0 0 auto;
    flex-wrap: wrap;
    gap: var(--sp-2);
  }

  /* ── Cabeçalho: identificação do equipamento ──
     Lê-se como o carimbo de um documento emitido: régua pesada embaixo,
     equipamento em corpo de título e o identificador da avaliação numa caixa
     regrada à direita, do mesmo jeito que o número falável da folha impressa. */
  .app .ficha-cabecalho {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    justify-content: space-between;
    gap: var(--sp-3) var(--sp-5);
    padding-bottom: var(--sp-3);
    border-bottom: var(--rule-heavy) solid var(--console-text);
  }
  .app .ficha-cabecalho :is(h2, h3) {
    margin: 0;
    color: var(--console-text);
    font-family: var(--font-label);
    font-stretch: var(--stretch-label);
    font-size: var(--t-doc);
    font-weight: 700;
    letter-spacing: 0.02em;
    line-height: var(--lh-tight);
    text-transform: uppercase;
  }
  .app .ficha-cabecalho p {
    margin: var(--sp-1) 0 0;
    max-width: var(--measure);
    color: var(--console-muted);
    font-size: var(--t-sm);
    line-height: var(--lh-body);
  }
  .app .ficha-cabecalho :is(code, output) {
    flex: 0 0 auto;
    padding: var(--sp-1) var(--sp-3);
    border: var(--rule-body) solid var(--console-text);
    color: var(--console-text);
    font-family: var(--font-value);
    font-size: var(--t-lg);
    font-variant-numeric: tabular-nums;
    line-height: var(--lh-tight);
  }

  /* ── Seções numeradas, e os blocos que não entram na conta ──
     A numeração é do CSS: um contador não sai do lugar quando alguém insere
     uma seção no meio, e uma folha cujo "3." virou o segundo bloco é uma folha
     que ninguém consegue citar por telefone.

     Por isso existe `.ficha-bloco-titulo`. A ficha tem exatamente TRÊS seções
     numeradas — capacidade, potência e tensões —, que são as três da folha de
     papel. "Perfil do transportador" e "Memória de cálculo" são blocos da
     mesma folha, mas não são seções dela: entram como material de apoio, um
     antes e um depois. Se o contador os pegasse, o "3" da tela deixaria de ser
     o "3" do papel e ninguém mais conseguiria dizer "olha a três" no rádio.
     Então eles recebem a mesma presença — mesma faixa, mesma régua, mesma
     versal — e só não recebem o número: a diferença entre os dois títulos é
     exatamente a diferença que existe entre as duas coisas. */
  .app .ficha-secao {
    min-width: 0;
    border: var(--rule-hair) solid var(--console-line);
    background: var(--console-panel);
  }
  .app .ficha-secao-titulo,
  .app .ficha-bloco-titulo {
    display: flex;
    align-items: center;
    gap: var(--sp-3);
    margin: 0;
    padding: var(--sp-3) var(--sp-4);
    border-bottom: var(--rule-body) solid var(--console-line-strong);
    background: var(--console-panel-2);
    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 .ficha-secao-titulo::before {
    counter-increment: ficha-secao;
    content: counter(ficha-secao);
    flex: 0 0 auto;
    min-width: 1.8em;
    padding: 0 0.25em;
    border: var(--rule-body) solid currentColor;
    font-family: var(--font-value);
    font-size: var(--t-label);
    line-height: 1.6;
    text-align: center;
  }

  /* ── Faixa de título com uma ação dentro ──
     A memória de cálculo abre e fecha, e o botão que faz isso pertence ao
     título dela, não ao corpo da seção. Quem passa a ser a faixa é este
     contêiner: o título dentro dele abre mão da própria régua e do próprio
     fundo, senão a tela desenha duas faixas empilhadas de alturas
     diferentes. */
  .app .ficha-secao-head {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-2);
    padding-inline-end: var(--sp-4);
    border-bottom: var(--rule-body) solid var(--console-line-strong);
    background: var(--console-panel-2);
  }
  .app .ficha-secao-head > :is(.ficha-secao-titulo, .ficha-bloco-titulo) {
    flex: 1 1 auto;
    border-bottom: 0;
    background: transparent;
  }

  /* ── Os subtítulos 1.1 e 1.2 ──
     Esta é a única numeração da ficha que NÃO é do CSS, e não é por
     esquecimento: "1.1 Velocidade da correia" e "1.2 Capacidade de
     transporte" citam a ordem da NBR 8011, não a ordem da tela. Um contador
     os renumeraria conforme a tela mudasse, e aí o subtítulo deixaria de
     apontar para a norma. Ficam em corpo de rótulo, com régua de fio em cima,
     separando grupos de linhas dentro da mesma seção. */
  .app .ficha-secao h3 {
    margin: 0;
    padding: var(--sp-3) var(--sp-4) var(--sp-1);
    border-top: var(--rule-hair) solid var(--console-line);
    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;
  }
  /* Logo abaixo da faixa do título a régua seria a segunda em dois pixels. */
  .app .ficha-secao > :is(.ficha-secao-titulo, .ficha-bloco-titulo, .ficha-secao-head) + h3 {
    border-top: 0;
  }

  /* A linha da ficha traz a própria sangria; o que não é linha — a nota de
     preenchimento, a tabela de trechos, o botão de adicionar trecho e o
     veredito — precisa da mesma margem, ou encosta na régua da seção e passa
     a parecer que vazou do bloco. */
  .app .ficha-secao > :is(p, .table-wrap, .btn, .ficha-veredito) {
    margin-inline: var(--sp-4);
  }
  .app .ficha-secao > .btn {
    margin-bottom: var(--sp-4);
  }
  .app .ficha-secao > .ficha-veredito {
    margin-block: var(--sp-4);
  }

  /* Nota de preenchimento: a instrução que vinha impressa em letra miúda no
     rodapé do campo, na folha de papel. Continua sendo isso. */
  .app .ficha-nota {
    margin: 0;
    max-width: var(--measure);
    color: var(--console-muted);
    font-size: var(--t-sm);
    line-height: var(--lh-body);
  }

  /* ── A linha da ficha ──
     Esta é a forma da ficha de papel de onde o cálculo veio: rótulo à
     esquerda, fila de pontos, valor e unidade à direita. Os pontos são um item
     flexível vazio no meio da linha — cresce até encostar no valor e encolhe
     quando o rótulo é longo. Alinhado pela LINHA DE BASE: uma caixa vazia tem
     a base na própria aresta inferior, então a régua pontilhada pousa
     exatamente onde as letras pousam.

     A ordem visual é declarada (`order`) e não depende da ordem do HTML, então
     a marcação pode continuar sendo rótulo → valor → unidade, que é como se
     lê. Em tela estreita o valor cai para a linha de baixo e a margem
     automática o mantém encostado à direita. */
  .app .ficha-linha {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    column-gap: var(--sp-2);
    row-gap: var(--sp-1);
    min-width: 0;
    padding: var(--sp-2) var(--sp-4);
    border-bottom: var(--rule-hair) solid var(--console-line);
  }
  .app .ficha-linha:last-child {
    border-bottom: 0;
  }
  .app .ficha-linha > * {
    order: 3;
  }
  .app .ficha-linha::before {
    content: '';
    order: 2;
    flex: 1 1 var(--sp-8);
    align-self: baseline;
    min-width: var(--sp-6);
    border-bottom: var(--rule-hair) dotted var(--console-line-strong);
  }
  .app .ficha-linha > :first-child {
    order: 1;
    flex: 0 1 auto;
    min-width: 0;
    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 .ficha-linha > :first-child + * {
    margin-inline-start: auto;
    color: var(--console-text);
    font-family: var(--font-value);
    font-size: var(--t-value);
    font-variant-numeric: tabular-nums;
  }
  .app .ficha-linha > :first-child + * ~ * {
    margin-inline-start: 0;
    color: var(--console-muted);
    font-size: var(--t-sm);
  }

  /* ── Entrada e resultado ──
     A ficha original separava os dois por cor: amarelo onde se escreve, verde
     onde o sistema devolve. Aqui a diferença é de MATÉRIA, que é como este
     produto diz as coisas, e que sobrevive ao preto e branco da impressora e
     ao daltonismo.

     O que se preenche é um poço de campo: fundo recuado e régua pesada
     embaixo, a mesma forma de todo campo do sistema, com o foco levando essa
     régua para a tinta do carimbo.

     O que o sistema devolve não é campo — é resultado impresso. Superfície
     rasa, régua pontilhada, hachura e a palavra "calculado" em corpo miúdo:
     a mesma língua do campo fechado, que já quer dizer "aqui não se escreve".
     Nenhuma das duas regras toca em fundo ou borda do valor comum acima, então
     as duas apenas somam à tipografia da linha em vez de disputar com ela. */
  .app .ficha-campo-entrada {
    min-height: 44px;
    padding: var(--sp-1) var(--sp-3);
    border: 0;
    border-bottom: var(--rule-body) solid var(--console-line-strong);
    background: var(--console-bg);
    text-align: right;
  }
  .app .ficha-campo-entrada:focus {
    border-bottom-color: var(--primary);
    outline: none;
  }
  .app .ficha-campo-calculado {
    display: inline-flex;
    align-items: baseline;
    gap: var(--sp-2);
    padding: var(--sp-1) var(--sp-3);
    border-bottom: var(--rule-hair) dotted var(--console-line-strong);
    background-color: var(--console-panel-2);
    background-image: var(--hatch);
  }
  .app .ficha-campo-calculado::after {
    content: 'calculado';
    color: var(--console-muted);
    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;
  }

  /* ── Tabela de trechos do perfil ── */
  .app .ficha-perfil {
    width: 100%;
    min-width: 0;
    border-collapse: collapse;
  }
  .app .ficha-perfil :is(th, td) {
    padding: var(--sp-2) var(--sp-3);
    border-bottom: var(--rule-hair) solid var(--console-line);
    text-align: right;
  }
  .app .ficha-perfil :is(th, td):first-child {
    text-align: left;
  }
  .app .ficha-perfil th {
    border-bottom: var(--rule-body) solid var(--console-line-strong);
    background: var(--console-panel-2);
    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;
    white-space: nowrap;
  }
  .app .ficha-perfil td {
    color: var(--console-text);
    font-family: var(--font-value);
    font-size: var(--t-sm);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
  }
  /* Faixa alternada discreta: num perfil de oito trechos com quatro colunas de
     número, é o que impede o olho de pular de linha no escuro. */
  .app .ficha-trecho:nth-of-type(even) > * {
    background: var(--console-panel-2);
  }
  .app .ficha-trecho .form-control {
    min-width: 0;
    text-align: right;
  }

  /* ── Veredito ──
     Este bloco É a classe de risco da avaliação, e por isso ele pode ocupar o
     slot de 8px reservado à tarja — não há aqui uma classe inventada, há a
     conclusão do documento. A palavra vai junto da tarja, sempre: impressora
     de mina é preto e branco. */
  .app .ficha-veredito {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: var(--sp-2) var(--sp-4);
    min-width: 0;
    padding: var(--sp-4);
    border: var(--rule-hair) solid var(--console-line);
    border-top: var(--rule-band) solid var(--console-line-strong);
    background: var(--console-panel);
    color: var(--console-text);
    line-height: var(--lh-body);
  }
  .app .ficha-veredito strong {
    font-family: var(--font-label);
    font-stretch: var(--stretch-label);
    font-size: var(--t-doc);
    font-weight: 700;
    letter-spacing: var(--track-label);
    line-height: var(--lh-tight);
    text-transform: uppercase;
  }
  .app .ficha-veredito.atende {
    border-top-color: var(--risk-clear-edge);
  }
  .app .ficha-veredito.atende strong {
    color: var(--success);
  }
  .app .ficha-veredito.atencao {
    border-top-color: var(--risk-attention-edge);
  }
  .app .ficha-veredito.atencao strong {
    color: var(--warning);
  }
  .app .ficha-veredito.naoAtende {
    border-top-color: var(--risk-blocked-edge);
  }
  .app .ficha-veredito.naoAtende strong {
    color: var(--danger);
  }

  /* ── Memória de cálculo ──
     É o que torna o número defensável: a conta inteira, na ordem em que foi
     feita. Quebra dentro da própria linha em vez de rolar de lado, porque no
     celular uma fórmula que sai da tela é uma fórmula que ninguém confere. */
  .app .ficha-memoria {
    margin: 0;
    min-width: 0;
    padding: var(--sp-4);
    border-top: var(--rule-hair) solid var(--console-line);
    background: var(--console-bg);
    color: var(--console-muted);
    font-family: var(--font-value);
    font-size: var(--t-sm);
    line-height: var(--lh-value);
  }
  /* Uma linha da memória tem cinco partes: de onde vem (a seção), o que é (o
     rótulo), a fórmula, a fórmula com os números no lugar das letras, e o
     resultado.
     A linha é um contêiner FLEXÍVEL e não um bloco de texto pré-formatado:
     com `white-space: pre-wrap` no contêiner, a própria indentação do HTML
     viraria espaço em branco na tela, e a memória apareceria cheia de buracos
     que ninguém escreveu. Quem precisa de `pre-wrap` é a fórmula — e é nela
     que ele está agora. */
  .app .ficha-memoria-linha {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    column-gap: var(--sp-2);
    row-gap: var(--sp-1);
    min-width: 0;
    padding-block: var(--sp-2);
    font-variant-numeric: tabular-nums;
    overflow-wrap: anywhere;
  }
  .app .ficha-memoria-linha + .ficha-memoria-linha {
    border-top: var(--rule-hair) dotted var(--console-line);
  }
  .app .ficha-memoria-secao {
    padding-inline-end: var(--sp-2);
    border-inline-end: var(--rule-hair) solid var(--console-line);
    color: var(--console-muted);
    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;
  }
  .app .ficha-memoria-rotulo {
    flex: 1 1 auto;
    min-width: 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;
  }
  /* A fórmula e a substituição tomam a linha inteira. Espremer
     `Q = 3,6 · S · v · ρ · k` ao lado do rótulo é o mesmo que não mostrar a
     fórmula: quem assina precisa conseguir ler a conta de uma vez. */
  .app .ficha-memoria-linha code {
    flex: 1 1 100%;
    min-width: 0;
    color: var(--console-muted);
    white-space: pre-wrap;
    overflow-wrap: anywhere;
  }
  /* O resultado fecha a linha encostado à direita, como todo valor da ficha. */
  .app .ficha-memoria-linha strong {
    margin-inline-start: auto;
    color: var(--console-text);
    font-size: var(--t-value);
  }

  /* ── Comparar duas avaliações ──
     Condição real à esquerda, capacidade máxima à direita, separadas por uma
     régua de fio e não por um vão: as duas colunas são o mesmo documento visto
     de dois jeitos, e o que interessa é a diferença linha a linha. Abaixo de
     ~600px elas empilham, e a régua passa a separar em cima e embaixo. */
  .app .ficha-comparar {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(280px, 100%), 1fr));
    gap: var(--rule-hair);
    min-width: 0;
    border: var(--rule-hair) solid var(--console-line);
    background: var(--console-line);
  }
  .app .ficha-comparar > * {
    min-width: 0;
    background: var(--console-panel);
  }

  /* ────────────────────────────────────────────────────────────────
     3. RÓTULO E VALOR — a dupla que se repete
     A mesma distinção epistemológica do resto do sistema: o rótulo é o que o
     formulário PERGUNTOU (condensada, versal, pré-impressa) e o valor é o que
     alguém RESPONDEU (monoespaçado, tabular, lançado). Como as células destes
     dois submódulos seguem sempre a ordem rótulo → valor, a folha veste por
     posição e a integração não precisa de nenhuma classe a mais.
     ──────────────────────────────────────────────────────────────── */
  .app .rotas-resumo-item > :first-child,
  .app .tc-detalhe-campo > :first-child,
  .app .rota-cartao-metricas > * > :first-child {
    display: block;
    color: var(--console-muted);
    font-family: var(--font-label);
    font-stretch: var(--stretch-label);
    font-size: var(--t-micro);
    font-weight: 700;
    letter-spacing: var(--track-label);
    line-height: var(--lh-tight);
    text-transform: uppercase;
  }
  .app .rotas-resumo-item > :first-child + *,
  .app .tc-detalhe-campo > :first-child + *,
  .app .rota-cartao-metricas > * > :first-child + * {
    display: block;
    margin-top: var(--sp-1);
    color: var(--console-text);
    font-family: var(--font-value);
    font-variant-numeric: tabular-nums;
    line-height: var(--lh-value);
  }
  .app .rotas-resumo-item > :first-child + * {
    font-size: var(--t-doc);
  }
  .app .tc-detalhe-campo > :first-child + *,
  .app .rota-cartao-metricas > * > :first-child + * {
    font-size: var(--t-value);
  }
  /* Campo sem informação: o cadastro veio de um fluxograma em Excel e nem todo
     transportador trazia potência, subestação ou inclinação. Um traço em tinta
     de apoio diz "a planilha não informava", que é diferente de "vale zero" —
     e essa diferença é a razão de o cadastro existir. */
  .app .tc-detalhe-campo.vazio > :first-child + * {
    color: var(--console-muted);
  }

  /* ────────────────────────────────────────────────────────────────
     4. TELA ESTREITA — 360px é a largura de trabalho, não a exceção
     ──────────────────────────────────────────────────────────────── */
  @media (max-width: 560px) {
    .app .rotas-resumo,
    .app .tc-detalhe-grade,
    .app .rota-cartao-metricas {
      grid-template-columns: repeat(2, minmax(0, 1fr));
    }
    .app .rotas-aba {
      padding-inline: var(--sp-3);
    }
    .app .ficha-linha,
    .app .inspecao-item,
    .app .historico-item,
    .app .rotas-resumo-item,
    .app .ficha-biblioteca-head,
    .app .ficha-biblioteca-item {
      padding-inline: var(--sp-3);
    }
    /* O que mora dentro da seção da ficha acompanha a mesma sangria: a nota,
       a tabela de trechos, o botão, o veredito e os subtítulos da norma. */
    .app .estatistica-linha,
    .app .ficha-secao h3 {
      padding-inline: var(--sp-3);
    }
    .app .ficha-secao > :is(p, .table-wrap, .btn, .ficha-veredito) {
      margin-inline: var(--sp-3);
    }
    .app .ficha-secao-head {
      padding-inline-end: var(--sp-3);
    }
    .app .rota-formulario > :not(.card-head) {
      margin-inline: var(--sp-4);
    }
    .app .rota-formulario > :last-child {
      margin-bottom: var(--sp-4);
    }
    /* O rótulo não desce de 11px, que é o piso absoluto de legibilidade
       declarado na escala — abaixo disso ele deixa de ser lido de capacete. */
    .app .ficha-linha > :first-child,
    .app .ficha-secao-titulo,
    .app .ficha-bloco-titulo,
    .app .rotas-aba {
      font-size: var(--t-micro);
    }
    /* A palavra "calculado" some: nesta largura ela empurra o número para
       fora da linha, e a hachura sozinha já diz que ali não se escreve. */
    .app .ficha-campo-calculado::after {
      display: none;
    }
    .app .historico-item {
      grid-template-columns: minmax(0, 1fr);
    }
    /* Empilhados, os totais não têm mais direita para encostar. */
    .app .historico-numeros {
      justify-content: flex-start;
    }
    .app .ficha-cabecalho,
    .app .rotas-head {
      align-items: flex-start;
    }

    /* ── O checklist a 360px ──
       O item empilha, e as quatro situações viram dois por dois. Não é um
       arranjo bonito: é o único que cabe. Numa fileira só, quatro botões com
       "não aplicável" escrito dentro ficam com menos de 80px cada, e a
       palavra quebra em três linhas; numa coluna só, o quarto botão nasce
       abaixo da dobra e a pessoa acha que só existem três situações.
       Dois por dois com `1fr` mantém os quatro alvos do mesmo tamanho e
       acima dos 44px que a luva exige. */
    .app .inspecao-item {
      grid-template-columns: minmax(0, 1fr);
    }
    .app .inspecao-item-acoes {
      display: grid;
      grid-template-columns: repeat(2, minmax(0, 1fr));
      grid-column: 1;
    }
    /* A faixa de fichas encurta a coluna para caber mais de uma na tela: a
       faixa só serve se der para ver que existe outra ficha ao lado. */
    .app .ficha-biblioteca-lista {
      grid-auto-columns: minmax(9rem, 1fr);
    }
  }

  /* ────────────────────────────────────────────────────────────────
     4b. TELA LARGA — a coluna estreita vira coluna
     O corte está explicado na planta dos dois módulos, lá em cima. Aqui só
     acontece o que muda quando a lista deixa de ser faixa: ela rola para
     baixo em vez de para o lado, e a régua da ficha aberta sai do topo e vai
     para a borda de entrada, que é onde a leitura começa numa coluna.
     ──────────────────────────────────────────────────────────────── */
  @media (min-width: 1024px) {
    .app .ficha-biblioteca-lista {
      grid-auto-flow: row;
      grid-auto-columns: auto;
      max-height: min(60vh, 520px);
      overflow-x: hidden;
      overflow-y: auto;
    }
    .app .ficha-biblioteca-item.active {
      box-shadow: inset var(--rule-heavy) 0 0 var(--console-text);
    }
  }

  /* ────────────────────────────────────────────────────────────────
     5. MOVIMENTO
     As durações já vão a zero em `prefers-reduced-motion` porque vêm de
     `--dur`, declarado em tokens.css. Este bloco existe mesmo assim: se
     alguém, numa edição futura, escrever uma duração literal aqui dentro, ela
     não passa em silêncio.
     ──────────────────────────────────────────────────────────────── */
  @media (prefers-reduced-motion: reduce) {
    .app .rotas-aba,
    .app .rota-cartao,
    .app .inspecao-item,
    .app .ficha-campo-entrada,
    .app .ficha-biblioteca-item,
    .app .rota-sugestao-btn {
      transition: none;
    }
  }

  /* ── Acionamento: as quatro peças escolhidas ──
     A seção não entra no contador das três seções da ficha, e por isso o título
     dela é `.ficha-bloco-titulo`: o motor, o redutor e os acoplamentos vêm de
     outro documento — a planilha calculadora —, não da Ficha de
     Dimensionamento que alguém assina.

     Cada peça é um bloco de rótulo e valor, e o valor é o registro: sai em
     monoespaçada tabular para que 293 HP e 1143 kg alinhem casa por casa
     quando as quatro peças ficam lado a lado. */
  .app .ficha-acionamento {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(240px, 100%), 1fr));
    gap: var(--rule-hair);
    margin: var(--sp-4);
    border: var(--rule-hair) solid var(--console-line);
    background: var(--console-line);
  }
  .app .acionamento-peca {
    min-width: 0;
    padding: var(--sp-3) var(--sp-4);
    background: var(--console-panel-2);
  }
  /* Peça não escolhida é pendência de cadastro, não classe de risco: hachura e
     régua, como o cadastro divergente da malha. A frase dentro do bloco diz o
     que falta — sem ela, o vão pareceria peça sem nome. */
  .app .acionamento-peca.sem-escolha {
    background-image: var(--hatch);
    box-shadow: inset 0 calc(-1 * var(--rule-body)) 0 var(--console-line-strong);
  }
  .app .acionamento-peca > header {
    display: flex;
    flex-wrap: wrap;
    gap: var(--sp-2) var(--sp-3);
    align-items: baseline;
    justify-content: space-between;
    padding-bottom: var(--sp-2);
    border-bottom: var(--rule-hair) solid var(--console-line);
  }
  .app .acionamento-peca h3 {
    margin: 0;
    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;
  }
  /* A identificação da peça é o que se leva para a cotação: fica no peso do
     valor, e não no do rótulo. */
  .app .acionamento-peca > header > span {
    color: var(--console-text);
    font-family: var(--font-value);
    font-size: var(--t-value);
    font-variant-numeric: tabular-nums;
  }
  .app .acionamento-peca > p {
    margin: var(--sp-2) 0 0;
    color: var(--console-muted);
    font-size: var(--t-sm);
    line-height: var(--lh-body);
  }
  .app .acionamento-dados {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, auto);
    gap: 0;
    margin: 0;
  }
  .app .acionamento-dados dt,
  .app .acionamento-dados dd {
    margin: 0;
    padding: var(--sp-1) 0;
    border-bottom: var(--rule-hair) solid var(--console-line);
  }
  .app .acionamento-dados dt {
    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 .acionamento-dados dd {
    color: var(--console-text);
    font-family: var(--font-value);
    font-size: var(--t-sm);
    font-variant-numeric: tabular-nums;
    text-align: right;
    white-space: nowrap;
  }
  .app .acionamento-folga {
    margin: var(--sp-2) 0 0;
    color: var(--console-muted);
    font-family: var(--font-value);
    font-size: var(--t-micro);
    font-variant-numeric: tabular-nums;
  }
  /* O aviso é o único lugar com tinta nesta seção, e ele a merece: ou a peça
     gira acima da rotação que admite, ou o caderno de origem escolheria um
     tamanho abaixo do exigido. As duas coisas quebram equipamento. */
  .app .acionamento-aviso {
    margin: var(--sp-2) 0 0;
    padding-inline-start: var(--sp-3);
    border-inline-start: var(--rule-heavy) solid var(--warning);
    color: var(--console-text);
    font-size: var(--t-sm);
    line-height: var(--lh-body);
  }
  .app .acionamento-memoria {
    display: grid;
    gap: var(--sp-3);
    margin: var(--sp-4);
  }
  .app .acionamento-memoria-bloco > span {
    display: block;
    margin-bottom: var(--sp-1);
    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 .acionamento-memoria-bloco ul {
    display: grid;
    gap: var(--sp-1);
    margin: 0;
    padding: 0;
    list-style: none;
  }
  .app .acionamento-memoria-bloco li {
    padding: var(--sp-1) var(--sp-3);
    border-inline-start: 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;
    line-height: var(--lh-body);
  }

  /* ── Trajetória de descarga ──
     O desenho é a única figura deste sistema que não é tabela nem régua, e ele
     obedece à mesma regra: sem tinta. As três fibras do material se distinguem
     por traço — cheio no centro de gravidade, tracejado no topo, pontilhado na
     face de baixo —, o que atravessa o preto e branco de uma impressora de mina
     e o daltonismo de quem lê.

     O sistema de coordenadas do SVG está em milímetros de equipamento, com o
     centro do tambor na origem. Por isso `vector-effect: non-scaling-stroke` em
     tudo que é linha: sem ele, uma espessura de 2 seria 2 mm de desenho, que
     num quadro de três metros de largura desaparece. */
  .app .traj-figura {
    margin: var(--sp-4);
    padding: var(--sp-3);
    border: var(--rule-hair) solid var(--console-line);
    background: var(--console-panel-2);
  }
  .app .traj-figura svg {
    display: block;
    width: 100%;
    height: auto;
    max-height: 60vh;
    overflow: visible;
  }
  .app .traj-figura :is(path, line, circle) {
    fill: none;
    vector-effect: non-scaling-stroke;
  }
  /* O eixo do tambor é referência, não informação: fica na régua mais fina que
     o arquivo tem. */
  .app .traj-eixo {
    stroke: var(--console-line);
    stroke-width: 1;
    stroke-dasharray: 8 6;
  }
  .app .traj-tambor {
    stroke: var(--console-line-strong);
    stroke-width: 2;
  }
  .app .traj-correia {
    stroke: var(--console-line-strong);
    stroke-width: 2;
  }
  .app .traj-material {
    stroke: var(--console-text);
    stroke-width: 2;
    stroke-linecap: round;
  }
  .app .traj-cg {
    stroke-width: 3;
  }
  .app .traj-topo {
    stroke-dasharray: 10 7;
  }
  .app .traj-baixo {
    stroke-dasharray: 2 5;
  }
  /* A marca do alcance é cota, e cota se lê no valor: a linha é fina e o rótulo
     vem em condensada versal, como todo rótulo deste sistema. */
  .app .traj-marca line {
    stroke: var(--console-muted);
    stroke-width: 1;
  }
  .app .traj-marca text {
    fill: var(--console-muted);
    font-family: var(--font-label);
    font-size: 52px;
    font-stretch: var(--stretch-label);
    font-weight: 700;
    letter-spacing: var(--track-label);
    text-anchor: middle;
    text-transform: uppercase;
  }
  .app .traj-figura figcaption {
    margin-top: var(--sp-3);
    max-width: var(--measure);
    color: var(--console-muted);
    font-size: var(--t-micro);
    line-height: var(--lh-body);
  }
  /* ── Diagrama da malha ──
     A malha volta a ser desenho: caixa por equipamento, linha por ligação.
     A caixa é console como o resto da tela; a faixa à esquerda é a única cor,
     e é classe de risco (a última inspeção). Fluxo e alimentação elétrica se
     distinguem por traço, não por tinta: linha cheia com seta é material
     andando, tracejada é energia. Cadastro a conferir é hachura, como em todo
     o módulo. */
  .app .malha-modo {
    display: flex;
    width: max-content;
    border: var(--rule-hair) solid var(--console-line);
    border-left: 0;
    background: var(--console-panel-2);
  }
  .app .dg-host {
    min-width: 0;
  }
  .app .dg-carregando {
    margin: 0;
    padding: var(--sp-5);
    color: var(--console-muted);
    border: var(--rule-hair) solid var(--console-line);
  }
  /* Coluna única com piso zero: sem isto a barra e a área tomavam a largura
     do próprio conteúdo (413 px numa tela de 390) e o corpo cortava o resto. */
  .app .dg {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: var(--sp-3);
    min-width: 0;
  }
  .app .dg > * {
    min-width: 0;
  }
  .app .dg-barra {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--sp-2) var(--sp-4);
  }
  .app .dg-grupo {
    flex-wrap: wrap;
  }
  .app .dg-grupo {
    display: flex;
    align-items: center;
    gap: var(--sp-1);
  }
  .app .dg-zoom {
    min-width: 3.5rem;
    color: var(--console-text);
    font-family: var(--font-value);
    font-size: var(--t-sm);
    font-variant-numeric: tabular-nums;
    text-align: center;
  }
  .app .dg-modo {
    min-height: 36px;
    padding: 0 var(--sp-3);
    border: var(--rule-hair) solid var(--console-line);
    color: var(--console-muted);
    background: transparent;
    font: 700 var(--t-label) / 1.2 var(--font-label);
    letter-spacing: var(--track-label);
    text-transform: uppercase;
    cursor: pointer;
  }
  /* Ferramenta escolhida é "você está aqui", não autorização: régua neutra,
     como a aba ativa. */
  .app .dg-modo[aria-pressed='true'] {
    color: var(--console-text);
    background: var(--void-3);
    box-shadow: inset 0 calc(-1 * var(--rule-heavy)) 0 var(--console-text);
  }
  .app .dg-modo:disabled {
    cursor: not-allowed;
    border-style: dashed;
  }
  .app .dg-localizar {
    display: flex;
    gap: var(--sp-1);
    min-width: 0;
  }
  .app .dg-localizar .form-control {
    width: 11rem;
    max-width: 100%;
    min-width: 0;
    min-height: 36px;
  }
  .app .dg-status {
    margin: 0 0 0 auto;
    color: var(--console-muted);
    font-size: var(--t-sm);
  }
  .app .dg-aviso {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--sp-2) var(--sp-4);
    padding: var(--sp-3) var(--sp-4);
    /* Régua de atenção no topo, na largura inteira — a lateral é o tique de
       cartão gerado que o DESIGN.md proíbe pelo nome. */
    border: var(--rule-hair) solid var(--console-line);
    border-top: var(--rule-heavy) solid var(--warning);
    background: var(--console-panel-2);
    color: var(--console-text);
  }
  .app .dg-aviso[hidden] {
    display: none;
  }
  .app .dg-aviso p {
    flex: 1 1 24rem;
    margin: 0;
    font-size: var(--t-sm);
    line-height: var(--lh-body);
  }
  .app .dg-corpo {
    display: grid;
    gap: var(--sp-4);
    min-width: 0;
  }
  @media (min-width: 1024px) {
    .app .dg-corpo {
      grid-template-columns: minmax(0, 1fr) minmax(0, 20rem);
      align-items: start;
    }
  }
  .app .dg-area {
    position: relative;
    height: min(72vh, 760px);
    min-height: 420px;
    overflow: hidden;
    border: var(--rule-hair) solid var(--console-line);
    background-color: var(--void-2);
    cursor: grab;
    touch-action: none;
    user-select: none;
  }
  .app .dg-area:focus-visible {
    outline: var(--rule-body) solid var(--console-text);
    outline-offset: -2px;
  }
  .app .dg-area.dg-navegando {
    cursor: grabbing;
  }
  .app .dg-area[data-modo='fluxo'],
  .app .dg-area[data-modo='eletrica'] {
    cursor: crosshair;
  }
  .app .dg-svg {
    display: block;
    width: 100%;
    height: 100%;
  }

  .app .dg-no {
    cursor: pointer;
  }
  .app .dg-area:not([data-modo='mover']) .dg-no {
    cursor: crosshair;
  }
  .app .dg-no-caixa {
    fill: var(--console-panel);
    stroke: var(--console-line-strong);
    stroke-width: 1;
  }
  .app .dg-no--subestacao .dg-no-caixa {
    fill: var(--console-panel-2);
    stroke: var(--console-text);
    stroke-width: 2;
  }
  .app .dg-no--equipamento .dg-no-caixa,
  .app .dg-no--conferir .dg-no-caixa {
    stroke-dasharray: 5 3;
  }
  .app .dg-no-hachura {
    fill: url(#dgHachura);
    pointer-events: none;
  }
  .app .dg-hachura-traco {
    fill: var(--console-line-strong);
  }
  .app .dg-no:hover .dg-no-caixa {
    stroke: var(--console-text);
  }
  .app .dg-no--sel .dg-no-caixa {
    stroke: var(--console-text);
    stroke-width: 3;
  }
  .app .dg-no--origem .dg-no-caixa {
    stroke: var(--console-text);
    stroke-width: 3;
    stroke-dasharray: 8 4;
  }
  /* Fora do filtro: some para o fundo, mas continua lá, porque a ligação que
     atravessa o filtro precisa das duas pontas para fazer sentido. */
  .app .dg-no--apagado {
    opacity: 0.28;
  }
  .app .dg-no-faixa {
    fill: var(--console-line);
  }
  .app .dg-sit--liberado .dg-no-faixa {
    fill: var(--success);
  }
  .app .dg-sit--atencao .dg-no-faixa {
    fill: var(--warning);
  }
  .app .dg-sit--impedido .dg-no-faixa {
    fill: var(--danger);
  }
  .app .dg-no-tag {
    fill: var(--console-text);
    font-family: var(--font-value);
    font-size: 16px;
    font-weight: 700;
  }
  .app .dg-no-linha {
    fill: var(--console-muted);
    font-size: 12.5px;
  }
  .app .dg-no-sit {
    fill: var(--console-text);
    font-family: var(--font-label);
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.05em;
    text-transform: uppercase;
  }
  .app .dg-sit--semInspecao .dg-no-sit {
    fill: var(--console-muted);
  }

  .app .dg-lig {
    cursor: pointer;
  }
  .app .dg-lig-toque {
    fill: none;
    stroke: transparent;
    stroke-width: 14;
  }
  .app .dg-lig-linha {
    fill: none;
    pointer-events: none;
  }
  .app .dg-lig--fluxo .dg-lig-linha {
    stroke: var(--console-text);
    stroke-width: 2.25;
    stroke-linejoin: round;
  }
  .app .dg-lig--eletrica .dg-lig-linha {
    stroke: var(--console-muted);
    stroke-width: 1.5;
    stroke-dasharray: 1 5;
    stroke-linecap: round;
    stroke-linejoin: round;
  }
  .app .dg-lig:hover .dg-lig-linha,
  .app .dg-lig--sel .dg-lig-linha {
    stroke-width: 4;
  }
  .app .dg-lig--apagada {
    opacity: 0.2;
  }
  .app .dg-seta--fluxo {
    fill: var(--console-text);
  }
  .app .dg-seta--eletrica {
    fill: var(--console-muted);
  }
  .app .dg-previa {
    fill: none;
    stroke: var(--console-text);
    stroke-width: 2;
    stroke-dasharray: 4 4;
    pointer-events: none;
  }
  .app .dg-previa[hidden] {
    display: none;
  }

  /* ── Fluxograma (13/10/2026): faixas, leitura de longe, foco e minimapa ── */
  .app .dg-faixa-fundo {
    fill: var(--void-3);
    fill-opacity: 0.5;
    stroke: var(--console-line);
    stroke-width: 1;
  }
  .app .dg-faixa-titulo {
    fill: var(--console-text);
    font-family: var(--font-label);
    font-size: 15px;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
  }
  .app .dg-faixa-qtd {
    fill: var(--console-muted);
    font-weight: 400;
    letter-spacing: 0;
    text-transform: none;
  }
  /* A subestação é a cabeça da faixa: caixa cheia, régua grossa. */
  .app .dg-no--subestacao .dg-no-tag {
    font-size: 18px;
  }
  .app .dg-no-tag-longe {
    display: none;
    fill: var(--console-text);
    font-family: var(--font-value);
    font-size: 44px;
    font-weight: 700;
  }
  .app .dg-longe .dg-no-tag,
  .app .dg-longe .dg-no-linha,
  .app .dg-longe .dg-no-sit {
    display: none;
  }
  .app .dg-longe .dg-no-tag-longe {
    display: inline;
  }
  .app .dg-longe .dg-faixa-titulo {
    font-size: 34px;
  }
  .app .dg-longe .dg-faixa-qtd {
    display: none;
  }
  /* Ponteiro sobre uma caixa: acendem ela, as vizinhas e as ligações entre
     elas; o resto recua. Só opacidade anima. */
  .app .dg-no,
  .app .dg-lig {
    transition: opacity var(--dur-saida, 150ms) var(--curva-saida, ease-out);
  }
  .app .dg-foco .dg-lig:not(.dg-lig--foco) {
    opacity: 0.12;
  }
  .app .dg-foco .dg-no:not(.dg-no--foco) {
    opacity: 0.4;
  }
  .app .dg-lig--foco .dg-lig-linha {
    stroke-width: 3.5;
  }
  .app .dg-lig--eletrica.dg-lig--foco .dg-lig-linha {
    stroke: var(--console-text);
  }
  @media (prefers-reduced-motion: reduce) {
    .app .dg-no,
    .app .dg-lig {
      transition: none;
    }
  }
  .app .dg-mini {
    position: absolute;
    right: var(--sp-3);
    bottom: var(--sp-3);
    width: 216px;
    height: 140px;
    border: var(--rule-hair) solid var(--console-line-strong);
    background: var(--console-panel);
    box-shadow: 0 6px 18px rgba(0, 0, 0, 0.35);
    cursor: pointer;
    touch-action: none;
  }
  .app .dg-mini-no {
    fill: var(--console-line-strong);
  }
  .app .dg-mini-no--subestacao {
    fill: var(--console-text);
  }
  .app .dg-mini-vista {
    fill: var(--console-text);
    fill-opacity: 0.08;
    stroke: var(--console-text);
    stroke-width: 2;
    vector-effect: non-scaling-stroke;
  }
  @media (max-width: 640px) {
    .app .dg-mini {
      width: 148px;
      height: 96px;
    }
  }

  .app .dg-lateral {
    display: grid;
    align-content: start;
    gap: var(--sp-4);
    min-width: 0;
  }
  .app .dg-lateral-vazia h2,
  .app .dg-form h2 {
    margin: 0 0 var(--sp-2);
    color: var(--console-text);
    font-size: var(--t-body);
  }
  .app .dg-lateral-vazia p {
    margin: 0 0 var(--sp-3);
    color: var(--console-muted);
    font-size: var(--t-sm);
    line-height: var(--lh-body);
  }
  .app .dg-sit-linha {
    display: flex;
    align-items: center;
    gap: var(--sp-2);
    margin: 0;
    color: var(--console-text);
    font-size: var(--t-sm);
  }
  .app .dg-sit-marca {
    width: 12px;
    height: 12px;
    flex: 0 0 auto;
    border: var(--rule-hair) solid var(--console-line-strong);
  }
  .app .dg-sit--liberado .dg-sit-marca {
    background: var(--success);
  }
  .app .dg-sit--atencao .dg-sit-marca {
    background: var(--warning);
  }
  .app .dg-sit--impedido .dg-sit-marca {
    background: var(--danger);
  }
  .app .dg-lista {
    margin: var(--sp-1) 0 0;
    padding: 0;
    list-style: none;
    display: grid;
    gap: var(--sp-1);
    color: var(--console-text);
    font-size: var(--t-sm);
  }
  .app .dg-link {
    min-height: 24px;
    padding: 0;
    border: 0;
    color: var(--console-text);
    background: none;
    font-family: var(--font-value);
    font-weight: 700;
    text-decoration: underline;
    text-underline-offset: 3px;
    cursor: pointer;
  }
  .app .dg-ligacao-texto {
    margin: 0;
    color: var(--console-text);
    line-height: var(--lh-body);
  }
  .app .dg-acoes {
    display: flex;
    flex-wrap: wrap;
    gap: var(--sp-2);
  }
  .app .dg-form {
    display: grid;
    gap: var(--sp-3);
  }
  .app .dg-form .form-group {
    margin: 0;
  }
  .app .dg-form-grade {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--sp-3);
  }
  .app .dg-form-erro {
    margin: 0;
    padding-inline-start: var(--sp-3);
    border-inline-start: var(--rule-heavy) solid var(--danger);
    color: var(--console-text);
    font-size: var(--t-sm);
  }
  .app .dg-form-erro[hidden] {
    display: none;
  }

  .app .dg-rodape {
    display: grid;
    gap: var(--sp-2);
  }
  .app .dg-legenda {
    display: flex;
    flex-wrap: wrap;
    gap: var(--sp-2) var(--sp-4);
    margin: 0;
    padding: 0;
    list-style: none;
    color: var(--console-muted);
    font-size: var(--t-sm);
  }
  .app .dg-legenda li {
    display: inline-flex;
    align-items: center;
    gap: var(--sp-2);
  }
  .app .dg-leg {
    width: 14px;
    height: 14px;
    border: var(--rule-hair) solid var(--console-line-strong);
    background: var(--console-panel);
  }
  .app .dg-leg--liberado {
    background: var(--success);
  }
  .app .dg-leg--atencao {
    background: var(--warning);
  }
  .app .dg-leg--impedido {
    background: var(--danger);
  }
  .app .dg-leg--conferir {
    border-style: dashed;
    background-image: var(--hatch);
  }
  .app .dg-leg--faixa {
    width: 22px;
    background: var(--void-3);
    border-color: var(--console-line);
  }
  .app .dg-leg-linha {
    width: 28px;
    height: 0;
  }
  .app .dg-leg-linha--fluxo {
    border-top: 3px solid var(--console-text);
  }
  .app .dg-leg-linha--eletrica {
    border-top: 2px dotted var(--console-muted);
  }
  .app .dg-ajuda {
    margin: 0;
    color: var(--console-muted);
    font-size: var(--t-sm);
  }
}

/* ════════════════════════════════════════════════════════════════════
   6. A FOLHA — a ficha de avaliação impressa

   A avaliação de correia não termina na tela: ela é assinada, arquivada e
   cobrada. Na impressão o mundo vira o do papel, exatamente como o bloco
   "A FOLHA" do relatório diário faz em styles.css.

   Três decisões que este bloco toma:

   1. O fundo é BRANCO de impressora, e não `--stock`. O cartão bege é a
      superfície da tela; imprimir bege gasta tinta e derruba o contraste do
      que vai ser lido sob luz de escritório. É a mesma escolha de `A FOLHA`.

   2. Nada de `!important`. Este arquivo é carregado depois de styles.css e
      as regras abaixo têm especificidade igual ou maior que as regras de
      console que elas precisam vencer — a ordem desempata sozinha. O
      `!important` do bloco de impressão de styles.css existe porque aquelas
      regras vinham ANTES das regras de tela no mesmo arquivo; aqui não vêm.

   3. A hachura sai. Ela é feita de linhas claras sobre o escuro e some no
      papel branco; no lugar dela ficam a régua pontilhada e a palavra escrita,
      que atravessam o preto e branco de uma impressora de mina.
   ════════════════════════════════════════════════════════════════════ */
@media print {
  /* Filtro, aba e botão são ferramenta de tela. No papel eles ocupariam a
     folha dizendo ao leitor para clicar em coisa nenhuma.
     A biblioteca de fichas entra na mesma conta, e por um motivo mais forte:
     ela é a NAVEGAÇÃO entre avaliações. A folha impressa é uma avaliação, com
     um equipamento e um cenário; a lista das outras doze ao lado dela só
     serviria para alguém assinar a errada. */
  .app .rotas-abas,
  .app .malha-filtros,
  .app .rotas-module .toolbar,
  .app .ficha-module .toolbar,
  .app .rotas-module .btn,
  .app .ficha-module .btn,
  .app .ficha-biblioteca,
  .app .ficha-cabecalho-acoes,
  .app .rota-passo-acoes,
  .app .rota-sugestao,
  .app .malha-modo,
  .app .dg-barra,
  .app .dg-aviso,
  .app .dg-ajuda {
    display: none;
  }

  /* ── A situação que não foi escolhida não existe no papel ──
     Em tela os quatro botões são a pergunta; no papel só a resposta é
     registro. Imprimir as quatro deixaria a folha assinada dizendo quatro
     coisas ao mesmo tempo sobre o mesmo item — e uma folha assinada que
     admite quatro leituras não registra nada. */
  .app .inspecao-botao:not(.ativo) {
    display: none;
  }

  /* A folha não disputa largura com a coluna da tela: no papel a medida quem
     dá é a página. */
  .app .ficha-documento {
    max-width: none;
  }

  .app .rotas-module,
  .app .ficha-module,
  .app .ficha-documento,
  .app .ficha-secao,
  .app .ficha-secao-head,
  .app .ficha-veredito,
  .app .ficha-comparar,
  .app .ficha-comparar > *,
  .app .ficha-memoria,
  .app .ficha-avisos,
  .app .rota-cartao,
  .app .rota-lista,
  .app .rota-passo,
  .app .rota-sequencia.editavel,
  .app .rota-sequencia.editavel > .rota-passo,
  .app .inspecao-bloco,
  .app .inspecao-itens,
  .app .inspecao-item,
  .app .inspecao-tc,
  .app .inspecao-critico,
  .app .historico-lista,
  .app .historico-item,
  .app .historico-colunas,
  .app .estatistica-linha,
  .app .estatistica-barra,
  .app .rotas-head,
  .app .rotas-conteudo,
  .app .rotas-resumo,
  .app .rotas-resumo-item,
  .app .malha-corpo,
  .app .malha-marca,
  .app .tc-detalhe,
  .app .tc-detalhe-head,
  .app .tc-detalhe-grade,
  .app .tc-detalhe-campo,
  .app .tc-divergencia,
  .app .tc-fluxo,
  .app .rota-cartao-metricas,
  .app .rota-cartao-metricas > * {
    background: white;
    background-image: none;
    color: var(--ink);
    box-shadow: none;
  }

  /* As réguas viram tinta preta: cinza de console sobre papel branco fica em
     torno de 1,5:1 e some na primeira fotocópia. */
  .app .ficha-secao,
  .app .ficha-veredito,
  .app .ficha-comparar,
  .app .ficha-avisos,
  .app .rota-cartao,
  .app .rota-passo,
  .app .rota-sequencia.editavel,
  .app .inspecao-itens,
  .app .inspecao-critico,
  .app .tc-divergencia,
  .app .rotas-resumo,
  .app .malha-marca,
  .app .tc-detalhe-grade,
  .app .estatistica-barra,
  .app .historico-lista {
    border-color: var(--ink);
  }
  .app .ficha-linha,
  .app .inspecao-item,
  .app .historico-item,
  .app .ficha-perfil :is(th, td),
  .app .ficha-memoria,
  .app .ficha-memoria-secao,
  .app .ficha-secao h3,
  .app .estatistica-linha,
  .app .historico-numeros > * + *,
  .app .rota-cartao > footer,
  .app .tc-detalhe-nota,
  .app .tc-fluxo,
  .app .malha-linha.divergente > td {
    border-color: var(--rule-hair-ink);
  }
  .app .ficha-cabecalho {
    border-bottom-color: var(--ink);
  }
  .app .ficha-secao-titulo,
  .app .ficha-bloco-titulo,
  .app .ficha-secao-head,
  .app .rotas-head,
  .app .tc-detalhe-head,
  .app .ficha-perfil th {
    border-bottom-color: var(--ink);
  }

  /* Rótulo e valor mantêm os dois registros no papel — é o que faz a folha
     impressa ser o mesmo documento que estava na tela. */
  .app .ficha-linha > :first-child,
  .app .ficha-secao-titulo,
  .app .ficha-bloco-titulo,
  .app .ficha-secao h3,
  .app .ficha-nota,
  .app .ficha-memoria-secao,
  .app .ficha-perfil th,
  .app .rotas-head p,
  .app .rotas-resumo-item > :first-child,
  .app .tc-detalhe-campo > :first-child,
  .app .tc-detalhe-head p,
  .app .tc-detalhe-nota,
  .app .tc-fluxo > span,
  .app .malha-marca,
  .app .inspecao-critico,
  .app .inspecao-item-texto small,
  .app .estatistica-linha > :first-child,
  .app .rota-cartao > header p,
  .app .rota-cartao-metricas > * > :first-child {
    color: var(--ink-2);
  }
  .app .ficha-linha > :first-child + *,
  .app .ficha-perfil td,
  .app .ficha-memoria-rotulo,
  .app .ficha-memoria-linha :is(code, strong),
  .app .malha-tabela td,
  .app .rotas-head :is(h2, h3),
  .app .rotas-resumo-item > :first-child + *,
  .app .tc-detalhe-campo > :first-child + *,
  .app .tc-detalhe-head h2,
  .app .tc-fluxo > p,
  .app .estatistica-linha > strong,
  .app .historico-numeros,
  .app .rota-cartao h3,
  .app .rota-cartao-metricas > * > :first-child + *,
  .app .ficha-cabecalho :is(h2, h3, code, output),
  .app .inspecao-tc strong {
    color: var(--ink);
  }
  /* A barra de reincidência mede quantidade: no papel ela vira campo cheio de
     tinta preta, que é o que sobrevive à fotocópia. */
  .app .estatistica-barra > * {
    background: var(--ink);
    -webkit-print-color-adjust: exact;
    print-color-adjust: exact;
  }
  .app .ficha-linha::before,
  .app .ficha-memoria-linha + .ficha-memoria-linha {
    border-bottom-color: var(--rule-hair-ink);
    border-top-color: var(--rule-hair-ink);
  }
  .app .ficha-cabecalho :is(code, output) {
    border-color: var(--ink);
  }

  /* O campo preenchido continua sendo o campo preenchido: a régua pesada
     embaixo é o que diz, no papel, onde alguém escreveu à mão. */
  .app .ficha-campo-entrada {
    border-bottom-color: var(--ink);
    background: white;
    color: var(--ink);
  }
  .app .ficha-campo-calculado {
    border-bottom-color: var(--rule-hair-ink);
    background-color: var(--stock-2);
    background-image: none;
    color: var(--ink);
    -webkit-print-color-adjust: exact;
    print-color-adjust: exact;
  }

  /* Classe de risco: a tarja sai na folha, e a palavra sai junto dela. As
     tintas de TARJA (`--risk-*-band`) são as saturadas, que é o uso certo —
     tarja é campo, não texto, e o piso dela é 3:1. */
  .app .ficha-veredito {
    border-top-width: var(--rule-band);
    -webkit-print-color-adjust: exact;
    print-color-adjust: exact;
  }
  .app .ficha-veredito.atende {
    border-top-color: var(--risk-clear-band);
  }
  .app .ficha-veredito.atencao {
    border-top-color: var(--risk-attention-band);
  }
  .app .ficha-veredito.naoAtende {
    border-top-color: var(--risk-blocked-band);
  }
  .app .ficha-veredito.atende strong {
    color: var(--risk-clear);
  }
  .app .ficha-veredito.atencao strong {
    color: var(--risk-attention);
  }
  .app .ficha-veredito.naoAtende strong {
    color: var(--risk-blocked);
  }

  /* A situação deixa de ser campo cheio e vira marca regrada: economiza tinta,
     sobrevive à impressora preto e branco e continua legível porque a palavra
     está escrita dentro. A classe vai na régua de topo. */
  .app .situacao-conforme,
  .app .situacao-atencao,
  .app .situacao-critico,
  .app .situacao-pendente,
  .app .situacao-naoAplicavel {
    border: var(--rule-hair) solid var(--ink);
    border-top-width: var(--rule-heavy);
    background: white;
    background-image: none;
    color: var(--ink);
    -webkit-print-color-adjust: exact;
    print-color-adjust: exact;
  }
  .app .situacao-conforme {
    border-top-color: var(--risk-clear-band);
  }
  .app .situacao-atencao {
    border-top-color: var(--risk-attention-band);
  }
  .app .situacao-critico {
    border-top-color: var(--risk-blocked-band);
  }
  .app .situacao-pendente {
    border-style: dotted;
    border-top-width: var(--rule-heavy);
  }

  /* A linha do histórico recebe a classe de risco no próprio elemento, e não
     numa marca dentro dela. No papel ela mantém a tarja na borda de entrada,
     como na tela: a folha impressa precisa ser lida do mesmo jeito que a tela
     foi lida, ou as duas deixam de ser o mesmo documento. */
  .app
    .historico-item:is(
      .situacao-conforme,
      .situacao-atencao,
      .situacao-critico,
      .situacao-pendente,
      .situacao-naoAplicavel
    ) {
    border: var(--rule-hair) solid var(--rule-hair-ink);
    border-inline-start: var(--rule-band) solid var(--ink);
  }
  .app .historico-item.situacao-conforme {
    border-inline-start-color: var(--risk-clear-band);
  }
  .app .historico-item.situacao-atencao {
    border-inline-start-color: var(--risk-attention-band);
  }
  .app .historico-item.situacao-critico {
    border-inline-start-color: var(--risk-blocked-band);
  }

  /* O desenho da trajetória vai para o papel como desenho técnico: fundo
     branco, traço preto, e as três fibras continuando distinguíveis pelo
     tracejado, que é o que sobrevive à fotocópia. */
  .app .traj-figura {
    background: transparent;
    border-color: var(--ink);
  }
  .app .traj-figura :is(.traj-material, .traj-correia, .traj-tambor) {
    stroke: var(--ink);
  }
  .app .traj-figura :is(.traj-eixo, .traj-marca line) {
    stroke: var(--rule-hair-ink);
  }
  .app .traj-marca text,
  .app .traj-figura figcaption {
    fill: var(--ink);
    color: var(--ink);
  }
  .app .traj-figura {
    break-inside: avoid;
  }

  /* O aviso do acionamento perde a tinta e fica com a régua: o que é registro é
     a palavra que o HTML escreve — o tamanho que a planilha imprimiria, a
     rotação excedida. E a peça não escolhida troca hachura por régua, porque
     hachura em impressora de mina vira mancha. */
  .app .acionamento-aviso {
    border-inline-start-color: var(--ink);
    color: var(--ink);
  }
  .app .acionamento-peca.sem-escolha {
    background-image: none;
    box-shadow: none;
    border-bottom: var(--rule-body) solid var(--ink);
  }
  .app .ficha-acionamento,
  .app .acionamento-peca {
    background: transparent;
    border-color: var(--ink);
  }
  .app .acionamento-dados dt,
  .app .acionamento-dados dd,
  .app .acionamento-peca > header {
    border-color: var(--rule-hair-ink);
    color: var(--ink);
  }

  /* O cadastro divergente continua marcado, sem cor: régua pesada embaixo da
     linha e a palavra que o HTML já escreve. */
  .app .malha-linha.divergente > td {
    background-image: none;
    border-bottom: var(--rule-body) solid var(--ink);
  }
  .app .rota-vencida {
    background-image: none;
    border-color: var(--ink);
    color: var(--ink-2);
  }

  /* O quadro que rola em tela precisa se abrir na folha: um `max-height` e um
     `overflow` que sobrevivam à impressão cortam a tabela na primeira página e
     escondem o resto sem avisar. Cabeçalho preso também não faz sentido em
     papel — ele volta a ser uma linha comum. */
  .app .table-wrap:has(.malha-tabela) {
    max-height: none;
    overflow: visible;
  }
  .app .malha-tabela th,
  .app .inspecao-tc {
    position: static;
    box-shadow: none;
    background: var(--stock-2);
    color: var(--ink);
    border-bottom: var(--rule-body) solid var(--ink);
    -webkit-print-color-adjust: exact;
    print-color-adjust: exact;
  }
  .app .malha-tabela th {
    text-align: left;
  }

  /* Nada de bloco partido ao meio pela quebra de página: uma seção da ficha,
     um cartão de rota ou um item do checklist cortado entre duas folhas é
     exatamente o defeito que faz alguém conferir a página errada. */
  .app .acionamento-peca,
  .app .acionamento-memoria-bloco,
  .app .ficha-secao,
  .app .ficha-veredito,
  .app .rota-cartao,
  .app .inspecao-bloco,
  .app .inspecao-item,
  .app .historico-item,
  .app .ficha-linha,
  .app .ficha-memoria-linha,
  .app .estatistica-linha,
  .app .tc-detalhe,
  .app .ficha-avisos,
  .app .tc-divergencia {
    break-inside: avoid;
  }
  /* Um título nunca fica sozinho no pé da página: a seção começa na folha em
     que o título está, ou o "3." aparece numa página e a seção 3 em outra. */
  .app .ficha-secao-titulo,
  .app .ficha-bloco-titulo,
  .app .ficha-secao-head,
  .app .ficha-secao h3,
  .app .rotas-head,
  .app .tc-detalhe-head {
    break-after: avoid;
  }
  /* A tabela do perfil pode atravessar páginas, mas o cabeçalho a acompanha. */
  .app .ficha-perfil thead {
    display: table-header-group;
  }
}
