/*
 * ═══════════════════════════════════════════════════════════════════════════════════════════
 *  LUMINA 7 — a folha de estilo do blog
 * ═══════════════════════════════════════════════════════════════════════════════════════════
 *
 *  Um arquivo só, enfileirado no `<head>`. O porquê de não haver inline de "CSS crítico" está
 *  no comentário de `lumina7_enqueue_assets()` em `functions.php`.
 *
 *  ── Ordem das seções ──────────────────────────────────────────────────────────────────────
 *   1. Tokens (claro, escuro por preferência, escuro/claro por escolha)
 *   2. Reset e base
 *   3. Utilidades (sr-only, skip link, botões)
 *   4. Cabeçalho e rodapé
 *   5. Grade do artigo, índice, coluna lateral
 *   6. Tipografia do texto (.l-prose) — o coração do produto
 *   7. Conversão (card, CTA do meio, bloco de oferta, barra fixa)
 *   8. Listagens, paginação, busca, 404
 *   9. Movimento e impressão
 */

/* ─── 1. TOKENS ──────────────────────────────────────────────────────────────────────────────
 *
 * As três declarações do tema seguem a mesma disciplina de qualquer página que respeita a
 * preferência do sistema E oferece um botão:
 *
 *   :root                                        → paleta clara COMPLETA (o default)
 *   @media (prefers-color-scheme: dark)
 *     :root:not([data-theme="light"])             → escuro por preferência do sistema
 *   :root[data-theme="dark"]                      → escuro por ESCOLHA, vence em qualquer caso
 *
 * O `:not([data-theme="light"])` é o que faz o botão funcionar nos DOIS sentidos: sem ele,
 * quem está no escuro por preferência do sistema e clica em "claro" não vê nada mudar, porque
 * a media query continuaria sobrescrevendo.
 *
 * Nenhuma cor tem sua ÚNICA definição dentro de um bloco de media query ou de `[data-theme]` —
 * é o que garante que a página nunca fique sem valor para um token.
 *
 * ── Contraste ──
 * Os pares foram escolhidos para ≥ 4.5:1 em texto normal e ≥ 3:1 em componente (WCAG 2.2 AA).
 * `--fg-muted` sobre `--bg` é o par mais apertado da folha: #55606d sobre #ffffff dá 6.1:1, e
 * #9aa7b4 sobre #14181d dá 7.4:1. Há margem porque texto secundário é onde a tentação de
 * clarear mais é maior.
 */
:root {
	color-scheme: light;

	--bg: #ffffff;
	--bg-soft: #f6f7f9;
	--bg-inset: #eef0f4;
	--fg: #14181d;
	--fg-muted: #55606d;
	--border: #dfe3e9;
	--border-strong: #c3cad4;
	/* A BORDA DE COMPONENTE INTERATIVO — 3:1 contra o fundo, como manda a WCAG 2.2 SC 1.4.11.
	   `--border` (1,29:1 no claro) e `--border-strong` (1,65:1) são corretos para SEPARADOR
	   decorativo, que o critério isenta: um `hr` ou a linha do rodapé não identificam controle
	   nenhum. Mas o campo de busca, o botão fantasma, o alternador de tema e os números da
	   paginação são identificados PELA BORDA — sem ela não há o que enxergar. Aí a isenção não
	   vale, e 1,65:1 reprova para quem tem baixa visão ou está no sol. */
	--border-control: #7f8895;

	--brand: #0e6b5c;
	--brand-ink: #ffffff;
	--brand-soft: #e6f2ef;
	--brand-hover: #0a5347;

	--accent: #a8571b;
	--accent-soft: #fdf1e6;

	--focus: #0f62fe;

	--radius: 10px;
	--radius-lg: 16px;
	--shadow: 0 1px 2px rgb(20 24 29 / 6%), 0 8px 24px -12px rgb(20 24 29 / 18%);

	/* A medida do texto. 68 caracteres é o meio da faixa de 45–75 que a literatura de
	   legibilidade sustenta; abaixo disso o olho salta linha demais, acima ele perde o
	   retorno. É o único número desta folha que governa a leitura. */
	--measure: 68ch;

	--font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial,
		"Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji";
	--font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
}

@media (prefers-color-scheme: dark) {
	:root:not([data-theme="light"]) {
		color-scheme: dark;

		--bg: #14181d;
		--bg-soft: #1b2027;
		--bg-inset: #222933;
		--fg: #eef1f4;
		--fg-muted: #9aa7b4;
		--border: #2b323b;
		--border-strong: #3d4650;
		--border-control: #6d7885;

		--brand: #4ec4ad;
		--brand-ink: #06231e;
		--brand-soft: #17302c;
		--brand-hover: #6fd6c1;

		--accent: #e8a165;
		--accent-soft: #2c2216;

		--focus: #78a9ff;

		--shadow: 0 1px 2px rgb(0 0 0 / 40%), 0 8px 24px -12px rgb(0 0 0 / 60%);
	}
}

:root[data-theme="dark"] {
	color-scheme: dark;

	--bg: #14181d;
	--bg-soft: #1b2027;
	--bg-inset: #222933;
	--fg: #eef1f4;
	--fg-muted: #9aa7b4;
	--border: #2b323b;
	--border-strong: #3d4650;
	--border-control: #6d7885;

	--brand: #4ec4ad;
	--brand-ink: #06231e;
	--brand-soft: #17302c;
	--brand-hover: #6fd6c1;

	--accent: #e8a165;
	--accent-soft: #2c2216;

	--focus: #78a9ff;

	--shadow: 0 1px 2px rgb(0 0 0 / 40%), 0 8px 24px -12px rgb(0 0 0 / 60%);
}

/* ─── 2. RESET E BASE ────────────────────────────────────────────────────────────────────── */

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

html {
	/* `scroll-padding-top` é o que faz um link do índice parar ABAIXO do cabeçalho fixo em vez
	   de deixar o heading escondido atrás dele. Sem isto, todo item do índice parece levar ao
	   parágrafo errado — e o defeito é sutil o bastante para passar em revisão.

	   A reserva do PÉ é a WCAG 2.2 SC 2.4.11 e mora mais abaixo, condicionada — ver
	   `html:has(body.single-post)`. */
	scroll-padding-top: 5.5rem;
	-webkit-text-size-adjust: 100%;
}

/*
 * SC 2.4.11 (Foco Não Obscurecido, AA) — a reserva do PÉ, e só onde a barra existe.
 *
 * No celular a barra de oferta é `position: fixed` no pé da tela, e o navegador rola o elemento
 * focado para dentro da viewport SEM saber que ela está lá. Sem reserva, o Tab chega no último
 * link da matéria e ele fica inteiro atrás da barra: o foco existe e ninguém vê onde.
 *
 * As duas condições são necessárias, e uma reserva incondicional era o defeito da primeira
 * versão: a barra só é impressa na matéria (`lumina7_offer_bar()` sai cedo fora de
 * `is_singular('post')`) e só é exibida abaixo de 62rem. Reservar 5rem em toda página do celular
 * fazia TODA âncora parar 5rem cedo em listagem, busca e 404 — onde não há nada cobrindo nada.
 *
 * `:has()` porque o elemento que rola é o `<html>`, e é o `<body>` que recebe as classes de
 * contexto do WordPress (`post_class`/`body_class`). Onde `:has()` não existir, a reserva
 * simplesmente não se aplica — a degradação cai no comportamento anterior, não num pior.
 */
