/* ─────────────────────────────────────────────────────────────────────────────
   Tokens e base.  (L-44)

   Vindos do protótipo `l01-pencil.html`, validados no iPad e no Mac nos
   Blocos A e B — não reinventados aqui. As duas decisões que mais importam:

   1. A medida da coluna é em **em**, não em rem. A coluna cresce junto com a
      fonte, e o número de caracteres por linha fica estável em qualquer
      tamanho — foi o achado da rodada 1 da L-03, no iPad.
   2. As cores de destaque têm variante por tema, calibradas para o texto
      seguir acima de 4.5:1 **por cima do destaque** (03-destaques §5.1).
   ───────────────────────────────────────────────────────────────────────── */

/* ── fontes ───────────────────────────────────────────────────────────────
   Os três `@font-face` e os tokens de família subiram ao núcleo (Task 9,
   Scriptorium). O que fica aqui é só o vocabulário de destino: os blocos
   `[data-fonte=…]` abaixo apontam para `--serif`, `--serif-leitura` e
   `--sans`, que o `nucleo.css` declara.
   ───────────────────────────────────────────────────────────────────────── */

:root {
  --size-base: clamp(1.125rem, 1.02rem + 0.5vw, 1.345rem);
  --size: calc(var(--size-base) + var(--tamanho, 0) * 0.0625rem);
  --leading: 1.6;
  /* Espaço entre a coluna e a beirada da folha. Mora no `:root` desde a
     L-74: o `main` também precisa dele para reservar a margem da marginália. */
  --respiro: clamp(1.5rem, 5vw, 4rem);
  /* A medida virou DERIVADA com o espaçamento para dislexia (Bloco J2): a
     largura que o leitor escolhe entra em `--medida-base`, e `--fator-espaco`
     multiplica. Os dois se separaram porque a compensação de medida precisa
     valer para as TRÊS larguras, e não só para a padrão — a conta está na
     nota de `[data-espacamento]`, abaixo. Com o fator em 1, que é o padrão,
     o valor computado continua sendo o mesmo `34.5em` de sempre. */
  --medida-base: 34.5em;
  --measure: calc(var(--medida-base) * var(--fator-espaco, 1));
  --space-para: 0.9em;
  --space-block: 2.2em;

  /* Charter (spec 50 §3.6): do sistema da Apple, zero byte no casco. A pilha
     cai em serifas de desenho parecido onde ela não existe. */
  --serif-charter: Charter, "Bitstream Charter", "Sitka Text", Cambria, serif;

  /* ── Duas famílias de cor, e a distinção é o conserto da L-51b ───────────
     `--hl-*` é a cor de **marcação**: ela entra POR BAIXO DO TEXTO, e por isso
     muda com o tema (03 §5.1). `--vivo-*` é a cor de **amostra**: aparece em
     botão e em bolinha, sobre fundo de cromo, e não muda nunca — a amostra
     precisa ser reconhecível como "a azul", e uma azul escurecida para o tema
     escuro deixaria de ser. */
  /* 2026-08-21 — os quatro descem meio tom para o registro do pigmento:
     ouro-ouropigmento, verdete, laca de quermes, azurita. É a mesma família
     de matiz de sempre, com menos croma de papelaria e mais de manuscrito.

     **O NOME é contrato de dado, e por isso a matiz se move dentro da
     família em vez de trocar de família.** `roxo`, `amarelo`, `rosa` e
     `azul` são valores PERSISTIDOS: a API os valida
     (`api/leitor-api/lib/destaques.mjs`, `CORES` e as duas mensagens
     `cor-invalida`), grava `cor` com eles em cada destaque, e `corPadrao`
     das preferências guarda um deles (`lib/prefs.mjs`). Um `--hl-azul`
     violeta seria um nome mentindo sobre a cor; mudar o nome exigiria
     migrar destaque já gravado. Então a azurita continua azul, e a laca de
     quermes continua rosa.

     ── O roxo entrou e o verde saiu (2026-08-21) ─────────────────────────
     O roxo é a cor PADRÃO agora — `motor.mjs` declara `CORES` e
     `artigo.mjs` faz `corAtiva = CORES[0]`, então a primeira posição é o
     mecanismo inteiro; não há preferência gravada por trás.

     **Tirar o verde não custou migração, e isso foi medido, não suposto:**
     dos 158 destaques gravados, 156 são amarelo e 2 são rosa — verde e
     azul, zero. Nenhum destaque ficou órfão de token. Se algum verde
     existisse, ele cairia num `var(--hl-verde)` sem valor e apareceria
     sem marcação nenhuma; como não existe, o custo é zero. O azul ficou
     mesmo sem uso porque carrega o rótulo "Estrutural", que é o que
     conversa com a lente do arquiteto (03 §5.1).

     O roxo do escuro (`#42305c`) é o par mais apertado do arquivo, e a
     razão é nova: no tema escuro o ACENTO também é púrpura (`#c19ae6`), e
     `.prosa a` é destacável — um link roxo pode nascer por cima de uma
     marcação roxa. Medido em 4,99:1, dentro da faixa dos outros três
     (4,87–4,90). */
  --hl-roxo:    #d3bbe8;  --hl-amarelo: #eed88a;
  --hl-rosa:    #eeaebd;  --hl-azul:    #a6c3e4;

  --vivo-roxo:    #d3bbe8;  --vivo-amarelo: #eed88a;
  --vivo-rosa:    #eeaebd;  --vivo-azul:    #a6c3e4;

  /* `--raio` e `--raio-p` subiram ao núcleo (Task 9) com os mesmos valores —
     12px e 8px. A nuance de que dentro do texto não há superfície para
     arredondar (02 §9; o `4px` da imagem e do bloco de código não usa estes
     tokens de propósito) continua valendo, só que o token agora vem de fora. */

  /* ── A matiz de cada TEMA  (spec 73 §5.1 e §5.9) ─────────────────────────
     Terceira família de cor deste arquivo, e a distinção contra as outras
     duas é a mesma de sempre — **camada e função**:

     | família | onde vive | muda com o tema visual? |
     |---|---|---|
     | `--hl-*`   | POR BAIXO do texto do artigo | sim, obrigatoriamente |
     | `--vivo-*` | amostra em botão e bolinha   | nunca |
     | `--t-*`    | identidade de um dos cinco temas | só de valor, nunca de matiz |

     Desde a spec 73 os temas são CINCO e fixos, iguais em toda conta, e o
     token leva o slug do tema: `--t-${slug}`, sem tabela no meio. Quem liga
     um slug (ou um alias velho, como `canone`) ao token é
     `assets/matizes.mjs`; declarar o token aqui não põe cor em lugar nenhum —
     quem aplica é o `--t` inline do elemento.

     Duas regras governam os valores, e as duas são medidas em graus:
     1. **O acento tem matiz exclusiva.** Nenhum tema fica a menos de ~50° da
        brasa (17,4°, a mesma nos três temas visuais) — se um tema ocupasse a
        matiz da marca, o chip ativo e o app diriam a mesma coisa em lugares
        diferentes. O teste «nenhum tema ocupa a matiz do acento»
        (`artigo.test.mjs`) mede isso.
     2. **Nome pela coisa, nunca pelo papel.** `--t-literatura`, e não `--t-1`.

     Os valores são os da rodada da brasa (01/09, Claude Design, «Leitor —
     rodada 1», prancha 1a), e a spec 73 só trocou os NOMES — nenhuma medida
     de contraste precisou ser refeita:
     - Literatura — bordô magenta `#83306b` (317°), a 59,9° da brasa, o par
       mais apertado do conjunto e ainda acima do mínimo de 50°;
     - Fé e Filosofia — azul-noite `#33538f` (219°), a matiz que foi do acento
       antes de a brasa chegar;
     - História e Sociedade — oliva `#5c6b52` (96°);
     - Ciência e Tecnologia — petróleo `#2f6d63` (170°);
     - Artes e Vida — ameixa `#6b4a8c` (270°).

     Medido, nos TRÊS temas visuais, contra a brasa:
       ciência 153,0° · fé 158,2° · artes 107,3° · literatura 59,9° · história 78,7°
     Menor vão entre temas: 47,3° (artes × literatura). */
  --t-ciencia-tecnologia: #2f6d63;  --t-artes-vida:         #6b4a8c;
  --t-fe-filosofia:       #33538f;  --t-literatura:         #83306b;
  --t-historia-sociedade: #5c6b52;

  /* ── A LOMBADA da estante: a mesma matiz, no registro de tinta  (02/09) ───
     A estante deixou de ser uma grade de capas em campo cheio e passou a ser
     a lombada de pé numa prateleira — e a capa virou detalhe de foco, uma por
     tela, na coluna da direita. A lombada é a cor do OBJETO: o mesmo livro na
     prateleira, na grade, na capa grande da coluna e na mesa do frontispício.

     Cinco tintas fundas (L~20%, croma baixo) nas MESMAS matizes dos `--t-*`
     claros acima: magenta 317°, petróleo 170°, ameixa 270°, azul-noite 219°,
     oliva 96°. Elas moram no `:root` e não num bloco de tema: um livro na
     prateleira não muda de cor quando se apaga a luz da sala.

     Medido, texto sobre as cinco: título `--sobre-lombada` dá 9,88–11,33:1; o
     autor, que é o mesmo branco esmaecido, foi de 60% para **65%** porque a
     60% o pior caso (petróleo) media 4,67:1 — passava o piso de 4.5 e raspava
     a mira de 4.7 da casa. A 65% o pior caso é 5,15:1. Texto miúdo não afrouxa
     piso por ser miúdo; ele sobe a opacidade.

     Obra sem tema não tem `--lombada` no elemento, e as regras que a consomem
     caem direto no cinza `--tenue` (`var(--lombada, var(--tenue))`): a capa
     sem tema é cinza, e não transparente.

     `--sobre-lombada` é cravado e não vem de `--sobre-acento`: é o papel da
     lombada, e tem de ser o MESMO sobre as cinco matizes — a mesma razão que o
     `#fdf6ef` da capa cega já registra adiante. */
  --lombada-literatura: #4a2038;         --lombada-ciencia-tecnologia: #1f3d38;
  --lombada-artes-vida: #3a2a4c;         --lombada-fe-filosofia:       #23304a;
  --lombada-historia-sociedade: #333a2c;
  --sobre-lombada: #f2eae0;

  /* A sombra da lombada é PRÓPRIA, e não `--sombra-erguida`: aquela é de
     objeto pairando sobre a mesa (dois degraus, deslocamento negativo em X
     pela `--luz-x`), e um livro apoiado na tábua não paira — ele encosta. Y
     positivo, luz alta, uma camada só. */
  --sombra-lombada: 3px 8px 16px rgba(34,33,29,.26);

  /* A tábua da prateleira. Não é `--papel-elev-*`: aquilo é papel, e isto é
     madeira vista de canto — 9px de altura, o brilho de cima e a sombra
     projetada logo abaixo. Vive no `:root` pela mesma razão das lombadas. */
  --tabua-1: #d3cabb; --tabua-2: #b6ab97;
  /* ── A tábua MUDA por tema, e a lombada não  (visto na captura de 02/09) ──
     Parece contradizer a regra do parágrafo acima, e não contradiz — separa
     duas coisas que a palavra «objeto» juntava. O LIVRO é objeto: a série tem
     de ser reconhecível, e um livro não muda de cor quando se apaga a luz da
     sala. A tábua é o MÓVEL, e móvel em sala escura está na penumbra.

     Sem isto, no tema escuro a prateleira vira a coisa mais clara da tela —
     mais clara que os livros que ela sustenta —, e o olho vai para o suporte
     em vez de ir para o acervo. Foi o que a captura mostrou, e não havia
     medição que pegasse: contraste de superfície contra superfície não tem
     piso, tem juízo. */

  /* ── `--perigo`: quinta família de cor, e a razão de nascer é a revisão
     final medindo `#d1495b` cravado em nove lugares, 3,38–4,29:1 contra o
     fundo real — hex fixo é invisível para o harness de contraste, que lê
     TOKEN, não literal (`contraste.mjs:tokens`), então nada aqui tinha
     como reprovar sozinho antes de chegar ao aparelho.

     Claro e sépia dividem o mesmo valor — `--papel-elev` e `--regra` dos
     dois temas são vizinhos de arredondamento (mesma razão do núcleo ter
     unificado os dois), então a mesma cor passa nos dois com a mesma
     folga. Escurecido de `#d1495b` (L 55,3%) para `#b42e3f` (L 44,3%),
     mesmo hue/saturação — é vermelho mais fundo, não vermelho diferente.
     Isso resolve as quatro superfícies de TEXTO onde a revisão media
     abaixo de 4.5:1 (`#acoes .perigo` sobre `--papel-elev`: 4,29→6,07:1;
     `.redondo.excluir:hover` idem; `.aviso-excluir`, texto corrido, idem;
     `.destaque .x:hover` sobre `--regra`: 3,37→4,77:1) e a pior das duas
     superfícies "armadas", onde o texto some sobre o próprio fundo tingido
     de si mesmo (`.redondo.excluir.armado`: 3,58→4,88:1). Mirado ≥4.7:1 em
     toda superfície, não 4.5 raspado — a mesma folga que o núcleo já usa
     nos ajustes de `--tenue`.

     As duas superfícies que são só MARCA (o tingido de fundo de `.armada`/
     `.armado`, 14–16% de mix sobre `--papel-elev`) não têm piso próprio —
     não são a única pista de nada, o texto e a borda ao lado já carregam
     a informação — e viram token pela mesma razão de qualquer literal:
     consistência de tema, não uma medição que precisavam passar.

     2026-08-21 — o acento entrou no vermelho, e `--perigo` teve de se
     afastar. **A separação não é de matiz — é de profundidade e croma**,
     e a escolha foi forçada pela aritmética: `#b42e3f` já media 4,708:1
     no pior caso (`.destaque .x:hover` sobre `--regra`), ou seja, já
     estava no TETO de claridade que o piso de 4.5 permite. Clarear não
     era uma opção disponível; o que sobrava era croma.

     `#b81028` mantém a mesma profundidade e sobe a saturação de 59% para
     84% (croma 168 contra os 112 do acento). Contra o oxblood do acento
     — que é fundo, apagado e lido como TINTA — este é claro, quente e
     lido como ALARME. Os dois vizinhos de matiz, separados por tudo o
     mais.

     Efeito colateral, e favorável: toda medição do teste SOBE.
     `--papel-elev` 6,07→6,58:1 · `--regra` 4,77→5,17:1 · armado 14%
     4,71→5,14:1 · armada 16% 4,71→4,95:1. O pior caso saiu de raspar o
     piso (4,708) para 4,95. */
  --perigo: #b81028;
}

[data-entrelinha="compacta"] { --leading: 1.45; }
[data-entrelinha="normal"]   { --leading: 1.6; }
[data-entrelinha="arejada"]  { --leading: 1.75; }
[data-largura="estreita"] { --medida-base: 31em; }
[data-largura="media"]    { --medida-base: 34.5em; }
[data-largura="larga"]    { --medida-base: 38em; }
[data-fonte="literata"]     { --corpo: var(--serif); }
[data-fonte="source-serif"] { --corpo: var(--serif-leitura); }
[data-fonte="inter"]        { --corpo: var(--sans); }
[data-fonte="charter"]      { --corpo: var(--serif-charter); }

/* ── Espaçamento para dislexia  (Bloco J2, `data-espacamento`) ──────────────
   Zorzi et al., PNAS 2012: espaço extra entre as letras deu ~20% mais
   velocidade de leitura e METADE dos erros em crianças disléxicas — sem
   treino nenhum, só a tipografia mudando debaixo do mesmo texto. É o único
   ajuste deste arquivo com efeito medido em ensaio clínico, e é exatamente
   por isso que ele entra como OPÇÃO e não como padrão: o mesmo trabalho não
   achou ganho em leitor típico, e `normal` tem de continuar sendo byte a byte
   a tipografia que o Bloco B validou no iPad. Ajuste que ajuda um grupo e
   custa a todos os outros não vira padrão; vira interruptor.

   ── Os dois andam JUNTOS, e é aqui que se erra ─────────────────────────────
   Subir `letter-spacing` sozinho PIORA a leitura, e a razão é estrutural: as
   letras de duas palavras vizinhas passam a ficar tão distantes entre si
   quanto as letras de dentro de uma palavra, e a fronteira de palavra — que é
   o que o olho usa para segmentar a linha — deixa de existir. O que o ensaio
   mediu foi espaço extra COM a palavra ainda coesa. Daí `word-spacing` crescer
   3× o `letter-spacing`, e não o mesmo tanto: manter a razão entre os dois é o
   ganho; igualá-la seria trocar um problema de leitura por outro.

   ── A medida da coluna é compensada, e a conta está aqui ────────────────────
   A 02 §2.3 fixa 62–72 caracteres por linha, e o protótipo mediu o avanço
   médio do caractere em **0,486em** (é o que dá as três larguras declaradas
   acima: 31em≈65ch, 34.5em≈71ch, 38em≈78ch). Espaçar sem mexer na medida
   encolheria a linha em ~16% de caracteres — 71 viraria 60, ABAIXO do piso —,
   e o ajuste que existe para facilitar a leitura cobraria de volta em salto de
   linha o que deu em legibilidade de letra.

   O avanço por caractere com o espaçamento ligado:

     0,486em (base)
     + 0,06em            (letter-spacing, que incide em todo caractere)
     + 0,18em ÷ 5,96     (word-spacing, diluído pela palavra do português:
                          4,96 letras + 1 espaço = 5,96 caracteres — contado
                          em 2.990 palavras de prosa da própria spec, não
                          estimado)
     = 0,576em           →  fator 1,19

   `--fator-espaco` multiplica `--medida-base`, então a compensação alcança as
   três larguras sem repetir número nenhum, e uma quarta largura que nasça
   amanhã já nasce compensada. É a diferença entre um invariante e três
   constantes que por acaso combinam hoje. */
[data-espacamento="arejado"] { --fator-espaco: 1.19; }
[data-espacamento="arejado"] .prosa { letter-spacing: .06em; word-spacing: .18em; }
/* O bloco de código é a exceção, e não por gosto: dentro de `<pre>` o
   alinhamento de coluna carrega informação (saída de terminal, diff, tabela
   ASCII), e `word-spacing` desalinha tudo o que tem mais de um espaço seguido.
   `<code>` inline fica espaçado junto com a frase em que vive — ali não há
   coluna a preservar, e destoar do texto ao redor é que seria o defeito. */
[data-espacamento="arejado"] .prosa pre { letter-spacing: normal; word-spacing: normal; }

/* ── O acento é RUBRICA · CARMESIM · PÚRPURA  (02 §3, direção Câmara) ───────
   2026-08-21 — o azul-noite saiu. Ele fora fechado em 2026-08-02 contra
   índigo, ametista e verde-petróleo; a ametista `#6a3f86`/`#c294dd` que
   aquela rodada rejeitou é, com dois pontos de diferença, o que hoje veste o
   tema escuro. Os rejeitados de então ficam registrados, agora como
   histórico e não como alternativa viva: índigo `#3f3d8f`/`#9a97e0`,
   petróleo `#2f6d63`/`#6fb3a5`, azul-noite `#26436e`/`#8fb3dd`.

   A cor nova é a do ofício que dá nome à fundação (ver a nota de paleta em
   `nucleo.css`): a **rubrica** do escriba no claro, o **carmesim** de
   quermes no sépia, a **púrpura** do codex purpureus no escuro. O valor é o
   mesmo de `--foco` do núcleo nos três temas — dois tokens, um valor,
   porque no Leitor o anel de foco e o acento do app são a mesma cor da casa
   e sempre foram (antes disto eram `#2b4c85` e `#26436e`, vizinhos de
   arredondamento fingindo ser dois).

   **O acento não colide com o rosa de destaque**, e a razão não é a matiz —
   as duas são avermelhadas. É a função e a saturação: o destaque é um
   pigmento dessaturado que vive POR BAIXO do texto; o acento é um tom fundo
   e saturado que vive no cromo. Nunca aparecem na mesma camada — e há teste
   que mede `--acento` sobre os quatro `--hl-*` justamente porque `.prosa a`
   pode receber marcação por baixo (medido: 4,96–6,43:1 no claro).

   A tensão papel quente × acento fundo continua deliberada: é ela que faz o
   acento parecer tinta sobre papel em vez de interface colorida.

   **`--sobre-acento` não é cosmético — é conserto de defeito.** O botão
   primário escrevia `#fff` sobre `var(--acento)`, e no tema escuro o acento é
   **claro**: dava ~2:1. O token existe para que ninguém volte a assumir
   branco, e há teste que falha se alguém voltar.

   **`--tenue` é informação, não decoração**: ele carrega a linha de crédito
   do item (fonte · minutos · data) e o rótulo da barra de navegação. Por isso
   responde ao 4.5:1 como qualquer outro texto — contra ~6.8:1 do `--tinta-2`.
   Um terceiro cinza "decorativo" a 3:1 é o defeito que a primeira versão dos
   mockups tinha.

   **O valor do escuro diverge do mockup, e a divergência é medida.** Lá o
   `--tenue` era `#83807b`, verificado contra `--papel` — e passava, com 4.56:1.
   Mas neste app ele mora **dentro do cartão**, sobre `--papel-elev`, que no tema
   escuro é MAIS CLARO que o papel: ali o mesmo valor caía para **4.19:1**. O
   mockup não pegou porque a tela onde o crédito do item aparece é a única em
   que o fundo dele não é `--papel`. Corrigido para `#8b8883` (bg 5.08:1, elev
   4.67:1), e há teste que confere as duas superfícies. */
/* ── O acompanhamento da voz saiu do `--acento`  (2026-08-26) ───────────────
   Até aqui as duas regras de `::highlight()` — a faixa da frase e a palavra
   corrente, lá embaixo — pintavam com `var(--acento)`. O empréstimo passou
   despercebido por meses porque o acento era vermelho no claro e no sépia
   enquanto o pigmento padrão do marca-texto é roxo: duas famílias de matiz,
   nenhuma colisão possível. Em 21/08 o acento do escuro virou púrpura, e o
   acompanhamento foi junto — **três coisas na mesma família** naquele tema
   (destaque `#42305c`, faixa de parágrafo e palavra), sem pista de cor para
   separá-las.

   O que fecha a questão é que **contraste nunca foi a pergunta ali**. Púrpura
   clara sobre púrpura escura mede 4,9:1 — passa todos os pisos deste arquivo,
   com folga, e ainda assim confunde. O que colidiu foi a MATIZ, e nenhum
   teste media matiz entre estas duas famílias. Por isso o conserto tem duas
   metades: os tokens abaixo, e um guarda de matiz em `bimodal-css.test.mjs`.

   `--acento` é cor de CROMO — link, botão primário, chip ativo, aba corrente,
   anel de foco, 65 usos neste arquivo. O acompanhamento é cor da CAMADA DE
   LEITURA, e divide superfície com o marca-texto. São perguntas diferentes, e
   um token só não podia responder às duas sem que a resposta de uma amarrasse
   a outra: mexer no acompanhamento do escuro exigiria repintar o app inteiro.

   ── Quem é âncora e quem carrega a identidade do tema ─────────────────────
   A divisão de papéis foi decidida junto, e ela é o que impede a colisão de
   voltar sob outro nome: **o marca-texto é a âncora** — fica na família
   amarela nos três temas, com o valor por tema que ele já tinha
   (`#eed88a` · `#ecd07a` · `#463911`, hue 45–47°, ver `--hl-amarelo`) — e **o
   acompanhamento é o que muda**, uma cor por tema. O padrão voltou a ser o
   amarelo em `motor.mjs` (`CORES[0]`) pela mesma decisão; a nota de lá conta o
   resto.

   ── A voz é ACROMÁTICA, e isso foi validado no olho, não deduzido ──────────
   As três cores foram escolhidas por Yuri numa página de amostras que punha
   nove candidatas sobre o papel de cada tema, com os três níveis na mesma
   frase (`C02 Claude/Output/2026-08-26 — Leitor — acompanhamento de
   leitura`). Havia saturadas na mesa em todos os temas — carmesim, verdete,
   azul-noite —, e as três escolhidas são **neutras**. Vale escrever a regra
   que saiu daí, porque ela é melhor do que a que entrou:

   **A camada de leitura tem uma cor só, e ela é do marca-texto.** O amarelo é
   o único pigmento saturado que a página recebe; a voz passando é um VÉU
   acromático. Isso dá ao olho um critério que não depende de comparar matiz —
   o que tem cor é decisão que fica, o que é cinza é a voz que passa —, e é
   uma distinção mais forte do que "amarelo contra verde", porque sobrevive a
   quem enxerga cor de outro jeito.

   O corolário derrubou a primeira escolha desta rodada, e fica registrado: com
   a âncora amarela, **o acompanhamento não podia ser dourado**. O ouro de
   iluminura `#d8b25a` (hue 41,9°) foi escolhido enquanto a âncora ainda era o
   roxo, e mede 3,4° do ocre `#463911` do escuro — a mesma colisão de hoje,
   trocada de família. Caiu antes de existir.

   Um valor por tema. São três cinzas, e cada um pende para um lado diferente:
   · claro  `#454a52` — ardósia de lápide, 8,41:1 contra o papel, croma 5%.
     Pende para o frio sobre papel quente. Aqui o acento (a rubrica `#8c1c22`)
     já é o vermelho da casa: uma segunda cor saturada brigaria com ele.
   · sépia  `#4a3f52` — ardósia arroxeada, 8,18:1, croma 7,5%. É o cinza que
     pende para a púrpura, e sobre papel rosa-velho ele lê como sombra do
     próprio papel. O carmesim `#8e1233` estava na mesa e foi visto lado a
     lado: perdeu por ser um segundo vermelho numa página que já tem o acento
     em carmesim.
   · escuro `#b0aca2` — cinza-osso, 7,91:1, croma 5,5%. O único que pende para
     o quente, e sobre papel frio é isso que o separa. Atenção para quem for
     medir: a matiz nominal dele é 43°, a **2,4° do ocre** do marca-texto — a
     separação aqui não é de matiz, é de CROMA (5,5% contra 21%) e de valor. O
     guarda em `bimodal-css.test.mjs` sabe disso e mede as duas coisas.

   ── `--leitura-forca`, e a outra metade do "difícil diferenciar" ───────────
   A faixa da frase é a cor da palavra enfraquecida, e a força era **12%
   cravada nos três temas**. Sobre `#16171a` isso dá 1,25:1 de uma cor clara
   sobre fundo quase preto — piso de 1,2:1 raspado, véu nenhum. Era a parte do
   defeito que não tinha nada a ver com matiz: no escuro a faixa mal existia, e
   o que sobrava para o olho eram duas coisas roxas em vez de três níveis.
   **20%** devolve 1,46:1 ali.

   Os temas claros também subiram, e por uma razão que só apareceu ao medir as
   cores escolhidas: com os cinzas, 12% valia 1,209:1 no claro e **1,205:1 no
   sépia** — acima do piso pelo terceiro decimal, que neste projeto conta como
   reprovado (a mesma régua que reprovou o `--tenue` do núcleo por 0,22% de
   margem). **14%** devolve 1,245:1 e 1,253:1, sem tocar em cor nenhuma: a
   folga se compra na força, que é o parâmetro que não foi validado no olho.
   O vermelho antigo tinha 1,232:1 no claro e não sofria disso — cinza a igual
   alpha rende menos contraste que pigmento, e é a conta que a troca de paleta
   trouxe junto.

   Nada disto é novo neste arquivo: `--hl-fantasma` faz o movimento idêntico e
   pela mesma razão (22% no claro e no sépia, 48% no escuro — ver a nota dele
   adiante). A força virou token pelo mesmo motivo pelo qual a cor virou: um
   literal na regra obriga os três temas a concordarem num número que só serve
   a um. */
/* ── `--foco` é declarado AQUI, e essa é uma fronteira nova  (2026-09-01) ────
   O token mora no `nucleo.css`, que é do Scriptorium e vale para os quatro
   apps — e lá ele valia exatamente os hex do acento do Leitor, porque o anel
   de foco e o cromo sempre foram a mesma cor nesta pele.

   Com a brasa isso deixa de ser verdade sozinho: mover `--acento` sem mover
   `--foco` deixaria um anel carmim em volta de um botão brasa. E mover
   `--foco` no núcleo alcançaria Tabula, Codex e Memoria — os dois últimos
   nem declaram acento próprio, eles pintam TEXTO com `--foco`, e o README do
   Scriptorium avisa que trocá-lo olhando só o teste de lá "passa verde e
   quebra dois apps".

   Então a pele redeclara o token para si. O núcleo não se toca, e o piso de
   3:1 como anel que `nucleo.test.mjs` mede continua medido lá — aqui a brasa
   passa com folga nos três temas (8,33 / 7,82 / 8,46 contra o papel). */
[data-tema="claro"]  { --acento:#832f0d; --sobre-acento:#ffffff; --foco:#832f0d;
  /* ── As duas bordas FINAS da rodada «grafite, lombada, prateleira» ────────
     `--papel-borda-fina` é o contorno de uma superfície que já se separa da
     mesa pela SOMBRA — cartão da lista, cartão do destaque, a caixa da busca,
     a cápsula flutuante. Ele não responde ao piso de 3:1 e não deve: o piso é
     para borda que é a ÚNICA pista de controle, e em nenhum destes ela é (a
     sombra é a pista; no cartão, a lombada também).

     `--aro-fino` é o aro do controle secundário — os círculos de ação de 29px
     no cartão e os de 34px na coluna da capa, e o chip de tema em repouso.
     Mesma dispensa e mesma razão: o glifo do círculo é `--tenue` (4,5:1+) e o
     chip carrega ponto colorido e rótulo. Onde a borda for tudo o que há, o
     token continua sendo `--borda-controle`, que é o que tem piso medido. */
  --papel-borda-fina: rgba(34,33,29,.07); --aro-fino: rgba(34,33,29,.15);
  /* ── A pele redeclara o grafite, e por que ela pode  (02/09) ──────────────
     Os `--cromo-*` do núcleo são os valores do tema claro, e é ele quem manda:
     o cromo não muda por tema (a nota no `nucleo.css` diz por quê). Os dois
     ajustes abaixo não desfazem isso — são o mesmo grafite deslocado um ponto,
     e existem por razões locais desta pele.

     Fica em TOKEN e não num `background` literal por dentro da media query
     porque o harness de contraste lê token, nunca literal: um gradiente
     cravado em regra é uma superfície que nenhum teste consegue medir, e a
     bateria de `cromo.test.mjs` precisa dos três temas. Mesmo movimento que
     `--foco` fez em 2026-09-01, e pela mesma razão. */
  --hl-fantasma: 22%;
  --leitura:#454a52; --sobre-leitura:#ffffff; --leitura-forca: 14%;
  --progresso:#26436e; }
[data-tema="sepia"]  { --acento:#7c2c0b; --sobre-acento:#ffffff; --foco:#7c2c0b;
  --papel-borda-fina: rgba(46,37,25,.07); --aro-fino: rgba(46,37,25,.16);
  /* Um ponto mais quente, para o grafite não brigar com o papel rosado. */
  --cromo-1:#2a2b2c; --cromo-2:#1e1d1d;
  /* Um passo mais quente, como o resto do sépia. */
  --tabua-1: #d6c8b2; --tabua-2: #b9a88e;
  --hl-fantasma: 22%;
  --leitura:#4a3f52; --sobre-leitura:#ffffff; --leitura-forca: 14%;
  --progresso:#2b4468;
  /* ── O amarelo do sépia é próprio, e foi o papel quente que obrigou ───────
     O `#f7e08a` que o claro usa ficava a **1.188:1** contra o papel novo
     (`#f8f3e9`) — abaixo do piso de 1.2:1 que a §5.1 registra, e o teste
     reprovou na hora. Não é caso de afrouxar o piso: um destaque que se
     confunde com a página é um destaque que não se acha ao reler, e o piso
     existe porque isso já aconteceu.

     Amarelo sobre papel amarelado é o par mais apertado que existe aqui, e ele
     já era o mais apertado no papel antigo (1.220:1). Esta é a variante por
     tema que a §5.1 sempre previu, aplicada onde a aritmética a exigiu:
     `#f2d36c` dá 1.327:1 contra a página e 11.56:1 de texto por cima.

     As outras três não precisaram: verde 1.41, rosa 1.61, azul 1.57. E
     `--vivo-amarelo` **não** muda — a amostra do botão precisa ser a mesma
     bolinha em todo tema, senão "a amarela" deixa de ser uma coisa só.

     2026-08-21 — reajustado para `#ecd07a` junto com a descida dos quatro ao
     registro do pigmento (ver `:root`): contra o papel do sépia dá 1,31:1,
     e o texto por cima segue em 10,10:1. */
  --hl-amarelo: #ecd07a;
}

/* ── O tema escuro precisa de OUTRA cor, não da mesma esmaecida ────────────
   Um pastel claro por baixo de texto claro é ilegível por construção, e
   esmaecer o `<mark>` inteiro só piora: `opacity` no elemento apaga o texto
   junto com o fundo. A saída é a que a §5.1 sempre pediu — **variante por
   tema**: no escuro, a mesma matiz vira um tom fundo e saturado, sobre o qual
   o texto claro do tema segue acima de 4.5:1, medido cor a cor.

   As matizes continuam distinguíveis entre si, que é o que faz a semântica das
   quatro cores (importante / vale citar / suspeito / estrutural) sobreviver. */
[data-tema="escuro"] {
  --acento:#f39d7a;
  /* Aqui o acento é CLARO. Branco por cima dele daria ~2:1 — quem escreve
     sobre o acento pergunta ao token, e o token responde com o papel. */
  --sobre-acento:#16171a;
  /* Mesma razão do bloco claro: a pele redeclara `--foco` para não deixar o
     anel numa cor e o cromo em outra. Ver a nota lá em cima. */
  --foco:#f39d7a;
  --papel-borda-fina: rgba(255,255,255,.06); --aro-fino: rgba(255,255,255,.16);
  /* Aqui a razão NÃO é cosmética: a mesa do escuro é `#14171a`, e o cromo tem
     de ficar um degrau mais CLARO que ela. Uma lateral mais funda que a mesa
     deixa de ser objeto pousado e vira buraco na tela. A borda também sobe um
     ponto, pelo mesmo motivo: sobre fundo escuro, .07 de branco some. */
  --cromo-1:#23282d; --cromo-2:#191c20; --cromo-borda:rgba(255,255,255,.08);
  /* A madeira na penumbra — ver a nota da tábua no `:root`. */
  --tabua-1: #3a3f45; --tabua-2: #262a30;
  /* O tema que obrigou a família a nascer — história e medições na nota
     "── O acompanhamento da voz saiu do `--acento`" acima. O cinza-osso é
     claro como o acento, então quem escreve por cima responde igual: o papel. */
  --leitura:#b0aca2; --sobre-leitura:#16171a; --leitura-forca: 20%;
  --progresso:#8fb3dd;
  /* Escurecidos nesta rodada (Onda 3, §4): o guarda de contraste que só
     testava `--tinta` sobre `--hl-*` ganhou `--acento` (`.prosa a` também
     é destacável — mesmo mecanismo, mesmo risco) e `--acento` claro sobre
     estes quatro fundos escuros dava 3,98–4,24:1, abaixo do piso. O
     conserto é aqui, não em `--acento`: o token do acento é usado em
     dezenas de outras superfícies já medidas e passando (links fora do
     destaque, chips ativos, foco), e mexer nele reabriria toda essa
     medição por um problema que só existe embaixo de quatro cores
     específicas. `--tinta` tinha folga de sobra para ceder (6,7–7,1:1
     antes de escurecer, ver `nucleo.test.mjs`) — escurecer o hl não a
     derruba, só cresce a margem. Mirado ≥4.7:1 contra `--acento`,
     preservando ≥4.5:1 contra `--tinta`: amarelo 3,98→4,82:1 (tinta
     6,69→8,09:1), verde 4,22→4,79:1 (tinta 7,09→8,04:1), rosa 4,16→4,80:1
     (tinta 6,98→8,06:1), azul 4,24→4,72:1 (tinta 7,13→7,92:1).

     2026-08-21 — os quatro descem mais um passo, pela MESMA aritmética e por
     um motivo novo: o acento deixou de ser o azul claro `#8fb3dd` e virou a
     púrpura `#c19ae6`, que é mais clara, e por isso mais apertada por cima
     de um fundo escuro. Com os valores da Onda 3 o par `--acento` × `--hl-*`
     media 4,59–4,70:1 — passava o piso de 4.5 raspando, sem a folga que este
     projeto exige. Escurecidos para mirar ≥4,8:1 contra o acento: amarelo
     4,64→4,87 · verde 4,62→4,82 · rosa 4,70→4,90 · azul 4,59→4,88. O par
     contra `--tinta` só cresce (8,66–8,81:1). */
  --hl-roxo:    #42305c;  --hl-amarelo: #463911;
  --hl-rosa:    #632439;  --hl-azul:    #1f3c5a;
  /* As matizes dos temas trocam de VALOR, nunca de matiz: no escuro elas
     precisam ser claras para continuarem legíveis sobre `--papel`, e continuam
     sendo a mesma cor do mesmo tema.

     2026-09-01 — refeitas junto com as claras (ver o bloco da matiz de cada
     tema em `:root`). Cada uma é a matiz no mesmo registro de L e S que a irmã
     escura tinha antes: a regra deste bloco é "troca de valor, nunca de
     matiz", e mover a matiz em cima sem mover aqui embaixo a quebraria — foi
     exatamente o que o teste «nenhum tema ocupa a matiz do acento» pegou, com
     o azul-noite de Fé e Filosofia a 25° da brasa no escuro enquanto a versão
     clara já estava a 158°.

     A exceção é o de Fé e Filosofia, que precisou subir de L 56,5% para 67%:
     no azul-noite o valor herdado dava 4,42:1 contra `--papel`, fora do
     registro dos irmãos (6,05–8,89). A 67% dá 6,57:1 e volta para a família.

     Contraste sobre `--papel` (#16171a): ciência 6,06 · artes 6,37 ·
     fé 6,57 · literatura 6,67 · história 7,34. */
  --t-ciencia-tecnologia: #5fa297;  --t-artes-vida:         #b585e6;
  --t-fe-filosofia:       #7d9dd9;  --t-literatura:         #c48db4;
  --t-historia-sociedade: #a1a89d;
  /* O fantasma do ajuste precisa de mais força aqui: 22% de um tom já escuro,
     sobre fundo escuro, some. */
  --hl-fantasma: 48%;
  /* Medido depois de escurecer os quatro `--hl-*` acima (Onda 3, correção):
     o fantasma (48% de mistura sobre `--papel`) não foi remedido junto, e a
     razão contra a página caiu de 1,310–1,351 (hl-* antigo) para
     1,240–1,260 (amarelo 1,253 / verde 1,258 / rosa 1,240 / azul 1,260) —
     ainda acima do piso de 1,2:1 que a 03-destaques §5.1 registra, mas com
     folga de 3–5% em vez dos 9–12% de antes.

     Decisão: não mexer. A diferença para o caso do `--tenue` (nucleo.css,
     onde 0,22–0,7% de folga foi tratado como reprovação) é dupla: 1,2:1 é
     um piso DESTE projeto para a identificabilidade da marcação — não é o
     piso normativo de texto da WCAG que o `--tenue` precisa cumprir sem
     alternativa —, e o fantasma nunca é a ÚNICA pista: `.editando` sempre
     vem com `outline: 1px dashed var(--acento)` ao lado (duas regras
     abaixo), que não depende desta cor nem deste contraste para marcar onde
     o destaque em ajuste começa e termina. O `--tenue` carrega informação
     sozinho, em texto lido a todo momento; o fantasma é um estado
     transitório — só existe enquanto o dedo arrasta uma alça — e tem reforço
     redundante ao lado. A mesma folga apertada que era risco real num é
     folga suficiente no outro. */
  /* --perigo clareia no escuro, mesma lógica de `--acento`: o fundo é que
     ficou escuro, então quem carrega a cor de perigo precisa ficar clara
     para continuar lendo acima do piso — vermelho profundo sobre fundo
     quase preto é a MESMA aritmética que branco sobre acento, invertida.
     `#e08692`, mesmo hue/saturação do claro, L 70,3%. Sobre `--papel-elev`
     escuro dá 6,28:1 (era 3,78); sobre `--regra` escuro (hover do ✕ de
     `.destaque`) 5,10:1 (era 3,07 — o pior caso do tema, por isso decide o
     valor); sobre o próprio fundo "armado" (tingido de si mesmo a 14–16%)
     4,84–5,02:1 (era 3,22–3,30 — correção: o relatório anterior citava
     3,30–3,58, que troca o pior caso do escuro por 3,58, o pior caso do
     CLARO; o par certo do escuro antigo é 3,22–3,30).

     2026-08-21 — `#f27f92`, um passo mais claro e mais saturado, acompanhando
     o `#b81028` do claro. Aqui não havia colisão a resolver (o acento do
     escuro é púrpura), mas a cor de perigo é uma só ideia nos três temas e
     não faria sentido ficar dois passos atrás no escuro. Todas as medições
     sobem: `--papel-elev` 6,28→6,46:1 · `--regra` 5,10→5,25:1 · armado
     14–16% 4,84–5,02→4,97–5,16:1. */
  --perigo: #f27f92;
}

/* O reset (box-sizing, -webkit-text-size-adjust, margin/font-smoothing do
   body) e o `@media (prefers-reduced-motion)` subiram ao núcleo (Task 9). O
   que fica é só o que é do Leitor: papel/tinta vêm do tema, e a tipografia de
   leitura (`--corpo`, `--size`, `--leading`) não existe na fundação.

   ── `--tela`, não `--papel` (Onda 3) ────────────────────────────────────
   O corpo é a MESA, não a folha — é o que faz o claro do Leitor bater com o
   claro do Tabula (os dois são vistas do mesmo mundo: papel sobre
   escrivaninha). A folha ganhou existência própria em `.artigo` (ver
   comentário lá): só a tela de leitura tem folha, então só ela pinta
   `--papel`; toda superfície de serviço (inbox, destaques, busca, entrada)
   fica direto sobre a mesa, como sempre foi visualmente — a diferença é
   que agora a mesa tem um token que é dela, e não emprestado do papel. */
body {
  background: var(--tela); color: var(--tinta);
  font-family: var(--corpo); font-size: var(--size); line-height: var(--leading);
  transition: background-color var(--dur) var(--curva), color var(--dur) var(--curva);
}

/* ═══════════════════════════════════════════════════════════════════════════
   CROMO GLOBAL — cabeçalho que rola, navegação embaixo  (L-66, 02 §4, D1)
   ═══════════════════════════════════════════════════════════════════════════
   O `#topo` fixo de 52px saiu. Duas razões, e a segunda é a que decide:

   1. O alcance do polegar em retrato e do dedo apoiado em paisagem está
      **embaixo**. Uma navegação no alto do iPad é uma navegação que se alcança
      levantando a mão do aparelho.
   2. O alto da tela é onde o olho **começa a ler**. O cabeçalho fixo cobrava
      aquela faixa em toda leitura, com `backdrop-filter` permanente por cima
      do texto — e o blur estava ali para disfarçar o que ele mesmo criava.

   No lugar dele, duas peças com papéis distintos:

   - `.cabeca` — **no fluxo**, rola com o conteúdo e some sozinha. Leva a
     identidade do app e os dois controles que não são navegação (`Aa` e sair).
   - `#barra-nav` — fixa embaixo, em vidro, um destino por alvo de 52px.

   **A barra some pelo mesmo `data-cromo` que escondia o `#topo`** — não por um
   mecanismo novo. É o que mantém vivo o gesto da L-53b (tocar no texto traz o
   cromo de volta): ele mexe num atributo do `<body>`, e continua mexendo no
   mesmo. Inventar um segundo caminho aqui seria criar dois donos para "o cromo
   está visível?", que é como um deles fica para trás. E some **só na tela de
   artigo** — a regra é `body[data-leitura][data-cromo="oculto"]`, ver a
   seção do cromo adiante.
   ─────────────────────────────────────────────────────────────────────────── */

/* Altura reservada embaixo. Um token porque três coisas dependem dela — o
   fim do `main`, o botão da caneta e o aviso de diagnóstico —, e uma altura
   copiada em três lugares é uma altura que desalinha na primeira mudança. */
:root { --barra-h: calc(58px + env(safe-area-inset-bottom)); }

/* ── A base da coluna flutuante  (spec 14 §4.1) ─────────────────────────────
   A pílula do tempo mora ABAIXO da caneta, e abaixo da caneta não havia lugar:
   ela estava a 1rem da barra de navegação, e as duas aparecem no MESMO
   instante — o cromo visível mostra as duas ou esconde as duas. A faixa teve
   de ser aberta.

   `--tempo-h` é reservado SEMPRE, com pílula ou sem. Sem isso a caneta subiria
   e desceria a cada rolagem, e **controle que salta é pior que controle
   deslocado**: o polegar aprende uma posição, não uma fórmula. O custo é uma
   mudança única e permanente de ~28px, e o que a 02 §4 exige da caneta —
   "acima da barra inferior, para o dedo não acertar Destaques" — continua
   valendo com folga. */
/* `--bolha`/`--bolha-folga` (Bloco J4): a coluna nasceu com uma bolha e chegou
   a três, e cada degrau repetia "56px + .7rem" escrito à mão. Um número solto
   num degrau desalinha a coluna inteira em silêncio — nada quebra, os botões
   só deixam de se encaixar. */
:root {
  --tempo-h: 26px; --pilha-base: calc(var(--barra-h) + 1rem);
  /* 48px desde 01/09 (era 56). A coluna voltou a ter as SETE bolhas depois do
     rollback da gaveta, e sete de 56px cobrem o fim de muita linha no iPhone —
     foi o que fez a gaveta parecer necessária. Encolher 8px devolve ~15% da
     coluna sem tirar nada da tela, e 48 continua acima do `--alvo` de 44px que
     o núcleo exige de qualquer toque. Escolha de Yuri vendo as três medidas.

     Quem depende deste número: o `--degrau` abaixo (e portanto as sete
     posições), o recuo do `#velocidade-painel` e do painel de ajustes, e o
     corpo de texto das duas bolhas que carregam TEXTO em vez de glifo — a do
     progresso e a da velocidade, ambas ajustadas junto. */
  --bolha: 48px; --bolha-folga: .7rem;
  /* O DEGRAU da coluna — bolha mais folga, uma vez só. A coluna chegou a cinco
     bolhas no Bloco J7, e a corrente escrita à mão em cada uma já vinha
     repetindo "+ var(--bolha) + var(--bolha-folga)" quatro vezes na mais alta.
     Com o degrau, cada bolha declara a POSIÇÃO dela (`* 2`, `* 3`) em vez de
     recontar a coluna inteira, e mudar o diâmetro continua movendo as cinco
     juntas. */
  --degrau: calc(var(--bolha) + var(--bolha-folga));
  /* O primeiro degrau: acima da barra e da faixa reservada da pílula do tempo.
     Ele é a base de TODAS as bolhas, e por isso tem nome. */
  --pilha-0: calc(var(--pilha-base) + var(--tempo-h) + .5rem);

  /* ── AS DUAS CÁPSULAS  (02/09) ───────────────────────────────────────────
     `--bolha` e `--degrau` continuam vivos acima: eles regiam SETE posições e
     agora regem a base da pilha e a folga da pílula do tempo. Apagá-los
     levaria junto o `#tempo-leitura`, que é o que a nota da spec 14 §4.1
     protege.

     A geometria das cápsulas é declarada, e não somada à mão em cada regra,
     por uma razão concreta: dois painéis se alinham a itens do MEIO da pilha
     (o deslizante da velocidade e o sumário), e uma altura escrita à mão em
     três lugares desalinha na primeira mudança. */
  --capsula-l: 52px;
  --capsula-item: 48px;
  --capsula-anel: 52px;
  --capsula-item-texto: 50px;
  --capsula-gap: 14px;
  --capsula-x: 22px;
  /* A altura do «Seguir» tem nome porque é lida em DOIS lugares: o botão, lá
     embaixo, e a conta que centra a pilha no Mac. Escrita à mão nos dois, a
     primeira mudança desalinha a coluna sem quebrar nada visível. */
  --capsula-seguir-h: calc(var(--capsula-item-texto) + 10px);
}

/* ── A geometria das TRÊS cápsulas mora TODA no `body`  (04/09) ────────────
   Em 03/09 esta seção aprendeu, por um defeito de 128px, que **um `var()` é
   substituído no elemento em que a variável é declarada**: escrita no `:root`,
   uma soma congela os valores do `:root` e desce como número pronto, e a rota
   que redeclara uma das parcelas no `body` chega depois da conta já feita.
   A regra que ficou foi «derivada de token que alguma rota redeclara mora no
   mesmo elemento em que a rota o redeclara» — e a rodada de 04/09 a levou até
   o fim: **as parcelas também**. Altura de cápsula e soma da coluna vivem
   ambas aqui, e a escrivaninha redeclara o que muda sem precisar refazer as
   somas à mão. Um lugar só para errar, em vez de três que têm de concordar.

   Os `+ 2px` de cada altura são os dois FIOS da borda da cápsula (1px em cima
   e embaixo). Sem eles a altura declarada fica 2px menor que a real por
   cápsula, e o centramento do Mac erra por metade da soma.

   `--voz-bloco` é a cápsula da voz **mais o gap acima dela**, e vale zero
   quando ela não existe: um artigo sem narração não tem `⏸`, não tem `1,0×` e
   não tem `⇕`, e a coluna é de duas peças. Quem acende o atributo é
   `ligarOuvir` — ver `artigo.mjs`. */
body {
  --capsula-pagina-h: calc(var(--capsula-anel) + var(--capsula-item) + 2px);
  --capsula-voz-h: calc(var(--capsula-item) * 3 + 2px);
  --capsula-mao-h: calc(var(--capsula-item-texto) * 3 + 2px);
  --voz-bloco: 0px;
  --pilha-h: calc(var(--capsula-pagina-h) + var(--capsula-gap)
    + var(--voz-bloco) + var(--capsula-mao-h));

  /* Onde a BASE da pilha pousa: no modo barra é acima da barra e da pílula do
     tempo, como sempre foi; no Mac ela se centra — e se centra pela base,
     porque é pela base que a coluna é ancorada. Depois do primeiro arrasto
     quem manda é o valor guardado, que `pilha.mjs` escreve inline aqui. */
  --pilha-y: var(--pilha-0);

  /* As alturas a partir da base da pilha, para os dois painéis que nascem de
     um item do meio: o sumário (do anel do progresso) e o deslizante da
     velocidade. O `Aa` é o item de BAIXO da cápsula da página, e o anel está
     um item acima dele; o `1,0×` é o do meio da voz, um item acima da base
     dela. */
  --y-aa: calc(var(--capsula-mao-h) + var(--capsula-gap) + var(--voz-bloco));
  --y-progresso: calc(var(--y-aa) + var(--capsula-item));
  --y-velocidade: calc(var(--capsula-mao-h) + var(--capsula-gap) + var(--capsula-item));
}
body[data-voz] { --voz-bloco: calc(var(--capsula-voz-h) + var(--capsula-gap)); }

@media (min-width: 1100px) and (pointer: fine) {
  body { --pilha-y: calc(50% - var(--pilha-h) / 2); }
}

/* ── O vermelho que se lê SOBRE o cromo  (04/09) ───────────────────────────
   Irmão do `--cromo-acento` do núcleo, e pela mesma razão registrada lá: o
   cromo não muda por tema, então a tinta que escreve sobre ele também não.
   `--perigo` é `#b81028` no claro — vermelho de papel, escuro sobre escuro
   assim que o botão que o usa passou a ter campo grafite. Este é o `--perigo`
   do tema ESCURO, servido nos três.

   Mora na pele e não no `nucleo.css` porque o núcleo é do Scriptorium: editar
   a cópia que vive dentro do app é perder a edição na próxima sincronização. */
:root { --cromo-perigo: #f27f92; }

/* ── A pilha e as três cápsulas ───────────────────────────────────────────
   `pointer-events: none` na coluna e `auto` nas cápsulas: a coluna é uma faixa
   de 52px de largura sobre o texto, e sem isto ela roubaria o toque da prosa
   nas margens do que ela mesma não desenha.

   `overflow: hidden` na cápsula é o que faz o raio de 26px cortar o primeiro e
   o último item — sem ele, o realce de hover do item do topo escapa pela
   quina arredondada.

   ── O CROMO desceu para cá  (04/09) ─────────────────────────────────────
   A cápsula era papel elevado sobre papel: uma pastilha clara sobre a folha
   clara, separada dela por um fio. Passou a ser **o mesmo material da lateral
   e da barra** — o gradiente `--cromo-1 → --cromo-2`, grafite nos três temas.
   É a decisão de 02/09 aplicada ao resto do app: a coluna flutuante não é
   página, é ferramenta, e ferramenta se distingue da página pelo material, não
   por um filete.

   Com o campo escuro vem o resto do pacote daquela decisão: a tinta é
   `--cromo-tinta-2`, o realce é `--cromo-acento` (o acento do tema ESCURO, em
   qualquer tema) e a divisória é `--cromo-borda`. Um acento claro sobre
   grafite reprovaria medido, e a regra da casa é clarear a TINTA, nunca o
   campo. */
#pilha-leitura {
  position: fixed; right: var(--capsula-x); bottom: var(--pilha-y);
  z-index: 46; pointer-events: none;
  display: flex; flex-direction: column; align-items: flex-end; gap: var(--capsula-gap);
}
.capsula {
  pointer-events: auto;
  width: var(--capsula-l); flex: none;
  display: flex; flex-direction: column;
  background: linear-gradient(180deg, var(--cromo-1), var(--cromo-2));
  border: 1px solid var(--cromo-borda);
  border-radius: 26px; box-shadow: var(--sombra-erguida); overflow: hidden;
  /* O arrasto da coluna (04/09): sem isto o Safari decide rolar a página no
     início do gesto, e o dedo que queria mover a pilha rola o artigo debaixo
     dela. A mesma armadilha do `touchstart` da caneta, e o mesmo remédio —
     dizer ao motor, ANTES do gesto, que esta superfície não é para rolar. */
  touch-action: none;
}
/* Enquanto a coluna está sendo arrastada, o cursor é o mesmo no documento
   inteiro: o ponteiro sai de cima da cápsula durante um gesto rápido, e um
   cursor que pisca entre a mão fechada e a seta faz o arrasto parecer ter
   terminado quando não terminou. */
body[data-arrastando-pilha] { cursor: grabbing; }
body[data-arrastando-pilha] .capsula > button { cursor: grabbing; }
/* A divisória entre itens, e o seletor merece nota: `:not([hidden]) ~
   :not([hidden])` dá a régua a todo item que tenha ALGUM irmão visível antes
   dele — que é exatamente «todos menos o primeiro visível». Com
   `:not(:first-child)` a régua nasceria no topo da cápsula sempre que o
   primeiro item estivesse escondido. */
.capsula > :not([hidden]) ~ :not([hidden]) {
  border-top: 1px solid var(--cromo-borda);
}
/* Uma cápsula sem nenhum item visível não pode desenhar uma pílula vazia.
   `:not(:has(...))` faz isso sem JavaScript, e o Safari o suporta desde 2023
   — se algum dia não suportar, o pior caso é uma pílula vazia, não um app
   quebrado.

   É esta regra que faz a cápsula da VOZ nascer inteira ou não nascer: os três
   itens dela seguem o mesmo sinal («este artigo tem narração?»), e quando ele
   é não, os três estão `hidden` e a peça se recolhe sozinha. */
.capsula:not(:has(> :not([hidden]))) { display: none; }
/* ── E fora da leitura a pilha INTEIRA não existe  (03/09) ─────────────────
   A regra acima testa o ATRIBUTO `hidden`. Só que, fora da leitura, os itens
   somem por `display: none` do CSS (`body:not([data-leitura]) …`), e um
   elemento assim continua casando com `:not([hidden])` — a cápsula
   sobrevivia ao teste e desenhava a si mesma sem nada dentro: uma pílula de
   52 px por 2, pairando sobre a inbox. «o que é essa barrinha branca?»

   Não dá para consertar isso alargando o `:has()`: CSS não pergunta pelo
   `display` computado de um filho. O conserto é dizer a verdade mais simples,
   que é a da rota — fora da leitura não há coluna nenhuma, e por isso ela não
   se desenha. A regra acima continua valendo DENTRO da leitura, onde a
   cápsula pode esvaziar por atributo. */
body:not([data-leitura]) #pilha-leitura { display: none; }
/* Os itens: mesma forma, alturas do desenho. Sem `border-radius` próprio (a
   cápsula corta), sem sombra (a cápsula tem a dela) e sem fundo (a cápsula é
   a superfície). É o que os faz parecer UMA peça em vez de três coladas. */
.capsula > button {
  width: var(--capsula-l); height: var(--capsula-item); min-height: 0;
  flex: none; border: 0; background: none; color: var(--cromo-tinta-2);
  display: grid; place-items: center; cursor: pointer; padding: 0;
  position: relative;
  appearance: none; -webkit-appearance: none;
  font-family: var(--sans); line-height: 1;
}
/* O `display: grid` acima é regra de autor e vence o `[hidden] { display:
   none }` da folha do navegador (o defeito da L-120). As guardas por id mais
   abaixo cobrem quatro itens; esta cobre a cápsula inteira, e é a que pega
   o `⇧`, o `✎` e o `▶`, que tinham ficado de fora (revisão M109). */
.capsula > [hidden] { display: none; }
.capsula > button:hover, .capsula > button:focus-visible { color: var(--cromo-acento); }
#capsula-mao > button { height: var(--capsula-item-texto); }

/* ═══ A COLUNA NO TELEFONE: A BARRA DO RODAPÉ  (14/09) ═══════════════════════
   «Olha o tanto que a interface do Leitor está ruim no iPhone» — a captura
   (440 × 956) mostrava a coluna de três cápsulas em cima da prosa: 56 px de
   cada linha por 428 px de altura, e na tela do estudo, com cinco cápsulas,
   26 das 30 linhas da tela. No telefone não há margem ao lado da prosa para
   uma coluna, e estreitar a prosa para abrir uma seria piorar o que já é
   escasso.

   A forma é a do Codex («Ilhas no telefone», 14/09), de propósito a mesma:
   abaixo de 37rem (`TELEFONE` em `pilha.mjs`, que escreve `data-arranjo` no
   `<body>`), as cápsulas deitam numa fileira de borda a borda, colada em cima
   da barra de abas, no material dela, rolável na horizontal, com a pílula do
   tempo na ponta esquerda. As cápsulas viram GRUPOS — sem moldura própria,
   porque a barra é o fundo — separados por um fio. Nada muda de tamanho além
   do piso: todo item tem o `--alvo` de 44px. Na tela do estudo os itens não
   cabem na largura: os que passam ficam a um arrasto de lado, e a ordem põe
   a leitura primeiro (progresso, Aa, voz, mão), o estudo depois e a bancada
   por último.

   A barra NÃO segue o `data-cromo` — é o que o percentual exige («estou
   sentindo falta do percentual na tela», 01/09). Quando a barra de abas some
   ao rolar, esta desce ao chão com ela e passa a responder pela zona do
   indicador de início.

   Os seletores começam em `body[data-arranjo="barra"]` e por isso vencem as
   regras da coluna pela especificidade, não pela posição neste arquivo. */
body[data-arranjo="barra"] {
  /* A altura da fileira: o alvo mais o fio de cima. É o que a pílula do tempo,
     o fim do fluxo e os painéis ancorados na coluna precisam saber. */
  --fileira-h: calc(var(--alvo) + 1px);
  --pilha-y: calc(var(--barra-h) + var(--fileira-h));
  --pilha-0: calc(var(--pilha-y) + .5rem);
  /* Os painéis nasciam ao lado de itens do MEIO da coluna; deitada, todos os
     itens estão na mesma linha, e a âncora é a base da barra. */
  --y-aa: 0px; --y-progresso: 0px; --y-velocidade: 0px;
}
body[data-arranjo="barra"] #pilha-leitura {
  left: 0; right: 0; bottom: var(--barra-h);
  flex-direction: row; align-items: stretch; gap: 0;
  /* A ponta esquerda é da pílula do tempo, que é outra peça pendurada no
     corpo. */
  padding-inline: calc(env(safe-area-inset-left, 0px) + 3.6rem)
                  calc(env(safe-area-inset-right, 0px) + var(--alvo) + 1rem);
  overflow-x: auto; overscroll-behavior-x: contain; scrollbar-width: none;
  /* Na coluna a faixa deixava o toque passar para a prosa; na barra não há
     prosa debaixo dela. */
  pointer-events: auto;
  background: linear-gradient(180deg, var(--cromo-1), var(--cromo-2));
  border-top: 1px solid var(--cromo-borda);
  transition: bottom var(--dur) var(--curva), padding-bottom var(--dur) var(--curva);
}
body[data-arranjo="barra"] #pilha-leitura::-webkit-scrollbar { display: none; }
/* A cápsula vira grupo: sem moldura própria (a barra É o fundo) e com
   `pan-x`, porque na coluna o `touch-action: none` existia para o arrasto
   vertical — aqui ele impediria o dedo de rolar a fileira. */
body[data-arranjo="barra"] .capsula {
  flex-direction: row; flex: none; width: auto; height: var(--alvo);
  background: none; border: 0; border-radius: 0; box-shadow: none; overflow: visible;
  touch-action: pan-x;
}
body[data-arranjo="barra"] .capsula ~ .capsula {
  margin-inline-start: .25rem; padding-inline-start: .25rem;
  border-inline-start: 1px solid var(--cromo-borda);
}
/* A régua entre itens era horizontal na coluna; deitada, não há régua. */
body[data-arranjo="barra"] .capsula > :not([hidden]) ~ :not([hidden]) { border-top: 0; }
/* `:is()` e não uma lista de seletores: o teste da bolha do progresso lê o
   PRIMEIRO `#progresso-flutuante {` do arquivo por regex, e uma lista aqui,
   antes da regra dela, seria o que ele encontraria. */
body[data-arranjo="barra"] :is(.capsula > button, #capsula-mao > button, #progresso-flutuante) {
  width: var(--alvo); height: var(--alvo);
}
/* Os dois botões que carregam TEXTO em vez de glifo crescem na largura. */
body[data-arranjo="barra"] #estudo-seguir,
body[data-arranjo="barra"] #bancada-face { width: auto; min-width: var(--alvo); padding: 4px 10px 5px; }
/* A leitura primeiro; o que a tela do estudo acrescenta vem depois, e a
   bancada por último — é o que fica a um arrasto de lado. */
body[data-arranjo="barra"] #capsula-pagina { order: 1; }
body[data-arranjo="barra"] #capsula-voz { order: 2; }
body[data-arranjo="barra"] #capsula-mao { order: 3; }
body[data-arranjo="barra"] #capsula-estudo { order: 4; }
body[data-arranjo="barra"] #capsula-bancada { order: 5; }
/* A pílula do tempo na ponta esquerda da barra, na tinta do cromo, mostrando
   só a sessão: «12 min». O acumulado é secundário por desenho, e na barra
   não há largura para dois números. */
body[data-arranjo="barra"] #tempo-leitura {
  left: calc(env(safe-area-inset-left, 0px) + .5rem); right: auto;
  bottom: var(--barra-h); z-index: 47;
  height: var(--alvo); padding: 0 .3rem;
  background: none; border: 0; box-shadow: none;
  color: var(--cromo-tinta-2); font-size: .72rem; font-weight: 600;
  transition: bottom var(--dur) var(--curva);
}
body[data-arranjo="barra"] #tempo-leitura :is(.sep, .total, .rot) { display: none; }
body[data-arranjo="barra"][data-cromo="oculto"] #tempo-leitura {
  opacity: 1; transform: none; bottom: env(safe-area-inset-bottom, 0px);
}
/* O fim do texto rola até acima das DUAS barras. */
body[data-arranjo="barra"] #versao { padding-bottom: calc(var(--pilha-y) + 1.5rem); }
/* Os painéis que nasciam à esquerda da coluna pousam acima da barra. */
body[data-arranjo="barra"] #velocidade-painel {
  right: .6rem; left: auto; bottom: calc(var(--pilha-y) + .5rem);
  width: min(20rem, calc(100vw - 1.2rem));
}
body[data-arranjo="barra"] #coloquio { right: .6rem; width: min(30rem, calc(100vw - 1.2rem)); }

/* ── UMA BARRA SÓ NO TELEFONE  (spec 63, 19/09) ──────────────────────────────
   «esses menus do leitor no iphone estão muito feios». Lendo, o rodapé tinha
   DUAS barras de grafite empilhadas — esta fileira e as abas —, ~170 px de
   cromo escuro sobre a página creme, com ícones de pesos diferentes e fios
   que não se alinhavam de uma barra para a outra.

   O dono escolheu o modelo do Books: lendo, a fileira toma o lugar das abas,
   que voltam pelo «≡» na ponta direita ou rolando para cima (`data-abas`,
   escrito por `ligarAbas` em `pilha.mjs`). O `data-cromo` deixa de mandar na
   fileira do telefone: ele mostra tudo perto do topo e a cada toque no texto,
   e a barra dupla voltaria justamente na abertura do artigo.

   O material é o GRAFITE da lateral, como no iPad e no Mac. De 19 a 25/09 o
   telefone vestiu vidro (papel a 78% com desfoque, `--cromo-*` redeclarados
   com escopo no rodapé) — revogação só no telefone da regra de 02/09 («a
   barra de baixo é o mesmo cromo da lateral»). Em 25/09 o dono a restituiu:
   «aquela barra lá embaixo tinha que seguir o padrão de cor da barra lateral
   do ipad e macbook». Nada aqui redeclara o cromo: a fileira, as abas, o «≡»
   e a pílula do tempo herdam os tokens de todo o app. */
/* A barra de abas do telefone mede EXATAMENTE `--barra-h`. Media 62,6 px
   (itens de 52 + a folga da lista + o fio) contra os 58 do token, e a
   fileira, que pousa em `--barra-h`, cobria 4,6 px do topo dela — o fio entre
   as duas sumia ali (medido no simulador, 19/09). Os itens descem ao alvo de
   toque, que é o piso, e a altura passa a ser a do token que todos leem. */
body[data-arranjo="barra"] #barra-nav { box-sizing: border-box; height: var(--barra-h); }
body[data-arranjo="barra"] #barra-nav a { min-height: var(--alvo); padding-block: .3rem; }
/* Os ícones num tamanho só: o `▶` e o `⇕` são texto, o microfone, o `⇧` e
   o `✎` são desenho — e cada um herdava um tamanho de fonte de outra época
   (o microfone ainda a serifa de 1,35rem do antigo `?`). */
body[data-arranjo="barra"] :is(.capsula > button, #abas-alternar) svg { width: 22px; height: 22px; }
body[data-arranjo="barra"] #perguntar-flutuante { font-family: var(--sans); font-size: 1rem; }
body[data-arranjo="barra"] #ouvir-flutuante { font-size: 1.05rem; }

/* Lendo, sem o «≡»: uma barra só, no chão. `--pilha-y` desce junto, e os
   painéis que se ancoram nele (a folha da voz, as caixas, a tarja da versão)
   pousam acima da fileira, não acima de uma barra que não está lá. */
body[data-arranjo="barra"][data-leitura]:not([data-abas]) {
  --pilha-y: calc(var(--fileira-h) + env(safe-area-inset-bottom, 0px));
}
body[data-arranjo="barra"][data-leitura]:not([data-abas]) #barra-nav {
  transform: translateY(100%);
}
body[data-arranjo="barra"][data-leitura]:not([data-abas]) #pilha-leitura {
  bottom: 0; padding-bottom: env(safe-area-inset-bottom, 0px);
}
body[data-arranjo="barra"][data-leitura]:not([data-abas]) #tempo-leitura {
  bottom: env(safe-area-inset-bottom, 0px);
}
/* Com o «≡»: as abas voltam mesmo com o cromo oculto. Três atributos contra
   os dois de `body[data-leitura][data-cromo="oculto"] #barra-nav` — vence pela
   especificidade, não pela posição no arquivo. */
body[data-arranjo="barra"][data-leitura][data-abas] #barra-nav { transform: none; }
body[data-arranjo="barra"][data-leitura][data-abas] #tempo-leitura { bottom: var(--barra-h); }

/* O «≡» na ponta direita da fileira, fora dela (ver o `index.html`). Tem
   fundo próprio porque a fileira rola por baixo dele na tela do estudo. */
#abas-alternar { display: none; }
body[data-arranjo="barra"][data-leitura] #abas-alternar {
  display: grid; place-items: center;
  position: fixed; z-index: 47; right: 0; bottom: var(--barra-h);
  width: calc(var(--alvo) + .75rem + env(safe-area-inset-right, 0px)); height: var(--alvo);
  padding: 0 calc(.35rem + env(safe-area-inset-right, 0px)) 0 .4rem;
  background: var(--cromo-1); border: 0; border-left: 1px solid var(--cromo-borda); border-radius: 0;
  color: var(--cromo-tinta-2); cursor: pointer;
  transition: bottom var(--dur) var(--curva);
}
body[data-arranjo="barra"][data-leitura]:not([data-abas]) #abas-alternar {
  bottom: env(safe-area-inset-bottom, 0px);
}
body[data-arranjo="barra"] #abas-alternar[aria-expanded="true"] { color: var(--cromo-acento); }
body[data-arranjo="barra"] #abas-alternar:focus-visible { outline: 2px solid var(--foco); outline-offset: -2px; }

/* ── A folha da voz  (spec 63) ─────────────────────────────────────────────
   No telefone o bloco de quatro controles no alto do artigo (Ouvir, motor,
   Quem lê, Gerar) empurrava o texto 600 px para baixo e parecia formulário.
   Com a cápsula da voz em cena (`data-voz`), ele sai: o `▶` da fileira toca,
   e o `1,0×` abre esta folha, que já montava o motor, o «Quem lê» e a
   velocidade e agora leva o «Gerar» também. Sem `data-voz` (navegador sem
   fala e sem narração) o bloco fica, porque é o único caminho até a voz. */
body[data-arranjo="barra"][data-voz] .artigo > header :is(.controles-voz, .btn.ouvir) { display: none; }
body[data-arranjo="barra"] #velocidade-painel {
  left: .6rem; right: .6rem; width: auto;
  padding: 1rem 1rem 1.1rem;
  transform: translateY(.5rem);
}
body[data-arranjo="barra"] #velocidade-painel[data-aberto="sim"] { transform: none; }
body[data-arranjo="barra"] #velocidade-painel .controles-voz { gap: 1.1rem; }
body[data-arranjo="barra"] #velocidade-painel .fila-voz { gap: 1rem; }
body[data-arranjo="barra"] #velocidade-painel :is(.motor-voz, .timbre, .timbre select, .gerar-estudio) {
  width: 100%; max-width: none;
}
body[data-arranjo="barra"] #velocidade-painel .motor-voz .segmentado { display: flex; }
body[data-arranjo="barra"] #velocidade-painel .motor-voz .opcao { flex: 1; }
/* O `⇕` desce para a folha no telefone: com o «≡» na ponta, a fileira de
   440 px deixava o `✎` debaixo dele. Ele só age com a voz tocando, e já era
   da família da voz. O interruptor é a mesma pergunta, dita por extenso. */
.rolagem-folha { display: none; }
body[data-arranjo="barra"] #rolagem-flutuante { display: none; }
body[data-arranjo="barra"] #velocidade-painel .rolagem-folha {
  display: flex; align-items: center; justify-content: space-between; gap: 1rem;
  width: 100%; min-height: var(--alvo); padding: 0 .1rem;
  background: none; border: 0; border-top: 1px solid var(--regra);
  font: 500 .88rem/1.2 var(--sans); color: var(--tinta); cursor: pointer; text-align: left;
}
body[data-arranjo="barra"] #velocidade-painel .rolagem-folha::after {
  content: ""; flex: none; width: 38px; height: 22px; border-radius: 11px;
  background: radial-gradient(circle 8px at 11px 50%, var(--papel-elev) 97%, transparent) no-repeat,
              var(--borda-controle);
  transition: background-position var(--dur) var(--curva);
}
body[data-arranjo="barra"] #velocidade-painel .rolagem-folha[aria-pressed="true"]::after {
  background: radial-gradient(circle 8px at 27px 50%, var(--sobre-acento) 97%, transparent) no-repeat,
              var(--acento);
}
body[data-arranjo="barra"] #velocidade-painel .rolagem-folha:focus-visible { outline: 2px solid var(--foco); outline-offset: 2px; }

/* ── O topo desce abaixo da barra de status  (16/09) ──────────────────────
   O casco nativo pinta sob a barra de status (`ignoresSafeArea` + inset
   `.never`), e no iPhone os 1.7rem ficavam atrás do relógio e da ilha:
   «aquela barra superior está ficando muito em cima» (Yuri). O `max` deixa
   o Mac e o navegador como estavam (inset zero) e só desce onde há barra. */
.cabeca {
  max-width: var(--measure); margin: 0 auto;
  padding: max(1.7rem, calc(env(safe-area-inset-top, 0px) + .5rem)) max(1.1rem, env(safe-area-inset-right)) 0 max(1.1rem, env(safe-area-inset-left));
  display: flex; align-items: center; gap: .7rem;
  font-family: var(--sans); font-size: .84rem; line-height: 1;
}
/* Glifo e nome são **um link só**, e não dois vizinhos para o mesmo destino:
   dois links com o mesmo `href` lado a lado são duas paradas de teclado e duas
   leituras iguais no VoiceOver para uma única coisa. */
/* Sem min-height explícito de propósito: é `<a href="/">` de verdade — vai
   para a raiz —, alvo de toque real, não rótulo decorativo. Os ~30px do
   glifo dentro são só o ÍCONE; a caixa do link em si já herda os 44px do
   `--alvo` do núcleo (`:where(...,a[href])`) porque nada aqui redeclara
   `min-height` para vencer essa herança, e `.cabeca` (o pai) não tem altura
   fixa que corte a caixa. */
.cabeca .marca {
  display: inline-flex; align-items: center; gap: .7rem;
  font-weight: 600; font-size: 1rem; letter-spacing: -.01em;
  color: var(--tinta); text-decoration: none;
}
/* ── O glifo perdeu o CAMPO  (23/09) ──────────────────────────────────────
   Era um quadradinho de 30px cheio de acento com a fogueira branca de 17px
   dentro — o ícone do aparelho encolhido. O dono: «o ícone fica empapado nos
   tamanhos pequenos… vira uma mancha». O campo cobrava duas vezes: de perto
   ele é um adesivo colado ao lado do texto (o mesmo veredito que o web clipper
   já tinha recebido em 20/09, ver `icons/marca-barra-v1.svg`), e de longe ele
   rouba 13 dos 30px que o desenho tinha para existir.

   Agora é SILHUETA: 26px de fogueira desenhada na cor do acento, sem fundo. O
   recorte do `viewBox` mora no glifo (`app.mjs`), não aqui.

   Contraste medido (≥3:1, WCAG 1.4.11 — é componente gráfico, não texto):
     claro  #832f0d × #e8e2d7 = 6,85:1
     sépia  #7c2c0b × #e4d4c3 = 6,53:1
     escuro #f39d7a × #14171a = 8,49:1
   O campo cheio não tinha essa conta: o que se media era o branco contra o
   acento, e o acento contra a tela ninguém olhava. */
.cabeca .glifo {
  width: 26px; height: 26px; flex: none;
  color: var(--acento);
  display: grid; place-items: center;
}
.cabeca .glifo svg { width: 26px; height: 26px; display: block; }
.cabeca .fim { margin-left: auto; display: flex; align-items: center; gap: .5rem; }
.cabeca #aa {
  font-family: var(--sans); font-size: .8rem; font-weight: 600;
  color: var(--tinta-2); background: var(--papel-elev); border: 1px solid var(--regra);
  border-radius: 999px; min-width: 44px; min-height: 36px; padding: 0 .8rem; cursor: pointer;
}
.cabeca #aa:hover, .cabeca #aa:focus-visible { color: var(--acento); border-color: var(--acento); }
/* `inline-flex` + `align-items` (revisão 2026-08-24): o link herda os 44px
   de `--alvo` do núcleo, e sem o flex o texto assentava no TOPO dessa caixa
   — o controle do canto flutuava acima da linha do `Aa` ao lado. Era o
   «Sair»; desde a spec 69 §2.1 é a «Conta», e o Sair mora no pé dela. */
.cabeca #conta-entrada { color: var(--tenue); text-decoration: none; padding: .5rem .2rem;
  display: inline-flex; align-items: center; }
.cabeca #conta-entrada:hover, .cabeca #conta-entrada:focus-visible { color: var(--acento); }
/* ── E o `[hidden]` de volta, o mesmo defeito da L-120  (23/09) ───────────
   `ajustarCabecalho` põe `hidden` no «Conta» quando não há sessão, e o
   `display: inline-flex` de autor logo acima vence o `[hidden] { display:
   none }` da folha do navegador. O efeito: a tela de ENTRADA oferecendo a
   conta a quem ainda não tem uma, no canto de cima. O JS estava certo, o
   atributo estava certo — só o pixel estava errado, que é a assinatura
   exata desta classe de defeito. As duas caixas do controle levam a guarda,
   porque ele muda de pai conforme a largura (`acomodarControles`). */
.cabeca #conta-entrada[hidden] { display: none; }

/* ── O «?» da tela  (spec 75) ────────────────────────────────────────────────
   Desenho de 24/1,7 como o globo ao lado, na tinta dos vizinhos. O alvo é o
   `--alvo` do núcleo (44px): o botão é pequeno de ver, não de tocar. O
   `[hidden]` leva guarda própria pela mesma razão do «Conta» logo acima — o
   `display` de autor venceria o da folha do navegador. */
.ajuda-botao {
  display: inline-grid; place-items: center;
  width: var(--alvo, 44px); height: var(--alvo, 44px); padding: 0;
  background: none; border: 0; border-radius: 999px; cursor: pointer;
  color: var(--tenue); font-size: 1.15rem;
}
.ajuda-botao[hidden] { display: none; }
.ajuda-botao:hover, .ajuda-botao:focus-visible { color: var(--acento); }
.ajuda-botao:focus-visible { outline: 2px solid var(--acento); outline-offset: 2px; }

/* ── A barra de baixo é o MESMO cromo da lateral  (02/09) ──────────────────
   Ela era vidro sobre a mesa: `--tela` a 82% com `backdrop-filter`. Isso fazia
   sentido enquanto o cromo do app inteiro era claro — e deixou de fazer no dia
   em que o Mac ganhou a lateral grafite. «No iPad aquela barra lá embaixo
   deveria ter sido na mesma cor grafite da barra lateral que aparece no
   MacBook» (Yuri, 02/09).

   É a mesma peça em duas diagramações — o mesmo `<nav>`, o mesmo DOM, a mesma
   ordem de leitura —, e uma peça que muda de MATERIAL conforme a largura da
   tela é duas peças. O vidro sai junto: sobre um campo escuro e opaco ele não
   tem o que borrar, e o `backdrop-filter` custa composição a cada quadro de
   rolagem no aparelho mais fraco dos dois.

   O gradiente é vertical numa faixa de 58px, então quase chapado — e é de
   propósito: são os mesmos dois tokens da lateral, e o dia em que a lateral
   mudar de tinta, esta muda junto. */
#barra-nav {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 40;
  padding-bottom: env(safe-area-inset-bottom);
  background: linear-gradient(180deg, var(--cromo-1), var(--cromo-2));
  border-top: 1px solid var(--cromo-borda);
  transition: transform var(--dur) var(--curva);
}
#barra-nav[hidden] { display: none; }
#barra-nav ul {
  list-style: none; margin: 0 auto; max-width: var(--measure); display: flex; gap: .2rem;
  padding: .3rem max(.6rem, env(safe-area-inset-right)) .3rem max(.6rem, env(safe-area-inset-left));
}
#barra-nav li { flex: 1; }
#barra-nav a {
  display: flex; flex-direction: column; align-items: center; gap: .18rem;
  text-decoration: none; color: var(--cromo-tinta-2);
  font-family: var(--sans); font-size: .66rem; font-weight: 500; letter-spacing: .01em;
  padding: .45rem .2rem; min-height: 52px; border-radius: var(--raio-p);
}
/* Ícone **e** rótulo. Ícone sozinho num app de um leitor só é adivinhação com
   estética: não há onboarding, não há tooltip no iPad, e o custo do rótulo são
   dez pixels de altura que a barra já tem de sobra para o alvo de 52px. */
/* SVG, não glifo de texto (revisão 2026-08-24): "▤" e "✦" eram fonte, e
   fonte muda de peso por família — os dois ícones da barra nunca tinham o
   mesmo traço. Os desenhos vivem em `ICONES` no app.mjs, na gramática do
   GLIFO; aqui só a caixa. */
#barra-nav a .ic { display: block; height: 21px; }
#barra-nav a .ic svg { width: 21px; height: 21px; display: block; }
#barra-nav a:hover, #barra-nav a:focus-visible { color: var(--cromo-acento); }

/* A contagem é da LATERAL, e não da barra — e desde 04/09 só das PRATELEIRAS,
   dentro da estante: os destinos (Inbox, Destaques, Estante, Escrivaninha)
   perderam o número, que contava uma partição diferente da que a tela lista
   («Inbox 31» com cinco na aba). A prateleira conta o que ela mesma mostra.

   Na barra inferior nenhuma contagem aparece: o item é uma coluna — ícone em
   cima, palavra embaixo —, então o número viraria uma TERCEIRA linha empilhada
   num alvo de 52px. A barra é para ir a algum lugar, não para saber quanto tem
   lá. */
#barra-nav a .conta { display: none; }

/* ── No Mac os três destinos saem da barra e vão para a LATERAL  (1e) ───────
   «Barra inferior é idioma de dedo, não de trackpad.» É a adaptação por
   plataforma mais concreta desta rodada, e ela é de CSS: o mesmo `<nav>`, o
   mesmo DOM, a mesma ordem de leitura — só a diagramação muda.

   O corte é 1100px e não 900px de propósito. O iPad em paisagem tem 1180pt e
   continua sendo um aparelho de dedo: pôr a lateral nele tiraria a navegação
   do alcance do polegar para ganhar nada. 1100px com `pointer: fine` pede as
   DUAS coisas — tela grande E apontador de precisão —, que juntas só
   descrevem um computador de mesa.

   `--barra-h` vai a zero aqui porque ele é a folga reservada EMBAIXO: com a
   barra na lateral, aquela faixa morta viraria um rodapé em branco. */
/* ── Este bloco vem ANTES da @media da lateral, e isso é de propósito ─────
   Ele e a regra do ativo lá dentro têm a MESMA especificidade (um id, um
   tipo, um atributo), e `@media` não empresta peso nenhum — quem vence é a
   última no arquivo. Enquanto este bloco ficou depois, o ativo da lateral
   grafite saía pintado com o acento do PAPEL e com o leito de 9% por cima do
   cromo. É o mesmo modo de falha que o comentário do `translateY(100%)`
   registra no fim da media query, e o remédio é o mesmo: ordem. */
/* O ativo, nos DOIS modos. `--cromo-acento` porque o campo é grafite em ambos
   — a brasa funda do tema claro mede 1,55:1 sobre ele e desaparece. O leito de
   branco a 7% substitui o tingido de acento a 9%: sobre escuro, quem levanta
   uma superfície é luz, não cor. */
#barra-nav a[aria-current="page"] {
  color: var(--cromo-tinta); font-weight: 600;
  /* 8%, não 9 (revisão 2026-08-24): com o sépia rosa-velho o tingido de
     acento deixou de sair salmão-por-acidente, e um ponto a menos devolve à
     pílula o peso de estado — presença que se nota ao procurar, não mancha
     que se nota antes do rótulo.

     2026-09-01 — volta a 9% (prancha 1d). A razão do desconto era o carmim
     virando salmão POR ACIDENTE sobre o papel rosado do sépia; a brasa é
     laranja-avermelhada de propósito, então o tingido quente deixou de ser
     acidente e passou a ser o desenho. O ponto devolvido é o que sustenta o
     que a prancha cobra: cor sozinha, no vidro, some contra papel claro
     visto em ângulo — o leito é o que salva o estado nessa condição.

     2026-09-02 — o tingido de acento sai e entra o véu de branco: o campo
     deixou de ser papel e virou grafite nos dois modos. */
  background: rgba(255,255,255,.07);
}
#barra-nav a[aria-current="page"] .ic { color: var(--cromo-acento); }

/* ── Este bloco vem ANTES da @media da lateral, e isso é de propósito ─────
   Terceira vez que a mesma armadilha aparece nesta rodada: a regra genérica e
   a da lateral têm a mesma especificidade (uma classe), `@media` não empresta
   peso, e quem vence é a última no arquivo. Enquanto este bloco ficou depois,
   o `.nav-rodape` da lateral nascia `display: none` — o `Aa`, o `Sair` e o
   carimbo simplesmente não apareciam no Mac, e o teste de CSS não pega isso
   porque as duas regras existem e as duas estão certas.

   A marca escapava por acidente: `#barra-nav a` (um id) tem especificidade
   maior que `.nav-marca` e a mantinha visível. Acidente que salva um dos três
   é pior que defeito que derruba os três. */
/* A marca, as prateleiras e o rodapé são da LATERAL. Na barra inferior eles
   caíam como texto solto e enorme embaixo dos três destinos — o `<p>` herdava
   a serifa do corpo porque a regra que os desenha vive na media query da
   lateral, e fora dela não havia regra nenhuma. Um elemento sem estilo não é
   um elemento discreto: é o estilo do documento aparecendo.

   O `.nav-rodape` entrou na lista em 02/09 e some com os irmãos — mas o que
   ele carrega NÃO some com ele: `Aa` e `Sair` já saíram daqui para a
   `.cabeca` antes da pintura (`acomodarControles`, em `app.mjs`), e o carimbo
   de versão continua no `#versao` do fluxo, que só se recolhe no modo
   lateral. Nenhum dos três aparece duas vezes na mesma tela, e nenhum
   desaparece das duas. */
/* `#barra-nav .nav-marca`, e não `.nav-marca` sozinha: desde 02/09 a marca é
   um `<a>`, e `#barra-nav a { display: flex }` (um id) vencia a classe — no
   iPad ela aparecia DENTRO da barra inferior, como um quarto destino gigante.
   Enquanto era um `<p>`, a regra curta bastava; o elemento mudou e a
   especificidade mudou com ele. */
#barra-nav .nav-marca, #nav-prateleiras, .nav-rodape { display: none; }

@media (min-width: 1100px) and (pointer: fine) {
  :root { --barra-h: 0px; }

  /* ── A lateral é CROMO, e cromo é grafite nos três temas  (02/09) ────────
     O que havia aqui: `--papel-elev-2` — um dos três beges que vivem dentro
     de 1,2:1 de razão uns dos outros (`--tela`, `--papel-elev-2`,
     `--papel-elev`). A coluna de navegação pintada com um deles é uma coluna
     que não se separa da mesa, e era essa a queixa que abriu a rodada: «são
     muitos tons pastéis sobrepostos».

     A saída é um corte de valor só — cromo escuro contra papel claro —, e ele
     responde «onde eu ando» × «o que eu leio» sem gastar cor nenhuma. Os
     tokens `--cromo-*` moram no núcleo do Scriptorium: é verdade de qualquer
     app, e a nota lá explica por que eles não mudam por tema.

     Os dois ajustes por tema abaixo são cosméticos, com uma exceção que não
     é: no ESCURO a mesa é `#14171a`, e o cromo tem de ficar um degrau mais
     CLARO que ela — no escuro a lateral não pode ser a parte mais funda da
     tela, senão ela deixa de ser objeto e vira buraco. */
  #barra-nav {
    top: 0; bottom: 0; right: auto; width: 236px;
    border-top: 0; border-right: 1px solid var(--cromo-borda);
    padding: 22px 0 16px; padding-left: env(safe-area-inset-left);
    overflow-y: auto;
    background: linear-gradient(180deg, var(--cromo-1), var(--cromo-2));
    backdrop-filter: none; -webkit-backdrop-filter: none;
    display: flex; flex-direction: column;
  }

  /* ── A marca volta a ser A MARCA  (era um rótulo de 10px) ────────────────
     No papel claro ela vivia na `.cabeca`, dentro da coluna de leitura, e a
     lateral só tinha o nome do app em versalete miúdo. Sobre grafite é ela
     que ancora a coluna: glifo de 30px e o nome em 16px, os mesmos da
     `.cabeca` — que some inteira neste modo, logo adiante.

     `--cromo-acento` é o acento do tema ESCURO em qualquer tema, e o glifo por
     cima dele é `--cromo-2`, a base do próprio gradiente. Sobre grafite a
     brasa funda do tema claro desapareceria. */
  #barra-nav .nav-marca {
    display: flex; align-items: center; gap: .7rem; flex: none;
    margin: 0; padding: 0 18px 18px;
    font: 600 16px/1 var(--sans); letter-spacing: -.01em;
    color: var(--cromo-tinta); text-decoration: none; text-transform: none;
  }
  /* Silhueta, como na `.cabeca` (23/09): o campo cheio saiu dos dois lugares
     juntos, porque é o mesmo glifo e vê-los diferentes lado a lado é o defeito
     que o campo existia para não causar.
     Medido: #f39d7a × #272c31 (cromo-1) = 6,65:1 · × #1b1e22 (cromo-2) = 7,90:1
     — e nos dois temas que redeclaram o grafite, 6,70:1 e 7,02:1. */
  .nav-marca .glifo {
    width: 26px; height: 26px; flex: none;
    color: var(--cromo-acento);
    display: grid; place-items: center;
  }
  .nav-marca .glifo svg { width: 26px; height: 26px; display: block; }

  #barra-nav ul {
    flex-direction: column; gap: 2px; max-width: none;
    padding: 0 12px;
  }
  #barra-nav li { flex: 0 0 auto; }
  /* Deitado: ícone à esquerda do rótulo, como qualquer lateral. O alvo de
     44px fica — ele é de acessibilidade, não de dedo. */
  #barra-nav a {
    position: relative;
    flex-direction: row; justify-content: flex-start; gap: 11px;
    font: 500 13.5px/1 var(--sans); letter-spacing: 0;
    padding: 11px 12px; min-height: 44px; border-radius: 8px;
    color: var(--cromo-tinta-2);
  }
  #barra-nav a .ic, #barra-nav a .ic svg { width: 20px; height: 20px; }
  #barra-nav a:hover, #barra-nav a:focus-visible {
    /* Véu de branco puro, e não uma cor: sobre cromo o realce é LUZ, e uma
       cor aqui teria de existir em três temas para dizer a mesma coisa. */
    background: rgba(255,255,255,.045); color: var(--cromo-tinta);
  }
  /* O ativo é fundo + peso + ícone no acento + filete colado à esquerda. São
     quatro pistas porque o leito sozinho, sobre grafite, é sutil demais — e
     porque nenhuma delas é cor apenas. */
  /* O leito, o peso e o ícone acentuado do ativo vêm do bloco global (o cromo
     é o mesmo nos dois modos). O que a lateral acrescenta é o FILETE: numa
     coluna vertical ele marca a linha inteira, e na barra horizontal de 58px
     não haveria onde pousá-lo. */
  #barra-nav a[aria-current="page"]::before {
    content: ""; position: absolute; left: 0; top: 9px; bottom: 9px;
    width: 2px; border-radius: 2px; background: var(--cromo-acento);
  }
  /* A contagem das prateleiras é informação (mesma tese do `--tenue`), então
     responde ao piso de 4.5:1 como qualquer texto — `--cromo-tenue` está
     medido contra os dois extremos do gradiente. No ativo ela sobe junto com a
     linha. */
  #barra-nav a .conta {
    display: block;
    margin-left: auto; font: 500 11.5px/1 var(--sans); color: var(--cromo-tenue);
    font-variant-numeric: tabular-nums;
  }
  #barra-nav a[aria-current="page"] .conta {
    color: color-mix(in srgb, var(--cromo-tinta) 78%, transparent); opacity: 1;
  }

  .nav-titulo {
    font: 600 10px/1 var(--sans); letter-spacing: .12em; text-transform: uppercase;
    color: var(--cromo-tenue); margin: 0; padding: 18px 18px 8px;
  }
  /* As prateleiras não têm ícone: são recortes do mesmo acervo, não destinos.
     O recuo é o que diz isso sem precisar de palavra. */
  #nav-prateleiras ul { padding: 0 12px; }
  #nav-prateleiras a {
    padding: 9px 12px 9px 33px; font: 500 12.5px/1 var(--sans);
    min-height: 38px; border-radius: 7px; color: var(--cromo-tinta-2);
  }
  #nav-prateleiras[hidden] { display: none; }

  /* ── O rodapé da lateral: `Aa`, `Sair` e o carimbo  (02/09) ──────────────
     Os dois controles que NÃO são navegação moravam na `.cabeca`, dentro da
     coluna de leitura. Aqui eles descem para o pé do cromo, que é onde se
     procura o que configura o app — e a `.cabeca` some, porque tudo o que ela
     carregava passou a ter casa melhor.

     `margin-top: auto` cola o bloco no fim da coluna; é o que faz o rodapé ser
     rodapé mesmo com três destinos e nenhuma prateleira. */
  .nav-rodape {
    margin-top: auto; flex: none;
    display: flex; align-items: center; gap: .6rem; flex-wrap: wrap;
    padding: 14px 18px 0; margin-left: 0; margin-right: 0;
    border-top: 1px solid var(--cromo-borda);
  }
  .nav-rodape #aa {
    font: 600 12px/1 var(--sans); color: var(--cromo-tinta);
    background: rgba(255,255,255,.06); border: 1px solid rgba(255,255,255,.1);
    border-radius: 999px; min-width: 0; min-height: 32px; padding: 0 12px;
    cursor: pointer;
  }
  .nav-rodape #aa:hover, .nav-rodape #aa:focus-visible {
    color: var(--cromo-acento); border-color: var(--cromo-acento);
  }
  .nav-rodape #conta-entrada {
    font: 500 12px/1 var(--sans); color: var(--cromo-tenue);
    text-decoration: none; padding: 0; min-height: 32px;
    display: inline-flex; align-items: center;
  }
  .nav-rodape #conta-entrada[hidden] { display: none; }
  /* O «?» no rodapé grafite (spec 75): o tamanho e a tinta do globo. */
  /* Na lateral o `Aa` fica só com o glifo: a palavra do rótulo («Texto»)
     some, e o nome inteiro segue no `aria-label` e no `title` (25/09). */
  .nav-rodape #aa .aa-palavra { display: none; }
  /* O «?» no rodapé grafite (spec 75). 28px, e não os 32 do globo de antes:
     com ele a fileira passou a ter quatro controles, e «Conta» caía para a
     linha de baixo (25/09). Medido nas cinco línguas — o pior é «Aa Testo» +
     «Account» — em `harness-ajuda.html?lateral=1`. O `min-height: 0` desfaz
     o `--alvo` de 44px do núcleo, que o fazia mais alto que os vizinhos. */
  .nav-rodape .ajuda-botao { width: 28px; height: 28px; min-height: 0; color: var(--cromo-tenue); }
  .nav-rodape .ajuda-botao:hover, .nav-rodape .ajuda-botao:focus-visible { color: var(--cromo-acento); }
  .nav-rodape #conta-entrada:hover, .nav-rodape #conta-entrada:focus-visible { color: var(--cromo-acento); }
  /* O carimbo responde «a versão que estou vendo é a que subiu?», e ele é
     lido com ATENÇÃO quando alguém pergunta — por isso ele não desce de cor
     para se recolher (o `#versao` do fluxo já recusou `opacity` pela mesma
     razão): quem o recolhe é o tamanho. */
  .nav-rodape .nav-versao {
    flex-basis: 100%; font: 500 10.5px/1.4 var(--sans); letter-spacing: .05em;
    color: var(--cromo-tenue); font-variant-numeric: tabular-nums;
  }

  /* ── A `.cabeca` e o `#versao` do fluxo somem  (02/09) ───────────────────
     Tudo o que os dois carregavam mora agora no cromo: a marca no topo da
     lateral, o `Aa` e o `Sair` no rodapé dela (movidos de pai por
     `acomodarControles`, não copiados), e o carimbo ao pé. Deixá-los na tela
     seria a marca duas vezes e o carimbo duas vezes.

     A folga que o `#versao` reservava embaixo não se perde: ela era
     `--barra-h`, e `--barra-h` é 0 aqui — não há barra sob a qual o fim da
     lista possa cair. */
  body[data-dentro] .cabeca,
  body[data-dentro] #versao { display: none; }

  /* O conteúdo abre espaço para a lateral. `margin`, e não `padding`, para o
     `max-width: var(--measure)` do `main` seguir medindo a COLUNA e não a
     coluna mais a barra — a medida da linha é o ativo mais protegido deste
     app, e some sem avisar se a conta mudar de base. */
  body[data-dentro] main { margin-left: 236px; }
  /* O cromo escondido leva esta lateral para o LADO, e não para baixo — mas a
     regra que faz isso **não mora aqui**: ela mora na seção do cromo, adiante,
     logo depois da regra do modo barra. A razão é de cascata, não de arrumação
     (2026-09-02): as duas têm a mesma especificidade, então quem vence é a
     última no arquivo — e enquanto esta ficou aqui em cima, o `translateY(100%)`
     de baixo venceu sempre. A lateral sumia deslizando para BAIXO, que é o
     gesto errado para uma barra vertical, e ninguém notou porque some de
     qualquer jeito. Estar dentro de uma `@media` não empresta peso nenhum. */
}

/* ── conteúdo ────────────────────────────────────────────────────────────── */
main {
  max-width: var(--measure);
  margin: 0 auto;
  /* A folga da barra fixa saiu daqui e foi para o `#versao` (L-71): quem
     precisa dela é o ÚLTIMO elemento do fluxo, e o último passou a ser o
     carimbo de versão, não o `main`. Mantida aqui, o carimbo cairia atrás da
     barra — e a folga apareceria duas vezes, uma em cada elemento. */
  padding: 1.6rem max(1.1rem, env(safe-area-inset-right)) 1.5rem max(1.1rem, env(safe-area-inset-left));
}

/* ── o carimbo do build  (L-71) ───────────────────────────────────────────
   Responde a uma pergunta só, e a pergunta é operacional: «a versão que estou
   vendo é a que subiu?». Ela apareceu do jeito caro — botões novos que não
   apareciam no iPad, sem como distinguir "o deploy não pegou" de "o cache é
   velho" de "o código está errado". Sem carimbo, essas três hipóteses custam
   uma sessão de depuração cada.

   Alinhado à direita e em 10px: é para ser CONFERIDO quando alguém pergunta,
   não lido no caminho. E sem `opacity` — o que o recolhe é o tamanho, não a
   transparência, que tiraria contraste justamente de um texto cuja única
   função é ser lido com atenção. Mesma decisão registrada no `.versao` do
   Tabula. */
#versao {
  max-width: var(--measure);
  margin: 0 auto;
  padding: 0 max(1.1rem, env(safe-area-inset-right)) calc(var(--barra-h) + 1.5rem) max(1.1rem, env(safe-area-inset-left));
  font-family: var(--sans); font-size: 10px; letter-spacing: .06em;
  font-variant-numeric: tabular-nums; color: var(--tenue); text-align: right;
}
/* Sem regra `:empty` de propósito, e a razão é a garantia acima dele: este
   elemento é o ÚLTIMO do fluxo, então é o padding DELE que impede o fim da
   lista de ficar debaixo do vidro da barra. Escondê-lo quando vazio faria a
   folga sumir junto — e sumiria justamente no caso em que o `app.mjs` não
   rodou, que é quando a tela já está estranha e ninguém suspeitaria do CSS.
   Vazio ele não mostra nada; só reserva o fim, que é o trabalho. */
/* Na rota de leitura, quem contém a coluna é a folha (`.artigo`), não o
   `main` — ela precisa ser mais larga que `--measure` para sobrar respiro
   dos dois lados (§1). Sem isto o `main` travaria a folha em `--measure`
   antes de o respiro entrar em cena, e a folha nasceria do mesmo tamanho do
   texto que carrega — apertada, não pousada. `data-rota` já existe no
   `<body>` para exatamente este tipo de regra (ver `app.mjs:160`). */
/* ── `data-leitura`, e não mais `data-rota="artigo"`  (spec 23 §6.3) ────────
   Estas regras nunca perguntaram «que rota é esta?»; perguntavam «esta tela é
   de leitura?» — e enquanto houve uma só tela de leitura, as duas perguntas
   tinham a mesma resposta. A escrivaninha põe uma segunda: a rota `/e/:id` É o
   leitor de artigo, montado sobre o documento da etapa, e ela precisa da
   tipografia, do sumário, da narração e do cromo que some ao rolar.
   Duplicar quinze seletores em `[data-rota="estudo"]` seria manter duas listas
   que precisam concordar para sempre. O atributo passa a nomear o que a regra
   de fato quer saber, e quem o escreve é `aoNavegar`, a partir da própria
   tabela de rotas — uma tela de leitura nova o ganha declarando `leitura:
   true`, e não editando CSS. */
body[data-leitura] main { max-width: none; padding: 0; }
main h1 { font-size: 1.5em; line-height: 1.25; margin: 0 0 .3em; }
main p { margin: 0 0 var(--space-para); }
.sub { color: var(--tinta-2); font-family: var(--sans); font-size: .82rem; }
.vazio { color: var(--tinta-2); font-style: italic; padding: 3rem 0; text-align: center; }

/* ── tela de entrada (L-69) ────────────────────────────────────────────────
   A única tela em que o app se apresenta, e a primeira que um aparelho novo
   vê. É aqui que a direção investe: ícone grande, botão com alvo de 52px e um
   lençol de cor ao fundo. Nada disto contraria a 02 §1 — ela fala da tela de
   leitura (D3), e esta é o oposto dela.

   ── A NOITE  (23/09, com o nome Lareia) ──────────────────────────────────

   *Lareira* + *leia*: o nome é o convite a ler junto ao fogo, e fogo não se vê
   de dia. A tela de entrada deixa de ser papel e passa a ser o céu da
   ilustração que o dono gerou (`B01 Projects/Leitor/Imagens/Lareia 4.png`),
   servida em `/imagens/lareia-fogueira-v1.webp`.

   ── POR QUE A COR MORA EM TOKEN PRÓPRIO, E NÃO NO TEMA ────────────────────

   Os oito `--entrada-*` valem igual nos três temas, e isso é a decisão, não um
   descuido. Quem vê esta tela ainda não entrou: não há preferência de leitura
   para respeitar, há uma MARCA para apresentar — e uma marca que muda de cor
   conforme o sistema de quem chega não é marca. O resto do app continua
   inteiramente a cargo do tema; nada aqui vaza para fora do `[data-entrada]`.

   Em TOKEN e não em literal pela razão de sempre nesta folha: o harness de
   contraste lê token, nunca `background` cravado em regra (ver a nota do
   `--foco` em `[data-tema="claro"]`). `entrada-css.test.mjs` mede estes oito.

   ── O GRAFITE, E NÃO MAIS O VERDE  (25/09) ────────────────────────────────

   A noite nasceu no verde-azulado do céu da ilustração (#0b1f23 → #13282b).
   Ficava bonita e ficava DIFERENTE do tema escuro do app — quem entra saía de
   uma noite verde para uma mesa grafite. Pedido do dono: «deixar no tom mais
   grafite do nosso tema escuro». O céu passa a ser o grafite do tema (a
   `--tela` escura descendo ao `--cromo-2`); a ilustração, que é arte, fica
   como é, e a brasa também.

   ── CONTRASTE MEDIDO, contra o pé do gradiente (`#191c20`, o mais claro) ──

     título    #f7f1e8 × #191c20 = 15,23:1    (piso 4,5)
     subtítulo #c4c0b8 × #191c20 =  9,43:1    (piso 4,5)
     rodapé    #a09d96 × #191c20 =  6,32:1    (piso 4,5 — é informação)
     botão     #e3a577 × #191c20 =  8,07:1    (piso 3, contorno/superfície)
     no botão  #16171a × #e3a577 =  8,46:1    (piso 4,5)

   O botão ANTIGO era `--acento` sobre papel claro; sobre a noite ele reprovava
   (#832f0d × o céu = ~1,2:1, invisível). A brasa `#e3a577` é a luz do fogo
   da própria ilustração, e é ela que passa nos dois papéis: como superfície
   contra o céu e como fundo do texto escuro que ela carrega.

   ── E O MESMO, MEDIDO NO PIXEL  (`interacao-entrada.mjs`, 23/09) ──────────

   Os números acima são dos TOKENS, e token certo com regra que não casa dá
   tela errada com teste verde. A sonda abre a tela num navegador de verdade,
   lê a tinta do `getComputedStyle` e amostra o fundo na captura, ao lado de
   cada linha. O que ela vê difere do papel — o gradiente muda com a altura, e
   o lençol de brasa passa por baixo de duas linhas —, e é por isso que ela
   existe:

     título     #f7f1e8 × #181b1e = 15,40:1
     subtítulo  #c4c0b8 × #171a1e =  9,63:1
     botão      #16171a × #e3a577 =  8,46:1
     rodapé     #a09d96 × #191c20 =  6,32:1
     (25/09, no grafite, Chrome headless: o Safari tem a Automação Remota
     desligada, e a sonda que o abriria roubaria a tela do dono. O pior de
     três pontos atrás de cada linha, com o texto apagado. Com o halo de raio
     menor, nenhuma linha fica mais sobre o lençol.)
   ───────────────────────────────────────────────────────────────────────── */
/* As boas-vindas (spec 75 §6) vestem a mesma noite: são a marca se
   apresentando, com a prancha e o botão desta tela. A vitrine (spec 78) veste
   os mesmos oito tokens nas duas faixas dela, pelo seletor alargado; o fundo
   dela é o do cromo, na seção da vitrine, no fim. */
body[data-entrada], .boas-vindas, .vitrine-noite {
  /* O GRAFITE do tema escuro (25/09), e não mais o verde-noite da
     ilustração: o céu é a `--tela` escura (#14171a) descendo ao `--cromo-2`
     (#191c20), a mata é o `--papel` escuro, e as duas tintas secundárias são
     os cinzas quentes do tema, um degrau mais claros para ler sob o halo. */
  --entrada-ceu-alto: #14171a;
  --entrada-ceu-baixo: #191c20;
  --entrada-mata: #16171a;
  --entrada-brasa: #e3a577;
  --entrada-sobre-brasa: #16171a;
  --entrada-tinta: #f7f1e8;
  --entrada-tinta-2: #c4c0b8;
  --entrada-tenue: #a09d96;
  background: linear-gradient(180deg, var(--entrada-ceu-alto) 0%, var(--entrada-ceu-baixo) 100%)
    var(--entrada-ceu-alto);
  /* `fixed`: sem isto o gradiente termina na altura do CONTEÚDO, e num monitor
     alto sobraria uma faixa da cor de fundo abaixo dele. */
  background-attachment: fixed;
  color: var(--entrada-tinta);
}
/* ── O que MAIS aparece nesta tela ────────────────────────────────────────
   Deslogado, a barra de navegação some inteira e a `.cabeca` fica (é a regra
   «sem sessão a barra some INTEIRA, e a identidade fica», guardada em
   `artigo.test.mjs`). Ela e o carimbo de versão herdariam a tinta do TEMA —
   escura, nos dois temas claros — e sumiriam na noite. Duas linhas resolvem, e
   as duas seguem medidas contra o topo do céu (`#14171a`):
     nome da marca #f7f1e8 × #14171a = 16,02:1
     glifo         #e3a577 × #14171a =  8,49:1
     carimbo       #a09d96 × #14171a =  6,65:1                              */
body[data-entrada] .cabeca .marca { color: var(--entrada-tinta); }
body[data-entrada] .cabeca .glifo { color: var(--entrada-brasa); }
body[data-entrada] #versao { color: var(--entrada-tenue); }
#login {
  min-height: 62vh; display: flex; flex-direction: column; justify-content: center;
  align-items: center; text-align: center; position: relative;
}
/* O lençol: um halo da brasa atrás da prancha. `pointer-events: none` porque
   ele cobre o botão — um brilho que engole o toque é o defeito mais bobo
   possível na única tela que precisa de um toque só.
   22% e não 15%: sobre a noite um lençol de 15% não se vê.

   O raio é 40% × 48% da caixa, e não 60% × 60% (25/09, na troca para o
   grafite): com 60%, o halo ainda não tinha se apagado onde a caixa acaba —
   nas laterais, onde o `overflow-x: clip` do `main` o corta, e no topo, onde
   ela começa —, e a tela mostrava um retângulo de bordas retas. O verde
   disfarçava; o grafite não. A conta: a caixa tem 160% da largura do
   `#login`, e o fim do gradiente (70% do raio) cai a 0,4 × 0,7 × 1,6 = 45% da
   largura do `#login` a partir do centro, antes da borda do corte (50%); no
   alto, a 0,48 × 0,7 = 34% da altura da caixa, que é onde o centro está. */
#login::before {
  content: ""; position: absolute; inset: -10% -30% auto -30%; height: 70%;
  pointer-events: none;
  background: radial-gradient(40% 48% at 50% 34%,
    color-mix(in srgb, var(--entrada-brasa) 22%, transparent), transparent 70%);
}
/* ── O lençol não pode empurrar a largura da página  (medido em 23/09) ────
   `inset: … -30% … -30%` põe o halo 30% para fora do `#login` dos dois lados —
   e o que está fora à DIREITA conta para o `scrollWidth`. No telefone isso dava
   531px de rolagem numa tela de 430: a página deslizava de lado, e o defeito é
   anterior a esta rodada (os insets não mudaram). Apareceu agora porque a sonda
   passou a medi-lo.

   Recorta-se no `main`, e não no `#login`: no `#login` o corte pegaria também a
   sombra da prancha, que é o que a descola do céu. E `clip`, não `hidden` —
   `hidden` faria do `main` um contêiner de rolagem, e um contêiner de rolagem
   novo no meio da árvore muda onde o teclado do iPad rola. O que se perde no
   corte é a cauda do halo, que ali já é transparente. */
body[data-entrada] main { overflow-x: clip; }
/* O lençol é um elemento POSICIONADO e o primeiro filho: sem esta linha ele
   pintaria POR CIMA de todo irmão em fluxo, e um véu de brasa sobre as letras
   tira contraste de texto que já foi medido. Posicionar os irmãos os põe depois
   dele na ordem de pintura, sem stacking context novo.

   Ele continua ATRÁS do texto, e isso contava: no verde, a sonda media o
   subtítulo contra o céu com o lençol por baixo (6,96:1, e não 9,51). Desde o
   raio menor (25/09) o lençol já se apagou quando chega ao subtítulo, e o
   pixel dá o céu puro — mas a medição continua no pixel, porque é ali que um
   raio mexido de novo apareceria. */
#login > * { position: relative; }
/* ── A PRANCHA ────────────────────────────────────────────────────────────
   A ilustração entra como FAIXA acima da marca, e não como fundo da tela
   inteira com um véu escuro por cima. As duas versões foram desenhadas; esta
   ganhou por uma razão que não é de gosto: com a imagem atrás do texto, o
   contraste de cada linha passa a depender do PIXEL que calhou de ficar
   embaixo dela — a fogueira tem um núcleo quase branco —, e um contraste que
   só vale para o enquadramento de hoje é um contraste que ninguém mede.
   Acima do título, cada letra pousa no céu liso, e os cinco números do
   cabeçalho desta seção valem sempre.

   `background` de um bloco vazio, e não `<img>`: é decoração (o `<h1>` logo
   abaixo diz o nome), e `aria-hidden` no `app.mjs` fecha a conta.

   `aspect-ratio` 16/9 é a proporção do arquivo (1600×900): a imagem entra
   inteira, sem corte, em qualquer largura. */
:is(#login, .boas-vindas) .cena, .vitrine .cena {
  width: 100%; max-width: 30rem; aspect-ratio: 16 / 9;
  margin: 0 0 1.7rem; border-radius: 18px; flex: none;
  background: var(--entrada-mata) center / cover no-repeat
    url("/imagens/lareia-fogueira-v1.webp");
  box-shadow: 0 18px 44px rgba(0, 0, 0, .45);
  /* O fio quente no contorno: sem ele a prancha escura sobre céu escuro perde
     a borda de cima e parece um buraco, não uma imagem. */
  outline: 1px solid color-mix(in srgb, var(--entrada-brasa) 20%, transparent);
  outline-offset: -1px;
}
#login .icone {
  width: 76px; height: 76px; border-radius: 20px; margin: 0 0 1.2rem; display: block;
  /* Sobre a noite o campo de brasa funda do ícone (#832f0d) encosta no fundo:
     o halo o descola, e é ele que faz o azulejo continuar sendo objeto. */
  box-shadow: 0 10px 30px color-mix(in srgb, var(--entrada-brasa) 26%, transparent);
}
#login h1 {
  font-family: var(--serif); font-size: 1.85em; font-weight: 600; line-height: 1.2;
  letter-spacing: -.02em; margin: 0 0 .5rem; color: var(--entrada-tinta);
}
#login .sub {
  font-size: .94rem; max-width: 23em; line-height: 1.55; margin: 0 0 2.2rem;
  color: var(--entrada-tinta-2);
}
/* Botão, e não link de texto: 52px de alvo, fundo de brasa e a cor de cima
   vinda de `--entrada-sobre-brasa` — nunca `#fff`, que sobre a brasa dá
   2,12:1. */
:is(#login, .boas-vindas) .entrar {
  display: inline-flex; align-items: center; justify-content: center;
  font-family: var(--sans); font-size: .95rem; font-weight: 600;
  color: var(--entrada-sobre-brasa); background: var(--entrada-brasa);
  border: 0; border-radius: var(--raio); text-decoration: none;
  padding: 0 2.4rem; min-height: 52px; min-width: 14rem; cursor: pointer;
  box-shadow: 0 6px 20px color-mix(in srgb, var(--entrada-brasa) 30%, transparent);
}
:is(#login, .boas-vindas) .entrar:hover, :is(#login, .boas-vindas) .entrar:focus-visible { filter: brightness(1.08); }
:is(#login, .boas-vindas) .entrar:focus-visible { outline: 3px solid var(--entrada-tinta); outline-offset: 3px; }

/* ── As boas-vindas  (spec 75 §6) ───────────────────────────────────────────
   Tela cheia sobre o app, na noite da entrada, uma vez por aparelho. Rola por
   dentro no telefone baixo (o «Começar» nunca some), e as quatro safe areas
   entram pelo `max()`, como no resto do cromo. Acima da barra (40) e das
   folhas (80): enquanto ela está aberta, nada mais responde. */
.boas-vindas {
  position: fixed; inset: 0; z-index: 90; overflow-y: auto;
  display: grid; place-items: center; text-align: center;
  padding: max(1.5rem, env(safe-area-inset-top)) max(1.25rem, env(safe-area-inset-right))
    max(1.5rem, env(safe-area-inset-bottom)) max(1.25rem, env(safe-area-inset-left));
  animation: boas-vindas-chega .5s var(--curva, ease-out) both;
}
.boas-vindas-conteudo {
  width: min(30rem, 100%); display: flex; flex-direction: column; align-items: center;
}
.boas-vindas h2 {
  font-family: var(--serif); font-size: 1.85rem; font-weight: 600; line-height: 1.2;
  letter-spacing: -.02em; margin: 0 0 .4rem; color: var(--entrada-tinta);
}
.boas-vindas-lema {
  font-family: var(--serif); font-style: italic; font-size: 1.15rem; line-height: 1.4;
  margin: 0 0 1.2rem; color: var(--entrada-brasa);
}
.boas-vindas-corpo p {
  font-family: var(--sans); font-size: .98rem; line-height: 1.6; max-width: 26em;
  margin: 0 auto .9rem; color: var(--entrada-tinta-2);
}
.boas-vindas-corpo .boas-vindas-fecho { color: var(--entrada-tinta); font-weight: 600; margin-bottom: 1.8rem; }
@keyframes boas-vindas-chega { from { opacity: 0; } to { opacity: 1; } }
@media (prefers-reduced-motion: reduce) { .boas-vindas { animation: none; } }
#login .rodape {
  font-family: var(--sans); font-size: .75rem; color: var(--entrada-tenue); margin: 1.6rem 0 0;
}
/* «Continuar com a Apple» (spec 74 item 0.6), só no casco que a oferece. A HIG
   da Apple pede o botão branco sobre fundo escuro (a noite da entrada), o
   título e a fonte do sistema, e o logotipo à esquerda do título — por isso
   aqui não entra a brasa: o botão é da Apple, não da Lareia. Preto sobre
   branco, 21:1. */
#login .entrar-apple {
  gap: .45rem; font-family: -apple-system, system-ui, var(--sans); font-weight: 600;
  color: #000; background: #fff; box-shadow: 0 6px 20px rgb(0 0 0 / .25);
}
#login .entrar-apple .logo-apple { font-size: 1.15em; line-height: 1; transform: translateY(-.06em); }
#login .entrar-apple:disabled { opacity: .7; cursor: progress; }
/* O e-mail das contas da casa, embaixo e menor (31 §3), com alvo de 44px. */
#login .entrar-email {
  display: inline-flex; align-items: center; min-height: 44px; margin-top: .6rem;
  font-family: var(--sans); font-size: .88rem; color: var(--entrada-tinta-2);
  text-underline-offset: .2em;
}
#login .entrar-email:focus-visible { outline: 3px solid var(--entrada-tinta); outline-offset: 3px; }
#login .aviso-entrada {
  font-family: var(--sans); font-size: .85rem; line-height: 1.5; max-width: 23em;
  color: var(--entrada-tinta); margin: .6rem 0 0;
}
#login .aviso-entrada:empty { display: none; }

/* ── inbox e clusters (L-47, L-67) ─────────────────────────────────────────
   **O título do item é serifado; o resto da lista não** (02 §2.1, D4). A regra
   antiga — "navegar é varrer, ler é demorar" — punha a lista inteira em sans, e
   continua valendo para resumo, crédito e rótulo, que são navegação. O título
   volta à Literata porque ele não é rótulo: é o começo da leitura, e é por ele
   que se decide abrir.

   Os tokens de tamanho da coluna (`--measure`) valem aqui também — a lista não
   fica larga num monitor grande, porque varrer uma linha de 140 caracteres é
   pior que rolar.
   ───────────────────────────────────────────────────────────────────────── */

/* ── Controle segmentado: um alvo, três opções, estado sempre visível ──────
   As três abas com filete embaixo da palavra dependiam de 2px para dizer onde
   se está — e de relance, no iPad, custavam um segundo olhar. */
.abas.seg {
  display: flex; gap: .15rem; margin: 0 0 1rem;
  background: var(--papel-elev-2); border-radius: var(--raio-p); padding: .22rem;
  font-family: var(--sans);
}
.abas.seg .aba {
  flex: 1; text-align: center; text-decoration: none; color: var(--tinta-2);
  font-size: .82rem; font-weight: 500; padding: .5rem .4rem; min-height: 38px;
  border-radius: 6px; display: flex; align-items: center; justify-content: center;
}
.abas.seg .aba:hover, .abas.seg .aba:focus-visible { color: var(--acento); }
/* O ativo é uma superfície que sobe do trilho, não uma cor de texto: é o que o
   dedo procura, e sobrevive a qualquer tema. */
.abas.seg .aba.ativa {
  background: var(--papel-elev); color: var(--tinta); font-weight: 600;
  /* pousada: sobe do trilho, não do papel — a mais rasa das superfícies que
     usavam --sombra crua. Os degraus do núcleo já são o box-shadow inteiro
     (duas camadas), não uma cor a compor — por isso o token substitui a
     declaração toda, não só a cor. */
  box-shadow: var(--sombra-pousada);
}

.clusters { font-family: var(--sans); font-size: .82rem; margin: 0 0 1.4rem; }
.clusters .fileira {
  display: flex; gap: .4rem; overflow-x: auto; scrollbar-width: none; padding-bottom: .2rem;
}
.clusters .fileira::-webkit-scrollbar { display: none; }

/* Borda em --borda-controle, não --regra (§2): o fundo próprio (--papel-elev
   sobre --tela) mede só 1,09–1,29:1 — tom demais para contar como pista, de
   longe abaixo do piso de 3:1 — então a borda é a única coisa que diz "isto
   é um chip", e precisa do piso que --regra não garante. */
.chip { display: inline-flex; align-items: center; gap: .4rem; flex: none;
  text-decoration: none; font-size: .79rem; font-weight: 500;
  color: var(--tinta-2); background: var(--papel-elev); border: 1px solid var(--borda-controle);
  border-radius: 999px; padding: .42rem .8rem; min-height: 34px; white-space: nowrap; }
.chip:hover, .chip:focus-visible { color: var(--acento); border-color: var(--acento); }
/* O chip ativo veste a matiz do PRÓPRIO tema, e não o acento: é o que impede a
   fileira de dizer "cyber" com a cor do app. Sem `--t` — cluster fora da
   tabela e sem hash — cai no acento, que é o comportamento de antes. */
.chip.ativo {
  color: var(--tinta); border-color: var(--t, var(--acento));
  background: color-mix(in srgb, var(--t, var(--acento)) 10%, var(--papel-elev));
}
.chip .ponto { width: 7px; height: 7px; border-radius: 50%; flex: none;
  background: var(--t, var(--tenue)); }
.chip .conta { color: var(--tenue); font-variant-numeric: tabular-nums; font-size: .74rem; }
/* O chip do tema como BOTÃO (spec 73 §5.5): no rodapé do artigo e no
   frontispício ele abre o lápis com o foco em «Tema». O `<button>` não herda
   a fonte nem o cursor; o resto é o `.chip` de sempre, com o ponto da matiz. */
button.chip { font-family: inherit; cursor: pointer; }

.lista { list-style: none; margin: 0; padding: 0;
  display: flex; flex-direction: column; gap: .6rem; }
/* O cartão (D3). O filete de 1px que separava os itens virou a borda de uma
   superfície própria: a diferença é que agora o alvo do dedo tem contorno, e no
   iPad um alvo com contorno é um alvo que se acerta.

   Borda em --borda-controle, não --regra (Onda 3, correção): o `.item` mora
   sobre `--tela` (a mesa, ver `body` acima), e `--regra` × `--tela` mede
   1,003:1 no claro e 1,001:1 no sépia — o contorno que este comentário
   promete tinha sumido de novo, coincidência de cor entre os dois tokens, não
   escolha. `--borda-controle` é o token que o núcleo já garante com piso 3:1
   contra as três superfícies (3,359 claro / 3,631 sépia / 4,570 escuro contra
   --tela) — o mesmo caso que `.chip` já resolve dois parágrafos abaixo, e o
   card inteiro É o alvo do dedo, exatamente o que `--borda-controle` existe
   para marcar. */
/* ── A LOMBADA virou a pista, e a borda saiu do caminho  (02/09) ───────────
   O comentário acima conta que a borda subiu de `--regra` para
   `--borda-controle` porque o contorno sumia contra a mesa. O contorno voltou
   a aparecer e a lista ficou com um retângulo cinza em volta de cada cartão —
   catorze deles numa tela, todos do mesmo peso. Era a metade cara da queixa
   «os cards são sem graça»: peso igual em tudo é ausência de hierarquia.

   O que entra no lugar são DUAS pistas, e nenhuma delas é a borda:

     · a **lombada** de 3px na matiz do tema, colada à esquerda. Ela é a mesma
       cor que a sobrancelha já usa, então não é vocabulário novo — é a cor do
       cluster ganhando corpo. E é a razão pela qual baixar a borda é legítimo:
       o piso de 3:1 vale para borda que é a ÚNICA pista de controle, e aqui
       ela deixou de ser;
     · a **sombra**, que é o que o núcleo já manda usar para separar folha de
       mesa (a nota de `--papel-borda`: «é a sombra que separa a folha da mesa,
       não o contraste de cor»). O cartão pousa em `--sombra-pousada` e sobe
       para `--sombra-erguida` no hover — o mesmo par das `.abas.seg`.

   A lombada é OBRIGATÓRIA. Cluster fora da tabela e sem hash cai no acento,
   como o `.chip` já faz, e `inbox.test.mjs` cobra que todo `.item` tenha cor
   resolvida: sem ela o cartão fica sem pista nenhuma, que é pior do que
   estava antes.

   `overflow: hidden` para o raio de 12px cortar a faixa nos dois cantos da
   esquerda; sem ele a lombada é um retângulo que escapa pela quina. */
.item {
  background: var(--papel-elev); border: 1px solid var(--papel-borda-fina);
  border-radius: var(--raio); box-shadow: var(--sombra-pousada);
  padding: 17px 20px 15px 23px; position: relative; overflow: hidden;
}
.item:hover { box-shadow: var(--sombra-erguida); }
.item .lombada {
  position: absolute; left: 0; top: 0; bottom: 0; width: 3px;
  background: var(--t, var(--acento));
}
.item .alvo { display: block; text-decoration: none; color: inherit; }
/* A sobrancelha: versalete na matiz do tema. Ela é o segundo lugar onde a cor
   do cluster aparece, e o primeiro em que ela vem com a palavra junto — é
   assim que o olho aprende a associar as duas. */
/* A sobrancelha e o CRÉDITO dividem a primeira linha (02/09). O crédito
   («fonte · minutos · data») é procedência, e procedência pertence ao alto do
   cartão, junto do tema — embaixo ele disputava a linha com a barra de
   progresso e cinco botões, e era o primeiro a ceder com reticências.
   `align-items: baseline` porque são duas tipografias de tamanhos diferentes
   na mesma linha: o que tem de alinhar é a base das letras, não as caixas. */
.item .eyebrow {
  display: flex; align-items: baseline; gap: 10px; margin: 0 0 7px;
  font-family: var(--sans);
}
.item .eyebrow .temas {
  font-size: 10px; font-weight: 600; letter-spacing: .11em; text-transform: uppercase;
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.item .eyebrow a { color: var(--t, var(--tenue)); text-decoration: none; }
.item .eyebrow a:hover, .item .eyebrow a:focus-visible { text-decoration: underline; }
/* `flex: none` e empurrado à direita: o crédito não encolhe mais, porque quem
   cede agora é a lista de temas ao lado — um tema pela metade ainda diz de que
   tema é, e "31 ju" não é uma data. */
.item .eyebrow .meta {
  margin-left: auto; flex: none;
  font-size: 11.5px; font-weight: 400; color: var(--tenue);
}
/* O selo do formato de origem (25/09): PDF, EPUB, DOCX, na frente do crédito.
   É a procedência de quem não tem fonte — o arquivo mandado de outro app —,
   e por isso mora no crédito, e não no título. Uma sigla em versalete com
   fio, na tinta do crédito: diz o formato sem disputar com o tema ao lado. */
.item .selo-formato {
  display: inline-block; margin-right: 6px; padding: 1px 4px 0;
  border: 1px solid color-mix(in srgb, var(--tenue) 70%, transparent); border-radius: 3px;
  font-size: 9.5px; font-weight: 700; letter-spacing: .08em; line-height: 1.35;
  color: var(--tinta-2); vertical-align: 1px;
}
.item h2 { font-family: var(--serif); font-size: 21px; line-height: 1.28;
  margin: 0 0 7px; font-weight: 600; letter-spacing: -.008em; text-wrap: balance; }
.item .alvo:hover h2, .item .alvo:focus-visible h2 { color: var(--acento); }
.item .resumo { font-family: var(--sans); font-size: 13.5px; color: var(--tinta-2);
  margin: 0 0 13px; line-height: 1.55; text-wrap: pretty; }
.item .rodape { font-family: var(--sans); font-size: .74rem; color: var(--tenue); }
/* A palavra de estado, onde o crédito estava. Ver `estadoEmPalavra` no
   `inbox.mjs`: na aba «Todos» ela é a única pista visível de que um item já
   foi lido — os botões mostram a AÇÃO, não o estado. */
.item .rodape .estado {
  font-size: 11.5px; font-weight: 500; color: var(--tenue);
}
/* As ações encolhem para 29px e vão para a direita da linha. Exceção
   deliberada ao `--alvo` de 44px, no mesmo registro que `.linha-progresso
   .redondo` (32px) já abriu: são alvos SECUNDÁRIOS dentro de um cartão que
   tem área de toque própria e bem maior. O `min-height` explícito é o que
   impede o `min-height: 44px` do núcleo de vencer o `height` e transformar o
   círculo numa elipse — é o defeito que aquele comentário descreve. */
/* O grupo da direita começa no SINAL da voz de estúdio quando ele existe, e
   nas ações quando não: desde 14/09 o sinal só é desenhado com narração
   pronta ou gerando, e sem ele as ações têm de ir sozinhas para a direita. */
.item .rodape .sinal-estudio, .item .rodape .acoes { margin-left: auto; }
.item .rodape .sinal-estudio + .acoes { margin-left: 0; }
.item .rodape .sinal-estudio { flex: none; padding-inline: 4px; }
.item .rodape .acoes { display: flex; gap: 5px; }
/* Todos os redondos do rodapé, e não só os de dentro de `.acoes`: o `↺` de
   reler mora fora dela, e ficava sendo o único de 32px numa fileira de 29 —
   visível na primeira captura desta rodada, invisível para os testes. */
.item .rodape .redondo {
  width: 29px; height: 29px; min-height: 29px; font-size: 12.5px;
  border-color: var(--aro-fino);
}
.item .rodape .acoes .excluir:hover, .item .rodape .acoes .excluir:focus-visible {
  color: var(--perigo); border-color: var(--perigo);
}
/* `flex: none` até a L-70, e a mudança é consequência dela: a linha ganhou
   mais dois botões de 32px, e com o crédito rígido ela estourava a largura do
   cartão no iPhone — empurrando o ✕ para fora em vez de encurtar
   "exemplo.com · 9 min · 31 jul", que é o que ali sobra de dispensável.
   Agora o crédito é o PRIMEIRO a ceder, e cede com reticências: os botões e o
   percentual seguem `flex: none`, porque um botão pela metade não é um botão
   e "6" não é "62%". */
.item .rodape .meta {
  flex: 0 1 auto; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* Piso da barra: `flex: 1` também encolhe, e uma barra de progresso de 8px
   não informa nada — melhor encurtar mais o crédito. */
.linha-progresso .progresso { min-width: 3rem; }
.item .pct { font-variant-numeric: tabular-nums; flex: none; }

/* No telefone, o crédito ganha a linha inteira em vez de caber por reticências.
   Medido: num cartão de 360px a linha sobra 292px, e com barra + `62%` + ↺ +
   os três botões o crédito era espremido a 39px — o que a reticência entrega
   ali é a letra "e", que não é informação, é entulho. Acima disso (iPad, que é
   onde este app vive) nada muda: tudo continua numa linha só.

   `flex: 1 0 100%` e não `flex-basis: 100%` solto: o `0` de shrink é o que
   impede o crédito de ser puxado de volta para a primeira linha quando o
   título é curto. */
/* A regra que dava a linha inteira ao crédito no telefone saiu em 02/09 junto
   com o crédito: ele subiu para a linha da sobrancelha, onde tem a largura do
   cartão só para ele e não disputa com barra nem com botão. O que sobrou
   embaixo é a palavra de estado (ou a barra) mais os alvos, que cabem em
   360px sem quebrar. */

/* Barra de progresso: 4px, e agora COM número ao lado. Sozinha ela responde
   "quanto falta" de relance; o número responde "vale a pena terminar agora?",
   que é a pergunta de quem está escolhendo entre dois artigos. */
.progresso { height: 4px; background: var(--papel-elev-2); border-radius: 2px; overflow: hidden; }
.progresso span { display: block; height: 100%; background: var(--t, var(--acento));
  border-radius: 2px; }

.vazio.erro { font-style: normal; color: var(--tinta); }
.voltar { font-family: var(--sans); font-size: .82rem; margin: 0 0 .4rem; }
.voltar a { color: var(--tinta-2); text-decoration: none; }
.voltar a:hover { color: var(--acento); }

/* ── tela de leitura (L-48) ────────────────────────────────────────────────
   "A página desaparece" (02 §1). O leitor não deve notar a tipografia — deve
   notar que leu 4.000 palavras sem cansar. Tudo aqui serve a isso: nada
   pisca, nada salta, nada compete com o texto. O único elemento com direito a
   chamar atenção é o destaque, porque ele é uma decisão do leitor.
   ───────────────────────────────────────────────────────────────────────── */

/* ── a folha (Onda 3, §1) ────────────────────────────────────────────────
   O artigo virou objeto: `--papel` pousado sobre `--tela`, com sombra. Antes
   desta mudança o Leitor não tinha folha nenhuma — a tela inteira ERA o
   papel (`body { background: var(--papel) }`), e por isso o claro do Leitor
   nunca batia com o claro do Tabula, que sempre pintou uma mesa por baixo
   dos post-its. Os dois agora são vistas do mesmo mundo.

   **Sombra `--sombra-pousada`, não `--erguida`.** Os três degraus do núcleo
   modelam um objeto a alturas diferentes da mesa (ver o cabeçalho dos temas
   em `nucleo.css`); a folha não paira — ela está apoiada, é a mais rasa das
   três sombras que existe,
   a mesma que `.abas.seg .aba.ativa` já usa para "sobe do trilho, não do
   papel". Erguida ou alta fariam a folha parecer um cartão flutuando sobre
   a escrivaninha, não papel pousado nela.

   **`--respiro` é o espaço entre a coluna e a beirada da folha**, não a
   largura da folha em si — a coluna continua sendo `--measure`, sempre.
   `box-sizing: border-box` (reset do núcleo) faz a aritmética sozinha: ao
   somar `--respiro` duas vezes no `max-width` e usá-lo como `padding`, a
   ÁREA DE CONTEÚDO que sobra por dentro do padding é exatamente
   `--measure`, sem precisar redeclarar largura em `header`/`.prosa`/
   `footer`. `clamp` mantém o respiro generoso num monitor largo sem deixar
   a folha enorme, e mínimo (mas nunca zero) numa tela só um pouco maior que
   a coluna — abaixo de 900px o respiro desiste de vez (regra seguinte). */
.artigo {
  max-width: calc(var(--measure) + var(--respiro) * 2);
  /* Margem de baixo reduzida na L-71 pela mesma razão do `main`: a folga da
     barra fixa é do último elemento do fluxo, e agora o último é o `#versao`.
     Somadas, as duas dariam folga em dobro na rota de leitura — a única em
     que o `main` não tem padding próprio e a folha responde por ela. */
  margin: 1.6rem auto 1.5rem;
  padding: 2rem var(--respiro);
  background: var(--papel);
  border-radius: var(--raio);
  box-shadow: var(--sombra-pousada);
}
/* No escuro, sombra preta sobre mesa quase preta some — mesmo modo de falha
   que o post-it do Tabula documenta: `--papel` (#16171a) × `--tela`
   (#14171a) mede 1,004:1, e a camada mais forte de `--sombra-pousada`
   compõe #0a0c0d sobre a mesa, 1,090:1 — as duas cores próximas demais para
   o olho separar. Ali a borda volta a ser carga real (é a única pista que
   sobra de "isto é uma folha à parte"), então ela fica só neste tema, no
   mesmo token que o Tabula usa para o mesmo problema. */
[data-tema="escuro"] .artigo { border: 1px solid var(--papel-borda); }
/* Tela estreita: iPhone inteiro e a maioria dos iPads em retrato — todos
   menos o 12,9" Pro, que só ele sobra respiro real a 1024px (calculado com
   `--tamanho` padrão e largura "média": iPhone e iPad mini/9-10ª geração
   ficam de ponta a ponta MESMO SEM esta regra, porque `--measure` +
   2×`--respiro` já estoura a viewport sozinho; os de 11", 810–834px, é que
   sobrariam uma margem de mesa de 13–22px de cada lado — fina demais para
   ler como respiro deliberado, fina o bastante para ler como acidente de
   raio de canto brigando com a borda da tela). Uma margem de escrivaninha
   ali rouba exatamente a largura que este app existe para proteger. A
   folha vai de ponta a ponta — sem raio (não há beirada para arredondar
   quando a beirada é a própria tela) e sem margem lateral; o padding volta
   a ser o do `main` original, preservando o safe-area-inset que o resto do
   app usa. O vertical (margem de 1.6rem/barra-h e padding de 2rem) não
   muda: só a dimensão que competia com a coluna é que cede. */
@media (max-width: 900px) {
  .artigo {
    max-width: none;
    margin-left: 0; margin-right: 0;
    border-radius: 0;
    padding-left: max(1.1rem, env(safe-area-inset-left));
    padding-right: max(1.1rem, env(safe-area-inset-right));
  }
  /* ── A coluna de cápsulas pede o seu lado da folha  (25/09, o iPhone Duo) ──
     Entre o corte do telefone (37rem) e os 900px a folha vai de ponta a
     ponta, mas a coluna de cápsulas continua em pé na borda direita, fixa, e
     não deitada no rodapé como no telefone: sem margem de mesa ao lado da
     folha, ela pousava EM CIMA da borda direita do texto e do seletor
     «Acompanhar». A captura do Duo aberto (669pt) mostrou; a sonda mediu os
     mesmos 56px de sobreposição a 744 (iPad mini) e a 834 (iPad 11"). A folha
     recua o lado direito até a coluna — a largura dela, a folga dela até a
     borda e um vão —, e só onde a coluna está em pé: no telefone
     (`data-arranjo="barra"`) ela é a barra do rodapé e a folha fica inteira.
     Acima de 900px a folha já tem o respiro, e a coluna cabe na mesa. */
  body[data-leitura]:not([data-arranjo="barra"]) .artigo {
    padding-right: max(env(safe-area-inset-right), calc(var(--capsula-x) + var(--capsula-l) + .75rem));
  }
}
.artigo > header { margin: 0 0 var(--space-block); }
.artigo h1 { font-size: 1.75em; line-height: 1.18; margin: 0 0 .35em; font-weight: 600;
  letter-spacing: -0.01em; text-wrap: balance; }
.artigo .meta { font-family: var(--sans); font-size: .8rem; color: var(--tinta-2); margin: 0; }

/* O botão "Ouvir" mora no CABEÇALHO, não no rodapé (ouvir é a primeira
   decisão ao abrir o artigo, não a última — antes dele só era alcançável
   depois de rolar o texto inteiro). `.btn.ouvir` e `.audio-leitura`
   continuam sendo as mesmas classes do Bloco J — só o
   respiro abaixo da `.meta` é próprio deste lugar, porque aqui não há mais
   o wrapper `.acoes` do rodapé para dar esse espaçamento. `display: inline-flex`
   evita que o botão estique para a largura da coluna, como um `<p>` faria. */
.artigo > header .btn.ouvir { display: inline-flex; margin-top: .9rem; }
/* E o `[hidden]` de volta, que o `display` acima derrubava.  (L-120)

   `botao.hidden = true` é o que tira o botão de cena quando a voz começa —
   o player nasce onde ele estava. Só que uma regra de autor com `display`
   vence o `[hidden] { display: none }` da folha do navegador, e o efeito era
   o botão «Tocar» ficando na tela ao lado do player durante a leitura
   inteira, contradizendo o próprio estado. Nenhum teste via: o JS punha o
   atributo certo e o markup estava certo — só o pixel estava errado.

   Sete outros lugares deste arquivo já trazem a guarda (`#acoes[hidden]`,
   `.audio-leitura[hidden]`, `#tempo-leitura[hidden]`…); esta era a que
   faltava, e apareceu na primeira renderização do bloco do lado. */
.artigo > header .btn.ouvir[hidden] { display: none; }
/* `.audio-leitura` já tem `margin-top: .8rem` na regra genérica mais abaixo —
   suficiente aqui também, porque ela nasce logo depois do botão (escondido)
   ou da `.meta`, nos dois casos com margem zero por cima. */
.artigo > header .sub[data-ouvir-aviso] { margin: .5rem 0 0; }

/* O corpo. Cada linha destas foi escolhida em 02 §2.4 e vale reler o porquê
   antes de mexer — em especial as duas primeiras. */
.prosa {
  font-optical-sizing: auto;         /* usa o eixo opsz das variáveis */
  text-wrap: pretty;                 /* sem órfãs nem linha final de 1 palavra */
  hyphens: auto;                     /* com lang="pt-BR" no <html> */
  -webkit-hyphens: auto;
  -webkit-hyphenate-limit-before: 3; -webkit-hyphenate-limit-after: 3;
  text-align: left;                  /* NUNCA justificado: abre rios de branco */
  font-variant-numeric: oldstyle-nums proportional-nums;
  font-kerning: normal;
  overflow-wrap: break-word;         /* URL de advisory não estoura a coluna */
}
.prosa > * { margin: 0 0 var(--space-para); }
.prosa h2, .prosa h3 { font-weight: 600; line-height: 1.25; margin: var(--space-block) 0 .4em; }
.prosa h2 { font-size: 1.28em; }
.prosa h3 { font-size: 1.1em; }
.prosa a { color: var(--acento); text-underline-offset: .18em; text-decoration-thickness: 1px; }

/* ── A nota de rodapé não pode sair da caixa da linha  (2026-09-01) ─────────
   Estas quatro declarações não são tipografia: são o conserto do «rastro
   vermelho» relatado no iPad, e mexer nos números reabre o defeito.

   ── O sintoma, e por que ele parecia ser de outro assunto ──────────────────
   Enquanto a voz lia, ficavam na página faixas finas órfãs — um pedaço na cor
   da palavra acesa, outro na cor da faixa da frase —, **sempre logo acima da
   linha que traz uma nota**. Medidas na captura: 4,5px de altura, e o pedaço
   colorido começando exatamente onde começa a palavra seguinte ao `[12]`.
   Parecia defeito de repintura do `::highlight()`, e o `leitura-falada.mjs` já
   carregava um conserto de 31/08 escrito sob essa suspeita (a "invalidação
   forçada"). Não era ali.

   ── A causa ───────────────────────────────────────────────────────────────
   `Range.getClientRects()` — que é **o retângulo que o `::highlight()` pinta**
   — devolve a caixa do TEXTO de cada fragmento inline: ascent + descent da
   fonte, e não a caixa da linha (medido: 30px fixos para as três entrelinhas,
   cujo `line-height` vai de 29,5 a 35,6px). Um `<sup>` na folha do navegador
   herda o `line-height` do parágrafo e sobe por `vertical-align: super`: o
   retângulo dele nascia **3,8 a 4,8px acima** do retângulo dos vizinhos de
   linha. O motor pintava o acompanhamento naquela faixa estendida e, ao
   despintar, invalidava só a caixa normal. A sobra ficava na página.

   Ou seja: a página pedia tinta fora da linha, e o defeito de repaint do
   WebKit era o segundo passo, não o primeiro. Tirado o pedido, não há sobra —
   e o conserto vale para qualquer motor, presente ou futuro.

   ── Os números, e por que são estes ────────────────────────────────────────
   Com fonte a `.7em`, o teto medido em 54 combinações (3 fontes de leitura × 3
   entrelinhas × 3 tamanhos, no Safari) é `.4em` de subida e ~`.07em` de
   descida. A folga é assimétrica porque a caixa do texto é: sobra muito
   ascent acima da baseline e quase nada de descent abaixo. Daí o `<sub>`
   descer pouco — o índice fica sutil, e é o preço de ele não deixar rastro na
   entrelinha de baixo. Os valores escolhidos ficam **abaixo** do teto:

     <sup>  .7em / +.35em  → sobra 0 nas 54     (teto: +.4em)
     <sub>  .7em / −.06em  → sobra 0 nas 54     (teto: ~−.07em)

   `web/test/interacao-rastro.mjs` mede as duas coisas: a sobra geométrica, em
   toda a matriz, e — por screenshot do Safari — a tinta órfã que ela produz.
   Um valor mais alto passa no olho e reprova lá. */
.prosa sup { font-size: .7em; vertical-align: .35em; }
.prosa sub { font-size: .7em; vertical-align: -.06em; }

/* ── A imagem continua `block`, e a razão foi MEDIDA  (05/09) ──────────────
   Ela é da mesma família do rótulo do callout: uma `<img>` em `display: block`
   dentro de um `<p>` COM TEXTO parte o parágrafo em blocos anônimos, e o
   WebKit deixa de pintar `::highlight()` no resto dele.

   `inline-block` conserta e cobra caro: um `<p>` com só a figura media 374px e
   passou a medir 463 (Safari, medido), porque a caixa de linha traz o strut —
   e isso empurraria TODA figura do acervo. O `:only-child` não separa os dois
   casos: ele conta elementos, e um `<p>` com imagem e texto tem a imagem como
   único filho-elemento.

   Então o conserto foi para a INGESTÃO, onde o caso ruim deixa de nascer:
   `paraHtml` separa a imagem do texto em parágrafos próprios
   (`markdown.mjs`, `imagemEmParagrafoProprio`). Com essa garantia na origem,
   `block` aqui não pode apagar realce nenhum — não há texto ao lado dela.
   Varredura do acervo em 05/09: 22 parágrafos com imagem, zero com texto
   junto, o que este passo torna invariante em vez de acaso. */
.prosa img { display: block; width: 100%; height: auto; border-radius: 4px; margin: var(--space-block) 0; }
/* --tinta, não --tinta-2: figcaption recebe data-bid (bids.mjs:48-51), logo é
   destacável, e os --hl-* foram calibrados para --tinta por cima — --tinta-2
   sob destaque reprovava em 9 das 12 combinações (Task 4/9). */
.prosa figcaption { font-family: var(--sans); font-size: .85em; color: var(--tinta); margin-top: -1.4em; }
.prosa blockquote { border-left: 2px solid var(--regra); padding-left: 1.2em; margin-left: 0; }
.prosa code { font-family: var(--mono); font-size: .88em; background: var(--papel-elev);
  padding: .1em .3em; border-radius: 3px; }
/* A cerca QUEBRA a linha, e não rola  (06/09, a pedido do dono)
   ─────────────────────────────────────────────────────────────────────────
   A barra horizontal esconde o fim da linha atrás de um gesto: quem lê um
   estudo no iPad não arrasta código, salta ele. Com a quebra, a linha longa
   continua na de baixo, alinhada com o começo do programa (o `padding-left`
   da calha vale para a continuação também), e a calha diz onde uma linha de
   verdade termina. O `overflow-x` fica como rede: uma tabela ASCII de
   `language-text` ainda pode não caber. */
.prosa pre { background: var(--papel-elev); padding: 1em; border-radius: 4px; overflow-x: auto;
  white-space: pre-wrap; overflow-wrap: anywhere; }
.prosa pre code { background: none; padding: 0; font-size: .88em; }

/* ── A matemática  (spec 44) ──────────────────────────────────────────────
   O servidor marca `span.matematica` e o KaTeX desenha dentro dele. Duas
   formas, decididas pelo DOM e não por campo: a fórmula que é o único filho do
   parágrafo é display (linha própria, centrada); a que divide o parágrafo com
   prosa fica na linha, no meio da frase.

   `inline-block` com `width: 100%`, NUNCA `block` — a mesma pedra da calha de
   números logo acima: um filho inline da prosa que vira bloco parte o `<p>` em
   blocos anônimos e o WebKit deixa de pintar `::highlight()` no resto dele. O
   parágrafo aqui é justamente um dos que a voz lê. Há guarda no
   `bimodal-css.test.mjs`.

   `overflow-x: auto` porque uma matriz do Cryptography and Network Security é
   mais larga que os 390px do iPhone: sem isto quem rola é a PÁGINA, e o app
   inteiro ganha barra horizontal por causa de um parágrafo. */
.prosa .matematica { overflow-x: auto; overflow-y: hidden; max-width: 100%; }
/* `[data-display]` é escrito pelo `renderizarMatematica`, e não por
   `:only-child`: o seletor conta ELEMENTOS e ignora o texto, então um
   parágrafo que TERMINA em fórmula casaria e a fórmula saltaria para o meio
   da linha. A régua é uma só, e mora no JS. */
.prosa .matematica[data-display] { display: inline-block; width: 100%;
  box-sizing: border-box; text-align: center; padding: .4em 0; }
/* A fórmula que não compilou fica como texto — feio, honesto, e é o que se
   copia para consertar. Monoespaçada para o LaTeX ficar legível. */
.prosa .formula-falhou { font-family: var(--mono, ui-monospace, monospace);
  font-size: .9em; opacity: .85; }

/* A calha de números. `--calha` é escrito pelo `numerarLinhas` conforme o
   total de linhas — dois dígitos num estudo, três num capítulo de livro. */
/* `inline-block` com `width: 100%`, nunca `block`: um filho inline da prosa
   que vira bloco parte o parágrafo em blocos anônimos e o WebKit deixa de
   pintar `::highlight()` no resto dele — o realce da voz sumiria dentro da
   cerca inteira, sem erro nenhum. É a lição de 05/09, e há guarda no
   `bimodal-css.test.mjs` que a cobra. */
.prosa pre > code.numerada { counter-reset: ln; }
.prosa pre > code.numerada > .ln { display: inline-block; width: 100%;
  box-sizing: border-box; position: relative;
  padding-left: calc(var(--calha, 2ch) + 1.4ch);
  /* A linha EM BRANCO de um programa é uma linha: sem altura mínima ela mede
     zero, e o número dela cai por cima do número da linha seguinte. Foi o que
     a captura mostrou e a medição de altura não pegava — ela olhava a linha
     mais alta, não a mais baixa. */
  min-height: 1.4em; min-height: 1lh; }
.prosa pre > code.numerada > .ln::before {
  counter-increment: ln; content: counter(ln);
  position: absolute; left: 0; top: 0; width: var(--calha, 2ch);
  text-align: right; color: var(--tinta-fraca);
  user-select: none; -webkit-user-select: none; }
/* A quebra de linha continua no texto do bloco — é a coordenada dos destaques
   — e sai do fluxo para não desenhar uma linha em branco a cada linha. */
.prosa pre .nl { position: absolute; width: 0; height: 0; overflow: hidden; }
.prosa ul, .prosa ol { padding-left: 1.4em; }
.prosa li { margin-bottom: calc(var(--space-para) / 2); }
/* O texto do item-pai de uma lista aninhada vem num `<p>` (bids.mjs, para
   ganhar bid): o respiro até a sublista é o mesmo de um item ao seguinte. */
.prosa li > p:first-child:has(+ :is(ul, ol)) { margin-bottom: calc(var(--space-para) / 2); }
/* --tinta, mesma regra do figcaption acima: `li` está em BLOCOS (bids.mjs) e
   é destacável — o marcador vive dentro do mesmo elemento que pode ganhar um
   --hl-* por baixo. */
.prosa li::marker { color: var(--tinta); }
.prosa table { width: 100%; border-collapse: collapse; font-variant-numeric: tabular-nums lining-nums;
  font-size: .92em; display: block; overflow-x: auto; }
.prosa th, .prosa td { text-align: left; padding: .45em .7em; border-bottom: 1px solid var(--regra); }
.prosa th { font-weight: 600; }
.prosa hr { border: 0; border-top: 1px solid var(--regra); margin: var(--space-block) 0; }

/* Rodapé: fonte, data, autor, clusters e as ações de estado. */
.artigo > footer { margin-top: calc(var(--space-block) * 1.5); padding-top: 1.2rem;
  border-top: 1px solid var(--regra); font-family: var(--sans); font-size: .84rem; }
.artigo > footer p { color: var(--tinta-2); margin: 0 0 .8rem; }
.artigo > footer a { color: var(--acento); }
/* O grupo dos três botões. É o MESMO wrapper nos dois lugares (rodapé do
   artigo e linha da lista) — o que muda é o gap e a margem, declarados por
   contexto logo abaixo e na seção dos redondos. */
.acoes { display: flex; align-items: center; gap: .4rem; }
.artigo > footer .acoes { flex-wrap: wrap; gap: .6rem; margin-top: 1rem; }

/* A barra de progresso que morava aqui (4px no topo, com marcos de meta em
   25·50·75%) virou a bolha `#progresso-flutuante` — ver a seção dela junto
   das irmãs da coluna flutuante, adiante. Duas encarnações no topo não
   bastaram: 2px quase subliminar, depois 4px em cor plena — e continuou
   difícil de ver, porque o topo é onde o olho NÃO está durante a leitura. */

/* Cromo que some ao rolar para baixo e volta ao rolar para cima — ou ao toque
   no texto (L-53b). A `.cabeca` não precisa de regra: ela está no fluxo e sai
   da tela sozinha, rolando junto com o que a empurrou. Quem precisa é a barra,
   que é fixa.

   **É na tela de artigo que isto conta**, e desde 2026-09-02 é só lá que
   acontece. A versão anterior desta regra não qualificava a rota e se apoiava
   numa premissa: «nas telas de serviço o conteúdo raramente passa da `folga`
   de 80px do `criarCromo`, então a barra fica onde está». A premissa é falsa
   — a inbox com nove artigos rola muitas telas —, e a D1 (navegação presente
   fora do texto, ausente dentro dele) valia por acidente de altura, não por
   desenho. O defeito ficou visível no Mac, onde a barra é a lateral de 216px:
   rolar a lista apagava a navegação inteira.

   O conserto é aqui e não no `criarCromo`: o atributo diz «a rolagem foi para
   baixo», que é verdade em qualquer tela, e o app.mjs já declara que a rota no
   `<body>` existe **para o CSS** decidir coisas assim. */
body[data-leitura][data-cromo="oculto"] #barra-nav { transform: translateY(100%); }

/* E no Mac, onde a mesma barra é a lateral de 216px, ela sai pelo LADO. A
   regra vive aqui, colada na irmã, porque é a ORDEM que a faz valer: as duas
   têm especificidade idêntica (`body[atributo][atributo] #id`), e `@media` não
   soma peso — de cima, ela perdia calada. Medido no Safari por
   `test/interacao-cromo.mjs`, que foi onde o defeito apareceu. */
@media (min-width: 1100px) and (pointer: fine) {
  body[data-leitura][data-cromo="oculto"] #barra-nav { transform: translateX(-100%); }
}

/* ── Ajustando um destaque: o cromo sai do caminho da sondagem (L-71) ───────
   Arrastar uma alça não move o intervalo por deslocamento — `ajuste.mover()`
   pergunta ao documento QUE TEXTO está sob o dedo (`caretRangeFromPoint`), e
   qualquer elemento por cima da prosa responde por si. A resposta não cai na
   prosa, o `mover` desiste em silêncio, e o destaque simplesmente não vai.

   Quatro alvos, e nenhum é folclore:
   - `#barra-nav`  faixa cheia, fixa embaixo — nasceu na L-66 e é a faixa morta
                   maior, bem onde o polegar arrasta;
   - `#caneta`     56px que a L-66 subiu para cima da barra, e que em tela
                   estreita cai dentro da coluna de leitura;
   - `#acoes`      z-60, ancorada 10px acima do trecho, em cima da bolinha da
                   `#alcaA`, que se desenha 18px acima da linha;
   - `.alca`       44px de alvo de toque, o mínimo — ela come os ~22px iniciais
                   do próprio gesto, e é por isso que ajustar de leve nunca
                   funcionou e puxar longe sempre funcionou.

   Desligar o hit-test da própria alça no meio do arraste é seguro porque o
   arraste **escuta no documento** desde a L-51 (ver o cabeçalho de ajuste.mjs):
   nenhum `pointermove` depende de acertar a alça. Quem repõe isto é o fim do
   gesto, nos dois caminhos — `soltar` e `sair`. */
/* A coluna INTEIRA, e não só o `#caneta` (Bloco J7): o argumento acima é sobre
   qualquer elemento fixo por cima da prosa, e a coluna passou de uma bolha a
   cinco. As outras quatro estavam de fora por idade, não por decisão — e são
   56px cada, empilhados exatamente na metade de baixo da tela, que é onde o
   polegar arrasta. */
body[data-ajustando] #barra-nav,
body[data-ajustando] #caneta,
body[data-ajustando] #ouvir-flutuante,
body[data-ajustando] #velocidade-flutuante,
body[data-ajustando] #velocidade-painel,
body[data-ajustando] #ajustes-flutuante,
body[data-ajustando] #perguntar-flutuante,
body[data-ajustando] #rolagem-flutuante,
/* A bolha do progresso entrou na lista na L-124, quando virou alvo. Enquanto
   era só mostrador ela se protegia sozinha, com `pointer-events: none`
   permanente — a mesma solução da pílula do tempo, que segue de fora. */
body[data-ajustando] #progresso-flutuante,
body[data-ajustando] #acoes,
/* O trilho de marcadores (28/08): o painel largo é coluna de grade ao LADO
   do texto e nunca precisou estar aqui; o trilho é sobreposição na beirada
   direita, e elemento por cima da prosa responde pelo caretRangeFromPoint. */
body[data-ajustando] #marginalia,
/* A cápsula e a fileira (revisão M108): desde que a coluna virou cápsula,
   cada botão da lista acima mora dentro de uma `.capsula { pointer-events:
   auto }`, e um filho que não recebe toque devolve a sondagem ao PAI — o
   caret voltava de dentro da cápsula, não da prosa. No telefone, a fileira
   `#pilha-leitura` volta a `auto` com a largura inteira, no lugar da
   `#barra-nav` que está aqui desde o começo; o «≡» mora ao lado dela. Pela
   cápsula entram também o ⇧ e as cápsulas do estudo e da bancada. A fileira
   vem por id para empatar em especificidade com a regra do arranjo barra,
   que está antes. */
body[data-ajustando] #pilha-leitura,
body[data-ajustando] .capsula,
body[data-ajustando] #abas-alternar,
body[data-ajustando] .alca { pointer-events: none; }

/* Borda em --borda-controle (§2): `.btn` mora tanto na folha (`.acoes` do
   rodapé, fundo --papel) quanto dentro de sheets com fundo --papel-elev
   (#ajustes, #nota) — e aí o próprio fundo do botão É o mesmo --papel-elev
   do sheet, diferença zero. Nos dois lugares a borda é a única pista de que
   ali existe um controle. */
/* O `.btn` acompanha o `.redondo` (04/09): mesma família, mesmo material. Ele
   mora tanto na folha (o rodapé do artigo, fundo `--papel`) quanto dentro dos
   sheets (`#ajustes`, `#nota`, fundo `--papel-elev`) — e era JUSTAMENTE nos
   sheets que ele desaparecia, porque ali o fundo do botão e o do painel eram o
   mesmo `--papel-elev` e a borda fina fazia todo o trabalho sozinha. Em cromo,
   o controle se distingue da superfície em qualquer uma das duas. */
.btn { font-family: var(--sans); font-size: .82rem; color: var(--cromo-tinta);
  background: linear-gradient(180deg, var(--cromo-1), var(--cromo-2));
  border: 1px solid var(--cromo-borda); border-radius: 6px; padding: .38rem .7rem; cursor: pointer; }
.btn:hover, .btn:focus-visible { border-color: var(--cromo-acento); color: var(--cromo-acento); }
.btn[aria-pressed="true"] { border-color: var(--cromo-acento); color: var(--cromo-acento); }
.btn[disabled] { opacity: .5; cursor: default; }

/* Painel de ajustes: sheet inferior. Cinco controles, nada mais — cada opção
   a mais é uma decisão que o leitor toma em vez de ler (02 §4). */
#ajustes { position: fixed; left: 0; right: 0; bottom: 0; z-index: 50;
  background: var(--papel-elev); border-top: 1px solid var(--regra);
  /* aresta, não alta: o painel nasce da borda de baixo e não paira sobre
     nada — é oclusão de contato, não sombra projetada por --luz-x. --alta
     projeta para BAIXO (Y positivo) e caía para fora da tela aqui. */
  box-shadow: var(--sombra-aresta); padding: 1rem 1rem calc(1rem + env(safe-area-inset-bottom));
  /* .22s ease, revertido de --dur var(--curva) (Onda 3, correção): a adoção
     do token trocava duas coisas de uma vez, e só uma delas foi decidida — os
     40ms de duração são de fato imperceptíveis, mas a curva NÃO é a mesma:
     `--curva` (.2,.7,.3,1) chega a 90% do curso em ~85ms contra ~135ms do
     `ease` original, com o painel em 37% do curso aos 20ms onde `ease`
     mostrava 8%. Isso muda a sensação do gesto — o sheet passa a "saltar"
     em vez de deslizar —, e ninguém decidiu essa parte. Duração e curva são
     duas decisões separadas; adotar o token de duração não obriga a adotar
     a curva junto. */
  font-family: var(--sans); transform: translateY(101%);
  /* Fechado é INVISÍVEL, não só deslizado para fora (revisão M110): como no
     `#sumario` e no `#velocidade-painel`, um painel fora da vista continua
     parada de Tab e lido pelo VoiceOver, e Enter num botão dele trocava a
     fonte sem painel nenhum à vista. O atraso segura a visibilidade até o
     fim do deslize; ao abrir ela volta na hora (`transition-delay: 0s`). */
  visibility: hidden; transition: transform .22s ease, visibility 0s .22s; }
#ajustes[data-aberto="sim"] { transform: none; visibility: visible; transition-delay: 0s; }

/* ── Em tela larga o sheet vira CARTÃO flutuante  (revisão 2026-08-24) ──────
   Um sheet de aresta faz sentido no telefone, onde a borda de baixo é a mão.
   No iPad e no Mac ele virava uma faixa de 1024px — cromo do tamanho da tela
   para cinco decisões do tamanho de um cartão. Flutuando na medida do texto,
   o painel fica um OBJETO da mesma família do `#nota`/`#conversa`: papel
   elevado, borda, raio.

   A física da sombra muda junto, e de propósito: ancorado na aresta ele
   usava `--sombra-aresta` (oclusão de contato, Y para cima); descolado da
   borda ele paira, e o que paira projeta — `--sombra-erguida`, com a luz de
   `--luz-x`, como a pílula de ações. É a distinção que o núcleo documenta.

   O fechado desce `101% + 2rem`: o 101% sozinho deixava a beirada de cima
   do cartão espiando na base da tela, porque agora há 1rem de mesa entre
   ele e a borda. */
@media (min-width: 592px) {
  #ajustes {
    left: 0; right: 0; margin-inline: auto;
    width: min(46rem, calc(100% - 2rem));
    bottom: calc(1rem + env(safe-area-inset-bottom));
    padding: 1.15rem 1.3rem 1.3rem;
    border: 1px solid var(--papel-borda); border-top-color: var(--papel-borda);
    border-radius: var(--raio);
    box-shadow: var(--sombra-erguida);
    transform: translateY(calc(101% + 2rem));
  }
  #ajustes[data-aberto="sim"] { transform: none; visibility: visible; transition-delay: 0s; }
}
/* ── O sumário  (L-124) ────────────────────────────────────────────────────
   Mesmo material e mesma física do `#ajustes` — sheet de aresta no telefone,
   cartão flutuante a partir de 592px — porque é a mesma família de painel, e
   inventar uma segunda gramática para o segundo sheet é como o cromo de um
   app começa a parecer costurado por duas pessoas.

   O que muda é a ALTURA: o de ajustes tem cinco grupos e nunca rola; este tem
   tantas linhas quanto o texto tiver seções, e um paper de trinta seções
   passaria da tela inteira. Daí o teto de 60vh com rolagem própria, e o
   `overscroll-behavior: contain` — sem ele, chegar ao fim da lista transfere
   o gesto para a prosa por baixo, e o leitor perde o lugar exatamente enquanto
   procura para onde ir.

   O painel abre à DIREITA no cartão, alinhado com a coluna de bolhas: ele
   nasce de uma delas, e um cartão centralizado faria o gesto perder a origem.
   No telefone continua de aresta a aresta, onde não há origem a perder. */
#sumario {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 50;
  background: var(--papel-elev); border-top: 1px solid var(--regra);
  box-shadow: var(--sombra-aresta);
  padding: .9rem 1rem calc(1rem + env(safe-area-inset-bottom));
  font-family: var(--sans);
  max-height: 60vh; overscroll-behavior: contain;
  /* ── O SCROLL só existe com o painel ABERTO  (31/08) ────────────────────
     `overflow-y: auto` permanente deixava a barra de rolagem do painel
     pintada na tela DEPOIS de ele fechar — uma faixa vertical fina, do alto
     até 60vh, sobrevivendo ao `visibility: hidden`. No WebKit a barra overlay
     é composta à parte e não segue a visibilidade do dono; num livro de 180
     seções, que é onde a lista rola de verdade, ela ficava lá até o próximo
     repaint.
     `hidden` no fechado resolve na origem: barra que não existe não sobra. */
  overflow: hidden;
  transform: translateY(101%); transition: transform .22s ease, visibility 0s .22s;
  /* ── FECHADO É INVISÍVEL, e não «deslizado para fora»  (conserto de 31/08)
     O `#ajustes` pode contar só com o `translateY(101%)` porque nasce colado
     na borda de baixo: descer a própria altura o tira da tela. Este painel
     não — a partir de 592px ele é um cartão ancorado no MEIO da coluna, e
     101% da altura dele o move oitenta pixels para baixo, ainda em cena.
     Foi assim que o painel VAZIO apareceu na inbox: uma caixa branca no canto
     direito, sem campo, sem explicação. `visibility` (e não `display`) para
     que a transição continue existindo; o atraso de .22s a segura até o fim
     do deslize. */
  visibility: hidden;
}
#sumario[data-aberto="sim"] {
  transform: none; visibility: visible; transition-delay: 0s;
  overflow-y: auto;
}

/* Fora do artigo não há texto que tenha sumário — mesma regra da bolha que o
   abre, e das cinco bolhas irmãs. `data-rota`, e não `hidden`: nenhuma tela o
   revela, então nenhuma teria de recolhê-lo. */
body:not([data-leitura]) #sumario { display: none; }

@media (min-width: 592px) {
  #sumario {
    /* AO LADO da coluna de bolhas, nunca por cima: o painel nasce de uma
       delas, e cobrir as outras seis tira da tela justamente os controles que
       o leitor pode querer em seguida (pausar a voz, ajustar o texto). O
       recuo é o diâmetro da bolha mais a folga do degrau. */
    left: auto; right: calc(var(--capsula-x) + var(--capsula-l) + .6rem);
    width: min(22rem, calc(100vw - 6rem));
    /* Alinhado pelo item que o abre — o anel do progresso —, e crescendo para
       cima. `--y-progresso` é a altura dele a partir da base da pilha. */
    bottom: calc(var(--pilha-y) + var(--y-progresso));
    padding: .9rem 1rem 1rem;
    border: 1px solid var(--papel-borda); border-radius: var(--raio);
    box-shadow: var(--sombra-erguida);
    transform: translateY(1rem);
    /* ── O TETO é o espaço acima da ÂNCORA, não uma fração da tela  (31/08)
       O painel cresce para cima a partir da bolha, que está a seis degraus do
       rodapé. `max-height: 60vh` mede a tela inteira e ignora isso: no iPad,
       60vh mais a altura da âncora passava do topo, e os primeiros itens do
       sumário ficavam cortados acima da borda — invisíveis e inalcançáveis,
       porque nem rolando se chega ao que está fora da tela.

       A conta é a mesma da âncora, e por isso não desafina quando o degrau
       muda: altura da janela menos a distância até a bolha, menos uma folga
       de respiro. `dvh` porque no Safari do iPad a barra de endereço entra e
       sai da conta de `vh`; o `vh` fica como reserva para quem não conhece a
       unidade nova. */
    max-height: calc(100vh - (var(--pilha-y) + var(--y-progresso)) - 1.5rem);
    max-height: calc(100dvh - (var(--pilha-y) + var(--y-progresso)) - 1.5rem);
  }
  #sumario[data-aberto="sim"] { transform: none; }
}

.sumario-lista { list-style: none; margin: 0; padding: 0; }

/* O recuo por profundidade, e o teto de três níveis: `h1`→`h4` dão quatro
   degraus, e o quarto recuo já come metade da largura útil de um telefone.
   O `data-profundidade` chega da `extrairSecoes` já limitado a 3. */
.sumario-lista li[data-profundidade="1"] { padding-left: .9rem; }
.sumario-lista li[data-profundidade="2"] { padding-left: 1.8rem; }
.sumario-lista li[data-profundidade="3"] { padding-left: 2.7rem; }

/* A linha inteira é o alvo — 44px de altura mínima, o alvo de toque do resto
   do app. Alinhamento ao TOPO (e não centralizado): título de duas linhas com
   a marca centralizada faz o `▸` flutuar no meio do texto em vez de apontar
   para o começo dele. */
.sumario-lista button {
  display: flex; align-items: flex-start; gap: .5rem;
  width: 100%; min-height: var(--alvo); padding: .45rem .3rem;
  border: 0; background: none; cursor: pointer; text-align: left;
  font-family: var(--sans); font-size: .92rem; line-height: 1.35;
  color: var(--tinta-2); border-radius: var(--raio-p);
}
.sumario-lista .marca {
  flex: 0 0 1rem; text-align: center; color: var(--tenue);
  /* A marca ocupa a calha MESMO vazia (a seção adiante não tem glifo): sem a
     largura fixa, as linhas sem marca começariam 1rem à esquerda das outras e
     a lista pareceria desalinhada em vez de hierárquica. */
  line-height: 1.35;
}

/* Já passou por aqui: mais claro, nunca riscado. Riscar diria «resolvido», e
   o que se leu continua sendo o que se pode reler. */
.sumario-lista li[data-estado="passou"] button { color: var(--tenue); }
.sumario-lista li[data-estado="passou"] .marca { color: var(--progresso); }

/* Você está aqui. Peso e cor plena, mais a barra de acento à esquerda: é a
   única linha que o olho precisa achar sem ler, porque é a resposta à
   pergunta que fez o painel ser aberto. */
.sumario-lista li[data-estado="aqui"] button {
  color: var(--tinta); font-weight: 600;
  background: color-mix(in srgb, var(--progresso) 10%, transparent);
}
.sumario-lista li[data-estado="aqui"] .marca { color: var(--progresso); }

/* ── O painel de ajustes  (L-73) ───────────────────────────────────────────
   Antes: cinco fileiras de pílulas de texto idênticas, presas a uma calha de
   rótulos de 5.5rem, deixando metade da largura vazia à direita. Num app cuja
   razão de existir é a tipografia, era o único lugar que traía a premissa.

   Agora: uma grade de dois campos que ocupa a medida inteira, e cada opção é
   uma AMOSTRA do próprio efeito. A ordem do DOM não mudou — fonte, tamanho,
   entrelinha, largura, tema —, então a `fonte` ocupa a faixa inteira e os
   outros quatro caem em pares, sem `grid-area` nenhum. */
#ajustes .grade {
  display: grid; grid-template-columns: 1fr 1fr;
  gap: .9rem 1.4rem; max-width: var(--measure); margin-inline: auto;
}
#ajustes .grupo[data-grupo="fonte"] { grid-column: 1 / -1; }

/* No telefone a grade vira uma coluna. Em duas, cada grupo fica com metade da
   medida para três opções — e "Compacta" numa caixa de ~55px quebra a palavra
   ou a corta. Empilhado, cada fileira tem a largura inteira, e a única perda é
   rolagem que este painel não tem (ele cresce para cima, e são cinco grupos).
   Mesmo corte da linha da lista, pelo mesmo motivo. */
@media (max-width: 480px) {
  #ajustes .grade { grid-template-columns: 1fr; gap: .75rem; }
}

/* O rótulo vira sobrancelha: a mesma voz do `.eyebrow` da lista e do
   `.rotulo-temas`. Em cima da fileira, e não ao lado, é o que devolve a
   largura que a calha comia. */
#ajustes .rotulo {
  display: block; font-size: .62rem; font-weight: 600; letter-spacing: .09em;
  text-transform: uppercase; color: var(--tenue); margin: 0 0 .4rem .1rem;
}
#ajustes .opcoes { display: flex; gap: .4rem; }

/* Um só botão para as cinco linhas. `flex: 1` e não largura fixa: as três
   opções dividem a coluna em partes iguais, e a fileira acaba onde a medida
   acaba — é isso que fecha o vazio à direita. */
#ajustes .opcao {
  flex: 1; display: flex; flex-direction: column; align-items: center;
  justify-content: center; gap: .3rem;
  /* Altura ÚNICA para os cinco grupos, e não `min-height: var(--alvo)`: as
     opções com glifo e palavra chegam a ~54px sozinhas, as de só glifo param
     nos 44px do alvo, e as duas colunas da grade saíam desencontradas — o
     `A−` visivelmente mais baixo que o `Compacta` ao lado. Uma altura fixa
     alinha as fileiras e continua acima do alvo mínimo. */
  min-height: 3.4rem; padding: .5rem .3rem;
  border: 1px solid var(--borda-controle); border-radius: var(--raio-p);
  background: none; color: var(--tinta); font-family: var(--sans);
  cursor: pointer; overflow: hidden;
}
#ajustes .opcao:hover, #ajustes .opcao:focus-visible {
  border-color: var(--acento); color: var(--acento);
}
#ajustes .opcao[disabled] { opacity: .4; cursor: default; }
#ajustes .opcao[disabled]:hover { border-color: var(--borda-controle); color: var(--tinta); }

/* Escolhido. Mesma língua do `[aria-pressed]` dos botões de estado (L-70):
   tinta, borda e um fundo tingido — três pistas, não uma. */
#ajustes .opcao[aria-pressed="true"] {
  color: var(--acento); border-color: var(--acento);
  background: color-mix(in srgb, var(--acento) 12%, transparent);
}
#ajustes .nome { font-size: .68rem; line-height: 1; color: inherit; }

/* A fonte se apresenta na própria fonte — a amostra mais óbvia das cinco, e a
   que a versão anterior deixava passar: os três nomes vinham no mesmo sans da
   interface, então escolher "Source Serif" era escolher no escuro. */
/* ── O espécimen  (revisão 2026-08-24) ─────────────────────────────────────
   Só o nome na própria face era amostra tímida: em ~16px, Literata e Source
   Serif são duas serifas que se distinguem por espremer os olhos. O "Ag" —
   o par clássico de espécimen de fundição, uma caixa-alta de haste e uma
   minúscula de bojo e descendente — mostra o desenho da face num tamanho em
   que a diferença é visível de relance, e o nome desce para rótulo.

   O "Ag" entra por `::before`, NÃO por markup, e isso é deliberado: o
   pseudo-elemento herda a família de `[data-face]` sozinho, o leitor de
   tela não anuncia um "Ag" sem sentido (o `aria-label` do botão já diz
   "Fonte: Literata"), e o contrato que os testes cravam — nenhum `.nome`
   dentro de `.am-fonte`, a palavra é a amostra — continua verdadeiro
   letra a letra. */
#ajustes .am-fonte {
  display: flex; flex-direction: column; align-items: center; gap: .42rem;
  font-size: .7rem; line-height: 1;
}
#ajustes .am-fonte::before { content: "Ag"; font-size: 1.7rem; line-height: 1; }
#ajustes .grupo[data-grupo="fonte"] .opcao { min-height: 4.7rem; }
#ajustes .am-fonte[data-face="literata"]     { font-family: var(--serif); }
#ajustes .am-fonte[data-face="source-serif"] { font-family: var(--serif-leitura); }
#ajustes .am-fonte[data-face="inter"]        { font-family: var(--sans); }
#ajustes .am-fonte[data-face="charter"]      { font-family: var(--serif-charter); }

/* Entrelinha: três filetes, com o vão do valor. A caixa tem altura fixa para
   que o botão não mude de tamanho entre as opções — o que muda é o ar. */
#ajustes .am-linhas {
  display: flex; flex-direction: column; justify-content: center;
  width: 1.6rem; height: .9rem;
}
#ajustes .am-linhas i { height: 1px; background: currentColor; opacity: .75; }
#ajustes [data-valor="compacta"] .am-linhas { gap: 2px; }
#ajustes [data-valor="normal"]   .am-linhas { gap: 4px; }
#ajustes [data-valor="arejada"]  .am-linhas { gap: 6px; }

/* Largura: a coluna dentro da página. A caixa é a página, o filete é o texto,
   e é a razão de a caixa existir — sem a moldura de referência, três filetes
   soltos de larguras parecidas não dizem "estreita" nem "larga", dizem só
   "filete". A moldura vem em `--regra` e não em `currentColor` para não
   competir com o filete, que é o que muda. */
#ajustes .am-largura {
  display: flex; align-items: center; justify-content: center;
  width: 1.9rem; height: 1.05rem;
  /* Derivada de `currentColor` e não de `--regra`: em `--regra` a moldura
     sumia no sépia, e uma moldura quase invisível é pior que nenhuma — lê
     como sujeira, não como página. A 32% ela fica claramente presente e
     ainda assim atrás do filete, que é o que carrega a informação. */
  border: 1px solid color-mix(in srgb, currentColor 32%, transparent);
  border-radius: 2px;
}
#ajustes .am-largura i { height: 2px; background: currentColor; opacity: .8; }
#ajustes [data-valor="estreita"] .am-largura i { width: 30%; }
#ajustes [data-valor="media"]    .am-largura i { width: 58%; }
#ajustes [data-valor="larga"]    .am-largura i { width: 88%; }

/* Tema: o papel e a tinta daquele tema, literais. São as únicas cores fixas
   do arquivo, e por isso mesmo: um token resolveria para o tema CORRENTE, e
   a amostra existe para mostrar um tema em que ainda não se está. Os valores
   saem de `[data-tema]` no núcleo — `--papel` e `--tinta` de cada um. */
#ajustes .am-tema {
  display: flex; align-items: center; justify-content: center;
  width: 1.6rem; height: 1.15rem; border-radius: 3px;
  border: 1px solid var(--regra);
  font-family: var(--serif); font-size: .72rem; line-height: 1;
}
#ajustes .am-tema[data-t="claro"]  { background: #faf8f4; color: #22211d; }
#ajustes .am-tema[data-t="sepia"]  { background: #f3e8da; color: #2e2519; }
#ajustes .am-tema[data-t="escuro"] { background: #16171a; color: #e4e2dd; }
/* O auto é metade e metade — e as duas metades são as que ELE produz: sépia de
   dia, escuro de noite. Sem o «Aa», porque letra nenhuma é legível sobre a
   divisa e o nome embaixo já diz o que é. */
#ajustes .am-tema[data-t="auto"] {
  background: linear-gradient(105deg, #f3e8da 50%, #16171a 50%);
  color: transparent;
}

/* ── O passo do tamanho é UM controle, não três coisas soltas ──────────────
   Na primeira volta eram dois botões com borda e um punhado de bolinhas
   flutuando no meio — três objetos onde há uma decisão só, e o único grupo do
   painel que não parecia um grupo. A moldura passa para a fileira e os botões
   ficam nus por dentro, separados por filete: um estepe, como o `A− A+` de
   qualquer leitor. */
#ajustes .grupo[data-grupo="tamanho"] .opcoes {
  gap: 0; border: 1px solid var(--borda-controle);
  border-radius: var(--raio-p); overflow: hidden;
}
#ajustes .passo-btn {
  flex: none; width: 3.2rem; font-size: .95rem;
  border: 0; border-radius: 0; min-height: 3.4rem;
}
#ajustes .passo-btn:first-child { border-right: 1px solid var(--regra); }
#ajustes .passo-btn:last-child  { border-left: 1px solid var(--regra); }
/* Sem o realce de borda dos outros: aqui a borda é da fileira, e pintá-la a
   partir de um botão de dentro acenderia o controle inteiro no hover de meia
   dúzia de pixels. */
#ajustes .passo-btn:hover, #ajustes .passo-btn:focus-visible { border-color: var(--regra); }

/* As sete posições de 02 §4, que o `0` cru nunca mostrou. */
#ajustes .passo {
  flex: 1; display: flex; align-items: center; justify-content: center; gap: .32rem;
}
/* 8px e não 6: o medidor existe para ser CONTADO de relance — "estou no
   quarto de sete" —, e a 6px distinguir cheia de vazia exigia parar e olhar,
   que é justamente o que um medidor deve poupar. */
#ajustes .passo i {
  width: 8px; height: 8px; border-radius: 50%; flex: none;
  border: 1px solid var(--borda-controle);
}
#ajustes .passo i.on { background: var(--acento); border-color: var(--acento); }

/* ── destaque (L-49, refeito na spec 45) ───────────────────────────────────
   O texto NÃO muda de cor. Quem lê marcou o trecho, não pediu outra fonte.

   ── O `<mark>` saiu daqui, e a razão é o parágrafo inteiro ─────────────────

   Até 10/09 o destaque era `<mark class="leitor-hl">` no DOM, com
   `padding: .08em 0` para fechar o vão entre as linhas. A nota que morava aqui
   contava metade da história: em 02/09 tirou-se o `box-decoration-break:
   clone` porque ele "fazia o WebKit abandonar o `text-wrap: pretty` do
   parágrafo inteiro". Estava certo, e era metade — **o elemento inline, e não
   a decoração dele, é o que muda o insumo do `pretty`**, que no WebKit é
   otimização de parágrafo e não de linha.

   Medido no Safari 26.6.2 (`interacao-quebras.mjs`): com `<mark>`, 14 de 360
   combinações de fonte × largura × espaçamento × corpo × posição da marca
   remaquetam o parágrafo; num caso ele sai byte a byte igual ao layout
   guloso. Um `<span>` sem estilo nenhum faz o mesmo, e trocar o `text-wrap`
   não resolve — com o guloso ainda são 8/360, e a órfã volta em 8 de 81
   perfis. O relato que fechou o caso: «quando faz uma marcação as vezes muda
   a disposição do texto. fica ruim».

   Marcar um trecho não pode remaquetar a página que se está lendo. O pigmento
   passou à Custom Highlight API, que pinta sem nó nenhum — a mesma peça que a
   voz usa desde a spec 11, e o `pretty` fica intocado.

   ── O que se perdeu, e o que não se perdeu ────────────────────────────────

   `::highlight()` aceita cor, `text-decoration` e sombra — não aceita padding
   nem raio. Perdeu-se: os `.08em` verticais e os 2px de canto. **Não** se
   perdeu o bloco contínuo, que era o medo: capturado lado a lado, o `<mark>`
   pinta 137px de faixa contínua e o highlight 134px — os 3px são o padding, e
   não há listra entre as linhas.

   `opacity` continua fora daqui, e pela razão de sempre: ela apagaria o texto
   junto com o fundo. Marcação mais fraca no escuro é propriedade da COR, e
   vive nos tokens do tema.

   Quem pinta cada nome é `pigmento.mjs`; a lista dos nomes é `NOMES` lá.
   ───────────────────────────────────────────────────────────────────────── */
::highlight(destaque-amarelo) { background-color: var(--hl-amarelo); }
::highlight(destaque-roxo)    { background-color: var(--hl-roxo); }
::highlight(destaque-rosa)    { background-color: var(--hl-rosa); }
::highlight(destaque-azul)    { background-color: var(--hl-azul); }

/* ── O destaque que tem nota  (L-51, refeito na spec 45) ───────────────────
   Era uma bolinha de 4px na ÚLTIMA marca do destaque, por `::after`. Sem
   elemento não há pseudo-elemento, e a informação — «este trecho tem nota
   escrita» — passa a ser dita pelo sublinhado pontilhado do trecho inteiro.

   A troca preserva as três decisões da L-51 e melhora uma: continua havendo um
   sinal no CORPO (nota que ninguém vê é nota perdida), continua sendo um sinal
   só por destaque (a bolinha em cada fragmento dizia três vezes o mesmo fato),
   continua fora da margem (indicador de margem marca o parágrafo, e o destaque
   é de um trecho) — e agora o sinal cobre exatamente o trecho anotado, em vez
   de pousar no fim dele.

   `--tinta-2` e não o acento: a nota é fato registrado, não chamado de ação. */
::highlight(destaque-amarelo-nota),
::highlight(destaque-roxo-nota),
::highlight(destaque-rosa-nota),
::highlight(destaque-azul-nota) {
  text-decoration: underline dotted var(--tinta-2);
  text-decoration-thickness: 1px;
  text-underline-offset: .18em;
}
::highlight(destaque-amarelo-nota) { background-color: var(--hl-amarelo); }
::highlight(destaque-roxo-nota)    { background-color: var(--hl-roxo); }
::highlight(destaque-rosa-nota)    { background-color: var(--hl-rosa); }
::highlight(destaque-azul-nota)    { background-color: var(--hl-azul); }

/* ── A frase que a voz está lendo  (Bloco J, spec 11 §6) ────────────────────
   Pintada pela Custom Highlight API (`leitura-falada.mjs`), que **não toca
   no DOM** — só por isso ela convive com os quatro `<mark>` acima sem que um
   apague o outro: um destaque de leitura em `<mark>` morreria na primeira
   repintura do motor (`repintar()` reescreve o `innerHTML` do bloco inteiro).

   O tom é deliberadamente MAIS FRACO que qualquer `--hl-*`: aqueles são
   pigmento opaco (uma decisão que fica na página); este é acompanhamento
   passageiro, que desliga sozinho quando a frase muda. `var(--leitura)` a
   12% no claro e no sépia — abaixo dos 14–16% que este arquivo já usa para
   tingir um ESTADO (`.acao-estado[aria-pressed]`, `.armado`) — e não um
   `--hl-*`: usar a família do destaque faria o olho ler "isto é um destaque
   marcado", que é exatamente a confusão que a §6 da spec pede para evitar.

   2026-08-26 — deixou de ser `var(--acento)` a 12% cravado. A cor veio para a
   família própria e a força virou token por tema; as duas razões estão na nota
   "── O acompanhamento da voz saiu do `--acento`" lá em cima. Uma regra só
   continua servindo aos três temas — só que agora respondendo a tokens que
   sabem em qual tema estão. */
::highlight(leitura) {
  background-color: color-mix(in srgb, var(--leitura) var(--leitura-forca), transparent);
}

/* ── A palavra que a voz está dizendo AGORA  (Bloco J2, spec 11) ────────────
   Segundo `Highlight`, registrado sob o nome `leitura-palavra` pelo
   `leitura-falada.mjs`, e ele acende POR DENTRO da faixa de cima — os dois ao
   mesmo tempo, sempre, porque respondem a perguntas diferentes (a faixa diz
   onde estou no texto; a palavra, o que está sendo dito). Daí as duas
   exigências que fixam esta regra:

   1. **Mais forte que a faixa, sem margem de dúvida.** A faixa é `--leitura`
      enfraquecida pela força do tema: 1,25:1 no claro, 1,25:1 no sépia e
      1,46:1 no escuro contra a página. A palavra é a cor CHEIA — 8,41:1 no
      claro, 8,18:1 no sépia, 7,91:1 no escuro. Não é um degrau a mais de
      intensidade, é outra ordem de grandeza, e é o que faz o olho achar a
      palavra dentro da faixa sem procurar. A WCAG 1.4.11 pede 3:1 para realce
      não-textual; os três passam com folga de 2,6×.

   2. **Nunca confundível com marcação da Pencil.** A cor ser outra não bastava
      como argumento, embora também seja verdade (`--leitura` fica a 4,68–6,30:1
      de qualquer `--hl-*`). O que de fato separa as duas coisas é o MECANISMO,
      e ele já está escrito três regras acima: a marcação **não muda a cor do
      texto** — "quem lê marcou o trecho, não pediu outra fonte". A voz inverte:
      o papel sobe para cima da cor. Marcação é pigmento POR BAIXO da letra,
      que fica na página; a voz passando é a letra vestindo outra cor por um
      instante. São gestos visualmente distintos antes de serem cores
      distintas, e o leitor não precisa comparar matiz para saber qual é qual.

      Desde 26/08 há uma terceira separação, e ela é de PALETA: a voz é
      acromática nos três temas e a marcação é o único pigmento saturado da
      página. Ver a nota da família lá em cima.

   `--sobre-leitura`, e não `--tinta`: no escuro a cor é o cinza-osso CLARO, e
   tinta clara por cima dela daria ~1,2:1. O token existe exatamente para essa
   pergunta ("quem escreve sobre a cor pergunta ao token") e responde certo
   nos três temas — 8,92 · 9,89 · 7,91:1.

   Só `background-color` e `color` porque `::highlight()` aceita um
   subconjunto pequeno de propriedades: `border`, `padding` e `transform`
   seriam ignorados **em silêncio**. Registrado para quem vier tentar
   arredondar o canto daqui e concluir que o navegador está quebrado. */
/* ── A palavra acesa volta ao acento  (2026-09-01, prancha 1i) ─────────────
   «A palavra acende na brasa», e ela acende.

   O caminho até aqui vale registro, porque o erro foi de INSTRUMENTO. A nota
   de 26/08 acima tirou a voz do acento por uma colisão real: em 21/08 o acento
   do escuro virou púrpura `#c19ae6`, a 6,2° do `--hl-roxo` `#42305c`, e três
   coisas caíram na mesma família de matiz naquele tema. O guarda que nasceu
   dali mede **matiz ou croma** — e recusou a brasa, porque ela fica a 27,9° do
   marca-texto no escuro e a 29,5° no claro.

   Só que matiz não é o que separa este par. Luminância é:

     escuro   voz #f39d7a × pigmento #463911 →  5,35:1
     claro    voz #832f0d × pigmento #eed88a →  6,24:1

   E há uma diferença estrutural entre 21/08 e hoje que o número sozinho não
   conta: naquela rodada a BANDA e a palavra eram as duas do acento, então um
   pigmento na mesma família fazia três coisas rimarem. Hoje a banda é
   `--leitura`, neutra — sobram duas, e elas se separam por valor.

   Por isso o guarda foi estendido, e não dispensado: ele passa a aceitar
   separação por luminância **desde que a banda continue neutra**. Com essa
   condição ele segue reprovando o caso de 21/08, que tinha 4,99:1 de
   luminância e colidia mesmo assim — luminância sozinha nunca o teria pego. */
::highlight(leitura-palavra) {
  background-color: var(--acento);
  color: var(--sobre-acento);
}

/* ── Régua de linha  (Bloco J2, `data-regua`) ───────────────────────────────
   CHI 2023, "Digital Reading Rulers": +86 palavras/min em média, com ganho
   maior entre leitores disléxicos, e entre os estilos testados o preferido foi
   o *Lightbox* — escurecer tudo MENOS a linha corrente, em vez de sublinhar
   ou emoldurar a linha. É o que está implementado aqui.

   ── A técnica, e por que não são dois retângulos ───────────────────────────
   O véu é um `box-shadow` de espalhamento 100vmax no PRÓPRIO elemento da
   faixa: a sombra cobre a tela inteira e o elemento recorta o próprio buraco.
   A alternativa óbvia — uma div acima e outra abaixo — custa dois elementos a
   posicionar em sincronia e reintroduz, em dobro, o problema que a linha
   seguinte resolve. Uma caixa, uma sombra, nenhum retângulo por cima do texto.

   ── `pointer-events: none` é requisito, não higiene ────────────────────────
   A 14 §4.2 registra a regra em letra de forma: o que não recebe toque não tem
   como roubar o `caretRangeFromPoint`. Um elemento fixo sobre a prosa SEM esta
   linha responde ao hit-test no lugar do texto, e o traço da Pencil passa a
   marcar nada — reprovando o critério de aceite do projeto ("20 destaques
   seguidos sem um traço errado"). A régua fica por cima da coluna inteira
   enquanto o áudio toca: sem isto, ela é o pior infrator que este app já teve.

   ── O alpha do véu muda por tema, e a razão foi medida ──────────────────────
   O lightbox funciona por caminhos OPOSTOS no claro e no escuro, e isso só
   aparece quando se mede em vez de copiar o número:
   · claro e sépia — o véu escurece o PAPEL (1,98:1 e 1,80:1 contra a faixa) e
     quase não toca no texto, que já era escuro (1,10:1 e 1,02:1). A faixa é
     que brilha. O texto de fora segue perfeitamente legível, a 8,49:1 e
     7,20:1 sobre o próprio fundo velado: recuar não é apagar, e o leitor
     ainda enxerga o parágrafo em volta.
   · escuro — não há para onde escurecer um papel que já é `#16171a`: o fundo
     mede 1,10:1 velado, ou seja, nada. Quem recua é o TEXTO — `--tinta` clara
     sob 55% de preto cai 4,44:1, indo de 16,5:1 contra a página para 3,45:1.
     Mesmo efeito, outro mecanismo. Por isso o alpha do escuro é o dobro do
     dos claros, e não um descuido a "uniformizar" um dia.

   O sépia usa preto QUENTE (`#3c280a`, o mesmo pigmento das sombras do sépia
   no núcleo): preto puro sobre papel amarelado sai cinza e frio, e a página
   inteira trocaria de temperatura fora da faixa.

   `--veu` mora aqui, e não no bloco de tema lá em cima, porque tem um único
   consumidor e porque a razão dos três valores é uma coisa só — separá-los
   deixaria três números órfãos da conta que os produziu. */
[data-tema="claro"]  { --veu: rgba(0,0,0,.28); }
[data-tema="sepia"]  { --veu: rgba(60,40,10,.30); }
[data-tema="escuro"] { --veu: rgba(0,0,0,.55); }

#regua {
  position: fixed; left: 0; right: 0;
  pointer-events: none;
  box-shadow: 0 0 0 100vmax var(--veu);
  /* Acima da prosa e ABAIXO de todo o cromo — a barra (40), o tempo (44), o
     botão da caneta (45/46), as ações (60). Velar a própria interface faria o
     app parecer desligado toda vez que o áudio começasse. */
  z-index: 30;
  /* `top` e `height` são do JS, e não por preguiça de CSS: linha não é
     elemento. Só o retângulo do `Range` da palavra sabe onde a linha caiu
     depois que fonte, tamanho, entrelinha e largura do leitor foram
     aplicados. */
  display: none;
  transition: top var(--dur) var(--curva);
}

/* Acesa só sob os dois valores que ligam a régua, e só quando o JS não a
   escondeu. É cinto E suspensório de propósito: `nao` é o padrão e custa
   `display: none` — nem sombra, nem camada de composição, nem pintura —, e o
   `:not([hidden])` garante que ela não fique acesa sobre um artigo parado. O
   `esconderRegua()` do `leitura-falada.mjs` a apaga quando o áudio termina;
   se um dia ele falhar, o pior caso vira uma régua esquecida na última linha
   lida, e não uma página velada sem áudio nenhum. Cada um dos dois já
   bastaria; nenhum dos dois custa. */
[data-regua="uma"] #regua:not([hidden]),
[data-regua="tres"] #regua:not([hidden]) { display: block; }

/* O véu de três linhas tinha opacidade própria (.72, "a faixa larga já dá
   contexto") e ela SAIU em 27/08, a pedido do Yuri: o tom deve ser o mesmo
   nas duas réguas. O argumento que a derrubou é de percepção — a troca de tom
   era o único efeito instantâneo de mudar a régua (a altura vinha de uma
   cópia que só o preparo escrevia, defeito consertado no mesmo dia), então o
   véu mais fraco lia-se como "mudou alguma coisa, mas não o que pedi". */

/* A régua salta de linha em linha, e o salto É o movimento: sem transição ela
   pisca de posição, com ela o olho é conduzido. Quem pediu menos movimento não
   pediu menos régua — pediu o corte seco, que é o que fica. */
@media (prefers-reduced-motion: reduce) {
  #regua { transition: none; }
}

/* ── As duas amostras do painel  (Bloco J2) ─────────────────────────────────
   Ficam aqui, e não junto das outras cinco lá em cima, pela mesma razão que
   pôs `.am-marg` no bloco da marginália: o desenho de uma amostra é
   consequência do que a opção faz, e as duas mudam pelo mesmo motivo.

   A régua repete a gramática de `.am-linhas` — filetes numa caixa de altura
   fixa —, com a diferença que carrega a informação: aqui o que muda não é o
   vão entre os filetes, é **qual deles está aceso e quanto a caixa escurece**.
   É o lightbox em 15px, e é o único jeito de "Uma linha" e "Três linhas"
   dizerem algo antes de o leitor ligar o áudio e ver na página.

   O espaçamento se mostra em si mesmo, como a fonte faz: `abc` na medida da
   opção. Sem isso, "Arejado" é uma palavra sobre uma palavra. */
#ajustes .am-regua {
  display: flex; flex-direction: column; justify-content: center; gap: 3px;
  width: 1.6rem; height: 1.05rem; padding: 0 2px; border-radius: 2px;
}
#ajustes .am-regua i { height: 1px; background: currentColor; opacity: .16; }
/* Sem régua: os três filetes iguais, e nenhum véu — a página como está hoje. */
#ajustes .am-regua[data-r="nao"] i { opacity: .7; }
/* O véu da amostra vem de `currentColor` e não de `--veu`: o botão herda a
   tinta do estado (e o acento quando escolhido), então a amostra acompanha o
   controle em vez de destoar dele. `--veu` é preto, e preto dentro de um botão
   aceso em acento leria como sujeira. */
#ajustes .am-regua[data-r="uma"] {
  background: color-mix(in srgb, currentColor 20%, transparent);
}
#ajustes .am-regua[data-r="uma"] i:nth-child(2) { opacity: 1; }
/* Três linhas: a faixa toma a caixa inteira, e o véu é mais fraco — a mesma
   relação que `[data-regua="tres"] #regua { opacity: .72 }` tem na página. */
#ajustes .am-regua[data-r="tres"] {
  background: color-mix(in srgb, currentColor 12%, transparent);
}
#ajustes .am-regua[data-r="tres"] i { opacity: .95; }

#ajustes .am-espaco { font-family: var(--corpo, var(--serif)); font-size: 1rem; line-height: 1.15; }
#ajustes .am-espaco[data-e="arejado"] { letter-spacing: .06em; word-spacing: .18em; }

/* NÃO há filete de margem, e isso é decisão testada no iPad (03 §5.1), não
   esquecimento. A barra marca o PARÁGRAFO inteiro enquanto o destaque é de um
   TRECHO: o olho lê a barra como se o bloco todo estivesse marcado, e a
   discrepância incomoda em leitura longa. O <mark> já diz onde o destaque
   está; um segundo indicador com granularidade diferente subtrai informação.

   A classe `.tem-destaque` continua sendo posta no bloco — serve de âncora
   para o salto de volta da L-54 —, mas sem pintura. O §3.3 da spec ainda
   mostra o filete num trecho de CSS antigo; quem vale é o §5.1, que é
   posterior e registra o teste. */

/* ── A seleção nativa É o feedback do modo B ───────────────────────────────
   `user-select: none` NÃO entra aqui, e a regra tem dono: no protótipo ela
   existe presa ao **modo A** (`[data-gesto="tinta"]`), onde a tinta ao vivo
   competiria com a seleção do sistema. O modo B venceu a L-04b justamente
   porque a seleção mostra o alcance ENQUANTO se arrasta — desligá-la apaga o
   feedback inteiro: o traço passa a funcionar às cegas e só aparece depois de
   confirmado.

   `pan-y` preserva o scroll vertical do dedo e mata gesto horizontal; o
   `touch-callout` evita o menu do iOS disputando o toque longo. */
.prosa.modo-caneta { touch-action: pan-y; -webkit-touch-callout: none; }

/* E ela é pintada NA COR ATIVA, a 62%: o que se vê antes de confirmar é o
   resultado, não uma seleção azul de sistema que não diz nada sobre o que vai
   ficar na página. */
.prosa::selection, .prosa *::selection {
  background-color: color-mix(in srgb, var(--cor-ativa, var(--hl-roxo)) 62%, transparent);
  color: inherit;
}
[data-cor-ativa="roxo"]    { --cor-ativa: var(--hl-roxo);    --cor-ativa-viva: var(--vivo-roxo); }
[data-cor-ativa="amarelo"] { --cor-ativa: var(--hl-amarelo); --cor-ativa-viva: var(--vivo-amarelo); }
[data-cor-ativa="rosa"]    { --cor-ativa: var(--hl-rosa);    --cor-ativa-viva: var(--vivo-rosa); }
[data-cor-ativa="azul"]    { --cor-ativa: var(--hl-azul);    --cor-ativa-viva: var(--vivo-azul); }

/* O botão é o ÚNICO indicador de modo. Um contorno na área de texto foi
   testado no Bloco A e descartado: no iPad, onde o modo vive ligado, virava
   moldura permanente em volta do artigo. Estado da ferramenta se comunica na
   ferramenta, não na superfície de trabalho. */
/* Acima da barra inferior, e por isso o `--barra-h`: sobre ela, o botão
   cairia sobre um alvo de navegação — e o dedo que quer marcar acertaria
   "Destaques". */
/* Desde 02/09 a forma, a superfície e a posição vêm da CÁPSULA — aqui fica só
   o que é da caneta: o glifo e o estado ligado. A nota de cima («acima da
   barra inferior, para o dedo não acertar Destaques») continua valendo: quem
   a honra agora é a base da pilha, `--pilha-y`. */
#caneta { font-size: 1.25rem; }
/* O botão ligado veste a COR ATIVA — é onde o leitor lê em que cor vai marcar,
   sem abrir nada. Cor viva e texto escuro em qualquer tema: é cromo sobre
   cromo, não marcação sobre texto. */
/* O halo encolheu de 6px para 5px e perdeu a sombra composta: dentro de uma
   cápsula com `overflow: hidden` o anel de 6px era cortado pela borda, e uma
   sombra erguida dentro de uma peça que já tem a dela é sombra duplicada. */
#caneta[aria-pressed="true"] {
  background: var(--cor-ativa-viva, var(--vivo-roxo)); color: #201c14;
  box-shadow: 0 0 0 5px color-mix(in srgb, var(--cor-ativa-viva, var(--vivo-roxo)) 34%, transparent);
}

/* ── A bolha de perguntar  (Bloco J8) ──────────────────────────────────────
   Primeiro degrau, colada na caneta, e a razão é uma regra de coluna que vale
   daqui para a frente: **embaixo o que age sobre o texto, em cima o que
   configura a tela.** Marcar e perguntar são o mesmo gesto de leitura — a
   reação ao parágrafo que se acabou de ler —, e são os dois que precisam do
   alcance curto do polegar. Ouvir, velocidade e `Aa` sobem um degrau por isso.

   O `?` em SERIFA, como o `Aa` do quarto degrau: num círculo de 56px o sinal
   deixa de ser ícone de sistema (onde `?` significa «ajuda») e vira marca
   tipográfica — e este app não tem ajuda nenhuma para o sinal disputar.

   NEUTRA como as irmãs, e não vestida do acento que o `.btn.ia` do rodapé usa:
   na coluna o acento já quer dizer «este painel está aberto» (ver a velocidade
   e o `Aa`), e um terceiro sentido para a mesma cor, permanente, apagaria os
   outros dois. Quem carrega a identidade da IA é o sheet que ela abre. */
#perguntar-flutuante {
  font-family: var(--serif); font-size: 1.35rem; font-weight: 500;
}
#perguntar-flutuante[hidden] { display: none; }

/* ── Controle flutuante de pausar/retomar a leitura falada (Bloco J) ───────
   O dono relatou o problema de ponta a ponta: o player mora no cabeçalho,
   pausar exige rolar até lá, rolar é gesto manual e desliga o acompanhamento
   automático — o próprio ato de alcançar o controle mata o que ele foi
   buscar. Isto é o conserto: um controle igual em espécie ao `#caneta`
   acima (mesmo tamanho, mesmo `position: fixed`, mesmo canto), sempre ao
   alcance do polegar sem precisar sair do lugar onde se está lendo.

   EMPILHADO acima do `#caneta`, não ao lado: os dois vivem juntos na tela de
   artigo, e uma coluna no mesmo canto não disputa o polegar do jeito que duas
   bolhas lado a lado disputariam — nem exige decidir uma segunda coordenada
   horizontal.

   ── Perene, desde o Bloco J6 ──────────────────────────────────────────────
   Este botão aparecia só DURANTE a escuta, e a janela era curta demais: quem
   volta a um artigo de 50 minutos cai no meio do texto, onde não havia play
   nenhum — o cabeçalho ficava a uma rolagem inteira, e a rolagem era o gesto
   que o botão de cima existe para não exigir. Agora ele acompanha o ARTIGO,
   como o `#caneta`, e o que muda com o estado da voz é o glifo (▶/⏸). Só o
   `#rolagem-flutuante` abaixo continua preso à sessão — fora dela não há
   rolagem que acompanhe voz nenhuma. */
/* A POSIÇÃO deixou de ser declarada item a item: quem ordena os três é a
   ordem no DOM, dentro da cápsula. É o que faz uma bolha que some não deixar
   buraco — antes, com degrau fixo, as de cima não desciam para ocupar o lugar
   dela. */
#ouvir-flutuante { font-size: 1.25rem; }

/* ── O relógio da espera  (06/09) ──────────────────────────────────────────
   «hoje eu clico e nada acontece, e demora muito a gerar.» O glifo do play dá
   lugar a `1:32` enquanto a Azure sintetiza, e volta ao `▶` quando a narração
   chega. A receita tipográfica é a da bolha da velocidade ao lado, e pelo
   mesmo motivo: cinco caracteres num círculo de 48px, com o pior caso
   (`12:03`) medido no harness em vez de estimado.

   `tabular-nums` não é capricho — o número repinta a cada segundo, e sem
   largura fixa de algarismo «1:19» e «1:11» ocupam larguras diferentes: o
   texto pularia de lado uma vez por segundo.

   NENHUMA animação, e isso é decisão. Pulsar a opacidade de um glifo parado
   (o que a bolinha da lista faz) diz «vivo»; pulsar um texto que se LÊ atrapalha
   a leitura dele. Aqui o sinal de vida é o próprio relógio andando.

   `--cromo-acento` porque a cápsula é campo grafite nos três temas: o acento
   do papel seria tinta escura sobre campo escuro. Mesma regra de 02/09 —
   clarear a tinta, nunca o campo. */
#ouvir-flutuante[data-estado="gerando"] {
  font-family: var(--sans); font-size: 11px; font-weight: 600;
  font-variant-numeric: tabular-nums; letter-spacing: -.01em;
  color: var(--cromo-acento);
}

/* A síntese parou, e o botão que se tocou é quem conta. O motivo inteiro está
   no `aria-label` e no `title` — num círculo de 48px não cabe frase, e a frase
   continua também no aviso do cabeçalho, que tem a largura para ela. */
#ouvir-flutuante[data-estado="falhou"] {
  font-family: var(--sans); font-size: 1.1rem; font-weight: 700;
  color: var(--cromo-perigo);
}

/* ── A bolha da velocidade da narração  (Bloco J7) ─────────────────────────
   Terceiro degrau. Ela é a única bolha da coluna que carrega TEXTO em vez de
   glifo, e isso não é estilo: é o desenho. Um velocímetro desenhado diria
   «aqui se muda a velocidade» sem dizer QUAL — e a pergunta que se faz
   olhando para a tela é a segunda. O número é o estado; o deslizante que ela
   abre é a mudança.

   `tabular-nums` porque o valor troca sozinho enquanto o dedo arrasta o
   deslizante ao lado, e sem largura fixa de algarismo o texto dança dentro do
   círculo.

   `.72rem`, e ela é a MENOR letra da coluna — menor até que a do percentual ao
   lado, que também carrega texto. Não é inconsistência: é que o pior caso dela
   tem cinco caracteres (`1,25×`), e o do percentual tem três (`23%`). Medir a
   fonte pelo rótulo mais curto é como o texto estoura em silêncio.

   Foi exatamente o que aconteceu ao encolher a bolha de 56 para 48px em 01/09:
   `.86rem` desceu para `.8rem`, o `23%` ficou com 17px de folga e o `1,25×`
   ficou com **zero** — dentro do círculo, encostado nas duas bordas. O harness
   agora mede `clientWidth − scrollWidth` nas duas e exige 8px, para que a
   próxima mudança de diâmetro seja um teste vermelho e não uma descoberta no
   aparelho. */
#velocidade-flutuante {
  font-family: var(--sans); font-size: 11px; font-weight: 600;
  font-variant-numeric: tabular-nums; letter-spacing: -.01em;
}
#velocidade-flutuante[hidden] { display: none; }
/* Aberta, ela veste o acento: o painel ao lado é um objeto flutuante sobre a
   mesa, e sem a bolha acesa não há nada dizendo de onde ele saiu. */
/* Aberta, ela veste o acento. A borda saiu junto com a bolha: dentro da
   cápsula o item não tem contorno próprio, então quem diz «este está aberto» é
   a tinta e o leito. */
/* Sobre o campo grafite quem diz «aberto» é o `--cromo-acento` — o acento do
   tema escuro, em qualquer tema (02/09). O acento do papel, aqui, seria tinta
   escura sobre campo escuro. */
#velocidade-flutuante[aria-expanded="true"] {
  color: var(--cromo-acento);
  background: color-mix(in srgb, var(--cromo-acento) 13%, transparent);
}

/* ── O deslizante que ela abre ─────────────────────────────────────────────
   Ao LADO da bolha, e não por cima da coluna: o dedo que acabou de tocar o
   número continua sobre ele, e um painel que nascesse embaixo do dedo seria
   um painel que o próprio toque de abertura já estaria arrastando.

   Alinhado pela BASE da bolha, com `min-height` igual ao diâmetro dela: as
   duas peças formam uma fileira só, e centrar por `transform` exigiria saber
   a altura do painel, que depende do texto.

   A largura é o que sobra da tela depois da coluna, com teto de 20rem — o
   trilho precisa de curso útil, e num telefone de 375px o que sobra ainda dá
   uns 270px. Abaixo disso o `.velocidade` do painel de voz já quebra a
   fileira sozinho. */
#velocidade-painel {
  position: fixed; z-index: 47;
  /* Ancorado na CÁPSULA, e não mais numa bolha solta: à esquerda dela, e
     alinhado pela base do item de velocidade — que é o terceiro da pilha
     contando de baixo (`--y-velocidade`). As duas contas saem dos tokens da
     geometria, então mudar a altura de um item move o painel junto. */
  right: calc(var(--capsula-x) + var(--capsula-l) + .6rem);
  bottom: calc(var(--pilha-y) + var(--y-velocidade));
  width: min(20rem, calc(100vw - var(--capsula-x) * 2 - var(--capsula-l) - .6rem));
  min-height: var(--capsula-item);
  display: flex; align-items: center;
  padding: .5rem .8rem;
  background: var(--papel-elev); border: 1px solid var(--papel-borda);
  border-radius: var(--raio); box-shadow: var(--sombra-erguida);
  transition: opacity var(--dur) var(--curva), transform var(--dur) var(--curva);
}
/* `visibility`, e não só `opacity`: um painel transparente continua sendo uma
   parada de teclado e continua sendo lido pelo VoiceOver. E não `display:
   none`, que levaria a transição junto. */
#velocidade-painel[data-aberto="nao"] {
  opacity: 0; visibility: hidden; pointer-events: none; transform: translateX(.5rem);
}
/* O bloco lá dentro é o MESMO `.controles-voz` do cabeçalho — o que muda é só
   que aqui ele não vem depois de nada, então a folga de cima sai. */
#velocidade-painel .controles-voz { margin-top: 0; width: 100%; }

/* ── A bolha dos ajustes de leitura  (Bloco J7) ────────────────────────────
   Quarto degrau, e o mesmo `Aa` do cabeçalho — mesmo rótulo porque é o mesmo
   painel, e um segundo nome para a mesma porta é uma porta a mais na cabeça
   de quem usa.

   Em SERIFA, e o cabeçalho em sans: lá o `Aa` é uma pílula de cromo entre
   outras; aqui ele tem 56px e é a única coisa dentro do círculo. Nesse
   tamanho a letra deixa de ser rótulo e vira ESPÉCIME — mostra a tipografia
   de que o painel trata, que é o mesmo princípio das amostras lá dentro
   («o controle mostra o que ele faz»). */
/* Em SANS desde 02/09, e a nota acima explica por que ele era serifado: num
   círculo de 56px o `Aa` deixava de ser rótulo e virava espécime. Num item de
   52×48 dentro de uma cápsula ele volta a ser rótulo — e o espécime de
   verdade está dentro do painel que ele abre, onde a fonte se apresenta na
   própria fonte. */
#ajustes-flutuante {
  font-family: var(--sans); font-size: 15px; font-weight: 600;
}
#ajustes-flutuante[hidden] { display: none; }
#ajustes-flutuante[aria-expanded="true"] {
  color: var(--cromo-acento);
  background: color-mix(in srgb, var(--cromo-acento) 13%, transparent);
}

/* Fora do artigo não há o que ajustar nem o que narrar. O `data-rota` já
   existe no `<body>` (ver `#tempo-leitura` logo abaixo), e é ele quem recolhe
   as duas bolhas e o painel — sem isso, o `hidden = false` que a tela de
   leitura escreve nunca seria desfeito, e o `Aa` ficaria pendurado sobre a
   inbox abrindo um painel de tipografia para uma lista. */
body:not([data-leitura]) #velocidade-flutuante,
body:not([data-leitura]) #velocidade-painel,
body:not([data-leitura]) #perguntar-flutuante,
/* O `▶` e o `✎` entraram nesta lista em 03/09, e estavam de fora desde
   sempre: os dois são escondidos por `hidden` no JavaScript, e `hidden` é um
   estado que alguém tem de LEMBRAR de repor. Bastava sair de um artigo por um
   caminho que não passasse pelo lugar certo para eles ficarem pairando sobre a
   inbox e a escrivaninha — duas bolhas para narrar e marcar um texto que não
   está em cena.
   Mesma razão das irmãs acima: fora da leitura não há o que narrar nem o que
   marcar, e a rota já responde por isso sem ninguém precisar lembrar. */
body:not([data-leitura]) #ouvir-flutuante,
body:not([data-leitura]) #caneta,
body:not([data-leitura]) #compartilhar-flutuante,
body:not([data-leitura]) #ajustes-flutuante { display: none; }

/* ── O `⇧` tem uma pergunta A MAIS que as irmãs  (spec 25 §3.3) ────────────
   `#capsula-mao` vive nas DUAS rotas de leitura, e as irmãs valem nas duas.
   Este não: na escrivaninha, «compartilhar» é o estudo inteiro — visão geral,
   partes e síntese num arquivo só —, e uma etapa solta não é o gesto que se
   quer. A ação está no `⋯`, que é onde as ações do estudo moram.

   Duas regras porque são duas perguntas: `[data-leitura]` responde «há texto
   em cena?» e `[data-rota]` responde «esta rota mostra o botão?». Uma só não
   dá conta de nenhuma das duas. */
body[data-rota="estudo"] #compartilhar-flutuante { display: none; }

/* ── O interruptor da autorrolagem  (Bloco J4) ─────────────────────────────
   O TOPO da coluna desde o Bloco J7 (era o terceiro degrau, quando a coluna
   tinha três), e o relato que o pediu é a continuação exata
   do de cima: com o botão de pausa ao alcance, pausar deixou de exigir a
   subida ao cabeçalho — mas QUALQUER outro toque que role a página continua
   desligando o acompanhamento, e não havia como pedi-lo de volta sem parar a
   voz.

   Mesmo material dos irmãos (papel elevado, borda em regra, sombra erguida):
   é a mesma família de cromo flutuante, e um botão diferente em espécie
   sugeriria uma função de outra ordem.

   ── Por que o estado se vê sem depender de cor ────────────────────────────
   Este botão é também o MOSTRADOR: o desligar por gesto é silencioso — o
   texto simplesmente para de andar. O apagado, então, precisa se ler de
   relance e sem cor: além de descer a tinta para `--tenue`, o `::after`
   risca o ícone. Uma opacidade a menos é diferença que só existe lado a lado
   com a versão acesa, e ninguém vê as duas ao mesmo tempo. */
#rolagem-flutuante {
  /* ── O TOPO da coluna, e por que é aqui  (Bloco J7) ─────────────────────
     Ele é a única bolha que aparece e some DENTRO do artigo — nasce ao tocar
     e some no `ended`, enquanto as outras acompanham o artigo inteiro.
     Numa coluna posicionada por degrau fixo, uma bolha intermitente no meio
     abre um buraco: as de cima não descem para ocupar o lugar dela. No topo,
     o que ela deixa quando some é o vazio da mesa, que não se vê.
     (Subiu do 5 ao 6 quando o progresso entrou na coluna — a regra do topo
     é dela, não do número.) */
  font-size: 1.25rem;
}
/* A seta cresce ao ser riscada: o corte come o meio dela, e é o que sobra em
   cima e embaixo que ainda tem de se ler como seta — não como dois traços. */
/* Aceso é a tinta CHEIA do cromo, apagado é a tinta secundária mais o risco.
   Sobre grafite, `--tenue` (um cinza de papel) seria quase o próprio campo — e
   o mostrador que precisa se ler de relance é justamente este. */
#rolagem-flutuante[aria-pressed="true"] { color: var(--cromo-tinta); }
#rolagem-flutuante[aria-pressed="false"] { color: var(--cromo-tinta-2); font-size: 1.4rem; }
#rolagem-flutuante[aria-pressed="false"]::after {
  content: ""; position: absolute; left: 16%; right: 16%; top: 50%;
  height: 1.75px; border-radius: 2px; background: currentColor; transform: rotate(-45deg);
  /* A folga em volta do risco é o que o faz LER como risco: encostado no
     glifo os dois viram uma mancha só — foi o que o primeiro screenshot
     mostrou. O contorno acompanha a rotação porque mora no elemento girado. */
  box-shadow: 0 0 0 1.5px var(--cromo-2);
}
/* O `position: relative` que ancora este risco vem da regra genérica
   `.capsula > button` — antes vinha do `position: fixed` do próprio botão. */
#rolagem-flutuante[hidden] { display: none; }

/* ── A bolha do progresso de leitura  (02 §4, terceira encarnação) ─────────
   Era a barra de 4px no topo. Duas rodadas de conserto lá (2px quase
   subliminar → 4px em cor plena com marcos de meta) não resolveram a queixa
   original — "difícil de ver" —, e o diagnóstico da terceira é de POSIÇÃO,
   não de força: o topo da tela é onde o olho não está durante a leitura. A
   coluna da direita é onde ele já vai buscar os controles, então o progresso
   virou mais uma moradora dela: anel na borda + número no centro.

   Quinto degrau, ABAIXO da rolagem: a rolagem continua no topo porque a
   regra do topo é dela — é a única bolha intermitente, e um buraco no meio
   da coluna não se fecha sozinho (ver o comentário dela, acima).

   MOSTRADOR, não botão — mesmo argumento da pílula do tempo: `pointer-events:
   none` permanente elimina por construção a classe de bug do
   `data-ajustando`, porque o que não recebe toque não rouba a resposta do
   `caretRangeFromPoint` durante o arraste de alça. E mesmo z-index 44 dela,
   não o 46 das bolhas tocáveis: os dois números são famílias, e este aqui é
   da família dos que só se leem.

   O número segue o desenho da bolha de velocidade («o número é o estado»):
   sans .86rem 600, `tabular-nums` porque ele troca sozinho enquanto a página
   rola, e sem largura fixa de algarismo o texto dançaria dentro do círculo.

   SEMPRE visível na tela de artigo — não segue o `data-cromo`. É a correção
   inteira: um progresso que some enquanto se rola é um progresso que nunca
   está lá quando a leitura acontece. As bolhas irmãs já se comportam assim. */
/* Dentro da cápsula ele deixou de ser um círculo de 48px e virou um ANEL de
   30px centrado num item de 52 — a bolha inteira era a mancha mais pesada da
   coluna, e o que informa é o arco, não o disco em volta dele.
   `pointer-events: none` continua permanente aqui; a exceção do sumário está
   logo abaixo. */
#progresso-flutuante {
  /* O único item quadrado da pilha: o anel precisa de folga igual em volta, e
     52×48 daria um oval de 2px. */
  height: var(--capsula-anel);
  /* ── O arco é MONOCROMÁTICO dentro da cápsula  (04/09) ──────────────────
     `--progresso` é um azul de tinta (`#26436e` no claro), escolhido para ser
     lido sobre papel; sobre o campo grafite ele desaparece. O arco passa a
     usar a tinta do cromo, e com isso a coluna inteira volta a ser de uma cor
     só — a mesma razão pela qual os glifos das irmãs não são coloridos. A
     trilha e os marcos continuam derivados dele, então nada aqui precisou de
     um segundo valor. */
  --progresso: var(--cromo-tinta);
  pointer-events: none;
  font-family: var(--sans); font-size: 8.5px; font-weight: 600;
  font-variant-numeric: tabular-nums; letter-spacing: -.01em;
  /* O ponto de partida do anel. Quem escreve o valor real é `ligarRolagem`,
     a cada quadro de rolagem — o mesmo lugar que escrevia o width da barra. */
  --p: 0;
}
/* O número mora no furo do anel, e o furo tem 22px: um `<span>` sem caixa
   própria seria centrado pelo item de 52 e sairia do buraco assim que o anel
   deixasse de ser concêntrico. */
/* O disco por trás do número era `--papel-elev`: dentro da cápsula grafite ele
   virava uma pastilha clara no meio do anel. Some — quem já fura o centro é a
   máscara radial do `::before`, e o `z-index: 1` continua pondo o número na
   frente do arco. */
#progresso-flutuante > span {
  position: relative; z-index: 1;
  width: 22px; height: 22px; border-radius: 50%;
  display: grid; place-items: center;
  background: transparent;
}

/* ── Quando o texto TEM estrutura, a bolha aceita o toque  (L-124) ──────────
   O `pointer-events: none` acima é permanente de propósito, e o comentário
   original explica por quê: o que não recebe toque não rouba a resposta do
   `caretRangeFromPoint` durante o arraste de alça. Isso continua valendo — a
   exceção é estreita e declarada em duas frentes.

   Primeira: só em artigo com sumário. Na notícia curta, que é a maioria do
   acervo, nada muda em nenhum aspecto — nem o hit-test, nem o z-index.

   Segunda: durante o ajuste de alça ela volta a ser intocável, agora pela
   lista do `body[data-ajustando]` lá em cima, onde ela entrou junto com esta
   regra. É o mesmo tratamento das seis bolhas irmãs; o que a mantinha fora da
   lista era ser mostrador, e ela deixou de ser só isso.

   O z-index sobe de 44 para 46 no mesmo movimento: os dois números são
   famílias — 44 é dos que só se leem, 46 dos que se tocam — e a bolha muda de
   família exatamente quando muda de natureza. */
#progresso-flutuante[data-sumario="sim"] { pointer-events: auto; z-index: 46; cursor: pointer; }

/* O anel: um conic-gradient dirigido por `--p`, furado no centro pela
   máscara radial — sem ela o arco seria um disco cheio por trás do número.
   Preenche em sentido horário a partir do topo, que é onde a leitura começa.

   Os MARCOS de meta (25·50·75%) vêm na segunda camada, POR BAIXO do arco:
   meta vencida é absorvida pela cor plena, não celebrada com efeito — a
   mesma semântica dos traços da barra antiga, na mesma força (55%, a que a
   página de amostras validou). Cada tick tem 4,5° (~2px de arco no raio de
   26px): os 2,5° da primeira tentativa davam ~1px, o mesmo erro do marco de
   1px da barra — marco que não se vê não é meta, é ruído de render.

   `inset: 2px` deixa 1px de papel entre a borda da bolha e o anel — colado
   na borda, o arco e o contorno viravam um traço só. A espessura de 4px é
   a da barra que ele substitui. */
#progresso-flutuante::before {
  content: ""; position: absolute; border-radius: 50%;
  /* 30px centrados, e não `inset` na caixa toda: a caixa agora é o item da
     cápsula (52×52), e o anel é uma peça dentro dele. */
  width: 30px; height: 30px; top: 50%; left: 50%; margin: -15px 0 0 -15px;
  --marco: color-mix(in srgb, var(--progresso) 55%, transparent);
  /* ── A TRILHA, terceira camada e a de baixo  (31/08) ────────────────────
     Sem ela, um artigo em 0% desenha três risquinhos soltos na borda — os
     marcos de 25, 50 e 75% sobre nada — e o que se vê não parece um anel
     vazio, parece sujeira na tela. Foi assim que o dono a descreveu, e ele
     tinha razão: marco é referência DENTRO de um percurso, e sem o percurso
     desenhado ele não referencia coisa nenhuma.

     Derivada de `--progresso`, e não um cinza próprio: assim ela acompanha o
     acento em qualquer tema, e o anel inteiro continua sendo uma cor só em
     duas intensidades. */
  --trilha: color-mix(in srgb, var(--progresso) 14%, transparent);
  background:
    conic-gradient(var(--progresso) calc(var(--p) * 1%), transparent 0),
    conic-gradient(transparent 0 87.75deg,  var(--marco) 0 92.25deg,
                   transparent 0 177.75deg, var(--marco) 0 182.25deg,
                   transparent 0 267.75deg, var(--marco) 0 272.25deg,
                   transparent 0),
    linear-gradient(var(--trilha), var(--trilha));
  /* O furo de 22px num anel de 30 dá 4px de arco, que é a espessura da barra
     que ele substituiu — a mesma conta de antes, refeita para o raio novo. */
  -webkit-mask: radial-gradient(closest-side, transparent 11px, #000 12px);
  mask: radial-gradient(closest-side, transparent 11px, #000 12px);
}

/* Fora do artigo não há meta de leitura — era a regra da #barra-marcos e
   continua sendo a desta bolha. Por `data-rota`, e não por `hidden`: nenhuma
   tela a revela, então nenhuma teria de recolhê-la. */
body:not([data-leitura]) #progresso-flutuante { display: none; }

/* ── A pílula do tempo de leitura  (spec 14 §4.2) ──────────────────────────
   Pílula, e não bolha: são dois números, e "25 min · 1h10" não cabe num
   círculo de 56px. Mesmo material da caneta acima — papel elevado, borda em
   regra, sombra erguida — porque é a mesma família de cromo flutuante; o que
   muda é que este não se toca.

   `pointer-events: none` PERMANENTE, e isso elimina uma classe inteira de bug
   por construção: a pílula nunca precisa entrar na lista do
   `body[data-ajustando]` lá em cima, que desliga o hit-test da caneta, das
   ações e da barra durante o arraste de alça. Arrastar uma alça pergunta ao
   documento que texto está sob o dedo, e qualquer elemento por cima da prosa
   responde por si — o que não recebe toque não tem como roubar a resposta. */
#tempo-leitura {
  position: fixed; right: 1.1rem; bottom: var(--pilha-base);
  z-index: 44; pointer-events: none;
  display: flex; align-items: center; gap: .3rem;
  height: var(--tempo-h); padding: 0 .6rem;
  border-radius: 999px;
  background: var(--papel-elev); border: 1px solid var(--regra);
  box-shadow: var(--sombra-erguida);
  font-family: var(--sans); font-size: .68rem; line-height: 1;
  color: var(--tinta); white-space: nowrap;
  /* Só a opacidade e o deslocamento, nunca `display`: a transição existe para
     que o número acompanhe o cromo em vez de aparecer estalando, e `display`
     não transiciona. */
  transition: opacity .18s ease, transform .18s ease;
}
#tempo-leitura[hidden] { display: none; }

/* O acumulado é secundário POR DESENHO: a sessão é o que está acontecendo, o
   total é o que já aconteceu. */
#tempo-leitura .sep { color: var(--tenue); }
#tempo-leitura .rot {
  font-size: .6rem; font-weight: 600; letter-spacing: .08em;
  text-transform: uppercase; color: var(--tenue);
}

/* Segue o cromo. É esta regra que responde à proibição da 02 §4 ("sem contador
   de palavras piscando"): enquanto se lê rolando para baixo o número não está
   lá — ele volta com a barra, quando o leitor levanta os olhos. */
body[data-cromo="oculto"] #tempo-leitura { opacity: 0; transform: translateY(.4rem); }

/* Fora do artigo não há sessão de leitura para contar. O `data-rota` já existe
   no `<body>` exatamente para uma regra saber isto sem que nenhuma tela avise. */
body:not([data-leitura]) #tempo-leitura { display: none; }

/* ── barra de ações do destaque (L-51, 03 §5.2) ────────────────────────────
   Pílula flutuante, posicionada em coordenadas de DOCUMENTO (`absolute`) e não
   de viewport: em `fixed` ela ficaria parada enquanto o texto rola por baixo, e
   apontaria para o trecho errado no primeiro movimento do dedo. */
#acoes {
  position: absolute; z-index: 60; display: flex; align-items: stretch; gap: 0;
  /* ── Ícone sobre legenda  (19/09) ──────────────────────────────────────────
     A pílula de rótulos corridos, com o aro de acento no ajuste e a dica
     «arraste as alças…», saiu a pedido: «lúdico, de estética de mau gosto».
     Das três propostas da página de amostras, a escolhida foi esta — cada ação
     é um desenho com a legenda curta embaixo, num cartão de filete quase
     invisível e sombra erguida. É também a única das três que cabe numa linha
     no iPhone 16 Pro Max (pede 416 px dos 424). */
  background: var(--papel-elev); border: 1px solid var(--papel-borda-fina); border-radius: 16px;
  box-shadow: var(--sombra-erguida); padding: 4px;
  font-family: var(--sans); white-space: nowrap;
  /* ── Nunca mais larga que a tela: QUEBRA em linhas  (17/09) ──────────────
     A captura do dono no iPhone 16 Pro Max: a pílula do ajuste tem nove itens
     desde a L-73, mede 791 px numa tela de 440, e da «Nota» em diante nada se
     alcançava — `posicaoDaBarra` prende a borda ESQUERDA, e a direita saía.
     `white-space: nowrap` continua nos botões (uma legenda não parte ao meio);
     quem quebra é a fileira. `acoes.mjs` marca `data-quebrada` quando isso
     acontece — num iPhone de 390 px, ou com as quatro cores abertas. */
  max-width: calc(100vw - 16px); box-sizing: border-box;
  flex-wrap: wrap; justify-content: center; row-gap: 2px;
}
#acoes[hidden] { display: none; }
/* Em duas linhas o fio entre grupos fica solto no começo ou no fim de uma
   linha, e some; o raio fica o mesmo (a pílula de 999px é que virava estádio). */
#acoes[data-quebrada] { border-radius: 16px; }
#acoes[data-quebrada] .sep { display: none; }

/* 48px de alvo: a caneta e o dedo precisam do alvo grande. O desenho em cima,
   a legenda de 11px embaixo; a cor de repouso é a da tinta secundária, e o
   realce é o papel um degrau abaixo, não uma cor. */
#acoes button { display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 5px; border: 0; background: none; color: var(--tinta-2); cursor: pointer;
  font: 500 .6875rem/1 var(--sans); letter-spacing: .005em;
  min-width: 48px; min-height: 48px; padding: 8px 4px 7px; border-radius: 11px; }
#acoes button .ic { display: grid; place-items: center; width: 24px; height: 20px; pointer-events: none; }
#acoes button .ic svg { width: 20px; height: 20px; pointer-events: none; }
#acoes button .leg { pointer-events: none; }
#acoes button:hover, #acoes button:focus-visible { background: var(--papel-elev-2); color: var(--tinta); }
#acoes button:active { background: var(--regra); }
/* O que confirma é o único com massa: o visto (ou o marcador) num disco de
   acento, e a legenda no acento. */
#acoes .primaria, #acoes .primaria:hover { color: var(--acento); }
#acoes .primaria .ic { width: 24px; height: 24px; margin: -2px 0; border-radius: 50%;
  background: var(--acento); color: var(--sobre-acento); }
#acoes .primaria .ic svg { width: 15px; height: 15px; }
#acoes .perigo, #acoes .perigo:hover { color: var(--perigo); }
/* Fechar é só o desenho, menor e mais apagado: ele sai do caminho. */
#acoes .so-icone { min-width: 36px; color: var(--tenue); }
#acoes .so-icone .ic svg { width: 16px; height: 16px; }
#acoes .so-icone .leg { display: none; }
/* O rótulo de "já fiz": copiar não muda nada na tela, e sem um sinal o leitor
   toca de novo para ter certeza. O desenho vira um visto por ~1,4s. */
#acoes .feita  { color: var(--acento); }
#acoes .falhou { color: var(--perigo); }
#acoes .sep { width: 1px; background: var(--regra); margin: 10px 4px; flex: none; }
/* Abaixo de 430px (o iPhone de 390, o SE) os oito botões pediam 416 px e o ✕
   caía sozinho numa segunda linha. Um passo mais justo — o alvo continua com
   44px de altura e de largura mínima — e a fileira volta a caber em uma. */
@media (max-width: 430px) {
  #acoes { padding: 3px; }
  #acoes button { min-width: 44px; padding: 8px 2px 7px; font-size: .65rem; letter-spacing: 0; }
  #acoes .so-icone { min-width: 32px; }
  #acoes .sep { margin: 10px 2px; }
}

/* A amostra de cor ocupa o lugar do desenho: uma pinta de 20px. */
#acoes .pinta { display: block; width: 20px; height: 20px; border-radius: 50%;
  background: var(--hl-cor); box-shadow: inset 0 0 0 1px rgba(0,0,0,.12); }
/* Aberto o seletor, a cor em uso ganha o anel; recolhido, o botão é um menu
   (`aria-expanded`) e a legenda «Cor» já diz isso. */
#acoes .swatch[aria-pressed="true"]:not([aria-expanded]) .pinta {
  box-shadow: 0 0 0 2px var(--papel-elev), 0 0 0 3px var(--tinta); }
/* O seletor de cor recolhido (L-73, spec 13 §2.2).
   `display: contents` faz o <span> desaparecer da caixa e as amostras
   participarem do flex da própria barra — sem isso, expandido viraria uma
   caixa dentro da caixa e a pílula ganharia um degrau de altura. */
#acoes .cores { display: contents; }
#acoes .swatch[data-cor="roxo"]    { --hl-cor: var(--vivo-roxo); }
#acoes .swatch[data-cor="amarelo"] { --hl-cor: var(--vivo-amarelo); }
#acoes .swatch[data-cor="rosa"]    { --hl-cor: var(--vivo-rosa); }
#acoes .swatch[data-cor="azul"]    { --hl-cor: var(--vivo-azul); }

/* ── modo ajuste (03 §5.2b, refeito na spec 45) ────────────────────────────
   O original vira FANTASMA enquanto se ajusta. Sem isso, ao encolher, a parte
   removida continuaria pintada e o gesto pareceria não ter efeito — o mesmo
   padrão de defeito da absorção, em outra roupa.

   Era classe numa `<mark>` (`.editando`) e é um NOME de highlight próprio: o
   `pigmento.ajuste()` pinta a proposta enquanto ela é puxada. Trocar a cor no
   meio do ajuste não o apaga mais — o `ajuste.remarcar()`, que existia só para
   repor a classe que a repintura destruía, morreu com a spec 45.

   O `outline` tracejado virou `underline dashed`: `::highlight()` não aceita
   contorno, e a mensagem — «isto é proposta, não fato» — é a mesma. As alças
   nas duas pontas continuam dizendo o resto.

   `--cor-ajuste` vem do `[data-cor-ajuste]` no documento, publicado por
   `pigmento.ajuste(segmentos, cor)`: é a cor DO DESTAQUE em edição, que pode
   não ser a cor ativa da barra. */
[data-cor-ajuste="amarelo"] { --cor-ajuste: var(--hl-amarelo); }
[data-cor-ajuste="roxo"]    { --cor-ajuste: var(--hl-roxo); }
[data-cor-ajuste="rosa"]    { --cor-ajuste: var(--hl-rosa); }
[data-cor-ajuste="azul"]    { --cor-ajuste: var(--hl-azul); }
::highlight(destaque-ajuste) {
  background-color: color-mix(in srgb, var(--cor-ajuste, var(--hl-amarelo)) var(--hl-fantasma, 22%), transparent);
  text-decoration: underline dashed var(--acento);
  text-decoration-thickness: 1px;
  text-underline-offset: .16em;
}

/* A bolinha de nota saiu na spec 45 — sem elemento não há `::after`. O sinal
   agora é o `underline dotted` de `::highlight(destaque-*-nota)`, lá em cima,
   onde a troca está explicada. */

/* Alças próprias: o iOS não desenha alças arrastáveis em seleção criada por
   programa em conteúdo não editável (medido no Bloco A). `touch-action: none`
   é o que impede a página de rolar enquanto se puxa. */
.alca { position: absolute; z-index: 58; width: 44px; margin-left: -22px; display: none;
  touch-action: none; -webkit-user-select: none; user-select: none; cursor: ew-resize; }
.alca.on { display: block; }
.alca > i { position: absolute; left: 50%; top: 0; width: 2px; height: 100%; margin-left: -1px;
  background: var(--acento); display: block; }
/* pousada: a bolinha de arraste toca a linha de texto — apoiada, não
   flutuando acima dela como a pílula de ações. */
.alca > i::after { content: ""; position: absolute; left: 50%; width: 18px; height: 18px;
  margin-left: -9px; border-radius: 50%; background: var(--acento); box-shadow: var(--sombra-pousada); }
#alcaA > i::after { top: -18px; }
#alcaB > i::after { bottom: -18px; }
.alca.puxando > i::after { transform: scale(1.25); }

/* ── sheet da nota (03 §5.3) ───────────────────────────────────────────────
   Mesma família do painel de ajustes: o leitor já aprendeu que o que vem de
   baixo se fecha para baixo. Nunca há botão "salvar" — ver nota.mjs. */
/* ── Painel flutuante, e não mais sheet de rodapé  (L-76) ──────────────────
   Ancorado na base, ele ficava **atrás do teclado**: no iPad o teclado ocupa
   quase metade da tela, e escrever sem ver o que se escreve não é escrever.
   Flutuando no terço superior, o painel permanece visível com qualquer
   teclado — encaixado ou flutuante.

   Fica claro o que isto NÃO resolve: o tamanho do teclado é ajuste do
   sistema, e nenhuma página escolhe. O que se resolve é o painel deixar de
   disputar o mesmo pedaço de vidro com ele. */
#nota, #conversa, #colar, #metadados, .sheet {
  position: fixed; z-index: 70;
  top: max(4.5rem, env(safe-area-inset-top)); left: 50%;
  width: min(36rem, calc(100% - 2rem));
  /* ── Quem rola é a LISTA, não o painel  (L-81) ───────────────────────────
     Com `overflow-y` no painel inteiro, uma conversa longa empurrava a linha
     dos botões para fora da área visível — «Perguntar» e «Fechar» existiam
     abaixo do corte, e enviar só funcionava pelo Enter. Controle que sai da
     tela é controle que não existe.

     Coluna flexível: a lista de turnos encolhe e rola por dentro, o campo e
     os botões ficam presos no pé do painel, sempre alcançáveis. */
  max-height: min(70vh, 34rem);
  display: flex; flex-direction: column; min-height: 0;
  background: var(--papel-elev); border: 1px solid var(--regra); border-radius: 14px;
  /* Sombra de objeto que paira, e não a aresta do rodapé: ele deixou de estar
     ancorado numa borda, então a luz volta a vir de --luz-x. */
  box-shadow: var(--sombra-flutuante, 0 12px 40px rgba(0,0,0,.35));
  padding: 1rem;
  font-family: var(--sans);
  transform: translate(-50%, -8px); opacity: 0; pointer-events: none;
  /* `visibility` também (revisão M86/M110): `opacity` e `pointer-events`
     tiram o painel da vista e do dedo, não do Tab nem do VoiceOver — a caixa
     da leitura nasce com cada artigo, e o `#colar` fica no `<body>` depois do
     primeiro uso com o link antigo no campo. A visibilidade cai DEPOIS do
     fade; ao abrir, a regra de baixo tem `transition: none`, então ela volta
     no mesmo instante e o `focus()` do L-91 encontra o painel visível. */
  visibility: hidden;
  transition: opacity .16s ease, transform .16s ease, visibility 0s .16s;
}
/* ── ABRIR NÃO INTERPOLA `opacity`, E ISSO É O QUE DÁ TECLADO  (L-91) ──────
   O estado fechado é `opacity: 0`, e a transição de .16s COMEÇA nesse zero.
   Como `abrir()` foca no mesmo task em que marca `data-aberto="sim"` — e tem
   de focar ali, senão o iPadOS não liga o foco ao gesto —, o `focus()`
   acontecia com o painel medindo `opacity: 0`. Medido em Chrome headless:

       opacity no instante do campo.focus() = 0

   O WebKit não apresenta o teclado para um elemento que não considera
   visível. O campo ficava focado, o cursor piscava, e o teclado não vinha —
   o sintoma que custou seis rodadas de depuração em 21/08 e foi atribuído ao
   sistema (armadilha 52), porque o CSS parecia eliminado "por construção".

   `transition: none` aqui faz a abertura resolver `opacity: 1` de imediato;
   o deslize continua, agora como animação, que não mexe em `opacity`. O
   fade de FECHAMENTO não se perde: ele vem da regra base, que é o destino
   quando `data-aberto` volta a "nao".

   Regra que fica: painel que ganha foco não pode desvanecer a partir do
   zero. Ou abre opaco, ou anima a partir de um valor visível — é o que a
   gaveta do Tabula faz (`from{opacity:.4}`) e por isso ela nunca falhou. */
#nota[data-aberto="sim"], #conversa[data-aberto="sim"], #colar[data-aberto="sim"],
#metadados[data-aberto="sim"], .sheet[data-aberto="sim"] {
  transform: translate(-50%, 0); opacity: 1; pointer-events: auto; visibility: visible;
  transition: none;
  animation: sheet-entra .16s var(--curva);
}
@keyframes sheet-entra { from { transform: translate(-50%, -8px); } }
#caixa-leitura-nota .pergunta, #caixa-destaques-nota .pergunta, #caixa-leitura-nota .trecho, #caixa-destaques-nota .trecho, #caixa-leitura-nota textarea, #caixa-destaques-nota textarea, #caixa-leitura-nota .linha, #caixa-destaques-nota .linha, #nota .pergunta, #nota .trecho, #nota textarea, #nota .linha {
  max-width: var(--measure); margin-inline: auto; }
/* A pergunta do turno de IA, acima do trecho (L-80). Em negrito porque é ela
   que dá sentido à resposta logo abaixo. */
#caixa-leitura-nota .pergunta, #caixa-destaques-nota .pergunta, #nota .pergunta { font-family: var(--sans); font-size: .92rem; font-weight: 600;
  color: var(--tinta); margin: 0 0 .5rem; }
#caixa-leitura-nota .trecho, #caixa-destaques-nota .trecho, #nota .trecho { font-family: var(--corpo); font-size: .9rem; color: var(--tinta-2);
  border-left: 2px solid var(--regra); padding-left: .7rem; margin-bottom: .7rem;
  max-height: 4.5em; overflow: hidden; }
/* 1rem, e não .92rem: abaixo de 16px o iOS DÁ ZOOM ao focar o campo — a
   página salta e o campo vai parar atrás do teclado. Vale para os dois
   textarea deste arquivo, e é o único lugar do app onde o número tem de ser
   lido em pixels de iPad, não em escala tipográfica. */
#caixa-leitura-nota textarea, #caixa-destaques-nota textarea, #nota textarea { display: block; width: 100%; min-height: 7rem; resize: vertical;
  font-family: var(--sans); font-size: 1rem; line-height: 1.5; color: var(--tinta);
  background: var(--papel); border: 1px solid var(--regra); border-radius: 8px; padding: .6rem .7rem; }
#caixa-leitura-nota textarea:focus-visible, #caixa-destaques-nota textarea:focus-visible, #nota textarea:focus-visible { outline: none; border-color: var(--acento); }
#caixa-leitura-nota .linha, #caixa-destaques-nota .linha, #nota .linha { display: flex; align-items: center; justify-content: space-between; margin-top: .7rem; }

/* ── A janela de METADADOS  (02/09) ────────────────────────────────────────
   «Preciso de alguma forma de editar metadados… pode ser por exemplo o símbolo
   de um lápis abre uma janela flutuante.»

   Nada de desenho novo: ela entra na família do `#nota`, do `#conversa` e do
   `#colar` — mesma caixa, mesma sombra, mesma entrada de .16s, mesmo lugar na
   tela. Uma quarta gramática de painel seria justamente o contrário do que o
   pedido manda («mantém a identidade visual»), e o app já tem três painéis que
   se abrem do mesmo jeito.

   O que ela acrescenta é só o formulário: dois campos rotulados, e a linha de
   botões que o `.linha` do `#nota` já desenha. */
/* 40rem desde a spec 73: o Tema entrou com cinco opções, e a 26rem a ficha
   de um livro com a língua visível rolava antes do botão Salvar. O teto é a
   tela menos o topo do painel (4,5rem) e um respiro de 1rem, e não 80vh:
   medido a 375 × 667, 80vh dava 533px para uma ficha de ~575, e a linha do
   Salvar saía do corte; com este teto ela cabe inteira ali, e numa tela ainda
   menor rola o corpo (`.corpo-sheet`), nunca o Salvar. `vh` vem antes como
   reserva de quem não lê `dvh`. */
#metadados {
  max-height: min(calc(100vh - 5.5rem), 40rem);
  max-height: min(calc(100dvh - 5.5rem), 40rem);
  gap: .1rem;
}
/* ── O CORPO que rola dentro do painel  (spec 73, prova 14) ───────────────
   A regra do L-81 aplicada às folhas de formulário: quem rola é o corpo, e a
   linha dos botões fica presa no pé. Sem isto, um formulário mais alto que o
   painel vazava por baixo da caixa (o `.sheet` é coluna flexível, e filho
   que não encolhe transborda) e o botão de confirmar ia para fora da tela.
   O `gap` repete o do painel, para o espaçamento entre campos não mudar ao
   entrarem no corpo; o recuo de 4px com margem negativa dá lugar ao anel de
   foco (2px + 2px de afastamento), que o `overflow` cortaria rente. */
.sheet > .corpo-sheet {
  flex: 1 1 auto; min-height: 0; overflow-y: auto;
  display: flex; flex-direction: column; gap: inherit;
  padding: 4px; margin: -4px;
}
#metadados .titulo-sheet {
  font-family: var(--sans); font-size: .78rem; font-weight: 600;
  letter-spacing: .08em; text-transform: uppercase; color: var(--tenue);
  margin: 0 0 .9rem;
}
/* O rótulo por CIMA do campo, e não ao lado: são dois campos de larguras
   diferentes, e rótulo à esquerda obrigaria a uma coluna fixa que o «Título»
   e o «Autor» não preenchem igual. */
.campo-meta { display: block; margin-bottom: .8rem; }
.campo-meta > span {
  display: block; font-family: var(--sans); font-size: .74rem; font-weight: 500;
  color: var(--tenue); margin-bottom: .3rem;
}
.campo-meta input {
  display: block; width: 100%; box-sizing: border-box;
  font-family: var(--serif); font-size: 1rem; color: var(--tinta);
  background: var(--papel); border: 1px solid var(--borda-controle);
  border-radius: var(--raio-p); padding: .6rem .7rem; min-height: var(--alvo);
  -webkit-appearance: none; appearance: none;
}
/* Serifa no valor e sans no rótulo: o que se digita aqui é o TÍTULO da obra, e
   ele vai aparecer em Literata na lombada, na capa e no alto da folha. Ver o
   texto na fonte em que ele vai viver é o mesmo princípio do espécime do
   painel de ajustes — «o controle mostra o que ele faz». */
.campo-meta input:focus-visible { outline: none; border-color: var(--acento); }
#metadados .linha {
  display: flex; align-items: center; gap: .5rem; margin-top: .2rem;
}
/* O estado (erro ou aviso) come a sobra e empurra os botões para a direita. */
#metadados .linha .sub { flex: 1; min-width: 0; color: var(--perigo); }
/* Salvar é PRIMÁRIO — é a ação que a janela existe para fazer. Mesmo desenho
   do «Publicar» do sheet de colar, que a revisão de 24/08 fixou. */
#metadados .btn.primario {
  background: var(--acento); color: var(--sobre-acento); border-color: var(--acento);
}

/* ── sheet da conversa (L-72, spec 12 §6.3) ────────────────────────────────
   Mesma família do sheet de nota: vem de baixo, fecha para baixo, mesma
   aresta. A diferença de forma segue a de conteúdo — a nota é um campo, a
   conversa é um histórico com um campo no pé. Por isso a lista rola dentro
   do sheet, e não o sheet dentro da tela: o campo de perguntar tem de ficar
   alcançável com o polegar por mais longa que a conversa fique. */
#caixa-leitura-perguntar .trecho, #caixa-leitura-perguntar .turnos, #caixa-leitura-perguntar textarea, #caixa-leitura-perguntar .linha, #conversa .trecho, #conversa .turnos, #conversa textarea, #conversa .linha, .sala .trecho, .sala .turnos, .sala textarea, .sala .linha {
  max-width: var(--measure); margin-inline: auto; }
#caixa-leitura-perguntar .trecho, #conversa .trecho, .sala .trecho { font-family: var(--corpo); font-size: .9rem; color: var(--tinta-2);
  border-left: 2px solid var(--acento); padding-left: .7rem; margin-bottom: .7rem;
  max-height: 3em; overflow: hidden; }
#caixa-leitura-perguntar .turnos, #conversa .turnos, .sala .turnos { flex: 1 1 auto; min-height: 0; overflow-y: auto; margin-bottom: .7rem; }
#caixa-leitura-perguntar .turnos .vazio, #conversa .turnos .vazio, .sala .turnos .vazio { color: var(--tinta-2); font-size: .9rem; text-align: center;
  padding: 1.2rem 0; }
#caixa-leitura-perguntar .turno, #conversa .turno, .sala .turno { margin-bottom: .9rem; position: relative; padding-right: 2.6rem; }
#caixa-leitura-perguntar .turno .p, #conversa .turno .p, .sala .turno .p { font-weight: 600; color: var(--tinta); font-size: .92rem;
  margin: 0 0 .25rem; }
/* O ✕ do turno é o irmão do `.destaque .x` — e a única porta de saída do
   turno de IA, que não é pintado no texto (L-88) e nunca abre a barra de
   ajuste. Armado, o botão diz "apagar?" por extenso: um ✕ que só muda de cor
   não avisa que falta o segundo toque. */
#caixa-leitura-perguntar .turno .x, #conversa .turno .x, .sala .turno .x {
  position: absolute; top: 0; right: 0; min-width: 32px; height: 32px;
  border: 0; background: none; color: var(--tinta-2); cursor: pointer;
  border-radius: 16px; font-size: .8rem; line-height: 1; opacity: .55;
  min-height: 32px; padding: 0 .5rem; font-family: var(--sans);
}
#caixa-leitura-perguntar .turno .x:hover, #caixa-leitura-perguntar .turno .x:focus-visible, #conversa .turno .x:hover, #conversa .turno .x:focus-visible, .sala .turno .x:hover, .sala .turno .x:focus-visible {
  opacity: 1; color: var(--perigo); background: var(--regra); }
#caixa-leitura-perguntar .turno .x.confirma, #conversa .turno .x.confirma, .sala .turno .x.confirma { opacity: 1; color: var(--perigo); background: var(--regra); }
/* A resposta é da máquina, e o filete à esquerda diz isso sem escrever
   "IA" em lugar nenhum — é o mesmo recurso que a citação do trecho usa. */
#caixa-leitura-perguntar .turno .r, #conversa .turno .r, .sala .turno .r { color: var(--tinta-2); font-size: .92rem; line-height: 1.55;
  margin: 0; border-left: 2px solid var(--regra); padding-left: .7rem;
  white-space: pre-wrap; }
/* 1rem pelo mesmo motivo do campo da nota — ver ali. */
#caixa-leitura-perguntar textarea, #conversa textarea, .sala textarea { flex: none; display: block; width: 100%; min-height: 3.2rem; resize: vertical;
  font-family: var(--sans); font-size: 1rem; line-height: 1.5; color: var(--tinta);
  background: var(--papel); border: 1px solid var(--regra); border-radius: 8px;
  padding: .6rem .7rem; box-sizing: border-box; }
#caixa-leitura-perguntar textarea:focus-visible, #conversa textarea:focus-visible, .sala textarea:focus-visible { outline: none; border-color: var(--acento); }
#caixa-leitura-perguntar .linha, #conversa .linha, .sala .linha { flex: none; display: flex; align-items: center; gap: .5rem; margin-top: .7rem; }
#caixa-leitura-perguntar .linha .sub, #conversa .linha .sub, .sala .linha .sub { flex: 1; }
#caixa-leitura-perguntar #conversa-enviar[disabled], #conversa #conversa-enviar[disabled], .sala #sala-enviar[disabled] { opacity: .55; }

/* ── sheet de colar um link (L-104, spec 16 §6) ────────────────────────────
   Terceiro membro da família do `#nota`/`#conversa`, e por isso já herdou a
   caixa flutuante e — o que importa de verdade — o `transition: none` da
   regra de abertura: sem ele o painel vale `opacity: 0` no instante do
   `focus()` e o iPadOS não apresenta o teclado (L-91).

   O que muda é só a forma: uma linha de texto, não um bloco. Um endereço não
   tem segunda linha, então `<input type="url">` — que no iPad ainda traz o
   teclado de endereço, com a tecla «.com». */
#colar .titulo, #colar input, #colar .linha {
  max-width: var(--measure); margin-inline: auto; }
/* Serif, não sans (revisão 2026-08-24): é o único título que este painel
   tem, e a voz de título do app é a Literata — a mesma do h1 da inbox e do
   artigo. Em sans ele lia como rótulo de formulário. */
#colar .titulo { font-family: var(--serif); font-size: 1.08rem; font-weight: 600;
  letter-spacing: -.01em; color: var(--tinta); margin: 0 0 .8rem; }
/* 1rem pelo mesmo motivo dos dois campos acima: abaixo de 16px o iOS DÁ ZOOM
   ao focar, a página salta e o campo vai parar atrás do teclado. */
/* Borda em --borda-controle, não --regra (revisão 2026-08-24 — mesmo caso da
   `.busca` dos destaques): o campo é a afordância principal do painel, e
   `--regra` sobre o papel do sheet era um aro que quase não existia. */
#colar input { display: block; width: 100%;
  font-family: var(--sans); font-size: 1rem; line-height: 1.5; color: var(--tinta);
  background: var(--papel); border: 1px solid var(--borda-controle);
  border-radius: var(--raio-p); padding: .65rem .8rem; box-sizing: border-box; }
#colar input:focus-visible { outline: none; border-color: var(--acento); }
#colar input::placeholder { color: var(--tenue); }

/* ── O arquivo escolhido e a pergunta sobre ele  (21/09/2026) ───────────────
   O painel de envio (EPUB, spec 50; arquivo, spec 68) nasceu SEM estilo para
   este bloco: o nome do arquivo e a pergunta de múltipla escolha herdavam o
   corpo de leitura (18–21px), e a regra `#colar input` acima — feita para o
   campo de link — pegava os rádios e os esticava numa linha inteira, com borda
   e enchimento de campo de texto. No EPUB mal se via («Literário», «Técnico»
   cabem em qualquer lugar); com «Documento — artigo, norma, manual, relatório»
   o painel virou o que o dono fotografou: enorme, quebrando linha.

   A voz é a do painel: sans, no tamanho dos botões. O nome do arquivo é a única
   coisa com peso; o resto é apoio. */
/* Sem `max-width`/centralização: a medida é em `em`, e com a fonte deste bloco ela
   ficava mais estreita que o painel — o nome do arquivo saía recuado do título. */
#colar-epub { font-family: var(--sans); }
#colar-epub-nome { margin: 0 0 .2rem; font-size: .95rem; font-weight: 600; line-height: 1.35;
  color: var(--tinta); overflow-wrap: anywhere; }
#colar-epub-meta { margin: 0 0 .8rem; }
#colar fieldset.temperamento { margin: 0 0 .9rem; padding: 0; border: 0; min-width: 0; }
#colar fieldset.temperamento[hidden] { display: none; }
#colar fieldset.temperamento legend { padding: 0; margin: 0 0 .25rem; font-size: .8rem; font-weight: 600;
  letter-spacing: .02em; color: var(--tinta-2); }
#colar fieldset.temperamento label { display: flex; align-items: center; gap: .6rem;
  min-height: var(--alvo); font-size: .9rem; line-height: 1.35; color: var(--tinta); cursor: pointer; }
/* O rádio NÃO é o campo de link: desfaz o `display:block; width:100%` e o
   cromo de campo de texto que a regra `#colar input` lhe daria. */
#colar fieldset.temperamento input[type="radio"] { display: inline-block; flex: none; width: 1.15rem; height: 1.15rem;
  margin: 0; padding: 0; border: 0; background: none; accent-color: var(--acento); }
#colar fieldset.temperamento input[type="radio"]:focus-visible { outline: 2px solid var(--foco); outline-offset: 2px; }

/* ── A língua do TEXTO (spec 72 §5.2) ──────────────────────────────────────
   Na ficha, o mesmo desenho do campo de título; no painel de envio, uma linha
   só, antes dos botões, porque vale para os quatro caminhos; no rodapé, a
   sugestão discreta de declarar. 1rem no seletor: abaixo de 16px o iOS dá
   zoom ao focar. */
.campo-meta[hidden] { display: none; }
.campo-meta select, #colar .lingua-do-texto select {
  display: block; width: 100%; box-sizing: border-box;
  font-family: var(--sans); font-size: 1rem; color: var(--tinta);
  background: var(--papel); border: 1px solid var(--borda-controle);
  border-radius: var(--raio-p); padding: .45rem .6rem; min-height: var(--alvo);
}
.campo-meta select:focus-visible, #colar .lingua-do-texto select:focus-visible {
  outline: 2px solid var(--foco); outline-offset: 2px;
}
/* ── O TEMA na ficha (spec 73 §5.5) ────────────────────────────────────────
   Cinco rádios, cada um com o ponto da matiz, no desenho de chip — a mesma
   pílula da fileira de temas, para que a escolha se reconheça pela cor antes
   da palavra. A opção inteira é o alvo (44px), o escolhido veste a matiz do
   próprio tema, como o `.chip.ativo`. */
#metadados fieldset.campo-tema { border: 0; padding: 0; margin: 0 0 .8rem; min-width: 0; }
#metadados .campo-tema legend {
  padding: 0; font-family: var(--sans); font-size: .74rem; font-weight: 500;
  color: var(--tenue); margin-bottom: .3rem;
}
/* A mesma pílula serve à calibração (nível 1, spec 73 §5.6): lá e aqui a
   escolha é entre os cinco temas, e os dois lugares se reconhecem pela cor. */
#metadados .temas-meta, #calibrar .temas-calibrar { display: flex; flex-wrap: wrap; gap: .4rem; }
#metadados .opcao-tema, #calibrar .opcao-tema {
  position: relative; display: inline-flex; align-items: center; gap: .45rem; min-height: var(--alvo);
  box-sizing: border-box; padding: .35rem .8rem; cursor: pointer;
  font-family: var(--sans); font-size: .86rem; color: var(--tinta-2);
  background: var(--papel); border: 1px solid var(--borda-controle); border-radius: 999px;
}
#metadados .opcao-tema input, #calibrar .opcao-tema input { position: absolute; opacity: 0; width: 1px; height: 1px; margin: 0; }
#metadados .opcao-tema .ponto, #calibrar .opcao-tema .ponto { width: 8px; height: 8px; border-radius: 50%; flex: none; background: var(--t, var(--tenue)); }
#metadados .opcao-tema:has(input:checked), #calibrar .opcao-tema:has(input:checked) {
  color: var(--tinta); border-color: var(--t, var(--acento));
  background: color-mix(in srgb, var(--t, var(--acento)) 10%, var(--papel));
}
#metadados .opcao-tema:has(input:focus-visible), #calibrar .opcao-tema:has(input:focus-visible) { outline: 2px solid var(--foco); outline-offset: 2px; }
#metadados .dica-meta { display: block; font-family: var(--sans); font-size: .78rem; color: var(--tenue); margin: .35rem 0 0; }
#metadados #meta-casa { margin: -.3rem 0 .8rem; }
#metadados #meta-casa[hidden] { display: none; }
.campo-meta input:disabled { color: var(--tenue); background: var(--papel-elev); }

#colar .lingua-do-texto { display: flex; align-items: center; gap: .6rem; margin: 0 0 .9rem; }
#colar .lingua-do-texto > span { flex: none; font-size: .8rem; font-weight: 600; letter-spacing: .02em; color: var(--tinta-2); }
#colar .lingua-do-texto select { flex: 1; min-width: 0; width: auto; }
.lingua-sugestao { font-size: .85rem; color: var(--tenue); }
.lingua-sugestao .btn { margin-left: .3rem; }

/* ── O arquivo, e a prévia que o segura (L-111, spec 17 §3.1) ──────────────
   A prévia não é enfeite: a detecção de duas colunas NÃO funciona, e o texto
   extraído na tela é a única salvaguarda que existe entre um PDF embaralhado
   e a inbox de quem vai ler. Por isso ela ocupa o corpo do painel, rola por
   dentro (como os turnos da conversa, L-81) e deixa os botões presos no pé —
   controle que sai da tela é controle que não existe. */

/* ── A porta do arquivo  (revisão 2026-08-24) ──────────────────────────────
   Antes: o `<input type="file">` NU — «Escolher arquivo · Nenhum arquivo
   escolhido» desenhado pelo sistema, o único pedaço de cromo do app que
   nenhum CSS vestia. Um botão de sistema no meio de um painel de papel.

   Agora o label é a porta inteira: zona tracejada na medida do campo de URL
   acima, com o ícone da bandeja (gramática do GLIFO, traço `currentColor`)
   e os formatos aceitos escritos — a informação que o `accept` sempre teve
   e nenhum olho via. O tracejado diz «aqui entra coisa de fora», o mesmo
   vocabulário do chip «Limpar» dos filtros.

   O input segue vivo dentro do label (ver o comentário no colar.mjs):
   escondido por tamanho e opacidade, nunca por `display:none` — senão o
   teclado o perde. O anel de foco acende no LABEL via `:focus-within`,
   porque o anel do núcleo acenderia num elemento de 1px. */
#colar label.arquivo {
  display: flex; flex-direction: column; align-items: center; gap: .32rem;
  position: relative; margin: .8rem auto 0; max-width: var(--measure);
  padding: 1.05rem 1rem 1.1rem; text-align: center; cursor: pointer;
  border: 1.5px dashed var(--borda-controle); border-radius: var(--raio);
  font-family: var(--sans); color: var(--tinta-2);
  transition: border-color var(--dur-rapida) ease, color var(--dur-rapida) ease,
              background-color var(--dur-rapida) ease;
}
#colar label.arquivo:hover, #colar label.arquivo:focus-within, #colar label.arquivo.arrastando {
  border-color: var(--acento); color: var(--acento);
  background: color-mix(in srgb, var(--acento) 5%, transparent);
}
/* Com um arquivo no ar, a porta diz que é ali: o tracejado fecha e o fundo sobe. */
#colar label.arquivo.arrastando {
  border-style: solid; background: color-mix(in srgb, var(--acento) 12%, transparent);
}
#colar label.arquivo:focus-within { outline: 2px solid var(--foco); outline-offset: 2px; }
#colar .porta-ic { width: 26px; height: 26px; }
#colar .porta-titulo { font-size: .88rem; font-weight: 600; color: inherit; }
#colar .porta-formatos { font-size: .66rem; font-weight: 600; letter-spacing: .09em;
  text-transform: uppercase; color: var(--tenue); }
#colar input[type="file"] {
  position: absolute; width: 1px; height: 1px; opacity: 0;
  overflow: hidden; clip-path: inset(50%);
}
#colar-previa { flex: 1 1 auto; min-height: 0; overflow-y: auto;
  max-width: var(--measure); margin-inline: auto; width: 100%; }
#colar-previa[hidden] { display: none; }
#colar-previa-titulo { font-family: var(--sans); font-size: .95rem; font-weight: 600;
  color: var(--tinta); margin: 0 0 .2rem; }
#colar-previa-meta { margin: 0 0 .6rem; }
/* Fonte de corpo e `pre-wrap` porque o que se julga aqui é a leitura: as
   quebras de linha SÃO a evidência de que as colunas se costuraram, e um
   `white-space: normal` esconderia justamente o defeito que a prévia veio
   mostrar. */
#colar-previa-texto { font-family: var(--corpo); font-size: .9rem; line-height: 1.55;
  color: var(--tinta-2); white-space: pre-wrap; overflow-wrap: anywhere;
  border-left: 2px solid var(--regra); padding-left: .7rem; }
#colar .linha { display: flex; align-items: center; gap: .5rem; margin-top: .9rem;
  flex: none; flex-wrap: wrap; }
#colar .linha button[hidden] { display: none; }
/* A frase de erro é a entrega deste recurso (spec §8) e pode ter duas linhas:
   `flex: 1` dá a ela a largura que sobra em vez de espremer os botões. */
#colar .linha .sub { flex: 1; line-height: 1.4; }
/* ── «Publicar» é PRIMÁRIO  (revisão 2026-08-24) ───────────────────────────
   O painel tem uma ação só que importa, e ela vestia a mesma borda cinza do
   «Fechar» ao lado — a tela dizia que publicar e desistir pesavam igual.
   Acento cheio + `--sobre-acento`, como o «Entrar» do login: mesmo papel na
   hierarquia, mesma roupa. O hover NÃO herda o de `.btn` (que troca a tinta
   para o acento — invisível sobre o próprio acento): clareia, como o Entrar.

   A ordem visual vem por `order`, sem tocar no DOM: confirmação à direita,
   como todo sheet do iPadOS — e o foco do teclado continua na ordem do
   documento, que ninguém reordenou. */
#colar #colar-publicar, #colar #colar-previa-publicar {
  background: var(--acento); color: var(--sobre-acento);
  border-color: transparent; font-weight: 600; padding: .38rem 1.1rem;
  order: 4;
}
#colar #colar-publicar:hover, #colar #colar-publicar:focus-visible,
#colar #colar-previa-publicar:hover, #colar #colar-previa-publicar:focus-visible {
  color: var(--sobre-acento); border-color: transparent; filter: brightness(1.08);
}
#colar #colar-previa-descartar { order: 3; }
#colar #colar-fechar { order: 2; }
#colar #colar-publicar[disabled], #colar #colar-previa-publicar[disabled] { opacity: .55; filter: none; }
/* O «Adicionar» do pacote .zip (spec 79 §9.2) veste a mesma roupa primária:
   é a ação que importa naquele modo, e o painel só mostra uma por vez. */
#colar #colar-pacote-enviar {
  background: var(--acento); color: var(--sobre-acento);
  border-color: transparent; font-weight: 600; padding: .38rem 1.1rem;
  order: 4;
}
#colar #colar-pacote-enviar:hover, #colar #colar-pacote-enviar:focus-visible {
  color: var(--sobre-acento); border-color: transparent; filter: brightness(1.08);
}
#colar #colar-pacote-enviar[disabled] { opacity: .55; filter: none; }
#colar #colar-pacote-descartar { order: 3; }

/* ── O pacote .zip e as figuras da prévia  (spec 79 §9.2) ─────────────────
   O .zip escolhido tem a mesma voz do arquivo que sobe: o nome com peso, o
   resto como apoio. A linha das figuras da prévia fica entre a meta e o
   texto, na cor de apoio do painel. */
#colar-pacote { font-family: var(--sans); }
#colar-pacote[hidden], #colar-previa-figuras[hidden] { display: none; }
#colar-pacote-nome { margin: 0 0 .2rem; font-size: .95rem; font-weight: 600; line-height: 1.35;
  color: var(--tinta); overflow-wrap: anywhere; }
#colar-pacote-meta { margin: 0 0 .8rem; }
#colar-previa-figuras { margin: -.3rem 0 .6rem; color: var(--tinta-2); }

/* ── «Preparar antes de mandar»  (spec 79 §3.2) ───────────────────────────
   Um `<details>` recolhido, logo abaixo da porta do arquivo, na medida dela.
   Recolhido ele é uma linha só — o título e o ícone —, e aberto ele vive
   dentro do `.corpo-sheet`, que rola: a `.linha` do painel (status e botões)
   continua presa no pé, no telefone inclusive.

   O `summary` perde o triângulo do sistema (cromo que nenhum CSS veste
   igual nos três navegadores) e ganha o chevron em traço, que gira ao abrir.
   Toda tinta é das que o painel já usa sobre `--papel-elev`: `--tinta` no
   que se lê, `--tinta-2` no apoio e `--tenue` no rodapé — os três medidos
   nos três temas pelo `preparar-secao.test.mjs` (mira ≥ 4,7:1). */
#colar details.preparar {
  max-width: var(--measure); margin: .9rem auto 0; width: 100%; box-sizing: border-box;
  border-top: 1px solid var(--regra); padding-top: .35rem;
  font-family: var(--sans); color: var(--tinta-2);
}
#colar details.preparar > summary {
  display: flex; align-items: center; gap: .55rem; min-height: var(--alvo);
  list-style: none; cursor: pointer; border-radius: var(--raio-p);
  font-size: .88rem; font-weight: 600; color: var(--tinta-2);
  transition: color var(--dur-rapida) ease;
}
#colar details.preparar > summary::-webkit-details-marker { display: none; }
#colar details.preparar > summary::after {
  content: ""; flex: none; margin: 0 .35rem 0 auto; width: .45rem; height: .45rem;
  border-right: 1.7px solid currentColor; border-bottom: 1.7px solid currentColor;
  transform: translateY(-2px) rotate(45deg); transition: transform var(--dur-rapida) ease;
}
#colar details.preparar[open] > summary::after { transform: translateY(2px) rotate(-135deg); }
#colar details.preparar > summary:hover { color: var(--acento); }
#colar details.preparar > summary:focus-visible { outline: 2px solid var(--foco); outline-offset: 2px; }
#colar .preparar-ic { width: 22px; height: 22px; flex: none; }
#colar .preparar-corpo { padding: .2rem 0 .3rem; }
#colar .preparar-texto { margin: .2rem 0 .8rem; font-size: .88rem; line-height: 1.5; color: var(--tinta); }
#colar .preparar-acoes { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: .6rem; }
#colar .preparar-acao { display: flex; align-items: center; flex-wrap: wrap; gap: .25rem .75rem; }
#colar .preparar-acao .btn {
  display: inline-flex; align-items: center; gap: .45rem; min-height: var(--alvo);
  box-sizing: border-box; text-decoration: none;
}
#colar .preparar-acao .btn svg { width: 18px; height: 18px; flex: none; }
#colar .preparar-para { font-size: .8rem; line-height: 1.35; color: var(--tinta-2); }
/* O ✓ no próprio botão depois de copiar: a gramática da cerca de código e
   dos Destaques (`copiar.mjs`). */
#colar .preparar-copiar .ic-copiado { display: none; }
#colar .preparar-copiar[data-estado="copiado"] .ic-copiar { display: none; }
#colar .preparar-copiar[data-estado="copiado"] .ic-copiado { display: inline; }
#colar .preparar-copiar[data-estado="copiado"] { color: var(--cromo-acento); border-color: var(--cromo-acento); }
#colar .preparar-copiar[disabled] { opacity: .55; cursor: default; }
#colar .preparar-status { margin: .6rem 0 0; font-size: .8rem; line-height: 1.4; color: var(--tinta-2); }
#colar .preparar-status:empty { display: none; }
#colar .preparar-mostrar { margin-top: .5rem; }
#colar .preparar-mostrar[hidden], #colar pre.prompt-manual[hidden] { display: none; }
/* O prompt à mão (a cópia falhou): rola por DENTRO, com altura máxima, para
   não empurrar o resto da seção; o `tabindex` o põe no Tab, e o anel acende. */
#colar pre.prompt-manual {
  margin: .6rem 0 0; max-height: 12rem; overflow: auto; box-sizing: border-box;
  white-space: pre-wrap; overflow-wrap: anywhere;
  font-family: var(--mono); font-size: .75rem; line-height: 1.45; color: var(--tinta);
  background: var(--papel); border: 1px solid var(--regra); border-radius: var(--raio-p);
  padding: .6rem .7rem; user-select: text; -webkit-user-select: text;
}
#colar pre.prompt-manual:focus-visible { outline: 2px solid var(--foco); outline-offset: 2px; }
#colar .preparar-fecho { margin: .8rem 0 0; font-size: .8rem; line-height: 1.45; color: var(--tenue); }

/* O gatilho, no cabeçalho da inbox. É BOTÃO e não campo — `desenhar()`
   repinta o cabeçalho inteiro a cada 30s (`inbox.mjs:406`), e botão não tem
   estado a perder. A linha alinha pela base para o rótulo do botão assentar
   na do título, e não no meio dele. */
.titulo-inbox { display: flex; align-items: center; justify-content: space-between;
  gap: .8rem; }
.titulo-inbox h1 { margin-bottom: 0; }

/* ── O botão de entrada ─────────────────────────────────────────────────────
   A versão anterior era um `.btn` com rótulo «＋ Ler», e ela errava em
   hierarquia: ficava idêntica às abas de status logo abaixo — quatro
   retângulos com a mesma borda —, de modo que a AÇÃO da tela pesava o mesmo
   que os FILTROS. Numa página que é tipografia sobre papel, era também o
   único objeto com cara de formulário.

   ── Quadrado de canto arredondado, não disco  (2026-08-24) ────────────────
   Foi disco («círculo quer dizer coisa que se faz», como o `#caneta`) e
   Yuri o reprovou OVAL: o `border-radius:50%` nunca desenhou círculo aqui,
   porque o `min-height:44px` do núcleo (`:where(button…)`) vence o
   `height:30px` — a caixa real era 30×44. É a MESMA armadilha que o
   comentário de `.linha-progresso .redondo` já registrava («min-height
   vence height e o círculo vira elipse»), e este botão nunca recebeu a
   exceção. A forma nova resolve o defeito e ganha parentesco melhor: o
   quadrado de canto arredondado é a forma do GLIFO da marca no outro lado
   do mesmo cabeçalho (30px, raio 9) e a do próprio ícone do app — os dois
   selos de acento da tela agora são a mesma família, um diz «Leitor», o
   outro diz «entra coisa aqui». O raio segue a proporção do glifo (9/30).

   É o ÚNICO ponto saturado da tela, e isso é a decisão: todo o resto é tinta
   sobre papel, então a cor marca a única coisa que se pode fazer. O `+` sem
   rótulo se sustenta porque é ícone consagrado para «acrescentar» — o veto da
   §5.2 é a ícone INVENTADO, e o nome acessível continua inteiro no
   `aria-label`. */
.entrada {
  flex: none; display: grid; place-items: center;
  /* 30px, e não 34: a 34 o botão competia com a altura do «Inbox» em vez de
     servi-lo. O controle é a ação da tela, não o assunto dela. O
     `min-height` explícito é a exceção ao `--alvo` do núcleo — sem ele a
     caixa estica para 44px e a forma vira oval; a exceção é legítima pela
     mesma razão dos `.redondo` da lista: o alvo real do gesto continua
     confortável no cabeçalho, sem vizinho a meio dedo de distância. */
  width: 30px; height: 30px; min-height: 30px; border-radius: 9px;
  border: none; cursor: pointer;
  background: var(--acento); color: var(--sobre-acento);
  font: 500 1.25rem/1 var(--sans);
  /* O glifo `+` assenta alto na caixa da fonte; 1px o traz ao centro óptico. */
  padding-bottom: 1px;
  transition: transform .12s ease, filter .12s ease;
}
.entrada:hover { filter: brightness(1.12); }
.entrada:active { transform: scale(.94); }
@media (prefers-reduced-motion: reduce) { .entrada { transition: none; } }

/* ── A lupa, ao lado do `+`  (02/09) ───────────────────────────────────────
   Mesma forma e mesma caixa do botão de entrada — são os dois controles do
   cabeçalho da lista —, e a hierarquia entre eles é de PESO: o `+` é a ação
   que traz coisa nova e veste o acento cheio; a lupa é o caminho até o que já
   está lá, e veste aro fino sobre papel. Cheia, ela empataria com o `+` e a
   tela passaria a ter duas ações principais.

   `text-decoration: none` porque agora é um `<a>`: link que leva a uma tela é
   o que o roteador, o «abrir em nova aba» e o teclado já sabem tratar. */
.entrada.lupa {
  background: var(--papel-elev); color: var(--tinta-2);
  border: 1px solid var(--aro-fino); text-decoration: none;
  padding-bottom: 0;
}
.entrada.lupa svg { width: 17px; height: 17px; display: block; }
.entrada.lupa:hover, .entrada.lupa:focus-visible {
  filter: none; color: var(--acento); border-color: var(--acento);
}

/* ── O resultado da busca de artigos  (02/09) ──────────────────────────────
   Agrupado por estado — «Lendo», «Não lidos», «Lidos», «Arquivados» —, na
   gramática que os Destaques já usam para o cabeçalho de cluster: uma LINHA
   com nome, contagem e régua embaixo, e não um cartão em volta. O que a busca
   devolve são cartões; um cartão em volta de cartões é uma moldura a mais. */
/* ── `--measure` está em `em`, e isso morde quem tem fonte menor  (02/09) ──
   `--measure: calc(34.5em * var(--fator-espaco))` mede em EM, relativo à fonte
   do próprio elemento — é o que faz a medida de linha valer 34,5 caracteres em
   qualquer tamanho de texto, que é a razão de ela existir.

   O efeito colateral aparece quando o token vira `max-width` de um bloco com
   fonte MENOR: a contagem do resultado é `.sub` (.82rem), e 34,5em ali deram
   453px contra os 707 dos grupos ao lado — a linha «3 artigos» nascia recuada
   sozinha no meio da coluna.

   Aqui nenhum dos três precisa do teto: o `main` já limita a coluna, e o que
   estes blocos querem é a largura do irmão de cima. Quem mede LINHA usa o
   token; quem só quer acompanhar a coluna herda do pai. */
.busca-artigos { margin: 0 0 1rem; }
.conta-busca { margin: 0 0 .9rem; }
.grupo-busca { margin: 0 0 1.6rem; }
.grupo-busca > h2 {
  display: flex; align-items: baseline; gap: 9px;
  font-family: var(--sans); font-size: 12.5px; font-weight: 600; color: var(--tinta);
  margin: 0 0 14px; padding-bottom: 9px; border-bottom: 1px solid var(--regra);
}
/* ── O pé da página de destaques  (02/09) ─────────────────────────────────
   «Mostrando 200 de 1430» à esquerda e o botão à direita: o número diz onde a
   lista está, e o botão diz o que fazer com isso. Separados por `auto`, e não
   centrados, porque a leitura é «quanto» → «e daí» — a mesma ordem da linha de
   estado dos cartões. */
.mais-destaques {
  max-width: var(--measure); margin: .4rem auto 2rem;
  display: flex; align-items: center; gap: .8rem;
}
.mais-destaques .sub { flex: 1; min-width: 0; }
.mais-destaques .btn { flex: none; }

.grupo-busca > h2 .conta {
  margin-left: auto; font-size: 11.5px; font-weight: 400; color: var(--tenue);
  font-variant-numeric: tabular-nums;
}

/* O botão de perguntar no rodapé do artigo acompanha os três de `montarAcoes`,
   mas não é um deles: leva rótulo escrito porque não tem ícone consagrado, e
   um ícone inventado seria o defeito que a §5.2 já nomeou uma vez — a ação
   que existe e não é encontrada. */
.artigo > footer .acoes .btn.ia { border-color: var(--cromo-acento); color: var(--cromo-acento); }

/* A amostra do controle de marginália mostra o próprio efeito, como as outras
   cinco: uma coluna sozinha, ou uma coluna com o filete da margem ao lado. */
#ajustes .am-marg { display: inline-flex; gap: 2px; align-items: stretch; height: 15px; }
#ajustes .am-marg i { display: block; width: 9px; background: var(--tinta-2); border-radius: 1px; }
#ajustes .am-marg i + i { width: 4px; background: var(--regra); }
#ajustes .am-marg[data-m="nao"] i + i { display: none; }
/* O controle «Notas» aparece em toda largura desde o trilho (28/08): abaixo
   do limiar ele passou a ligar alguma coisa — os marcadores — e um controle
   que só existe em paisagem deixaria o retrato sem como desligá-los. */
#ajustes .grupo[data-grupo="marginalia"] { display: block; }
/* `block`, e não `flex` (25/09): o grupo é o mesmo `div` de rótulo + fileira
   dos outros sete, e em `flex` o rótulo «Notas» deitava na mesma linha dos
   dois botões, colado ao primeiro, em vez de ficar em cima como os outros.
   Quem mostrou foi a captura da vaga 3 da App Store, no telefone. */

/* ── marginália: as notas na margem (L-74, spec 13 §3) ─────────────────────
   A nota volta para onde a anotação esteve por mil anos antes de virar um
   painel que se abre. **A `--measure` não muda** — o painel ocupa a folga que
   já sobrava ao lado da coluna, e não um pedaço da leitura (01: estética de
   leitura é inegociável).

   Todo o layout é CSS, comandado pelo `data-marginalia` do `<html>`. Nenhum
   JavaScript mede coluna nem margem: o que o JS calcula é só a ALTURA de cada
   nota, que depende do texto e não da tela. */
:root {
  /* ── Em `rem`, e isto é correção de defeito, não gosto  (L-74) ────────────
     Estavam em `em`, e `em` resolve contra a fonte do ELEMENTO. A mesma
     variável era lida em dois lugares com fontes diferentes — no `<main>`,
     contra a fonte de leitura; dentro do painel, contra os .78rem dele — e o
     `<main>` reservava mais espaço do que o painel ocupava. A sobra virava um
     vão entre o texto e a nota, que crescia junto com o tamanho do texto.
     `rem` resolve contra a raiz e vale o mesmo nos dois lados da conta. */
  --marg-largura: 14rem;
  --marg-vao: 1rem;
}

/* Fora do limiar o painel não existe — nem ele, nem o controle que o liga
   (ver `#ajustes`). Some sozinho, sem aviso e sem estado a lembrar: um painel
   que pedisse para ser fechado ao girar o iPad seria um diálogo no meio da
   leitura. O limiar é em `em` e não em px porque a medida é em `em`, e o
   leitor muda o tamanho do texto. */
#marginalia { display: none; }

@media (min-width: 56em) {
  /* A composição é coluna + vão + painel, e é ELA que fica centrada. Com a
     coluna centrada, a folga se dividiria em duas e o painel herdaria metade
     — larga demais para nada, estreita demais para uma nota. */
  /* ── Grade, e não conta de largura  (L-74, correção) ─────────────────────
     A primeira versão prendia o painel à borda do `<main>` e confiava numa
     `max-width` calculada para que essa borda caísse logo depois da folha.
     Conta que precisa fechar é conta que uma hora não fecha: bastava a
     largura efetiva do `<main>` diferir da prevista — por viewport, por
     tamanho de texto, por arredondamento — e o painel afastava-se da folha
     sem que nada no CSS dissesse isso.

     Duas colunas resolvem por construção. O painel é **vizinho** da folha,
     não um elemento pendurado numa borda que se espera no lugar certo: o vão
     é o `gap`, e nenhuma aritmética o produz. */
  /* ── Escopado à ROTA, e não só à preferência ─────────────────────────────
     O `<main>` é a raiz de TODAS as telas — inbox, destaques, artigo. Um
     `display: grid` solto nele partiu a inbox em duas colunas, com os cartões
     espremidos na faixa de 14rem reservada para as notas. A grade vale só
     onde há folha ao lado da qual pousar.

     E o `max-width` saiu daqui: `body[data-leitura] main` já declara
     `max-width: none` com especificidade maior, então a conta que eu escrevia
     nunca valeu — era ela que deixava o painel ir para a borda da tela. Com
     a grade não há conta: `justify-content: center` centra as duas faixas. */
  [data-marginalia="sim"] body[data-leitura] main {
    display: grid;
    grid-template-columns: minmax(0, auto) var(--marg-largura);
    gap: var(--marg-vao);
    align-items: start;
    justify-content: center;
    /* ── A faixa da coluna de cápsulas fica fora da grade  (25/09) ─────────
       A coluna flutuante mora na borda direita, fixa, e a grade centrava
       folha + margem na janela inteira: a 951 (o Duo aberto deitado), a 1032
       (o iPad de 13" em retrato) e a 1180, a margem de notas corria por
       baixo da coluna — a sonda mediu 74, 74 e 17px. Reservar a faixa dela
       no `<main>` centra a composição no que sobra; onde sobra espaço (1376,
       o iPad deitado) a composição só desliza meia faixa para a esquerda, e
       onde não sobra é a coluna do texto (`minmax(0, auto)`) que cede. */
    padding-right: max(env(safe-area-inset-right), calc(var(--capsula-x) + var(--capsula-l) + .75rem));
  }
  [data-marginalia="sim"] body[data-leitura] .artigo {
    margin-inline: 0;
    padding-right: 1.5rem;
    max-width: calc(var(--measure) + var(--respiro) + 1.5rem);
    /* ── A coluna, DECLARADA  (03/09) ─────────────────────────────────────
       Prender um filho não diz nada sobre o seguinte. A trilha do estudo já
       era `grid-column: 1`, e o auto-posicionamento punha a folha na célula
       livre à direita — a da margem: no Mac do Yuri o artigo apareceu numa
       tira de 224px com o título quebrando uma palavra por linha, e o painel
       da marginália ocupando os 492px do texto. Numa grade que recebe filhos
       de mais de uma rota, cada um diz onde mora. */
    grid-column: 1;
  }

  /* ── O painel e as marcas medem a partir do MESMO elemento ───────────────
     O painel é filho do `<main>` (é o que sobrevive ao `raiz.innerHTML` que
     redesenha o artigo), então é o `<main>` que vira o bloco de contenção.
     Isso alinha os dois lados da conta: `offsetTop` de uma marca também passa
     a ser medido a partir daqui, porque `offsetParent` é o ancestral
     posicionado mais próximo. Pendurar o painel na `.prosa` enquanto o JS
     mede contra o `<main>` foi exatamente o defeito da primeira tentativa —
     o painel saía da tela. */
  /* O `<main>` continua sendo a origem da conta de ALTURA: `offsetTop` de uma
     marca é medido a partir do ancestral posicionado mais próximo, e o painel
     começa no topo da mesma linha da grade. Os dois lados da conta partem do
     mesmo zero. */
  [data-marginalia="sim"] body[data-leitura] main { position: relative; }
  [data-marginalia="sim"] body[data-leitura] #marginalia {
    display: block; position: relative;
    font-family: var(--sans); font-size: .78rem; line-height: 1.5;
    grid-column: 2;
  }

  /* ── Na rota do ESTUDO a grade tem três filhos, e uma linha a mais ────────
     A trilha ocupa a primeira linha sozinha; a folha e o painel dividem a
     segunda. As duas LINHAS são declaradas porque o painel mede a altura das
     notas por `offsetTop` a partir do `<main>`: se ele começasse na linha da
     trilha e a folha na de baixo, toda nota nasceria deslocada pela altura da
     trilha. Fora do estudo não há trilha, e nada disto se aplica — daí a
     qualificação pela rota, em vez de linhas fixas para todo mundo. */
  [data-marginalia="sim"] body[data-rota="estudo"] .trilha { grid-row: 1; }
  [data-marginalia="sim"] body[data-rota="estudo"] .artigo,
  [data-marginalia="sim"] body[data-rota="estudo"] .antessala,
  [data-marginalia="sim"] body[data-rota="estudo"] .erro-estudo,
  [data-marginalia="sim"] body[data-rota="estudo"] #marginalia { grid-row: 2; }
}

/* Os dois trilhos partem do topo. O de baixo não empurra o de cima porque
   ambos são absolutos — quem impede a colisão é o `piso` do posicionador, que
   mede o bloco de cima e começa o de baixo depois dele. */
#marginalia .marg-sem-ancora,
#marginalia .marg-ancoradas { position: absolute; top: 0; left: 0; right: 0; }
/* ── O bloco não nasce atrás do cabeçalho vivo  (spec 64 §2.4) ─────────────
   `.marg-sem-ancora` começa no topo do `<main>` — e no capítulo de livro o
   `.cabecalho-vivo` é `position: fixed`, opaco e mede 61 px ali por cima. O
   rótulo e as duas primeiras linhas da primeira nota ficavam invisíveis, e
   foi assim que o defeito chegou em 19/09 numa captura do dono.

   A altura é MEDIDA (`--cabecalho-h`, escrita por `repintarMargem`) e não
   cravada: ela depende de `--alvo` e da área de segurança do aparelho. Sem a
   variável — artigo avulso, onde não há cabeçalho vivo — vale zero. */
#marginalia .marg-sem-ancora { padding-top: var(--cabecalho-h, 0px); }
#marginalia .marg-sem-ancora .rotulo {
  margin: 0 0 .4rem; color: var(--tinta-2); text-transform: uppercase;
  letter-spacing: .06em; font-size: .68rem;
}
#marginalia .marg-sem-ancora .marg-nota { position: static; margin-bottom: .6rem; }

#marginalia .marg-nota {
  position: absolute; left: 0; right: 0;
  color: var(--tinta-2); cursor: pointer;
  /* O filete na cor do destaque é o que liga a nota ao trecho sem uma linha
     desenhada atravessando a página. */
  border-left: 2px solid var(--hl-cor, var(--regra));
  padding: .1rem 0 .1rem .6rem;
  transition: color .15s ease, border-color .15s ease;
}
#marginalia .marg-nota[data-cor="roxo"]    { --hl-cor: var(--vivo-roxo); }
#marginalia .marg-nota[data-cor="amarelo"] { --hl-cor: var(--vivo-amarelo); }
#marginalia .marg-nota[data-cor="rosa"]    { --hl-cor: var(--vivo-rosa); }
#marginalia .marg-nota[data-cor="azul"]    { --hl-cor: var(--vivo-azul); }
#marginalia .marg-nota p { margin: 0; }
/* A pergunta da conversa vem antes da resposta, e mais apagada: ela é o que
   você perguntou, não o que se quer reler. */
#marginalia .marg-nota .p { font-weight: 600; color: var(--tinta); margin-bottom: .15rem; }
/* O que a máquina escreveu se distingue sem escrever "IA" em lugar nenhum. */
#marginalia .marg-nota[data-origem] .t { font-style: italic; }
#marginalia .marg-nota:hover,
#marginalia .marg-nota:focus-visible { color: var(--tinta); outline: none; }
#marginalia .marg-nota.acesa { color: var(--tinta); border-left-width: 4px; }

/* ── O trilho de marcadores: a marginália onde ela não cabe  (28/08) ────────
   Abaixo do limiar o painel de 14rem não tem onde existir — a medida não
   encolhe (spec 13 §2.3) — e até aqui a marginália simplesmente não existia
   no iPad em retrato. O que cabe é um TRILHO: um marcador por nota, na
   altura exata em que o cartão pousaria, encostado na borda direita, dentro
   da calha de padding da folha. Vê-se de relance onde há pensamento seu na
   página; o toque salta para o trecho E abre a nota (ver `quandoTocar` na
   tela), porque um marcador não mostra texto nenhum.

   `width < 56em` de propósito: é o MESMO número do painel — os dois lados da
   fronteira declarados com o mesmo limiar, sem faixa morta entre eles. E o
   mesmo `data-marginalia`: trilho e painel são a mesma preferência em duas
   larguras, não dois recursos.

   «Sobre o artigo» fica de fora: aquelas anotações não têm altura no texto,
   e um marcador no trilho apontaria para lugar nenhum. Continuam alcançáveis
   pela conversa, como antes do trilho.

   O alvo é 44px de ALTURA numa régua de ~20px de largura na beirada — alvo
   de borda se acerta rolando o polegar contra o canto, e alargá-lo para
   dentro poria uma superfície tocável por cima da última coluna de texto,
   roubando a seleção. O empilhamento do posicionador passa a espaçar por
   estes 44px medidos, então marcadores nunca se sobrepõem. */
@media (width < 56em) {
  [data-marginalia="sim"] body[data-leitura] main { position: relative; }
  [data-marginalia="sim"] body[data-leitura] #marginalia {
    display: block; position: absolute; top: 0; bottom: 0;
    right: max(.15rem, env(safe-area-inset-right));
    width: 1.1rem;
  }
  #marginalia .marg-sem-ancora { display: none; }
  #marginalia .marg-nota {
    height: 44px; border-left: 0; padding: 0;
    display: grid; place-items: center;
  }
  #marginalia .marg-nota .t,
  #marginalia .marg-nota .p { display: none; }
  /* A bolinha herda a MESMA `--hl-cor` do filete do cartão largo; o anel de
     tinta a 22% é o que a separa do papel quando a cor do destaque é clara. */
  #marginalia .marg-nota::before {
    content: ""; width: .45rem; height: .45rem; border-radius: 50%;
    background: var(--hl-cor, var(--regra));
    box-shadow: 0 0 0 1px color-mix(in srgb, var(--tinta) 22%, transparent);
  }
  #marginalia .marg-nota.acesa::before { width: .7rem; height: .7rem; }
}

/* ── página de destaques: a LISTA DE TEXTOS  (spec 55 §2.1) ──────────────────
   Era a árvore tema → texto → trecho, em `<details>` dentro de `<details>`.
   Virou uma linha por texto: o título em serifa, a contagem à direita, a
   sobrancelha (tipo · autor · tema) embaixo e uma faixa de 3px com a
   proporção das cores — a única pista de «que tipo de marca há aqui» que cabe
   numa linha. A linha inteira é o alvo: é um `<a>`. */
.filtros.dq-filtros { font-family: var(--sans); }
.dq-filtros .chip, .dq-filtros .seg-item { font-family: var(--sans); }
.dq-soma { margin: 0 0 .6rem !important; text-align: left; }
.dq-textos { list-style: none; margin: 0 0 2rem; padding: 0;
  border-top: 1px solid var(--regra); }
.dq-textos > li { border-bottom: 1px solid var(--regra); }
.dq-texto {
  display: grid; grid-template-columns: minmax(0, 1fr) auto; column-gap: 1rem; row-gap: 4px;
  padding: 14px 6px 12px; color: inherit; text-decoration: none; border-radius: 6px;
}
.dq-texto:hover, .dq-texto:focus-visible { background: var(--papel-elev); }
.dq-texto:hover .dq-titulo { color: var(--acento); }
.dq-titulo {
  grid-column: 1; font-family: var(--serif); font-size: 16px; font-weight: 600;
  line-height: 1.35; color: var(--tinta); text-wrap: pretty;
}
.dq-titulo .sub { font-weight: 400; font-style: italic; }
.dq-conta {
  grid-column: 2; grid-row: 1; align-self: baseline; justify-self: end; font-family: var(--sans);
  font-size: 13px; color: var(--tinta-2); font-variant-numeric: tabular-nums;
}
.dq-conta b { font-weight: 600; color: var(--tinta); }
.dq-meta, .dq-sobrancelha {
  font-family: var(--sans); font-size: 12px; color: var(--tenue);
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 0 6px; min-width: 0;
}
.dq-meta { grid-column: 1; }
.dq-quando { grid-column: 2; grid-row: 2; font-family: var(--sans); font-size: 11.5px; color: var(--tenue);
  text-align: right; white-space: nowrap; }
.dq-tipo { font-weight: 600; letter-spacing: .06em; text-transform: uppercase; font-size: 10.5px; color: var(--tinta-2); }
.dq-sep { color: var(--aro-fino); }
.dq-tema { display: inline-flex; align-items: baseline; gap: 5px; }
.dq-tema .ponto, .dq-filtros .ponto, .dq-filtros-texto .ponto {
  width: 6px; height: 6px; border-radius: 50%; display: inline-block; flex: none;
  background: var(--t, var(--tenue)); align-self: center;
}
.dq-faixa {
  grid-column: 1 / -1; display: flex; gap: 2px; height: 3px; margin-top: 6px;
  border-radius: 2px; overflow: hidden; max-width: 14rem;
}
.dq-faixa i { display: block; min-width: 3px; }
.dq-faixa i[data-cor="roxo"], .ponto[data-cor="roxo"]       { background: var(--vivo-roxo); }
.dq-faixa i[data-cor="amarelo"], .ponto[data-cor="amarelo"] { background: var(--vivo-amarelo); }
.dq-faixa i[data-cor="rosa"], .ponto[data-cor="rosa"]       { background: var(--vivo-rosa); }
.dq-faixa i[data-cor="azul"], .ponto[data-cor="azul"]       { background: var(--vivo-azul); }

/* ── Trechos do dia  (spec 60) ─────────────────────────────────────────────
   O que restou do Memoria: três trechos no topo da lista, em rodízio, só para
   reler. O cartão é o irmão do `.destaque` (papel elevado, filete da cor), mas
   sem pé de pigmento nem ✎/✕ — aqui nada se avalia nem se edita. O texto é o
   protagonista: serifa um ponto acima do cartão da lista, e a proveniência
   embaixo, miúda, como legenda de citação. Tudo em tokens: claro, sépia e
   escuro vêm de graça, e o contraste é o já medido para `--tinta-2`/`--tenue`
   sobre `--papel-elev`. */
#trechos-do-dia:empty { display: none; }
.td { margin: 2px 0 22px; }
.td-cabeca {
  display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between;
  gap: 2px 12px; margin: 0 0 10px;
}
.td-cabeca h2 {
  margin: 0; font-family: var(--sans); font-size: 12px; font-weight: 600;
  letter-spacing: .08em; text-transform: uppercase; color: var(--tinta-2);
}
.td-data { font-weight: 500; letter-spacing: .01em; text-transform: none; color: var(--tenue); }
.td-roda { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px; }
.td-roda p { margin: 0; font-family: var(--sans); font-size: 11.5px; color: var(--tenue); }
/* «Outros» e «Os do dia» (spec 60 §6): a mesma pílula quieta dos cartões,
   ao lado da conta da roda — é ela que o botão faz girar. */
.td-botoes { display: inline-flex; flex-wrap: wrap; gap: 6px; }
.td-botoes .td-acao { padding: 0 12px; font-size: 12px; }
.td-lista { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 10px; }
.td-cartao {
  position: relative; margin: 0; padding: 16px 18px 12px 20px;
  background: var(--papel-elev); border: 1px solid var(--papel-borda-fina);
  border-radius: 10px; box-shadow: var(--sombra-pousada); overflow: hidden;
}
.td-cartao .filete {
  position: absolute; left: 0; top: 0; bottom: 0; width: 3px;
  background: var(--hl-cor, var(--vivo-roxo));
}
.td-cartao[data-cor="roxo"]    { --hl-cor: var(--vivo-roxo); }
.td-cartao[data-cor="amarelo"] { --hl-cor: var(--vivo-amarelo); }
.td-cartao[data-cor="rosa"]    { --hl-cor: var(--vivo-rosa); }
.td-cartao[data-cor="azul"]    { --hl-cor: var(--vivo-azul); }
.td-texto {
  margin: 0; padding: 0; border: 0; font-style: normal;
  font-family: var(--serif); font-size: 16px; line-height: 1.6; color: var(--tinta);
  text-wrap: pretty; overflow-wrap: anywhere;
}
.td-texto p { margin: 0 0 .6em; }
.td-texto p:last-child { margin-bottom: 0; }
.td p.td-nota {
  font-family: var(--sans); font-size: 12.5px; line-height: 1.5; color: var(--tinta-2);
  margin: 10px 0 0; padding-left: 10px; border-left: 2px solid var(--aro-fino);
}
.td p.td-de {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 0 6px; margin: 10px 0 0;
  font-family: var(--sans); font-size: 12px; line-height: 1.45; color: var(--tenue);
}
.td-obra { font-style: normal; font-weight: 600; color: var(--tinta-2); }
.td-obra .sub { font-weight: 400; font-style: italic; }
.td-acoes { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 12px; }
/* Os dois alvos são a pílula quieta do «Copiar» da seção, não o `.btn` de
   cromo: em sépia o cromo é um bloco escuro, e seis deles gritariam mais que
   os três trechos. 36px como os `.dq-acoes`: alvo secundário dentro do cartão. */
.td-acao {
  display: inline-flex; align-items: center; gap: 6px; cursor: pointer; text-decoration: none;
  font-family: var(--sans); font-size: 12.5px; font-weight: 500; color: var(--tinta-2);
  background: none; border: 1px solid var(--aro-fino); border-radius: 999px;
  padding: 0 14px; min-height: 36px;
}
.td-acao:hover, .td-acao:focus-visible { color: var(--acento); border-color: var(--acento); }
.td-acao svg { width: 14px; height: 14px; flex: none; }
.td-copiar > .ic-copiado { display: none; }
.td-copiar[data-estado="copiado"] > .ic-copiar { display: none; }
.td-copiar[data-estado="copiado"] > .ic-copiado { display: block; }
.td-copiar[data-estado="copiado"] { color: var(--foco); border-color: var(--foco); }
.td-copiar[data-estado="falhou"] { color: var(--perigo); border-color: var(--perigo); }

/* ── Os filtros, recolhidos  (spec 55 §2.3) ───────────────────────────────
   À vista: a busca, o segmentado do tipo e o botão «Filtrar» com a contagem.
   Tema, cor e período moram no painel — e o que está LIGADO fica fora dele,
   como pílula com ✕, porque o filtro esquecido é a armadilha que os chips
   sempre expostos existiam para impedir. */
.dq-controles { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.dq-controles .segmentado { flex: none; }
.dq-abrir { margin-left: auto; cursor: pointer; font-family: var(--sans); }
.dq-abrir[aria-expanded="true"] { border-color: var(--acento); color: var(--acento); }
.dq-n {
  display: inline-grid; place-items: center; min-width: 18px; height: 18px; padding: 0 5px;
  border-radius: 999px; background: var(--acento); color: var(--sobre-acento);
  font-size: 10.5px; font-weight: 700; font-variant-numeric: tabular-nums;
}
.dq-ativos { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 12px; }
.dq-ativos .chip.limpar { margin-left: 0; }
.dq-painel {
  margin-top: 12px; padding: 14px 16px 16px; border-radius: 10px;
  background: var(--papel-elev); border: 1px solid var(--papel-borda-fina);
  box-shadow: var(--sombra-pousada);
}
.dq-painel[hidden] { display: none; }
.dq-rotulo {
  font-family: var(--sans); font-size: 10.5px; font-weight: 600; letter-spacing: .09em;
  text-transform: uppercase; color: var(--tenue); margin: 12px 0 8px !important;
}
.dq-painel > .dq-rotulo:first-child { margin-top: 0 !important; }
.dq-chips { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }

/* ── O calendário do dia  (17/09) ─────────────────────────────────────────
   O controle nativo de data só sabe `min`, `max` e `step` — não sabe desligar
   um dia avulso. Como a regra aqui é exatamente essa (dia sem destaque não é
   botão), a grade é desenhada: sete colunas, o dia marcado com a contagem, o
   vazio ainda no lugar dele e sem alvo. A caixa tem largura máxima porque um
   calendário esticado numa tela larga deixa de parecer um calendário. */
#dq-cal[hidden] { display: none; }
.dq-cal { margin-top: 12px; max-width: 300px; }
.dq-cal-topo { display: flex; align-items: center; gap: 4px; margin: 0 !important; }
.dq-cal-mes {
  flex: 1; display: block; text-align: center; font-family: var(--sans);
  font-size: 12.5px; font-weight: 600; color: var(--tinta-2);
}
.dq-cal-mes::first-letter { text-transform: uppercase; }
.dq-mes {
  flex: none; width: 36px; padding: 0; border: 0; border-radius: 9px; background: none;
  color: var(--tinta-2); font-size: 18px; line-height: 1; cursor: pointer;
}
.dq-mes:hover:not(:disabled), .dq-mes:focus-visible {
  color: var(--acento); background: color-mix(in srgb, var(--acento) 8%, transparent);
}
.dq-mes:disabled { color: var(--tenue); opacity: .45; cursor: default; }
.dq-grade { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px; }
.dq-sem {
  font-family: var(--sans); font-size: 10px; font-weight: 700; letter-spacing: .06em;
  color: var(--tenue); text-align: center; padding-bottom: 4px;
}
.dq-dia {
  display: grid; align-content: center; justify-items: center; min-height: 38px;
  border: 1px solid transparent; border-radius: 9px; font-family: var(--sans);
  font-size: 12.5px; font-variant-numeric: tabular-nums; color: var(--tenue);
  text-decoration: none;
}
.dq-dia b { font-weight: 500; }
.dq-dia.tem {
  color: var(--tinta); background: color-mix(in srgb, var(--acento) 8%, transparent);
}
.dq-dia.tem b { font-weight: 600; }
.dq-dia.tem i {
  font-style: normal; font-size: 9.5px; font-weight: 700; line-height: 1.1; color: var(--acento);
}
.dq-dia.tem:hover, .dq-dia.tem:focus-visible { border-color: var(--acento); }
.dq-dia.hoje { border-color: var(--aro-fino); }
.dq-dia.escolhido, .dq-dia.escolhido:hover {
  background: var(--acento); border-color: var(--acento); color: var(--sobre-acento);
}
.dq-dia.escolhido i { color: var(--sobre-acento); }
.dq-dia-abrir { cursor: pointer; font-family: var(--sans); }
.dq-dia-abrir[aria-expanded="true"] { border-color: var(--acento); color: var(--acento); }
.ic-cal { width: 14px; height: 14px; margin-right: 5px; vertical-align: -2px; }
.dq-filtros-texto .chip {
  display: inline-flex; align-items: center; gap: 6px; padding: 6px 11px;
  border: 1px solid var(--aro-fino); border-radius: 999px; font-family: var(--sans);
  font-size: 12px; font-weight: 500; color: var(--tinta-2); text-decoration: none;
  white-space: nowrap; min-height: 0; background: none;
}
.dq-filtros-texto .chip:hover, .dq-filtros-texto .chip:focus-visible { border-color: var(--acento); color: var(--acento); }
.dq-filtros-texto .chip.ativo {
  color: var(--tinta); border-color: color-mix(in srgb, var(--acento) 45%, transparent);
  background: color-mix(in srgb, var(--acento) 9%, var(--papel-elev));
}

/* ── Os achados da busca: trechos sob o nome do texto ─────────────────── */
.dq-achados { margin: 0 0 1.4rem; }
.dq-achados > h2, .dq-secao > h2 {
  display: flex; align-items: center; gap: 10px; margin: 0 0 12px; padding: 8px 0 9px;
  border-bottom: 1px solid var(--regra); font-family: var(--sans); font-size: 13px;
  font-weight: 600; color: var(--tinta);
}
.dq-achados > h2 a { color: inherit; text-decoration: none; font-family: var(--serif); font-size: 14.5px; }
.dq-achados > h2 a:hover { color: var(--acento); }
.dq-achados > h2 .conta, .dq-secao > h2 .conta {
  font-weight: 400; font-size: 12px; color: var(--tenue); font-variant-numeric: tabular-nums;
}

/* ── A página de UM texto  (spec 55 §2.2) ─────────────────────────────────
   Mais larga que a coluna de leitura quando há sumário: o sumário mora à
   esquerda, grudado no topo, e a coluna dos trechos mantém a medida. Abaixo de
   60rem o sumário deita numa fileira rolável sobre os trechos. */
body[data-rota="destaques-texto"] main { max-width: calc(var(--measure) + 15rem); }
.dq-volta { margin: 0 0 10px; font-family: var(--sans); font-size: 13px; }
.dq-volta a { color: var(--tinta-2); text-decoration: none; }
.dq-volta a:hover { color: var(--acento); }
.dq-cabeca { margin: 0 0 14px; }
.dq-cabeca h1 { margin: 4px 0 2px; text-wrap: balance; }
.dq-autor { font-family: var(--serif); font-style: italic; color: var(--tinta-2); margin: 0 0 6px !important; }
.dq-acoes { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 12px; }
.dq-acoes .btn { display: inline-flex; align-items: center; gap: 7px; text-decoration: none; min-height: 36px; }
.dq-acoes .btn svg, .dq-copiar-secao svg { width: 15px; height: 15px; flex: none; }
.dq-filtros-texto { margin: 0 0 18px; }
.dq-corpo.com-sumario { display: grid; grid-template-columns: 13rem minmax(0, var(--measure)); gap: 0 2.2rem; align-items: start; }
.dq-sumario { position: sticky; top: 1rem; max-height: calc(100vh - 2rem); overflow-y: auto; font-family: var(--sans); }
.dq-sumario ol { list-style: none; margin: 0; padding: 0; }
.dq-sumario a {
  display: flex; gap: 8px; align-items: baseline; padding: 6px 8px; border-radius: 6px;
  font-size: 12.5px; color: var(--tinta-2); text-decoration: none; min-height: 0;
}
.dq-sumario a:hover, .dq-sumario a:focus-visible { background: var(--papel-elev); color: var(--acento); }
.dq-sumario .t { flex: 1; min-width: 0; line-height: 1.35; }
.dq-sumario .n { color: var(--tenue); font-variant-numeric: tabular-nums; font-size: 11.5px; }
.dq-secao { margin: 0 0 1.6rem; scroll-margin-top: 1rem; }
.dq-secao > h2 .t { font-family: var(--serif); font-size: 15px; }
.dq-copiar-secao {
  margin-left: auto; display: inline-flex; align-items: center; gap: 6px; cursor: pointer;
  font-family: var(--sans); font-size: 12px; font-weight: 500; color: var(--tinta-2);
  background: none; border: 1px solid var(--aro-fino); border-radius: 999px;
  padding: 4px 10px; min-height: 0;
}
.dq-copiar-secao:hover, .dq-copiar-secao:focus-visible { color: var(--acento); border-color: var(--acento); }
@media (max-width: 60rem) {
  .dq-corpo.com-sumario { display: block; }
  .dq-sumario { position: static; max-height: none; overflow-x: auto; margin: 0 0 16px;
    -webkit-overflow-scrolling: touch; }
  .dq-sumario .dq-rotulo { display: none; }
  .dq-sumario ol { display: flex; gap: 6px; }
  .dq-sumario li { flex: none; }
  .dq-sumario a { border: 1px solid var(--aro-fino); border-radius: 999px; padding: 5px 11px; white-space: nowrap; }
  .dq-sumario .t { flex: none; }
}

/* O ✓ do copiar: as duas folhas nascem juntas e o estado escolhe qual se vê —
   a mesma gramática do botão da cerca de código. */
:is(.destaque .copiar, [data-copiar-tudo], .dq-copiar-secao) > .ic-copiado { display: none; }
:is(.destaque .copiar, [data-copiar-tudo], .dq-copiar-secao)[data-estado="copiado"] > .ic-copiar { display: none; }
:is(.destaque .copiar, [data-copiar-tudo], .dq-copiar-secao)[data-estado="copiado"] > .ic-copiado { display: block; }
:is(.destaque .pe .copiar, [data-copiar-tudo], .dq-copiar-secao)[data-estado="copiado"] { color: var(--foco); border-color: var(--foco); }
:is(.destaque .pe .copiar, [data-copiar-tudo], .dq-copiar-secao)[data-estado="falhou"] { color: var(--perigo); border-color: var(--perigo); }

.destaques { list-style: none; margin: 0 0 1rem; padding: 0;
  display: flex; flex-direction: column; gap: 9px; }
/* ── O destaque virou CARTÃO, e o filete entrou nele  (02/09) ──────────────
   Era uma linha com filete à esquerda, direto sobre a mesa. Com o agrupador
   deixando de ser cartão, a superfície desceu um nível: quem é objeto aqui é o
   trecho marcado, e é ele que ganha papel, borda fina e sombra.

   O filete leva a cor do destaque: aqui ele identifica a marca, ao contrário
   do filete de margem no TEXTO, que a §5.1 descartou por marcar o parágrafo
   inteiro. Numa lista, o item É o destaque — não há discrepância possível.
   `overflow: hidden` para o raio cortá-lo nos cantos, como no `.item`. */
.destaque {
  position: relative; padding: 14px 18px 12px; margin: 0;
  background: var(--papel-elev); border: 1px solid var(--papel-borda-fina);
  border-radius: 10px; box-shadow: var(--sombra-pousada); overflow: hidden;
}
.destaque .filete {
  position: absolute; left: 0; top: 0; bottom: 0; width: 3px;
  background: var(--hl-cor, var(--hl-roxo));
}
.destaque[data-cor="roxo"]    { --hl-cor: var(--vivo-roxo); }
.destaque[data-cor="amarelo"] { --hl-cor: var(--vivo-amarelo); }
.destaque[data-cor="rosa"]    { --hl-cor: var(--vivo-rosa); }
.destaque[data-cor="azul"]    { --hl-cor: var(--vivo-azul); }
/* Sem min-height explícito de propósito: é `<a href>` de verdade — navega até
   o trecho no artigo —, então o alvo de toque não é rótulo, é a linha
   inteira. Já herda os 44px do `--alvo` do núcleo (`:where(...,a[href])`),
   e nada aqui redeclara `min-height` para vencer essa herança. Verificado:
   `.destaque` (o pai) não tem altura fixa nem `overflow` que corte a caixa. */
.destaque .trecho {
  display: block; color: var(--tinta); text-decoration: none;
  font-family: var(--serif); font-weight: 400; font-size: 15px; line-height: 1.6;
  text-wrap: pretty;
}
.destaque .trecho:hover { color: var(--acento); }
/* ── O pé do cartão: pigmento, nota e os dois alvos  (02/09) ───────────────
   O rótulo do pigmento em PALAVRA é o ganho que não é estético: a cor do
   destaque significa alguma coisa (importante / vale citar / suspeito /
   estrutural), e até aqui essa semântica só existia na cabeça de quem marcou.
   Quem relê um mês depois lê a palavra. */
.destaque .pe {
  display: flex; align-items: center; gap: 8px; margin-top: 12px;
  font-family: var(--sans); min-width: 0;
}
.destaque .pigmento {
  font-size: 11px; font-weight: 500; letter-spacing: .09em; text-transform: uppercase;
  color: var(--tenue); flex: none;
}
.destaque .pe .divisa { width: 1px; height: 12px; background: var(--aro-fino); flex: none; }
/* A nota ganhou linha própria (spec 55): cortada em reticências no pé, ela
   era ilegível justamente quando existia; e o «sem nota» ocupava o pé de
   todos os cartões para dizer uma ausência. */
.destaque .nota-texto {
  font-family: var(--sans); font-size: 12.5px; line-height: 1.5; color: var(--tinta-2);
  margin: 8px 0 0; padding-left: 10px; border-left: 2px solid var(--aro-fino);
}
/* A pergunta da IA (19/09) em cima da resposta, no mesmo fio: os dois são um
   turno só. Em peso, como a `.p` da margem do texto — é quem pergunta. */
.destaque .dq-pergunta, .td p.td-pergunta {
  font-family: var(--sans); font-size: 12.5px; line-height: 1.5; font-weight: 600;
  color: var(--tinta); margin: 8px 0 0; padding-left: 10px; border-left: 2px solid var(--aro-fino);
}
.td p.td-pergunta { margin-top: 10px; }
:is(.destaque .dq-pergunta + .nota-texto, .td p.td-pergunta + .td-nota) { margin-top: 0; padding-top: 4px; }
.destaque .quando { font-family: var(--sans); font-size: 11px; color: var(--tenue); }
.destaque .dq-de { font-family: var(--sans); font-size: 11.5px; color: var(--tenue); margin: 0 0 4px; }
.destaque .pe .copiar svg { width: 13px; height: 13px; }
.destaque .pe .acoes { margin-left: auto; display: flex; gap: 5px; flex: none; }
/* 26px, e `min-height` explícito pela mesma razão de sempre: sem ele o
   `--alvo` de 44px do núcleo vence o `height` e o círculo vira elipse. A
   exceção é a de sempre — alvo secundário dentro de um cartão cuja linha
   inteira já é alvo conforme. */
.destaque .pe .redondo {
  width: 26px; height: 26px; min-height: 26px; font-size: 12px;
}
/* A tinta é a do CROMO, que o `.redondo` já dá (19/09). Esta regra ainda
   dizia `color: var(--tenue)` e a borda em `--aro-fino` — o par do botão
   VAZADO de antes de 04/09. Quando o redondo virou grafite, o glifo ficou
   cinza de papel sobre campo escuro, e o ✎ e o ✕ quase sumiam. Os estados
   seguem a mesma troca: `--foco` e `--perigo` são tintas de papel, e sobre o
   grafite quem se lê é `--cromo-acento` e `--cromo-perigo`. Vêm DEPOIS do
   `:is(...)[data-estado]` lá de cima, com o mesmo peso, e por isso vencem. */
.destaque .pe .copiar[data-estado="copiado"] { color: var(--cromo-acento); border-color: var(--cromo-acento); }
.destaque .pe .copiar[data-estado="falhou"],
.destaque .pe .x:hover, .destaque .pe .x:focus-visible {
  color: var(--cromo-perigo); border-color: var(--cromo-perigo);
}
.destaque .selo {
  font-family: var(--sans); font-size: .72rem; color: var(--tinta-2);
  margin: .3rem 0 0; opacity: .85;
}
.destaque .selo::before { content: "⚠ "; }
/* O ✕ é o segundo caminho de desmarcar (03 §5.2): na lista, o item some na
   frente de quem apagou — é o caminho que se acha sem procurar. Em 02/09 ele
   saiu do canto absoluto e desceu para o pé do cartão, ao lado do `✎` que
   abre a nota: os dois são o que se faz COM o trecho, e o que se faz com uma
   coisa mora junto dela, não flutuando sobre a quina. */

/* O pulso do salto de volta: o olho precisa de onde pousar depois de rolar
   vários parágrafos. Duas piscadas curtas, e só. */
/* Era `animation` numa `<mark>`, com o `.4s ease 2` literal e a nota que
   explicava o literal; na spec 45 quem pisca é o REGISTRO — `pigmento.pulsar()`
   põe e tira o trecho deste nome duas vezes, a 380ms. `::highlight` não anima,
   e o efeito é o mesmo porque o pulso sempre foi ligar e desligar uma cor, não
   interpolar nada. A cadência continua sendo escolhida a olho, e agora mora em
   `PULSO_MS`/`PULSO_VEZES` no `pigmento.mjs`, junto de quem a executa.

   `prefers-reduced-motion` perdeu a regra própria: sem animação, o que resta
   são duas trocas de cor — que é exatamente o que a preferência pedia no lugar
   da animação. */
::highlight(destaque-pulso) {
  background-color: color-mix(in srgb, var(--acento) 45%, var(--hl-amarelo));
}

/* ── O pulso do BLOCO  (L-123) ─────────────────────────────────────────────
   O salto da busca no texto pousa num parágrafo que ninguém marcou, e a
   animação acima não serve: ela interpola a partir de `--hl-cor`, que é a cor
   do destaque e não existe fora de uma `<mark>`. Sem custom property, o
   `background-color` inicial resolveria para `transparent` e as duas piscadas
   seriam uma só, no fim.

   Mesma cadência (duas piscadas, .4s ease), mesma razão de ser literal, e o
   mesmo respeito ao `prefers-reduced-motion` — ali o realce é estático, e não
   ausente: quem pediu menos movimento também precisa achar o parágrafo. */
@keyframes leitor-pulso-bloco {
  0%, 100% { background-color: transparent; }
  50% { background-color: color-mix(in srgb, var(--acento) 18%, transparent); }
}
.prosa [data-bid].pulsa {
  animation: leitor-pulso-bloco .4s ease 2;
  border-radius: var(--raio-p);
}
@media (prefers-reduced-motion: reduce) {
  .prosa [data-bid].pulsa {
    animation: none;
    background-color: color-mix(in srgb, var(--acento) 12%, transparent);
  }
}

/* ── As passagens do texto, na busca  (L-123) ──────────────────────────────
   Terceiro nível da mesma família de `<details>` da tela — cluster, artigo e
   agora isto —, mas visualmente SUBORDINADO aos dois: borda tracejada e
   sobrancelha tênue. A hierarquia é a mensagem: em cima está o que a mão
   marcou, aqui o que só passou pelos olhos. Um cartão com o mesmo peso dos
   grupos de destaque diluiria o acervo curado do leitor no acervo inteiro. */
.passagens {
  margin-top: 1.6rem; padding-top: 1.1rem;
  border-top: 1px dashed var(--regra);
}
.passagens > summary {
  display: flex; align-items: baseline; gap: .6rem; cursor: pointer;
  font-family: var(--sans);
}
.passagens > summary .titulo {
  font-size: .68rem; font-weight: 600; letter-spacing: .09em;
  text-transform: uppercase; color: var(--tenue);
}
.passagens > summary .conta { font-size: .78rem; color: var(--tenue); }
.passagens > .sub { margin: .3rem 0 .8rem; }
.passagens ul { list-style: none; margin: 0; padding: 0; }

.passagem a {
  display: block; padding: .6rem .7rem; border-radius: var(--raio-p);
  text-decoration: none; color: inherit;
  border: 1px solid transparent;
}
.passagem a:hover, .passagem a:focus-visible {
  background: var(--papel-elev); border-color: var(--regra);
}
/* O título do artigo vem ANTES do trecho, e menor: a pergunta que a lista
   responde é «onde eu li isso», e a resposta é o nome do texto. */
.passagem .onde {
  display: block; font-family: var(--sans); font-size: .72rem;
  color: var(--tenue); margin-bottom: .2rem;
}
/* O trecho na SERIFADA da leitura, não na sans do cromo: é prosa do artigo
   citada aqui dentro, e ler no mesmo tipo em que se leu ajuda a reconhecer. */
.passagem .texto {
  display: block; font-family: var(--serif); font-size: .92rem; line-height: 1.5;
  color: var(--tinta-2);
}
.passagem .texto mark {
  background: color-mix(in srgb, var(--acento) 22%, transparent);
  color: inherit; border-radius: 2px; padding: 0 .1em;
}

/* ── filtros dos destaques (L-55) ──────────────────────────────────────────
   Chips no lugar dos menus que a §7.1 desenha: menu no iPad é um toque a mais
   e uma camada sobre o conteúdo, e o que está ativo tem de ficar visível SEM
   abrir nada — é o que impede o filtro esquecido. */
.filtros { max-width: var(--measure); margin: 0 auto 1.4rem; }
/* ── Uma fileira só, e três registros dentro dela  (02/09) ─────────────────
   Eram três `<nav class="linha">` empilhados — cluster, pigmento, período —
   com catorze pastilhas do mesmo peso. Agora é uma fileira: os chips de
   recorte, uma divisa de 1px, e o segmentado do período. `flex-wrap` continua,
   porque num iPhone catorze pastilhas não cabem numa linha e a alternativa
   seria rolagem horizontal escondendo filtro ativo. */
.filtros .linha { display: flex; flex-wrap: wrap; align-items: center; gap: 8px;
  font-family: var(--sans); font-size: .78rem; }
.filtros .grupo-chips { display: contents; }
/* A divisa separa registros sem desenhar mais uma caixa. Some quando a
   fileira quebra logo antes dela? Não: ela quebra junto, e um traço no começo
   de uma linha ainda diz «daqui em diante é outra coisa». */
.filtros .divisa {
  width: 1px; height: 20px; background: var(--regra); margin: 0 3px; flex: none;
}
/* ── O chip em repouso é HAIRLINE, e só o ativo se tinge  (02/09) ──────────
   O que havia: fundo `--papel-elev` e borda `--borda-controle` em todos, o
   ativo se distinguindo só pela cor da borda. Catorze superfícies elevadas
   para catorze recortes que ninguém ligou ainda.

   Agora o repouso é transparente com aro fino, e o ATIVO ganha leito na
   própria matiz — a mesma gramática do `.chip` da inbox, que já tinge o ativo
   com `--t` para não dizer «cyber» com a cor do app.

   O aro fino é dispensado do piso de 3:1 pela razão que a nota de
   `--aro-fino` registra: o chip carrega ponto colorido e rótulo em
   `--tinta-2`, e a borda não é a única pista. */
.filtros .chip { display: inline-flex; align-items: center; gap: 6px;
  padding: 7px 12px; border: 1px solid var(--aro-fino); border-radius: 999px;
  font-size: 12px; font-weight: 500;
  color: var(--tinta-2); background: none; text-decoration: none; white-space: nowrap;
  min-height: 0; }
.filtros .chip:hover, .filtros .chip:focus-visible {
  border-color: var(--acento); color: var(--acento); }
.filtros .chip.ativo {
  color: var(--tinta);
  border-color: color-mix(in srgb, var(--t, var(--acento)) 45%, transparent);
  background: color-mix(in srgb, var(--t, var(--acento)) 9%, var(--papel-elev));
}
.filtros .chip.limpar { margin-left: auto; border-style: dashed; }
/* 6px, não 10: no chip hairline o ponto é o acento da peça, e a 10px ele
   competia com o rótulo. Sem aro próprio pelo mesmo motivo — dois contornos
   concêntricos num chip de 12px de texto. */
.filtros .ponto { width: 6px; height: 6px; border-radius: 50%; display: inline-block;
  flex: none; background: var(--t, var(--tenue)); border: 0; }

/* ── O período vira SEGMENTADO  (02/09) ───────────────────────────────────
   Quatro valores mutuamente exclusivos, sempre um deles ligado: é a definição
   de segmentado, e é a peça que as `.abas.seg` da inbox e as `.vistas` da
   estante já usam. Como pastilhas soltas, «Sempre» ligado parecia um filtro
   aplicado — quando é justamente a ausência de filtro. */
.filtros .segmentado {
  display: inline-flex; gap: 2px; padding: 3px; flex: none;
  background: var(--papel-elev-2); border-radius: 999px;
}
.filtros .seg-item {
  font-size: 11.5px; font-weight: 500; color: var(--tinta-2);
  text-decoration: none; padding: 7px 12px; border-radius: 999px;
  white-space: nowrap; min-height: 0;
}
.filtros .seg-item:hover, .filtros .seg-item:focus-visible { color: var(--acento); }
.filtros .seg-item.ativo {
  background: var(--papel-elev); color: var(--tinta); font-weight: 600;
  box-shadow: var(--sombra-pousada);
}
.filtros .ponto[data-cor="roxo"]    { background: var(--vivo-roxo); }
.filtros .ponto[data-cor="amarelo"] { background: var(--vivo-amarelo); }
.filtros .ponto[data-cor="rosa"]    { background: var(--vivo-rosa); }
.filtros .ponto[data-cor="azul"]    { background: var(--vivo-azul); }

/* ── busca nos destaques (L-56, L-68) ──────────────────────────────────────
   A caixa com aro e ícone existe porque um `<input type=search>` sem moldura,
   num app sem barra de navegação no alto, não se lê como campo — se lê como
   uma linha de texto cinza. O aro é a afordância. */
/* Borda em --borda-controle, não --regra (Onda 3, correção — mesmo caso do
   `.item` acima): mora sobre `--tela`, e `--regra` × `--tela` some de novo. O
   aro inteiro É a afordância do campo — a razão pela qual esta regra existe
   —, então é o mesmo controle que `--borda-controle` já cobre. */
/* Borda fina desde 02/09, e a afordância não se perdeu: ela mudou de peça. O
   aro grosso existia porque a caixa não tinha nada que a separasse da mesa —
   agora ela é `--papel-elev` COM sombra, que é a regra que o núcleo escreve
   para qualquer folha («é a sombra que separa a folha da mesa»). A lupa e o
   texto-guia continuam onde estavam. */
/* O seletor perdeu o `.filtros` em 02/09: a estante ganhou a MESMA caixa, e é
   a mesma pergunta em outra tela («onde está isto?»). Duas caixas diferentes
   para uma pergunta só seriam duas coisas na cabeça de quem usa. */
.busca {
  display: flex; align-items: center; gap: 10px; margin: 0 0 14px;
  background: var(--papel-elev); border: 1px solid var(--papel-borda-fina);
  border-radius: 10px; padding: 0 14px; min-height: 44px;
  box-shadow: var(--sombra-pousada);
}
.busca:focus-within { border-color: var(--acento); }
/* SVG desde a revisão 2026-08-24 — mesma razão dos ícones da barra: o "⌕"
   era glifo de texto e saía com peso de traço diferente do resto do cromo. */
.busca .ic { color: var(--tenue); flex: none; display: block; }
.busca .ic svg { width: 17px; height: 17px; display: block; }
.busca input[type="search"] {
  flex: 1; width: 100%; font-family: var(--sans); font-size: .9rem; color: var(--tinta);
  background: none; border: 0; border-radius: 0;
  padding: .6rem 0; -webkit-appearance: none; appearance: none;
}
/* O foco acende a CAIXA, não o campo: o campo já não tem borda própria, e um
   contorno interno dentro de um aro externo são duas molduras concêntricas. */
.busca input[type="search"]:focus-visible { outline: none; }
.busca input[type="search"]::placeholder { color: var(--tenue); }
/* Na estante ela divide a linha com o alternador de vista: `max-width` para não
   esticar até a coluna da capa num Mac de tela larga. */
.busca-estante { max-width: var(--measure); margin: 0 auto 1.1rem; }

/* ── painel de diagnóstico (L-58c) ────────────────────────────────────────
   No iPad não há console: sem isto, todo defeito que só acontece no aparelho
   vira adivinhação. Só existe no DOM quando ligado por `?diag=1`. */
#diag {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 90; max-height: 42vh;
  display: flex; flex-direction: column;
  background: color-mix(in srgb, var(--papel-elev) 94%, transparent);
  /* aresta: painel fixo cobrindo até 42vh por baixo — mesma classe de sheet
     que #ajustes e #nota, ancorado na borda, não pairando sobre a página. */
  border-top: 2px solid var(--acento); box-shadow: var(--sombra-aresta);
  font-family: var(--mono); font-size: 11px; line-height: 1.45; color: var(--tinta);
  padding-bottom: env(safe-area-inset-bottom);
}
#diag .topo { display: flex; align-items: center; gap: .5rem; padding: .4rem .6rem;
  border-bottom: 1px solid var(--regra); }
#diag .topo strong { color: var(--acento); letter-spacing: .04em; }
/* Sem min-height explícito de propósito: são `<button>` de verdade (copiar,
   limpar, fechar) — controles isolados, não rótulos —, então merecem o
   alvo cheio. Já herdam os 44px do `--alvo` do núcleo (`:where(button,…)`)
   porque nada aqui redeclara `min-height`, e `#diag .topo` (o pai) é flex
   com altura livre, sem `overflow` que corte a caixa. */
/* Borda em --borda-controle (§2): background:none — o botão não tem fundo
   próprio, só o do painel atrás dele —, então a borda é a única pista. */
#diag button { margin-left: auto; font: inherit; color: var(--tinta-2);
  background: none; border: 1px solid var(--borda-controle); border-radius: 5px;
  padding: .25rem .5rem; cursor: pointer; }
#diag button + button { margin-left: .3rem; }
#diag .contas { padding: .4rem .6rem; color: var(--acento); word-break: break-all; }
#diag .linhas { padding: 0 .6rem .5rem; overflow-y: auto; white-space: pre-wrap;
  word-break: break-word; color: var(--tinta-2); }

/* ── prévia da seleção (L-58d) ─────────────────────────────────────────────
   Enquanto há seleção nativa viva, o iOS mostra o menu dele (Copiar,
   Consultar) por cima da nossa barra, e o leitor não alcança "Destacar".
   A seleção nativa é o feedback DURANTE o arrasto; terminado o gesto, ela sai
   e esta tinta fica no lugar — diz a mesma coisa e não traz menu junto.

   O tracejado a distingue de um destaque confirmado: é proposta, não fato. */
/* Na spec 45 a prévia deixou de ser um destaque falso com `hlId="__previa__"`
   passado ao pintor e virou nome próprio, pintado por `pigmento.previa()`. A
   cor vem de `--cor-ativa`, que o `usarCor()` já publica no documento — a
   mesma variável que acende o botão da caneta, então as duas não têm como
   discordar. O tracejado trocou `outline` por `underline`, que é o que
   `::highlight()` aceita. */
::highlight(destaque-previa) {
  background-color: color-mix(in srgb, var(--cor-ativa, var(--hl-amarelo)) 55%, transparent);
  text-decoration: underline dashed var(--acento);
  text-decoration-thickness: 1px;
  text-underline-offset: .16em;
}

/* ── os botões redondos: um desenho, dois lugares  (L-70) ──────────────────
   `.redondo` é a forma; quem diz o tamanho é o CONTEXTO, logo abaixo. Antes
   havia dois blocos quase idênticos (`.item .zerar` e `.item .excluir`) e, no
   rodapé do artigo, um `.btn` retangular fazendo o mesmo trabalho com outra
   cara — a divergência que a L-70 foi consertar. Uma classe é o que impede a
   terceira variante.

   Borda em --borda-controle (§2): `background: none` — o botão some no fundo
   do `.item` e no da folha —, então a borda é a única pista de que ali há um
   botão e não um enfeite. */
/* ── E o redondo virou CROMO  (04/09) ─────────────────────────────────────
   Ele era vazado: `background: none` e a borda como única pista de que ali há
   um botão. Passa a ser o mesmo material da lateral, da barra e da pilha — o
   gradiente grafite —, e com isso o app inteiro passa a dizer a mesma coisa
   com a mesma tinta: **página é papel, ferramenta é cromo**. Antes disso a
   regra valia só para o cromo de navegação, e um botão de ação vazado no meio
   de um cartão era a exceção que sobrava.

   O ganho não é só de coerência. Vazado, o `.redondo` dependia da borda para
   existir, e a borda é um fio de `--borda-controle` que num cartão claro
   sobre folha clara é a coisa mais fraca da tela. Cheio, ele se acha de
   relance — e o glifo, que era `--tinta-2` (um cinza de papel), passa a ser a
   tinta do cromo, medida sobre o campo em que de fato está. */
.redondo {
  flex: none; border-radius: 50%; box-sizing: border-box;
  display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid var(--cromo-borda);
  background: linear-gradient(180deg, var(--cromo-1), var(--cromo-2));
  color: var(--cromo-tinta);
  font-family: var(--sans); line-height: 1; cursor: pointer; padding: 0;
}
.redondo:hover, .redondo:focus-visible {
  color: var(--cromo-acento); border-color: var(--cromo-acento);
}
/* ── Ação DESENHADA dentro do botão redondo  (03/09) ───────────────────────
   As outras ações são glifo de texto e herdam o tamanho da fonte; a
   escrivaninha é um SVG (a mesma marca do destino, ver `ICONE_ESCRIVANINHA`),
   e SVG sem tamanho declarado assume 300×150 — o botão viraria uma bolha
   deformada. `block` tira a folga da linha de base, que num `inline` deixaria
   o desenho 3px fora do centro do círculo. */
.redondo svg { width: 58%; height: 58%; display: block; }
.redondo[disabled] { opacity: .5; cursor: default; }

/* ── reler do começo, na inbox (L-53g) ─────────────────────────────────────
   A ação mora aqui, e não no rodapé do artigo: num texto longo, reiniciar
   exigiria rolar até o fim para achar o botão — percorrer justamente o que se
   quer recomeçar. */
.linha-progresso { display: flex; align-items: center; gap: .6rem; }
.linha-progresso .progresso { flex: 1; }

/* 32px na linha da lista. `min-height` sobrepõe o --alvo:44px do núcleo de
   propósito: sem isto, min-height vence height e o círculo vira elipse de
   32×44. A exceção é legítima porque estes são alvos SECUNDÁRIOS dentro do
   `.item`, que já tem área de toque própria bem acima de 44px — não são
   controles isolados. O `.acoes` que os agrupa usa gap .4rem, e não os .6rem
   da linha: a 32px com .6rem entre todos, os quatro (↺ ✓ ⤓ ✕) empurravam o
   crédito para uma segunda linha no iPad em retrato. Os .6rem sobram para
   separar o ↺ — que é ação de progresso — do grupo de estado. */
.linha-progresso .redondo { width: 32px; height: 32px; min-height: 32px; font-size: .86rem; }
.linha-progresso .acoes { flex: none; }

/* 44px no rodapé do artigo: ali são controles ISOLADOS, não passageiros de um
   cartão tocável — merecem o alvo cheio que o núcleo manda dar. É a mesma
   forma da lista num tamanho diferente, que é exatamente o que "mesma
   identidade visual" quer dizer: a diferença é de contexto, não de desenho. */
.artigo > footer .acoes .redondo { width: 44px; height: 44px; font-size: 1.05rem; }

/* Aceso = o estado em que o artigo está. O segundo toque no aceso devolve à
   inbox — o `title` e o `aria-label` já dizem isso, e o fundo tingido é o que
   distingue "onde estou" de "para onde posso ir" sem precisar ler nada.

   O tingido não é a única pista (a cor da tinta e a da borda mudam junto), o
   que o dispensa de piso de contraste próprio — mesma razão registrada em
   `--perigo` para o fundo de `.armado`. */
/* Aceso, sobre o campo grafite: a tinta e a borda vão para o acento do cromo e
   o leito ganha uma lavagem dele. O `color-mix` é sobre o gradiente, então o
   campo continua sendo o mesmo material — só tingido. */
.acao-estado[aria-pressed="true"] {
  color: var(--cromo-acento); border-color: var(--cromo-acento);
  background: linear-gradient(180deg,
    color-mix(in srgb, var(--cromo-acento) 20%, var(--cromo-1)),
    color-mix(in srgb, var(--cromo-acento) 20%, var(--cromo-2)));
}

/* O painel de diagnóstico não pode cobrir o que se está diagnosticando —
   foi o que aconteceu: ele tapou justamente o botão em teste. */
body:has(#diag) main { padding-bottom: 46vh; }

/* O ✕ é destrutivo, então pede o segundo toque. Mas **não muda de largura** ao
   ser armado: um botão que cresce empurra o que está ao lado, e o segundo
   toque cairia noutro lugar. Quem explica é a linha de aviso abaixo. */
/* `--cromo-perigo`, e não `--perigo`: o vermelho do papel claro é `#b81028`,
   uma tinta escolhida para ser lida sobre folha branca — sobre o campo grafite
   ele é escuro sobre escuro. Mesmo movimento que `--cromo-acento` fez em
   02/09, e pela mesma razão: o cromo não muda por tema, então quem escreve
   sobre ele também não. */
.redondo.excluir:hover, .redondo.excluir:focus-visible {
  color: var(--cromo-perigo); border-color: var(--cromo-perigo);
}
.redondo.excluir.armado {
  color: var(--cromo-perigo); border-color: var(--cromo-perigo);
  background: linear-gradient(180deg,
    color-mix(in srgb, var(--cromo-perigo) 20%, var(--cromo-1)),
    color-mix(in srgb, var(--cromo-perigo) 20%, var(--cromo-2)));
}

/* O `<audio>` perdeu os `controls` em 07/09 e virou só o motor: quem aparece é
   `.transporte`, logo abaixo. A largura continua declarada porque o elemento
   sem `controls` tem caixa zero e `[hidden]` é o sinal que o JS lê — deixá-lo
   participar do fluxo com altura nenhuma evita um reflow ao revelar. */
.audio-leitura { width: 100%; height: 0; }
.audio-leitura[hidden] { display: none; }

/* ── O transporte do LIVRO  (07/09) ─────────────────────────────────────────

   Uma fileira só: passo, play, passo, relógio, barra, relógio. Os controles
   herdam o vocabulário do `.controles-voz` de propósito — os dois vivem
   colados no cabeçalho, e um `range` desenhado de outro jeito a dois
   centímetros do outro leria como dois apps.

   `display: none` no `[hidden]`, como em toda regra de autor com `display`
   aqui: `flex` vence o `[hidden]{display:none}` da folha do navegador, e sem
   esta linha o transporte apareceria antes de o leitor pedir a voz. */
.transporte { display: flex; align-items: center; flex-wrap: wrap; gap: .45rem; margin-top: .8rem; }
.transporte[hidden] { display: none; }

/* `min-width` e não `width`: o alvo mínimo é piso, e `−15`/`+15` são três
   caracteres que num quadrado de `--alvo` cru sairiam apertados. */
.transporte-botao {
  flex: none; min-width: var(--alvo); height: var(--alvo); padding: 0 .5rem;
  display: flex; align-items: center; justify-content: center;
  font-family: var(--sans); font-size: .82rem; line-height: 1;
  color: var(--tinta); background: var(--papel-elev);
  border: 1px solid var(--borda-controle); border-radius: var(--raio-p);
  cursor: pointer;
}
.transporte-botao:hover, .transporte-botao:focus-visible { border-color: var(--acento); color: var(--acento); }
.transporte-play { font-size: 1rem; }
.transporte-airplay { color: var(--tinta-2); }

/* `tabular-nums` e largura mínima: sem elas a barra encolhe e cresce a cada
   segundo, e o dedo que ia pegar o polegar erra o alvo que acabou de andar.
   `5.4ch` cabe `11:34:27`, que é o maior relógio do acervo. */
.transporte-relogio {
  flex: none; min-width: 5.4ch; text-align: center;
  font-family: var(--sans); font-size: .76rem; font-variant-numeric: tabular-nums;
  color: var(--tinta-2);
}

/* A parte só aparece quando não há régua — e aí ela é a única verdade que o
   transporte tem para dar. */
.transporte-parte {
  flex: none; font-family: var(--sans); font-size: .68rem;
  letter-spacing: .04em; color: var(--tenue);
}
.transporte-parte[hidden] { display: none; }

/* A barra. Mesmo desenho do deslizante de velocidade — inclusive o
   `box-sizing` explícito no polegar, que o reset universal não alcança porque
   `::-webkit-slider-thumb` é pseudo-elemento do navegador.

   O que ela tem a mais é o PREENCHIMENTO à esquerda do polegar: numa barra de
   progresso é por ele que se lê «onde estou» de relance, e o trilho de cor
   única obrigaria a procurar o polegar. `--pct` é escrito pelo JS a cada
   pintura; o `0%` de partida existe para a barra nascer vazia e não herdar
   o valor da última que passou por aqui. */
.transporte-barra {
  --pct: 0%;
  flex: 1 1 12rem; min-width: 0; height: var(--alvo);
  -webkit-appearance: none; appearance: none;
  background: none; margin: 0; cursor: pointer;
}
.transporte-barra::-webkit-slider-runnable-track {
  height: 4px; border-radius: 2px;
  background: linear-gradient(to right, var(--acento) var(--pct), var(--borda-controle) var(--pct));
}
.transporte-barra::-moz-range-track {
  height: 4px; border-radius: 2px;
  background: linear-gradient(to right, var(--acento) var(--pct), var(--borda-controle) var(--pct));
}
.transporte-barra::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none; box-sizing: border-box;
  width: 26px; height: 26px; border-radius: 50%;
  background: var(--acento); border: 2px solid var(--papel-elev);
  margin-top: -11px;
}
.transporte-barra::-moz-range-thumb {
  box-sizing: border-box;
  width: 26px; height: 26px; border-radius: 50%;
  background: var(--acento); border: 2px solid var(--papel-elev);
}
.transporte-barra:focus-visible { outline: 2px solid var(--foco); outline-offset: 2px; }

/* ── Os controles do player: velocidade e granularidade  (L-120) ────────────

   Nasceram sem uma linha de CSS. Funcionavam — `step="0.1"` sempre deu 0,8× —
   mas o deslizante era o nativo cru, ~130px de trilho para a faixa de 0,5 a
   2,0. São ~9px por parada para um dedo de ~40px de contato: o valor existia e
   não se conseguia apontar para ele. O que este bloco conserta é MIRA, não
   alcance.

   `display: none` no `[hidden]` é obrigatório, não zelo: `display: flex` numa
   regra de autor vence o `[hidden]{display:none}` da folha do navegador, e sem
   esta linha os controles apareceriam ANTES de o leitor pedir a voz — que é a
   coisa exata que o comentário do markup diz não querer. Mesma armadilha que
   `.audio-leitura[hidden]` acima já resolvia. */
/* ── Duas filas, e a divisão é por NATUREZA do ato  (12/09) ─────────────────

   Antes era uma fila só em `flex-wrap`, com a ordem de chegada: velocidade,
   destaque, voz. Abaixo de ~380px ela quebrava em três alturas desiguais e o
   seletor de voz — o único controle que decide QUEM fala, e do qual pende um
   gasto de verdade — descia para o fim, atrás dos dois que só ajustam COMO se
   fala.

   `grid` com duas filas separa a AÇÃO (qual motor; gerar o do estúdio) do
   AJUSTE (velocidade; destaque). Cada fila quebra dentro de si, e nenhuma
   consegue se embaralhar com a outra por falta de largura. */
.controles-voz { display: grid; gap: .85rem; margin-top: .9rem; }
.controles-voz[hidden] { display: none; }
.controles-voz .fila-voz { display: flex; flex-wrap: wrap; align-items: flex-end; gap: .9rem 1.4rem; }
/* A mesma armadilha do `[hidden]` que a barra inteira já resolvia, agora uma
   camada abaixo: `display: flex` numa regra de autor vence o `[hidden]` da
   folha do navegador, e a fila do ajuste vazaria para antes da escuta. */
.controles-voz .fila-voz[hidden] { display: none; }
/* ── A fila da ação: dois controles que sentam na MESMA linha  (12/09) ──────

   `align-items: center` centrava os dois BLOCOS, e os blocos não são iguais: o
   do motor carrega a sobrancelha «Voz» por cima do segmentado, o de gerar é um
   botão pelado. Centrar um bloco alto contra um baixo põe o botão acima do
   segmentado — o desalinho de 6px que se vê antes de se saber explicar.

   `flex-end` casa as bases, e a conta abaixo iguala as alturas: a pílula mede o
   alvo de toque por dentro, e o quadro do segmentado a envolve com a folga dos
   dois lados mais as duas bordas. O botão de gerar usa a MESMA conta — não um
   `50px` copiado, que envelheceria calado no dia em que `--alvo` mudasse. */
.controles-voz .fila-voz.acao { --folga-seg: 2px; align-items: flex-end; }

/* A velocidade toma a linha e a granularidade cabe ao lado quando há espaço;
   `16rem` é a base a partir da qual o deslizante ainda tem trilho útil — abaixo
   disso a fileira quebra em vez de espremer. */
.controles-voz .velocidade { flex: 1 1 16rem; min-width: 0; }

/* Mesma sobrancelha do painel de ajustes e da lista: o rótulo em cima, não ao
   lado, porque ao lado ele come a largura que o trilho precisa ter. */
.controles-voz .rotulo {
  display: block; font-family: var(--sans); font-size: .62rem; font-weight: 600;
  letter-spacing: .09em; text-transform: uppercase; color: var(--tenue);
  margin: 0 0 .4rem .1rem;
}
.controles-voz .estepe { display: flex; align-items: center; gap: .5rem; }

/* Os dois botões de passo. Quadrado de `--alvo` cheio: o ponto deste controle
   é ser acertável, e um botão de passo menor que o alvo mínimo devolveria o
   problema que ele veio resolver. `line-height: 1` porque o `−` e o `+` são
   glifos altos e o padding sozinho os desalinharia do centro. */
.controles-voz .passo-voz {
  flex: none; width: var(--alvo); height: var(--alvo);
  display: flex; align-items: center; justify-content: center;
  font-family: var(--sans); font-size: 1.05rem; line-height: 1;
  color: var(--tinta); background: var(--papel-elev);
  border: 1px solid var(--borda-controle); border-radius: var(--raio-p);
  cursor: pointer;
}
.controles-voz .passo-voz:hover:not([disabled]),
.controles-voz .passo-voz:focus-visible { border-color: var(--acento); color: var(--acento); }
/* No extremo da faixa. `.5` e não `.4`: é a mesma opacidade de `.btn[disabled]`,
   e os dois controles convivem na mesma tela. */
.controles-voz .passo-voz[disabled] { opacity: .5; cursor: default; }

/* O valor. `tabular-nums` para a fileira não dançar quando 1,0× vira 0,9×, e
   largura mínima pelo mesmo motivo — sem ela o `+` anda para o lado a cada
   passo, e o dedo que ia clicar de novo erra o botão que acabou de mover. */
.controles-voz .valor {
  flex: none; min-width: 3.2ch; text-align: right;
  font-family: var(--sans); font-size: .85rem; font-variant-numeric: tabular-nums;
  color: var(--tinta);
}

/* O deslizante. `appearance: none` obriga a desenhar trilho e polegar à mão nos
   dois motores — e a altura de `--alvo` não é a espessura do trilho (4px), é a
   ÁREA DE TOQUE: o trilho fino fica no meio de uma faixa alta o bastante para
   o dedo. */
.controles-voz input[type="range"] {
  flex: 1 1 auto; min-width: 0; height: var(--alvo);
  -webkit-appearance: none; appearance: none;
  background: none; margin: 0; cursor: pointer;
}
.controles-voz input[type="range"]::-webkit-slider-runnable-track {
  height: 4px; border-radius: 2px; background: var(--borda-controle);
}
.controles-voz input[type="range"]::-moz-range-track {
  height: 4px; border-radius: 2px; background: var(--borda-controle);
}
/* O WebKit não centra polegar em trilho por conta própria: a margem negativa
   tem de ser escrita, e ela é (altura do trilho − caixa do polegar) / 2 —
   (4 − 26) / 2 = −11px.

   `box-sizing` explícito, e não herdado do reset: o `*,*::before,*::after` do
   núcleo NÃO alcança `::-webkit-slider-thumb`, que é pseudo-elemento do
   navegador e não casa com o universal. Sem esta linha a caixa seria 26 + 2×2
   = 30px em vez de 26px, a margem certa passaria a ser −13px, e o polegar
   ficaria 2px fora do eixo do trilho — desalinho pequeno demais para se ver
   no Mac e visível no iPad, que é onde este controle é usado. Declarar a
   regra torna a conta decidível em vez de dependente do motor.

   O anel em `--papel-elev` é o que separa o polegar do trilho quando os dois
   passam por cima da mesma cor. */
.controles-voz input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none; box-sizing: border-box;
  width: 26px; height: 26px; border-radius: 50%;
  background: var(--acento); border: 2px solid var(--papel-elev);
  margin-top: -11px;
}
.controles-voz input[type="range"]::-moz-range-thumb {
  box-sizing: border-box;
  width: 26px; height: 26px; border-radius: 50%;
  background: var(--acento); border: 2px solid var(--papel-elev);
}
.controles-voz input[type="range"]:focus-visible { outline: 2px solid var(--foco); outline-offset: 2px; }

/* A granularidade: rótulo em cima como o da velocidade, e o `<select>` com a
   mesma altura de alvo dos botões de passo — os dois controles são uma fileira
   só aos olhos, e alturas diferentes a fariam parecer duas. */
.controles-voz .granularidade,
.controles-voz .timbre { flex: 0 1 auto; display: block; min-width: 0; }
.controles-voz .granularidade > span,
.controles-voz .timbre > span {
  display: block; font-family: var(--sans); font-size: .62rem; font-weight: 600;
  letter-spacing: .09em; text-transform: uppercase; color: var(--tenue);
  margin: 0 0 .4rem .1rem;
}
/* `height`, e não só `min-height`: o `<select>` nativo ignora o mínimo e desenha
   na altura da própria fonte, e a fileira do ajuste ficava com dois controles de
   alturas diferentes — as duas sobrancelhas (VELOCIDADE e DESTAQUE) pousavam em
   linhas distintas, que é o desalinho que se vê antes de se saber explicar. */
.controles-voz .granularidade select,
.controles-voz .timbre select {
  height: var(--alvo); font-family: var(--sans); font-size: .82rem;
  color: var(--tinta); background: var(--papel-elev);
  border: 1px solid var(--borda-controle); border-radius: var(--raio-p);
  padding: 0 .6rem; cursor: pointer;
}
.controles-voz .granularidade[hidden],
.controles-voz .timbre[hidden] { display: none; }
/* O seletor de voz carrega nomes longos («Automática · Karen (Premium) ·
   Austrália»): sem teto, empurraria a oficina do estúdio para fora da fila no
   iPhone. Encolhe até o teto e corta com reticências — o menu aberto mostra o
   nome inteiro. */
.controles-voz .timbre select { max-width: min(22rem, 100%); text-overflow: ellipsis; }
/* Na fila da AÇÃO ele pousa ao lado do segmentado do motor, que tem o alvo
   MAIS a folga das pílulas e a borda do campo (2 + 2 + 1 + 1). Com a altura do
   alvo só, as duas sobrancelhas (VOZ e QUEM LÊ) ficavam 6px desencontradas —
   o mesmo desalinho que a granularidade já tinha resolvido na fila de baixo. */
.controles-voz .acao .timbre select { height: calc(var(--alvo) + 2 * var(--folga-seg, 2px) + 2px); }

/* ── O motor da voz: segmentado, não `<select>`  (12/09) ────────────────────

   Com DOIS valores, o menu suspenso esconde metade do controle: a alternativa
   só existe depois de um toque que não escolhe nada. O segmentado mostra as
   duas o tempo todo, a vigente acesa, e a troca custa o toque que antes só
   servia para abrir o menu.

   A caixa externa é o campo; as pílulas vivem DENTRO dela, com 2px de folga —
   é essa folga que faz a acesa parecer encaixada em vez de colada. O raio de
   dentro é o de fora menos a folga, senão o canto da pílula acesa corta o
   canto do campo. */
.controles-voz .motor-voz { flex: 0 0 auto; }
.controles-voz .motor-voz .segmentado {
  display: inline-flex; padding: var(--folga-seg, 2px); gap: 2px;
  background: var(--papel-elev);
  border: 1px solid var(--borda-controle);
  border-radius: var(--raio-p);
}
.controles-voz .motor-voz .opcao {
  min-height: var(--alvo); padding: 0 .9rem;
  font-family: var(--sans); font-size: .82rem; line-height: 1;
  color: var(--tinta-2); background: none; border: 0;
  border-radius: calc(var(--raio-p) - 2px);
  cursor: pointer; white-space: nowrap;
}
/* Acento cheio com `--sobre-acento`, nunca `#fff`: no tema escuro o acento é
   claro, e um branco cravado ali cairia para ~2:1 sobre ele. */
.controles-voz .motor-voz .opcao[aria-checked="true"] {
  background: var(--acento); color: var(--sobre-acento);
}
/* Apagada, não ausente: a opção indisponível ainda ensina que a segunda voz
   existe — é a oficina, logo ao lado, que a destrava. */
/* `.5`, o mesmo dos botões de passo apagados: é o número que esta barra já usa
   para «existe e não dá para acionar», e dois números para o mesmo estado são
   duas linguagens na mesma fileira. */
.controles-voz .motor-voz .opcao[data-indisponivel="sim"] { opacity: .5; }
.controles-voz .motor-voz .opcao:focus-visible { outline: 2px solid var(--foco); outline-offset: 2px; }

/* ── O botão que custa, e a conta antes dele ────────────────────────────────

   O botão é secundário de propósito (borda, não acento cheio): o primário
   desta tela é ouvir, e ouvir já é de graça. Quem gasta é este, e ele não
   convida — ele espera.

   A altura é a EXTERNA do segmentado ao lado, derivada dele: alvo de toque por
   dentro, mais a folga dos dois lados, mais as duas bordas. */
.controles-voz .gerar-estudio {
  min-height: calc(var(--alvo) + 2 * var(--folga-seg, 2px) + 2px); padding: 0 .9rem;
  font-family: var(--sans); font-size: .82rem;
  color: var(--tinta); background: none;
  border: 1px solid var(--borda-controle); border-radius: var(--raio-p);
  cursor: pointer;
}
.controles-voz .gerar-estudio:hover,
.controles-voz .gerar-estudio:focus-visible { border-color: var(--acento); color: var(--acento); }
.controles-voz .gerar-estudio[hidden] { display: none; }

/* ── A narração de uma régua anterior  (spec 58 §4) ─────────────────────────

   Aviso, não alarme: o que está tocando é legítimo e foi pago; só não é da
   régua de hoje. Por isso a tinta fraca da nota de rodapé, e não a do erro —
   quem sobe a régua quer saber, quem só quer ouvir não precisa ser
   interrompido. `Regravar` é link de texto pela mesma razão: ele custa uma
   síntese inteira, e um botão sólido convidaria a gastar. */
.controles-voz .regua-anterior {
  margin: .45rem 0 0; font-family: var(--sans); font-size: .78rem;
  color: var(--tinta-2); line-height: 1.5;
}
.controles-voz .regua-anterior[hidden] { display: none; }
.controles-voz .regua-anterior .btn.discreto {
  min-height: var(--alvo); padding: 0 .35rem;
  font: inherit; color: var(--acento); background: none; border: 0;
  text-decoration: underline; text-underline-offset: 2px; cursor: pointer;
}
.controles-voz .regua-anterior .btn.discreto:focus-visible {
  outline: 2px solid var(--foco); outline-offset: 2px;
}

/* A conta do gasto saiu daqui na spec 53 (16/09): a caixa embutida
   (`.confirma-estudio`, com a conta em caracteres) virou a folha do
   `confirmarComCusto` — `.custo-fundo`, mais abaixo neste arquivo —, e a
   pele dela ficou órfã até 17/09. Regra que não casa com elemento nenhum não
   avisa: ela só engorda a folha e finge que o mecanismo ainda existe. */

.aviso-excluir {
  font-family: var(--sans); font-size: .76rem; color: var(--perigo);
  margin: .5rem 0 0; padding-left: .1rem;
}
/* A falha de rede ao mudar de estado fala no mesmo lugar e no mesmo tom que a
   confirmação do ✕ — é uma linha abaixo do item, não um alerta que rouba a
   tela. Em --tinta-2 e não em --perigo: nada se perdeu, só não foi feito. */
.aviso-estado {
  font-family: var(--sans); font-size: .76rem; color: var(--tinta-2);
  margin: .5rem 0 0; padding-left: .1rem;
}

/* ── O sinal da voz de estúdio  (spec 11 §6, revisto em 14/09) ─────────────
   Três barras de onda, e nenhum aro: o aro era a forma do BOTÃO da casa, e
   este sinal não é botão — da lista e da estante só se vê que a narração
   existe; gerá-la passa pela conta, dentro do artigo (spec 49 §4.2). A cor é
   `currentColor` para servir nas duas superfícies: acento sobre o papel da
   lista, a tinta da lombada sobre o campo escuro da estante. Gerando é o mesmo
   desenho, pulsando. Ver `montarSinalEstudio` em inbox.mjs. */
.sinal-estudio {
  display: inline-flex; align-items: center; gap: .4rem;
  color: var(--acento); cursor: default; line-height: 1;
}
.sinal-estudio svg { flex: none; fill: currentColor; }
.sinal-estudio.gerando { animation: sinal-pulso 1.4s ease-in-out infinite; }
@keyframes sinal-pulso { 0%, 100% { opacity: 1; } 50% { opacity: .35; } }
/* Sem animação, gerando seria idêntico a pronta — o tom apagado é o que resta
   de pista quando o movimento é vetado. */
@media (prefers-reduced-motion: reduce) {
  .sinal-estudio.gerando { animation: none; opacity: .55; }
}
.item .progresso.vazia { flex: 1; background: none; }

/* "Temas" antes dos chips: sem o rótulo, a fileira logo abaixo das abas parece
   um segundo filtro do mesmo recorte — e a contagem, que é do tema e não da
   aba, passa a parecer errada. */
.clusters .rotulo-temas {
  display: block; color: var(--tenue); font-size: .68rem; font-weight: 600;
  letter-spacing: .08em; text-transform: uppercase; margin: 0 0 .45rem .1rem;
}

/* ── administração (spec 19) ────────────────────────────────────────────────
   Formulário de operação, não tela de leitura: tudo em --sans, painéis na
   mesma gramática dos cartões da inbox (borda --borda-controle, fundo
   --papel-elev) e controles nativos — select e input herdam o tema em vez de
   fingir outro sistema. O link do rodapé vive na regra do #versao. */
#versao a { color: inherit; text-decoration: none; }
#versao a:hover, #versao a:focus-visible { color: var(--acento); }

#admin { font-family: var(--sans); }
#admin > .sub { margin: -.2rem 0 1.1rem; color: var(--tinta-2); font-size: .88rem; }
#admin .painel {
  background: var(--papel-elev); border: 1px solid var(--borda-controle);
  border-radius: 10px; padding: 1rem 1.1rem; margin: 0 0 1.1rem;
}
#admin .painel h2 { font-size: .95rem; font-weight: 600; margin: 0 0 .6rem; }
#admin .painel .sub { margin: -.3rem 0 .9rem; line-height: 1.5; font-size: .82rem;
  color: var(--tinta-2); }
#admin .estado { margin: 0; display: grid; gap: .8rem 1.4rem;
  grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr)); }
#admin .estado dt { font-size: .72rem; color: var(--tenue); letter-spacing: .04em;
  text-transform: uppercase; }
#admin .estado dd { margin: .1rem 0 0; font-size: .88rem;
  font-variant-numeric: tabular-nums; }
#admin .estado dd.mini { font-size: .72rem; color: var(--tenue); }

/* ── A gramática única (14/09) ──────────────────────────────────────────────
   Um bloco por papel de IA — título, o que governa, e as caixas lado a lado —
   e toda caixa da página com a mesma forma: rótulo, marca «alterado» quando o
   valor salvo não é o padrão, a caixa, e a nota que explica por que ela está
   desligada. O `fieldset` é o agrupamento que o leitor de tela anuncia; a
   `legend` flutua porque é o único jeito de ela ocupar a largura sem o
   desenho de moldura que o navegador lhe dá. */
#admin .papel { border: 0; border-top: 1px solid var(--borda-controle);
  margin: 0; padding: .95rem 0 .15rem; min-width: 0; }
#admin .papel:first-of-type { border-top: 0; padding-top: .1rem; }
#admin .papel legend { float: left; width: 100%; padding: 0; margin: 0 0 .15rem;
  font-size: .9rem; font-weight: 600; }
#admin .papel .governa { clear: both; margin: 0 0 .65rem; font-size: .8rem;
  line-height: 1.45; color: var(--tinta-2); }
#admin .grade-campos { display: grid; column-gap: 1rem;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 15rem), 1fr)); }
/* No bloco de papel o MODELO é a caixa larga: o rótulo dele carrega id,
   provedor, preço e «(padrão)», e em meia coluna saía cortado no meio do
   preço («US$ 5/25 (pad…»). O esforço e o liga/desliga cabem em pouco. */
@media (min-width: 700px) {
  #admin .papel .grade-campos { grid-template-columns: minmax(0, 2fr) minmax(0, 1fr); }
  #admin .papel .grade-campos:has(#vozIa) { grid-template-columns: minmax(0, 1fr) minmax(0, 2.4fr) minmax(0, 1fr); }
}
#admin .campo { display: block; margin: 0 0 .8rem; min-width: 0; }
#admin .campo > label { display: flex; align-items: baseline; flex-wrap: wrap; gap: .45rem;
  font-size: .76rem; font-weight: 600; margin: 0 0 .3rem; }
#admin .alterado { font-size: .64rem; font-weight: 600; letter-spacing: .05em;
  text-transform: uppercase; color: var(--acento); border: 1px solid currentColor;
  border-radius: 999px; padding: 0 .4rem; line-height: 1.5; }
#admin .campo select, #admin .campo textarea {
  width: 100%; box-sizing: border-box; font: inherit; font-size: .88rem;
  color: var(--tinta); background: var(--papel); border: 1px solid var(--borda-controle);
  border-radius: 7px; padding: .5rem .6rem; min-height: 44px;
}
/* O Safari desenha o `<select>` nativo com a altura dele e IGNORA `min-height`
   e `padding` — medido: 22px, metade do alvo de toque. `appearance: none`
   devolve a caixa ao CSS, e a seta passa a ser desenhada aqui, com dois
   gradientes na tinta tênue do tema (um SVG em `url()` não herdaria a cor). */
#admin .campo select {
  -webkit-appearance: none; appearance: none; padding-right: 2.1rem;
  background-image: linear-gradient(45deg, transparent 50%, var(--tenue) 50%),
    linear-gradient(135deg, var(--tenue) 50%, transparent 50%);
  background-position: calc(100% - 1.05rem) 50%, calc(100% - .75rem) 50%;
  background-size: .3rem .3rem; background-repeat: no-repeat;
  text-overflow: ellipsis;
}
#admin .campo select:focus-visible, #admin .campo textarea:focus-visible {
  outline: none; border-color: var(--acento);
}
#admin .campo select:disabled { opacity: .5; cursor: not-allowed; }
/* O campo com escolha ainda não salva: um fio de acento na borda esquerda, o
   mesmo sinal que a barra de salvar lista por extenso. */
#admin .campo[data-pendente] select, #admin .campo[data-pendente] textarea {
  border-color: var(--acento); box-shadow: inset 3px 0 0 var(--acento);
}
#admin .campo .nota { display: block; font-size: .72rem; line-height: 1.4;
  color: var(--tenue); margin-top: .3rem; }
#admin .campo .erro-campo { display: block; font-size: .76rem; font-weight: 600;
  line-height: 1.4; color: var(--acento); margin-top: .35rem; }
/* Os hosts da bancada (spec 42 §3.5): um por linha, em mono — é lista, não
   prosa, e `resize: vertical` porque a largura é a do painel. */
#admin .campo textarea { font-family: var(--mono); line-height: 1.5;
  resize: vertical; }
#admin .painel h3 { font-size: .82rem; font-weight: 600; margin: 1rem 0 .4rem; }
#admin .fontes-admin { list-style: none; margin: 0; padding: 0; font-size: .85rem; }
#admin .fontes-admin li { padding: .5rem 0; border-top: 1px solid var(--borda-controle);
  line-height: 1.5; }
#admin .fontes-admin small { color: var(--tenue); font-size: .75rem; }
#admin .fontes-admin small.motivo { color: var(--tinta-2); }
#admin .fontes-admin code { font-size: .8rem; }
#admin .fontes-admin [data-estado="pendente"] .estado-fonte { color: var(--acento); font-weight: 600; }
#admin .fontes-admin [data-estado="recusada"] .estado-fonte,
#admin .fontes-admin [data-estado="falhou"] .estado-fonte { color: var(--tinta-2); }
/* As sessões da bancada (spec 43 §5). Mesma forma da lista das fontes — é a
   mesma pergunta, «o que o servidor tem sobre isto» — com duas diferenças:
   esta lista TEM botão, e o total do mês vem antes dela, porque é o número que
   se veio conferir antes de escolher o teto logo acima. */
#admin .total-sessoes { margin: 0 0 .3rem; font-size: .8rem; color: var(--tinta-2); }
#admin .sessoes-admin { list-style: none; margin: 0; padding: 0; font-size: .85rem; }
#admin .sessoes-admin li { padding: .5rem 0; border-top: 1px solid var(--borda-controle);
  line-height: 1.5; }
#admin .sessoes-admin small { color: var(--tenue); font-size: .75rem; }
#admin .sessoes-admin [data-viva] b { color: var(--acento); }
#admin .linha-sessao { display: flex; align-items: flex-start; justify-content: space-between;
  gap: .8rem; }
#admin .btn.encerrar { flex: none; font-size: .78rem; padding: .35rem .8rem; }
#admin #sessoes-status { display: block; font-size: .8rem; color: var(--tinta-2);
  margin-top: .5rem; }
#admin #sessoes-status:empty { display: none; }
/* O custo da memória por obra (17/09). Não tinha regra nenhuma: `ul` e `b`
   herdavam o corpo da leitura, e sete livros viravam uma página de prosa em
   negrito. Mesma forma das sessões — total antes, título e dólar numa linha. */
#admin .total-custos { margin: 1rem 0 .3rem; font-size: .8rem; color: var(--tinta-2); }
#admin .custos-memoria { list-style: none; margin: 0; padding: 0; font-size: .85rem; }
#admin .custos-memoria li { padding: .5rem 0; border-top: 1px solid var(--borda-controle);
  line-height: 1.5; }
#admin .custos-memoria b { font-weight: 600; }
#admin .custos-memoria small { display: block; color: var(--tenue); font-size: .75rem; }
#admin .linha-custo { display: flex; align-items: baseline; justify-content: space-between;
  gap: .8rem; }
#admin .linha-custo .usd { flex: none; font-variant-numeric: tabular-nums; color: var(--tinta-2); }

/* ── A barra de salvar ──────────────────────────────────────────────────────
   Presa ao pé da janela enquanto se rola, porque o que ela diz — quantas
   escolhas estão por salvar, e quais — é a pergunta de antes de sair da
   página. `--barra-h` é a altura da navegação inferior no iPad e no telefone
   (zero no modo lateral): sem ela a barra pousaria debaixo dos ícones. */
#admin .barra-salvar {
  position: sticky; bottom: calc(var(--barra-h, 0px) + .6rem); z-index: 5;
  display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: .4rem 1rem; align-items: center;
  background: var(--papel-elev); border: 1px solid var(--borda-controle); border-radius: 10px;
  padding: .7rem .9rem; margin: 1.2rem 0 0; box-shadow: 0 4px 18px rgb(0 0 0 / .14);
}
#admin .barra-salvar:has(#pendencias li) { border-color: var(--acento); }
#admin #pendencias p { margin: 0; font-size: .82rem; }
#admin #pendencias .nada { color: var(--tenue); }
#admin #pendencias .conta { font-weight: 600; }
#admin #pendencias ul { margin: .25rem 0 0; padding-left: 1rem; font-size: .78rem;
  line-height: 1.45; color: var(--tinta-2); max-height: 7.5rem; overflow: auto;
  overflow-wrap: anywhere; }
#admin .barra-salvar .botoes { display: flex; gap: .5rem; }
#admin .barra-salvar .btn { min-height: 44px; padding: .5rem 1.1rem; font-size: .88rem; }
#admin #admin-status { grid-column: 1 / -1; font-size: .8rem; color: var(--tinta-2); }
#admin #admin-status:empty { display: none; }
@media (max-width: 560px) {
  #admin .barra-salvar { grid-template-columns: 1fr; }
  #admin .barra-salvar .botoes { justify-content: flex-end; }
}

/* ── O /admin das contas e dos preços  (plano 2026-09-22 item 9) ───────────
   Duas subrotas do /admin, e por isso a mesma folha: `--sans`, os mesmos
   painéis, a mesma barra. O que muda é a unidade — ali é um campo, aqui é uma
   CONTA, e o cartão existe para que um gesto perigoso (ligar o lume de alguém)
   esteja visivelmente dentro dos limites de uma pessoa, e não solto numa
   lista onde a linha de cima e a de baixo se parecem.

   Os blocos são `<details>` fechados de propósito: o que se faz todo dia é
   OLHAR (quem está ligado, quanto gastou), e creditar cortesia ou zerar um
   lote de ensaio são gestos de vez em quando. Abertos, eles fariam a página
   ter três vezes a altura para a pergunta que ninguém faz. */
#admin-contas, #admin-tabela { font-family: var(--sans); }
#admin-contas h1, #admin-tabela h1 { font-size: 1.25rem; margin: 0 0 .3rem; }
#admin-contas h2, #admin-tabela h2 { font-size: .95rem; font-weight: 600; margin: 1.4rem 0 .6rem; }
.admin-abas { margin: 0 0 1.1rem; font-size: .82rem; color: var(--tinta-2); }
.admin-nota { margin: 0 0 .9rem; font-size: .82rem; line-height: 1.5; color: var(--tinta-2); }
.admin-status { margin: .3rem 0 .6rem; font-size: .8rem; color: var(--tinta-2); min-height: 1.1em; }
.admin-status:empty { display: none; }

.contas { display: grid; gap: .9rem; }
#admin-contas .conta {
  border: 1px solid var(--borda-controle); border-radius: 10px;
  padding: .9rem 1rem; background: var(--fundo-painel, transparent);
}
#admin-contas .conta-cabeca { display: flex; align-items: baseline; gap: .6rem; }
#admin-contas .conta-cabeca h3 { margin: 0; font-size: 1rem; }
#admin-contas .conta-sub { margin: 0; font-size: .72rem; color: var(--tenue); letter-spacing: .04em; }
#admin-contas .conta-faixa { margin: .35rem 0 .1rem; font-size: .85rem; }
#admin-contas .conta-medidor { margin: 0 0 .1rem; font-size: .85rem; color: var(--tinta-2); }
#admin-contas .conta-pausas { margin: .2rem 0 0; font-size: .8rem; color: var(--acento); }
#admin-contas .conta-status { margin: .3rem 0 0; font-size: .8rem; color: var(--tinta-2); }
#admin-contas .conta-status:empty { display: none; }
#admin-contas .conta-acoes {
  display: flex; flex-wrap: wrap; align-items: center; gap: .6rem; margin: .7rem 0 .2rem;
}
/* O link herda a SERIFA do corpo e nasce com o corpo de leitura: ao lado de um
   botão de 44px ele saía maior que o botão, e o olho lia o link como o gesto
   principal — que é o contrário do que a tela quer. */
#admin-contas .conta-dias { font-family: var(--sans); font-size: .85rem; }
/* O alvo de 44px também aqui: é a mesma mão, e um «desligar o lume» tocado
   por engano custa mais que um botão grande. */
#admin-contas .conta-acoes button, #admin-contas .conta-bloco button { min-height: 44px; padding: .45rem 1rem; }
#admin-contas .conta-bloco { margin-top: .5rem; border-top: 1px solid var(--borda-controle); padding-top: .5rem; }
#admin-contas .conta-bloco summary { font-size: .82rem; cursor: pointer; min-height: 32px; }
#admin-contas .conta-bloco label { display: block; margin: .6rem 0 .2rem; font-size: .75rem; color: var(--tenue); }
#admin-contas .conta-bloco select, #admin-contas .conta-bloco input { min-height: 40px; }
#admin-contas .conta-rubrica { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem; margin: .5rem 0; font-size: .85rem; }
#admin-contas .conta-rubrica span { min-width: 6.5rem; }
#admin-contas .conta-nota { margin: .3rem 0; font-size: .78rem; color: var(--tenue); }

/* A tabela do `DIA#`: números à direita, e o total em destaque. Rola no
   telefone em vez de espremer as colunas — sete rubricas não cabem em 360px,
   e uma coluna espremida a 2 dígitos mente sobre o número. */
/* O total do período FORA da tabela, além do `tfoot`: em 520px a tabela rola
   dentro de si, e o número que o dono veio ver ficava fora da tela, à direita
   de sete colunas. */
#admin-contas .dia-soma { margin: 0 0 .9rem; font-size: .9rem; }
#admin-contas .dias { width: 100%; border-collapse: collapse; font-size: .82rem; display: block; overflow-x: auto; }
#admin-contas .dias th, #admin-contas .dias td { padding: .35rem .5rem; text-align: right; white-space: nowrap; }
#admin-contas .dias th[scope="row"] { text-align: left; font-weight: 400; }
#admin-contas .dias thead th { font-size: .72rem; color: var(--tenue); letter-spacing: .03em; }
#admin-contas .dias tbody tr { border-top: 1px solid var(--borda-controle); }
#admin-contas .dias .dia-total { font-variant-numeric: tabular-nums; font-weight: 600; }
#admin-contas .dias tfoot { border-top: 2px solid var(--borda-controle); }

/* Os rótulos soltos (o limiar, a vigência) herdam a SERIFA do corpo e nascem
   com o corpo de leitura: ao lado de um campo de 40px eles saíam do tamanho de
   um título. */
#admin-tabela label { font-family: var(--sans); font-size: .78rem; color: var(--tenue); display: block; margin: .6rem 0 .2rem; }
#admin-tabela .admin-acoes label { display: inline; margin: 0; }
#admin-tabela #limiarPadrao { min-height: 40px; max-width: 8rem; }
#admin-tabela .precos { display: grid; gap: .8rem; grid-template-columns: repeat(auto-fill, minmax(11rem, 1fr)); }
#admin-tabela .preco { border: 1px solid var(--borda-controle); border-radius: 8px; padding: .6rem .7rem; margin: 0; }
#admin-tabela .preco legend { padding: 0 .3rem; font-size: .78rem; color: var(--tenue); }
#admin-tabela .preco label { display: block; margin: .4rem 0 .15rem; font-size: .72rem; color: var(--tenue); }
#admin-tabela .preco input { width: 100%; min-height: 40px; }
#admin-tabela .planos { width: 100%; border-collapse: collapse; font-size: .85rem; }
#admin-tabela .planos th, #admin-tabela .planos td { padding: .35rem .5rem; text-align: right; }
#admin-tabela .planos th[scope="row"] { text-align: left; font-weight: 400; }
#admin-tabela .planos tbody tr { border-top: 1px solid var(--borda-controle); }
#admin-tabela .admin-json { margin: .9rem 0; }
#admin-tabela .admin-json summary { font-size: .8rem; cursor: pointer; min-height: 32px; }
#admin-tabela .admin-json textarea { width: 100%; font-family: var(--mono, monospace); font-size: .75rem; }
#admin-tabela .admin-acoes { display: flex; flex-wrap: wrap; align-items: center; gap: .6rem; margin-top: .8rem; }
#admin-tabela .admin-acoes button { min-height: 44px; padding: .5rem 1.1rem; }
#admin-tabela .admin-acoes label { font-size: .75rem; color: var(--tenue); }
#admin-tabela .admin-acoes input[type="date"] { min-height: 40px; }

/* ── A estante  (spec 21 §3.3) ─────────────────────────────────────────────
   A grade de capas. Duas regras aqui não são estética e sim defeito conhecido:
   a proporção fixa (sem ela a fileira desalinha e a grade deixa de parecer
   estante) e o título FORA da imagem — texto dentro de imagem gerada é onde a
   IA erra feio, e o nosso já está em Literata de graça.

   `auto-fill` em vez de contagem fixa de colunas porque o iPad girando é o
   caso comum: um `repeat(4, 1fr)` desperdiça meia tela em paisagem e aperta
   em retrato. */
.titulo-tela { font-family: var(--serif); font-size: 1.3rem; margin: 0 0 1rem; font-weight: 600; }

/* ── A estante VIVA: prateleiras à esquerda, capa à direita  (02/09) ───────
   A grade de capas em campo cheio saiu. Ela tinha um defeito que a rodada
   inteira existe para desfazer: a única superfície de cor forte do app era
   justamente a tela que devia ser a mais discreta — vinte e seis capas
   saturadas lado a lado.

   O que entra é a LOMBADA de pé numa prateleira, e a capa vira detalhe de
   foco: uma por tela, na coluna da direita. É a inversão que faz a estante
   parecer estante — numa de verdade se veem lombadas, e a capa só aparece
   quando se tira o livro.

   A coluna some abaixo de 900px: no iPhone ela comeria metade da tela para
   mostrar um livro de cada vez, e a prateleira inteira caberia em nada. */
.estante-viva { display: flex; align-items: flex-start; gap: 2rem; }
.estante-viva .prateleiras { flex: 1; min-width: 0; }

.prateleira { margin: 0 0 2rem; }
.prateleira h2 {
  font-family: var(--sans); font-size: 10.5px; font-weight: 600; letter-spacing: .12em;
  text-transform: uppercase; color: var(--tinta-2); margin: 0 0 .7rem;
  display: flex; align-items: center; gap: .5rem;
}
/* A pílula da contagem em aro fino: ela conta, não comanda — e o piso de 3:1
   é de borda que é a única pista de CONTROLE. */
.prateleira h2 .conta {
  font-size: 10.5px; color: var(--tenue); background: none;
  border: 1px solid var(--aro-fino); border-radius: 999px; padding: 2px 7px;
  font-variant-numeric: tabular-nums;
}

/* ── A prateleira ROLA  (prancha 1e, 2026-09-01) ───────────────────────────
   «A prateleira não é uma grade com título: a fileira rola na horizontal e o
   corte à direita é a pista de que há mais.»

   A grade de `auto-fill` que morava aqui resolvia bem o iPad girando, e é por
   isso que ela durou — mas ela mente sobre o objeto: uma grade que quebra em
   três linhas diz «este é o conjunto todo», e uma estante nunca mostra o
   conjunto todo. O corte é a informação.

   `scroll-snap` no eixo X para o dedo parar em capa inteira, e `overscroll-
   behavior-x: contain` para a rolagem da fileira não virar rolagem da página
   quando ela chega ao fim — no iPad, sem isso, arrastar a última capa arrasta
   a tela. A classe mudou de `.grade` para `.fileira`: o nome antigo descrevia
   a diagramação que saiu, e `#ajustes .grade` continua existindo. */
/* A fileira alinha as lombadas pela BASE — elas têm alturas diferentes, e o
   que as iguala numa estante é a tábua, não o topo.

   A altura da fileira é ~24px maior que a lombada mais alta, e isso não é
   folga solta: é o que o `translateY(-14px)` do hover consome. Sem ela o livro
   sobe por cima do rótulo da prateleira. */
/* A fileira alinha as lombadas pela BASE de cada LINHA — em flex com quebra o
   alinhamento cruzado é por linha, e é isso que põe cada livro sobre a sua
   tábua. `align-content: flex-start` impede as linhas de se espalharem na
   altura que sobrar.

   ── A tábua de cada linha é DESENHADA NO FUNDO, e por quê ─────────────────
   Um `<span class="tabua">` por linha é impossível: quem decide onde a linha
   quebra é o navegador, com a largura da tela e as larguras variáveis das
   lombadas — o HTML não sabe quantas linhas existem. Um `repeating-linear-
   gradient` sabe: as lombadas de uma prateleira têm todas a MESMA altura e o
   `row-gap` é fixo, então o passo é exato e o desenho acompanha qualquer
   número de linhas, em qualquer largura, sem uma linha de JavaScript.

   A folga do hover (`translateY(-14px)`) é MARGEM, e não padding: o fundo
   pinta a caixa de padding, e 16px de padding-top deslocariam o gradiente
   inteiro meio degrau para baixo — a tábua sairia atravessando os livros. */
.prateleira .fileira {
  list-style: none; margin: 16px 0 0;
  /* O padding de baixo é o que faz a tábua da ÚLTIMA linha existir: o fundo
     pinta a caixa de padding, e sem esses 31px a caixa termina exatamente onde
     a lombada termina — a faixa de madeira ficaria fora dela. Foi o que a
     captura mostrou na prateleira «Lendo agora», que tem uma linha só. */
  padding: 0 0 31px;
  display: flex; flex-wrap: wrap;
  align-items: flex-end; align-content: flex-start;
  column-gap: 5px;
  /* 31px = a tábua (9) mais o respiro até a linha de baixo (22). É o mesmo
     número que fecha o passo do gradiente. */
  row-gap: 31px;
  --lombada-h: 238px;
  --linha-h: calc(var(--lombada-h) + 31px);
  background-image: repeating-linear-gradient(to bottom,
    transparent 0 var(--lombada-h),
    /* o brilho de cima da madeira */
    rgba(255,255,255,.5) var(--lombada-h) calc(var(--lombada-h) + 1px),
    var(--tabua-1) calc(var(--lombada-h) + 1px),
    var(--tabua-2) calc(var(--lombada-h) + 9px),
    /* a sombra projetada, que o `box-shadow` de um elemento daria */
    rgba(34,33,29,.13) calc(var(--lombada-h) + 9px),
    transparent calc(var(--lombada-h) + 20px) var(--linha-h));
}
/* As prateleiras que não são «Lendo agora» têm a lombada 14px mais baixa: é o
   que faz a fileira em curso se ler primeiro sem precisar de cor nem de peso
   de fonte. O gradiente acompanha porque o passo dele sai deste mesmo token. */
.prateleira:not([data-chave="lendo"]) .fileira { --lombada-h: 224px; }
.prateleira .fileira > .obra { flex: 0 0 auto; width: auto; height: auto; }

/* ── A LOMBADA ────────────────────────────────────────────────────────────
   Largura variável (36–68px, `--largura`, escrita pelo `estante.mjs` a partir
   da extensão da obra) e altura fixa por prateleira. O gradiente de 90° é o
   volume: uma luz na quina esquerda, sombra crescendo até a direita — é o que
   separa «lombada» de «retângulo colorido».

   O canto de FORA é o arredondado (`2px 4px 4px 2px`), como num livro fechado:
   a lombada dobra para a direita, onde estão as folhas. */
/* ── Duas heranças da vista GRADE que precisam ser desfeitas aqui ──────────
   `.obra .alvo` declara `flex: 1` para empurrar as ações para a base do cartão
   da grade. Num contêiner flex em COLUNA o `flex-basis: 0%` que vem junto
   vence o `height` — e a lombada nascia com a altura do texto: 124px numa
   obra, 171 na vizinha, na mesma fileira. `flex: none` devolve a altura
   declarada.

   O `.titulo` da grade é `-webkit-box` com `line-clamp: 2`, e um `-webkit-box`
   ignora `writing-mode` no WebKit: o título saía deitado dentro da lombada de
   pé. Ver a regra do título, adiante. */
.obra.lombada .alvo {
  display: flex; flex: none; flex-direction: column; align-items: center;
  width: var(--largura, 44px); height: 238px;
  padding: 12px 4px 14px; box-sizing: border-box;
  border-radius: 2px 4px 4px 2px;
  background:
    linear-gradient(90deg, rgba(255,255,255,.15), rgba(255,255,255,0) 15%,
                    rgba(0,0,0,.12) 74%, rgba(0,0,0,.3)),
    var(--lombada, var(--tenue));
  box-shadow: var(--sombra-lombada);
  color: var(--sobre-lombada);
  overflow: hidden; cursor: pointer;
  transition: transform var(--dur) var(--curva);
}
.prateleira:not([data-chave="lendo"]) .obra.lombada .alvo { height: 224px; }
/* Sobe ao passar E ao receber foco: hover é atalho, foco é interface. Um
   realce que só existe com o cursor em cima não existe para quem usa
   teclado. */
.obra.lombada .alvo:hover, .obra.lombada .alvo:focus-visible {
  transform: translateY(-14px);
}
@media (prefers-reduced-motion: reduce) {
  .obra.lombada .alvo { transition: none; }
}
/* O filete do topo: a linha de capa que quase toda coleção tem. Acompanha a
   largura da lombada em vez de ser fixo, senão numa de 68px ele vira um
   traço perdido no meio. */
.obra.lombada .filete {
  display: block; flex: none; height: 1px; width: 60%;
  background: rgba(255,255,255,.42); margin-bottom: 12px;
}
/* `vertical-rl` sem `rotate(180deg)`: o título lê de cima para baixo, que é a
   convenção das lombadas em português. O corte é por `overflow`, e o texto
   continua INTEIRO no DOM — é o que o leitor de tela ouve e o que a busca do
   navegador acha. */
/* ── O título da lombada é UMA linha, e corta com reticências  (02/09) ─────
   `overflow: hidden` sozinho não bastava: em `writing-mode: vertical-rl` o
   texto que não cabe **quebra em outra coluna**, e a coluna nova cresce para o
   lado — para dentro da lombada, por cima do que já estava escrito. «Carmilla
   (Clássicos da literatura mundial)» virava duas colunas sobrepostas numa
   lombada de 40px (relato do Yuri, com o app aberto).

   `white-space: nowrap` mantém tudo numa coluna só e devolve o corte ao eixo
   que a lombada controla — a altura —, e aí `text-overflow: ellipsis` diz onde
   ele acabou. O texto continua INTEIRO no DOM: é o que o leitor de tela ouve,
   o que a busca do navegador acha, e o que a coluna da capa mostra por
   extenso quando o livro recebe o foco. */
.obra.lombada .titulo {
  /* `block`, desfazendo o `-webkit-box` da vista grade: o box do WebKit ignora
     `writing-mode`, e o título ficava deitado numa lombada de pé. */
  display: block; -webkit-line-clamp: none; min-height: 0;
  writing-mode: vertical-rl; text-orientation: mixed;
  font-family: var(--serif); font-weight: 600; font-size: 13px; line-height: 1.15;
  max-height: 170px; overflow: hidden; text-align: left;
  white-space: nowrap; text-overflow: ellipsis;
}
.prateleira:not([data-chave="lendo"]) .obra.lombada .titulo {
  font-size: 12px; max-height: 158px;
}
.obra.lombada .autor {
  writing-mode: vertical-rl; text-orientation: mixed;
  font-family: var(--sans); font-weight: 600; font-size: 8px; letter-spacing: .16em;
  text-transform: uppercase; margin-top: auto;
  /* Mesma razão do título: o nome longo («Joseph Sheridan Le Fanu») abria uma
     segunda coluna que crescia por cima da lombada. */
  white-space: nowrap; text-overflow: ellipsis;
  /* 65%, e não os 60% do desenho: a 60% o pior par das cinco tintas (petróleo)
     media 4,67:1 — passava o piso de 4.5 e raspava a mira de 4.7 da casa.
     Texto miúdo não afrouxa piso por ser miúdo; ele sobe a opacidade. */
  color: color-mix(in srgb, var(--sobre-lombada) 65%, transparent);
  max-height: 90px; overflow: hidden;
}
/* No PÉ da lombada, onde a estante de verdade põe o sinete da editora. Na
   tinta da lombada, e não no acento: brasa sobre bordô some (ver o título).
   Sem autor, é ele quem desce ao pé. */
.obra.lombada .sinal-estudio {
  flex: none; margin-top: 10px; color: var(--sobre-lombada);
}
.obra.lombada .titulo + .sinal-estudio { margin-top: auto; }

/* ── A TÁBUA ──────────────────────────────────────────────────────────────
   Nove pixels de madeira vista de canto, com o brilho de cima e a sombra
   projetada logo abaixo. Sem ela as lombadas flutuam — e lombada que não se
   apoia em nada se lê como barra de gráfico, não como livro.

   Desde 02/09 ela é o `repeating-linear-gradient` da fileira (ver acima), e
   não mais um elemento: com a quebra em várias linhas, quem sabe quantas
   tábuas existem é o navegador, não o HTML. O `<span class="tabua">` saiu do
   markup junto. */

/* ── A COLUNA DA CAPA ─────────────────────────────────────────────────────
   A `.capa-cega` de hoje, só que UMA por tela em vez de vinte e seis — e por
   isso ela pode ser grande e ter medida em px, sem `cqw`. */
/* `sticky`: com o acervo inteiro em prateleiras empilhadas, a página rola —
   e uma coluna presa ao topo sairia de cena no terceiro livro, levando junto
   as quatro ações da obra em foco. Ela acompanha a rolagem e para quando o
   fim das prateleiras a alcança. */
.coluna-capa {
  flex: none; width: 248px;
  position: sticky; top: 1.6rem; align-self: flex-start;
  display: flex; flex-direction: column; gap: .55rem;
}
.coluna-capa .capa-grande {
  display: flex; flex-direction: column; justify-content: flex-end;
  aspect-ratio: 2 / 3; border-radius: 3px; padding: 26px 24px;
  background:
    linear-gradient(160deg, rgba(255,255,255,.12), rgba(0,0,0,.16)),
    var(--lombada, var(--tenue));
  /* Sombra própria, projetada para a ESQUERDA: a capa está de frente para
     quem olha, e a luz da casa vem de cima e da esquerda. */
  box-shadow: -2px 10px 26px rgba(34,33,29,.3);
  color: var(--sobre-lombada); overflow: hidden;
}
.coluna-capa .capa-titulo {
  font-family: var(--serif); font-weight: 600; font-size: 25px; line-height: 1.12;
  letter-spacing: -.01em; text-wrap: pretty;
  display: -webkit-box; -webkit-line-clamp: 5; -webkit-box-orient: vertical;
  overflow: hidden;
}
.coluna-capa .capa-filete {
  display: block; height: 1px; background: rgba(255,255,255,.45);
  margin: 16px 0 12px; flex: none;
}
.coluna-capa .capa-autor {
  font-family: var(--sans); font-weight: 600; font-size: 9.5px; letter-spacing: .15em;
  text-transform: uppercase; opacity: .88;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.coluna-capa .tema {
  font-family: var(--sans); font-weight: 600; font-size: 10px; letter-spacing: .12em;
  text-transform: uppercase; color: var(--tenue);
}
.coluna-capa .legenda {
  font-family: var(--sans); font-size: 12.5px; color: var(--tinta-2);
  font-variant-numeric: tabular-nums;
}
/* `sinal-texto`, e não `rotulo`: `.rotulo` é nome genérico demais, usado em
   quatro telas e no próprio harness de design — cuja regra de legenda de cena
   vestiu a primeira captura de versalete apagado («VOZ DE ESTÚDIO · 11H»). */
.coluna-capa .sinal-estudio { font-family: var(--sans); font-size: 12.5px; color: var(--tinta-2); }
.coluna-capa .sinal-estudio svg { color: var(--acento); }
.coluna-capa .acoes { display: flex; gap: .4rem; margin-top: .2rem; }
.coluna-capa .acoes .redondo {
  width: 34px; height: 34px; min-height: 34px; font-size: .95rem;
  border-color: var(--aro-fino);
}
.coluna-capa .acoes .excluir:hover, .coluna-capa .acoes .excluir:focus-visible {
  color: var(--perigo); border-color: var(--perigo);
}
.coluna-capa .aviso-estado { margin-top: .4rem; }

/* No iPad em retrato e no iPhone a coluna sai: 248px ali são metade da tela
   para mostrar um livro de cada vez. A prateleira continua inteira, e a capa
   volta a ser o que era antes de existir coluna — a vista Grade. */
@media (max-width: 899px) {
  .coluna-capa { display: none; }
}
/* A regra da grade 2×2 das ações saiu com a capa da prateleira (02/09): a
   fileira mostra LOMBADAS, e a lombada não carrega botão nenhum — quem tem as
   ações da obra em foco é a coluna da capa. */
/* A regra que engordava a capa de 104 para 124px em tela larga saiu com a
   capa: a lombada tira a largura da EXTENSÃO da obra, não da tela. */

/* ── O cartão é uma COLUNA, e o rodapé dele mora embaixo  (01/09) ──────────
   Sem isto, a fileira de ações cai onde o título terminar. Numa grade de cinco
   colunas isso põe cinco fileiras de botões em cinco alturas diferentes — e
   basta um título de seis linhas («O jardim das Aflições: de Epicuro à
   ressurreicão de César ; ensaio sobre o materialismo e a religião civil») para
   a coluna dele descer sozinha e a linha inteira perder o pé.

   Duas peças, e as duas são necessárias:

     · o `<li>` vira coluna e ESTICA até a altura da linha da grade (é o
       `align-items: stretch` que o grid já dá de graça, mas só serve se o item
       for um contêiner de altura cheia);
     · o `.alvo` fica com `flex: 1` e come a sobra, empurrando `.acoes` para a
       base. `margin-top: auto` faria o mesmo — mas o `flex: 1` deixa a área
       clicável ocupar o vazio, e num cartão de livro o vazio embaixo do autor
       ainda é o livro.

   Vale na grade e na fileira: os dois são contêiner flex, e o cartão não
   precisa saber em qual está. */
.obra {
  position: relative;
  display: flex; flex-direction: column; height: 100%;
}
.obra .alvo {
  display: flex; flex-direction: column; flex: 1;
  text-decoration: none; color: inherit;
}

/* ── A capa é DESENHADA  (prancha 1f, candidato «papel manchado») ──────────
   «A capa não ilustra a obra: ela veste a matiz do tema de estudo.»

   Papel do tema com uma mancha radial a 62% da matiz, entrando por um canto
   sorteado pelo hash do slug (`capa.mjs`), título em Literata por cima e um
   filete a 35% de tinta. Nenhuma imagem, nunca — e por isso nenhum `<img>`,
   nenhuma rede, nenhum estado de carregamento e nada que possa falhar.

   Escolhido entre os três candidatos pelo que a prancha registra: é o que
   sobrevive melhor a 84px, e 84px é o tamanho da prateleira. */
.obra .capa {
  display: flex; align-items: flex-end; width: 100%; aspect-ratio: 2 / 3;
  border-radius: var(--raio); border: 1px solid var(--borda-controle);
  background: var(--papel-elev);
  overflow: hidden; position: relative; box-sizing: border-box;
  padding: .55rem .5rem .5rem;
}
/* Só o manchado tinge o filete de tinta: no campo cheio ele é branco a 45%,
   declarado no bloco da capa cega. */
.obra .capa-manchado .capa-titulo {
  color: var(--tinta);
  border-top-color: color-mix(in srgb, var(--tinta) 35%, transparent);
}
.obra .capa-manchado::before {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: radial-gradient(74% 62% at var(--mancha, 18% 14%),
    color-mix(in srgb, var(--t, var(--tenue)) 62%, transparent), transparent 72%);
}
/* O filete, acima do título. A 35% de tinta ele separa sem virar moldura —
   moldura é o que a prancha manda não ter. */
.obra .capa-titulo {
  position: relative; z-index: 1;
  /* Largura cheia, e não a do texto: o filete é uma RÉGUA sobre o rodapé da
     capa, e um filete do tamanho da palavra vira sublinhado — que é outra
     coisa, e a que a prancha não pediu. */
  width: 100%; box-sizing: border-box;
  font-family: var(--serif); font-weight: 600;
  font-size: .72rem; line-height: 1.22;
  /* `inherit`, e não `var(--tinta)`. Este bloco nasceu para o «papel manchado»,
     onde o título é tinta sobre papel; a capa de campo cheio põe texto CLARO
     sobre a matiz, e declarar a cor aqui vencia a herança do pai — o título
     saía preto sobre roxo, ilegível. Quem decide a cor do texto é o campo. */
  color: inherit;
  display: -webkit-box; -webkit-line-clamp: 4; -webkit-box-orient: vertical;
  overflow: hidden;
  padding-top: .4rem;
  border-top: 1px solid currentColor;
  text-wrap: pretty;
}

/* O traço do progresso, na base da capa. Fino de propósito: é informação de
   canto de olho, e a mesma semântica do anel da bolha no artigo. */
.obra .traco {
  display: block; height: 3px; margin-top: -3px; position: relative;
  border-radius: 0 0 var(--raio) var(--raio); overflow: hidden;
  background: color-mix(in srgb, var(--tinta) 12%, transparent);
}
/* `--t`, e não `--acento` (2026-09-01): é a mesma regra que a prancha 1c fixa
   para a lista — a barra de progresso veste a matiz do TEMA, nunca a cor do
   app. O traço da capa é a mesma informação noutra tela, e estava dizendo
   «cyber» com a voz da marca. */
.obra .traco > span { display: block; height: 100%; background: var(--t, var(--acento)); }

/* ── O título ocupa DUAS linhas, sempre  (01/09) ───────────────────────────
   Alinhar o rodapé embaixo conserta o desalinhamento e deixa outra feiura no
   lugar: com um título de uma linha ao lado de um de seis, o cartão curto fica
   com um rombo de branco entre o autor e os botões. O que a grade quer é o
   contrário disso — legendas do mesmo tamanho, como numa estante de verdade as
   lombadas têm a mesma altura.

   `-webkit-line-clamp` corta o que passa de duas linhas e põe reticências, e o
   `min-height` reserva as duas mesmo quando só há uma. O par é que iguala; um
   sozinho resolve metade.

   O texto continua INTEIRO no DOM — o corte é visual, então o leitor de tela
   ouve o título completo e a busca o encontra. E a capa logo acima já cortava
   com reticências desde a prancha 1f: duas medidas diferentes do mesmo título
   na mesma peça seria o estranho. */
.obra .titulo {
  font-family: var(--serif); font-size: .9rem; line-height: 1.3;
  margin-top: .5rem; font-weight: 600; text-wrap: balance;
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2;
  overflow: hidden;
  min-height: calc(2 * 1.3em);
}
.obra .autor { display: block; font-family: var(--sans); font-size: .75rem; color: var(--tinta-2); }
.obra:not(.lombada) .sinal-estudio { display: flex; margin-top: .3rem; }
/* A legenda «71% · canto XXII» só existe em «Lendo agora» — quem decide é o
   `montarObra`, não o CSS, porque é informação e não aparência. Aqui só a voz:
   sans, miúda e em `--tenue`, que é o registro do que se lê de canto de olho. */
.obra .legenda {
  display: block; font-family: var(--sans); font-size: .7rem; color: var(--tenue);
  margin-top: .15rem; font-variant-numeric: tabular-nums;
}
/* O acento no título é da vista GRADE, onde ele é texto sobre papel e o realce
   precisa de cor. Na LOMBADA ele é texto claro sobre campo escuro: o acento
   pinta o título de brasa por cima do bordô — visto no iPad em 02/09, no livro
   que o toque levantou. Lá o realce já existe e é outro: o livro sobe 14px,
   que é o gesto de tirá-lo da prateleira. */
.obra:not(.lombada) .alvo:hover .titulo,
.obra:not(.lombada) .alvo:focus-visible .titulo { color: var(--acento); }

/* ── As cinco ações da GRADE cabem numa LINHA  (02/09) ────────────────────
   Duas tentativas antes desta, e as duas foram vistas no aparelho:

   1. **Cinco em `flex` sem quebra**, herdado de quando eram quatro: 5×36px
      mais os vãos dão ~196px numa coluna que pode ter 144, e os botões foram
      parar por cima do cartão vizinho.
   2. **Grade de 3+2**: não transborda, e fica torto — duas fileiras
      desiguais de círculos embaixo de cada capa, vinte e seis vezes. «Ficou
      feio», e estava.

   O que faz a linha caber é o par: o botão desce de 36 para 30px (o registro
   do alvo secundário, que o `✎` do destaque já usa a 26) e a coluna sobe de
   9 para 10,5rem. 5×30 + 4×3 = 162px numa coluna que nunca é menor que 168.

   A coluna maior não é custo: no iPad ela troca cinco capas apertadas por
   quatro maiores, que é o que uma grade de capas quer mostrar. */
/* ── E eram SEIS, não cinco  (17/09) ──────────────────────────────────────
   O lápis de editar título e autor entrou na fileira no MESMO dia, depois da
   conta de cima: 6×30 + 5×3 = 195px numa coluna de 171 no iPhone. O ✕ de um
   cartão pousava sobre o ✓ do vizinho, e o da coluna direita saía da tela e
   dava à página inteira uma rolagem lateral. O teste cobrava `lado × 5`, com
   o cinco escrito à mão, e seguiu verde.

   Agora o círculo é ELÁSTICO: 30px quando cabe, cedendo até 26 (o registro do
   `✎` do destaque) quando não cabe, com 2px de vão. Seis a 26 com cinco vãos
   medem 166px, dentro dos 168 da coluna mínima; no iPad e no Mac, onde a
   coluna é larga, nada muda. `aspect-ratio` mantém o círculo quando a largura
   cede, e `align-items: center` impede o esticamento de desfazê-lo. */
/* ── E são SETE, em duas fileiras  (18/09, spec 61) ──────────────────────
   «Mandar para lista…» entrou como sétima. Sete círculos de 26px com vão
   medem 194px, e a coluna mínima é 168 — o teto para o iPhone manter duas
   colunas é 171. Encolher o círculo abaixo de 26 tira o alvo; alargar a
   coluna põe o iPhone numa coluna só. Duas fileiras de quatro, e a divisão
   tem sentido: em cima, onde o livro está (✓ ⤓ ▤ e a escrivaninha); embaixo,
   o que fazer com ele (a lista, o lápis e o ✕). 4×30 + 3×4 = 132px. */
.obra .acoes {
  display: grid; grid-template-columns: repeat(4, 30px); gap: 4px;
  justify-content: start; align-items: center; margin-top: .4rem;
}
/* ── O tamanho que faltava, e faltava desde antes desta rodada  (2026-09-01)
   A regra de `.redondo` diz com todas as letras que «a forma é dele, o TAMANHO
   é do contexto» — e a estante nunca disse o seu. Os botões herdavam 44px de
   altura do `--alvo` do núcleo e tiravam a largura do CONTEÚDO: um glifo de
   uma letra, ~12px. Quatro elipses verticais de 12×44.
   Não apareceu antes porque a grade dava colunas de 144px e as elipses tinham
   espaço de sobra para não parecerem apertadas; a fileira de 104px as pôs lado
   a lado e o defeito ficou visível. Ele já estava lá.
   36px é o registro do `.linha-progresso` (32) mais folga, e cabe duas por
   fileira nos 104px — com a quebra logo abaixo, as quatro ficam em 2×2. */
.obra .acoes .redondo {
  flex: 0 1 30px; min-width: 26px; height: auto; min-height: 0;
  aspect-ratio: 1; font-size: .82rem;
}


/* ── O alternador de vista da estante  (prancha 1e) ────────────────────────
   «Grade | Prateleiras», um segmentado ao lado do título. Duas vistas do mesmo
   acervo: a prateleira agrupa por estado e rola; a grade mostra tudo de uma
   vez, ordenado pela última leitura.

   `role="tablist"` e `aria-selected` em vez de `aria-pressed`: são vistas
   mutuamente exclusivas do mesmo conteúdo, que é exatamente o que uma aba é —
   e dois botões de alternar independentes diriam a quem usa leitor de tela que
   as duas podem estar ligadas ao mesmo tempo. */
.cabeca-estante {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 1rem; flex-wrap: wrap; margin: 0 0 1rem;
}
.cabeca-estante .titulo-tela { margin: 0; }
.vistas {
  display: inline-flex; padding: 3px; gap: 2px;
  background: var(--papel-elev-2); border-radius: 999px;
}
.vistas .vista {
  font-family: var(--sans); font-size: .78rem; font-weight: 500;
  color: var(--tinta-2); background: none; border: 0; cursor: pointer;
  padding: .4rem .9rem; border-radius: 999px; min-height: 34px;
}
.vistas .vista[aria-selected="true"] {
  background: var(--papel-elev); color: var(--tinta);
  box-shadow: var(--sombra-pousada);
}
.vistas .vista:hover, .vistas .vista:focus-visible { color: var(--acento); }

/* A grade: aqui SIM o `auto-fill` é a resposta certa, e pelo motivo que a
   prateleira não tinha. A vista Grade existe justamente para mostrar o
   conjunto todo de uma vez — quebrar em linhas é o que ela promete, e o iPad
   girando continua sendo o caso comum. */
/* 10,5rem (168px) desde 02/09, e o número sai da fileira de ações: cinco
   alvos de 30px com 3px de vão medem 162, e uma coluna que possa ser menor que
   isso é uma coluna em que os botões transbordam. O mínimo da grade e a largura
   da fileira são a MESMA decisão — separá-los foi o que deixou os cinco botões
   caírem por cima do cartão vizinho. */
.grade-estante {
  list-style: none; margin: 0; padding: 0;
  display: grid; grid-template-columns: repeat(auto-fill, minmax(10.5rem, 1fr));
  gap: 1rem;
}

/* ── A capa «tipográfica cega»  (prancha 1f, candidato 1 — escolhido em 01/09)
   Campo cheio na matiz do tema, título em Literata sobre ele, filete a 45% de
   branco e o autor em versalete. Nenhuma imagem, nunca.

   As medidas vêm da prancha, que compõe sobre uma capa de 100px: título 17px,
   filete de 1px com 8px/6px de folga, autor 7,5px com 0,14em de entreletra.
   Aqui elas viram `cqw` — a prateleira desenha a 104px e o Mac a 124, e uma
   capa que muda de tamanho com o título fixo deixa de ser a mesma capa. Com
   unidade de contêiner a proporção atravessa os dois. */
.obra .capa-cega {
  /* `stretch`, desfazendo o `align-items: flex-end` de `.obra .capa`. Aquele
     valor servia ao manchado, que é `flex-direction: row` e queria o título no
     rodapé; aqui a direção é `column`, e no eixo cruzado `flex-end` empurra o
     texto para a DIREITA. Título curto saía alinhado à direita e título longo
     à esquerda, na mesma prateleira. */
  align-items: stretch;
  container-type: inline-size;
  border-radius: 2px;
  /* A tinta da LOMBADA (02/09): é o mesmo livro nas duas vistas, e ele não
     pode mudar de cor ao trocar de vista. A cadeia de reserva desce da
     lombada para o `--t` (o elemento que só recebeu `estiloDoCluster`) e daí
     para o cinza — o token do meio, morto desde 02/09, saiu com a spec 73. */
  background: var(--lombada, var(--t, var(--tenue)));
  box-shadow: var(--sombra-pousada);
  /* O padding em `%`, e não em `cqw`, e isto vale um comentário porque custou
     uma rodada: `container-type: inline-size` faz o elemento ser contêiner
     para os DESCENDENTES dele, não para si mesmo. Um `cqw` escrito aqui
     resolve contra o contêiner de fora — a capa de 104px ganhou 12% de 1150 e
     virou uma caixa de 266. Percentual resolve contra o pai, que é o que se
     queria. */
  padding: 12% 11%;
  display: flex; flex-direction: column; justify-content: flex-end;
  /* Cravado, e não `--sobre-acento`: este branco é o papel da CAPA, e ele tem
     de ser o mesmo sobre as cinco matizes — um token que muda por tema faria a
     série mudar de cor de texto conforme a hora do dia. */
  color: #fdf6ef;
  overflow: hidden;
}
.obra .capa-cega .capa-titulo {
  font: 600 17cqw/1.1 var(--serif); letter-spacing: -.01em;
  color: inherit;
  /* Sem filete próprio: aqui ele é um `<span>` dedicado, entre título e autor,
     porque a prancha o quer com o branco a 45% e uma folga própria de cada
     lado. O `border-top` do bloco genérico serve ao manchado, que não tem
     autor embaixo. */
  border-top: 0; padding-top: 0; width: auto;
  display: -webkit-box; -webkit-line-clamp: 4; -webkit-box-orient: vertical;
  overflow: hidden; text-wrap: pretty;
}
.obra .capa-cega .capa-filete {
  display: block; height: 1px; background: rgba(255,255,255,.45);
  margin: 8% 0 6%; flex: none;
}
.obra .capa-cega .capa-autor {
  font: 600 7.5cqw/1 var(--sans); letter-spacing: .14em;
  text-transform: uppercase; opacity: .88;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* ── Visível para o leitor de tela, invisível para o olho ──────────────────
   A prancha 1c vai da marca direto ao segmentado: não há título «Inbox» acima
   das abas. Mas uma tela sem `<h1>` é uma regressão de navegação por
   cabeçalhos, e trocar acessibilidade por diagramação é troca ruim — então o
   título fica no documento e sai da vista.

   `clip-path: inset(50%)` e não `display:none` nem `visibility:hidden`: os
   dois últimos tiram o elemento da árvore de acessibilidade junto, que é
   exatamente o oposto do que se quer aqui. Mesma técnica do
   `#colar input[type=file]`, e pelo mesmo motivo. */
.so-leitor {
  position: absolute; width: 1px; height: 1px; margin: -1px;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap;
}



/* ═══════════════════════════════════════════════════════════════════════════
   A ESCRIVANINHA  (spec 23)
   ═══════════════════════════════════════════════════════════════════════════
   A quarta seção, a rota do estudo e a revisão. Nada aqui inventa gramática:
   a lista é a lista, os painéis são da família do `#nota`, e a cápsula do
   estudo é uma terceira cápsula na pilha que já existe.
   ═════════════════════════════════════════════════════════════════════════ */

/* ── A pilha ganha uma QUARTA cápsula, e SÓ na rota do estudo ──────────────
   Duas parcelas mudam aqui, e as somas que dependem delas se refazem sozinhas
   porque todas moram no mesmo `body` (ver a nota da geometria, lá em cima):

     · a cápsula do estudo entra no topo;
     · a MÃO perde um item — o `⇧` não existe na escrivaninha, onde
       compartilhar é o estudo inteiro e mora no `⋯`.

   O TETO é 520px, e ele é requisito, não estimativa: a coluna tem de caber em
   iPad retrato com o texto embaixo. O `npm run design` mede. */
body[data-rota="estudo"] {
  /* O «Seguir» mais os DOIS glifos (original, `⋯`) e os dois fios. Eram três
     até a F1 da spec 51, que tirou o ▤ dos cartões da cápsula e deixou a conta
     com o glifo que não existe: 206px declarados contra 158 reais, a coluna do
     Mac 24px abaixo do centro e a da bancada 48px «mais alta» do que é. Quem
     cobra é o `npm run design`, pela folga de cima igual à de baixo. */
  --capsula-estudo-h: calc(var(--capsula-seguir-h) + var(--capsula-item) * 2 + 2px);
  --capsula-mao-h: calc(var(--capsula-item-texto) * 2 + 2px);
  /* A cápsula da bancada (spec 43 §7.1): a face alta, como o «Seguir», mais
     os QUATRO glifos (`</>`, `>_`, `▶▶`, `✕`) e os dois fios. Ela mora aqui,
     e não no `:root`, pela regra desta seção: parcela que uma rota redeclara
     mora no elemento em que a rota a redeclara. */
  --capsula-bancada-h: calc(var(--capsula-seguir-h) + var(--capsula-item) * 4 + 2px);
  --bancada-bloco: 0px;
  --pilha-h: calc(var(--bancada-bloco) + var(--capsula-estudo-h) + var(--capsula-gap)
    + var(--capsula-pagina-h) + var(--capsula-gap)
    + var(--voz-bloco) + var(--capsula-mao-h));
  --y-aa: calc(var(--capsula-mao-h) + var(--capsula-gap) + var(--voz-bloco));
  --y-progresso: calc(var(--y-aa) + var(--capsula-item));
  --y-velocidade: calc(var(--capsula-mao-h) + var(--capsula-gap) + var(--capsula-item));
}

/* ── E a QUINTA cápsula, só quando há laboratório em cena  (spec 43 §7.1) ──
   `--bancada-bloco` é a cápsula MAIS o gap abaixo dela, e vale zero quando
   ela não existe — o mesmo desenho do `--voz-bloco`, e pela mesma razão: uma
   soma que muda de número de parcelas dá `calc()` inválido, e `calc()`
   inválido não desenha nada de errado, só faz o Mac centrar a coluna pela
   altura de antes. Quem acende o atributo é a própria cápsula, que o escreve
   ao nascer e o apaga ao sair (`capsula-bancada.mjs`). */
body[data-rota="estudo"][data-bancada] {
  --bancada-bloco: calc(var(--capsula-bancada-h) + var(--capsula-gap));
}

/* O «Seguir» é o único item da pilha inteira com rótulo em TEXTO e com o
   acento em campo — é a ação primária da tela, e a única que o leitor procura
   sem saber onde está. As irmãs continuam glifos de 48px. */
#capsula-estudo > button { font-size: .8rem; }
/* ── O «Seguir»: DUAS linhas, e a razão é a largura da cápsula ─────────────
   A pilha tem 52 px, e um rótulo de uma linha só ali cabia em três letras —
   «Perguntas da parte 2» saía como «Per…», que é pior que glifo nenhum: o
   botão promete uma palavra e entrega o começo dela. A captura de 03/09
   mostrou isso, e nenhum teste de estado veria.
   Então o item é ALTO (a spec já pedia «item alto, com rótulo»): a ação em
   cima, o destino embaixo, ambos em caixa pequena. O rótulo inteiro vive no
   `title` e no `aria-label`. */
#estudo-seguir {
  height: var(--capsula-seguir-h);
  background: var(--acento); color: var(--sobre-acento);
  padding: 4px 2px 5px; text-align: center;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 1px; overflow: hidden;
}
#estudo-seguir .acao {
  font-size: .58rem; font-weight: 600; letter-spacing: .07em; text-transform: uppercase;
  opacity: .82; line-height: 1;
}
#estudo-seguir .alvo {
  font-size: .57rem; font-weight: 600; line-height: 1.25; letter-spacing: -.005em;
  /* Duas linhas no máximo, e a quebra é no ESPAÇO — nunca no meio da palavra.
     Com `overflow-wrap: anywhere`, «Perguntas 2» saía «Pergunt / as 2», que é
     o mesmo defeito do «Per…» com mais linhas: o botão promete uma palavra e
     entrega um pedaço dela. Quebrando no espaço, sai «Perguntas / 2». */
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2;
  overflow: hidden; max-width: 100%; overflow-wrap: normal; hyphens: none;
}
#estudo-seguir:hover, #estudo-seguir:focus-visible { color: var(--sobre-acento); opacity: .92; }
#estudo-seguir[disabled] { opacity: .55; cursor: default; }
/* Enquanto gera, o botão é inerte E parece inerte: clicar duas vezes não gera
   duas vezes (a API recusa com 409), mas um botão que aceita o toque e não faz
   nada é pior que um desligado. */
/* ── E ela veste o CROMO, não o papel  (05/09) ─────────────────────────────
   Nasceu com `--papel-elev-2`/`--tinta-2`, que é o campo esmaecido certo para
   um botão inerte sobre PAPEL. A cápsula, porém, é cromo grafite nos três
   temas desde a repaginação de 02/09 — e ali um campo de papel claro vira a
   coisa mais brilhante da coluna. Medido em 7,5:1 nos três temas
   (`espera.test.mjs`), um degrau abaixo das irmãs porque inerte é o que ele é. */
#estudo-seguir.gerando { background: var(--cromo-2); color: var(--cromo-tinta-2); }
/* ── Mas «gerando» NÃO se apaga como «indisponível»  (03/09) ───────────────
   O botão é `disabled` enquanto escreve — e o `[disabled]` acima deita
   `opacity: .55` sobre ele. Somado à tinta já esmaecida, o rótulo da espera
   media **2,30 : 1** no claro (2,48 no sépia, 2,78 no escuro), contra o piso
   de 4,5 — o texto que o leitor mais encara na tela era o menos legível dela,
   e a queixa que originou o relógio era justamente não saber se algo estava
   acontecendo.

   A opacidade volta a 1: quem diz «inerte» aqui são as cores trocadas, e uma
   coisa que está TRABALHANDO não se anuncia como coisa que não está
   disponível. Medido em `espera.test.mjs`, nos três temas. */
#estudo-seguir.gerando[disabled] { opacity: 1; }
/* ── E quando o próprio pedido falha  (03/09) ──────────────────────────────
   Mesmo campo esmaecido do «gerando», tinta do perigo — medido em 5,72 : 1 no
   claro, 4,95 no sépia, 5,77 no escuro. O botão continua clicável, porque
   tentar de novo é o gesto óbvio e o motivo inteiro está no `title`. */
/* O irmão da espera, e pela mesma razão veste o mesmo campo de cromo. A tinta
   passa a ser `--cromo-perigo` — o `--perigo` de papel dá 2,50:1 sobre grafite
   no claro, e a regra é clarear a TINTA, nunca o campo. O token já existia
   desde 04/09, criado por este mesmo motivo noutro botão da mesma coluna. */
#estudo-seguir.falhou { background: var(--cromo-2); color: var(--cromo-perigo); }

/* ═══════════════════════════════════════════════════════════════════════════
   A CÁPSULA DA BANCADA  (spec 43 §7.1)

   A barra do pé da página saiu — ela era `sticky` sobre o texto e, no iPad,
   nascia debaixo da navegação inferior (visto em 08/09: «Rodar até aqui» e
   «Reiniciar» cobertos). O que entra é uma cápsula no TOPO da pilha, com os
   mesmos 52px das irmãs e a mesma anatomia do «Seguir»: face alta de duas
   linhas e quatro glifos abaixo.

   As regras são gêmeas das do `#estudo-seguir` e ficam escritas em separado
   de propósito — juntar os dois seletores quebraria as conferências que leem
   `#estudo-seguir { … }` por regex. Quem cobra que elas não divirjam é o
   `bancada.test.mjs`, que lê esta folha.
   ═════════════════════════════════════════════════════════════════════════ */
#capsula-bancada > button { font-size: .8rem; }
#bancada-face {
  height: var(--capsula-seguir-h);
  background: var(--acento); color: var(--sobre-acento);
  padding: 4px 2px 5px; text-align: center;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 1px; overflow: hidden;
}
#bancada-face .acao {
  font-size: .58rem; font-weight: 600; letter-spacing: .07em; text-transform: uppercase;
  opacity: .82; line-height: 1;
}
#bancada-face .alvo {
  font-size: .57rem; font-weight: 600; line-height: 1.25; letter-spacing: -.005em;
  /* Duas linhas, quebra no espaço — e o hífen de sílaba do «reconec­tando…»,
     que é a única palavra do mostrador que não cabe numa linha de 52px. */
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2;
  overflow: hidden; max-width: 100%; overflow-wrap: normal; hyphens: manual;
  font-variant-numeric: tabular-nums;
}
#bancada-face:hover, #bancada-face:focus-visible { color: var(--sobre-acento); opacity: .92; }
/* Subindo e caído a face é cromo, e não acento: ela ainda é o mostrador, mas
   não é convite — o acento cheio numa coluna grafite é o que chama a mão, e
   a mão não tem nada a fazer enquanto a task nasce. A tinta é a clara sobre
   cromo, nunca o campo clareado (a regra de 05/09). */
#bancada-face[data-estado="subindo"] { background: var(--cromo-2); color: var(--cromo-tinta-2); }
#bancada-face[data-estado="caiu"] { background: var(--cromo-2); color: var(--cromo-perigo); }
#bancada-face[data-estado="falhou"] { background: var(--cromo-2); color: var(--cromo-perigo); }
#bancada-face[data-estado="encerrada"] { background: var(--cromo-2); color: var(--cromo-tinta-2); }
/* Rodando o campo é acento e o mostrador pulsa: é o único estado em que tocar
   INTERROMPE, e ele tem de se distinguir do «pronta» sem trocar de lugar. */
#bancada-face[data-estado="rodando"] .acao { animation: bancada-pulso 1.1s ease-in-out infinite; }
/* Inerte é o «sem relé», e só ele: o mostrador não se apaga por estar
   ocupado — quem trabalha não se anuncia como indisponível (03/09). */
#bancada-face[disabled] { opacity: .55; cursor: default; }
#bancada-fechar[disabled], #bancada-ate-aqui[disabled] { opacity: .45; cursor: default; }

/* ── Numa janela BAIXA, a bancada recolhe «Até aqui» e «Fechar»  (43 §7.1) ─
   Os dois têm gêmeos na aba Shell da caixa; «Editar» e «Caixa» não têm outro
   lugar, e por isso ficam. O corte é 900px porque é onde a coluna com CINCO
   cápsulas deixa de caber: 866 (pilha) + 90 (--pilha-0) + 24 (folga) = 980,
   e o degrau redondo abaixo disso é 900.

   E o token encolhe junto. Esconder dois itens sem mexer em
   `--capsula-bancada-h` deixaria a altura DECLARADA 96px maior que a real, e
   é por ela que o Mac centra a coluna — a folga de cima abriria pela
   diferença. */
@media (max-height: 900px) {
  #bancada-ate-aqui, #bancada-fechar { display: none; }
  body[data-rota="estudo"] {
    --capsula-bancada-h: calc(var(--capsula-seguir-h) + var(--capsula-item) * 2 + 2px);
  }
}

/* ── Numa janela BAIXA, a cápsula recolhe ao essencial  (03/09) ────────────
   Com as três cápsulas abertas a coluna mede 584px — medido no harness, com
   todas as bolhas em cena. O corte é o PONTO EM QUE ELA NÃO CABE, e não a
   altura de um aparelho (a lição de 02/09 no Tabula, com o iPhone que ficava
   dez pixels fora da media query). A conta, no modo barra, que é o pior caso
   por ser o único que ancora a pilha embaixo:

       584 (pilha) + 90 (--pilha-0) + 24 (folga em cima) = 698

   Daí 720px, o degrau redondo logo acima. Um iPhone em retrato tem ~780 de
   viewport e NÃO recolhe; um iPad com o teclado aberto recolhe, que é
   exatamente quem precisa. Recolhida, a conta cai para 488 + 90 + 24 = 602.

   O que sobrevive ao aperto é o par que não tem substituto: a ação primária
   («Seguir») e a saída («⋯»). O glifo que recolhe continua alcançável pelo
   menu, que é a lista completa — recolher não pode virar sumir. */
@media (max-height: 720px) {
  #estudo-original { display: none; }
}

/* ── A visão: a partida, o mapa e o que ficou de fora  (03/09) ─────────────
   O mapa é DADO — cada unidade com o peso e o botão de riscar —, e a lista do
   que ficou de fora existe para o corte de ruído ser conferível: motivo e
   contagem, item por item. */
.partida {
  border-left: 3px solid var(--acento); padding: .2rem 0 .2rem 1rem;
  margin: 0 0 1.6rem; max-width: var(--measure);
}
.partida .rotulo {
  font-family: var(--sans); font-size: .72rem; letter-spacing: .08em;
  text-transform: uppercase; color: var(--acento); margin: 0 0 .3rem;
}
.partida .pergunta {
  font-family: var(--corpo); font-size: 1.05rem; line-height: 1.5;
  color: var(--tinta); margin: 0;
}
.mapa-estudo {
  margin: 2.5rem auto 0; max-width: var(--measure);
  border-top: 1px solid var(--regra); padding-top: 1.2rem;
  font-family: var(--sans);
}
.mapa-estudo h2 {
  font-size: .74rem; letter-spacing: .09em; text-transform: uppercase;
  color: var(--tenue); margin: 0 0 .8rem;
}
.mapa-estudo .unidades { list-style: none; margin: 0; padding: 0; }
.mapa-estudo .unidades li {
  display: flex; flex-wrap: wrap; align-items: center; gap: .25rem .6rem; padding: .45rem 0;
  border-bottom: 1px solid var(--papel-borda-fina);
}
.mapa-estudo .termo { flex: 1 1 auto; font-size: .94rem; color: var(--tinta); }
/* A ideia-mestra é uma proposição: o título nomeia, o enunciado DIZ. Ele toma
   a linha inteira (`flex-basis: 100%` quebra a linha do flex) para não
   disputar espaço com o «Já domino» num telefone. */
.mapa-estudo .enunciado {
  flex: 1 0 100%; font-size: .82rem; line-height: 1.4; color: var(--tenue);
}
.mapa-estudo .peso { color: var(--acento); font-size: .7rem; letter-spacing: .1em; }
.mapa-estudo .domino {
  font-size: .78rem; padding: .2rem .55rem; min-height: 0; flex: none;
}
/* Riscada, não sumida: o leitor tem de ver o que ele mesmo tirou. */
.mapa-estudo .dominada .termo { color: var(--tenue); text-decoration: line-through; }
.mapa-estudo .dominada .peso { opacity: .35; }
.mapa-estudo .dominada .enunciado { opacity: .5; }
.mapa-estudo details { margin-top: 1rem; }
.mapa-estudo summary {
  font-size: .8rem; color: var(--tinta-2); cursor: pointer;
}
.mapa-estudo .fora-do-estudo ul { list-style: none; margin: .5rem 0 0; padding: 0; }
.mapa-estudo .fora-do-estudo li {
  display: flex; justify-content: space-between; font-size: .82rem;
  color: var(--tenue); padding: .2rem 0;
}
.mapa-estudo .partida-resposta p {
  font-family: var(--corpo); font-size: .95rem; line-height: 1.55;
  color: var(--tinta-2); margin: .4rem 0 0;
}

/* ── O fecho do estudo  (spec 51) ──────────────────────────────────────────
   Na conclusão: o laboratório sob demanda (só no técnico) e a passagem que
   ficou (nos gêneros de ressonância). Da família do juízo da parte — no fim do
   texto, discreto, e sem campo nenhum dentro do `<main>`: a frase se escreve no
   painel `#ressonancia`, fora dele. */
.fecho-estudo {
  margin: 2.5rem auto 0; max-width: var(--measure);
  border-top: 1px solid var(--regra); padding-top: 1.2rem;
  display: flex; flex-direction: column; gap: 1.4rem;
}
.fecho-estudo h2 {
  font-family: var(--sans); font-size: .74rem; letter-spacing: .09em;
  text-transform: uppercase; color: var(--tenue); margin: 0 0 .5rem;
}
.fecho-estudo .sub { font-family: var(--sans); font-size: .9rem; color: var(--tinta-2); margin: 0 0 .6rem; }
.fecho-estudo .aviso { font-family: var(--sans); font-size: .86rem; color: var(--perigo); margin: 0 0 .6rem; }
.fecho-estudo .passagem, #ressonancia .escolhida {
  margin: 0 0 .5rem; padding: .4rem .8rem; border-left: 3px solid var(--acento);
  font-family: var(--corpo); font-size: .96rem; line-height: 1.55; color: var(--tinta);
}
.fecho-estudo .frase { font-family: var(--corpo); font-style: italic; color: var(--tinta-2); margin: 0 0 .6rem; }
/* O parágrafo tocado, enquanto o painel está aberto. Contorno e não fundo: o
   fundo é dos destaques, e confundir os dois faria a escolha parecer marcação. */
.prosa .passagem-escolhida { outline: 2px solid var(--acento); outline-offset: 4px; border-radius: 4px; }
#ressonancia .dica { font-family: var(--sans); font-size: .88rem; color: var(--tinta-2); margin: 0 0 .7rem; }

/* ── O juízo da parte: um toque, três palavras  (03/09) ────────────────────
   O instrumento que transforma a reclamação verbal num dado. Discreto de
   propósito: é pergunta de saída, não parte do estudo. */
.juizo-parte {
  display: flex; align-items: center; gap: .5rem; flex-wrap: wrap;
  margin: 1.6rem auto 0; max-width: var(--measure);
  font-family: var(--sans);
}
.juizo-parte .rotulo { font-size: .78rem; color: var(--tenue); }
.juizo-parte .btn { font-size: .78rem; padding: .2rem .6rem; min-height: 0; }
.juizo-parte .btn.ativo { border-color: var(--cromo-acento); color: var(--cromo-acento); }

/* ── A trilha ───────────────────────────────────────────────────────────── */
/* ── A coluna, quando a marginália liga a GRADE  (03/09) ───────────────────
   Com `data-marginalia="sim"`, `body[data-leitura] main` vira uma grade de
   duas colunas: o texto e a margem. A grade espera DOIS filhos — a folha e o
   painel —, e a rota do estudo acrescenta outros: a trilha e a antessala.
   Sem dizer a coluna, o segundo filho cai na coluna da MARGEM, e foi o que
   apareceu no Mac: a trilha à esquerda e o título do estudo espremido na
   faixa da direita.
   Os três pertencem à coluna do texto, e é isso que a linha abaixo declara —
   inofensiva quando não há grade nenhuma. */
.trilha, .antessala, .erro-estudo { grid-column: 1; }

.trilha { max-width: var(--measure); margin: .4rem auto 1.2rem; padding-inline: 1.1rem; }
.trilha ol {
  list-style: none; margin: 0; padding: 0;
  /* `align-items: center`: metade dos passos é `<button>` e metade é `<span>`,
     e os dois têm linhas de base diferentes — sem isto a trilha sai em
     degraus, com «Início» acima de «Pré». A captura de 03/09 mostrou.  */
  display: flex; flex-wrap: wrap; align-items: center; gap: .3rem .45rem;
  font-family: var(--sans); font-size: .74rem;
}
.trilha .passo { display: flex; }
.trilha .passo > span, .trilha .passo > button {
  display: block; padding: .18rem .5rem; border-radius: 999px;
  border: 1px solid var(--papel-borda-fina); background: none;
  color: var(--tenue); font: inherit; line-height: 1.5;
}
.trilha .passo > button { cursor: pointer; }
/* O ponto diz «esta parte já tem perguntas escritas» — o que antes custava uma
   pastilha inteira ao lado. `currentColor` para acender junto com a pastilha
   quando ela é a corrente. */
.trilha .ponto {
  display: inline-block; width: 4px; height: 4px; border-radius: 50%;
  background: currentColor; opacity: .55; margin-left: .3rem; vertical-align: middle;
}
.trilha .passo.pronto > span, .trilha .passo.pronto > button {
  color: var(--tinta-2); border-color: var(--regra);
}
/* O laboratório ainda não montado (spec 51, 14/09): o tracejado diz «opcional,
   ainda não existe» sem apagar a porta. Antes de `.atual`/`.lendo`, que vencem
   por cima quando coincidem. A borda é `--tenue` e não `--regra`: no claro e
   no sépia a `--regra` some contra o papel, e o tracejado — que É o sinal —
   desaparecia (captura do harness, 14/09). */
.trilha .passo.opcional > span, .trilha .passo.opcional > button {
  border-style: dashed; border-color: var(--tenue); color: var(--tinta-2);
}
/* `.atual` = onde o ESTUDO está (o cursor). Campo cheio: é o que se vê de
   longe, e responde «até onde eu cheguei». */
.trilha .passo.atual > span, .trilha .passo.atual > button {
  background: var(--acento); color: var(--sobre-acento); border-color: transparent; font-weight: 600;
}
/* `.lendo` = o documento em CENA. Anel, não campo: são duas perguntas
   diferentes («até onde cheguei» e «onde estou agora») e elas caem na mesma
   pastilha na maior parte do tempo — dois campos cheios seriam a mesma tinta
   dizendo duas coisas. O anel se lê por cima do campo quando coincidem. */
.trilha .passo.lendo > button, .trilha .passo.lendo > span {
  border-color: var(--acento); color: var(--acento); font-weight: 600;
  box-shadow: 0 0 0 1px var(--acento);
}
.trilha .passo.lendo.atual > button, .trilha .passo.lendo.atual > span {
  color: var(--sobre-acento);
  box-shadow: 0 0 0 2px var(--papel), 0 0 0 3px var(--acento);
}

/* ── A ESCRIVANINHA: a ficha de estudo  (03/09) ────────────────────────────
   A lista era texto cru sobre a mesa. Ao lado do cartão da inbox e das
   lombadas da estante ela parecia um rascunho — e era, no sentido literal de
   nunca ter recebido desenho.

   A ficha herda o que dá coerência ao app (a lombada de 3px na matiz do tema,
   o título em serifa, a sobrancelha do cluster) e acrescenta o que só ela tem:
   a RÉGUA DAS PARTES. É o que responde de longe a pergunta que traz alguém a
   esta tela — «onde eu parei?» — sem precisar abrir nada.
   ═════════════════════════════════════════════════════════════════════════ */
.cabeca-escrivaninha { max-width: var(--measure); margin: 0 auto .2rem; padding: 0 1.1rem; }

.caderno, .prateleira-estudos { max-width: var(--measure); margin: 0 auto 2.2rem; padding: 0 1.1rem; }
/* ── O caderno recolhe  (08/09) ─────────────────────────────────────────────
   O cabeçalho do caderno é um `<summary>`: recolhido, o caderno é UMA linha
   e a prateleira vira a lista dos livros; expandido, as fichas descem. O
   triângulo e o marcador são os dos grupos da página de destaques. Recolhido,
   a margem encolhe — dez livros recolhidos têm de caber numa tela. */
.caderno:not([open]) { margin-bottom: .35rem; }
.caderno > summary, .prateleira-estudos > h2 {
  font-family: var(--sans); font-size: .78rem; font-weight: 600;
  letter-spacing: .08em; text-transform: uppercase; color: var(--tenue);
  margin: 0 0 .5rem; display: flex; align-items: baseline; gap: .5rem;
}
.caderno > summary {
  list-style: none; cursor: pointer; padding: .55rem 0;
  min-height: var(--alvo);
  border-bottom: 1px solid var(--regra);
  -webkit-tap-highlight-color: transparent;
}
.caderno > summary::-webkit-details-marker { display: none; }
.caderno > summary::before {
  content: "▸"; color: var(--tinta-2); font-size: .8em; align-self: center;
  transition: transform var(--dur-rapida) var(--curva);
}
.caderno[open] > summary::before { transform: rotate(90deg); }
.caderno[open] > summary { border-bottom-color: transparent; }
.caderno > summary:focus-visible { outline: 2px solid var(--foco); outline-offset: 2px; border-radius: 6px; }
/* O nome do caderno é o nome de um LIVRO: serifa, caixa normal — ele não é um
   rótulo de seção como «na mesa», é um título. */
.caderno > summary .nome {
  font-family: var(--corpo); font-size: 1.12rem; font-weight: 600;
  letter-spacing: 0; text-transform: none; color: var(--tinta);
}
.caderno > summary .conta, .prateleira-estudos > h2 .conta {
  margin-left: auto; white-space: nowrap; font-variant-numeric: tabular-nums;
  font-size: .74rem; color: var(--tenue); letter-spacing: 0; text-transform: none;
}
.fichas { list-style: none; margin: 0; padding: 0; }
/* A ENCADERNAÇÃO: um filete que atravessa os capítulos do mesmo livro. É o que
   uma pilha de capítulos tem e uma lista de avulsos não tem. */
.fichas.encadernadas { border-left: 2px solid var(--papel-borda); padding-left: .9rem; margin-left: .2rem; }

.ficha {
  position: relative; display: flex; align-items: stretch; gap: .6rem;
  background: var(--papel-elev); border: 1px solid var(--papel-borda-fina);
  border-radius: 14px; box-shadow: var(--sombra-erguida);
  margin-bottom: .8rem; overflow: hidden;
}
/* A lombada, na matiz do tema — a mesma do cartão da inbox: duas telas que
   mostram o mesmo acervo não podem discordar de cor. */
.ficha::before {
  content: ""; position: absolute; left: 0; top: 0; bottom: 0;
  width: 3px; background: var(--t, var(--acento));
}
.ficha .alvo {
  flex: 1 1 auto; min-width: 0; display: block;
  padding: .9rem 1rem .9rem 1.1rem; text-decoration: none; color: inherit;
}
.ficha .tema {
  display: block; font-family: var(--sans); font-size: .7rem; font-weight: 600;
  letter-spacing: .1em; text-transform: uppercase; color: var(--t, var(--tenue));
  margin-bottom: .3rem;
}
.ficha .titulo {
  display: block; font-family: var(--corpo); font-size: 1.06rem; line-height: 1.3;
  color: var(--tinta); margin-bottom: .15rem;
}
.ficha .autor { display: block; font-family: var(--sans); font-size: .82rem; color: var(--tenue); }
/* A legenda do MODO do estudo (spec 73 §5.10): a cor e a sobrancelha são do
   livro, e o modo — que pode ser de outro tema — é texto miúdo, em `--tinta-2`
   (e não em `--tenue`, que já é a voz do autor logo acima), sem matiz: pintá-lo
   com a cor do tema do modo poria duas cores de tema na mesma ficha. */
.ficha .modo-estudo {
  display: block; margin-top: .45rem;
  font-family: var(--sans); font-size: .78rem; color: var(--tinta-2);
}

/* ── A régua das partes ───────────────────────────────────────────────────
   Um traço por parte, e não uma barra contínua: o estudo não anda em
   porcentagem, anda em ETAPAS, e uma barra mentiria sobre a granularidade. */
.ficha .percurso { display: flex; align-items: center; gap: .6rem; margin-top: .7rem; }
.ficha .regua { display: flex; gap: 3px; flex: none; }
.ficha .regua i {
  display: block; width: 16px; height: 4px; border-radius: 2px;
  background: var(--regra);
}
.ficha .regua i.feita { background: var(--t, var(--acento)); }
.ficha .regua i.corrente { background: var(--acento); box-shadow: 0 0 0 2px var(--papel-elev), 0 0 0 3px var(--acento); }
.ficha .estado {
  font-family: var(--sans); font-size: .8rem; font-weight: 600; color: var(--acento);
}
.ficha.concluida .estado { color: var(--tenue); font-weight: 500; }

.ficha .acoes { flex: none; display: flex; align-items: center; gap: .3rem; padding-right: .8rem; }
.ficha .acoes .redondo { width: 29px; height: 29px; min-height: 0; font-size: .8rem; }
/* O caderno é o gesto DISCRETO da ficha: o ✕ apaga um estudo inteiro e este só
   muda o arco a que ele pertence. Sem contorno até o toque ou o foco. */
.ficha .acoes .caderno-de { border-color: transparent; background: transparent; color: var(--tenue); }
.ficha .acoes .caderno-de:hover, .ficha .acoes .caderno-de:focus-visible {
  border-color: var(--papel-borda); color: var(--tinta);
}
.ficha .aviso-estado {
  flex-basis: 100%; font-family: var(--sans); font-size: .8rem;
  color: var(--perigo); margin: 0; padding: 0 1rem .8rem 1.1rem;
}

/* ── Os painéis: da família do `#nota` ──────────────────────────────────── */
#respostas .enunciado, #calibrar .titulo, #ressonancia .titulo, #escrivaninha .titulo {
  font-family: var(--sans); font-weight: 600; font-size: 1rem; color: var(--tinta);
  margin: 0 0 .8rem; line-height: 1.4;
}
/* ── O miolo rola; a linha de botões fica  (L-81) ─────────────────────────
   O `.sheet` é uma coluna flexível com teto de altura, e sem um filho que
   role o excedente escapa da caixa: a correção de uma resposta aberta
   desenhava por cima da página e empurrava os botões para fora da tela. É a
   mesma regra dos turnos do `#conversa` e da lista do `⋯`. */
#respostas .corpo-resposta {
  flex: 1 1 auto; min-height: 0; overflow-y: auto;
  /* Espaço para o anel de foco do campo e das alternativas, que é desenhado
     para fora da borda e seria cortado pelo `overflow`. */
  padding-inline: 2px; margin-inline: -2px;
}
/* O código e o negrito que o modelo escreve. `code` numa medida menor porque
   a fonte monoespaçada desenha maior no mesmo corpo — sem isto, `/wps` fica
   mais alto que a frase em volta. */
#respostas code {
  font-family: var(--mono, ui-monospace, SFMono-Regular, Menlo, monospace);
  font-size: .88em; background: var(--papel-elev-2); border-radius: 4px;
  padding: .05em .3em;
}
/* O termo em jogo, dentro do enunciado. O enunciado inteiro já é seminegrito,
   então um `<strong>` ali não se distingue de nada — na captura de 03/09 as
   duas palavras marcadas pelo modelo sumiam no meio da frase. O acento é a
   marca que este app usa para «é disto que se trata», e mede 8,69 : 1 no
   claro (8,43 sépia, 7,78 escuro) sobre o papel do painel. */
#respostas .enunciado strong { color: var(--acento); }
#respostas .passo-resposta {
  font-family: var(--sans); font-size: .74rem; letter-spacing: .06em;
  text-transform: uppercase; color: var(--tenue); margin: 0 0 .4rem;
}
/* ── A questão aberta de um quiz antigo  (spec 51 §7) ─────────────────────
   A caixa de texto saiu com a questão aberta. A que ficou gravada se LÊ: o que
   o leitor escreveu vai como citação, e a pendente diz que não se responde
   mais — sem campo e sem botão. */
#respostas .resposta-escrita {
  margin: 0; padding: .5rem .8rem; border-left: 3px solid var(--regra);
  font-family: var(--corpo); font-size: .96rem; line-height: 1.55; color: var(--tinta-2);
}
#respostas .questao-antiga { margin: 0; font-family: var(--sans); font-size: .88rem; color: var(--tenue); }
/* ── A tabela do «ler o dado» e o fundamento  (spec 54) ─────────────────────
   A tabela ROLA na horizontal dentro do painel: no telefone, cinco colunas
   não cabem, e a página não pode ganhar rolagem lateral por causa dela. */
#respostas .tabela-rola { overflow-x: auto; margin: .2rem 0 .6rem; }
/* O corpo é o das alternativas (.92rem, em rem): em `em` ela herdava o corpo
   da página e saía maior que o texto das opções — visto na captura de 16/09. */
#respostas .tabela-questao { border-collapse: collapse; font-family: var(--sans); font-size: .92rem;
  line-height: 1.35; min-width: 100%; font-variant-numeric: tabular-nums lining-nums; }
#respostas .tabela-questao th,
#respostas .tabela-questao td { padding: .3rem .6rem; border-bottom: 1px solid var(--regra); text-align: left; }
#respostas .tabela-questao th { color: var(--tinta); font-weight: 600; vertical-align: bottom; }
#respostas .fundamento { margin-top: .5rem; }
#respostas .alternativas { display: flex; flex-direction: column; gap: .4rem; }
#respostas .alternativa {
  text-align: left; font-family: var(--sans); font-size: .92rem; line-height: 1.45;
  padding: .6rem .7rem; border: 1px solid var(--regra); border-radius: 10px;
  background: var(--papel); color: var(--tinta); cursor: pointer;
}
#respostas .alternativa b { color: var(--acento); margin-right: .4rem; }
/* ── ORDENAR  (spec 51 §4.4) ──────────────────────────────────────────────
   Toque, não arraste: ↑ e ↓ em cada item, com 44px de alvo cada. Respondida, a
   borda diz se o item ficou no lugar (acento) ou fora dele (perigo), e a
   explicação do que ficou fora vem na devolutiva, embaixo. */
#respostas .ordenar { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: .4rem; }
#respostas .item-ordenar {
  display: flex; align-items: center; gap: .5rem; padding: .2rem .25rem .2rem .7rem;
  border: 1px solid var(--regra); border-radius: 10px; background: var(--papel);
  font-family: var(--sans); font-size: .92rem; line-height: 1.45; color: var(--tinta);
}
#respostas .item-ordenar .pos { min-width: 1.1em; font-weight: 600; color: var(--acento); }
#respostas .item-ordenar .texto { flex: 1 1 auto; padding-block: .4rem; }
#respostas .item-ordenar .mover { display: flex; gap: .25rem; flex: 0 0 auto; }
#respostas .item-ordenar button {
  min-width: 44px; min-height: 44px; padding: 0;
  border: 1px solid var(--regra); border-radius: 8px; background: var(--papel-elev-2);
  color: var(--tinta); font-size: 1.05rem; cursor: pointer;
}
#respostas .item-ordenar button:disabled { opacity: .35; cursor: default; }
#respostas .item-ordenar[data-lugar="certo"] { border-color: var(--acento); }
#respostas .item-ordenar[data-lugar="errado"] { border-color: var(--perigo); }
#respostas .conferir { margin: .7rem 0 0; }
/* ── O descarte do verificador, e o `menos`  (spec 51 §4.3, §4.4) ─────────
   Uma linha que se abre: o número vem à vista, e o motivo de cada questão sob
   o toque. Tinta secundária, e não a do perigo: não é erro do leitor nem do
   app — é a régua funcionando. O `summary` é o alvo, com 44px. */
.descartadas {
  margin: 0 0 .8rem; padding: 0 .7rem; border: 1px solid var(--regra); border-radius: 10px;
  font-family: var(--sans); font-size: .86rem; color: var(--tinta-2); background: var(--papel);
}
.descartadas summary { min-height: 44px; display: flex; align-items: center; cursor: pointer; }
.descartadas ul { margin: 0 0 .6rem; padding-left: 1.1rem; }
.descartadas li + li { margin-top: .4rem; }
.descartadas .enunciado-descartado { display: block; color: var(--tinta); }
.descartadas .motivo { display: block; font-size: .82rem; }
/* O quiz que ficou vazio: o aviso mora na coluna do texto, abaixo da trilha. */
.quiz-vazio { max-width: 46rem; margin: 0 auto 1rem; padding-inline: 1rem; }
.quiz-vazio .sub { font-family: var(--sans); font-size: .9rem; color: var(--tinta-2); margin: 0 0 .6rem; }
#respostas .menos {
  margin: 0 0 .8rem; font-family: var(--sans); font-size: .86rem; color: var(--tinta-2);
}
#respostas .fora-de-lugar { margin: .5rem 0 0; padding-left: 1.1rem; font-size: .9rem; }
#respostas .fora-de-lugar li + li { margin-top: .3rem; }
#respostas .alternativa[data-escolhida="sim"] { border-color: var(--acento); }
#respostas .feedback {
  margin-top: .8rem; padding: .7rem .8rem; border-radius: 10px;
  background: var(--papel-elev-2); font-family: var(--corpo);
  font-size: .94rem; line-height: 1.55; color: var(--tinta);
}
/* A marca vive DENTRO do parágrafo (ver o `desenhar` do painel): inline, ela
   abre a primeira linha do texto em vez de ocupar uma linha só para si. */
#respostas .feedback .marca { font-size: 1.1rem; margin-right: .4rem; font-weight: 600; }
#respostas .feedback.rcerto .marca { color: var(--acento); }
#respostas .feedback.rerrado .marca { color: var(--perigo); }
#respostas .feedback p { margin: 0; }
/* A rubrica só aparece DEPOIS da resposta — antes dela, o servidor nem a
   manda (a projeção do §3.2). Esta regra desenha o que já chegou; não é ela
   que esconde. */
#respostas .feedback .rubrica {
  margin-top: .5rem; font-size: .86rem; color: var(--tinta-2);
}
#respostas .linha, #calibrar .botoes, #ressonancia .botoes, #escrivaninha .botoes {
  display: flex; align-items: center; gap: .5rem; margin-top: .9rem;
}
#respostas .linha .sub, #calibrar .botoes .sub, #ressonancia .botoes .sub {
  flex: 1 1 auto; font-size: .82rem; color: var(--tenue);
}

/* ── Calibrar e enviar ─────────────────────────────────────────────────── */
#calibrar .campo, #ressonancia .campo, #escrivaninha .opcao {
  display: block; font-family: var(--sans); font-size: .84rem; color: var(--tinta-2);
  margin-bottom: .8rem;
}
#calibrar select, #calibrar input[type="text"], #ressonancia input[type="text"],
#escrivaninha select, #escrivaninha input[type="text"] {
  display: block; width: 100%; margin-top: .3rem;
  font-family: var(--sans); font-size: .95rem; color: var(--tinta);
  background: var(--papel); border: 1px solid var(--regra); border-radius: 10px;
  padding: .5rem .6rem;
}
/* ── A lente do técnico  (spec 51 §2) ─────────────────────────────────────
   Duas opções com uma linha cada. A opção INTEIRA é o alvo (o `<label>`), com
   44px de piso: o círculo do rádio sozinho tem 13px e não se acerta com o
   dedo no iPad. A escolhida ganha a borda do acento — a mesma marca da
   alternativa escolhida no quiz. */
#calibrar fieldset.campo { border: 0; padding: 0; margin: 0 0 .8rem; min-width: 0; }
/* O `display: block` do `.campo` vence o `[hidden]` do navegador, e o campo
   que não se aplica ficava na tela: o técnico mostrava «Modo: Catequético»
   (visto na captura de 14/09), e mostraria a lente no filosófico. */
#calibrar .campo[hidden] { display: none; }
#calibrar fieldset.campo legend { padding: 0; margin-bottom: .3rem; }
#calibrar .lente {
  display: flex; align-items: flex-start; gap: .6rem; min-height: 44px;
  box-sizing: border-box; padding: .55rem .7rem; margin-top: .35rem;
  border: 1px solid var(--regra); border-radius: 10px; background: var(--papel);
  color: var(--tinta); cursor: pointer;
}
#calibrar .lente:has(input:checked) { border-color: var(--acento); }
#calibrar .lente input { margin: .2rem 0 0; accent-color: var(--acento); }
#calibrar .lente b { display: block; font-size: .95rem; font-weight: 600; }
#calibrar .lente .linha-lente { display: block; font-size: .84rem; color: var(--tinta-2); line-height: 1.4; }
/* A folha em dois níveis é a mais alta das folhas (spec 73 §5.6): os cinco
   temas em três fileiras e até três modos com linha. O corpo rola
   (`.corpo-sheet`) e o «Começar» fica no pé; o teto sobe para quase a tela
   inteira, para que num iPhone pequeno se role o mínimo. Medido a 375 × 667
   com Fé e Filosofia: o conteúdo pede ~800px, e 70vh davam 465. */
#calibrar {
  max-height: min(calc(100vh - 5.5rem), 40rem);
  max-height: min(calc(100dvh - 5.5rem), 40rem);
}
/* Artes e Vida tem um modo só (spec 73 §5.6): o mesmo cartão, sem rádio e sem
   cursor de toque — é texto, não escolha. */
#calibrar .modo-unico { margin: .35rem 0 0; cursor: default; }
/* A linha «Isto muda só o estudo» fica colada à fileira de temas. */
#calibrar #campo-tema .dica { display: block; margin: .4rem 0 0; }

/* ── A lista do combobox  (03/09) ────────────────────────────────────────
   Ela nasce e some conforme o que se digita, e por isso mora DENTRO do fluxo
   do painel, e não flutuando por cima: um menu absoluto sobre um sheet que já
   é `position: fixed` teria de repetir a conta de posição do pai a cada
   tecla — e erraria no iPad, onde o teclado muda a altura útil no meio da
   digitação. No fluxo, quem resolve é o navegador. */
#escrivaninha #caderno-lista {
  list-style: none; margin: .1rem 0 .6rem; padding: 0;
  max-height: 9rem; overflow-y: auto;
  border: 1px solid var(--regra); border-radius: 10px; background: var(--papel);
}
#escrivaninha #caderno-lista li {
  display: flex; align-items: center; justify-content: space-between; gap: .6rem;
  padding: .45rem .7rem; cursor: pointer;
  font-family: var(--sans); font-size: .92rem; color: var(--tinta);
}
#escrivaninha #caderno-lista li + li { border-top: 1px solid var(--papel-borda-fina); }
#escrivaninha #caderno-lista li:hover,
#escrivaninha #caderno-lista li[aria-selected="true"] { background: var(--papel-elev-2); }
#escrivaninha #caderno-lista .conta { font-size: .8rem; color: var(--tenue); }
/* A dica diz o que o «Enviar» VAI fazer — antes de ele fazer. É a diferença
   entre um campo que aceita qualquer coisa e um que declara a consequência. */
#escrivaninha #caderno-dica { min-height: 1.1em; }

#escrivaninha .opcao { display: flex; align-items: center; gap: .5rem; font-size: .95rem; color: var(--tinta); }
#escrivaninha .alvo { font-family: var(--corpo); color: var(--tinta-2); margin: 0 0 .9rem; }
#calibrar .dica, #escrivaninha .dica { font-size: .82rem; color: var(--tenue); margin: 0 0 .8rem; }
#escrivaninha .aviso { font-size: .84rem; color: var(--perigo); margin: .6rem 0 0; }
/* A primária é a exceção deliberada: ela veste o ACENTO do papel, em campo
   cheio, e é assim que se distingue das irmãs agora que as irmãs são grafite.
   Um sheet em que todos os botões são cromo não tem ação primária nenhuma. */
.btn.primario { background: var(--acento); color: var(--sobre-acento); border-color: transparent; font-weight: 600; }

/* ── Os callouts do estudo ─────────────────────────────────────────────────
   A pipeline da ingestão já converte `> [!important]` em
   `blockquote.callout.callout-important` (é o que a skill `enviar-leitor`
   produz há meses), e até aqui o app não os desenhava: a ideia-mestra de uma
   parte, que é o elemento de maior peso do estudo, saía como uma citação
   comum. Estas regras valem para TODO artigo do vault que use callout, e não
   só para o estudo — é a mesma marcação. */
.prosa blockquote.callout {
  border-left: 3px solid var(--acento);
  background: var(--papel-elev-2);
  padding: .8rem 1rem; border-radius: 0 10px 10px 0; margin: 1.4rem 0;
  font-style: normal;
}
.prosa blockquote.callout p:first-child { margin-top: 0; }
.prosa blockquote.callout p:last-child { margin-bottom: 0; }
/* ── `inline-block`, e NUNCA `block`  (05/09) ──────────────────────────────
   Este rótulo era `display: block`, e com isso o `::highlight()` da leitura
   falada **parava de pintar o parágrafo inteiro** no WebKit: um filho inline
   que vira bloco parte o `<p>` em blocos anônimos, e o realce da frase e o da
   palavra somem de tudo que vem depois. O dono leu a caixa inteira com a voz
   e sem marca nenhuma — «depois que saiu da caixa funcionou normal».

   Nada no DOM denuncia: o `Highlight` fica registrado, os ranges resolvem, o
   seletor casa. O observável é o pixel, e é o que `npm run design` mede agora.

   `inline-block` com `width: 100%` dá a MESMA quebra de linha e mantém o
   `margin-bottom` (que um inline puro ignoraria), sem partir o parágrafo: o
   átomo inline não cria bloco anônimo. Vale para qualquer filho inline da
   `.prosa` — dentro de texto que se narra, `display: block` é proibido. */
.prosa blockquote.callout strong:first-child {
  font-family: var(--sans); font-size: .78rem; letter-spacing: .06em;
  text-transform: uppercase; color: var(--acento);
  display: inline-block; width: 100%; margin-bottom: .3rem;
}
/* A passagem verbatim é a única que continua parecendo CITAÇÃO: ela é a voz do
   texto original dentro do estudo, e igualá-la à ideia-mestra apagaria a
   diferença entre o que o autor disse e o que o tutor concluiu. */
.prosa blockquote.callout-quote {
  border-left-color: var(--regra); background: none;
  font-family: var(--corpo); font-style: italic;
}
/* `--tinta`, e não uma tinta secundária: este rótulo vive DENTRO da `.prosa`,
   que é destacável, e os quatro `--hl-*` foram calibrados contra `--tinta`
   (nucleo.test). Quem separa o micro-contexto do corpo da citação é o tamanho
   e o espacejamento, não a cor — que é o que a regra da prosa obriga. */
.prosa blockquote.callout-quote strong:first-child { color: var(--tinta); font-style: normal; opacity: .75; }

/* ── Os desenhos do arquiteto: trade-off e quadro de falhas  (spec 51 §3.4) ──
   O servidor os entrega como tabela DENTRO de um callout (`recursos.mjs`),
   porque `callout-*` é a única classe que o sanitizador deixa o conteúdo
   carregar. Só tokens: é o que os faz valer nos três temas sem uma regra por
   tema. A borda do acento vira regra neutra no trade-off — ele não é a
   ideia-mestra, e duas caixas com a mesma marca disputariam a atenção —, e o
   quadro de falhas leva a cor do perigo, que é do que ele fala. */
.prosa blockquote.callout-tradeoff,
.prosa blockquote.callout-falhas { border-left-color: var(--regra); padding-bottom: .5rem; }
.prosa blockquote.callout-falhas { border-left-color: var(--perigo); }
.prosa blockquote.callout-tradeoff table,
.prosa blockquote.callout-falhas table { margin: .2rem 0 0; font-family: var(--sans); font-size: .88em; }
/* A primeira coluna é o NOME (a opção, a falha): é por ela que a linha se lê. */
.prosa blockquote.callout-tradeoff td:first-child,
.prosa blockquote.callout-falhas td:first-child { font-weight: 600; color: var(--tinta); }
/* Nas células do trade-off cabe uma palavra ou um sinal: centradas, a coluna
   se compara de relance, que é para o que a grade existe. */
.prosa blockquote.callout-tradeoff th:not(:first-child),
.prosa blockquote.callout-tradeoff td:not(:first-child) { text-align: center; }
.prosa blockquote.callout-tradeoff tr:last-child td,
.prosa blockquote.callout-falhas tr:last-child td { border-bottom: 0; }

/* ── A espinha da parte do arquiteto  (spec 51 §3.2) ──────────────────────
   problema → forças → (as seções) → alternativas → premissas → limite. Cada
   elo é um callout com classe própria (`montar.mjs`), e a folha os distingue
   só por borda, com tokens: o problema e as premissas são contexto (regra
   neutra), as forças são o miolo da decisão (o acento, como a ideia-mestra), e
   o limite é onde o desenho quebra — a cor do perigo, como o quadro de falhas.
   A lista dentro do callout perde a margem de cima: o título já separa. */
.prosa blockquote.callout-problema,
.prosa blockquote.callout-premissas { border-left-color: var(--regra); }
.prosa blockquote.callout-forcas { border-left-color: var(--acento); }
.prosa blockquote.callout-limite { border-left-color: var(--perigo); }

/* ── As caixas do Concurso  (spec 54 §2.2) ──────────────────────────────────
   «Cai assim» é o que a banca cobra: o acento, como a ideia-mestra. A
   «pegadinha» é onde a banca derruba: a cor do perigo, como o limite do
   arquiteto. Só a borda muda; o corpo é o de todo callout. */
.prosa blockquote.callout-cai { border-left-color: var(--acento); }
.prosa blockquote.callout-pegadinha { border-left-color: var(--perigo); }
/* O nome da força (e de qualquer item em negrito numa lista de callout) é o
   PRIMEIRO `strong` do `li`, e a regra do rótulo acima o pegava: caixa alta, no
   acento e em bloco, com a linha da força solta embaixo — visto na captura de
   14/09. Dentro de `li` o negrito volta a ser negrito de texto. `inline`, e
   não `block`: dentro da prosa narrada, bloco apaga o realce da voz. */
.prosa blockquote.callout li strong:first-child {
  display: inline; width: auto; margin: 0; font-family: inherit; font-size: inherit;
  letter-spacing: normal; text-transform: none; color: var(--tinta);
}
.prosa blockquote.callout-forcas ul,
.prosa blockquote.callout-premissas ul { margin-top: .2rem; margin-bottom: 0; }

/* ── «Há uma versão nova»  (03/09) ─────────────────────────────────────────
   No pé, e não no topo: o topo é onde o título do que se lê mora, e uma tarja
   ali empurra a primeira linha do texto. Acima da barra de navegação do modo
   estreito, para não cobrir os destinos. */
/* ── Refeita em UMA linha, centrada sem `left: 50%`  (17/09) ───────────────
   A de 04/09 quebrava em duas linhas e o Yuri a achou feia em todo lugar, pior
   no iPhone. O defeito de fundo não era a frase: era `left: 50%` com
   `translateX(-50%)`. Uma caixa fixa sem largura declarada encolhe até caber
   no espaço entre o `left` e a borda direita — METADE da tela. Num iPhone de
   393px ela media 200px, e o `flex-wrap` de 04/09 só escolheu onde quebrar.

   Agora: `left: 0; right: 0; margin-inline: auto` com `width: fit-content`
   centra usando a tela inteira como limite; frase curta, sem quebra; pílula de
   verdade (é sempre uma linha); o ✕ é um ícone sem cromo, e não um quadrado
   escuro de gradiente, que no sépia parecia uma tecla solta. Os dois alvos
   continuam com os 44px do `--alvo`. Se a tela for estreita demais (320px), a
   frase cede com reticências antes de os botões cederem. */
#versao-nova {
  position: fixed; z-index: 80;
  left: 0; right: 0; margin-inline: auto;
  width: fit-content; max-width: calc(100% - 2rem); box-sizing: border-box;
  bottom: calc(var(--barra-h, 0px) + 1rem + env(safe-area-inset-bottom));
  display: flex; align-items: center; flex-wrap: nowrap; gap: .35rem;
  padding: 4px 4px 4px 1.1rem; border-radius: 999px;
  background: var(--papel-elev); border: 1px solid var(--regra);
  box-shadow: 0 1px 2px rgba(0,0,0,.08), 0 10px 30px rgba(0,0,0,.18);
  font-family: var(--sans); font-size: .88rem; color: var(--tinta);
}
#versao-nova > span {
  flex: 0 1 auto; min-width: 0; margin-right: .4rem;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
#versao-nova > button {
  flex: none; height: var(--alvo, 44px); border: 0; border-radius: 999px;
  font: inherit; cursor: pointer;
}
#versao-nova #versao-recarregar {
  padding: 0 1.1rem;
  background: var(--acento); color: var(--sobre-acento); font-weight: 600;
}
#versao-nova #versao-depois {
  width: var(--alvo, 44px); padding: 0;
  display: grid; place-items: center;
  background: transparent; color: var(--tenue);
}
#versao-nova #versao-recarregar:hover { filter: brightness(1.06); }
#versao-nova #versao-depois:hover { color: var(--tinta); background: color-mix(in srgb, var(--tinta) 8%, transparent); }
#versao-nova > button:focus-visible { outline: 2px solid var(--acento); outline-offset: 2px; }
/* Lendo no telefone há DUAS barras no pé: a de abas e, acima dela, a fileira
   de controles da leitura. Pousada só acima da primeira, a tarja cobria a
   segunda inteira — o ⏸, o Aa e o progresso sumiam debaixo dela. Visto no
   Safari do iPhone simulado em 17/09; o Chrome emulado não montava a cena.
   `--pilha-y` já é a soma das duas no arranjo em barra. */
body[data-leitura][data-arranjo="barra"] #versao-nova {
  bottom: calc(var(--pilha-y) + .75rem);
}
@media (min-width: 1100px) and (pointer: fine) {
  /* No Mac a navegação é lateral: a tarja desce para o canto e não disputa o
     centro com a coluna de leitura. */
  #versao-nova { left: auto; right: 1.2rem; margin-inline: 0; bottom: 1.2rem; }
}

/* ── A língua da conta: a tarja e o globo  (spec 72 §5.1, plano B4) ─────────
   A tarja é a irmã da «Versão nova»: a mesma pílula no pé, porque as duas
   dizem a mesma coisa — «a tela muda quando você recarregar» — e duas formas
   para uma frase seriam duas coisas a aprender. `#lingua-aviso` e não uma
   classe partilhada: a da versão já tem os seus ids nos testes. A da
   confirmação leva um link («Mudar»), que ganha o mesmo alvo de 44px. */
#lingua-aviso {
  position: fixed; z-index: 80;
  left: 0; right: 0; margin-inline: auto;
  width: fit-content; max-width: calc(100% - 2rem); box-sizing: border-box;
  bottom: calc(var(--barra-h, 0px) + 1rem + env(safe-area-inset-bottom));
  display: flex; align-items: center; flex-wrap: nowrap; gap: .35rem;
  padding: 4px 4px 4px 1.1rem; border-radius: 999px;
  background: var(--papel-elev); border: 1px solid var(--regra);
  box-shadow: 0 1px 2px rgba(0,0,0,.08), 0 10px 30px rgba(0,0,0,.18);
  font-family: var(--sans); font-size: .88rem; color: var(--tinta);
}
#lingua-aviso > span {
  flex: 0 1 auto; min-width: 0; margin-right: .4rem;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
#lingua-aviso > button, #lingua-aviso > a {
  flex: none; height: var(--alvo, 44px); border: 0; border-radius: 999px;
  font: inherit; cursor: pointer;
  display: inline-grid; place-items: center; text-decoration: none;
}
#lingua-aviso #lingua-recarregar, #lingua-aviso #lingua-continuar {
  padding: 0 1.1rem;
  background: var(--acento); color: var(--sobre-acento); font-weight: 600;
}
#lingua-aviso #lingua-mudar { padding: 0 .9rem; color: var(--tinta); }
#lingua-aviso #lingua-depois {
  width: var(--alvo, 44px); padding: 0;
  background: transparent; color: var(--tenue);
}
#lingua-aviso > button:focus-visible, #lingua-aviso > a:focus-visible { outline: 2px solid var(--acento); outline-offset: 2px; }
body[data-leitura][data-arranjo="barra"] #lingua-aviso { bottom: calc(var(--pilha-y) + .75rem); }
@media (min-width: 1100px) and (pointer: fine) {
  #lingua-aviso { left: auto; right: 1.2rem; margin-inline: 0; bottom: 1.2rem; }
}

/* O globo do menu: o `<select>` nativo por cima do desenho, transparente. O
   toque abre a lista do sistema; o foco do teclado aparece no globo. */
.lingua-menu {
  position: relative; display: inline-grid; place-items: center;
  width: var(--alvo, 44px); height: var(--alvo, 44px);
  color: inherit; font-size: 1.1rem;
}
.lingua-menu[hidden] { display: none; }
.lingua-menu select {
  position: absolute; inset: 0; width: 100%; height: 100%;
  opacity: 0; cursor: pointer; font-size: 16px; /* 16px: o iOS não dá zoom no toque */
}
.lingua-menu:focus-within { outline: 2px solid var(--acento); outline-offset: 2px; border-radius: 999px; }
/* A cor do globo é a dos vizinhos, nunca a herdada (24/09). Com `inherit`, no
   rodapé da lateral — que é grafite em TODO tema — o globo pegava a tinta do
   corpo: clara no escuro (ficava bom), escura no claro e no sépia (escuro sobre
   escuro, quase invisível). Na barra do telefone ele segue o «Conta». */
.cabeca .lingua-menu { color: var(--tenue); }
.cabeca .lingua-menu:hover, .cabeca .lingua-menu:focus-within { color: var(--acento); }
.nav-rodape .lingua-menu { color: var(--cromo-tenue); width: 28px; height: 28px; }
.nav-rodape .lingua-menu:hover, .nav-rodape .lingua-menu:focus-within { color: var(--cromo-acento); }

/* ═══════════════════════════════════════════════════════════════════════════
   A ESCRIVANINHA — os três blocos que não chegaram a existir  (03/09)
   ═══════════════════════════════════════════════════════════════════════════
   Eles foram escritos e a edição do arquivo não casou o ponto de inserção; o
   resultado, no Mac, foi o painel do «Mais» desenhado pelo NAVEGADOR: bolinhas
   de lista ao lado dos botões, nome e descrição correndo na mesma linha
   («RecomeçarApaga as suas respostas…») e tudo centrado.

   Ficam guardados por teste (`estudo.test.mjs`): uma folha de estilo em que
   uma regra some não falha em lugar nenhum — ela só fica feia, e feio não
   quebra build.
   ═════════════════════════════════════════════════════════════════════════ */

/* ── A antessala: o fundo das etapas que não são documento ────────────────── */
.antessala h1 {
  font-family: var(--corpo); font-size: 1.6rem; line-height: 1.25; margin: 0 0 .3rem;
}
.antessala .autor {
  font-family: var(--sans); font-size: .88rem; color: var(--tenue); margin: 0 0 .8rem;
}
.antessala .sub {
  font-family: var(--sans); font-size: .95rem; color: var(--tinta-2); margin: 0;
}

/* ── O rodapé de uma ETAPA de estudo ──────────────────────────────────────
   Ela é um `ART#` como outro (é o que lhe dá narração e Pencil), mas não é item
   do acervo: não se marca como lida, não vai para a estante e não se manda
   estudar. Fica o que se aplica — de onde veio e para onde voltar. */
.rodape-etapa .procedencia {
  font-family: var(--sans); font-size: .86rem; color: var(--tinta-2);
}

/* ── O «Mais» do estudo: três gestos que apagam coisas diferentes ─────────
   Cada opção diz o que leva junto ANTES da confirmação — é a spec 23 §7 na
   tela, e a razão de eles serem três botões e não um item de menu.

   `list-style: none` não é higiene: sem ele o navegador desenha marcadores ao
   lado de botões. E `<b>`/`<span>` precisam de `display: block`, senão o nome
   e a descrição correm na mesma linha. */
/* ── Quem rola é a LISTA, não o painel — a regra L-81, aplicada aqui ───────
   O painel é uma coluna flexível com teto de altura (`.sheet`, lá em cima), e
   sem `flex`/`overflow` na lista o excedente empurrava a linha do «Cancelar»
   para FORA da caixa: em 03/09 o menu passou de três para cinco opções e a
   captura mostrou o botão pendurado no vazio, por cima da tela de trás.
   Controle que sai do painel é controle que não existe — a mesma frase que o
   `#conversa` já carregava. */
.opcoes-estudo {
  list-style: none; margin: 0 0 .2rem; padding: 0;
  flex: 1 1 auto; min-height: 0; overflow-y: auto;
  /* Os 2px seguram o anel de foco do botão, que é desenhado para fora da
     borda e seria cortado pelo `overflow`. */
  padding-inline: 2px; margin-inline: -2px;
}
.opcoes-estudo li { margin: 0 0 .45rem; }
.opcoes-estudo button {
  display: block; width: 100%; text-align: left; cursor: pointer;
  padding: .75rem .85rem;
  background: var(--papel); border: 1px solid var(--regra); border-radius: 12px;
  font-family: var(--sans); color: var(--tinta);
}
.opcoes-estudo button:hover, .opcoes-estudo button:focus-visible {
  border-color: var(--acento); outline: none;
}
.opcoes-estudo b {
  display: block; font-size: .96rem; font-weight: 600; margin-bottom: .2rem; line-height: 1.3;
}
.opcoes-estudo span {
  display: block; font-size: .84rem; line-height: 1.5; color: var(--tinta-2);
}
.opcoes-estudo .perigo b { color: var(--perigo); }
.opcoes-estudo .perigo:hover, .opcoes-estudo .perigo:focus-visible { border-color: var(--perigo); }
/* O título do painel na serifa, como o dos irmãos: é o nome da coisa, não um
   rótulo de controle. */
#mais-estudo .titulo { font-family: var(--corpo); font-size: 1.15rem; }

/* ── A trilha dentro do `⋯`  (14/09) ───────────────────────────────────────
   A do documento mora no alto dele, e alcançá-la do meio da leitura custava
   subir a página inteira — e gravar o topo como a posição da parte. Aqui ela
   é a MESMA marcação (`montarTrilha`), com as duas marcas de sempre, e só
   muda de tamanho: no alto do texto a pastilha é legenda de 22 px; num painel
   que se abre para tocar, ela é alvo, e alvo tem o `--alvo` do núcleo.
   `max-width`/`margin`/`padding` desfeitos porque os da trilha centram uma
   coluna de leitura, e aqui a coluna é o painel. */
#mais-estudo .ir-para .trilha { max-width: none; margin: .1rem 0 .9rem; padding: 0; }
#mais-estudo .ir-para .trilha ol { font-size: .9rem; gap: .45rem; }
#mais-estudo .ir-para .trilha .passo > button,
#mais-estudo .ir-para .trilha .passo > span {
  min-height: var(--alvo); min-width: var(--alvo); padding: 0 .85rem;
  display: flex; align-items: center; justify-content: center;
}

/* ── A linha dos dois toques do compartilhar  (spec 25 §5.4) ───────────────
   O painel troca a lista por UMA linha — «Montando o estudo… 3 de 7», depois
   «Estudo pronto · 24 KB» com o botão ao lado, ou o motivo da falha. Não é um
   painel novo: é o mesmo `#mais-estudo` com outro conteúdo, porque o gesto
   começou nele e o segundo toque é a continuação do primeiro.

   `min-height` de uma linha para o painel não pular de altura entre as três
   mensagens — o botão «Compartilhar» ficaria dançando sob o dedo. */
#mais-estudo .passo-linha {
  font-family: var(--sans); font-size: .92rem; color: var(--tinta-2);
  margin: .8rem 0 1.2rem; min-height: 1.4em;
}

/* ══ O COLÓQUIO — a conversa falada  (spec 24 §6.1) ═════════════════════════

   Faixa BAIXA, e é isso que faz o recurso: o artigo continua visível e
   rolável atrás, e dá para apontar o parágrafo com o olho enquanto se fala
   dele. Um `.sheet` cheio devolveria o defeito que a bolha flutuante existiu
   para consertar — conversar sobre um texto que não se vê.

   Ancorado como o `#velocidade-painel`: à esquerda da cápsula, pelos mesmos
   tokens de geometria, para que mexer na cápsula mova o painel junto em vez
   de abrir uma segunda conta que precisa concordar com a primeira. */
#coloquio {
  position: fixed; z-index: 60;
  right: calc(var(--capsula-x) + var(--capsula-l) + .6rem);
  /* ── `--pilha-0`, e NÃO `--pilha-y`  (correção da captura, 04/09) ─────────
     A primeira versão usava `--pilha-y`, como o `#velocidade-painel` faz — e
     no Mac isso é o CENTRO da tela, porque a cápsula se centra ali (a regra do
     `@media` acima). A captura mostrou o painel pousado em cima do parágrafo
     que se estava lendo, que é precisamente o defeito que a faixa baixa existe
     para não ter.
     E não é acaso: a linha de leitura desta casa É o meio da tela — é o que
     `segmentosDaLeitura()` mede, pela razão de que «ninguém lê no topo». Um
     painel ancorado no centro cobre exatamente onde o olho está.
     `--pilha-0` é o token que diz «acima do cromo de baixo»: a barra de
     navegação e a pílula do tempo, no modo barra. É o piso certo nos dois
     modos. Anexar a bolha era o instinto; o chão é o requisito. */
  bottom: var(--pilha-0);
  width: min(30rem, calc(100vw - var(--capsula-x) * 2 - var(--capsula-l) - 1.2rem));
  display: flex; flex-direction: column; gap: .5rem;
  padding: .7rem .9rem;
  background: var(--papel-elev); border: 1px solid var(--papel-borda);
  border-radius: var(--raio); box-shadow: var(--sombra-erguida);
  font-family: var(--sans);
  transition: opacity var(--dur) var(--curva), transform var(--dur) var(--curva);
}
/* `visibility`, e não só `opacity`, pelo motivo do `#velocidade-painel`: um
   painel transparente continua sendo parada de teclado e continua sendo lido
   pelo VoiceOver. */
#coloquio[data-aberto="nao"] {
  opacity: 0; visibility: hidden; pointer-events: none; transform: translateX(.5rem);
}

#coloquio .col-cabeca {
  display: flex; align-items: center; gap: .5rem;
}
#coloquio .col-quem {
  font-size: 13px; color: var(--tinta-fraca); flex: 1 1 auto;
}
/* Tabular: o relógio anda a cada segundo, e um dígito de largura variável faz
   a linha inteira tremer — o mesmo motivo do contador da escrivaninha. */
#coloquio .col-tempo {
  font-size: 13px; color: var(--tinta-fraca);
  font-variant-numeric: tabular-nums;
}
#coloquio .btn { flex: 0 0 auto; }

/* A luz é o único mostrador de estado que se lê sem ler. Três cores para três
   coisas, e nenhuma delas é vermelha: vermelho aqui seria confundido com
   gravação, e não se está gravando áudio nenhum (§11). */
#coloquio .col-luz {
  width: 9px; height: 9px; border-radius: 50%; flex: 0 0 auto;
  background: var(--tinta-fraca);
}
#coloquio .col-luz[data-quem="ouvindo"] { background: var(--foco); }
#coloquio .col-luz[data-quem="falando"] { background: var(--foco); opacity: .55; }
#coloquio .col-luz[data-quem="conectando"],
#coloquio .col-luz[data-quem="pensando"],
#coloquio .col-luz[data-quem="encerrando"] { background: var(--tinta-fraca); opacity: .6; }

#coloquio .col-retomada {
  font-size: 12px; color: var(--tinta-fraca);
}
#coloquio .col-retomada[hidden] { display: none; }

/* Três linhas à vista, e não a conversa inteira: isto é conferência — «ela
   entendeu o que eu disse?» —, não histórico. O histórico está gravado. */
#coloquio .col-fala {
  max-height: 7.5rem; overflow-y: auto;
  font-size: 14px; line-height: 1.45;
  border-top: 1px solid var(--regra); padding-top: .5rem;
}
#coloquio .col-linha { margin: 0 0 .4rem; }
#coloquio .col-linha:last-child { margin-bottom: 0; }
#coloquio .col-papel {
  display: inline-block; margin-right: .35rem;
  font-size: 11px; text-transform: uppercase; letter-spacing: .04em;
  color: var(--tinta-fraca);
}
#coloquio .col-linha[data-papel="leitor"] { color: var(--tinta-fraca); }
/* A busca não é fala: é uma MARCA DE PROCEDÊNCIA. Ela se distingue das duas
   vozes porque a pergunta que responde é outra — «isto veio de onde?» — e a
   resposta a essa pergunta é o que sustenta o senso crítico de quem ouve. */
#coloquio .col-linha[data-papel="busca"],
#coloquio .col-linha[data-papel="busca-falhou"] {
  color: var(--tinta-fraca); font-style: italic;
}
#coloquio .col-linha[data-papel="busca"] .col-papel,
#coloquio .col-linha[data-papel="busca-falhou"] .col-papel { color: var(--foco); }
#coloquio .col-vazio { margin: 0; font-size: 13px; color: var(--tinta-fraca); }

/* O aviso NÃO se esconde num cinza discreto: ele existe porque alguma coisa
   não aconteceu, e a lição de 03/09 é que um braço mudo trava quem chamou. */
#coloquio .col-aviso {
  font-size: 13px; line-height: 1.4;
  border-top: 1px solid var(--regra); padding-top: .5rem;
  color: var(--foco);
}
#coloquio .col-aviso[data-tom="nota"] { color: var(--tinta-fraca); }
#coloquio .col-aviso[hidden] { display: none; }

/* ── A transcrição arquivada ───────────────────────────────────────────────
   `.sheet` inteiro, e não faixa: aqui não há sessão viva atrás, e o que se
   quer é ler. */
#transcricao .trans-titulo {
  margin: 0 0 .6rem; font-weight: 600; font-size: 15px;
}
#transcricao .trans-corpo {
  flex: 1 1 auto; overflow-y: auto; min-height: 0;
  font-size: 15px; line-height: 1.6;
}
#transcricao .trans-corpo p { margin: 0 0 .7rem; }
#transcricao .trans-corpo p:last-child { margin-bottom: 0; }

/* ── O status não cabe na linha dos botões  (correção da captura, 04/09) ────
   A `.linha` do `#nota` é `space-between` com um `.sub` curto de um lado
   («pensando…») e os botões do outro. O status daqui é uma FRASE —
   «transcrição crua — a arrumação não completou» —, e na captura ela corria
   por baixo do «Arrumar» e era cortada no meio: o leitor via «a arrumação não
   completou» virar «a arrumação não comple».
   Envolver e dar base larga ao status faz a frase descer para a própria linha
   quando não couber ao lado, e ficar ao lado quando couber (é o caso do
   status vazio, que é o comum). `min-width: 0` porque item de flex não encolhe
   abaixo do conteúdo sem ele — é o que fazia a frase transbordar em vez de
   quebrar. */
/* Não há `.linha` genérica no arquivo — cada sheet declara a sua (`#nota`,
   `#conversa`, `#colar`, `#metadados`). A do `#transcricao` não existia, e por
   isso o `flex-wrap` da primeira tentativa não teve em que pegar. */
#transcricao .linha {
  display: flex; align-items: center; flex-wrap: wrap;
  justify-content: flex-end; gap: .5rem; margin-top: .8rem;
}
#transcricao #trans-status { flex: 1 1 16rem; min-width: 0; line-height: 1.35; text-align: left; }

/* ─────────────────────────────────────────────────────────────────────────────
   O desenho e o destaque de sintaxe  (spec 37 §3.5, §3.6)

   O diagrama vive DENTRO do `<pre>` que o trouxe — é ele que carrega o
   `data-bid`, e o bid é o endereço do bloco para o progresso, a busca e o
   sumário. Trocar o elemento apagaria o endereço; trocar o conteúdo, não.
   ───────────────────────────────────────────────────────────────────────── */

.prosa pre.diagrama {
  background: none;
  /* A faixa de cima é do BOTÃO, e por isso ela existe: na captura de 07/09 o
     botão pousava em cima da caixa do último participante do sequenceDiagram.
     Um controle que encobre justamente o que ele serve para mostrar é pior
     que a falta dele.

     3.2rem porque o botão mede 44px de verdade — `min-height: var(--alvo)`
     do núcleo vence qualquer `height` menor, armadilha que esta folha já
     registrou duas vezes (o `#colar` que virou oval, o `.redondo` que virou
     elipse). A primeira tentativa reservou 2.3rem para um botão que eu
     achava de 34px, e a conferência de sobreposição pegou os 10px que
     faltavam. */
  padding: 3.2rem 0 .5em;
  overflow-x: auto;
  text-align: center;
  position: relative;
}
.prosa pre.diagrama svg { max-width: 100%; height: auto; }

/* ── A porta para a lente  (07/09) ───────────────────────────────────────────
   «Alguns diagramas ficam muito pequenos… tem como abrir ele grandão na
   tela?» O `max-width: 100%` acima está certo — um diagrama que estoura a
   medida do texto quebra a página —, e o preço dele é um `sequenceDiagram` de
   quatro participantes com rótulos de 5px. O botão é a saída.

   O glifo é conteúdo GERADO, como o número da linha: `content:` não entra no
   `textContent` do bloco, não é selecionável e não viaja na cópia. Um `⤢`
   escrito como texto entraria na coordenada dos destaques e na área de
   transferência de quem leva o exemplo para rodar.

   Duas coisas que a folha NÃO deixa fazer aqui, e as duas por bons motivos.
   Nada de `opacity` — a lição de 03/09: uma opacidade deitada sobre tinta já
   esmaecida mediu 2,30:1 no rótulo que se encarava por dois minutos. E nada
   de tinta secundária: `nucleo.test.mjs` proíbe `--tenue` e `--tinta-2`
   dentro de `.prosa`, porque um `--hl-*` pode nascer por baixo e os quatro
   destaques foram calibrados para `--tinta`. Escrevi `--tenue` aqui e o
   guarda pegou.

   Então a discrição vem da MEDIDA e da moldura — 34px num canto, com o campo
   da cerca por trás —, e não do apagamento da tinta. E no iPad, que é onde
   se lê, não existe `hover`: um botão que só aparece ao passar o mouse é um
   botão que não existe. */
/* ─────────────────────────────────────────────────────────────────────────────
   O botão de copiar a cerca  (07/09)

   Ele mora num wrapper `.cerca` e não dentro do `<pre>`: o `data-bid` está no
   `<pre>`, e o `textContent` dele é a coordenada de todo destaque, o que a
   busca varre e o que a voz narra. Um nó a mais lá dentro moveria traços já
   feitos — a razão de o número de linha ter de ser conteúdo gerado.

   O wrapper também tira o botão do alcance do pintor de destaques, que
   fotografa o miolo dos elementos com `data-bid` e devolve ao retrato o que
   mudou.
   ────────────────────────────────────────────────────────────────────────── */
/* Uma GRADE de uma célula, e não um contexto de posicionamento.
   `position: relative` aqui tornaria a cerca o `offsetParent` do `<pre>`, e a
   marginália mede a altura de cada nota com `offsetTop` — da marca ou do
   bloco —, contado a partir do ancestral posicionado, que o CSS fixa no
   `<main>`. Toda nota ancorada dentro de um bloco de código subiria para o
   topo da página. Medido no Safari: com `relative`, o `offsetTop` do bloco cai
   de centenas de pixels para ZERO. `display: grid` não mexe em
   `offsetParent`, e o botão se põe com `justify-self`. */
.prosa .cerca {
  display: grid;
  /* A grade abre um contexto de formatação próprio, então a margem do `<pre>`
     deixaria de colapsar com a dos vizinhos e o espaçamento da página mudaria.
     A margem sobe para o wrapper, e o bloco fica sem a sua. */
  margin: 1em 0;
}
.prosa .cerca > pre, .prosa .cerca > button.copiar { grid-area: 1 / 1; }
/* A faixa que o `<pre>` cede ao botão. Sem ela a primeira linha do programa
   corre por baixo do alvo de 44px — o defeito que a lente teve em 07/09, e que
   nenhum teste de CSS vê: quem o pega é a conferência de sobreposição. */
.prosa .cerca > pre {
  padding-right: 3.4rem;
  margin: 0;
}
.prosa .cerca > button.copiar {
  justify-self: end; align-self: start;
  margin: .2rem;
  /* 44 nos dois eixos, como o da lente: o núcleo impõe `min-height:
     var(--alvo)` a todo `button`, e uma altura menor só produz um retângulo. */
  width: 44px; height: 44px;
  display: grid; place-items: center;
  border: 1px solid var(--borda-controle); border-radius: 8px;
  background: var(--papel-elev);
  color: var(--tinta);
  cursor: pointer;
  transition: color .15s ease, border-color .15s ease;
  -webkit-tap-highlight-color: transparent;
}
.prosa .cerca > button.copiar svg { width: 17px; height: 17px; grid-area: 1 / 1; }
/* Quem troca o desenho é o ESTADO, e não o DOM: os dois nascem no botão e a
   folha mostra um de cada vez. */
.prosa .cerca > button.copiar .ic-copiado { display: none; }
.prosa .cerca > button.copiar[data-estado="copiado"] { color: var(--foco); border-color: var(--foco); }
.prosa .cerca > button.copiar[data-estado="copiado"] .ic-copiar { display: none; }
.prosa .cerca > button.copiar[data-estado="copiado"] .ic-copiado { display: block; }
/* A falha aparece — sucesso mudo aqui é o leitor colando o que estava antes. */
.prosa .cerca > button.copiar[data-estado="falhou"] { color: var(--perigo); border-color: currentColor; }
@media (hover: hover) {
  .prosa .cerca > button.copiar:hover { color: var(--foco); border-color: var(--foco); }
}
.prosa .cerca > button.copiar:focus-visible {
  outline: 2px solid var(--foco); outline-offset: 2px;
}

/* ──────────────────────────────────────────────────────────────────────────
   A bancada  (spec 39 §3.4)

   O ▶ é o terceiro filho da grade da cerca, à esquerda do copiar e com os
   mesmos 44 px; a saída é a segunda LINHA da grade. `.com-rodar` marca a
   cerca que é célula do lab — só ela cede a faixa dupla ao `<pre>`; a cerca
   comum continua cedendo só a do copiar. A barra é `sticky` no pé do artigo:
   «Parar» tem de estar à mão enquanto a célula lá em cima roda.
   ────────────────────────────────────────────────────────────────────────── */
.prosa .cerca.com-rodar > pre { padding-right: calc(3.4rem + 44px + .4rem); }
.prosa .cerca > button.rodar {
  grid-area: 1 / 1;
  justify-self: end; align-self: start;
  margin: .2rem calc(.2rem + 44px + .4rem) 0 0;
  width: 44px; height: 44px;
  display: grid; place-items: center;
  border: 1px solid var(--borda-controle); border-radius: 8px;
  background: var(--papel-elev);
  color: var(--foco);
  cursor: pointer;
  transition: color .15s ease, border-color .15s ease;
  -webkit-tap-highlight-color: transparent;
}
.prosa .cerca > button.rodar svg { width: 18px; height: 18px; }
.prosa .cerca > button.rodar[data-estado="rodando"] { color: var(--tinta-suave, var(--tinta)); border-color: var(--foco); }
.prosa .cerca > button.rodar[data-estado="ok"] { border-color: var(--foco); background: var(--foco); color: var(--papel); }
.prosa .cerca > button.rodar[data-estado="erro"] { color: var(--perigo); border-color: currentColor; }
.prosa .cerca > button.rodar:focus-visible { outline: 2px solid var(--foco); outline-offset: 2px; }

/* A saída: segunda linha da grade, colada à cerca. */
.prosa .cerca > .saida {
  grid-row: 2; grid-column: 1;
  margin: 0;
  padding: .55rem .9rem .65rem;
  border: 1px solid var(--borda-controle); border-top: 0;
  border-radius: 0 0 6px 6px;
  background: var(--papel);
  font-family: var(--mono); font-size: .82em; line-height: 1.5;
  color: var(--tinta);
  position: relative;
}
.prosa .cerca > .saida[data-antiga] { opacity: .55; }
.prosa .cerca > .saida[data-n]:not([data-n=""])::before {
  content: "[" attr(data-n) "]";
  display: block;
  font-size: .8em; opacity: .6;
  margin-bottom: .25rem;
}
.prosa .cerca > .saida pre {
  margin: 0; padding: 0;
  background: none; border: 0; border-radius: 0;
  font-size: inherit; line-height: inherit;
  white-space: pre-wrap; overflow-wrap: anywhere;
}
.prosa .cerca > .saida pre + pre { margin-top: .35rem; }
.prosa .cerca > .saida pre.g-resultado { border-left: 3px solid var(--foco); padding-left: .6rem; }
.prosa .cerca > .saida pre.g-stderr, .prosa .cerca > .saida pre.g-erro { color: var(--perigo); }
.prosa .cerca > .saida p.g-corte { margin: .35rem 0 0; font-style: italic; opacity: .7; }
/* `width: auto` DECLARADO, e é ele que faz o `max-width` acima valer alguma
   coisa: a figura da ilustração do artigo é `.prosa img { width: 100% }` (lá em
   cima), e essa largura descia até aqui — a regra mais específica trocava o
   `max-width` e deixava o `width` de pé. Uma figura de matplotlib de 534px
   esticada para os 742 da coluna é 39% de ampliação num raster com eixo e
   rótulo dentro: fica borrada, e nada avisa. Ilustração de artigo preenche a
   coluna porque é decisão de página; saída de célula tem o tamanho que o
   kernel desenhou. Medido no Safari em 09/09, pelo `npm run bancada`. */
.prosa .cerca > .saida img { display: block; width: auto; max-width: 100%; height: auto; margin-top: .5rem; }

/* ── A saída de REFERÊNCIA e a célula que não passou  (spec 43 §6.3-6.4) ──
   A referência é a saída que o gate MEDIU quando escreveu a etapa, e ela vem
   no próprio markdown. Enquanto a célula não roda neste aparelho, ela é a
   melhor resposta que há para «o que sai daqui?» — esmaecida, porque é de
   outra máquina e de outro dia. Quando a saída local chega, ela some: duas
   respostas para a mesma pergunta, uma sob a outra, é o leitor comparando o
   que acabou de rodar com um fantasma.

   A célula que não passou na conferência não tem ▶ (o dado decide, em
   `bancada.mjs`), e a cerca diz isso na borda: o motivo já está escrito acima
   dela, em prosa, e a marca é só para o olho achar. */
.prosa .saida[data-origem="referencia"] { opacity: .62; }
.prosa .saida[data-origem="referencia"] p { font-size: .82em; }
.prosa .cerca.nao-conferida { border-left: 3px solid var(--perigo); padding-left: .5rem; }
.prosa .cerca.nao-conferida > pre { opacity: .8; }

/* ──────────────────────────────────────────────────────────────────────────
   O modo Editar  (spec 43 §7.2)

   O campo ocupa a MESMA célula da grade que o `<pre>` — `1 / 1` —, e o `pre`
   sai por `hidden`. Duas versões do mesmo código na tela, uma sobre a outra,
   seria a pior leitura possível de um lab.

   A medida do texto é a do `<pre>` para que ligar o modo não reflua a página:
   a mesma família, o mesmo corpo e a mesma entrelinha. E a faixa da direita é
   a mesma que o `<pre>` cede — o ▶ e o copiar continuam onde estavam, e o
   programa não corre por baixo deles.
   ────────────────────────────────────────────────────────────────────────── */
.prosa .cerca > textarea.celula-editor {
  grid-area: 1 / 1;
  width: 100%;
  box-sizing: border-box;
  margin: 0;
  padding: .55rem 3.4rem .65rem .9rem;
  border: 1px solid var(--foco);
  border-radius: 6px;
  background: var(--papel-elev);
  color: var(--tinta);
  font-family: var(--mono); font-size: .86em; line-height: 1.55;
  /* O campo é CÓDIGO, e o `<pre>` que ele cobre não quebra linha nenhuma: um
     textarea que quebra faz a linha longa mudar de forma ao ligar o modo, e a
     coluna 80 cair no meio da tela. `pre` (com o `wrap="off"` que o módulo
     põe no elemento) rola na horizontal, como a cerca ao lado.

     `hyphens`/`word-break` vêm da PROSA, que é o pai: a folha hifeniza o
     texto do estudo, e o campo herdava — um traço no meio de um identificador
     Python é código que não existe. Aqui se recusa a herança, e não se muda a
     prosa. */
  white-space: pre;
  hyphens: none;
  word-break: normal;
  overflow-wrap: normal;
  /* A altura vem do `rows`, que o módulo recalcula a cada tecla, e o teto é
     desta folha: sem ele, uma célula de cem linhas empurra a saída e o ▶ para
     fora da tela e o leitor rola a PÁGINA para achar o que está editando. No
     teto, quem rola é o campo. A alça de redimensionar daria ao leitor um
     segundo controle da mesma coisa, que desandaria no primeiro `input`. */
  max-height: 60vh;
  resize: none;
  overflow: auto;
  -webkit-tap-highlight-color: transparent;
}
.prosa .cerca.com-rodar > textarea.celula-editor { padding-right: calc(3.4rem + 44px + .4rem); }
/* A guarda da L-120: `[hidden]` só vem da folha do navegador, e qualquer
   regra de autor que ponha `display` num `pre` a venceria em silêncio — o
   leitor veria o código duas vezes, um em cima do outro na mesma célula da
   grade. Declarada aqui, a intenção não depende de ninguém não mexer ali. */
.prosa .cerca > pre[hidden] { display: none; }
.prosa .cerca > textarea.celula-editor:focus-visible { outline: 2px solid var(--foco); outline-offset: 1px; }

/* A marca e o desfazer, na terceira linha da grade — abaixo da saída, que é a
   segunda. A marca é conteúdo GERADO: rótulo é apresentação, e um `<span>` a
   mais dentro da cerca é um nó a mais no caminho do pintor de destaques. */
.prosa .cerca[data-modificada]::after {
  content: "modificada";
  grid-row: 3; grid-column: 1;
  justify-self: end; align-self: center;
  font-family: var(--mono); font-size: .72em; letter-spacing: .04em;
  color: var(--foco);
  padding-top: .25rem;
}
.prosa .cerca > button.restaurar {
  grid-row: 3; grid-column: 1;
  justify-self: start;
  margin-top: .25rem;
  padding: 0 .6rem;
  /* 44 de altura, como manda o núcleo: o botão é discreto pela TINTA e pelo
     corpo da letra, nunca pelo alvo — encolher o alvo é o defeito que a lente
     pegou em 07/09, e quem lê num iPad toca com o polegar. */
  min-height: var(--alvo);
  border: 1px solid var(--borda-controle); border-radius: 6px;
  background: none;
  color: var(--tinta-suave, var(--tinta));
  font-family: var(--corpo); font-size: .78em;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
@media (hover: hover) {
  .prosa .cerca > button.restaurar:hover { color: var(--foco); border-color: var(--foco); }
}
.prosa .cerca > button.restaurar:focus-visible { outline: 2px solid var(--foco); outline-offset: 2px; }

/* O pulso do mostrador da bancada: a única animação da cápsula, e ela diz uma
   coisa só — a célula ainda está rodando lá longe. */
@keyframes bancada-pulso { 0%, 100% { opacity: .35; } 50% { opacity: 1; } }

/* O painel das fontes  (spec 42 §3.4): uma linha por dado, no pé do artigo.
   Compacto — nome, estado, para quê, host — e os botões da decisão
   com a mesma cara dos da barra, menores. O estado fala pela cor da situação:
   pronta no acento, pendente na tinta suave, falha e recusa no perigo. */
.bancada-fontes {
  margin: .5rem 0 0;
  padding: .35rem .9rem;
  border: 1px solid var(--borda-controle); border-radius: 12px;
  background: var(--papel-elev);
  font-size: .85em;
}
.bancada-fontes .fonte {
  display: flex; flex-wrap: wrap; gap: .25rem .7rem; align-items: center;
  padding: .3rem 0;
  font-variant-numeric: tabular-nums;
}
.bancada-fontes .fonte + .fonte { border-top: 1px solid var(--borda-controle); }
.bancada-fontes .fonte .nome { font-family: var(--mono); font-size: .95em; }
.bancada-fontes .fonte .situacao { color: var(--tinta-suave, var(--tinta)); }
.bancada-fontes .fonte[data-estado="pronto"] .situacao { color: var(--foco); }
.bancada-fontes .fonte[data-estado="falhou"] .situacao,
.bancada-fontes .fonte[data-estado="recusada"] .situacao,
.bancada-fontes .fonte .falha-decisao { color: var(--perigo); }
.bancada-fontes .fonte[data-estado="baixando"] .situacao::before {
  content: ""; display: inline-block; width: .5em; height: .5em; border-radius: 50%;
  background: var(--foco); margin-right: .45em; vertical-align: middle;
  animation: bancada-pulso 1.1s ease-in-out infinite;
}
.bancada-fontes .fonte .para-que { flex: 1 1 12rem; color: var(--tinta-suave, var(--tinta)); }
.bancada-fontes .fonte .host { font-family: var(--mono); font-size: .85em; opacity: .7; }
.bancada-fontes .fonte .decisao { display: flex; flex-wrap: wrap; gap: .35rem; align-items: center; margin-left: auto; }
.bancada-fontes .fonte .decisao button {
  min-height: var(--alvo); padding: 0 .7rem;
  border: 1px solid var(--borda-controle); border-radius: 8px;
  background: var(--papel); color: var(--tinta);
  font: inherit; font-size: .95em; cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.bancada-fontes .fonte .decisao button[data-acao="aprovar"],
.bancada-fontes .fonte .decisao button[data-acao="repetir"] { color: var(--foco); border-color: var(--foco); }
.bancada-fontes .fonte .decisao button[data-acao="recusar"],
.bancada-fontes .fonte .decisao button[data-acao="recusar-confirmar"] { color: var(--perigo); border-color: currentColor; }
.bancada-fontes .fonte .decisao button:disabled { opacity: .5; cursor: default; }
.bancada-fontes .fonte .decisao button:focus-visible { outline: 2px solid var(--foco); outline-offset: 2px; }
.bancada-fontes .fonte .decisao input {
  min-height: var(--alvo); padding: 0 .6rem;
  border: 1px solid var(--borda-controle); border-radius: 8px;
  background: var(--papel); color: var(--tinta);
  font: inherit; font-size: .95em;
  flex: 1 1 10rem;
}
.bancada-fontes .fontes-aviso { margin: .3rem 0 .15rem; color: var(--tinta-suave, var(--tinta)); font-style: italic; }


.prosa pre.diagrama > button.ampliar {
  position: absolute;
  top: .2rem; right: .2rem;
  /* 44 nos dois eixos, e não 34: o núcleo impõe `min-height: var(--alvo)` a
     todo `button`, e um `height` menor só produziria um retângulo. */
  width: 44px; height: 44px;
  display: grid; place-items: center;
  border: 1px solid var(--borda-controle); border-radius: 8px;
  background: var(--papel-elev);
  color: var(--tinta);
  cursor: pointer;
  transition: color .15s ease, border-color .15s ease;
  -webkit-tap-highlight-color: transparent;
}
.prosa pre.diagrama > button.ampliar::before {
  content: "⤢";
  font: 16px/1 var(--fonte-interface, system-ui, sans-serif);
  user-select: none; -webkit-user-select: none;
}
@media (hover: hover) {
  .prosa pre.diagrama > button.ampliar:hover { color: var(--foco); border-color: var(--foco); }
}
.prosa pre.diagrama > button.ampliar:focus-visible {
  outline: 2px solid var(--foco); outline-offset: 2px;
}

/* ─────────────────────────────────────────────────────────────────────────────
   A lente — o desenho em tela cheia  (07/09)

   Fundo OPACO, e não um véu: o diagrama é linha fina sobre papel, e um texto
   de artigo aparecendo por trás dele compete com as arestas exatamente onde a
   leitura é mais difícil.

   `touch-action: none` porque os gestos são nossos: sem isto o Safari faz o
   seu próprio pinch-zoom da página e o desenho fica preso no meio dos dois.
   ───────────────────────────────────────────────────────────────────────── */

#lente {
  position: fixed; inset: 0; z-index: 85;
  display: none;
  background: var(--papel);
  touch-action: none;
  overscroll-behavior: contain;
  overflow: hidden;
  cursor: grab;
}
#lente[data-aberto="sim"] { display: block; }
#lente:active { cursor: grabbing; }

/* O palco é o que se move e escala. `transform-origin: 0 0` não é gosto: toda
   a aritmética de `lente.mjs` — o zoom ancorado no dedo e o limite do arrasto
   — assume o canto como origem, e o padrão (`50% 50%`) faria cada conta errar
   por meia largura, em silêncio. */
#lente .palco {
  position: absolute; top: 0; left: 0;
  transform-origin: 0 0;
  will-change: transform;
}
#lente .palco svg { display: block; }

#lente .fechar {
  position: absolute; z-index: 2;
  top: calc(.6rem + env(safe-area-inset-top));
  right: calc(.6rem + env(safe-area-inset-right));
  width: 44px; height: 44px;
  display: grid; place-items: center;
  border: 1px solid var(--borda-controle); border-radius: 50%;
  background: var(--papel-elev);
  color: var(--tinta);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
#lente .fechar::before {
  content: "✕";
  font: 17px/1 var(--fonte-interface, system-ui, sans-serif);
  user-select: none; -webkit-user-select: none;
}
#lente .fechar:focus-visible { outline: 2px solid var(--foco); outline-offset: 2px; }

/* A dica de gesto. Pinça e duplo-toque não têm affordance nenhuma na tela —
   ou se diz que existem, ou elas não existem. Discreta e fixa: um aviso que
   some sozinho depois de três segundos é um aviso que só quem já sabia leu. */
#lente .dica {
  position: absolute; z-index: 2;
  left: 50%; transform: translateX(-50%);
  bottom: calc(.7rem + env(safe-area-inset-bottom));
  margin: 0;
  font: 12px/1.3 var(--fonte-interface, system-ui, sans-serif);
  letter-spacing: .02em;
  color: var(--tenue);
  opacity: .7;
  pointer-events: none;
  user-select: none; -webkit-user-select: none;
}

/* A `leitura` do recurso — o parágrafo em itálico logo abaixo do desenho. É o
   campo que impede o diagrama de ser enfeite, e por isso ele se lê como legenda
   e não como corpo. */
.prosa pre.diagrama + p em,
.prosa pre.diagrama + p > em:only-child {
  font-style: italic;
  color: var(--tinta-fraca);
}

/* Diagrama que não compilou fica como fonte à vista: feio, e honesto. O
   contrário — sumir em silêncio — é o defeito que a spec 23 chama de sucesso
   mudo, do lado do cliente. */
.prosa pre.diagrama-falhou { border-left: 2px solid var(--foco); }

/* ── O destaque de sintaxe ───────────────────────────────────────────────────
   Sete papéis, e não a paleta de 40 tokens do highlight.js: num estudo o
   código é lido devagar, e um arco-íris compete com a explicação ao redor.
   As cores saem dos tokens da folha, então os três temas seguem juntos. */

.prosa pre code.hljs { color: var(--tinta); }
.prosa .hljs-comment, .prosa .hljs-quote { color: var(--tinta-fraca); font-style: italic; }
.prosa .hljs-keyword, .prosa .hljs-selector-tag, .prosa .hljs-literal,
.prosa .hljs-doctag, .prosa .hljs-meta .hljs-keyword { color: var(--acento); font-weight: 600; }
.prosa .hljs-string, .prosa .hljs-regexp, .prosa .hljs-addition { color: var(--realce-texto); }
.prosa .hljs-number, .prosa .hljs-symbol, .prosa .hljs-bullet { color: var(--realce-numero); }
.prosa .hljs-title, .prosa .hljs-title.function_, .prosa .hljs-section,
.prosa .hljs-name { color: var(--realce-nome); font-weight: 600; }
.prosa .hljs-attr, .prosa .hljs-attribute, .prosa .hljs-variable,
.prosa .hljs-params, .prosa .hljs-property { color: var(--tinta); }
.prosa .hljs-type, .prosa .hljs-built_in, .prosa .hljs-class .hljs-title {
  color: var(--realce-nome); }
.prosa .hljs-deletion { color: var(--perigo, #b3261e); }
.prosa .hljs-emphasis { font-style: italic; }
.prosa .hljs-strong { font-weight: 700; }

/* As três cores próprias do destaque, por tema. Medidas sobre `--papel-elev`,
   que é o fundo da cerca — não sobre `--papel`. */
[data-tema="claro"] { --realce-texto:#0f6b4f; --realce-numero:#7a4e00; --realce-nome:#1c4f8a; }
[data-tema="sepia"] { --realce-texto:#0e6249; --realce-numero:#74490a; --realce-nome:#1b4a80; }
[data-tema="escuro"] { --realce-texto:#7fd3ae; --realce-numero:#e0b062; --realce-nome:#8fbdf0; }

/* ══ A CAIXA DO LABORATÓRIO  (spec 43 §7.3) ═════════════════════════════════

   Da família do `#nota`/`#conversa`/`#colar` — mesmo papel, mesma borda, mesma
   sombra de objeto que paira —, com UMA diferença de fundo: ela atraca no
   chão. Os outros fugiram do rodapé em 21/08 porque o teclado do iPad os
   engolia; esta não pode fugir, porque o que interessa num terminal é a última
   linha, e a última linha vive no pé.

   O que resolve o teclado aqui não é mudar de lugar, é SUBIR: o
   `teclado-virtual.mjs` mede o vão (`innerHeight` menos o viewport visual) e
   escreve `--teclado`; o `bottom` daqui é o máximo entre esse vão e a área
   segura, porque com o teclado aberto não há barra de gestos a evitar e com
   ele fechado não há vão.

   E ela é LARGA: 48rem, contra as 36rem das irmãs. Um terminal se mede em
   colunas, e 36rem dão umas sessenta — abaixo do que qualquer `pip install`
   ou `traceback` supõe ao quebrar as próprias linhas. */
/* ── A moldura é de TODA caixa  (spec 56 §2) ───────────────────────────────
   A caixa do lab virou a caixa padrão de escrever: a da leitura (nota e
   pergunta) veste a mesma moldura. As regras da moldura se escrevem sobre os
   DOIS ids por `:is()`, e não sobre uma classe `.caixa`, por causa do peso: um
   `:is()` pesa o seu argumento mais pesado, e é o id que vence
   `.alca { display: none }` (a alça de seleção da Pencil) e, sobretudo,
   `body[data-dentro] .cabeca { display: none }` — a regra do modo lateral
   que esconde o cabeçalho da PÁGINA. Com uma classe (0,2,0) contra (0,2,1), a
   cabeça da caixa da leitura sumiria no Mac, justamente com o `⌄` dentro.
   O que é de uma caixa só — largura, altura de partida, o terminal — fica no
   id dela. */
:is(#caixa-lab, #caixa-leitura, #caixa-destaques) {
  top: auto;
  bottom: max(var(--teclado, 0px), env(safe-area-inset-bottom));
  /* O teto com o teclado aberto é do JS (`limitesDaCaixa` ouve a área
     visível). Um `min(70vh, calc(100svh - var(--teclado)…))` aqui foi
     DESCARTADO pelo WebKit do simulador em 17/09 (medido: valia o
     `min(70vh, 34rem)` do `.sheet`), e isso prenderia a caixa do lab em 34rem
     no iPad. */
  max-height: 70vh;
  min-height: 160px;
  padding: 0;
  gap: 0;
  overflow: hidden;
}
/* A altura é o token que a alça escreve. Sem preferência guardada o módulo
   não escreve NADA e vale o padrão daqui — 40vh, que é caixa e não tela. */
#caixa-lab {
  width: min(48rem, calc(100% - 1.5rem));
  height: var(--caixa-lab-h, 40vh);
}
/* A entrada vem de BAIXO, e não de cima: o objeto nasce da borda em que ele
   está ancorado. A regra da família anima `sheet-entra`, que desce 8px — na
   caixa isso seria a mesma animação de um painel do topo, tocada no chão. */
:is(#caixa-lab, #caixa-leitura, #caixa-destaques)[data-aberto="sim"] { animation: caixa-lab-entra .16s var(--curva); }
@keyframes caixa-lab-entra { from { transform: translate(-50%, 8px); } }

/* ── A alça ────────────────────────────────────────────────────────────────
   `.alca` já existe nesta folha, para as alças de seleção da Pencil, e lá ela
   nasce `display: none`. As regras daqui têm o id na frente e por isso vencem
   — mas o `display` precisa ser declarado, e não herdado, senão a alça da
   caixa some sem erro nenhum no console.

   44px de alvo (o mínimo de toque da casa) com um filete de 4px desenhado no
   meio: o dedo pega a faixa inteira, o olho vê a marca. */
:is(#caixa-lab, #caixa-leitura, #caixa-destaques) .alca {
  display: flex; align-items: center; justify-content: center;
  position: relative; z-index: auto;
  width: 100%; margin: 0; height: 22px; flex: none;
  cursor: ns-resize;
  /* Sem isto a página rola por baixo enquanto o dedo puxa — o gesto vira
     scroll no meio do caminho e a caixa fica presa onde estava. */
  touch-action: none;
  -webkit-user-select: none; user-select: none;
}
:is(#caixa-lab, #caixa-leitura, #caixa-destaques) .alca > i {
  display: block; position: static;
  width: 44px; height: 4px; margin: 0;
  border-radius: 2px; background: var(--regra);
}
:is(#caixa-lab, #caixa-leitura, #caixa-destaques) .alca:hover > i, :is(#caixa-lab, #caixa-leitura, #caixa-destaques) .alca.puxando > i { background: var(--acento); }
/* O botão redondo de 18px é o puxador da alça de SELEÇÃO da Pencil
   (`.alca > i::after`), e casava aqui pelo nome: a captura do simulador em
   17/09 mostrou um círculo marrom pendurado no filete da caixa. */
:is(#caixa-lab, #caixa-leitura, #caixa-destaques) .alca > i::after { content: none; }

/* ── A cabeça: as abas à esquerda, os quatro botões à direita ──────────────
   Ela encolhe até virar duas fileiras nas telas estreitas: no iPhone as quatro
   ações não cabem ao lado das abas, e apertá-las abaixo do alvo de toque seria
   trocar um controle por um enfeite. */
:is(#caixa-lab, #caixa-leitura, #caixa-destaques) .cabeca {
  display: flex; align-items: center; justify-content: space-between;
  flex-wrap: wrap; gap: .4rem;
  flex: none;
  /* `max-width` e `margin` DECLARADOS, e não herdados. `.cabeca` é a classe do
     cabeçalho da PÁGINA (`.cabeca { max-width: var(--measure); margin: 0 auto }`,
     lá em cima), e a caixa reusou o nome: sem estas duas linhas a cabeça da
     caixa nasce com 34,5em e centrada dentro de 48rem — o `space-between`
     aproxima as abas dos botões, e o filete de baixo, que devia riscar a caixa
     inteira, vira um traço curto no meio. Medido no Safari em 09/09, pelo
     `npm run bancada`: 464px de cabeça numa caixa de 768px. */
  max-width: none; margin: 0;
  padding: 0 .8rem .5rem;
  border-bottom: 1px solid var(--regra);
}
/* `:not([hidden])`: com uma aba só (Destaques) a fileira nasce `hidden`, e um
   `display` de autor venceria o atributo — a armadilha da guarda do painel. */
:is(#caixa-lab, #caixa-leitura, #caixa-destaques) .abas:not([hidden]) { display: flex; gap: .1rem; }
:is(#caixa-lab, #caixa-leitura, #caixa-destaques) .abas [role="tab"] {
  font-family: var(--sans); font-size: .82rem; font-weight: 600;
  color: var(--tenue); background: none; border: none;
  border-bottom: 2px solid transparent;
  padding: .35rem .7rem; min-height: 32px; cursor: pointer;
}
:is(#caixa-lab, #caixa-leitura, #caixa-destaques) .abas [role="tab"][aria-selected="true"] {
  color: var(--tinta); border-bottom-color: var(--acento);
}
:is(#caixa-lab, #caixa-leitura, #caixa-destaques) .abas [role="tab"]:focus-visible { outline: 2px solid var(--foco); outline-offset: -2px; }
#caixa-lab .botoes { display: flex; gap: .35rem; flex-wrap: wrap; }
/* ── Recolher, e a cabeça no telefone  (14/09) ──────────────────────────────
   O «recolher» fecha a CAIXA (o «Fechar» ao lado encerra o lab). Um glifo, no
   tamanho de alvo, sem campo: é a porta de saída, não uma ação do lab. No
   telefone a cabeça já quebra em duas linhas (abas em cima, botões embaixo);
   o recolher vai para a ponta direita da linha das abas, onde o polegar o
   acha sem ler — e os quatro botões descem inteiros para a segunda linha. */
:is(#caixa-lab, #caixa-leitura, #caixa-destaques) .recolher {
  margin-left: auto; width: 32px; height: 32px; flex: none;
  border: 0; background: none; color: var(--tenue); cursor: pointer;
  font-family: var(--sans); font-size: 1.15rem; line-height: 1;
  border-radius: var(--raio-p);
  display: grid; place-items: center;
}
:is(#caixa-lab, #caixa-leitura, #caixa-destaques) .recolher:hover, :is(#caixa-lab, #caixa-leitura, #caixa-destaques) .recolher:focus-visible { color: var(--tinta); }
:is(#caixa-lab, #caixa-leitura, #caixa-destaques) .recolher:focus-visible { outline: 2px solid var(--foco); outline-offset: -2px; }
@media (max-width: 37rem) {
  :is(#caixa-lab, #caixa-leitura, #caixa-destaques) .abas { order: 1; }
  :is(#caixa-lab, #caixa-leitura, #caixa-destaques) .recolher { order: 2; }
  #caixa-lab .botoes { order: 3; width: 100%; }
}
/* Na barra do rodapé do telefone a caixa pousa ACIMA da barra, e não sobre
   ela: o `>_` que a abriu continua na tela, e a barra continua sendo a barra.
   Com o teclado aberto vale o vão dele, que é maior. */
body[data-arranjo="barra"] :is(#caixa-lab, #caixa-leitura, #caixa-destaques) {
  bottom: max(var(--teclado, 0px), var(--pilha-y));
  max-height: 60vh;
}
/* «Reiniciar o kernel» é o gesto raro e caro desta caixa, e o único que pede
   confirmação. Ele não veste o acento — chamar a mão para o que se arrepende
   depois é o contrário do que o preço declarado existe para fazer. */
#caixa-lab .botoes .btn { font-size: .74rem; padding: .3rem .55rem; }

/* ── Os painéis ───────────────────────────────────────────────────────────
   Quem rola é o painel, e não a caixa: a cabeça com as abas e os quatro botões
   fica presa no alto, sempre alcançável, como a linha de botões do `#conversa`
   fica presa no pé. Controle que sai da tela é controle que não existe. */
:is(#caixa-lab, #caixa-leitura, #caixa-destaques) .painel {
  flex: 1 1 auto; min-height: 0; overflow: auto;
  padding: .6rem .8rem .8rem;
}
:is(#caixa-lab, #caixa-leitura, #caixa-destaques) .painel:focus-visible { outline: 2px solid var(--foco); outline-offset: -2px; }
/* A aba Shell é COLUNA: a tarja do «sem kernel» fica presa no alto e o corpo
   rola por baixo dela. Um aviso que rolasse junto com a saída sairia da tela
   no terceiro comando, e é no terceiro comando que ele mais importa. */
#caixa-lab .painel.shell:not([hidden]) { display: flex; flex-direction: column; overflow: hidden; }
#caixa-lab .shell-corpo { flex: 1 1 auto; min-height: 0; overflow: auto; }
/* A guarda do `[hidden]`: o `display` de autor acima venceria o
   `[hidden] { display: none }` do navegador, e o painel escondido pela troca
   de aba ficaria na tela por baixo do outro.

   A guarda era só ORDEM — «mesma especificidade, e depois dela». Ordem só
   segura enquanto ninguém escrever mais específico, e a aba Conversa (§8)
   escreveu: `#caixa-lab #caixa-lab-conversa[role="tabpanel"]` tem dois ids e
   passa por cima daqui. O resultado, medido no Safari em 09/09 pelo
   `npm run bancada`: com a Shell aberta, o painel da Conversa continuava na
   tela — campo, botão «Perguntar» e 180px roubados da caixa, que sobravam 84
   para o terminal. Um `fit()` sobre 84px dá seis linhas, e seis linhas de
   terminal numa caixa de 379 é o defeito que nenhum teste de estado vê.

   Por isso o `:not([hidden])` nas regras de FORMA, e não mais um degrau de
   especificidade aqui: quem esconde é o atributo, e nenhuma regra de aparência
   se aplica a um painel escondido — independentemente de ordem e de peso. */
:is(#caixa-lab, #caixa-leitura, #caixa-destaques) .painel[hidden] { display: none; }
/* A tarja: perigo, porque o que ela anuncia é uma tecla que some. */
#caixa-lab .sem-kernel {
  flex: none; margin: 0 0 .5rem;
  font-family: var(--sans); font-size: .78rem; color: var(--perigo);
}
/* Sem linha o terminal se apaga um pouco: ele continua legível (o histórico é
   o trabalho), e deixa de parecer que está esperando o que se digita. */
#caixa-lab[data-sem-kernel] .terminal { opacity: .6; }

/* O terminal precisa de CAIXA: o FitAddon divide a altura disponível pela
   altura do glifo, e uma caixa de zero dá zero linha — o `fit()` roda, não
   falha, e o terminal fica com uma linha só. O `min-height` é o piso de duas
   dúzias de linhas a 13px; o `height: 100%` é o que faz ele crescer com a
   alça. */
#caixa-lab .terminal {
  width: 100%; height: 100%; min-height: 96px;
  /* Preto porque é o fundo que o xterm pinta por dentro (o padrão do tema
     dele). Os dois são um fato só: um container de outra cor apareceria como
     uma moldura que não é de ninguém quando o terminal tem menos linhas que a
     caixa. */
  background: #000;
  border-radius: var(--raio-p);
  overflow: hidden;
}

/* ── A reserva: a linha de comando sem pty ─────────────────────────────────
   Ela é declarada, e a frase é o que a declara. Sem ela o leitor acha que
   ISTO é o Shell e vai culpar o app quando o `vim` não abrir. */
#caixa-lab .sem-xterm {
  font-family: var(--sans); font-size: .78rem; color: var(--perigo);
  margin: 0 0 .5rem;
}
#caixa-lab .saida-pty {
  font-family: var(--mono); font-size: .82rem; line-height: 1.45;
  color: var(--tinta); background: var(--papel-elev-2);
  border: 1px solid var(--regra); border-radius: var(--raio-p);
  padding: .5rem .6rem; margin: 0 0 .5rem;
  max-height: 60vh; overflow: auto; white-space: pre-wrap; word-break: break-word;
}
#caixa-lab .linha-comando { display: flex; align-items: center; gap: .4rem; }
#caixa-lab .linha-comando .rotulo {
  font-family: var(--mono); font-size: .9rem; color: var(--tenue); flex: none;
}
/* 1rem, e não menos: abaixo de 16px o iOS DÁ ZOOM ao focar o campo, e a página
   salta com a caixa junto. É o mesmo número dos dois `textarea` da folha. */
#caixa-lab .linha-comando input {
  flex: 1; min-width: 0; box-sizing: border-box;
  font-family: var(--mono); font-size: 1rem; color: var(--tinta);
  background: var(--papel); border: 1px solid var(--borda-controle);
  border-radius: var(--raio-p); padding: .45rem .6rem; min-height: var(--alvo);
  -webkit-appearance: none; appearance: none;
}
#caixa-lab .linha-comando input:focus-visible { outline: none; border-color: var(--acento); }

/* ── A aba Conversa: a assistente do lab  (spec 43 §8) ─────────────────────
   Mesma gramática do `#conversa` do artigo — lista que rola, campo, linha de
   botão presa no pé —, porque é a mesma conversa em outro lugar: o leitor não
   deve ter de aprender duas vezes onde se digita.
   O painel vira coluna aqui (e não no `.painel` genérico) porque o Shell quer
   o contrário: lá o terminal ocupa a caixa inteira.

   O `:not([hidden])` é o que faz esta regra — dois ids — não atropelar a
   guarda do `[hidden]` lá em cima. Ver o comentário dela. */
#caixa-lab #caixa-lab-conversa[role="tabpanel"]:not([hidden]) {
  display: flex; flex-direction: column; gap: 0;
}
#caixa-lab .turnos { flex: 1 1 auto; min-height: 3rem; overflow-y: auto; margin-bottom: .7rem; }
#caixa-lab .turnos .vazio {
  color: var(--tinta-2); font-size: .88rem; text-align: center; margin: 1.2rem 0;
}
#caixa-lab .turno { margin-bottom: .9rem; }
#caixa-lab .turno .p {
  font-family: var(--sans); font-weight: 600; color: var(--tinta); font-size: .9rem;
  margin: 0 0 .3rem; white-space: pre-wrap;
}
#caixa-lab .turno .r {
  font-family: var(--sans); color: var(--tinta-2); font-size: .9rem; line-height: 1.55;
  margin: 0; white-space: pre-wrap;
}
#caixa-lab .turno .r code {
  font-family: var(--mono); font-size: .84em; background: var(--papel-elev-2);
  border-radius: var(--raio-p); padding: .05rem .25rem;
}

/* A proposta é um bloco à parte, recuado: ela não é a resposta, é o que a
   resposta oferece — e o recuo é o que diz isso sem uma legenda. */
#caixa-lab .proposta {
  margin: .5rem 0 0; padding: .5rem .6rem;
  border-left: 3px solid var(--regra); background: var(--papel-elev-2);
  border-radius: var(--raio-p);
}
/* A cerca ROLA, e não estica: código de uma linha longa alargaria a caixa
   inteira, e a caixa está atracada na largura da janela. */
#caixa-lab .proposta pre {
  margin: 0 0 .4rem; padding: 0; overflow-x: auto;
  font-family: var(--mono); font-size: .8rem; line-height: 1.45;
  color: var(--tinta); white-space: pre;
}
#caixa-lab .proposta .estado {
  font-family: var(--sans); font-size: .78rem; color: var(--tinta-2);
  margin: 0 0 .4rem; white-space: pre-wrap; word-break: break-word;
}
#caixa-lab .proposta .aplicar { font-size: .76rem; padding: .3rem .55rem; }
/* Desabilitado é ESTADO, e tem de parecer estado: a proposta que ainda não
   rodou (ou que falhou) não pode ter a mesma cara da que rodou. */
#caixa-lab .proposta .aplicar[disabled] { opacity: .5; cursor: default; }

/* A resposta tem parágrafos e cercas (13/09): o `<p>` herdaria a margem do
   núcleo, e o `code` de dentro da cerca herdaria a pílula do `code` inline. */
#caixa-lab .turno .r p { margin: 0 0 .45rem; }
#caixa-lab .turno .r p:last-child { margin-bottom: 0; }
#caixa-lab .turno .r .cerca { margin: .2rem 0 .5rem; }
#caixa-lab .turno .r .cerca > pre {
  padding: .45rem .6rem; background: var(--papel-elev-2); border-radius: var(--raio-p);
  font-family: var(--mono); font-size: .8rem; line-height: 1.45;
  color: var(--tinta); white-space: pre;
}
#caixa-lab .turno .cerca pre code { background: none; padding: 0; border-radius: 0; font-size: inherit; }

/* O botão de copiar é o MESMO da prosa (`cercar`, em desenho.mjs), e as regras
   de lá são `.prosa .cerca`: a caixa não mora na prosa. A grade põe o botão por
   cima do canto da cerca, e a cerca rola por baixo dele. */
#caixa-lab .cerca { display: grid; }
#caixa-lab .cerca > pre, #caixa-lab .cerca > button.copiar { grid-area: 1 / 1; }
#caixa-lab .cerca > pre { padding-right: 3.2rem; overflow-x: auto; margin: 0; }
#caixa-lab .cerca > button.copiar {
  justify-self: end; align-self: start; margin: .15rem;
  width: 44px; height: 44px; display: grid; place-items: center;
  border: 1px solid var(--borda-controle); border-radius: 8px;
  background: var(--papel-elev); color: var(--tinta); cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
#caixa-lab .cerca > button.copiar svg { width: 16px; height: 16px; grid-area: 1 / 1; }
#caixa-lab .cerca > button.copiar .ic-copiado { display: none; }
#caixa-lab .cerca > button.copiar[data-estado="copiado"] { color: var(--foco); border-color: var(--foco); }
#caixa-lab .cerca > button.copiar[data-estado="copiado"] .ic-copiar { display: none; }
#caixa-lab .cerca > button.copiar[data-estado="copiado"] .ic-copiado { display: block; }
#caixa-lab .cerca > button.copiar[data-estado="falhou"] { color: var(--perigo); border-color: currentColor; }
#caixa-lab .cerca > button.copiar:focus-visible { outline: 2px solid var(--foco); outline-offset: 2px; }

/* 1rem pelo mesmo motivo da linha de comando acima: abaixo de 16px o iOS dá
   zoom ao focar o campo, e a página salta com a caixa junto. */
#caixa-lab #caixa-lab-txt {
  flex: none; display: block; width: 100%; min-height: 3.2rem; resize: vertical;
  font-family: var(--sans); font-size: 1rem; line-height: 1.5; color: var(--tinta);
  background: var(--papel); border: 1px solid var(--borda-controle); border-radius: 8px;
  padding: .6rem .7rem; box-sizing: border-box;
}
#caixa-lab #caixa-lab-txt:focus-visible { outline: none; border-color: var(--acento); }
#caixa-lab #caixa-lab-conversa .linha {
  flex: none; display: flex; align-items: center; gap: .5rem; margin-top: .7rem;
}
#caixa-lab #caixa-lab-conversa .linha .sub { flex: 1; font-size: .78rem; color: var(--tinta-2); }
#caixa-lab #caixa-lab-perguntar[disabled] { opacity: .55; }

/* ══ A CAIXA DA LEITURA  (spec 56) ═════════════════════════════════════════

   A nota e a pergunta, que eram folhas no TOPO — sobre o parágrafo em que se
   pensava —, viram duas abas desta caixa, que atraca embaixo com a moldura do
   lab (acima). Lê-se em cima, escreve-se embaixo. A tela de Destaques usa a
   mesma caixa só com a aba Nota (`#caixa-destaques`).

   Mais estreita que a do lab: 40rem. A do lab se mede em colunas de terminal;
   esta se mede na linha de prosa que se escreve, e uma nota de 48rem no Mac
   teria linhas mais longas que as do próprio texto ao lado. */
#caixa-leitura {
  width: min(40rem, calc(100% - 1.5rem));
  /* 42vh: no iPhone deitado de teclado aberto a moldura grampeia no piso, e
     no iPad sobra texto acima para ler o parágrafo inteiro. */
  height: var(--caixa-leitura-h, 42vh);
}
#caixa-destaques {
  width: min(40rem, calc(100% - 1.5rem));
  height: var(--caixa-destaques-h, 36vh);
}

/* ── A cabeça do foco: SOBRE O QUE se escreve ────────────────────────────────
   Uma linha, cortada com reticências; o toque abre inteira. Escrever a nota
   sobre o trecho errado é o erro que ninguém percebe na hora, e é por isso
   que o trecho fica à vista em cima do campo — e pisca uma vez quando troca
   com a caixa aberta (spec 56 §4). */
:is(#caixa-leitura, #caixa-destaques) .foco {
  flex: none; display: block; box-sizing: border-box;
  width: calc(100% - 1.6rem); margin: .55rem .8rem 0; padding: .15rem .6rem;
  min-height: 32px;
  text-align: left; font-family: var(--corpo); font-size: .9rem; line-height: 1.45;
  color: var(--tinta-2); background: none;
  border: 0; border-left: 2px solid var(--acento); border-radius: 0;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  cursor: pointer;
}
:is(#caixa-leitura, #caixa-destaques) .foco[data-inteiro="sim"] { white-space: normal; max-height: 30vh; overflow-y: auto; }
:is(#caixa-leitura, #caixa-destaques) .foco:disabled { cursor: default; font-family: var(--sans); font-size: .82rem; opacity: 1; }
:is(#caixa-leitura, #caixa-destaques) .foco:focus-visible { outline: 2px solid var(--foco); outline-offset: -2px; }
:is(#caixa-leitura, #caixa-destaques) .foco[data-trocou="sim"] { animation: caixa-foco-trocou .7s var(--curva); }
@keyframes caixa-foco-trocou {
  from { background: color-mix(in srgb, var(--acento) 28%, transparent); }
}

/* ── As abas são COLUNA: o campo e a linha de status presos no pé ────────────
   A mesma razão do `#conversa` (L-81): quem rola é a lista de turnos, nunca o
   campo — controle que sai da tela é controle que não existe. O
   `:not([hidden])` é o invariante da moldura: regra de forma não alcança
   painel escondido. */
:is(#caixa-leitura, #caixa-destaques) .painel:not([hidden]) { display: flex; flex-direction: column; gap: 0; }
/* Os filhos das abas herdam da folha antiga `max-width: var(--measure);
   margin-inline: auto`, que numa coluna flex ENCOLHE o filho ao conteúdo: o
   botão «Perguntar» saía centrado e a lista de turnos estreita (simulador,
   17/09). Na caixa a medida é a da própria caixa. */
:is(#caixa-leitura, #caixa-destaques) .painel > * { max-width: none; margin-inline: 0; align-self: stretch; }
/* O trecho de dentro das abas é o da folha antiga; na caixa quem o mostra é a
   cabeça, e dois trechos iguais um sobre o outro seriam ruído. */
:is(#caixa-leitura, #caixa-destaques) .painel .trecho { display: none; }
/* A nota ocupa a caixa: o campo cresce com a alça, e a linha fica no pé. */
:is(#caixa-leitura, #caixa-destaques) #nota-txt { flex: 1 1 auto; min-height: 3.2rem; resize: none; box-sizing: border-box; }
:is(#caixa-leitura, #caixa-destaques) .painel .linha { flex: none; justify-content: flex-end; }
/* `campo.hidden` e `linha.hidden` quando o foco não é destaque: o `display`
   das regras da nota (`#nota textarea`, `#nota .linha`) venceria o atributo. */
#caixa-leitura-nota textarea[hidden], #caixa-destaques-nota textarea[hidden],
#caixa-leitura-nota .linha[hidden], #caixa-destaques-nota .linha[hidden] { display: none; }
:is(#caixa-leitura, #caixa-destaques) .sem-destaque {
  font-family: var(--sans); font-size: .88rem; color: var(--tinta-2);
  text-align: center; margin: 1.2rem 0;
}
:is(#caixa-leitura, #caixa-destaques) .sem-destaque[hidden] { display: none; }

/* ── O capítulo  (spec 50 §3.1–3.2, F2) ──────────────────────────────────────
   A moldura mínima. A tipografia literária (capitular, recuo, versalete da
   parte) é da F3 e entra por cima destes seletores.

   Cabeçalho e rodapé vivos seguem UM sinal, o `data-cromo` do corpo que
   `criarCromo` escreve: rolando para baixo o cabeçalho sai e o rodapé entra
   (a barra de navegação também sai, e o pé da tela fica livre); rolando para
   cima, o contrário. Dois sinais para «rolou para baixo» divergiriam.

   A altura dele é TOKEN  (25/09). Fixo e opaco no alto, ele cobria a
   `.cabeca` — que está no fluxo, no mesmo alto — inteira no topo do capítulo:
   no telefone e no iPad em retrato, o globo, o «?», o `Aa` e a Conta sumiam
   da leitura de livro sem caminho de volta («está sumindo a barra superior»).
   O cabeçalho vivo mede exatamente o token, e a `.cabeca` começa depois dele;
   rolando, ela sai com o texto, como em qualquer artigo. */
:root { --cabecalho-vivo-h: calc(1rem + 1px + var(--alvo) + env(safe-area-inset-top, 0px)); }
body:has(#cabecalho-vivo) .cabeca { padding-top: calc(var(--cabecalho-vivo-h) + .5rem); }
.cabecalho-vivo {
  box-sizing: border-box; height: var(--cabecalho-vivo-h);
  position: fixed; top: 0; left: 0; right: 0; z-index: 30;
  /* O mesmo inset do topo que a `.cabeca` (16/09): fixo em `top: 0`, sem ele
     o título corrente morava atrás do relógio do iPhone. */
  padding: calc(.5rem + env(safe-area-inset-top, 0px)) 1rem .5rem;
  font: 500 .8125rem/1.3 var(--sans); color: var(--tenue);
  background: var(--papel); border-bottom: 1px solid var(--regra);
  text-align: center; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  transition: transform var(--dur) var(--curva);
}
body[data-cromo="oculto"] .cabecalho-vivo { transform: translateY(-100%); }

.rodape-vivo {
  position: fixed; bottom: 0; left: 0; right: 0; z-index: 30;
  padding: .4rem 1rem calc(.4rem + env(safe-area-inset-bottom));
  font: 500 .75rem/1.3 var(--sans); color: var(--tenue);
  background: var(--papel); text-align: center; pointer-events: none;
  transition: opacity var(--dur) var(--curva);
}
body:not([data-cromo="oculto"]) .rodape-vivo { opacity: 0; }

.respiracao {
  margin: 4rem auto 5rem; max-width: 34rem; text-align: center;
  font-family: var(--serif-leitura); color: var(--tinta);
}
.respiracao-vinheta { font-size: 2rem; color: var(--tenue); margin: 0 0 2rem; }

/* ── A sala do fim  (spec 64) ────────────────────────────────────────────────
   A pergunta sobre o texto inteiro morava no TOPO da margem: quem lia o
   capítulo e perguntava no fim rolava o livro inteiro para trás para ler a
   resposta — e lá em cima ela nascia atrás do cabeçalho vivo, que é `fixed` e
   opaco (61 px medidos).

   Aqui ela fica onde o gesto acontece. A seção é irmã da respiração e a
   moldura segue a dela: a mesma coluna de leitura, centrada, e um rótulo em
   versalete entre dois filetes — o mesmo vocabulário do ❦, que é o que separa
   o fim do texto do que vem depois dele. */
.sala {
  max-width: var(--measure); margin: 2.5rem auto 1rem;
  font-family: var(--sans);
}
.sala-titulo {
  display: flex; align-items: center; gap: .75rem;
  margin: 0 0 1.1rem; font: 500 .8rem/1.3 var(--sans); color: var(--tenue);
  font-variant-caps: all-small-caps; letter-spacing: .08em; text-align: center;
}
.sala-titulo::before, .sala-titulo::after {
  content: ""; flex: 1; height: 1px; background: var(--regra);
}
/* Na página a conversa NÃO rola dentro de si: ela cresce com o texto, como
   qualquer coisa que se lê rolando. A rolagem interna é do sheet, onde o campo
   precisa ficar alcançável com o polegar por mais longa que a conversa fique. */
.sala .turnos { flex: none; overflow: visible; max-height: none; }
.sala .turnos .vazio { font-style: italic; }
.sala-antes {
  margin: -.4rem 0 1rem; font-size: .8rem; color: var(--tinta-2); font-style: italic;
}

/* ── A conversa falada no fio  (spec 64 §6) ──────────────────────────────────
   Escolha do dono entre as duas formas, olhando as duas: a transcrição aberta
   no fio, e não um título que abre um painel. O bloco é o MESMO turno dos
   escritos — mesma pergunta em cima, mesma resposta com filete —, com uma
   cabeça que diz de onde ele veio e um fio à esquerda que o mantém junto: uma
   conversa de seis minutos são muitos parágrafos, e sem ele o fim dela não
   pareceria pertencer ao começo. */
.sala .turno.falado {
  border-left: 2px solid var(--regra); padding-left: .8rem;
}
.sala .turno.falado .falado-cabeca {
  display: flex; align-items: center; gap: .4rem; margin: 0 0 .5rem;
  font: 500 .78rem/1.3 var(--sans); color: var(--tenue);
  font-variant-caps: all-small-caps; letter-spacing: .06em;
}
.sala .turno.falado .falado-cabeca .ic { display: inline-flex; width: 15px; height: 15px; }
.sala .turno.falado .falado-cabeca .ic svg { width: 15px; height: 15px; }
/* Os turnos de dentro da fala respiram menos que os de fora: são a mesma
   conversa, e o vão de um turno inteiro os faria parecer vários.

   `.falado-cabeca + .p`, e não `.p:first-of-type`: a cabeça TAMBÉM é um `<p>`,
   então `:first-of-type` nunca casaria com a primeira fala — seria uma regra
   escrita, publicada e morta. */
.sala .turno.falado .p { margin-top: .6rem; }
.sala .turno.falado .falado-cabeca + .p { margin-top: 0; }
.sala .turno.falado .falado-busca {
  margin: .4rem 0 0; font: italic .8rem/1.5 var(--sans); color: var(--tenue);
}
.sala-antes[hidden] { display: none; }
/* «ou falar com o autor»: o colóquio, que até a spec 64 era um botão do mesmo
   tamanho do «Próximo capítulo», ao lado dele. Aqui ele é a segunda via da
   MESMA conversa, e o desenho diz isso — uma linha discreta embaixo do campo,
   não um segundo convite competindo com o primeiro. */
.sala-ou {
  /* Flex, e não `text-align`: o botão tem 44px de alvo e a palavra «ou» tem a
     altura da linha — alinhados pela caixa, o «ou» pousava no pé do botão. */
  margin: .8rem 0 0; display: flex; align-items: center; justify-content: center;
  gap: .15rem; font-size: .82rem; color: var(--tinta-2);
}
.sala-coloquio {
  display: inline-flex; align-items: center; gap: .4rem;
  min-height: var(--alvo); padding: 0 .7rem; font-size: .82rem;
  background: none; border: 0; color: var(--tinta-2); cursor: pointer;
  text-decoration: underline; text-underline-offset: .2em;
}
.sala-coloquio:hover, .sala-coloquio:focus-visible { color: var(--tinta); }
.sala-coloquio .ic { display: inline-flex; width: 18px; height: 18px; }
.sala-coloquio .ic svg { width: 18px; height: 18px; }

/* O rodapé do capítulo é vazio de propósito (spec 64 §2.5): as ações de
   acervo são da OBRA e moram no frontispício e na Estante. Ele existe só
   porque `montarRodape` é um lugar só para as duas rotas. */
.rodape-capitulo { display: none; }
.respiracao-grifos { list-style: none; padding: 0; margin: 0 0 2rem; text-align: left; }
.respiracao-grifos li {
  border-left: 3px solid var(--regra); padding: .25rem 0 .25rem .75rem; margin: 0 0 .75rem;
}
.respiracao-proximo { font: 500 .9375rem/1.4 var(--sans); color: var(--tinta); }
.respiracao-acoes {
  display: flex; flex-wrap: wrap; gap: .75rem; justify-content: center; margin-top: 1rem;
}

/* A voz na respiração (spec 50 §5.6, F7): o aviso de que ela segue, e a
   pausa que oferece os dois caminhos. Só layout — a cor é a da respiração. */
.respiracao-voz { margin-block-start: 1.5em; text-align: center; }
.respiracao-voz .respiracao-acoes { justify-content: center; flex-wrap: wrap; }

/* ── O temperamento literário  (spec 50 §3.3, F3) ────────────────────────────
   Declarado pelo pipeline e escrito pelo leitor no <article>; o técnico é a
   AUSÊNCIA do atributo, e por isso é a tipografia de hoje sem uma linha a mais.

   Nada aqui toca o DOM do texto: a capitular é `::first-letter`, o numeral é
   `attr()`, o verso é `white-space`. Bids e offsets ficam como a ingestão os
   gravou — e a Pencil pergunta ao documento, não ao pixel.

   A capitular é UMA linha, de propósito: se a sondagem da alça reprovar
   (`web/test/sondagem-capitular.json`), ela sai apagando a linha, e o teste
   de CSS lê o veredito. Sem justificação: abre rios de branco (spec 02). */
.artigo[data-capitulo] .prosa > h1 { font-variant-caps: all-small-caps; letter-spacing: .08em; font-weight: 500; font-size: 1em; text-align: center; margin: 3rem 0 .25rem; color: var(--tinta); }
.artigo[data-capitulo] .prosa > [data-numeral] { text-align: center; margin-top: 1.25rem; }
.artigo[data-capitulo] .prosa > [data-numeral]::before { content: attr(data-numeral); display: block; font-size: .8em; font-weight: 400; letter-spacing: .12em; color: var(--tenue); margin-bottom: .35em; }
.artigo[data-temperamento="literario"] .prosa > p { margin: 0; text-indent: 1.5em; }
.artigo[data-temperamento="literario"] .prosa > p + :not(p) { margin-top: var(--space-para); }
.artigo[data-temperamento="literario"] .prosa > :is(h1, h2, h3, h4, h5, h6, hr, blockquote, figure, pre, ul, ol, table, section) + p,
.artigo[data-temperamento="literario"] .prosa > p.verso + p,
.artigo[data-temperamento="literario"] .prosa > p:first-child { text-indent: 0; }
.prosa > p.verso { white-space: pre-line; text-indent: 0; width: fit-content; max-width: 100%; margin-inline: auto; text-align: left; }
@supports (text-indent: 1em hanging each-line) {
  .prosa > p.verso { text-indent: 1.5em hanging each-line; }
}
.artigo[data-temperamento="literario"] .prosa > p.verso { margin-block: var(--space-para); }
.artigo[data-temperamento="literario"] .prosa > hr:not(.footnotes-sep) { border: 0; height: auto; margin: var(--space-block) 0; text-align: center; }
.artigo[data-temperamento="literario"] .prosa > hr:not(.footnotes-sep)::after { content: "❦"; color: var(--tenue); font-size: 1.1em; }

/* ── relembrar (spec 50 §5.5) ─────────────────────────────────────────────── */
.relembrar {
  margin: 0 0 1.25rem;
  padding: .6rem .8rem;
  border-left: 3px solid var(--acento);
  border-radius: var(--raio);
  background: var(--papel);
  color: var(--tinta);
  font-family: var(--sans);
  font-size: .9rem;
  line-height: 1.45;
}
.relembrar-rotulo { font-variant-caps: all-small-caps; letter-spacing: .04em; color: var(--acento); }
.relembrar[data-estado="falhou"] { border-left-color: var(--perigo); }
.relembrar-tentar { min-height: var(--alvo); min-width: var(--alvo); margin-left: .5rem; }
/* ── fim relembrar */

/* ── A fita de cetim  (spec 50 §3.5, F3) ─────────────────────────────────────
   Dois botões de 44px: o do canto do cabeçalho vivo (marca o topo, ou tira a
   fita do topo) e o pendurado na margem do parágrafo (tira aquela). A camada
   é irmã da prosa e não ocupa altura: marcar não move uma linha do texto. */
.cabecalho-vivo { padding-left: calc(var(--alvo) + 1rem); padding-right: calc(var(--alvo) + 1rem); }
.fita-marcar { position: absolute; top: 50%; right: .5rem; transform: translateY(-50%); width: var(--alvo); height: var(--alvo); min-height: var(--alvo); display: grid; place-items: center; padding: 0; border: 0; background: none; color: var(--tenue); cursor: pointer; }
.fita-marcar[aria-pressed="true"] { color: var(--acento); }
.fita-tecido { display: block; width: 12px; height: 22px; background: currentColor; clip-path: polygon(0 0, 100% 0, 100% 100%, 50% 78%, 0 100%); }
.fitas-margem { position: relative; height: 0; }
.fita-margem { position: absolute; z-index: 5; width: var(--alvo); height: var(--alvo); min-height: var(--alvo); display: grid; justify-items: end; align-items: start; padding: 0; border: 0; background: none; color: var(--acento); cursor: pointer; }
.fita-margem .fita-tecido { height: 34px; }
.fita-margem[hidden] { display: none; }

/* ── O título do cabeçalho vivo, caminho ao frontispício  (spec 50 §3.1, F4)
   Vira <a href="/o/:id"> só em obra fatiada (Task 7); mede 44px como
   qualquer alvo de toque, herdando a cor do cabeçalho vivo. */
.cabecalho-vivo a.cabecalho-vivo-texto { display: inline-flex; align-items: center; min-height: var(--alvo); color: inherit; text-decoration: none; }

/* ── O frontispício  (spec 50 §4, F4) ────────────────────────────────────────
   A mesa em duas colunas (capa e texto) que empilham no telefone; o botão
   primário é o gesto da tela. A capa é a MESMA da estante (`.obra .capa`),
   com largura própria. Todo alvo de toque mede 44px. */
body[data-rota="obra"] main { max-width: 52rem; margin-inline: auto; }
.frontispicio { padding-block: 2rem 4rem; }
.frontispicio .mesa { display: grid; grid-template-columns: 10.5rem 1fr; gap: 1.75rem; align-items: start; }
.frontispicio .mesa-capa { width: 10.5rem; height: auto; }
.frontispicio h1 { font-family: var(--serif); font-size: 2rem; line-height: 1.15; margin: 0 0 .35rem; text-wrap: balance; }
.frontispicio .autor { font-family: var(--serif); font-size: 1.1rem; margin: 0; color: var(--tinta); }
.frontispicio :is(.tradutor, .edicao, .extensao) { font: 400 .875rem/1.4 var(--sans); color: var(--tinta-2); margin: .25rem 0 0; }
.frontispicio .continuar-obra { margin-top: 1.25rem; }
.frontispicio [data-continuar] { display: inline-flex; align-items: center; min-height: var(--alvo); text-decoration: none; }
.frontispicio .continuar-linha { font-family: var(--serif); font-style: italic; color: var(--tinta-2); margin: .6rem 0 0; }
/* Os verbos do acervo na mesa da obra (spec 64 §2.5): os mesmos círculos da
   Estante e do rodapé do artigo avulso, com o mesmo alvo de 44px. Ficam
   abaixo do «Continuar», separados por um respiro — eles são o que se faz
   com o livro, não o que se faz agora. */
.acoes-obra { flex-wrap: wrap; gap: .6rem; margin-top: 1.5rem; }
.acoes-obra .redondo { width: var(--alvo); height: var(--alvo); min-height: var(--alvo); font-size: 1.05rem; }
.frontispicio .continuar-min { font: 400 .8125rem/1.3 var(--sans); color: var(--tenue); margin: .25rem 0 0; }
.frontispicio .argumento { font-family: var(--serif); margin-top: 2rem; }
.frontispicio .sobre-edicao { margin-top: 1rem; border-top: 1px solid var(--regra); }
.frontispicio .sobre-edicao summary { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem; min-height: var(--alvo); cursor: pointer; font: 500 .9375rem/1.3 var(--sans); }
.frontispicio .sobre-edicao .resumo { color: var(--tenue); font-weight: 400; }
.abas-obra { display: flex; gap: .25rem; overflow-x: auto; margin-top: 2rem; border-bottom: 1px solid var(--regra); }
.abas-obra [role="tab"] { min-height: var(--alvo); padding: 0 .9rem; border: 0; border-bottom: 2px solid transparent; background: none; color: var(--tinta-2); font: 500 .9375rem/1 var(--sans); white-space: nowrap; cursor: pointer; }
.abas-obra [role="tab"][aria-selected="true"] { color: var(--tinta); border-bottom-color: var(--acento); }
.aba-obra[hidden] { display: none; }
.aba-obra :is(ol, ul) { list-style: none; padding: 0; margin: 0; }
.parte-obra { font-variant-caps: all-small-caps; letter-spacing: .08em; color: var(--tinta-2); margin: 1.25rem 0 .25rem; }
:is(.cap-obra, .destaque-obra, .fita-obra) a { display: flex; gap: .6rem; align-items: baseline; min-height: var(--alvo); padding: .5rem 0; border-bottom: 1px solid var(--regra); color: inherit; text-decoration: none; }
.cap-obra .numeral { min-width: 2.5rem; color: var(--tenue); font-family: var(--serif); }
.cap-obra .min { margin-left: auto; color: var(--tenue); font: 400 .8125rem/1 var(--sans); }
.cap-obra .estado { min-width: 2.5rem; text-align: right; font: 500 .8125rem/1 var(--sans); color: var(--tinta-2); }
.cap-obra[data-estado="lido"] .estado { color: var(--acento); }
.grupo-obra h3 { font: 600 .875rem/1.3 var(--sans); color: var(--tinta-2); margin: 1.25rem 0 .25rem; }
.destaque-obra { border-left: 3px solid var(--regra); padding-left: .75rem; }
.destaque-obra[data-cor="roxo"] { border-left-color: var(--vivo-roxo); }
.destaque-obra[data-cor="amarelo"] { border-left-color: var(--vivo-amarelo); }
.destaque-obra[data-cor="rosa"] { border-left-color: var(--vivo-rosa); }
.destaque-obra[data-cor="azul"] { border-left-color: var(--vivo-azul); }
/* O grifo em cima, a nota embaixo (spec 50 §4.1, «grifos e notas da obra»). O `a` herda o `flex` em linha da
   lista de capítulos; com a nota ao lado, uma resposta longa do autor espremia o grifo numa coluna de uma
   palavra (15/09). A nota longa fica em quatro linhas — tocar leva ao parágrafo, onde ela está inteira. */
.destaque-obra a { flex-direction: column; align-items: stretch; gap: .3rem; }
.destaque-obra .nota { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 4; overflow: hidden; color: var(--tinta-2); font-size: .875rem; }
.fita-obra .numeral { min-width: 4rem; color: var(--tenue); font: 500 .8125rem/1 var(--sans); }
@media (max-width: 600px) {
  .frontispicio .mesa { grid-template-columns: 1fr; }
  .frontispicio .mesa-capa { width: 9rem; margin-inline: auto; }
}

/* ── Notas flutuantes  (spec 50 §3.4, F3) ────────────────────────────────────
   A lista do capítulo mora na prosa (é o HTML da ingestão) e fica recolhida
   por atributo no <article>; o número vem de `data-n` por `::before`, porque
   cada capítulo tem só as notas dele e a numeração do <ol> recomeçaria do 1.
   O balão é absoluto no documento, rola por dentro e nunca passa da janela.

   O número da nota usa `--tinta`, não `--tenue`: é DENTRO de `.prosa`, e o
   teste de hoje «dentro de .prosa, texto usa só --tinta» (destacável) o
   pega — diferente do numeral do capítulo (`::before` de `[data-numeral]`,
   Task 5) e do ❦ (`::after` de `hr`, Task 5), que ficam com `--tenue` de
   propósito: aqueles dois são ornamento fora do fluxo do texto, este é a
   numeração da nota que se lê. */
.prosa hr.footnotes-sep { display: none; }
.artigo[data-notas="recolhidas"] .prosa section.footnotes { display: none; }
.prosa section.footnotes { border-top: 1px solid var(--regra); margin-top: var(--space-block); padding-top: 1rem; font-size: .9em; }
.prosa section.footnotes ol { list-style: none; padding: 0; margin: 0; }
.prosa .footnote-item::before { content: attr(data-n) ". "; color: var(--tinta); font-variant-numeric: lining-nums; }
.prosa .footnote-item > p { display: inline; }
.notas-capitulo { display: block; min-height: var(--alvo); margin: 1.5rem auto 0; }
.balao-nota { position: absolute; z-index: 45; box-sizing: border-box; max-width: min(380px, 100vw - 2.5rem); overflow: auto; overscroll-behavior: contain; padding: .75rem 1rem; background: var(--papel-elev); color: var(--tinta); border: 1px solid var(--papel-borda); border-radius: 10px; box-shadow: var(--sombra-erguida); font: 400 .9375rem/1.5 var(--corpo); }
.balao-nota p { margin: 0 0 .5em; text-indent: 0; }
.balao-nota p:last-child { margin-bottom: 0; }
.balao-nota-alhures { color: var(--tenue); font-style: italic; }

/* ── A pílula Continuar  (spec 50 §4.1, F4) ─────────────────────────────────
   O segundo controle do cartão: a capa abre o frontispício, a pílula abre o
   parágrafo. Mede 44px mesmo onde os botões redondos do cartão medem 30. */
:is(.obra, .coluna-capa) > .continuar { display: inline-flex; align-items: center; justify-content: center; align-self: flex-start; min-height: var(--alvo); margin-top: .35rem; padding: 0 .9rem; border-radius: 999px; background: var(--acento); color: var(--sobre-acento); font: 600 .8125rem/1 var(--sans); text-decoration: none; }

/* ── quem é (spec 50 §5.4) ────────────────────────────────────────────────── */
.ficha-personagem {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  max-height: 70vh;
  overflow: auto;
  padding: 1rem 1.25rem 1.5rem;
  background: var(--papel);
  color: var(--tinta);
  border-top: 1px solid var(--papel-borda);
  border-radius: var(--raio) var(--raio) 0 0;
  font-family: var(--sans);
  z-index: 60;
}
/* `.ficha-personagem` reusa a classe `.sheet` (molde comum de nota/conversa/
   colar/metadados), mas é bandeja INFERIOR de largura total — não a coluna
   centrada em `left: 50%` que aquele molde presume. Sem este `transform:
   none`, a regra `.sheet[data-aberto="sim"] { transform: translate(-50%, 0) }`
   deslocaria a bandeja meia tela para a esquerda ao abrir (o `left: 0` daqui
   já não deixa margem para o `-50%` descontar). Mesmo remédio que `#ajustes`
   e `#sumario`, os outros dois sheets de largura total da casa. */
.ficha-personagem[data-aberto="sim"] { transform: none; }
.ficha-personagem .fechar-ficha { float: right; min-height: var(--alvo); min-width: var(--alvo); }
.ficha-revelacoes, .ficha-relacoes { padding-left: 1.2rem; }
.ficha-alcance { color: var(--acento); font-size: .85rem; }
/* ── fim quem é */

/* ── memória da obra no frontispício (spec 50 §5.1, §4.2) ───────────────────── */
.frontispicio-memoria { font-family: var(--sans); font-size: .85rem; color: var(--tinta); }
.frontispicio-memoria[data-estado="falhou"] .memoria-frase { color: var(--perigo); }
.memoria-tentar, .esquecer-conversa .btn { min-height: var(--alvo); }
.sessao-excluir { min-height: var(--alvo); }
.personagens-obra, .sessoes-obra { list-style: none; padding: 0; }
.personagem-obra { padding: .45rem 0; border-bottom: 1px solid var(--papel-borda); }
/* A aba Conversa (15/09): sem regra própria, o resumo saía como um bloco corrido do tamanho do texto do
   livro, os títulos das sessões no azul sublinhado do navegador e o Excluir como botão escuro ao lado de
   cada linha. Rótulo pequeno por seção; o resumo recuado por um fio da cor da obra; a sessão em uma linha
   (tipo · título em até duas linhas · Excluir discreto, que só se acende no toque que confirma). */
.rotulo-conversa { font: 600 .6875rem/1.2 var(--sans); letter-spacing: .1em; text-transform: uppercase; color: var(--tenue); margin: 1.75rem 0 .6rem; }
.resumo-conversa { font-family: var(--serif); color: var(--tinta); }
.resumo-conversa > p:not(.turnos-lembrados) { margin: 0; max-width: 62ch; font-size: 1rem; line-height: 1.65; color: var(--tinta-2); border-left: 2px solid var(--acento); padding-left: 1rem; }
.turnos-lembrados { margin: .6rem 0 0; font: 400 .8125rem/1.3 var(--sans); color: var(--tenue); }
.sessoes-obra { list-style: none; padding: 0; margin: 0; }
.sessao-obra { display: flex; align-items: center; gap: .75rem; padding: .2rem 0; border-bottom: 1px solid var(--papel-borda); }
.sessao-link { flex: 1; min-width: 0; display: flex; align-items: baseline; gap: .75rem; min-height: var(--alvo); padding: .45rem 0; color: inherit; text-decoration: none; }
.sessao-obra .tipo { flex: 0 0 4.25rem; font: 600 .6875rem/1 var(--sans); letter-spacing: .08em; text-transform: uppercase; color: var(--acento); }
.sessao-titulo { font: 400 .9375rem/1.4 var(--serif); color: var(--tinta); display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; }
a.sessao-link:hover .sessao-titulo { text-decoration: underline; text-decoration-color: var(--papel-borda); }
.btn.sessao-excluir { flex: none; background: transparent; border: 1px solid transparent; box-shadow: none; color: var(--tenue); }
.btn.sessao-excluir:hover, .btn.sessao-excluir[data-confirmar="sim"] { color: var(--perigo); border-color: currentColor; }
.esquecer-conversa { margin-top: 2rem; }
.resumo-estado[data-estado="falhou"], .conversa-esquecida, .sessao-excluida, .sessao-motivo { color: var(--perigo); font-family: var(--sans); font-size: .85rem; }
/* ── fim memória da obra no frontispício */
/* ═════════════════════════════════════════════════════════════════════════
   O ACERVO DE DECISÕES  (spec 51 §6.2, fase F4)

   A ficha de decisão de cada estudo técnico, e o lugar de uso dela:
   `/decisoes`, dentro da seção da escrivaninha. Bloco próprio, no fim do
   arquivo, só com tokens — os três temas vêm de graça, e o teste do acervo
   recusa cor crua aqui dentro.

   Os controles passam o `--alvo` de 44px: o filtro e a força são tocados no
   iPad, com o dedo, e um chip de 24px é o controle que se erra.
   ═════════════════════════════════════════════════════════════════════════ */
.cabeca-escrivaninha {
  display: flex; align-items: center; justify-content: space-between;
  gap: .4rem .8rem; flex-wrap: wrap;
}
.cabeca-escrivaninha .link-decisoes, .cabeca-decisoes .voltar-escrivaninha {
  flex: none; min-height: var(--alvo); display: inline-flex; align-items: center;
  text-decoration: none;
}

.decisoes { max-width: var(--measure); margin: 0 auto 3rem; padding: 0 1.1rem; }

.filtros-decisoes {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(10.5rem, 1fr));
  gap: .6rem .8rem; margin: .6rem 0 1rem;
}
.filtros-decisoes label {
  display: flex; flex-direction: column; gap: .25rem;
  font-family: var(--sans); font-size: .72rem; font-weight: 600;
  letter-spacing: .06em; text-transform: uppercase; color: var(--tenue);
}
.filtros-decisoes select, .filtros-decisoes input[type="search"] {
  min-height: var(--alvo); box-sizing: border-box; width: 100%;
  font-family: var(--sans); font-size: .95rem; letter-spacing: 0; text-transform: none;
  color: var(--tinta); background: var(--papel-elev);
  border: 1px solid var(--borda-controle); border-radius: 10px; padding: 0 .7rem;
}
/* O Safari desenha o `<select>` nativo com 24px e IGNORA o `min-height` —
   medido pela bancada de design em 14/09, com o teste de CSS verde. Sem a
   aparência nativa ele obedece, e a seta volta desenhada pelo rótulo (sem
   imagem: a CSP não aceita `data:` em `img-src`). */
.filtros-decisoes select { -webkit-appearance: none; appearance: none; padding-right: 2rem; }
.filtros-decisoes label { position: relative; }
.filtros-decisoes label:not(.busca-decisoes)::after {
  content: "▾"; position: absolute; right: .75rem; bottom: 0; height: var(--alvo);
  display: flex; align-items: center; pointer-events: none;
  font-size: .9rem; color: var(--tinta-2); letter-spacing: 0;
}
.filtros-decisoes select:focus-visible, .filtros-decisoes input:focus-visible {
  outline: 2px solid var(--foco); outline-offset: 1px;
}
.filtros-decisoes .busca-decisoes { grid-column: 1 / -1; }

.aviso-decisoes {
  font-family: var(--sans); font-size: .84rem; color: var(--tinta-2);
  border-left: 3px solid var(--acento); padding: .4rem .7rem; margin: .4rem 0;
}
.conta-decisoes {
  display: flex; align-items: center; flex-wrap: wrap; gap: .4rem .7rem;
  font-family: var(--sans); font-size: .82rem; color: var(--tenue); margin: 0 0 .8rem;
}
.conta-decisoes .limpar, .resultado-decisoes .vazio .btn { min-height: var(--alvo); }
/* Voltar e limpar são gestos SECUNDÁRIOS: a primeira captura (14/09) os
   mostrou como os dois blocos mais escuros da tela, acima das próprias fichas. */
.cabeca-decisoes .voltar-escrivaninha, .cabeca-escrivaninha .link-decisoes, .resultado-decisoes [data-limpar] {
  background: transparent; color: var(--tinta); border: 1px solid var(--borda-controle); box-shadow: none;
}

.lista-decisoes { list-style: none; margin: 0; padding: 0; }
.decisao {
  position: relative; background: var(--papel-elev);
  border: 1px solid var(--papel-borda-fina); border-radius: 14px;
  box-shadow: var(--sombra-erguida);
  padding: 1rem 1.1rem .6rem 1.3rem; margin-bottom: .9rem;
}
/* A lombada no acento: a ficha é da escrivaninha, e fala a língua da ficha
   de estudo que mora ao lado. */
.decisao::before {
  content: ""; position: absolute; left: 0; top: 0; bottom: 0;
  width: 3px; border-radius: 14px 0 0 14px; background: var(--acento);
}
.decisao.em-foco { outline: 2px solid var(--foco); outline-offset: 3px; }
.decisao header {
  display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between;
  gap: 0 .8rem;
}
.decisao h2 {
  font-family: var(--corpo); font-size: 1.14rem; line-height: 1.3; font-weight: 600;
  color: var(--tinta); margin: 0; flex: 1 1 18rem;
}
.decisao h2:focus { outline: none; }
.decisao .origem {
  min-height: var(--alvo); display: inline-flex; align-items: center;
  font-family: var(--sans); font-size: .8rem; color: var(--tenue);
  text-underline-offset: 3px;
}
.decisao .origem:hover, .decisao .origem:focus-visible { color: var(--acento); }

.decisao .etiquetas { display: flex; flex-wrap: wrap; gap: .3rem; margin: .45rem 0 .55rem; }
.decisao .chip {
  display: inline-flex; align-items: center; line-height: 1.2;
  font-family: var(--sans); font-size: .74rem; padding: .22rem .6rem;
  border-radius: 999px; border: 1px solid var(--papel-borda);
  color: var(--tinta-2); background: transparent;
}
.decisao .chip.onde { color: var(--acento); border-color: var(--acento); font-weight: 600; }

.decisao .escolha { font-family: var(--corpo); color: var(--tinta); margin: 0 0 .35rem; }
.decisao .escolha .rotulo, .fecho-fichas .rotulo {
  font-family: var(--sans); font-size: .68rem; font-weight: 600; letter-spacing: .08em;
  text-transform: uppercase; color: var(--tenue); margin-right: .35rem;
}
.decisao .contexto { font-family: var(--sans); font-size: .88rem; color: var(--tinta-2); margin: 0 0 .55rem; }

.decisao .forcas { list-style: none; margin: 0 0 .3rem; padding: 0; display: flex; flex-wrap: wrap; gap: .35rem; }
.decisao .chip.forca {
  min-height: var(--alvo); padding: 0 .85rem; font-size: .84rem; cursor: pointer;
  color: var(--tinta); border-color: var(--borda-controle);
}
.decisao .chip.forca:hover, .decisao .chip.forca:focus-visible {
  color: var(--acento); border-color: var(--acento); outline: none;
}

.decisao details > summary {
  min-height: var(--alvo); display: flex; align-items: center; gap: .45rem;
  list-style: none; cursor: pointer;
  font-family: var(--sans); font-size: .84rem; font-weight: 600; color: var(--tinta-2);
}
.decisao details > summary::-webkit-details-marker { display: none; }
.decisao details > summary::before {
  content: "▸"; font-size: .8em; transition: transform var(--dur-rapida) var(--curva);
}
.decisao details[open] > summary::before { transform: rotate(90deg); }
.decisao details > summary:focus-visible { outline: 2px solid var(--foco); outline-offset: 2px; border-radius: 6px; }
.decisao dl { margin: 0 0 .6rem; font-family: var(--sans); font-size: .88rem; }
.decisao dt { font-weight: 600; color: var(--tinta); margin-top: .5rem; }
.decisao dd { margin: .15rem 0 0; color: var(--tinta-2); }
.decisao dd ul { margin: 0; padding-left: 1.1rem; }

/* «Mesma força»: o fio entre fichas de estudos diferentes. Separada por uma
   regra, porque ela não é mais um campo da ficha — é a ficha olhando para
   fora dela. */
.decisao .mesma-forca { border-top: 1px solid var(--regra); margin-top: .2rem; }
.decisao .mesma-forca ul { list-style: none; margin: 0 0 .4rem; padding: 0; }
.decisao .mesma-forca li { display: flex; flex-wrap: wrap; align-items: center; gap: 0 .6rem; }
.decisao .mesma-forca .vizinha {
  min-height: var(--alvo); padding: 0; border: 0; background: none; cursor: pointer;
  font-family: var(--corpo); font-size: .98rem; text-align: left; color: var(--acento);
  text-decoration: underline; text-underline-offset: 3px; text-decoration-thickness: 1px;
}
.decisao .mesma-forca .vizinha:focus-visible { outline: 2px solid var(--foco); outline-offset: 2px; border-radius: 4px; }
.decisao .mesma-forca .via { font-family: var(--sans); font-size: .76rem; color: var(--tenue); }
.decisao .mesma-forca.vazia {
  font-family: var(--sans); font-size: .8rem; color: var(--tenue);
  margin: .2rem 0 .4rem; padding-top: .6rem;
}

/* A ficha no fecho do estudo: a lista curta, e o caminho até o acervo. */
.fecho-fichas .fichas-do-estudo { list-style: none; padding: 0; margin: .4rem 0 .9rem; }
.fecho-fichas .fichas-do-estudo li {
  display: flex; flex-direction: column; gap: .15rem;
  padding: .6rem 0; border-bottom: 1px solid var(--regra);
}
.fecho-fichas .fichas-do-estudo strong { font-family: var(--corpo); color: var(--tinta); }
.fecho-fichas .fichas-do-estudo .escolha { font-family: var(--sans); font-size: .9rem; color: var(--tinta-2); }
.fecho-fichas .via { font-family: var(--sans); font-size: .76rem; color: var(--tenue); }
.fecho-fichas .btn { min-height: var(--alvo); }

@media (max-width: 592px) {
  .filtros-decisoes { grid-template-columns: 1fr; }
}

/* ── O laboratório de DECISÃO  (spec 51 §5.2) ──────────────────────────────
   Um painel sobre o documento do lab, entre a abertura e a primeira seção. O
   que se toca são os segmentados — valores fechados, a vigente acesa, cada
   opção com o `--alvo` do núcleo nos dois eixos —, e o que se lê é a tabela
   das rodadas, onde o trade-off aparece comparando linhas.

   Tudo sob `.prosa .lab-decisao`: o painel mora DENTRO da prosa, e as regras
   de `h2`, `table` e `ul` da leitura venceriam uma classe solta — a tabela de
   rodadas sairia com a moldura das tabelas do texto, e o título do painel
   com o tamanho de seção. E a tinta é SÓ `--tinta`, como toda regra sob
   `.prosa` (`nucleo.test.mjs`): a hierarquia sai do corpo, do peso e da caixa
   alta, não de tinta secundária. Nenhum campo de texto aqui, de propósito: zero
   digitação e nenhuma previsão (spec 51 §10). */
.prosa .lab-decisao {
  margin: 1.6rem 0 2.2rem; padding: 1.1rem 1.2rem 1.2rem;
  border: 1px solid var(--borda-controle); border-radius: 14px;
  background: var(--papel-elev); font-family: var(--sans);
  max-width: 100%; box-sizing: border-box;
}
.prosa .lab-decisao h2 {
  font-family: var(--sans); font-size: .74rem; line-height: 1.3; letter-spacing: .09em;
  text-transform: uppercase; color: var(--tinta); margin: 0 0 .9rem; font-weight: 600;
}
.prosa .lab-decisao .parametros-decisao { display: flex; flex-direction: column; gap: .8rem; }
.prosa .lab-decisao .parametro-decisao {
  display: flex; flex-wrap: wrap; align-items: center; gap: .4rem .9rem;
}
.prosa .lab-decisao .parametro-decisao .rotulo {
  flex: 0 0 9.5rem; font-size: .88rem; font-weight: 600; color: var(--tinta); line-height: 1.3;
}
/* Mesma construção do segmentado do motor da voz: o campo por fora, as
   pílulas por dentro com 2px de folga, e o raio de dentro é o de fora menos
   a folga. `flex-wrap` porque quatro valores longos numa coluna de iPad em
   retrato não cabem numa linha, e pílula cortada não é alvo. */
.prosa .lab-decisao .segmentado {
  display: inline-flex; flex-wrap: wrap; padding: 2px; gap: 2px; max-width: 100%;
  background: var(--papel-elev-2); border: 1px solid var(--borda-controle);
  border-radius: var(--raio-p);
}
.prosa .lab-decisao .opcao {
  min-height: var(--alvo); min-width: var(--alvo); padding: 0 .9rem; margin: 0;
  font-family: var(--sans); font-size: .86rem; line-height: 1;
  color: var(--tinta); background: none; border: 0;
  border-radius: calc(var(--raio-p) - 2px); cursor: pointer; white-space: nowrap;
}
/* Acento cheio com `--sobre-acento`, nunca `#fff` — o motivo é o do motor da voz. */
.prosa .lab-decisao .opcao[aria-checked="true"] {
  background: var(--acento); color: var(--sobre-acento); font-weight: 600;
}
.prosa .lab-decisao .opcao:focus-visible { outline: 2px solid var(--foco); outline-offset: 2px; }
.prosa .lab-decisao .opcao .padrao { opacity: .7; }
.prosa .lab-decisao .rodar-decisao {
  display: flex; flex-wrap: wrap; align-items: center; gap: .5rem 1rem; margin: 1.1rem 0 .9rem;
}
.prosa .lab-decisao .rodar-combinacao { min-height: var(--alvo); margin: 0; }
.prosa .lab-decisao .estado-decisao { margin: 0; font-size: .86rem; line-height: 1.4; color: var(--tinta); }
/* A tabela rola na PRÓPRIA caixa: três parâmetros e quatro métricas numa
   coluna estreita passam da largura, e quem rola não pode ser a página. */
.prosa .lab-decisao .tabela-decisao { overflow-x: auto; max-width: 100%; }
.prosa .lab-decisao table {
  width: 100%; border-collapse: collapse; margin: 0; border: 0;
  font-family: var(--sans); font-size: .88rem; font-variant-numeric: tabular-nums;
  background: none; box-shadow: none;
}
.prosa .lab-decisao th, .prosa .lab-decisao td {
  padding: .5rem .6rem; border: 0; border-bottom: 1px solid var(--regra);
  text-align: left; vertical-align: bottom; color: var(--tinta); background: none;
}
.prosa .lab-decisao thead th { font-size: .74rem; font-weight: 600; color: var(--tinta); line-height: 1.25; }
.prosa .lab-decisao .unidade { display: block; font-weight: 400; }
.prosa .lab-decisao .metrica { text-align: right; }
.prosa .lab-decisao th.n { width: 2rem; color: var(--tinta); font-weight: 600; }
.prosa .lab-decisao tr.escolhida td, .prosa .lab-decisao tr.escolhida th { background: var(--papel-elev-2); }
.prosa .lab-decisao tr.ultima th.n { color: var(--acento); }
.prosa .lab-decisao td.erro { color: var(--perigo); font-size: .84rem; }
.prosa .lab-decisao tr.vazia td { color: var(--tinta); font-size: .86rem; }
.prosa .lab-decisao .leituras-decisao:empty { display: none; }
.prosa .lab-decisao .leituras-decisao h3 {
  font-family: var(--sans); font-size: .74rem; letter-spacing: .09em; text-transform: uppercase;
  color: var(--tinta); margin: 1.1rem 0 .5rem; font-weight: 600;
}
.prosa .lab-decisao .leituras-decisao ul { margin: 0; padding-left: 1.1rem; }
.prosa .lab-decisao .leituras-decisao li {
  font-family: var(--corpo); font-size: .96rem; line-height: 1.5; color: var(--tinta); margin: 0 0 .35rem;
}
/* O cabeçalho quebra por palavra, nunca no meio dela: «Répli-cas» vinha da
   hifenização da prosa, que aqui só atrapalha a leitura da coluna. */
.prosa .lab-decisao th { hyphens: manual; -webkit-hyphens: manual; }

/* ── A língua do Leitor  (spec 53 §5.2–5.4) ────────────────────────────────
   Quatro peças que qualquer tela usa: o aviso de erro, o processo em
   andamento, a barra de desfazer e a folha de custo. A régua é a de TDAH e
   dislexia: frase visível, nada animado puxando a atenção, alvo de 44px,
   contraste da tinta do corpo e nunca só cor. */

.aviso-erro { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem .75rem;
  font: 400 .9375rem/1.5 var(--sans); color: var(--tinta); }
.aviso-erro-frase { margin: 0; flex: 1 1 16rem; }
.aviso-erro-frase > span:first-child { font-weight: 600; }
.aviso-erro-tentar, .aviso-erro-entrar { min-height: 44px; }
.aviso-erro-detalhe { flex: 1 0 100%; font-size: .8rem; color: var(--tenue); }
.aviso-erro-detalhe summary { cursor: pointer; min-height: 32px; display: inline-flex; align-items: center; }
.aviso-erro-detalhe code { font-family: var(--mono); word-break: break-word; }

.processo { display: flex; flex-wrap: wrap; align-items: baseline; gap: .15rem .6rem;
  font: 400 .9375rem/1.45 var(--sans); color: var(--tinta); }
.processo-frase { font-weight: 600; }
.processo-tempo { color: var(--tinta-2); font-variant-numeric: tabular-nums; }
.processo-sair { flex-basis: 100%; color: var(--tinta-2); font-size: .85rem; }
.processo[data-processo="demorando"] .processo-tempo { color: var(--tinta); }
.processo-tentar, .processo-acao { min-height: 44px; }

.desfazer { position: fixed; z-index: 70; left: 50%; transform: translateX(-50%);
  bottom: calc(var(--barra-h) + .75rem);
  /* Largura PRÓPRIA (L-323): centrada por `left: 50%`, a caixa sem ela
     encolhia para caber na metade da tela, e a frase longa do «Puxado…» saiu
     no iPhone com 195 px e 16 linhas, quebrada no meio da palavra. O teto de
     40rem é a medida de uma frase que se lê de uma vez: sem ele, a mesma
     frase ia a 1.168 px no Mac. */
  box-sizing: border-box; width: max-content; max-width: min(calc(100vw - 2rem), 40rem);
  display: flex; align-items: center; gap: 1rem; padding: .35rem .5rem .35rem 1rem;
  background: var(--tinta); color: var(--papel); border-radius: 12px; box-shadow: var(--sombra-erguida);
  font: 500 .9375rem/1.4 var(--sans); }
.desfazer-frase { overflow-wrap: anywhere; }
.desfazer-botao { flex: none; min-height: 44px; min-width: 44px; padding: 0 .9rem; border: 0; border-radius: 8px;
  background: transparent; color: var(--papel); font: 700 .9375rem/1 var(--sans); text-decoration: underline;
  text-underline-offset: 3px; cursor: pointer; }
.desfazer-botao:focus-visible { outline: 2px solid var(--papel); outline-offset: 2px; }
/* Na lateral do Mac a nota se centra na ÁREA ÚTIL, não na janela: centrada
   na janela, a frase longa entrava 79 px na lateral de 236 (L-323), em toda
   `.desfazer` e `.aviso-mandado` do app. E só aqui ela desce ao chão: sem
   `pointer: fine` (o iPad deitado, 1.180 px) a barra continua embaixo, e o
   `bottom` de 1,5rem punha a nota por cima dela. */
@media (min-width: 1100px) and (pointer: fine) {
  .desfazer { bottom: 1.5rem; left: calc(50% + 118px); max-width: min(calc(100vw - 236px - 2rem), 40rem); }
}

.custo-fundo { position: fixed; inset: 0; z-index: 80; display: grid; place-items: end center;
  background: color-mix(in srgb, var(--tinta) 35%, transparent); padding: 1rem; }
@media (min-width: 37rem) { .custo-fundo { place-items: center; } }
.custo { box-sizing: border-box; width: min(28rem, 100%); padding: 1.25rem; border-radius: 14px;
  background: var(--papel-elev); color: var(--tinta); border: 1px solid var(--papel-borda);
  box-shadow: var(--sombra-erguida); padding-bottom: calc(1.25rem + env(safe-area-inset-bottom, 0px)); }
.custo-frase { margin: 0 0 1rem; font: 400 1rem/1.5 var(--sans); }
/* A folha da IA de terceiros (spec 74, item 0.11): a folha de custo com um
   título e a lista de quem recebe o texto. Rola por dentro no telefone baixo:
   o «Permitir» nunca pode sair da tela. */
.folha-ia { max-height: calc(100dvh - 2rem); overflow-y: auto; }
.folha-ia-titulo { margin: 0 0 .5rem; font: 600 1.125rem/1.3 var(--sans); }
/* A folha da ajuda (spec 75): a folha de custo com título e dois ou três
   parágrafos. Rola por dentro no telefone baixo, como a da IA: o «Entendi»
   nunca sai da tela. */
.folha-ajuda { max-height: calc(100dvh - 2rem); overflow-y: auto; }
.folha-ajuda-titulo { margin: 0 0 .5rem; font: 600 1.125rem/1.3 var(--sans); }
.folha-ajuda-corpo p { margin: 0 0 .75rem; font: 400 .9375rem/1.5 var(--sans); color: var(--tinta-2); }
.folha-ajuda-corpo p:first-child { color: var(--tinta); }
.folha-ia-provedores { margin: 0 0 1rem; padding-left: 1.25rem; font: 400 .9375rem/1.45 var(--sans); }
.folha-ia-provedores li { margin: .25rem 0; }
.folha-ia-nota { margin: 0 0 .75rem; font: 400 .9375rem/1.45 var(--sans); color: var(--tinta-2); }
/* O saldo da folha (69 §5.2, 24/09): à parte da frase e com peso de número,
   porque é o que a pessoa procura quando a folha diz quanto vai gastar. Não
   é cromo (69 §2.1): só existe enquanto a folha está aberta. */
.custo-saldo { margin: 0 0 1rem; padding: .75rem 0 0; border-top: 1px solid var(--papel-borda); }
/* O número encolhe no telefone estreito (320 px) para o par caber numa linha:
   quebrado, a seta ficava solta no fim da primeira. */
.custo-saldo-desenho { display: flex; flex-wrap: wrap; align-items: flex-end; gap: .25rem .75rem; }
.custo-saldo-par { display: flex; flex-direction: column; gap: .125rem; }
.custo-saldo-rotulo { font: 500 .8125rem/1.3 var(--sans); color: var(--tinta-2); }
.custo-saldo-n { font: 600 clamp(1.25rem, 5.5vw, 1.5rem)/1.1 var(--sans); font-variant-numeric: tabular-nums; white-space: nowrap; }
.custo-saldo-unidade { font-size: .875rem; font-weight: 400; color: var(--tinta-2); }
.custo-saldo-seta { font: 400 1.25rem/1.4 var(--sans); color: var(--tinta-2); }
.custo-saldo-aviso { font: 400 .9375rem/1.45 var(--sans); color: var(--tinta-2); }
.custo-botoes { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: .5rem; }
.custo-botoes .btn { min-height: 44px; padding: 0 1rem; font-size: .9375rem; }

/* O estado da fila no cabeçalho (§5.3): só aparece quando há o que dizer. */
.fila-estado { font: 500 .8rem/1.3 var(--sans); color: var(--tinta-2); }
.fila-estado[data-fila="bloqueada"] { color: var(--perigo); }
.fila-estado:empty { display: none; }

/* O subtítulo do destino na lateral do Mac («seus estudos», spec 53 §5.1).
   Classe e não `style=`: a CSP do app não deixa passar estilo inline. */
#barra-nav .nav-sub small { font-size: 11px; font-weight: 400; opacity: .85; }

/* ── O glifo de pausa desenhado, no meio de uma linha de texto  (16/09) ─────
   Na cápsula o botão é flex e centra sozinho; no «Pausar» do cabeçalho e no
   transporte o SVG senta na linha de base e fica alto demais. O deslocamento
   é o de um ícone de 1em sobre texto de x-height comum. */
svg[data-glifo="pausa"] { vertical-align: -.14em; }

/* ── O boletim não lido (spec 62) ── */
/* Um ponto no ícone do destino Notícias quando alguma gazeta tem edição que a
   pessoa ainda não abriu. Ponto e não número: os números saíram dos destinos
   em 04/09. `--cromo-acento` porque o campo é grafite nos dois modos (o mesmo
   motivo do ícone do ativo). O anel de cromo em volta separa o ponto do traço
   do ícone quando os dois se tocam. Forma, e não só cor: quem não distingue o
   acento ainda vê um círculo cheio onde o ícone não tem. */
#barra-nav a[data-novo] .ic { position: relative; }
#barra-nav a[data-novo] .ic::after {
  content: ""; position: absolute; top: -2px; right: -4px;
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--cromo-acento);
  box-shadow: 0 0 0 2px var(--cromo-1);
}
/* A linha que diz QUAL: só na lateral. Na barra do telefone cada destino é
   uma coluna de 58px, e uma terceira linha empurraria a barra inteira — ali
   fica o ponto, e o nome vai no rótulo de acessibilidade. */
.nav-aviso { display: none; }
@media (min-width: 1100px) and (pointer: fine) {
  #barra-nav .nav-aviso { display: inline; }
  #barra-nav .nav-aviso small {
    font-size: 11px; font-weight: 400; color: var(--cromo-tenue);
  }
}
/* O ponto no título da gazeta, quando ela é a única (com várias, vai no texto
   da opção do seletor). */
.ponto-novo {
  display: inline-block; width: 8px; height: 8px; border-radius: 50%;
  background: var(--acento); vertical-align: middle; margin-left: .35em;
}
/* ── fim do boletim não lido ── */

/* ── Notícias (spec 59) ── */
/* ═══════════════════════════════════════════════════════════════════════════
   O destino «Notícias»: a casca, o Boletim, o Feed, as Fontes e os Ajustes
   (spec 59 §4 · L-309). Bloco próprio, no fim do arquivo, só com tokens — os
   três temas vêm de graça, e o teste das Notícias recusa cor crua e token
   que não existe aqui dentro.

   A régua é a do app, e não uma nova: título em serifa, navegação em sans,
   superfícies do núcleo, alvo de 44px em tudo que se toca. O único gesto
   próprio é o NÚMERO do Boletim — o `n` do contrato pendurado na margem,
   em algarismo de texto e na cor do acento. A edição é uma sequência
   numerada de verdade (o `n` é contínuo de ponta a ponta, §8), e é o número
   que a pessoa usa para voltar a um item («o 7 de ontem»); por isso ele
   ganha a margem, e o resto da página fica quieto em volta.
   ═════════════════════════════════════════════════════════════════════════ */

/* O Feed precisa da coluna de seções AO LADO da lista no iPad e no Mac; a
   medida de leitura sozinha não comporta as duas. A prosa do Boletim, dos
   Ajustes e das Fontes continua na medida (ver as telas abaixo). */
body[data-rota^="noticias"] main { max-width: calc(var(--measure) + 14rem); }

/* O filete das listas. O `--regra` do núcleo é desenhado para a FOLHA
   (`--papel`), e as listas das Notícias moram na MESA (`--tela`): no tema
   claro, `--regra` #e6e2d9 sobre `--tela` #e8e2d7 dá contraste 1,0 — o Feed
   de 138 linhas por dia saía sem uma divisória visível (Safari, L-310). A
   tinta a 14% sobre transparente vale nas duas superfícies e nos três temas,
   porque compõe com o que estiver embaixo. */
.noticias { --regra-mesa: color-mix(in srgb, var(--tinta) 14%, transparent); }

/* ── A casca ─────────────────────────────────────────────────────────────── */
.cabeca-noticias {
  display: flex; align-items: center; flex-wrap: wrap; gap: .35rem .9rem; margin: 0 0 .9rem;
}
.cabeca-noticias .titulo-tela { margin: 0; }
.gazeta-titulo {
  margin: 0; font-family: var(--serif); font-style: italic; font-size: 1.3rem;
  line-height: 1.25; color: var(--tinta-2);
}
.gazeta-escolha { position: relative; }
.gazeta-escolha select {
  -webkit-appearance: none; appearance: none; min-height: var(--alvo); box-sizing: border-box;
  font-family: var(--serif); font-style: italic; font-size: 1.15rem; color: var(--tinta);
  background: var(--papel-elev); border: 1px solid var(--borda-controle); border-radius: 10px;
  padding: 0 2rem 0 .75rem; cursor: pointer;
}
.engrenagem {
  margin-left: auto; flex: none; display: inline-flex; align-items: center; justify-content: center;
  width: var(--alvo); height: var(--alvo); border-radius: var(--raio-p); color: var(--tinta-2);
}
.engrenagem svg { width: 22px; height: 22px; }
.engrenagem:hover, .engrenagem:focus-visible { color: var(--acento); }
.engrenagem[aria-current] { color: var(--tinta); background: var(--papel-elev-2); }
.abas-config { margin-top: -.4rem; }
/* O segmentado do app nasceu para a inbox, com 38px; aqui ele é a navegação
   principal do destino, tocado a cada troca de vista, e a régua das Notícias
   é o alvo de 44 (medido no Safari, L-310: 38 nas duas fileiras de abas). */
.abas.seg:is(.abas-noticias, .abas-config) .aba { min-height: var(--alvo); box-sizing: border-box; }

.noticias .btn {
  min-height: var(--alvo); display: inline-flex; align-items: center; justify-content: center;
  gap: .4rem; text-decoration: none; box-sizing: border-box;
}
.noticias .botoes { display: flex; flex-wrap: wrap; gap: .5rem; }
.noticias :is(input:not([type="radio"]):not([type="checkbox"]):not([type="file"]), textarea, select):focus-visible,
.noticias :is(a, button):focus-visible {
  outline: 2px solid var(--foco); outline-offset: 2px;
}

/* Os campos: o mesmo aro dos filtros das decisões — sobre `--tela`, a borda
   `--borda-controle` é a única pista de que isto é um campo. */
.noticias :is(input[type="text"], input:not([type]), input[type="search"], input[type="number"],
  input[type="date"], input[type="time"], textarea, select):not(.gazeta-escolha select) {
  min-height: var(--alvo); box-sizing: border-box; width: 100%;
  font-family: var(--sans); font-size: .95rem; color: var(--tinta);
  background: var(--papel-elev); border: 1px solid var(--borda-controle); border-radius: 10px;
  padding: 0 .7rem;
}
.noticias textarea { padding: .6rem .7rem; line-height: 1.5; resize: vertical; }
/* O `<select>` nativo do Safari ignora o `min-height` (medido em 14/09 nas
   decisões): sem a aparência nativa ele obedece, e a seta volta desenhada
   pelo rótulo — a CSP não aceita `data:` numa imagem de fundo. */
.noticias select { -webkit-appearance: none; appearance: none; padding-right: 2rem; }
.noticias label:has(> select) { position: relative; }
.noticias label:has(> select)::after {
  content: "▾"; position: absolute; right: .75rem; bottom: 0; height: var(--alvo);
  display: flex; align-items: center; pointer-events: none; font-size: .9rem; color: var(--tinta-2);
}
.noticias label > span:first-child:not(.so-leitor) {
  display: block; margin: 0 0 .25rem; font-family: var(--sans); font-size: .78rem; font-weight: 600;
  color: var(--tinta-2);
}
.noticias .gazeta-escolha > span:first-child { display: none; }

.aviso-noticias {
  font-family: var(--sans); font-size: .84rem; color: var(--tinta-2);
  border-left: 3px solid var(--acento); padding: .4rem .7rem; margin: .2rem 0 .9rem;
}
.recado-noticias {
  font-family: var(--sans); font-size: .9rem; line-height: 1.5; color: var(--tinta);
  background: var(--papel-elev); border: 1px solid var(--papel-borda); border-radius: var(--raio);
  padding: .7rem .9rem; margin: 0 0 1rem;
}
.recado-noticias p { margin: 0; }
.recado-noticias summary { min-height: var(--alvo); display: flex; align-items: center; cursor: pointer; color: var(--tinta-2); }
.noticias .url { font-family: var(--mono); font-size: .8rem; overflow-wrap: anywhere; }

/* ── Os modelos: sem gazeta, a tela oferece por onde começar ─────────────── */
.modelos-intro { max-width: var(--measure); font-size: .9rem; line-height: 1.5; }
.modelos {
  list-style: none; margin: 1rem 0 2rem; padding: 0;
  display: grid; gap: 1rem; grid-template-columns: repeat(auto-fill, minmax(16rem, 1fr));
}
.modelo {
  display: flex; flex-direction: column; gap: .5rem; padding: 1.1rem 1.2rem 1rem;
  background: var(--papel-elev); border: 1px solid var(--papel-borda-fina); border-radius: 14px;
  box-shadow: var(--sombra-erguida);
}
.modelo h2 { font-family: var(--serif); font-size: 1.25rem; line-height: 1.2; font-weight: 600; margin: 0; }
.modelo-descricao { font-family: var(--serif); font-size: .98rem; line-height: 1.45; margin: 0; color: var(--tinta); }
.modelo-meta { font-family: var(--sans); font-size: .8rem; line-height: 1.45; color: var(--tinta-2); margin: 0; }
.modelo-acao { margin-top: auto; padding-top: .3rem; display: grid; gap: .5rem; }

/* ── O Feed ──────────────────────────────────────────────────────────────── */
.feed-grade { display: grid; grid-template-columns: minmax(0, 1fr); gap: .7rem; }
/* Abaixo de 40rem, as seções são a fileira de fichas rolável da barra do
   telefone; acima, uma coluna ao lado que fica parada enquanto a lista rola. */
.secoes-feed {
  display: flex; gap: .4rem; overflow-x: auto; scrollbar-width: none; padding-bottom: .15rem;
  font-family: var(--sans);
}
.secoes-feed::-webkit-scrollbar { display: none; }
.secao-feed {
  flex: none; min-height: var(--alvo); display: inline-flex; align-items: center; box-sizing: border-box;
  padding: 0 .9rem; border: 1px solid var(--borda-controle); border-radius: 999px;
  background: var(--papel-elev); color: var(--tinta-2); text-decoration: none;
  font-size: .84rem; font-weight: 500; white-space: nowrap;
}
.secao-feed:hover { color: var(--acento); }
.secao-feed[aria-current] {
  color: var(--tinta); font-weight: 600; border-color: var(--acento);
  background: color-mix(in srgb, var(--acento) 10%, var(--papel-elev));
}
@media (min-width: 37rem) {
  .feed-grade { grid-template-columns: 11rem minmax(0, 1fr); gap: 1.5rem; align-items: start; }
  .secoes-feed {
    flex-direction: column; gap: .1rem; overflow: visible; position: sticky; top: 1rem;
  }
  .secao-feed {
    border: 0; background: none; border-radius: var(--raio-p); padding: .55rem .75rem;
    white-space: normal; line-height: 1.3;
  }
  .secao-feed[aria-current] { background: var(--papel-elev-2); box-shadow: inset 3px 0 0 var(--acento); }
}

.ferramentas-feed { display: flex; gap: .5rem; align-items: center; margin: 0 0 .4rem; }
.busca-feed { flex: 1; margin: 0; }
.ferramentas-feed [data-selecionar][aria-pressed="true"] { color: var(--acento); border-color: var(--acento); }

.feed { list-style: none; margin: 0; padding: 0; }
.feed ul { list-style: none; margin: 0; padding: 0; }
.dia-feed h2 {
  display: flex; align-items: center; gap: .6rem; margin: 1.3rem 0 .2rem;
  font-family: var(--sans); font-size: .8rem; font-weight: 600; color: var(--tinta-2);
}
.dia-feed:first-child h2 { margin-top: .6rem; }
.dia-feed h2::after { content: ""; flex: 1; border-top: 1px solid var(--regra-mesa); }

.item-feed { display: grid; grid-template-columns: minmax(0, 1fr); border-bottom: 1px solid var(--regra-mesa); }
.feed.selecionando .item-feed { grid-template-columns: var(--alvo) minmax(0, 1fr); }
.feed.selecionando .item-feed > :not(.marcar-feed) { grid-column: 2; }
.marcar-feed { display: flex; align-items: flex-start; justify-content: center; padding-top: .85rem; cursor: pointer; }
.marcar-feed input { width: 1.15rem; height: 1.15rem; margin: 0; accent-color: var(--acento); }

.linha-feed {
  -webkit-appearance: none; appearance: none; background: none; border: 0; margin: 0;
  width: 100%; min-height: var(--alvo); box-sizing: border-box; padding: .7rem .15rem;
  display: grid; gap: .15rem; text-align: left; color: var(--tinta); font: inherit; cursor: pointer;
}
.linha-feed:hover .titulo { color: var(--acento); }
.linha-feed:focus-visible { outline: 2px solid var(--foco); outline-offset: 2px; border-radius: var(--raio-p); }
.linha-feed .meta {
  font-family: var(--sans); font-size: .74rem; color: var(--tenue); font-variant-numeric: tabular-nums;
}
.linha-feed .titulo { font-family: var(--serif); font-size: 1.02rem; line-height: 1.35; font-weight: 600; }
/* Uma linha de resumo, e não mais: a lista é para varrer. O inteiro abre no lugar. */
.linha-feed .resumo {
  font-family: var(--sans); font-size: .84rem; color: var(--tinta-2);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.item-feed.aberto .linha-feed .resumo { display: none; }
.aberta-feed { padding: 0 .15rem .9rem; }
.resumo-inteiro {
  font-family: var(--corpo, var(--serif)); font-size: .98rem; line-height: 1.55; color: var(--tinta); margin: 0 0 .7rem;
}
.acoes-feed { display: flex; flex-wrap: wrap; gap: .5rem; align-items: center; }
.item-feed > .enviada { justify-self: start; margin: -.35rem 0 .6rem .15rem; }
.noticias .enviada {
  display: inline-flex; align-items: center; gap: .35rem;
  font-family: var(--sans); font-size: .76rem; font-weight: 600; color: var(--tinta-2);
}
.noticias .enviada::before { content: "✓"; color: var(--acento); }
.noticias .enviando { font-family: var(--sans); font-size: .8rem; color: var(--tinta-2); }
.noticias .erro-envio { font-family: var(--sans); font-size: .84rem; color: var(--tinta); margin: .5rem 0 0; }

/* A linha fina: não é contador, é um marco — «daqui para cima é novo». */
.novos-desde {
  display: flex; align-items: center; gap: .6rem; margin: .45rem 0;
  font-family: var(--sans); font-size: .74rem; font-weight: 500; color: var(--acento);
}
.novos-desde::before, .novos-desde::after { content: ""; flex: 1; border-top: 1px solid var(--acento); }

/* O `sticky` mora no LUGAR da barra, e não nela: um elemento pegajoso só
   anda dentro do próprio pai, e o pai da barra é o `.selecao-lugar`, da
   altura dela. Pregada na barra, ela ficava no fim da lista — a 2.000px da
   janela no Safari (L-310) —, e «Mandando 2 de 4» acontecia fora da vista.
   O pai do lugar é a coluna inteira, e é nela que ele anda. */
.selecao-lugar { position: sticky; bottom: calc(var(--barra-h) + .75rem); z-index: 5; }
.barra-selecao {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: .5rem;
  margin-top: .8rem; padding: .5rem; box-sizing: border-box;
  background: var(--papel-elev); border: 1px solid var(--papel-borda); border-radius: var(--raio);
  box-shadow: var(--sombra-erguida);
}
.progresso-envio {
  margin: 0 auto 0 .4rem; font-family: var(--sans); font-size: .9rem; font-weight: 600;
  font-variant-numeric: tabular-nums; color: var(--tinta);
}
.resultado-envio {
  font-family: var(--sans); font-size: .9rem; line-height: 1.5; color: var(--tinta);
  background: var(--papel-elev); border-left: 3px solid var(--acento);
  border-radius: 0 var(--raio-p) var(--raio-p) 0; padding: .6rem .9rem; margin: 0 0 1rem;
}
.resultado-envio p { margin: 0 0 .3rem; }
.resultado-envio ul { margin: 0 0 .5rem; padding-left: 1.1rem; }
.feed-vazio a { color: var(--acento); }

/* ── O Boletim ───────────────────────────────────────────────────────────── */
/* A edição é uma FOLHA, a mesma do artigo (`.artigo`): `--papel` pousado na
   mesa, a coluna em `--measure` e o corpo na tipografia de leitura do dono
   (`--corpo`, `--size`, `--leading`), porque a edição se lê, não se opera.
   A primeira versão pôs só o destaque num cartão e deixou os blocos direto
   na mesa; a segunda deu um cartão a cada bloco — e o dono respondeu que
   continuava chapado: rótulos em sans a 12px, MENORES que o texto que
   rotulavam, e tudo no mesmo peso. Aqui a hierarquia é de jornal, feita só
   com tamanho, peso e régua:
     · a manchete da edição a 2em, e um fio cheio embaixo do cabeçalho;
     · o destaque com título a 1.55em e as partes em cabeça corrida —
       «O que é.» em itálico, no corpo do texto e na cor do acento;
     · o bloco abre com fio cheio e o nome em serifa, maior que o título
       dos itens que ele contém;
     · o pé do item é uma linha só, em sans miúda — serviço, não notícia.
   O arquivo do mês fica fora da folha, na mesa: é navegação. */
.boletim-tela { max-width: calc(var(--measure) + var(--respiro) * 2); margin: 0 auto; }
.boletim-tela > :not(.boletim) { max-width: var(--measure); margin-left: auto; margin-right: auto; }
.boletim {
  padding: 2.4rem var(--respiro) 2rem; margin: .4rem 0 0;
  background: var(--papel); border-radius: var(--raio); box-shadow: var(--sombra-pousada);
  font-family: var(--corpo); font-size: var(--size); line-height: var(--leading); color: var(--tinta);
  --regra-mesa: color-mix(in srgb, var(--tinta) 13%, transparent);
}
/* O mesmo problema da `.artigo` no escuro: papel e mesa a 1,004:1. */
[data-tema="escuro"] .boletim { border: 1px solid var(--papel-borda); }
@media (max-width: 900px) {
  .boletim { border-radius: 0; padding-left: max(1.1rem, env(safe-area-inset-left)); padding-right: max(1.1rem, env(safe-area-inset-right)); }
}

.cabeca-edicao { margin: 0 0 2rem; padding: 0 0 1.1rem; border-bottom: 2px solid var(--tinta); }
.titulo-edicao {
  font-family: var(--corpo); font-size: 2em; line-height: 1.12; letter-spacing: -.015em;
  font-weight: 600; margin: 0 0 .45rem; text-wrap: balance;
}
.estado-edicao { font-family: var(--corpo); font-style: italic; font-size: .88em; line-height: 1.45; color: var(--tinta-2); margin: 0; }
.cabeca-edicao .ouvir-edicao { margin-top: .9rem; }
.escritores {
  display: inline-flex; flex-wrap: wrap; gap: 2px; padding: 3px; margin: 0 0 1.1rem;
  background: var(--papel-elev-2); border-radius: var(--raio-p); font-family: var(--sans);
}
.escritores a {
  min-height: var(--alvo); display: inline-flex; align-items: center; padding: 0 .9rem;
  border-radius: calc(var(--raio-p) - 2px); font-size: .86rem; font-weight: 500;
  color: var(--tinta-2); text-decoration: none;
}
.escritores a[aria-current] { background: var(--papel-elev); color: var(--tinta); font-weight: 600; box-shadow: var(--sombra-pousada); }

/* O número pendurado. A grade tem duas colunas — o `n` e o texto — e o
   cabeçalho do item se dissolve nela (`display: contents`): o número senta
   na linha de base do título, e tudo o que vem depois alinha pela segunda
   coluna. Com respiro que caiba (≥ 1100px), a coluna do número sai para a
   margem da folha e o texto dos itens alinha com a manchete. */
.destaque-edicao, .item-edicao {
  display: grid; grid-template-columns: 2.4rem minmax(0, 1fr); column-gap: .7rem; align-items: baseline;
}
.destaque-edicao > *, .item-edicao > * { grid-column: 2; }
.destaque-edicao > header, .item-edicao > header { display: contents; }
.destaque-edicao .n, .item-edicao .n {
  grid-column: 1; grid-row: 1; justify-self: end;
  font-family: var(--corpo); font-weight: 400; line-height: 1; color: var(--acento);
  font-variant-numeric: oldstyle-nums proportional-nums;
}
.destaque-edicao :is(h2, h3), .item-edicao :is(h2, h3) { grid-column: 2; grid-row: 1; margin: 0; }

.destaque-edicao { padding: 0 0 1.6rem; margin: 0 0 1.8rem; border-bottom: 1px solid var(--regra-mesa); }
.destaque-edicao .n { font-size: 2.1em; }
.destaque-edicao h2 {
  font-family: var(--corpo); font-size: 1.55em; line-height: 1.18; letter-spacing: -.01em;
  font-weight: 600; text-wrap: pretty;
}
.partes { margin: .7em 0 .5em; }
.partes > div { margin: 0 0 .85em; text-wrap: pretty; }
/* Cabeça corrida: o rótulo abre o parágrafo, no tamanho do texto. */
.partes dt { display: inline; font-style: italic; font-weight: 600; color: var(--acento); }
.partes dt::after { content: ".\2002"; }
.partes dd { display: inline; margin: 0; }
.boletim :is(.partes dd, .texto) a { color: var(--acento); text-underline-offset: 3px; }
.boletim :is(.partes dd, .texto) code { font-family: var(--mono); font-size: .88em; }

.bloco-edicao { margin: 2.6rem 0 0; }
.destaques-edicao + .bloco-edicao { margin-top: 2.2rem; }
.bloco-edicao > h2 {
  font-family: var(--corpo); font-size: 1.3em; line-height: 1.2; font-weight: 600; color: var(--tinta);
  margin: 0; padding: .55rem 0 0; border-top: 2px solid var(--tinta);
}
.itens-edicao { list-style: none; margin: 0; padding: 0; }
.item-edicao { padding: 1.1rem 0 .9rem; border-bottom: 1px solid var(--regra-mesa); }
.item-edicao:last-child { border-bottom: 0; padding-bottom: 0; }
.item-edicao .n { font-size: 1.4em; }
.item-edicao h3 { font-family: var(--corpo); font-size: 1.2em; line-height: 1.26; font-weight: 600; text-wrap: pretty; }
.item-edicao .texto { font-size: .95em; line-height: var(--leading); margin: .35em 0 .3em; text-wrap: pretty; }
/* Depois das regras de `margin` do destaque e do item: `@media` não empresta
   peso, e escrita antes ela era zerada por elas. */
@media (min-width: 1100px) {
  .destaque-edicao, .item-edicao { margin-left: -3.1rem; }
}
/* No telefone a coluna do número encolhe: 2,4rem de 390px é texto perdido. */
@media (max-width: 600px) {
  .destaque-edicao, .item-edicao { grid-template-columns: 1.5rem minmax(0, 1fr); column-gap: .45rem; }
  .destaque-edicao .n { font-size: 1.7em; }
  .titulo-edicao { font-size: 1.65em; }
}

/* O pé: de onde veio, o fio e os gestos, numa linha que quebra se precisar.
   Os alvos continuam com `--alvo` de altura; o que saiu foi a moldura. */
.pe-item {
  display: flex; flex-wrap: wrap; align-items: center; gap: 0 .9rem;
  font-family: var(--sans); font-size: .78rem; line-height: 1.3; color: var(--tinta-2);
}
.fontes-edicao { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 0 .9rem; }
.fontes-edicao li { display: inline-flex; align-items: center; flex-wrap: wrap; gap: 0 .5rem; }
/* O nome da fonte é link e é alvo: com 44 de altura ele fica na mesma linha
   de base do «Mandar para…» ao lado, e o «AP» de duas letras deixa de ser
   um alvo de 17px (medido no Safari, L-310). */
.fontes-edicao .fonte-nome {
  min-height: var(--alvo); min-width: var(--alvo); box-sizing: border-box;
  display: inline-flex; align-items: center; color: var(--tinta-2); font-weight: 500;
  text-decoration-color: color-mix(in srgb, currentColor 40%, transparent); text-underline-offset: 3px;
}
.fontes-edicao .fonte-nome:hover { color: var(--tinta); }
.enviar-fonte {
  min-height: var(--alvo); padding: 0 .25rem; background: none; border: 0; cursor: pointer;
  font-family: var(--sans); font-size: .78rem; font-weight: 600; color: var(--acento);
}
.enviar-fonte:hover { text-decoration: underline; text-underline-offset: 3px; }
.fio {
  min-height: var(--alvo); display: inline-flex; align-items: center; padding: 0 .3rem; cursor: pointer;
  background: none; border: 0; font-family: var(--sans); font-size: .78rem; font-style: italic; color: var(--tinta-2);
}
.fio:hover, .fio[aria-expanded="true"] { color: var(--acento); }
.edicoes-do-fio ul { margin: 0 0 .4rem; padding-left: 1.1rem; font-family: var(--sans); font-size: .86rem; line-height: 1.5; }
.edicoes-do-fio a { display: inline-block; padding: .35rem 0; color: var(--tinta); }

.gestos { display: flex; flex-wrap: wrap; gap: .15rem; margin: 0 0 0 auto; }
.gesto {
  min-height: var(--alvo); padding: 0 .6rem; cursor: pointer; background: transparent;
  border: 0; border-radius: 999px;
  font-family: var(--sans); font-size: .76rem; font-weight: 500; color: var(--tenue);
}
.gesto:hover { color: var(--acento); }
.gesto[aria-pressed="true"] { background: var(--tinta); color: var(--papel); }
.rodape-edicao {
  font-family: var(--sans); font-size: .78rem; line-height: 1.5; color: var(--tenue);
  margin: 2rem 0 0; padding: .9rem 0 0; border-top: 1px solid var(--regra-mesa);
}
.boletim-vazio { padding: 2rem 0 1rem; font-family: var(--sans); font-size: .95rem; line-height: 1.6; color: var(--tinta-2); }
.boletim-vazio a { color: var(--acento); }

.arquivo { margin: 2.8rem 0 1rem; padding-top: 1.2rem; border-top: 1px solid var(--regra-mesa); }
.arquivo h2 { font-family: var(--serif); font-size: 1.12rem; font-weight: 600; margin: 0; }
.arquivo-nav { display: flex; justify-content: space-between; gap: 1rem; margin: .2rem 0 .5rem; }
.arquivo-nav a {
  min-height: var(--alvo); display: inline-flex; align-items: center;
  font-family: var(--sans); font-size: .86rem; color: var(--tinta-2);
}
.busca-arquivo { margin: 0 0 .5rem; }
.arquivo-edicoes { list-style: none; margin: 0; padding: 0; font-family: var(--sans); }
.arquivo-edicoes li { border-bottom: 1px solid var(--regra-mesa); }
.arquivo-edicoes a, .arquivo-edicoes .nao-saiu {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: .1rem .7rem;
  min-height: var(--alvo); box-sizing: border-box; padding: .6rem 0; text-decoration: none; color: var(--tinta);
}
.arquivo-edicoes .data { flex: none; min-width: 7.5rem; font-size: .8rem; font-weight: 600; color: var(--tinta-2); }
.arquivo-edicoes .titulo { font-family: var(--serif); font-size: .98rem; }
/* «do motor» vai DEPOIS do título: antes dele, os títulos das edições do
   motor começavam mais à direita que os da skill, e a coluna de títulos do
   arquivo saía serrilhada (Safari, L-310). */
.arquivo-edicoes .escritor { order: 1; font-size: .74rem; color: var(--tenue); }
.arquivo-edicoes .nao-saiu { font-size: .86rem; color: var(--tinta-2); }

/* ── As Fontes ───────────────────────────────────────────────────────────── */
.fontes-tela, .ajustes-tela { max-width: var(--measure); margin: 0 auto; }
.adicionar-fonte, .nova-secao {
  display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: .5rem; align-items: end; margin: 0 0 1rem;
}
.adicionar-fonte .erro-lugar, .nova-secao .erro-lugar { grid-column: 1 / -1; }
.nova-secao { margin-top: 1.6rem; }
.previa-fonte {
  display: grid; gap: .6rem; padding: 1rem; margin: 0 0 1.4rem;
  background: var(--papel-elev); border: 1px solid var(--papel-borda); border-radius: var(--raio);
  box-shadow: var(--sombra-pousada);
}
.previa-endereco { margin: 0; font-family: var(--mono); font-size: .8rem; color: var(--tinta-2); overflow-wrap: anywhere; }
.previa-fonte .sub { margin: 0; }
.itens-previa { margin: 0; padding-left: 1.3rem; font-family: var(--serif); font-size: .95rem; line-height: 1.45; }
.itens-previa .data { font-family: var(--sans); font-size: .76rem; color: var(--tenue); }

.secao-fontes { margin: 1.5rem 0 0; }
.secao-fontes > header {
  display: flex; align-items: center; flex-wrap: wrap; gap: .4rem .6rem;
  padding-bottom: .3rem; border-bottom: 1px solid var(--regra-mesa);
}
.secao-fontes > header h2 { flex: 1 1 10rem; margin: 0; font-family: var(--serif); font-size: 1.08rem; font-weight: 600; }
.secao-acoes, .fonte-acoes { display: inline-flex; gap: .35rem; }
.secao-acoes .btn, .fonte-acoes .btn {
  background: transparent; color: var(--tinta); border: 1px solid var(--borda-controle); box-shadow: none;
}
.lista-fontes-secao { list-style: none; margin: 0; padding: 0; }
.fonte { padding: .55rem 0; border-bottom: 1px solid var(--regra-mesa); }
/* Uma grade, e não um flex que quebra: com flex, a fonte de nome curto e
   saúde curta («NIST · viva») cabia numa linha e a de saúde longa («morta:
   404») jogava os botões para a linha de baixo — no iPhone, cada fonte saía
   com um desenho (Safari, L-310). Aqui os botões têm sempre a mesma coluna à
   direita, e a saúde desce para baixo do nome abaixo de 40rem. */
.fonte-linha {
  display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; gap: .1rem .7rem;
}
.fonte-linha .fonte-nome { grid-column: 1; font-family: var(--serif); font-size: .98rem; font-weight: 600; overflow-wrap: anywhere; }
.fonte-linha .saude { grid-column: 1; grid-row: 2; }
.fonte-linha .fonte-acoes { grid-column: 2; grid-row: 1 / span 2; }
@media (min-width: 37rem) {
  .fonte-linha { grid-template-columns: minmax(0, 1fr) auto auto; }
  .fonte-linha .saude { grid-column: 2; grid-row: 1; }
  .fonte-linha .fonte-acoes { grid-column: 3; grid-row: 1; }
}
.fonte-site { margin: .1rem 0 0; font-family: var(--sans); font-size: .76rem; color: var(--tenue); overflow-wrap: anywhere; }

/* A saúde é dita em palavras; o ponto só a acompanha — nunca só cor. Viva é
   o ponto cheio, quieta é o ponto cheio em tom tênue (está bem, só publica
   pouco: nada de perigo, que 41 de 102 em vermelho ensinavam a não olhar),
   vazia é o aro, morta vem na cor de perigo, e a que ainda não foi lida é o
   aro fino e tênue. (Era tracejado: num círculo de 8px o
   tracejado do Safari vira dois riscos soltos, e a captura da L-310 mostrou
   um glifo quebrado, e não um aro.) */
.saude {
  display: inline-flex; align-items: center; gap: .35rem;
  font-family: var(--sans); font-size: .76rem; font-weight: 500; color: var(--tinta-2);
}
.saude::before {
  content: ""; width: .5rem; height: .5rem; border-radius: 50%; box-sizing: border-box;
  background: var(--tinta-2); border: 1.5px solid var(--tinta-2);
}
.saude[data-estado="quieto"]::before { background: var(--tenue); border-color: var(--tenue); }
.saude[data-estado="vazio"]::before { background: transparent; }
.saude[data-estado="nova"]::before { background: transparent; border-width: 1px; border-color: var(--tenue); }
.saude[data-estado="morto"] { color: var(--perigo); }
.saude[data-estado="morto"]::before { background: var(--perigo); border-color: var(--perigo); }

:is(.editar-fonte, .renomear-secao, .apagar-secao) {
  display: grid; gap: .6rem; padding: .8rem; margin: .5rem 0;
  background: var(--papel-elev-2); border-radius: var(--raio-p);
}
.apagar-secao p { margin: 0; font-family: var(--sans); font-size: .9rem; }

.opml { margin: 2.2rem 0 1rem; padding-top: 1rem; border-top: 1px solid var(--regra-mesa); }
.opml h2 { font-family: var(--serif); font-size: 1.08rem; font-weight: 600; margin: 0 0 .3rem; }
.importar-opml { cursor: pointer; }
.importar-opml:focus-within { outline: 2px solid var(--foco); outline-offset: 2px; }
.resultado-opml { font-family: var(--sans); font-size: .88rem; line-height: 1.5; margin-top: .7rem; }
.resultado-opml p { margin: 0 0 .3rem; }
.resultado-opml ul { margin: 0; padding-left: 1.1rem; }

/* ── Os Ajustes ──────────────────────────────────────────────────────────── */
.ajustes-gazeta { display: grid; gap: 1.4rem; }
.ajustes-gazeta .campo { border: 0; margin: 0; padding: 0; min-width: 0; display: grid; gap: .45rem; }
.ajustes-gazeta legend { padding: 0; margin: 0 0 .3rem; font-family: var(--serif); font-size: 1.05rem; font-weight: 600; }
.ajustes-gazeta .sub { margin: 0; line-height: 1.45; }
.frequencia-atual {
  margin: 0; font-family: var(--sans); font-size: .86rem; color: var(--tinta-2);
  border-left: 3px solid var(--acento); padding: .35rem .7rem;
}
.conta-criterio { margin: 0; text-align: right; font-variant-numeric: tabular-nums; }
.erro-campo { margin: 0; font-family: var(--sans); font-size: .84rem; font-weight: 600; color: var(--perigo); }
.erro-campo:empty { display: none; }

.blocos-ajuste, .partes-ajuste { list-style: none; margin: 0; padding: 0; display: grid; gap: .5rem; }
.bloco-ajuste {
  display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: .5rem; align-items: end; padding: .7rem;
  background: var(--papel-elev); border: 1px solid var(--papel-borda); border-radius: var(--raio-p);
}
.bloco-campos { display: grid; gap: .45rem; }
.bloco-botoes { display: flex; gap: .3rem; }
.bloco-botoes .btn { min-width: var(--alvo); }
.partes-ajuste li { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: .5rem; align-items: center; }
@media (max-width: 37rem) { .bloco-ajuste { grid-template-columns: minmax(0, 1fr); } }
.ajustes-gazeta [data-mais-bloco], .ajustes-gazeta [data-mais-parte] { justify-self: start; }

.segmentado-ajuste {
  display: inline-flex; flex-wrap: wrap; gap: 2px; padding: 3px; justify-self: start;
  background: var(--papel-elev-2); border-radius: var(--raio-p);
}
.opcao-radio { position: relative; display: inline-flex; }
.opcao-radio input { position: absolute; inset: 0; margin: 0; opacity: 0; cursor: pointer; }
.segmentado-ajuste .opcao-radio span {
  min-height: var(--alvo); min-width: var(--alvo); box-sizing: border-box; padding: 0 .9rem;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: calc(var(--raio-p) - 2px); font-family: var(--sans); font-size: .86rem; font-weight: 500; color: var(--tinta-2);
}
.segmentado-ajuste .opcao-radio input:checked + span {
  background: var(--papel-elev); color: var(--tinta); font-weight: 600; box-shadow: var(--sombra-pousada);
}
.opcao-radio input:focus-visible + span { outline: 2px solid var(--foco); outline-offset: 1px; }

.freq-campos { display: flex; flex-wrap: wrap; gap: .6rem 1rem; align-items: end; }
.freq-campos label { display: grid; gap: .25rem; min-width: 8rem; flex: 1 1 8rem; }
.frequencia[data-tipo="diaria"] [data-para],
.frequencia[data-tipo="semanal"] [data-para="cada"],
.frequencia[data-tipo="cada"] [data-para="semanal"] { display: none; }

.escritores-ajuste { display: grid; gap: .4rem; }
.escritores-ajuste .opcao-radio { display: block; }
.escritores-ajuste .opcao-radio span {
  display: block; min-height: var(--alvo); box-sizing: border-box; padding: .6rem .8rem;
  border: 1px solid var(--borda-controle); border-radius: var(--raio-p);
  font-family: var(--sans); font-size: .88rem; line-height: 1.4; color: var(--tinta-2);
}
.escritores-ajuste .opcao-radio strong { color: var(--tinta); font-weight: 600; }
.escritores-ajuste .opcao-radio input:checked + span {
  border-color: var(--acento); background: color-mix(in srgb, var(--acento) 8%, var(--papel-elev));
}

.salvar-ajustes { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem 1rem; }
.estado-ajustes { margin: 0; font-family: var(--sans); font-size: .88rem; color: var(--tinta-2); }
.outras-gazetas { margin: 2rem 0 0; }
.zona-apagar {
  margin: 2.4rem 0 1rem; padding: 1rem; border-radius: var(--raio);
  border: 1px solid color-mix(in srgb, var(--perigo) 45%, transparent);
}
.zona-apagar h2 { font-family: var(--serif); font-size: 1.02rem; font-weight: 600; margin: 0 0 .3rem; }
.zona-apagar .sub { margin: 0 0 .7rem; }
.noticias .btn.perigo { background: transparent; color: var(--perigo); border-color: currentColor; box-shadow: none; }

/* ── Listas de Leitura (spec 61) ── */
/* ═══════════════════════════════════════════════════════════════════════════
   A lista é uma fila, na ordem — e a tela diz isso: número à esquerda, o
   título, e os gestos à direita. Só tokens do núcleo, e os três temas saem
   deles (claro, escuro, auto). Todo controle isolado tem 44px (`--alvo`);
   os círculos das fileiras de ação seguem o registro de cada contexto. */

/* O gesto «Mandar para lista…» nas fileiras de ação: aceso quando o item JÁ
   está numa lista (o botão diz onde, no `title`). */
.redondo.acao-lista[aria-pressed="true"] {
  color: var(--acento); border-color: var(--acento);
  background: color-mix(in srgb, var(--acento) 12%, var(--papel-elev));
}

/* ── /listas ── */
.cabeca-listas {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 1rem; flex-wrap: wrap; margin: 0 0 .8rem;
}
.cabeca-listas .titulo-tela { margin: 0; }
.cabeca-listas .btn, .tela-lista .btn, .mandar-para .btn { min-height: var(--alvo); padding: 0 .9rem; }
.nova-lista { display: flex; flex-wrap: wrap; align-items: flex-end; gap: .5rem; margin: 0 0 .6rem; }
.nova-lista[hidden] { display: none; }
.nova-lista .campo { display: flex; flex-direction: column; gap: .25rem; flex: 1 1 14rem;
  font-family: var(--sans); font-size: .82rem; color: var(--tinta-2); }
.nova-lista input, .renomear input, .mover-posicao input {
  box-sizing: border-box; min-height: var(--alvo); padding: 0 .7rem;
  font: 400 1rem/1.2 var(--sans); color: var(--tinta);
  background: var(--papel); border: 1px solid var(--borda-controle); border-radius: var(--raio-p);
}
.nova-lista input:focus-visible, .renomear input:focus-visible, .mover-posicao input:focus-visible {
  outline: 2px solid var(--foco); outline-offset: 1px;
}
.cabeca-listas ~ .dica, .tela-lista .dica { font-family: var(--sans); font-size: .84rem; color: var(--tinta-2); margin: 0 0 .6rem; }
.cabeca-listas ~ .dica:empty { display: none; }

.cartoes-listas { list-style: none; margin: 0; padding: 0; display: grid; gap: .6rem;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 18rem), 1fr)); }
/* A moldura é do <li>: dentro dela, o link (abre a lista) e o «Puxar» da vez,
   irmãos — botão dentro de link não é HTML válido (pedido do dono, 18/09). */
.cartao-lista {
  display: flex; flex-direction: column; box-sizing: border-box; height: 100%;
  background: var(--papel-elev); border: 1px solid var(--regra); border-radius: var(--raio);
}
.cartao-lista:has(> a:hover), .cartao-lista:has(> a:focus-visible) { border-color: var(--acento); }
.cartao-lista a {
  flex: 1; display: flex; align-items: center; gap: .9rem; min-height: var(--alvo);
  padding: .8rem 1rem; box-sizing: border-box; border-radius: var(--raio);
  color: var(--tinta); text-decoration: none;
}
.cartao-lista a:focus-visible { outline: 2px solid var(--foco); outline-offset: 2px; }
.cartao-lista > .puxar { align-self: flex-start; min-height: var(--alvo); padding: 0 .9rem;
  margin: 0 1rem .8rem; white-space: nowrap; }
.capa-lista { flex: none; width: 3.2rem; container-type: inline-size; }
/* `.obra` só para a capa desenhada ter pele (L-323); o resto do `.obra` da
   estante (coluna flex de altura cheia) não vale aqui. */
.capa-lista.obra { display: block; height: auto; }
.capa-lista .capa { display: flex; width: 100%; aspect-ratio: 2 / 3; border-radius: 3px; overflow: hidden; }
.texto-lista { display: flex; flex-direction: column; gap: .15rem; min-width: 0; }
.texto-lista .nome { font-family: var(--serif); font-size: 1.08rem; font-weight: 600; }
.texto-lista .proximo { font-family: var(--sans); font-size: .86rem; color: var(--tinta-2);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.texto-lista .conta { font-family: var(--sans); font-size: .78rem; color: var(--tenue); font-variant-numeric: tabular-nums; }

.aviso-offline, .progresso-lista {
  font-family: var(--sans); font-size: .86rem; color: var(--tinta);
  background: var(--papel-elev-2); border-left: 3px solid var(--tenue);
  border-radius: 0 var(--raio-p) var(--raio-p) 0; padding: .5rem .8rem; margin: 0 0 .8rem;
}
.progresso-lista { border-left-color: var(--acento); font-variant-numeric: tabular-nums; }

/* ── /listas/:id ── */
.cabeca-lista { display: flex; align-items: center; gap: .6rem; margin: 0 0 .2rem; flex-wrap: wrap; }
.cabeca-lista .titulo-tela { margin: 0; display: flex; align-items: center; gap: .5rem; flex: 1 1 auto; min-width: 0; }
.cabeca-lista .titulo-tela .ic { flex: none; width: 1.3rem; height: 1.3rem; color: var(--acento); }
.cabeca-lista .titulo-tela .ic svg { width: 100%; height: 100%; display: block; }
.renomear { display: flex; flex-wrap: wrap; gap: .5rem; flex: 1 1 16rem; }
.renomear input { flex: 1 1 12rem; font-family: var(--serif); font-size: 1.1rem; }
.menu-lista { position: relative; flex: none; }
.menu-lista > summary {
  list-style: none; display: grid; place-items: center; cursor: pointer;
  width: var(--alvo); height: var(--alvo); border-radius: 50%;
  font: 700 1.2rem/1 var(--sans); color: var(--tinta-2); border: 1px solid transparent;
}
.menu-lista > summary::-webkit-details-marker { display: none; }
.menu-lista > summary:hover, .menu-lista > summary:focus-visible { color: var(--acento); border-color: var(--regra); }
.menu-lista[open] > summary { color: var(--acento); border-color: var(--acento); }
.menu-itens {
  position: absolute; right: 0; top: calc(100% + .3rem); z-index: 20;
  display: flex; flex-direction: column; gap: .3rem; padding: .4rem; min-width: 11rem;
  background: var(--papel-elev); border: 1px solid var(--regra); border-radius: var(--raio);
  box-shadow: var(--sombra-erguida);
}
.menu-itens .btn { text-align: left; }
.tela-lista .btn.perigo, .apagar-lista .btn.perigo { color: var(--perigo); border-color: currentColor; background: transparent; }
.conta-lista { font-family: var(--sans); font-size: .82rem; color: var(--tinta-2); margin: 0 0 1rem; }

/* A fila mora direto na mesa (`--tela`), e `--regra` é fio de PAPEL: sobre
   a mesa do tema claro ele mediu 1,00 no Safari — a divisória não existia
   (L-323). A régua das Notícias: tinta a 14%, que acompanha os três temas. */
.tela-lista { --regra-mesa: color-mix(in srgb, var(--tinta) 14%, transparent); }
.itens-lista { list-style: none; margin: 0; padding: 0; counter-reset: none; }
.item-lista {
  display: grid; align-items: center; column-gap: .6rem;
  grid-template-columns: 2.2rem var(--alvo) minmax(0, 1fr) auto;
  padding: .45rem .2rem; border-bottom: 1px solid var(--regra-mesa);
}
.item-lista.pego { background: color-mix(in srgb, var(--acento) 10%, transparent); border-radius: var(--raio-p); }
.item-lista .posicao {
  font: 600 .95rem/1 var(--sans); color: var(--tenue); text-align: right;
  font-variant-numeric: tabular-nums;
}
.item-lista:first-child .posicao { color: var(--acento); }
/* No leito tingido da linha pega, `--tenue` cai a 4,03 (L-323). */
.item-lista.pego .posicao { color: var(--tinta-2); }
.marcar-item { display: grid; place-items: center; width: var(--alvo); height: var(--alvo); cursor: pointer; }
.marcar-item input { width: 1.15rem; height: 1.15rem; margin: 0; accent-color: var(--acento); cursor: pointer; }
.item-lista .alvo {
  display: flex; flex-direction: column; gap: .12rem; min-width: 0; min-height: var(--alvo);
  justify-content: center; color: var(--tinta); text-decoration: none;
}
.item-lista .alvo .titulo { font-family: var(--serif); font-size: 1rem; line-height: 1.3;
  overflow-wrap: anywhere; }
.item-lista .alvo .meta { font-family: var(--sans); font-size: .76rem; color: var(--tinta-2); }
.item-lista .alvo:hover .titulo, .item-lista .alvo:focus-visible .titulo { color: var(--acento); }
.item-lista .alvo:focus-visible { outline: 2px solid var(--foco); outline-offset: 2px; border-radius: var(--raio-p); }
/* Com algo pego, a linha inteira é o alvo do «pôr aqui». */
.tela-lista:has(.barra-mover) .item-lista:not(.pego) .alvo { cursor: copy; }
.acoes-item { display: flex; align-items: center; gap: .35rem; justify-content: flex-end; }
.acoes-item .redondo { width: var(--alvo); height: var(--alvo); min-height: var(--alvo); font-size: 1rem; }
.acoes-item .pegar[aria-pressed="true"] {
  color: var(--sobre-acento); background: var(--acento); border-color: var(--acento);
}
.acoes-item .puxar { min-height: var(--alvo); padding: 0 .9rem; white-space: nowrap; }
.mais-lista { text-align: center; margin: 1rem 0; }

/* A barra do pé: «Movendo 3 itens · Topo · Fim · Posição · Mandar… · Cancelar».
   Presa ACIMA da barra de navegação do telefone, no fluxo da coluna — a mesma
   lição do `.selecao-lugar` das Notícias: pegajosa no pé da tela visível. */
.barra-mover {
  position: sticky; bottom: calc(var(--barra-h) + .75rem); z-index: 6;
  display: flex; flex-wrap: wrap; align-items: center; gap: .5rem;
  margin-top: 1rem; padding: .5rem; box-sizing: border-box;
  background: var(--papel-elev); border: 1px solid var(--regra); border-radius: var(--raio);
  box-shadow: var(--sombra-erguida); font-family: var(--sans);
}
.barra-mover .movendo { font-weight: 600; font-size: .9rem; color: var(--tinta); margin-right: auto;
  padding-left: .3rem; font-variant-numeric: tabular-nums; }
.mover-posicao { display: flex; align-items: center; gap: .3rem; }
.mover-posicao label { display: flex; align-items: center; gap: .35rem; font-size: .84rem; color: var(--tinta-2); }
.mover-posicao input { width: 4.2rem; text-align: center; font-variant-numeric: tabular-nums; }
/* «Ir» é uma palavra de duas letras: sem piso, o alvo media 39 px (L-323). */
.barra-mover .btn { min-width: var(--alvo); }

/* No telefone, o título da linha ganha a largura: a caixa e o número ficam,
   e os gestos descem para baixo do título. */
@media (max-width: 37rem) {
  .item-lista { grid-template-columns: 1.8rem var(--alvo) minmax(0, 1fr); row-gap: .2rem; }
  .acoes-item { grid-column: 3; justify-content: flex-start; flex-wrap: wrap; }
  .barra-mover .movendo { flex-basis: 100%; }
}

/* ── A folha «Mandar para lista…» ── */
.mandar-para .titulo { font-family: var(--serif); font-size: 1.1rem; font-weight: 600; margin: 0 0 .3rem; }
.mandar-para .alvo { font-family: var(--serif); color: var(--tinta-2); margin: 0 0 .8rem; }
.mandar-para .aviso-estudo {
  font-size: .86rem; line-height: 1.45; color: var(--tinta); margin: 0 0 .8rem;
  background: color-mix(in srgb, var(--perigo) 8%, var(--papel-elev));
  border-left: 3px solid var(--perigo); border-radius: 0 var(--raio-p) var(--raio-p) 0; padding: .5rem .7rem;
}
.mandar-para .destinos { list-style: none; margin: 0 0 .6rem; padding: 0; overflow-y: auto; min-height: 0;
  display: flex; flex-direction: column; gap: .3rem; }
.mandar-para .destino {
  display: flex; align-items: center; justify-content: space-between; gap: .8rem; width: 100%;
  min-height: var(--alvo); padding: .4rem .8rem; box-sizing: border-box; text-align: left; cursor: pointer;
  font: 500 .95rem/1.3 var(--sans); color: var(--tinta);
  background: var(--papel); border: 1px solid var(--regra); border-radius: var(--raio-p);
}
.mandar-para .destino .conta { font-size: .8rem; color: var(--tinta-2); font-variant-numeric: tabular-nums; flex: none; }
.mandar-para .destino:hover:not([disabled]), .mandar-para .destino:focus-visible { border-color: var(--acento); }
.mandar-para .destino:focus-visible { outline: 2px solid var(--foco); outline-offset: 1px; }
.mandar-para .destino[aria-pressed="true"] {
  border-color: var(--acento); background: color-mix(in srgb, var(--acento) 12%, var(--papel));
}
.mandar-para .destino[disabled] { opacity: .6; cursor: default; }
.mandar-para .destino.nova { color: var(--acento); justify-content: flex-start; }
.mandar-para .vazio-destinos { font-size: .86rem; color: var(--tinta-2); padding: .3rem .2rem; }
.mandar-para .nova-lista { margin: 0 0 .5rem; }
.mandar-para .dica { font-size: .86rem; color: var(--tinta-2); min-height: 1.2em; margin: 0 0 .6rem; }
.mandar-para .botoes { display: flex; justify-content: flex-end; gap: .5rem; margin: 0; }

/* ── O diálogo do apagar com itens ── */
.destinos-itens { display: flex; flex-direction: column; gap: .5rem; margin: 0 0 1rem; }
.destinos-itens .btn {
  display: flex; flex-direction: column; align-items: flex-start; gap: .15rem; text-align: left;
  min-height: var(--alvo); padding: .55rem .9rem; font-size: .95rem; font-weight: 600;
}
.destinos-itens .btn small { font-weight: 400; font-size: .8rem; color: var(--tinta-2); }
/* O `.btn` é cromo escuro: `--tinta-2` por cima mediu 2,04 (L-323). A linha
   de baixo segue a tinta do botão, um degrau mais fraca. */
.destinos-itens .btn:not(.perigo) small { color: color-mix(in srgb, currentColor 80%, transparent); }

/* ── A barra do telefone: só o ícone  (L-323) ──
   Com o sexto destino cada coluna do iPhone ficou com 55 px, e «Listas de
   Leitura» quebrou em duas linhas no Safari (390 px): a barra cresceu de 62
   para 83 px e passou por cima da barra de mover. Como o plano decidiu para
   esse caso, no telefone a barra é só de ícones; o rótulo continua no DOM,
   fora da vista, e é ele o nome do destino para o VoiceOver. O iPad e a
   lateral do Mac têm largura, e mantêm a palavra. */
@media (max-width: 37rem) {
  #barra-nav .nav-rotulo {
    position: absolute; width: 1px; height: 1px; margin: -1px;
    overflow: hidden; clip-path: inset(50%); white-space: nowrap;
  }
  #barra-nav a { justify-content: center; }
  #barra-nav a .ic, #barra-nav a .ic svg { width: 24px; height: 24px; }
}

/* A nota do «mandado» (fica até o Fechar, como a nota de falha). */
.desfazer.aviso-mandado { background: var(--tinta); color: var(--papel); }

/* ── A faixa dos envios  (spec 68 §15) ────────────────────────────────────────
   O estado do que subiu para converter, em qualquer tela: presa ao pé, ACIMA da
   barra de navegação do telefone (a mesma lição da `.barra-mover`), estreita no
   computador para não cobrir a coluna de leitura. Some quando não há o que dizer. */
#envios {
  position: fixed; z-index: 40;
  right: max(.75rem, env(safe-area-inset-right)); bottom: calc(var(--barra-h, 0px) + .75rem);
  width: min(24rem, calc(100vw - 1.5rem)); box-sizing: border-box;
  display: flex; flex-direction: column; gap: .35rem;
  font-family: var(--sans); font-size: .84rem; line-height: 1.35;
}
#envios[hidden] { display: none; }
#envios .envio {
  display: grid; grid-template-columns: minmax(0, 1fr) auto auto; align-items: center; column-gap: .4rem;
  padding: .5rem .55rem .5rem .75rem; border-radius: var(--raio);
  background: var(--papel-elev); color: var(--tinta); border: 1px solid var(--regra);
  box-shadow: var(--sombra-erguida);
}
#envios .envio-texto { overflow-wrap: anywhere; font-variant-numeric: tabular-nums; }
#envios .envio-andamento { color: var(--tinta-2); }
#envios .envio-falhou { border-color: color-mix(in srgb, var(--perigo) 55%, var(--regra)); }
#envios .envio-pronto { border-color: color-mix(in srgb, var(--acento) 55%, var(--regra)); }
#envios .envio-abrir { color: var(--acento); font-weight: 600; text-decoration: none;
  min-height: var(--alvo); display: inline-flex; align-items: center; padding: 0 .35rem; }
#envios .envio-dispensar { min-width: var(--alvo); min-height: var(--alvo); border: 0; background: none;
  color: var(--tinta-2); font-size: 1.15rem; line-height: 1; cursor: pointer; border-radius: var(--raio); }
#envios .envio-dispensar:hover { color: var(--tinta); }
#envios details { grid-column: 1 / -1; color: var(--tinta-2); font-size: .78rem; }
#envios details summary { cursor: pointer; min-height: 1.6rem; }
#envios details p { margin: .15rem 0 .1rem; overflow-wrap: anywhere; }
#envios .envio-mais { margin: 0; text-align: right; color: var(--tinta-2); font-size: .78rem; }
/* A pergunta do quality check (spec 68 §17): a linha que espera resposta. O
   texto ocupa a largura toda e os dois botões vão embaixo, o que continua à
   direita — o polegar acha «Converter» onde acha o «Abrir» das outras linhas. */
#envios .envio-confirmar { border-color: color-mix(in srgb, var(--acento) 75%, var(--regra)); }
#envios .envio-confirmar .envio-texto { grid-column: 1 / -1; }
#envios .envio-decisao { grid-column: 1 / -1; display: flex; justify-content: flex-end; flex-wrap: wrap; gap: .4rem; margin-top: .45rem; }
#envios .envio-decisao .btn { min-height: var(--alvo); }

/* ── A conta  (spec 69 §3, §7.1; fatia 1) ────────────────────────────────────
   Uma coluna em todas as larguras, na largura de leitura: a página é lida de
   cima para baixo, e a ordem é o argumento. Cartões na gramática do `/admin`
   — um bloco por assunto, rótulo em cima, conteúdo embaixo, sem caixas dentro
   de caixas —, porque as duas são as telas de administrar do app e devem
   parecer parentes.

   Nenhuma barra animada, nenhuma contagem regressiva e nenhum vermelho de
   alarme: o aviso usa o tom de aviso do app. Contagem regressiva em tela de
   dinheiro é padrão de pressão, e pressão é o que o público da tese menos
   precisa (53 §2).

   ── A FOLHA  (25/09, amostra A) ───────────────────────────────────────────
   «A página da conta está feia, fria» — o dono, 25/09. Era um campo bege de
   sans miúda com fios escuros entre os assuntos e o `<select>` branco do
   sistema no meio do sépia. Das três amostras (`harness-conta-amostras.html`,
   `interacao-conta.mjs --amostras`) ficou a A: o vocabulário da Acolhida de
   «Para ler» estendido à conta. Cada assunto é uma FOLHA pousada sobre a mesa
   (`--papel-elev` + `--sombra-pousada`), o título em serifa com o desenho do
   assunto (`conta-icones.mjs`), e a capa com o grão, o banho de brasa e a
   fogueira da marca. Nenhuma cor nova: o calor vem de matéria, como lá.

   O tamanho da letra é declarado aqui porque o `body` tem o da LEITURA
   (`--size`, que a pessoa aumenta no Aa), e o texto da conta que não tinha
   classe herdava isso: o «Como tratamos os seus dados» saía o dobro das
   frases vizinhas. */
#conta { font-family: var(--sans); font-size: .9rem; max-width: 42rem; margin: 0 auto; padding: .4rem 0 2.5rem; }
#conta h1 {
  font-family: var(--serif); font-size: 1.75rem; font-weight: 600; letter-spacing: -.015em;
  line-height: 1.2; margin: 0 0 .6rem;
}
#conta h2 {
  display: flex; align-items: center; gap: .55rem;
  font-family: var(--serif); font-size: 1.15rem; font-weight: 600; line-height: 1.3; margin: 0 0 .7rem;
}
#conta section {
  background: var(--papel-elev); border: 1px solid var(--papel-borda-fina);
  border-radius: var(--raio); box-shadow: var(--sombra-pousada);
  padding: 1.15rem 1.35rem 1rem; margin: 0 0 1rem;
}
/* No extrato inteiro os meses são folhas também, e o mês é o título delas. */
#conta .conta-mes h2 { margin-top: 0; }
/* O desenho do assunto, na brasa: ≥3:1 contra `--papel-elev` nos três temas
   (é o `--acento`, que já passa como texto). */
#conta .conta-ic { display: inline-flex; flex: none; width: 1.2em; height: 1.2em; color: var(--acento); }
#conta .conta-ic svg, #conta .conta-lume svg { width: 100%; height: 100%; display: block; pointer-events: none; }

/* ── A capa ─────────────────────────────────────────────────────────────────
   O banho sai do canto da fogueira, e não do alto ao centro como na Acolhida:
   aqui a fogueira está à esquerda do título, e a luz vem de onde está o fogo.
   Grão e banho são as camadas da `.acolhida .convite-folha`, com a mesma
   razão para cada número (o comentário de lá). */
#conta .conta-capa {
  position: relative; overflow: hidden;
  display: grid; grid-template-columns: auto minmax(0, 1fr); column-gap: 1.1rem; align-items: start;
  background:
    radial-gradient(70% 120% at 0% 0%, color-mix(in srgb, var(--acento) 16%, transparent), transparent 70%),
    var(--papel-elev);
  border: 1px solid var(--papel-borda-fina); border-radius: var(--raio);
  box-shadow: var(--sombra-pousada);
  padding: 1.5rem 1.5rem 1.3rem; margin: 0 0 1.1rem;
}
#conta .conta-capa > * { position: relative; }
#conta .grao {
  position: absolute; inset: 0; pointer-events: none; opacity: .04;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='120' height='120' filter='url(%23g)'/%3E%3C/svg%3E");
}
#conta .conta-capa > .conta-lume { width: 52px; height: 52px; margin-top: .1rem; color: var(--acento); }
#conta .conta-capa h1 { margin: 0; }
#conta .conta-capa .conta-faixa { padding: .35rem 0 0; margin: 0; }
#conta .conta-capa .conta-caminho { margin: .35rem 0 0; }
#conta .conta-capa .conta-nota { margin: .3rem 0 0; }
/* A tabela de preços mora numa folha que rola por dentro no telefone. */
#conta .conta-precos-folha { padding: .6rem .7rem; }
#conta .conta-capa .conta-faixa p { font-family: var(--serif); font-size: 1.02rem; color: var(--tinta-2); }
#conta .conta-capa .conta-faixa[data-tom="aviso"] { padding: .8rem 1rem; margin-top: .6rem; }
#conta .conta-capa .conta-faixa[data-tom="aviso"] p { color: var(--tinta); }
#conta .conta-nota { margin: .35rem 0; font-size: .82rem; line-height: 1.5; color: var(--tinta-2); }
#conta .conta-caminho { margin: .6rem 0 .2rem; font-size: .85rem; }
/* Os links da conta vestem o acento do app. Sem isto eles saíam no AZUL do
   navegador — a imagem pegou: numa página de sienna queimada, três links
   azuis eram a única coisa que não era do Leitor. */
#conta a { color: var(--acento); text-underline-offset: .18em; }
/* «Baixar o acervo» é `<a class="btn">` (o casco só manda ao Safari o link
   TOCADO): veste o botão, e não o link da regra acima, que ganharia dele. */
#conta a.btn { display: inline-block; color: var(--cromo-tinta); text-decoration: none; }
#conta a.btn:hover, #conta a.btn:focus-visible { color: var(--cromo-acento); }
#conta .conta-status { margin: .3rem 0; font-size: .8rem; color: var(--tinta-2); min-height: 1.1em; }
#conta .conta-status:empty { display: none; }
#conta .vazio { margin: .4rem 0; font-size: .85rem; color: var(--tinta-2); }

/* A faixa de estado: a primeira coisa lida, e a única que muda de tom (§3.1).
   Texto simples quando não pede nada; fundo tingido quando pede ação — e
   NUNCA o vermelho de erro, porque o atraso não é um defeito da pessoa. O
   tingido vem do `--acento`, que é a cor de aviso do app; `--perigo` fica com
   o que de fato falhou. */
#conta .conta-faixa {
  display: flex; flex-wrap: wrap; align-items: center; gap: .8rem;
  padding: .2rem 0 .8rem; margin: 0 0 .2rem;
}
#conta .conta-faixa-texto { flex: 1 1 14rem; display: flex; flex-direction: column; gap: .3rem; }
#conta .conta-faixa p { margin: 0; font-size: .92rem; line-height: 1.5; }
#conta .conta-faixa[data-tom="aviso"] {
  padding: .8rem 1rem; border-radius: 10px;
  background: color-mix(in srgb, var(--acento) 10%, var(--papel));
  border: 1px solid color-mix(in srgb, var(--acento) 34%, var(--regra));
}
#conta .conta-aviso { margin: 0 0 .6rem; font-size: .85rem; line-height: 1.5; }

/* Os números à direita, em algarismos tabulares: é uma coluna de dinheiro, e
   coluna de dinheiro se lê pelo alinhamento. O total num corpo maior, e só
   ele (69 §7.1). */
#conta .conta-total {
  display: flex; align-items: center; gap: .5rem; margin: .1rem 0 .7rem;
  font-family: var(--serif); font-size: 2.8rem; font-weight: 600; letter-spacing: -.02em; line-height: 1;
  font-variant-numeric: tabular-nums;
}
#conta .conta-total .conta-lume { width: .8em; height: .8em; color: var(--acento); flex: none; }
#conta .conta-lotes, #conta .conta-cotas, #conta .conta-linhas, #conta .conta-livre {
  list-style: none; margin: 0; padding: 0;
}
#conta .conta-lote {
  display: grid; grid-template-columns: minmax(3.5rem, auto) minmax(0, 1fr) auto;
  gap: .2rem .7rem; align-items: baseline;
  padding: .3rem 0; font-size: .88rem;
}
#conta .conta-lote-n { text-align: right; font-variant-numeric: tabular-nums; }
#conta .conta-lote-vence { color: var(--tinta-2); font-size: .8rem; white-space: nowrap; }

/* Os aparelhos ligados à folha de compartilhar (spec 74, Task 7): o modelo, as
   datas em tinta de apoio e o «Desligar» no fim da linha. No telefone a linha
   quebra e o botão desce, em vez de espremer as datas. */
#conta .conta-aparelhos { list-style: none; margin: 0; padding: 0; }
#conta .conta-aparelho {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: .2rem .7rem;
  padding: .35rem 0; font-size: .88rem;
}
#conta .conta-aparelho-este, #conta .conta-aparelho-quando { color: var(--tinta-2); font-size: .8rem; }
#conta .conta-aparelho-quando { flex: 1 1 12rem; }
#conta .conta-aparelho .btn { margin-left: auto; }

#conta .conta-cota {
  display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: .15rem .7rem;
  padding: .35rem 0; font-size: .88rem; align-items: baseline;
}
#conta .conta-cota-medida { text-align: right; font-variant-numeric: tabular-nums;
  white-space: nowrap; color: var(--tinta-2); }
#conta .conta-cota-aviso { grid-column: 1 / -1; font-size: .8rem; line-height: 1.45;
  color: color-mix(in srgb, var(--tinta) 82%, var(--acento)); }
/* O fio da cota: parado, na tinta de apoio; só a linha com aviso veste a
   brasa. A largura vem do `style` da linha (a CSP já libera o inline). */
#conta .conta-cota-fio {
  grid-column: 1 / -1; display: block; height: 5px; border-radius: 99px; margin: .3rem 0 .15rem;
  background: color-mix(in srgb, var(--tinta) 9%, transparent); overflow: hidden;
}
#conta .conta-cota-fio i {
  display: block; height: 100%; border-radius: inherit;
  background: color-mix(in srgb, var(--tinta-2) 62%, transparent);
}
#conta .conta-cota[data-aviso] .conta-cota-fio i { background: var(--acento); }
/* No telefone a medida desce para a própria linha: «310 mil de 500 mil
   caracteres no mês · 12 mil de 50 mil hoje» ao lado do nome espremia as duas
   colunas até se tocarem (a imagem de 520px pegou). */
@media (max-width: 34rem) {
  #conta .conta-cota { grid-template-columns: minmax(0, 1fr); }
  #conta .conta-cota-medida { text-align: left; white-space: normal; }
}

/* O extrato: dia, o que foi, e o número à direita. O sinal vai escrito, e por
   isso não há cor decidindo nada aqui. */
#conta .conta-linha {
  display: grid; grid-template-columns: auto minmax(0, 1fr) auto;
  gap: .15rem .7rem; align-items: baseline;
  padding: .45rem 0; font-size: .88rem;
  border-top: 1px dotted color-mix(in srgb, var(--tinta) 22%, transparent);
}
#conta .conta-linha:first-child { border-top: 0; }
#conta .conta-linha-dia { color: var(--tinta-2); font-variant-numeric: tabular-nums; white-space: nowrap; }
#conta .conta-linha-delta { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
#conta .conta-linha-detalhe { grid-column: 1 / -1; font-size: .8rem; color: var(--tinta-2); }
#conta .conta-linha-detalhe summary { cursor: pointer; min-height: 32px; display: flex; align-items: center; }
#conta .conta-linha-detalhe ul { list-style: none; margin: .2rem 0; padding: 0; }

#conta .conta-limiar-linha { margin: .2rem 0 .4rem; font-size: .88rem; }
#conta .conta-limiar-linha select { min-height: var(--alvo); }
#conta .conta-lingua-linha { margin: .2rem 0 .4rem; font-size: .88rem; }
#conta .conta-lingua-linha select { min-height: var(--alvo); }
#conta button { min-height: var(--alvo); padding: .45rem 1rem; }
/* Sobre a folha (`--papel-elev`) o campo grafite do `.btn` fica a 1,30:1 no
   tema escuro, e a borda passa a ser a pista — a mesma troca da Acolhida. */
#conta .btn { border-color: var(--borda-controle); font-size: .86rem; }
/* O `<select>` volta ao CSS, como no `/admin`: o nativo era a peça mais fria
   da tela (branco no sépia), e o Safari ignora o `min-height` dele. 1rem para
   o iOS não dar zoom ao focar. */
#conta select {
  -webkit-appearance: none; appearance: none;
  font: 400 1rem/1.2 var(--sans); color: var(--tinta);
  background-color: var(--papel);
  background-image: linear-gradient(45deg, transparent 50%, var(--tenue) 50%),
    linear-gradient(135deg, var(--tenue) 50%, transparent 50%);
  background-position: calc(100% - 1.05rem) 50%, calc(100% - .75rem) 50%;
  background-size: .3rem .3rem; background-repeat: no-repeat;
  border: 1px solid var(--borda-controle); border-radius: 8px;
  padding: .45rem 2.2rem .45rem .7rem; min-height: var(--alvo); margin-left: .4rem;
}
/* Sair e Excluir, juntos no pé de «Seus dados», depois de um fio. */
#conta .conta-saida {
  display: flex; flex-wrap: wrap; gap: .5rem; margin-top: 1.1rem; padding-top: 1rem;
  border-top: 1px dashed color-mix(in srgb, var(--tinta) 18%, transparent);
}
#conta .conta-saida p { margin: 0; }

/* A tabela de preços rola DENTRO de si no telefone, em vez de empurrar a
   página: três colunas com exemplo não cabem em 360px, e a coluna espremida
   mente sobre o preço. */
#conta .conta-precos { width: 100%; border-collapse: collapse; font-size: .84rem;
  display: block; overflow-x: auto; }
#conta .conta-precos th, #conta .conta-precos td { padding: .4rem .6rem; text-align: left;
  vertical-align: top; border-top: 1px dotted color-mix(in srgb, var(--tinta) 22%, transparent); }
#conta .conta-precos thead th { font-size: .72rem; color: var(--tenue); letter-spacing: .03em;
  border-top: 0; }
#conta .conta-precos th[scope="row"] { font-weight: 500; }
#conta .conta-livre li { padding: .2rem 0; font-size: .85rem; color: var(--tinta-2); }
#conta .conta-suporte { margin: 1.4rem 0 .4rem; font-family: var(--serif); font-style: italic;
  font-size: .92rem; line-height: 1.5; text-align: center; color: var(--tinta-2); }

/* A folha de excluir (69 §3.10; 31 §5.2). Na página, logo abaixo do botão, e
   não num modal: é para ler inteira — a data, o que sai, o que se perde. O
   «Excluir a conta» leva o `--perigo` só no texto, e o foco nasce no
   «Cancelar»; o vermelho diz o que o botão faz, não empurra ninguém. */
#conta .conta-folha {
  margin: .4rem 0 .8rem; padding: .8rem 1rem; border-radius: 10px;
  border: 1px solid color-mix(in srgb, var(--perigo) 30%, var(--regra));
}
#conta .conta-folha h3 { font-size: .9rem; font-weight: 600; margin: 0 0 .4rem; }
#conta .conta-gestos { display: flex; flex-wrap: wrap; gap: .5rem; margin: .6rem 0 .2rem; }
#conta .conta-gestos .perigo { color: var(--perigo); }

/* O telefone: a folha perde gordura dos lados, e a fogueira diminui. */
@media (max-width: 37rem) {
  #conta section, #conta .conta-capa { padding-inline: 1.05rem; }
  #conta .conta-capa > .conta-lume { width: 42px; height: 42px; }
  #conta .conta-total { font-size: 2.4rem; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   A ACOLHIDA: o vazio de «Para ler»  (23/09 · spec 53, fase 2)

   «Essa página inicial está muito fria, pouco acolhedora, pouco aconchegante.»
   — o dono, 23/09, sobre a primeira tela depois de entrar. Com a caixa vazia
   ela era um campo bege com «Nada por aqui.» em itálico no meio, e vinha logo
   depois da noite de fogueira da entrada (spec 30), o que tornava o corte
   ainda mais duro. A varredura da 53 já a tinha catalogado — «não diz como
   trazer algo» — e a fase 2 promete vazio que ensina e traz o botão.

   O HTML vem de `montarAcolhida` (`inbox.mjs`), e o cabeçalho de lá conta o
   PORQUÊ de cada peça. Aqui fica a matéria.

   ── O CALOR VEM DE MATÉRIA, NÃO DE SATURAÇÃO ──────────────────────────────

   Quatro coisas, e nenhuma é cor cheia:

     · o GRÃO do papel — dois fios cruzados a 4% e 3% de tinta, que é papel
       vergê visto de perto;
     · o BANHO DE BRASA descendo do alto da folha, a 15% do acento;
     · a SOMBRA, que é o que o núcleo já manda usar para separar folha de mesa
       — a folha pousa, e a capa de cada livro pousa sobre ela;
     · a SERIFA na frase e no título do livro, que é a tipografia da leitura
       entrando onde antes só havia rótulo.

   O único ponto saturado da tela continua sendo o `+` do cabeçalho: os dois
   gestos e os «Puxar» são `.btn` de grafite. Cinco campos de acento numa tela
   seriam a «parede de cor» que a rodada «grafite, lombada, prateleira» existe
   para desfazer.

   ── A LUZ DO FOGO É `--acento`, E NÃO `--entrada-brasa` ───────────────────

   `#e3a577` é tinta calibrada contra o céu da tela de entrada, e a nota de
   `body[data-entrada]` diz que nada de lá vaza para fora daquele escopo.
   Sobre `--papel-elev` do tema claro ela mede 1,7:1 — invisível. `--acento` é
   a mesma chama na tinta que cada superfície aguenta: brasa funda no claro
   (#832f0d) e no sépia (#7c2c0b), brasa clara no escuro (#f39d7a). O banho
   segue o acento pelo `color-mix`, então ele clareia junto no tema escuro,
   onde um banho de brasa funda sobre papel quase preto não existiria.

   ── CONTRASTE, medido no pixel  (`interacao-acolhida.mjs`) ────────────────

   Os números são o fundo REAL — o papel já tingido pelo banho —, e não o
   token: no token este fundo não existe. Ver as capturas em
   `test/capturas/acolhida/`.
   ═════════════════════════════════════════════════════════════════════════ */
.acolhida { --lume: var(--acento); }

/* A folha do convite. `overflow: hidden` para o grão e o banho respeitarem o
   raio; `position: relative` porque os dois são camadas posicionadas. */
.acolhida .convite-folha {
  position: relative; overflow: hidden; text-align: center;
  background:
    radial-gradient(72% 56% at 50% -8%, color-mix(in srgb, var(--lume) 15%, transparent), transparent 72%),
    var(--papel-elev);
  border: 1px solid var(--papel-borda-fina); border-radius: var(--raio);
  box-shadow: var(--sombra-pousada);
  padding: 2.1rem 1.6rem 1.7rem; margin: 0 0 1.9rem;
}
/* O grão e o banho são camadas POSICIONADAS, e por isso pintariam por cima de
   todo irmão em fluxo. Posicionar os irmãos os põe depois deles na ordem de
   pintura, sem abrir contexto de empilhamento novo — a mesma linha que o
   `#login > *` da tela de entrada precisou, e pela mesma razão. */
.acolhida .convite-folha > * { position: relative; }
/* ── O grão: ruído, e não trama  (medido em 23/09) ────────────────────────
   A primeira versão eram dois `repeating-linear-gradient` cruzados a 4% e 3%
   de tinta, um fio a cada 3 e 4 px. Na captura a 2× isso não parecia papel:
   parecia TELA DE MOSQUITEIRO. Trama regular é regular, e regularidade é
   justamente o que papel não tem — o olho lê a grade antes de ler a textura.

   O que entra é ruído de verdade: um `feTurbulence` fractal de 120×120 em SVG
   embutido, que se repete sem costura visível porque não há padrão a casar. É
   `data:` num `background-image`, que o `img-src 'self' … data:` da CSP já
   permite (cloudfront.tf) — nenhum byte a mais desce do CDN.

   A força mora na `opacity` do elemento, e não na tinta do desenho: o ruído é
   cinza, então sobre papel claro ele escurece e sobre papel escuro ele clareia,
   que é o que grão faz nos dois casos. Um valor por tema seria a mesma coisa
   escrita duas vezes.

   4% é o teto do discreto: a 6% a folha ganha sujeira visível a um braço de
   distância, e o que se quer é a textura que só se nota quando se procura. */
.acolhida .grao {
  position: absolute; inset: 0; pointer-events: none; opacity: .04;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='120' height='120' filter='url(%23g)'/%3E%3C/svg%3E");
}
/* A fogueira da marca (`GLIFO`, o mesmo desenho da `.cabeca` e do favicon), em
   `currentColor`. Desenho e não emoji, pela regra de sempre. */
.acolhida .lume { display: block; width: 44px; height: 44px; margin: 0 auto .85rem; color: var(--lume); }
.acolhida .lume svg { width: 100%; height: 100%; display: block; }

.acolhida h2 {
  font-family: var(--serif); font-size: 1.45rem; font-weight: 600;
  letter-spacing: -.01em; line-height: 1.25; margin: 0;
}
.acolhida .convite {
  font-family: var(--serif); font-size: .98rem; line-height: 1.5;
  color: var(--tinta-2); max-width: 27em; margin: .4rem auto 0;
}
.acolhida .gestos { display: flex; flex-wrap: wrap; justify-content: center; gap: .5rem; margin: 1.15rem 0 0; }
/* O alvo de 44px e a caixa de um botão de verdade: o `.btn` da casa é miúdo
   (.38rem de padding) porque vive em barra e em menu. Aqui ele é a única coisa
   a fazer na tela. `text-decoration: none` porque um deles é `<a>`, e link com
   cara de botão não leva sublinhado. */
.acolhida .gestos .btn {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: var(--alvo); padding: 0 .95rem; text-decoration: none;
}
/* ── A borda do botão, e por que ela muda AQUI  (medido em 23/09) ─────────
   O `.btn` da casa é grafite com borda `--cromo-borda` (branco a 7%), e ele se
   lê pelo CAMPO: objeto escuro sobre papel claro, 12,3:1 no tema claro. No
   tema escuro esse campo (#23282d) fica a **1,30:1** do `--papel-elev`
   (#1d1f24) desta folha — abaixo do piso de 3:1 da WCAG 1.4.11, e o botão
   deixa de ter contorno. Não é defeito do `.btn`: fora daqui ele mora sobre
   `--papel` ou sobre a mesa, que são mais fundas, e ali o campo basta.

   Então a borda passa a ser a pista, e borda que é a única pista usa o token
   que tem piso medido — `--borda-controle`, 3:1 contra as três superfícies do
   núcleo. Medido nesta folha: 4,17:1 no escuro, e no claro e no sépia o anel
   cinza sobre o campo escuro não tira nada do que já passava. */
.acolhida .btn { border-color: var(--borda-controle); }

/* ── A cabeceira: o primeiro de cada fila ──────────────────────────────── */
.acolhida .rotulo-cabeceira {
  font: 600 .72rem/1 var(--sans); letter-spacing: .09em; text-transform: uppercase;
  color: var(--tenue); margin: 0 0 .6rem;
}
/* A segunda metade da linha explica a primeira, e explicação não vai em
   versalete espaçado — ela se lê, não se varre. */
.acolhida .rotulo-cabeceira .leve { text-transform: none; letter-spacing: 0; font-weight: 400; }
.acolhida .cabeceira { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: .6rem; }

/* O cartão é o `.item` da própria lista — lombada na matiz, sobrancelha,
   título em serifa —, com duas colunas a mais: a capa, que o cartão comum não
   tem, e o gesto. O `padding-left` desce de 23 para 19 porque a capa já afasta
   o texto da lombada. */
.acolhida .livro-da-fila {
  display: grid; grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center; column-gap: 1rem; padding: 14px 16px 14px 19px;
}
.acolhida .livro-da-fila .capa-lista { width: 3.6rem; }
/* A sombra é o que faz a capa ser objeto pousado no cartão, e não um retângulo
   colorido impresso nele. O raio assimétrico é a lombada do livro à esquerda. */
.acolhida .livro-da-fila .capa-lista .capa {
  box-shadow: var(--sombra-pousada); border-radius: 2px 3px 3px 2px;
}
.acolhida .livro-da-fila .miolo { min-width: 0; }
.acolhida .livro-da-fila .eyebrow { margin-bottom: 4px; }
.acolhida .livro-da-fila h2 { font-size: 1.12rem; line-height: 1.25; margin: 0; }
/* `justify-content: center` porque o núcleo dá `min-height: var(--alvo)` a todo
   `<a>`: com título de uma linha sobra folga dentro do alvo, e sem isto ela
   cairia toda embaixo do texto, que é o que fazia o cartão parecer torto. */
.acolhida .livro-da-fila .alvo {
  display: flex; flex-direction: column; justify-content: center; gap: 3px;
  text-decoration: none; color: inherit;
}
.acolhida .livro-da-fila .alvo:hover h2, .acolhida .livro-da-fila .alvo:focus-visible h2 { color: var(--acento); }
.acolhida .livro-da-fila .credito { font: 400 .8rem/1.35 var(--sans); color: var(--tinta-2); }
/* A capa é um segundo caminho para o MESMO livro, e por isso sai da ordem de
   tabulação e da árvore de acessibilidade: dois links vizinhos com o mesmo
   destino são um tropeço a mais para quem navega por teclado ou por voz, sem
   nada a mais para oferecer. Ela existe para o dedo e para o olho. */
.acolhida .livro-da-fila .capa-lista { display: block; }
.acolhida .livro-da-fila .puxar {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: var(--alvo); padding: 0 .9rem; white-space: nowrap;
}

/* ── O telefone (spec 63: abaixo de 40rem a coluna deita) ──────────────────
   O gesto não cabe na mesma linha do título: a 390px sobrava pouco mais de um
   dedo para o título, e o botão `white-space: nowrap` passava POR CIMA dele.
   Ele desce para uma linha própria, alinhado ao texto — a mesma decisão que a
   `.item-lista` das Listas de Leitura já tinha tomado no mesmo corte. */
@media (max-width: 37rem) {
  .acolhida .convite-folha { padding: 1.8rem 1.1rem 1.4rem; }
  .acolhida .gestos .btn { flex: 1 1 100%; }
  .acolhida .livro-da-fila { grid-template-columns: auto minmax(0, 1fr); row-gap: .7rem; }
  .acolhida .livro-da-fila .puxar { grid-column: 1 / -1; justify-self: stretch; }
}


/* ═══════════════════════════════════════════════════════════════════════════
   A VITRINE  (spec 78)
   ═══════════════════════════════════════════════════════════════════════════
   O que um visitante SEM sessão vê em `/`, fora do casco. Três faixas e um
   rodapé: o topo e o fecho no GRAFITE do app — o mesmo `--cromo-*` da lateral
   do Mac e da barra do telefone (25/09, pedido do dono: a faixa era o
   verde-noite da ilustração, e a Lareia é grafite) —, com as tintas da
   entrada (`--entrada-*`); e o deck no meio, sobre a mesa do TEMA (`--tela`,
   `--papel`), sépia ou escuro conforme o sistema de quem chega.

   ── A casca do app some inteira ──────────────────────────────────────────
   A vitrine tem cabeça própria (a marca e «Já tenho conta · Entrar») e
   rodapé próprio; a `.cabeca` do app, o carimbo e a pilha seriam uma segunda
   identidade na mesma tela. Quem põe e tira o atributo é o `app.mjs`.

   ── Fundo LISO, e não o gradiente do cromo ────────────────────────────────
   O contraste desta página é medido no DOM (`interacao-vitrine.mjs`): a
   tinta computada contra o fundo composto, subindo pela árvore. Um gradiente
   é fundo que a medida não sabe ler, e um número adivinhado não é medida. O
   liso é o `--cromo-1`, o mais CLARO dos dois — o pior caso para as tintas
   claras, então o que passa nele passa no gradiente inteiro.
   ─────────────────────────────────────────────────────────────────────────── */
body[data-vitrine] :is(.cabeca, #versao, #barra-nav, #pilha-leitura, #abas-alternar) { display: none; }
body[data-vitrine] main { max-width: none; margin: 0; padding: 0; overflow-x: clip; }

.vitrine { font-family: var(--sans); color: var(--tinta); }
.vitrine .vitrine-noite {
  background: var(--cromo-1);
  background-attachment: scroll;
  color: var(--entrada-tinta);
  text-align: center;
  padding-inline: max(1rem, env(safe-area-inset-left)) max(1rem, env(safe-area-inset-right));
}
/* O anel de foco do tema (a brasa funda do sépia) some no céu: aqui ele é a
   tinta clara da noite, 15:1 contra o fundo. */
.vitrine .vitrine-noite :focus-visible { outline-color: var(--entrada-tinta); }

/* ── O topo ──────────────────────────────────────────────────────────────── */
.vitrine-topo { padding-top: max(.5rem, env(safe-area-inset-top)); padding-bottom: 3.25rem; }
.vitrine-barra {
  display: flex; align-items: center; justify-content: space-between; gap: .5rem 1rem;
  max-width: 68rem; margin: 0 auto; text-align: left;
}
.vitrine .vitrine-marca {
  display: flex; align-items: center; gap: .55rem; margin: 0;
  font-family: var(--serif); font-size: 1.2rem; font-weight: 600; letter-spacing: -.01em;
  color: var(--entrada-tinta);
}
.vitrine-marca img { width: 32px; height: 32px; border-radius: 8px; flex: none; }
.vitrine .vitrine-conta {
  display: flex; align-items: center; justify-content: flex-end; flex-wrap: wrap;
  margin: 0; font-size: .84rem; color: var(--entrada-tinta-2); text-align: right;
}
.vitrine-conta span[aria-hidden] { margin: 0 .3rem; }
.vitrine-conta a {
  display: inline-flex; align-items: center; padding: 0 .2rem;
  color: var(--entrada-brasa); font-weight: 600;
  text-decoration: underline; text-underline-offset: 3px; text-decoration-thickness: 1px;
}
.vitrine .cena { margin: 1.4rem auto 2rem; max-width: 34rem; }
.vitrine h1 {
  font-family: var(--serif); font-size: clamp(2.05rem, 1.35rem + 3vw, 3.3rem); font-weight: 600;
  line-height: 1.1; letter-spacing: -.025em; margin: 0 auto .7rem; max-width: 14em;
  color: var(--entrada-tinta); text-wrap: balance;
}
.vitrine .vitrine-sub {
  font-family: var(--serif); font-style: italic; font-size: clamp(1.1rem, 1rem + .6vw, 1.35rem);
  line-height: 1.45; margin: 0 auto; max-width: 24em; color: var(--entrada-tinta-2); text-wrap: balance;
}
/* «Em breve na App Store»: um rótulo com forma de botão, e contorno em vez de
   campo cheio. Cheio, ele pediria o toque que ainda não tem destino. */
.vitrine .vitrine-loja {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 52px; padding: 0 1.6rem; margin: 2rem 0 0;
  border: 1.5px solid var(--entrada-brasa); border-radius: 999px;
  font-family: var(--sans); font-size: .95rem; font-weight: 600; letter-spacing: .01em;
  color: var(--entrada-tinta);
}
/* O selo oficial, quando ligado (spec 78 §7): a arte da Apple em tamanho de
   tela ≥ 40px, com a margem livre de um quarto da altura em volta. */
.vitrine-selo { display: inline-block; margin: 2rem 0 0; padding: 14px; min-height: 0; }
.vitrine-selo img { display: block; height: 54px; width: auto; }

/* ── O deck ──────────────────────────────────────────────────────────────── */
.vitrine-deck { max-width: 72rem; margin: 0 auto; padding: 2.75rem 0 2.25rem; }
.vitrine-cartoes {
  list-style: none; margin: 0;
  padding: .5rem max(1rem, env(safe-area-inset-right)) 1.25rem max(1rem, env(safe-area-inset-left));
  display: grid; grid-auto-flow: column; grid-auto-columns: min(80vw, 19rem); gap: 1rem;
  overflow-x: auto; overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory; scroll-behavior: smooth;
  scroll-padding-inline: max(1rem, env(safe-area-inset-left)) max(1rem, env(safe-area-inset-right));
  scrollbar-width: none;
}
.vitrine-cartoes::-webkit-scrollbar { display: none; }
/* O trilho ocupa a largura toda, e o `main` corta o que passa da borda: o
   anel por fora sumiria nos lados. Por dentro, ele aparece inteiro. */
.vitrine-cartoes:focus-visible { outline-offset: -3px; border-radius: var(--raio); }
.vitrine-cartao {
  scroll-snap-align: start;
  display: flex; flex-direction: column;
  background: var(--papel); border-radius: 22px; padding: 1rem 1.15rem 1.3rem;
  box-shadow: var(--sombra-pousada);
}
.vitrine-tela {
  margin: 0 0 1.15rem; padding: 1.25rem 0; border-radius: 16px;
  display: flex; justify-content: center; align-items: center;
  background: var(--papel-elev-2);
}
/* O iPhone inteiro, e não só o alto dele: em metade dos cartões o que se conta
   mora embaixo (a caixa da pergunta, a faixa do envio, a saída da célula). */
.vitrine-tela img { display: block; width: 70%; height: auto; filter: drop-shadow(0 10px 18px rgba(0, 0, 0, .18)); }
/* O iPad deitado ocupa a largura do cartão. */
.vitrine-cartao[data-aparelho="ipad"] .vitrine-tela { padding: 1.25rem .9rem; }
.vitrine-cartao[data-aparelho="ipad"] .vitrine-tela img { width: 100%; }
.vitrine .vitrine-cartao h3 {
  font-family: var(--serif); font-size: 1.14rem; font-weight: 700; line-height: 1.28;
  letter-spacing: -.01em; margin: 0 0 .45rem; color: var(--tinta);
}
.vitrine .vitrine-frase { font-size: .95rem; line-height: 1.5; margin: 0; color: var(--tinta-2); }
.vitrine .vitrine-lumes {
  margin: auto 0 0; padding-top: .85rem;
  font-size: .78rem; font-weight: 600; letter-spacing: .02em; color: var(--acento);
}
.vitrine-setas { display: flex; justify-content: center; gap: .75rem; margin-top: .25rem; }
.vitrine-seta {
  display: grid; place-items: center; width: var(--alvo); height: var(--alvo); padding: 0;
  border: 1px solid var(--borda-controle); border-radius: 50%;
  background: var(--papel); color: var(--tinta); font-size: 1.35rem; cursor: pointer;
}
.vitrine-seta:hover { background: var(--papel-elev); }
.vitrine-seta[aria-disabled="true"] { color: var(--tenue); cursor: default; }

/* ── O fecho ─────────────────────────────────────────────────────────────── */
.vitrine-fecho { padding-top: 3.5rem; padding-bottom: 3.75rem; }
.vitrine-chama {
  display: block; width: 56px; height: 56px; margin: 0 auto 1.3rem; border-radius: 15px;
  box-shadow: 0 10px 30px color-mix(in srgb, var(--entrada-brasa) 26%, transparent);
}
.vitrine .vitrine-fecho h2 {
  font-family: var(--serif); font-size: clamp(1.75rem, 1.3rem + 2.2vw, 2.6rem); font-weight: 600;
  line-height: 1.15; letter-spacing: -.02em; margin: 0 auto .6rem; color: var(--entrada-tinta); text-wrap: balance;
}

/* ── O rodapé ────────────────────────────────────────────────────────────── */
.vitrine-rodape {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: .5rem 2rem;
  max-width: 68rem; margin: 0 auto;
  padding: 1.5rem max(1rem, env(safe-area-inset-right)) max(2rem, env(safe-area-inset-bottom)) max(1rem, env(safe-area-inset-left));
  font-size: .88rem;
}
.vitrine .vitrine-legais { display: flex; flex-wrap: wrap; gap: 0 1.25rem; margin: 0; }
.vitrine-rodape a {
  display: inline-flex; align-items: center;
  color: var(--tinta-2); text-decoration: underline; text-underline-offset: 3px; text-decoration-thickness: 1px;
}
.vitrine-linguas ul { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 0 1rem; }
.vitrine-linguas a[aria-current="true"] { color: var(--tinta); font-weight: 700; text-decoration: none; }

/* ── Larguras ────────────────────────────────────────────────────────────── */
@media (min-width: 48rem) {
  .vitrine-topo { padding-bottom: 4.25rem; }
  .vitrine .cena { margin-top: 2rem; }
  .vitrine-cartoes { gap: 1.25rem; }
  /* O iPad é a melhor experiência de leitura, e é ele que a página mostra
     maior: o cartão dele vale dois. */
  .vitrine-cartao[data-aparelho="ipad"] { grid-column: span 2; }
}
/* Na tela larga o topo abre em duas colunas: a chamada à esquerda, a prancha
   à direita. Centrado numa coluna só, o título ficava ilhado no meio de uma
   noite de mil pixels. */
@media (min-width: 60rem) {
  .vitrine-heroi {
    display: grid; grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr); align-items: center;
    gap: 3rem; max-width: 68rem; margin: 0 auto; text-align: left;
  }
  /* A prancha menor que o iPad do deck: a fogueira é a marca, o iPad é o produto. */
  .vitrine-heroi .cena { order: 2; margin: 2.5rem 0; max-width: 24rem; justify-self: end; width: 100%; }
  .vitrine .vitrine-heroi h1, .vitrine .vitrine-heroi .vitrine-sub { margin-left: 0; }
}

/* Com movimento reduzido, a seta e o teclado levam ao cartão sem deslizar. */
@media (prefers-reduced-motion: reduce) {
  .vitrine-cartoes { scroll-behavior: auto; }
}
/* A linha de marca da Apple (spec 78 §7). */
.vitrine .vitrine-credito { flex-basis: 100%; margin: .5rem 0 0; font-size: .75rem; line-height: 1.45; color: var(--tenue); }
