v1.4.1 — UI polish + indoor cursor fix
Polish release on top of v1.4.0.
Fixes
- Slider tick alignment — the labels under the density slider now line up with the thumb exactly. The thumb has a fixed pixel width and the runnable track is inset by half that on each side; ticks are now offset by `(0.5 - pct) × 16 px` so they sit directly under the thumb at every value.
- Indoor cursor now flips to crosshair while drawing. Root cause was a Vue scheduler interaction: `MapCanvas`'s six watchers stayed alive past unmount and dereferenced a null map, throwing inside `flushJobs()`. That aborted the rest of the scheduler queue — including `IndoorCanvas`'s re-render — so its template never reflected the new `state.drawing`. All six watchers now null-guard the map.
- 3D density modal: removed the Reset (↺) button. Drag-to-orbit already restores the framing intuitively; the extra button was clutter.
- Bottom-right map controls reordered to (i) → Satellite. The OSM attribution group is shifted left via CSS so Satellite can sit in the corner without the expanded © text overlapping it.
- Default density at zone creation bumped from 1.5 → 2 ppl/m² to match the Purple Guide planning ceiling (which is the default standard).
No new features, no breaking changes. `crowd-count.html` is byte-stable around 1.79 MB (gzip 481 kB).