/* ============================================================
   motion.css — Sistema de movimento (base: 21tsi.com)
   Depende de tokens.css + style.css. Carregar por último.
   Tudo degrada: sem JS → visível; prefers-reduced-motion → estático.
   ============================================================ */

:root {
  --ease-editorial: cubic-bezier(0.19, 1, 0.22, 1);      /* "glide" */
  --ease-expo: cubic-bezier(0.16, 1, 0.30, 1);           /* ≈ easeOutExpo (21tsi) */
  --dur-word: 800ms;                                     /* 21tsi: duration 800 */
  --stagger-word: 60ms;                                  /* 21tsi: x.stagger(60) */
  --hud-size: 66svh;
}

/* ------------------------------------------------------------
   0. INTRO LOADER  (mecânica idêntica ao 21tsi.com — main.js `ib()`)
   preto → frase → nome JEANDRE letra a letra (translateY 100→0,
   rotate 10→0) → sequência de fotos desfocadas (scale 1.5→1,
   rotate 8→0, opacity 0→1, stagger) → tudo sai (blur + scale + fade)
   ------------------------------------------------------------ */
.loader {
  position: fixed; inset: 0; z-index: 1000;
  background: var(--color-black-void);
  overflow: hidden;
  transition: background 520ms linear, opacity 300ms linear 260ms;
}
.loader[hidden] { display: none; }
/* handoff: o PRETO recua; a foto final segura e "vira" o hero */
.loader.is-done { background: rgba(0, 0, 0, 0); pointer-events: none; opacity: 0; }
body.is-loading { overflow: hidden; }

/* sequência de fotos — entram desfocadas, uma após a outra */
.loader-sequence { position: absolute; inset: 0; }
.loader-sequence-item {
  position: absolute; inset: 0;
  width: 100%; height: 100%; object-fit: cover;
  opacity: 0;
  filter: blur(28px) brightness(0.42);
  transform: scale(1.5) rotate(8deg);
  transform-origin: center;
  transition: opacity var(--dur-word) var(--ease-expo),
              transform var(--dur-word) var(--ease-expo),
              filter 900ms var(--ease-expo);
}
.loader-sequence-item.is-on { opacity: 1; transform: scale(1) rotate(0deg); }
/* a ÚLTIMA foto = a foto principal do hero: ao fim da contagem ela "surge"
   (ganha foco até o mesmo nível do hero) e SEGURA na saída → handoff invisível */
/* a ÚLTIMA foto = a foto do hero (studio-87), MESMA cor (quase original) e
   desfoque que a camada WebGL em --pb:0 → "entra" no background sem pulo. */
.loader-sequence-item.is-final.is-on {
  filter: blur(13px) brightness(0.82) contrast(1.04);
  transform: scale(1.05) rotate(0deg);
}
.loader-scrim { /* scrim que separa o texto da imagem; some antes do handoff */
  position: absolute; inset: 0; pointer-events: none; z-index: 1;
  background: linear-gradient(180deg, rgba(0,0,0,.62), rgba(0,0,0,.44) 45%, rgba(0,0,0,.74));
  transition: opacity 500ms linear;
}

.loader-inner {
  position: absolute; inset: 0; z-index: 2;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: clamp(var(--spacing-27), 6vh, var(--spacing-63));
  padding: var(--spacing-20);
  transition: opacity 360ms linear;
}

/* contagem — número pequeno no canto, tica pela sequência (eco do 0→21 do 21tsi) */
.loader-count {
  position: absolute; z-index: 2;
  left: var(--spacing-20); bottom: var(--spacing-23);
  font-size: var(--text-caption); letter-spacing: 0.08em;
  font-variant-numeric: tabular-nums; text-transform: uppercase;
  color: var(--color-paper-white); opacity: 0.6;
  transition: opacity 300ms linear;
}
.loader.is-text-out .loader-inner { opacity: 0; transition-delay: 220ms; }
.loader.is-out .loader-count { opacity: 0; }
.loader.is-out .loader-scrim { opacity: 0; }

/* TUDO centralizado, sobre PRETO PURO (as fotos só entram depois) */
.loader-inner { text-align: center; }
.loader-phrase { display: none; }

/* FRASE DE EFEITO — aparece RÁPIDO (palavra a palavra) antes de JEANDRE e
   rola pra cima, no mesmo espírito da troca JEANDRE→FILMS. Centrada sobre o
   mesmo eixo óptico do nome (position:absolute em relação ao .loader fixo). */
