/* jarvis-wiki — folha de estilo pública.
   Única fonte de cor: o bloco :root abaixo. Nenhuma cor literal fora dele
   (regra global do projeto). O laranja da marca (`--marca-laranja`,
   `--linha`, `--linha-forte`) entra SÓ como aresta — borda, divisória,
   separador — nunca em texto, link, item ativo ou botão: essas ficam no
   violeta (`--cor-primaria`). Se o laranja vazar pra conteúdo, as duas
   cores passam a disputar "o que é importante aqui" na página. */

:root {
  color-scheme: dark;

  /* Marca (extraída da logo do servidor) */
  --cor-primaria: #d08be5;
  --cor-primaria-forte: #c27bd0;
  --marca-1: #d08be5;
  --marca-2: #d887d1;
  --marca-3: #d55f8f;
  --marca-4: #d4516a;
  --marca-laranja: #fea610;
  --linha: rgba(198, 106, 13, .22);
  --linha-forte: rgba(198, 106, 13, .40);

  /* Superfícies e texto */
  --cor-fundo: #14161f;
  --cor-elev: #1b1e2b;
  --cor-elev-2: #23273a;
  --cor-texto: #eceef4;
  --cor-sub: #a2a7bd;

  /* Semânticas (caixas, banner de anúncio) */
  --cor-info: #7aa2ff;
  --cor-sucesso: #3dd68c;
  --cor-aviso: #f5c451;
  --cor-perigo: #e5484d;

  /* Cor inline `{nome:texto}` do markdown — mesmos hex do §5 da spec */
  --c-roxo: #c27bd0;
  --c-lilas: #d08be5;
  --c-purpura: #d887d1;
  --c-rosa: #d55f8f;
  --c-coral: #d4516a;
  --c-vermelho: #e5484d;
  --c-verde: #3dd68c;
  --c-amarelo: #f5c451;
  --c-cinza: #a2a7bd;

  --raio: 10px;
  --raio-pequeno: 6px;
  --altura-header: 64px;
  --largura-sidebar: 288px;
  --largura-outline: 240px;
  --largura-conteudo: 768px;
  --largura-conteudo-larga: 1152px;
  --sombra: 0 8px 24px rgba(0, 0, 0, .35);
}

/* ===== Reset mínimo ===== */

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

html { -webkit-text-size-adjust: 100%; }

/* O layout é montado com ÁREAS NOMEADAS, nunca com número de linha.
   Motivo concreto: dois filhos do <body> são opcionais — o banner de anúncio
   (só existe quando há aviso no config) e a coluna "Nesta página" (some em
   página sem heading). Com `grid-row: 2 / 3` escrito à mão, a chegada do
   banner empurrava tudo uma linha e o cabeçalho — que ficava com linha
   automática — era jogado para uma linha implícita DEPOIS do conteúdo, isto
   é, renderizava no pé da página. Com área nomeada não existe número para
   desalinhar: cada elemento pede o nome do lugar dele. E a linha `auto` do
   banner colapsa sozinha para 0 quando o banner não é emitido, sem `:has()`
   e sem classe condicional no <body>. */
body {
  margin: 0;
  background: var(--cor-fundo);
  color: var(--cor-texto);
  font: 16px/1.65 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  display: grid;
  grid-template-columns: var(--largura-sidebar) 1fr var(--largura-outline);
  grid-template-rows: auto var(--altura-header) 1fr auto;
  grid-template-areas:
    "banner  banner    banner"
    "topo    topo      topo"
    "indice  conteudo  outline"
    "rodape  rodape    rodape";
  min-height: 100vh;
}

/* Página sem heading (e também a 404 e a /recent): duas colunas. Redefinir só
   as colunas não bastaria — as ÁREAS também têm que perder a coluna da
   direita, senão sobra um nome de área apontando para uma coluna que não
   existe mais. */
body.sem-outline {
  grid-template-columns: var(--largura-sidebar) 1fr;
  grid-template-areas:
    "banner  banner"
    "topo    topo"
    "indice  conteudo"
    "rodape  rodape";
}

img { max-width: 100%; }

a { color: var(--cor-primaria); text-decoration: none; }
a:hover { color: var(--cor-primaria-forte); text-decoration: underline; }
a:focus-visible, button:focus-visible, input:focus-visible, summary:focus-visible {
  outline: 2px solid var(--cor-primaria);
  outline-offset: 2px;
}

button {
  font: inherit;
  color: var(--cor-texto);
  background: var(--cor-elev);
  border: 1px solid var(--linha);
  border-radius: var(--raio-pequeno);
  cursor: pointer;
}

hr { border: 0; border-top: 1px solid var(--linha-forte); margin: 2rem 0; }

/* Checkboxes de gaveta (menu mobile / outline mobile) — sem JS. Ficam antes
   dos elementos que controlam na ordem do documento (ver lib/views.mjs), o
   que os combinadores `~` abaixo exigem. */
.alterna-drawer {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
}

/* ===== Cabeçalho ===== */

.cabecalho {
  grid-area: topo;
  position: sticky;
  top: 0;
  z-index: 20;
  display: flex;
  align-items: center;
  gap: 1rem;
  height: var(--altura-header);
  padding: 0 1.25rem;
  background: var(--cor-fundo);
  border-bottom: 1px solid var(--linha-forte);
  /* Item de grid tem mínimo AUTOMÁTICO: sem isto o cabeçalho se recusa a
     ficar menor que o próprio conteúdo e ESTOURA a coluna em vez de encolher
     o que está dentro — e quem rola horizontalmente é a página inteira, não
     ele. Medido a 320px com um `MARCA` longo: cabeçalho 376,1px numa tela de
     320, com rolagem horizontal; com `min-width: 0` ele volta a 320 e o nome
     é cortado pela reticência, que é o que se quer. */
  min-width: 0;
}

.cabecalho .marca {
  display: flex;
  align-items: center;
  gap: .6rem;
  color: var(--cor-texto);
  font-weight: 600;
  white-space: nowrap;
  /* O nome vem do `MARCA` do .env, ou seja, é texto que o dono escolhe e
     pode ser longo. Com `white-space: nowrap` e sem estes dois, um nome
     grande empurra o cabeçalho além da tela e a PÁGINA INTEIRA ganha
     rolagem horizontal no celular — medido a 320px: "Servidor Brasileiro de
     Minecraft Wiki" levava a marca a 280px de largura terminando em x=356
     numa tela de 320. `min-width: 0` é o que destrava o encolhimento (item
     de flex não encolhe abaixo do conteúdo sem isso) e a reticência corta o
     que não couber. */
  min-width: 0;
}
.cabecalho .marca span {
  /* O `min-width: 0` tem que estar AQUI também: o span é item de flex da
     própria `.marca`, e item de flex não encolhe abaixo do conteúdo
     enquanto o mínimo automático valer — sem ele a reticência nunca chega a
     ser usada e o nome empurra do mesmo jeito. */
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
}
.cabecalho .marca:hover { color: var(--cor-texto); text-decoration: none; }
.cabecalho .marca img { border-radius: var(--raio-pequeno); }

