/* =========================================================================
   Central de Ajuda — Torge Sistemas
   Implementação do design "Portal do Cliente".

   Regras do repositório:
   - O HTML é GERADO por scripts externos: estilizamos as tags direto, sem
     criar classes/ids. Se precisar de marcação nova, avisar o usuário.
     Única exceção: os callouts do corpo do artigo, onde o gerador já emite
     .note/.tip/.important/.warning/.caution (+ .title) — ver a seção
     "callouts" mais abaixo.
   - O JS não cria nós no DOM (ver script.js). Ícones extras, separadores e
     enfeites saem de ::before/::after aqui.
   - TEMA CLARO/ESCURO: toda cor sai dos tokens do :root, e todo token traz os
     dois temas em light-dark(). Cor nova entra ali, não solta numa regra —
     ver a seção "tokens" logo abaixo.

   Estrutura do build atual (todas as páginas):
       body > header + main [+ nav | + aside] + footer
   O <nav> entre o main e o rodapé é a lista "CATEGORIAS" (só a home e o artigo
   não a emitem); na categoria ele é promovido a coluna lateral — ver a seção
   COLUNA DE CATEGORIAS no fim do arquivo. No lugar dele, o ARTIGO emite um
   <aside> com os "Artigos relacionados" — ver a seção do mesmo nome.
   Atenção: <search> aparece em TRÊS lugares — a busca compacta da navbar
   (header > search, em toda página interna), o hero da home e a coluna de
   filtros da tela de pesquisa; os dois últimos são main > search. Todo seletor
   de busca é ancorado no pai por isso, e os dois usos dentro do <main> se
   separam pelo <form>: só a home o emite (na pesquisa o campo é um <div> solto,
   porque lá não há submit — o JS filtra a cada tecla).
   Tipos de página, distinguidos pelos filhos de <main>:
       Home         -> main > search:has(> form)
       Pesquisa     -> main > search:not(:has(> form))   (+ main > ul)
       Categoria    -> main > header        (e main > nav:has(> h2))
       Subcategoria -> main > header, com breadcrumb de 3 níveis
       Artigo       -> main > article
   A SUBCATEGORIA é uma MISTURA das duas vizinhas: a capa e o breadcrumb vêm da
   categoria (e o que a distingue dela é a profundidade do breadcrumb, 3 <li>
   contra 2), mas a lista é a da pesquisa — os mesmos cartões `main > ul > li >
   a > article`. Próprio dela só a capa branca e a linha de contagem
   (`main > p`) — ver a seção SUBCATEGORIA.

   Largura/faixas: --gutter é o padding lateral que centraliza o conteúdo em
   1240px. header, main e footer usam o mesmo gutter, então as três bordas de
   conteúdo se alinham. Faixas full-bleed dentro do main (o hero) só precisam
   de margin-inline: calc(var(--gutter) * -1) — sem hack de 50vw e, por isso,
   sem overflow horizontal em telas com barra de rolagem.
   ========================================================================= */

@import url('https://fonts.googleapis.com/css2?family=Open+Sans:ital,wght@0,400;0,500;0,600;0,700;0,800&display=swap');

/* ------------------------------------------------------------------ tokens
   MODO ESCURO. Cada token de cor traz os DOIS temas em light-dark(): o primeiro
   valor vale no claro, o segundo no escuro. Quem escolhe entre eles é o
   `color-scheme` do <html>.

   O SITE NÃO SEGUE A PREFERÊNCIA DO SISTEMA (decisão do responsável): o padrão
   é `light`, fixo, e o escuro só entra com `data-tema="escuro"` no <html>. Ou
   seja, hoje ninguém cai no escuro sem pedir. Por enquanto quem pede é o
   console — ver `tema()` no script.js; o botão da navbar depende de marcação
   que o gerador ainda não emite (gerador-botao-tema.md).
   Para voltar a acompanhar o sistema um dia, basta trocar o `color-scheme` do
   :root para `light dark`: nenhum token muda.

   A paleta fica em UM bloco só, com os dois valores lado a lado, em vez de um
   @media duplicando trinta linhas de token para sair do ar de sincronia.

   O escuro NÃO está no mockup do design (que só tem o tema claro): a paleta foi
   derivada dele mantendo o viés azul da marca — carvão azulado no lugar do
   cinza, azul e turquesa CLAROS no texto, e o azul Torge preservado só onde ele
   é superfície (--faixa) ou ação (--botao). Se o mockup ganhar um escuro
   oficial, é aqui que ele entra.

   TRÊS papéis que o azul #00336a acumulava e aqui se separam, porque no escuro
   eles deixam de poder ser a mesma cor:
       --azul    texto e títulos      -> clareia (vira quase branco azulado)
       --faixa   hero, capa, rodapé   -> escurece (continua sendo superfície)
       --botao   botão primário       -> clareia um pouco (precisa saltar) */
