/* =========================================================
   Fervor — site institucional
   Etapa 1: estrutura estática, mobile-first, sem animação.
   ========================================================= */

:root {
  /* ---------- PALETA ----------
     Todas as cores da marca vivem aqui. Trocar de paleta e editar
     este bloco: nenhuma cor esta escrita a mao no resto do arquivo.
     As variaveis -rgb existem para os usos com transparencia, via
     rgb(var(--x-rgb) / alfa). Mantenha hex e -rgb em sincronia.
     Fora daqui so restam rgba(0,0,0,...): mascaras e veus neutros,
     que nao pertencem a paleta e nao mudam quando ela muda. */

  /* base */
  --carvao:            #241C18;
  --carvao-2:          #3B2A21;
  --carvao-3:          #4A3830;
  --areia:             #F5EEE4;
  --creme:             #FFF6EA;

  /* acentos */
  --terracota:         #E8763F;
  --terracota-med:     #B8492A;
  --terracota-esc:     #A33D20;
  --marrom-texto:      #6B5C51;
  --borda-clara:       #E3D7C7;

  /* tons intermediarios dos gradientes */
  --ambar-escuro:      #744B1E;
  --areia-media:       #E0CFB8;
  --areia-quente:      #E7CFB4;
  --brasa-media:       #F0873B;
  --caramelo:          #C98A5C;
  --caramelo-escuro:   #8E5836;
  --carvao-barra:      #32251E;
  --carvao-suave:      #2E231D;
  --dourado:           #FFC169;
  --dourado-claro:     #FFF3D6;
  --listra-a:          #3F241A;
  --listra-b:          #311C15;
  --marrom-brasa:      #45261A;
  --marrom-medio:      #543B2C;
  --marrom-noite:      #3A251C;
  --tijolo:            #8E3A22;
  --tijolo-claro:      #B85632;
  --tijolo-escuro:     #6B2E1B;

  /* versoes RGB, para os usos com transparencia */
  --terracota-rgb:     232 118 63;
  --areia-rgb:         245 238 228;
  --carvao-rgb:        36 28 24;
  --creme-rgb:         255 246 234;
  --sombra-rgb:        20 12 8;
  --sombra-quente-rgb: 36 16 8;
  --terracota-esc-rgb: 163 61 32;
  --ambar-escuro-rgb:  116 75 30;
  --dourado-halo-rgb:  255 190 110;
  --brasa-halo-rgb:    255 170 80;

  /* tipografia */
  --serif: Aleo, Georgia, "Times New Roman", serif;
  --sans: "IBM Plex Sans", system-ui, -apple-system, "Segoe UI", sans-serif;

  /* respiro lateral */
  --gutter: 22px;
}

@media (min-width: 720px)  { :root { --gutter: 40px; } }
@media (min-width: 1080px) { :root { --gutter: 64px; } }

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

html { scroll-behavior: smooth; }

/* O header fixo cobriria o topo da seção ao clicar num link do menu. Vale para
   qualquer <section id>, não só as três do menu de hoje — assim um link novo já
   nasce certo. Os valores são a altura do header no estado ROLADO, que é o
   estado em que ele sempre está quando um salto de âncora termina, mais uma
   folga para o título não encostar na barra. */
section[id] { scroll-margin-top: 84px; }
@media (min-width: 900px) { section[id] { scroll-margin-top: 104px; } }

body {
  margin: 0;
  font-family: var(--sans);
  background: var(--carvao);
  color: var(--areia);
  -webkit-font-smoothing: antialiased;
}

img { max-width: 100%; display: block; }

h1, h2, h3, p, ul, figure { margin: 0; }
ul { padding: 0; list-style: none; }

a { color: var(--terracota); text-decoration: none; }
a:hover { color: var(--areia); }

/* ---------- elementos compartilhados ---------- */

.eyebrow {
  margin: 0 0 18px;
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: rgb(var(--areia-rgb) / 0.45);
}

.eyebrow--icon {
  display: flex;
  align-items: center;
  gap: 12px;
}
.eyebrow--icon img { width: 24px; height: 24px; border-radius: 7px; }

.h2 {
  font-family: var(--serif);
  font-weight: 700;
  font-size: clamp(34px, 8vw, 56px);
  line-height: 1.1;
  letter-spacing: -0.015em;
  text-wrap: pretty;
}
.h2--light  { color: var(--areia); }
.h2--center { text-align: center; }

.section-head { display: grid; gap: 24px; }
.section-head__sub {
  margin-top: 12px;
  font-size: clamp(18px, 4.6vw, 21px);
  line-height: 1.4;
  color: var(--marrom-texto);
}
.section-head__sub--light { color: rgb(var(--areia-rgb) / 0.62); }
.section-head__text {
  font-size: clamp(17px, 4.4vw, 20px);
  line-height: 1.6;
  color: rgb(var(--areia-rgb) / 0.78);
  text-wrap: pretty;
}
.section-head__text--light { color: rgb(var(--areia-rgb) / 0.82); }

@media (min-width: 900px) {
  .section-head {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr);
    gap: 56px;
    align-items: end;
  }
  .section-head__text { margin-bottom: 8px; }
}

/* Numeração das seções.
   Primeira linha do bloco de conteúdo de cada seção — mesma posição, tamanho e
   estilo em todas, sem exceção por seção. Fica em aria-hidden: é sinalização
   visual de sistema, e ler "zero zero, zero um" em voz alta não acrescenta nada.
   Duas variantes só de COR, porque a numeração precisa funcionar tanto sobre o
   azul-noite quanto sobre o creme. */
.secao-num {
  display: block;
  margin: 0 0 16px;
  text-align: left;
  font-family: var(--sans);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.24em;
  font-variant-numeric: tabular-nums;
  color: rgb(var(--areia-rgb) / 0.42);
}
/* sobre fundo claro */
/* Sobre creme, o MESMO alpha do lado escuro rende um cinza bem mais fraco:
   0.45 daria 2.72:1 contra os 3.57:1 que o número tem sobre o azul-noite. Os
   0.55 abaixo dão 3.61:1 — o alpha muda para o PESO PERCEBIDO não mudar. */
.secao-num--escuro { color: rgb(var(--carvao-rgb) / 0.55); }

/* ---------- kickers ----------
   Espaçamento em px, não na margem padrão do navegador: aquela é relativa ao
   tamanho da fonte do elemento, e como os títulos das seções têm tamanhos
   diferentes (56px no Labs, 46px nas demos), o mesmo markup abriria distâncias
   diferentes em cada uma. Em px o trio número/kicker/título fica idêntico. */
.eyebrow + .h2,
.eyebrow + .gain__title { margin-top: 0; }

/* Variante para fundo claro (seção das demos). O alpha é maior que os 45%
   usados no escuro de propósito: sobre creme, 45% resultaria num cinza bem
   mais fraco. Em 57% o contraste dá 3.83:1, praticamente o mesmo 3.88:1 que o
   kicker do Labs já tem sobre o azul-noite — o PESO PERCEBIDO é que precisa
   bater, não o número do alpha. */
.eyebrow--escuro { color: rgb(var(--carvao-rgb) / 0.57); }

/* O kicker da silhueta cai sobre a foto, não sobre cor sólida: mesma sombra do
   título ao lado dele, só para não perder a leitura no céu claro. */
.gain__text .eyebrow { text-shadow: 0 2px 22px rgb(var(--sombra-rgb) / 0.5); }

/* No contato o título é centralizado. Número e kicker à esquerda sobre um
   título centralizado leem como erro, então ali o trio inteiro centraliza. */
.cta__body .secao-num,
.cta__body .eyebrow { text-align: center; }

/* O "Soa familiar?" do hero usa a mesma classe mas não é kicker de seção — é
   rótulo da lista de dores. Devolve a margem que ele tinha, para o hero ficar
   exatamente como estava. */
.hero__pains .eyebrow { margin: 12px 0; }


/* botões */
.btn {
  display: inline-block;
  border-radius: 3px;
  font-size: 16px;
  font-weight: 500;
  text-align: center;
  padding: 15px 28px;
  border: 1px solid transparent;
  transition: background-color .18s ease, border-color .18s ease, color .18s ease;
}
.btn--solid {
  background: var(--terracota-med);
  border-color: var(--terracota-med);
  color: var(--creme);
}
.btn--solid:hover {
  background: var(--terracota-esc);
  border-color: var(--terracota-esc);
  color: var(--creme);
}
.btn--outline {
  background: transparent;
  border-color: rgb(var(--creme-rgb) / 0.45);
  color: var(--creme);
}
.btn--outline:hover {
  border-color: var(--creme);
  background: rgb(var(--creme-rgb) / 0.08);
  color: var(--creme);
}
.btn--ghost {
  background: transparent;
  border-color: rgb(var(--areia-rgb) / 0.28);
  color: var(--areia);
  padding: 13px 24px;
  font-size: 15px;
}
.btn--ghost:hover { border-color: var(--areia); color: var(--areia); }

/* molduras de foto */
.frame {
  position: relative;
  overflow: hidden;
  border-radius: 4px;
  background: var(--areia-media);
}
.frame--45 { aspect-ratio: 4 / 5; }
.frame > img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
}

/* =========================================================
   1. HERO
   ========================================================= */
.hero {
  position: relative;
  display: flex;
  flex-direction: column;
  min-height: 100svh;
  overflow: hidden;
}
.hero__bg,
.hero__glow {
  position: absolute;
  inset: -4%;
}
.hero__bg   { background-image: repeating-linear-gradient(115deg, var(--listra-a) 0 22px, var(--listra-b) 22px 44px); }
.hero__glow { background: radial-gradient(110% 78% at 66% 96%, rgb(var(--terracota-rgb) / 0.42) 0%, rgb(var(--terracota-esc-rgb) / 0.2) 44%, rgb(var(--carvao-rgb) / 0.04) 74%); }

/* ---- lado direito do hero (só desktop) ----
   Os dois blocos ficam escondidos por padrão e só aparecem a partir de 1024px.
   No celular o hero segue limpo, como estava. */
.hero__chama,
.hero__publico { display: none; }

