/* ═══════════════════════════════════════════════════════════════════════════
   COMPILA · MOTOR — A LINGUAGEM DE MOVIMENTO
   ---------------------------------------------------------------------------
   Um vocabulário só para o site inteiro. Nenhum componente inventa o próprio
   tempo, a própria curva ou a própria distância: tudo sai daqui.

   Os dois tipos de movimento, e a diferença custa caro:

     ENTRADA  [data-m]   O elemento chega uma vez. Um IntersectionObserver põe
                         a classe .m-in e a TRANSIÇÃO do CSS faz o resto, no
                         compositor. Custo por quadro: ZERO.

     RASPADO  [data-mk]  O elemento acompanha a rolagem o tempo todo. O motor
                         escreve --k (0→1) enquanto ele está na tela. Custo por
                         quadro: uma escrita. Reservado para o punhado de
                         momentos que são cinema de verdade.

   Regra que não se quebra: só transform e opacity. Nada de width, top, filter
   ou box-shadow por quadro — são as duas únicas coisas que o compositor
   resolve sozinho, sem passar por layout nem por pintura.
   ═════════════════════════════════════════════════════════════════════════ */

:root{
  /* ── FORÇA ────────────────────────────────────────────────────────────────
     O único botão do sistema. Toda distância e toda profundidade multiplica
     por ele. Celular baixa para .55; movimento reduzido zera. Mudar a
     intensidade do site inteiro é mudar este número.                        */
  --forca: 1;

  /* ── TEMPO ──────────────────────────────────────────────────────────────
     Quatro faixas. Microinteração é resposta, não animação: tem que parecer
     instantânea. Cena é cinema: pode respirar.                              */
  --t-micro:  140ms;   /* pressão, foco, troca de cor      */
  --t-ui:     260ms;   /* hover, estado, abrir/fechar      */
  --t-entra:  620ms;   /* um elemento chegando             */
  --t-cena:  1100ms;   /* uma cena entregando a próxima    */

  /* ── CURVAS ─────────────────────────────────────────────────────────────
     Quem chega desacelera. Quem sai acelera. A câmera começa e termina
     parada. Só a microinteração tem um triz de volta, e só ela.             */
  --e-chega: cubic-bezier(.22, 1, .36, 1);
  --e-sai:   cubic-bezier(.55, 0, .85, .4);
  --e-cena:  cubic-bezier(.65, 0, .35, 1);
  --e-toque: cubic-bezier(.34, 1.36, .64, 1);

  /* ── DISTÂNCIA ──────────────────────────────────────────────────────────
     Quatro degraus. O tamanho do elemento escolhe o degrau: texto anda
     pouco, painel anda muito. Misturar os dois é o que faz uma página
     parecer animada por várias pessoas diferentes.                          */
  --d-micro:  calc(  4px * var(--forca));
  --d-texto:  calc( 22px * var(--forca));
  --d-card:   calc( 44px * var(--forca));
  --d-painel: calc( 84px * var(--forca));

  /* ── PROFUNDIDADE: a escada de Z ────────────────────────────────────────
     Cinco planos fixos, e nada mora fora deles. É isso que faz o site
     inteiro parecer um espaço só em vez de vinte caixinhas com perspectiva
     própria. A `perspective` mora na SEÇÃO, nunca no card: uma perspectiva
     por elemento dá a cada um o seu próprio ponto de fuga, e o espaço
     compartilhado desaparece.                                               */
  --z-fundo:  calc(-420px * var(--forca));
  --z-longe:  calc(-180px * var(--forca));
  --z-base:   0px;
  --z-perto:  calc(  60px * var(--forca));
  --z-frente: calc( 140px * var(--forca));
  --persp: 1200px;

  /* ── LUZ ────────────────────────────────────────────────────────────────
     O brilho é raro e é sempre o mesmo. Um acento que está em tudo não é
     acento.                                                                 */
  --luz-sutil: 0 0 0 1px rgba(79,195,247,.14), 0 8px 30px rgba(79,195,247,.10);
  --luz-foco:  0 0 0 1px rgba(255,201,60,.34), 0 14px 44px rgba(255,201,60,.16);
}

/* ── celular: mesma narrativa, menos camadas ──────────────────────────────
   Não é o desktop encolhido. A força cai, a perspectiva encurta (tela
   estreita com perspectiva longa achata o 3D) e a escada de Z usa três
   degraus em vez de cinco.                                                  */
