/* ══ AS DUAS FAMÍLIAS DO SISTEMA (SISTEMA-DE-DESIGN.md §2) ══
   Servidas por NÓS, de `static/assets/fontes/`. Zero recursos externos
   continua a valer: não há uma referência a `fonts.googleapis.com` no
   produto, e é por isso que os arquivos e a licença (OFL 1.1) vivem lado a
   lado no repositório.

   Os `unicode-range` são COPIADOS do que o Google serve
   (`PROVENIENCIA-*.css`, ao lado dos arquivos) e não escritos à mão: um erro
   num intervalo não falha em lado nenhum — só faz a fonte não carregar para
   certas letras, e ninguém repara até aparecer um nome com acento raro.

   ⚠ `font-display: swap`, e a escolha tem preço: o texto aparece IMEDIATO na
   fonte de reserva e troca quando a nossa chega, o que produz um salto de
   layout. A alternativa `optional` não daria salto — e deixaria a primeira
   visita sem o desenho, que é justamente o que esta fase existe para pôr na
   tela. `block` esconderia o texto até a fonte chegar, e nesta casa nada se
   esconde à espera de um arquivo (é a mesma razão das telas de erro).
   ▲ O salto pode ser reduzido com `size-adjust`/`ascent-override` medidos
   contra as métricas reais das duas famílias. NÃO os medi, e por isso não os
   escrevi.

   As duas são VARIÁVEIS: um arquivo cobre 200–800, e nenhum peso fica de
   fora. */