.cabecalho .busca { flex: 1; max-width: 420px; }
.cabecalho .busca input {
  width: 100%;
  font: inherit;
  color: var(--cor-texto);
  background: var(--cor-elev);
  border: 1px solid var(--linha);
  border-radius: var(--raio);
  padding: .5rem .75rem;
}
.cabecalho .busca input::placeholder { color: var(--cor-sub); }

.botao-menu {
  display: none;
  align-items: center;
  justify-content: center;
  width: 2.25rem;
  height: 2.25rem;
  border-radius: var(--raio-pequeno);
  cursor: pointer;
}
.hamburguer,
.hamburguer::before,
.hamburguer::after {
  display: block;
  width: 1.25rem;
  height: 2px;
  background: var(--cor-texto);
  border-radius: 2px;
}
.hamburguer::before, .hamburguer::after { content: ""; position: relative; }
.hamburguer::before { top: -5px; }
.hamburguer::after { top: 3px; }

/* ===== Sidebar ("Índice") ===== */

/* Quem gruda é o <nav> DE DENTRO, não o <aside>. A divisória mora no aside e
   por isso acompanha a coluna inteira.

   Antes o próprio `.indice` era o bloco sticky, e para isso precisava de
   `align-self: start` — que faz o item de grid encolher até a altura do
   conteúdo dele. Com a wiki cheia isso não aparece (a sidebar bate no teto de
   `100vh - 64` e a linha fica contínua), mas com poucas páginas a divisória
   virava um toco: medido 227px de borda contra 1615px de coluna, ou seja 14%
   da altura, parando no meio do nada. E a wiki do dono nasce com poucas
   páginas — o caso feio é o caso inicial.

   Deixando o aside esticar (é o `stretch` padrão do grid, não precisa
   declarar) a borda volta a ter a coluna toda, e o sticky continua
   funcionando porque o bloco que contém o `nav` passa a ser um `.indice`
   alto: é justamente essa folga que o sticky precisa para ter por onde
   deslizar. O `top` casa com a altura do cabeçalho, que é quem ocupa a faixa
   de cima quando a página está rolada, e o `max-height` + `overflow-y` vão
   junto com o nav, senão um índice longo não teria como rolar.

   ⚠️ Não voltar `align-self: start` para cá: além do toco, ele vaza para a
   gaveta do celular (ver a media query no fim do arquivo). */
.indice {
  grid-area: indice;
  border-right: 1px solid var(--linha);
}

.indice > nav {
  position: sticky;
  top: var(--altura-header);
  max-height: calc(100vh - var(--altura-header));
  overflow-y: auto;
  padding: 1rem 0;
}

.grupo-indice { border-bottom: 1px solid var(--linha); }
.grupo-indice:last-child { border-bottom: 0; }

/* Recuo e raio aqui NÃO são cosmética: são a mesma correção do item do
   índice, aplicada ao controle que a rodada passada deixou de fora. O
   `.grupo-titulo` ia de ponta a ponta do `<nav>` (medido: 0..287 numa coluna
   de 287) e o anel de foco do teclado desta folha é `outline: 2px` com
   `outline-offset: 2px`, ou seja, pinta de -4 a 291. O `<nav>` tem
   `overflow-y: auto`, o que força `overflow-x: auto` junto, e tudo que passa
   da caixa é RECORTADO: o anel aparecia como dois traços horizontais soltos,
   sem lado esquerdo nem direito. Fotografado antes da correção.

   O padding encolhe exatamente o que a margem cresce — 8 + 12 = os mesmos
   20px de antes — então o rótulo não se move, e a seta (que é
   `margin-left: auto`) continua terminando em 267. A única coisa que muda na
   tela é o anel, que agora cabe inteiro e é arredondado como o resto. */
.grupo-titulo {
  margin: 0 .5rem;
  padding: .5rem .75rem;
  border-radius: var(--raio-pequeno);
  font-size: .75rem;
  font-weight: 700;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--cor-sub);
  cursor: pointer;
  list-style: none;
}
.grupo-titulo::-webkit-details-marker { display: none; }

.indice ul { list-style: none; margin: 0; padding: 0; }

/* Item do índice. O seletor tem DUAS metades de propósito: `li > a` é a página
   comum e `li > details > summary > a` é a página que TEM subpáginas — esse
   link mora dentro do <summary> e por isso `li > a` nunca o alcançou. Medido
   antes desta rodada: item comum cinza (--cor-sub) e item que abre galho
   VIOLETA (#d08be5, herdado da regra global de `a`), sem fundo no hover e sem
   a barra de ativo. Duas famílias de item na mesma lista, e a diferença não
   queria dizer nada.

   Recuo lateral e canto arredondado são pedido do dono ("achei os botões do
   canto lateral quadrados até demais"), e ele tem razão por medida, não por
   gosto: este era o ÚNICO bloco preenchido do site com raio ZERO — busca 10px,
   caixa colorida 10px, cartão anterior/próximo 10px, botão 6px, logo 6px — e
   ainda encostava na divisória do aside, então o realce lia como faixa de
   ponta a ponta e não como bloco próprio. O raio é o token que já existe
   (--raio-pequeno), de propósito: um quarto valor de raio quebraria o sistema
   em vez de completá-lo.

   O padding encolhe exatamente o que a margem cresce, então o texto NÃO se
   move: 8 (margem) + 3 (borda) + 16 (padding) = os mesmos 27px de antes.
   A barra violeta de 3px do ativo FICA — é ela que diz "você está aqui". */
.indice li > a,
.indice li > details > summary > a {
  display: block;
  margin: 0 .5rem;
  padding: .45rem 1rem;
  color: var(--cor-sub);
  border-left: 3px solid transparent;
  border-radius: var(--raio-pequeno);
}
.indice li > a:hover,
.indice li > details > summary > a:hover {
  color: var(--cor-texto);
  text-decoration: none;
  background: var(--cor-elev);
}
.indice li > a.ativo,
.indice li > details > summary > a.ativo {
  color: var(--cor-primaria);
  border-left-color: var(--cor-primaria);
  background: var(--cor-elev);
  font-weight: 600;
}

.indice details ul { padding-left: 1rem; }
.indice details summary {
  list-style: none;
  cursor: pointer;
}
.indice details summary::-webkit-details-marker { display: none; }

/* ===== Seta de "isto abre" na sidebar =====

   Medido: `.grupo-titulo` tinha `list-style: none`,
   `::-webkit-details-marker { display: none }` e `::before`/`::after` com
   content `none` — o marcador nativo foi escondido e NADA foi posto no lugar.
   "PRIMEIRO JOGADOR" se lia como rótulo de seção, não como controle. Só o
   `cursor: pointer` denunciava, e cursor não existe no celular, que é onde
   esta wiki mais vai ser lida.

   A seta é `::after`, e não markup: pseudo-elemento não entra na árvore de
   acessibilidade (é o que um `aria-hidden` compraria) e não custa um byte de
   HTML por grupo em toda página. Desenhada com DUAS BORDAS em `currentColor`
   — nada de SVG de fundo, porque a CSP deste site é `img-src 'self'` e um
   `data:` URI em background-image seria bloqueado sem erro visível.
   `margin-left: auto` empurra a seta para a direita do rótulo, que é onde o
   GitBook põe a dele. A rotação mora no bloco de prefers-reduced-motion. */
