/* ── P48-15 — a pele da página de vendas do 48º (Operação UAU, onda 1) ──────────────────────

   A direção A (clara) do protótipo v6.2 aprovado pelo owner em 18/09/2026, portada para a
   página real. Fonte: `prototipo-v6.2/app.css` (sha256 f5a78beb…), que foi escrito para virar
   partials. O que mudou na passagem, e por quê:

   - tudo mora sob `body.pv48`: esta folha carrega DEPOIS de `app.css` (que continua dando as
     fontes do portal, o painel de privacidade e o aviso de mensuração) e ⛔ não pode vazar para
     nenhuma outra página;
   - as classes genéricas do protótipo que colidem com o `app.css` ganharam prefixo
     (`.field` → `.pv-campo`, `.gap` sai, `.warn` → `.pv-adv`, `.tlink` → `.pv-link`,
     `.cel`/`.t-*` → `.pv-cel`/`.pv-t-*`);
   - ⛔ nenhum instrumento de revisão do protótipo (`.prov`, `.gap`, `.pv-revisao`,
     `.pv-nota-prototipo`) vem junto: eles ⛔ não vão ao ar;
   - as fontes são as do portal (`static/fonts/`, sha256 idênticos aos do protótipo), declaradas
     uma vez em `app.css` — esta folha ⛔ não repete `@font-face`.

   Cores: SÓ os tokens do bloco `:root`. Nenhuma cor literal fora dele. */

/* ── Tokens (contrato §3.1, claro; valores medidos no protótipo) ─────────────────────────── */
:root {
  --paper: #FAF9F6;
  --raised: #F3F1EC;
  --ink: #2A2A2E;
  --soft: #5D5D64;
  --rule: rgba(22, 22, 27, .14);
  --rule2: rgba(22, 22, 27, .28);
  --ctl: #84838A;
  --accent: #7D5C1E;
  /* ⭐ P48-25 · o MESMO âmbar, um tom abaixo: é a mão em cima do botão de compra, ⛔ uma
     segunda cor de ação. A direção de arte §5 pede exatamente isto ("o botão de compra escurece
     um tom"), e §3 proíbe cor NOVA — um estado da cor que já existe ⛔ é cor nova.
     Medido: `--on-accent` sobre ele rende 7,23:1, contra 5,83:1 do âmbar em repouso. O estado
     ⛔ pode piorar o que a régua de contraste já aprovou, e aqui ele MELHORA. */
  --accent-escuro: #6B4F19;
  --accent-soft: rgba(125, 92, 30, .12);
  /* P48-17: `--accent-soft` já composto sobre `--raised`, para uso ATRÁS de texto. */
  --accent-selo: #E5DFD3;
  --on-accent: #FAF9F6;
  --alert: #B02A30;
  /* P48-21: o verde do WhatsApp JÁ ESCURECIDO para fundo claro — o mesmo `#147a3d` que
     a página do 47º usa no botão claro do FAQ. Sobre `--paper` rende 5,14:1, acima dos
     4,5:1 de texto e muito acima dos 3:1 de um componente gráfico. A cor de marca cheia
     (#25D366) daria 1,88:1 aqui e ⛔ entra. */
  --whatsapp: #147A3D;
  --focus: #7D5C1E;
  --quiet: #E9E6DF;
  /* área sob a curva que é "metade de tudo": só preenchimento de figura, nunca fundo de texto */
  --accent-area: rgba(125, 92, 30, .26);

  --serif: "Fraunces", Georgia, "Times New Roman", serif;
  --sans: "Hanken Grotesk", system-ui, -apple-system, "Segoe UI", sans-serif;

  --gutter: 20px;
  --measure: 38rem;
  --wide: 72rem;
  /* P48-23 · a largura da coluna de leitura quando a seção ⛔ tem peça à direita: ela se
     CENTRALIZA no envelope, e a medida continua sendo a mesma (só a posição muda). As duas
     seções que carregam quadro largo (os certificados da S12, o FAQ da S15) redeclaram o
     token com a largura DELAS, para que a caixa ⛔ encolha. */
  --coluna: var(--measure);
  /* O respiro de cima e de baixo de cada seção. Token porque o bloco de compra (P48-23) mora
     ENTRE duas seções e precisa anular EXATAMENTE o de baixo da seção acima dele. */
  --respiro-secao: 64px;
  /* ⭐ P48-25 · item 2 — O FIM DO ESCALONAMENTO DO TOPO, escrito como token porque ele é uma
     COORDENAÇÃO, ⛔ um número solto: é aqui que a entrada do topo acaba e é daqui que o tobogã
     começa a se desenhar. Quem mexer num dos dois mexe no outro sem precisar descobrir isso.
     A conta: o último elemento do topo entra com 300ms de atraso e leva 440ms. */
  --entrada-fim: 740ms;
  /* O quanto a peça fixa desce do alto da tela. O topo desta página é `position: relative`
     (⛔ flutua sobre o conteúdo), então isto é RESPIRO, ⛔ compensação de barra: é o mesmo
     valor do fim do `clamp()` com que a âncora do menu para no título (casca, `scroll-margin`). */
  --fixa-topo: 40px;
}
@media (min-width: 600px) { :root { --gutter: 40px; } }
@media (min-width: 1100px) { :root { --gutter: 64px; } }

/* ── Base ───────────────────────────────────────────────────────────────────────────────── */
/* `app.css` põe o body em flex coluna com halo dourado. Aqui ele é bloco, liso: um item flex
   com `min-width: auto` é o que deixava conteúdo largo empurrar a página para o lado. */
/* ⭐ P48-25 · item 3 — O GRÃO DE PAPEL.

   `#FAF9F6` chapado, em 1440 px de largura, ⛔ é papel: é uma superfície de tinta digital que o
   olho lê como "tela". Papel de verdade tem fibra, e a fibra é o que faz a página parecer
   IMPRESSA em vez de renderizada. Aqui ela é uma pitada de ruído — o suficiente para a
   superfície deixar de ser plana, e de longe o suficiente para ninguém dizer o que mudou.

   Três decisões, e cada uma tem um motivo:

   1. `feTurbulence` INLINE, em data-URI: zero requisição, 380 bytes, e ⛔ há arquivo para
      alguém trocar por engano. `fractalNoise` (⛔ `turbulence`) porque é o que dá fibra, ⛔
      nuvem; `stitchTiles='stitch'` porque sem ele o ladrilho mostra as emendas e a página ganha
      uma grade de 160 px que ninguém desenhou; `feColorMatrix saturate 0` porque o ruído do SVG
      sai COLORIDO — sem dessaturar, o papel fica com pontinhos vermelhos e verdes.
   2. Ele mora no `background-image` do `<body>`, que é a camada MAIS BAIXA que a página tem.
      É assim que ele fica abaixo de todo texto sem precisar de `z-index`, de `pointer-events`
      nem de um elemento a mais: ⛔ existe camada por onde ele passar na frente de alguma coisa.
      E é assim que ele ⛔ toca os cartões (`--raised`), os quadros nem os DOCUMENTOS — todos
      têm fundo OPACO próprio, e fundo opaco cobre o que está atrás.
   3. `background-color` continua `var(--paper)`, puro. A régua de contraste (P48-19) lê ESTA
      propriedade, e ela continua dizendo a verdade: o grão ⛔ muda a cor do papel — ele a
      granula. ⚠ A régua ⛔ mede textura, e ⛔ deveria: ela compara pares de cor, e um ruído
      ⛔ é uma cor. A prova de que ele ⛔ atrapalha a leitura é ESTRUTURAL (a camada, a
      opacidade fixa, o fundo opaco de cada superfície de texto), e está em
      `test_p48_25_acabamento.GraoDePapelTests`. */
body.pv48 {
  display: block; min-height: 0; margin: 0;
  background: var(--paper); color: var(--ink);
  background-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20width='160'%20height='160'%3E%3Cfilter%20id='g'%3E%3CfeTurbulence%20type='fractalNoise'%20baseFrequency='.8'%20numOctaves='4'%20stitchTiles='stitch'/%3E%3CfeColorMatrix%20type='saturate'%20values='0'/%3E%3C/filter%3E%3Crect%20width='160'%20height='160'%20filter='url%28%23g%29'%20opacity='.035'/%3E%3C/svg%3E");
  background-repeat: repeat; background-size: 160px 160px;
  font: 400 16px/1.5 var(--sans);
  -webkit-font-smoothing: antialiased; text-rendering: optimizeLegibility;
  overflow-x: clip;
}
html:has(body.pv48) { scroll-padding-top: 16px; }
body.pv48 [hidden] { display: none !important; }
/* ⭐ P48-19 · B02 + P48-31 · item 1 — RESET ⛔ PODE VENCER COMPONENTE.

   Isto aqui é um reset: ele pega o elemento por ele ser aquele elemento. A história tem duas
   metades, e a segunda é a prova de que a primeira ⛔ era um caso isolado.

   A PRIMEIRA (P48-19). Escrito `body.pv48 button`, o reset pesava (0,1,2) — e derrubava o
   `color` de `.btn--primary`, que pesa (0,1,0) e mora em `app.css`. O resultado, na página
   PÚBLICA: "Salvar preferências" e "Aceitar" — os dois botões com que a pessoa exerce a
   OPOSIÇÃO ao rastreamento — ficavam com o fundo preto da casca e a tinta grafite da página.
   1,261:1, onde a base dá 17,125:1. O `.btn--ghost` do banner perdia a tinta pelo mesmo
   caminho. Aquele comentário fechou dizendo que os vizinhos ficavam "como estão".

   A SEGUNDA (P48-31). O vizinho de cima — o reset de MARGEM — estava com o mesmo defeito, e
   fazia o mesmo estrago um andar acima: `body.pv48 p` pesa (0,1,2) e vence TODA margem de
   componente de classe única, que pesa (0,1,0). Medido no Chrome a 390 px, 36 pares
   regra/propriedade desta folha declaravam margem ≠ 0 e computavam ZERO — `.pv-sub` (o vão do
   título ao subtítulo, em doze seções), `.pv-cta__rodape` (a linha de selos colada no botão de
   compra, em cinco), `.pv-toboga`, `.pv-indice`, o bloco de preço inteiro, as peças do treino
   da S8. O owner viu isso no celular por um deles: o tracinho do Núcleo riscando o rótulo da
   barra, porque `.pv-barra__pos { margin-top: 14px }` computava 0.

   ⛔ Foi regressão de gosto: foi regressão da PORTA. No protótipo v6.2 aprovado o reset é
   `h1, h2, h3, p, ol, ul, dl, dd, figure { margin: 0 }`, que pesa (0,0,1) e deixa qualquer
   classe passar na frente; o commit `860d9eee` (P48-15), ao trazer a folha para a página,
   prefixou cada seletor com `body.pv48` — e matou os respiros de uma vez só, em silêncio, sem
   que uma linha do CSS ficasse errada para quem lê.

   `:where()` põe os dois resets em (0,0,0), e é por isso que a solução SOBREVIVE: ⛔ é uma
   exceção para os botões de hoje nem para as margens de hoje — é um PISO. Qualquer componente
   vence um piso, o `.btn--primary` que existe e o botão (ou a margem) que alguém escrever
   amanhã. ⛔ Há lista para manter, e ⛔ há como esquecer de incluir alguém nela.

   Nada de fora entra pela brecha: em `app.css` o que alcança estes elementos é
   `* { margin: 0 }`, que já pesa (0,0,0) e vem antes — o piso continua sendo o piso.

   ⚠ Os outros dois vizinhos ficam como estão, e cada um por um motivo: `main ol/ul` e `main a`
   moram dentro do `<main>`, que nesta página só tem conteúdo da 48 (a casca compartilhada —
   painel de privacidade e aviso de mensuração — é irmã de `<main>`, ⛔ filha); e `main a` ⛔
   pode pesar zero, senão o `a { color: inherit }` de `app.css`, que pesa (0,0,1), venceria a
   tinta dos links da página. Quem garante isso ⛔ é este comentário: é
   `test_p48_19_contraste_e_mascara`, que mede a subárvore das parciais compartilhadas, e é
   `test_p48_31_revisao_no_celular`, que mede no NAVEGADOR toda margem que esta folha declara.
   Régua no texto do CSS ⛔ enxergaria nenhuma das duas metades: as duas regras estavam
   escritas certas, e era o navegador que computava outra coisa. */
:where(body.pv48) h1, :where(body.pv48) h2, :where(body.pv48) h3, :where(body.pv48) h4,
:where(body.pv48) p, :where(body.pv48) ol, :where(body.pv48) ul, :where(body.pv48) dl,
:where(body.pv48) dd, :where(body.pv48) figure { margin: 0; }
body.pv48 main ol, body.pv48 main ul { padding: 0; list-style: none; }
body.pv48 main a { color: var(--accent); text-decoration: underline; text-underline-offset: .18em; }
body.pv48 img, body.pv48 svg { display: block; max-width: 100%; }
:where(body.pv48 button) { font: inherit; color: inherit; }
:where(body.pv48 strong), :where(body.pv48 b) { font-weight: 600; }
body.pv48 :focus-visible { outline: 3px solid var(--focus); outline-offset: 3px; border-radius: 2px; }

/* Texto só para o leitor de tela. O nome `sp5-sr-only` é o que as réguas da página contam
   (o aviso de nova aba da S7); a regra é a mesma do protótipo (`.vh`). */
body.pv48 .sp5-sr-only {
  position: absolute !important; width: 1px; height: 1px; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
}

.pv-pular {
  position: absolute; left: var(--gutter); top: -4rem; z-index: 80;
  display: inline-flex; align-items: center; min-height: 44px; padding: 0 .9rem;
  background: var(--ink); color: var(--paper); border-radius: 4px; font-weight: 600; text-decoration: none;
}
.pv-pular:focus { top: .5rem; }

.pv-wrap { width: 100%; max-width: calc(var(--wide) + 2 * var(--gutter)); margin: 0 auto; padding: 0 var(--gutter); }

/* Valor em reais que ⛔ não pode quebrar entre "R$" e o número. `nowrap` num span, ⛔ não espaço
   inseparável: o texto continua byte a byte o aprovado. */
.pv-nowrap { white-space: nowrap; }

/* ── Tipografia da venda (contrato §2.3) ────────────────────────────────────────────────── */
body.pv48 .pv-h1 {
  font: 560 35px/1.06 var(--serif); letter-spacing: -.018em; max-width: 20ch; color: var(--ink);
  font-variation-settings: "opsz" 72;
}
body.pv48 .pv-h2 { font: 560 30px/1.1 var(--serif); letter-spacing: -.015em; max-width: 24ch; text-wrap: balance; color: var(--ink); }
body.pv48 .pv-h3, body.pv48 .pv-afericao > h3 { font: 500 24px/1.25 var(--serif); color: var(--ink); }
.pv-sub { margin-top: 14px; max-width: 40rem; font: 400 19px/1.5 var(--serif); color: var(--ink); }
.pv-cab { margin-bottom: 32px; }
.pv-prosa { max-width: var(--measure); font: 400 18px/1.62 var(--serif); }
.pv-prosa p + p, .pv-prosa p + h3, .pv-prosa h3 + p { margin-top: 1em; }
.pv-prosa h3:not(:first-child) { margin-top: 1.6em; }
.pv-prosa strong { font-weight: 600; }
.pv-realce { font-weight: 600; }
.pv-leg { margin-top: 14px; font: 400 14.5px/1.5 var(--sans); color: var(--soft); max-width: 40rem; }
/* 320px: com 35/30px a coluna do título ficava abaixo de 9em da própria fonte. */
@media (max-width: 359.98px) {
  body.pv48 .pv-h1 { font-size: 29px; }
  body.pv48 .pv-h2 { font-size: 27px; }
}
@media (min-width: 600px) {
  body.pv48 .pv-h1 { font-size: 46px; }
  body.pv48 .pv-h2 { font-size: 38px; }
  .pv-sub { font-size: 21px; }
  .pv-prosa { font-size: 19px; }
}
@media (min-width: 1100px) {
  body.pv48 .pv-h1 { font-size: 62px; max-width: 17ch; }
  body.pv48 .pv-h2 { font-size: 46px; }
  body.pv48 .pv-h3, body.pv48 .pv-afericao > h3 { font-size: 28px; }
  .pv-sub { font-size: 22px; }
  .pv-cab { margin-bottom: 44px; }
}

/* ── Seções ─────────────────────────────────────────────────────────────────────────────── */
.pv-sec { padding: var(--respiro-secao) 0; }
.pv-sec--painel { background: var(--raised); }
.pv-sec--fio { border-top: 1px solid var(--rule); }
/* ⭐ P48-26: `.pv-sec--wa` SAIU. A P48-21 já dizia que o bloco de WhatsApp depois do FAQ ⛔ era
   uma seção nova de conteúdo — ele fecha o FAQ —, e por isso lhe tirava o respiro de cima. A
   conclusão dessa frase era que ele ⛔ devia ser uma `<section>`: agora ⛔ é. Ele mora dentro da
   S15, e o respiro em cima dele é o fio de `.pv-wa--pos_faq`. ⛔ Deixo a regra órfã: seletor que
   ⛔ casa nada é a folha dizendo que a página tem um elemento que ela ⛔ tem. */
@media (min-width: 1100px) { :root { --respiro-secao: 112px; } }

/* ⭐ P48-23 · o bloco de compra ENTRE duas seções (depois da S5 e depois da S8). Ele ⛔ é uma
   seção: ⛔ tem título, ⛔ tem nome acessível e ⛔ entrega inventário nenhum — é o fecho em ação
   da seção de cima. Por isso a margem negativa: ela anula EXATAMENTE o respiro de baixo daquela
   seção, e o que separa o botão do texto passa a ser a margem do próprio bloco (48 / 64 px).
   Abaixo dele, quem dá o respiro é a seção seguinte, com o dela. */
.pv-sec--cta { padding: 0; margin-top: calc(-1 * var(--respiro-secao)); }

/* ── Botão da venda (contrato §5.1) ─────────────────────────────────────────────────────── */
body.pv48 .pv-cta {
  display: flex; align-items: center; justify-content: center; width: 100%;
  min-height: 52px; padding: 0 28px; border-radius: 4px;
  background: var(--accent); color: var(--on-accent); border: 1px solid var(--accent);
  font: 700 17px/1.25 var(--sans); text-decoration: none; text-align: center; text-wrap: balance;
}
/* Sem identidade de release o botão ⛔ não tem destino: o texto fica, a ação ⛔ não existe. */
body.pv48 .pv-cta[aria-disabled="true"] { cursor: default; }
.pv-cta__rodape { margin-top: 10px; font: 400 14px/1.45 var(--sans); color: var(--soft); }
/* P48-23 · a caixa dos DOIS pontos de compra novos (depois da S5 e depois da S8). A medida é a
   mesma do `.pv-botao__acao` da S2 — é o mesmo botão, e a hierarquia dele ⛔ muda de lugar para
   lugar. O respiro em cima é o que separa o botão do texto que acabou de convencer. */
