E1 · Your frames
10 minRun the "your frames on the page and verify" block (you need the frames folder from lesson 2).
Done when: quadros: 144 (frames/), OK: 3 de 3 posições and saída: 0.
Lesson 3 · 18 min
The engine that ties scrolling to frames has few parts, and each one fixes a measured stutter. You look at the parts, swap the kit page's frames for your own from lesson 2, prove with the test contract that the right frame shows up at each point, and ask the scroll-film-studio skill, from INEMA, for the new page.
Start the lesson
Goal: tie your frames to the kit's scroll engine, prove it with the ?jump and __ready contract, and ask the skill for the page.
The parts of motor-rolagem.js (site-movimento, INEMA). Click each one.
In site-movimento, the bitmap window fix took the worst scroll hitch from 150–315 ms down to 33–36 ms (README and engine comment, 10/18/2026).
Copy the page to a rehearsal folder, swap frames/ for the frames from lesson 2, and verify.
K=~/projetos/formacao-cinema-ia-sites-v72/kit
E=${TMPDIR:-/tmp}/ensaio-sites/a3; rm -rf "$E/site"
cp -r "$K/site" "$E/site"; rm -rf "$E/site/frames"
cp -r "${TMPDIR:-/tmp}/ensaio-sites/a2/quadros" "$E/site/frames"
node "$K/scripts/servir.mjs" "$E/site" > "$E/url.txt" & S=$!
until U=$(cat "$E/url.txt") && [ -n "$U" ] && curl -s -o /dev/null "$U"; do sleep 0.3; done
node "$K/scripts/verificar.mjs" "$U"; echo "saída: $?"
kill $S filme = MotionEngine.Scrub({
canvas: document.getElementById('tela'), driver: secao, count: m.count, fps: m.fps || 24, dpr: 1,
maxCrop: VERT ? 0.8 : 0.22, bg: '#0c0c10',
frozen: parado,
src: function (i) { return m.dir + '/f_' + String(i + 1).padStart(4, '0') + '.jpg'; },K=~/projetos/formacao-cinema-ia-sites-v72/kit
E=${TMPDIR:-/tmp}/ensaio-sites/a3
node "$K/scripts/servir.mjs" "$K/site" > "$E/url.txt" & S=$!
until U=$(cat "$E/url.txt") && [ -n "$U" ] && curl -s -o /dev/null "$U"; do sleep 0.3; done
node "$K/scripts/verificar.mjs" "${U}erro-sem-contrato.html"; echo "saída: $?"
kill $SChromium 156.0.8078.4 (Playwright 1.64.0) · 1366×768 quadros: 144 (frames/) rolagem 0% → quadro 0 · tela pintada rolagem 50% → quadro 72 · tela pintada rolagem 100% → quadro 143 · tela pintada transbordo horizontal: não OK: 3 de 3 posições saída: 0
The verifier opens the page three times with ?jump= at the start, middle, and end of the track and reads the engine's frame.
Chromium 156.0.8078.4 (Playwright 1.64.0) · 1366×768 FALHA: a página não marcou window.__ready em 15 s (falta o contrato ?jump + __ready) saída: 1
The copy erro-sem-contrato.html never calls MotionEngine.ready: the page works for someone scrolling by hand, but no test knows when to look.
Two lines that both INEMA skills require on every page they build.
The page reads the jump parameter from the URL and scrolls to y pixels before anything else, with no smooth scrolling. Opening the page at 50% becomes a URL.
The kit's engine does this in MotionEngine.ready.
After positioning and drawing, the page sets window.__ready = true. The test waits for that flag instead of waiting a fixed time.
Waiting 2 s "to be safe" passes on your machine and fails on a loaded one.
Screenshot, verifier, and the agent checking its own work, all through the same path.
The skill's verify.js refuses to capture the screen if __ready never arrives.
INEMA skill for Codex and Claude Code: interview, concepts, art direction, page, and gates. Two lanes: Lane A code only (no cost) and Lane B with film from your generator. The kit's verificar.mjs reads the kit's hooks ([data-filme] section, #tela canvas, window.__filme, and window.__filmeInfo) in addition to the contract; that's why the prompt tells the skill to start from kit/site. A page built from scratch by the skill checks out with its own verify.js.
E=${TMPDIR:-/tmp}/ensaio-sites/a3; rm -rf "$E"; mkdir -p "$E"; cd "$E"
git clone -q https://github.com/inematds/scroll-film-studio && git -C scroll-film-studio checkout -q 9d64875; echo "clone: $?"
cd scroll-film-studio/skills/scroll-film-studio
ls; ls references scripts
sed -n 2p SKILL.mdgit clone https://github.com/inematds/scroll-film-studio ~/projetos/scroll-film-studio mkdir -p ~/.claude/skills ~/.codex/skills ln -s ~/projetos/scroll-film-studio/skills/scroll-film-studio ~/.claude/skills/scroll-film-studio ln -s ~/projetos/scroll-film-studio/skills/scroll-film-studio ~/.codex/skills/scroll-film-studio # Codex that can't find the skill in ~/.codex/skills: use ~/.agents/skills
Use the scroll-film-studio skill in Lane A (code only, no video generation). Product: <name and one sentence about what it is>. For whom: <who buys>. The opening film uses the frames already in frames/ (manifest.json with the count). Copy: only what is in this file: <path to your text>. Don't invent numbers or testimonials. Fixed rules: static page, no build; start from kit/site (motor-rolagem.js and site.js) and change only the look and the text, keeping the [data-filme] section, the #tela canvas, window.__filme, window.__filmeInfo, the ?jump=<y> + window.__ready contract, and the still mode with reduced motion. Done when: node ~/projetos/formacao-cinema-ia-sites-v72/kit/scripts/verificar.mjs <url> answers OK: 3 de 3 posições.
clone: 0 agents references scripts SKILL.md references: engine.md finishing.md playbook.md scripts: assemble.sh chain-step.sh continuity-gate.sh copy-gate.js kie-chain.py package.json package-lock.json shot.js vector-check.py verify.js name: scroll-film-studio
The skill was written in Jul/2026 and cites generators by the names from that time for Lane B. Which generator to use today is a topic for course 1; here Lane A is enough.
The text over the film sells the product. If it narrates the camera ("the camera pushes in") or tells people to scroll, it's shooting script leaking onto the page. copy-gate.js fails it.
K=~/projetos/formacao-cinema-ia-sites-v72/kit
G=${TMPDIR:-/tmp}/ensaio-sites/a3/scroll-film-studio/skills/scroll-film-studio/scripts/copy-gate.js
node "$G" "$K/site/index.html"; echo "saída: $?"
node "$G" "$K/exemplos/texto-ruim.html" 2>&1 | head -5; echo "saída: ${PIPESTATUS[0]}"✓ ~/projetos/formacao-cinema-ia-sites-v72/kit/site/index.html — copy clean
saída: 0
✗ ~/projetos/formacao-cinema-ia-sites-v72/kit/exemplos/texto-ruim.html — 5 copy defect(s)
line 6: narrates the scroll instead of performing it
…ction class="beat">Aurora 35As you scroll, the camera pushes in through the glass…
line 7: instructs the visitor to scroll
…s="beat">One continuous takeKeep scrolling to see the reveal. </body…
saída: 1copy-gate.js reads English. For pages in Portuguese and Spanish, site-movimento has an equivalent copy gate, which you run in lesson 6.
Your frames on the page, the contract proven, and the skill installed.
Run the "your frames on the page and verify" block (you need the frames folder from lesson 2).
Done when: quadros: 144 (frames/), OK: 3 de 3 posições and saída: 0.
Run the verifier against erro-sem-contrato.html (the "common mistake: page without the contract" block) and then open kit/site/site.js and find the line that calls MotionEngine.ready.
Done when: FALHA: a página não marcou window.__ready em 15 s with saída: 1.
Run "baixar a skill" and install it in your agent. Run the copy gate. Optional: ask for the page with the Lane A prompt, using your product, in a new folder.
Done when: ls ~/.claude/skills/scroll-film-studio/SKILL.md (or ~/.codex/skills/…) shows the file, and the copy gate block shows copy clean and then saída: 1.
The explanation appears after you answer.
Question 1 of 4
Scrolling stutters the first time you scroll fast. Which part of the engine fixes this?
Question 2 of 4
Why does the checker wait for window.__ready instead of waiting 2 seconds?
Question 3 of 4
Which of these sentences does the copy gate reject for a lens film?
Question 4 of 4
In the scroll-film-studio skill, what changes between Lane A and Lane B?
Choose an option. The explanation appears after your attempt.