@media (min-width: 1024px) {
  /* Marca d'água: o próprio símbolo da chama em traço, não o PNG do brasão —
     o PNG traria junto o quadrado arredondado, e o que se quer aqui é só a
     chama. Vem do mesmo caminho vetorial usado no ícone 3D. */
  .hero__chama {
    display: block;
    position: absolute;
    /* z-index 1: acima do fundo listrado, do glow e do véu; abaixo do corpo do
       hero, que é z-index 2. Nunca passa por cima de texto. */
    z-index: 1;
    top: 50%;
    right: 2%;
    height: 62%;
    transform: translateY(-50%);
    color: var(--areia);
    opacity: 0.1;
    pointer-events: none;
  }
  .hero__chama svg { height: 100%; width: auto; display: block; }

  /* Bloco de público. Centrado na faixa livre entre a nav e a régua de dores,
     via top 50% do hero — sem número mágico preso à altura de nenhum vizinho. */
  .hero__publico {
    display: block;
    position: absolute;
    z-index: 2;
    top: 50%;
    right: var(--gutter);
    transform: translateY(-50%);
    max-width: 260px;
    text-align: left;
  }
  .hero__publicolista {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 14px;
    font-size: 17px;
    line-height: 1.3;
    color: rgb(var(--areia-rgb) / 0.86);
  }
  .hero__publicolista li {
    position: relative;
    padding-left: 20px;
  }
  /* marcador terracota: usa --terracota-rgb, que na paleta petróleo guarda o
     laranja quente (232 118 63) e não o petróleo dos botões. É a mesma cor da
     chama e das brasas, então o calor do hero fica coerente. */
  .hero__publicolista li::before {
    content: "";
    position: absolute;
    left: 0;
    top: 0.5em;
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: rgb(var(--terracota-rgb));
  }
}

.hero__veil {
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgb(var(--carvao-rgb) / 0.92) 0%, rgb(var(--carvao-rgb) / 0.66) 34%, rgb(var(--carvao-rgb) / 0.5) 62%, rgb(var(--carvao-rgb) / 0.86) 100%);
}


/* Ponte hero -> Fervor Labs.
   O glow quente do hero está centrado em 96% de um elemento com inset -4%, ou
   seja, praticamente EM CIMA da emenda: no último pixel do hero ele ainda vale
   0.42 de alfa. Depois do véu isso deixa a cor final em ~(33,38,44), contra os
   (20,32,42) com que o Labs abre — 13 pontos de vermelho trocados de uma vez, e
   é essa troca que se lê como linha.
   A ponte leva o fim do hero exatamente até var(--carvao), a MESMA cor com que
   o Labs começa, então a emenda passa a ser contínua por construção, não por
   ajuste de olho. Mesma técnica estática das outras transições do site:
   gradiente em CSS, presente na primeira pintura, sem scroll e sem JS. */
.hero::after {
  content: "";
  /* absoluto também o tira do fluxo flex do .hero — como pseudo-elemento de um
     container flex, no fluxo ele viraria um item vazio e mexeria no layout */
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 240px;
  /* acima do fundo listrado, do glow e do véu; abaixo de todo o conteúdo, que
     é z-index 2 — o texto de "Soa familiar?" não é tocado */
  z-index: 1;
  pointer-events: none;
  /* Curva atrasada de propósito. Numa rampa linear o brilho quente do hero já
     estaria pela metade no meio do caminho; assim ele sobrevive quase inteiro e
     só o trecho final neutraliza. São 13 pontos de vermelho diluídos em 240px,
     ou 0.05 por pixel — abaixo de qualquer limiar de percepção. */
  background: linear-gradient(180deg,
    rgb(var(--carvao-rgb) / 0) 0%,
    rgb(var(--carvao-rgb) / 0.10) 35%,
    rgb(var(--carvao-rgb) / 0.28) 58%,
    rgb(var(--carvao-rgb) / 0.50) 74%,
    rgb(var(--carvao-rgb) / 0.72) 86%,
    rgb(var(--carvao-rgb) / 0.88) 94%,
    var(--carvao) 100%);
}
@media (min-width: 1080px) {
  /* o hero é mais alto no desktop; a ponte cresce junto para manter a mesma
     suavidade por pixel */
  .hero::after { height: 320px; }
}

/* navegação */
/* Header fixo.
   Fica DENTRO do .hero, que tem overflow: hidden — e isso funciona porque
   overflow só recorta descendentes cujo bloco contentor seja ele. O de um
   position:fixed é a viewport. Verifiquei que nenhum ancestral tem transform,
   filter, perspective ou contain, que prenderiam o fixed de volta. Se algum dia
   aparecer um desses no hero, este header para de acompanhar a rolagem. */
.nav {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  /* acima de tudo: o maior z-index do resto do site é 4 */
  z-index: 50;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 20px var(--gutter);
  /* sem fundo no topo: a abertura fica limpa */
  background-color: transparent;
  transition: padding .28s ease, background-color .28s ease;
}

/* estado rolado, ligado pelo JS depois de 60px */
.nav--solido {
  background-color: rgb(var(--carvao-rgb) / 0.78);
  -webkit-backdrop-filter: blur(14px) saturate(118%);
  backdrop-filter: blur(14px) saturate(118%);
  /* encolhe para devolver altura ao conteúdo */
  padding-top: 12px;
  padding-bottom: 12px;
}
/* sem blur disponível, o fundo precisa segurar a legibilidade sozinho */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .nav--solido { background-color: rgb(var(--carvao-rgb) / 0.94); }
}

/* No celular o header fixo compete com a tela toda, então o estado rolado
   encolhe também o botão e o logo. Só nesse estado: parado no topo, ambos
   seguem no tamanho cheio. */
@media (max-width: 899px) {
  /* 12px, nao menos: abaixo disso o botao cai dos 44px de altura minima
     recomendada para alvo de toque. Com 10px ele media 41px. */
  .nav--solido .nav__cta { padding: 12px 18px; font-size: 15px; }
  .nav--solido .nav__logo img { height: 20px; }
}

/* movimento reduzido: o estado muda na mesma, só não anima */
@media (prefers-reduced-motion: reduce) {
  .nav { transition: none; }
}

.nav__logo img { height: 24px; width: auto; }
.nav__links { display: none; gap: 32px; font-size: 15px; }

/* ---- ícone de menu (só abaixo do desktop) ----
   A versão anterior tinha barras de 1.5px: contraste ótimo (13.7:1), mas só
   5.6% do alvo tinha tinta, e no topo da página o header é transparente — três
   fios de cabelo sobre o hero texturizado não se anunciam como botão.
   Barras mais grossas e uma moldura discreta resolvem: a moldura é o que diz
   "isto aqui é tocável", e ela usa a mesma borda do .btn--ghost que ficava
   nesse canto antes. */
.nav__abrir {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  gap: 5px;
  /* 44x44: mínimo confortável de alvo de toque */
  width: 44px;
  height: 44px;
  padding: 0;
  background: rgb(var(--areia-rgb) / 0.07);
  border: 1px solid rgb(var(--areia-rgb) / 0.26);
  border-radius: 11px;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: background-color .18s ease, border-color .18s ease;
}
.nav__abrir:hover,
.nav__abrir[aria-expanded="true"] {
  background: rgb(var(--areia-rgb) / 0.14);
  border-color: rgb(var(--areia-rgb) / 0.42);
}
.nav__abrir span {
  display: block;
  width: 22px;
  height: 2.5px;
  background: var(--areia);
  border-radius: 2px;
  transition: transform .26s ease, opacity .2s ease;
}
/* vira X enquanto a gaveta está aberta.
   7.5px é a distância entre centros de barras vizinhas: 2.5 de altura + 5 de
   gap. Com o valor errado o X fecha torto. */
