/* ============================================================================
   BG MÍDIA · DEVCODE OS · FASE 4 (SOAP) · Camada de movimento
   ----------------------------------------------------------------------------
   ADITIVIDADE À PROVA DE FALHA
   Todo estado inicial (opacity 0, translate) está TRAVADO atrás do seletor
   [data-motion="full"], que só é escrito no <html> pelo init.js do SOAP.
   Se o JavaScript falhar, não carregar ou for bloqueado, nenhum elemento fica
   invisível: a página aparece exatamente como o ATELIER a construiu.

   PARA DESATIVAR TODA A CAMADA VISUAL: remover o <link> deste arquivo.

   ZONAS DE EXCLUSÃO (Kernel §4): nenhuma regra aqui alcança .dc-bot-* nem
   <footer>. O CONCIERGE e o FOOTER têm motion próprio e escopado.
   ========================================================================== */

/* ---------------------------------------------------------------------------
   1 · TOKENS DE MOVIMENTO
   Ampliam os tokens do ATELIER, não os substituem. As micro-interações de
   hover e foco continuam usando --duration-fast e --ease-out do styles.css.
   --------------------------------------------------------------------------- */
:root {
  /* ESCALA DE DURAÇÃO · quatro degraus e um teto que ninguém passa.
     Era 200 / 350 / 620 / 900. O reveal levava 620ms e, somado ao stagger,
     o último cartão de um grupo só terminava de entrar aos 920ms. O split do
     H1 levava 900ms por palavra: com oito palavras, o título só ficava
     completo 1,28s depois de a página aparecer. Movimento longo não é calmo,
     é lento. Calmo é chegar sem susto e sair do caminho.

     --soap-d-follow é o único abaixo do degrau micro, e de propósito: tilt e
     botão magnético seguem o cursor, e transição mais longa que o intervalo
     entre duas amostras do ponteiro faz o elemento parecer preso em borracha. */
  --soap-d-follow:  90ms;
  --soap-d-micro:  120ms;
  --soap-d-short:  320ms;   /* entrada de superfície grande */
  --soap-d-medium: 480ms;   /* teto absoluto, uso raro      */
  --soap-d-long:   480ms;   /* mantido como apelido: mesmo teto */

  --soap-e-enter:  cubic-bezier(0.16, 1, 0.3, 1);      /* out expo   */
  --soap-e-gentle: cubic-bezier(0.22, 1, 0.36, 1);     /* out quint  */
  --soap-e-smooth: cubic-bezier(0.45, 0, 0.55, 1);     /* in-out sine */

  --soap-dist-small:  16px;
  --soap-dist-medium: 28px;
  --soap-dist-large:  44px;
}

/* ---------------------------------------------------------------------------
   2 · REVEAL DE SCROLL
   Aplicado pelo JS a partir do mapa de seletores em motion-tokens.js.

   POR QUE `translate` E `scale` EM VEZ DE `transform`
   Os mesmos elementos que recebem reveal também recebem tilt (cards de ponto,
   de pacote e de processo) e parallax (mídia do hero). Se as duas camadas
   escrevessem em `transform`, a última do arquivo venceria e o reveal nunca
   rodaria no desktop. As propriedades individuais `translate` e `scale` são
   compostas ANTES de `transform` pelo navegador, então as duas camadas
   coexistem sem disputar a mesma declaração.

   Navegador sem suporte a `translate` individual ignora a linha e o elemento
   ainda entra em fade. Degradação suave, nada quebra.
   --------------------------------------------------------------------------- */
[data-motion="full"] .soap-reveal {
  opacity: 0;
  translate: 0 var(--soap-dist-medium);
  /* `scale` saiu da lista junto com a variante que o usava: transição
     declarada para propriedade que ninguém anima é trabalho que o navegador
     agenda e joga fora. */
  transition:
    opacity   var(--soap-d-medium) var(--soap-e-enter) var(--soap-delay, 0ms),
    translate var(--soap-d-medium) var(--soap-e-enter) var(--soap-delay, 0ms);
}

[data-motion="full"] .soap-reveal.is-visible {
  opacity: 1;
  translate: none;
}

/* Variantes.
   `scale` saiu em 14/08. Atendia um único seletor (.pacotes__grid > li) e
   custava um vocabulário inteiro de movimento a mais na página: os cards de
   pacote cresciam enquanto tudo em volta subia. */
[data-motion="full"] .soap-reveal[data-soap="fade"] { translate: none; }

