/* Visantismo · monocromático, limpo, misterioso. Sem neon, sem cor, sem carnaval. */
:root {
  --bg: #0a0a0b;
  --fg: #ededee;
  /* #6f6f74 dava ~4.3:1 sobre --bg e reprovava WCAG AA — e é o token de TODO
     texto secundário (lead, corpo dos cards, FAQ, footer, labels em 0.7rem).
     #8b8b93 dá ~5.8:1 mantendo o cinza discreto. */
  --muted: #8b8b93;
  --faint: #2a2a2d;
  --line: #1a1a1c;
  --card: #0f0f10;
  --radius: 4px;
  --font-sans: 'Manrope', ui-sans-serif, system-ui, sans-serif;
  --font-mono: 'Red Hat Mono', ui-monospace, monospace;
  --display: clamp(2.75rem, 8vw, 6.5rem);
  --h2: clamp(1.75rem, 3.6vw, 3rem);
  --section: clamp(5rem, 13vw, 11rem);
  /* Motion SSoT (visant-motion). Curvas fortes: o `ease` nativo lê lento.
     Nenhum componente declara cubic-bezier ou duração própria — só tokens. */
  --ease-out: cubic-bezier(0.23, 1, 0.32, 1); /* entra/sai, responde a input */
  --ease-in-out: cubic-bezier(0.77, 0, 0.175, 1); /* move/morph em tela */
  --dur-press: 0.12s;
  --dur-fast: 0.16s;
  --dur-base: 0.2s;
  --dur-slow: 0.3s;
  --dur-reveal: 0.7s; /* entradas de marketing (scroll reveal, barra do ratchet) */
}
* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}
html {
  scroll-behavior: smooth;
}
body {
  font-family: var(--font-sans);
  background: var(--bg);
  color: var(--fg);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
  letter-spacing: -0.01em;
}
/* grão filmico sutil, dá o "misterioso" sem cor */
body::after {
  content: '';
  position: fixed;
  inset: 0;
  z-index: 9999;
  pointer-events: none;
  opacity: 0.025;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='3'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}
::selection {
  background: var(--fg);
  color: var(--bg);
}
a {
  color: inherit;
  text-decoration: none;
}

/* foco visível — o CSS não tinha NENHUM estilo de foco, então navegar por
   teclado era invisível. :focus-visible não aparece em clique de mouse. */
:focus-visible {
  outline: 2px solid var(--fg);
  outline-offset: 3px;
  border-radius: 2px;
}

.skip-link {
  position: absolute;
  left: 12px;
  top: -100px;
  z-index: 100;
  background: var(--fg);
  color: var(--bg);
  padding: 12px 20px;
  border-radius: var(--radius);
  font-weight: 600;
  font-size: 0.9rem;
  /* sem transição: skip-link é utilitário de teclado, aparece na hora */
}
.skip-link:focus {
  top: 12px;
}

.container {
  max-width: 1080px;
  margin: 0 auto;
  padding: 0 28px;
}
.container-narrow {
  max-width: 720px;
}
.container-faq {
  max-width: 740px;
}
.container-final {
  max-width: 680px;
}
section {
  padding: var(--section) 0;
  border-top: 1px solid var(--line);
}
.center {
  text-align: center;
}
.muted {
  color: var(--muted);
}

/* tipografia */
.label-caps {
  font-family: var(--font-mono);
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.16em;
  color: var(--muted);
}
.display {
  font-size: var(--display);
  line-height: 0.98;
  letter-spacing: -0.04em;
  font-weight: 700;
}
h1,
.h1 {
  font-size: clamp(2rem, 4.5vw, 3.5rem);
  line-height: 1.05;
  letter-spacing: -0.03em;
  font-weight: 700;
}
h2,
.h2 {
  font-size: var(--h2);
  line-height: 1.08;
  letter-spacing: -0.03em;
  font-weight: 700;
}
h3,
.h3 {
  font-size: 1.05rem;
  font-weight: 600;
  letter-spacing: -0.01em;
}
.lead {
  font-size: clamp(1.05rem, 1.3vw, 1.2rem);
  color: var(--muted);
  max-width: 54ch;
  line-height: 1.65;
}
.lead-centered {
  margin-left: auto;
  margin-right: auto;
}
.accent {
  color: var(--fg);
} /* sem cor: emphasis = branco puro */

