/* ================================================================
   Dede Viagens — LINGUAGEM DE MOVIMENTO
   Todo o CSS de animacao do site vive neste arquivo. Nenhuma
   biblioteca externa. Apenas CSS + Web Animations/IntersectionObserver
   em assets/js/motion.js.

   CONCEITO: "A Viagem" e "O Ingresso".
   Todo movimento remete a um destes dois eixos — o deslocamento
   (estrada, rota, embarque, chegada) ou o bilhete (destacar,
   validar, entrar no estadio). Nada de fade-in generico.

   ----------------------------------------------------------------
   AS 14 ASSINATURAS
   ----------------------------------------------------------------
   01 .route-map             Rota de Embarque — traçado SVG desenhado pelo scroll
   02 .ticket                Ingresso Destacavel — canhoto perfurado, entrada 3D
   03 .flap                  Placar Mecanico — digitos girando em rotateX
   04 .sweep                 Refletores do Estadio — varredura de luz continua
   05 .marquee               Faixa Cinetica — velocidade reage ao scroll
   06 [data-boarding]        Embarque Escalonado — entrada em fila, atraso por indice
   07 .site-header           Header Inteligente — encolhe, esconde e volta
   08 .trip-progress         Barra de Progresso da Viagem
   09 .floating-whatsapp     CTA Magnetico — atracao pelo cursor + pulso
   10 .page-curtain          Transicao entre Paginas — cortina de estadio
   11 [data-parallax]        Parallax por Camadas no Hero
   12 .field / .form         Microinteracoes de Formulario — carimbo, shake, cascata
   13 [data-words]           Reveal de Texto por Palavra — mascara vertical
   14 .team-card             Wipe diagonal do acento + profundidade no hover

   ----------------------------------------------------------------
   TOKENS (ajuste aqui para calibrar o site inteiro)
   ----------------------------------------------------------------
   --dv-dur-fast    150ms   microinteracoes (carimbo, chip, hover curto)
   --dv-dur-base    420ms   entradas de card e texto
   --dv-dur-slow    760ms   entradas grandes, cortina, ingresso
   --dv-dur-amb     16s     movimento ambiente (refletores)
   --dv-ease-boarding       curva de embarque: sai rapido, acomoda devagar
   --dv-ease-ticket         curva do ingresso: leve passagem do ponto final
   --dv-ease-exit           curva de saida
   --dv-stagger     70ms    intervalo entre itens de uma fila
   --dv-lift        14px    deslocamento vertical padrao de entrada
   --dv-slide       28px    deslocamento lateral do embarque escalonado

   ----------------------------------------------------------------
   COMO DESATIVAR
   ----------------------------------------------------------------
   • Usuario: ativar "reduzir movimento" no sistema. O bloco
     prefers-reduced-motion no fim deste arquivo converte tudo em
     uma transicao de opacidade de 150ms. Nada some, nada quebra.
   • Site inteiro: remover <link> deste arquivo e o <script> de
     motion.js. O site continua 100% legivel e funcional — todos os
     estados escondidos sao escopados em html.js, entao sem
     JavaScript nada fica preso em opacity:0.
   • Uma assinatura so: adicione data-motion="off" no elemento.
   ================================================================ */

:root{
  --dv-dur-fast:150ms;--dv-dur-base:420ms;--dv-dur-slow:760ms;--dv-dur-amb:16s;
  --dv-ease-boarding:cubic-bezier(.22,.86,.28,1);
  --dv-ease-ticket:cubic-bezier(.34,1.42,.44,1);
  --dv-ease-exit:cubic-bezier(.55,0,.66,.2);
  --dv-stagger:70ms;--dv-lift:14px;--dv-slide:28px;
}

/* Escopo de seguranca: nada fica invisivel se o JS nao rodar.
   O <script> inline no <head> adiciona a classe js no <html>. */
[data-motion="off"]{opacity:1!important;transform:none!important;animation:none!important}

/* ================================================================
   06. EMBARQUE ESCALONADO  —  a entrada padrao do site
   Cards e itens de lista entram como uma fila embarcando no onibus:
   deslocamento lateral curto + subida, com atraso por indice.
   O indice vem de --i, escrito pelo motion.js.
   ================================================================ */
