/* ── Marca: a borboleta (Borboleta.astro) ─────────────────────────────── */
.borboleta { display: inline-flex; filter: drop-shadow(var(--sombra-glow)); transform-style: preserve-3d; }
.borboleta svg { display: block; transform-style: preserve-3d; }
.borboleta .asa { transform-box: fill-box; }
.borboleta .asa--esq { transform-origin: 100% 50%; }
.borboleta .asa--dir { transform-origin: 0% 50%; }

/* ── Nebulosa (Nebulosa.astro) ────────────────────────────────────────── */
.fas-nebulosa {
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  overflow: hidden;
}
/* .55 multiplicava TODAS as camadas de uma vez — cada uma já baixa por si
   só (aurora a .42/.26, horizonte a .3), o produto composto ficava perto
   do imperceptível e sobrava só o roxo de fundo, chapado. O mockup
   (referencia/mockup/Home.dc.html) não tinha esse multiplicador nenhum;
   ambiente sobe perto de hero — a diferença entre os dois deixa de ser o
   que salva o contraste (isso é papel das superfícies dos cards) e volta
   a ser só uma leve reserva de intensidade para fundos com conteúdo. */
.fas-nebulosa--ambiente { opacity: .92; }
.fas-nebulosa--hero { opacity: 1; }

.fas-nebulosa .camada { position: absolute; inset: -12%; }

/* 1. Fundo em deriva diagonal lenta.
   O doc 02 pede TRÊS períodos independentes: translate 24s, translate 31s e
   scale 27s. Como os três animam `transform`, uma única camada não consegue —
   a última regra venceria. Daí os três níveis aninhados: cada um carrega uma
   transformação, e o resultado composto nunca repete o mesmo quadro em menos
   de dezenas de minutos. */
.fas-nebulosa .deriva-x, .fas-nebulosa .deriva-y, .fas-nebulosa .deriva-escala { position: absolute; inset: 0; }
.fas-nebulosa .deriva-x { inset: -12%; animation: deriva-x var(--dur-neb-translate-a) ease-in-out infinite; }
.fas-nebulosa .deriva-y { animation: deriva-y var(--dur-neb-translate-b) ease-in-out infinite; }
.fas-nebulosa .deriva-escala {
  background:
    radial-gradient(58% 42% at 18% 12%, rgb(126 74 255 / .42), rgb(126 74 255 / 0) 70%),
    radial-gradient(50% 38% at 86% 34%, rgb(213 78 224 / .26), rgb(213 78 224 / 0) 72%),
    radial-gradient(62% 40% at 34% 72%, rgb(121 226 255 / .16), rgb(121 226 255 / 0) 74%);
  animation: deriva-escala var(--dur-neb-scale) ease-in-out infinite;
}

/* 2. Auroras em screen. Opacidade e drift têm períodos próprios e são
   propriedades diferentes, então convivem na mesma camada. Drift oposto. */
.fas-nebulosa .camada--aurora-violeta {
  background: radial-gradient(56% 40% at 26% 24%, rgb(126 74 255 / .42), rgb(126 74 255 / 0) 70%);
  mix-blend-mode: screen;
  animation:
    pulsa-violeta var(--dur-aurora-violeta-opacidade) ease-in-out infinite,
    drift-a var(--dur-aurora-violeta-drift) ease-in-out infinite;
}
.fas-nebulosa .camada--aurora-magenta {
  background: radial-gradient(50% 36% at 72% 70%, rgb(213 78 224 / .26), rgb(213 78 224 / 0) 72%);
  mix-blend-mode: screen;
  animation:
    pulsa-magenta var(--dur-aurora-magenta-opacidade) ease-in-out infinite,
    drift-b var(--dur-aurora-magenta-drift) ease-in-out infinite;
}

/* 3. Horizonte rosa pulsando */
.fas-nebulosa .camada--horizonte {
  background: radial-gradient(95% 42% at 50% 108%, rgb(255 64 208 / .3), rgb(255 64 208 / 0) 70%);
  mix-blend-mode: screen;
  animation: horizonte var(--dur-horizonte) ease-in-out infinite;
}