/* espaçamentos de seção (antes eram style= inline no HTML, furando os tokens) */
.section-head {
  text-align: center;
  margin-bottom: 52px;
}
.section-title {
  margin-top: 16px;
}
.container-narrow .section-title {
  margin: 18px 0 22px;
}
.plans-subtitle {
  margin-top: 14px;
}
.proof-note {
  margin-top: 40px;
  max-width: 58ch;
  margin-left: auto;
  margin-right: auto;
}
.display-final {
  font-size: clamp(2.25rem, 5vw, 3.75rem);
  margin: 20px 0;
}
.final-lead {
  margin-bottom: 36px;
}
.hero-actions {
  display: flex;
  gap: 14px;
  justify-content: center;
  flex-wrap: wrap;
  margin-bottom: 32px;
}

/* botões: limpo, sem glow */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  font-family: inherit;
  font-weight: 600;
  font-size: 0.95rem;
  border-radius: var(--radius);
  padding: 15px 30px;
  cursor: pointer;
  border: 1px solid transparent;
  letter-spacing: inherit;
  text-align: center;
  /* cor no `ease` nativo (correto pra hover); transform no press curto e forte */
  transition:
    background var(--dur-base) ease,
    color var(--dur-base) ease,
    border-color var(--dur-base) ease,
    opacity var(--dur-base) ease,
    transform var(--dur-press) var(--ease-out);
}
/* todo botão responde ao toque — feedback no pointer-down, não no release */
.btn:active {
  transform: scale(0.97);
}
.btn-lg {
  padding: 18px 40px;
  font-size: 1rem;
}
.btn-block {
  width: 100%;
}
.btn-primary {
  background: var(--fg);
  color: var(--bg);
}
.btn-outline {
  border-color: var(--faint);
  background: transparent;
  color: var(--fg);
}
/* hover só onde hover existe de verdade — touch dispara falso hover no tap */
@media (hover: hover) and (pointer: fine) {
  .btn-primary:hover {
    opacity: 0.82;
  }
  .btn-outline:hover {
    border-color: var(--fg);
  }
  .value-item:hover {
    background: var(--card);
  }
}
.btn[disabled],
.btn[aria-disabled='true'],
.btn.sold-out {
  opacity: 0.45;
  cursor: not-allowed;
  pointer-events: none;
}
/* o botão em estado "abrindo checkout" não pode encolher e mexer o layout */
.btn[data-busy='true'] {
  opacity: 0.6;
  cursor: progress;
}

/* nav */
.nav {
  position: sticky;
  top: 0;
  z-index: 50;
  background: rgba(10, 10, 11, 0.7);
  -webkit-backdrop-filter: blur(14px);
  backdrop-filter: blur(14px);
  border-bottom: 1px solid var(--line);
}
.nav .container {
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: 72px;
}
.logo {
  font-weight: 700;
  font-size: 1.05rem;
  letter-spacing: 0.04em;
}
.nav a.btn {
  padding: 9px 18px;
  font-size: 0.85rem;
}

/* hero */
.hero {
  padding: clamp(6rem, 14vw, 11rem) 0 var(--section);
  text-align: center;
  border-top: 0;
}
.hero .display {
  margin: 28px auto 24px;
  max-width: 14ch;
}
.hero .lead {
  margin: 0 auto 40px;
}

/* grids */
.grid {
  display: grid;
  gap: 1px;
  background: var(--line);
  border: 1px solid var(--line);
}
.grid > * {
  background: var(--bg);
}
.grid-2 {
  grid-template-columns: repeat(2, 1fr);
}
.grid-3 {
  grid-template-columns: repeat(3, 1fr);
}
.grid-4 {
  grid-template-columns: repeat(4, 1fr);
}
@media (max-width: 820px) {
  .grid-2,
  .grid-3,
  .grid-4 {
    grid-template-columns: 1fr;
  }
}