.loader-lead {
  position: absolute; left: 50%; top: 50%;
  transform: translate(-50%, -50%);
  width: min(86vw, 20ch);
  text-align: center; text-wrap: balance;
  font-size: clamp(20px, 4.2vw, 46px);
  font-weight: var(--font-weight-display, 350);
  line-height: 1.15; letter-spacing: normal;
  color: var(--color-paper-white);
  z-index: 3; pointer-events: none;
}
.loader-lead .lw { display: inline; }
.loader-lead .ltr {
  display: inline-block; overflow: clip; vertical-align: bottom;
  padding-bottom: 0.14em; margin-bottom: -0.14em;
}
.loader-lead .ltr > span {
  display: inline-block; opacity: 0;
  transform: translateY(115%) rotate(6deg); transform-origin: 0% 50%;
  transition: transform 560ms var(--ease-expo), opacity 320ms linear;
}
.loader-lead .ltr.is-on > span { transform: none; opacity: 1; }
.loader-lead.is-out .ltr > span {
  transform: translateY(-120%) rotate(-4deg); opacity: 0;
  transition: transform 460ms var(--ease-expo), opacity 280ms linear;
  transition-delay: calc(var(--i, 0) * 20ms);
}
@media (prefers-reduced-motion: reduce) {
  .loader-lead { display: none; }
}

/* NOME — a palavra gigante central (como o contador do 21tsi).
   Dois "words" empilhados no mesmo lugar: .lw--1 = JEANDRE (constrói letra a
   letra), .lw--2 = FILMS (entra no fim, trocando com JEANDRE). */
.loader-name {
  display: grid; justify-items: center; align-items: center;
  font-size: var(--fluid-counter);      /* 21tsi: .loading_counter = clamp(100px,17svw,320px) */
  line-height: 1;
  font-weight: var(--font-weight-w380); /* eco do wordmark "21TSI" (380) */
  letter-spacing: normal;               /* 21tsi: sem tracking negativo */
  color: var(--color-paper-white);
}
.loader-name .lw {
  grid-area: 1 / 1;                 /* os dois ocupam a mesma célula */
  display: inline-flex; align-items: baseline; white-space: nowrap;
}
.loader-name .ltr {
  display: inline-block; overflow: clip;
  padding-bottom: 0.16em; margin-bottom: -0.16em;
}
.loader-name .ltr > span {
  display: inline-block;
  transform: translateY(115%) rotate(8deg); transform-origin: 0% 50%; opacity: 0;
  transition: transform 520ms var(--ease-expo), opacity 300ms linear;
}
/* cada letra "surge" quando o JS põe .is-on na .ltr, em sequência */
.loader-name .ltr.is-on > span { transform: none; opacity: 1; }
/* palavra saindo pra cima (JEANDRE → FILMS, e no fim do intro) */
.loader-name .lw.is-out .ltr > span {
  transform: translateY(-120%) rotate(-4deg); opacity: 0;
  transition: transform 480ms var(--ease-expo), opacity 300ms linear;
  transition-delay: calc(var(--i, 0) * 28ms);
}

/* SAÍDA do texto — a palavra final (FILMS) rola pra cima ANTES das fotos */
.loader.is-text-out .loader-name .lw .ltr > span {
  transform: translateY(-120%) rotate(-4deg); opacity: 0;
  transition: transform 540ms var(--ease-expo), opacity 320ms linear;
  transition-delay: calc(var(--i, 0) * 26ms);
}

/* as fotos anteriores somem; a ÚLTIMA (is-final) SEGURA, já igual ao hero */
.loader.is-out .loader-sequence-item.is-on:not(.is-final) {
  opacity: 0; filter: blur(44px) brightness(0.35); transform: scale(1.25);
}

.loader-bar {
  position: absolute; left: 0; bottom: 0; height: var(--border-width);
  width: 100%; transform: scaleX(0); transform-origin: left;
  background: var(--color-paper-white); z-index: 2;
}

/* ------------------------------------------------------------
   1. SCROLL PROGRESS — o filete do topo vira barra
   ------------------------------------------------------------ */
.site-header-progress {
  position: absolute; top: calc(-1 * var(--border-width)); left: 0;
  height: var(--border-width); width: 100%;
  transform: scaleX(var(--progress, 0)); transform-origin: left;
  background: var(--color-paper-white);
  z-index: 2;
}
.site-header { border-top-color: color-mix(in srgb, var(--color-paper-white) 28%, transparent); }

/* toggle da grelha técnica — mesma linguagem dos nav-links */
.hud-toggle-btn {
  font-size: var(--text-caption); letter-spacing: 0.05em; text-transform: uppercase;
  opacity: 0.55; transition: opacity var(--dur-micro) linear;
}
.hud-toggle-btn:hover { opacity: 1; }
.hud-toggle-btn.is-off { opacity: 0.28; text-decoration: line-through; }
@media (max-width: 900px) { .hud-toggle-btn { display: none; } }