.pv-cta__bloco { max-width: 34rem; margin-top: 48px; }
@media (min-width: 1100px) { .pv-cta__bloco { margin-top: 64px; } }
/* ⭐ P48-55 · na ABERTURA o mesmo bloco respira menos, e é o texto de cima que manda: entre as
   seções ele fecha uma seção inteira (48 / 64px); aqui ele segue a instrução de play, a três
   linhas de distância, e herda o respiro que o atalho da demonstração tinha (24px). O WhatsApp
   vem DEPOIS da linha de preço, subordinado, e a medida dele é a do bloco. */
/* ⭐ P48-58 · a margem foi a ZERO (era 24px). O bloco de apoio virou ITEM da grade da S1, e o
   botão é o PRIMEIRO filho dele: o respiro acima dele é o `gap` de 22px da grade, e a margem
   somaria a ele. No celular, onde o apoio vem logo abaixo do player, os 24px extras custariam
   exatamente da altura que o vídeo precisa na primeira tela. */
.pv-hero__apoio > .pv-cta__bloco { margin-top: 0; }
.pv-hero__apoio > .pv-wa { margin-top: 18px; max-width: 34rem; }
@media (min-width: 600px) { body.pv48 .pv-cta { display: inline-flex; width: auto; } body.pv48 .pv-cta--bloco { display: flex; width: 100%; } }

/* Link de texto (contrato §5.2): sublinhado sempre. */
body.pv48 .pv-link {
  display: inline-flex; align-items: center; min-height: 44px; color: var(--accent);
  font-weight: 600; text-decoration: underline; text-underline-offset: .18em;
  background: none; border: 0; padding: 0; cursor: pointer; text-align: left;
}

/* ══ S1 · primeira dobra ════════════════════════════════════════════════════════════════════ */
.pv-hero { padding: 26px 0 56px; }
.pv-hero__grade { display: grid; gap: 22px; }
.pv-lead { font: 400 18px/1.5 var(--sans); max-width: 40rem; }
/* ⭐ P48-58 · A CHAMADA DO PÚBLICO — a linha pequena acima da manchete.

   Ela é o RÓTULO da página: diz para quem isto é, com a data da prova, e é a primeira coisa que
   quem chega do anúncio lê. Por isso ela é pequena e em âmbar, ⛔ um segundo título: o peso da
   primeira dobra é da manchete e do vídeo.

   ⚠ O ÂMBAR aqui ⛔ é a cor de AÇÃO virando decoração. `--accent` já veste a instrução de play
   desde a P48-15, pela mesma razão: as duas linhas mandam a pessoa fazer algo — uma diz que a
   página é para ela, a outra manda apertar o play. O botão continua sendo o único elemento
   PREENCHIDO de âmbar, e é isso que o distingue.

   Contraste medido sobre `--paper` (#FAF9F6) com o aparato da P48-19: **5,89:1** — acima do
   mínimo de 4,5:1 de texto comum em AA, e ela é texto comum (13,5 px).

   ⚠ O respiro abaixo dela mora AQUI, e ⛔ no `gap` da grade: a chamada e a manchete são irmãs
   dentro de `.pv-hero__abre`, que é UM item da grade nas duas telas. */
.pv-publico {
  margin-bottom: 10px; font: 600 13.5px/1.35 var(--sans); color: var(--accent);
  letter-spacing: .01em; max-width: 40rem;
}
/* ⭐ P48-58 · a margem SAIU (era 14px). A instrução deixou de ser um parágrafo dentro do bloco de
   apoio e passou a ser ITEM da grade da S1, acima do player: quem dá o respiro agora é o `gap`
   de 22px da grade, nas duas telas. Somar a margem a ele seria empurrar o vídeo 14px para baixo
   na primeira tela do celular — que é exatamente o que esta fatia existe para não fazer. */
.pv-instrucao { font: 700 17px/1.45 var(--sans); color: var(--accent); max-width: 40rem; }
.pv-sob-video { margin-top: 18px; max-width: 40rem; font: 400 19px/1.55 var(--serif); }

/* O player (`_player48.html`) chega com as classes de sempre e ganha aqui a moldura do
   protótipo: 16:9, papel levantado, fio. Sem mídia ⛔ não existe moldura nenhuma — quem
   decide isso é o `{% if vsl_media %}` da parcial, ⛔ esta folha: sem o `<div>` ⛔ há regra
   com alvo.

   ⭐ P48-54 · a MOLDURA passa a ser de TINTA (decisão do owner, 25/09/2026, 22h58). O fio de
   `--rule` desaparecia no papel, e o vídeo — que agora abre a primeira dobra no celular — ⛔
   parecia uma peça: parecia um vão. O fio vira `--ink` e ganha uma sombra leve, a MESMA do
   estado levantado da galeria (`0 2px 10px var(--rule)`), para o quadro descolar do papel.
   ⛔ Âmbar: `--accent` é o acento ÚNICO desta página (o botão de compra e a instrução de
   play), e uma moldura dourada roubaria a única cor que pede ação. O raio ⛔ muda: 4px, o
   mesmo do resto da página e o mesmo do quadro flutuante do mini (P48-32). */
body.pv48 .sp5-vsl {
  position: relative; width: 100%; max-width: 880px; aspect-ratio: 16 / 9; margin-bottom: 0;
  background: var(--raised); border: 1px solid var(--ink); border-radius: 4px; overflow: hidden;
  box-shadow: 0 2px 10px var(--rule);
}
/* ⭐ P48-59 · O QUE É O PARETO OAB, EM 30 SEGUNDOS — o bloco logo abaixo do botão.

   Ele existe porque as três pessoas que responderam ao WhatsApp em 28/09 perguntaram a mesma
   coisa ("como funciona o curso") e chegaram à página achando que é curso de videoaula. A
   primeira dobra ⛔ dizia, em uma frase, o que o produto é.

   【HIERARQUIA】 É um `h2` — subordinado à manchete da S1, que é o `h1` —, e ⛔ usa `.pv-h2`: a
   classe da página mede 30/38/46 px, que é tamanho de ABERTURA DE SEÇÃO. Aqui ele é a entrada de
   um bloco DENTRO da S1, e um título desse tamanho brigaria com a manchete e com o vídeo, que é
   o que a P48-58 acabou de pôr no centro. O estilo é o mesmo (serifa, tinta, `560`), num degrau
   abaixo — o mesmo degrau de `.pv-h3`, sem herdar a medida dele.

   【OS NÚMEROS】 `main ol` é `list-style: none` nesta página desde a P48-15, então o marcador ⛔
   existe: quem numera é um `counter`, e o número sai em âmbar e serifa — o MESMO tratamento que
   `.pv-item__n` dá aos quatro itens da S8. Âmbar como acento tipográfico ⛔ é o dourado do botão:
   o dourado é PREENCHIMENTO (`background: var(--accent)`), e aqui ⛔ há fundo nenhum.

   【O LINK】 é `.pv-link`, o link de texto do contrato §5.2 — sublinhado, 44 px de alvo, âmbar
   como todo link do corpo. ⛔ `.pv-cta`: o botão preenchido continua sendo só dos CTAs de compra,
   e um segundo botão cheio aqui competiria com o de cima, a três linhas de distância.

   【O FIO】 separa o bloco do WhatsApp que vem acima dele sem gastar altura: 1 px de `--rule` e
   18 px de respiro fazem o trabalho que um cartão faria com 24 px de borda em cada lado — e a
   altura é exatamente o que esta fatia ⛔ pode gastar (a régua do player). */
.pv-oque { max-width: 34rem; padding-top: 18px; border-top: 1px solid var(--rule); }
body.pv48 .pv-oque__titulo {
  font: 560 21px/1.2 var(--serif); letter-spacing: -.012em; max-width: 30ch; color: var(--ink);
  /* ⚠ MEDIDO no celular: sem isto o título quebrava em "O que é o Pareto / OAB, em 30 segundos",
     partindo o nome do produto na virada da linha. */
  text-wrap: balance;
}
.pv-oque__resumo { margin-top: 10px; font: 400 16.5px/1.5 var(--serif); color: var(--ink); }
.pv-oque__passos { margin-top: 14px; display: grid; gap: 8px; counter-reset: pv-oque; }
.pv-oque__passos > li {
  counter-increment: pv-oque;
  display: grid; grid-template-columns: 1.15em minmax(0, 1fr); column-gap: 8px;
  font: 400 15.5px/1.45 var(--sans); color: var(--ink);
}
.pv-oque__passos > li::before {
  content: counter(pv-oque) ".";
  font: 560 15.5px/1.45 var(--serif); color: var(--accent);
}
.pv-oque__fecho { margin-top: 14px; font: 600 16.5px/1.45 var(--serif); color: var(--ink); }
/* ⚠ O `gap` ⛔ é enfeite: `.pv-link` é `inline-flex`, e num contêiner flex o espaço em branco
   entre o texto e o `<span>` da seta é DESCARTADO — a seta nascia colada na última palavra. */
body.pv48 .pv-oque__link { margin-top: 4px; gap: .3em; font-size: 15.5px; }
@media (min-width: 1100px) {
  .pv-oque { grid-column: 1; }
  body.pv48 .pv-oque__titulo { font-size: 23px; }
  .pv-oque__resumo, .pv-oque__fecho { font-size: 17.5px; }
  .pv-oque__passos > li { font-size: 16.5px; }
  .pv-oque__passos > li::before { font-size: 16.5px; }
}
/* Celular curto: o bloco aperta com o resto da abertura, e ⛔ nenhuma palavra sai. */
@media (max-width: 480px) and (max-height: 720px) {
  .pv-oque { padding-top: 12px; }
  body.pv48 .pv-oque__titulo { font-size: 19px; }
  .pv-oque__resumo { margin-top: 8px; font-size: 15.5px; }
  .pv-oque__passos { margin-top: 10px; gap: 6px; }
  .pv-oque__passos > li { font-size: 14.5px; }
  .pv-oque__passos > li::before { font-size: 14.5px; }
  .pv-oque__fecho { margin-top: 10px; font-size: 15.5px; }
}

body.pv48 .sp5-vsl__frame { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }

/* ⭐ P48-73 (via P48-58) · A CAMADA DO AUTOPLAY SEM SOM, e ela só existe no braço B do teste
   (`_player48.html`).

   A camada é o QUADRO INTEIRO, menos a faixa de baixo: na 1ª rodada do teste no iPhone (05/10) o
   owner tocou no vídeo, fora do aviso, e nada aconteceu. Com ela, qualquer toque no vídeo devolve
   o som desde o começo. A faixa de baixo (64 px) fica LIVRE, e isso é requisito,
   ⛔ gosto: é onde ficam os controles do Stream, e a WCAG 2.2.2 exige poder pausar conteúdo que
   começa sozinho. Medido no Chrome com o player REAL a 360 px (`docs/evidence/p48-73/`): os
   botões ficam a ~21 px do pé e a barra de progresso a ~47 px — com 56 px ela ficava a 9 px da
   borda da camada, apertado para um alvo de toque; com 64, sobram 17.

   O AVISO mora no alto da camada. A pele é a da faixa da oferta, e pela mesma razão: papel sobre
   tinta, sem alarme. ⛔ Vermelho, ⛔ piscar, ⛔ animação. O contraste é o mesmo 13,58:1 medido lá.

   ⚠ Ela é `<button>` e ganha `cursor: pointer` e `:focus-visible` pela regra geral da página —
   quem chega por teclado vê o foco.

   ⚠ `hidden` é honrado: a camada nasce escondida e só o controlador a mostra. Uma regra de
   `display` aqui sem `[hidden]` faria o aviso aparecer antes do vídeo começar, que é a mentira
   que esta fatia ⛔ pode contar. */
body.pv48 .pv-som {
  --pv-som-tinta: 88%;
  position: absolute; z-index: 2; left: 0; right: 0; top: 0; bottom: 64px;
  display: flex; align-items: flex-start; justify-content: center;
  margin: 0; padding: 0; border: 0; border-radius: 4px 4px 0 0;
  background: transparent; color: var(--paper); cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
body.pv48 .pv-som[hidden] { display: none; }
body.pv48 .pv-som__aviso {
  display: flex; align-items: center; justify-content: center; width: 100%;
  min-height: 44px; padding: 10px 14px; border-radius: 4px 4px 0 0;
  background: color-mix(in srgb, var(--ink) var(--pv-som-tinta), transparent); color: var(--paper);
  font: 600 14px/1.3 var(--sans); text-align: center; text-wrap: balance;
}
/* ⚠ Todo controle escrito nas parciais da 48 entrega `:hover` E `:active` — é a régua da P48-25
   (`TodoControleDosTemplatesTemEstadoTests`), e ela existe porque um botão sem retorno de toque
   parece quebrado no celular. Aqui o retorno é de TINTA, ⛔ de movimento: a faixa do aviso fica
   cheia no toque, e nada se desloca. ⚠ O estado mora no BOTÃO e muda só a variável que a faixa
   lê — pintar o próprio botão escureceria o vídeo inteiro. */
body.pv48 .pv-som:hover { --pv-som-tinta: 94%; }
body.pv48 .pv-som:active { --pv-som-tinta: 100%; }
@media (min-width: 600px) { body.pv48 .pv-som__aviso { font-size: 15px; } }
/* No mini-player o quadro sai do lugar, e a camada ⛔ acompanha — ela ⛔ existe enquanto ele
   flutua (o mini só entra depois do som, e aí a camada já saiu). */
body.pv48 .sp5-vsl.pv48-mini .pv-som { display: none; }

@media (min-width: 600px) {
  .pv-hero { padding: 48px 0 72px; }
  .pv-lead { font-size: 19px; }
}
@media (min-width: 1100px) {
  .pv-hero { padding: 28px 0 72px; }
  /* ⭐ P48-58 · A MESMA ORDEM DO CELULAR, NA COLUNA DE TEXTO. A grade de duas colunas ⛔ mudou
     (5fr/7fr, 64px de vão): o que mudou é quantas LINHAS a coluna 1 tem, porque a instrução de
     play subiu para cima do player e o `pv-lead` desceu para o fim.

     A coluna 1, de cima para baixo: instrução → botão + linha de preço + WhatsApp → lead.
     A coluna 2: o player e a legenda dele, como sempre.

     ⚠ ⛔ Há `grid-row` em quem ⛔ precisa, e isso é decisão: o único item POSICIONADO é o vídeo
     (linha 2, coluna 2, atravessando as três linhas de texto). Os outros são colocados pelo
     algoritmo, na ordem do documento, e é por isso que a grade continua certa nos estados em que
     falta uma peça — sem data da prova ⛔ há chamada, sem mídia ⛔ há instrução nem player, e
     nenhum desses casos deixa linha vazia pesando o `row-gap`. Uma linha fixa por item devolveria
     esse defeito.

     ⚠ `span 3` e ⛔ `-1`: `-1` aponta para o fim do grid EXPLÍCITO, e aqui as linhas são
     implícitas — ele encurtaria a caixa para a linha 2. */
  .pv-hero__grade { grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); column-gap: 64px; row-gap: 22px; align-items: start; }
  .pv-hero__abre { grid-column: 1 / -1; }
  .pv-hero__titulo { max-width: 22ch; }
  .pv-instrucao { grid-column: 1; }
  .pv-hero__apoio { grid-column: 1; padding-top: 6px; }
  .pv-hero__grade > .pv-lead { grid-column: 1; }
  /* o vídeo vai para a segunda coluna, na altura da instrução de play: cabe inteiro na primeira
     dobra sem encolher a headline (MENTOR 17/09, 23h45) */
  .pv-hero__video { grid-column: 2; grid-row: 2 / span 3; align-self: start; }
  body.pv48 .sp5-vsl { max-width: min(880px, 62vh * 16 / 9); }
  .pv-sob-video { margin-top: 12px; font-size: 17px; }
  .pv-lead { font-size: 20px; }
  body.pv48 .pv-h1 { font-size: 50px; }
}
@media (min-width: 1100px) and (max-height: 820px) {
  .pv-hero { padding: 18px 0 64px; }
  body.pv48 .pv-h1 { font-size: 42px; }
  body.pv48 .sp5-vsl { max-width: min(880px, 54vh * 16 / 9); }
}
/* Celular curto: o topo aperta para o vídeo caber inteiro sem rolar; nenhuma palavra sai. */
@media (max-width: 480px) and (max-height: 720px) {
  /* ⭐ P48-58: o topo aperta mais 2 px e o vão da grade, 2 px. ⚠ MEDIDO, ⛔ arbitrado: em 375×548
     (iPhone SE com as barras do Safari) e SEM a oferta — onde a barra da prova gasta 122 px porque
     a linha da data quebra em duas — o player ficava com 0,65 da primeira tela, e a régua desta
     fatia exige ≥ ⅔. A instrução de play virou item da grade nesta fatia, então acima do player há
     DOIS vãos em vez de um: os 2 px do vão valem 4. Com a oferta no ar sobra folga (0,97 na mesma
     tela). ⛔ Nenhuma palavra sai. */
  .pv-hero { padding: 10px 0 40px; }
  .pv-hero__grade { gap: 12px; }
  body.pv48 .pv-h1 { font-size: 30px; line-height: 1.12; }
  .pv-lead { font-size: 16px; line-height: 1.42; }
  /* ⭐ P48-58: aqui a margem também saiu (era 8px) — a instrução é item da grade, e o `gap` de
     14px desta tela é o respiro dela. E a chamada do público aperta com o resto. */
  .pv-instrucao { font-size: 15px; line-height: 1.38; }
  .pv-publico { margin-bottom: 4px; font-size: 12.5px; }
  .pv-sob-video { margin-top: 12px; font-size: 17px; }
}