.grupo-titulo,
.indice li > details > summary {
  display: flex;
  align-items: center;
}
/* Mesmo conserto do `.grupo-titulo`, com uma diferença: este `<summary>` não
   é o bloco pintado — quem pinta é o `<a>` que mora dentro dele. Se a margem
   entrasse aqui e o link ficasse com a dele, o texto da página COM subpáginas
   andaria 8px para a direita e passaria a desalinhar das irmãs. Então a
   margem MUDA DE DONO: sai do link (só neste contexto) e vai para o summary.
   A conta fecha igual — o link começava em 16+8 e agora começa em 24+0 — e a
   faixa de 44px que abre o galho no dedo continua a mesma, porque o
   `max-width` do link é percentual da caixa do summary. */
.indice li > details > summary {
  margin: 0 .5rem;
  padding-right: .75rem;
  border-radius: var(--raio-pequeno);
}
.indice li > details > summary > a { margin-inline: 0; }
.grupo-titulo::after,
.indice li > details > summary::after {
  content: "";
  flex: none;
  width: .4rem;
  height: .4rem;
  margin-left: auto;
  border-right: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  transform: rotate(-45deg);
  opacity: .7;
}
details[open] > .grupo-titulo::after,
.indice li > details[open] > summary::after { transform: rotate(45deg); }

/* ===== Gaveta do grupo: animação de abrir/fechar =====

   Pedido do dono: "quando clica no 'primeiro jogador' aparecem os temas... que
   desse no seco sem uma animação de gaveta que o GitBook tem".

   CSS PURO, zero JavaScript. `<details>` não anima sozinho porque o conteúdo
   fechado é `display: none`, e `display` não transiciona. As duas saídas
   clássicas foram recusadas: o truque do grid `0fr -> 1fr` exige um elemento
   embrulhando o conteúdo (o `<details>` esconde o conteúdo sozinho, não há
   onde pendurar), e medir `scrollHeight` no JS traz código para uma coisa
   puramente decorativa e quebra quando o conteúdo muda.

   `::details-content` + `interpolate-size: allow-keywords` resolve sem nada
   disso, e DEGRADA PERFEITAMENTE: onde o navegador não conhece o
   pseudo-elemento a regra inteira é descartada e o grupo abre instantâneo,
   que é o comportamento de hoje. Conferido nesta máquina (Chrome 148):
   `selector(details::details-content)`, `interpolate-size: allow-keywords`,
   `calc-size(auto, size)` e `transition-behavior: allow-discrete` todos true.

   `content-visibility` precisa de `allow-discrete` senão o conteúdo some no
   primeiro frame do fechamento e a altura anima sobre o vazio.

   `overflow: hidden` recorta o que passa da altura animada — e recortaria
   junto o anel de foco do teclado do primeiro item da lista, que sobra 4px
   para cima (2px de traço + 2px de `outline-offset`). Por isso a <ul> ganha
   .25rem de respiro em cima e embaixo: o anel cabe dentro da caixa recortada.

   Duração curta de propósito: isto é navegação usada todo dia, não uma
   entrada de apresentação. O :::detalhes do CONTEÚDO fica de fora — lá dentro
   moram imagem, tabela e bloco de código, e o mesmo `overflow: hidden` teria
   que ser medido contra cada um deles; o pedido era sobre a sidebar. */
@media (prefers-reduced-motion: no-preference) {
  :root { interpolate-size: allow-keywords; }

  .indice details::details-content {
    block-size: 0;
    overflow: hidden;
    transition: block-size .22s ease, content-visibility .22s allow-discrete;
  }
  .indice details[open]::details-content { block-size: auto; }
  .indice details > ul { padding-block: .25rem; }

  .grupo-titulo::after,
  .indice li > details > summary::after { transition: transform .22s ease; }
}

/* ===== Conteúdo ===== */

.conteudo {
  grid-area: conteudo;
  min-width: 0;
  padding: 2rem 1.5rem 4rem;
  display: flex;
  justify-content: center;
}

.conteudo > article {
  width: 100%;
  max-width: var(--largura-conteudo);
}

body.larga .conteudo > article { max-width: var(--largura-conteudo-larga); }

.capa {
  display: block;
  width: 100%;
  aspect-ratio: 1990 / 480;
  object-fit: cover;
  border-radius: var(--raio);
  margin-bottom: 1.5rem;
}

.trilha {
  display: flex;
  align-items: center;
  gap: .75rem;
  margin-bottom: .75rem;
  color: var(--cor-sub);
  font-size: .875rem;
}
.trilha ol { display: flex; align-items: center; list-style: none; margin: 0; padding: 0; gap: .5rem; flex-wrap: wrap; }
.trilha li { display: flex; align-items: center; gap: .5rem; }
/* A trilha mora DENTRO de <article>, então o <ol> e os <li> dela pegavam
   `margin: 1rem 0` de `.conteudo article ol` e `.35rem 0` de
   `.conteudo article li` — regras escritas para lista de TEXTO CORRIDO. O
   `margin: 0` da linha de cima já dizia o contrário e PERDIA por
   especificidade (0,1,1 contra 0,1,2): a declaração estava escrita e não
   valia. Medido no celular, em página com grupo E página-pai: 32px de margem
   no <ol> mais 11,2px por linha de crumb, dando 150,4px de trilha para 96px
   de conteúdo. O espaçamento da trilha é o `margin-bottom: .75rem` dela, e é
   só esse. */
.conteudo .trilha ol,
.conteudo .trilha li { margin: 0; }
.trilha li.separador { color: var(--cor-sub); opacity: .6; }
.trilha a { color: var(--cor-sub); }
.trilha a:hover { color: var(--cor-primaria); }
/* O botão "Copiar" que ficava aqui SAIU (pedido do dono: "não é muito
   necessário um botão de copiar o título, tinha isso no GitBook e não tinha
   muita utilidade, só acabava ocupando um lugar"). Ele copiava o markdown
   inteiro da página, lido de um <template id="fonte-md"> embutido em TODA
   página — 10,9% do HTML da página de skills, 10,5% da home, e a fração cresce
   com o tamanho do texto porque o markdown viajava duplicado ao lado do HTML
   já renderizado. O template saiu junto; quem quer o markdown continua tendo a
   rota `.md`. O `.copiar` dos blocos de código FICA, esse tem uso real. */
.trilha .botao-outline {
  margin-left: auto;
  padding: .3rem .7rem;
  font-size: .8rem;
}
/* O rótulo que abre a gaveta "Nesta página" precisa se ler como controle, e
   sozinho no fim da trilha ele precisa disso ainda mais do que antes: era o
   glifo `§` solto, sem caixa nenhuma, e naquela época ele pelo menos tinha ao
   lado um botão escrito "Copiar", com borda e fundo, que dizia "esta ponta da
   linha é onde ficam os controles". Esse vizinho SAIU (ver o bloco acima), e
   um `§` sem caixa sobraria como sujeira tipográfica do texto. O conteúdo
   virou um ícone de lista (três traços, o primeiro mais longo) em SVG inline
   no HTML — ver lib/views.mjs — que herda a cor por `currentColor` e por isso
   acompanha qualquer tema.

   `display: none` continua sendo o estado normal: este controle só existe
   abaixo de 768px, onde a coluna "Nesta página" virou gaveta. Acima disso a
   coluna está na tela e um botão para abri-la não teria o que fazer. */
