Mirror the proven `presentation_cities` city store for units: a parallel
`presentation_units: Vec<Vec<mc_state::MapUnit>>` slot on GdGameState, owned
by a new `unit_slot` ops module that is the exact unit-side analogue of
`city_slot`.
- `api-gdext/src/unit_slot.rs`: bounds-safe `at/at_mut`, stable-u32-id
`index_by_id/locate_by_id`, `spawn`, `move_unit`, `transfer_owner` (capture),
`remove` (index-shift-safe), `take_damage/heal/set_hp`, posture setters
(fortify/sentry/movement), `to_dict` projection, `to_json/load_from_json`
serde round-trip. Pure holding + projection; turn/action logic stays in
mc-turn / mc-player-api dispatch (no duplication of MapUnit mutation).
- GdGameState gains `presentation_units`, initialised parallel to
`presentation_cities` (empty rows grow on demand) and folded into the save
envelope at every site (init, serialize_full, load_from_json).
- SaveEnvelope gains `presentation_units` (#[serde(default)]); CURRENT_VERSION
bumped v3 → v4. save_envelope.rs literals + version-lock test updated.
- `#[func]` delegators on GdGameState mirror the city_* surface (spawn_unit,
move_unit_slot, transfer_unit, remove_unit, unit_take_damage/heal/set_hp,
posture setters, unit_dict, unit_index_by_id/locate_by_id, unit_to_json/
load_from_json).
- `GdUnit` per-instance wrapper for parity with GdCity (owned MapUnit,
to_dict/to_json/field reads).
Tests: 7 unit_slot ops tests (spawn→locate, move, remove-shift-id-stable,
damage/heal clamp, posture, transfer between rows, json round-trip) + the
updated save_envelope suite, all green.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>