/* =========================================================================
   Mojibake — folha de estilo única.

   Princípios:
   1. TODO tamanho em rem. A escala de fonte do usuário multiplica o
      font-size do <html>, então tudo — cabeçalho, formulários, grafo —
      acompanha. Nada em px, exceto bordas de 1px e sombras.
   2. Cores só via custom properties, definidas por tema. Contraste do texto
      do corpo ≥ 4,5:1 (WCAG 2.1 AA) em TODOS os temas, não só no de alto
      contraste.
   3. Mobile-first. Breakpoints em rem — mas veja a ressalva na seção 17: em
      media query, `rem` NÃO acompanha a escala de fonte do usuário.
   4. Alvos de toque ≥ 2.75rem (~44px). Nenhuma função depende de hover.
   ========================================================================= */

/* --- 1. Escala de fonte controlada pelo usuário ------------------------- */

:root {
  --fs: 1;                      /* sobrescrito inline pelo JS antes da pintura */

  /* Coluna de leitura. 39rem dá ~71 caracteres por linha na base de 18px —
     dentro da faixa confortável de 45 a 75. Antes eram 46rem, que rendiam 87:
     acima de 80, o olho começa a errar a volta para a linha seguinte, e quem
     tem dificuldade de enxergar paga esse erro mais caro.

     Medido no navegador, contando as linhas cheias de um parágrafo real — não
     estimado por largura média de caractere.

     Em rem, então acompanha a escala de fonte: aumentar o texto alarga a coluna
     na mesma proporção e o número de caracteres por linha não muda. */
  --largura: 39rem;

  /* Cabeçalho, rodapé, painel e grafo. Não seguem a coluna de leitura. */
  --largura-larga: 72rem;
  --raio: 0.375rem;
  --espaco: 1rem;
}

/* Base do site: 112,5% da fonte padrão do navegador — 18px onde o padrão são
   os 16px de sempre. Texto de nota fica em 19px.

   Em porcentagem, e não em px, de propósito: quem já aumentou a fonte padrão do
   próprio navegador continua sendo respeitado, com o aumento aplicado por cima.
   Um valor em px anularia essa escolha em silêncio.

   Como TODO tamanho da folha é em rem, mexer só aqui move a interface inteira —
   e a coluna de texto cresce junto, então o número de palavras por linha não
   muda: o texto fica maior, não mais espremido. */
html {
  font-size: calc(112.5% * var(--fs));
  -webkit-text-size-adjust: 100%;
}

/* --- 2. Temas ----------------------------------------------------------- */

/* Claro (padrão). Texto #1a1a1a sobre #fff ≈ 17:1. Secundário #595959 ≈ 7:1. */
:root,
:root[data-tema="claro"] {
  color-scheme: light;

  /* PALETA SATORII (§52).
     Adaptada do tema WordPress Satorii, de Felipe Lavin. O caráter é dele —
     creme de papel, tinta quente, acentos de terra. O que mudou foi a
     CLARIDADE: o sage, o dourado e os apagados originais ficavam entre 2,5 e
     2,9:1, abaixo do mínimo de 4,5. Matiz preservado, luminosidade corrigida.
     O azul de link do original saiu: ele brigava com a paleta nos dois temas,
     e o tan ocupou o lugar. */

  --bg: #fffdf6;          /* papel, não folha de escritório */
  --bg-alt: #f2efdf;      /* o creme #eeeedc do Satorii */
  --bg-code: #f7f4ea;     /* o creme das tabelas dele */
  --texto: #2b2a24;       /* tinta quente, no lugar de um cinza frio */
  --texto-suave: #4b5049; /* o sage #868F83, escurecido até 8,1:1 */
  --borda: #d8d4bf;
  --borda-forte: #8d8a72;
  --link: #8a5a1f;        /* o tan do escuro, escurecido para o papel */
  --acento: #5f3d18;      /* o marrom #963 das tabelas dele, escurecido */
  --foco: #c2410c;        /* o laranja #f30 do hover dele */
  --perigo: #9b1c1c;
  --ok: #3f5c22;
  --marca-privada: #523d00;  /* o dourado #c90, escurecido */

  /* Mapa de escrita: do creme ao marrom, em vez de branco ao azul. Cinco
     degraus de luminosidade bem separados — diferença de tom é o primeiro
     sinal a sumir com sensibilidade ao contraste reduzida. */
  --mapa-0: #f2efdf;
  --mapa-1: #d6c096;
  --mapa-2: #c0a06c;
  --mapa-3: #96703a;
  --mapa-4: #5f3d18;
  --sombra: 0 1px 2px rgba(60, 50, 30, .10);
}

/* Escuro. Texto #e8eaed sobre #14161a ≈ 15:1. Secundário #a3a9b3 ≈ 7,4:1. */
:root[data-tema="escuro"] {
  color-scheme: dark;

  /* A contraparte do Satorii, que o tema original não tem (§52).
     Não é inversão: é a mesma lógica sob outra luz. O creme, que era fundo,
     vira o TEXTO; a terra escura vira o fundo — nunca preto, que com texto
     claro cria halo para quem tem astigmatismo.

     O link é o tan #d3a97a, escolhido por ele. Para caber, três vizinhos se
     afastaram: o sage escureceu, o dourado clareou e o verde do selo escureceu
     — antes os quatro tinham praticamente a mesma luminosidade, e matiz é o
     primeiro sinal a sumir. */

  --bg: #16150f;
  --bg-alt: #211f17;
  --bg-code: #1c1b14;
  --texto: #eae6d5;          /* o creme do Satorii, agora como tinta */
  --texto-suave: #879084;    /* o sage, clareado o suficiente e não mais */
  --borda: #3c3a2c;
  --borda-forte: #7d7f6e;
  --link: #d3a97a;           /* o tan */
  --acento: #a8846a;
  --foco: #ff8a4c;
  --perigo: #f08a8a;
  --ok: #739b3b;
  --marca-privada: #f0d385;
  --mapa-0: #211f17;
  --mapa-1: #4a3f2c;
  --mapa-2: #7d6544;
  --mapa-3: #b08d5e;
  --mapa-4: #e8cfa6;
  --sombra: 0 1px 2px rgba(0, 0, 0, .5);
}

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

    /* A contraparte do Satorii, que o tema original não tem (§52).
       Não é inversão: é a mesma lógica sob outra luz. O creme, que era fundo,
       vira o TEXTO; a terra escura vira o fundo — nunca preto, que com texto
       claro cria halo para quem tem astigmatismo.

       O link é o tan #d3a97a, escolhido por ele. Para caber, três vizinhos se
       afastaram: o sage escureceu, o dourado clareou e o verde do selo escureceu
       — antes os quatro tinham praticamente a mesma luminosidade, e matiz é o
       primeiro sinal a sumir. */

    --bg: #16150f;
    --bg-alt: #211f17;
    --bg-code: #1c1b14;
    --texto: #eae6d5;          /* o creme do Satorii, agora como tinta */
    --texto-suave: #879084;    /* o sage, clareado o suficiente e não mais */
    --borda: #3c3a2c;
    --borda-forte: #7d7f6e;
    --link: #d3a97a;           /* o tan */
    --acento: #a8846a;
    --foco: #ff8a4c;
    --perigo: #f08a8a;
    --ok: #739b3b;
    --marca-privada: #f0d385;
    --mapa-0: #211f17;
    --mapa-1: #4a3f2c;
    --mapa-2: #7d6544;
    --mapa-3: #b08d5e;
    --mapa-4: #e8cfa6;
    --sombra: 0 1px 2px rgba(0, 0, 0, .5);
  }
}

/* Alto contraste: preto puro / branco puro = 21:1. Bordas sólidas, sem cinzas. */
:root[data-tema="contraste"] {
  color-scheme: dark;
  --bg: #000000;
  --bg-alt: #000000;
  --bg-code: #000000;
  --texto: #ffffff;
  --texto-suave: #ffffff;
  --borda: #ffffff;
  --borda-forte: #ffffff;
  --link: #ffe680;
  --acento: #ffe680;
  --foco: #00e5ff;
  --perigo: #ff9a8f;
  --ok: #7dffab;
  --marca-privada: #ffe680;
  /* Alto contraste: degraus em cinza puro, do preto ao branco. */
  --mapa-0: #000000;
  --mapa-1: #595959;
  --mapa-2: #8c8c8c;
  --mapa-3: #c4c4c4;
  --mapa-4: #ffffff;
  --sombra: none;
}

:root[data-tema="contraste"] * {
  text-shadow: none !important;
  box-shadow: none !important;
}

:root[data-tema="contraste"] a,
:root[data-tema="contraste"] .etiqueta {
  text-decoration: underline;
}

:root[data-tema="contraste"] button,
:root[data-tema="contraste"] .botao,
:root[data-tema="contraste"] input,
:root[data-tema="contraste"] select,
:root[data-tema="contraste"] textarea,
:root[data-tema="contraste"] .cartao {
  border: 2px solid var(--borda) !important;
}

/* --- 2½. Fonte de leitura ----------------------------------------------- */

/* Bitter, hospedada por nós e reduzida ao subconjunto latino: 33 KB por corte.
   Nada de CDN — menos uma dependência externa, e a NFSN cobra banda.

   Serifa em bloco e traço quase monolinear: não tem filete fino para sumir,
   que é o defeito das serifadas de contraste alto. Medida no navegador, a
   altura-x é 52% do corpo — a MESMA da sans do sistema, então a troca não
   encolhe nem aumenta o texto aparente.

   `font-display: swap`: o texto aparece imediatamente na fonte de reserva e
   troca quando a Bitter chega. Nunca fica invisível esperando download. */
@font-face {
  font-family: "Bitter";
  src: url("../fonts/bitter-latin.woff2") format("woff2");
  font-weight: 100 900;          /* fonte variável: um arquivo cobre os pesos */
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "Bitter";
  src: url("../fonts/bitter-latin-italic.woff2") format("woff2");
  font-weight: 100 900;
  font-style: italic;
  font-display: swap;
}

/* Só o texto de leitura. A interface — cabeçalho, botões, formulários, painel —
   continua na sans do sistema: é o pareamento que o gwern.net usa, e limita o
   download ao que de fato se lê por muito tempo.

   Georgia como reserva por ser serifada, larga e presente em quase todo lugar:
   a troca ao carregar a Bitter fica discreta em vez de dar um salto. */