@media (max-width: 900px){
  :root{
    --forca: .55;
    --persp: 860px;
    --z-fundo:  calc(-240px * var(--forca));
    --z-longe:  calc(-120px * var(--forca));
    --z-frente: var(--z-perto);
  }
}

/* ═══════════════════════════════════════════════════════════════════════════
   ENTRADAS — custo zero por quadro
   ---------------------------------------------------------------------------
   Estado de partida no [data-m], estado final no [data-m].m-in. O prefixo
   completo em ambos é de propósito: entrada declarada só no estado inicial
   perde na cascata para qualquer regra posterior, e a animação some sem aviso.
   ═════════════════════════════════════════════════════════════════════════ */

[data-m]{
  transition: opacity var(--t-entra) var(--e-chega),
              transform var(--t-entra) var(--e-chega);
  transition-delay: var(--m-atraso, 0ms);
}

/* Sem JS, tudo aparece. A animação é enfeite, nunca requisito de leitura. */
.js [data-m]{ opacity: 0 }

/* selo: cresce de dentro, como um carimbo */
.js [data-m="selo"]      { transform: scale(.82) }
/* texto: sobe para o lugar */
.js [data-m="texto"]     { transform: translateY(var(--d-texto)) }
.js [data-m="titulo"]    { transform: translateY(var(--d-texto)) }
.js [data-m="sobe"]      { transform: translateY(var(--d-texto)) }
/* cartão: sobe e vem de um degrau de profundidade.
   O transform é escrito UMA vez e parametrizado por variáveis. Cada seção
   ajusta a chegada mexendo em --fundura, --m-x, --m-ry, --m-rz e --m-escala,
   nunca reescrevendo o transform: uma regra de seção seria mais específica
   que a de .m-in e o cartão nunca chegaria ao lugar. */
.js [data-m="cartao"]{
  transform: translate3d(var(--m-x, 0px), var(--d-card), calc(var(--z-longe) * var(--fundura, 1)))
             rotateY(var(--m-ry, 0deg)) rotateZ(var(--m-rz, 0deg))
             scale(var(--m-escala, 1));
}
/* painel: vem de longe, é grande e por isso anda mais */
.js [data-m="painel"]{
  transform: translate3d(0, var(--d-painel), calc(var(--z-fundo) * var(--fundura, 1)));
}
/* lado: entra pela borda, alternando por irmão (--lado vem do JS) */
.js [data-m="lado"]      { transform: translateX(var(--lado, var(--d-card))) }

[data-m].m-in{ opacity: 1; transform: none }

/* Delays aposentados quando a entrada termina. Sem isto, todo hover nos
   irmãos posteriores herda o atraso do escalonamento — para sempre. A regra
   precisa ganhar em especificidade de quem escreveu o delay.                */
[data-m].m-in.m-feito{ transition-delay: 0ms !important; --m-atraso: 0ms }

/* A camada de composição só existe durante o voo. Ligada no registro pelo
   observer, desligada no fim da transição. Nunca permanente.                */
[data-m].m-voando{ will-change: transform, opacity }

/* ── título em letras: o momento assinado ─────────────────────────────────
   Opt-in, e só em três lugares do site. Antes TODO h1/h2 era dividido, o que
   dava 366 spans com transform próprio: caro de estilo e barato de efeito,
   porque um efeito que está em todo título não impressiona em nenhum.       */
[data-m="titulo-letras"]{ opacity: 1; transform: none; transition: none }
.m-w{ display: inline-block; white-space: pre }
.m-ch{
  display: inline-block;
  opacity: 0;
  transform: translateY(var(--jy, 18px)) rotate(var(--jr, 0deg));
  transition: opacity 520ms var(--e-chega), transform 520ms var(--e-chega);
  transition-delay: var(--chd, 0ms);
}
[data-m="titulo-letras"].m-in .m-ch{ opacity: 1; transform: none }
[data-m="titulo-letras"].m-in.m-feito .m-ch{ transition-delay: 0ms !important }

/* ═══════════════════════════════════════════════════════════════════════════
   RASPADOS — uma escrita por quadro, e só enquanto visíveis
   ═════════════════════════════════════════════════════════════════════════ */

/* linha que se desenha: um path de SVG, um elemento, zero layout */
[data-mk="traco"]{
  stroke-dasharray: var(--len, 1000);
  stroke-dashoffset: calc(var(--len, 1000) * (1 - var(--k, 1)));
}

