/* ═══════════════════════════════════════════════════════════════════════════
   HERÓI 3D — estilos
   O contexto completo (por que três camadas, o que já foi tentado e rejeitado)
   está no cabeçalho de js/hero-3d.js e em docs/hero-3d.md.

   Identidade: a mesma do site. #F9F9F9 de fundo, #2846c9 da marca, #111827 de
   texto, Manrope. Nada aqui muda a identidade — só a forma de apresentá-la.
   ═══════════════════════════════════════════════════════════════════════════ */

.hero3d {
  --h3d-ground: #F9F9F9;
  --h3d-ink: #111827;
  --h3d-muted: #4A5468;
  --h3d-faint: #8A93AC;
  --h3d-brand: #2846c9;
  --h3d-rule: rgba(17, 24, 39, .12);
  --h3d-mono: ui-monospace, SFMono-Regular, Menlo, monospace;
  /* calha lateral do herói, em um lugar só: a chamada, as legendas e o HUD
     usam a mesma, e o CTA de celular precisa cancelá-la exatamente */
  --h3d-calha: clamp(20px, 5vw, 76px);

  position: relative;
  /* A altura da seção é a DURAÇÃO da animação. Menos que isto e os atos
     ficam curtos demais para serem lidos — foi o erro repetido no protótipo. */
  height: 620vh;
}

/* ── reserva de último caso ───────────────────────────────────────────────
   A sala em arame, em CSS, no palco. É o que sobra na tela quando NADA mais
   funciona: script bloqueado, WebP não suportado, extensão barrando o
   diretório dos quadros, imagem que não chega.

   Ela é o padrão e some assim que o JS entra (`[data-js]`) — por isso não
   pisca no caminho bom nem muda o herói animado. Volta se, no fim do
   carregamento, nenhum quadro tiver sido desenhado (`[data-cena="vazia"]`).

   A alternativa seria detectar a falha em JS, mas o pior dos casos é
   justamente aquele em que o JS não roda: quem detecta tem que ser o CSS.

   O arquivo é o quadro zero da camada de linhas, que o site já carrega — nada
   novo entra por causa disto. */
