/* ==========================================================================
   Rhoven — Movimento cinemático
   Momentos fortes do site: hero que se abre, manifesto palavra a palavra,
   método como jornada e cards que respondem ao cursor.

   ---------------------------------------------------------------------------
   COMO ESTE ARQUIVO FUNCIONA — leia antes de mexer
   ---------------------------------------------------------------------------
   Tudo aqui é ANIMAÇÃO LIGADA À ROLAGEM (scroll-driven animation) nativa do
   CSS: `view-timeline` publica o progresso de um elemento pela tela e as
   animações consomem esse progresso em vez de tempo. Não há biblioteca, não
   há listener de scroll, não há requestAnimationFrame — o compositor do
   navegador roda isso fora da thread principal, então não engasga.

   Três guardas cercam CADA bloco cinemático, e nenhuma é opcional:

     @supports (animation-timeline: view())   navegador antigo ignora tudo e
                                              fica com o site anterior intacto
     @media (min-width: …)                    o efeito só existe onde há espaço
     @media (prefers-reduced-motion: no-preference)

   A terceira guarda é a mais importante e é o motivo de ela aparecer aqui em
   vez de um bloco `reduce` no fim do arquivo: quando uma animação ligada à
   rolagem recebe `animation-duration` explícita — e a regra global de
   movimento reduzido, em base.css, força `.01ms !important` em TUDO — o
   navegador trata essa duração como uma FRAÇÃO do percurso e a animação salta
   direto para o último quadro. No hero, o último quadro é o texto já
   desvanecido: quem pede menos movimento receberia um hero em branco. Por
   isso o movimento reduzido nunca entra nestes blocos — ele simplesmente não
   os ativa, e o layout estático de paginas.css continua valendo.
   ========================================================================== */


/* ==========================================================================
   1. BARRA DE PROGRESSO DA PÁGINA
   Fio de 2px na base do header que acompanha a leitura. É o único elemento
   novo permanentemente na tela, e por isso é o mais discreto possível.
   ========================================================================== */

.cabecalho__progresso {
  position: absolute;
  left: 0;
  bottom: -1px;
  height: 2px;
  width: 100%;
  background: linear-gradient(90deg, var(--laranja), var(--laranja-escuro));
  transform: scaleX(0);
  transform-origin: left center;
  pointer-events: none;
}

@supports (animation-timeline: scroll()) {
  @media (prefers-reduced-motion: no-preference) {
    .cabecalho__progresso {
      animation: progresso-rolagem linear;
      animation-timeline: scroll(root block);
    }
  }
}

@keyframes progresso-rolagem {
  from {
    transform: scaleX(0);
  }

  to {
    transform: scaleX(1);
  }
}


/* ==========================================================================
   2. HERO — vídeo de fundo, SEM efeito de rolagem
   O efeito cinemático (o hero prendia a tela e o vídeo abria de blob a
   sangria conforme a rolagem) foi REMOVIDO a pedido: preferiu-se o hero
   parado, com o vídeo tocando ao fundo sob a máscara radial de paginas.css —
   o mesmo enquadramento do comparar.html.

   O que sobra aqui é só o invólucro do vídeo. O .hero-palco continua no HTML
   como um <div> em volta da seção, mas agora é inerte (altura automática).
   Os outros momentos cinemáticos — manifesto, método, cards — seguem intactos
   nos blocos abaixo; só o do hero saiu.
   ========================================================================== */

.hero-palco {
  position: relative;
}

/* Envolve o vídeo dentro de .hero__midia, que é quem aplica a máscara radial
   (paginas.css). Sem esta moldura o object-fit do vídeo não teria caixa. */
.hero__moldura {
  position: absolute;
  inset: 0;
  overflow: hidden;
}

.hero__moldura video {
  width: 100%;
  height: 100%;
  object-fit: cover;
}


/* ==========================================================================
   3. MANIFESTO PALAVRA A PALAVRA
   A frase central do posicionamento se acende palavra por palavra conforme
   a pessoa rola. É o texto que carrega o argumento inteiro da agência —
   revelá-lo aos poucos faz o olho lê-lo de fato, em vez de varrê-lo.

   O JS (movimento.js) quebra a frase em <span class="palavra">, numera cada
   uma em --i e publica o total em --n. Sem JS, não há spans: a frase é uma
   frase comum e nada disto se aplica.
   ========================================================================== */

.palavra {
  display: inline-block;
  /* Repouso em 28%, não em 0: mesmo no meio da revelação o texto continua
     legível. Uma palavra invisível é um buraco na frase para quem chegou
     de teclado, de leitor de tela ou simplesmente parou de rolar ali. */
  opacity: .28;
  will-change: opacity, transform;
}