.conteudo,
.item__resumo,
/* O título da nota também é conteúdo, e ele mora FORA de .conteudo. Sem esta
   linha, o título saía em sans logo acima dos títulos de seção em serifada.
   `article > header > h1` acerta só as três telas de conteúdo (nota, página,
   livro): nenhuma tela do painel usa <article>. */
article > header > h1 {
  font-family: "Bitter", Georgia, "Times New Roman", serif;
}

/* Hifenização só no texto corrido — não em título, que fica feio quebrado.
   Não é adivinhação do navegador: são dicionários de padrões por idioma,
   escolhidos pelo `lang="pt-BR"` do <html>. Testado com 16 palavras difíceis
   em português (dígrafos, hiatos, encontros consonantais): 16 acertos. O modo
   de falhar é NÃO separar — `ilhéu` ele se recusou a quebrar, porque deixaria
   uma letra sozinha na linha.

   Sem justificação de propósito: alinhar as duas margens faria o espaço entre
   palavras variar de linha para linha, e é a constância desse espaço que ajuda
   o olho a achar o começo da linha seguinte. */
.conteudo p,
.conteudo li,
.conteudo blockquote {
  hyphens: auto;
  -webkit-hyphens: auto;
}

/* --- 3. Reset e base ---------------------------------------------------- */

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

body {
  margin: 0;

  /* Container de consulta para as notas de margem (seção 22). Precisa medir a
     largura DISPONÍVEL na página, não a da coluna de leitura — por isso mora
     aqui, e não no <main>, que já vem limitado por --largura. */
  container: pagina / inline-size;

  background: var(--bg);
  color: var(--texto);
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
               "Helvetica Neue", Arial, sans-serif;
  font-size: 1rem;
  line-height: 1.65;
  overflow-wrap: break-word;
}

h1, h2, h3, h4, h5, h6 {
  line-height: 1.25;
  margin: 2rem 0 0.75rem;
  font-weight: 650;
}
h1 { font-size: 1.875rem; margin-top: 0; }
h2 { font-size: 1.5rem; }
h3 { font-size: 1.25rem; }
h4 { font-size: 1.0625rem; }
h5, h6 { font-size: 1rem; }

p, ul, ol, blockquote, pre, table, figure { margin: 0 0 1.15rem; }

a { color: var(--link); text-underline-offset: 0.15em; }
a:hover { text-decoration-thickness: 0.14em; }

/* NENHUM link muda de cor por ter sido visitado.
   A regra é explícita (em vez de simplesmente ausente) para também anular o
   roxo padrão da folha de estilo do navegador.

   Por quê: a cor de :visited só tem contraste garantido sobre o fundo da
   página. Sobre qualquer outro fundo — botão, cartão, selo — ela vira risco de
   legibilidade, e já causou um rótulo de botão a 1,00:1 no tema escuro. Um
   único par de cores por link é uma coisa a menos para dar errado. */
a:visited { color: var(--link); }

/* Guarda de especificidade. Estes componentes definem a própria cor por classe
   (0-1-0), o que hoje já ganha de `a` (0-0-1). As regras abaixo existem para o
   caso de alguém reintroduzir coloração por estado no futuro: com classe +
   pseudo-classe (0-2-0) elas vencem qualquer `a:visited` ou `a:hover`. */
.botao:link,              .botao:visited,
.topo__marca:link,        .topo__marca:visited,
.nav-principal a:link,    .nav-principal a:visited,
.perfis a:link,           .perfis a:visited,
.pular-para-conteudo:link,.pular-para-conteudo:visited,
.estante a:link,          .estante a:visited {
  color: var(--texto);
}

.botao--principal:link, .botao--principal:visited { color: var(--bg); }
.botao--perigo:link,    .botao--perigo:visited    { color: var(--perigo); }

img { max-width: 100%; height: auto; }

/* Foco visível em TUDO que é interativo. Nunca removido. */
:focus-visible {
  outline: 3px solid var(--foco);
  outline-offset: 2px;
  border-radius: 2px;
}
:focus:not(:focus-visible) { outline: none; }

/* --- 4. Utilitários ----------------------------------------------------- */