.nav__abrir[aria-expanded="true"] span:nth-child(1) { transform: translateY(7.5px) rotate(45deg); }
.nav__abrir[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
.nav__abrir[aria-expanded="true"] span:nth-child(3) { transform: translateY(-7.5px) rotate(-45deg); }

/* ---- gaveta ---- */
.gaveta__fundo {
  position: fixed;
  inset: 0;
  z-index: 55;
  background: rgb(var(--carvao-rgb) / 0.62);
  -webkit-backdrop-filter: blur(2px);
  backdrop-filter: blur(2px);
  opacity: 0;
  /* visibility em vez de display: display:none nao anima. O atraso na volta
     segura o elemento visivel ate a transicao terminar. */
  visibility: hidden;
  transition: opacity .3s ease, visibility 0s linear .3s;
}
.gaveta {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  z-index: 60;              /* acima do header, que é 50 */
  width: min(320px, 82vw);
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 18px 24px calc(24px + env(safe-area-inset-bottom));
  background: var(--carvao-2);
  border-left: 1px solid rgb(var(--areia-rgb) / 0.08);
  /* só transform e opacity animam: sai de graça no compositor */
  transform: translateX(100%);
  visibility: hidden;
  transition: transform .32s cubic-bezier(.4, 0, .2, 1), visibility 0s linear .32s;
  overflow-y: auto;
  overscroll-behavior: contain;   /* rolar dentro dela não arrasta a página */
}
.gaveta__fundo.esta-aberta {
  opacity: 1;
  visibility: visible;
  transition: opacity .3s ease, visibility 0s;
}
.gaveta.esta-aberta {
  transform: translateX(0);
  visibility: visible;
  transition: transform .32s cubic-bezier(.4, 0, .2, 1), visibility 0s;
}

.gaveta__fechar {
  align-self: flex-end;
  width: 44px;
  height: 44px;
  margin-right: -10px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: none;
  border: 0;
  padding: 0;
  color: rgb(var(--areia-rgb) / 0.7);
  cursor: pointer;
}
.gaveta__fechar svg { width: 22px; height: 22px; }
.gaveta__fechar:hover { color: var(--areia); }

.gaveta__links { display: flex; flex-direction: column; margin-top: 4px; }
.gaveta__links a {
  /* 48px de altura: os itens ficam colados, então cada um precisa de alvo
     próprio folgado para não haver toque errado */
  padding: 13px 0;
  font-size: 17px;
  color: rgb(var(--areia-rgb) / 0.82);
  border-bottom: 1px solid rgb(var(--areia-rgb) / 0.07);
}
.gaveta__links a:last-child { border-bottom: 0; }
.gaveta__links a:hover { color: var(--areia); }
.gaveta__cta { margin-top: 20px; }

@media (prefers-reduced-motion: reduce) {
  .gaveta, .gaveta__fundo, .nav__abrir span { transition-duration: 0s; }
}

.nav__links a { color: rgb(var(--areia-rgb) / 0.74); }
.nav__links a:hover { color: var(--areia); }

@media (min-width: 900px) {
  .nav { padding: 30px var(--gutter); }
  /* precisa vir DEPOIS da linha acima: mesma especificidade que .nav--solido,
     entao quem ganha e a ordem no arquivo. Sem isto o header nao encolhe no
     desktop, porque o padding de 30px daqui anula o do estado rolado. */
  .nav--solido { padding-top: 18px; padding-bottom: 18px; }
  .nav__logo img { height: 28px; }
}

/* A lista completa só entra quando há espaço de verdade para ela. Com 3 links
   cabia em 900px; com 6 não cabe, então o corte subiu para 1080px e o tablet
   passa a usar a gaveta. Abaixo disso o header é logo + ícone: o botão "Falar
   com a Fervor" vai para dentro da gaveta, como pedido. */
@media (max-width: 1079px) {
  .nav__cta { display: none; }
}
@media (min-width: 1080px) {
  .nav__links { display: flex; }
  .nav__abrir { display: none; }
  .gaveta, .gaveta__fundo { display: none; }
}

/* corpo do hero */
.hero__body {
  position: relative;
  z-index: 2;
  margin-top: auto;
  padding: 72px var(--gutter) 0;
  max-width: 1000px;
}
.hero__mark {
  position: relative;
  width: 58px;
  height: 58px;
  margin-bottom: 32px;
}
.hero__mark img {
  position: relative;
  width: 100%;
  height: 100%;
  border-radius: 15px;
}


.hero__markglow {
  position: absolute;
  inset: -30px;
  border-radius: 50%;
  background: radial-gradient(circle, rgb(var(--terracota-rgb) / 0.5) 0%, rgb(var(--terracota-rgb) / 0.14) 46%, rgb(var(--terracota-rgb) / 0) 72%);
}
/* Sem mouse (celular/tablet) a chama ganha um respiro lento no lugar do
   paralaxe. O JS nunca toca nestes elementos nesses aparelhos, entao a
   animação do CSS roda sozinha e sem conflito de transform. */
@media (hover: none) {
  .hero__mark img { animation: fervorRespiro 4s ease-in-out infinite; }
  .hero__markglow { animation: fervorBrilho 4s ease-in-out infinite; }
}
@keyframes fervorRespiro {
  0%, 100% { transform: scale(1); }
  50%      { transform: scale(1.03); }
}
@keyframes fervorBrilho {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.74; }
}
@media (prefers-reduced-motion: reduce) {
  .hero__mark img,
  .hero__markglow { animation: none; }
}

.hero__title {
  font-family: var(--serif);
  font-weight: 700;
  font-size: clamp(41px, 10.6vw, 84px);
  line-height: 1.06;
  letter-spacing: -0.018em;
  max-width: 15ch;
  text-wrap: pretty;
}
.hero__lead {
  margin-top: 24px;
  max-width: 610px;
  font-size: clamp(17px, 4.4vw, 19px);
  line-height: 1.62;
  color: rgb(var(--areia-rgb) / 0.76);
  text-wrap: pretty;
}
.hero__actions { margin-top: 36px; }
.hero__actions .btn {
  display: block;
  width: 100%;
  padding: 19px 30px;
  font-size: 17px;
}

@media (min-width: 600px) {
  .hero__actions .btn { display: inline-block; width: auto; padding: 19px 40px; }
}
@media (min-width: 900px) {
  .hero__mark { width: 74px; height: 74px; margin-bottom: 40px; }
  .hero__mark img { border-radius: 18px; }
  .hero__mark .hero__markglow { inset: -34px; }
  .hero__body { padding-top: 96px; }
}

/* faixa "soa familiar?" */
.hero__pains {
  position: relative;
  z-index: 2;
  margin-top: 56px;
  padding: 22px var(--gutter) 26px;
  /* SEM border-top de proposito. Havia aqui uma divisoria de 1px em areia a
     14%, que sobre o fundo do hero compunha rgb(60,65,69) contra rgb(30,37,44)
     ao redor: 30 pontos de salto num unico pixel, e era ELA a linha dura entre
     o hero e esta faixa — nao um degrau de fundo. A faixa nao tem fundo
     proprio, e o do hero atravessando, entao sem a borda nao sobra emenda
     nenhuma. Os 56px de margin-top mais 22px de padding ja separam o bloco. */
  display: flex;
  flex-direction: column;
  gap: 16px;
}
.hero__painlist {
  display: flex;
  flex-direction: column;
  gap: 8px;
  font-size: 16px;
  color: rgb(var(--areia-rgb) / 0.72);
}
@media (min-width: 900px) {
  .hero__pains {
    flex-direction: row;
    align-items: center;
    gap: 56px;
    margin-top: 84px;
    padding: 26px var(--gutter) 30px;
  }
  .hero__pains .eyebrow { white-space: nowrap; font-size: 13px; }
  .hero__painlist { flex-direction: row; flex-wrap: wrap; gap: 44px; }
}

/* =========================================================
   2. SOLUÇÕES — FERVOR LABS
   ========================================================= */
.labs {
  position: relative;
  padding: 88px var(--gutter) 96px;
  background: linear-gradient(180deg, var(--carvao) 0%, var(--carvao-2) 52%, var(--carvao-3) 100%);
  overflow: hidden;
}
.labs__halo {
  position: absolute;
  right: -20%;
  top: 12%;
  width: 620px;
  height: 620px;
  border-radius: 50%;
  background: radial-gradient(circle, rgb(var(--terracota-rgb) / 0.16) 0%, rgb(var(--terracota-rgb) / 0.05) 45%, rgb(var(--terracota-rgb) / 0) 70%);
  pointer-events: none;
}
.labs__head { position: relative; margin-bottom: 48px; }
.labs__head .eyebrow--icon { margin-bottom: 22px; }
.labs__head .section-head__sub { color: rgb(var(--areia-rgb) / 0.6); }


/* ---- Fervor Labs: texto à esquerda, 3D à direita (só no desktop) ----
   Abaixo de 1024px nada disto vale: .labs__interior nem vira grid, o palco
   some, e a seção fica exatamente como sempre foi — cabeçalho, cards
   empilhados, carrossel no celular. */
.labs__palco { display: none; }

@media (min-width: 1024px) {
  .labs__interior {
    position: relative;
    display: grid;
    /* 55fr / 45fr divide o espaço ÚTIL — o gap de 64px sai antes, então a
       conta e a leitura batem: a área dos cards fica com 55% e a do 3D com 45%
       do que sobra. Escrito assim em vez de 1fr/0.82fr porque os números do
       CSS passam a ser os mesmos da decisão. */
    grid-template-columns: minmax(0, 55fr) minmax(0, 45fr);
    column-gap: 64px;
  }

  /* Colocação explícita por linha. Antes o palco usava align-items: center e
     ficava alinhado ao conteúdo INTEIRO da esquerda — mas o cabeçalho só existe
     desse lado, e puxava o centro 163px para cima do bloco de cards.
     Com o palco na MESMA LINHA da grade, o centro dele passa a ser o centro dos
     quatro cards, que é o alinhamento pedido. */
  .labs__interior > .labs__head { grid-column: 1; grid-row: 1; }
  .labs__interior > .labs__grid { grid-column: 1; grid-row: 2; }
  .labs__interior > .labs__palco {
    grid-column: 2;
    grid-row: 2;
    align-self: center;
  }

  /* O cabeçalho é grid de duas colunas no resto do site. Dentro desta coluna
     mais estreita as duas ficariam apertadas, então aqui ele empilha. */
  .labs__interior .labs__head.section-head {
    grid-template-columns: minmax(0, 1fr);
    gap: 20px;
  }
  .labs__interior .labs__head .section-head__text { margin-bottom: 0; }

  .labs__palco {
    display: block;
    position: relative;
    /* quadrado: o modelo é um cubo, e um palco quadrado não sobra nem corta */
    aspect-ratio: 1 / 1;
    width: 100%;
  }

  .labs__marca2d,
  .labs__3d {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    border: 0;
    background: transparent;
  }
  /* o brasão 2D entra contido, não esticado: ele é quadrado e pequeno perto
     do palco, então fica centrado em 42% da caixa */
  .labs__marca2d {
    width: 42%;
    height: auto;
    inset: auto;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    border-radius: 18px;
    transition: opacity .6s ease-out;
  }
  .labs__3d {
    opacity: 0;
    /* mesma duracao do brasao 2D saindo: com valores diferentes a soma das duas
       opacidades afunda no meio e o crossfade da uma piscada */
    transition: opacity .6s ease-out;
    /* o arrasto para girar só faz sentido onde há mouse; e é o único lugar
       onde este bloco existe */
    pointer-events: none;
  }
  /* a troca só acontece quando o iframe confirma o load */
  .labs__palco.tem-3d .labs__3d { opacity: 1; pointer-events: auto; }
  .labs__palco.tem-3d .labs__marca2d { opacity: 0; }
}

/* movimento reduzido: nada de 3D, o brasão fica */
@media (prefers-reduced-motion: reduce) {
  .labs__3d { display: none; }
  .labs__palco.tem-3d .labs__marca2d { opacity: 1; }
}

.labs__grid {
  position: relative;
  display: grid;
  gap: 18px;
}

.card {
  background: var(--creme);
  color: var(--carvao);
  border-radius: 4px;
  padding: 34px 28px 38px;
}
.card__rule {
  display: flex;
  align-items: baseline;
  gap: 14px;
  margin-bottom: 20px;
}
.card__rule span {
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.06em;
  color: var(--terracota-med);
}
.card__rule i { flex: 1; height: 1px; background: var(--borda-clara); }
.card__title {
  font-family: var(--serif);
  font-weight: 700;
  font-size: clamp(23px, 5.6vw, 27px);
  line-height: 1.2;
  margin-bottom: 14px;
}
.card__text {
  font-size: 17px;
  line-height: 1.62;
  color: var(--marrom-texto);
  text-wrap: pretty;
}