/* barra que preenche: scaleX, nunca width */
[data-mk="barra"]{
  transform-origin: 0 50%;
  transform: scaleX(var(--k, 1));
}

/* algo que se aproxima conforme você avança */
[data-mk="aproxima"]{
  transform: translate3d(0, 0, calc(var(--z-longe) * (1 - var(--k, 1))));
}

/* ═══════════════════════════════════════════════════════════════════════════
   MICROINTERAÇÕES — resposta, não animação
   ═════════════════════════════════════════════════════════════════════════ */

/* O botão afunda um triz quando é pressionado. Catorze centésimos de segundo:
   uma microinteração é RESPOSTA, e resposta que demora deixa de responder. */
.btn, .cr-btn, .c-btn, .course-cta, .btn-nav-cta, .btn-copy, .m-toque{
  transition: transform var(--t-micro) var(--e-toque),
              box-shadow var(--t-ui) var(--e-chega),
              background-color var(--t-ui) var(--e-chega),
              border-color var(--t-ui) var(--e-chega);
}
.btn:active, .cr-btn:active, .c-btn:active, .course-cta:active,
.btn-nav-cta:active, .btn-copy:active, .m-toque:active{
  transform: translateY(2px) scale(.985);
}

/* O cartão responde ao ponteiro com PROFUNDIDADE, não com sombra maior: é a
   mesma escada de Z do resto do site, e é o que faz um hover parecer parte
   do mesmo mundo em vez de um efeito avulso. Só onde existe ponteiro fino —
   num celular isto seria custo sem efeito, porque hover não acontece. */
@media (hover: hover) and (pointer: fine){
  .c-card.m-feito, .course-card.m-feito, .trilha-card.m-feito,
  .gallery-grid > .m-feito, .challenge-grid > .m-feito, .m-sobe-hover{
    transition: transform var(--t-ui) var(--e-chega),
                box-shadow var(--t-ui) var(--e-chega);
  }
  .c-card.m-feito:hover, .course-card.m-feito:hover, .trilha-card.m-feito:hover,
  .gallery-grid > .m-feito:hover, .challenge-grid > .m-feito:hover,
  .m-sobe-hover:hover{
    transform: translate3d(0, -4px, var(--z-perto));
  }
}

/* ═══════════════════════════════════════════════════════════════════════════
   MOVIMENTO REDUZIDO — estado final, layout intacto
   ---------------------------------------------------------------------------
   Zerar --forca sozinho não basta: os elementos ficariam em opacity 0 até o
   observer passar. Aqui tudo já nasce chegado.
   ═════════════════════════════════════════════════════════════════════════ */
@media (prefers-reduced-motion: reduce){
  :root{ --forca: 0 }
  .js [data-m], [data-m], .m-ch{
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
    transition-delay: 0ms !important;
    will-change: auto !important;
  }
  [data-mk="traco"]{ stroke-dashoffset: 0 !important }
  [data-mk="barra"]{ transform: scaleX(1) !important }
  [data-mk="aproxima"]{ transform: none !important }
  html{ scroll-behavior: auto !important }
}

/* A mesma pausa, agora para quem trocou de aba. Animation-play-state não se
   herda, então a regra precisa alcançar pseudo-elementos um por um.         */
body.m-pausado *,
body.m-pausado *::before,
body.m-pausado *::after{ animation-play-state: paused !important }

/* ═══════════════════════════════════════════════════════════════════════════
   NADA ESCAPA PARA O LADO — e por que a regra NÃO está aqui
   ---------------------------------------------------------------------------
   A receita de manual é `overflow-x: clip` no html E no body. Aqui ela não
   pode entrar, e custou uma regressão descobrir: com overflow no <html>, o
   `position: sticky` do palco da abertura PARA DE GRUDAR. O palco sai da tela
   junto com a rolagem e a cena inteira — notebook, código, painéis — some,
   deixando só o fundo. Medido: o topo do palco ia para -6200px em vez de 0.

   O body já carrega `overflow-x: hidden` desde sempre e isso basta nesta
   página: conferido com todos os cartões no estado de partida (inclusive os
   dos desafios, que entram pela direita), a largura de rolagem continua igual
   à da janela e `scrollTo(400,0)` não move nada.

   Regra de convivência: entrada lateral nova é sempre conferida contra a
   largura da página, porque aqui não existe a rede do overflow no html.
   ═════════════════════════════════════════════════════════════════════════ */