.vh {                       /* visualmente oculto, mas lido por leitor de tela */
  position: absolute !important;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.pular-para-conteudo {
  position: absolute;
  left: 0.5rem;
  top: -6rem;
  z-index: 100;
  padding: 0.75rem 1rem;
  background: var(--bg);
  color: var(--texto);
  border: 2px solid var(--foco);
  border-radius: var(--raio);
  transition: top .15s ease;
}
.pular-para-conteudo:focus { top: 0.5rem; }

.rolagem-lateral { overflow-x: auto; max-width: 100%; }

.suave { color: var(--texto-suave); }
.pequeno { font-size: 0.875rem; }

/* Ícones inline. Dimensionados em `em` de propósito: acompanham a escala de
   fonte do usuário e o tamanho do texto ao lado, sem regra extra por contexto.
   A cor vem de currentColor, então herdam o tema — inclusive o alto contraste. */
.icone {
  width: 1em;
  height: 1em;
  flex: none;                 /* não encolhe dentro de contêiner flex */
  vertical-align: -0.125em;   /* alinha com a linha de base do texto */
}

/* Marca de conteúdo privado. Amarelo/âmbar auditado em todos os temas
   (≥ 7,4:1) — o ícone carrega informação, então precisa de contraste real,
   não do mínimo tolerado para enfeite. */
.icone--privado { color: var(--marca-privada); }

/* --- 5. Layout ---------------------------------------------------------- */

.envoltorio {
  width: 100%;
  max-width: var(--largura);
  margin-inline: auto;
  padding-inline: var(--espaco);
}
.envoltorio--largo { max-width: var(--largura-larga); }

main { padding-block: 1.5rem 3rem; }

/* --- 6. Cabeçalho e barra de acessibilidade ----------------------------- */

.topo {
  border-bottom: 1px solid var(--borda);
  background: var(--bg);
}

.topo__linha {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem 1rem;
  padding-block: 0.75rem;

  /* Âncora do painel de opções. Precisa ser ESTA linha, e não a engrenagem:
     quando o menu quebra em várias linhas, a engrenagem vai parar à esquerda,
     e um painel de 17rem alinhado à direita DELA sai pela borda esquerda da
     tela. Visto no celular. Ancorado aqui, o painel encosta sempre na margem
     direita do cabeçalho. */
  position: relative;
}

.topo__marca {
  font-weight: 700;
  font-size: 1.125rem;
  text-decoration: none;
  color: var(--texto);
  margin-right: auto;
  min-height: 2.75rem;
  display: inline-flex;
  align-items: center;
}

.nav-principal ul {
  display: flex;
  flex-wrap: wrap;
  gap: 0.125rem 0.25rem;
  list-style: none;
  margin: 0;
  padding: 0;
}

/* Os perfis das redes (§68) dividem a linha da engrenagem em vez de abrirem
   uma terceira no celular — o porquê, com a medida, está no layout.php. Herdam
   as regras do link de menu abaixo, e o alvo de toque de 2.75rem junto: são
   ícones de 1em, e sem isso o alvo teria 18px num dedo. */
.perfis {
  display: flex;
  gap: 0.125rem 0.25rem;
  flex: none;
}

.nav-principal a,
.perfis a {
  display: inline-flex;
  align-items: center;
  /* Em contêiner flex, um nó de texto só com espaço é descartado — era por
     isso que a marca de privado colava no nome do blog. O gap repõe o
     espaçamento de forma explícita, sem depender de espaço no HTML. */
  gap: 0.4em;
  min-height: 2.75rem;          /* alvo de toque ≥ 44px */
  padding-inline: 0.6rem;
  border-radius: var(--raio);
  text-decoration: none;
  color: var(--texto);
}
.nav-principal a:hover,
.perfis a:hover { background: var(--bg-alt); text-decoration: underline; }
.nav-principal a[aria-current="page"] {
  background: var(--bg-alt);
  box-shadow: inset 0 -0.1875rem 0 var(--acento);
  font-weight: 600;
}

/* Opções atrás da engrenagem, ao lado do sorteio.

   Substituiu a barra sempre visível. A decisão anterior — não esconder
   controle de acessibilidade — foi revista porque fonte e tema PERSISTEM no
   localStorage: são escolhidos uma vez, e a barra custava três linhas de
   altura no celular em toda visita. */
.opcoes { flex: none; }

/* Some com o triângulo nativo do <summary>, nos dois motores. */
.opcoes__botao { list-style: none; }
.opcoes__botao::-webkit-details-marker { display: none; }
.opcoes__botao::marker { content: ""; }

.opcoes__botao {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 2.75rem;           /* alvo de toque ≥ 44px */
  min-height: 2.75rem;
  padding-inline: 0.5rem;
  border: 1px solid var(--borda-forte);
  border-radius: var(--raio);
  cursor: pointer;
  color: var(--texto);
  font-size: 1.15rem;           /* a engrenagem é dimensionada em em */
}
.opcoes__botao:hover { background: var(--bg-alt); }

/* Aberta, a engrenagem gira um oitavo — confirma o estado sem depender de cor.
   O giro respeita prefers-reduced-motion na seção 18. */
.opcoes[open] .opcoes__botao {
  background: var(--bg-alt);
  box-shadow: inset 0 -0.1875rem 0 var(--acento);
}
.opcoes[open] .opcoes__botao .icone { transform: rotate(45deg); }
.opcoes__botao .icone { transition: transform .18s ease; }

.opcoes__painel {
  position: absolute;
  top: calc(100% + 0.4rem);
  right: 0;
  z-index: 60;
  width: 17rem;
  max-width: calc(100vw - 2rem);   /* nunca sai da tela no celular */
  padding: 0.875rem;
  background: var(--bg);
  border: 1px solid var(--borda-forte);
  border-radius: var(--raio);
  box-shadow: var(--sombra);
  display: flex;
  flex-direction: column;
  gap: 0.875rem;
}

.opcoes__bloco { display: flex; flex-direction: column; gap: 0.3rem; margin: 0; }
.opcoes__bloco > label,
.opcoes__bloco > span:first-child {
  font-size: 0.8125rem;
  color: var(--texto-suave);
}

.opcoes__linha { display: flex; align-items: center; gap: 0.25rem; }
.opcoes__linha input[type="search"] { flex: 1 1 auto; min-width: 0; }
.opcoes__linha button { flex: none; }

.opcoes__valor {
  min-width: 3.2rem;
  text-align: center;
  font-size: 0.8125rem;
  color: var(--texto-suave);
}

.opcoes__bloco--conta {
  border-top: 1px solid var(--borda);
  padding-top: 0.875rem;
}
.opcoes__bloco--conta .botao,
.opcoes__bloco--conta button { width: 100%; justify-content: center; }

/* --- 7. Botões e formulários -------------------------------------------- */

button, .botao {
  font: inherit;
  min-height: 2.75rem;
  min-width: 2.75rem;
  padding: 0.375rem 0.875rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.375rem;
  background: var(--bg-alt);
  color: var(--texto);
  border: 1px solid var(--borda-forte);
  border-radius: var(--raio);
  cursor: pointer;
  text-decoration: none;
}
button:hover, .botao:hover { border-color: var(--borda-forte); }

.botao--principal {
  background: var(--acento);
  border-color: var(--acento);
  color: var(--bg);
  font-weight: 600;
}
:root[data-tema="contraste"] .botao--principal { color: #000; }

.botao--perigo { color: var(--perigo); border-color: var(--perigo); }
.botao--fantasma { background: transparent; }

.botao-icone {
  padding: 0.375rem;
  font-size: 1.0625rem;
  line-height: 1;
}

input, select, textarea {
  font: inherit;
  color: var(--texto);
  background: var(--bg);
  border: 1px solid var(--borda-forte);
  border-radius: var(--raio);
  padding: 0.5rem 0.625rem;
  min-height: 2.75rem;
  width: 100%;
  max-width: 100%;
}
textarea { min-height: 18rem; resize: vertical; line-height: 1.6; }

.campo { margin-bottom: 1.15rem; }
.campo > label,
.campo > .campo__rotulo {
  display: block;
  font-weight: 600;
  margin-bottom: 0.3125rem;
}
.campo__ajuda {
  display: block;
  font-size: 0.8125rem;
  color: var(--texto-suave);
  margin-top: 0.3125rem;
}

/* As seções da tela de configuração (§69).
 *
 * `fieldset` chega com borda e recuo próprios do navegador, diferentes em cada
 * um; aqui ele é zerado e redesenhado com os tokens do tema, para a caixa
 * parecer com o resto do painel e acompanhar claro/escuro/alto contraste.
 *
 * `min-width: 0` no fieldset não é firula: sem ele o elemento se recusa a
 * encolher abaixo do conteúdo mais largo — é um comportamento antigo e
 * específico dele — e um <select> comprido empurra a tela para o lado no
 * celular. */
.secao-config {
  min-width: 0;
  margin: 0 0 2rem;
  padding: 1rem 1.25rem 0.25rem;
  border: 1px solid var(--borda);
  border-radius: var(--raio);
}

.secao-config legend {
  padding-inline: 0.4rem;
  font-weight: 700;
  font-size: 1.0625rem;
}

.secao-config__ajuda {
  margin: 0 0 1.15rem;
  font-size: 0.8125rem;
  color: var(--texto-suave);
}

/* O índice: linha de atalhos, não lista com marcadores. */
.indice-config ul {
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem 0.5rem;
  list-style: none;
  margin: 0 0 1.5rem;
  padding: 0;
}

.indice-config a {
  display: inline-flex;
  align-items: center;
  min-height: 2.75rem;          /* alvo de toque, como no menu */
  padding-inline: 0.6rem;
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  text-decoration: none;
}

.indice-config a:hover { background: var(--bg-alt); text-decoration: underline; }

/* Caixa de marcar com o rótulo ao lado.
 *
 * O `.campo__caixa` existia no HTML desde a fila de triagem (§56) e NUNCA teve
 * regra: a caixa herdava `min-height: 2.75rem` e `width: 100%` da regra
 * genérica de `input` — que é feita para campo de texto — e virava um quadrado
 * enorme acima do rótulo. Ele viu na tela de configuração (§68), no laptop e no
 * celular. A correção já existia para `.campo--inline`; o que faltava era ela
 * valer para esta classe.
 *
 * O seletor é `.campo > .campo__caixa` porque `.campo > label` (0-1-1) ganharia
 * de `.campo__caixa` (0-1-0) e devolveria o `display: block`.
 *
 * O ALVO DE CLIQUE É A LINHA INTEIRA, e não o quadradinho de 20px: o <label>
 * envolve a caixa e o texto. É o que faz esta caixa ser mirável por quem não
 * enxerga bem — o tamanho do desenho não precisa ser o tamanho do alvo. */
.campo__caixa,
.campo > .campo__caixa {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-weight: 600;
  cursor: pointer;
}

.campo__caixa input[type="checkbox"],
.campo--inline input[type="checkbox"] {
  width: 1.25rem;
  height: 1.25rem;
  min-height: 0;
  flex: none;
}

.campo--inline {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}
.campo--inline label { font-weight: 600; margin: 0; }

/* Campo de senha com o botão de revelar ao lado.
 *
 * O <div> é criado pelo JS, nunca pelo HTML: sem script não existe botão, e
 * sem botão não existe esta linha — o campo volta a ser um input comum, com a
 * largura de sempre. É a mesma regra de §5.2, de não deixar controle morto na
 * tela.
 *
 * `align-items: stretch` de propósito: o botão fica exatamente da altura do
 * campo, e os dois alvos ficam do mesmo tamanho. Com `center` o botão
 * encolheria para o mínimo de 2.75rem e desalinharia quando a escala de fonte
 * aumenta — justamente na configuração de quem mais precisa acertar o clique.
 */
.campo__senha {
  display: flex;
  align-items: stretch;
  gap: 0.5rem;
}
.campo__senha input { flex: 1 1 auto; }
.campo__senha button { flex: none; white-space: nowrap; }

.grade-campos {
  display: grid;
  gap: 0 1rem;
  grid-template-columns: 1fr;
}

/* Ocupa a linha inteira da grade, seja ela de uma ou de duas colunas. Numa
   coluna só, `1 / -1` já é o comportamento normal — a regra existe para a
   janela larga, onde .grade-campos vira duas colunas (§17 do CSS). */
.campo--largo { grid-column: 1 / -1; }

/* O nome do quadrante no editor: a frase que devolve, em uma linha, o que
   saiu da combinação de "Quando" e "Visibilidade" (§42).

   Sem cor própria e sem fundo: é uma frase de leitura, não um alerta, e
   qualquer par novo de cores aqui teria que passar pelo contraste.php. O peso
   vem do <strong> dentro dela, que é onde está o nome. */
.quadrante {
  display: block;
  margin-top: 0.35rem;
  padding: 0.5rem 0.65rem;
  border-inline-start: 3px solid var(--borda);
  line-height: 1.4;
}
.quadrante strong { font-weight: 600; }
.quadrante__porque { color: var(--texto-suave); }

fieldset {
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  padding: 1rem;
  margin: 0 0 1.15rem;
}
legend { font-weight: 600; padding-inline: 0.375rem; }

.acoes-form {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  align-items: center;
  margin-top: 1.5rem;
}

/* --- 8. Avisos ---------------------------------------------------------- */

.aviso {
  border: 1px solid var(--borda);
  border-left: 0.25rem solid var(--acento);
  background: var(--bg-alt);
  border-radius: var(--raio);
  padding: 0.75rem 1rem;
  margin-bottom: 1.5rem;
}
.aviso--erro { border-left-color: var(--perigo); }
.aviso--ok { border-left-color: var(--ok); }

/* --- 9. Listagens ------------------------------------------------------- */

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

.lista-notas > li {
  padding-block: 1.15rem;
  border-bottom: 1px solid var(--borda);
}
.lista-notas > li:first-child { padding-top: 0; }

.item__titulo { margin: 0 0 0.25rem; font-size: 1.1875rem; }
.item__titulo a { text-decoration: none; }
.item__titulo a:hover { text-decoration: underline; }

.item__meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.25rem 0.75rem;
  font-size: 0.8125rem;
  color: var(--texto-suave);
  margin-bottom: 0.375rem;
}

.item__resumo { margin: 0; color: var(--texto); }

/* Aside na listagem: sem título, o conteúdo é o cartão inteiro. */
.item--aside .item__resumo { font-size: 1.0625rem; }

.selo {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  font-size: 0.75rem;
  font-weight: 600;
  padding: 0.125rem 0.5rem;
  border: 1px solid var(--borda);
  border-radius: 999px;
  color: var(--texto-suave);
  white-space: nowrap;
}
.selo--privada { color: var(--marca-privada); border-color: currentColor; }
.selo--maturidade { color: var(--ok); border-color: currentColor; }

.cartao {
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  padding: 1rem;
  background: var(--bg-alt);
  box-shadow: var(--sombra);
}

.grade-cartoes {
  display: grid;
  gap: 1rem;
  grid-template-columns: 1fr;
  list-style: none;
  padding: 0;
  margin: 0 0 1.5rem;
}

/* --- 10. Conteúdo renderizado da nota ----------------------------------- */

.conteudo { font-size: 1.0625rem; }
.conteudo > :first-child { margin-top: 0; }

.conteudo blockquote {
  margin-inline: 0;
  padding: 0.25rem 0 0.25rem 1rem;
  border-left: 0.25rem solid var(--borda-forte);
  color: var(--texto-suave);
}

.conteudo code {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.9em;
  background: var(--bg-code);
  padding: 0.1em 0.3em;
  border-radius: 3px;
}

.conteudo pre {
  background: var(--bg-code);
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  padding: 0.875rem 1rem;
  overflow-x: auto;
}
.conteudo pre code { background: none; padding: 0; font-size: 0.875rem; }

.conteudo table { border-collapse: collapse; width: 100%; font-size: 0.9375rem; }
.conteudo th, .conteudo td {
  border: 1px solid var(--borda);
  padding: 0.4375rem 0.625rem;
  text-align: left;
}
.conteudo th { background: var(--bg-alt); }

.conteudo hr { border: 0; border-top: 1px solid var(--borda); margin: 2rem 0; }

.lista-tarefas { list-style: none; padding-left: 0.25rem; }
.lista-tarefas .tarefa { display: flex; gap: 0.5rem; align-items: baseline; }

/* Wikilinks: rascunho vazio e alvo inexistente ficam visualmente distintos —
   e a distinção não é só por cor (usa borda tracejada). */
.wikilink { text-decoration-style: solid; }
.wikilink--rascunho {
  color: var(--marca-privada);
  border-bottom: 1px dashed currentColor;
  text-decoration: none;
}
.wikilink--ausente {
  color: var(--texto-suave);
  border-bottom: 1px dotted currentColor;
  cursor: help;
}

.etiqueta {
  display: inline-block;
  font-size: 0.9em;
  text-decoration: none;
  border-bottom: 1px solid currentColor;
}

/* Imagem dentro da nota.
   `display: block` com margem automática centraliza sem depender de o autor
   escrever qualquer coisa. A borda existe porque foto de fundo claro sobre
   tema claro (e escuro sobre escuro) some na página sem uma aresta. */
/* Figura com legenda (§47).

   A imagem dentro da figura perde a margem própria: quem espaça agora é a
   `<figure>`, senão sobra um vão entre a foto e a legenda dela. */
.figura {
  margin: 1.5rem 0;
}
.figura .imagem-nota {
  margin: 0 auto;
}
.figura figcaption {
  /* Inclinada porque é assim que ela é escrita (`*legenda*`) e é assim que ele
     já a via com o `<small>`. O itálico vem daqui e não de um <em> no HTML:
     legenda não é ênfase, e leitor de tela não deve anunciá-la como tal. */
  font-style: italic;
  color: var(--texto-suave);
  font-size: 0.9375rem;
  line-height: 1.45;
  text-align: center;
  margin-top: 0.5rem;
  text-wrap: pretty;
}

.imagem-nota {
  display: block;
  max-width: 100%;

  /* `width: auto` é obrigatório aqui, junto do max-height abaixo.
     O <img> traz width="1600" height="1200" no HTML (ver Markdown::imageEmbeds),
     e o atributo vira uma largura DEFINIDA. Com largura definida, o navegador
     não preserva proporção ao aplicar `max-height`: ele corta a altura e deixa
     a largura onde estava, achatando a foto. Medido no Firefox — um retrato de
     1200x1600 saía 738x722 em vez de 542x722.
     Com as duas dimensões automáticas, a proporção volta a ser respeitada, e a
     reserva de espaço contra salto de layout continua vindo do aspect-ratio que
     o navegador deriva dos mesmos atributos. */
  width: auto;
  height: auto;

  margin: 1.5rem auto;
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  background: var(--bg-alt);

  /* Teto de altura para foto em pé.
     Sem isto, um retrato de 1200x1600 na coluna de 704px sai com 939px de
     altura e ocupa mais que a janela inteira: some o texto de cima e o de
     baixo ao mesmo tempo, e não sobra referência de onde se estava lendo.
     Uma captura de tela comprida é pior ainda.

     Nada é cortado — `max-width` e `max-height` juntos, com largura e altura
     automáticas, fazem o navegador reduzir a imagem inteira preservando a
     proporção. Quando o teto entra em ação a imagem fica mais estreita que a
     coluna, e o `margin: auto` acima a centraliza.

     `dvh` depois de `vh`: no celular, `vh` mede a janela com a barra do
     navegador escondida, então 80vh pode passar do que está visível de fato.
     Onde `dvh` existe, ele vence; onde não existe, a linha é ignorada e fica
     valendo `vh`. */
  max-height: 80vh;
  max-height: 80dvh;
}

/* Imagem citada que não existe na biblioteca. Mesmo tratamento do wikilink
   ausente: tracejado além da cor, para não depender de enxergar a diferença
   de tom. */
.imagem-ausente {
  display: inline-block;
  color: var(--texto-suave);
  border: 1px dashed currentColor;
  border-radius: var(--raio);
  padding: 0.125em 0.5em;
  font-size: 0.9em;
  cursor: help;
}

/* --- 11. Seções laterais da nota ---------------------------------------- */

.secao-nota {
  margin-top: 2.5rem;
  padding-top: 1.25rem;
  border-top: 1px solid var(--borda);
}
.secao-nota h2 { font-size: 1.125rem; margin-top: 0; }

.lista-simples { list-style: none; padding: 0; margin: 0; }
.lista-simples li { padding-block: 0.375rem; }

.nuvem { display: flex; flex-wrap: wrap; gap: 0.375rem; list-style: none; padding: 0; margin: 0; }
.nuvem a {
  display: inline-flex;
  align-items: center;
  /* O `gap` NÃO é enfeite: sem ele sai "#notetaking(22)", grudado.
     Numa caixa flex cada trecho de texto vira um item anônimo e o espaço em
     branco das BORDAS de cada item é descartado — o espaço que existe no HTML
     entre o nome e o "(22)" some por regra do flexbox. Trocar o display
     resolveria o espaço e quebraria a centralização vertical da pílula, que
     depende do inline-flex com min-height. O `.vh` é position:absolute, então
     não é item de flex e não ganha gap. */
  gap: 0.3rem;
  min-height: 2.25rem;
  padding: 0.25rem 0.6rem;
  border: 1px solid var(--borda);
  border-radius: 999px;
  text-decoration: none;
}
.nuvem a:hover { border-color: var(--borda-forte); text-decoration: underline; }

/* --- 12. Paginação ------------------------------------------------------ */

.paginacao {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
  margin-top: 2rem;
  padding-top: 1rem;
  border-top: 1px solid var(--borda);
}
.paginacao__status { color: var(--texto-suave); font-size: 0.875rem; }

/* --- 13. Leituras ------------------------------------------------------- */

.estante {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(9rem, 1fr));
  gap: 1.25rem;
  list-style: none;
  padding: 0;
  margin: 0;
}