.botao-outline {
  display: none;
  align-items: center;
  justify-content: center;
  color: var(--cor-sub);
  background: var(--cor-elev);
  border: 1px solid var(--linha);
  border-radius: var(--raio-pequeno);
}
.botao-outline:hover { color: var(--cor-texto); }
.botao-outline svg { display: block; }

h1 {
  display: flex;
  align-items: baseline;
  gap: .5rem;
  margin: .5rem 0 0;
  font-size: 2rem;
  line-height: 1.25;
}
h1 .emoji:empty { display: none; }

.resposta { margin: .5rem 0 1.75rem; color: var(--cor-sub); font-size: 1.0625rem; }

.conteudo article h2,
.conteudo article h3,
.conteudo article h4 {
  scroll-margin-top: calc(var(--altura-header) + 1rem);
  line-height: 1.3;
}
.conteudo article h2 { margin: 2.5rem 0 1rem; font-size: 1.5rem; }
.conteudo article h3 { margin: 2rem 0 .75rem; font-size: 1.25rem; }
.conteudo article h4 { margin: 1.5rem 0 .5rem; font-size: 1.0625rem; }

.ancora { margin-left: .4rem; opacity: 0; text-decoration: none; color: var(--cor-sub); }
h2:hover .ancora, h3:hover .ancora, h4:hover .ancora, .ancora:focus-visible { opacity: 1; }

.conteudo article p { margin: 1rem 0; }
.conteudo article ul, .conteudo article ol { margin: 1rem 0; padding-left: 1.5rem; }
.conteudo article li { margin: .35rem 0; }
.conteudo article li input[type="checkbox"] { margin-right: .4rem; }

.conteudo article blockquote {
  margin: 1.25rem 0;
  padding: .25rem 1rem;
  border-left: 3px solid var(--linha-forte);
  color: var(--cor-sub);
}

.conteudo article code {
  background: var(--cor-elev);
  border-radius: 4px;
  padding: .15em .4em;
  font-size: .9em;
  font-family: ui-monospace, "Cascadia Code", Consolas, monospace;
}

/* ===== Tabela ===== */

.rolagem-tabela { overflow-x: auto; margin: 1.25rem 0; }
.rolagem-tabela table { width: 100%; border-collapse: collapse; }
.rolagem-tabela th, .rolagem-tabela td {
  padding: .55rem .75rem;
  border-bottom: 1px solid var(--linha);
  text-align: left;
}
/* Sem `position: sticky` no `thead th` de propósito. A regra existia e era
   código morto: o `overflow-x: auto` do wrapper faz o `overflow-y` computar
   para `auto`, então o wrapper — e não a página — vira o container de rolagem
   do `th`; como nada limita a altura dele, `scrollHeight === clientHeight`
   (medido duas vezes, em tabelas de tamanhos diferentes: 1844 = 1844 e
   408 = 408) e não há rolagem vertical nenhuma para o sticky atuar.
   Fazer o cabeçalho grudar de verdade exigiria `max-height` no wrapper, o que
   daria à tabela uma rolagem vertical própria dentro da página — decisão de
   design que o dono não pediu e que o próprio GitBook não faz. */
.rolagem-tabela thead th {
  border-bottom: 1px solid var(--linha-forte);
}

/* ===== Blocos de código ===== */

.codigo {
  margin: 1.25rem 0;
  border: 1px solid var(--linha);
  border-radius: var(--raio);
  overflow: hidden;
  background: var(--cor-elev);
  position: relative;
}
.codigo-titulo {
  margin: 0;
  padding: .5rem .9rem;
  font-size: .8125rem;
  color: var(--cor-sub);
  border-bottom: 1px solid var(--linha);
}
.codigo pre {
  margin: 0;
  padding: .9rem 1rem;
  overflow-x: auto;
}
.codigo code {
  background: none;
  padding: 0;
  font-size: .875rem;
  line-height: 1.6;
}
.codigo .line { display: block; }
.codigo-numerado code { counter-reset: linha; }
.codigo-numerado .line { counter-increment: linha; padding-left: 2.5rem; position: relative; }
.codigo-numerado .line::before {
  content: counter(linha);
  position: absolute;
  left: 0;
  width: 2rem;
  text-align: right;
  color: var(--cor-sub);
  opacity: .6;
}
.codigo .copiar {
  position: absolute;
  top: .4rem;
  right: .4rem;
  padding: .25rem .6rem;
  font-size: .75rem;
  opacity: 0;
}
.codigo:hover .copiar, .codigo .copiar:focus-visible { opacity: 1; }

/* ===== Caixas de destaque ===== */

.caixa {
  margin: 1.25rem 0;
  padding: .9rem 1.1rem;
  border-radius: var(--raio);
  border: 1px solid var(--linha);
  border-left-width: 3px;
}
.caixa-titulo { margin: 0 0 .35rem; font-weight: 700; }
.caixa-info { border-left-color: var(--cor-info); }
.caixa-sucesso { border-left-color: var(--cor-sucesso); }
.caixa-aviso { border-left-color: var(--cor-aviso); }
.caixa-perigo { border-left-color: var(--cor-perigo); }
/* "dica" não tem cor semântica própria na spec — usa o meio do gradiente da
   marca (--marca-2) pra ficar visualmente distinta de info/sucesso/aviso/
   perigo sem inventar hex fora do :root. */
.caixa-dica { border-left-color: var(--marca-2); }

/* ===== Detalhes (accordion do markdown) ===== */

.conteudo article details {
  margin: 1.25rem 0;
  padding: .75rem 1rem;
  border: 1px solid var(--linha);
  border-radius: var(--raio);
}
.conteudo article details summary {
  cursor: pointer;
  font-weight: 600;
}
.conteudo article details[open] summary { margin-bottom: .5rem; }

/* ===== Figura ===== */

.figura {
  margin: 1.5rem 0;
  text-align: center;
}
.figura img { border-radius: var(--raio); }
.figura figcaption { margin-top: .5rem; color: var(--cor-sub); font-size: .875rem; }
.figura-pequeno { max-width: 320px; margin-inline: auto; }
.figura-medio { max-width: 560px; margin-inline: auto; }
.figura-grande { max-width: 100%; }
.figura-cheio { max-width: none; }

/* ===== Cards ===== */

.cards {
  display: grid;
  gap: .9rem;
  margin: 1.25rem 0;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
}
.cards-grande { grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); }
.card {
  display: flex;
  flex-direction: column;
  gap: .35rem;
  padding: 1rem;
  border: 1px solid var(--linha);
  border-radius: var(--raio);
  background: var(--cor-elev);
  color: var(--cor-texto);
}
.card:hover { border-color: var(--linha-forte); text-decoration: none; }
.card-titulo { font-weight: 700; }
.card-desc { color: var(--cor-sub); font-size: .875rem; }

.erro-bloco { color: var(--cor-perigo); }