/* ══ P48-54 · O VÍDEO LOGO ABAIXO DO TÍTULO, NO CELULAR ═════════════════════════════════════

   O dado que gerou a decisão (owner, 25/09/2026, 22h58): no maior iPhone o player aparecia só
   no pé da primeira tela, cortado pela barra do Safari, e nos celulares menores ficava ABAIXO
   dela — acima dele vinham o título, o apoio, a instrução, o botão da demonstração e a nota.
   Três plays em ~165 visitantes do topo. O acervo diz o contrário: título, instrução de
   assistir e o VÍDEO como protagonista da primeira dobra.

   A ordem visual passou a ser título → player → lead → instrução → botão → nota → legenda.

   ⭐ **P48-58 (27/09/2026, 23h10) — A ORDEM MUDOU DE NOVO, e agora o TEXTO também.** Desde 26/09
   houve ZERO play real no topo (medição conferida numa aba anônima). A primeira tela não chamava
   ninguém e não dizia o que o vídeo entrega: a manchete era uma tese, e a instrução de assistir
   ficava ABAIXO do player. A ordem de hoje é

     chamada do público → manchete → INSTRUÇÃO DE PLAY → player → botão → WhatsApp → legenda da
     oferta → lead

   e a `pv-sob-video` "Se você já fez a prova…" saiu (ela ocupava a linha logo abaixo do vídeo — o
   lugar do botão). ⚠ A `@media` de teto continua sendo o que prende TUDO isto ao celular: acima
   de 1100px a grade é de duas colunas, e a ordem de lá é a mesma, na coluna de texto.

   ⛔ O HTML é o MESMO nas duas telas: só a ordem da grade muda, e só abaixo de 1100px, que é onde
   a grade da S1 empilha (é por isso que estas regras moram numa `@media` de teto, e ⛔ soltas).

   ⚠ `display: contents` no envelope do vídeo é a peça que faz a coisa funcionar: o player e a
   legenda moram no MESMO `<div>` no HTML — o que o desktop usa como segunda coluna —, e a
   ordem aprovada os separa (o player em segundo, a legenda no fim). Sem tirar a caixa do
   envelope, `order` moveria os dois juntos. O envelope ⛔ perde nada com isso: no celular ele
   ⛔ tem fundo, fio, medida nem posição (`.pv-fixa` só existe ≥1100px), e ⛔ carrega semântica
   (é um `div` sem papel, então a árvore acessível ⛔ muda).

   ⚠ A ordem de LEITURA (a do HTML: título → apoio → player → legenda) ⛔ acompanha a visual, e
   isso é uma decisão, ⛔ um descuido: ela é a ordem que a página sempre teve, continua fazendo
   sentido lida em voz alta e é a mesma do computador. Mexer no HTML para casar as duas mudaria
   o que o computador recebe, que é o que esta fatia ⛔ pode fazer.

   ⚠ A margem da legenda zera: dentro do envelope ela era o respiro abaixo do player; como item
   da grade, ela somaria ao vão de 22px. */
@media (max-width: 1099.98px) {
  .pv-hero__video { display: contents; }
  .pv-hero__abre { order: 1; }
  .pv-instrucao { order: 2; }
  .pv-hero__video > .sp5-vsl { order: 3; }
  .pv-hero__apoio { order: 4; }
  .pv-hero__video > .pv-sob-video { order: 5; margin-top: 0; }
  /* ⭐ P48-59: o bloco "em 30 segundos" entra AQUI, depois do botão — ⛔ antes do vídeo. O
     `pv-lead` desce um degrau e continua sendo a última linha da seção. */
  .pv-hero__grade > .pv-oque { order: 6; }
  .pv-hero__grade > .pv-lead { order: 7; }
}

/* ── P48-31 · itens 2 e 3 — O RESPIRO ENTRE SEÇÕES NO CELULAR ───────────────────────────

   O owner, percorrendo a página no celular em 21/09: o vão do gráfico da primeira dobra até o
   título seguinte estava grande demais. Medido: 120 px (56 do pé do hero + 64 da seção). E
   entre duas seções, 128. Numa tela de 390 px isso é um terço da altura visível gasto em nada.

   O que ele aprovou tem DUAS partes, e a segunda é a que faz a página parecer desenhada:

   1. o respiro cai para 44 px por lado (88 entre seções) e o pé da primeira dobra para 36 px
      (80 até o primeiro título) — "agora ficou ok";
   2. onde o FUNDO TROCA, o respiro passa a ser 32 px de cada lado, nas duas direções — "a
      própria mudança de cor já separa; quem precisa do respiro cheio é a emenda invisível".
      É regra única, ⛔ um ajuste por fronteira: são dez trocas na página, e cada uma vale nos
      dois sentidos. — "Aprovado".

   ⚠ Este bloco mora AQUI, depois das media queries do hero, por ordem de cascata: `.pv-hero`
   pesa (0,1,0) em todas elas, e a regra do celular curto (480×720) escreve `padding` inteiro.
   Declarar só `padding-bottom` depois dela mantém o aperto do TOPO que aquela regra existe para
   dar, e leva o pé aos 36 px aprovados em qualquer celular. Trocar a ordem ⛔ é inofensivo: o
   pé do hero voltaria a 40 px na tela curta, que é maior que o da tela normal.

   ⚠ `:has()` é a peça que sabe qual seção vem antes de um painel. Onde ele ⛔ existir, a seção
   ANTERIOR ao painel fica com 44 em vez de 32 — degradação sem dano, e o painel já entra com
   os 32 dele. */
@media (max-width: 599.98px) {
  :root { --respiro-secao: 44px; }
  .pv-hero { padding-bottom: 36px; }
  .pv-sec--painel { padding-top: 32px; padding-bottom: 32px; }
  .pv-sec:has(+ .pv-sec--painel), .pv-hero:has(+ .pv-sec--painel) { padding-bottom: 32px; }
  .pv-sec--painel + .pv-sec { padding-top: 32px; }
}

/* ── P48-25 · item 2 — O MOMENTO DE CARREGAMENTO, e é UM só ──────────────────────────────

   O sinal de página gerada ⛔ é o movimento: é o movimento SEM hierarquia — o fade-in igual em
   cada elemento, de cima a baixo, que diz que tudo tem a mesma importância e portanto que nada
   tem. A direção de arte §5 já tinha decidido o contrário: um único momento orquestrado no
   carregamento, e depois disso só o movimento das peças que já existem.

   O topo entra na ordem em que se lê, escalonado, e acaba em `--entrada-fim` (740ms):

     título ─ ⛔ anima (P48-38: ele é o LCP)
     subtítulo ─ ⛔ anima (P48-38)
     instrução ─ ⛔ anima (P48-38: o outro LCP medido)
     quadro do vídeo ─ 180ms ────────────┐ 520ms
     botão de compra da abertura ─ 240ms ┐ 440ms
     legenda do vídeo ─ 280ms ──────────┐ 440ms
     WhatsApp da abertura ─ 300ms ───────┐ 440ms  ← o último, e ele fecha em 740ms

   ⭐ **P48-38 · item 1 (22/09/2026) — O TOPO PERDEU A MÁSCARA E O FADE, e a razão é medida.**
   O Lighthouse do celular deu à página 75–96 de desempenho na MESMA manhã, e a oscilação tinha
   um nome: o elemento LCP é TEXTO (`h1.pv-hero__titulo`, ou `p.pv-instrucao`), com TTFB ~0,8s,
   load 0 e **render delay de 1,2s a 4,9s**. O texto chega na primeira resposta e a fonte vem por
   `preload` — mas o Chrome só CONTA o LCP quando o elemento APARECE, e uma animação CSS só
   começa quando a thread principal roda o primeiro quadro, disputando-o com o Pixel (duas
   configurações), o `fbevents` e o SDK do Cloudflare Stream. O título nascia coberto por uma
   máscara (`pv-entra-titulo`, `clip-path: inset(… 100% …)`) e o resto do topo nascia com
   `opacity: 0`: quem esconde o próprio LCP paga o atraso da fila inteira.

   Por isso, hoje: **o título, o subtítulo e a instrução ⛔ têm animação de entrada nenhuma**, e os
   quatro itens de baixo do topo mantêm o escalonamento **só por `transform`**. O movimento
   orquestrado continua e o `--entrada-fim` ⛔ mudou — o que saiu foi o esconderijo. O estado
   final de cada um é byte a byte o de antes: `inset()` com lados NEGATIVOS ⛔ corta nada, e o
   `to` do fade já era `opacity: 1`. ⚠ A régua está em `test_p48_38_entrada_da_dobra.py`, e ela
   lê as classes do topo do PRÓPRIO template: um parágrafo novo com fade cai nela.

   ⚠ Os atrasos são fixos, e a instrução é condicional (ela só existe com a MÍDIA, P48-55). Sem
   ela o escalonamento ganha um vão e acaba ANTES — ⛔ depois, que é o que importaria.

   ⭐ P48-55 (26/09/2026): os dois slots do meio mudaram de DONO, ⛔ de tempo. Saíram o botão da
   demonstração (240ms) e a nota dele (300ms); entraram o BOTÃO DE COMPRA da abertura e o
   WhatsApp que veio da S2, nos mesmos 240 e 300ms. O escalonamento continua fechando em
   `--entrada-fim` (740ms), e o tobogã continua partindo de lá.

   ⛔ NADA ABAIXO DA PRIMEIRA DOBRA ENTRA ANIMADO. A única coisa que se move fora do topo é o
   tobogã, que já se movia e que agora PARTE do fim daqui. É o único movimento da página no
   carregamento, e é por isso que ele conta.

   ⚠ Com movimento reduzido, o bloco `reduce` lá do fim desliga toda animação com `!important`,
   e cada elemento nasce no estado normal dele: opacidade 1 e sem deslocamento. */
@media (prefers-reduced-motion: no-preference) {
  .pv-hero__video .sp5-vsl { animation: pv-entra 520ms cubic-bezier(.22, .61, .36, 1) 180ms both; }
  .pv-hero__apoio > .pv-cta__bloco { animation: pv-entra 440ms cubic-bezier(.22, .61, .36, 1) 240ms both; }
  .pv-hero__video > .pv-sob-video { animation: pv-entra 440ms cubic-bezier(.22, .61, .36, 1) 280ms both; }
  .pv-hero__apoio > .pv-wa { animation: pv-entra 440ms cubic-bezier(.22, .61, .36, 1) 300ms both; }
}
/* ⚠ `transform` E SÓ `transform` (P48-38). O `opacity: 0` daqui era o esconderijo do LCP; o
   deslocamento de 10px ⛔ é — o Chrome conta o elemento PINTADO, ainda que 10px acima do lugar.
   E o `transform` ⛔ sai: o slot do vídeo carrega `animation: pv-entra … both`, e é ela que faz
   dele bloco de contenção — a causa que a P48-32 mediu e neutraliza no estado mini. Sem
   `transform` aqui, o `!important` de `pagina-vendas-48-mini.css` vira ruído. */
@keyframes pv-entra {
  from { transform: translateY(10px); }
  to { transform: none; }
}

/* ── P1 · o tobogã ─────────────────────────────────────────────────────────────────────────
   A curva real dos 1.275 assuntos que já caíram (dados gerados, ⛔ não digitados) e a linha da
   metade. O único movimento que ninguém pediu: a curva se desenha uma vez, da esquerda para a
   direita, e só então sobe a linha. Com movimento reduzido ela aparece pronta. */