@font-face {
  font-family: 'Manrope'; font-style: normal; font-weight: 200 800; font-display: swap;
  src: url("assets/fontes/manrope-latin-ext.623714ac1d99.woff2") format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Manrope'; font-style: normal; font-weight: 200 800; font-display: swap;
  src: url("assets/fontes/manrope-latin.101877a7a906.woff2") format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Newsreader'; font-style: normal; font-weight: 200 800; font-display: swap;
  src: url("assets/fontes/newsreader-latin-ext.e9872dc7e2eb.woff2") format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Newsreader'; font-style: normal; font-weight: 200 800; font-display: swap;
  src: url("assets/fontes/newsreader-latin.ae1fc56ffd7e.woff2") format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* **UM ÚNICO `:root`, e a fusão é um conserto medido.**

   Havia DOIS blocos `:root` nesta folha, um na linha 1 e outro na 2008,
   declarando os MESMOS 14 tokens com valores DIFERENTES. O segundo vencia por
   cascata, e o primeiro era letra morta — medido no navegador, não deduzido:
   `--accent` valia #2563eb enquanto o topo da folha dizia #0071e3, e
   `--radius-lg` valia 12px enquanto o topo dizia 22px.

   **O custo não era estético, era de leitura:** quem abrisse a folha, achasse
   o primeiro bloco e trocasse um valor não mudava um pixel — e concluía que o
   token não era usado.

   Os valores abaixo são os do SEGUNDO bloco, que é o que já pintava a tela
   antes desta fusão. `--success`, `--danger`, `color-scheme`, `font-synthesis`
   e a `font-family` só existiam no primeiro e vieram junto: apagar o bloco
   inteiro teria tirado a fonte do produto. */
:root {
  color-scheme: light;
  font-synthesis: none;

  /* ── A2 · O ANEL DE FOCO, UM SÓ (D-1614, lote 2) ─────────────────────────
     Antes eram TRÊS azuis estrangeiros em dezassete declarações — #2563eb
     (o Tailwind que o Alan rejeitou nos e-mails), #0071e3 e #0066cc — e
     nenhum deles é cor desta casa. Medidos contra o chão dos dois tons, ao
     alfa que cada um usava, TODOS reprovavam o 3,0 da 1.4.11:

         #2563eb .35 ...  1,65 claro · 1,46 escuro
         #2563eb .14 ...  1,21 claro · 1,13 escuro
         #0071e3 40 ....  1,41 claro · 1,31 escuro
         #0071e3 .12 ...  1,17 claro · 1,12 escuro
         #0066cc .26 ...  1,47 claro · 1,27 escuro
         #0066cc .34 ...  1,67 claro · 1,40 escuro

     ⛔⛔ E O `--ciano` NÃO SERVE DE ORIGEM, por muito que seja o azul da casa:
     ele NÃO inverte, e no CLARO mede **2,72** sobre o papel — opaco, a 100%.
     Não há alfa que o salve: 2,72 é o teto. A proposta que chegou dizia
     «derive do ciano, ex.: 35%»; a medida recusou-a, e é por isso que este
     comentário existe em vez de um `color-mix` do ciano.

     ⭐ Quem serve é o `--acento-escuro`, que É o par que inverte: #00679C no
     claro e #009FF0 no escuro. A 80% de opacidade o anel mede

         sobre o papel ..........  3,91 claro · 4,53 escuro   ✅
         sobre `--acento-lavado`   3,55 claro · 3,85 escuro   ✅
         sobre `--tinta-50` ......  3,60 claro · 4,20 escuro   ✅

     e passa o 3,0 nos dois tons, sobre os três chãos onde ele cai.

     ⚠ O 3,91 e o 4,53 foram lidos DUAS VEZES, por dois instrumentos que não
     partilham código: `getComputedStyle` com o alfa composto à mão, e o PIXEL
     recortado da captura ao lado do campo em foco — (50,132,174) sobre
     (250,247,242) no claro. Deram 3,89 e 4,50 contra 3,91 e 4,53, e a
     diferença é o arredondamento do canal. ⛔ A primeira versão deste
     comentário dizia 3,55/4,12: era a conta a **75%**, colada por cima de uma
     declaração a 80%. Foi o instrumento dos pixels que a apanhou.

     ⚠ UMA declaração e não três: o `color-mix` resolve-se no sítio de uso, e
     `--acento-escuro` já tem valor próprio em cada tom. Repetir este token
     nos dois blocos escuros seria criar duas cópias para manter em passo —
     que é o defeito que a fusão dos dois `:root` desta folha veio consertar. */
  --foco: color-mix(in srgb, var(--acento-escuro) 80%, transparent);

  /* ⚠ O SEGUNDO, e a razão de serem dois está na MEDIDA e não no gosto.
     Cinco regras usam este azul como ORLA de uma caixa que já está pintada
     de `--acento-lavado` — a caixa do saldo, o aviso do «depois», o balão
     nosso, o acordeão aberto e o cartão escolhido. Aí o indicador de estado
     é o ENCHIMENTO, e a orla é reforço: é o mesmo argumento escrito na
     família das pílulas («a pílula não tem contorno próprio»).

     ⛔ Por isso ela fica ABAIXO de 3,0 de propósito — 1,87 claro e 2,01
     escuro sobre o papel, 1,80 e 1,96 sobre o `--acento-lavado`, a 40% —, e
     isto vai escrito para a próxima varredura não a
     reportar como defeito. Subi-la a 80% punha uma moldura azul forte à
     volta de cinco caixas que hoje têm um fio, e isso é redesenhar, não
     consertar. Se um dia a orla for o ÚNICO sinal nalguma delas, é o `--foco`
     que essa regra passa a usar — não este. */
  --foco-borda: color-mix(in srgb, var(--acento-escuro) 40%, transparent);

  /* ── A2 · O PAR DO AVISO, e ele NÃO se copiou de ninguém (D-1614, lote 3) ──
     A casa não tinha token de aviso: eram onze literais âmbar espalhados. Este
     par nasce para os servir todos — a mensagem `.code-sent.warning`, o ícone
     `.conta-icone.aviso` e a `.mk-card-nota`.

     ⚠⚠ E a nota que está escrita na família das pílulas vale aqui à letra:
     **copiar o L e o S do verde para outro matiz dá razões de 3,40 a 9,52,
     porque o contraste depende do matiz.** Resolveu-se para a RAZÃO. Medido
     com composição de alfa, contra o chão de cada tom:

         tinta sobre lavado ....  5,23 claro · 4,96 escuro   ✅ (piso 4,5)
         tinta sobre o papel ...  6,00 claro · 5,75 escuro   ✅ (a `.mk-card-nota`)
         lavado sobre o papel ..  1,15 claro · 1,16 escuro   ⭐ é uma LAVAGEM,
                                  e fica no mesmo degrau dos três irmãos
                                  (`--acento-lavado` 1,14 · `--certo-lavado`
                                  1,14 · `--erro-lavado` 1,16)

     ⭐ E PROCUREI O TOKEN ANTES DE O CUNHAR: `--espera-tinta`/`--espera-lavado`
     já existem e já medem 4,95/4,96. **Não servem, e a razão é de PAPEL e não
     de número:** o `--espera-lavado` claro é `#EAE8E1`, saturação 0,18 — um
     bege quase neutro, que é o que uma pílula de 20px dentro de um cartão
     precisa de ser. Uma faixa de aviso da largura do cartão nesse bege deixa
     de dizer «atenção» e passa a dizer «fundo». O par do aviso fica a 0,70 de
     saturação, e é essa a diferença entre os dois. Escrito aqui para a
     próxima varredura não os fundir. */
  --aviso-lavado: #F5E7C7;
  --aviso-tinta: #7B590A;

  /* ── AS DUAS FAMÍLIAS, com a reserva declarada ao lado (§2) ──
     ⚠ A serifada é SÓ para o título de tela e para o texto transcrito: ela é
     a voz do documento lido, e usá-la noutro lugar apaga essa distinção. */
  --ui: "Manrope", "Helvetica Neue", Helvetica, Arial, sans-serif;
  --leitura: "Newsreader", Georgia, "Times New Roman", serif;

  /* ⭐ O TETO DE LEITURA DA CASA — D-1563, decisão do Alan de 04/09/2026:
     *«iguale tudo na medida de leitura (…) quando houver uma caixa limitando
     na largura de leitura, a outra logo abaixo ou acima dela NÃO PODE ser
     tela inteira»*.

     ⭐ O nome existe para que não haja um 800 numa tela e um 840 noutra. Onde
     uma caixa de TEXTO CORRIDO precisar de teto, é este — e a vizinha
     empilhada dela também.

     ⛔ NÃO se chama `--leitura`, e a razão está uma linha acima: `--leitura`
     já é a FAMÍLIA serifada. Dois tokens com o mesmo nome e tipos diferentes
     — um para `font-family`, outro para `max-width` — é colisão que não dá
     erro nenhum, só uma tela errada.

     ⚠ E ele não é para tudo: uma grelha de cartões, uma tabela ou uma lista
     não são texto corrido, e apertá-las a 820 é aplicar uma medida de linha
     a algo que não tem linha. O teto acompanha o TEXTO. */
  --medida-de-leitura: 820px;

  /* ── OS 22 TOKENS DO SISTEMA (SISTEMA-DE-DESIGN.md §1) ──
     Valores COPIADOS da prancha aprovada, não derivados. O par escuro está
     no bloco `prefers-color-scheme` no fim deste arquivo, e é copiado
     também: medido, fora de cor e borda o escuro não muda NADA — nem peso,
     nem espaçamento, nem raio, nem tamanho. */
  --papel: #FAF7F2;
  --tinta-50: #F0E9DF;
  --tinta-100: #E7DFD2;
  --tinta-200: #DCD2C3;
  --tinta-300: #C4B8A6;
  --tinta-400: #7D8AA9;
  --tinta-500: #5C6C93;
  --tinta-600: #475A85;
  --tinta-700: #293F71;
  --tinta-800: #142C64;
  --texto: #101B3A;

  /* ⛔⛔ A CASA TEM DUAS RAMPAS DE PESO AO MESMO TEMPO, E É DE PROPÓSITO.
     Decisão do Alan em 04/09/2026, e ele reconsiderou em voz alta antes de a
     tomar: «desça as 62 também» → «espere» → «são muitas telas, não desça não,
     deixe as outras como estão».

         a tela de Preços ....  400 · 500 · 600            ⭐ a rampa da prancha
         as outras 26 .......  400 · 500 · 600 · 700 · 750

     ⭐ O NÚMERO, para ninguém ter de o remedir: são **62 elementos com peso
     ≥700, em 26 telas** — `a.skip-link` ×26, `b` ×15, `.mk-selo` ×9, `strong`
     ×3, `td` ×2, `.mk-contagem` ×2, `.sp-etiqueta` a 750, e mais seis.
     Varridas as 30 telas do `capturar` a 1440, em 04/09/2026.

     ⚠️⚠️ QUEM VARRER AMANHÃ ACHA 62 PEÇAS «FORA DA RAMPA» E AS QUATRO DE PREÇOS
     «CERTAS», e vai concluir que faltam 62 consertos. ⛔ NÃO FALTAM. Ele viu
     este número à vista e escolheu com ele. NÃO É PENDÊNCIA — é decisão, como
     os 32 alvos abaixo de 44px.

     📌 E é a mesma armadilha que custou meio dia em 04/09: uma lista de 50
     «defeitos» de Preços, de que 31 eram divergências deliberadas com razão
     medida escrita ao lado do código. Um número de diferenças não mede
     defeito: mede DIFERENÇA. */

  /* ⚠ ESTE VERDE NÃO É DO SISTEMA — é o valor literal da prancha
     `Passo20Isencao`. A paleta não tem verde nenhum: o padrão de aviso foi
     para o neutro e o verde ficou sendo um dos estados, sem token próprio.
     Escrevo-o com nome para que exista UM sítio a mudar quando a paleta lhe
     der casa, em vez de três literais espalhados por duas telas. */
  --verde-desconto: #1B7251;
  --texto-fraco: #475A85;
  --linha: #E0D7C8;
  /* ⚠ Os quatro que NÃO invertem (§1.2). Uma inversão automática destrói
     exatamente estes — a marca, a confirmação e o erro têm de ser a mesma
     cor nos dois modos, ou deixam de ser reconhecíveis. */
  /* ⚠️ D-1616, decisão do Alan de 05/09: medido 15,33:1 no claro e 1,03:1 no
     escuro — o título de tela em `--marinho` fica ilegível no escuro se
     seguir a prancha à risca. Seguir a prancha apaga o título; o produto
     fica como está. NÃO É PENDÊNCIA — quem varrer e achar o título fora da
     prancha no escuro: é decisão. */
  --marinho: #001A56;
  --ciano: #009FF0;
  --certo: #0B7A57;
  /* ⚠⚠ DOIS PAPÉIS, O MESMO VERDE, E POR ISSO DOIS TOKENS.

     `--certo` é cor de ESTADO — a marca, o tique, o «deu certo» — e está
     bem na lista acima: NÃO inverte, e a prancha declara `#0B7A57` nos dois
     modos de propósito. Isso não se mexe.

     Mas TINTA sobre um chão é outro papel, e precisa de par próprio.
     Medido: `#0B7A57` sobre o papel claro dá 4,99 ✅, sobre o escuro 3,52 ⛔.
     O par escuro é o `#4E9978` que o Alan aprovou no D-1272.

     ⚠ E o `#4E9978` NÃO serve de substituto: sobre o papel CLARO mede 3,19,
     PIOR do que o que lá está. Por isso é token de dois valores e não uma
     troca — foi medir os dois modos que o disse, e medir só o escuro teria
     produzido uma correção que partia o claro. */
  /* ⚠⚠ #0B7A57 → #00714F, e a razão é a superfície NOVA, não a antiga.
     Sobre o `--papel` o `#0B7A57` mede 4,99 e passa. Sobre o `--certo-lavado`
     — a superfície de confirmação, adoptada em 12 pranchas — mede 4,37 e
     REPROVA. O `#00714F` passa nos dois: 5,66 e 4,95. Foi derivado do próprio
     `--certo`, escurecido no mesmo matiz (163,9° contra 164,3°).

     ⭐ E o que se fez aqui foi ALARGAR o token, não cunhar um ao lado. A
     proposta que chegou era um `--certo-tinta` novo para o segundo valor — e
     esse nome já era este. Um token a valer duas cores conforme quem o lesse
     não aparece em varredura nenhuma: um token com o valor errado não é um
     hexadecimal cru. */
  --certo-tinta: #00714F;
  /* A superfície de confirmação. Só existe do lado claro como cor própria; no
     escuro é o `#002310`, e o `--certo-tinta` escuro serve os dois usos sem
     mudar (5,51 no papel, 4,93 aqui). Era só a metade clara que estava
     apertada. */
  --certo-lavado: #E2EBE2;
  /* ⭐ A FAMÍLIA DAS PÍLULAS DE ESTADO — SISTEMA-DE-DESIGN §1.0.
     Uma pílula de estado é `tinta sobre lavado`, dentro de um cartão, e o par
     tem de existir porque o lavado é quase o cartão: sem par, ele vira mancha
     clara no escuro. Os três literais que estavam no `.chip-run`, `.chip-wait`
     e `.chip-err` mediam 1,06 contra o cartão claro e ~15 contra o escuro.

     ⚠️ E o que a casa fixou no par verde NÃO foram as coordenadas: foram as
     RAZÕES. Copiar o L e o S do verde para os outros matizes dá razões de 3,40
     a 9,52, porque o contraste depende do matiz. Os valores resolvem-se para a
     razão, e não o contrário.

     Conferido aqui, e não aceite: tinta sobre lavado dá 4,93 a 4,96 nos dois
     modos, nos quatro estados. O lavado contra o cartão fica entre 1,09 e
     1,16 — a pílula não tem contorno próprio, e é por isso que ela leva
     `border-color` da própria tinta.

     ⭐ E DOIS dos quatro estados já tinham dono, e é por isso que só entram
     QUATRO valores novos — o par da espera e o lavado do erro:

       · o ERRO não precisa de tinta nova: `--selo` serve, 5,26 no claro e
         4,64 no escuro sobre o lavado dele. O verde precisou de cunhar
         `--certo-tinta` porque o `--certo` reprova no escuro (3,15); o
         `--selo` não reprova, porque já inverte.
       · o ANDAMENTO não precisa de par nenhum: o `--acento-lavado` já está
         RESERVADO ao chip de estado — está escrito duas linhas acima da
         própria definição dele, e no §1 da tabela. O `.chip-run` já o usa,
         vindo da `Passo5Acompanhar`, e mede 13,96 e 14,12.

     ⚠️ A primeira versão desta secção cunhou um `--andamento-*` por cima dessa
     reserva. Eu escrevi-o na folha, corri, e a pílula não mudou — a regra de
     baixo ganhava. Foi assim que a duplicação apareceu, e não por leitura: um
     token que já resolve não se duplica, e este estava a dois parágrafos. */
  --espera-lavado: #EAE8E1;
  --espera-tinta: #835B00;
  --erro-lavado: #EDE5E5;
  --selo: #B3271B;
  /* ⚠⚠ #0077C2 → #00679C, e o valor veio da PRANCHA e não de mim.
     Eu ia mandar o Alan decidir um número para os 4,45 do «Comprar», com um
     `#0074BD` que calculei à mão. O desenho já o tinha, e eu não o via porque
     andava a ler a prancha aos bocados em vez de a extrair inteira.
         prancha #00679C ....  5,75 sobre o papel claro  ✅
         antes   #0077C2 ....  4,45                      ⛔
     ⚠ E é o valor CLARO de um par: #00679C sobre o papel escuro dá 3,06. O
     escuro fica no #009FF0, a 6,46. A prancha dá metade do par — que é a
     metade que uma prancha do modo claro PODE dar. */
  --acento-escuro: #00679C;
  /* ⚠ A ÚNICA superfície fria legítima no chão quente, e só para o chip de
     ESTADO, onde o frio carrega informação (§1.1). Fora daí, superfície
     fria sobre chão quente não lê como acento: lê como estranha. */
  --acento-lavado: #DFEBF2;

  /* ── A SUPERFÍCIE DE SOBREVOO ──────────────────────────────────────────
     Hover e seleção separam-se por MATIZ: o sobrevoo é pardo, a seleção é
     azul. O intervalo azul não dava para três degraus — dava dois de 1,07.

     ⚠⚠ O VALOR ESCURO AINDA NÃO É ESTE. Aqui ele fica em `--tinta-50`, que no
     escuro é azul: ou seja, no escuro sobrevoo e seleção voltam a competir na
     mesma rampa, a 1,11 contra 1,25 sobre o chão. Está errado e está sabido —
     ver o bloco escuro. O token existe para que a resposta troque UM valor. */
  --sobrevoo: var(--tinta-50);

  /* ── O MARINHO QUANDO É SUPERFÍCIE ────────────────────────────────────
     `--marinho` é cor de MARCA e não inverte: no claro serve de fundo à ação
     primária, e no escuro esse mesmo fundo tem de clarear ou some no chão.

     ⚠ Este token é o PAPEL «superfície de ação primária», e não um apelido do
     marinho: onde o marinho é TINTA ele continua `--marinho`, e é por isso que
     os dois nomes existem.

     ⚠⚠ E o `--sobrevoo` NÃO aponta para aqui, apesar de hoje coincidirem no
     escuro. Dois papéis que coincidem num hex não são um papel — foi essa
     regra que já nos poupou uma vez, quando o bege do sobrevoo era o
     `--texto-fraco` «por acaso». */
  --primario: var(--marinho);


  /* ── OS NOMES ANTIGOS, APONTADOS PARA OS NOVOS ──
     São 696 usos de `var(--…)` no produto, e trocá-los um a um seria 696
     lugares onde errar sem que nada fique vermelho. Apontados aqui, o
     produto inteiro vira de uma vez e a troca é REVERSÍVEL numa linha.
     Cada apelido diz de que token do sistema ele passou a ser um nome. */
  --bg: var(--papel);
  --surface: var(--papel);          /* cartão e chão são o MESMO pardo; o que
                                       os separa é a linha, nunca o tom (§3.2) */
  --surface-solid: var(--papel);
  --text: var(--texto);
  --muted: var(--texto-fraco);
  --line: var(--linha);
  --line-strong: var(--tinta-300);  /* contorno de CONTROLE, não de superfície */
  --accent: var(--ciano);
  --accent-hover: var(--acento-escuro);
  --success: var(--certo);
  --danger: var(--selo);
  --navy: var(--marinho);
  --light-blue: var(--acento-lavado);
  /* ⚠ ZERO SOMBRAS (§1.3): a prancha aprovada não tem nenhuma — a
     profundidade vem da borda de 1px. Os dois nomes ficam porque 30 regras
     os citam; o que muda é o que eles valem. */
  --shadow: none;
  --shadow-lg: none;
  /* ⚠ DECLARADO E COM ZERO USOS até 05/09/2026 — 23 regras diziam `8px` à
     mão e nenhuma dizia o nome. É o caso em que o token existe, está certo, e
     não alcança nada: quem trocasse o valor aqui não movia um pixel e
     concluía que o raio não era usado. (D-1614; a excepção de raio que a
     auditoria abriu à regra «espaçamento e raio ficam fora desta passagem».)
     ⛔ Fica de fora o `legal/static/legal/legal.css`, que é outra folha e vai
     com o mesmo `:root` — mas é superfície de outra frente. */
  --radius-md: 8px;                 /* botão, item de menu, campo */
  --radius-lg: 12px;                /* caixa interna, cartão de e-mail */

  /* ── A1 · A TINTA QUE CAI SOBRE A AÇÃO PRIMÁRIA ───────────────────────
     ⭐ O valor NÃO muda e não é para mudar: 11 regras diziam `#fff` sobre
     `--marinho` ou `--primario`, e este token diz o mesmo `#fff` nos dois
     tons. Medido antes e depois, nas cinco telas: `rgb(255, 255, 255)` no
     claro e no escuro, em todas.

     ⛔ Então porquê? Porque `#fff` sozinho não diz SOBRE O QUÊ, e é essa
     ausência que produz o defeito da casa: o mesmo `#fff` está certo sobre o
     marinho (16,38) e errado sobre o `--tinta-500` escuro (1,67) — os dois
     números estão medidos na nota do `.jn-selo`, em `produto.css`. Um nome
     que diz a superfície não se copia para a superfície errada.

     ⚠ E ele NÃO é «branco»: é a tinta desta superfície. Onde o chão for
     outro — o véu preto da lupa, o `--selo` do botão de apagar — a tinta
     continua a ser escrita ali, porque é outro papel.

     📌 O par dele já existia noutro sítio com outro nome: o `--sobre-marinho`
     de `nucleo/templates/_erro.html`, que é folha própria e não vê esta. Os
     dois valem `#fff`; as superfícies é que são diferentes (lá o botão é
     marinho nos dois modos, aqui é `--primario`, que inverte). Ficam
     separados, e fica dito. */
  --sobre-primario: #fff;

  font-family: var(--ui);
}

/* ⚠ O MODO ESCURO — e ele é troca PURA de token.
   Medido pela frente de desenho: 108 declarações no claro contra 108 no
   escuro, 8 diferem, e fora de cor e borda ZERO. Por isso este bloco só
   redeclara valores e não repete regra nenhuma.
   Os quatro que não invertem (--marinho, --ciano, --certo, --selo) NÃO
   estão aqui, de propósito: ausência é o que os mantém iguais. */
/* ── O ESCURO EM TRÊS ESTADOS (pedido do Alan) ─────────────────────────────
   Antes havia um só: o do sistema operativo, e ninguém podia discordar dele.

   ⚠ O `:not([data-theme="light"])` NÃO é enfeite: sem ele, o sistema escuro
   ganharia a quem escolheu claro de propósito — e a escolha explícita da
   pessoa perderia para a preferência do computador dela, que é exatamente ao
   contrário do que um interruptor significa.

   Os dois blocos abaixo têm o MESMO corpo, e é por isso que ele está escrito
   duas vezes em vez de num sítio: CSS não deixa dois seletores de contextos
   diferentes partilharem uma declaração sem um pré-processador, e a casa não
   tem nenhum. Se um dia divergirem, é defeito — não variação. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;
    /* ── A2 · o par do aviso, metade escura (D-1614, lote 3) ──
       4,96 tinta sobre lavado · 5,75 tinta sobre o papel · 1,16 lavado sobre
       o papel. Resolvido para as RAZÕES, não copiado de coordenada nenhuma. */
    --aviso-lavado: #2A1F03;
    --aviso-tinta: #AA8A41;
    --papel: #05102C;
    --tinta-50: #0C1B3E;
    --tinta-100: #13244B;
    --tinta-200: #1C2E58;
    --tinta-300: #2A3F6E;
    --tinta-400: #55689A;
    --tinta-500: #CBC8C3;
    --tinta-600: #D5D2CD;
    --tinta-700: #DFDCD7;
    --tinta-800: #EAE6E2;
    --texto: #FAF7F2;
    --texto-fraco: #D5D2CD;
    --linha: #1C2E58;
    /* ⚠️ D-1616 (05/09): --marinho NÃO é redeclarado aqui de propósito —
       é um dos que não invertem (§1.2). O título de tela nele mede 1,03:1
       no escuro; seguir a prancha apagaria o título. NÃO É PENDÊNCIA — é
       decisão do Alan, o produto fica como está.
    */
    /* ⚠⚠ ESTE TOKEN DESCE DE CONTRASTE AO SER CORRIGIDO — 7,70 para 6,46 — E A
       CORREÇÃO ESTÁ CERTA. No escuro o link é o PRÓPRIO ciano da casa; o
       `#5EAFD8` não é uma cor daqui, e 6,46 passa com folga.
       *Nem toda a correção sobe um número.* Quem vir este a descer numa
       varredura futura: confira contra a `RAMPA-ESCURA.md` antes de o tratar
       como regressão. */
    --acento-escuro: #009FF0;
    --acento-lavado: #0E2649;
    /* ⚠ O `--selo` NÃO divergia: não estava escrito. Sem esta linha ele ficava
       com o valor do claro (#B3271B) e dava 2,89 sobre o chão escuro — errado
       em silêncio, que é pior do que errado à vista. O matiz do selo vive a
       4,7° e o vermelho puro a 0°: enquanto é escuro a inclinação não se vê,
       clarear fá-la aparecer. Preservar o matiz dava laranja, e o Alan
       escolheu 355° — não o mais perto da marca, o mais longe do defeito. */
    --selo: #F04C59;
    /* ⚠ `--certo` NÃO INVERTE, e a ausência dele aqui não era omissão: era a
       resposta. A `TranscreverEscuroBegePardo` declara `--certo: #0B7A57` no
       seu próprio `:root` escuro — o mesmo do claro. Escrito à mão para a
       próxima varredura não o voltar a marcar como «ausente». */
    --certo: #0B7A57;
    --certo-tinta: #4E9978;   /* 5,51 no papel, 4,93 no lavado */
    /* ⚠⚠ O TERCEIRO VERDE, e a ausência dele aqui ERA omissão — ao contrário
       da do `--certo`, três linhas acima, que era resposta.

       Sem esta linha o `--verde-desconto` ficava com o valor do claro,
       `#1B7251`, e media **3,20** sobre o papel escuro: abaixo do piso de 4,5,
       em cinco sítios de duas telas, e um deles é a promoção da isenção — o
       número que o Alan pôs na tela para se ver.

       ⭐ O valor NÃO é novo: é o mesmo `#4E9978` da linha de cima, que ele
       aprovou no D-1272 para o verde irmão. Escolhido por ele em 04/09/2026,
       da prancha das quatro opções, com os números à vista: opção 2.

       📌 E o que se copia de um par para o outro não são as coordenadas, são
       as RAZÕES: o par do `--certo` mantém a leitura entre 4,99 e 5,51, e este
       fica entre 5,50 e 5,51 — praticamente a mesma nos dois modos. */
    --verde-desconto: #4E9978;
    --certo-lavado: #002310;
    /* A família das pílulas de estado, metade escura (§1.0). O `--erro-tinta`
       não existe: quem serve é o `--selo`, que já inverte sozinho. */
    --espera-lavado: #251900;
    --espera-tinta: #9E8751;
    --erro-lavado: #440500;
    /* ⚠ O SOBREVOO ESCURO, e o Alan escolheu-o nomeando a peça: «use a cor do
       botão "Escolher o que fazer", se não houver outra definida». Não havia —
       varri a prancha e a única ocorrência de `hover` nela é tinta de link.

       ⚠⚠ E ESTE HEX NÃO É SÓ DAQUELE BOTÃO. Na `TranscreverEscuroBegePardo`
       ele pinta QUATRO peças: o avatar, a bola ativa da trilha e os dois
       botões primários — as mesmas que na `Passo1Enviar` são `--marinho`. É o
       par escuro do marinho quando o marinho é SUPERFÍCIE.

       ⭐ Fica em token PRÓPRIO, e não a apontar para um `--primario`, mesmo
       tendo o mesmo valor: dois papéis que coincidem num hex não são um papel.
       Separados, mover um amanhã não move o outro — e é essa separação que
       torna barato desfazer isto, se o Alan achar que o sobrevoo se lê como
       ação a acontecer. */
    --sobrevoo: #0C5680;
    --primario: #0E6E9E;
    /* ── A1 · a tinta da ação primária NÃO INVERTE ───────────────────
       Escrita aqui, com o mesmo valor do claro, pela razão do `--certo` seis
       linhas acima: a ausência seria a resposta certa e ilegível. Quem varrer
       amanhã acha-a declarada e não a reporta como par em falta. */
    --sobre-primario: #fff;
  }
}
:root[data-theme="dark"] {
    color-scheme: dark;
    /* ── A2 · o par do aviso, metade escura (D-1614, lote 3) ──
       4,96 tinta sobre lavado · 5,75 tinta sobre o papel · 1,16 lavado sobre
       o papel. Resolvido para as RAZÕES, não copiado de coordenada nenhuma. */
    --aviso-lavado: #2A1F03;
    --aviso-tinta: #AA8A41;
    --papel: #05102C;
    --tinta-50: #0C1B3E;
    --tinta-100: #13244B;
    --tinta-200: #1C2E58;
    --tinta-300: #2A3F6E;
    --tinta-400: #55689A;
    --tinta-500: #CBC8C3;
    --tinta-600: #D5D2CD;
    --tinta-700: #DFDCD7;
    --tinta-800: #EAE6E2;
    --texto: #FAF7F2;
    --texto-fraco: #D5D2CD;
    --linha: #1C2E58;
    /* ⚠️ D-1616 (05/09): --marinho NÃO é redeclarado aqui de propósito —
       é um dos que não invertem (§1.2). O título de tela nele mede 1,03:1
       no escuro; seguir a prancha apagaria o título. NÃO É PENDÊNCIA — é
       decisão do Alan, o produto fica como está.
    */
    /* ⚠⚠ ESTE TOKEN DESCE DE CONTRASTE AO SER CORRIGIDO — 7,70 para 6,46 — E A
       CORREÇÃO ESTÁ CERTA. No escuro o link é o PRÓPRIO ciano da casa; o
       `#5EAFD8` não é uma cor daqui, e 6,46 passa com folga.
       *Nem toda a correção sobe um número.* Quem vir este a descer numa
       varredura futura: confira contra a `RAMPA-ESCURA.md` antes de o tratar
       como regressão. */
    --acento-escuro: #009FF0;
    --acento-lavado: #0E2649;
    /* ⚠ O `--selo` NÃO divergia: não estava escrito. Sem esta linha ele ficava
       com o valor do claro (#B3271B) e dava 2,89 sobre o chão escuro — errado
       em silêncio, que é pior do que errado à vista. O matiz do selo vive a
       4,7° e o vermelho puro a 0°: enquanto é escuro a inclinação não se vê,
       clarear fá-la aparecer. Preservar o matiz dava laranja, e o Alan
       escolheu 355° — não o mais perto da marca, o mais longe do defeito. */
    --selo: #F04C59;
    /* ⚠ `--certo` NÃO INVERTE, e a ausência dele aqui não era omissão: era a
       resposta. A `TranscreverEscuroBegePardo` declara `--certo: #0B7A57` no
       seu próprio `:root` escuro — o mesmo do claro. Escrito à mão para a
       próxima varredura não o voltar a marcar como «ausente». */
    --certo: #0B7A57;
    --certo-tinta: #4E9978;   /* 5,51 no papel, 4,93 no lavado */
    /* ⚠⚠ O TERCEIRO VERDE, e a ausência dele aqui ERA omissão — ao contrário
       da do `--certo`, três linhas acima, que era resposta.

       Sem esta linha o `--verde-desconto` ficava com o valor do claro,
       `#1B7251`, e media **3,20** sobre o papel escuro: abaixo do piso de 4,5,
       em cinco sítios de duas telas, e um deles é a promoção da isenção — o
       número que o Alan pôs na tela para se ver.

       ⭐ O valor NÃO é novo: é o mesmo `#4E9978` da linha de cima, que ele
       aprovou no D-1272 para o verde irmão. Escolhido por ele em 04/09/2026,
       da prancha das quatro opções, com os números à vista: opção 2.

       📌 E o que se copia de um par para o outro não são as coordenadas, são
       as RAZÕES: o par do `--certo` mantém a leitura entre 4,99 e 5,51, e este
       fica entre 5,50 e 5,51 — praticamente a mesma nos dois modos. */
    --verde-desconto: #4E9978;
    --certo-lavado: #002310;
    /* A família das pílulas de estado, metade escura (§1.0). O `--erro-tinta`
       não existe: quem serve é o `--selo`, que já inverte sozinho. */
    --espera-lavado: #251900;
    --espera-tinta: #9E8751;
    --erro-lavado: #440500;
    /* ⚠ O SOBREVOO ESCURO, e o Alan escolheu-o nomeando a peça: «use a cor do
       botão "Escolher o que fazer", se não houver outra definida». Não havia —
       varri a prancha e a única ocorrência de `hover` nela é tinta de link.

       ⚠⚠ E ESTE HEX NÃO É SÓ DAQUELE BOTÃO. Na `TranscreverEscuroBegePardo`
       ele pinta QUATRO peças: o avatar, a bola ativa da trilha e os dois
       botões primários — as mesmas que na `Passo1Enviar` são `--marinho`. É o
       par escuro do marinho quando o marinho é SUPERFÍCIE.

       ⭐ Fica em token PRÓPRIO, e não a apontar para um `--primario`, mesmo
       tendo o mesmo valor: dois papéis que coincidem num hex não são um papel.
       Separados, mover um amanhã não move o outro — e é essa separação que
       torna barato desfazer isto, se o Alan achar que o sobrevoo se lê como
       ação a acontecer. */
    --sobrevoo: #0C5680;
    --primario: #0E6E9E;
    /* ── A1 · a tinta da ação primária NÃO INVERTE ───────────────────
       Escrita aqui, com o mesmo valor do claro, pela razão do `--certo` seis
       linhas acima: a ausência seria a resposta certa e ilegível. Quem varrer
       amanhã acha-a declarada e não a reporta como par em falta. */
    --sobre-primario: #fff;
}

