# Motion Map3D

A tilted 3D city map built from CSS alone (perspective and a rotated plane: no WebGL, no map tiles, no fetch). Blocks stand on a ground plane as three-faced boxes, either a seeded generated city, explicit blocks, or generated district clusters (cities). Outlines of real-world countries or states can be drawn directly on the ground plane under the blocks and route. As p runs 0 to 1 the camera descends and tilts in (p 0 to 0.3), then one or more legs draw on from station to station (p 0.3 to 0.92, optionally bending in arcs and pausing at stations with dwell times) with each station going from idle to active as a leg reaches it and then to its own state (idle, active, done, warn or error), payload chips can travel along the legs, and an optional clock chip counts in clock time, seconds or milliseconds. Station pins and labels sit on their own layer above the city, so blocks never cover them. Made for journeys through a system as much as through a city: a request trace, an agent's tool call and its reply, a deploy pipeline, an incident. At p = 1 every leg is fully drawn, the stations are in their final states and the clock shows its end value.

## Surfaces

web, google-apps-script-web, mcp-apps, android

## Fields

| Field | Type |
|---|---|
| seed | integer (optional). 0 to 9999, default 7. Seeds the generated city when no blocks are given: the same seed always makes the same city. Generated blocks leave the streets under the route and the stations clear, and are lower close to them, so the route is never hidden. |
| blocks | array (optional, up to 200) of {x, y, w, h, height}: x, y, w, h in percent of the map (0 to 100, w and h at least 1) and height the box height (0 to 40, default 6). When given and non-empty they replace the generated city and are drawn exactly as written, so keep your own blocks off the route. More than 200 draw the first 200 with a visible note. |
| ground | object (optional) {set, window, highlight, fill, accent}. Real map outlines drawn directly on the city plane under blocks and routes. set: "world-countries", "europe-countries", or "us-states". window: [lon0, lon1, lat0, lat1] bounding box in degrees (lon -180..180, lat -85..85 with lon0 < lon1 and lat0 < lat1). highlight: array (up to 24) of region id strings. fill and accent: "#rrggbb" colours (defaults #2a3342 and #3a4a63). Example: ground: {set: "europe-countries", window: [-10, 30, 35, 60], highlight: ["FRA", "DEU"]}. Maximum 400 regions and 6000 points; when ground is valid without blocks or cities, the full-plane generated city is omitted. |
| cities | array (optional, up to 8) of {x, y, w, h, count, seed, height}. Clusters of small buildings generated inside rectangular districts (0 to 100 percent map coords). count: 1 to 24 (default 4); height: 1 to 40 (default 8); seed: optional integer (defaults to atom seed + city index). Example: cities: [{x: 20, y: 30, w: 25, h: 25, count: 9}]. Omits the full-plane random city. |
| arc | number 0 to 0.6 or boolean (optional, true = 0.25). Bends route leg segments into quadratic bezier curves bulging outward to the left of travel direction (back legs bend opposite). Example: arc: 0.2 curves all legs gently. |
| stations | array (optional, up to 24) of {id, x, y, lon, lat, label, state, dwell}: id letters, digits and underscore, starting with a letter, max 24 (else s1, s2 by position; a repeated id is left out with a note), x and y in percent of the map (0 to 100, default 50). When a valid ground is active, lon and lat (numbers) can be given instead of x/y and are projected via Web Mercator. dwell: 0 to 0.3, portion of the p dial the route holds at this station before resuming. label max 24 characters (default the id) and state idle, active, done, warn or error (default idle). The state is the settled one: a station on a leg is idle until a leg arrives, active while it is there, then its own state. warn draws an amber pin with "!" and error a red pin with "×", so colour is never the only cue; the text alternative names every state. A station off every leg simply shows its state. Without stations the map shows a note. |
| route | array (optional, up to 32) of station ids in order. Each pair draws one straight or arched segment on the ground. An id that is not a station is skipped with a note, and an id repeated straight after itself is ignored. Ignored when legs has at least one valid leg. |
| clock | object (optional) {from, to, unit}. unit "hhmm" (default; anything else unknown also means hhmm): from and to as HH:MM, 24-hour, a to earlier than from runs through midnight. unit "s" or "ms": from and to are whole non-negative numbers (fractions are floored; s up to 86400, ms up to 3600000) and to must not be below from; the chip reads like 480 ms or 1560 s. The chip at the top left counts over p 0.3 to 0.92. Both values must be valid or no chip is drawn. |
| tilt | number (optional). Final camera tilt in degrees, 0 (straight down) to 75, default 55. The camera starts straight down and tilts in over p 0 to 0.3. |
| camera | object (optional) {from, to, keys, follow, track}. from and to: zoom of the map at p 0 and at the end of the descent, 0.3 to 3, defaults 0.55 and 1. keys: array (up to 8) of {at, turn, tilt, zoom}, poses the camera passes through over the whole film instead of the default descent: at is p (0 to 1, each later than the one before), turn the rotation of the map in degrees (-180 to 180, default 22), tilt 0 to 75, zoom 0.3 to 3; a missing value keeps the previous key's; held before the first key and after the last; bad keys are left out with a note. follow: integer 1 to 6 (used only without keys): after the descent the camera turns to a new angle each time the route arrives at every follow-th station, and swings round and closes in on the last destination (a little closer at each stop). track: 0 to 1, how firmly the camera pans to keep the head of the route (where it is drawing now) at the centre, so the view rides along the journey; default 0.6 with follow, otherwise 0 (no pan). Station pins and labels keep their size and keep facing the viewer at every angle. |
| color | "#rrggbb" (optional). Route and active-station colour. Default the stage accent. |
| legs | array (optional, up to 4) of {route, color, back}: several legs drawn one after another, replacing route when at least one is valid. route is station ids as in route (a leg needs two known stations, else it is left out with a note); color "#rrggbb" (default the atom colour); back true reverses the leg, for a reply going back along the path, and draws it in its own lane beside the outbound leg. The drawing window is shared by all legs in proportion to their length. Segment keys run over all legs (from-to, a repeat gets -2, -3). |
| messages | array (optional, up to 12) of {leg, text, at, back}: a payload chip that travels along a leg while it is drawn. leg is an index into the drawn legs (default 0); text max 24 characters; at the p (0 to 1) when it sets off (default the leg's own start); back true sends it from the leg's end to its start. A chip is visible only while it travels, so the settled frame shows none; the text alternative lists every message with its start and end station. Bad entries are left out with a note. |
| version | integer (optional, default 1). 1 and 2 draw the same; a whole number above 2 draws as version 2 with a muted note. |

## Example payload

```json
{
  "type": "motion_map3d"
}
```

Live page: https://a2uicatalog.ai/atoms/motion_map3d/
Full field contract: https://a2uicatalog.ai/spec.json