.js [data-boarding]>*{opacity:0;transform:translate3d(calc(var(--dv-slide) * -1),var(--dv-lift),0)}
.js [data-boarding].is-boarding>*{opacity:1;transform:none;transition:opacity var(--dv-dur-base) var(--dv-ease-boarding),transform var(--dv-dur-base) var(--dv-ease-boarding);transition-delay:calc(var(--i,0) * var(--dv-stagger))}
.js [data-boarding="right"]>*{transform:translate3d(var(--dv-slide),var(--dv-lift),0)}
.js [data-boarding="up"]>*{transform:translate3d(0,calc(var(--dv-lift) * 2),0)}

/* Entrada simples para blocos isolados (mesma curva, sem fila) */
.js [data-arrive]{opacity:0;transform:translate3d(0,var(--dv-lift),0)}
.js [data-arrive].is-here{opacity:1;transform:none;transition:opacity var(--dv-dur-base) var(--dv-ease-boarding),transform var(--dv-dur-base) var(--dv-ease-boarding)}
.js [data-arrive="left"]{transform:translate3d(calc(var(--dv-slide) * -1),0,0)}
.js [data-arrive="right"]{transform:translate3d(var(--dv-slide),0,0)}

/* ================================================================
   13. REVEAL DE TEXTO POR PALAVRA
   Mascara vertical: cada palavra sobe de dentro de uma faixa com
   overflow hidden. Palavra por palavra — nunca letra por letra,
   nunca fade puro. Reservado aos H2 principais.
   ================================================================ */
.js [data-words]{--dv-word-stagger:52ms}
.js [data-words] .word{display:inline-block;overflow:hidden;vertical-align:bottom}
.js [data-words] .word>span{display:inline-block;transform:translate3d(0,105%,0)}
.js [data-words].is-read .word>span{transform:none;transition:transform var(--dv-dur-slow) var(--dv-ease-boarding);transition-delay:calc(var(--w,0) * var(--dv-word-stagger))}

/* ================================================================
   02. INGRESSO DESTACAVEL
   O card de jogo entra como um bilhete sendo apresentado: leve
   rotacao 3D no eixo X. No hover o canhoto "destaca" — desloca e
   ganha sombra. No clique/foco, um flash rapido de validado.
   A borda perfurada e feita com radial-gradient (ver style.css).
   ================================================================ */
.js .ticket{perspective:1100px}
.js [data-boarding] .ticket{transform-origin:50% 0}
.js [data-boarding]>.ticket{opacity:0;transform:translate3d(0,var(--dv-lift),0) rotateX(-9deg)}
.js [data-boarding].is-boarding>.ticket{opacity:1;transform:none;transition:opacity var(--dv-dur-base) var(--dv-ease-boarding),transform var(--dv-dur-slow) var(--dv-ease-ticket);transition-delay:calc(var(--i,0) * var(--dv-stagger))}
.ticket-stub{transition:transform var(--dv-dur-base) var(--dv-ease-ticket),box-shadow var(--dv-dur-base) ease}
.ticket:hover .ticket-stub,.ticket:focus-within .ticket-stub{transform:translate3d(0,4px,0);box-shadow:0 -10px 26px rgba(11,31,58,.1)}
.ticket-validate{position:absolute;z-index:5;inset:0;border-radius:inherit;background:linear-gradient(115deg,transparent 34%,rgba(0,194,95,.45) 50%,transparent 66%);opacity:0;pointer-events:none}
.ticket.is-validated .ticket-validate{animation:dv-validate 560ms var(--dv-ease-exit) 1}
@keyframes dv-validate{0%{opacity:0;transform:translate3d(-60%,0,0)}22%{opacity:1}100%{opacity:0;transform:translate3d(60%,0,0)}}

/* ================================================================
   03. PLACAR MECANICO (split-flap)
   Cada digito gira em rotateX como um painel de aeroporto. O
   escalonamento por digito e feito com --d, escrito pelo motion.js.
   ================================================================ */