* { box-sizing: border-box; }
html { scroll-behavior: smooth; }

button, input { font: inherit; }
button { -webkit-tap-highlight-color: transparent; }
[hidden] { display: none !important; }
.wrap, .shell { width: min(1240px, calc(100% - 32px)); margin-inline: auto; }
.skip-link {
  position: fixed; top: -70px; left: 16px; z-index: 999;
  padding: 12px 16px; border-radius: 0 0 10px 10px;
  color: var(--sobre-primario); background: var(--navy); font-weight: 700; text-decoration: none;
}
.skip-link:focus { top: 0; }

.site-header {
  position: sticky; top: 0; z-index: 50;
  /* ⚠ ESTES DOIS JÁ NÃO PINTAVAM. Medido em 05/09 nas cinco telas e no
     console: o cabeçalho computa `rgb(250,247,242)` e `rgb(224,215,200)` —
     `--papel` e `--linha` —, porque a regra `.site-header` de baixo (a da
     «superfície limpa») vence e redeclara os dois. O `rgba(238,250,252,.8)`
     é um azul-gelo da paleta antiga que ninguém vê há voltas.
     ⭐ Escrever aqui o que já lá está computado não muda um pixel e tira da
     folha dois literais que a próxima varredura ia contar como cor viva. A
     fusão das duas regras é da frente A3. */
  border-bottom: 1px solid var(--linha);
  background: var(--papel);
  backdrop-filter: saturate(180%) blur(20px);
}
.brand-row { min-height: 68px; display: flex; align-items: center; justify-content: space-between; gap: 16px; }
.logo-box { width: min(380px, 64vw); height: 60px; display: flex; align-items: center; overflow: hidden; }
.logo { display: block; width: auto; max-width: 380px; height: auto; max-height: 52px; object-fit: contain; object-position: left center; }
.product-chip {
  padding: 8px 13px; border: 1px solid var(--line);
  border-radius: 999px; color: var(--navy); background: var(--papel);
  font-size: .78rem; font-weight: 750;
}
.logout-button svg {
  width: 17px; height: 17px; fill: none; stroke: currentColor;
  stroke-width: 1.45; stroke-linecap: round; stroke-linejoin: round;
}
.header-right-group { display: flex; align-items: center; gap: 14px; }
.active-registry-office-topbar {
  display: flex; align-items: center; font-size: .72rem; font-weight: 400;
  color: var(--muted); white-space: nowrap; text-align: right;
}

main { flex: 1 0 auto; }
/* `place-items: center` deixava a coluna do grid em `auto`, e coluna `auto` se
   estica até o MAIOR conteúdo: as seis caixas do código pedem 6×56 mais folga,
   e o cartão nascia com 428px dentro de uma casca de 343 — a lateral direita
   saía fora da tela no celular, cortada. `minmax(0, 1fr)` prende a coluna à
   casca, e aí `width: 100%` do cartão volta a querer dizer o que diz. */
/* O chão da família da entrada — ver o comentário em `allauth/layouts/base.html`.
   Não pode ir na `.login-shell`: ela é a COLUNA de 420px, e pintá-la daria uma
   faixa e não um chão. */