/* ------------------------------------------------------------
   2. CIRCLES — HUD do 21tsi.com (`.circles`) — RÉPLICA EXATA
      2–3 aros concêntricos: borda gira SEMPRE (CSS animation
      90s / 120s), o miolo (números + cruzes) gira e escala com
      o scroll (`--c-rotate` / `--c-rotate-inverse` / `--c-scale`).
      O `.hud` antigo dos HTML fica escondido; `.circles` é injetado.
   ------------------------------------------------------------ */
@keyframes rotate        { 0% { transform: rotateZ(-360deg); } 100% { transform: rotateZ(0deg); } }
@keyframes rotateInverse { 0% { transform: rotateZ( 360deg); } 100% { transform: rotateZ(0deg); } }

.hud { display: none !important; }   /* substituído por .circles */

.circles {
  position: fixed; inset: 0 0 auto 0; height: 100dvh; z-index: 5;
  pointer-events: none; color: var(--color-paper-white);
  overflow: hidden;
  --c-rotate: 0deg; --c-rotate-inverse: 0deg; --c-scale: 0.5;
  --c-split: 0;                 /* 0 = grille única · 1 = dividida em 2 grupos */
  --c-dock: 0;                  /* 0 = centrado · 1 = docado na lateral (galerias Vídeo/Foto) */
  --c-dock-dir: 1;              /* +1 = doca à esquerda · -1 = à direita (lado oposto ao texto) */
}
/* DOCK — nas galerias de Vídeo/Foto o grille se junta e desliza p/ a lateral
   OPOSTA ao texto do álbum (mecânica da "méthodologie" 21tsi). A transição só
   dispara nas viradas discretas (entrada/saída e troca de lado), não a cada
   quadro de scroll — `--c-dock` é praticamente degrau durante a seção. */
.circles {
  translate: calc(var(--c-dock) * var(--c-dock-dir) * -22vw) 0;
  transition: translate 560ms var(--ease-editorial);
}
.circles.is-off { display: none; }
.circles .circle {
  position: absolute;
  width: var(--hud-size); height: var(--hud-size);
  top: 53svh; left: 50vw;
  margin: calc(var(--hud-size) / -2) 0 0 calc(var(--hud-size) / -2);
  opacity: 0;
  transition: opacity 700ms var(--ease-out-soft);   /* split segue o scroll, sem transição */
}
.circles.is-visible .circle { opacity: 1; }
.circles.is-visible .circle--3 { opacity: 0.5; }
.circles.is-visible .circle--4 { opacity: 1; }
/* SPLIT — a partir do frame "Film de marque": grupo esquerdo desliza p/ a
   esquerda, grupo direito p/ a direita (efeito Venn do 21tsi). Durante o DOCK
   o fator (1 - --c-dock) traz os dois grupos de volta ao centro (se juntam). */
.circles .circle--1, .circles .circle--2 { translate: calc(var(--c-split) * (1 - var(--c-dock)) * -16vw) 0; }
.circles .circle--3, .circles .circle--4 { translate: calc(var(--c-split) * (1 - var(--c-dock)) *  16vw) 0; }
/* mira: linhas H + V atravessando o aro */
.circles .circle::before, .circles .circle::after {
  content: ""; position: absolute; left: -10%; top: 50%;
  width: 120%; height: var(--border-width);
  margin-top: calc(var(--border-width) / -2);
  background: currentColor; opacity: 0.2;
}
.circles .circle::after { transform: rotate(90deg); }
/* GIRO CONTÍNUO — o miolo (bezel + números) roda SEMPRE, mesmo sem rolagem
   (como no 21tsi): giro lento e suave, um grupo p/ um lado, outro p/ o outro,
   no próprio eixo. O scroll só SOMA um empurrão via a propriedade `rotate:`
   (compõe com o `transform:` da animação sem conflito). `scale:` = zoom c/ scroll. */
.circles .circle_inner { position: absolute; inset: 0; scale: var(--c-scale); }
/* os DOIS aros numerados (1 e 4) giram em sentidos OPOSTOS:
   grille esquerda → horário · grille direita → anti-horário */