/* ===== Cores inline {nome:texto} ===== */

.c-roxo { color: var(--c-roxo); }
.c-lilas { color: var(--c-lilas); }
.c-purpura { color: var(--c-purpura); }
.c-rosa { color: var(--c-rosa); }
.c-coral { color: var(--c-coral); }
.c-vermelho { color: var(--c-vermelho); }
.c-verde { color: var(--c-verde); }
.c-amarelo { color: var(--c-amarelo); }
.c-cinza { color: var(--c-cinza); }

/* ===== Navegação anterior/próximo ===== */

.paginacao {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1rem;
  margin: 3rem 0 0;
  padding-top: 1.5rem;
  border-top: 1px solid var(--linha);
}
.paginacao a {
  display: flex;
  flex-direction: column;
  gap: .25rem;
  padding: .9rem 1rem;
  border: 1px solid var(--linha);
  border-radius: var(--raio);
  color: var(--cor-texto);
}
.paginacao a:hover { border-color: var(--cor-primaria); text-decoration: none; }
.nav-proximo { text-align: right; align-items: flex-end; }
.paginacao .rotulo { font-size: .75rem; color: var(--cor-sub); }
.paginacao .titulo { font-weight: 600; }

/* ===== "Nesta página" (outline) ===== */

.outline {
  grid-area: outline;
  align-self: start;
  position: sticky;
  top: var(--altura-header);
  max-height: calc(100vh - var(--altura-header));
  overflow-y: auto;
  padding: 2rem 1.25rem;
}
.outline-titulo {
  margin: 0 0 .75rem;
  font-size: .75rem;
  font-weight: 700;
  letter-spacing: .04em;
  color: var(--cor-sub);
}
.outline ul { list-style: none; margin: 0; padding: 0; border-left: 1px solid var(--linha); }
.outline li { margin: 0; }
/* Mesmo raio do índice (--raio-pequeno, o token que já existe). Aqui o link
   não tem fundo, então o canto só aparece no anel de foco do teclado — que é
   justamente onde ele importa: `outline` do Chrome acompanha o
   `border-radius`, e um anel quadrado ao redor de um sistema arredondado é a
   inconsistência que o dono apontou, só que na versão do teclado. */
.outline a {
  display: block;
  padding: .3rem .75rem;
  color: var(--cor-sub);
  font-size: .875rem;
  border-left: 2px solid transparent;
  border-radius: var(--raio-pequeno);
  margin-left: -1px;
}
.outline a:hover { color: var(--cor-texto); text-decoration: none; }
.outline a.ativo { color: var(--cor-primaria); border-left-color: var(--cor-primaria); }
.outline .nivel-3 a { padding-left: 1.5rem; }

/* ===== Rodapé do site ===== */

.rodape {
  grid-area: rodape;
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 1rem;
  padding: 1.5rem 1.25rem;
  border-top: 1px solid var(--linha-forte);
  color: var(--cor-sub);
  font-size: .875rem;
}
.rodape-links { display: flex; gap: 1.25rem; }
.rodape-links a {
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  color: var(--cor-sub);
}
.rodape-links a:hover { color: var(--cor-texto); text-decoration: none; }
.rodape-links img { display: block; }
.rodape-copy { margin: 0; }

/* ===== Banner de anúncio (site inteiro; classes .caixa-* reaproveitadas) ===== */

.banner-anuncio {
  grid-area: banner;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 1rem;
  margin: 0;
  border-radius: 0;
  border-left: 0;
  border-bottom: 3px solid var(--linha-forte);
}
.banner-anuncio .fechar { margin-left: .5rem; }

/* O X do banner some com ele via `banner.hidden = true` no wiki.js, e sem esta
   regra o clique não fazia NADA: o `display: flex` acima é regra de autor e
   ganha do `[hidden] { display: none }` da folha do navegador. Medido ao vivo
   antes do conserto — depois do clique, `hidden` virava true, `display`
   continuava flex, a altura continuava 33px e a linha do grid não colapsava;
   pior, a dispensa já ia gravada no localStorage, então o aviso ficava
   permanentemente infechável. Com `display: none` o elemento sai do fluxo e a
   linha `auto` da área `banner` colapsa para 0 sozinha. */
.banner-anuncio[hidden] { display: none; }

/* ===== 404 ===== */

.sugestoes-404 { list-style: none; padding: 0; }
.sugestoes-404 li { margin: .5rem 0; }

/* ===== /recent ===== */

.lista-recentes { list-style: none; padding: 0; }
.lista-recentes li { margin: .5rem 0; display: flex; gap: .5rem; align-items: baseline; }
.lista-recentes time { color: var(--cor-sub); font-size: .875rem; }

/* ===== Mobile (§6.6) ===== */