@media (max-width: 61.9375rem) {
	html:has(body.single-post) {
		scroll-padding-bottom: 5rem;
	}

	/*
	 * E o mesmo problema para o CONTEÚDO, não só para o foco: no fim do documento a barra cobre
	 * ~70px de rodapé. A reserva acompanha a barra de verdade (`data-visible`, que o JS liga ao
	 * passar de 45% da leitura e apaga quando o leitor a dispensa) em vez de ser permanente —
	 * um vão de 4,5rem no pé de uma página sem barra é o defeito trocado de lado.
	 */
	body:has(.l-bar[data-visible='true']) {
		padding-bottom: 4.5rem;
	}
}

body {
	margin: 0;
	background: var(--bg);
	color: var(--fg);
	font-family: var(--font);
	font-size: 1.0625rem;
	line-height: 1.65;
	/* `optimizeLegibility` liga ligaduras e kerning em corpo de texto longo. Custa nada em
	   fonte de sistema, que já vem com as tabelas. */
	text-rendering: optimizeLegibility;
	-webkit-font-smoothing: antialiased;
}

img,
picture,
video,
iframe {
	max-width: 100%;
	height: auto;
}

a {
	color: var(--brand);
	text-decoration-thickness: 1px;
	text-underline-offset: 0.2em;
}

a:hover {
	color: var(--brand-hover);
}

/* Um indicador de foco em TODA a folha, com `:focus-visible` — visível para o teclado, ausente
   para o clique de mouse. `outline` e não `box-shadow`: `outline` acompanha a forma do elemento
   e nunca é cortado por `overflow: hidden` de um ancestral. */
:focus-visible {
	outline: 3px solid var(--focus);
	outline-offset: 2px;
	border-radius: 3px;
}

h1,
h2,
h3,
h4 {
	line-height: 1.22;
	/* `balance` distribui as palavras entre as linhas de um título curto, evitando a última
	   linha com uma palavra órfã. Suportado onde há suporte; ignorado onde não há. */
	text-wrap: balance;
	margin: 0 0 0.5em;
	letter-spacing: -0.011em;
}

p,
ul,
ol,
figure,
table,
pre,
blockquote {
	margin: 0 0 1.1em;
}

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

/* ─── 3. UTILIDADES ──────────────────────────────────────────────────────────────────────── */

/* Escondido para o olho, presente na árvore de acessibilidade. `clip-path` além do `clip`
   legado porque `clip` está deprecado e alguns navegadores já o ignoram. */
.l-sr {
	position: absolute !important;
	width: 1px;
	height: 1px;
	padding: 0;
	margin: -1px;
	overflow: hidden;
	clip: rect(0 0 0 0);
	clip-path: inset(50%);
	white-space: nowrap;
	border: 0;
}

/* O SKIP LINK reaparece ao receber foco. Escondê-lo com `.l-sr` sozinho o esconderia também de
   quem chega nele pelo Tab — que é exatamente quem ele serve. */
.l-skip {
	position: absolute;
	left: -9999px;
	top: 0;
	z-index: 100;
	padding: 0.75rem 1.25rem;
	background: var(--bg);
	color: var(--fg);
	border: 2px solid var(--focus);
	border-radius: 0 0 var(--radius) 0;
	font-weight: 600;
	text-decoration: none;
}

.l-skip:focus {
	left: 0;
}

.l-btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 0.5rem;
	/* 44px de altura mínima: o alvo de toque confortável. A WCAG 2.2 exige 24×24 (2.5.8); 44 é
	   a recomendação das diretrizes de plataforma, e num botão de compra a diferença entre
	   acertar e errar o toque é a diferença entre vender e não vender. */
	min-height: 44px;
	padding: 0.7rem 1.25rem;
	border: 1px solid transparent;
	border-radius: var(--radius);
	font: inherit;
	font-weight: 600;
	line-height: 1.2;
	text-align: center;
	text-decoration: none;
	cursor: pointer;
	transition: background-color 120ms ease, border-color 120ms ease;
}

.l-btn--primary {
	background: var(--brand);
	color: var(--brand-ink);
}

.l-btn--primary:hover {
	background: var(--brand-hover);
	color: var(--brand-ink);
}

.l-btn--ghost {
	background: transparent;
	border-color: var(--border-control);
	color: var(--fg);
}

.l-btn--ghost:hover {
	background: var(--bg-soft);
	color: var(--fg);
}

/* ─── 4. CABEÇALHO E RODAPÉ ──────────────────────────────────────────────────────────────── */

.l-header {
	position: sticky;
	top: 0;
	z-index: 40;
	background: color-mix(in srgb, var(--bg) 88%, transparent);
	/* `backdrop-filter` é enfeite que degrada sozinho: onde não há suporte, o fundo fica com a
	   opacidade acima e o texto continua legível. */
	backdrop-filter: saturate(1.4) blur(8px);
	border-bottom: 1px solid var(--border);
}

.l-header__inner,
.l-footer__inner,
.l-main {
	width: 100%;
	max-width: 78rem;
	margin: 0 auto;
	padding: 0 1.25rem;
}

.l-header__inner {
	display: flex;
	align-items: center;
	gap: 1rem;
	/* Altura FIXA no cabeçalho fixo. Um cabeçalho que cresce quando o logo carrega empurra a
	   página inteira — é CLS na dobra, o pior lugar possível. */
	min-height: 4rem;
}

.l-brand {
	margin: 0;
	font-weight: 700;
	flex: 0 0 auto;
}

.l-brand a {
	display: inline-flex;
	align-items: center;
	gap: 0.55rem;
	color: var(--fg);
	text-decoration: none;
}

.l-brand__mark {
	width: 28px;
	height: 28px;
	/* Dimensão reservada mesmo com o atributo no HTML: se o SVG não carregar, a caixa não
	   colapsa e o texto ao lado não salta. */
	flex: 0 0 28px;
}

.l-brand__name {
	font-size: 1.05rem;
	letter-spacing: -0.01em;
}

/* O CABEÇALHO REDUZIDO AO LOGO.
 *
 * Quando há logotipo do site, o cabeçalho não repete o nome escrito ao lado dele: a imagem já
 * diz de quem é o site, e o nome aparece no `<title>`, no rodapé e no JSON-LD. É o que o pedido
 * de 04/09/2026 chama de "deixar somente a imagem de logo".
 *
 * `height` fixa e `width: auto` (com `!important` porque o núcleo imprime `width`/`height` reais
 * no atributo): é o que impede um logo de 1200px de empurrar o menu para fora da linha, e o que
 * reserva a altura antes de a imagem chegar — sem isso, o cabeçalho salta e leva o CLS junto.
 */
.l-brand--custom img {
	height: 34px;
	width: auto !important;
	max-width: 220px;
	object-fit: contain;
}

@media (min-width: 40rem) {
	.l-brand--custom img {
		height: 40px;
	}
}

/* A versão escura só existe quando o Customizer tem uma (ver `lumina7_logo_dark`). Enquanto não
   houver, este seletor não casa com nada e o logo do núcleo serve aos dois temas. */
.l-brand__dark {
	display: none;
}

@media (prefers-color-scheme: dark) {
	:root:not([data-theme="light"]) .l-brand--custom .l-brand__dark {
		display: inline-flex;
	}

	:root:not([data-theme="light"]) .l-brand--custom .custom-logo-link {
		display: none;
	}
}