@media (min-width: 720px) {
  .labs__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 22px; }
  .card { padding: 46px 44px 50px; }
}
@media (min-width: 1080px) {
  .labs { padding: 130px var(--gutter) 140px; }
  .labs__head { margin-bottom: 76px; }
}

/* =========================================================
   3. SEGMENTOS
   ========================================================= */
.segments {
  position: relative;
  padding: 88px var(--gutter) 100px;
  color: var(--carvao);
  background: linear-gradient(180deg, var(--carvao-3) 0%, var(--marrom-medio) 12%, var(--caramelo-escuro) 20%, var(--caramelo) 26%, var(--areia-quente) 32%, var(--areia) 40%, var(--areia) 100%);
}
.segments__head { margin-bottom: 64px; }
.segments__grid { display: grid; gap: 34px; }
.segment__title {
  margin: 22px 0 10px;
  font-family: var(--serif);
  font-weight: 700;
  font-size: clamp(22px, 5.4vw, 24px);
  line-height: 1.22;
}
.segment__text {
  font-size: 16px;
  line-height: 1.62;
  color: var(--marrom-texto);
  text-wrap: pretty;
}

@media (min-width: 620px) {
  .segments__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 26px 22px; }
}
@media (min-width: 1080px) {
  .segments { padding: 130px var(--gutter) 150px; }
  .segments__head { margin-bottom: 120px; }
  .segments__grid { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 26px; }
}

/* =========================================================
   VEJA FUNCIONANDO — provas em vídeo
   Encaixa entre Segmentos e Conceito, na faixa clara da página.
   ========================================================= */
.demo {
  background-color: var(--areia);
  /* faixa escura no pé: é dentro dela que a imagem da seção seguinte sobe,
     para não haver divisão visível entre as duas */
  /* alfa cresce devagar no começo: sobre o creme, mesmo 20% de escuro já é um
     degrau visível, então a rampa precisa ser adiantada e suave */
  background-image: linear-gradient(
    180deg,
    rgb(var(--carvao-rgb) / 0) 0%,
    rgb(var(--carvao-rgb) / 0.05) 20%,
    rgb(var(--carvao-rgb) / 0.18) 40%,
    rgb(var(--carvao-rgb) / 0.45) 62%,
    rgb(var(--carvao-rgb) / 0.78) 82%,
    var(--carvao) 100%
  );
  background-size: 100% 200px;
  background-position: bottom left;
  background-repeat: no-repeat;
  color: var(--carvao);
  padding: 88px var(--gutter) 200px;
}
.demo__head { max-width: 720px; margin-bottom: 44px; }
.demo__title { font-size: clamp(30px, 7.4vw, 46px); letter-spacing: -0.012em; }
.demo__sub {
  margin-top: 14px;
  font-size: clamp(17px, 4.4vw, 20px);
  line-height: 1.55;
  color: var(--marrom-texto);
  text-wrap: pretty;
}

/* faixas empilhadas; no desktop viram zigue-zague */
.demo__rows { display: grid; gap: 72px; }
.demo__row { display: grid; gap: 28px; align-items: center; }
.demo__rowtitle {
  font-family: var(--serif);
  font-weight: 700;
  font-size: clamp(24px, 6vw, 32px);
  line-height: 1.2;
  letter-spacing: -0.01em;
  text-wrap: pretty;
}
.demo__rowtext {
  margin-top: 14px;
  font-size: clamp(16px, 4.2vw, 18px);
  line-height: 1.62;
  color: var(--marrom-texto);
  text-wrap: pretty;
}


/* ---- cards de demonstração ----
   A faixa vira card de verdade: fundo, borda e raio. Sobre o creme da seção o
   contraste entre --areia e --creme é mínimo de propósito — quem desenha o
   limite é a borda de 1px, não o fundo. É o que mantém o card discreto. */
.demo__row {
  position: relative;
  background: var(--creme);
  border: 1px solid var(--borda-clara);
  /* acima dos 18px da moldura do navegador, que fica dentro dele: o raio de
     fora precisa ser maior que o de dentro para o encaixe não parecer torto */
  border-radius: 20px;
  padding: 26px 22px 24px;
  /* o gap herdado servia para separar moldura e texto lado a lado; agora ele
     também separaria selo e rodapé do miolo, e 64px ali seria buraco */
  column-gap: 0;
  row-gap: 22px;
}

/* selo no canto superior. É item do grid ocupando a linha inteira, não um
   absolute: assim ele reserva o próprio espaço e nunca cobre a moldura,
   qualquer que seja o lado dela no zigue-zague. */
.demo__badge {
  grid-column: 1 / -1;
  justify-self: start;
  margin: 0;
  padding: 6px 12px;
  border-radius: 999px;
  background: rgb(var(--carvao-rgb) / 0.05);
  border: 1px solid rgb(var(--carvao-rgb) / 0.11);
  font-family: var(--sans);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  font-variant-numeric: tabular-nums;
  color: rgb(var(--carvao-rgb) / 0.62);
}

/* o kicker do card usa a mesma classe .eyebrow das seções; falta só zerar a
   margem em em que o navegador dá ao h3 logo abaixo */
.eyebrow + .demo__rowtitle { margin-top: 0; }

/* rodapé do card, atravessando as duas colunas */
.demo__cta {
  grid-column: 1 / -1;
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0;
  padding-top: 20px;
  border-top: 1px solid var(--borda-clara);
  font-family: var(--sans);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  /* petróleo, a cor de ação da paleta: é o que diferencia o rodapé do kicker,
     que fora a cor tem exatamente a mesma tipografia. 5.7:1 sobre o creme. */
  color: var(--terracota-med);
}
.demo__seta { font-size: 14px; line-height: 1; }

/* ---- molduras de aparelho ---- */
.device { position: relative; background: var(--carvao); }

.device--phone {
  border-radius: 30px;
  padding: 9px;
  box-shadow: 0 20px 46px rgb(var(--sombra-quente-rgb) / 0.18);
}
.device--phone .device__screen { border-radius: 22px; aspect-ratio: 9 / 19; }
.device__notch {
  position: absolute;
  top: 17px;
  left: 50%;
  transform: translateX(-50%);
  width: 52px;
  height: 4px;
  border-radius: 3px;
  background: rgb(var(--areia-rgb) / 0.3);
  z-index: 2;
}

.device--browser {
  border-radius: 10px;
  overflow: hidden;
  box-shadow: 0 20px 46px rgb(var(--sombra-quente-rgb) / 0.18);
}
.device__bar {
  display: flex;
  align-items: center;
  gap: 6px;
  height: 32px;
  padding: 0 12px;
  background: var(--carvao-barra);
}
.device__dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: rgb(var(--areia-rgb) / 0.2);
}
.device__dot:first-child { background: rgb(var(--terracota-rgb) / 0.65); }
.device__url {
  flex: 1;
  height: 14px;
  margin-left: 10px;
  border-radius: 7px;
  background: rgb(var(--areia-rgb) / 0.09);
}
.device--browser .device__screen { aspect-ratio: 16 / 10; }

/* ---- tela: placeholder por baixo, vídeo por cima ---- */
.device__screen {
  position: relative;
  overflow: hidden;
  background: radial-gradient(120% 90% at 50% 38%, var(--carvao-suave) 0%, var(--carvao) 72%);
}

.device__screen video {
  position: relative;
  z-index: 1;
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  border: 0;
}
/* app.js marca .is-empty quando o arquivo de vídeo ainda não existe */
.device__screen.is-empty video { display: none; }

.device__fallback {
  position: absolute;
  inset: 0;
  display: grid;
  place-content: center;
  justify-items: center;
  gap: 14px;
  padding: 16px;
}
.playmark {
  width: 40px;
  height: 40px;
  color: rgb(var(--creme-rgb) / 0.3);
}
.device__hint {
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  text-align: center;
  color: rgb(var(--creme-rgb) / 0.28);
}

/* no mobile a moldura fica em cima e o texto embaixo (ordem do HTML) */
.demo__media .device--phone {
  width: 100%;
  max-width: 240px;
  margin-inline: auto;
}

@media (min-width: 900px) {
  .demo__rows { gap: 120px; }
  /* column-gap, nao o atalho gap: o atalho reescreveria tambem o row-gap do
     card, e 64px entre selo, miolo e rodape seria buraco */
  .demo__row { column-gap: 64px; row-gap: 28px; padding: 34px 30px 30px; }
  /* colunas assimetricas: o celular pede pouca largura, o painel pede muita */
  .demo__row--phone { grid-template-columns: minmax(0, 320px) minmax(0, 1fr); }
  .demo__row--browser { grid-template-columns: minmax(0, 1fr) minmax(0, 620px); }
  /* Zigue-zague: na faixa do painel a moldura vai para a coluna da direita.
     Os QUATRO itens precisam de ordem explicita. Com order so na moldura, os
     outros tres ficariam em 0 e o rodape passaria na frente dela. */
  .demo__row--browser .demo__badge { order: 1; }
  .demo__row--browser .demo__copy  { order: 2; }
  .demo__row--browser .demo__media { order: 3; }
  .demo__row--browser .demo__cta   { order: 4; }
  .demo__copy { max-width: 480px; }
  .demo__media .device--phone { max-width: 320px; }
}

@media (min-width: 1080px) {
  .demo { padding: 130px var(--gutter) 260px; background-size: 100% 260px; }
  .demo__head { margin-bottom: 72px; }
  .demo__rows { gap: 140px; }
  .demo__row { column-gap: 80px; row-gap: 32px; padding: 40px 36px 34px; }
}

/* =========================================================
   4. CONCEITO
   ========================================================= */
