@seatlayer/core 0.15.1 → 0.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +88 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +15 -2
- package/dist/index.d.ts +15 -2
- package/dist/index.js +88 -8
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/i18n/locales/es.ts","../src/i18n/locales/de.ts","../src/i18n/locales/fr.ts","../src/index.ts","../src/core/types.ts","../src/core/layout.ts","../src/core/ga.ts","../src/core/sections.ts","../src/engine/SeatmapRenderer.ts","../src/lib/money.ts","../src/i18n/locales/en.ts","../src/i18n/index.ts","../src/core/orphans.ts","../src/picker/PickerController.ts","../src/view/generatePanorama.ts","../src/i18n/bundles.ts"],"sourcesContent":["/**\n * Spanish (es) bundle — neutral/international Spanish translation.\n * Follows the same key structure as en.ts; all placeholders and brand\n * names preserved.\n */\n\nimport type { Dict } from '../index';\n\nexport const es: Dict = {\n // shared\n 'common.cancel': 'Cancelar',\n 'common.close': 'Cerrar',\n 'common.done': 'Listo',\n 'common.copied': '✓ Copiado',\n\n // buyer picker (extraction in progress — P4 of the port plan)\n 'picker.holdSeats': 'Retener asientos y comprar',\n 'picker.completeBooking': 'Completar reserva',\n 'picker.seatsHeld': 'Asientos retenidos — {time}',\n 'picker.holdExpired': 'Tu retención expiró — los asientos fueron liberados. Elige de nuevo.',\n 'picker.seatTaken': 'El asiento {label} fue tomado por otro comprador.',\n 'picker.poweredBy': 'Con la tecnología de SeatLayer',\n 'picker.testMode': 'MODO DE PRUEBA',\n 'picker.colorblind': 'Colores aptos para daltonismo',\n 'picker.orphanHint': 'Esto deja un asiento aislado — considera desplazarte un asiento.',\n 'picker.seats.one': '{count} asiento',\n 'picker.seats.other': '{count} asientos',\n\n // renderer (drawn on the Konva map — shared by the embed SDK)\n 'map.aria': 'Mapa de asientos. Usa las flechas para moverte entre asientos, Intro para seleccionar.',\n 'map.seatsLeft': '{count} LIBRES',\n 'map.statusHeld': 'En espera',\n 'map.statusTaken': 'Ocupado',\n 'map.fromPrice': 'DESDE {price}',\n\n // buyer picker page (src/pages/PickerPage.tsx)\n 'picker.language': 'Idioma',\n 'picker.zoomToFit': 'Ajustar zoom',\n 'picker.viewMode': 'Modo de vista',\n 'picker.floor': 'Piso',\n 'picker.zoomLevel': 'Nivel de zoom',\n 'picker.rungTip.zones': 'Vista general — grupos de secciones como Grada norte o VIP',\n 'picker.rungTip.sections': 'Bloques de sección — mezcla de categorías + matiz de disponibilidad',\n 'picker.rungTip.seats': 'Asientos individuales — los bloques se convierten en puntos',\n 'picker.rungLabel.zones': 'ZONAS',\n 'picker.rungLabel.sections': 'SECCIONES',\n 'picker.rungLabel.seats': 'ASIENTOS',\n 'picker.sectionSummaryAria': 'Resumen de sección {label}',\n 'picker.closeSectionSummary': 'Cerrar resumen de sección',\n 'picker.seatsLeftInSection.one': '{count} asiento disponible',\n 'picker.seatsLeftInSection.other': '{count} asientos disponibles',\n 'picker.overview': 'Descripción general',\n 'picker.tapSeatHint': 'Toca cualquier asiento para ver su vista',\n 'picker.chartSize': 'Tamaño del gráfico',\n 'picker.custom': 'Personalizado',\n 'picker.categories': 'Categorías',\n 'picker.accessibility': 'Accesibilidad',\n 'picker.showAnyAccessible': 'Mostrar cualquier asiento accesible',\n 'picker.any': 'Cualquiera',\n 'picker.yourSeats': 'Tus asientos',\n 'picker.emptySeats': 'Toca asientos en el mapa',\n 'picker.emptySeatsWithGa': 'Toca asientos en el mapa · toca un área de pie para entradas de entrada general',\n 'picker.oneFewer': 'Uno menos',\n 'picker.oneMore': 'Uno más',\n 'picker.remove': 'Eliminar {label}',\n 'picker.ticketTierFor': 'Categoría de entrada para {label}',\n 'picker.total': 'Total: {amount}',\n 'picker.viewFromSeat': 'Vista desde el asiento {label}',\n 'picker.real360': 'REAL 360°',\n 'picker.preview': 'VISTA PREVIA',\n 'picker.open360': 'Abrir vista de 360°',\n 'picker.sightline': '≈ {rows} filas del escenario · {angle}° fuera del centro',\n 'picker.bookedDemo': '¡Reservado! (demostración)',\n 'picker.bookButton.one': 'Reservar {count} entrada — {amount}',\n 'picker.bookButton.other': 'Reservar {count} entradas — {amount}',\n 'picker.simulateCrowd': 'Simular multitud: {state}',\n 'picker.on': 'ACTIVADO',\n 'picker.off': 'DESACTIVADO',\n 'picker.panorama360': 'Foto de 360° del lugar',\n 'picker.illustrationCaption': 'ilustración · ≈ {m} m del escenario',\n};\n","/**\n * German bundle — native-quality translations of the English reference dictionary.\n * Keys are identical to en.ts; values are translated to German (de).\n *\n * Conventions:\n * - flat dot-namespaced keys: \"<surface>.<element>\" (picker.holdSeats)\n * - {name} interpolation, {count} reserved for tCount plural keys\n * - plural keys end in \".one\" / \".other\" (Intl.PluralRules categories)\n */\n\nimport type { Dict } from '../index';\n\nexport const de: Dict = {\n // shared\n 'common.cancel': 'Abbrechen',\n 'common.close': 'Schließen',\n 'common.done': 'Fertig',\n 'common.copied': '✓ Kopiert',\n\n // buyer picker (extraction in progress — P4 of the port plan)\n 'picker.holdSeats': 'Plätze reservieren & Kasse',\n 'picker.completeBooking': 'Buchung abschließen',\n 'picker.seatsHeld': 'Plätze reserviert — {time}',\n 'picker.holdExpired': 'Ihre Reservierung ist abgelaufen — die Plätze wurden freigegeben. Bitte erneut auswählen.',\n 'picker.seatTaken': 'Platz {label} wurde gerade von einem anderen Käufer gebucht.',\n 'picker.poweredBy': 'Bereitgestellt von SeatLayer',\n 'picker.testMode': 'TESTMODUS',\n 'picker.colorblind': 'Farbenblind-freundliche Farben',\n 'picker.orphanHint': 'Dadurch bleibt ein einzelner Platz übrig — rücken Sie ggf. einen Platz weiter.',\n 'picker.seats.one': '{count} Platz',\n 'picker.seats.other': '{count} Plätze',\n\n // renderer (drawn on the Konva map — shared by the embed SDK)\n 'map.aria': 'Sitzplan. Mit Pfeiltasten zwischen Plätzen navigieren, Eingabe zum Auswählen.',\n 'map.seatsLeft': '{count} FREI',\n 'map.statusHeld': 'Reserviert',\n 'map.statusTaken': 'Vergeben',\n 'map.fromPrice': 'AB {price}',\n\n // buyer picker page (src/pages/PickerPage.tsx)\n 'picker.language': 'Sprache',\n 'picker.zoomToFit': 'Auf Größe anpassen',\n 'picker.viewMode': 'Ansichtsmodus',\n 'picker.floor': 'Etage',\n 'picker.zoomLevel': 'Zoomstufe',\n 'picker.rungTip.zones': 'Übersicht — Bereichsgruppen wie Nordtribüne oder VIP',\n 'picker.rungTip.sections': 'Bereichs-Blöcke — Kategoriesortierung + Verfügbarkeitstönung',\n 'picker.rungTip.seats': 'Einzelne Plätze — Blöcke lösen sich zu Punkten auf',\n 'picker.rungLabel.zones': 'ZONEN',\n 'picker.rungLabel.sections': 'BEREICHE',\n 'picker.rungLabel.seats': 'PLÄTZE',\n 'picker.sectionSummaryAria': 'Bereichszusammenfassung {label}',\n 'picker.closeSectionSummary': 'Bereichszusammenfassung schließen',\n 'picker.seatsLeftInSection.one': '{count} Platz verfügbar',\n 'picker.seatsLeftInSection.other': '{count} Plätze verfügbar',\n 'picker.overview': 'Übersicht',\n 'picker.tapSeatHint': 'Tippen Sie auf einen Platz, um die Ansicht zu prüfen',\n 'picker.chartSize': 'Kartengröße',\n 'picker.custom': 'Benutzerdefiniert',\n 'picker.categories': 'Kategorien',\n 'picker.accessibility': 'Barrierefreiheit',\n 'picker.showAnyAccessible': 'Jeden barrierefreien Platz anzeigen',\n 'picker.any': 'Beliebig',\n 'picker.yourSeats': 'Ihre Plätze',\n 'picker.emptySeats': 'Tippen Sie auf die Plätze auf der Karte',\n 'picker.emptySeatsWithGa': 'Tippen Sie auf die Plätze auf der Karte · tippen Sie auf einen Stehbereich für Stehplatztickets',\n 'picker.oneFewer': 'Einen weniger',\n 'picker.oneMore': 'Einen mehr',\n 'picker.remove': '{label} entfernen',\n 'picker.ticketTierFor': 'Ticketklasse für {label}',\n 'picker.total': 'Gesamt: {amount}',\n 'picker.viewFromSeat': 'Ansicht von Platz {label}',\n 'picker.real360': 'REAL 360°',\n 'picker.preview': 'VORSCHAU',\n 'picker.open360': 'Öffnen Sie die 360°-Ansicht',\n 'picker.sightline': '≈ {rows} Reihen von der Bühne · {angle}° seitlich versetzt',\n 'picker.bookedDemo': 'Gebucht! (Demo)',\n 'picker.bookButton.one': '{count} Ticket buchen — {amount}',\n 'picker.bookButton.other': '{count} Tickets buchen — {amount}',\n 'picker.simulateCrowd': 'Menschenmenge simulieren: {state}',\n 'picker.on': 'AN',\n 'picker.off': 'AUS',\n 'picker.panorama360': '360°-Veranstaltungsfotos',\n 'picker.illustrationCaption': 'Illustration · ≈ {m} m von der Bühne',\n};\n","/**\n * French (fr) bundle — native French translation.\n * Follows the same key structure as en.ts; all placeholders and brand\n * names preserved.\n */\n\nimport type { Dict } from '../index';\n\nexport const fr: Dict = {\n // shared\n 'common.cancel': 'Annuler',\n 'common.close': 'Fermer',\n 'common.done': 'Terminé',\n 'common.copied': '✓ Copié',\n\n // buyer picker (extraction in progress — P4 of the port plan)\n 'picker.holdSeats': 'Réserver les sièges et valider',\n 'picker.completeBooking': 'Terminer la réservation',\n 'picker.seatsHeld': 'Sièges réservés — {time}',\n 'picker.holdExpired': 'Votre réservation a expiré — les sièges ont été libérés. Sélectionnez à nouveau.',\n 'picker.seatTaken': 'Le siège {label} vient d\\'être réservé par un autre acheteur.',\n 'picker.poweredBy': 'Propulsé par SeatLayer',\n 'picker.testMode': 'MODE TEST',\n 'picker.colorblind': 'Couleurs adaptées au daltonisme',\n 'picker.orphanHint': \"Cela laisse un siège isolé — pensez à vous décaler d'un siège.\",\n 'picker.seats.one': '{count} siège',\n 'picker.seats.other': '{count} sièges',\n\n // renderer (drawn on the Konva map — shared by the embed SDK)\n 'map.aria': 'Plan de salle. Utilisez les flèches pour naviguer entre les sièges, Entrée pour sélectionner.',\n 'map.seatsLeft': '{count} LIBRES',\n 'map.statusHeld': 'En attente',\n 'map.statusTaken': 'Pris',\n 'map.fromPrice': 'DÈS {price}',\n\n // buyer picker page (src/pages/PickerPage.tsx)\n 'picker.language': 'Langue',\n 'picker.zoomToFit': 'Ajuster le zoom',\n 'picker.viewMode': 'Mode d\\'affichage',\n 'picker.floor': 'Étage',\n 'picker.zoomLevel': 'Niveau de zoom',\n 'picker.rungTip.zones': 'Vue générale — groupes de sections comme Tribune nord ou VIP',\n 'picker.rungTip.sections': 'Blocs de sections — mélange de catégories + teinte de disponibilité',\n 'picker.rungTip.seats': 'Sièges individuels — les blocs se transforment en points',\n 'picker.rungLabel.zones': 'ZONES',\n 'picker.rungLabel.sections': 'SECTIONS',\n 'picker.rungLabel.seats': 'SIÈGES',\n 'picker.sectionSummaryAria': 'Résumé de la section {label}',\n 'picker.closeSectionSummary': 'Fermer le résumé de la section',\n 'picker.seatsLeftInSection.one': '{count} siège restant',\n 'picker.seatsLeftInSection.other': '{count} sièges restants',\n 'picker.overview': 'Vue d\\'ensemble',\n 'picker.tapSeatHint': 'Appuyez sur un siège pour vérifier sa vue',\n 'picker.chartSize': 'Taille du plan',\n 'picker.custom': 'Personnalisé',\n 'picker.categories': 'Catégories',\n 'picker.accessibility': 'Accessibilité',\n 'picker.showAnyAccessible': 'Afficher un siège accessible',\n 'picker.any': 'N\\'importe quel',\n 'picker.yourSeats': 'Vos sièges',\n 'picker.emptySeats': 'Appuyez sur les sièges sur le plan',\n 'picker.emptySeatsWithGa': 'Appuyez sur les sièges sur le plan · appuyez sur une zone debout pour les billets GA',\n 'picker.oneFewer': 'Un de moins',\n 'picker.oneMore': 'Un de plus',\n 'picker.remove': 'Supprimer {label}',\n 'picker.ticketTierFor': 'Catégorie de billet pour {label}',\n 'picker.total': 'Total : {amount}',\n 'picker.viewFromSeat': 'Vue depuis le siège {label}',\n 'picker.real360': 'VRAI 360°',\n 'picker.preview': 'APERÇU',\n 'picker.open360': 'Ouvrir la vue à 360°',\n 'picker.sightline': '≈ {rows} rangées de la scène · {angle}° décalé du centre',\n 'picker.bookedDemo': 'Réservé ! (démo)',\n 'picker.bookButton.one': 'Réserver {count} billet — {amount}',\n 'picker.bookButton.other': 'Réserver {count} billets — {amount}',\n 'picker.simulateCrowd': 'Simuler la foule : {state}',\n 'picker.on': 'ACTIVÉ',\n 'picker.off': 'DÉSACTIVÉ',\n 'picker.panorama360': 'Photo panoramique 360° du lieu',\n 'picker.illustrationCaption': 'illustration · ≈ {m} m de la scène',\n};\n","/**\n * @seatlayer/core — the shared, framework-agnostic seat-rendering engine.\n *\n * Pure TypeScript + Konva (HTML canvas). No React, no framework. This is the\n * brain shared by the SeatLayer dashboard and every SDK wrapper. It is synced\n * byte-for-byte from the main app via `scripts/sync-core.mjs` until the app\n * migrates to consume this package directly.\n */\nexport * from './core/types';\nexport * from './core/layout';\nexport * from './core/ga';\nexport * from './core/sections';\nexport * from './engine/SeatmapRenderer';\nexport * from './picker/PickerController';\nexport * from './view/generatePanorama';\nexport * from './i18n';\nexport * from './i18n/bundles';\nexport * from './lib/money';\n","/**\n * SeatMap chart document — the single source of truth shared by the\n * Designer (authoring) and the Renderer (buyer picker).\n *\n * Mirrors docs/seatmap-build-spec.md §5. Coordinates are abstract units\n * (roughly \"pixels at scale 1\"); the renderer fits the chart to its container.\n * Rows are PARAMETRIC (origin + count + spacing + curve + rotation) — never\n * store per-seat coordinates in the document; expansion happens in layout.ts.\n */\n\nexport interface Point {\n x: number;\n y: number;\n}\n\nexport interface Category {\n key: string;\n label: string;\n color: string;\n /** Base price — used when the category has no explicit tiers. */\n price?: number;\n /**\n * Ticket tiers (Adult / Child / Senior…). When present, a buyer picks a tier\n * per seat in this category and the tier's price applies; the first tier is the\n * default. Per-category (not per-seat) pricing — see Batch 3.5. Empty/absent =\n * a single price (the `price` above).\n */\n tiers?: CategoryTier[];\n}\n\n/** One ticket tier within a category: a named price (Adult, Child, Senior…). */\nexport interface CategoryTier {\n id: string;\n name: string;\n price: number;\n}\n\n/**\n * Accessibility accommodations a seat can carry. Mirrors the taxonomy real\n * venues (and seats.io) expose so buyers can filter for exactly what they need\n * and organizers can mark seats precisely. `wheelchair` is the legacy default.\n */\nexport type AccessibilityType =\n | 'wheelchair'\n | 'companion'\n | 'semi-ambulatory'\n | 'hearing'\n | 'sign-language'\n | 'plus-size'\n | 'lift-armrest';\n\nexport interface AccessibilityMeta {\n key: AccessibilityType;\n /** Full descriptive label (designer checkbox, picker legend). */\n label: string;\n /** Compact label for chips/badges. */\n short: string;\n /** Single-glyph badge shown on seat chips + filter chips. */\n icon: string;\n}\n\n/** Ordered taxonomy — drives the designer seat panel and the picker filters. */\nexport const ACCESSIBILITY_TYPES: AccessibilityMeta[] = [\n { key: 'wheelchair', label: 'Wheelchair space', short: 'Wheelchair', icon: '♿' },\n { key: 'companion', label: 'Companion seat', short: 'Companion', icon: '🧑🤝🧑' },\n { key: 'semi-ambulatory', label: 'Semi-ambulatory (limited mobility)', short: 'Limited mobility', icon: '🦯' },\n { key: 'hearing', label: 'Assistive listening', short: 'Hearing', icon: '🦻' },\n { key: 'sign-language', label: 'Sign-language view', short: 'Sign language', icon: '🤟' },\n { key: 'plus-size', label: 'Plus-size seat', short: 'Plus-size', icon: '💺' },\n { key: 'lift-armrest', label: 'Lift-up armrest', short: 'Lift armrest', icon: '↕️' },\n];\n\nconst ACCESSIBILITY_LABEL = new Map(ACCESSIBILITY_TYPES.map((a) => [a.key, a]));\n\n/** Metadata for one accessibility key (undefined for unknown keys). */\nexport function accessibilityMeta(key: AccessibilityType): AccessibilityMeta | undefined {\n return ACCESSIBILITY_LABEL.get(key);\n}\n\nexport interface SeatOverride {\n /** 0-based seat index within the row. */\n index: number;\n /** Physical seat absent (pillar, sound desk) — numbering gap preserved. */\n skip?: boolean;\n /** Position nudge in chart units. */\n dx?: number;\n dy?: number;\n /** Replace the computed label entirely. */\n label?: string;\n categoryKey?: string;\n /** @deprecated legacy flag — read as `['wheelchair']`; write `accessibility`. */\n accessible?: boolean;\n /** Accessibility accommodations of this seat (empty/absent = none). */\n accessibility?: AccessibilityType[];\n}\n\n/** Brand/venue theming — applied by the renderer in both designer and picker. */\nexport interface ChartTheme {\n /** Canvas background color (default dark: #0e1117-ish radial). */\n background?: string;\n /** Seat label text color (default dark ink #0b1220). */\n seatLabelColor?: string;\n /** Selection ring / accent color (default white ring + brand accent). */\n selectionColor?: string;\n /** Décor (stage/shape) default fill. */\n decorFill?: string;\n /** Free-text color default. */\n textColor?: string;\n /** Font family (CSS stack) for all rendered text — seat labels, sections, décor text. */\n fontFamily?: string;\n /** Seat size multiplier on the base radius (0.7–1.6, default 1) — bigger seats fit longer labels. */\n seatScale?: number;\n // ---- White-label branding (applied by the buyer picker chrome) ----\n /** Brand accent color — recolors buttons, links, the hold pill, selection UI. */\n accent?: string;\n /** Ink color for text on the accent (e.g. button labels). Default light. */\n accentInk?: string;\n /** Organizer logo shown in the picker header (data/R2 URL). Falls back to the name. */\n logoUrl?: string;\n /** Brand/venue name shown in the picker header when no event name is set. */\n brandName?: string;\n /** Paid-tier flag: hide the \"Powered by SeatMap\" badge. */\n hideBadge?: boolean;\n}\n\nexport interface RowObject {\n type: 'row';\n id: string;\n /** Row label, e.g. \"A\". Seat labels are `${label}-${n}`. */\n label: string;\n /** Position of the FIRST seat. */\n origin: Point;\n /** Degrees, clockwise. 0 = seats laid out along +x. */\n rotation: number;\n /**\n * Total arc sweep in degrees across the whole row. 0 = straight.\n * Positive bends away from +y (concave toward the focal point when the\n * row faces it). Typical theatre rows: 10–40.\n */\n curve: number;\n seatCount: number;\n /** Distance between adjacent seat centers, in chart units. */\n seatSpacing: number;\n categoryKey: string;\n /** First seat number (default 1). */\n seatLabelStart?: number;\n /** Seat numbering within the row (default ltr, step 1). */\n seatNumbering?: {\n /** ltr / rtl number from an end; `center` numbers outward from the middle\n * (centre seat lowest — the premium-centre theatre convention). */\n direction: 'ltr' | 'rtl' | 'center';\n /** 2 = odd/even numbering (1,3,5… — start at 2 for evens). */\n step?: 1 | 2;\n };\n /**\n * Per-seat exceptions, keyed by seat index (0-based position in the row).\n * `skip` removes the physical seat but keeps the numbering gap (theatre\n * convention: a pillar eats A-3; A-4 stays A-4).\n */\n overrides?: SeatOverride[];\n /**\n * Organizer-supplied equirectangular 360 (or wide photo) shown as the\n * view-from-seat for every seat in this row. When absent, the picker\n * generates a synthetic panorama from chart geometry.\n */\n viewFromSeatUrl?: string;\n}\n\nexport interface GAAreaObject {\n type: 'gaArea';\n id: string;\n label: string;\n /** Closed polygon, in chart units. */\n points: Point[];\n capacity: number;\n categoryKey: string;\n}\n\n/** Non-bookable décor: stage, walls, exits. */\nexport interface ShapeObject {\n type: 'shape';\n id: string;\n kind: 'rect' | 'ellipse' | 'polygon';\n label?: string;\n /** For rect/ellipse: bounding box. For a stage polygon: the base (pre-shape) box, so its kind can be regenerated. */\n x?: number;\n y?: number;\n width?: number;\n height?: number;\n /** For polygon. */\n points?: Point[];\n fill?: string;\n /** Degrees clockwise about the shape's center (default 0). Applied at render time. */\n rotation?: number;\n /**\n * Semantic tag driving special rendering. `'stage'` gets the gradient +\n * prominent uppercase label treatment; a décor landmark role (bar, exit…)\n * gets a quieter label. Loose string to avoid a circular import with\n * stage.ts / decor.ts (see StageKind / DecorRole there).\n */\n role?: string;\n /** For a stage: which `StageKind` its polygon was generated from. */\n stageKind?: string;\n}\n\n/** Seats arranged around a table; bookable per-seat or as a whole. */\nexport interface TableObject {\n type: 'table';\n id: string;\n /** e.g. \"T1\" — seat labels are `${label}-${n}`. */\n label: string;\n center: Point;\n shape: 'round' | 'rect';\n /** Seats around the perimeter (round) or along the enabled edges (rect). */\n seatCount: number;\n /** Rect tables: which edges get seats (default ['top','bottom']). */\n sides?: Array<'top' | 'bottom' | 'left' | 'right'>;\n rotation: number;\n /** Round tables. */\n radius?: number;\n /**\n * Round tables: the arc (in degrees) the seats occupy, default 360 (full\n * ring). Below 360 leaves an open side — e.g. a service gap for waiters, a\n * head table facing the room, or clearance against a wall. The opening is\n * centred on the `rotation` direction; seats spread across the rest.\n */\n seatArc?: number;\n /** Rect tables. */\n width?: number;\n height?: number;\n categoryKey: string;\n /** Whole-table booking: buyers get all seats or none (per-event override later). */\n bookAsWhole?: boolean;\n}\n\n/** A booth: one bookable unit rendered as a block (trade shows, VIP boxes). */\nexport interface BoothObject {\n type: 'booth';\n id: string;\n label: string;\n center: Point;\n width: number;\n height: number;\n rotation: number;\n categoryKey: string;\n}\n\n/**\n * A named region of the venue (Balcony Left, Floor B…). Sections are outlines\n * only — objects belong to a section spatially (center inside the outline),\n * keeping the document flat (no nesting; simpler for tools and for AI edits).\n * Renderer: far zoom shows section shapes/labels instead of seats; clicking\n * a section zooms into it.\n */\nexport interface SectionObject {\n type: 'section';\n id: string;\n label: string;\n /** Closed polygon, chart units. */\n outline: Point[];\n /** Optional tint override (defaults to a neutral fill / dominant category mix). */\n color?: string;\n /** Zone this section belongs to (id into `ChartDoc.zones`). Far-zoom nav + pricing group. */\n zone?: string;\n /**\n * Tier height. 0 = floor (default). Higher values lift the section in the\n * picker's isometric (\"3D\") view, drawn on extruded side faces. Same field a\n * future multi-floor mode reuses — authored in 2D, never drawn by the user.\n */\n elevation?: number;\n /** Uniform scale about the outline centroid (1 = as drawn). Scales members too. */\n scale?: number;\n /** 0–1: how strongly member-row curves are bent toward a common arc fitted to the outline. */\n smoothing?: number;\n /** Degrees clockwise about the outline centroid (default 0). Rotates members too. */\n rotation?: number;\n}\n\n/**\n * A group of sections (Lower Bowl, Upper Bowl, Floor…). One concept, three jobs:\n * the farthest-zoom navigation unit, a pricing group, and (Batch 3) a timed-\n * release unit. Kept as a flat list on the doc; sections point back by `zone` id.\n */\nexport interface ZoneDef {\n id: string;\n label: string;\n color?: string;\n}\n\n/**\n * Selection layer — a hit-test/dim filter in the designer, NOT z-order management.\n * Fixed set of four; derived from object type via `layerOf()` (no per-object field yet).\n */\nexport type SelectionLayer = 'interactive' | 'background' | 'foreground' | 'surroundings';\n\n/** Derive an object's selection layer from its type (design contract, HANDOFF §03). */\nexport function layerOf(obj: ChartObject): SelectionLayer {\n switch (obj.type) {\n case 'row':\n case 'table':\n case 'gaArea':\n case 'booth':\n case 'section':\n return 'interactive';\n // stage / décor live on 'shape'; free text + decor images are background furniture.\n case 'shape':\n case 'text':\n case 'decorImage':\n return 'background';\n default:\n return 'interactive';\n }\n}\n\n/** Free-standing text on the chart (aisle names, door labels…). */\nexport interface TextObject {\n type: 'text';\n id: string;\n text: string;\n position: Point;\n fontSize: number;\n rotation: number;\n color?: string;\n}\n\n/**\n * A raster/vector decor graphic drawn IN the chart, beneath the seats and\n * sections (ice rink, basketball court, stage art, pitch markings). Purely\n * visual venue context — never bookable, never hit-tested, so it never steals a\n * seat click. `href` is a self-contained data URL (image or SVG) produced by the\n * same client-side downscale used for row photos, so it travels with the doc and\n * caches as a single bitmap blit (zero per-frame cost). Placed by top-left\n * (x,y) + size, rotated about its centre — the same handles a shape rect uses.\n */\nexport interface DecorImageObject {\n type: 'decorImage';\n id: string;\n /** Image or SVG data URL. */\n href: string;\n x: number;\n y: number;\n width: number;\n height: number;\n /** Degrees clockwise about the image centre (default 0). */\n rotation?: number;\n /** 0–1 (default 1). Multiplied by any chart-theme dimming at render time. */\n opacity?: number;\n /** Optional caption for the designer inspector / accessibility (not drawn). */\n label?: string;\n}\n\nexport type ChartObject =\n | RowObject\n | GAAreaObject\n | ShapeObject\n | TableObject\n | BoothObject\n | TextObject\n | SectionObject\n | DecorImageObject;\n\n/**\n * One floor / level of a multi-floor venue (Batch 5). Each floor owns its own\n * geometry, stage focal point, and trace image; categories/zones/tiers stay\n * chart-global (one event, one inventory). A single-floor chart has NO `floors`\n * — its `objects[]` is the whole venue — so all existing charts are untouched.\n */\nexport interface Floor {\n id: string;\n name: string;\n objects: ChartObject[];\n focalPoint: Point;\n backgroundImage?: ChartDoc['backgroundImage'];\n}\n\nexport interface ChartDoc {\n version: 1;\n name: string;\n venueType: 'SIMPLE' | 'MIXED';\n /** The stage / point every seat looks at. Anchors seat-view + sightlines.\n * Multi-floor: mirrors floor 0; each floor also carries its own focalPoint. */\n focalPoint: Point;\n categories: Category[];\n /** Section groupings for far-zoom navigation + pricing (optional; sections reference by id). */\n zones?: ZoneDef[];\n /** Multi-floor venues (Batch 5): present ⇒ floors[] is the source of truth;\n * absent ⇒ single-floor and `objects` below is the whole chart. `objects`\n * is kept mirroring floor 0 so single-floor readers never branch. */\n floors?: Floor[];\n objects: ChartObject[];\n /** Floor-plan photo the organizer traces over (designer-only aid, also rendered dimly in picker if kept). */\n backgroundImage?: {\n url: string;\n center: Point;\n /** Rendered width in chart units (height follows the image aspect). */\n width: number;\n opacity: number;\n locked?: boolean;\n };\n /** Brand/venue theming (colors); categories carry their own colors separately. */\n theme?: ChartTheme;\n /** Parametric-template provenance: present ⇒ the chart came from a capacity-\n * adjustable template family, and the designer offers a capacity control that\n * regenerates it at a new target seat count (Batch 4 \"curated singles + resize\"). */\n template?: { family: string; targetSeats: number };\n}\n\n// ---------------------------------------------------------------------------\n// Expanded (render-time) model — produced by layout.ts, consumed by the engine\n// ---------------------------------------------------------------------------\n\nexport interface ExpandedSeat {\n /** Stable id: `${rowId}:${index}` */\n id: string;\n /** Public label: `${rowLabel}-${seatNumber}` */\n label: string;\n x: number;\n y: number;\n rowId: string;\n categoryKey: string;\n /** 'booth' units render as blocks (dimensions looked up via rowId = booth id). */\n kind?: 'seat' | 'booth';\n /** True when the seat has any accessibility accommodation — renderer rings/dims these. */\n accessible?: boolean;\n /** Specific accessibility accommodations (absent = none) — picker badges/filters these. */\n accessibility?: AccessibilityType[];\n /** Organizer-supplied view-from-seat image (inherited from the row). */\n viewUrl?: string;\n}\n\nexport type SeatStatus = 'free' | 'held' | 'booked' | 'not_for_sale';\n\n// ---------------------------------------------------------------------------\n// Renderer engine public API — implemented in src/engine/SeatmapRenderer.ts\n// ---------------------------------------------------------------------------\n\nexport interface RendererCallbacks {\n onSelect?: (seat: ExpandedSeat) => void;\n onDeselect?: (seat: ExpandedSeat) => void;\n /** seat is null when the pointer leaves any seat. */\n onHover?: (seat: ExpandedSeat | null) => void;\n /** Keyboard focus moved to a seat (arrow-key navigation) — for screen-reader announcements. */\n onFocusSeat?: (seat: ExpandedSeat | null) => void;\n /** Called ~1×/sec with the measured frames-per-second. */\n onFps?: (fps: number) => void;\n /** Fired when a GA area is clicked (quantity picking is UI-side). */\n onGAClick?: (areaId: string) => void;\n /**\n * Fired when a tap lands on a section outline while seats are NOT the active\n * rung (i.e. zoomed out, section/zone LOD). The host glides in + shows a\n * section-summary card instead of trying to select a 4px seat (Slice 5).\n */\n onSectionTap?: (sectionId: string) => void;\n /**\n * Fired when a seat/deck is tapped in the 3D all-floors stacked overview — the\n * host drops back to the flat 2D map on that floor (\"tap a deck to enter\").\n */\n onDeckTap?: (floorId: string) => void;\n /** Fired after any pan/zoom/resize settles — re-anchor screen-space overlays. */\n onViewChange?: () => void;\n /**\n * Organizer manage-mode only (`manageMode` + `marqueeSelect`): fired on\n * pointer-UP after a rubber-band marquee drag, or a ⌘A/Escape bulk shortcut,\n * with the FULL current selection (selectable seats only). The host toolbar\n * reads this to drive bulk block/unblock. Never fires when manageMode is off.\n */\n onMarquee?: (seats: ExpandedSeat[]) => void;\n}\n\n/** Far-zoom level-of-detail rung: whole zones → section blocks → individual seats. */\nexport type LodRung = 'zones' | 'sections' | 'seats';\n\nexport interface RendererOptions extends RendererCallbacks {\n /** Max seats selectable at once (default 10). */\n maxSelection?: number;\n /** Only these statuses are clickable (default ['free']). */\n selectableStatuses?: SeatStatus[];\n /**\n * Opt-in host behaviour flag — the renderer's own click/selection logic is\n * unchanged (it still selects + fires `onSelect` immediately, so the seat\n * highlights right away). When true, the host (e.g. PublicEventPage) treats\n * that `onSelect` as a pending candidate and shows a confirm card instead of\n * pushing straight into the cart; `deselect([seat.id])` on Cancel un-highlights.\n */\n confirmSelection?: boolean;\n /** ISO 4217 currency for on-map prices (\"FROM …\"); defaults to money.DEFAULT_CURRENCY.\n * Locale for grouping/symbol placement comes from the active i18n locale. */\n currency?: string;\n /**\n * Organizer manage surface (SDK SeatManager). Opt-in — enables the manage-mode\n * gestures (marquee, ⌘A/Escape) and the bulk-selection helpers. Buyer pan /\n * pinch / tap and every existing code path are byte-identical when this is\n * false (every manage branch is gated on it). Default false.\n */\n manageMode?: boolean;\n /**\n * When `manageMode` is on, a mouse/pen primary-button drag at the seats rung\n * draws a rubber-band marquee that bulk-selects the seats it covers (emitting\n * `onMarquee` on pointer-up) instead of panning. Touch keeps single-finger\n * pan (pinch to zoom); a middle-button drag pans with a mouse. Disabled below\n * the seats rung (zoom in first). No effect unless `manageMode` is also set.\n */\n marqueeSelect?: boolean;\n}\n\nexport interface ISeatmapRenderer {\n /** Replace the chart. Resets selection and statuses, zooms to fit.\n * `opts.floorId` picks which floor to render on a multi-floor chart (Batch 5). */\n setChart(doc: ChartDoc, opts?: { floorId?: string }): void;\n /** Bulk status update; re-renders affected seats only. */\n setStatus(seatIds: string[], status: SeatStatus): void;\n /**\n * Mark the active buyer's own held seats. They remain server-status `held`,\n * but render with the buyer selection treatment instead of the anonymous\n * unavailable treatment used for another buyer's hold.\n */\n setOwnedHold?(seatIds: string[] | null): void;\n /**\n * Mark one selected seat as the buyer's pending confirmation candidate.\n * The candidate receives a strong focus halo while unrelated seats recede;\n * pass null after Select/Cancel. This is visual only and never mutates the\n * renderer selection.\n */\n setSelectionFocus?(seatId: string | null): void;\n /**\n * SYNCHRONOUS repaint that bypasses requestAnimationFrame. Konva's batchDraw()\n * (used by setStatus and friends) schedules the actual paint on the next rAF\n * tick, which Chrome throttles/pauses on hidden, backgrounded, or occluded\n * tabs — so a seat-status delta updates the scene graph but the pixels never\n * change until the tab is foregrounded again. forceDraw() paints the affected\n * layers immediately (Layer.draw() is synchronous) and flushes any pending\n * cache-debounce, so a caller (visibilitychange catch-up, or an opted-in\n * always-live board) can guarantee the canvas reflects current state\n * regardless of tab visibility. No-op difference in the foreground.\n */\n forceDraw(): void;\n getStatus(seatId: string): SeatStatus;\n getSelection(): ExpandedSeat[];\n clearSelection(): void;\n /**\n * Dynamically update organizer-only interaction without rebuilding the\n * renderer. No buyer surface calls this; every behavior remains gated by\n * `manageMode` exactly as it is at construction time.\n */\n setManageInteraction?(options: {\n manageMode: boolean;\n marqueeSelect: boolean;\n selectableStatuses: SeatStatus[];\n maxSelection?: number;\n }): void;\n /** Organizer-only section heat overlay. Values are normalized 0..1. */\n setSectionHeat?(scores: Record<string, number> | null): void;\n /**\n * Manage-mode bulk selection helpers (no-op / empty unless `manageMode`).\n * They select the matching SELECTABLE seats (respecting `selectableStatuses`\n * + closed sections), union with the current selection, and return the seats\n * they added — the SDK SeatManager expands category/row/section picks to\n * labels and drives one batched block/unblock from them.\n */\n selectAllSelectable?(): ExpandedSeat[];\n selectByLabels?(labels: string[]): ExpandedSeat[];\n /** Selectable seats belonging to a section OR zone id (no selection side-effect). */\n getSelectableInSection?(sectionId: string): ExpandedSeat[];\n /** Programmatic deselect of specific seats (e.g. chip × in the cart). */\n deselect(seatIds: string[]): void;\n /**\n * Brief attention pulse on a seat (a ring that expands + fades once) — used to\n * signal live activity, e.g. a seat \"just taken\" by another buyer via a WS\n * delta. Purely visual; no state change. `color` overrides the default.\n */\n flashSeat(seatId: string, color?: string): void;\n zoomToFit(): void;\n /** Zoom in one step about the viewport center, clamped to the usual zoom bounds. */\n zoomIn(): void;\n /** Zoom out one step about the viewport center, clamped to the usual zoom bounds. */\n zoomOut(): void;\n /** Total seat count of the current chart. */\n seatCount(): number;\n /**\n * Maps a chart-space point (or a seat, by its x/y) to container-relative\n * screen pixels, using the current stage scale/position. Lets host UI anchor\n * DOM overlays (confirm card, tooltip) over a live seat and re-anchor them\n * on `onViewChange`.\n */\n worldToScreen(point: Point): { x: number; y: number };\n /** When on, dim non-accessible free seats so accessible seats stand out. */\n setAccessibleFilter(on: boolean): void;\n /**\n * Dim free seats that lack ANY of these accessibility types. `null` clears the\n * filter; `[]` means \"any accessible seat\" (same as setAccessibleFilter(true)).\n */\n setAccessibilityFilter(types: AccessibilityType[] | null): void;\n /** Legend hover-highlight: dim free seats of other categories (null clears). */\n setCategoryHighlight?(key: string | null): void;\n /** Price-band filter (F4): dim free seats whose category is NOT in `keys`\n * (null clears). The widget resolves which categories fall in the band. */\n setCategoryFilter?(keys: string[] | null): void;\n /** Dim the seats of these section/zone ids (organizer manager: held-back inventory). */\n setDimmedSections?(ids: string[] | null): void;\n /**\n * Phase 2 event-level section states: mark these section/zone ids `closed` —\n * flat grey block, seats greyed + not pickable, section stays rendered.\n * `null`/empty clears. (Distinct from the buyer's applyHidden seat-strip.)\n */\n setClosedSections?(ids: string[] | null): void;\n /**\n * AXS section-focus: dim + desaturate every other section, draw a calm backdrop\n * behind this section, and glide the camera to frame it. Seat-picking is gated\n * until seats are large enough on screen (≥ LABEL_SCALE). Slice 5 / Phase 2 §4.\n */\n focusSection?(id: string): void;\n /** Clear an AXS section focus (restore full-bowl brightness + drop backdrop). */\n clearSectionFocus?(): void;\n /** The currently AXS-focused section id, or null. */\n getFocusedSection?(): string | null;\n /** World-space rect currently visible in the viewport (minimap viewport frame). */\n getVisibleWorldRect?(): { x: number; y: number; width: number; height: number };\n /** Axis-aligned world bounds of all seats + section outlines (minimap frame). */\n getWorldBounds?(): { x: number; y: number; width: number; height: number };\n /**\n * Colorblind-safe mode: category hues switch to an Okabe-Ito palette and\n * booked seats render hollow (a non-color cue), so seat state never relies\n * on hue alone. Off (the default) renders exactly as before.\n */\n setColorblindSafe?(on: boolean): void;\n /**\n * Switch the projection. `'flat'` = normal top-down; `'isometric'` = the \"3D\"\n * view (affine skew/rotate + elevation lift), hit-testing preserved in screen\n * space. Purely visual — the chart is authored flat. Animated unless reduced-motion.\n */\n setViewMode?(mode: 'flat' | 'isometric'): void;\n /** Current projection (defaults to 'flat' when unimplemented). */\n getViewMode?(): 'flat' | 'isometric';\n /** Multi-floor (Batch 5): switch the shown floor; list floors; read the active id. */\n setActiveFloor?(floorId: string): void;\n getFloors?(): { id: string; name: string }[];\n getActiveFloorId?(): string;\n /** Render all floors stacked (3D overview) vs the active floor. No-op single-floor. */\n setStacked?(on: boolean): void;\n isStacked?(): boolean;\n /**\n * Section id whose outline contains a container-relative screen point (or null).\n * Feeds the far-zoom \"tap a section to zoom in\" flow (Slice 5).\n */\n sectionAt?(clientPoint: Point): string | null;\n /** Seat ids belonging to a section — for the section-summary card (Slice 5). */\n sectionMembers?(id: string): string[];\n /**\n * Smoothly glide (pan+zoom) the camera to frame a section (by id) or a world-\n * space bounds rect over ~450ms easeInOutCubic. `prefers-reduced-motion` snaps.\n * A pointer-down (grab/pan) cancels an in-flight glide. Slice 5 \"glide in\".\n */\n focusRegion?(\n target: string | { x: number; y: number; width: number; height: number },\n opts?: { animate?: boolean },\n ): void;\n /** Current LOD rung derived from zoom (for the ZONES/SECTIONS/SEATS pill). */\n getRung?(): LodRung;\n /** Jump the camera to a rung's zoom band, centred on the chart (glided). */\n setRung?(rung: LodRung): void;\n destroy(): void;\n}\n\n/** localStorage key the Designer writes and the Picker reads. */\nexport const CHART_STORAGE_KEY = 'seatmap.chart';\n","/**\n * Pure geometry helpers — no Konva, no DOM. Turns the parametric chart\n * document into concrete seat coordinates and computes bounding boxes.\n */\n\nimport type {\n AccessibilityType,\n BoothObject,\n ChartDoc,\n ChartObject,\n ExpandedSeat,\n Floor,\n Point,\n RowObject,\n SeatOverride,\n TableObject,\n} from './types';\n\n/** Resolve a seat override's accessibility, honouring the legacy boolean flag. */\nfunction overrideAccessibility(o: SeatOverride | undefined): AccessibilityType[] {\n if (!o) return [];\n if (o.accessibility && o.accessibility.length) return o.accessibility;\n return o.accessible ? ['wheelchair'] : [];\n}\n\nconst DEG = Math.PI / 180;\n/** Seat visual radius (mirrors the renderer) — used only for bounds padding. */\nconst SEAT_R = 9;\n/** How far outside a table's body its seats sit. */\nconst TABLE_SEAT_OFFSET = 16;\n\n/** Rotate a local point clockwise by `deg` (screen coords, +y down) then translate. */\nfunction place(lx: number, ly: number, deg: number, origin: Point): { x: number; y: number } {\n const a = deg * DEG;\n const cos = Math.cos(a);\n const sin = Math.sin(a);\n return {\n x: origin.x + lx * cos - ly * sin,\n y: origin.y + lx * sin + ly * cos,\n };\n}\n\n/**\n * Expand a parametric row into seat positions.\n *\n * Straight (curve === 0): seat i sits at local (i·spacing, 0).\n *\n * Curved: seats lie on a circular arc. Per-seat angular step is\n * `curve/(seatCount-1)`; radius is derived so the chord between neighbours\n * equals seatSpacing → radius = spacing / (2·sin(step/2)). Seat 0 sits at the\n * bottom of the arc (local origin) with the circle centre directly above it at\n * (0,-radius); increasing index sweeps toward +x while the ends rise toward -y,\n * i.e. positive curve is concave toward -y (a row wrapping a stage above it).\n * Local points are then rotated by `rotation` and translated to `origin`.\n *\n * Numbering (labels only, never geometry): `seatNumbering.direction === 'rtl'`\n * numbers from the far physical end; `step === 2` produces odd/even numbering\n * (start at 1 → 1,3,5…; start at 2 → 2,4,6…).\n */\n/** Base (pre-override) seat centre per index — shared by expandRow + designer edit mode. */\nfunction rowSeatPositions(row: RowObject): Point[] {\n const { seatCount, seatSpacing, curve, rotation, origin } = row;\n const out: Point[] = [];\n if (seatCount <= 1) {\n if (seatCount === 1) out.push({ x: origin.x, y: origin.y });\n return out;\n }\n if (curve === 0) {\n for (let i = 0; i < seatCount; i++) out.push(place(i * seatSpacing, 0, rotation, origin));\n return out;\n }\n const arcStep = (curve / (seatCount - 1)) * DEG; // radians per seat\n const radius = seatSpacing / (2 * Math.sin(Math.abs(arcStep) / 2));\n // Centre above seat 0. φ measured from the downward vertical, growing with index.\n for (let i = 0; i < seatCount; i++) {\n const phi = i * arcStep;\n const lx = radius * Math.sin(phi);\n const ly = -radius + radius * Math.cos(phi); // ≤ 0 → ends rise toward -y\n out.push(place(lx, ly, rotation, origin));\n }\n return out;\n}\n\nfunction overrideMap(row: RowObject): Map<number, SeatOverride> {\n const m = new Map<number, SeatOverride>();\n if (row.overrides) for (const o of row.overrides) m.set(o.index, o);\n return m;\n}\n\n/**\n * Every seat slot of a row INCLUDING skipped ones (designer seat-edit mode uses\n * this to draw un-skip handles). Overrides (dx/dy/label/categoryKey) are applied\n * but a skipped slot is flagged, not omitted.\n */\nexport interface RowSeatSlot {\n index: number;\n x: number;\n y: number;\n label: string;\n categoryKey: string;\n skipped: boolean;\n accessible: boolean;\n accessibility: AccessibilityType[];\n}\n\nexport function expandRowSlots(row: RowObject): RowSeatSlot[] {\n const start = row.seatLabelStart ?? 1;\n const dir = row.seatNumbering?.direction ?? 'ltr';\n const step = row.seatNumbering?.step ?? 1;\n const n = row.seatCount;\n let seatNumber: (i: number) => number;\n if (dir === 'center') {\n // Number outward from the middle: rank seats by distance from centre\n // (inner-left wins ties), so the centre seat gets `start`.\n const rank = new Array<number>(n);\n Array.from({ length: n }, (_, i) => i)\n .sort((a, b) => Math.abs(2 * a - (n - 1)) - Math.abs(2 * b - (n - 1)) || a - b)\n .forEach((idx, k) => (rank[idx] = k));\n seatNumber = (i) => start + rank[i] * step;\n } else {\n seatNumber = (i) => start + (dir === 'rtl' ? n - 1 - i : i) * step;\n }\n const ov = overrideMap(row);\n return rowSeatPositions(row).map((p, i) => {\n const o = ov.get(i);\n const accessibility = overrideAccessibility(o);\n return {\n index: i,\n x: p.x + (o?.dx ?? 0),\n y: p.y + (o?.dy ?? 0),\n label: o?.label ?? `${row.label}-${seatNumber(i)}`,\n categoryKey: o?.categoryKey ?? row.categoryKey,\n skipped: !!o?.skip,\n accessible: accessibility.length > 0,\n accessibility,\n };\n });\n}\n\nexport function expandRow(row: RowObject): ExpandedSeat[] {\n const seats: ExpandedSeat[] = [];\n for (const slot of expandRowSlots(row)) {\n if (slot.skipped) continue; // physical seat absent; numbering gap preserved\n seats.push({\n id: `${row.id}:${slot.index}`,\n label: slot.label,\n x: slot.x,\n y: slot.y,\n rowId: row.id,\n categoryKey: slot.categoryKey,\n accessible: slot.accessible || undefined,\n accessibility: slot.accessibility.length ? slot.accessibility : undefined,\n viewUrl: row.viewFromSeatUrl,\n });\n }\n return seats;\n}\n\n/**\n * Expand a table into its perimeter seats.\n *\n * Round: seats spread evenly on a circle of radius `radius + 16`, the first at\n * angle `rotation` (degrees, clockwise from +x). Rect: seats line the top and\n * bottom edges (split evenly, any remainder to the top), 16u outside the edge,\n * the whole set rotated about the table centre.\n */\nexport function expandTable(t: TableObject): ExpandedSeat[] {\n const seats: ExpandedSeat[] = [];\n const n = Math.max(0, Math.round(t.seatCount));\n if (n === 0) return seats;\n\n const mk = (i: number, x: number, y: number): ExpandedSeat => ({\n id: `${t.id}:${i}`,\n label: `${t.label}-${i + 1}`,\n x,\n y,\n rowId: t.id,\n categoryKey: t.categoryKey,\n });\n\n if (t.shape === 'round') {\n const R = (t.radius ?? 40) + TABLE_SEAT_OFFSET;\n const base = t.rotation * DEG;\n const arc = Math.max(0, Math.min(360, t.seatArc ?? 360));\n if (arc >= 360 || n === 1) {\n // Full ring (or a lone seat) — evenly spaced around the whole table.\n for (let i = 0; i < n; i++) {\n const a = base + (i / n) * 2 * Math.PI;\n seats.push(mk(i, t.center.x + R * Math.cos(a), t.center.y + R * Math.sin(a)));\n }\n return seats;\n }\n // Open side: seats fill the arc, leaving a gap centred on `rotation` (the\n // opening — face it toward the aisle/wall). Seats span edge-to-edge of the\n // seated arc so people flank the gap.\n const arcRad = arc * DEG;\n const halfGap = (2 * Math.PI - arcRad) / 2;\n const start = base + halfGap;\n for (let i = 0; i < n; i++) {\n const a = start + (i / (n - 1)) * arcRad;\n seats.push(mk(i, t.center.x + R * Math.cos(a), t.center.y + R * Math.sin(a)));\n }\n return seats;\n }\n\n // Rect: seats line the enabled edges. Round-robin the count across sides in\n // canonical order so they stay balanced; top/bottom run along width, left/\n // right along height, all 16u outside and rotated with the table.\n const w = t.width ?? 80;\n const h = t.height ?? 50;\n const enabled: NonNullable<TableObject['sides']> =\n t.sides && t.sides.length ? t.sides : ['top', 'bottom'];\n const order = (['top', 'bottom', 'left', 'right'] as const).filter((s) => enabled.includes(s));\n if (!order.length) return seats;\n const counts = new Map<(typeof order)[number], number>(order.map((s) => [s, 0]));\n for (let i = 0; i < n; i++) {\n const s = order[i % order.length];\n counts.set(s, counts.get(s)! + 1);\n }\n let idx = 0;\n for (const side of order) {\n const count = counts.get(side)!;\n for (let j = 0; j < count; j++) {\n let localX: number;\n let localY: number;\n if (side === 'top') {\n localX = -w / 2 + ((j + 0.5) * w) / count;\n localY = -h / 2 - TABLE_SEAT_OFFSET;\n } else if (side === 'bottom') {\n localX = -w / 2 + ((j + 0.5) * w) / count;\n localY = h / 2 + TABLE_SEAT_OFFSET;\n } else if (side === 'left') {\n localX = -w / 2 - TABLE_SEAT_OFFSET;\n localY = -h / 2 + ((j + 0.5) * h) / count;\n } else {\n localX = w / 2 + TABLE_SEAT_OFFSET;\n localY = -h / 2 + ((j + 0.5) * h) / count;\n }\n const p = place(localX, localY, t.rotation, t.center);\n seats.push(mk(idx++, p.x, p.y));\n }\n }\n return seats;\n}\n\n/** Expand a booth into its single bookable block unit. */\nexport function expandBooth(b: BoothObject): ExpandedSeat[] {\n return [\n {\n id: `${b.id}:0`,\n label: b.label,\n x: b.center.x,\n y: b.center.y,\n rowId: b.id,\n categoryKey: b.categoryKey,\n kind: 'booth',\n },\n ];\n}\n\n/** Ray-cast point-in-polygon test — odd crossings ⇒ inside. */\nexport function pointInPolygon(p: Point, poly: Point[]): boolean {\n let inside = false;\n for (let i = 0, j = poly.length - 1; i < poly.length; j = i++) {\n const xi = poly[i].x;\n const yi = poly[i].y;\n const xj = poly[j].x;\n const yj = poly[j].y;\n const hit = yi > p.y !== yj > p.y && p.x < ((xj - xi) * (p.y - yi)) / (yj - yi) + xi;\n if (hit) inside = !inside;\n }\n return inside;\n}\n\n/** Average of polygon vertices (v1 centroid — good enough for labels/membership). */\nfunction polygonCentroid(pts: Point[]): Point {\n if (!pts.length) return { x: 0, y: 0 };\n let x = 0;\n let y = 0;\n for (const p of pts) {\n x += p.x;\n y += p.y;\n }\n return { x: x / pts.length, y: y / pts.length };\n}\n\n/**\n * Visual centre of any object — used for spatial section membership and for\n * rotating an object about its centre. Rows: centroid of expanded seats (or\n * origin when empty); tables/booths: centre; GA/section: polygon centroid;\n * shape: bbox centre; text: its position.\n */\nexport function objectCenter(o: ChartObject): Point {\n switch (o.type) {\n case 'row': {\n const seats = expandRow(o);\n if (!seats.length) return { x: o.origin.x, y: o.origin.y };\n let x = 0;\n let y = 0;\n for (const s of seats) {\n x += s.x;\n y += s.y;\n }\n return { x: x / seats.length, y: y / seats.length };\n }\n case 'table':\n case 'booth':\n return { x: o.center.x, y: o.center.y };\n case 'gaArea':\n return polygonCentroid(o.points);\n case 'section':\n return polygonCentroid(o.outline);\n case 'text':\n return { x: o.position.x, y: o.position.y };\n case 'shape':\n if (o.points && o.points.length) return polygonCentroid(o.points);\n if (o.x != null && o.y != null && o.width != null && o.height != null) {\n return { x: o.x + o.width / 2, y: o.y + o.height / 2 };\n }\n return { x: o.x ?? 0, y: o.y ?? 0 };\n case 'decorImage':\n return { x: o.x + o.width / 2, y: o.y + o.height / 2 };\n }\n}\n\n/**\n * Normalized floor list (Batch 5): a multi-floor chart's `floors`, or a synthetic\n * single floor wrapping a single-floor chart's `objects`. Every consumer that needs\n * to reason about floors goes through this so single-floor charts stay untouched.\n */\nexport function floorsOf(doc: ChartDoc): Floor[] {\n if (doc.floors && doc.floors.length) return doc.floors;\n return [{ id: 'floor-0', name: 'Main', objects: doc.objects, focalPoint: doc.focalPoint, backgroundImage: doc.backgroundImage }];\n}\n\n/** Objects of one floor by id (defaults to the first floor). */\nexport function floorObjects(doc: ChartDoc, floorId?: string): ChartObject[] {\n const floors = floorsOf(doc);\n return (floorId ? floors.find((f) => f.id === floorId) : floors[0])?.objects ?? [];\n}\n\n/** Every object across ALL floors — the whole venue (single-floor = `doc.objects`). */\nexport function allObjects(doc: ChartDoc): ChartObject[] {\n return doc.floors && doc.floors.length ? doc.floors.flatMap((f) => f.objects) : doc.objects;\n}\n\n/** A copy of an object translated by (dx, dy) — every coordinate field shifted. */\nfunction translateObject(o: ChartObject, dx: number, dy: number): ChartObject {\n const p = (pt: Point): Point => ({ x: pt.x + dx, y: pt.y + dy });\n const pts = (a: Point[]): Point[] => a.map(p);\n switch (o.type) {\n case 'row':\n return { ...o, origin: p(o.origin) };\n case 'table':\n case 'booth':\n return { ...o, center: p(o.center) };\n case 'gaArea':\n return { ...o, points: pts(o.points) };\n case 'section':\n return { ...o, outline: pts(o.outline) };\n case 'text':\n return { ...o, position: p(o.position) };\n case 'shape':\n return {\n ...o,\n ...(o.points ? { points: pts(o.points) } : {}),\n ...(o.x != null ? { x: o.x + dx } : {}),\n ...(o.y != null ? { y: o.y + dy } : {}),\n };\n case 'decorImage':\n return { ...o, x: o.x + dx, y: o.y + dy };\n }\n}\n\n/**\n * Multi-floor 3D stack (Batch 5): flatten every floor into ONE doc with floor `i`\n * lifted by `i * spread` in −y, so the isometric view shows the floors as stacked\n * decks (ground at the bottom). Returns a single-floor doc (no `floors`). Meant\n * only for the 3D overview render — 2D still shows one floor via `floorObjects`.\n */\nexport function stackFloors(doc: ChartDoc, spread = 900): ChartDoc {\n if (!doc.floors || doc.floors.length < 2) return doc;\n const objects: ChartObject[] = [];\n doc.floors.forEach((f, i) => {\n const dy = -i * spread;\n for (const o of f.objects) objects.push(dy === 0 ? o : translateObject(o, 0, dy));\n });\n return { ...doc, objects, floors: undefined };\n}\n\n/** Expand every seat-bearing object across all floors (rows, tables, booths). */\nexport function expandChart(doc: ChartDoc): ExpandedSeat[] {\n const out: ExpandedSeat[] = [];\n for (const obj of allObjects(doc)) {\n if (obj.type === 'row') out.push(...expandRow(obj));\n else if (obj.type === 'table') out.push(...expandTable(obj));\n else if (obj.type === 'booth') out.push(...expandBooth(obj));\n }\n return out;\n}\n\nconst PAD = 40;\n\n/** Axis-aligned bounds over every object plus the background image, with padding. */\nexport function chartBounds(doc: ChartDoc): { x: number; y: number; width: number; height: number } {\n let minX = Infinity;\n let minY = Infinity;\n let maxX = -Infinity;\n let maxY = -Infinity;\n\n const acc = (x: number, y: number) => {\n if (x < minX) minX = x;\n if (y < minY) minY = y;\n if (x > maxX) maxX = x;\n if (y > maxY) maxY = y;\n };\n\n for (const s of expandChart(doc)) acc(s.x, s.y);\n\n for (const obj of allObjects(doc)) {\n if (obj.type === 'gaArea') {\n for (const p of obj.points) acc(p.x, p.y);\n } else if (obj.type === 'section') {\n for (const p of obj.outline) acc(p.x, p.y);\n } else if (obj.type === 'decorImage') {\n acc(obj.x, obj.y);\n acc(obj.x + obj.width, obj.y + obj.height);\n } else if (obj.type === 'shape') {\n if (obj.points && obj.points.length) {\n for (const p of obj.points) acc(p.x, p.y);\n } else if (obj.x != null && obj.y != null && obj.width != null && obj.height != null) {\n acc(obj.x, obj.y);\n acc(obj.x + obj.width, obj.y + obj.height);\n }\n } else if (obj.type === 'table') {\n const off = TABLE_SEAT_OFFSET + SEAT_R;\n const ext =\n obj.shape === 'round'\n ? (obj.radius ?? 40) + off\n : Math.max((obj.width ?? 80) / 2, (obj.height ?? 50) / 2) + off; // rotation-agnostic over-approximation\n acc(obj.center.x - ext, obj.center.y - ext);\n acc(obj.center.x + ext, obj.center.y + ext);\n } else if (obj.type === 'booth') {\n const ext = Math.max(obj.width, obj.height) / 2;\n acc(obj.center.x - ext, obj.center.y - ext);\n acc(obj.center.x + ext, obj.center.y + ext);\n } else if (obj.type === 'text') {\n const w = obj.fontSize * obj.text.length * 0.6; // approximate glyph advance\n acc(obj.position.x, obj.position.y);\n acc(obj.position.x + w, obj.position.y + obj.fontSize);\n }\n }\n\n if (doc.backgroundImage) {\n const { center, width } = doc.backgroundImage;\n const bh = (width * 3) / 4; // assume 4:3 when the true aspect is unknown at bounds-time\n acc(center.x - width / 2, center.y - bh / 2);\n acc(center.x + width / 2, center.y + bh / 2);\n }\n\n // Empty document → a sane default box around the focal point.\n if (!isFinite(minX)) {\n const f = doc.focalPoint ?? { x: 0, y: 0 };\n return { x: f.x - 200, y: f.y - 200, width: 400, height: 400 };\n }\n\n return {\n x: minX - PAD,\n y: minY - PAD,\n width: maxX - minX + PAD * 2,\n height: maxY - minY + PAD * 2,\n };\n}\n","import type { ChartDoc, GAAreaObject } from './types';\nimport { allObjects } from './layout';\n\nconst PREFIX = '__sl_ga__';\nexport const MAX_GA_CAPACITY = 100_000;\nexport const MAX_EVENT_INVENTORY = 100_000;\n\n/** Stable internal inventory label for one unit of a GA area's capacity. */\nexport function gaUnitLabel(areaId: string, index: number): string {\n return `${PREFIX}${encodeURIComponent(areaId)}__${index + 1}`;\n}\n\nexport function gaUnitLabels(area: GAAreaObject): string[] {\n const capacity = Math.min(MAX_GA_CAPACITY, Math.max(0, Math.floor(area.capacity)));\n return Array.from({ length: capacity }, (_, i) => gaUnitLabel(area.id, i));\n}\n\nexport function gaAreasOf(doc: ChartDoc): GAAreaObject[] {\n return allObjects(doc).filter((o): o is GAAreaObject => o.type === 'gaArea');\n}\n\nexport function isGaUnitLabel(label: string): boolean {\n return label.startsWith(PREFIX);\n}\n","/**\n * Section membership + hide/show resolution (Batch 3.3).\n *\n * A `SectionObject` is a polygon drawn over existing seat objects; an object\n * \"belongs\" to a section when its visual centre (`objectCenter`) falls inside\n * the section outline, first section in doc order winning. This is the same\n * spatial notion `objectCenter`'s doc-comment describes, resolved once here so\n * BOTH the event manager (Sections tab counts) and the buyer picker (omit\n * hidden seats) agree on which seats live in which section.\n *\n * Hiding is per-EVENT (the EventDO holds the hidden id set), not a chart edit —\n * so a republish of the chart never disturbs it. A hidden id may be a section\n * id, a zone id (hides every section in the zone), or `UNGROUPED_ID` (the\n * catch-all bucket of seat objects that sit in no section).\n */\nimport type { ChartDoc, ChartObject, SectionObject } from './types';\nimport { allObjects, expandBooth, expandRow, expandTable, objectCenter, pointInPolygon } from './layout';\nimport { gaUnitLabels } from './ga';\n\n/** Synthetic section id for seat objects that fall in no drawn section. */\nexport const UNGROUPED_ID = '__ungrouped__';\n\n/**\n * A per section/zone availability window (Batch 3.4). Wire-compatible with the\n * EventDO's own `AvailabilityRule`. Absence of a rule for an id = on sale.\n * 'hidden' — manual: hidden until the organizer reveals it (3.3).\n * 'timed' — hidden until `revealAt` (epoch ms), then auto-reveals.\n * 'threshold' — auto-reveals once the on-sale inventory is `thresholdPct`% sold.\n * 'closed' — visible to buyers but not purchasable (rendered flat grey);\n * unlike 'hidden', the seats stay on the map, just off sale.\n * `labels` are the seat labels the id governs, so a threshold's denominator can\n * exclude still-hidden seats.\n */\nexport interface AvailabilityRule {\n mode: 'hidden' | 'timed' | 'threshold' | 'closed';\n revealAt?: number;\n thresholdPct?: number;\n labels?: string[];\n}\n\nexport interface SectionNode {\n /** Section id (a `SectionObject.id`, or `UNGROUPED_ID`). */\n id: string;\n label: string;\n /** Zone id this section points at (`SectionObject.zone`), if any. */\n zone?: string;\n /** Total seats across the member objects. */\n seatCount: number;\n /** Ids of the seat-bearing objects that belong to this section. */\n objectIds: string[];\n /** Seat labels across the member objects (for availability-rule denominators). */\n seatLabels: string[];\n}\n\n/** Seat labels produced by one seat-bearing object (rows/tables/booths); [] otherwise. */\nfunction objectSeatLabels(o: ChartObject): string[] {\n if (o.type === 'row') return expandRow(o).map((s) => s.label);\n if (o.type === 'table') return expandTable(o).map((s) => s.label);\n if (o.type === 'booth') return expandBooth(o).map((s) => s.label);\n if (o.type === 'gaArea') return gaUnitLabels(o);\n return [];\n}\n\nfunction isSeatObject(o: ChartObject): boolean {\n return o.type === 'row' || o.type === 'table' || o.type === 'booth' || o.type === 'gaArea';\n}\n\n/**\n * Resolve section membership for a chart. Returns one node per drawn section\n * (doc order), a synthetic \"Ungrouped\" node for loose seat objects (null when\n * every seat sits in a section), and the object→section id map.\n */\nexport function computeSections(doc: ChartDoc): {\n sections: SectionNode[];\n ungrouped: SectionNode | null;\n /** seat-object id → owning section id (or `UNGROUPED_ID`). */\n objectToSection: Map<string, string>;\n} {\n // Span all floors (Batch 5) — a multi-floor chart's sections live in floors[];\n // single-floor charts fall through to doc.objects. Section ids are chart-unique.\n const objs = allObjects(doc);\n const sectionObjs = objs.filter((o): o is SectionObject => o.type === 'section');\n const nodes = new Map<string, SectionNode>();\n for (const s of sectionObjs) {\n nodes.set(s.id, { id: s.id, label: s.label || 'Section', zone: s.zone, seatCount: 0, objectIds: [], seatLabels: [] });\n }\n const ungrouped: SectionNode = { id: UNGROUPED_ID, label: 'Other seats', seatCount: 0, objectIds: [], seatLabels: [] };\n const objectToSection = new Map<string, string>();\n\n for (const obj of objs) {\n if (!isSeatObject(obj)) continue;\n const labels = objectSeatLabels(obj);\n if (labels.length === 0) continue;\n const c = objectCenter(obj);\n // First drawn section (doc order) whose outline contains the object centre.\n const owner = sectionObjs.find((s) => pointInPolygon(c, s.outline));\n const node = owner ? nodes.get(owner.id)! : ungrouped;\n node.seatCount += labels.length;\n node.objectIds.push(obj.id);\n node.seatLabels.push(...labels);\n objectToSection.set(obj.id, node.id);\n }\n\n return {\n sections: sectionObjs.map((s) => nodes.get(s.id)!),\n ungrouped: ungrouped.objectIds.length ? ungrouped : null,\n objectToSection,\n };\n}\n\n/** Is a drawn section hidden under `hidden` — directly, or via its zone? */\nexport function isSectionHidden(s: SectionObject, hidden: ReadonlySet<string>): boolean {\n return hidden.has(s.id) || (!!s.zone && hidden.has(s.zone));\n}\n\n/**\n * The set of seat-object ids to omit from the buyer view for a given hidden id\n * set. An object is hidden when its owning section is hidden (directly or via\n * zone), or it is ungrouped and the catch-all bucket is hidden.\n */\nexport function hiddenObjectIds(doc: ChartDoc, hidden: ReadonlySet<string>): Set<string> {\n const out = new Set<string>();\n if (!hidden.size) return out;\n const { sections, ungrouped, objectToSection } = computeSections(doc);\n const hiddenSectionIds = new Set<string>();\n const zoneById = new Map(sections.map((s) => [s.id, s.zone] as const));\n for (const s of sections) {\n const zone = zoneById.get(s.id);\n if (hidden.has(s.id) || (zone && hidden.has(zone))) hiddenSectionIds.add(s.id);\n }\n const ungroupedHidden = !!ungrouped && hidden.has(UNGROUPED_ID);\n for (const [objId, secId] of objectToSection) {\n if (hiddenSectionIds.has(secId) || (ungroupedHidden && secId === UNGROUPED_ID)) out.add(objId);\n }\n return out;\n}\n\n/**\n * A copy of the doc with hidden sections' member objects removed, plus the\n * hidden section overlays themselves (so no empty block renders). Returns the\n * SAME reference when nothing is hidden — callers can skip a re-render on `===`.\n */\nexport function applyHidden(doc: ChartDoc, hidden: ReadonlySet<string>): ChartDoc {\n if (!hidden.size) return doc;\n const hide = hiddenObjectIds(doc, hidden);\n const hiddenSet = hidden instanceof Set ? hidden : new Set(hidden);\n const keep = (o: ChartObject): boolean => {\n if (hide.has(o.id)) return false;\n if (o.type === 'section' && isSectionHidden(o, hiddenSet)) return false;\n return true;\n };\n // Multi-floor (Batch 5): filter each floor + the floor-0 mirror.\n if (doc.floors && doc.floors.length) {\n let changed = false;\n const floors = doc.floors.map((f) => {\n const objects = f.objects.filter(keep);\n if (objects.length !== f.objects.length) changed = true;\n return objects.length === f.objects.length ? f : { ...f, objects };\n });\n if (!changed) return doc;\n return { ...doc, floors, objects: floors[0].objects };\n }\n const objects = doc.objects.filter(keep);\n if (objects.length === doc.objects.length) return doc;\n return { ...doc, objects };\n}\n","/**\n * SeatmapRenderer — the shared canvas rendering core (buyer picker shell).\n *\n * Uses Konva directly with per-module imports to keep the bundle lean. The\n * whole point of the spike is staying smooth at ~5,000 seats on mobile, so the\n * hot paths lean on: layer bitmap caching + listening(false) when zoomed out,\n * per-seat fill updates (never full rebuilds) on status change, and viewport-\n * only label rendering rebuilt on interaction-end rather than per frame.\n */\n\n// Core (not Global): Core assembles the real Konva namespace — Global alone\n// lacks DD/Util and Stage._pointermove dereferences Konva.DD unconditionally.\nimport { Konva } from 'konva/lib/Core';\nimport { Stage } from 'konva/lib/Stage';\nimport { Layer } from 'konva/lib/Layer';\nimport { Group } from 'konva/lib/Group';\nimport { Circle } from 'konva/lib/shapes/Circle';\nimport { Rect } from 'konva/lib/shapes/Rect';\nimport { Ellipse } from 'konva/lib/shapes/Ellipse';\nimport { Line } from 'konva/lib/shapes/Line';\nimport { Text } from 'konva/lib/shapes/Text';\nimport { Image as KImage } from 'konva/lib/shapes/Image';\nimport type { KonvaEventObject } from 'konva/lib/Node';\nimport type { Shape } from 'konva/lib/Shape';\n\nimport type {\n AccessibilityType,\n ChartDoc,\n ChartTheme,\n ExpandedSeat,\n ISeatmapRenderer,\n LodRung,\n Point,\n RendererOptions,\n SeatStatus,\n SectionObject,\n} from '../core/types';\nimport { chartBounds, expandChart, floorsOf, pointInPolygon, stackFloors } from '../core/layout';\nimport { t } from '../i18n';\nimport { formatMoney } from '../lib/money';\n\nconst SEAT_RADIUS = 9;\n/** Absolute scale at which a seat (r=9) renders ~legibly (~8px). */\nconst SEAT_LEGIBLE_SCALE = 0.9;\n/** Below this absolute scale we swap seats for a cached bitmap. */\nconst CACHE_THRESHOLD = 0.55 * SEAT_LEGIBLE_SCALE;\n/** Show per-seat labels above this ABSOLUTE scale (seat ⌀ ≈ 18px) — chart-size independent. */\nconst LABEL_SCALE = 1.0;\n/** Extra screen-px of slack around a seat circle that still counts as a tap on\n * it. Gives small seats a finger-friendly hit target (§4 \"hit ≥ 24px\") so a\n * near-miss on mobile still selects the nearest seat instead of doing nothing. */\nconst SEAT_TAP_SLOP_PX = 14;\n/**\n * At/below this scale, sections read as solid BLOCKS with row-line hints (seats\n * fully hidden) — the seats.io-style default overview.\n */\nconst SECTION_PROMINENT_SCALE = 0.45 * SEAT_LEGIBLE_SCALE;\n/**\n * Above this scale, seats are fully shown (dots); between here and\n * SECTION_PROMINENT the block melts in. Set high so a big sectioned chart OPENS\n * as named blocks and only reveals seats once you zoom in close.\n */\nconst BLOCK_MELT_TOP = 0.9 * SEAT_LEGIBLE_SCALE;\n/** Camera scale used after a section drill-in. Keeping this above the block\n * melt band guarantees that a section tap lands on live, legible seats even\n * when a narrow phone viewport cannot frame the whole section at that scale. */\nconst SEAT_FOCUS_SCALE = Math.max(SEAT_LEGIBLE_SCALE * 1.1, BLOCK_MELT_TOP);\n/** Ignore normal finger jitter before treating a tap as a map pan. */\nconst PAN_START_SLOP_PX = 8;\n/**\n * Below this scale, ZONE blocks/labels take over from per-section detail (the\n * farthest rung). ~0.55× the section rung so: seats → section blocks → zones.\n */\nconst ZONE_PROMINENT_SCALE = 0.55 * SECTION_PROMINENT_SCALE;\n/** Never label more than this many seats at once (viewport clutter guard). */\nconst MAX_LABELS = 700;\n/**\n * Manage-mode marquee: above this many selected seats we stop drawing per-seat\n * selection-ring nodes (they'd be an invisible speck at that zoom and a huge\n * node count on a 13k arena) and rely on the seat-fill selection paint instead.\n * Selection membership (getSelection / bulk block) is unaffected.\n */\nconst MARQUEE_RING_CAP = 2500;\n\n// ---- Isometric (\"3D\") view mode -------------------------------------------\n/** Full-iso rotation of the chart about its centre (degrees). */\nconst ISO_ANGLE_DEG = -11.5;\n/** Full-iso vertical squash (1 = flat). */\nconst ISO_SQUASH = 0.58;\n/** World units a section (and its members) lift per elevation step at full iso. */\nconst LIFT_PER_STEP = 58;\n/** Flat⇄iso tween duration (ms); reduced-motion snaps. */\nconst ISO_TWEEN_MS = 320;\n\n// ---- Section/zone LOD (\"melt\") tuning -------------------------------------\n/** Peak fill opacity of a solid section block at the block rung. */\nconst BLOCK_FILL_ALPHA = 0.85;\n/** How far a fully-sold section's fill darkens toward black. */\nconst SOLD_DARKEN = 0.5;\n/** Screen-space target sizes (px) for scale-compensated section/zone labels. */\nconst SECTION_LABEL_PX = 20;\nconst SECTION_SUB_PX = 12.5;\nconst ZONE_LABEL_PX = 30;\nconst ZONE_SUB_PX = 12;\n\nconst HELD_FILL = '#6b7280';\nconst TAKEN_FILL = '#374151';\nconst NFS_STROKE = '#4b5563';\n/** Phase 2 event-level `closed` section: a flat desaturated slate block (label\n * kept), distinct from the per-seat availability-grey. Seats inside read grey\n * at 40% and are not pickable (per chart-design-standards §3). */\nconst CLOSED_SECTION_FILL = '#586070';\nconst CLOSED_SEAT_FILL = '#4b5563';\nconst CLOSED_SEAT_OPACITY = 0.4;\n/** AXS section-focus: non-focused sections dim to this opacity + desaturate. */\nconst FOCUS_DIM_OPACITY = 0.16;\nconst FOCUS_DESATURATE = 0.72; // lerp non-focused fills toward neutral grey\nconst FOCUS_NEUTRAL = '#6b7280';\n/** Light/neutral backdrop panel drawn behind the focused section's seats. */\nconst FOCUS_BACKDROP_FILL = 'rgba(244,246,248,0.06)';\n/** Okabe-Ito colorblind-safe hues (black dropped — unreadable on dark charts).\n * Categories map to these by their doc order when colorblind mode is on. */\nconst CB_PALETTE = ['#E69F00', '#56B4E9', '#009E73', '#F0E442', '#0072B2', '#D55E00', '#CC79A7'];\n\n/** Outer-ring colour per accommodation (a seat's first-listed type wins). */\nconst ACCESS_RING: Record<AccessibilityType, string> = {\n wheelchair: '#3b82f6',\n companion: '#8b5cf6',\n 'semi-ambulatory': '#0ea5e9',\n hearing: '#14b8a6',\n 'sign-language': '#f59e0b',\n 'plus-size': '#ec4899',\n 'lift-armrest': '#22c55e',\n};\n\n/** Does a seat satisfy a filter? `[]` means \"any accessible seat\". */\nfunction seatMatchesAccess(seat: ExpandedSeat, filter: AccessibilityType[]): boolean {\n if (filter.length === 0) return !!seat.accessible;\n return !!seat.accessibility?.some((t) => filter.includes(t));\n}\n\n// Theme fallbacks (dark defaults) — used when doc.theme leaves a slot unset.\nconst DEF_SEAT_LABEL = '#0b1220';\nconst DEF_SELECTION = '#ffffff';\n/** Selection/hover ring on LIGHT canvases — a white ring vanishes there. */\nconst DEF_SELECTION_ON_LIGHT = '#0b1220';\nconst DEF_DECOR_FILL = '#232c40';\nconst DEF_TEXT = '#8b93a7';\n\n/**\n * Relative luminance (0..1) of a CSS color — supports #rgb, #rrggbb and\n * rgb()/rgba(). Returns NaN for anything unparseable (gradients, ''), which\n * callers must treat as \"unknown → assume dark\" to preserve dark defaults.\n */\nfunction colorLuminance(color: string): number {\n const s = color.trim();\n let r = NaN;\n let g = NaN;\n let b = NaN;\n const hex = /^#([\\da-f]{3}|[\\da-f]{6})$/i.exec(s);\n if (hex) {\n const h = hex[1].length === 3 ? hex[1].split('').map((c) => c + c).join('') : hex[1];\n r = parseInt(h.slice(0, 2), 16);\n g = parseInt(h.slice(2, 4), 16);\n b = parseInt(h.slice(4, 6), 16);\n } else {\n const rgb = /^rgba?\\(\\s*(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*(\\d+)/.exec(s);\n if (rgb) {\n r = +rgb[1];\n g = +rgb[2];\n b = +rgb[3];\n }\n }\n if (Number.isNaN(r)) return NaN;\n return (0.2126 * r + 0.7152 * g + 0.0722 * b) / 255;\n}\n\n/** Light enough that white UI accents (selection ring) lose contrast. */\nfunction isLightColor(color: string): boolean {\n const lum = colorLuminance(color);\n return !Number.isNaN(lum) && lum > 0.6;\n}\n\nconst clamp = (v: number, lo: number, hi: number) => Math.max(lo, Math.min(hi, v));\n\n/** Read a custom attr off an event target (Stage | Shape union isn't callable directly). */\nfunction seatIdOf(target: unknown): string | undefined {\n const n = target as { getAttr?: (k: string) => unknown } | null;\n return (n?.getAttr?.('seatId') as string | undefined) ?? undefined;\n}\n\n/** Mix a #rrggbb colour toward white by `amt` (0..1). */\nfunction lighten(hex: string, amt: number): string {\n const m = /^#?([\\da-f]{6})$/i.exec(hex.trim());\n if (!m) return hex;\n const n = parseInt(m[1], 16);\n const r = (n >> 16) & 255;\n const g = (n >> 8) & 255;\n const b = n & 255;\n const mix = (c: number) => Math.round(c + (255 - c) * amt);\n return `#${((1 << 24) | (mix(r) << 16) | (mix(g) << 8) | mix(b)).toString(16).slice(1)}`;\n}\n\n/** Mix a #rrggbb colour toward black by `amt` (0..1). */\nfunction darken(hex: string, amt: number): string {\n const m = /^#?([\\da-f]{6})$/i.exec(hex.trim());\n if (!m) return hex;\n const n = parseInt(m[1], 16);\n const mix = (c: number) => Math.round(c * (1 - amt));\n return `#${((1 << 24) | (mix((n >> 16) & 255) << 16) | (mix((n >> 8) & 255) << 8) | mix(n & 255)).toString(16).slice(1)}`;\n}\n\n/** Axis-aligned bounds of a polygon (no padding). */\nfunction polyBounds(pts: Point[]): { x: number; y: number; width: number; height: number } {\n let minX = Infinity;\n let minY = Infinity;\n let maxX = -Infinity;\n let maxY = -Infinity;\n for (const p of pts) {\n if (p.x < minX) minX = p.x;\n if (p.y < minY) minY = p.y;\n if (p.x > maxX) maxX = p.x;\n if (p.y > maxY) maxY = p.y;\n }\n return { x: minX, y: minY, width: Math.max(1, maxX - minX), height: Math.max(1, maxY - minY) };\n}\n\n/** #rrggbb → rgba() string at alpha `a`; passes non-hex through unchanged. */\nfunction rgba(hex: string, a: number): string {\n const m = /^#?([\\da-f]{6})$/i.exec(hex.trim());\n if (!m) return hex;\n const n = parseInt(m[1], 16);\n return `rgba(${(n >> 16) & 255},${(n >> 8) & 255},${n & 255},${a})`;\n}\n\n/** Parse #rrggbb → [r,g,b] (0..255); null for non-hex. */\nfunction hexToRgb(hex: string): [number, number, number] | null {\n const m = /^#?([\\da-f]{6})$/i.exec(hex.trim());\n if (!m) return null;\n const n = parseInt(m[1], 16);\n return [(n >> 16) & 255, (n >> 8) & 255, n & 255];\n}\n\nconst toHex = (r: number, g: number, b: number): string =>\n `#${((1 << 24) | (Math.round(r) << 16) | (Math.round(g) << 8) | Math.round(b)).toString(16).slice(1)}`;\n\n/**\n * Count-weighted RGB blend of member seat colours — a section reads as its\n * price makeup, not one flat colour. Falls back to `fallback` when empty.\n */\nfunction mixColors(parts: Array<{ hex: string; w: number }>, fallback: string): string {\n let r = 0;\n let g = 0;\n let b = 0;\n let tw = 0;\n for (const p of parts) {\n const rgb = hexToRgb(p.hex);\n if (!rgb || p.w <= 0) continue;\n r += rgb[0] * p.w;\n g += rgb[1] * p.w;\n b += rgb[2] * p.w;\n tw += p.w;\n }\n return tw > 0 ? toHex(r / tw, g / tw, b / tw) : fallback;\n}\n\n/** Linear interpolate between two #rrggbb colours (t 0..1); passes `a` through if unparseable. */\nfunction lerpColor(a: string, b: string, t: number): string {\n const ca = hexToRgb(a);\n const cb = hexToRgb(b);\n if (!ca || !cb) return a;\n return toHex(ca[0] + (cb[0] - ca[0]) * t, ca[1] + (cb[1] - ca[1]) * t, ca[2] + (cb[2] - ca[2]) * t);\n}\n\n/** Per-section render state for the block LOD rung (fills, labels, membership). */\ninterface SectionRender {\n id: string;\n label: string;\n outline: Point[];\n centroid: Point;\n zone?: string;\n /** Seats whose centre falls inside the outline (first-match, doc order). */\n memberIds: string[];\n total: number;\n free: number;\n /** Category-mix (or explicit override) fill BEFORE the availability tint. */\n baseFill: string;\n outlineTint: string;\n /** Faint outline drawn under seats — the existing near-zoom look, untouched. */\n outlinePoly: Line;\n /** Solid block fill that melts in at the block rung. */\n blockPoly: Line;\n /** Faint per-row hint lines drawn inside the block (the seats.io \"rows\" look). */\n rowLines: Line[];\n /** Section name (always drawn; brightens at the block rung, hides at zone rung). */\n nameLabel: Text;\n /** Mono \"N LEFT\" availability sublabel (block rung only). */\n subLabel: Text;\n /** Tier height (0 = floor). Lifts the section + members in iso (\"3D\") view. */\n elevation: number;\n /**\n * When elevation > 0, the section's bg nodes + member seats live in these\n * groups so a single position offset lifts the whole tier in iso view.\n */\n liftGroupBg: Group | null;\n liftGroupSeat: Group | null;\n /** Extruded side faces (one per outline edge) shown only as isoT rises. */\n sideFaces: Line[];\n}\n\n/** Per-zone render state for the farthest LOD rung. */\ninterface ZoneRender {\n id: string;\n label: Text;\n sub: Text | null;\n}\n\nexport class SeatmapRenderer implements ISeatmapRenderer {\n private container: HTMLDivElement;\n private opts: Required<Pick<RendererOptions, 'maxSelection'>> & RendererOptions;\n\n private stage: Stage;\n private bgLayer: Layer;\n private seatLayer: Layer;\n private overlayLayer: Layer;\n private labelGroup: Group;\n\n private seats: ExpandedSeat[] = [];\n private seatById = new Map<string, ExpandedSeat>();\n /** Multi-floor (Batch 5): the last-set chart + which floor we're rendering. */\n private chartDoc: ChartDoc | null = null;\n private activeFloorId = '';\n /** When true on a multi-floor chart, render ALL floors stacked (3D overview). */\n private stacked = false;\n /** Interactive node per seat/booth — a Circle for seats, a Rect for booths. */\n private circleById = new Map<string, Shape>();\n /** Booth block geometry, keyed by booth id (= the unit's rowId). */\n private boothDims = new Map<string, { width: number; height: number; rotation: number }>();\n /** Booth label node so status changes can say HELD/SOLD on the full block. */\n private boothLabelById = new Map<string, Text>();\n private statusById = new Map<string, SeatStatus>();\n private catColor = new Map<string, string>();\n private theme: ChartTheme = {};\n /** Effective selection/hover ring color — resolved per chart in setChart(). */\n private effSelection: string = DEF_SELECTION;\n /** Colorblind-safe mode (Okabe-Ito hues + hollow booked seats). */\n private colorblind = false;\n /** Category order from the doc — the stable index into the CB palette. */\n private catOrder: string[] = [];\n\n private selection = new Set<string>();\n /** Whole-seat/block selection markers: outline + non-colour check cue. */\n private selectionMarkers = new Map<string, Group>();\n /** Held by this picker instance, not by another buyer. */\n private ownedHold = new Set<string>();\n /** One selected seat being inspected before it is committed to the cart. */\n private selectionFocusId: string | null = null;\n private hoverRing: Circle;\n /** Keyboard-navigation focus ring + the currently focused seat id. */\n private focusRing: Circle;\n private focusedId: string | null = null;\n /**\n * Accessibility filter: `null` = off; `[]` = dim all non-accessible free seats;\n * a type list = dim free seats lacking any of those accommodations.\n */\n private accessFilter: AccessibilityType[] | null = null;\n /** Category highlight (legend hover): dims free seats NOT of this category. */\n private categoryHighlight: string | null = null;\n /** Price-band filter (F4): dim free seats whose category is NOT in this set. */\n private categoryFilter: Set<string> | null = null;\n\n // Section/zone overlays (bgLayer) — the 3-rung LOD: seats → section blocks →\n // zone blocks. Kept for the melt restyle and for hit-testing a zoomed-out tap.\n private sections: SectionRender[] = [];\n private zones: ZoneRender[] = [];\n private seatSection = new Map<string, SectionRender>();\n private catPrice = new Map<string, number>();\n /** ISO 4217 currency for on-map \"FROM …\" prices (undefined ⇒ money default). */\n private currency: string | undefined;\n /** Section/zone ids to render dimmed (organizer manager: held-back inventory). */\n private dimmedSections = new Set<string>();\n /** Organizer control-room velocity overlay; absent on buyer surfaces. */\n private sectionHeat = new Map<string, number>();\n /** Phase 2: section/zone ids in the event-level `closed` state — flat grey\n * block, seats greyed + not pickable, but the section stays rendered. */\n private closedSections = new Set<string>();\n /** AXS section-focus: the currently-focused section id (others dim), or null. */\n private focusedSectionId: string | null = null;\n /** Light backdrop panel drawn behind the focused section (removed on clear). */\n private focusBackdrop: Line | null = null;\n /** Object id → floor id (multi-floor only) — resolves a deck tap in the 3D stack. */\n private objectFloor = new Map<string, string>();\n /** Zone id → colour (drives extruded side faces in iso view). */\n private zoneColor = new Map<string, string>();\n private hasSections = false;\n /** seatLayer carries Text (booth labels) — gate the upright-label scan. */\n private hasBoothText = false;\n\n // Isometric (\"3D\") view — an affine skew/rotate + elevation lift, tweened.\n /** 0 = flat (default), 1 = full isometric; animated by setViewMode. */\n private isoT = 0;\n private isoTarget = 0;\n private isoRaf = 0;\n /** Chart centre the iso projection pivots about (bounds centre). */\n private isoCentre = { x: 0, y: 0 };\n /** rAF for an in-flight camera glide (focusRegion / setRung); 0 = none. */\n private glideRaf = 0;\n /** Set in destroy() so an in-flight iso tween bails. */\n private destroyed = false;\n /** Cached scale the section/zone labels were last sized for (scale-compensation). */\n private lodScale = 0;\n /** prefers-reduced-motion → hard-swap rungs instead of cross-fading. */\n private reducedMotion =\n typeof window !== 'undefined' &&\n typeof window.matchMedia === 'function' &&\n window.matchMedia('(prefers-reduced-motion: reduce)').matches;\n\n private fitScale = 1;\n /** Effective seat radius (base × theme.seatScale), set per chart in setChart. */\n private seatR = SEAT_RADIUS;\n private bounds = { x: 0, y: 0, width: 1, height: 1 };\n private cached = false;\n private dpr = Math.min(typeof window !== 'undefined' ? window.devicePixelRatio || 1 : 1, 2);\n\n private rafId = 0;\n private frames = 0;\n private lastFpsAt = 0;\n private recacheTimer: ReturnType<typeof setTimeout> | null = null;\n private resizeObs: ResizeObserver | null = null;\n /** Coalesces bursty view-change sources (pointermove, wheel) into ≤1 callback/frame. */\n private viewChangeRaf = 0;\n\n // Gesture state — pan/pinch are handled with raw pointer events on the\n // container (Konva stage dragging is off; its touch pipeline proved\n // unreliable for multi-touch on real devices).\n private pointers = new Map<number, { x: number; y: number }>();\n private pinch: { startDist: number; startScale: number; worldMid: { x: number; y: number } } | null = null;\n private panLast: { x: number; y: number } | null = null;\n private panStart: { x: number; y: number } | null = null;\n private panStarted = false;\n /** Maximum displacement from gesture start — suppress taps only after a real pan/pinch. */\n private moved = 0;\n /**\n * Manage-mode rubber-band marquee (option-gated). `start`/`cur` are WORLD-space\n * points (overlayLayer rides the stage transform); `rect` is the on-canvas\n * selection band. Null except during an active manage-mode drag.\n */\n private marquee: { start: { x: number; y: number }; rect: Rect } | null = null;\n private marqueeCur: { x: number; y: number } | null = null;\n\n constructor(container: HTMLDivElement, options: RendererOptions = {}) {\n this.container = container;\n this.opts = { maxSelection: 10, selectableStatuses: ['free'], ...options };\n this.currency = options.currency;\n\n Konva.pixelRatio = this.dpr;\n\n this.stage = new Stage({\n container,\n width: container.clientWidth || 1,\n height: container.clientHeight || 1,\n draggable: false, // pan/pinch are ours, via pointer events\n });\n\n container.style.touchAction = 'none';\n container.addEventListener('pointerdown', this.onPointerDown, { passive: false });\n container.addEventListener('pointermove', this.onPointerMove, { passive: false });\n container.addEventListener('pointerup', this.onPointerEnd, { passive: false });\n container.addEventListener('pointercancel', this.onPointerEnd, { passive: false });\n\n // Keyboard accessibility: the canvas is focusable and navigable seat-by-seat.\n if (container.tabIndex < 0) container.tabIndex = 0;\n container.setAttribute('role', 'application');\n if (!container.getAttribute('aria-label')) {\n container.setAttribute('aria-label', t('map.aria'));\n }\n container.addEventListener('keydown', this.onKeyDown);\n\n this.bgLayer = new Layer({ listening: true });\n this.seatLayer = new Layer({ listening: true });\n this.overlayLayer = new Layer({ listening: false });\n this.labelGroup = new Group({ listening: false });\n this.overlayLayer.add(this.labelGroup);\n\n this.hoverRing = new Circle({\n radius: SEAT_RADIUS + 2,\n stroke: '#ffffff',\n strokeWidth: 2,\n opacity: 0.85,\n listening: false,\n visible: false,\n perfectDrawEnabled: false,\n shadowForStrokeEnabled: false,\n });\n this.overlayLayer.add(this.hoverRing);\n\n this.focusRing = new Circle({\n radius: SEAT_RADIUS + 3,\n stroke: '#38bdf8',\n strokeWidth: 2.5,\n dash: [4, 3],\n opacity: 0.95,\n listening: false,\n visible: false,\n perfectDrawEnabled: false,\n shadowForStrokeEnabled: false,\n });\n this.overlayLayer.add(this.focusRing);\n\n this.stage.add(this.bgLayer, this.seatLayer, this.overlayLayer);\n\n this.wireInteraction();\n this.startFpsLoop();\n\n if (import.meta.env.DEV) {\n (window as unknown as Record<string, unknown>).__seatmap = this;\n }\n\n if (typeof ResizeObserver !== 'undefined') {\n this.resizeObs = new ResizeObserver(() => this.handleResize());\n this.resizeObs.observe(container);\n }\n }\n\n // ---- ISeatmapRenderer -----------------------------------------------------\n\n setChart(doc: ChartDoc, opts?: { floorId?: string }): void {\n // Multi-floor: render the active floor (2D) or all floors stacked (3D). `view`\n // scopes the chart accordingly — single-floor charts pass through (=== doc).\n // A fresh chart (new ref) resets to 2D; a re-render (same ref) preserves the mode.\n if (doc !== this.chartDoc) this.stacked = false;\n this.chartDoc = doc;\n this.activeFloorId = opts?.floorId ?? floorsOf(doc)[0].id;\n // Object id → floor id, for resolving which deck a tap hit in the 3D stack\n // (stackFloors keeps object ids, so the map holds across the flatten).\n this.objectFloor.clear();\n if (doc.floors && doc.floors.length > 1) {\n for (const f of doc.floors) for (const o of f.objects) this.objectFloor.set(o.id, f.id);\n }\n const view = this.floorView(doc);\n this.focusedId = null;\n this.focusRing.visible(false);\n this.bgLayer.destroyChildren();\n this.seatLayer.destroyChildren();\n this.labelGroup.destroyChildren();\n this.circleById.clear();\n this.boothDims.clear();\n this.boothLabelById.clear();\n this.selectionMarkers.clear();\n this.ownedHold.clear();\n this.selectionFocusId = null;\n this.statusById.clear();\n this.selection.clear();\n this.seatById.clear();\n this.cached = false;\n this.accessFilter = null;\n this.sections = [];\n this.zones = [];\n this.seatSection.clear();\n this.catPrice.clear();\n this.zoneColor.clear();\n this.lodScale = 0;\n this.hasBoothText = false;\n // Reloading the chart resets the view to flat (identity layer transforms).\n if (this.isoRaf) { cancelAnimationFrame(this.isoRaf); this.isoRaf = 0; }\n this.isoT = 0;\n this.isoTarget = 0;\n this.resetLayerTransforms();\n this.hasSections = view.objects.some((o) => o.type === 'section');\n for (const z of doc.zones ?? []) if (z.color) this.zoneColor.set(z.id, z.color);\n // Seats fade against the block fill during the melt; reset to fully opaque.\n this.seatLayer.opacity(1);\n this.hoverRing.visible(false);\n\n this.theme = doc.theme ?? {};\n // Adjustable seat size: a chart-level scale on the base radius. Clamped so\n // enlarged seats don't collide with typical row spacing (~24 units).\n this.seatR = clamp(this.theme.seatScale ?? 1, 0.7, 1.6) * SEAT_RADIUS;\n // Canvas background via container style (reset to '' when theme omits it).\n this.container.style.background = this.theme.background ?? '';\n this.effSelection = this.resolveSelectionColor();\n this.hoverRing.stroke(this.effSelection);\n this.hoverRing.radius(this.seatR + 2);\n\n this.catColor.clear();\n this.catPrice.clear();\n this.catOrder = doc.categories.map((c) => c.key);\n for (const c of doc.categories) {\n this.catColor.set(c.key, c.color);\n if (typeof c.price === 'number') this.catPrice.set(c.key, c.price);\n }\n\n for (const obj of view.objects) {\n if (obj.type === 'booth') {\n this.boothDims.set(obj.id, { width: obj.width, height: obj.height, rotation: obj.rotation });\n }\n }\n\n this.seats = expandChart(view);\n for (const s of this.seats) {\n this.seatById.set(s.id, s);\n this.statusById.set(s.id, 'free');\n }\n\n this.renderBackground(view);\n this.renderSeats();\n // re-add overlay furniture wiped by destroyChildren above\n this.overlayLayer.add(this.labelGroup);\n this.overlayLayer.add(this.hoverRing);\n\n this.bounds = chartBounds(view);\n this.isoCentre = { x: this.bounds.x + this.bounds.width / 2, y: this.bounds.y + this.bounds.height / 2 };\n this.zoomToFit();\n }\n\n /** The chart to render: all floors stacked (3D overview), the active floor, or\n * the whole chart for single-floor charts. */\n private floorView(doc: ChartDoc): ChartDoc {\n if (!doc.floors || !doc.floors.length) return doc;\n if (this.stacked && doc.floors.length >= 2) return stackFloors(doc);\n const floor = doc.floors.find((f) => f.id === this.activeFloorId) ?? doc.floors[0];\n return { ...doc, objects: floor.objects, focalPoint: floor.focalPoint, backgroundImage: floor.backgroundImage, floors: undefined };\n }\n\n /** Toggle the 3D all-floors stacked overview (Batch 5). Re-renders; no-op on\n * single-floor charts. The caller re-applies statuses + animates the iso view. */\n setStacked(on: boolean): void {\n if (!this.chartDoc || on === this.stacked) return;\n const multi = !!this.chartDoc.floors && this.chartDoc.floors.length >= 2;\n if (!multi) return;\n this.stacked = on;\n this.setChart(this.chartDoc, { floorId: this.activeFloorId });\n }\n isStacked(): boolean {\n return this.stacked;\n }\n\n /** Switch which floor is shown (2D). Re-renders + re-fits; no-op if unchanged. */\n setActiveFloor(floorId: string): void {\n if (!this.chartDoc || floorId === this.activeFloorId) return;\n this.setChart(this.chartDoc, { floorId });\n }\n\n /** Floors for the host's switcher (single-floor charts return one synthetic floor). */\n getFloors(): { id: string; name: string }[] {\n return this.chartDoc ? floorsOf(this.chartDoc).map((f) => ({ id: f.id, name: f.name })) : [];\n }\n\n getActiveFloorId(): string {\n return this.activeFloorId;\n }\n\n setStatus(seatIds: string[], status: SeatStatus): void {\n let touched = false;\n // Sections whose availability tint / \"N LEFT\" needs a cheap recompute.\n const affected = this.hasSections ? new Set<SectionRender>() : null;\n for (const id of seatIds) {\n if (!this.statusById.has(id)) continue;\n const prev = this.statusById.get(id);\n this.statusById.set(id, status);\n const c = this.circleById.get(id);\n if (c) {\n this.paintSeat(c, id);\n touched = true;\n }\n if (affected) {\n const sec = this.seatSection.get(id);\n if (sec) {\n if ((prev === 'free') !== (status === 'free')) {\n sec.free += status === 'free' ? 1 : -1;\n }\n affected.add(sec);\n }\n }\n }\n if (affected && affected.size) {\n for (const sec of affected) this.refreshSectionFill(sec);\n this.bgLayer.batchDraw();\n }\n if (!touched) return;\n if (this.cached) {\n // bitmap is stale; debounce a re-cache so bulk updates coalesce\n if (this.recacheTimer) clearTimeout(this.recacheTimer);\n this.recacheTimer = setTimeout(() => this.cacheSeatLayer(), 150);\n } else {\n this.seatLayer.batchDraw();\n }\n if (this.effScale() > LABEL_SCALE) this.updateLabels();\n }\n\n setOwnedHold(seatIds: string[] | null): void {\n const next = new Set((seatIds ?? []).filter((id) => this.statusById.has(id)));\n const touched = new Set([...this.ownedHold, ...next]);\n this.ownedHold = next;\n for (const id of touched) {\n const shape = this.circleById.get(id);\n if (shape) this.paintSeat(shape, id);\n this.syncSelectionMarker(id);\n }\n if (!touched.size) return;\n if (this.cached) {\n if (this.recacheTimer) clearTimeout(this.recacheTimer);\n this.recacheTimer = setTimeout(() => this.cacheSeatLayer(), 150);\n } else {\n this.seatLayer.batchDraw();\n }\n if (this.effScale() > LABEL_SCALE) this.updateLabels();\n this.overlayLayer.batchDraw();\n }\n\n setSelectionFocus(seatId: string | null): void {\n const next = seatId && this.selection.has(seatId) ? seatId : null;\n if (next === this.selectionFocusId) return;\n const previous = this.selectionFocusId;\n this.selectionFocusId = next;\n\n for (const seat of this.seats) {\n const shape = this.circleById.get(seat.id);\n if (shape) this.paintSeat(shape, seat.id);\n }\n if (previous) this.syncSelectionMarker(previous);\n if (next) this.syncSelectionMarker(next);\n for (const [id, marker] of this.selectionMarkers) {\n marker.opacity(!next || id === next ? 1 : 0.2);\n }\n if (this.cached) {\n this.seatLayer.clearCache();\n this.cacheSeatLayer();\n } else {\n this.seatLayer.batchDraw();\n }\n this.overlayLayer.batchDraw();\n }\n\n getStatus(seatId: string): SeatStatus {\n return this.statusById.get(seatId) ?? 'free';\n }\n\n getSelection(): ExpandedSeat[] {\n const out: ExpandedSeat[] = [];\n for (const id of this.selection) {\n const s = this.seatById.get(id);\n if (s) out.push(s);\n }\n return out;\n }\n\n clearSelection(): void {\n const ids = [...this.selection];\n for (const id of ids) this.setSelected(id, false, true);\n this.overlayLayer.batchDraw();\n }\n\n /** Switch organizer interaction in place so the host preserves camera, LOD,\n * focus and live status state while moving between Monitor and Block. */\n setManageInteraction(options: {\n manageMode: boolean;\n marqueeSelect: boolean;\n selectableStatuses: SeatStatus[];\n maxSelection?: number;\n }): void {\n if (this.marquee) this.cancelMarquee();\n this.panLast = null;\n this.panStart = null;\n this.panStarted = false;\n this.opts.manageMode = options.manageMode;\n this.opts.marqueeSelect = options.marqueeSelect;\n this.opts.selectableStatuses = [...options.selectableStatuses];\n if (options.maxSelection != null) this.opts.maxSelection = options.maxSelection;\n\n // A selection from a previous interaction mode must not remain actionable\n // after the new mode makes it read-only or changes its eligible statuses.\n const invalid = [...this.selection].filter((id) => !this.isSelectable(id));\n if (invalid.length) this.deselect(invalid);\n if (!options.manageMode && this.selection.size) this.clearSelection();\n this.container.style.cursor = 'default';\n this.overlayLayer.batchDraw();\n }\n\n /** Apply a non-destructive velocity treatment to section outlines. Seat\n * category/status fills remain untouched so heat never changes seat meaning. */\n setSectionHeat(scores: Record<string, number> | null): void {\n this.sectionHeat.clear();\n for (const [sectionId, raw] of Object.entries(scores ?? {})) {\n if (Number.isFinite(raw)) this.sectionHeat.set(sectionId, Math.max(0, Math.min(1, raw)));\n }\n for (const section of this.sections) this.refreshSectionHeat(section);\n this.bgLayer.batchDraw();\n }\n\n deselect(seatIds: string[]): void {\n let changed = false;\n for (const id of seatIds) {\n if (this.selection.has(id)) {\n this.setSelected(id, false, true);\n changed = true;\n }\n }\n if (changed) this.overlayLayer.batchDraw();\n }\n\n // ---- manage-mode bulk selection (SDK SeatManager) -------------------------\n // All option-gated: no-ops (or empty) unless `manageMode` is set, so buyer\n // surfaces that never pass the flag can't reach any of this.\n\n /** Select every selectable seat on the chart (⌘A). Returns the added seats. */\n selectAllSelectable(): ExpandedSeat[] {\n if (!this.opts.manageMode) return [];\n const ids: string[] = [];\n for (const seat of this.seats) if (this.isSelectable(seat.id)) ids.push(seat.id);\n return this.selectMany(ids);\n }\n\n /** Select the selectable seats matching these public labels (category/row/\n * section bulk resolves to labels host-side). Returns the newly added seats. */\n selectByLabels(labels: string[]): ExpandedSeat[] {\n if (!this.opts.manageMode) return [];\n const want = new Set(labels);\n const ids: string[] = [];\n for (const seat of this.seats) {\n if (want.has(seat.label) && this.isSelectable(seat.id)) ids.push(seat.id);\n }\n return this.selectMany(ids);\n }\n\n /** Selectable seats in a section OR zone id — pure read (no selection change). */\n getSelectableInSection(sectionId: string): ExpandedSeat[] {\n const out: ExpandedSeat[] = [];\n const seen = new Set<string>();\n for (const sec of this.sections) {\n if (sec.id !== sectionId && sec.zone !== sectionId) continue;\n for (const id of sec.memberIds) {\n if (seen.has(id)) continue;\n seen.add(id);\n if (!this.isSelectable(id)) continue;\n const s = this.seatById.get(id);\n if (s) out.push(s);\n }\n }\n return out;\n }\n\n /**\n * Union `ids` into the selection in one batched pass. Beyond MARQUEE_RING_CAP\n * total selected we skip the per-seat ring nodes (fill paint still marks the\n * seats) so a whole-arena select doesn't spawn thousands of Konva shapes.\n * Returns the full current selection.\n */\n private selectMany(ids: string[]): ExpandedSeat[] {\n const fresh = ids.filter((id) => !this.selection.has(id));\n if (!fresh.length) return this.getSelection();\n const drawRings = this.selection.size + fresh.length <= MARQUEE_RING_CAP;\n for (const id of fresh) {\n if (drawRings) {\n this.setSelected(id, true, true); // ring + fill, silent (batch draw below)\n } else {\n this.selection.add(id);\n const c = this.circleById.get(id);\n if (c) this.paintSeat(c, id);\n }\n }\n if (!this.cached) this.seatLayer.batchDraw();\n this.overlayLayer.batchDraw();\n return this.getSelection();\n }\n\n // ---- manage-mode marquee gesture ------------------------------------------\n\n private beginMarquee(clientPt: { x: number; y: number }): void {\n const w = this.screenToWorld(clientPt);\n const s = this.stage.scaleX() || 1;\n const rect = new Rect({\n x: w.x,\n y: w.y,\n width: 0,\n height: 0,\n stroke: this.effSelection,\n strokeWidth: 1.5 / s, // world units → ~constant on-screen px under the stage scale\n dash: [5 / s, 4 / s],\n fill: 'rgba(110,123,255,0.10)',\n listening: false,\n perfectDrawEnabled: false,\n shadowForStrokeEnabled: false,\n });\n this.overlayLayer.add(rect);\n this.marquee = { start: w, rect };\n this.marqueeCur = w;\n this.overlayLayer.batchDraw();\n }\n\n private updateMarquee(clientPt: { x: number; y: number }): void {\n if (!this.marquee) return;\n const w = this.screenToWorld(clientPt);\n const { start, rect } = this.marquee;\n rect.setAttrs({\n x: Math.min(start.x, w.x),\n y: Math.min(start.y, w.y),\n width: Math.abs(w.x - start.x),\n height: Math.abs(w.y - start.y),\n });\n this.marqueeCur = w;\n this.overlayLayer.batchDraw();\n }\n\n private cancelMarquee(): void {\n if (!this.marquee) return;\n this.marquee.rect.destroy();\n this.marquee = null;\n this.marqueeCur = null;\n this.overlayLayer.batchDraw();\n }\n\n /**\n * Pointer-up: hit-test the marquee world-rect against the in-memory seat\n * centres (NOT the Konva hit-graph — that's a cached bitmap when zoomed and\n * far slower), keep only SELECTABLE seats, union them into the selection and\n * fire `onMarquee`. A near-zero drag reads as a click: clear the selection.\n */\n private finishMarquee(): void {\n const m = this.marquee;\n this.marquee = null;\n if (!m) return;\n m.rect.destroy();\n this.overlayLayer.batchDraw();\n const cur = this.marqueeCur ?? m.start;\n this.marqueeCur = null;\n const x0 = Math.min(m.start.x, cur.x);\n const x1 = Math.max(m.start.x, cur.x);\n const y0 = Math.min(m.start.y, cur.y);\n const y1 = Math.max(m.start.y, cur.y);\n const s = this.stage.scaleX() || 1;\n // Sub-4px drag = a click on empty canvas → deselect-all affordance.\n if ((x1 - x0) * s < 4 && (y1 - y0) * s < 4) {\n if (this.selection.size) {\n this.clearSelection();\n this.opts.onMarquee?.([]);\n }\n return;\n }\n const ids: string[] = [];\n for (const seat of this.seats) {\n if (seat.x < x0 || seat.x > x1 || seat.y < y0 || seat.y > y1) continue;\n if (!this.isSelectable(seat.id)) continue;\n ids.push(seat.id);\n }\n this.selectMany(ids);\n this.opts.onMarquee?.(this.getSelection());\n }\n\n flashSeat(seatId: string, color = '#f43f5e'): void {\n const seat = this.seatById.get(seatId);\n if (!seat) return;\n const ring = new Circle({\n x: seat.x,\n y: seat.y,\n radius: this.seatR,\n stroke: color,\n strokeWidth: 3,\n opacity: 0.9,\n listening: false,\n perfectDrawEnabled: false,\n shadowForStrokeEnabled: false,\n });\n this.overlayLayer.add(ring);\n const start = performance.now();\n const dur = 620;\n const step = (now: number): void => {\n // Guard against a destroy() mid-animation (layer torn down).\n if (!ring.getLayer()) return;\n const t = Math.min(1, (now - start) / dur);\n ring.radius(this.seatR * (1 + t * 1.8));\n ring.opacity(0.9 * (1 - t));\n this.overlayLayer.batchDraw();\n if (t < 1) requestAnimationFrame(step);\n else {\n ring.destroy();\n this.overlayLayer.batchDraw();\n }\n };\n requestAnimationFrame(step);\n }\n\n // ---- keyboard navigation (accessibility) ----------------------------------\n\n private onKeyDown = (e: KeyboardEvent): void => {\n // Manage-mode bulk shortcuts: ⌘/Ctrl-A selects all selectable, Escape clears.\n // Both fire onMarquee so the SDK toolbar tracks selection through one path.\n if (this.opts.manageMode) {\n if ((e.metaKey || e.ctrlKey) && (e.key === 'a' || e.key === 'A')) {\n e.preventDefault();\n this.opts.onMarquee?.(this.selectAllSelectable());\n return;\n }\n if (e.key === 'Escape' && this.selection.size) {\n e.preventDefault();\n this.clearSelection();\n this.opts.onMarquee?.([]);\n return;\n }\n }\n const dir =\n e.key === 'ArrowLeft' ? { x: -1, y: 0 }\n : e.key === 'ArrowRight' ? { x: 1, y: 0 }\n : e.key === 'ArrowUp' ? { x: 0, y: -1 }\n : e.key === 'ArrowDown' ? { x: 0, y: 1 }\n : null;\n if (dir) {\n e.preventDefault();\n const next = this.focusedId ? this.nearestSeat(this.focusedId, dir) : this.seats[0]?.id ?? null;\n if (next) this.focusSeat(next);\n return;\n }\n if ((e.key === 'Enter' || e.key === ' ') && this.focusedId) {\n e.preventDefault();\n this.toggleSeat(this.focusedId);\n const s = this.seatById.get(this.focusedId);\n if (s) this.opts.onFocusSeat?.(s); // re-announce; status may have changed\n }\n };\n\n /** Nearest seat from `fromId` in a cardinal direction (aligned + close wins). */\n private nearestSeat(fromId: string, dir: { x: number; y: number }): string | null {\n const from = this.seatById.get(fromId);\n if (!from) return null;\n let best: string | null = null;\n let bestScore = Infinity;\n for (const s of this.seats) {\n if (s.id === fromId) continue;\n const dx = s.x - from.x;\n const dy = s.y - from.y;\n const proj = dx * dir.x + dy * dir.y; // along the chosen direction\n if (proj <= 0.5) continue; // must lie in that direction\n const perp = Math.abs(dx * dir.y - dy * dir.x); // lateral offset\n const score = proj + perp * 2.5; // reward alignment + proximity\n if (score < bestScore) {\n bestScore = score;\n best = s.id;\n }\n }\n return best;\n }\n\n private focusSeat(id: string): void {\n const seat = this.seatById.get(id);\n if (!seat) return;\n this.focusedId = id;\n this.focusRing.radius(this.seatR + 3);\n this.focusRing.position({ x: seat.x, y: seat.y });\n this.focusRing.visible(true);\n this.ensureVisible(seat);\n this.overlayLayer.batchDraw();\n this.opts.onFocusSeat?.(seat);\n }\n\n /** Pan/zoom so a seat sits on-screen at a legible scale (for keyboard focus). */\n private ensureVisible(seat: ExpandedSeat): void {\n const w = this.stage.width();\n const h = this.stage.height();\n const target = Math.max(this.stage.scaleX(), SEAT_LEGIBLE_SCALE * 1.2);\n const p = this.worldToScreen(seat);\n const margin = 70;\n const offscreen = p.x < margin || p.x > w - margin || p.y < margin || p.y > h - margin;\n if (this.stage.scaleX() < target || offscreen) {\n // Centre on the PROJECTED seat position so iso view frames it correctly.\n const ip = this.isoT === 0 ? seat : this.isoForward(seat);\n this.stage.scale({ x: target, y: target });\n this.stage.position({ x: w / 2 - ip.x * target, y: h / 2 - ip.y * target });\n this.afterViewChange();\n this.stage.batchDraw();\n }\n }\n\n zoomToFit(): void {\n const w = this.stage.width();\n const h = this.stage.height();\n const b = this.bounds;\n this.fitScale = Math.min(w / b.width, h / b.height) || 1;\n const s = this.fitScale;\n this.stage.scale({ x: s, y: s });\n this.stage.position({\n x: (w - b.width * s) / 2 - b.x * s,\n y: (h - b.height * s) / 2 - b.y * s,\n });\n this.afterViewChange();\n this.stage.batchDraw();\n }\n\n /** Step factor for the on-screen +/− buttons (B1) — same clamp path as pinch/wheel. */\n private static readonly ZOOM_STEP = 1.4;\n\n zoomIn(): void {\n const center = { x: this.stage.width() / 2, y: this.stage.height() / 2 };\n this.zoomAbout(this.stage.scaleX() * SeatmapRenderer.ZOOM_STEP, center);\n }\n\n zoomOut(): void {\n const center = { x: this.stage.width() / 2, y: this.stage.height() / 2 };\n this.zoomAbout(this.stage.scaleX() / SeatmapRenderer.ZOOM_STEP, center);\n }\n\n seatCount(): number {\n return this.seats.length;\n }\n\n worldToScreen(point: Point): { x: number; y: number } {\n const s = this.stage.scaleX();\n // In iso view, host overlays (confirm card, tooltip) must anchor to the\n // PROJECTED seat, so run the point through the iso affine first. At isoT=0\n // isoForward is the identity — byte-for-byte the flat behaviour.\n const p = this.isoT === 0 ? point : this.isoForward(point);\n return { x: p.x * s + this.stage.x(), y: p.y * s + this.stage.y() };\n }\n\n setAccessibleFilter(on: boolean): void {\n this.setAccessibilityFilter(on ? [] : null);\n }\n\n setAccessibilityFilter(types: AccessibilityType[] | null): void {\n const next = types === null ? null : [...types];\n if (this.sameAccessFilter(next)) return;\n this.accessFilter = next;\n for (const seat of this.seats) {\n const c = this.circleById.get(seat.id);\n if (c) this.paintSeat(c, seat.id);\n }\n if (this.cached) {\n this.seatLayer.clearCache();\n this.cacheSeatLayer();\n } else {\n this.seatLayer.batchDraw();\n }\n }\n\n private sameAccessFilter(next: AccessibilityType[] | null): boolean {\n const cur = this.accessFilter;\n if (cur === null || next === null) return cur === next;\n return cur.length === next.length && cur.every((t, i) => t === next[i]);\n }\n\n /**\n * Price-band filter (F4): dim free, unselected seats whose category key is NOT\n * in `keys`. `null` clears the filter (all categories fully visible). The\n * widget resolves which categories fall inside the buyer's chosen band.\n */\n setCategoryFilter(keys: string[] | null): void {\n const next = keys === null ? null : new Set(keys);\n const same = (next === null && this.categoryFilter === null) ||\n (next !== null && this.categoryFilter !== null &&\n next.size === this.categoryFilter.size && [...next].every((k) => this.categoryFilter!.has(k)));\n if (same) return;\n this.categoryFilter = next;\n for (const seat of this.seats) {\n const c = this.circleById.get(seat.id);\n if (c) this.paintSeat(c, seat.id);\n }\n if (this.cached) {\n this.seatLayer.clearCache();\n this.cacheSeatLayer();\n } else {\n this.seatLayer.batchDraw();\n }\n }\n\n // ---- isometric (\"3D\") view mode -------------------------------------------\n\n /**\n * Switch the projection between flat top-down and the isometric \"3D\" view\n * (rotate + y-squash about the chart centre, plus per-elevation lift). Tweens\n * `isoT` 0⇄1 over ~0.32s (ease in-out); reduced-motion snaps. Purely visual —\n * geometry stays flat, so hit-testing (Konva's own, plus the manual section\n * inverse) keeps landing on the projected seats/sections.\n */\n setViewMode(mode: 'flat' | 'isometric'): void {\n const target = mode === 'isometric' ? 1 : 0;\n this.isoTarget = target;\n if (this.isoRaf) { cancelAnimationFrame(this.isoRaf); this.isoRaf = 0; }\n if (this.reducedMotion) {\n this.isoT = target;\n this.applyIso();\n this.afterViewChange();\n return;\n }\n const from = this.isoT;\n if (from === target) { this.applyIso(); this.afterViewChange(); return; }\n const start = performance.now();\n const step = (now: number): void => {\n if (this.destroyed) return; // guard a destroy() mid-tween\n const raw = Math.min(1, (now - start) / ISO_TWEEN_MS);\n // easeInOutCubic — matches the melt's camera glide.\n const e = raw < 0.5 ? 4 * raw * raw * raw : 1 - Math.pow(-2 * raw + 2, 3) / 2;\n this.isoT = from + (this.isoTarget - from) * e;\n this.applyIso();\n this.scheduleViewChange();\n if (raw < 1) {\n this.isoRaf = requestAnimationFrame(step);\n } else {\n this.isoT = this.isoTarget;\n this.isoRaf = 0;\n this.applyIso();\n this.afterViewChange(); // re-evaluate cache/labels at the settled effective scale\n }\n };\n this.isoRaf = requestAnimationFrame(step);\n }\n\n /** Current projection — reflects the tween target, not the mid-tween isoT. */\n getViewMode(): 'flat' | 'isometric' {\n return this.isoTarget === 1 ? 'isometric' : 'flat';\n }\n\n /** Iso angle (rad) + y-squash for the current isoT. */\n private isoParams(): { th: number; sg: number } {\n return { th: (ISO_ANGLE_DEG * Math.PI) / 180 * this.isoT, sg: 1 - (1 - ISO_SQUASH) * this.isoT };\n }\n\n /** Effective vertical scale = stage scale × iso squash — legibility math uses this. */\n private effScale(): number {\n return this.stage.scaleX() * (1 - (1 - ISO_SQUASH) * this.isoT);\n }\n\n /** Project a world point through the iso affine about the chart centre (→ iso-world). */\n private isoForward(p: Point): { x: number; y: number } {\n const { th, sg } = this.isoParams();\n const c = this.isoCentre;\n const dx = p.x - c.x;\n const dy = p.y - c.y;\n const rx = dx * Math.cos(th) - dy * Math.sin(th);\n const ry = (dx * Math.sin(th) + dy * Math.cos(th)) * sg;\n return { x: c.x + rx, y: c.y + ry };\n }\n\n /** Inverse of isoForward (iso-world → world) for screen-space hit-testing. */\n private isoInverse(p: Point): { x: number; y: number } {\n const { th, sg } = this.isoParams();\n const c = this.isoCentre;\n const dx = p.x - c.x;\n const dy = p.y - c.y;\n const uy = dy / sg;\n const wx = dx * Math.cos(th) + uy * Math.sin(th);\n const wy = -dx * Math.sin(th) + uy * Math.cos(th);\n return { x: c.x + wx, y: c.y + wy };\n }\n\n /**\n * Local-space offset that, once the layer applies the iso affine, lifts an\n * object straight UP in iso-world by `elevation × LIFT_PER_STEP × isoT`\n * (= inverse-linear of the pure vertical lift). Zero at isoT=0.\n */\n private isoLiftLocal(elevation: number): { x: number; y: number } {\n const { th, sg } = this.isoParams();\n const delta = elevation * LIFT_PER_STEP * this.isoT;\n return { x: -(delta / sg) * Math.sin(th), y: -(delta / sg) * Math.cos(th) };\n }\n\n /** Restore the three layers to identity (flat) — byte-for-byte the original. */\n private resetLayerTransforms(): void {\n for (const layer of [this.bgLayer, this.seatLayer, this.overlayLayer]) {\n layer.position({ x: 0, y: 0 });\n layer.offset({ x: 0, y: 0 });\n layer.scale({ x: 1, y: 1 });\n layer.rotation(0);\n layer.skewX(0);\n layer.skewY(0);\n }\n }\n\n /**\n * Apply the current isoT to the scene: the base rotate+squash as a decomposed\n * layer transform (so seats/décor/rings project together and Konva's own\n * hit-testing follows), upright counter-transforms on text, and the elevation\n * lift + extruded side faces on elevated sections.\n */\n private applyIso(): void {\n const t = this.isoT;\n if (t === 0) {\n this.resetLayerTransforms();\n } else {\n const { th, sg } = this.isoParams();\n // L_iso = Scale(1,sg)·Rot(th) about the centre; decompose to Konva props.\n const a = Math.cos(th);\n const b = sg * Math.sin(th);\n const cc = -Math.sin(th);\n const d = sg * Math.cos(th);\n const r = Math.sqrt(a * a + b * b);\n const delta = a * d - b * cc; // = sg\n const rotationDeg = (Math.atan2(b, a) * 180) / Math.PI;\n const scaleX = r;\n const scaleY = delta / r;\n const skewX = (a * cc + b * d) / delta;\n const c = this.isoCentre;\n for (const layer of [this.bgLayer, this.seatLayer, this.overlayLayer]) {\n layer.position({ x: c.x, y: c.y });\n layer.offset({ x: c.x, y: c.y });\n layer.rotation(rotationDeg);\n layer.scaleX(scaleX);\n layer.scaleY(scaleY);\n layer.skewX(skewX);\n layer.skewY(0);\n }\n }\n\n this.applyUprightLabels();\n this.applyElevation();\n\n this.bgLayer.batchDraw();\n this.seatLayer.batchDraw();\n this.overlayLayer.batchDraw();\n }\n\n /** Counter-skew every visible label so it renders upright at its projected anchor. */\n private applyUprightLabels(): void {\n const thDeg = ISO_ANGLE_DEG * this.isoT;\n const invScaleY = 1 / (1 - (1 - ISO_SQUASH) * this.isoT);\n // Seat labels live in overlayLayer (labelGroup); section/zone/décor in bgLayer.\n // Skip the seatLayer scan unless it actually holds booth labels (else it is\n // thousands of Circles with no Text).\n const layers = this.hasBoothText\n ? [this.bgLayer, this.seatLayer, this.overlayLayer]\n : [this.bgLayer, this.overlayLayer];\n for (const layer of layers) {\n const texts = layer.find('Text') as unknown as Text[];\n for (const tn of texts) {\n let base = tn.getAttr('uprightBase') as number | undefined;\n if (base == null) {\n base = tn.rotation();\n tn.setAttr('uprightBase', base);\n }\n tn.rotation(base - thDeg);\n tn.scaleX(1);\n tn.scaleY(invScaleY);\n tn.skewX(0);\n }\n }\n }\n\n /** Lift elevated sections (+ their members) and update their extruded side faces. */\n private applyElevation(): void {\n const t = this.isoT;\n for (const sec of this.sections) {\n if (sec.elevation <= 0) continue;\n const off = this.isoLiftLocal(sec.elevation);\n sec.liftGroupBg?.position(off);\n sec.liftGroupSeat?.position(off);\n // Side faces: quad per edge from base outline to the lifted outline, in\n // local (world) space — the layer projects them. Invisible at isoT=0.\n const alpha = 0.9 * t;\n for (let i = 0; i < sec.sideFaces.length; i++) {\n const face = sec.sideFaces[i];\n const p0 = sec.outline[i];\n const p1 = sec.outline[(i + 1) % sec.outline.length];\n face.points([p0.x, p0.y, p1.x, p1.y, p1.x + off.x, p1.y + off.y, p0.x + off.x, p0.y + off.y]);\n face.opacity(alpha);\n }\n }\n }\n\n destroy(): void {\n this.destroyed = true;\n if (this.rafId) cancelAnimationFrame(this.rafId);\n if (this.isoRaf) cancelAnimationFrame(this.isoRaf);\n if (this.glideRaf) cancelAnimationFrame(this.glideRaf);\n if (this.viewChangeRaf) cancelAnimationFrame(this.viewChangeRaf);\n if (this.recacheTimer) clearTimeout(this.recacheTimer);\n this.resizeObs?.disconnect();\n this.container.removeEventListener('pointerdown', this.onPointerDown);\n this.container.removeEventListener('pointermove', this.onPointerMove);\n this.container.removeEventListener('pointerup', this.onPointerEnd);\n this.container.removeEventListener('pointercancel', this.onPointerEnd);\n this.container.removeEventListener('keydown', this.onKeyDown);\n this.stage.destroy();\n }\n\n // ---- rendering ------------------------------------------------------------\n\n /** Theme font stack for all rendered text (falls back to Inter). */\n private labelFont(): string {\n return this.theme.fontFamily || 'Inter, sans-serif';\n }\n\n /**\n * Where a seat's nodes live: an elevated section's lift group (so the whole\n * tier shifts with one offset in iso view) or the seat layer directly.\n */\n private seatContainer(id: string): Group | Layer {\n return this.seatSection.get(id)?.liftGroupSeat ?? this.seatLayer;\n }\n\n private renderSeats(): void {\n for (const seat of this.seats) {\n if (seat.kind === 'booth') {\n this.renderBoothUnit(seat);\n continue;\n }\n const target = this.seatContainer(seat.id);\n const c = new Circle({\n x: seat.x,\n y: seat.y,\n radius: this.seatR,\n perfectDrawEnabled: false,\n shadowForStrokeEnabled: false,\n hitStrokeWidth: 0,\n });\n c.setAttr('seatId', seat.id);\n this.circleById.set(seat.id, c);\n this.paintSeat(c, seat.id);\n target.add(c);\n // Accessible seats get a static 2px outer ring, coloured by their primary\n // accommodation (few per chart, so the extra node is cheap).\n if (seat.accessible) {\n const primary = seat.accessibility?.[0];\n target.add(\n new Circle({\n x: seat.x,\n y: seat.y,\n radius: this.seatR + 1,\n stroke: (primary && ACCESS_RING[primary]) || '#3b82f6',\n strokeWidth: 2,\n listening: false,\n perfectDrawEnabled: false,\n shadowForStrokeEnabled: false,\n }),\n );\n }\n }\n }\n\n /** A booth renders as a click-selectable rounded block (dims from the doc). */\n private renderBoothUnit(seat: ExpandedSeat): void {\n const target = this.seatContainer(seat.id);\n const dims = this.boothDims.get(seat.rowId) ?? { width: 40, height: 30, rotation: 0 };\n const rect = new Rect({\n x: seat.x,\n y: seat.y,\n width: dims.width,\n height: dims.height,\n offsetX: dims.width / 2,\n offsetY: dims.height / 2,\n rotation: dims.rotation,\n cornerRadius: 4,\n perfectDrawEnabled: false,\n shadowForStrokeEnabled: false,\n hitStrokeWidth: 0,\n });\n rect.setAttr('seatId', seat.id);\n this.circleById.set(seat.id, rect);\n this.paintSeat(rect, seat.id);\n target.add(rect);\n\n const t = new Text({\n x: seat.x,\n y: seat.y,\n text: seat.label,\n fontSize: 10,\n fontStyle: '600',\n fontFamily: this.labelFont(),\n fill: this.theme.seatLabelColor ?? DEF_SEAT_LABEL,\n listening: false,\n perfectDrawEnabled: false,\n });\n t.offsetX(t.width() / 2);\n t.offsetY(t.height() / 2);\n this.hasBoothText = true; // gate the upright-label scan of the seat layer\n this.boothLabelById.set(seat.id, t);\n target.add(t);\n }\n\n /** The category's display color — Okabe-Ito hue when colorblind-safe is on. */\n private seatBaseColor(categoryKey: string): string {\n if (!this.colorblind) return this.catColor.get(categoryKey) ?? '#6e7bff';\n const idx = this.catOrder.indexOf(categoryKey);\n return CB_PALETTE[(idx >= 0 ? idx : 0) % CB_PALETTE.length];\n }\n\n /** Apply fill/stroke/opacity for a seat's current status + selection. */\n private paintSeat(c: Shape, id: string): void {\n const seat = this.seatById.get(id)!;\n const status = this.statusById.get(id) ?? 'free';\n const selected = this.selection.has(id);\n const base = this.seatBaseColor(seat.categoryKey);\n const boothLabel = this.boothLabelById.get(id);\n\n c.dash([]);\n c.strokeWidth(0);\n c.stroke('');\n c.opacity(1);\n\n switch (status) {\n case 'free':\n // Selected: on dark canvases the lightened fill + white ring pops; on\n // light canvases that same wash reads as *disabled*, so keep the full\n // category fill and let the dark contrast ring carry the state.\n c.fill(\n selected && this.effSelection === DEF_SELECTION ? lighten(base, 0.28) : base,\n );\n break;\n case 'held':\n if (this.ownedHold.has(id)) {\n // A buyer returning from checkout must be able to distinguish their\n // own inventory from somebody else's hold. Preserve the category\n // identity and outline the actual seat/booth shape (full rectangle\n // for a booth), rather than painting it generic unavailable grey.\n c.fill(lighten(base, this.effSelection === DEF_SELECTION ? 0.24 : 0.1));\n c.stroke(this.effSelection);\n c.strokeWidth(3);\n } else {\n c.fill(HELD_FILL);\n }\n break;\n case 'booked':\n if (this.colorblind) {\n // Non-color cue: booked reads as a hollow ring, never hue alone.\n c.fill('rgba(0,0,0,0)');\n c.stroke(TAKEN_FILL);\n c.strokeWidth(1.5);\n c.opacity(0.9);\n } else {\n c.fill(TAKEN_FILL);\n c.opacity(0.45);\n }\n break;\n case 'not_for_sale':\n c.fill(TAKEN_FILL);\n c.stroke(NFS_STROKE);\n c.strokeWidth(1);\n c.dash([2, 2]);\n break;\n }\n\n if (boothLabel) {\n boothLabel.text(status === 'booked' ? 'SOLD' : status === 'held' ? 'HELD' : seat.label);\n boothLabel.fontSize(status === 'free' ? 10 : Math.min(10, Math.max(6, this.boothDims.get(seat.rowId)?.width ?? 40) / 6));\n boothLabel.fontStyle(status === 'free' ? '600' : '800');\n boothLabel.fill(status === 'free' ? (this.theme.seatLabelColor ?? DEF_SEAT_LABEL) : '#ffffff');\n boothLabel.offsetX(boothLabel.width() / 2);\n boothLabel.offsetY(boothLabel.height() / 2);\n }\n\n // Accessibility filter dims free, unselected seats that don't match.\n if (this.accessFilter && status === 'free' && !selected && !seatMatchesAccess(seat, this.accessFilter)) {\n c.opacity(0.25);\n }\n // Legend hover-highlight dims free, unselected seats of other categories.\n if (this.categoryHighlight && status === 'free' && !selected && seat.categoryKey !== this.categoryHighlight) {\n c.opacity(0.25);\n }\n // Price-band filter (F4): dim free, unselected seats outside the chosen band.\n if (this.categoryFilter && status === 'free' && !selected && !this.categoryFilter.has(seat.categoryKey)) {\n c.opacity(0.22);\n }\n // Held-back inventory (organizer manager): seats in a dimmed section/zone\n // read as inactive so the map matches the Sections list at a glance.\n if (this.dimmedSections.size) {\n const sec = this.seatSection.get(id);\n if (sec && (this.dimmedSections.has(sec.id) || (sec.zone != null && this.dimmedSections.has(sec.zone)))) {\n c.opacity(0.18);\n }\n }\n // Phase 2 `closed` section: flat grey, 40% opacity, never a category hue —\n // overrides the status paint above. Seats stay visible but read off-sale.\n if (this.closedSections.size && this.seatInClosedSection(id)) {\n c.fill(CLOSED_SEAT_FILL);\n c.stroke('');\n c.strokeWidth(0);\n c.dash([]);\n c.opacity(CLOSED_SEAT_OPACITY);\n }\n // AXS section-focus: seats outside the focused section desaturate + dim so\n // the focused block reads against a calm ground (§4 focus spec).\n if (this.focusedSectionId) {\n const sec = this.seatSection.get(id);\n const inFocus = !!sec && (sec.id === this.focusedSectionId || sec.zone === this.focusedSectionId);\n if (!inFocus) c.opacity(FOCUS_DIM_OPACITY);\n }\n // Buyer confirmation focus: retain the candidate at full strength while\n // every unrelated seat recedes. The candidate/selected markers live on the\n // overlay layer and are dimmed separately so state remains readable.\n if (this.selectionFocusId && id !== this.selectionFocusId) c.opacity(Math.min(c.opacity(), 0.16));\n }\n\n /** True when a seat sits in a section/zone currently marked `closed`. */\n private seatInClosedSection(id: string): boolean {\n if (!this.closedSections.size) return false;\n const sec = this.seatSection.get(id);\n return !!sec && (this.closedSections.has(sec.id) || (sec.zone != null && this.closedSections.has(sec.zone)));\n }\n\n /**\n * Colorblind-safe mode: swap category hues for the Okabe-Ito palette and\n * render booked seats hollow. Off restores the exact default rendering.\n */\n setColorblindSafe(on: boolean): void {\n if (on === this.colorblind) return;\n this.colorblind = on;\n for (const seat of this.seats) {\n const c = this.circleById.get(seat.id);\n if (c) this.paintSeat(c, seat.id);\n }\n if (this.cached) {\n this.seatLayer.clearCache();\n this.cacheSeatLayer();\n } else {\n this.seatLayer.batchDraw();\n }\n }\n\n /**\n * Dim the seats of these section/zone ids (organizer manager use) so held-back\n * inventory is visually distinct on the canvas without hiding it. `null`/empty\n * clears. Unlike the buyer's applyHidden, the sections stay rendered.\n */\n setDimmedSections(ids: string[] | null): void {\n const next = new Set(ids ?? []);\n if (next.size === this.dimmedSections.size && [...next].every((i) => this.dimmedSections.has(i))) return;\n this.dimmedSections = next;\n for (const seat of this.seats) {\n const c = this.circleById.get(seat.id);\n if (c) this.paintSeat(c, seat.id);\n }\n if (this.cached) {\n this.seatLayer.clearCache();\n this.cacheSeatLayer();\n } else {\n this.seatLayer.batchDraw();\n }\n }\n\n /**\n * Phase 2 event-level section states: mark these section/zone ids `closed` —\n * flat grey block, seats greyed + not pickable, but the section stays rendered\n * (unlike the buyer's applyHidden which strips it). `null`/empty clears.\n */\n setClosedSections(ids: string[] | null): void {\n const next = new Set(ids ?? []);\n if (next.size === this.closedSections.size && [...next].every((i) => this.closedSections.has(i))) return;\n this.closedSections = next;\n this.repaintSectionsAndSeats();\n }\n\n /**\n * AXS section-focus: dim + desaturate every other section, draw a calm backdrop\n * panel behind this section's seats, and glide the camera in to frame it (the\n * seat-pick gate below only lets buyers pick once seats are ≥ LABEL_SCALE big).\n */\n focusSection(id: string): void {\n if (!this.sections.some((s) => s.id === id)) return;\n this.focusedSectionId = id;\n this.drawFocusBackdrop(id);\n this.repaintSectionsAndSeats();\n this.updateLOD();\n this.focusRegion(id, { minScale: SEAT_FOCUS_SCALE });\n }\n\n /** Clear an AXS section focus — restore full-bowl brightness + drop the backdrop. */\n clearSectionFocus(): void {\n if (!this.focusedSectionId) return;\n this.focusedSectionId = null;\n if (this.focusBackdrop) {\n this.focusBackdrop.destroy();\n this.focusBackdrop = null;\n }\n this.repaintSectionsAndSeats();\n this.updateLOD();\n }\n\n /** The currently AXS-focused section id, or null. */\n getFocusedSection(): string | null {\n return this.focusedSectionId;\n }\n\n /** Draw (or replace) the light backdrop panel behind the focused section. */\n private drawFocusBackdrop(id: string): void {\n if (this.focusBackdrop) {\n this.focusBackdrop.destroy();\n this.focusBackdrop = null;\n }\n const sec = this.sections.find((s) => s.id === id);\n if (!sec) return;\n const panel = new Line({\n points: sec.outline.flatMap((p) => [p.x, p.y]),\n closed: true,\n fill: FOCUS_BACKDROP_FILL,\n stroke: rgba('#ffffff', 0.1),\n strokeWidth: 1,\n listening: false,\n perfectDrawEnabled: false,\n });\n this.bgLayer.add(panel);\n panel.moveToTop(); // above the dimmed sibling blocks, still under the seat layer\n this.focusBackdrop = panel;\n }\n\n /** Repaint every seat + section block to reflect closed/focus state, then redraw. */\n private repaintSectionsAndSeats(): void {\n for (const seat of this.seats) {\n const c = this.circleById.get(seat.id);\n if (c) this.paintSeat(c, seat.id);\n }\n for (const sec of this.sections) sec.blockPoly.fill(this.sectionBlockFill(sec));\n if (this.cached) {\n this.seatLayer.clearCache();\n this.cacheSeatLayer();\n } else {\n this.seatLayer.batchDraw();\n }\n this.bgLayer.batchDraw();\n }\n\n /** The world-space rectangle currently visible in the viewport (minimap F3). */\n getVisibleWorldRect(): { x: number; y: number; width: number; height: number } {\n const tl = this.screenToWorld({ x: 0, y: 0 });\n const br = this.screenToWorld({ x: this.stage.width(), y: this.stage.height() });\n return {\n x: Math.min(tl.x, br.x),\n y: Math.min(tl.y, br.y),\n width: Math.abs(br.x - tl.x),\n height: Math.abs(br.y - tl.y),\n };\n }\n\n /** Axis-aligned world bounds of all seats + section outlines (minimap F3 frame). */\n getWorldBounds(): { x: number; y: number; width: number; height: number } {\n let minX = Infinity;\n let minY = Infinity;\n let maxX = -Infinity;\n let maxY = -Infinity;\n const grow = (x: number, y: number): void => {\n if (x < minX) minX = x;\n if (y < minY) minY = y;\n if (x > maxX) maxX = x;\n if (y > maxY) maxY = y;\n };\n for (const s of this.seats) grow(s.x, s.y);\n for (const sec of this.sections) for (const p of sec.outline) grow(p.x, p.y);\n if (!Number.isFinite(minX)) return { x: 0, y: 0, width: 1, height: 1 };\n return { x: minX, y: minY, width: Math.max(1, maxX - minX), height: Math.max(1, maxY - minY) };\n }\n\n /** Legend hover: highlight one category (dim the rest), or null to clear. */\n setCategoryHighlight(key: string | null): void {\n if (this.categoryHighlight === key) return;\n this.categoryHighlight = key;\n for (const seat of this.seats) {\n const c = this.circleById.get(seat.id);\n if (c) this.paintSeat(c, seat.id);\n }\n if (this.cached) {\n this.seatLayer.clearCache();\n this.cacheSeatLayer();\n } else {\n this.seatLayer.batchDraw();\n }\n }\n\n private renderBackground(doc: ChartDoc): void {\n if (doc.backgroundImage) this.renderBackgroundImage(doc.backgroundImage);\n // Decor graphics (ice rink, court art) draw first so they sit UNDER the\n // section outlines and — being on bgLayer, below seatLayer entirely — under\n // every seat. listening(false) keeps them out of the hit graph.\n for (const obj of doc.objects) if (obj.type === 'decorImage') this.renderDecorImage(obj);\n // Sections sit under all other décor so their outlines never occlude seats.\n // NOTE(phase-2): event-level section open/closed/hidden state will gate this\n // draw + the seat membership below — hide/dim a section by id/zone here.\n for (const obj of doc.objects) if (obj.type === 'section') this.renderSection(obj);\n // Zone labels sit above section blocks (drawn after) — the farthest rung.\n this.renderZones(doc);\n for (const obj of doc.objects) {\n if (obj.type === 'shape') {\n this.renderShape(obj);\n } else if (obj.type === 'gaArea') {\n this.renderGA(obj);\n } else if (obj.type === 'table') {\n this.renderTable(obj);\n } else if (obj.type === 'text') {\n this.renderText(obj);\n }\n }\n // Focal-point crosshair marker.\n const f = doc.focalPoint;\n if (f) {\n const size = 14;\n const cross = new Group({ listening: false });\n cross.add(\n new Line({ points: [f.x - size, f.y, f.x + size, f.y], stroke: '#4b5563', strokeWidth: 1.5 }),\n new Line({ points: [f.x, f.y - size, f.x, f.y + size], stroke: '#4b5563', strokeWidth: 1.5 }),\n new Circle({ x: f.x, y: f.y, radius: 3, fill: '#4b5563' }),\n );\n this.bgLayer.add(cross);\n }\n }\n\n /** Organizer floor-plan photo, dimmed, at the very bottom of the bg layer. */\n private renderBackgroundImage(bg: NonNullable<ChartDoc['backgroundImage']>): void {\n const img = new window.Image();\n img.onload = () => {\n const natW = img.naturalWidth || 4;\n const natH = img.naturalHeight || 3;\n const w = bg.width;\n const h = w * (natH / natW);\n const node = new KImage({\n image: img,\n x: bg.center.x - w / 2,\n y: bg.center.y - h / 2,\n width: w,\n height: h,\n opacity: bg.opacity,\n listening: false,\n });\n this.bgLayer.add(node);\n node.moveToBottom();\n this.bgLayer.batchDraw();\n };\n img.src = bg.url;\n }\n\n /**\n * A decor graphic (rink / court / stage art). The KImage node is added to the\n * bgLayer synchronously so it keeps its z-slot beneath the sections drawn right\n * after; the bitmap is decoded async and pasted in on load. A single node = a\n * single drawImage per frame, and it rides the same layer cache — effectively\n * zero per-frame cost. Never listens, so it can't intercept a seat click.\n */\n private renderDecorImage(obj: Extract<ChartDoc['objects'][number], { type: 'decorImage' }>): void {\n // Pass the (not-yet-loaded) Image element as the node's image: Konva draws\n // nothing until it decodes, then onload triggers a repaint. Keeps the node's\n // z-slot fixed beneath the sections drawn immediately after.\n const img = new window.Image();\n const node = new KImage({\n image: img,\n x: obj.x + obj.width / 2,\n y: obj.y + obj.height / 2,\n offsetX: obj.width / 2,\n offsetY: obj.height / 2,\n width: obj.width,\n height: obj.height,\n rotation: obj.rotation ?? 0,\n opacity: clamp(obj.opacity ?? 1, 0, 1),\n listening: false,\n perfectDrawEnabled: false,\n });\n this.bgLayer.add(node);\n img.onload = () => {\n if (!node.getLayer()) return; // chart swapped out before the image loaded\n this.bgLayer.batchDraw();\n };\n img.src = obj.href;\n }\n\n private renderTable(obj: Extract<ChartDoc['objects'][number], { type: 'table' }>): void {\n if (obj.shape === 'round') {\n this.bgLayer.add(\n new Circle({\n x: obj.center.x,\n y: obj.center.y,\n radius: obj.radius ?? 40,\n fill: '#232c40',\n stroke: '#2a3348',\n strokeWidth: 1.5,\n listening: false,\n }),\n );\n } else {\n const w = obj.width ?? 80;\n const h = obj.height ?? 50;\n this.bgLayer.add(\n new Rect({\n x: obj.center.x,\n y: obj.center.y,\n width: w,\n height: h,\n offsetX: w / 2,\n offsetY: h / 2,\n rotation: obj.rotation,\n fill: '#232c40',\n stroke: '#2a3348',\n strokeWidth: 1.5,\n cornerRadius: 4,\n listening: false,\n }),\n );\n }\n this.addCentredLabel(this.bgLayer, obj.label, obj.center.x, obj.center.y, '#cbd5e1', 12, true);\n }\n\n private renderText(obj: Extract<ChartDoc['objects'][number], { type: 'text' }>): void {\n this.bgLayer.add(\n new Text({\n x: obj.position.x,\n y: obj.position.y,\n text: obj.text,\n fontSize: obj.fontSize,\n rotation: obj.rotation,\n fill: obj.color ?? this.theme.textColor ?? DEF_TEXT,\n fontFamily: this.labelFont(),\n listening: false,\n perfectDrawEnabled: false,\n }),\n );\n }\n\n private renderShape(obj: Extract<ChartDoc['objects'][number], { type: 'shape' }>): void {\n const fill = obj.fill ?? this.theme.decorFill ?? DEF_DECOR_FILL;\n const isStage = obj.role === 'stage';\n const isDecor = !!obj.role && !isStage;\n // Stage: darker at the back (min-y), brighter toward the audience edge (max-y).\n const stroke = isStage ? lighten(fill, 0.28) : undefined;\n let cx = 0;\n let cy = 0;\n if (obj.kind === 'rect' && obj.x != null && obj.y != null && obj.width != null && obj.height != null) {\n const grad = isStage\n ? {\n fillLinearGradientStartPoint: { x: 0, y: 0 },\n fillLinearGradientEndPoint: { x: 0, y: obj.height },\n fillLinearGradientColorStops: [0, darken(fill, 0.3), 1, lighten(fill, 0.12)],\n }\n : { fill };\n cx = obj.x + obj.width / 2;\n cy = obj.y + obj.height / 2;\n // Rotate about center: pivot at (cx,cy) via offset; local coords (and the\n // gradient) are unchanged, so the fill spans the box regardless of angle.\n this.bgLayer.add(\n new Rect({\n x: cx,\n y: cy,\n offsetX: obj.width / 2,\n offsetY: obj.height / 2,\n rotation: obj.rotation ?? 0,\n width: obj.width,\n height: obj.height,\n ...grad,\n stroke,\n strokeWidth: isStage ? 1 : 0,\n cornerRadius: 4,\n listening: false,\n }),\n );\n } else if (obj.kind === 'ellipse' && obj.x != null && obj.y != null && obj.width != null && obj.height != null) {\n cx = obj.x + obj.width / 2;\n cy = obj.y + obj.height / 2;\n const grad = isStage\n ? {\n fillLinearGradientStartPoint: { x: 0, y: -obj.height / 2 },\n fillLinearGradientEndPoint: { x: 0, y: obj.height / 2 },\n fillLinearGradientColorStops: [0, darken(fill, 0.3), 1, lighten(fill, 0.12)],\n }\n : { fill };\n this.bgLayer.add(\n new Ellipse({ x: cx, y: cy, rotation: obj.rotation ?? 0, radiusX: obj.width / 2, radiusY: obj.height / 2, ...grad, stroke, strokeWidth: isStage ? 1 : 0, listening: false }),\n );\n } else if (obj.kind === 'polygon' && obj.points && obj.points.length) {\n const pts = obj.points.flatMap((p) => [p.x, p.y]);\n const b = polyBounds(obj.points);\n cx = obj.points.reduce((a, p) => a + p.x, 0) / obj.points.length;\n cy = obj.points.reduce((a, p) => a + p.y, 0) / obj.points.length;\n const grad = isStage\n ? {\n // Line points are absolute chart coords; the gradient endpoints share\n // that space and rotate with the node (pivot at the centroid below).\n fillLinearGradientStartPoint: { x: 0, y: b.y },\n fillLinearGradientEndPoint: { x: 0, y: b.y + b.height },\n fillLinearGradientColorStops: [0, darken(fill, 0.3), 1, lighten(fill, 0.12)],\n }\n : { fill };\n // Rotate about the centroid: position=offset=centroid leaves the polygon\n // in place at rotation 0 and pivots there for any angle.\n this.bgLayer.add(\n new Line({ points: pts, closed: true, x: cx, y: cy, offsetX: cx, offsetY: cy, rotation: obj.rotation ?? 0, ...grad, stroke, strokeWidth: isStage ? 1 : 0, listening: false }),\n );\n }\n if (obj.label) {\n if (isStage) this.addStageLabel(cx, cy, obj.label);\n else if (isDecor) this.addCentredLabel(this.bgLayer, obj.label, cx, cy, '#9aa3b5', 12, false);\n else this.addCentredLabel(this.bgLayer, obj.label, cx, cy, '#cbd5e1', 16, true);\n }\n }\n\n /** Prominent stage caption: uppercase, letter-spaced, larger, softly dimmed. */\n private addStageLabel(x: number, y: number, text: string): void {\n const t = new Text({\n x,\n y,\n text: text.toUpperCase(),\n fontSize: 22,\n fontStyle: '700',\n letterSpacing: 4,\n fontFamily: this.labelFont(),\n fill: rgba('#e6e9f0', 0.62),\n listening: false,\n perfectDrawEnabled: false,\n });\n t.offsetX(t.width() / 2);\n t.offsetY(t.height() / 2);\n this.bgLayer.add(t);\n }\n\n private renderGA(obj: Extract<ChartDoc['objects'][number], { type: 'gaArea' }>): void {\n const color = this.catColor.get(obj.categoryKey) ?? '#6e7bff';\n const pts = obj.points.flatMap((p) => [p.x, p.y]);\n const poly = new Line({\n points: pts,\n closed: true,\n fill: color,\n opacity: 0.22,\n stroke: color,\n strokeWidth: 1.5,\n });\n poly.setAttr('gaId', obj.id);\n poly.on('click tap', () => this.opts.onGAClick?.(obj.id));\n poly.on('mouseenter', () => {\n this.container.style.cursor = 'pointer';\n });\n poly.on('mouseleave', () => {\n this.container.style.cursor = 'default';\n });\n this.bgLayer.add(poly);\n\n const cx = obj.points.reduce((a, p) => a + p.x, 0) / obj.points.length;\n const cy = obj.points.reduce((a, p) => a + p.y, 0) / obj.points.length;\n this.addCentredLabel(this.bgLayer, obj.label, cx, cy - 8, '#e6e9f0', 15, false);\n this.addCentredLabel(this.bgLayer, `cap ${obj.capacity}`, cx, cy + 10, '#8b93a7', 11, false);\n }\n\n /**\n * A section renders in three coordinated layers driven by the LOD melt:\n * • a faint outline (the existing near-zoom look, untouched),\n * • a solid category-mix block that fades in at the block rung, and\n * • a name + \"N LEFT\" sublabel.\n * Membership (which seats live inside the outline) + the mix fill + the live\n * availability count are precomputed here (once), not per frame.\n */\n private renderSection(obj: SectionObject): void {\n const pts = obj.outline.flatMap((p) => [p.x, p.y]);\n const centroid = {\n x: obj.outline.reduce((a, p) => a + p.x, 0) / obj.outline.length,\n y: obj.outline.reduce((a, p) => a + p.y, 0) / obj.outline.length,\n };\n\n // Membership: seats inside the outline, first section (doc order) wins.\n const memberIds: string[] = [];\n const catCounts = new Map<string, number>();\n let free = 0;\n for (const seat of this.seats) {\n if (this.seatSection.has(seat.id)) continue;\n if (!pointInPolygon(seat, obj.outline)) continue;\n memberIds.push(seat.id);\n catCounts.set(seat.categoryKey, (catCounts.get(seat.categoryKey) ?? 0) + 1);\n if ((this.statusById.get(seat.id) ?? 'free') === 'free') free++;\n }\n\n // Category-mix fill: explicit override wins, else blend member colours by count.\n const baseFill =\n obj.color ??\n mixColors(\n [...catCounts].map(([key, w]) => ({ hex: this.catColor.get(key) ?? '#6e7bff', w })),\n '#3a4358',\n );\n\n // Elevation: elevated sections lift as one tier in the iso view, so their bg\n // nodes + member seats go into lift groups (positioned in applyElevation).\n // Side faces (a zone-coloured quad per outline edge) extrude only as isoT rises.\n const elevation = Math.max(0, Math.round(obj.elevation ?? 0));\n let liftGroupBg: Group | null = null;\n let liftGroupSeat: Group | null = null;\n const sideFaces: Line[] = [];\n if (elevation > 0) {\n const faceFill = darken(this.zoneColor.get(obj.zone ?? '') ?? baseFill, 0.42);\n for (let i = 0; i < obj.outline.length; i++) {\n const face = new Line({\n points: [],\n closed: true,\n fill: faceFill,\n stroke: rgba('#000000', 0.25),\n strokeWidth: 1,\n opacity: 0,\n listening: false,\n perfectDrawEnabled: false,\n });\n sideFaces.push(face);\n this.bgLayer.add(face); // behind the group added next → behind the fill\n }\n liftGroupBg = new Group({ listening: false });\n this.bgLayer.add(liftGroupBg);\n liftGroupSeat = new Group({ listening: false });\n this.seatLayer.add(liftGroupSeat);\n }\n const bgTarget: Group | Layer = liftGroupBg ?? this.bgLayer;\n\n // Zone-coloured outline under the seats — matches the crisp section blocks\n // the designer draws, so the near-zoom map reads as defined zones too.\n const outlineTint = obj.color ?? this.zoneColor.get(obj.zone ?? '') ?? '#3a4358';\n const outlinePoly = new Line({\n points: pts,\n closed: true,\n stroke: rgba(outlineTint, 0.5),\n strokeWidth: 1.75,\n fill: rgba(outlineTint, 0.08),\n lineJoin: 'round',\n listening: false,\n perfectDrawEnabled: false,\n });\n bgTarget.add(outlinePoly);\n\n // Solid block fill — melts in at the block rung (opacity driven by the LOD).\n const blockPoly = new Line({\n points: pts,\n closed: true,\n fill: baseFill,\n stroke: rgba('#ffffff', 0.12),\n strokeWidth: 1,\n opacity: 0,\n listening: false,\n perfectDrawEnabled: false,\n });\n bgTarget.add(blockPoly);\n\n // Faint per-row hint lines (the seats.io \"block-with-rows\" look): a polyline\n // through each member row's seats, fading in with the block. Lets a section\n // read as SEATING — not a flat colour — at the overview zoom, seats hidden.\n const rowSeats = new Map<string, Array<{ i: number; x: number; y: number }>>();\n for (const id of memberIds) {\n const s = this.seatById.get(id);\n if (!s) continue;\n const i = Number(id.slice(id.lastIndexOf(':') + 1)) || 0;\n (rowSeats.get(s.rowId) ?? rowSeats.set(s.rowId, []).get(s.rowId)!).push({ i, x: s.x, y: s.y });\n }\n const rowLines: Line[] = [];\n for (const arr of rowSeats.values()) {\n if (arr.length < 2) continue;\n arr.sort((a, b) => a.i - b.i);\n const line = new Line({\n points: arr.flatMap((p) => [p.x, p.y]),\n stroke: rgba('#ffffff', 0.34),\n strokeWidth: SEAT_RADIUS * 0.55,\n lineCap: 'round',\n lineJoin: 'round',\n opacity: 0,\n listening: false,\n perfectDrawEnabled: false,\n });\n rowLines.push(line);\n bgTarget.add(line);\n }\n\n const nameLabel = new Text({\n x: centroid.x,\n y: centroid.y,\n text: obj.label,\n fontSize: 22,\n fontStyle: '700',\n fontFamily: this.labelFont(),\n fill: '#8b93a7',\n // Dark halo so the label reads over the seat dots at any zoom.\n shadowColor: '#05070c',\n shadowBlur: 6,\n shadowOpacity: 0.9,\n shadowForStrokeEnabled: false,\n listening: false,\n perfectDrawEnabled: false,\n });\n nameLabel.offsetX(nameLabel.width() / 2);\n nameLabel.offsetY(nameLabel.height() / 2);\n bgTarget.add(nameLabel);\n\n const subLabel = new Text({\n x: centroid.x,\n y: centroid.y,\n text: t('map.seatsLeft', { count: free }),\n fontSize: 12,\n fontStyle: '700',\n fontFamily: 'JetBrains Mono, ui-monospace, monospace',\n fill: '#f4f6fb',\n shadowColor: '#05070c',\n shadowBlur: 5,\n shadowOpacity: 0.9,\n shadowForStrokeEnabled: false,\n opacity: 0,\n listening: false,\n perfectDrawEnabled: false,\n });\n subLabel.offsetX(subLabel.width() / 2);\n bgTarget.add(subLabel);\n\n const sec: SectionRender = {\n id: obj.id,\n label: obj.label,\n outline: obj.outline,\n centroid,\n zone: obj.zone,\n memberIds,\n total: memberIds.length,\n free,\n baseFill,\n outlineTint,\n outlinePoly,\n blockPoly,\n rowLines,\n nameLabel,\n subLabel,\n elevation,\n liftGroupBg,\n liftGroupSeat,\n sideFaces,\n };\n for (const id of memberIds) this.seatSection.set(id, sec);\n this.refreshSectionFill(sec);\n this.refreshSectionHeat(sec);\n this.sections.push(sec);\n }\n\n private refreshSectionHeat(sec: SectionRender): void {\n const raw = this.sectionHeat.get(sec.id) ?? (sec.zone ? this.sectionHeat.get(sec.zone) : undefined);\n if (raw == null || raw <= 0) {\n sec.outlinePoly.stroke(rgba(sec.outlineTint, 0.5));\n sec.outlinePoly.fill(rgba(sec.outlineTint, 0.08));\n sec.outlinePoly.strokeWidth(1.75);\n sec.outlinePoly.shadowOpacity(0);\n return;\n }\n const color = lerpColor('#f4b740', '#ef4444', raw);\n sec.outlinePoly.stroke(rgba(color, 0.72 + raw * 0.25));\n sec.outlinePoly.fill(rgba(color, 0.08 + raw * 0.13));\n sec.outlinePoly.strokeWidth(2 + raw * 3.5);\n sec.outlinePoly.shadowColor(color);\n sec.outlinePoly.shadowBlur(4 + raw * 12);\n sec.outlinePoly.shadowOpacity(0.25 + raw * 0.45);\n }\n\n /** Recompute a section's availability-tinted fill + \"N LEFT\" (cheap; on status change). */\n private refreshSectionFill(sec: SectionRender): void {\n sec.blockPoly.fill(this.sectionBlockFill(sec));\n sec.subLabel.text(t('map.seatsLeft', { count: sec.free }));\n sec.subLabel.offsetX(sec.subLabel.width() / 2);\n }\n\n /** True when a section/zone is currently in the `closed` event-state. */\n private isSectionClosed(sec: SectionRender): boolean {\n return this.closedSections.has(sec.id) || (sec.zone != null && this.closedSections.has(sec.zone));\n }\n\n /**\n * The block-fill colour for a section: flat desaturated grey when `closed`,\n * else the availability-darkened category mix; then desaturated toward neutral\n * when another section holds focus (AXS dim treatment).\n */\n private sectionBlockFill(sec: SectionRender): string {\n let fill: string;\n if (this.isSectionClosed(sec)) {\n fill = CLOSED_SECTION_FILL;\n } else {\n const sold = sec.total > 0 ? (sec.total - sec.free) / sec.total : 0;\n fill = darken(sec.baseFill, sold * SOLD_DARKEN);\n }\n if (this.focusedSectionId && sec.id !== this.focusedSectionId && sec.zone !== this.focusedSectionId) {\n fill = lerpColor(fill, FOCUS_NEUTRAL, FOCUS_DESATURATE);\n }\n return fill;\n }\n\n /**\n * Zone rung: one giant screen-constant label per zone (+ optional \"FROM $n\"),\n * shown at the farthest zoom in place of per-section detail. Skipped entirely\n * when the doc declares no zones — sections then stay the far rung (graceful).\n */\n private renderZones(doc: ChartDoc): void {\n if (!doc.zones?.length || !this.sections.length) return;\n const byZone = new Map<string, SectionRender[]>();\n for (const sec of this.sections) {\n if (!sec.zone) continue;\n (byZone.get(sec.zone) ?? byZone.set(sec.zone, []).get(sec.zone)!).push(sec);\n }\n for (const z of doc.zones) {\n const members = byZone.get(z.id);\n if (!members || !members.length) continue;\n // Anchor at the TOPMOST member (min y), not the mean centroid: for a\n // symmetric bowl (a zone = a full ring around the stage) the mean lands on\n // the origin and every zone label stacks on the stage. The topmost member\n // gives a distinct point per ring (labels stack up the vertical axis).\n let anchor = members[0];\n for (const s of members) if (s.centroid.y < anchor.centroid.y) anchor = s;\n const cx = anchor.centroid.x;\n const cy = anchor.centroid.y;\n\n // \"FROM $n\" = cheapest category price found among this zone's member seats.\n let minPrice = Infinity;\n for (const sec of members) {\n for (const id of sec.memberIds) {\n const seat = this.seatById.get(id);\n const p = seat && this.catPrice.get(seat.categoryKey);\n if (typeof p === 'number' && p < minPrice) minPrice = p;\n }\n }\n\n const label = new Text({\n x: cx,\n y: cy,\n text: z.label.toUpperCase(),\n fontSize: 34,\n fontStyle: '800',\n letterSpacing: 2,\n fontFamily: this.labelFont(),\n fill: z.color ?? '#f2f4f8',\n shadowColor: '#05070c',\n shadowBlur: 10,\n shadowOpacity: 0.95,\n shadowForStrokeEnabled: false,\n opacity: 0,\n listening: false,\n perfectDrawEnabled: false,\n });\n label.offsetX(label.width() / 2);\n label.offsetY(label.height() / 2);\n this.bgLayer.add(label);\n\n let sub: Text | null = null;\n if (isFinite(minPrice)) {\n sub = new Text({\n x: cx,\n y: cy,\n text: t('map.fromPrice', { price: formatMoney(minPrice, this.currency) }),\n fontSize: 14,\n fontStyle: '600',\n fontFamily: 'JetBrains Mono, ui-monospace, monospace',\n fill: rgba('#e6e9f0', 0.75),\n opacity: 0,\n listening: false,\n perfectDrawEnabled: false,\n });\n sub.offsetX(sub.width() / 2);\n this.bgLayer.add(sub);\n }\n this.zones.push({ id: z.id, label, sub });\n }\n }\n\n /**\n * THE MELT — a continuous, scale-driven cross-fade across the three rungs:\n * seats ⇄ section blocks ⇄ zone blocks.\n * `blockT` ramps 0→1 as scale falls through [SECTION_PROMINENT, CACHE_THRESHOLD]\n * so the solid fill is fully present exactly as seats become the cached bitmap\n * and fade out; `zoneT` ramps 0→1 across [ZONE_PROMINENT, SECTION_PROMINENT] so\n * per-section detail hands off to giant zone labels. Reduced-motion hard-swaps.\n * Section/zone labels are scale-compensated to hold a roughly constant screen size.\n */\n private applySectionLod(scale: number): void {\n let blockT: number;\n let zoneT: number;\n if (this.reducedMotion) {\n blockT = scale <= SECTION_PROMINENT_SCALE ? 1 : 0;\n zoneT = scale <= ZONE_PROMINENT_SCALE ? 1 : 0;\n } else {\n blockT = clamp((BLOCK_MELT_TOP - scale) / (BLOCK_MELT_TOP - SECTION_PROMINENT_SCALE), 0, 1);\n zoneT = clamp((SECTION_PROMINENT_SCALE - scale) / (SECTION_PROMINENT_SCALE - ZONE_PROMINENT_SCALE), 0, 1);\n }\n // No zones ⇒ skip the zone rung: sections stay the far rung (graceful).\n if (!this.zones.length) zoneT = 0;\n\n // Seats melt out as the block fill melts in (coordinated with the bitmap swap).\n this.seatLayer.opacity(1 - blockT);\n\n // Labels are drawn UPRIGHT (the iso squash is cancelled per-text), so their\n // on-screen size follows the raw stage scale, not the squashed effective one.\n const sx = this.stage.scaleX();\n // Scale-compensate label sizes only when the scale meaningfully changed.\n const rescale = this.lodScale === 0 || Math.abs(scale - this.lodScale) / (this.lodScale || 1) > 0.02;\n if (rescale) this.lodScale = scale;\n\n const focus = this.focusedSectionId;\n for (const sec of this.sections) {\n // AXS focus: non-focused sections dim to ~16%; the focused block stays full.\n const dim = focus && sec.id !== focus && sec.zone !== focus ? FOCUS_DIM_OPACITY : 1;\n sec.blockPoly.opacity(BLOCK_FILL_ALPHA * blockT * dim);\n for (const line of sec.rowLines) line.opacity(blockT * (1 - zoneT) * dim);\n // Name: faint→bright with blockT, then fades out as zones take over.\n sec.nameLabel.fill(lerpColor('#aab3c5', '#ffffff', blockT));\n sec.nameLabel.opacity((1 - zoneT) * dim);\n sec.subLabel.opacity(blockT * (1 - zoneT) * dim);\n if (rescale) {\n this.sizeLabel(sec.nameLabel, SECTION_LABEL_PX / sx, sec.centroid.y - SECTION_SUB_PX / sx);\n this.sizeLabel(sec.subLabel, SECTION_SUB_PX / sx, sec.centroid.y + SECTION_LABEL_PX / sx);\n }\n }\n\n // Fade the big zone labels out as the view tilts into 3D — the raised tiers\n // read clearly on their own, and the overlaid zone text just clutters them.\n const zoneOpacity = zoneT * (1 - this.isoT);\n for (const zone of this.zones) {\n zone.label.opacity(zoneOpacity);\n if (zone.sub) zone.sub.opacity(zoneOpacity);\n if (rescale) {\n const cy = zone.label.y();\n this.sizeLabel(zone.label, ZONE_LABEL_PX / sx, cy);\n if (zone.sub) this.sizeLabel(zone.sub, ZONE_SUB_PX / sx, cy + ZONE_LABEL_PX / sx);\n }\n }\n // Greedy de-collision of the visible label tiers (small canvases stack\n // \"UPPER BOWL\"/\"LOWER BOWL\"/FROM-$ on top of each other otherwise).\n this.decollideRungLabels(sx);\n this.bgLayer.batchDraw();\n }\n\n /**\n * Greedy label de-collision for the zone/section rungs (same approach as the\n * designer's cullRowLabels): price/\"N LEFT\" sublabels are lowest priority and\n * drop first; name labels keep top-to-bottom, left-to-right; anything whose\n * on-screen box (+4px gap) overlaps an already-kept box hides. Recomputed on\n * every LOD pass so hidden labels reappear as zoom spreads them apart.\n * Culling multiplies the opacity applySectionLod just assigned (never raises).\n */\n private decollideRungLabels(sx: number): void {\n const GAP = 4;\n interface Cand { node: Text; tier: number; owner?: Text; box: { x: number; y: number; w: number; h: number } }\n const cands: Cand[] = [];\n const boxOf = (t: Text): { x: number; y: number; w: number; h: number } => {\n // Labels are centred (offset = w/2,h/2); world size × stage scale = screen px.\n const p = this.worldToScreen({ x: t.x(), y: t.y() });\n const w = t.width() * sx;\n const h = t.height() * sx;\n return { x: p.x - w / 2, y: p.y - h / 2, w, h };\n };\n // Tier order = drop priority (higher tier drops first): zone names (0) win\n // over section names (1); price/\"N LEFT\" sublabels (2/3) drop before names.\n // A sublabel records its `owner` name: if the name lost, the sub hides too\n // (never a floating price tag without the zone/section it belongs to).\n for (const zone of this.zones) {\n if (zone.label.opacity() > 0.05) cands.push({ node: zone.label, tier: 0, box: boxOf(zone.label) });\n if (zone.sub && zone.sub.opacity() > 0.05) cands.push({ node: zone.sub, tier: 2, owner: zone.label, box: boxOf(zone.sub) });\n }\n for (const sec of this.sections) {\n if (sec.nameLabel.opacity() > 0.05) cands.push({ node: sec.nameLabel, tier: 1, box: boxOf(sec.nameLabel) });\n if (sec.subLabel.opacity() > 0.05) cands.push({ node: sec.subLabel, tier: 3, owner: sec.nameLabel, box: boxOf(sec.subLabel) });\n }\n if (cands.length < 2) return;\n cands.sort((a, b) => a.tier - b.tier || a.box.y - b.box.y || a.box.x - b.box.x);\n const kept: Cand['box'][] = [];\n const culled = new Set<Text>();\n const collides = (b: Cand['box']): boolean =>\n kept.some((k) =>\n b.x < k.x + k.w + GAP && k.x < b.x + b.w + GAP &&\n b.y < k.y + k.h + GAP && k.y < b.y + b.h + GAP,\n );\n for (const c of cands) {\n if ((c.owner && culled.has(c.owner)) || collides(c.box)) {\n c.node.opacity(0);\n culled.add(c.node);\n } else {\n kept.push(c.box);\n }\n }\n }\n\n /** Set a centred label's world fontSize (for a target screen px) and re-anchor it. */\n private sizeLabel(t: Text, fontSize: number, y: number): void {\n t.fontSize(Math.max(1, fontSize));\n t.offsetX(t.width() / 2);\n t.offsetY(t.height() / 2);\n t.y(y);\n }\n\n /**\n * Map a container-relative screen point back to world coords. Inverts the\n * stage (scale/pos) and, in iso view, the iso affine — so screen-space taps\n * test against the flat world outlines/geometry. Identity-equivalent at isoT=0.\n */\n private screenToWorld(clientPoint: { x: number; y: number }): { x: number; y: number } {\n const s = this.stage.scaleX();\n const iso = { x: (clientPoint.x - this.stage.x()) / s, y: (clientPoint.y - this.stage.y()) / s };\n return this.isoT === 0 ? iso : this.isoInverse(iso);\n }\n\n /** Section id under a container-relative screen point, or null (Slice 5 tap-to-zoom). */\n sectionAt(clientPoint: { x: number; y: number }): string | null {\n if (!this.sections.length) return null;\n const world = this.screenToWorld(clientPoint);\n const hit = this.sections.find((sec) => pointInPolygon(world, sec.outline));\n return hit ? hit.id : null;\n }\n\n /** Seat ids belonging to a section (Slice 5 section-summary card). */\n sectionMembers(id: string): string[] {\n return this.sections.find((s) => s.id === id)?.memberIds.slice() ?? [];\n }\n\n private addCentredLabel(\n layer: Layer,\n text: string,\n x: number,\n y: number,\n fill: string,\n fontSize: number,\n bold: boolean,\n ): void {\n const t = new Text({\n x,\n y,\n text,\n fontSize,\n fontStyle: bold ? '700' : '500',\n fontFamily: this.labelFont(),\n fill,\n listening: false,\n perfectDrawEnabled: false,\n });\n t.offsetX(t.width() / 2);\n t.offsetY(t.height() / 2);\n layer.add(t);\n }\n\n // ---- selection ------------------------------------------------------------\n\n private isSelectable(id: string): boolean {\n // A closed section's seats are never pickable, whatever their raw status.\n if (this.seatInClosedSection(id)) return false;\n const statuses = this.opts.selectableStatuses ?? ['free'];\n return statuses.includes(this.statusById.get(id) ?? 'free');\n }\n\n private toggleSeat(id: string): void {\n if (this.selection.has(id)) {\n this.setSelected(id, false);\n const seat = this.seatById.get(id);\n if (seat) this.opts.onDeselect?.(seat);\n } else {\n if (!this.isSelectable(id)) return;\n if (this.selection.size >= this.opts.maxSelection) return; // ignore beyond cap\n this.setSelected(id, true);\n const seat = this.seatById.get(id);\n if (seat) this.opts.onSelect?.(seat);\n }\n this.overlayLayer.batchDraw();\n }\n\n /**\n * Selection/hover ring color. An explicit theme.selectionColor always wins;\n * otherwise auto-contrast against the effective canvas background — the\n * designer renders on dark (white ring reads), but light-themed hosts (e.g.\n * the DesiPass buyer picker on cream) made the white ring invisible and\n * selected seats looked *disabled*. theme.background is checked first, then\n * the container's computed CSS background (walking up past transparent\n * ancestors). Unknown/unparseable backgrounds keep the dark default.\n */\n private resolveSelectionColor(): string {\n if (this.theme.selectionColor) return this.theme.selectionColor;\n let bg = this.theme.background ?? '';\n if (!bg && typeof getComputedStyle === 'function') {\n let el: HTMLElement | null = this.container;\n while (el) {\n const c = getComputedStyle(el).backgroundColor;\n if (c && c !== 'transparent' && !/^rgba\\(\\s*\\d+\\s*,\\s*\\d+\\s*,\\s*\\d+\\s*,\\s*0\\s*\\)$/.test(c)) {\n bg = c;\n break;\n }\n el = el.parentElement;\n }\n }\n return isLightColor(bg) ? DEF_SELECTION_ON_LIGHT : DEF_SELECTION;\n }\n\n private setSelected(id: string, on: boolean, silent = false): void {\n const c = this.circleById.get(id);\n if (on) {\n this.selection.add(id);\n } else {\n if (this.selectionFocusId === id) this.setSelectionFocus(null);\n this.selection.delete(id);\n }\n this.syncSelectionMarker(id);\n if (c) {\n this.paintSeat(c, id);\n if (!silent && !this.cached) this.seatLayer.batchDraw();\n }\n }\n\n /** Rebuild one marker after selected/held/candidate state changes. */\n private syncSelectionMarker(id: string): void {\n this.selectionMarkers.get(id)?.destroy();\n this.selectionMarkers.delete(id);\n if (!this.selection.has(id) && !this.ownedHold.has(id)) return;\n\n const seat = this.seatById.get(id);\n if (!seat) return;\n const candidate = this.selectionFocusId === id;\n const dims = this.boothDims.get(seat.rowId);\n const marker = new Group({\n x: seat.x,\n y: seat.y,\n rotation: dims?.rotation ?? 0,\n listening: false,\n perfectDrawEnabled: false,\n opacity: this.selectionFocusId && !candidate ? 0.2 : 1,\n });\n const common = {\n stroke: this.effSelection,\n listening: false,\n perfectDrawEnabled: false,\n shadowForStrokeEnabled: false,\n };\n\n if (dims) {\n marker.add(new Rect({\n ...common,\n width: dims.width,\n height: dims.height,\n offsetX: dims.width / 2,\n offsetY: dims.height / 2,\n cornerRadius: 4,\n strokeWidth: candidate ? 4 : 3,\n }));\n if (candidate) {\n marker.add(new Rect({\n ...common,\n width: dims.width + 10,\n height: dims.height + 10,\n offsetX: (dims.width + 10) / 2,\n offsetY: (dims.height + 10) / 2,\n cornerRadius: 7,\n strokeWidth: 2,\n opacity: 0.55,\n }));\n } else {\n const badgeX = Math.max(0, dims.width / 2 - 14);\n const badgeY = -Math.max(0, dims.height / 2 - 14);\n marker.add(new Circle({ x: badgeX, y: badgeY, radius: 10, fill: this.effSelection, listening: false }));\n marker.add(new Line({\n x: badgeX,\n y: badgeY,\n points: [-4.5, 0, -1, 3.5, 5.5, -4.5],\n stroke: isLightColor(this.effSelection) ? '#0b1220' : '#ffffff',\n strokeWidth: 2.4,\n lineCap: 'round',\n lineJoin: 'round',\n listening: false,\n }));\n }\n } else {\n marker.add(new Circle({ ...common, radius: this.seatR + (candidate ? 4.5 : 2.5), strokeWidth: candidate ? 3.5 : 2.5 }));\n if (candidate) {\n marker.add(new Circle({\n ...common,\n radius: this.seatR + 8,\n strokeWidth: 2,\n opacity: 0.55,\n }));\n } else {\n marker.add(new Line({\n points: [-this.seatR * 0.52, 0, -this.seatR * 0.12, this.seatR * 0.4, this.seatR * 0.6, -this.seatR * 0.46],\n stroke: '#ffffff',\n strokeWidth: Math.max(2.6, this.seatR * 0.34),\n lineCap: 'round',\n lineJoin: 'round',\n shadowColor: '#0b1220',\n shadowBlur: 1.5,\n shadowOpacity: 0.55,\n listening: false,\n }));\n }\n }\n\n this.selectionMarkers.set(id, marker);\n this.overlayLayer.add(marker);\n }\n\n // ---- interaction ----------------------------------------------------------\n\n /**\n * The stage scale `focusRegion(id)` would settle at — i.e. the zoom that\n * frames this section in the current viewport. Used to decide whether\n * redirecting a seat tap to section-focus would actually zoom in FURTHER, or\n * whether the section already fills the viewport (small container) so the tap\n * must fall through and pick.\n */\n private sectionFrameScale(id: string): number {\n const sec = this.sections.find((s) => s.id === id);\n if (!sec) return this.stage.scaleX();\n const b = polyBounds(sec.outline);\n const w = this.stage.width();\n const h = this.stage.height();\n const { min, max } = this.zoomBounds();\n const margin = 1.12;\n if (b.width <= 0 || b.height <= 0) return this.stage.scaleX();\n const frameScale = Math.min(w / (b.width * margin), h / (b.height * margin));\n return clamp(Math.max(frameScale, SEAT_FOCUS_SCALE), min, max);\n }\n\n /**\n * Resolve a seat tap: honour the 3D deck-drill and the AXS seat-pick gate,\n * then toggle. The gate (§4) redirects small on-screen seats to section-focus\n * to avoid blind mis-picks at overview scales — but ONLY when focusing would\n * zoom the seat up to a safe size. If we're already focused on the section, or\n * the section already fills the viewport (a narrow — OR even a wide — container\n * frames a big section BELOW LABEL_SCALE), redirecting is a no-op that would\n * leave the seat permanently unpickable (§5 `picking-gate-unreachable`), so we\n * fall through and PICK. This is the invariant: seats are never unpickable.\n */\n private handleSeatTap(id: string): void {\n // In the 3D all-floors overview, tapping a seat enters its deck in 2D\n // rather than selecting (seat picking happens on the flat floor map).\n if (this.stacked && this.opts.onDeckTap) {\n const floorId = this.objectFloor.get(this.seatById.get(id)?.rowId ?? '');\n if (floorId) { this.opts.onDeckTap(floorId); return; }\n }\n if (this.effScale() < LABEL_SCALE && this.sections.length) {\n const sec = this.seatSection.get(id);\n if (sec) {\n const alreadyFocused = this.focusedSectionId === sec.id;\n // Would section-focus zoom us in meaningfully (>2%)? If not, the gate has\n // nowhere left to go — pick instead of deadlocking.\n const canZoomInFurther = this.sectionFrameScale(sec.id) > this.stage.scaleX() * 1.02;\n if (!alreadyFocused && canZoomInFurther) {\n if (this.opts.onSectionTap) this.opts.onSectionTap(sec.id);\n else this.focusSection(sec.id);\n return;\n }\n }\n }\n this.toggleSeat(id);\n }\n\n /**\n * Nearest SELECTABLE seat whose centre is within `slopPx` (screen space) of a\n * seat circle edge, or null. Enlarges the effective tap target for small seats\n * so a near-miss on mobile still lands on the intended seat, without ever\n * hijacking a clean tap on empty space beyond the slop.\n */\n private nearestSeatToScreen(screen: { x: number; y: number }, slopPx: number): string | null {\n const s = this.stage.scaleX() || 1;\n const reachWorld = this.seatR + slopPx / s; // circle radius + finger slack\n const world = this.screenToWorld(screen);\n let best: string | null = null;\n let bestD = reachWorld;\n for (const seat of this.seats) {\n if (!this.selection.has(seat.id) && !this.isSelectable(seat.id)) continue;\n const d = Math.hypot(seat.x - world.x, seat.y - world.y);\n if (d < bestD) {\n bestD = d;\n best = seat.id;\n }\n }\n return best;\n }\n\n private wireInteraction(): void {\n this.seatLayer.on('click tap', (e: KonvaEventObject<Event>) => {\n if (this.moved > PAN_START_SLOP_PX) return; // it was a pan/pinch, not a tap\n const id = seatIdOf(e.target);\n if (!id) return;\n this.handleSeatTap(id);\n });\n\n // Hover (mouse only) via delegated enter/leave on seat circles.\n this.seatLayer.on('mouseover', (e: KonvaEventObject<MouseEvent>) => {\n const id = seatIdOf(e.target);\n if (!id) return;\n const seat = this.seatById.get(id);\n if (!seat) return;\n this.hoverRing.position({ x: seat.x, y: seat.y });\n this.hoverRing.visible(true);\n this.overlayLayer.batchDraw();\n this.container.style.cursor = 'pointer';\n this.opts.onHover?.(seat);\n });\n this.seatLayer.on('mouseout', () => {\n this.hoverRing.visible(false);\n this.overlayLayer.batchDraw();\n this.container.style.cursor = 'default';\n this.opts.onHover?.(null);\n });\n\n this.stage.on('wheel', (e: KonvaEventObject<WheelEvent>) => {\n e.evt.preventDefault();\n // Position from the event itself — Konva's tracked pointer position is\n // unreliable when the last pointer event went elsewhere.\n const r = this.container.getBoundingClientRect();\n const pointer = { x: e.evt.clientX - r.left, y: e.evt.clientY - r.top };\n // Scale with the actual wheel delta so trackpad flings and fast wheels\n // zoom proportionally (a fixed step per event ignores delta magnitude).\n const factor = Math.exp(-e.evt.deltaY * 0.002);\n this.zoomAbout(this.stage.scaleX() * clamp(factor, 0.5, 2), pointer);\n });\n\n // Zoomed out, the seat layer is a non-listening cached bitmap and seats\n // are finger-width anyway — a tap zooms into that area instead of\n // attempting a 4px-precision selection (same behaviour as seats.io).\n this.stage.on('click tap', (e: KonvaEventObject<Event>) => {\n if (this.moved > PAN_START_SLOP_PX) return;\n const pointer = this.stage.getPointerPosition();\n if (!pointer) return;\n // Seats are LIVE (not a cached bitmap): the seatLayer handler above owns\n // direct seat hits. Here we only rescue near-misses — a finger landing just\n // off a small seat picks the nearest one (mobile hit target, §4 hit ≥ 24px).\n // A clean tap on empty space beyond the slop still does nothing.\n if (!this.cached) {\n if (seatIdOf(e.target)) return; // direct hit already handled\n const near = this.nearestSeatToScreen(pointer, SEAT_TAP_SLOP_PX);\n if (near) this.handleSeatTap(near);\n return;\n }\n // 3D all-floors overview: tapping a deck enters that floor in 2D. The iso\n // projection is a layer transform, so the flat screenToWorld hit-test below\n // won't work here — resolve the deck via the iso-aware nearest seat instead.\n if (this.stacked && this.opts.onDeckTap) {\n const floorId = this.deckFloorAt();\n if (floorId) { this.opts.onDeckTap(floorId); return; }\n }\n // A tap inside a section (seats aren't the active rung here — the layer is\n // cached) hands off to the host: fire onSectionTap so the picker can glide\n // in + show the section-summary card (Slice 5). With no handler wired we\n // keep the standalone behaviour of gliding to fit that section.\n if (this.sections.length) {\n const world = this.screenToWorld(pointer);\n const hit = this.sections.find((sn) => pointInPolygon(world, sn.outline));\n if (hit) {\n if (this.opts.onSectionTap) this.opts.onSectionTap(hit.id);\n else this.focusRegion(hit.id);\n return;\n }\n }\n const target = Math.max(SEAT_LEGIBLE_SCALE * 1.2, this.stage.scaleX() * 2.5);\n this.zoomAbout(target, pointer);\n });\n }\n\n /**\n * Which deck (floor) a screen tap landed on in the 3D stacked overview. The\n * seat layer is melt-cached at that zoom so individual seat nodes aren't\n * hit-testable; instead we invert the iso+stage transform via the layer's\n * relative pointer and take the nearest seat's floor. Only the floor matters,\n * so within-floor elevation offsets don't affect the result. Null if none.\n */\n private deckFloorAt(): string | null {\n if (!this.objectFloor.size) return null;\n const p = this.seatLayer.getRelativePointerPosition();\n if (!p) return null;\n let best: string | null = null;\n let bestD = Infinity;\n for (const s of this.seats) {\n const dx = s.x - p.x;\n const dy = s.y - p.y;\n const d = dx * dx + dy * dy;\n if (d < bestD) { bestD = d; best = s.rowId; }\n }\n return best ? this.objectFloor.get(best) ?? null : null;\n }\n\n // ---- Pan & pinch (raw pointer events — mouse, touch and pen alike) --------\n\n private toLocal(e: PointerEvent): { x: number; y: number } {\n const r = this.container.getBoundingClientRect();\n return { x: e.clientX - r.left, y: e.clientY - r.top };\n }\n\n // NOTE: no setPointerCapture here — capturing on the container retargets\n // pointer events away from Konva's canvas, killing its click/tap/hover\n // pipeline. We rely on bubbling instead.\n private onPointerDown = (e: PointerEvent): void => {\n this.cancelGlide(); // grabbing the map cancels an in-flight glide\n const local = this.toLocal(e);\n this.pointers.set(e.pointerId, local);\n if (this.pointers.size === 1) {\n this.moved = 0;\n this.pinch = null;\n this.panStart = local;\n this.panStarted = false;\n // Manage-mode rubber-band marquee (option-gated — buyer pan is byte-\n // identical when manageMode is off). A mouse/pen primary-button drag at\n // the seats rung selects instead of panning; touch keeps single-finger\n // pan (pinch zooms) and a middle-button drag (button !== 0) still pans.\n // Disabled below the seats rung so the organizer zooms in first.\n if (\n this.opts.manageMode && this.opts.marqueeSelect &&\n e.pointerType !== 'touch' && e.button === 0 &&\n this.getRung() === 'seats'\n ) {\n this.beginMarquee(local);\n this.panLast = null;\n } else {\n this.panLast = local;\n }\n } else if (this.pointers.size === 2) {\n // A second finger converts an in-progress marquee into a pinch-zoom.\n if (this.marquee) this.cancelMarquee();\n // Anchor the whole pinch to its starting geometry: scale follows the\n // finger-distance ratio and the world point under the midpoint stays\n // glued to the midpoint. No per-event compounding → no drift.\n const [a, b] = [...this.pointers.values()];\n const mid = { x: (a.x + b.x) / 2, y: (a.y + b.y) / 2 };\n const s = this.stage.scaleX();\n this.pinch = {\n startDist: Math.hypot(b.x - a.x, b.y - a.y),\n startScale: s,\n worldMid: { x: (mid.x - this.stage.x()) / s, y: (mid.y - this.stage.y()) / s },\n };\n this.panLast = null;\n this.panStart = null;\n this.panStarted = true;\n this.moved = PAN_START_SLOP_PX + 1;\n }\n };\n\n private onPointerMove = (e: PointerEvent): void => {\n if (!this.pointers.has(e.pointerId)) return;\n e.preventDefault();\n const p = this.toLocal(e);\n this.pointers.set(e.pointerId, p);\n if (this.pointers.size === 1 && this.panStart) {\n this.moved = Math.max(this.moved, Math.hypot(p.x - this.panStart.x, p.y - this.panStart.y));\n } else if (this.pointers.size >= 2) {\n this.moved = PAN_START_SLOP_PX + 1;\n }\n\n if (this.marquee) {\n this.updateMarquee(p);\n return;\n }\n if (this.pinch && this.pointers.size >= 2) {\n const [a, b] = [...this.pointers.values()];\n const dist = Math.hypot(b.x - a.x, b.y - a.y);\n if (this.pinch.startDist < 1) return;\n const mid = { x: (a.x + b.x) / 2, y: (a.y + b.y) / 2 };\n const { min, max } = this.zoomBounds();\n const scale = clamp(this.pinch.startScale * (dist / this.pinch.startDist), min, max);\n this.stage.scale({ x: scale, y: scale });\n this.stage.position({\n x: mid.x - this.pinch.worldMid.x * scale,\n y: mid.y - this.pinch.worldMid.y * scale,\n });\n this.stage.batchDraw();\n this.scheduleViewChange();\n } else if (this.panLast && this.pointers.size === 1) {\n // Keep the camera still through normal finger jitter. Aside from making\n // taps feel steadier, this lets Konva deliver the section tap instead of\n // losing it to a one- or two-pixel accidental drag.\n if (!this.panStarted) {\n if (this.moved <= PAN_START_SLOP_PX) return;\n this.panStarted = true;\n }\n this.stage.position({\n x: this.stage.x() + (p.x - this.panLast.x),\n y: this.stage.y() + (p.y - this.panLast.y),\n });\n this.panLast = p;\n this.stage.batchDraw();\n this.scheduleViewChange();\n }\n };\n\n private onPointerEnd = (e: PointerEvent): void => {\n // Finishing a manage-mode marquee: compute the selection on pointer-UP.\n if (this.marquee) {\n this.finishMarquee();\n this.pointers.delete(e.pointerId);\n if (this.pointers.size === 0) this.panLast = null;\n return;\n }\n this.pointers.delete(e.pointerId);\n if (this.pointers.size < 2) this.pinch = null;\n if (this.pointers.size === 1) {\n // pinch → single finger: continue as a pan without jumping\n this.panLast = [...this.pointers.values()][0];\n this.panStart = this.panLast;\n this.panStarted = true;\n }\n if (this.pointers.size === 0) {\n this.panLast = null;\n this.panStart = null;\n this.panStarted = false;\n this.afterViewChange();\n }\n };\n\n /**\n * Min is chart-relative (never lose the room); max is absolute so seats\n * reach a readable size on any chart, however large the venue.\n */\n private zoomBounds(): { min: number; max: number } {\n let min = 0.5 * this.fitScale;\n // When the chart has zones, the zone rung lives at an ABSOLUTE scale\n // (ZONE_PROMINENT_SCALE). On a large venue `0.5·fitScale` can sit above it,\n // making the zone overview unreachable by zooming out — allow a touch more\n // room so the rung is actually reachable (zone-charts only).\n if (this.zones.length) min = Math.min(min, ZONE_PROMINENT_SCALE * 0.9);\n return { min, max: Math.max(10 * this.fitScale, 4) };\n }\n\n /** Zoom so `clientPoint` (stage-relative px) stays fixed under the cursor. */\n private zoomAbout(nextScale: number, clientPoint: { x: number; y: number }): void {\n const { min, max } = this.zoomBounds();\n const scale = clamp(nextScale, min, max);\n const old = this.stage.scaleX();\n if (scale === old) return;\n const worldX = (clientPoint.x - this.stage.x()) / old;\n const worldY = (clientPoint.y - this.stage.y()) / old;\n this.stage.scale({ x: scale, y: scale });\n this.stage.position({\n x: clientPoint.x - worldX * scale,\n y: clientPoint.y - worldY * scale,\n });\n this.afterViewChange();\n this.stage.batchDraw();\n }\n\n /** Zoom + pan so world-rect `b` fills the viewport (with a small margin). */\n private zoomToBounds(\n b: { x: number; y: number; width: number; height: number },\n minScale?: number,\n ): void {\n const w = this.stage.width();\n const h = this.stage.height();\n const { min, max } = this.zoomBounds();\n const margin = 1.12;\n const frameScale = Math.min(w / (b.width * margin), h / (b.height * margin));\n const scale = clamp(Math.max(frameScale, minScale ?? min), min, max);\n this.stage.scale({ x: scale, y: scale });\n this.stage.position({\n x: w / 2 - (b.x + b.width / 2) * scale,\n y: h / 2 - (b.y + b.height / 2) * scale,\n });\n this.afterViewChange();\n this.stage.batchDraw();\n }\n\n /**\n * Smoothly glide the camera to frame a section (by id) or a world-space bounds\n * rect — the Slice 5 \"glide in\". Pan+zoom tween over ~450ms easeInOutCubic; the\n * melt/LOD rides the camera every frame. `prefers-reduced-motion` (or\n * `opts.animate === false`) snaps via zoomToBounds. A grab (pointer-down) or a\n * newer glide cancels an in-flight one.\n */\n focusRegion(\n target: string | { x: number; y: number; width: number; height: number },\n opts?: { animate?: boolean; minScale?: number },\n ): void {\n const b =\n typeof target === 'string'\n ? (() => {\n const sec = this.sections.find((s) => s.id === target);\n return sec ? polyBounds(sec.outline) : null;\n })()\n : target;\n if (!b) return;\n this.cancelGlide();\n if (opts?.animate === false || this.reducedMotion) {\n this.zoomToBounds(b, opts?.minScale);\n return;\n }\n const w = this.stage.width();\n const h = this.stage.height();\n const { min, max } = this.zoomBounds();\n const margin = 1.12;\n const frameScale = Math.min(w / (b.width * margin), h / (b.height * margin));\n const toScale = clamp(Math.max(frameScale, opts?.minScale ?? min), min, max);\n const toX = w / 2 - (b.x + b.width / 2) * toScale;\n const toY = h / 2 - (b.y + b.height / 2) * toScale;\n const fromScale = this.stage.scaleX();\n const fromX = this.stage.x();\n const fromY = this.stage.y();\n if (Math.abs(toScale - fromScale) < 1e-4 && Math.abs(toX - fromX) < 0.5 && Math.abs(toY - fromY) < 0.5) {\n this.afterViewChange();\n return;\n }\n const start = performance.now();\n const DUR = 450;\n const step = (now: number): void => {\n if (this.destroyed) { this.glideRaf = 0; return; }\n const raw = Math.min(1, (now - start) / DUR);\n const e = raw < 0.5 ? 4 * raw * raw * raw : 1 - Math.pow(-2 * raw + 2, 3) / 2;\n const sc = fromScale + (toScale - fromScale) * e;\n this.stage.scale({ x: sc, y: sc });\n this.stage.position({ x: fromX + (toX - fromX) * e, y: fromY + (toY - fromY) * e });\n this.updateLOD(); // the melt cross-fades as the camera rides in\n this.scheduleViewChange();\n this.stage.batchDraw();\n if (raw < 1) {\n this.glideRaf = requestAnimationFrame(step);\n } else {\n this.glideRaf = 0;\n this.afterViewChange();\n }\n };\n this.glideRaf = requestAnimationFrame(step);\n }\n\n /** Cancel an in-flight camera glide (a grab or a newer glide interrupts it). */\n private cancelGlide(): void {\n if (this.glideRaf) {\n cancelAnimationFrame(this.glideRaf);\n this.glideRaf = 0;\n }\n }\n\n /** Current LOD rung derived from effective zoom — drives the ZONES/SECTIONS/SEATS pill. */\n getRung(): LodRung {\n const scale = this.effScale();\n if (scale >= CACHE_THRESHOLD) return 'seats';\n if (this.zones.length && scale < ZONE_PROMINENT_SCALE) return 'zones';\n return 'sections';\n }\n\n /** Jump the camera to a rung's zoom band, centred on the chart (glided). */\n setRung(rung: LodRung): void {\n if (rung === 'zones') {\n this.cancelGlide();\n this.zoomToFit();\n return;\n }\n const target =\n rung === 'sections'\n ? (SECTION_PROMINENT_SCALE + CACHE_THRESHOLD) / 2\n : Math.max(SEAT_FOCUS_SCALE, CACHE_THRESHOLD * 1.3);\n const w = this.stage.width();\n const h = this.stage.height();\n const cx = this.bounds.x + this.bounds.width / 2;\n const cy = this.bounds.y + this.bounds.height / 2;\n const bw = w / (target * 1.12);\n const bh = h / (target * 1.12);\n this.focusRegion({ x: cx - bw / 2, y: cy - bh / 2, width: bw, height: bh });\n }\n\n /** Recompute LOD (cache/labels) after any pan/zoom settles. */\n private afterViewChange(): void {\n this.updateLOD();\n this.updateLabels();\n this.scheduleViewChange();\n }\n\n /** rAF-coalesced `onViewChange` — at most one host callback per animation frame. */\n private scheduleViewChange(): void {\n if (this.viewChangeRaf) return;\n this.viewChangeRaf = requestAnimationFrame(() => {\n this.viewChangeRaf = 0;\n this.opts.onViewChange?.();\n });\n }\n\n private updateLOD(): void {\n // Effective scale folds in the iso y-squash (smaller ⇒ seats read smaller),\n // so LOD/melt thresholds trip correctly in 3D view. Equals the raw stage\n // scale at isoT=0 → flat behaviour is unchanged.\n const scale = this.effScale();\n if (this.hasSections) this.applySectionLod(scale);\n const shouldCache = scale < CACHE_THRESHOLD;\n if (shouldCache && !this.cached) {\n this.cacheSeatLayer();\n } else if (!shouldCache && this.cached) {\n this.seatLayer.clearCache();\n this.seatLayer.listening(true);\n this.cached = false;\n this.seatLayer.batchDraw();\n }\n }\n\n /** Rebuild the seat-layer bitmap synchronously (no paint). Shared by the\n * debounced cacheSeatLayer() and the synchronous forceDraw() catch-up. */\n private rebuildSeatCache(): void {\n // Cache at ~screen resolution: bitmap px ≈ on-screen px, so a huge chart in\n // chart-units doesn't blow up into a gigapixel canvas when zoomed out.\n const pr = clamp(this.stage.scaleX() * this.dpr, 0.15, 2);\n this.seatLayer.clearCache();\n this.seatLayer.cache({ pixelRatio: pr });\n this.seatLayer.listening(false);\n this.cached = true;\n }\n\n private cacheSeatLayer(): void {\n this.rebuildSeatCache();\n this.seatLayer.batchDraw();\n }\n\n /**\n * SYNCHRONOUS repaint that bypasses requestAnimationFrame — see the\n * ISeatmapRenderer.forceDraw() contract. Chrome pauses rAF (and therefore\n * Konva's batchDraw) on hidden/backgrounded/occluded tabs, so seat-status\n * deltas applied via setStatus() mutate the scene graph but never reach the\n * canvas until the tab is foregrounded. This flushes the cache-debounce and\n * paints every layer setStatus() can touch, immediately.\n *\n * Additive: the foreground path never calls this, so foreground behaviour is\n * byte-identical.\n */\n forceDraw(): void {\n // Flush any pending cache-debounce (setStatus coalesces bursts behind a\n // 150ms setTimeout) so a returning tab isn't left showing a stale bitmap.\n if (this.recacheTimer) {\n clearTimeout(this.recacheTimer);\n this.recacheTimer = null;\n // Fold the coalesced deltas into the bitmap now, synchronously.\n this.rebuildSeatCache();\n }\n // Synchronous paint of every layer setStatus() may repaint. Layer.draw()\n // renders on the calling thread, unlike batchDraw()'s rAF schedule.\n this.bgLayer.draw();\n this.seatLayer.draw();\n this.overlayLayer.draw();\n }\n\n private updateLabels(): void {\n const show = this.effScale() > LABEL_SCALE;\n this.labelGroup.destroyChildren();\n if (!show) {\n this.overlayLayer.batchDraw();\n return;\n }\n // Visible chart rect (with a small margin) in chart coordinates.\n const s = this.stage.scaleX();\n const x0 = (-this.stage.x()) / s;\n const y0 = (-this.stage.y()) / s;\n const x1 = (this.stage.width() - this.stage.x()) / s;\n const y1 = (this.stage.height() - this.stage.y()) / s;\n\n let count = 0;\n for (const seat of this.seats) {\n // Booth labels already live beside their rectangular shape in seatLayer\n // (renderBoothUnit). Adding them again to the zoom-only overlay produces\n // the offset/doubled numbers visible at close zoom levels.\n if (seat.kind === 'booth') continue;\n if (seat.x < x0 || seat.x > x1 || seat.y < y0 || seat.y > y1) continue;\n const status = this.statusById.get(seat.id) ?? 'free';\n const statusCue = status === 'booked' ? '×' : status === 'held' && !this.ownedHold.has(seat.id) ? 'H' : null;\n const t = new Text({\n x: seat.x,\n y: seat.y,\n text: statusCue ?? seat.label,\n fontSize: statusCue ? (status === 'booked' ? 13 : 8) : 7,\n fontStyle: statusCue ? '800' : '600',\n fontFamily: this.labelFont(),\n fill: statusCue ? '#ffffff' : (this.theme.seatLabelColor ?? DEF_SEAT_LABEL),\n listening: false,\n perfectDrawEnabled: false,\n });\n // Auto-fit: shrink long labels (e.g. \"T10-10\") so they never spill out of\n // the seat circle. Down to a legibility floor; below that the label is\n // dropped rather than rendered as an unreadable speck.\n const maxW = this.seatR * 2 - 3;\n if (t.width() > maxW) t.fontSize(Math.max(4, (t.fontSize() * maxW) / t.width()));\n if (t.fontSize() < 4.2) { t.destroy(); continue; }\n t.offsetX(t.width() / 2);\n t.offsetY(t.height() / 2);\n this.labelGroup.add(t);\n if (++count >= MAX_LABELS) break;\n }\n // Keep freshly-built seat labels upright under the iso layer skew.\n if (this.isoT > 0) this.applyUprightLabels();\n this.overlayLayer.batchDraw();\n }\n\n private handleResize(): void {\n const w = this.container.clientWidth || 1;\n const h = this.container.clientHeight || 1;\n if (w === this.stage.width() && h === this.stage.height()) return;\n this.stage.size({ width: w, height: h });\n // Keep the chart framed; refit is the least surprising behaviour on resize.\n this.zoomToFit();\n }\n\n private startFpsLoop(): void {\n const tick = (now: number) => {\n if (!this.lastFpsAt) this.lastFpsAt = now;\n this.frames++;\n const elapsed = now - this.lastFpsAt;\n if (elapsed >= 1000) {\n this.opts.onFps?.(Math.round((this.frames * 1000) / elapsed));\n this.frames = 0;\n this.lastFpsAt = now;\n }\n this.rafId = requestAnimationFrame(tick);\n };\n this.rafId = requestAnimationFrame(tick);\n }\n}\n\nexport function createRenderer(container: HTMLDivElement, opts?: RendererOptions): ISeatmapRenderer {\n return new SeatmapRenderer(container, opts);\n}\n","/**\n * Money formatting — the ONE place currency rendering happens.\n *\n * Ticket money is multi-currency: the org sets a default and each event can\n * override it (ISO 4217 code delivered with the event/chart payload). Until\n * those backend fields land, callers fall back to DEFAULT_CURRENCY, which is\n * kept at EUR so live buyer pages render exactly what they rendered when the\n * symbol was hardcoded. Flipping an org to USD/INR/… later is data, not code.\n *\n * Amounts are in MAJOR units (45 === €45) matching Category.price in\n * src/core/types.ts. If/when backend money fields arrive in minor units,\n * convert at the API boundary, not here.\n */\n\n// App-wide fallback when no org currency is available (unauthed/demo surfaces).\n// Owner decision 2026-07-08: USD default (orgs.currency also defaults to USD).\nexport const DEFAULT_CURRENCY = 'USD';\n\n/** BCP 47 locale used for number/date rendering; kept in sync by src/i18n. */\nlet displayLocale: string | undefined;\n\nexport function setMoneyLocale(locale: string | undefined): void {\n displayLocale = locale;\n}\n\nconst formatterCache = new Map<string, Intl.NumberFormat>();\n\nfunction formatter(currency: string, digits: number | undefined): Intl.NumberFormat {\n const key = `${displayLocale ?? ''}|${currency}|${digits ?? 'auto'}`;\n let fmt = formatterCache.get(key);\n if (!fmt) {\n fmt = new Intl.NumberFormat(displayLocale, {\n style: 'currency',\n currency,\n minimumFractionDigits: digits,\n maximumFractionDigits: digits,\n });\n formatterCache.set(key, fmt);\n }\n return fmt;\n}\n\n/**\n * \"€45\" / \"$1,500\" / \"45 €\" (locale-dependent placement).\n * Whole amounts render without \".00\" (design shows \"$45\", \"$120\"); pass\n * `fractionDigits` for fixed precision (e.g. 3 for \"$0.045 / credit\").\n */\nexport function formatMoney(\n amount: number,\n currency: string = DEFAULT_CURRENCY,\n fractionDigits?: number,\n): string {\n const digits = fractionDigits ?? (Number.isInteger(amount) ? 0 : undefined);\n return formatter(currency, digits).format(amount);\n}\n\n/** Bare symbol for input adornments (\"€\", \"$\", \"₹\"). */\nexport function currencySymbol(currency: string = DEFAULT_CURRENCY): string {\n const part = formatter(currency, 0)\n .formatToParts(0)\n .find((p) => p.type === 'currency');\n return part?.value ?? currency;\n}\n","/**\n * English bundle — the reference dictionary every other locale is checked\n * against. Keys are added as pages route their strings through t() during\n * the design port (docs/design-port-plan.md); buyer-surface keys land first.\n *\n * Conventions:\n * - flat dot-namespaced keys: \"<surface>.<element>\" (picker.holdSeats)\n * - {name} interpolation, {count} reserved for tCount plural keys\n * - plural keys end in \".one\" / \".other\" (Intl.PluralRules categories)\n */\n\nimport type { Dict } from '../index';\n\nexport const en: Dict = {\n // shared\n 'common.cancel': 'Cancel',\n 'common.close': 'Close',\n 'common.done': 'Done',\n 'common.copied': '✓ Copied',\n\n // buyer picker (extraction in progress — P4 of the port plan)\n 'picker.holdSeats': 'Hold seats & checkout',\n 'picker.completeBooking': 'Complete booking',\n 'picker.seatsHeld': 'Seats held — {time}',\n 'picker.holdExpired': 'Your hold expired — the seats were released. Pick again.',\n 'picker.seatTaken': 'Seat {label} was just taken by another buyer.',\n 'picker.poweredBy': 'Powered by SeatLayer',\n 'picker.testMode': 'TEST MODE',\n 'picker.colorblind': 'Colorblind-friendly colors',\n 'picker.orphanHint': 'This leaves a single seat stranded — consider shifting one seat over.',\n 'picker.seats.one': '{count} seat',\n 'picker.seats.other': '{count} seats',\n\n // renderer (drawn on the Konva map — shared by the embed SDK)\n 'map.aria': 'Seating map. Use arrow keys to move between seats, Enter to select.',\n 'map.seatsLeft': '{count} LEFT',\n 'map.fromPrice': 'FROM {price}',\n 'map.statusHeld': 'On hold',\n 'map.statusTaken': 'Taken',\n\n // buyer picker page (src/pages/PickerPage.tsx)\n 'picker.language': 'Language',\n 'picker.zoomToFit': 'Zoom to fit',\n 'picker.viewMode': 'View mode',\n 'picker.floor': 'Floor',\n 'picker.zoomLevel': 'Zoom level',\n 'picker.rungTip.zones': 'Venue overview — groups of sections such as North Stand or VIP',\n 'picker.rungTip.sections': 'Section blocks — category-mix fill + availability tint',\n 'picker.rungTip.seats': 'Individual seats — blocks melt into dots',\n 'picker.rungLabel.zones': 'ZONES',\n 'picker.rungLabel.sections': 'SECTIONS',\n 'picker.rungLabel.seats': 'SEATS',\n 'picker.sectionSummaryAria': '{label} section summary',\n 'picker.closeSectionSummary': 'Close section summary',\n 'picker.seatsLeftInSection.one': '{count} seat left',\n 'picker.seatsLeftInSection.other': '{count} seats left',\n 'picker.overview': 'Overview',\n 'picker.tapSeatHint': 'Tap any seat to check its view',\n 'picker.chartSize': 'Chart size',\n 'picker.custom': 'Custom',\n 'picker.categories': 'Categories',\n 'picker.accessibility': 'Accessibility',\n 'picker.showAnyAccessible': 'Show any accessible seat',\n 'picker.any': 'Any',\n 'picker.yourSeats': 'Your seats',\n 'picker.emptySeats': 'Tap seats on the map',\n 'picker.emptySeatsWithGa': 'Tap seats on the map · tap a standing area for GA tickets',\n 'picker.oneFewer': 'One fewer',\n 'picker.oneMore': 'One more',\n 'picker.remove': 'Remove {label}',\n 'picker.ticketTierFor': 'Ticket tier for {label}',\n 'picker.total': 'Total: {amount}',\n 'picker.viewFromSeat': 'View from seat {label}',\n 'picker.real360': 'REAL 360°',\n 'picker.preview': 'PREVIEW',\n 'picker.open360': 'Open 360° view',\n 'picker.sightline': '≈ {rows} rows from stage · {angle}° off-center',\n 'picker.bookedDemo': 'Booked! (demo)',\n 'picker.bookButton.one': 'Book {count} ticket — {amount}',\n 'picker.bookButton.other': 'Book {count} tickets — {amount}',\n 'picker.simulateCrowd': 'Simulate crowd: {state}',\n 'picker.on': 'ON',\n 'picker.off': 'OFF',\n 'picker.panorama360': '360° venue photo',\n 'picker.illustrationCaption': 'illustration · ≈ {m} m from stage',\n};\n","/**\n * i18n core — deliberately tiny and framework-free so the embed SDK can share\n * it without dragging in a runtime library (the 60KB-gzipped SDK budget is a\n * product contract).\n *\n * Scope (docs/design-port-plan.md): the buyer surface (picker, public event\n * page, SDK) ships fully translated in en/es/de/fr; dashboard pages route\n * their strings through t() as they are rebuilt but ship English this round.\n *\n * Keys are flat dot-namespaced strings (\"picker.holdSeats\"). Interpolation\n * uses {name} placeholders. Missing keys fall back to English, then to the\n * key itself — a page never crashes over a translation.\n */\n\nimport { setMoneyLocale } from '../lib/money';\nimport { en } from './locales/en';\n\nexport type Locale = 'en' | 'es' | 'de' | 'fr';\nexport const SUPPORTED_LOCALES: Locale[] = ['en', 'es', 'de', 'fr'];\n\nexport type Dict = Record<string, string>;\n\nconst bundles: Partial<Record<Locale, Dict>> = { en };\n\n/** Extra strings layered over the active bundle (SDK white-label overrides). */\nlet overrides: Dict = {};\n\nlet active: Locale = 'en';\n\n/** explicit setting → stored preference → browser language → en */\nexport function resolveLocale(explicit?: string | null, stored?: string | null): Locale {\n for (const candidate of [explicit, stored, typeof navigator !== 'undefined' ? navigator.language : null]) {\n if (!candidate) continue;\n const base = candidate.toLowerCase().split('-')[0] as Locale;\n if (SUPPORTED_LOCALES.includes(base)) return base;\n }\n return 'en';\n}\n\nexport function getLocale(): Locale {\n return active;\n}\n\n/**\n * Set the active locale. Locale bundles other than English are registered by\n * the surface that needs them (the picker imports its own es/de/fr bundles;\n * the dashboard stays English until its translations ship).\n */\nexport function setLocale(locale: Locale, bundle?: Dict): void {\n if (bundle) bundles[locale] = { ...bundles[locale], ...bundle };\n active = bundles[locale] ? locale : 'en';\n setMoneyLocale(active);\n if (typeof document !== 'undefined') document.documentElement.lang = active;\n}\n\nexport function setStringOverrides(next: Dict): void {\n overrides = next;\n}\n\nconst PLACEHOLDER = /\\{(\\w+)\\}/g;\n\nexport function t(key: string, vars?: Record<string, string | number>): string {\n const raw = overrides[key] ?? bundles[active]?.[key] ?? en[key] ?? key;\n if (!vars) return raw;\n return raw.replace(PLACEHOLDER, (_, name: string) => String(vars[name] ?? `{${name}}`));\n}\n\n/** \"1 seat\" / \"3 seats\" without hand-rolled concatenation. */\nexport function tCount(key: string, count: number, vars?: Record<string, string | number>): string {\n const rule = new Intl.PluralRules(active).select(count);\n const exact = overrides[`${key}.${rule}`] ?? bundles[active]?.[`${key}.${rule}`] ?? en[`${key}.${rule}`];\n const raw = exact ?? overrides[`${key}.other`] ?? bundles[active]?.[`${key}.other`] ?? en[`${key}.other`] ?? key;\n return raw.replace(PLACEHOLDER, (_, name: string) => String({ count, ...vars }[name] ?? `{${name}}`));\n}\n\nexport function formatDate(value: number | Date, opts?: Intl.DateTimeFormatOptions): string {\n return new Intl.DateTimeFormat(active, opts ?? { dateStyle: 'medium', timeStyle: 'short' }).format(value);\n}\n","/**\n * Orphan-seat detection for MANUAL selection — the client-side sibling of the\n * server's best-available orphan avoidance (workers/api/src/bestAvailable):\n * a \"stranded single\" is a free seat whose both same-row neighbors are\n * unavailable (non-free or currently selected). The picker uses this to show\n * a non-blocking hint; nothing is ever prevented.\n */\nimport type { ExpandedSeat, SeatStatus } from './types';\n\n/** Numeric seat index from the stable id (`${rowId}:${index}`). */\nfunction seatIndex(id: string): number {\n const n = Number(id.slice(id.lastIndexOf(':') + 1));\n return Number.isFinite(n) ? n : -1;\n}\n\n/**\n * Free seats stranded by the current selection: both same-row neighbors exist\n * and are unavailable, and at least one neighbor is part of `selectedIds` —\n * so pre-existing single gaps (caused by earlier buyers) never nag.\n * Booth units are ignored (no row adjacency).\n */\nexport function strandedSingles(\n seats: Iterable<ExpandedSeat>,\n statusOf: (seatId: string) => SeatStatus,\n selectedIds: ReadonlySet<string>,\n): ExpandedSeat[] {\n // Group by row, ordered by index, skipping booths.\n const rows = new Map<string, ExpandedSeat[]>();\n for (const s of seats) {\n if (s.kind === 'booth') continue;\n const list = rows.get(s.rowId);\n if (list) list.push(s);\n else rows.set(s.rowId, [s]);\n }\n\n const unavailable = (s: ExpandedSeat): boolean =>\n selectedIds.has(s.id) || statusOf(s.id) !== 'free';\n\n const out: ExpandedSeat[] = [];\n for (const list of rows.values()) {\n if (list.length < 3) continue;\n list.sort((a, b) => seatIndex(a.id) - seatIndex(b.id));\n for (let i = 1; i < list.length - 1; i++) {\n const seat = list[i];\n if (unavailable(seat)) continue; // not free (or selected) → not stranded\n const left = list[i - 1];\n const right = list[i + 1];\n // Neighbors must be physically adjacent (index gap of 1) — a labelled\n // aisle gap in the numbering doesn't strand anyone.\n if (seatIndex(seat.id) - seatIndex(left.id) !== 1 || seatIndex(right.id) - seatIndex(seat.id) !== 1) continue;\n if (!unavailable(left) || !unavailable(right)) continue;\n if (!selectedIds.has(left.id) && !selectedIds.has(right.id)) continue;\n out.push(seat);\n }\n }\n return out;\n}\n","/**\n * PickerController — the single, framework-agnostic buyer-picker core.\n *\n * Consolidates the transport + booking logic that was copy-pasted across\n * sdk/src/SeatingChart.ts, src/pages/PublicEventPage.tsx and PickerPage.tsx:\n * fetch the published chart, mount the Konva renderer, seed statuses from a REST\n * snapshot, keep them live over a WebSocket (reconnect w/ backoff, re-snapshot on\n * every open), and run the hold → book state machine (best-available, hold reuse,\n * per-label partial release, 409 semantics, server-authoritative hold expiry).\n *\n * The SDK, the live buyer page, and the demo picker all drive this one class;\n * presentation (confirm card, legend, cart, etc.) lives in the consumers.\n *\n * Transport is injected (PickerTransport) so the SDK can use its CORS-trivial\n * PubApi while the dashboard uses an adapter over src/lib/api.ts.\n */\nimport { createRenderer } from '../engine/SeatmapRenderer';\nimport { allObjects, expandChart } from '../core/layout';\nimport { applyHidden, computeSections } from '../core/sections';\nimport { strandedSingles } from '../core/orphans';\nimport { t } from '../i18n';\nimport type {\n CategoryTier,\n ChartDoc,\n ExpandedSeat,\n ISeatmapRenderer,\n LodRung,\n RendererCallbacks,\n SeatStatus,\n SectionObject,\n} from '../core/types';\nimport { gaAreasOf, gaUnitLabels } from '../core/ga';\n\nconst DEFAULT_MAX_SELECTION = 10;\nconst MAX_BACKOFF_MS = 15_000;\n\nexport interface PickerSeat {\n id: string;\n label: string;\n categoryKey: string;\n /** Price for the chosen tier when the category has tiers, else the base price. */\n price: number;\n /** Ticket tiers the seat's category offers (Adult/Child/…); absent when none. */\n tiers?: CategoryTier[];\n /** The chosen tier's id — defaults to the first tier; absent when no tiers. */\n tierId?: string;\n}\n\n/**\n * Rich hover payload for seat tooltips — the PickerSeat plus everything a\n * buyer-facing popover needs: category label + swatch color, live status and\n * the chart currency. Emitted by `onSeatHover` (null on hover-out).\n */\nexport interface SeatHoverDetails extends PickerSeat {\n categoryLabel: string;\n categoryColor: string;\n status: SeatStatus;\n currency: string;\n /** Human-readable spatial context for hover and confirmation UI. */\n sectionLabel?: string;\n rowLabel?: string;\n seatNumber?: string;\n}\n\nexport interface HoldConflict {\n label: string;\n status: string;\n}\n\n/** An open hold — its id, the labels it covers, and the server's expiry time (ms epoch). */\nexport interface HoldInfo {\n holdId: string;\n labels: string[];\n expiresAt: number;\n /** The held seats with their chosen ticket tier — what the host books against. */\n seats: PickerSeat[];\n /** Server-authoritative commercial line items, including GA units and resolved prices. */\n items?: HoldServerItem[];\n}\n\n/** One category's slice of a section (dot + price + count) for the summary card. */\nexport interface SectionCategory {\n key: string;\n label: string;\n color: string;\n price: number;\n count: number;\n}\n\n/**\n * Big-venue section-summary — everything the tapped-section card renders: name,\n * its zone, live seats-left, price range, and the per-category breakdown.\n * Computed from the renderer's spatial section membership (Slice 5).\n */\nexport interface SectionSummary {\n id: string;\n label: string;\n /** Zone label (from ChartDoc.zones); '' when the section has no zone. */\n zoneLabel: string;\n /** Mix/section colour for the card's dot (section.color → zone colour → dominant category). */\n color: string;\n /** Free member seats right now. */\n seatsLeft: number;\n priceMin: number;\n priceMax: number;\n /** Per-category breakdown, cheapest first. */\n categories: SectionCategory[];\n}\n\ninterface HoldResponse {\n holdId: string;\n expiresAt: number;\n items?: HoldServerItem[];\n}\ninterface ResumeHoldResponse extends HoldResponse {\n items: HoldServerItem[];\n}\nexport interface HoldServerItem {\n label: string;\n objectId: string;\n objectType: 'seat' | 'booth' | 'ga';\n categoryKey: string;\n tierId: string | null;\n unitPrice: number;\n currency: string;\n quantity?: number;\n}\nexport interface HoldSelectionRequest { label: string; tierId?: string | null }\ninterface BestAvailableResponse extends HoldResponse {\n labels: string[];\n}\n\n/** Swappable public-surface transport (SDK PubApi or a dashboard `api.pub.*` adapter). */\nexport interface PickerTransport {\n chart(key: string): Promise<{\n doc: ChartDoc;\n event: { key: string; name: string; salesClosed?: boolean; venue?: string | null; startsAt?: number | null; currency?: string; mode?: string };\n }>;\n objects(key: string): Promise<{ seats: Record<string, string>; hidden?: string[]; closed?: string[] }>;\n hold(key: string, selections: HoldSelectionRequest[], ttlMs?: number, replaceHoldId?: string): Promise<HoldResponse>;\n bestAvailable(key: string, qty: number, categoryKey?: string): Promise<BestAvailableResponse>;\n release(key: string, labels: string[], holdId: string): Promise<unknown>;\n /** Optional capability-style lookup used to restore an active browser hold. */\n resume?(key: string, holdId: string): Promise<ResumeHoldResponse>;\n /** Optional — the SDK omits booking (it hands the holdId to the host page). */\n book?(key: string, labels: string[], holdId: string, bookingRef: string): Promise<unknown>;\n /** Optional (P4) — push an active hold's expiry out (\"need more time?\"). */\n extend?(key: string, holdId: string, ttlMs?: number): Promise<{ holdId: string; expiresAt: number; extends?: number }>;\n socketUrl(key: string): string;\n}\n\nexport interface PickerCallbacks extends RendererCallbacks {\n /** Selection changed (manual clicks or a server best-available pick). */\n onSelectionChange?: (seats: PickerSeat[]) => void;\n /** A hold opened (manual hold or best-available). */\n onHold?: (hold: HoldInfo) => void;\n /** A prior active hold was restored from its opaque hold id. */\n onHoldRestored?: (hold: HoldInfo) => void;\n /** The open hold expired server-side (the controller has already released it). */\n onHoldExpired?: () => void;\n /** A booking completed with this ref. */\n onBook?: (bookingRef: string) => void;\n /** Any live seat-status change arrived (delta or snapshot) — e.g. to recount \"N left\". */\n onStatusChange?: () => void;\n /**\n * Mouse hover moved onto a seat (null on hover-out) — the seat enriched with\n * category label/color, resolved price and live status, ready for a tooltip.\n * Fires alongside the raw renderer-level `onHover`.\n */\n onSeatHover?: (details: SeatHoverDetails | null) => void;\n /** The server declared the event closed (a 409 event_closed). */\n onSalesClosed?: () => void;\n /**\n * A section block was tapped at the far/zone rung — the controller has glided\n * the camera in and passes the computed summary (or null when cleared, e.g.\n * overview() / zoom-to-zones) so the host can show/hide the summary card.\n */\n onSectionFocus?: (summary: SectionSummary | null) => void;\n /** A deck was tapped in the 3D all-floors overview — host enters that floor in 2D. */\n onDeckTap?: (floorId: string) => void;\n /**\n * Non-blocking selection advice (localized): currently the orphan-seat hint —\n * the selection would strand a single free seat between unavailable\n * neighbors. `null` clears a previously shown hint. Never prevents anything.\n */\n onHint?: (message: string | null) => void;\n onError?: (err: unknown) => void;\n}\n\nexport interface PickerOptions extends PickerCallbacks {\n transport: PickerTransport;\n eventKey: string;\n maxSelection?: number;\n /** Renderer confirm-card mode (host shows a confirm popover instead of instant cart add). */\n confirmSelection?: boolean;\n /** ISO 4217 currency for on-map prices (default from money.DEFAULT_CURRENCY). */\n currency?: string;\n /** Flash a pulse when a seat we didn't touch goes free→taken (live-activity cue). */\n flashOnLiveChange?: boolean;\n /** Start in colorblind-safe rendering (Okabe-Ito hues + hollow booked seats). */\n colorblindSafe?: boolean;\n /**\n * Keep painting seat-status deltas even while the tab is hidden/backgrounded.\n *\n * Default FALSE — the buyer widget stays efficient: it lets rAF stay paused\n * while hidden and does a single synchronous catch-up repaint on regain (the\n * visibilitychange handler resnapshots + forceDraw()s). Set TRUE only for an\n * always-live surface — the future organizer control-room board — where a\n * backgrounded monitor must keep repainting; then each delta calls\n * renderer.forceDraw() when the tab is hidden. Purely a paint hint; enforcement\n * and the WS protocol are identical either way.\n */\n keepLiveWhileHidden?: boolean;\n}\n\n/** Read `status`/`conflicts`/`reason` off any thrown error without importing a specific ApiError. */\nfunction errInfo(err: unknown): { status?: number; conflicts?: HoldConflict[]; reason?: string } {\n const e = (err ?? {}) as { status?: number; conflicts?: HoldConflict[]; reason?: string };\n return { status: e.status, conflicts: e.conflicts, reason: e.reason };\n}\n\n/** DO seat status → renderer status ('blocked' has no renderer analogue → 'not_for_sale'). */\nfunction mapStatus(s: string): SeatStatus {\n if (s === 'blocked') return 'not_for_sale';\n if (s === 'held' || s === 'booked' || s === 'free' || s === 'not_for_sale') return s;\n return 'free';\n}\n\nexport class PickerController {\n private readonly opts: PickerOptions;\n private readonly api: PickerTransport;\n private readonly key: string;\n private readonly maxSelection: number;\n\n private renderer: ISeatmapRenderer | null = null;\n private _doc: ChartDoc | null = null;\n /** Section/zone ids hidden from buyers this event (3.3) — seats vanish, not grey. */\n private hidden = new Set<string>();\n /** Section/zone ids in the `closed` event-state (Phase 2) — seats stay, greyed\n * + not pickable. Kept separate from `hidden` (which strips them). */\n private closedSections = new Set<string>();\n\n /** label ⇄ id maps — backend speaks labels, the engine speaks ids. */\n private labelToId = new Map<string, string>();\n private labelToSeat = new Map<string, ExpandedSeat>();\n /** seatId → chosen ticket-tier id (absent ⇒ the category's first/default tier). */\n private seatTiers = new Map<string, string>();\n /** id → seat, for the section-summary breakdown (renderer members are ids). */\n private seatById = new Map<string, ExpandedSeat>();\n /** id → buyer-facing spatial metadata used by every tooltip/confirm surface. */\n private seatContext = new Map<string, { sectionLabel?: string; rowLabel?: string; seatNumber?: string }>();\n private allIds: string[] = [];\n\n // realtime socket\n private ws: WebSocket | null = null;\n private reconnectTimer: ReturnType<typeof setTimeout> | null = null;\n private attempt = 0;\n private closed = false;\n /** Bound visibilitychange listener (buyer catch-up on tab regain). Kept on the\n * instance so destroy() can detach it; null when not attached (guards double\n * mounts / non-DOM environments). */\n private onVisibilityChange: (() => void) | null = null;\n\n // hold state\n private hold_: HoldInfo | null = null;\n private liveStatuses = new Map<string, string>();\n private currency = 'USD';\n private expiryTimer: ReturnType<typeof setTimeout> | null = null;\n\n constructor(options: PickerOptions) {\n this.opts = options;\n this.api = options.transport;\n this.key = options.eventKey;\n this.maxSelection = options.maxSelection ?? DEFAULT_MAX_SELECTION;\n }\n\n get doc(): ChartDoc | null {\n return this._doc;\n }\n\n /** The chart with hidden sections' seats removed — what buyers actually see. */\n private visibleDoc(): ChartDoc {\n return this._doc ? applyHidden(this._doc, this.hidden) : ({ objects: [] } as unknown as ChartDoc);\n }\n\n /** Adopt a new hidden set; rebuild the visible chart only if it differs. */\n private syncHidden(ids: string[]): boolean {\n const next = ids.filter((x): x is string => typeof x === 'string');\n if (next.length === this.hidden.size && next.every((id) => this.hidden.has(id))) return false;\n this.hidden = new Set(next);\n this.renderer?.setChart(this.visibleDoc());\n return true;\n }\n\n /** Adopt a new closed-section set; restyle (grey + non-pickable) if it differs.\n * Cheap restyle — no chart rebuild — so mid-sale open/close repaints live. */\n private syncClosed(ids: string[] | undefined): boolean {\n const next = (ids ?? []).filter((x): x is string => typeof x === 'string');\n if (next.length === this.closedSections.size && next.every((id) => this.closedSections.has(id))) return false;\n this.closedSections = new Set(next);\n this.renderer?.setClosedSections?.(next);\n return true;\n }\n\n /** Whether a section is currently in the `closed` state (card must not open). */\n isSectionClosed(id: string): boolean {\n return this.closedSections.has(id);\n }\n currentHold(): HoldInfo | null {\n return this.hold_;\n }\n getRenderer(): ISeatmapRenderer | null {\n return this.renderer;\n }\n seatByLabel(label: string): ExpandedSeat | undefined {\n return this.labelToSeat.get(label);\n }\n idForLabel(label: string): string | undefined {\n return this.labelToId.get(label);\n }\n\n /** Fetch chart, build label maps, mount the renderer, seed statuses, go live. */\n async render(host: HTMLDivElement): Promise<{\n doc: ChartDoc;\n salesClosed: boolean;\n eventName: string;\n venue?: string | null;\n startsAt?: number | null;\n currency?: string;\n /** 'test' ⇒ sandbox event (hosts show a TEST MODE ribbon). */\n mode?: string;\n } | null> {\n if (this.renderer) return null; // already rendered — never mount twice on one controller\n this.closed = false;\n let res;\n try {\n res = await this.api.chart(this.key);\n } catch (err) {\n this.emitError(err);\n return null;\n }\n // destroy() may have run while the chart fetch was in flight (StrictMode\n // double-mount, or a fast key change) — bail before mounting anything.\n if (this.closed) return null;\n this._doc = res.doc;\n\n this.labelToId = new Map();\n this.labelToSeat = new Map();\n this.seatById = new Map();\n this.seatContext = new Map();\n this.allIds = [];\n const chartObjects = new Map(allObjects(res.doc).map((object) => [object.id, object] as const));\n const membership = computeSections(res.doc);\n const sectionLabels = new Map(\n [...membership.sections, ...(membership.ungrouped ? [membership.ungrouped] : [])].map((section) => [section.id, section.label] as const),\n );\n for (const s of expandChart(res.doc)) {\n this.labelToId.set(s.label, s.id);\n this.labelToSeat.set(s.label, s);\n this.seatById.set(s.id, s);\n this.allIds.push(s.id);\n const source = chartObjects.get(s.rowId);\n const sourceLabel = source && 'label' in source && typeof source.label === 'string' ? source.label : undefined;\n const rowLabel = s.kind === 'booth' ? undefined : sourceLabel;\n const labelParts = s.label.split('-');\n const seatNumber = rowLabel && s.label.startsWith(`${rowLabel}-`)\n ? s.label.slice(rowLabel.length + 1)\n : s.kind === 'booth'\n ? s.label\n : labelParts[labelParts.length - 1] ?? s.label;\n this.seatContext.set(s.id, {\n sectionLabel: sectionLabels.get(membership.objectToSection.get(s.rowId) ?? ''),\n rowLabel,\n seatNumber,\n });\n }\n\n // The organizer's currency travels with the chart payload; it wins over any\n // option passed at construction (the SDK host may not know it up front).\n const currency = res.event.currency ?? this.opts.currency;\n this.currency = currency ?? 'USD';\n const renderer = createRenderer(host, {\n maxSelection: this.maxSelection,\n confirmSelection: this.opts.confirmSelection,\n currency,\n onSelect: (seat) => {\n this.opts.onSelect?.(seat);\n this.emitSelectionChange();\n },\n onDeselect: (seat) => {\n this.opts.onDeselect?.(seat);\n this.emitSelectionChange();\n },\n onHover: (seat) => {\n this.opts.onHover?.(seat);\n if (this.opts.onSeatHover) this.opts.onSeatHover(seat ? this.describeSeat(seat) : null);\n },\n onFocusSeat: this.opts.onFocusSeat,\n onViewChange: this.opts.onViewChange,\n onGAClick: this.opts.onGAClick,\n // Section tap at the far/zone rung → glide in + surface the summary card.\n onSectionTap: (id) => this.handleSectionTap(id),\n onDeckTap: (floorId) => this.handleDeckTap(floorId),\n onFps: this.opts.onFps,\n });\n if (this.closed) {\n renderer.destroy(); // destroyed during createRenderer — don't leak the stage\n return null;\n }\n this.renderer = renderer;\n\n // Pull live state (seat statuses + hidden section/zone ids) BEFORE the first\n // paint so hidden sections never flash in. Falls back to the raw chart if the\n // snapshot is briefly unavailable — the WS re-snapshot then reconciles.\n let seats: Record<string, string> | null = null;\n let closedIds: string[] = [];\n try {\n const objs = await this.api.objects(this.key);\n this.hidden = new Set(objs.hidden ?? []);\n closedIds = (objs.closed ?? []).filter((x): x is string => typeof x === 'string');\n seats = objs.seats;\n } catch {\n /* transient — connect()'s onopen re-snapshots */\n }\n if (this.closed) {\n renderer.destroy();\n this.renderer = null;\n return null;\n }\n renderer.setChart(this.visibleDoc());\n if (this.opts.colorblindSafe) renderer.setColorblindSafe?.(true);\n // Closed sections are applied AFTER setChart (which resets state) so their\n // grey + non-pickable treatment lands on the first paint, no flash.\n this.closedSections = new Set(closedIds);\n if (closedIds.length) renderer.setClosedSections?.(closedIds);\n if (seats) this.applySeatsMap(seats);\n this.attachVisibilityListener();\n this.connect();\n return {\n doc: res.doc,\n salesClosed: !!res.event.salesClosed,\n eventName: res.event.name,\n venue: res.event.venue,\n startsAt: res.event.startsAt,\n currency,\n // 'test' ⇒ sandbox event: hosts render a TEST MODE ribbon (Phase 11).\n mode: res.event.mode ?? 'live',\n };\n }\n\n // ---- selection ------------------------------------------------------------\n\n getSelection(): PickerSeat[] {\n if (!this.renderer) return [];\n return this.renderer.getSelection().map((s) => this.toSeat(s));\n }\n /** Enriched metadata for a seat confirmation card or tooltip. */\n seatDetails(seatId: string): SeatHoverDetails | null {\n const seat = this.seatById.get(seatId);\n return seat ? this.describeSeat(seat) : null;\n }\n clearSelection(): void {\n this.renderer?.clearSelection();\n this.emitSelectionChange();\n }\n deselect(ids: string[]): void {\n this.renderer?.deselect(ids);\n this.emitSelectionChange();\n }\n\n // ---- booking machine ------------------------------------------------------\n\n /**\n * Hold the current selection (or a given label set). The controller does the\n * renderer/hold side (409 → deselect + repaint the taken seats held) and then\n * re-throws so the caller can choose the banner copy. Returns null only when\n * there's nothing to hold.\n */\n async hold(labelsArg?: string[], ttlMs?: number): Promise<HoldInfo | null> {\n const r = this.renderer;\n if (!r) return null;\n const labels = labelsArg ?? r.getSelection().map((s) => s.label);\n const existingGA = (this.hold_?.items ?? []).filter((item) => item.objectType === 'ga');\n const combinedLabels = [...new Set([...existingGA.map((item) => item.label), ...labels])];\n if (!combinedLabels.length) return null;\n\n // Reuse an existing hold that exactly covers this selection (re-holding 409s).\n if (this.hold_ && this.holdCovers(combinedLabels)) return this.hold_;\n try {\n const selections = combinedLabels.map((label) => {\n const ga = existingGA.find((item) => item.label === label);\n if (ga) return { label, tierId: ga.tierId };\n const seat = this.labelToSeat.get(label);\n const resolved = seat ? this.toSeat(seat) : null;\n return { label, ...(resolved?.tierId ? { tierId: resolved.tierId } : {}) };\n });\n const result = await this.api.hold(this.key, selections, ttlMs, this.hold_?.holdId);\n this.setHold({ holdId: result.holdId, labels: combinedLabels, expiresAt: result.expiresAt, items: result.items });\n return this.hold_;\n } catch (err) {\n this.handle409Conflicts(err);\n throw err;\n }\n }\n\n /** Restore an active server hold without creating or extending inventory. */\n async resumeHold(holdId: string): Promise<HoldInfo | null> {\n if (this.closed || !holdId || !this.api.resume) return null;\n const result = await this.api.resume(this.key, holdId);\n if (this.closed) return null;\n const labels = [...new Set(result.items.map((item) => item.label))];\n if (!labels.length) return null;\n this.setHold(\n { holdId: result.holdId, labels, expiresAt: result.expiresAt, items: result.items },\n 'restored',\n );\n return this.hold_;\n }\n\n /**\n * P4 \"need more time?\": extend the OPEN hold's server-side expiry and re-arm\n * the client expiry timer to match (via setHold), so the controller doesn't\n * fire a false expiry and start polling. Returns the new hold, or null if\n * there's no open hold or the transport can't extend / the server refused\n * (hold gone, expired, or at its renewal cap). Never throws for the refusal\n * case — the caller decides the copy.\n */\n async extendHold(ttlMs?: number): Promise<HoldInfo | null> {\n const current = this.hold_;\n if (!current || !this.api.extend) return null;\n try {\n const result = await this.api.extend(this.key, current.holdId, ttlMs);\n if (this.hold_?.holdId !== current.holdId) return this.hold_; // superseded meanwhile\n // Keep the same labels/items — only the expiry moved. setHold re-arms the timer.\n this.setHold({ holdId: current.holdId, labels: current.labels, expiresAt: result.expiresAt, items: current.items });\n return this.hold_;\n } catch {\n return null;\n }\n }\n\n /** Public GA inventory derived from the live synthetic-unit status stream. */\n /**\n * Live seats-left per category key (status 'free' right now). Recompute on\n * onStatusChange — this is what a price panel's \"N left\" counters read.\n */\n categoryAvailability(): Record<string, number> {\n const out: Record<string, number> = {};\n const closedMembers = this.closedMemberIds();\n for (const [id, s] of this.seatById) {\n if (closedMembers.has(id)) continue; // closed sections aren't on sale\n if ((this.getStatus(id) ?? 'free') === 'free') {\n out[s.categoryKey] = (out[s.categoryKey] ?? 0) + 1;\n }\n }\n return out;\n }\n\n /** Seat ids belonging to a currently-closed section (excluded from counts). */\n private closedMemberIds(): Set<string> {\n const out = new Set<string>();\n const r = this.renderer;\n if (!r || !this.closedSections.size) return out;\n for (const id of this.closedSections) for (const sid of (r.sectionMembers?.(id) ?? [])) out.add(sid);\n return out;\n }\n\n getGAAreas(): { id: string; label: string; capacity: number; available: number; categoryKey: string; price: number; currency: string; tiers?: CategoryTier[] }[] {\n const doc = this.visibleDoc();\n if (!doc) return [];\n return gaAreasOf(doc).map((area) => {\n const category = doc.categories.find((candidate) => candidate.key === area.categoryKey);\n return {\n id: area.id,\n label: area.label,\n capacity: Math.max(0, Math.floor(area.capacity)),\n available: gaUnitLabels(area).filter((label) => (this.liveStatuses.get(label) ?? 'free') === 'free').length,\n categoryKey: area.categoryKey,\n tiers: category?.tiers,\n price: category?.tiers?.[0]?.price ?? category?.price ?? 0,\n currency: this.currency,\n };\n });\n }\n\n /** Select a quantity from one GA area and hold it atomically. */\n async holdGA(\n areaId: string,\n qty: number,\n options: { tierId?: string | null; ttlMs?: number } = {},\n ): Promise<HoldInfo | null> {\n const doc = this.visibleDoc();\n if (!doc || !Number.isFinite(qty) || qty < 1) return null;\n const area = gaAreasOf(doc).find((candidate) => candidate.id === areaId);\n if (!area) return null;\n const labels = gaUnitLabels(area)\n .filter((label) => !this.hold_?.labels.includes(label) && (this.liveStatuses.get(label) ?? 'free') === 'free')\n .slice(0, Math.floor(qty));\n if (labels.length !== Math.floor(qty)) return null;\n const selections = new Map<string, { label: string; tierId?: string | null }>();\n for (const item of this.hold_?.items ?? []) selections.set(item.label, { label: item.label, tierId: item.tierId });\n if (this.hold_ && !this.hold_?.items?.length) {\n for (const seat of this.hold_.seats) selections.set(seat.label, { label: seat.label, ...(seat.tierId ? { tierId: seat.tierId } : {}) });\n }\n for (const seat of this.renderer?.getSelection() ?? []) {\n const resolved = this.labelToSeat.get(seat.label);\n const chosen = resolved ? this.toSeat(resolved) : null;\n selections.set(seat.label, { label: seat.label, ...(chosen?.tierId ? { tierId: chosen.tierId } : {}) });\n }\n for (const label of labels) selections.set(label, { label, ...(options.tierId ? { tierId: options.tierId } : {}) });\n const combined = [...selections.values()];\n const result = await this.api.hold(this.key, combined, options.ttlMs, this.hold_?.holdId);\n this.setHold({ holdId: result.holdId, labels: combined.map((s) => s.label), expiresAt: result.expiresAt, items: result.items });\n return this.hold_;\n }\n\n /** Server-picks `qty` best free seats and holds them atomically. Throws on failure. */\n async bestAvailable(qty: number, categoryKey?: string): Promise<HoldInfo | null> {\n const r = this.renderer;\n if (!r) return null;\n // Drop any prior auto-hold first.\n if (this.hold_ && !(await this.release())) return null;\n try {\n const result = await this.api.bestAvailable(this.key, qty, categoryKey);\n r.clearSelection();\n const ids = result.labels.map((l) => this.labelToId.get(l)).filter((v): v is string => !!v);\n if (ids.length) r.setStatus(ids, 'held');\n this.setHold({ holdId: result.holdId, labels: [...result.labels], expiresAt: result.expiresAt, items: result.items });\n const seats = result.labels\n .map((l) => this.labelToSeat.get(l))\n .filter((s): s is ExpandedSeat => !!s)\n .map((s) => this.toSeat(s));\n this.opts.onSelectionChange?.(seats);\n return this.hold_;\n } catch (err) {\n const { status, reason } = errInfo(err);\n if (status === 409 && reason === 'event_closed') this.opts.onSalesClosed?.();\n throw err;\n }\n }\n\n /**\n * Complete a booking. Requires a transport that supports book() (the SDK\n * deliberately does not). `bookingRef` MUST be a real reference from the caller.\n * `labelsArg` lets the caller book its own cart (the live page's confirm-flow\n * cart can hold best-available seats that aren't in the renderer selection);\n * defaults to the renderer selection. Reuses an existing exact-match hold, else\n * holds first. Returns the labels booked, or null on failure (conflicts painted).\n */\n async book(bookingRef: string, labelsArg?: string[]): Promise<string[] | null> {\n const r = this.renderer;\n if (!r) return null;\n if (!this.api.book) throw new Error('picker: transport has no book() — hold-only mode');\n const labels = labelsArg ?? r.getSelection().map((s) => s.label);\n if (!labels.length) return null;\n\n let holdId: string | undefined;\n try {\n if (this.hold_ && this.holdCovers(labels)) {\n holdId = this.hold_.holdId; // already held server-side — re-holding would 409\n } else {\n const replaceHoldId = this.hold_?.holdId;\n const h = await this.api.hold(\n this.key,\n labels.map((label) => {\n const seat = this.labelToSeat.get(label);\n const resolved = seat ? this.toSeat(seat) : null;\n return { label, ...(resolved?.tierId ? { tierId: resolved.tierId } : {}) };\n }),\n undefined,\n replaceHoldId,\n );\n holdId = h.holdId;\n this.setHold({ holdId, labels: [...labels], expiresAt: h.expiresAt, items: h.items });\n }\n await this.api.book(this.key, labels, holdId, bookingRef);\n } catch (err) {\n const { status, conflicts, reason } = errInfo(err);\n this.clearHold();\n if (status === 409 && reason === 'event_closed') {\n this.opts.onSalesClosed?.();\n } else if (status === 409 && conflicts?.length) {\n // Paint the taken seats, deselect them, release the still-free remainder.\n const takenLabels = new Set(conflicts.map((c) => c.label));\n const takenIds = [...takenLabels].map((l) => this.labelToId.get(l)).filter((v): v is string => !!v);\n if (takenIds.length) {\n r.setStatus(takenIds, 'booked');\n r.deselect(takenIds);\n }\n const stillFree = labels.filter((l) => !takenLabels.has(l));\n if (stillFree.length && holdId) void this.api.release(this.key, stillFree, holdId).catch(() => {});\n this.emitSelectionChange();\n } else if (holdId) {\n // Non-conflict failure after a hold landed — release it so seats aren't stranded.\n void this.api.release(this.key, labels, holdId).catch(() => {});\n }\n throw err;\n }\n // Success — optimistically paint booked, deselect just the booked seats\n // (not the whole selection — the cart may be an explicit subset), clear hold.\n const ids = labels.map((l) => this.labelToId.get(l)).filter((v): v is string => !!v);\n if (ids.length) {\n r.setStatus(ids, 'booked');\n r.deselect(ids);\n }\n this.clearHold();\n this.emitSelectionChange();\n this.opts.onBook?.(bookingRef);\n return labels;\n }\n\n /** Release the whole open hold (if any), repaint those seats free. */\n async release(): Promise<boolean> {\n const hold = this.hold_;\n if (!hold) return true;\n try {\n const result = await this.api.release(this.key, hold.labels, hold.holdId);\n if (!this.releaseConfirmed(result, hold.labels)) {\n await this.resnapshot();\n return false;\n }\n } catch (err) {\n this.emitError(err);\n return false;\n }\n if (this.hold_?.holdId !== hold.holdId) return true;\n this.clearHold();\n const ids = hold.labels.map((l) => this.labelToId.get(l)).filter((v): v is string => !!v);\n if (ids.length) {\n this.renderer?.deselect(ids);\n this.renderer?.setStatus(ids, 'free');\n }\n return true;\n }\n\n /**\n * Release just some labels from the open hold, keeping the rest held (used when\n * a buyer removes one seat chip). Clears the hold entirely once it empties.\n */\n async releaseLabels(labels: string[]): Promise<boolean> {\n const hold = this.hold_;\n if (!hold) return true;\n const drop = labels.filter((l) => hold.labels.includes(l));\n if (!drop.length) return true;\n try {\n const result = await this.api.release(this.key, drop, hold.holdId);\n if (!this.releaseConfirmed(result, drop)) {\n await this.resnapshot();\n return false;\n }\n } catch (err) {\n this.emitError(err);\n return false;\n }\n if (this.hold_?.holdId !== hold.holdId) return true;\n const remaining = hold.labels.filter((l) => !drop.includes(l));\n const remainingItems = hold.items?.filter((item) => !drop.includes(item.label));\n if (remaining.length) this.setHold({ ...hold, labels: remaining, items: remainingItems });\n else this.clearHold();\n const ids = drop.map((l) => this.labelToId.get(l)).filter((v): v is string => !!v);\n if (ids.length) {\n this.renderer?.deselect(ids);\n this.renderer?.setStatus(ids, 'free');\n }\n return true;\n }\n\n /** New transports return the exact labels released; tolerate older adapters. */\n private releaseConfirmed(result: unknown, requested: string[]): boolean {\n const released = (result as { released?: unknown } | null)?.released;\n return !Array.isArray(released) || requested.every((label) => released.includes(label));\n }\n\n // ---- renderer proxies (so consumers don't reach through) ------------------\n\n setStatus(ids: string[], status: SeatStatus): void {\n this.renderer?.setStatus(ids, status);\n }\n getStatus(id: string): SeatStatus | undefined {\n return this.renderer?.getStatus(id);\n }\n flashSeat(id: string, color?: string): void {\n this.renderer?.flashSeat(id, color);\n }\n zoomIn(): void {\n this.renderer?.zoomIn();\n }\n zoomOut(): void {\n this.renderer?.zoomOut();\n }\n zoomToFit(): void {\n this.renderer?.zoomToFit();\n }\n worldToScreen(p: { x: number; y: number }): { x: number; y: number } {\n return this.renderer?.worldToScreen(p) ?? { x: 0, y: 0 };\n }\n setSelectionFocus(seatId: string | null): void {\n this.renderer?.setSelectionFocus?.(seatId);\n }\n setAccessibilityFilter(types: string[] | null): void {\n this.renderer?.setAccessibilityFilter?.(types as never);\n }\n\n // ---- multi-floor (Batch 5) ------------------------------------------------\n\n /** Floors for the buyer's switcher (>1 ⇒ show it). Single-floor ⇒ one entry. */\n getFloors(): { id: string; name: string }[] {\n return this.renderer?.getFloors?.() ?? [];\n }\n getActiveFloorId(): string {\n return this.renderer?.getActiveFloorId?.() ?? '';\n }\n /** Switch the shown floor (2D), then re-apply live seat statuses onto it. */\n setFloor(id: string): void {\n const r = this.renderer;\n if (!r?.setActiveFloor || id === r.getActiveFloorId?.()) return;\n r.setStacked?.(false); // leaving any 3D stack — back to a single floor\n r.setActiveFloor(id);\n void this.resnapshot(); // re-paint statuses on the newly-rendered floor\n this.emitSelectionChange();\n }\n\n /** 3D all-floors stacked overview ⇄ active floor. Re-applies statuses after. */\n setStacked(on: boolean): void {\n const r = this.renderer;\n if (!r?.setStacked || on === r.isStacked?.()) return;\n r.setStacked(on);\n void this.resnapshot(); // re-paint statuses across the rebuilt view\n }\n isMultiFloor(): boolean {\n return (this._doc?.floors?.length ?? 0) > 1;\n }\n\n /** Tap-a-deck-to-enter: leave the 3D stack, drop to flat 2D on `floorId`, and\n * tell the host so it can sync its 2D/3D toggle + floor-switcher state. */\n private handleDeckTap(floorId: string): void {\n const r = this.renderer;\n if (!r) return;\n r.setViewMode?.('flat');\n r.setStacked?.(false);\n r.setActiveFloor?.(floorId);\n void this.resnapshot();\n this.emitSelectionChange();\n this.opts.onDeckTap?.(floorId);\n }\n\n // ---- big-venue: sections / rungs / projection (Slice 5) -------------------\n\n /** Switch the map projection (2D flat ⇄ 3D isometric). No-op on a flat renderer. */\n setViewMode(mode: 'flat' | 'isometric'): void {\n this.renderer?.setViewMode?.(mode);\n }\n getViewMode(): 'flat' | 'isometric' {\n return this.renderer?.getViewMode?.() ?? 'flat';\n }\n /** Current LOD rung (for the ZONES/SECTIONS/SEATS pill). */\n getRung(): LodRung {\n return this.renderer?.getRung?.() ?? 'seats';\n }\n /** Jump to a rung; ZONES clears any focused summary (back to overview). */\n setRung(rung: LodRung): void {\n if (rung === 'zones') {\n this.overview();\n return;\n }\n this.renderer?.setRung?.(rung);\n }\n\n /** Price-band filter (F4): dim free seats whose category is outside `keys`\n * (null clears). The widget resolves which categories fall in the band. */\n setCategoryFilter(keys: string[] | null): void {\n this.renderer?.setCategoryFilter?.(keys);\n }\n\n /** World-space rect currently visible + full chart bounds (F3 minimap frame). */\n getViewport(): { visible: { x: number; y: number; width: number; height: number }; bounds: { x: number; y: number; width: number; height: number } } | null {\n const r = this.renderer;\n if (!r?.getVisibleWorldRect || !r.getWorldBounds) return null;\n return { visible: r.getVisibleWorldRect(), bounds: r.getWorldBounds() };\n }\n /** Glide in on a section and surface its summary (same path as a section tap). */\n focusSection(id: string): void {\n this.handleSectionTap(id);\n }\n /** Zoom back out to the whole chart and clear the section-summary card + focus. */\n overview(): void {\n this.renderer?.clearSectionFocus?.();\n this.renderer?.zoomToFit();\n this.opts.onSectionFocus?.(null);\n }\n\n /** Glide the camera into a tapped section and emit its computed summary. Uses\n * the AXS focus treatment (dim + backdrop) when the engine supports it; a\n * closed section is framed but never opens a buyer card. */\n private handleSectionTap(id: string): void {\n const r = this.renderer;\n if (!r) return;\n if (r.focusSection) r.focusSection(id);\n else r.focusRegion?.(id);\n if (this.isSectionClosed(id)) {\n this.opts.onSectionFocus?.(null); // closed: no purchase card\n return;\n }\n this.opts.onSectionFocus?.(this.sectionSummary(id));\n }\n\n /**\n * Build a section summary from the renderer's spatial membership: section +\n * zone labels, live seats-left, price range, and the per-category breakdown.\n */\n private sectionSummary(id: string): SectionSummary | null {\n const r = this.renderer;\n const doc = this._doc;\n if (!r || !doc) return null;\n const sec = doc.objects.find(\n (o): o is SectionObject => o.type === 'section' && o.id === id,\n );\n if (!sec) return null;\n\n const memberIds = r.sectionMembers?.(id) ?? [];\n const byCat = new Map<string, number>();\n let seatsLeft = 0;\n for (const sid of memberIds) {\n const seat = this.seatById.get(sid);\n if (!seat) continue;\n byCat.set(seat.categoryKey, (byCat.get(seat.categoryKey) ?? 0) + 1);\n if (r.getStatus(sid) === 'free') seatsLeft++;\n }\n\n const categories: SectionCategory[] = [...byCat.entries()]\n .map(([key, count]) => {\n const cat = doc.categories.find((c) => c.key === key);\n return {\n key,\n count,\n label: cat?.label ?? key,\n color: cat?.color ?? '#6e7bff',\n price: cat?.price ?? 0,\n };\n })\n .sort((a, b) => a.price - b.price);\n\n const prices = categories.map((c) => c.price);\n const zone = sec.zone ? doc.zones?.find((z) => z.id === sec.zone) : undefined;\n const color = sec.color ?? zone?.color ?? categories[0]?.color ?? '#6e7bff';\n\n return {\n id,\n label: sec.label,\n zoneLabel: zone?.label ?? '',\n color,\n seatsLeft,\n priceMin: prices.length ? prices[0] : 0,\n priceMax: prices.length ? prices[prices.length - 1] : 0,\n categories,\n };\n }\n\n destroy(): void {\n this.closed = true;\n this.detachVisibilityListener();\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = null;\n }\n if (this.expiryTimer) {\n clearTimeout(this.expiryTimer);\n this.expiryTimer = null;\n }\n if (this.ws) {\n try {\n this.ws.close();\n } catch {\n /* ignore */\n }\n this.ws = null;\n }\n this.renderer?.destroy();\n this.renderer = null;\n }\n\n // ---- internals ------------------------------------------------------------\n\n private toSeat(s: ExpandedSeat): PickerSeat {\n const tiers = this.tiersFor(s.categoryKey);\n if (!tiers) {\n return { id: s.id, label: s.label, categoryKey: s.categoryKey, price: this.priceFor(s.categoryKey) };\n }\n const chosen = tiers.find((t) => t.id === this.seatTiers.get(s.id)) ?? tiers[0];\n return {\n id: s.id,\n label: s.label,\n categoryKey: s.categoryKey,\n price: chosen.price,\n tiers,\n tierId: chosen.id,\n };\n }\n /** Tooltip payload for a hovered seat — see PickerCallbacks.onSeatHover. */\n private describeSeat(s: ExpandedSeat): SeatHoverDetails {\n const cat = this._doc?.categories.find((c) => c.key === s.categoryKey);\n return {\n ...this.toSeat(s),\n categoryLabel: cat?.label ?? s.categoryKey,\n categoryColor: cat?.color ?? '#6e7bff',\n status: this.renderer?.getStatus(s.id) ?? 'free',\n currency: this.currency,\n ...this.seatContext.get(s.id),\n };\n }\n\n private priceFor(categoryKey: string): number {\n return this._doc?.categories.find((c) => c.key === categoryKey)?.price ?? 0;\n }\n private tiersFor(categoryKey: string): CategoryTier[] | undefined {\n const t = this._doc?.categories.find((c) => c.key === categoryKey)?.tiers;\n return t && t.length ? t : undefined;\n }\n\n /**\n * Choose a ticket tier for a selected seat (e.g. Adult → Child). Re-emits the\n * selection so the host's cart + the eventual hold carry the new tier + price.\n * `tierId = null` reverts to the category's first (default) tier. No-op if the\n * seat's category has no tiers or the id isn't one of them.\n */\n setSeatTier(seatId: string, tierId: string | null): void {\n const seat = this.seatById.get(seatId);\n if (!seat) return;\n const tiers = this.tiersFor(seat.categoryKey);\n if (!tiers) return;\n if (tierId == null) this.seatTiers.delete(seatId);\n else if (tiers.some((t) => t.id === tierId)) this.seatTiers.set(seatId, tierId);\n else return;\n this.emitSelectionChange();\n if (this.hold_) this.hold_ = { ...this.hold_, seats: this.seatsForLabels(this.hold_.labels) };\n }\n\n /** PickerSeats (with chosen tier) for a set of held labels. */\n private seatsForLabels(labels: string[]): PickerSeat[] {\n const out: PickerSeat[] = [];\n for (const l of labels) {\n const s = this.labelToSeat.get(l);\n if (s) out.push(this.toSeat(s));\n }\n return out;\n }\n private emitSelectionChange(): void {\n this.opts.onSelectionChange?.(this.getSelection());\n this.emitOrphanHint();\n }\n\n /** Whether the last emitted hint was non-null (avoids clearing repeatedly). */\n private hintShown = false;\n\n /**\n * Orphan-seat advice on manual selection: when the buyer's current picks\n * strand one (or more) single free seats between unavailable same-row\n * neighbors, surface a localized, non-blocking hint. Cleared (null) as soon\n * as the selection stops stranding anyone.\n */\n private emitOrphanHint(): void {\n if (!this.opts.onHint) return;\n const r = this.renderer;\n if (!r) return;\n const selected = new Set(r.getSelection().map((s) => s.id));\n const stranded = selected.size\n ? strandedSingles(this.seatById.values(), (id) => r.getStatus(id), selected)\n : [];\n if (stranded.length > 0) {\n this.hintShown = true;\n this.opts.onHint(t('picker.orphanHint'));\n } else if (this.hintShown) {\n this.hintShown = false;\n this.opts.onHint(null);\n }\n }\n\n /** Toggle colorblind-safe rendering at runtime (see PickerOptions.colorblindSafe). */\n setColorblindSafe(on: boolean): void {\n this.renderer?.setColorblindSafe?.(on);\n }\n private emitError(err: unknown): void {\n if (this.opts.onError) this.opts.onError(err);\n else console.error('[picker]', err);\n }\n\n private holdCovers(labels: string[]): boolean {\n const h = this.hold_;\n if (!h || h.labels.length !== labels.length || !labels.every((l) => h.labels.includes(l))) return false;\n const tiers = new Map((h.items ?? []).map((item) => [item.label, item.tierId]));\n return labels.every((label) => {\n const seat = this.labelToSeat.get(label);\n const currentTier = seat ? this.toSeat(seat).tierId ?? null : null;\n return !tiers.has(label) || tiers.get(label) === currentTier;\n });\n }\n\n private handle409Conflicts(err: unknown): void {\n const { status, conflicts } = errInfo(err);\n if (status !== 409 || !conflicts?.length) return;\n const r = this.renderer;\n if (!r) return;\n const takenIds = conflicts.map((c) => this.labelToId.get(c.label)).filter((v): v is string => !!v);\n if (takenIds.length) {\n r.deselect(takenIds);\n r.setStatus(takenIds, 'held');\n }\n this.emitSelectionChange();\n }\n\n /** Set the open hold + (re)arm the server-authoritative expiry timer. */\n private setHold(\n hold: Omit<HoldInfo, 'seats'> & { seats?: PickerSeat[] },\n source: 'created' | 'restored' = 'created',\n ): void {\n // Always resolve seats (with chosen tier) from the held labels so the host's\n // onHold — and any later book — carries the tier the buyer picked per seat.\n const full: HoldInfo = { ...hold, seats: this.seatsForLabels(hold.labels) };\n this.hold_ = full;\n this.renderer?.setOwnedHold?.(\n full.labels.map((label) => this.labelToId.get(label)).filter((id): id is string => !!id),\n );\n if (this.expiryTimer) clearTimeout(this.expiryTimer);\n const ms = Math.max(0, full.expiresAt - Date.now());\n this.expiryTimer = setTimeout(() => void this.expireActiveHold(), ms);\n if (source === 'restored') this.opts.onHoldRestored?.(full);\n else this.opts.onHold?.(full);\n }\n private clearHold(): void {\n this.hold_ = null;\n this.renderer?.setOwnedHold?.(null);\n if (this.expiryTimer) {\n clearTimeout(this.expiryTimer);\n this.expiryTimer = null;\n }\n }\n private async expireActiveHold(): Promise<void> {\n const hold = this.hold_;\n if (!hold) return;\n try {\n const snap = await this.api.objects(this.key);\n if (this.hold_?.holdId !== hold.holdId) return;\n this.applySeatsMap(snap.seats);\n } catch {\n // Do not report expiry from a disconnected/stale client. Reconcile once\n // the authoritative snapshot becomes reachable.\n if (this.hold_?.holdId === hold.holdId) {\n this.expiryTimer = setTimeout(() => void this.expireActiveHold(), 2_000);\n }\n return;\n }\n if (this.hold_?.holdId !== hold.holdId) return; // booked snapshot cleared it\n if (hold.labels.some((label) => this.liveStatuses.get(label) === 'held')) {\n this.expiryTimer = setTimeout(() => void this.expireActiveHold(), 1_000);\n return;\n }\n this.clearHold();\n this.opts.onHoldExpired?.();\n }\n\n private applySeatsMap(seats: Record<string, string>): void {\n const r = this.renderer;\n if (!r) return;\n this.liveStatuses = new Map(Object.entries(seats));\n if (this.allIds.length) r.setStatus(this.allIds, 'free');\n // setChart() rebuilds renderer state (floor/hidden-section changes), so\n // restore the buyer-ownership layer before repainting held statuses.\n r.setOwnedHold?.(\n (this.hold_?.labels ?? [])\n .map((label) => this.labelToId.get(label))\n .filter((id): id is string => !!id),\n );\n const byStatus: Record<SeatStatus, string[]> = { free: [], held: [], booked: [], not_for_sale: [] };\n for (const [label, st] of Object.entries(seats)) {\n const id = this.labelToId.get(label);\n if (id) byStatus[mapStatus(st)].push(id);\n }\n (['held', 'booked', 'not_for_sale'] as SeatStatus[]).forEach((st) => {\n if (byStatus[st].length) r.setStatus(byStatus[st], st);\n });\n this.opts.onStatusChange?.();\n this.clearBookedHoldIfSettled();\n }\n\n private clearBookedHoldIfSettled(): void {\n if (this.hold_?.labels.every((label) => this.liveStatuses.get(label) === 'booked')) this.clearHold();\n }\n\n private async resnapshot(): Promise<void> {\n try {\n const objs = await this.api.objects(this.key);\n this.applySeatsMap(objs.seats);\n } catch {\n /* transient — the socket delta stream keeps us fresh */\n }\n }\n\n // ---- realtime socket ------------------------------------------------------\n\n /**\n * Buyer catch-up on tab regain. While a tab is hidden Chrome pauses rAF, so\n * seat-status deltas that arrived over the WS mutated the scene graph but the\n * canvas colors never repainted. When the tab becomes visible again we (1)\n * resnapshot to pull authoritative state for anything the socket may have\n * missed while backgrounded, then (2) forceDraw() a synchronous repaint so the\n * seat colors are correct immediately rather than on the next incidental draw.\n *\n * Attached once per mount; guarded against double-attach and non-DOM\n * environments; detached in destroy() (no leaks).\n */\n private attachVisibilityListener(): void {\n if (this.onVisibilityChange) return; // already attached (guard double mount)\n if (typeof document === 'undefined' || typeof document.addEventListener !== 'function') return;\n const handler = (): void => {\n if (this.closed) return;\n if (document.visibilityState !== 'visible') return;\n // Re-fetch authoritative state, then paint it synchronously.\n void this.resnapshot().then(() => {\n if (!this.closed) this.renderer?.forceDraw();\n });\n };\n this.onVisibilityChange = handler;\n document.addEventListener('visibilitychange', handler);\n }\n\n private detachVisibilityListener(): void {\n if (!this.onVisibilityChange) return;\n if (typeof document !== 'undefined' && typeof document.removeEventListener === 'function') {\n document.removeEventListener('visibilitychange', this.onVisibilityChange);\n }\n this.onVisibilityChange = null;\n }\n\n private connect(): void {\n if (this.closed) return;\n let ws: WebSocket;\n try {\n ws = new WebSocket(this.api.socketUrl(this.key));\n } catch {\n this.scheduleReconnect();\n return;\n }\n this.ws = ws;\n\n ws.onopen = () => {\n this.attempt = 0;\n void this.resnapshot();\n };\n ws.onmessage = (e) => {\n let msg: unknown;\n try {\n msg = JSON.parse(typeof e.data === 'string' ? e.data : '');\n } catch {\n return;\n }\n const r = this.renderer;\n if (!r || !msg || typeof msg !== 'object') return;\n const m = msg as { type?: string; hidden?: string[]; closed?: string[]; seats?: Record<string, string>; changes?: { label: string; status: string }[] };\n // Reconcile hidden sections whenever they arrive (dedicated 'hidden' message\n // OR a snapshot that carries them). Only rebuilds the chart when it changed.\n if (Array.isArray(m.hidden) && this.syncHidden(m.hidden)) {\n void this.resnapshot(); // repaint statuses onto the rebuilt chart\n this.opts.onStatusChange?.();\n }\n // Reconcile closed sections (Phase 2). Cheap grey restyle, no chart rebuild —\n // so flipping a section open/closed mid-sale repaints for connected buyers.\n if (Array.isArray(m.closed) && this.syncClosed(m.closed)) {\n this.opts.onStatusChange?.();\n }\n if (m.type === 'hidden') return; // dedicated hidden message carries no seats\n if (m.seats && typeof m.seats === 'object') {\n this.applySeatsMap(m.seats);\n } else if (Array.isArray(m.changes)) {\n for (const ch of m.changes) {\n this.liveStatuses.set(ch.label, ch.status);\n const id = this.labelToId.get(ch.label);\n if (!id) continue;\n const next = mapStatus(ch.status);\n // Flash a live free→taken change — but not the buyer's OWN just-held\n // seats (a manual hold leaves them 'free' locally, so the server's\n // held-delta would otherwise flash them as if someone else grabbed them).\n if (\n this.opts.flashOnLiveChange &&\n next !== 'free' &&\n r.getStatus(id) === 'free' &&\n !this.hold_?.labels.includes(ch.label)\n ) {\n // Pulse color mirrors the manager board's status language:\n // amber for a hold landing, red for a booking.\n r.flashSeat(id, next === 'held' ? '#f4b740' : '#f43f5e');\n }\n r.setStatus([id], next);\n }\n // Stay-live-while-hidden (opt-in, default OFF). setStatus paints via\n // batchDraw (rAF), which Chrome pauses on a hidden tab — so an always-on\n // board (the future organizer control room) would freeze while\n // backgrounded. When enabled, force a synchronous repaint so a hidden\n // board keeps painting. The buyer widget leaves this off and relies on\n // the visibilitychange catch-up instead.\n if (\n this.opts.keepLiveWhileHidden &&\n typeof document !== 'undefined' &&\n document.visibilityState === 'hidden'\n ) {\n r.forceDraw();\n }\n this.clearBookedHoldIfSettled();\n this.opts.onStatusChange?.();\n }\n };\n ws.onclose = () => {\n if (this.ws === ws) this.ws = null;\n this.scheduleReconnect();\n };\n ws.onerror = () => {\n try {\n ws.close();\n } catch {\n /* onclose drives reconnect */\n }\n };\n }\n\n private scheduleReconnect(): void {\n if (this.closed || this.reconnectTimer) return;\n const attempt = Math.min(this.attempt++, 5);\n const delay = Math.min(1000 * 2 ** attempt, MAX_BACKOFF_MS);\n this.reconnectTimer = setTimeout(() => {\n this.reconnectTimer = null;\n this.connect();\n }, delay);\n }\n}\n","/**\n * Synthetic view-from-seat panorama, generated from chart geometry alone.\n *\n * Draws a 2048×1024 equirectangular texture of a dark hall with the stage\n * placed at the correct bearing and angular size for THIS seat — closer seats\n * see a bigger stage, off-center seats see it at an angle. Used whenever the\n * organizer hasn't uploaded a real photo/360 for the seat; both go through the\n * same viewer.\n *\n * Equirectangular mapping: x = (yaw + 180°)/360° · W, y = (90° − pitch)/180° · H,\n * where yaw 0 = the direction the camera faces by default.\n */\n\nimport type { ExpandedSeat, Point } from '../core/types';\n\nconst W = 2048;\nconst H = 1024;\n/** Chart units → meters, for plausible eye-level proportions (seatSpacing 24 ≈ 0.55m). */\nconst UNIT = 0.55 / 24;\n\nconst yawToX = (yawDeg: number) => ((yawDeg + 180) / 360) * W;\nconst pitchToY = (pitchDeg: number) => ((90 - pitchDeg) / 180) * H;\n\nexport interface PanoramaResult {\n url: string;\n /** Meters from the stage, for the caption. */\n distanceM: number;\n}\n\nexport function generateSeatPanorama(\n seat: ExpandedSeat,\n focalPoint: Point,\n neighborSeats: ExpandedSeat[],\n): PanoramaResult {\n const canvas = document.createElement('canvas');\n canvas.width = W;\n canvas.height = H;\n const ctx = canvas.getContext('2d')!;\n\n const dx = focalPoint.x - seat.x;\n const dy = focalPoint.y - seat.y;\n const distU = Math.hypot(dx, dy);\n const distM = Math.max(2, distU * UNIT);\n\n // ---- room shell: ceiling → walls → floor -------------------------------\n const sky = ctx.createLinearGradient(0, 0, 0, H);\n sky.addColorStop(0, '#05070c');\n sky.addColorStop(0.42, '#11172a');\n sky.addColorStop(0.5, '#1a2238');\n sky.addColorStop(0.56, '#10141f');\n sky.addColorStop(1, '#07090f');\n ctx.fillStyle = sky;\n ctx.fillRect(0, 0, W, H);\n\n // ---- stage, centered at yaw 0 (the viewer opens facing it) -------------\n // Angular size from real proportions: stage ~8m wide, ~1m platform + 6m set.\n const stageHalfYaw = Math.min(80, (Math.atan2(4, distM) * 180) / Math.PI);\n const stageTopPitch = Math.min(45, (Math.atan2(5, distM) * 180) / Math.PI);\n const stageBasePitch = Math.max(-30, (-Math.atan2(1.1, distM) * 180) / Math.PI);\n\n const sx0 = yawToX(-stageHalfYaw);\n const sx1 = yawToX(stageHalfYaw);\n const sy0 = pitchToY(stageTopPitch);\n const sy1 = pitchToY(stageBasePitch);\n\n // glow behind the stage\n const glow = ctx.createRadialGradient(W / 2, (sy0 + sy1) / 2, 10, W / 2, (sy0 + sy1) / 2, (sx1 - sx0) * 1.1);\n glow.addColorStop(0, 'rgba(129, 140, 248, 0.5)');\n glow.addColorStop(0.5, 'rgba(99, 102, 241, 0.16)');\n glow.addColorStop(1, 'rgba(99, 102, 241, 0)');\n ctx.fillStyle = glow;\n ctx.fillRect(sx0 - (sx1 - sx0) * 0.6, sy0 - (sy1 - sy0) * 1.2, (sx1 - sx0) * 2.2, (sy1 - sy0) * 3.4);\n\n // stage box + lit backdrop\n ctx.fillStyle = '#242c44';\n ctx.fillRect(sx0, sy0, sx1 - sx0, sy1 - sy0);\n const backdrop = ctx.createLinearGradient(0, sy0, 0, sy1);\n backdrop.addColorStop(0, '#7c5cff');\n backdrop.addColorStop(0.5, '#e1447a');\n backdrop.addColorStop(1, '#f59e0b');\n ctx.globalAlpha = 0.75;\n ctx.fillStyle = backdrop;\n const inset = (sx1 - sx0) * 0.06;\n ctx.fillRect(sx0 + inset, sy0 + (sy1 - sy0) * 0.12, sx1 - sx0 - inset * 2, (sy1 - sy0) * 0.62);\n ctx.globalAlpha = 1;\n // stage lip\n ctx.fillStyle = '#0d1119';\n ctx.fillRect(sx0, sy1 - (sy1 - sy0) * 0.1, sx1 - sx0, (sy1 - sy0) * 0.1);\n\n // performer silhouettes, scaled by distance\n const performerH = (sy1 - sy0) * 0.45;\n ctx.fillStyle = 'rgba(8, 10, 16, 0.85)';\n for (const fx of [0.35, 0.5, 0.65]) {\n const px = sx0 + (sx1 - sx0) * fx;\n const py = sy1 - (sy1 - sy0) * 0.12;\n ctx.beginPath();\n ctx.arc(px, py - performerH * 0.82, performerH * 0.16, 0, Math.PI * 2); // head\n ctx.fill();\n ctx.fillRect(px - performerH * 0.14, py - performerH * 0.68, performerH * 0.28, performerH * 0.68); // body\n }\n\n // spotlight beams from above the stage\n ctx.globalAlpha = 0.14;\n ctx.fillStyle = '#c7d2fe';\n for (const fx of [0.3, 0.5, 0.7]) {\n const bx = sx0 + (sx1 - sx0) * fx;\n ctx.beginPath();\n ctx.moveTo(bx - 8, pitchToY(Math.min(60, stageTopPitch + 25)));\n ctx.lineTo(bx - (sx1 - sx0) * 0.09, sy1);\n ctx.lineTo(bx + (sx1 - sx0) * 0.09, sy1);\n ctx.lineTo(bx + 8, pitchToY(Math.min(60, stageTopPitch + 25)));\n ctx.closePath();\n ctx.fill();\n }\n ctx.globalAlpha = 1;\n\n // ---- rig lights along the ceiling all around ---------------------------\n ctx.fillStyle = 'rgba(199, 210, 254, 0.8)';\n for (let i = 0; i < 26; i++) {\n const x = (i / 26) * W;\n const y = pitchToY(55 + (i % 3) * 6);\n ctx.beginPath();\n ctx.arc(x, y, 3.2, 0, Math.PI * 2);\n ctx.fill();\n }\n\n // ---- audience: heads of nearby seats, at their true bearings -----------\n // Bearing relative to the stage direction so yaw 0 keeps facing the stage.\n const stageBearing = Math.atan2(dx, -dy); // screen coords, -y is \"up\" the hall\n ctx.fillStyle = 'rgba(16, 20, 30, 0.95)';\n for (const other of neighborSeats) {\n if (other.id === seat.id) continue;\n const ox = other.x - seat.x;\n const oy = other.y - seat.y;\n const d = Math.hypot(ox, oy) * UNIT;\n if (d < 0.3 || d > 14) continue;\n const bearing = Math.atan2(ox, -oy) - stageBearing;\n const yaw = ((((bearing * 180) / Math.PI + 540) % 360) - 180);\n const headPitch = (-Math.atan2(0.35, d) * 180) / Math.PI; // heads slightly below eye level\n const headR = Math.min(46, 260 / (d / UNIT / 24 + 1.2) / 4);\n const hx = yawToX(yaw);\n const hy = pitchToY(headPitch);\n ctx.beginPath();\n ctx.arc(hx, hy, headR, 0, Math.PI * 2);\n ctx.fill();\n ctx.beginPath(); // shoulders\n ctx.ellipse(hx, hy + headR * 1.4, headR * 1.7, headR * 0.9, 0, Math.PI, 0, true);\n ctx.fill();\n }\n\n // subtle vignette at the poles (hides equirect pinching)\n const poleFade = ctx.createLinearGradient(0, 0, 0, H);\n poleFade.addColorStop(0, 'rgba(0,0,0,0.85)');\n poleFade.addColorStop(0.12, 'rgba(0,0,0,0)');\n poleFade.addColorStop(0.88, 'rgba(0,0,0,0)');\n poleFade.addColorStop(1, 'rgba(0,0,0,0.85)');\n ctx.fillStyle = poleFade;\n ctx.fillRect(0, 0, W, H);\n\n return { url: canvas.toDataURL('image/jpeg', 0.82), distanceM: Math.round(distM) };\n}\n\n// ---------------------------------------------------------------------------\n// Compact forward-view thumbnail — a cheap (480×270) rectilinear preview of\n// what this seat faces, for inline display inside the buyer's confirm card.\n// Unlike the full equirectangular panorama it maps a ~100°×60° forward field\n// of view directly (no 360 squish), so it reads as a real POV at a glance and\n// costs a fraction of the full render. Same geometry → the two stay consistent.\n// ---------------------------------------------------------------------------\n\nconst TW = 480;\nconst TH = 270;\nconst HALF_HFOV = 50; // degrees left/right of the stage direction\nconst HALF_VFOV = 30; // degrees up/down of the horizon\n\nconst yawToTX = (yawDeg: number) => ((yawDeg + HALF_HFOV) / (2 * HALF_HFOV)) * TW;\nconst pitchToTY = (pitchDeg: number) => ((HALF_VFOV - pitchDeg) / (2 * HALF_VFOV)) * TH;\n\nexport function generateSeatThumb(seat: ExpandedSeat, focalPoint: Point, _neighborSeats?: ExpandedSeat[]): PanoramaResult {\n const canvas = document.createElement('canvas');\n canvas.width = TW;\n canvas.height = TH;\n const ctx = canvas.getContext('2d')!;\n\n const dx = focalPoint.x - seat.x;\n const dy = focalPoint.y - seat.y;\n const distM = Math.max(2, Math.hypot(dx, dy) * UNIT);\n\n // hall shell (ceiling → wall → floor), horizon at mid-height\n const sky = ctx.createLinearGradient(0, 0, 0, TH);\n sky.addColorStop(0, '#05070c');\n sky.addColorStop(0.44, '#141b30');\n sky.addColorStop(0.5, '#1b2440');\n sky.addColorStop(0.58, '#10141f');\n sky.addColorStop(1, '#070910');\n ctx.fillStyle = sky;\n ctx.fillRect(0, 0, TW, TH);\n\n // stage geometry (identical formulas to the full panorama)\n const stageHalfYaw = Math.min(HALF_HFOV - 2, (Math.atan2(4, distM) * 180) / Math.PI);\n const stageTopPitch = Math.min(HALF_VFOV - 2, (Math.atan2(5, distM) * 180) / Math.PI);\n const stageBasePitch = Math.max(-HALF_VFOV + 2, (-Math.atan2(1.1, distM) * 180) / Math.PI);\n const sx0 = yawToTX(-stageHalfYaw);\n const sx1 = yawToTX(stageHalfYaw);\n const sy0 = pitchToTY(stageTopPitch);\n const sy1 = pitchToTY(stageBasePitch);\n const sw = sx1 - sx0;\n const sh = sy1 - sy0;\n\n // glow\n const glow = ctx.createRadialGradient(TW / 2, (sy0 + sy1) / 2, 4, TW / 2, (sy0 + sy1) / 2, sw * 1.1);\n glow.addColorStop(0, 'rgba(129,140,248,0.5)');\n glow.addColorStop(0.5, 'rgba(99,102,241,0.15)');\n glow.addColorStop(1, 'rgba(99,102,241,0)');\n ctx.fillStyle = glow;\n ctx.fillRect(sx0 - sw * 0.6, sy0 - sh * 1.2, sw * 2.2, sh * 3.4);\n\n // stage box + lit backdrop + lip\n ctx.fillStyle = '#242c44';\n ctx.fillRect(sx0, sy0, sw, sh);\n const backdrop = ctx.createLinearGradient(0, sy0, 0, sy1);\n backdrop.addColorStop(0, '#7c5cff');\n backdrop.addColorStop(0.5, '#e1447a');\n backdrop.addColorStop(1, '#f59e0b');\n ctx.globalAlpha = 0.78;\n ctx.fillStyle = backdrop;\n const inset = sw * 0.06;\n ctx.fillRect(sx0 + inset, sy0 + sh * 0.12, sw - inset * 2, sh * 0.62);\n ctx.globalAlpha = 1;\n ctx.fillStyle = '#0d1119';\n ctx.fillRect(sx0, sy1 - sh * 0.1, sw, sh * 0.1);\n\n // performer silhouettes\n const ph = sh * 0.45;\n ctx.fillStyle = 'rgba(8,10,16,0.85)';\n for (const fx of [0.35, 0.5, 0.65]) {\n const px = sx0 + sw * fx;\n const py = sy1 - sh * 0.12;\n ctx.beginPath();\n ctx.arc(px, py - ph * 0.82, ph * 0.16, 0, Math.PI * 2);\n ctx.fill();\n ctx.fillRect(px - ph * 0.14, py - ph * 0.68, ph * 0.28, ph * 0.68);\n }\n\n // spotlight beams\n ctx.globalAlpha = 0.15;\n ctx.fillStyle = '#c7d2fe';\n for (const fx of [0.3, 0.5, 0.7]) {\n const bx = sx0 + sw * fx;\n ctx.beginPath();\n ctx.moveTo(bx - 5, pitchToTY(Math.min(HALF_VFOV, stageTopPitch + 18)));\n ctx.lineTo(bx - sw * 0.09, sy1);\n ctx.lineTo(bx + sw * 0.09, sy1);\n ctx.lineTo(bx + 5, pitchToTY(Math.min(HALF_VFOV, stageTopPitch + 18)));\n ctx.closePath();\n ctx.fill();\n }\n ctx.globalAlpha = 1;\n\n // a few rig lights across the ceiling\n ctx.fillStyle = 'rgba(199,210,254,0.75)';\n for (let i = 0; i < 8; i++) {\n ctx.beginPath();\n ctx.arc(((i + 0.5) / 8) * TW, pitchToTY(HALF_VFOV - 4 - (i % 2) * 3), 2.2, 0, Math.PI * 2);\n ctx.fill();\n }\n\n // seat-back rows in the foreground for depth\n ctx.fillStyle = 'rgba(10,13,20,0.9)';\n ctx.fillRect(0, TH - 26, TW, 26);\n ctx.fillStyle = 'rgba(30,37,54,0.9)';\n for (let i = 0; i < 9; i++) ctx.fillRect(i * (TW / 9) + 6, TH - 22, TW / 9 - 12, 14);\n\n return { url: canvas.toDataURL('image/jpeg', 0.8), distanceM: Math.round(distM) };\n}\n","/**\n * Locale bundle loader — keeps non-English translations OUT of the initial\n * bundle (the 60 KB SDK budget is a product contract) and code-splits each\n * locale so a page/SDK only downloads the language it actually uses.\n *\n * `loadLocale('de')` dynamic-imports the German dictionary, registers it via\n * setLocale(), and resolves once it's active. English is built in, so\n * `loadLocale('en')` is synchronous and never fetches. Unknown/unsupported\n * codes fall back to English without throwing.\n */\nimport { setLocale, resolveLocale, type Dict, type Locale } from './index';\n\n/** Dynamic importers per non-English locale (English ships in the core). */\nconst LOADERS: Record<Exclude<Locale, 'en'>, () => Promise<{ default: Dict }>> = {\n es: () => import('./locales/es').then((m) => ({ default: m.es })),\n de: () => import('./locales/de').then((m) => ({ default: m.de })),\n fr: () => import('./locales/fr').then((m) => ({ default: m.fr })),\n};\n\nconst loaded = new Set<Locale>(['en']);\n\n/**\n * Resolve `code` to a supported locale, load its bundle if needed, and make it\n * active. Returns the locale that ended up active (English on any failure).\n */\nexport async function loadLocale(code?: string | null): Promise<Locale> {\n const locale = resolveLocale(code);\n if (locale === 'en' || loaded.has(locale)) {\n setLocale(locale);\n return locale;\n }\n try {\n const mod = await LOADERS[locale]();\n setLocale(locale, mod.default);\n loaded.add(locale);\n return locale;\n } catch {\n setLocale('en');\n return 'en';\n }\n}\n"],"mappings":"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","names":["t","objects","t","KImage","t"]}
|
|
1
|
+
{"version":3,"sources":["../src/i18n/locales/es.ts","../src/i18n/locales/de.ts","../src/i18n/locales/fr.ts","../src/index.ts","../src/core/types.ts","../src/core/layout.ts","../src/core/ga.ts","../src/core/sections.ts","../src/engine/SeatmapRenderer.ts","../src/lib/money.ts","../src/i18n/locales/en.ts","../src/i18n/index.ts","../src/core/orphans.ts","../src/picker/PickerController.ts","../src/view/generatePanorama.ts","../src/i18n/bundles.ts"],"sourcesContent":["/**\n * Spanish (es) bundle — neutral/international Spanish translation.\n * Follows the same key structure as en.ts; all placeholders and brand\n * names preserved.\n */\n\nimport type { Dict } from '../index';\n\nexport const es: Dict = {\n // shared\n 'common.cancel': 'Cancelar',\n 'common.close': 'Cerrar',\n 'common.done': 'Listo',\n 'common.copied': '✓ Copiado',\n\n // buyer picker (extraction in progress — P4 of the port plan)\n 'picker.holdSeats': 'Retener asientos y comprar',\n 'picker.completeBooking': 'Completar reserva',\n 'picker.seatsHeld': 'Asientos retenidos — {time}',\n 'picker.holdExpired': 'Tu retención expiró — los asientos fueron liberados. Elige de nuevo.',\n 'picker.seatTaken': 'El asiento {label} fue tomado por otro comprador.',\n 'picker.poweredBy': 'Con la tecnología de SeatLayer',\n 'picker.testMode': 'MODO DE PRUEBA',\n 'picker.colorblind': 'Colores aptos para daltonismo',\n 'picker.orphanHint': 'Esto deja un asiento aislado — considera desplazarte un asiento.',\n 'picker.seats.one': '{count} asiento',\n 'picker.seats.other': '{count} asientos',\n\n // renderer (drawn on the Konva map — shared by the embed SDK)\n 'map.aria': 'Mapa de asientos. Usa las flechas para moverte entre asientos, Intro para seleccionar.',\n 'map.seatsLeft': '{count} LIBRES',\n 'map.statusHeld': 'En espera',\n 'map.statusTaken': 'Ocupado',\n 'map.fromPrice': 'DESDE {price}',\n\n // buyer picker page (src/pages/PickerPage.tsx)\n 'picker.language': 'Idioma',\n 'picker.zoomToFit': 'Ajustar zoom',\n 'picker.viewMode': 'Modo de vista',\n 'picker.floor': 'Piso',\n 'picker.zoomLevel': 'Nivel de zoom',\n 'picker.rungTip.zones': 'Vista general — grupos de secciones como Grada norte o VIP',\n 'picker.rungTip.sections': 'Bloques de sección — mezcla de categorías + matiz de disponibilidad',\n 'picker.rungTip.seats': 'Asientos individuales — los bloques se convierten en puntos',\n 'picker.rungLabel.zones': 'ZONAS',\n 'picker.rungLabel.sections': 'SECCIONES',\n 'picker.rungLabel.seats': 'ASIENTOS',\n 'picker.sectionSummaryAria': 'Resumen de sección {label}',\n 'picker.closeSectionSummary': 'Cerrar resumen de sección',\n 'picker.seatsLeftInSection.one': '{count} asiento disponible',\n 'picker.seatsLeftInSection.other': '{count} asientos disponibles',\n 'picker.overview': 'Descripción general',\n 'picker.tapSeatHint': 'Toca cualquier asiento para ver su vista',\n 'picker.chartSize': 'Tamaño del gráfico',\n 'picker.custom': 'Personalizado',\n 'picker.categories': 'Categorías',\n 'picker.accessibility': 'Accesibilidad',\n 'picker.showAnyAccessible': 'Mostrar cualquier asiento accesible',\n 'picker.any': 'Cualquiera',\n 'picker.yourSeats': 'Tus asientos',\n 'picker.emptySeats': 'Toca asientos en el mapa',\n 'picker.emptySeatsWithGa': 'Toca asientos en el mapa · toca un área de pie para entradas de entrada general',\n 'picker.oneFewer': 'Uno menos',\n 'picker.oneMore': 'Uno más',\n 'picker.remove': 'Eliminar {label}',\n 'picker.ticketTierFor': 'Categoría de entrada para {label}',\n 'picker.total': 'Total: {amount}',\n 'picker.viewFromSeat': 'Vista desde el asiento {label}',\n 'picker.real360': 'REAL 360°',\n 'picker.preview': 'VISTA PREVIA',\n 'picker.open360': 'Abrir vista de 360°',\n 'picker.sightline': '≈ {rows} filas del escenario · {angle}° fuera del centro',\n 'picker.bookedDemo': '¡Reservado! (demostración)',\n 'picker.bookButton.one': 'Reservar {count} entrada — {amount}',\n 'picker.bookButton.other': 'Reservar {count} entradas — {amount}',\n 'picker.simulateCrowd': 'Simular multitud: {state}',\n 'picker.on': 'ACTIVADO',\n 'picker.off': 'DESACTIVADO',\n 'picker.panorama360': 'Foto de 360° del lugar',\n 'picker.illustrationCaption': 'ilustración · ≈ {m} m del escenario',\n};\n","/**\n * German bundle — native-quality translations of the English reference dictionary.\n * Keys are identical to en.ts; values are translated to German (de).\n *\n * Conventions:\n * - flat dot-namespaced keys: \"<surface>.<element>\" (picker.holdSeats)\n * - {name} interpolation, {count} reserved for tCount plural keys\n * - plural keys end in \".one\" / \".other\" (Intl.PluralRules categories)\n */\n\nimport type { Dict } from '../index';\n\nexport const de: Dict = {\n // shared\n 'common.cancel': 'Abbrechen',\n 'common.close': 'Schließen',\n 'common.done': 'Fertig',\n 'common.copied': '✓ Kopiert',\n\n // buyer picker (extraction in progress — P4 of the port plan)\n 'picker.holdSeats': 'Plätze reservieren & Kasse',\n 'picker.completeBooking': 'Buchung abschließen',\n 'picker.seatsHeld': 'Plätze reserviert — {time}',\n 'picker.holdExpired': 'Ihre Reservierung ist abgelaufen — die Plätze wurden freigegeben. Bitte erneut auswählen.',\n 'picker.seatTaken': 'Platz {label} wurde gerade von einem anderen Käufer gebucht.',\n 'picker.poweredBy': 'Bereitgestellt von SeatLayer',\n 'picker.testMode': 'TESTMODUS',\n 'picker.colorblind': 'Farbenblind-freundliche Farben',\n 'picker.orphanHint': 'Dadurch bleibt ein einzelner Platz übrig — rücken Sie ggf. einen Platz weiter.',\n 'picker.seats.one': '{count} Platz',\n 'picker.seats.other': '{count} Plätze',\n\n // renderer (drawn on the Konva map — shared by the embed SDK)\n 'map.aria': 'Sitzplan. Mit Pfeiltasten zwischen Plätzen navigieren, Eingabe zum Auswählen.',\n 'map.seatsLeft': '{count} FREI',\n 'map.statusHeld': 'Reserviert',\n 'map.statusTaken': 'Vergeben',\n 'map.fromPrice': 'AB {price}',\n\n // buyer picker page (src/pages/PickerPage.tsx)\n 'picker.language': 'Sprache',\n 'picker.zoomToFit': 'Auf Größe anpassen',\n 'picker.viewMode': 'Ansichtsmodus',\n 'picker.floor': 'Etage',\n 'picker.zoomLevel': 'Zoomstufe',\n 'picker.rungTip.zones': 'Übersicht — Bereichsgruppen wie Nordtribüne oder VIP',\n 'picker.rungTip.sections': 'Bereichs-Blöcke — Kategoriesortierung + Verfügbarkeitstönung',\n 'picker.rungTip.seats': 'Einzelne Plätze — Blöcke lösen sich zu Punkten auf',\n 'picker.rungLabel.zones': 'ZONEN',\n 'picker.rungLabel.sections': 'BEREICHE',\n 'picker.rungLabel.seats': 'PLÄTZE',\n 'picker.sectionSummaryAria': 'Bereichszusammenfassung {label}',\n 'picker.closeSectionSummary': 'Bereichszusammenfassung schließen',\n 'picker.seatsLeftInSection.one': '{count} Platz verfügbar',\n 'picker.seatsLeftInSection.other': '{count} Plätze verfügbar',\n 'picker.overview': 'Übersicht',\n 'picker.tapSeatHint': 'Tippen Sie auf einen Platz, um die Ansicht zu prüfen',\n 'picker.chartSize': 'Kartengröße',\n 'picker.custom': 'Benutzerdefiniert',\n 'picker.categories': 'Kategorien',\n 'picker.accessibility': 'Barrierefreiheit',\n 'picker.showAnyAccessible': 'Jeden barrierefreien Platz anzeigen',\n 'picker.any': 'Beliebig',\n 'picker.yourSeats': 'Ihre Plätze',\n 'picker.emptySeats': 'Tippen Sie auf die Plätze auf der Karte',\n 'picker.emptySeatsWithGa': 'Tippen Sie auf die Plätze auf der Karte · tippen Sie auf einen Stehbereich für Stehplatztickets',\n 'picker.oneFewer': 'Einen weniger',\n 'picker.oneMore': 'Einen mehr',\n 'picker.remove': '{label} entfernen',\n 'picker.ticketTierFor': 'Ticketklasse für {label}',\n 'picker.total': 'Gesamt: {amount}',\n 'picker.viewFromSeat': 'Ansicht von Platz {label}',\n 'picker.real360': 'REAL 360°',\n 'picker.preview': 'VORSCHAU',\n 'picker.open360': 'Öffnen Sie die 360°-Ansicht',\n 'picker.sightline': '≈ {rows} Reihen von der Bühne · {angle}° seitlich versetzt',\n 'picker.bookedDemo': 'Gebucht! (Demo)',\n 'picker.bookButton.one': '{count} Ticket buchen — {amount}',\n 'picker.bookButton.other': '{count} Tickets buchen — {amount}',\n 'picker.simulateCrowd': 'Menschenmenge simulieren: {state}',\n 'picker.on': 'AN',\n 'picker.off': 'AUS',\n 'picker.panorama360': '360°-Veranstaltungsfotos',\n 'picker.illustrationCaption': 'Illustration · ≈ {m} m von der Bühne',\n};\n","/**\n * French (fr) bundle — native French translation.\n * Follows the same key structure as en.ts; all placeholders and brand\n * names preserved.\n */\n\nimport type { Dict } from '../index';\n\nexport const fr: Dict = {\n // shared\n 'common.cancel': 'Annuler',\n 'common.close': 'Fermer',\n 'common.done': 'Terminé',\n 'common.copied': '✓ Copié',\n\n // buyer picker (extraction in progress — P4 of the port plan)\n 'picker.holdSeats': 'Réserver les sièges et valider',\n 'picker.completeBooking': 'Terminer la réservation',\n 'picker.seatsHeld': 'Sièges réservés — {time}',\n 'picker.holdExpired': 'Votre réservation a expiré — les sièges ont été libérés. Sélectionnez à nouveau.',\n 'picker.seatTaken': 'Le siège {label} vient d\\'être réservé par un autre acheteur.',\n 'picker.poweredBy': 'Propulsé par SeatLayer',\n 'picker.testMode': 'MODE TEST',\n 'picker.colorblind': 'Couleurs adaptées au daltonisme',\n 'picker.orphanHint': \"Cela laisse un siège isolé — pensez à vous décaler d'un siège.\",\n 'picker.seats.one': '{count} siège',\n 'picker.seats.other': '{count} sièges',\n\n // renderer (drawn on the Konva map — shared by the embed SDK)\n 'map.aria': 'Plan de salle. Utilisez les flèches pour naviguer entre les sièges, Entrée pour sélectionner.',\n 'map.seatsLeft': '{count} LIBRES',\n 'map.statusHeld': 'En attente',\n 'map.statusTaken': 'Pris',\n 'map.fromPrice': 'DÈS {price}',\n\n // buyer picker page (src/pages/PickerPage.tsx)\n 'picker.language': 'Langue',\n 'picker.zoomToFit': 'Ajuster le zoom',\n 'picker.viewMode': 'Mode d\\'affichage',\n 'picker.floor': 'Étage',\n 'picker.zoomLevel': 'Niveau de zoom',\n 'picker.rungTip.zones': 'Vue générale — groupes de sections comme Tribune nord ou VIP',\n 'picker.rungTip.sections': 'Blocs de sections — mélange de catégories + teinte de disponibilité',\n 'picker.rungTip.seats': 'Sièges individuels — les blocs se transforment en points',\n 'picker.rungLabel.zones': 'ZONES',\n 'picker.rungLabel.sections': 'SECTIONS',\n 'picker.rungLabel.seats': 'SIÈGES',\n 'picker.sectionSummaryAria': 'Résumé de la section {label}',\n 'picker.closeSectionSummary': 'Fermer le résumé de la section',\n 'picker.seatsLeftInSection.one': '{count} siège restant',\n 'picker.seatsLeftInSection.other': '{count} sièges restants',\n 'picker.overview': 'Vue d\\'ensemble',\n 'picker.tapSeatHint': 'Appuyez sur un siège pour vérifier sa vue',\n 'picker.chartSize': 'Taille du plan',\n 'picker.custom': 'Personnalisé',\n 'picker.categories': 'Catégories',\n 'picker.accessibility': 'Accessibilité',\n 'picker.showAnyAccessible': 'Afficher un siège accessible',\n 'picker.any': 'N\\'importe quel',\n 'picker.yourSeats': 'Vos sièges',\n 'picker.emptySeats': 'Appuyez sur les sièges sur le plan',\n 'picker.emptySeatsWithGa': 'Appuyez sur les sièges sur le plan · appuyez sur une zone debout pour les billets GA',\n 'picker.oneFewer': 'Un de moins',\n 'picker.oneMore': 'Un de plus',\n 'picker.remove': 'Supprimer {label}',\n 'picker.ticketTierFor': 'Catégorie de billet pour {label}',\n 'picker.total': 'Total : {amount}',\n 'picker.viewFromSeat': 'Vue depuis le siège {label}',\n 'picker.real360': 'VRAI 360°',\n 'picker.preview': 'APERÇU',\n 'picker.open360': 'Ouvrir la vue à 360°',\n 'picker.sightline': '≈ {rows} rangées de la scène · {angle}° décalé du centre',\n 'picker.bookedDemo': 'Réservé ! (démo)',\n 'picker.bookButton.one': 'Réserver {count} billet — {amount}',\n 'picker.bookButton.other': 'Réserver {count} billets — {amount}',\n 'picker.simulateCrowd': 'Simuler la foule : {state}',\n 'picker.on': 'ACTIVÉ',\n 'picker.off': 'DÉSACTIVÉ',\n 'picker.panorama360': 'Photo panoramique 360° du lieu',\n 'picker.illustrationCaption': 'illustration · ≈ {m} m de la scène',\n};\n","/**\n * @seatlayer/core — the shared, framework-agnostic seat-rendering engine.\n *\n * Pure TypeScript + Konva (HTML canvas). No React, no framework. This is the\n * brain shared by the SeatLayer dashboard and every SDK wrapper. It is synced\n * byte-for-byte from the main app via `scripts/sync-core.mjs` until the app\n * migrates to consume this package directly.\n */\nexport * from './core/types';\nexport * from './core/layout';\nexport * from './core/ga';\nexport * from './core/sections';\nexport * from './engine/SeatmapRenderer';\nexport * from './picker/PickerController';\nexport * from './view/generatePanorama';\nexport * from './i18n';\nexport * from './i18n/bundles';\nexport * from './lib/money';\n","/**\n * SeatMap chart document — the single source of truth shared by the\n * Designer (authoring) and the Renderer (buyer picker).\n *\n * Mirrors docs/seatmap-build-spec.md §5. Coordinates are abstract units\n * (roughly \"pixels at scale 1\"); the renderer fits the chart to its container.\n * Rows are PARAMETRIC (origin + count + spacing + curve + rotation) — never\n * store per-seat coordinates in the document; expansion happens in layout.ts.\n */\n\nexport interface Point {\n x: number;\n y: number;\n}\n\nexport interface Category {\n key: string;\n label: string;\n color: string;\n /** Base price — used when the category has no explicit tiers. */\n price?: number;\n /**\n * Ticket tiers (Adult / Child / Senior…). When present, a buyer picks a tier\n * per seat in this category and the tier's price applies; the first tier is the\n * default. Per-category (not per-seat) pricing — see Batch 3.5. Empty/absent =\n * a single price (the `price` above).\n */\n tiers?: CategoryTier[];\n}\n\n/** One ticket tier within a category: a named price (Adult, Child, Senior…). */\nexport interface CategoryTier {\n id: string;\n name: string;\n price: number;\n}\n\n/**\n * Accessibility accommodations a seat can carry. Mirrors the taxonomy real\n * venues (and seats.io) expose so buyers can filter for exactly what they need\n * and organizers can mark seats precisely. `wheelchair` is the legacy default.\n */\nexport type AccessibilityType =\n | 'wheelchair'\n | 'companion'\n | 'semi-ambulatory'\n | 'hearing'\n | 'sign-language'\n | 'plus-size'\n | 'lift-armrest';\n\nexport interface AccessibilityMeta {\n key: AccessibilityType;\n /** Full descriptive label (designer checkbox, picker legend). */\n label: string;\n /** Compact label for chips/badges. */\n short: string;\n /** Single-glyph badge shown on seat chips + filter chips. */\n icon: string;\n}\n\n/** Ordered taxonomy — drives the designer seat panel and the picker filters. */\nexport const ACCESSIBILITY_TYPES: AccessibilityMeta[] = [\n { key: 'wheelchair', label: 'Wheelchair space', short: 'Wheelchair', icon: '♿' },\n { key: 'companion', label: 'Companion seat', short: 'Companion', icon: '🧑🤝🧑' },\n { key: 'semi-ambulatory', label: 'Semi-ambulatory (limited mobility)', short: 'Limited mobility', icon: '🦯' },\n { key: 'hearing', label: 'Assistive listening', short: 'Hearing', icon: '🦻' },\n { key: 'sign-language', label: 'Sign-language view', short: 'Sign language', icon: '🤟' },\n { key: 'plus-size', label: 'Plus-size seat', short: 'Plus-size', icon: '💺' },\n { key: 'lift-armrest', label: 'Lift-up armrest', short: 'Lift armrest', icon: '↕️' },\n];\n\nconst ACCESSIBILITY_LABEL = new Map(ACCESSIBILITY_TYPES.map((a) => [a.key, a]));\n\n/** Metadata for one accessibility key (undefined for unknown keys). */\nexport function accessibilityMeta(key: AccessibilityType): AccessibilityMeta | undefined {\n return ACCESSIBILITY_LABEL.get(key);\n}\n\nexport interface SeatOverride {\n /** 0-based seat index within the row. */\n index: number;\n /** Physical seat absent (pillar, sound desk) — numbering gap preserved. */\n skip?: boolean;\n /** Position nudge in chart units. */\n dx?: number;\n dy?: number;\n /** Replace the computed label entirely. */\n label?: string;\n categoryKey?: string;\n /** @deprecated legacy flag — read as `['wheelchair']`; write `accessibility`. */\n accessible?: boolean;\n /** Accessibility accommodations of this seat (empty/absent = none). */\n accessibility?: AccessibilityType[];\n}\n\n/** Brand/venue theming — applied by the renderer in both designer and picker. */\nexport interface ChartTheme {\n /** Canvas background color (default dark: #0e1117-ish radial). */\n background?: string;\n /** Seat label text color (default dark ink #0b1220). */\n seatLabelColor?: string;\n /** Selection ring / accent color (default white ring + brand accent). */\n selectionColor?: string;\n /** Décor (stage/shape) default fill. */\n decorFill?: string;\n /** Free-text color default. */\n textColor?: string;\n /** Font family (CSS stack) for all rendered text — seat labels, sections, décor text. */\n fontFamily?: string;\n /** Seat size multiplier on the base radius (0.7–1.6, default 1) — bigger seats fit longer labels. */\n seatScale?: number;\n // ---- White-label branding (applied by the buyer picker chrome) ----\n /** Brand accent color — recolors buttons, links, the hold pill, selection UI. */\n accent?: string;\n /** Ink color for text on the accent (e.g. button labels). Default light. */\n accentInk?: string;\n /** Organizer logo shown in the picker header (data/R2 URL). Falls back to the name. */\n logoUrl?: string;\n /** Brand/venue name shown in the picker header when no event name is set. */\n brandName?: string;\n /** Paid-tier flag: hide the \"Powered by SeatMap\" badge. */\n hideBadge?: boolean;\n}\n\nexport interface RowObject {\n type: 'row';\n id: string;\n /** Row label, e.g. \"A\". Seat labels are `${label}-${n}`. */\n label: string;\n /** Position of the FIRST seat. */\n origin: Point;\n /** Degrees, clockwise. 0 = seats laid out along +x. */\n rotation: number;\n /**\n * Total arc sweep in degrees across the whole row. 0 = straight.\n * Positive bends away from +y (concave toward the focal point when the\n * row faces it). Typical theatre rows: 10–40.\n */\n curve: number;\n seatCount: number;\n /** Distance between adjacent seat centers, in chart units. */\n seatSpacing: number;\n categoryKey: string;\n /** First seat number (default 1). */\n seatLabelStart?: number;\n /** Seat numbering within the row (default ltr, step 1). */\n seatNumbering?: {\n /** ltr / rtl number from an end; `center` numbers outward from the middle\n * (centre seat lowest — the premium-centre theatre convention). */\n direction: 'ltr' | 'rtl' | 'center';\n /** 2 = odd/even numbering (1,3,5… — start at 2 for evens). */\n step?: 1 | 2;\n };\n /**\n * Per-seat exceptions, keyed by seat index (0-based position in the row).\n * `skip` removes the physical seat but keeps the numbering gap (theatre\n * convention: a pillar eats A-3; A-4 stays A-4).\n */\n overrides?: SeatOverride[];\n /**\n * Organizer-supplied equirectangular 360 (or wide photo) shown as the\n * view-from-seat for every seat in this row. When absent, the picker\n * generates a synthetic panorama from chart geometry.\n */\n viewFromSeatUrl?: string;\n}\n\nexport interface GAAreaObject {\n type: 'gaArea';\n id: string;\n label: string;\n /** Closed polygon, in chart units. */\n points: Point[];\n capacity: number;\n categoryKey: string;\n}\n\n/** Non-bookable décor: stage, walls, exits. */\nexport interface ShapeObject {\n type: 'shape';\n id: string;\n kind: 'rect' | 'ellipse' | 'polygon';\n label?: string;\n /** For rect/ellipse: bounding box. For a stage polygon: the base (pre-shape) box, so its kind can be regenerated. */\n x?: number;\n y?: number;\n width?: number;\n height?: number;\n /** For polygon. */\n points?: Point[];\n fill?: string;\n /** Degrees clockwise about the shape's center (default 0). Applied at render time. */\n rotation?: number;\n /**\n * Semantic tag driving special rendering. `'stage'` gets the gradient +\n * prominent uppercase label treatment; a décor landmark role (bar, exit…)\n * gets a quieter label. Loose string to avoid a circular import with\n * stage.ts / decor.ts (see StageKind / DecorRole there).\n */\n role?: string;\n /** For a stage: which `StageKind` its polygon was generated from. */\n stageKind?: string;\n}\n\n/** Seats arranged around a table; bookable per-seat or as a whole. */\nexport interface TableObject {\n type: 'table';\n id: string;\n /** e.g. \"T1\" — seat labels are `${label}-${n}`. */\n label: string;\n center: Point;\n shape: 'round' | 'rect';\n /** Seats around the perimeter (round) or along the enabled edges (rect). */\n seatCount: number;\n /** Rect tables: which edges get seats (default ['top','bottom']). */\n sides?: Array<'top' | 'bottom' | 'left' | 'right'>;\n rotation: number;\n /** Round tables. */\n radius?: number;\n /**\n * Round tables: the arc (in degrees) the seats occupy, default 360 (full\n * ring). Below 360 leaves an open side — e.g. a service gap for waiters, a\n * head table facing the room, or clearance against a wall. The opening is\n * centred on the `rotation` direction; seats spread across the rest.\n */\n seatArc?: number;\n /** Rect tables. */\n width?: number;\n height?: number;\n categoryKey: string;\n /** Whole-table booking: buyers get all seats or none (per-event override later). */\n bookAsWhole?: boolean;\n}\n\n/** A booth: one bookable unit rendered as a block (trade shows, VIP boxes). */\nexport interface BoothObject {\n type: 'booth';\n id: string;\n label: string;\n center: Point;\n width: number;\n height: number;\n rotation: number;\n categoryKey: string;\n}\n\n/**\n * A named region of the venue (Balcony Left, Floor B…). Sections are outlines\n * only — objects belong to a section spatially (center inside the outline),\n * keeping the document flat (no nesting; simpler for tools and for AI edits).\n * Renderer: far zoom shows section shapes/labels instead of seats; clicking\n * a section zooms into it.\n */\nexport interface SectionObject {\n type: 'section';\n id: string;\n label: string;\n /** Closed polygon, chart units. */\n outline: Point[];\n /** Optional tint override (defaults to a neutral fill / dominant category mix). */\n color?: string;\n /** Zone this section belongs to (id into `ChartDoc.zones`). Far-zoom nav + pricing group. */\n zone?: string;\n /**\n * Tier height. 0 = floor (default). Higher values lift the section in the\n * picker's isometric (\"3D\") view, drawn on extruded side faces. Same field a\n * future multi-floor mode reuses — authored in 2D, never drawn by the user.\n */\n elevation?: number;\n /** Uniform scale about the outline centroid (1 = as drawn). Scales members too. */\n scale?: number;\n /** 0–1: how strongly member-row curves are bent toward a common arc fitted to the outline. */\n smoothing?: number;\n /** Degrees clockwise about the outline centroid (default 0). Rotates members too. */\n rotation?: number;\n}\n\n/**\n * A group of sections (Lower Bowl, Upper Bowl, Floor…). One concept, three jobs:\n * the farthest-zoom navigation unit, a pricing group, and (Batch 3) a timed-\n * release unit. Kept as a flat list on the doc; sections point back by `zone` id.\n */\nexport interface ZoneDef {\n id: string;\n label: string;\n color?: string;\n}\n\n/**\n * Selection layer — a hit-test/dim filter in the designer, NOT z-order management.\n * Fixed set of four; derived from object type via `layerOf()` (no per-object field yet).\n */\nexport type SelectionLayer = 'interactive' | 'background' | 'foreground' | 'surroundings';\n\n/** Derive an object's selection layer from its type (design contract, HANDOFF §03). */\nexport function layerOf(obj: ChartObject): SelectionLayer {\n switch (obj.type) {\n case 'row':\n case 'table':\n case 'gaArea':\n case 'booth':\n case 'section':\n return 'interactive';\n // stage / décor live on 'shape'; free text + decor images are background furniture.\n case 'shape':\n case 'text':\n case 'decorImage':\n return 'background';\n default:\n return 'interactive';\n }\n}\n\n/** Free-standing text on the chart (aisle names, door labels…). */\nexport interface TextObject {\n type: 'text';\n id: string;\n text: string;\n position: Point;\n fontSize: number;\n rotation: number;\n color?: string;\n}\n\n/**\n * A raster/vector decor graphic drawn IN the chart, beneath the seats and\n * sections (ice rink, basketball court, stage art, pitch markings). Purely\n * visual venue context — never bookable, never hit-tested, so it never steals a\n * seat click. `href` is a self-contained data URL (image or SVG) produced by the\n * same client-side downscale used for row photos, so it travels with the doc and\n * caches as a single bitmap blit (zero per-frame cost). Placed by top-left\n * (x,y) + size, rotated about its centre — the same handles a shape rect uses.\n */\nexport interface DecorImageObject {\n type: 'decorImage';\n id: string;\n /** Image or SVG data URL. */\n href: string;\n x: number;\n y: number;\n width: number;\n height: number;\n /** Degrees clockwise about the image centre (default 0). */\n rotation?: number;\n /** 0–1 (default 1). Multiplied by any chart-theme dimming at render time. */\n opacity?: number;\n /** Optional caption for the designer inspector / accessibility (not drawn). */\n label?: string;\n}\n\nexport type ChartObject =\n | RowObject\n | GAAreaObject\n | ShapeObject\n | TableObject\n | BoothObject\n | TextObject\n | SectionObject\n | DecorImageObject;\n\n/**\n * One floor / level of a multi-floor venue (Batch 5). Each floor owns its own\n * geometry, stage focal point, and trace image; categories/zones/tiers stay\n * chart-global (one event, one inventory). A single-floor chart has NO `floors`\n * — its `objects[]` is the whole venue — so all existing charts are untouched.\n */\nexport interface Floor {\n id: string;\n name: string;\n objects: ChartObject[];\n focalPoint: Point;\n backgroundImage?: ChartDoc['backgroundImage'];\n}\n\nexport interface ChartDoc {\n version: 1;\n name: string;\n venueType: 'SIMPLE' | 'MIXED';\n /** The stage / point every seat looks at. Anchors seat-view + sightlines.\n * Multi-floor: mirrors floor 0; each floor also carries its own focalPoint. */\n focalPoint: Point;\n categories: Category[];\n /** Section groupings for far-zoom navigation + pricing (optional; sections reference by id). */\n zones?: ZoneDef[];\n /** Multi-floor venues (Batch 5): present ⇒ floors[] is the source of truth;\n * absent ⇒ single-floor and `objects` below is the whole chart. `objects`\n * is kept mirroring floor 0 so single-floor readers never branch. */\n floors?: Floor[];\n objects: ChartObject[];\n /** Floor-plan photo the organizer traces over (designer-only aid, also rendered dimly in picker if kept). */\n backgroundImage?: {\n url: string;\n center: Point;\n /** Rendered width in chart units (height follows the image aspect). */\n width: number;\n opacity: number;\n locked?: boolean;\n };\n /** Brand/venue theming (colors); categories carry their own colors separately. */\n theme?: ChartTheme;\n /** Parametric-template provenance: present ⇒ the chart came from a capacity-\n * adjustable template family, and the designer offers a capacity control that\n * regenerates it at a new target seat count (Batch 4 \"curated singles + resize\"). */\n template?: { family: string; targetSeats: number };\n}\n\n// ---------------------------------------------------------------------------\n// Expanded (render-time) model — produced by layout.ts, consumed by the engine\n// ---------------------------------------------------------------------------\n\nexport interface ExpandedSeat {\n /** Stable id: `${rowId}:${index}` */\n id: string;\n /** Public label: `${rowLabel}-${seatNumber}` */\n label: string;\n x: number;\n y: number;\n rowId: string;\n categoryKey: string;\n /** 'booth' units render as blocks (dimensions looked up via rowId = booth id). */\n kind?: 'seat' | 'booth';\n /** True when the seat has any accessibility accommodation — renderer rings/dims these. */\n accessible?: boolean;\n /** Specific accessibility accommodations (absent = none) — picker badges/filters these. */\n accessibility?: AccessibilityType[];\n /** Organizer-supplied view-from-seat image (inherited from the row). */\n viewUrl?: string;\n}\n\nexport type SeatStatus = 'free' | 'held' | 'booked' | 'not_for_sale';\n\n// ---------------------------------------------------------------------------\n// Renderer engine public API — implemented in src/engine/SeatmapRenderer.ts\n// ---------------------------------------------------------------------------\n\nexport interface RendererCallbacks {\n onSelect?: (seat: ExpandedSeat) => void;\n onDeselect?: (seat: ExpandedSeat) => void;\n /** seat is null when the pointer leaves any seat. */\n onHover?: (seat: ExpandedSeat | null) => void;\n /** Keyboard focus moved to a seat (arrow-key navigation) — for screen-reader announcements. */\n onFocusSeat?: (seat: ExpandedSeat | null) => void;\n /** Called ~1×/sec with the measured frames-per-second. */\n onFps?: (fps: number) => void;\n /** Fired when a GA area is clicked (quantity picking is UI-side). */\n onGAClick?: (areaId: string) => void;\n /**\n * Fired when a tap lands on a section outline while seats are NOT the active\n * rung (i.e. zoomed out, section/zone LOD). The host glides in + shows a\n * section-summary card instead of trying to select a 4px seat (Slice 5).\n */\n onSectionTap?: (sectionId: string) => void;\n /**\n * Fired when a seat/deck is tapped in the 3D all-floors stacked overview — the\n * host drops back to the flat 2D map on that floor (\"tap a deck to enter\").\n */\n onDeckTap?: (floorId: string) => void;\n /** Fired after any pan/zoom/resize settles — re-anchor screen-space overlays. */\n onViewChange?: () => void;\n /**\n * Organizer manage-mode only (`manageMode` + `marqueeSelect`): fired on\n * pointer-UP after a rubber-band marquee drag, or a ⌘A/Escape bulk shortcut,\n * with the FULL current selection (selectable seats only). The host toolbar\n * reads this to drive bulk block/unblock. Never fires when manageMode is off.\n */\n onMarquee?: (seats: ExpandedSeat[]) => void;\n}\n\n/** Far-zoom level-of-detail rung: whole zones → section blocks → individual seats. */\nexport type LodRung = 'zones' | 'sections' | 'seats';\n\nexport interface RendererOptions extends RendererCallbacks {\n /** Max seats selectable at once (default 10). */\n maxSelection?: number;\n /** Only these statuses are clickable (default ['free']). */\n selectableStatuses?: SeatStatus[];\n /**\n * Opt-in host behaviour flag — the renderer's own click/selection logic is\n * unchanged (it still selects + fires `onSelect` immediately, so the seat\n * highlights right away). When true, the host (e.g. PublicEventPage) treats\n * that `onSelect` as a pending candidate and shows a confirm card instead of\n * pushing straight into the cart; `deselect([seat.id])` on Cancel un-highlights.\n */\n confirmSelection?: boolean;\n /** ISO 4217 currency for on-map prices (\"FROM …\"); defaults to money.DEFAULT_CURRENCY.\n * Locale for grouping/symbol placement comes from the active i18n locale. */\n currency?: string;\n /**\n * Organizer manage surface (SDK SeatManager). Opt-in — enables the manage-mode\n * gestures (marquee, ⌘A/Escape) and the bulk-selection helpers. Buyer pan /\n * pinch / tap and every existing code path are byte-identical when this is\n * false (every manage branch is gated on it). Default false.\n */\n manageMode?: boolean;\n /**\n * When `manageMode` is on, a mouse/pen primary-button drag at the seats rung\n * draws a rubber-band marquee that bulk-selects the seats it covers (emitting\n * `onMarquee` on pointer-up) instead of panning. Touch keeps single-finger\n * pan (pinch to zoom); a middle-button drag pans with a mouse. Disabled below\n * the seats rung (zoom in first). No effect unless `manageMode` is also set.\n */\n marqueeSelect?: boolean;\n}\n\nexport interface ISeatmapRenderer {\n /** Replace the chart. Resets selection and statuses, zooms to fit.\n * `opts.floorId` picks which floor to render on a multi-floor chart (Batch 5). */\n setChart(doc: ChartDoc, opts?: { floorId?: string }): void;\n /** Bulk status update; re-renders affected seats only. */\n setStatus(seatIds: string[], status: SeatStatus): void;\n /**\n * Mark the active buyer's own held seats. They remain server-status `held`,\n * but render with the buyer selection treatment instead of the anonymous\n * unavailable treatment used for another buyer's hold.\n */\n setOwnedHold?(seatIds: string[] | null): void;\n /**\n * Mark one selected seat as the buyer's pending confirmation candidate.\n * The candidate receives a strong focus halo while unrelated seats recede;\n * pass null after Select/Cancel. This is visual only and never mutates the\n * renderer selection.\n */\n setSelectionFocus?(seatId: string | null): void;\n /**\n * SYNCHRONOUS repaint that bypasses requestAnimationFrame. Konva's batchDraw()\n * (used by setStatus and friends) schedules the actual paint on the next rAF\n * tick, which Chrome throttles/pauses on hidden, backgrounded, or occluded\n * tabs — so a seat-status delta updates the scene graph but the pixels never\n * change until the tab is foregrounded again. forceDraw() paints the affected\n * layers immediately (Layer.draw() is synchronous) and flushes any pending\n * cache-debounce, so a caller (visibilitychange catch-up, or an opted-in\n * always-live board) can guarantee the canvas reflects current state\n * regardless of tab visibility. No-op difference in the foreground.\n */\n forceDraw(): void;\n getStatus(seatId: string): SeatStatus;\n getSelection(): ExpandedSeat[];\n clearSelection(): void;\n /**\n * Dynamically update organizer-only interaction without rebuilding the\n * renderer. No buyer surface calls this; every behavior remains gated by\n * `manageMode` exactly as it is at construction time.\n */\n setManageInteraction?(options: {\n manageMode: boolean;\n marqueeSelect: boolean;\n selectableStatuses: SeatStatus[];\n maxSelection?: number;\n }): void;\n /** Organizer-only section heat overlay. Values are normalized 0..1. */\n setSectionHeat?(scores: Record<string, number> | null): void;\n /**\n * Manage-mode bulk selection helpers (no-op / empty unless `manageMode`).\n * They select the matching SELECTABLE seats (respecting `selectableStatuses`\n * + closed sections), union with the current selection, and return the seats\n * they added — the SDK SeatManager expands category/row/section picks to\n * labels and drives one batched block/unblock from them.\n */\n selectAllSelectable?(): ExpandedSeat[];\n selectByLabels?(labels: string[]): ExpandedSeat[];\n /** Selectable seats belonging to a section OR zone id (no selection side-effect). */\n getSelectableInSection?(sectionId: string): ExpandedSeat[];\n /** Programmatic deselect of specific seats (e.g. chip × in the cart). */\n deselect(seatIds: string[]): void;\n /**\n * Brief attention pulse on a seat (a ring that expands + fades once) — used to\n * signal live activity, e.g. a seat \"just taken\" by another buyer via a WS\n * delta. Purely visual; no state change. `color` overrides the default.\n */\n flashSeat(seatId: string, color?: string): void;\n zoomToFit(): void;\n /** Zoom in one step about the viewport center, clamped to the usual zoom bounds. */\n zoomIn(): void;\n /** Zoom out one step about the viewport center, clamped to the usual zoom bounds. */\n zoomOut(): void;\n /** Total seat count of the current chart. */\n seatCount(): number;\n /**\n * Maps a chart-space point (or a seat, by its x/y) to container-relative\n * screen pixels, using the current stage scale/position. Lets host UI anchor\n * DOM overlays (confirm card, tooltip) over a live seat and re-anchor them\n * on `onViewChange`.\n */\n worldToScreen(point: Point): { x: number; y: number };\n /** When on, dim non-accessible free seats so accessible seats stand out. */\n setAccessibleFilter(on: boolean): void;\n /**\n * Dim free seats that lack ANY of these accessibility types. `null` clears the\n * filter; `[]` means \"any accessible seat\" (same as setAccessibleFilter(true)).\n */\n setAccessibilityFilter(types: AccessibilityType[] | null): void;\n /** Legend hover-highlight: dim free seats of other categories (null clears). */\n setCategoryHighlight?(key: string | null): void;\n /** Price-band filter (F4): dim free seats whose category is NOT in `keys`\n * (null clears). The widget resolves which categories fall in the band. */\n setCategoryFilter?(keys: string[] | null): void;\n /** Smoothly frame the currently available seats in these categories. `null`\n * returns to the full chart. Used after an explicit buyer price-filter action. */\n focusCategories?(keys: string[] | null): void;\n /** Dim the seats of these section/zone ids (organizer manager: held-back inventory). */\n setDimmedSections?(ids: string[] | null): void;\n /**\n * Phase 2 event-level section states: mark these section/zone ids `closed` —\n * flat grey block, seats greyed + not pickable, section stays rendered.\n * `null`/empty clears. (Distinct from the buyer's applyHidden seat-strip.)\n */\n setClosedSections?(ids: string[] | null): void;\n /**\n * AXS section-focus: dim + desaturate every other section, draw a calm backdrop\n * behind this section, and glide the camera to frame it. Seat-picking is gated\n * until seats are large enough on screen (≥ LABEL_SCALE). Slice 5 / Phase 2 §4.\n */\n focusSection?(id: string): void;\n /** Clear an AXS section focus (restore full-bowl brightness + drop backdrop). */\n clearSectionFocus?(): void;\n /** The currently AXS-focused section id, or null. */\n getFocusedSection?(): string | null;\n /** World-space rect currently visible in the viewport (minimap viewport frame). */\n getVisibleWorldRect?(): { x: number; y: number; width: number; height: number };\n /** Axis-aligned world bounds of all seats + section outlines (minimap frame). */\n getWorldBounds?(): { x: number; y: number; width: number; height: number };\n /**\n * Colorblind-safe mode: category hues switch to an Okabe-Ito palette and\n * booked seats render hollow (a non-color cue), so seat state never relies\n * on hue alone. Off (the default) renders exactly as before.\n */\n setColorblindSafe?(on: boolean): void;\n /**\n * Switch the projection. `'flat'` = normal top-down; `'isometric'` = the \"3D\"\n * view (affine skew/rotate + elevation lift), hit-testing preserved in screen\n * space. Purely visual — the chart is authored flat. Animated unless reduced-motion.\n */\n setViewMode?(mode: 'flat' | 'isometric'): void;\n /** Current projection (defaults to 'flat' when unimplemented). */\n getViewMode?(): 'flat' | 'isometric';\n /** Multi-floor (Batch 5): switch the shown floor; list floors; read the active id. */\n setActiveFloor?(floorId: string): void;\n getFloors?(): { id: string; name: string }[];\n getActiveFloorId?(): string;\n /** Render all floors stacked (3D overview) vs the active floor. No-op single-floor. */\n setStacked?(on: boolean): void;\n isStacked?(): boolean;\n /**\n * Section id whose outline contains a container-relative screen point (or null).\n * Feeds the far-zoom \"tap a section to zoom in\" flow (Slice 5).\n */\n sectionAt?(clientPoint: Point): string | null;\n /** Seat ids belonging to a section — for the section-summary card (Slice 5). */\n sectionMembers?(id: string): string[];\n /**\n * Smoothly glide (pan+zoom) the camera to frame a section (by id) or a world-\n * space bounds rect over a calm easeInOutCubic glide. `prefers-reduced-motion` snaps.\n * A pointer-down (grab/pan) cancels an in-flight glide. Slice 5 \"glide in\".\n */\n focusRegion?(\n target: string | { x: number; y: number; width: number; height: number },\n opts?: { animate?: boolean; minScale?: number; durationMs?: number },\n ): void;\n /** Current LOD rung derived from zoom (for the ZONES/SECTIONS/SEATS pill). */\n getRung?(): LodRung;\n /** Jump the camera to a rung's zoom band, centred on the chart (glided). */\n setRung?(rung: LodRung): void;\n destroy(): void;\n}\n\n/** localStorage key the Designer writes and the Picker reads. */\nexport const CHART_STORAGE_KEY = 'seatmap.chart';\n","/**\n * Pure geometry helpers — no Konva, no DOM. Turns the parametric chart\n * document into concrete seat coordinates and computes bounding boxes.\n */\n\nimport type {\n AccessibilityType,\n BoothObject,\n ChartDoc,\n ChartObject,\n ExpandedSeat,\n Floor,\n Point,\n RowObject,\n SeatOverride,\n TableObject,\n} from './types';\n\n/** Resolve a seat override's accessibility, honouring the legacy boolean flag. */\nfunction overrideAccessibility(o: SeatOverride | undefined): AccessibilityType[] {\n if (!o) return [];\n if (o.accessibility && o.accessibility.length) return o.accessibility;\n return o.accessible ? ['wheelchair'] : [];\n}\n\nconst DEG = Math.PI / 180;\n/** Seat visual radius (mirrors the renderer) — used only for bounds padding. */\nconst SEAT_R = 9;\n/** How far outside a table's body its seats sit. */\nconst TABLE_SEAT_OFFSET = 16;\n\n/** Rotate a local point clockwise by `deg` (screen coords, +y down) then translate. */\nfunction place(lx: number, ly: number, deg: number, origin: Point): { x: number; y: number } {\n const a = deg * DEG;\n const cos = Math.cos(a);\n const sin = Math.sin(a);\n return {\n x: origin.x + lx * cos - ly * sin,\n y: origin.y + lx * sin + ly * cos,\n };\n}\n\n/**\n * Expand a parametric row into seat positions.\n *\n * Straight (curve === 0): seat i sits at local (i·spacing, 0).\n *\n * Curved: seats lie on a circular arc. Per-seat angular step is\n * `curve/(seatCount-1)`; radius is derived so the chord between neighbours\n * equals seatSpacing → radius = spacing / (2·sin(step/2)). Seat 0 sits at the\n * bottom of the arc (local origin) with the circle centre directly above it at\n * (0,-radius); increasing index sweeps toward +x while the ends rise toward -y,\n * i.e. positive curve is concave toward -y (a row wrapping a stage above it).\n * Local points are then rotated by `rotation` and translated to `origin`.\n *\n * Numbering (labels only, never geometry): `seatNumbering.direction === 'rtl'`\n * numbers from the far physical end; `step === 2` produces odd/even numbering\n * (start at 1 → 1,3,5…; start at 2 → 2,4,6…).\n */\n/** Base (pre-override) seat centre per index — shared by expandRow + designer edit mode. */\nfunction rowSeatPositions(row: RowObject): Point[] {\n const { seatCount, seatSpacing, curve, rotation, origin } = row;\n const out: Point[] = [];\n if (seatCount <= 1) {\n if (seatCount === 1) out.push({ x: origin.x, y: origin.y });\n return out;\n }\n if (curve === 0) {\n for (let i = 0; i < seatCount; i++) out.push(place(i * seatSpacing, 0, rotation, origin));\n return out;\n }\n const arcStep = (curve / (seatCount - 1)) * DEG; // radians per seat\n const radius = seatSpacing / (2 * Math.sin(Math.abs(arcStep) / 2));\n // Centre above seat 0. φ measured from the downward vertical, growing with index.\n for (let i = 0; i < seatCount; i++) {\n const phi = i * arcStep;\n const lx = radius * Math.sin(phi);\n const ly = -radius + radius * Math.cos(phi); // ≤ 0 → ends rise toward -y\n out.push(place(lx, ly, rotation, origin));\n }\n return out;\n}\n\nfunction overrideMap(row: RowObject): Map<number, SeatOverride> {\n const m = new Map<number, SeatOverride>();\n if (row.overrides) for (const o of row.overrides) m.set(o.index, o);\n return m;\n}\n\n/**\n * Every seat slot of a row INCLUDING skipped ones (designer seat-edit mode uses\n * this to draw un-skip handles). Overrides (dx/dy/label/categoryKey) are applied\n * but a skipped slot is flagged, not omitted.\n */\nexport interface RowSeatSlot {\n index: number;\n x: number;\n y: number;\n label: string;\n categoryKey: string;\n skipped: boolean;\n accessible: boolean;\n accessibility: AccessibilityType[];\n}\n\nexport function expandRowSlots(row: RowObject): RowSeatSlot[] {\n const start = row.seatLabelStart ?? 1;\n const dir = row.seatNumbering?.direction ?? 'ltr';\n const step = row.seatNumbering?.step ?? 1;\n const n = row.seatCount;\n let seatNumber: (i: number) => number;\n if (dir === 'center') {\n // Number outward from the middle: rank seats by distance from centre\n // (inner-left wins ties), so the centre seat gets `start`.\n const rank = new Array<number>(n);\n Array.from({ length: n }, (_, i) => i)\n .sort((a, b) => Math.abs(2 * a - (n - 1)) - Math.abs(2 * b - (n - 1)) || a - b)\n .forEach((idx, k) => (rank[idx] = k));\n seatNumber = (i) => start + rank[i] * step;\n } else {\n seatNumber = (i) => start + (dir === 'rtl' ? n - 1 - i : i) * step;\n }\n const ov = overrideMap(row);\n return rowSeatPositions(row).map((p, i) => {\n const o = ov.get(i);\n const accessibility = overrideAccessibility(o);\n return {\n index: i,\n x: p.x + (o?.dx ?? 0),\n y: p.y + (o?.dy ?? 0),\n label: o?.label ?? `${row.label}-${seatNumber(i)}`,\n categoryKey: o?.categoryKey ?? row.categoryKey,\n skipped: !!o?.skip,\n accessible: accessibility.length > 0,\n accessibility,\n };\n });\n}\n\nexport function expandRow(row: RowObject): ExpandedSeat[] {\n const seats: ExpandedSeat[] = [];\n for (const slot of expandRowSlots(row)) {\n if (slot.skipped) continue; // physical seat absent; numbering gap preserved\n seats.push({\n id: `${row.id}:${slot.index}`,\n label: slot.label,\n x: slot.x,\n y: slot.y,\n rowId: row.id,\n categoryKey: slot.categoryKey,\n accessible: slot.accessible || undefined,\n accessibility: slot.accessibility.length ? slot.accessibility : undefined,\n viewUrl: row.viewFromSeatUrl,\n });\n }\n return seats;\n}\n\n/**\n * Expand a table into its perimeter seats.\n *\n * Round: seats spread evenly on a circle of radius `radius + 16`, the first at\n * angle `rotation` (degrees, clockwise from +x). Rect: seats line the top and\n * bottom edges (split evenly, any remainder to the top), 16u outside the edge,\n * the whole set rotated about the table centre.\n */\nexport function expandTable(t: TableObject): ExpandedSeat[] {\n const seats: ExpandedSeat[] = [];\n const n = Math.max(0, Math.round(t.seatCount));\n if (n === 0) return seats;\n\n const mk = (i: number, x: number, y: number): ExpandedSeat => ({\n id: `${t.id}:${i}`,\n label: `${t.label}-${i + 1}`,\n x,\n y,\n rowId: t.id,\n categoryKey: t.categoryKey,\n });\n\n if (t.shape === 'round') {\n const R = (t.radius ?? 40) + TABLE_SEAT_OFFSET;\n const base = t.rotation * DEG;\n const arc = Math.max(0, Math.min(360, t.seatArc ?? 360));\n if (arc >= 360 || n === 1) {\n // Full ring (or a lone seat) — evenly spaced around the whole table.\n for (let i = 0; i < n; i++) {\n const a = base + (i / n) * 2 * Math.PI;\n seats.push(mk(i, t.center.x + R * Math.cos(a), t.center.y + R * Math.sin(a)));\n }\n return seats;\n }\n // Open side: seats fill the arc, leaving a gap centred on `rotation` (the\n // opening — face it toward the aisle/wall). Seats span edge-to-edge of the\n // seated arc so people flank the gap.\n const arcRad = arc * DEG;\n const halfGap = (2 * Math.PI - arcRad) / 2;\n const start = base + halfGap;\n for (let i = 0; i < n; i++) {\n const a = start + (i / (n - 1)) * arcRad;\n seats.push(mk(i, t.center.x + R * Math.cos(a), t.center.y + R * Math.sin(a)));\n }\n return seats;\n }\n\n // Rect: seats line the enabled edges. Round-robin the count across sides in\n // canonical order so they stay balanced; top/bottom run along width, left/\n // right along height, all 16u outside and rotated with the table.\n const w = t.width ?? 80;\n const h = t.height ?? 50;\n const enabled: NonNullable<TableObject['sides']> =\n t.sides && t.sides.length ? t.sides : ['top', 'bottom'];\n const order = (['top', 'bottom', 'left', 'right'] as const).filter((s) => enabled.includes(s));\n if (!order.length) return seats;\n const counts = new Map<(typeof order)[number], number>(order.map((s) => [s, 0]));\n for (let i = 0; i < n; i++) {\n const s = order[i % order.length];\n counts.set(s, counts.get(s)! + 1);\n }\n let idx = 0;\n for (const side of order) {\n const count = counts.get(side)!;\n for (let j = 0; j < count; j++) {\n let localX: number;\n let localY: number;\n if (side === 'top') {\n localX = -w / 2 + ((j + 0.5) * w) / count;\n localY = -h / 2 - TABLE_SEAT_OFFSET;\n } else if (side === 'bottom') {\n localX = -w / 2 + ((j + 0.5) * w) / count;\n localY = h / 2 + TABLE_SEAT_OFFSET;\n } else if (side === 'left') {\n localX = -w / 2 - TABLE_SEAT_OFFSET;\n localY = -h / 2 + ((j + 0.5) * h) / count;\n } else {\n localX = w / 2 + TABLE_SEAT_OFFSET;\n localY = -h / 2 + ((j + 0.5) * h) / count;\n }\n const p = place(localX, localY, t.rotation, t.center);\n seats.push(mk(idx++, p.x, p.y));\n }\n }\n return seats;\n}\n\n/** Expand a booth into its single bookable block unit. */\nexport function expandBooth(b: BoothObject): ExpandedSeat[] {\n return [\n {\n id: `${b.id}:0`,\n label: b.label,\n x: b.center.x,\n y: b.center.y,\n rowId: b.id,\n categoryKey: b.categoryKey,\n kind: 'booth',\n },\n ];\n}\n\n/** Ray-cast point-in-polygon test — odd crossings ⇒ inside. */\nexport function pointInPolygon(p: Point, poly: Point[]): boolean {\n let inside = false;\n for (let i = 0, j = poly.length - 1; i < poly.length; j = i++) {\n const xi = poly[i].x;\n const yi = poly[i].y;\n const xj = poly[j].x;\n const yj = poly[j].y;\n const hit = yi > p.y !== yj > p.y && p.x < ((xj - xi) * (p.y - yi)) / (yj - yi) + xi;\n if (hit) inside = !inside;\n }\n return inside;\n}\n\n/** Average of polygon vertices (v1 centroid — good enough for labels/membership). */\nfunction polygonCentroid(pts: Point[]): Point {\n if (!pts.length) return { x: 0, y: 0 };\n let x = 0;\n let y = 0;\n for (const p of pts) {\n x += p.x;\n y += p.y;\n }\n return { x: x / pts.length, y: y / pts.length };\n}\n\n/**\n * Visual centre of any object — used for spatial section membership and for\n * rotating an object about its centre. Rows: centroid of expanded seats (or\n * origin when empty); tables/booths: centre; GA/section: polygon centroid;\n * shape: bbox centre; text: its position.\n */\nexport function objectCenter(o: ChartObject): Point {\n switch (o.type) {\n case 'row': {\n const seats = expandRow(o);\n if (!seats.length) return { x: o.origin.x, y: o.origin.y };\n let x = 0;\n let y = 0;\n for (const s of seats) {\n x += s.x;\n y += s.y;\n }\n return { x: x / seats.length, y: y / seats.length };\n }\n case 'table':\n case 'booth':\n return { x: o.center.x, y: o.center.y };\n case 'gaArea':\n return polygonCentroid(o.points);\n case 'section':\n return polygonCentroid(o.outline);\n case 'text':\n return { x: o.position.x, y: o.position.y };\n case 'shape':\n if (o.points && o.points.length) return polygonCentroid(o.points);\n if (o.x != null && o.y != null && o.width != null && o.height != null) {\n return { x: o.x + o.width / 2, y: o.y + o.height / 2 };\n }\n return { x: o.x ?? 0, y: o.y ?? 0 };\n case 'decorImage':\n return { x: o.x + o.width / 2, y: o.y + o.height / 2 };\n }\n}\n\n/**\n * Normalized floor list (Batch 5): a multi-floor chart's `floors`, or a synthetic\n * single floor wrapping a single-floor chart's `objects`. Every consumer that needs\n * to reason about floors goes through this so single-floor charts stay untouched.\n */\nexport function floorsOf(doc: ChartDoc): Floor[] {\n if (doc.floors && doc.floors.length) return doc.floors;\n return [{ id: 'floor-0', name: 'Main', objects: doc.objects, focalPoint: doc.focalPoint, backgroundImage: doc.backgroundImage }];\n}\n\n/** Objects of one floor by id (defaults to the first floor). */\nexport function floorObjects(doc: ChartDoc, floorId?: string): ChartObject[] {\n const floors = floorsOf(doc);\n return (floorId ? floors.find((f) => f.id === floorId) : floors[0])?.objects ?? [];\n}\n\n/** Every object across ALL floors — the whole venue (single-floor = `doc.objects`). */\nexport function allObjects(doc: ChartDoc): ChartObject[] {\n return doc.floors && doc.floors.length ? doc.floors.flatMap((f) => f.objects) : doc.objects;\n}\n\n/** A copy of an object translated by (dx, dy) — every coordinate field shifted. */\nfunction translateObject(o: ChartObject, dx: number, dy: number): ChartObject {\n const p = (pt: Point): Point => ({ x: pt.x + dx, y: pt.y + dy });\n const pts = (a: Point[]): Point[] => a.map(p);\n switch (o.type) {\n case 'row':\n return { ...o, origin: p(o.origin) };\n case 'table':\n case 'booth':\n return { ...o, center: p(o.center) };\n case 'gaArea':\n return { ...o, points: pts(o.points) };\n case 'section':\n return { ...o, outline: pts(o.outline) };\n case 'text':\n return { ...o, position: p(o.position) };\n case 'shape':\n return {\n ...o,\n ...(o.points ? { points: pts(o.points) } : {}),\n ...(o.x != null ? { x: o.x + dx } : {}),\n ...(o.y != null ? { y: o.y + dy } : {}),\n };\n case 'decorImage':\n return { ...o, x: o.x + dx, y: o.y + dy };\n }\n}\n\n/**\n * Multi-floor 3D stack (Batch 5): flatten every floor into ONE doc with floor `i`\n * lifted by `i * spread` in −y, so the isometric view shows the floors as stacked\n * decks (ground at the bottom). Returns a single-floor doc (no `floors`). Meant\n * only for the 3D overview render — 2D still shows one floor via `floorObjects`.\n */\nexport function stackFloors(doc: ChartDoc, spread = 900): ChartDoc {\n if (!doc.floors || doc.floors.length < 2) return doc;\n const objects: ChartObject[] = [];\n doc.floors.forEach((f, i) => {\n const dy = -i * spread;\n for (const o of f.objects) objects.push(dy === 0 ? o : translateObject(o, 0, dy));\n });\n return { ...doc, objects, floors: undefined };\n}\n\n/** Expand every seat-bearing object across all floors (rows, tables, booths). */\nexport function expandChart(doc: ChartDoc): ExpandedSeat[] {\n const out: ExpandedSeat[] = [];\n for (const obj of allObjects(doc)) {\n if (obj.type === 'row') out.push(...expandRow(obj));\n else if (obj.type === 'table') out.push(...expandTable(obj));\n else if (obj.type === 'booth') out.push(...expandBooth(obj));\n }\n return out;\n}\n\nconst PAD = 40;\n\n/** Axis-aligned bounds over every object plus the background image, with padding. */\nexport function chartBounds(doc: ChartDoc): { x: number; y: number; width: number; height: number } {\n let minX = Infinity;\n let minY = Infinity;\n let maxX = -Infinity;\n let maxY = -Infinity;\n\n const acc = (x: number, y: number) => {\n if (x < minX) minX = x;\n if (y < minY) minY = y;\n if (x > maxX) maxX = x;\n if (y > maxY) maxY = y;\n };\n\n for (const s of expandChart(doc)) acc(s.x, s.y);\n\n for (const obj of allObjects(doc)) {\n if (obj.type === 'gaArea') {\n for (const p of obj.points) acc(p.x, p.y);\n } else if (obj.type === 'section') {\n for (const p of obj.outline) acc(p.x, p.y);\n } else if (obj.type === 'decorImage') {\n acc(obj.x, obj.y);\n acc(obj.x + obj.width, obj.y + obj.height);\n } else if (obj.type === 'shape') {\n if (obj.points && obj.points.length) {\n for (const p of obj.points) acc(p.x, p.y);\n } else if (obj.x != null && obj.y != null && obj.width != null && obj.height != null) {\n acc(obj.x, obj.y);\n acc(obj.x + obj.width, obj.y + obj.height);\n }\n } else if (obj.type === 'table') {\n const off = TABLE_SEAT_OFFSET + SEAT_R;\n const ext =\n obj.shape === 'round'\n ? (obj.radius ?? 40) + off\n : Math.max((obj.width ?? 80) / 2, (obj.height ?? 50) / 2) + off; // rotation-agnostic over-approximation\n acc(obj.center.x - ext, obj.center.y - ext);\n acc(obj.center.x + ext, obj.center.y + ext);\n } else if (obj.type === 'booth') {\n const ext = Math.max(obj.width, obj.height) / 2;\n acc(obj.center.x - ext, obj.center.y - ext);\n acc(obj.center.x + ext, obj.center.y + ext);\n } else if (obj.type === 'text') {\n const w = obj.fontSize * obj.text.length * 0.6; // approximate glyph advance\n acc(obj.position.x, obj.position.y);\n acc(obj.position.x + w, obj.position.y + obj.fontSize);\n }\n }\n\n if (doc.backgroundImage) {\n const { center, width } = doc.backgroundImage;\n const bh = (width * 3) / 4; // assume 4:3 when the true aspect is unknown at bounds-time\n acc(center.x - width / 2, center.y - bh / 2);\n acc(center.x + width / 2, center.y + bh / 2);\n }\n\n // Empty document → a sane default box around the focal point.\n if (!isFinite(minX)) {\n const f = doc.focalPoint ?? { x: 0, y: 0 };\n return { x: f.x - 200, y: f.y - 200, width: 400, height: 400 };\n }\n\n return {\n x: minX - PAD,\n y: minY - PAD,\n width: maxX - minX + PAD * 2,\n height: maxY - minY + PAD * 2,\n };\n}\n","import type { ChartDoc, GAAreaObject } from './types';\nimport { allObjects } from './layout';\n\nconst PREFIX = '__sl_ga__';\nexport const MAX_GA_CAPACITY = 100_000;\nexport const MAX_EVENT_INVENTORY = 100_000;\n\n/** Stable internal inventory label for one unit of a GA area's capacity. */\nexport function gaUnitLabel(areaId: string, index: number): string {\n return `${PREFIX}${encodeURIComponent(areaId)}__${index + 1}`;\n}\n\nexport function gaUnitLabels(area: GAAreaObject): string[] {\n const capacity = Math.min(MAX_GA_CAPACITY, Math.max(0, Math.floor(area.capacity)));\n return Array.from({ length: capacity }, (_, i) => gaUnitLabel(area.id, i));\n}\n\nexport function gaAreasOf(doc: ChartDoc): GAAreaObject[] {\n return allObjects(doc).filter((o): o is GAAreaObject => o.type === 'gaArea');\n}\n\nexport function isGaUnitLabel(label: string): boolean {\n return label.startsWith(PREFIX);\n}\n","/**\n * Section membership + hide/show resolution (Batch 3.3).\n *\n * A `SectionObject` is a polygon drawn over existing seat objects; an object\n * \"belongs\" to a section when its visual centre (`objectCenter`) falls inside\n * the section outline, first section in doc order winning. This is the same\n * spatial notion `objectCenter`'s doc-comment describes, resolved once here so\n * BOTH the event manager (Sections tab counts) and the buyer picker (omit\n * hidden seats) agree on which seats live in which section.\n *\n * Hiding is per-EVENT (the EventDO holds the hidden id set), not a chart edit —\n * so a republish of the chart never disturbs it. A hidden id may be a section\n * id, a zone id (hides every section in the zone), or `UNGROUPED_ID` (the\n * catch-all bucket of seat objects that sit in no section).\n */\nimport type { ChartDoc, ChartObject, SectionObject } from './types';\nimport { allObjects, expandBooth, expandRow, expandTable, objectCenter, pointInPolygon } from './layout';\nimport { gaUnitLabels } from './ga';\n\n/** Synthetic section id for seat objects that fall in no drawn section. */\nexport const UNGROUPED_ID = '__ungrouped__';\n\n/**\n * A per section/zone availability window (Batch 3.4). Wire-compatible with the\n * EventDO's own `AvailabilityRule`. Absence of a rule for an id = on sale.\n * 'hidden' — manual: hidden until the organizer reveals it (3.3).\n * 'timed' — hidden until `revealAt` (epoch ms), then auto-reveals.\n * 'threshold' — auto-reveals once the on-sale inventory is `thresholdPct`% sold.\n * 'closed' — visible to buyers but not purchasable (rendered flat grey);\n * unlike 'hidden', the seats stay on the map, just off sale.\n * `labels` are the seat labels the id governs, so a threshold's denominator can\n * exclude still-hidden seats.\n */\nexport interface AvailabilityRule {\n mode: 'hidden' | 'timed' | 'threshold' | 'closed';\n revealAt?: number;\n thresholdPct?: number;\n labels?: string[];\n}\n\nexport interface SectionNode {\n /** Section id (a `SectionObject.id`, or `UNGROUPED_ID`). */\n id: string;\n label: string;\n /** Zone id this section points at (`SectionObject.zone`), if any. */\n zone?: string;\n /** Total seats across the member objects. */\n seatCount: number;\n /** Ids of the seat-bearing objects that belong to this section. */\n objectIds: string[];\n /** Seat labels across the member objects (for availability-rule denominators). */\n seatLabels: string[];\n}\n\n/** Seat labels produced by one seat-bearing object (rows/tables/booths); [] otherwise. */\nfunction objectSeatLabels(o: ChartObject): string[] {\n if (o.type === 'row') return expandRow(o).map((s) => s.label);\n if (o.type === 'table') return expandTable(o).map((s) => s.label);\n if (o.type === 'booth') return expandBooth(o).map((s) => s.label);\n if (o.type === 'gaArea') return gaUnitLabels(o);\n return [];\n}\n\nfunction isSeatObject(o: ChartObject): boolean {\n return o.type === 'row' || o.type === 'table' || o.type === 'booth' || o.type === 'gaArea';\n}\n\n/**\n * Resolve section membership for a chart. Returns one node per drawn section\n * (doc order), a synthetic \"Ungrouped\" node for loose seat objects (null when\n * every seat sits in a section), and the object→section id map.\n */\nexport function computeSections(doc: ChartDoc): {\n sections: SectionNode[];\n ungrouped: SectionNode | null;\n /** seat-object id → owning section id (or `UNGROUPED_ID`). */\n objectToSection: Map<string, string>;\n} {\n // Span all floors (Batch 5) — a multi-floor chart's sections live in floors[];\n // single-floor charts fall through to doc.objects. Section ids are chart-unique.\n const objs = allObjects(doc);\n const sectionObjs = objs.filter((o): o is SectionObject => o.type === 'section');\n const nodes = new Map<string, SectionNode>();\n for (const s of sectionObjs) {\n nodes.set(s.id, { id: s.id, label: s.label || 'Section', zone: s.zone, seatCount: 0, objectIds: [], seatLabels: [] });\n }\n const ungrouped: SectionNode = { id: UNGROUPED_ID, label: 'Other seats', seatCount: 0, objectIds: [], seatLabels: [] };\n const objectToSection = new Map<string, string>();\n\n for (const obj of objs) {\n if (!isSeatObject(obj)) continue;\n const labels = objectSeatLabels(obj);\n if (labels.length === 0) continue;\n const c = objectCenter(obj);\n // First drawn section (doc order) whose outline contains the object centre.\n const owner = sectionObjs.find((s) => pointInPolygon(c, s.outline));\n const node = owner ? nodes.get(owner.id)! : ungrouped;\n node.seatCount += labels.length;\n node.objectIds.push(obj.id);\n node.seatLabels.push(...labels);\n objectToSection.set(obj.id, node.id);\n }\n\n return {\n sections: sectionObjs.map((s) => nodes.get(s.id)!),\n ungrouped: ungrouped.objectIds.length ? ungrouped : null,\n objectToSection,\n };\n}\n\n/** Is a drawn section hidden under `hidden` — directly, or via its zone? */\nexport function isSectionHidden(s: SectionObject, hidden: ReadonlySet<string>): boolean {\n return hidden.has(s.id) || (!!s.zone && hidden.has(s.zone));\n}\n\n/**\n * The set of seat-object ids to omit from the buyer view for a given hidden id\n * set. An object is hidden when its owning section is hidden (directly or via\n * zone), or it is ungrouped and the catch-all bucket is hidden.\n */\nexport function hiddenObjectIds(doc: ChartDoc, hidden: ReadonlySet<string>): Set<string> {\n const out = new Set<string>();\n if (!hidden.size) return out;\n const { sections, ungrouped, objectToSection } = computeSections(doc);\n const hiddenSectionIds = new Set<string>();\n const zoneById = new Map(sections.map((s) => [s.id, s.zone] as const));\n for (const s of sections) {\n const zone = zoneById.get(s.id);\n if (hidden.has(s.id) || (zone && hidden.has(zone))) hiddenSectionIds.add(s.id);\n }\n const ungroupedHidden = !!ungrouped && hidden.has(UNGROUPED_ID);\n for (const [objId, secId] of objectToSection) {\n if (hiddenSectionIds.has(secId) || (ungroupedHidden && secId === UNGROUPED_ID)) out.add(objId);\n }\n return out;\n}\n\n/**\n * A copy of the doc with hidden sections' member objects removed, plus the\n * hidden section overlays themselves (so no empty block renders). Returns the\n * SAME reference when nothing is hidden — callers can skip a re-render on `===`.\n */\nexport function applyHidden(doc: ChartDoc, hidden: ReadonlySet<string>): ChartDoc {\n if (!hidden.size) return doc;\n const hide = hiddenObjectIds(doc, hidden);\n const hiddenSet = hidden instanceof Set ? hidden : new Set(hidden);\n const keep = (o: ChartObject): boolean => {\n if (hide.has(o.id)) return false;\n if (o.type === 'section' && isSectionHidden(o, hiddenSet)) return false;\n return true;\n };\n // Multi-floor (Batch 5): filter each floor + the floor-0 mirror.\n if (doc.floors && doc.floors.length) {\n let changed = false;\n const floors = doc.floors.map((f) => {\n const objects = f.objects.filter(keep);\n if (objects.length !== f.objects.length) changed = true;\n return objects.length === f.objects.length ? f : { ...f, objects };\n });\n if (!changed) return doc;\n return { ...doc, floors, objects: floors[0].objects };\n }\n const objects = doc.objects.filter(keep);\n if (objects.length === doc.objects.length) return doc;\n return { ...doc, objects };\n}\n","/**\n * SeatmapRenderer — the shared canvas rendering core (buyer picker shell).\n *\n * Uses Konva directly with per-module imports to keep the bundle lean. The\n * whole point of the spike is staying smooth at ~5,000 seats on mobile, so the\n * hot paths lean on: layer bitmap caching + listening(false) when zoomed out,\n * per-seat fill updates (never full rebuilds) on status change, and viewport-\n * only label rendering rebuilt on interaction-end rather than per frame.\n */\n\n// Core (not Global): Core assembles the real Konva namespace — Global alone\n// lacks DD/Util and Stage._pointermove dereferences Konva.DD unconditionally.\nimport { Konva } from 'konva/lib/Core';\nimport { Stage } from 'konva/lib/Stage';\nimport { Layer } from 'konva/lib/Layer';\nimport { Group } from 'konva/lib/Group';\nimport { Circle } from 'konva/lib/shapes/Circle';\nimport { Rect } from 'konva/lib/shapes/Rect';\nimport { Ellipse } from 'konva/lib/shapes/Ellipse';\nimport { Line } from 'konva/lib/shapes/Line';\nimport { Text } from 'konva/lib/shapes/Text';\nimport { Image as KImage } from 'konva/lib/shapes/Image';\nimport type { KonvaEventObject } from 'konva/lib/Node';\nimport type { Shape } from 'konva/lib/Shape';\n\nimport type {\n AccessibilityType,\n ChartDoc,\n ChartTheme,\n ExpandedSeat,\n ISeatmapRenderer,\n LodRung,\n Point,\n RendererOptions,\n SeatStatus,\n SectionObject,\n} from '../core/types';\nimport { chartBounds, expandChart, floorsOf, pointInPolygon, stackFloors } from '../core/layout';\nimport { t } from '../i18n';\nimport { formatMoney } from '../lib/money';\n\nconst SEAT_RADIUS = 9;\n/** Absolute scale at which a seat (r=9) renders ~legibly (~8px). */\nconst SEAT_LEGIBLE_SCALE = 0.9;\n/** Below this absolute scale we swap seats for a cached bitmap. */\nconst CACHE_THRESHOLD = 0.55 * SEAT_LEGIBLE_SCALE;\n/** Show per-seat labels above this ABSOLUTE scale (seat ⌀ ≈ 18px) — chart-size independent. */\nconst LABEL_SCALE = 1.0;\n/** Extra screen-px of slack around a seat circle that still counts as a tap on\n * it. Gives small seats a finger-friendly hit target (§4 \"hit ≥ 24px\") so a\n * near-miss on mobile still selects the nearest seat instead of doing nothing. */\nconst SEAT_TAP_SLOP_PX = 14;\n/**\n * At/below this scale, sections read as solid BLOCKS with row-line hints (seats\n * fully hidden) — the seats.io-style default overview.\n */\nconst SECTION_PROMINENT_SCALE = 0.45 * SEAT_LEGIBLE_SCALE;\n/**\n * Above this scale, seats are fully shown (dots); between here and\n * SECTION_PROMINENT the block melts in. Set high so a big sectioned chart OPENS\n * as named blocks and only reveals seats once you zoom in close.\n */\nconst BLOCK_MELT_TOP = 0.9 * SEAT_LEGIBLE_SCALE;\n/** Camera scale used after a section drill-in. Keeping this above the block\n * melt band guarantees that a section tap lands on live, legible seats even\n * when a narrow phone viewport cannot frame the whole section at that scale. */\nconst SEAT_FOCUS_SCALE = Math.max(SEAT_LEGIBLE_SCALE * 1.1, BLOCK_MELT_TOP);\n/** Ignore normal finger jitter before treating a tap as a map pan. */\nconst PAN_START_SLOP_PX = 8;\n/**\n * Below this scale, ZONE blocks/labels take over from per-section detail (the\n * farthest rung). ~0.55× the section rung so: seats → section blocks → zones.\n */\nconst ZONE_PROMINENT_SCALE = 0.55 * SECTION_PROMINENT_SCALE;\n/** Never label more than this many seats at once (viewport clutter guard). */\nconst MAX_LABELS = 700;\n/**\n * Manage-mode marquee: above this many selected seats we stop drawing per-seat\n * selection-ring nodes (they'd be an invisible speck at that zoom and a huge\n * node count on a 13k arena) and rely on the seat-fill selection paint instead.\n * Selection membership (getSelection / bulk block) is unaffected.\n */\nconst MARQUEE_RING_CAP = 2500;\n\n// ---- Isometric (\"3D\") view mode -------------------------------------------\n/** Full-iso rotation of the chart about its centre (degrees). */\nconst ISO_ANGLE_DEG = -11.5;\n/** Full-iso vertical squash (1 = flat). */\nconst ISO_SQUASH = 0.58;\n/** World units a section (and its members) lift per elevation step at full iso. */\nconst LIFT_PER_STEP = 58;\n/** Flat⇄iso tween duration (ms); reduced-motion snaps. */\nconst ISO_TWEEN_MS = 320;\n/** Buyer camera travel should be easy to follow without feeling sluggish. */\nconst CAMERA_GLIDE_MS = 650;\n\n// ---- Section/zone LOD (\"melt\") tuning -------------------------------------\n/** Peak fill opacity of a solid section block at the block rung. */\nconst BLOCK_FILL_ALPHA = 0.85;\n/** How far a fully-sold section's fill darkens toward black. */\nconst SOLD_DARKEN = 0.5;\n/** Screen-space target sizes (px) for scale-compensated section/zone labels. */\nconst SECTION_LABEL_PX = 20;\nconst SECTION_SUB_PX = 12.5;\nconst ZONE_LABEL_PX = 30;\nconst ZONE_SUB_PX = 12;\n\nconst HELD_FILL = '#6b7280';\nconst TAKEN_FILL = '#374151';\nconst NFS_STROKE = '#4b5563';\n/** Phase 2 event-level `closed` section: a flat desaturated slate block (label\n * kept), distinct from the per-seat availability-grey. Seats inside read grey\n * at 40% and are not pickable (per chart-design-standards §3). */\nconst CLOSED_SECTION_FILL = '#586070';\nconst CLOSED_SEAT_FILL = '#4b5563';\nconst CLOSED_SEAT_OPACITY = 0.4;\n/** AXS section-focus: non-focused sections dim to this opacity + desaturate. */\nconst FOCUS_DIM_OPACITY = 0.16;\nconst FOCUS_DESATURATE = 0.72; // lerp non-focused fills toward neutral grey\nconst FOCUS_NEUTRAL = '#6b7280';\n/** Light/neutral backdrop panel drawn behind the focused section's seats. */\nconst FOCUS_BACKDROP_FILL = 'rgba(244,246,248,0.06)';\n/** Okabe-Ito colorblind-safe hues (black dropped — unreadable on dark charts).\n * Categories map to these by their doc order when colorblind mode is on. */\nconst CB_PALETTE = ['#E69F00', '#56B4E9', '#009E73', '#F0E442', '#0072B2', '#D55E00', '#CC79A7'];\n\n/** Outer-ring colour per accommodation (a seat's first-listed type wins). */\nconst ACCESS_RING: Record<AccessibilityType, string> = {\n wheelchair: '#3b82f6',\n companion: '#8b5cf6',\n 'semi-ambulatory': '#0ea5e9',\n hearing: '#14b8a6',\n 'sign-language': '#f59e0b',\n 'plus-size': '#ec4899',\n 'lift-armrest': '#22c55e',\n};\n\n/** Does a seat satisfy a filter? `[]` means \"any accessible seat\". */\nfunction seatMatchesAccess(seat: ExpandedSeat, filter: AccessibilityType[]): boolean {\n if (filter.length === 0) return !!seat.accessible;\n return !!seat.accessibility?.some((t) => filter.includes(t));\n}\n\n// Theme fallbacks (dark defaults) — used when doc.theme leaves a slot unset.\nconst DEF_SEAT_LABEL = '#0b1220';\nconst DEF_SELECTION = '#ffffff';\n/** Selection/hover ring on LIGHT canvases — a white ring vanishes there. */\nconst DEF_SELECTION_ON_LIGHT = '#0b1220';\nconst DEF_DECOR_FILL = '#232c40';\nconst DEF_TEXT = '#8b93a7';\n\n/**\n * Relative luminance (0..1) of a CSS color — supports #rgb, #rrggbb and\n * rgb()/rgba(). Returns NaN for anything unparseable (gradients, ''), which\n * callers must treat as \"unknown → assume dark\" to preserve dark defaults.\n */\nfunction colorLuminance(color: string): number {\n const s = color.trim();\n let r = NaN;\n let g = NaN;\n let b = NaN;\n const hex = /^#([\\da-f]{3}|[\\da-f]{6})$/i.exec(s);\n if (hex) {\n const h = hex[1].length === 3 ? hex[1].split('').map((c) => c + c).join('') : hex[1];\n r = parseInt(h.slice(0, 2), 16);\n g = parseInt(h.slice(2, 4), 16);\n b = parseInt(h.slice(4, 6), 16);\n } else {\n const rgb = /^rgba?\\(\\s*(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*(\\d+)/.exec(s);\n if (rgb) {\n r = +rgb[1];\n g = +rgb[2];\n b = +rgb[3];\n }\n }\n if (Number.isNaN(r)) return NaN;\n return (0.2126 * r + 0.7152 * g + 0.0722 * b) / 255;\n}\n\n/** Light enough that white UI accents (selection ring) lose contrast. */\nfunction isLightColor(color: string): boolean {\n const lum = colorLuminance(color);\n return !Number.isNaN(lum) && lum > 0.6;\n}\n\nconst clamp = (v: number, lo: number, hi: number) => Math.max(lo, Math.min(hi, v));\n\n/** Read a custom attr off an event target (Stage | Shape union isn't callable directly). */\nfunction seatIdOf(target: unknown): string | undefined {\n const n = target as { getAttr?: (k: string) => unknown } | null;\n return (n?.getAttr?.('seatId') as string | undefined) ?? undefined;\n}\n\n/** Mix a #rrggbb colour toward white by `amt` (0..1). */\nfunction lighten(hex: string, amt: number): string {\n const m = /^#?([\\da-f]{6})$/i.exec(hex.trim());\n if (!m) return hex;\n const n = parseInt(m[1], 16);\n const r = (n >> 16) & 255;\n const g = (n >> 8) & 255;\n const b = n & 255;\n const mix = (c: number) => Math.round(c + (255 - c) * amt);\n return `#${((1 << 24) | (mix(r) << 16) | (mix(g) << 8) | mix(b)).toString(16).slice(1)}`;\n}\n\n/** Mix a #rrggbb colour toward black by `amt` (0..1). */\nfunction darken(hex: string, amt: number): string {\n const m = /^#?([\\da-f]{6})$/i.exec(hex.trim());\n if (!m) return hex;\n const n = parseInt(m[1], 16);\n const mix = (c: number) => Math.round(c * (1 - amt));\n return `#${((1 << 24) | (mix((n >> 16) & 255) << 16) | (mix((n >> 8) & 255) << 8) | mix(n & 255)).toString(16).slice(1)}`;\n}\n\n/** Axis-aligned bounds of a polygon (no padding). */\nfunction polyBounds(pts: Point[]): { x: number; y: number; width: number; height: number } {\n let minX = Infinity;\n let minY = Infinity;\n let maxX = -Infinity;\n let maxY = -Infinity;\n for (const p of pts) {\n if (p.x < minX) minX = p.x;\n if (p.y < minY) minY = p.y;\n if (p.x > maxX) maxX = p.x;\n if (p.y > maxY) maxY = p.y;\n }\n return { x: minX, y: minY, width: Math.max(1, maxX - minX), height: Math.max(1, maxY - minY) };\n}\n\n/** #rrggbb → rgba() string at alpha `a`; passes non-hex through unchanged. */\nfunction rgba(hex: string, a: number): string {\n const m = /^#?([\\da-f]{6})$/i.exec(hex.trim());\n if (!m) return hex;\n const n = parseInt(m[1], 16);\n return `rgba(${(n >> 16) & 255},${(n >> 8) & 255},${n & 255},${a})`;\n}\n\n/** Parse #rrggbb → [r,g,b] (0..255); null for non-hex. */\nfunction hexToRgb(hex: string): [number, number, number] | null {\n const m = /^#?([\\da-f]{6})$/i.exec(hex.trim());\n if (!m) return null;\n const n = parseInt(m[1], 16);\n return [(n >> 16) & 255, (n >> 8) & 255, n & 255];\n}\n\nconst toHex = (r: number, g: number, b: number): string =>\n `#${((1 << 24) | (Math.round(r) << 16) | (Math.round(g) << 8) | Math.round(b)).toString(16).slice(1)}`;\n\n/**\n * Count-weighted RGB blend of member seat colours — a section reads as its\n * price makeup, not one flat colour. Falls back to `fallback` when empty.\n */\nfunction mixColors(parts: Array<{ hex: string; w: number }>, fallback: string): string {\n let r = 0;\n let g = 0;\n let b = 0;\n let tw = 0;\n for (const p of parts) {\n const rgb = hexToRgb(p.hex);\n if (!rgb || p.w <= 0) continue;\n r += rgb[0] * p.w;\n g += rgb[1] * p.w;\n b += rgb[2] * p.w;\n tw += p.w;\n }\n return tw > 0 ? toHex(r / tw, g / tw, b / tw) : fallback;\n}\n\n/** Linear interpolate between two #rrggbb colours (t 0..1); passes `a` through if unparseable. */\nfunction lerpColor(a: string, b: string, t: number): string {\n const ca = hexToRgb(a);\n const cb = hexToRgb(b);\n if (!ca || !cb) return a;\n return toHex(ca[0] + (cb[0] - ca[0]) * t, ca[1] + (cb[1] - ca[1]) * t, ca[2] + (cb[2] - ca[2]) * t);\n}\n\n/** Per-section render state for the block LOD rung (fills, labels, membership). */\ninterface SectionRender {\n id: string;\n label: string;\n outline: Point[];\n centroid: Point;\n zone?: string;\n /** Seats whose centre falls inside the outline (first-match, doc order). */\n memberIds: string[];\n total: number;\n free: number;\n /** Category-mix (or explicit override) fill BEFORE the availability tint. */\n baseFill: string;\n outlineTint: string;\n /** Faint outline drawn under seats — the existing near-zoom look, untouched. */\n outlinePoly: Line;\n /** Solid block fill that melts in at the block rung. */\n blockPoly: Line;\n /** Faint per-row hint lines drawn inside the block (the seats.io \"rows\" look). */\n rowLines: Line[];\n /** Section name (always drawn; brightens at the block rung, hides at zone rung). */\n nameLabel: Text;\n /** Mono \"N LEFT\" availability sublabel (block rung only). */\n subLabel: Text;\n /** Tier height (0 = floor). Lifts the section + members in iso (\"3D\") view. */\n elevation: number;\n /**\n * When elevation > 0, the section's bg nodes + member seats live in these\n * groups so a single position offset lifts the whole tier in iso view.\n */\n liftGroupBg: Group | null;\n liftGroupSeat: Group | null;\n /** Extruded side faces (one per outline edge) shown only as isoT rises. */\n sideFaces: Line[];\n}\n\n/** Per-zone render state for the farthest LOD rung. */\ninterface ZoneRender {\n id: string;\n label: Text;\n sub: Text | null;\n}\n\nexport class SeatmapRenderer implements ISeatmapRenderer {\n private container: HTMLDivElement;\n private opts: Required<Pick<RendererOptions, 'maxSelection'>> & RendererOptions;\n\n private stage: Stage;\n private bgLayer: Layer;\n private seatLayer: Layer;\n private overlayLayer: Layer;\n private labelGroup: Group;\n\n private seats: ExpandedSeat[] = [];\n private seatById = new Map<string, ExpandedSeat>();\n /** Multi-floor (Batch 5): the last-set chart + which floor we're rendering. */\n private chartDoc: ChartDoc | null = null;\n private activeFloorId = '';\n /** When true on a multi-floor chart, render ALL floors stacked (3D overview). */\n private stacked = false;\n /** Interactive node per seat/booth — a Circle for seats, a Rect for booths. */\n private circleById = new Map<string, Shape>();\n /** Booth block geometry, keyed by booth id (= the unit's rowId). */\n private boothDims = new Map<string, { width: number; height: number; rotation: number }>();\n /** Booth label node so status changes can say HELD/SOLD on the full block. */\n private boothLabelById = new Map<string, Text>();\n private statusById = new Map<string, SeatStatus>();\n private catColor = new Map<string, string>();\n private theme: ChartTheme = {};\n /** Effective selection/hover ring color — resolved per chart in setChart(). */\n private effSelection: string = DEF_SELECTION;\n /** Colorblind-safe mode (Okabe-Ito hues + hollow booked seats). */\n private colorblind = false;\n /** Category order from the doc — the stable index into the CB palette. */\n private catOrder: string[] = [];\n\n private selection = new Set<string>();\n /** Whole-seat/block selection markers: outline + non-colour check cue. */\n private selectionMarkers = new Map<string, Group>();\n /** Held by this picker instance, not by another buyer. */\n private ownedHold = new Set<string>();\n /** One selected seat being inspected before it is committed to the cart. */\n private selectionFocusId: string | null = null;\n private hoverRing: Circle;\n /** Keyboard-navigation focus ring + the currently focused seat id. */\n private focusRing: Circle;\n private focusedId: string | null = null;\n /**\n * Accessibility filter: `null` = off; `[]` = dim all non-accessible free seats;\n * a type list = dim free seats lacking any of those accommodations.\n */\n private accessFilter: AccessibilityType[] | null = null;\n /** Category highlight (legend hover): dims free seats NOT of this category. */\n private categoryHighlight: string | null = null;\n /** Price-band filter (F4): dim free seats whose category is NOT in this set. */\n private categoryFilter: Set<string> | null = null;\n\n // Section/zone overlays (bgLayer) — the 3-rung LOD: seats → section blocks →\n // zone blocks. Kept for the melt restyle and for hit-testing a zoomed-out tap.\n private sections: SectionRender[] = [];\n private zones: ZoneRender[] = [];\n private seatSection = new Map<string, SectionRender>();\n private catPrice = new Map<string, number>();\n /** ISO 4217 currency for on-map \"FROM …\" prices (undefined ⇒ money default). */\n private currency: string | undefined;\n /** Section/zone ids to render dimmed (organizer manager: held-back inventory). */\n private dimmedSections = new Set<string>();\n /** Organizer control-room velocity overlay; absent on buyer surfaces. */\n private sectionHeat = new Map<string, number>();\n /** Phase 2: section/zone ids in the event-level `closed` state — flat grey\n * block, seats greyed + not pickable, but the section stays rendered. */\n private closedSections = new Set<string>();\n /** AXS section-focus: the currently-focused section id (others dim), or null. */\n private focusedSectionId: string | null = null;\n /** Light backdrop panel drawn behind the focused section (removed on clear). */\n private focusBackdrop: Line | null = null;\n /** Object id → floor id (multi-floor only) — resolves a deck tap in the 3D stack. */\n private objectFloor = new Map<string, string>();\n /** Zone id → colour (drives extruded side faces in iso view). */\n private zoneColor = new Map<string, string>();\n private hasSections = false;\n /** seatLayer carries Text (booth labels) — gate the upright-label scan. */\n private hasBoothText = false;\n\n // Isometric (\"3D\") view — an affine skew/rotate + elevation lift, tweened.\n /** 0 = flat (default), 1 = full isometric; animated by setViewMode. */\n private isoT = 0;\n private isoTarget = 0;\n private isoRaf = 0;\n /** Chart centre the iso projection pivots about (bounds centre). */\n private isoCentre = { x: 0, y: 0 };\n /** rAF for an in-flight camera glide (focusRegion / setRung); 0 = none. */\n private glideRaf = 0;\n /** Set in destroy() so an in-flight iso tween bails. */\n private destroyed = false;\n /** Cached scale the section/zone labels were last sized for (scale-compensation). */\n private lodScale = 0;\n /** prefers-reduced-motion → hard-swap rungs instead of cross-fading. */\n private reducedMotion =\n typeof window !== 'undefined' &&\n typeof window.matchMedia === 'function' &&\n window.matchMedia('(prefers-reduced-motion: reduce)').matches;\n\n private fitScale = 1;\n /** Effective seat radius (base × theme.seatScale), set per chart in setChart. */\n private seatR = SEAT_RADIUS;\n private bounds = { x: 0, y: 0, width: 1, height: 1 };\n private cached = false;\n private dpr = Math.min(typeof window !== 'undefined' ? window.devicePixelRatio || 1 : 1, 2);\n\n private rafId = 0;\n private frames = 0;\n private lastFpsAt = 0;\n private recacheTimer: ReturnType<typeof setTimeout> | null = null;\n private resizeObs: ResizeObserver | null = null;\n /** Coalesces bursty view-change sources (pointermove, wheel) into ≤1 callback/frame. */\n private viewChangeRaf = 0;\n\n // Gesture state — pan/pinch are handled with raw pointer events on the\n // container (Konva stage dragging is off; its touch pipeline proved\n // unreliable for multi-touch on real devices).\n private pointers = new Map<number, { x: number; y: number }>();\n private pinch: { startDist: number; startScale: number; worldMid: { x: number; y: number } } | null = null;\n private panLast: { x: number; y: number } | null = null;\n private panStart: { x: number; y: number } | null = null;\n private panStarted = false;\n /** Maximum displacement from gesture start — suppress taps only after a real pan/pinch. */\n private moved = 0;\n /**\n * Manage-mode rubber-band marquee (option-gated). `start`/`cur` are WORLD-space\n * points (overlayLayer rides the stage transform); `rect` is the on-canvas\n * selection band. Null except during an active manage-mode drag.\n */\n private marquee: { start: { x: number; y: number }; rect: Rect } | null = null;\n private marqueeCur: { x: number; y: number } | null = null;\n\n constructor(container: HTMLDivElement, options: RendererOptions = {}) {\n this.container = container;\n this.opts = { maxSelection: 10, selectableStatuses: ['free'], ...options };\n this.currency = options.currency;\n\n Konva.pixelRatio = this.dpr;\n\n this.stage = new Stage({\n container,\n width: container.clientWidth || 1,\n height: container.clientHeight || 1,\n draggable: false, // pan/pinch are ours, via pointer events\n });\n\n container.style.touchAction = 'none';\n container.addEventListener('pointerdown', this.onPointerDown, { passive: false });\n container.addEventListener('pointermove', this.onPointerMove, { passive: false });\n container.addEventListener('pointerup', this.onPointerEnd, { passive: false });\n container.addEventListener('pointercancel', this.onPointerEnd, { passive: false });\n\n // Keyboard accessibility: the canvas is focusable and navigable seat-by-seat.\n if (container.tabIndex < 0) container.tabIndex = 0;\n container.setAttribute('role', 'application');\n if (!container.getAttribute('aria-label')) {\n container.setAttribute('aria-label', t('map.aria'));\n }\n container.addEventListener('keydown', this.onKeyDown);\n\n this.bgLayer = new Layer({ listening: true });\n this.seatLayer = new Layer({ listening: true });\n this.overlayLayer = new Layer({ listening: false });\n this.labelGroup = new Group({ listening: false });\n this.overlayLayer.add(this.labelGroup);\n\n this.hoverRing = new Circle({\n radius: SEAT_RADIUS + 2,\n stroke: '#ffffff',\n strokeWidth: 2,\n opacity: 0.85,\n listening: false,\n visible: false,\n perfectDrawEnabled: false,\n shadowForStrokeEnabled: false,\n });\n this.overlayLayer.add(this.hoverRing);\n\n this.focusRing = new Circle({\n radius: SEAT_RADIUS + 3,\n stroke: '#38bdf8',\n strokeWidth: 2.5,\n dash: [4, 3],\n opacity: 0.95,\n listening: false,\n visible: false,\n perfectDrawEnabled: false,\n shadowForStrokeEnabled: false,\n });\n this.overlayLayer.add(this.focusRing);\n\n this.stage.add(this.bgLayer, this.seatLayer, this.overlayLayer);\n\n this.wireInteraction();\n this.startFpsLoop();\n\n if (import.meta.env.DEV) {\n (window as unknown as Record<string, unknown>).__seatmap = this;\n }\n\n if (typeof ResizeObserver !== 'undefined') {\n this.resizeObs = new ResizeObserver(() => this.handleResize());\n this.resizeObs.observe(container);\n }\n }\n\n // ---- ISeatmapRenderer -----------------------------------------------------\n\n setChart(doc: ChartDoc, opts?: { floorId?: string }): void {\n // Multi-floor: render the active floor (2D) or all floors stacked (3D). `view`\n // scopes the chart accordingly — single-floor charts pass through (=== doc).\n // A fresh chart (new ref) resets to 2D; a re-render (same ref) preserves the mode.\n if (doc !== this.chartDoc) this.stacked = false;\n this.chartDoc = doc;\n this.activeFloorId = opts?.floorId ?? floorsOf(doc)[0].id;\n // Object id → floor id, for resolving which deck a tap hit in the 3D stack\n // (stackFloors keeps object ids, so the map holds across the flatten).\n this.objectFloor.clear();\n if (doc.floors && doc.floors.length > 1) {\n for (const f of doc.floors) for (const o of f.objects) this.objectFloor.set(o.id, f.id);\n }\n const view = this.floorView(doc);\n this.focusedId = null;\n this.focusRing.visible(false);\n this.bgLayer.destroyChildren();\n this.seatLayer.destroyChildren();\n this.labelGroup.destroyChildren();\n this.circleById.clear();\n this.boothDims.clear();\n this.boothLabelById.clear();\n this.selectionMarkers.clear();\n this.ownedHold.clear();\n this.selectionFocusId = null;\n this.statusById.clear();\n this.selection.clear();\n this.seatById.clear();\n this.cached = false;\n this.accessFilter = null;\n this.sections = [];\n this.zones = [];\n this.seatSection.clear();\n this.catPrice.clear();\n this.zoneColor.clear();\n this.lodScale = 0;\n this.hasBoothText = false;\n // Reloading the chart resets the view to flat (identity layer transforms).\n if (this.isoRaf) { cancelAnimationFrame(this.isoRaf); this.isoRaf = 0; }\n this.isoT = 0;\n this.isoTarget = 0;\n this.resetLayerTransforms();\n this.hasSections = view.objects.some((o) => o.type === 'section');\n for (const z of doc.zones ?? []) if (z.color) this.zoneColor.set(z.id, z.color);\n // Seats fade against the block fill during the melt; reset to fully opaque.\n this.seatLayer.opacity(1);\n this.hoverRing.visible(false);\n\n this.theme = doc.theme ?? {};\n // Adjustable seat size: a chart-level scale on the base radius. Clamped so\n // enlarged seats don't collide with typical row spacing (~24 units).\n this.seatR = clamp(this.theme.seatScale ?? 1, 0.7, 1.6) * SEAT_RADIUS;\n // Canvas background via container style (reset to '' when theme omits it).\n this.container.style.background = this.theme.background ?? '';\n this.effSelection = this.resolveSelectionColor();\n this.hoverRing.stroke(this.effSelection);\n this.hoverRing.radius(this.seatR + 2);\n\n this.catColor.clear();\n this.catPrice.clear();\n this.catOrder = doc.categories.map((c) => c.key);\n for (const c of doc.categories) {\n this.catColor.set(c.key, c.color);\n if (typeof c.price === 'number') this.catPrice.set(c.key, c.price);\n }\n\n for (const obj of view.objects) {\n if (obj.type === 'booth') {\n this.boothDims.set(obj.id, { width: obj.width, height: obj.height, rotation: obj.rotation });\n }\n }\n\n this.seats = expandChart(view);\n for (const s of this.seats) {\n this.seatById.set(s.id, s);\n this.statusById.set(s.id, 'free');\n }\n\n this.renderBackground(view);\n this.renderSeats();\n // re-add overlay furniture wiped by destroyChildren above\n this.overlayLayer.add(this.labelGroup);\n this.overlayLayer.add(this.hoverRing);\n\n this.bounds = chartBounds(view);\n this.isoCentre = { x: this.bounds.x + this.bounds.width / 2, y: this.bounds.y + this.bounds.height / 2 };\n this.zoomToFit();\n }\n\n /** The chart to render: all floors stacked (3D overview), the active floor, or\n * the whole chart for single-floor charts. */\n private floorView(doc: ChartDoc): ChartDoc {\n if (!doc.floors || !doc.floors.length) return doc;\n if (this.stacked && doc.floors.length >= 2) return stackFloors(doc);\n const floor = doc.floors.find((f) => f.id === this.activeFloorId) ?? doc.floors[0];\n return { ...doc, objects: floor.objects, focalPoint: floor.focalPoint, backgroundImage: floor.backgroundImage, floors: undefined };\n }\n\n /** Toggle the 3D all-floors stacked overview (Batch 5). Re-renders; no-op on\n * single-floor charts. The caller re-applies statuses + animates the iso view. */\n setStacked(on: boolean): void {\n if (!this.chartDoc || on === this.stacked) return;\n const multi = !!this.chartDoc.floors && this.chartDoc.floors.length >= 2;\n if (!multi) return;\n this.stacked = on;\n this.setChart(this.chartDoc, { floorId: this.activeFloorId });\n }\n isStacked(): boolean {\n return this.stacked;\n }\n\n /** Switch which floor is shown (2D). Re-renders + re-fits; no-op if unchanged. */\n setActiveFloor(floorId: string): void {\n if (!this.chartDoc || floorId === this.activeFloorId) return;\n this.setChart(this.chartDoc, { floorId });\n }\n\n /** Floors for the host's switcher (single-floor charts return one synthetic floor). */\n getFloors(): { id: string; name: string }[] {\n return this.chartDoc ? floorsOf(this.chartDoc).map((f) => ({ id: f.id, name: f.name })) : [];\n }\n\n getActiveFloorId(): string {\n return this.activeFloorId;\n }\n\n setStatus(seatIds: string[], status: SeatStatus): void {\n let touched = false;\n // Sections whose availability tint / \"N LEFT\" needs a cheap recompute.\n const affected = this.hasSections ? new Set<SectionRender>() : null;\n for (const id of seatIds) {\n if (!this.statusById.has(id)) continue;\n const prev = this.statusById.get(id);\n this.statusById.set(id, status);\n const c = this.circleById.get(id);\n if (c) {\n this.paintSeat(c, id);\n touched = true;\n }\n if (affected) {\n const sec = this.seatSection.get(id);\n if (sec) {\n if ((prev === 'free') !== (status === 'free')) {\n sec.free += status === 'free' ? 1 : -1;\n }\n affected.add(sec);\n }\n }\n }\n if (affected && affected.size) {\n for (const sec of affected) this.refreshSectionFill(sec);\n this.bgLayer.batchDraw();\n }\n if (!touched) return;\n if (this.cached) {\n // bitmap is stale; debounce a re-cache so bulk updates coalesce\n if (this.recacheTimer) clearTimeout(this.recacheTimer);\n this.recacheTimer = setTimeout(() => this.cacheSeatLayer(), 150);\n } else {\n this.seatLayer.batchDraw();\n }\n if (this.effScale() > LABEL_SCALE) this.updateLabels();\n }\n\n setOwnedHold(seatIds: string[] | null): void {\n const next = new Set((seatIds ?? []).filter((id) => this.statusById.has(id)));\n const touched = new Set([...this.ownedHold, ...next]);\n this.ownedHold = next;\n for (const id of touched) {\n const shape = this.circleById.get(id);\n if (shape) this.paintSeat(shape, id);\n this.syncSelectionMarker(id);\n }\n if (!touched.size) return;\n if (this.cached) {\n if (this.recacheTimer) clearTimeout(this.recacheTimer);\n this.recacheTimer = setTimeout(() => this.cacheSeatLayer(), 150);\n } else {\n this.seatLayer.batchDraw();\n }\n if (this.effScale() > LABEL_SCALE) this.updateLabels();\n this.overlayLayer.batchDraw();\n }\n\n setSelectionFocus(seatId: string | null): void {\n const next = seatId && this.selection.has(seatId) ? seatId : null;\n if (next === this.selectionFocusId) return;\n const previous = this.selectionFocusId;\n this.selectionFocusId = next;\n\n for (const seat of this.seats) {\n const shape = this.circleById.get(seat.id);\n if (shape) this.paintSeat(shape, seat.id);\n }\n if (previous) this.syncSelectionMarker(previous);\n if (next) this.syncSelectionMarker(next);\n for (const [id, marker] of this.selectionMarkers) {\n marker.opacity(!next || id === next ? 1 : 0.2);\n }\n if (this.cached) {\n this.seatLayer.clearCache();\n this.cacheSeatLayer();\n } else {\n this.seatLayer.batchDraw();\n }\n this.overlayLayer.batchDraw();\n }\n\n getStatus(seatId: string): SeatStatus {\n return this.statusById.get(seatId) ?? 'free';\n }\n\n getSelection(): ExpandedSeat[] {\n const out: ExpandedSeat[] = [];\n for (const id of this.selection) {\n const s = this.seatById.get(id);\n if (s) out.push(s);\n }\n return out;\n }\n\n clearSelection(): void {\n const ids = [...this.selection];\n for (const id of ids) this.setSelected(id, false, true);\n this.overlayLayer.batchDraw();\n }\n\n /** Switch organizer interaction in place so the host preserves camera, LOD,\n * focus and live status state while moving between Monitor and Block. */\n setManageInteraction(options: {\n manageMode: boolean;\n marqueeSelect: boolean;\n selectableStatuses: SeatStatus[];\n maxSelection?: number;\n }): void {\n if (this.marquee) this.cancelMarquee();\n this.panLast = null;\n this.panStart = null;\n this.panStarted = false;\n this.opts.manageMode = options.manageMode;\n this.opts.marqueeSelect = options.marqueeSelect;\n this.opts.selectableStatuses = [...options.selectableStatuses];\n if (options.maxSelection != null) this.opts.maxSelection = options.maxSelection;\n\n // A selection from a previous interaction mode must not remain actionable\n // after the new mode makes it read-only or changes its eligible statuses.\n const invalid = [...this.selection].filter((id) => !this.isSelectable(id));\n if (invalid.length) this.deselect(invalid);\n if (!options.manageMode && this.selection.size) this.clearSelection();\n this.container.style.cursor = 'default';\n this.overlayLayer.batchDraw();\n }\n\n /** Apply a non-destructive velocity treatment to section outlines. Seat\n * category/status fills remain untouched so heat never changes seat meaning. */\n setSectionHeat(scores: Record<string, number> | null): void {\n this.sectionHeat.clear();\n for (const [sectionId, raw] of Object.entries(scores ?? {})) {\n if (Number.isFinite(raw)) this.sectionHeat.set(sectionId, Math.max(0, Math.min(1, raw)));\n }\n for (const section of this.sections) this.refreshSectionHeat(section);\n this.bgLayer.batchDraw();\n }\n\n deselect(seatIds: string[]): void {\n let changed = false;\n for (const id of seatIds) {\n if (this.selection.has(id)) {\n this.setSelected(id, false, true);\n changed = true;\n }\n }\n if (changed) this.overlayLayer.batchDraw();\n }\n\n // ---- manage-mode bulk selection (SDK SeatManager) -------------------------\n // All option-gated: no-ops (or empty) unless `manageMode` is set, so buyer\n // surfaces that never pass the flag can't reach any of this.\n\n /** Select every selectable seat on the chart (⌘A). Returns the added seats. */\n selectAllSelectable(): ExpandedSeat[] {\n if (!this.opts.manageMode) return [];\n const ids: string[] = [];\n for (const seat of this.seats) if (this.isSelectable(seat.id)) ids.push(seat.id);\n return this.selectMany(ids);\n }\n\n /** Select the selectable seats matching these public labels (category/row/\n * section bulk resolves to labels host-side). Returns the newly added seats. */\n selectByLabels(labels: string[]): ExpandedSeat[] {\n if (!this.opts.manageMode) return [];\n const want = new Set(labels);\n const ids: string[] = [];\n for (const seat of this.seats) {\n if (want.has(seat.label) && this.isSelectable(seat.id)) ids.push(seat.id);\n }\n return this.selectMany(ids);\n }\n\n /** Selectable seats in a section OR zone id — pure read (no selection change). */\n getSelectableInSection(sectionId: string): ExpandedSeat[] {\n const out: ExpandedSeat[] = [];\n const seen = new Set<string>();\n for (const sec of this.sections) {\n if (sec.id !== sectionId && sec.zone !== sectionId) continue;\n for (const id of sec.memberIds) {\n if (seen.has(id)) continue;\n seen.add(id);\n if (!this.isSelectable(id)) continue;\n const s = this.seatById.get(id);\n if (s) out.push(s);\n }\n }\n return out;\n }\n\n /**\n * Union `ids` into the selection in one batched pass. Beyond MARQUEE_RING_CAP\n * total selected we skip the per-seat ring nodes (fill paint still marks the\n * seats) so a whole-arena select doesn't spawn thousands of Konva shapes.\n * Returns the full current selection.\n */\n private selectMany(ids: string[]): ExpandedSeat[] {\n const fresh = ids.filter((id) => !this.selection.has(id));\n if (!fresh.length) return this.getSelection();\n const drawRings = this.selection.size + fresh.length <= MARQUEE_RING_CAP;\n for (const id of fresh) {\n if (drawRings) {\n this.setSelected(id, true, true); // ring + fill, silent (batch draw below)\n } else {\n this.selection.add(id);\n const c = this.circleById.get(id);\n if (c) this.paintSeat(c, id);\n }\n }\n if (!this.cached) this.seatLayer.batchDraw();\n this.overlayLayer.batchDraw();\n return this.getSelection();\n }\n\n // ---- manage-mode marquee gesture ------------------------------------------\n\n private beginMarquee(clientPt: { x: number; y: number }): void {\n const w = this.screenToWorld(clientPt);\n const s = this.stage.scaleX() || 1;\n const rect = new Rect({\n x: w.x,\n y: w.y,\n width: 0,\n height: 0,\n stroke: this.effSelection,\n strokeWidth: 1.5 / s, // world units → ~constant on-screen px under the stage scale\n dash: [5 / s, 4 / s],\n fill: 'rgba(110,123,255,0.10)',\n listening: false,\n perfectDrawEnabled: false,\n shadowForStrokeEnabled: false,\n });\n this.overlayLayer.add(rect);\n this.marquee = { start: w, rect };\n this.marqueeCur = w;\n this.overlayLayer.batchDraw();\n }\n\n private updateMarquee(clientPt: { x: number; y: number }): void {\n if (!this.marquee) return;\n const w = this.screenToWorld(clientPt);\n const { start, rect } = this.marquee;\n rect.setAttrs({\n x: Math.min(start.x, w.x),\n y: Math.min(start.y, w.y),\n width: Math.abs(w.x - start.x),\n height: Math.abs(w.y - start.y),\n });\n this.marqueeCur = w;\n this.overlayLayer.batchDraw();\n }\n\n private cancelMarquee(): void {\n if (!this.marquee) return;\n this.marquee.rect.destroy();\n this.marquee = null;\n this.marqueeCur = null;\n this.overlayLayer.batchDraw();\n }\n\n /**\n * Pointer-up: hit-test the marquee world-rect against the in-memory seat\n * centres (NOT the Konva hit-graph — that's a cached bitmap when zoomed and\n * far slower), keep only SELECTABLE seats, union them into the selection and\n * fire `onMarquee`. A near-zero drag reads as a click: clear the selection.\n */\n private finishMarquee(): void {\n const m = this.marquee;\n this.marquee = null;\n if (!m) return;\n m.rect.destroy();\n this.overlayLayer.batchDraw();\n const cur = this.marqueeCur ?? m.start;\n this.marqueeCur = null;\n const x0 = Math.min(m.start.x, cur.x);\n const x1 = Math.max(m.start.x, cur.x);\n const y0 = Math.min(m.start.y, cur.y);\n const y1 = Math.max(m.start.y, cur.y);\n const s = this.stage.scaleX() || 1;\n // Sub-4px drag = a click on empty canvas → deselect-all affordance.\n if ((x1 - x0) * s < 4 && (y1 - y0) * s < 4) {\n if (this.selection.size) {\n this.clearSelection();\n this.opts.onMarquee?.([]);\n }\n return;\n }\n const ids: string[] = [];\n for (const seat of this.seats) {\n if (seat.x < x0 || seat.x > x1 || seat.y < y0 || seat.y > y1) continue;\n if (!this.isSelectable(seat.id)) continue;\n ids.push(seat.id);\n }\n this.selectMany(ids);\n this.opts.onMarquee?.(this.getSelection());\n }\n\n flashSeat(seatId: string, color = '#f43f5e'): void {\n const seat = this.seatById.get(seatId);\n if (!seat) return;\n const ring = new Circle({\n x: seat.x,\n y: seat.y,\n radius: this.seatR,\n stroke: color,\n strokeWidth: 3,\n opacity: 0.9,\n listening: false,\n perfectDrawEnabled: false,\n shadowForStrokeEnabled: false,\n });\n this.overlayLayer.add(ring);\n const start = performance.now();\n const dur = 620;\n const step = (now: number): void => {\n // Guard against a destroy() mid-animation (layer torn down).\n if (!ring.getLayer()) return;\n const t = Math.min(1, (now - start) / dur);\n ring.radius(this.seatR * (1 + t * 1.8));\n ring.opacity(0.9 * (1 - t));\n this.overlayLayer.batchDraw();\n if (t < 1) requestAnimationFrame(step);\n else {\n ring.destroy();\n this.overlayLayer.batchDraw();\n }\n };\n requestAnimationFrame(step);\n }\n\n // ---- keyboard navigation (accessibility) ----------------------------------\n\n private onKeyDown = (e: KeyboardEvent): void => {\n // Manage-mode bulk shortcuts: ⌘/Ctrl-A selects all selectable, Escape clears.\n // Both fire onMarquee so the SDK toolbar tracks selection through one path.\n if (this.opts.manageMode) {\n if ((e.metaKey || e.ctrlKey) && (e.key === 'a' || e.key === 'A')) {\n e.preventDefault();\n this.opts.onMarquee?.(this.selectAllSelectable());\n return;\n }\n if (e.key === 'Escape' && this.selection.size) {\n e.preventDefault();\n this.clearSelection();\n this.opts.onMarquee?.([]);\n return;\n }\n }\n const dir =\n e.key === 'ArrowLeft' ? { x: -1, y: 0 }\n : e.key === 'ArrowRight' ? { x: 1, y: 0 }\n : e.key === 'ArrowUp' ? { x: 0, y: -1 }\n : e.key === 'ArrowDown' ? { x: 0, y: 1 }\n : null;\n if (dir) {\n e.preventDefault();\n const next = this.focusedId ? this.nearestSeat(this.focusedId, dir) : this.seats[0]?.id ?? null;\n if (next) this.focusSeat(next);\n return;\n }\n if ((e.key === 'Enter' || e.key === ' ') && this.focusedId) {\n e.preventDefault();\n this.toggleSeat(this.focusedId);\n const s = this.seatById.get(this.focusedId);\n if (s) this.opts.onFocusSeat?.(s); // re-announce; status may have changed\n }\n };\n\n /** Nearest seat from `fromId` in a cardinal direction (aligned + close wins). */\n private nearestSeat(fromId: string, dir: { x: number; y: number }): string | null {\n const from = this.seatById.get(fromId);\n if (!from) return null;\n let best: string | null = null;\n let bestScore = Infinity;\n for (const s of this.seats) {\n if (s.id === fromId) continue;\n const dx = s.x - from.x;\n const dy = s.y - from.y;\n const proj = dx * dir.x + dy * dir.y; // along the chosen direction\n if (proj <= 0.5) continue; // must lie in that direction\n const perp = Math.abs(dx * dir.y - dy * dir.x); // lateral offset\n const score = proj + perp * 2.5; // reward alignment + proximity\n if (score < bestScore) {\n bestScore = score;\n best = s.id;\n }\n }\n return best;\n }\n\n private focusSeat(id: string): void {\n const seat = this.seatById.get(id);\n if (!seat) return;\n this.focusedId = id;\n this.focusRing.radius(this.seatR + 3);\n this.focusRing.position({ x: seat.x, y: seat.y });\n this.focusRing.visible(true);\n this.ensureVisible(seat);\n this.overlayLayer.batchDraw();\n this.opts.onFocusSeat?.(seat);\n }\n\n /** Pan/zoom so a seat sits on-screen at a legible scale (for keyboard focus). */\n private ensureVisible(seat: ExpandedSeat): void {\n const w = this.stage.width();\n const h = this.stage.height();\n const target = Math.max(this.stage.scaleX(), SEAT_LEGIBLE_SCALE * 1.2);\n const p = this.worldToScreen(seat);\n const margin = 70;\n const offscreen = p.x < margin || p.x > w - margin || p.y < margin || p.y > h - margin;\n if (this.stage.scaleX() < target || offscreen) {\n // Centre on the PROJECTED seat position so iso view frames it correctly.\n const ip = this.isoT === 0 ? seat : this.isoForward(seat);\n this.stage.scale({ x: target, y: target });\n this.stage.position({ x: w / 2 - ip.x * target, y: h / 2 - ip.y * target });\n this.afterViewChange();\n this.stage.batchDraw();\n }\n }\n\n zoomToFit(): void {\n const w = this.stage.width();\n const h = this.stage.height();\n const b = this.bounds;\n this.fitScale = Math.min(w / b.width, h / b.height) || 1;\n const s = this.fitScale;\n this.stage.scale({ x: s, y: s });\n this.stage.position({\n x: (w - b.width * s) / 2 - b.x * s,\n y: (h - b.height * s) / 2 - b.y * s,\n });\n this.afterViewChange();\n this.stage.batchDraw();\n }\n\n /** Step factor for the on-screen +/− buttons (B1) — same clamp path as pinch/wheel. */\n private static readonly ZOOM_STEP = 1.4;\n\n zoomIn(): void {\n const center = { x: this.stage.width() / 2, y: this.stage.height() / 2 };\n this.zoomAbout(this.stage.scaleX() * SeatmapRenderer.ZOOM_STEP, center);\n }\n\n zoomOut(): void {\n const center = { x: this.stage.width() / 2, y: this.stage.height() / 2 };\n this.zoomAbout(this.stage.scaleX() / SeatmapRenderer.ZOOM_STEP, center);\n }\n\n seatCount(): number {\n return this.seats.length;\n }\n\n worldToScreen(point: Point): { x: number; y: number } {\n const s = this.stage.scaleX();\n // In iso view, host overlays (confirm card, tooltip) must anchor to the\n // PROJECTED seat, so run the point through the iso affine first. At isoT=0\n // isoForward is the identity — byte-for-byte the flat behaviour.\n const p = this.isoT === 0 ? point : this.isoForward(point);\n return { x: p.x * s + this.stage.x(), y: p.y * s + this.stage.y() };\n }\n\n setAccessibleFilter(on: boolean): void {\n this.setAccessibilityFilter(on ? [] : null);\n }\n\n setAccessibilityFilter(types: AccessibilityType[] | null): void {\n const next = types === null ? null : [...types];\n if (this.sameAccessFilter(next)) return;\n this.accessFilter = next;\n for (const seat of this.seats) {\n const c = this.circleById.get(seat.id);\n if (c) this.paintSeat(c, seat.id);\n }\n if (this.cached) {\n this.seatLayer.clearCache();\n this.cacheSeatLayer();\n } else {\n this.seatLayer.batchDraw();\n }\n }\n\n private sameAccessFilter(next: AccessibilityType[] | null): boolean {\n const cur = this.accessFilter;\n if (cur === null || next === null) return cur === next;\n return cur.length === next.length && cur.every((t, i) => t === next[i]);\n }\n\n /**\n * Price-band filter (F4): dim free, unselected seats whose category key is NOT\n * in `keys`. `null` clears the filter (all categories fully visible). The\n * widget resolves which categories fall inside the buyer's chosen band.\n */\n setCategoryFilter(keys: string[] | null): void {\n const next = keys === null ? null : new Set(keys);\n const same = (next === null && this.categoryFilter === null) ||\n (next !== null && this.categoryFilter !== null &&\n next.size === this.categoryFilter.size && [...next].every((k) => this.categoryFilter!.has(k)));\n if (same) return;\n this.categoryFilter = next;\n for (const seat of this.seats) {\n const c = this.circleById.get(seat.id);\n if (c) this.paintSeat(c, seat.id);\n }\n if (this.cached) {\n this.seatLayer.clearCache();\n this.cacheSeatLayer();\n } else {\n this.seatLayer.batchDraw();\n }\n }\n\n /** Frame the currently available inventory that survived a buyer price\n * filter. Clearing the filter glides back to the full venue. */\n focusCategories(keys: string[] | null): void {\n if (!keys?.length) {\n this.focusRegion(this.bounds, { durationMs: CAMERA_GLIDE_MS });\n return;\n }\n const wanted = new Set(keys);\n const matching = this.seats.filter((seat) => {\n if (!wanted.has(seat.categoryKey) || this.seatInClosedSection(seat.id)) return false;\n const status = this.statusById.get(seat.id) ?? 'free';\n return status === 'free' || this.ownedHold.has(seat.id);\n });\n if (!matching.length) return;\n let minX = Infinity;\n let maxX = -Infinity;\n let minY = Infinity;\n let maxY = -Infinity;\n for (const seat of matching) {\n minX = Math.min(minX, seat.x);\n maxX = Math.max(maxX, seat.x);\n minY = Math.min(minY, seat.y);\n maxY = Math.max(maxY, seat.y);\n }\n const pad = Math.max(24, this.seatR * 3);\n minX -= pad;\n maxX += pad;\n minY -= pad;\n maxY += pad;\n this.focusRegion(\n { x: minX, y: minY, width: Math.max(40, maxX - minX), height: Math.max(40, maxY - minY) },\n { durationMs: CAMERA_GLIDE_MS },\n );\n }\n\n // ---- isometric (\"3D\") view mode -------------------------------------------\n\n /**\n * Switch the projection between flat top-down and the isometric \"3D\" view\n * (rotate + y-squash about the chart centre, plus per-elevation lift). Tweens\n * `isoT` 0⇄1 over ~0.32s (ease in-out); reduced-motion snaps. Purely visual —\n * geometry stays flat, so hit-testing (Konva's own, plus the manual section\n * inverse) keeps landing on the projected seats/sections.\n */\n setViewMode(mode: 'flat' | 'isometric'): void {\n const target = mode === 'isometric' ? 1 : 0;\n this.isoTarget = target;\n if (this.isoRaf) { cancelAnimationFrame(this.isoRaf); this.isoRaf = 0; }\n if (this.reducedMotion) {\n this.isoT = target;\n this.applyIso();\n this.afterViewChange();\n return;\n }\n const from = this.isoT;\n if (from === target) { this.applyIso(); this.afterViewChange(); return; }\n const start = performance.now();\n const step = (now: number): void => {\n if (this.destroyed) return; // guard a destroy() mid-tween\n const raw = Math.min(1, (now - start) / ISO_TWEEN_MS);\n // easeInOutCubic — matches the melt's camera glide.\n const e = raw < 0.5 ? 4 * raw * raw * raw : 1 - Math.pow(-2 * raw + 2, 3) / 2;\n this.isoT = from + (this.isoTarget - from) * e;\n this.applyIso();\n this.scheduleViewChange();\n if (raw < 1) {\n this.isoRaf = requestAnimationFrame(step);\n } else {\n this.isoT = this.isoTarget;\n this.isoRaf = 0;\n this.applyIso();\n this.afterViewChange(); // re-evaluate cache/labels at the settled effective scale\n }\n };\n this.isoRaf = requestAnimationFrame(step);\n }\n\n /** Current projection — reflects the tween target, not the mid-tween isoT. */\n getViewMode(): 'flat' | 'isometric' {\n return this.isoTarget === 1 ? 'isometric' : 'flat';\n }\n\n /** Iso angle (rad) + y-squash for the current isoT. */\n private isoParams(): { th: number; sg: number } {\n return { th: (ISO_ANGLE_DEG * Math.PI) / 180 * this.isoT, sg: 1 - (1 - ISO_SQUASH) * this.isoT };\n }\n\n /** Effective vertical scale = stage scale × iso squash — legibility math uses this. */\n private effScale(): number {\n return this.stage.scaleX() * (1 - (1 - ISO_SQUASH) * this.isoT);\n }\n\n /** Project a world point through the iso affine about the chart centre (→ iso-world). */\n private isoForward(p: Point): { x: number; y: number } {\n const { th, sg } = this.isoParams();\n const c = this.isoCentre;\n const dx = p.x - c.x;\n const dy = p.y - c.y;\n const rx = dx * Math.cos(th) - dy * Math.sin(th);\n const ry = (dx * Math.sin(th) + dy * Math.cos(th)) * sg;\n return { x: c.x + rx, y: c.y + ry };\n }\n\n /** Inverse of isoForward (iso-world → world) for screen-space hit-testing. */\n private isoInverse(p: Point): { x: number; y: number } {\n const { th, sg } = this.isoParams();\n const c = this.isoCentre;\n const dx = p.x - c.x;\n const dy = p.y - c.y;\n const uy = dy / sg;\n const wx = dx * Math.cos(th) + uy * Math.sin(th);\n const wy = -dx * Math.sin(th) + uy * Math.cos(th);\n return { x: c.x + wx, y: c.y + wy };\n }\n\n /**\n * Local-space offset that, once the layer applies the iso affine, lifts an\n * object straight UP in iso-world by `elevation × LIFT_PER_STEP × isoT`\n * (= inverse-linear of the pure vertical lift). Zero at isoT=0.\n */\n private isoLiftLocal(elevation: number): { x: number; y: number } {\n const { th, sg } = this.isoParams();\n const delta = elevation * LIFT_PER_STEP * this.isoT;\n return { x: -(delta / sg) * Math.sin(th), y: -(delta / sg) * Math.cos(th) };\n }\n\n /** Restore the three layers to identity (flat) — byte-for-byte the original. */\n private resetLayerTransforms(): void {\n for (const layer of [this.bgLayer, this.seatLayer, this.overlayLayer]) {\n layer.position({ x: 0, y: 0 });\n layer.offset({ x: 0, y: 0 });\n layer.scale({ x: 1, y: 1 });\n layer.rotation(0);\n layer.skewX(0);\n layer.skewY(0);\n }\n }\n\n /**\n * Apply the current isoT to the scene: the base rotate+squash as a decomposed\n * layer transform (so seats/décor/rings project together and Konva's own\n * hit-testing follows), upright counter-transforms on text, and the elevation\n * lift + extruded side faces on elevated sections.\n */\n private applyIso(): void {\n const t = this.isoT;\n if (t === 0) {\n this.resetLayerTransforms();\n } else {\n const { th, sg } = this.isoParams();\n // L_iso = Scale(1,sg)·Rot(th) about the centre; decompose to Konva props.\n const a = Math.cos(th);\n const b = sg * Math.sin(th);\n const cc = -Math.sin(th);\n const d = sg * Math.cos(th);\n const r = Math.sqrt(a * a + b * b);\n const delta = a * d - b * cc; // = sg\n const rotationDeg = (Math.atan2(b, a) * 180) / Math.PI;\n const scaleX = r;\n const scaleY = delta / r;\n const skewX = (a * cc + b * d) / delta;\n const c = this.isoCentre;\n for (const layer of [this.bgLayer, this.seatLayer, this.overlayLayer]) {\n layer.position({ x: c.x, y: c.y });\n layer.offset({ x: c.x, y: c.y });\n layer.rotation(rotationDeg);\n layer.scaleX(scaleX);\n layer.scaleY(scaleY);\n layer.skewX(skewX);\n layer.skewY(0);\n }\n }\n\n this.applyUprightLabels();\n this.applyElevation();\n\n this.bgLayer.batchDraw();\n this.seatLayer.batchDraw();\n this.overlayLayer.batchDraw();\n }\n\n /** Counter-skew every visible label so it renders upright at its projected anchor. */\n private applyUprightLabels(): void {\n const thDeg = ISO_ANGLE_DEG * this.isoT;\n const invScaleY = 1 / (1 - (1 - ISO_SQUASH) * this.isoT);\n // Seat labels live in overlayLayer (labelGroup); section/zone/décor in bgLayer.\n // Skip the seatLayer scan unless it actually holds booth labels (else it is\n // thousands of Circles with no Text).\n const layers = this.hasBoothText\n ? [this.bgLayer, this.seatLayer, this.overlayLayer]\n : [this.bgLayer, this.overlayLayer];\n for (const layer of layers) {\n const texts = layer.find('Text') as unknown as Text[];\n for (const tn of texts) {\n let base = tn.getAttr('uprightBase') as number | undefined;\n if (base == null) {\n base = tn.rotation();\n tn.setAttr('uprightBase', base);\n }\n tn.rotation(base - thDeg);\n tn.scaleX(1);\n tn.scaleY(invScaleY);\n tn.skewX(0);\n }\n }\n }\n\n /** Lift elevated sections (+ their members) and update their extruded side faces. */\n private applyElevation(): void {\n const t = this.isoT;\n for (const sec of this.sections) {\n if (sec.elevation <= 0) continue;\n const off = this.isoLiftLocal(sec.elevation);\n sec.liftGroupBg?.position(off);\n sec.liftGroupSeat?.position(off);\n // Side faces: quad per edge from base outline to the lifted outline, in\n // local (world) space — the layer projects them. Invisible at isoT=0.\n const alpha = 0.9 * t;\n for (let i = 0; i < sec.sideFaces.length; i++) {\n const face = sec.sideFaces[i];\n const p0 = sec.outline[i];\n const p1 = sec.outline[(i + 1) % sec.outline.length];\n face.points([p0.x, p0.y, p1.x, p1.y, p1.x + off.x, p1.y + off.y, p0.x + off.x, p0.y + off.y]);\n face.opacity(alpha);\n }\n }\n }\n\n destroy(): void {\n this.destroyed = true;\n if (this.rafId) cancelAnimationFrame(this.rafId);\n if (this.isoRaf) cancelAnimationFrame(this.isoRaf);\n if (this.glideRaf) cancelAnimationFrame(this.glideRaf);\n if (this.viewChangeRaf) cancelAnimationFrame(this.viewChangeRaf);\n if (this.recacheTimer) clearTimeout(this.recacheTimer);\n this.resizeObs?.disconnect();\n this.container.removeEventListener('pointerdown', this.onPointerDown);\n this.container.removeEventListener('pointermove', this.onPointerMove);\n this.container.removeEventListener('pointerup', this.onPointerEnd);\n this.container.removeEventListener('pointercancel', this.onPointerEnd);\n this.container.removeEventListener('keydown', this.onKeyDown);\n this.stage.destroy();\n }\n\n // ---- rendering ------------------------------------------------------------\n\n /** Theme font stack for all rendered text (falls back to Inter). */\n private labelFont(): string {\n return this.theme.fontFamily || 'Inter, sans-serif';\n }\n\n /**\n * Where a seat's nodes live: an elevated section's lift group (so the whole\n * tier shifts with one offset in iso view) or the seat layer directly.\n */\n private seatContainer(id: string): Group | Layer {\n return this.seatSection.get(id)?.liftGroupSeat ?? this.seatLayer;\n }\n\n private renderSeats(): void {\n for (const seat of this.seats) {\n if (seat.kind === 'booth') {\n this.renderBoothUnit(seat);\n continue;\n }\n const target = this.seatContainer(seat.id);\n const c = new Circle({\n x: seat.x,\n y: seat.y,\n radius: this.seatR,\n perfectDrawEnabled: false,\n shadowForStrokeEnabled: false,\n hitStrokeWidth: 0,\n });\n c.setAttr('seatId', seat.id);\n this.circleById.set(seat.id, c);\n this.paintSeat(c, seat.id);\n target.add(c);\n // Accessible seats get a static 2px outer ring, coloured by their primary\n // accommodation (few per chart, so the extra node is cheap).\n if (seat.accessible) {\n const primary = seat.accessibility?.[0];\n target.add(\n new Circle({\n x: seat.x,\n y: seat.y,\n radius: this.seatR + 1,\n stroke: (primary && ACCESS_RING[primary]) || '#3b82f6',\n strokeWidth: 2,\n listening: false,\n perfectDrawEnabled: false,\n shadowForStrokeEnabled: false,\n }),\n );\n }\n }\n }\n\n /** A booth renders as a click-selectable rounded block (dims from the doc). */\n private renderBoothUnit(seat: ExpandedSeat): void {\n const target = this.seatContainer(seat.id);\n const dims = this.boothDims.get(seat.rowId) ?? { width: 40, height: 30, rotation: 0 };\n const rect = new Rect({\n x: seat.x,\n y: seat.y,\n width: dims.width,\n height: dims.height,\n offsetX: dims.width / 2,\n offsetY: dims.height / 2,\n rotation: dims.rotation,\n cornerRadius: 4,\n perfectDrawEnabled: false,\n shadowForStrokeEnabled: false,\n hitStrokeWidth: 0,\n });\n rect.setAttr('seatId', seat.id);\n this.circleById.set(seat.id, rect);\n this.paintSeat(rect, seat.id);\n target.add(rect);\n\n const t = new Text({\n x: seat.x,\n y: seat.y,\n text: seat.label,\n fontSize: 10,\n fontStyle: '600',\n fontFamily: this.labelFont(),\n fill: this.theme.seatLabelColor ?? DEF_SEAT_LABEL,\n listening: false,\n perfectDrawEnabled: false,\n });\n t.offsetX(t.width() / 2);\n t.offsetY(t.height() / 2);\n this.hasBoothText = true; // gate the upright-label scan of the seat layer\n this.boothLabelById.set(seat.id, t);\n target.add(t);\n }\n\n /** The category's display color — Okabe-Ito hue when colorblind-safe is on. */\n private seatBaseColor(categoryKey: string): string {\n if (!this.colorblind) return this.catColor.get(categoryKey) ?? '#6e7bff';\n const idx = this.catOrder.indexOf(categoryKey);\n return CB_PALETTE[(idx >= 0 ? idx : 0) % CB_PALETTE.length];\n }\n\n /** Apply fill/stroke/opacity for a seat's current status + selection. */\n private paintSeat(c: Shape, id: string): void {\n const seat = this.seatById.get(id)!;\n const status = this.statusById.get(id) ?? 'free';\n const selected = this.selection.has(id);\n const base = this.seatBaseColor(seat.categoryKey);\n const boothLabel = this.boothLabelById.get(id);\n\n c.dash([]);\n c.strokeWidth(0);\n c.stroke('');\n c.opacity(1);\n\n switch (status) {\n case 'free':\n // Selected: on dark canvases the lightened fill + white ring pops; on\n // light canvases that same wash reads as *disabled*, so keep the full\n // category fill and let the dark contrast ring carry the state.\n c.fill(\n selected && this.effSelection === DEF_SELECTION ? lighten(base, 0.28) : base,\n );\n break;\n case 'held':\n if (this.ownedHold.has(id)) {\n // A buyer returning from checkout must be able to distinguish their\n // own inventory from somebody else's hold. Preserve the category\n // identity and outline the actual seat/booth shape (full rectangle\n // for a booth), rather than painting it generic unavailable grey.\n c.fill(lighten(base, this.effSelection === DEF_SELECTION ? 0.24 : 0.1));\n c.stroke(this.effSelection);\n c.strokeWidth(3);\n } else {\n c.fill(HELD_FILL);\n }\n break;\n case 'booked':\n if (this.colorblind) {\n // Non-color cue: booked reads as a hollow ring, never hue alone.\n c.fill('rgba(0,0,0,0)');\n c.stroke(TAKEN_FILL);\n c.strokeWidth(1.5);\n c.opacity(0.9);\n } else {\n c.fill(TAKEN_FILL);\n c.opacity(0.45);\n }\n break;\n case 'not_for_sale':\n c.fill(TAKEN_FILL);\n c.stroke(NFS_STROKE);\n c.strokeWidth(1);\n c.dash([2, 2]);\n break;\n }\n\n if (boothLabel) {\n boothLabel.text(status === 'booked' ? 'SOLD' : status === 'held' ? 'HELD' : seat.label);\n boothLabel.fontSize(status === 'free' ? 10 : Math.min(10, Math.max(6, this.boothDims.get(seat.rowId)?.width ?? 40) / 6));\n boothLabel.fontStyle(status === 'free' ? '600' : '800');\n boothLabel.fill(status === 'free' ? (this.theme.seatLabelColor ?? DEF_SEAT_LABEL) : '#ffffff');\n boothLabel.offsetX(boothLabel.width() / 2);\n boothLabel.offsetY(boothLabel.height() / 2);\n }\n\n // Accessibility filter dims free, unselected seats that don't match.\n if (this.accessFilter && status === 'free' && !selected && !seatMatchesAccess(seat, this.accessFilter)) {\n c.opacity(0.25);\n }\n // Legend hover-highlight dims free, unselected seats of other categories.\n if (this.categoryHighlight && status === 'free' && !selected && seat.categoryKey !== this.categoryHighlight) {\n c.opacity(0.25);\n }\n // Price-band filter (F4): dim free, unselected seats outside the chosen band.\n if (this.categoryFilter && status === 'free' && !selected && !this.categoryFilter.has(seat.categoryKey)) {\n c.opacity(0.22);\n }\n // Held-back inventory (organizer manager): seats in a dimmed section/zone\n // read as inactive so the map matches the Sections list at a glance.\n if (this.dimmedSections.size) {\n const sec = this.seatSection.get(id);\n if (sec && (this.dimmedSections.has(sec.id) || (sec.zone != null && this.dimmedSections.has(sec.zone)))) {\n c.opacity(0.18);\n }\n }\n // Phase 2 `closed` section: flat grey, 40% opacity, never a category hue —\n // overrides the status paint above. Seats stay visible but read off-sale.\n if (this.closedSections.size && this.seatInClosedSection(id)) {\n c.fill(CLOSED_SEAT_FILL);\n c.stroke('');\n c.strokeWidth(0);\n c.dash([]);\n c.opacity(CLOSED_SEAT_OPACITY);\n }\n // AXS section-focus: seats outside the focused section desaturate + dim so\n // the focused block reads against a calm ground (§4 focus spec).\n if (this.focusedSectionId) {\n const sec = this.seatSection.get(id);\n const inFocus = !!sec && (sec.id === this.focusedSectionId || sec.zone === this.focusedSectionId);\n if (!inFocus) c.opacity(FOCUS_DIM_OPACITY);\n }\n // Buyer confirmation focus: retain the candidate at full strength while\n // every unrelated seat recedes. The candidate/selected markers live on the\n // overlay layer and are dimmed separately so state remains readable.\n if (this.selectionFocusId && id !== this.selectionFocusId) c.opacity(Math.min(c.opacity(), 0.16));\n }\n\n /** True when a seat sits in a section/zone currently marked `closed`. */\n private seatInClosedSection(id: string): boolean {\n if (!this.closedSections.size) return false;\n const sec = this.seatSection.get(id);\n return !!sec && (this.closedSections.has(sec.id) || (sec.zone != null && this.closedSections.has(sec.zone)));\n }\n\n /**\n * Colorblind-safe mode: swap category hues for the Okabe-Ito palette and\n * render booked seats hollow. Off restores the exact default rendering.\n */\n setColorblindSafe(on: boolean): void {\n if (on === this.colorblind) return;\n this.colorblind = on;\n for (const seat of this.seats) {\n const c = this.circleById.get(seat.id);\n if (c) this.paintSeat(c, seat.id);\n }\n if (this.cached) {\n this.seatLayer.clearCache();\n this.cacheSeatLayer();\n } else {\n this.seatLayer.batchDraw();\n }\n }\n\n /**\n * Dim the seats of these section/zone ids (organizer manager use) so held-back\n * inventory is visually distinct on the canvas without hiding it. `null`/empty\n * clears. Unlike the buyer's applyHidden, the sections stay rendered.\n */\n setDimmedSections(ids: string[] | null): void {\n const next = new Set(ids ?? []);\n if (next.size === this.dimmedSections.size && [...next].every((i) => this.dimmedSections.has(i))) return;\n this.dimmedSections = next;\n for (const seat of this.seats) {\n const c = this.circleById.get(seat.id);\n if (c) this.paintSeat(c, seat.id);\n }\n if (this.cached) {\n this.seatLayer.clearCache();\n this.cacheSeatLayer();\n } else {\n this.seatLayer.batchDraw();\n }\n }\n\n /**\n * Phase 2 event-level section states: mark these section/zone ids `closed` —\n * flat grey block, seats greyed + not pickable, but the section stays rendered\n * (unlike the buyer's applyHidden which strips it). `null`/empty clears.\n */\n setClosedSections(ids: string[] | null): void {\n const next = new Set(ids ?? []);\n if (next.size === this.closedSections.size && [...next].every((i) => this.closedSections.has(i))) return;\n this.closedSections = next;\n this.repaintSectionsAndSeats();\n }\n\n /**\n * AXS section-focus: dim + desaturate every other section, draw a calm backdrop\n * panel behind this section's seats, and glide the camera in to frame it (the\n * seat-pick gate below only lets buyers pick once seats are ≥ LABEL_SCALE big).\n */\n focusSection(id: string): void {\n if (!this.sections.some((s) => s.id === id)) return;\n this.focusedSectionId = id;\n this.drawFocusBackdrop(id);\n this.repaintSectionsAndSeats();\n this.updateLOD();\n this.focusRegion(id, { minScale: SEAT_FOCUS_SCALE });\n }\n\n /** Clear an AXS section focus — restore full-bowl brightness + drop the backdrop. */\n clearSectionFocus(): void {\n if (!this.focusedSectionId) return;\n this.focusedSectionId = null;\n if (this.focusBackdrop) {\n this.focusBackdrop.destroy();\n this.focusBackdrop = null;\n }\n this.repaintSectionsAndSeats();\n this.updateLOD();\n }\n\n /** The currently AXS-focused section id, or null. */\n getFocusedSection(): string | null {\n return this.focusedSectionId;\n }\n\n /** Draw (or replace) the light backdrop panel behind the focused section. */\n private drawFocusBackdrop(id: string): void {\n if (this.focusBackdrop) {\n this.focusBackdrop.destroy();\n this.focusBackdrop = null;\n }\n const sec = this.sections.find((s) => s.id === id);\n if (!sec) return;\n const panel = new Line({\n points: sec.outline.flatMap((p) => [p.x, p.y]),\n closed: true,\n fill: FOCUS_BACKDROP_FILL,\n stroke: rgba('#ffffff', 0.1),\n strokeWidth: 1,\n listening: false,\n perfectDrawEnabled: false,\n });\n this.bgLayer.add(panel);\n panel.moveToTop(); // above the dimmed sibling blocks, still under the seat layer\n this.focusBackdrop = panel;\n }\n\n /** Repaint every seat + section block to reflect closed/focus state, then redraw. */\n private repaintSectionsAndSeats(): void {\n for (const seat of this.seats) {\n const c = this.circleById.get(seat.id);\n if (c) this.paintSeat(c, seat.id);\n }\n for (const sec of this.sections) sec.blockPoly.fill(this.sectionBlockFill(sec));\n if (this.cached) {\n this.seatLayer.clearCache();\n this.cacheSeatLayer();\n } else {\n this.seatLayer.batchDraw();\n }\n this.bgLayer.batchDraw();\n }\n\n /** The world-space rectangle currently visible in the viewport (minimap F3). */\n getVisibleWorldRect(): { x: number; y: number; width: number; height: number } {\n const tl = this.screenToWorld({ x: 0, y: 0 });\n const br = this.screenToWorld({ x: this.stage.width(), y: this.stage.height() });\n return {\n x: Math.min(tl.x, br.x),\n y: Math.min(tl.y, br.y),\n width: Math.abs(br.x - tl.x),\n height: Math.abs(br.y - tl.y),\n };\n }\n\n /** Axis-aligned world bounds of all seats + section outlines (minimap F3 frame). */\n getWorldBounds(): { x: number; y: number; width: number; height: number } {\n let minX = Infinity;\n let minY = Infinity;\n let maxX = -Infinity;\n let maxY = -Infinity;\n const grow = (x: number, y: number): void => {\n if (x < minX) minX = x;\n if (y < minY) minY = y;\n if (x > maxX) maxX = x;\n if (y > maxY) maxY = y;\n };\n for (const s of this.seats) grow(s.x, s.y);\n for (const sec of this.sections) for (const p of sec.outline) grow(p.x, p.y);\n if (!Number.isFinite(minX)) return { x: 0, y: 0, width: 1, height: 1 };\n return { x: minX, y: minY, width: Math.max(1, maxX - minX), height: Math.max(1, maxY - minY) };\n }\n\n /** Legend hover: highlight one category (dim the rest), or null to clear. */\n setCategoryHighlight(key: string | null): void {\n if (this.categoryHighlight === key) return;\n this.categoryHighlight = key;\n for (const seat of this.seats) {\n const c = this.circleById.get(seat.id);\n if (c) this.paintSeat(c, seat.id);\n }\n if (this.cached) {\n this.seatLayer.clearCache();\n this.cacheSeatLayer();\n } else {\n this.seatLayer.batchDraw();\n }\n }\n\n private renderBackground(doc: ChartDoc): void {\n if (doc.backgroundImage) this.renderBackgroundImage(doc.backgroundImage);\n // Decor graphics (ice rink, court art) draw first so they sit UNDER the\n // section outlines and — being on bgLayer, below seatLayer entirely — under\n // every seat. listening(false) keeps them out of the hit graph.\n for (const obj of doc.objects) if (obj.type === 'decorImage') this.renderDecorImage(obj);\n // Sections sit under all other décor so their outlines never occlude seats.\n // NOTE(phase-2): event-level section open/closed/hidden state will gate this\n // draw + the seat membership below — hide/dim a section by id/zone here.\n for (const obj of doc.objects) if (obj.type === 'section') this.renderSection(obj);\n // Zone labels sit above section blocks (drawn after) — the farthest rung.\n this.renderZones(doc);\n for (const obj of doc.objects) {\n if (obj.type === 'shape') {\n this.renderShape(obj);\n } else if (obj.type === 'gaArea') {\n this.renderGA(obj);\n } else if (obj.type === 'table') {\n this.renderTable(obj);\n } else if (obj.type === 'text') {\n this.renderText(obj);\n }\n }\n // Focal-point crosshair marker.\n const f = doc.focalPoint;\n if (f) {\n const size = 14;\n const cross = new Group({ listening: false });\n cross.add(\n new Line({ points: [f.x - size, f.y, f.x + size, f.y], stroke: '#4b5563', strokeWidth: 1.5 }),\n new Line({ points: [f.x, f.y - size, f.x, f.y + size], stroke: '#4b5563', strokeWidth: 1.5 }),\n new Circle({ x: f.x, y: f.y, radius: 3, fill: '#4b5563' }),\n );\n this.bgLayer.add(cross);\n }\n }\n\n /** Organizer floor-plan photo, dimmed, at the very bottom of the bg layer. */\n private renderBackgroundImage(bg: NonNullable<ChartDoc['backgroundImage']>): void {\n const img = new window.Image();\n img.onload = () => {\n const natW = img.naturalWidth || 4;\n const natH = img.naturalHeight || 3;\n const w = bg.width;\n const h = w * (natH / natW);\n const node = new KImage({\n image: img,\n x: bg.center.x - w / 2,\n y: bg.center.y - h / 2,\n width: w,\n height: h,\n opacity: bg.opacity,\n listening: false,\n });\n this.bgLayer.add(node);\n node.moveToBottom();\n this.bgLayer.batchDraw();\n };\n img.src = bg.url;\n }\n\n /**\n * A decor graphic (rink / court / stage art). The KImage node is added to the\n * bgLayer synchronously so it keeps its z-slot beneath the sections drawn right\n * after; the bitmap is decoded async and pasted in on load. A single node = a\n * single drawImage per frame, and it rides the same layer cache — effectively\n * zero per-frame cost. Never listens, so it can't intercept a seat click.\n */\n private renderDecorImage(obj: Extract<ChartDoc['objects'][number], { type: 'decorImage' }>): void {\n // Pass the (not-yet-loaded) Image element as the node's image: Konva draws\n // nothing until it decodes, then onload triggers a repaint. Keeps the node's\n // z-slot fixed beneath the sections drawn immediately after.\n const img = new window.Image();\n const node = new KImage({\n image: img,\n x: obj.x + obj.width / 2,\n y: obj.y + obj.height / 2,\n offsetX: obj.width / 2,\n offsetY: obj.height / 2,\n width: obj.width,\n height: obj.height,\n rotation: obj.rotation ?? 0,\n opacity: clamp(obj.opacity ?? 1, 0, 1),\n listening: false,\n perfectDrawEnabled: false,\n });\n this.bgLayer.add(node);\n img.onload = () => {\n if (!node.getLayer()) return; // chart swapped out before the image loaded\n this.bgLayer.batchDraw();\n };\n img.src = obj.href;\n }\n\n private renderTable(obj: Extract<ChartDoc['objects'][number], { type: 'table' }>): void {\n if (obj.shape === 'round') {\n this.bgLayer.add(\n new Circle({\n x: obj.center.x,\n y: obj.center.y,\n radius: obj.radius ?? 40,\n fill: '#232c40',\n stroke: '#2a3348',\n strokeWidth: 1.5,\n listening: false,\n }),\n );\n } else {\n const w = obj.width ?? 80;\n const h = obj.height ?? 50;\n this.bgLayer.add(\n new Rect({\n x: obj.center.x,\n y: obj.center.y,\n width: w,\n height: h,\n offsetX: w / 2,\n offsetY: h / 2,\n rotation: obj.rotation,\n fill: '#232c40',\n stroke: '#2a3348',\n strokeWidth: 1.5,\n cornerRadius: 4,\n listening: false,\n }),\n );\n }\n this.addCentredLabel(this.bgLayer, obj.label, obj.center.x, obj.center.y, '#cbd5e1', 12, true);\n }\n\n private renderText(obj: Extract<ChartDoc['objects'][number], { type: 'text' }>): void {\n this.bgLayer.add(\n new Text({\n x: obj.position.x,\n y: obj.position.y,\n text: obj.text,\n fontSize: obj.fontSize,\n rotation: obj.rotation,\n fill: obj.color ?? this.theme.textColor ?? DEF_TEXT,\n fontFamily: this.labelFont(),\n listening: false,\n perfectDrawEnabled: false,\n }),\n );\n }\n\n private renderShape(obj: Extract<ChartDoc['objects'][number], { type: 'shape' }>): void {\n const fill = obj.fill ?? this.theme.decorFill ?? DEF_DECOR_FILL;\n const isStage = obj.role === 'stage';\n const isDecor = !!obj.role && !isStage;\n // Stage: darker at the back (min-y), brighter toward the audience edge (max-y).\n const stroke = isStage ? lighten(fill, 0.28) : undefined;\n let cx = 0;\n let cy = 0;\n if (obj.kind === 'rect' && obj.x != null && obj.y != null && obj.width != null && obj.height != null) {\n const grad = isStage\n ? {\n fillLinearGradientStartPoint: { x: 0, y: 0 },\n fillLinearGradientEndPoint: { x: 0, y: obj.height },\n fillLinearGradientColorStops: [0, darken(fill, 0.3), 1, lighten(fill, 0.12)],\n }\n : { fill };\n cx = obj.x + obj.width / 2;\n cy = obj.y + obj.height / 2;\n // Rotate about center: pivot at (cx,cy) via offset; local coords (and the\n // gradient) are unchanged, so the fill spans the box regardless of angle.\n this.bgLayer.add(\n new Rect({\n x: cx,\n y: cy,\n offsetX: obj.width / 2,\n offsetY: obj.height / 2,\n rotation: obj.rotation ?? 0,\n width: obj.width,\n height: obj.height,\n ...grad,\n stroke,\n strokeWidth: isStage ? 1 : 0,\n cornerRadius: 4,\n listening: false,\n }),\n );\n } else if (obj.kind === 'ellipse' && obj.x != null && obj.y != null && obj.width != null && obj.height != null) {\n cx = obj.x + obj.width / 2;\n cy = obj.y + obj.height / 2;\n const grad = isStage\n ? {\n fillLinearGradientStartPoint: { x: 0, y: -obj.height / 2 },\n fillLinearGradientEndPoint: { x: 0, y: obj.height / 2 },\n fillLinearGradientColorStops: [0, darken(fill, 0.3), 1, lighten(fill, 0.12)],\n }\n : { fill };\n this.bgLayer.add(\n new Ellipse({ x: cx, y: cy, rotation: obj.rotation ?? 0, radiusX: obj.width / 2, radiusY: obj.height / 2, ...grad, stroke, strokeWidth: isStage ? 1 : 0, listening: false }),\n );\n } else if (obj.kind === 'polygon' && obj.points && obj.points.length) {\n const pts = obj.points.flatMap((p) => [p.x, p.y]);\n const b = polyBounds(obj.points);\n cx = obj.points.reduce((a, p) => a + p.x, 0) / obj.points.length;\n cy = obj.points.reduce((a, p) => a + p.y, 0) / obj.points.length;\n const grad = isStage\n ? {\n // Line points are absolute chart coords; the gradient endpoints share\n // that space and rotate with the node (pivot at the centroid below).\n fillLinearGradientStartPoint: { x: 0, y: b.y },\n fillLinearGradientEndPoint: { x: 0, y: b.y + b.height },\n fillLinearGradientColorStops: [0, darken(fill, 0.3), 1, lighten(fill, 0.12)],\n }\n : { fill };\n // Rotate about the centroid: position=offset=centroid leaves the polygon\n // in place at rotation 0 and pivots there for any angle.\n this.bgLayer.add(\n new Line({ points: pts, closed: true, x: cx, y: cy, offsetX: cx, offsetY: cy, rotation: obj.rotation ?? 0, ...grad, stroke, strokeWidth: isStage ? 1 : 0, listening: false }),\n );\n }\n if (obj.label) {\n if (isStage) this.addStageLabel(cx, cy, obj.label);\n else if (isDecor) this.addCentredLabel(this.bgLayer, obj.label, cx, cy, '#9aa3b5', 12, false);\n else this.addCentredLabel(this.bgLayer, obj.label, cx, cy, '#cbd5e1', 16, true);\n }\n }\n\n /** Prominent stage caption: uppercase, letter-spaced, larger, softly dimmed. */\n private addStageLabel(x: number, y: number, text: string): void {\n const t = new Text({\n x,\n y,\n text: text.toUpperCase(),\n fontSize: 22,\n fontStyle: '700',\n letterSpacing: 4,\n fontFamily: this.labelFont(),\n fill: rgba('#e6e9f0', 0.62),\n listening: false,\n perfectDrawEnabled: false,\n });\n t.offsetX(t.width() / 2);\n t.offsetY(t.height() / 2);\n this.bgLayer.add(t);\n }\n\n private renderGA(obj: Extract<ChartDoc['objects'][number], { type: 'gaArea' }>): void {\n const color = this.catColor.get(obj.categoryKey) ?? '#6e7bff';\n const pts = obj.points.flatMap((p) => [p.x, p.y]);\n const poly = new Line({\n points: pts,\n closed: true,\n fill: color,\n opacity: 0.22,\n stroke: color,\n strokeWidth: 1.5,\n });\n poly.setAttr('gaId', obj.id);\n poly.on('click tap', () => this.opts.onGAClick?.(obj.id));\n poly.on('mouseenter', () => {\n this.container.style.cursor = 'pointer';\n });\n poly.on('mouseleave', () => {\n this.container.style.cursor = 'default';\n });\n this.bgLayer.add(poly);\n\n const cx = obj.points.reduce((a, p) => a + p.x, 0) / obj.points.length;\n const cy = obj.points.reduce((a, p) => a + p.y, 0) / obj.points.length;\n this.addCentredLabel(this.bgLayer, obj.label, cx, cy - 8, '#e6e9f0', 15, false);\n this.addCentredLabel(this.bgLayer, `cap ${obj.capacity}`, cx, cy + 10, '#8b93a7', 11, false);\n }\n\n /**\n * A section renders in three coordinated layers driven by the LOD melt:\n * • a faint outline (the existing near-zoom look, untouched),\n * • a solid category-mix block that fades in at the block rung, and\n * • a name + \"N LEFT\" sublabel.\n * Membership (which seats live inside the outline) + the mix fill + the live\n * availability count are precomputed here (once), not per frame.\n */\n private renderSection(obj: SectionObject): void {\n const pts = obj.outline.flatMap((p) => [p.x, p.y]);\n const centroid = {\n x: obj.outline.reduce((a, p) => a + p.x, 0) / obj.outline.length,\n y: obj.outline.reduce((a, p) => a + p.y, 0) / obj.outline.length,\n };\n\n // Membership: seats inside the outline, first section (doc order) wins.\n const memberIds: string[] = [];\n const catCounts = new Map<string, number>();\n let free = 0;\n for (const seat of this.seats) {\n if (this.seatSection.has(seat.id)) continue;\n if (!pointInPolygon(seat, obj.outline)) continue;\n memberIds.push(seat.id);\n catCounts.set(seat.categoryKey, (catCounts.get(seat.categoryKey) ?? 0) + 1);\n if ((this.statusById.get(seat.id) ?? 'free') === 'free') free++;\n }\n\n // Category-mix fill: explicit override wins, else blend member colours by count.\n const baseFill =\n obj.color ??\n mixColors(\n [...catCounts].map(([key, w]) => ({ hex: this.catColor.get(key) ?? '#6e7bff', w })),\n '#3a4358',\n );\n\n // Elevation: elevated sections lift as one tier in the iso view, so their bg\n // nodes + member seats go into lift groups (positioned in applyElevation).\n // Side faces (a zone-coloured quad per outline edge) extrude only as isoT rises.\n const elevation = Math.max(0, Math.round(obj.elevation ?? 0));\n let liftGroupBg: Group | null = null;\n let liftGroupSeat: Group | null = null;\n const sideFaces: Line[] = [];\n if (elevation > 0) {\n const faceFill = darken(this.zoneColor.get(obj.zone ?? '') ?? baseFill, 0.42);\n for (let i = 0; i < obj.outline.length; i++) {\n const face = new Line({\n points: [],\n closed: true,\n fill: faceFill,\n stroke: rgba('#000000', 0.25),\n strokeWidth: 1,\n opacity: 0,\n listening: false,\n perfectDrawEnabled: false,\n });\n sideFaces.push(face);\n this.bgLayer.add(face); // behind the group added next → behind the fill\n }\n liftGroupBg = new Group({ listening: false });\n this.bgLayer.add(liftGroupBg);\n liftGroupSeat = new Group({ listening: false });\n this.seatLayer.add(liftGroupSeat);\n }\n const bgTarget: Group | Layer = liftGroupBg ?? this.bgLayer;\n\n // Zone-coloured outline under the seats — matches the crisp section blocks\n // the designer draws, so the near-zoom map reads as defined zones too.\n const outlineTint = obj.color ?? this.zoneColor.get(obj.zone ?? '') ?? '#3a4358';\n const outlinePoly = new Line({\n points: pts,\n closed: true,\n stroke: rgba(outlineTint, 0.5),\n strokeWidth: 1.75,\n fill: rgba(outlineTint, 0.08),\n lineJoin: 'round',\n listening: false,\n perfectDrawEnabled: false,\n });\n bgTarget.add(outlinePoly);\n\n // Solid block fill — melts in at the block rung (opacity driven by the LOD).\n const blockPoly = new Line({\n points: pts,\n closed: true,\n fill: baseFill,\n stroke: rgba('#ffffff', 0.12),\n strokeWidth: 1,\n opacity: 0,\n listening: false,\n perfectDrawEnabled: false,\n });\n bgTarget.add(blockPoly);\n\n // Faint per-row hint lines (the seats.io \"block-with-rows\" look): a polyline\n // through each member row's seats, fading in with the block. Lets a section\n // read as SEATING — not a flat colour — at the overview zoom, seats hidden.\n const rowSeats = new Map<string, Array<{ i: number; x: number; y: number }>>();\n for (const id of memberIds) {\n const s = this.seatById.get(id);\n if (!s) continue;\n const i = Number(id.slice(id.lastIndexOf(':') + 1)) || 0;\n (rowSeats.get(s.rowId) ?? rowSeats.set(s.rowId, []).get(s.rowId)!).push({ i, x: s.x, y: s.y });\n }\n const rowLines: Line[] = [];\n for (const arr of rowSeats.values()) {\n if (arr.length < 2) continue;\n arr.sort((a, b) => a.i - b.i);\n const line = new Line({\n points: arr.flatMap((p) => [p.x, p.y]),\n stroke: rgba('#ffffff', 0.34),\n strokeWidth: SEAT_RADIUS * 0.55,\n lineCap: 'round',\n lineJoin: 'round',\n opacity: 0,\n listening: false,\n perfectDrawEnabled: false,\n });\n rowLines.push(line);\n bgTarget.add(line);\n }\n\n const nameLabel = new Text({\n x: centroid.x,\n y: centroid.y,\n text: obj.label,\n fontSize: 22,\n fontStyle: '700',\n fontFamily: this.labelFont(),\n fill: '#8b93a7',\n // Dark halo so the label reads over the seat dots at any zoom.\n shadowColor: '#05070c',\n shadowBlur: 6,\n shadowOpacity: 0.9,\n shadowForStrokeEnabled: false,\n listening: false,\n perfectDrawEnabled: false,\n });\n nameLabel.offsetX(nameLabel.width() / 2);\n nameLabel.offsetY(nameLabel.height() / 2);\n bgTarget.add(nameLabel);\n\n const subLabel = new Text({\n x: centroid.x,\n y: centroid.y,\n text: t('map.seatsLeft', { count: free }),\n fontSize: 12,\n fontStyle: '700',\n fontFamily: 'JetBrains Mono, ui-monospace, monospace',\n fill: '#f4f6fb',\n shadowColor: '#05070c',\n shadowBlur: 5,\n shadowOpacity: 0.9,\n shadowForStrokeEnabled: false,\n opacity: 0,\n listening: false,\n perfectDrawEnabled: false,\n });\n subLabel.offsetX(subLabel.width() / 2);\n bgTarget.add(subLabel);\n\n const sec: SectionRender = {\n id: obj.id,\n label: obj.label,\n outline: obj.outline,\n centroid,\n zone: obj.zone,\n memberIds,\n total: memberIds.length,\n free,\n baseFill,\n outlineTint,\n outlinePoly,\n blockPoly,\n rowLines,\n nameLabel,\n subLabel,\n elevation,\n liftGroupBg,\n liftGroupSeat,\n sideFaces,\n };\n for (const id of memberIds) this.seatSection.set(id, sec);\n this.refreshSectionFill(sec);\n this.refreshSectionHeat(sec);\n this.sections.push(sec);\n }\n\n private refreshSectionHeat(sec: SectionRender): void {\n const raw = this.sectionHeat.get(sec.id) ?? (sec.zone ? this.sectionHeat.get(sec.zone) : undefined);\n if (raw == null || raw <= 0) {\n sec.outlinePoly.stroke(rgba(sec.outlineTint, 0.5));\n sec.outlinePoly.fill(rgba(sec.outlineTint, 0.08));\n sec.outlinePoly.strokeWidth(1.75);\n sec.outlinePoly.shadowOpacity(0);\n return;\n }\n const color = lerpColor('#f4b740', '#ef4444', raw);\n sec.outlinePoly.stroke(rgba(color, 0.72 + raw * 0.25));\n sec.outlinePoly.fill(rgba(color, 0.08 + raw * 0.13));\n sec.outlinePoly.strokeWidth(2 + raw * 3.5);\n sec.outlinePoly.shadowColor(color);\n sec.outlinePoly.shadowBlur(4 + raw * 12);\n sec.outlinePoly.shadowOpacity(0.25 + raw * 0.45);\n }\n\n /** Recompute a section's availability-tinted fill + \"N LEFT\" (cheap; on status change). */\n private refreshSectionFill(sec: SectionRender): void {\n sec.blockPoly.fill(this.sectionBlockFill(sec));\n sec.subLabel.text(t('map.seatsLeft', { count: sec.free }));\n sec.subLabel.offsetX(sec.subLabel.width() / 2);\n }\n\n /** True when a section/zone is currently in the `closed` event-state. */\n private isSectionClosed(sec: SectionRender): boolean {\n return this.closedSections.has(sec.id) || (sec.zone != null && this.closedSections.has(sec.zone));\n }\n\n /**\n * The block-fill colour for a section: flat desaturated grey when `closed`,\n * else the availability-darkened category mix; then desaturated toward neutral\n * when another section holds focus (AXS dim treatment).\n */\n private sectionBlockFill(sec: SectionRender): string {\n let fill: string;\n if (this.isSectionClosed(sec)) {\n fill = CLOSED_SECTION_FILL;\n } else {\n const sold = sec.total > 0 ? (sec.total - sec.free) / sec.total : 0;\n fill = darken(sec.baseFill, sold * SOLD_DARKEN);\n }\n if (this.focusedSectionId && sec.id !== this.focusedSectionId && sec.zone !== this.focusedSectionId) {\n fill = lerpColor(fill, FOCUS_NEUTRAL, FOCUS_DESATURATE);\n }\n return fill;\n }\n\n /**\n * Zone rung: one giant screen-constant label per zone (+ optional \"FROM $n\"),\n * shown at the farthest zoom in place of per-section detail. Skipped entirely\n * when the doc declares no zones — sections then stay the far rung (graceful).\n */\n private renderZones(doc: ChartDoc): void {\n if (!doc.zones?.length || !this.sections.length) return;\n const byZone = new Map<string, SectionRender[]>();\n for (const sec of this.sections) {\n if (!sec.zone) continue;\n (byZone.get(sec.zone) ?? byZone.set(sec.zone, []).get(sec.zone)!).push(sec);\n }\n for (const z of doc.zones) {\n const members = byZone.get(z.id);\n if (!members || !members.length) continue;\n // Anchor at the TOPMOST member (min y), not the mean centroid: for a\n // symmetric bowl (a zone = a full ring around the stage) the mean lands on\n // the origin and every zone label stacks on the stage. The topmost member\n // gives a distinct point per ring (labels stack up the vertical axis).\n let anchor = members[0];\n for (const s of members) if (s.centroid.y < anchor.centroid.y) anchor = s;\n const cx = anchor.centroid.x;\n const cy = anchor.centroid.y;\n\n // \"FROM $n\" = cheapest category price found among this zone's member seats.\n let minPrice = Infinity;\n for (const sec of members) {\n for (const id of sec.memberIds) {\n const seat = this.seatById.get(id);\n const p = seat && this.catPrice.get(seat.categoryKey);\n if (typeof p === 'number' && p < minPrice) minPrice = p;\n }\n }\n\n const label = new Text({\n x: cx,\n y: cy,\n text: z.label.toUpperCase(),\n fontSize: 34,\n fontStyle: '800',\n letterSpacing: 2,\n fontFamily: this.labelFont(),\n fill: z.color ?? '#f2f4f8',\n shadowColor: '#05070c',\n shadowBlur: 10,\n shadowOpacity: 0.95,\n shadowForStrokeEnabled: false,\n opacity: 0,\n listening: false,\n perfectDrawEnabled: false,\n });\n label.offsetX(label.width() / 2);\n label.offsetY(label.height() / 2);\n this.bgLayer.add(label);\n\n let sub: Text | null = null;\n if (isFinite(minPrice)) {\n sub = new Text({\n x: cx,\n y: cy,\n text: t('map.fromPrice', { price: formatMoney(minPrice, this.currency) }),\n fontSize: 14,\n fontStyle: '600',\n fontFamily: 'JetBrains Mono, ui-monospace, monospace',\n fill: rgba('#e6e9f0', 0.75),\n opacity: 0,\n listening: false,\n perfectDrawEnabled: false,\n });\n sub.offsetX(sub.width() / 2);\n this.bgLayer.add(sub);\n }\n this.zones.push({ id: z.id, label, sub });\n }\n }\n\n /**\n * THE MELT — a continuous, scale-driven cross-fade across the three rungs:\n * seats ⇄ section blocks ⇄ zone blocks.\n * `blockT` ramps 0→1 as scale falls through [SECTION_PROMINENT, CACHE_THRESHOLD]\n * so the solid fill is fully present exactly as seats become the cached bitmap\n * and fade out; `zoneT` ramps 0→1 across [ZONE_PROMINENT, SECTION_PROMINENT] so\n * per-section detail hands off to giant zone labels. Reduced-motion hard-swaps.\n * Section/zone labels are scale-compensated to hold a roughly constant screen size.\n */\n private applySectionLod(scale: number): void {\n let blockT: number;\n let zoneT: number;\n if (this.reducedMotion) {\n blockT = scale <= SECTION_PROMINENT_SCALE ? 1 : 0;\n zoneT = scale <= ZONE_PROMINENT_SCALE ? 1 : 0;\n } else {\n blockT = clamp((BLOCK_MELT_TOP - scale) / (BLOCK_MELT_TOP - SECTION_PROMINENT_SCALE), 0, 1);\n zoneT = clamp((SECTION_PROMINENT_SCALE - scale) / (SECTION_PROMINENT_SCALE - ZONE_PROMINENT_SCALE), 0, 1);\n }\n // No zones ⇒ skip the zone rung: sections stay the far rung (graceful).\n if (!this.zones.length) zoneT = 0;\n\n // Seats melt out as the block fill melts in (coordinated with the bitmap swap).\n this.seatLayer.opacity(1 - blockT);\n\n // Labels are drawn UPRIGHT (the iso squash is cancelled per-text), so their\n // on-screen size follows the raw stage scale, not the squashed effective one.\n const sx = this.stage.scaleX();\n // Scale-compensate label sizes only when the scale meaningfully changed.\n const rescale = this.lodScale === 0 || Math.abs(scale - this.lodScale) / (this.lodScale || 1) > 0.02;\n if (rescale) this.lodScale = scale;\n\n const focus = this.focusedSectionId;\n for (const sec of this.sections) {\n // AXS focus: non-focused sections dim to ~16%; the focused block stays full.\n const dim = focus && sec.id !== focus && sec.zone !== focus ? FOCUS_DIM_OPACITY : 1;\n sec.blockPoly.opacity(BLOCK_FILL_ALPHA * blockT * dim);\n for (const line of sec.rowLines) line.opacity(blockT * (1 - zoneT) * dim);\n // Name: faint→bright with blockT, then fades out as zones take over.\n sec.nameLabel.fill(lerpColor('#aab3c5', '#ffffff', blockT));\n sec.nameLabel.opacity((1 - zoneT) * dim);\n sec.subLabel.opacity(blockT * (1 - zoneT) * dim);\n if (rescale) {\n this.sizeLabel(sec.nameLabel, SECTION_LABEL_PX / sx, sec.centroid.y - SECTION_SUB_PX / sx);\n this.sizeLabel(sec.subLabel, SECTION_SUB_PX / sx, sec.centroid.y + SECTION_LABEL_PX / sx);\n }\n }\n\n // Fade the big zone labels out as the view tilts into 3D — the raised tiers\n // read clearly on their own, and the overlaid zone text just clutters them.\n const zoneOpacity = zoneT * (1 - this.isoT);\n for (const zone of this.zones) {\n zone.label.opacity(zoneOpacity);\n if (zone.sub) zone.sub.opacity(zoneOpacity);\n if (rescale) {\n const cy = zone.label.y();\n this.sizeLabel(zone.label, ZONE_LABEL_PX / sx, cy);\n if (zone.sub) this.sizeLabel(zone.sub, ZONE_SUB_PX / sx, cy + ZONE_LABEL_PX / sx);\n }\n }\n // Greedy de-collision of the visible label tiers (small canvases stack\n // \"UPPER BOWL\"/\"LOWER BOWL\"/FROM-$ on top of each other otherwise).\n this.decollideRungLabels(sx);\n this.bgLayer.batchDraw();\n }\n\n /**\n * Greedy label de-collision for the zone/section rungs (same approach as the\n * designer's cullRowLabels): price/\"N LEFT\" sublabels are lowest priority and\n * drop first; name labels keep top-to-bottom, left-to-right; anything whose\n * on-screen box (+4px gap) overlaps an already-kept box hides. Recomputed on\n * every LOD pass so hidden labels reappear as zoom spreads them apart.\n * Culling multiplies the opacity applySectionLod just assigned (never raises).\n */\n private decollideRungLabels(sx: number): void {\n const GAP = 4;\n interface Cand { node: Text; tier: number; owner?: Text; box: { x: number; y: number; w: number; h: number } }\n const cands: Cand[] = [];\n const boxOf = (t: Text): { x: number; y: number; w: number; h: number } => {\n // Labels are centred (offset = w/2,h/2); world size × stage scale = screen px.\n const p = this.worldToScreen({ x: t.x(), y: t.y() });\n const w = t.width() * sx;\n const h = t.height() * sx;\n return { x: p.x - w / 2, y: p.y - h / 2, w, h };\n };\n // Tier order = drop priority (higher tier drops first): zone names (0) win\n // over section names (1); price/\"N LEFT\" sublabels (2/3) drop before names.\n // A sublabel records its `owner` name: if the name lost, the sub hides too\n // (never a floating price tag without the zone/section it belongs to).\n for (const zone of this.zones) {\n if (zone.label.opacity() > 0.05) cands.push({ node: zone.label, tier: 0, box: boxOf(zone.label) });\n if (zone.sub && zone.sub.opacity() > 0.05) cands.push({ node: zone.sub, tier: 2, owner: zone.label, box: boxOf(zone.sub) });\n }\n for (const sec of this.sections) {\n if (sec.nameLabel.opacity() > 0.05) cands.push({ node: sec.nameLabel, tier: 1, box: boxOf(sec.nameLabel) });\n if (sec.subLabel.opacity() > 0.05) cands.push({ node: sec.subLabel, tier: 3, owner: sec.nameLabel, box: boxOf(sec.subLabel) });\n }\n if (cands.length < 2) return;\n cands.sort((a, b) => a.tier - b.tier || a.box.y - b.box.y || a.box.x - b.box.x);\n const kept: Cand['box'][] = [];\n const culled = new Set<Text>();\n const collides = (b: Cand['box']): boolean =>\n kept.some((k) =>\n b.x < k.x + k.w + GAP && k.x < b.x + b.w + GAP &&\n b.y < k.y + k.h + GAP && k.y < b.y + b.h + GAP,\n );\n for (const c of cands) {\n if ((c.owner && culled.has(c.owner)) || collides(c.box)) {\n c.node.opacity(0);\n culled.add(c.node);\n } else {\n kept.push(c.box);\n }\n }\n }\n\n /** Set a centred label's world fontSize (for a target screen px) and re-anchor it. */\n private sizeLabel(t: Text, fontSize: number, y: number): void {\n t.fontSize(Math.max(1, fontSize));\n t.offsetX(t.width() / 2);\n t.offsetY(t.height() / 2);\n t.y(y);\n }\n\n /**\n * Map a container-relative screen point back to world coords. Inverts the\n * stage (scale/pos) and, in iso view, the iso affine — so screen-space taps\n * test against the flat world outlines/geometry. Identity-equivalent at isoT=0.\n */\n private screenToWorld(clientPoint: { x: number; y: number }): { x: number; y: number } {\n const s = this.stage.scaleX();\n const iso = { x: (clientPoint.x - this.stage.x()) / s, y: (clientPoint.y - this.stage.y()) / s };\n return this.isoT === 0 ? iso : this.isoInverse(iso);\n }\n\n /** Section id under a container-relative screen point, or null (Slice 5 tap-to-zoom). */\n sectionAt(clientPoint: { x: number; y: number }): string | null {\n if (!this.sections.length) return null;\n const world = this.screenToWorld(clientPoint);\n const hit = this.sections.find((sec) => pointInPolygon(world, sec.outline));\n return hit ? hit.id : null;\n }\n\n /** Seat ids belonging to a section (Slice 5 section-summary card). */\n sectionMembers(id: string): string[] {\n return this.sections.find((s) => s.id === id)?.memberIds.slice() ?? [];\n }\n\n private addCentredLabel(\n layer: Layer,\n text: string,\n x: number,\n y: number,\n fill: string,\n fontSize: number,\n bold: boolean,\n ): void {\n const t = new Text({\n x,\n y,\n text,\n fontSize,\n fontStyle: bold ? '700' : '500',\n fontFamily: this.labelFont(),\n fill,\n listening: false,\n perfectDrawEnabled: false,\n });\n t.offsetX(t.width() / 2);\n t.offsetY(t.height() / 2);\n layer.add(t);\n }\n\n // ---- selection ------------------------------------------------------------\n\n private isSelectable(id: string): boolean {\n // A closed section's seats are never pickable, whatever their raw status.\n if (this.seatInClosedSection(id)) return false;\n const statuses = this.opts.selectableStatuses ?? ['free'];\n return statuses.includes(this.statusById.get(id) ?? 'free');\n }\n\n private toggleSeat(id: string): void {\n if (this.selection.has(id)) {\n this.setSelected(id, false);\n const seat = this.seatById.get(id);\n if (seat) this.opts.onDeselect?.(seat);\n } else {\n if (!this.isSelectable(id)) return;\n if (this.selection.size >= this.opts.maxSelection) return; // ignore beyond cap\n this.setSelected(id, true);\n const seat = this.seatById.get(id);\n if (seat) this.opts.onSelect?.(seat);\n }\n this.overlayLayer.batchDraw();\n }\n\n /**\n * Selection/hover ring color. An explicit theme.selectionColor always wins;\n * otherwise auto-contrast against the effective canvas background — the\n * designer renders on dark (white ring reads), but light-themed hosts (e.g.\n * the DesiPass buyer picker on cream) made the white ring invisible and\n * selected seats looked *disabled*. theme.background is checked first, then\n * the container's computed CSS background (walking up past transparent\n * ancestors). Unknown/unparseable backgrounds keep the dark default.\n */\n private resolveSelectionColor(): string {\n if (this.theme.selectionColor) return this.theme.selectionColor;\n let bg = this.theme.background ?? '';\n if (!bg && typeof getComputedStyle === 'function') {\n let el: HTMLElement | null = this.container;\n while (el) {\n const c = getComputedStyle(el).backgroundColor;\n if (c && c !== 'transparent' && !/^rgba\\(\\s*\\d+\\s*,\\s*\\d+\\s*,\\s*\\d+\\s*,\\s*0\\s*\\)$/.test(c)) {\n bg = c;\n break;\n }\n el = el.parentElement;\n }\n }\n return isLightColor(bg) ? DEF_SELECTION_ON_LIGHT : DEF_SELECTION;\n }\n\n private setSelected(id: string, on: boolean, silent = false): void {\n const c = this.circleById.get(id);\n if (on) {\n this.selection.add(id);\n } else {\n if (this.selectionFocusId === id) this.setSelectionFocus(null);\n this.selection.delete(id);\n }\n this.syncSelectionMarker(id);\n if (c) {\n this.paintSeat(c, id);\n if (!silent && !this.cached) this.seatLayer.batchDraw();\n }\n }\n\n /** Rebuild one marker after selected/held/candidate state changes. */\n private syncSelectionMarker(id: string): void {\n this.selectionMarkers.get(id)?.destroy();\n this.selectionMarkers.delete(id);\n if (!this.selection.has(id) && !this.ownedHold.has(id)) return;\n\n const seat = this.seatById.get(id);\n if (!seat) return;\n const candidate = this.selectionFocusId === id;\n const dims = this.boothDims.get(seat.rowId);\n const marker = new Group({\n x: seat.x,\n y: seat.y,\n rotation: dims?.rotation ?? 0,\n listening: false,\n perfectDrawEnabled: false,\n opacity: this.selectionFocusId && !candidate ? 0.2 : 1,\n });\n const common = {\n stroke: this.effSelection,\n listening: false,\n perfectDrawEnabled: false,\n shadowForStrokeEnabled: false,\n };\n\n if (dims) {\n marker.add(new Rect({\n ...common,\n width: dims.width,\n height: dims.height,\n offsetX: dims.width / 2,\n offsetY: dims.height / 2,\n cornerRadius: 4,\n strokeWidth: candidate ? 4 : 3,\n }));\n if (candidate) {\n marker.add(new Rect({\n ...common,\n width: dims.width + 10,\n height: dims.height + 10,\n offsetX: (dims.width + 10) / 2,\n offsetY: (dims.height + 10) / 2,\n cornerRadius: 7,\n strokeWidth: 2,\n opacity: 0.55,\n }));\n } else {\n const badgeX = Math.max(0, dims.width / 2 - 14);\n const badgeY = -Math.max(0, dims.height / 2 - 14);\n marker.add(new Circle({ x: badgeX, y: badgeY, radius: 10, fill: this.effSelection, listening: false }));\n marker.add(new Line({\n x: badgeX,\n y: badgeY,\n points: [-4.5, 0, -1, 3.5, 5.5, -4.5],\n stroke: isLightColor(this.effSelection) ? '#0b1220' : '#ffffff',\n strokeWidth: 2.4,\n lineCap: 'round',\n lineJoin: 'round',\n listening: false,\n }));\n }\n } else {\n marker.add(new Circle({ ...common, radius: this.seatR + (candidate ? 4.5 : 2.5), strokeWidth: candidate ? 3.5 : 2.5 }));\n if (candidate) {\n marker.add(new Circle({\n ...common,\n radius: this.seatR + 8,\n strokeWidth: 2,\n opacity: 0.55,\n }));\n } else {\n marker.add(new Line({\n points: [-this.seatR * 0.52, 0, -this.seatR * 0.12, this.seatR * 0.4, this.seatR * 0.6, -this.seatR * 0.46],\n stroke: '#ffffff',\n strokeWidth: Math.max(2.6, this.seatR * 0.34),\n lineCap: 'round',\n lineJoin: 'round',\n shadowColor: '#0b1220',\n shadowBlur: 1.5,\n shadowOpacity: 0.55,\n listening: false,\n }));\n }\n }\n\n this.selectionMarkers.set(id, marker);\n this.overlayLayer.add(marker);\n }\n\n // ---- interaction ----------------------------------------------------------\n\n /**\n * The stage scale `focusRegion(id)` would settle at — i.e. the zoom that\n * frames this section in the current viewport. Used to decide whether\n * redirecting a seat tap to section-focus would actually zoom in FURTHER, or\n * whether the section already fills the viewport (small container) so the tap\n * must fall through and pick.\n */\n private sectionFrameScale(id: string): number {\n const sec = this.sections.find((s) => s.id === id);\n if (!sec) return this.stage.scaleX();\n const b = polyBounds(sec.outline);\n const w = this.stage.width();\n const h = this.stage.height();\n const { min, max } = this.zoomBounds();\n const margin = 1.12;\n if (b.width <= 0 || b.height <= 0) return this.stage.scaleX();\n const frameScale = Math.min(w / (b.width * margin), h / (b.height * margin));\n return clamp(Math.max(frameScale, SEAT_FOCUS_SCALE), min, max);\n }\n\n /**\n * Resolve a seat tap: honour the 3D deck-drill and the AXS seat-pick gate,\n * then toggle. The gate (§4) redirects small on-screen seats to section-focus\n * to avoid blind mis-picks at overview scales — but ONLY when focusing would\n * zoom the seat up to a safe size. If we're already focused on the section, or\n * the section already fills the viewport (a narrow — OR even a wide — container\n * frames a big section BELOW LABEL_SCALE), redirecting is a no-op that would\n * leave the seat permanently unpickable (§5 `picking-gate-unreachable`), so we\n * fall through and PICK. This is the invariant: seats are never unpickable.\n */\n private handleSeatTap(id: string): void {\n // In the 3D all-floors overview, tapping a seat enters its deck in 2D\n // rather than selecting (seat picking happens on the flat floor map).\n if (this.stacked && this.opts.onDeckTap) {\n const floorId = this.objectFloor.get(this.seatById.get(id)?.rowId ?? '');\n if (floorId) { this.opts.onDeckTap(floorId); return; }\n }\n if (this.effScale() < LABEL_SCALE && this.sections.length) {\n const sec = this.seatSection.get(id);\n if (sec) {\n const alreadyFocused = this.focusedSectionId === sec.id;\n // Would section-focus zoom us in meaningfully (>2%)? If not, the gate has\n // nowhere left to go — pick instead of deadlocking.\n const canZoomInFurther = this.sectionFrameScale(sec.id) > this.stage.scaleX() * 1.02;\n if (!alreadyFocused && canZoomInFurther) {\n if (this.opts.onSectionTap) this.opts.onSectionTap(sec.id);\n else this.focusSection(sec.id);\n return;\n }\n }\n }\n this.toggleSeat(id);\n }\n\n /**\n * Nearest SELECTABLE seat whose centre is within `slopPx` (screen space) of a\n * seat circle edge, or null. Enlarges the effective tap target for small seats\n * so a near-miss on mobile still lands on the intended seat, without ever\n * hijacking a clean tap on empty space beyond the slop.\n */\n private nearestSeatToScreen(screen: { x: number; y: number }, slopPx: number): string | null {\n const s = this.stage.scaleX() || 1;\n const reachWorld = this.seatR + slopPx / s; // circle radius + finger slack\n const world = this.screenToWorld(screen);\n let best: string | null = null;\n let bestD = reachWorld;\n for (const seat of this.seats) {\n if (!this.selection.has(seat.id) && !this.isSelectable(seat.id)) continue;\n const d = Math.hypot(seat.x - world.x, seat.y - world.y);\n if (d < bestD) {\n bestD = d;\n best = seat.id;\n }\n }\n return best;\n }\n\n private wireInteraction(): void {\n this.seatLayer.on('click tap', (e: KonvaEventObject<Event>) => {\n if (this.moved > PAN_START_SLOP_PX) return; // it was a pan/pinch, not a tap\n const id = seatIdOf(e.target);\n if (!id) return;\n this.handleSeatTap(id);\n });\n\n // Hover (mouse only) via delegated enter/leave on seat circles.\n this.seatLayer.on('mouseover', (e: KonvaEventObject<MouseEvent>) => {\n const id = seatIdOf(e.target);\n if (!id) return;\n const seat = this.seatById.get(id);\n if (!seat) return;\n this.hoverRing.position({ x: seat.x, y: seat.y });\n this.hoverRing.visible(true);\n this.overlayLayer.batchDraw();\n this.container.style.cursor = 'pointer';\n this.opts.onHover?.(seat);\n });\n this.seatLayer.on('mouseout', () => {\n this.hoverRing.visible(false);\n this.overlayLayer.batchDraw();\n this.container.style.cursor = 'default';\n this.opts.onHover?.(null);\n });\n\n this.stage.on('wheel', (e: KonvaEventObject<WheelEvent>) => {\n e.evt.preventDefault();\n // Position from the event itself — Konva's tracked pointer position is\n // unreliable when the last pointer event went elsewhere.\n const r = this.container.getBoundingClientRect();\n const pointer = { x: e.evt.clientX - r.left, y: e.evt.clientY - r.top };\n // Scale with the actual wheel delta so trackpad flings and fast wheels\n // zoom proportionally (a fixed step per event ignores delta magnitude).\n const factor = Math.exp(-e.evt.deltaY * 0.002);\n this.zoomAbout(this.stage.scaleX() * clamp(factor, 0.5, 2), pointer);\n });\n\n // Zoomed out, the seat layer is a non-listening cached bitmap and seats\n // are finger-width anyway — a tap zooms into that area instead of\n // attempting a 4px-precision selection (same behaviour as seats.io).\n this.stage.on('click tap', (e: KonvaEventObject<Event>) => {\n if (this.moved > PAN_START_SLOP_PX) return;\n const pointer = this.stage.getPointerPosition();\n if (!pointer) return;\n // Seats are LIVE (not a cached bitmap): the seatLayer handler above owns\n // direct seat hits. Here we only rescue near-misses — a finger landing just\n // off a small seat picks the nearest one (mobile hit target, §4 hit ≥ 24px).\n // A clean tap on empty space beyond the slop still does nothing.\n if (!this.cached) {\n if (seatIdOf(e.target)) return; // direct hit already handled\n const near = this.nearestSeatToScreen(pointer, SEAT_TAP_SLOP_PX);\n if (near) this.handleSeatTap(near);\n return;\n }\n // 3D all-floors overview: tapping a deck enters that floor in 2D. The iso\n // projection is a layer transform, so the flat screenToWorld hit-test below\n // won't work here — resolve the deck via the iso-aware nearest seat instead.\n if (this.stacked && this.opts.onDeckTap) {\n const floorId = this.deckFloorAt();\n if (floorId) { this.opts.onDeckTap(floorId); return; }\n }\n // A tap inside a section (seats aren't the active rung here — the layer is\n // cached) hands off to the host: fire onSectionTap so the picker can glide\n // in + show the section-summary card (Slice 5). With no handler wired we\n // keep the standalone behaviour of gliding to fit that section.\n if (this.sections.length) {\n const world = this.screenToWorld(pointer);\n const hit = this.sections.find((sn) => pointInPolygon(world, sn.outline));\n if (hit) {\n if (this.opts.onSectionTap) this.opts.onSectionTap(hit.id);\n else this.focusRegion(hit.id);\n return;\n }\n }\n const target = Math.max(SEAT_LEGIBLE_SCALE * 1.2, this.stage.scaleX() * 2.5);\n this.zoomAbout(target, pointer);\n });\n }\n\n /**\n * Which deck (floor) a screen tap landed on in the 3D stacked overview. The\n * seat layer is melt-cached at that zoom so individual seat nodes aren't\n * hit-testable; instead we invert the iso+stage transform via the layer's\n * relative pointer and take the nearest seat's floor. Only the floor matters,\n * so within-floor elevation offsets don't affect the result. Null if none.\n */\n private deckFloorAt(): string | null {\n if (!this.objectFloor.size) return null;\n const p = this.seatLayer.getRelativePointerPosition();\n if (!p) return null;\n let best: string | null = null;\n let bestD = Infinity;\n for (const s of this.seats) {\n const dx = s.x - p.x;\n const dy = s.y - p.y;\n const d = dx * dx + dy * dy;\n if (d < bestD) { bestD = d; best = s.rowId; }\n }\n return best ? this.objectFloor.get(best) ?? null : null;\n }\n\n // ---- Pan & pinch (raw pointer events — mouse, touch and pen alike) --------\n\n private toLocal(e: PointerEvent): { x: number; y: number } {\n const r = this.container.getBoundingClientRect();\n return { x: e.clientX - r.left, y: e.clientY - r.top };\n }\n\n // NOTE: no setPointerCapture here — capturing on the container retargets\n // pointer events away from Konva's canvas, killing its click/tap/hover\n // pipeline. We rely on bubbling instead.\n private onPointerDown = (e: PointerEvent): void => {\n this.cancelGlide(); // grabbing the map cancels an in-flight glide\n const local = this.toLocal(e);\n this.pointers.set(e.pointerId, local);\n if (this.pointers.size === 1) {\n this.moved = 0;\n this.pinch = null;\n this.panStart = local;\n this.panStarted = false;\n // Manage-mode rubber-band marquee (option-gated — buyer pan is byte-\n // identical when manageMode is off). A mouse/pen primary-button drag at\n // the seats rung selects instead of panning; touch keeps single-finger\n // pan (pinch zooms) and a middle-button drag (button !== 0) still pans.\n // Disabled below the seats rung so the organizer zooms in first.\n if (\n this.opts.manageMode && this.opts.marqueeSelect &&\n e.pointerType !== 'touch' && e.button === 0 &&\n this.getRung() === 'seats'\n ) {\n this.beginMarquee(local);\n this.panLast = null;\n } else {\n this.panLast = local;\n }\n } else if (this.pointers.size === 2) {\n // A second finger converts an in-progress marquee into a pinch-zoom.\n if (this.marquee) this.cancelMarquee();\n // Anchor the whole pinch to its starting geometry: scale follows the\n // finger-distance ratio and the world point under the midpoint stays\n // glued to the midpoint. No per-event compounding → no drift.\n const [a, b] = [...this.pointers.values()];\n const mid = { x: (a.x + b.x) / 2, y: (a.y + b.y) / 2 };\n const s = this.stage.scaleX();\n this.pinch = {\n startDist: Math.hypot(b.x - a.x, b.y - a.y),\n startScale: s,\n worldMid: { x: (mid.x - this.stage.x()) / s, y: (mid.y - this.stage.y()) / s },\n };\n this.panLast = null;\n this.panStart = null;\n this.panStarted = true;\n this.moved = PAN_START_SLOP_PX + 1;\n }\n };\n\n private onPointerMove = (e: PointerEvent): void => {\n if (!this.pointers.has(e.pointerId)) return;\n e.preventDefault();\n const p = this.toLocal(e);\n this.pointers.set(e.pointerId, p);\n if (this.pointers.size === 1 && this.panStart) {\n this.moved = Math.max(this.moved, Math.hypot(p.x - this.panStart.x, p.y - this.panStart.y));\n } else if (this.pointers.size >= 2) {\n this.moved = PAN_START_SLOP_PX + 1;\n }\n\n if (this.marquee) {\n this.updateMarquee(p);\n return;\n }\n if (this.pinch && this.pointers.size >= 2) {\n const [a, b] = [...this.pointers.values()];\n const dist = Math.hypot(b.x - a.x, b.y - a.y);\n if (this.pinch.startDist < 1) return;\n const mid = { x: (a.x + b.x) / 2, y: (a.y + b.y) / 2 };\n const { min, max } = this.zoomBounds();\n const scale = clamp(this.pinch.startScale * (dist / this.pinch.startDist), min, max);\n this.stage.scale({ x: scale, y: scale });\n this.stage.position({\n x: mid.x - this.pinch.worldMid.x * scale,\n y: mid.y - this.pinch.worldMid.y * scale,\n });\n this.stage.batchDraw();\n this.scheduleViewChange();\n } else if (this.panLast && this.pointers.size === 1) {\n // Keep the camera still through normal finger jitter. Aside from making\n // taps feel steadier, this lets Konva deliver the section tap instead of\n // losing it to a one- or two-pixel accidental drag.\n if (!this.panStarted) {\n if (this.moved <= PAN_START_SLOP_PX) return;\n this.panStarted = true;\n }\n this.stage.position({\n x: this.stage.x() + (p.x - this.panLast.x),\n y: this.stage.y() + (p.y - this.panLast.y),\n });\n this.panLast = p;\n this.stage.batchDraw();\n this.scheduleViewChange();\n }\n };\n\n private onPointerEnd = (e: PointerEvent): void => {\n // Finishing a manage-mode marquee: compute the selection on pointer-UP.\n if (this.marquee) {\n this.finishMarquee();\n this.pointers.delete(e.pointerId);\n if (this.pointers.size === 0) this.panLast = null;\n return;\n }\n this.pointers.delete(e.pointerId);\n if (this.pointers.size < 2) this.pinch = null;\n if (this.pointers.size === 1) {\n // pinch → single finger: continue as a pan without jumping\n this.panLast = [...this.pointers.values()][0];\n this.panStart = this.panLast;\n this.panStarted = true;\n }\n if (this.pointers.size === 0) {\n this.panLast = null;\n this.panStart = null;\n this.panStarted = false;\n this.afterViewChange();\n }\n };\n\n /**\n * Min is chart-relative (never lose the room); max is absolute so seats\n * reach a readable size on any chart, however large the venue.\n */\n private zoomBounds(): { min: number; max: number } {\n let min = 0.5 * this.fitScale;\n // When the chart has zones, the zone rung lives at an ABSOLUTE scale\n // (ZONE_PROMINENT_SCALE). On a large venue `0.5·fitScale` can sit above it,\n // making the zone overview unreachable by zooming out — allow a touch more\n // room so the rung is actually reachable (zone-charts only).\n if (this.zones.length) min = Math.min(min, ZONE_PROMINENT_SCALE * 0.9);\n return { min, max: Math.max(10 * this.fitScale, 4) };\n }\n\n /** Zoom so `clientPoint` (stage-relative px) stays fixed under the cursor. */\n private zoomAbout(nextScale: number, clientPoint: { x: number; y: number }): void {\n const { min, max } = this.zoomBounds();\n const scale = clamp(nextScale, min, max);\n const old = this.stage.scaleX();\n if (scale === old) return;\n const worldX = (clientPoint.x - this.stage.x()) / old;\n const worldY = (clientPoint.y - this.stage.y()) / old;\n this.stage.scale({ x: scale, y: scale });\n this.stage.position({\n x: clientPoint.x - worldX * scale,\n y: clientPoint.y - worldY * scale,\n });\n this.afterViewChange();\n this.stage.batchDraw();\n }\n\n /** Zoom + pan so world-rect `b` fills the viewport (with a small margin). */\n private zoomToBounds(\n b: { x: number; y: number; width: number; height: number },\n minScale?: number,\n ): void {\n const w = this.stage.width();\n const h = this.stage.height();\n const { min, max } = this.zoomBounds();\n const margin = 1.12;\n const frameScale = Math.min(w / (b.width * margin), h / (b.height * margin));\n const scale = clamp(Math.max(frameScale, minScale ?? min), min, max);\n this.stage.scale({ x: scale, y: scale });\n this.stage.position({\n x: w / 2 - (b.x + b.width / 2) * scale,\n y: h / 2 - (b.y + b.height / 2) * scale,\n });\n this.afterViewChange();\n this.stage.batchDraw();\n }\n\n /**\n * Smoothly glide the camera to frame a section (by id) or a world-space bounds\n * rect — the Slice 5 \"glide in\". Pan+zoom tween over a calm easeInOutCubic; the\n * melt/LOD rides the camera every frame. `prefers-reduced-motion` (or\n * `opts.animate === false`) snaps via zoomToBounds. A grab (pointer-down) or a\n * newer glide cancels an in-flight one.\n */\n focusRegion(\n target: string | { x: number; y: number; width: number; height: number },\n opts?: { animate?: boolean; minScale?: number; durationMs?: number },\n ): void {\n const b =\n typeof target === 'string'\n ? (() => {\n const sec = this.sections.find((s) => s.id === target);\n return sec ? polyBounds(sec.outline) : null;\n })()\n : target;\n if (!b) return;\n this.cancelGlide();\n if (opts?.animate === false || this.reducedMotion) {\n this.zoomToBounds(b, opts?.minScale);\n return;\n }\n const w = this.stage.width();\n const h = this.stage.height();\n const { min, max } = this.zoomBounds();\n const margin = 1.12;\n const frameScale = Math.min(w / (b.width * margin), h / (b.height * margin));\n const toScale = clamp(Math.max(frameScale, opts?.minScale ?? min), min, max);\n const toX = w / 2 - (b.x + b.width / 2) * toScale;\n const toY = h / 2 - (b.y + b.height / 2) * toScale;\n const fromScale = this.stage.scaleX();\n const fromX = this.stage.x();\n const fromY = this.stage.y();\n if (Math.abs(toScale - fromScale) < 1e-4 && Math.abs(toX - fromX) < 0.5 && Math.abs(toY - fromY) < 0.5) {\n this.afterViewChange();\n return;\n }\n const start = performance.now();\n const duration = Math.max(180, Math.min(1200, opts?.durationMs ?? CAMERA_GLIDE_MS));\n const step = (now: number): void => {\n if (this.destroyed) { this.glideRaf = 0; return; }\n const raw = Math.min(1, (now - start) / duration);\n const e = raw < 0.5 ? 4 * raw * raw * raw : 1 - Math.pow(-2 * raw + 2, 3) / 2;\n const sc = fromScale + (toScale - fromScale) * e;\n this.stage.scale({ x: sc, y: sc });\n this.stage.position({ x: fromX + (toX - fromX) * e, y: fromY + (toY - fromY) * e });\n this.updateLOD(); // the melt cross-fades as the camera rides in\n this.scheduleViewChange();\n this.stage.batchDraw();\n if (raw < 1) {\n this.glideRaf = requestAnimationFrame(step);\n } else {\n this.glideRaf = 0;\n this.afterViewChange();\n }\n };\n this.glideRaf = requestAnimationFrame(step);\n }\n\n /** Cancel an in-flight camera glide (a grab or a newer glide interrupts it). */\n private cancelGlide(): void {\n if (this.glideRaf) {\n cancelAnimationFrame(this.glideRaf);\n this.glideRaf = 0;\n }\n }\n\n /** Current LOD rung derived from effective zoom — drives the ZONES/SECTIONS/SEATS pill. */\n getRung(): LodRung {\n const scale = this.effScale();\n if (scale >= CACHE_THRESHOLD) return 'seats';\n if (this.zones.length && scale < ZONE_PROMINENT_SCALE) return 'zones';\n return 'sections';\n }\n\n /** Jump the camera to a rung's zoom band, centred on the chart (glided). */\n setRung(rung: LodRung): void {\n if (rung === 'zones') {\n this.cancelGlide();\n this.zoomToFit();\n return;\n }\n const target =\n rung === 'sections'\n ? (SECTION_PROMINENT_SCALE + CACHE_THRESHOLD) / 2\n : Math.max(SEAT_FOCUS_SCALE, CACHE_THRESHOLD * 1.3);\n const w = this.stage.width();\n const h = this.stage.height();\n const cx = this.bounds.x + this.bounds.width / 2;\n const cy = this.bounds.y + this.bounds.height / 2;\n const bw = w / (target * 1.12);\n const bh = h / (target * 1.12);\n this.focusRegion({ x: cx - bw / 2, y: cy - bh / 2, width: bw, height: bh });\n }\n\n /** Recompute LOD (cache/labels) after any pan/zoom settles. */\n private afterViewChange(): void {\n this.updateLOD();\n this.updateLabels();\n this.scheduleViewChange();\n }\n\n /** rAF-coalesced `onViewChange` — at most one host callback per animation frame. */\n private scheduleViewChange(): void {\n if (this.viewChangeRaf) return;\n this.viewChangeRaf = requestAnimationFrame(() => {\n this.viewChangeRaf = 0;\n this.opts.onViewChange?.();\n });\n }\n\n private updateLOD(): void {\n // Effective scale folds in the iso y-squash (smaller ⇒ seats read smaller),\n // so LOD/melt thresholds trip correctly in 3D view. Equals the raw stage\n // scale at isoT=0 → flat behaviour is unchanged.\n const scale = this.effScale();\n if (this.hasSections) this.applySectionLod(scale);\n const shouldCache = scale < CACHE_THRESHOLD;\n if (shouldCache && !this.cached) {\n this.cacheSeatLayer();\n } else if (!shouldCache && this.cached) {\n this.seatLayer.clearCache();\n this.seatLayer.listening(true);\n this.cached = false;\n this.seatLayer.batchDraw();\n }\n }\n\n /** Rebuild the seat-layer bitmap synchronously (no paint). Shared by the\n * debounced cacheSeatLayer() and the synchronous forceDraw() catch-up. */\n private rebuildSeatCache(): void {\n // Cache at ~screen resolution: bitmap px ≈ on-screen px, so a huge chart in\n // chart-units doesn't blow up into a gigapixel canvas when zoomed out.\n const pr = clamp(this.stage.scaleX() * this.dpr, 0.15, 2);\n this.seatLayer.clearCache();\n this.seatLayer.cache({ pixelRatio: pr });\n this.seatLayer.listening(false);\n this.cached = true;\n }\n\n private cacheSeatLayer(): void {\n this.rebuildSeatCache();\n this.seatLayer.batchDraw();\n }\n\n /**\n * SYNCHRONOUS repaint that bypasses requestAnimationFrame — see the\n * ISeatmapRenderer.forceDraw() contract. Chrome pauses rAF (and therefore\n * Konva's batchDraw) on hidden/backgrounded/occluded tabs, so seat-status\n * deltas applied via setStatus() mutate the scene graph but never reach the\n * canvas until the tab is foregrounded. This flushes the cache-debounce and\n * paints every layer setStatus() can touch, immediately.\n *\n * Additive: the foreground path never calls this, so foreground behaviour is\n * byte-identical.\n */\n forceDraw(): void {\n // Flush any pending cache-debounce (setStatus coalesces bursts behind a\n // 150ms setTimeout) so a returning tab isn't left showing a stale bitmap.\n if (this.recacheTimer) {\n clearTimeout(this.recacheTimer);\n this.recacheTimer = null;\n // Fold the coalesced deltas into the bitmap now, synchronously.\n this.rebuildSeatCache();\n }\n // Synchronous paint of every layer setStatus() may repaint. Layer.draw()\n // renders on the calling thread, unlike batchDraw()'s rAF schedule.\n this.bgLayer.draw();\n this.seatLayer.draw();\n this.overlayLayer.draw();\n }\n\n private updateLabels(): void {\n const show = this.effScale() > LABEL_SCALE;\n this.labelGroup.destroyChildren();\n if (!show) {\n this.overlayLayer.batchDraw();\n return;\n }\n // Visible chart rect (with a small margin) in chart coordinates.\n const s = this.stage.scaleX();\n const x0 = (-this.stage.x()) / s;\n const y0 = (-this.stage.y()) / s;\n const x1 = (this.stage.width() - this.stage.x()) / s;\n const y1 = (this.stage.height() - this.stage.y()) / s;\n\n let count = 0;\n for (const seat of this.seats) {\n // Booth labels already live beside their rectangular shape in seatLayer\n // (renderBoothUnit). Adding them again to the zoom-only overlay produces\n // the offset/doubled numbers visible at close zoom levels.\n if (seat.kind === 'booth') continue;\n if (seat.x < x0 || seat.x > x1 || seat.y < y0 || seat.y > y1) continue;\n const status = this.statusById.get(seat.id) ?? 'free';\n const unavailable = status === 'booked' || (status === 'held' && !this.ownedHold.has(seat.id));\n if (unavailable) {\n // Status is geometry, not a letter: a centred lock for a temporary hold\n // and one quiet diagonal mark for sold. This stays aligned at every\n // zoom level and does not ask buyers to decode \"H\" or a large × glyph.\n const cue = new Group({ x: seat.x, y: seat.y, listening: false });\n if (status === 'held') {\n cue.add(new Rect({\n x: -4.2, y: -0.7, width: 8.4, height: 6.5, cornerRadius: 1.3,\n stroke: '#ffffff', strokeWidth: 1.25, listening: false,\n }));\n cue.add(new Line({\n points: [-2.4, -0.8, -2.4, -2.7, -1.2, -4, 0, -4.35, 1.2, -4, 2.4, -2.7, 2.4, -0.8],\n stroke: '#ffffff', strokeWidth: 1.2, lineCap: 'round', lineJoin: 'round', listening: false,\n }));\n } else {\n cue.add(new Line({\n points: [-4.2, 4.2, 4.2, -4.2], stroke: '#ffffff', strokeWidth: 1.8,\n lineCap: 'round', listening: false,\n }));\n }\n this.labelGroup.add(cue);\n if (++count >= MAX_LABELS) break;\n continue;\n }\n const t = new Text({\n x: seat.x,\n y: seat.y,\n text: seat.label,\n fontSize: 7,\n fontStyle: '600',\n fontFamily: this.labelFont(),\n fill: this.theme.seatLabelColor ?? DEF_SEAT_LABEL,\n listening: false,\n perfectDrawEnabled: false,\n });\n // Auto-fit: shrink long labels (e.g. \"T10-10\") so they never spill out of\n // the seat circle. Down to a legibility floor; below that the label is\n // dropped rather than rendered as an unreadable speck.\n const maxW = this.seatR * 2 - 3;\n if (t.width() > maxW) t.fontSize(Math.max(4, (t.fontSize() * maxW) / t.width()));\n if (t.fontSize() < 4.2) { t.destroy(); continue; }\n t.offsetX(t.width() / 2);\n t.offsetY(t.height() / 2);\n this.labelGroup.add(t);\n if (++count >= MAX_LABELS) break;\n }\n // Keep freshly-built seat labels upright under the iso layer skew.\n if (this.isoT > 0) this.applyUprightLabels();\n this.overlayLayer.batchDraw();\n }\n\n private handleResize(): void {\n const w = this.container.clientWidth || 1;\n const h = this.container.clientHeight || 1;\n if (w === this.stage.width() && h === this.stage.height()) return;\n this.stage.size({ width: w, height: h });\n // Keep the chart framed; refit is the least surprising behaviour on resize.\n this.zoomToFit();\n }\n\n private startFpsLoop(): void {\n const tick = (now: number) => {\n if (!this.lastFpsAt) this.lastFpsAt = now;\n this.frames++;\n const elapsed = now - this.lastFpsAt;\n if (elapsed >= 1000) {\n this.opts.onFps?.(Math.round((this.frames * 1000) / elapsed));\n this.frames = 0;\n this.lastFpsAt = now;\n }\n this.rafId = requestAnimationFrame(tick);\n };\n this.rafId = requestAnimationFrame(tick);\n }\n}\n\nexport function createRenderer(container: HTMLDivElement, opts?: RendererOptions): ISeatmapRenderer {\n return new SeatmapRenderer(container, opts);\n}\n","/**\n * Money formatting — the ONE place currency rendering happens.\n *\n * Ticket money is multi-currency: the org sets a default and each event can\n * override it (ISO 4217 code delivered with the event/chart payload). Until\n * those backend fields land, callers fall back to DEFAULT_CURRENCY, which is\n * kept at EUR so live buyer pages render exactly what they rendered when the\n * symbol was hardcoded. Flipping an org to USD/INR/… later is data, not code.\n *\n * Amounts are in MAJOR units (45 === €45) matching Category.price in\n * src/core/types.ts. If/when backend money fields arrive in minor units,\n * convert at the API boundary, not here.\n */\n\n// App-wide fallback when no org currency is available (unauthed/demo surfaces).\n// Owner decision 2026-07-08: USD default (orgs.currency also defaults to USD).\nexport const DEFAULT_CURRENCY = 'USD';\n\n/** BCP 47 locale used for number/date rendering; kept in sync by src/i18n. */\nlet displayLocale: string | undefined;\n\nexport function setMoneyLocale(locale: string | undefined): void {\n displayLocale = locale;\n}\n\nconst formatterCache = new Map<string, Intl.NumberFormat>();\n\nfunction formatter(currency: string, digits: number | undefined): Intl.NumberFormat {\n const key = `${displayLocale ?? ''}|${currency}|${digits ?? 'auto'}`;\n let fmt = formatterCache.get(key);\n if (!fmt) {\n fmt = new Intl.NumberFormat(displayLocale, {\n style: 'currency',\n currency,\n minimumFractionDigits: digits,\n maximumFractionDigits: digits,\n });\n formatterCache.set(key, fmt);\n }\n return fmt;\n}\n\n/**\n * \"€45\" / \"$1,500\" / \"45 €\" (locale-dependent placement).\n * Whole amounts render without \".00\" (design shows \"$45\", \"$120\"); pass\n * `fractionDigits` for fixed precision (e.g. 3 for \"$0.045 / credit\").\n */\nexport function formatMoney(\n amount: number,\n currency: string = DEFAULT_CURRENCY,\n fractionDigits?: number,\n): string {\n const digits = fractionDigits ?? (Number.isInteger(amount) ? 0 : undefined);\n return formatter(currency, digits).format(amount);\n}\n\n/** Bare symbol for input adornments (\"€\", \"$\", \"₹\"). */\nexport function currencySymbol(currency: string = DEFAULT_CURRENCY): string {\n const part = formatter(currency, 0)\n .formatToParts(0)\n .find((p) => p.type === 'currency');\n return part?.value ?? currency;\n}\n","/**\n * English bundle — the reference dictionary every other locale is checked\n * against. Keys are added as pages route their strings through t() during\n * the design port (docs/design-port-plan.md); buyer-surface keys land first.\n *\n * Conventions:\n * - flat dot-namespaced keys: \"<surface>.<element>\" (picker.holdSeats)\n * - {name} interpolation, {count} reserved for tCount plural keys\n * - plural keys end in \".one\" / \".other\" (Intl.PluralRules categories)\n */\n\nimport type { Dict } from '../index';\n\nexport const en: Dict = {\n // shared\n 'common.cancel': 'Cancel',\n 'common.close': 'Close',\n 'common.done': 'Done',\n 'common.copied': '✓ Copied',\n\n // buyer picker (extraction in progress — P4 of the port plan)\n 'picker.holdSeats': 'Hold seats & checkout',\n 'picker.completeBooking': 'Complete booking',\n 'picker.seatsHeld': 'Seats held — {time}',\n 'picker.holdExpired': 'Your hold expired — the seats were released. Pick again.',\n 'picker.seatTaken': 'Seat {label} was just taken by another buyer.',\n 'picker.poweredBy': 'Powered by SeatLayer',\n 'picker.testMode': 'TEST MODE',\n 'picker.colorblind': 'Colorblind-friendly colors',\n 'picker.orphanHint': 'This leaves a single seat stranded — consider shifting one seat over.',\n 'picker.seats.one': '{count} seat',\n 'picker.seats.other': '{count} seats',\n\n // renderer (drawn on the Konva map — shared by the embed SDK)\n 'map.aria': 'Seating map. Use arrow keys to move between seats, Enter to select.',\n 'map.seatsLeft': '{count} LEFT',\n 'map.fromPrice': 'FROM {price}',\n 'map.statusHeld': 'On hold',\n 'map.statusTaken': 'Taken',\n\n // buyer picker page (src/pages/PickerPage.tsx)\n 'picker.language': 'Language',\n 'picker.zoomToFit': 'Zoom to fit',\n 'picker.viewMode': 'View mode',\n 'picker.floor': 'Floor',\n 'picker.zoomLevel': 'Zoom level',\n 'picker.rungTip.zones': 'Venue overview — groups of sections such as North Stand or VIP',\n 'picker.rungTip.sections': 'Section blocks — category-mix fill + availability tint',\n 'picker.rungTip.seats': 'Individual seats — blocks melt into dots',\n 'picker.rungLabel.zones': 'ZONES',\n 'picker.rungLabel.sections': 'SECTIONS',\n 'picker.rungLabel.seats': 'SEATS',\n 'picker.sectionSummaryAria': '{label} section summary',\n 'picker.closeSectionSummary': 'Close section summary',\n 'picker.seatsLeftInSection.one': '{count} seat left',\n 'picker.seatsLeftInSection.other': '{count} seats left',\n 'picker.overview': 'Overview',\n 'picker.tapSeatHint': 'Tap any seat to check its view',\n 'picker.chartSize': 'Chart size',\n 'picker.custom': 'Custom',\n 'picker.categories': 'Categories',\n 'picker.accessibility': 'Accessibility',\n 'picker.showAnyAccessible': 'Show any accessible seat',\n 'picker.any': 'Any',\n 'picker.yourSeats': 'Your seats',\n 'picker.emptySeats': 'Tap seats on the map',\n 'picker.emptySeatsWithGa': 'Tap seats on the map · tap a standing area for GA tickets',\n 'picker.oneFewer': 'One fewer',\n 'picker.oneMore': 'One more',\n 'picker.remove': 'Remove {label}',\n 'picker.ticketTierFor': 'Ticket tier for {label}',\n 'picker.total': 'Total: {amount}',\n 'picker.viewFromSeat': 'View from seat {label}',\n 'picker.real360': 'REAL 360°',\n 'picker.preview': 'PREVIEW',\n 'picker.open360': 'Open 360° view',\n 'picker.sightline': '≈ {rows} rows from stage · {angle}° off-center',\n 'picker.bookedDemo': 'Booked! (demo)',\n 'picker.bookButton.one': 'Book {count} ticket — {amount}',\n 'picker.bookButton.other': 'Book {count} tickets — {amount}',\n 'picker.simulateCrowd': 'Simulate crowd: {state}',\n 'picker.on': 'ON',\n 'picker.off': 'OFF',\n 'picker.panorama360': '360° venue photo',\n 'picker.illustrationCaption': 'illustration · ≈ {m} m from stage',\n};\n","/**\n * i18n core — deliberately tiny and framework-free so the embed SDK can share\n * it without dragging in a runtime library (the 60KB-gzipped SDK budget is a\n * product contract).\n *\n * Scope (docs/design-port-plan.md): the buyer surface (picker, public event\n * page, SDK) ships fully translated in en/es/de/fr; dashboard pages route\n * their strings through t() as they are rebuilt but ship English this round.\n *\n * Keys are flat dot-namespaced strings (\"picker.holdSeats\"). Interpolation\n * uses {name} placeholders. Missing keys fall back to English, then to the\n * key itself — a page never crashes over a translation.\n */\n\nimport { setMoneyLocale } from '../lib/money';\nimport { en } from './locales/en';\n\nexport type Locale = 'en' | 'es' | 'de' | 'fr';\nexport const SUPPORTED_LOCALES: Locale[] = ['en', 'es', 'de', 'fr'];\n\nexport type Dict = Record<string, string>;\n\nconst bundles: Partial<Record<Locale, Dict>> = { en };\n\n/** Extra strings layered over the active bundle (SDK white-label overrides). */\nlet overrides: Dict = {};\n\nlet active: Locale = 'en';\n\n/** explicit setting → stored preference → browser language → en */\nexport function resolveLocale(explicit?: string | null, stored?: string | null): Locale {\n for (const candidate of [explicit, stored, typeof navigator !== 'undefined' ? navigator.language : null]) {\n if (!candidate) continue;\n const base = candidate.toLowerCase().split('-')[0] as Locale;\n if (SUPPORTED_LOCALES.includes(base)) return base;\n }\n return 'en';\n}\n\nexport function getLocale(): Locale {\n return active;\n}\n\n/**\n * Set the active locale. Locale bundles other than English are registered by\n * the surface that needs them (the picker imports its own es/de/fr bundles;\n * the dashboard stays English until its translations ship).\n */\nexport function setLocale(locale: Locale, bundle?: Dict): void {\n if (bundle) bundles[locale] = { ...bundles[locale], ...bundle };\n active = bundles[locale] ? locale : 'en';\n setMoneyLocale(active);\n if (typeof document !== 'undefined') document.documentElement.lang = active;\n}\n\nexport function setStringOverrides(next: Dict): void {\n overrides = next;\n}\n\nconst PLACEHOLDER = /\\{(\\w+)\\}/g;\n\nexport function t(key: string, vars?: Record<string, string | number>): string {\n const raw = overrides[key] ?? bundles[active]?.[key] ?? en[key] ?? key;\n if (!vars) return raw;\n return raw.replace(PLACEHOLDER, (_, name: string) => String(vars[name] ?? `{${name}}`));\n}\n\n/** \"1 seat\" / \"3 seats\" without hand-rolled concatenation. */\nexport function tCount(key: string, count: number, vars?: Record<string, string | number>): string {\n const rule = new Intl.PluralRules(active).select(count);\n const exact = overrides[`${key}.${rule}`] ?? bundles[active]?.[`${key}.${rule}`] ?? en[`${key}.${rule}`];\n const raw = exact ?? overrides[`${key}.other`] ?? bundles[active]?.[`${key}.other`] ?? en[`${key}.other`] ?? key;\n return raw.replace(PLACEHOLDER, (_, name: string) => String({ count, ...vars }[name] ?? `{${name}}`));\n}\n\nexport function formatDate(value: number | Date, opts?: Intl.DateTimeFormatOptions): string {\n return new Intl.DateTimeFormat(active, opts ?? { dateStyle: 'medium', timeStyle: 'short' }).format(value);\n}\n","/**\n * Orphan-seat detection for MANUAL selection — the client-side sibling of the\n * server's best-available orphan avoidance (workers/api/src/bestAvailable):\n * a \"stranded single\" is a free seat whose both same-row neighbors are\n * unavailable (non-free or currently selected). The picker uses this to show\n * a non-blocking hint; nothing is ever prevented.\n */\nimport type { ExpandedSeat, SeatStatus } from './types';\n\n/** Numeric seat index from the stable id (`${rowId}:${index}`). */\nfunction seatIndex(id: string): number {\n const n = Number(id.slice(id.lastIndexOf(':') + 1));\n return Number.isFinite(n) ? n : -1;\n}\n\n/**\n * Free seats stranded by the current selection: both same-row neighbors exist\n * and are unavailable, and at least one neighbor is part of `selectedIds` —\n * so pre-existing single gaps (caused by earlier buyers) never nag.\n * Booth units are ignored (no row adjacency).\n */\nexport function strandedSingles(\n seats: Iterable<ExpandedSeat>,\n statusOf: (seatId: string) => SeatStatus,\n selectedIds: ReadonlySet<string>,\n): ExpandedSeat[] {\n // Group by row, ordered by index, skipping booths.\n const rows = new Map<string, ExpandedSeat[]>();\n for (const s of seats) {\n if (s.kind === 'booth') continue;\n const list = rows.get(s.rowId);\n if (list) list.push(s);\n else rows.set(s.rowId, [s]);\n }\n\n const unavailable = (s: ExpandedSeat): boolean =>\n selectedIds.has(s.id) || statusOf(s.id) !== 'free';\n\n const out: ExpandedSeat[] = [];\n for (const list of rows.values()) {\n if (list.length < 3) continue;\n list.sort((a, b) => seatIndex(a.id) - seatIndex(b.id));\n for (let i = 1; i < list.length - 1; i++) {\n const seat = list[i];\n if (unavailable(seat)) continue; // not free (or selected) → not stranded\n const left = list[i - 1];\n const right = list[i + 1];\n // Neighbors must be physically adjacent (index gap of 1) — a labelled\n // aisle gap in the numbering doesn't strand anyone.\n if (seatIndex(seat.id) - seatIndex(left.id) !== 1 || seatIndex(right.id) - seatIndex(seat.id) !== 1) continue;\n if (!unavailable(left) || !unavailable(right)) continue;\n if (!selectedIds.has(left.id) && !selectedIds.has(right.id)) continue;\n out.push(seat);\n }\n }\n return out;\n}\n","/**\n * PickerController — the single, framework-agnostic buyer-picker core.\n *\n * Consolidates the transport + booking logic that was copy-pasted across\n * sdk/src/SeatingChart.ts, src/pages/PublicEventPage.tsx and PickerPage.tsx:\n * fetch the published chart, mount the Konva renderer, seed statuses from a REST\n * snapshot, keep them live over a WebSocket (reconnect w/ backoff, re-snapshot on\n * every open), and run the hold → book state machine (best-available, hold reuse,\n * per-label partial release, 409 semantics, server-authoritative hold expiry).\n *\n * The SDK, the live buyer page, and the demo picker all drive this one class;\n * presentation (confirm card, legend, cart, etc.) lives in the consumers.\n *\n * Transport is injected (PickerTransport) so the SDK can use its CORS-trivial\n * PubApi while the dashboard uses an adapter over src/lib/api.ts.\n */\nimport { createRenderer } from '../engine/SeatmapRenderer';\nimport { allObjects, expandChart } from '../core/layout';\nimport { applyHidden, computeSections } from '../core/sections';\nimport { strandedSingles } from '../core/orphans';\nimport { t } from '../i18n';\nimport type {\n CategoryTier,\n ChartDoc,\n ExpandedSeat,\n ISeatmapRenderer,\n LodRung,\n RendererCallbacks,\n SeatStatus,\n SectionObject,\n} from '../core/types';\nimport { gaAreasOf, gaUnitLabels } from '../core/ga';\n\nconst DEFAULT_MAX_SELECTION = 10;\nconst MAX_BACKOFF_MS = 15_000;\n\nexport interface PickerSeat {\n id: string;\n label: string;\n categoryKey: string;\n /** Price for the chosen tier when the category has tiers, else the base price. */\n price: number;\n /** Ticket tiers the seat's category offers (Adult/Child/…); absent when none. */\n tiers?: CategoryTier[];\n /** The chosen tier's id — defaults to the first tier; absent when no tiers. */\n tierId?: string;\n}\n\n/**\n * Rich hover payload for seat tooltips — the PickerSeat plus everything a\n * buyer-facing popover needs: category label + swatch color, live status and\n * the chart currency. Emitted by `onSeatHover` (null on hover-out).\n */\nexport interface SeatHoverDetails extends PickerSeat {\n categoryLabel: string;\n categoryColor: string;\n status: SeatStatus;\n currency: string;\n /** Human-readable spatial context for hover and confirmation UI. */\n sectionLabel?: string;\n rowLabel?: string;\n seatNumber?: string;\n}\n\nexport interface HoldConflict {\n label: string;\n status: string;\n}\n\n/** An open hold — its id, the labels it covers, and the server's expiry time (ms epoch). */\nexport interface HoldInfo {\n holdId: string;\n labels: string[];\n expiresAt: number;\n /** The held seats with their chosen ticket tier — what the host books against. */\n seats: PickerSeat[];\n /** Server-authoritative commercial line items, including GA units and resolved prices. */\n items?: HoldServerItem[];\n}\n\n/** One category's slice of a section (dot + price + count) for the summary card. */\nexport interface SectionCategory {\n key: string;\n label: string;\n color: string;\n price: number;\n count: number;\n}\n\n/**\n * Big-venue section-summary — everything the tapped-section card renders: name,\n * its zone, live seats-left, price range, and the per-category breakdown.\n * Computed from the renderer's spatial section membership (Slice 5).\n */\nexport interface SectionSummary {\n id: string;\n label: string;\n /** Zone label (from ChartDoc.zones); '' when the section has no zone. */\n zoneLabel: string;\n /** Mix/section colour for the card's dot (section.color → zone colour → dominant category). */\n color: string;\n /** Free member seats right now. */\n seatsLeft: number;\n priceMin: number;\n priceMax: number;\n /** Per-category breakdown, cheapest first. */\n categories: SectionCategory[];\n}\n\ninterface HoldResponse {\n holdId: string;\n expiresAt: number;\n items?: HoldServerItem[];\n}\ninterface ResumeHoldResponse extends HoldResponse {\n items: HoldServerItem[];\n}\nexport interface HoldServerItem {\n label: string;\n objectId: string;\n objectType: 'seat' | 'booth' | 'ga';\n categoryKey: string;\n tierId: string | null;\n unitPrice: number;\n currency: string;\n quantity?: number;\n}\nexport interface HoldSelectionRequest { label: string; tierId?: string | null }\ninterface BestAvailableResponse extends HoldResponse {\n labels: string[];\n}\n\n/** Swappable public-surface transport (SDK PubApi or a dashboard `api.pub.*` adapter). */\nexport interface PickerTransport {\n chart(key: string): Promise<{\n doc: ChartDoc;\n event: { key: string; name: string; salesClosed?: boolean; venue?: string | null; startsAt?: number | null; currency?: string; mode?: string };\n }>;\n objects(key: string): Promise<{ seats: Record<string, string>; hidden?: string[]; closed?: string[] }>;\n hold(key: string, selections: HoldSelectionRequest[], ttlMs?: number, replaceHoldId?: string): Promise<HoldResponse>;\n bestAvailable(key: string, qty: number, categoryKey?: string): Promise<BestAvailableResponse>;\n release(key: string, labels: string[], holdId: string): Promise<unknown>;\n /** Optional capability-style lookup used to restore an active browser hold. */\n resume?(key: string, holdId: string): Promise<ResumeHoldResponse>;\n /** Optional — the SDK omits booking (it hands the holdId to the host page). */\n book?(key: string, labels: string[], holdId: string, bookingRef: string): Promise<unknown>;\n /** Optional (P4) — push an active hold's expiry out (\"need more time?\"). */\n extend?(key: string, holdId: string, ttlMs?: number): Promise<{ holdId: string; expiresAt: number; extends?: number }>;\n socketUrl(key: string): string;\n}\n\nexport interface PickerCallbacks extends RendererCallbacks {\n /** Selection changed (manual clicks or a server best-available pick). */\n onSelectionChange?: (seats: PickerSeat[]) => void;\n /** A hold opened (manual hold or best-available). */\n onHold?: (hold: HoldInfo) => void;\n /** A prior active hold was restored from its opaque hold id. */\n onHoldRestored?: (hold: HoldInfo) => void;\n /** The open hold expired server-side (the controller has already released it). */\n onHoldExpired?: () => void;\n /** A booking completed with this ref. */\n onBook?: (bookingRef: string) => void;\n /** Any live seat-status change arrived (delta or snapshot) — e.g. to recount \"N left\". */\n onStatusChange?: () => void;\n /**\n * Mouse hover moved onto a seat (null on hover-out) — the seat enriched with\n * category label/color, resolved price and live status, ready for a tooltip.\n * Fires alongside the raw renderer-level `onHover`.\n */\n onSeatHover?: (details: SeatHoverDetails | null) => void;\n /** The server declared the event closed (a 409 event_closed). */\n onSalesClosed?: () => void;\n /**\n * A section block was tapped at the far/zone rung — the controller has glided\n * the camera in and passes the computed summary (or null when cleared, e.g.\n * overview() / zoom-to-zones) so the host can show/hide the summary card.\n */\n onSectionFocus?: (summary: SectionSummary | null) => void;\n /** A deck was tapped in the 3D all-floors overview — host enters that floor in 2D. */\n onDeckTap?: (floorId: string) => void;\n /**\n * Non-blocking selection advice (localized): currently the orphan-seat hint —\n * the selection would strand a single free seat between unavailable\n * neighbors. `null` clears a previously shown hint. Never prevents anything.\n */\n onHint?: (message: string | null) => void;\n onError?: (err: unknown) => void;\n}\n\nexport interface PickerOptions extends PickerCallbacks {\n transport: PickerTransport;\n eventKey: string;\n maxSelection?: number;\n /** Renderer confirm-card mode (host shows a confirm popover instead of instant cart add). */\n confirmSelection?: boolean;\n /** ISO 4217 currency for on-map prices (default from money.DEFAULT_CURRENCY). */\n currency?: string;\n /** Flash a pulse when a seat we didn't touch goes free→taken (live-activity cue). */\n flashOnLiveChange?: boolean;\n /** Start in colorblind-safe rendering (Okabe-Ito hues + hollow booked seats). */\n colorblindSafe?: boolean;\n /**\n * Keep painting seat-status deltas even while the tab is hidden/backgrounded.\n *\n * Default FALSE — the buyer widget stays efficient: it lets rAF stay paused\n * while hidden and does a single synchronous catch-up repaint on regain (the\n * visibilitychange handler resnapshots + forceDraw()s). Set TRUE only for an\n * always-live surface — the future organizer control-room board — where a\n * backgrounded monitor must keep repainting; then each delta calls\n * renderer.forceDraw() when the tab is hidden. Purely a paint hint; enforcement\n * and the WS protocol are identical either way.\n */\n keepLiveWhileHidden?: boolean;\n}\n\n/** Read `status`/`conflicts`/`reason` off any thrown error without importing a specific ApiError. */\nfunction errInfo(err: unknown): { status?: number; conflicts?: HoldConflict[]; reason?: string } {\n const e = (err ?? {}) as { status?: number; conflicts?: HoldConflict[]; reason?: string };\n return { status: e.status, conflicts: e.conflicts, reason: e.reason };\n}\n\n/** DO seat status → renderer status ('blocked' has no renderer analogue → 'not_for_sale'). */\nfunction mapStatus(s: string): SeatStatus {\n if (s === 'blocked') return 'not_for_sale';\n if (s === 'held' || s === 'booked' || s === 'free' || s === 'not_for_sale') return s;\n return 'free';\n}\n\nexport class PickerController {\n private readonly opts: PickerOptions;\n private readonly api: PickerTransport;\n private readonly key: string;\n private readonly maxSelection: number;\n\n private renderer: ISeatmapRenderer | null = null;\n private _doc: ChartDoc | null = null;\n /** Section/zone ids hidden from buyers this event (3.3) — seats vanish, not grey. */\n private hidden = new Set<string>();\n /** Section/zone ids in the `closed` event-state (Phase 2) — seats stay, greyed\n * + not pickable. Kept separate from `hidden` (which strips them). */\n private closedSections = new Set<string>();\n\n /** label ⇄ id maps — backend speaks labels, the engine speaks ids. */\n private labelToId = new Map<string, string>();\n private labelToSeat = new Map<string, ExpandedSeat>();\n /** seatId → chosen ticket-tier id (absent ⇒ the category's first/default tier). */\n private seatTiers = new Map<string, string>();\n /** id → seat, for the section-summary breakdown (renderer members are ids). */\n private seatById = new Map<string, ExpandedSeat>();\n /** id → buyer-facing spatial metadata used by every tooltip/confirm surface. */\n private seatContext = new Map<string, { sectionLabel?: string; rowLabel?: string; seatNumber?: string }>();\n private allIds: string[] = [];\n\n // realtime socket\n private ws: WebSocket | null = null;\n private reconnectTimer: ReturnType<typeof setTimeout> | null = null;\n private attempt = 0;\n private closed = false;\n /** Bound visibilitychange listener (buyer catch-up on tab regain). Kept on the\n * instance so destroy() can detach it; null when not attached (guards double\n * mounts / non-DOM environments). */\n private onVisibilityChange: (() => void) | null = null;\n\n // hold state\n private hold_: HoldInfo | null = null;\n private liveStatuses = new Map<string, string>();\n private currency = 'USD';\n private expiryTimer: ReturnType<typeof setTimeout> | null = null;\n\n constructor(options: PickerOptions) {\n this.opts = options;\n this.api = options.transport;\n this.key = options.eventKey;\n this.maxSelection = options.maxSelection ?? DEFAULT_MAX_SELECTION;\n }\n\n get doc(): ChartDoc | null {\n return this._doc;\n }\n\n /** The chart with hidden sections' seats removed — what buyers actually see. */\n private visibleDoc(): ChartDoc {\n return this._doc ? applyHidden(this._doc, this.hidden) : ({ objects: [] } as unknown as ChartDoc);\n }\n\n /** Adopt a new hidden set; rebuild the visible chart only if it differs. */\n private syncHidden(ids: string[]): boolean {\n const next = ids.filter((x): x is string => typeof x === 'string');\n if (next.length === this.hidden.size && next.every((id) => this.hidden.has(id))) return false;\n this.hidden = new Set(next);\n this.renderer?.setChart(this.visibleDoc());\n return true;\n }\n\n /** Adopt a new closed-section set; restyle (grey + non-pickable) if it differs.\n * Cheap restyle — no chart rebuild — so mid-sale open/close repaints live. */\n private syncClosed(ids: string[] | undefined): boolean {\n const next = (ids ?? []).filter((x): x is string => typeof x === 'string');\n if (next.length === this.closedSections.size && next.every((id) => this.closedSections.has(id))) return false;\n this.closedSections = new Set(next);\n this.renderer?.setClosedSections?.(next);\n return true;\n }\n\n /** Whether a section is currently in the `closed` state (card must not open). */\n isSectionClosed(id: string): boolean {\n return this.closedSections.has(id);\n }\n currentHold(): HoldInfo | null {\n return this.hold_;\n }\n getRenderer(): ISeatmapRenderer | null {\n return this.renderer;\n }\n seatByLabel(label: string): ExpandedSeat | undefined {\n return this.labelToSeat.get(label);\n }\n idForLabel(label: string): string | undefined {\n return this.labelToId.get(label);\n }\n\n /** Fetch chart, build label maps, mount the renderer, seed statuses, go live. */\n async render(host: HTMLDivElement): Promise<{\n doc: ChartDoc;\n salesClosed: boolean;\n eventName: string;\n venue?: string | null;\n startsAt?: number | null;\n currency?: string;\n /** 'test' ⇒ sandbox event (hosts show a TEST MODE ribbon). */\n mode?: string;\n } | null> {\n if (this.renderer) return null; // already rendered — never mount twice on one controller\n this.closed = false;\n let res;\n try {\n res = await this.api.chart(this.key);\n } catch (err) {\n this.emitError(err);\n return null;\n }\n // destroy() may have run while the chart fetch was in flight (StrictMode\n // double-mount, or a fast key change) — bail before mounting anything.\n if (this.closed) return null;\n this._doc = res.doc;\n\n this.labelToId = new Map();\n this.labelToSeat = new Map();\n this.seatById = new Map();\n this.seatContext = new Map();\n this.allIds = [];\n const chartObjects = new Map(allObjects(res.doc).map((object) => [object.id, object] as const));\n const membership = computeSections(res.doc);\n const sectionLabels = new Map(\n [...membership.sections, ...(membership.ungrouped ? [membership.ungrouped] : [])].map((section) => [section.id, section.label] as const),\n );\n for (const s of expandChart(res.doc)) {\n this.labelToId.set(s.label, s.id);\n this.labelToSeat.set(s.label, s);\n this.seatById.set(s.id, s);\n this.allIds.push(s.id);\n const source = chartObjects.get(s.rowId);\n const sourceLabel = source && 'label' in source && typeof source.label === 'string' ? source.label : undefined;\n const rowLabel = s.kind === 'booth' ? undefined : sourceLabel;\n const labelParts = s.label.split('-');\n const seatNumber = rowLabel && s.label.startsWith(`${rowLabel}-`)\n ? s.label.slice(rowLabel.length + 1)\n : s.kind === 'booth'\n ? s.label\n : labelParts[labelParts.length - 1] ?? s.label;\n this.seatContext.set(s.id, {\n sectionLabel: sectionLabels.get(membership.objectToSection.get(s.rowId) ?? ''),\n rowLabel,\n seatNumber,\n });\n }\n\n // The organizer's currency travels with the chart payload; it wins over any\n // option passed at construction (the SDK host may not know it up front).\n const currency = res.event.currency ?? this.opts.currency;\n this.currency = currency ?? 'USD';\n const renderer = createRenderer(host, {\n maxSelection: this.maxSelection,\n confirmSelection: this.opts.confirmSelection,\n currency,\n onSelect: (seat) => {\n this.opts.onSelect?.(seat);\n this.emitSelectionChange();\n },\n onDeselect: (seat) => {\n this.opts.onDeselect?.(seat);\n this.emitSelectionChange();\n },\n onHover: (seat) => {\n this.opts.onHover?.(seat);\n if (this.opts.onSeatHover) this.opts.onSeatHover(seat ? this.describeSeat(seat) : null);\n },\n onFocusSeat: this.opts.onFocusSeat,\n onViewChange: this.opts.onViewChange,\n onGAClick: this.opts.onGAClick,\n // Section tap at the far/zone rung → glide in + surface the summary card.\n onSectionTap: (id) => this.handleSectionTap(id),\n onDeckTap: (floorId) => this.handleDeckTap(floorId),\n onFps: this.opts.onFps,\n });\n if (this.closed) {\n renderer.destroy(); // destroyed during createRenderer — don't leak the stage\n return null;\n }\n this.renderer = renderer;\n\n // Pull live state (seat statuses + hidden section/zone ids) BEFORE the first\n // paint so hidden sections never flash in. Falls back to the raw chart if the\n // snapshot is briefly unavailable — the WS re-snapshot then reconciles.\n let seats: Record<string, string> | null = null;\n let closedIds: string[] = [];\n try {\n const objs = await this.api.objects(this.key);\n this.hidden = new Set(objs.hidden ?? []);\n closedIds = (objs.closed ?? []).filter((x): x is string => typeof x === 'string');\n seats = objs.seats;\n } catch {\n /* transient — connect()'s onopen re-snapshots */\n }\n if (this.closed) {\n renderer.destroy();\n this.renderer = null;\n return null;\n }\n renderer.setChart(this.visibleDoc());\n if (this.opts.colorblindSafe) renderer.setColorblindSafe?.(true);\n // Closed sections are applied AFTER setChart (which resets state) so their\n // grey + non-pickable treatment lands on the first paint, no flash.\n this.closedSections = new Set(closedIds);\n if (closedIds.length) renderer.setClosedSections?.(closedIds);\n if (seats) this.applySeatsMap(seats);\n this.attachVisibilityListener();\n this.connect();\n return {\n doc: res.doc,\n salesClosed: !!res.event.salesClosed,\n eventName: res.event.name,\n venue: res.event.venue,\n startsAt: res.event.startsAt,\n currency,\n // 'test' ⇒ sandbox event: hosts render a TEST MODE ribbon (Phase 11).\n mode: res.event.mode ?? 'live',\n };\n }\n\n // ---- selection ------------------------------------------------------------\n\n getSelection(): PickerSeat[] {\n if (!this.renderer) return [];\n return this.renderer.getSelection().map((s) => this.toSeat(s));\n }\n /** Enriched metadata for a seat confirmation card or tooltip. */\n seatDetails(seatId: string): SeatHoverDetails | null {\n const seat = this.seatById.get(seatId);\n return seat ? this.describeSeat(seat) : null;\n }\n clearSelection(): void {\n this.renderer?.clearSelection();\n this.emitSelectionChange();\n }\n deselect(ids: string[]): void {\n this.renderer?.deselect(ids);\n this.emitSelectionChange();\n }\n\n // ---- booking machine ------------------------------------------------------\n\n /**\n * Hold the current selection (or a given label set). The controller does the\n * renderer/hold side (409 → deselect + repaint the taken seats held) and then\n * re-throws so the caller can choose the banner copy. Returns null only when\n * there's nothing to hold.\n */\n async hold(labelsArg?: string[], ttlMs?: number): Promise<HoldInfo | null> {\n const r = this.renderer;\n if (!r) return null;\n const labels = labelsArg ?? r.getSelection().map((s) => s.label);\n const existingGA = (this.hold_?.items ?? []).filter((item) => item.objectType === 'ga');\n const combinedLabels = [...new Set([...existingGA.map((item) => item.label), ...labels])];\n if (!combinedLabels.length) return null;\n\n // Reuse an existing hold that exactly covers this selection (re-holding 409s).\n if (this.hold_ && this.holdCovers(combinedLabels)) return this.hold_;\n try {\n const selections = combinedLabels.map((label) => {\n const ga = existingGA.find((item) => item.label === label);\n if (ga) return { label, tierId: ga.tierId };\n const seat = this.labelToSeat.get(label);\n const resolved = seat ? this.toSeat(seat) : null;\n return { label, ...(resolved?.tierId ? { tierId: resolved.tierId } : {}) };\n });\n const result = await this.api.hold(this.key, selections, ttlMs, this.hold_?.holdId);\n this.setHold({ holdId: result.holdId, labels: combinedLabels, expiresAt: result.expiresAt, items: result.items });\n return this.hold_;\n } catch (err) {\n this.handle409Conflicts(err);\n throw err;\n }\n }\n\n /** Restore an active server hold without creating or extending inventory. */\n async resumeHold(holdId: string): Promise<HoldInfo | null> {\n if (this.closed || !holdId || !this.api.resume) return null;\n const result = await this.api.resume(this.key, holdId);\n if (this.closed) return null;\n const labels = [...new Set(result.items.map((item) => item.label))];\n if (!labels.length) return null;\n this.setHold(\n { holdId: result.holdId, labels, expiresAt: result.expiresAt, items: result.items },\n 'restored',\n );\n return this.hold_;\n }\n\n /**\n * P4 \"need more time?\": extend the OPEN hold's server-side expiry and re-arm\n * the client expiry timer to match (via setHold), so the controller doesn't\n * fire a false expiry and start polling. Returns the new hold, or null if\n * there's no open hold or the transport can't extend / the server refused\n * (hold gone, expired, or at its renewal cap). Never throws for the refusal\n * case — the caller decides the copy.\n */\n async extendHold(ttlMs?: number): Promise<HoldInfo | null> {\n const current = this.hold_;\n if (!current || !this.api.extend) return null;\n try {\n const result = await this.api.extend(this.key, current.holdId, ttlMs);\n if (this.hold_?.holdId !== current.holdId) return this.hold_; // superseded meanwhile\n // Keep the same labels/items — only the expiry moved. setHold re-arms the timer.\n this.setHold({ holdId: current.holdId, labels: current.labels, expiresAt: result.expiresAt, items: current.items });\n return this.hold_;\n } catch {\n return null;\n }\n }\n\n /** Public GA inventory derived from the live synthetic-unit status stream. */\n /**\n * Live seats-left per category key (status 'free' right now). Recompute on\n * onStatusChange — this is what a price panel's \"N left\" counters read.\n */\n categoryAvailability(): Record<string, number> {\n const out: Record<string, number> = {};\n const closedMembers = this.closedMemberIds();\n for (const [id, s] of this.seatById) {\n if (closedMembers.has(id)) continue; // closed sections aren't on sale\n if ((this.getStatus(id) ?? 'free') === 'free') {\n out[s.categoryKey] = (out[s.categoryKey] ?? 0) + 1;\n }\n }\n return out;\n }\n\n /** Seat ids belonging to a currently-closed section (excluded from counts). */\n private closedMemberIds(): Set<string> {\n const out = new Set<string>();\n const r = this.renderer;\n if (!r || !this.closedSections.size) return out;\n for (const id of this.closedSections) for (const sid of (r.sectionMembers?.(id) ?? [])) out.add(sid);\n return out;\n }\n\n getGAAreas(): { id: string; label: string; capacity: number; available: number; categoryKey: string; price: number; currency: string; tiers?: CategoryTier[] }[] {\n const doc = this.visibleDoc();\n if (!doc) return [];\n return gaAreasOf(doc).map((area) => {\n const category = doc.categories.find((candidate) => candidate.key === area.categoryKey);\n return {\n id: area.id,\n label: area.label,\n capacity: Math.max(0, Math.floor(area.capacity)),\n available: gaUnitLabels(area).filter((label) => (this.liveStatuses.get(label) ?? 'free') === 'free').length,\n categoryKey: area.categoryKey,\n tiers: category?.tiers,\n price: category?.tiers?.[0]?.price ?? category?.price ?? 0,\n currency: this.currency,\n };\n });\n }\n\n /** Select a quantity from one GA area and hold it atomically. */\n async holdGA(\n areaId: string,\n qty: number,\n options: { tierId?: string | null; ttlMs?: number } = {},\n ): Promise<HoldInfo | null> {\n const doc = this.visibleDoc();\n if (!doc || !Number.isFinite(qty) || qty < 1) return null;\n const area = gaAreasOf(doc).find((candidate) => candidate.id === areaId);\n if (!area) return null;\n const labels = gaUnitLabels(area)\n .filter((label) => !this.hold_?.labels.includes(label) && (this.liveStatuses.get(label) ?? 'free') === 'free')\n .slice(0, Math.floor(qty));\n if (labels.length !== Math.floor(qty)) return null;\n const selections = new Map<string, { label: string; tierId?: string | null }>();\n for (const item of this.hold_?.items ?? []) selections.set(item.label, { label: item.label, tierId: item.tierId });\n if (this.hold_ && !this.hold_?.items?.length) {\n for (const seat of this.hold_.seats) selections.set(seat.label, { label: seat.label, ...(seat.tierId ? { tierId: seat.tierId } : {}) });\n }\n for (const seat of this.renderer?.getSelection() ?? []) {\n const resolved = this.labelToSeat.get(seat.label);\n const chosen = resolved ? this.toSeat(resolved) : null;\n selections.set(seat.label, { label: seat.label, ...(chosen?.tierId ? { tierId: chosen.tierId } : {}) });\n }\n for (const label of labels) selections.set(label, { label, ...(options.tierId ? { tierId: options.tierId } : {}) });\n const combined = [...selections.values()];\n const result = await this.api.hold(this.key, combined, options.ttlMs, this.hold_?.holdId);\n this.setHold({ holdId: result.holdId, labels: combined.map((s) => s.label), expiresAt: result.expiresAt, items: result.items });\n return this.hold_;\n }\n\n /** Server-picks `qty` best free seats and holds them atomically. Throws on failure. */\n async bestAvailable(qty: number, categoryKey?: string): Promise<HoldInfo | null> {\n const r = this.renderer;\n if (!r) return null;\n // Drop any prior auto-hold first.\n if (this.hold_ && !(await this.release())) return null;\n try {\n const result = await this.api.bestAvailable(this.key, qty, categoryKey);\n r.clearSelection();\n const ids = result.labels.map((l) => this.labelToId.get(l)).filter((v): v is string => !!v);\n if (ids.length) r.setStatus(ids, 'held');\n this.setHold({ holdId: result.holdId, labels: [...result.labels], expiresAt: result.expiresAt, items: result.items });\n const seats = result.labels\n .map((l) => this.labelToSeat.get(l))\n .filter((s): s is ExpandedSeat => !!s)\n .map((s) => this.toSeat(s));\n this.opts.onSelectionChange?.(seats);\n return this.hold_;\n } catch (err) {\n const { status, reason } = errInfo(err);\n if (status === 409 && reason === 'event_closed') this.opts.onSalesClosed?.();\n throw err;\n }\n }\n\n /**\n * Complete a booking. Requires a transport that supports book() (the SDK\n * deliberately does not). `bookingRef` MUST be a real reference from the caller.\n * `labelsArg` lets the caller book its own cart (the live page's confirm-flow\n * cart can hold best-available seats that aren't in the renderer selection);\n * defaults to the renderer selection. Reuses an existing exact-match hold, else\n * holds first. Returns the labels booked, or null on failure (conflicts painted).\n */\n async book(bookingRef: string, labelsArg?: string[]): Promise<string[] | null> {\n const r = this.renderer;\n if (!r) return null;\n if (!this.api.book) throw new Error('picker: transport has no book() — hold-only mode');\n const labels = labelsArg ?? r.getSelection().map((s) => s.label);\n if (!labels.length) return null;\n\n let holdId: string | undefined;\n try {\n if (this.hold_ && this.holdCovers(labels)) {\n holdId = this.hold_.holdId; // already held server-side — re-holding would 409\n } else {\n const replaceHoldId = this.hold_?.holdId;\n const h = await this.api.hold(\n this.key,\n labels.map((label) => {\n const seat = this.labelToSeat.get(label);\n const resolved = seat ? this.toSeat(seat) : null;\n return { label, ...(resolved?.tierId ? { tierId: resolved.tierId } : {}) };\n }),\n undefined,\n replaceHoldId,\n );\n holdId = h.holdId;\n this.setHold({ holdId, labels: [...labels], expiresAt: h.expiresAt, items: h.items });\n }\n await this.api.book(this.key, labels, holdId, bookingRef);\n } catch (err) {\n const { status, conflicts, reason } = errInfo(err);\n this.clearHold();\n if (status === 409 && reason === 'event_closed') {\n this.opts.onSalesClosed?.();\n } else if (status === 409 && conflicts?.length) {\n // Paint the taken seats, deselect them, release the still-free remainder.\n const takenLabels = new Set(conflicts.map((c) => c.label));\n const takenIds = [...takenLabels].map((l) => this.labelToId.get(l)).filter((v): v is string => !!v);\n if (takenIds.length) {\n r.setStatus(takenIds, 'booked');\n r.deselect(takenIds);\n }\n const stillFree = labels.filter((l) => !takenLabels.has(l));\n if (stillFree.length && holdId) void this.api.release(this.key, stillFree, holdId).catch(() => {});\n this.emitSelectionChange();\n } else if (holdId) {\n // Non-conflict failure after a hold landed — release it so seats aren't stranded.\n void this.api.release(this.key, labels, holdId).catch(() => {});\n }\n throw err;\n }\n // Success — optimistically paint booked, deselect just the booked seats\n // (not the whole selection — the cart may be an explicit subset), clear hold.\n const ids = labels.map((l) => this.labelToId.get(l)).filter((v): v is string => !!v);\n if (ids.length) {\n r.setStatus(ids, 'booked');\n r.deselect(ids);\n }\n this.clearHold();\n this.emitSelectionChange();\n this.opts.onBook?.(bookingRef);\n return labels;\n }\n\n /** Release the whole open hold (if any), repaint those seats free. */\n async release(): Promise<boolean> {\n const hold = this.hold_;\n if (!hold) return true;\n try {\n const result = await this.api.release(this.key, hold.labels, hold.holdId);\n if (!this.releaseConfirmed(result, hold.labels)) {\n await this.resnapshot();\n return false;\n }\n } catch (err) {\n this.emitError(err);\n return false;\n }\n if (this.hold_?.holdId !== hold.holdId) return true;\n this.clearHold();\n const ids = hold.labels.map((l) => this.labelToId.get(l)).filter((v): v is string => !!v);\n if (ids.length) {\n this.renderer?.deselect(ids);\n this.renderer?.setStatus(ids, 'free');\n }\n return true;\n }\n\n /**\n * Release just some labels from the open hold, keeping the rest held (used when\n * a buyer removes one seat chip). Clears the hold entirely once it empties.\n */\n async releaseLabels(labels: string[]): Promise<boolean> {\n const hold = this.hold_;\n if (!hold) return true;\n const drop = labels.filter((l) => hold.labels.includes(l));\n if (!drop.length) return true;\n try {\n const result = await this.api.release(this.key, drop, hold.holdId);\n if (!this.releaseConfirmed(result, drop)) {\n await this.resnapshot();\n return false;\n }\n } catch (err) {\n this.emitError(err);\n return false;\n }\n if (this.hold_?.holdId !== hold.holdId) return true;\n const remaining = hold.labels.filter((l) => !drop.includes(l));\n const remainingItems = hold.items?.filter((item) => !drop.includes(item.label));\n if (remaining.length) this.setHold({ ...hold, labels: remaining, items: remainingItems });\n else this.clearHold();\n const ids = drop.map((l) => this.labelToId.get(l)).filter((v): v is string => !!v);\n if (ids.length) {\n this.renderer?.deselect(ids);\n this.renderer?.setStatus(ids, 'free');\n }\n return true;\n }\n\n /** New transports return the exact labels released; tolerate older adapters. */\n private releaseConfirmed(result: unknown, requested: string[]): boolean {\n const released = (result as { released?: unknown } | null)?.released;\n return !Array.isArray(released) || requested.every((label) => released.includes(label));\n }\n\n // ---- renderer proxies (so consumers don't reach through) ------------------\n\n setStatus(ids: string[], status: SeatStatus): void {\n this.renderer?.setStatus(ids, status);\n }\n getStatus(id: string): SeatStatus | undefined {\n return this.renderer?.getStatus(id);\n }\n flashSeat(id: string, color?: string): void {\n this.renderer?.flashSeat(id, color);\n }\n zoomIn(): void {\n this.renderer?.zoomIn();\n }\n zoomOut(): void {\n this.renderer?.zoomOut();\n }\n zoomToFit(): void {\n this.renderer?.zoomToFit();\n }\n worldToScreen(p: { x: number; y: number }): { x: number; y: number } {\n return this.renderer?.worldToScreen(p) ?? { x: 0, y: 0 };\n }\n setSelectionFocus(seatId: string | null): void {\n this.renderer?.setSelectionFocus?.(seatId);\n }\n setAccessibilityFilter(types: string[] | null): void {\n this.renderer?.setAccessibilityFilter?.(types as never);\n }\n\n // ---- multi-floor (Batch 5) ------------------------------------------------\n\n /** Floors for the buyer's switcher (>1 ⇒ show it). Single-floor ⇒ one entry. */\n getFloors(): { id: string; name: string }[] {\n return this.renderer?.getFloors?.() ?? [];\n }\n getActiveFloorId(): string {\n return this.renderer?.getActiveFloorId?.() ?? '';\n }\n /** Switch the shown floor (2D), then re-apply live seat statuses onto it. */\n setFloor(id: string): void {\n const r = this.renderer;\n if (!r?.setActiveFloor || id === r.getActiveFloorId?.()) return;\n r.setStacked?.(false); // leaving any 3D stack — back to a single floor\n r.setActiveFloor(id);\n void this.resnapshot(); // re-paint statuses on the newly-rendered floor\n this.emitSelectionChange();\n }\n\n /** 3D all-floors stacked overview ⇄ active floor. Re-applies statuses after. */\n setStacked(on: boolean): void {\n const r = this.renderer;\n if (!r?.setStacked || on === r.isStacked?.()) return;\n r.setStacked(on);\n void this.resnapshot(); // re-paint statuses across the rebuilt view\n }\n isMultiFloor(): boolean {\n return (this._doc?.floors?.length ?? 0) > 1;\n }\n\n /** Tap-a-deck-to-enter: leave the 3D stack, drop to flat 2D on `floorId`, and\n * tell the host so it can sync its 2D/3D toggle + floor-switcher state. */\n private handleDeckTap(floorId: string): void {\n const r = this.renderer;\n if (!r) return;\n r.setViewMode?.('flat');\n r.setStacked?.(false);\n r.setActiveFloor?.(floorId);\n void this.resnapshot();\n this.emitSelectionChange();\n this.opts.onDeckTap?.(floorId);\n }\n\n // ---- big-venue: sections / rungs / projection (Slice 5) -------------------\n\n /** Switch the map projection (2D flat ⇄ 3D isometric). No-op on a flat renderer. */\n setViewMode(mode: 'flat' | 'isometric'): void {\n this.renderer?.setViewMode?.(mode);\n }\n getViewMode(): 'flat' | 'isometric' {\n return this.renderer?.getViewMode?.() ?? 'flat';\n }\n /** Current LOD rung (for the ZONES/SECTIONS/SEATS pill). */\n getRung(): LodRung {\n return this.renderer?.getRung?.() ?? 'seats';\n }\n /** Jump to a rung; ZONES clears any focused summary (back to overview). */\n setRung(rung: LodRung): void {\n if (rung === 'zones') {\n this.overview();\n return;\n }\n this.renderer?.setRung?.(rung);\n }\n\n /** Price-band filter (F4): dim free seats whose category is outside `keys`\n * (null clears). The widget resolves which categories fall in the band. */\n setCategoryFilter(keys: string[] | null): void {\n this.renderer?.setCategoryFilter?.(keys);\n }\n\n /** An explicit buyer price-filter action should not only dim the rest of the\n * chart: clear any older section drill-in and guide the camera to the seats\n * that remain relevant. Clearing the filter glides back to the full chart. */\n focusCategoryFilter(keys: string[] | null): void {\n const renderer = this.renderer;\n if (!renderer) return;\n renderer.clearSectionFocus?.();\n this.opts.onSectionFocus?.(null);\n if (renderer.focusCategories) renderer.focusCategories(keys);\n else renderer.zoomToFit();\n }\n\n /** World-space rect currently visible + full chart bounds (F3 minimap frame). */\n getViewport(): { visible: { x: number; y: number; width: number; height: number }; bounds: { x: number; y: number; width: number; height: number } } | null {\n const r = this.renderer;\n if (!r?.getVisibleWorldRect || !r.getWorldBounds) return null;\n return { visible: r.getVisibleWorldRect(), bounds: r.getWorldBounds() };\n }\n /** Glide in on a section and surface its summary (same path as a section tap). */\n focusSection(id: string): void {\n this.handleSectionTap(id);\n }\n /** Zoom back out to the whole chart and clear the section-summary card + focus. */\n overview(): void {\n this.renderer?.clearSectionFocus?.();\n this.renderer?.zoomToFit();\n this.opts.onSectionFocus?.(null);\n }\n\n /** Glide the camera into a tapped section and emit its computed summary. Uses\n * the AXS focus treatment (dim + backdrop) when the engine supports it; a\n * closed section is framed but never opens a buyer card. */\n private handleSectionTap(id: string): void {\n const r = this.renderer;\n if (!r) return;\n if (r.focusSection) r.focusSection(id);\n else r.focusRegion?.(id);\n if (this.isSectionClosed(id)) {\n this.opts.onSectionFocus?.(null); // closed: no purchase card\n return;\n }\n this.opts.onSectionFocus?.(this.sectionSummary(id));\n }\n\n /**\n * Build a section summary from the renderer's spatial membership: section +\n * zone labels, live seats-left, price range, and the per-category breakdown.\n */\n private sectionSummary(id: string): SectionSummary | null {\n const r = this.renderer;\n const doc = this._doc;\n if (!r || !doc) return null;\n const sec = doc.objects.find(\n (o): o is SectionObject => o.type === 'section' && o.id === id,\n );\n if (!sec) return null;\n\n const memberIds = r.sectionMembers?.(id) ?? [];\n const byCat = new Map<string, number>();\n let seatsLeft = 0;\n for (const sid of memberIds) {\n const seat = this.seatById.get(sid);\n if (!seat) continue;\n byCat.set(seat.categoryKey, (byCat.get(seat.categoryKey) ?? 0) + 1);\n if (r.getStatus(sid) === 'free') seatsLeft++;\n }\n\n const categories: SectionCategory[] = [...byCat.entries()]\n .map(([key, count]) => {\n const cat = doc.categories.find((c) => c.key === key);\n return {\n key,\n count,\n label: cat?.label ?? key,\n color: cat?.color ?? '#6e7bff',\n price: cat?.price ?? 0,\n };\n })\n .sort((a, b) => a.price - b.price);\n\n const prices = categories.map((c) => c.price);\n const zone = sec.zone ? doc.zones?.find((z) => z.id === sec.zone) : undefined;\n const color = sec.color ?? zone?.color ?? categories[0]?.color ?? '#6e7bff';\n\n return {\n id,\n label: sec.label,\n zoneLabel: zone?.label ?? '',\n color,\n seatsLeft,\n priceMin: prices.length ? prices[0] : 0,\n priceMax: prices.length ? prices[prices.length - 1] : 0,\n categories,\n };\n }\n\n destroy(): void {\n this.closed = true;\n this.detachVisibilityListener();\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = null;\n }\n if (this.expiryTimer) {\n clearTimeout(this.expiryTimer);\n this.expiryTimer = null;\n }\n if (this.ws) {\n try {\n this.ws.close();\n } catch {\n /* ignore */\n }\n this.ws = null;\n }\n this.renderer?.destroy();\n this.renderer = null;\n }\n\n // ---- internals ------------------------------------------------------------\n\n private toSeat(s: ExpandedSeat): PickerSeat {\n const tiers = this.tiersFor(s.categoryKey);\n if (!tiers) {\n return { id: s.id, label: s.label, categoryKey: s.categoryKey, price: this.priceFor(s.categoryKey) };\n }\n const chosen = tiers.find((t) => t.id === this.seatTiers.get(s.id)) ?? tiers[0];\n return {\n id: s.id,\n label: s.label,\n categoryKey: s.categoryKey,\n price: chosen.price,\n tiers,\n tierId: chosen.id,\n };\n }\n /** Tooltip payload for a hovered seat — see PickerCallbacks.onSeatHover. */\n private describeSeat(s: ExpandedSeat): SeatHoverDetails {\n const cat = this._doc?.categories.find((c) => c.key === s.categoryKey);\n return {\n ...this.toSeat(s),\n categoryLabel: cat?.label ?? s.categoryKey,\n categoryColor: cat?.color ?? '#6e7bff',\n status: this.renderer?.getStatus(s.id) ?? 'free',\n currency: this.currency,\n ...this.seatContext.get(s.id),\n };\n }\n\n private priceFor(categoryKey: string): number {\n return this._doc?.categories.find((c) => c.key === categoryKey)?.price ?? 0;\n }\n private tiersFor(categoryKey: string): CategoryTier[] | undefined {\n const t = this._doc?.categories.find((c) => c.key === categoryKey)?.tiers;\n return t && t.length ? t : undefined;\n }\n\n /**\n * Choose a ticket tier for a selected seat (e.g. Adult → Child). Re-emits the\n * selection so the host's cart + the eventual hold carry the new tier + price.\n * `tierId = null` reverts to the category's first (default) tier. No-op if the\n * seat's category has no tiers or the id isn't one of them.\n */\n setSeatTier(seatId: string, tierId: string | null): void {\n const seat = this.seatById.get(seatId);\n if (!seat) return;\n const tiers = this.tiersFor(seat.categoryKey);\n if (!tiers) return;\n if (tierId == null) this.seatTiers.delete(seatId);\n else if (tiers.some((t) => t.id === tierId)) this.seatTiers.set(seatId, tierId);\n else return;\n this.emitSelectionChange();\n if (this.hold_) this.hold_ = { ...this.hold_, seats: this.seatsForLabels(this.hold_.labels) };\n }\n\n /** PickerSeats (with chosen tier) for a set of held labels. */\n private seatsForLabels(labels: string[]): PickerSeat[] {\n const out: PickerSeat[] = [];\n for (const l of labels) {\n const s = this.labelToSeat.get(l);\n if (s) out.push(this.toSeat(s));\n }\n return out;\n }\n private emitSelectionChange(): void {\n this.opts.onSelectionChange?.(this.getSelection());\n this.emitOrphanHint();\n }\n\n /** Whether the last emitted hint was non-null (avoids clearing repeatedly). */\n private hintShown = false;\n\n /**\n * Orphan-seat advice on manual selection: when the buyer's current picks\n * strand one (or more) single free seats between unavailable same-row\n * neighbors, surface a localized, non-blocking hint. Cleared (null) as soon\n * as the selection stops stranding anyone.\n */\n private emitOrphanHint(): void {\n if (!this.opts.onHint) return;\n const r = this.renderer;\n if (!r) return;\n const selected = new Set(r.getSelection().map((s) => s.id));\n const stranded = selected.size\n ? strandedSingles(this.seatById.values(), (id) => r.getStatus(id), selected)\n : [];\n if (stranded.length > 0) {\n this.hintShown = true;\n this.opts.onHint(t('picker.orphanHint'));\n } else if (this.hintShown) {\n this.hintShown = false;\n this.opts.onHint(null);\n }\n }\n\n /** Toggle colorblind-safe rendering at runtime (see PickerOptions.colorblindSafe). */\n setColorblindSafe(on: boolean): void {\n this.renderer?.setColorblindSafe?.(on);\n }\n private emitError(err: unknown): void {\n if (this.opts.onError) this.opts.onError(err);\n else console.error('[picker]', err);\n }\n\n private holdCovers(labels: string[]): boolean {\n const h = this.hold_;\n if (!h || h.labels.length !== labels.length || !labels.every((l) => h.labels.includes(l))) return false;\n const tiers = new Map((h.items ?? []).map((item) => [item.label, item.tierId]));\n return labels.every((label) => {\n const seat = this.labelToSeat.get(label);\n const currentTier = seat ? this.toSeat(seat).tierId ?? null : null;\n return !tiers.has(label) || tiers.get(label) === currentTier;\n });\n }\n\n private handle409Conflicts(err: unknown): void {\n const { status, conflicts } = errInfo(err);\n if (status !== 409 || !conflicts?.length) return;\n const r = this.renderer;\n if (!r) return;\n const takenIds = conflicts.map((c) => this.labelToId.get(c.label)).filter((v): v is string => !!v);\n if (takenIds.length) {\n r.deselect(takenIds);\n r.setStatus(takenIds, 'held');\n }\n this.emitSelectionChange();\n }\n\n /** Set the open hold + (re)arm the server-authoritative expiry timer. */\n private setHold(\n hold: Omit<HoldInfo, 'seats'> & { seats?: PickerSeat[] },\n source: 'created' | 'restored' = 'created',\n ): void {\n // Always resolve seats (with chosen tier) from the held labels so the host's\n // onHold — and any later book — carries the tier the buyer picked per seat.\n const full: HoldInfo = { ...hold, seats: this.seatsForLabels(hold.labels) };\n this.hold_ = full;\n this.renderer?.setOwnedHold?.(\n full.labels.map((label) => this.labelToId.get(label)).filter((id): id is string => !!id),\n );\n if (this.expiryTimer) clearTimeout(this.expiryTimer);\n const ms = Math.max(0, full.expiresAt - Date.now());\n this.expiryTimer = setTimeout(() => void this.expireActiveHold(), ms);\n if (source === 'restored') this.opts.onHoldRestored?.(full);\n else this.opts.onHold?.(full);\n }\n private clearHold(): void {\n this.hold_ = null;\n this.renderer?.setOwnedHold?.(null);\n if (this.expiryTimer) {\n clearTimeout(this.expiryTimer);\n this.expiryTimer = null;\n }\n }\n private async expireActiveHold(): Promise<void> {\n const hold = this.hold_;\n if (!hold) return;\n try {\n const snap = await this.api.objects(this.key);\n if (this.hold_?.holdId !== hold.holdId) return;\n this.applySeatsMap(snap.seats);\n } catch {\n // Do not report expiry from a disconnected/stale client. Reconcile once\n // the authoritative snapshot becomes reachable.\n if (this.hold_?.holdId === hold.holdId) {\n this.expiryTimer = setTimeout(() => void this.expireActiveHold(), 2_000);\n }\n return;\n }\n if (this.hold_?.holdId !== hold.holdId) return; // booked snapshot cleared it\n if (hold.labels.some((label) => this.liveStatuses.get(label) === 'held')) {\n this.expiryTimer = setTimeout(() => void this.expireActiveHold(), 1_000);\n return;\n }\n this.clearHold();\n this.opts.onHoldExpired?.();\n }\n\n private applySeatsMap(seats: Record<string, string>): void {\n const r = this.renderer;\n if (!r) return;\n this.liveStatuses = new Map(Object.entries(seats));\n if (this.allIds.length) r.setStatus(this.allIds, 'free');\n // setChart() rebuilds renderer state (floor/hidden-section changes), so\n // restore the buyer-ownership layer before repainting held statuses.\n r.setOwnedHold?.(\n (this.hold_?.labels ?? [])\n .map((label) => this.labelToId.get(label))\n .filter((id): id is string => !!id),\n );\n const byStatus: Record<SeatStatus, string[]> = { free: [], held: [], booked: [], not_for_sale: [] };\n for (const [label, st] of Object.entries(seats)) {\n const id = this.labelToId.get(label);\n if (id) byStatus[mapStatus(st)].push(id);\n }\n (['held', 'booked', 'not_for_sale'] as SeatStatus[]).forEach((st) => {\n if (byStatus[st].length) r.setStatus(byStatus[st], st);\n });\n this.opts.onStatusChange?.();\n this.clearBookedHoldIfSettled();\n }\n\n private clearBookedHoldIfSettled(): void {\n if (this.hold_?.labels.every((label) => this.liveStatuses.get(label) === 'booked')) this.clearHold();\n }\n\n private async resnapshot(): Promise<void> {\n try {\n const objs = await this.api.objects(this.key);\n this.applySeatsMap(objs.seats);\n } catch {\n /* transient — the socket delta stream keeps us fresh */\n }\n }\n\n // ---- realtime socket ------------------------------------------------------\n\n /**\n * Buyer catch-up on tab regain. While a tab is hidden Chrome pauses rAF, so\n * seat-status deltas that arrived over the WS mutated the scene graph but the\n * canvas colors never repainted. When the tab becomes visible again we (1)\n * resnapshot to pull authoritative state for anything the socket may have\n * missed while backgrounded, then (2) forceDraw() a synchronous repaint so the\n * seat colors are correct immediately rather than on the next incidental draw.\n *\n * Attached once per mount; guarded against double-attach and non-DOM\n * environments; detached in destroy() (no leaks).\n */\n private attachVisibilityListener(): void {\n if (this.onVisibilityChange) return; // already attached (guard double mount)\n if (typeof document === 'undefined' || typeof document.addEventListener !== 'function') return;\n const handler = (): void => {\n if (this.closed) return;\n if (document.visibilityState !== 'visible') return;\n // Re-fetch authoritative state, then paint it synchronously.\n void this.resnapshot().then(() => {\n if (!this.closed) this.renderer?.forceDraw();\n });\n };\n this.onVisibilityChange = handler;\n document.addEventListener('visibilitychange', handler);\n }\n\n private detachVisibilityListener(): void {\n if (!this.onVisibilityChange) return;\n if (typeof document !== 'undefined' && typeof document.removeEventListener === 'function') {\n document.removeEventListener('visibilitychange', this.onVisibilityChange);\n }\n this.onVisibilityChange = null;\n }\n\n private connect(): void {\n if (this.closed) return;\n let ws: WebSocket;\n try {\n ws = new WebSocket(this.api.socketUrl(this.key));\n } catch {\n this.scheduleReconnect();\n return;\n }\n this.ws = ws;\n\n ws.onopen = () => {\n this.attempt = 0;\n void this.resnapshot();\n };\n ws.onmessage = (e) => {\n let msg: unknown;\n try {\n msg = JSON.parse(typeof e.data === 'string' ? e.data : '');\n } catch {\n return;\n }\n const r = this.renderer;\n if (!r || !msg || typeof msg !== 'object') return;\n const m = msg as { type?: string; hidden?: string[]; closed?: string[]; seats?: Record<string, string>; changes?: { label: string; status: string }[] };\n // Reconcile hidden sections whenever they arrive (dedicated 'hidden' message\n // OR a snapshot that carries them). Only rebuilds the chart when it changed.\n if (Array.isArray(m.hidden) && this.syncHidden(m.hidden)) {\n void this.resnapshot(); // repaint statuses onto the rebuilt chart\n this.opts.onStatusChange?.();\n }\n // Reconcile closed sections (Phase 2). Cheap grey restyle, no chart rebuild —\n // so flipping a section open/closed mid-sale repaints for connected buyers.\n if (Array.isArray(m.closed) && this.syncClosed(m.closed)) {\n this.opts.onStatusChange?.();\n }\n if (m.type === 'hidden') return; // dedicated hidden message carries no seats\n if (m.seats && typeof m.seats === 'object') {\n this.applySeatsMap(m.seats);\n } else if (Array.isArray(m.changes)) {\n for (const ch of m.changes) {\n this.liveStatuses.set(ch.label, ch.status);\n const id = this.labelToId.get(ch.label);\n if (!id) continue;\n const next = mapStatus(ch.status);\n // Flash a live free→taken change — but not the buyer's OWN just-held\n // seats (a manual hold leaves them 'free' locally, so the server's\n // held-delta would otherwise flash them as if someone else grabbed them).\n if (\n this.opts.flashOnLiveChange &&\n next !== 'free' &&\n r.getStatus(id) === 'free' &&\n !this.hold_?.labels.includes(ch.label)\n ) {\n // Pulse color mirrors the manager board's status language:\n // amber for a hold landing, red for a booking.\n r.flashSeat(id, next === 'held' ? '#f4b740' : '#f43f5e');\n }\n r.setStatus([id], next);\n }\n // Stay-live-while-hidden (opt-in, default OFF). setStatus paints via\n // batchDraw (rAF), which Chrome pauses on a hidden tab — so an always-on\n // board (the future organizer control room) would freeze while\n // backgrounded. When enabled, force a synchronous repaint so a hidden\n // board keeps painting. The buyer widget leaves this off and relies on\n // the visibilitychange catch-up instead.\n if (\n this.opts.keepLiveWhileHidden &&\n typeof document !== 'undefined' &&\n document.visibilityState === 'hidden'\n ) {\n r.forceDraw();\n }\n this.clearBookedHoldIfSettled();\n this.opts.onStatusChange?.();\n }\n };\n ws.onclose = () => {\n if (this.ws === ws) this.ws = null;\n this.scheduleReconnect();\n };\n ws.onerror = () => {\n try {\n ws.close();\n } catch {\n /* onclose drives reconnect */\n }\n };\n }\n\n private scheduleReconnect(): void {\n if (this.closed || this.reconnectTimer) return;\n const attempt = Math.min(this.attempt++, 5);\n const delay = Math.min(1000 * 2 ** attempt, MAX_BACKOFF_MS);\n this.reconnectTimer = setTimeout(() => {\n this.reconnectTimer = null;\n this.connect();\n }, delay);\n }\n}\n","/**\n * Synthetic view-from-seat panorama, generated from chart geometry alone.\n *\n * Draws a 2048×1024 equirectangular texture of a dark hall with the stage\n * placed at the correct bearing and angular size for THIS seat — closer seats\n * see a bigger stage, off-center seats see it at an angle. Used whenever the\n * organizer hasn't uploaded a real photo/360 for the seat; both go through the\n * same viewer.\n *\n * Equirectangular mapping: x = (yaw + 180°)/360° · W, y = (90° − pitch)/180° · H,\n * where yaw 0 = the direction the camera faces by default.\n */\n\nimport type { ExpandedSeat, Point } from '../core/types';\n\nconst W = 2048;\nconst H = 1024;\n/** Chart units → meters, for plausible eye-level proportions (seatSpacing 24 ≈ 0.55m). */\nconst UNIT = 0.55 / 24;\n\nconst yawToX = (yawDeg: number) => ((yawDeg + 180) / 360) * W;\nconst pitchToY = (pitchDeg: number) => ((90 - pitchDeg) / 180) * H;\n\nexport interface PanoramaResult {\n url: string;\n /** Meters from the stage, for the caption. */\n distanceM: number;\n}\n\nexport function generateSeatPanorama(\n seat: ExpandedSeat,\n focalPoint: Point,\n neighborSeats: ExpandedSeat[],\n): PanoramaResult {\n const canvas = document.createElement('canvas');\n canvas.width = W;\n canvas.height = H;\n const ctx = canvas.getContext('2d')!;\n\n const dx = focalPoint.x - seat.x;\n const dy = focalPoint.y - seat.y;\n const distU = Math.hypot(dx, dy);\n const distM = Math.max(2, distU * UNIT);\n\n // ---- room shell: ceiling → walls → floor -------------------------------\n const sky = ctx.createLinearGradient(0, 0, 0, H);\n sky.addColorStop(0, '#05070c');\n sky.addColorStop(0.42, '#11172a');\n sky.addColorStop(0.5, '#1a2238');\n sky.addColorStop(0.56, '#10141f');\n sky.addColorStop(1, '#07090f');\n ctx.fillStyle = sky;\n ctx.fillRect(0, 0, W, H);\n\n // ---- stage, centered at yaw 0 (the viewer opens facing it) -------------\n // Angular size from real proportions: stage ~8m wide, ~1m platform + 6m set.\n const stageHalfYaw = Math.min(80, (Math.atan2(4, distM) * 180) / Math.PI);\n const stageTopPitch = Math.min(45, (Math.atan2(5, distM) * 180) / Math.PI);\n const stageBasePitch = Math.max(-30, (-Math.atan2(1.1, distM) * 180) / Math.PI);\n\n const sx0 = yawToX(-stageHalfYaw);\n const sx1 = yawToX(stageHalfYaw);\n const sy0 = pitchToY(stageTopPitch);\n const sy1 = pitchToY(stageBasePitch);\n\n // glow behind the stage\n const glow = ctx.createRadialGradient(W / 2, (sy0 + sy1) / 2, 10, W / 2, (sy0 + sy1) / 2, (sx1 - sx0) * 1.1);\n glow.addColorStop(0, 'rgba(129, 140, 248, 0.5)');\n glow.addColorStop(0.5, 'rgba(99, 102, 241, 0.16)');\n glow.addColorStop(1, 'rgba(99, 102, 241, 0)');\n ctx.fillStyle = glow;\n ctx.fillRect(sx0 - (sx1 - sx0) * 0.6, sy0 - (sy1 - sy0) * 1.2, (sx1 - sx0) * 2.2, (sy1 - sy0) * 3.4);\n\n // stage box + lit backdrop\n ctx.fillStyle = '#242c44';\n ctx.fillRect(sx0, sy0, sx1 - sx0, sy1 - sy0);\n const backdrop = ctx.createLinearGradient(0, sy0, 0, sy1);\n backdrop.addColorStop(0, '#7c5cff');\n backdrop.addColorStop(0.5, '#e1447a');\n backdrop.addColorStop(1, '#f59e0b');\n ctx.globalAlpha = 0.75;\n ctx.fillStyle = backdrop;\n const inset = (sx1 - sx0) * 0.06;\n ctx.fillRect(sx0 + inset, sy0 + (sy1 - sy0) * 0.12, sx1 - sx0 - inset * 2, (sy1 - sy0) * 0.62);\n ctx.globalAlpha = 1;\n // stage lip\n ctx.fillStyle = '#0d1119';\n ctx.fillRect(sx0, sy1 - (sy1 - sy0) * 0.1, sx1 - sx0, (sy1 - sy0) * 0.1);\n\n // performer silhouettes, scaled by distance\n const performerH = (sy1 - sy0) * 0.45;\n ctx.fillStyle = 'rgba(8, 10, 16, 0.85)';\n for (const fx of [0.35, 0.5, 0.65]) {\n const px = sx0 + (sx1 - sx0) * fx;\n const py = sy1 - (sy1 - sy0) * 0.12;\n ctx.beginPath();\n ctx.arc(px, py - performerH * 0.82, performerH * 0.16, 0, Math.PI * 2); // head\n ctx.fill();\n ctx.fillRect(px - performerH * 0.14, py - performerH * 0.68, performerH * 0.28, performerH * 0.68); // body\n }\n\n // spotlight beams from above the stage\n ctx.globalAlpha = 0.14;\n ctx.fillStyle = '#c7d2fe';\n for (const fx of [0.3, 0.5, 0.7]) {\n const bx = sx0 + (sx1 - sx0) * fx;\n ctx.beginPath();\n ctx.moveTo(bx - 8, pitchToY(Math.min(60, stageTopPitch + 25)));\n ctx.lineTo(bx - (sx1 - sx0) * 0.09, sy1);\n ctx.lineTo(bx + (sx1 - sx0) * 0.09, sy1);\n ctx.lineTo(bx + 8, pitchToY(Math.min(60, stageTopPitch + 25)));\n ctx.closePath();\n ctx.fill();\n }\n ctx.globalAlpha = 1;\n\n // ---- rig lights along the ceiling all around ---------------------------\n ctx.fillStyle = 'rgba(199, 210, 254, 0.8)';\n for (let i = 0; i < 26; i++) {\n const x = (i / 26) * W;\n const y = pitchToY(55 + (i % 3) * 6);\n ctx.beginPath();\n ctx.arc(x, y, 3.2, 0, Math.PI * 2);\n ctx.fill();\n }\n\n // ---- audience: heads of nearby seats, at their true bearings -----------\n // Bearing relative to the stage direction so yaw 0 keeps facing the stage.\n const stageBearing = Math.atan2(dx, -dy); // screen coords, -y is \"up\" the hall\n ctx.fillStyle = 'rgba(16, 20, 30, 0.95)';\n for (const other of neighborSeats) {\n if (other.id === seat.id) continue;\n const ox = other.x - seat.x;\n const oy = other.y - seat.y;\n const d = Math.hypot(ox, oy) * UNIT;\n if (d < 0.3 || d > 14) continue;\n const bearing = Math.atan2(ox, -oy) - stageBearing;\n const yaw = ((((bearing * 180) / Math.PI + 540) % 360) - 180);\n const headPitch = (-Math.atan2(0.35, d) * 180) / Math.PI; // heads slightly below eye level\n const headR = Math.min(46, 260 / (d / UNIT / 24 + 1.2) / 4);\n const hx = yawToX(yaw);\n const hy = pitchToY(headPitch);\n ctx.beginPath();\n ctx.arc(hx, hy, headR, 0, Math.PI * 2);\n ctx.fill();\n ctx.beginPath(); // shoulders\n ctx.ellipse(hx, hy + headR * 1.4, headR * 1.7, headR * 0.9, 0, Math.PI, 0, true);\n ctx.fill();\n }\n\n // subtle vignette at the poles (hides equirect pinching)\n const poleFade = ctx.createLinearGradient(0, 0, 0, H);\n poleFade.addColorStop(0, 'rgba(0,0,0,0.85)');\n poleFade.addColorStop(0.12, 'rgba(0,0,0,0)');\n poleFade.addColorStop(0.88, 'rgba(0,0,0,0)');\n poleFade.addColorStop(1, 'rgba(0,0,0,0.85)');\n ctx.fillStyle = poleFade;\n ctx.fillRect(0, 0, W, H);\n\n return { url: canvas.toDataURL('image/jpeg', 0.82), distanceM: Math.round(distM) };\n}\n\n// ---------------------------------------------------------------------------\n// Compact forward-view thumbnail — a cheap (480×270) rectilinear preview of\n// what this seat faces, for inline display inside the buyer's confirm card.\n// Unlike the full equirectangular panorama it maps a ~100°×60° forward field\n// of view directly (no 360 squish), so it reads as a real POV at a glance and\n// costs a fraction of the full render. Same geometry → the two stay consistent.\n// ---------------------------------------------------------------------------\n\nconst TW = 480;\nconst TH = 270;\nconst HALF_HFOV = 50; // degrees left/right of the stage direction\nconst HALF_VFOV = 30; // degrees up/down of the horizon\n\nconst yawToTX = (yawDeg: number) => ((yawDeg + HALF_HFOV) / (2 * HALF_HFOV)) * TW;\nconst pitchToTY = (pitchDeg: number) => ((HALF_VFOV - pitchDeg) / (2 * HALF_VFOV)) * TH;\n\nexport function generateSeatThumb(seat: ExpandedSeat, focalPoint: Point, _neighborSeats?: ExpandedSeat[]): PanoramaResult {\n const canvas = document.createElement('canvas');\n canvas.width = TW;\n canvas.height = TH;\n const ctx = canvas.getContext('2d')!;\n\n const dx = focalPoint.x - seat.x;\n const dy = focalPoint.y - seat.y;\n const distM = Math.max(2, Math.hypot(dx, dy) * UNIT);\n\n // hall shell (ceiling → wall → floor), horizon at mid-height\n const sky = ctx.createLinearGradient(0, 0, 0, TH);\n sky.addColorStop(0, '#05070c');\n sky.addColorStop(0.44, '#141b30');\n sky.addColorStop(0.5, '#1b2440');\n sky.addColorStop(0.58, '#10141f');\n sky.addColorStop(1, '#070910');\n ctx.fillStyle = sky;\n ctx.fillRect(0, 0, TW, TH);\n\n // stage geometry (identical formulas to the full panorama)\n const stageHalfYaw = Math.min(HALF_HFOV - 2, (Math.atan2(4, distM) * 180) / Math.PI);\n const stageTopPitch = Math.min(HALF_VFOV - 2, (Math.atan2(5, distM) * 180) / Math.PI);\n const stageBasePitch = Math.max(-HALF_VFOV + 2, (-Math.atan2(1.1, distM) * 180) / Math.PI);\n const sx0 = yawToTX(-stageHalfYaw);\n const sx1 = yawToTX(stageHalfYaw);\n const sy0 = pitchToTY(stageTopPitch);\n const sy1 = pitchToTY(stageBasePitch);\n const sw = sx1 - sx0;\n const sh = sy1 - sy0;\n\n // glow\n const glow = ctx.createRadialGradient(TW / 2, (sy0 + sy1) / 2, 4, TW / 2, (sy0 + sy1) / 2, sw * 1.1);\n glow.addColorStop(0, 'rgba(129,140,248,0.5)');\n glow.addColorStop(0.5, 'rgba(99,102,241,0.15)');\n glow.addColorStop(1, 'rgba(99,102,241,0)');\n ctx.fillStyle = glow;\n ctx.fillRect(sx0 - sw * 0.6, sy0 - sh * 1.2, sw * 2.2, sh * 3.4);\n\n // stage box + lit backdrop + lip\n ctx.fillStyle = '#242c44';\n ctx.fillRect(sx0, sy0, sw, sh);\n const backdrop = ctx.createLinearGradient(0, sy0, 0, sy1);\n backdrop.addColorStop(0, '#7c5cff');\n backdrop.addColorStop(0.5, '#e1447a');\n backdrop.addColorStop(1, '#f59e0b');\n ctx.globalAlpha = 0.78;\n ctx.fillStyle = backdrop;\n const inset = sw * 0.06;\n ctx.fillRect(sx0 + inset, sy0 + sh * 0.12, sw - inset * 2, sh * 0.62);\n ctx.globalAlpha = 1;\n ctx.fillStyle = '#0d1119';\n ctx.fillRect(sx0, sy1 - sh * 0.1, sw, sh * 0.1);\n\n // performer silhouettes\n const ph = sh * 0.45;\n ctx.fillStyle = 'rgba(8,10,16,0.85)';\n for (const fx of [0.35, 0.5, 0.65]) {\n const px = sx0 + sw * fx;\n const py = sy1 - sh * 0.12;\n ctx.beginPath();\n ctx.arc(px, py - ph * 0.82, ph * 0.16, 0, Math.PI * 2);\n ctx.fill();\n ctx.fillRect(px - ph * 0.14, py - ph * 0.68, ph * 0.28, ph * 0.68);\n }\n\n // spotlight beams\n ctx.globalAlpha = 0.15;\n ctx.fillStyle = '#c7d2fe';\n for (const fx of [0.3, 0.5, 0.7]) {\n const bx = sx0 + sw * fx;\n ctx.beginPath();\n ctx.moveTo(bx - 5, pitchToTY(Math.min(HALF_VFOV, stageTopPitch + 18)));\n ctx.lineTo(bx - sw * 0.09, sy1);\n ctx.lineTo(bx + sw * 0.09, sy1);\n ctx.lineTo(bx + 5, pitchToTY(Math.min(HALF_VFOV, stageTopPitch + 18)));\n ctx.closePath();\n ctx.fill();\n }\n ctx.globalAlpha = 1;\n\n // a few rig lights across the ceiling\n ctx.fillStyle = 'rgba(199,210,254,0.75)';\n for (let i = 0; i < 8; i++) {\n ctx.beginPath();\n ctx.arc(((i + 0.5) / 8) * TW, pitchToTY(HALF_VFOV - 4 - (i % 2) * 3), 2.2, 0, Math.PI * 2);\n ctx.fill();\n }\n\n // seat-back rows in the foreground for depth\n ctx.fillStyle = 'rgba(10,13,20,0.9)';\n ctx.fillRect(0, TH - 26, TW, 26);\n ctx.fillStyle = 'rgba(30,37,54,0.9)';\n for (let i = 0; i < 9; i++) ctx.fillRect(i * (TW / 9) + 6, TH - 22, TW / 9 - 12, 14);\n\n return { url: canvas.toDataURL('image/jpeg', 0.8), distanceM: Math.round(distM) };\n}\n","/**\n * Locale bundle loader — keeps non-English translations OUT of the initial\n * bundle (the 60 KB SDK budget is a product contract) and code-splits each\n * locale so a page/SDK only downloads the language it actually uses.\n *\n * `loadLocale('de')` dynamic-imports the German dictionary, registers it via\n * setLocale(), and resolves once it's active. English is built in, so\n * `loadLocale('en')` is synchronous and never fetches. Unknown/unsupported\n * codes fall back to English without throwing.\n */\nimport { setLocale, resolveLocale, type Dict, type Locale } from './index';\n\n/** Dynamic importers per non-English locale (English ships in the core). */\nconst LOADERS: Record<Exclude<Locale, 'en'>, () => Promise<{ default: Dict }>> = {\n es: () => import('./locales/es').then((m) => ({ default: m.es })),\n de: () => import('./locales/de').then((m) => ({ default: m.de })),\n fr: () => import('./locales/fr').then((m) => ({ default: m.fr })),\n};\n\nconst loaded = new Set<Locale>(['en']);\n\n/**\n * Resolve `code` to a supported locale, load its bundle if needed, and make it\n * active. Returns the locale that ended up active (English on any failure).\n */\nexport async function loadLocale(code?: string | null): Promise<Locale> {\n const locale = resolveLocale(code);\n if (locale === 'en' || loaded.has(locale)) {\n setLocale(locale);\n return locale;\n }\n try {\n const mod = await LOADERS[locale]();\n setLocale(locale, mod.default);\n loaded.add(locale);\n return locale;\n } catch {\n setLocale('en');\n return 'en';\n }\n}\n"],"mappings":"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","names":["t","objects","t","KImage","t"]}
|