.livro__capa {
  display: block;
  width: 100%;
  aspect-ratio: 2 / 3;
  object-fit: cover;
  background: var(--bg-alt);
  border: 1px solid var(--borda);
  border-radius: var(--raio);
}

.livro__capa-vazia {
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 0.5rem;
  font-size: 0.8125rem;
  color: var(--texto-suave);
  aspect-ratio: 2 / 3;
  border: 1px dashed var(--borda-forte);
  border-radius: var(--raio);
  background: var(--bg-alt);
}

.livro__titulo { font-size: 0.9375rem; font-weight: 600; margin: 0.5rem 0 0; }
.livro__autor { font-size: 0.8125rem; color: var(--texto-suave); margin: 0; }

/* As estrelas viraram SVG: o letter-spacing não se aplica mais a glifo
   nenhum, e o respiro entre elas passa a ser gap de flex. inline-flex para a
   fileira não herdar o entrelinha do parágrafo. */
.nota-estrelas {
  display: inline-flex;
  align-items: center;
  gap: 0.1em;
}

/* Um pouco menor que a letra: no tamanho cheio a fileira de cinco pesava mais
   que o título do livro ao lado. */
.icone--estrela {
  width: 0.9em;
  height: 0.9em;
  vertical-align: -0.08em;
}

/*
 * Trilha do painel. Fica acima do <h1>, com margem inferior curta para ler
 * como pertencente ao título, e não como uma linha solta de conteúdo.
 */
.trilha {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.5rem;
  font-size: 0.875rem;
  margin-bottom: 1rem;
}

.trilha__sep { color: var(--texto-suave); }

/*
 * Zona de perigo: o bloco de exclusão, separado do formulário por uma faixa de
 * espaço grande o bastante para o clique não escorregar do "Salvar" para cá.
 *
 * A borda é da cor de perigo, mas a cor NÃO é o que informa: o título diz
 * "Excluir esta nota" e a lista diz o que se perde. No modo de alto contraste,
 * onde a cor da borda pode ser substituída pelo sistema, o bloco continua
 * dizendo a mesma coisa.
 */
/* Anúncios nas redes (§68).

   Moldura discreta, ao contrário da zona-perigo: publicar nas redes é
   irreversível, mas não é destrutivo — não desfaz nada que exista aqui. O
   freio dessa irreversibilidade é o confirm() e a pausa entre anúncios, não a
   cor da borda. */
.anuncios {
  margin-top: 2.5rem;
  padding: 1.25rem;
  border: 1px solid var(--borda);
  border-radius: var(--raio);
}

.anuncios h2 { margin-top: 0; font-size: 1.125rem; }

.anuncios__lista {
  list-style: none;
  margin: 0 0 1rem;
  padding: 0;
}

.anuncios__lista > li { margin-bottom: 1rem; }

/* A palavra "falhou" carrega informação, então vai na cor de perigo — que é
   auditada — e não numa tinta decorativa. Ela vem sempre acompanhada do texto
   do erro: cor sozinha não informa quem não distingue a cor. */
.anuncios__falha { color: var(--perigo); font-weight: 600; }

.anuncios__erro {
  margin: 0.25rem 0;
  padding: 0.5rem 0.75rem;
  border-left: 3px solid var(--perigo);
  background: var(--bg-alt);
}

/* Os links de responder: alvo de toque cheio, como todo botão do site. */
.responder__lista {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin: 0;
  padding: 0;
}

.zona-perigo {
  margin-top: 3rem;
  padding: 1.25rem;
  border: 2px solid var(--perigo);
  border-radius: var(--raio);
}

.zona-perigo h2 { margin-top: 0; font-size: 1.125rem; }
.zona-perigo ul { margin: 0 0 1rem; padding-left: 1.25rem; }
.zona-perigo li { margin-bottom: 0.375rem; }
.zona-perigo p:first-of-type { margin-bottom: 0.5rem; }

/*
 * Progresso de leitura.
 *
 * A porcentagem é TEXTO; a barra é uma segunda representação do mesmo número,
 * marcada aria-hidden para não ser lida duas vezes. Nunca há informação só na
 * barra — quem enxerga mal, quem lê por leitor de tela e quem está no modo de
 * alto contraste leem o número igual.
 *
 * A borda da barra é sólida (e não só o preenchimento colorido) para o trilho
 * continuar visível quando o preenchimento for 0%.
 */
.livro__progresso {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.8125rem;
  color: var(--texto-suave);
  margin: 0.25rem 0 0;
}

.livro__progresso .barra {
  flex: 1 1 auto;
  min-width: 2.5rem;
  height: 0.5rem;
  border: 1px solid var(--borda-forte);
  border-radius: 999px;
  background: var(--bg-alt);
  overflow: hidden;
}

.livro__progresso .barra > span {
  display: block;
  height: 100%;
  background: var(--link);
}

/* --- 14. Grafo ---------------------------------------------------------- */

.grafo-caixa {
  position: relative;
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  background: var(--bg-alt);
  overflow: hidden;
  touch-action: pan-y;
}