.concept {
  position: relative;
  /* sem padding no topo: quem posiciona a imagem é a margem negativa dela,
     que a faz subir para dentro da faixa escura da seção anterior */
  /* O padding do topo existe para a frase de contexto ter para onde crescer:
     acima da chama só há ~56px dentro da própria imagem, e o texto grande
     precisa de mais. Como é carvão sólido, a emenda com a seção anterior
     continua sem costura. */
  padding: 110px var(--gutter) 150px;
  /* flow-root é obrigatório: sem padding no topo, a margem negativa do frame
     colapsaria com a do pai e arrastaria a SEÇÃO inteira para cima — o fundo
     sólido subiria junto e criaria justamente a linha dura que queremos evitar.
     Com um BFC, só a imagem transborda; o fundo fica onde está. */
  display: flow-root;
  /* nada de overflow:hidden aqui — é ele que impediria a imagem de transbordar.
     O halo já é limitado a 96vw, então não há estouro horizontal. */
  overflow-x: clip;
  /* carvão puro: a seção de cima já chega escura, então não há emenda a fazer.
     A camada de cima é o fade de 88px no pé, que fecha no tom da foto seguinte. */
  background-color: var(--carvao);
  /* Zona de difusão com a foto seguinte, CONTIDA na faixa abaixo do claim.
     Ela não pode alcançar a imagem: o véu da imagem termina em carvão sólido
     e tem a largura dela, então sobre âmbar ele apareceria como um retângulo
     escuro. Por isso o padding da base é maior que o necessário para o texto —
     a sobra é o espaço exclusivo desta transição.
     A seção de baixo abre com a MESMA cor (ver .gain::before), então na emenda
     não há degrau nenhum. */
  background-image: linear-gradient(180deg,
    rgb(var(--ambar-escuro-rgb) / 0) 0%,
    rgb(var(--ambar-escuro-rgb) / 0.14) 28%,
    rgb(var(--ambar-escuro-rgb) / 0.42) 55%,
    rgb(var(--ambar-escuro-rgb) / 0.76) 80%,
    var(--ambar-escuro) 100%);
  background-size: 100% 140px;
  background-position: bottom left;
  background-repeat: no-repeat;
}
/* Frase de contexto SOBRE a imagem, no mesmo tratamento do claim da base:
   creme, centrada, sem scrim. A legibilidade vem do mesmo lugar que a do
   claim — os 7% do topo estão na faixa onde a máscara já dissolveu a foto,
   então o que há atrás do texto é o carvão da seção, não a fotografia.
   Absoluta de propósito: fora do fluxo, não abre espaço vazio algum. */
.concept__intro {
  position: absolute;
  z-index: 2;
  /* Ancorada pela BASE, não pelo topo. Ancorar pelo topo com percentual
     falhava: a imagem tem 559px no celular e 2146px no desktop, então o mesmo
     percentual deixava a frase colada na chama num caso e a 126px dela no
     outro. Com bottom, a borda inferior do texto cai sempre logo acima da
     chama (que fica a 14% do topo), e o bloco cresce para cima conforme o
     texto — o vão não depende mais da altura da imagem. */
  bottom: 93%;
  top: auto;
  left: 0;
  right: 0;
  margin: 0 auto;
  max-width: 20ch;
  padding: 0 var(--gutter);
  pointer-events: none;
}

/* As duas frases da seção são irmãs: mesmo tipo, tamanho, peso, cor,
   alinhamento e sombra. A única diferença é a âncora — uma cresce para cima
   a partir do topo da chama, a outra para baixo a partir da base da imagem. */
.concept__intro,
.concept__claim {
  text-align: center;
  font-family: var(--serif);
  font-weight: 700;
  /* No celular sobra pouco espaço acima da chama, então as duas descem juntas
     para caber; no desktop as duas ficam grandes. Mexer aqui move as duas. */
  font-size: clamp(30px, 7.6vw, 78px);
  line-height: 1.1;
  letter-spacing: -0.018em;
  color: var(--creme);
  text-wrap: pretty;
  /* Duas sombras: a larga separa do fundo, a curta dá nitidez na borda das
     letras. Necessário porque o claim agora cai sobre a faixa âmbar da
     transição, e não mais sobre carvão sólido. */
  text-shadow:
    0 2px 20px rgb(var(--carvao-rgb) / 0.85),
    0 1px 3px rgb(var(--carvao-rgb) / 0.55);
}

.concept__frame {
  position: relative;
  /* no celular sangra até as bordas: a tela é estreita, então a foto em pé
     cabe numa altura razoável */
  max-width: none;
  margin: 0 calc(-1 * var(--gutter));
  /* A frase de contexto é position:absolute e sobe ~60px ACIMA deste quadro.
     O número e o kicker "04 / A VIRADA" foram acrescentados depois que essa
     posição foi calibrada, e passaram a ocupar justamente essa faixa — a frase
     encavalava 42px sobre o kicker.
     Esta margem abre a folga: empurra o quadro, e com ele a frase, para baixo
     dos dois. Ficam ~44px livres entre o kicker e o topo da frase.
     O ganho liquido nao e o valor cheio: a margem de baixo do kicker (18px) e
     esta colapsam entre si, entao o quadro desce apenas a diferenca.
     Só no celular: no desktop a seção tem padding de sobra e nunca houve
     colisão. */
  margin-top: 104px;
}
@media (min-width: 1080px) {
  .concept__frame { margin-top: 0; }
}

/* Largura limitada da tablet para cima, mas com folga: a zona de dissolução é
   proporcional ao tamanho da imagem, então estreitar demais endurece as bordas.
   Em 940px a rampa do topo tem 448px e a lateral 273px — contra 687px e 418px
   quando a foto sangrava os 1440px inteiros, e contra apenas 315px e 191px se
   fosse para 660px. É o ponto onde a fusão continua macia sem a seção voltar
   para quase três telas. */
@media (min-width: 768px) {
  .concept__frame {
    max-width: min(1000px, 90vw);
    margin-inline: auto;
  }
}
.concept__halo {
  position: absolute;
  left: 50%;
  top: 42%;
  width: min(1100px, 96vw);
  height: min(1100px, 96vw);
  transform: translate(-50%, -50%);
  border-radius: 50%;
  background: radial-gradient(circle, rgb(var(--terracota-rgb) / 0.34) 0%, rgb(var(--terracota-rgb) / 0.13) 38%, rgb(var(--terracota-rgb) / 0) 68%);
  pointer-events: none;
}

/* Sem moldura: nada de borda, canto arredondado, sombra ou fundo. A proporção
   é a nativa do arquivo (1240x1848), então nada é cortado. */
.concept__img {
  position: relative;
  /* a máscara isolava o grupo, e era isso que mantinha o mix-blend-mode do
     glow limitado à imagem. Sem ela, isolation faz o mesmo — e sem o custo
     de renderizar o grupo numa textura à parte. */
  isolation: isolate;
  width: 100%;
  aspect-ratio: 1240 / 1848;
  overflow: hidden;
  /* Fade longo: opaco só do miolo, com rampas generosas nas duas pontas. Os
     stops intermediários evitam a "borda" que um gradiente de dois pontos cria,
     e é isso que faz o começo da imagem ser imperceptível. */
}

/* A dissolução nos quatro lados era feita com mask-image + mask-composite.
   Trocada por um VÉU pintado por cima, em carvão — a mesma cor de fundo da
   seção, então o resultado na tela é o mesmo.
   O motivo é de performance: um elemento mascarado precisa ser renderizado
   numa textura própria antes de receber a máscara, e qualquer mudança lá
   dentro (a opacidade da corrente, as 48 brasas animando) forçava re-rasterizar
   essa textura inteira a cada quadro — numa imagem que sangra a tela toda.
   Um véu é apenas mais uma camada composta, e sai de graça. */
.concept__img::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 4;
  pointer-events: none;
  /* As paradas são em PORCENTAGEM, então a zona de dissolução encolhe junto
     com a imagem: ao estreitar a foto, a mesma rampa de 29% caiu de 622px para
     285px e a borda passou a parecer dura. As rampas foram alongadas (32% no
     topo, 29% nas laterais) para compensar a imagem menor. */
  background:
    linear-gradient(180deg,
      /* topo e miolo: inalterados */
      var(--carvao) 0%, rgb(var(--carvao-rgb) / 0.93) 8%, rgb(var(--carvao-rgb) / 0.72) 16%,
      rgb(var(--carvao-rgb) / 0.38) 24%, transparent 32%, transparent 58%,
      /* Base: a rampa começa antes (58% em vez de 63%) mas com alfa muito
         baixo no início — aos 70% ainda são só 20%, então a corrente, que vai
         até ali, continua nítida. A dissolução de verdade acontece depois,
         sobre o antebraço, e chega ao carvão em passos curtos para não
         deixar degrau na borda. */
      rgb(var(--carvao-rgb) / 0.06) 64%, rgb(var(--carvao-rgb) / 0.20) 70%,
      rgb(var(--carvao-rgb) / 0.42) 77%, rgb(var(--carvao-rgb) / 0.66) 85%,
      rgb(var(--carvao-rgb) / 0.86) 92%, rgb(var(--carvao-rgb) / 0.96) 97%,
      var(--carvao) 100%),
    linear-gradient(90deg,
      var(--carvao) 0%, rgb(var(--carvao-rgb) / 0.92) 6%, rgb(var(--carvao-rgb) / 0.66) 13%,
      rgb(var(--carvao-rgb) / 0.30) 21%, transparent 29%, transparent 71%,
      rgb(var(--carvao-rgb) / 0.30) 79%, rgb(var(--carvao-rgb) / 0.66) 87%,
      rgb(var(--carvao-rgb) / 0.92) 94%, var(--carvao) 100%);
}

/* as duas fotos ocupam exatamente a mesma caixa */
.concept__img img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* BRASAS SUBINDO
   Doze pontos que sobem do pulso em direção à chama, cada um com atraso,
   duração, desvio lateral e tamanho próprios — é a irregularidade que faz
   parecer fogo e não uma fileira. Cada ponto anima só transform/opacity;
   quem liga e desliga o conjunto é a opacidade do container, escrita pelo JS
   conforme o scroll. Sem blend aqui de propósito: já são três camadas em
   screen nesta seção e o celular agradece. */