/* 4. Poeira de luz */
.fas-nebulosa .poeira { position: absolute; inset: 0; }
.fas-nebulosa .particula {
  position: absolute;
  bottom: -5%;
  border-radius: 50%;
  background: var(--fas-lavanda);
  box-shadow: 0 0 10px 3px rgb(169 112 255 / .5);
}

/* Poeira de luz — valores fixos, um por partícula.
   Tamanhos 3.5–10.5px, subida 28–54s, cintilar 2.2–4.8s, conforme
   docs/02-marca-e-motion.md. Literais em vez de gerados: determinismo
   que não depende de nenhum código rodar. */
.fas-nebulosa .particula:nth-child(1) { left: 9.04%; width: 7.71px; height: 7.71px;
  animation: sobe 52.0s linear infinite 0.3s, cintila 3.04s ease-in-out infinite 0.3s; }
.fas-nebulosa .particula:nth-child(2) { left: 41.33%; width: 5.84px; height: 5.84px;
  animation: sobe 31.2s linear infinite 7.5s, cintila 2.23s ease-in-out infinite 7.5s; }
.fas-nebulosa .particula:nth-child(3) { left: 79.07%; width: 9.71px; height: 9.71px;
  animation: sobe 52.8s linear infinite 29.4s, cintila 3.18s ease-in-out infinite 29.4s; }
.fas-nebulosa .particula:nth-child(4) { left: 13.14%; width: 6.63px; height: 6.63px;
  animation: sobe 32.2s linear infinite 9.4s, cintila 4.20s ease-in-out infinite 9.4s; }
.fas-nebulosa .particula:nth-child(5) { left: 86.75%; width: 4.12px; height: 4.12px;
  animation: sobe 35.0s linear infinite 9.0s, cintila 4.71s ease-in-out infinite 9.0s; }
.fas-nebulosa .particula:nth-child(6) { left: 97.45%; width: 9.74px; height: 9.74px;
  animation: sobe 35.9s linear infinite 25.4s, cintila 3.86s ease-in-out infinite 25.4s; }
.fas-nebulosa .particula:nth-child(7) { left: 30.72%; width: 10.16px; height: 10.16px;
  animation: sobe 37.2s linear infinite 12.6s, cintila 2.57s ease-in-out infinite 12.6s; }
.fas-nebulosa .particula:nth-child(8) { left: 57.93%; width: 8.61px; height: 8.61px;
  animation: sobe 34.0s linear infinite 15.8s, cintila 4.24s ease-in-out infinite 15.8s; }
.fas-nebulosa .particula:nth-child(9) { left: 53.98%; width: 6.52px; height: 6.52px;
  animation: sobe 29.6s linear infinite 14.1s, cintila 4.20s ease-in-out infinite 14.1s; }
.fas-nebulosa .particula:nth-child(10) { left: 98.55%; width: 6.74px; height: 6.74px;
  animation: sobe 47.9s linear infinite 21.1s, cintila 4.20s ease-in-out infinite 21.1s; }
.fas-nebulosa .particula:nth-child(11) { left: 25.11%; width: 3.99px; height: 3.99px;
  animation: sobe 52.0s linear infinite 22.7s, cintila 2.75s ease-in-out infinite 22.7s; }
.fas-nebulosa .particula:nth-child(12) { left: 71.40%; width: 5.85px; height: 5.85px;
  animation: sobe 28.5s linear infinite 22.8s, cintila 3.50s ease-in-out infinite 22.8s; }
.fas-nebulosa .particula:nth-child(13) { left: 31.21%; width: 9.62px; height: 9.62px;
  animation: sobe 37.0s linear infinite 25.5s, cintila 3.61s ease-in-out infinite 25.5s; }