.flap-digit{display:inline-block;backface-visibility:hidden}
.js .flap:not(.is-settled) .flap-digit{animation:dv-flap 480ms var(--dv-ease-boarding) both;animation-delay:calc(var(--d,0) * 60ms)}
@keyframes dv-flap{
  0%{transform:rotateX(-92deg) translate3d(0,-4px,0);opacity:0}
  55%{transform:rotateX(16deg);opacity:1}
  78%{transform:rotateX(-7deg)}
  100%{transform:none;opacity:1}
}

/* ================================================================
   04. REFLETORES DO ESTADIO (light sweep)
   Varredura conica lenta atras do conteudo. Continua, quase
   imperceptivel, com grao sutil por cima. O motion.js pausa a
   animacao quando a aba esta oculta ou o bloco sai da viewport.
   ================================================================ */
.sweep{position:relative;isolation:isolate}
.sweep-light{position:absolute;z-index:-1;inset:-30%;pointer-events:none;opacity:.5;background:conic-gradient(from 0deg at 62% 34%,transparent 0deg,rgba(255,255,255,.13) 26deg,transparent 62deg,transparent 180deg,rgba(0,194,95,.11) 214deg,transparent 258deg,transparent 360deg);animation:dv-sweep var(--dv-dur-amb) linear infinite;will-change:transform}
.sweep-light-warm{background:conic-gradient(from 0deg at 40% 60%,transparent 0deg,rgba(255,196,0,.12) 30deg,transparent 70deg,transparent 200deg,rgba(255,255,255,.1) 236deg,transparent 280deg,transparent 360deg);animation-duration:20s;animation-direction:reverse}
.sweep.is-paused .sweep-light{animation-play-state:paused}
@keyframes dv-sweep{to{transform:rotate(360deg)}}

/* ================================================================
   05. FAIXA CINETICA DE DESTINOS
   Rolagem continua movida por requestAnimationFrame. A direcao e a
   velocidade respondem a direcao do scroll do usuario. No hover, o
   item sob o cursor cresce e os vizinhos recuam.
   ================================================================ */