.concept__brasas {
  position: absolute;
  inset: 0;
  opacity: 0;
  pointer-events: none;
  --subida: 260px;
}
.concept__brasas i {
  position: absolute;
  /* nasce a 64% da altura (região do pulso e da corrente), ainda dentro da
     faixa opaca da máscara — mais embaixo elas já nasceriam apagadas */
  bottom: 36%;
  border-radius: 50%;
  /* núcleo quase branco virando dourado e depois brasa: é esse degradê, mais o
     halo duplo do box-shadow, que faz o ponto ler como ember e não como poeira */
  background: radial-gradient(circle, var(--dourado-claro) 0%, var(--dourado) 30%, var(--brasa-media) 55%, rgb(var(--terracota-rgb) / 0.45) 72%, rgb(var(--terracota-rgb) / 0) 86%);
  box-shadow: 0 0 10px rgb(var(--brasa-halo-rgb) / 0.9), 0 0 22px rgb(var(--terracota-rgb) / 0.5);
  opacity: 0;
  animation: fervorBrasaSobe var(--t, 4s) linear var(--d, 0s) infinite;
}

/* as maiores ganham um halo extra, para o conjunto não ficar uniforme */
.concept__brasas i:nth-child(3n) {
  box-shadow: 0 0 12px rgb(var(--dourado-halo-rgb) / 0.95), 0 0 30px rgb(var(--terracota-rgb) / 0.6);
}

/* A trajetória zigueza: o desvio lateral troca de sinal no meio do caminho, em
   vez de ir reto de A a B. É o que faz parecer brasa levada pelo ar quente. */
@keyframes fervorBrasaSobe {
  0%   { transform: translate3d(0, 0, 0) scale(0.4); opacity: 0; }
  8%   { opacity: 1; }
  30%  { transform: translate3d(calc(var(--dx) * 0.45), calc(var(--subida) * -0.28), 0) scale(1); opacity: 1; }
  55%  { transform: translate3d(calc(var(--dx) * -0.35), calc(var(--subida) * -0.55), 0) scale(1.12); opacity: 0.95; }
  78%  { transform: translate3d(calc(var(--dx) * 0.8), calc(var(--subida) * -0.78), 0) scale(1.02); opacity: 0.6; }
  100% { transform: translate3d(var(--dx), calc(-1 * var(--subida)), 0) scale(0.8); opacity: 0; }
}

/* A variação vem de três ciclos de tamanhos COPRIMOS (11, 5 e 3): como
   11×5×3 = 165 > 48, nenhuma brasa repete a combinação de posição, tempo e
   desvio da outra. Dezenove regras cobrem as 48 partículas — enumerar uma a
   uma seria quase três vezes mais CSS para o mesmo resultado. */

/* posição horizontal e tamanho — ciclo de 11 */
.concept__brasas i:nth-child(11n+1)  { left: 36%; width: 5px; height: 5px; }
.concept__brasas i:nth-child(11n+2)  { left: 43%; width: 7px; height: 7px; }
.concept__brasas i:nth-child(11n+3)  { left: 50%; width: 4px; height: 4px; }
.concept__brasas i:nth-child(11n+4)  { left: 57%; width: 8px; height: 8px; }
.concept__brasas i:nth-child(11n+5)  { left: 64%; width: 5px; height: 5px; }
.concept__brasas i:nth-child(11n+6)  { left: 40%; width: 6px; height: 6px; }
.concept__brasas i:nth-child(11n+7)  { left: 47%; width: 9px; height: 9px; }
.concept__brasas i:nth-child(11n+8)  { left: 54%; width: 4px; height: 4px; }
.concept__brasas i:nth-child(11n+9)  { left: 61%; width: 6px; height: 6px; }
.concept__brasas i:nth-child(11n+10) { left: 45%; width: 7px; height: 7px; }
.concept__brasas i:nth-child(11n+11) { left: 59%; width: 5px; height: 5px; }

/* atraso, duração e altura de nascimento — ciclo de 5 */
.concept__brasas i:nth-child(5n+1) { --d: 0s;   --t: 4.2s; bottom: 36%; }
.concept__brasas i:nth-child(5n+2) { --d: 1.3s; --t: 5.1s; bottom: 33%; }
.concept__brasas i:nth-child(5n+3) { --d: 2.6s; --t: 3.7s; bottom: 39%; }
.concept__brasas i:nth-child(5n+4) { --d: 3.9s; --t: 4.8s; bottom: 31%; }
.concept__brasas i:nth-child(5n+5) { --d: 5.2s; --t: 4.4s; bottom: 41%; }

/* desvio lateral — ciclo de 3 */
.concept__brasas i:nth-child(3n+1) { --dx: -17px; }
.concept__brasas i:nth-child(3n+2) { --dx: 13px; }
.concept__brasas i:nth-child(3n+3) { --dx: -8px; }

/* no celular ficam 32 brasas em vez de 48: a imagem é menor, então a densidade
   percebida continua alta e sobra folga de processamento para a rolagem */
@media (max-width: 767.98px) {
  /* de 32 para 20. Cada brasa anima com box-shadow duplo, que e a propriedade
     mais cara do conjunto: ao contrario de transform e opacity ela nao sai de
     graca no compositor e obriga a repintar. Doze a menos e um terco do custo
     de pintura fora, e a densidade percebida quase nao muda porque as que ficam
     mantem a mesma variedade de tamanho, atraso e trajetoria. */
  .concept__brasas i:nth-child(n+21) { display: none; }

  /* o halo extra das maiores sai no celular: sao duas sombras somadas por
     elemento, e o brilho de base ja da o efeito de ember */
  .concept__brasas i:nth-child(3n) { box-shadow: 0 0 10px rgb(var(--brasa-halo-rgb) / 0.9); }
}
@media (min-width: 768px) {
  .concept__brasas { --subida: 560px; }
}

/* Brilho quente e CONSTANTE sobre a chama. Sem animação e sem controle pelo
   scroll: é um glow fixo, parado. O movimento da seção fica todo por conta das
   brasas subindo. */
.concept__brasa {
  position: absolute;
  left: 50%;
  top: 22%;
  width: 52%;
  aspect-ratio: 1;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  background: radial-gradient(circle, rgb(var(--terracota-rgb) / 0.62) 0%, rgb(var(--terracota-rgb) / 0.26) 40%, rgb(var(--terracota-rgb) / 0) 70%);
  mix-blend-mode: screen;
  opacity: 1;
  pointer-events: none;
}

/* A corrente é CONTEÚDO, não enfeite: começa sempre visível e não depende de
   nenhuma chave de animação. Sem JS ela simplesmente fica assim — estática e
   inteira. Só o "sumir ao rolar" é aplicado pelo JS, via opacity inline. */
.concept__presa { opacity: 1; will-change: opacity, transform; }

/* desfoque FIXO: rasteriza uma vez e nunca mais. O que anima é só a opacidade */
.concept__desfoque {
  opacity: 0;
  filter: blur(7px);
  will-change: opacity, transform;
}
/* No celular esta camada sai. É uma terceira cópia da imagem inteira com blur
   e will-change, ou seja, 210k px rasterizados e uma camada de composição
   mantida em memória o tempo todo — o item mais caro da seção num aparelho
   pequeno. Sem ela o crossfade vai direto da corrente para a mão livre, em vez
   de passar por um meio borrado: menos efeito, mais fluidez.
   Não muda o download: é o mesmo arquivo da camada da corrente.
   O JS já testa "if (desfoque)" e escreve num elemento oculto sem efeito. */
@media (max-width: 767px) {
  .concept__desfoque { display: none; }
}

/* Esta seção INTEIRA roda mesmo com prefers-reduced-motion, por decisão de
   marca: a corrente virando fogo é o momento central da página. Por isso não
   existe aqui nenhum bloco @media (prefers-reduced-motion: reduce) — nem para
   a chama, nem para as brasas, nem para a dissolução.
   O resto do site continua respeitando a preferência: fade das seções,
   cascata dos cards e paralaxe do hero seguem desligados nela. */

.concept__claim {
  position: relative;
  /* sobe sobre a cauda já quase transparente da imagem, para não haver um
     degrau entre foto e texto */
  margin: -56px auto 0;
  max-width: 20ch;
}
@media (min-width: 1080px) {
  /* o padding do topo não é espaço morto: é onde a frase de contexto cresce.
     Com a imagem em 1401px, a frase começa 98px abaixo do topo dela e ocupa
     257px, então precisa de ~160px acima. A base essa sim foi enxugada. */
  .concept { padding: 165px var(--gutter) 230px; }
  /* no desktop a difusão sobe bem mais: a seção é alta e uma faixa curta
     ficaria proporcionalmente tímida */
  .concept { background-size: 100% 220px; }
  .gain::before { height: 320px; }
  .gain::after  { height: 540px; }
  .concept__claim { margin-top: -96px; }
}

/* =========================================================
   5. O QUE VOCÊ GANHA
   ========================================================= */
.gain {
  position: relative;
  display: flex;
  align-items: flex-start;
  min-height: 90vh;
  min-height: 90svh;
  overflow: hidden;
  background: var(--carvao);
}

/* O outro lado da emenda. Abre exatamente na mesma cor em que a seção de cima
   fecha (--ambar-escuro) e dissolve para dentro da foto ao longo de 200px.
   Como as duas pontas são a mesma cor, o olho não acha onde uma acaba.
   Só a faixa do topo é tratada — o pôr do sol e a silhueta ficam intactos. */
.gain::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 240px;
  z-index: 1;
  pointer-events: none;
  background: linear-gradient(180deg,
    var(--ambar-escuro) 0%,
    rgb(var(--ambar-escuro-rgb) / 0.72) 26%,
    rgb(var(--ambar-escuro-rgb) / 0.38) 52%,
    rgb(var(--ambar-escuro-rgb) / 0.14) 76%,
    rgb(var(--ambar-escuro-rgb) / 0) 100%);
}

/* Espelho do ::before, na saída: a foto dissolve para baixo e termina
   exatamente em var(--carvao), a mesma cor com que a seção de contato começa.
   Mesma técnica da entrada — gradiente estático no CSS, presente desde o
   primeiro paint, sem depender de scroll nem de JS. */
