Prompt
skill @scroll-web.md
Prompt completo
name: Scroll-web
description: >
Converte um ficheiro de vídeo numa experiência web premium controlada por scroll,
usando sequência de frames em canvas, GSAP ScrollTrigger e scroll suave com Lenis.
O objetivo não é apenas "animar um vídeo", mas criar uma narrativa visual premium,
com coreografia por camadas, hierarquia tipográfica agressiva, desempenho sólido
e comportamento responsivo previsível.
goal:
primary: >
Transformar um vídeo num produto web interativo em que o scroll controla a
progressão visual do canvas e ativa secções editoriais coreografadas.
success_definition:
- O canvas responde ao scroll sem flicker nem saltos visíveis.
- A leitura do conteúdo continua clara sobre o fundo visual.
- O utilizador sente progressão narrativa, não repetição de efeitos.
- O layout mantém qualidade visual em desktop e fallback limpo em mobile.
inputs:
required:
- video_path: caminho para um ficheiro de vídeo local (mp4, mov, webm, etc.)
optional:
- brand_name: nome da marca ou produto
- theme: tema editorial ou direção conceptual
- copy_sections: lista de secções com label, título, texto e CTA
- palette: cores preferidas
- design_direction: estilo visual pretendido
- stats: lista de métricas numéricas para a secção de estatísticas
- nav_items: itens do header fixo
defaults_when_missing:
- Inferir paleta a partir do primeiro frame e do tema visual dominante.
- Gerar entre 5 e 7 secções editoriais.
- Assumir direção visual "premium editorial / product reveal".
- Se faltarem estatísticas, gerar secção factual apenas se houver dados plausíveis; caso contrário, omitir essa secção.
decision_priority:
- 1: correção funcional e ausência de flicker
- 2: fluidez de scroll e estabilidade do canvas
- 3: legibilidade do conteúdo
- 4: hierarquia visual premium
- 5: efeitos decorativos e flourishes
output_contract:
required_files:
- index.html
- css/style.css
- js/app.js
- data/manifest.json
- README.md
- frames/desktop/frame_0001.webp ...
optional_files:
- frames/mobile/frame_0001.webp ...
manifest_must_include:
- frameCount
- width
- height
- fps
- aspectRatio
- desktopPathPattern
- mobilePathPattern_if_available
- introFrameCount
- sequenceEndProgress
README_must_include:
- comando usado para ffprobe
- comando usado para ffmpeg
- como servir localmente por HTTP
- limitações conhecidas
- tuning knobs principais
non_negotiables:
- Usar canvas para o frame sequence principal; não usar <video> para scrubbing.
- Usar Lenis para scroll suave e GSAP ScrollTrigger para orquestração.
- Renderizar frames apenas em requestAnimationFrame, nunca diretamente no evento de scroll.
- Não repetir o mesmo tipo de animação em duas secções consecutivas.
- Aplicar revelação escalonada: label -> título -> texto -> CTA.
- Em desktop, o conteúdo editorial deve viver nas laterais; o centro pertence ao produto.
- Apenas a secção de estatísticas pode usar conteúdo centrado.
- O CTA final deve persistir visualmente no fecho da experiência.
- Sem glassmorphism por defeito.
- Se houver conflito entre efeito e legibilidade, cortar o efeito.
visual_system:
typography:
hero_title_min: 12rem
section_title_min: 4rem
marquee_min: 10vw
preferred_line_length: 10-16 words per line em headlines
content_alignment:
desktop:
left_zone: padding-left 5vw / padding-right 55vw
right_zone: padding-left 55vw / padding-right 5vw
rule: usar apenas align-left ou align-right
tablet:
rule: permitir compressão lateral moderada
mobile:
rule: pode centrar texto; adicionar fundo de contraste simples por trás do texto quando necessário
style_rules:
- fundos limpos
- contraste alto
- hierarquia por tamanho, peso e cor
- sem cartões translúcidos desnecessários
- espaçamento vertical amplo
marquee:
- incluir pelo menos um bloco tipográfico horizontal gigante
- tamanho mínimo 12vw em desktop
- movimento horizontal ligado ao scroll
stats_overlay:
- overlay escuro obrigatório
- opacidade entre 0.88 e 0.92
- números animam sempre a partir de 0
- preservar decimais e sufixos
section_choreography:
required_animation_pool:
- fade-up
- slide-left
- slide-right
- scale-up
- rotate-in
- stagger-up
- clip-reveal
rules:
- nunca usar o mesmo data-animation em duas secções consecutivas
- variar também a direção de entrada
- alternar secções align-left e align-right sempre que fizer sentido editorial
- reservar os efeitos mais fortes para hero, marquee e transições-chave
sequence_template:
- hero-intro
- product-sequence-start
- editorial-sections
- dark-stats-overlay
- marquee-break
- final-cta-persist
scroll_architecture:
hero:
- secção independente de 100vh
- domina entre 18% e 25% do percurso narrativo
- desaparece antes da sequência principal assumir o palco
canvas:
- sticky, full viewport
- produto central e dominante
- IMAGE_SCALE preferencial entre 0.82 e 0.90
total_scroll:
rule: >
calcular com base no número de secções; para 6 secções, usar como referência
750vh a 900vh em desktop, nunca menos de 650vh
frame_timeline:
- a sequência principal deve completar-se por volta de 50% a 60% do progresso total
- usar 55% como default
- não usar multiplicadores ambíguos tipo "1.8-2.2" sem fórmula explícita
final_cta:
- manter visível no fecho
- segurar a permanência visual durante os últimos 80vh a 120vh
- pode usar data-persist="true"
hero_to_canvas_transition:
- O hero deve sair gradualmente.
- O canvas deve entrar com revelação circular via clip-path: circle().
- A transição deve parecer uma transferência de protagonismo, não um corte.
- O primeiro frame útil do canvas tem de estar pronto antes de a máscara abrir.
video_analysis:
command: >
ffprobe -v error -select_streams v:0 -show_entries
stream=width,height,duration,r_frame_rate,nb_frames -of csv=p=0 "<VIDEO>"
must_extract:
- width
- height
- duration
- fps
- total_frames
- aspect_ratio
target_frame_policy:
short_video_under_10s:
- preferir fps original até ~300 frames
medium_video_10s_to_30s:
- extrair a 10-15 fps
long_video_over_30s:
- extrair a 5-10 fps
frame_budget:
desktop: 150-260 frames default
mobile: 70-140 frames default
rule: >
evitar 300+ frames salvo razão forte; a prioridade é fluidez, não obsessão com granularidade invisível
frame_export:
format: webp
rationale: >
WebP é o formato de primeira escolha para reduzir peso mantendo boa qualidade visual.
export_rules:
- manter proporção original
- limitar largura máxima desktop a 1920
- gerar variante mobile a 1280 ou menos quando necessário
- qualidade default 80
commands:
desktop: >
ffmpeg -i "<VIDEO>" -vf "fps=,scale=:-1"
-c:v libwebp -quality 80 "frames/desktop/frame_%04d.webp"
mobile_optional: >
ffmpeg -i "<VIDEO>" -vf "fps=,scale=:-1"
-c:v libwebp -quality 76 "frames/mobile/frame_%04d.webp"
loading_strategy:
doctrine: >
Não bloquear a experiência inteira sem necessidade, mas também nunca expor scrub
sobre frames que ainda não estão prontos.
phases:
- phase_1_boot:
load: primeiros 8-12 frames essenciais
requirement: primeiro frame visível desenhado com sucesso
- phase_2_ready_buffer:
load: frames seguintes até cobrir o arranque da narrativa visual
requirement: hero e entrada do canvas podem começar
- phase_3_full_unlock:
load: restantes frames em lotes de 15-20
requirement: só libertar totalmente a zona de scrub quando a sequência inteira estiver pronta
loader_rules:
- nunca esconder o loader antes de existir first paint válido do canvas
- só mostrar progresso real
- em caso de erro, falhar com mensagem explícita
decoding_rules:
- decodificar imagens antes de as usar
- preferir pipeline que evite frames vazios ou atrasos na primeira troca
error_handling:
- se um frame falhar, abortar a sequência e reportar o número do frame
- se a pasta frames estiver vazia, parar imediatamente
canvas_rules:
context:
- usar 2D context
- se transparência não for necessária, preferir alpha false
retina:
- aplicar devicePixelRatio
- ajustar width/height reais do canvas e escalar o contexto
resize:
- recalcular DPR, canvas size e draw bounds no resize
- não reexportar frames no browser
draw_rules:
- desenhar apenas quando o frame-alvo muda
- arredondar coordenadas de drawImage quando útil para reduzir custo subpixel
- evitar escalar agressivamente no drawImage a cada frame quando houver alternativa estável
lenis_gsap_integration:
mandatory:
- carregar lenis.css ou equivalente
- integrar Lenis com GSAP ScrollTrigger corretamente
- usar ticker GSAP para alimentar lenis.raf
anti_patterns:
- múltiplos loops RAF concorrentes sem necessidade
- ScrollTrigger sem sincronização com Lenis
- lag smoothing ativo a causar atraso visual
app_js_behavior:
required_modules:
- frame preloader
- canvas renderer
- scroll state manager
- section animation orchestrator
- counters animator
- marquee animator
- overlay manager
state_separation:
- scroll -> calcular progresso e frame-alvo
- raf -> desenhar frame e aplicar updates visuais
section_api:
each_section_must_define:
- data-enter
- data-leave
- data-animation
- data-align
counters:
- iniciar em 0
- animar ao entrar em viewport
- respeitar decimais, prefixos e sufixos
marquee:
- deslocar horizontalmente em função do scroll
- não competir com a leitura das secções adjacentes
overlay:
- ativar apenas em intervalos narrativos definidos
- nunca escurecer o canvas inteiro durante toda a experiência
responsive_behavior:
desktop:
- layout lateral obrigatório
- sequência full-fat
tablet:
- reduzir densidade de texto
- simplificar overlap de camadas
mobile:
- permitir texto centrado
- reduzir scroll total para ~500vh a 600vh
- usar menos frames
- usar menor resolução
- simplificar animações mais pesadas
- remover qualquer efeito que comprometa legibilidade ou FPS
accessibility_and_fallbacks:
required:
- suportar prefers-reduced-motion
- reduzir ou remover scrub pesado quando motion reduction estiver ativa
- manter conteúdo textual totalmente acessível sem depender da animação
- garantir contraste suficiente
reduced_motion_mode:
- usar poster frame ou sequência extremamente reduzida
- desativar marquee agressiva
- substituir clip reveals por fades simples
- manter narrativa sem panning excessivo
testing:
serve_over_http:
- npx serve .
- python -m http.server 8000
never_use:
- file://
acceptance_checklist:
- scroll suave sem stutter visível
- zero flickers brancos
- frame sequence sincronizada com o scroll
- hero -> canvas com transição limpa
- overlay escuro ativa só onde deve
- estatísticas contam a partir de 0
- nenhuma repetição de animação em secções consecutivas
- CTA final permanece visível
- mobile mantém usabilidade
- reduced-motion produz experiência alternativa funcional
common_failures:
- frames não carregam -> página aberta com file:// ou paths errados
- stutter -> excesso de frames, resolução demasiado alta ou render indevido fora do RAF
- blur -> canvas sem DPR
- secções sobrepostas -> ranges mal distribuídos
- triggers falham -> data-enter/data-leave incoerentes ou refresh incorreto
- mobile rebenta memória -> frames/resolução em excesso
- loader mente -> sequência ainda não pronta quando a UI é libertada
philosophy:
- Premium não significa efeitos em excesso.
- Premium significa controlo, ritmo, contraste, legibilidade e ausência de fricção.
- Quando houver dúvida, escolher a versão mais clara, mais estável e mais elegante.