Replaces the auto-renumbered 1..N position key with operator-OWNED page
numbers: sparse, gaps allowed, editable, never auto-renumbered. Order follows
the numbers; unnumbered pages sort to the tail. This is the fix for the model
that clobbered hand-set numbers on the flatten — numbers are now data, not a
derived sequence.
- series_service: drop the renumber-on-reorder/remove; order by page_number
NULLS LAST; new set_page_number(image_id, n|None); list_pages returns `gaps`
(one entry per missing-number run) + each pending group's parsed `start_page`;
set_cover renumbers below the current min; place_pending(image_ids, start_page)
numbers placed pages sequentially from the start (drop junk first → numbers
line up); add_post stamps the parsed start on staged pages.
- api/tags: POST /series/<id>/pages/number (set one page's number); /pending/
place takes start_page; removed /reorder.
- frontend: per-card editable number input; one gap block per gap with
drop-on-edge to assign the adjacent number (middle → type); append drop zone;
pending tray gets a "from page N" field + "Place from page N".
- tests reworked: sparse numbers + gaps, place-from-start, set-page-number route.
No migration; nothing destructive.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>