@media (max-width: 768px) {
  /* Uma coluna só. As ÁREAS precisam ser redefinidas junto com as colunas: se
     ficassem as três da versão larga, sobrariam colunas implícitas e o grid
     de celular quebraria. Aqui só entram quatro áreas — `indice` e `outline`
     viram gaveta `position: fixed`, saem do fluxo e não ocupam célula
     nenhuma. */
  body, body.sem-outline {
    grid-template-columns: 1fr;
    grid-template-areas:
      "banner"
      "topo"
      "conteudo"
      "rodape";
  }

  .botao-menu { display: flex; }
  /* `inline-flex` (e não `inline-block`) para o ícone ficar centrado na caixa
     quando ela cresce para 44x44 no bloco de ponteiro grosso lá embaixo. */
  .botao-outline { display: inline-flex; }

  /* `align-self: stretch` aqui NÃO é enfeite: as duas gavetas usam `inset`
     com topo E base fixados, e um elemento posicionado com os dois lados
     presos só estica até a base quando o alinhamento é `stretch`. É o padrão
     do grid, mas fica declarado de propósito: no dia em que alguém puser
     `align-self: start` na regra de desktop de novo (foi o que a versão
     anterior fazia para o sticky), a gaveta encolheria até a altura do
     conteúdo e um índice longo ficaria fora do alcance do dedo, abaixo da
     dobra, sem rolagem possível — ela é `position: fixed`. Já mordeu uma
     vez. */
  .indice {
    grid-area: auto;
    position: fixed;
    align-self: stretch;
    inset: var(--altura-header) auto 0 0;
    width: min(var(--largura-sidebar), calc(100% - 4.5rem));
    max-width: calc(100% - 4.5rem);
    background: var(--cor-fundo);
    box-shadow: var(--sombra);
    transform: translateX(-100%);
    z-index: 15;
  }
  #alterna-menu:checked ~ .indice { transform: translateX(0); }

  /* Veu clicavel: no celular, tocar no conteudo a direita fecha a gaveta.
     Antes so o hamburguer fechava, e o toque ainda podia navegar num link
     por baixo. Fica abaixo da gaveta (z-index 14 contra 15) e acima do
     conteudo, entao ele intercepta o toque em vez de deixar passar. */
  /* Especificidade acima do `.veu-indice { display: none }` de fora da media
     query, que aparece depois no arquivo — sem o id aqui, ele venceria por
     ordem e o veu nunca apareceria. */
  #alterna-menu ~ .veu-indice {
    display: block;
    position: fixed;
    inset: var(--altura-header) 0 0 0;
    z-index: 14;
    background: rgba(0, 0, 0, .45);
    opacity: 0;
    pointer-events: none;
    /* sem transicao: a folha proibe movimento fora de prefers-reduced-motion,
       e um veu que aparece na hora e igualmente bom */
  }
  #alterna-menu:checked ~ .veu-indice { opacity: 1; pointer-events: auto; }

  /* No celular a gaveta INTEIRA é a área de rolagem: o nav enche a altura
     dela e rola dentro. Sticky aqui não teria sentido — a gaveta é `fixed`,
     não acompanha a rolagem da página — e `max-height: 100vh - 64` seria o
     limite errado se a barra de endereço do celular mudar de altura. */
  .indice > nav {
    position: static;
    height: 100%;
    max-height: none;
    overflow-y: auto;
  }

  .outline {
    grid-area: auto;
    position: fixed;
    align-self: stretch;
    inset: var(--altura-header) 0 0 auto;
    top: var(--altura-header);
    width: min(var(--largura-outline), calc(100% - 4.5rem));
    max-width: calc(100% - 4.5rem);
    max-height: none;
    background: var(--cor-fundo);
    box-shadow: var(--sombra);
    transform: translateX(100%);
    z-index: 15;
  }
  #alterna-outline:checked ~ .outline { transform: translateX(0); }

  /* O deslizar das duas gavetas era a ÚNICA animação desta folha fora de
     `prefers-reduced-motion`, e é de longe a maior: 288px de painel entrando
     pela lateral, contra os 0,22s de altura do galho da sidebar que a rodada
     passada guardou com todo o cuidado. Quem liga "reduzir movimento" no
     aparelho ficava com o galho abrindo no seco e o painel inteiro voando —
     política de movimento contraditória dentro do mesmo arquivo. Sem a
     transição a gaveta aparece pronta, que é como ela já degrada. */
  @media (prefers-reduced-motion: no-preference) {
    .indice, .outline { transition: transform .2s ease; }
  }

  /* O campo de busca sai do cabeçalho do celular ENQUANTO não existe motor
     (ele só chega na Fase 4). Medido a 375px: o campo ocupava 215 de 375px,
     57% da barra — o maior elemento do cabeçalho da tela onde esta wiki mais
     vai ser lida — e a única coisa que ele consegue fazer é responder que
     não está ligado. Era o mesmo tipo de promessa vazia que esta rodada
     tirou do `Ctrl+K` no placeholder e das três saídas da 404.

     A DESIGN §6.6 pede hambúrguer + logo + BOTÃO DE LUPA aqui. A lupa não
     entra agora de propósito: um botão que abre um campo que só sabe dizer
     "ainda não está ligada" é a mesma promessa, uma batida de dedo mais
     fundo. Ela volta na Fase 4, junto com o motor que a torna verdadeira.
     No desktop o campo continua igual — lá ele não disputa espaço com nada.

     E o espaço que sobra devolve o NOME da wiki ao cabeçalho: ele estava
     escondido só porque a busca não deixava lugar. */
  .cabecalho .busca { display: none; }
  .conteudo { padding: 1.25rem 1rem 3rem; }
  .paginacao { grid-template-columns: 1fr; }
  .rodape { justify-content: center; text-align: center; }
}

/* ===== Alvo de toque com ponteiro impreciso =====

   A WCAG 2.2 tem DUAS réguas de tamanho de alvo, e elas não medem a mesma
   coisa: a 2.5.8 (nível AA) pede 24x24 e esta folha já cumpria em tudo; a
   2.5.5 (nível AAA) pede 44x44, que é também o mínimo recomendado por Apple
   e Google para o dedo. O que separa "confortável" de "ruim" aqui não é a
   LARGURA DA TELA e sim a PRECISÃO DO PONTEIRO — 28px é tranquilo com mouse
   e péssimo com polegar. Por isso o gatilho é `pointer: coarse`, e não mais
   uma `max-width`: a consulta de 768px que já existe neste arquivo deixa de
   fora o tablet grande e o celular em paisagem, que têm dedo e mais de 768px.
   Efeito colateral desejado: no desktop com mouse NADA aqui vale, e as
   medidas de lá continuam as de sempre.

   Duas técnicas, escolhidas caso a caso:
   1. crescer a caixa de verdade (padding / min-height) — previsível, e o que
      empurra o layout empurra para baixo, nunca por cima de vizinho;
   2. `::after` posicionado, quando crescer a caixa deslocaria o texto ao
      redor. É o caso da âncora "#", colada no fim do título: a área se
      estende só para o lado VAZIO (à direita e um pouco acima/abaixo), nunca
      por cima do texto do heading.

   Alvo grande DEMAIS, invadindo o vizinho, é pior que alvo pequeno: o toque
   cai no elemento errado e a pessoa não entende por quê. Por isso o critério
   aqui não é "44 em tudo", é "44 sem encostar em ninguém".

   FICAM DE FORA, de propósito:
   - `.alterna-drawer` (1x1): é o checkbox que guarda o estado da gaveta, não
     recebe toque nenhum — quem recebe é o `<label>`, que está na lista.
   - link no meio de parágrafo: é a EXCEÇÃO DE INLINE da própria 2.5.8 —
     alvo cujo tamanho é determinado pelo texto ao redor está isento. E com
     razão: esticar link dentro da frase quebra a entrelinha do texto
     corrido, que é o produto principal de uma wiki. */

