/* -----------------------------------------------------------------
   Pulsio, folha de estilos do painel

   Sem dependencias externas: nem CDN, nem fontes remotas, nem bibliotecas.
   Tudo o que a pagina carrega sai deste servidor, que e o que permite a
   politica de seguranca de conteudos estrita do .htaccess.

   A linguagem visual e a do projecto de referencia da casa. Os nomes dos
   simbolos estao em portugues, como manda o CLAUDE.md, seccao 3.

   INDICE
     1.  Simbolos, tema claro
     2.  Tema escuro
     3.  Base e foco
     4.  Cabecalho e navegacao
     5.  Botoes
     6.  Cartoes
     7.  Tabelas
     8.  Etiquetas de estado e de gravidade
     9.  Notas e mensagens
     10. Formularios
     11. Listas de valores
     12. Medidores
     13. Registos: estado e abertura
     14. Estados vazios e paginacao
     15. Utilitarios
     16. Paginas autonomas
     17. Impressao
   ----------------------------------------------------------------- */

/* -----------------------------------------------------------------
   1. Simbolos, tema claro
   ----------------------------------------------------------------- */

:root {
    color-scheme: light dark;

    /* Superficies e texto */
    --fundo: #f5f5f7;
    --superficie: #ffffff;
    --superficie-recuada: #f4f4f6;
    --texto: #141416;
    --esbatido: #63636b;
    --tenue: #6d6d75;
    --borda: #c9c9cf;
    --borda-fraca: #e6e6ea;

    /* Acento */
    --acento: #2f6df6;
    --acento-lavado: #dfeaff;
    --acento-texto: #2456d6;
    --sobre-acento: #ffffff;

    /* Fundo da linha sob o rato, simbolo proprio e nao `--acento-lavado`.

       Sao coisas diferentes com a mesma cor por acaso: `--acento-lavado` e fundo
       de etiqueta e de botao tenue, onde o texto e escuro e saturado; a linha sob
       o rato leva por cima texto `--tenue` de 11 e 12 pixeis, e a 4,24:1 esse
       texto ficava abaixo do minimo da norma. Separando os dois simbolos, a
       linha clareia sem lavar as etiquetas. */
    --linha-sobre: #eef3ff;

    /* O VIDRO DA ETIQUETA DE AJUDA, que ACOMPANHA o tema em vez de o inverter.

       Esteve invertido -- etiqueta escura sobre painel claro -- durante uma hora, e o
       problema de inverter e o texto: uma etiqueta que troca o fundo tem de trocar
       tambem a cor das letras, e passa a precisar da sua propria paleta. Com o vidro a
       seguir o tema, a etiqueta usa as cores normais da pagina e nao ha segunda paleta
       para manter alinhada com a primeira.

       O alfa e o desfoque e que fazem o trabalho de a separar do que esta por baixo. A
       moldura e a mais fraca das duas, que e o suficiente para fechar a forma sem a
       fazer parecer uma caixa de dialogo. */
    --vidro-ajuda: rgba(255, 255, 255, .72);

    /* Vocabulario de estado do Pulsio, nos tons do Bootstrap.

       Uma palavra, uma cor, em todo o produto: `atencao` e o mesmo laranja num
       cartao da pagina inicial, numa etiqueta de ocorrencia e num filete da
       grelha de factos. Sem isso, a mesma palavra aparecia de duas cores em
       dois ecras, que e como se perde a leitura de relance.

       AS TONALIDADES SAO AS DO BOOTSTRAP; OS VALORES NAO SAO OS CRUS.

       O `$danger` #dc3545 do Bootstrap da 4,53 sobre branco e apenas 3,39
       sobre o proprio fundo lavado; o `$warning` #ffc107 da 1,63 e 1,47. Como
       texto de etiqueta nao se lem. O que se usa e o passo escuro de cada
       escala, escolhido para passar 4,5 SOBRE O FUNDO LAVADO, que e o sitio
       mais exigente onde a cor aparece:

           critico          #b02a37   6,50 sobre branco   4,86 sobre o lavado
           atencao          #a5520d   5,51                4,56
           sem-comunicacao  #8a6803   5,17                4,67
           saudavel         #146c43   6,45                4,97
           informacao       #0a58ca   6,44                4,90

       Os fundos lavados sao os passos 100 das escalas do Bootstrap, tal e qual.

       A cor sozinha continua a nao chegar: oito por cento dos homens nao
       distingue o vermelho do verde, e por isso cada etiqueta traz um simbolo
       em `::before`. */
    --saudavel: #146c43;
    --saudavel-lavado: #d1e7dd;
    --atencao: #a5520d;
    --atencao-lavado: #ffe5d0;
    --critico: #b02a37;
    --critico-lavado: #f8d7da;
    --sem-comunicacao: #8a6803;
    --sem-comunicacao-lavado: #fff3cd;
    --informacao: #0a58ca;
    --informacao-lavado: #cfe2ff;
    --sobre-critico: #ffffff;

    /* DUAS TONALIDADES QUE SO A AUDITORIA USA, e por isso nao tem lavado.

       As cinco de cima sao o vocabulario de ESTADO de um equipamento, e a
       auditoria nao lista estados: lista actos. Havia nove actos -- os sete do
       ciclo dos avisos ao cliente, a heranca de duplicado e a sessao retomada --
       a cair no cinzento da rotina por nao haver familia nenhuma que os
       descrevesse, e o cinzento da rotina e o mesmo do fluxo antigo dos codigos
       de activacao, que esta morto. Um recado entregue no computador de um
       cliente ontem lia-se com o peso de uma linha de 2026 que nunca volta a
       acontecer.

       `percurso` e o recado a caminho do cliente: escrito, entregue, aberto no
       ecra. Nao afirma nada -- ninguem respondeu ainda --, nao pede nada e nao
       e decisao de ninguem depois da primeira. Nenhuma das cinco diz isto.

       `acesso` e entrar no painel sem escrever a palavra-passe, pela lembranca
       da sessao. Nao e o verde da entrada com exito, que afirma que alguem
       provou quem era, nem o vermelho da falhada. E o terceiro caso, e e o que
       mais interessa ver de relance quando se desconfia de um acesso.

       Medidas com a formula do WCAG 2.1 sobre os tres fundos onde aparecem --
       superficie, linha par e linha sob o rato --, e nao estimadas:

           percurso  #6f42c1   6,51 sobre branco   5,93 na par   5,86 sob o rato
           acesso    #0b6473   6,81                6,20          6,12

       As tonalidades sao as do Bootstrap, como as outras cinco: o violeta e o
       `$purple` a 262 graus, e o ciano e o passo escuro da escala `$cyan`,
       a 189 graus. Ficam a 27 e a 33 graus do azul e do verde mais proximos,
       que e o suficiente para se distinguirem -- e, por nao chegar, cada
       familia leva tambem o seu simbolo. */
    --percurso: #6f42c1;
    --acesso: #0b6473;

    /* Elevacao: duas camadas por nivel, contacto curto mais difusao longa
       com espalhamento negativo. E o que impede que as sombras parecam
       caixas em vez de elevacao. */
    --sombra-1: 0 1px 2px rgba(20, 20, 24, .05), 0 8px 24px -18px rgba(20, 20, 24, .35);
    --sombra-2: 0 4px 10px -4px rgba(20, 20, 24, .10), 0 16px 36px -16px rgba(20, 20, 24, .35);
    --luz: inset 0 1px 0 rgba(255, 255, 255, 0);

    /* Escala de espacamento.

       Antes desta escala a mesma pagina usava 8, 9, 10, 11, 12, 13, 14, 16 e 18
       pixeis, escolhidos um a um. Nenhum desses numeros estava errado sozinho;
       juntos nao formam ritmo nenhum, e e disso que se faz a sensacao de coisa
       montada a pressa. Sao quatro degraus de 4px mais dois de 8px, e nada fora
       deles, com uma excepcao declarada: 2px, que serve para colar um rotulo ao
       seu valor e nao e espacamento de composicao. */
    --e0: 2px;
    --e1: 4px;
    --e2: 8px;
    --e3: 12px;
    --e4: 16px;
    --e5: 24px;
    --e6: 32px;

    /* Altura da linha de uma celula de tabela.

       Um valor em pixeis, e nao um multiplo: e o que permite que a primeira
       linha de todas as celulas da mesma fila caia no mesmo sitio, mesmo quando
       uma esta a 14px e a do lado a 12px. Ver a seccao 7. */
    --linha-celula: 20px;

    /* Raios */
    --raio-1: 8px;
    --raio-2: 10px;
    --raio-3: 14px;
    --raio-total: 999px;

    /* Escala tipografica, colada aos usos reais e nao a uma progressao. */
    --letra-xs: 11px;
    --letra-sm: 12px;
    --letra-md: 13px;
    --letra-base: 14px;
    --letra-lg: 15px;
    --letra-xl: 18px;
    --letra-titulo: 20px;
    --letra-xxl: 22px;
    --letra-numero: 30px;

    --mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;

    /* Halo de foco. O valor fixo e o mesmo que o `color-mix` de baixo produz, e
       existe para os navegadores que nao o tem. O tema escuro tem o SEU, escrito
       por extenso nos dois blocos da seccao 2: derivar por `color-mix` la deixava
       o halo azul-claro num fundo escuro em quem nao suporta a funcao. */
    --foco: rgba(47, 109, 246, .45);

    /* A SETA DO SELECT E' A UNICA QUE NAO E' MASCARA, e por isso continua
       declarada uma vez por tema. Um `<select>` desenha-a em `background-image`, e
       um `background-image` nao resolve `currentColor`; a mascara, que e' o que o
       resto do painel usa, recortaria o campo inteiro e nao so a seta. O DESENHO,
       esse, e' o mesmo `caret-down` do Phosphor que os `<details>` usam. */
    --seta: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256' fill='%235d6773'><path d='M216.49,104.49l-80,80a12,12,0,0,1-17,0l-80-80a12,12,0,0,1,17-17L128,159l71.51-71.52a12,12,0,0,1,17,17Z'/></svg>");
}

/* OITO `@supports` SAIRAM DESTA FOLHA A 22 DE SETEMBRO DE 2026, e este comentario e o
   unico rasto que ficou deles. Fica aqui, no primeiro que existia, e nao repetido oito
   vezes: a decisao e sobre o ficheiro e nao sobre este sitio.

   Envolviam `color-mix()` (duas vezes), `selector(:has(*))` (quatro), `backdrop-filter`
   e `min-height: 100dvh`. Nenhuma dessas capacidades distingue hoje navegador nenhum, e
   um teste que responde sempre que sim nao e uma proteccao: e uma linha que quem le tem
   de perceber para descobrir que nao protege nada.

   O QUE ACONTECE SEM ELES, medido caso a caso e nao presumido: um navegador a que falte
   a capacidade ignora a DECLARACAO (no `color-mix`, no `backdrop-filter` e no `100dvh`)
   ou descarta a REGRA inteira por o selector nao casar (nos quatro do `:has()`). Nos dois
   casos o resultado e o mesmo que o involucro dava.

   TRES FICARAM, E POR DUAS RAZOES DIFERENTES:

     `(grid-template-rows: subgrid)`, mais abaixo, porque o bloco dele tem SETE
     declaracoes e so uma precisa da capacidade. Sem o involucro, as outras seis
     aplicavam-se na mesma e deixavam um desenho a meio, que e pior do que nenhum.

     Os dois `not selector(::-webkit-scrollbar)` porque nao testam uma capacidade:
     distinguem o motor do navegador, e essa pergunta continua a ter duas respostas. */
:root {
    --foco: color-mix(in srgb, var(--acento) 45%, transparent);
}

/* -----------------------------------------------------------------
   2. Tema escuro

   AS CORES DE ESTADO NO ESCURO NAO SAO OS PASSOS 300 DO BOOTSTRAP, e a razao
   e medivel.

   O Bootstrap escuro usa o passo 300 de cada escala. Sobre esta superficie, o
   amarelo #ffda6a tem luminancia 0,724 e o vermelho #ea868f tem 0,365: o
   amarelo brilharia o DOBRO do vermelho, e a ordem por que os olhos apanham as
   coisas passaria a ser o contrario da gravidade. Na grelha de factos de um
   equipamento, o «Aviso» saltava a vista antes de «0,9 % livres».

   Cada tonalidade e escurecida ou clareada ate a escada de luminancia
   acompanhar a urgencia, sem sair da tonalidade do Bootstrap:

       critico          #f59aa2   luminancia 0,451   contraste 8,53
       atencao          #f0a05f              0,445              8,43
       sem-comunicacao  #cfae48              0,440              8,34
       saudavel         #75b798              0,399              7,65
       informacao       #6ea8fe              0,385              7,40

   Os tres primeiros ficam praticamente ao mesmo nivel de proposito: sao os tres
   que pedem alguma coisa, e o que os separa e a tonalidade. Os dois ultimos
   ficam abaixo, porque nao pedem nada.

   Declarado duas vezes com o mesmo corpo: uma para quem nao escolheu e
   tem o sistema em escuro, outra para quem escolheu explicitamente.

   Cinzentos NEUTROS, e nao azulados: o azul deve vir do acento e nada
   mais. A escada de luminancia e a mesma do tema claro, invertida.
   ----------------------------------------------------------------- */

@media (prefers-color-scheme: dark) {
    :root:not([data-tema="claro"]) {
        color-scheme: dark;

        --fundo: #0a0a0d;
        --superficie: #1d1e23;
        --superficie-recuada: #292a31;
        --texto: #ececed;
        --esbatido: #adadb6;
        --tenue: #9a9aa4;
        --borda: #757682;
        --borda-fraca: #383941;

        --acento: #4f8bff;
        --acento-lavado: #1e2c47;
        --acento-texto: #7aa9ff;
        --sobre-acento: #0b1020;
        --linha-sobre: #22304e;

        /* O halo de foco tambem tem valor proprio aqui, e era o unico dos 54
           simbolos que nao tinha. Num navegador sem `color-mix` -- e ha-os, e e
           por isso que o `@supports` existe -- o escuro ficava com o azul do tema
           claro a volta do que esta focado, que e o unico sinal que quem navega
           por teclado tem de onde esta. */
        --foco: rgba(79, 139, 255, .45);

        --vidro-ajuda: rgba(10, 10, 12, .5);

        --saudavel: #75b798;
        --saudavel-lavado: #0f2e20;
        --atencao: #f0a05f;
        --atencao-lavado: #3a2312;
        --critico: #f59aa2;
        --critico-lavado: #3a1418;
        --sem-comunicacao: #cfae48;
        --sem-comunicacao-lavado: #332701;
        --informacao: #6ea8fe;
        --informacao-lavado: #0f2544;
        --sobre-critico: #261110;

        /* As duas da auditoria. Ver o comentario longo no tema claro.

           A luminancia fica ABAIXO das cinco de cima, de proposito e pela mesma
           razao que a escada existe: nenhuma destas duas pede nada a ninguem, e
           uma cor que brilhe mais do que o critico apanha os olhos primeiro.

               percurso  #b795f0   luminancia 0,378   contraste 6,79
               acesso    #58b4c8              0,389              6,95

           Sobre a linha par e a linha sob o rato dao 5,83 e 5,35 o violeta,
           5,97 e 5,48 o ciano. Todos acima dos 4,5 da norma. */
        --percurso: #b795f0;
        --acesso: #58b4c8;

        /* No escuro a sombra nao e o que separa: preto sobre quase-preto nao se
           ve. O que separa e a borda, que subiu de contraste, e este fio de luz
           no bordo de cima, que e como um objecto real diz que esta levantado.
           As sombras ficam para dar peso, e nao para desenhar o limite. */
        --sombra-1: 0 1px 2px rgba(0, 0, 0, .40), 0 10px 26px -18px rgba(0, 0, 0, .90);
        --sombra-2: 0 4px 12px -4px rgba(0, 0, 0, .60), 0 18px 40px -16px rgba(0, 0, 0, .95);
        --luz: inset 0 1px 0 rgba(255, 255, 255, .08);

        --seta: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256' fill='%23adadb6'><path d='M216.49,104.49l-80,80a12,12,0,0,1-17,0l-80-80a12,12,0,0,1,17-17L128,159l71.51-71.52a12,12,0,0,1,17,17Z'/></svg>");
    }
}

:root[data-tema="escuro"] {
    color-scheme: dark;

    --fundo: #0a0a0d;
    --superficie: #1d1e23;
    --superficie-recuada: #292a31;
    --texto: #ececed;
    --esbatido: #adadb6;
    --tenue: #9a9aa4;
    --borda: #757682;
    --borda-fraca: #383941;

    --acento: #4f8bff;
    --acento-lavado: #1e2c47;
    --acento-texto: #7aa9ff;
    --sobre-acento: #0b1020;
    --linha-sobre: #22304e;

    /* Ver o comentario igual no bloco de cima, que vale para os dois. */
    --foco: rgba(79, 139, 255, .45);

    --vidro-ajuda: rgba(10, 10, 12, .5);

    --saudavel: #75b798;
    --saudavel-lavado: #0f2e20;
    --atencao: #f0a05f;
    --atencao-lavado: #3a2312;
    --critico: #f59aa2;
    --critico-lavado: #3a1418;
    --sem-comunicacao: #cfae48;
    --sem-comunicacao-lavado: #332701;
    --informacao: #6ea8fe;
    --informacao-lavado: #0f2544;
    --sobre-critico: #261110;

    /* As duas da auditoria. Ver o comentario igual no bloco de cima. */
    --percurso: #b795f0;
    --acesso: #58b4c8;

    /* No escuro a sombra nao e o que separa: preto sobre quase-preto nao se
       ve. O que separa e a borda, que subiu de contraste, e este fio de luz
       no bordo de cima, que e como um objecto real diz que esta levantado.
       As sombras ficam para dar peso, e nao para desenhar o limite. */
    --sombra-1: 0 1px 2px rgba(0, 0, 0, .40), 0 10px 26px -18px rgba(0, 0, 0, .90);
    --sombra-2: 0 4px 12px -4px rgba(0, 0, 0, .60), 0 18px 40px -16px rgba(0, 0, 0, .95);
    --luz: inset 0 1px 0 rgba(255, 255, 255, .08);

    --seta: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256' fill='%23adadb6'><path d='M216.49,104.49l-80,80a12,12,0,0,1-17,0l-80-80a12,12,0,0,1,17-17L128,159l71.51-71.52a12,12,0,0,1,17,17Z'/></svg>");
}

:root[data-tema="claro"] {
    color-scheme: light;
}

/* ------------------------------------------------------------------
   OS ICONES, E COMO E' QUE UM DELES CHEGA AO ECRA

   Sao do Phosphor, peso bold, v2.0.8, licenca MIT. Os ficheiros estao em
   `estatico/icones/` com a licenca ao lado, e o bloco aqui em baixo e'
   ESCRITO POR `testes/gerar_icones.py` a partir dessa pasta. Nao se edita
   a mao: o que se edita e' a pasta, e depois corre-se o guiao.

   NAO SE DESENHAM, RECORTAM-SE. A regra pinta um rectangulo com
   `background: currentColor` e usa o SVG como mascara por cima. A cor vem
   de quem o contem -- a etiqueta critica pinta-o de vermelho, a saudavel de
   verde -- e por isso NAO HA uma segunda copia por tema. E' a diferenca
   para a `--seta`, que tinha a cor codificada dentro do `data:` e por isso
   estava declarada tres vezes; passou a mascara e ficou numa.

   O QUE ISTO SUBSTITUIU foram caracteres de texto -- `content: "A0"` e
   companhia. Um caractere e' desenhado pela fonte que a maquina tiver, e o
   `A0` nao tem apresentacao textual garantida: o Windows e o Gmail
   trocavam-no pelo emoji a cores, com outro amarelo, outra linha de base e
   outro peso, ao lado de um `¹5` e de um `¹3` que continuavam
   monocromaticos. Tres desenhos de tres familias na mesma coluna.
   ------------------------------------------------------------------ */

/* INICIO DO BLOCO GERADO POR testes/gerar_icones.py */
:root {
    --icone-arrow-counter-clockwise: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256' fill='black'><path d='M228,128a100,100,0,0,1-98.66,100H128a99.39,99.39,0,0,1-68.62-27.29,12,12,0,0,1,16.48-17.45,76,76,0,1,0-1.57-109c-.13.13-.25.25-.39.37L54.89,92H72a12,12,0,0,1,0,24H24a12,12,0,0,1-12-12V56a12,12,0,0,1,24,0V76.72L57.48,57.06A100,100,0,0,1,228,128Z'/></svg>");
    --icone-arrow-left: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256' fill='black'><path d='M228,128a12,12,0,0,1-12,12H69l51.52,51.51a12,12,0,0,1-17,17l-72-72a12,12,0,0,1,0-17l72-72a12,12,0,0,1,17,17L69,116H216A12,12,0,0,1,228,128Z'/></svg>");
    --icone-arrow-right: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256' fill='black'><path d='M224.49,136.49l-72,72a12,12,0,0,1-17-17L187,140H40a12,12,0,0,1,0-24H187L135.51,64.48a12,12,0,0,1,17-17l72,72A12,12,0,0,1,224.49,136.49Z'/></svg>");
    --icone-arrow-square-out: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256' fill='black'><path d='M228,104a12,12,0,0,1-24,0V69l-59.51,59.51a12,12,0,0,1-17-17L187,52H152a12,12,0,0,1,0-24h64a12,12,0,0,1,12,12Zm-44,24a12,12,0,0,0-12,12v64H52V84h64a12,12,0,0,0,0-24H48A20,20,0,0,0,28,80V208a20,20,0,0,0,20,20H176a20,20,0,0,0,20-20V140A12,12,0,0,0,184,128Z'/></svg>");
    --icone-caret-down: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256' fill='black'><path d='M216.49,104.49l-80,80a12,12,0,0,1-17,0l-80-80a12,12,0,0,1,17-17L128,159l71.51-71.52a12,12,0,0,1,17,17Z'/></svg>");
    --icone-chart-line-up: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256' fill='black'><path d='M236,208a12,12,0,0,1-12,12H32a12,12,0,0,1-12-12V48a12,12,0,0,1,24,0v99l43.51-43.52a12,12,0,0,1,17,0L128,127l43-43H160a12,12,0,0,1,0-24h40a12,12,0,0,1,12,12v40a12,12,0,0,1-24,0V101l-51.51,51.52a12,12,0,0,1-17,0L96,129,44,181v15H224A12,12,0,0,1,236,208Z'/></svg>");
    --icone-chat-centered-dots: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256' fill='black'><path d='M216,36H40A20,20,0,0,0,20,56V184a20,20,0,0,0,20,20H97.23l13.62,22.29a20,20,0,0,0,34.25.08L158.77,204H216a20,20,0,0,0,20-20V56A20,20,0,0,0,216,36Zm-4,144H156.53a20,20,0,0,0-17.1,9.63L128,208.33l-11.41-18.67A20.1,20.1,0,0,0,99.47,180H44V60H212ZM88,120a16,16,0,1,1,16,16A16,16,0,0,1,88,120Zm48,0a16,16,0,1,1,16,16A16,16,0,0,1,136,120Z'/></svg>");
    --icone-check: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256' fill='black'><path d='M232.49,80.49l-128,128a12,12,0,0,1-17,0l-56-56a12,12,0,1,1,17-17L96,183,215.51,63.51a12,12,0,0,1,17,17Z'/></svg>");
    --icone-circle-dashed: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256' fill='black'><path d='M92.38,38.05A12,12,0,0,1,101,23.42a108,108,0,0,1,54,0,12,12,0,1,1-6,23.23,84.11,84.11,0,0,0-42,0A12,12,0,0,1,92.38,38.05ZM50.94,52.34a108.1,108.1,0,0,0-27,46.76,12,12,0,0,0,8.37,14.77,12.2,12.2,0,0,0,3.2.43,12,12,0,0,0,11.56-8.8,84,84,0,0,1,21-36.35A12,12,0,1,0,50.94,52.34Zm-3.88,98.14a12,12,0,0,0-23.12,6.42,108,108,0,0,0,27,46.78A12,12,0,0,0,68,186.85,84,84,0,0,1,47.06,150.48ZM149,209.35a84,84,0,0,1-42,0,12,12,0,1,0-6,23.23,108,108,0,0,0,54,0,12,12,0,1,0-6-23.23Zm74.72-67.22A12,12,0,0,0,209,150.5a84,84,0,0,1-21,36.35,12,12,0,0,0,17.12,16.82,108.19,108.19,0,0,0,27-46.77A12,12,0,0,0,223.71,142.13Zm-14.77-36.61a12,12,0,0,0,23.12-6.42,108,108,0,0,0-27-46.78A12,12,0,1,0,188,69.15,84,84,0,0,1,208.94,105.52Z'/></svg>");
    --icone-clipboard-text: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256' fill='black'><path d='M172,156a12,12,0,0,1-12,12H96a12,12,0,0,1,0-24h64A12,12,0,0,1,172,156Zm-12-52H96a12,12,0,0,0,0,24h64a12,12,0,0,0,0-24Zm60-56V216a20,20,0,0,1-20,20H56a20,20,0,0,1-20-20V48A20,20,0,0,1,56,28H90.53a51.88,51.88,0,0,1,74.94,0H200A20,20,0,0,1,220,48ZM128,36a28,28,0,0,0-27.71,24h55.42A28,28,0,0,0,128,36Zm68,16H178.59A52.13,52.13,0,0,1,180,64v8a12,12,0,0,1-12,12H88A12,12,0,0,1,76,72V64a52.13,52.13,0,0,1,1.41-12H60V212H196Z'/></svg>");
    --icone-clock: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256' fill='black'><path d='M128,20A108,108,0,1,0,236,128,108.12,108.12,0,0,0,128,20Zm0,192a84,84,0,1,1,84-84A84.09,84.09,0,0,1,128,212Zm68-84a12,12,0,0,1-12,12H128a12,12,0,0,1-12-12V72a12,12,0,0,1,24,0v44h44A12,12,0,0,1,196,128Z'/></svg>");
    --icone-copy: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256' fill='black'><path d='M216,28H88A12,12,0,0,0,76,40V76H40A12,12,0,0,0,28,88V216a12,12,0,0,0,12,12H168a12,12,0,0,0,12-12V180h36a12,12,0,0,0,12-12V40A12,12,0,0,0,216,28ZM156,204H52V100H156Zm48-48H180V88a12,12,0,0,0-12-12H100V52H204Z'/></svg>");
    --icone-cpu: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256' fill='black'><path d='M152,92H104a12,12,0,0,0-12,12v48a12,12,0,0,0,12,12h48a12,12,0,0,0,12-12V104A12,12,0,0,0,152,92Zm-12,48H116V116h24Zm92,0H220V116h12a12,12,0,0,0,0-24H220V56a20,20,0,0,0-20-20H164V24a12,12,0,0,0-24,0V36H116V24a12,12,0,0,0-24,0V36H56A20,20,0,0,0,36,56V92H24a12,12,0,0,0,0,24H36v24H24a12,12,0,0,0,0,24H36v36a20,20,0,0,0,20,20H92v12a12,12,0,0,0,24,0V220h24v12a12,12,0,0,0,24,0V220h36a20,20,0,0,0,20-20V164h12a12,12,0,0,0,0-24Zm-36,56H60V60H196Z'/></svg>");
    --icone-currency-eur: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256' fill='black'><path d='M192.94,189.66a12,12,0,0,1-.94,17A84,84,0,0,1,53.55,160H40a12,12,0,0,1,0-24H52V120H40a12,12,0,0,1,0-24H53.55A84,84,0,0,1,192,49.39a12,12,0,0,1-16,17.89A60,60,0,0,0,78.18,96H136a12,12,0,0,1,0,24H76v16h44a12,12,0,0,1,0,24H78.18A60,60,0,0,0,176,188.72,12,12,0,0,1,192.94,189.66Z'/></svg>");
    --icone-database: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256' fill='black'><path d='M196,35.52C177.62,25.51,153.48,20,128,20S78.38,25.51,60,35.52C39.37,46.79,28,62.58,28,80v96c0,17.42,11.37,33.21,32,44.48,18.35,10,42.49,15.52,68,15.52s49.62-5.51,68-15.52c20.66-11.27,32-27.06,32-44.48V80C228,62.58,216.63,46.79,196,35.52ZM204,128c0,17-31.21,36-76,36s-76-19-76-36v-8.46a88.9,88.9,0,0,0,8,4.94c18.35,10,42.49,15.52,68,15.52s49.62-5.51,68-15.52a88.9,88.9,0,0,0,8-4.94ZM128,44c44.79,0,76,19,76,36s-31.21,36-76,36S52,97,52,80,83.21,44,128,44Zm0,168c-44.79,0-76-19-76-36v-8.46a88.9,88.9,0,0,0,8,4.94c18.35,10,42.49,15.52,68,15.52s49.62-5.51,68-15.52a88.9,88.9,0,0,0,8-4.94V176C204,193,172.79,212,128,212Z'/></svg>");
    --icone-desktop-tower: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256' fill='black'><path d='M28,96v68a4,4,0,0,0,4,4h76a12,12,0,0,1,0,24h-8v12h8a12,12,0,0,1,0,24H68a12,12,0,0,1,0-24h8V192H32A28,28,0,0,1,4,164V96A28,28,0,0,1,32,68h76a12,12,0,0,1,0,24H32A4,4,0,0,0,28,96Zm152-8h24a12,12,0,0,0,0-24H180a12,12,0,0,0,0,24Zm0,36h24a12,12,0,0,0,0-24H180a12,12,0,0,0,0,24Zm72-76V208a20,20,0,0,1-20,20H152a20,20,0,0,1-20-20V48a20,20,0,0,1,20-20h80A20,20,0,0,1,252,48Zm-24,4H156V204h72ZM192,160a16,16,0,1,0,16,16A16,16,0,0,0,192,160Z'/></svg>");
    --icone-download-simple: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256' fill='black'><path d='M228,152v56a20,20,0,0,1-20,20H48a20,20,0,0,1-20-20V152a12,12,0,0,1,24,0v52H204V152a12,12,0,0,1,24,0Zm-108.49,8.49a12,12,0,0,0,17,0l40-40a12,12,0,0,0-17-17L140,123V40a12,12,0,0,0-24,0v83L96.49,103.51a12,12,0,0,0-17,17Z'/></svg>");
    --icone-envelope-simple: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256' fill='black'><path d='M224,44H32A12,12,0,0,0,20,56V192a20,20,0,0,0,20,20H216a20,20,0,0,0,20-20V56A12,12,0,0,0,224,44ZM193.15,68,128,127.72,62.85,68ZM44,188V83.28l75.89,69.57a12,12,0,0,0,16.22,0L212,83.28V188Z'/></svg>");
    --icone-eye: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256' fill='black'><path d='M251,123.13c-.37-.81-9.13-20.26-28.48-39.61C196.63,57.67,164,44,128,44S59.37,57.67,33.51,83.52C14.16,102.87,5.4,122.32,5,123.13a12.08,12.08,0,0,0,0,9.75c.37.82,9.13,20.26,28.49,39.61C59.37,198.34,92,212,128,212s68.63-13.66,94.48-39.51c19.36-19.35,28.12-38.79,28.49-39.61A12.08,12.08,0,0,0,251,123.13Zm-46.06,33C183.47,177.27,157.59,188,128,188s-55.47-10.73-76.91-31.88A130.36,130.36,0,0,1,29.52,128,130.45,130.45,0,0,1,51.09,99.89C72.54,78.73,98.41,68,128,68s55.46,10.73,76.91,31.89A130.36,130.36,0,0,1,226.48,128,130.45,130.45,0,0,1,204.91,156.12ZM128,84a44,44,0,1,0,44,44A44.05,44.05,0,0,0,128,84Zm0,64a20,20,0,1,1,20-20A20,20,0,0,1,128,148Z'/></svg>");
    --icone-file-text: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256' fill='black'><path d='M216.49,79.52l-56-56A12,12,0,0,0,152,20H56A20,20,0,0,0,36,40V216a20,20,0,0,0,20,20H200a20,20,0,0,0,20-20V88A12,12,0,0,0,216.49,79.52ZM160,57l23,23H160ZM60,212V44h76V92a12,12,0,0,0,12,12h48V212Zm112-80a12,12,0,0,1-12,12H96a12,12,0,0,1,0-24h64A12,12,0,0,1,172,132Zm0,40a12,12,0,0,1-12,12H96a12,12,0,0,1,0-24h64A12,12,0,0,1,172,172Z'/></svg>");
    --icone-floppy-disk: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256' fill='black'><path d='M222.14,77.17,178.83,33.86A19.86,19.86,0,0,0,164.69,28H48A20,20,0,0,0,28,48V208a20,20,0,0,0,20,20H208a20,20,0,0,0,20-20V91.31A19.86,19.86,0,0,0,222.14,77.17ZM164,204H92V156h72Zm40,0H188V152a20,20,0,0,0-20-20H88a20,20,0,0,0-20,20v52H52V52H163l41,41ZM164,80a12,12,0,0,1-12,12H96a12,12,0,0,1,0-24h56A12,12,0,0,1,164,80Z'/></svg>");
    --icone-funnel-simple: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256' fill='black'><path d='M204,128a12,12,0,0,1-12,12H64a12,12,0,0,1,0-24H192A12,12,0,0,1,204,128Zm28-60H24a12,12,0,0,0,0,24H232a12,12,0,0,0,0-24Zm-80,96H104a12,12,0,0,0,0,24h48a12,12,0,0,0,0-24Z'/></svg>");
    --icone-gauge: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256' fill='black'><path d='M209.88,77.83A115.19,115.19,0,0,0,128,44h-.41C63.85,44.22,12,96.76,12,161.13V184a20,20,0,0,0,20,20H224a20,20,0,0,0,20-20V160A115.25,115.25,0,0,0,209.88,77.83ZM220,180H127.32l46.44-65A12,12,0,1,0,154.24,101L97.82,180H36V161.13c0-1.72,0-3.43.14-5.13H56a12,12,0,0,0,0-24H40.62c10.91-33.39,40-58.52,75.38-63.21V88a12,12,0,0,0,24,0V68.8A92,92,0,0,1,215.66,132H200a12,12,0,0,0,0,24h19.9c.06,1.33.1,2.66.1,4Z'/></svg>");
    --icone-gear-six: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256' fill='black'><path d='M128,76a52,52,0,1,0,52,52A52.06,52.06,0,0,0,128,76Zm0,80a28,28,0,1,1,28-28A28,28,0,0,1,128,156Zm113.86-49.57A12,12,0,0,0,236,98.34L208.21,82.49l-.11-31.31a12,12,0,0,0-4.25-9.12,116,116,0,0,0-38-21.41,12,12,0,0,0-9.68.89L128,37.27,99.83,21.53a12,12,0,0,0-9.7-.9,116.06,116.06,0,0,0-38,21.47,12,12,0,0,0-4.24,9.1l-.14,31.34L20,98.35a12,12,0,0,0-5.85,8.11,110.7,110.7,0,0,0,0,43.11A12,12,0,0,0,20,157.66l27.82,15.85.11,31.31a12,12,0,0,0,4.25,9.12,116,116,0,0,0,38,21.41,12,12,0,0,0,9.68-.89L128,218.73l28.14,15.74a12,12,0,0,0,9.7.9,116.06,116.06,0,0,0,38-21.47,12,12,0,0,0,4.24-9.1l.14-31.34,27.81-15.81a12,12,0,0,0,5.85-8.11A110.7,110.7,0,0,0,241.86,106.43Zm-22.63,33.18-26.88,15.28a11.94,11.94,0,0,0-4.55,4.59c-.54,1-1.11,1.93-1.7,2.88a12,12,0,0,0-1.83,6.31L184.13,199a91.83,91.83,0,0,1-21.07,11.87l-27.15-15.19a12,12,0,0,0-5.86-1.53h-.29c-1.14,0-2.3,0-3.44,0a12.08,12.08,0,0,0-6.14,1.51L93,210.82A92.27,92.27,0,0,1,71.88,199l-.11-30.24a12,12,0,0,0-1.83-6.32c-.58-.94-1.16-1.91-1.7-2.88A11.92,11.92,0,0,0,63.7,155L36.8,139.63a86.53,86.53,0,0,1,0-23.24l26.88-15.28a12,12,0,0,0,4.55-4.58c.54-1,1.11-1.94,1.7-2.89a12,12,0,0,0,1.83-6.31L71.87,57A91.83,91.83,0,0,1,92.94,45.17l27.15,15.19a11.92,11.92,0,0,0,6.15,1.52c1.14,0,2.3,0,3.44,0a12.08,12.08,0,0,0,6.14-1.51L163,45.18A92.27,92.27,0,0,1,184.12,57l.11,30.24a12,12,0,0,0,1.83,6.32c.58.94,1.16,1.91,1.7,2.88A11.92,11.92,0,0,0,192.3,101l26.9,15.33A86.53,86.53,0,0,1,219.23,139.61Z'/></svg>");
    --icone-hard-drives: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256' fill='black'><path d='M208,36H48A20,20,0,0,0,28,56V200a20,20,0,0,0,20,20H208a20,20,0,0,0,20-20V56A20,20,0,0,0,208,36Zm-4,24v56H52V60ZM52,196V140H204v56ZM160,88a16,16,0,1,1,16,16A16,16,0,0,1,160,88Zm32,80a16,16,0,1,1-16-16A16,16,0,0,1,192,168Z'/></svg>");
    --icone-info: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256' fill='black'><path d='M108,84a16,16,0,1,1,16,16A16,16,0,0,1,108,84Zm128,44A108,108,0,1,1,128,20,108.12,108.12,0,0,1,236,128Zm-24,0a84,84,0,1,0-84,84A84.09,84.09,0,0,0,212,128Zm-72,36.68V132a20,20,0,0,0-20-20,12,12,0,0,0-4,23.32V168a20,20,0,0,0,20,20,12,12,0,0,0,4-23.32Z'/></svg>");
    --icone-list-bullets: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256' fill='black'><path d='M76,64A12,12,0,0,1,88,52H216a12,12,0,0,1,0,24H88A12,12,0,0,1,76,64Zm140,52H88a12,12,0,0,0,0,24H216a12,12,0,0,0,0-24Zm0,64H88a12,12,0,0,0,0,24H216a12,12,0,0,0,0-24ZM44,112a16,16,0,1,0,16,16A16,16,0,0,0,44,112Zm0-64A16,16,0,1,0,60,64,16,16,0,0,0,44,48Zm0,128a16,16,0,1,0,16,16A16,16,0,0,0,44,176Z'/></svg>");
    --icone-list-checks: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256' fill='black'><path d='M228,128a12,12,0,0,1-12,12H128a12,12,0,0,1,0-24h88A12,12,0,0,1,228,128ZM128,76h88a12,12,0,0,0,0-24H128a12,12,0,0,0,0,24Zm88,104H128a12,12,0,0,0,0,24h88a12,12,0,0,0,0-24ZM79.51,39.51,56,63l-7.51-7.52a12,12,0,0,0-17,17l16,16a12,12,0,0,0,17,0l32-32a12,12,0,0,0-17-17Zm0,64L56,127l-7.51-7.52a12,12,0,1,0-17,17l16,16a12,12,0,0,0,17,0l32-32a12,12,0,0,0-17-17Zm0,64L56,191l-7.51-7.52a12,12,0,1,0-17,17l16,16a12,12,0,0,0,17,0l32-32a12,12,0,0,0-17-17Z'/></svg>");
    --icone-lock-key: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256' fill='black'><path d='M208,76H180V56A52,52,0,0,0,76,56V76H48A20,20,0,0,0,28,96V208a20,20,0,0,0,20,20H208a20,20,0,0,0,20-20V96A20,20,0,0,0,208,76ZM100,56a28,28,0,0,1,56,0V76H100ZM204,204H52V100H204Zm-76-92a32,32,0,0,0-12,61.66V180a12,12,0,0,0,24,0v-6.34A32,32,0,0,0,128,112Zm0,24a8,8,0,1,1-8,8A8,8,0,0,1,128,136Z'/></svg>");
    --icone-lock-key-open: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256' fill='black'><path d='M208,76H100V56a28,28,0,0,1,28-28c13.51,0,25.65,9.62,28.24,22.39a12,12,0,1,0,23.52-4.78C174.87,21.5,153.1,4,128,4A52.06,52.06,0,0,0,76,56V76H48A20,20,0,0,0,28,96V208a20,20,0,0,0,20,20H208a20,20,0,0,0,20-20V96A20,20,0,0,0,208,76Zm-4,128H52V100H204Zm-88-30.34V180a12,12,0,0,0,24,0v-6.34a32,32,0,1,0-24,0ZM128,136a8,8,0,1,1-8,8A8,8,0,0,1,128,136Z'/></svg>");
    --icone-magnifying-glass: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256' fill='black'><path d='M232.49,215.51,185,168a92.12,92.12,0,1,0-17,17l47.53,47.54a12,12,0,0,0,17-17ZM44,112a68,68,0,1,1,68,68A68.07,68.07,0,0,1,44,112Z'/></svg>");
    --icone-moon: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256' fill='black'><path d='M236.37,139.4a12,12,0,0,0-12-3A84.07,84.07,0,0,1,119.6,31.59a12,12,0,0,0-15-15A108.86,108.86,0,0,0,49.69,55.07,108,108,0,0,0,136,228a107.09,107.09,0,0,0,64.93-21.69,108.86,108.86,0,0,0,38.44-54.94A12,12,0,0,0,236.37,139.4Zm-49.88,47.74A84,84,0,0,1,68.86,69.51,84.93,84.93,0,0,1,92.27,48.29Q92,52.13,92,56A108.12,108.12,0,0,0,200,164q3.87,0,7.71-.27A84.79,84.79,0,0,1,186.49,187.14Z'/></svg>");
    --icone-pencil-simple: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256' fill='black'><path d='M230.14,70.54,185.46,25.85a20,20,0,0,0-28.29,0L33.86,149.17A19.85,19.85,0,0,0,28,163.31V208a20,20,0,0,0,20,20H92.69a19.86,19.86,0,0,0,14.14-5.86L230.14,98.82a20,20,0,0,0,0-28.28ZM91,204H52V165l84-84,39,39ZM192,103,153,64l18.34-18.34,39,39Z'/></svg>");
    --icone-phone: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256' fill='black'><path d='M224,154.8l-47.09-21.11-.18-.08a19.94,19.94,0,0,0-19,1.75,13.08,13.08,0,0,0-1.12.84l-22.31,19c-13-7.05-26.43-20.37-33.49-33.21l19.06-22.66a11.76,11.76,0,0,0,.85-1.15,20,20,0,0,0,1.66-18.83,1.42,1.42,0,0,1-.08-.18L101.2,32A20.06,20.06,0,0,0,80.42,20.15,60.27,60.27,0,0,0,28,80c0,81.61,66.39,148,148,148a60.27,60.27,0,0,0,59.85-52.42A20.06,20.06,0,0,0,224,154.8ZM176,204A124.15,124.15,0,0,1,52,80,36.29,36.29,0,0,1,80.48,44.46l18.82,42L80.14,109.28a12,12,0,0,0-.86,1.16A20,20,0,0,0,78,130.08c9.42,19.28,28.83,38.56,48.31,48A20,20,0,0,0,146,176.63a11.63,11.63,0,0,0,1.11-.85l22.43-19.07,42,18.81A36.29,36.29,0,0,1,176,204Z'/></svg>");
    --icone-plus: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256' fill='black'><path d='M228,128a12,12,0,0,1-12,12H140v76a12,12,0,0,1-24,0V140H40a12,12,0,0,1,0-24h76V40a12,12,0,0,1,24,0v76h76A12,12,0,0,1,228,128Z'/></svg>");
    --icone-prohibit: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256' fill='black'><path d='M128,20A108,108,0,1,0,236,128,108.12,108.12,0,0,0,128,20Zm84,108a83.6,83.6,0,0,1-16.75,50.28L77.72,60.75A84,84,0,0,1,212,128ZM44,128A83.6,83.6,0,0,1,60.75,77.72L178.28,195.25A84,84,0,0,1,44,128Z'/></svg>");
    --icone-question: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256' fill='black'><path d='M144,180a16,16,0,1,1-16-16A16,16,0,0,1,144,180Zm92-52A108,108,0,1,1,128,20,108.12,108.12,0,0,1,236,128Zm-24,0a84,84,0,1,0-84,84A84.09,84.09,0,0,0,212,128ZM128,64c-24.26,0-44,17.94-44,40v4a12,12,0,0,0,24,0v-4c0-8.82,9-16,20-16s20,7.18,20,16-9,16-20,16a12,12,0,0,0-12,12v8a12,12,0,0,0,23.73,2.56C158.31,137.88,172,122.37,172,104,172,81.94,152.26,64,128,64Z'/></svg>");
    --icone-seal-check: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256' fill='black'><path d='M228.75,100.05c-3.52-3.67-7.15-7.46-8.34-10.33-1.06-2.56-1.14-7.83-1.21-12.47-.15-10-.34-22.44-9.18-31.27s-21.27-9-31.27-9.18c-4.64-.07-9.91-.15-12.47-1.21-2.87-1.19-6.66-4.82-10.33-8.34C148.87,20.46,140.05,12,128,12s-20.87,8.46-27.95,15.25c-3.67,3.52-7.46,7.15-10.33,8.34-2.56,1.06-7.83,1.14-12.47,1.21C67.25,37,54.81,37.14,46,46S37,67.25,36.8,77.25c-.07,4.64-.15,9.91-1.21,12.47-1.19,2.87-4.82,6.66-8.34,10.33C20.46,107.13,12,116,12,128S20.46,148.87,27.25,156c3.52,3.67,7.15,7.46,8.34,10.33,1.06,2.56,1.14,7.83,1.21,12.47.15,10,.34,22.44,9.18,31.27s21.27,9,31.27,9.18c4.64.07,9.91.15,12.47,1.21,2.87,1.19,6.66,4.82,10.33,8.34C107.13,235.54,116,244,128,244s20.87-8.46,27.95-15.25c3.67-3.52,7.46-7.15,10.33-8.34,2.56-1.06,7.83-1.14,12.47-1.21,10-.15,22.44-.34,31.27-9.18s9-21.27,9.18-31.27c.07-4.64.15-9.91,1.21-12.47,1.19-2.87,4.82-6.66,8.34-10.33C235.54,148.87,244,140.05,244,128S235.54,107.13,228.75,100.05Zm-17.32,39.29c-4.82,5-10.28,10.72-13.19,17.76-2.82,6.8-2.93,14.16-3,21.29-.08,5.36-.19,12.71-2.15,14.66s-9.3,2.07-14.66,2.15c-7.13.11-14.49.22-21.29,3-7,2.91-12.73,8.37-17.76,13.19C135.78,214.84,130.4,220,128,220s-7.78-5.16-11.34-8.57c-5-4.82-10.72-10.28-17.76-13.19-6.8-2.82-14.16-2.93-21.29-3-5.36-.08-12.71-.19-14.66-2.15s-2.07-9.3-2.15-14.66c-.11-7.13-.22-14.49-3-21.29-2.91-7-8.37-12.73-13.19-17.76C41.16,135.78,36,130.4,36,128s5.16-7.78,8.57-11.34c4.82-5,10.28-10.72,13.19-17.76,2.82-6.8,2.93-14.16,3-21.29C60.88,72.25,61,64.9,63,63s9.3-2.07,14.66-2.15c7.13-.11,14.49-.22,21.29-3,7-2.91,12.73-8.37,17.76-13.19C120.22,41.16,125.6,36,128,36s7.78,5.16,11.34,8.57c5,4.82,10.72,10.28,17.76,13.19,6.8,2.82,14.16,2.93,21.29,3,5.36.08,12.71.19,14.66,2.15s2.07,9.3,2.15,14.66c.11,7.13.22,14.49,3,21.29,2.91,7,8.37,12.73,13.19,17.76,3.41,3.56,8.57,8.94,8.57,11.34S214.84,135.78,211.43,139.34ZM176.49,95.51a12,12,0,0,1,0,17l-56,56a12,12,0,0,1-17,0l-24-24a12,12,0,1,1,17-17L112,143l47.51-47.52A12,12,0,0,1,176.49,95.51Z'/></svg>");
    --icone-shield-check: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256' fill='black'><path d='M208,36H48A20,20,0,0,0,28,56V114.8c0,92.36,78.1,123,93.76,128.18a19.6,19.6,0,0,0,12.48,0C149.9,237.78,228,207.16,228,114.8V56A20,20,0,0,0,208,36Zm-4,78.8c0,73.56-60.53,99.53-76,105-15.47-5.42-76-31.39-76-104.95V60H204ZM79.51,144.49a12,12,0,1,1,17-17L112,143l47.51-47.51a12,12,0,0,1,17,17l-56,56a12,12,0,0,1-17,0Z'/></svg>");
    --icone-sign-in: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256' fill='black'><path d='M144.49,136.49l-40,40a12,12,0,0,1-17-17L107,140H24a12,12,0,0,1,0-24h83L87.51,96.49a12,12,0,0,1,17-17l40,40A12,12,0,0,1,144.49,136.49ZM192,28H136a12,12,0,0,0,0,24h52V204H136a12,12,0,0,0,0,24h56a20,20,0,0,0,20-20V48A20,20,0,0,0,192,28Z'/></svg>");
    --icone-sign-out: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256' fill='black'><path d='M116,216a12,12,0,0,1-12,12H48a20,20,0,0,1-20-20V48A20,20,0,0,1,48,28h56a12,12,0,0,1,0,24H52V204h52A12,12,0,0,1,116,216Zm108.49-96.49-40-40a12,12,0,0,0-17,17L187,116H104a12,12,0,0,0,0,24h83l-19.52,19.51a12,12,0,0,0,17,17l40-40A12,12,0,0,0,224.49,119.51Z'/></svg>");
    --icone-sliders-horizontal: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256' fill='black'><path d='M40,92H70.06a36,36,0,0,0,67.88,0H216a12,12,0,0,0,0-24H137.94a36,36,0,0,0-67.88,0H40a12,12,0,0,0,0,24Zm64-24A12,12,0,1,1,92,80,12,12,0,0,1,104,68Zm112,96H201.94a36,36,0,0,0-67.88,0H40a12,12,0,0,0,0,24h94.06a36,36,0,0,0,67.88,0H216a12,12,0,0,0,0-24Zm-48,24a12,12,0,1,1,12-12A12,12,0,0,1,168,188Z'/></svg>");
    --icone-sun: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256' fill='black'><path d='M116,32V16a12,12,0,0,1,24,0V32a12,12,0,0,1-24,0Zm80,96a68,68,0,1,1-68-68A68.07,68.07,0,0,1,196,128Zm-24,0a44,44,0,1,0-44,44A44.05,44.05,0,0,0,172,128ZM51.51,68.49a12,12,0,1,0,17-17l-12-12a12,12,0,0,0-17,17Zm0,119-12,12a12,12,0,0,0,17,17l12-12a12,12,0,1,0-17-17ZM196,72a12,12,0,0,0,8.49-3.51l12-12a12,12,0,0,0-17-17l-12,12A12,12,0,0,0,196,72Zm8.49,115.51a12,12,0,0,0-17,17l12,12a12,12,0,0,0,17-17ZM44,128a12,12,0,0,0-12-12H16a12,12,0,0,0,0,24H32A12,12,0,0,0,44,128Zm84,84a12,12,0,0,0-12,12v16a12,12,0,0,0,24,0V224A12,12,0,0,0,128,212Zm112-96H224a12,12,0,0,0,0,24h16a12,12,0,0,0,0-24Z'/></svg>");
    --icone-thumbs-up: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256' fill='black'><path d='M237,77.47A28,28,0,0,0,216,68H164V56a44.05,44.05,0,0,0-44-44,12,12,0,0,0-10.73,6.63L72.58,92H32a20,20,0,0,0-20,20v88a20,20,0,0,0,20,20H204a28,28,0,0,0,27.78-24.53l12-96A28,28,0,0,0,237,77.47ZM36,116H68v80H36ZM220,96.5l-12,96a4,4,0,0,1-4,3.5H92V106.83L126.82,37.2A20,20,0,0,1,140,56V80a12,12,0,0,0,12,12h64a4,4,0,0,1,4,4.5Z'/></svg>");
    --icone-user-circle: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256' fill='black'><path d='M128,20A108,108,0,1,0,236,128,108.12,108.12,0,0,0,128,20ZM79.57,196.57a60,60,0,0,1,96.86,0,83.72,83.72,0,0,1-96.86,0ZM100,120a28,28,0,1,1,28,28A28,28,0,0,1,100,120ZM194,179.94a83.48,83.48,0,0,0-29-23.42,52,52,0,1,0-74,0,83.48,83.48,0,0,0-29,23.42,84,84,0,1,1,131.9,0Z'/></svg>");
    --icone-user-minus: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256' fill='black'><path d='M256,136a12,12,0,0,1-12,12H204a12,12,0,0,1,0-24h40A12,12,0,0,1,256,136Zm-54.81,56.28a12,12,0,1,1-18.38,15.44C169.12,191.42,145,172,108,172c-28.89,0-55.46,12.68-74.81,35.72a12,12,0,0,1-18.38-15.44A124.08,124.08,0,0,1,63.5,156.53a72,72,0,1,1,89,0A124,124,0,0,1,201.19,192.28ZM108,148a48,48,0,1,0-48-48A48.05,48.05,0,0,0,108,148Z'/></svg>");
    --icone-user-plus: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256' fill='black'><path d='M256,136a12,12,0,0,1-12,12h-8v8a12,12,0,0,1-24,0v-8h-8a12,12,0,0,1,0-24h8v-8a12,12,0,0,1,24,0v8h8A12,12,0,0,1,256,136Zm-54.81,56.28a12,12,0,1,1-18.38,15.44C169.12,191.42,145,172,108,172c-28.89,0-55.46,12.68-74.81,35.72a12,12,0,0,1-18.38-15.44A124.08,124.08,0,0,1,63.5,156.53a72,72,0,1,1,89,0A124,124,0,0,1,201.19,192.28ZM108,148a48,48,0,1,0-48-48A48.05,48.05,0,0,0,108,148Z'/></svg>");
    --icone-users-three: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256' fill='black'><path d='M164.38,181.1a52,52,0,1,0-72.76,0,75.89,75.89,0,0,0-30,28.89,12,12,0,0,0,20.78,12,53,53,0,0,1,91.22,0,12,12,0,1,0,20.78-12A75.89,75.89,0,0,0,164.38,181.1ZM100,144a28,28,0,1,1,28,28A28,28,0,0,1,100,144Zm147.21,9.59a12,12,0,0,1-16.81-2.39c-8.33-11.09-19.85-19.59-29.33-21.64a12,12,0,0,1-1.82-22.91,20,20,0,1,0-24.78-28.3,12,12,0,1,1-21-11.6,44,44,0,1,1,73.28,48.35,92.18,92.18,0,0,1,22.85,21.69A12,12,0,0,1,247.21,153.59Zm-192.28-24c-9.48,2.05-21,10.55-29.33,21.65A12,12,0,0,1,6.41,136.79,92.37,92.37,0,0,1,29.26,115.1a44,44,0,1,1,73.28-48.35,12,12,0,1,1-21,11.6,20,20,0,1,0-24.78,28.3,12,12,0,0,1-1.82,22.91Z'/></svg>");
    --icone-warning: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256' fill='black'><path d='M240.26,186.1,152.81,34.23h0a28.74,28.74,0,0,0-49.62,0L15.74,186.1a27.45,27.45,0,0,0,0,27.71A28.31,28.31,0,0,0,40.55,228h174.9a28.31,28.31,0,0,0,24.79-14.19A27.45,27.45,0,0,0,240.26,186.1Zm-20.8,15.7a4.46,4.46,0,0,1-4,2.2H40.55a4.46,4.46,0,0,1-4-2.2,3.56,3.56,0,0,1,0-3.73L124,46.2a4.77,4.77,0,0,1,8,0l87.44,151.87A3.56,3.56,0,0,1,219.46,201.8ZM116,136V104a12,12,0,0,1,24,0v32a12,12,0,0,1-24,0Zm28,40a16,16,0,1,1-16-16A16,16,0,0,1,144,176Z'/></svg>");
    --icone-warning-diamond: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256' fill='black'><path d='M128,68a12,12,0,0,1,12,12v52a12,12,0,0,1-24,0V80A12,12,0,0,1,128,68Zm0,88a16,16,0,1,0,16,16A16,16,0,0,0,128,156Zm116-28a19.86,19.86,0,0,1-5.84,14.11l-96,96.06a20,20,0,0,1-28.21,0h0l-96-96.06a20,20,0,0,1,0-28.22l96.05-96.06a20,20,0,0,1,28.21,0l96.06,96.06A19.86,19.86,0,0,1,244,128Zm-25.68,0L128,37.67,37.68,128,128,218.33Z'/></svg>");
    --icone-windows-logo: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256' fill='black'><path d='M107.69,51.88a12,12,0,0,0-9.84-2.6l-60,10.91A12,12,0,0,0,28,72v36a12,12,0,0,0,12,12h60a12,12,0,0,0,12-12V61.09A12,12,0,0,0,107.69,51.88ZM88,96H52V82l36-6.54ZM223.69,30.79a12,12,0,0,0-9.84-2.6L137.85,42A12,12,0,0,0,128,53.82V108a12,12,0,0,0,12,12h76a12,12,0,0,0,12-12V40A12,12,0,0,0,223.69,30.79ZM204,96H152V63.83l52-9.45ZM100,136H40a12,12,0,0,0-12,12v36a12,12,0,0,0,9.85,11.81l60,10.91A12,12,0,0,0,112,194.91V148A12,12,0,0,0,100,136ZM88,180.53,52,174V160H88ZM216,136H140a12,12,0,0,0-12,12v54.18A12,12,0,0,0,137.85,214l76,13.82A12,12,0,0,0,228,216V148A12,12,0,0,0,216,136Zm-12,65.62-52-9.45V160h52Z'/></svg>");
    --icone-wrench: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256' fill='black'><path d='M230.47,67.5a12,12,0,0,0-19.26-4.32L172.43,99l-12.68-2.72L157,83.57l35.79-38.78a12,12,0,0,0-4.32-19.26A76,76,0,0,0,89.24,123.8L31.17,174c-.22.19-.44.39-.64.6a36,36,0,0,0,50.91,50.91c.21-.2.41-.42.6-.64l50.16-58.07A76,76,0,0,0,230.47,67.5ZM160,148a52.1,52.1,0,0,1-25.13-6.46A12,12,0,0,0,120,144.2L64.21,208.75a12,12,0,0,1-17-17L111.8,136a12,12,0,0,0,2.65-14.89A52,52,0,0,1,160,44h.89L135.17,71.87a12,12,0,0,0-2.91,10.65l5.66,26.35a12,12,0,0,0,9.21,9.21l26.35,5.66a12,12,0,0,0,10.65-2.91L212,95.12c0,.3,0,.59,0,.89A52.06,52.06,0,0,1,160,148Z'/></svg>");
    --icone-x: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256' fill='black'><path d='M208.49,191.51a12,12,0,0,1-17,17L128,145,64.49,208.49a12,12,0,0,1-17-17L111,128,47.51,64.49a12,12,0,0,1,17-17L128,111l63.51-63.52a12,12,0,0,1,17,17L145,128Z'/></svg>");
}

/* Uma classe por icone, para os sitios em que o icone e' um elemento do HTML.
   Da a FORMA e mais nada: o tamanho e a cor vem da `.icone` e do que estiver a
   volta. */
.icone-arrow-counter-clockwise { --i: var(--icone-arrow-counter-clockwise); }
.icone-arrow-left { --i: var(--icone-arrow-left); }
.icone-arrow-right { --i: var(--icone-arrow-right); }
.icone-arrow-square-out { --i: var(--icone-arrow-square-out); }
.icone-caret-down { --i: var(--icone-caret-down); }
.icone-chart-line-up { --i: var(--icone-chart-line-up); }
.icone-chat-centered-dots { --i: var(--icone-chat-centered-dots); }
.icone-check { --i: var(--icone-check); }
.icone-circle-dashed { --i: var(--icone-circle-dashed); }
.icone-clipboard-text { --i: var(--icone-clipboard-text); }
.icone-clock { --i: var(--icone-clock); }
.icone-copy { --i: var(--icone-copy); }
.icone-cpu { --i: var(--icone-cpu); }
.icone-currency-eur { --i: var(--icone-currency-eur); }
.icone-database { --i: var(--icone-database); }
.icone-desktop-tower { --i: var(--icone-desktop-tower); }
.icone-download-simple { --i: var(--icone-download-simple); }
.icone-envelope-simple { --i: var(--icone-envelope-simple); }
.icone-eye { --i: var(--icone-eye); }
.icone-file-text { --i: var(--icone-file-text); }
.icone-floppy-disk { --i: var(--icone-floppy-disk); }
.icone-funnel-simple { --i: var(--icone-funnel-simple); }
.icone-gauge { --i: var(--icone-gauge); }
.icone-gear-six { --i: var(--icone-gear-six); }
.icone-hard-drives { --i: var(--icone-hard-drives); }
.icone-info { --i: var(--icone-info); }
.icone-list-bullets { --i: var(--icone-list-bullets); }
.icone-list-checks { --i: var(--icone-list-checks); }
.icone-lock-key { --i: var(--icone-lock-key); }
.icone-lock-key-open { --i: var(--icone-lock-key-open); }
.icone-magnifying-glass { --i: var(--icone-magnifying-glass); }
.icone-moon { --i: var(--icone-moon); }
.icone-pencil-simple { --i: var(--icone-pencil-simple); }
.icone-phone { --i: var(--icone-phone); }
.icone-plus { --i: var(--icone-plus); }
.icone-prohibit { --i: var(--icone-prohibit); }
.icone-question { --i: var(--icone-question); }
.icone-seal-check { --i: var(--icone-seal-check); }
.icone-shield-check { --i: var(--icone-shield-check); }
.icone-sign-in { --i: var(--icone-sign-in); }
.icone-sign-out { --i: var(--icone-sign-out); }
.icone-sliders-horizontal { --i: var(--icone-sliders-horizontal); }
.icone-sun { --i: var(--icone-sun); }
.icone-thumbs-up { --i: var(--icone-thumbs-up); }
.icone-user-circle { --i: var(--icone-user-circle); }
.icone-user-minus { --i: var(--icone-user-minus); }
.icone-user-plus { --i: var(--icone-user-plus); }
.icone-users-three { --i: var(--icone-users-three); }
.icone-warning { --i: var(--icone-warning); }
.icone-warning-diamond { --i: var(--icone-warning-diamond); }
.icone-windows-logo { --i: var(--icone-windows-logo); }
.icone-wrench { --i: var(--icone-wrench); }
.icone-x { --i: var(--icone-x); }
/* FIM DO BLOCO GERADO POR testes/gerar_icones.py */

/* A classe que todos usam, seja em `::before` seja como elemento.

   `1.15em` E NAO `1em`: medido lado a lado com o texto das etiquetas, a
   1em o traco do Phosphor bold le-se mais leve do que a palavra ao lado, e
   a 1.3em passa a competir com ela. A 1.15em tem o mesmo peso optico.

   `flex: none` porque quase todos vivem dentro de um contentor flex -- a
   etiqueta, a nota, a linha da navegacao -- e sem ele o icone e' o primeiro
   a encolher quando o espaco falta, ate desaparecer sem deixar rasto. */
.icone,
.etiqueta::before,
.nota::before,
.marca-ajuda::before,
details > summary::after {
    /* `display` E' OBRIGATORIO AQUI, e a falta dele nao da erro nenhum.

       Um `::before` nasce inline, e um elemento inline IGNORA `width` e `height`. Nas
       etiquetas e nas notas isso nao se notava, porque o pai e' um contentor flex e um
       item de flex e' blockificado por ele; na marca de ajuda, cujo pai e' um `<button>`,
       o icone media 16 px no `getComputedStyle` e nao se via no ecra. */
    display: block;
    width: 1.15em;
    height: 1.15em;
    flex: none;
    background: currentColor;
    -webkit-mask: var(--i) center / contain no-repeat;
    mask: var(--i) center / contain no-repeat;
    /* O ICONE ASSENTA 0,7 PX ACIMA DO CENTRO DAS MAIUSCULAS, E DESCE-SE AQUI.

       Medido em pixeis, a dez vezes a resolucao, contra a caixa de tinta da primeira
       letra de cada rotulo -- que e' sempre uma maiuscula, e e' por ela que o olho
       centra: o `ç` de «Atenção» desce abaixo da linha de base e o acento de «Crítico»
       sobe acima das maiusculas, e nenhum dos dois conta.

       A CAUSA NAO E' O CONTEXTO. Mediu-se o mesmo glifo nos dois mecanismos de
       alinhamento que o painel usa -- `align-items: center` num contentor flex, e
       `vertical-align` num contexto inline -- e a diferenca entre eles foi de 0,00 px
       em oito glifos. E' um desvio do proprio desenho: os traçados do Phosphor nao
       estao centrados na vertical dentro do viewBox de 256.

       0,055em E' O VALOR QUE MINIMIZA O PIOR CASO, e nao a media. Os oito glifos
       medidos espalham-se de -0,33 px (`check`, `caret-down`) a -1,00 px (`warning`);
       descer todos 0,66 px deixa o erro entre -0,34 e +0,33 px, que e' metade de um
       pixel de ecra e nao se ve. Corrigir a media deixaria o `warning` em -0,3 e o
       `check` em +0,4. O que sobra e' a dispersao entre desenhos, e essa so se tirava
       com um numero por icone -- trinta e oito numeros escritos a mao para ganhar um
       terco de pixel. */
    transform: translateY(.055em);
    /* O navegador pode decidir nao imprimir fundos, e isto E' um fundo. O
       Chromium imprimiu-o sem isto, mas a norma nao o garante, e um icone
       que falta numa folha impressa nao se distingue de um que nunca la
       esteve. */
    print-color-adjust: exact;
    -webkit-print-color-adjust: exact;
}

.icone {
    display: inline-block;
    vertical-align: -.18em;
}

/* O ESPACO ENTRE O ICONE E A PALAVRA VEM DO `gap` DO CONTENTOR, e um contentor que
   nao seja flex nao tem gap nenhum.

   A navegacao, os botoes e o `.titulo-do-grupo` sao todos flex e ja traziam o seu -- 8
   px, 8 px e 12 px, medidos. Os `<h2>` dos cartoes e os `<label>` sao BLOCOS: o `gap`
   declarado neles nao faz coisa nenhuma, e o icone saiu colado a primeira letra, com
   zero pixeis pelo meio. Ve-se de imediato num telemovel, e nao ha verificacao que
   acenda: nada rola, nada perde contraste, nenhum alvo de toque encolhe.

   OITO PIXEIS E NAO UMA MEDIDA EM `em`: e' o mesmo `--e2` que os contentores flex usam,
   e o objectivo e' que a distancia seja a MESMA em todo o painel, e nao proporcional a
   cada tamanho de letra.

   QUANDO PUSERES UM ICONE NUM SITIO NOVO: se o pai nao for flex, acrescenta-o aqui. */
h2 > .icone,
label > .icone {
    margin-right: var(--e2);
}

/* ALTO CONTRASTE DO WINDOWS, e sem isto isto seria uma REGRESSAO.

   Um caractere de texto sobrevive ao contraste forcado: o Windows pinta-o
   com a cor de texto do sistema e continua la. Uma mascara nao e' texto, e'
   fundo -- e o contraste forcado pinta o fundo de `Canvas`, que da branco
   sobre branco. Medido nesta folha: o `background-color` calculado passava
   de `rgb(176, 42, 55)` para `rgb(255, 255, 255)`, e a etiqueta ficava so
   com a palavra.

   `CanvasText` e' a cor de texto do sistema, seja ela qual for -- e' essa a
   razao de nao se escrever aqui uma cor. */
@media (forced-colors: active) {
    .icone,
    .etiqueta::before,
    .nota::before,
    .marca-ajuda::before,
    details > summary::after {
        background: CanvasText;
    }
}

/* -----------------------------------------------------------------
   3. Base e foco
   ----------------------------------------------------------------- */

*,
*::before,
*::after {
    box-sizing: border-box;
}

html {
    -webkit-text-size-adjust: 100%;
    overflow-x: clip;

    /* O ESPACO DA BARRA DE ROLAMENTO FICA SEMPRE RESERVADO.

       Sem isto, uma pagina curta -- a ficha de um cliente com dois equipamentos,
       as definicoes -- nao tem barra, uma pagina comprida tem, e a barra rouba
       uns quinze pixeis a largura util. O conteudo esta centrado, portanto essa
       largura a menos desloca TUDO meia dezena de pixeis para o lado: navegar
       entre duas paginas do painel fazia o cabecalho, a navegacao e a marca dar
       um salto horizontal.

       `stable` reserva a goteira mesmo quando nao ha nada a rolar, e as duas
       paginas passam a ter a mesma largura util. Onde nao ha suporte, o
       comportamento e o de antes: nada piora. */
    scrollbar-gutter: stable;
}

body {
    margin: 0;
    background: var(--fundo);
    color: var(--texto);
    font: var(--letra-lg)/1.5 system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
    -webkit-font-smoothing: antialiased;
}

/* A ESCALA TINHA DE TER DEGRAUS, E NAO TINHA.

   Era h1 a 18, h2 a 15, corpo a 15 e h3 a 14: o titulo de um cartao tinha
   exactamente o mesmo tamanho do texto que estava debaixo dele, e o titulo da
   pagina ficava a tres pixeis do titulo do cartao. Uma pagina sem degraus le-se
   toda ao mesmo nivel, e depois nada e' importante.

   Agora sao 20, 15 e 13, com o h3 em maiusculas pequenas, que e o mesmo
   tratamento dos rotulos das medidas: dentro de um cartao, uma sub-seccao nao
   e um titulo mais pequeno, e outra coisa. */
h1,
h2,
h3 {
    margin: 0;
    font-weight: 650;
    letter-spacing: -.2px;
}

h1 {
    font-size: var(--letra-titulo);
    line-height: 1.25;
}

h2 {
    font-size: var(--letra-lg);
}

h3 {
    font-size: var(--letra-md);
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--esbatido);
}

p {
    margin: 0 0 var(--e3);
}

p:last-child {
    margin-bottom: 0;
}

/* LIGACOES MODERNAS, e nao a azul-sublinhado-sempre do navegador.
 *
 * Por decisao do responsavel do projecto, 31 de Agosto de 2026: «detesto aqueles links que
 * aparecem sublinhados em baixo e ficam azul em hover. Too old not modern.»
 *
 * O `a` base nao tirava o `text-decoration` de omissao, por isso as ligacoes soltas no meio
 * de texto -- as das notas e das ajudas -- saiam sempre sublinhadas, a moda antiga. Os
 * botoes, a navegacao e as ligacoes das tabelas ja punham `text-decoration: none` cada um
 * por si; era so o texto corrido que ficava por modernizar.
 *
 * Agora: cor de acento, SEM sublinhado -- nem em repouso, nem em hover, em lado nenhum
 * (segunda decisao do mesmo dia: «nao gosto de sublinhado, nem com hover ou sem hover»).
 * Onde havia sublinhado ao passar o rato -- `.tabela a`, `.meta-equipamento`,
 * `.ocorrencia-resumo > a` -- passou a um sinal discreto por opacidade. Nao se acrescenta
 * um `a:hover` global de proposito: os botoes sao `<a>` tambem, e um hover global
 * mexer-lhes-ia. */
a {
    color: var(--acento-texto);
    text-decoration: none;
}

:focus-visible {
    outline: 2px solid var(--acento);
    outline-offset: 2px;
}

[hidden] {
    display: none !important;
}

/* QUEM DESLIGOU AS ANIMACOES NO SISTEMA DEIXA DE AS VER AQUI.

   Ate 22 de Setembro de 2026 esta folha tinha quinze `transition` e duas `animation` e
   nem um unico `prefers-reduced-motion`: o painel animava-se na mesma a quem tinha pedido
   ao Windows que nao animasse nada. E uma definicao de acessibilidade, em Definicoes ->
   Acessibilidade -> Efeitos visuais, e existe porque ha gente a quem o movimento no ecra
   causa tonturas e enjoo -- nao e uma preferencia de gosto.

   O PUBLICO DESTE PAINEL E O TECNICO, e a auditoria do CSS marcou este ponto como
   «decisao e nao automatismo» precisamente por isso. A decisao foi fazer: sao oito
   linhas, nao mexem no desenho de ninguem que nao tenha pedido, e o dia em que o tecnico
   tiver uma razao para ligar aquela definicao o painel ja o respeita.

   `.01ms` E NAO `0s`, e nao e um capricho: com duracao zero o evento `transitionend`
   deixa de disparar em alguns navegadores, e qualquer codigo que espere por ele fica
   pendurado para sempre. Um centesimo de milissegundo e imperceptivel e continua a
   disparar. E o `animation-iteration-count: 1` existe para o que roda em ciclo nao ficar
   a rodar depressa: para uma vez e fica quieto.

   OS `!important` SAO OBRIGATORIOS AQUI, e sao a unica excepcao que esta folha faz alem
   do `[hidden]` de cima. Uma preferencia de acessibilidade tem de ganhar a TODAS as
   declaracoes que o painel escreveu, e algumas delas sao mais especificas do que um
   selector universal. */
@media (prefers-reduced-motion: reduce) {
    *,
    *::before,
    *::after {
        animation-duration: .01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: .01ms !important;
        scroll-behavior: auto !important;
    }
}

/* Numeros que se comparam na vertical alinham sempre. */
.numero,
.tabela td.numero,
.medida dd,
.cartao-estado .valor {
    font-variant-numeric: tabular-nums;
}

code {
    font-family: var(--mono);
    font-size: var(--letra-sm);
}

/* -----------------------------------------------------------------
   4. Cabecalho e navegacao
   ----------------------------------------------------------------- */

/* O TOPO TODO FICA FIXO NO DESKTOP: cabecalho E navegacao.
 *
 * Ate 31 de Agosto de 2026 so o `.topo` (o cabecalho) era sticky; a `.navegacao`, que e
 * a irma seguinte, rolava e desaparecia -- num scroll longo o tecnico perdia o menu e
 * tinha de subir para navegar. Envolveram-se os dois neste contentor sticky, para o topo
 * inteiro ficar.
 *
 * EM TELEMOVEL o contentor vira `display: contents` (ver o @media la em baixo): a caixa
 * dele desaparece, o cabecalho e a nav voltam a ser filhos directos do corpo, e a nav
 * cola sozinha a PAGINA inteira -- que e o desenho de telemovel (o cabecalho recolhe para
 * poupar altura, a nav fica). Sem o `display: contents`, a nav so colaria dentro da caixa
 * curta do contentor, ou seja, quase nada. */
/* A PASSAGEM DE UMA PAGINA PARA A OUTRA, e o cabecalho que nao se mexe.

   ISTO NAO E UMA APLICACAO DE PAGINA UNICA, e e a razao de estar aqui em vez de
   no `painel.js`. Cada ligacao continua a pedir a pagina inteira ao servidor, o
   historico e o do navegador, e sem JavaScript navega-se exactamente igual. O
   que a regra pede e so que a troca do documento seja desvanecida em vez de
   instantanea. Zero bytes na rede, zero linhas de JavaScript, zero rotas novas.

   OS DOIS `view-transition-name` SAO O PONTO TODO. Sem eles o cabecalho entra no
   desvanecimento da raiz com tudo o resto, e ve-se a piscar entre duas paginas
   onde ele e identico. Com um nome proprio, cada um e SEGUIDO de uma pagina para
   a outra: como a geometria e a mesma nas duas, o desenho fica parado, e o que
   se ve trocar e so o conteudo por baixo.

   SAO DOIS E NAO UM, e a razao esta no `display: contents` do telemovel. La em
   baixo o `.cabecalho-fixo` deixa de gerar caixa, e um elemento sem caixa nao e
   capturado -- o nome ficava inerte e o cabecalho voltava a piscar, so em
   telemovel e so onde ninguem olha. O `.topo` e a `.navegacao` geram caixa nas
   duas larguras.

   ESTA TRANSICAO IGNORA O `prefers-reduced-motion`, DE PROPOSITO.

   DECISAO EXPLICITA DO RESPONSAVEL DO PROJECTO, 29 de Setembro de 2026: «nao
   quero respeitar o prefers-reduced-motion». Contraria a regra de movimento
   reduzido que esta la em cima, na seccao 3, e que continua a valer para tudo o
   resto da folha -- so esta transicao esta fora dela.

   O que aqui esteve, e porque saiu: a declaracao nasceu dentro de um
   `@media (prefers-reduced-motion: no-preference)`, e esse involucro NAO era
   redundante -- os pseudo-elementos `::view-transition-*` vivem numa arvore a
   parte e o selector universal da seccao 3 nao lhes toca, portanto sem ele a
   transicao corria a quem tivesse pedido menos movimento. Medido antes de sair:
   com `reduce`, o `pageswap` devolvia `viewTransition=NAO`.

   O PUBLICO DESTE PAINEL E O TECNICO, e e o mesmo argumento que a auditoria do
   CSS ja tinha usado para marcar este ponto como «decisao e nao automatismo».
   Esta maquina reporta `reduce: false`, portanto o involucro nao estava a
   esconder nada a ninguem hoje; o que ele fazia era cobrir o dia em que a
   definicao fosse ligada. Para voltar atras basta envolver o bloco todo em
   `@media (prefers-reduced-motion: no-preference) { ... }` outra vez.

   .16s E NAO OS .25s POR OMISSAO: este painel abre-se dezenas de vezes num turno,
   e a um quarto de segundo por navegacao a espera passa a sentir-se. A duracao
   tem de estar nos tres pseudo-elementos: o `group` move a caixa, mas quem
   desvanece o conteudo sao o `old` e o `new`, cada um com o seu relogio.

   NO FIREFOX NAO ACONTECE NADA, E NAO PARTE NADA: a metade entre documentos ainda
   nao saiu de la (a de dentro do mesmo documento existe desde o 144). O navegador
   ignora a regra e a navegacao fica exactamente como esta hoje. O mesmo vale para
   qualquer navegador anterior ao Chrome 126 ou ao Safari 18.2. */
@view-transition {
    navigation: auto;
}

.topo {
    view-transition-name: topo;
}

.navegacao {
    view-transition-name: navegacao;
}

::view-transition-group(*),
::view-transition-old(*),
::view-transition-new(*) {
    animation-duration: .16s;
}

.cabecalho-fixo {
    position: sticky;
    top: 0;
    z-index: 40;
}

/* Ao rolar, o topo fixo ganha uma sombra por baixo -- o sinal de que ha conteudo por cima. */
html.rolou .cabecalho-fixo {
    box-shadow: var(--sombra-1);
}

.topo {
    /* `relative` e nao `sticky`: quem cola agora e o contentor. O `relative` fica para o
       `::before` do filete de registos se posicionar em relacao ao cabecalho. */
    position: relative;
    background: var(--superficie);
    border-bottom: 1px solid var(--borda-fraca);
    transition: box-shadow .18s, border-color .18s;
}

/* Filete de estado dos registos: sinal periferico permanente, sempre a
   vista em todas as paginas, sem gastar cor no resto da interface. */
.topo::before {
    content: "";
    position: absolute;
    inset: 0 0 auto;
    height: 3px;
    background: transparent;
}

:root[data-registos="abertos"] .topo::before {
    background: var(--critico);
}

/* O FILETE ESCOA

   Ele ja dizia «os registos estao abertos». Passa a dizer tambem QUANTO FALTA,
   sem ocupar um pixel a mais e sem ser preciso ler nada: encolhe da direita
   para a esquerda ao longo do que resta da janela, e acaba quando o servidor
   fecha. E a mesma contagem que o cabecalho escreve por extenso, para quem
   esta a olhar para o meio da pagina.

   A animacao dura a JANELA INTEIRA e arranca com um atraso NEGATIVO igual ao que
   ja correu: e o proprio navegador que salta para o ponto certo. Com 300 s de
   janela e 60 s ja passados, `300s linear -60s` poe o filete a 80 % e deixa-o
   descer dai. E por isso que a barra recomeca no sitio verdadeiro depois de um
   F5 ou de uma navegacao, em vez de recomecar do principio.

   Os dois tempos vem do servidor e entram pelo `painel.js`, que os le de dois
   `data-` do `<html>` e os poe pelo CSSOM. NAO podem vir num `style=`: o CSP
   deste painel e `style-src 'self'` sem `unsafe-inline` e o navegador atira-o
   fora, com o que a regra `animation` fica invalida e o filete para cheio.

   `data-janela` so existe quando ha prazo. Sem ele nao ha animacao nenhuma e o
   filete fica inteiro, que e o que uma abertura sem prazo merece. */
:root[data-janela] .topo::before {
    transform-origin: left;
    animation: escoar-registos var(--janela-registos) linear var(--decorrido-registos) forwards;
}

@keyframes escoar-registos {
    from { transform: scaleX(1); }
    to { transform: scaleX(0); }
}


.topo-interior {
    max-width: 1440px;
    margin: 0 auto;
    padding: var(--e3) var(--e4);
    display: flex;
    align-items: center;
    gap: var(--e3);
    flex-wrap: wrap;
}

.marca {
    display: flex;
    align-items: center;
    gap: var(--e2);
    font-size: var(--letra-lg);
    font-weight: 650;
    margin-right: auto;
    min-width: 0;
    white-space: nowrap;
    text-decoration: none;
    color: inherit;
}

.marca svg {
    flex: none;
    color: var(--acento);
    transition: color .15s;
}

.marca-texto {
    padding-left: var(--e3);
    border-left: 1px solid var(--borda);
    font-weight: 600;
    color: var(--esbatido);
    font-size: var(--letra-md);
}

/* O cabecalho em telemovel: duas filas, e nao tres.

   Em fila unica com quebra automatica, a marca ocupava a primeira linha
   inteira, o interruptor a segunda e os botoes a terceira. Com a descricao da
   marca fora e o interruptor mandado para o fim, ficam duas: marca e botoes
   em cima, registos em baixo com uma linha a separa-los. */
@media (max-width: 45rem) {
    .marca-texto {
        display: none;
    }

    .registos {
        order: 3;
        flex: 1 1 100%;
        flex-wrap: wrap;
        row-gap: var(--e2);
        justify-content: space-between;
        padding-top: var(--e2);
        border-top: 1px solid var(--borda-fraca);
    }

    /* A 390 pixeis, «Registos fechados» mede uns 150 e o grupo mede uns 240:
       juntos passam dos 358 que ha, e como nem o texto nem o selector encolhem,
       o que passava a medir 402 era a PAGINA. Com `overflow-x: clip` no `html`
       isso nao rola - fica cortado, que e pior, e nao aparece em nenhuma medicao
       de rolamento.

       Com esta base flexivel, o grupo fica ao lado do estado quando ha espaco e
       passa para a linha de baixo, com a largura toda, quando nao ha. */
    .registos .grupo-controlo {
        flex: 1 1 15rem;
    }

    /* E O BOTAO QUE LEVA O ESPACO QUE SOBRA, E NAO A MOLDURA.

       O grupo estica com a regra de cima, mas nenhuma das duas metades crescia:
       o selector tem a largura do texto, o botao tambem, e o resto ficava a
       sobrar DENTRO da caixa, a direita do «Abrir 60 s». Medido: 58 pixeis a
       360 de largura, 88 a 390, 112 a 414, 94 a 719.

       E moldura com o mesmo fundo do botao, dentro do mesmo canto arredondado,
       logo a seguir a ele. Quem olha ve um botao que vai ate ao fim da caixa;
       quem carrega no ultimo terco dele acerta no `<form>` e nao acontece nada.
       Confirmado com `elementFromPoint`: aos 75 % da metade da accao ja e o
       formulario que responde.

       Nao aparecia em medicao nenhuma - o botao tem os seus 44 px de altura, o
       contraste passa e nada rola na horizontal. So se ve carregando nele, que
       foi como o responsavel do projecto deu por isso, no telemovel. */
    .registos .grupo-controlo > .parte-accao {
        flex: 1 1 auto;
        justify-content: center;
    }

    /* O estado leva o espaco que sobra, e assim o «Fechar já» fica ao lado dele
       em vez de gastar uma linha inteira de telemovel para um botao so. */
    .registos-estado {
        flex: 1 1 12rem;
        min-width: 0;
    }

    /* Com os registos abertos o estado passa a ser «Registos abertos, 3 por
       criar, faltam 59 minutos», e isso nao cabe numa linha de 358 pixeis. A
       versao anterior resolvia escondendo o detalhe em telemovel; mas e' no
       telemovel, em casa do cliente, que o tecnico esta quando os registos
       estao abertos, e e' ai que ele mais precisa de saber quanto falta. */
    .registos-estado {
        white-space: normal;
    }

    /* O CONTENTOR DEIXA DE EXISTIR EM TELEMOVEL. `display: contents` remove a caixa dele,
       e o cabecalho e a nav voltam a ser filhos directos do corpo: a nav volta a colar a
       PAGINA inteira, e nao a caixa curta do contentor. Sem isto, a nav sticky do
       telemovel ficava presa dentro do contentor e mal colava. */
    .cabecalho-fixo {
        display: contents;
    }

    /* O contentor nao tem caixa em telemovel, logo nao leva sombra; quem a leva e a nav. */
    html.rolou .cabecalho-fixo {
        box-shadow: none;
    }

    /* EM TELEMOVEL, QUEM FICA COLADO AO ALTO DO ECRA E O MENU.

       Ao contrario, que era como estava, o que sobrevivia ao rolamento era a marca, o
       tema, a saida e o interruptor dos registos - tudo o que se usa uma vez por
       instalacao -, e desaparecia o menu, que e a unica coisa que alguem procura a meio
       de uma pagina. Bastou trocar qual dos dois e pegajoso.

       Nao ha animacao nenhuma nisto de proposito: o topo sai de vista empurrado pelo
       proprio dedo, ao ritmo do rolamento, e volta da mesma maneira. E o movimento que
       o menu ja fazia, agora do outro lado.

       O `relative` no `.topo` nao e decoracao: o filete vermelho dos registos abertos e
       um `::before` absoluto, e sem um antepassado posicionado ia medir-se pela pagina.
       Nao se perde sinal nenhum com o topo fora de vista - o filete some-se com ele,
       mas o contador de ocorrencias criticas do menu fica, e o interruptor esta a um
       rolamento para cima de distancia. */
    .topo {
        position: relative;
    }

    .navegacao {
        position: sticky;
        top: 0;
        z-index: 40;
    }

    /* A sombra do rolamento acompanha quem fica. */
    html.rolou .topo {
        box-shadow: none;
        border-bottom-color: var(--borda-fraca);
    }

    html.rolou .navegacao {
        border-bottom-color: transparent;
        box-shadow: var(--sombra-1);
    }
}

.navegacao {
    background: var(--superficie);
    border-bottom: 1px solid var(--borda-fraca);
}

/* O menu arrasta-se para os lados e SO para os lados.

   `overflow-x: auto` sozinho nao chega: em CSS, o eixo que fica em `visible` quando o
   outro deixa de o estar passa a `auto` sozinho, e o menu tinha rolamento vertical
   tambem. Havia um pixel para rolar - o `margin-bottom: -1px` com que a ligacao activa
   punha o seu sublinhado por cima da linha da barra -, e um pixel chega para o dedo
   sentir que aquilo abana. O pixel mudou-se para o envolvente, que nao e a caixa que
   rola, e o sublinhado continua exactamente onde estava.

   `overscroll-behavior-x` e a outra metade: sem ele, o puxao para alem do fim do menu
   passa para a pagina, e no telemovel esse gesto e o de recuar no historico. */
.navegacao-interior {
    max-width: 1440px;
    margin: 0 auto -1px;
    padding: 0 var(--e4);
    display: flex;
    gap: var(--e1);
    overflow-x: auto;
    overflow-y: hidden;
    overscroll-behavior-x: contain;
    scrollbar-width: none;
}

.navegacao-interior::-webkit-scrollbar {
    display: none;
}

/* Em telemovel a barra nao cabe, e acabava cortada a meio de uma palavra sem
   nada a dizer que se arrasta: lia-se como partida. O esbatimento a direita e o
   sinal, e nao ocupa espaco nenhum. */
@media (max-width: 45rem) {
    .navegacao-interior {
        mask-image: linear-gradient(to right, #000 calc(100% - 28px), transparent);
        -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 28px), transparent);
    }
}

/* O ICONE DA SECCAO SAI EM TELEMOVEL, e e' uma conta e nao um gosto.

   As sete ligacoes com icone medem 896 px de conteudo. A 360 px de ecra sobram 355
   visiveis, e a barra passaria a obrigar a rolar 541 px por dentro -- o
   `capturar_painel.py` recusa acima de 400, e tem razao: a essa altura as duas ultimas
   seccoes estao longe de mais para alguem adivinhar que existem. Sem o icone o conteudo
   volta aos 728 px e a rolagem aos 373, que e exactamente o que ja era antes disto.

   Os 40rem sao o ponto de quebra desta folha imediatamente acima do limite: a 640 px a
   barra com icones rola 261 px, muito dentro do aceitavel.

   Nao se perde o que o icone veio fazer. Ele veio distinguir sete rotulos parecidos
   quando estao TODOS a vista, que e o caso do computador; no telemovel eles nunca estao
   todos a vista, e o que a barra precisa la e' de caber. */
@media (max-width: 39.99rem) {
    .navegacao a .icone {
        display: none;
    }
}

.navegacao a {
    display: inline-flex;
    align-items: center;
    gap: var(--e2);
    padding: var(--e3) var(--e4);
    color: var(--esbatido);
    text-decoration: none;
    font-size: var(--letra-base);
    font-weight: 600;
    white-space: nowrap;
    border-bottom: 2px solid transparent;
    min-height: 44px;
    transition: color .13s, border-color .13s, background .13s;
}

.navegacao a:hover {
    color: var(--texto);
}

.navegacao a.activa {
    color: var(--acento-texto);
    border-bottom-color: var(--acento);
}

.navegacao .contador {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 20px;
    height: 20px;
    /* O ALGARISMO ASSENTA 0,44 PX ACIMA DO MEIO, E FICA ASSIM.

       Tentou-se compensar com padding, como nas etiquetas. Aqui nao resulta: com
       `height` fixa o efeito e' DISCRETO, porque o navegador arredonda a posicao
       do texto. Medido: 0,04em deixa -0,44 px e 0,08em deixa +0,56 px, e 0,06em
       tambem da +0,56 -- nao ha valor nenhum entre os dois. Dos dois degraus, o
       mais perto de zero e' o de nao compensar nada.

       Meio pixel de CSS num contador de 20 px. Fica medido para ninguem voltar a
       tentar e chegar ao mesmo sitio. */
    padding: 0 var(--e1);
    border-radius: var(--raio-total);
    background: var(--critico-lavado);
    color: var(--critico);
    font-size: var(--letra-xs);
    font-weight: 700;
    font-variant-numeric: tabular-nums;
}

.envolvente {
    max-width: 1440px;
    margin: 0 auto;
    padding: var(--e4);
}

.rodape {
    max-width: 1440px;
    margin: 0 auto;
    padding: var(--e2) var(--e4) var(--e6);
    color: var(--tenue);
    font-size: var(--letra-sm);
}

.cabecalho-pagina {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--e3);
    flex-wrap: wrap;
    margin-bottom: var(--e4);
}

.cabecalho-pagina .subtitulo {
    color: var(--esbatido);
    font-size: var(--letra-md);
    margin: var(--e0) 0 0;
}

/* O correio e o telefone de um cliente, no cabecalho da ficha. Separados por
   um ponto medio desenhado em CSS: em HTML seria um caracter que os leitores
   de ecra anunciam, e nao ha nada para anunciar entre dois contactos. */
.contactos {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--e2) var(--e3);
    margin: var(--e2) 0 0;
    font-size: var(--letra-md);
}

.contactos a + a::before {
    content: "";
    display: inline-block;
    width: 3px;
    height: 3px;
    margin-right: var(--e3);
    border-radius: var(--raio-total);
    background: var(--borda);
    vertical-align: middle;
}

.accoes-pagina {
    display: flex;
    gap: var(--e2);
    flex-wrap: wrap;
    align-items: center;
}

/* -----------------------------------------------------------------
   5. Botoes
   ----------------------------------------------------------------- */

.botao {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--e2);
    padding: var(--e2) var(--e4);
    min-height: 40px;
    border-radius: var(--raio-2);
    border: 1px solid var(--borda);
    background: var(--superficie);
    color: var(--texto);
    font: inherit;
    font-size: var(--letra-base);
    font-weight: 600;
    text-decoration: none;
    cursor: pointer;
    white-space: nowrap;
    transition: background .12s, border-color .12s, box-shadow .12s, transform .06s;
}

.botao:hover:not(:disabled) {
    background: var(--borda-fraca);
}

.botao:active:not(:disabled) {
    transform: translateY(1px);
}

.botao:disabled {
    opacity: .55;
    cursor: not-allowed;
}

.botao.principal {
    background: var(--acento);
    border-color: var(--acento);
    color: var(--sobre-acento);
}

.botao.perigo {
    background: var(--critico);
    border-color: var(--critico);
    color: var(--sobre-critico);
}

/* A VARIANTE `fantasma` SAIU A 19 DE SETEMBRO DE 2026, e nao se volta a pôr.

   > DECISAO DO RESPONSAVEL DO PROJECTO, repetida tres vezes no mesmo dia: «vamos
   > uniformizar isso?», «para ficarem todos uniformes», e por fim «o botao Ver
   > exemplos escritos nao tem botao mesmo design como os outros de linha».

   Ela era um terceiro nivel -- sem contorno e sem fundo -- para a accao terciaria ao
   lado de uma principal. Deu dois problemas, e o segundo nao tinha volta:

   Aparecia SOZINHA em quatro sitios, e ai nao tinha contra o que ser o menos: ficava
   texto cinzento com um alvo de toque invisivel. Isso ainda se corrigiu, com um
   `:has()` que lhe punha o contorno quando nao houvesse irmao desenhado.

   Mas mesmo acompanhada continuava a ser o unico botao do painel com outro desenho, e
   e' precisamente isso que se nota: dois botoes na mesma linha, um com moldura e outro
   sem. A hierarquia que resta -- `principal` com fundo de acento, e o resto com
   contorno -- chega para dizer qual e' a accao primaria.

   Ficam DOIS niveis, e nao tres. */

/* (nada aqui: o botao normal ja tem tudo o que o fantasma precisava) */

.botao.pequeno {
    padding: var(--e1) var(--e3);
    min-height: 34px;
    font-size: var(--letra-md);
}

/* Misturar com o texto escurece no tema claro e clareia no escuro, que
   e a direccao certa nos dois. brightness() lavava as cores saturadas
   no escuro. */
.botao.principal:hover:not(:disabled) {
    background: color-mix(in srgb, var(--acento) 88%, var(--texto));
    box-shadow: 0 3px 10px -3px color-mix(in srgb, var(--acento) 55%, transparent);
}

.botao.perigo:hover:not(:disabled) {
    background: color-mix(in srgb, var(--critico) 88%, var(--texto));
}

/* 34 pixeis, e nao 38: e a altura de `.botao.pequeno`, que e o que esta ao
   lado dele no cabecalho. Com 38 contra 34, os tres controlos do canto
   superior direito nao assentavam na mesma linha, e a diferenca de quatro
   pixeis via-se sem se conseguir dizer porque. */
.botao-icone {
    border: 1px solid var(--borda);
    background: var(--superficie);
    color: var(--esbatido);
    width: 34px;
    height: 34px;
    border-radius: var(--raio-2);
    cursor: pointer;
    padding: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    transition: background .13s, color .13s, border-color .13s;
}

/* O BOTAO DO TEMA NAO EXISTE SEM JAVASCRIPT, e e por isto que se esconde e nao
   pelo `hidden` que aqui esteve. O `hidden` tinha de ser retirado por codigo, o
   codigo que o retirava era `defer`, e o cabecalho refluia 46 px a cada pagina.

   A REGRA E' ESTA E NAO A INVERSA. Escrever `#botao-tema { display: none }` mais
   `:root[data-js] #botao-tema { display: inline-flex }` resolvia o mesmo, e
   prendia o botao a um `display` escrito a mao: no dia em que o `.botao-icone`
   deixasse de ser `inline-flex`, este ficava para tras sem nada acender. Assim
   nao ha `display` nenhum declarado no caminho normal -- so se retira o botao
   quando a marca falta.

   A marca chega no `tema.js`, sincrono no cabecalho, antes de o <body> ser
   parseado. Sem JavaScript nunca chega, e o botao fica escondido, que e o que
   um botao que nao funciona merece. */
:root:not([data-js]) #botao-tema {
    display: none;
}

.botao-icone:hover {
    color: var(--texto);
    border-color: var(--tenue);
}

.botao-icone:active {
    transform: translateY(1px);
}

.accoes {
    display: flex;
    gap: var(--e2);
    flex-wrap: wrap;
    align-items: center;
}

/* -----------------------------------------------------------------
   6. Cartoes

   A REGRA DE COMPOSICAO, que vale para o painel inteiro:

       .cartao
         > header      titulo, accoes, e a dica a direita
         > .corpo      TUDO o que nao seja uma tabela ou uma lista
         > .tabela-envolvente | .lista-*    encostado aos bordos

   Duas consequencias, e sao as que resolvem metade do que estava torto:

   1. NAO HA CARTOES DENTRO DE CARTOES. Uma seccao dentro de um cartao
      separa-se com um `<h3>` e com espaco, nunca com outra caixa que tenha
      moldura, fundo e sombra propria. A unica caixa interior autorizada e a
      `.medida`, e essa e uma celula de uma grelha de valores, nao um cartao.

   2. O AVANCO E UM SO. Quem tem `.corpo` tem 16 pixeis de cada lado; quem
      tem tabela encosta, porque a tabela ja traz os seus. Antes disto havia
      oito receitas diferentes de avanco para a mesma coisa, e via-se: tres
      listas do mesmo componente na mesma pagina comecavam a 20, a 20 e a 36
      pixeis do bordo.
   ----------------------------------------------------------------- */

/* `--luz` a seguir a sombra, e nao em vez dela.

   No tema claro `--luz` e transparente e nao muda nada. No escuro e um fio
   branco a 8% no bordo de cima, e e ele que faz o cartao parecer levantado:
   uma sombra preta sobre um fundo quase preto nao se ve, por muito que se
   lhe suba a opacidade. */
.cartao {
    background: var(--superficie);
    border: 1px solid var(--borda-fraca);
    border-radius: var(--raio-3);
    box-shadow: var(--sombra-1), var(--luz);
    margin-bottom: var(--e4);
    transition: border-color .18s ease, box-shadow .18s ease;
}

.cartao:hover,
.cartao:focus-within {
    border-color: var(--borda);
    box-shadow: var(--sombra-2), var(--luz);
}

/* 56 pixeis, e o mesmo numero no `summary` de um cartao colapsavel.

   Eram 60 aqui e 48 la, e as duas coisas aparecem uma debaixo da outra na
   mesma coluna: tres cartoes normais seguidos de tres colapsaveis desciam de
   altura a meio da pagina sem nada que o justificasse. */
.cartao > header {
    display: flex;
    align-items: center;
    gap: var(--e3);
    padding: var(--e3) var(--e4);
    border-bottom: 1px solid var(--borda-fraca);
    min-height: 56px;
    flex-wrap: wrap;
}

.cartao > header h2 {
    font-size: var(--letra-lg);
}

.cartao > header .dica {
    color: var(--tenue);
    font-size: var(--letra-sm);
    font-weight: 400;
    margin-left: auto;
    text-align: right;
}

.cartao > header .botao {
    margin-left: auto;
}

.cartao > header .botao + .dica {
    margin-left: var(--e3);
}

.cartao .corpo {
    padding: var(--e4);
}

/* A faixa de filtros dentro do cartao da lista. Separa-se da tabela com uma
   linha, e nao com sombra nem com fundo: dentro de um cartao, uma divisoria
   chega, e tudo o resto vira caixa dentro de caixa. */
.faixa-filtros {
    border-bottom: 1px solid var(--borda-fraca);
}

/* Um filtro de um campo so nao merece uma faixa: vai para o cabecalho do
   cartao, ao lado do titulo, que e onde a referencia da casa poe as accoes
   de um cartao. */
.cartao > header .filtro-de-cabecalho {
    display: flex;
    align-items: center;
    gap: var(--e2);
    margin-left: auto;
}

.cartao > header .filtro-de-cabecalho select {
    width: auto;
    min-width: 12rem;
    min-height: 34px;
    padding-top: 0;
    padding-bottom: 0;
    font-size: var(--letra-md);
}

/* Quando ha dica, e ela que empurra: o controlo fica no fim, que e onde uma
   accao vive, e a legenda antes dele. Com margem automatica nos dois, o espaco
   livre dividia-se e a dica ficava a meio do cabecalho.

   AS DUAS REGRAS, e nao so a do filtro. Esta linha existia so para o
   `.filtro-de-cabecalho`, e o `.botao` tem exactamente o mesmo `margin-left:
   auto` tres regras acima -- portanto exactamente o mesmo defeito, por corrigir.
   No cartao «Avisos ao cliente» da ficha de um equipamento, que e o unico sitio
   do painel com dica ANTES de botao, o «1 escrito» ficava pousado a meio do
   cabecalho, longe do titulo e longe do botao, e lia-se como se pertencesse a
   nenhum dos dois.

   E a familia de defeito que este projecto ja conhece: corrigiu-se o caso que se
   viu em vez de ir buscar a lista de quem tem `margin-left: auto`. Sao dois, e
   estao os dois aqui. */
.cartao > header .dica + .filtro-de-cabecalho,
.cartao > header .dica + .botao {
    margin-left: var(--e3);
}

.colunas {
    display: grid;
    gap: var(--e4);
    grid-template-columns: 1fr;
}

@media (min-width: 60rem) {
    .colunas {
        grid-template-columns: 1fr 1fr;
        align-items: start;
        /* A MARGEM PASSA DOS FILHOS PARA O PAI, e nao se perde pelo caminho.

           Tirar a margem aos cartoes e' certo -- a grelha ja os separa com o `gap`,
           e a margem somava-se a ele --, mas o `.colunas` nao tinha nenhuma: o
           cartao que viesse A SEGUIR da grelha encostava-lhe a zero pixeis. Ve-se na
           ficha de um aviso, onde o «O que aconteceu, por ordem» ficava colado ao
           cartao mais alto dos dois de cima.

           So acontece aqui dentro: abaixo de 60rem a grelha e' de uma coluna, os
           cartoes ficam com a sua margem, e o espaco existe. */
        margin-bottom: var(--e4);
    }

    .colunas .cartao {
        margin-bottom: 0;
    }
}

/* Cartao colapsavel, sem uma linha de JavaScript. */
details.cartao > summary {
    display: flex;
    align-items: center;
    gap: var(--e3);
    padding: var(--e3) var(--e4);
    cursor: pointer;
    font-size: var(--letra-lg);
    font-weight: 650;
    list-style: none;
    min-height: 56px;
    border-radius: calc(var(--raio-3) - 1px);
    transition: background .13s;
}

/* O cartao inteiro levanta com o rato porque e um `.cartao`, mas so o
   `summary` e que se clica. Sem uma marca propria, quem passa o rato pela
   tabela de dentro ve o cartao a reagir a uma coisa que nao pode carregar. */
details.cartao > summary:hover {
    background: var(--superficie-recuada);
}

details.cartao[open] > summary {
    border-radius: calc(var(--raio-3) - 1px) calc(var(--raio-3) - 1px) 0 0;
    border-bottom: 1px solid var(--borda-fraca);
}

details.cartao > summary::-webkit-details-marker {
    display: none;
}

/* A SETA E UMA SO, EM TODO O PAINEL.

   Estava declarada tres vezes, com 7 pixeis num sitio e 6 nos outros dois, e
   um dos tres nem sequer a tinha. Sao duas bordas rodadas quarenta e cinco
   graus, e nao um SVG: um SVG por cada `details` seriam vinte imagens iguais
   a viajar por causa de uma seta. */
details > summary::after {
    content: "";
    --i: var(--icone-caret-down);
    /* 1em e nao os 1.15em da `.icone`: aqui o icone nao acompanha uma palavra, marca
       um canto. Ao tamanho das etiquetas ficava a competir com o titulo do cartao. */
    width: 1em;
    height: 1em;
    transition: transform .18s ease;
}

details[open] > summary::after {
    transform: rotate(180deg);
}

details.cartao > summary::after {
    margin-left: var(--e3);
    color: var(--esbatido);
}

details.cartao > summary .dica {
    color: var(--tenue);
    font-size: var(--letra-sm);
    font-weight: 400;
    margin-left: auto;
    text-align: right;
}

/* UMA ACCAO NO CABECALHO DE UM CARTAO RECOLHIVEL, com as mesmas duas regras do
   cabecalho de um cartao normal, dezoito linhas acima: sozinho, o botao e
   empurrado para o fim; com dica antes dele, e ela que empurra e ele fica
   colado ao fim, a distancia de um espaco.

   Existe por causa do cartao «Avisos ao cliente» da ficha de um equipamento,
   onde o «Escrever um aviso» estava dentro do corpo e desaparecia com ele.
   Sem estas duas linhas o botao encostava-se ao titulo, a meio do cabecalho. */
details.cartao > summary .botao {
    margin-left: auto;
}

details.cartao > summary .dica + .botao {
    margin-left: var(--e3);
}

/* A dica de um cabecalho de cartao, em telemovel.

   Alinhada a direita e com o titulo a esquerda, quando as duas nao cabiam na
   mesma linha ficavam em escada: titulo a esquerda em cima, dica a direita em
   baixo, e o olho a saltar de um canto para o outro. Em linha propria, as duas
   comecam no mesmo sitio. */
@media (max-width: 45rem) {
    /* O `summary` nasce sem quebra, e sem ela a dica nao tem para onde ir: em
       vez de descer para a linha de baixo, encolhia ate caber ao lado do titulo
       e partia as duas em escada. */
    details.cartao > summary {
        flex-wrap: wrap;
    }

    /* A seta fica na linha do titulo, e nao numa terceira sua. Sem a ordem
       explicita, a dica a 100% empurrava-a para baixo dela. */
    details.cartao > summary::after {
        order: 1;
    }

    .cartao > header .dica,
    details.cartao > summary .dica {
        flex: 1 1 100%;
        margin-left: 0;
        text-align: left;
        order: 2;
    }

    /* E o botao desce para debaixo dela, em linha sua.

       Na linha do titulo nao cabia: «Avisos ao cliente» mais «Escrever um
       aviso» mais a seta passam dos 320 px, e o que quebrava era o botao a
       meio, com a seta pendurada ao lado dele. Em linha propria a ordem le-se
       de cima para baixo -- titulo, quantos, o que fazer. */
    details.cartao > summary .botao {
        margin-left: 0;
        order: 3;
    }
}


/* -----------------------------------------------------------------
   Cartoes de estado da pagina inicial

   A hierarquia e deliberada: o que precisa de atencao ocupa mais espaco
   e mais cor do que o que esta bem. Um painel em que «saudavel» chama
   tanto a atencao como «critico» nao responde a pergunta que se lhe faz.
   ----------------------------------------------------------------- */

.cartoes-estado {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
    gap: var(--e3);
    margin-bottom: var(--e4);
}

/* O numero sobe para o lado do rotulo, e nao para debaixo dele.

   Em coluna, cada cartao media 341 por 103 pixeis a 1440 para tres linhas de
   texto curto, e quatro caixas quase vazias lado a lado sao exactamente o que
   faz um painel parecer barato. Em fila, a mesma informacao ocupa 80 pixeis de
   altura e o numero fica com o tamanho que merece.

   A ordem no HTML nao muda, e a ordem de leitura tambem nao: rotulo, numero,
   explicacao continua a ler-se da esquerda para a direita e de cima para
   baixo. */
.cartao-estado {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: baseline;
    column-gap: var(--e3);
    background: var(--superficie);
    border: 1px solid var(--borda-fraca);
    border-radius: var(--raio-3);
    box-shadow: var(--sombra-1), var(--luz);
    padding: var(--e3) var(--e4);
    text-decoration: none;
    color: inherit;
    min-width: 0;
    transition: border-color .18s, box-shadow .18s, transform .06s;
}

.cartao-estado:hover {
    border-color: var(--borda);
    box-shadow: var(--sombra-2), var(--luz);
}

.cartao-estado:active {
    transform: translateY(1px);
}

.cartao-estado .rotulo {
    grid-column: 1;
    grid-row: 1;
    display: flex;
    align-items: center;
    gap: var(--e1);
    font-size: var(--letra-xs);
    color: var(--tenue);
    text-transform: uppercase;
    letter-spacing: .04em;
    font-weight: 650;
}

.cartao-estado .valor {
    grid-column: 2;
    grid-row: 1 / span 2;
    align-self: center;
    display: block;
    font-size: var(--letra-numero);
    font-weight: 700;
    letter-spacing: -.02em;
    line-height: 1.1;
}

/* `explicacao` e nao `nota`: `.nota` e a caixa de alerta, e o selector mais
   fraco perdia para ela. O texto de uma linha dentro do cartao de estado
   aparecia com moldura, fundo e espacamento de aviso. */
.cartao-estado .explicacao {
    grid-column: 1;
    grid-row: 2;
    display: block;
    font-size: var(--letra-sm);
    color: var(--esbatido);
    margin-top: var(--e0);
    line-height: 1.35;
}

/* UM cartao cheio, e nao quatro.

   A versao anterior pintava tres dos quatro: vermelho, ambar e cinzento
   lavados, lado a lado, mais um branco ao fundo. Quatro caixas coloridas em
   fila nao ordenam nada - so fazem barulho, e ensinam a nao olhar. E o
   cinzento lavado do «sem comunicacao» dizia «desligado» a respeito do
   estado que, num servico de acompanhamento preventivo, e dos que mais
   interessam.

   Fica assim: todos se enchem da sua cor, com a mesma construcao, e o que os
   separa e a tonalidade - vermelho, laranja, amarelo, verde, azul. O que nao se
   enche e o cartao a ZERO, que volta ao branco: a ausencia de problema nao e
   uma noticia, e numa base instalada saudavel isso deixa o verde do «saudavel»
   sozinho a falar. */
/* Tres cartoes numa grelha de duas colunas deixam o terceiro sozinho, com
   metade da largura e a outra metade vazia. Passa a ocupar a linha inteira.

   `nth-child(3)` e nao `nth-child(odd)`: com quatro cartoes o ultimo e o quarto,
   e nao pode esticar. Abaixo de 31rem a grelha tem sempre duas colunas - tres
   colunas de 150 pixeis mais dois intervalos precisam de 506, e nesta largura
   nao ha. */
@media (max-width: 31rem) {
    .cartoes-estado > :last-child:nth-child(3) {
        grid-column: 1 / -1;
    }
}

/* TODOS OS CARTOES SAO CONSTRUIDOS DA MESMA MANEIRA.

   Fundo lavado, moldura da cor do estado, e o numero e o rotulo na mesma cor.
   Muda a cor e mais nada: e a mesma peca cinco vezes, e nao cinco pecas.

   A versao anterior tinha o critico assim e os outros com um filete de tres
   pixeis a esquerda - tres construcoes para quatro cartoes, e o quarto sem
   marca nenhuma. Lado a lado parecia inacabado.

   O `sem-valor`, mais abaixo, e a unica excepcao, e continua a ser: um cartao
   a zero volta ao branco, porque a ausencia de problema nao e uma noticia. E'
   o que impede que uma base instalada saudavel apareca como uma parede de cor.
   ----------------------------------------------------------------- */

.cartao-estado.critico {
    border-color: var(--critico);
    background: var(--critico-lavado);
}

.cartao-estado.critico .valor,
.cartao-estado.critico .rotulo {
    color: var(--critico);
}

.cartao-estado.atencao {
    border-color: var(--atencao);
    background: var(--atencao-lavado);
}

.cartao-estado.atencao .valor,
.cartao-estado.atencao .rotulo {
    color: var(--atencao);
}

.cartao-estado.sem_comunicacao {
    border-color: var(--sem-comunicacao);
    background: var(--sem-comunicacao-lavado);
}

.cartao-estado.sem_comunicacao .valor,
.cartao-estado.sem_comunicacao .rotulo {
    color: var(--sem-comunicacao);
}

.cartao-estado.saudavel {
    border-color: var(--saudavel);
    background: var(--saudavel-lavado);
}

.cartao-estado.saudavel .valor,
.cartao-estado.saudavel .rotulo {
    color: var(--saudavel);
}

.cartao-estado.informativo {
    border-color: var(--informacao);
    background: var(--informacao-lavado);
}

.cartao-estado.informativo .valor,
.cartao-estado.informativo .rotulo {
    color: var(--informacao);
}

/* Um valor a zero nao merece destaque nenhum: e a ausencia de problema.

   `sem-valor` e nao `vazio`, porque `.vazio` e o estado vazio de uma pagina, com
   26px de espacamento e texto centrado, e apanhava estes cartoes: o numero saia
   ao meio e o rotulo descaia, so no cartao que estivesse a zero. */
.cartao-estado.sem-valor,
.cartao-estado.sem-valor:hover {
    background: var(--superficie);
    border-color: var(--borda-fraca);
    box-shadow: var(--sombra-1), var(--luz);
}

.cartao-estado.sem-valor .valor,
.cartao-estado.sem-valor .rotulo {
    color: var(--tenue);
}

/* -----------------------------------------------------------------
   7. Tabelas

   Em ecra grande sao tabelas. Abaixo de 60rem deixam de o ser e cada
   linha vira um cartao, com o rotulo de cada celula a aparecer a partir
   do atributo data-rotulo. E por isso que TODAS as celulas o levam.
   ----------------------------------------------------------------- */

.tabela-envolvente {
    overflow-x: auto;
}

.tabela {
    width: 100%;
    border-collapse: collapse;
    font-size: var(--letra-base);
}

.tabela th {
    text-align: left;
    font-size: var(--letra-xs);
    color: var(--tenue);
    letter-spacing: .04em;
    text-transform: uppercase;
    font-weight: 650;
    /* Havia zero em cima, e os rotulos encostavam ao bordo do cabecalho do
       cartao como se tivessem escorregado para la. */
    padding: var(--e3) var(--e3) var(--e2);
    line-height: 1.3;
    /* «OCORRÊNCIAS» aparecia partida em «OCOR-» e «RÊNCIAS» a 820 pixeis. Um
       rotulo de coluna quebra entre palavras ou nao quebra. */
    hyphens: manual;
    overflow-wrap: normal;
}

.tabela th:first-child,
.tabela td:first-child {
    padding-left: var(--e4);
}

.tabela th:last-child,
.tabela td:last-child {
    padding-right: var(--e4);
}

/* `top`, e nao `middle`.

   Com `middle` cada celula centrava-se na altura da sua propria linha, e como
   as alturas diferem, a primeira linha de uma celula caia num sitio e a da
   celula ao lado noutro: 22px de dispersao DENTRO da mesma fila, medidos a
   1280. Nenhum olho le isso como uma tabela; le como texto derramado.

   A altura da linha em pixeis, e nao em multiplos, e a segunda metade da
   correccao: sem ela, uma celula com texto de 12px e a vizinha com texto de
   14px continuavam a comecar a alturas diferentes, porque cada uma calculava
   a sua entrelinha a partir do seu proprio corpo. */
.tabela td {
    padding: var(--e3);
    border-top: 1px solid var(--borda-fraca);
    vertical-align: top;
    line-height: var(--linha-celula);
    overflow-wrap: break-word;
}

/* Ritmo vertical.

   `height` numa linha de tabela e um MINIMO, e nao uma altura fixa: quem
   precisar de mais, cresce. Duas medidas, e nao uma: uma tabela cujas linhas
   tem identificador e nome por baixo reserva duas linhas de texto para todas,
   e assim as que so tem uma nao ficam mais baixas; uma tabela de campos curtos
   reserva uma. Sem isto a mesma tabela media 45, 61, 63, 79 e 82 pixeis por
   linha, e a grelha vertical simplesmente nao existia. */
.tabela tbody tr {
    height: 44px;
    transition: background .13s, box-shadow .13s;
}

.tabela tbody:has(.secundario-da-linha) tr {
    height: 64px;
}

.tabela tbody tr:hover {
    background: var(--linha-sobre);
    box-shadow: inset 3px 0 0 var(--acento);
}

.tabela a {
    color: var(--texto);
    text-decoration: none;
    font-weight: 600;
}

.tabela a:hover {
    /* SEM SUBLINHADO E SEM VIRAR AZUL, por decisao do responsavel do projecto (31 de
       Agosto de 2026). A linha ja se acende inteira no `tr:hover` -- fundo e barra de
       acento -- portanto o link so precisa de um sinal discreto por cima disso. */
    opacity: 0.7;
}

/* Uma ligacao na linha secundaria - o telefone por baixo do correio - continua a
   ser a linha secundaria: cinzenta e de peso normal. Sem isto ficava escura e a
   negrito, com mais peso do que o dado principal por cima dela. */
.tabela .secundario-da-linha a {
    color: inherit;
    font-weight: inherit;
}

/* O MESMO, FORA DA TABELA -- e faltava.

   Todas as regras desta classe estavam prefixadas com `.tabela`, e a ficha de um
   equipamento usa-a numa `<dd>`: o «abrir no CRM» ao lado do nome do cliente ficava
   SEM ESTILO NENHUM. Mesmo tamanho, mesma cor de ligacao e mesmo peso do que o nome,
   a 3,8 px dele. Lia-se como uma frase so, «Rita Ferreira abrir no CRM», e em telemovel
   quebrava para a linha seguinte e punha a `<dd>` com 44 px de altura em vez de 21.

   O comentario que la esta prometia «cinzenta e de peso normal» desde o primeiro dia.
   Passa a ser verdade tambem aqui.

   O PONTO MEDIO E' O SEPARADOR DESTE PAINEL, o mesmo que o PHP escreve entre os
   nomes de antivirus e nas linhas de estado. Sem ele, duas coisas de tamanhos
   diferentes coladas continuavam a ler-se como uma frase, so que agora com metade
   dela mais pequena. */
dd > .secundario-da-linha {
    font-size: var(--letra-sm);
    color: var(--esbatido);
}

dd > .secundario-da-linha::before {
    content: "·";
    margin: 0 .4em 0 .3em;
    color: var(--borda);
}

dd > .secundario-da-linha a {
    color: inherit;
    font-weight: inherit;
}

.tabela td.numero,
.tabela th.numero {
    text-align: right;
    white-space: nowrap;
}

/*
 * A COLUNA DA SUBSCRICAO NAO QUEBRA, e vale a pena dizer o que acontece sem isto.
 *
 * Entrou a 18 de Setembro de 2026 e fez da lista de equipamentos uma tabela de SETE
 * colunas. O `table-layout` automatico distribuiu o espaco pelo conteudo e deu 235px a
 * uma celula que diz «Activa» -- e, nao havendo mais espaco, espremeu a ULTIMA coluna,
 * a do agente, ate zero. Com largura zero, o `1.1.0` la dentro quebrou caractere a
 * caractere na vertical, e cada linha da tabela passou de 65 para 125 pixeis de altura.
 *
 * Nada disto acende no `capturar_painel.py`: a tabela vive dentro de um
 * `.tabela-envolvente` com `overflow-x: auto`, portanto rolar ali e legitimo e o
 * contraste continua a passar. Viu-se OLHANDO para a captura, que e o que o CLAUDE.md
 * manda fazer a seguir a medir.
 *
 * O `nowrap` impede «Inactiva» de quebrar numa coluna estreita. QUEM RESOLVEU O
 * COLAPSO, no entanto, nao foi isto: foi dar largura a SETIMA coluna na lista de
 * percentagens por posicao, mais abaixo neste ficheiro. Um `width: 1%` esteve aqui e
 * nao fez nada -- as larguras daquela tabela sao atribuidas por `nth-child`, e uma
 * largura numa classe perde para elas.
 */
.tabela td.celula-subscricao,
.tabela th.celula-subscricao {
    white-space: nowrap;
}

/*
 * OS TRES BADGES DOS EQUIPAMENTOS, LADO A LADO.
 *
 * Era um numero alinhado a direita com uma etiqueta POR BAIXO, e a etiqueta so existia
 * nos clientes que tinham alguma coisa a precisar de atencao: as linhas da tabela tinham
 * duas alturas diferentes conforme a linha, e uma lista assim le-se pior do que uma onde
 * todas sao iguais.
 *
 * Sao tres desde 22 de Setembro de 2026 -- computadores, subscricoes, atencao -- e ja
 * nao levam a palavra la dentro, so o simbolo e o numero. O que cada um conta diz-se no
 * balao de ajuda, que sai do `title` de cada span. Ver `Vistas/clientes/lista.php`.
 *
 * O `display` DA CELULA NAO SE TOCA. Um `td` com `display: flex` deixa de ser
 * `table-cell` e sai do algoritmo que reparte as larguras da tabela -- e as larguras
 * desta tabela vem de percentagens por `nth-child`, que passariam a nao se aplicar. As
 * etiquetas ja sao `inline-flex`, portanto ficam lado a lado sozinhas: o que as separava
 * era um `<span class="bloco">` a volta da segunda, e o que faltava era espaco entre
 * elas.
 *
 * A margem vai na SEGUNDA e nao nas duas, para a primeira comecar encostada a esquerda
 * como o resto da coluna.
 */
.tabela td.celula-equipamentos > .etiqueta + .etiqueta {
    margin-left: var(--e1);
}

.tabela .principal-da-linha {
    display: block;
    font-weight: 650;
}

/* Nunca quebra.

   O que aqui vem e o nome do computador, e um nome de computador e um
   identificador: `PORTATIL-DA-SALA-DE-ESTAR` partido em `PORTATIL-DA-SALA-` e
   `DE-ESTAR` deixa de se ler como uma coisa so, e o hifen e precisamente onde
   o navegador quebra por omissao. Nao ha propriedade nenhuma em CSS que proiba
   a quebra no hifen sem proibir todas as outras, e por isso a solucao e nao
   quebrar de todo, com reticencias quando nao couber. Com as larguras de
   coluna desta seccao, quase nunca chega a acontecer. */
.tabela .secundario-da-linha {
    display: block;
    font-size: var(--letra-sm);
    color: var(--esbatido);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* O NOME DO CLIENTE NAO PODE ESTICAR A LINHA PARA BAIXO.
   A coluna tem 15 % da largura, e um cliente chamado «Condomínio do Edifício Nossa
   Senhora da Conceição e São João Baptista de Vila Nova de Gaia, Administração Conjunta
   dos Blocos A, B e C, Lote 14, Rés-do-chão» -- 150 caracteres, o maximo da coluna, e um
   nome perfeitamente real num condominio -- ocupava OITO linhas e empurrava tudo o que
   estava a direita para longe do olhar. Uma linha de tabela que mede oito linhas de
   altura deixa de se ler como fila.
   Duas linhas e o compromisso: cabe um nome comprido de uma pessoa inteiro, e um nome de
   pessoa colectiva fica pelas reticencias com o resto no `title` do proprio texto. O
   `line-clamp` sem prefixo ainda nao e universal, e por isso vai com os dois.

   E O CORTE E DE UM ELEMENTO DENTRO DA CELULA, e nao da celula. Esteve no proprio `td`
   ate 28 de Agosto de 2026, e uma celula de tabela nao respeita `overflow`: a altura dela
   vem da linha, e a linha vem do conteudo. O resultado era o tal condominio com as duas
   linhas cortadas, as reticencias postas, e a TERCEIRA linha na mesma la, cortada a meio
   pela borda de baixo. Visto numa captura, e nao apanhado por medicao nenhuma. */
.corta-em-duas-linhas {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    overflow: hidden;
}

/*
 * A COLISAO QUE FAZIA O CORTE NAO CORTAR NADA.
 *
 * O `-webkit-line-clamp` so funciona sobre `display: -webkit-box`. Nas duas listas onde
 * o nome leva as DUAS classes -- `principal-da-linha corta-em-duas-linhas` --, a regra
 * `.tabela .principal-da-linha { display: block }` tem mais especificidade (0,2,0 contra
 * 0,1,0) e ganhava: o `display` computado era `block`, o clamp ficava inerte, e o nome
 * de um condominio com 150 caracteres ocupava TRES linhas numa lista desenhada para
 * duas.
 *
 * Estava assim desde que as duas classes se encontraram, e nao acendia em lado nenhum:
 * o texto nao transborda, nao rola, e o contraste nao muda -- so a linha da tabela fica
 * mais alta do que as outras. Viu-se a olhar para uma captura a 18 de Setembro de 2026,
 * ao estreitar a coluna do nome para dar espaco aos badges dos equipamentos.
 *
 * E o mesmo feitio de defeito que a replica da janela do aviso ja tinha apanhado: uma
 * classe solta noutra folha a ganhar a uma propriedade que se esperava herdar.
 */
.tabela .principal-da-linha.corta-em-duas-linhas {
    display: -webkit-box;
}

/* Em cartao a celula tem a largura toda e nao ha nada a cortar. */
@media (max-width: 60rem) {
    .corta-em-duas-linhas {
        display: block;
        overflow: visible;
    }
}

/* A etiqueta ocupa exactamente uma linha de celula, para a fila continuar a
   ler-se como fila. Sem isto, a caixa da etiqueta media 24px numa linha de 20
   e empurrava o texto das celulas vizinhas para baixo dela. */
.tabela td > .etiqueta {
    height: var(--linha-celula);
    padding-block: 0;
}

/* CELULA inteira clicavel, sem JavaScript.

   A margem negativa engole o enchimento da celula e o `padding` repoe-o por
   dentro da ligacao: o alvo passa a ser o rectangulo todo, e o texto fica onde
   estava. A CELULA, e nao a linha -- este comentario dizia «linha inteira» e
   levou a recusar uma segunda `ligacao-completa` na mesma fila com o argumento
   de que o clique ficava ambiguo. Nao fica: cada celula tem um destino so, e um
   clique cai numa celula. Duas colunas de uma tabela podem ambas levar a
   propria, e em `/equipamentos` levam. */
.tabela td .ligacao-completa {
    display: block;
    margin: calc(var(--e3) * -1);
    padding: var(--e3);
}

/* -----------------------------------------------------------------
   7.1 Largura das colunas

   Nenhuma tabela do painel declarava largura nenhuma, e o algoritmo
   automatico faz sempre a mesma coisa: reparte o espaco que sobra na
   proporcao do texto de cada coluna. Quem ja tem muito, leva mais.
   Medido a 1920: em /equipamentos a coluna «Ultima comunicacao» ficava
   com 345px para 42px de texto, enquanto «Equipamento» partia o
   identificador em tres linhas dentro de 235px. Em /auditoria,
   «Detalhe» levava 561px para 388px de tinta e «Endereco IP» ficava com
   140px. Isso e o algoritmo a decidir o desenho da pagina.

   A correccao e declarar as larguras. Duas decisoes que a acompanham:

   1. `table-layout: fixed` so entra nas tabelas que aqui estao
      reconhecidas. Uma tabela que nao esteja nesta lista, ou que mude de
      colunas amanha, continua a portar-se exactamente como hoje, em vez
      de espremer tudo em partes iguais. As tabelas cruas de
      /relatorios/{id}, com vinte e seis colunas, dependem disso.

   2. As tabelas reconhecem-se pelo `data-rotulo` das celulas, que ja la
      esta porque e ele que da titulo a cada campo quando a linha vira
      cartao. Nao houve um unico atributo acrescentado as vistas para
      isto. Onde o rotulo leva acentos, o selector agarra-se ao pedaco
      sem eles: um comentario mal descodificado nao faz mal a ninguem,
      um SELECTOR mal descodificado deixa de casar e as larguras caem
      todas de uma vez, sem aviso.
   ----------------------------------------------------------------- */

.tabela:has(td[data-rotulo="Desde"]),
.tabela:has(td[data-rotulo$=" comunicou"]),
.tabela:has(td[data-rotulo="Agente"]):has(td[data-rotulo^="Ocorr"]),
.tabela:has(td[data-rotulo="Cliente desde"]),
.tabela:has(td[data-rotulo="Perfil"]),
.tabela:has(td[data-rotulo$=" IP"]),
.tabela:has(td[data-rotulo="Aceita"]),
.tabela:has(td[data-rotulo="Intervalo"]),
.tabela:has(td[data-rotulo="Conta"]),
.tabela:has(td[data-rotulo="Assunto"]),
.tabela:has(td[data-rotulo="Aberta"]),
.tabela:has(td[data-rotulo="Tamanho"]),
.tabela:has(td[data-rotulo="Motivo"]),
.tabela:has(td[data-rotulo="Quem"]),
.tabela:has(td[data-rotulo="Aplicada"]) {
    table-layout: fixed;
}

/* Com largura declarada, um cabecalho comprido numa coluna estreita
   transbordava para fora da celula. Passa a quebrar, que em maiusculas
   de 11px se le sem custo nenhum.

   `hyphens: auto` antes de `overflow-wrap`, por esta ordem de preferencia:
   o <html> declara `lang="pt-PT"` e o navegador sabe partir «OCORRENCIAS»
   por silabas, com o hifen a dizer que a palavra continua. Sem isso, a
   quebra dava «OCORREN» e «CIAS» em linhas seguidas, sem sinal nenhum de
   que era a mesma palavra. */
.tabela:has(td[data-rotulo]) th {
    white-space: normal;
    hyphens: auto;
    overflow-wrap: break-word;
}

/* A coluna de estado leva medida fixa, e nao percentagem.

   O que la vai e uma etiqueta que nao quebra, e a mais comprida delas,
   «Sem comunicacao», mede 140 pixeis aconteca o que acontecer. Com 9% de
   largura, a 1280 a etiqueta transbordava por cima do identificador do
   equipamento e liam-se as duas por cima uma da outra. Uma percentagem
   serve para repartir espaco; para conteudo de tamanho conhecido serve
   uma medida. As colunas em percentagem repartem o que sobrar. */
.tabela:has(td[data-rotulo="Estado"]) th:nth-child(1) {
    width: 11rem;
}

/* `/`, precisam de atencao */
.tabela:has(td[data-rotulo="Desde"]) th:nth-child(2) { width: 19%; }
.tabela:has(td[data-rotulo="Desde"]) th:nth-child(3) { width: 13%; }
.tabela:has(td[data-rotulo="Desde"]) th:nth-child(4) { width: 36%; }
.tabela:has(td[data-rotulo="Desde"]) th:nth-child(5) { width: 8%; }
.tabela:has(td[data-rotulo="Desde"]) th:nth-child(6) { width: 15%; }

/* `/`, registados nas ultimas 24 horas */
.tabela:has(td[data-rotulo$=" comunicou"]) th:nth-child(1) { width: 16%; }
.tabela:has(td[data-rotulo$=" comunicou"]) th:nth-child(2) { width: 21%; }
.tabela:has(td[data-rotulo$=" comunicou"]) th:nth-child(3) { width: 23%; }
.tabela:has(td[data-rotulo$=" comunicou"]) th:nth-child(4) { width: 14%; }
.tabela:has(td[data-rotulo$=" comunicou"]) th:nth-child(5) { width: 13%; }
.tabela:has(td[data-rotulo$=" comunicou"]) th:nth-child(6) { width: 13%; }

/* `/equipamentos`, SETE colunas desde que a da subscricao entrou.
   Eram seis, e a lista de larguras tinha cinco linhas -- uma por cada coluna
   depois da do estado, que leva medida fixa. A coluna nova entrou em quarto
   lugar e EMPURROU as outras: cada uma passou a receber a largura da
   anterior, e a ultima, o agente, ficou sem regra nenhuma -- com zero.

   Com zero, o `1.1.0` la dentro quebrou caractere a caractere na vertical e
   cada linha da tabela passou de 65 para 125 pixeis de altura. A tabela
   continuava a nao rolar a pagina (vive num `overflow-x: auto`), o contraste
   continuava a passar, e o `capturar_painel.py` deu tudo verde: viu-se
   OLHANDO para a captura.

   As percentagens somam 89%, como antes -- os 11% que faltam sao os 11rem
   fixos da coluna do estado. O que cedeu foi o cliente (21 -> 19) e a ultima
   comunicacao (17 -> 13): tem texto que quebra bem. As ocorrencias mostram
   um numero e nao precisavam de 11%. */
.tabela:has(td[data-rotulo="Agente"]):has(td[data-rotulo^="Ocorr"]) th:nth-child(2) { width: 24%; }
.tabela:has(td[data-rotulo="Agente"]):has(td[data-rotulo^="Ocorr"]) th:nth-child(3) { width: 19%; }
.tabela:has(td[data-rotulo="Agente"]):has(td[data-rotulo^="Ocorr"]) th:nth-child(4) { width: 10%; }
.tabela:has(td[data-rotulo="Agente"]):has(td[data-rotulo^="Ocorr"]) th:nth-child(5) { width: 13%; }
.tabela:has(td[data-rotulo="Agente"]):has(td[data-rotulo^="Ocorr"]) th:nth-child(6) { width: 9%; }
.tabela:has(td[data-rotulo="Agente"]):has(td[data-rotulo^="Ocorr"]) th:nth-child(7) { width: 14%; }

/* `/clientes`, quatro colunas desde que a de estado saiu.

   A dos equipamentos subiu ate 34% enquanto os badges traziam a palavra la
   dentro -- «5 equipamentos», «2 a precisar de atenção» --, e a 22 de Setembro
   de 2026 desceu para 22%, quando passaram a ser TRES badges so com o simbolo e
   o numero. Sao badges que nao quebram: o mais largo mede um icone, um espaco e
   tres algarismos, e os tres juntos nao passam dos 170 px mesmo com as
   contagens mais compridas que esta base de dados pode ter. A 22% da 198 px na
   largura minima em que isto ainda e uma tabela (60rem), e sobra sempre.

   O ESPACO VOLTOU PARA ONDE TINHA SAIDO: o contacto (25 -> 31) e o nome
   (29 -> 35). Sao os dois que tem texto a serio, e eram os dois que o
   emprestaram em Setembro. */
.tabela:has(td[data-rotulo="Cliente desde"]) th:nth-child(1) { width: 35%; }
.tabela:has(td[data-rotulo="Cliente desde"]) th:nth-child(2) { width: 31%; }
.tabela:has(td[data-rotulo="Cliente desde"]) th:nth-child(3) { width: 22%; }
.tabela:has(td[data-rotulo="Cliente desde"]) th:nth-child(4) { width: 12%; }

/* `/clientes/{id}`, SEIS colunas desde que a da subscricao entrou.

   Eram cinco, e esta lista tinha quatro linhas -- uma por cada coluna depois
   da do estado, que leva medida fixa. A coluna nova entrou em TERCEIRO lugar,
   e sem mexer aqui teria feito exactamente o que a coluna da subscricao ja fez
   uma vez na lista de equipamentos, tres paragrafos acima: empurrar as outras,
   cada uma a receber a largura da anterior, e deixar a ULTIMA sem regra
   nenhuma -- com zero. Ali foi a do agente, aqui seria a da ultima
   comunicacao, e «há 14 dias» com largura zero quebra caractere a caractere.

   Nada disto acende no `capturar_painel.py`: a tabela vive dentro de um
   `.tabela-envolvente` com `overflow-x: auto`, portanto rolar ali e legitimo,
   e o contraste continua a passar. Ve-se OLHANDO para a captura.

   As percentagens somam 89%, como antes -- os 11% que faltam sao os 11rem
   fixos da coluna do estado. O espaco da coluna nova veio do perfil (20 -> 18)
   e da ultima comunicacao (27 -> 21): os dois tem texto que quebra bem.
   «Inactiva» nao quebra porque a celula leva `celula-subscricao`. */
.tabela:has(td[data-rotulo="Perfil"]) th:nth-child(2) { width: 27%; }
.tabela:has(td[data-rotulo="Perfil"]) th:nth-child(3) { width: 11%; }
.tabela:has(td[data-rotulo="Perfil"]) th:nth-child(4) { width: 18%; }
.tabela:has(td[data-rotulo="Perfil"]) th:nth-child(5) { width: 12%; }
.tabela:has(td[data-rotulo="Perfil"]) th:nth-child(6) { width: 21%; }

/* `/auditoria`.

   QUATRO DAS SEIS COLUNAS LEVAM MEDIDA, e nao percentagem, pela razao que a coluna
   do estado ja tinha escrita tres paragrafos acima: uma percentagem serve para
   repartir o que sobra, e para conteudo de tamanho conhecido serve uma medida. Aqui
   quatro sao de tamanho conhecido, e foram medidas no navegador com a fonte e o
   tamanho reais:

       Quando        «há 10 minutos»                 88px  ->  7rem
       Accao         «Actualizações autorizadas»    168px  -> 12,5rem
       Equipamento   «T3C-658-048», seminegrito      83px  ->  7rem
       Endereço IP   «255.255.255.255», monoespacada 99px  ->  8rem

   AS MEDIDAS LEVAM FOLGA, e a folga nao e desperdicio: ha um passo entre o que o
   Range mede e o que o navegador reparte, e a 110 contra 112 o endereco IP ainda
   partia -- «188.251.42.» numa linha e «10» na outra, que se le como outro
   endereco. Duas rondas gastas a afinar dois pixeis de cada vez nao valeram uma,
   e o que fecha a questao e medir o PIOR caso possivel de cada coluna e dar-lhe
   espaco a sobrar. O endereco IP e dimensionado para «255.255.255.255», que e o
   IPv4 mais largo que existe, e nao para o que estava na pagina naquele dia.

   Mais os 24 pixeis de enchimento de cada celula, que e o `var(--e3)` dos dois lados.

   OS NUMEROS FORAM MEDIDOS NA PAGINA, e nao numa caixa de teste a parte. A primeira
   tentativa mediu um `<span>` solto com a fonte escrita a mao e deu 79 pixeis para o
   identificador, e uma coluna de 6,5rem: na captura ele partia em «T3C-658-» e «048».
   O que faltava eram tres pixeis, e faltavam porque o identificador da tabela e
   SEMINEGRITO -- a caixa de teste nao herdava o peso, e a diferenca entre 400 e 600
   neste texto sao quatro pixeis. Mede-se o no de texto no sitio onde ele vive, com um
   Range e a celula em `nowrap`.

   O UTILIZADOR TAMBEM LEVA MEDIDA, e esteve em percentagem com o argumento de que
   um nome de pessoa nao tem tamanho conhecido. O argumento nao estava errado; a
   conclusao estava. Com 16 % a coluna levava 225 pixeis a 1440 para «Técnico
   Responsável», que pede 150 -- setenta e cinco pixeis de ar numa coluna de tres
   palavras, e a crescer com o ecra. Um nome nao tem tamanho conhecido, mas tem
   tamanho TIPICO, e a percentagem estava a dimensionar pelo espaco disponivel em vez
   de pelo conteudo.

   Os 10,5rem chegam para «Maria Antónia Pereira»; um nome mais longo do que isso
   parte em duas linhas, e um nome partido em duas linhas le-se -- ao contrario de um
   identificador ou de um endereco IP, que partidos se leem como outro identificador
   e outro endereco. E por isso que este e o unico dos cinco dimensionado pelo caso
   tipico e nao pelo pior.

   E O DETALHE NAO LEVA LARGURA NENHUMA, de proposito: as outras cinco tem medida, e
   com `table-layout: fixed` a coluna sem largura declarada recebe tudo o que sobrar.
   Nao ha aqui percentagem nenhuma, e e o que faz com que o espaco a mais de um ecra
   grande va todo para um sitio em vez de ser repartido por seis. E onde esta o texto -- uma
   frase de aviso, uma mensagem de excepcao -- e e a unica coluna desta tabela que
   ganha alguma coisa com um ecra maior. Com os 40 % que aqui tinha, a 1920 levava
   espaco que nao usava enquanto o identificador do equipamento partia em duas
   linhas a 1024.

   A COLUNA DA ACCAO ESTAVA A 14 %, QUE DAVA 139 PIXEIS A 1024, e o resultado era
   vinte e oito dos trinta e seis nomes partidos em duas linhas, com a segunda linha
   a cair debaixo do simbolo -- lia-se como indentacao errada e nao como continuacao.
   Foi o que fez rever a tabela inteira. */
.tabela:has(td[data-rotulo$=" IP"]) th:nth-child(1) { width: 7rem; }
.tabela:has(td[data-rotulo$=" IP"]) th:nth-child(2) { width: 12.5rem; }
.tabela:has(td[data-rotulo$=" IP"]) th:nth-child(3) { width: 10.5rem; }
.tabela:has(td[data-rotulo$=" IP"]) th:nth-child(4) { width: 7rem; }
.tabela:has(td[data-rotulo$=" IP"]) th:nth-child(6) { width: 8rem; }

/* `/definicoes`, limiares e prazos.

   A primeira coluna deixou 66 % e ficou nos 52: as explicacoes que a esticavam
   passaram das linhas da tabela para a marca de ajuda, e o que la vive agora e o
   nome da definicao mais a chave. O que ela largou foi para a coluna «Aceita», que
   partia «um endereço de correio, ou vazio» em duas linhas em TODAS as larguras.
   A do valor tem `max-width: 20rem` no proprio grupo, e por isso nao cresce com a
   percentagem. */
.tabela:has(td[data-rotulo="Aceita"]) th:nth-child(1) { width: 52%; }
.tabela:has(td[data-rotulo="Aceita"]) th:nth-child(2) { width: 22%; }
.tabela:has(td[data-rotulo="Aceita"]) th:nth-child(3) { width: 26%; }

/* `/definicoes`, tarefas periodicas.

   A coluna do resultado passou de 22 % para 34 %, e e agora a mais larga da tabela.
   E onde esta o texto: cinco medidas na limpeza, uma mensagem de excepcao ate 180
   caracteres quando a tarefa rebenta. As outras tres tem tamanho conhecido -- um
   nome, «60 min», «há 4 horas» -- e nao ganham nada com espaco a mais. */
/* A COLUNA DO INTERVALO PASSOU DE 12 % PARA 20 % a 28 de Agosto de 2026, quando
   deixou de ser texto e passou a ter um selector com o botao de gravar ao lado.
   Doze por cento chegavam para «60 min»; nao chegam para «15 min», a seta do
   selector e «Guardar», e o que acontecia com menos era o texto ficar cortado
   dentro do controlo -- «diár», «15 ı» --, que nenhuma das verificacoes automaticas
   apanha porque nada rola e o contraste passa. Sai dos trinta por cento do nome, que
   os tinha de sobra: o mais comprido e «Detecção de agentes calados». */
.tabela:has(td[data-rotulo="Intervalo"]) th:nth-child(1) { width: 26%; }
.tabela:has(td[data-rotulo="Intervalo"]) th:nth-child(2) { width: 20%; }
.tabela:has(td[data-rotulo="Intervalo"]) th:nth-child(3) { width: 18%; }
.tabela:has(td[data-rotulo="Intervalo"]) th:nth-child(4) { width: 36%; }

/* `/definicoes`, contas. Seis colunas desde que as duas accoes se separaram. */
.tabela:has(td[data-rotulo="Conta"]) th:nth-child(1) { width: 21%; }
.tabela:has(td[data-rotulo="Conta"]) th:nth-child(2) { width: 21%; }
.tabela:has(td[data-rotulo="Conta"]) th:nth-child(3) { width: 15%; }
.tabela:has(td[data-rotulo="Conta"]) th:nth-child(4) { width: 17%; }
.tabela:has(td[data-rotulo="Conta"]) th:nth-child(5) { width: 12%; }
.tabela:has(td[data-rotulo="Conta"]) th:nth-child(6) { width: 14%; }

/* `/definicoes/notificacoes` */
.tabela:has(td[data-rotulo="Assunto"]) th:nth-child(1) { width: 13%; }
.tabela:has(td[data-rotulo="Assunto"]) th:nth-child(2) { width: 19%; }
.tabela:has(td[data-rotulo="Assunto"]) th:nth-child(3) { width: 38%; }
.tabela:has(td[data-rotulo="Assunto"]) th:nth-child(4) { width: 15%; }
.tabela:has(td[data-rotulo="Assunto"]) th:nth-child(5) { width: 15%; }

/* `/equipamentos/{id}`, ocorrencias abertas */
.tabela:has(td[data-rotulo="Aberta"]):not(:has(td[data-rotulo="Resolvida"])) th:nth-child(1) { width: 12%; }
.tabela:has(td[data-rotulo="Aberta"]):not(:has(td[data-rotulo="Resolvida"])) th:nth-child(2) { width: 74%; }
.tabela:has(td[data-rotulo="Aberta"]):not(:has(td[data-rotulo="Resolvida"])) th:nth-child(3) { width: 14%; }

/* `/equipamentos/{id}`, ocorrencias resolvidas */
.tabela:has(td[data-rotulo="Resolvida"]) th:nth-child(1) { width: 12%; }
.tabela:has(td[data-rotulo="Resolvida"]) th:nth-child(2) { width: 56%; }
.tabela:has(td[data-rotulo="Resolvida"]) th:nth-child(3) { width: 16%; }
.tabela:has(td[data-rotulo="Resolvida"]) th:nth-child(4) { width: 16%; }

/* `/equipamentos/{id}`, historico de relatorios */
.tabela:has(td[data-rotulo="Tamanho"]) th:nth-child(1) { width: 22%; }
.tabela:has(td[data-rotulo="Tamanho"]) th:nth-child(2) { width: 20%; }
.tabela:has(td[data-rotulo="Tamanho"]) th:nth-child(3) { width: 14%; }
.tabela:has(td[data-rotulo="Tamanho"]) th:nth-child(4) { width: 12%; }
.tabela:has(td[data-rotulo="Tamanho"]) th:nth-child(5) { width: 32%; }

/* `/equipamentos/{id}`, versoes do estado-base */
.tabela:has(td[data-rotulo="Motivo"]) th:nth-child(1) { width: 10%; }
.tabela:has(td[data-rotulo="Motivo"]) th:nth-child(2) { width: 22%; }
.tabela:has(td[data-rotulo="Motivo"]) th:nth-child(3) { width: 20%; }
.tabela:has(td[data-rotulo="Motivo"]) th:nth-child(4) { width: 48%; }

/* `/equipamentos/{id}`, auditoria do equipamento */
.tabela:has(td[data-rotulo="Quem"]) th:nth-child(1) { width: 15%; }
.tabela:has(td[data-rotulo="Quem"]) th:nth-child(2) { width: 20%; }
.tabela:has(td[data-rotulo="Quem"]) th:nth-child(3) { width: 18%; }
.tabela:has(td[data-rotulo="Quem"]) th:nth-child(4) { width: 47%; }

/* `/definicoes/base-de-dados` */
.tabela:has(td[data-rotulo="Aplicada"]) th:nth-child(2) { width: 40%; }
.tabela:has(td[data-rotulo="Aplicada"]) th:nth-child(3) { width: 22%; }
.tabela:has(td[data-rotulo="Aplicada"]) th:nth-child(4) { width: 24%; }

/* O corte de tabela para cartao, a 60rem.

   Abaixo desta largura cada linha vira um cartao. A excepcao esta no bloco
   seguinte, e explica-se la. */
@media (max-width: 60rem) {
    .tabela thead {
        display: none;
    }

    .tabela,
    .tabela tbody,
    .tabela tr,
    .tabela td {
        display: block;
        width: auto;
    }

    .tabela tbody tr,
    .tabela tr {
        height: auto;
        border-top: 1px solid var(--borda-fraca);
        padding: var(--e3) var(--e4);
    }

    /* Em cartao o nome do computador tem a largura toda e pode quebrar: as
       reticencias da tabela deixam de fazer falta. */
    .tabela .secundario-da-linha {
        white-space: normal;
        overflow: visible;
    }

    .tabela tr:first-child {
        border-top: 0;
    }

    .tabela tbody tr:nth-of-type(even) {
        background: var(--superficie-recuada);
    }

    .tabela tbody tr:hover {
        box-shadow: none;
        background: var(--linha-sobre);
    }

    .tabela td {
        padding: var(--e0) 0;
        border-top: 0;
    }

    .tabela th:first-child,
    .tabela td:first-child,
    .tabela th:last-child,
    .tabela td:last-child {
        padding-left: 0;
        padding-right: 0;
    }

    /* UMA CELULA SEM NADA A DIZER NAO OCUPA DUAS LINHAS NO TELEMOVEL.

       Em ecra grande, um `-` numa celula vazia mantem o alinhamento da tabela e le-se
       de relance como «nao ha». No telemovel a tabela vira cartao e cada celula ganha o
       rotulo por cima: «DESDE» numa linha e `-` na seguinte, duas linhas para nao dizer
       nada. Na pagina inicial eram tres das sete fichas.

       O `display: none` GANHA AO `display: block` das celulas porque a classe acrescenta
       especificidade e vem depois. E onde o vazio DIZ alguma coisa -- «sem cliente»,
       «ainda nao saiu daqui» -- a celula nao leva esta classe e continua a aparecer: o
       que se esconde e o traco, nao a ausencia. */
    .tabela td.celula-vazia {
        display: none;
    }

    .tabela td::before {
        content: attr(data-rotulo);
        display: block;
        font-size: var(--letra-xs);
        font-weight: 650;
        color: var(--tenue);
        text-transform: uppercase;
        letter-spacing: .04em;
        margin-bottom: var(--e0);
    }

    /* O identificador e o estado sobem para o topo da linha, lado a lado, e
       perdem o rotulo. Sao o titulo do cartao: rotula-los como aos outros
       campos fazia cada linha comecar com duas etiquetas a dizer o obvio, e
       com sete campos por linha isso e um terco da altura do ecra gasto em
       palavras que ninguem le. */
    .tabela tr {
        display: grid;
        grid-template-columns: minmax(0, 1fr) auto;
        gap: var(--e0) var(--e3);
        align-items: start;
    }

    .tabela td {
        grid-column: 1 / -1;
    }

    .tabela td.celula-principal {
        grid-column: 1;
        grid-row: 1;
        font-size: var(--letra-lg);
        margin-bottom: var(--e2);
    }

    .tabela td.celula-estado {
        grid-column: 2;
        grid-row: 1;
        text-align: right;
        /*
         * AS ETIQUETAS EMPILHAM-SE, E NAO FICAM LADO A LADO.
         *
         * Esta celula tinha uma etiqueta so ate a marca do silencio existir. Com duas,
         * a coluna da direita e `auto` e cresce ate caber as duas seguidas, e o que
         * paga a conta e a coluna da esquerda -- que e `minmax(0, 1fr)` e encolhe.
         * Medido a 360 px com «Sem comunicação» mais «Só as graves»: o identificador
         * partiu-se em TRES linhas, «T3C-» / «599-» / «499», e o nome do computador
         * logo a seguir em duas. Nada rolava na horizontal e o contraste passava, por
         * isso o `capturar_painel.py` deu tudo verde -- isto so se ve olhando.
         *
         * Empilhadas, a coluna pede a largura da etiqueta MAIS LARGA e nao a soma das
         * duas, que e exactamente o que ela ja pedia antes de haver a segunda.
         */
        display: flex;
        flex-direction: column;
        align-items: flex-end;
        gap: var(--e0);
    }

    .tabela td.celula-principal::before,
    .tabela td.celula-estado::before {
        content: none;
    }

    /*
     * A BARRA DA FAMILIA SAI, no cartao. Ficam o simbolo e o texto, que levam a cor.
     *
     * A barra existe para formar um carril: trinta e seis linhas empilhadas com o
     * filete todo no mesmo x, que se varre de relance sem ler nome nenhum. Num cartao
     * nao ha coluna nem empilhamento -- a accao e a segunda linha de sete --, e o que
     * a barra faz ali e outra coisa.
     *
     * Duas coisas, e as duas mas. Como e uma sombra INTERIOR, desenha-se dentro da
     * celula, e em cartao todas as celulas tem `padding: 0`: o filete caia por cima
     * da primeira letra do rotulo, e lia-se «|ACCAO» com o A cortado. Afastar o texto
     * com `padding-left` resolvia isso e trazia a seguinte -- «ACÇÃO» recuava doze
     * pixeis e deixava de estar alinhada com «UTILIZADOR» e «EQUIPAMENTO», que e a
     * coluna de rotulos que da forma ao cartao.
     *
     * Sem a barra, nao ha nada para afastar e nada desalinha. A cor nao se perde: o
     * simbolo e o nome continuam a te-la, e num cartao sao eles que se olham.
     *
     * E o `nowrap` e desfeito: aqui o nome tem a largura do cartao para ele, e nao
     * uma coluna repartida com cinco outras.
     */
    .tabela td[data-rotulo="Acção"] {
        box-shadow: none;
        white-space: normal;
    }

    /* Alvo de toque de 44px nas ligacoes das tabelas.
       Em ecra grande a linha inteira e alta e o rato acerta em qualquer sitio.
       Colapsada em cartao, cada ligacao fica com a altura de uma linha de texto,
       19 a 23 pixeis, e um dedo nao acerta nisso. Medido com o navegador, e nao
       por estimativa. */
    .tabela td a {
        display: flex;
        align-items: center;
        flex-wrap: wrap;
        min-height: 44px;
        padding: var(--e0) 0;
    }

    /* A `.ligacao-completa` estava na lista acima e depois era desfeita aqui: ficava
       com `align-items` e `flex-wrap` inertes num elemento `display: block`, e o
       `min-height` -- o unico que interessa, e o que foi medido -- escrito oito linhas
       acima do sitio onde e preciso. Mesmo desenho, uma intencao so, num sitio so. */
    .tabela td .ligacao-completa {
        display: block;
        min-height: 44px;
        margin: 0;
        padding: var(--e3) 0;
    }

    .marca {
        min-height: 44px;
    }

    /* Uma ligacao que ocupa sozinha o valor de uma ficha e um alvo como outro
       qualquer, e nao uma ligacao numa frase: cresce ate aos 44px. */
    .ficha dd > a:only-child {
        display: inline-flex;
        align-items: center;
        min-height: 44px;
    }

    /* E QUANDO O VALOR TEM DUAS LIGACOES, o `:only-child` deixa de casar -- e leva as
       DUAS com ele.

       Aconteceu a 18 de Setembro de 2026, ao pôr o «abrir no CRM» ao lado do nome do
       cliente na ficha do equipamento: a ligacao nova nascia com 19px, e a do nome, que
       ate ai cumpria, caiu para os mesmos 19px sem ninguem lhe ter tocado. O
       `capturar_painel.py` so nomeou a nova, porque foi a primeira que encontrou.

       A classe e explicita e nao um `:not(:only-child)`: quem escrever um `dd` com duas
       ligacoes tem de dizer que sao alvos, em vez de o herdar de um selector que casa
       por acidente. Ligacoes dentro de uma frase continuam de fora, como sempre. */
    .ficha dd.valor-com-ligacoes a {
        display: inline-flex;
        align-items: center;
        min-height: 44px;
    }

    .tabela td:empty {
        display: none;
    }

    .tabela td.numero {
        text-align: left;
    }

}

/* A altura minima de linha nao se aplica a uma linha que virou cartao.

   O bloco acima ja repunha `height: auto` em `.tabela tr`, e nao chegava: a
   regra dos 64 pixeis apanha-se por `tbody:has(.secundario-da-linha)`, que e
   mais especifica, e continuava a ganhar. O resultado via-se em `/definicoes`
   a 390: cada linha ficava com 64 pixeis para 189 de conteudo, e o valor de
   uma definicao aparecia escrito por cima do nome da seguinte.

   Fica ANTES da seccao 7.2 de proposito: a excepcao do tablet volta a fixar a
   altura para as tabelas que la continuam a ser tabelas, e para ganhar a esta
   precisa de vir depois. */
@media (max-width: 60rem) {
    .tabela tbody:has(.secundario-da-linha) tr {
        height: auto;
    }
}

/* -----------------------------------------------------------------
   7.2 O tablet fica com a tabela, quando a tabela cabe

   O corte para cartao era o mesmo para todas as tabelas, e nao devia ser: um
   ecra de 768 tem largura de sobra para as seis colunas curtas de
   `/equipamentos`, e em cartao cada equipamento gastava 270 pixeis de altura
   para seis campos que cabiam em 61. Onze equipamentos passavam de um ecra a
   tres.

   Mas o mesmo corte tambem apanha a tabela de `/`, que tem uma coluna de prosa,
   e essa a 768 nao cabe: medido, «O que se passa» ficava com 184 pixeis e o
   resumo de uma ocorrencia saia em oito linhas, com o cabecalho «Ultima
   comunicacao» a transbordar para fora do cartao. Aqui o cartao ganha.

   Por isso o corte deixa de ser um numero so. As tabelas de colunas curtas,
   nomeadas uma a uma como as larguras da seccao 7.1, voltam a ser tabelas a
   partir de 44rem; as que tem prosa esperam pelas 60rem.
   ----------------------------------------------------------------- */

@media (min-width: 44rem) and (max-width: 60rem) {
    .tabela:has(td[data-rotulo="Agente"]):has(td[data-rotulo^="Ocorr"]),
    .tabela:has(td[data-rotulo="Cliente desde"]),
    .tabela:has(td[data-rotulo="Perfil"]),
    .tabela:has(td[data-rotulo="Aplicada"]) {
        display: table;
        width: 100%;
    }

    .tabela:has(td[data-rotulo="Agente"]):has(td[data-rotulo^="Ocorr"]) thead,
    .tabela:has(td[data-rotulo="Cliente desde"]) thead,
    .tabela:has(td[data-rotulo="Perfil"]) thead,
    .tabela:has(td[data-rotulo="Aplicada"]) thead {
        display: table-header-group;
    }

    .tabela:has(td[data-rotulo="Agente"]):has(td[data-rotulo^="Ocorr"]) tbody,
    .tabela:has(td[data-rotulo="Cliente desde"]) tbody,
    .tabela:has(td[data-rotulo="Perfil"]) tbody,
    .tabela:has(td[data-rotulo="Aplicada"]) tbody {
        display: table-row-group;
    }

    .tabela:has(td[data-rotulo="Agente"]):has(td[data-rotulo^="Ocorr"]) tr,
    .tabela:has(td[data-rotulo="Cliente desde"]) tr,
    .tabela:has(td[data-rotulo="Perfil"]) tr,
    .tabela:has(td[data-rotulo="Aplicada"]) tr {
        display: table-row;
        padding: 0;
        border-top: 0;
        height: 64px;
    }

    .tabela:has(td[data-rotulo="Agente"]):has(td[data-rotulo^="Ocorr"]) tbody tr:nth-of-type(even),
    .tabela:has(td[data-rotulo="Cliente desde"]) tbody tr:nth-of-type(even),
    .tabela:has(td[data-rotulo="Perfil"]) tbody tr:nth-of-type(even),
    .tabela:has(td[data-rotulo="Aplicada"]) tbody tr:nth-of-type(even) {
        background: transparent;
    }

    .tabela:has(td[data-rotulo="Agente"]):has(td[data-rotulo^="Ocorr"]) td,
    .tabela:has(td[data-rotulo="Cliente desde"]) td,
    .tabela:has(td[data-rotulo="Perfil"]) td,
    .tabela:has(td[data-rotulo="Aplicada"]) td {
        display: table-cell;
        width: auto;
        padding: var(--e3);
        border-top: 1px solid var(--borda-fraca);
        text-align: left;
    }

    .tabela:has(td[data-rotulo="Agente"]):has(td[data-rotulo^="Ocorr"]) td:empty,
    .tabela:has(td[data-rotulo="Cliente desde"]) td:empty,
    .tabela:has(td[data-rotulo="Perfil"]) td:empty,
    .tabela:has(td[data-rotulo="Aplicada"]) td:empty {
        display: table-cell;
    }

    .tabela:has(td[data-rotulo="Agente"]):has(td[data-rotulo^="Ocorr"]) td.numero,
    .tabela:has(td[data-rotulo="Cliente desde"]) td.numero,
    .tabela:has(td[data-rotulo="Perfil"]) td.numero,
    .tabela:has(td[data-rotulo="Aplicada"]) td.numero,
    .tabela:has(td[data-rotulo="Agente"]):has(td[data-rotulo^="Ocorr"]) td.ao-fim,
    .tabela:has(td[data-rotulo="Aplicada"]) td.ao-fim {
        text-align: right;
    }

    .tabela:has(td[data-rotulo="Agente"]):has(td[data-rotulo^="Ocorr"]) td:first-child,
    .tabela:has(td[data-rotulo="Cliente desde"]) td:first-child,
    .tabela:has(td[data-rotulo="Perfil"]) td:first-child,
    .tabela:has(td[data-rotulo="Aplicada"]) td:first-child {
        padding-left: var(--e4);
    }

    .tabela:has(td[data-rotulo="Agente"]):has(td[data-rotulo^="Ocorr"]) td:last-child,
    .tabela:has(td[data-rotulo="Cliente desde"]) td:last-child,
    .tabela:has(td[data-rotulo="Perfil"]) td:last-child,
    .tabela:has(td[data-rotulo="Aplicada"]) td:last-child {
        padding-right: var(--e4);
    }

    /* O rotulo de cada celula era o titulo do campo dentro do cartao. Com
       cabecalho de tabela outra vez visivel, seria o mesmo texto duas
       vezes. */
    .tabela:has(td[data-rotulo="Agente"]):has(td[data-rotulo^="Ocorr"]) td::before,
    .tabela:has(td[data-rotulo="Cliente desde"]) td::before,
    .tabela:has(td[data-rotulo="Perfil"]) td::before,
    .tabela:has(td[data-rotulo="Aplicada"]) td::before {
        content: none;
    }

    .tabela:has(td[data-rotulo="Agente"]):has(td[data-rotulo^="Ocorr"]) td.celula-principal,
    .tabela:has(td[data-rotulo="Cliente desde"]) td.celula-principal,
    .tabela:has(td[data-rotulo="Perfil"]) td.celula-principal,
    .tabela:has(td[data-rotulo="Aplicada"]) td.celula-principal {
        font-size: var(--letra-base);
        margin-bottom: 0;
    }

    .tabela:has(td[data-rotulo="Agente"]):has(td[data-rotulo^="Ocorr"]) td a,
    .tabela:has(td[data-rotulo="Cliente desde"]) td a,
    .tabela:has(td[data-rotulo="Perfil"]) td a,
    .tabela:has(td[data-rotulo="Aplicada"]) td a {
        display: inline;
        min-height: 0;
        padding: 0;
    }

    .tabela:has(td[data-rotulo="Agente"]):has(td[data-rotulo^="Ocorr"]) td .ligacao-completa,
    .tabela:has(td[data-rotulo="Cliente desde"]) td .ligacao-completa,
    .tabela:has(td[data-rotulo="Perfil"]) td .ligacao-completa,
    .tabela:has(td[data-rotulo="Aplicada"]) td .ligacao-completa {
        display: block;
        margin: calc(var(--e3) * -1);
        padding: var(--e3);
    }

    .tabela:has(td[data-rotulo="Agente"]):has(td[data-rotulo^="Ocorr"]) .secundario-da-linha,
    .tabela:has(td[data-rotulo="Cliente desde"]) .secundario-da-linha,
    .tabela:has(td[data-rotulo="Perfil"]) .secundario-da-linha,
    .tabela:has(td[data-rotulo="Aplicada"]) .secundario-da-linha {
        white-space: nowrap;
        overflow: hidden;
    }
}

/* -----------------------------------------------------------------
   8. Etiquetas de estado e de gravidade

   Cada uma traz um simbolo em ::before. A cor sozinha nao chega: oito
   por cento dos homens nao distingue o vermelho do verde, e um painel
   que so use cor mente-lhes.
   ----------------------------------------------------------------- */

.etiqueta {
    display: inline-flex;
    align-items: center;
    gap: var(--e1);
    /* O PADDING E' ASSIMETRICO DE PROPOSITO, e a diferenca sao 0,05em.

       O `padding` nao envolve a tinta: envolve a CAIXA DE LINHA, que reserva espaco
       para descendentes e para acentos. Numa palavra que nao use esse espaco todo, a
       tinta assenta mais abaixo do que o meio da capsula -- medido em pixeis, a dez
       vezes a resolucao, nas seis etiquetas: +0,55 a +1,55 px, media +0,87.

       Tentou-se primeiro pelo `line-height`, que e' onde a assimetria nasce, e nao
       chega: o melhor valor (1.3) deixa +0,27 px e encolhe a capsula de 24 para 22,8
       px, o que mexe no alinhamento dela com tudo o que esta ao lado. Tirar a
       compensacao de cima e dar-lha em baixo sobe a tinta e NAO mexe na altura.

       O que sobra e' a diferenca entre palavras -- «Atenção» tem um `ç` que desce e
       «Crítico» nao --, e essa nao se corrige sem um numero por palavra. */
    padding: calc(var(--e0) - .05em) var(--e2) calc(var(--e0) + .05em);
    border-radius: var(--raio-total);
    border: 1px solid currentColor;
    font-size: var(--letra-sm);
    font-weight: 650;
    white-space: nowrap;
    background: var(--borda-fraca);
    color: var(--esbatido);
}

.etiqueta::before {
    font-weight: 700;
}

.etiqueta-saudavel {
    background: var(--saudavel-lavado);
    color: var(--saudavel);
}

.etiqueta-saudavel::before {
    content: "";
    --i: var(--icone-check);
}

.etiqueta-atencao {
    background: var(--atencao-lavado);
    color: var(--atencao);
}

.etiqueta-atencao::before {
    content: "";
    --i: var(--icone-warning);
}

.etiqueta-critico {
    background: var(--critico-lavado);
    color: var(--critico);
}

.etiqueta-critico::before {
    content: "";
    --i: var(--icone-x);
}

.etiqueta-sem_comunicacao {
    background: var(--sem-comunicacao-lavado);
    color: var(--sem-comunicacao);
}

/* Circulo vazio, e nao um traco: o traco longo esta fora do vocabulario deste
   projecto, e um circulo por encher le-se como «nao chegou nada», que e
   exactamente o que este estado quer dizer. */
.etiqueta-sem_comunicacao::before {
    content: "";
    --i: var(--icone-circle-dashed);
}

.etiqueta-informativo {
    background: var(--informacao-lavado);
    color: var(--informacao);
}

.etiqueta-informativo::before {
    content: "";
    --i: var(--icone-info);
}

.etiqueta-neutra {
    background: var(--superficie-recuada);
    color: var(--esbatido);
    border-color: var(--borda);
}

.etiqueta-neutra::before {
    content: none;
}

/* Estados de capacidade, na pagina de um relatorio. */
.etiqueta-presente {
    background: var(--saudavel-lavado);
    color: var(--saudavel);
}

.etiqueta-presente::before {
    content: "";
    --i: var(--icone-check);
}

.etiqueta-erro {
    background: var(--critico-lavado);
    color: var(--critico);
}

.etiqueta-erro::before {
    content: "";
    --i: var(--icone-x);
}

/* OS DOIS BADGES DE CONTAGEM DA LISTA DE CLIENTES.

   Vem sempre acompanhados de `.etiqueta-saudavel` ou `.etiqueta-critico`, que sao quem
   da a cor. O que estas duas classes fazem e' trocar o SIMBOLO: sem elas, os tres
   badges da celula apareciam os tres com o visto ou os tres com a cruz, e um visto
   verde a dizer «5» ao lado de outro visto verde a dizer «4» nao distingue o que se
   esta a contar de o que se esta a contar.

   VEM DEPOIS das regras da cor de proposito. A especificidade e' a mesma -- uma classe
   mais um pseudo-elemento nos dois lados --, e num empate ganha a ultima. Movidas para
   cima do `.etiqueta-saudavel::before`, deixavam de fazer efeito nenhum e nada acendia:
   os badges continuavam a desenhar-se, so que com o simbolo errado.

   E E' ISSO QUE SEGURA O AMARELO DA SUBSCRICAO. O badge do meio usa as tres cores --
   verde com todos subscritos, amarelo com alguns, vermelho com nenhum --, e a do meio
   e' `.etiqueta-atencao`, que traz o triangulo. Sem esta regra por cima, o badge da
   subscricao ficava com o mesmo simbolo do badge da atencao, que esta ao lado dele na
   mesma celula.

   O `content` repete-se aqui porque estas duas classes tem de poder pintar o simbolo
   sozinhas. Sem ele, um badge que um dia perdesse a classe da cor ficaria com a caixa
   do icone por preencher. */
.etiqueta-inventario::before {
    content: "";
    --i: var(--icone-desktop-tower);
}

.etiqueta-subscricao::before {
    content: "";
    --i: var(--icone-currency-eur);
}

/* -----------------------------------------------------------------
   9. Notas e mensagens

   TRES FILHOS, E SO TRES: o simbolo, o texto e, se existir, a accao.

   A nota e um contentor flex, e um contentor flex parte o que la esta
   dentro em items: cada `<b>`, cada `<a>` e cada troco de texto entre eles
   passava a ser uma caixa com 12 pixeis de intervalo a volta. Uma frase com
   uma ligacao a meio abria um espaco antes e depois dela, e o ponto final
   ficava a flutuar longe da palavra. Metade das notas do painel tinha um
   `<div>` de remendo a envolver o texto, e a outra metade nao tinha, o que
   explica porque e que a mesma nota se lia bem numa pagina e mal na
   seguinte.

   Aqui o `<div class="texto">` deixa de ser remendo e passa a ser regra: a
   prosa vive toda dentro dele, e o flex so tem de arrumar tres caixas.

   O simbolo em `::before` e o mesmo argumento das etiquetas: oito por cento
   dos homens nao distingue o vermelho do verde, e uma nota que so mude de
   cor nao lhes diz nada.
   ----------------------------------------------------------------- */

.nota {
    display: flex;
    gap: var(--e2);
    align-items: flex-start;
    padding: var(--e3) var(--e4);
    border-radius: var(--raio-2);
    font-size: var(--letra-md);
    line-height: 1.45;
    border: 1px solid var(--borda-fraca);
    background: var(--superficie-recuada);
    color: var(--texto);
    margin: 0 0 var(--e3);
    flex-wrap: wrap;
}

.nota:last-child {
    margin-bottom: 0;
}

/* O texto leva o espaco que sobra, e encolhe ate caber. Sem `min-width: 0`
   uma palavra comprida - um caminho, um endereco - estica a caixa. */
.nota .texto {
    flex: 1 1 16rem;
    min-width: 0;
    /* `margin: 0` porque o `.texto` do painel e um `<p>` (leva uma ligacao inline), e um
       `<p>` traz margens por omissao que abririam espaco a mais dentro da nota. Nos `.texto`
       que sao `<div>` isto nao muda nada. */
    margin: 0;
}

.nota::before {
    flex: none;
    font-weight: 700;
    /* A mesma altura de linha do texto, para o simbolo assentar na primeira
       linha e nao a meio da nota inteira. */
    line-height: 1.45;
}

.nota.atencao {
    background: var(--atencao-lavado);
    border-color: var(--atencao);
    color: var(--atencao);
}

.nota.atencao::before {
    content: "";
    --i: var(--icone-warning);
}

.nota.erro {
    background: var(--critico-lavado);
    border-color: var(--critico);
    color: var(--critico);
}

.nota.erro::before {
    content: "";
    --i: var(--icone-x);
}

.nota.exito {
    background: var(--saudavel-lavado);
    border-color: var(--saudavel);
    color: var(--saudavel);
}

.nota.exito::before {
    content: "";
    --i: var(--icone-check);
}

.nota.informacao {
    background: var(--informacao-lavado);
    border-color: var(--informacao);
    color: var(--informacao);
}

.nota.informacao::before {
    content: "";
    --i: var(--icone-info);
}

.nota b {
    font-weight: 650;
}

/* A accao nao estica a nota: fica com a altura de um botao pequeno e alinha
   pelo cimo, ao lado da primeira linha do texto. */
.nota .botao {
    margin-left: auto;
    flex: none;
    padding: var(--e1) var(--e3);
    min-height: 34px;
    font-size: var(--letra-sm);
    border-color: currentColor;
    background: transparent;
    color: inherit;
}

.nota .botao:hover:not(:disabled) {
    background: rgba(128, 128, 128, .14);
}

/* Uma nota comprida escreve-se em paragrafos, e o ultimo nao empurra o fundo
   da caixa. Sao tambem eles que dizem ao `capturar_painel.py` que uma ligacao
   la dentro esta numa frase, e nao e um alvo de toque solto. */
.nota .texto p:last-child {
    margin-bottom: 0;
}

/* Uma accao que precise de POST vem embrulhada num `<form>`, e o formulario
   passa a ser o filho da nota. Sem isto o `margin-left: auto` de cima ficava a
   empurrar o botao dentro de um formulario que ja e do tamanho dele, e a accao
   encostava ao texto em vez de encostar a direita. */
.nota > form {
    margin-left: auto;
    flex: none;
}

/* -----------------------------------------------------------------
   10. Formularios
   ----------------------------------------------------------------- */

.campos {
    display: grid;
    gap: var(--e3);
    grid-template-columns: repeat(12, minmax(0, 1fr));
}

.campo {
    display: flex;
    flex-direction: column;
    gap: var(--e1);
    min-width: 0;
    grid-column: span 6;
}

.campo.larga {
    grid-column: 1 / -1;
}

.campo.c4 {
    grid-column: span 4;
}

/* Um quarto da linha, para QUATRO campos curtos caberem lado a lado.
   Entrou a 18 de Setembro de 2026, quando o «Alterar dados» da ficha do
   equipamento passou a ter quatro selectores curtos -- nome, cliente, perfil e
   subscricao. Com `c4` o quarto caia sozinho para a linha seguinte e ficava a
   ocupar um terco de largura sem precisar de nenhum dele. */
.campo.c3 {
    grid-column: span 3;
}

.campo label {
    font-size: var(--letra-sm);
    font-weight: 600;
    color: var(--esbatido);
}

input,
select,
textarea {
    width: 100%;
    padding: var(--e2) var(--e3);
    font: inherit;
    font-size: var(--letra-base);
    color: var(--texto);
    background: var(--superficie-recuada);
    border: 1px solid var(--borda);
    border-radius: var(--raio-1);
    min-height: 40px;
    transition: border-color .12s, background .12s, box-shadow .12s;
}

textarea {
    resize: vertical;
    min-height: 74px;
    line-height: 1.5;
}

input:focus,
select:focus,
textarea:focus {
    border-color: var(--acento);
    background: var(--superficie);
}

input:focus-visible,
select:focus-visible,
textarea:focus-visible {
    outline: 2px solid var(--acento);
    outline-offset: 0;
    border-color: var(--acento);
    background: var(--superficie);
    box-shadow: 0 0 0 4px var(--foco);
}

select {
    appearance: none;
    -webkit-appearance: none;
    padding-right: 32px;
    cursor: pointer;
    background-image: var(--seta);
    background-repeat: no-repeat;
    background-position: right 10px center;
    background-size: 15px;
}

.ajuda {
    font-size: var(--letra-sm);
    color: var(--tenue);
    line-height: 1.4;
}

.filtros {
    display: flex;
    gap: var(--e3);
    flex-wrap: wrap;
    align-items: flex-end;
}

/* O `max-width` e o que impede que um filtro sozinho ocupe a barra inteira.

   Sem ele, o unico selector de `/auditoria` media 1289 pixeis a 1920 para
   escolher entre nove palavras, e o campo de valor das definicoes media 618
   para escrever um numero de dois digitos. Um campo largo nao le melhor: le
   pior, porque a etiqueta fica a um palmo do que rotula. */
.filtros .campo {
    grid-column: auto;
    flex: 1 1 180px;
    min-width: 140px;
    max-width: 22rem;
}

.filtros .campo.pesquisa {
    flex: 2 1 240px;
    max-width: 34rem;
}

/* O grupo dentro de uma celula nao ocupa a coluna inteira: um numero de dois
   digitos num campo de 618 pixeis nao se le melhor, le-se pior, porque o
   rotulo fica a um palmo do que rotula. */
.tabela td .grupo-controlo {
    max-width: 20rem;
}

/* Em ecra pequeno, um campo por linha. Um NIF e um nome nao precisam da
   mesma largura, mas abaixo de 45rem nenhum deles cabe ao lado do outro. */
@media (max-width: 45rem) {
    .campo,
    .campo.c3,
    .campo.c4 {
        grid-column: 1 / -1;
    }
}

/* ENTRE AS DUAS LARGURAS, O `c3` COMPORTA-SE COMO O `c4`.
   Quatro campos lado a lado precisam de largura a serio: a 48rem cada um ficava
   com pouco mais de 10rem, e um selector com «Utilização ocasional» la dentro
   corta a palavra. Dos 45rem aos 64rem passam a tres por linha, que e o que o
   `c4` sempre fez, e o quarto desce -- que continua a ser melhor do que quatro
   ilegiveis. */
@media (min-width: 45.0625rem) and (max-width: 64rem) {
    .campo.c3 {
        grid-column: span 4;
    }
}

/* O Safari do iPhone amplia a pagina quando um campo tem menos de 16px. */
@media (max-width: 48rem) {
    input,
    select,
    textarea {
        font-size: 16px;
    }
}

/* -----------------------------------------------------------------
   11. Listas de valores
   ----------------------------------------------------------------- */

/* VINTE E QUATRO CAIXAS DENTRO DE UM CARTAO ERAM VINTE E QUATRO CAIXAS A MAIS.

   Cada medida tinha fundo proprio, moldura propria e cantos proprios, dentro
   de um cartao que ja tinha os seus. O resultado era uma parede cinzenta em
   que «Cópia de segurança: Nenhuma» pesava exactamente o mesmo que «Modelo:
   IdeaPad 3 15ITL6», e nada saltava a vista porque tudo saltava a vista.

   Agora nao ha caixa nenhuma: ha um filete por cima de cada medida, que faz o
   trabalho de alinhamento que a moldura fazia e ainda faz outro por cima.
   Esse filete E A GRAVIDADE. Vermelho onde a medida esta ma, ambar onde esta
   morna, cinzento onde nao ha nada a dizer. Percorrer a grelha com os olhos
   passou a ser encontrar as marcas de cor, e nao ler vinte e quatro rotulos.

   O intervalo horizontal e maior do que o vertical de proposito: sao colunas
   de dados, e o que as separa umas das outras tem de ser mais visivel do que
   o que separa uma linha da seguinte. */
/* QUATRO PONTOS DE REPOUSO NUMA GRELHA QUE NAO TINHA NENHUM.

   O filete resolveu a parede cinzenta e criou outro problema, que so se ve com
   a grelha cheia: com cor em metade de vinte e sete posicoes ja nao ha marcas
   para encontrar, ha mosaico. Vermelho na primeira, vermelho na terceira, verde
   na oitava, na nona e na decima, ambar na decima primeira, e o plano fala em
   chegar as trinta e oito medidas.

   O que faltava nao era menos cor: era paragens. Quatro titulos com regua dao
   quatro sitios onde os olhos assentam, e dentro de cada bloco as medidas mas
   vem primeiro, de modo que os filetes vermelhos se juntam no principio de cada
   grupo em vez de andarem espalhados pela pagina inteira.

   Sem caixa nenhuma, que e o que a regra de composicao manda: um `h3` e espaco.
   Uma seccao dentro de um cartao nunca leva moldura, fundo nem sombra propria. */
.grupo-de-medidas + .grupo-de-medidas {
    margin-top: var(--e6);
}

/* A regua estende-se ate ao fim da largura disponivel, e o titulo fica preso ao
   bordo esquerdo com o resto do corpo. E um `::after` elastico, e nao um
   `border-bottom` no titulo: assim a linha comeca onde o texto acaba e nao
   passa por baixo dele.

   O corpo de letra e o mesmo dos rotulos das medidas, `--letra-xs`. Nao pode
   ser maior: um titulo de grupo que pese mais do que os valores que anuncia
   inverte a hierarquia que veio aqui construir. Distingue-se pela regua, que
   nenhum rotulo tem, e nao pelo tamanho. */
.titulo-do-grupo {
    display: flex;
    align-items: center;
    gap: var(--e3);
    margin: 0 0 var(--e4);
    font-size: var(--letra-xs);
    font-weight: 650;
    text-transform: uppercase;
    letter-spacing: .06em;
    color: var(--tenue);
}

.titulo-do-grupo::after {
    content: "";
    flex: 1 1 auto;
    height: 1px;
    min-width: var(--e5);
    background: var(--borda-fraca);
}

/* `auto-fill` E NAO `auto-fit`, E A DIFERENCA VE-SE A OLHO NU.

   O `auto-fit` colapsa as faixas que sobram, e por isso um grupo de quatro
   medidas esticava-as pela largura toda enquanto o grupo de seis por baixo as
   punha em seis colunas estreitas. Quatro grelhas diferentes empilhadas: a
   segunda coluna do armazenamento comecava a 345 pixeis e a da seguranca a 238,
   e a pagina lia-se como se estivesse desalinhada, porque estava.

   O `auto-fill` guarda as faixas vazias, de modo que todos os grupos partilham
   as mesmas colunas e um grupo curto deixa espaco a direita em vez de inchar. O
   espaco a direita nao e defeito nenhum: e o que diz que aquele grupo acabou.

   So dentro de `.grupo-de-medidas`: a mesma classe serve as definicoes e o
   detalhe de um relatorio, onde as listas sao curtas e esticar e o que se quer. */
.grupo-de-medidas .medidas {
    grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
}

/* ------------------------------------------------------------------
   A barra de resumo do «Estado do ultimo relatorio».
   ------------------------------------------------------------------
   Uma pilula por estado presente, com a contagem e a cor. Da o balanco do relatorio de
   relance -- «cinco nao ok, cinco a vigiar» --, e ao mesmo tempo e a legenda das cinco
   cores que se repetem nos filetes das medidas la em baixo. So aparecem os estados que
   existem: um zero nao e informacao que valha uma pilula. */
.resumo-de-estados {
    display: flex;
    flex-wrap: wrap;
    gap: var(--e2);
    margin-bottom: var(--e5);
}

.pastilha-estado {
    display: inline-flex;
    align-items: baseline;
    gap: var(--e1);
    padding: var(--e1) var(--e3);
    border-radius: var(--raio-total);
    font-size: var(--letra-sm);
    font-weight: 600;
    white-space: nowrap;
}

.pastilha-numero {
    font-size: var(--letra-base);
    font-weight: 700;
    font-variant-numeric: tabular-nums;
}

.pastilha-mau {
    background: var(--critico-lavado);
    color: var(--critico);
}

.pastilha-morno {
    background: var(--atencao-lavado);
    color: var(--atencao);
}

.pastilha-bom {
    background: var(--saudavel-lavado);
    color: var(--saudavel);
}

.pastilha-informativo {
    background: var(--acento-lavado);
    color: var(--acento-texto);
}

.pastilha-desconhecido {
    background: var(--superficie-recuada);
    color: var(--tenue);
}

/* A zero, a pastilha perde a cor do estado e fica neutra: continua la, na mesma posicao
   que teria noutra maquina, mas nao grita uma cor por um numero que e zero. Vem depois
   das cinco de cima para as vencer na cascata. */
.pastilha-vazia {
    background: var(--superficie-recuada);
    color: var(--tenue);
    font-weight: 500;
}

.pastilha-vazia .pastilha-numero {
    color: var(--tenue);
    font-weight: 600;
}

.medidas {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
    gap: var(--e4) var(--e5);
}

.medida {
    border-top: 3px solid var(--borda);
    padding-top: var(--e2);
    min-width: 0;
}

.medida-mau {
    border-top-color: var(--critico);
}

.medida-morno {
    border-top-color: var(--atencao);
}

/* O VERDE VOLTOU AO FILETE, E O QUE MUDOU FOI A GRELHA POR BAIXO DELE.

   Ate 22 de Agosto de 2026 as medidas boas eram as unicas sem cor no filete, e
   o motivo escrito era que «um filete verde por cada medida boa pintava a
   grelha inteira de verde». Era verdade numa fila corrida de vinte e sete, onde
   os quatro verdes da seguranca caiam entre um vermelho do disco e um ambar dos
   eventos e o resultado era vermelho-verde-verde-ambar-verde.

   Com quatro grupos e com as medidas mas a frente dentro de cada um, os verdes
   caem todos no FIM do seu bloco. A fila da seguranca le-se vermelho, ambar,
   verde, verde, verde, verde: uma escada, e nao uma parede. O argumento antigo
   caiu com a grelha que o sustentava.

   E o que ficou a perder sem ele era maior: numa fila em que todas as vizinhas
   tem um filete colorido, a medida sem filete nenhum nao se le como «nada a
   dizer», le-se como uma medida a que falta alguma coisa. */
.medida-bom {
    border-top-color: var(--saudavel);
}

/* O AZUL e o quinto estado: informativo. Um facto sem juizo de gravidade -- os
   processos a correr, o tempo ligado, a memoria virtual -- nao esta bem nem mal,
   e nao e uma leitura em falta. Tem cor propria para nao se confundir com nenhuma
   das outras quatro: o verde diria «esta bem», o cinzento diria «nao se leu». */
.medida-informativo {
    border-top-color: var(--acento);
}

/* Por definir: nao se conseguiu ler. Um cinzento que se ve -- e diferente de nao
   ter filete, que leria como «nada a dizer». O que ha a dizer e «isto ficou por
   saber», e isso tambem e informacao. */
.medida-desconhecido {
    border-top-color: var(--tenue);
}

/* O rotulo alinha com os vizinhos da mesma fila, e nao com um minimo fixo.

   A versao anterior reservava 2,5 linhas de altura a TODOS os rotulos, para
   os valores alinharem quando um deles tivesse duas linhas. Funcionava, e
   custava 14 pixeis de vazio por caixa em cada rotulo de uma linha so, seis
   vezes por fila, numa pagina que tem quase quarenta destas caixas.

   O subgrid faz o mesmo trabalho sem cobrar nada: cada caixa ocupa duas
   linhas da grelha de cima e herda-as, de modo que todos os rotulos da mesma
   fila partilham a mesma altura, e essa altura e a que a fila precisa. Se
   ninguem tiver duas linhas, ninguem paga por duas linhas.

   `row-gap` proprio, porque o subgrid herda tambem o intervalo do pai, e 12
   pixeis entre o rotulo e o seu valor separavam o que devia estar junto. */
.medida dt {
    /* Sem MAIUSCULAS, e o rotulo continua a distinguir-se do valor pelo tamanho e pela
       cor tenue. As maiusculas pequenas repetidas em duas duzias de rotulos davam a esta
       grelha um ar de formulario tecnico, e eram o que a fazia parecer montada a pressa.
       O destaque em cima e que grita; o detalhe fala baixo, mas em letra que se le. */
    font-size: var(--letra-sm);
    color: var(--tenue);
    font-weight: 600;
    margin-bottom: var(--e0);
    min-height: 2.5em;
    line-height: 1.3;
}

@supports (grid-template-rows: subgrid) {
    .medida {
        display: grid;
        grid-row: span 2;
        grid-template-rows: subgrid;
        row-gap: var(--e0);
        align-content: start;
    }

    .medida dt {
        min-height: 0;
        margin-bottom: 0;
    }
}

.medida dd {
    margin: 0;
    font-size: var(--letra-lg);
    font-weight: 600;
    overflow-wrap: break-word;
}

/* A nota por baixo do valor de uma medida.

   Usava `.relativo`, que existe para «ha 2 horas» e traz `white-space: nowrap`
   colado. Aplicada a prosa, a nota nao quebrava: cortava. Medido a 1280,
   «Bluetooth Device (Personal Area Network) (desactivado, provavelmente de
   proposito)» aparecia como «Bluetooth Device (Personal A...». Aqui quebra,
   e `anywhere` cobre o caso de uma palavra sozinha ser mais larga do que a
   caixa, que numa ficha de equipamento acontece. */
/* A ETIQUETA DO RELATORIO QUE CHEGOU ATRASADO.

   Informativa, e nao de gravidade. Um relatorio atrasado e um facto, e a causa mais
   comum e inteiramente normal -- um portatil que passou a tarde fechado. Leva a cor de
   quem nao julga, a mesma das medidas informativas, e nunca o vermelho: a cor de
   gravidade neste painel vem sempre das ocorrencias.

   Fica em linha com o texto ao lado, e nao em bloco, porque o que ela qualifica e a data
   que esta imediatamente antes dela. */
.etiqueta-atraso {
    display: inline-block;
    margin-left: var(--e2);
    /* 7px nao esta na escala de espacamento da seccao 1, que diz «nada fora deles» com
       uma unica excepcao declarada. Com a capsula redonda a folga lateral conta: o raio
       e metade da altura, 10,25 px, e e nas pontas que o texto se encosta. */
    padding: 1px var(--e2);
    border: 1px solid var(--acento-lavado);
    border-radius: var(--raio-total);
    background: var(--acento-lavado);
    color: var(--acento-texto);
    font-size: var(--letra-xs);
    font-weight: 600;
    line-height: 1.5;
    white-space: nowrap;
    vertical-align: middle;
    cursor: help;
}

/* Dentro de uma celula de tabela a data fica numa linha e a etiqueta na seguinte: a
   coluna «Recebido» e estreita, e as duas lado a lado empurravam a tabela para fora.

   ERA `display: table`, que e o encosto classico para uma caixa de bloco encolher ao
   conteudo, e DENTRO DE UMA TABELA DESFAZIA A CAPSULA. `border-collapse` herda-se, e
   `.tabela` declara `collapse`: a etiqueta herdava-o, e ao virar tabela caia no modelo
   de bordas colapsadas, onde o `padding` da propria tabela e ignorado e a borda e
   desenhada pelo algoritmo de colapso, que nao conhece `border-radius`.

   O resultado media-se, na ficha do equipamento a 1280 px: a caixa dava 88,25 px por
   18,5 em vez de 104,25 por 20,5, o texto ficava a 1 px do bordo em vez de 9, e a borda
   saia a esquadria por cima de um fundo redondo, com o fundo da pagina a espreitar pelos
   quatro cantos. Nada disto acendia em lado nenhum: a pagina desenha-se, nao rola e nao
   perde contraste, a etiqueta nao e alvo de toque, e nenhuma verificacao olha para a
   forma de um canto. Foi preciso alguem ampliar a etiqueta e reparar.

   `width: fit-content` encolhe ao conteudo na mesma e nao e tabela nenhuma: a etiqueta
   dentro da tabela passa a ser exactamente a mesma capsula que ja estava certa fora
   dela. */
.tabela .etiqueta-atraso {
    display: block;
    width: fit-content;
    margin: 3px 0 0;
}

/* O nome de um campo do relatorio: o legivel em cima, o do contrato por baixo.

   O do contrato fica em monoespacado e em cinzento porque e o que ele e -- uma chave de
   JSON, para copiar e para procurar --, e nao concorre com o nome que se le. */
.nome-do-campo {
    display: inline;
}

/* O cabecalho de tabela e maiusculas por folha de estilos, e a chave do contrato
   apanhava-as: `ESTADO_BRUTO` em vez de `estado_bruto`. Uma chave de JSON nao tem
   maiusculas, e escrita assim deixa de servir para o Ctrl+F. */
.tabela th .campo-do-contrato {
    text-transform: none;
    letter-spacing: normal;
}

.campo-do-contrato {
    display: block;
    margin-top: 1px;
    color: var(--esbatido);
    font-family: var(--mono);
    font-size: var(--letra-xs);
    font-weight: 400;
    overflow-wrap: anywhere;
}

/* Debaixo de um nome a 650 de peso, a chave herdava-o e ficava a competir com aquilo
   que devia acompanhar. Em `/definicoes` isso via-se em doze linhas seguidas. */
.principal-da-linha + .campo-do-contrato {
    font-weight: 400;
}

/* ------------------------------------------------------------------
   O RESULTADO DE UMA TAREFA PERIODICA, em `/definicoes`.
   ------------------------------------------------------------------
   `12 relatórios, 0 linhas de auditoria, 0 notificações, 3 limites, 1 pasta` sao cinco
   medidas numa frase corrida, todas com o mesmo peso. As que estao a zero -- que sao a
   maioria das passagens -- ocupam exactamente o mesmo espaco das que fizeram alguma
   coisa, e para saber se a limpeza apagou relatorios era preciso ler a frase toda.

   Uma medida por linha, com o numero em destaque a abrir. O texto e o mesmo, sem uma
   palavra reescrita; o que muda e poder-se varrer a coluna de cima a baixo em vez de a
   ler. E porque a coluna e agora a mais larga da tabela, o que se ganha em altura
   perde-se em linhas quebradas a meio.

   `tabular-nums` pela mesma razao de sempre: numeros que se comparam na vertical
   alinham. Aqui comparam-se os da mesma passagem e os da linha de cima. */
.resultado-da-tarefa {
    margin: 0;
    padding: 0;
    list-style: none;
    display: flex;
    flex-direction: column;
    gap: var(--e0);
}

.resultado-da-tarefa li {
    line-height: var(--linha-celula);
}

.resultado-da-tarefa .numero {
    font-weight: 650;
    font-variant-numeric: tabular-nums;
}

/* O ZERO NAO E UMA MEDIDA, e uma ausencia de medida.

   Esbatido, a linha continua legivel a 4,5 de contraste -- `--tenue` foi escolhido para
   isso -- e deixa de disputar o olhar com a que tem numero. Uma passagem em que nao
   houve nada para fazer le-se cinzenta de relance, sem ser preciso ler nenhum numero. */
.resultado-da-tarefa .a-zero {
    color: var(--tenue);
}

.resultado-da-tarefa .a-zero .numero {
    font-weight: 400;
}

/* A mensagem da excepcao, debaixo da etiqueta «Falhou». Vai ate 180 caracteres, que e o
   corte do `Despachante`, e por isso quebra em vez de ir por reticencias: numa mensagem
   de erro, a parte que interessa esta quase sempre no fim. */
.mensagem-de-falha {
    color: var(--critico);
    font-size: var(--letra-sm);
    line-height: 1.4;
}

/* A INTENCAO ESTAVA ESCRITA NO HTML E O CSS NAO A CUMPRIA.

   `.mau` e `.bom` so tinham regra dentro de `.medida dd` e de `.ficha-do-computador dd`.
   O `<td class="mau">` da tabela «Autorizados que continuam na versão antiga», em
   `/definicoes`, saia da cor do texto normal: a falha de actualizacao de um equipamento
   -- «o Windows recusou o ficheiro», «o resumo não confere» -- lia-se exactamente como a
   coluna do lado, que e um numero de versao. Era a unica ocorrencia da classe num `td`
   em todo o painel, e ninguem a viu porque nao ha nenhuma captura com um equipamento
   parado. */
.tabela td.mau {
    color: var(--critico);
}

.tabela td.bom {
    color: var(--saudavel);
}

/* ------------------------------------------------------------------
   A MARCA DE AJUDA, e o balao que ela abre.
   ------------------------------------------------------------------
   As explicacoes das medidas viviam por baixo do valor, em texto corrido. Uma frase de
   258 caracteres numa coluna de 180 pixeis ocupa seis linhas, e como a grelha alinha as
   linhas todas pela celula mais alta, a medida ao lado ficava com um palmo de branco por
   baixo. A grelha deixava de se ler como grelha.

   O que ficou por baixo do valor sao os COMPLEMENTOS -- «44,9 GB de 475,7 GB», «nos
   ultimos 30 dias» --, que sao curtos e falam daquele valor. As EXPLICACOES, que falam
   do campo e sao sempre as mesmas, passaram para aqui.

   O botao mede 44x44 e recupera o espaco com margem negativa: o alvo de toque cumpre o
   minimo de acessibilidade, e ocupa dezoito pixeis no desenho. Sem isto,
   `capturar_painel.py` marcava-o como alvo pequeno de mais -- e teria razao. */
.marca-ajuda {
    /* 44x44 de alvo de toque, dezoito pixeis de desenho: a margem negativa devolve o
       resto ao layout. Sem ela, `capturar_painel.py` marcava-o como alvo pequeno de
       mais -- e teria razao. */
    width: 44px;
    height: 44px;
    margin: -13px -15px -13px -11px;
    vertical-align: middle;
    padding: 0;
    border: 0;
    background: none;
    color: var(--esbatido);
    font: inherit;
    line-height: 1;
    cursor: help;
    /* O `?` que esta no HTML fica sem tamanho: existe para o leitor de ecra que ignora
       o `::before`, e quem ve o ecra le o do circulo. Havia um `font-size` tres linhas
       acima, a dizer `var(--letra-xs)`, que este apagava sempre: saiu a 22 de Setembro
       de 2026. */
    font-size: 0;
}

/* O circulo desenha-se aqui dentro, para o botao poder ser grande sem o parecer. */
.marca-ajuda::before {
    content: "";
    /* O `question` do Phosphor ja desenha o circulo a volta do ponto de
       interrogacao. Foi-se a borda, o raio e o fundo que estavam aqui a fazer
       esse circulo a mao. */
    --i: var(--icone-question);
    width: 16px;
    height: 16px;
    margin: 0 auto;
    transition: background-color .13s ease;
}

/* A marca escurece, e nao muda de cor. Uma bola azul no meio de um rotulo cinzento
   puxa mais atencao do que a coisa que ela explica. */
.marca-ajuda:hover::before,
.marca-ajuda:focus-visible::before {
    /* `background` e nao `color`: a marca e' agora uma mascara pintada de fundo, e
       a `border-color` que aqui estava deixou de ter borda a que se aplicar. */
    background: var(--texto);
}

/* A ETIQUETA DE AJUDA, uma so em toda a pagina, a acompanhar o cursor.

   `painel.js` cria-a uma vez, recolhe TODOS os `title` do painel para dentro dela, e
   move-a com o rato. Substituiu duas coisas ao mesmo tempo: o balao que estava escrito
   ao lado de cada medida, e o desenho que o proprio navegador fazia dos vinte e seis
   `title` das listas, dos botoes e das accoes. Havia duas ajudas com aspecto diferente
   na mesma pagina, e duas convencoes sao o mesmo que nenhuma.

   `position: fixed` porque as coordenadas vem do cursor, que sao da janela e nao do
   documento -- com `absolute`, uma pagina rolada punha a etiqueta a centenas de pixeis
   do sitio. E `pointer-events: none` porque uma etiqueta que apanhe o rato passa a
   tapar aquilo que se esta a apontar, e comeca a piscar.

   Sem JavaScript nao existe, e o `title` fica onde esta: o navegador desenha o dele, e
   o painel continua a explicar-se. */
.ajuda-flutuante {
    position: fixed;
    top: 0;
    left: 0;
    z-index: 90;
    /* 240 pixeis, e nao uma medida em `rem`: uma etiqueta que acompanha o rato tem de
       ser lida de relance, e uma linha larga obriga a percorrer o ecra com o cursor
       parado. */
    max-width: min(240px, calc(100vw - 2rem));
    padding: 6px 9px;
    border: 1px solid var(--borda-fraca);
    border-radius: var(--raio-1);
    background: var(--vidro-ajuda);
    color: var(--texto);
    box-shadow: var(--sombra-2);
    font-size: var(--letra-sm);
    font-weight: 500;
    line-height: 1.4;
    text-align: left;
    white-space: normal;
    overflow-wrap: break-word;
    pointer-events: none;
    /* A etiqueta acompanha o cursor com `transform`, e uma transicao nessa propriedade
       punha-a a arrastar-se atras do rato com um atraso visivel. So a entrada e que se
       anima. */
    animation: ajuda-a-aparecer .12s ease-out;
}

/* O desfoque atras do vidro. Fica dentro de um `@supports` porque nem todos os
   navegadores o tem, e sem ele a etiqueta continua legivel: quem garante o contraste e o
   ALFA do `--vidro-ajuda`, e o desfoque so acrescenta profundidade.

   DIZIA «o fundo a 0,90» ate 28 de Agosto de 2026, e nenhum tema teve alguma vez 0,90.
   O claro esta em `rgba(255,255,255,.72)` desde que nasceu; o escuro nasceu a 0,78 e
   desceu para 0,50. Um comentario que promete um numero que nao existe em lado nenhum e
   pior do que nao ter comentario, porque quem for mexer no alfa vai procurar o 0,90 e
   nao o encontra.

   OS NUMEROS MEDIDOS, com o alfa composto sobre o que esta por baixo e o texto em
   `--texto`, que e o par que a norma pede:

     claro .72 sobre --fundo #f5f5f7 ......... 17,97
     claro .72 sobre --superficie #ffffff .... 18,40
     claro .72 sobre --acento #2f6df6 ........ 12,63
     escuro .50 sobre --fundo #0a0a0d ........ 16,75
     escuro .50 sobre --superficie #1d1e23 ... 15,58
     escuro .50 sobre --superficie-recuada ... 14,70
     escuro .50 sobre --acento #4f8bff ....... 7,28

   O pior caso e o escuro por cima de um botao de acento, a 7,28, e mesmo esse fica muito
   acima dos 4,5 do minimo. Nas superficies onde a etiqueta aparece de facto -- fundo,
   cartao, linha recuada -- nao desce dos 14,7 em nenhum dos dois temas. E por isso que o
   0,50 do escuro se pode dar ao luxo de deixar ver o que esta por baixo: o que o alfa
   perde em opacidade nao chega perto de fazer falta ao texto. */
.ajuda-flutuante {
    -webkit-backdrop-filter: blur(6px) saturate(.9);
    backdrop-filter: blur(6px) saturate(.9);
}

.ajuda-flutuante[hidden] {
    display: none;
}

@keyframes ajuda-a-aparecer {
    from { opacity: 0; }
    to { opacity: 1; }
}


.nota-da-medida {
    display: block;
    margin-top: var(--e1);
    font-size: var(--letra-sm);
    font-weight: 400;
    line-height: 1.4;
    color: var(--esbatido);
    white-space: normal;
    overflow-wrap: anywhere;
}

.medida dd.bom {
    color: var(--saudavel);
}

.medida dd.mau {
    color: var(--critico);
}

.medida dd.morno {
    color: var(--atencao);
}


/* «nao foi possivel determinar» e um valor como os outros, e nao um valor
   mais pequeno: com dois corpos de letra diferentes, a mesma fila de medidas
   media 15, 13, 13 e 15 pixeis e nenhuma linha assentava na outra. Distingue-se
   pela cor e pelo peso, que chegam. */
.medida dd.desconhecido {
    color: var(--tenue);
    font-weight: 400;
}

/* O QUE A MAQUINA E, A FALAR MAIS BAIXO.

   Modelo, processador, memoria instalada, ranhuras, sistema operativo, data de
   instalacao e programas instalados eram SETE das vinte e sete caixas da
   grelha, com o mesmo corpo de letra e o mesmo peso 600 de «Cópia de segurança:
   Nenhuma». Um quarto da atencao da pagina gasto em linhas que nunca mudam de
   um relatorio para o outro e que nunca sao um problema.

   E exactamente o defeito que se corrigiu quando se tirou a moldura de cada
   medida: tirou-se a moldura e ficou o peso. Aqui deixam de ser medidas e
   passam a ficha, que e o que sempre foram: rotulo a esquerda, valor a direita,
   sem filete, sem maiusculas, em corpo de texto normal.

   A cor no valor mantem-se, e nao e incoerencia: a aptidao para o Windows 11 e
   as ranhuras livres tem juizo a fazer, e sao as duas perguntas desta ficha que
   valem dinheiro. O que se tirou foi o PESO, nao o significado.

   Colunas mais largas do que as das medidas porque cada linha leva rotulo mais
   valor lado a lado. O numero sai do campo mais comprido que aqui aparece:
   `11th Gen Intel(R) Core(TM) i5-1135G7` mede cerca de 215 pixeis a 14, e com
   os 148 do rotulo e os 24 do intervalo sao 387. A 300 quebrava em duas linhas
   em todas as maquinas Intel, que sao quase todas. */
.ficha-do-computador {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(390px, 1fr));
    gap: 0 var(--e5);
    margin: 0;
    font-size: var(--letra-base);
}

/* A linha por baixo de cada par faz o alinhamento que a grelha das medidas faz
   com o filete de cima. Sem ela, duas colunas de pares soltos leem-se como
   quatro colunas de texto. */
.ficha-do-computador > div {
    display: grid;
    grid-template-columns: minmax(0, 148px) minmax(0, 1fr);
    gap: var(--e3);
    align-items: baseline;
    padding: var(--e2) 0;
    border-bottom: 1px solid var(--borda-fraca);
}

.ficha-do-computador dt {
    color: var(--tenue);
    font-size: var(--letra-md);
    line-height: 1.4;
}

.ficha-do-computador dd {
    margin: 0;
    font-weight: 500;
    line-height: 1.4;
    overflow-wrap: break-word;
}

.ficha-do-computador dd.bom {
    color: var(--saudavel);
}

.ficha-do-computador dd.morno {
    color: var(--atencao);
}

.ficha-do-computador dd.mau {
    color: var(--critico);
}

.ficha-do-computador dd.desconhecido {
    color: var(--tenue);
    font-weight: 400;
}

/* Uma coluna so, quando duas nao cabem. Pela mesma razao da `.ficha`: com o
   rotulo a ocupar 148 dos 328 pixeis uteis de um ecra de 360, «11th Gen
   Intel(R) Core(TM) i5-1135G7» saia em cinco linhas.

   A REGRA DO CONTENTOR TEM DE ESTAR AQUI, e nao so a das linhas. Um
   `minmax(390px, 1fr)` nao encolhe abaixo dos 390: num ecra de 390 sobram 358
   uteis depois do avanco do corpo, e a ficha saia 33 pixeis para fora, com a
   pagina a rolar na horizontal. Foi o que `capturar_painel.py` apanhou, e e
   precisamente para isto que ela mede quatro larguras. */
@media (max-width: 34rem) {
    .ficha-do-computador {
        grid-template-columns: minmax(0, 1fr);
    }

    .ficha-do-computador > div {
        grid-template-columns: minmax(0, 1fr);
        gap: var(--e0);
    }
}

/* Par rotulo e valor, para fichas. */
.ficha {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    gap: var(--e2) var(--e4);
    font-size: var(--letra-base);
    margin: 0;
}

.ficha dt {
    color: var(--esbatido);
    font-size: var(--letra-md);
}

.ficha dd {
    margin: 0;
    overflow-wrap: break-word;
}

/* Uma coluna so, quando duas nao cabem.

   A coluna do rotulo era `auto`, ou seja, a largura do rotulo mais comprido.
   Em `/relatorios/{id}` esse rotulo e `tempo_funcionamento_segundos`, que mede
   226 pixeis. Num ecra de 360 sobravam 23 para o valor, e
   `2024-11-03T10:12:00Z` saia em sete linhas, letra a letra. Nao havia nada de
   errado com a quebra: nao havia largura nenhuma para quebrar.

   Abaixo de 34rem o rotulo passa para cima do valor e fica com a largura toda
   da caixa, que e o que qualquer ficha faz em telemovel. */
@media (max-width: 34rem) {
    .ficha {
        grid-template-columns: minmax(0, 1fr);
        gap: 0;
    }

    .ficha dt {
        margin-top: var(--e3);
        font-size: var(--letra-sm);
    }

    .ficha dt:first-of-type {
        margin-top: 0;
    }

    .ficha dd {
        margin-top: var(--e0);
    }
}

.ficha dd b {
    font-weight: 650;
}

.lista-valores {
    margin: 0;
    padding-left: var(--e4);
    font-size: var(--letra-base);
}

.lista-valores li {
    margin-bottom: var(--e0);
}

/* Identificador grande da ficha de um equipamento. */
.identificacao {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--e3);
    flex-wrap: wrap;
    padding-bottom: var(--e3);
    margin-bottom: var(--e3);
    border-bottom: 1px solid var(--borda-fraca);
}

.identificador {
    display: block;
    font-size: var(--letra-xxl);
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    line-height: 1.2;
}

.identificacao .nome {
    display: block;
    font-size: var(--letra-md);
    color: var(--esbatido);
    margin-top: var(--e0);
}

/* -----------------------------------------------------------------
   12. Medidores

   A largura vem de uma classe por decil e nao de um atributo style:
   a politica de seguranca de conteudos proibe estilos em linha, e e
   essa proibicao que impede um relatorio hostil de injectar CSS.
   ----------------------------------------------------------------- */

.medidor {
    height: 8px;
    border-radius: var(--raio-total);
    background: var(--borda-fraca);
    overflow: hidden;
    margin-top: var(--e2);
}

/* Um traco minimo, sempre.

   NASCEU DE UM CASO QUE JA NAO EXISTE, E CONTINUA A SERVIR PARA OUTRO.

   Quando a barra do espaco media o LIVRE, um disco a 0,9 % de espaco livre desenhava
   menos de dois pixeis: o unico elemento grafico do cartao ficava um carril cinzento
   vazio, que se le como controlo desligado e nao como disco cheio. A 3 de Setembro de
   2026 a barra passou a encher com o USO, e esse caso inverteu-se -- o disco cheio e
   agora o que desenha a barra toda.

   O minimo fica porque o caso simetrico continua a existir, so que do lado inofensivo:
   um disco praticamente vazio, ou um SSD com 0 % de desgaste, desenhariam nada. Com o
   minimo, ve-se um traco
   vermelho encostado a esquerda, que e exactamente o que a medida quer dizer. */
.medidor .enchimento {
    min-width: 3px;
    display: block;
    height: 100%;
    border-radius: var(--raio-total);
    background: var(--saudavel);
    transition: width .3s ease;
}

.medidor.morno .enchimento {
    background: var(--atencao);
}

.medidor.mau .enchimento {
    background: var(--critico);
}

/* As barras que enchem com o PROBLEMA nao sao verdes por omissao.

   O verde daqui de cima e o valor por omissao de todas as barras, e nas que medem
   sinal isso esta certo: mais barra e melhor. Nas que medem CARGA -- espaco em
   disco, desgaste do SSD, memoria virtual -- estava ao contrario. Um disco a 100 %
   usado sem ocorrencia aberta, porque a regra ainda nao correu ou porque o tecnico
   a ACEITOU, desenhava uma barra cheia e verde sobre um disco sem um byte livre.

   O verde e uma afirmacao, e a ausencia de ocorrencia nao a faz. Neutro por
   omissao; a cor da regra quando ela fala. As duas variantes vao escritas com as
   tres classes para nao dependerem da ordem das declaracoes neste ficheiro. */
.medidor.carga .enchimento {
    background: var(--esbatido);
}

/* E O VERDE VOLTA, mas so quando alguem o afirmou.

   O `bom` do `$classeDaRegra` quer dizer «a regra correu sobre este alvo e nao
   disparou», e isso e uma afirmacao. A classe VAZIA quer dizer «nao se avaliou», e
   fica no neutro da regra acima. Sao os dois casos que a primeira versao disto
   juntou, e por os juntar apagou o verde do painel inteiro. */
.medidor.carga.bom .enchimento {
    background: var(--saudavel);
}

.medidor.carga.morno .enchimento {
    background: var(--atencao);
}

.medidor.carga.mau .enchimento {
    background: var(--critico);
}

.enchimento-0 { width: 0; }
.enchimento-10 { width: 10%; }
.enchimento-20 { width: 20%; }
.enchimento-30 { width: 30%; }
.enchimento-40 { width: 40%; }
.enchimento-50 { width: 50%; }
.enchimento-60 { width: 60%; }
.enchimento-70 { width: 70%; }
.enchimento-80 { width: 80%; }
.enchimento-90 { width: 90%; }
.enchimento-100 { width: 100%; }

/* -----------------------------------------------------------------
   13. Registos: o estado e a abertura

   O estado tem de estar visivel em todas as paginas, e nao numa que seja
   preciso ir procurar: com ele aberto, qualquer executavel que chegue ao
   servidor cria um equipamento.

   SAO DUAS COISAS, E POR ISSO SAO DUAS FORMAS

   O ESTADO nao se clica: e uma frase, e fica como uma frase, sem moldura
   nenhuma. A ABERTURA clica-se: e um controlo, e leva uma moldura so.

   A versao anterior metia as duas dentro de uma capsula de cantos redondos,
   e dentro dessa capsula um selector com cantos proprios e um botao com
   cantos proprios. Tres molduras encaixadas, tres raios diferentes e duas
   alturas diferentes, para uma accao so. Aqui o selector e o botao sao duas
   metades da MESMA caixa, separadas por uma linha, e a caixa e uma.

   Fechado, o conjunto e cinzento e nao pede nada a ninguem. Aberto, passa a
   vermelho e a unica accao que oferece e fecha-lo, porque enquanto estiver
   aberto e isso que interessa.
   ----------------------------------------------------------------- */

.registos {
    display: flex;
    align-items: center;
    gap: var(--e3);
    min-width: 0;
}

.registos-estado {
    display: inline-flex;
    align-items: center;
    gap: var(--e2);
    font-size: var(--letra-md);
    font-weight: 600;
    color: var(--esbatido);
    white-space: nowrap;
}

/* Cinzento neutro, e nao a cor de «sem comunicacao».

   As duas coisas nunca tiveram que ver uma com a outra - partilhavam o simbolo
   por o cinzento servir as duas - e desde que «sem comunicacao» passou a
   amarelo isso deixou de ser inocente: um ponto amarelo ao lado de «Registos
   fechados» diz «atencao» a respeito do estado SEGURO. */
.registos-estado .sinal {
    --i: var(--icone-lock-key);
    width: 15px;
    height: 15px;
    flex: none;
    display: block;
    background: var(--tenue);
    -webkit-mask: var(--i) center / contain no-repeat;
    mask: var(--i) center / contain no-repeat;
    print-color-adjust: exact;
    -webkit-print-color-adjust: exact;
}

.registos.abertos .registos-estado {
    color: var(--critico);
}

/* ABERTO, O CADEADO ABRE-SE. Antes era um ponto com um halo a dizer «isto esta a
   acontecer agora»; o halo saiu com o ponto, porque uma sombra desenha-se a volta da
   CAIXA e nao da forma, e a volta de um cadeado dava um rectangulo luminoso.

   Nao se perde sinal nenhum: a forma passou a dizer o que a cor ja dizia -- e diz
   melhor, porque um cadeado aberto le-se do outro lado da sala e um ponto vermelho
   e' so mais um ponto vermelho -- e o filete do topo continua onde estava. */
.registos.abertos .sinal {
    --i: var(--icone-lock-key-open);
    background: var(--critico);
}

@media (forced-colors: active) {
    .registos-estado .sinal {
        background: CanvasText;
    }
}

/* Quantos faltam criar e quanto tempo falta: o texto ao lado do estado, com
   peso normal, para nao competir com ele. */
.registos-detalhe {
    font-weight: 400;
    color: var(--tenue);
    font-variant-numeric: tabular-nums;
}

.registos.abertos .registos-detalhe {
    color: inherit;
}

/* A contagem nao leva caixa nenhuma, por decisao explicita do responsavel do
   projecto a 18 de Setembro de 2026. A versao anterior punha-a numa pilula com
   largura minima, para o «Fechar já» nao andar para tras e para a frente quando
   o numero muda de largura -- e essa largura minima somada ao resto da frase
   fazia o conjunto passar a DUAS linhas, que e um defeito maior do que o que
   resolvia. Os digitos tabulares do `.registos-detalhe` ja seguram os numeros;
   o que sobra e um caracter de diferenca entre «9 segundos» e «10 segundos»,
   e esse ve-se muito menos do que uma segunda linha no cabecalho. */
.registos-contagem {
    white-space: nowrap;
}

/* -----------------------------------------------------------------
   Grupo de controlo: uma caixa, duas metades

   Serve para um controlo que so faz sentido acompanhado da escolha que o
   precede - aqui, «quantos computadores» mais «abrir». A moldura e do
   grupo; as metades sao chatas por dentro e so as separa uma linha.
   ----------------------------------------------------------------- */

.grupo-controlo {
    display: flex;
    align-items: stretch;
    height: 34px;
    border: 1px solid var(--borda);
    border-radius: var(--raio-2);
    background: var(--superficie);
}

.grupo-controlo > .parte {
    height: 100%;
    min-height: 0;
    margin: 0;
    border: 0;
    border-radius: 0;
    background-color: transparent;
    font: inherit;
    font-size: var(--letra-md);
    font-weight: 600;
    color: var(--texto);
}

/* `background-color` e nao `background`: a forma curta apagava a seta do
   selector, que e uma imagem de fundo declarada na seccao 10. */
.grupo-controlo > select.parte {
    width: auto;
    padding: 0 30px 0 var(--e3);
    border-radius: calc(var(--raio-2) - 1px) 0 0 calc(var(--raio-2) - 1px);
    background-position: right 9px center;
    cursor: pointer;
}

/* Um campo de texto tambem serve de primeira metade: e o que junta o valor de
   uma definicao ao botao que o grava, e faz das duas coisas um objecto so em
   vez de um campo com um botao a flutuar ao lado. */
.grupo-controlo > input.parte {
    flex: 1 1 auto;
    width: auto;
    min-width: 0;
    padding: 0 var(--e3);
    border-radius: calc(var(--raio-2) - 1px) 0 0 calc(var(--raio-2) - 1px);
    /* O fundo recuado e o que distingue o que se escreve do que se carrega. Um
       campo branco encostado a um botao branco e uma caixa comprida em que nao
       se sabe onde acaba um e comeca o outro. */
    background-color: var(--superficie-recuada);
    font-weight: 400;
    font-variant-numeric: tabular-nums;
}

/* Um selector NO LUGAR do campo de texto, e nao ao lado dele.

   O intervalo de recolha so aceita oito valores -- tem de dividir 24 --, e uma
   lista evita que o tecnico escreva um numero que o formulario vai recusar. Mas
   sem esta regra o selector herdava o `width: auto` da regra de cima, que existe
   para os selectores estreitos do resto da pagina: encolhia ao tamanho do texto,
   e o botao de gravar ficava a flutuar a meio da caixa com um vazio a seguir.

   Estica como o campo de texto, e usa o mesmo fundo recuado, porque faz o mesmo
   papel: e a metade onde se escolhe, contra a metade onde se carrega. */
.grupo-controlo > select.parte-valor {
    flex: 1 1 auto;
    width: auto;
    min-width: 0;
    background-color: var(--superficie-recuada);
    font-weight: 400;
    font-variant-numeric: tabular-nums;
}

/* O SELECTOR DO INTERVALO CORTAVA O TEXTO, e nenhuma medicao o apanhava.
   O `min-width: 0` da regra de cima existe para o cartao «Limiares e prazos», onde a
   celula e larga e o selector estica. Na tabela das tarefas periodicas a coluna e
   estreita - divide o espaco com «Ultima execucao» e «Resultado» -, e o mesmo zero
   deixava o selector encolher ABAIXO do texto: «diário» saia «diár» e «15 min» saia
   «15 ı», com a letra cortada a meio.
   O `capturar_painel.py` dava tudo verde, e dava-o com razao: nada rolava na horizontal,
   o contraste passava e nao havia erro de JavaScript nenhum. Texto cortado dentro de um
   controlo nao e nada disso - e das coisas que so se veem OLHANDO para as capturas, que
   e o que a seccao 12 do CLAUDE.md manda fazer a seguir a medir.
   `auto` e nao um numero em rem: o tamanho minimo automatico de um item flexivel e o do
   conteudo dele, portanto acompanha sozinho a opcao mais larga da lista. Um valor fixo
   ficaria curto no dia em que alguem acrescentasse «de 2 em 2 dias». */
.grupo-controlo > select.parte-intervalo {
    min-width: auto;
}

/* `--luz` e um fio branco a seis por cento no bordo de cima, e no tema claro e
   transparente. E' o que impede que a metade da accao se leia como a metade
   VAZIA de um campo comprido: no escuro, o fundo do campo (`--superficie-recuada`)
   e mais claro do que o do botao (`--superficie`), e sem uma marca propria os
   dois trocam de papel. */
.grupo-controlo > .parte-accao {
    display: inline-flex;
    align-items: center;
    padding: 0 var(--e4);
    border-left: 1px solid var(--borda);
    border-radius: 0 calc(var(--raio-2) - 1px) calc(var(--raio-2) - 1px) 0;
    box-shadow: var(--luz);
    color: var(--esbatido);
    cursor: pointer;
    white-space: nowrap;
    transition: background-color .12s, color .12s;
}

.grupo-controlo > .parte-accao:hover {
    background-color: var(--borda-fraca);
    color: var(--texto);
}

.grupo-controlo > .parte:focus-visible {
    outline: 2px solid var(--acento);
    outline-offset: -2px;
    background-color: var(--superficie);
    box-shadow: none;
}

/* -----------------------------------------------------------------
   14. Estados vazios e paginacao
   ----------------------------------------------------------------- */

.vazio {
    padding: var(--e5) var(--e4);
    text-align: center;
    color: var(--tenue);
    font-size: var(--letra-md);
}

.vazio strong {
    display: block;
    color: var(--esbatido);
    font-size: var(--letra-base);
    font-weight: 600;
    margin-bottom: var(--e1);
}

/* O `margin-top` ja la estava, e nao chegava: num `inline-flex` sem quebra
   antes, o botao ficava pendurado no fim da ultima frase, com a margem a
   empurra-lo para baixo do texto que tinha ao lado. A margem provava a
   intencao que o CSS nao cumpria. Com `flex` e margem automatica, o botao tem
   uma linha sua e fica centrado, que era o que se queria desde o inicio. */
.vazio .botao {
    display: flex;
    width: fit-content;
    margin: var(--e4) auto 0;
}

td .vazio,
dd .vazio,
span.vazio {
    display: inline;
    padding: 0;
    color: var(--tenue);
    font-style: normal;
}

/* Nenhum `summary` do painel usa o triangulo do sistema.

   `details.cartao` e `.aceitar` ja o tiravam cada um por sua conta, e o
   `<details>` de «Alterar palavra-passe», na tabela de contas, nao era nem
   um nem outro: ficava com o triangulo preto do navegador no meio de uma
   pagina que nao tem mais nenhum, e com 21 pixeis de altura para o dedo.
   A regra passa a ser de toda a folha, e a seta desenha-se sempre aqui. */
summary {
    list-style: none;
}

summary::-webkit-details-marker {
    display: none;
}

/* Um `summary` que nao seja cartao nem `.aceitar` porta-se como uma ligacao
   com seta, e tem o alvo de toque que a norma pede. */
/* Um `details` solto, fora de um cartao: dentro de uma celula de tabela, ou
   debaixo de um formulario. Cinzento e nao azul - o azul deste painel e o das
   ligacoes, e uma tabela onde a unica coisa azul e um comando que nao navega
   para lado nenhum ensina a carregar no sitio errado. */
details:not(.cartao):not(.aceitar) > summary {
    display: inline-flex;
    align-items: center;
    gap: var(--e2);
    min-height: 44px;
    cursor: pointer;
    color: var(--esbatido);
    font-weight: 600;
    user-select: none;
}

details:not(.cartao):not(.aceitar) > summary:hover {
    color: var(--texto);
}

/* DENTRO DE UMA CELULA DE TABELA, o `summary` assenta na linha do botao ao lado.

   E o «Alterar» da coluna «Palavra-passe», em `/definicoes`, contra o «Desactivar» da
   coluna seguinte. As celulas alinham pelo topo, o `summary` mede 44 e o
   `.botao.pequeno` mede 34: o texto de um centra a 22 pixeis do topo e o do outro a 17,
   e as duas colunas de accao da mesma linha ficavam cinco pixeis desencontradas. Cinco
   pixeis nao se nomeiam a olho; veem-se na mesma, como uma tabela mal assente.

   Os 44 continuam a valer abaixo de 60rem, que e onde a tabela vira cartao e onde o
   alvo de toque e medido. Acima disso quem aponta e um rato, e ao lado esta um botao de
   34 que ninguem falha. E o unico `details` do painel dentro de um `td`. */
.tabela td > details:not(.cartao):not(.aceitar) > summary {
    min-height: 34px;
}

@media (max-width: 60rem) {
    .tabela td > details:not(.cartao):not(.aceitar) > summary {
        min-height: 44px;
    }
}

/* Uma celula de accao onde nao ha accao nenhuma: «não se aplica», na conta que nao se
   pode desactivar a si propria. Assenta na mesma linha que o botao das linhas vizinhas,
   pela mesma razao e com a mesma medida. */
.accao-ausente {
    display: inline-flex;
    align-items: center;
    min-height: 34px;
}

.paginacao {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--e3);
    padding: var(--e3) var(--e4);
    border-top: 1px solid var(--borda-fraca);
    font-size: var(--letra-md);
    color: var(--esbatido);
    flex-wrap: wrap;
}

.paginacao .paginas {
    display: flex;
    gap: var(--e2);
}

/* -----------------------------------------------------------------
   15. Utilitarios
   ----------------------------------------------------------------- */

.espaco-acima {
    margin-top: var(--e4);
}

/* Um degrau de quatro pixeis, para colar um segundo elemento ao primeiro
   dentro da mesma celula sem os separar como se fossem coisas diferentes. */
.espaco-minimo {
    margin-top: var(--e1);
}

.espaco-abaixo {
    margin-bottom: var(--e4);
}

.relativo {
    color: var(--esbatido);
    font-size: var(--letra-sm);
    white-space: nowrap;
}

.quebravel {
    word-break: break-all;
}

pre.dados {
    background: var(--superficie-recuada);
    border: 1px solid var(--borda-fraca);
    border-radius: var(--raio-1);
    padding: var(--e3);
    font-size: var(--letra-sm);
    overflow-x: auto;
    white-space: pre-wrap;
    word-break: break-all;
    margin: 0;
    color: var(--esbatido);
    font-family: var(--mono);
}

/* Barras de deslocamento finas, na cor do acento.
   As duas familias sao exclusivas: desde o Chrome 121, definir
   scrollbar-width desliga os ::-webkit-scrollbar. */
@supports not selector(::-webkit-scrollbar) {
    :root {
        scrollbar-width: thin;
        scrollbar-color: var(--acento) transparent;
    }
}

*::-webkit-scrollbar {
    width: 5px;
    height: 5px;
}

*::-webkit-scrollbar-track {
    background: transparent;
}

*::-webkit-scrollbar-thumb {
    background: var(--acento);
    border-radius: 3px;
}

*::-webkit-scrollbar-corner {
    background: transparent;
}


/* -----------------------------------------------------------------
   16. Paginas autonomas: entrada, erros e instalador

   Nao tem navegacao nem sessao. Ja tiveram CSS embebido em <style>, o que
   nao funcionava: a politica de seguranca de conteudos e `style-src 'self'`
   sem `unsafe-inline`, e em producao o navegador RECUSAVA esses blocos.
   O ecra de entrada e os 403, 404 e 500 apareciam sem formatacao nenhuma.
   Agora usam esta folha, como o resto.

   Dividida em duas, porque as duas paginas deixaram de ser a mesma coisa:

     16.1  Caixa unica, dos 403, 404 e 500. Uma pagina de erro tem uma frase
           e uma saida, e mais nada lhe faz falta.
     16.2  Entrada. E o unico ecra do produto que alguem ve antes de saber o
           que o produto e, e por isso tem identidade, e nao so um campo e um
           botao. Ver o comentario proprio, mais abaixo.
     16.3  Instalador, em /a. Reaproveita inteira a estrutura da 16.2 - e a
           mesma situacao, pagina sem sessao com identidade e uma caixa - e
           so acrescenta o que e proprio dela.
   ----------------------------------------------------------------- */

/* -----------------------------------------------------------------
   16.1 Caixa unica: 403, 404 e 500
   ----------------------------------------------------------------- */

.pagina-central {
    min-height: 100vh;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: var(--e5);
}

.caixa-central {
    width: 100%;
    max-width: 360px;
    background: var(--superficie);
    border: 1px solid var(--borda-fraca);
    border-radius: var(--raio-3);
    box-shadow: var(--sombra-2), var(--luz);
    padding: var(--e5);
}

/* A caixa larga e a da verificacao de requisitos, que leva uma tabela de tres
   colunas la dentro. A 520 pixeis, «Escrita em dados/registos» partia-se em
   duas linhas e «a funcionar nos dois sentidos» em outras duas, numa pagina
   com mil e quatrocentos pixeis de largura livre a volta. */
.caixa-central.larga {
    max-width: 720px;
}

.caixa-central .botao {
    width: 100%;
    min-height: 44px;
}

/* Uma tabela dentro da caixa central encosta ao avanco da propria caixa.

   As celulas trazem 16 pixeis de avanco proprio, para se alinharem com o
   cabecalho de um cartao. Dentro da caixa central esses 16 somavam-se aos 24
   dela, e a nota de estado ficava dezasseis pixeis a esquerda da primeira
   coluna da tabela que estava logo por baixo. */
.caixa-central .tabela th:first-child,
.caixa-central .tabela td:first-child {
    padding-left: 0;
}

.caixa-central .tabela th:last-child,
.caixa-central .tabela td:last-child {
    padding-right: 0;
}

.codigo-erro {
    font-size: var(--letra-xs);
    font-weight: 650;
    text-transform: uppercase;
    letter-spacing: .04em;
    line-height: 1;
    color: var(--tenue);
    font-variant-numeric: tabular-nums;
    margin: var(--e2) 0 var(--e4);
}

/* -----------------------------------------------------------------
   16.2 Entrada

   Duas colunas em ecra largo, identidade a esquerda e formulario a
   direita; uma coluna abaixo de 58rem, porque a frase da esquerda deixa
   de caber ao lado de um campo de texto sem estrangular os dois. A ordem
   no HTML e a mesma nos dois casos, e por isso quem le com leitor de ecra
   ou sem folha de estilos le sempre na ordem certa.

   Os simbolos decorativos sao declarados AQUI, presos a `.entrada`, e nao
   na seccao 1: so esta pagina os usa, e o vocabulario geral do painel nao
   deve engordar com o que serve um ecra so. Sao redeclarados nos dois
   blocos de tema escuro pela mesma razao da seccao 2: um bloco para quem
   nao escolheu tema e tem o sistema escuro, outro para quem escolheu.
   ----------------------------------------------------------------- */

.entrada {
    /* Brilho do acento e cor da grelha, tema claro. */
    --brilho-entrada: rgba(47, 109, 246, .11);
    --brilho-entrada-longe: rgba(47, 109, 246, .07);
    --linha-entrada: rgba(20, 20, 24, .05);

    position: relative;
    min-height: 100vh;
    padding: 34px 24px 26px;

    /* Duas linhas, e nao uma coluna flexivel centrada: a primeira ocupa o
       que sobra e centra o conteudo, a segunda encosta a nota ao fundo do
       ecra. Com tudo centrado junto, a nota ficava suspensa a meio do
       espaco vazio, que e onde nenhum rodape deve estar. */
    display: grid;
    grid-template-rows: 1fr auto;
    align-items: center;
    justify-items: center;
    gap: 24px;

    /* Fundo em tres camadas: dois brilhos do acento em cantos opostos, que
       dao profundidade, e uma grelha fina por cima, que e o que impede que
       a superficie pareca uma parede lisa. A grelha e a de um instrumento
       de medida, que e o que o produto e.

       `fixed` prende as tres camadas ao ecra: sem isso a grelha andava com
       a rolagem em telemovel, e uma grelha que anda le-se como ruido. */
    background-color: var(--fundo);
    background-image:
        radial-gradient(60rem 34rem at 12% -12%, var(--brilho-entrada), transparent 68%),
        radial-gradient(48rem 30rem at 92% 108%, var(--brilho-entrada-longe), transparent 70%),
        linear-gradient(var(--linha-entrada) 1px, transparent 1px),
        linear-gradient(90deg, var(--linha-entrada) 1px, transparent 1px);
    background-size: auto, auto, 100% 58px, 58px 100%;
    /* `fixed` prende a grelha ao ecra em vez de a fazer andar com a rolagem, que e o
       que se quer num fundo. O Safari do iOS trata-o como `scroll` em alguns casos: a
       degradacao e a grelha acompanhar a rolagem, e nao a pagina partir-se. Verificado
       apenas em Chromium. */
    background-attachment: fixed;
}

/* A barra do navegador em telemovel come parte dos 100vh. Onde houver
   `dvh`, a altura passa a ser a que se ve mesmo. */
.entrada {
    min-height: 100dvh;
}

/* Preso ao ecra, e nao ao conteudo: assim nao empurra nada, nao cria
   rolagem horizontal e fica no mesmo sitio do cabecalho do painel. */
.canto-tema {
    position: fixed;
    top: 14px;
    right: 14px;
    z-index: 2;
}

.canto-tema .botao-icone {
    width: 40px;
    height: 40px;
}

.entrada-interior {
    position: relative;
    width: 100%;
    max-width: 58rem;
    display: grid;
    grid-template-columns: minmax(0, 1fr) 23.5rem;
    align-items: center;
    gap: 3.25rem;
}

.identidade {
    min-width: 0;
}

.marca-entrada {
    display: flex;
    align-items: center;
    gap: 12px;
    margin: 0 0 10px;
    font-size: var(--letra-numero);
    font-weight: 700;
    letter-spacing: -1px;
    line-height: 1.1;
}

.marca-entrada svg {
    flex: none;
    color: var(--acento);
}

.frase-entrada {
    margin: 0 0 14px;
    font-size: var(--letra-xl);
    font-weight: 600;
    letter-spacing: -.2px;
}

.texto-entrada {
    margin: 0;
    color: var(--esbatido);
    font-size: var(--letra-lg);
    line-height: 1.6;
}

.pontos-entrada {
    list-style: none;
    margin: 20px 0 0;
    padding: 0;
    display: grid;
    gap: 10px;
}

.pontos-entrada li {
    position: relative;
    padding-left: 22px;
    color: var(--esbatido);
    font-size: var(--letra-md);
    line-height: 1.45;
}

/* Ponto com halo, e nao um travessao nem um visto: o visto e vocabulario
   do estado saudavel na seccao 8, e nao se gasta aqui. */
.pontos-entrada li::before {
    content: "";
    position: absolute;
    left: 2px;
    top: .5em;
    width: 6px;
    height: 6px;
    border-radius: var(--raio-total);
    background: var(--acento);
    box-shadow: 0 0 0 3px var(--acento-lavado);
}

/* `--sombra-2`, a mesma da caixa central do 404 e dos requisitos.

   Era a `--sombra-3`, e ficava a flutuar muito acima de tudo o resto do
   produto: tres escalas de elevacao em tres paginas, quando ha duas situacoes
   e nao tres - um cartao pousado na pagina, e uma caixa que fala sozinha. */
.cartao-entrada {
    position: relative;
    overflow: hidden;
    background: var(--superficie);
    border: 1px solid var(--borda-fraca);
    border-radius: var(--raio-3);
    box-shadow: var(--sombra-2), var(--luz);
    padding: var(--e5) var(--e5) var(--e5);
}

/* Fio de acento no topo do cartao: o unico sitio da pagina onde o acento
   e superficie, e o que amarra o formulario a marca do lado. */
.cartao-entrada::before {
    content: "";
    position: absolute;
    inset: 0 0 auto;
    height: 2px;
    background: linear-gradient(90deg, transparent, var(--acento), transparent);
}

.cartao-entrada h2 {
    font-size: var(--letra-xl);
    margin-bottom: 18px;
}

.cartao-entrada .nota {
    margin-bottom: 16px;
}

.cartao-entrada form {
    display: flex;
    flex-direction: column;
    gap: 14px;
}

/* `.campo` nasce da grelha de doze colunas da seccao 10. Aqui o pai e uma
   coluna flexivel, e a coluna herdada nao tem sentido nenhum. */
.cartao-entrada .campo {
    grid-column: auto;
}

.cartao-entrada .botao {
    width: 100%;
    min-height: 46px;
    margin-top: 2px;
}

.rodape-entrada {
    position: relative;
    width: 100%;
    max-width: 58rem;
    margin: 0;
    color: var(--tenue);
    font-size: var(--letra-sm);
    text-align: center;
}

/* -----------------------------------------------------------------
   16.3  Pagina do instalador, em /a

   Vive dentro do mesmo `.entrada` e do mesmo `.cartao-entrada` da pagina
   de entrada, porque e a mesma situacao: uma pagina sem sessao e sem
   navegacao, com identidade a esquerda e uma caixa a direita. So o que
   e proprio do instalador esta aqui.

   Ha uma diferenca real e e esta: aqui o botao e um `<a>` e nao um
   `<button>`. O `.cartao-entrada .botao` acima ja lhe da a largura
   inteira e os 46 pixeis de altura; falta-lhe o alinhamento vertical,
   que num `<a>` de bloco nao vem de lado nenhum.
   ----------------------------------------------------------------- */

.versao-instalador {
    margin: -10px 0 18px;
    color: var(--esbatido);
    font-size: var(--letra-sm);
}

.nota-instalador {
    margin: 12px 0 0;
    color: var(--tenue);
    font-size: var(--letra-sm);
}

/* O separador nao e enfeite: acima esta o caminho normal, abaixo esta o
   caminho para quem sabe o que e um PowerShell. Sem a linha, as duas
   coisas leem-se como uma lista de passos a seguir por ordem. */
.alternativa-instalador {
    margin-top: 20px;
    padding-top: 18px;
    border-top: 1px solid var(--borda-fraca);
}

.alternativa-instalador .nota-instalador {
    margin-top: 0;
    margin-bottom: 10px;
}

/* O comando nao se parte a meio: quem o copia com o rato tem de levar a
   linha inteira. `pre.dados` parte por caracter, o que aqui daria
   `irm https://pulsio.t3c.` numa linha e o resto na seguinte. */
.alternativa-instalador pre.dados {
    white-space: pre;
    word-break: normal;
    color: var(--texto);
}

/* Abaixo desta largura a coluna da esquerda cai abaixo de 28rem, e uma
   frase estrangulada ao lado de um campo de texto le-se pior do que a
   mesma frase por cima dele. */
@media (max-width: 58rem) {
    .entrada-interior,
    .rodape-entrada {
        max-width: 29rem;
    }

    .entrada-interior {
        grid-template-columns: minmax(0, 1fr);
        gap: 26px;
    }

    .marca-entrada {
        font-size: var(--letra-xxl);
        gap: 10px;
    }

    .marca-entrada svg {
        width: 24px;
        height: 24px;
    }

    .frase-entrada {
        font-size: var(--letra-lg);
        margin-bottom: 10px;
    }

    .texto-entrada {
        font-size: var(--letra-base);
    }

    .pontos-entrada {
        margin-top: 16px;
    }
}

/* Alvo de toque a norma em telemovel.

   A norma pede 44 pixeis, e o painel tinha 18 na ligacao do equipamento de
   uma ocorrencia, 21 no `summary` de «aceitar como normal», 32 no botao do
   cabecalho, 34 nos botoes pequenos, 38 no botao de icone e 41 no botao
   normal. Nenhum deles estava longe, e nenhum deles la chegava. Ficam todos
   aqui juntos, e nao espalhados por seis regras, para se ver de uma vez o que
   e que o dedo tem de acertar. */
@media (max-width: 48rem) {
    .canto-tema .botao-icone {
        width: 44px;
        height: 44px;
    }

    .botao,
    .botao.pequeno,
    .nota .botao {
        min-height: 44px;
    }

    /* A altura vai para as METADES, e nao para o grupo.

       Com 44 no grupo, cada metade ficava com 42: o dedo acerta no que tem area
       propria, e as bordas do grupo nao contam para ela. */
    .grupo-controlo {
        height: auto;
    }

    .grupo-controlo > .parte {
        min-height: 44px;
    }

    /* O selector do cabecalho de um cartao segue a mesma regra: 34 pixeis sao os
       do ecra grande, onde ele assenta ao lado do titulo. */
    .cartao > header .filtro-de-cabecalho select {
        min-height: 44px;
    }

    .botao-icone {
        width: 44px;
        height: 44px;
    }

    /* Um campo de formulario e um alvo de toque como outro qualquer. Ficavam
       nos 40 e nos 42, este por causa dos 16px de corpo que o Safari do iPhone
       exige para nao ampliar a pagina. */
    input,
    select,
    textarea {
        min-height: 44px;
    }

    .aceitar > summary,
    details:not(.cartao):not(.aceitar) > summary {
        min-height: 44px;
    }

    /* A ligacao do equipamento, dentro da linha de dados de uma ocorrencia.
       Deixa de alinhar pela base para poder crescer em altura sem descolar do
       resto da linha. */
    .meta-equipamento {
        min-height: 44px;
        align-items: center;
    }
}

@media (prefers-color-scheme: dark) {
    :root:not([data-tema="claro"]) .entrada {
        --brilho-entrada: rgba(79, 139, 255, .14);
        --brilho-entrada-longe: rgba(79, 139, 255, .08);
        --linha-entrada: rgba(255, 255, 255, .035);
    }
}

:root[data-tema="escuro"] .entrada {
    --brilho-entrada: rgba(79, 139, 255, .14);
    --brilho-entrada-longe: rgba(79, 139, 255, .08);
    --linha-entrada: rgba(255, 255, 255, .035);
}

/* -----------------------------------------------------------------
   17. Lista de ocorrencias
   -----------------------------------------------------------------

   Era uma tabela de seis colunas, e o responsavel do projecto apontou o
   que isso fazia: o nome do cliente e o identificador do equipamento
   partiam-se a meio, porque seis colunas nao cabem sem espremer nenhuma.

   O conteudo tambem nao e tabular. Uma ocorrencia e um resumo comprido
   em prosa mais quatro dados curtos, e uma tabela da a cada um a mesma
   largura quando e o resumo que precisa dela toda.
   ----------------------------------------------------------------- */

/* `padding: 0` nao e enfeite: uma `<ul>` nasce com 40 pixeis de avanco a
   esquerda para os pontos que aqui nao existem. Medido a 360, a lista de
   ocorrencias comecava a 40px do bordo do cartao e o resumo de cada uma
   perdia esses 40 pixeis de largura, todos. */
.lista-ocorrencias {
    list-style: none;
    margin: 0;
    padding: 0;
}

.ocorrencia {
    display: grid;
    gap: var(--e2);
    padding: var(--e3) var(--e4);
    border-bottom: 1px solid var(--borda-fraca);
    /* Filete de gravidade a esquerda: a cor le-se de relance, e a etiqueta
       confirma-a para quem nao a distingue. */
    border-left: 3px solid transparent;
}

.ocorrencia:last-child {
    border-bottom: 0;
}

/* Um filho de grid nasce com `min-width: auto`, o que significa «pelo menos a largura
   do meu conteudo». Um resumo comprido ou um nome de cliente comprido esticavam a
   celula, a celula esticava a grelha, e a pagina inteira passava a rolar na
   horizontal. Medido a 360px: 432px de largura numa lista que devia ter 328.
   O `min-width: 0` e o que autoriza o filho a encolher e o texto a quebrar. */
.ocorrencia > * {
    min-width: 0;
}

/* As TRES gravidades, e nao duas. O `informativo` faltava aqui, e a lista emite-o
   mesmo: uma alteracao de estado-base -- memoria que cresceu, disco novo, nome do
   computador mudado -- sai do `ComparadorEstadoBase` com esta gravidade e chega a
   /ocorrencias com `class="ocorrencia ocorrencia-informativo"`. Sem regra, ficava com
   o filete transparente da linha 3505, ou seja, sem filete nenhum ao lado de duas
   irmas que o tem. A etiqueta ja tinha a cor; o filete e que nao. */
.ocorrencia-critico { border-left-color: var(--critico); }
.ocorrencia-atencao { border-left-color: var(--atencao); }
.ocorrencia-informativo { border-left-color: var(--informacao); }

/* O QUARTO, QUE OS AVISOS TROUXERAM. Um aviso respondido e a unica linha destas
   listas que e boa noticia, e nao havia filete verde nenhum para lhe dar.

   Sem ele, o cartao «Avisos ao cliente» de uma ficha desenhava items SEM filete
   ao lado de ocorrencias COM filete, no mesmo ecra e com a mesma marcacao. A
   etiqueta comecava colada ao bordo do cartao e a linha ficava a flutuar, o que
   e exactamente o «completamente diferente dos outros» que se via a olho.

   A COR SAI DA MESMA FAMILIA DA ETIQUETA, e nao de uma paleta nova: e o mesmo
   principio que a vista ja segue ao reaproveitar `etiqueta-saudavel` e
   companhia. Um estado de aviso nao e uma gravidade, mas le-se pelas mesmas
   tres perguntas - esta a decorrer, correu bem, correu mal - e o painel ja tem
   cor escolhida para as tres. */
.ocorrencia-saudavel { border-left-color: var(--saudavel); }
.ocorrencia-neutra { border-left-color: var(--borda); }

.ocorrencia-topo {
    display: flex;
    align-items: flex-start;
    gap: var(--e3);
}

/* A linha SO quebra quando o formulario esta aberto, e nunca quando esta
   fechado.

   Com quebra permanente, um resumo comprido - «A partição de sistema EFI tem
   apenas 11,4 MB livres de 100,0 MB...» - empurrava o gatilho para uma linha
   propria numas ocorrencias e nao noutras, e a lista ficava com items de duas
   e de tres linhas alternados sem nada que o explicasse. Sem quebra, o resumo
   encolhe e parte-se dentro da sua largura, e o gatilho fica sempre na mesma
   coluna.

   Aberto e ao contrario: o formulario precisa da largura toda, e para isso
   tem de passar para a linha de baixo.

   Sem `:has()` fica a versao sem quebra, que continua a funcionar - o
   formulario e' que reparte a linha com o resumo. */
.ocorrencia-topo:has(> .aceitar[open]) {
    flex-wrap: wrap;
}

/* A etiqueta nao encolhe nem quebra, aconteca o que acontecer ao resumo.

   E tem largura MINIMA, para o resumo comecar sempre no mesmo sitio. «Crítico»
   e «Atenção» tem larguras diferentes, e sem isto o bordo esquerdo do texto
   abanava nove pixeis para a direita e para a esquerda ao longo da lista,
   conforme a gravidade de cada linha.

   E FICA CENTRADA COM A PRIMEIRA LINHA DO RESUMO, que e' a frase que se le ao
   lado dela. A etiqueta tem 24 px de altura - 12 px de letra a 1,5, mais 2+2
   de preenchimento e 1+1 de bordo - e a primeira linha do resumo tem 20,3 -
   14 px a 1,45. Centrar uma na outra pede que a etiqueta comece 1,85 px ACIMA
   do texto, e nao 1 px abaixo: com `margin-top: 1px` o desnivel medido entre
   os dois centros era de 3,5 px, e a pastilha lia-se pousada mais abaixo do
   que a frase.

   E -2px e nao -1,85px porque meio pixel nao se desenha. Medido a -2, o
   desnivel fica em 0,5 px.

   MEDE-SE CONTRA A PRIMEIRA LINHA e nao contra o bloco todo, e por isso e' um
   deslocamento fixo e nao `align-items: center` no pai: com o resumo a quebrar
   em duas linhas, centrar o pai punha a etiqueta entre as duas. Um titulo de
   aviso pode ter 120 caracteres, e a 641 px ja quebra. */
.ocorrencia-topo > .etiqueta {
    flex: 0 0 auto;
    margin-top: -2px;
    min-width: 6.5rem;
}

.ocorrencia-resumo {
    margin: 0;
    font-size: var(--letra-base);
    line-height: 1.45;
    color: var(--texto);
}

/* Os dados curtos vao todos na mesma linha, e NENHUM deles quebra.
   Quando nao cabem, mudam de linha inteiros. */
.ocorrencia-meta {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: var(--e1) var(--e4);
    font-size: var(--letra-sm);
    color: var(--esbatido);
}

.meta-item,
.meta-equipamento {
    display: inline-flex;
    align-items: baseline;
    gap: var(--e1);
    min-width: 0;
    max-width: 100%;
}

/* Quem NAO pode quebrar e o identificador, o codigo da regra e o alvo. O nome de um
   cliente pode e deve: medido a 360px, «Associação de Reformados e Pensionistas do
   Concelho...» com nowrap ocupava 432px e empurrava a pagina inteira. */
/* O `text-overflow: ellipsis` estava aqui desde sempre e NUNCA actuou: sem largura
   maxima, o elemento cresce ate o texto caber e nao ha nada para cortar. Com um cliente
   chamado «Condomínio do Edifício Nossa Senhora da Conceição e São João Baptista de Vila
   Nova de Gaia, Administração Conjunta dos Blocos A, B e C, Lote 14, Rés-do-chão» -- 150
   caracteres, que e o maximo que a coluna aceita e existe mesmo --, o nome ocupava metade
   da linha de metadados e empurrava o codigo da regra e a data para fora do olhar. As
   tres informacoes tem o mesmo direito ao espaco, e a que varia de tamanho e a que tem
   de ceder.

   O `min()` deixa o corte acontecer so quando ha por onde cortar: em telemovel o item ja
   ocupa a linha toda e 100% ganha. */
.meta-item {
    display: inline-block;
    max-width: min(24rem, 100%);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    vertical-align: bottom;
}

.meta-equipamento {
    white-space: nowrap;
}

.meta-equipamento {
    font-weight: 650;
    color: var(--acento-texto);
    text-decoration: none;
}

.meta-equipamento:hover {
    /* Sem sublinhado: um sinal discreto por opacidade chega. */
    opacity: 0.7;
}

/* O nome amigavel e o unico que pode ser cortado: o identificador nunca.

   E cortado quando NAO CABE, e nao aos 22 caracteres. Um limite em `ch` nao
   sabe quanto espaco ha: cortava o nome em todas as larguras, inclusive a
   1920 com 440 pixeis livres a direita, e o nome do computador e o que o
   tecnico usa para reconhecer a maquina. Com `flex-shrink` a fazer o
   trabalho, as reticencias so aparecem quando a linha esta mesmo cheia. */
.meta-nome {
    font-weight: 400;
    color: var(--esbatido);
    overflow: hidden;
    text-overflow: ellipsis;
    flex: 0 1 auto;
    min-width: 0;
}

/* `.vazio` dentro de um item da linha de dados: fica com a cor de uma
   ausencia, e mantem o `inline-block` que o corte com reticencias exige. */
.ocorrencia-meta .meta-item.vazio {
    display: inline-block;
    padding: 0;
}

.meta-alvo {
    font-family: var(--mono);
    font-size: var(--letra-xs);
    color: var(--tenue);
}

.ocorrencia-meta code {
    font-size: var(--letra-xs);
}

/* Nunca quebrar. Para identificadores, codigos e nomes de ficheiro. */
.sem-quebra {
    white-space: nowrap;
}


/* -----------------------------------------------------------------
   A linha de um AVISO: o que foi dito a esquerda, o que o cliente
   fez a direita

   A lista dos avisos reaproveita a linha das ocorrencias, e ate 22 de
   Setembro de 2026 reaproveitava-a INTEIRA -- com os cinco dados do
   aviso enfiados na mesma fileira de items cinzentos que uma
   ocorrencia usa para tres. O resultado era uma frase corrida,
   «T3C-076-454 G3 Loja Vítor Silva escrito há 2 dias carregou em
   «Entendido» ao fim de 50 segundos válido até 03/10/2026», onde
   «G3 Loja  Vítor Silva» se lia como uma coisa so e onde a resposta
   do cliente -- a unica coisa daquela pagina que prova alguma coisa
   -- tinha exactamente o mesmo peso que a data de validade.

   E ao lado disto, mais de metade da largura em branco: uma ocorrencia
   enche o lado direito com o gatilho do «É normal neste computador»,
   e um aviso nao tem gatilho nenhum.

   O QUE ESTE BLOCO FAZ e dar ao desfecho uma coluna propria. Resolve
   as duas coisas de uma vez: a informacao que interessa ganha peso e
   posicao fixa, e o vazio da direita passa a ter conteudo.

   A COLUNA E FIXA, E NAO `auto`. Com `auto` cada linha media a largura
   do seu proprio texto e o desfecho comecava num sitio diferente em
   cada uma; encostado a direita com `justify`, ficava a novecentos
   pixeis do titulo com um deserto pelo meio. Largura fixa mais filete
   e o que faz a coluna existir para o olho.
   ----------------------------------------------------------------- */

/* AO TOPO E NAO AO CENTRO, e e a primeira linha de cada coluna que o
   decide. Centradas, a frase do desfecho nascia 6 px abaixo do titulo que
   lhe fica ao lado e o pormenor 4 px acima da fileira de dados: as duas
   colunas desencontradas nas duas alturas, o que numa lista se ve de
   imediato porque se repete em cada linha. Alinhadas ao topo, o titulo e a
   frase partem do mesmo pixel -- as duas em 14 px, com 0,7 px entre as
   bases --, que e a linha por onde o olho corre. */
.lista-avisos .ocorrencia {
    grid-template-columns: minmax(0, 1fr) 19rem;
    align-items: start;
    column-gap: var(--e4);
    padding: var(--e4);
}

.aviso-corpo {
    display: grid;
    gap: var(--e2);
    min-width: 0;
}

/* O `min-width: 0` OUTRA VEZ, UM NIVEL ABAIXO, e nao e repeticao: e a
   mesma armadilha do `.ocorrencia > *` la em cima, recriada por esta
   camada.

   A etiqueta, o resumo e a fileira de dados eram filhos directos de
   `.ocorrencia` e apanhavam la o `min-width: 0`. Com o `.aviso-corpo`
   pelo meio passaram a ser netos, e voltaram a nascer com o
   `min-width: auto` de qualquer filho de grelha -- ou seja, «pelo menos
   a largura do meu conteudo».

   Medido a 390px, antes de isto existir: o nome de um cliente com 90
   caracteres esticava o `.ocorrencia-meta` para 500 pixeis dentro de um
   cartao de 326, e a pagina inteira passava a rolar na horizontal. A
   correccao anterior tinha reintroduzido o proprio defeito que
   corrigia. */
.aviso-corpo > * {
    min-width: 0;
}

/* `align-self: stretch` da o filete de cima a baixo da linha -- e o que
   o faz parecer uma coluna e nao um traco solto --, e o `align-content`
   poe o texto no topo dessa caixa esticada, alinhado com o titulo. */
.aviso-desfecho {
    display: grid;
    align-content: start;
    align-self: stretch;
    gap: 1px;
    min-width: 0;
    padding-left: var(--e4);
    border-left: 1px solid var(--borda-fraca);
}

.desfecho-frase {
    font-size: var(--letra-base);
    font-weight: 600;
    line-height: 1.35;
    color: var(--texto);
}

.desfecho-pormenor {
    font-size: var(--letra-sm);
    line-height: 1.35;
    color: var(--esbatido);
}

/* O nome do cliente com a cor do texto e nao com a dos dados esbatidos:
   e uma PESSOA, e a seguir ao nome da maquina precisava de alguma coisa
   que o separasse dela. */
.lista-avisos .meta-cliente {
    color: var(--texto);
}

/* O PONTO SEPARADOR VAI DEPOIS DO ITEM, E NUNCA ANTES.

   Com `::before`, o item que abrisse uma linha nova depois de uma
   quebra nascia com um ponto solto encostado a esquerda, sem nada
   antes dele. Depois, uma quebra deixa o ponto no fim da linha de
   cima, que e como qualquer trilho de navegacao se comporta e nao
   se le como defeito.

   Desliga-se no telemovel, onde a fileira quebra de certeza e o
   espaco nao sobra para enfeites. */
.lista-avisos .ocorrencia-meta {
    gap: var(--e1) var(--e3);
}

.lista-avisos .ocorrencia-meta > *:not(:last-child)::after {
    content: "·";
    margin-left: var(--e3);
    /* `--tenue` E NAO `--borda`. A cor de bordo da 1,65:1 contra o branco:
       comparadas lado a lado, ampliadas tres vezes, a versao com `--borda`
       nao tem ponto nenhum -- ve-se uma sujidade onde devia estar um
       separador, e um separador que nao se ve nao separa. */
    color: var(--tenue);
}

/* -----------------------------------------------------------------
   Aceitar como normal

   Um `details` e nao JavaScript: a politica de seguranca de conteudos
   e `script-src 'self'` sem `unsafe-inline`, e um formulario que abre
   e fecha nao precisa de codigo nenhum para o fazer.
   ----------------------------------------------------------------- */

/* O gatilho e uma accao RARA, e passa a pesar como uma accao rara.

   Era um `<summary class="botao pequeno">`, ou seja, um botao a serio, com
   moldura e 34 pixeis de altura, repetido uma vez por ocorrencia. Em
   `/ocorrencias` com doze ocorrencias abertas isso davam doze botoes iguais,
   mais de quinhentos pixeis de altura so de botoes, contra pouco mais de
   quatrocentos do texto das proprias ocorrencias. A coisa mais visivel da
   pagina era a accao que quase nunca se usa.

   Alem disso nao tinha seta nem mudava de aspecto ao abrir: nada dizia que
   era um comando que abria coisa nenhuma.

   Agora e texto pequeno, alinhado a direita, com a seta que os cartoes
   colapsaveis ja usam - a mesma seta, o mesmo angulo, a mesma rotacao. */
/* `grid` no proprio `details` para o `justify-self` do `summary` ter a quem
   obedecer: dentro de um bloco, alinhar a direita nao quer dizer nada. O
   formulario que abre por baixo continua a esticar, como qualquer item de
   grelha, e fica com a largura toda. */
.aceitar {
    display: grid;
}

/* O gatilho fica na PRIMEIRA linha da ocorrencia, ao lado do resumo e encostado
   a direita, que e onde vive uma accao de um item.

   Nao na linha dos dados: essa tem o identificador, o nome do computador, o
   nome do cliente, o codigo da regra e a antiguidade, e com um nome de cliente
   comprido enche-se. O gatilho passava para a linha seguinte numas ocorrencias
   e nao noutras, e a lista ficava com items de duas e de tres linhas
   alternados sem nada que o explicasse.

   Ao abrir, ocupa a linha inteira - a seta continua a direita, so desce - e o
   formulario nasce por baixo com a largura toda. */
.ocorrencia-topo > .aceitar {
    margin-left: auto;
    flex: none;
}

.ocorrencia-topo > .aceitar[open] {
    flex: 1 1 100%;
}

/* O resumo leva o espaco que sobra e quebra dentro dele. Sem `min-width: 0` um
   resumo comprido empurrava o gatilho para fora da linha. */
.ocorrencia-topo > .ocorrencia-resumo {
    flex: 1 1 auto;
    min-width: 0;
}

.aceitar > summary {
    display: inline-flex;
    align-items: center;
    gap: var(--e1);
    justify-self: end;
    padding: var(--e1) var(--e2);
    border-radius: var(--raio-1);
    font-size: var(--letra-sm);
    font-weight: 600;
    color: var(--esbatido);
    cursor: pointer;
    list-style: none;
    user-select: none;
    transition: background .13s, color .13s;
}

.aceitar > summary:hover {
    background: var(--superficie-recuada);
    color: var(--texto);
}

.aceitar > summary::-webkit-details-marker {
    display: none;
}

.aceitar[open] > summary {
    color: var(--texto);
    margin-bottom: var(--e3);
}

.formulario-aceitar {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: var(--e3);
    padding: var(--e3);
    border-radius: var(--raio-1);
    background: var(--superficie-recuada);
}

/* O motivo leva o espaco que sobra; o prazo e o botao ficam com o seu. */
.formulario-aceitar > .campo:first-of-type {
    flex: 1 1 18rem;
    min-width: 0;
}

.formulario-aceitar > .campo {
    margin: 0;
}

/* O `.aceitar > .ajuda` SAIU A 22 DE SETEMBRO DE 2026, com o paragrafo que ele
   espacava: o que a aceitacao faz passou para o `title` do `<summary>`, nas duas
   paginas onde este controlo existe. Ficou so o que fecha o formulario. */
.aceitar:not([open]) > .formulario-aceitar {
    display: none;
}

/* Sem caixa: o motivo de uma aceitacao e uma frase, e uma frase dentro de um
   cartao nao precisa de um segundo cartao a volta. */
.ocorrencia-aceitacao {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--e3);
}

.ocorrencia-aceitacao > .ajuda {
    flex: 1 1 20rem;
    margin: 0;
}


/* Visivel para leitores de ecra, invisivel no ecra. Um `display: none`
   tira-o tambem do leitor, que e o contrario do que se quer. */
.oculto-visualmente {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

.bloco {
    display: block;
}

.ao-fim {
    text-align: right;
}

@media (max-width: 40rem) {
    .ocorrencia {
        padding: var(--e3);
    }

    /* A etiqueta de gravidade passa a ter linha propria.

       Em fila, a etiqueta ficava com metade da largura da ocorrencia e o
       resumo com a outra metade: medido a 360, 171 pixeis para o resumo, e
       «O disco WDC WD10SPZX-24Z10T0 tem sectores pendentes» esticava-se por
       seis linhas ao lado de uma palavra. A etiqueta e curta e sabe-se de
       relance; o resumo e que precisa da largura toda. */
    .ocorrencia-topo {
        flex-wrap: wrap;
    }

    .ocorrencia-resumo {
        flex: 1 1 100%;
    }

    /* A accao passa para o FIM do item, e alinhada a esquerda como tudo o resto.
       Encostada a direita entre a frase e os dados, cortava a ligacao entre a
       descricao e a identificacao dela, e era o unico elemento alinhado a
       direita num ecra todo alinhado a esquerda.

       `display: contents` dissolve o `.ocorrencia-topo` e entrega os tres filhos
       a grelha do item, que e onde a ordem se pode mudar. Os selectores
       continuam a apanha-los: o pai no documento nao mudou, so a participacao
       na disposicao. */
    .ocorrencia-topo {
        display: contents;
    }

    .ocorrencia-topo > .aceitar {
        order: 1;
        margin-left: 0;
        justify-self: start;
    }

    /* E SEM O DESLOCAMENTO PARA CIMA, que aqui nao tem com o que se alinhar.

       Os -2px de cima centram a pastilha com a primeira linha do resumo, que
       esta AO LADO dela. Neste ecra o resumo esta por baixo, e o que ficava ao
       lado dos -2px era o bordo do item: a etiqueta nascia a 10 px do topo
       dentro de um preenchimento de 12. */
    .ocorrencia-topo > .etiqueta {
        margin-top: 0;
        min-width: 0;
    }

    .formulario-aceitar > .campo:first-of-type {
        flex: 1 1 100%;
    }

    .lista-avisos .ocorrencia {
        padding: var(--e3);
    }

    /* Sem pontos: aqui a fileira quebra de certeza, e o ponto que sobra
       no fim de uma linha e enfeite a ocupar espaco que nao ha. */
    .lista-avisos .ocorrencia-meta > *:not(:last-child)::after {
        content: none;
    }
}

/* O DESFECHO DO AVISO PASSA PARA BAIXO, com o filete a virar-se de lado.

   A 60rem E NAO A 40rem, que e o corte de todo o resto desta folha. A
   coluna do desfecho tem largura fixa, portanto e o CORPO que paga a
   conta a medida que o ecra encolhe: medido a 768px, sobravam-lhe 374
   pixeis contra os 304 do desfecho -- as duas colunas praticamente
   iguais, com o titulo do aviso partido em quatro linhas ao lado de uma
   frase de duas. Empilhado, o titulo volta a ter a largura toda. */
@media (max-width: 60rem) {
    .lista-avisos .ocorrencia {
        grid-template-columns: minmax(0, 1fr);
    }

    .aviso-desfecho {
        padding-left: 0;
        padding-top: var(--e2);
        border-left: 0;
        border-top: 1px solid var(--borda-fraca);
    }
}

/* -----------------------------------------------------------------
   18. Impressao
   ----------------------------------------------------------------- */

@media print {
    .topo,
    .navegacao,
    .accoes,
    .accoes-pagina,
    .paginacao,
    .filtros,
    .faixa-filtros,
    .rodape {
        display: none !important;
    }

    body {
        background: #fff;
        color: #000;
    }

    .cartao {
        break-inside: avoid;
        box-shadow: none;
        border: 1px solid #999;
    }

    details.cartao {
        display: block;
    }

    details.cartao > div {
        display: block !important;
    }
}



/*
 * O cartao que esta a filtrar a lista.
 *
 * O `aria-current="page"` ja la estava, para quem usa leitor de ecra, e nao pintava nada:
 * clicar em «Críticas» filtrava a lista sem que nada no ecra dissesse qual dos tres estava
 * activo. Passou a notar-se quando o terceiro cartao deixou de ser um contador morto e
 * virou o «Todas», que e por onde se volta atras.
 *
 * Um anel por fora, e nao uma cor de fundo nova: os cartoes ja levam a cor da gravidade
 * deles, e uma segunda cor por cima competia com a primeira.
 *
 * O anel sai NEUTRO -- `currentColor` aqui e a cor base do texto do cartao, e nao a do
 * numero -- e e melhor assim: um anel vermelho a volta de um cartao vermelho nao se ve,
 * e a funcao dele e dizer «e este que esta a filtrar», nao repetir a gravidade. Nos dois
 * temas acompanha o texto: escuro no claro, claro no escuro.
 */
.cartao-estado[aria-current="page"] {
    outline: 2px solid currentColor;
    outline-offset: 2px;
}

/*
 * As cores da auditoria, uma por natureza de accao.
 *
 * A cor entra no TEXTO e numa barra a esquerda da celula, nunca no fundo: sessenta
 * linhas com fundo colorido sao sessenta linhas onde nada se destaca, e o que se
 * quer e o contrario. O mapa de qual accao leva qual familia esta na vista,
 * comentado.
 *
 * SAO OITO FAMILIAS E NAO CINCO desde 16 de Setembro de 2026, e as tres que
 * entraram vieram tapar um buraco e nao enfeitar: nove das trinta e sete accoes
 * -- o ciclo inteiro dos avisos ao cliente, a heranca de duplicado e a sessao
 * retomada -- nao estavam em mapa nenhum e caiam no cinzento da rotina, que e o
 * mesmo cinzento do fluxo antigo dos codigos de activacao. Sao coisas opostas: um
 * recado que o cliente leu ontem e uma linha de um mecanismo que morreu em Agosto.
 *
 *
 * O cinzento da rotina e mais fraco do que o texto normal, de proposito: o fluxo
 * antigo sao muitas linhas em quem o teve, e o trabalho delas e sair da frente.
 */
.accao-grave,
.accao-a-vigiar,
.accao-sem-resposta,
.accao-boa,
.accao-percurso,
.accao-decidida,
.accao-acesso,
.accao-rotina {
    font-weight: 600;

    /* O NOME DA ACCAO NAO PARTE EM DUAS LINHAS, e sem isto nada do resto vale.
       A 1024 pixeis partiam VINTE E OITO dos trinta e seis: «Entradas com exito»
       virava «Entradas com» mais «exito», e a segunda linha caia debaixo do
       simbolo, alinhada com ele em vez do texto -- lia-se como indentacao
       errada e nao como continuacao. Cada linha ficava com o dobro da altura, e
       uma tabela onde uma linha em cada duas e alta perde o ritmo que faz uma
       lista ler-se de relance.

«Actualizacoes autorizadas» sao 25 caracteres num lugar que o
       algoritmo da tabela reparte pela coluna com mais texto, que e o detalhe.

       Com `nowrap` a coluna pede a largura que precisa e o detalhe cede: parte
       em duas ou tres linhas, que e o que texto corrido faz e nao incomoda. A
       envolvente rola na horizontal se nem assim couber, e abaixo de 60rem esta
       regra e desfeita -- la a tabela e um cartao e o nome tem a linha toda. */
    white-space: nowrap;
}

.accao-grave {
    box-shadow: inset 3px 0 0 var(--critico);
    color: var(--critico);
}

.accao-a-vigiar {
    box-shadow: inset 3px 0 0 var(--atencao);
    color: var(--atencao);
}

/*
 * O SILENCIO DO OUTRO LADO, e e a unica coisa nesta pagina que o amarelo do tema
 * descreve melhor do que qualquer das outras.
 *
 * Este amarelo esteve fora da auditoria de proposito, e a nota que o proibia dizia
 * que `--sem-comunicacao` e a cor do estado de um equipamento que se calou e que
 * usa-la para outra coisa punha duas linguagens no mesmo painel. Continua a ser
 * verdade, e e por isso que entra so aqui: um aviso expirado E uma maquina que se
 * calou -- a janela abriu-se no ecra do cliente, esteve la o tempo todo, e fechou-se
 * sem que ninguem carregasse em nada. Nao e a mesma linguagem outra vez; e a mesma
 * linguagem no mesmo sentido.
 */
.accao-sem-resposta {
    box-shadow: inset 3px 0 0 var(--sem-comunicacao);
    color: var(--sem-comunicacao);
}

.accao-boa {
    box-shadow: inset 3px 0 0 var(--saudavel);
    color: var(--saudavel);
}

.accao-percurso {
    box-shadow: inset 3px 0 0 var(--percurso);
    color: var(--percurso);
}

.accao-decidida {
    box-shadow: inset 3px 0 0 var(--informacao);
    color: var(--informacao);
}

.accao-acesso {
    box-shadow: inset 3px 0 0 var(--acesso);
    color: var(--acesso);
}

/*
 * O fluxo antigo dos codigos de activacao leva barra como todas as outras, e nao
 * apenas texto fraco.
 *
 * Sem ela, a coluna ficava com buracos: numa auditoria verdadeira estas linhas sao
 * muitas e aparecem no meio das outras, e uma coluna onde umas linhas tem barra e
 * outras nao le-se como uma coluna por acabar. A barra alinha; a cor e que hierarquiza.
 */
.accao-rotina {
    box-shadow: inset 3px 0 0 var(--borda);
    color: var(--esbatido);
    /* Menos peso do que as outras sete, e e a unica diferenca que lhe resta: o
       fluxo antigo nao pede nada a ninguem. */
    font-weight: 500;
}

/*
 * O SIMBOLO DE CADA FAMILIA.
 *
 * LARGURA FIXA, e e o que faz a coluna ser uma coluna: os oito simbolos tem larguras
 * diferentes -- o visto e estreito, o aviso e largo -- e sem a caixa de 1,1em cada
 * nome de accao comecava num sitio diferente. Centrado dentro dela, porque encostado
 * a esquerda o estreito ficava colado a barra e o largo nao.
 *
 * Herda a cor da familia por `currentColor`, que e o que o `color` da celula ja pos.
 * Uma segunda declaracao de cor aqui era a segunda copia da paleta.
 */
/*
 * OS SIMBOLOS SAIRAM, a 16 de Setembro de 2026.
 *
 * > DECISAO EXPLICITA DO RESPONSAVEL DO PROJECTO: «remova os glifos, fica feio.»
 *
 * Cada familia teve durante algumas horas o seu sinal antes do nome -- visto, cruz,
 * triangulo de aviso, circulo vazio, triangulo cheio, losango, seta em circulo e
 * ponto --, e sairam depois de vistos na pagina.
 *
 * O QUE SE PERDE FICA ESCRITO, porque nao e nada: oito por cento dos homens nao
 * distingue o vermelho do verde, e para essas pessoas «Revogações» e «Registos
 * automáticos» passam a ter o mesmo aspecto. O resto do painel resolve isto com um
 * simbolo em `::before` em cada etiqueta de estado (seccao 8), e a auditoria deixou
 * de o fazer. O que resta para elas e a BARRA a esquerda, que distingue por
 * luminancia e nao por matiz, e o nome da accao, que esta escrito por extenso.
 *
 * Nao se volta a acrescentar sem ordem. Se algum dia voltar, o que estava aqui era
 * uma caixa `inline-flex` de largura fixa com o glifo centrado dentro -- e a razao
 * de ser `inline-flex` esta no commit 3d4c055: com `inline-block`, cada glifo
 * assentava a SUA linha de base e os oito apareciam a oito alturas diferentes.
 */

/* -----------------------------------------------------------------
   A PALETA DOS AVISOS

   Cinco familias, tres tons cada uma, e cada tom com um trabalho:

     cor     - texto sobre branco, e fundo de botao com texto branco
     escura  - texto sobre o proprio lavado, onde a `cor` nao chega aos 4,5:1
     lavado  - fundo do cartao de contacto

   AS CORES ESTAO AQUI E NAO NO PHP, e sao classes e nao `style=`.

   Foram um `style="--realce: #218358"` escrito pelo PHP no proprio
   elemento, e o navegador recusou-os todos: a politica de seguranca de
   conteudo deste painel e `style-src 'self'` sem `unsafe-inline`. No
   compositor nao se notava, porque o JavaScript repunha as cores logo a
   seguir pelo CSSOM, que o CSP nao trava; no detalhe, onde nao ha
   JavaScript nenhum, a janela saia sem cor nenhuma. E a mesma cicatriz que
   `Vistas/entrada.php` ja documenta.

   O servidor nunca precisa de saber o que e o verde: recebe a chave
   `verde` do formulario, verifica que esta na lista de
   `Constantes::AVISO_CORES`, e guarda-a. Quem desenha sao dois ficheiros
   -- este, e `JanelaAviso.xaml` para a janela verdadeira --, e ha um
   ensaio a exigir que os valores batam certo entre os dois.

   AS 125 COMBINACOES QUE O COMPOSITOR DEIXA FAZER FORAM MEDIDAS UMA A UMA
   com a formula do WCAG 2.1, e todas passam os 4,5:1. Nao foram estimadas:
   o 4,5:1 e o limiar calibrado em acuidade 20/40, que o W3C descreve como
   a visao tipica aos 80 anos -- e essa e exactamente a pessoa que esta a
   olhar para esta janela.

   O vermelho e `#CE2C31` e nao o `#B02A37` de antes porque o antigo se lia
   como carmim: estava a 20,9 graus de matiz em OKLCH quando o vermelho
   puro esta a 29,2. Duas causas somadas -- vinha do Bootstrap com a matiz
   ja errada, e era o menos saturado do grupo, o que roda a matiz para o
   rosa.

   UM AZUL SO, por decisao explicita: o informativo E o azul do Pulsio.
   ----------------------------------------------------------------- */

.av-realce-azul { --realce: #2f6df6; }
.av-realce-laranja { --realce: #ab6400; }
.av-realce-vermelho { --realce: #ce2c31; }
.av-realce-verde { --realce: #218358; }
.av-realce-cinzento { --realce: #6e6e78; }

.av-contacto-azul {
    --contacto: #2f6df6;
    --contacto-escura: #2657c5;
    --contacto-lavado: #e2ebfe;
}

.av-contacto-laranja {
    --contacto: #ab6400;
    --contacto-escura: #895000;
    --contacto-lavado: #f3e9db;
}

.av-contacto-vermelho {
    --contacto: #ce2c31;
    --contacto-escura: #a52327;
    --contacto-lavado: #f8e1e2;
}

.av-contacto-verde {
    --contacto: #218358;
    --contacto-escura: #1a6946;
    --contacto-lavado: #e0eee8;
}

.av-contacto-cinzento {
    --contacto: #6e6e78;
    --contacto-escura: #585860;
    --contacto-lavado: #ebebec;
}

/* O SEGUNDO VALOR DE CADA UM E O FUNDO COM O RATO POR CIMA, e sai da mesma
   familia: o botao principal escurece para a `escura`, e o de contorno
   enche-se com o `lavado`.

   E o que o XAML faz, e tem de ser o mesmo: a replica existe para se ver a
   janela antes de a enviar, e um hover que aqui fosse de outra maneira era uma
   promessa que a janela nao cumpria. */
.av-botao1-azul { --botao-1: #2f6df6; --botao-1-sob-rato: #2657c5; }
.av-botao1-laranja { --botao-1: #ab6400; --botao-1-sob-rato: #895000; }
.av-botao1-vermelho { --botao-1: #ce2c31; --botao-1-sob-rato: #a52327; }
.av-botao1-verde { --botao-1: #218358; --botao-1-sob-rato: #1a6946; }
.av-botao1-cinzento { --botao-1: #6e6e78; --botao-1-sob-rato: #585860; }

.av-botao2-azul { --botao-2: #2f6df6; --botao-2-sob-rato: #e2ebfe; }
.av-botao2-laranja { --botao-2: #ab6400; --botao-2-sob-rato: #f3e9db; }
.av-botao2-vermelho { --botao-2: #ce2c31; --botao-2-sob-rato: #f8e1e2; }
.av-botao2-verde { --botao-2: #218358; --botao-2-sob-rato: #e0eee8; }
.av-botao2-cinzento { --botao-2: #6e6e78; --botao-2-sob-rato: #ebebec; }

/* -----------------------------------------------------------------
   OS CONTROLOS DO ASPECTO, no compositor
   ----------------------------------------------------------------- */

/* SAO BOTOES DE RADIO A SERIO, com a amostra desenhada por cima.

   O `<input>` fica escondido para o CSS, mas nao para o teclado nem para o
   leitor de ecra: `opacity: 0` e `position: absolute` sobre o rotulo. Um
   `display: none` tirava-o da ordem de tabulacao e o grupo deixava de se
   poder percorrer com as setas, que e como um grupo de radios se usa. */
.escolha-de-cor {
    display: flex;
    flex-wrap: wrap;
    gap: var(--e2);
}

/* O ESCONDIDO E O PADRAO `visually-hidden`, e nao um `opacity: 0` solto.

   Com `position: absolute` sem coordenadas, os cinco `<input>` do grupo
   caiam todos no mesmo ponto e sobrepunham-se ao primeiro rotulo: nao
   incomodava ninguem a usar o painel -- levam `pointer-events: none` --,
   mas era uma pilha de cinco elementos invisiveis por cima de um botao.
   O `clip-path: inset(50%)` recorta-os a nada sem os tirar do fluxo. */
.escolha-de-cor input {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    border: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
}

.escolha-de-cor label {
    display: inline-flex;
    align-items: center;
    gap: var(--e2);
    min-height: 44px;
    padding: 0 var(--e3);
    border: 1px solid var(--borda);
    border-radius: var(--raio-2);
    background: var(--superficie);
    color: var(--texto);
    font-size: var(--letra-sm);
    font-weight: 500;
    cursor: pointer;
}

/* A amostra e um circulo cheio com a cor da familia. Uma etiqueta so com o
   nome obrigava a saber de cor qual e o laranja deste projecto. */
.escolha-de-cor label::before {
    content: "";
    box-sizing: border-box;
    width: 18px;
    height: 18px;
    flex: 0 0 auto;
    border: 2px solid transparent;
    border-radius: 50%;
    background: var(--amostra);
}

/* AS AMOSTRAS DOS OITO FEITIOS DO SEGUNDO BOTAO.

   Era um `<select>`, e passou a ser igual ao controlo das cores por pedido do
   responsavel do projecto: sao duas escolhas do mesmo genero, e uma delas
   escondia as opcoes ate se lhe tocar.

   CADA AMOSTRA MOSTRA O QUE O BOTAO E. As cinco cores saem em ANEL, e nao
   cheias, porque e isso que o botao e - um circulo cheio dizia «cor de fundo»,
   que e precisamente o que estes feitios nao tem. Nenhum deles e cheio, e essa
   e a decisao: dois botoes cheios lado a lado disputam a atencao e o cliente
   deixa de saber qual e o que se carrega.

   O `box-sizing` e a borda transparente da regra de cima estao la para os oito
   terem o MESMO diametro: sem eles, os que levam contorno mediam 22 px e os
   cheios 18, e a fila ficava com os circulos a saltar de tamanho. */
.escolha-de-cor label.amostra-anel::before {
    background: #fff;
    border-color: var(--amostra);
}

/* O branco leva a MESMA borda do botao, `#8E919A`, e nao um cinzento claro: o
   `#D4D4DA` dava 1,48:1 sobre branco e a amostra desaparecia. */
.escolha-de-cor label.amostra-feitio-branco::before {
    background: #fff;
    border-color: #8e919a;
}

.escolha-de-cor label.amostra-feitio-cinzento-suave::before {
    background: #eef0f4;
    border-color: #d9dce3;
}

/* O tracejado diz «nao tem contorno nenhum» sem deixar de se ver que ali ha um
   circulo. Um circulo transparente sem borda seria um buraco. */
.escolha-de-cor label.amostra-feitio-so-texto::before {
    background: transparent;
    border: 2px dashed #a6a9b1;
}

.escolha-de-cor label.amostra-azul { --amostra: #2f6df6; }
.escolha-de-cor label.amostra-laranja { --amostra: #ab6400; }
.escolha-de-cor label.amostra-vermelho { --amostra: #ce2c31; }
.escolha-de-cor label.amostra-verde { --amostra: #218358; }
.escolha-de-cor label.amostra-cinzento { --amostra: #6e6e78; }

.escolha-de-cor label:hover {
    border-color: var(--texto);
    background: var(--superficie-recuada);
}

/* A ESCOLHA MARCA-SE COM BORDA E FUNDO, e nao so com a cor da amostra: a
   amostra ja esta la nos cinco, e um circulo colorido que nao muda nao
   pode ser tambem o sinal de qual deles esta escolhido. */
.escolha-de-cor input:checked + label {
    border-color: var(--acento);
    box-shadow: inset 0 0 0 1px var(--acento);
    background: var(--superficie-recuada);
}

.escolha-de-cor input:focus-visible + label {
    outline: 2px solid var(--foco);
    outline-offset: 2px;
}

/* O interruptor do bloco de contacto.

   Uma caixa de marcar com o rotulo ao lado, com area de toque a chegar aos
   44 px: e a mesma regra que o resto do painel cumpre. */
.campo .interruptor {
    display: inline-flex;
    align-items: center;
    gap: var(--e3);
    min-height: 44px;
    cursor: pointer;
    font-weight: 500;
}

.campo .interruptor input {
    width: 18px;
    height: 18px;
    margin: 0;
    accent-color: var(--acento);
    cursor: pointer;
}

/* -----------------------------------------------------------------
   A JANELA DO AVISO AO CLIENTE, REPLICADA

   Aparece em dois sitios, e o desenho e o mesmo nos dois: no compositor,
   a mudar enquanto o tecnico escreve, e no detalhe, a mostrar a copia
   congelada do que foi entregue. O HTML vem de um so parcial,
   `Vistas/parciais/replica_da_janela.php`.

   ISTO JA NAO E UMA APROXIMACAO. Era, e dizia-o: «serve para conferir o
   texto, nao o aspecto». Passou a ser a replica, com as medidas e as cores
   que sairam do provador onde foram todas medidas -- porque o aspecto
   passou a ser ESCOLHIDO A CADA AVISO, e uma pre-visualizacao que nao
   mostre a escolha nao serve para a fazer.

   O que continua a nao bater certo sao as quebras de linha num texto muito
   comprido: o WPF quebra com regras proprias. Tudo o resto e igual.

   AS CORES NAO ESTAO AQUI: vem em `style="--realce: ..."` no proprio
   elemento, escritas pelo PHP a partir de `Constantes::AVISO_PALETA`. Ter
   a paleta em dois sitios era garantir que um deles ficava para tras.

   AS MEDIDAS SAO EM PIXEIS E NAO NAS VARIAVEIS DO PAINEL, e e deliberado:
   isto nao e um componente do painel, e o retrato de uma janela que existe
   noutro programa. No dia em que o painel mudasse de escala, este retrato
   tinha de continuar a mostrar a janela como ela e.
   ----------------------------------------------------------------- */

/* O escurecimento a 75 % que a janela poe por cima do ecra do cliente.

   Sem ele a pre-visualizacao mostrava uma janela clara sobre fundo claro,
   que e a unica coisa que ela nunca vai ser: quem a ve tem o ambiente de
   trabalho apagado por tras, e e desse contraste que ela tira a forca. */
/* A JANELA TEM 612 px E NAO ENCOLHE. Quando nao cabe, e o PALCO que rola.

   A janela do cliente tem 612 px fixos no Windows. Nao existe uma versao estreita dela, e
   mostrar uma versao estreita era mostrar uma coisa que nao existe -- o contrario do que
   esta replica serve para fazer.

   E era o que acontecia. Com `width: 100%; max-width: 612px` a janela encolhia com a
   coluna: a 390 px ficava com 242, o cartao de contacto transbordava, o telefone partia-se
   em TRES linhas, o logotipo -- 180 px fixos dentro do SVG -- saia cortado, e o segundo
   botao ficava fora da caixa. A 1024 px, no compositor, a segunda coluna dava-lhe 422 e o
   mesmo acontecia em menor grau. Medido a 16 de Setembro de 2026, nos tres ecras que a
   mostram, e acontecia desde que a replica existe.

   NENHUMA MEDICAO O APANHAVA. O `capturar_painel.py` mede o rolamento da PAGINA, e a
   `.janela-aviso` tem `overflow: hidden`: o conteudo esmagava-se la dentro sem nada
   transbordar para fora. So se via ao abrir a captura.

   NAO E UM `@media`, E DE PROPOSITO. Isto nao depende da largura do ecra, depende de a
   janela caber na coluna onde esta -- e a mesma largura de ecra da colunas diferentes no
   compositor, no detalhe e na biblioteca. Um limiar de `@media` acertava num dos tres e
   falhava nos outros dois, e foi o que a primeira tentativa fez.

   `justify-content: safe center` E O QUE TORNA ISTO UTILIZAVEL. Um item centrado num
   contentor com rolamento fica com o INICIO cortado e inalcancavel: rola-se para a direita
   e nunca se chega a esquerda. O `safe` centra enquanto cabe e encosta ao inicio quando
   nao cabe, que e o comportamento certo dos dois lados. */
.palco-do-aviso {
    display: grid;
    align-items: center;
    justify-content: safe center;
    overflow-x: auto;

    /* Sem isto o `overflow` nao vale nada: um item de grelha ou de caixa flexivel nao
       encolhe abaixo do conteudo que tem dentro, e o palco ficava com os 612 px da janela
       a empurrar a PAGINA para o lado. O rolamento mudava de sitio em vez de desaparecer. */
    min-width: 0;
    padding: var(--e6) var(--e4);
    border-radius: var(--raio-3);
    background: #3f3f46;
    background-image: linear-gradient(140deg, #4a4a53, #33333a 62%, #26262c);
}

/* E o mesmo pela coluna acima, que e por onde a largura chega ao palco. */
.colunas > .cartao,
.cartao > .corpo,
.bib-par {
    min-width: 0;
}



/* `box-sizing: border-box` E OS 612 SAO O CARTAO INTEIRO, borda incluida.

   Sem ele o `max-width` valia so o interior e a borda somava-se por fora: o cartao
   media 614 px onde o do XAML mede 612. Dois pixeis nao se veem, mas entram na
   conta da largura da linha, e esta folha existe para essa conta bater certo. No
   WPF a `BorderThickness` do `Border` desenha-se PARA DENTRO da largura dada, e e
   esse o comportamento que se imita aqui. */
.janela-aviso {
    box-sizing: border-box;
    width: 100%;

    /* O `min-width` IGUAL AO `max-width` E O QUE A IMPEDE DE ENCOLHER, e o `max-width`
       fica porque e ele que a guarda compara com o `Width` do XAML. Ver o comentario do
       `.palco-do-aviso`. */
    min-width: 612px;
    max-width: 612px;
    border: 1px solid #eaeaee;
    border-radius: 16px;
    box-shadow: 0 10px 42px rgba(15, 15, 20, .34);
    overflow: hidden;
    font-family: "Segoe UI Variable Text", "Segoe UI", system-ui, sans-serif;
    color: #141416;
}

/* A BARRA DO TOPO FOI AUMENTADA E DEPOIS EMAGRECIDA.

   O conteudo cresceu -- o simbolo para 26 px, a marca para 16 -- e o
   espacamento vertical desceu de 21 para 12 px na mesma passagem. Sem a
   segunda metade a barra crescia duas vezes: uma pelo conteudo e outra
   pelo ar a volta dele, e ficava com 68 px em vez dos 54 que tem. */
.ja-cabeca {
    display: flex;
    align-items: center;
    gap: 11px;
    padding: 12px 26px;
    background: #f7f7f9;
    border-bottom: 1px solid #eaeaee;
}

/* `line-height: 1` NOS DOIS TEXTOS, e nao e um pormenor: com a altura de
   linha por omissao, o centro da caixa deixa de ser o centro da letra e os
   dois textos ficam desalinhados um do outro por uns dois pixeis -- o
   suficiente para a barra parecer torta sem se perceber porque. */
/* SEM `letter-spacing`, e nao e esquecimento: A JANELA NAO O CONSEGUE FAZER.

   O `CharacterSpacing` existe em WinUI e em UWP; o `TextBlock` do WPF so
   oferece a classe `Typography` -- ligaduras, kerning, versaletes --, que
   nao faz tracking. O provador onde isto se decidiu tinha-o, porque era
   HTML e ninguem tinha ido ver se o WPF o tinha tambem.

   Uma replica que prometa o que a janela nao consegue fazer e pior do que
   nao ter replica: e sobre ela que o tecnico escolhe. */
/* `ja-marca` E NAO `marca`: O PAINEL JA TEM UMA.

   O cabecalho do painel tem `<a href="/" class="marca">`, com regras
   proprias, e elas caiam em cima desta. Media-se: com `gap: 11px` e
   `margin-left: 0`, o lema aparecia a 269 px da marca em vez dos 11 -- a
   janela verdadeira poe-os lado a lado, e a replica separava-os pela
   largura do cartao.

   Uma replica que difere da janela no sitio onde ninguem esta a olhar e
   pior do que replica nenhuma: e sobre ela que o tecnico escolhe.

   O texto tambem estava em minusculas aqui e em maiusculas no XAML. O
   `text-transform` disfarcava-o. */
.ja-cabeca .ja-marca {
    font-weight: 700;
    font-size: 16px;
    text-transform: uppercase;
    line-height: 1;
}

.ja-cabeca .ja-lema {
    font-size: 15px;
    color: #4d4d54;
    line-height: 1;
}

/* A AREA DE LEITURA TEM ALTURA MAXIMA, COMO A DA JANELA.

   Sem isto a replica crescia sem limite e mostrava um texto comprido inteiro,
   quando na janela verdadeira ele ganha barra de deslocamento aos 380 px. Era
   exactamente ao contrario do que esta replica existe para fazer: o tecnico
   via caber tudo, e no ecra do cliente nao cabia. Apanhado a olho pelo
   responsavel do projecto.

   NA JANELA A ALTURA PODE SER MENOR do que estes 380, e aqui nao ha como o
   saber: o `AjustarAlturaAoEcra` encolhe-a num ecra baixo ou a 150 % de
   escala, e o ecra que conta e o do cliente. O 380 e o maximo desejado, e e
   com ele que se escreve. */
.ja-leitura {
    position: relative;
}

/* Os 26 px de dentro sao 16 a direita mais 10 de margem no conteudo, como no
   XAML: e o espaco onde a barra passa sem tapar as ultimas letras de cada
   linha. */
/* `box-sizing: border-box` PELA MESMA RAZAO DO CARTAO, e aqui pesava 28 px.

   O `MaxHeight` de um elemento do WPF conta a caixa INTEIRA, com o `Padding` dentro:
   a area de leitura da janela nunca passa dos 380 px, e o texto que se ve sao os 380
   menos os 24 de cima e os 4 de baixo, ou seja 352.

   Em CSS, sem `border-box`, o `max-height` vale so o conteudo e o padding soma-se por
   fora: a replica mostrava 380 px de texto e media 408 de altura. Vinte e oito pixeis
   de texto a mais do que o cliente ve, exactamente na fronteira onde se decide se o
   aviso cabe ou ganha barra de deslocamento, que e a pergunta que esta replica existe
   para responder. Medido a 2 de Setembro de 2026.

   E OS 4 px DE BAIXO SAO UMA `border` E NAO `padding`, pela mesma razao vista de outro
   angulo. Num elemento que rola, o `padding-bottom` do CSS pertence ao CONTEUDO
   ROLAVEL: so aparece quando se chega ao fim, e enquanto se esta no topo aqueles 4 px
   sao texto. No WPF o `Padding` do `ScrollViewer` encolhe a janela de leitura, e os 4
   px de baixo estao la sempre. Com `padding`, a replica mostrava mais 4 px de texto do
   que o cliente ve, e via-se: um pedaco de 8 px de uma linha que na janela nao existe.

   Uma `border` transparente com `box-sizing: border-box` encolhe a caixa da mesma
   maneira que o `Padding` do WPF, e o fundo branco pinta por baixo dela. */
.ja-corpo {
    box-sizing: border-box;
    max-height: 380px;
    overflow-y: auto;
    padding: 24px 16px 0 26px;
    border-bottom: 4px solid transparent;
    background: #fff;
}

/* `.janela-aviso` A FRENTE, E E O QUE FAZ ESTA REGRA EXISTIR DE FACTO.

   Escrita como `.ja-corpo > *`, empatava em especificidade com `.ja-paragrafo`,
   `.ja-titulo` e `.ja-destaque`, que vem mais abaixo nesta folha e declaram a
   margem em atalho (`margin: 0 0 14px`). Em caso de empate ganha a ultima, e a
   ultima punha a margem direita a ZERO.

   Resultado medido a 2 de Setembro de 2026: o texto da replica tinha 570 px de
   largura onde o da janela tem 558. Doze pixeis, sempre do mesmo lado, a mudar
   onde cada linha quebra. A regra estava escrita, estava certa, e nao valia nada. */
.janela-aviso .ja-corpo > * {
    margin-right: 10px;
}

/* A BARRA E DE 6 px E DISCRETA, como a `BarraDiscreta` do XAML. A do sistema
   ocupa 15 px e desenha setas nas pontas: numa janela de 612 px de largura,
   com este desenho, le-se como uma peca de outro programa.

   O `scrollbar-width: thin` E O `scrollbar-color` ESTIVERAM AQUI E TIVERAM DE SAIR.

   Desde o Chrome 121, QUALQUER uma das duas propriedades padrao presente no
   elemento faz o navegador ignorar os pseudo-elementos `::-webkit-scrollbar`
   inteiros. Elas estavam ca as duas, e o resultado era uma barra de 10 px onde
   este bloco promete 6 -- medido no Chrome 152 a 2 de Setembro de 2026:

       scrollbar-width: thin + ::-webkit-scrollbar 6px     10 px
       so ::-webkit-scrollbar 6px                           6 px
       scrollbar-color + ::-webkit-scrollbar 6px           15 px
       sem regra nenhuma                                   15 px

   Nao se ve a olho e muda onde o texto quebra: sao 4 px roubados a largura da
   linha, do lado onde ninguem os procura. A janela verdadeira nao tem barra
   nenhuma na maior parte dos avisos, e e quando ela aparece que as duas
   deixavam de dizer a mesma coisa.

   O `@supports` la em baixo devolve as duas propriedades aos navegadores que
   nao conhecem o pseudo-elemento -- o Firefox --, onde elas sao a unica forma
   de afinar a barra e nao estao a anular nada. */
.ja-corpo::-webkit-scrollbar {
    width: 6px;
}

.ja-corpo::-webkit-scrollbar-track {
    background: transparent;
}

.ja-corpo::-webkit-scrollbar-thumb {
    background: #c2c2cb;
    border-radius: 3px;
}

/* SO ONDE NAO HA `::-webkit-scrollbar`, e a condicao e o que impede isto de
   desfazer o bloco de cima. Ver a explicacao ali. */
@supports not selector(::-webkit-scrollbar) {
    .ja-corpo {
        scrollbar-width: thin;
        scrollbar-color: #c2c2cb transparent;
    }
}

/* O DEGRADE QUE DIZ QUE HA MAIS TEXTO.

   Sem ele, um aviso comprido acaba com uma linha CORTADA A MEIO da altura,
   encostada ao que vem a seguir. Quem le nao sabe se aquilo acabou ou se ha
   mais, e o produto e para quem nao se lembra de tentar rolar uma janela.

   So aparece quando ha mesmo alguma coisa por baixo: o JavaScript liga-o e
   desliga-o, como o `AoRolar` faz na janela. Um degrade permanente numa
   janela curta seria uma mancha sem explicacao. */
.ja-desvanecimento {
    position: absolute;
    right: 0;
    bottom: 0;
    left: 0;
    height: 36px;
    pointer-events: none;
    background: linear-gradient(to bottom, rgba(255, 255, 255, 0), #fff 95%);
}

.ja-desvanecimento[hidden] {
    display: none;
}

/* O `text-transform: none` DESFAZ O `uppercase` DOS `h3` DO PAINEL, e nao e
   um pormenor: o titulo do aviso saiu «FORAM DETECTADOS PROBLEMAS NESTE
   COMPUTADOR» na primeira captura. Isto e um `h3` porque esta dentro de um
   cartao com `h2`, e a etiqueta certa traz o estilo do painel atras -- que e
   o que sempre acontece quando se desenha uma coisa dentro de outra que ja
   tem regras suas. */
/* `letter-spacing: normal` PELA MESMA RAZAO DO `text-transform: none` LOGO ABAIXO, e
   chegou dois dias depois dele.

   Este elemento e um `h3`, e o painel tem uma regra para os seus `h3`:

       h1, h2, h3 { letter-spacing: -.2px; }
       h3         { letter-spacing: .04em; text-transform: uppercase; }

   O `text-transform` foi desfeito no dia em que o titulo saiu em maiusculas na primeira
   captura, porque isso ve-se. O `letter-spacing` ficou, porque nao se ve: a 22 px sao
   0,88 px por letra, meio pixel entre cada duas. Num titulo de 42 letras sao 37 px de
   largura a mais, e o WPF NAO FAZ TRACKING NENHUM -- o `TextBlock` so oferece a classe
   `Typography`, sem `CharacterSpacing`.

   Medido a 2 de Setembro de 2026, em duas capturas do mesmo aviso tiradas pelo
   responsavel do projecto: o titulo media 460 px na janela e 497 px no simulador. As duas
   imagens parecem iguais, e sao, ate ao dia em que um titulo com mais de umas 47 letras
   quebre em duas linhas no simulador e numa so no ecra do cliente.

   A guarda nao o via porque compara o CSS ESCRITO: nas regras `.ja-*` nao havia
   `letter-spacing` nenhum, e o que o punha la era uma regra do painel que nunca fala da
   janela. Ver a verificacao da cascata no `verificar_replica_da_janela.py`. */
/* AS QUEBRAS DE LINHA ESCRITAS PELO TECNICO TEM DE SE VER AQUI, e e a razao destes
   tres `white-space`.

   Do lado do agente, cada um destes tres textos e o `Text` de um `TextBlock`, e um
   `TextBlock` quebra a linha em cada `
` que la esteja. Em HTML o `
` e espaco em
   branco como qualquer outro e colapsa num espaco: o tecnico escrevia o recado em
   linhas, via-o todo corrido na replica, e no ecra do cliente ele aparecia quebrado.

   E precisamente a divergencia que esta replica existe para nao ter, e nenhuma
   verificacao acendia, porque ninguem compara espaco em branco.

   `pre-line` E NAO `pre-wrap`: quebra nos `
` e continua a colapsar sequencias de
   espacos e a quebrar as linhas compridas por si. Com `pre-wrap`, um espaco a mais
   colado ao fim de uma linha passava a empurrar o texto, e um paragrafo colado de
   outro sitio com indentacao trazia-a consigo para dentro da janela. */
.ja-titulo {
    margin: 0 0 18px;
    letter-spacing: normal;
    text-transform: none;
    font-size: 22px;
    font-weight: 600;
    line-height: 30px;
    color: #141416;
    white-space: pre-line;
}

.ja-paragrafo {
    margin: 0 0 14px;
    font-size: 15px;
    line-height: 25px;
    color: #2e2e35;
    white-space: pre-line;
}

/* Um paragrafo vazio nao pode deixar o espaco dele. O compositor desenha
   sempre os quatro, e a maioria dos avisos usa um ou dois. */
.ja-paragrafo:empty,
.ja-destaque:empty {
    display: none;
}

/* A FRASE REALCADA MARCA-SE SO PELA COR: sem caixa, sem filete, sem fundo.

   E POR ISSO QUE O ESPACO POR CIMA TEM DE SER `padding` E NAO `margin`.
   Sem caixa nem filete, o espaco e o unico sinal de que ali comeca outra
   coisa -- e os 12 px de margem que aqui estiveram primeiro foram engolidos
   pelos 14 do paragrafo de cima, porque margens verticais vizinhas colapsam
   na maior em vez de se somarem. Com `padding` somam-se, e a frase fica com
   os 28 px que precisa de ter.

   O CINZENTO E UMA ESCOLHA VALIDA AQUI, e nao um realce que falhou: com as
   quatro cores a frase avanca, com o cinzento recua, e o mesmo lugar serve
   tambem para a ressalva que nao deve roubar a atencao ao resto. */
.ja-destaque {
    margin: 0 0 8px;
    padding: 14px 0 6px;
    font-size: 15px;
    line-height: 23px;
    font-weight: 600;
    color: var(--realce);
    white-space: pre-line;
}

.ja-contacto {
    padding: 18px 26px 20px;
    background: #fff;
    border-top: 1px solid #eaeaee;
    border-bottom: 1px solid #eaeaee;
}

.ja-contacto .ja-moldura {
    display: flex;
    align-items: center;
    gap: 16px;
    padding: 14px 18px;
    border: 2px solid var(--contacto);
    border-radius: 12px;
    background: var(--contacto-lavado);
}

/* AS CLASSES DE DENTRO DA JANELA LEVAM TODAS O PREFIXO `ja-`, E E A TERCEIRA
   VEZ QUE ESTE PROJECTO APRENDE PORQUE.

   Primeiro foi a `.marca`, que colidiu com a do cabecalho do painel e punha o
   lema a 269 px da marca em vez dos 11. Depois foi esta: o `.numero` do
   cartao de contacto tem o nome da classe que o painel usa nas celulas de
   tabela que alinham a direita, e essa regra POE `font-variant-numeric:
   tabular-nums`. O telefone do cliente saia com figuras tabulares numa janela
   que nao as pede.

   E na biblioteca de avisos foi pior: a folha da galeria tem um `.numero` seu
   -- o numero de ordem de cada ficha --, e o telefone saiu MONOESPACADO E
   CINZENTO. Encontrado a olho pelo responsavel do projecto, duas vezes.

   O MECANISMO E SEMPRE O MESMO, E VALE A PENA GUARDA-LO: estas regras nao
   declaram `font-family` nem `color`, porque os herdam da `.janela-aviso`. E a
   HERANCA PERDE PARA QUALQUER REGRA QUE SE APLIQUE AO ELEMENTO, por mais fraca
   que ela seja. Um `.numero` solto no fim de outra folha ganha a uma heranca
   que vem de dois niveis acima.

   Ha uma guarda a exigir que nenhuma classe da janela seja estilizada fora do
   bloco da janela: `testes/verificar_replica_da_janela.py`. */

/* O CONVITE SAI NA COR ESCURA E NAO NA NORMAL: esta sobre o `lavado` da
   propria familia, e ai a cor normal nao chega aos 4,5:1. */
.ja-contacto .ja-convite {
    margin-bottom: 1px;
    font-size: 13px;
    font-weight: 600;
    color: var(--contacto-escura);
}

.ja-contacto .ja-numero {
    font-size: 26px;
    font-weight: 600;
    line-height: 1.33;
}

.ja-contacto .ja-rodape-cartao {
    margin-top: 2px;
    font-size: 12px;
    color: #63636b;
}

.ja-contacto .ja-convite:empty,
.ja-contacto .ja-numero:empty,
.ja-contacto .ja-rodape-cartao:empty {
    display: none;
}

.ja-contacto .ja-cartao-texto {
    min-width: 0;
}

/* O logotipo herda a cor do cartao pelo `currentColor` do proprio `path`. */
.ja-contacto .ja-logo-canto {
    flex: 0 0 auto;
    margin-left: auto;
    color: var(--contacto);
    line-height: 0;
}

.ja-botoes {
    display: flex;
    justify-content: flex-end;
    gap: 12px;
    padding: 18px 26px 22px;
    background: #fff;
}

/* O FILETE POR CIMA DOS BOTOES SO EXISTE QUANDO NAO HA CARTAO DE CONTACTO.

   E o que o `.xaml.cs` faz na linha a seguir a mostrar a faixa: com ela, a
   separacao ja e feita pelo filete de baixo do cartao, e um segundo risco a um
   pixel de distancia do primeiro le-se como um erro de desenho. Sem ela, os
   botoes ficavam a flutuar no fim do texto, sem nada a dizer que o corpo tinha
   acabado.

   A replica nao o tinha, e por isso os avisos sem contacto -- o «esta tudo bem»,
   o «so para dar a saber» -- apareciam no painel sem uma linha que a janela
   verdadeira desenha. */
.ja-contacto[hidden] + .ja-botoes {
    border-top: 1px solid #eaeaee;
}

/* O PESO 500 ESTA AQUI E NAO SO NA VARIANTE COLORIDA.

   Estava so la, e um peso diferente muda a largura do texto: os coloridos
   mediam 203,64 px e os neutros 199,30. Trocar de feitio fazia o bordo
   esquerdo do botao saltar 4,34 px, e quem mexia no controlo via a janela
   inteira estremecer sem perceber porque.

   A borda de 2 px esta em TODOS, transparente onde nao se ve, pela mesma
   razao: sem ela, os feitios com contorno mediam 4 px a mais em largura e
   em altura do que os outros. */
.ja-botao {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: 46px;
    min-width: 132px;
    padding: 0 22px;
    border: 2px solid transparent;
    border-radius: 10px;
    font-family: inherit;
    font-size: 15px;
    font-weight: 500;
}

.ja-botao.principal {
    background: var(--botao-1);
    color: #fff;
    font-weight: 600;
}

/* A BORDA DO BRANCO E `#8E919A` E NAO UM CINZENTO CLARO.

   O `#D4D4DA` que aqui esteve dava 1,48:1 sobre branco, e o WCAG 1.4.11
   pede 3:1 para o limite de um controlo. O `#8E919A` e o cinzento mais
   claro que ainda passa, com 3,15:1 -- e ao lado dos feitios coloridos,
   que estao entre 4,53 e 5,21, ja nao e ele o que se ve pior. */
.ja-botao.sec-branco {
    background: #fff;
    border-color: #8e919a;
    color: #2e2e35;
}

.ja-botao.sec-cinzento-suave {
    background: #eef0f4;
    color: #2e2e35;
}

.ja-botao.sec-so-texto {
    background: transparent;
    color: #2e2e35;
}

.ja-botao.sec-cor {
    background: #fff;
    border-color: var(--botao-2);
    color: var(--botao-2);
}

/* OS BOTOES DA REPLICA NAO SAO `disabled`, E JA FORAM.

   Um `<button disabled>` nao recebe eventos de ponteiro no Chrome, e por isso o
   `:hover` nunca disparava: a replica mostrava dois botoes que nao respondiam
   ao rato, e e precisamente a resposta ao rato que o tecnico esta ali a ver.
   Encontrado a olho pelo responsavel do projecto.

   O cursor fica em seta e nao em mao: o hover mostra-se, mas nada convida a
   carregar num desenho. */
.ja-botao {
    cursor: default;
}

/* O RATO POR CIMA TROCA O FUNDO, E NAO BAIXA A OPACIDADE.

   E o que o XAML faz, depois de la ter sido `Opacity 0.9` para todos: num botao
   de contorno isso esbatia a BORDA E O TEXTO ao mesmo tempo que o fundo, e ele
   parecia desligar-se em vez de responder. */
.ja-botao.principal:hover {
    background: var(--botao-1-sob-rato);
}

.ja-botao.sec-branco:hover {
    background: #f2f3f6;
    border-color: #6e6e78;
}

.ja-botao.sec-cinzento-suave:hover {
    background: #e2e6ee;
}

.ja-botao.sec-so-texto:hover {
    background: #eef0f4;
}

.ja-botao.sec-cor:hover {
    background: var(--botao-2-sob-rato);
}

.ja-botao[hidden] {
    display: none;
}

/* No detalhe, qual deles o cliente carregou.

   SEM VISTO, por decisao do responsavel do projecto: esteve aqui um ` ✓` a
   seguir ao texto e ficava feio, encostado a uma palavra dentro de um botao que
   ja tem o texto centrado.

   O anel chega para o marcar, e nao e ele sozinho a dize-lo: a linha por cima da
   janela ja diz «O cliente carregou em ...», com o texto do botao em primeiro
   lugar. Isto e a confirmacao visual, e nao a informacao. */
.ja-botao.carregado {
    box-shadow: 0 0 0 2px #fff, 0 0 0 4px var(--foco);
}

/* O contador de caracteres, ao lado do rotulo de cada campo com limite.

   Um formulario de treze campos que se esvazie por causa de um limite que
   nao se via deixa de ser usado a segunda vez que isso acontece. */
.conta-caracteres {
    float: right;
    color: var(--tenue);
    font-size: var(--letra-sm);
    font-weight: 400;
    font-variant-numeric: tabular-nums;
}

.conta-caracteres.perto {
    color: var(--atencao);
    font-weight: 600;
}

/* -----------------------------------------------------------------
   Correccoes que os ecras dos avisos obrigaram, e nao apenas la

   As duas nasceram do `capturar_painel.py` a 360 e 390 px, e as duas sao de
   familias que este projecto ja conhece: um alvo de toque abaixo dos 44 px, e
   um controlo que empurra a pagina para fora do ecra.
   ----------------------------------------------------------------- */

/* O TITULO DE UM AVISO E UMA LIGACAO, e a lista de ocorrencias nao tinha
   nenhuma no resumo: la o resumo e texto, e o clique vive no `<a>` do
   equipamento, la em baixo. Aqui o titulo E o caminho para o detalhe, e um
   `<a>` inline herda a altura da linha -- 19 px medidos --, menos de metade
   dos 44 px que um dedo precisa.

   `inline-flex` com `min-height` da-lhe o alvo sem lhe mexer no aspecto: o
   sublinhado, a cor e a quebra de linha ficam como estavam. Sem `padding`
   vertical de proposito, que empurraria as linhas da lista umas das outras.

   E O TEXTO ENCOSTA AO TOPO DA CAIXA, e nao ao centro dela.

   Com `align-items: center`, um titulo de uma linha ficava a flutuar no meio
   dos 44 px enquanto a etiqueta ao lado nascia em cima: medidos 8,3 px de
   desnivel entre o centro da pastilha e o centro da primeira linha, contra os
   0,5 px de uma ocorrencia normal na lista de cima da mesma pagina. Era o
   unico sitio do painel onde a altura de um ALVO DE TOQUE mexia com o sitio
   onde o texto se senta.

   O alvo continua com os 44 px onde ha um dedo, e a verificacao de toque do
   `capturar_painel.py` continua a medi-los. O que muda e' so onde e' que o
   texto se poe dentro dele. */
.ocorrencia-resumo > a {
    display: inline-flex;
    align-items: flex-start;
}

/* OS 44 PX SO ONDE HA UM DEDO, e nao em todas as larguras.

   Estiveram na regra base ate 22 de Setembro de 2026, e num portatil isso
   eram 23,7 PIXEIS DE VAZIO por baixo de cada titulo: o texto ocupa 20,3 da
   caixa de 44 e encosta ao topo dela, portanto a folga cai toda entre o
   titulo e a linha de dados por baixo. Somada aos 8 px de intervalo da
   grelha, dava um vao de 31,7 px dentro do que devia ser um bloco so -- o
   titulo e os seus dados a lerem-se como duas coisas sem relacao, e a linha
   com 103 px de altura para 38 px de texto.

   E NAO SE MEDIA EM LADO NENHUM. O verificador de alvos de toque do
   `capturar_painel.py` so corre `if largura <= 480`, ou seja a 360 e a 390:
   no portatil a folga nao tinha quem a acusasse nem quem a justificasse.

   O CORTE E A 64rem E NAO A 30rem, que seria o que bastava para a guarda
   passar. A guarda mede onde mede, e o dedo existe onde existe: um tablet a
   820 px tambem se toca, e dimensionar o alvo para o que o verificador
   inspecciona era medir o que e facil em vez do que e preciso. Acima disso
   ha rato, e um rato nao precisa de 44 px.

   O CENTRO EM VEZ DO TOPO, abaixo dos 40rem: o `.ocorrencia-topo` passa la
   a `display: contents` e a etiqueta vai para uma linha propria. Deixa de
   haver com que alinhar, e a folga do alvo caia toda por baixo do titulo --
   medidos 8 px acima e 33 abaixo, contra 19,8 e 21,2 ao centro. */
@media (max-width: 64rem) {
    .ocorrencia-resumo > a {
        min-height: 44px;
    }
}

/* ESTA REGRA TEM DE FICAR DEPOIS DA DE CIMA, e nao la em cima com as outras
   do mesmo ponto de quebra. Tem a mesma especificidade, e uma consulta de
   media nao acrescenta nenhuma: se ficasse antes, perdia para a regra base e
   nao fazia nada. Foi o que aconteceu a primeira vez. */
@media (max-width: 40rem) {
    .ocorrencia-resumo > a {
        align-items: center;
    }
}

/* E LE-SE COMO O RESUMO DE UMA OCORRENCIA, que e o que esta ao lado dele.

   O PESO E QUE DIZ QUE E CLICAVEL, e nao o sublinhado -- que nao existe em lado nenhum do
   painel, por decisao do responsavel do projecto. O titulo pesa o mesmo que o resumo da
   ocorrencia irma, fica com a cor de texto (e nao azul), e a etiqueta de estado a esquerda
   volta a ser o elemento mais forte da linha -- que e o que se quer ler primeiro. */
.ocorrencia-resumo > a:link,
.ocorrencia-resumo > a:visited {
    color: var(--texto);
    text-decoration: none;
    font-weight: 600;
}

.ocorrencia-resumo > a:hover {
    /* SEM SUBLINHADO E SEM VIRAR AZUL. O peso ja diz que e clicavel; o hover e so um sinal
       discreto por opacidade. O foco pelo teclado tem o seu proprio contorno global
       (`:focus-visible`), por isso nao precisa de nada aqui. */
    opacity: 0.7;
}

/* O SELECT DE «DUPLICAR» EMPURRAVA A PAGINA PARA FORA DO ECRA.

   O `min-width: 12rem` do filtro de cabecalho e generoso e serve bem nos
   filtros de uma palavra que ja existiam. Aqui as opcoes sao TITULOS DE AVISOS
   escritos a mao -- «Foram detectados problemas neste computador» --, e o
   navegador dimensiona o `<select>` pelo texto mais comprido que la esta: a
   360 px saia 59 px para fora, e arrastava consigo o cabecalho, o corpo e o
   formulario inteiro.

   O `max-width` resolve-o sem tocar em mais nada, e o `text-overflow` faz o
   texto que nao cabe acabar em reticencias em vez de ser cortado a meio de uma
   letra. A largura minima cai para o que um dedo precisa, e nao para o que o
   texto quer. */
.cartao > header .filtro-de-cabecalho select {
    max-width: 100%;
    text-overflow: ellipsis;
}

/* O `flex-wrap` do cabecalho ja punha o filtro numa linha sua quando nao
   cabia. O que faltava era ele CABER nessa linha: com `min-width: 12rem` no
   select e `width: auto`, a caixa continuava a pedir a largura do texto mais
   comprido, e o `flex-wrap` nao encolhe um item que se recusa a encolher.

   `flex-basis: 100%` forca a linha propria, e `min-width: 0` autoriza o
   encolhimento -- sem ele, o minimo de conteudo de um item flex e a largura do
   proprio conteudo, que e a armadilha classica do flexbox. */
@media (max-width: 30rem) {
    .cartao > header .filtro-de-cabecalho {
        flex: 1 1 100%;
        min-width: 0;
        margin-left: 0;
    }

    .cartao > header .filtro-de-cabecalho select {
        flex: 1 1 auto;
        width: 100%;
        min-width: 0;
    }
}

/* A PRE-VISUALIZACAO ACOMPANHA O FORMULARIO.

   O compositor tem treze campos e rola muito; a coluna da direita e curta e
   saia do ecra assim que se chegava ao segundo paragrafo. Uma pre-visualizacao
   que nao se ve enquanto se escreve nao serve para o que foi feita.

   So a partir de 60rem, que e onde as duas colunas existem: mais estreito do
   que isso, a `.colunas` empilha-as e uma coluna colada ao topo tapava o
   formulario. */
@media (min-width: 60rem) {
    #pre-visualizacao {
        position: sticky;
        top: var(--e4);
    }
}

/* A REGRA DA AJUDA DOS CAMPOS SAIU A 22 DE SETEMBRO DE 2026.
   Era `#formulario-aviso .campo .ajuda { margin-bottom: var(--e4) }`, e existia porque
   a ajuda de um campo se colava ao rotulo do campo seguinte. As quinze ajudas do
   compositor passaram nesse dia para marcas `(?)` no proprio rotulo, e deixou de haver
   um so `.ajuda` dentro de um `.campo` desta pagina: a regra passou a nao apanhar nada.
   O espaco entre campos vem agora da `.campos`, que e a grelha do resto do painel. */

/* OS TITULOS DE SECCAO PRECISAM DE AR EM CIMA, E DE UM RISCO.

   «CONTACTO» e «COMO A JANELA SE COMPORTA» nasciam encostados a ajuda do campo
   anterior, a poucos pixeis dela e sem nada entre os dois. Num formulario de
   treze campos que ja e uma coluna comprida de texto cinzento, um titulo
   maiusculo pousado no meio dessa coluna nao se le como um titulo: le-se como
   mais uma linha da ajuda de cima, e as tres partes do ecra - o que o cliente
   le, quem contactar, como a janela se porta - deixam de existir a olho.

   O risco fino faz o trabalho que o espaco sozinho nao faz. Sem ele era preciso
   muito mais espaco para a separacao se ver, e o formulario ficava ainda mais
   comprido do que ja e.

   O PRIMEIRO NAO LEVA NADA. Um titulo logo a seguir ao cabecalho do cartao ja
   esta separado pela borda dele, e um segundo risco a poucos pixeis do primeiro
   le-se como um erro de desenho - que e a mesma razao pela qual o rodape dos
   botoes da janela do aviso so poe filete quando nao ha faixa de contacto. */
#formulario-aviso h3 {
    margin-top: var(--e5);
    padding-top: var(--e4);
    border-top: 1px solid var(--borda-fraca);
}

#formulario-aviso h3:first-of-type {
    margin-top: var(--e4);
    padding-top: 0;
    border-top: 0;
}

/* O rotulo do campo que vem logo a seguir ao titulo nao precisa do espaco que
   os outros levam: o titulo ja o deu. */
#formulario-aviso h3 + .campos {
    margin-top: var(--e3);
}

/* AS LIGACOES DA LINHA DE DADOS DE UMA OCORRENCIA PRECISAM DE ALVO.

   A linha de `.ocorrencia-meta` era so texto e um `<a>` para o equipamento --
   e esse ja tinha alvo pelo seu proprio bloco. Os avisos ao cliente trouxeram
   dois links novos para dentro dela, «Avisar o cliente» e «cliente avisado», e
   um `<a>` inline no meio de texto de 12 px mede 16 px de altura: menos de
   metade dos 44 px que um dedo precisa, medido pelo `capturar_painel.py` a 360
   e 390 px.

   `inline-flex` com `min-height` da-lhes o alvo sem lhes mexer no aspecto nem
   empurrar as linhas umas das outras, que e a mesma solucao que o titulo da
   lista de avisos ja levou. */
.ocorrencia-meta .meta-item > a {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
}

/* -----------------------------------------------------------------
   A biblioteca de exemplos, em /avisos/biblioteca

   TODAS AS CLASSES LEVAM `bib-`, E NAO E ARRUMACAO.

   Isto veio da folha da galeria offline, `testes/modelos_da_biblioteca/galeria.css`, e
   DEZ das classes de la existem tambem aqui: `.accoes`, `.campo`, `.campos`, `.etiqueta`,
   `.ficha`, `.marca`, `.nota`, `.numero`, `.topo` e `.vazio`. Copiadas com o nome que
   tinham, cada uma delas passava a valer em todo o painel.

   E ha uma que ja fez estragos com esse mecanismo exacto: as regras da janela do aviso
   nao declaram `font-family` nem `color` -- herdam-nos da `.janela-aviso` --, e a heranca
   PERDE para qualquer regra que se aplique ao elemento, por mais fraca que seja. Um
   `.numero` solto no fim de outra folha ja pos o telefone do cliente MONOESPACADO E
   CINZENTO dentro da janela. Ver `testes/replica_do_aviso.py::colisoes()`, que recusa
   nesta folha qualquer regra sem prefixo que atinja a janela.

   O QUE NAO ESTA AQUI, porque o painel ja o tem e seria a segunda copia: o cabecalho da
   pagina, os filtros, a paginacao, os botoes, as etiquetas de gravidade e o `.vazio`.
   Das 717 linhas da galeria, cerca de 420 nao vieram.
   ----------------------------------------------------------------- */

.bib-catalogo {
    display: flex;
    flex-direction: column;
    gap: var(--e5);
    padding: var(--e4) 0 var(--e2);
}

/* Dentro do cartao da lista o catalogo ja tem as margens dele. */
.cartao > .bib-catalogo {
    padding: var(--e4);
}

/* O `max-width` NAO E ARRUMACAO: a janela mede 612 px fixos e a ficha ao lado tem seis
   linhas de texto. Sem limite, num ecra de 1440 o cartao esticava-se todo e a metade
   direita ficava com um palmo de branco por baixo de meia duzia de pastilhas. O espaco a
   mais vai para FORA do cartao, onde nao se le como falta de conteudo. */
.bib-aviso {
    max-width: 1240px;
    padding: var(--e5);
    border: 1px solid var(--borda-fraca);
    border-radius: var(--raio-3);
    background: var(--superficie);
    box-shadow: var(--sombra-1);
}

.bib-topo {
    display: flex;
    align-items: center;
    gap: var(--e3);
    flex-wrap: wrap;
}

.bib-numero {
    font-family: var(--mono);
    font-size: var(--letra-md);
    color: var(--tenue);
    font-variant-numeric: tabular-nums;
}

/* O NOME DO EXEMPLO E UM `h3`, E O PAINEL TEM REGRAS PARA OS SEUS `h3`.

       h3 { font-size: var(--letra-md); text-transform: uppercase;
            letter-spacing: .04em; color: var(--esbatido); }

   Sem as desfazer aqui, «O disco está a falhar» saiu «O DISCO ESTÁ A FALHAR», a treze
   pixeis e cinzento, na primeira captura desta pagina. E a etiqueta certa -- isto e um
   titulo dentro de um cartao com `h2` -- e a etiqueta certa traz o estilo do painel
   atras, que e o que sempre acontece quando se desenha uma coisa dentro de outra que ja
   tem regras suas.

   E JA TINHA ACONTECIDO DUAS VEZES, as duas no `.ja-titulo` da janela do aviso: o
   `text-transform` a 2 de Setembro de 2026, porque se ve, e o `letter-spacing` dois dias
   depois, porque nao se ve e so aparece num titulo comprido a quebrar noutro sitio. As
   quatro propriedades sao desfeitas juntas, pela mesma razao. */
.bib-topo h3 {
    margin: 0;
    flex: 1 1 auto;
    font-size: var(--letra-xl);
    font-weight: 600;
    text-transform: none;
    letter-spacing: -.01em;
    color: var(--texto);
}

.bib-perfil {
    padding: var(--e0) var(--e3);
    border-radius: var(--raio-total);
    border: 1px solid var(--borda);
    background: var(--superficie-recuada);
    color: var(--esbatido);
    font-size: var(--letra-sm);
    letter-spacing: .04em;
    text-transform: uppercase;
}

.bib-quando {
    margin: var(--e2) 0 var(--e4);
    max-width: 82ch;
    color: var(--esbatido);
    font-size: var(--letra-base);
}

/* A JANELA A ESQUERDA, O QUE HA A SABER A DIREITA.

   Os 664 px da primeira coluna sao os 612 da janela mais o enchimento do palco, e por
   isso a replica aparece no tamanho verdadeiro sempre que a largura o permita. Abaixo dos
   1040 a ficha desce para baixo da janela, que continua a caber: ela e
   `width:100%; max-width:612px` e encolhe sem transbordar. */
.bib-par {
    display: grid;
    grid-template-columns: minmax(0, 664px) minmax(300px, 1fr);
    gap: var(--e5);
    align-items: start;
}

@media (max-width: 1040px) {
    .bib-par {
        grid-template-columns: minmax(0, 1fr);
    }
}

/* O PALCO NAO TEM CLASSE PROPRIA, E E DELIBERADO.

   A galeria offline desenhava o seu, `#1b1b1f` com um gradiente proprio, porque abre
   sozinha e nao tem painel a volta. Aqui o parcial ja traz o `.palco-do-aviso` que o
   compositor e o detalhe usam, e usa-lo e o que faz a janela ter o MESMO aspecto nos tres
   sitios do painel onde aparece. Um segundo palco era uma segunda aparencia para a mesma
   coisa, e a divergir a partir da primeira alteracao.

   Nenhuma regra desta seccao toca na janela, e assim e que tem de ficar: a
   `replica_do_aviso.py::colisoes()` recusa nesta folha qualquer regra que a atinja sem
   prefixo, e uma que a atingisse COM prefixo passava a guarda e mudava na mesma o que o
   tecnico ve. */

.bib-ficha {
    display: flex;
    flex-direction: column;
    gap: var(--e4);
}

.bib-aspecto {
    display: flex;
    flex-wrap: wrap;
    gap: var(--e1) 7px;
}

.bib-pastilha {
    display: inline-flex;
    align-items: baseline;
    gap: 6px;
    padding: var(--e1) var(--e3);
    border: 1px solid var(--borda-fraca);
    border-radius: 7px;
    background: var(--superficie-recuada);
    font-size: var(--letra-sm);
    color: var(--esbatido);
}

.bib-pastilha em {
    font-style: normal;
    font-weight: 600;
    color: var(--texto);
}

/* AS CINCO CORES DO ASPECTO, no vocabulario de estado do painel e nao numa paleta nova.
   Sao as mesmas tonalidades que as etiquetas de gravidade usam, e passam 4,5 sobre o
   fundo lavado, que e o sitio mais exigente onde aparecem. */
.bib-pastilha.bib-cor-vermelho em { color: var(--critico); }
.bib-pastilha.bib-cor-laranja em { color: var(--atencao); }
.bib-pastilha.bib-cor-azul em { color: var(--informacao); }
.bib-pastilha.bib-cor-verde em { color: var(--saudavel); }
.bib-pastilha.bib-cor-cinzento em { color: var(--tenue); }

.bib-numeros {
    display: flex;
    gap: var(--e5);
    flex-wrap: wrap;
    padding: var(--e3) var(--e4);
    border-radius: var(--raio-1);
    background: var(--superficie-recuada);
    border: 1px solid var(--borda-fraca);
}

.bib-numeros div {
    display: flex;
    flex-direction: column;
}

.bib-numeros b {
    font-size: var(--letra-lg);
    font-variant-numeric: tabular-nums;
}

.bib-numeros span {
    font-size: var(--letra-sm);
    color: var(--tenue);
}

.bib-regras {
    margin: 0;
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
}

.bib-regras code {
    padding: var(--e0) var(--e2);
    border-radius: 5px;
    background: var(--superficie-recuada);
    border: 1px solid var(--borda-fraca);
    font-family: var(--mono);
    font-size: var(--letra-sm);
    color: var(--esbatido);
}

.bib-porque {
    margin: 0;
    color: var(--esbatido);
    font-size: var(--letra-base);
    max-width: 74ch;
}

.bib-porque b {
    color: var(--texto);
    font-weight: 600;
}

/* O BOTAO FICA NO FIM DA FICHA E ALINHADO A ESQUERDA, e nao esticado: um botao com a
   largura da coluna le-se como «continuar» de assistente, e isto nao e um assistente. */
.bib-usar {
    align-self: flex-start;
    margin-top: var(--e1);
}