:root[data-theme="dark"] .l-brand--custom .l-brand__dark {
	display: inline-flex;
}

:root[data-theme="dark"] .l-brand--custom .custom-logo-link {
	display: none;
}

/* E o caminho de volta: quem escolheu o tema CLARO num sistema escuro precisa do logo claro de
   volta, e a media query acima já teria escondido ele. */
:root[data-theme="light"] .l-brand--custom .l-brand__dark {
	display: none;
}

:root[data-theme="light"] .l-brand--custom .custom-logo-link {
	display: inline-flex;
}

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

.l-nav__list {
	display: flex;
	gap: 0.35rem 1.1rem;
	flex-wrap: wrap;
	margin: 0;
	padding: 0;
	list-style: none;
	font-size: 0.95rem;
}

.l-nav__list a {
	color: var(--fg-muted);
	text-decoration: none;
	padding: 0.25rem 0;
	display: inline-block;
}

.l-nav__list a:hover,
.l-nav__list .current-cat > a {
	color: var(--fg);
	text-decoration: underline;
}

/* ── O MENU NO CELULAR ────────────────────────────────────────────────────────────────────────
 *
 * Sem isto, as categorias eram um `<ul>` com `flex-wrap` dentro de um cabeçalho STICKY: em
 * telas estreitas as seis viravam três linhas grudadas no topo, comendo a altura útil da tela
 * em toda rolagem, em toda página.
 *
 * O recolhimento só vale quando o JavaScript marcou o `<nav>` com `data-collapsible`. É o que
 * garante que um navegador sem JS veja a lista (feia, e funcionando) em vez de um botão inerte
 * com a navegação do blog trancada atrás — ver o comentário do botão em `header.php`.
 */
.l-nav__toggle {
	display: none;
	align-items: center;
	justify-content: center;
	/* 44×44: o mesmo alvo de toque dos outros botões do tema. */
	width: 44px;
	height: 44px;
	flex: 0 0 44px;
	padding: 0;
	background: none;
	border: 1px solid transparent;
	border-radius: var(--radius);
	color: var(--fg);
	cursor: pointer;
}

.l-nav__toggle:hover {
	background: var(--bg-inset);
}

/* Um só SVG desenha os dois estados: as barras somem quando aberto, o X aparece. Trocar o
   `d` por JavaScript faria o ícone depender de mais script do que o necessário. */
.l-nav__toggle-x {
	display: none;
}

.l-nav__toggle[aria-expanded="true"] .l-nav__toggle-bars {
	display: none;
}

.l-nav__toggle[aria-expanded="true"] .l-nav__toggle-x {
	display: block;
}

@media (max-width: 47.99rem) {
	/*
	 * O botão só aparece quando o JS tirou o `hidden` dele — ou seja, quando há quem responda ao
	 * clique. `:not([hidden])` e não uma classe: o atributo JÁ é o estado, e duplicá-lo numa
	 * classe cria duas verdades que podem divergir.
	 */
	.l-nav__toggle:not([hidden]) {
		display: inline-flex;
	}

	/*
	 * A lista vira um painel ABAIXO do cabeçalho, e não um dropdown flutuante preso ao botão:
	 * num cabeçalho sticky de 100% da largura, o painel de largura total é o que não empurra
	 * nada e não some atrás do `backdrop-filter`.
	 */
	.l-nav[data-collapsible] {
		position: static;
		flex: 0 0 auto;
	}

	.l-nav[data-collapsible] .l-nav__list {
		display: none;
		position: absolute;
		left: 0;
		right: 0;
		top: 100%;
		flex-direction: column;
		gap: 0;
		padding: 0.5rem 1.25rem 0.75rem;
		background: var(--bg);
		border-bottom: 1px solid var(--border);
		box-shadow: var(--shadow);
		font-size: 1rem;
	}

	.l-nav[data-collapsible][data-open] .l-nav__list {
		display: flex;
	}

	/* Cada item vira uma linha de 44px: no celular, links de 0,95rem colados um no outro são o
	   motivo mais comum de tocar no item errado. */
	.l-nav[data-collapsible] .l-nav__list li {
		display: block;
	}

	.l-nav[data-collapsible] .l-nav__list a {
		display: flex;
		align-items: center;
		min-height: 44px;
		padding: 0 0.25rem;
	}
}

.l-header__actions {
	display: flex;
	align-items: center;
	gap: 0.6rem;
	flex: 0 0 auto;
}

.l-header__store {
	display: none;
	padding: 0.5rem 0.9rem;
	border: 1px solid var(--brand);
	border-radius: var(--radius);
	color: var(--brand);
	font-size: 0.9rem;
	font-weight: 600;
	text-decoration: none;
	white-space: nowrap;
}

.l-header__store:hover {
	background: var(--brand-soft);
}

.l-toggle {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 40px;
	height: 40px;
	padding: 0;
	background: transparent;
	border: 1px solid var(--border-control);
	border-radius: 50%;
	cursor: pointer;
	color: var(--fg-muted);
}

.l-toggle:hover {
	color: var(--fg);
	border-color: var(--fg-muted);
}

/* O ícone é CSS puro: um disco que ganha uma mordida em forma de lua no tema escuro. Um SVG
   aqui custaria uma requisição ou 400 bytes de markup inline por página para desenhar o que
   duas formas resolvem. */
.l-toggle__icon {
	width: 16px;
	height: 16px;
	border-radius: 50%;
	background: currentcolor;
	box-shadow: inset -4px -1px 0 0 var(--bg);
}

.l-toggle[aria-pressed="true"] .l-toggle__icon {
	box-shadow: none;
}

/* A BARRA DE PROGRESSO. `position: fixed` e altura de 3px: ela informa sem ocupar espaço de
   layout, e por não estar no fluxo não pode causar CLS. */
.l-progress {
	position: fixed;
	top: 0;
	left: 0;
	right: 0;
	height: 3px;
	z-index: 60;
	background: transparent;
	pointer-events: none;
}

.l-progress__bar {
	display: block;
	height: 100%;
	/*
	 * `width: 100%` com `scaleX(0)` — e NÃO `width: 0`.
	 *
	 * `transform: scaleX(n)` multiplica a largura existente. Numa caixa de largura zero, zero
	 * vezes qualquer coisa continua zero: a barra nunca apareceria, e o defeito é invisível na
	 * revisão porque o JS "funciona" (ele escreve o `transform` correto a cada quadro).
	 *
	 * `transform` no lugar de animar `width`: `width` recalcula layout a cada quadro de rolagem;
	 * `transform` roda no compositor. Numa página longa é a diferença entre uma barra fluida e
	 * uma rolagem que engasga.
	 */
	width: 100%;
	transform: scaleX(0);
	background: var(--brand);
	transform-origin: 0 50%;
	will-change: transform;
}

.l-footer {
	margin-top: 4rem;
	border-top: 1px solid var(--border);
	background: var(--bg-soft);
	padding: 2.5rem 0 1.5rem;
	font-size: 0.95rem;
}

.l-footer__inner {
	display: grid;
	gap: 2rem;
	grid-template-columns: 1fr;
}

.l-footer__name {
	margin: 0 0 0.35rem;
	font-weight: 700;
	font-size: 1.05rem;
}

.l-footer__desc {
	color: var(--fg-muted);
	max-width: 34ch;
}