/* itens de valor: numerados, sem emoji */
.value-item {
  padding: 36px 32px;
  display: block;
  transition: background var(--dur-slow) ease;
}
.value-item .n {
  font-family: var(--font-mono);
  font-size: 0.75rem;
  color: var(--muted);
  letter-spacing: 0.08em;
}
.value-item h3 {
  margin: 18px 0 8px;
}
.value-item p {
  font-size: 0.92rem;
  color: var(--muted);
  line-height: 1.6;
}

/* prova / números — as divisórias vinham de border-right inline em cada .stat,
   que quebrava no wrap do mobile. Mesma técnica do .grid: gap de 1px. */
.stats {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 1px;
  background: var(--line);
  border: 1px solid var(--line);
}
@media (max-width: 820px) {
  .stats {
    grid-template-columns: repeat(2, 1fr);
  }
}
.stat {
  text-align: center;
  padding: 28px 12px;
  background: var(--bg);
}
.stat .num {
  font-size: clamp(2rem, 4vw, 3rem);
  font-weight: 700;
  letter-spacing: -0.03em;
}
.stat .lbl {
  font-family: var(--font-mono);
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--muted);
  margin-top: 8px;
}

/* planos */
.price-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1px;
  background: var(--line);
  border: 1px solid var(--line);
  max-width: 860px;
  margin: 0 auto;
}
@media (max-width: 720px) {
  .price-grid {
    grid-template-columns: 1fr;
  }
}
.price-card {
  background: var(--bg);
  padding: 44px 38px;
}
.price-card.featured {
  background: var(--card);
}
.price-card .tier {
  font-family: var(--font-mono);
  text-transform: uppercase;
  letter-spacing: 0.12em;
  font-size: 0.72rem;
  color: var(--muted);
}
.price-card .price {
  font-size: 3rem;
  font-weight: 700;
  letter-spacing: -0.04em;
  margin: 16px 0 4px;
}
.price-card .price small {
  font-size: 1rem;
  font-weight: 500;
  color: var(--muted);
  letter-spacing: 0;
}
.price-card .note {
  font-family: var(--font-mono);
  font-size: 0.72rem;
  color: var(--muted);
  letter-spacing: 0.04em;
}
.price-card ul {
  list-style: none;
  margin: 26px 0;
  display: grid;
  gap: 13px;
}
.price-card li {
  display: flex;
  gap: 12px;
  align-items: flex-start;
  font-size: 0.92rem;
  color: var(--fg);
}
.price-card li::before {
  content: '';
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--muted);
  margin-top: 9px;
  flex-shrink: 0;
}
.plan-features-offset {
  margin-top: 46px;
}
.ratchet-bar {
  height: 1px;
  background: var(--faint);
  margin: 16px 0 8px;
}
.ratchet-fill {
  height: 1px;
  width: 100%;
  background: var(--fg);
  /* preenchimento por scaleX (GPU, interruptível), não por width (layout) */
  transform: scaleX(0.01);
  transform-origin: left;
  transition: transform var(--dur-reveal) var(--ease-out);
}

/* O preço chega do /api/sold depois do primeiro paint. Sem largura reservada
   e sem números tabulares, "R$ 497" → "R$ 1.240" empurrava o layout (CLS). */
.price-slot {
  display: inline-block;
  min-width: 5ch;
  font-variant-numeric: tabular-nums;
}
.price-card .price .price-slot {
  min-width: 6ch;
}