.circles .circle--1 .circle_inner { rotate: var(--c-rotate);         animation: rotate 70s linear infinite; }        /* CW  */
.circles .circle--2 .circle_inner { rotate: var(--c-rotate-inverse); animation: rotateInverse 96s linear infinite; } /* CCW */
.circles .circle--3 .circle_inner { animation: rotate 132s linear infinite; }                                         /* CW  */
.circles .circle--4 .circle_inner {
  rotate: var(--c-rotate-inverse);
  scale: calc(var(--c-scale) * 0.88);
  animation: rotateInverse 88s linear infinite;                                                                       /* CCW */
}
.circles .circle_border {
  position: absolute; inset: 0;
  border: var(--border-width) solid color-mix(in srgb, var(--color-paper-white) 30%, transparent);
  border-radius: 50%;
}
.circles .circle--1 .circle_border { animation: rotate 90s linear infinite; }
.circles .circle--2 .circle_border { animation: rotateInverse 120s linear infinite; }
.circles .circle--4 .circle_border { animation: rotate 110s linear infinite; }
/* marcas "+" nos 4 pontos cardeais, EM CIMA do aro */
.circles .circle_plus {
  position: absolute; width: 12px; height: 12px;
  margin: -6px 0 0 -6px;                       /* centraliza no ponto cardeal */
}
.circles .circle_plus::before, .circles .circle_plus::after {
  content: ""; position: absolute; inset: 0; margin: auto; background: currentColor;
}
.circles .circle_plus::before { width: 100%; height: var(--border-width); }
.circles .circle_plus::after  { width: var(--border-width); height: 100%; }
/* :nth-of-type (não :nth-child) — o 1º filho de .circle_inner é o .circle_border */
.circles .circle_plus:nth-of-type(1) { top: 0;    left: 50%; }   /* 12 h */
.circles .circle_plus:nth-of-type(2) { top: 100%; left: 50%; }   /* 6 h  */
.circles .circle_plus:nth-of-type(3) { top: 50%;  left: 100%; }  /* 3 h  */
.circles .circle_plus:nth-of-type(4) { top: 50%;  left: 0;    }  /* 9 h  */
/* número FORA do aro, logo depois do "+" (como no 21tsi). Centrado via
   `translate:` — o `transform` fica livre p/ a contra-rotação. */
.circles .circle_value {
  position: absolute; white-space: nowrap;
  font-size: var(--text-caption); letter-spacing: 0.05em; opacity: 0.6;
  font-variant-numeric: tabular-nums; line-height: 1;
}
.circles .circle_plus:nth-of-type(1) .circle_value { bottom: calc(100% + 16px); left: 50%; translate: -50% 0; }  /* acima do 12 h */
.circles .circle_plus:nth-of-type(2) .circle_value { top:    calc(100% + 16px); left: 50%; translate: -50% 0; }  /* abaixo do 6 h */
.circles .circle_plus:nth-of-type(3) .circle_value { left:   calc(100% + 16px); top: 50%;  translate: 0 -50%; }  /* à direita do 3 h */
.circles .circle_plus:nth-of-type(4) .circle_value { right:  calc(100% + 16px); top: 50%;  translate: 0 -50%; }  /* à esquerda do 9 h */
/* o miolo GIRA, mas o número CONTRA-GIRA (mesma duração, sentido oposto) →
   fica sempre na HORIZONTAL, só orbitando junto com o aro. */
.circles .circle--1 .circle_value {
  rotate: calc(-1 * var(--c-rotate));
  animation: rotateInverse 70s linear infinite;
}
.circles .circle--4 .circle_value {
  rotate: calc(-1 * var(--c-rotate-inverse));
  animation: rotate 88s linear infinite;
}
/* MOBILE: o grille não doca (o painel do álbum fica embaixo da mídia, não ao
   lado) e vira uma textura de fundo bem discreta. */
@media (max-width: 900px) {
  .circles { translate: none; }
  .circles.is-visible .circle { opacity: 0.3; }
  .circles.is-visible .circle--3 { opacity: 0.16; }
}
@media (prefers-reduced-motion: reduce) {
  .circles { transition: none; }
  .circles .circle_border, .circles .circle_inner, .circles .circle_value { animation: none !important; }
}

/* ------------------------------------------------------------
   3. SPLIT-TEXT — palavras/linhas mascaradas rolam de baixo com
      leve rotação (21tsi: translateY 100%→0, rotate 10→0, opacity,
      duration 800, stagger 60, easeOutExpo)
   ------------------------------------------------------------ */
.line-mask, .word-mask {
  display: block; overflow: clip;
  padding-bottom: 0.16em; margin-bottom: -0.16em; /* descendentes (g, p, ç) */
}
.word-mask { display: inline-block; }
.word-mask + .word-mask,
.word-mask { margin-right: 0.26em; }

.line-inner, .word-inner {
  display: inline-block;
  transform: translateY(110%) rotate(3deg);   /* 21tsi EXATO: .word { translateY(110%) rotate(3deg) } */
  transform-origin: 0% 50%;
  opacity: 0;
  transition: transform var(--dur-word) var(--ease-expo),
              opacity calc(var(--dur-word) * 0.55) linear;
  /* atraso = posição do bloco na cascata (--reveal-i) + posição da linha/palavra */
  transition-delay: calc(var(--reveal-i, 0) * var(--stagger-reveal, 0ms)
                       + var(--line-i, 0) * var(--stagger-word));
  will-change: transform, opacity;
}
.line-inner { display: block; }
[data-split].is-in .line-inner,
[data-split].is-in .word-inner { transform: none; opacity: 1; }
/* re-armável: ao perder .is-in as unidades voltam a translateY(110%) e re-animam */