/* `touch-action: none` é o que faz arrastar um nó funcionar no celular: sem
   isso o navegador interpreta o gesto como rolagem da página e o pointermove
   nunca chega. Vale para o pan do fundo pela mesma razão. */
.grafo-svg {
  display: block;
  width: 100%;
  height: min(75vh, 40rem);
  touch-action: none;
}

/* Só o cursor muda: o nó arrastado não ganha cor nem tamanho novo, porque o
   tamanho já significa grau de conexão e a cor já significa privacidade. */
.grafo-no { cursor: grab; }
.grafo-no--arrastado { cursor: grabbing; }
.grafo-no--arrastado circle { stroke: var(--foco); stroke-width: 3; }

.grafo-aresta { stroke: var(--borda-forte); stroke-opacity: .55; stroke-width: 1; }

.grafo-no circle {
  fill: var(--acento);
  stroke: var(--bg);
  stroke-width: 1.5;
}
.grafo-no--privada circle { fill: var(--marca-privada); }
.grafo-no--aside circle { fill: var(--ok); }
.grafo-no:hover circle,
.grafo-no:focus circle { stroke: var(--foco); stroke-width: 3; }
.grafo-no text {
  fill: var(--texto);
  font-size: 0.6875rem;
  paint-order: stroke;
  stroke: var(--bg);
  stroke-width: 0.1875rem;
  stroke-linejoin: round;
}

.grafo-legenda {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem 1.25rem;
  list-style: none;
  padding: 0.75rem 0 0;
  margin: 0;
  font-size: 0.875rem;
}
.grafo-legenda li { display: flex; align-items: center; gap: 0.4375rem; }
.grafo-legenda .amostra {
  width: 0.75rem; height: 0.75rem; border-radius: 50%;
  border: 1px solid var(--borda-forte);
}

/* Alternativa textual ao grafo: sempre presente no DOM, nunca escondida
   de leitores de tela. */
.grafo-alternativa { margin-top: 1.5rem; }
.grafo-alternativa summary {
  cursor: pointer;
  min-height: 2.75rem;
  display: flex;
  align-items: center;
  font-weight: 600;
}

/* --- 15. Rodapé --------------------------------------------------------- */

.rodape {
  border-top: 1px solid var(--borda);
  padding-block: 1.5rem 2.5rem;
  font-size: 0.875rem;
  color: var(--texto-suave);
}
/*
 * Imagem no texto do rodapé: o campo aceita Markdown, e ele passou a usar isso
 * para pôr o botão de 88×31. Sem estas duas linhas a imagem senta na LINHA DE
 * BASE — o botão fica alto demais em relação à frase — e cola no aviso de
 * conteúdo público que vem logo depois, no mesmo <p>.
 *
 * Não é regra para imagem qualquer: só para a que aparece nesse texto.
 */
.rodape p img {
  vertical-align: middle;
  margin-inline: 0.15rem 0.4rem;
}

/*
 * O <nav> é quem RECORTA — ele não se move, e por isso serve de régua.
 *
 * O padding de 6px empurra a borda do recorte para fora em todos os lados, e a
 * margem negativa igual devolve o bloco ao lugar: o layout fica idêntico, mas a
 * área visível passa a ter 6px de folga. Sem isso, `overflow` cortaria o anel
 * de foco (3px de traço + 2px de afastamento) do primeiro link de cada linha —
 * trocar um quadradinho pendurado por foco invisível seria péssimo negócio.
 */
.rodape nav {
  overflow: hidden;
  padding: 6px;
  margin: -6px;
}

.rodape ul {
  display: flex;
  flex-wrap: wrap;
  /* Sem vão de coluna: o espaçamento horizontal inteiro vem do separador, que
     tem largura fixa. É isso que torna o deslocamento abaixo exato. */
  gap: 0.5rem 0;
  list-style: none;
  padding: 0;
  /* Puxa a lista para a esquerda exatamente a largura de um separador. Cada
     linha passa a começar com o seu separador fora da área visível — inclusive
     as linhas criadas por quebra, porque todas compartilham a mesma margem
     esquerda. */
  margin: 0 0 0.75rem -2.2rem;
}

/*
 * Separador do rodapé: vem ANTES de cada item, inclusive do primeiro.
 *
 * O CSS não sabe onde a linha quebrou, então não dá para suprimir o separador
 * "do último item da linha". A saída é inverter o problema: se ele precede todo
 * item, o que sobra é sempre o do COMEÇO de cada linha — e o começo de todas as
 * linhas está na mesma coordenada, que é justamente o que o recorte acima
 * elimina, de uma vez, em qualquer largura e em qualquer escala de fonte.
 *
 * A largura fixa em rem (e não em em) é o que faz o deslocamento bater: ela
 * acompanha a escala de fonte do site, mas ignora o `font-size: 0.75em` daqui
 * de dentro, que encolhe só o glifo. Com o quadrado centrado numa caixa de
 * 2.2rem, sobra folga de sobra dos dois lados da borda do recorte.
 *
 * As duas declarações de `content` são de propósito: a segunda usa a sintaxe
 * `"x" / ""`, que dá texto alternativo VAZIO ao conteúdo gerado — sem ela o
 * leitor de tela anuncia "quadrado preto" entre cada link. Navegador que não
 * entender a sintaxe descarta a segunda e fica com a primeira, mantendo o
 * separador visível. Verificado: o Firefox daqui aceita.
 */
.rodape li::before {
  content: "◼";
  content: "◼" / "";
  display: inline-block;
  width: 2.2rem;
  text-align: center;
  color: var(--borda-forte);
  font-size: 0.75em;
  vertical-align: 0.1em;
}

/* --- 16. Tabela do admin ------------------------------------------------ */

.tabela { width: 100%; border-collapse: collapse; font-size: 0.9375rem; }
.tabela th, .tabela td {
  text-align: left;
  padding: 0.625rem 0.5rem;
  border-bottom: 1px solid var(--borda);
  vertical-align: top;
}
.tabela th { white-space: nowrap; }
.tabela tbody tr:hover { background: var(--bg-alt); }

.linha-acoes { display: flex; flex-wrap: wrap; gap: 0.375rem; }
.linha-acoes form { display: inline; }

/* --- 17. Breakpoints ---------------------------------------------------- */

/* ATENÇÃO: `rem` em media query NÃO segue o font-size do <html>.
   Por especificação, unidades relativas em media query são resolvidas contra o
   valor INICIAL — a fonte padrão do navegador —, nunca contra o resultado de
   uma declaração. Então estes 40rem valem ~640px de viewport sempre, tanto na
   escala de 85% quanto na de 175%.

   Medido: com --fs em 1.75 numa janela de 1000px, .grade-campos continua em
   duas colunas. Se o breakpoint acompanhasse a escala, 40rem seriam 1260px e
   ela teria voltado para uma coluna.

   Consequência prática: em escala alta e janela estreita, um formulário de duas
   colunas pode ficar apertado. Corrigir exigiria container queries ou JS —
   nenhum dos dois foi feito aqui. */

@media (min-width: 40rem) {
  .grade-campos { grid-template-columns: 1fr 1fr; }
  .grade-cartoes { grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr)); }
  h1 { font-size: 2.25rem; }
}

@media (min-width: 60rem) {
  main { padding-block: 2.5rem 4rem; }
}

/* --- 18. Movimento reduzido -------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }
}

/* --- 19. Impressão ------------------------------------------------------ */

@media print {
  .topo, .opcoes, .rodape, .paginacao, .grafo-caixa { display: none; }
  body { background: #fff; color: #000; }
  a::after { content: " (" attr(href) ")"; font-size: 0.75em; }
}

/* --- 20. Abertura da home ----------------------------------------------- */

/* Texto de abertura vindo de uma página. Ligeiramente maior que o corpo:
   é a primeira coisa que se lê, e o site inteiro escala junto pelo --fs. */
.abertura {
  font-size: 1.125rem;
  margin-bottom: 2rem;
  padding-bottom: 1.5rem;
  border-bottom: 1px solid var(--borda);
}
.abertura > :last-child { margin-bottom: 0; }

/* --- 21. Biblioteca de imagens (admin) ---------------------------------- */

/* Cartões e não linhas de tabela: a miniatura precisa ser grande o bastante
   para reconhecer a foto sem depender de ler o nome do arquivo.
   `auto-fill` com mínimo em rem faz a grade acompanhar a escala de fonte —
   com a fonte em 175%, os cartões ficam maiores e passam a caber menos por
   linha, em vez de espremerem o texto. */
.biblioteca {
  list-style: none;
  padding: 0;
  margin: 1.5rem 0 0;
  display: grid;
  gap: 1.25rem;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 22rem), 1fr));
}

.biblioteca__item {
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  background: var(--bg-alt);
  padding: 0.875rem;
  display: flex;
  flex-direction: column;
  gap: 0.625rem;
}

.biblioteca__foto {
  display: block;
  /* Xadrez leve por baixo: sem ele, um PNG transparente fica indistinguível
     de um PNG de fundo sólido igual ao do tema. */
  background-color: var(--bg);
  background-image:
    linear-gradient(45deg, var(--bg-alt) 25%, transparent 25%, transparent 75%, var(--bg-alt) 75%),
    linear-gradient(45deg, var(--bg-alt) 25%, transparent 25%, transparent 75%, var(--bg-alt) 75%);
  background-size: 1rem 1rem;
  background-position: 0 0, 0.5rem 0.5rem;
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  overflow: hidden;
}

.biblioteca__foto img {
  display: block;
  width: 100%;
  height: auto;
  max-height: 15rem;
  object-fit: contain;
}

.biblioteca__corpo { display: flex; flex-direction: column; gap: 0.5rem; }
.biblioteca__corpo > p { margin: 0; }

.biblioteca__nome code {
  display: inline-block;
  word-break: break-all;
}

.biblioteca__notas {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
}

.biblioteca__alt { margin: 0; }
.biblioteca__alt .campo { margin-bottom: 0.5rem; }

.envio-imagem { margin: 1.5rem 0; }

/* Marca de campo obrigatório. Não fica só na cor: a palavra está escrita. */
.obrigatorio {
  font-weight: 400;
  color: var(--texto-suave);
}

/* --- 22. Notas de margem ------------------------------------------------ */

/* Largura da faixa da direita e o respiro entre ela e o texto. */
:root {
  --margem-nota: 13rem;
  --margem-vao: 1.5rem;
}