.l-footer__title {
	margin: 0 0 0.6rem;
	font-size: 0.8rem;
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.06em;
	color: var(--fg-muted);
}

.l-footer__nav ul,
.l-footer__legal ul {
	margin: 0;
	padding: 0;
	list-style: none;
	display: grid;
	gap: 0.45rem;
}

.l-footer__nav a,
.l-footer__legal a {
	color: var(--fg);
	text-decoration: none;
}

.l-footer__nav a:hover,
.l-footer__legal a:hover {
	text-decoration: underline;
}

.l-footer__copy {
	max-width: 78rem;
	margin: 2rem auto 0;
	padding: 1.25rem 1.25rem 0;
	border-top: 1px solid var(--border);
	color: var(--fg-muted);
	font-size: 0.85rem;
}

/* ─── 5. GRADE DO ARTIGO, ÍNDICE, COLUNA LATERAL ─────────────────────────────────────────── */

.l-main {
	padding-top: 2rem;
	padding-bottom: 2rem;
}

.l-crumbs {
	margin: 0 0 1.5rem;
	font-size: 0.85rem;
	color: var(--fg-muted);
}

.l-crumbs ol {
	display: flex;
	flex-wrap: wrap;
	gap: 0.4rem;
	margin: 0;
	padding: 0;
	list-style: none;
}

.l-crumbs li:not(:last-child)::after {
	content: "/";
	margin-left: 0.4rem;
	color: var(--border-strong);
}

.l-crumbs a {
	color: var(--fg-muted);
}

.l-single__head {
	max-width: var(--measure);
	margin: 0 auto 2rem;
}

.l-single__kicker {
	margin: 0 0 0.6rem;
	font-size: 0.8rem;
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.07em;
}

.l-single__kicker a {
	color: var(--accent);
	text-decoration: none;
}

.l-single__title {
	/* Escala fluida sem media query. O `clamp` interpola entre 1.95rem no celular e 3rem no
	   desktop; o meio (`4.4vw`) é o que faz o título de uma matéria longa caber em três linhas
	   numa tela de 390px em vez de cinco. */
	font-size: clamp(1.95rem, 4.4vw, 3rem);
	margin: 0 0 0.75rem;
}

.l-byline {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 0.5rem;
	margin: 0 0 1.5rem;
	color: var(--fg-muted);
	font-size: 0.9rem;
}

.l-byline__author {
	font-weight: 600;
	color: var(--fg);
}

.l-byline__sep {
	color: var(--border-strong);
}

.l-byline__updated {
	color: var(--accent);
}

.l-figure {
	margin: 0 0 2rem;
}

.l-figure img,
.l-figure__img {
	display: block;
	width: 100%;
	/* A PROPORÇÃO FIXA é o que zera o CLS da imagem do topo — a caixa existe antes do primeiro
	   byte da imagem chegar. 16/9 casa com o tamanho `lumina7-hero` (1280×720) declarado em
	   `inc/setup.php`, então não há corte inesperado. */
	aspect-ratio: 16 / 9;
	object-fit: cover;
	border-radius: var(--radius-lg);
	background: var(--bg-inset);
}

.l-figure__caption {
	margin-top: 0.6rem;
	font-size: 0.85rem;
	color: var(--fg-muted);
	text-align: center;
}

.l-single__body {
	display: grid;
	grid-template-columns: minmax(0, 1fr);
	gap: 2.5rem;
	/* As áreas nomeadas existem já no celular para que a promoção ao layout de três colunas
	   seja só uma troca de `grid-template`, sem reposicionar item por item. */
	grid-template-areas:
		"toc"
		"content"
		"aside";
}

.l-single__body--full {
	grid-template-areas: "content";
}

.l-toc {
	grid-area: toc;
	border: 1px solid var(--border);
	border-radius: var(--radius);
	background: var(--bg-soft);
	padding: 0.9rem 1.1rem;
	font-size: 0.92rem;
}

.l-toc__title {
	font-weight: 700;
	cursor: pointer;
	list-style: none;
	display: flex;
	align-items: center;
	gap: 0.5rem;
	min-height: 24px;
}

/* O triângulo padrão do `<summary>` é removido nos dois motores e substituído por um marcador
   próprio, que gira. Sem `::-webkit-details-marker` o Safari mantém o dele e a página fica com
   dois indicadores. */
.l-toc__title::-webkit-details-marker {
	display: none;
}

.l-toc__title::before {
	content: "";
	width: 0;
	height: 0;
	border-left: 5px solid currentcolor;
	border-top: 4px solid transparent;
	border-bottom: 4px solid transparent;
	transition: transform 140ms ease;
}

.l-toc details[open] > .l-toc__title::before {
	transform: rotate(90deg);
}

.l-toc__list {
	margin: 0.75rem 0 0;
	padding: 0;
	list-style: none;
	display: grid;
	gap: 0.15rem;
	/* `counter` no lugar de `<ol>` numerado nativo: os itens de nível 3 são recuados e NÃO
	   devem receber número da mesma sequência dos de nível 2. */
	counter-reset: lumina-toc;
}

.l-toc__item a {
	display: block;
	padding: 0.3rem 0.4rem;
	border-radius: 6px;
	color: var(--fg-muted);
	text-decoration: none;
	line-height: 1.4;
}

.l-toc__item a:hover {
	background: var(--bg-inset);
	color: var(--fg);
}

.l-toc__item--h2 {
	counter-increment: lumina-toc;
}

.l-toc__item--h2 > a::before {
	content: counter(lumina-toc) ". ";
	color: var(--border-strong);
	font-variant-numeric: tabular-nums;
}

.l-toc__item--h3 {
	padding-left: 1.1rem;
	font-size: 0.88rem;
}

/* O item ativo do scroll-spy. `aria-current="true"` e não uma classe: o estado é semântico, o
   leitor de tela o anuncia, e o CSS pega o mesmo atributo — uma fonte de verdade só. */
.l-toc__item a[aria-current="true"] {
	background: var(--brand-soft);
	color: var(--fg);
	font-weight: 600;
}

.l-single__content {
	grid-area: content;
	min-width: 0;
}

.l-aside {
	grid-area: aside;
	min-width: 0;
}

.l-widget {
	margin-top: 1.5rem;
	padding: 1.1rem;
	border: 1px solid var(--border);
	border-radius: var(--radius);
}

.l-widget__title {
	margin: 0 0 0.7rem;
	font-size: 0.95rem;
}

@media (min-width: 62rem) {
	.l-header__store {
		display: inline-block;
	}

	.l-single__body {
		grid-template-columns: minmax(0, 1fr) 19rem;
		grid-template-areas:
			"content aside"
			"toc     aside";
	}

	.l-single__body--full {
		grid-template-columns: minmax(0, 1fr);
		grid-template-areas: "content";
	}

	.l-footer__inner {
		grid-template-columns: 1.4fr 1fr 1fr 1fr;
	}
}

