PTENES
MODULE 3.1

🖱️ Frame, cursor & zoom

The animation layer that turns a static screenshot into a professional walkthrough: the browser frame, the cursor that targets the bounding box real, the click with ripple, the zoom on the result, and the premium dark amber house style.

7
Topics
30
Minutes
Advanced
Level
Reading
Type
canvas 1920×1080 · #appwin 🔒 localhost:8000 shot inside the window at (WIN_L, SHOT_T) target (.hlbox) power3.inOut canvasX = WIN_L + sx · canvasY = SHOT_T + sy · tip = target − (6,3)
1

🪟 The browser frame

A persistent window surrounds each screenshot — it gives the video a “browser” feel and disguises the fact that the content is a screenshot.

💡Main Concept

The window #appwin lives in the bg-layer with data-layout-ignore: border, radius, large shadow, title bar with 3 dots (red/yellow/green), and a mono URL pill with a lock + window.urlLabel. The screenshots (1 clip per scene) go inside from it, in (WIN_L, SHOT_T) with size VW×VH.

steps.json — window block
"window": {
  "top": 96,           // WIN_T — topo da janela no canvas
  "titleH": 52,        // altura da barra de título
  "urlLabel": "localhost:8000"
}
// derivados no build-demo.mjs:
WIN_L  = (1920 - VW) / 2     // centraliza horizontal
SHOT_T = WIN_T + TITLE_H     // topo do screenshot
✓DO
  • ✓Mark the frame with data-layout-ignore
  • ✓Use the urlLabel real captured app
  • ✓Keep the persistent window (don’t recreate it for each scene)
✗DO NOT
  • ✗Draw the screenshot outside the window area
  • ✗Load the live site inside the frame (rendering is deterministic)
  • ✗Animate the frame as if it were a scene
2

➡️ The animated cursor and the path to the target

A single global cursor glides along the main timeline and lands exactly in the center of the bounding box real control.

💡Coordinate mapping

The capture runs in a fixed viewport (e.g., 1280×800)—every bbox is in this space. One point (sx, sy) of the screenshot becomes canvasX = WIN_L + sx, canvasY = SHOT_T + sy. The cursor target is the center of the mapped bbox.

cursor tween (concept)
// hotspot na ponta da seta ≈ (6,3) num SVG de 42px
const HOT = { x: 6, y: 3 };
// a PONTA cai no centro do alvo, não o canto
tl.to("#cursor", {
  x: alvoX - HOT.x,
  y: alvoY - HOT.y,
  duration: 0.7,
  ease: "power3.inOut"
}, s.start + 0.35);   // deixa a cena aparecer antes
📊
Why target the real bbox

The bounding box comes from getBoundingClientRect() during capture—not from a guess "by eye." That’s exactly what makes the cursor look professional: it lands on the right pixel of the button or field.

🧭
Global cursor
main timeline
📍
Hotspot at the end
(6,3)
📦
real bbox
getBoundingClientRect
〰️
power3.inOut
curved easing
3

👆 The click and the visual effect

When the cursor "clicks," a pulse on the cursor itself and an amber ripple communicate the action to the viewer.

~start + 0.35scursor starts

The cursor moves from its previous position toward the target, letting the scene appear first.

~start + 1.05sreaches the target

The pointer lands at the center of the bbox; the highlight is already pulsing around the control.

~start + 1.15sclick

Cursor does scale:.82 in yoyo (pulse) and the #ripple (amber circle) expands and disappears at the center of the target.

⚡
Practical tip

Read-only steps (without click:true) don't trigger the ripple—good for the home screen (intro:true), where you only present the app without interacting.

4

🔍 Zoom and highlight the active region

The highlight draws the eye to the control; the zoom adds a cinematic push-in when the result appears.

🟨
.hlbox (destaque)

Rectangle only with box-shadow (amber ring + glow) on the mapped bbox with ~6px of clearance. Comes in with back.out and pulses the glow a few times — draws focus without covering anything.

🔎
zoom: true

In the results step, the <img> receives scale 1 → 1.12 throughout the narration, with transformOrigin in the center of the target (e.g., the results panel).

steps.json — step with zoom
{
  "shot": "04-result.png",
  "target": { "x": 668, "y": 128, "w": 484, "h": 324 },
  "zoom": true,
  "caption": "O resultado aparece pronto para baixar.",
  "narration": "E pronto: o resultado já está disponível."
}
📊
Recommended pacing

The final content step usually shows the result with zoom:true — a light "ta-da" that closes the walkthrough arc before the CTA.

5

🎨 Premium dark amber house style

A fixed palette of 6 colors, with amber as the only dominant accent — the visual identity of all the videos.

#0D1321
background (--bg)
#1D2D44
panel (--bg2)
#3E5C76
border (--bg3)
#F0EBD8
text (--fg)
#FFC300
amber (--accent)
#2EC4B6
code (--code)
⚡
Single accent rule

ONE dominant accent: amber. It appears in the click ripple, the highlight ring, the background glow, and the CTA. Identical background in every scene — never flat.

📊
Video composition (not a website)

Persistent background layer with data-layout-ignore: breathing amber radial glow, giant drifting ghost text, hairline grid, and grain. Large scale: 64–172px headline, decorative elements at 12–25% opacity.

6

🔤 The embedded fonts

Sora, Inter, and JetBrains Mono as .woff2 local—never CDN, because rendering is offline and deterministic.

Aa
Sora 700–800

Titles and headlines (geometric, high impact).

Aa
Inter 400–600

Body and captions (high legibility).

Aa
JetBrains Mono

URL pill, values, and code.

🚨
Never use Google Fonts via CDN

The render environment may not have internet access. External sources fall back and break the visuals. The fonts come from assets/fonts/ (the Latin subset covers PT-BR); the build-demo.mjs injects the fonts.css rewriting the paths.

🅰️
Sora
titles
📝
Inter
body
⌨️
JetBrains
mono
📦
.woff2 local
offline-safe
7

⏱️ Each step's timing matching the narration

The cursor responds to the narration: it reaches the target before the explanation and clicks at the right moment, at a pace defined by LEAD/TAIL/FADE.

💡Recommended pacing

LEAD 0.5s — the scene appears before the voice starts.

TAIL 0.7s — breathing room after the audio ends.

FADE 0.4s — transition between scenes.

The cursor reaches the target ~0.7s before the main explanation; the click lands near start + 1.15s.

⚡
Keep it to 5–8 steps

Also, video is tiring, and capture/editing becomes a major task. 5–8 steps + CTA ≈ 35–50s—the ideal length for a walkthrough.

🎯 What you learned

  • ✓The frame #appwin wraps the shot and gives it a browser look
  • ✓The global cursor targets the real bbox, with the hotspot at its tip and curved easing
  • ✓The click triggers an amber pulse + ripple; the zoom pushes in on the result
  • ✓Dark premium amber palette and local Sora/Inter/JetBrains fonts
  • ✓LEAD/TAIL/FADE timing syncs the animation with the narration

Next: Module 3.2 — how to generate local narration with Kokoro and put it all together with the build-demo.mjs.