.marquee-track{transform:translate3d(0,0,0)}
.marquee:hover .marquee-item{color:rgba(255,255,255,.28);transform:scale(.94)}
.marquee-light:hover .marquee-item{color:rgba(11,31,58,.16)}
.marquee .marquee-item.is-near{color:rgba(255,255,255,.85);transform:scale(1.02)}
.marquee-light .marquee-item.is-near{color:rgba(11,31,58,.6)}
.marquee .marquee-item.is-hot{color:#fff;transform:scale(1.12)}
.marquee-light .marquee-item.is-hot{color:var(--navy)}

/* ================================================================
   01. ROTA DE EMBARQUE (scroll-drawn route)
   O traco ES -> Rio e desenhado conforme a pagina rola. Usa
   stroke-dashoffset — unica propriedade animada fora de
   transform/opacity em todo o site, e a unica forma real de
   "desenhar" um caminho SVG. Nao gera reflow de layout: o repaint
   fica contido no proprio SVG.
   Se o navegador suportar animation-timeline: view(), o desenho e
   feito pelo compositor, sem JavaScript nenhum.
   ================================================================ */
.route-path-live{stroke-dasharray:var(--dv-route-len,1400);stroke-dashoffset:var(--dv-route-len,1400)}
.route-pin circle{transform:scale(.7);opacity:.5;transition:transform var(--dv-dur-base) var(--dv-ease-ticket),opacity var(--dv-dur-base) ease,fill var(--dv-dur-base) ease}
.route-pin.is-lit circle{transform:scale(1);opacity:1}
.route-pin text{opacity:.45;transition:opacity var(--dv-dur-base) ease}
.route-pin.is-lit text{opacity:1}
.route-bus{opacity:0;transition:opacity var(--dv-dur-base) ease}
.route-map.is-drawing .route-bus{opacity:1}
@supports (animation-timeline: view()){
  .js .route-map[data-native-scroll] .route-path-live{animation:dv-draw linear both;animation-timeline:view();animation-range:entry 22% cover 62%}
}
@keyframes dv-draw{to{stroke-dashoffset:0}}

/* ================================================================
   07. HEADER INTELIGENTE
   Encolhe e ganha fundo solido ao rolar. Some ao descer, volta ao
   subir — sempre em transform, nunca em display.

   POR QUE NADA AQUI ANIMA LAYOUT
   A versao anterior encolhia o logo animando `width` e os links
   animando `padding`, com o header em `position: sticky`. Como o
   header sticky ocupa espaco no fluxo, encolher empurrava a pagina
   inteira ~16px para cima; isso mudava a posicao de scroll, que
   reentrava no limite do `is-stuck`, que encolhia de novo — a barra
   travava e piscava no scroll do mouse.
   Correcao em tres frentes:
     1. header `position: fixed` (o body compensa com padding-top),
        entao encolher nao reflui mais nada;
     2. o logo encolhe com `transform: scale()`, no compositor;
     3. o motion.js usa histerese nos dois limites (ver initHeader).
   ================================================================ */
.site-header{transition:transform 380ms var(--dv-ease-boarding),background 280ms ease,box-shadow 280ms ease,height 260ms var(--dv-ease-boarding)}
.site-header.is-stuck{background:rgba(255,255,255,.97);box-shadow:0 6px 26px rgba(11,31,58,.09)}
.site-header.is-hidden{transform:translate3d(0,-100%,0)}
.header-inner{transition:height 260ms var(--dv-ease-boarding)}
.is-stuck .header-inner{height:calc(var(--header-h) - 14px)}
.brand img{transition:transform 300ms var(--dv-ease-boarding)}
.is-stuck .brand img{transform:scale(.82)}

/* ================================================================
   08. BARRA DE PROGRESSO DA VIAGEM
   O trajeto percorrido da pagina, com o marcador deslizando junto.
   Escala em X — sem animar width.
   ================================================================ */
.trip-progress-bar{transition:transform 90ms linear}
@supports (animation-timeline: scroll()){
  .js .trip-progress[data-native-scroll] .trip-progress-bar{transition:none;animation:dv-progress linear both;animation-timeline:scroll(root block)}
}
@keyframes dv-progress{from{transform:scaleX(0)}to{transform:scaleX(1)}}

/* ================================================================
   09. CTA MAGNETICO DE WHATSAPP
   No desktop o botao reage a proximidade do cursor (max. 6px). Se o
   usuario ficar 8s parado, um pulso lento e discreto chama atencao.
   No mobile, so o pulso.
   ================================================================ */
.floating-whatsapp{transition:transform 260ms var(--dv-ease-boarding),background .22s}
.floating-whatsapp:before{content:"";position:absolute;inset:0;border-radius:inherit;background:var(--green);opacity:0;z-index:-1}
.floating-whatsapp.is-calling:before{animation:dv-pulse 2.6s var(--dv-ease-boarding) infinite}
@keyframes dv-pulse{0%{opacity:.5;transform:scale(1)}70%{opacity:0;transform:scale(1.42)}100%{opacity:0;transform:scale(1.42)}}

/* ================================================================
   10. TRANSICAO ENTRE PAGINAS
   Cortina de estadio: sobe ao sair, desce ao entrar. 250ms. Se o JS
   falhar, a cortina nunca aparece e a navegacao segue normal.
   ================================================================ */
.page-curtain{transition:transform 250ms var(--dv-ease-exit)}
.page-curtain.is-leaving{transform:scaleY(1)}
.page-curtain.is-arriving{transform:scaleY(0);transform-origin:50% 0;transition-timing-function:var(--dv-ease-boarding)}

/* ================================================================
   11. PARALLAX POR CAMADAS NO HERO
   Tres camadas, velocidades diferentes, deslocamento curto para nao
   gerar enjoo nem CLS. Desligado abaixo de 768px pelo motion.js.
   ================================================================ */
[data-parallax]{will-change:transform}
.hero-bg,.hero-plate,.hero-badge{transform:translate3d(0,0,0)}

/* ================================================================
   12. MICROINTERACOES DE FORMULARIO
   Carimbo de validado, shake horizontal curto no erro (nunca
   vermelho piscando) e cascata nas opcoes do select customizado.
   ================================================================ */
.field-stamp{transform:scale(.4) rotate(-18deg);transition:opacity var(--dv-dur-fast) ease,transform var(--dv-dur-fast) var(--dv-ease-ticket)}
.field.is-valid .field-stamp{opacity:1;transform:none}
.field.has-error{animation:dv-shake 380ms var(--dv-ease-boarding) 1}
@keyframes dv-shake{0%,100%{transform:none}18%{transform:translate3d(-6px,0,0)}38%{transform:translate3d(5px,0,0)}58%{transform:translate3d(-3px,0,0)}78%{transform:translate3d(2px,0,0)}}
.field input,.field select,.field textarea{transition:border-color .2s,box-shadow .2s,transform var(--dv-dur-fast) var(--dv-ease-boarding)}
.field input:focus,.field select:focus,.field textarea:focus{transform:translate3d(0,-1px,0)}
.js .board-select .bs-option{opacity:0;transform:translate3d(0,-6px,0)}
.js .board-select.is-open .bs-option{opacity:1;transform:none;transition:opacity 180ms var(--dv-ease-boarding),transform 180ms var(--dv-ease-boarding);transition-delay:calc(var(--o,0) * 26ms)}

/* ================================================================
   14. ESTADOS DE HOVER DOS CARDS DE TIME
   A cor de acento entra num wipe diagonal e o conteudo ganha
   profundidade. Cores genericas de acento — a identidade real vem
   da foto do card.
   ================================================================ */
.team-card{transition:transform var(--dv-dur-base) var(--dv-ease-boarding),box-shadow var(--dv-dur-base) ease}
.team-card-accent{clip-path:polygon(0 100%,0 100%,0 100%,0 100%);opacity:.72;transition:clip-path 560ms var(--dv-ease-boarding)}
.team-card:hover,.team-card:focus-visible{transform:translate3d(0,-6px,0);box-shadow:var(--shadow-card)}
.team-card:hover .team-card-accent,.team-card:focus-visible .team-card-accent{clip-path:polygon(0 -20%,120% -20%,120% 120%,0 120%)}
.team-card>img{transition:transform 620ms var(--dv-ease-boarding)}
.team-card:hover>img{transform:scale(1.07)}
.team-card-crest,.team-card h3,.team-card p,.team-card b{transition:transform var(--dv-dur-base) var(--dv-ease-boarding)}
.team-card:hover .team-card-crest{transform:translate3d(0,-5px,0) scale(1.06)}
.team-card:hover h3,.team-card:hover p{transform:translate3d(0,-3px,0)}

/* --- Microinteracoes gerais coerentes com a linguagem --- */
.chip,.tag{transition:transform var(--dv-dur-fast) var(--dv-ease-boarding),border-color .2s,background .2s,color .2s}
.info-card i svg,.button svg{transition:transform var(--dv-dur-base) var(--dv-ease-ticket)}
.button:hover svg{transform:translate3d(2px,0,0)}
.faq-answer{overflow:hidden}
.js .faq-item[open] .faq-answer{animation:dv-unfold 320ms var(--dv-ease-boarding) both}
@keyframes dv-unfold{from{opacity:0;transform:translate3d(0,-8px,0)}to{opacity:1;transform:none}}

/* ================================================================
   PREFERS-REDUCED-MOTION — obrigatorio
   Todo movimento vira uma transicao de opacidade de 150ms. Nada
   some, nada fica preso fora da tela, nada quebra.
   ================================================================ */
@media(prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  *,*:before,*:after{
    animation-duration:1ms!important;animation-iteration-count:1!important;
    transition-duration:150ms!important;transition-property:opacity,background-color,border-color,color!important;
    scroll-behavior:auto!important
  }
  .js [data-boarding]>*,.js [data-arrive],.js [data-boarding]>.ticket{transform:none!important}
  .js [data-words] .word>span{transform:none!important}
  .js [data-boarding].is-boarding>*,.js [data-arrive].is-here{transition-delay:0ms!important}
  .sweep-light,.marquee-track{animation:none!important;transform:none!important}
  .route-path-live{stroke-dashoffset:0!important}
  .route-pin circle{transform:none!important;opacity:1!important}
  .site-header.is-hidden{transform:none!important}
  .page-curtain{display:none!important}
  .floating-whatsapp,.team-card,.ticket-stub,.field-stamp{transform:none!important}
  .team-card-accent{clip-path:none!important;opacity:0!important}
  .field.has-error{animation:none!important}
  [data-parallax]{transform:none!important}
}
