Issue #3611792: Add a graphical seat-map selector to the seat booking form
Adds a graphical "select your seats" picker to the per-slot seat booking form, the interactive equivalent of the current per-section list.
- New
SeatMapBuilderservice: one compact payload per slot (inlined venue map-background SVG, sprite ids, grades for the legend, sections, and every seat with geometry, grade, section, printed number and per-slot state). Returns nothing when the venue has no drawable map, so the list stays as the fallback. seat_maplibrary (JS behavior + CSS): draws the background, positions each seat as a button by its x/y/angle, colors by grade, supports zoom/pan (wheel, pinch, buttons, fit) and keyboard navigation (roving tabindex, arrows within a section, Enter to select). Seat semantics live on each button's accessible name; the tooltip is decorative and aria-hidden.SeatBookingFormprogressive enhancement: the map is layered over the existing list; picking seats fills a hidden field that a "Book the selected seats" action holds through the engine (group hold). With no JavaScript or no geometry, the grouped list and the single-seat / party selectors remain the working fallback.- Kernel test for the payload builder (states, background, null fallback).
Follow-up (separate slice): the reseat "change my seat" mode, which also needs a reseat engine primitive.
Part of issue #3611792.