:root {
	color-scheme: light;
	--azul: light-dark(#00336a, #dbe8f7);
	/* bloco de código: fundo e borda. No claro ele é a única coisa escura da
	   página; no escuro isso deixa de bastar — o fundo desce ABAIXO do fundo da
	   página (fica recuado) e a borda, que era mais escura ainda, inverte para
	   mais clara, senão o bloco não teria contorno nenhum. */
	--azul-escuro: light-dark(#001f41, #060e17);
	--azul-quase-preto: light-dark(#001a38, #22303f);
	/* texto sobre o fundo escuro do bloco de código (escuro nos dois temas) */
	--codigo-texto: #dfe7f2;
	--teal: #33b0a5;
	--teal-transparente: #33b0a681;
	/* turquesa de TEXTO: no escuro o #078980 sumiria sobre o fundo */
	--teal-escuro: light-dark(#078980, #55d0c2);
	--texto: light-dark(#00336a, #dbe8f7);
	--texto-2: light-dark(#4d6a8f, #a3bbd4);
	--texto-3: light-dark(#6d91b5, #8199b3);
	--texto-corpo: light-dark(#223c5e, #c6d6e8);
	--fundo: light-dark(#f5f5f5, #0d151e);
	--superficie: light-dark(#fff, #16212d);
	--sutil: light-dark(#f4f5f9, #1e2b39);
	/* superfícies azuis da marca: hero, capa de categoria, cabeçalho de tabela e
	   rodapé. Escurecem no tema escuro em vez de inverter — é o que mantém essas
	   faixas se destacando do fundo, com o texto branco de sempre por cima. */
	--faixa: light-dark(#00336a, #132c47);
	--botao: light-dark(#00336a, #2f6bad);
	--botao-hover: light-dark(#001f41, #3d7fc4);
	/* realces que precisam aparecer TANTO sobre o fundo da página quanto sobre a
	   superfície dos cartões — o --sutil desaparece sobre o fundo. No escuro o
	   véu inverte: azul escuro sobre escuro não realçaria nada. */
	--realce: light-dark(rgba(0, 51, 106, 0.06), rgba(255, 255, 255, 0.07));
	--realce-teal: light-dark(rgba(51, 176, 165, 0.14), rgba(51, 176, 165, 0.20));
	--borda: light-dark(rgba(0, 51, 106, 0.10), rgba(255, 255, 255, 0.12));
	--borda-forte: light-dark(#b1c5d7, #40556d);
	/* véu do menu lateral: no escuro precisa de mais opacidade, porque o painel
	   por cima já é escuro e o contraste entre os dois some */
	--veu: light-dark(rgba(0, 31, 65, 0.45), rgba(0, 0, 0, 0.62));
	--raio: 15px;
	--raio-sm: 12px;
	/* sombra escura sobre fundo escuro não separa nada: no escuro ela sobe muito
	   de opacidade, para funcionar como o "vazio" abaixo do cartão */
	--sombra-card: 0 2px 8px light-dark(rgba(0, 20, 52, 0.06), rgba(0, 0, 0, 0.45));
	--sombra-menu: 0 12px 28px light-dark(rgba(0, 20, 52, 0.12), rgba(0, 0, 0, 0.55));
	--nav-h: 64px;
	/* largura do menu lateral (só existe no celular). Fica aqui porque o botão
	   de fechar se posiciona pela borda direita do painel. */
	--drawer-w: min(300px, 82vw);
	--transicao: 0.15s ease;
	/* conteúdo centralizado em 1240px, com 24px de respiro mínimo */
	--gutter: max(24px, calc((100vw - 1240px) / 2 + 24px));
	/* artigo: coluna de leitura mais estreita (46rem) */
	--gutter-artigo: max(24px, calc((100vw - 736px) / 2 + 24px));
}

/* A ÚNICA chave do tema escuro. Sem este atributo o site é claro, sempre —
   inclusive para quem usa o sistema no escuro. Quem escreve o atributo é o
   `tema()` do script.js, chamado do console. */
:root[data-tema="escuro"] { color-scheme: dark; }

/* -------------------------------------------------------------- base global */
* { box-sizing: border-box; }

html {
	scroll-behavior: smooth;
	scroll-padding-top: calc(var(--nav-h) + 12px); /* âncoras não ficam sob a navbar */
	/* Barra de rolagem no tom da página: o trilho se dissolve no fundo e sobra
	   só o polegar. `scrollbar-color` é HERDADA, então isto vale para TODA caixa
	   que rola (menu lateral, sumário, filtros) — quem tem outro fundo atrás
	   redeclara com o seu (ver o <pre> do bloco de código). */
	scrollbar-color: var(--borda-forte) var(--fundo);
}

body {
	margin: 0;
	min-height: 100vh;
	display: flex;
	flex-direction: column;              /* rodapé sempre no fim da página */
	font-family: 'Open Sans', system-ui, sans-serif;
	font-size: 15px;
	line-height: 1.5;
	color: var(--texto);
	background: var(--fundo);
	-webkit-font-smoothing: antialiased;
}

main {
	flex: 1;
	padding-inline: var(--gutter);
	padding-bottom: 8px;
}

a { color: var(--texto); text-decoration: underline; text-underline-offset: 2px; }
a:hover { color: var(--teal-escuro); }

img { max-width: 100%; }

svg { flex: none; }

::selection { background: var(--teal); color: #fff; }

/* Anel de foco. O padrão de design traz `border-radius: 4px` junto, mas aqui na
   folha ele arredondaria o ELEMENTO, não só o anel: `:focus-visible` tem
   especificidade de classe e vence os seletores de tag do resto do arquivo, então
   botão, pill e chip achatariam ao receber foco. Sem a regra, o anel já acompanha
   o raio de cada um sozinho. */
:focus-visible { outline: 2px solid var(--teal); outline-offset: 2px; }

/* Campos de busca (navbar, hero e tela de pesquisa): o input ocupa 100% da
   altura da barra, então o anel com offset positivo vaza para fora dela e
   encosta no botão ao lado. Quem sinaliza o foco é a barra inteira, pelo
   `:focus-within` de cada seção. Pela mesma especificidade citada acima, o
   `outline: none` das regras do input não basta — o seletor precisa repetir o
   `:focus-visible`. */
body > header form input:focus-visible,
main > search:has(> form) input:focus-visible,
main > search > div > input:focus-visible { outline: none; }

/* Âncoras sem texto que o gerador ainda emite em algumas listas */
a:empty { display: none; }
li:has(> a:empty) { display: none; }

/* =========================================================================
   NAVBAR  —  body > header
   flex: [button hambúrguer] [logo] [search ............... à direita]
   (o <nav> é o drawer: fica fixed, fora do fluxo do flex)
   ========================================================================= */
/* Sticky, e não fixed, porque aqui o header ainda ocupa a sua faixa no fluxo.
   No desktop ele sai do fluxo e vira `fixed` — ver o bloco "BARRA DE ROLAGEM
   ABAIXO DA NAVBAR", no fim do arquivo. */
body > header {
	position: sticky;
	top: 0;
	z-index: 60;
	display: flex;
	align-items: center;
	gap: 14px;
	height: var(--nav-h);
	padding-inline: var(--gutter);
	background: var(--superficie);
	border-bottom: 1px solid var(--borda);
}

/* Os DOIS botões-ícone da barra (40x40, radius 10, fundo só no hover).
   O header tem exatamente dois <button> filhos, sempre nesta ordem, e é a
   POSIÇÃO que os distingue — o gerador não emite classe nem id:
       :first-of-type  hambúrguer, à esquerda, só no celular
       :last-of-type   tema claro/escuro, na ponta direita, em toda tela
   Todo seletor de hambúrguer neste arquivo precisa do :first-of-type, senão
   pega o de tema junto (inclusive os do drawer, lá no responsivo). */
body > header > button {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 40px;
	height: 40px;
	padding: 0;
	border: none;
	border-radius: 10px;
	background: transparent;
	color: var(--azul);
	cursor: pointer;
	transition: background var(--transicao), color var(--transicao);
}
body > header > button:hover { background: var(--sutil); }
body > header > button > svg { width: 22px; height: 22px; }

/* hambúrguer: só no celular (ver @media 768px no fim do arquivo) */
body > header > button:first-of-type { display: none; }

/* ------------------------------------------------------ botão de tema
   AINDA NÃO EXISTE. Depende de marcação que o gerador não emite; hoje o tema é
   ligado pelo console (`tema('escuro')` — ver script.js). Estas regras ficam
   prontas para quando o botão chegar; a marcação está em
   gerador-botao-tema.md, e junto com ela entra o handler no script.js, que é
   quem passará a escrever o aria-pressed.

   Último filho do header. Na home não existe a busca da navbar para empurrá-lo
   com o `margin-left: auto` dela, então ele mesmo assume o empurrão.
   Ícones: sol (1º) e lua (2º), e aparece o do tema PARA ONDE o clique leva —
   lua enquanto está claro (sem atributo), sol quando aria-pressed="true".

   O `:has(> button ~ button)` é a trava do período de transição: enquanto o
   segundo botão não existir, o :last-of-type É o hambúrguer, e sem a trava
   estas regras esconderiam o ícone dele. Sai quando a marcação chegar. */
body > header:has(> button ~ button) > button:last-of-type { color: var(--texto-2); }
body > header:has(> button ~ button) > button:last-of-type:hover { color: var(--azul); }
body > header:has(> button ~ button):not(:has(> search)) > button:last-of-type { margin-left: auto; }
body > header:has(> button ~ button) > button:last-of-type > svg:first-child { display: none; }
body > header > button[aria-pressed="true"] > svg:first-child { display: block; }
body > header > button[aria-pressed="true"] > svg:last-child { display: none; }

/* ------------------------------------------------------------------- marca
   O <a> traz a logo (SVG 260x78 inline, precisa de altura explícita) e o texto
   "Central de Ajuda" como nó solto — ou seja, um item flex ANÔNIMO. Por isso o
   espaço entre os dois vem do `gap`, e o traço divisório do design vem de um
   ::before: com o svg em `order: -1`, o pseudo sobra entre a logo e o texto
   (ambos no grupo order 0, resolvidos por ordem de documento). */
body > header > a {
	display: inline-flex;
	align-items: center;
	gap: 10px;
	font-size: 14px;
	font-weight: 600;
	color: var(--texto-2);
	text-decoration: none;
	white-space: nowrap;
}
body > header > a:hover { color: var(--texto-2); }   /* a marca não reage ao hover */
body > header > a > svg {
	order: -1;
	display: block;
	height: 26px;
	width: auto;
}
body > header > a::before {
	content: "";
	width: 1px;
	height: 20px;
	background: var(--borda-forte);
}
/* A logo vem do images/logo-light.svg com os fills CRAVADOS no arquivo: azul
   Torge no letreiro e turquesa no arco. No tema escuro o letreiro azul quase
   desapareceria sobre a barra — os dois seletores de atributo devolvem os
   caminhos aos tokens, que já trocam de valor sozinhos. Casa o valor como está
   escrito no SVG (maiúsculo); atributo, não classe. */
body > header > a > svg path[fill="#00336A"] { fill: var(--azul); }
body > header > a > svg path[fill="#33B0A5"] { fill: var(--teal); }

/* ---------------------------------------------- menu lateral (só no hambúrguer)
   Os links Início/Financeiro/Fiscal nunca aparecem soltos na barra: ficam num
   painel lateral (drawer) que desliza pela esquerda POR CIMA da navbar (altura
   cheia, do topo ao rodapé da janela). Como o botão só existe no celular, no
   desktop o menu não aparece — a navegação lá é pelos cards da home e pelo
   breadcrumb. As regras que ABREM o painel estão na @media de 768px; aqui ele
   é só desenhado, e nasce fora da tela.
   Pilha dentro do <header> (que já é z-index 60 na página):
       véu (::after) 1  <  painel (nav) 2  <  hambúrguer (button) 3
   O botão fica acima do painel de propósito: ele continua no lugar de sempre e
   passa a ser o "fechar" do drawer.
   O `visibility: hidden` do estado fechado é o que tira os links da ordem de
   tabulação — sem ele o painel continuaria focável fora da tela. */
body > header > nav {
	position: fixed;
	inset: 0 auto 0 0;                   /* topo/base da janela, encostado à esquerda */
	z-index: 2;
	display: none;                       /* vira flex na @media de 768px */
	flex-direction: column;
	width: var(--drawer-w);
	padding: 0 12px 18px;
	overflow-y: auto;
	overscroll-behavior: contain;
	background: var(--superficie);
	border-right: 1px solid var(--borda);
	box-shadow: var(--sombra-menu);
	visibility: hidden;
	transform: translateX(-100%);
	transition: transform 0.22s ease, visibility 0.22s ease;
}
/* "Menu" vira a barra de título do painel: mesma altura da navbar que ele
   cobre, com a divisória alinhada à do header. O padding-right abre espaço para
   o botão de fechar, que flutua no canto direito do painel; o padding-left
   alinha o rótulo com os ícones dos itens.
   Fica visível porque o <nav> inteiro só existe no drawer. */
body > header > nav > h2 {
	flex: none;
	display: flex;
	align-items: center;
	height: var(--nav-h);
	margin: 0 -12px 10px;                /* a divisória atravessa o painel todo */
	padding: 0 52px 0 24px;
	border-bottom: 1px solid var(--borda);
	font-size: 13px;
	font-weight: 800;
	text-transform: uppercase;
	letter-spacing: 0.5px;
	color: var(--azul);
}
body > header > nav ul {
	display: flex;
	flex-direction: column;
	align-items: stretch;
	gap: 2px;
	margin: 0;
	padding: 0;
	list-style: none;
}
/* subtítulo do grupo: tudo depois de "Início" é categoria. Sem marcação nova —
   o rótulo é ::before do 2º <li> (some junto, se a categoria não existir). */
body > header > nav li:nth-child(2)::before {
	content: "Categorias";
	display: block;
	margin: 14px 0 4px;
	padding: 0 12px;
	font-size: 12px;
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.5px;
	color: var(--texto-2);
}
body > header > nav a {
	display: flex;
	align-items: center;
	gap: 10px;
	height: 44px;
	padding: 0 12px;
	border-radius: 9px;
	color: var(--texto-2);
	font-size: 15px;
	font-weight: 700;
	text-decoration: none;
	white-space: nowrap;
	transition: background var(--transicao), color var(--transicao);
}
body > header > nav a:hover { background: var(--sutil); color: var(--azul); }
body > header > nav a svg { width: 18px; height: 18px; color: var(--texto-3); }
/* seção da página atual: o script.js marca o link com aria-current="page"
   (só atributo, nada de nó novo no DOM) — igual à coluna de categorias */
body > header > nav a[aria-current] {
	background: var(--realce-teal);
	color: var(--azul);
	font-weight: 800;
}
body > header > nav a[aria-current] svg { color: var(--teal); }

/* véu do drawer: pseudo do <header> porque o JS não pode criar nós. Cobre a
   janela inteira (inclusive a navbar, que o painel também cobre) e fica sob o
   painel; o header já é o topo da pilha da página (z-index 60), então nada do
   <main> vaza por cima. Clicar nele tem o <header> como alvo — é assim que o
   script.js fecha o menu. */
body > header::after {
	content: "";
	position: fixed;
	inset: 0;
	z-index: 1;
	display: none;                       /* vira block na @media de 768px */
	background: var(--veu);
	opacity: 0;
	pointer-events: none;
	transition: opacity 0.22s ease;
}

/* ------------------------------------------------- busca do header
   Todas as páginas internas emitem `header > search > form` (a home tem só a
   busca grande do hero). Quem se posiciona é o <search>, porque é ELE o item
   flex do header: é nele que ficam o `margin-left: auto` que joga a busca para
   a direita e o `flex` que a deixa encolher quando a barra aperta. O <form>
   apenas preenche esse espaço. O `display: contents` no <div> deixa a regra
   funcionar com ou sem esse wrapper interno.
   Fica escondido na home, que já tem a busca grande no hero. */
body > header > search {
	margin-left: auto;
	flex: 0 1 320px;
	min-width: 0;
}
body > header form {
	display: flex;
	align-items: center;
	gap: 9px;
	min-width: 0;
	height: 40px;
	padding: 0 14px;
	border-radius: 10px;
	background: var(--sutil);
	transition: background var(--transicao), box-shadow var(--transicao);
}
body > header form > div { display: contents; }
body > header form:focus-within { background: var(--superficie); box-shadow: inset 0 0 0 1px var(--teal); }
body > header form svg { width: 18px; height: 18px; color: var(--texto-3); }
body > header form input {
	flex: 1;
	min-width: 0;
	height: 100%;
	border: none;
	outline: none;
	background: none;
	font: inherit;
	font-size: 14px;
	color: var(--texto);
}
body > header form input::placeholder { color: var(--texto-2); }
/* se vier um botão de submit, o header usa Enter (não cabe rótulo em 40px) */
body > header form button { display: none; }
/* Onde o <main> já tem a sua própria busca (home e tela de pesquisa), a da
   navbar sai — duas caixas de busca na mesma tela seriam redundantes. Sem
   qualificar de propósito: vale para os DOIS usos de main > search. E some o
   wrapper inteiro, não só o form: escondendo só o form, o <search> continuaria
   como item flex de 320px reservando espaço vazio à direita. */
body:has(main > search) > header > search { display: none; }

/* =========================================================================
   HOME  —  main > search:has(> form)
   Faixa azul full-bleed com título, busca e chips de "Buscas populares".

   O `:has(> form)` NÃO é enfeite: a tela de pesquisa também abre o <main> com
   um <search>, e sem ele o azul do hero, a caixa branca e os chips cairiam lá
   também. O <form> é o discriminante porque só a home submete a busca (vai
   para /pesquisa/?q=…); na pesquisa o campo filtra a lista a cada tecla e o
   gerador emite um <div> solto, sem form.
   ========================================================================= */
main > search:has(> form) {
	display: block;
	margin-inline: calc(var(--gutter) * -1);     /* full-bleed */
	padding: 72px var(--gutter) 80px;
	background: var(--faixa);
	color: #fff;
	text-align: center;
}
main > search:has(> form) > header { max-width: 760px; margin: 0 auto 28px; }
main > search:has(> form) h1 {
	margin: 0 0 12px;
	font-size: clamp(28px, 4.4vw, 44px);
	font-weight: 800;
	line-height: 1.1;
	letter-spacing: -0.5px;
}
main > search:has(> form) > header p {
	margin: 0;
	font-size: clamp(15px, 2vw, 18px);
	color: rgba(255, 255, 255, 0.78);
}

/* ---- caixa de busca (form > div com svg + input + button) ---- */
main > search:has(> form) form { max-width: 680px; margin: 0 auto; }
main > search:has(> form) form > div {
	display: flex;
	align-items: center;
	gap: 10px;
	padding: 8px 8px 8px 18px;
	/* NÃO é --superficie: no escuro a caixa cairia mais escura que o próprio
	   hero e sumiria nele. Aqui ela precisa ser sempre o degrau CLARO por cima
	   da faixa azul, então tem um valor próprio nos dois temas. */
	background: light-dark(#fff, #1e3a5c);
	border-radius: 14px;
	box-shadow: 0 12px 34px rgba(0, 20, 52, 0.28);
	transition: box-shadow var(--transicao);
}
/* o anel de foco do input aqui é desligado (ver base global): quem marca é a
   caixa, com o realce POR DENTRO para não invadir o azul do hero */
main > search:has(> form) form > div:focus-within {
	box-shadow: 0 12px 34px rgba(0, 20, 52, 0.28), inset 0 0 0 2px var(--teal);
}
main > search:has(> form) form > div > svg { width: 22px; height: 22px; color: var(--texto-3); }
main > search:has(> form) input {
	flex: 1;
	min-width: 0;
	height: 40px;
	border: none;
	outline: none;
	background: none;
	font: inherit;
	font-size: 16px;
	color: var(--azul);
}
main > search:has(> form) input::placeholder { color: var(--texto-3); }
main > search:has(> form) input::-webkit-search-cancel-button { cursor: pointer; }
main > search:has(> form) form button {
	height: 44px;
	padding: 0 20px;
	border: none;
	border-radius: 10px;
	background: var(--botao);
	color: #fff;
	font: inherit;
	font-size: 15px;
	font-weight: 600;
	cursor: pointer;
	transition: background var(--transicao);
}
main > search:has(> form) form button:hover { background: var(--botao-hover); }

/* ---- buscas populares (fieldset > legend + ul > li > button) ---- */
/* Rótulo e chips na MESMA linha, o rótulo à esquerda. Por isso o fieldset é
   flex: a <legend> e o <ul> são os dois itens. Em tela estreita a linha quebra
   e o rótulo volta para cima dos chips (row-gap do `gap`). */
main > search:has(> form) fieldset {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: center;
	gap: 8px 12px;
	max-width: 680px;
	margin: 22px auto 0;
	padding: 0;
	border: 0;
}
/* O `float` é o que tira a <legend> do papel de legenda do <fieldset>: enquanto
   ela é a legenda RENDERIZADA, o navegador a desenha na borda do fieldset e a
   mantém fora do flex, empilhada acima do conteúdo. Floatada, ela deixa de ser
   a legenda; e como float não vale dentro de container flex, sobra um item de
   flex comum, que senta na linha dos chips. Não dá para resolver com marcação
   (um wrapper), porque o gerador emite este HTML. */
main > search:has(> form) legend {
	float: left;
	padding: 0;
	white-space: nowrap;                 /* o rótulo nunca quebra em duas linhas */
	font-size: 12px;
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.5px;
	color: rgba(255, 255, 255, 0.55);
}
main > search:has(> form) fieldset ul {
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	gap: 8px;
	margin: 0;
	padding: 0;
	list-style: none;
}
main > search:has(> form) fieldset button {
	height: 30px;
	padding: 0 13px;
	border: none;
	border-radius: 999px;
	background: rgba(255, 255, 255, 0.12);
	color: #fff;
	font: inherit;
	font-size: 13px;
	font-weight: 600;
	cursor: pointer;
	transition: background var(--transicao);
}
main > search:has(> form) fieldset button:hover { background: rgba(255, 255, 255, 0.22); }

/* =========================================================================
   BREADCRUMB  —  main > nav:first-of-type  (categoria, artigo e pesquisa)
   ========================================================================= */
main > nav:first-of-type { margin-top: 20px; font-size: 13px; }
main > nav:first-of-type ul {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 8px;
	margin: 0;
	padding: 0;
	list-style: none;
}
main > nav:first-of-type li { display: flex; align-items: center; gap: 8px; }
main > nav:first-of-type li + li::before {
	content: "\203A";
	color: var(--texto-3);
}
main > nav:first-of-type a {
	color: var(--texto-2);
	font-weight: 600;
	text-decoration: none;
}
main > nav:first-of-type a:hover { color: var(--teal-escuro); }
main > nav:first-of-type li:last-child a { color: var(--azul); }

/* =========================================================================
   PÁGINA DE PESQUISA  —  main > search:not(:has(> form))  +  main > ul

   Marcação gerada (nada aqui pode mudar isso):

       main
         nav                 breadcrumb (Início / Pesquisa)
         search
           div               svg(lupa) + input[type=search]
           section           h2 "Filtros" + fieldset(Categorias) + fieldset(Tags)
           fieldset          ordenação: 3 radios name="order"
           output            "<span>0</span> resultado(s)"
         ul > li > a > article    TODOS os artigos do site, já no HTML

   DISCRIMINANTE. A home também abre o <main> com um <search>; o que separa as
   duas é o <form>, que só a home emite (lá o Enter navega para cá). Por isso o
   hero é `main > search:has(> form)` e esta página é a negação. Nas regras dos
   FILHOS o discriminante fica implícito e o combinador de filho basta: o
   <search> da home só tem `header` e `form` dentro, então `main > search > div`,
   `> section`, `> fieldset` e `> output` existem apenas aqui.

   LAYOUT. O design pede três coisas em faixas diferentes: campo de busca no
   topo, filtros numa coluna à esquerda e — no topo da coluna de resultados —
   a contagem à esquerda com as abas de ordenação à direita. Mas contagem e
   ordenação são filhos do <search>, e a lista de resultados é irmã dele: não há
   um elemento que envolva "coluna da direita". A saída é `display: contents` no
   <search>: ele deixa de gerar caixa e os quatro filhos viram itens da grade do
   próprio <main>, ao lado do <ul>. É o mesmo truque já usado na busca da navbar
   (`body > header form > div`), aqui em escala maior. Grade:

       linha 1   [ breadcrumb ................................................ ]
       linha 2   [ campo de busca ............................................ ]
       linha 3   [ filtros  ] [ contagem ............ ] [ ordenação ]
       linha 4   [ (sticky) ] [ resultados ......................... ]

   O `display: contents` mexe SÓ na caixa: a árvore do DOM continua a mesma, e
   por isso nenhum seletor de outra página passa a alcançar esta — `main >
   section` (as seções da home e da categoria) segue sem chegar na <section> de
   filtros, que continua sendo filha do <search>.

   Abaixo de 1000px a grade vira uma coluna só e tudo volta à ordem do
   documento — filtros acima dos resultados (ver o responsivo no fim).
   ========================================================================= */
main:has(> search > output) {
	display: grid;
	grid-template-columns: 280px minmax(0, 1fr) auto;
	column-gap: 32px;
	row-gap: 16px;
	align-items: start;                  /* nada estica: o sticky precisa de altura própria */
}
main > search:not(:has(> form)) { display: contents; }

main:has(> search > output) > nav:first-of-type { grid-area: 1 / 1 / 2 / -1; }
main > search > div { grid-area: 2 / 1 / 3 / -1; }
/* span alto pelo mesmo motivo do sumário do artigo: a área de grade precisa ser
   tão alta quanto a lista para o sticky ter por onde correr (as linhas
   implícitas que sobram têm altura zero). */
main > search > section { grid-area: 3 / 1 / span 99 / 2; }
main > search > output { grid-area: 3 / 2; align-self: center; }
main > search > fieldset { grid-area: 3 / 3; }
main:has(> search > output) > ul { grid-area: 4 / 2 / 5 / -1; }

/* ---- campo de busca: <div> com lupa + input, sem form (o JS filtra ao digitar) ---- */
main > search > div {
	display: flex;
	align-items: center;
	gap: 12px;
	height: 52px;
	padding: 0 16px;
	background: var(--superficie);
	border: 1px solid var(--borda-forte);
	border-radius: var(--raio-sm);
	transition: border-color var(--transicao);
}
main > search > div:focus-within { border-color: var(--teal); }
main > search > div > svg { width: 22px; height: 22px; color: var(--texto-3); }
main > search > div > input {
	flex: 1;
	min-width: 0;
	height: 100%;
	border: none;
	outline: none;
	background: none;
	font: inherit;
	font-size: 16px;
	color: var(--azul);
}
main > search > div > input::placeholder { color: var(--texto-3); }
main > search > div > input::-webkit-search-cancel-button { cursor: pointer; }

/* ---- painel de filtros: cartão branco com "Filtros" + os dois grupos ---- */
main > search > section {
	position: sticky;
	top: calc(var(--nav-h) + 16px);
	max-height: calc(100vh - var(--nav-h) - 32px);
	overflow-y: auto;
	overscroll-behavior: contain;
	padding: 18px;
	background: var(--superficie);
	border: 1px solid var(--borda);
	border-radius: var(--raio);
}
main > search > section > h2 {                     /* svg(funil) + "Filtros" */
	display: flex;
	align-items: center;
	gap: 10px;
	margin: 0 0 16px;
	font-size: 18px;
	font-weight: 700;
	color: var(--azul);
}
main > search > section > h2 > svg { width: 19px; height: 19px; color: var(--teal); }
main > search > section fieldset {
	margin: 0;
	padding: 0;
	border: 0;
}
main > search > section fieldset + fieldset { margin-top: 20px; }
main > search > section legend {                   /* "CATEGORIAS" / "TAGS" */
	padding: 0;
	margin-bottom: 8px;
	font-size: 12px;
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.5px;
	color: var(--texto-2);
}
/* Linha clicável: [caixa] [ícone] [nome] [contagem]. O seletor é DESCENDENTE de
   propósito — o gerador fecha o </fieldset> das Tags dentro do loop, então da
   segunda tag em diante o <label> sai como filho direto da <section>, fora de
   qualquer fieldset (bug conhecido). O nome é um nó de texto solto entre o
   input e o <span>: item flex ANÔNIMO, sem seletor possível — daí a contagem
   ser empurrada pela própria margem, não por um flex:1 no nome. */
main > search > section label {
	display: flex;
	align-items: center;
	gap: 9px;
	padding: 7px 9px;
	border-radius: 8px;
	font-size: 13.5px;
	font-weight: 500;
	color: var(--texto-2);
	cursor: pointer;
	transition: background var(--transicao), color var(--transicao);
}
/* o realce do design (--sutil) some sobre o branco do painel; --realce é o véu
   azul que aparece nos dois fundos (ver tokens) */
main > search > section label:hover { background: var(--realce); color: var(--azul); }
/* a caixa vem DEPOIS do ícone no HTML; order a traz para a frente sem tocar no
   resto da linha (ícone, nome e contagem ficam todos no grupo 0).

   A CAIXA DO DESIGN não é a nativa: é um quadrado 18px de raio 5px com borda de
   2px, que vira turquesa cheio com um "check" branco quando marcado. Como o JS
   não pode criar nós e não há como envolver o input num <span>, ela sai do
   PRÓPRIO input com `appearance: none` — a borda e o fundo são do input, e o
   check é um background-image (Lucide `check`, o mesmo path do icons/check.svg)
   embutido como data-URI. Por que não ::before/::after: o input é elemento
   substituído, e pseudo-elemento nele não é confiável entre navegadores.
   O branco do traço é literal, não token, porque o fundo por baixo é sempre o
   turquesa — não muda com o tema. E o traço vai a 3 (contra 2 do mockup, que é
   o padrão do Lucide) porque num SVG de viewBox 24 desenhado a 12px o 2 vira
   meio pixel e o check desaparece. */
main > search > section label > input {
	order: -1;
	flex: none;
	appearance: none;
	width: 18px;
	height: 18px;
	margin: 0;
	border: 2px solid var(--borda-forte);
	border-radius: 5px;
	background: transparent no-repeat center / 12px 12px;
	cursor: pointer;
	transition: background-color var(--transicao), border-color var(--transicao);
}
main > search > section label > input:checked {
	border-color: var(--teal);
	background-color: var(--teal);
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E");
}
main > search > section label > svg { width: 17px; height: 17px; color: var(--texto-3); }
/* contagem: o gerador manda o número do `wc -l` com os espaços de alinhamento
   (`<span>       1</span>`). Como item flex o <span> é blocado, e o espaço em
   branco no início da linha colapsa sozinho — sobra só o número. */
main > search > section label > span {
	margin-left: auto;
	min-width: 24px;
	padding: 1px 7px;
	border-radius: 999px;
	background: var(--realce);
	font-size: 11.5px;
	font-weight: 700;
	text-align: center;
	color: var(--texto-3);
}
main > search > section label:has(input:checked) {
	background: var(--realce-teal);
	color: var(--azul);
	font-weight: 700;
}
main > search > section label:has(input:checked) > svg { color: var(--teal); }
main > search > section label:has(input:checked) > span {
	background: light-dark(rgba(51, 176, 165, 0.22), rgba(51, 176, 165, 0.28));
	color: var(--teal-escuro);
}

/* ---- ordenação: o controle segmentado no topo dos resultados ----
   No design não são três chips soltos: é UMA cápsula branca, com borda e 4px de
   respiro interno, e dentro dela as três opções sem borda própria — a marcada
   vira um retângulo azul de texto branco (o mesmo azul do botão primário). Como
   cada opção é um <label> com o radio dentro, a cápsula é o próprio <fieldset>,
   e `justify-self` a mantém do tamanho do conteúdo em vez de esticar na coluna.

   A CAIXA NATIVA SAI DE CENA — o design não tem bolinha, o estado é o retângulo
   azul. O input fica escondido mas ainda FOCÁVEL (`opacity: 0` e 1px, não
   `display: none`), e por isso o anel de foco é redesenhado no <label>: o
   :focus-visible global marcaria um elemento invisível. */
main > search > fieldset {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-self: end;
	gap: 6px;
	margin: 0;
	padding: 4px;
	background: var(--superficie);
	border: 1px solid var(--borda);
	border-radius: 10px;
}
main > search > fieldset > label {
	position: relative;                  /* âncora do input escondido */
	display: inline-flex;
	align-items: center;
	justify-content: center;
	height: 30px;
	padding: 0 12px;
	border-radius: 7px;
	font-size: 13px;
	font-weight: 600;
	white-space: nowrap;
	color: var(--texto-2);
	cursor: pointer;
	transition: background var(--transicao), color var(--transicao);
}
main > search > fieldset > label > input {
	position: absolute;
	width: 1px;
	height: 1px;
	margin: 0;
	opacity: 0;
	pointer-events: none;                /* quem recebe o clique é o <label> */
}
main > search > fieldset > label:hover { background: var(--realce); color: var(--azul); }
/* offset 1px, e não os 2px do foco global: a cápsula só tem 4px de padding e o
   anel vazaria por cima da borda */
main > search > fieldset > label:has(input:focus-visible) {
	outline: 2px solid var(--teal);
	outline-offset: 1px;
}
main > search > fieldset > label:has(input:checked) {
	background: var(--botao);
	color: #fff;                         /* sobre o azul do botão, não muda com o tema */
}
/* Ordem sem dado na marcação (hoje só "Mais vistos", quando o <article> vem sem
   data-views): o script.js desabilita o radio e explica no title. Aqui ele só
   fica esmaecido — e o :hover acima não pode revivê-lo, por isso a regra vem
   depois. */
main > search > fieldset > label:has(input:disabled),
main > search > fieldset > label:has(input:disabled):hover {
	background: transparent;
	color: var(--texto-3);
	opacity: 0.5;
	cursor: not-allowed;
}

/* ---- contagem: "<span>3</span> resultado(s)" ---- */
main > search > output {
	font-size: 13px;
	color: var(--texto-3);
}
main > search > output > span {
	font-weight: 700;
	color: var(--azul);
}
/* Quando nenhum artigo casa TODOS os termos, o script relaxa a busca para
   quem casa parte deles e marca data-busca="parcial" no <search>. O aviso é
   daqui porque o script.js não pode criar nós. */
main > search[data-busca="parcial"] > output::after {
	content: " · correspondência parcial";
	font-style: italic;
}

/* ---- destaque do termo buscado ----
   Sem <mark>: o script registra Ranges na CSS Custom Highlight API (nada é
   inserido na árvore) e a pintura é toda daqui. Navegador sem suporte
   simplesmente ignora estas duas regras. */
::highlight(busca) {
	background: var(--realce-teal);
	color: var(--azul);
}
main > ul article h3::highlight(busca) { background: var(--teal-transparente); }

/* ---- lista de resultados  —  main > ul > li > a > article ----
   `main > ul` só existe nesta página (na home e na categoria as listas estão
   dentro de <section>/<nav>, no artigo dentro de <article>).

   O `display: flex` é OBRIGATÓRIO, não estético: o script.js ordena a lista
   escrevendo `style.order` em cada <li> (não pode mover nós), e `order` só vale
   entre itens de um contêiner flex ou grid. Pelo mesmo motivo o [hidden]
   precisa da regra explícita abaixo — como item flex o <li> é blocado, e o
   display do UA para [hidden] seria sobrescrito. */
main > ul {
	display: flex;
	flex-direction: column;
	gap: 12px;
	margin: 0 0 56px;
	padding: 0;
	list-style: none;
	transition: opacity var(--transicao);
}
main > ul > li[hidden] { display: none; }
main > ul > li > a {
	display: block;
	color: inherit;
	text-decoration: none;
}
main > ul > li > a:hover { color: inherit; }
main > ul article {
	display: flex;
	flex-direction: column;
	gap: 7px;
	padding: 16px 18px;
	background: var(--superficie);
	border: 1px solid var(--borda);
	border-radius: var(--raio);
	transition: border-color var(--transicao), transform var(--transicao), box-shadow var(--transicao);
}
main > ul > li > a:hover article {
	border-color: var(--teal-transparente);
	transform: translateY(-2px);
	box-shadow: var(--sombra-card);
}
/* 1º <p>: categoria (o único <span> com ícone) + tags. A categoria fica no véu
   azul e as tags no turquesa, os mesmos chips do resto do site. */
main > ul article > p:first-of-type {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 6px;
	margin: 0;
	font-size: 11.5px;
	line-height: 1.5;
}
main > ul article > p:first-of-type > span {
	display: inline-flex;
	align-items: center;
	gap: 5px;
	padding: 2px 9px;
	border-radius: 999px;
	background: var(--realce-teal);
	font-weight: 700;
	color: var(--teal-escuro);
}
main > ul article > p:first-of-type > span:has(svg) {
	background: var(--realce);
	color: var(--azul);
}
main > ul article > p:first-of-type svg { width: 13px; height: 13px; }
main > ul article h3 {
	margin: 0;
	font-size: 16px;
	font-weight: 700;
	line-height: 1.35;
	color: var(--azul);
}
/* 2º <p>: descrição, duas linhas e o resto em reticências — é o que mantém os
   cartões com a mesma altura mesmo com textos de tamanhos bem diferentes */
main > ul article > p:nth-of-type(2) {
	display: -webkit-box;
	-webkit-line-clamp: 2;
	-webkit-box-orient: vertical;
	overflow: hidden;
	margin: 0;
	font-size: 13.5px;
	line-height: 1.5;
	color: var(--texto-2);
}
/* 3º <p>: tempo de leitura + data */
main > ul article > p:last-of-type {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 6px 16px;
	margin: 2px 0 0;
	font-size: 12px;
	color: var(--texto-3);
}
main > ul article > p:last-of-type > span,
main > ul article time {
	display: inline-flex;
	align-items: center;
	gap: 5px;
}
main > ul article > p:last-of-type svg { width: 13px; height: 13px; }

/* ---- "nenhum resultado" ----
   O script.js não pode criar nós, então o aviso é um ::after do próprio <ul>,
   que aparece quando não sobra nenhum <li> sem [hidden]. Como o <ul> é flex, o
   pseudo entra como item da coluna e ocupa a largura toda. */
main > ul:not(:has(> li:not([hidden])))::after {
	content: "Nenhum artigo encontrado. Tente outros termos ou remova filtros.";
	padding: 44px 24px;
	border: 1px dashed var(--borda-forte);
	border-radius: var(--raio);
	font-size: 14px;
	color: var(--texto-2);
	text-align: center;
}
/* A SUBCATEGORIA reaproveita esta mesma lista (ver a seção dela), mas lá não há
   termo digitado nem filtro marcado para afrouxar: a lista só está vazia porque
   a pasta ainda não tem artigo. Muda só o texto; a caixa é a mesma. */
main > header ~ ul:not(:has(> li:not([hidden])))::after {
	content: "Nenhum artigo nesta subcategoria ainda.";
}
/* enquanto o debounce não terminou o script marca aria-busy no <search>; a
   lista esmaece de leve para o resultado não parecer já atualizado */
main:has(> search[aria-busy="true"]) > ul { opacity: 0.55; }

/* =========================================================================
   CATEGORIA  —  main > header  (+ o que vem depois dele)
   `main > header` só existe nesta página (na home o main abre com <search>, no
   artigo o header está dentro do <article>). Por isso o combinador de irmão
   `main > header ~ …` é o escopo da categoria: pega o <nav> de subcategorias e
   as <section> de listas sem afetar a home, e deixa de fora o breadcrumb, que
   vem ANTES do header.
   ========================================================================= */
/* ---- capa da categoria: cartão azul com ícone, título, descrição e contagens */
main > header {
	position: relative;                   /* âncora do ícone (ver abaixo) */
	margin: 22px 0 28px;
	padding: 26px;
	border-radius: 16px;
	background: var(--faixa);
	color: #fff;
}
/* ÍCONE DA CAPA: quadrado translúcido de 60px com o SVG de 32px centralizado,
   à esquerda do bloco de texto (design: gap de 18px, alinhado pelo topo).
   O gerador emite o icon.svg como PRIMEIRO filho do <header>, irmão solto do
   h1 e das contagens — não há wrapper onde apoiar a coluna de texto, e virar
   grade não serve: cada contagem viraria um item e as duas deixariam de
   dividir a linha (elas são inline-flex e hoje fluem juntas). Por isso o ícone
   sai do fluxo e é o padding-left do header que abre a coluna.
   O véu é branco porque a capa da CATEGORIA é a faixa azul nos dois temas; se
   um dia o gerador emitir o ícone também na SUBCATEGORIA, cuja capa é branca,
   ele precisa de um véu próprio na seção daquela página. */
main > header:has(> svg:first-child) { padding-left: calc(26px + 60px + 18px); }
main > header > svg:first-child {
	position: absolute;
	top: 26px;
	left: 26px;
	width: 32px;
	height: 32px;
	padding: 14px;                        /* 32 + 2×14 = o quadrado de 60px */
	box-sizing: content-box;
	border-radius: var(--raio);
	background: rgba(255, 255, 255, 0.14);
}
main > header h1 {
	margin: 0;
	font-size: clamp(24px, 3vw, 30px);
	font-weight: 800;
	letter-spacing: -0.3px;
	color: inherit;
}
main > header > p {
	margin: 8px 0 12px;
	max-width: 620px;
	font-size: 15px;
	line-height: 1.55;
	color: rgba(255, 255, 255, 0.8);
}
main > header > span {                            /* "N artigos", "N subcategorias" */
	display: inline-flex;
	align-items: center;
	gap: 6px;
	margin-right: 20px;
	font-size: 13px;
	color: rgba(255, 255, 255, 0.72);
}
main > header > span > svg { width: 15px; height: 15px; }

/* ---- subcategorias: grade de cartões com nome + contagem empilhados ---- */
main > header ~ nav { margin-bottom: 32px; }
main > header ~ nav > h2 {
	margin: 0 0 14px;
	font-size: 18px;
	font-weight: 700;
	color: var(--azul);
}
main > header ~ nav > ul {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
	gap: 12px;
	margin: 0;
	padding: 0;
	list-style: none;
}
main > header ~ nav a {
	display: grid;
	grid-template-columns: 1fr auto;      /* [nome / contagem] [chevron] */
	align-items: center;
	gap: 2px 10px;
	height: 100%;
	padding: 15px 16px;
	background: var(--superficie);
	border: 1px solid var(--borda);
	border-radius: var(--raio-sm);
	color: inherit;
	text-decoration: none;
	transition: border-color var(--transicao), transform var(--transicao), box-shadow var(--transicao);
}
main > header ~ nav a:hover {
	border-color: var(--teal-transparente);
	transform: translateY(-1px);
	box-shadow: var(--sombra-card);
}
main > header ~ nav a p {
	grid-area: 1 / 1;
	margin: 0;
	font-size: 14.5px;
	font-weight: 700;
	color: var(--azul);
}
main > header ~ nav a span {
	grid-area: 2 / 1;
	font-size: 12px;
	font-weight: 400;
	color: var(--texto-3);
}
main > header ~ nav a svg {
	grid-area: 1 / 2 / span 2 / span 1;
	width: 18px;
	height: 18px;
	color: var(--borda-forte);
}
main > header ~ nav a:hover svg { color: var(--borda-forte); }

/* =========================================================================
   SEÇÕES  —  main > section  (home: categorias + recentes; categoria: recentes)
   ========================================================================= */
main > section { margin-top: 40px; }
main > section:last-of-type { margin-bottom: 56px; }

main > section > header {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: 12px;
	margin-bottom: 16px;
}
main > section > header h2,
main > section > h2 {
	/* Flex para o ícone ficar centralizado com o texto: o gerador emite o SVG
	   como irmão inline do título, e inline se apoiaria na baseline. */
	display: flex;
	align-items: center;
	gap: 10px;
	margin: 0 0 16px;
	font-size: 22px;
	font-weight: 700;
	color: var(--azul);
}
main > section > header h2 { margin-bottom: 0; }
main > section > h2 > svg { width: 22px; height: 22px; color: var(--teal); }
main > section > header p {
	margin: 0;
	font-size: 13.5px;
	font-weight: 600;
	color: var(--texto-3);
	white-space: nowrap;
}

/* ---- cards de categoria (home) ---- */
main > section > nav > ul {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
	gap: 16px;
	margin: 0;
	padding: 0;
	list-style: none;
}
main > section > nav a {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 12px;
	height: 100%;
	padding: 20px;
	background: var(--superficie);
	border: 1px solid var(--borda);
	border-radius: var(--raio);
	color: inherit;
	text-decoration: none;
	transition: border-color var(--transicao), transform var(--transicao), box-shadow var(--transicao);
}
main > section > nav a:hover {
	border-color: var(--teal-transparente);
	transform: translateY(-2px);
	box-shadow: var(--sombra-card);
}
main > section > nav a > svg {
	width: 24px;
	height: 24px;
	padding: 11px;
	box-sizing: content-box;
	border-radius: 12px;
	background: var(--sutil);
	color: var(--azul);
	transition: background var(--transicao), color var(--transicao);
}
main > section > nav a:hover > svg { background: var(--sutil); color: var(--azul); }
main > section > nav a h3 { margin: 0; font-size: 16px; font-weight: 700; color: var(--azul); }
main > section > nav a p { margin: 0; font-size: 13.5px; line-height: 1.45; color: var(--texto-2); }
main > section > nav a span {
	margin-top: auto;
	font-size: 12.5px;
	font-weight: 600;
	color: var(--texto-3);
}

/* ---- listas de artigos: UM cartão com as linhas divididas ----
   Vale para as duas listas da home ("Mais acessados" e "Atualizados
   recentemente") e para a da categoria: em toda parte o design agrupa os artigos
   dentro de uma caixa branca só, com separador entre as linhas — não são cartões
   soltos. `main > section > ol` é sempre uma dessas listas (a tela de pesquisa
   usa `main > ul`, ver PESQUISA), então o estilo mora aqui e a categoria só
   ajusta o título. */
main > section > ol {
	overflow: hidden;                              /* corta os cantos das linhas */
	margin: 0;
	padding: 0;
	list-style: none;
	background: var(--superficie);
	border: 1px solid var(--borda);
	border-radius: var(--raio);
	counter-reset: rank;                           /* numeração de "Mais acessados" */
}
main > section > ol a {
	display: grid;
	grid-template-columns: auto minmax(0, 1fr) auto;   /* [ícone] [título / data] [chevron] */
	align-items: center;
	gap: 2px 14px;
	padding: 14px 18px;
	color: inherit;
	text-decoration: none;
	transition: background var(--transicao);
}
main > section > ol a:hover { background: var(--sutil); }
/* separador só entre linhas VISÍVEIS: `li:has(h3)` ignora os <li> vazios que o
   gerador emite (ver contorno abaixo), então não sobra divisória solta no fim */
main > section > ol > li:has(h3) ~ li:has(h3) a {
	border-top: 1px solid light-dark(rgba(0, 51, 106, 0.07), rgba(255, 255, 255, 0.09));
}
main > section > ol a > svg:first-child { /* quadrado com o ícone do artigo */
	grid-area: 1 / 1 / span 2 / span 1;
	width: 18px;
	height: 18px;
	padding: 9px;
	box-sizing: content-box;
	border-radius: 9px;
	background: var(--sutil);
	color: var(--azul);
}
main > section > ol a h3 {
	grid-area: 1 / 2;
	margin: 0;
	font-size: 14.5px;
	font-weight: 600;
	line-height: 1.35;
	color: var(--azul);
}
main > section > ol a span {
	grid-area: 2 / 2;
	font-size: 12px;
	font-weight: 400;
	color: var(--texto-3);
}
main > section > ol a > svg:last-child {
	grid-area: 1 / 3 / span 2 / span 1;
	width: 18px;
	height: 18px;
	color: var(--borda-forte);
}

/* Contorno para o bug do gerador: categoria sem artigos ainda emite um <li>
   vazio (sem <h3>) em "Atualizados recentemente". Esconde a linha e, se a
   lista ficar vazia, a seção inteira. Remover quando o gerador for corrigido. */
main > section > ol > li:not(:has(h3)) { display: none; }
main > section:has(> ol):not(:has(h3)) { display: none; }

/* ---- "Mais acessados": número de rank no lugar do ícone ----
   O gerador não emite o número (a linha é h3 + span(visualizações) +
   span(categoria) + chevron), então ele sai de um CONTADOR do CSS — enfeite de
   ::before, não nó novo. `display: none` não incrementa contador, então os <li>
   vazios do contorno acima não furam a numeração.

   O discriminante é o <h3> como PRIMEIRO filho da âncora: em "Atualizados
   recentemente" o primeiro filho é o svg do arquivo, e na linha de resultado
   (mais abaixo) também.

   Colunas: [nº] [visualizações] [categoria …] [chevron]. As duas metas são
   spans IRMÃOS, sem nada envolvendo o par, então cada uma fica na sua coluna e o
   título atravessa as duas; o "·" entre elas é ::before da segunda. */
main > section > ol > li { counter-increment: rank; }
main > section > ol a:has(> h3:first-child) {
	grid-template-columns: auto auto minmax(0, 1fr) auto;
	/* 6px é o respiro ENTRE as metas; o nº e o chevron completam os 14px da
	   linha com margem própria, porque o gap é um só para todas as colunas */
	gap: 3px 6px;
}
main > section > ol a:has(> h3:first-child)::before {
	content: counter(rank);
	grid-area: 1 / 1 / span 2 / span 1;
	width: 20px;
	margin-right: 8px;
	font-size: 15px;
	font-weight: 800;
	text-align: center;
	color: var(--borda-forte);
}
main > section > ol a:has(> h3:first-child) > h3 { grid-area: 1 / 2 / span 1 / span 2; }
main > section > ol a:has(> h3:first-child) > span:first-of-type {
	grid-area: 2 / 2;
	display: inline-flex;                          /* o olho alinha com o número */
	align-items: center;
	gap: 5px;
	white-space: nowrap;
}
main > section > ol a:has(> h3:first-child) > span:first-of-type > svg { width: 13px; height: 13px; }
main > section > ol a:has(> h3:first-child) > span + span {
	grid-area: 2 / 3;
	/* em tela estreita esta é a coluna que cede (as visualizações não quebram):
	   sem o corte, o nome da categoria vazaria por cima do chevron */
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}
main > section > ol a:has(> h3:first-child) > span + span::before {
	content: "·";
	margin-right: 6px;
}
main > section > ol a:has(> h3:first-child) > svg:last-child {
	grid-area: 1 / 4 / span 2 / span 1;            /* uma coluna mais à direita que na outra lista */
	margin-left: 8px;
}

/* ---- as duas listas LADO A LADO (home e categoria) ----
   O design põe "Mais acessados" e "Atualizados recentemente" na mesma faixa, em
   duas colunas, nas duas páginas. O gerador emite duas <section> irmãs e nada
   envolve o par, então quem forma as colunas é o próprio <main>: ele vira grade
   de duas colunas e TODO filho atravessa as duas, menos as seções de lista. É a
   mesma saída da tela de pesquisa, que também monta a grade no <main> por não ter
   um wrapper (ver PESQUISA).

   `main:has(> section > ol)` alcança só essas duas páginas: no artigo o <main> só
   tem <article>, e na pesquisa a lista é `main > ul`. As duas seções nascem e
   somem juntas (o mesmo glob alimenta as duas), então não há o caso de uma
   coluna sozinha ocupando metade da faixa.

   É a única grade do site com CONTAGEM FIXA de colunas, e não `auto-fit`: como
   as faixas de cima moram na mesma grade e atravessam tudo, um `auto-fit` de
   320px abriria uma terceira coluna nos 1240px e as duas listas ficariam com
   menos da metade da faixa cada. Quem empilha, então, é a @media de 768px —
   perto do ponto em que a coluna cairia abaixo dos 320px do design. */
main:has(> section > ol) {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	column-gap: 24px;
	/* o <main> é `flex: 1` e numa página curta sobra altura: sem isto a grade
	   distribui a folga ENTRE as faixas (`align-content: stretch` é o padrão) e
	   abre buracos entre o hero, os cartões e as listas */
	align-content: start;
}
main:has(> section > ol) > * { grid-column: 1 / -1; }
/* Em grade não há colapso de margem: na categoria os 32px de baixo da lista de
   subcategorias passariam a SOMAR com os 32px de cima da seção seguinte. Quem
   mede esse respiro é a seção, como no fluxo normal. */
main:has(> section > ol) > header ~ nav { margin-bottom: 0; }
main:has(> section > ol) > section:has(> ol) {
	grid-column: auto;
	/* as duas fecham a página juntas: `section:last-of-type` pegaria só a
	   segunda, e a primeira pode ser a mais alta (ela lista TODOS os artigos) */
	margin-bottom: 56px;
}
/* título de subseção em coluna, um degrau abaixo do "Navegue por categoria" */
main:has(> search > form) > section:has(> ol) > h2 { font-size: 19px; }
main:has(> search > form) > section:has(> ol) > h2 > svg { width: 20px; height: 20px; }

/* ---- lista da CATEGORIA: só o título muda ---- */
main > header ~ section { margin-top: 32px; }
main > header ~ section > h2 {
	display: flex;
	align-items: center;
	gap: 10px;
	margin: 0 0 14px;
	font-size: 18px;
}
main > header ~ section > h2 > svg { width: 19px; height: 19px; color: var(--teal); }

/* =========================================================================
   SUBCATEGORIA  —  main > nav:has(li:nth-child(3)) + header

   Marcação gerada (o loop de dois níveis do build.sh, o que itera
   <categoria>/<subcategoria>; escrever o glob aqui fecharia este comentário):

       main
         nav               breadcrumb de 3 níveis (Início / Fiscal / NFC-e)
         header            h1 + p(descrição, hoje sempre vazia) + span(N artigos)
         p                 <span>N</span> artigos encontrados
         ul > li > a > article    os artigos da subcategoria

   Ela NÃO repete a marcação da categoria, ao contrário do que esta seção dizia
   enquanto a página ainda não existia: a capa é a mesma, mas a lista é a da
   PESQUISA — os mesmos cartões `main > ul > li > a > article`, só sem os data-*
   que ali servem ao filtro e à ordenação. Ou seja, a pintura dos cartões toda
   vem da seção da pesquisa e não se repete aqui; deste bloco é só o que é
   próprio desta página, a capa branca e a linha de contagem.

   A capa é herdada de `main > header`, e o DISCRIMINANTE é a PROFUNDIDADE DO
   BREADCRUMB: a categoria tem 2 <li>, a subcategoria tem 3. Daí
   `main > nav:has(li:nth-child(3)) + header`. O artigo tem 4, mas o header dele
   está dentro do <article>, então não entra aqui.

   A diferença de pintura é a capa ser BRANCA em vez de azul: o cartão de
   superfície se destacando do cinza da página, com o azul só no texto. Assim a
   capa azul continua marcando "você está numa categoria" e não compete com ela
   um nível abaixo.

   O QUE O GERADOR AINDA NÃO EMITE AQUI (não inventar marcação — ver CLAUDE.md):
   o icon.svg na capa; o <nav> "CATEGORIAS" depois do </main>, que na categoria
   vira a coluna lateral (`body:has(main > header)`) e que na subcategoria não
   existe, deixando a página em largura cheia; e os data-* dos cartões.
   ========================================================================= */
main > nav:has(li:nth-child(3)) + header {
	background: var(--superficie);
	border: 1px solid var(--borda);
	box-shadow: var(--sombra-card);
	color: var(--texto);
	/* margin/padding/radius vêm de `main > header`: mantidos iguais aos da
	   categoria para a coluna lateral continuar alinhada com o topo da capa
	   (ela compensa essas medidas à mão — ver COLUNA DE CATEGORIAS). */
}
main > nav:has(li:nth-child(3)) + header > p { color: var(--texto-2); }
main > nav:has(li:nth-child(3)) + header > span { color: var(--texto-3); }
/* A subcategoria não tem arquivo `description` (só o `name` é lido; o gerador
   faz `cat` de um arquivo que não existe), então esse <p> sai VAZIO. Um <p>
   sem filho tem altura zero, mas as margens da capa da categoria continuam
   valendo: sobram 20px soltos entre o título e a contagem. Zerar o topo deixa
   os 12px que na categoria separam a descrição das contagens. */
main > nav:has(li:nth-child(3)) + header > p:empty { margin: 0 0 12px; }

/* ---- contagem: "<span>N</span> artigos encontrados" ----
   Mesmo papel do <output> da pesquisa, mas aqui o gerador emite um <p> solto
   entre a capa e a lista — e `main > p` não existe em nenhuma outra página (a
   categoria põe nav e section depois do header, o artigo só tem <article>).
   Sem esta regra ele herda o corpo: 15px em --texto, o azul cheio, com mais
   peso que os títulos dos cartões logo abaixo. */
main > header ~ p {
	margin: 0 0 12px;
	font-size: 13px;
	color: var(--texto-3);
}
main > header ~ p > span {
	font-weight: 700;
	color: var(--azul);
}

/* =========================================================================
   ARTIGO  —  main > article
   Coluna de leitura estreita; o corpo vem convertido do article.md.

   O gerador emite o Sumário DENTRO do <article> (2º filho, um <nav> com h2 +
   ol de âncoras). Para chegar na sidebar fixa do design sem mexer no HTML, o
   próprio <article> é a grade: tudo cai na coluna 1 (a coluna de leitura) e só
   esse <nav> vai para a coluna 2, esticado por todas as linhas para poder ser
   sticky. Abaixo de 1100px a grade desliga e o sumário volta ao fluxo, como
   cartão antes do texto (ver @media no fim do arquivo).
   ========================================================================= */
main > article {
	display: grid;
	grid-template-columns: minmax(0, 780px) 240px;
	justify-content: space-between;      /* leitura à esquerda, sumário na borda */
	column-gap: 48px;
	align-items: start;
}
main > article > * { grid-column: 1; min-width: 0; }

/* ------------------------------------------------------------ sumário */
main > article > nav:first-of-type {
	grid-column: 2;
	/* span alto porque o nº de blocos do artigo é desconhecido: o sticky precisa
	   de uma área de grade tão alta quanto o texto para poder acompanhar a
	   rolagem (as linhas implícitas que sobram têm altura zero). */
	grid-row: 1 / span 999;
	position: sticky;
	top: calc(var(--nav-h) + 24px);
	align-self: start;
	max-height: calc(100vh - var(--nav-h) - 48px);
	overflow-y: auto;
	overscroll-behavior: contain;
}
main > article > nav:first-of-type > h2 {        /* "Sumário" */
	margin: 0 0 12px;
	font-size: 12px;
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.5px;
	color: var(--texto-2);
}
main > article > nav:first-of-type ol {
	display: flex;
	flex-direction: column;
	gap: 2px;
	margin: 0;
	padding: 0;
	list-style: none;                              /* sem a numeração do prose */
	font-size: 13.5px;
	line-height: 1.45;
	color: inherit;
}
main > article > nav:first-of-type li { margin: 0; }
main > article > nav:first-of-type a {
	display: flex;
	align-items: flex-start;
	gap: 9px;
	padding: 7px 10px;
	border-radius: 8px;
	color: var(--texto-2);
	font-weight: 500;
	text-decoration: none;
	transition: background var(--transicao), color var(--transicao);
}
main > article > nav:first-of-type a::before {   /* marcador do design */
	content: "";
	flex: none;
	width: 6px;
	height: 6px;
	margin-top: 6px;
	border-radius: 50%;
	background: transparent;
	transition: background var(--transicao);
}
main > article > nav:first-of-type a:hover { background: var(--realce); color: var(--azul); }
/* seção em leitura: o script.js marca a âncora com aria-current (só atributo,
   nada de nó novo no DOM) */
main > article > nav:first-of-type a[aria-current] {
	background: var(--realce-teal);
	color: var(--azul);
	font-weight: 700;
}
main > article > nav:first-of-type a[aria-current]::before { background: var(--teal); }

main > article > header {
	margin: 14px 0 20px;
	padding-bottom: 16px;
	border-bottom: 1px solid var(--borda);
}
/* o primeiro bloco do texto não soma margem à do header/sumário */
main > article > header + *,
main > article > nav:first-of-type + * { margin-top: 0; }
/* etiqueta(s) do tipo do artigo — <ul><li>Tutorial</li></ul> antes do h1.
   Precisa anular as regras de lista do corpo do artigo (marcador, recuo, 16px). */
main > article > header > ul {
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
	margin: 0;
	padding: 0;
	list-style: none;
}
main > article > header > ul li {
	margin: 0;
	padding: 5px 12px;
	border-radius: 999px;
	background: var(--realce-teal);
	font-size: 12px;
	font-weight: 700;
	line-height: 1.4;
	color: var(--teal-escuro);
}

main > article > header h1 {
	margin: 0 0 12px;
	font-size: clamp(26px, 4vw, 36px);
	font-weight: 800;
	line-height: 1.15;
	letter-spacing: -0.5px;
	color: var(--azul);
}
main > article > header > ul + h1 { margin-top: 12px; }

/* "Atualizado em …" / "N min de leitura" — cada um com seu ícone. O inline-flex
   centraliza o ícone com o texto (o SVG vem 24x24 e alinhado pela baseline) e a
   margem substitui o separador "•", que dentro do flex viraria um item.
   O vertical-align faz o papel do align-items:center do mockup: os spans são
   caixas inline de alturas diferentes (o do autor tem 38px por causa do avatar),
   e sem isso eles se alinhariam pela baseline, cada um numa altura. */
main > article > header span {
	display: inline-flex;
	align-items: center;
	vertical-align: middle;
	gap: 6px;
	margin-right: 18px;
	font-size: 13px;
	font-weight: 400;
	color: var(--texto-2);
}
main > article > header span > svg { width: 15px; height: 15px; color: var(--texto-3); }

/* AUTOR — <span><span>iniciais</span><span>nome</span><span>cargo</span></span>,
   o único span do cabeçalho com <span> filho (os outros trazem ícone + texto).
   O nome do autor vem do `git log` do article.md; o cargo é fixo no gerador.

   Nome em cima e cargo embaixo, à direita do avatar — e como os três spans vêm
   irmãos, sem um nó que agrupe nome + cargo, quem empilha é uma GRADE de duas
   colunas (mesmo recurso dos callouts): o avatar ocupa as duas linhas da
   primeira coluna e nome e cargo caem sozinhos na segunda, um por linha. */
main > article > header > span:has(> span) {
	display: inline-grid;
	grid-template-columns: auto auto;
	align-items: center;
	column-gap: 10px;
	row-gap: 0;                          /* anula o gap: 6px do span de meta */
}
main > article > header > span > span { margin-right: 0; }
/* avatar: círculo azul com as iniciais */
main > article > header > span > span:first-child {
	grid-row: span 2;
	width: 38px;
	height: 38px;
	flex: none;
	justify-content: center;
	border-radius: 50%;
	background: var(--faixa);
	font-size: 13px;
	font-weight: 700;
	color: #fff;
}
main > article > header > span > span:nth-child(2) {
	font-size: 14px;
	font-weight: 700;
	line-height: 1.3;
	color: var(--azul);
}
main > article > header > span > span:nth-child(3) {
	font-size: 12.5px;
	font-weight: 400;
	line-height: 1.3;
	color: var(--texto-2);
}
/* variante em que nome e cargo vêm embrulhados num <div>: o `display: contents`
   dissolve o embrulho e devolve os dois spans à grade acima, nas mesmas linhas */
main > article > header > span > div { display: contents; }
main > article > header > span > div > span { margin-right: 0; }
main > article > header > span > div > span:first-child {
	font-size: 14px;
	font-weight: 700;
	line-height: 1.3;
	color: var(--azul);
}
main > article > header > span > div > span:last-child {
	font-size: 12.5px;
	font-weight: 400;
	line-height: 1.3;
	color: var(--texto-2);
}
/* fora de um clone do git o `git log` não devolve nada e sobraria o círculo
   azul vazio ao lado de um nome em branco (o cargo é fixo, nunca fica vazio) */
main > article > header > span:has(> span:nth-child(2):empty),
main > article > header > span:has(> div > span:first-child:empty) { display: none; }

/* corpo do artigo */
main > article h2 { margin: 26px 0 10px; font-size: 20px; font-weight: 700; color: var(--azul); }
main > article h3 { margin: 20px 0 8px; font-size: 17px; font-weight: 700; color: var(--azul); }
main > article p { margin: 0 0 16px; font-size: 16px; line-height: 1.75; color: var(--texto-corpo); }
main > article ul,
main > article ol { margin: 0 0 16px; padding-left: 24px; font-size: 16px; line-height: 1.75; color: var(--texto-corpo); }
main > article li { margin-bottom: 6px; }
main > article li::marker { color: var(--texto-3); }
main > article strong { font-weight: 700; color: var(--azul); }
main > article a { color: var(--teal-escuro); font-weight: 600; }
/* imagens do corpo: o gerador emite o <img> solto (sem <figure>/<figcaption>).
   Sem moldura — só a captura centralizada, com os cantos arredondados do resto
   do desenho. `height: auto` mantém a proporção (o Markdown só informa o width). */
main > article img {
	display: block;
	max-width: 100%;
	height: auto;
	margin: 24px auto;                   /* centraliza no bloco que a contém */
	justify-self: center;                /* … e na grade, quando é filha do <article> */
	border-radius: var(--raio-sm);
}
/* capturas dentro de passo numerado ou de citação: o recuo do bloco (padding do
   <ol> / barra do <blockquote>) deslocaria a imagem para a direita da coluna de
   leitura. O `left` devolve metade do recuo, sem afetar o fluxo — as três
   capturas do artigo ficam alinhadas no mesmo eixo. */
main > article li > img {
	position: relative;
	left: -12px;                         /* metade do padding-left: 24px do ol/ul */
}
main > article blockquote > img {
	position: relative;
	left: -10px;                         /* metade da barra + padding: 3px + 18px */
}
main > article hr { margin: 32px 0; border: none; border-top: 1px solid var(--borda); }
main > article blockquote {
	margin: 20px 0;
	padding: 2px 0 2px 18px;
	border-left: 3px solid var(--teal-transparente);
	color: var(--texto-2);
}

/* ---- lista de tarefas (checklist do GFM) ----
   `- [x] item` / `- [ ] item` viram uma lista sem marcador, com o item inteiro
   embrulhado num <label> — a caixa é irmã do texto, dentro do rótulo:

       <ul class="task-list">
         <li><label><input type="checkbox" checked="" />Item concluído</label></li>
         <li><label><input type="checkbox" />Item pendente</label></li>

   O pandoc põe uma classe na <ul>, mas ela não é usada aqui: como no resto do
   arquivo, a lista se identifica pelo CONTEÚDO (`:has`) — o conversor de Markdown
   já mudou duas vezes, e o :has sobrevive à troca do nome da classe.

   A CAIXA é A MESMA das facetas da pesquisa, que é o único componente de
   checkbox do padrão de design: quadrado de 18px, raio 5px, borda de 2px, e
   marcada vira turquesa cheio com o check branco. Mesma técnica, pelos mesmos
   motivos: `appearance: none` (o JS não pode criar nós, e não há como envolver o
   input num <span>), o check como data-URI do Lucide `check` (pseudo-elemento em
   input, que é elemento substituído, não é confiável), branco literal em vez de
   token porque o fundo por baixo é sempre o turquesa, e traço 3 para o check não
   desaparecer desenhado a 12px.
   NÃO é o quadrado verde de 22px do "checklist de pré-requisitos" do mockup:
   aquele é decoração de item já concluído, e estas caixas são controles de
   verdade — o pandoc as emite habilitadas, com os dois estados. */
main > article ul:has(> li > label > input[type="checkbox"]) {
	padding-left: 0;
	list-style: none;
}
main > article ul:has(> li > label > input[type="checkbox"]) > li { margin-bottom: 10px; }
/* O rótulo NÃO pode ser flex: num container flex cada <code>, <em> ou <strong>
   do item viraria um item de flex próprio e o trecho sairia numa "coluna"
   separada do texto normal — bem visível no mobile, onde a linha é curta. Daí o
   recuo pendente: `padding-left` alinha TODAS as linhas em 28px e o
   `text-indent` negativo devolve só a primeira, que é a que leva a caixa. O
   conteúdo continua inline, como o parágrafo. */
main > article label:has(> input[type="checkbox"]) {
	display: block;
	padding-left: 28px;                  /* 18px da caixa + 10px de respiro */
	text-indent: -28px;                  /* a caixa "pendura" à esquerda do texto */
	cursor: pointer;
}
main > article label > input[type="checkbox"] {
	appearance: none;
	width: 18px;
	height: 18px;
	margin-right: 10px;
	/* centraliza a caixa na primeira linha do texto (line-height de 28px): ~3px
	   abaixo da linha de base deixam a folga de cima e a de baixo iguais */
	vertical-align: -3px;
	border: 2px solid var(--borda-forte);
	border-radius: 5px;
	background: transparent no-repeat center / 12px 12px;
	cursor: pointer;
	transition: background-color var(--transicao), border-color var(--transicao);
}
main > article label:hover > input[type="checkbox"]:not(:checked) { border-color: var(--teal); }
main > article label > input[type="checkbox"]:checked {
	border-color: var(--teal);
	background-color: var(--teal);
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E");
}
/* versões do pandoc que emitem a caixa desabilitada: aí ela é só marca, sem clique */
main > article label:has(> input[type="checkbox"]:disabled),
main > article label > input[type="checkbox"]:disabled { cursor: default; }

/* ---- callouts (alertas do GFM) ----
   `> [!NOTE]` & cia. viram um <div> com a classe do tipo, o ícone Lucide
   injetado como primeiro filho e o rótulo já traduzido:

       <div class="note">
         <svg …>
         <div class="title"><p>Nota</p></div>
         <p>corpo…</p>
       </div>

   São as ÚNICAS classes que o gerador emite; fora daqui o arquivo seletora só
   tags (ver o cabeçalho). Como o ícone e o corpo NÃO estão agrupados em um
   wrapper, o layout é uma grade de duas colunas em vez do flex do design: o SVG
   fica travado em 1/1 e todo o resto é empurrado para a coluna 2 — assim o corpo
   aceita qualquer conteúdo (vários parágrafos, listas, código, tabela).

   O TÍTULO é sempre azul; o ÍCONE leva a cor da variante (--callout-icone), o
   matiz do fundo em claridade cheia, para dizer o tipo do callout de relance. Os
   seis fundos do design são TINTAS SÓLIDAS pálidas, não véus rgba — cada um com
   o matiz da sua variante — e por isso não dependem do que está atrás: funcionam
   igual sobre o cinza da página e sobre o branco de um cartão.

   Escala de ênfase, do menos ao mais grave:
   nota (azul) → dica (violeta) → importante (cinza-azulado) → aviso (bege) →
   cuidado (vermelho); fora da escala, pronto (verde), que fecha tutorial.

   .success ("Pronto!") AINDA NÃO É EMITIDO: o GFM só tem os cinco alertas e o
   pandoc não conhece `> [!SUCCESS]`. O estilo fica escrito aqui esperando o
   gerador, como o da subcategoria. */
main > article :is(.note, .tip, .important, .warning, .caution, .success) {
	--callout-icone: var(--azul);
	--callout-fundo: light-dark(#e3edfb, #1f2e41);
	--callout-borda: light-dark(#b7cef0, #3b506d);
	display: grid;
	grid-template-columns: 22px minmax(0, 1fr);
	column-gap: 12px;
	margin: 20px 0;
	padding: 16px 18px;
	border: 1px solid var(--callout-borda);
	border-radius: var(--raio-sm);
	background: var(--callout-fundo);
}
/* Nenhuma das seis tintas do design sobrevive ao tema escuro — pálido sobre
   carvão viraria uma faixa clara no meio do artigo. O escuro mantém o MATIZ de
   cada variante e troca a claridade: fundo em L 19% e borda em L 33%, na mesma
   faixa das superfícies escuras (--sutil é #1e2b39). O ícone inverte junto:
   escuro sobre a tinta clara, claro sobre a tinta escura. A nota não precisa de
   valor próprio — seu matiz é o azul, então ela fica com o --azul do bloco base,
   que já troca de claridade sozinho. */
main > article .tip {
	--callout-icone: light-dark(#6d3fa5, #c9a9f0);
	--callout-fundo: light-dark(#efe6f7, #321f41);
	--callout-borda: light-dark(#d6c2ec, #563b6d);
}
main > article .important {
	--callout-icone: light-dark(#1e8449, #58d98a);
	--callout-fundo: light-dark(#e1f5e9, #1f412d);
	--callout-borda: light-dark(#B8e0c5, #3b6d4f);
}
main > article .warning {
	--callout-icone: light-dark(#b8860b, #f0cb5c);
	--callout-fundo: light-dark(#fdf3e8, #41311f);
	--callout-borda: light-dark(#f2dabd, #6d553b);
}
main > article .caution {
	--callout-icone: light-dark(#c0392b, #ff8574);
	--callout-fundo: light-dark(#fbe2e1, #41211f);
	--callout-borda: light-dark(#ef8380, #6d3d3b);
}
main > article .success {
	--callout-icone: light-dark(#1e8449, #58d98a);
	--callout-fundo: light-dark(#e1f5e9, #1f412d);
	--callout-borda: light-dark(#B8e0c5, #3b6d4f);
}
/* o ícone vem 24x24 do arquivo em icons/ e herda a cor da variante */
main > article :is(.note, .tip, .important, .warning, .caution, .success) > svg {
	grid-area: 1 / 1;
	width: 22px;
	height: 22px;
	color: var(--callout-icone);
}
main > article :is(.note, .tip, .important, .warning, .caution, .success) > :not(svg) {
	grid-column: 2;
}
/* corpo: um passo abaixo do texto do artigo (16px) */
main > article :is(.note, .tip, .important, .warning, .caution, .success) :is(p, ul, ol) {
	font-size: 14.5px;
	line-height: 1.65;
	color: var(--texto-2);
}
main > article :is(.note, .tip, .important, .warning, .caution, .success) > *:last-child { margin-bottom: 0; }
/* rótulo: o <p> dentro de .title carrega o nome do tipo ("Nota", "Dica", …).
   SEMPRE azul, como no design — quem colore por variante é o ícone (e o fundo e
   a borda), nunca o texto. line-height 22px o alinha com o ícone da mesma
   altura, sem margem extra. */
main > article .title { margin: 0 0 6px; }
main > article .title p {
	margin: 0;
	font-size: 14.5px;
	font-weight: 700;
	line-height: 22px;
	color: var(--azul);
}

main > article code {
	padding: 2px 6px;
	/* trecho longo sem espaço (caminho, comando) não cabe na linha estreita do
	   mobile e vazaria para fora da coluna: aqui ele pode quebrar no meio */
	overflow-wrap: break-word;
	border-radius: 6px;
	background: var(--sutil);
	font-family: ui-monospace, 'Cascadia Code', Consolas, monospace;
	font-size: 0.9em;
	color: var(--azul);
}
/* bloco de código: fundo azul escuro com texto claro, como no design. O gerador
   não emite a barra superior com nome do arquivo e botão "Copiar", então só o
   <pre> carrega a moldura. */
main > article pre {
	margin: 0 0 20px;
	padding: 16px 18px;
	overflow-x: auto;
	/* o trilho herdado do <html> é o cinza da página e brilharia dentro do
	   bloco escuro: aqui ele é o fundo do próprio bloco */
	scrollbar-color: var(--borda-forte) var(--azul-escuro);
	border: 1px solid var(--azul-quase-preto);
	border-radius: var(--raio-sm);
	background: var(--azul-escuro);
	line-height: 1.7;
	color: var(--codigo-texto);
}
main > article pre code {
	padding: 0;
	background: none;
	color: inherit;
}
/* ---- tabelas ----
   No design a tabela vive dentro de um <div> com borda, raio e overflow hidden;
   o gerador emite a <table> solta, então a moldura vai na própria tabela. Isso
   exige `border-collapse: separate`: com `collapse` o raio da tabela não recorta
   o fundo das células, e os cantos do cabeçalho azul vazariam. Como o desenho
   separa as linhas por zebra (e não por régua), nenhuma célula tem borda — daí
   `border-spacing: 0` não deixa rastro. */
main > article table {
	width: 100%;
	margin: 14px 0 20px;
	border: 1px solid var(--borda);
	border-radius: var(--raio-sm);
	border-collapse: separate;
	border-spacing: 0;
	/* o branco é o "par" da zebra: sem ele a linha ímpar mostraria o cinza da
	   página (--fundo), que é quase igual ao --sutil e apagaria o zebrado */
	background: var(--superficie);
	font-size: 14px;
	line-height: 1.55;
}
main > article thead tr { background: var(--faixa); color: #fff; }
main > article th {
	padding: 11px 14px;
	font-weight: 700;
	text-align: left;
	color: inherit;                                /* branco, herdado do <tr> */
}
main > article td {
	padding: 11px 14px;
	border: none;
	color: var(--texto-corpo);
	vertical-align: middle;
}
main > article tbody tr:nth-child(even) { background: var(--sutil); }
main > article tbody td:first-child { font-weight: 700; color: var(--azul); }
/* cantos: com `separate`, quem arredonda são as células das pontas */
main > article thead tr:first-child th:first-child { border-top-left-radius: 11px; }
main > article thead tr:first-child th:last-child { border-top-right-radius: 11px; }
main > article tbody tr:last-child td:first-child { border-bottom-left-radius: 11px; }
main > article tbody tr:last-child td:last-child { border-bottom-right-radius: 11px; }
main > article > *:last-child { margin-bottom: 56px; }

/* =========================================================================
   ARTIGOS RELACIONADOS  —  body > main + aside
   Só o artigo emite este bloco, e o gerador o coloca FORA do <main>, entre ele
   e o rodapé:

       aside > h2 + ul > li > a > article
                                    p    nome da categoria do artigo
                                    h3   título
                                    p    svg(relógio) + tempo de leitura

   No design ele é o último bloco DENTRO da coluna de leitura, depois do painel
   de feedback (que o gerador não emite). Como aqui ele nasce irmão do <main>,
   repete o gutter da página e a largura da coluna de leitura (os 780px da grade
   de `main > article`), para as bordas dos cartões se alinharem com o texto
   acima. Abaixo de 1100px passa a acompanhar o --gutter-artigo, junto do main
   (ver o responsivo no fim do arquivo).

   LAYOUT: UM ARTIGO POR LINHA, como as outras listagens do site ("Atualizados
   recentemente" na home e a lista da categoria) — não a grade de cartões lado a
   lado do mockup. Cada linha repete a anatomia dessas listas: título em cima,
   meta embaixo e o tempo de leitura à direita, centralizado na altura da linha.
   As cores e os tamanhos continuam sendo os do mockup.
   ========================================================================= */
body > main + aside {
	padding: 0 var(--gutter) 44px;
}
/* alinhamento com a coluna de leitura (o resto da largura é do sumário) */
body > main + aside > * { max-width: 780px; }

body > main + aside > h2 {
	margin: 0 0 14px;
	font-size: 20px;
	font-weight: 700;
	color: var(--azul);
}
body > main + aside > ul {
	display: grid;                       /* uma coluna: um artigo por linha */
	gap: 10px;
	margin: 0;
	padding: 0;
	list-style: none;
}
/* a âncora é só a área clicável; quem desenha o cartão é o <article> */
body > main + aside a {
	display: block;
	color: inherit;
	text-decoration: none;
}
body > main + aside a:hover { color: inherit; }
/* Colunas: [título / categoria] [tempo de leitura]. Grade (e não flex) porque a
   ordem do HTML é categoria → título → tempo: as áreas explícitas sobem o título
   para a 1ª linha sem depender da ordem em que o gerador emite. */
body > main + aside article {
	display: grid;
	grid-template-columns: minmax(0, 1fr) auto;
	align-items: center;
	gap: 2px 14px;
	padding: 14px 18px;
	background: var(--superficie);
	border: 1px solid var(--borda);
	border-radius: var(--raio-sm);
	transition: border-color var(--transicao), transform var(--transicao), box-shadow var(--transicao);
}
body > main + aside a:hover article {
	border-color: var(--teal-transparente);
	transform: translateY(-1px);
	box-shadow: var(--sombra-card);
}
body > main + aside article h3 {
	grid-area: 1 / 1;
	margin: 0;
	font-size: 15px;
	font-weight: 700;
	line-height: 1.35;
	color: var(--azul);
}
body > main + aside article > p:first-of-type {   /* categoria */
	grid-area: 2 / 1;
	margin: 0;
	font-size: 12px;
	font-weight: 600;
	color: var(--teal-escuro);
}
/* tempo de leitura: o número é um nó de texto solto ao lado do svg (item flex
   ANÔNIMO, sem seletor possível), então o espaço entre os dois vem do gap */
body > main + aside article > p:last-of-type {
	grid-area: 1 / 2 / span 2 / span 1;
	display: flex;
	align-items: center;
	gap: 5px;
	margin: 0;
	font-size: 12px;
	color: var(--texto-3);
	white-space: nowrap;
}
body > main + aside article > p:last-of-type > svg { width: 13px; height: 13px; }

/* Contorno para o gerador: quando nenhum outro artigo casa as `keywords`, o
   <aside> ainda vem com o título e uma lista VAZIA. Esconde o bloco inteiro.
   Remover quando o build.sh deixar de emiti-lo nesse caso. */
body > main + aside:not(:has(li)) { display: none; }

/* =========================================================================
   COLUNA DE CATEGORIAS  —  body > main + nav
   Lista de todas as categorias (ícone + nome + nº de artigos). O gerador a
   emite FORA do <main>, entre ele e o rodapé, e em todas as páginas menos a
   home.

   No design ela é a coluna DIREITA da página de categoria: 240px, sticky sob a
   navbar, ao lado da capa azul. Para chegar lá sem marcação nova, o próprio
   <body> vira a grade nessa página (ver @media 1000px): header e rodapé
   atravessam as duas colunas, o main fica na 1 e este <nav> na 2.

   O estado base abaixo é o do fluxo normal — usado no artigo (onde o design
   reserva a coluna direita para o sumário) e em tela estreita: um bloco de
   chips no fim da página.
   ========================================================================= */
body > main + nav {
	padding: 0 var(--gutter) 44px;
}
/* separador: no fluxo a lista encosta no conteúdo de cima, e o design não
   prevê esse estado (lá a lista é sempre coluna) */
body > main + nav > h2 {                           /* "CATEGORIAS" */
	margin: 0 0 12px;
	padding-top: 20px;
	border-top: 1px solid var(--borda);
	font-size: 12px;
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.5px;
	color: var(--texto-2);
}
body > main + nav > ul {
	display: flex;
	flex-wrap: wrap;
	gap: 2px;
	margin: 0;
	padding: 0;
	list-style: none;
}
/* item: [ícone] [nome] [contagem]. O nome é um nó de texto solto (item flex
   ANÔNIMO, sem seletor possível), então a contagem é empurrada para a direita
   pela própria margem, não por um flex:1 no nome. */
body > main + nav a {
	display: flex;
	align-items: center;
	gap: 10px;
	padding: 8px 10px;
	border-radius: 8px;
	font-size: 13.5px;
	font-weight: 500;
	color: var(--texto-2);
	text-decoration: none;
	transition: background var(--transicao), color var(--transicao);
}
body > main + nav a > svg {
	width: 17px;
	height: 17px;
	color: var(--texto-3);
	transition: color var(--transicao);
}
body > main + nav a > span {                       /* nº de artigos */
	margin-left: auto;
	font-size: 12px;
	font-weight: 400;
	color: var(--borda-forte);
}
/* O realce do design (#f4f5f9) desapareceria sobre o fundo cinza da página —
   mesma troca já feita no sumário do artigo (ver tokens --realce*). */
body > main + nav a:hover { background: var(--realce); color: var(--azul); }
/* categoria da página atual: o script.js marca o link com aria-current="page"
   (só atributo, nada de nó novo no DOM) */
body > main + nav a[aria-current] {
	background: var(--realce-teal);
	color: var(--azul);
	font-weight: 700;
}
body > main + nav a[aria-current] > svg { color: var(--teal); }

/* ---- coluna lateral: só na categoria e só quando as duas colunas cabem ----
   (o design mostra a coluna a partir de ~1000px) */
@media (min-width: 1000px) {
	body:has(main > header):has(> main + nav) {
		display: grid;
		/* a 2ª coluna carrega o gutter direito, senão os 240px do design ficariam
		   colados na borda da janela */
		grid-template-columns: minmax(0, 1fr) calc(240px + var(--gutter));
		grid-template-rows: auto 1fr auto;         /* navbar · conteúdo · rodapé */
		column-gap: 40px;
	}
	/* Todas as regras deste bloco precisam do `:has(> main + nav)`, não só a que
	   monta a grade: a capa `main > header` é compartilhada com a SUBCATEGORIA, e
	   lá o gerador não emite a lista de categorias (ver bugs do gerador). Sem a
	   guarda, aquela página perdia o `padding-right` do <main> sem ganhar a 2ª
	   coluna que devolve o gutter, e o conteúdo ia até a borda da janela. */
	body:has(main > header):has(> main + nav) > header,
	body:has(main > header):has(> main + nav) > footer { grid-column: 1 / -1; }
	body:has(main > header):has(> main + nav) > main { padding-right: 0; }

	body:has(main > header) > main + nav {
		position: sticky;
		top: calc(var(--nav-h) + 24px);
		align-self: start;
		/* margem superior: alinha o rótulo com o topo da capa azul — 20px da margem
		   do breadcrumb + a altura dele (13px x 1.5) + 22px da margem da capa.
		   Margem (e não padding) à direita para a coluna medir os 240px do design
		   e a barra de rolagem nascer junto do conteúdo, não na borda da janela. */
		margin: calc(42px + 13px * 1.5) var(--gutter) 0 0;
		padding: 0;
		max-height: calc(100vh - var(--nav-h) - 48px);
		overflow-y: auto;
		overscroll-behavior: contain;
	}
	body:has(main > header) > main + nav > h2 {
		padding-top: 0;
		border-top: none;
	}
	body:has(main > header) > main + nav > ul { flex-direction: column; flex-wrap: nowrap; }
}

/* =========================================================================
   RODAPÉ  —  body > footer
   grid: [logo] [nav] [nav] [address] + <p> de copyright ocupando a linha.
   ========================================================================= */
body > footer {
	margin-top: 8px;
	padding: 44px var(--gutter) 0;
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
	gap: 28px 32px;
	align-items: start;
	background: var(--faixa);
	color: #fff;
}
body > footer > svg:first-child {                 /* logo 713x214 branco */
	display: block;
	height: 32px;
	width: auto;
}
body > footer h2 {
	margin: 0 0 14px;
	font-size: 12px;
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.5px;
	color: rgba(255, 255, 255, 0.5);
}
body > footer ul { margin: 0; padding: 0; list-style: none; }
body > footer li { margin-bottom: 10px; }
body > footer a {
	display: inline-flex;
	align-items: center;
	gap: 9px;
	color: rgba(255, 255, 255, 0.8);
	font-size: 13.5px;
	text-decoration: none;
	transition: color var(--transicao);
}
body > footer a:hover { color: var(--teal); }
body > footer a svg { width: 16px; height: 16px; }
body > footer address { font-style: normal; }
body > footer address a { display: flex; margin-bottom: 10px; }
body > footer address br { display: none; }       /* os <a> já são blocos */
body > footer > p {
	grid-column: 1 / -1;
	margin: 0;
	padding: 18px 0;
	border-top: 1px solid rgba(255, 255, 255, 0.12);
	font-size: 12.5px;
	color: rgba(255, 255, 255, 0.55);
}

/* ---------------------------------------------------------------- responsivo */

/* PESQUISA EM COLUNA ÚNICA: abaixo de 1000px — o mesmo limite em que a coluna
   de categorias deixa de existir — filtros e ordenação não cabem ao lado dos
   resultados. Todas as áreas de grade voltam a `auto` e os itens caem na ordem
   do documento: campo de busca, filtros, ordenação, contagem, resultados. O
   painel de filtros perde o sticky — grudado no topo, em coluna única, ele
   cobriria a lista inteira. */
@media (max-width: 999px) {
	main:has(> search > output) { grid-template-columns: minmax(0, 1fr); }
	main:has(> search > output) > nav:first-of-type,
	main:has(> search > output) > ul,
	main > search > div,
	main > search > section,
	main > search > fieldset,
	main > search > output { grid-area: auto; }
	main > search > section {
		position: static;
		max-height: none;
		overflow: visible;
	}
	/* sem a coluna da direita não há o que alinhar à borda: a cápsula de ordenação
	   segue o mesmo eixo esquerdo do resto da página */
	main > search > fieldset { justify-self: start; }
	main > search > output { align-self: auto; }
}

/* TELA ESTREITA: não cabem coluna de leitura (780px) + sumário (240px) lado a
   lado. O artigo volta a ser uma coluna só, centralizada e estreita, e o
   sumário vira um cartão no fluxo, antes do texto. */
@media (max-width: 1100px) {
	body:has(main > article) main { padding-inline: var(--gutter-artigo); }
	/* a lista de categorias acompanha a coluna de leitura */
	body:has(main > article) > main + nav { padding-inline: var(--gutter-artigo); }
	/* … e os artigos relacionados também (o max-width de 780px fica inerte: a
	   coluna de leitura já é mais estreita que isso daqui para baixo) */
	body > main + aside { padding-inline: var(--gutter-artigo); }
	main > article { display: block; }
	main > article > nav:first-of-type {
		position: static;
		max-height: none;
		margin: 0 0 30px;
		padding: 16px 18px;
		background: var(--superficie);
		border: 1px solid var(--borda);
		border-radius: var(--raio-sm);
	}
}

/* LISTAS EM COLUNA ÚNICA: as duas listas lado a lado só se sustentam enquanto cada
   coluna tem os 320px que o design pede — abaixo disso o título de artigo quebra
   em três linhas e a meta não cabe numa. Empilhadas, o respiro de 56px volta a
   ser só da última: nas duas ele somaria com o margin-top da seguinte. */
@media (max-width: 768px) {
	main:has(> section > ol) { grid-template-columns: minmax(0, 1fr); }
	main:has(> section > ol) > section:not(:last-of-type) { margin-bottom: 0; }
}

/* CELULAR: só aqui o hambúrguer existe, e só aqui o menu lateral pode abrir.
   O painel e o véu passam a existir sempre (para a animação ter de onde sair) e
   o estado aberto/fechado é só transform + visibility + opacity. */
@media (max-width: 768px) {
	body > header > button:first-of-type {
		display: inline-flex;
		/* acima do painel e do véu: o botão não é coberto pelo drawer */
		position: relative;
		z-index: 3;
		/* Compensação ÓPTICA do gap: o botão é 40x40 com ícone de 22px, logo tem
		   9px de vazio de cada lado do traço, e o gap de 14px do header vinha
		   somado a esse vazio — 23px até o logo, contra os 14px do logo até a
		   caixa da busca (que tem fundo, então a borda dela é onde o gap acaba).
		   O -11px devolve o vazio e deixa esse lado um fio mais apertado. */
		margin-right: -11px;
		transition: background var(--transicao), transform 0.22s ease;
	}
	body > header > nav { display: flex; }
	body > header::after { display: block; }

	/* no celular a marca é só o logo: "Central de Ajuda" é um nó de TEXTO solto
	   no <a> (sem seletor possível), então quem o apaga é o font-size: 0 — o svg
	   não se mexe porque tem altura explícita. Sem o texto, o traço divisório
	   (::before) e o gap também saem. */
	body > header > a { gap: 0; font-size: 0; }
	body > header > a::before { display: none; }

	/* no celular o sumário sai de vez: como cartão no fluxo (regra dos 1100px)
	   ele empurra o texto do artigo para baixo da dobra, e a mesma navegação já
	   se resolve rolando. O scrollspy do script.js continua marcando âncoras
	   invisíveis, o que é inofensivo. */
	main > article > nav:first-of-type { display: none; }

	/* META DO ARTIGO NUMA TELA ESTREITA: autor, data, tempo de leitura e views são
	   <span> inline soltos no header, sem um nó que os agrupe — o respiro entre as
	   linhas que sobram da quebra não pode vir de row-gap. Como cada um é
	   inline-flex (caixa inline atômica), a margem VERTICAL vale neles, e é ela que
	   separa as linhas; o padding do header encurta para descontar a margem da
	   última, mantendo os 16px até a divisória. */
	main > article > header { padding-bottom: 6px; }
	main > article > header > span { margin-bottom: 10px; }
	/* no celular a meta fica só com data e tempo de leitura, numa linha:
	   - AUTOR: é o único span do header com <span> filho. Com 38px de avatar contra
	     13px de texto das outras metas, era ele que apertava a linha;
	   - VIEWS: o último span (a ordem do gerador é autor, data, leitura, views). */
	main > article > header > span:has(> span),
	main > article > header > span:last-of-type { display: none; }

	body > header:has(> button[aria-expanded="true"]) > nav {
		visibility: visible;
		transform: none;
	}

	/* ABERTO: o hambúrguer atravessa a barra de título do drawer e vira o
	   "fechar" no canto direito do painel — o ícone some e o X é desenhado com
	   os pseudos. O translate mantém o botão no fluxo do header (nada se
	   desloca) e desliza junto do painel. Alvo: 12px da borda direita do painel,
	   ou seja largura - 12 - 40 do botão; a origem é o gutter do header.
	   Verticalmente já está centrado, porque a barra de título tem a mesma
	   altura da navbar.
	   `:first-of-type` em TODAS estas: o `:has()` só testa que o painel está
	   aberto, e sem ele o sujeito `> button` levaria o botão de tema junto. */
	body > header:has(> button[aria-expanded="true"]) > button:first-of-type {
		transform: translateX(calc(var(--drawer-w) - 52px - var(--gutter)));
	}
	body > header:has(> button[aria-expanded="true"]) > button:first-of-type > svg { display: none; }
	body > header:has(> button[aria-expanded="true"]) > button:first-of-type::before,
	body > header:has(> button[aria-expanded="true"]) > button:first-of-type::after {
		content: "";
		position: absolute;
		top: 50%;
		left: 50%;
		width: 18px;
		height: 2px;
		margin: -1px 0 0 -9px;
		border-radius: 2px;
		background: currentColor;
	}
	body > header:has(> button[aria-expanded="true"]) > button:first-of-type::before { transform: rotate(45deg); }
	body > header:has(> button[aria-expanded="true"]) > button:first-of-type::after { transform: rotate(-45deg); }
	body > header:has(> button[aria-expanded="true"])::after {
		opacity: 1;
		pointer-events: auto;
	}
	/* com o painel aberto a página de trás não rola */
	html:has(> body > header > button[aria-expanded="true"]) { overflow: hidden; }

	/* Fallback sem JS: o script marca o hambúrguer com aria-expanded ao iniciar;
	   se o atributo não existe, ele não rodou — aí abre com o foco no header. O
	   botão acompanha o canto direito do painel (senão cobriria o título), mas
	   segue com o ícone de hambúrguer: sem JS ele não fecha nada, quem fecha é
	   tirar o foco.
	   O `:first-of-type` dentro do :has() é obrigatório: o botão de tema NUNCA
	   tem aria-expanded, então sem ele a condição passaria a valer sempre e o
	   drawer abriria a cada foco no header, com JS e tudo. */
	body > header:has(> button:first-of-type:not([aria-expanded])):focus-within > button:first-of-type {
		transform: translateX(calc(var(--drawer-w) - 52px - var(--gutter)));
	}
	body > header:has(> button:first-of-type:not([aria-expanded])):focus-within > nav {
		visibility: visible;
		transform: none;
	}
	body > header:has(> button:first-of-type:not([aria-expanded])):focus-within::after {
		opacity: 1;
		pointer-events: auto;
	}
}

@media (max-width: 640px) {
	/* o painel lateral fica mais largo, mas sempre deixa ver o véu à direita
	   (o token move o painel E o botão de fechar, que se ancora na borda dele) */
	:root { --drawer-w: min(320px, 86vw); }

	/* a coluna de leitura fica tão estreita quanto a captura: compensar o recuo
	   do passo/citação aqui faria a imagem vazar pela esquerda */
	main > article li > img,
	main > article blockquote > img { left: 0; }

	/* barra apertada: a busca deixa de mirar 320px e fica com o que sobrar do
	   hambúrguer e do logo, com menos respiro interno para o campo não virar um
	   talo de 80px */
	body > header > search { flex: 1 1 auto; }
	body > header form { gap: 7px; padding: 0 10px; }

	main > search:has(> form) { padding-block: 52px 60px; }
	main > search:has(> form) form > div { flex-wrap: wrap; padding: 10px; }
	main > search:has(> form) form > div > svg { margin-left: 8px; }
	main > search:has(> form) form button { width: 100%; }
	main > section > header { flex-direction: column; align-items: flex-start; gap: 4px; }
	/* só a home: na categoria as linhas já são grid com o título em cima da data */
	main > search:has(> form) ~ section > ol a { flex-wrap: wrap; }
	main > search:has(> form) ~ section > ol a h3 { flex: 1 0 100%; order: -1; }
	main > header { padding: 20px; }
	/* a coluna de texto ao lado do ícone sobraria com ~200px num celular: aqui o
	   quadrado volta para o fluxo e fica ACIMA do título, em largura cheia */
	main > header:has(> svg:first-child) { padding-left: 20px; }
	main > header > svg:first-child {
		position: static;
		display: block;
		margin-bottom: 14px;
	}
	main > header ~ nav > ul { grid-template-columns: 1fr; }

	/* PESQUISA: painel, abas e cartões perdem respiro para o texto sobrar mais
	   largo (o design compacta a partir de 720px; aqui usamos a faixa que o
	   arquivo já tem) */
	main:has(> search > output) { row-gap: 12px; }
	main > search > section { padding: 14px; }
	main > search > fieldset > label { height: 28px; padding: 0 10px; font-size: 12.5px; }
	main > ul article { padding: 14px; }
	main > ul article h3 { font-size: 15px; }
	/* tabela: célula mais apertada e quebra de palavra longa, para caber sem
	   rolagem horizontal (a <table> vem solta, sem wrapper onde rolar) */
	main > article th,
	main > article td { padding: 9px 10px; }
	main > article table { font-size: 13.5px; }
	main > article td { overflow-wrap: break-word; }

	/* SUBCATEGORIA: nada próprio aqui. A capa segue o `main > header` acima e a
	   lista é a mesma da pesquisa, então o `main > ul article` desta faixa já a
	   compacta. */
}

/* =========================================================================
   BARRA DE ROLAGEM ABAIXO DA NAVBAR  —  desktop (>= 1000px)

   A barra de rolagem pertence à CAIXA que rola. Enquanto quem rola é o
   documento, ela corre de ponta a ponta da janela — inclusive ao lado da
   navbar, que é fixa e não rola coisa nenhuma. Aqui a rolagem passa para o
   <body>: o <html> deixa de rolar, o <body> vira a caixa (uma janela de
   altura menos a navbar, encostada abaixo dela) e o <header> sai do fluxo,
   fixo no topo. Assim o trilho começa no corpo da página.

   Não dá para fazer isso só com o trilho: nenhuma propriedade encurta a barra
   do documento. E não dá para embrulhar <main> + <footer> num contêiner que
   role, porque o gerador não emite esse nó (ver "Fluxo de edição" no
   CLAUDE.md) — daí a troca de quem rola.

   O limite é o mesmo 1000px das colunas laterais. Abaixo dele quem rola segue
   sendo o documento: no celular a barra é sobreposta (não ocupa largura, não
   encosta na navbar) e é a rolagem do documento que recolhe a barra de
   endereço do navegador.

   Quem lê essa troca do lado do JS é o `caixaDeRolagem()` do script.js, pelo
   overflow computado do <body> — a regra abaixo é a única fonte da verdade.
   ========================================================================= */
@media (min-width: 1000px) {
	html {
		height: 100%;
		overflow: hidden;                    /* tira a rolagem do documento */
	}
	body {
		margin-top: var(--nav-h);            /* a caixa começa abaixo da navbar */
		height: calc(100% - var(--nav-h));
		min-height: 0;                       /* senão o 100vh da base venceria */
		overflow-y: auto;
		/* o scroll-behavior e o scroll-padding do <html> valem para a caixa
		   DELE; esta caixa é outra. O desconto da navbar aqui não é mais
		   necessário — a caixa já começa embaixo dela —, sobra o respiro. */
		scroll-behavior: smooth;
		scroll-padding-top: 12px;
	}
	/* O header não pode viver dentro da caixa que rola. Fixo, ele volta a medir
	   a janela INTEIRA, enquanto o conteúdo mede a janela menos a barra de
	   rolagem: o --barra (medido no script.js) devolve essa diferença, senão a
	   busca da navbar fica alguns pixels à direita da coluna que ela encima. */
	body > header {
		position: fixed;
		top: 0;
		left: 0;
		right: 0;
		padding-right: calc(var(--gutter) + var(--barra, 0px));
	}
	/* a grade da categoria perde a linha do header, que saiu do fluxo: sobram
	   conteúdo (1fr) e rodapé */
	body:has(main > header):has(> main + nav) { grid-template-rows: 1fr auto; }
	/* Os sticky se medem pelo topo da CAIXA, que já começa abaixo da navbar:
	   descontá-la de novo empurraria as colunas 64px para baixo. Os max-height
	   continuam em 100vh - --nav-h, que é justamente a altura da caixa. */
	main > search > section { top: 16px; }
	main > article > nav:first-of-type { top: 24px; }
	body:has(main > header) > main + nav { top: 24px; }
}

@media (prefers-reduced-motion: reduce) {
	html { scroll-behavior: auto; }
	body { scroll-behavior: auto; }        /* a caixa do desktop, idem */
	*, *::before, *::after { transition-duration: 0.01ms; }
}