.checkout-status {
  margin: 28px auto 0;
  max-width: 46ch;
  text-align: center;
  font-family: var(--font-mono);
  font-size: 0.78rem;
  line-height: 1.6;
  letter-spacing: 0.03em;
  color: var(--muted);
  min-height: 1.4em;
}
.checkout-status[data-state='error'] {
  color: var(--fg);
}
/* Vazia não ocupa espaço. A região existe em 4 pontos da landing do e-book
   (uma por CTA, senão o erro do botão do hero é escrito cinco telas abaixo);
   reservar 1.4em em cada uma custaria pixel de dobra pra mostrar nada. Fica
   no DOM, renderizada, então o aria-live continua anunciando quando enche. */
.checkout-status:empty {
  min-height: 0;
  margin: 0;
}
/* A do nav flutua sob a barra: o CTA do nav é sticky, e empurrar o layout do
   header a cada clique moveria a página inteira sob o dedo do usuário. */
.checkout-status-nav {
  position: absolute;
  left: 0;
  right: 0;
  top: 100%;
  margin: 0;
  padding: 8px 28px;
  max-width: none;
  background: var(--card);
  border-bottom: 1px solid var(--line);
}
.checkout-status-nav:empty {
  padding: 0;
  border-bottom: 0;
}

/* faq */
.faq details {
  border-bottom: 1px solid var(--line);
  padding: 24px 0;
}
.faq summary {
  font-weight: 600;
  font-size: 1.02rem;
  list-style: none;
  display: flex;
  justify-content: space-between;
  cursor: pointer;
  gap: 24px;
}
.faq summary::-webkit-details-marker {
  display: none;
}
.faq summary::after {
  content: '+';
  color: var(--muted);
  font-weight: 400;
  /* rotaciona 45° e vira ×: contínuo e interruptível, sem swap de caractere */
  transition: transform var(--dur-base) var(--ease-out);
}
.faq details[open] summary::after {
  transform: rotate(45deg);
}
.faq p {
  color: var(--muted);
  margin-top: 14px;
  max-width: 70ch;
  line-height: 1.65;
}
.faq details[open] p {
  animation: faq-in var(--dur-slow) var(--ease-out);
}
@keyframes faq-in {
  from {
    opacity: 0;
    transform: translateY(-4px);
  }
}

footer {
  border-top: 1px solid var(--line);
  padding: 48px 0;
  color: var(--muted);
  font-size: 0.85rem;
}
footer .container {
  display: flex;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 16px;
}

/* Reveal on scroll — só existe quando o JS está vivo (.js no <html>).
   Antes o opacity:0 era incondicional e o IntersectionObserver era a ÚNICA
   forma de devolver: JS bloqueado = página sem a seção de planos. */
.js .reveal {
  opacity: 0;
  transform: translateY(14px);
  transition:
    opacity var(--dur-reveal) var(--ease-out),
    transform var(--dur-reveal) var(--ease-out);
}
.js .reveal.in {
  opacity: 1;
  transform: none;
}

/* Stagger curto e capped (50ms × 5 máx.) nos itens dos grids revelados —
   a cascata lê como um movimento só, não item-a-item. */
.js .reveal .grid > *,
.js .reveal .stats > * {
  opacity: 0;
  transform: translateY(12px);
  transition:
    opacity var(--dur-reveal) var(--ease-out),
    transform var(--dur-reveal) var(--ease-out);
}
.js .reveal.in .grid > *,
.js .reveal.in .stats > * {
  opacity: 1;
  transform: none;
}
.js .reveal.in .grid > :nth-child(2),
.js .reveal.in .stats > :nth-child(2) {
  transition-delay: 50ms;
}
.js .reveal.in .grid > :nth-child(3),
.js .reveal.in .stats > :nth-child(3) {
  transition-delay: 100ms;
}
.js .reveal.in .grid > :nth-child(4),
.js .reveal.in .stats > :nth-child(4) {
  transition-delay: 150ms;
}
.js .reveal.in .grid > :nth-child(5) {
  transition-delay: 200ms;
}
.js .reveal.in .grid > :nth-child(6) {
  transition-delay: 250ms;
}

/* Entrada do hero no load: fade-up em cascata (eyebrow → título → lead →
   ações → ratchet). Só sob .js — sem script, tudo visível de primeira. */