/* ------------------------------------------------------------
   3b. MANIFESTO — texto que "entra em foco" palavra a palavra
       com a rolagem (21tsi EXATO: .pSection--sport .manifesto .word
       { scale(0.85); filter: blur(15px) } → .active { scale(1); blur(0) })
   ------------------------------------------------------------ */
[data-manifesto] { --lead: 1.5; }
[data-manifesto] .mf-word {
  display: inline-block; white-space: pre;
  transform: scale(0.85);
  filter: blur(15px);
  opacity: 0.28;
  transition: opacity 0.2s linear,
              filter 0.3s linear,
              transform 0.6s var(--ease-circ);   /* 21tsi: cubic-bezier(.075,.82,.165,1) */
  will-change: transform, filter, opacity;
}
[data-manifesto] .mf-word.active {
  transform: scale(1); filter: blur(0px); opacity: 1;
}
.no-js [data-manifesto] .mf-word,
.reduce [data-manifesto] .mf-word { transform: none; filter: none; opacity: 1; }

/* ------------------------------------------------------------
   4. FRAMES DA GALERIA — nítidas por padrão. Na entrada dão um
      "arranco" com rastro de movimento que assenta rápido — o
      eco do dissolve-com-trail do 21tsi. SEM desfoque contínuo.
      JS põe .is-armed antes de entrar em cena e retira 1x.
   ------------------------------------------------------------ */
.frame-media img,
.frame-media video {
  transform: translate3d(0, 0, 0) scale(1.001);
  filter: none;
  transition: transform 900ms var(--ease-expo), filter 620ms var(--ease-expo);
  will-change: transform, filter;
}
/* estado "armado" — pré-entrada: deslocada + rastro; sem transição */
.frame-media.is-armed img {
  transform: translateY(8%) scale(1.16);
  filter: blur(22px) brightness(0.72);
  transition: none;
}
.frame-media.is-armed video {
  transform: translateY(5%) scale(1.09);
  filter: blur(11px) brightness(0.8);
  transition: none;
}
.no-js .frame-media img,
.no-js .frame-media video { filter: none; transform: none; }

/* ============================================================
   HERO PINADO COM ESTADOS  (mecânica do 21tsi: a rolagem no
   hero NÃO desce a página — troca a foto e revela a frase.
   Só quando o .hero-pin termina começa a rolagem normal.)
   ============================================================ */
.hero-pin {
  position: relative;
  /* uma tela presa + faixa de scrub por estado. --state-scrub controla
     quanto se rola por estado (não precisa ser rápido, precisa ser coerente) */
  height: calc(100svh + var(--states, 3) * var(--state-scrub, 55svh));
  /* 21tsi: .pSection--hero ≈ 2,5 telas para os estados do título */
}
.hero-pin .hero {
  position: sticky; top: 0;
  height: 100svh; min-height: 0;
  overflow: hidden;
}
/* tudo que vem depois do hero cobre o hero pinado */
/* ~77% opaco: deixa a fumaça do canvas WebGL vazar de leve por todo o site */
main > *:not(.hero-pin) { position: relative; z-index: 1; background: rgba(0, 0, 0, 0.77); }

/* palco de fotos — camada "fixa" (como o .render do 21tsi).
   O desfoque NÃO é filtro na imagem: é uma camada .hero-blur com
   backdrop-filter + tint 10% preto (21tsi: .render_blur), que cresce
   com o progresso do pin --p. */
.hero-stage { position: absolute; inset: 0; overflow: hidden; --p: 0; --pb: 0; }
/* canvas WebGL — FIXO em tela cheia, atrás de todo o conteúdo (== .render do
   21tsi). Renderiza a foto do hero (só na região do hero) + a FUMAÇA do mouse
   (visível em todo o site, vazando pelo conteúdo ~82% opaco). */