/* A marca. `aria-hidden` no HTML: sozinho, um "1" no meio da frase é ruído
   para quem ouve. O corpo vem logo depois, anunciado como nota. */
.nota-marca {
  font-size: 0.72em;
  font-weight: 700;
  line-height: 1;
  vertical-align: super;
  color: var(--acento);
  padding-inline: 0.12em;
}

/* PADRÃO — tela estreita: bloco destacado logo depois da marca.
   Não é escondido atrás de um toque, como faz o Tufte CSS: aquilo depende de
   um <label> vazio, que leitor de tela anuncia mal, e esconde conteúdo de quem
   já tem dificuldade para achá-lo. */
.nota-margem {
  display: block;
  margin: 0.875rem 0;
  padding: 0.625rem 0.875rem;
  border-left: 0.25rem solid var(--borda-forte);
  background: var(--bg-alt);
  border-radius: 0 var(--raio) var(--raio) 0;
  font-size: 0.9375rem;
  line-height: 1.55;
}

.nota-margem__num {
  font-weight: 700;
  color: var(--acento);
  margin-right: 0.4em;
}

/* Referência sem definição no fim do texto. Tracejado além da cor, como o
   wikilink e a imagem ausentes — a diferença não pode depender só do tom. */
.nota-ausente {
  color: var(--texto-suave);
  border-bottom: 1px dashed currentColor;
  cursor: help;
}

/* Definição de nota que ninguém citou (§49).

   O `.nota-ausente` acima é feito para uma MARCA no meio da frase: sublinhado
   tracejado sob duas ou três letras. Como parágrafo, esse mesmo tracejado
   atravessaria a coluna inteira e pareceria decoração. Aqui o aviso vem da
   barra à esquerda, e o texto volta a ser texto — porque é texto dele, e o
   objetivo é justamente ele não perdê-lo de vista. */
.notas-orfas {
  margin-top: 2rem;
}
.notas-orfas .nota-ausente {
  border-bottom: 0;
  cursor: auto;
  border-inline-start: 3px solid var(--borda-forte);
  padding: 0.5rem 0.75rem;
  margin: 0.75rem 0;
}
.notas-orfas .nota-ausente strong {
  /* A mesma pilha dos outros quatro lugares do arquivo: não existe token de
     fonte monoespaçada neste CSS, e inventar um aqui criaria uma quinta
     definição divergente em vez de resolver. */
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.9375rem;
}

/* MODO MARGEM — só quando existe espaço de sobra.
   `@container` e não `@media`: em media query, `rem` é resolvido contra a
   fonte PADRÃO do navegador e ignora a escala escolhida pelo usuário (ver
   seção 17). Aqui o que importa é justamente se a coluna JÁ ESCALADA cabe
   junto com a faixa da direita, então a comparação precisa acompanhar --fs. */
@container pagina (min-width: 58rem) {
  /* Só as páginas que têm nota reservam a faixa. Quem não usa o recurso não vê
     diferença nenhuma — daí o :has() em vez de uma classe posta pelo PHP. */
  main.envoltorio:has(.nota-margem) {
    max-width: calc(var(--largura) + var(--margem-nota) + var(--margem-vao));
  }

  /* O padding reserva a faixa DENTRO da caixa, e a margem negativa puxa a nota
     para dentro dela. Como a faixa é padding do próprio elemento, e o
     envoltório nunca passa de 100% da largura disponível, a nota não tem como
     sair da tela — que é o que aconteceria com margem negativa solta. */
  .conteudo:has(.nota-margem) {
    padding-right: calc(var(--margem-nota) + var(--margem-vao));
  }

  .conteudo:has(.nota-margem) .nota-margem {
    float: right;
    clear: right;
    width: var(--margem-nota);
    /* topo · direita NEGATIVA (puxa para dentro do padding) · baixo · esquerda */
    margin: 0.2rem calc(-1 * (var(--margem-nota) + var(--margem-vao))) 0.75rem 0;
    padding: 0;
    border-left: 0;
    background: none;
    border-radius: 0;
    font-size: 0.875rem;
    color: var(--texto-suave);
  }

  .conteudo:has(.nota-margem) .nota-margem__num { color: var(--acento); }
}

/* --- 23. Autocompletar de wikilinks no editor --------------------------- */

/* Lista das notas existentes ao digitar `[[`. Fica logo ABAIXO do campo, e não
   junto do cursor: um <textarea> não expõe a posição do cursor, e a gambiarra
   do "div espelho" para descobri-la é frágil — além de fazer a lista pular pela
   tela a cada tecla. Num lugar fixo ela é mais fácil de acompanhar. */
.autocompletar {
  list-style: none;
  margin: 0.25rem 0 0;
  padding: 0.25rem;
  border: 1px solid var(--borda-forte);
  border-radius: var(--raio);
  background: var(--bg);
  box-shadow: var(--sombra);
  max-height: 17rem;
  overflow-y: auto;
}

.autocompletar__item {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  min-height: 2.75rem;          /* alvo de toque ≥ 44px */
  padding: 0.35rem 0.6rem;
  border-radius: var(--raio);
  cursor: pointer;
}

/* O item destacado não se distingue só pela cor de fundo: leva também uma
   barra de acento à esquerda, pelo mesmo motivo do resto do projeto. */
.autocompletar__item.is-marcado {
  background: var(--bg-alt);
  box-shadow: inset 0.1875rem 0 0 var(--acento);
}

.autocompletar__titulo { flex: 1 1 auto; min-width: 0; }

.autocompletar__nova { color: var(--texto-suave); font-size: 0.875rem; }

.autocompletar__marca {
  flex: none;
  font-size: 0.75rem;
  color: var(--marca-privada);
  border: 1px solid currentColor;
  border-radius: var(--raio);
  padding: 0 0.35em;
}

kbd {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.85em;
  border: 1px solid var(--borda-forte);
  border-radius: 3px;
  padding: 0.05em 0.35em;
  background: var(--bg-alt);
}

/* --- 24. Barra e modo foco do editor ------------------------------------ */

.editor-barra {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.375rem;
  margin-bottom: 0.375rem;
}

/* Estado do alternador: fundo E barra de acento. A cor sozinha nunca carrega
   informação neste projeto. */
.editor-barra button[aria-pressed="true"] {
  background: var(--bg-alt);
  box-shadow: inset 0 -0.1875rem 0 var(--acento);
  font-weight: 600;
}

/* Salvar só existe no modo foco: fora dele, os botões do fim do formulário já
   fazem esse papel, e um terceiro só confundiria. */
.editor-barra__salvar { display: none; }
#area-edicao.is-foco .editor-barra__salvar { display: inline-flex; }

/* Fonte do campo: por padrão a mesma da leitura, para o que você escreve já
   parecer o que vai sair. O alternador troca para a monoespaçada do sistema —
   zero bytes, e a mesma que o app já usa nos blocos de código. */
#content {
  font-family: "Bitter", Georgia, "Times New Roman", serif;
}
#content.is-mono {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}

/* MODO FOCO — por CSS, não pela API de tela cheia do navegador.
   Em tela cheia nativa só o elemento em tela cheia é desenhado, então tudo que
   estivesse fora dele — a lista do [[, os botões — sumiria. Por CSS eu escolho
   o que entra, e funciona igual em todo lugar, sem depender de permissão. */
#area-edicao.is-foco {
  position: fixed;
  inset: 0;
  z-index: 100;
  margin: 0;
  padding: 1rem;
  background: var(--bg);
  display: flex;
  flex-direction: column;
  align-items: center;      /* centraliza a coluna de escrita */
  gap: 0.375rem;
  overflow: auto;

  /*
   * Largura da linha no modo foco: ~70 caracteres.
   *
   * MEDIDO no Firefox, com a Bitter provadamente carregada (comparada com
   * Georgia na mesma string): 70 caracteres de prosa em português ocupam
   * 573,5px a 18px, ou seja 31,86rem. Daí os 32rem.
   *
   * A monoespaçada é MUITO mais larga: os mesmos 70 caracteres dão 42,13rem.
   * Uma medida só para as duas fontes deixaria uma das duas errada — na Bitter,
   * `70ch` (a largura do "0", que é bem mais larga que a letra média) daria
   * 99 caracteres por linha.
   *
   * Em rem, então acompanha a escala de fonte: aumentar o texto alarga a
   * coluna na mesma proporção e a contagem de caracteres não muda.
   *
   * O `+ 1.25rem + 2px` é o padding lateral do campo (0.625rem de cada lado)
   * mais a borda. Sem ele a conta some 3 caracteres: `max-width` mede a caixa
   * inteira, não o texto — medido, dava 67 em vez de 70.
   */
  --medida-foco: calc(32rem + 1.25rem + 2px);
}

/* Com a mono ligada, a coluna inteira acompanha — inclusive a barra e a lista
   do [[, senão elas ficariam mais estreitas que o campo.

   Aqui vai o valor MEDIDO em rem, e não `70ch`: `ch` resolve na fonte do
   elemento, e este contêiner não é monoespaçado — `70ch` aqui daria a largura
   de 70 zeros da fonte da interface, que é outra coisa. A consequência é que
   a barra e o campo podem diferir alguns pixels (2,3px medidos a 175% de
   escala), porque um usa a medida em rem e o outro o `ch` exato. Abaixo da
   percepção, e o preço de manter o campo exato — que é o que importa. */
#area-edicao.is-foco:has(#content.is-mono) {
  --medida-foco: calc(42rem + 1.25rem + 2px);
}

#area-edicao.is-foco > * {
  width: 100%;
  max-width: var(--medida-foco);
}

/* No campo mono a medida é exata, e não aproximada: em fonte monoespaçada 1ch
   É um caractere. Também se ajusta sozinha à mono que cada sistema escolher,
   que não é a mesma no Linux, no Mac e no Windows. */
#area-edicao.is-foco #content.is-mono { max-width: calc(70ch + 1.25rem + 2px); }

#area-edicao.is-foco > label { flex: none; }
#area-edicao.is-foco .editor-barra { flex: none; margin-bottom: 0; }

/* O campo toma o espaço que sobra. min-height: 0 é obrigatório: sem ele, um
   item flex não encolhe abaixo do próprio conteúdo e o campo estoura a tela. */