.texto-destaque .palavra,
.destaque .palavra,
span.destaque .palavra,
span.texto-destaque .palavra {
  background-image: linear-gradient(120deg, #FF7A28 0%, #F45A00 40%, #FFB380 65%, #FF7A28 100%) !important;
  background-size: 200% auto !important;
  background-clip: text !important;
  -webkit-background-clip: text !important;
  -webkit-text-fill-color: transparent !important;
  color: transparent !important;
  animation: gradiente-texto 6s ease-in-out infinite !important;
  filter: drop-shadow(0 0 16px rgba(255, 122, 40, .45)) !important;
  display: inline-block !important;
  opacity: 1 !important;
}

/* --- Versão com scrub (a boa): a revelação segue o dedo na rolagem ------- */

@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .frase-cinema {
      view-timeline-name: --frase;
      view-timeline-axis: block;
    }

    .frase-cinema .palavra {
      animation: acende-palavra linear both;
      animation-timeline: --frase;
      /* Cada palavra ocupa uma fatia distinta do percurso: a i-ésima de n
         começa proporcionalmente mais tarde. A janela de cada uma (12%) é
         maior que o passo entre elas, então as revelações se sobrepõem e o
         efeito lê como onda, não como letreiro piscando item a item. */
      animation-range:
        cover calc(24% + (var(--i) / var(--n)) * 26%)
        cover calc(36% + (var(--i) / var(--n)) * 26%);
    }

    @keyframes acende-palavra {
      from {
        opacity: .28;
        transform: translateY(.16em);
      }

      to {
        opacity: 1;
        transform: none;
      }
    }
  }
}

/* --- Fallback: mesma leitura, disparada por IntersectionObserver ---------
   Navegador sem scroll-driven animation recebe a mesma cascata, só que
   por tempo em vez de por rolagem. A classe .visivel já é posta pelo
   observador que o site sempre teve. */

@supports not (animation-timeline: view()) {
  .frase-cinema .palavra {
    transform: translateY(.16em);
    transition:
      opacity 620ms var(--facil-forte),
      transform 620ms var(--facil-forte);
    transition-delay: calc(var(--i) * 42ms);
  }

  .frase-cinema.visivel .palavra {
    opacity: 1;
    transform: none;
  }
}

/* Quem pede menos movimento lê a frase inteira, acesa, de uma vez. */
@media (prefers-reduced-motion: reduce) {
  .palavra {
    opacity: 1;
    transform: none;
    transition: none;
  }
}


/* ==========================================================================
   4. MÉTODO COMO JORNADA
   A seção prende a tela por pouco mais de uma rolagem e os quatro passos
   avançam um a um, com a linha tracejada se desenhando entre eles.

   "Pode, mas curto" foi decisão explícita: o palco tem 260vh, ou seja, 160vh
   de tela presa. Esticar isso é o caminho mais rápido para o visitante achar
   que a página travou. No celular nada disto roda — a grade vira uma coluna
   e os passos usam a revelação normal.
   ========================================================================== */

.metodo-palco {
  position: relative;
}