@media (pointer: coarse) {
  /* --- Cabeçalho --- */

  /* Único link de "voltar ao início" do site. O `min-width` garante os 44
     de alvo mesmo quando só a logo de 32x32 aparece — o que acontece quando
     o nome é curto demais ou foi encolhido pela reticência. Na maioria dos
     casos o texto já passa de 44 de largura e só a altura muda. */
  .cabecalho .marca {
    justify-content: center;
    min-width: 2.75rem;
    min-height: 2.75rem;
  }

  /* O X do aviso, 25x30 — o segundo menor alvo da página, e o ÚNICO que não
     chega aos 44. Vale a medida, porque é geometria e não preguiça:

     a faixa encosta no topo da página, e o campo de busca do cabeçalho
     começa a 43,2px do topo (faixa 33,4 + a sobra de 9,8 que centra um campo
     de 44,4 num cabeçalho de 64). Ou seja: entre a borda de cima da tela e o
     primeiro vizinho existem 43,2px, e não 44. Qualquer área de 44 aqui ou
     some para fora da tela, em cima, ou entra por cima do campo de busca —
     que é exatamente o "toque cai no elemento errado" que se quer evitar.

     A saída óbvia seria engordar a faixa para 44. Foi medida e RECUSADA: a
     faixa empurra o cabeçalho para baixo, e as duas gavetas do celular são
     `fixed` com o topo preso em `--altura-header` (64px, constante). Com a
     faixa a 44 o cabeçalho passa a terminar em 108 e cobre 28 dos 44px do
     primeiro título de grupo do índice, deixando o centro dele intocável no
     topo da página. Esse desencontro entre "topo da gaveta" e "fim do
     cabeçalho" é defeito ANTIGO (com a faixa a 33 o cabeçalho já invadia 17
     daqueles pixels); a régua aqui é não piorá-lo por causa de 2px.

     Então: 44 de largura (de graça — a faixa é `flex` centrado, engordar um
     filho não muda a altura dela) por 42 de altura, que é o máximo que cabe
     sem encostar em ninguém. De 25x30 para 44x42.

     `align-self: stretch` cola o botão no topo da faixa, e o `top: -1px`
     cancela a borda de 1px que todo `button` desta folha tem — juntos fazem
     a área começar exatamente em y=0, sem nenhum número mágico.

     CORREÇÃO DESTA RODADA: a versão anterior declarava 42px de altura e os
     ~9px que sobravam da faixa foram tratados como "sobra vazia do
     cabeçalho". Medido de novo, não eram: a área ia de y=0,2 a y=41,7 com
     `z-index: 21`, a faixa termina em y=33,4 e o campo de busca começa em
     y=42,7. Sobrava 0,99px entre "dispensar o aviso PARA SEMPRE"
     (localStorage, sem desfazer) e "focar a busca" — menos de um pixel para
     separar duas ações que não se parecem em nada, no aparelho em que o dedo
     erra por milímetros. E um toque no cabeçalho, visualmente ABAIXO da
     faixa, apagava o aviso sem que nada ali parecesse clicável.

     Regra adotada: a área de toque de um controle não passa da superfície a
     que ele pertence. `inset: -1px 0` prende a área ao próprio botão (que já
     enche a altura da faixa por `align-self: stretch`), e o -1px continua
     cancelando a borda. A altura resultante é a da faixa, ~35px em vez de
     44 — a exceção medida e assumida desta folha, agora com o limite vindo
     da geometria e não de um número escolhido a dedo. O `z-index: 21` saiu
     junto: existia só para ganhar do cabeçalho naqueles 9px que não existem
     mais. */
  .banner-anuncio .fechar {
    position: relative;
    align-self: stretch;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 2.75rem;
  }
  .banner-anuncio .fechar::after {
    content: "";
    position: absolute;
    inset: -1px 0;
  }

  /* --- Trilha (breadcrumb + abrir sumário) --- */

  .trilha .botao-outline {
    min-width: 2.75rem;
    min-height: 2.75rem;
    padding: .3rem .9rem;
  }
  /* O crumb é linha de navegação, não link dentro de frase: dar altura a ele
     é o mesmo critério dos outros itens de navegação desta folha. */
  .trilha ol a {
    display: inline-flex;
    align-items: center;
    min-height: 2.75rem;
  }
  /* Em página com GRUPO E PÁGINA-PAI a <ol> quebra em mais de uma linha, e
     com `align-items: center` (o padrão da trilha) o botão do sumário ficava
     centrado contra ela: parava ENTRE duas linhas de crumb, alinhado com
     nenhuma. Medido: 108,6px de trilha viraram 150,4px, e o buraco no meio
     não era ocupado por nada. Encostar o botão no topo alinha ele com a
     PRIMEIRA linha do crumb, que é a linha que ele acompanha. */
  .trilha { align-items: flex-start; }

  /* --- Linhas de navegação (largura já é grande; falta altura) --- */

  .indice .grupo-titulo,
  .indice li > a,
  .indice li > details > summary,
  .indice li > details > summary > a,
  .outline a,
  .rodape-links a {
    display: flex;
    align-items: center;
    min-height: 2.75rem;
  }

  /* O <summary> do :::detalhes SAIU do grupo acima, e a altura dele vem de
     padding em vez de `display: flex`.

     Motivo, medido a 375px variando SÓ o ponteiro: um <summary> só pinta o
     marcador de disclosure (o triângulo "isto abre") quando é
     `display: list-item`; qualquer outro valor apaga o marcador. Com
     `pointer: fine` o display era `list-item` e o texto recuava 16,9px atrás
     do triângulo; com `pointer: coarse` virava `flex`, o recuo caía para 0px
     e o triângulo sumia. O accordion continuava abrindo — o que sumia era a
     PISTA de que dá para clicar, e sumia justamente no aparelho onde o
     `cursor: pointer` não serve de muleta. Diferente da sidebar, este
     summary nunca teve `list-style: none`: ele SEMPRE dependeu do marcador
     nativo, que é grátis, acompanha `currentColor` e troca de forma sozinho
     ao abrir.

     `display: list-item` fica declarado de propósito (é o valor padrão do
     <summary>): é o contrato, e uma edição futura que o troque por flex
     apaga o triângulo de novo sem erro nenhum. `.55rem` de padding em cima e
     embaixo sobre uma linha de 26,4px dá exatamente os 44. */
  .conteudo article details > summary {
    display: list-item;
    padding-block: .55rem;
    min-height: 2.75rem;
  }

  /* A página COM subpáginas tem o link dentro do `<summary>`: o link navega e
     o resto da linha abre/fecha o galho, e os dois precisam dos 44 lado a
     lado.

     O `flex: 0 0 auto` que estava aqui conseguia isso proibindo o link de
     encolher — e um link que não encolhe dentro de um summary de 271px
     simplesmente TRANSBORDA. Medido a 375x812 com uma página filha: o <a>
     media 612,7x44 dentro do summary de 271, e a gaveta ganhava rolagem
     horizontal (nav.scrollWidth 629 contra clientWidth 287). Limiar: 34
     caracteres sem emoji, 30 com emoji — "Configurações do sistema de clãs"
     já estoura. E como esta consulta é por PONTEIRO, alcançava também o
     tablet de 1024px, onde a sidebar é coluna fixa e não gaveta.

     Agora o link encolhe (o `flex` inicial, `0 1 auto`, mais `min-width: 0`
     para vencer a largura mínima automática de item flex) e quebra em duas
     linhas como já fazia no desktop. Quem garante os 44px do TOGGLE é o
     `max-width`: sobram sempre 2,75rem de summary fora do link, e é nessa
     faixa que mora a seta. Sem ele, um título longo encheria a linha inteira
     e o galho ficaria sem como abrir no dedo. */
  .indice li > details > summary > a {
    min-width: 0;
    max-width: calc(100% - 2.75rem);
  }

  /* --- Botão de copiar do bloco de código --- */

  /* O botão é revelado por `:hover` no desktop, e num aparelho de toque
     `hover` não existe (`(hover: none)` casa junto com `pointer: coarse`).
     Deixá-lo invisível E clicável é o pior dos dois mundos: ninguém vê o
     controle e ainda assim tropeça nele. Aqui ele fica visível. */
  .codigo .copiar {
    opacity: 1;
    top: .5rem;
  }
  /* A área vai num `::after` em vez de padding porque o botão flutua sobre o
     código: engordar a caixa taparia a primeira linha do bloco. A altura de
     toque vai de 30 a 44 sem cobrir mais nenhum caractere, e não há outro
     alvo dentro do bloco para encostar. O `top: .5rem` acima existe para a
     borda de cima da área não cair fora do `overflow: hidden` do `.codigo`,
     que recortaria o toque de volta para menos de 44.

     Altura DECLARADA (44) em vez de `inset: -7px 0`: o bloco de contenção do
     `::after` é a caixa de PADDING do botão, que já desconta 1px de borda de
     cada lado — medido, `inset: -7px` dava 41,8 e não 44. Declarar a altura
     e centrar com `margin-top` não depende de borda nenhuma. */
  .codigo .copiar::after {
    content: "";
    position: absolute;
    top: 50%;
    left: 0;
    right: 0;
    height: 2.75rem;
    margin-top: -1.375rem;
  }

  /* --- Âncora "#" do título --- */

  /* Era o pior alvo da página: 14x32 no h2, 10x22 no h4. E, como só aparecia
     no `:hover`, num celular ela era invisível E clicável ao mesmo tempo —
     dar 44x44 a um alvo invisível só aumentaria a armadilha. Então aqui ela
     PASSA A APARECER (apagada, na cor secundária) e só então ganha os 44.
     `opacity` fica abaixo de `h2:hover .ancora` na especificidade, então o
     toque, que no Chrome aplica `:hover` por um instante, ainda a acende.

     A opacidade subiu de .55 para .75 nesta rodada: sobre o fundo do site,
     .55 dá contraste 3,16:1 contra --cor-sub. Isso passa o piso de 3:1 de
     texto grande no h2 e no h3, mas o h4 tem 17px em negrito — abaixo dos
     18,66px que qualificam como texto grande — e o piso dele é 4,5:1. Tornar
     um alvo VISÍVEL abaixo do piso de contraste é meio conserto. Em .75 a
     conta dá 4,78:1 e vale nos três níveis de título.

     A LARGURA vem de caixa de verdade, não mais de `::after`. A versão
     anterior punha `left: 0; width: 44px` no pseudo-elemento, crescendo 44px
     para a direita a partir do início do "#": quando a última linha do
     título terminava perto da margem, esses 44px saíam da viewport, e caixa
     posicionada CONTA para o overflow rolável do documento. Medido a 375px
     numa varredura de 186 títulos com palavras normais de português: 8 deles
     (4,3%) sozinhos já produziam rolagem horizontal na página inteira, o
     pior levando scrollWidth a 388 contra clientWidth 375 — e a mesma
     varredura com as âncoras escondidas dava 375 == 375, ou seja não havia
     nenhuma outra fonte de transbordo. Isso quebrava o invariante "zero
     rolagem horizontal" desta folha, e só no celular.

     Foi medida também a saída por `overflow-x: clip` na coluna de conteúdo e
     ela foi RECUSADA: corta o transbordo, mas corta junto a área de toque
     que passa da coluna, e nos 8 títulos da varredura o alvo cairia para
     31,7-42,7px de largura. Devolver 44px de rolagem em troca de tirar 12px
     de alvo é desfazer metade da rodada passada.

     Caixa de verdade não tem esse problema: `inline-flex` de 2,75rem é
     conteúdo em linha comum, e conteúdo em linha não transborda — ele quebra
     de linha. E a área continua sem cobrir texto do título: ela ocupa o
     lugar dela na linha, depois do texto, nunca por cima.

     Só que uma âncora de 44px quebrando sozinha para a linha seguinte vira
     um "#" solto embaixo do título, e isso não é raro: medido nos mesmos 186
     títulos, a caixa em fluxo pura punha a âncora em linha própria em 23
     deles (12,4%) contra 10 (5,4%) da versão de antes. Por isso o título
     RESERVA os 44px no fim da linha (`padding-right`) e a âncora ANDA por
     cima dessa reserva (`margin-right` negativo, que zera a largura de
     avanço dela): o texto passa a quebrar 44px mais cedo, a âncora nunca é
     quem força a quebra e nunca passa da coluna, porque o pior caso dela é
     terminar exatamente na borda da reserva. Medido: 3 âncoras em linha
     própria em 186 (1,6%), menos que a versão de antes desta rodada, ao
     preço de 507px a mais de altura NUMA PÁGINA COM 186 TÍTULOS — 2,7px por
     título, que numa página real de meia dúzia de títulos não se vê.

     A ALTURA continua no `::after`, e aí sim faz sentido: crescer a caixa na
     vertical esticaria a entrelinha do título. Com `left: 0; right: 0` o
     pseudo-elemento tem exatamente a largura da caixa de 44 e não sobra para
     lado nenhum. */
  .conteudo article h2,
  .conteudo article h3,
  .conteudo article h4 { padding-right: 2.75rem; }
  .ancora {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.75rem;
    margin-left: 0;
    margin-right: -2.75rem;
    opacity: .75;
  }
  .ancora::after {
    content: "";
    position: absolute;
    top: 50%;
    left: 0;
    right: 0;
    height: 2.75rem;
    margin-top: -1.375rem;
  }
  /* A âncora do h4 é a mais baixa (22px), então a área dela sobra mais para
     baixo do que a margem de 8px do h4 aguentava — encostava na primeira
     linha do parágrafo seguinte, onde pode haver link. 12px de margem afasta
     o suficiente. */
  .conteudo article h4 { margin-bottom: .75rem; }
}