.hero-webgl {
  position: fixed; inset: 0; width: 100vw; height: 100svh;
  display: block; z-index: 0; pointer-events: none;
}
.hero-slide {
  position: absolute; inset: 0;
  width: 100%; height: 100%; object-fit: cover;
  object-position: 50% calc(46% + var(--p) * 10%);          /* pan lento e contínuo */
  opacity: 0;
  /* grade "cinema" SÓ no fundo do hero (21tsi: imagens escuras/monocromáticas).
     Os frames da galeria continuam nítidos e com cor cheia. */
  filter: saturate(0.5) brightness(0.58) contrast(1.08);
  transform: scale(calc(1.04 + var(--p) * 0.10));           /* ken-burns por todo o pin */
  transition: opacity 1000ms var(--ease-glide);
  will-change: opacity, transform;
}
.hero-slide.is-active { opacity: 1; }
.hero-blur {                                                /* == .render_blur do 21tsi */
  position: absolute; inset: 0; z-index: 1; pointer-events: none;
  /* COMEÇA desfocada (--pb:0 → ~13px) e RESOLVE RÁPIDO — --pb chega a 1 já na
     2ª imagem (main.js: pb = prog/0.4). */
  background: rgba(0, 0, 0, calc(0.05 + (1 - var(--pb)) * 0.05));
  -webkit-backdrop-filter: blur(calc(1.5px + (1 - var(--pb)) * 11.5px));
  backdrop-filter: blur(calc(1.5px + (1 - var(--pb)) * 11.5px));
}
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .hero-slide {
    filter: blur(calc(1.5px + (1 - var(--pb)) * 11.5px))
            saturate(0.8) brightness(0.66) contrast(1.12);
  }
}

/* blocos de texto por estado — ancorados EMBAIXO À ESQUERDA (21tsi).
   Revelam com máscara de palavra e derivam de leve pra cima com a rolagem. */
.hero-states { position: absolute; inset: 0; z-index: 2; }
.hero-state {
  position: absolute;
  left: var(--text-inset); right: var(--text-inset);
  bottom: 12svh;
  display: flex; flex-direction: column; gap: var(--spacing-27);
  opacity: 0; visibility: hidden;
  transform: translateY(40px);          /* 21tsi: .pSection_header_title .st4 { translateY(40px) } */
  transition: opacity 240ms linear, visibility 0s linear 240ms,
              transform 700ms var(--ease-glide);
  will-change: transform, opacity;
}
.hero-state.is-active {
  visibility: visible; opacity: var(--st-o, 1);
  /* deriva sutil pra cima conduzida pelo scroll (--st 0→1) — sem escala */
  transform: translateY(calc((34 - var(--st, 0) * 50) * 1px));
  transition: opacity 200ms linear;
}
.hero-state.is-past {
  visibility: hidden; opacity: 0; transform: translateY(-40px);
  transition: opacity 190ms linear, visibility 0s linear 190ms,
              transform 600ms var(--ease-glide);
}
.hero-state.is-future {
  visibility: hidden; opacity: 0; transform: translateY(40px);
  transition: opacity 240ms linear, visibility 0s linear 240ms;
}
.hero-state .display { max-width: 15ch; }
.hero-state .lede { max-width: 34ch; }
.hero-state .eyebrow {
  opacity: 0; transform: translateY(10px);
  transition: opacity 400ms linear, transform 500ms var(--ease-glide);
}
.hero-state.is-active .eyebrow { opacity: 0.9; transform: none; transition-delay: 120ms; }

/* ---- botão SCROLL (21tsi: .hero_scroll) — injetado por JS em .hero ---- */
.hero-scroll {
  position: absolute; z-index: 3;
  right: var(--text-inset); bottom: 5svh;
  width: 100px; height: 100px;
  display: grid; place-items: center;
  color: var(--color-paper-white);
}
.hero-scroll-ring {
  position: absolute; inset: 0; border-radius: 100px;
  border: var(--border-width) solid color-mix(in srgb, var(--color-paper-white) 42%, transparent);
  transition: transform 800ms var(--ease-glide);
}
.hero-scroll:hover .hero-scroll-ring { transform: scale(1.04); }
.hero-scroll:active .hero-scroll-ring { transform: scale(0.92); }
.hero-scroll-arrow {
  position: absolute; top: 30px; left: 50%; margin-left: -5px;
  width: 10px; height: 10px;
  border-right: var(--border-width) solid currentColor;
  border-bottom: var(--border-width) solid currentColor;
  transform: rotate(45deg);
  animation: hero-scroll-bob 1.9s var(--ease-glide) infinite;
}
@keyframes hero-scroll-bob {
  0%, 100% { transform: rotate(45deg) translate(0, 0); opacity: 0.5; }
  50%      { transform: rotate(45deg) translate(3px, 3px); opacity: 1; }
}
.hero-scroll-label {
  position: absolute; top: 54%; width: 100%; text-align: center;
  font-size: var(--text-caption); letter-spacing: 0.1em; text-transform: uppercase;
  opacity: 0.8;
}
.hero-pin.is-engaged .hero-scroll { opacity: 1; transition: opacity 400ms linear; }
.hero-scroll.is-hidden { opacity: 0; pointer-events: none; transition: opacity 300ms linear; }