.fas-nebulosa .particula:nth-child(14) { left: 6.01%; width: 9.11px; height: 9.11px;
  animation: sobe 40.7s linear infinite 19.3s, cintila 4.78s ease-in-out infinite 19.3s; }
.fas-nebulosa .particula:nth-child(15) { left: 87.49%; width: 7.07px; height: 7.07px;
  animation: sobe 48.2s linear infinite 3.2s, cintila 4.41s ease-in-out infinite 3.2s; }
.fas-nebulosa .particula:nth-child(16) { left: 40.40%; width: 3.66px; height: 3.66px;
  animation: sobe 28.1s linear infinite 22.0s, cintila 4.02s ease-in-out infinite 22.0s; }
.fas-nebulosa .particula:nth-child(17) { left: 50.58%; width: 9.05px; height: 9.05px;
  animation: sobe 50.1s linear infinite 7.6s, cintila 2.44s ease-in-out infinite 7.6s; }
.fas-nebulosa .particula:nth-child(18) { left: 72.15%; width: 8.44px; height: 8.44px;
  animation: sobe 48.4s linear infinite 1.4s, cintila 4.78s ease-in-out infinite 1.4s; }
.fas-nebulosa .particula:nth-child(19) { left: 55.40%; width: 5.59px; height: 5.59px;
  animation: sobe 28.4s linear infinite 5.4s, cintila 3.73s ease-in-out infinite 5.4s; }
.fas-nebulosa .particula:nth-child(20) { left: 8.28%; width: 10.30px; height: 10.30px;
  animation: sobe 32.1s linear infinite 15.4s, cintila 3.44s ease-in-out infinite 15.4s; }
.fas-nebulosa .particula:nth-child(21) { left: 35.52%; width: 7.08px; height: 7.08px;
  animation: sobe 47.5s linear infinite 21.4s, cintila 2.49s ease-in-out infinite 21.4s; }
.fas-nebulosa .particula:nth-child(22) { left: 7.43%; width: 5.86px; height: 5.86px;
  animation: sobe 36.3s linear infinite 26.4s, cintila 4.34s ease-in-out infinite 26.4s; }
.fas-nebulosa .particula:nth-child(23) { left: 40.16%; width: 6.59px; height: 6.59px;
  animation: sobe 37.5s linear infinite 3.3s, cintila 3.25s ease-in-out infinite 3.3s; }
.fas-nebulosa .particula:nth-child(24) { left: 57.40%; width: 9.46px; height: 9.46px;
  animation: sobe 35.1s linear infinite 17.2s, cintila 3.54s ease-in-out infinite 17.2s; }
.fas-nebulosa .particula:nth-child(25) { left: 83.56%; width: 3.79px; height: 3.79px;
  animation: sobe 50.0s linear infinite 19.8s, cintila 3.30s ease-in-out infinite 19.8s; }
.fas-nebulosa .particula:nth-child(26) { left: 47.37%; width: 3.66px; height: 3.66px;
  animation: sobe 43.0s linear infinite 2.2s, cintila 2.86s ease-in-out infinite 2.2s; }

/* translate ±2% / ±1.4% e scale 1.09 ± 0.03, cada um no seu período */
@keyframes deriva-x      { 0%, 100% { transform: translateX(-2%); }   50% { transform: translateX(2%); } }
@keyframes deriva-y      { 0%, 100% { transform: translateY(-1.4%); } 50% { transform: translateY(1.4%); } }
@keyframes deriva-escala { 0%, 100% { transform: scale(1.06); }       50% { transform: scale(1.12); } }
@keyframes drift-a { 0%, 100% { transform: translate(0, 0); } 50% { transform: translate(1.5%, -1%); } }
@keyframes drift-b { 0%, 100% { transform: translate(0, 0); } 50% { transform: translate(-1.5%, 1%); } }
@keyframes pulsa-violeta { 0%, 100% { opacity: .35; } 50% { opacity: .85; } }
@keyframes pulsa-magenta { 0%, 100% { opacity: .25; } 50% { opacity: .85; } }
@keyframes horizonte { 0%, 100% { opacity: .15; } 50% { opacity: .75; } }
@keyframes sobe { from { transform: translateY(0); } to { transform: translateY(-110svh); } }
@keyframes cintila { 0%, 100% { opacity: .16; } 50% { opacity: .66; } }