@keyframes rise {
  from {
    opacity: 0;
    transform: translateY(14px);
  }
}
.js .hero .container > * {
  animation: rise var(--dur-reveal) var(--ease-out) backwards;
}
.js .hero .container > :nth-child(2) {
  animation-delay: 70ms;
}
.js .hero .container > :nth-child(3) {
  animation-delay: 140ms;
}
.js .hero .container > :nth-child(4) {
  animation-delay: 210ms;
}
.js .hero .container > :nth-child(5) {
  animation-delay: 280ms;
}

/* ════════════════════════════════════════════════════════════════════════
   E-BOOK · ebook.html
   Escopo próprio: nenhuma regra abaixo altera a landing do Club. Só tokens
   já declarados no :root — sem cubic-bezier, sem duração e sem cor solta.
   ════════════════════════════════════════════════════════════════════════ */

/* CTA da nav: entra quando o CTA do hero sai de vista (js/ebook.js). Some do
   fluxo de tab enquanto está oculto — botão invisível que recebe foco é uma
   armadilha de teclado. */
.nav-cta {
  opacity: 0;
  transform: translateY(-6px);
  pointer-events: none;
  visibility: hidden;
  transition:
    opacity var(--dur-base) var(--ease-out),
    transform var(--dur-base) var(--ease-out),
    visibility 0s linear var(--dur-base);
}
.nav-cta.is-in {
  opacity: 1;
  transform: none;
  pointer-events: auto;
  visibility: visible;
  transition-delay: 0s;
}

/* Progresso da amostra: 1px na borda da nav. scaleX vem do JS. */
.read-bar {
  position: absolute;
  left: 0;
  right: 0;
  bottom: -1px;
  height: 1px;
  opacity: 0;
  transition: opacity var(--dur-base) ease;
}
.read-bar.is-on {
  opacity: 1;
}
.read-bar i {
  display: block;
  height: 1px;
  background: var(--fg);
  transform: scaleX(0);
  transform-origin: left;
}

/* hero */
.hero-title {
  margin: 26px auto 22px;
  max-width: 20ch;
}
.trigger {
  font-family: var(--font-mono);
  font-size: 0.8rem;
  line-height: 1.6;
  letter-spacing: 0.03em;
  color: var(--muted);
}
/* A linha de specs ("34 páginas · 9 etapas · …") responde a pergunta que decide
   a compra de um livro barato: quanto tempo isso me custa. Estava como
   .label-caps: 61 caracteres em caixa alta com 0.18em de tracking, ou seja, a
   informação mais decisiva da dobra era a menos legível dela. Caixa alta serve
   pra rótulo de 2 palavras, não pra linha de dados. */
.hero-meta {
  margin-top: 28px;
  font-family: var(--font-mono);
  font-size: 0.8rem;
  letter-spacing: 0.02em;
  color: var(--muted);
}
.mech-body2 {
  margin-top: 20px;
}

/* ── A cascata ─────────────────────────────────────────────────────────
   O fio vertical desenha de cima pra baixo quando o grupo entra: a
   animação repete o argumento (uma etapa alimenta a outra). É o único
   movimento longo da página, e é de marketing, não de UI. */
