/* Movimento do site. É só aprimoramento: sem este arquivo, com "reduzir
   movimento" ligado ou num navegador sem suporte, a página fica completa e parada.
   Anima só transform, opacity, clip-path, translate e scale.
   Textos, o h1 e os botões do topo nunca animam na entrada. Exceção na branch noite-criativa:
   o h2 de Serviços sobe de uma máscara e os traços dos outros títulos se desenham, presos à rolagem (V6). */

@media (prefers-reduced-motion: no-preference) {

  :root {
    --curva-saida: cubic-bezier(0.23, 1, 0.32, 1);   /* entradas e toque; o style.css também lê */
    --curva-gaveta: cubic-bezier(0.32, 0.72, 0, 1);  /* abertura do menu */
    --curva-rolagem: cubic-bezier(0.33, 1, 0.68, 1); /* chegadas presas à rolagem: mais branda, não salta com um giro da roda */
    --duracao-toque: 140ms;                          /* o style.css também lê (reserva 0s) */
    --escala-toque: 0.97;
  }

  /* ---------- Toque ---------- */

  /* A lista de transições mora no style.css; aqui só as variáveis (acima) e o estado apertado. */
  .botao:active,
  .menu-lista .botao-menu:active,
  .cabecalho-whatsapp:active,
  .menu-botao:active {
    scale: var(--escala-toque);
  }

  /* Luz nas faixas escuras (noite-criativa, V2): o js/brilho.js cria um span por faixa (topo, contato,
     rodapé) e escreve só o transform e a opacity dele. Fica no z-index -1 da própria faixa (isolada),
     acima do fundo e da aurora e abaixo de todo o conteúdo, então nunca cobre texto nem foco.
     Sem o script não existe nada disto. */
  .com-luz {
    position: relative;
    isolation: isolate;
    overflow: clip; /* a luz passa da caixa; clip não cria rolagem */
  }

  .luz,
  .luz-onda {
    position: absolute;
    top: 0;
    left: 0;
    z-index: -1;
    pointer-events: none;
  }

  /* Lanterna difusa: 160px de caixa, sem aro nem borda. O alfa só cai, do centro (mais claro) até 0 na
     borda, em passos que aproximam uma gaussiana; o brilho visível tem uns 100px e se dissolve, sem
     tamanho de disco. O transform leva o centro exatamente ao ponteiro (a margem negativa é metade do lado).
     Alfa máximo .32 de #BFD3EA no centro: o texto claro segue acima de 4.5:1 sobre o ponto mais claro. */
  .luz {
    width: 160px;
    height: 160px;
    margin: -80px 0 0 -80px;
    opacity: 0;
    background: radial-gradient(closest-side, rgb(191 211 234 / 0.32), rgb(191 211 234 / 0.23) 22%, rgb(191 211 234 / 0.13) 45%, rgb(191 211 234 / 0.055) 68%, rgb(191 211 234 / 0.015) 86%, rgb(191 211 234 / 0));
    transition: opacity 250ms var(--curva-saida);
  }

  /* Onda do toque: o mesmo brilho, que se expande (WAAPI do script, 560ms, de 29px a 173px) e se dissolve. */
  .luz-onda {
    width: 96px;
    height: 96px;
    margin: -48px 0 0 -48px;
    background: radial-gradient(closest-side, rgb(191 211 234 / 0.42), rgb(191 211 234 / 0.28) 25%, rgb(191 211 234 / 0.14) 50%, rgb(191 211 234 / 0.05) 75%, rgb(191 211 234 / 0));
  }

  /* ---------- Menu do celular ---------- */

  /* A folha (nav, por cima da página) só ganha opacidade; a lista se desenrola de cima para baixo.
     Transições, não keyframes: abrir e fechar rápido inverte do ponto onde está.
     A saída é mais curta que a entrada. */
  @media not all and (min-width: 64em) {
    .js .cabecalho nav {
      opacity: 0;
      transition:
        opacity 160ms var(--curva-saida),
        display 160ms allow-discrete;
    }

    .js .cabecalho .menu-lista {
      translate: 0 -6px;
      /* Folga de 8px: o anel de foco (2px + 3px de offset) não sai cortado. */
      clip-path: inset(-8px -8px calc(100% + 8px) -8px);
      transition:
        translate 160ms var(--curva-saida),
        clip-path 160ms var(--curva-saida);
    }

    /* A folha cobre em 100ms, com curva de saída, e a lista se desenrola em 240ms: o texto do menu
       não passa por cima do título ainda visível. */
    .js .menu-botao[aria-expanded="true"] + nav {
      opacity: 1;
      transition-duration: 100ms;
    }

    .js .menu-botao[aria-expanded="true"] + nav .menu-lista {
      translate: 0 0;
      clip-path: inset(-8px);
      transition-duration: 240ms;
      transition-timing-function: var(--curva-gaveta);
    }

    @starting-style {
      .js .menu-botao[aria-expanded="true"] + nav {
        opacity: 0;
      }

      .js .menu-botao[aria-expanded="true"] + nav .menu-lista {
        translate: 0 -6px;
        clip-path: inset(-8px -8px calc(100% + 8px) -8px);
      }
    }
  }

  /* ---------- Topo ---------- */

  /* Abertura: a ilustração se monta uma vez ao abrir a página, em menos de 1s.
     Declarada uma vez em --abertura; parallax e cinema a reaproveitam.
     "backwards": espera no primeiro quadro durante o atraso e depois volta ao estilo normal. */
  .janela-esboco { --abertura: surge 480ms var(--curva-saida) 60ms backwards;  --afasta: -16px; }
  .janela-layout { --abertura: sobe 480ms var(--curva-saida) 180ms backwards;  --afasta: -40px; }
  .janela-pronta { --abertura: sobe 480ms var(--curva-saida) 300ms backwards;  --afasta: -64px; }

  .janela {
    animation: var(--abertura);
  }

  .layout-barra,
  .pronta-titulo,
  .pronta-linha {
    animation: enche 320ms var(--curva-saida) var(--atraso) backwards;
  }

  .pronta-botao,
  .pronta-cartao {
    animation: surge 320ms var(--curva-saida) var(--atraso) backwards;
  }

  /* --atraso: momento na abertura (a janela já abre com o conteúdo; o cinema só reorganiza e destaca). */
  .layout-barra:nth-child(2) { --atraso: 400ms; }
  .layout-barra:nth-child(3) { --atraso: 440ms; }
  .layout-barra:nth-child(4) { --atraso: 480ms; }
  .pronta-titulo             { --atraso: 520ms; }
  .pronta-linha:nth-child(3) { --atraso: 560ms; }
  .pronta-linha:nth-child(4) { --atraso: 600ms; }
  .pronta-botao              { --atraso: 640ms; }
  .pronta-cartao:nth-child(1) { --atraso: 680ms; }
  .pronta-cartao:nth-child(2) { --atraso: 720ms; }
  .pronta-cartao:nth-child(3) { --atraso: 760ms; }

  /* Aurora (noite-criativa, V1): só no computador com mouse; no celular fica parada (menos pintura).
     Só transform, na própria camada; termina parada no estado final (3 ciclos, sem botão de pausa). */
  @media (min-width: 64em) and (hover: hover) {
    .topo::before {
      will-change: transform;
      animation: aurora 38s ease-in-out 3 alternate both; /* 3 ciclos (WCAG 2.2.2) e para no quadro final */
    }
  }

  /* Inclinação 3D (noite-criativa, V3): o js/inclina.js escreve o transform na .ilustracao (que não anima
     transform; as janelas animam por dentro, então abertura, parallax e cinema seguem intactos) e o
     transform/opacity destes reflexos, criados por ele dentro de cada janela. Sem o script não existem. */
  .reflexo {
    position: absolute;
    top: 0;
    bottom: 0;
    left: -50%;
    width: 200%;
    pointer-events: none;
    opacity: 0;
    /* Faixa de luz de 115°, centrada na janela; o overflow da janela recorta. */
    background: linear-gradient(115deg, transparent 42%, rgb(255 255 255 / 0.16) 50%, transparent 58%);
  }

  /* Na janela branca o branco some: reflexo azulado. */
  .janela-pronta .reflexo {
    background: linear-gradient(115deg, transparent 42%, rgb(143 180 220 / 0.3) 50%, transparent 58%);
  }

  /* ---------- Projetos: o "Site pronto" voa até o site real (noite-criativa, V4) ---------- */

  /* O js/transicao.js põe voo-parte (janela do topo) e depois voo-chega (imagem do projeto) no <html>
     só durante a transição: os nomes nunca existem fora dela nem duplicados. */
  .voo-parte .janela-pronta,
  .voo-chega .projeto-imagem {
    view-transition-name: site-real;
  }

  /* Só onde o cabeçalho é grudado (abaixo do computador); lá em cima ele é da página e sai com ela. */
  @media not all and (min-width: 64em) {
    .js.voo-parte .cabecalho,
    .js.voo-sem-origem .cabecalho,
    .js.voo-chega .cabecalho {
      view-transition-name: cabecalho;
    }
  }

  /* Seção que recebeu o foco pelo script: não é controle, então sem anel em volta de tudo. */
  .projetos:focus {
    outline: none;
  }

  /* Voo de 640ms com um pequeno passo além do destino e a acomodação; halo só enquanto voa. */
  ::view-transition-group(site-real) {
    animation-name: -ua-view-transition-group-anim-site-real, voo-halo;
    animation-duration: 640ms;
    animation-timing-function: cubic-bezier(0.34, 1.2, 0.64, 1), linear;
    border-radius: var(--radius-md);
  }

  ::view-transition-image-pair(site-real) {
    border-radius: var(--radius-md);
    overflow: clip;
  }

  /* A janela branca fica por baixo, inteira, e a imagem aparece por cima (sem "buraco" no meio do fade). */
  ::view-transition-old(site-real),
  ::view-transition-new(site-real) {
    height: 100%;
    object-fit: cover;
    object-position: top;
    mix-blend-mode: normal;
  }

  ::view-transition-old(site-real) {
    animation: none;
  }

  ::view-transition-new(site-real) {
    animation: voo-entra 420ms linear both;
  }

  /* O resto da página: a antiga recua um pouco e a nova entra em 240ms. */
  ::view-transition-old(root),
  ::view-transition-new(root) {
    mix-blend-mode: normal;
    animation-duration: 240ms;
    animation-timing-function: var(--curva-saida);
    animation-fill-mode: both;
  }

  ::view-transition-old(root) {
    animation-name: voo-raiz-sai;
  }

  ::view-transition-new(root) {
    animation-name: voo-raiz-entra;
  }

  /* Ao pousar, uma faixa de luz cruza a imagem uma vez. A classe .chegou é posta e tirada pelo script. */
  .projeto.chegou picture {
    position: relative;
    overflow: clip;
    border-radius: var(--radius-md);
  }

  .projeto.chegou picture::after {
    content: "";
    position: absolute;
    top: 0;
    bottom: 0;
    left: -50%;
    width: 200%;
    pointer-events: none;
    background: linear-gradient(105deg, transparent 38%, rgb(255 255 255 / 0.5) 46%, rgb(191 211 234 / 0.6) 50%, rgb(255 255 255 / 0.5) 54%, transparent 62%); /* branco puro some na captura clara: núcleo azul da marca */
    opacity: 1; /* a faixa presa à rolagem (bloco Rolagem) fica invisível parada */
    animation: luz-pousa 520ms cubic-bezier(0.65, 0, 0.35, 1) both;
  }

  /* ---------- Rolagem ---------- */

  @supports (animation-timeline: view()) {

    .topo {
      view-timeline-name: --topo;
    }

    /* Parallax (padrão): enquanto o topo sai da tela, as janelas sobem em velocidades
       diferentes. "translate" soma com o "transform" da abertura, sem brigar. */
    .janela {
      animation: var(--abertura), afasta linear both;
      animation-timeline: auto, --topo;
      animation-range: normal, exit;
    }

    /* Cinema: só com tela larga, mouse e altura para o conteúdo grudado caber
       (em acompanha a fonte do navegador). A abertura monta as janelas; a rolagem
       constrói o conteúdo delas e a cena acaba quando Serviços começa a entrar. */
    @media (min-width: 64em) and (min-height: 40em) and (hover: hover) and (pointer: fine) {
      .topo {
        height: calc(100svh + min(60svh, 480px));
        padding-block: 0;
        view-timeline-inset: var(--altura-cabecalho, 64px) 0px; /* a cena começa no pixel 0 */
      }

      .topo .container {
        position: sticky;
        top: var(--altura-cabecalho, 64px); /* o texto fica onde estava no y=0: nada sobe ao grudar */
        min-height: calc(100svh - var(--altura-cabecalho, 64px));
        padding-block: var(--espaco-4);
        align-content: center;
      }

      /* Final (10% a 100%: a rolagem inteira mexe na cena): o site pronto cresce para cima e para a esquerda e os rascunhos recuam.
         scale e opacity separados não brigam com o transform da abertura. */
      .janela-esboco { --final: recua-esboco; }
      .janela-layout { --final: recua-layout; }
      .janela-pronta { --final: destaca-pronta; transform-origin: 100% 100%; }

      .janela {
        animation: var(--abertura), var(--final) linear forwards;
        animation-timeline: auto, --topo;
        animation-range: normal, contain 10% contain 100%;
      }
    }

    /* ---------- Faixa de fatos (noite-criativa, V5) ---------- */

    /* Duas linhas em sentidos opostos, presas à rolagem (só mexem quando a pessoa rola, então não há o que
       pausar). Cada linha fica numa linha só, mais larga que a tela, e percorre exatamente a sobra: começa
       com a ponta esquerda (ou direita) à vista e termina com a outra. Só translate. O tamanho é menor que
       o do h1 do topo (a faixa é ponte, o ponto alto é o topo): ~60% da altura da primeira versão. */
    .faixa {
      view-timeline-name: --faixa;
      font-size: clamp(1.75rem, 6vw, 4rem);
    }

    .faixa-linha {
      flex-direction: row;
      flex-wrap: nowrap;
      justify-content: flex-start;
      align-items: center;
      width: max-content;
      gap: 0 0.55em;
      text-align: left;
      white-space: nowrap;
      animation: faixa-esquerda linear both;
      animation-timeline: --faixa;
      animation-range: cover 0% cover 100%;
    }

    .faixa-linha + .faixa-linha {
      animation-name: faixa-direita;
    }

    /* Só contorno (só aqui, com a letra grande): miolo na cor do fundo e um anel de 12 sombras de
       --texto-claro em volta. Não usa -webkit-text-stroke porque a fonte variável tem contornos que se
       cruzam por dentro das letras e o traço os mostra como riscos. O anel tem no mínimo 1.25px. */
    .faixa-contorno {
      --anel: max(0.035em, 1.25px);
      color: var(--brand);
      text-shadow:
        var(--anel) 0 var(--texto-claro), calc(var(--anel) * -1) 0 var(--texto-claro),
        0 var(--anel) var(--texto-claro), 0 calc(var(--anel) * -1) var(--texto-claro),
        calc(var(--anel) * 0.866) calc(var(--anel) * 0.5) var(--texto-claro),
        calc(var(--anel) * -0.866) calc(var(--anel) * 0.5) var(--texto-claro),
        calc(var(--anel) * 0.866) calc(var(--anel) * -0.5) var(--texto-claro),
        calc(var(--anel) * -0.866) calc(var(--anel) * -0.5) var(--texto-claro),
        calc(var(--anel) * 0.5) calc(var(--anel) * 0.866) var(--texto-claro),
        calc(var(--anel) * -0.5) calc(var(--anel) * 0.866) var(--texto-claro),
        calc(var(--anel) * 0.5) calc(var(--anel) * -0.866) var(--texto-claro),
        calc(var(--anel) * -0.5) calc(var(--anel) * -0.866) var(--texto-claro);
    }

    .faixa-ponto,
    .faixa-barra {
      display: block;
    }

    /* ---------- Títulos e cortina do Contato (noite-criativa, V6) ---------- */

    /* Cada título tem o seu efeito (não repetem a fórmula). Todos declaram --titulo no h2, que não se move:
       a animação corre "por dentro" e não realimenta a medida. Termina com o título a ~40% da subida
       pela tela: quem chega por âncora já o encontra pronto.
       Serviços: o texto sobe de trás da borda de baixo do h2 (o clip-path com folga negativa é a máscara sem
       mexer no layout; acento e descendente cabem) e o traço curto se desenha da esquerda. */
    .servicos h2,
    .projetos h2,
    .como-funciona h2,
    .sobre h2 {
      view-timeline-name: --titulo;
    }

    .servicos h2 {
      clip-path: inset(-0.2em -0.1em);
    }

    .servicos .titulo-texto {
      display: block;
      animation: titulo-sobe var(--curva-rolagem) both;
      animation-timeline: --titulo;
      animation-range: cover 14% cover 40%;
    }

    .servicos h2::before,
    .projetos h2::before,
    .como-funciona h2::before,
    .sobre h2::before {
      animation-timeline: --titulo;
      animation-range: cover 8% cover 26%;
      animation-fill-mode: both;
      animation-timing-function: var(--curva-rolagem);
    }

    /* Serviços: o traço se desenha da esquerda. */
    .servicos h2::before {
      transform-origin: 0 50%;
      animation-name: linha-desenha;
    }

    /* Projetos: o fio nasce junto do título e corre para a esquerda. */
    .projetos h2::before {
      transform-origin: 100% 50%;
      animation-name: linha-desenha;
    }

    /* Como funciona: os quatro traços aparecem da esquerda para a direita, um passo de cada vez. */
    .como-funciona h2::before {
      animation-name: tracos-revelam;
      animation-timing-function: linear;
    }

    /* Sobre: a barra ao lado desce do alto do título. */
    .sobre h2::before {
      transform-origin: 50% 0;
      animation-name: barra-desce;
    }

    /* O Contato abre como uma cortina de baixo: começa um arco estreito e se abre até a largura toda
       enquanto entra. "backwards" solta o clip-path no fim, então o Contato parado é a seção normal. */
    .contato {
      animation: cortina var(--curva-rolagem) backwards;
      animation-timeline: view();
      animation-range: entry 0% entry 80%;
    }

    /* ---------- Projetos: a imagem abre como uma janela ---------- */

    /* Entrada por rolagem, à altura do voo do "Site pronto" (V4), para quem chega descendo: a imagem abre
       de uma janela pequena, um halo acende em volta dela, uma faixa de luz a cruza e o celular sobe.
       Tudo preso à `--quadro` (o .projeto-quadro não se move) e reversível. Quem chega pelo voo ou por
       âncora já encontra o fim de tudo (a imagem sobe além do intervalo), então nada toca duas vezes;
       a faixa de luz do pouso (.chegou, no relógio) só existe depois do voo. */
    .projeto-quadro {
      view-timeline-name: --quadro;
      isolation: isolate; /* o halo fica atrás da imagem sem ir para trás da seção */
    }

    .projeto-imagem {
      animation: abre var(--curva-rolagem) both;
      animation-timeline: --quadro;
      animation-range: cover 0vh cover 50vh;
    }

    /* Halo: aro de 2px, brilho azul em volta e sombra embaixo, aceso pela rolagem: sobe em 25% do trecho, fica até 65%
       e apaga no fim (cover 0 a 60vh). O elemento é fixo; só a opacidade muda. */
    .projeto-quadro::before {
      content: "";
      position: absolute;
      inset: 0;
      z-index: -1;
      border-radius: var(--radius-md);
      box-shadow: 0 0 0 2px rgb(191 211 234 / 0.95), 0 0 56px 8px rgb(143 180 220 / 0.55), 0 44px 110px -8px rgb(90 134 179 / 0.65);
      pointer-events: none;
      opacity: 0;
      animation: halo-rola linear both;
      animation-timeline: --quadro;
      animation-range: cover 0vh cover 60vh;
    }

    /* Faixa de luz da V4, a cruzar a imagem uma vez enquanto ela abre; parada nas pontas, invisível. */
    .projeto picture {
      position: relative;
      overflow: clip;
      border-radius: var(--radius-md);
    }

    .projeto picture::after {
      content: "";
      position: absolute;
      top: 0;
      bottom: 0;
      left: -50%;
      width: 200%;
      pointer-events: none;
      opacity: 0;
      background: linear-gradient(105deg, transparent 32%, rgb(255 255 255 / 0.55) 43%, rgb(143 180 220 / 0.85) 50%, rgb(255 255 255 / 0.55) 57%, transparent 68%); /* núcleo azul da marca: o branco puro some na captura clara */
      animation: luz-rola linear both;
      animation-timeline: --quadro;
      animation-range: cover 6vh cover 60vh;
    }

    /* O celular do projeto sobe de baixo com a moldura ainda pequena e transparente e, enquanto o projeto
       cruza a tela, o site dele rola por dentro da moldura. Parado, mostra o topo do site no lugar final.
       Só aparece a partir de ~70% do quadro (é onde o topo do celular entra na tela) e termina com ele
       chegando ao lugar, então o intervalo é o do fim da entrada do quadro. */
    .projeto {
      view-timeline-name: --projeto;
    }

    .projeto-celular {
      animation: celular-chega var(--curva-rolagem) both;
      animation-timeline: --quadro;
      animation-range: entry 68% entry 112%;
    }

    /* O site rola por dentro da moldura enquanto ela mesma cruza a tela: começa no hero, desce até os cartões
       quando ela acaba de entrar e volta ao hero antes de ela estar inteira e parada à vista. */
    .projeto-celular-tela {
      view-timeline-name: --cel;
    }

    .projeto-celular img {
      animation: celular-rola linear both;
      animation-timeline: --cel;
      animation-range: entry 0% contain 70%;
    }

    /* ---------- Como funciona: linha de progresso entre os números ---------- */

    /* Cada trecho cresce enquanto a leitura vai de um número ao seguinte,
       medido numa linha imaginária a 80% da altura da tela. */
    .passos li {
      position: relative;
      view-timeline-name: --passo;
    }

    .passos li:not(:last-child)::after {
      content: "";
      position: absolute;
      left: 4px;
      top: calc(var(--passos-linha, 1.625rem) + 6px);
      bottom: calc(4px - var(--passos-vao, var(--espaco-4)));
      width: 2px;
      border-radius: var(--radius-xs, 3px);
      background-color: var(--linha-passos, var(--brand));
      transform-origin: top;
      animation: progride linear both;
      animation-timeline: --passo;
      animation-range: entry 20vh entry calc(100% + 20vh + var(--passos-vao, var(--espaco-4)));
    }
  }

  /* ---------- Contato: montador e botão em palco (noite-criativa, V8) ---------- */

  .contato .botao:hover {
    translate: 0 -2px;
  }

  .contato.com-montador .botao::after {
    transition: translate 200ms var(--curva-saida);
  }

  .contato.com-montador .botao:hover::after {
    translate: 3px 0;
  }

  /* Faixa de luz que cruza o botão no hover e no foco de teclado (nunca sozinha em repetição): 650ms,
     só translate e opacity. Nome próprio (não o da entrada) para começar do zero ao passar o mouse. */
  .contato .botao:hover::before,
  .contato .botao:focus-visible::before {
    animation: luz-toque 650ms var(--curva-saida) both;
    animation-timeline: auto;
    animation-range: normal;
  }

  /* Halo respira um pouco mais quando o botão está em uso. */
  .contato-acao::before {
    transition: scale 250ms var(--curva-saida);
  }

  .contato-acao:has(.botao:hover, .botao:focus-visible)::before {
    scale: 1.05;
  }

  /* A opção marcada dá um leve salto; o balão da mensagem sobe e aparece a cada mudança de texto
     (opacity e translate curtos; o texto já está no lugar quando começa, o aria-live não espera a animação). */
  .opcao:has(:checked) {
    animation: pilula-marca 260ms var(--curva-saida);
  }

  .montador-previa output.nova {
    animation: balao-chega 220ms var(--curva-saida);
  }

  @supports (animation-timeline: view()) {
    .contato.com-montador .contato-acao {
      animation: painel-chega linear both;
      animation-timeline: view();
      animation-range: entry 0% entry 45%;
    }

    /* A faixa cruza o botão uma vez enquanto ele entra pela base da tela (do momento em que aparece até
       ~20% do percurso: no fim da página o botão já passou disso, então a faixa sempre termina). */
    .contato .botao {
      view-timeline-name: --botao-contato;
    }

    .contato .botao::before {
      animation: luz-entra linear both;
      animation-timeline: --botao-contato;
      animation-range: cover 0% cover 20%;
    }
  }

  @keyframes luz-entra {
    from { translate: -80% 0; opacity: 1; }
    to   { translate: 80% 0; opacity: 1; }
  }

  @keyframes luz-toque {
    from { translate: -80% 0; opacity: 1; }
    to   { translate: 80% 0; opacity: 1; }
  }

  @keyframes pilula-marca {
    from { scale: 0.94; }
  }

  @keyframes balao-chega {
    from { opacity: 0; translate: 0 8px; }
  }

  @keyframes painel-chega {
    from { opacity: 0; translate: 0 32px; }
  }

  /* ---------- Rodapé: painel de medidas (noite-criativa, V7) ---------- */

  /* Entrada e saída do popover: opacidade e translate em 180ms. O `display` e o `overlay` em
     allow-discrete seguram o painel na tela até a saída terminar. Sem suporte, ele só aparece e some. */
  @supports selector(:popover-open) {
    .ficha {
      opacity: 0;
      translate: 0 24px;
      transition:
        opacity 180ms var(--curva-saida),
        translate 180ms var(--curva-saida),
        display 180ms allow-discrete,
        overlay 180ms allow-discrete;
    }

    .ficha:popover-open {
      opacity: 1;
      translate: 0 0;
    }

    @starting-style {
      .ficha:popover-open {
        opacity: 0;
        translate: 0 24px;
      }
    }

    @media (min-width: 64em) {
      .ficha {
        translate: 0 8px;
      }

      @starting-style {
        .ficha:popover-open {
          translate: 0 8px;
        }
      }
    }
  }

  /* Ponto de "Medido agora": três pulsos (4,8s no total, menos que os 5s da WCAG 2.2.2), só com o painel aberto. */
  .ficha-ponto::after {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: 50%;
    background-color: var(--ficha-luz);
    opacity: 0;
  }

  .ficha:popover-open .ficha-ponto::after {
    animation: ficha-pulso 1600ms ease-out 3;
  }

  @keyframes ficha-pulso {
    from { opacity: 0.6; scale: 1; }
    to   { opacity: 0; scale: 1.8; }
  }

  /* ---------- Quadros ---------- */

  @keyframes aurora {
    from { transform: translate(-3%, -2%) rotate(-4deg); }
    to   { transform: translate(3%, 2%) rotate(4deg) scale(1.05); }
  }

  @keyframes surge {
    from { opacity: 0; transform: scale(0.94); }
  }

  @keyframes sobe {
    from { opacity: 0; transform: translateY(12%); }
    50% { opacity: 1; } /* opaca antes de pousar: não fica cinza no caminho */
  }

  /* 3px = --radius-xs, por extenso como a curva. A opacidade evita um ponto escuro solto no começo. */
  @keyframes enche {
    from { clip-path: inset(0 100% 0 0 round 3px); opacity: 0; }
    20%  { opacity: 0; }
    60%  { opacity: 1; }
    to   { clip-path: inset(0 0 0 0 round 3px); opacity: 1; }
  }

  /* 125%: sobra para o texto ficar todo atrás da borda de baixo, mesmo com folga na máscara. */
  @keyframes titulo-sobe {
    from { translate: 0 125%; }
  }

  @keyframes linha-desenha {
    from { scale: 0 1; }
  }

  /* Quatro traços revelados por recorte, da esquerda para a direita. */
  @keyframes tracos-revelam {
    from { clip-path: inset(0 100% 0 0); }
    to   { clip-path: inset(0); }
  }

  @keyframes barra-desce {
    from { scale: 1 0; }
  }

  /* Arco de cúpula que se abre até a seção inteira; 100% aqui é do tamanho da própria seção. */
  @keyframes cortina {
    from { clip-path: inset(14% 10% 0 10% round 50% 50% 0 0 / 22% 22% 0 0); }
    to   { clip-path: inset(0 0 0 0 round 0 0 0 0 / 0 0 0 0); }
  }

  @keyframes afasta {
    to { translate: 0 var(--afasta); }
  }

  @keyframes recua-esboco {
    to { opacity: 0.8; scale: 0.96; } /* 0.8: o nome "Esboço" mantém 4.5:1 sobre o vidro e a aurora (medido nos pixels) */
  }

  @keyframes recua-layout {
    to { opacity: 0.9; scale: 0.97; }
  }

  @keyframes destaca-pronta {
    to { scale: 1.04; }
  }

  /* Janela pequena e centrada que se abre até a moldura inteira; o scale acompanha para a imagem crescer
     junto com o recorte (sem ele, só o recorte, ela parece fixa e "descoberta"). */
  @keyframes abre {
    from { clip-path: inset(18% 22% 26% round var(--radius-md)); scale: 0.92; }
    to   { clip-path: inset(0 round var(--radius-md)); scale: 1; }
  }

  @keyframes halo-rola {
    0%   { opacity: 0; }
    25%  { opacity: 1; }
    65%  { opacity: 1; }
    100% { opacity: 0; }
  }

  /* Igual ao luz-pousa (translate de -36% a 36% de uma faixa de 200% da imagem), invisível nas pontas. */
  @keyframes luz-rola {
    0%   { translate: -36% 0; opacity: 0; }
    15%  { opacity: 1; }
    85%  { opacity: 1; }
    100% { translate: 36% 0; opacity: 0; }
  }


  /* Vai até o meio do site e volta ao topo: o quadro final é o hero (título e botão grandes), legível pequeno. */
  @keyframes celular-rola {
    from { translate: 0 0; }
    50%  { translate: 0 -61%; }
    to   { translate: 0 0; }
  }

  @keyframes celular-chega {
    from { translate: 0 48px; scale: 0.94; }
    to   { translate: 0 0; scale: 1; }
  }

  @keyframes progride {
    from { scale: 1 0; opacity: 0; }
    15%  { opacity: 1; }
    to   { scale: 1 1; opacity: 1; }
  }

  /* 100cqw = largura da faixa (contêiner); 100% = largura da própria linha. */
  @keyframes faixa-esquerda {
    from { translate: 0 0; }
    to   { translate: calc(100cqw - 100%) 0; }
  }

  @keyframes faixa-direita {
    from { translate: calc(100cqw - 100%) 0; }
    to   { translate: 0 0; }
  }

  /* V4: voo do Site pronto */
  @keyframes voo-halo {
    from { box-shadow: 0 0 0 1px rgb(191 211 234 / 0), 0 40px 90px -20px rgb(90 134 179 / 0); }
    35%  { box-shadow: 0 0 0 1px #BFD3EA, 0 40px 90px -20px rgb(90 134 179 / 0.55); }
    to   { box-shadow: 0 0 0 1px rgb(191 211 234 / 0), 0 40px 90px -20px rgb(90 134 179 / 0); }
  }

  @keyframes voo-entra {
    from { opacity: 0; }
    to   { opacity: 1; }
  }

  @keyframes voo-raiz-sai {
    from { scale: 1; }
    to   { scale: 0.985; }
  }

  @keyframes voo-raiz-entra {
    from { opacity: 0; }
    to   { opacity: 1; }
  }

  /* Translação em % da faixa (200% da imagem): a luz entra à esquerda e sai à direita. */
  @keyframes luz-pousa {
    from { translate: -36% 0; }
    to   { translate: 36% 0; }
  }
}