/* pontinhos de estado — o ativo "preenche" conforme o sub-progresso --st */
.hero-dots {
  position: absolute; left: max(var(--text-inset), var(--spacing-20));
  bottom: var(--spacing-23); z-index: 1;
  display: flex; gap: var(--spacing-11);
}
.hero-dots i {
  position: relative; overflow: hidden;
  width: 26px; height: var(--border-width);
  background: color-mix(in srgb, var(--color-paper-white) 26%, transparent);
}
.hero-dots i::after {
  content: ""; position: absolute; inset: 0;
  background: var(--color-paper-white);
  transform: scaleX(0); transform-origin: left;
}
.hero-dots i.is-past::after { transform: scaleX(1); }
.hero-dots i.is-active::after { transform: scaleX(var(--st, 0)); }

@media (prefers-reduced-motion: reduce) {
  .hero-pin { height: auto !important; }
  .hero-pin .hero { position: relative !important; }
  .hero-slide { transition: none; }
  .hero-slide:first-child { opacity: 1; }             /* mostra só a 1ª foto */
  .hero-state { position: relative; opacity: 1; visibility: visible; }
  .hero-state:not(:first-child) { display: none; }    /* mostra só o 1º estado */
  .hero-dots { display: none; }
}
.no-js .hero-pin { height: auto; }
.no-js .hero-pin .hero { position: relative; }
.no-js .hero-slide:first-child { opacity: 1; filter: none; transform: none; }
.no-js .hero-state:first-child { opacity: 1; visibility: visible; }
.no-js .hero-state:not(:first-child), .no-js .hero-dots { display: none; }

/* ------------------------------------------------------------
   5. MARQUEE — tira cinética de texto entre seções
   ------------------------------------------------------------ */
.marquee {
  border-top: var(--border-width) solid var(--border-muted);
  border-bottom: var(--border-width) solid var(--border-muted);
  overflow: hidden; white-space: nowrap;
  padding: var(--spacing-19) 0;
}
.marquee-track {
  display: inline-flex; gap: var(--spacing-38);
  will-change: transform;
  animation: marquee 34s linear infinite;
}
.marquee span {
  font-size: var(--text-subheading);
  text-transform: uppercase; letter-spacing: 0.05em;
  font-weight: var(--font-weight-w380);
}
.marquee span::after { content: "—"; margin-left: var(--spacing-38); opacity: 0.4; }
@keyframes marquee { to { transform: translateX(-50%); } }

/* --- CLIENTES: mesma tira cinética, com as logos passando pro lado --- */
.clients {
  padding: clamp(var(--spacing-38), 7vh, var(--spacing-63)) 0;
}
.clients .eyebrow {
  display: block;
  padding-left: max(var(--text-inset), var(--spacing-20));
  margin-bottom: clamp(var(--spacing-19), 3.5vh, var(--spacing-38));
}
.marquee--logos { padding: clamp(var(--spacing-19), 3vh, var(--spacing-30)) 0; }
.marquee--logos .marquee-track { gap: clamp(44px, 7vw, 104px); align-items: center; }
.marquee--logos img {
  height: clamp(17px, 2.2vw, 27px);
  width: auto; max-width: clamp(110px, 15vw, 220px);
  object-fit: contain; flex: none;
  filter: brightness(0) invert(1);      /* qualquer logo → branco puro */
  opacity: 0.46;
  transition: opacity var(--dur-word) var(--ease-editorial);
}
.marquee--logos img:hover { opacity: 0.9; }
/* hover em qualquer parte da tira → congela o deslize (como no 21tsi) */
.marquee--logos:hover .marquee-track { animation-play-state: paused; }