@media (prefers-reduced-motion: reduce) {
  /* :nth-child(n) casa todas as partículas e iguala a especificidade das
     regras individuais acima — sem isso, `.particula` sozinho (0,1,0)
     perde para `.particula:nth-child(3)` (0,2,0). */
  .fas-nebulosa .camada, .fas-nebulosa .deriva-x, .fas-nebulosa .deriva-y, .fas-nebulosa .deriva-escala { animation: none; }
  .fas-nebulosa .particula:nth-child(n) { animation: none; }
  .fas-nebulosa .camada--aurora-violeta { opacity: .6; }
  .fas-nebulosa .camada--aurora-magenta { opacity: .55; }
  .fas-nebulosa .camada--horizonte { opacity: .45; }
  .fas-nebulosa .particula { opacity: .4; }
}

/* ── Enxame de borboletas (Borboletas.astro) ──────────────────────────── */
.fas-enxame { position: fixed; inset: 0; z-index: 0; pointer-events: none; overflow: hidden; }

.fas-enxame .voo { position: absolute; left: 0; }

/* Balanço lateral senoidal aninhado: o pai (.voo) sobe reto na diagonal
   (keyframe `atravessa`), o filho ondula de lado com período mais curto —
   várias ondulações acontecem ao longo de uma travessia, lendo como
   serpenteio em vez da linha quase reta de antes. */
.fas-enxame .ondula {
  display: block;
  animation-name: ondula;
  animation-timing-function: ease-in-out;
  animation-iteration-count: infinite;
}

/* Batida 3D real, terceira tentativa — as duas primeiras foram rejeitadas:
   v1 (scaleX na borboleta inteira) lia como losango achatando; v2 (dois
   SVGs clipados) lia como duas lâminas com fresta; v3 (este mesmo <g>
   agrupado, só rotateY) lia como "chacoalha de um lado pro outro" — um
   rotateY puro gira a asa como PORTA em torno de um eixo vertical: visto
   de frente isso é só compressão horizontal, a ponta não sai do lugar em
   y, nunca sobe. Correção (v4): a ponta da asa precisa descrever um arco
   PARA CIMA ao fechar, não só para dentro. Duas peças fazem isso aparecer:

   1. `.asas .asa--esq/--dir` abaixo não gira só em rotateY — some
      .fas-enxame um rotateZ de sinal OPOSTO entre os lados (positivo à esquerda,
      negativo à direita) que cresce junto com o rotateY. Como os dois
      compartilham o mesmo transform-origin (a costura, ver
      Borboleta.astro), o rotateZ dobra a ponta pra cima em torno do MESMO
      eixo que o rotateY já usa — não é um efeito plano por cima, é a asa
      subindo enquanto fecha.
   2. `.camera` inclina o palco 3D em rotateX antes da perspectiva projetar
      os <g>: de frente (rotateX 0) o V formado pelo rotateZ acima fica
      acima do corpo e é invisível — encolhe mas não se vê subir. Só um
      observador ligeiramente por cima e por trás revela o arco. */
.fas-enxame .asas {
  /* Sem isso, width/height não valem nada: <span> é inline por padrão, e
     propriedades de tamanho não se aplicam a caixa inline não-substituída
     — a caixa colapsava pra 0×0 e cascateava pro svg dentro. */
  display: block;
  position: relative;
  width: 4.2svh;
  height: 4.2svh;
  perspective: 420px;
  animation-name: corpo-bate;
  animation-timing-function: ease-in-out;
  animation-iteration-count: infinite;
}