.gain::after {
  content: "";
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  /* 380px para igualar o COMPRIMENTO TOTAL da entrada (140 no lado da mão +
     240 no lado da foto). Aqui não faz sentido dividir em dois trechos: na
     entrada as seções têm cores-base diferentes e a ponte precisa dos dois
     lados; na saída ambos já são carvão, então só este gradiente conta e ele
     tem que carregar sozinho toda a distância. */
  height: 380px;
  z-index: 1;
  pointer-events: none;
  /* rampa longa e de início muito suave: o alfa quase não sobe no primeiro
     terço, que é onde a emenda ficava aparente */
  background: linear-gradient(180deg,
    rgb(var(--carvao-rgb) / 0) 0%,
    rgb(var(--carvao-rgb) / 0.06) 18%,
    rgb(var(--carvao-rgb) / 0.18) 36%,
    rgb(var(--carvao-rgb) / 0.38) 55%,
    rgb(var(--carvao-rgb) / 0.62) 72%,
    rgb(var(--carvao-rgb) / 0.84) 87%,
    rgb(var(--carvao-rgb) / 0.95) 95%,
    var(--carvao) 100%);
}

/* foto full-bleed; o recorte no mobile mantem o ceu livre no topo/esquerda */
.gain__photo {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* 57% enquadra a figura inteira no recorte estreito do celular,
     deixando o ceu livre na faixa de cima para o texto */
  object-position: 57% center;
}

/* veu escuro so no topo, o bastante para o texto ler sobre o ceu claro */
.gain__scrim {
  position: absolute;
  inset: 0 0 auto 0;
  height: 58%;
  background: linear-gradient(180deg, rgb(var(--sombra-rgb) / 0.56) 0%, rgb(var(--sombra-rgb) / 0.3) 40%, rgb(var(--sombra-rgb) / 0) 100%);
  pointer-events: none;
}

.gain__text {
  position: relative;
  /* acima da ponte âmbar do ::before, que é z-index 1 */
  z-index: 2;
  width: 100%;
  max-width: 560px;
  padding: clamp(36px, 8vw, 104px) var(--gutter) 0;
}
.gain__title {
  font-family: var(--serif);
  font-weight: 700;
  font-size: clamp(29px, 7.4vw, 56px);
  line-height: 1.12;
  letter-spacing: -0.015em;
  color: var(--creme);
  text-wrap: pretty;
  text-shadow: 0 2px 22px rgb(var(--sombra-rgb) / 0.5);
}
.gain__closing {
  margin-top: 18px;
  font-size: clamp(16px, 4.2vw, 20px);
  line-height: 1.55;
  color: rgb(var(--creme-rgb) / 0.92);
  text-wrap: pretty;
  text-shadow: 0 1px 16px rgb(var(--sombra-rgb) / 0.6);
}

@media (min-width: 720px) {
  .gain__photo { object-position: center; }
  .gain__scrim {
    height: 100%;
    background:
      linear-gradient(180deg, rgb(var(--sombra-rgb) / 0.46) 0%, rgb(var(--sombra-rgb) / 0.16) 46%, rgb(var(--sombra-rgb) / 0) 68%),
      linear-gradient(90deg, rgb(var(--sombra-rgb) / 0.34) 0%, rgb(var(--sombra-rgb) / 0) 52%);
  }
  .gain__text { max-width: 500px; }
}
@media (min-width: 1080px) {
  .gain__text { max-width: 640px; }
}

/* =========================================================
   6. CONTATO / CTA
   ========================================================= */
.cta {
  position: relative;
  padding: 96px var(--gutter) 100px;
  text-align: center;
  overflow: hidden;
  /* Mesma cor com que o Fervor Labs começa: var(--carvao), sólido. Antes havia
     aqui um degradê próprio que destoava do resto. Como o rodapé também é
     carvão, as duas últimas faixas do site ficam contínuas, e o brilho da
     seção passa a vir só do halo. */
  background: var(--carvao);
}
/* O halo tinha 1100px de ALTURA FIXA centrados em top:30%, o que jogava a
   borda dele centenas de pixels acima do topo da seção — e como .cta tem
   overflow:hidden, ele era cortado a seco bem na fronteira com a foto, ainda
   com ~12% de opacidade. Aquele corte era a faixa horizontal.
   Agora a altura é relativa (90% da seção) e o centro fica em 50%, então ele
   vai de 5% a 95% e nunca encosta nas bordas. A largura é limitada a 130vw
   para que, na lateral, o corte também caia onde o gradiente já é zero. */
.cta__halo {
  position: absolute;
  left: 50%;
  top: 50%;
  width: min(1100px, 130vw);
  height: 90%;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  background: radial-gradient(ellipse, rgb(var(--terracota-rgb) / 0.34) 0%, rgb(var(--terracota-rgb) / 0.12) 40%, rgb(var(--terracota-rgb) / 0) 68%);
  pointer-events: none;
}
.cta__body {
  position: relative;
  max-width: 860px;
  margin: 0 auto;
}
.cta__mark {
  position: relative;
  width: 74px;
  height: 74px;
  margin: 0 auto 36px;
}
.cta__mark img {
  position: relative;
  width: 100%;
  height: 100%;
  border-radius: 18px;
  box-shadow: 0 20px 60px rgb(var(--sombra-quente-rgb) / 0.35);
}
.cta__markglow {
  position: absolute;
  inset: -40px;
  border-radius: 50%;
  background: radial-gradient(circle, rgb(var(--creme-rgb) / 0.4) 0%, rgb(var(--terracota-rgb) / 0.28) 40%, rgb(var(--terracota-rgb) / 0) 70%);
}
.cta__title {
  font-family: var(--serif);
  font-weight: 700;
  font-size: clamp(32px, 8.4vw, 62px);
  line-height: 1.12;
  letter-spacing: -0.018em;
  color: var(--creme);
  text-wrap: pretty;
}
.cta__lead {
  margin: 24px auto 0;
  max-width: 640px;
  font-size: clamp(17px, 4.4vw, 19px);
  line-height: 1.62;
  color: rgb(var(--creme-rgb) / 0.86);
  text-wrap: pretty;
}
.cta__actions {
  display: flex;
  flex-direction: column;
  /* centrado: com um botao so, sem isto ele esticaria a largura toda do bloco */
  align-items: center;
  gap: 12px;
  margin-top: 36px;
}
.cta__actions .btn--solid { box-shadow: 0 14px 40px rgb(var(--sombra-quente-rgb) / 0.35); }

@media (min-width: 600px) {
  .cta__actions { flex-direction: row; justify-content: center; gap: 16px; }
  .cta__actions .btn { padding: 17px 34px; }
}
@media (min-width: 1080px) {
  .cta { padding: 150px var(--gutter) 150px; }
  .cta__mark { width: 92px; height: 92px; margin-bottom: 46px; }
  .cta__mark img { border-radius: 22px; }
  .cta__markglow { inset: -46px; }
  .cta__actions { margin-top: 48px; }
}

/* =========================================================
   REVELAÇÃO NO SCROLL
   O estado inicial (invisível) só existe sob .js-revelar, classe que o
   próprio JS coloca no <html>. Sem JS nada disto se aplica e o conteúdo
   fica visível — o padrão do documento nunca é "escondido".
   ========================================================= */
.js-revelar [data-revelar] {
  opacity: 0;
  transform: translateY(20px);
  transition: opacity .6s ease-out, transform .6s ease-out;
}
.js-revelar [data-revelar].e-visivel {
  opacity: 1;
  transform: none;
}


/* ---------------------------------------------------------
   REVELAÇÃO DOS TÍTULOS
   Nos blocos com data-cena o BLOCO deixa de animar e quem entra em cena são as
   peças dentro dele. Sem isto o fade do bloco somaria ao do título e ele
   apareceria por duas curvas ao mesmo tempo — é o mesmo problema que o
   data-escalonar já resolvia nos cards.
   --------------------------------------------------------- */
.js-revelar [data-cena] {
  opacity: 1;
  transform: none;
  transition: none;
}

/* As peças são listadas por classe, não por posição. Um seletor estrutural
   pegaria também a <div> de layout do .section-head, e aí o fade dela somaria
   ao dos filhos. */
.js-revelar [data-cena] .secao-num,
.js-revelar [data-cena] .eyebrow,
.js-revelar [data-cena] .h2,
.js-revelar [data-cena] .cta__title,
.js-revelar [data-cena] .section-head__sub,
.js-revelar [data-cena] .section-head__text,
.js-revelar [data-cena] .demo__sub,
.js-revelar [data-cena] .cta__mark,
.js-revelar [data-cena] .cta__lead,
.js-revelar [data-cena] .cta__actions {
  opacity: 0;
  transform: translateY(14px);
  /* A curva sai rápido e desacelera longo — é ela que dá o ar de cinema, mais
     do que a distância percorrida, que segue curta de propósito.
     A opacidade termina antes do deslize: se as duas durassem o mesmo, o texto
     passaria a cauda inteira translúcido e pareceria desbotado. */
  transition:
    opacity .5s cubic-bezier(.16, 1, .3, 1),
    transform .85s cubic-bezier(.16, 1, .3, 1);
}

/* Escalonamento em três tempos, na ordem em que se lê o bloco. 70ms é curto o
   bastante para não virar "um, dois, três" e longo o bastante para o título
   parecer a chegada, não o começo. */
.js-revelar [data-cena] .secao-num { transition-delay: 0s; }
.js-revelar [data-cena] .eyebrow   { transition-delay: .07s; }
.js-revelar [data-cena] .section-head__sub,
.js-revelar [data-cena] .section-head__text,
.js-revelar [data-cena] .demo__sub,
.js-revelar [data-cena] .cta__mark,
.js-revelar [data-cena] .cta__lead,
.js-revelar [data-cena] .cta__actions { transition-delay: .2s; }

/* O TÍTULO: cortina horizontal, descobrindo da esquerda para a direita.
   Quem anima é o inset da DIREITA: em 100% a janela visível tem largura zero e
   nada aparece; ao encolher até -12% o texto vai sendo descoberto da borda
   esquerda em diante.
   Sem deslize: a cortina é o movimento inteiro. O fade acompanha curto, só
   para a borda que abre não entrar dura.
   3.5s. A curva é muito frontal: 87% do percurso acontece nos primeiros 30% do
   tempo, então o que se percebe como abertura é só essa fatia. Foi de 282ms em
   0.95s, para 505ms em 1.7s, 773ms em 2.6s, e agora 1041ms. O resto do tempo
   é o assentamento dos últimos 12%, que quase não se vê mas tira a dureza da
   parada.
   Se um dia a abertura precisar ser mais lenta ainda, alongar a duração rende
   cada vez menos: o ajuste passa a ser trocar a curva por uma menos frontal.
   As outras três bordas ficam fixas em -40px de propósito. Em 0 elas cortariam
   o text-shadow e as descidas do "g" e do "ç"; em porcentagem a folga
   encolheria junto com o elemento. E a direita segue em % nos DOIS estados
   porque é ela que anima — misturar unidade suja a interpolação. */