.cascade {
  margin-top: 64px;
  display: grid;
  gap: 44px;
}
.cascade-head {
  display: flex;
  align-items: baseline;
  gap: 12px;
  flex-wrap: wrap;
  margin-bottom: 18px;
}
.cascade-phase-note {
  font-family: var(--font-mono);
  font-size: 0.78rem;
  color: var(--muted);
  letter-spacing: 0.02em;
}
.cascade-list {
  list-style: none;
  position: relative;
  padding-left: 26px;
}
.cascade-list::before {
  content: '';
  position: absolute;
  left: 0;
  top: 10px;
  bottom: 10px;
  width: 1px;
  background: var(--faint);
  transform: scaleY(0);
  transform-origin: top;
  transition: transform var(--dur-reveal) var(--ease-out);
}
.js .cascade-group.in .cascade-list::before {
  transform: scaleY(1);
}
.cascade-step {
  position: relative;
  display: flex;
  align-items: baseline;
  gap: 14px;
  flex-wrap: wrap;
  padding: 13px 0;
  border-bottom: 1px solid var(--line);
}
.cascade-step:last-child {
  border-bottom: 0;
}
/* o ponto que ancora a etapa no fio */
.cascade-step::before {
  content: '';
  position: absolute;
  left: -26px;
  top: 22px;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--faint);
  transform: translateX(-2px);
}
.cascade-step.is-free::before {
  background: var(--fg);
}
.cascade-n {
  font-family: var(--font-mono);
  font-size: 0.72rem;
  color: var(--muted);
  letter-spacing: 0.06em;
  min-width: 2.4ch;
}
.cascade-t {
  font-weight: 600;
  font-size: 1rem;
}
.cascade-note {
  font-family: var(--font-mono);
  font-size: 0.78rem;
  color: var(--muted);
  letter-spacing: 0.02em;
}
.cascade-badge {
  margin-left: auto;
  font-family: var(--font-mono);
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--bg);
  background: var(--fg);
  padding: 5px 10px;
  border-radius: var(--radius);
  transition: opacity var(--dur-base) ease;
}

/* ── A amostra (long-form) ─────────────────────────────────────────────
   Corpo de leitura levemente rebaixado do --fg: 2 mil palavras em branco
   puro cansam, e em --muted ficam apagadas. Derivado dos tokens, não é
   uma cor nova. */
.container-read {
  max-width: 680px;
}
.read {
  color: color-mix(in srgb, var(--fg) 84%, var(--bg));
  font-size: 1.06rem;
  line-height: 1.78;
}
.read > p {
  margin-bottom: 22px;
}
.read-head {
  border-bottom: 1px solid var(--line);
  padding-bottom: 26px;
  margin-bottom: 34px;
}
.read-title {
  margin: 14px 0 6px;
  color: var(--fg);
}
.read-sub {
  font-family: var(--font-mono);
  font-size: 0.8rem;
  color: var(--muted);
  letter-spacing: 0.02em;
}
.read-h {
  color: var(--fg);
  font-size: 1.15rem;
  font-weight: 700;
  letter-spacing: -0.01em;
  margin: 40px 0 16px;
}
.read-defs {
  display: grid;
  gap: 12px;
  margin: 0 0 26px;
}
.read-defs > div {
  display: flex;
  gap: 10px;
  align-items: baseline;
  flex-wrap: wrap;
  border-left: 1px solid var(--line);
  padding-left: 16px;
}
.read-defs dt {
  font-weight: 700;
  color: var(--fg);
  font-size: 1rem;
}
.read-defs dd {
  color: var(--muted);
  font-size: 0.92rem;
  flex: 1 1 16ch;
}
.read-defs-tight {
  margin-bottom: 30px;
}
.read-formula {
  font-family: var(--font-mono);
  font-size: 0.92rem;
  letter-spacing: 0.02em;
  color: var(--fg);
  text-align: center;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 20px 18px;
  margin: 0 0 26px;
}
.read-q {
  border-left: 2px solid var(--fg);
  padding-left: 20px;
  margin: 0 0 22px;
  color: var(--fg);
  font-size: 1.15rem;
  line-height: 1.55;
  letter-spacing: -0.01em;
}
.read-mc {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 26px 24px;
  margin: 0 0 26px;
}
/* Era .label-caps: 34 caracteres em caixa alta. Caixa alta é pra rótulo de duas
   ou três palavras; isto é uma frase, e frase em caixa alta perde a silhueta das
   palavras, que é justamente o que o olho usa pra varrer. */
.read-mc-label {
  font-family: var(--font-mono);
  font-size: 0.78rem;
  letter-spacing: 0.02em;
  color: var(--muted);
}
.read-mc p {
  margin-top: 12px;
  color: var(--fg);
  font-size: 1.15rem;
  line-height: 1.5;
  letter-spacing: -0.01em;
}