/* Câmera: inclinação FIXA (não anima — não é motion, é o ângulo de onde a
   cena 3D é vista), então não precisa de tratamento de
   prefers-reduced-motion aqui (o enxame inteiro já vira display:none
   nesse modo, mais abaixo). `transform-style: preserve-3d` é o que faz o
   rotateY/rotateZ dos <g>, duas gerações abaixo, continuar participando do
   MESMO espaço 3D que a perspective de .asas define — sem isso em CADA
   elemento da cadeia (aqui e em Borboleta.astro), o navegador achataria
   este span num plano 2D antes da perspectiva agir, e o giro dos <g>
   voltaria a renderizar ortográfico (o problema de origem do chacoalho). */
.fas-enxame .camera {
  display: block;
  width: 100%;
  height: 100%;
  transform-style: preserve-3d;
  transform: rotateX(-24deg);
}

/* transform-box/transform-origin de .asa--esq/.asa--dir vivem em
   Borboleta.astro (é geometria intrínseca do SVG, não coreografia); aqui
   só o nome do keyframe e o timing base — duração/atraso por borboleta
   ficam nas regras .voo--N mais abaixo, junto com .asas, pra ficarem em
   fase. O glow individual que <Borboleta> aplica por instância (filter:
   drop-shadow) é desligado dentro do enxame e substituído por um único
   glow no corpo (.asas), que pulsa junto com a batida. */
.fas-enxame .asas .borboleta { display: block; width: 100%; height: 100%; filter: none; }
.fas-enxame .asas .borboleta svg { width: 100%; height: 100%; }
.fas-enxame .asas .asa--esq { animation-name: asa-esq; animation-timing-function: ease-in-out; animation-iteration-count: infinite; }
.fas-enxame .asas .asa--dir { animation-name: asa-dir; animation-timing-function: ease-in-out; animation-iteration-count: infinite; }

/* Enxame (10 borboletas): profundidade por opacidade (.34–.84), desfoque
   (até 2.2px) e saturação (.62–1) crescem juntos; ordem de pintura
   acompanha — mais apagada primeiro (fica atrás), mais nítida por último
   (fica na frente), porque sem z-index o DOM decide quem pinta em cima.

   Atraso NEGATIVO, não positivo: atraso positivo congela o elemento no
   primeiro keyframe até o atraso terminar — com atrasos de 0s a 23.8s, as
   dez ficavam empilhadas no ponto de entrada por até ~24s antes de sair do
   .fas-enxame lugar. Atraso negativo faz a animação nascer já adiantada nesse tanto,
   ou seja, cada borboleta aparece a partir do primeiro frame já no meio do
   próprio trajeto.
   O atraso é uma fração da PRÓPRIA duração de cada borboleta (24–28s), não
   um passo fixo (um passo fixo distribuiria mal já que os ciclos têm
   .fas-enxame tamanhos diferentes): fase = -(2n-1)/20 × duração, .fas-enxame ou seja ~5%, .fas-enxame 15%,
   25% ... 95% do próprio ciclo — dez pontos de entrada bem espaçados ao
   longo do trajeto inteiro, sem repetir a extremidade 0%/100% (que seriam
   a mesma posição de entrada e voltariam a empilhar duas borboletas ali).

   Correção (11/08): todas nasciam na metade baixa da tela (top 43–91svh) e
   subiam pela esquerda — a impressão era "vêm todas de baixo". `top`
   agora varia entre terço alto (~8–20svh), meio (~38–60svh) e baixo
   (~67–90svh), e cada borboleta usa uma de três trajetórias (abaixo):
   entra pela esquerda subindo (`atravessa`, a receita original), entra
   pela direita subindo (`atravessa-direita`, espelho horizontal exato) ou
   .fas-enxame entra pela esquerda descendo de leve (`atravessa-desce-leve`). Duração,
   atraso e a progressão de opacidade/desfoque/saturação por índice não
   mudam — só `top` e o nome do keyframe. */