@media (min-width: 82rem) {
	/* TRÊS COLUNAS só a partir de 1312px: abaixo disso, tirar 15rem do índice e 19rem da oferta
	   deixaria o texto abaixo da medida de leitura confortável — e a medida do texto tem
	   prioridade sobre ter o índice sempre visível. */
	.l-single__body {
		grid-template-columns: 15rem minmax(0, 1fr) 19rem;
		grid-template-areas: "toc content aside";
	}

	.l-toc {
		position: sticky;
		top: 5.5rem;
		align-self: start;
		max-height: calc(100vh - 7rem);
		overflow-y: auto;
		background: transparent;
		border: 0;
		border-left: 2px solid var(--border);
		border-radius: 0;
		padding: 0.25rem 0 0.25rem 1rem;
	}

	.l-aside {
		position: sticky;
		top: 5.5rem;
		align-self: start;
	}
}

/* ─── 6. TIPOGRAFIA DO TEXTO ─────────────────────────────────────────────────────────────────
 *
 * `.l-prose` é o que o leitor realmente consome, e é o único bloco desta folha que recebe
 * atenção linha a linha. As matérias vêm da API REST como HTML puro (`<p>`, `<h2>`, `<ul>`,
 * `<table>`), sanitizado em `packages/blog/src/sanitize.ts` — então o estilo é aplicado por
 * SELETOR DE ELEMENTO, não por classe. Não há classe nenhuma para colocar no HTML do modelo.
 */

.l-prose {
	max-width: var(--measure);
	font-size: 1.125rem;
	line-height: 1.75;
}

/* `pretty` só no corpo: ele evita a palavra órfã na última linha do parágrafo sem o custo de
   `balance`, que reflui o bloco inteiro e não deve ser usado em texto longo. */
.l-prose p {
	text-wrap: pretty;
	margin: 0 0 1.35em;
}

.l-prose > :first-child {
	margin-top: 0;
}

.l-prose h2 {
	font-size: 1.6rem;
	margin: 2.4em 0 0.6em;
	/* `scroll-margin-top` no heading, e não só `scroll-padding` no `html`: quando o navegador
	   pula para o `#id` do índice, é a margem do PRÓPRIO alvo que decide onde ele para. Os dois
	   juntos cobrem o pulo por link e o pulo por `scrollIntoView` do JS. */
	scroll-margin-top: 5.5rem;
}

.l-prose h3 {
	font-size: 1.28rem;
	margin: 2em 0 0.5em;
	scroll-margin-top: 5.5rem;
}

.l-prose h4 {
	font-size: 1.08rem;
	margin: 1.8em 0 0.4em;
	scroll-margin-top: 5.5rem;
}

/* O LINK DE ÂNCORA que aparece ao passar o mouse num heading. É o que permite compartilhar um
   trecho específico de uma matéria longa — e é `opacity` e não `display`, para que o link
   continue focável por teclado. */
.l-prose :is(h2, h3) > .l-anchor {
	opacity: 0;
	margin-left: 0.35rem;
	font-size: 0.7em;
	text-decoration: none;
	color: var(--fg-muted);
}

.l-prose :is(h2, h3):hover > .l-anchor,
.l-prose .l-anchor:focus-visible {
	opacity: 1;
}

.l-prose :is(ul, ol) {
	padding-left: 1.4em;
	margin: 0 0 1.35em;
}

.l-prose li {
	margin-bottom: 0.5em;
}

.l-prose li > :is(ul, ol) {
	margin: 0.5em 0 0;
}

.l-prose strong {
	font-weight: 650;
}

.l-prose a {
	text-decoration: underline;
}

.l-prose blockquote {
	margin: 1.8em 0;
	padding: 0.2em 0 0.2em 1.2em;
	border-left: 3px solid var(--brand);
	color: var(--fg-muted);
	font-size: 1.05em;
}

.l-prose blockquote p:last-child {
	margin-bottom: 0;
}

.l-prose img {
	border-radius: var(--radius);
	/* Toda imagem do corpo entra com proporção declarada pelo próprio arquivo (o WordPress
	   escreve `width`/`height`), então aqui basta não deixá-la esticar. */
	height: auto;
}

.l-prose figure {
	margin: 2em 0;
}

.l-prose figcaption {
	margin-top: 0.5rem;
	font-size: 0.88rem;
	color: var(--fg-muted);
}

/* TABELAS — o caso em que uma matéria comparativa quebra o layout no celular.
 *
 * O `<table>` recebe um invólucro com `overflow-x: auto` pelo JS do tema; o `min-width` aqui é
 * o que garante que ela role em vez de comprimir as colunas até ficarem ilegíveis. O corpo da
 * página nunca rola na horizontal — só a tabela, dentro da própria caixa. */
.l-prose .l-table-scroll {
	overflow-x: auto;
	margin: 1.8em 0;
	/* `tabindex="0"` é posto pelo JS para a caixa ser rolável por teclado; a borda de foco
	   precisa então caber. */
	border-radius: var(--radius);
}

.l-prose table {
	width: 100%;
	min-width: 34rem;
	border-collapse: collapse;
	font-size: 0.95rem;
	margin: 0;
}

.l-prose caption {
	caption-side: top;
	text-align: left;
	font-weight: 600;
	padding-bottom: 0.6rem;
	color: var(--fg-muted);
	font-size: 0.9rem;
}

.l-prose :is(th, td) {
	padding: 0.6rem 0.8rem;
	border: 1px solid var(--border);
	text-align: left;
	vertical-align: top;
}

.l-prose th {
	background: var(--bg-soft);
	font-weight: 650;
}

.l-prose :is(code, kbd, samp) {
	font-family: var(--font-mono);
	font-size: 0.9em;
	background: var(--bg-inset);
	padding: 0.15em 0.4em;
	border-radius: 5px;
}

.l-prose pre {
	background: var(--bg-inset);
	padding: 1rem;
	border-radius: var(--radius);
	overflow-x: auto;
}

.l-prose pre code {
	background: none;
	padding: 0;
}

/*
 * A RESPOSTA DIRETA — o bloco que a regra ANSWER-FIRST produz.
 *
 * O agente de blog marca com `class="lumina-answer"` o parágrafo que responde a pergunta do
 * título sem depender do resto do texto (ver o prompt `blog.article`). É a única classe que o
 * sanitizador aceita no corpo, por allowlist fechada — o comentário de `sanitize.ts` explica
 * por que uma allowlist de VALORES é diferente de afrouxar o atributo.
 *
 * O destaque visual existe pelo mesmo motivo que o schema existe: essa é a frase que a pessoa
 * veio buscar, e a que um sistema de AI Search tem mais chance de citar. Enterrá-la no meio de
 * parágrafos idênticos desperdiça as duas coisas.
 */
.l-prose .lumina-answer {
	margin: 0 0 1.5em;
	padding: 1.1rem 1.25rem;
	background: var(--brand-soft);
	border-left: 3px solid var(--brand);
	border-radius: 0 var(--radius) var(--radius) 0;
	font-size: 1.06em;
	font-weight: 500;
}

.l-prose .lumina-key-takeaway {
	margin: 2em 0;
	padding: 1.1rem 1.25rem;
	background: var(--accent-soft);
	border: 1px solid color-mix(in srgb, var(--accent) 35%, transparent);
	border-radius: var(--radius);
}

.l-tags {
	margin: 2.5rem 0 0;
	padding-top: 1.25rem;
	border-top: 1px solid var(--border);
	font-size: 0.9rem;
	color: var(--fg-muted);
}

.l-tags__label {
	font-weight: 600;
}