/* BALÃO — hover numa logo abre um pill branco grande com a logo em preto */
.client-balloon {
  position: fixed; z-index: 40;
  left: 50%; top: 50%;
  transform: translate(-50%, -50%) scale(0.92);
  display: flex; align-items: center; justify-content: center;
  padding: clamp(24px, 4.6vh, 50px) clamp(44px, 7.5vw, 94px);
  background: var(--color-paper-white, #fff);
  border-radius: 999px;
  box-shadow: 0 24px 70px -28px rgba(0, 0, 0, 0.6);
  opacity: 0; pointer-events: none;
  transition: opacity 260ms var(--ease-editorial),
              transform 380ms var(--ease-editorial);
}
.client-balloon.is-visible { opacity: 1; transform: translate(-50%, -50%) scale(1); }
.client-balloon img {
  height: clamp(32px, 6vh, 74px); width: auto;
  max-width: min(58vw, 440px); object-fit: contain;
  filter: brightness(0);                 /* logo em preto sólido (ref. 21tsi) */
}
@media (prefers-reduced-motion: reduce) {
  .marquee--logos { overflow: visible; }
  .marquee--logos .marquee-track { flex-wrap: wrap; justify-content: center; gap: 34px 52px; }
  .client-balloon,
  .client-balloon.is-visible { transform: translate(-50%, -50%); transition: opacity 160ms linear; }
}

/* ------------------------------------------------------------
   6. SECTION COUNTER — índice fixo canto inferior direito
   ------------------------------------------------------------ */
.section-counter {
  position: fixed; right: var(--spacing-20); bottom: var(--spacing-19);
  z-index: 4; pointer-events: none;
  font-size: var(--text-caption); letter-spacing: 0.05em; text-transform: uppercase;
  font-variant-numeric: tabular-nums; color: var(--color-paper-white);
  display: flex; gap: 0.5em; align-items: baseline;
  opacity: 0; transition: opacity 500ms var(--ease-out-soft);
}
.section-counter.is-visible { opacity: 0.7; }
.section-counter .sep { opacity: 0.4; }
.section-counter .total { opacity: 0.4; }

/* ------------------------------------------------------------
   7. MENU OVERLAY — entrada escalonada dos links
   ------------------------------------------------------------ */
.mobile-nav { -webkit-backdrop-filter: blur(14px); backdrop-filter: blur(14px);
  background: color-mix(in srgb, var(--color-black-void) 86%, transparent); }
.mobile-nav a {
  display: flex; align-items: baseline; gap: 0.7em;
  transform: translateX(24px); opacity: 0;
  transition: transform 600ms var(--ease-editorial), opacity 400ms linear;
}
.mobile-nav a::before {
  content: ""; width: 5px; height: 5px; flex: none;
  background: var(--color-paper-white); opacity: 0.6;
  transform: translateY(-0.15em);
}
body.nav-open .mobile-nav a { transform: translateX(0); opacity: 1; }
body.nav-open .mobile-nav a:nth-child(1) { transition-delay: 120ms; }
body.nav-open .mobile-nav a:nth-child(2) { transition-delay: 180ms; }
body.nav-open .mobile-nav a:nth-child(3) { transition-delay: 240ms; }
body.nav-open .mobile-nav a:nth-child(4) { transition-delay: 300ms; }

/* ------------------------------------------------------------
   8. CUSTOM CURSOR — ponto + anel que segue com atraso
   ------------------------------------------------------------ */
.cursor-dot, .cursor-ring {
  position: fixed; top: 0; left: 0; z-index: 350;
  pointer-events: none; border-radius: var(--radius-circular);
  mix-blend-mode: difference;
  translate: -50% -50%;
}
.cursor-dot { width: 5px; height: 5px; background: var(--color-paper-white); }
.cursor-ring {
  width: 34px; height: 34px; border: var(--border-width) solid var(--color-paper-white);
  transition: width 250ms var(--ease-out-soft), height 250ms var(--ease-out-soft), opacity 250ms linear;
}
.cursor-ring.is-hover { width: 58px; height: 58px; }
body.has-cursor { cursor: none; }
body.has-cursor a, body.has-cursor button { cursor: none; }
@media (hover: none), (pointer: coarse) { .cursor-dot, .cursor-ring { display: none; } }

/* ------------------------------------------------------------
   9. REDUCED MOTION — tudo estático e visível
   ------------------------------------------------------------ */
@media (prefers-reduced-motion: reduce) {
  .loader { display: none !important; }
  body.is-loading { overflow: auto; }
  .line-inner, .word-inner { transform: none !important; opacity: 1 !important; transition: none !important; }
  .frame-media img, .frame-media video,
  .hero-media img, .hero-media video {
    filter: none !important; transform: none !important; transition: none !important;
  }
  .hero-media { transform: none !important; }
  .hero-pin { height: auto !important; }
  .hero-pin .hero { position: relative !important; height: 100svh; }
  .masthead .display, .masthead .heading { transform: none !important; }
  .marquee-track { animation: none !important; }
  .hud { display: none !important; }
  .section-counter { opacity: 0.7 !important; }
  .mobile-nav a { transform: none !important; opacity: 1 !important; }
  .cursor-dot, .cursor-ring { display: none !important; }
  body.has-cursor { cursor: auto; }
}

/* Sem JS: nada some */
.no-js .loader { display: none; }
.no-js .line-inner, .no-js .word-inner { transform: none; opacity: 1; }
.no-js .section-counter { display: none; }
.no-js .hud { display: none; }
.no-js .hero-pin { height: auto; }
.no-js .hero-pin .hero { position: relative; }
.no-js .frame-media img, .no-js .frame-media video,
.no-js .hero-media img, .no-js .hero-media video { filter: none; transform: none; }