body.entrada { background: var(--tinta-50); }
/* ⚠️ A FAIXA DO TOPO NA ENTRADA — e são TRÊS coisas, não uma.
   A prancha desenha a faixa com 64px e fundo TRANSPARENTE: o bege do chão
   atravessa-a. O produto pinta-a de `--papel` com uma linha por baixo, e isso
   dá um degrau claro sobre o bege. A altura bate ao pixel — 64 contra 64 —, e
   por isso nenhuma medida de geometria a apanhava.

   ⛔ Mas tirar-lhe o fundo SEM tirar o `sticky` seria pior do que deixá-la:
   medido, a tela de cadastro rola 625px, e um logótipo fixo e transparente
   passaria por cima dos campos com nada por trás.

   ⚠️ **E o `static` NÃO vem da prancha — vem da cor.** Uma prancha é uma imagem
   parada e não pode dizer «isto acompanha a rolagem»: o que lá está é a
   AUSÊNCIA de qualquer indicação sobre rolagem, e ler ausência como decisão é
   pôr na prancha uma resposta que ela não deu. A cadeia real é:

     1. a prancha dá a COR — transparente, sem borda .......... é dela
     2. transparente + `sticky` é incoerente, medido .......... é nossa
     3. logo o `static` é CONSEQUÊNCIA de 1, escolhida por nós  é nossa

   **A mudança de comportamento é nossa e está na fila do Alan.** Se ele quiser
   a faixa a acompanhar a rolagem, o que volta atrás é a COR — e aí é a prancha
   que fica por explicar. As três andam juntas ou nenhuma anda.

   ⚠️ E é `body.entrada .site-header` e não `.site-header`: a faixa é a MESMA
   peça da moldura do produto inteiro (`cliente/_barra.html`, incluída também
   pela `cliente/base.html`). Mexer nela sem escopo mudava todas as telas. */
body.entrada .site-header {
  background: transparent;
  border-bottom-color: transparent;
  position: static;
}
.login-shell {
  width: min(420px, calc(100% - 32px)); margin: auto; padding: 70px 0;
  display: grid; grid-template-columns: minmax(0, 1fr); align-content: center;
}
.login-card {
  /* 420 de cartão e 35 de recheio dão os 350 de conteúdo que a prancha
     desenha — medido nas sete telas dela. Era 520/44, que dava 430. */
  width: 100%; padding: clamp(24px, 6vw, 35px); border: 1px solid var(--line);
  border-radius: 14px; background: var(--papel);
  box-shadow: none;
}
/* Três rem serviam a "Entrar" e estouravam com "Insira o código de
   verificação de e-mail", que é o título que o allauth manda de verdade e
   ocupava duas linhas gigantes antes de qualquer conteúdo. */
/* ⚠️ O TÍTULO NUNCA RECEBEU A REGRA DA SERIFADA, e são cinco coisas de uma vez.
   Esta peça declarava margem, tamanho, entrelinha, entreletras e `text-wrap` —
   e nem família, nem peso, nem cor. O que faltava vinha de onde calhava:

     família  ..  herdava o Manrope do `body`; a prancha pede a de leitura,
                  que é um dos DOIS lugares dela (produto.css §1)
     peso     ..  700, e NÃO é herança: é o padrão do navegador para `h1`, e
                  um seletor de elemento ganha à herança. Quem tentasse
                  consertar isto no `body` não mudava nada
     cor      ..  herdava `--tinta-600` do `body`, que é o piso fraco

   ⚠️ A cor é `--texto` e NÃO o `--marinho` que a prancha desenha: a prancha é
   do modo claro e dá metade do par. O marinho não inverte — no escuro este
   título dava 1,15 sobre o papel (errata da §2.1, 02/09/2026). Geometria do
   desenho, cor da regra.

   ⚠️ E o `clamp(…, 5.2vw, …)` SAI. Um título que muda de tamanho com a largura
   da janela não bate com uma prancha em largura nenhuma — a 1000px dava 34,
   noutra dava outro. A prancha diz 25, uniforme nas sete telas.
   O 25 não é o 30 de `.page-heading h1`: aquele é o título de tela DENTRO da
   moldura do produto, e esta família não tem essa moldura. */
.login-card h1 {
  margin: 7px 0 12px; font-family: var(--leitura); font-size: 25px;
  font-weight: 400; line-height: 1.15; letter-spacing: normal;
  color: var(--texto); text-wrap: balance;
}
/* `anywhere` por causa do endereço de e-mail: "confirmamos para
   fulano@empresa-de-nome-comprido.com" é uma palavra só para o navegador, e
   ela furava o cartão pela direita. */
.login-intro { margin: 0 0 28px; color: var(--muted); line-height: 1.55; overflow-wrap: anywhere; }
/* ⚠️ PROVISÓRIO, E A PRANCHA NÃO RESPONDEU.
   Os links deste cartão não tinham cor nenhuma — saíam no `rgb(0,0,238)` do
   agente de utilizador, que não é token da casa e não inverte. Isto NÃO é o
   piso do `--tinta-600`: ali o elemento herda um valor errado e resolve-se
   mudando a herança; aqui ele não tem valor NENHUM, e só se resolve
   declarando. Mesmo que o `body` mude amanhã, estes continuavam azuis.

   Fui buscar a cor à prancha, que é a fonte, e ela não desenha link nenhum —
   ZERO nas sete telas, procurados por `<a>` e por sublinhado. `--acento-escuro`
   é o token de estado da casa, tem par nos dois modos, e é o que outras telas
   usam. ⚠️ Fica até a prancha ser completada; quem a completar decide. */
.login-card a { color: var(--acento-escuro); }
/* O parágrafo que vem DEPOIS do formulário é rodapé, não introdução: "entre em
   contato se tiver problema" é nota de pé de página, e no corpo do texto ele
   competia com a ação da tela. */
.login-card form ~ .login-intro { margin: 16px 0 0; font-size: .72rem; line-height: 1.5; }
/* A fileira de ações do formulário de conta. `row-reverse` porque o allauth
   manda o botão principal primeiro e o nosso Cancelar depois: na tela o
   desistir fica à esquerda e o seguir adiante à direita, como no resto do
   sistema. `:has(> *)` para não abrir folga nas telas que não têm ação
   nenhuma. */
.conta-acoes { display: flex; gap: 10px; }
.conta-acoes:has(> *) { margin-top: 22px; }
.conta-acoes:has(> * + *) { flex-direction: row-reverse; justify-content: space-between; align-items: center; }
.conta-acoes > .button, .conta-acoes > .login-link { margin-top: 0; }
.conta-acoes:has(> * + *) > .button { width: auto; }
/* O allauth às vezes entrega os dois botões dentro de um grupo (`.ev-acoes`),
   como na tela do código: a fileira de fora vê UM filho e não inverte nada. A
   mesma regra vale para o grupo — desistir à esquerda, seguir à direita, em
   toda tela de conta. */
.conta-acoes > .ev-acoes { flex: 1; margin-top: 0; }
.conta-acoes > .ev-acoes:has(> * + *) { flex-direction: row-reverse; justify-content: space-between; }
/* `minmax(0, 1fr)` pelo mesmo motivo da `.login-shell`: coluna `auto` cresce
   até o maior conteúdo, e as seis caixas do código pediam 371px dentro de um
   campo de 302 — as duas últimas saíam pela direita do cartão. */
.login-field { display: grid; grid-template-columns: minmax(0, 1fr); gap: 8px; }
.login-field + .login-field { margin-top: 20px; }
/* 500 e não 750: a prancha desenha o rótulo com o peso médio, e 750 põe-no a
   competir com o título. Medido nas três telas públicas. */
.login-field > span, .login-field label span { font-size: .78rem; font-weight: 500; }
.login-field label { display: block; }
/* O `select` é campo como os outros: sem isto ele nasce com a caixa nativa do
   sistema no meio de campos de 49px e raio 12, e a tela inteira perde o
   ritmo. */
/* ⚠⚠ 44 E NÃO 43, e o 43 NÃO era descuido: era a prancha.
   Estava escrito aqui «43 de altura e 14 de texto, que é o que a prancha
   desenha. Era 49 e 15» — e continua a ser verdade sobre a prancha. O que
   mudou foi que o Alan fixou 44 como a altura de controle da casa (04/09/2026)
   e mandou, com estas palavras: «aumente os itens de 43px para 44px de forma a
   resolver o problema definitivamente».

   ⭐ É ordem dele CONTRA a medida do desenho, e há precedente: o item 4a de
   03/09 decidiu o mesmo empate a favor dele. O 14 do texto fica — ele nomeou a
   altura, e só a altura.

   📌 E o 44 não é gosto: é o piso de alvo de dedo, e é o que os botões e as
   ligações desta mesma família JÁ TINHAM. Um formulário onde o botão mede 44 e
   o campo acima dele mede 43 é a família a discordar de si mesma por um pixel
   que ninguém escolheu — o 43 vinha de uma prancha, e o 44 de uma decisão.

   ⚠ UMA LINHA e não catorze: o 43 estava escrito UMA vez, aqui, e vestia 30
   controles em 8 telas. Medido antes e depois.

   ⛔⛔ E OS OUTROS 31 CONTROLES ABAIXO DE 44 FICAM COMO ESTÃO, ATÉ SEGUNDA
   ORDEM. Decisão do Alan em 04/09/2026, depois de eu lhe levar o inventário
   com a rota de cada um e a captura do menor. Palavras dele:

     «já olhei, mesmo o menor está bom de usar, pq fica isolado na tela
      e não há como errar»

   📌 A MEDIDA CONTINUA CERTA E A DECISÃO TAMBÉM: 26px é 26px, e a lista sai
   de novo em qualquer varredura. O que o número não sabe é o que está À VOLTA
   dele — um alvo pequeno cercado de alvos é onde o dedo erra, e um alvo
   pequeno sozinho num canto não é o mesmo caso. Ele foi ver, e é ele quem
   decide o risco.

   ⚠ E o que ele inspecionou foi o MENOR, o × de 26px que apaga um campo em
   `/document-types/new/`. A razão que ele deu — o isolamento — foi observada
   nesse; a decisão que ele tomou cobre os 31. Fica dito para quem quiser
   reabrir com outro caso na mão.

   ⭐ E O TRIGÉSIMO SEGUNDO ENTROU EM 04/09, pela mesma razão dele: o
   `.sp-anexo-baixar` do chamado — o link que baixa o anexo — mede 197×32.
   Ele não estava nos 31 porque a `/support/<codigo>/` não fazia parte das 30
   telas varridas; foi medida pela primeira vez nesse dia. Palavras dele:

     «deixe o baixar do tamanho que está»

   📌 Mesma conta dos outros: alvo isolado, sem nada ao lado para errar.

   ⭐ Os 31, para não terem de ser remedidos: `.mk-mini-bt` 26 · `.hd-tema-botao`
   28 · as setas do resultado 30 · dois `select` 31 e 34 · `.hd-idioma` 32 ·
   `.password-toggle-button` 34 (seis) · `.mk-ico` 36 · `input.mk-rotulo` 40 e
   43 · `label.toggle-field` 42.

   ⛔ NÃO É PENDÊNCIA. Quem os encontrar numa varredura futura: não são achado,
   são decisão — a mesma distinção que este arquivo já faz a propósito do
   `--acento-escuro` («confira contra a RAMPA-ESCURA.md antes de o tratar como
   regressão»). */
.login-field input, .login-field select { min-height: 44px; font-size: .875rem; width: 100%; }
/* ⚠⚠ `background-color:` e NÃO o atalho `background:`. O atalho reinicia
   `background-image`, `background-repeat` e `background-position`, e estas duas
   regras só querem a COR — pagavam quatro propriedades por uma.

   📌 Foi assim que a seta do `<select>` saiu LADRILHADA no escuro: a regra da
   seta declara imagem + `no-repeat` + posição com especificidade 0,0,1; este
   atalho, com 0,1,1, apagava as três; e a regra do modo escuro, também 0,1,1 e
   mais abaixo, devolvia só a IMAGEM — sem o `no-repeat` nem a posição. Daí
   dezenas de setas repetidas, com ar de borda tracejada.

   ⚠ E no CLARO parecia bem pela pior das razões: a imagem ficava apagada pelo
   atalho e não se via seta nenhuma. O conserto estava certo por acidente — não
   porque a seta funcionasse, mas porque ela não aparecia. */