/*
 * OS ASSUNTOS SÃO ALVOS DE TOQUE — e antes eles não eram.
 *
 * WCAG 2.2 SC 2.5.8 (Tamanho do Alvo, nível AA) pede 24×24 px CSS, ou espaçamento equivalente.
 * Como `inline-block` herdando `font-size: 0.9rem` e `line-height: 1.65`, cada tag tinha ~23,8 px
 * de altura e 6,4 px de folga lateral — reprovava pelos dois caminhos ao mesmo tempo, e num link
 * que num celular fica a um dedo do seguinte.
 *
 * A correção é o `min-height` explícito (não confiar em altura derivada de line-height, que muda
 * quando alguém mexe na tipografia) mais `gap` no contêiner. Vira uma pastilha, que também é o
 * que sinaliza "isto é clicável" — a linha de tags sublinhadas parecia texto corrido.
 */
.l-tags {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 0.5rem;
}

.l-tags a {
	display: inline-flex;
	align-items: center;
	min-height: 24px;
	padding: 0.15rem 0.6rem;
	border: 1px solid var(--border-control);
	border-radius: 999px;
	color: var(--fg-muted);
	text-decoration: none;
}

.l-tags a:hover,
.l-tags a:focus-visible {
	color: var(--fg);
	border-color: var(--fg-muted);
	background: var(--bg-soft);
}

/* PERGUNTAS RELACIONADAS e LEIA TAMBÉM — os links internos de saída. */
.l-related {
	margin-top: 3rem;
	padding-top: 1.75rem;
	border-top: 1px solid var(--border);
	max-width: var(--measure);
}

.l-related__title {
	font-size: 1.2rem;
	margin: 0 0 1rem;
}

.l-related__list {
	margin: 0;
	padding: 0;
	list-style: none;
	display: grid;
	gap: 0.9rem;
}

.l-related__list a {
	display: block;
	padding: 0.85rem 1rem;
	border: 1px solid var(--border);
	border-radius: var(--radius);
	color: var(--fg);
	text-decoration: none;
	font-weight: 600;
	line-height: 1.4;
}

.l-related__list a:hover {
	border-color: var(--brand);
	background: var(--bg-soft);
}

/* ─── 7. CONVERSÃO ───────────────────────────────────────────────────────────────────────────
 *
 * Três superfícies, cada uma no seu momento: o card da lateral (presente todo o tempo, sem
 * interromper), o bloco no meio do texto (quando o interesse está no pico) e a barra do celular
 * (quando o botão da lateral já saiu da tela). Nenhuma delas aparece sem produto vinculado ao
 * post — `inc/product.php` não imprime nada sem `lumina_product_url`.
 */

.l-offer {
	padding: 1.25rem;
	border: 1px solid var(--border-strong);
	border-radius: var(--radius-lg);
	background: var(--bg-soft);
	box-shadow: var(--shadow);
}

.l-offer__kicker {
	margin: 0 0 0.75rem;
	font-size: 0.75rem;
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.07em;
	color: var(--fg-muted);
}

.l-offer__cover {
	display: block;
	width: 100%;
	max-width: 13rem;
	margin: 0 auto 1rem;
	/* 3/4 é a proporção do mockup de capa que o pipeline gera. Reservá-la evita o salto do card
	   quando a imagem chega — e o card fica na lateral, onde um salto empurra o texto do
	   artigo no desktop. */
	aspect-ratio: 3 / 4;
	object-fit: contain;
	filter: drop-shadow(0 8px 18px rgb(20 24 29 / 22%));
}

.l-offer__title {
	margin: 0 0 0.5rem;
	font-size: 1.08rem;
	line-height: 1.3;
}

.l-offer__price {
	margin: 0 0 0.9rem;
	font-size: 1.35rem;
	font-weight: 700;
	font-variant-numeric: tabular-nums;
}

.l-offer__cta {
	width: 100%;
}

/* O BLOCO NO MEIO DO TEXTO. Ele interrompe a leitura de propósito — e por isso é o menor dos
   três: uma linha de texto e um botão. Um card grande no meio do artigo é o padrão que faz a
   pessoa fechar a aba. */
.l-inline-offer {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 0.9rem 1.25rem;
	margin: 2.5em 0;
	padding: 1.1rem 1.25rem;
	border: 1px solid var(--brand);
	border-radius: var(--radius);
	background: var(--brand-soft);
}

.l-inline-offer__text {
	flex: 1 1 16rem;
	margin: 0;
	font-size: 1rem;
	line-height: 1.5;
}

.l-inline-offer__action {
	flex: 0 0 auto;
}

/*
 * O BLOCO DE OFERTA DO FIM — `packages/blog/src/cta.ts`.
 *
 * Ele vem do worker com estilo INLINE, de propósito: tem de funcionar em qualquer tema,
 * inclusive num que o operador troque amanhã (o comentário do arquivo explica). O estilo inline
 * vence a folha por especificidade, então o que este bloco faz NÃO é repintar o que já está
 * pintado — é o que o inline não alcança: o espaçamento em relação ao texto e o comportamento
 * responsivo, que um `style` de atributo não consegue expressar (não há media query em atributo).
 *
 * As 28 matérias publicadas antes desta tarefa não têm `class="lumina-cta"` no HTML gravado; o
 * tema a acrescenta em tempo de render (`lumina7_tag_legacy_cta()`), casando a assinatura
 * literal que `renderBlogCta` emite. Por isso o seletor vale para as duas gerações.
 */
.l-prose .lumina-cta {
	margin: 3em 0 1em;
	max-width: 100%;
}

.l-prose .lumina-cta img {
	height: auto;
}

/* A BARRA FIXA DO CELULAR.
 *
 * `translateY(100%)` no estado inicial, e não `display: none`: o elemento existe no layout do
 * compositor desde o começo, então a entrada é uma transformação — sem reflow, sem CLS. E o JS
 * só troca um atributo.
 *
 * `padding-bottom` com `env(safe-area-inset-bottom)` é o que a tira de baixo da barra de gestos
 * do iPhone, onde o botão fica inalcançável. */
.l-bar {
	position: fixed;
	left: 0;
	right: 0;
	bottom: 0;
	z-index: 50;
	display: flex;
	align-items: center;
	gap: 0.75rem;
	padding: 0.7rem 0.9rem calc(0.7rem + env(safe-area-inset-bottom, 0px));
	background: var(--bg);
	border-top: 1px solid var(--border-strong);
	box-shadow: 0 -6px 24px -12px rgb(20 24 29 / 35%);
	transform: translateY(110%);
	transition: transform 200ms ease;
}

.l-bar[data-visible="true"] {
	transform: translateY(0);
}

/*
 * O ATRIBUTO `hidden` TEM DE VENCER — e sem esta regra ele perdia.
 *
 * `inc/product.php` imprime a barra com `hidden`, e o `display: none` que o atributo carrega vem
 * da folha do NAVEGADOR. O `display: flex` acima é folha de autor, e folha de autor vence folha
 * de navegador: o atributo era ignorado por inteiro.
 *
 * Visualmente ninguém notaria (o `translateY(110%)` a mantém fora da tela). O que se perdia é o
 * resto: a barra continuava na árvore de acessibilidade e na ordem de Tab, então um leitor de
 * tela anunciava um botão de compra invisível, e o Tab "desaparecia" no fim da página. É o
 * mesmo defeito que a barra da loja evita com `inert`.
 */
.l-bar[hidden] {
	display: none;
}

.l-bar__text {
	flex: 1 1 auto;
	min-width: 0;
	margin: 0;
	font-size: 0.9rem;
	line-height: 1.3;
}

