/* ══════════════════════════════════════════════════════════════════════════════
   BRUNO ROSS — VIDEO EDITOR
   Sistema visual: gramática do MoneyClub, paleta desta página.

   O que veio de lá (medido no arquivo publicado, nunca estimado no olho):
   a escala de espaço, os raios, as quatro sombras, as superfícies em alfa de
   branco, a cápsula da barra do topo, o botão-bandeja, o grão da página e a
   gramática do movimento — 73px de deslize lateral, 10px de pulo por palavra.

   O que NÃO veio: a cor. O acento continua sendo o vermelho de sinal desta
   página, hex por hex. Lá o acento é dourado; aqui a mesma receita roda em
   vermelho, e é só isso que muda.
   ══════════════════════════════════════════════════════════════════════════════ */

/* ══ 1 · TOKENS ══════════════════════════════════════════════════════════════ */
:root{
  /* Superfícies. Nenhuma é preto puro — preto puro fecha a imagem e mata a
     profundidade que o grão vai criar em cima. */
  --canvas:#0A0A0B;
  --surface:#131316;
  --surface-2:#1C1C20;

  --ink:#F5F5F7;
  --ink-2:#A1A1A6;
  --ink-3:#8A8A90;
  --hairline:rgba(255,255,255,.10);
  --hairline-2:rgba(255,255,255,.20);
  --overlay:rgba(0,0,0,.66);

  /* Acento — vermelho de sinal. Branco sobre ele dá só 3.3:1, então todo
     preenchimento em acento carrega rótulo quase preto. */
  --accent:#FF4B32;
  --accent-hover:#FF5A42;
  --accent-light:#FF8A73;
  /* O núcleo escuro da bandeja do botão. É o próprio acento rebaixado, do mesmo
     jeito que o MoneyClub rebaixa o dourado para rgb(90,38,10). */
  --accent-deep:#5E1810;
  --accent-rgb:255,75,50;
  --on-accent:#0A0A0B;

  --font:"Schibsted Grotesk",ui-sans-serif,system-ui,-apple-system,"Segoe UI",sans-serif;
  --mono:"IBM Plex Mono",ui-monospace,"SF Mono",Menlo,monospace;

  --ease-out-expo:cubic-bezier(.16,1,.30,1);
  --ease-in-out:cubic-bezier(.65,0,.35,1);
  --ease-smooth:cubic-bezier(.40,0,.20,1);
  --dur-entrance:800ms;
  --dur-sat:400ms;

  /* ESPAÇO — a escala do MoneyClub. Três degraus, e eles NÃO encolhem no
     celular na mesma proporção que o tipo. Lá o vão entre blocos mede 26px a
     430px e 25px a 1440px: o que encolhe é a letra, não o respiro. Ignorar isso
     é o erro que transforma celular em bloco único de texto. */
  --gap-act:clamp(104px,13vh,164px);   /* entre atos de peso diferente */
  --gap-sec:clamp(88px,11vh,146px);    /* entre atos de uma mesma seção */
  --gap-band:clamp(56px,7vh,72px);     /* faixa compacta */
  --gap-stack:clamp(40px,5vw,64px);    /* pilha interna */
  --gap-card:24px;

  /* RAIOS — os do MoneyClub: 12 cartão, 20 moldura do botão, 22 painel,
     208 cápsula. */
  --r-card:12px;
  --r-btn:20px;
  --r-panel:22px;
  --r-pill:37px;
  --r-capsule:208px;

  --max:1240px;
  --gutter:24px;
  --nav-h:54px;

  /* AS QUATRO SOMBRAS. Dois filetes internos e duas quedas — é a receita que
     faz um retângulo virar objeto em vez de área pintada. */
  --sh-card:
    inset 0 1px 2.8px rgba(255,255,255,.25),
    inset 0 -1px 2.4px rgba(0,0,0,.25),
    0 9px 17.3px rgba(0,0,0,.25),
    0 4px 11.6px rgba(0,0,0,.25);
  --sh-panel:
    -8px 27px 44.5px rgba(0,0,0,.78),
    inset 0 1px 2.8px rgba(255,255,255,.25),
    inset 0 -1px 2.4px rgba(0,0,0,.25);
  --sh-glass:0 37px 78.9px #000;
  --sh-seal:inset 0 0 3.5px rgba(var(--accent-rgb),.25);
}
@media (min-width:600px){ :root{ --nav-h:60px } }
@media (min-width:1024px){ :root{ --gutter:40px; --nav-h:64px } }

/* ══ 2 · BASE ════════════════════════════════════════════════════════════════ */
*,*::before,*::after{ box-sizing:border-box }
html{ -webkit-text-size-adjust:100%; scroll-behavior:smooth; background:var(--canvas); overflow-x:clip }
body{
  margin:0;
  overflow-x:clip;
  background:var(--canvas);
  color:var(--ink);
  font-family:var(--font);
  font-size:1.0625rem;
  line-height:1.55;
  -webkit-font-smoothing:antialiased;
  -moz-osx-font-smoothing:grayscale;
  text-wrap:pretty;
}
h1,h2,h3,h4,p,figure,ul,ol,dl,dd{ margin:0; padding:0 }
ul,ol{ list-style:none }
img{ display:block; max-width:100%; height:auto }
button{ font:inherit; color:inherit; background:none; border:0; cursor:pointer }
a{ color:inherit; text-decoration:none }
:focus-visible{ outline:2px solid var(--accent); outline-offset:3px; border-radius:2px }
.num,.step__num,.card__dur,.stat__n{ font-variant-numeric:tabular-nums }
::selection{ background:rgba(255,255,255,.20); color:var(--ink) }

.skip{ position:absolute; left:-9999px; width:1px; height:1px; overflow:hidden }
.skip:focus{
  left:var(--gutter); top:12px; z-index:300;
  width:auto; height:auto; overflow:visible;
  padding:10px 18px; border-radius:999px;
  background:var(--ink); color:var(--canvas);
  font-size:.9375rem; font-weight:600;
}

.wrap{ width:100%; max-width:var(--max); margin-inline:auto; padding-inline:var(--gutter) }
.section{ padding-block:var(--gap-act); scroll-margin-top:calc(var(--nav-h) + 24px) }
.section--band{ background:var(--surface) }
.section--tight{ padding-block:var(--gap-sec) }

/* ══ 3 · O GRÃO DA PÁGINA ════════════════════════════════════════════════════
   Ruído fixo cobrindo a viewport inteira, na frente de tudo, a 5%.
   É a peça mais barata do MoneyClub e a que mais muda a percepção: sem ela o
   preto lê como área chapada de CSS; com ela lê como superfície fotografada.
   O ruído é feTurbulence embutido — zero requisição, zero arquivo pra perder. */
.grain{
  position:fixed; inset:0; z-index:90;
  pointer-events:none;
  opacity:.05;
  /* Promovido a camada própria. Um overlay fixo de tela cheia, na frente de
     tudo, obriga o compositor a repintar a viewport inteira a cada quadro de
     rolagem. Com `translateZ(0)` ele é desenhado UMA vez e depois só
     reaproveitado — o custo cai de "a cada quadro" para "uma vez na vida". */
  transform:translateZ(0);
  backface-visibility:hidden;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='256' height='256'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.82' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='256' height='256' filter='url(%23n)'/%3E%3C/svg%3E");
  background-size:256px 256px;
}

