GSAP
/v2/vendor/gsap.min.js?v=3.15.0
Motor de tween. O WDF só liga o resto se gsap existir. Default de duração no registro: 1.15s, ease wdf.out.
/// 00 · autópsia visual
A LP da Upward Academy em /promo parece “nível Apple” porque o HTML já nasce no estado final, as seções trocam de pele, e o JS só anima. O curso é outro assunto. Aqui está o que o site faz.
/// 00 até 10, cada uma com data-theme.theme-color junto.wdf.*.js./// 01 · o que está no ar
Captura do HTML vivo em 29/10/2026. Comentários no próprio arquivo mapeiam um spec interno (core-top F0a, chrome-top F0b, §4.x). Quem desenhou isso pensa em peças, não em “seções de LP”.
<style> de 137 kB. Zero CSS externo.frame_0042.webp./v2/dist/wdf.4167b7bf16.js (109 kB) expõe WDF 2.0.0, registra plugins, cria as eases wdf.out e wdf.inout.lerp: .09, autoRaf: false, tick no ticker do GSAP.requestIdleCallback.no-js, coloca is-motion ou is-static.saveData, hash na URL, UTM/gclid/fbclid, mobile < 900px, ou preloader já visto na sessão.history.scrollRestoration = 'manual' porque o Lenis manda no scroll./// 02 · as libs
Tudo self-hosted em /v2/vendor/ e um bundle próprio. A ordem no HTML é a ordem do motor: GSAP primeiro, plugins, Lenis, WDF por último. Tracking fica de fora dessa fila — entra no idle.
/v2/vendor/gsap.min.js?v=3.15.0
Motor de tween. O WDF só liga o resto se gsap existir. Default de duração no registro: 1.15s, ease wdf.out.
/v2/vendor/ScrollTrigger.min.js?v=3.15.0
Pin, scrub e troca de pele. Cada section[data-theme] dispara em start: "top 60px" e o bundle pinta o theme-color.
/v2/vendor/SplitText.min.js?v=3.15.0
Quebra títulos em lines e words — não em letras. Plugin pago do GSAP Club. No caderno da Gestão Bem, um reveal CSS cobre o mesmo papel.
/v2/vendor/CustomEase.min.js?v=3.15.0
Cria as duas curvas do sistema: wdf.out .19,1,.22,1 e wdf.inout .77,0,.18,1. É a mesma bezier do CSS.
/v2/vendor/lenis.min.js?v=1.3.26
lerp: .09, smoothWheel: true, syncTouch: false, autoRaf: false. O RAF é o ticker do GSAP. Touch fica nativo. respectReducedMotion: false — quem corta o smooth é o boot is-static.
/v2/dist/wdf.4167b7bf16.js
O design system. Expõe window.WDF: registra plugins, cria as eases, liga Lenis, cursor, magnético, preloader, dock e o bus das camadas. Sem isso, os vendors são só arquivos.
ok = gsap && ScrollTrigger
&& SplitText && CustomEase
ok && gsap.registerPlugin(
ScrollTrigger, SplitText, CustomEase)
ok && CustomEase.create(
"wdf.out", ".19,1,.22,1")
ok && gsap.defaults({
ease: "wdf.out", duration: 1.15 })
Self-hosted em /v2/fonts/, subset PT, preload no <head>. Não passam por fonts.googleapis.com.
Três tags num requestIdleCallback (fallback 3s). Fora da fila GSAP/Lenis, depois da página interativa.
Não entra no HTML
/// 03 · anatomia
Os comentários do HTML separam chrome (sempre presente) de seções (que só pintam). É por isso que o site não “parece template”.
F0a · core-top
Ícones e logo num sprite. Skip link. Toast e <dialog> prontos. Entra logo depois do body.
F0b · chrome-top
Grade 64px no preloader, duas tampas que se abrem. Nav em pílulas de vidro. Rail de progresso. Cursor dot+anel. Grain SVG.
Main · 13 seções
Cada <section data-theme> é ink, paper ou flame. O ScrollTrigger sincroniza o theme-color do browser quando a seção cruza 60px do topo.
Tipo
Display (NeuePower), corpo (Geist), mono (kickers). Mega usa min(vw, svh). Corpo fixo em 16px. Kicker 12px com /// 00 ·.
Motion
cubic-bezier(.19, 1, .22, 1) em tudo. Durações xs 0.15 / s 0.3 / m 0.45 / l 0.9 / xl 1.15. SplitText em linhas, não em letras.
F0b · chrome-bottom
Botão flutuante no desktop, dock de conversão no mobile. Visibilidade por JS. CTA magnético com --mx/--my.
/// 04 · as três peles
Eles não pintam seção por seção com hex solto. Têm um dicionário (--ink, --paper, --flame) e um segundo dicionário semântico (--bg, --display, --cta-bg) que cada pele reescreve. O caderno que você está lendo usa os hex reais.
Paper inverte o contraste (fundo quente, texto ink, acento flame-deep). Flame vira o laranja em palco e o ink vira o acento. CTA sempre “o contrário do fundo”: branco no ink, ink no paper e no flame. Uma cor de marca, usada como interruptor — não como gradiente em tudo.
[data-theme=ink] { --bg: var(--ink); --display: #fff; --cta-bg: #fff; --accent: var(--flame); }
[data-theme=paper] { --bg: var(--paper); --display: var(--ink); --cta-bg: var(--ink); --accent: var(--flame); }
[data-theme=flame] { --bg: var(--flame); --display: #fff; --cta-bg: var(--ink); --accent: var(--ink); }
/// 05 · escala
Na LP o display chega a 172px e o mega usa o menor entre a viewport e 46svh. Corpo travado em 16 / 14 / 12. Kickers em 12px com letter-spacing aberto. Isso é o “nível Apple”: um cartaz, não um artigo.
--fs-statementPáginas que pesam.--fs-d2Uma ideia por seção.--fs-leadLead curto, no máximo 44ch.--fs-body 16Corpo que não cresce com a viewport.--fs-kicker 12/// 05 · escala/// 06 · chrome
Preloader, grain, cursor e botão magnético não vendem o curso. Eles dizem “isso foi feito à mão”. No desktop. No mobile eles desligam metade.
SVG de 160px com feTurbulence, opacity 0.06 (0.045 no paper). No desktop com motion, o bitmap anda em steps(1) a cada 1.2s — parece filme, não GIF. Este caderno usa o mesmo truque.
Dot de 6px + anel de 38px. Lerp no anel (1 − 0.82^(dt×60)). Em links o anel cresce e pode mostrar um label mono. Some se um dialog abre. Prefer reduced-motion: nem nasce.
Classe .magnetic + CSS translate: var(--mx) var(--my). O JS mede o retângulo, tira o offset atual, escreve a diferença. O botão “Pular para a receita” deste caderno faz a versão curta.
Grade 64px com máscara radial, duas tampas ink. Se o visitante veio de anúncio (UTM), está no celular, ou já viu nesta sessão — pre-skip e o preloader nem pinta. Performance como feature de marca.
/// 07 · o pulo do gato
Comentário literal da seção Solução: “HTML no ESTADO FINAL (.is-struck .is-selected .is-checked .is-paid); em is-motion o JS remove as classes ainda não alcançadas e as reaplica.” Autor: a foto já aparece inteira no CSS; o JS só esconde o rosto se houver motion.
Quem abre o arquivo sem JavaScript ainda vê a página vendida. O motion é um verniz, não a estrutura.Leitura dos comentários em /promo · 29/10/2026
Isso mata CLS, mata o “flash de conteúdo vazio” e deixa o no-js utilizável. Para as LPs da Gestão Bem: escreve o markup como se a animação já tivesse acabado. Se o GSAP falhar, a página continua certa.
/// 08 · motion
CustomEase.create("wdf.out", ".19,1,.22,1") — a mesma curva do CSS.lines e words, não em caracteres (barato e legível).lerp: .09, smoothWheel: true, syncTouch: false. O RAF é o ticker do GSAP, não um loop paralelo.prefers-reduced-motion — vira is-static e o HTML final permanece./// 09 · o roteiro
A beleza também é editorial: ink → paper → ink → paper → flame no preço → paper no autor → ink na garantia. O olho descansa. A oferta só pinta de laranja quando precisa.
Ink. Figura + first-frame webp. Layout side/stack medido no inline.
inkAinda ink. Continuação do herói, sem quebrar a pele.
inkPaper. HTML já com struck/selected/checked/paid.
paper“Do zero absoluto à página vendida.” Volta ink.
inkBloco oculto a pedido do dono; anatomia continua no DOM.
ink · hiddenPaper. Prova social no fundo quente.
paperInk. “Galeria que liga ao chegar.” Posters já coloridos no HTML.
inkPaper. “Sumário vivo”, sem pin de scroll.
paperFlame. A única seção que vira o laranja em palco.
flamePaper. Cortina da armadura → rosto, scrub reversível.
paperInk de novo, depois do choque laranja.
inkFAQ paper; fecho ink com data-ui-theme=flame no chrome.
/// 10 · o que copiar
Oito hábitos. Nenhum pede GSAP Club, NeuePower nem 137 kB de CSS. O caderno que você está vendo já faz 1, 2, 3, 5 e 7.
01
--bg --fg --accent --muted --line. Uma pele dark, uma paper, uma de acento. Seção declara a pele, não o hex.
02
/// 00 · em mono. O visitante sabe onde está. Custa um :before.
03
cubic-bezier(.19, 1, .22, 1) em hover, translate e theme. Duração 150–250 ms no UI, 900–1150 ms no reveal.
04
Escreve a seção já “terminada”. Motion só descasca e recoloca. No-js continua vendendo.
05
SVG noise a 5%. Padding de seção clamp(96px, 14vh, 180px) na LP; aqui um pouco menos, a ideia é a mesma: ar.
06
Display com personalidade, corpo neutro, mono pra meta. Self-hosted. Preload só do first-frame e das woff2 do herói.
07
Preloader, cursor, Lenis no touch, grain animado: off abaixo de 900px, off em UTM, off em reduced-motion.
08
Hero side/stack e altura da figura no inline, não no bundle. CLS zero é parte do “bonitão”.
/// 11 · o que não copiar
Cursor custom em formulário. 137 kB de CSS inline. SplitText Club se um reveal CSS resolve. Copiar NeuePower, os posters, os depoimentos, o copy do curso. Pixel/Clarity “porque a LP tem”. Flame em todas as seções — eles usam uma vez, no preço.
Pele por seção. Kicker. HTML final. Uma easing. Grain quieto. Self-hosted. Tracking idle. Comentários no HTML apontando o spec (eles fazem isso; o arquivo vira documentação).