.l-bar__title {
	display: block;
	font-weight: 600;
	/* Uma linha só, com reticências: o título de um e-book tem 60 caracteres e a barra tem a
	   largura de um celular. Duas linhas empurrariam o botão para fora. */
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

.l-bar__price {
	display: block;
	color: var(--fg-muted);
	font-variant-numeric: tabular-nums;
}

.l-bar__cta {
	flex: 0 0 auto;
	padding: 0.6rem 1rem;
	min-height: 40px;
}

.l-bar__close {
	flex: 0 0 auto;
	width: 32px;
	height: 32px;
	padding: 0;
	background: transparent;
	border: 0;
	border-radius: 50%;
	color: var(--fg-muted);
	font-size: 1.1rem;
	line-height: 1;
	cursor: pointer;
}

.l-bar__close:hover {
	background: var(--bg-inset);
	color: var(--fg);
}

@media (min-width: 62rem) {
	/* No desktop a barra não existe: o card da lateral é sticky e o botão nunca sai da tela.
	   Duas ofertas visíveis ao mesmo tempo competem entre si. */
	.l-bar {
		display: none;
	}

}

/* A CAPTURA DE LEAD.
 *
 * O markup vem do PLUGIN (`lumina7_lead_form`, em `lead-capture.php`), pelos ganchos
 * `lumina7_after_article_content` e `lumina7_before_footer` — o tema só sabe como ela APARECE.
 * Sem o plugin, nenhuma destas regras casa com nada, e é assim que tem de ser: a lista de e-mail
 * é do site, não do tema, e trocar de tema não pode levá-la embora.
 */
.l-lead {
	max-width: var(--measure);
	margin: 3rem auto;
	padding: clamp(1.5rem, 4vw, 2.25rem);
	background: var(--brand-soft);
	border: 1px solid var(--border);
	border-radius: var(--radius-lg);
}

/* A variante do rodapé: ela fica logo acima do rodapé, onde a margem de cima do bloco normal
   somaria com o espaço do rodapé e abriria um buraco. */
.l-lead--compact {
	margin-bottom: 0;
}

.l-lead__title {
	margin: 0 0 0.5rem;
	font-size: clamp(1.3rem, 3vw, 1.75rem);
}

.l-lead__text {
	margin: 0 0 1.5rem;
	color: var(--fg-muted);
	text-wrap: pretty;
}

.l-lead__form {
	display: grid;
	gap: 1rem;
}

@media (min-width: 40rem) {
	/* Três campos numa linha e o botão embaixo, ocupando a largura: o formulário deixa de parecer
	   um cadastro e passa a parecer uma inscrição. */
	.l-lead__form {
		grid-template-columns: repeat(3, 1fr);
		align-items: end;
	}

	.l-lead__submit,
	.l-lead__consent {
		grid-column: 1 / -1;
	}
}

.l-lead__field {
	display: grid;
	gap: 0.35rem;
	min-width: 0;
}

.l-lead__field label {
	font-size: 0.9rem;
	font-weight: 600;
}

.l-lead__optional {
	margin-left: 0.35rem;
	font-weight: 400;
	color: var(--fg-muted);
}

/* Os mesmos 44px e a mesma borda de 3:1 do campo de busca — um formulário com dois estilos de
   input no mesmo site é um formulário que parece de outro site. */
.l-lead__field input {
	min-width: 0;
	min-height: 44px;
	padding: 0.6rem 0.8rem;
	background: var(--bg);
	color: var(--fg);
	border: 1px solid var(--border-control);
	border-radius: var(--radius);
	font: inherit;
	font-size: 1rem;
}

.l-lead__field input::placeholder {
	color: var(--fg-muted);
	opacity: 1;
}

.l-lead__submit {
	justify-self: start;
}

.l-lead__consent {
	margin: 0;
	font-size: 0.85rem;
	color: var(--fg-muted);
}

.l-lead__done,
.l-lead__error {
	margin: 0;
	font-weight: 600;
}

.l-lead__error {
	margin-bottom: 1rem;
	color: var(--accent);
}

/* O HONEYPOT — e por que NÃO é `.l-sr`.
 *
 * `.l-sr` esconde do olho e MANTÉM na árvore de acessibilidade: é o oposto do que este campo
 * precisa. Um leitor de tela leria "Não preencha, campo de edição" e o usuário cego cairia na
 * armadilha feita para robôs. Aqui a intenção é sumir para todo mundo — `display: none` faz
 * exatamente isso, e o `aria-hidden` do markup é o cinto de segurança.
 *
 * Um robô que interpreta CSS não preenche o campo e passa; um que não interpreta preenche e é
 * recusado. É a troca que o honeypot sempre foi.
 */
.l-lead__hp {
	display: none;
}

/* ─── 8. LISTAGENS, PAGINAÇÃO, BUSCA, 404 ────────────────────────────────────────────────── */

.l-hero {
	max-width: var(--measure);
	margin: 1rem auto 3rem;
	text-align: center;
}

.l-hero__title {
	font-size: clamp(2rem, 5vw, 3.1rem);
	margin: 0 0 0.6rem;
}

.l-hero__lead {
	font-size: 1.15rem;
	color: var(--fg-muted);
	margin: 0 0 1.5rem;
	text-wrap: pretty;
}

.l-hero__actions {
	margin: 0;
}

/* O HERO COM IMAGEM DE FUNDO.
 *
 * Só existe quando `lumina7_hero_image` está preenchida no Customizer — `index.php` acrescenta a
 * classe e a variável `--l-hero-img` no mesmo `style` inline. Sem a opção, nada disto vale, e a
 * home continua sendo o hero de texto acima. Uma imagem de fundo não é o default deste tema.
 *
 * ── O véu não é decoração ───────────────────────────────────────────────────────────────────
 *
 * O texto fica sobre uma imagem que o autor do site escolhe e o tema nunca viu. Sem o gradiente
 * escuro por cima, o contraste do `<h1>` depende de a foto ser clara ou escura — o que é o mesmo
 * que não ter contraste garantido. O véu de 62%/78% sobre PRETO sustenta o branco acima de 7:1
 * em qualquer imagem, inclusive numa foto de neve, e é a razão de as cores aqui serem literais
 * em vez de tokens: os tokens invertem no modo escuro, e o texto sobre a foto não pode inverter
 * junto — ele ficaria preto sobre um véu preto.
 */
.l-hero--banner {
	max-width: none;
	margin-inline: 0;
	padding: clamp(2.5rem, 8vw, 5rem) 1.5rem;
	border-radius: var(--radius-lg);
	background-image:
		linear-gradient(rgb(0 0 0 / 62%), rgb(0 0 0 / 78%)),
		var(--l-hero-img);
	background-size: cover;
	background-position: center;
	/* A cor de fundo por baixo da imagem: se a imagem falhar em carregar, o texto branco continua
	   legível em vez de sumir contra o `--bg` do tema. */
	background-color: #14181d;
}

.l-hero--banner .l-hero__inner {
	max-width: var(--measure);
	margin: 0 auto;
}

.l-hero--banner .l-hero__title,
.l-hero--banner .l-hero__lead {
	color: #ffffff;
}

/* O botão sobre a foto ganha o `--brand` sólido, não o fantasma: uma borda de 1px sobre uma
   imagem com detalhe some, e o alvo deixa de ser identificável (WCAG 2.2 SC 1.4.11). */
.l-hero--banner .l-btn--primary {
	box-shadow: 0 2px 12px rgb(0 0 0 / 35%);
}

/* O foco de teclado sobre a foto: o `--focus` azul do tema perde contra um fundo escuro
   arbitrário. Branco sólido funciona sobre o véu em qualquer imagem. */
.l-hero--banner :focus-visible {
	outline-color: #ffffff;
}

@media (forced-colors: active) {
	/* No modo de alto contraste do sistema o navegador descarta a imagem de fundo, e o texto
	   branco literal ficaria branco sobre o fundo forçado do sistema. Devolver a cor ao sistema
	   é o comportamento correto — quem liga esse modo pediu as cores dele, não as nossas. */
	.l-hero--banner {
		background-image: none;
	}

	.l-hero--banner .l-hero__title,
	.l-hero--banner .l-hero__lead {
		color: CanvasText;
	}
}

.l-archive__head {
	max-width: var(--measure);
	margin: 0 0 2.5rem;
}

.l-archive__title {
	font-size: clamp(1.7rem, 3.6vw, 2.4rem);
	margin: 0 0 0.6rem;
}

.l-archive__desc {
	color: var(--fg-muted);
	margin: 0 0 1rem;
	text-wrap: pretty;
}

.l-list {
	display: grid;
	gap: 1.75rem;
	grid-template-columns: 1fr;
}

@media (min-width: 40rem) {
	.l-list {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}
}

@media (min-width: 68rem) {
	.l-list {
		grid-template-columns: repeat(3, minmax(0, 1fr));
	}
}

.l-card {
	display: flex;
	flex-direction: column;
	border: 1px solid var(--border);
	border-radius: var(--radius-lg);
	overflow: hidden;
	background: var(--bg);
	transition: border-color 140ms ease, transform 140ms ease;
}

.l-card:hover {
	border-color: var(--border-strong);
	transform: translateY(-2px);
}

.l-card__media {
	display: block;
	background: var(--bg-inset);
}

.l-card__img {
	display: block;
	width: 100%;
	/* 16/10 é a proporção do tamanho `lumina7-card` (760×475) declarado em `inc/setup.php`.
	   Casar os dois números é o que evita o corte inesperado no `object-fit`. */
	aspect-ratio: 16 / 10;
	object-fit: cover;
}

.l-card__body {
	display: flex;
	flex-direction: column;
	gap: 0.5rem;
	padding: 1.1rem 1.2rem 1.25rem;
	flex: 1 1 auto;
}

.l-card__kicker {
	margin: 0;
	font-size: 0.74rem;
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.07em;
}

.l-card__kicker a {
	color: var(--accent);
	text-decoration: none;
}

.l-card__title {
	margin: 0;
	font-size: 1.15rem;
	line-height: 1.32;
}

.l-card__title a {
	color: var(--fg);
	text-decoration: none;
}

.l-card__title a:hover {
	text-decoration: underline;
}

.l-card__excerpt {
	margin: 0;
	color: var(--fg-muted);
	font-size: 0.95rem;
	text-wrap: pretty;
}

.l-card__meta {
	margin: auto 0 0;
	display: flex;
	gap: 0.45rem;
	color: var(--fg-muted);
	font-size: 0.85rem;
	padding-top: 0.5rem;
}

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

.l-pagination .nav-links {
	display: flex;
	flex-wrap: wrap;
	gap: 0.4rem;
	align-items: center;
}

.l-pagination :is(a, span).page-numbers {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-width: 44px;
	min-height: 44px;
	padding: 0 0.7rem;
	border: 1px solid var(--border-control);
	border-radius: var(--radius);
	color: var(--fg);
	text-decoration: none;
	font-variant-numeric: tabular-nums;
}

.l-pagination a.page-numbers:hover {
	border-color: var(--brand);
	background: var(--bg-soft);
}

.l-pagination .page-numbers.current {
	background: var(--brand);
	border-color: var(--brand);
	color: var(--brand-ink);
	font-weight: 700;
}

.l-pagination .page-numbers.dots {
	border-color: transparent;
	min-width: auto;
}

.l-searchform {
	display: flex;
	gap: 0.5rem;
	flex-wrap: wrap;
}

.l-searchform__field {
	flex: 1 1 12rem;
	min-width: 0;
	min-height: 44px;
	padding: 0.6rem 0.8rem;
	background: var(--bg);
	color: var(--fg);
	border: 1px solid var(--border-control);
	border-radius: var(--radius);
	font: inherit;
	font-size: 1rem;
}

.l-searchform__field::placeholder {
	color: var(--fg-muted);
	opacity: 1;
}

.l-empty {
	max-width: var(--measure);
	color: var(--fg-muted);
}

.l-empty__title {
	margin: 2rem 0 0.75rem;
	font-size: 1.15rem;
	color: var(--fg);
}

.l-empty__list,
.l-404__list {
	margin: 0 0 1.5rem;
	padding: 0;
	list-style: none;
	display: flex;
	flex-wrap: wrap;
	gap: 0.5rem;
}

.l-empty__list a,
.l-404__list a {
	display: inline-block;
	padding: 0.45rem 0.85rem;
	border: 1px solid var(--border);
	border-radius: 999px;
	color: var(--fg);
	text-decoration: none;
	font-size: 0.9rem;
}

.l-empty__list a:hover,
.l-404__list a:hover {
	border-color: var(--brand);
	background: var(--bg-soft);
}

.l-404__section {
	margin-bottom: 2.5rem;
}

.l-404__title {
	font-size: 1.2rem;
	margin: 0 0 1rem;
}

.l-404__cta {
	margin-top: 1rem;
}

/* ─── 9. MOVIMENTO E IMPRESSÃO ───────────────────────────────────────────────────────────── */

/*
 * `prefers-reduced-motion` não é "desligar animação": é honrar um pedido de acessibilidade de
 * quem sente náusea ou tem gatilho vestibular com movimento na tela. As transições daqui são
 * todas decorativas — nada de função se perde ao zerá-las.
 *
 * `!important` porque este bloco tem de vencer qualquer regra acima, inclusive as que venham a
 * ser adicionadas depois sem que alguém lembre desta seção.
 */
@media (prefers-reduced-motion: reduce) {
	*,
	*::before,
	*::after {
		animation-duration: 0.01ms !important;
		animation-iteration-count: 1 !important;
		transition-duration: 0.01ms !important;
		scroll-behavior: auto !important;
	}

	.l-card:hover {
		transform: none;
	}
}

/*
 * IMPRESSÃO. Uma matéria de blog é salva em PDF com frequência, e o default imprime o
 * cabeçalho fixo em cima do texto e gasta uma página com a barra de oferta.
 */
@media print {
	.l-header,
	.l-footer,
	.l-progress,
	.l-bar,
	.l-toc,
	.l-aside,
	.l-inline-offer,
	.l-skip,
	.l-pagination {
		display: none !important;
	}

	.l-prose,
	.l-single__head {
		max-width: none;
	}

	body {
		background: #fff;
		color: #000;
		font-size: 11pt;
	}

	/* O destino de cada link, impresso ao lado dele: num papel, um link é texto morto sem a URL. */
	.l-prose a::after {
		content: " (" attr(href) ")";
		font-size: 0.85em;
		color: #444;
		word-break: break-all;
	}
}