/* Os dois controles de gaveta só existem abaixo de 768px (acima disso índice
   e sumário são colunas na tela e um botão para abri-los não teria função).
   Por isso a medida deles mora numa consulta com as duas condições: com
   `pointer: coarse` sozinho, mexer no `display` do rótulo do sumário faria
   ele aparecer no tablet, ligado a um checkbox que ali não abre nada. */
@media (pointer: coarse) and (max-width: 768px) {
  .botao-menu { width: 2.75rem; height: 2.75rem; }
}

/* ==== INÍCIO REALCE GERADO (scripts/gerar-css-realce.mjs — não editar à mão; rode `node scripts/gerar-css-realce.mjs` para regenerar) ==== */
.sk-24292E{color:#24292E}
.sk-2F363D{color:#2F363D}
.sk-6A737D{color:#6A737D}
.sk-79B8FF{color:#79B8FF}
.sk-85E89D{color:#85E89D}
.sk-9ECBFF{color:#9ECBFF}
.sk-B392F0{color:#B392F0}
.sk-D1D5DA{color:#D1D5DA}
.sk-DBEDFF{color:#DBEDFF}
.sk-E1E4E8{color:#E1E4E8}
.sk-F97583{color:#F97583}
.sk-FDAEB7{color:#FDAEB7}
.sk-FFAB70{color:#FFAB70}
/* ==== FIM REALCE GERADO ==== */

/* Aviso de "a busca ainda não está ligada" (public/wiki.js). Fica fora do
   fluxo do cabeçalho para não empurrar nada quando aparece. */
.cabecalho .busca { position: relative; }

/* O veu da gaveta so existe no celular (ver a media query de 768px). Fora
   dela ele nao pode virar item do grid do body nem ocupar espaco. */
.veu-indice { display: none; }
.busca-aviso {
  position: absolute;
  top: calc(100% + 0.35rem);
  left: 0;
  right: 0;
  z-index: 20;
  margin: 0;
  padding: 0.5rem 0.7rem;
  font-size: 0.85rem;
  line-height: 1.35;
  color: var(--cor-texto);
  background: var(--cor-elev-2);
  border: 1px solid var(--linha-forte);
  border-radius: var(--raio-pequeno);
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.35);
}
