Pipeline: detect oriented bounding boxes → rotate each → count → OCR per spine.
Stage 1 — detect: OpenCV.js Canny + contours + minAreaRect, scored by area·rectangularity·aspect, NMS at IoU>0.3. Sorted left-to-right with row tolerance for multi-shelf shots.
Stage 2 — rotate: per-spine warpAffine deskew + 90° CCW for portraits.
Stage 3 — count: numbered overlays match thumbnail indices.
Stage 4 — OCR: per-engine lazy load; results cached per-spine. Toggle Apply to all to batch-run an engine across every spine sequentially.
Flip 180°: classical CV can't tell which end of a spine is "top of title." Manual flip handles the 50/50 ambiguity. Existing OCR results dim to indicate they're now stale relative to the flipped input.