.js-revelar [data-cena] .h2,
.js-revelar [data-cena] .cta__title,
.js-revelar .concept__claim[data-revelar] {
  opacity: 0;
  /* zera o deslize herdado: a regra das pecas acima, e a generica de
     [data-revelar] no caso do claim, aplicam translateY. Esta regra tem a
     mesma especificidade ou mais, mas so vence nas propriedades que DECLARA —
     sem esta linha o titulo continuaria subindo. */
  transform: none;
  clip-path: inset(-40px 100% -40px -40px);
  transition:
    opacity .45s cubic-bezier(.16, 1, .3, 1) .14s,
    clip-path 3.5s cubic-bezier(.16, 1, .3, 1) .14s;
}

.js-revelar [data-cena].e-visivel .secao-num,
.js-revelar [data-cena].e-visivel .eyebrow,
.js-revelar [data-cena].e-visivel .h2,
.js-revelar [data-cena].e-visivel .cta__title,
.js-revelar [data-cena].e-visivel .section-head__sub,
.js-revelar [data-cena].e-visivel .section-head__text,
.js-revelar [data-cena].e-visivel .demo__sub,
.js-revelar [data-cena].e-visivel .cta__mark,
.js-revelar [data-cena].e-visivel .cta__lead,
.js-revelar [data-cena].e-visivel .cta__actions {
  opacity: 1;
  transform: none;
}
.js-revelar [data-cena].e-visivel .h2,
.js-revelar [data-cena].e-visivel .cta__title,
.js-revelar .concept__claim[data-revelar].e-visivel {
  /* opacity e transform precisam estar AQUI tambem por causa do claim: a regra
     que o esconde tem especificidade 0,3,0 e vence a generica de [data-revelar],
     que e 0,2,0. Sem isto a mascara abria e o texto ficava invisivel. */
  opacity: 1;
  transform: none;
  clip-path: inset(-40px -12% -40px -40px);
}


/* ---------------------------------------------------------
   FOTOS: entrada suave em vez de "pop"
   Os fundos de placeholder já existem e não precisaram ser criados: .frame tem
   --areia-media, e .gain e .concept são carvão. O que faltava era a foto não
   aparecer seca por cima deles.
   Tudo gated em .js-revelar: sem JS nenhuma destas regras se aplica e as fotos
   nascem visíveis, como antes.
   --------------------------------------------------------- */
.js-revelar .segments .frame > img,
.js-revelar .concept__img,
.js-revelar .gain__photo {
  opacity: 0;
  transition: opacity .25s ease-out;
}
.js-revelar .segments .frame > img.foto-pronta,
.js-revelar .concept__img.foto-pronta,
.js-revelar .gain__photo.foto-pronta {
  opacity: 1;
}

/* Sem transição quando a imagem chegou instantaneamente — cache, ou rede rápida
   o bastante para o load vir em menos de 120ms. Nesses casos o fade não suaviza
   nada: só adiciona espera depois que os pixels já estão prontos. Era o que
   fazia o desktop parecer lento, porque lá o download acaba antes do fade.
   A classe entra junto com .foto-pronta, no mesmo recálculo de estilo, então o
   navegador computa transition:none e opacity:1 de uma vez e não anima. */
.js-revelar .segments .frame > img.sem-fade,
.js-revelar .concept__img.sem-fade,
.js-revelar .gain__photo.sem-fade {
  transition: none;
}

/* Na seção da corrente quem recebe o fade é o CONTAINER, não as imagens.
   As três camadas de lá têm opacity escrita inline pelo crossfade a cada
   quadro; uma transição nelas brigaria com essa escrita e deixaria o efeito
   arrastado. O container não é tocado por JS nenhum. */

@media (prefers-reduced-motion: reduce) {
  .js-revelar .segments .frame > img,
  .js-revelar .concept__img,
  .js-revelar .gain__photo { opacity: 1; transition: none; }
}

/* ---------------------------------------------------------
   Cascata dos cards — só no desktop (>= 768px)
   Abaixo disso os grupos são carrossel horizontal: cascata em scroll
   lateral fica estranha, então lá vale o fade simples do grupo inteiro.
   --------------------------------------------------------- */
@media (min-width: 768px) {
  /* no desktop quem anima são os cards, não a caixa do grupo — senão os
     dois fades se somam e o conjunto pisca duas vezes */
  .js-revelar [data-escalonar] {
    opacity: 1;
    transform: none;
    transition: none;
  }

  .js-revelar [data-escalonar] > * {
    opacity: 0;
    transform: translateY(24px);
    transition: opacity .5s ease-out, transform .5s ease-out;
    transition-delay: var(--atraso, 0s);
  }
  .js-revelar [data-escalonar].e-visivel > * {
    opacity: 1;
    transform: none;
  }

  /* 0,12s de degrau entre um card e o próximo */
  .js-revelar [data-escalonar] > *:nth-child(1) { --atraso: 0s; }
  .js-revelar [data-escalonar] > *:nth-child(2) { --atraso: .12s; }
  .js-revelar [data-escalonar] > *:nth-child(3) { --atraso: .24s; }
  .js-revelar [data-escalonar] > *:nth-child(4) { --atraso: .36s; }
  .js-revelar [data-escalonar] > *:nth-child(5) { --atraso: .48s; }
  .js-revelar [data-escalonar] > *:nth-child(6) { --atraso: .6s; }
}

/* segunda trava, caso a preferência mude depois do carregamento */
@media (prefers-reduced-motion: reduce) {
  .js-revelar [data-revelar],
  .js-revelar [data-revelar].e-visivel,
  .js-revelar [data-escalonar] > *,
  .js-revelar [data-escalonar].e-visivel > *,
  /* as peças de data-cena precisam estar aqui: sem isto o clip-path deixaria
     os títulos recortados para fora e eles simplesmente não apareceriam */
  .js-revelar [data-cena] .secao-num,
  .js-revelar [data-cena] .eyebrow,
  .js-revelar [data-cena] .h2,
  .js-revelar [data-cena] .cta__title,
  .js-revelar [data-cena] .section-head__sub,
  .js-revelar [data-cena] .section-head__text,
  .js-revelar [data-cena] .demo__sub,
  .js-revelar [data-cena] .cta__mark,
  .js-revelar [data-cena] .cta__lead,
  .js-revelar [data-cena] .cta__actions,
  .js-revelar .concept__claim[data-revelar] {
    opacity: 1;
    transform: none;
    clip-path: none;
    transition: none;
    transition-delay: 0s;
  }
}

/* =========================================================
   CARROSSEL — só no celular (< 768px)
   Acima disso as grades voltam a ser exatamente o que eram.
   ========================================================= */
.dots { display: none; }

@media (max-width: 767.98px) {
  .carousel {
    display: flex;
    gap: 14px;
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scroll-snap-type: x mandatory;
    scroll-padding-left: var(--gutter);
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    /* sangra até a borda da tela para o próximo card espiar */
    margin-inline: calc(-1 * var(--gutter));
    padding-inline: var(--gutter);
    padding-bottom: 2px;
  }
  .carousel::-webkit-scrollbar { display: none; }

  .carousel > * {
    flex: 0 0 84vw;
    max-width: 380px;
    scroll-snap-align: start;
  }

  .dots {
    display: flex;
    justify-content: center;
    gap: 2px;
    margin-top: 22px;
  }
  .dots__dot {
    display: grid;
    place-items: center;
    width: 22px;
    height: 22px;
    padding: 0;
    border: 0;
    background: none;
    color: inherit;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
  }
  .dots__dot::before {
    content: "";
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: currentColor;
    opacity: 0.26;
    transition: opacity .2s ease, transform .2s ease;
  }
  .dots__dot.is-active::before {
    opacity: 0.9;
    transform: scale(1.3);
  }
}

/* =========================================================
   RODAPÉ
   ========================================================= */
.footer {
  background: var(--carvao);
  color: var(--areia);
  padding: 64px var(--gutter) 32px;
}
.footer__top {
  display: grid;
  gap: 40px;
  padding-bottom: 40px;
  border-bottom: 1px solid rgb(var(--areia-rgb) / 0.14);
}
.footer__brand img { height: 28px; width: auto; margin-bottom: 18px; }
.footer__brand p {
  font-size: 17px;
  line-height: 1.6;
  color: rgb(var(--areia-rgb) / 0.72);
  max-width: 34ch;
}
.footer__col { display: flex; flex-direction: column; gap: 12px; font-size: 16px; }

/* Redes ainda sem perfil. A regra global pinta todo <a> com o petróleo de ação,
   e sem href esses dois pareceriam clicáveis sem ser — promessa falsa. Aqui
   recebem o tom apagado do rótulo da coluna, que já lê como "não interativo",
   e o cursor de texto normal em vez do de link. */
.footer__embreve {
  color: rgb(var(--areia-rgb) / 0.48);
  cursor: default;
}
.footer__embreve:hover { color: rgb(var(--areia-rgb) / 0.48); }

.footer__label {
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: rgb(var(--areia-rgb) / 0.45);
  margin-bottom: 8px;
}
.footer__bottom {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding-top: 24px;
  font-size: 14px;
  color: rgb(var(--areia-rgb) / 0.42);
}

@media (min-width: 720px) {
  .footer__top { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 48px; }
  .footer__brand { grid-column: 1 / -1; }
  .footer__bottom { flex-direction: row; justify-content: space-between; align-items: center; }
}
@media (min-width: 1080px) {
  .footer { padding: 90px var(--gutter) 40px; }
  .footer__top {
    grid-template-columns: minmax(0, 1.4fr) repeat(2, minmax(0, 0.8fr));
    gap: 64px;
    padding-bottom: 64px;
  }
  .footer__brand { grid-column: auto; }
  .footer__brand img { height: 30px; margin-bottom: 22px; }
  .footer__bottom { padding-top: 28px; }
}