/* ══ 4 · TIPOGRAFIA ══════════════════════════════════════════════════════════ */
.eyebrow{
  font-family:var(--mono);
  font-size:.75rem; font-weight:500; line-height:1.2;
  letter-spacing:.18em; text-transform:uppercase;
  color:var(--ink-2);
}
.h-section{
  font-size:clamp(2.25rem,5vw,4rem);
  line-height:1.02; letter-spacing:-.038em; font-weight:600;
  text-wrap:balance;
}
.lede{
  margin-top:clamp(18px,2.2vw,26px);
  max-width:52ch;
  font-size:clamp(1.0625rem,1.3vw,1.1875rem);
  color:var(--ink-2);
}
/* O TIQUE TIPOGRÁFICO DO MONEYCLUB. Negrito no meio do corpo com tracking
   NEGATIVO: o negrito fecha em vez de abrir. É o detalhe mais reconhecível
   da página deles e custa uma linha. */
strong,b,.lede strong{ font-weight:700; letter-spacing:-.04em; color:var(--ink) }

/* Texto em degradê — só para uma palavra por seção, no máximo. Usado em duas
   ele deixa de ser ênfase e vira decoração. */
.grad{
  background:linear-gradient(270deg,var(--accent-light),#FDFDFD);
  -webkit-background-clip:text; background-clip:text;
  -webkit-text-fill-color:transparent; color:transparent;
}

/* ══ 5 · O SELO ══════════════════════════════════════════════════════════════
   Cápsula com lavagem de acento, fio e filete interno. Tracking de 0.2em —
   é o que faz três palavras lerem como crachá e não como subtítulo. */
.seal{
  display:inline-flex; align-items:center; gap:9px;
  max-width:100%;
  padding:9px 18px;
  border-radius:var(--r-capsule);
  background:rgba(var(--accent-rgb),.10);
  border:1px solid rgba(var(--accent-rgb),.34);
  box-shadow:var(--sh-seal);
  color:var(--accent-light);
  font-family:var(--mono);
  font-size:.6875rem; font-weight:500; line-height:1.3;
  letter-spacing:.16em; text-transform:uppercase;
  text-align:center; text-wrap:balance;
}
/* A 320px, 0.2em de tracking em 11px estoura a cápsula para fora da coluna.
   O tracking é a primeira coisa que cede — antes do corpo, antes do recuo. */
@media (max-width:419.98px){ .seal{ padding:8px 14px; font-size:.625rem; letter-spacing:.1em; gap:8px; line-height:1.5 } }
@media (max-width:359.98px){ .seal{ padding:7px 11px; letter-spacing:.07em; gap:7px } }
@media (min-width:700px){ .seal{ padding:10px 22px; font-size:.75rem; letter-spacing:.2em; white-space:nowrap } }
.seal__dot{
  flex:none; width:7px; height:7px; border-radius:50%;
  background:var(--accent);
  box-shadow:0 0 0 0 rgba(var(--accent-rgb),.7);
}
/* A luz de REC. Duas piscadas por ciclo, lentas — um ponto que pulsa rápido
   vira alarme e puxa o olho para longe do título. */
@media (prefers-reduced-motion:no-preference){
  .seal__dot{ animation:rec 2.6s var(--ease-in-out) infinite }
}
@keyframes rec{
  0%,72%,100%{ box-shadow:0 0 0 0 rgba(var(--accent-rgb),.55) }
  36%        { box-shadow:0 0 0 7px rgba(var(--accent-rgb),0) }
}

/* ══ 6 · O BOTÃO ═════════════════════════════════════════════════════════════
   Não é um botão: é uma BANDEJA DENTRO DE UMA MOLDURA DE VIDRO.

   Moldura: padding 8px 26px 8px 8px — assimétrico de propósito, o recuo maior
   à direita é o que abre o vão onde o ícone mora, fora da bandeja.

   Bandeja: radial com o foco em 51.4% 6.1%, quase no topo e levemente à
   direita. É esse deslocamento que dá a impressão de luz vindo de cima em vez
   de gradiente centrado, que lê como botão de framework.

   Mais os dois brilhos em color-dodge nos cantos de cima, que se esticam no
   hover — a animação do botão é essa, não um scale. */
.btn{
  position:relative;
  display:inline-flex; align-items:center; gap:18px;
  padding:8px 24px 8px 8px;
  border-radius:var(--r-btn);
  background:rgba(255,255,255,.10);
  box-shadow:
    0 0 42px rgba(var(--accent-rgb),0),
    inset 0 2px 29px rgba(207,207,207,.12),
    0 0 153px rgba(var(--accent-rgb),0);
  overflow:hidden;
  isolation:isolate;
  transition:box-shadow 420ms var(--ease-smooth);
  will-change:transform;
}
.btn:hover,.btn:focus-visible{
  box-shadow:
    0 0 34px rgba(var(--accent-rgb),.22),
    inset 0 2px 29px rgba(207,207,207,.16),
    0 0 110px rgba(var(--accent-rgb),.10);
}
.btn__tray{
  position:relative; z-index:1;
  display:block;
  padding:15px 20px;
  border-radius:var(--r-card);
  /* BRANCO SOBRE O VERMELHO — e o vermelho teve que descer para isso.

     Branco sobre #FF4B32 dá 3.3:1. Reprova em AA para corpo de 16px, e não é
     detalhe de conformidade: é um rótulo que some para quem lê no sol ou tem
     baixa visão, no único elemento da página que precisa ser clicado.

     A solução não foi desistir do branco, foi aprofundar o miolo. O foco do
     radial fica em 51.4% 6.1% — quase no topo — então o texto, que é centrado,
     assenta na zona escura. Com a parada intermediária em #B62D19 aos 58%, o
     branco encosta em 5:1 onde as letras realmente estão, e a borda continua
     com o vermelho vivo de sinal. */
  background:radial-gradient(72% 118% at 51.4% 6.1%,
    var(--accent-deep) 0%, #B62D19 58%, var(--accent) 100%);
  /* As camadas internas. O MoneyClub usa 26; estas 13 reproduzem o mesmo
     efeito: brilho subindo do rodapé, filete branco no topo, rebordo claro nos
     dois lados e uma linha branca sólida na base. */
  box-shadow:
    inset 0 -.74px .74px rgba(255,255,255,.23),
    inset 0 -3px 3px rgba(255,255,255,.14),
    inset 0 -8px 8px rgba(255,255,255,.08),
    inset 0 -16px 14px rgba(255,255,255,.04),
    inset 0 -38px 30px rgba(255,255,255,.015),
    inset 0 1px 1px rgba(255,255,255,.69),
    inset 0 3px 4px rgba(255,255,255,.25),
    inset 2px 0 3px rgba(255,255,255,.16),
    inset -2px 0 3px rgba(255,255,255,.16),
    inset 0 -12px 22px rgba(var(--accent-rgb),.55),
    inset 0 -3px 3.8px #fff,
    0 3px 10px rgba(0,0,0,.45);
  color:#fff;
  font-size:1rem; font-weight:700; letter-spacing:-.01em; line-height:1.1;
  text-shadow:0 1px 2px rgba(60,12,6,.55),0 3px 11px rgba(60,12,6,.45);
  transition:transform 420ms var(--ease-smooth);
}
.btn:hover .btn__tray{ transform:translateY(-1px) }
/* Os dois brilhos, fora da caixa, nos cantos de cima. color-dodge é o que faz
   eles queimarem a borda em vez de clarear em cima dela. */
/* OS DOIS BRILHOS NASCEM APAGADOS.

   No MoneyClub o halo de acento do botão é `0 0 42px <acento a ALFA ZERO>` em
   repouso — ele existe na regra e não existe na tela até o hover. Eu tinha
   deixado em 0.5, e o resultado foi o que aparece em qualquer captura de
   celular: duas manchas vermelhas borradas em volta do botão, que o `color-dodge`
   ainda queima e espalha.

   Apagados, o botão volta a ser um objeto de borda definida — e o hover passa a
   ter para onde ir, que é o ponto inteiro do gesto. */
.btn::before,.btn::after{
  content:""; position:absolute; z-index:0;
  top:-38px; width:96px; height:70px;
  border-radius:50%;
  background:radial-gradient(50% 50%,rgba(var(--accent-rgb),.6),transparent 70%);
  /* O modo de mesclagem só liga no hover.

     `mix-blend-mode` força o navegador a ler o fundo por baixo do elemento para
     poder misturar — e ele faz isso mesmo com o elemento em `opacity: 0`, que
     é invisível mas não é inexistente. Dois desses em cada botão da página,
     custando leitura de fundo o tempo todo, por um efeito que só aparece no
     hover.

     Em repouso: `normal` e opacidade zero, custo zero. */
  mix-blend-mode:normal;
  opacity:0;
  transition:transform 620ms var(--ease-out-expo),opacity 480ms var(--ease-smooth);
  pointer-events:none;
  will-change:transform,opacity;
}
.btn:hover::before,.btn:hover::after,
.btn:focus-visible::before,.btn:focus-visible::after{ mix-blend-mode:color-dodge }
.btn::before{ left:-30px }
.btn::after{ right:-30px }
.btn:hover::before,.btn:focus-visible::before{ transform:translate(16px,10px) scale(1.3); opacity:.7 }
.btn:hover::after,.btn:focus-visible::after{ transform:translate(-16px,10px) scale(1.3); opacity:.7 }

.btn__icon{
  position:relative; z-index:1;
  flex:none; width:20px; height:20px;
  color:var(--accent-light);
  filter:drop-shadow(0 5px 8px rgba(var(--accent-rgb),.39)) drop-shadow(0 2px 2px rgba(0,0,0,.7));
  transition:transform 420ms var(--ease-out-expo);
}
.btn:hover .btn__icon{ transform:translate(3px,-3px) }

/* Variante compacta — barra do topo e rodapé. A bandeja perde o recuo próprio,
   exatamente como na variante compacta de lá. */
/* O compacto começa pequeno de verdade e cresce, não o contrário. A 390px o
   rótulo "Start a project" na medida anterior ocupava 58% da barra inteira. */
.btn--sm{ gap:8px; padding:5px 12px 5px 5px; border-radius:15px }
.btn--sm .btn__tray{ padding:9px 13px; font-size:.8125rem; letter-spacing:-.012em; border-radius:10px; white-space:nowrap }
.btn--sm .btn__icon{ width:15px; height:15px }
@media (max-width:419.98px){
  .btn--sm{ gap:0; padding:5px }
  .btn--sm .btn__tray{ padding:9px 12px; font-size:.78125rem }
  .btn--sm .btn__icon{ display:none }
  .wordmark{ font-size:.875rem }
}
@media (min-width:600px){
  .btn--sm{ gap:13px; padding:6px 18px 6px 6px; border-radius:16px }
  .btn--sm .btn__tray{ padding:10px 15px; font-size:.875rem }
  .btn--sm .btn__icon{ width:16px; height:16px }
}
/* No hero, o botão grande também nasce menor: 15px de rótulo com 20px de recuo
   deixa "See the work" com 210px, e a 320px isso é dois terços da tela. */
@media (max-width:479.98px){
  .btn{ gap:12px; padding:6px 16px 6px 6px; border-radius:16px }
  .btn__tray{ padding:13px 17px; font-size:.9375rem; border-radius:11px }
  .btn__icon{ width:18px; height:18px }
}

/* Link de texto — a alternativa discreta ao lado do botão. */
.tlink{
  position:relative;
  display:inline-block;
  font-size:1rem; font-weight:500; padding-block:5px;
  color:var(--ink-2);
  transition:color 240ms var(--ease-smooth);
}
.tlink::after{
  content:""; position:absolute; left:0; right:0; bottom:0; height:1px;
  background:var(--accent);
  transform:scaleX(0); transform-origin:100% 50%;
  transition:transform 480ms var(--ease-out-expo);
}
.tlink:hover,.tlink:focus-visible{ color:var(--ink) }
.tlink:hover::after,.tlink:focus-visible::after{ transform:scaleX(1); transform-origin:0 50% }

/* ══ 7 · TRILHO E BARRA DO TOPO ══════════════════════════════════════════════
   A barra é CÁPSULA FLUTUANTE, não faixa de ponta a ponta. É a decisão de
   layout mais visível que veio do MoneyClub: uma barra de largura total divide
   a tela em duas e o conteúdo passa a nascer "debaixo" de alguma coisa; uma
   cápsula flutua sobre a página e a página continua inteira. */
.rail{ position:fixed; inset:0 0 auto 0; height:2px; z-index:120; background:rgba(255,255,255,.07) }
.rail__fill{
  position:absolute; inset:0;
  background:linear-gradient(90deg,var(--accent),var(--accent-light));
  transform:scaleX(0); transform-origin:0 50%;
  will-change:transform;
  backface-visibility:hidden;
}
.rail__tick{ position:absolute; top:0; width:1px; height:100%; background:var(--canvas); opacity:.9 }

/* No celular a cápsula encosta mais no topo e no gutter: 14px de folga numa
   tela de 390 come 7% da largura útil sem devolver nada. */
.nav{
  position:fixed; inset:8px 0 auto 0; z-index:100;
  padding-inline:14px;
  pointer-events:none;
}
@media (min-width:600px){ .nav{ inset:14px 0 auto 0; padding-inline:var(--gutter) } }
.nav__in{
  pointer-events:auto;
  width:100%; max-width:var(--max); margin-inline:auto;
  height:var(--nav-h);
  display:flex; align-items:center; justify-content:space-between; gap:20px;
  padding:0 6px 0 14px;
  border-radius:var(--r-capsule);
  background:transparent;
  border:1px solid transparent;
  transition:background-color 420ms var(--ease-smooth),
             border-color 420ms var(--ease-smooth),
             box-shadow 420ms var(--ease-smooth),
             max-width 520ms var(--ease-out-expo);
}
/* Escondida: sobe além da própria altura mais a folga do topo, senão a sombra
   fica pendurada na borda. O `pointer-events:none` do pai já impede clique
   fantasma na faixa vazia. */
.nav{ transition:transform 520ms var(--ease-out-expo) }
.nav.is-hidden{ transform:translateY(calc(-100% - 24px)) }
.nav.is-stuck .nav__in{
  max-width:min(var(--max),980px);
  background:rgba(10,10,11,.72);
  /* `backdrop-filter` é a propriedade mais cara do CSS: ela obriga o navegador
     a ler de volta tudo que está atrás do elemento, filtrar e recompor. Numa
     barra fixa, isso acontece o tempo todo.

     `saturate` empilhado no `blur` dobra a cadeia de filtro e não se vê a
     diferença sobre preto. Saiu. E 14px de desfoque sobre fundo escuro é
     visualmente indistinguível de 20px, custando bem menos. */
  -webkit-backdrop-filter:blur(14px);
  backdrop-filter:blur(14px);
  border-color:var(--hairline);
  box-shadow:0 18px 44px rgba(0,0,0,.45);
}
/* A cápsula do topo já tem vidro, fio e sombra. No celular ela nasce SEM nada
   disso — transparente sobre a foto — e só ganha o vidro depois de rolar. Uma
   caixa flutuando em cima de outra caixa, as duas com borda, é o "box in the
   box" que faz o topo parecer apertado antes mesmo de alguém ler. */
.nav__in{ padding-block:0 }
@media (min-width:600px){ .nav__in{ padding:0 10px 0 20px } }
.wordmark{ display:inline-flex; align-items:center; gap:8px; font-size:.9375rem; font-weight:700; letter-spacing:-.028em; white-space:nowrap }
@media (min-width:600px){ .wordmark{ gap:9px; font-size:1.0625rem } }
.wordmark i{ width:7px; height:7px; border-radius:50%; background:var(--accent); flex:none }
.nav__links{ display:none; gap:30px; align-items:center }
.nav__links a{
  position:relative;
  font-size:.9375rem; font-weight:500;
  color:var(--ink-2);
  padding-block:6px;
  transition:color 240ms var(--ease-smooth);
}
.nav__links a::after{
  content:""; position:absolute; left:0; right:0; bottom:0; height:1px;
  background:var(--accent);
  transform:scaleX(0); transform-origin:100% 50%;
  transition:transform 420ms var(--ease-out-expo);
}
.nav__links a:hover{ color:var(--ink) }
.nav__links a:hover::after{ transform:scaleX(1); transform-origin:0 50% }
.nav__links a[aria-current="true"]{ color:var(--ink) }
.nav__links a[aria-current="true"]::after{ transform:scaleX(1); background:var(--hairline-2) }
@media (min-width:760px){ .nav__links{ display:flex } }

/* ══ 8 · HERO ════════════════════════════════════════════════════════════════ */
.hero{ position:relative; scroll-margin-top:0 }
.media[hidden]{ display:none }
.media{
  position:relative; width:100%;
  height:min(74vh,660px);
  background:var(--canvas);
  overflow:hidden;
}
@media (min-width:700px){ .media{ height:min(84vh,920px) } }

/* ══ AS REGRAS BASE DA FOTO — celular primeiro ═════════════════════════════
   (Elas tinham sumido numa substituição anterior minha, e era exatamente por
   isso que o texto do celular nascia em cima do carro: não havia véu nenhum.)
   ═══════════════════════════════════════════════════════════════════════════ */
.media__in{ display:block; width:100%; height:100% }
.media__in picture{ display:block; width:100%; height:100% }

.media__img{
  width:100%; height:100%;
  object-fit:cover;
  /* A foto de celular é retrato e o rosto está no terço superior. Ancorando em
     36% na vertical, o corte come sempre o pé — nunca a cabeça. */
  object-position:50% 36%;
  filter:grayscale(.16) contrast(1.04);
  /* A ESCALA É DO CSS, A PARALAXE É DO GSAP. Separados, nenhum dos dois desfaz
     o outro — que era o defeito de quando os dois escreviam em `transform`. */
  transform:scale(var(--zoom,1.06)) translateZ(0);
  transform-origin:50% 42%;
  will-change:transform;
  backface-visibility:hidden;
}

/* O VÉU TERMINA ONDE O TEXTO COMEÇA. Nem antes, nem depois.

   O erro anterior não era o véu faltar: era ele fechar CEDO DEMAIS. Fechando
   aos 54% e o texto começando aos 80%, sobravam ~170px de preto morto entre o
   fim da fotografia e o selo — uma faixa vazia que não é respiro, é buraco.
   Respiro tem medida; buraco é o que sobra quando duas peças não conversam.

   Os dois números aqui são um PAR e mudam juntos:

     véu fecha em .......... 76% da altura da foto
     texto sobe .............. 22% da altura da foto  (o `margin-top` negativo)

   Somando, o texto nasce a 78% — dois pontos abaixo de onde o preto ficou
   sólido. A fotografia vive mais um terço a mais de tela, e ainda assim
   nenhuma letra encosta em pixel de imagem.

   Se um dia mexer num, mexa no outro. É a única dependência do arquivo que o
   CSS não consegue expressar sozinho. */
.media__scrim{
  position:absolute; inset:0; pointer-events:none;
  background:
    /* A faixa do topo, onde a cápsula da barra flutua sobre a neve. */
    linear-gradient(to bottom,
      rgba(10,10,11,.88) 0%, rgba(10,10,11,.62) 7%,
      rgba(10,10,11,.18) 15%, transparent 24%),
    /* A descida até o preto, terminando na linha do texto. */
    linear-gradient(to bottom,
      transparent 30%, rgba(10,10,11,.30) 46%,
      rgba(10,10,11,.72) 60%, rgba(10,10,11,.96) 70%,
      var(--canvas) 76%);
}
/* Um sopro de acento na base. Sem `mix-blend-mode`: em `screen` ele clareava
   a neve junto e virava mancha. Pintado normal, a 9%, tinge só o preto. */
.media__wash{
  position:absolute; inset:auto 0 0 0; height:34%;
  pointer-events:none;
  background:radial-gradient(58% 100% at 50% 100%,rgba(var(--accent-rgb),.10),transparent 72%);
}


/* 22% da altura da foto — o par do 76% do véu acima. Em px isso é ~145 numa
   tela de 932 e ~120 numa de 780; a proporção é o que mantém a relação com o
   degradê em qualquer altura de tela, que um valor fixo não faria. */
.hero__type{ position:relative; z-index:1; margin-top:calc(-1 * min(74vh,660px) * .22) }
.hero__h1{
  margin-top:clamp(26px,3vw,40px);
  font-size:clamp(3.25rem,9.4vw,9.5rem);
  line-height:.95; letter-spacing:-.045em; font-weight:600;
  max-width:16ch; text-wrap:balance;
  margin-left:-.045em;
}
.hero__sub{
  margin-top:clamp(24px,2.8vw,36px);
  max-width:48ch;
  font-size:clamp(1.0625rem,1.4vw,1.3125rem);
  line-height:1.5; color:var(--ink-2);
}
/* O botão precisa de chão embaixo dele.

   A faixa de ferramentas encostava a 0px do CTA, e o resultado é o que qualquer
   captura de celular mostrava: o botão parecia apoiado numa prateleira. Dois
   objetos de peso diferente colados leem como um objeto só — e o mais forte
   dos dois, que é o botão, perde.

   88px é a escala de "entre atos" reduzida: a faixa ainda pertence ao hero,
   então não leva os 164px que separam seções de verdade. */
.hero__cta{
  margin-top:clamp(32px,3.8vw,52px);
  display:flex; align-items:center; gap:clamp(20px,3vw,36px); flex-wrap:wrap;
}
.hero{ padding-bottom:clamp(72px,9vh,112px) }
/* Máscara palavra a palavra. O padding preserva as descidas — sem ele o "g" de
   "graph" é decapitado pelo overflow:hidden. */
.wm{ display:inline-block; overflow:hidden; vertical-align:bottom; padding-bottom:.16em; margin-bottom:-.16em }
.wi{ display:inline-block }

/* ⚠ ESTE BLOCO PRECISA FICAR NO FIM DA SEÇÃO DO HERO.

   Ele estava ANTES das regras base — e media query não acrescenta
   especificidade nenhuma. `.hero__h1{max-width:16ch}` declarado depois vencia
   o `min(50%,590px)` daqui, e a manchete voltava a atravessar a tela por mais
   que eu ajustasse o número.

   Correção de largura vem DEPOIS do que ela corrige. Sempre. É a mesma regra
   que vale para o resto do arquivo e a que mais custa esquecer, porque o
   sintoma é "o CSS não fez efeito" e a causa é ordem de linha.
   ═══════════════════════════════════════════════════════════════════════════ */
/* ══ O HERO DE DESKTOP — outra foto, outro layout ═══════════════════════════

   Aqui mudou a peça, não o tamanho da peça. A foto de PC é paisagem, com o
   Bruno à direita e 55% de neve e árvore à esquerda. Esse vazio não é sobra:
   é o lugar da manchete. Foi por isso que a foto foi tirada assim.

   Então acima de 1000px o hero deixa de ser "foto em cima, texto puxado por
   baixo" e vira uma cena só: a fotografia ocupa a dobra inteira e o texto mora
   dentro dela, à esquerda, sobre a neve escurecida.

   O véu deixa de ser vertical e passa a ser DIAGONAL, da esquerda para a
   direita. A neve tem luminância alta — branco puro sobre ela dá menos de 2:1
   e some. O degradê carrega peso de verdade nos primeiros 45% e some
   completamente aos 72%, para nunca escurecer o rosto.
   ═══════════════════════════════════════════════════════════════════════════ */
@media (min-width:1000px){
  .hero{
    position:relative;
    display:block;
    min-height:min(94vh,940px);
    padding:0;
  }
  .media{ position:absolute; inset:0; height:100% }

  .media__in{ position:static; width:100%; height:100% }
  .media__in::after{ display:none }
  .media__img{
    width:100%; height:100%;
    object-fit:cover;
    /* SEM ZOOM. O zoom com `transform-origin` brigava com o `object-position`:
       um recorta o quadro, o outro escala o resultado, e as duas âncoras se
       compunham num ponto que nenhum dos dois pediu — o título caindo em cima
       do peito dele.

       `cover` sozinho já recorta o suficiente: a dobra é ~1.53 e a foto é 1.79,
       então sobram uns 250px de largura para escolher. Ancorando em 78%, esse
       corte sai todo da ESQUERDA — o Bruno assenta no terço direito e a neve
       fica exatamente onde a manchete mora. Uma propriedade, um resultado
       previsível. */
    --zoom:1;
    /* AS DUAS ÂNCORAS DO RECORTE — e elas andam ao contrário do que parece.

       `object-position` diz que PEDAÇO DA FOTO fica visível, não para onde o
       assunto se move. Os dois eixos são invertidos em relação à intuição:

         Y menor  → mostra mais do TOPO da foto → a imagem desce na tela
         X menor  → mostra mais da ESQUERDA     → o assunto vai para a direita

       14% na vertical desce a imagem quase até o limite do que existe acima da
       cabeça; 62% na horizontal empurra você para o terço direito e devolve
       mais neve para o lado da manchete, que é o fundo que ela precisa. */
    object-position:28% 14%;
    transform-origin:50% 50%;
    filter:grayscale(.10) contrast(1.03);
  }
  .media__scrim{
    background:
      linear-gradient(104deg,
        rgba(10,10,11,.95) 0%,  rgba(10,10,11,.90) 26%,
        rgba(10,10,11,.62) 44%, rgba(10,10,11,.18) 60%,
        rgba(0,0,0,0) 72%),
      linear-gradient(to bottom,
        rgba(10,10,11,.72) 0%, rgba(10,10,11,.10) 14%,
        rgba(0,0,0,0) 30%, rgba(0,0,0,0) 62%,
        rgba(10,10,11,.72) 86%, var(--canvas) 100%);
  }
  .media__wash{ height:38%; background:radial-gradient(46% 100% at 26% 100%,rgba(var(--accent-rgb),.10),transparent 70%) }

  /* O texto vive DENTRO da foto, e o bloco todo é centrado na vertical. */
  .hero__type{
    position:relative; z-index:1;
    margin-top:0;
    min-height:min(94vh,940px);
    display:flex; flex-direction:column; justify-content:center;
  }
  /* A COLUNA DE TEXTO É UMA COLUNA, não a largura da tela.

     `max-width` em `ch` não segura nada aqui: 13ch de uma fonte de 104px dá
     676px, e o `52%` que eu tinha posto brigava com ele por especificidade
     igual. O resultado foi a manchete atravessando o peito dele — exatamente o
     que o layout inteiro existia para evitar.

     Agora a largura é declarada UMA vez, no contêiner, e tudo dentro herda. Sem
     disputa, sem `ch`, sem porcentagem que depende da tela. */
  .hero__type > *{ max-width:min(50%,590px) }

  /* A CÁPSULA VOLTA A TER A LARGURA DO TEXTO DELA.

     `.seal` é `inline-flex`, mas como FILHA de um flex em coluna ela vira item
     de flex — e item de flex estica no eixo transversal por padrão. Resultado:
     uma cápsula de 590px em volta de cinco palavras, que deixa de ler como
     crachá e vira barra.

     `align-self: start` devolve a largura do conteúdo. É o comportamento que o
     `inline-flex` prometia e que o contexto de flex tirou — a pegadinha mais
     comum de flexbox, e a que mais parece bug de CSS quando acontece. */
  .seal{ align-self:start }
  .hero__h1{ font-size:clamp(3.25rem,4.6vw,4.75rem); max-width:min(50%,590px) }
  .hero__sub{ max-width:min(46%,470px) }

  /* E o bloco desce: com o conteúdo centrado numa dobra de 94vh, o selo subia
     até a altura da cápsula do topo e os dois se sobrepunham. O recuo de topo
     maior que o de base empurra a pilha para baixo da barra e mantém a
     sensação de centro óptico, que fica um pouco acima do centro real. */
  .hero__type{ padding-block:clamp(150px,19vh,240px) clamp(90px,11vh,140px) }
}

/* ══ 9 · MARQUEE ═════════════════════════════════════════════════════════════
   Carrossel contínuo com máscara nas duas pontas — a peça sai de cena em vez
   de bater na borda. Aqui ele carrega o que é verdade hoje: as ferramentas.
   Quando houver cliente, troca por logo e o componente não muda. */
.marq{
  position:relative;
  padding-block:clamp(30px,3.8vh,44px);
  border-block:1px solid var(--hairline);
  background:var(--surface);
  overflow:hidden;
  contain:paint;
}
/* AS PONTAS SÃO PINTADAS, NÃO RECORTADAS.

   `mask-image` obriga o navegador a recompor a máscara a cada quadro enquanto
   a pista se move por baixo dela — e a pista se move sempre. Sobre um fundo
   sólido, dois degradês desenhados POR CIMA produzem o mesmo desaparecimento e
   custam uma pintura estática que nunca mais muda.

   Só vale porque o fundo aqui é chapado. Sobre foto, a máscara seria a única
   saída correta. */
.marq::before,.marq::after{
  content:""; position:absolute; top:0; bottom:0; width:14%;
  z-index:2; pointer-events:none;
}
.marq::before{ left:0;  background:linear-gradient(90deg,var(--surface),rgba(19,19,22,0)) }
.marq::after { right:0; background:linear-gradient(270deg,var(--surface),rgba(19,19,22,0)) }
.marq__track{ display:flex; align-items:center; gap:0; width:max-content; will-change:transform; backface-visibility:hidden }
.marq__set{ display:flex; align-items:center; gap:clamp(46px,6vw,84px); padding-right:clamp(46px,6vw,84px) }
/* TRÊS MARCAS, E SÓ. A tipografia mudou junto.

   Com sete itens a faixa era textura — versalete de monoespaçada com tracking
   largo, feita para ler como faixa de dado. Com três ela é uma AFIRMAÇÃO, e
   nome de ferramenta é nome próprio: vai na fonte de texto da página, em caixa
   alta e baixa, com o peso que um nome merece.

   O tracking cai de 0.13em para quase zero pelo mesmo motivo. Tracking largo
   serve para versalete pequena ficar respirável; em caixa mista de 16px ele só
   afrouxa a palavra e faz "After Effects" parecer duas coisas. */
.marq__i{
  display:inline-flex; align-items:center; gap:13px;
  font-family:var(--font);
  font-size:1rem; font-weight:600;
  letter-spacing:-.012em;
  color:var(--ink-2);
  white-space:nowrap;
}
@media (min-width:600px){ .marq__i{ gap:15px; font-size:1.0625rem } }
.marq__i img{ flex:none; width:30px; height:30px; border-radius:6px }
@media (max-width:599.98px){ .marq__i img{ width:26px; height:26px } }

/* ══ 10 · MÉTODO ═════════════════════════════════════════════════════════════ */
.method{ background:var(--canvas); padding-block:var(--gap-act) }
.method__fig{ margin-top:clamp(40px,5vw,64px) }
.method__svg{ width:100%; height:auto; display:block; overflow:visible }
.method__svg .grid-l{ stroke:var(--hairline); stroke-width:1 }
.method__svg .axis{ stroke:var(--hairline-2); stroke-width:1 }
.method__svg .curve{ fill:none; stroke-linecap:round }
/* O DIAGRAMA NO CELULAR — o problema é escala, não desenho.

   O `viewBox` é 1000x280. Numa tela de 390, o SVG inteiro é reduzido a 0,39 do
   tamanho: um traço de 2 unidades vira 0,8px de tela e um rótulo de 14 vira
   5,5px. Foi exatamente isso que apareceu na captura — a legenda existia e era
   ilegível.

   A correção é escalar em UNIDADES DE SVG, não em pixels de CSS: o traço vai a
   6 e o rótulo a 30, que depois da redução dão 2,3px e 11,7px na tela. Mesmo
   desenho, mesma proporção, legível.

   As linhas de grade somem: a 109px de altura elas viram ruído entre duas
   curvas que já se explicam sozinhas. */
.method__svg .curve--drop{ stroke:var(--ink-3); stroke-width:5; opacity:.55 }
.method__svg .curve--hold{ stroke:url(#gHold); stroke-width:8 }
.method__svg .lbl{ font-family:var(--mono); font-size:30px; letter-spacing:.04em; fill:var(--ink-2) }
.method__svg .lbl--hold{ fill:var(--accent-light) }
.method__svg .grid-l{ display:none }
@media (min-width:700px){
  .method__svg .grid-l{ display:block }
  .method__svg .curve--drop{ stroke-width:2.6 }
  .method__svg .curve--hold{ stroke-width:4 }
  .method__svg .lbl{ font-size:15px; letter-spacing:.06em }
}
/* Nada de forçar altura mínima aqui. Esticar o SVG para preencher uma altura
   deforma o traço E a letra — o rótulo fica alto e fino e o gráfico deixa de
   ser um gráfico. Desenho tem proporção, e ela não se negocia por altura.
   O que devolve legibilidade é escala de traço e de corpo, acima. */
.method__fig{ position:relative }
/* Uma respiração a mais em volta, que é o que faz o gráfico ler como peça e
   não como sobra entre dois parágrafos. */
@media (max-width:699.98px){
  .method__fig{ margin-top:clamp(30px,4.5vw,52px) }
  .method__cap{ margin-top:18px; font-size:.6875rem; letter-spacing:.12em }
}
.method__svg .area{ fill:url(#gArea); opacity:0 }
.method__cap{
  margin-top:clamp(22px,2.6vw,32px);
  font-family:var(--mono);
  font-size:.75rem; letter-spacing:.16em; text-transform:uppercase;
  color:var(--ink-3);
}

/* ══ 11 · CARTÕES ════════════════════════════════════════════════════════════ */
.filters{ margin-top:clamp(40px,5vw,64px); display:flex; flex-wrap:wrap; gap:8px }
.filter{
  min-height:40px; padding:0 18px; border-radius:var(--r-pill);
  font-size:.9375rem; font-weight:500; color:var(--ink-2);
  border:1px solid transparent;
  transition:color 240ms var(--ease-smooth),background-color 240ms var(--ease-smooth),border-color 240ms var(--ease-smooth);
}
.filter:hover{ color:var(--ink); background:rgba(255,255,255,.06) }
.filter[aria-pressed="true"]{ background:var(--ink); color:var(--canvas); border-color:var(--ink) }

.grid{ margin-top:clamp(36px,4.4vw,56px); display:grid; grid-template-columns:1fr; gap:44px var(--gap-card) }
@media (min-width:680px){ .grid{ grid-template-columns:repeat(2,1fr); gap:52px 32px } }
@media (min-width:1080px){ .grid{ grid-template-columns:repeat(3,1fr); gap:60px 32px } }
@media (min-width:680px){ .card--featured{ grid-column:1/-1 } }

.card__link{ display:block }
.card__shot{
  position:relative; aspect-ratio:16/9;
  border-radius:var(--r-card); overflow:hidden;
  border:1px solid var(--hairline);
  background:var(--surface-2);
  box-shadow:var(--sh-card);
  transition:transform var(--dur-sat) var(--ease-smooth),
             border-color var(--dur-sat) var(--ease-smooth),
             box-shadow var(--dur-sat) var(--ease-smooth);
}
/* ⚠ `transform` NÃO ENTRA NESTA TRANSIÇÃO. NUNCA.

   A paralaxe escreve `transform` nesta imagem a cada quadro. Se o CSS também
   tiver uma transição de 700ms em `transform`, o navegador passa a interpolar
   CADA escrita do GSAP ao longo de 700ms — sessenta transições novas por
   segundo, todas se cancelando.

   O sintoma não é "está lento": é a página TRAVANDO em blocos, que foi
   exatamente o que apareceu. É o erro mais caro que existe em animação na web,
   e o mais difícil de achar, porque as duas linhas parecem inofensivas
   separadas.

   Regra: propriedade animada por JS não aparece em `transition`. O zoom do
   hover mora no pai (.card__shot), que ninguém tuíta. */
.card__shot img{
  width:100%; height:100%; object-fit:cover;
  filter:saturate(.68) contrast(.98);
  transition:filter var(--dur-sat) var(--ease-smooth);
}
.card__dur{
  position:absolute; right:10px; bottom:10px;
  padding:3px 9px; border-radius:6px;
  background:var(--overlay); color:var(--ink);
  font-family:var(--mono); font-size:.75rem; line-height:1.4;
  -webkit-backdrop-filter:blur(6px); backdrop-filter:blur(6px);
}
.card__len{ margin-top:14px; height:2px; background:rgba(255,255,255,.09); border-radius:1px; overflow:hidden }
.card__len i{ display:block; height:100%; background:var(--ink-3); transform:scaleX(0); transform-origin:0 50%;
              transition:background-color var(--dur-sat) var(--ease-smooth) }
.card__body{ margin-top:16px }
.card__title{ font-size:clamp(1.0625rem,1.2vw,1.1875rem); line-height:1.3; letter-spacing:-.018em; font-weight:600 }
.card--featured .card__title{ font-size:clamp(1.375rem,2vw,1.75rem); letter-spacing:-.028em }
.card__arrow{ display:inline-block; margin-left:8px; opacity:0; transform:translateX(-6px);
              transition:opacity var(--dur-sat) var(--ease-smooth),transform var(--dur-sat) var(--ease-smooth) }
.card__cat{ margin-top:8px; font-family:var(--mono); font-size:.6875rem; letter-spacing:.14em;
            text-transform:uppercase; color:var(--ink-3) }
.card__link:hover .card__shot,.card__link:focus-visible .card__shot{
  transform:translateY(-6px);
  border-color:rgba(var(--accent-rgb),.34);
  box-shadow:0 26px 73.5px rgba(var(--accent-rgb),.14),var(--sh-card);
}
.card__link:hover .card__shot img{ filter:saturate(1) contrast(1) }
.card__link:hover .card__arrow{ opacity:1; transform:none }
.card__link:hover .card__len i{ background:var(--accent) }

/* O SLOT VAZIO. Uma vaga desenhada lê como decisão; um placehold.co lê como
   página inacabada. Enquanto não houver upload real, é isto que aparece — e é
   honesto, porque diz exatamente o que é. */
.card--slot .card__shot{
  display:grid; place-items:center;
  background:
    repeating-linear-gradient(135deg,rgba(255,255,255,.022) 0 1px,transparent 1px 9px),
    var(--surface-2);
  border-style:dashed;
  border-color:var(--hairline);
  box-shadow:none;
}
.slot__mark{ display:grid; justify-items:center; gap:10px; color:var(--ink-3) }
.slot__mark span{ font-family:var(--mono); font-size:.6875rem; letter-spacing:.2em; text-transform:uppercase }
.slot__rec{ width:11px; height:11px; border-radius:50%; background:rgba(var(--accent-rgb),.55) }

/* ══ 12 · ENTREGA ════════════════════════════════════════════════════════════ */
/* O CABEÇALHO QUE FICA PARADO ENQUANTO OS CARTÕES PASSAM.

   Segunda cena que segura a rolagem, e esta custa três linhas de CSS: o título
   é `sticky` no topo da própria seção e os quatro cartões deslizam ao lado
   dele. Nenhum JavaScript envolvido — o que significa que nenhum recálculo,
   resize ou refresh consegue quebrá-la.

   Só a partir de 1080px: abaixo disso os cartões empilham em uma coluna e
   prender o título tiraria metade da tela de quem está lendo. */

.deliv{ margin-top:clamp(40px,5vw,64px); display:grid; grid-template-columns:1fr; gap:var(--gap-card) }
@media (min-width:680px){ .deliv{ grid-template-columns:repeat(2,1fr) } }

.dcard{
  position:relative;
  padding:26px 24px 28px;
  border-radius:var(--r-card);
  background:rgba(255,255,255,.045);
  border:1px solid var(--hairline);
  box-shadow:var(--sh-card);
  overflow:hidden;
  transition:border-color var(--dur-sat) var(--ease-smooth),background-color var(--dur-sat) var(--ease-smooth);
}
.dcard:hover{ border-color:rgba(var(--accent-rgb),.28); background:rgba(255,255,255,.06) }
.dcard__n{
  font-family:var(--mono); font-size:.6875rem; letter-spacing:.2em;
  text-transform:uppercase; color:rgba(var(--accent-rgb),.85);
}
.dcard__t{ margin-top:16px; font-size:1.1875rem; line-height:1.25; letter-spacing:-.024em; font-weight:600 }
.dcard__d{ margin-top:10px; font-size:.9375rem; line-height:1.5; color:var(--ink-2) }

/* ══ A ENTREGA NO DESKTOP — duas por duas, ao lado do título ═══════════════

   No celular são quatro cartões empilhados, e está certo assim.

   No PC estavam quatro EM LINHA dentro de dois terços da largura: colunas de
   150px, texto quebrando em seis linhas de três palavras, e um vazio enorme à
   esquerda porque o título sticky é curto. Quatro colunas magras não são uma
   grade, são uma lista espremida.

   Duas por duas resolve os três de uma vez: a coluna de texto volta a ter
   medida de leitura, o bloco ganha altura suficiente para o título grudado ter
   por onde acompanhar, e o vazio à esquerda deixa de existir porque a grade
   passa a ocupar o espaço que sobrava.

   ⚠ Esta regra tem que ficar DEPOIS da base `repeat(4,1fr)`. Foi exatamente
   aqui que ela falhou antes: escrita acima, perdia por ordem de linha, e o
   layout continuava com quatro colunas por mais que eu mudasse o número. */
@media (min-width:1080px){
  .deliv-wrap{
    display:grid;
    grid-template-columns:minmax(0,.82fr) minmax(0,1.18fr);
    gap:clamp(48px,5.5vw,96px);
    align-items:start;
  }
  .deliv-head{ position:sticky; top:calc(var(--nav-h) + 64px) }
  .deliv{ margin-top:0; grid-template-columns:repeat(2,1fr); gap:clamp(20px,2vw,28px) }
  .dcard{ padding:30px 28px 32px }
  .dcard__t{ font-size:1.3125rem }
  .dcard__d{ font-size:1rem; line-height:1.55 }
}

/* ══ 13 · PROCESSO ═══════════════════════════════════════════════════════════ */
.process{ position:relative; background:var(--surface); scroll-margin-top:var(--nav-h) }
.process__in{ padding-block:var(--gap-act) }
.process__head{ margin-bottom:clamp(44px,5.5vw,72px) }
.process__body{ position:relative; display:grid; grid-template-columns:1fr; gap:clamp(36px,4.5vw,52px) }
.prail{ display:none }
.steps{ display:grid; gap:clamp(38px,5.5vw,52px) }
.step{ display:grid; grid-template-columns:auto minmax(0,1fr); gap:clamp(18px,2.6vw,40px); align-items:start }
.step__num{
  font-size:clamp(1.875rem,3.6vw,3.25rem);
  line-height:.9; letter-spacing:-.04em; font-weight:600; color:var(--ink);
  transform:translateX(-.06em); transform-origin:0% 50%;
}
.step__t{ font-size:clamp(1.1875rem,1.9vw,1.625rem); line-height:1.15; letter-spacing:-.028em; font-weight:600 }
.step__d{ margin-top:12px; max-width:52ch; font-size:1.0625rem; line-height:1.55; color:var(--ink-2) }

/* ══ A ROLAGEM QUE NÃO DESCE — e por que agora ela é `sticky` ═══════════════

   O efeito é o mesmo de antes: a seção trava na tela e os quatro passos trocam
   enquanto você rola. O QUE MUDOU é quem segura o elemento.

   A primeira versão usava `pin` do ScrollTrigger, que tira o elemento do fluxo,
   deixa ele `position: fixed` e reserva o espaço num espaçador calculado por
   JavaScript. Se qualquer coisa recalcular o layout no meio — o FAQ abrindo, o
   filtro trocando cartões, a barra de endereço do celular — o espaçador fica
   com a altura errada e o elemento fixo passa a flutuar POR CIMA da seção
   seguinte. Foi o que aconteceu.

   `position: sticky` resolve pelo lado do layout, não do script: o elemento
   nunca sai do fluxo, e a altura é reservada pelo PAI, declarada aqui em CSS.
   Não existe cálculo para dar errado. O JavaScript não move mais nada — ele só
   LÊ o progresso e troca uma classe.

   É a mesma regra do resto do arquivo: quem pode ser CSS, é CSS. JavaScript
   entra onde não há alternativa.
   ═══════════════════════════════════════════════════════════════════════════ */
@media (min-width:900px){
  /* 380vh dá 2.8 telas de curso para quatro passos — 0,7 tela por passo, que é
     o ritmo em que dá para ler cada um sem sentir que a página emperrou. */
  .process{ height:380vh }
  .process__in{
    position:sticky; top:0;
    height:100vh;
    display:flex; flex-direction:column; justify-content:center;
    padding-block:clamp(72px,9vh,110px);
    overflow:hidden;
  }
  .process__body{ grid-template-columns:2px minmax(0,1fr) minmax(0,1fr); gap:clamp(28px,3.4vw,52px); align-items:start }
  .prail{ display:block; position:relative; align-self:stretch; background:var(--hairline) }
  .prail i{
    position:absolute; inset:0 0 auto 0; height:0%;
    background:linear-gradient(180deg,var(--accent),var(--accent-light));
    will-change:height;
  }
  .steps{ gap:clamp(24px,3vh,40px) }
  .step{ opacity:.24; transition:opacity 520ms var(--ease-in-out) }
  .step .step__num{ transition:transform 520ms var(--ease-in-out),color 520ms var(--ease-in-out) }
  .step.is-active{ opacity:1 }
  .step.is-active .step__num{ transform:translateX(-.06em) scale(1.08); color:var(--accent-light) }

  /* As quatro descrições ocupam a MESMA célula, empilhadas: só a ativa
     aparece. Absolutas para que as três apagadas não deixem buraco e a coluna
     nunca pule de altura ao trocar de passo. */
  .step__d{
    position:absolute; top:0; left:calc(50% + clamp(14px,1.7vw,26px));
    width:calc(50% - clamp(14px,1.7vw,26px));
    margin-top:0; max-width:44ch;
    font-size:clamp(1.0625rem,1.15vw,1.1875rem);
    opacity:0; transform:translateY(14px);
    transition:opacity 520ms var(--ease-in-out),transform 520ms var(--ease-in-out);
    pointer-events:none;
  }
  .step.is-active .step__d{ opacity:1; transform:none; pointer-events:auto }
}
@media (prefers-reduced-motion:reduce){
  .process{ height:auto !important }
  .process__in{ position:static !important; height:auto !important; overflow:visible !important }
  .step{ opacity:1 !important }
  .step__d{ position:static !important; left:auto !important; width:auto !important;
            margin-top:12px !important; opacity:1 !important; transform:none !important }
}

/* ══ 14 · FAQ ════════════════════════════════════════════════════════════════ */
.faq{ margin-top:clamp(40px,5vw,64px); border-top:1px solid var(--hairline) }
.faq__i{ border-bottom:1px solid var(--hairline) }
.faq__q{
  width:100%; display:flex; align-items:center; justify-content:space-between; gap:24px;
  padding:clamp(22px,2.6vw,30px) 0;
  text-align:left;
  font-size:clamp(1.0625rem,1.5vw,1.3125rem); font-weight:600; letter-spacing:-.022em; line-height:1.3;
  color:var(--ink);
  transition:color 240ms var(--ease-smooth);
}
.faq__q:hover{ color:var(--accent-light) }
.faq__ico{ position:relative; flex:none; width:18px; height:18px }
.faq__ico::before,.faq__ico::after{
  content:""; position:absolute; left:50%; top:50%; background:currentColor;
  transform:translate(-50%,-50%);
  transition:transform 420ms var(--ease-out-expo),opacity 300ms var(--ease-smooth);
}
.faq__ico::before{ width:18px; height:1.5px }
.faq__ico::after{ width:1.5px; height:18px }
.faq__i.is-open .faq__ico::after{ transform:translate(-50%,-50%) rotate(90deg); opacity:0 }
/* Fechado só quando há JS para reabrir. Sem a classe .js — script
   bloqueado, CDN fora, JS desligado — as respostas nascem abertas, que é a
   degradação certa: conteúdo visível ganha de acordeão bonito e mudo. */
.faq__a{ overflow:hidden }
.js .faq__a{ height:0 }
.faq__a p{ padding-bottom:clamp(22px,2.6vw,30px); max-width:66ch; font-size:1.0625rem; line-height:1.6; color:var(--ink-2) }

/* ══ 15 · CONTATO ════════════════════════════════════════════════════════════ */
.mailto{
  display:inline-block; position:relative;
  margin-top:clamp(40px,5.5vw,72px);
  max-width:100%;
  font-size:clamp(1.375rem,4.4vw,3.25rem);
  line-height:1.1; letter-spacing:-.032em; font-weight:600;
  overflow-wrap:anywhere;
}
.mailto::after{
  content:""; position:absolute; left:0; right:0; bottom:-.12em; height:2px;
  background:linear-gradient(90deg,var(--accent),var(--accent-light));
  transform:scaleX(0); transform-origin:0 50%;
  transition:transform 520ms var(--ease-out-expo);
}
.mailto:hover::after,.mailto:focus-visible::after{ transform:scaleX(1) }
.contact__ways{ margin-top:clamp(32px,3.6vw,48px); display:flex; flex-wrap:wrap; gap:14px 26px; font-size:1.0625rem }
.contact__ways:empty{ margin-top:0 }
.contact__meta{
  margin-top:clamp(36px,4.2vw,56px);
  display:flex; flex-wrap:wrap; gap:12px 26px;
  font-family:var(--mono); font-size:.75rem; letter-spacing:.14em;
  text-transform:uppercase; color:var(--ink-3);
}
.contact__meta span{ display:inline-flex; align-items:center; gap:9px }
.contact__meta i{ width:6px; height:6px; border-radius:50%; background:rgba(var(--accent-rgb),.7); flex:none }

/* ══ 16 · RODAPÉ ═════════════════════════════════════════════════════════════ */
.foot{ border-top:1px solid var(--hairline); padding-block:clamp(36px,4.5vw,60px) }
.foot__in{ display:flex; flex-wrap:wrap; align-items:baseline; gap:16px clamp(24px,4vw,48px); justify-content:space-between }
.foot__c{ font-size:.9375rem; color:var(--ink-2) }
.foot__top{ position:relative; font-size:.9375rem; font-weight:500; padding-block:4px }
.foot__top::after{
  content:""; position:absolute; left:0; right:0; bottom:0; height:1px; background:var(--hairline-2);
  transition:background-color 240ms var(--ease-smooth);
}
.foot__top:hover::after{ background:var(--accent) }

/* ══ 17 · MOVIMENTO REDUZIDO ═════════════════════════════════════════════════
   Estado final em tudo. Não é cortesia: é a diferença entre uma página que
   alguém com labirintite consegue ler e uma que ela fecha. */
@media (prefers-reduced-motion:reduce){
  html{ scroll-behavior:auto }
  *,*::before,*::after{
    animation-duration:.001ms !important; animation-iteration-count:1 !important;
    transition-duration:.001ms !important; transition-delay:0ms !important;
  }
  .media__img{ transform:none !important }
  .process__in{ position:static !important; min-height:0 !important; overflow:visible !important }
  .process__body{ grid-template-columns:1fr !important }
  .prail{ display:none !important }
  .step{ opacity:1 !important }
  .step .step__num{ transform:translateX(-.06em) !important }
  .step__d{ position:static !important; left:auto !important; width:auto !important;
            margin-top:12px !important; opacity:1 !important; transform:none !important }
  .faq__a{ height:auto !important }
}