/* ⚠️ VARIANTES HORIZONTAIS · a causa do corte lateral relatado três vezes.
   `left` e `right` são aplicados a .sobre__media, .sobre__content,
   .decisao__pitch e .form-card. Abaixo de 900px esses quatro blocos ocupam a
   largura INTEIRA do container, porque .sobre__inner e .decisao__inner só
   viram duas colunas em @media (min-width: 900px).

   Deslocar 44px na horizontal um bloco que já ocupa toda a largura não é
   animação: é garantia de corte. Enquanto o elemento espera a vez de aparecer,
   e durante os 620ms da transição, o conteúdo fica 44px fora do lugar. Quem
   rolava a página no celular pegava o texto cortado à esquerda (variante
   `left`) ou à direita (variante `right`), exatamente como nos prints.

   Não aparecia como barra de rolagem porque o body tem overflow-x: clip.

   Abaixo de 900px as duas viram verticais, que é o único eixo em que um bloco
   de largura total pode se mover sem sair da caixa. Acima de 900px, onde há
   duas colunas e sobra de viewport, o efeito direcional continua. */
[data-motion="full"] .soap-reveal[data-soap="left"],
[data-motion="full"] .soap-reveal[data-soap="right"] {
  translate: 0 var(--soap-dist-medium);
}

@media (min-width: 900px) {
  [data-motion="full"] .soap-reveal[data-soap="left"]  { translate: calc(var(--soap-dist-large) * -1) 0; }
  [data-motion="full"] .soap-reveal[data-soap="right"] { translate: var(--soap-dist-large) 0; }
}

/* will-change entra só enquanto o elemento espera a vez, e sai ao terminar.
   Deixar will-change permanente cria camada de GPU desnecessária. */
[data-motion="full"] .soap-reveal:not(.is-visible) { will-change: opacity, translate; }
[data-motion="full"] .soap-reveal.is-done          { will-change: auto; }

/* ---------------------------------------------------------------------------
   3 · SPLIT DE TEXTO POR PALAVRA (H1 do hero)
   O JS envolve cada palavra e coloca aria-label com o texto íntegro no <h1>,
   então o leitor de tela anuncia a frase inteira e ignora os spans.
   --------------------------------------------------------------------------- */
[data-motion="full"] .soap-word {
  display: inline-block;
  overflow: hidden;
  vertical-align: bottom;
  /* compensa o corte de descendentes (g, p, q, y) pelo overflow */
  padding-bottom: var(--descida);
  margin-bottom: calc(var(--descida) * -1);
}

[data-motion="full"] .soap-word__i {
  display: inline-block;
  transform: translate3d(0, 108%, 0);
  transition: transform var(--soap-d-long) var(--soap-e-enter) var(--soap-delay, 0ms);
}

[data-motion="full"] .soap-split.is-visible .soap-word__i { transform: none; }

/* ---------------------------------------------------------------------------
   4 · TILT E BRILHO NOS CARTÕES
   Só em ponteiro fino com hover real. Em toque, nada disso existe.
   O brilho é box-shadow interpolada: zero pseudo-elemento, zero risco de
   empilhamento sobre o conteúdo do card.
   --------------------------------------------------------------------------- */
@media (hover: hover) and (pointer: fine) {
  [data-motion="full"] .soap-tilt {
    transform:
      perspective(1000px)
      rotateX(var(--soap-rx, 0deg))
      rotateY(var(--soap-ry, 0deg))
      translate3d(0, var(--soap-lift, 0px), 0);
    box-shadow: 0 18px 44px rgba(244, 96, 14, var(--soap-glow, 0));
    transition:
      transform  var(--soap-d-short) var(--soap-e-gentle),
      box-shadow var(--soap-d-short) var(--soap-e-gentle);
  }

  /* Enquanto o mouse está sobre o card, o acompanhamento precisa ser quase
     imediato, senão parece elástico e atrasado. */
  [data-motion="full"] .soap-tilt.is-tilting {
    transition-duration: var(--soap-d-follow), var(--soap-d-short);
  }
}

/* ---------------------------------------------------------------------------
   5 · BOTÃO MAGNÉTICO
   --------------------------------------------------------------------------- */
@media (hover: hover) and (pointer: fine) {
  [data-motion="full"] .soap-magnetic {
    transform: translate3d(var(--soap-mx, 0px), var(--soap-my, 0px), 0);
    transition: transform var(--soap-d-short) var(--soap-e-gentle);
  }
  [data-motion="full"] .soap-magnetic.is-pulling { transition-duration: var(--soap-d-follow); }
}