.fas-enxame .voo--1 { top: 14svh; opacity: .34; filter: blur(2.2px) saturate(.62); animation: atravessa          24s linear infinite  -1.2s; }
.fas-enxame .voo--2 { top: 82svh; opacity: .40; filter: blur(2.0px) saturate(.66); animation: atravessa          25s linear infinite  -3.75s; }
.fas-enxame .voo--3 { top: 50svh; opacity: .46; filter: blur(1.8px) saturate(.70); animation: atravessa-direita  26s linear infinite  -6.5s; }
.fas-enxame .voo--4 { top: 20svh; opacity: .52; filter: blur(1.5px) saturate(.75); animation: atravessa-direita  27s linear infinite  -9.45s; }
.fas-enxame .voo--5 { top: 60svh; opacity: .58; filter: blur(1.2px) saturate(.80); animation: atravessa-desce-leve 28s linear infinite -12.6s; }
.fas-enxame .voo--6 { top: 70svh; opacity: .64; filter: blur(1.0px) saturate(.84); animation: atravessa          24s linear infinite -13.2s; }
.fas-enxame .voo--7 { top: 38svh; opacity: .70; filter: blur(.8px)  saturate(.88); animation: atravessa-direita  25s linear infinite -16.25s; }
.fas-enxame .voo--8 { top: 8svh;  opacity: .74; filter: blur(.5px)  saturate(.92); animation: atravessa          26s linear infinite -19.5s; }
.fas-enxame .voo--9 { top: 90svh; opacity: .78; filter: blur(.2px)  saturate(.96); animation: atravessa-direita  27s linear infinite -22.95s; }
.fas-enxame .voo--10 { top: 46svh; opacity: .84; filter: saturate(1);               animation: atravessa-desce-leve 28s linear infinite -26.6s; }

/* Ondulação lateral — período e amplitude variam por borboleta via custom
   property em classe (nunca atributo style inline) pra não ondularem em
   coro. Mesmo problema da travessia: passo fixo (0.6s) não respeita que
   cada uma tem duração própria (6.00–7.00s), então o atraso positivo
   sincronizava demais quem tem ciclo parecido. Atraso negativo, mesma
   fração -(2n-1)/20 × duração usada acima, pra nascerem em fases
   diferentes do próprio balanço, não só da travessia. */
.fas-enxame .voo--1  .ondula { --ondula-amp: 2.4vw; animation-duration: 6.00s; animation-delay: -0.3s; }
.fas-enxame .voo--2  .ondula { --ondula-amp: 3.6vw; animation-duration: 6.25s; animation-delay: -0.9375s; }
.fas-enxame .voo--3  .ondula { --ondula-amp: 2.8vw; animation-duration: 6.50s; animation-delay: -1.625s; }
.fas-enxame .voo--4  .ondula { --ondula-amp: 3.9vw; animation-duration: 6.75s; animation-delay: -2.3625s; }
.fas-enxame .voo--5  .ondula { --ondula-amp: 3.1vw; animation-duration: 7.00s; animation-delay: -3.15s; }
.fas-enxame .voo--6  .ondula { --ondula-amp: 2.6vw; animation-duration: 6.00s; animation-delay: -3.3s; }
.fas-enxame .voo--7  .ondula { --ondula-amp: 3.8vw; animation-duration: 6.25s; animation-delay: -4.0625s; }
.fas-enxame .voo--8  .ondula { --ondula-amp: 3.0vw; animation-duration: 6.50s; animation-delay: -4.875s; }
.fas-enxame .voo--9  .ondula { --ondula-amp: 2.5vw; animation-duration: 6.75s; animation-delay: -5.7375s; }
.fas-enxame .voo--10 .ondula { --ondula-amp: 3.7vw; animation-duration: 7.00s; animation-delay: -6.65s; }

/* Batida 1.5–2.2Hz (período .455–.667s), fase própria por borboleta —
   corpo e as duas metades compartilham duração/atraso pra continuarem em
   fase entre si (uma borboleta não bate a asa esquerda fora de sincronia
   com a direita; o que dessincroniza é uma borboleta da outra).
   Mesmo passo fixo positivo (0.05s) da versão anterior, mesmo problema em
   escala menor: com período tão curto (.455–.655s) o efeito de começar
   todas "fechadas" (frame 0%) é menos visível a olho nu, mas ainda existe
   e ainda é sincronismo indevido. Atraso negativo com a mesma fração
   -(2n-1)/20 × duração usada nas outras duas camadas. */