/* o gate: fim da amostra, começo da oferta */
.gate {
  border: 1px solid var(--faint);
  border-radius: var(--radius);
  background: var(--card);
  padding: 44px 34px;
  margin-top: 56px;
  text-align: center;
}
.gate-title {
  margin: 14px 0 12px;
}
.gate-body {
  max-width: 44ch;
  margin: 0 auto 28px;
}

/* ── As páginas do livro ───────────────────────────────────────────────
   O padding branco na imagem faz o papel da margem da página impressa: o
   artefato é claro e a landing é escura, então ele lê como objeto. */
.spreads {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 22px;
  align-items: start;
}
@media (max-width: 820px) {
  .spreads {
    grid-template-columns: 1fr;
  }
}
.spread img {
  display: block;
  width: 100%;
  height: auto;
  background: #fff;
  padding: 18px;
  border-radius: var(--radius);
  transition: transform var(--dur-slow) var(--ease-out);
}
.spread figcaption {
  margin-top: 14px;
  text-align: center;
}
@media (hover: hover) and (pointer: fine) {
  .spread:hover img {
    transform: translateY(-4px);
  }
}

/* ── Quem escreveu ─────────────────────────────────────────────────────── */
.author {
  display: grid;
  grid-template-columns: 0.85fr 1fr;
  gap: 48px;
  align-items: center;
}
@media (max-width: 820px) {
  .author {
    grid-template-columns: 1fr;
    gap: 32px;
  }
}
.author-photo img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: var(--radius);
}
.author-title {
  margin: 16px 0 18px;
}
.author-stats {
  grid-template-columns: repeat(3, 1fr);
  margin-top: 32px;
}

/* ── Banda do Club ─────────────────────────────────────────────────────
   Peso baixo e depois do CTA: ancora o preço sem virar segunda ação
   primária competindo com a compra. */
.club-band {
  padding: clamp(3rem, 7vw, 5rem) 0;
  background: var(--card);
}
.club-title {
  margin: 14px 0 10px;
}
.club-body {
  max-width: 52ch;
  margin: 0 auto 24px;
  font-size: 0.92rem;
}

/* Stagger das listas do e-book, mesmo padrão curto e capped dos grids. */
.js .reveal .cascade-list > li,
.js .reveal .spreads > * {
  opacity: 0;
  transform: translateY(12px);
  transition:
    opacity var(--dur-reveal) var(--ease-out),
    transform var(--dur-reveal) var(--ease-out);
}
.js .reveal.in .cascade-list > li,
.js .reveal.in .spreads > * {
  opacity: 1;
  transform: none;
}
.js .reveal.in .cascade-list > :nth-child(2),
.js .reveal.in .spreads > :nth-child(2) {
  transition-delay: 60ms;
}
.js .reveal.in .cascade-list > :nth-child(3),
.js .reveal.in .spreads > :nth-child(3) {
  transition-delay: 120ms;
}
.js .reveal.in .cascade-list > :nth-child(4) {
  transition-delay: 180ms;
}

/* Respeita quem pediu menos movimento no sistema. */
@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    /* delays também: um stagger de 250ms com duração 0.01ms ainda seguraria
       o conteúdo invisível por 250ms */
    animation-delay: 0s !important;
    transition-duration: 0.01ms !important;
    transition-delay: 0s !important;
    scroll-behavior: auto !important;
  }
  .js .reveal,
  .js .reveal .grid > *,
  .js .reveal .stats > *,
  .js .reveal .cascade-list > li,
  .js .reveal .spreads > * {
    opacity: 1;
    transform: none;
  }
  /* O fio da cascata some se ficar em scaleY(0): aqui ele nasce inteiro.
     Reduced motion zera o movimento, nunca o resultado. */
  .cascade-list::before {
    transform: scaleY(1);
  }
}