@supports (animation-timeline: view()) {
  /* min-height é guarda de segurança medida, não estética: o quadro preso
     tem `100vh - header` de altura e os quatro passos ocupam ~550px numa
     tela de 1280px de largura. Numa janela de 700px de altura sobram 616px
     — margem estreita demais, e um passo com uma linha a mais de texto
     transbordaria o quadro por cima da seção seguinte. A 760px o conteúdo
     cabe com folga; abaixo disso a seção volta a ser uma grade rolável. */
  @media (min-width: 981px) and (min-height: 760px) and (prefers-reduced-motion: no-preference) {

    /* Sem padding na seção: quem dá o respiro vertical agora é o quadro
       preso, que ocupa a tela inteira e centraliza o conteúdo. */
    .metodo {
      padding-block: 0;
    }

    .metodo-palco {
      height: 260vh;
      view-timeline-name: --metodo;
      view-timeline-axis: block;
    }

    .metodo-quadro {
      position: sticky;
      top: var(--altura-header);
      display: flex;
      align-items: center;
      height: calc(100vh - var(--altura-header));
    }

    .metodo-quadro > .container {
      width: 100%;
    }

    /* A revelação padrão sairia disputando opacidade e transform com a
       animação de rolagem. Ela é desligada aqui e a jornada assume. */
    .js .metodo__passo.revelar,
    .js .metodo__passo.revelar.visivel {
      opacity: 1;
      transform: none;
      filter: none;
      transition: none;
    }

    .metodo__passo {
      animation: passo-entra linear both;
      animation-timeline: --metodo;
      /* Quatro entradas de 24% cada, espaçadas de 18%: elas se sobrepõem,
         então a cena flui em vez de avançar aos trancos. A última assenta
         em 86% e sobram 14% de percurso com os quatro passos montados,
         antes de a tela ser liberada. Sem essa folga, o quarto passo
         terminaria de entrar no exato instante em que a seção se solta e
         ninguém chegaria a lê-lo. */
      animation-range:
        contain calc(8% + var(--i) * 18%)
        contain calc(32% + var(--i) * 18%);
    }

    @keyframes passo-entra {
      from {
        opacity: 0;
        transform: translateY(38px) scale(.96);
        filter: blur(5px);
      }

      to {
        opacity: 1;
        transform: none;
        filter: blur(0);
      }
    }

    /* O selo numerado chega girando um pouco além do lugar e volta —
       assenta em vez de aparecer. */
    .metodo__selo {
      animation: selo-assenta linear both;
      animation-timeline: --metodo;
      animation-range:
        contain calc(8% + var(--i) * 18%)
        contain calc(24% + var(--i) * 18%);
    }

    @keyframes selo-assenta {
      from {
        transform: scale(.6) rotate(-14deg);
      }

      to {
        transform: scale(1) rotate(0deg);
      }
    }

    /* A trilha sólida se desenha por cima da tracejada, à frente dos passos:
       é ela que conduz o olho de um selo ao próximo. Termina junto com o
       último passo (86%).

       O seletor precisa de `path.` e do `.js` por causa da regra
       `.js .metodo__linha path { animation: flui-traco … }`, em paginas.css,
       que casa com AMBOS os caminhos do SVG. Com o seletor simples esta
       regra perdia por especificidade e o traço de avanço saía marchando
       tracejado em vez de se desenhar. */
    .js .metodo__linha path.metodo__linha-avanco {
      animation: desenha-avanco linear both;
      animation-timeline: --metodo;
      animation-range: contain 8% contain 82%;
    }

    @keyframes desenha-avanco {
      from {
        stroke-dashoffset: 1;
      }

      to {
        stroke-dashoffset: 0;
      }
    }
  }
}

/* Traço sólido que marca o avanço. Fica escondido (dashoffset 1) até a
   animação acontecer; fora do modo jornada ele nunca é desenhado, e a
   linha tracejada original continua sendo a única visível.

   `path.` no seletor é obrigatório: `.metodo__linha path`, em paginas.css,
   impõe o tracejado `.006 .024` a qualquer caminho dentro do SVG. Sem
   ganhar essa disputa, o traço de avanço nasceria tracejado — dois
   tracejados sobrepostos, e nenhuma linha sólida para conduzir o olho. */
.metodo__linha path.metodo__linha-avanco {
  fill: none;
  stroke: var(--laranja);
  stroke-width: 2.5;
  stroke-linecap: round;
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
}


/* ==========================================================================
   5. CARDS QUE RESPONDEM AO CURSOR
   Os cards de serviço, as especialidades e os depoimentos ganham um foco de
   luz que segue o mouse e uma inclinação de poucos graus. O JS publica a
   posição do ponteiro em --mx/--my (percentual, para o brilho) e --mx-n/
   --my-n (0 a 1, para a inclinação).

   A inclinação é de 4 a 6 graus de propósito. Acima disso o card deixa de
   parecer um objeto sobre a mesa e passa a parecer um adesivo balançando —
   é o erro que faz efeito de cursor parecer amador.
   ========================================================================== */

.servicos-grade,
.especialidades,
.depoimentos {
  perspective: 1400px;
}

.card-servico,
.especialidade,
.depoimento {
  /* Cria contexto de empilhamento próprio para o brilho poder ficar ACIMA
     do fundo do card e ABAIXO do texto (z-index -1 dentro do isolamento). */
  isolation: isolate;
  transform-style: preserve-3d;
}

.card-servico::before,
.especialidade::before,
.depoimento::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  background: radial-gradient(340px circle at var(--mx, 50%) var(--my, 0%),
      rgba(244, 90, 0, .13), transparent 64%);
  opacity: 0;
  transition: opacity var(--transicao);
  pointer-events: none;
}

.card-servico,
.especialidade {
  position: relative;
}

.card-servico:hover::before,
.especialidade:hover::before,
.depoimento:hover::before {
  opacity: 1;
}

/* Sobre o card carvão o laranja translúcido some. Ali o foco de luz é
   branco, que é o que se destaca sobre escuro. */
.card-servico--destaque::before {
  background: radial-gradient(340px circle at var(--mx, 50%) var(--my, 0%),
      rgba(255, 255, 255, .10), transparent 64%);
}