.fas-enxame .voo--1  .asas, .fas-enxame .voo--1  .asas .asa--esq, .fas-enxame .voo--1  .asas .asa--dir { animation-duration: .455s; animation-delay: -0.023s; }
.fas-enxame .voo--2  .asas, .fas-enxame .voo--2  .asas .asa--esq, .fas-enxame .voo--2  .asas .asa--dir { animation-duration: .480s; animation-delay: -0.072s; }
.fas-enxame .voo--3  .asas, .fas-enxame .voo--3  .asas .asa--esq, .fas-enxame .voo--3  .asas .asa--dir { animation-duration: .505s; animation-delay: -0.126s; }
.fas-enxame .voo--4  .asas, .fas-enxame .voo--4  .asas .asa--esq, .fas-enxame .voo--4  .asas .asa--dir { animation-duration: .530s; animation-delay: -0.186s; }
.fas-enxame .voo--5  .asas, .fas-enxame .voo--5  .asas .asa--esq, .fas-enxame .voo--5  .asas .asa--dir { animation-duration: .555s; animation-delay: -0.250s; }
.fas-enxame .voo--6  .asas, .fas-enxame .voo--6  .asas .asa--esq, .fas-enxame .voo--6  .asas .asa--dir { animation-duration: .580s; animation-delay: -0.319s; }
.fas-enxame .voo--7  .asas, .fas-enxame .voo--7  .asas .asa--esq, .fas-enxame .voo--7  .asas .asa--dir { animation-duration: .605s; animation-delay: -0.393s; }
.fas-enxame .voo--8  .asas, .fas-enxame .voo--8  .asas .asa--esq, .fas-enxame .voo--8  .asas .asa--dir { animation-duration: .630s; animation-delay: -0.473s; }
.fas-enxame .voo--9  .asas, .fas-enxame .voo--9  .asas .asa--esq, .fas-enxame .voo--9  .asas .asa--dir { animation-duration: .655s; animation-delay: -0.557s; }
.fas-enxame .voo--10 .asas, .fas-enxame .voo--10 .asas .asa--esq, .fas-enxame .voo--10 .asas .asa--dir { animation-duration: .500s; animation-delay: -0.475s; }

/* Esquerda→direita subindo (brisa), 7 paradas em vez de 3: a versão
   anterior (from/50%/to) era piecewise-linear com um único vinco no meio
   — lida como "passa direto". Y estritamente decrescente a cada parada
   (nunca desce, conforme o doc); X com incrementos desiguais pra não
   parecer mecânico mesmo antes de somar a ondulação lateral do pai. */
@keyframes atravessa {
  0%   { transform: translate(-12vw, 0); }
  18%  { transform: translate(6vw,  -4svh); }
  36%  { transform: translate(28vw, -9svh); }
  54%  { transform: translate(52vw, -15svh); }
  72%  { transform: translate(76vw, -23svh); }
  88%  { transform: translate(96vw, -29svh); }
  100% { transform: translate(112vw, -34svh); }
}
/* Espelho horizontal exato de `atravessa` (mesma curva de Y, X refletido em
   torno do centro: novoX = 100 − X): entra pela direita, sai pela
   esquerda, subindo do mesmo jeito. */
@keyframes atravessa-direita {
  0%   { transform: translate(112vw, 0); }
  18%  { transform: translate(94vw,  -4svh); }
  36%  { transform: translate(72vw,  -9svh); }
  54%  { transform: translate(48vw,  -15svh); }
  72%  { transform: translate(24vw,  -23svh); }
  88%  { transform: translate(4vw,   -29svh); }
  100% { transform: translate(-12vw, -34svh); }
}
/* Entra pela esquerda como `atravessa`, mas desce de leve em vez de subir —
   a variação "alguma descendo levemente" do pedido. Deslocamento vertical
   bem menor (8svh) que a subida das outras duas (34svh): é um contraponto
   sutil, não uma queda. */