#area-edicao.is-foco #content {
  flex: 1 1 auto;
  min-height: 0;
  resize: none;

  /* Reserva o espaço da barra de rolagem desde o início. Sem isto, no momento
     em que o texto passa da altura da tela a barra aparece, o campo perde ~12px
     e TODAS as linhas se requebram — o texto se mexe embaixo do cursor. Custa
     um caractere de largura e paga com a linha nunca mudando enquanto se
     escreve. */
  scrollbar-gutter: stable;
}

#area-edicao.is-foco .autocompletar { flex: none; max-height: 12rem; }

/* A ajuda sai no foco: o objetivo do modo é justamente ficar só com o texto. */
#area-edicao.is-foco .campo__ajuda { display: none; }

/* --- 25. Nota em inglês: sem hifenização -------------------------------- */

/* Até §36 este bloco era `hyphens: none`: o idioma do documento era pt-BR e
   silabar inglês por padrão português daria corte errado. Com `lang="en"`
   declarado, o navegador passou a ter os padrões CERTOS, e a pergunta virou
   tipográfica. Medido em 6 notas inglesas reais, 106 parágrafos:

                        sem hífen    auto      auto + limite
     linhas (desktop)      526        523          523
     linhas (celular)      989        974          977
     cortes com <3 letras   —          22            0     (desktop)
     cortes com <3 letras   —          49            0     (celular)
     escada máxima          —           4            2     (celular)
     folga média            8,5%       6,4%         6,9%   (celular)

   Duas conclusões que decidiram a regra:

   1. Hifenizar NÃO ganha espaço — 0,6% de linhas no desktop, 1,2% no celular.
      O que se ganha é margem direita menos irregular.
   2. O `auto` puro corta feio: `go|ing`, `un|der`, `re|vealed`, e chega a
      quatro linhas seguidas terminando em hífen no celular.

   Daí o limite: só palavra de 6+ letras, mínimo 3 de cada lado. Zera o corte
   curto nos dois tamanhos, derruba a escada para 2 e mantém ~80% do ganho de
   margem. O `hyphens: auto` vem herdado da seção 2, não se repete aqui.

   Onde `hyphenate-limit-chars` não existir (Firefox <121, Chrome <109,
   Safari <17), degrada para `auto` puro — pior, não quebrado. As linhas
   -webkit- cobrem o Safari antigo, que só tem before/after. */
[lang="en"] p,
[lang="en"] li,
[lang="en"] blockquote {
  hyphenate-limit-chars: 6 3 3;
  -webkit-hyphenate-limit-before: 3;
  -webkit-hyphenate-limit-after: 3;
}

/* --- 26. Estatísticas --------------------------------------------------- */

.numeros {
  list-style: none;
  padding: 0;
  margin: 0 0 1.5rem;
  display: grid;
  gap: 0.75rem;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 10rem), 1fr));
}

.numeros__item {
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  background: var(--bg-alt);
  padding: 0.75rem 0.875rem;
}

.numeros__valor { display: block; font-size: 1.75rem; font-weight: 700; line-height: 1.1; }
.numeros__rotulo { display: block; font-size: 0.8125rem; color: var(--texto-suave); }

/* Barras. Duas escalas diferentes em gráficos separados, e nunca sobrepostas:
   eixo duplo num desenho só é fácil de ler errado.
   O valor vai ESCRITO acima da barra — ler altura é impreciso para qualquer um,
   e mais ainda para quem enxerga pouco. */
.barras {
  list-style: none;
  padding: 0;
  margin: 0 0 1.5rem;
  display: flex;
  align-items: flex-end;
  justify-content: flex-start;
  gap: 0.375rem;
  overflow-x: auto;
  min-height: 11rem;
}

.barras__item {
  /* max-width importa no começo da vida do site: com um ano só, sem teto, a
     barra ocupava a largura inteira da tela e parecia um bloco, não um dado.
     Com muitos anos elas voltam a dividir o espaço. */
  flex: 1 1 2.5rem;
  min-width: 2.5rem;
  max-width: 5rem;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-end;
  height: 11rem;
}

.barras__valor { font-size: 0.75rem; color: var(--texto-suave); margin-bottom: 0.2rem; }

.barras__barra {
  width: 100%;
  background: var(--acento);
  border-radius: var(--raio) var(--raio) 0 0;
  min-height: 0.125rem;
}

/* Ano sem escrita: traço em vez de barra de altura zero, que sumiria e faria
   o ano parecer ausente do gráfico em vez de vazio. */
.barras__barra--zero {
  height: 0.125rem !important;
  background: var(--borda-forte);
  border-radius: 0;
}

.barras__rotulo {
  font-size: 0.75rem;
  margin-top: 0.3rem;
  border-top: 1px solid var(--borda);
  width: 100%;
  text-align: center;
  padding-top: 0.25rem;
}

/* Mapa de escrita. É DECORAÇÃO: o dado real está na tabela por mês, sempre
   presente logo abaixo — mesma decisão do grafo, que tem alternativa textual
   permanente. Cor sozinha nunca carrega informação neste projeto.

   Grade de colunas semanais: 7 linhas (domingo a sábado) e o fluxo por coluna. */
.mapa {
  display: grid;
  grid-template-rows: repeat(7, 0.75rem);
  grid-auto-flow: column;
  grid-auto-columns: 0.75rem;
  gap: 0.1875rem;
  overflow-x: auto;
  padding-bottom: 0.5rem;
  margin-bottom: 0.5rem;
}

/* A distinção "escrevi" x "não escrevi" é ESTRUTURAL, não cromática: dia vazio
   é contorno tracejado sem preenchimento, dia com escrita é bloco sólido. Cor
   sozinha não daria conta — no tema claro, o nível 1 fica a 1,63:1 do vazio, e
   quem tem sensibilidade ao contraste reduzida não veria a diferença.
   É a mesma regra do cadeado, do wikilink ausente e do item destacado. */
.mapa__dia {
  border-radius: 2px;
  background: transparent;
  border: 1px dashed var(--borda-forte);
}

/* Os quatro níveis usam LUMINOSIDADE bem separada, não matizes próximos:
   diferença de tom é o primeiro sinal a sumir com sensibilidade ao contraste
   reduzida. O nível 0 leva borda para não sumir contra o fundo. */
.mapa__dia--1,
.mapa__dia--2,
.mapa__dia--3,
.mapa__dia--4 { border-style: solid; border-color: transparent; }
.mapa__dia--1 { background: var(--mapa-1); }
.mapa__dia--2 { background: var(--mapa-2); }
.mapa__dia--3 { background: var(--mapa-3); }
.mapa__dia--4 { background: var(--mapa-4); }

.mapa__legenda { display: flex; align-items: center; gap: 0.25rem; }
.mapa__legenda .mapa__dia { display: inline-block; width: 0.75rem; height: 0.75rem; }

/* Uma grade por ano. Dia futuro fica mais apagado que dia vazio: "ainda não
   aconteceu" não é a mesma coisa que "não escrevi". */
.mapa__ano { margin: 1.25rem 0 0.4rem; font-size: 1.0625rem; }
.mapa__ano span { font-weight: 400; margin-left: 0.5rem; }
.mapa__dia--futuro { border-style: dotted; opacity: 0.45; }

/* Sinopse do livro. Um pouco menor que o corpo de uma nota: é metadado do
   livro, não texto do autor — a diferença de tamanho diz isso sem precisar de
   rótulo. */
.livro__descricao {
  font-size: 1rem;
  margin-top: 0.75rem;
  padding-left: 0.875rem;
  border-left: 0.1875rem solid var(--borda);
}
.livro__descricao > :last-child { margin-bottom: 0; }

/* --- 28. Índice de feeds ------------------------------------------------ */

.feeds { list-style: none; padding: 0; margin: 2rem 0 0; }

.feeds__item {
  padding-block: 1.25rem;
  border-top: 1px solid var(--borda);
}

.feeds__nome { font-size: 1.125rem; margin: 0 0 0.25rem; }
.feeds__texto { margin: 0 0 0.5rem; color: var(--texto-suave); }

/* O endereço é para copiar, então quebra em vez de estourar a linha no
   celular — e `user-select: all` faz um clique selecionar tudo. */
.feeds__endereco code {
  display: inline-block;
  max-width: 100%;
  overflow-wrap: anywhere;
  user-select: all;
}

.feeds__acoes { margin: 0.5rem 0 0; font-size: 0.9375rem; }
.feeds__sep { color: var(--texto-suave); margin-inline: 0.4rem; }

.feeds__explicacao {
  margin-top: 3rem;
  padding-top: 1.5rem;
  border-top: 1px solid var(--borda);
}

/* --- 29. Miudezas ------------------------------------------------------- */

/*
 * Cartões de pensamento curto.
 *
 * GRADE, e não colunas CSS: colunas encaixam sem sobra, mas a leitura desce a
 * coluna 1 inteira e volta ao topo para a coluna 2 — e numa página datada a
 * data salta para trás no meio da tela. A grade lê como texto, da esquerda
 * para a direita.
 *
 * A altura mínima igual é o que deixa os cartões quadrados; a sobra embaixo do
 * texto curto é intencional, é ela que dá o ar de recorte.
 */
.miudezas {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(17rem, 1fr));
  gap: 1.5rem;
  list-style: none;
  padding: 0;
  margin: 2rem 0 0;
}

.miudeza {
  display: flex;
  flex-direction: column;
  min-height: 13rem;
  padding: 1.75rem 1.5rem 1.25rem;
  border: 1px solid var(--borda-forte);
  background: var(--bg);
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.9375rem;
  line-height: 1.6;
}

/* Alternar o fundo separa um cartão do vizinho sem precisar de sombra. */
.miudeza:nth-child(even) { background: var(--bg-alt); }

.miudeza__texto > :first-child { margin-top: 0; }
.miudeza__texto > :last-child { margin-bottom: 0; }

.miudeza__data {
  margin-top: auto;           /* empurra a data para o rodapé do cartão */
  padding-top: 1.5rem;
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--texto-suave);
}

/*
 * A inclinação é o que dá o ar de papel colado. Ângulo abaixo de 2° de
 * propósito: texto torto custa mais a ler para quem já tem dificuldade, e o
 * leitor principal daqui é você. Cicla de quatro em quatro para o padrão não
 * ficar óbvio numa grade de duas ou três colunas.
 */
.miudeza:nth-child(4n+1) { transform: rotate(-1.6deg); }
.miudeza:nth-child(4n+2) { transform: rotate(1.1deg); }
.miudeza:nth-child(4n+3) { transform: rotate(0.7deg); }
.miudeza:nth-child(4n)   { transform: rotate(-0.9deg); }

