First render: both sonar pulse rings were visible from frame one. GSAP applies a fromTo tween's "from" state at authoring time (immediateRender), so the rings sat at opacity 0.85 long before their beat — the checker had warned about exactly this. Fixed with immediateRender: false on the pulse tweens; markers now stay hidden until their pop.
Country borders drew long straight streaks across the oceans in the first cut: polygon rings that cross the ±180° longitude seam (Russia, Fiji) connected the map's east edge straight back to its west edge. Fixed in the map generator — the subpath breaks whenever longitude jumps more than 180° between points.
The country highlight's first design — a stroked halo copy of the country path — read as an orange scribble at 110m border resolution. Replaced with a fill-opacity blink on the country itself (0 → 0.5 → 0.15 → 0.85); the shape now reads instantly.
Marker dots were first hidden with a scale transform and an SVG origin — unreliable, they leaked as hollow rings. Switched to animating the circle's radius attribute (r 0 → 5), which needs no transform origin at all.
Accepted check warnings: the SVG city labels measure under the 19px type floor in raw units but only appear after the 2.3x push-in (≈31px on screen), and the stat chips' nested divs split timeline rows in the checker — cosmetic only.
Banned list —Beat grid —Build method —Self-review —
<direction>
Build a 1280x720, 11-second animated map explainer in HyperFrames + GSAP: a real world map (Natural Earth 110m country borders, equirectangular projection) fades in, the camera pushes in on the route's ocean, the destination country blinks in the accent colour, an arc draws itself from origin to destination with a bright dot riding its head, and three stat callouts land under the map. A faint graticule grid (every 30 degrees) sits under the land. House style: background #0a0a0a, white type, ONE orange accent #ff5c1a, Arial/Helvetica bold, NO webfonts, no gradients, no glows, no 3D. The route is fictional sample content: the kicker carries "SAMPLE ROUTE" and the footer reads "ILLUSTRATIVE SAMPLE — SWAP IN YOUR OWN ROUTE, COUNTRY + STATS" for the whole film.
Route title: New York → London
Highlighted country: United Kingdom
Stat callouts (value — label, three of them): 5,570 KM — distance, 7H 55M — nonstop flight, 5 — time zones crossed
Banned: stock map imagery, map pins, extra colours, lorem ipsum, any real statistic presented as measured fact — the sample stats are illustrative.
</direction>
<structure>
0.0-0.7s: orange kicker "ANIMATED MAP EXPLAINER — SAMPLE ROUTE" and the route title settle at top-left; footer fades in.
0.7-1.7s: the full world map fades in (dark land #1f1f1f, hairline borders #3d3d3d) with a faint ghost copy of the route arc already visible.
1.7-3.4s: push-in — the map group scales to 2.3x around the route's midpoint so the ocean crossing fills the stage.
3.5-5.0s: the highlighted country's fill blinks twice in the accent colour and settles at 85% opacity; its name appears beside it. The origin country flashes once, softly, in white at the same moment its city marker pops with two sonar pulse rings and its label.
4.1-7.2s: the accent arc draws itself origin to destination (stroke-dashoffset, getTotalLength timing) with a small white dot riding the drawing head (getPointAtLength on the draw's progress); the first stat chip lands mid-draw.
7.2-7.6s: the destination marker pops with a pulse ring; its city label appears.
7.9-8.8s: the remaining stat chips pop in; the closing caption "ONE ROUTE · THREE NUMBERS · NO STOCK MAPS" fades in under them.
8.8-11.0s: hold the finished map, everything readable.
</structure>
<build>
Map data: generate the SVG paths from world-atlas countries-110m (Natural Earth) with topojson-client — one combined land path plus the highlighted country as its own path. When a polygon ring jumps more than 180 degrees of longitude between points (the ±180 seam: Russia, Fiji, Antarctica-adjacent rings), break the subpath with a new M command or the border draws a straight streak across the whole map. Markers and labels live INSIDE the zooming SVG group so they track the push-in; the country-name label is an HTML overlay because it must sit clear of the landmass in screen space. One paused GSAP timeline registered as window.__timelines["main"]. Marker dots animate the radius attribute (r 0 to 5), never scale — no transform origin to get wrong. Every fromTo tween that must stay invisible before its beat carries immediateRender: false, because GSAP otherwise applies the "from" state at authoring time and the element leaks into frame one. Draw the arc with getTotalLength() + strokeDasharray/strokeDashoffset so any replacement route still times correctly. Keep reading text at or above the 19px floor; SVG city labels are exempt in practice — they only appear after the 2.3x push-in, at roughly 31px effective.
</build>
The whole trick is the push-in: on the full world the sample route spans barely 230px, so the film zooms 2.3x into the ocean before any mechanic plays — the draw, the highlight and the markers all happen at a size where they read. Time the destination pop to the frame the arc's dashoffset reaches zero and the route feels flown, not drawn.