.pv-toboga { margin: 40px 0 0; }
.pv-toboga__quadro { position: relative; aspect-ratio: 350 / 196; }
.pv-toboga__svg { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; }
.pv-toboga__tom { stop-color: var(--accent); }
.pv-toboga__tinta { stop-color: var(--ink); }
.pv-toboga__metade { fill: url(#pv48-toboga-metade); }
.pv-toboga__resto { fill: url(#pv48-toboga-resto); }
.pv-toboga__traco {
  fill: none; stroke: var(--ink); stroke-width: 1.75px;
  stroke-linejoin: round; stroke-linecap: round; vector-effect: non-scaling-stroke;
}
.pv-toboga__base { stroke: var(--rule); stroke-width: 1px; vector-effect: non-scaling-stroke; }
.pv-toboga__marca {
  position: absolute; left: var(--metade); bottom: 0; top: 4%; width: 2px; margin-left: -1px;
  background: var(--accent); transform-origin: 50% 100%;
}
.pv-toboga__rotulo {
  position: absolute; left: calc(var(--metade) + 12px); top: 4%; right: 0; max-width: 17rem;
  font: 600 14px/1.35 var(--sans); color: var(--accent);
}
.pv-toboga__leg { margin-top: 12px; font: 400 14.5px/1.5 var(--sans); color: var(--soft); max-width: 36rem; }
/* ⭐ P48-25 · item 2 — o tobogã começa EXATAMENTE onde a entrada do topo acaba.
   Antes ele partia em 250ms, no meio do nada: a curva se desenhava enquanto o título ainda
   estava chegando, e duas coisas disputavam o mesmo instante. Agora o atraso dele É o fim do
   escalonamento (`--entrada-fim`), e a marca e o rótulo mantêm a proporção que tinham dentro
   do desenho (a marca a 66% dele, o rótulo logo depois). */
@media (prefers-reduced-motion: no-preference) {
  .pv-toboga__svg { animation: pv-desenha 1180ms cubic-bezier(.33, .1, .25, 1) var(--entrada-fim) both; }
  .pv-toboga__marca { animation: pv-sobe 420ms cubic-bezier(.2, .7, .2, 1) calc(var(--entrada-fim) + 780ms) both; }
  .pv-toboga__rotulo { animation: pv-aparece 360ms ease-out calc(var(--entrada-fim) + 1020ms) both; }
}
@keyframes pv-desenha { from { clip-path: inset(-4% 100% -4% 0); } to { clip-path: inset(-4% -1% -4% 0); } }
@keyframes pv-sobe { from { transform: scaleY(0); } to { transform: scaleY(1); } }
@keyframes pv-aparece { from { opacity: 0; } to { opacity: 1; } }
@media (min-width: 600px) { .pv-toboga__quadro { aspect-ratio: 16 / 8; } }
@media (min-width: 1100px) { .pv-toboga { margin-top: 56px; } .pv-toboga__quadro { aspect-ratio: 16 / 7; } }

/* ══ S2 · o botão ═══════════════════════════════════════════════════════════════════════════ */
.pv-botao { display: grid; gap: 28px; }
.pv-botao__cab { margin-bottom: 0; }
.pv-botao__acao { max-width: 34rem; }
.pv-botao__prosa { margin-top: 4px; }
@media (min-width: 1100px) {
  .pv-botao { grid-template-columns: minmax(0, 1fr) minmax(0, 31rem); column-gap: 72px; row-gap: 32px; align-items: start; }
  .pv-botao__cab { grid-column: 1; grid-row: 1; }
  .pv-botao__acao { grid-column: 1; grid-row: 2; }
  .pv-botao__prosa { grid-column: 1; grid-row: 3; }
  .pv-conta { grid-column: 2; grid-row: 1 / span 3; }
  /* sem a Conta, a coluna da direita ⛔ não existe: o texto ocupa a largura de leitura */
  .pv-botao:not(:has(.pv-conta:not([hidden]))) { grid-template-columns: minmax(0, 1fr); }
}

/* ── P2 · a Conta da Prova ─────────────────────────────────────────────────────────────── */
.pv-conta { background: var(--raised); border: 1px solid var(--rule); border-radius: 6px; padding: 22px 18px 24px; }
@media (min-width: 600px) { .pv-conta { padding: 28px 28px 30px; } }
body.pv48 .pv-conta__titulo { font: 500 24px/1.2 var(--serif); color: var(--ink); }
.pv-conta__intro { margin-top: 8px; font: 400 15px/1.5 var(--sans); color: var(--soft); }
.pv-conta__form { display: grid; gap: 22px; margin-top: 22px; }
/* Campo (contrato §5.5): o `.field` do protótipo, com prefixo — `app.css` tem um `.field`. */
.pv-campo { display: block; min-width: 0; border: 0; padding: 0; margin: 0; }
.pv-campo__rotulo { display: block; margin-bottom: 6px; padding: 0; font: 600 15px/1.3 var(--sans); color: var(--ink); }
.pv-campo__entrada {
  width: 100%; min-height: 48px; padding: 11px 12px; border: 1px solid var(--ctl); border-radius: 6px;
  background: var(--paper); color: var(--ink); font: 400 16px/1.5 var(--sans);
}
/* P48-16c · a data da prova é uma RESPOSTA que eu já dei, ⛔ um campo a preencher: ela veste o
   estilo dos valores do livro-caixa (serifada, sem caixa e sem borda). ⛔ Há `[readonly]` com
   cara de caixa na página: o único campo só-leitura é este. */
.pv-campo__dado {
  width: 100%; margin: 2px 0 0; padding: 0; border: 0; background: none; color: var(--ink);
  font: 500 20px/1.35 var(--serif); font-variant-numeric: tabular-nums;
}
.pv-campo__dado:focus-visible { outline: 2px solid var(--focus); outline-offset: 4px; }
.pv-campo__dica { margin-top: 6px; font: 400 14px/1.45 var(--sans); color: var(--soft); }
/* P48-16: os dois moldes de erro da Conta, no campo que os pediu (como no protótipo v6.2). */
.pv-campo__erro { margin-top: 6px; font: 600 14px/1.45 var(--sans); color: var(--alert); }
.pv-campo--invalido .pv-campo__entrada { border-color: var(--alert); border-width: 2px; }
.pv-minutos { display: flex; align-items: center; gap: 10px; }
.pv-minutos__campo { max-width: 9rem; font-variant-numeric: tabular-nums; }
.pv-minutos__un { font: 400 15px/1.3 var(--sans); color: var(--soft); }
.pv-atalhos { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px; }
body.pv48 .pv-atalho {
  min-height: 44px; padding: 0 14px; border: 1px solid var(--ctl); border-radius: 4px;
  background: var(--paper); font: 600 15px/1 var(--sans); cursor: pointer; font-variant-numeric: tabular-nums;
}
body.pv48 .pv-atalho[aria-pressed="true"] { border: 2px solid var(--accent); padding: 0 13px; background: var(--accent-soft); }
.pv-antes { display: grid; gap: 2px; }
.pv-opcao { display: flex; align-items: center; gap: 12px; min-height: 44px; font: 400 16px/1.35 var(--sans); cursor: pointer; }
.pv-opcao input { width: 20px; height: 20px; margin: 0; accent-color: var(--accent); flex: none; }
.pv-conta__saida { margin-top: 26px; padding-top: 22px; border-top: 1px solid var(--rule2); }
.pv-conta__vazio { font: 400 17px/1.5 var(--serif); color: var(--ink); }
.pv-conta__frase { font: 500 22px/1.3 var(--serif); }
.pv-conta__complemento { margin-top: 8px; font: 400 17px/1.5 var(--serif); }
/* O aviso do teto de 6 horas: depois do livro-caixa, que é onde ele explica o "360 minutos". */
.pv-conta__aviso { margin-top: 14px; font: 400 15px/1.45 var(--sans); color: var(--ink); }
/* Advertência do conteúdo (contrato §5.8): âmbar, serifada, ⛔ não é falha. */
.pv-adv { margin-top: 18px; padding: 2px 0 2px 14px; border-left: 3px solid var(--accent); font: 400 16px/1.5 var(--serif); color: var(--ink); }
/* A figura das faixas: largura de cada faixa pelas HORAS dela, e o cheio pelo tempo da conta. */
/* `clip` só na horizontal (⛔ `hidden`, que criaria contexto de rolagem): enquanto o marcador
   anda, o rótulo do ponto ⛔ pode empurrar a largura da página. */
.pv-rota { margin-top: 18px; overflow-x: clip; }
.pv-rota__faixas { position: relative; display: flex; gap: 3px; height: 26px; margin-top: 34px; }
/* P48-16 · o ponto de parada na barra: a haste marca onde o tempo da pessoa acaba, e o rótulo
   fica acima dela.

   ⭐ P48-16c — as duas caixas ⛔ se cruzam em posição nenhuma. A haste subia 30px e passava por
   dentro do rótulo (medido no Chrome em 390px, com a parada no bloco 99: a haste cortava a
   primeira letra). Agora a separação é VERTICAL, e por construção: a haste sobe
   `--haste-acima`, a base do rótulo fica `--rotulo-acima` acima do topo da barra, e
   `--rotulo-acima` é MAIOR que `--haste-acima`. Como as duas faixas verticais ⛔ se tocam,
   ⛔ importa onde o rótulo cai na horizontal: em posição nenhuma ele cruza a haste.

   ⚠ O `clamp()` prende o rótulo dentro do quadro sem medir nada em JavaScript: ele ⛔ começa
   antes da borda esquerda nem depois de "toda a largura menos o tamanho dele". Com
   `overflow-x: clip` no `.pv-rota`, ⛔ há rolagem lateral em largura nenhuma. */
.pv-rota__faixas { --haste-acima: 8px; --rotulo-acima: 14px; --rotulo-largura: 15.5rem; }
.pv-rota__ponto {
  position: absolute; top: calc(-1 * var(--haste-acima)); bottom: -6px;
  left: var(--ponto, 0%); width: 3px; margin-left: -1.5px; background: var(--accent);
}
.pv-rota__rotulo {
  position: absolute; bottom: calc(100% + var(--rotulo-acima));
  left: clamp(0px, var(--ponto, 0%), calc(100% - var(--rotulo-largura)));
  white-space: nowrap; font: 700 14px/1.2 var(--sans); color: var(--accent);
  font-variant-numeric: tabular-nums;
}
@media (prefers-reduced-motion: no-preference) {
  .pv-rota__ponto, .pv-rota__rotulo { transition: left 420ms cubic-bezier(.2, .7, .2, 1); }
}
.pv-rota__seg { position: relative; overflow: hidden; border: 1.5px solid var(--ink); }
.pv-rota__seg--alem { border-style: dashed; border-color: var(--ctl); }
.pv-rota__seg i { position: absolute; left: 0; top: 0; bottom: 0; width: var(--cheio, 0%); background: var(--ink); }
@media (prefers-reduced-motion: no-preference) { .pv-rota__seg i { transition: width 420ms cubic-bezier(.2, .7, .2, 1); } }
.pv-rota__leg { display: grid; gap: 6px; margin-top: 16px; font: 400 14.5px/1.4 var(--sans); }
.pv-rota__faixa { display: grid; grid-template-columns: auto 1fr; column-gap: 8px; color: var(--soft); }
.pv-rota__faixa::before { content: ""; grid-row: 1 / span 2; width: 14px; height: 14px; margin-top: 2px; border: 1.5px solid var(--ink); }
.pv-rota__faixa--alem::before { border-style: dashed; border-color: var(--ctl); }
.pv-rota__estado { grid-column: 2; color: var(--ink); font-weight: 600; }
.pv-rota__estado:empty { display: none; }
.pv-livro { margin-top: 20px; border-top: 1px solid var(--rule); }
.pv-livro > div { display: flex; justify-content: space-between; align-items: baseline; gap: 16px; padding: 9px 0; border-bottom: 1px solid var(--rule); }
.pv-livro dt { font: 400 14.5px/1.35 var(--sans); color: var(--soft); }
.pv-livro dd { font: 500 17px/1.3 var(--serif); text-align: right; font-variant-numeric: tabular-nums; }

/* ══ S3 · lista × rota ══════════════════════════════════════════════════════════════════════
   As duas colunas do protótipo eram uma tabela. Aqui continuam duas LISTAS, na ordem em que o
   texto aprovado as escreve (a lista inteira, depois a rota inteira), e a grade é que alinha
   as linhas: quatro linhas, preenchidas coluna a coluna. */
.pv-comparar {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); grid-template-rows: repeat(4, auto);
  grid-auto-flow: column; max-width: var(--measure); margin: 0 0 24px;
}
.pv-comparar__col, .pv-comparar__lista { display: contents; }
.pv-comparar__cab {
  padding: 0 12px 10px 0; align-self: end;
  font: 700 13px/1.3 var(--sans); letter-spacing: .06em; color: var(--soft); border-bottom: 1.5px solid var(--ink);
}
.pv-comparar__lista li { padding: 14px 12px 14px 0; border-bottom: 1px solid var(--rule); font: 400 17px/1.4 var(--serif); }
.pv-comparar__col--rota .pv-comparar__cab,
.pv-comparar__col--rota li { padding-left: 14px; border-left: 1px solid var(--rule); }
.pv-comparar__col--rota .pv-comparar__cab { color: var(--accent); }
.pv-comparar__col--rota li { font-weight: 500; }
@media (min-width: 600px) { .pv-comparar__lista li { font-size: 19px; } }
/* Abaixo de 480px as duas colunas espremeriam o texto (a régua do MENTOR: nenhum bloco com
   coluna menor que 9em). Aí as duas listas empilham, na mesma ordem do texto: a lista inteira,
   depois a rota inteira. */
@media (max-width: 479.98px) {
  .pv-comparar { grid-template-columns: minmax(0, 1fr); grid-template-rows: none; grid-auto-flow: row; }
  .pv-comparar__col--rota .pv-comparar__cab,
  .pv-comparar__col--rota li { padding-left: 0; border-left: 0; }
  .pv-comparar__col--rota .pv-comparar__cab { margin-top: 28px; }
}

.pv-dupla { display: grid; gap: 36px; }
@media (min-width: 1100px) {
  .pv-dupla { grid-template-columns: minmax(0, var(--measure)) minmax(0, 1fr); column-gap: 72px; align-items: start; }
}

/* ══ S4 · a cadeia de números ═══════════════════════════════════════════════════════════════ */
.pv-cadeia { display: grid; gap: 10px; max-width: 46rem; margin: 36px 0 28px; }
.pv-elo { display: block; font: 400 18px/1.45 var(--serif); max-width: var(--measure); }
.pv-num { display: block; margin-bottom: 6px; font: 560 44px/1 var(--serif); letter-spacing: -.02em; font-variant-numeric: lining-nums tabular-nums; }
.pv-elo--metade .pv-num { color: var(--accent); }
.pv-cadeia__seta { font: 600 18px/1 var(--sans); color: var(--accent); }
/* Os trilhos do protótipo: 2.186 (o programa inteiro, contorno), 1.275 (os que caíram, cheio) e
   911 (os que nunca caíram, tracejado). As larguras vêm do contexto, geradas da fonte. */
.pv-trilho { position: relative; display: block; height: 16px; margin-top: 12px; }
.pv-trilho i { position: absolute; top: 0; bottom: 0; }
.pv-trilho__tudo { left: 0; right: 0; border: 1.5px solid var(--ink); }
.pv-trilho__caidos { left: 0; background: var(--ink); }
.pv-trilho__nunca { right: 0; border: 1.5px dashed var(--ctl); background: var(--quiet); }
@media (min-width: 600px) { .pv-elo { font-size: 20px; } .pv-num { font-size: 56px; } }
.pv-cadeia + .pv-prosa { margin-bottom: 36px; }

.pv-blocos { position: relative; display: block; height: 18px; margin: 12px 0 4px; border: 1.5px solid var(--ctl); }
.pv-blocos i { position: absolute; left: 0; top: 0; bottom: 0; width: var(--nucleo); background: var(--accent); }

/* ══ S5 · procedência ═══════════════════════════════════════════════════════════════════════ */
/* ⭐ P48-24 · a linha dos seis marcos, acima das fotos. Ela é a legenda que ABRE a galeria, e
   por isso encosta nela: sans pequena sobre a prosa em serifa, na tinta das legendas da página
   (`--soft`, a mesma de `.pv-leg` e `.pv-toboga__leg`). ⛔ Ícone, ⛔ cartão, ⛔ caixa alta — a
   gramática da página é tipografia, e o que distingue esta linha do corpo é a família e o
   tamanho, ⛔ um enfeite. */
.pv-marcos {
  margin-top: 28px; max-width: 46rem;
  font: 500 14.5px/1.6 var(--sans); color: var(--soft);
}
.pv-marcos + .pv-galeria { margin-top: 10px; }

/* A galeria (obs. 15 do owner): o jornal do ITA e os outros seis documentos, cada imagem um
   botão que abre a lupa.
   P48-24: são SEIS na grade — o diploma de Bacharel em Direito da USP entrou entre a FUVEST e
   o certificado da OAB, que é onde a frase aprovada da S5 o põe ("FUVEST e Direito na USP").
   P48-26: o close do nome saiu, e o jornal ficou sozinho na primeira linha.

   ⭐ P48-28 · A FOLHA DE CONTATO. O owner viu a página no desktop em 19/09 e reprovou: "o jornal
   ficou totalmente desproporcional, gigante comparado com os outros documentos… pode até ser um
   pouco maior, mas tem que ficar com um aspecto agradável e proporcional". Ele tem razão — em
   1440 o jornal media 1.138px de largura e o bloco todo, 1.657px de altura — mais de uma tela —,
   contra seis caixas de 237px (medido em Chrome sobre a base, `docs/evidence/p48-28`).

   A composição nova é de revista, ⛔ de galeria de site: UMA imagem-líder à esquerda e as seis
   menores em caixas iguais à direita, num bloco só, na largura da grade. A partir de 600px a
   `.pv-galeria` passa a ser a grade inteira — três colunas e três linhas —, o jornal toma a
   coluna 1 das três linhas e as seis miniaturas se distribuem pelas colunas 2 e 3, na ordem do
   HTML (INSS · Receita / SP · FUVEST / USP · OAB).

   ⭐ **Quem dita a altura do bloco é o JORNAL.** As três linhas são `minmax(0, 1fr)`: elas
   dividem em três a altura que a imagem-líder pede, e o terço resultante é a caixa de cada
   miniatura. É isso que faz "um pouco maior" ser uma medida, ⛔ uma opinião — em 1440 o jornal
   mede 407px numa folha de 736px, e cada documento menor, 131px.

   ⚠ `.pv-galeria__grade` vira `display: contents` de propósito: o `<div>` da grade some como
   caixa e os seis botões passam a ser filhos diretos da folha. Sem isso eles ficariam empilhados
   dentro de uma única célula, e a grade teria de ser escrita duas vezes.

   ⛔ Abaixo de 600px nada disso vale: no celular o jornal já está proporcional (321px numa faixa
   de 335, que é a largura da prosa), com a grade 2×3 embaixo — e o owner ⛔ pediu mudança nenhuma
   lá. Em 320 e 390 a página de hoje é IDÊNTICA à de ontem, campo a campo. */
.pv-galeria { display: grid; gap: 12px; margin: 28px 0; max-width: 46rem; }
.pv-galeria__grade { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; align-items: start; }
@media (min-width: 600px) {
  .pv-galeria {
    grid-template-columns: minmax(0, 1.45fr) minmax(0, .5fr) minmax(0, .5fr);
    grid-template-rows: repeat(3, minmax(0, 1fr));
  }
  .pv-galeria__ita { grid-column: 1; grid-row: 1 / -1; }
  .pv-galeria__grade { display: contents; }
}
body.pv48 .pv-galeria__abrir {
  display: block; width: 100%; padding: 6px; margin: 0; cursor: zoom-in;
  background: var(--raised); border: 1px solid var(--rule); border-radius: 4px;
}
html.sem-js body.pv48 .pv-galeria__abrir { cursor: default; }
.pv-galeria__abrir img { width: 100%; height: auto; border-radius: 2px; }
/* ⭐ P48-23 · as cinco miniaturas em CAIXAS IGUAIS. Os documentos têm proporções muito
   diferentes — o Diário de São Paulo é uma tira de 4:1, a portaria da Receita é um retrato de
   0,71:1 —, e com a altura livre a grade ficava um degrau atrás do outro.

   ⚠ A escolha é `object-fit: contain` sobre o papel, ⛔ `cover`: `cover` deixaria a grade igual
   CORTANDO documento, e documento cortado é prova pela metade — a direção de arte §6 diz que o
   que ⛔ pode aparecer fica FORA do recorte, ⛔ escondido depois. Com `contain`, o que sobra na
   caixa é papel, e a peça vira folha de contato: cinco molduras do mesmo tamanho, cada documento
   inteiro dentro da sua.

   4:3 é a proporção que menos sobra de papel no conjunto (o certificado da OAB e a portaria do
   INSS entram quase cheios). O jornal do ITA ⛔ entra aqui: ele é o destaque, e continua com a
   largura dele. */
.pv-galeria__grade .pv-galeria__abrir img {
  height: auto; aspect-ratio: 4 / 3; object-fit: contain; object-position: center;
  background: var(--paper);
}
/* ⭐ P48-28 · na folha de contato a MINIATURA ⛔ pode contribuir altura.

   O primeiro desenho manteve a imagem no fluxo, e a caixa da portaria da Receita (retrato,
   0,71:1) impôs 186px a CADA uma das três linhas: o bloco foi a 623px de altura e o jornal ficou
   esticado sobre papel vazio. O erro é de sentido, ⛔ de número — quem manda na altura tem de ser
   a imagem-líder, e uma miniatura que empurra a linha inverte a hierarquia da composição.

   Por isso o botão vira contêiner de altura fixa (o terço da linha) e a imagem sai do fluxo:
   `position: absolute` com `inset: 6px`, que é o mesmo respiro do `padding` de antes. O
   `aspect-ratio` da caixa 4:3 é desligado — a proporção agora vem da GRADE.

   ⚠ Continua `object-fit: contain`, ⛔ `cover`. `cover` encheria a caixa CORTANDO documento, e
   documento cortado é prova pela metade (direção de arte §6). O que sobra na caixa é papel. */
@media (min-width: 600px) {
  .pv-galeria__grade .pv-galeria__abrir { position: relative; height: 100%; min-height: 0; }
  .pv-galeria__grade .pv-galeria__abrir img {
    position: absolute; inset: 6px; aspect-ratio: auto;
    width: calc(100% - 12px); height: calc(100% - 12px);
  }
}
@media (prefers-reduced-motion: no-preference) {
  /* P48-25 · a sombra curta e o 1px do `:active` andam junto com a borda que já andava. */
  body.pv48 .pv-galeria__abrir { transition: border-color 120ms ease-out, box-shadow 120ms ease-out, transform 120ms ease-out; }
}
body.pv48 .pv-galeria__abrir:hover { border-color: var(--ink); }

/* ⭐ P48-31 · item 6 — A LUPA EM DOIS ESTADOS: uma mesa de luz, ⛔ uma galeria de fotos.

   INTEIRO: o documento todo, centrado, o maior que a tela permite. AMPLIADO: 1 ponto da imagem
   = 1 px de CSS (teto 1600, ou a largura própria do documento), o quadro rola nos dois eixos e
   o dedo arrasta. Quem calcula as duas medidas é o script, que conhece a proporção ANTES de a
   imagem chegar — por isso ⛔ há salto quando ela chega, e ⛔ há tela vazia enquanto ela ⛔ chegou.

   ⚠ Dois tropeços pagos na prévia, os dois da MESMA família do item 1 desta fatia — a regra
   estava escrita certa e o navegador computava outra coisa:

   1. `body.pv48 img { max-width: 100% }` pesa (0,1,2) e ESMAGAVA a imagem ampliada: a largura
      presa à tela e a altura já ampliada, documento deformado. Por isso o seletor da imagem da
      lupa leva `body.pv48` na frente — ⛔ é enfeite, é o peso necessário para vencer o vizinho.
   2. `place-items: center` do estado INTEIRO é herdado pelo AMPLIADO, e o Chrome aplica
      `justify-self` a caixa de bloco: metade do documento ficava à ESQUERDA da origem da
      rolagem, inalcançável por qualquer arrasto. `place-items: start` no ampliado resolve.

   `100dvh` com `100vh` de reserva: no Safari do iPhone a barra de endereço come o fim da tela,
   e é ali que mora a dica. */
.pv-lupa {
  width: 100vw; max-width: none; height: 100vh; height: 100dvh; max-height: none; margin: 0; padding: 0;
  border: 0; background: var(--paper); overflow: hidden;
}
.pv-lupa::backdrop { background: var(--ink); }
.pv-lupa__quadro {
  position: absolute; inset: 0; overflow: auto; overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch; display: grid; place-items: center; cursor: zoom-out;
}
body.pv48 .pv-lupa__img { display: block; max-width: none; background: var(--raised); box-shadow: 0 0 0 1px var(--rule); }
.pv-lupa[data-lupa-amplia] .pv-lupa__img { cursor: zoom-in; }
.pv-lupa[data-lupa-ampliada] .pv-lupa__quadro { display: block; place-items: start; }
.pv-lupa[data-lupa-ampliada] .pv-lupa__img { cursor: zoom-out; box-shadow: none; }
/* O × é tinta sobre papel, redondo e de 44 px — o alvo de toque da casa. ⛔ Sombra nova. */
body.pv48 .pv-lupa__fechar {
  position: absolute; z-index: 2; top: max(10px, env(safe-area-inset-top)); right: max(10px, env(safe-area-inset-right));
  width: 44px; height: 44px; display: grid; place-items: center; padding: 0;
  background: var(--ink); color: var(--paper); border: 0; border-radius: 50%; cursor: pointer;
}
.pv-lupa__fechar svg { width: 18px; height: 18px; }
.pv-lupa__dica {
  position: absolute; z-index: 2; left: 0; right: 0; bottom: max(22px, env(safe-area-inset-bottom));
  margin: 0; text-align: center; font: 500 15px/1.3 var(--sans); color: var(--ink); pointer-events: none;
}
.pv-lupa__dica span { background: var(--paper); padding: 7px 14px; border-radius: 999px; box-shadow: 0 0 0 1px var(--rule); }
/* Quem toca lê "Toque"; quem tem mouse fino lê "Clique". As duas frases são da fonte v13 §3, e
   a escolha é da FOLHA: o script ⛔ lê aparelho nenhum. */
.pv-lupa__dica .pv-lupa__dica-clique { display: none; }
@media (hover: hover) and (pointer: fine) {
  .pv-lupa__dica .pv-lupa__dica-toque { display: none; }
  .pv-lupa__dica .pv-lupa__dica-clique { display: inline; }
}
/* ⛔ Dica onde ⛔ há o que ampliar (as duas tiras largas já abrem quase no tamanho real no
   desktop), e ⛔ dica no ampliado: ali a instrução já foi cumprida. */
.pv-lupa:not([data-lupa-amplia]) .pv-lupa__dica, .pv-lupa[data-lupa-ampliada] .pv-lupa__dica { display: none; }
.pv-procedencia + .pv-afericao { margin-top: 56px; }

/* ══ S6 · três perguntas ════════════════════════════════════════════════════════════════════ */
.pv-perguntas { display: grid; gap: 36px; margin-bottom: 40px; max-width: 58rem; }
.pv-pergunta { display: grid; grid-template-columns: 44px 1fr; column-gap: 12px; align-content: start; }
.pv-pergunta__n { grid-row: 1 / span 2; font: 560 26px/1.1 var(--serif); color: var(--accent); font-variant-numeric: tabular-nums; }
body.pv48 .pv-pergunta__q { font: 500 23px/1.25 var(--serif); margin-bottom: 8px; color: var(--ink); }
.pv-pergunta p { font: 400 18px/1.6 var(--serif); max-width: 36rem; }
@media (min-width: 1100px) {
  .pv-perguntas { grid-template-columns: repeat(3, 1fr); column-gap: 40px; }
  .pv-pergunta { grid-template-columns: 1fr; }
  .pv-pergunta__n { grid-row: auto; margin-bottom: 12px; font-size: 34px; }
  body.pv48 .pv-pergunta__q { font-size: 25px; }
}

/* ══ S7 · para quem é ═══════════════════════════════════════════════════════════════════════ */
.pv-serve { display: grid; gap: 32px; margin-bottom: 32px; max-width: 64rem; }
.pv-serve__cab { padding-bottom: 10px; border-bottom: 1.5px solid var(--ink); font: 700 13px/1.3 var(--sans); letter-spacing: .06em; }
.pv-serve__col--sim .pv-serve__cab { color: var(--accent); border-color: var(--accent); }
.pv-serve__lista li { position: relative; padding: 12px 0 12px 26px; border-bottom: 1px solid var(--rule); font: 400 18px/1.45 var(--serif); }
.pv-serve__lista li::before { content: ""; position: absolute; left: 2px; top: 1.05em; width: 10px; height: 10px; border-radius: 50%; }
.pv-serve__col--sim li::before { background: var(--accent); }
.pv-serve__col--nao li::before { border: 1.5px solid var(--ctl); }
@media (min-width: 900px) { .pv-serve { grid-template-columns: 1fr 1fr; column-gap: 48px; } }

/* ══ S8 · o que você recebe ═════════════════════════════════════════════════════════════════ */
.pv-itens { display: grid; gap: 56px; margin-top: 8px; }
.pv-item { display: grid; grid-template-columns: 34px minmax(0, 1fr); column-gap: 10px; }
.pv-item > .pv-prosa, .pv-item > .pv-item__dupla { grid-column: 2; }
.pv-item__n { grid-row: 1; font: 560 26px/1.15 var(--serif); color: var(--accent); }
body.pv48 .pv-item__t { grid-column: 2; margin-bottom: 12px; font: 500 24px/1.25 var(--serif); color: var(--ink); }
/* obs. 9 do owner (18/09): "E a barra." ⛔ não tem número, e ocupa a coluna inteira */
/* ⭐ P48-24 · os seis entregáveis do item 4, um por linha, com o nome na frente. `main ul` já é
   `list-style: none` nesta página, então ⛔ há marcador a esconder: o que separa um item do
   outro é o espaço, e o que o nomeia é o negrito. ⛔ Ícone, ⛔ cartão, ⛔ borda.

   ⚠ A segunda linha ⛔ é enfeite. `.pv-prosa` só dá respiro entre `p + p`, `p + h3` e `h3 + p`;
   o parágrafo que vem DEPOIS da lista ficava colado no sexto item, e "A única coisa que não vai
   para o papel…" era lida como parte de "A teoria inteira em PDF." — que é o contrário do que
   ela diz. Ela fecha o item, e por isso respira como parágrafo. */
.pv-entregaveis li + li { margin-top: .7em; }
.pv-prosa .pv-entregaveis + p { margin-top: 1em; }

.pv-item.pv-item--barra { grid-template-columns: minmax(0, 1fr); }
.pv-item.pv-item--barra > * { grid-column: 1 !important; }
.pv-item__dupla { display: grid; gap: 28px; }
.pv-itens + .pv-prosa { margin-top: 56px; }
@media (min-width: 1100px) {
  .pv-item { grid-template-columns: 56px minmax(0, 1fr); }
  .pv-item__n { font-size: 32px; }
  body.pv48 .pv-item__t { font-size: 28px; }
  .pv-item__dupla { grid-template-columns: minmax(0, var(--measure)) minmax(0, 1fr); column-gap: 56px; align-items: start; }
}

/* ── P6 · o produto à vista: quatro telas em molduras de celular ─────────────────────────── */
.pv-celulares {
  display: flex; gap: 18px; overflow-x: auto; scroll-snap-type: x mandatory; overscroll-behavior-x: contain;
  padding: 6px var(--gutter) 22px; scroll-padding: 0 var(--gutter); max-width: 100%; margin-bottom: 40px;
}
.pv-celulares:focus-visible { outline-offset: -3px; }
.pv-celular { flex: 0 0 258px; scroll-snap-align: start; }
.pv-celular__leg { margin-top: 14px; font: 400 15px/1.45 var(--sans); max-width: 258px; }
.pv-celular__leg b { font-weight: 700; }
@media (min-width: 1100px) {
  .pv-celulares {
    display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 28px; overflow: visible;
    max-width: calc(var(--wide) + 2 * var(--gutter)); margin: 0 auto 56px; padding: 8px var(--gutter) 24px;
  }
  .pv-celular { flex: none; }
  .pv-celular__leg { max-width: none; }
}
/* A moldura (ilustração do aparelho: o raio grande é do vidro, ⛔ não de componente). */
.pv-cel {
  position: relative; width: 100%; aspect-ratio: 9 / 18.6; overflow: hidden;
  border: 8px solid var(--ink); border-radius: 34px; background: var(--paper);
  font-family: var(--sans); color: var(--ink);
}
.pv-cel::before { content: ""; position: absolute; z-index: 2; top: 7px; left: 50%; width: 62px; height: 17px; margin-left: -31px; border-radius: 9px; background: var(--ink); }
.pv-cel__tela { position: absolute; inset: 0; padding-top: 30px; font-size: 12px; line-height: 1.45; }
.pv-cel ol, .pv-cel ul { margin: 0; padding: 0; list-style: none; }
.pv-t-topo { display: flex; align-items: center; gap: 5px; height: 36px; padding: 0 10px; border-bottom: 1px solid var(--rule); }
.pv-t-marca { margin-right: auto; font: 600 14px/1 var(--serif); }
.pv-t-hbtn { padding: 4px 6px; border: 1px solid var(--ctl); border-radius: 3px; font: 600 10px/1 var(--sans); }
.pv-t-corpo { padding: 12px 14px; }
.pv-t-sec { padding-bottom: 5px; margin-bottom: 8px; border-bottom: 1px solid var(--rule); font: 600 11px/1.3 var(--sans); color: var(--soft); }
.pv-t-sec--depois { margin-top: 16px; }
.pv-t-kicker { font: 400 11px/1.4 var(--sans); color: var(--soft); }
.pv-t-foco { margin-top: 3px; font: 500 19px/1.15 var(--serif); letter-spacing: -.01em; }
.pv-t-foco2 { margin-top: 4px; font: 400 14px/1.3 var(--serif); }
.pv-t-meta { margin-top: 6px; font: 400 10.5px/1.4 var(--sans); color: var(--soft); }
.pv-t-btn { display: block; margin-top: 12px; min-height: 34px; border: 1px solid var(--ctl); border-radius: 3px; text-align: center; font: 600 12px/34px var(--sans); }
.pv-t-btn--pri { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
.pv-t-link { display: block; margin-top: 10px; text-align: center; font: 600 11.5px/1.3 var(--sans); color: var(--accent); text-decoration: underline; }
.pv-t-idx li { display: grid; grid-template-columns: 1fr auto; column-gap: 8px; padding: 6px 0; border-bottom: 1px solid var(--rule); }
.pv-t-idx .n { font: 600 9.5px/1.3 var(--sans); color: var(--soft); }
.pv-t-idx .t { grid-column: 1; font: 400 12.5px/1.3 var(--serif); }
.pv-t-idx .d { grid-column: 2; grid-row: 1 / span 2; align-self: center; font: 400 10.5px/1 var(--sans); color: var(--soft); font-variant-numeric: tabular-nums; }
.pv-t-regua { position: relative; z-index: 1; display: flex; align-items: center; justify-content: space-between; gap: 6px; height: 34px; padding: 0 10px; border-bottom: 2px solid var(--accent); background: var(--paper); font: 600 10.5px/1.2 var(--sans); }
.pv-t-regua__b { color: var(--accent); }
.pv-t-regua__q { color: var(--soft); font-weight: 400; font-variant-numeric: tabular-nums; }
.pv-t-rolado { position: absolute; top: 64px; left: 0; right: 0; bottom: 0; display: flex; flex-direction: column; justify-content: flex-end; padding: 10px 11px 14px; overflow: hidden; }
.pv-t-enun { font: 500 12.5px/1.45 var(--serif); margin-bottom: 8px; }
.pv-t-opts { display: grid; gap: 5px; }
.pv-t-opt { display: grid; grid-template-columns: auto 1fr; column-gap: 7px; padding: 6px 7px; border: 1px solid var(--ctl); border-radius: 5px; font: 400 11.5px/1.4 var(--serif); }
.pv-t-letra { display: grid; place-items: center; width: 17px; height: 17px; border-radius: 50%; border: 1.5px solid var(--ctl); font: 600 9.5px/1 var(--sans); color: var(--soft); }
.pv-t-opt--certa { border-color: var(--accent); background: var(--accent-soft); }
.pv-t-opt--certa .pv-t-letra { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
.pv-t-opt--sua { border-style: dashed; }
.pv-t-opt--sua .pv-t-letra { background: var(--soft); border-color: var(--soft); color: var(--paper); }
.pv-t-otag { display: block; margin-top: 2px; font: 600 9.5px/1.3 var(--sans); color: var(--accent); font-style: normal; }
.pv-t-result { margin-top: 10px; padding-top: 8px; border-top: 1px solid var(--rule); font: 500 14px/1.35 var(--serif); }
.pv-t-coment { margin-top: 5px; font: 400 11.5px/1.5 var(--serif); }
.pv-t-fim__titulo { margin-top: 6px; font: 500 19px/1.2 var(--serif); }
.pv-t-fim__conta { margin-top: 6px; font: 400 14px/1.4 var(--serif); }
.pv-t-fim__nota { margin-top: 6px; font: 400 11px/1.45 var(--sans); color: var(--soft); }
.pv-t-volta { margin-top: 14px; padding: 2px 0 2px 10px; border-left: 3px solid var(--accent); }
.pv-t-volta__cab { font: 600 11px/1.3 var(--sans); }
.pv-t-volta__datas { display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px; margin-top: 6px; }
.pv-t-volta__datas b { display: block; font: 600 15px/1.1 var(--serif); font-variant-numeric: tabular-nums; }
.pv-t-volta__datas span { font: 400 9.5px/1.3 var(--sans); color: var(--soft); }
.pv-t-vitoria { margin-top: 8px; padding: 2px 0 2px 9px; border-left: 3px solid var(--accent); font: 500 13px/1.4 var(--serif); }
.pv-t-revisao .pv-t-enun { display: -webkit-box; -webkit-line-clamp: 6; -webkit-box-orient: vertical; overflow: hidden; }

/* ── a barra ("E a barra.") ─────────────────────────────────────────────────────────────── */
.pv-barra { background: var(--raised); border: 1px solid var(--rule); border-radius: 6px; padding: 20px 16px 16px; }
@media (min-width: 600px) { .pv-barra { padding: 24px 24px 18px; } }
.pv-barra__trilho { position: relative; height: 18px; border: 1.5px solid var(--ink); background: var(--paper); }
.pv-barra__trilho i { position: absolute; left: 0; top: 0; bottom: 0; width: var(--b, 0%); background: var(--accent); }
.pv-barra__nucleo { position: absolute; top: -9px; bottom: -9px; left: var(--n); width: 2px; margin-left: -1px; background: var(--ink); }
.pv-barra__pos { margin-top: 14px; font: 600 15px/1.3 var(--sans); font-variant-numeric: tabular-nums; }
body.pv48 .pv-barra__rever { font-size: 15px; }

/* ── a figura da S10: os mesmos assuntos em duas ordens ─────────────────────────────────── */
.pv-indice { margin: 32px 0 36px; max-width: 58rem; }
.pv-indice__linha + .pv-indice__linha { margin-top: 18px; }
.pv-indice__rot { margin-bottom: 6px; font: 600 14.5px/1.3 var(--sans); }
.pv-indice__svg { width: 100%; height: 40px; background: var(--raised); border-bottom: 1.5px solid var(--ink); }
.pv-indice__svg rect { fill: var(--accent); }
.pv-indice__eixo { display: flex; justify-content: space-between; margin-top: 6px; font: 400 13px/1.3 var(--sans); color: var(--soft); }

/* ══ S10 · o preço ══════════════════════════════════════════════════════════════════════════ */
.pv-preco {
  max-width: 30rem; margin-top: 44px; padding: 24px 20px 22px; background: var(--paper);
  border: 1.5px solid var(--ink); border-radius: 6px;
}
@media (min-width: 600px) { .pv-preco { padding: 30px 32px 26px; } }
.pv-preco__rot { font: 700 12.5px/1.3 var(--sans); letter-spacing: .06em; color: var(--soft); }
.pv-preco__parcela { margin-top: 6px; font: 560 46px/1.05 var(--serif); letter-spacing: -.02em; font-variant-numeric: tabular-nums; }
.pv-preco__parcela span:first-child { font: 500 .5em/1 var(--serif); letter-spacing: 0; }
.pv-preco__vista { margin-top: 4px; font: 500 30px/1.1 var(--serif); font-variant-numeric: tabular-nums; }
.pv-preco__rot--vista { margin-top: 18px; padding-top: 16px; border-top: 1px solid var(--rule); }
.pv-preco__frase { margin: 18px 0 20px; font: 400 17px/1.5 var(--serif); }
.pv-preco__frase strong { font-weight: 600; }
/* ⭐ P48-56 · Etapa 2 — o preço anterior riscado ACIMA do de agora, e a validade da oferta.
   As duas peças só existem com a âncora no banco. ⚠ O riscado é `aria-hidden`: ele é DECORAÇÃO
   redundante, e um `<s>` lido faria o leitor de tela anunciar dois preços soltos. `--soft`
   (#5D5D64) sobre o papel do cartão (#FAF9F6) mede 6,0:1 — acima do mínimo de 4,5:1 da AA. */
.pv-preco__de { margin-top: 4px; font: 400 21px/1.1 var(--serif); color: var(--soft); font-variant-numeric: tabular-nums; }
.pv-preco__ate { margin: -10px 0 20px; font: 400 14px/1.45 var(--sans); color: var(--soft); }

/* ══ S12 · P7, a garantia em certificado ═══════════════════════════════════════════════════ */
.pv-garantias { display: grid; gap: 36px; max-width: 46rem; }
.pv-garantias > .pv-prosa { max-width: var(--measure); }
.pv-cert {
  position: relative; margin-top: 26px; padding: 34px 22px 20px; background: var(--paper);
  border: 1.5px solid var(--ink); border-radius: 2px; font: 400 18px/1.6 var(--serif);
}
.pv-cert::before { content: ""; position: absolute; inset: 6px; border: 1px solid var(--accent); pointer-events: none; }
.pv-cert p + p { margin-top: .9em; }
.pv-cert__cab { display: block; margin-bottom: 10px; font: 560 24px/1.2 var(--serif); letter-spacing: -.01em; }
.pv-cert--rota .pv-cert__cab { margin-bottom: 0; font-size: 25px; }
.pv-cert__selo {
  position: absolute; top: -26px; right: 18px; display: grid; place-content: center; text-align: center;
  width: 78px; height: 78px; border-radius: 50%; background: var(--paper); border: 2px solid var(--accent);
  font: 600 11.5px/1.15 var(--sans); color: var(--accent);
}
.pv-cert__selo b { display: block; font: 560 25px/1 var(--serif); }
.pv-cert--rota .pv-cert__selo b { font: 600 13px/1.2 var(--sans); }
.pv-cert p.pv-cert__ass { margin-top: 18px; padding-top: 10px; border-top: 1px solid var(--rule); font: 600 13.5px/1.3 var(--sans); color: var(--soft); }
@media (min-width: 600px) {
  .pv-cert { padding: 40px 36px 24px; font-size: 19px; }
  .pv-cert__cab { font-size: 27px; }
  .pv-cert--rota .pv-cert__cab { font-size: 28px; }
}
/* Obs. 7 do owner (18/09): o selo é absoluto e o título ⛔ não reservava lugar para ele. O título
   abre um vão no canto de cima, do tamanho da parte do selo que entra no texto, mais 8 px de
   folga, e o texto contorna o vão. O selo vai de −26 a 52 px na vertical e ocupa 96 px a partir
   da borda direita (18 + 78). Largura do vão = 96 + 8 − padding direito; altura = 52 + 8 −
   padding de cima. ⛔ Nenhuma sobreposição em largura nenhuma (a régua mede). */
.pv-cert__cab::before { content: ""; float: right; width: 82px; height: 26px; }
@media (min-width: 600px) { .pv-cert__cab::before { width: 68px; height: 20px; } }
/* 320px: com 24/25px o título do certificado ficava abaixo de 9em da própria fonte. O padding
   lateral cai para 16 px, e o vão do selo cresce na mesma conta (96 + 8 − 16 = 88). */
@media (max-width: 359.98px) {
  .pv-cert { padding-left: 16px; padding-right: 16px; }
  .pv-cert__cab, .pv-cert--rota .pv-cert__cab { font-size: 22px; }
  .pv-cert__cab::before { width: 88px; }
}

/* ══ S13, S14 ═══════════════════════════════════════════════════════════════════════════════ */
body.pv48 .pv-prosa a[href^="mailto:"] { font-weight: 600; overflow-wrap: anywhere; }
.pv-fecho { font-weight: 500; }
body.pv48 .pv-h2--citacao { max-width: 20ch; }

/* ══ S15 · perguntas ════════════════════════════════════════════════════════════════════════ */
.pv-faq__grupo { max-width: 46rem; }
.pv-faq__grupo + .pv-faq__grupo { margin-top: 40px; }
body.pv48 .pv-faq__rot { padding-bottom: 10px; border-bottom: 1.5px solid var(--ink); font: 700 13px/1.3 var(--sans); letter-spacing: .06em; color: var(--ink); }
.pv-faq__grupo details { border-bottom: 1px solid var(--rule2); }
.pv-faq__grupo summary {
  position: relative; display: flex; align-items: center; min-height: 56px; padding: 12px 40px 12px 0;
  list-style: none; cursor: pointer; font: 600 17px/1.35 var(--sans);
}
.pv-faq__grupo summary::-webkit-details-marker { display: none; }
.pv-faq__grupo summary::after {
  content: ""; position: absolute; right: 8px; top: 50%; width: 10px; height: 10px; margin-top: -7px;
  border-right: 2px solid var(--ink); border-bottom: 2px solid var(--ink); transform: rotate(45deg);
}
.pv-faq__grupo details[open] summary::after { transform: rotate(-135deg); margin-top: -2px; }
.pv-faq__grupo details p { padding: 0 0 18px; font: 400 18px/1.6 var(--serif); max-width: var(--measure); }

/* ══ S16 · fechamento ═══════════════════════════════════════════════════════════════════════ */
.pv-fecho__acao { margin: 36px 0 44px; max-width: 34rem; }
.pv-ps p { padding-left: 14px; border-left: 3px solid var(--rule2); }
.pv-ps p + p { margin-top: 1.2em; }

/* ══ P48-17 · P3 — a lista que vira rota (S3) ═══════════════════════════════════════════════
   As regras são as do protótipo v6.2 (`app.css` §S3), com os seletores desta página. O estado
   ENTREGUE pelo servidor é "na ordem da rota": sem JavaScript a figura já está no estado final
   e completa. `data-modo="lista"` esconde o que só existe na rota (o bloco, o salto, a régua da
   parada e o "caiu N vezes") — é o que faz os dez parecerem ter o mesmo peso. */
.pv-reordena { background: var(--raised); border: 1px solid var(--rule); border-radius: 6px; padding: 16px 16px 20px; }
@media (min-width: 600px) { .pv-reordena { padding: 22px 24px 24px; } }
.pv-reordena__controle { display: grid; grid-template-columns: 1fr 1fr; border: 1px solid var(--ctl); border-radius: 4px; overflow: hidden; }
.pv-alterna {
  min-height: 44px; padding: 0 10px; border: 0; background: var(--paper); cursor: pointer;
  font: 600 15px/1.2 var(--sans); color: var(--ink);
}
.pv-alterna + .pv-alterna { border-left: 1px solid var(--ctl); }
.pv-alterna[aria-pressed="true"] { background: var(--ink); color: var(--paper); }
body.pv48 .pv-reordena__lista { margin-top: 14px; position: relative; }
.pv-rbloco {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 10px; padding: 16px 0 4px;
  font: 700 14px/1.3 var(--sans); color: var(--accent);
}
.pv-rbloco:first-child { padding-top: 6px; }
.pv-rbloco__d { font-weight: 400; color: var(--soft); font-variant-numeric: tabular-nums; }
/* ⚠ `--accent-selo`, ⛔ `--accent-soft`: o selo é o ÚNICO lugar em que a tinta translúcida
   fica atrás de TEXTO, e uma cor com alfa ⛔ tem contraste que se possa conferir sozinho — o
   que o olho vê é ela já composta sobre o papel. `--accent-selo` é exatamente essa composição
   (rgba(125,92,30,.12) sobre `--raised`), então a régua mede a cor que existe: 10,77:1. */
.pv-rbloco__pto { padding: 1px 7px; border-radius: 3px; background: var(--accent-selo); color: var(--ink); font: 600 12.5px/1.5 var(--sans); }
.pv-ritem { display: grid; gap: 2px; padding: 9px 0; border-bottom: 1px solid var(--rule); background: var(--raised); }
.pv-ritem__t { font: 400 17px/1.35 var(--serif); }
.pv-ritem__m { font: 400 13.5px/1.4 var(--sans); color: var(--soft); }
.pv-rsalto { padding: 14px 0 12px; font: 400 14px/1.3 var(--sans); color: var(--soft); border-bottom: 1px dashed var(--ctl); }
.pv-reordena[data-modo="lista"] .pv-rbloco,
.pv-reordena[data-modo="lista"] .pv-rsalto,
.pv-reordena[data-modo="lista"] .pv-rparada,
.pv-reordena[data-modo="lista"] .pv-ritem__q { display: none; }
.pv-reordena[data-modo="lista"] .pv-reordena__parada { visibility: hidden; }
.pv-rparada {
  position: relative; margin: 10px 0 2px; padding: 8px 0 0; border-top: 3px solid var(--accent);
  font: 700 14px/1.35 var(--sans); color: var(--accent);
}
.pv-rparada[hidden] { display: none; }
.pv-ritem--fora, .pv-rbloco--fora { padding-left: 12px; border-left: 2px dashed var(--ctl); }
/* ⭐ P48-31 · item 4 — o pontilhado SÓ na ordem da rota (o owner, no celular: "Aprovado").

   A marca de "fora do seu ponto de parada" é o pontilhado à esquerda, e ela só quer dizer
   alguma coisa ao lado da régua que a explica — a linha "o seu ponto de parada: bloco N", que
   é `.pv-rparada`, e que o modo lista esconde junto com o bloco e o salto. Em ordem alfabética
   sobravam itens pontilhados soltos, sem régua e sem legenda: marca sem significado.

   ⛔ Apagar a classe no JS: a marca é o resultado da conta, e ela tem de continuar lá para
   quando a pessoa voltar ao modo rota — voltar da lista ⛔ refaz a conta. Quem decide se ela
   APARECE é o modo, e modo é assunto da folha. O irmão `.pv-rbloco--fora` ⛔ precisa de regra:
   o bloco inteiro já tem `display: none` em modo lista. */
.pv-reordena[data-modo="lista"] .pv-ritem--fora { padding-left: 0; border-left: 0; }
.pv-reordena__parada { margin-top: 16px; font: 400 15px/1.5 var(--sans); }
.pv-reordena__leg { margin-top: 10px; }

/* ══ P48-17 · P5 — a aferição em pontos (S5b) ═══════════════════════════════════════════════
   As regras são as do protótipo v6.2 (`app.css` §S5b), com os seletores desta página. O estado
   ENTREGUE pelo servidor é o final: os círculos da rota já preenchidos, o ponteiro e a régua no
   lugar. `data-aguardando` é o estado de ESPERA que o JS liga quando vai animar, e a folha o
   desliga sozinha com movimento reduzido.

   Contraste (medido sobre `--paper` #FAF9F6): círculo apagado, número `--ink` 13,58:1 e contorno
   `--ctl` 3,57:1 (≥ 3:1, o teto do WCAG 2.2 para elemento não textual); círculo aceso, número
   `--paper` sobre `--ink`, 13,58:1; rótulo do teto, `--accent` 5,83:1. */
.pv-cartao__folha { border: 1.5px solid var(--ink); border-radius: 4px; padding: 16px 14px 14px; background: var(--paper); }
.pv-cartao__cab { display: flex; justify-content: space-between; align-items: flex-end; gap: 12px; padding-bottom: 12px; margin-bottom: 14px; border-bottom: 1px solid var(--rule2); }
.pv-cartao__nome { font: 600 14px/1.35 var(--sans); max-width: 16rem; }
.pv-cartao__conta { white-space: nowrap; }
.pv-cartao__n { font: 560 44px/1 var(--serif); font-variant-numeric: tabular-nums; letter-spacing: -.02em; }
body.pv48 .pv-cartao__grade { display: grid; grid-template-columns: repeat(10, minmax(0, 1fr)); gap: 7px 5px; }
/* ⚠ `body.pv48 .pv-bolha`, ⛔ `.pv-bolha`: a casca declara `body.pv48 button { color: inherit }`
   (0,1,1), que VENCE uma classe sozinha (0,1,0). Com o seletor curto, o número do círculo aceso
   herdava `--ink` sobre fundo `--ink` — 1:1, invisível. Quem achou foi a régua de contraste. */
body.pv48 .pv-bolha {
  display: grid; place-items: center; aspect-ratio: 1; border-radius: 50%;
  border: 1.5px solid var(--ctl); background: var(--paper);
  font: 600 10.5px/1 var(--sans); color: var(--ink); font-variant-numeric: tabular-nums;
  position: relative; width: 100%; margin: 0; padding: 0; cursor: pointer;
  -webkit-appearance: none; appearance: none;
}
/* A área de TOQUE cobre a célula inteira da grade, até a metade do vão de cada lado (7 px entre
   linhas, 5 px entre colunas, mais 1,5 px de borda), sem invadir o vizinho. */
.pv-bolha::after { content: ""; position: absolute; inset: -5px -4px; }
body.pv48 .pv-bolha--sim { background: var(--ink); border-color: var(--ink); color: var(--paper); }
body.pv48 .pv-cartao[data-aguardando] .pv-bolha--sim:not(.is-acesa) { background: var(--paper); border-color: var(--ctl); color: var(--ink); }
.pv-bolha[aria-current="true"] { box-shadow: 0 0 0 2px var(--paper), 0 0 0 4px var(--ink); }
@media (prefers-reduced-motion: no-preference) {
  .pv-bolha { transition: background-color 160ms ease-out, color 160ms ease-out, border-color 160ms ease-out, transform 160ms ease-out; }
}
@media (min-width: 600px) { body.pv48 .pv-bolha { font-size: 11.5px; } .pv-cartao__folha { padding: 20px 20px 16px; } }
.pv-cartao__assunto { min-height: 1.45em; margin-top: 12px; font: 400 14.5px/1.45 var(--sans); color: var(--ink); }
.pv-regua { position: relative; height: 74px; margin-top: 16px; }
.pv-regua__trilho { position: absolute; left: 0; right: 0; top: 34px; height: 2px; background: var(--ctl); }
.pv-regua__cheio { position: absolute; left: 0; top: 32px; height: 6px; width: var(--v, 0%); background: var(--ink); }
.pv-regua__teto { position: absolute; left: var(--teto, 0%); top: 18px; height: 36px; width: 2px; margin-left: -1px; background: var(--accent); }
.pv-regua__ponteiro { position: absolute; left: var(--v, 0%); top: 29px; width: 12px; height: 12px; margin-left: -6px; border-radius: 50%; background: var(--ink); border: 2px solid var(--paper); }
/* ⚠ Os dois rótulos são IRMÃOS das marcas, ⛔ filhos: dentro delas o texto ficaria sobre a
   própria cor da marca (a linha do teto é `--accent`, o ponteiro é `--ink`) — 1:1 na régua de
   contraste, e ilegível de verdade em quem herdasse o fundo. Aqui o fundo é o do cartão. */
.pv-regua__rotulo { position: absolute; white-space: nowrap; font: 700 13px/1.2 var(--sans); transform: translateX(-100%); }
.pv-regua__rotulo--teto { left: var(--teto, 0%); top: 14px; margin-left: -7px; color: var(--accent); }
.pv-regua__rotulo--ponteiro { left: var(--v, 0%); top: 49px; margin-left: 3px; color: var(--ink); }
.pv-cartao[data-aguardando] .pv-regua__rotulo { opacity: 0; }
@media (prefers-reduced-motion: no-preference) {
  .pv-regua__rotulo { transition: opacity 260ms ease-out; }
}
.pv-regua__zero, .pv-regua__oitenta { position: absolute; top: 42px; font: 400 12.5px/1 var(--sans); color: var(--soft); }
.pv-regua__zero { left: 0; }
.pv-regua__oitenta { right: 0; }

/* ══ P48-17 · P4 — a Volta do Erro em movimento (S8) ════════════════════════════════════════
   As regras são as do protótipo v6.2 (`app.css` §S8), com os seletores desta página. Sem
   JavaScript (e com movimento reduzido) os quatro estados ficam EMPILHADOS e legíveis: é o
   estado padrão do CSS. `data-anima`, que só o JS liga, é que os empilha numa área só. */
.pv-volta { margin-top: 22px; background: var(--raised); border: 1px solid var(--rule); border-radius: 6px; padding: 18px 16px; }
.pv-volta__eixo { position: relative; height: 92px; margin: 0 6px 14px; }
.pv-volta__linha { position: absolute; left: 0; right: 0; top: 45px; height: 2px; background: var(--ink); }
.pv-volta__parada { position: absolute; top: 0; bottom: 0; width: 0; }
.pv-volta__parada[data-volta-parada="0"] { left: 0; }
.pv-volta__parada[data-volta-parada="3"] { left: 10%; }
.pv-volta__parada[data-volta-parada="10"] { left: 33.333%; }
.pv-volta__parada[data-volta-parada="30"] { left: 100%; }
.pv-volta__parada i { position: absolute; top: 39px; left: -7px; width: 14px; height: 14px; border-radius: 50%; border: 2px solid var(--ink); background: var(--paper); }
.pv-volta__parada.is-passou i { background: var(--ink); }
.pv-volta__parada em { position: absolute; top: 62px; white-space: nowrap; font-style: normal; font-variant-numeric: tabular-nums; font: 400 13px/1.2 var(--sans); color: var(--soft); }
.pv-volta__parada[data-volta-parada="3"] em, .pv-volta__parada[data-volta-parada="30"] em { top: 16px; }
.pv-volta__parada[data-volta-parada="0"] em { left: -6px; }
.pv-volta__parada[data-volta-parada="3"] em, .pv-volta__parada[data-volta-parada="10"] em { transform: translateX(-50%); }
.pv-volta__parada[data-volta-parada="30"] em { right: -6px; }
.pv-volta__ficha {
  position: absolute; top: 36px; left: var(--p, 0%); width: 20px; height: 20px; margin-left: -10px;
  border-radius: 50%; background: var(--accent); border: 3px solid var(--paper); box-sizing: border-box;
  display: none;
}
.pv-volta[data-anima] .pv-volta__ficha { display: block; }
body.pv48 .pv-volta__estados { display: grid; gap: 8px; }
.pv-volta__estados li { padding-left: 12px; border-left: 3px solid var(--rule2); font: 400 16px/1.45 var(--serif); }
.pv-volta__estados b { font-weight: 600; }
.pv-volta[data-anima] .pv-volta__estados { grid-template-areas: "e"; }
.pv-volta[data-anima] .pv-volta__estados li { grid-area: e; visibility: hidden; border-left-color: var(--accent); }
.pv-volta[data-anima] .pv-volta__estados li.is-ativo { visibility: visible; }
@media (prefers-reduced-motion: no-preference) {
  .pv-volta__ficha { transition: left 220ms cubic-bezier(.2,.7,.2,1); }
}

/* ══ P48-17 · a demonstração — cinco questões do bloco 1 ════════════════════════════════════
   As regras são as do protótipo v6.2 (§demonstração), com TRÊS mudanças, e as três têm o mesmo
   motivo: ⛔ escrever palavra que a fonte congelada ⛔ aprovou.

   1. ⛔ há `::after` com " ✓ resposta" / " ✗ você marcou". Aquilo é TEXTO, escrito pelo CSS, e
      ⛔ está na v6 nem na v2. O estado da alternativa fica no desenho (borda, cor, o disco da
      letra) e, para quem usa leitor de tela, em `aria-pressed` — a resposta certa é dita logo
      abaixo, pela frase aprovada "A resposta é (x).";
   2. ⛔ há `text-transform: uppercase` no contador da questão. A régua da página varre as
      folhas por caixa alta e casa os seletores contra o DOM: ali, a frase aprovada chegaria à
      tela GRITADA;
   3. o estado ENTREGUE pelo servidor é o final — as cinco questões abertas, com a resposta e o
      porquê. `data-uma-a-uma`, que só o JS liga, é que as fecha. */
.pv-demo { max-width: 46rem; }
.pv-demo__aviso {
  margin-bottom: 28px; padding: 12px 14px; border-left: 3px solid var(--accent);
  background: var(--raised); font: 400 16px/1.5 var(--serif);
}
body.pv48 .pv-demo__lista { display: grid; gap: 40px; }
.pv-demoq { padding-bottom: 8px; }
.pv-demoq + .pv-demoq { border-top: 1px solid var(--rule); padding-top: 32px; }
.pv-demoq__conta { font: 600 13px/1.35 var(--sans); letter-spacing: .04em; color: var(--soft); }
.pv-demoq__enun { margin-top: 12px; font: 400 18px/1.55 var(--serif); }
.pv-demoq__enun strong { font-weight: 600; }
body.pv48 .pv-demoq__opts { display: grid; gap: 8px; margin-top: 18px; }
body.pv48 .pv-opt {
  display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 10px; align-items: start;
  width: 100%; min-height: 44px; padding: 12px 14px; text-align: left; cursor: pointer;
  border: 1px solid var(--ctl); border-radius: 4px; background: var(--paper);
  font: 400 16px/1.5 var(--serif); color: var(--ink);
}
.pv-opt__l {
  display: grid; place-items: center; width: 24px; height: 24px; border-radius: 50%;
  border: 1px solid var(--ctl); background: var(--paper);
  font: 600 13px/1 var(--sans); color: var(--ink);
}
body.pv48 .pv-opt:hover { border-color: var(--ink); }
body.pv48 .pv-opt:active { background: var(--quiet); }
body.pv48 .pv-opt[data-estado] { cursor: default; }
body.pv48 .pv-opt[data-estado="certa"] { border-color: var(--accent); border-width: 2px; background: var(--accent-selo); }
body.pv48 .pv-opt[data-estado="certa"] .pv-opt__l { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
body.pv48 .pv-opt[data-estado="sua"] { border-style: dashed; border-color: var(--soft); }
body.pv48 .pv-opt[data-estado="sua"] .pv-opt__l { background: var(--soft); border-color: var(--soft); color: var(--paper); }
.pv-demoq__resp { margin-top: 20px; padding-top: 16px; border-top: 1px solid var(--rule2); }
.pv-demoq__veredito { font: 500 20px/1.3 var(--serif); }
.pv-demoq__coment { margin-top: 10px; font: 400 16.5px/1.6 var(--serif); max-width: var(--measure); }
.pv-demoq__coment strong { font-weight: 600; }
.pv-demoq__coment em { font-style: italic; }
.pv-demoq__coment p + p { margin-top: .8em; }
.pv-demoq__pe { margin-top: 20px; }
.pv-demo__fecho { margin-top: 36px; padding-top: 20px; border-top: 1px solid var(--rule2); font: 400 17px/1.55 var(--serif); }
.pv-demo__fecho p + p { margin-top: 20px; }
.pv-demo__tudo { margin-top: 28px; }
body.pv48 .pv-demo__abrir {
  min-height: 44px; padding: 0; border: 0; background: none; cursor: pointer;
  font: 400 15px/1.4 var(--sans); color: var(--accent); text-decoration: underline;
  text-underline-offset: .18em; text-align: left;
}
/* Um por vez: o que o JS liga. Sem ele (e sem JavaScript), as cinco ficam abertas. */
.pv-demo[data-uma-a-uma] .pv-demoq:not(.is-atual) { display: none; }
.pv-demo[data-uma-a-uma] .pv-demoq__resp { display: none; }
.pv-demo[data-uma-a-uma] .pv-demoq.is-respondida .pv-demoq__resp { display: block; }
.pv-demo[data-uma-a-uma] .pv-demoq + .pv-demoq { border-top: 0; padding-top: 0; }

/* ── P48-21 · falar comigo antes de decidir ───────────────────────────────────────────────

   Dois pontos, a MESMA peça: abaixo do botão de compra da S2 e depois do FAQ. O desenho diz a
   hierarquia sem precisar de palavra: o CTA de compra é preenchido, dourado, 52px e 17/700; este
   é CONTORNO, sem dourado, 44px e 15/600, e vem sempre DEPOIS, nunca ao lado. Do verde só o
   ícone — o dourado continua sendo exclusividade dos CTAs de compra.

   ⚠ Especificidade: `body.pv48 main a` (0,1,3) impõe tinta `--accent` e sublinhado a todo link
   do corpo. Por isso o botão se escreve `body.pv48 .pv-wa__botao` (0,2,1) — ⛔ é preferência de
   estilo, é o que impede o reset da página de engolir a cor deste controle (a lição do B02).

   ⚠ ⛔ Há `data-clarity-mask` aqui, e ⛔ deve haver: este bloco ⛔ coleta nada. Não há campo,
   não há escolha e não há nada que a pessoa produza sobre ela mesma — só um link para fora. */
.pv-wa { display: flex; flex-direction: column; align-items: flex-start; gap: 10px; }
body.pv48 .pv-wa__pergunta {
  margin: 0; font: 400 14px/1.45 var(--sans); color: var(--soft); max-width: var(--measure);
}
body.pv48 .pv-wa__botao {
  display: inline-flex; align-items: center; justify-content: center; gap: 10px;
  width: 100%; min-height: 44px; padding: 10px 18px;
  border: 1px solid var(--ctl); border-radius: 4px; background: none;
  color: var(--ink); font: 600 15px/1.3 var(--sans);
  text-decoration: none; text-align: center; overflow-wrap: anywhere;
}
body.pv48 .pv-wa__icone { flex: none; color: var(--whatsapp); }
body.pv48 .pv-wa__botao:hover, body.pv48 .pv-wa__botao:focus-visible { border-color: var(--ink); }

/* ⭐ P48-26 · depois do FAQ o bloco ⛔ está mais sozinho: ele é o FIM DO FAQ.

   Até aqui ele era uma seção própria entre a S15 e a S16, e a moldura (`--raised`, borda, raio)
   era o que o ancorava no papel. O owner viu a página no desktop e apontou o defeito: o FAQ é
   uma faixa `--raised` de borda a borda, e logo abaixo dela flutuava uma caixinha `--raised` de
   500px — o mesmo fundo em duas escalas, a 40px de distância. Duas vezes o mesmo material ⛔
   é hierarquia; é ruído.

   Agora ele mora DENTRO do `.pv-wrap` da S15, e o fundo dele é o da faixa. Sem caixa: o que
   separa a última pergunta do convite é um fio, como entre dois `<details>` do próprio FAQ.
   Na S2 continua ⛔ havendo moldura nenhuma — lá ele é apoio do botão, e uma caixa competiria
   com o cartão de compra. */
.pv-wa--pos_faq {
  margin-top: 36px; padding-top: 28px; border-top: 1px solid var(--rule);
  /* ⚠ A MESMA medida dos grupos de perguntas (`.pv-faq__grupo`, 46rem), e ⛔ é coincidência: o
     fio é a linha que fecha a lista, e ele tem de terminar onde a última pergunta termina. A
     partir de 1360px o `.pv-wrap` ganha o corredor do trilho e vai a 1420px, enquanto os grupos
     continuam em 736px; sem este limite o fio media 1152px e apontava para 400px de papel vazio
     à direita do FAQ. ⚠ Medido na base: a caixa velha JÁ tinha 1152px em 1440px — só que, como
     caixa fechada e solta no papel, o desalinho lia como "outro bloco". Como coda, lê como
     erro. */
  max-width: 46rem;
}
@media (min-width: 600px) {
  body.pv48 .pv-wa__botao { width: auto; }
}

/* ══ P48-23 · A FORMA NO DESKTOP ═══════════════════════════════════════════════════════════
   O owner leu a página inteira no desktop em 19/09 e o diagnóstico foi de COMPOSIÇÃO, ⛔ de
   texto: "parece alinhado à esquerda". Medido (`docs/evidence/p48-23/forma-antes-1440.json`),
   em 1440 px: 608 px de prosa à esquerda e, em oito das dezesseis seções, 416 a 512 px de nada
   à direita — 36 % a 44 % do envelope. A direção de arte já dizia o que fazer (§4): "duas
   colunas assimétricas — prosa à esquerda em 38rem, a PEÇA da seção à direita, fixa enquanto a
   prosa rola; seção sem peça centraliza a prosa. ⛔ Coluna vazia."

   São duas regras, e ⛔ há terceira:

   1. `.pv-sec--centro` — a seção ⛔ tem peça: o envelope de leitura encolhe para `--coluna` e se
      centraliza. A medida de leitura ⛔ muda; muda a POSIÇÃO dela;
   2. `.pv-sec--dupla` + `.pv-fixa` — a seção TEM peça: a prosa ocupa `--measure` à esquerda, a
      peça vai para a segunda coluna e acompanha a prosa (`position: sticky`).

   Tudo isto é ≥ 1100 px. No celular a grade já é coluna única e está certa: ⛔ há uma linha
   destas fora da `@media`, e a régua de `forma-depois-390.json` prova, caixa por caixa, que em
   390 px ⛔ mudou nada. */
@media (min-width: 1100px) {
  /* ── 1 · a seção sem peça centraliza a prosa ─────────────────────────────────────────── */
  .pv-sec--centro > .pv-wrap { max-width: calc(var(--coluna) + 2 * var(--gutter)); }
  /* Os quadros largos da página. ⛔ São exceção de gosto: `.pv-garantias` (46rem) e o FAQ
     (46rem) são a LARGURA DA PEÇA, e encolhê-las para 38rem mudaria a peça, que esta fatia ⛔
     toca. O que muda nelas é só a posição, como em todas as outras.
     ⭐ P48-26: `.pv-sec--wa` saiu desta lista porque a seção saiu da página — o bloco do
     WhatsApp virou a coda do FAQ, e quem lhe dá a largura agora é o `.pv-wrap` da S15. */
  .pv-sec--s12, .pv-sec--s15 { --coluna: 46rem; }

  /* ── 2 · a seção com peça: prosa à esquerda, peça à direita, fixa ────────────────────── */
  .pv-fixa { position: sticky; top: var(--fixa-topo); align-self: start; }
  .pv-sec--dupla > .pv-wrap {
    display: grid; grid-template-columns: minmax(0, var(--measure)) minmax(0, 1fr);
    column-gap: 72px; row-gap: 0; align-items: start;
  }
  .pv-sec--dupla > .pv-wrap > * { grid-column: 1; }
  /* ⚠ `span 9`, ⛔ `1 / -1`: sem linhas explícitas, `-1` é o fim da grade EXPLÍCITA, que aqui é
     a linha 1 — a peça ficaria com a altura da primeira faixa e ⛔ teria por onde acompanhar. As
     faixas implícitas que sobrarem têm altura zero (e `row-gap` é zero), então elas ⛔ empurram
     nada. `test_p48_23_desktop_e_botoes` prova que ⛔ há seção dupla com mais de 9 filhos. */
  .pv-sec--dupla > .pv-wrap > .pv-fixa { grid-column: 2; grid-row: 1 / span 9; }
  /* Na grade a peça começa no alto da seção; a margem que a separava do texto acima ⛔ serve. */
  .pv-sec--dupla > .pv-wrap > .pv-preco { margin-top: 0; }

  /* ── 3 · a S8: a tira das quatro molduras vira o TRILHO da direita ───────────────────────
     A tira do topo (`.pv-celulares`) e os itens moram em caixas diferentes — ela sangra até a
     borda da tela no celular, e por isso ⛔ mora dentro do `.pv-wrap`. `.pv-s8` é a caixa que
     junta as duas SEM mexer na ordem de leitura: no celular ela é um `div` liso e ⛔ muda uma
     medida; aqui ela é a grade.

     ⚠ As duas ficam na MESMA faixa, e o `.pv-wrap` ocupa as duas colunas: é isso que deixa "E a
     barra." continuar com a largura inteira e a barra no lugar em que ela já estava. Os itens
     numerados é que ficam presos à coluna de leitura (`max-width` abaixo), e por isso ⛔ passam
     por baixo do trilho. Quando a barra entra na tela o trilho fica VAZIO — quem manda nisso é
     o JS, e é o que impede a moldura de cair por cima dela.

     ⭐ FALHA ABERTA, e ela é `[data-trilho="vivo"]`. Quem esconde três das quatro molduras é o
     `display: none` daqui; quem diz qual fica é o `data-atual` que o JS põe. Se a folha
     escondesse por conta própria e o JS ⛔ subisse — erro dele, navegador velho, script
     bloqueado —, o desktop ficaria com QUATRO molduras invisíveis e uma coluna vazia no lugar
     da peça. Então a folha ⛔ esconde nada até o JS DIZER que está de pé: ele marca a caixa, e
     é a marca que liga a grade, o trilho e o esconde-esconde. Sem ela, a página é a de antes —
     as quatro molduras em fila, acima dos itens. */
  html.com-js .pv-s8[data-trilho="vivo"] {
    display: grid; grid-template-columns: minmax(0, var(--measure)) minmax(0, 1fr);
    column-gap: 72px; align-items: start;
    width: 100%; max-width: calc(var(--wide) + 2 * var(--gutter));
    margin: 0 auto; padding: 0 var(--gutter);
  }
  .pv-s8[data-trilho="vivo"] > .pv-wrap { grid-column: 1 / -1; grid-row: 1; max-width: none; padding: 0; }
  .pv-s8[data-trilho="vivo"] > .pv-celulares {
    grid-column: 2; grid-row: 1; display: flex; justify-content: flex-end; align-items: flex-start;
    gap: 16px; margin: 0; padding: 0; overflow: visible;
    position: sticky; top: var(--fixa-topo);
  }
  /* 56px do número mais 10px do vão mais a medida de leitura: é até aqui que o item pode ir, e
     o trilho começa 6px depois (608 + 72). É isto que impede o título de um item de passar por
     baixo da moldura fixa. "E a barra." ⛔ entra: ela é a peça daquele item, e continua com a
     largura inteira, no lugar em que já estava. */
  .pv-s8[data-trilho="vivo"] .pv-item:not(.pv-item--barra) { max-width: calc(66px + var(--measure)); }
  .pv-s8[data-trilho="vivo"] .pv-celular { flex: 1 1 0; min-width: 0; max-width: 268px; display: none; }
  .pv-s8[data-trilho="vivo"] .pv-celular[data-atual] { display: block; }
  .pv-s8[data-trilho="vivo"] .pv-celular__leg { max-width: none; }
}
/* Telas baixas: a moldura inteira tem de caber na altura, senão o pé dela fica cortado pelo fim
   da tela e a peça deixa de ser peça. */
@media (min-width: 1100px) and (max-height: 820px) {
  .pv-s8[data-trilho="vivo"] .pv-celular { max-width: 226px; }
}
/* A troca da moldura é o ÚNICO movimento novo desta fatia, e é o mesmo `pv-aparece` que o topo
   já usa: a que entra aparece, a que saiu some. Com movimento reduzido ⛔ há troca animada —
   o bloco `prefers-reduced-motion: reduce` lá embaixo desliga toda animação da página.
   ⭐ P48-25 · item 2 — `[data-trocou]`: a PRIMEIRA moldura ⛔ anima. Quem põe a marca é o JS, e
   só a partir da segunda troca (ver `criarTrilho` em `pagina-vendas-48-uau.js`). A S8 fica muito
   abaixo da primeira dobra: animar ali no carregamento é movimento que ninguém vê acontecer. */
@media (min-width: 1100px) and (prefers-reduced-motion: no-preference) {
  .pv-s8[data-trilho="vivo"][data-trocou] .pv-celular[data-atual] { animation: pv-aparece 240ms ease-out both; }
}

/* ══ P48-25 · item 1 — OS ESTADOS DE TUDO QUE SE CLICA ═════════════════════════════════════

   O diagnóstico do MENTOR (19/09, 00h35): a folha inteira tinha DOIS `:hover` e UM `:active`.
   "Hover morto" — elemento clicável que ⛔ reage ao ponteiro — é o sinal mais barato de página
   gerada, porque é o que ninguém escreve quando ⛔ há decisão: o navegador ⛔ inventa estado,
   e um botão que fica idêntico sob a mão parece impresso, ⛔ vivo.

   A regra desta fatia, e ela é uma só: o estado se diz com a PALETA QUE EXISTE.
   ⛔ bounce, ⛔ escala, ⛔ cor nova. Três gestos, e cada um tem um papel:

   - `:hover`  — a superfície reconhece a mão: muda BORDA, FUNDO ou SUBLINHADO. Nada se move.
   - `:active` — a superfície cede: `translateY(1px)`. É o único movimento, e é o mesmo em
                 todo controle, porque a pressão é a mesma em todo controle.
   - `:focus-visible` — o anel de 3px em `--focus`, declarado UMA vez lá em cima
                 (`body.pv48 :focus-visible`). ⛔ Se repete aqui: um anel por controle seria
                 quinze cópias da mesma decisão, e a décima sexta peça nasceria sem anel. O
                 anel é um PISO, como o reset de B02 — e `test_p48_25_acabamento` prova que ele
                 alcança cada controle e que ninguém o desliga.

   ⚠ Contraste: os únicos estados que mexem em tinta sob texto são o botão de compra
   (`--accent-escuro`, 7,23:1 contra 5,83:1 em repouso), a pergunta do FAQ e a alternativa da
   demonstração (`--quiet`, 11,47:1) e o link premido (`--accent-escuro` sobre papel, 7,23:1).
   Todos SOBEM. A régua de P48-19 ⛔ mede pseudo-classe (`casa()` as recusa, e com razão), e por
   isso quem mede os estados é a régua desta fatia, que resolve cada par frente/fundo à mão.

   ⚠ Tudo o que segue vale sem movimento reduzido: as transições moram no bloco
   `no-preference`, e o `reduce` lá embaixo desliga o resto com `!important`. Com movimento
   reduzido os estados continuam EXISTINDO — eles só trocam na hora, sem rampa. */

/* A rampa é a mesma em toda a página: 140ms, com a curva de saída que o resto da folha já usa.
   ⛔ `linear` — nada no mundo físico começa e para na mesma velocidade. */
@media (prefers-reduced-motion: no-preference) {
  body.pv48 .pv-cta,
  body.pv48 .pv-link,
  body.pv48 .pv-entrar,
  body.pv48 .pv-atalho,
  body.pv48 .pv-alterna,
  body.pv48 .pv-opt,
  body.pv48 .pv-demo__abrir,
  body.pv48 .pv-wa__botao,
  body.pv48 .pv-campo__entrada,
  body.pv48 .pv-opcao,
  body.pv48 .pv-opcao input,
  body.pv48 .pv-pular,
  body.pv48 .pv-faq__grupo summary,
  body.pv48 .pv-faq__grupo summary::after,
  body.pv48 main a {
    transition:
      background-color 140ms cubic-bezier(.2, .7, .2, 1),
      border-color 140ms cubic-bezier(.2, .7, .2, 1),
      color 140ms cubic-bezier(.2, .7, .2, 1),
      box-shadow 140ms cubic-bezier(.2, .7, .2, 1),
      text-underline-offset 140ms cubic-bezier(.2, .7, .2, 1),
      text-decoration-thickness 140ms cubic-bezier(.2, .7, .2, 1),
      transform 140ms cubic-bezier(.2, .7, .2, 1);
  }
}

/* ── O botão de compra ──────────────────────────────────────────────────────────────────
   ⚠ `[aria-disabled="true"]` é o botão SEM identidade de release: ele ⛔ tem destino, e por
   isso ⛔ pode reagir como se tivesse. Hover morto ali ⛔ é esquecimento — é a verdade. */
body.pv48 .pv-cta:hover { background: var(--accent-escuro); border-color: var(--accent-escuro); }
body.pv48 .pv-cta:active { background: var(--accent-escuro); border-color: var(--accent-escuro); transform: translateY(1px); }
body.pv48 .pv-cta[aria-disabled="true"]:hover,
body.pv48 .pv-cta[aria-disabled="true"]:active { background: var(--accent); border-color: var(--accent); transform: none; }

/* ── Link de texto: o sublinhado desce e engrossa ──────────────────────────────────────── */
body.pv48 main a:hover { text-underline-offset: .28em; text-decoration-thickness: 2px; }
body.pv48 main a:active { color: var(--accent-escuro); }
body.pv48 .pv-link:hover { text-underline-offset: .28em; text-decoration-thickness: 2px; }
body.pv48 .pv-link:active { color: var(--accent-escuro); transform: translateY(1px); }
/* O botão de compra é `<a>` e ⛔ tem sublinhado: o estado dele é o de cima, ⛔ este. */
body.pv48 main a.pv-cta:hover { text-underline-offset: .18em; text-decoration-thickness: auto; }
body.pv48 main a.pv-cta:active { color: var(--on-accent); }

/* ── Pular para o conteúdo (só existe sob foco, e mesmo assim reage) ───────────────────── */
body.pv48 .pv-pular:hover { background: var(--accent-escuro); }
body.pv48 .pv-pular:active { transform: translateY(1px); }

/* ── Cartão da galeria: a sombra curta da direção de arte §5 ──────────────────────────────
   ⚠ `--rule` é tinta de FIO, e aqui ela é sombra: ⛔ há tinta com alfa atrás de texto nenhum.
   ⚠ Sem JavaScript a lupa ⛔ abre (o `cursor: default` acima já diz isso): ali o cartão ⛔ é
   clicável, e um hover ⛔ pode prometer o que a página ⛔ cumpre. */
body.pv48 .pv-galeria__abrir:hover { border-color: var(--ink); box-shadow: 0 2px 10px var(--rule); }
body.pv48 .pv-galeria__abrir:active { border-color: var(--ink); box-shadow: none; transform: translateY(1px); }
html.sem-js body.pv48 .pv-galeria__abrir:hover,
html.sem-js body.pv48 .pv-galeria__abrir:active { border-color: var(--rule); box-shadow: none; transform: none; }

/* ⭐ P48-31 · o × da lupa, no mesmo contrato de estado dos outros controles da página (P48-25):
   a superfície reage sob a mão e cede 1px sob o dedo. ⚠ `background` ⛔ muda no `:hover` — o
   botão já é tinta cheia; o que muda é o cerco, que é o que diz "este é o alvo". */
@media (prefers-reduced-motion: no-preference) {
  body.pv48 .pv-lupa__fechar { transition: box-shadow 140ms ease-out, transform 140ms ease-out; }
}
body.pv48 .pv-lupa__fechar:hover { box-shadow: 0 0 0 3px var(--paper), 0 0 0 4px var(--ink); }
body.pv48 .pv-lupa__fechar:active { box-shadow: none; transform: translateY(1px); }

/* ── Círculo da aferição: borda mais forte, e o âmbar sob a mão ───────────────────────── */
body.pv48 .pv-bolha:hover { border-color: var(--ink); }
body.pv48 .pv-bolha--sim:hover { border-color: var(--accent); }
body.pv48 .pv-bolha:active { background: var(--quiet); border-color: var(--ink); transform: translateY(1px); }
body.pv48 .pv-bolha--sim:active { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }

/* ── Alternativa da demonstração: a borda já forte, e a pressão ───────────────────────────
   `:hover` e `:active` de `.pv-opt` já existiam (P48-17). O que faltava: a alternativa JÁ
   RESPONDIDA ⛔ é clicável (`cursor: default`), e continuava reagindo como se fosse. */
body.pv48 .pv-opt:active { transform: translateY(1px); }
body.pv48 .pv-opt[data-estado]:hover { border-color: var(--ctl); }
body.pv48 .pv-opt[data-estado]:active { background: var(--paper); transform: none; }
body.pv48 .pv-opt[data-estado="certa"]:hover,
body.pv48 .pv-opt[data-estado="certa"]:active { border-color: var(--accent); background: var(--accent-selo); }
body.pv48 .pv-opt[data-estado="sua"]:hover,
body.pv48 .pv-opt[data-estado="sua"]:active { border-color: var(--soft); background: var(--paper); }

/* ── Pergunta do FAQ ──────────────────────────────────────────────────────────────────────
   ⚠ A sombra dos dois lados estende o fundo 10px além do texto SEM mexer no `padding`: a
   caixa da pergunta ⛔ muda de tamanho sob a mão (isso empurraria a lista inteira), e
   `box-shadow` ⛔ entra na conta da rolagem lateral. */
body.pv48 .pv-faq__grupo summary:hover { background: var(--quiet); box-shadow: -10px 0 0 var(--quiet), 10px 0 0 var(--quiet); }
body.pv48 .pv-faq__grupo summary:hover::after { border-color: var(--accent); }
body.pv48 .pv-faq__grupo summary:active { transform: translateY(1px); }

/* ── Os botões pequenos da Conta e da S3 ────────────────────────────────────────────────
   ⚠ `.pv-alterna` selecionado tem fundo `--ink` e tinta `--paper`. Um `:hover` que clareasse o
   fundo levaria a tinta clara para cima de tinta clara — o defeito B02 outra vez, agora por
   estado. Por isso o sinal dele é uma SUBLINHA interna em âmbar, que funciona igual nos dois
   estados e ⛔ toca em cor de texto nenhuma. */
body.pv48 .pv-atalho:hover { border-color: var(--ink); }
body.pv48 .pv-atalho:active { background: var(--quiet); transform: translateY(1px); }
body.pv48 .pv-alterna:hover { box-shadow: inset 0 -3px 0 var(--accent); }
body.pv48 .pv-alterna:active { box-shadow: inset 0 -3px 0 var(--accent); transform: translateY(1px); }
body.pv48 .pv-demo__abrir:hover { text-underline-offset: .28em; text-decoration-thickness: 2px; }
body.pv48 .pv-demo__abrir:active { color: var(--accent-escuro); transform: translateY(1px); }

/* ── Falar comigo (o botão de contorno) ─────────────────────────────────────────────────── */
body.pv48 .pv-wa__botao:active { border-color: var(--ink); transform: translateY(1px); }

/* ── Os campos da Conta da Prova ─────────────────────────────────────────────────────────
   ⚠ `.pv-campo__dado` ⛔ entra: ele é a data que EU já respondi (`readonly`, sem caixa e sem
   borda, P48-16c). Um campo só-leitura que reage ao ponteiro promete edição que ⛔ existe. */
body.pv48 .pv-campo__entrada:hover { border-color: var(--ink); }
body.pv48 .pv-campo__entrada:active { border-color: var(--ink); }
body.pv48 .pv-opcao:hover { text-decoration: underline; text-underline-offset: .2em; }
body.pv48 .pv-opcao:active { transform: translateY(1px); }
body.pv48 .pv-opcao input:hover,
body.pv48 .pv-opcao:hover input { box-shadow: 0 0 0 4px var(--accent-soft); border-radius: 50%; }
body.pv48 .pv-opcao input:active { transform: translateY(1px); }

/* ══ P48-25 · item 4 — O TRILHO DE RÓTULOS, e a grade assimétrica de verdade ════════════════

   A P48-23 tirou a coluna vazia da direita pondo a PEÇA da seção lá. Ficou faltando o outro
   lado: a prosa continuava encostada na borda esquerda do envelope, e uma página de dezesseis
   seções ⛔ dizia em que parte dela a pessoa está. Agora a grade é a da direção de arte §4,
   inteira: **trilho (estreito) · prosa (38rem) · peça (o resto)**.

   ⭐ **A PARTIR DE 1360px, e ⛔ de 1100.** O piso que a instrução dá é 1100 ("⛔ aparece abaixo
   de 1100 px"), e ele é respeitado com folga. A largura escolhida é uma decisão de FORMA, e a
   conta é esta: o corredor do trilho custa 140px de alguém. Em 1360px ele custa 60px da peça
   (472 → 412), o que a peça absorve. Em 1100px custaria 272px — a peça cairia para 200px, e o
   cartão de preço (30rem) e a figura da aferição ⛔ cabem em 200px. Trocar a coluna vazia da
   direita por uma peça espremida ⛔ é ganho: é o defeito de P48-23 outra vez, de outro jeito.

   ⚠ **Em 1440px a forma medida na P48-23 ⛔ muda.** O envelope cresce exatamente o tamanho do
   corredor (1280 → 1420), e como a tela tem 1440 ele cabe: a prosa continua com 608px e a peça
   com 472px, nos mesmos lugares. O que muda é o que estava vazio. Entre 1360 e 1420 a peça
   encolhe até 60px, e a prosa ⛔ encolhe nunca — a medida de leitura ⛔ se negocia.

   ⚠ O topo e o rodapé acompanham o envelope. Se ⛔ acompanhassem, a marca do topo ficaria 140px
   à esquerda da prosa e a página teria duas margens esquerdas diferentes — que é pior do que
   não ter trilho nenhum. */
.pv-guia { display: none; }

@media (min-width: 1360px) {
  :root {
    /* A largura do rótulo mais largo ("O que você recebe") com folga, e o vão até a prosa. */
    --guia: 120px;
    --guia-vao: 20px;
    --guia-corredor: calc(var(--guia) + var(--guia-vao));
  }

  /* O envelope inteiro desloca: main, topo e rodapé, pelo mesmo tanto, para que a página tenha
     UMA margem esquerda. `--wide` ⛔ muda: a medida do conteúdo é a mesma; o que entra é o
     corredor. */
  body.pv48 main .pv-wrap,
  body.pv48 .pv-topo__linha,
  body.pv48 .sp4-footer .container,
  html.com-js .pv-s8[data-trilho="vivo"] {
    max-width: calc(var(--wide) + 2 * var(--gutter) + var(--guia-corredor));
    padding-left: calc(var(--gutter) + var(--guia-corredor));
  }
  /* A tira de molduras da S8 sangra até a borda no celular e ⛔ mora dentro do `.pv-wrap`; ali
     o deslocamento entra pelo `.pv-s8`, que é a grade daquela seção. */
  .pv-sec--centro > .pv-wrap {
    max-width: calc(var(--coluna) + 2 * var(--gutter) + var(--guia-corredor));
  }

  /* ⭐ O trilho: `sticky` com ALTURA ZERO. Ele é o primeiro filho de `<main>`, que dura a página
     inteira, então ele acompanha a rolagem do começo ao fim sem `position: fixed` — e sem
     `fixed` ele ⛔ precisa medir `100vw` (que inclui a barra de rolagem e erra por 15px): a
     largura dele é a do MESMO envelope do conteúdo, pela mesma conta.
     `height: 0` é o que o deixa fora do fluxo sem sair do documento: ⛔ empurra nada. */
  html.com-js body.pv48 .pv-guia:not(:empty) {
    display: block; position: sticky; top: 0; z-index: 1; height: 0;
    width: 100%; margin: 0 auto;
    max-width: calc(var(--wide) + 2 * var(--gutter) + var(--guia-corredor));
    padding: 0 var(--gutter);
  }
  .pv-guia__lista {
    position: absolute; top: var(--fixa-topo); left: var(--gutter); width: var(--guia);
    display: grid; gap: 18px; margin: 0; padding: 0; list-style: none;
    border-left: 1px solid var(--rule);
  }
  /* Um filete curto por rótulo, no fio do trilho. O ativo cresce e vira âmbar — a mesma tinta
     de ação da página, e a única coisa que se destaca aqui. */
  .pv-guia__item {
    position: relative; padding-left: 16px;
    font: 500 12.5px/1.35 var(--sans); letter-spacing: .04em; color: var(--soft);
  }
  .pv-guia__item::before {
    content: ""; position: absolute; left: -1px; top: .48em;
    width: 8px; height: 1px; background: var(--rule2);
  }
  .pv-guia__item[data-atual] { color: var(--accent); font-weight: 700; }
  .pv-guia__item[data-atual]::before { width: 13px; height: 2px; background: var(--accent); }
}
/* A troca do rótulo ativo acompanha a rolagem: sem rampa ela pisca a cada seção. */
@media (min-width: 1360px) and (prefers-reduced-motion: no-preference) {
  .pv-guia__item, .pv-guia__item::before {
    transition: color 140ms cubic-bezier(.2, .7, .2, 1), background-color 140ms cubic-bezier(.2, .7, .2, 1), width 140ms cubic-bezier(.2, .7, .2, 1);
  }
}

/* ══ P48-25 · item 5 — DUAS QUEBRAS DE GRADE, DE PROPÓSITO ═════════════════════════════════

   A direção de arte §4 é explícita: quebras de grade "de propósito, e POUCAS". Uma página em
   que tudo tem o mesmo tamanho ⛔ tem hierarquia — e uma em que tudo quebra a grade ⛔ tem
   grade. São duas, na mesma seção, e cada uma diz uma coisa diferente.

   ⭐ Eram duas. Hoje é UMA: a sangria do jornal foi **revogada pelo owner em 19/09**, e o que
   sobrou é a citação. O texto abaixo guarda as duas porque a decisão revogada também é decisão,
   e quem ler a folha daqui a um mês precisa saber por que o jornal ⛔ sangra mais.

   ── 1 · O JORNAL DO ITA EM SANGRIA — REVOGADA (P48-28) ───────────────────────────────────

   A ideia era boa e o resultado, ⛔: o jornal é a imagem mais dramática da página (o resultado
   impresso de 1992, com o nome apontado), então ele rompia a coluna de leitura e ia até o fim do
   envelope do conteúdo. Com a saída do close do nome (P48-26) a sangria inteira ficou para uma
   foto só, e em 1440 ela mediu **1.138px de largura** num bloco de **1.657px de altura** — mais
   de uma tela —, contra seis miniaturas de **237px**. O owner, vendo isso: "o jornal ficou
   totalmente desproporcional, gigante comparado com os outros documentos… pode até ser um pouco
   maior, mas tem que ficar com um aspecto agradável e proporcional".

   ⭐ A lição: "destaque" ⛔ é o mesmo que "grande". Cinco vezes a área de um vizinho ⛔ é
   hierarquia — é uma imagem que engoliu a seção. Quem dá destaque numa composição de revista é a
   POSIÇÃO (a imagem-líder à esquerda, lida primeiro) e a proporção contra as outras, ⛔ o tamanho
   absoluto. O desenho novo está na seção da galeria, lá em cima: uma folha de contato de 736px em
   que o jornal vale 407px e cada documento menor, 131px — "um pouco maior", medido.

   ⚠ O que ficou desta quebra: a `.pv-procedencia` continua com `max-width: none` no desktop.
   ⛔ é resíduo — é ela que deixa a galeria (46rem) ser mais larga que a prosa (38rem), e é dela
   que a linha dos seis marcos passou a herdar a largura, logo abaixo.

   ── 2 · A CITAÇÃO QUE ATRAVESSA ──────────────────────────────────────────────────────────

   "A rota tocou 62 das 80 questões. O teto que eu tinha declarado era 61." é a frase em que a
   S5b inteira se apoia, e ela estava do mesmo tamanho dos parágrafos ao redor.

   ⭐ **É o MESMO nó de texto.** ⛔ nasce `<blockquote>`, ⛔ se repete a frase, ⛔ entra aspa
   decorativa: é o `<p class="pv-realce">` que a fonte congelada já aprovou, com outra roupa. O
   contrato do texto contaria duas, e a S5b passaria a entregar o que ⛔ é dela.

   ⭐ **`display: contents` no bloco de texto** é o que a deixa atravessar. A S5b é uma grade de
   duas colunas e a citação é NETA dela — dentro da coluna de leitura ela ⛔ tem como sair. Com
   `display: contents`, a caixa do bloco some e os oito parágrafos viram filhos diretos da
   grade: sete continuam na coluna 1, e a citação toma `1 / -1`. A medida de leitura deles ⛔
   muda (ela passa a vir da COLUNA, que é `minmax(0, var(--measure))`).

   ⚠ A figura da aferição desce para a faixa DEPOIS da citação. Acima dela ficam o run-in e os
   dois parágrafos que montam o caso, com a coluna da direita em branco — e o branco ali ⛔ é a
   "coluna vazia" que a P48-23 combateu: é o respiro que dá peso à manchete, e ele acaba na
   linha seguinte. `grid-row` é numérico porque a grade ⛔ tem como contar sozinha, e
   `test_p48_25_acabamento` pina a posição da citação entre os irmãos: se alguém acrescentar um
   parágrafo à S5b, a régua reprova antes de a figura ir parar no lugar errado. */

/* ── 1 · a galeria e a legenda dela (a sangria REVOGADA) ─────────────────────────────── */
@media (min-width: 1100px) {
  /* a prosa da S5 deixa de ser a régua da galeria; quem a segura passa a ser o `.pv-wrap`.
     A galeria fica nos 46rem da regra dela, em TODA largura — ⛔ há mais `var(--wide)` aqui. */
  .pv-procedencia { max-width: none; }
  .pv-procedencia > p { max-width: var(--measure); }
  /* ⭐ P48-28 · item 2 — a linha dos seis marcos é a LEGENDA da galeria, e toma a largura dela.
     Ela é um `<p>` dentro da S5, e por isso a regra acima a prendia em 608px: em 1440 ela
     quebrava em duas linhas no meio de um nome ("Auditor Fiscal / SP 2012"). ⛔ Texto menor,
     ⛔ texto novo — o que estava errado era a medida. */
  .pv-procedencia > .pv-marcos { max-width: 46rem; }
}

/* ── 2 · a citação ───────────────────────────────────────────────────────────────────── */
body.pv48 .pv-dupla--afericao .pv-realce {
  margin-top: .9em; margin-bottom: .25em;
  font: 500 24px/1.22 var(--serif); letter-spacing: -.012em;
  text-wrap: balance; color: var(--ink);
}
@media (min-width: 600px) { body.pv48 .pv-dupla--afericao .pv-realce { font-size: 29px; } }
@media (min-width: 1100px) {
  body.pv48 .pv-dupla--afericao .pv-realce { font-size: 36px; margin-top: 1.1em; margin-bottom: .35em; }
  /* o bloco de texto some como caixa e os parágrafos viram filhos diretos da grade */
  .pv-dupla--afericao > .pv-afericao { display: contents; }
  .pv-dupla--afericao > .pv-afericao > * { grid-column: 1; min-width: 0; }
  .pv-dupla--afericao > .pv-afericao > .pv-realce { grid-column: 1 / -1; max-width: none; }
  /* a figura, na faixa que começa DEPOIS da citação (o 4º dos oito irmãos) */
  .pv-dupla--afericao > .pv-cartao { grid-column: 2; grid-row: 5 / span 4; }
}

/* ── Movimento reduzido: tudo legível e completo sem movimento ─────────────────────────────── */
@media (prefers-reduced-motion: reduce) {
  body.pv48 *, body.pv48 *::before, body.pv48 *::after { animation: none !important; transition: none !important; scroll-behavior: auto !important; }
}
@media (prefers-reduced-motion: no-preference) { html:has(body.pv48) { scroll-behavior: smooth; } }

/* P48-60 · owner 29/09: abertura centralizada (exceção registrada à direção de arte §8) */
body.pv48 .pv-hero__abre { text-align: center; }
body.pv48 .pv-publico { margin-inline: auto; text-wrap: balance; }
body.pv48 .pv-hero__titulo { max-width: 30ch; margin-inline: auto; text-align: center; text-wrap: balance; }
body.pv48 .pv-instrucao { text-align: center; margin-inline: auto; text-wrap: balance; }
@media (min-width: 1100px) {
  body.pv48 .pv-instrucao { grid-column: 1 / -1; max-width: 68ch; }
  body.pv48 .pv-hero__video { grid-row: 3 / span 3; }
}
@media (max-width: 1099.98px) {
  .pv-hero__apoio .pv-cta__rodape, .pv-hero__apoio .pv-wa__pergunta { text-align: center; }
  .pv-hero__video > .pv-sob-video { text-align: center; margin-inline: auto; }
}