/* Numa coluna só, um atrás do outro, a inclinação vira desalinho e cansa.
   O cartão fica reto — o desenho some, o conteúdo não. */
@media (max-width: 30rem) {
  .miudeza { transform: none; min-height: 0; }
}

/* Na home é UM cartão só: sem a grade de várias colunas ele ocuparia a linha
   inteira e pareceria uma caixa de aviso, não um recorte. */
.miudezas--uma { grid-template-columns: minmax(0, 26rem); margin-top: 1rem; }
.home-miudeza { margin-bottom: 2.5rem; }

/* Livro decorativo antes do título, na lista de leituras ligadas. Um respiro
   à direita e a cor suave: ele acompanha o link sem competir com ele. */
.icone--livro {
  margin-right: 0.4rem;
  color: var(--texto-suave);
}

/* Estado do auto-salvamento, na barra do editor.
 *
 * Discreto, mas presente: rede que não se vê é rede em que não se confia. Ele
 * perdeu três textos e precisa VER que agora há um guardado.
 *
 * Sem cor própria no estado normal — herda `--texto-suave`, que já passa no
 * auditor. O erro usa `--perigo`, a mesma dos outros avisos do app, então não
 * entra cor nova na paleta.
 */
.rascunho-estado {
  font-size: 0.875rem;
  color: var(--texto-suave);
  align-self: center;
  margin-left: auto;          /* empurra para a ponta oposta dos botões */
}
.rascunho-estado--erro {
  color: var(--perigo);
  font-weight: 600;
}
#area-edicao.is-foco .rascunho-estado { margin-left: 0; }

/* =========================================================================
   VÍDEO EMBEDADO (§53)

   O bloco tem duas camadas: a CAPA, que é imagem servida pelo próprio Mojibake,
   e o IFRAME, que só existe depois do clique. Enquanto o leitor não clicar,
   nada aqui pede um byte ao Google — é a razão de o recurso ter esta forma e
   não um `<iframe>` direto (ver src/Videos.php).

   AS CORES DO SELO DE PLAY NÃO SÃO TOKENS DE TEMA, e é a única parte do CSS
   onde isso está certo: ele fica sobre uma FOTOGRAFIA, não sobre o fundo da
   página. Um `var(--texto)` ali teria contraste garantido contra `--bg` e
   nenhum contra os pixels que estão de fato atrás dele — uma capa clara comeria
   o selo do tema claro. Preto e branco puros são o único par que se sustenta
   sobre qualquer imagem, nos quatro temas.
   ========================================================================= */

.video {
  margin: 1.5rem 0;
}

/* O gatilho é um <a> de verdade: sem JavaScript ele leva ao YouTube, com
   JavaScript o clique é interceptado e o vídeo toca aqui (ver app.js). */
.video__gatilho {
  position: relative;
  display: block;
  aspect-ratio: 16 / 9;
  overflow: hidden;
  background: var(--bg-alt);
  border: 1px solid var(--borda);
  border-radius: 2px;

  /* Sem sublinhado nem borda de link: aqui o link é a imagem inteira. */
  text-decoration: none;
  border-bottom: 1px solid var(--borda);
}

/* Shorts são filmados em pé. Forçá-los em 16/9 encheria a tela de tarja preta
   dos dois lados; o teto de largura impede que a moldura em pé domine a coluna. */
.video--vertical .video__gatilho {
  aspect-ratio: 9 / 16;
  max-width: 20rem;
  margin-inline: auto;
}

/* `cover` de propósito: a capa nem sempre vem em 16/9 — quando o vídeo não tem
   `maxresdefault`, o YouTube entrega uma versão 4:3 com tarjas pretas embutidas
   na própria imagem. O corte come justamente as tarjas. */
.video__capa {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Sem capa em disco (YouTube fora do ar na hora de salvar): a moldura fica,
   agora como cartão de link, e o selo de play continua sendo o alvo. */
.video--sem-capa .video__gatilho {
  background:
    repeating-linear-gradient(135deg,
      var(--bg-alt) 0, var(--bg-alt) 8px,
      var(--bg-code) 8px, var(--bg-code) 16px);
}

/* O selo. 4rem de lado — bem acima do mínimo de 2.75rem de alvo de toque, e
   grande o suficiente para ser achado sem procurar. */
.video__play {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);

  width: 4rem;
  height: 4rem;
  border-radius: 50%;

  background: #000;
  border: 2px solid #fff;

  /* Sombra dupla: o anel branco garante a separação da foto, e a sombra escura
     dá a segunda aresta para quem enxerga o branco esmaecido sobre um céu claro. */
  box-shadow: 0 0 0 1px rgba(0, 0, 0, .55), 0 2px 8px rgba(0, 0, 0, .45);
}

/* O triângulo, em borda de CSS: uma forma sólida, sem arquivo para baixar e sem
   fonte de ícone que possa não carregar. */
.video__play::before {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-40%, -50%);   /* -40%: o centro ÓPTICO do triângulo */

  border-style: solid;
  border-width: 0.75rem 0 0.75rem 1.25rem;
  border-color: transparent transparent transparent #fff;
}

/* Hover e foco mudam o selo, nunca a existência dele: nenhuma função aqui
   depende de o ponteiro passar por cima. */
.video__gatilho:hover .video__play,
.video__gatilho:focus-visible .video__play {
  background: var(--foco);
  border-color: #fff;
}

/* O rodapé do bloco tem duas partes, e elas são coisas diferentes: a LEGENDA
   é o que ele escreveu sobre o vídeo, a FONTE é de onde o vídeo veio. A ordem
   põe a legenda encostada no vídeo, que é onde ela pertence. */
.video__rodape {
  display: block;
  margin-top: 0.5rem;
  font-size: 0.9375rem;
  line-height: 1.45;
  text-wrap: pretty;
}

/* Igual à legenda de foto (§47), e de propósito: uma convenção só para "isto é
   uma legenda". O itálico vem daqui, e não de um <em> no HTML — legenda não é
   ênfase, e leitor de tela não deve anunciá-la como tal. */
.video__legenda {
  display: block;
  font-style: italic;
  color: var(--texto-suave);
  text-align: center;
}

/* A procedência existe para o vídeo se anunciar POR ESCRITO: uma miniatura diz
   muito menos que o título, e não diz nada para quem não a enxerga bem. */
.video__fonte {
  display: block;
  color: var(--texto-suave);
  margin-top: 0.25rem;
}

.video__legenda + .video__fonte {
  /* Com legenda acima, a fonte recua um degrau: são duas vozes, e sem esta
     separação a legenda dele parece continuar no título do vídeo. */
  margin-top: 0.4rem;
  font-size: 0.875rem;
}

.video__titulo {
  color: var(--texto);
  font-weight: 600;
}

.video__fora {
  white-space: nowrap;
}

/* A seta de "abre fora daqui". Um pouco menor que a letra e com um respiro
   antes: no tamanho cheio ela competia com a palavra em vez de acompanhá-la.
   Herda currentColor, então segue o link nos quatro temas — que é justamente o
   que o emoji `↗` não fazia. */
.icone--fora {
  width: 0.8em;
  height: 0.8em;
  margin-left: 0.25em;
  /* O -0.125em do `.icone` foi calibrado para ícone de 1em; num de 0.8em ele
     joga a seta abaixo da linha e ela desgruda da palavra. Medido lado a lado
     em quatro variantes: com -0.05em a seta ocupa a faixa entre a altura-x e o
     topo das maiúsculas, que é onde ela lê como parte do texto. */
  vertical-align: -0.05em;
}

/* Depois do clique: o iframe ocupa exatamente a moldura que a capa ocupava, e
   por isso a página não dá um salto na hora de tocar. */
.video__quadro {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
  border: 1px solid var(--borda);
  border-radius: 2px;
  background: #000;
}

.video--vertical .video__quadro {
  aspect-ratio: 9 / 16;
  max-width: 20rem;
  margin-inline: auto;
}

/* --- Painel de custo (§61) ---------------------------------------------- */

/* O total vem antes de tudo: é o número que se veio buscar. Fundo alternativo
   para separá-lo da leitura sem precisar de borda nem de tamanho maior ainda. */
.custo-topo {
  background: var(--bg-alt);
  border: 1px solid var(--borda);
  border-radius: 6px;
  padding: 1.2rem 1.4rem;
  margin: 1.5rem 0;
}
.custo-cifra {
  margin: 0;
  font-size: 2.1rem;
  font-weight: 600;
  line-height: 1.1;
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
}
.custo-cifra__unidade {
  font-size: 1rem;
  font-weight: 400;
  color: var(--texto-suave);
  letter-spacing: 0;
}

/* Segunda representação do mesmo número, que já está em texto na coluna ao
   lado — como a barra de progresso de leitura. Trilho com borda sólida para
   ela existir também em alto contraste e no modo de contraste forçado. */
.custo-barra {
  display: block;
  width: 100%;
  min-width: 4rem;
  height: 0.55rem;
  border: 1px solid var(--borda);
  border-radius: 999px;
  overflow: hidden;
}
.custo-barra > span {
  display: block;
  height: 100%;
  background: var(--link);
}

/* --- Seções da home, uma por eixo do quadrante (§64) --------------------- */

/* Espaço generoso ENTRE as seções e curto dentro delas: é o que faz "Jardim
   digital" e "Blog" lerem como dois blocos, e não como uma lista com títulos
   no meio. Sem isso a divisão que a mudança existe para mostrar some. */
.home-secao { margin-top: 3rem; }
.home-secao > h2 { margin-bottom: 0.15rem; }

/* O subtítulo diz em que ordem a lista está — o jardim por quando foi cuidado,
   o blog por quando foi escrito. Colado no título, como legenda dele. */
.home-secao__sub {
  margin-top: 0;
  margin-bottom: 1.25rem;
  font-size: 0.9rem;
}

.home-secao__ir { margin-top: 1.25rem; }

/* A contagem dentro do botão não muda de cor no hover junto com o resto: ela é
   informação, não parte do rótulo da ação. */
.home-secao__ir .botao .pequeno { margin-left: 0.35rem; }

/* O arquivo cronológico fecha a home, separado por uma régua fina — ele não é
   uma terceira seção, é uma saída. */
.home-arquivo {
  margin-top: 2.5rem;
  padding-top: 1.25rem;
  border-top: 1px solid var(--borda);
}