/* A inclinação entra junto com a subida que os cards já tinham. Sem
   ponteiro fino (celular, tablet) nada disto se aplica: hover em toque
   gruda e o card ficaria torto até o próximo toque. */
@media (hover: hover) and (pointer: fine) and (prefers-reduced-motion: no-preference) {

  .card-servico,
  .especialidade,
  .depoimento {
    transition:
      transform 380ms var(--facil-forte),
      box-shadow var(--transicao),
      border-color var(--transicao);
  }

  .card-servico:hover,
  .especialidade:hover,
  .depoimento:hover {
    transform:
      translateY(-8px)
      rotateX(calc((var(--my-n, .5) - .5) * -5deg))
      rotateY(calc((var(--mx-n, .5) - .5) * 6deg));
  }

  /* O ícone sai do plano do card: é o que dá a profundidade real da
     inclinação. Sem isto, o card inteiro gira como uma figurinha chapada. */
  .card-servico__icone,
  .especialidade__icone {
    transition: transform 380ms var(--facil-forte);
  }

  .card-servico:hover .card-servico__icone,
  .especialidade:hover .especialidade__icone {
    transform: translateZ(38px) scale(1.06);
  }
}


/* ==========================================================================
   6. APOIO — o movimento que costura o resto da página
   Nada aqui é um "momento": são deslocamentos pequenos que impedem a página
   de parecer uma pilha de blocos parados entre um pico e outro.
   ========================================================================== */

@supports (animation-timeline: view()) {
  @media (min-width: 768px) and (prefers-reduced-motion: no-preference) {

    /* Paralaxe das composições de blob: elas sobem mais devagar que a
       página, então o fundo ganha profundidade sem nenhum elemento novo. */
    .sobre__marca,
    .contato__marca {
      animation: paralaxe-marca linear both;
      animation-timeline: view(block);
      animation-range: cover 0% cover 100%;
    }

    @keyframes paralaxe-marca {
      from {
        translate: 0 8%;
      }

      to {
        translate: 0 -8%;
      }
    }

    /* O rótulo de seção desliza junto com o traço que o acompanha. */
    .rotulo {
      animation: rotulo-entra linear both;
      animation-timeline: view(block);
      animation-range: entry 10% entry 90%;
    }

    @keyframes rotulo-entra {
      from {
        opacity: 0;
        translate: -14px 0;
      }

      to {
        opacity: 1;
        translate: 0 0;
      }
    }

    /* A faixa de números se aproxima levemente ao entrar — a única seção
       escura do meio da página merece um acento próprio. */
    .numeros__grade {
      animation: numeros-aproxima linear both;
      animation-timeline: view(block);
      animation-range: entry 0% entry 85%;
    }

    @keyframes numeros-aproxima {
      from {
        scale: .94;
        opacity: .3;
      }

      to {
        scale: 1;
        opacity: 1;
      }
    }

    /* --- ANIMAÇÃO DA LINHA DO TEMPO (REDES) --- */
    .cronograma__linha-avanco {
      height: 0%; /* Reseta para animar no scroll */
      animation: avanco-linha linear both;
      animation-timeline: view(block);
      animation-range: entry 15% exit 80%;
    }

    @keyframes avanco-linha {
      from {
        height: 0%;
      }
      to {
        height: 100%;
      }
    }

    /* Animação dos bullets ao rolar */
    .cronograma__item {
      view-timeline-name: --item-scroll;
      view-timeline-axis: block;
    }

    .cronograma__bullet {
      background: rgba(255, 255, 255, .25); /* Sobrescreve o laranja padrão */
      box-shadow: none;
      animation: acender-bullet linear both;
      animation-timeline: --item-scroll;
      animation-range: entry 90% contain 40%;
    }

    @keyframes acender-bullet {
      from {
        background: rgba(255, 255, 255, .25);
        box-shadow: none;
        transform: scale(1);
      }
      to {
        background: var(--laranja-80);
        box-shadow: 0 0 12px var(--laranja-80);
        transform: scale(1.35);
      }
    }
  }
}

/* --- ENTRADA 3D EM CASCATA DOS CARDS DO CRONOGRAMA --- */
.js .cronograma__item.revelar {
  opacity: 0;
  transform: translateY(32px) rotateX(-12deg) rotateY(6deg);
  filter: blur(8px);
  transform-origin: center top;
  transition: 
    opacity 1000ms var(--facil-forte),
    transform 1000ms var(--facil-forte),
    filter 1000ms var(--facil-forte);
}

.js .cronograma__item.revelar.visivel {
  opacity: 1;
  transform: none;
  filter: none;
}
