/* ==========================================================================
   CORE — motion
   Os três ganchos globais de entrada. Componente NÃO escreve observer nem
   keyframe próprio para "aparecer": usa data-rv, data-split ou .ttl.
   Regra: nada entra seco. Toda entrada carrega blur indo a zero.
   ========================================================================== */

/* ---- data-rv: o reveal padrão ----
   Fade + blur + subida. data-d="1|2|3" escalona o delay entre irmãos. */
[data-rv]{
  opacity:0;filter:blur(14px);transform:translateY(22px);
  transition:opacity 1s var(--ease),filter 1.1s var(--ease),transform 1s var(--ease);
}
[data-rv].in{opacity:1;filter:blur(0);transform:none}

/* CUIDADO, e não é bug: `blur(0)` continua sendo um FILTRO. Um elemento com
   filtro é bloco de contenção para descendente `position:fixed` — então tudo
   que já foi revelado por [data-rv] segue prendendo um filho fixo à própria
   caixa, para sempre, não só durante a entrada. Medido no Chrome: filho
   `fixed` com `top:0` dentro de um pai com `blur(0px)` pinta no topo do PAI;
   com `filter:none` no pai, pinta no topo da JANELA.

   Trocar por `filter:none` aqui não resolve: a transição sai de `blur(14px)`
   e `none` não interpola a partir de um filtro — a entrada perderia o
   desfoque, que o §5 do contrato exige. Então a regra fica, e quem precisa de
   um elemento `fixed` (uma imagem que segue o cursor, um painel colado à
   janela) põe esse elemento FORA de qualquer [data-rv] — filho direto da
   seção. É o que o listas/lista-imagem-flutuante faz. */
[data-rv][data-d="1"]{transition-delay:.08s}
[data-rv][data-d="2"]{transition-delay:.16s}
[data-rv][data-d="3"]{transition-delay:.24s}

/* ---- data-split: revelação palavra a palavra ----
   O JS quebra o texto em .w preservando as tags internas (<em>, <a>). */
.w{
  display:inline-block;opacity:0;filter:blur(12px);transform:translateY(.5em);
  transition:opacity .9s var(--ease),filter .9s var(--ease),transform .9s var(--ease);
}
.w.in{opacity:1;filter:blur(0);transform:none}

/* ---- .ttl: título de seção ----
   Animação própria (não transition) para poder disparar por classe sem
   depender do estado anterior. */
.ttl{opacity:0;filter:blur(14px);transform:translateY(10px)}
.ttl.see{animation:ttlReveal .9s var(--ease) forwards}
@keyframes ttlReveal{
  0%{opacity:0;filter:blur(14px);transform:translateY(10px)}
  100%{opacity:1;filter:blur(0);transform:translateY(0)}
}

/* ---- Sem JavaScript ----
   O estado de repouso destes três ganchos é INVISÍVEL, e quem devolve a
   visibilidade é o core/motion.js pondo .in / .see. Sem script — bloqueador,
   erro de rede, JavaScript desligado — a página inteira ficava em branco:
   o conteúdo estava no HTML, montado e correto, e ninguém via.

   `scripting: none` casa exatamente nesse caso. Medido no Chrome: com script
   ligado casa `scripting: enabled`, com script desligado casa `scripting:
   none`. Não é hipótese, é o teste.

   Por que aqui e não uma classe `.js` no <html>: a classe obrigaria todo
   consumidor a colar um <script> no <head> antes de qualquer coisa, e o alvo
   da biblioteca é um trecho que cola em página estática, em .astro ou em
   bloco do Elementor sem preparo. Esta consulta não pede nada de ninguém.

   Ressalva honesta: `scripting` é recente (Chrome 120, Firefox 113, Safari
   17). Em navegador mais antigo COM script desligado o problema persiste —
   é uma interseção pequena, e a alternativa custaria uma linha em toda
   página consumidora. */
@media (scripting: none){
  [data-rv],.w,.ttl{
    opacity:1;filter:none;transform:none;transition:none;
  }
  .ttl.see{animation:none}
}

/* ---- Acessibilidade ----
   Quem pediu menos movimento vê a página inteira, parada. */
@media(prefers-reduced-motion:reduce){
  [data-rv],.w,.ttl{
    opacity:1!important;filter:none!important;
    transform:none!important;transition:none!important;
  }
  .ttl.see{animation:none}
}