/* ---------------------------------------------------------------------------
   6 · BARRA DE PROGRESSO DE SCROLL
   Elemento criado pelo JS e anexado ao header. Nunca acima do chatbot.
   --------------------------------------------------------------------------- */
[data-motion="full"] .soap-progress {
  position: absolute;
  inset-inline: 0;
  bottom: -1px;
  height: 2px;
  transform: scaleX(var(--soap-p, 0));
  transform-origin: left center;
  /* Gradiente e não cor chapada: a ponta que avança fica mais clara e a barra
     ganha direção. Chapada, ela parecia uma borda mal colocada. */
  background: linear-gradient(90deg,
              var(--color-primary) 0%,
              var(--color-primary-hover) 100%);
  border-end-end-radius: 2px;
  box-shadow: var(--glow-primary-soft);
  z-index: var(--z-base);
  pointer-events: none;
  /* No topo absoluto da página a barra não existe, em vez de deixar o brilho
     da box-shadow aceso num elemento de largura zero: era isso que aparecia
     como um toco laranja grudado na esquerda do header.
     min(1, p × 100) chega a 1 com menos de 1% de rolagem e é 0 exatamente em
     0. Matemática em cima do valor real, não casamento de string no atributo
     style, que depende de como cada navegador serializa o setProperty. */
  opacity: min(1, calc(var(--soap-p, 0) * 100));
  transition: opacity var(--duration-fast) var(--ease-out);
}

/* ---------------------------------------------------------------------------
   7 · FAIXA "ATENDEMOS"
   Nada aqui. A faixa e todos os seus controles de pausa (hover, foco e botão)
   pertencem ao ATELIER e vivem no styles.css. O SOAP tinha uma regra de pausa
   no hover que virou duplicata quando o componente ganhou controle próprio,
   e foi removida: duas camadas escrevendo animation-play-state no mesmo
   elemento é conflito esperando para acontecer.
   --------------------------------------------------------------------------- */

/* ---------------------------------------------------------------------------
   8 · PARALLAX DO HERO
   Deslocamento vertical mínimo, calculado por rAF. Desligado no mobile.
   --------------------------------------------------------------------------- */
@media (min-width: 900px) {
  [data-motion="full"] .soap-parallax {
    transform: translate3d(0, var(--soap-py, 0px), 0);
  }
}

/* ---------------------------------------------------------------------------
   9 · CONTADOR (effects/countup.js)

   ⚠️ SEM O SELETOR [data-motion="full"], E DE PROPÓSITO.
   Todo o resto deste arquivo é guardado por ele porque descreve o estado
   INICIAL de elementos que já existem no HTML: sem a guarda, quem tem
   movimento reduzido veria a página começar invisível e nunca aparecer.
   Estes dois seletores não têm esse problema, porque os elementos só existem
   depois que o JS os criou, e o JS só roda com o movimento cheio. Guardar
   aqui não protegeria nada e criaria uma falha: se o atributo mudasse com os
   spans já montados, o valor de leitor de tela apareceria na tela, duplicando
   o número ao lado dele mesmo.
   --------------------------------------------------------------------------- */
.conta {
  display: inline-block;
  /* Algarismo de largura fixa. O min-width que o JS trava segura a CAIXA; o
     tnum segura o miolo, senão "111" e "380" medem diferente e o número treme
     dentro da própria largura enquanto sobe. */
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum";
}

/* O valor verdadeiro, só para leitor de tela. O número visível é aria-hidden
   porque passa quase toda a animação exibindo um valor que não é verdade.
   EXCEÇÃO DOCUMENTADA: 1px e -1px são o idioma consagrado de esconder da
   vista sem esconder do leitor. Não são medidas de espaçamento. */
.conta-sr {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0; border: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* ---------------------------------------------------------------------------
   10 · MOVIMENTO REDUZIDO
   Redundância proposital: o init.js já sai antes de escrever data-motion
   quando prefers-reduced-motion está ativo. Esta regra é a segunda trava,
   caso a preferência mude com a página já aberta.
   --------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  [data-motion] .soap-reveal,
  [data-motion] .soap-word__i,
  [data-motion] .soap-tilt,
  [data-motion] .soap-magnetic,
  [data-motion] .soap-parallax {
    opacity: 1 !important;
    transform: none !important;
    translate: none !important;
    scale: none !important;
    transition: none !important;
  }
  [data-motion] .soap-progress { display: none; }
}
