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 SeatMapBuilder service: 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_map library (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.
  • SeatBookingForm progressive 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.

Merge request reports

Loading