.hero3d__stage {
  position: sticky;
  top: 0;
  height: 100svh;
  overflow: hidden;
  background:
    url("../hero/desktop/linhas/f000.webp") center / cover no-repeat,
    radial-gradient(120% 92% at 22% 44%, #FFFFFF 0%, #F4F6FB 46%, #E8EDF7 100%),
    var(--h3d-ground);
}
@media (max-width: 767px) {
  .hero3d__stage { background-image: url("../hero/mobile/linhas/f000.webp") }
}
.hero3d[data-js] .hero3d__stage { background-image: none }
/* Aqui o `background` volta INTEIRO, e não só a imagem: sem o gradiente por
   baixo, o arame ficaria sobre a cor chapada — e é justamente neste caso que
   nada mais vai pintar por cima. */
.hero3d[data-js][data-cena="vazia"] .hero3d__stage {
  background:
    url("../hero/desktop/linhas/f000.webp") center / cover no-repeat,
    radial-gradient(120% 92% at 22% 44%, #FFFFFF 0%, #F4F6FB 46%, #E8EDF7 100%),
    var(--h3d-ground);
}
@media (max-width: 767px) {
  .hero3d[data-js][data-cena="vazia"] .hero3d__stage {
    background-image:
      url("../hero/mobile/linhas/f000.webp"),
      radial-gradient(120% 92% at 22% 44%, #FFFFFF 0%, #F4F6FB 46%, #E8EDF7 100%);
  }
}
/* E o véu da chamada vale aqui também: sem quadro desenhado, o texto passa a
   morar sobre o arame. */
.hero3d[data-cena="vazia"] .hero3d__stage::after {
  content: ""; position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background: linear-gradient(to right,
    rgba(252, 253, 255, .93) 0%,
    rgba(252, 253, 255, .80) 30%,
    rgba(252, 253, 255, 0) 62%);
}
.hero3d[data-cena="vazia"] .hero3d__claim { z-index: 2 }

/* CAMADA 1 — campo: o fundo do primeiro ato, feito para segurar o texto */
.hero3d__ground {
  position: absolute;
  inset: 0;
  background:
    radial-gradient(120% 92% at 22% 44%, #FFFFFF 0%, #F4F6FB 46%, #E8EDF7 100%),
    var(--h3d-ground);
}
.hero3d__ground canvas { position: absolute; inset: 0; width: 100%; height: 100%; display: block }

/* CAMADAS 2 e 3 — linhas e sólido. `cover` porque com height:auto sobram
   tarjas brancas em cima e embaixo. */
.hero3d__layer { position: absolute; inset: 0; opacity: 0 }
.hero3d__layer canvas {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; display: block;
}

/* véu SÓ embaixo, e só quando há legenda; nunca cobrindo a cena inteira */
.hero3d__scrim {
  position: absolute; inset: auto 0 0; height: 54%; pointer-events: none; opacity: 0;
  transition: opacity .4s ease;
  background: linear-gradient(to top,
    rgba(249, 249, 251, .94) 0%, rgba(249, 249, 251, .55) 46%, rgba(249, 249, 251, 0) 100%);
}

/* ── a chamada ───────────────────────────────────────────────────────────── */
.hero3d__claim {
  position: absolute; left: var(--h3d-calha); top: 50%; transform: translateY(-50%);
  width: min(660px, 48vw);
}
.hero3d__claim h1 {
  font-size: clamp(28px, 3.1vw, 50px); font-weight: 800; letter-spacing: -.04em;
  line-height: 1.02; margin: 0; color: var(--h3d-ink); text-wrap: balance;
}
.hero3d__sub {
  margin: 20px 0 0; width: min(420px, 34vw);
  font-size: clamp(15px, 1.35vw, 18px); line-height: 1.5;
  color: var(--h3d-muted); font-weight: 500;
}
.hero3d__cta { margin-top: 28px; display: inline-block }
/* ── aviso de animação desligada ──────────────────────────────────────────
   Uma pílula solta com "ver mesmo assim" não se lia como nada: nem como
   botão, nem como explicação. Quem chega numa página parada não sabe que ela
   deveria se mexer — então o texto vem antes do botão e diz POR QUE, e que a
   decisão foi do computador da pessoa, não do site.

   Nasce escondido no HTML: só o script o revela, e só quando a cena parou por
   preferência de movimento. */
.hero3d__aviso {
  margin-top: 26px; max-width: 420px;
  padding: 18px 20px; border-radius: 14px;
  border: 1px solid var(--h3d-rule);
  background: rgba(255, 255, 255, .86);
  backdrop-filter: blur(3px);
  box-shadow: 0 16px 34px -26px rgba(17, 24, 39, .5);
}
.hero3d__aviso[hidden] { display: none }
.hero3d__aviso-olho {
  margin: 0 0 8px; font-family: var(--h3d-mono);
  font-size: 10.5px; letter-spacing: .2em; text-transform: uppercase;
  color: var(--h3d-brand);
}
.hero3d__aviso-texto {
  margin: 0 0 14px; font-size: 14.5px; line-height: 1.5; color: var(--h3d-muted);
}
.hero3d__aviso-texto strong { color: var(--h3d-ink); font-weight: 600 }
.hero3d__aviso-botao {
  display: inline-block; padding: 11px 20px; border-radius: 999px; border: 0;
  background: var(--h3d-brand); color: #fff; cursor: pointer;
  font-family: inherit; font-size: 14.5px; font-weight: 700; letter-spacing: -.01em;
  transition: background .2s ease, transform .2s ease;
}
.hero3d__aviso-botao:hover { background: #1e37a6; transform: translateY(-1px) }
@media (max-width: 767px) {
  .hero3d__aviso { max-width: none; margin-top: 20px; padding: 16px 18px }
}

.hero3d__hint {
  margin: 18px 0 0; font-family: var(--h3d-mono); font-size: 10.5px;
  letter-spacing: .2em; text-transform: uppercase; color: var(--h3d-faint);
}

/* ── legendas: parte da composição, não rodapé ───────────────────────────── */
.hero3d__caps {
  position: absolute; left: 0; right: 0; bottom: 8vh;
  display: grid; justify-items: center; pointer-events: none;
  padding-inline: var(--h3d-calha); text-align: center;
}
.hero3d__cap {
  grid-area: 1/1; opacity: 0; transform: translateY(18px);
  transition: opacity .5s ease, transform .5s ease; max-width: min(880px, 86vw);
}
.hero3d__cap.is-on { opacity: 1; transform: none }
.hero3d__cap b {
  display: block; font-size: clamp(28px, 4vw, 62px); font-weight: 800;
  letter-spacing: -.045em; line-height: 1.02; color: var(--h3d-ink); text-wrap: balance;
}
.hero3d__cap span {
  display: block; margin-top: 14px; font-size: clamp(15px, 1.5vw, 20px);
  color: var(--h3d-muted); line-height: 1.5; font-weight: 500;
  max-width: 52ch; margin-inline: auto; text-wrap: balance;
}

/* ── fecho ───────────────────────────────────────────────────────────────── */
.hero3d__closer {
  position: absolute; inset: 0; display: grid; align-content: center; justify-items: center;
  opacity: 0; pointer-events: none; text-align: center;
  /* transparente nas bordas para as partículas aparecerem em volta da marca —
     sólido aqui deixava o final chapado */
  background: radial-gradient(46% 42% at 50% 48%,
    rgba(249, 249, 251, .92) 0%, rgba(249, 249, 251, .72) 55%, rgba(249, 249, 251, .28) 100%);
}
.hero3d__closer img { width: clamp(60px, 7.5vw, 104px); height: auto; display: block }
.hero3d__closer b {
  margin-top: 18px; font-size: clamp(26px, 3vw, 40px); font-weight: 800;
  letter-spacing: -.03em; color: var(--h3d-ink);
}
.hero3d__closer p {
  margin: 14px 0 0; font-size: clamp(17px, 1.8vw, 24px); color: var(--h3d-muted);
  font-weight: 500; max-width: 22ch; line-height: 1.35;
}
.hero3d__closer .hero3d__cta { margin-top: 32px; pointer-events: auto }

/* ── HUD e carregamento ──────────────────────────────────────────────────── */
.hero3d__hud {
  position: absolute; right: clamp(20px, 5vw, 72px); top: 50%; transform: translateY(-50%);
  display: flex; flex-direction: column; align-items: center; gap: 10px;
  font-family: var(--h3d-mono); font-size: 10px; letter-spacing: .16em; color: var(--h3d-faint);
}
.hero3d__hud .bar { width: 1px; height: 24vh; background: rgba(17, 24, 39, .18); position: relative; overflow: hidden }
.hero3d__hud .bar i {
  position: absolute; inset: 0 0 auto; height: 100%; background: var(--h3d-brand);
  transform-origin: top; transform: scaleY(var(--p, 0));
}

/* O carregamento é parte da cena, não um spinner por cima dela. Fica junto da
   dica de rolagem, some sozinho e NUNCA impede o uso. */
.hero3d__load {
  position: absolute; left: var(--h3d-calha); bottom: 5vh; z-index: 5;
  display: flex; align-items: center; gap: 12px;
  font-family: var(--h3d-mono); font-size: 10px; letter-spacing: .18em;
  text-transform: uppercase; color: var(--h3d-faint); transition: opacity .6s ease;
}
.hero3d__load[data-pronto="true"] { opacity: 0 }
.hero3d__load .trilho { width: clamp(90px, 12vw, 168px); height: 1px; background: rgba(17, 24, 39, .14); overflow: hidden }
.hero3d__load .trilho i {
  display: block; height: 100%; background: var(--h3d-brand);
  transform: scaleX(0); transform-origin: left; transition: transform .35s cubic-bezier(.2, .8, .2, 1);
}
.hero3d__load b { font-weight: 500; font-variant-numeric: tabular-nums; color: var(--h3d-muted) }

/* modo reduzido: a cena vira quadro parado e a página segue vendendo */
.hero3d[data-modo="estatico"] .hero3d__hud { opacity: .35 }

/* Cena parada: entra a sala em ARAME, a mesma da capa de apresentação.
   Não é o render sólido. Uma versão anterior fixava um quadro fotográfico da
   sequência, e foi o que apareceu em produção: parado e em tela cheia, o
   render denuncia que é render — mesma razão pela qual os planos abertos da
   sala saíram das peças de rede. O desenho em linha é o que o site usa como
   identidade quando não há movimento. */
.hero3d[data-modo="estatico"] .hero3d__stage {
  background:
    url("../hero/desktop/linhas/f000.webp") center / cover no-repeat,
    radial-gradient(120% 92% at 22% 44%, #FFFFFF 0%, #F4F6FB 46%, #E8EDF7 100%),
    var(--h3d-ground);
}
@media (max-width: 767px) {
  .hero3d[data-modo="estatico"] .hero3d__stage {
    background-image:
      url("../hero/mobile/linhas/f000.webp"),
      radial-gradient(120% 92% at 22% 44%, #FFFFFF 0%, #F4F6FB 46%, #E8EDF7 100%);
  }
}

/* E o `ground` perde o fundo PRÓPRIO: ele é opaco e cobria o palco inteiro,
   então o arame ficava desenhado embaixo e invisível. Aqui ele passa a ser só
   o suporte das partículas — que continuam sumindo com a rolagem, enquanto o
   arame fica, porque agora mora na camada de baixo, que ninguém apaga. */
.hero3d[data-modo="estatico"] .hero3d__ground { background: none }

/* ── véu do modo parado ───────────────────────────────────────────────────
   Com a cena congelada, o quadro fica à vista o herói inteiro — e a chamada
   passa a morar em cima dele. No modo animado isso não acontece: o primeiro
   ato é só gradiente, e o 3D só entra quando o texto já saiu.

   O degradê morre antes da metade do quadro, então a cena continua inteira do
   lado direito. Na tela estreita ele vira vertical, que é onde o texto cai
   nesse formato. */
.hero3d[data-modo="estatico"] .hero3d__stage::after {
  /* z-index 1 põe o véu acima das camadas da cena, que ficam em `auto`; a
     chamada sobe para 2 logo abaixo. Em 3 ele passava por cima do texto
     também, e a peça inteira saía lavada. */
  content: ""; position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background: linear-gradient(to right,
    rgba(252, 253, 255, .93) 0%,
    rgba(252, 253, 255, .80) 30%,
    rgba(252, 253, 255, 0) 62%);
}
.hero3d[data-modo="estatico"] .hero3d__claim,
.hero3d[data-modo="estatico"] .hero3d__caps,
.hero3d[data-modo="estatico"] .hero3d__closer { z-index: 2 }
@media (max-width: 900px) {
  .hero3d[data-modo="estatico"] .hero3d__stage::after {
    background: linear-gradient(to bottom,
      rgba(252, 253, 255, 0) 0%,
      rgba(252, 253, 255, .62) 34%,
      rgba(252, 253, 255, .93) 62%);
  }
}

@media (max-width: 900px) {
  .hero3d { height: 560vh }
  .hero3d__hud { display: none }
  .hero3d__claim {
    top: auto; bottom: 13vh; transform: none; width: auto;
    right: var(--h3d-calha);
  }
  .hero3d__sub { width: auto; max-width: 34ch }
  .hero3d__caps { padding-inline: clamp(20px, 5vw, 40px) }

  /* O CTA ficou de ponta a ponta por um tempo — pedido para "não ter margens
     das laterais no mobile" — e o resultado leu pior que a pílula: uma barra
     retangular colada nas duas bordas parece componente de sistema, não botão
     de ação de um site. Voltou a ser pílula, ocupando a coluna de texto. */
  .hero3d__claim .hero3d__cta { width: 100%; max-width: 420px }

  /* O botão do fecho não é o mesmo caso: ali ele fica sozinho no centro da
     tela, e sem teto de largura a regra geral `width: 100%` do site o esticava
     de borda a borda por cima da marca. */
  .hero3d__closer .hero3d__cta { width: min(100%, 340px) }
}

/* A altura do herói É a duração da animação: 620vh de rolagem é o que dá
   tempo aos quatro atos. Com movimento reduzido ela cai para uma tela, porque
   não há o que percorrer.

   O `:not([data-animar])` é o que faz a escolha da pessoa valer. Sem ele, quem
   ligava a animação pelo botão continuava sem rolagem: o carrossel girava e as
   partículas apareciam — porque isso é JS —, mas o 3D ficava parado, porque a
   media query já tinha cortado a altura. Media query não lê `sessionStorage`;
   quem carimba o atributo é o trecho no `head` do index. */
@media (prefers-reduced-motion: reduce) {
  :root:not([data-animar]) .hero3d { height: 100svh }
  :root:not([data-animar]) .hero3d__cap { transition: none }
}
/* O mesmo corte pelo parâmetro de teste, para `?movimento=reduzido`
   reproduzir o caso real inteiro — CSS incluído. */
:root[data-movimento="reduzido"]:not([data-animar]) .hero3d { height: 100svh }
:root[data-movimento="reduzido"]:not([data-animar]) .hero3d__cap { transition: none }