@keyframes atravessa-desce-leve {
  0%   { transform: translate(-12vw, 0); }
  18%  { transform: translate(6vw,  1.5svh); }
  36%  { transform: translate(28vw, 3svh); }
  54%  { transform: translate(52vw, 5svh); }
  72%  { transform: translate(76vw, 6.5svh); }
  88%  { transform: translate(96vw, 7.5svh); }
  100% { transform: translate(112vw, 8svh); }
}
@keyframes ondula {
  0%, 100% { transform: translateX(calc(-1 * var(--ondula-amp, 3vw))); }
  50%      { transform: translateX(var(--ondula-amp, 3vw)); }
}

/* Corpo estável, só o impulso vertical acompanha a batida (−4.5% do
   tamanho); o glow (drop-shadow) pulsa junto, mais forte no ponto mais
   fechado — "fecha e brilha". O pico em 32%, não 50%: a subida da asa
   (fechar) é mais rápida que a descida (abrir) numa borboleta real —
   keyframes desigualmente espaçados dão essa assimetria sem precisar de
   curva de easing própria por trecho. Fica em fase com asa-esq/asa-dir
   abaixo, que usam o mesmo 32%. */
@keyframes corpo-bate {
  0%, 100% { transform: translateY(0);      filter: brightness(1)   drop-shadow(0 0 6px rgb(150 96 255 / .35)); }
  32%      { transform: translateY(-4.5%);  filter: brightness(.66) drop-shadow(0 0 11px rgb(150 96 255 / .6)); }
}
/* Asa nunca plana: rotateY de 34° (aberta) a 74° (fechada), nunca 0° nem
   90° — isso sozinho é só a "porta girando" (v3, rejeitada: chacoalha).
   O rotateZ somado é o que faz a ponta SUBIR ao fechar: como ambos usam o
   mesmo transform-origin (a costura, em Borboleta.astro), o rotateZ
   dobra a asa pra cima em torno do mesmo eixo, não por cima dele. Sinal
   oposto ao da direita (esq positivo, dir negativo) — as duas pontas
   sobem formando um V acima do corpo, não uma pra cada lado do plano. Pico
   em 32% (ver corpo-bate) pra chegar rápido no fechado e voltar devagar. */
@keyframes asa-esq {
  0%, 100% { transform: rotateZ(4deg)  rotateY(34deg); }
  32%      { transform: rotateZ(20deg) rotateY(74deg); }
}
@keyframes asa-dir {
  0%, 100% { transform: rotateZ(-4deg)  rotateY(-34deg); }
  32%      { transform: rotateZ(-20deg) rotateY(-74deg); }
}

@media (prefers-reduced-motion: reduce) {
  /* Mesmo truque de especificidade das outras camadas: `.voo[class]`
     (0,2,0) some com uma classe extra em cada seletor pra sempre vencer o
     equivalente em `.voo--N ...` (uma classe a menos), sem depender da
     media query pra ganhar pontos — media query não soma especificidade.
     `.asa--esq`/`.asa--dir` ficam dentro de , que por si não
     conta ponto nenhum; o que conta é a classe escrita dentro dele.
     .fas-enxame `animation: none` aqui zera a trajetória (`atravessa`,
     `atravessa-direita` ou `atravessa-desce-leve`, tanto faz qual — a
     propriedade `animation` inteira é removida) sem precisar nomear as
     três variantes. */
  .fas-enxame .voo[class],
  .fas-enxame .voo[class] .ondula,
  .fas-enxame .voo[class] .asas,
  .fas-enxame .voo[class] .asas .asa--esq,
  .fas-enxame .voo[class] .asas .asa--dir { animation: none; }
  .fas-enxame .voo { display: none; }
}