.login-field select { padding: 11px 13px; border: 1px solid var(--line); background-color: var(--papel); color: var(--text); font-family: inherit }
.password-input-wrap { position: relative; }
.password-input-wrap input { padding-right: 46px; }
.password-toggle-button {
  position: absolute; top: 50%; right: 8px; transform: translateY(-50%);
  display: grid; place-items: center; width: 34px; height: 34px; padding: 0;
  border: none; background: transparent; color: var(--muted); cursor: pointer; border-radius: var(--radius-md);
}
.password-toggle-button:hover { color: var(--text); background: rgba(15,23,42,.06); }
.password-toggle-button svg { width: 20px; height: 20px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.login-submit { width: 100%; margin-top: 16px; justify-content: center; }
/* Seis caixas de 56px com folga de 8px pedem 376px, e o cartão oferece 307 no
   celular: a última saía por baixo dos botões. `flex: 1 1 0` com `min-width: 0`
   as faz dividir o que há. */
.code-boxes { display: flex; gap: clamp(5px, 1.8vw, 9px); }
.code-boxes .code-box {
  flex: 1 1 0; width: auto; min-width: 0; min-height: 54px; max-width: 56px; padding: 0;
  text-align: center; text-transform: uppercase;
  font-size: clamp(1.1rem, 5vw, 1.4rem); font-weight: 800; letter-spacing: 0;
}
/* **A caixa de mensagem, e o ESTADO dela vem do `messages` do Django.**
 *
 * Ela era verde e só: `color: #205d3c` sobre `#edf8f2`, com um "i" branco em
 * círculo verde ao lado, para TODA mensagem — inclusive as 21 de erro do
 * produto. Quem via um pagamento falhar recebia a notícia na cor que o resto da
 * interface usa para dizer que deu certo.
 *
 * **O neutro é a base agora, e o verde virou um dos estados.** Trocar a base
 * pelo verde de sucesso era o que fazia o padrão MENTIR: um estado que só
 * aparece quando alguém o pede não pode ser o que aparece quando ninguém pediu.
 *
 * O nome das classes é o do Django — `error`, `warning`, `success`, `info` —, e
 * é também o que `nucleo/base.html` já usa no `.toast` do console. Adotar em vez
 * de inventar `.erro`/`.aviso`: duas convenções para a mesma coisa divergem na
 * primeira tela que só uma delas lembra. */
.code-sent {
  margin: 0 0 22px; padding: 13px 14px; display: flex; align-items: flex-start; gap: 10px;
  border-radius: 13px; color: var(--acento-escuro); background: var(--acento-lavado);
}
/* ⚠⚠ A2 · OS QUATRO ESTADOS PASSAM A TER PAR ESCURO, e o que estava errado
   não era o tom: era o cravado. Medido no navegador, `getComputedStyle`
   nos dois modos, com o alfa composto:

       antes, no ESCURO, contra o papel escuro:
         a tinta do info ....  #1a3f6b sobre `--acento-lavado`  ⛔ 1,41
         o chão do sucesso ..  #edf8f2                          ⛔ 17,29
         o chão do erro .....  #fdf0ee                          ⛔ 16,90
         o chão do aviso ....  #fdf6e8                          ⛔ 17,48

   ⭐ Os três chãos cravados NÃO davam número mau de leitura — davam 7,17 /
   8,09 / 6,95 nos dois modos, porque a tinta era cravada também. O defeito
   é o outro: três faixas BRANCAS, da largura do cartão, no meio de uma tela
   escura. É a mesma mancha da pílula do «Pronto» (D-1505) e é por isso que
   se conserta pelo token e não pelo tom. E a do info não era mancha: era
   ilegível, porque só o chão dela invertia e a tinta não.
   Depois: 5,06/5,18 · 4,95/4,93 · 5,26/4,64 · 5,23/4,96. */
.code-sent.success { color: var(--certo-tinta); background: var(--certo-lavado); }
.code-sent.error { color: var(--selo); background: var(--erro-lavado); }
.code-sent.warning { color: var(--aviso-tinta); background: var(--aviso-lavado); }
/* O rótulo — "Erro", "Atenção", "Pronto" — é o sinal que sobrevive à captura de
   tela em preto e branco, que é como o suporte recebe a maioria dos defeitos.
   Herda a cor do texto de propósito: colorido à parte, ele viraria mais uma
   coisa dizendo por cor o que já está dito por palavra. */
.code-sent-rotulo { margin-right: 6px; }
/* `flex: none` porque o "i" é um círculo e não um pedaço de texto: como item
   de flex ele encolhia junto com a caixa quando o e-mail era comprido, e o
   redondo virava um ovo. */
/* O selo do glifo. O `background` muda com o estado, mas **o glifo é o sinal e a
   cor é o reforço**: ✕, !, ✓ e i têm quatro formas diferentes, e é por elas que
   um daltônico e uma captura em preto e branco distinguem as quatro. */
.code-sent > span { flex: none; width: 20px; height: 20px; display: grid; place-items: center; border-radius: 50%; color: #fff; background: var(--primario); font-size: .7rem; }
.code-sent.success > span { background: var(--certo-tinta); }
.code-sent.error > span { background: var(--selo); }
.code-sent.warning > span { background: var(--aviso-tinta); }
.code-sent p { margin: 0; font-size: .78rem; line-height: 1.45; overflow-wrap: anywhere; }
.login-note { margin: 9px 0 0; color: var(--muted); font-size: .72rem; line-height: 1.5; }
.login-link { width: 100%; margin-top: 13px; border: 0; color: var(--accent); background: transparent; cursor: pointer; font-size: .78rem; font-weight: 700; }
/* Estava definida só no `produto.css`, que a tela de conta não carrega: os
   botões do allauth encostavam nas caixas do código sem folga nenhuma. Uma
   fileira de ações não é do produto nem da conta — é do design system. */
.ev-acoes { display: flex; flex-wrap: wrap; gap: 9px; justify-content: center; margin-top: 24px; }

/* A escolha entre duas coisas: fichas, e o alvo é a ficha inteira. */
/* Duas fichas lado a lado; no celular elas dividem a largura e continuam com
   48px de altura, que é o alvo mínimo da D-257. */
.escolha-linha { display: flex; gap: 10px; }
.login-field .escolha span { font-size: .85rem; font-weight: 600; }
/* `.login-field label { display: block }` tem a mesma força e vem antes: a
   ficha voltava a ser bloco e o texto caía debaixo do círculo. */
.login-field .escolha {
  flex: 1; display: flex; align-items: center; gap: 9px; min-height: 48px;
  padding: 0 13px; border: 1px solid var(--line); border-radius: 12px;
  background: var(--papel); cursor: pointer; font-size: .85rem;
}
.login-field .escolha:has(input:checked) { border-color: var(--accent); background: var(--light-blue); }
.login-field .escolha input { width: 18px; height: 18px; margin: 0; flex: none; accent-color: var(--accent); }

/* As quatro regras, com os valores do desenho: lista a 12px do campo com 6px
   entre linhas, texto em .75rem. O verde e o vermelho vinham do design
   system escritos à mão (#16794d e #b42318) e por isso NÃO invertiam: no
   escuro mediam 3,47 e 2,86 sobre o papel. São agora `--certo-tinta` e
   `--selo`, que têm valor próprio nos dois modos — 5,66/5,51 e 6,15/5,04.
   (O medidor de força que ficava acima saiu — D-1175.) */
/* A regra nasce cinza e acende verde. Vermelha só depois que a pessoa
   escreveu alguma coisa: um item vermelho num campo vazio acusa quem ainda
   não fez nada. */
.senha-regras { margin: 12px 0 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: 6px }
.senha-regras li { display: flex; align-items: center; gap: 7px; font-size: .75rem; line-height: 1.35; color: var(--muted) }
.senha-regras svg { width: 13px; height: 13px; flex: none; fill: none; stroke: currentColor; stroke-width: 2.4; stroke-linecap: round; stroke-linejoin: round; opacity: .45 }
.senha-regras li.ok { color: var(--certo-tinta) }
.senha-regras li.ok svg { opacity: 1 }
.senha-regras li.falta { color: var(--selo) }
.senha-regras li.falta svg { opacity: 1 }
/* A forma acompanha o estado, e a cor é reforço: tique na cumprida, X na
   que falta. Antes de a pessoa digitar, o tique cinza de sempre. */
.senha-regras .xis { display: none }
.senha-regras li.falta .tique { display: none }
.senha-regras li.falta .xis { display: inline }

.login-message { min-height: 21px; margin: 16px 0 0; font-size: .78rem; line-height: 1.45; text-align: center; }
.login-message.error { color: var(--danger); }
.eyebrow, .section-kicker {
  margin: 0; color: var(--accent); font-size: .72rem; font-weight: 800;
  letter-spacing: .14em; text-transform: uppercase;
}
.page-heading h1 { margin: 5px 0 8px; font-size: clamp(2.4rem, 5vw, 4rem); line-height: .98; letter-spacing: -.055em; }
.lead { margin: 0; color: var(--muted); font-size: 1rem; line-height: 1.5; }
.module-tabs {
  position: static; width: 80%; max-width: 1080px; margin: 0 auto 34px; padding: 6px;
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 6px;
  border: 1px solid rgba(0, 0, 0, .08); border-radius: 20px;
  background: rgba(235, 235, 240, .82); box-shadow: none;
  backdrop-filter: blur(20px);
}
@keyframes tab-panel-in {
  from { opacity: 0; transform: translateY(7px); }
  to { opacity: 1; transform: none; }
}
.pipeline-dashboard-card .section-heading { align-items: flex-start; }
.status-chip { display: inline-flex; align-items: center; min-height: 28px; padding: 5px 10px; border-radius: 999px; background: #eef2ff; color: #3730a3; font-size: .75rem; }
.status-chip.neutral { background: #eef2f6; color: var(--muted); }
.status-chip.danger { background: #fdecea; color: var(--danger); }
#aiPromptVersionsTable td:last-child,
#aiPromptVersionsTable th:last-child { width: 1%; white-space: nowrap; vertical-align: top; }
.batch-filter-select {
  min-height: 34px; padding: 5px 10px; border: 1px solid var(--line); border-radius: var(--radius-md);
  background: var(--papel); font-size: .76rem; font-weight: 600; color: var(--text); cursor: pointer;
}
.filter-toolbar-row .batch-filter-select { min-width: 170px; }
[data-tooltip] { position: relative; }
[data-tooltip]::after {
  content: attr(data-tooltip); position: absolute; bottom: calc(100% + 6px); left: 50%; transform: translateX(-50%);
  background: var(--navy); color: var(--sobre-primario); font-size: .68rem; font-weight: 600; white-space: nowrap;
  padding: 4px 8px; border-radius: 6px; opacity: 0; pointer-events: none; transition: opacity .12s ease; z-index: 20;
}
[data-tooltip]:hover::after, [data-tooltip]:focus-visible::after { opacity: 1; }
#promptVersionModal.modal, #schemaVersionModal.modal { width: min(720px, calc(100% - 28px)); }
#schemaVersionModal textarea#aiNewSchemaJson { min-height: 220px; font-family: "SFMono-Regular", Consolas, monospace; font-size: .82rem; }
#aiSchemaVersionsTable td:last-child,
#aiSchemaVersionsTable th:last-child { width: 1%; white-space: nowrap; vertical-align: top; }
#aiNewPromptLivroEFamilyHelper { white-space: pre-line; display: block; }
/* ⚠ `--navy` como tinta media 1,15 sobre o papel escuro: o rótulo do
   interruptor desaparecia no «entrar» e nos «meus dados». É a MESMA peça nas
   duas telas, e por isso UMA linha fecha as duas — o que a varredura mostrou e
   uma lista de defeitos por tela teria escondido. `--texto` dá 15,85 no claro
   e 17,59 no escuro. */
.toggle-field { display: flex; align-items: center; gap: 8px; min-height: 42px; color: var(--texto); font-size: .82rem; }
.review-workbench-toolbar { display: flex; align-items: end; gap: 12px; flex-wrap: wrap; margin-bottom: 16px; }
.review-workbench-toolbar .field-group { min-width: min(100%, 390px); flex: 1 1 320px; }
.review-workbench-grid { display: grid; grid-template-columns: minmax(280px, .9fr) minmax(0, 1.35fr); gap: 18px; min-height: 420px; min-width: 0; }
.review-image-pane, .review-result-pane { min-width: 0; padding: 16px; border: 1px solid var(--line); border-radius: 14px; background: #fbfcfe; }
.review-image-frame { min-height: 330px; margin: 10px 0; display: grid; place-items: center; overflow: auto; border: 1px dashed var(--line-strong); border-radius: 10px; background: #f1f5f9; }
.review-image-frame img { display: block; max-width: 100%; max-height: 460px; object-fit: contain; }
.review-full-text { margin: 0; white-space: pre-wrap; overflow-wrap: anywhere; }
.review-data-list { display: grid; grid-template-columns: minmax(130px, .55fr) minmax(0, 1fr); gap: 8px 14px; margin: 0; }
.review-data-list dt { color: var(--muted); font-weight: 700; overflow-wrap: anywhere; }
.review-data-list dd { margin: 0; overflow-wrap: anywhere; }
.pipeline-v2-review-toolbar .field-group { flex: 1 1 260px; }
.pipeline-v2-queue .button { text-align:left; }
.pipeline-v2-effect .field-group { margin:0; }
.pipeline-v2-effect .field-group label { font-size:.72rem; }
.review-annotation-card { display: grid; gap: 5px; padding: 12px; margin: 8px 0; border: 1px solid #ead28a; border-radius: 10px; background: #fffaf0; }
.review-annotation-card.structured { border-color: #b9dfc7; background: #f1fbf4; }
.review-annotation-card small { color: var(--muted); }
.advance-button.button { display: flex; margin: 20px 0 0 auto; }
.form-grid { display: grid; gap: 16px; }
.three-columns { grid-template-columns: repeat(3, minmax(0, 1fr)); }
/* ⚠⚠ `background-color:` e NÃO o atalho `background:`. O atalho reinicia
   `background-image`, `background-repeat` e `background-position`, e estas duas
   regras só querem a COR — pagavam quatro propriedades por uma.

   📌 Foi assim que a seta do `<select>` saiu LADRILHADA no escuro: a regra da
   seta declara imagem + `no-repeat` + posição com especificidade 0,0,1; este
   atalho, com 0,1,1, apagava as três; e a regra do modo escuro, também 0,1,1 e
   mais abaixo, devolvia só a IMAGEM — sem o `no-repeat` nem a posição. Daí
   dezenas de setas repetidas, com ar de borda tracejada.

   ⚠ E no CLARO parecia bem pela pior das razões: a imagem ficava apagada pelo
   atalho e não se via seta nenhuma. O conserto estava certo por acidente — não
   porque a seta funcionasse, mas porque ela não aparecia. */
.field-group select, .field-group input, .sample-file-select { width: 100%; margin-top: 7px; min-height: 44px; border: 1px solid var(--line); border-radius: 10px; padding: 9px 11px; background-color: var(--papel); color: var(--text); font: inherit; }
.sample-accordion-list { display: grid; gap: 12px; margin-top: 18px; }
.sample-accordion { overflow: hidden; border: 1px solid var(--line); border-radius: 14px; background: var(--papel); }
.sample-accordion[open] { border-color: var(--foco-borda); box-shadow: none; }
.sample-accordion summary { padding: 15px 17px; display: flex; align-items: center; justify-content: space-between; gap: 12px; cursor: pointer; font-weight: 760; }
.sample-accordion summary::marker { color: var(--accent); }
.sample-accordion-body { padding: 0 17px 18px; border-top: 1px solid var(--line); }
.sample-form-grid .field-group { margin-top: 15px; }
.sample-editor .submission-row .field-group { flex: 1 1 220px; min-width: 180px; }
.sample-editor .submission-row .button,
.sample-editor .submission-row .icon-lock-button { flex: 0 0 auto; }
.inner-tab.active { color: var(--text); border-bottom-color: var(--accent); }
.responsive-table { overflow-x: auto; margin-top: 16px; }
.responsive-table table { width: 100%; border-collapse: collapse; }
.responsive-table th, .responsive-table td { padding: 12px; border-bottom: 1px solid var(--line); text-align: left; white-space: nowrap; }
.responsive-table td[colspan] { color: var(--muted); text-align: center; padding: 34px; }
.compact-datatable { border: 1px solid var(--line); border-radius: 10px; }
.compact-datatable table { min-width: 1380px; font-size: .71rem; }
.compact-datatable th { padding: 8px 9px; color: var(--muted); background: #f7f7f8; font-size: .67rem; text-transform: uppercase; letter-spacing: .025em; }
.compact-datatable td { max-width: 205px; padding: 7px 9px; vertical-align: top; white-space: normal; line-height: 1.35; }
.compact-datatable td span { display: block; }
.compact-datatable td .table-primary { color: var(--text); font-weight: 700; }
.compact-datatable td .table-secondary { margin-top: 2px; color: var(--muted); font-size: .66rem; }
.compact-datatable td .table-secondary.is-error { color: #b3261e; font-weight: 700; }
.compact-datatable td .table-link {
  background: none; border: none; padding: 0; margin: 0; cursor: pointer;
  color: var(--accent); text-decoration: underline; text-underline-offset: 2px;
  font: inherit; font-weight: 700; text-align: left;
}
.compact-datatable td .table-link:hover { color: var(--navy); }
.compact-datatable .button { min-height: 30px; padding: 5px 9px; font-size: .68rem; }
.compact-datatable td.table-actions { vertical-align: middle; }
.compact-datatable tfoot .table-totals-row td { border-top: 2px solid var(--line); border-bottom: none; background: #f7f7f8; font-weight: 700; color: var(--text); vertical-align: middle; }
.table-actions-inner { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
#resultadosNovaSummaryCard { margin-top: 22px; }
#cutBatchesPanel .compact-datatable table { min-width: 0; width: 100%; table-layout: auto; }
.batch-stage-icon.is-error { color: var(--danger); }
#cutBatchTypeFilter, #cutBatchStatusFilter {
  min-height: 34px; padding: 5px 10px; border: 1px solid var(--line); border-radius: var(--radius-md);
  background: var(--papel); font-size: .76rem; font-weight: 600; color: var(--text); cursor: pointer;
}
.stats-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 14px; margin-bottom: 18px; }
.stat-card { display: grid; gap: 8px; padding: 20px; border: 1px solid var(--line); border-radius: var(--radius-lg); background: var(--surface); }
.stat-card span, .stat-card small, .empty-state-card > p { color: var(--muted); }
.stat-card strong { font-size: 1.8rem; letter-spacing: -.04em; }
.financial-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 14px; margin-top: 14px; }
.financial-card { display: grid; gap: 6px; padding: 16px 18px; border: 1px solid var(--line); border-radius: var(--radius-lg); background: var(--surface); }
.financial-card span { color: var(--muted); font-size: .82rem; }
.financial-card small { color: var(--muted); }
.financial-card strong { font-size: 1.4rem; letter-spacing: -.03em; }
.financial-card-highlight { background: var(--accent-soft, #eef4ff); border-color: var(--accent); }
.financial-value-primary { font-size: 2rem; color: var(--accent); }
.empty-state-note { color: var(--muted); }
.filter-actions { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 10px; margin-top: 18px; }
#sandboxViewport { grid-column: 2; }
.button.small { padding: 5px 10px; min-height: 30px; font-size: .72rem; margin-top: 12px; }
.settings-card, .preview-card, .execution-card {
  border: 1px solid var(--line); border-radius: var(--radius-lg);
  background: var(--surface); box-shadow: var(--shadow); backdrop-filter: blur(18px);
}
.section-heading { display: flex; align-items: center; gap: 12px; }
.section-heading h2, .preview-card h2, .execution-card h2 { margin: 3px 0 0; font-size: 1.18rem; letter-spacing: -.02em; }
.field-note { margin: 7px 2px 0; color: var(--muted); font-size: .76rem; line-height: 1.4; overflow-wrap: anywhere; }
.field-group.validation-error .input-action input {
  border-color: rgba(180,35,24,.72);
  box-shadow: 0 0 0 1px rgba(180,35,24,.08);
}
.field-group.validation-error > label { color: var(--danger); }
/* `email`, `password` e `tel` entram nos mesmos dois seletores em que o
   `text` já estava, e não numa regra nova: a caixa é a mesma, e descrevê-la
   duas vezes seria duas verdades sobre o mesmo desenho. Eles faltavam porque
   até o M7.1 nenhuma tela tinha formulário de conta — nenhuma tela do console
   tem input desses três tipos, então nada do que já existia muda de aparência. */
/* `input:not([type])` junto com os outros: um `<input>` sem `type` É um campo
   de texto para o navegador, mas não casa com `input[type="text"]` — e cai
   para o desenho padrão do sistema, com borda de 2px em relevo e canto reto no
   meio de campos de raio 8. Aconteceu com o e-mail de Meus dados, e a próxima
   vez seria igual: o defeito não avisa, ele só fica feio. */
input:not([type]),
input[type="text"], input[type="number"],
input[type="email"], input[type="password"], input[type="tel"] {
  width: 100%; padding: 11px 13px; border: 1px solid var(--line-strong);
  border-radius: 12px; color: var(--text); background: var(--papel);
  transition: border-color .18s, box-shadow .18s, background .18s;
}
.mini-button {
  position: absolute; z-index: 1; right: 5px; top: 50%; min-height: 34px; padding: 5px 10px;
  transform: translateY(-50%);
  border: 0; border-radius: 9px; color: var(--texto); background: var(--light-blue);
  cursor: pointer; font-size: .75rem; font-weight: 750;
}
.button:disabled { opacity: .48; cursor: not-allowed; }
.button.danger { color: #fff; background: var(--danger); }
.page-heading .page-heading-settings-access { justify-self: end; }
.page-heading .page-heading-model-access { justify-self: end; max-width: 360px; }
.page-heading .page-heading-pipeline-access { justify-self: end; max-width: 360px; }
.ai-phase-defaults-table-wrap .button { min-height: 32px; padding: 6px 12px; font-size: .7rem; white-space: nowrap; }

@media (max-width: 700px) {
  .page-heading .page-heading-settings-access { justify-self: start; }
  .page-heading .page-heading-model-access { justify-self: start; max-width: none; }
  .page-heading .page-heading-pipeline-access { justify-self: start; max-width: none; }
}
@keyframes spin { to { transform: rotate(360deg); } }
@keyframes upload-indeterminate {
  from { transform: translateX(-110%); }
  to { transform: translateX(290%); }
}

fieldset { margin: 22px 0 0; padding: 0; border: 0; }
fieldset > legend { margin-bottom: 8px; }
.toggle {
  position: relative; width: 41px; height: 24px; flex: 0 0 auto;
  border-radius: 99px; background: #d2d2d7; transition: background .2s;
}
.toggle::after {
  content: ""; position: absolute; top: 2px; left: 2px; width: 20px; height: 20px;
  border-radius: 50%; background: var(--papel); box-shadow: none; transition: transform .2s;
}
input[type="checkbox"]:checked + .toggle { background: var(--accent); }
input[type="checkbox"]:checked + .toggle::after { transform: translateX(17px); }
#customPrefixInput { width: 64px; text-align: center; text-transform: lowercase; }
#bookNumberInput { width: 120px; background: var(--papel); }

.execution-card { margin-top: 22px; padding: 24px; }
#gcpUploadCard { margin-top: 22px; }
.action-buttons .button { flex: 0 1 auto; }
#openFolderButton { margin-left: auto; }
.progress-bar.success { background: var(--success); }
.progress-bar.failed { background: var(--danger); }
.cloud-upload-track.success > span { background: var(--success); }
.cloud-upload-track.failed > span { background: var(--danger); }
#gcpUploadButton { margin-top: 13px; }
.generated-group-item.bottom { flex-direction: column-reverse; }

.modal { width: min(520px, calc(100% - 28px)); padding: 0; border: 0; border-radius: 24px; background: transparent; box-shadow: none; }
.modal::backdrop { background: rgba(0, 15, 38, .6); backdrop-filter: blur(5px); }

#registryOfficialAddButton { margin-top: 12px; }
#registryOfficeNewButton { margin-top: 16px; }
.pipeline-results-dialog .field-group { padding: 10px 22px 0; }
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}
.two-columns {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}
.field-group textarea, .config-editor-section textarea {
  width: 100%; margin-top: 7px; padding: 10px 11px; resize: vertical;
  border: 1px solid var(--line); border-radius: 10px; background: var(--papel); color: var(--text); font: inherit;
}
@media (max-width: 720px) { .two-columns, .inline-catalog { grid-template-columns: 1fr; } }
.modal h2 { margin: 18px 0 8px; font-size: 1.35rem; letter-spacing: -.025em; }
.modal p { margin: 0; color: var(--muted); line-height: 1.55; }
.modal details { margin-top: 14px; color: var(--muted); font-size: .78rem; }
.modal ul { max-height: 110px; overflow: auto; }
.toast-region { position: fixed; right: 22px; bottom: 22px; z-index: 1200; display: grid; gap: 9px; }
.toast {
  width: min(390px, calc(100vw - 44px)); padding: 14px 16px; border: 1px solid var(--line);
  border-radius: 14px; color: var(--text); background: var(--papel);
  box-shadow: none; animation: toast-in .25s ease both; font-size: .83rem; line-height: 1.4;
}
.toast.success { border-color: rgba(22,121,77,.25); }
.toast.error { border-color: rgba(180,35,24,.3); }
@keyframes toast-in { from { opacity: 0; transform: translateY(8px); } }
@keyframes spinner-rotation { to { transform: rotate(360deg); } }
.fm-book-item.active { background: var(--light-blue); color: var(--texto); font-weight: 700; }
#fileManagerDeleteButton svg { width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 1.7; }
.footer-bottom span:last-child { text-align: right; }

@media (max-width: 1079px) {
  /* D-1615, CONSERTO A — o `sticky` da topbar falhava em silêncio: um
     `sticky` sem scrollport próprio não tem a que se colar, e um
     `overflow-x: hidden` aqui bastava para isso, porque a folha de estilo
     computada FUNDE os dois eixos — a espec do CSS Overflow trata um eixo
     `visible` ao lado de outro que não é `visible` como uma combinação
     confusa, e sobe o `visible` para `auto`; então o `overflow-y` do
     `body` virava `auto` mesmo sem regra nenhuma para ele, e o documento
     deixava de ser o scrollport. Medido por acto (não deduzido): com
     `hidden` o `body` calcula `overflow-y: auto`; com `clip` calcula
     `visible` — porque `clip`, ao contrário de `hidden`, não é tratado
     como "não-visible" para esse ajuste, e por isso não cria contexto de
     rolagem novo. `clip` ainda contém o transbordo horizontal (é o que
     a varredura mede) — só deixa de fabricar o scrollport que rouba o
     `sticky`. */
  html, body { max-width: 100%; overflow-x: clip; }
  .site-header { z-index: 90; }
  .brand-row {
    width: calc(100% - 20px);
    min-height: 60px;
    gap: 8px;
  }
  .logo-box { min-width: 0; width: auto; height: 50px; flex: 1 1 auto; }
  .logo { width: auto; max-width: 100%; max-height: 40px; }
  .logout-button {
    width: 40px;
    height: 40px;
    min-height: 40px;
    flex: 0 0 40px;
    justify-content: center;
    padding: 0;
    border-radius: 10px;
  }
  .logout-button span { display: none; }
  .logout-button svg { width: 19px; height: 19px; }
  .active-registry-office-topbar { display: none; }
}

/* Result/file viewer controls must wrap as a unit on narrow screens. */
@media (max-width: 800px) {
  .preview-toolbar > .section-heading, .generated-toolbar > div:first-child, .sample-preview-toolbar > div:first-child {
    min-width: 0;
    flex: 1 1 160px;
  }
}

@media (max-width: 960px) {
  .three-columns, .stats-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .submission-row .button.primary { grid-column: 1 / -1; }
}
@media (max-width: 640px) {
  .wrap, .shell { width: min(100% - 20px, 1240px); }
  .logo-box { width: min(270px, 63vw); }
  .logo { max-width: 270px; max-height: 42px; }
  .product-chip { display: none; }
  .app-shell { padding: 28px 0 46px; }
  .page-heading { align-items: flex-end; }
  .page-heading .lead { display: none; }
  .module-tab { min-height: 56px; padding-inline: 5px; font-size: .7rem; }
  .module-tabs {
    width: 100%;
    margin-bottom: 22px;
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }
  .module-tab-kicker { font-size: .54rem; letter-spacing: .06em; }
  .three-columns, .two-columns, .sample-form-grid, .stats-grid { grid-template-columns: 1fr; }
  .settings-card, .execution-card { padding: 18px; }
  .action-buttons .button { flex: 0 1 50%; padding-inline: 11px; }
  .footer-bottom span:last-child { text-align: left; }
}

/* Radix-inspired clean surface: low-contrast gray canvas, compact radii and quiet elevation. */
body {
  min-width: 320px;
  min-height: 100vh;
  margin: 0;
  color: var(--text);
  /* ⚠⚠ OS DOIS GRADIENTES DO `body` SAÍRAM, e a decisão é do DESENHO e não
  da folha. A A1 mediu que eles não pintavam nada:
  `getComputedStyle(body).backgroundImage` devolvia `none` nas oito leituras
  (cinco telas do produto, duas do console, dois tons, 05/09/2026), porque
  `background: var(--bg)`, escrito mais abaixo no mesmo seletor, é um atalho
  — e um atalho reescreve o `background-image` inteiro. A fusão dos dois
  blocos (A3) pôs as duas declarações uma debaixo da outra e a pergunta
  deixou de ter onde se esconder: ou o chão é gradiente, ou é chapado.

  ⭐ O `SISTEMA-DE-DESIGN.md` responde, e responde por AUSÊNCIA E POR
  PRESENÇA. Ausência: a palavra «gradiente» não aparece uma única vez no
  documento, nem na tabela dos 22 tokens, nem na das superfícies. Presença:
  o fundo da tela está escrito como token chapado — §5.1 dá `fundo` como
  `--papel` `#FAF7F2` / `#05102C`, e a folha diz `--bg: var(--papel)`. O
  chão desta casa é o papel do documento fotografado (§1), e um halo de
  ciano no canto superior é justamente o que o §3.2 nega quando diz que
  «cartão e chão são o MESMO pardo, e o que os separa é a linha».

  ⛔ Não se apagam por não pintarem — apagam-se por o desenho não os querer.
  A diferença importa: uma declaração morta que o desenho QUISESSE vivo era
  um defeito a consertar na regra de baixo, e não lixo a varrer. Ficam aqui
  os valores que tinham, para quem reabrir a decisão: dois
  `radial-gradient` a 15%/-10% e 100%/10%, com 34rem e 30rem de raio, a 14%
  e 10% de opacidade — e os literais eram `rgba(0,153,204,…)` e
  `rgba(0,221,255,…)`, dois azuis estrangeiros que a A1 já tinha trocado
  pelo `--ciano` da casa.

  📌 A tela não muda em pixel nenhum, e é por isso que isto é seguro: o
  papel do `body` mede `rgb(250,247,242)` no claro e `rgb(5,16,44)` no
  escuro, antes e depois. */
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  display: flex;
  flex-direction: column;
}

.site-header {
  border-bottom-color: var(--line);
  background: var(--papel);
  backdrop-filter: none;
}

.logout-button {
  min-height: 38px;
  padding: 8px 13px;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  border: 1px solid var(--line);
  cursor: pointer;
  font-size: .78rem;
  font-weight: 750;
  border-radius: var(--radius-md);
  color: var(--text);
  background: var(--papel);
  box-shadow: none;
}

.logout-button:hover {
  color: var(--accent);
  border-color: var(--foco-borda);
  background: var(--papel);
}

.module-tabs {
  width: min(100%, 1080px);
  padding: 5px;
  gap: 4px;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--papel);
  box-shadow: none;
  backdrop-filter: none;
}

.module-tab:focus-visible {
  outline: 2px solid var(--foco);
  outline-offset: 2px;
}

.settings-card, .preview-card, .execution-card,
.flow-card, .construction-card, .sample-accordion {
  border-color: var(--line);
  border-radius: 12px;
  background: var(--papel);
  box-shadow: var(--shadow);
  backdrop-filter: none;
}

.settings-card {
  padding: 20px;
}
.field-group {
  margin-top: 19px;
}
/* ⚠⚠ O RÓTULO DO CAMPO ERA UM CINZA QUE NÃO INVERTE, e o defeito não estava
   no claro. Este seletor vinha declarado DUAS vezes — `#3a3a3c` em cima e
   `#344054` em baixo — e o segundo vencia; a fusão já o deixou num bloco só.
   ⛔ Mas o vencedor era um literal, e um literal não tem metade escura.
   Medido na bancada (servidor 8104, `ferramentas/sondas/valores.py`,
   `.field-group > label` em `console:/novo-lote/`, 10 elementos, 05/09/2026):
   ele computa `rgb(52, 64, 84)` NOS DOIS TONS — o mesmo número sobre dois
   chões opostos, que é a assinatura de um literal.

       #344054 sobre o papel claro (#FAF7F2) ....   9,79  ✅
       #344054 sobre o papel escuro (#05102C) ...   1,80  ⛔

   No escuro o rótulo de TODO o formulário estava ilegível, em silêncio. E o
   perdedor não salvava nada: o `#3a3a3c` de cima dá 10,62 e 1,66.
   ⭐ `--texto-fraco` é o token deste papel — `--muted` aponta para ele — e já
   serve o rodapé do console duzentas linhas abaixo:

       --texto-fraco claro  (#475A85) sobre #FAF7F2 ....   6,40  ✅
       --texto-fraco escuro (#D5D2CD) sobre #05102C ....  12,47  ✅

   ⚠ O CLARO DESCE, de 9,79 para 6,40, e a troca continua certa: 6,40 passa o
   piso de 4,5 com folga e 1,80 não passa nada. É a espécie 11 — medir um modo
   e escolher por ele; aqui os dois estão medidos. */
.field-group > label, fieldset > legend {
  font-size: .82rem;
  font-weight: 750;
  color: var(--texto-fraco);
}

/* O `select` da tela de conta entra aqui junto com os campos de texto: ele
   estava com raio 12 enquanto os vizinhos tinham 8, e numa coluna de treze
   campos a diferença lê-se como defeito. Um número só, e é este. */
input:not([type]),
input[type="text"], input[type="number"],
input[type="email"], input[type="password"], input[type="tel"],
.login-field select,
.field-group select, .field-group input, .sample-file-select,
.field-inline input, .field-inline select {
  border-color: var(--line-strong);
  border-radius: var(--radius-md);
  /* ⚠⚠ `background-color:` — este é o TERCEIRO atalho que apagava a seta, e o
     que de facto a apagava. Consertei os outros dois primeiro, medi, e o
     ladrilho continuou lá: o meu `grep` por «select» com «background:» não
     apanhou este porque o `select` está no fim de uma lista de nove seletores.

     📌 Consertar dois de três e medir foi o que evitou dar isto por resolvido.
     Se eu tivesse consertado e reportado, teria ficado certo no papel. */
  background-color: var(--papel);
}

input:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--foco);
}

/* ⚠⚠ 40 → 44, e é UMA LINHA porque o recheio já é inerte: 9+16,8+9+2 = 36,8,
   e quem manda na altura é este `min-height`. Subir 40 para 44 troca UM número
   e não mexe em `padding` nenhum.

   📌 A prancha desenha o botão a 46 e o produto dava 40. A frente do desenho
   mediu os três renderizados e achou que a diferença NÃO era «qual dos três
   números vence»:

     prancha ....  fs 15 · lh 18   · recheio 13/13 · borda 1 → 46,0
     produto ....  fs 14 · lh 16,8 · recheio  9/9  · borda 1 → 40,0
     a tabela ...  diz 44, e ⛔ NINGUÉM nunca renderizou esse 44

   ⛔ O 44 da tabela é `11+11+2+20`, e o 20 não existe na folha: a coluna
   «altura resultante» é aritmética sobre uma entrelinha que a tabela não
   escreve, e metade da conta está nessa entrelinha.

   ⭐ «A causa não era qual dos três números vence: era que a conta que os
   gerava estava incompleta.»

   ⚠ E o 46 da prancha vem da MESMA tabela, na linha errada — `13px 22px` é o
   botão de E-MAIL, e aparece 83 vezes nas pranchas contra 36 do botão de
   verdade. O número certo do objeto errado, terceira vez em doze horas.

   ⭐⭐ E 44 já era o número da casa NO CELULAR (D-257, `.jn-pe .button`): esta
   linha não inventa uma medida, torna universal a que a barra de ações já
   usava — e traz o alvo de toque de 44 de graça em todo o produto.

   ⛔ E a TIPOGRAFIA não se mexe: 15/18 contra 14/16,8 toca 83 lugares e está
   retida. Com a altura declarada dos dois lados, ela deixa de produzir
   diferença de ALTURA. */
.button {
  padding: 9px 17px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  border: 1px solid transparent;
  cursor: pointer;
  white-space: nowrap;
  flex-shrink: 0;
  transition: background .18s, color .18s, border-color .18s, transform .18s, opacity .18s;
  min-height: 44px;
  border-radius: var(--radius-md);
  font-weight: 650;
  box-shadow: none;
}

.button:hover:not(:disabled) {
  transform: none;
}
.button.primary {
  color: var(--sobre-primario);
  background: var(--primario);
}
.button.primary:hover:not(:disabled) {
  background: var(--accent-hover);
}
.button.ghost {
  color: var(--text);
  border-color: var(--line);
  background: var(--papel);
}
/* ⚠⚠ O SOBREVOO DO BOTÃO FANTASMA ERA UM LITERAL FRIO QUE NÃO INVERTE — e no
   escuro isto não estava feio: estava INVISÍVEL.

   `#f9fafb` fica o MESMO nos dois modos, e a tinta por cima inverte:

       claro    --texto #101B3A sobre #f9fafb ....  16,21  ✅
       escuro   --texto #FAF7F2 sobre #f9fafb ....   1,02  ⛔

   📌 Passar o mouse por cima de um botão fantasma no escuro APAGAVA o rótulo,
   em todas as telas do produto. Ninguém tinha olhado porque o REPOUSO está
   certo: a sonda de contraste mede o que está na tela, e o sobrevoo não está na
   tela até alguém lá pôr o mouse.

   ⭐ E o token para isto JÁ EXISTE: `--sobrevoo`. Escrevi primeiro
   `--tinta-50`, que é para onde ele aponta no claro — e estava errado por uma
   razão escrita vinte linhas acima da declaração dele: no escuro os dois
   separam-se, e «dois papéis que coincidem num hex não são um papel».

       claro    --texto sobre --sobrevoo (#F0E9DF) ..  14,05  ✅
       escuro   --texto sobre --sobrevoo (#0C5680) ..   7,39  ✅

   E separa-se melhor do repouso no escuro: 2,38 contra os 1,11 do `--tinta-50`.

   ⚠ Não é um token de sobrevoo novo: a §9 do sistema diz que a prancha não
   desenha sobrevoo, e continua sem desenhar. */
.button.ghost:hover:not(:disabled) {
  border-color: var(--line-strong);
  background: var(--sobrevoo);
}

.site-footer {
  flex: none;
  margin-top: auto;
  border-top: 1px solid var(--line);
  border-top-color: var(--line);
  background: var(--papel);
}

.footer-bottom {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 22px;
  line-height: 1.45;
  min-height: 36px;
  padding: 8px 0;
  /* ⚠ `#7b8494` DAVA 3,53 SOBRE O PAPEL CLARO — abaixo do piso de 4,5, e é
  a linha do rodapé do console. Um literal não inverte: no escuro dava
  4,99, e o mesmo número servia dois chãos opostos por acaso.
  `--texto-fraco` dá 6,40 no claro e 12,47 no escuro. */
  color: var(--texto-fraco);
  font-size: .72rem;
}

@media (max-width: 640px) {
  .footer-bottom {
    flex-direction: column;
    align-items: flex-start;
    min-height: 36px;
    padding: 8px 0;
    gap: 4px;
  }
}

.module-sidebar-toggle:hover { color: var(--texto); background: var(--light-blue); }
.module-sidebar-toggle-glyph { display: block; width: 20px; height: 20px; line-height: 1; transition: transform .2s ease; }
.module-sidebar-toggle-glyph svg { width: 20px; height: 20px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.module-sidebar.is-expanded .module-sidebar-toggle-glyph { transform: rotate(180deg); }

.module-tabs {
  width: 100%;
  max-width: none;
  margin: 8px 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
  border: 0;
  border-radius: 0;
  background: transparent;
  box-shadow: none;
}

.module-tab::before {
  display: none;
}
.module-tab:hover .module-tab-icon { color: var(--text); }
.module-tab.active .module-tab-icon, .module-tab[aria-selected="true"] .module-tab-icon { color: var(--accent); }

@media (max-width: 1079px) {
  .module-tab-icon, .module-tab::after { display: none; }
}

/* Full-height module sidebar: Feather line icons collapsed by default, labels on demand. */
.app-shell {
  /* Compact module navigation: icon rail by default, labels on demand. */
  grid-template-columns: 56px minmax(0, 1fr);
  gap: 20px;
  align-items: start;
  width: auto;
  max-width: none;
  margin: 0;
  padding: 32px 32px 46px 96px;
  display: block;
}
.app-content {
  min-width: 0;
}
.module-sidebar {
  top: 84px;
  position: fixed;
  inset: 68px auto 0 0;
  z-index: 45;
  width: 64px;
  padding: 14px 10px;
  overflow: hidden;
  border: 0;
  border-right: 1px solid var(--line);
  border-radius: 0;
  background: var(--papel);
  box-shadow: none;
  transition: width .2s ease;
}
.module-sidebar.is-expanded {
  width: 236px;
}
/* O recuo do conteúdo acompanha a barra PRESA, e só ela.
   A barra é `position: fixed` — ela não empurra nada, ela cobre. O recuo de
   96px foi calculado para o trilho fechado (64 + 32 de folga) e nunca
   acompanhou os 236 do aberto: com a barra presa, 140px da tela ficavam
   embaixo dela, e numa tabela isso come a primeira coluna inteira.
   Presa e não aberta: a barra também abre ao passar o mouse, e nesse estado ela
   é passageira — empurrar o conteúdo a cada passada faria a página pular sob o
   cursor. Quem abriu por engano não deveria ver a tela inteira andar.
   `min-width` porque abaixo de 800px a barra vira gaveta e a conta é outra. */
@media (min-width: 1080px) {
  .app-shell { transition: padding-left .2s ease; }
  body.barra-presa .app-shell { padding-left: 268px; }
}
.module-sidebar-toggle {
  height: 34px;
  display: grid;
  place-items: center;
  border: 0;
  border-radius: var(--radius-md);
  color: var(--muted);
  background: transparent;
  width: 42px;
  margin: 0 auto 14px;
}
.module-tabs { margin-top: 0; gap: 2px; }
.module-tab {
  place-content: center;
  border: 0;
  background: transparent;
  font-weight: 760;
  cursor: pointer;
  transition: background .2s ease, color .2s ease, box-shadow .2s ease, transform .2s ease;
  /* Item da barra é alvo, e não frase: o sublinhado o fazia parecer link
  de texto no meio de uma coluna de ícones. */
  text-decoration: none;
  width: 100%;
  display: flex;
  align-items: center;
  text-align: left;
  min-height: 46px;
  padding: 9px 10px;
  justify-content: center;
  gap: 11px;
  border-radius: var(--radius-md);
  color: var(--muted);
  font-size: 0;
  white-space: nowrap;
}
.module-tab-glyph {
  width: 21px;
  height: 21px;
  flex: 0 0 21px;
  color: currentColor;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.3;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.module-tab:hover {
  color: var(--text);
  background: var(--sobrevoo);
}
.module-tab.active, .module-tab[aria-selected="true"] {
  /* ⚠ Medido: esta aba computa `rgb(223,235,242)` no claro e `rgb(14,38,73)`
     no escuro — o `--acento-lavado`, posto pelas regras de baixo. O `#f8fbff`
     nunca chega à tela;
  escrevê-lo com o nome que já vence alinha o perdedor
     com o vencedor sem mudar um pixel (a fusão é da A3). */
  background: var(--acento-lavado);
  color: var(--texto);
  background: var(--light-blue);
  box-shadow: none;
}
.module-tab-kicker {
  color: var(--accent);
  font-size: .67rem;
  font-weight: 850;
  letter-spacing: .11em;
  text-transform: uppercase;
  display: none !important;
}
.module-sidebar:not(.is-expanded) .module-tab { gap: 0; }
.module-sidebar.is-expanded .module-tab {
  justify-content: flex-start;
  font-size: .8rem;
  font-weight: 650;
  gap: 11px;
}
.module-sidebar.is-expanded .module-tab::after {
  overflow: hidden;
  color: var(--text);
  font-size: .78rem;
  font-weight: 650;
  text-overflow: ellipsis;
  white-space: nowrap;
  content: none;
}

/* Breadcrumbs discretos, persistentes no topo das telas. */
.page-heading {
  justify-content: flex-end;
  gap: 24px;
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
  align-items: center;
  margin-bottom: 18px;
}

/* Indicador de lote compacto: acompanha o breadcrumb sem criar uma faixa vazia. */
.page-heading .batch-count {
  min-width: 0;
  padding: 0;
  display: inline-flex;
  align-items: baseline;
  grid-column: 3;
  grid-row: 1;
  justify-self: end;
  gap: 5px;
  border: 0;
  border-radius: 0;
  background: transparent;
  box-shadow: none;
  white-space: nowrap;
}
.page-heading .batch-count strong { color: var(--text); font-size: .82rem; letter-spacing: 0; }
.page-heading .batch-count span { color: var(--muted); font-size: .75rem; }
.page-heading .batch-count.batch-count-with-model-lock { grid-column: 2; justify-self: center; }
.page-heading .page-heading-settings-access,
.page-heading .page-heading-model-access,
.page-heading .page-heading-pipeline-access {
  grid-column: 3;
  grid-row: 1;
  justify-self: end;
}
@media (max-width: 800px) {
  .page-heading { grid-template-columns: 1fr; gap: 10px; }
  .page-heading .batch-count { grid-column: 1; grid-row: auto; justify-self: end; }
  .page-heading .batch-count.batch-count-with-model-lock { grid-column: 1; justify-self: center; }
  .page-heading .page-heading-settings-access,
  .page-heading .page-heading-model-access,
  .page-heading .page-heading-pipeline-access { grid-column: 1; grid-row: auto; justify-self: start; }
}
#statsReprocessTab { display: none; }

@media (max-width: 1079px) {
  .module-sidebar.is-expanded { width: 100%; }
  .module-tab {
    min-height: 54px;
    justify-content: center;
    color: var(--text);
    font-size: .7rem;
    text-align: center;
  }
}
.expected-data-sidebar .field-group:first-child { margin-top: 0; }
#bookRegistryTermsTable { table-layout: fixed; }
#bookRegistryTermsTable th:nth-child(1),
#bookRegistryTermsTable td:nth-child(1) { width: 92px; }
#bookRegistryTermsTable th:nth-child(2),
#bookRegistryTermsTable td:nth-child(2) { width: 128px; }

@media (max-width: 900px) {
  .review-workbench-grid { grid-template-columns: 1fr; }
}

@media (max-width: 640px) {
  .pipeline-dashboard-card, .pipeline-builder, .pipeline-review-workbench,
  .review-workbench-grid, .review-result-pane, .review-image-pane { min-width: 0; max-width: 100%; }
  .pipeline-builder-footer .button { width: 100%; }
  .review-image-frame { min-height: 220px; }
  .review-data-list { grid-template-columns: 1fr; gap: 4px; }
  .review-data-list dd { margin-bottom: 8px; }
  .compact-datatable { max-width: 100%; overflow-x: auto; }
}

@media (max-width: 900px) {
  .ext3-phase-row .field-note { grid-column: 1 / -1; }
}

/* Final mobile navigation overrides (kept last so legacy responsive rules
   cannot turn the Feather sidebar back into horizontal tabs). */
@media (max-width: 1079px) {
  .app-shell {
    grid-template-columns: 1fr;
    gap: 14px;
    margin-inline: auto;
    width: 100%;
    max-width: none;
    margin: 0;
    padding: 18px 10px 42px;
    display: block;
  }
  .app-content, .tab-panel, .converter-flow, .workspace-grid, .flow-card {
    min-width: 0;
    max-width: 100%;
  }
  .module-sidebar {
    position: fixed;
    inset: 60px auto 0 0;
    z-index: 100;
    width: min(84vw, 282px);
    height: calc(100vh - 60px);
    padding: 16px 12px 24px;
    overflow-y: auto;
    border: 0;
    border-right: 1px solid var(--line);
    border-radius: 0;
    background: var(--papel);
    box-shadow: none;
    transform: translateX(-105%);
    transition: transform .22s ease;
  }
  .module-sidebar.mobile-open {
    width: min(84vw, 282px);
    transform: translateX(0);
  }
  .module-sidebar-toggle {
    display: none;
  }
  .module-tabs {
    margin-top: 0;
    width: 100%;
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: 6px;
  }
  .module-tab, .module-sidebar.is-expanded .module-tab {
    min-height: 48px;
    width: 100%;
    justify-content: flex-start;
    gap: 12px;
    padding: 10px 12px;
    border-radius: 9px;
    color: var(--text);
    font-size: .86rem;
    font-weight: 650;
    text-align: left;
  }
  .module-tab-glyph {
    display: block;
    width: 21px;
    height: 21px;
    flex: 0 0 21px;
  }
  .module-tab-kicker {
    font-size: .54rem;
    display: none !important;
  }
  .module-sidebar.is-expanded .module-tab::after {
    content: none;
  }
  .module-tab:hover {
    color: var(--text);
    background: var(--sobrevoo);
  }
  .module-tab.active, .module-tab[aria-selected="true"] {
    color: var(--texto);
    background: var(--light-blue);
    box-shadow: none;
  }
  .page-heading {
    grid-template-columns: minmax(0, 1fr);
    gap: 10px;
    align-items: start;
  }
  .page-heading .batch-count {
    grid-column: 1;
    justify-self: center;
  }
  .page-heading .page-heading-settings-access, .page-heading .page-heading-model-access, .page-heading .page-heading-pipeline-access {
    grid-column: 1;
    justify-self: start;
  }
  .submission-row .button, .submission-row .icon-lock-button {
    width: 100%;
  }
  .responsive-table {
    max-width: 100%;
    overflow-x: auto;
  }
  img, canvas, video {
    max-width: 100%;
  }
}

@media (max-width: 420px) {
  .brand-row {
    gap: 6px;
  }
  .mobile-nav-toggle, .logout-button {
    width: 38px;
    flex-basis: 38px;
  }
  .logo {
    max-height: 36px;
  }
  .app-shell {
    padding-inline: 8px;
  }
}

/* O DDI e o número, do desenho: 9px entre os dois, o alvo com 49px de altura
   e 11px de folga lateral, bandeira redonda de 21px. */
.ddi-par { display: flex; gap: 9px }
.ddi-alvo {
  position: relative; display: flex; align-items: center; gap: 7px; flex: none;
  min-height: 49px; padding: 0 11px; border: 1px solid var(--line);
  border-radius: 12px; background: var(--papel); cursor: pointer;
  font-size: .92rem;
}
/* O `<select>` de verdade fica por cima, invisível: quem clica em qualquer
   ponto do alvo abre a lista do sistema — no celular, a roda; no computador, a
   busca por digitação que o navegador já tem. Desenhar a nossa lista seria
   refazer pior o que o aparelho faz melhor. */
.ddi-alvo select {
  position: absolute; inset: 0; width: 100%; height: 100%;
  opacity: 0; border: 0; cursor: pointer; font-size: 16px;
}
.ddi-par input { flex: 1 1 auto; min-width: 0 }
/* A ajuda embaixo do campo. A força extra é contra `.login-field > span`, que
   é o RÓTULO — .78rem e peso 750 — e vem antes: sem ela, a frase de ajuda saía
   com o mesmo peso do rótulo e as duas competiam. */
.login-field > span.login-nota { font-size: .72rem; font-weight: 400; color: var(--muted) }

/* O quadrado do ícone: 42px, raio 11px, fundo azul claro. É o que separa uma
   tela da outra num conjunto em que todas são um cartão com campos. */
/* 44/12 e o desenho a 22, que é o que a prancha mede. Era 42/11 e 20.
   ⚠️ E o traço passou de `--accent` (ciano) para `--texto`. A prancha desenha
   `--marinho`, mas ela é do modo claro e dá metade do par: o marinho não
   inverte. É o mesmo caso do título desta tela — geometria do desenho, cor da
   regra —, e `--texto` é o que as outras telas usam desde a errata da §2.1.

   ⚠️ Medido no `stroke` e não no `color`: `color` não pinta um `svg`. A
   primeira medição desta peça leu `color` e devolveu o `--tinta-600` herdado,
   que não pinta nada — a diferença real era maior do que a que eu reportei. */
.conta-icone {
  width: 44px; height: 44px; border-radius: 12px; display: grid; place-items: center;
  background: var(--light-blue); margin-bottom: 16px;
}
.conta-icone svg { width: 22px; height: 22px; fill: none; stroke: var(--texto); stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round }
/* ⚠ A2 · o par do aviso. O chão cravado media 16,88 contra o papel ESCURO —
   um quadrado amarelo-claro de 44px numa tela escura —, e o traço 4,51 num
   chão que só existia no claro. Agora 5,23/4,96 traço sobre chão. */
.conta-icone.aviso { background: var(--aviso-lavado) }
.conta-icone.aviso svg { stroke: var(--aviso-tinta) }
