@seatlayer/js 0.7.3 → 0.9.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 +474 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +104 -3
- package/dist/index.d.ts +104 -3
- package/dist/index.js +477 -8
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/SeatingChart.ts","../src/api.ts","../src/EmbeddedDesigner.ts","../src/SeatPicker.ts"],"sourcesContent":["/**\n * @seatlayer/js — the framework-agnostic SeatLayer embed SDK.\n *\n * Works in any JS environment (plain HTML, React, Vue, Svelte, Angular, …).\n * Framework wrappers (@seatlayer/react, …) build on top of this.\n */\nexport { SeatingChart } from './SeatingChart';\nexport type { SeatingChartOptions, SelectedSeat, GAAreaAvailability } from './SeatingChart';\nexport { ApiError } from './api';\nexport type { HoldResult, HoldConflict, HoldLineItem, BestAvailableResult } from './api';\nexport { EmbeddedDesigner } from './EmbeddedDesigner';\nexport type {\n EmbeddedDesignerOptions,\n EmbeddedDesignerMessage,\n EmbeddedDesignerEventType,\n} from './EmbeddedDesigner';\nexport type { SeatHoverDetails } from '@seatlayer/core';\nexport { SeatPicker } from './SeatPicker';\nexport type { SeatPickerOptions, SeatPickerTheme } from './SeatPicker';\n","/**\n * SeatingChart — the embeddable buyer picker.\n *\n * A thin wrapper over the shared PickerController (src/picker/PickerController):\n * it owns the mount <div> + the public embed contract (hold-only — the SDK hands\n * the holdId to the host page for a server-side book) and delegates all transport\n * + booking to the controller, so the SDK inherits every fix made for the live\n * buyer page and the demo picker.\n */\nimport { PickerController, loadLocale, setStringOverrides, t, type PickerSeat, type SeatHoverDetails } from '@seatlayer/core';\nimport { PubApi, type BestAvailableResult, type HoldResult } from './api';\n\nconst DEFAULT_API_BASE = 'https://api.seatlayer.io';\nconst DEFAULT_MAX_SELECTION = 10;\n\n/** A seat as surfaced to the host page (prices resolved from the chart's categories). */\nexport type SelectedSeat = PickerSeat;\nexport interface GAAreaAvailability {\n id: string; label: string; capacity: number; available: number; categoryKey: string; price: number; currency: string;\n tiers?: Array<{ id: string; name: string; price: number }>;\n}\n\nexport interface SeatingChartOptions {\n /** CSS selector or an HTMLElement to render into. */\n container: string | HTMLElement;\n /** Event key, e.g. `ev_xxx`. */\n event: string;\n /** API origin. Defaults to https://api.seatlayer.io. */\n apiBase?: string;\n /** Reserved for future authenticated rendering — accepted + stored, not yet sent. */\n publicKey?: string;\n /** Max seats selectable at once (default 10). */\n maxSelection?: number;\n /**\n * BCP 47 language for the widget UI — `'de'`, `'es-MX'`, etc. Falls back to\n * the browser language, then English. Built-in: en, es, de, fr. The German\n * bundle (etc.) is fetched on demand so unused languages cost nothing.\n */\n locale?: string;\n /**\n * Per-key string overrides layered over the active locale — white-label copy\n * without shipping a whole bundle, e.g. `{ 'map.fromPrice': 'ab {price}' }`.\n */\n messages?: Record<string, string>;\n /** ISO 4217 currency for on-map prices (default USD). */\n currency?: string;\n /**\n * Colorblind-safe rendering: category hues switch to an Okabe-Ito palette\n * and booked seats render hollow, so state never relies on hue alone.\n * Toggleable later with setColorblindSafe().\n */\n colorblindSafe?: boolean;\n /**\n * Built-in seat tooltip on mouse hover (seat · category · price · status).\n * Rendered inside the widget so every host gets it; default true. Turn off\n * to draw your own popover from onSeatHover.\n */\n seatTooltip?: boolean;\n /**\n * Seat hover with everything a popover needs (category label/color, resolved\n * tier-aware price, live status, currency); null on hover-out. Fires whether\n * or not the built-in tooltip is enabled.\n */\n onSeatHover?: (details: SeatHoverDetails | null) => void;\n onSelectionChange?: (seats: SelectedSeat[]) => void;\n onHold?: (result: HoldResult) => void;\n onHoldExpired?: () => void;\n onGAClick?: (area: GAAreaAvailability) => void;\n onError?: (err: unknown) => void;\n /**\n * Multi-floor charts only: fires when the buyer taps a deck in the stacked\n * 3D view, after the picker switches to that floor — lets the host page sync\n * its own floor UI (tabs, labels) with the map.\n */\n onDeckTap?: (floorId: string) => void;\n /**\n * Non-blocking, localized selection advice — currently the orphan-seat hint\n * (the selection would strand a single free seat between taken neighbors).\n * `null` clears it. Purely informational; nothing is ever prevented.\n */\n onHint?: (message: string | null) => void;\n}\n\nfunction resolveContainer(container: string | HTMLElement): HTMLElement {\n if (typeof container === 'string') {\n const el = document.querySelector(container);\n if (!el) throw new Error(`seatmap: container \"${container}\" not found`);\n return el as HTMLElement;\n }\n if (!(container instanceof HTMLElement)) {\n throw new Error('seatmap: container must be a CSS selector or an HTMLElement');\n }\n return container;\n}\n\nexport class SeatingChart {\n private readonly opts: SeatingChartOptions;\n private readonly controller: PickerController;\n /** Reserved for future authenticated rendering — stored, not yet sent on any request. */\n readonly publicKey?: string;\n\n private mount: HTMLElement | null = null;\n private hostEl: HTMLDivElement | null = null;\n private rendered = false;\n private tipEl: HTMLDivElement | null = null;\n private tipPos = { x: 0, y: 0 };\n private onTipMove: ((e: MouseEvent) => void) | null = null;\n\n constructor(options: SeatingChartOptions) {\n if (!options || typeof options !== 'object') throw new Error('seatmap: options object is required');\n if (!options.container) throw new Error('seatmap: `container` is required');\n if (!options.event || typeof options.event !== 'string') throw new Error('seatmap: `event` key is required');\n\n this.opts = options;\n this.publicKey = options.publicKey;\n const api = new PubApi((options.apiBase ?? DEFAULT_API_BASE).replace(/\\/+$/, ''));\n this.controller = new PickerController({\n transport: api,\n eventKey: options.event,\n maxSelection: options.maxSelection ?? DEFAULT_MAX_SELECTION,\n currency: options.currency,\n onSelectionChange: (seats) => this.opts.onSelectionChange?.(seats),\n onHold: (h) => this.opts.onHold?.({ holdId: h.holdId, expiresAt: h.expiresAt, seats: h.seats, items: h.items }),\n onHoldExpired: () => this.opts.onHoldExpired?.(),\n onGAClick: (areaId) => {\n const area = this.controller.getGAAreas().find((candidate) => candidate.id === areaId);\n if (area) this.opts.onGAClick?.(area);\n },\n onError: (err) => this.opts.onError?.(err),\n onDeckTap: (floorId) => this.opts.onDeckTap?.(floorId),\n onHint: (message) => this.opts.onHint?.(message),\n // Live-activity cue: pulse seats that other buyers take while the map is\n // open — the WS feed already streams the status change, this makes it felt.\n flashOnLiveChange: true,\n onSeatHover: (details) => {\n this.opts.onSeatHover?.(details);\n if (this.opts.seatTooltip !== false) this.updateTooltip(details);\n },\n colorblindSafe: options.colorblindSafe,\n });\n }\n\n /** Fetch the chart, mount the renderer, seed statuses and go live. Idempotent. */\n async render(): Promise<this> {\n if (this.rendered) return this;\n this.rendered = true;\n\n // Resolve + load the UI language before the first paint so on-map labels\n // (\"N LEFT\", \"FROM …\", the map aria-label) render translated. English and\n // already-loaded locales resolve synchronously; others fetch one small chunk.\n await loadLocale(this.opts.locale);\n if (this.opts.messages) setStringOverrides(this.opts.messages);\n\n // Mount an owned <div> inside the caller's container so we never fight their\n // layout and can cleanly remove it on destroy().\n this.mount = resolveContainer(this.opts.container);\n const host = document.createElement('div');\n host.style.width = '100%';\n host.style.height = '100%';\n host.style.position = 'relative';\n this.mount.appendChild(host);\n this.hostEl = host;\n\n const info = await this.controller.render(host);\n if (!info) {\n this.rendered = false;\n return this;\n }\n\n // Tooltip element + cursor tracking (mouse only — touch selects directly and\n // reviews seats in the host tray). Positioned at the cursor, flipped at edges.\n // Appended AFTER controller.render — mounting the canvas replaces the host's\n // prior children, so anything added earlier would be wiped.\n if (this.opts.seatTooltip !== false) {\n const tip = document.createElement('div');\n tip.setAttribute('role', 'tooltip');\n tip.style.cssText =\n 'position:absolute;z-index:7;pointer-events:none;display:none;max-width:240px;' +\n 'background:#10162a;color:#fff;border-radius:10px;padding:9px 12px;' +\n 'font:500 12px/1.45 -apple-system,BlinkMacSystemFont,\"Segoe UI\",sans-serif;' +\n 'box-shadow:0 10px 30px -10px rgba(0,0,0,.5);';\n host.appendChild(tip);\n this.tipEl = tip;\n this.onTipMove = (e: MouseEvent) => {\n const r = host.getBoundingClientRect();\n this.tipPos = { x: e.clientX - r.left, y: e.clientY - r.top };\n if (this.tipEl && this.tipEl.style.display !== 'none') this.placeTooltip();\n };\n host.addEventListener('mousemove', this.onTipMove);\n }\n if (info.mode === 'test') {\n host.style.overflow = 'hidden';\n const ribbon = document.createElement('div');\n ribbon.textContent = t('picker.testMode');\n ribbon.setAttribute('aria-label', t('picker.testMode'));\n ribbon.style.cssText =\n 'position:absolute;top:18px;right:-34px;z-index:6;transform:rotate(45deg);' +\n 'width:140px;text-align:center;padding:4px 0;background:#f4b740;color:#1a1200;' +\n 'font:800 10.5px/1.4 -apple-system,BlinkMacSystemFont,sans-serif;letter-spacing:.12em;' +\n 'box-shadow:0 2px 8px rgba(0,0,0,.25);pointer-events:none;';\n host.appendChild(ribbon);\n }\n return this;\n }\n\n private placeTooltip(): void {\n if (!this.tipEl || !this.hostEl) return;\n const hw = this.hostEl.clientWidth;\n const tw = this.tipEl.offsetWidth;\n const th = this.tipEl.offsetHeight;\n let x = this.tipPos.x + 14;\n let y = this.tipPos.y - th - 12;\n if (x + tw > hw - 8) x = this.tipPos.x - tw - 14;\n if (y < 8) y = this.tipPos.y + 18;\n this.tipEl.style.left = `${Math.max(8, x)}px`;\n this.tipEl.style.top = `${Math.max(8, y)}px`;\n }\n\n private updateTooltip(details: SeatHoverDetails | null): void {\n if (!this.tipEl) return;\n if (!details) {\n this.tipEl.style.display = 'none';\n return;\n }\n const money = (() => {\n try {\n return new Intl.NumberFormat(undefined, { style: 'currency', currency: details.currency }).format(details.price);\n } catch {\n return `${details.price} ${details.currency}`;\n }\n })();\n const statusLine =\n details.status === 'free'\n ? ''\n : `<div style=\"margin-top:5px;font-size:10.5px;letter-spacing:.08em;text-transform:uppercase;color:#fca5a5;font-weight:700\">${\n details.status === 'held' ? t('map.statusHeld') : t('map.statusTaken')\n }</div>`;\n this.tipEl.innerHTML =\n `<div style=\"font-weight:700;font-size:13px\">${details.label}</div>` +\n `<div style=\"display:flex;align-items:center;gap:6px;margin-top:4px;color:#c7cddc\">` +\n `<span style=\"width:9px;height:9px;border-radius:50%;flex:none;background:${details.categoryColor}\"></span>` +\n `<span>${details.categoryLabel}</span>` +\n `<span style=\"margin-left:auto;font-weight:700;color:#fff\">${money}</span></div>` +\n statusLine;\n this.tipEl.style.display = 'block';\n this.placeTooltip();\n }\n\n /** Current selection with prices resolved from the chart categories. */\n getSelection(): SelectedSeat[] {\n return this.controller.getSelection();\n }\n\n /** Hold the current selection. Resolves the hold, or null on a 409 conflict. */\n async hold(options: { ttlMs?: number } = {}): Promise<HoldResult | null> {\n try {\n const h = await this.controller.hold(undefined, options.ttlMs);\n return h ? { holdId: h.holdId, expiresAt: h.expiresAt, seats: h.seats, items: h.items } : null;\n } catch (err) {\n this.opts.onError?.(err);\n return null;\n }\n }\n\n getGAAreas(): GAAreaAvailability[] {\n return this.controller.getGAAreas();\n }\n\n async holdGA(\n areaId: string,\n qty: number,\n options: { tierId?: string | null; ttlMs?: number } = {},\n ): Promise<HoldResult | null> {\n try {\n const h = await this.controller.holdGA(areaId, qty, options);\n return h ? { holdId: h.holdId, expiresAt: h.expiresAt, seats: h.seats, items: h.items } : null;\n } catch (err) {\n this.opts.onError?.(err);\n return null;\n }\n }\n\n /** Ask the server for the `qty` best free seats and hold them atomically. */\n async bestAvailable(qty: number, categoryKey?: string): Promise<BestAvailableResult | null> {\n try {\n const h = await this.controller.bestAvailable(qty, categoryKey);\n return h ? { holdId: h.holdId, expiresAt: h.expiresAt, labels: h.labels, seats: h.seats, items: h.items } : null;\n } catch (err) {\n this.opts.onError?.(err);\n return null;\n }\n }\n\n /**\n * Choose a ticket tier for a selected seat (e.g. Adult → Child). The seat's\n * available `tiers` are on each `SelectedSeat` from `getSelection()` /\n * `onSelectionChange`. Re-emits the selection with the new tier + price, and\n * the tier rides along in the next `hold()` / `onHold` per seat. `tierId=null`\n * reverts to the default tier.\n */\n setSeatTier(seatId: string, tierId: string | null): void {\n this.controller.setSeatTier(seatId, tierId);\n }\n\n /**\n * Floors of a multi-floor chart — `[{ id, name }]` (single-floor charts\n * return one entry; empty before render()). Pair with setFloor() to build a\n * host-side floor switcher.\n */\n getFloors(): { id: string; name: string }[] {\n return this.controller.getFloors();\n }\n\n /** Switch the shown floor (2D). Warns + no-ops on single-floor charts. */\n setFloor(floorId: string): void {\n if (this.controller.getFloors().length <= 1) {\n console.warn('seatmap: setFloor() ignored — this chart has a single floor');\n return;\n }\n this.controller.setFloor(floorId);\n }\n\n /** Toggle colorblind-safe rendering at runtime (see options.colorblindSafe). */\n setColorblindSafe(on: boolean): void {\n this.controller.setColorblindSafe(on);\n }\n\n /** Zoom in one step (same increment as the wheel/pinch gesture). */\n zoomIn(): void {\n this.controller.zoomIn();\n }\n\n /** Zoom out one step. */\n zoomOut(): void {\n this.controller.zoomOut();\n }\n\n /** Reset the camera so the whole chart fits the container. */\n zoomToFit(): void {\n this.controller.zoomToFit();\n }\n\n /** Release the current hold (if any). No-op when nothing is held. */\n async release(): Promise<void> {\n await this.controller.release();\n }\n\n /** Tear everything down: close the socket, stop timers, drop the canvas. */\n destroy(): void {\n if (this.hostEl && this.onTipMove) this.hostEl.removeEventListener('mousemove', this.onTipMove);\n this.tipEl = null;\n this.onTipMove = null;\n this.controller.destroy();\n if (this.hostEl && this.hostEl.parentNode) this.hostEl.parentNode.removeChild(this.hostEl);\n this.hostEl = null;\n this.mount = null;\n this.rendered = false;\n }\n}\n","/**\n * Minimal client for the public embed surface of workers/api (the `/pub/*`\n * routes). Deliberately self-contained — it does NOT reuse src/lib/api.ts,\n * which bakes in a build-time API base and dashboard session credentials. The\n * SDK runs cross-origin on a third-party ticketing page, so:\n * - apiBase is per-instance (constructor option), not a build constant;\n * - credentials are omitted (no cookie to send, avoids CORS-credential setup);\n * - no custom headers on mutating calls (keeps the CORS preflight trivial).\n */\nimport type { ChartDoc, PickerSeat as SelectedSeat } from '@seatlayer/core';\n\nexport interface HoldConflict {\n label: string;\n status: string;\n}\n\nexport interface HoldLineItem {\n label: string; objectId: string; objectType: 'seat' | 'booth' | 'ga'; categoryKey: string;\n tierId: string | null;\n /** Price in major currency units (for example 45 means $45.00). */\n unitPrice: number;\n currency: string;\n quantity?: number;\n}\n\nexport class ApiError extends Error {\n status: number;\n code?: string;\n /** Present when a hold 409s because seats were just taken/held. */\n conflicts?: HoldConflict[];\n /** Present when best-available 409s ('not_enough_together' | 'sold_out'). */\n reason?: string;\n\n constructor(status: number, message: string, code?: string, conflicts?: HoldConflict[], reason?: string) {\n super(message);\n this.name = 'ApiError';\n this.status = status;\n this.code = code;\n this.conflicts = conflicts;\n this.reason = reason;\n }\n}\n\nexport interface PubChartResult {\n event: { key: string; name: string };\n doc: ChartDoc;\n}\n\nexport interface PubObjectsResult {\n /** Every non-free seat's status, keyed by seat label. */\n seats: Record<string, string>;\n updatedAt: number;\n}\n\nexport interface HoldResult {\n holdId: string;\n expiresAt: number;\n /** The held seats with the buyer's chosen ticket tier per seat (present on hold). */\n seats?: SelectedSeat[];\n items?: HoldLineItem[];\n}\n\n/** Best-available response — the server-picked seats plus the hold they landed in. */\nexport interface BestAvailableResult {\n holdId: string;\n expiresAt: number;\n labels: string[];\n seats?: SelectedSeat[];\n items?: HoldResult['items'];\n}\n\nasync function request<T>(\n base: string,\n path: string,\n init: { method?: 'GET' | 'POST'; body?: unknown } = {},\n): Promise<T> {\n const method = init.method ?? 'GET';\n const headers: Record<string, string> = {};\n let body: string | undefined;\n if (init.body !== undefined) {\n headers['Content-Type'] = 'application/json';\n body = JSON.stringify(init.body);\n }\n\n const res = await fetch(`${base}${path}`, { method, headers, body, credentials: 'omit' });\n\n const isJson = (res.headers.get('content-type') ?? '').includes('application/json');\n const data = isJson ? await res.json().catch(() => null) : null;\n\n if (!res.ok) {\n const err = data as\n | { error?: string; code?: string; conflicts?: HoldConflict[]; reason?: string }\n | null;\n throw new ApiError(res.status, err?.error ?? `request_failed_${res.status}`, err?.code, err?.conflicts, err?.reason);\n }\n return data as T;\n}\n\n/** Public-surface client bound to one apiBase (e.g. https://api.seatlayer.io). */\nexport class PubApi {\n constructor(private readonly base: string) {}\n\n chart(key: string): Promise<PubChartResult> {\n return request(this.base, `/pub/events/${encodeURIComponent(key)}/chart`);\n }\n\n objects(key: string): Promise<PubObjectsResult> {\n return request(this.base, `/pub/events/${encodeURIComponent(key)}/objects`);\n }\n\n hold(key: string, selections: Array<{ label: string; tierId?: string | null }>, ttlMs?: number, replaceHoldId?: string): Promise<HoldResult> {\n return request(this.base, `/pub/events/${encodeURIComponent(key)}/hold`, {\n method: 'POST',\n body: { selections, ...(ttlMs ? { ttlMs } : {}), ...(replaceHoldId ? { replaceHoldId } : {}) },\n });\n }\n\n bestAvailable(key: string, qty: number, categoryKey?: string): Promise<BestAvailableResult> {\n return request(this.base, `/pub/events/${encodeURIComponent(key)}/best-available`, {\n method: 'POST',\n body: { qty, ...(categoryKey ? { categoryKey } : {}) },\n });\n }\n\n release(key: string, labels: string[], holdId: string): Promise<{ ok: true }> {\n return request(this.base, `/pub/events/${encodeURIComponent(key)}/release`, {\n method: 'POST',\n body: { labels, holdId },\n });\n }\n\n socketUrl(key: string): string {\n const wsBase = this.base.replace(/^http/, 'ws');\n return `${wsBase}/pub/events/${encodeURIComponent(key)}/subscribe`;\n }\n}\n","/**\n * A secure, framework-neutral host for the SeatLayer chart Designer.\n *\n * The Designer remains an iframe so a platform never gives its SeatLayer secret\n * key to a browser. This class owns the iframe lifecycle and accepts messages\n * only from that iframe's exact origin.\n */\nexport type EmbeddedDesignerEventType =\n | 'seatlayer.designer.ready'\n | 'seatlayer.designer.saved'\n | 'seatlayer.designer.published'\n | 'seatlayer.designer.close'\n | 'seatlayer.designer.error';\n\nexport interface EmbeddedDesignerMessage {\n type: EmbeddedDesignerEventType;\n chartId?: string;\n workspaceId?: string;\n expiresAt?: number;\n code?: string;\n message?: string;\n meta?: unknown;\n}\n\nexport interface EmbeddedDesignerOptions {\n /** The short-lived URL returned by your backend's Designer-session call. */\n designerUrl: string;\n /** CSS selector or element where the iframe is mounted. */\n container: string | HTMLElement;\n /** Verify the message belongs to the chart your backend opened. */\n expectedChartId?: string;\n /** Verify the message belongs to the workspace your backend opened. */\n expectedWorkspaceId?: string;\n title?: string;\n className?: string;\n style?: Partial<CSSStyleDeclaration>;\n allow?: string;\n referrerPolicy?: ReferrerPolicy;\n onReady?: (message: EmbeddedDesignerMessage) => void;\n onSaved?: (message: EmbeddedDesignerMessage) => void;\n onPublished?: (message: EmbeddedDesignerMessage) => void;\n onClose?: (message: EmbeddedDesignerMessage) => void;\n onError?: (message: EmbeddedDesignerMessage) => void;\n}\n\nconst TYPES = new Set<EmbeddedDesignerEventType>([\n 'seatlayer.designer.ready',\n 'seatlayer.designer.saved',\n 'seatlayer.designer.published',\n 'seatlayer.designer.close',\n 'seatlayer.designer.error',\n]);\n\nfunction resolveContainer(container: string | HTMLElement): HTMLElement {\n if (typeof container !== 'string') return container;\n const element = document.querySelector<HTMLElement>(container);\n if (!element) throw new Error(`EmbeddedDesigner container not found: ${container}`);\n return element;\n}\n\n/** Mount, replace, and destroy a scoped Designer iframe safely. */\nexport class EmbeddedDesigner {\n private options: EmbeddedDesignerOptions;\n private frame: HTMLIFrameElement | null = null;\n private designerOrigin = '';\n\n constructor(options: EmbeddedDesignerOptions) {\n this.options = options;\n }\n\n mount(): HTMLIFrameElement {\n this.destroy();\n const url = new URL(this.options.designerUrl, window.location.href);\n if (url.protocol !== 'https:' && url.hostname !== 'localhost' && url.hostname !== '127.0.0.1') {\n throw new Error('EmbeddedDesigner requires an HTTPS designerUrl outside local development.');\n }\n this.designerOrigin = url.origin;\n\n const frame = document.createElement('iframe');\n frame.title = this.options.title ?? 'Venue chart Designer';\n frame.allow = this.options.allow ?? 'clipboard-write';\n frame.referrerPolicy = this.options.referrerPolicy ?? 'origin';\n frame.src = url.toString();\n frame.style.width = '100%';\n frame.style.height = '100%';\n frame.style.border = '0';\n Object.assign(frame.style, this.options.style);\n if (this.options.className) frame.className = this.options.className;\n\n window.addEventListener('message', this.handleMessage);\n resolveContainer(this.options.container).append(frame);\n this.frame = frame;\n return frame;\n }\n\n /** Replace the iframe instead of assigning a new fragment to an existing one. */\n setDesignerUrl(designerUrl: string): HTMLIFrameElement {\n this.options = { ...this.options, designerUrl };\n return this.mount();\n }\n\n getIframe(): HTMLIFrameElement | null {\n return this.frame;\n }\n\n destroy(): void {\n window.removeEventListener('message', this.handleMessage);\n this.frame?.remove();\n this.frame = null;\n this.designerOrigin = '';\n }\n\n private handleMessage = (event: MessageEvent<unknown>) => {\n if (!this.frame || event.origin !== this.designerOrigin || event.source !== this.frame.contentWindow) return;\n if (!event.data || typeof event.data !== 'object') return;\n const data = event.data as Record<string, unknown>;\n if (typeof data.type !== 'string' || !TYPES.has(data.type as EmbeddedDesignerEventType)) return;\n\n const message: EmbeddedDesignerMessage = {\n type: data.type as EmbeddedDesignerEventType,\n chartId: typeof data.chartId === 'string' ? data.chartId : undefined,\n workspaceId: typeof data.workspaceId === 'string' ? data.workspaceId : undefined,\n expiresAt: typeof data.expiresAt === 'number' ? data.expiresAt : undefined,\n code: typeof data.code === 'string' ? data.code : undefined,\n message: typeof data.message === 'string' ? data.message : undefined,\n meta: data.meta,\n };\n if (this.options.expectedChartId && message.chartId && message.chartId !== this.options.expectedChartId) return;\n if (this.options.expectedWorkspaceId && message.workspaceId && message.workspaceId !== this.options.expectedWorkspaceId) return;\n\n switch (message.type) {\n case 'seatlayer.designer.ready': this.options.onReady?.(message); break;\n case 'seatlayer.designer.saved': this.options.onSaved?.(message); break;\n case 'seatlayer.designer.published': this.options.onPublished?.(message); break;\n case 'seatlayer.designer.close': this.options.onClose?.(message); break;\n case 'seatlayer.designer.error': this.options.onError?.(message); break;\n }\n };\n}\n","/**\n * SeatPicker — the full buyer experience as a widget.\n *\n * Where `SeatingChart` is canvas-only, SeatPicker owns the complete chrome\n * from the canonical UX (SeatmapUX/11 Buyer Picker.dc.html): branded header,\n * live price panel, selection tray with GA steppers, hold countdown, snipe\n * toasts and expiry recovery — all on top of the shared PickerController, so\n * every host gets the whole experience with one mount.\n *\n * Render contexts (owner requirement): the SAME widget adapts to a full-screen\n * takeover, an inline <div> in a content page, or a popup — breakpoints key\n * off the CONTAINER via ResizeObserver, never the viewport. `SeatPicker.open()`\n * mounts a document-level modal (scrim, ESC, focus restore) in one call.\n *\n * Theming (owner requirement): org account customization flows automatically —\n * the chart payload's ChartTheme (accent, accentInk, logoUrl, brand name,\n * fontFamily, …) seeds the look; the host `theme` option overrides any subset;\n * and every value lands as a `--sl-*` CSS custom property on the widget root\n * so plain host CSS can restyle too.\n */\nimport {\n PickerController,\n expandChart,\n loadLocale,\n setStringOverrides,\n t,\n type AccessibilityType,\n type ChartTheme,\n type ExpandedSeat,\n type PickerSeat,\n type SeatHoverDetails,\n} from '@seatlayer/core';\nimport { PubApi, type HoldResult } from './api';\nimport type { GAAreaAvailability } from './SeatingChart';\n\nconst DEFAULT_API_BASE = 'https://api.seatlayer.io';\nconst DEFAULT_MAX_SELECTION = 10;\n\n/** Host theme overrides — any subset; unset keys fall back to the org's chart theme, then defaults. */\nexport interface SeatPickerTheme {\n /** Brand accent (CTA, active chips, hold pill). */\n accent?: string;\n /** Ink on the accent (button labels). */\n accentInk?: string;\n /** Widget background. */\n background?: string;\n /** Panel/card surface color. */\n surface?: string;\n /** Primary text color. */\n text?: string;\n /** Secondary text color. */\n muted?: string;\n /** Hairline/border color. */\n line?: string;\n /** Font stack for all widget chrome. */\n fontFamily?: string;\n /** Corner radius base (px). */\n radius?: number;\n /** Header logo URL (falls back to the org logo from the chart theme, then a monogram). */\n logoUrl?: string;\n /** Brand/event fallback name for the monogram. */\n brandName?: string;\n}\n\nexport interface SeatPickerOptions {\n /** CSS selector or element to mount into. Omit when using SeatPicker.open(). */\n container?: string | HTMLElement;\n /** Event key, e.g. `ev_xxx`. */\n event: string;\n /** API origin. Defaults to https://api.seatlayer.io. */\n apiBase?: string;\n /** Reserved for future authenticated rendering. */\n publicKey?: string;\n /** Max seats selectable at once (default 10). */\n maxSelection?: number;\n /** BCP 47 language for the widget UI. Built-in: en, es, de, fr. */\n locale?: string;\n /** Per-key string overrides layered over the active locale. */\n messages?: Record<string, string>;\n /** ISO 4217 currency fallback (the org/event currency on the chart wins). */\n currency?: string;\n /** Colorblind-safe rendering (Okabe-Ito palette, hollow booked seats). */\n colorblindSafe?: boolean;\n /** Host theme overrides — see SeatPickerTheme. */\n theme?: SeatPickerTheme;\n /** Hold TTL in ms passed to hold(); server clamps to its own limits. */\n holdTtlMs?: number;\n /**\n * Confirm mode: tapping a seat shows an anchored popover (seat · category ·\n * price · Add/Cancel) instead of adding straight to the tray. Default false.\n */\n confirmSelection?: boolean;\n /**\n * Buyer pressed the CTA and the hold succeeded — hand off to YOUR checkout.\n * The hold carries holdId, expiresAt, seat labels and priced line items.\n */\n onCheckout?: (hold: HoldResult, seats: PickerSeat[]) => void;\n /** Selection changed (tap or best-available). */\n onSelectionChange?: (seats: PickerSeat[]) => void;\n /** The open hold expired server-side (widget already reset itself). */\n onHoldExpired?: () => void;\n /** Modal only: the buyer closed the picker (ESC / scrim / ✕). */\n onClose?: () => void;\n onError?: (err: unknown) => void;\n}\n\nfunction resolveContainer(container: string | HTMLElement): HTMLElement {\n if (typeof container === 'string') {\n const el = document.querySelector(container);\n if (!el) throw new Error(`seatmap: container \"${container}\" not found`);\n return el as HTMLElement;\n }\n if (!(container instanceof HTMLElement)) {\n throw new Error('seatmap: container must be a CSS selector or an HTMLElement');\n }\n return container;\n}\n\n/** Widget stylesheet — injected once per document. Every color/font/radius is a --sl-* token. */\nconst STYLE_ID = 'seatlayer-picker-style';\nconst CSS = `\n.sl-picker{position:relative;display:flex;flex-direction:column;width:100%;height:100%;min-height:420px;overflow:hidden;\n background:var(--sl-bg);color:var(--sl-text);font-family:var(--sl-font);border-radius:var(--sl-radius);\n --sl-r-sm:calc(var(--sl-radius) * .55)}\n.sl-picker *{box-sizing:border-box;margin:0;padding:0}\n.sl-picker button{font:inherit;color:inherit;background:none;border:0;cursor:pointer}\n\n/* header */\n.sl-head{display:flex;align-items:center;gap:12px;padding:12px 16px;border-bottom:1px solid var(--sl-line);flex:none}\n.sl-logo{width:34px;height:34px;border-radius:9px;flex:none;display:flex;align-items:center;justify-content:center;\n background:var(--sl-accent);color:var(--sl-accent-ink);font-weight:800;font-size:15px;overflow:hidden}\n.sl-logo img{width:100%;height:100%;object-fit:cover;display:block}\n.sl-head-info{min-width:0;flex:1}\n.sl-head-name{font-weight:700;font-size:15px;line-height:1.2;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n.sl-head-meta{font-size:10px;letter-spacing:.1em;text-transform:uppercase;color:var(--sl-muted);margin-top:3px;\n white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-weight:600}\n.sl-hold-pill{display:none;align-items:center;gap:6px;padding:6px 12px;border-radius:999px;flex:none;\n background:var(--sl-accent);color:var(--sl-accent-ink);font-weight:700;font-size:12px;font-variant-numeric:tabular-nums}\n.sl-hold-pill.on{display:inline-flex}\n.sl-close{width:32px;height:32px;border-radius:999px;flex:none;display:none;align-items:center;justify-content:center;\n border:1px solid var(--sl-line);color:var(--sl-muted);transition:color .15s,border-color .15s}\n.sl-close:hover{color:var(--sl-text);border-color:var(--sl-muted)}\n.sl-close.on{display:inline-flex}\n.sl-close svg{width:14px;height:14px;stroke:currentColor;stroke-width:2;fill:none;stroke-linecap:round}\n\n/* body */\n.sl-body{display:flex;flex:1;min-height:0}\n.sl-map{position:relative;flex:1;min-width:0}\n.sl-map-host{position:absolute;inset:0}\n.sl-side{width:300px;flex:none;border-left:1px solid var(--sl-line);display:flex;flex-direction:column;min-height:0;overflow-y:auto}\n\n/* narrow (container < 640px): side panel becomes a bottom sheet */\n.sl-picker[data-layout=\"narrow\"] .sl-body{flex-direction:column}\n.sl-picker[data-layout=\"narrow\"] .sl-map{min-height:0;flex:1}\n.sl-picker[data-layout=\"narrow\"] .sl-side{width:100%;max-height:46%;border-left:0;border-top:1px solid var(--sl-line)}\n.sl-picker[data-layout=\"narrow\"] .sl-tray{flex:none}\n.sl-picker[data-layout=\"narrow\"] .sl-foot{position:sticky;bottom:0;background:var(--sl-bg)}\n\n/* price panel */\n.sl-sec{padding:14px 16px 4px;font-size:9.5px;letter-spacing:.14em;text-transform:uppercase;color:var(--sl-muted);font-weight:700}\n.sl-prices{padding:4px 16px 10px;border-bottom:1px solid var(--sl-line)}\n.sl-price-row{display:flex;align-items:center;gap:8px;padding:5px 0;font-size:13px}\n.sl-dot{width:9px;height:9px;border-radius:50%;flex:none}\n.sl-price-label{flex:1;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-weight:600}\n.sl-price-left{font-size:11px;color:var(--sl-muted);font-variant-numeric:tabular-nums}\n.sl-price-amt{font-weight:800;font-variant-numeric:tabular-nums}\n\n/* tray */\n.sl-tray{flex:1;padding:10px 16px;display:flex;flex-direction:column;gap:8px;min-height:0}\n.sl-tray-hint{font-size:12.5px;color:var(--sl-muted);line-height:1.5}\n.sl-chip{display:flex;align-items:center;gap:9px;padding:9px 11px;border:1px solid var(--sl-line);\n border-radius:var(--sl-r-sm);background:var(--sl-surface);font-size:13px}\n.sl-chip b{font-weight:800}\n.sl-chip .cat{color:var(--sl-muted);font-size:11.5px;flex:1;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n.sl-chip .amt{font-weight:700;font-variant-numeric:tabular-nums}\n.sl-chip .rm{width:22px;height:22px;border-radius:999px;flex:none;display:flex;align-items:center;justify-content:center;color:var(--sl-muted)}\n.sl-chip .rm:hover{color:var(--sl-text)}\n.sl-chip .rm svg{width:11px;height:11px;stroke:currentColor;stroke-width:2.4;fill:none;stroke-linecap:round}\n\n/* GA rows */\n.sl-ga{display:flex;align-items:center;gap:10px;padding:9px 11px;border:1px dashed var(--sl-line);border-radius:var(--sl-r-sm)}\n.sl-ga-info{flex:1;min-width:0}\n.sl-ga-name{font-weight:700;font-size:13px}\n.sl-ga-sub{font-size:11px;color:var(--sl-muted);margin-top:2px}\n.sl-ga-qty{display:flex;align-items:center;gap:8px}\n.sl-ga-qty button{width:26px;height:26px;border-radius:999px;background:var(--sl-surface);border:1px solid var(--sl-line);\n font-size:15px;font-weight:700;display:flex;align-items:center;justify-content:center;transition:border-color .15s}\n.sl-ga-qty button:hover{border-color:var(--sl-muted)}\n.sl-ga-qty span{min-width:16px;text-align:center;font-weight:800;font-variant-numeric:tabular-nums}\n\n/* footer */\n.sl-foot{padding:12px 16px 14px;border-top:1px solid var(--sl-line);flex:none}\n.sl-total{display:flex;justify-content:space-between;align-items:center;font-size:13px;margin-bottom:10px}\n.sl-total b{font-size:17px;font-variant-numeric:tabular-nums}\n.sl-cta{width:100%;padding:13px;border-radius:var(--sl-r-sm);font-weight:800;font-size:14px;\n background:var(--sl-accent);color:var(--sl-accent-ink);transition:filter .15s,opacity .15s}\n.sl-cta:hover{filter:brightness(1.08)}\n.sl-cta:disabled{opacity:.45;cursor:not-allowed}\n\n/* zoom column */\n.sl-zoom{position:absolute;right:12px;bottom:12px;display:flex;flex-direction:column;gap:6px;z-index:5}\n.sl-zoom button{width:36px;height:36px;border-radius:999px;background:var(--sl-surface);border:1px solid var(--sl-line);\n color:var(--sl-text);font-size:17px;font-weight:700;display:flex;align-items:center;justify-content:center;transition:border-color .15s}\n.sl-zoom button:hover{border-color:var(--sl-muted)}\n.sl-zoom svg{width:14px;height:14px;stroke:currentColor;stroke-width:2;fill:none;stroke-linecap:round;stroke-linejoin:round}\n\n/* toast + boot states */\n.sl-toast{position:absolute;left:50%;bottom:16px;transform:translateX(-50%) translateY(6px);z-index:8;max-width:88%;\n background:var(--sl-surface);border:1px solid var(--sl-line);color:var(--sl-text);border-radius:999px;padding:9px 16px;\n font-size:12.5px;font-weight:600;opacity:0;pointer-events:none;transition:opacity .2s,transform .2s;white-space:nowrap;\n overflow:hidden;text-overflow:ellipsis}\n.sl-toast.on{opacity:1;transform:translateX(-50%) translateY(0)}\n.sl-boot{position:absolute;inset:0;z-index:6;display:flex;flex-direction:column;align-items:center;justify-content:center;\n gap:10px;background:var(--sl-bg);font-size:13px;font-weight:600;color:var(--sl-muted)}\n.sl-boot-spin{width:24px;height:24px;border-radius:50%;border:3px solid var(--sl-line);border-top-color:var(--sl-accent);\n animation:slspin .8s linear infinite}\n@keyframes slspin{to{transform:rotate(360deg)}}\n.sl-boot-title{font-weight:800;font-size:15px;color:var(--sl-text)}\n.sl-boot-retry{margin-top:4px;padding:9px 20px;border-radius:var(--sl-r-sm);background:var(--sl-accent);\n color:var(--sl-accent-ink);font-weight:700;font-size:13px}\n\n/* a11y filter chips (over the map, top-left) */\n.sl-chips{position:absolute;top:12px;left:12px;z-index:5;display:flex;gap:6px;flex-wrap:wrap;max-width:70%}\n.sl-chip-f{display:inline-flex;align-items:center;gap:6px;padding:7px 12px;border-radius:999px;font-size:12px;font-weight:700;\n background:var(--sl-surface);border:1px solid var(--sl-line);color:var(--sl-muted);transition:color .15s,border-color .15s}\n.sl-chip-f:hover{color:var(--sl-text)}\n.sl-chip-f.on{background:var(--sl-accent);color:var(--sl-accent-ink);border-color:transparent}\n\n/* confirm popover */\n.sl-confirm{position:absolute;z-index:9;min-width:190px;background:var(--sl-surface);border:1px solid var(--sl-line);\n border-radius:12px;padding:12px;box-shadow:0 18px 50px -18px rgba(0,0,0,.7);transform:translate(-50%,calc(-100% - 14px))}\n.sl-confirm-label{font-weight:800;font-size:14px}\n.sl-confirm-meta{display:flex;align-items:center;gap:6px;font-size:12px;color:var(--sl-muted);margin-top:4px}\n.sl-confirm-meta b{color:var(--sl-text);margin-left:auto}\n.sl-confirm-row{display:flex;gap:8px;margin-top:10px}\n.sl-confirm-row button{flex:1;padding:8px;border-radius:8px;font-weight:700;font-size:12.5px}\n.sl-confirm-add{background:var(--sl-accent);color:var(--sl-accent-ink)}\n.sl-confirm-cancel{border:1px solid var(--sl-line);color:var(--sl-muted)}\n.sl-confirm-cancel:hover{color:var(--sl-text)}\n\n/* best-available row */\n.sl-ba{display:flex;align-items:center;gap:8px;padding:9px 11px;border:1px solid var(--sl-line);border-radius:var(--sl-r-sm)}\n.sl-ba select{background:var(--sl-surface);color:var(--sl-text);border:1px solid var(--sl-line);border-radius:7px;\n font:inherit;font-size:12px;padding:5px 6px;max-width:110px}\n.sl-ba-qty{display:flex;align-items:center;gap:7px}\n.sl-ba-qty button{width:24px;height:24px;border-radius:999px;background:var(--sl-surface);border:1px solid var(--sl-line);\n font-size:14px;font-weight:700;display:flex;align-items:center;justify-content:center}\n.sl-ba-qty span{min-width:14px;text-align:center;font-weight:800}\n.sl-ba-go{margin-left:auto;padding:7px 12px;border-radius:999px;border:1px solid var(--sl-line);font-weight:700;font-size:12px;transition:border-color .15s}\n.sl-ba-go:hover{border-color:var(--sl-muted)}\n\n/* screen-reader live region */\n.sl-sr{position:absolute;width:1px;height:1px;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}\n\n/* modal host */\n.sl-modal-scrim{position:fixed;inset:0;z-index:2147483000;background:rgba(5,7,12,.66);display:flex;align-items:center;justify-content:center;padding:18px}\n.sl-modal-frame{width:min(1200px,100%);height:min(820px,100%);border-radius:16px;overflow:hidden;box-shadow:0 40px 120px -30px rgba(0,0,0,.8)}\n@media(max-width:640px){.sl-modal-scrim{padding:0}.sl-modal-frame{width:100%;height:100%;border-radius:0}}\n`;\n\nfunction ensureStyle(): void {\n if (document.getElementById(STYLE_ID)) return;\n const el = document.createElement('style');\n el.id = STYLE_ID;\n el.textContent = CSS;\n document.head.appendChild(el);\n}\n\n/** Merge order: defaults ← org chart theme ← host overrides. */\nfunction resolveTokens(chart: ChartTheme | undefined, host: SeatPickerTheme | undefined): Record<string, string> {\n const accent = host?.accent ?? chart?.accent ?? '#f4b740';\n const accentInk = host?.accentInk ?? chart?.accentInk ?? '#1a1200';\n return {\n '--sl-accent': accent,\n '--sl-accent-ink': accentInk,\n '--sl-bg': host?.background ?? chart?.background ?? '#0f1522',\n '--sl-surface': host?.surface ?? '#1a2234',\n '--sl-text': host?.text ?? chart?.textColor ?? '#eef1f8',\n '--sl-muted': host?.muted ?? '#8b93a7',\n '--sl-line': host?.line ?? 'rgba(139,147,167,.22)',\n '--sl-font': host?.fontFamily ?? chart?.fontFamily ?? \"-apple-system,BlinkMacSystemFont,'Segoe UI',Inter,sans-serif\",\n '--sl-radius': `${host?.radius ?? 14}px`,\n };\n}\n\nexport class SeatPicker {\n private readonly opts: SeatPickerOptions;\n private readonly controller: PickerController;\n\n private root: HTMLDivElement | null = null;\n private mapHost: HTMLDivElement | null = null;\n private rendered = false;\n private destroyed = false;\n\n // chrome refs\n private els: Record<string, HTMLElement> = {};\n private ro: ResizeObserver | null = null;\n private holdTimer: ReturnType<typeof setInterval> | null = null;\n private toastTimer: ReturnType<typeof setTimeout> | null = null;\n\n // state\n private currency = 'USD';\n private hold: HoldResult | null = null;\n private gaQty = new Map<string, number>();\n private tipEl: HTMLDivElement | null = null;\n private tipPos = { x: 0, y: 0 };\n private confirmEl: HTMLDivElement | null = null;\n private confirmSeat: ExpandedSeat | null = null;\n private srEl: HTMLDivElement | null = null;\n private a11yFilter: AccessibilityType | 'all' = 'all';\n private baQty = 2;\n private baCat = '';\n\n // modal plumbing (set by open())\n private modalScrim: HTMLElement | null = null;\n private prevFocus: Element | null = null;\n private escHandler: ((e: KeyboardEvent) => void) | null = null;\n\n /** Set by open(): closes the modal (scroll restore + destroy + onClose). */\n private closeModal: (() => void) | null = null;\n\n /**\n * Close the picker. In modal mode (SeatPicker.open()) this dismisses the\n * modal exactly like ESC/scrim/✕ — restores page scroll and fires onClose.\n * For inline mounts it simply destroys the widget.\n */\n close(): void {\n if (this.closeModal) this.closeModal();\n else this.destroy();\n }\n\n /** Mount the full picker as a document-level modal. Resolves after render. */\n static async open(options: Omit<SeatPickerOptions, 'container'>): Promise<SeatPicker> {\n ensureStyle();\n const scrim = document.createElement('div');\n scrim.className = 'sl-modal-scrim';\n const frame = document.createElement('div');\n frame.className = 'sl-modal-frame';\n scrim.appendChild(frame);\n document.body.appendChild(scrim);\n const prevOverflow = document.body.style.overflow;\n document.body.style.overflow = 'hidden';\n\n const picker = new SeatPicker({ ...options, container: frame });\n picker.modalScrim = scrim;\n picker.prevFocus = document.activeElement;\n const close = (): void => {\n document.body.style.overflow = prevOverflow;\n picker.destroy();\n options.onClose?.();\n };\n picker.closeModal = close;\n scrim.addEventListener('mousedown', (e) => {\n if (e.target === scrim) close();\n });\n picker.escHandler = (e: KeyboardEvent) => {\n if (e.key === 'Escape') close();\n };\n document.addEventListener('keydown', picker.escHandler);\n await picker.render();\n picker.els.close?.classList.add('on');\n picker.els.close?.addEventListener('click', close);\n return picker;\n }\n\n constructor(options: SeatPickerOptions) {\n if (!options || typeof options !== 'object') throw new Error('seatmap: options object is required');\n if (!options.event || typeof options.event !== 'string') throw new Error('seatmap: `event` key is required');\n if (!options.container) throw new Error('seatmap: `container` is required (or use SeatPicker.open())');\n this.opts = options;\n const api = new PubApi((options.apiBase ?? DEFAULT_API_BASE).replace(/\\/+$/, ''));\n this.controller = new PickerController({\n transport: api,\n eventKey: options.event,\n maxSelection: options.maxSelection ?? DEFAULT_MAX_SELECTION,\n currency: options.currency,\n flashOnLiveChange: true,\n colorblindSafe: options.colorblindSafe,\n onSelectionChange: () => this.syncTray(),\n onStatusChange: () => {\n this.syncPrices();\n this.evictTakenSelections();\n },\n onHoldExpired: () => {\n this.hold = null;\n this.stopHoldTimer();\n this.gaQty.clear();\n this.toast(t('picker.holdExpired', undefined) || 'Your hold expired — seats released. Pick again.');\n this.syncTray();\n this.opts.onHoldExpired?.();\n },\n confirmSelection: options.confirmSelection,\n onSelect: (seat) => {\n if (this.opts.confirmSelection) this.showConfirm(seat);\n },\n onViewChange: () => this.reanchorConfirm(),\n onFocusSeat: (seat) => this.announceSeat(seat),\n onSeatHover: (d) => this.updateTooltip(d),\n onHint: (m) => {\n if (m) this.toast(m);\n },\n onError: (err) => this.opts.onError?.(err),\n });\n }\n\n async render(): Promise<this> {\n if (this.rendered) return this;\n this.rendered = true;\n ensureStyle();\n await loadLocale(this.opts.locale);\n if (this.opts.messages) setStringOverrides(this.opts.messages);\n\n const mount = resolveContainer(this.opts.container!);\n const root = document.createElement('div');\n root.className = 'sl-picker';\n this.root = root;\n mount.appendChild(root);\n\n // skeleton first — tokens get re-applied once the chart theme arrives\n Object.entries(resolveTokens(undefined, this.opts.theme)).forEach(([k, v]) => root.style.setProperty(k, v));\n root.innerHTML = `\n <div class=\"sl-head\">\n <div class=\"sl-logo\" data-ref=\"logo\"></div>\n <div class=\"sl-head-info\">\n <div class=\"sl-head-name\" data-ref=\"name\"></div>\n <div class=\"sl-head-meta\" data-ref=\"meta\"></div>\n </div>\n <span class=\"sl-hold-pill\" data-ref=\"hold\"></span>\n <button type=\"button\" class=\"sl-close\" data-ref=\"close\" aria-label=\"Close\">\n <svg viewBox=\"0 0 24 24\"><line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"/><line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"/></svg>\n </button>\n </div>\n <div class=\"sl-body\">\n <div class=\"sl-map\">\n <div class=\"sl-map-host\" data-ref=\"map\"></div>\n <div class=\"sl-zoom\">\n <button type=\"button\" aria-label=\"Zoom in\" data-ref=\"zin\">+</button>\n <button type=\"button\" aria-label=\"Zoom out\" data-ref=\"zout\">−</button>\n <button type=\"button\" aria-label=\"Fit to screen\" data-ref=\"zfit\">\n <svg viewBox=\"0 0 24 24\"><path d=\"M8 3H5a2 2 0 0 0-2 2v3M16 3h3a2 2 0 0 1 2 2v3M8 21H5a2 2 0 0 1-2-2v-3M16 21h3a2 2 0 0 0 2-2v-3\"/></svg>\n </button>\n </div>\n <div class=\"sl-boot\" data-ref=\"boot\"><span class=\"sl-boot-spin\"></span>Loading seat map…</div>\n <div class=\"sl-toast\" data-ref=\"toast\" role=\"status\" aria-live=\"polite\"></div>\n </div>\n <div class=\"sl-side\">\n <div class=\"sl-sec\" data-ref=\"pricesSec\">Prices</div>\n <div class=\"sl-prices\" data-ref=\"prices\"></div>\n <div class=\"sl-sec\">Your seats</div>\n <div class=\"sl-tray\" data-ref=\"tray\"></div>\n <div class=\"sl-foot\">\n <div class=\"sl-total\"><span data-ref=\"count\"></span><b data-ref=\"total\"></b></div>\n <button type=\"button\" class=\"sl-cta\" data-ref=\"cta\" disabled></button>\n </div>\n </div>\n </div>`;\n root.querySelectorAll<HTMLElement>('[data-ref]').forEach((el) => {\n this.els[el.dataset.ref!] = el;\n });\n this.mapHost = this.els.map as HTMLDivElement;\n\n // container-adaptive layout\n this.ro = new ResizeObserver(() => {\n const w = root.clientWidth;\n root.dataset.layout = w < 640 ? 'narrow' : 'wide';\n });\n this.ro.observe(root);\n\n // zoom + tooltip wiring\n this.els.zin.addEventListener('click', () => this.controller.zoomIn());\n this.els.zout.addEventListener('click', () => this.controller.zoomOut());\n this.els.zfit.addEventListener('click', () => this.controller.zoomToFit());\n this.tipEl = document.createElement('div');\n this.tipEl.setAttribute('role', 'tooltip');\n this.tipEl.style.cssText =\n 'position:absolute;z-index:7;pointer-events:none;display:none;max-width:240px;background:var(--sl-surface);' +\n 'color:var(--sl-text);border:1px solid var(--sl-line);border-radius:10px;padding:9px 12px;font-size:12px;line-height:1.45;';\n this.els.map.appendChild(this.tipEl);\n this.els.map.addEventListener('mousemove', (e: MouseEvent) => {\n const r = this.els.map.getBoundingClientRect();\n this.tipPos = { x: e.clientX - r.left, y: e.clientY - r.top };\n if (this.tipEl && this.tipEl.style.display !== 'none') this.placeTooltip();\n });\n\n this.els.cta.addEventListener('click', () => void this.handleCta());\n\n const canvasHost = document.createElement('div');\n canvasHost.style.cssText = 'position:absolute;inset:0';\n this.mapHost.appendChild(canvasHost);\n const info = await this.controller.render(canvasHost);\n if (this.destroyed) return this;\n if (!info) {\n this.els.boot.innerHTML =\n '<div class=\"sl-boot-title\">The seat map didn’t load</div>' +\n '<div>Check your connection and try again.</div>' +\n '<button type=\"button\" class=\"sl-boot-retry\">Try again</button>';\n this.els.boot.querySelector('button')!.addEventListener('click', () => {\n // full remount: cheapest reliable recovery\n const container = this.opts.container!;\n const opts = this.opts;\n this.destroy();\n void new SeatPicker({ ...opts, container }).render();\n });\n return this;\n }\n this.els.boot.remove();\n\n if (info.mode === 'test') {\n const ribbon = document.createElement('div');\n ribbon.textContent = t('picker.testMode');\n ribbon.setAttribute('aria-label', t('picker.testMode'));\n ribbon.style.cssText =\n 'position:absolute;top:18px;right:-34px;z-index:6;transform:rotate(45deg);' +\n 'width:140px;text-align:center;padding:4px 0;background:#f4b740;color:#1a1200;' +\n 'font:800 10.5px/1.4 -apple-system,BlinkMacSystemFont,sans-serif;letter-spacing:.12em;' +\n 'box-shadow:0 2px 8px rgba(0,0,0,.25);pointer-events:none;';\n this.els.map.style.overflow = 'hidden';\n this.els.map.appendChild(ribbon);\n }\n\n // theme: defaults ← org chart theme ← host overrides\n const chartTheme = this.controller.doc?.theme;\n Object.entries(resolveTokens(chartTheme, this.opts.theme)).forEach(([k, v]) => root.style.setProperty(k, v));\n this.currency = info.currency ?? this.opts.currency ?? 'USD';\n\n // header\n const logoUrl = this.opts.theme?.logoUrl ?? chartTheme?.logoUrl;\n if (logoUrl) this.els.logo.innerHTML = `<img src=\"${logoUrl}\" alt=\"\">`;\n else this.els.logo.textContent = (this.opts.theme?.brandName ?? chartTheme?.brandName ?? info.eventName ?? '?').slice(0, 1).toUpperCase();\n this.els.name.textContent = info.eventName ?? '';\n const when = info.startsAt\n ? new Date(info.startsAt).toLocaleString(this.opts.locale, { month: 'short', day: 'numeric', hour: 'numeric', minute: '2-digit' })\n : '';\n this.els.meta.textContent = [info.venue, when].filter(Boolean).join(' · ');\n\n // Accessibility filter chips — only for types actually present in the chart.\n const present = new Set<AccessibilityType>();\n if (this.controller.doc) {\n for (const seat of expandChart(this.controller.doc)) {\n for (const type of seat.accessibility ?? []) present.add(type);\n if (seat.accessible && !seat.accessibility?.length) present.add('wheelchair');\n }\n }\n if (present.size) {\n const chips = document.createElement('div');\n chips.className = 'sl-chips';\n const GLYPH: Partial<Record<AccessibilityType, string>> = { wheelchair: '♿', companion: '🧑🤝🧑' };\n const mk = (key: AccessibilityType | 'all', label: string): string =>\n `<button type=\"button\" class=\"sl-chip-f${key === 'all' ? ' on' : ''}\" data-f=\"${key}\">${label}</button>`;\n chips.innerHTML =\n mk('all', 'All seats') +\n [...present]\n .map((type) => mk(type, `${GLYPH[type] ? GLYPH[type] + ' ' : ''}${type[0].toUpperCase()}${type.slice(1).replace(/-/g, ' ')}`))\n .join('');\n this.els.map.appendChild(chips);\n chips.querySelectorAll<HTMLButtonElement>('button').forEach((btn) => {\n btn.addEventListener('click', () => {\n const f = btn.dataset.f as AccessibilityType | 'all';\n this.a11yFilter = f;\n chips.querySelectorAll('button').forEach((b) => b.classList.toggle('on', b === btn));\n this.controller.setAccessibilityFilter(f === 'all' ? null : [f]);\n });\n });\n }\n\n // Colorblind-safe toggle rides in the zoom column.\n const cb = document.createElement('button');\n cb.type = 'button';\n cb.setAttribute('aria-label', 'Toggle colorblind-friendly colors');\n cb.setAttribute('aria-pressed', String(!!this.opts.colorblindSafe));\n cb.innerHTML = '<svg viewBox=\"0 0 24 24\"><path d=\"M1 12s4-7 11-7 11 7 11 7-4 7-11 7S1 12 1 12z\"/><circle cx=\"12\" cy=\"12\" r=\"3\"/></svg>';\n this.els.zfit.parentElement!.appendChild(cb);\n let cbOn = !!this.opts.colorblindSafe;\n cb.addEventListener('click', () => {\n cbOn = !cbOn;\n cb.setAttribute('aria-pressed', String(cbOn));\n this.controller.setColorblindSafe(cbOn);\n });\n\n // Screen-reader announcements for keyboard seat focus.\n this.srEl = document.createElement('div');\n this.srEl.className = 'sl-sr';\n this.srEl.setAttribute('aria-live', 'polite');\n root.appendChild(this.srEl);\n\n this.syncPrices();\n this.syncTray();\n return this;\n }\n\n /** aria-live readout when keyboard focus lands on a seat. */\n private announceSeat(seat: ExpandedSeat | null): void {\n if (!this.srEl) return;\n if (!seat) {\n this.srEl.textContent = '';\n return;\n }\n const cat = this.controller.doc?.categories.find((c) => c.key === seat.categoryKey);\n const status = this.controller.getStatus(seat.id) ?? 'free';\n const statusText = status === 'free' ? 'available' : status === 'held' ? 'on hold' : 'taken';\n const price = cat?.tiers?.length ? cat.tiers[0].price : cat?.price;\n this.srEl.textContent = `Seat ${seat.label}, ${cat?.label ?? seat.categoryKey}${\n price != null ? `, ${this.money(price)}` : ''\n }, ${statusText}`;\n }\n\n // ---- confirm popover (opt-in confirmSelection mode) ------------------------\n\n private showConfirm(seat: ExpandedSeat): void {\n this.closeConfirm();\n if (this.tipEl) this.tipEl.style.display = 'none';\n const cat = this.controller.doc?.categories.find((c) => c.key === seat.categoryKey);\n const price = cat?.tiers?.length ? cat.tiers[0].price : cat?.price;\n const el = document.createElement('div');\n el.className = 'sl-confirm';\n el.innerHTML =\n `<div class=\"sl-confirm-label\">${seat.label}</div>` +\n `<div class=\"sl-confirm-meta\"><span class=\"sl-dot\" style=\"background:${cat?.color ?? '#6e7bff'}\"></span>` +\n `${cat?.label ?? seat.categoryKey}${price != null ? `<b>${this.money(price)}</b>` : ''}</div>` +\n `<div class=\"sl-confirm-row\">` +\n `<button type=\"button\" class=\"sl-confirm-cancel\">Cancel</button>` +\n `<button type=\"button\" class=\"sl-confirm-add\">Add seat</button></div>`;\n this.els.map.appendChild(el);\n this.confirmEl = el;\n this.confirmSeat = seat;\n this.reanchorConfirm();\n el.querySelector('.sl-confirm-add')!.addEventListener('click', () => this.closeConfirm());\n el.querySelector('.sl-confirm-cancel')!.addEventListener('click', () => {\n this.controller.deselect([seat.id]);\n this.closeConfirm();\n });\n }\n\n private reanchorConfirm(): void {\n if (!this.confirmEl || !this.confirmSeat) return;\n const p = this.controller.worldToScreen({ x: this.confirmSeat.x, y: this.confirmSeat.y });\n this.confirmEl.style.left = `${p.x}px`;\n this.confirmEl.style.top = `${p.y}px`;\n }\n\n private closeConfirm(): void {\n this.confirmEl?.remove();\n this.confirmEl = null;\n this.confirmSeat = null;\n }\n\n // ---- chrome sync ----------------------------------------------------------\n\n private money(n: number): string {\n try {\n return new Intl.NumberFormat(this.opts.locale, { style: 'currency', currency: this.currency }).format(n);\n } catch {\n return `${n} ${this.currency}`;\n }\n }\n\n private syncPrices(): void {\n const doc = this.controller.doc;\n if (!doc || !this.els.prices) return;\n const left = this.controller.categoryAvailability();\n this.els.prices.innerHTML = doc.categories\n .map((c) => {\n const price = c.tiers?.length ? c.tiers[0].price : c.price;\n return (\n `<div class=\"sl-price-row\" data-cat=\"${c.key}\"><span class=\"sl-dot\" style=\"background:${c.color}\"></span>` +\n `<span class=\"sl-price-label\">${c.label}</span>` +\n `<span class=\"sl-price-left\">${left[c.key] ?? 0} left</span>` +\n (price != null ? `<span class=\"sl-price-amt\">${this.money(price)}</span>` : '') +\n `</div>`\n );\n })\n .join('');\n // Legend-hover highlight: dim other categories on the map while hovering a row.\n this.els.prices.querySelectorAll<HTMLElement>('.sl-price-row').forEach((row) => {\n row.addEventListener('mouseenter', () => this.controller.getRenderer()?.setCategoryHighlight?.(row.dataset.cat ?? null));\n row.addEventListener('mouseleave', () => this.controller.getRenderer()?.setCategoryHighlight?.(null));\n });\n }\n\n /** A live delta took one of OUR selected (not yet held) seats — evict + tell the buyer. */\n private evictTakenSelections(): void {\n // Our own hold's WS echo paints our seats 'held' — never treat those as sniped.\n const ownLabels = new Set<string>(this.controller.currentHold()?.labels ?? []);\n const gone = this.controller\n .getSelection()\n .filter((s) => !ownLabels.has(s.label) && (this.controller.getStatus(s.id) ?? 'free') !== 'free');\n if (!gone.length) return;\n this.controller.deselect(gone.map((s) => s.id));\n this.toast(`Seat ${gone[0].label} was just taken by another buyer.`);\n }\n\n private syncTray(): void {\n if (!this.els.tray) return;\n const seats = this.controller.getSelection();\n const gaAreas = this.controller.getGAAreas();\n const heldItems = this.hold?.items ?? [];\n const parts: string[] = [];\n\n if (!seats.length && !heldItems.length && !gaAreas.length) {\n parts.push(`<div class=\"sl-tray-hint\">Tap a seat on the map, or let us pick the best available for you.</div>`);\n } else if (!seats.length && !heldItems.length) {\n parts.push(`<div class=\"sl-tray-hint\">Tap a seat on the map — or grab standing tickets below.</div>`);\n }\n\n // Held line items (best-available or a completed hold) — locked in, no remove.\n for (const item of heldItems) {\n const cat = this.controller.doc?.categories.find((c) => c.key === item.categoryKey);\n parts.push(\n `<div class=\"sl-chip\"><b>${item.label}</b>` +\n `<span class=\"cat\">${cat?.label ?? item.categoryKey}</span>` +\n `<span class=\"amt\">${this.money(item.unitPrice * (item.quantity ?? 1))}</span></div>`,\n );\n }\n\n const heldLabels = new Set(heldItems.map((item) => item.label));\n for (const s of seats.filter((seat) => !heldLabels.has(seat.label))) {\n const cat = this.controller.doc?.categories.find((c) => c.key === s.categoryKey);\n parts.push(\n `<div class=\"sl-chip\" data-seat=\"${s.id}\"><b>${s.label}</b>` +\n `<span class=\"cat\">${cat?.label ?? s.categoryKey}</span>` +\n `<span class=\"amt\">${this.money(s.price)}</span>` +\n `<button type=\"button\" class=\"rm\" aria-label=\"Remove ${s.label}\">` +\n `<svg viewBox=\"0 0 24 24\"><line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"/><line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"/></svg>` +\n `</button></div>`,\n );\n }\n\n for (const area of gaAreas) {\n const qty = this.gaQty.get(area.id) ?? 0;\n parts.push(\n `<div class=\"sl-ga\" data-ga=\"${area.id}\"><div class=\"sl-ga-info\">` +\n `<div class=\"sl-ga-name\">${area.label}</div>` +\n `<div class=\"sl-ga-sub\">${this.money(area.price)} · ${area.available} left</div></div>` +\n `<div class=\"sl-ga-qty\">` +\n `<button type=\"button\" data-d=\"-1\" aria-label=\"Fewer\">−</button><span>${qty}</span>` +\n `<button type=\"button\" data-d=\"1\" aria-label=\"More\">+</button></div></div>`,\n );\n }\n\n // Best available — qty (+ optional category) picked server-side and held atomically.\n if (!this.hold) {\n const cats = this.controller.doc?.categories ?? [];\n parts.push(\n `<div class=\"sl-ba\">` +\n (cats.length > 1\n ? `<select aria-label=\"Category\" data-ba-cat>` +\n `<option value=\"\">Any tier</option>` +\n cats.map((c) => `<option value=\"${c.key}\"${this.baCat === c.key ? ' selected' : ''}>${c.label}</option>`).join('') +\n `</select>`\n : '') +\n `<div class=\"sl-ba-qty\">` +\n `<button type=\"button\" data-ba=\"-1\" aria-label=\"Fewer seats\">−</button><span>${this.baQty}</span>` +\n `<button type=\"button\" data-ba=\"1\" aria-label=\"More seats\">+</button></div>` +\n `<button type=\"button\" class=\"sl-ba-go\">Best available</button></div>`,\n );\n }\n\n this.els.tray.innerHTML = parts.join('');\n this.els.tray.querySelectorAll<HTMLButtonElement>('[data-ba]').forEach((btn) => {\n btn.addEventListener('click', () => {\n this.baQty = Math.max(1, Math.min(8, this.baQty + Number(btn.dataset.ba)));\n this.syncTray();\n });\n });\n this.els.tray.querySelector<HTMLSelectElement>('[data-ba-cat]')?.addEventListener('change', (e) => {\n this.baCat = (e.target as HTMLSelectElement).value;\n });\n this.els.tray.querySelector<HTMLButtonElement>('.sl-ba-go')?.addEventListener('click', () => {\n void this.bestAvailable(this.baQty, this.baCat || undefined);\n });\n this.els.tray.querySelectorAll<HTMLElement>('.sl-chip .rm').forEach((btn) => {\n btn.addEventListener('click', () => {\n const id = (btn.closest('.sl-chip') as HTMLElement).dataset.seat!;\n this.controller.deselect([id]);\n });\n });\n this.els.tray.querySelectorAll<HTMLElement>('.sl-ga button').forEach((btn) => {\n btn.addEventListener('click', () => {\n const areaEl = btn.closest('.sl-ga') as HTMLElement;\n const id = areaEl.dataset.ga!;\n const area = gaAreas.find((a) => a.id === id);\n const next = Math.max(0, Math.min(area?.available ?? 0, (this.gaQty.get(id) ?? 0) + Number(btn.dataset.d)));\n this.gaQty.set(id, next);\n this.syncTray();\n });\n });\n\n // totals + CTA (held lines + fresh selections + GA)\n const gaTotal = gaAreas.reduce((sum, a) => sum + a.price * (this.gaQty.get(a.id) ?? 0), 0);\n const gaCount = [...this.gaQty.values()].reduce((a, b) => a + b, 0);\n const heldTotal = heldItems.reduce((sum, item) => sum + item.unitPrice * (item.quantity ?? 1), 0);\n const heldCount = heldItems.reduce((sum, item) => sum + (item.quantity ?? 1), 0);\n const freshSeats = seats.filter((seat) => !heldLabels.has(seat.label));\n const total = freshSeats.reduce((sum, s) => sum + s.price, 0) + gaTotal + heldTotal;\n const count = freshSeats.length + gaCount + heldCount;\n this.els.count.textContent = count\n ? `${count} ${count === 1 ? 'ticket' : 'tickets'}`\n : 'No seats selected';\n this.els.total.textContent = count ? this.money(total) : '';\n const cta = this.els.cta as HTMLButtonElement;\n cta.disabled = count === 0;\n cta.textContent = this.hold ? 'Continue to checkout' : count ? 'Hold seats & checkout' : 'Select seats';\n this.opts.onSelectionChange?.(seats);\n }\n\n private async handleCta(): Promise<void> {\n const cta = this.els.cta as HTMLButtonElement;\n // Best-available (or a prior CTA press) already holds the seats — hand off.\n // Held seats are NOT in the client selection (the server holds them), so\n // pass the hold's own seat list to the host.\n if (this.hold && !this.controller.getSelection().some((s) => !(this.hold!.items ?? []).some((i) => i.label === s.label))) {\n this.opts.onCheckout?.(this.hold, this.hold.seats ?? this.controller.getSelection());\n return;\n }\n cta.disabled = true;\n cta.textContent = 'Holding…';\n try {\n // seats first (controller.hold covers selected seats); GA quantities ride along\n let hold: HoldResult | null = null;\n const gaEntries = [...this.gaQty.entries()].filter(([, q]) => q > 0);\n // Snapshot before hold — the hold's own WS echo repaints these seats.\n const chosenSeats = this.controller.getSelection();\n if (chosenSeats.length) {\n const h = await this.controller.hold(undefined, this.opts.holdTtlMs);\n hold = h ? { holdId: h.holdId, expiresAt: h.expiresAt, seats: h.seats, items: h.items } : null;\n }\n for (const [areaId, qty] of gaEntries) {\n const h = await this.controller.holdGA(areaId, qty, { ttlMs: this.opts.holdTtlMs });\n hold = h ? { holdId: h.holdId, expiresAt: h.expiresAt, seats: h.seats, items: h.items } : hold;\n }\n if (!hold) {\n this.toast('One or more seats were just taken. Please pick again.');\n this.syncTray();\n return;\n }\n this.hold = hold;\n this.startHoldTimer(hold.expiresAt);\n this.opts.onCheckout?.(hold, chosenSeats.length ? chosenSeats : hold.seats ?? []);\n } catch (err) {\n this.opts.onError?.(err);\n this.toast('One or more seats were just taken. Please pick again.');\n } finally {\n this.syncTray();\n }\n }\n\n private startHoldTimer(expiresAt: number): void {\n this.stopHoldTimer();\n const pill = this.els.hold;\n const tick = (): void => {\n const ms = Math.max(0, expiresAt - Date.now());\n const m = Math.floor(ms / 60000);\n const s = String(Math.floor((ms % 60000) / 1000)).padStart(2, '0');\n pill.textContent = `Held ${m}:${s}`;\n pill.classList.add('on');\n if (ms <= 0) this.stopHoldTimer();\n };\n tick();\n this.holdTimer = setInterval(tick, 500);\n }\n\n private stopHoldTimer(): void {\n if (this.holdTimer) clearInterval(this.holdTimer);\n this.holdTimer = null;\n this.els.hold?.classList.remove('on');\n }\n\n private toast(msg: string): void {\n const el = this.els.toast;\n if (!el) return;\n el.textContent = msg;\n el.classList.add('on');\n if (this.toastTimer) clearTimeout(this.toastTimer);\n this.toastTimer = setTimeout(() => el.classList.remove('on'), 4200);\n }\n\n private placeTooltip(): void {\n if (!this.tipEl) return;\n const hw = this.els.map.clientWidth;\n const tw = this.tipEl.offsetWidth;\n const th = this.tipEl.offsetHeight;\n let x = this.tipPos.x + 14;\n let y = this.tipPos.y - th - 12;\n if (x + tw > hw - 8) x = this.tipPos.x - tw - 14;\n if (y < 8) y = this.tipPos.y + 18;\n this.tipEl.style.left = `${Math.max(8, x)}px`;\n this.tipEl.style.top = `${Math.max(8, y)}px`;\n }\n\n private updateTooltip(details: SeatHoverDetails | null): void {\n if (!this.tipEl) return;\n if (!details) {\n this.tipEl.style.display = 'none';\n return;\n }\n const statusLine =\n details.status === 'free'\n ? ''\n : `<div style=\"margin-top:5px;font-size:10.5px;letter-spacing:.08em;text-transform:uppercase;font-weight:700\">${\n details.status === 'held' ? t('map.statusHeld') : t('map.statusTaken')\n }</div>`;\n this.tipEl.innerHTML =\n `<div style=\"font-weight:800;font-size:13px\">${details.label}</div>` +\n `<div style=\"display:flex;align-items:center;gap:6px;margin-top:4px\">` +\n `<span style=\"width:9px;height:9px;border-radius:50%;flex:none;background:${details.categoryColor}\"></span>` +\n `<span style=\"opacity:.75\">${details.categoryLabel}</span>` +\n `<span style=\"margin-left:auto;font-weight:800\">${this.money(details.price)}</span></div>` +\n statusLine;\n this.tipEl.style.display = 'block';\n this.placeTooltip();\n }\n\n // ---- public conveniences ----------------------------------------------------\n\n getSelection(): PickerSeat[] {\n return this.controller.getSelection();\n }\n\n async bestAvailable(qty: number, categoryKey?: string): Promise<HoldResult | null> {\n try {\n const h = await this.controller.bestAvailable(qty, categoryKey);\n if (h) {\n this.hold = { holdId: h.holdId, expiresAt: h.expiresAt, seats: h.seats, items: h.items };\n this.startHoldTimer(h.expiresAt);\n this.syncTray();\n return this.hold;\n }\n return null;\n } catch (err) {\n this.opts.onError?.(err);\n return null;\n }\n }\n\n async release(): Promise<void> {\n await this.controller.release();\n this.hold = null;\n this.stopHoldTimer();\n this.gaQty.clear();\n this.syncTray();\n }\n\n destroy(): void {\n this.destroyed = true;\n this.closeConfirm();\n this.stopHoldTimer();\n if (this.toastTimer) clearTimeout(this.toastTimer);\n this.ro?.disconnect();\n this.ro = null;\n if (this.escHandler) document.removeEventListener('keydown', this.escHandler);\n this.controller.destroy();\n this.root?.remove();\n this.root = null;\n if (this.modalScrim) {\n this.modalScrim.remove();\n this.modalScrim = null;\n (this.prevFocus as HTMLElement | null)?.focus?.();\n }\n }\n}\n"],"mappings":"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","names":["resolveContainer","import_core","DEFAULT_API_BASE","DEFAULT_MAX_SELECTION","resolveContainer"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/SeatingChart.ts","../src/api.ts","../src/EmbeddedDesigner.ts","../src/SeatPicker.ts"],"sourcesContent":["/**\n * @seatlayer/js — the framework-agnostic SeatLayer embed SDK.\n *\n * Works in any JS environment (plain HTML, React, Vue, Svelte, Angular, …).\n * Framework wrappers (@seatlayer/react, …) build on top of this.\n */\nexport { SeatingChart } from './SeatingChart';\nexport type { SeatingChartOptions, SelectedSeat, GAAreaAvailability } from './SeatingChart';\nexport { ApiError } from './api';\nexport type { HoldResult, HoldConflict, HoldLineItem, BestAvailableResult } from './api';\nexport { EmbeddedDesigner } from './EmbeddedDesigner';\nexport type {\n EmbeddedDesignerOptions,\n EmbeddedDesignerMessage,\n EmbeddedDesignerEventType,\n} from './EmbeddedDesigner';\nexport type { SeatHoverDetails } from '@seatlayer/core';\nexport { SeatPicker } from './SeatPicker';\nexport type {\n SeatPickerOptions,\n SeatPickerTheme,\n CheckoutHandoff,\n CheckoutLineItem,\n} from './SeatPicker';\n","/**\n * SeatingChart — the embeddable buyer picker.\n *\n * A thin wrapper over the shared PickerController (src/picker/PickerController):\n * it owns the mount <div> + the public embed contract (hold-only — the SDK hands\n * the holdId to the host page for a server-side book) and delegates all transport\n * + booking to the controller, so the SDK inherits every fix made for the live\n * buyer page and the demo picker.\n */\nimport { PickerController, loadLocale, setStringOverrides, t, type PickerSeat, type SeatHoverDetails } from '@seatlayer/core';\nimport { PubApi, type BestAvailableResult, type HoldResult } from './api';\n\nconst DEFAULT_API_BASE = 'https://api.seatlayer.io';\nconst DEFAULT_MAX_SELECTION = 10;\n\n/** A seat as surfaced to the host page (prices resolved from the chart's categories). */\nexport type SelectedSeat = PickerSeat;\nexport interface GAAreaAvailability {\n id: string; label: string; capacity: number; available: number; categoryKey: string; price: number; currency: string;\n tiers?: Array<{ id: string; name: string; price: number }>;\n}\n\nexport interface SeatingChartOptions {\n /** CSS selector or an HTMLElement to render into. */\n container: string | HTMLElement;\n /** Event key, e.g. `ev_xxx`. */\n event: string;\n /** API origin. Defaults to https://api.seatlayer.io. */\n apiBase?: string;\n /** Reserved for future authenticated rendering — accepted + stored, not yet sent. */\n publicKey?: string;\n /** Max seats selectable at once (default 10). */\n maxSelection?: number;\n /**\n * BCP 47 language for the widget UI — `'de'`, `'es-MX'`, etc. Falls back to\n * the browser language, then English. Built-in: en, es, de, fr. The German\n * bundle (etc.) is fetched on demand so unused languages cost nothing.\n */\n locale?: string;\n /**\n * Per-key string overrides layered over the active locale — white-label copy\n * without shipping a whole bundle, e.g. `{ 'map.fromPrice': 'ab {price}' }`.\n */\n messages?: Record<string, string>;\n /** ISO 4217 currency for on-map prices (default USD). */\n currency?: string;\n /**\n * Colorblind-safe rendering: category hues switch to an Okabe-Ito palette\n * and booked seats render hollow, so state never relies on hue alone.\n * Toggleable later with setColorblindSafe().\n */\n colorblindSafe?: boolean;\n /**\n * Built-in seat tooltip on mouse hover (seat · category · price · status).\n * Rendered inside the widget so every host gets it; default true. Turn off\n * to draw your own popover from onSeatHover.\n */\n seatTooltip?: boolean;\n /**\n * Seat hover with everything a popover needs (category label/color, resolved\n * tier-aware price, live status, currency); null on hover-out. Fires whether\n * or not the built-in tooltip is enabled.\n */\n onSeatHover?: (details: SeatHoverDetails | null) => void;\n onSelectionChange?: (seats: SelectedSeat[]) => void;\n onHold?: (result: HoldResult) => void;\n onHoldExpired?: () => void;\n onGAClick?: (area: GAAreaAvailability) => void;\n onError?: (err: unknown) => void;\n /**\n * Multi-floor charts only: fires when the buyer taps a deck in the stacked\n * 3D view, after the picker switches to that floor — lets the host page sync\n * its own floor UI (tabs, labels) with the map.\n */\n onDeckTap?: (floorId: string) => void;\n /**\n * Non-blocking, localized selection advice — currently the orphan-seat hint\n * (the selection would strand a single free seat between taken neighbors).\n * `null` clears it. Purely informational; nothing is ever prevented.\n */\n onHint?: (message: string | null) => void;\n}\n\nfunction resolveContainer(container: string | HTMLElement): HTMLElement {\n if (typeof container === 'string') {\n const el = document.querySelector(container);\n if (!el) throw new Error(`seatmap: container \"${container}\" not found`);\n return el as HTMLElement;\n }\n if (!(container instanceof HTMLElement)) {\n throw new Error('seatmap: container must be a CSS selector or an HTMLElement');\n }\n return container;\n}\n\nexport class SeatingChart {\n private readonly opts: SeatingChartOptions;\n private readonly controller: PickerController;\n /** Reserved for future authenticated rendering — stored, not yet sent on any request. */\n readonly publicKey?: string;\n\n private mount: HTMLElement | null = null;\n private hostEl: HTMLDivElement | null = null;\n private rendered = false;\n private tipEl: HTMLDivElement | null = null;\n private tipPos = { x: 0, y: 0 };\n private onTipMove: ((e: MouseEvent) => void) | null = null;\n\n constructor(options: SeatingChartOptions) {\n if (!options || typeof options !== 'object') throw new Error('seatmap: options object is required');\n if (!options.container) throw new Error('seatmap: `container` is required');\n if (!options.event || typeof options.event !== 'string') throw new Error('seatmap: `event` key is required');\n\n this.opts = options;\n this.publicKey = options.publicKey;\n const api = new PubApi((options.apiBase ?? DEFAULT_API_BASE).replace(/\\/+$/, ''));\n this.controller = new PickerController({\n transport: api,\n eventKey: options.event,\n maxSelection: options.maxSelection ?? DEFAULT_MAX_SELECTION,\n currency: options.currency,\n onSelectionChange: (seats) => this.opts.onSelectionChange?.(seats),\n onHold: (h) => this.opts.onHold?.({ holdId: h.holdId, expiresAt: h.expiresAt, seats: h.seats, items: h.items }),\n onHoldExpired: () => this.opts.onHoldExpired?.(),\n onGAClick: (areaId) => {\n const area = this.controller.getGAAreas().find((candidate) => candidate.id === areaId);\n if (area) this.opts.onGAClick?.(area);\n },\n onError: (err) => this.opts.onError?.(err),\n onDeckTap: (floorId) => this.opts.onDeckTap?.(floorId),\n onHint: (message) => this.opts.onHint?.(message),\n // Live-activity cue: pulse seats that other buyers take while the map is\n // open — the WS feed already streams the status change, this makes it felt.\n flashOnLiveChange: true,\n onSeatHover: (details) => {\n this.opts.onSeatHover?.(details);\n if (this.opts.seatTooltip !== false) this.updateTooltip(details);\n },\n colorblindSafe: options.colorblindSafe,\n });\n }\n\n /** Fetch the chart, mount the renderer, seed statuses and go live. Idempotent. */\n async render(): Promise<this> {\n if (this.rendered) return this;\n this.rendered = true;\n\n // Resolve + load the UI language before the first paint so on-map labels\n // (\"N LEFT\", \"FROM …\", the map aria-label) render translated. English and\n // already-loaded locales resolve synchronously; others fetch one small chunk.\n await loadLocale(this.opts.locale);\n if (this.opts.messages) setStringOverrides(this.opts.messages);\n\n // Mount an owned <div> inside the caller's container so we never fight their\n // layout and can cleanly remove it on destroy().\n this.mount = resolveContainer(this.opts.container);\n const host = document.createElement('div');\n host.style.width = '100%';\n host.style.height = '100%';\n host.style.position = 'relative';\n this.mount.appendChild(host);\n this.hostEl = host;\n\n const info = await this.controller.render(host);\n if (!info) {\n this.rendered = false;\n return this;\n }\n\n // Tooltip element + cursor tracking (mouse only — touch selects directly and\n // reviews seats in the host tray). Positioned at the cursor, flipped at edges.\n // Appended AFTER controller.render — mounting the canvas replaces the host's\n // prior children, so anything added earlier would be wiped.\n if (this.opts.seatTooltip !== false) {\n const tip = document.createElement('div');\n tip.setAttribute('role', 'tooltip');\n tip.style.cssText =\n 'position:absolute;z-index:7;pointer-events:none;display:none;max-width:240px;' +\n 'background:#10162a;color:#fff;border-radius:10px;padding:9px 12px;' +\n 'font:500 12px/1.45 -apple-system,BlinkMacSystemFont,\"Segoe UI\",sans-serif;' +\n 'box-shadow:0 10px 30px -10px rgba(0,0,0,.5);';\n host.appendChild(tip);\n this.tipEl = tip;\n this.onTipMove = (e: MouseEvent) => {\n const r = host.getBoundingClientRect();\n this.tipPos = { x: e.clientX - r.left, y: e.clientY - r.top };\n if (this.tipEl && this.tipEl.style.display !== 'none') this.placeTooltip();\n };\n host.addEventListener('mousemove', this.onTipMove);\n }\n if (info.mode === 'test') {\n host.style.overflow = 'hidden';\n const ribbon = document.createElement('div');\n ribbon.textContent = t('picker.testMode');\n ribbon.setAttribute('aria-label', t('picker.testMode'));\n ribbon.style.cssText =\n 'position:absolute;top:18px;right:-34px;z-index:6;transform:rotate(45deg);' +\n 'width:140px;text-align:center;padding:4px 0;background:#f4b740;color:#1a1200;' +\n 'font:800 10.5px/1.4 -apple-system,BlinkMacSystemFont,sans-serif;letter-spacing:.12em;' +\n 'box-shadow:0 2px 8px rgba(0,0,0,.25);pointer-events:none;';\n host.appendChild(ribbon);\n }\n return this;\n }\n\n private placeTooltip(): void {\n if (!this.tipEl || !this.hostEl) return;\n const hw = this.hostEl.clientWidth;\n const tw = this.tipEl.offsetWidth;\n const th = this.tipEl.offsetHeight;\n let x = this.tipPos.x + 14;\n let y = this.tipPos.y - th - 12;\n if (x + tw > hw - 8) x = this.tipPos.x - tw - 14;\n if (y < 8) y = this.tipPos.y + 18;\n this.tipEl.style.left = `${Math.max(8, x)}px`;\n this.tipEl.style.top = `${Math.max(8, y)}px`;\n }\n\n private updateTooltip(details: SeatHoverDetails | null): void {\n if (!this.tipEl) return;\n if (!details) {\n this.tipEl.style.display = 'none';\n return;\n }\n const money = (() => {\n try {\n return new Intl.NumberFormat(undefined, { style: 'currency', currency: details.currency }).format(details.price);\n } catch {\n return `${details.price} ${details.currency}`;\n }\n })();\n const statusLine =\n details.status === 'free'\n ? ''\n : `<div style=\"margin-top:5px;font-size:10.5px;letter-spacing:.08em;text-transform:uppercase;color:#fca5a5;font-weight:700\">${\n details.status === 'held' ? t('map.statusHeld') : t('map.statusTaken')\n }</div>`;\n this.tipEl.innerHTML =\n `<div style=\"font-weight:700;font-size:13px\">${details.label}</div>` +\n `<div style=\"display:flex;align-items:center;gap:6px;margin-top:4px;color:#c7cddc\">` +\n `<span style=\"width:9px;height:9px;border-radius:50%;flex:none;background:${details.categoryColor}\"></span>` +\n `<span>${details.categoryLabel}</span>` +\n `<span style=\"margin-left:auto;font-weight:700;color:#fff\">${money}</span></div>` +\n statusLine;\n this.tipEl.style.display = 'block';\n this.placeTooltip();\n }\n\n /** Current selection with prices resolved from the chart categories. */\n getSelection(): SelectedSeat[] {\n return this.controller.getSelection();\n }\n\n /** Hold the current selection. Resolves the hold, or null on a 409 conflict. */\n async hold(options: { ttlMs?: number } = {}): Promise<HoldResult | null> {\n try {\n const h = await this.controller.hold(undefined, options.ttlMs);\n return h ? { holdId: h.holdId, expiresAt: h.expiresAt, seats: h.seats, items: h.items } : null;\n } catch (err) {\n this.opts.onError?.(err);\n return null;\n }\n }\n\n getGAAreas(): GAAreaAvailability[] {\n return this.controller.getGAAreas();\n }\n\n async holdGA(\n areaId: string,\n qty: number,\n options: { tierId?: string | null; ttlMs?: number } = {},\n ): Promise<HoldResult | null> {\n try {\n const h = await this.controller.holdGA(areaId, qty, options);\n return h ? { holdId: h.holdId, expiresAt: h.expiresAt, seats: h.seats, items: h.items } : null;\n } catch (err) {\n this.opts.onError?.(err);\n return null;\n }\n }\n\n /** Ask the server for the `qty` best free seats and hold them atomically. */\n async bestAvailable(qty: number, categoryKey?: string): Promise<BestAvailableResult | null> {\n try {\n const h = await this.controller.bestAvailable(qty, categoryKey);\n return h ? { holdId: h.holdId, expiresAt: h.expiresAt, labels: h.labels, seats: h.seats, items: h.items } : null;\n } catch (err) {\n this.opts.onError?.(err);\n return null;\n }\n }\n\n /**\n * Choose a ticket tier for a selected seat (e.g. Adult → Child). The seat's\n * available `tiers` are on each `SelectedSeat` from `getSelection()` /\n * `onSelectionChange`. Re-emits the selection with the new tier + price, and\n * the tier rides along in the next `hold()` / `onHold` per seat. `tierId=null`\n * reverts to the default tier.\n */\n setSeatTier(seatId: string, tierId: string | null): void {\n this.controller.setSeatTier(seatId, tierId);\n }\n\n /**\n * Floors of a multi-floor chart — `[{ id, name }]` (single-floor charts\n * return one entry; empty before render()). Pair with setFloor() to build a\n * host-side floor switcher.\n */\n getFloors(): { id: string; name: string }[] {\n return this.controller.getFloors();\n }\n\n /** Switch the shown floor (2D). Warns + no-ops on single-floor charts. */\n setFloor(floorId: string): void {\n if (this.controller.getFloors().length <= 1) {\n console.warn('seatmap: setFloor() ignored — this chart has a single floor');\n return;\n }\n this.controller.setFloor(floorId);\n }\n\n /** Toggle colorblind-safe rendering at runtime (see options.colorblindSafe). */\n setColorblindSafe(on: boolean): void {\n this.controller.setColorblindSafe(on);\n }\n\n /** Zoom in one step (same increment as the wheel/pinch gesture). */\n zoomIn(): void {\n this.controller.zoomIn();\n }\n\n /** Zoom out one step. */\n zoomOut(): void {\n this.controller.zoomOut();\n }\n\n /** Reset the camera so the whole chart fits the container. */\n zoomToFit(): void {\n this.controller.zoomToFit();\n }\n\n /** Release the current hold (if any). No-op when nothing is held. */\n async release(): Promise<void> {\n await this.controller.release();\n }\n\n /** Tear everything down: close the socket, stop timers, drop the canvas. */\n destroy(): void {\n if (this.hostEl && this.onTipMove) this.hostEl.removeEventListener('mousemove', this.onTipMove);\n this.tipEl = null;\n this.onTipMove = null;\n this.controller.destroy();\n if (this.hostEl && this.hostEl.parentNode) this.hostEl.parentNode.removeChild(this.hostEl);\n this.hostEl = null;\n this.mount = null;\n this.rendered = false;\n }\n}\n","/**\n * Minimal client for the public embed surface of workers/api (the `/pub/*`\n * routes). Deliberately self-contained — it does NOT reuse src/lib/api.ts,\n * which bakes in a build-time API base and dashboard session credentials. The\n * SDK runs cross-origin on a third-party ticketing page, so:\n * - apiBase is per-instance (constructor option), not a build constant;\n * - credentials are omitted (no cookie to send, avoids CORS-credential setup);\n * - no custom headers on mutating calls (keeps the CORS preflight trivial).\n */\nimport type { ChartDoc, PickerSeat as SelectedSeat } from '@seatlayer/core';\n\nexport interface HoldConflict {\n label: string;\n status: string;\n}\n\nexport interface HoldLineItem {\n label: string; objectId: string; objectType: 'seat' | 'booth' | 'ga'; categoryKey: string;\n tierId: string | null;\n /** Price in major currency units (for example 45 means $45.00). */\n unitPrice: number;\n currency: string;\n quantity?: number;\n}\n\nexport class ApiError extends Error {\n status: number;\n code?: string;\n /** Present when a hold 409s because seats were just taken/held. */\n conflicts?: HoldConflict[];\n /** Present when best-available 409s ('not_enough_together' | 'sold_out'). */\n reason?: string;\n\n constructor(status: number, message: string, code?: string, conflicts?: HoldConflict[], reason?: string) {\n super(message);\n this.name = 'ApiError';\n this.status = status;\n this.code = code;\n this.conflicts = conflicts;\n this.reason = reason;\n }\n}\n\nexport interface PubChartResult {\n event: { key: string; name: string };\n doc: ChartDoc;\n}\n\nexport interface PubObjectsResult {\n /** Every non-free seat's status, keyed by seat label. */\n seats: Record<string, string>;\n updatedAt: number;\n}\n\nexport interface HoldResult {\n holdId: string;\n expiresAt: number;\n /** The held seats with the buyer's chosen ticket tier per seat (present on hold). */\n seats?: SelectedSeat[];\n items?: HoldLineItem[];\n}\n\n/** Best-available response — the server-picked seats plus the hold they landed in. */\nexport interface BestAvailableResult {\n holdId: string;\n expiresAt: number;\n labels: string[];\n seats?: SelectedSeat[];\n items?: HoldResult['items'];\n}\n\nasync function request<T>(\n base: string,\n path: string,\n init: { method?: 'GET' | 'POST'; body?: unknown } = {},\n): Promise<T> {\n const method = init.method ?? 'GET';\n const headers: Record<string, string> = {};\n let body: string | undefined;\n if (init.body !== undefined) {\n headers['Content-Type'] = 'application/json';\n body = JSON.stringify(init.body);\n }\n\n const res = await fetch(`${base}${path}`, { method, headers, body, credentials: 'omit' });\n\n const isJson = (res.headers.get('content-type') ?? '').includes('application/json');\n const data = isJson ? await res.json().catch(() => null) : null;\n\n if (!res.ok) {\n const err = data as\n | { error?: string; code?: string; conflicts?: HoldConflict[]; reason?: string }\n | null;\n throw new ApiError(res.status, err?.error ?? `request_failed_${res.status}`, err?.code, err?.conflicts, err?.reason);\n }\n return data as T;\n}\n\n/** Public-surface client bound to one apiBase (e.g. https://api.seatlayer.io). */\nexport class PubApi {\n constructor(private readonly base: string) {}\n\n chart(key: string): Promise<PubChartResult> {\n return request(this.base, `/pub/events/${encodeURIComponent(key)}/chart`);\n }\n\n objects(key: string): Promise<PubObjectsResult> {\n return request(this.base, `/pub/events/${encodeURIComponent(key)}/objects`);\n }\n\n hold(key: string, selections: Array<{ label: string; tierId?: string | null }>, ttlMs?: number, replaceHoldId?: string): Promise<HoldResult> {\n return request(this.base, `/pub/events/${encodeURIComponent(key)}/hold`, {\n method: 'POST',\n body: { selections, ...(ttlMs ? { ttlMs } : {}), ...(replaceHoldId ? { replaceHoldId } : {}) },\n });\n }\n\n bestAvailable(key: string, qty: number, categoryKey?: string): Promise<BestAvailableResult> {\n return request(this.base, `/pub/events/${encodeURIComponent(key)}/best-available`, {\n method: 'POST',\n body: { qty, ...(categoryKey ? { categoryKey } : {}) },\n });\n }\n\n release(key: string, labels: string[], holdId: string): Promise<{ ok: true }> {\n return request(this.base, `/pub/events/${encodeURIComponent(key)}/release`, {\n method: 'POST',\n body: { labels, holdId },\n });\n }\n\n /** P4 \"need more time?\": push an active hold's expiry out. Throws ApiError 409\n * (reason: expired | extend_limit | not_found | not_active) if it can't. */\n extend(key: string, holdId: string, ttlMs?: number): Promise<{ holdId: string; expiresAt: number; extends: number }> {\n return request(this.base, `/pub/events/${encodeURIComponent(key)}/extend`, {\n method: 'POST',\n body: { holdId, ...(ttlMs ? { ttlMs } : {}) },\n });\n }\n\n socketUrl(key: string): string {\n const wsBase = this.base.replace(/^http/, 'ws');\n return `${wsBase}/pub/events/${encodeURIComponent(key)}/subscribe`;\n }\n}\n","/**\n * A secure, framework-neutral host for the SeatLayer chart Designer.\n *\n * The Designer remains an iframe so a platform never gives its SeatLayer secret\n * key to a browser. This class owns the iframe lifecycle and accepts messages\n * only from that iframe's exact origin.\n */\nexport type EmbeddedDesignerEventType =\n | 'seatlayer.designer.ready'\n | 'seatlayer.designer.saved'\n | 'seatlayer.designer.published'\n | 'seatlayer.designer.close'\n | 'seatlayer.designer.error';\n\nexport interface EmbeddedDesignerMessage {\n type: EmbeddedDesignerEventType;\n chartId?: string;\n workspaceId?: string;\n expiresAt?: number;\n code?: string;\n message?: string;\n meta?: unknown;\n}\n\nexport interface EmbeddedDesignerOptions {\n /** The short-lived URL returned by your backend's Designer-session call. */\n designerUrl: string;\n /** CSS selector or element where the iframe is mounted. */\n container: string | HTMLElement;\n /** Verify the message belongs to the chart your backend opened. */\n expectedChartId?: string;\n /** Verify the message belongs to the workspace your backend opened. */\n expectedWorkspaceId?: string;\n title?: string;\n className?: string;\n style?: Partial<CSSStyleDeclaration>;\n allow?: string;\n referrerPolicy?: ReferrerPolicy;\n onReady?: (message: EmbeddedDesignerMessage) => void;\n onSaved?: (message: EmbeddedDesignerMessage) => void;\n onPublished?: (message: EmbeddedDesignerMessage) => void;\n onClose?: (message: EmbeddedDesignerMessage) => void;\n onError?: (message: EmbeddedDesignerMessage) => void;\n}\n\nconst TYPES = new Set<EmbeddedDesignerEventType>([\n 'seatlayer.designer.ready',\n 'seatlayer.designer.saved',\n 'seatlayer.designer.published',\n 'seatlayer.designer.close',\n 'seatlayer.designer.error',\n]);\n\nfunction resolveContainer(container: string | HTMLElement): HTMLElement {\n if (typeof container !== 'string') return container;\n const element = document.querySelector<HTMLElement>(container);\n if (!element) throw new Error(`EmbeddedDesigner container not found: ${container}`);\n return element;\n}\n\n/** Mount, replace, and destroy a scoped Designer iframe safely. */\nexport class EmbeddedDesigner {\n private options: EmbeddedDesignerOptions;\n private frame: HTMLIFrameElement | null = null;\n private designerOrigin = '';\n\n constructor(options: EmbeddedDesignerOptions) {\n this.options = options;\n }\n\n mount(): HTMLIFrameElement {\n this.destroy();\n const url = new URL(this.options.designerUrl, window.location.href);\n if (url.protocol !== 'https:' && url.hostname !== 'localhost' && url.hostname !== '127.0.0.1') {\n throw new Error('EmbeddedDesigner requires an HTTPS designerUrl outside local development.');\n }\n this.designerOrigin = url.origin;\n\n const frame = document.createElement('iframe');\n frame.title = this.options.title ?? 'Venue chart Designer';\n frame.allow = this.options.allow ?? 'clipboard-write';\n frame.referrerPolicy = this.options.referrerPolicy ?? 'origin';\n frame.src = url.toString();\n frame.style.width = '100%';\n frame.style.height = '100%';\n frame.style.border = '0';\n Object.assign(frame.style, this.options.style);\n if (this.options.className) frame.className = this.options.className;\n\n window.addEventListener('message', this.handleMessage);\n resolveContainer(this.options.container).append(frame);\n this.frame = frame;\n return frame;\n }\n\n /** Replace the iframe instead of assigning a new fragment to an existing one. */\n setDesignerUrl(designerUrl: string): HTMLIFrameElement {\n this.options = { ...this.options, designerUrl };\n return this.mount();\n }\n\n getIframe(): HTMLIFrameElement | null {\n return this.frame;\n }\n\n destroy(): void {\n window.removeEventListener('message', this.handleMessage);\n this.frame?.remove();\n this.frame = null;\n this.designerOrigin = '';\n }\n\n private handleMessage = (event: MessageEvent<unknown>) => {\n if (!this.frame || event.origin !== this.designerOrigin || event.source !== this.frame.contentWindow) return;\n if (!event.data || typeof event.data !== 'object') return;\n const data = event.data as Record<string, unknown>;\n if (typeof data.type !== 'string' || !TYPES.has(data.type as EmbeddedDesignerEventType)) return;\n\n const message: EmbeddedDesignerMessage = {\n type: data.type as EmbeddedDesignerEventType,\n chartId: typeof data.chartId === 'string' ? data.chartId : undefined,\n workspaceId: typeof data.workspaceId === 'string' ? data.workspaceId : undefined,\n expiresAt: typeof data.expiresAt === 'number' ? data.expiresAt : undefined,\n code: typeof data.code === 'string' ? data.code : undefined,\n message: typeof data.message === 'string' ? data.message : undefined,\n meta: data.meta,\n };\n if (this.options.expectedChartId && message.chartId && message.chartId !== this.options.expectedChartId) return;\n if (this.options.expectedWorkspaceId && message.workspaceId && message.workspaceId !== this.options.expectedWorkspaceId) return;\n\n switch (message.type) {\n case 'seatlayer.designer.ready': this.options.onReady?.(message); break;\n case 'seatlayer.designer.saved': this.options.onSaved?.(message); break;\n case 'seatlayer.designer.published': this.options.onPublished?.(message); break;\n case 'seatlayer.designer.close': this.options.onClose?.(message); break;\n case 'seatlayer.designer.error': this.options.onError?.(message); break;\n }\n };\n}\n","/**\n * SeatPicker — the full buyer experience as a widget.\n *\n * Where `SeatingChart` is canvas-only, SeatPicker owns the complete chrome\n * from the canonical UX (SeatmapUX/11 Buyer Picker.dc.html): branded header,\n * live price panel, selection tray with GA steppers, hold countdown, snipe\n * toasts and expiry recovery — all on top of the shared PickerController, so\n * every host gets the whole experience with one mount.\n *\n * Render contexts (owner requirement): the SAME widget adapts to a full-screen\n * takeover, an inline <div> in a content page, or a popup — breakpoints key\n * off the CONTAINER via ResizeObserver, never the viewport. `SeatPicker.open()`\n * mounts a document-level modal (scrim, ESC, focus restore) in one call.\n *\n * Theming (owner requirement): org account customization flows automatically —\n * the chart payload's ChartTheme (accent, accentInk, logoUrl, brand name,\n * fontFamily, …) seeds the look; the host `theme` option overrides any subset;\n * and every value lands as a `--sl-*` CSS custom property on the widget root\n * so plain host CSS can restyle too.\n */\nimport {\n PickerController,\n expandChart,\n generateSeatPanorama,\n loadLocale,\n setStringOverrides,\n t,\n tCount,\n type AccessibilityType,\n type ChartTheme,\n type ExpandedSeat,\n type LodRung,\n type PickerSeat,\n type SeatHoverDetails,\n type SectionSummary,\n} from '@seatlayer/core';\nimport { PubApi, type HoldLineItem, type HoldResult } from './api';\nimport type { GAAreaAvailability } from './SeatingChart';\n\nconst DEFAULT_API_BASE = 'https://api.seatlayer.io';\nconst DEFAULT_MAX_SELECTION = 10;\n/** Show the \"Need more time?\" prompt when the hold has this long (ms) left. */\nconst EXTEND_PROMPT_MS = 60_000;\n\n/**\n * Stable checkout-handoff contract (P4). Passed as the THIRD argument to\n * `onCheckout(hold, seats, handoff)` — additive, so the legacy `(hold, seats)`\n * shape used by DesiPass web-v2 (SDK 0.7.3+) is untouched. This is the object to\n * build your order against: it is self-contained (holdId, expiry, currency, and\n * per-line tier + price) and never changes shape across minor releases.\n */\nexport interface CheckoutLineItem {\n /** Seat label (or GA synthetic-unit label). */\n label: string;\n /** Chart object id (row/booth/GA area) the unit belongs to. */\n objectId: string;\n objectType: 'seat' | 'booth' | 'ga';\n categoryKey: string;\n /** Chosen ticket tier id (Adult/Child/…), or null when the category has no tiers. */\n tierId: string | null;\n /** Unit price in MAJOR currency units (e.g. 45 = 45.00). Server-authoritative. */\n unitPrice: number;\n /** ISO-4217, resolved server-side (per-event override → org → USD). */\n currency: string;\n quantity: number;\n}\n\nexport interface CheckoutHandoff {\n /** Server hold id — pass this to YOUR book call. */\n holdId: string;\n /** Epoch ms the hold expires (after any extensions). */\n expiresAt: number;\n /** ISO-4217 currency for the whole order. */\n currency: string;\n /** Priced line items (tier + unit price + currency), server-authoritative. */\n lineItems: CheckoutLineItem[];\n /** Convenience total in major units (Σ unitPrice × quantity). */\n total: number;\n}\n\n/** Host theme overrides — any subset; unset keys fall back to the org's chart theme, then defaults. */\nexport interface SeatPickerTheme {\n /** Brand accent (CTA, active chips, hold pill). */\n accent?: string;\n /** Ink on the accent (button labels). */\n accentInk?: string;\n /** Widget background. */\n background?: string;\n /** Panel/card surface color. */\n surface?: string;\n /** Primary text color. */\n text?: string;\n /** Secondary text color. */\n muted?: string;\n /** Hairline/border color. */\n line?: string;\n /** Font stack for all widget chrome. */\n fontFamily?: string;\n /** Corner radius base (px). */\n radius?: number;\n /** Header logo URL (falls back to the org logo from the chart theme, then a monogram). */\n logoUrl?: string;\n /** Brand/event fallback name for the monogram. */\n brandName?: string;\n}\n\nexport interface SeatPickerOptions {\n /** CSS selector or element to mount into. Omit when using SeatPicker.open(). */\n container?: string | HTMLElement;\n /** Event key, e.g. `ev_xxx`. */\n event: string;\n /** API origin. Defaults to https://api.seatlayer.io. */\n apiBase?: string;\n /** Reserved for future authenticated rendering. */\n publicKey?: string;\n /** Max seats selectable at once (default 10). */\n maxSelection?: number;\n /** BCP 47 language for the widget UI. Built-in: en, es, de, fr. */\n locale?: string;\n /** Per-key string overrides layered over the active locale. */\n messages?: Record<string, string>;\n /** ISO 4217 currency fallback (the org/event currency on the chart wins). */\n currency?: string;\n /** Colorblind-safe rendering (Okabe-Ito palette, hollow booked seats). */\n colorblindSafe?: boolean;\n /** Host theme overrides — see SeatPickerTheme. */\n theme?: SeatPickerTheme;\n /** Hold TTL in ms passed to hold(); server clamps to its own limits. */\n holdTtlMs?: number;\n /**\n * Confirm mode: tapping a seat shows an anchored popover (seat · category ·\n * price · Add/Cancel) instead of adding straight to the tray. Default false.\n */\n confirmSelection?: boolean;\n /**\n * Offer a \"View from seat\" 360° preview (confirm popover + tray chips). The\n * panorama is generated from the chart geometry, or the organizer's uploaded\n * photo when a seat carries one. Default true; set false to hide the affordance.\n */\n seatView?: boolean;\n /**\n * Buyer pressed the CTA and the hold succeeded — hand off to YOUR checkout.\n * `hold` and `seats` are the legacy args (unchanged since 0.6). `handoff` (P4)\n * is the stable, self-contained {@link CheckoutHandoff} to build your order\n * against — holdId, expiry, currency and priced line items. Prefer it.\n */\n onCheckout?: (hold: HoldResult, seats: PickerSeat[], handoff: CheckoutHandoff) => void;\n /**\n * The held seats were BOOKED (P4) — your server completed payment and the\n * booking landed over the realtime channel while the widget was still open.\n * The widget shows a success state; use this to advance your own UI (receipt,\n * redirect). Fires once per hold.\n */\n onBooked?: (handoff: CheckoutHandoff) => void;\n /** Selection changed (tap or best-available). */\n onSelectionChange?: (seats: PickerSeat[]) => void;\n /** The open hold expired server-side (widget already reset itself). */\n onHoldExpired?: () => void;\n /** Modal only: the buyer closed the picker (ESC / scrim / ✕). */\n onClose?: () => void;\n onError?: (err: unknown) => void;\n}\n\nfunction resolveContainer(container: string | HTMLElement): HTMLElement {\n if (typeof container === 'string') {\n const el = document.querySelector(container);\n if (!el) throw new Error(`seatmap: container \"${container}\" not found`);\n return el as HTMLElement;\n }\n if (!(container instanceof HTMLElement)) {\n throw new Error('seatmap: container must be a CSS selector or an HTMLElement');\n }\n return container;\n}\n\n/** Widget stylesheet — injected once per document. Every color/font/radius is a --sl-* token. */\nconst STYLE_ID = 'seatlayer-picker-style';\nconst CSS = `\n.sl-picker{position:relative;display:flex;flex-direction:column;width:100%;height:100%;min-height:420px;overflow:hidden;\n background:var(--sl-bg);color:var(--sl-text);font-family:var(--sl-font);border-radius:var(--sl-radius);\n --sl-r-sm:calc(var(--sl-radius) * .55)}\n.sl-picker *{box-sizing:border-box;margin:0;padding:0}\n.sl-picker button{font:inherit;color:inherit;background:none;border:0;cursor:pointer}\n\n/* header */\n.sl-head{display:flex;align-items:center;gap:12px;padding:12px 16px;border-bottom:1px solid var(--sl-line);flex:none}\n.sl-logo{width:34px;height:34px;border-radius:9px;flex:none;display:flex;align-items:center;justify-content:center;\n background:var(--sl-accent);color:var(--sl-accent-ink);font-weight:800;font-size:15px;overflow:hidden}\n.sl-logo img{width:100%;height:100%;object-fit:cover;display:block}\n.sl-head-info{min-width:0;flex:1}\n.sl-head-name{font-weight:700;font-size:15px;line-height:1.2;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n.sl-head-meta{font-size:10px;letter-spacing:.1em;text-transform:uppercase;color:var(--sl-muted);margin-top:3px;\n white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-weight:600}\n.sl-hold-pill{display:none;align-items:center;gap:6px;padding:6px 12px;border-radius:999px;flex:none;\n background:var(--sl-accent);color:var(--sl-accent-ink);font-weight:700;font-size:12px;font-variant-numeric:tabular-nums}\n.sl-hold-pill.on{display:inline-flex}\n.sl-close{width:32px;height:32px;border-radius:999px;flex:none;display:none;align-items:center;justify-content:center;\n border:1px solid var(--sl-line);color:var(--sl-muted);transition:color .15s,border-color .15s}\n.sl-close:hover{color:var(--sl-text);border-color:var(--sl-muted)}\n.sl-close.on{display:inline-flex}\n.sl-close svg{width:14px;height:14px;stroke:currentColor;stroke-width:2;fill:none;stroke-linecap:round}\n\n/* body */\n.sl-body{display:flex;flex:1;min-height:0}\n.sl-map{position:relative;flex:1;min-width:0}\n.sl-map-host{position:absolute;inset:0}\n.sl-side{width:300px;flex:none;border-left:1px solid var(--sl-line);display:flex;flex-direction:column;min-height:0;overflow-y:auto}\n\n/* narrow (container < 640px): side panel becomes a bottom sheet */\n.sl-picker[data-layout=\"narrow\"] .sl-body{flex-direction:column}\n.sl-picker[data-layout=\"narrow\"] .sl-map{min-height:0;flex:1}\n.sl-picker[data-layout=\"narrow\"] .sl-side{width:100%;max-height:46%;border-left:0;border-top:1px solid var(--sl-line)}\n.sl-picker[data-layout=\"narrow\"] .sl-tray{flex:none}\n.sl-picker[data-layout=\"narrow\"] .sl-foot{position:sticky;bottom:0;background:var(--sl-bg)}\n\n/* price panel */\n.sl-sec{padding:14px 16px 4px;font-size:9.5px;letter-spacing:.14em;text-transform:uppercase;color:var(--sl-muted);font-weight:700}\n.sl-prices{padding:4px 16px 10px;border-bottom:1px solid var(--sl-line)}\n.sl-price-row{display:flex;align-items:center;gap:8px;padding:5px 0;font-size:13px}\n.sl-dot{width:9px;height:9px;border-radius:50%;flex:none}\n.sl-price-label{flex:1;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-weight:600}\n.sl-price-left{font-size:11px;color:var(--sl-muted);font-variant-numeric:tabular-nums}\n.sl-price-amt{font-weight:800;font-variant-numeric:tabular-nums}\n\n/* tray */\n.sl-tray{flex:1;padding:10px 16px;display:flex;flex-direction:column;gap:8px;min-height:0}\n.sl-tray-hint{font-size:12.5px;color:var(--sl-muted);line-height:1.5}\n.sl-chip{display:flex;align-items:center;gap:9px;padding:9px 11px;border:1px solid var(--sl-line);\n border-radius:var(--sl-r-sm);background:var(--sl-surface);font-size:13px}\n.sl-chip b{font-weight:800}\n.sl-chip .cat{color:var(--sl-muted);font-size:11.5px;flex:1;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n.sl-chip .amt{font-weight:700;font-variant-numeric:tabular-nums}\n.sl-chip .rm{width:22px;height:22px;border-radius:999px;flex:none;display:flex;align-items:center;justify-content:center;color:var(--sl-muted)}\n.sl-chip .rm:hover{color:var(--sl-text)}\n.sl-chip .rm svg{width:11px;height:11px;stroke:currentColor;stroke-width:2.4;fill:none;stroke-linecap:round}\n\n/* GA rows */\n.sl-ga{display:flex;align-items:center;gap:10px;padding:9px 11px;border:1px dashed var(--sl-line);border-radius:var(--sl-r-sm)}\n.sl-ga-info{flex:1;min-width:0}\n.sl-ga-name{font-weight:700;font-size:13px}\n.sl-ga-sub{font-size:11px;color:var(--sl-muted);margin-top:2px}\n.sl-ga-qty{display:flex;align-items:center;gap:8px}\n.sl-ga-qty button{width:26px;height:26px;border-radius:999px;background:var(--sl-surface);border:1px solid var(--sl-line);\n font-size:15px;font-weight:700;display:flex;align-items:center;justify-content:center;transition:border-color .15s}\n.sl-ga-qty button:hover{border-color:var(--sl-muted)}\n.sl-ga-qty span{min-width:16px;text-align:center;font-weight:800;font-variant-numeric:tabular-nums}\n\n/* footer */\n.sl-foot{padding:12px 16px 14px;border-top:1px solid var(--sl-line);flex:none}\n.sl-total{display:flex;justify-content:space-between;align-items:center;font-size:13px;margin-bottom:10px}\n.sl-total b{font-size:17px;font-variant-numeric:tabular-nums}\n.sl-cta{width:100%;padding:13px;border-radius:var(--sl-r-sm);font-weight:800;font-size:14px;\n background:var(--sl-accent);color:var(--sl-accent-ink);transition:filter .15s,opacity .15s}\n.sl-cta:hover{filter:brightness(1.08)}\n.sl-cta:disabled{opacity:.45;cursor:not-allowed}\n\n/* zoom column */\n.sl-zoom{position:absolute;right:12px;bottom:12px;display:flex;flex-direction:column;gap:6px;z-index:5}\n.sl-zoom button{width:36px;height:36px;border-radius:999px;background:var(--sl-surface);border:1px solid var(--sl-line);\n color:var(--sl-text);font-size:17px;font-weight:700;display:flex;align-items:center;justify-content:center;transition:border-color .15s}\n.sl-zoom button:hover{border-color:var(--sl-muted)}\n.sl-zoom svg{width:14px;height:14px;stroke:currentColor;stroke-width:2;fill:none;stroke-linecap:round;stroke-linejoin:round}\n\n/* toast + boot states */\n.sl-toast{position:absolute;left:50%;bottom:16px;transform:translateX(-50%) translateY(6px);z-index:8;max-width:88%;\n background:var(--sl-surface);border:1px solid var(--sl-line);color:var(--sl-text);border-radius:999px;padding:9px 16px;\n font-size:12.5px;font-weight:600;opacity:0;pointer-events:none;transition:opacity .2s,transform .2s;white-space:nowrap;\n overflow:hidden;text-overflow:ellipsis}\n.sl-toast.on{opacity:1;transform:translateX(-50%) translateY(0)}\n.sl-boot{position:absolute;inset:0;z-index:6;display:flex;flex-direction:column;align-items:center;justify-content:center;\n gap:10px;background:var(--sl-bg);font-size:13px;font-weight:600;color:var(--sl-muted)}\n.sl-boot-spin{width:24px;height:24px;border-radius:50%;border:3px solid var(--sl-line);border-top-color:var(--sl-accent);\n animation:slspin .8s linear infinite}\n@keyframes slspin{to{transform:rotate(360deg)}}\n.sl-boot-title{font-weight:800;font-size:15px;color:var(--sl-text)}\n.sl-boot-retry{margin-top:4px;padding:9px 20px;border-radius:var(--sl-r-sm);background:var(--sl-accent);\n color:var(--sl-accent-ink);font-weight:700;font-size:13px}\n\n/* \"Need more time?\" extend prompt (bottom-center over the map, above the toast) */\n.sl-extend{position:absolute;left:50%;bottom:16px;transform:translateX(-50%) translateY(6px);z-index:9;\n display:none;align-items:center;gap:12px;max-width:92%;background:var(--sl-surface);border:1px solid var(--sl-line);\n color:var(--sl-text);border-radius:14px;padding:10px 12px 10px 16px;box-shadow:0 18px 50px -18px rgba(0,0,0,.6);\n opacity:0;transition:opacity .2s,transform .2s}\n.sl-extend.on{display:flex;opacity:1;transform:translateX(-50%) translateY(0)}\n.sl-extend-txt{font-size:12.5px;font-weight:600;line-height:1.35}\n.sl-extend-txt b{font-variant-numeric:tabular-nums}\n.sl-extend-btn{flex:none;padding:8px 14px;border-radius:999px;font-weight:800;font-size:12.5px;\n background:var(--sl-accent);color:var(--sl-accent-ink);transition:filter .15s,opacity .15s}\n.sl-extend-btn:hover{filter:brightness(1.08)}\n.sl-extend-btn:disabled{opacity:.5;cursor:not-allowed}\n\n/* booked confirmation overlay (covers the widget once the held seats are sold) */\n.sl-booked{position:absolute;inset:0;z-index:11;display:none;flex-direction:column;align-items:center;\n justify-content:center;gap:12px;text-align:center;padding:28px;background:var(--sl-bg)}\n.sl-booked.on{display:flex}\n.sl-booked-badge{width:60px;height:60px;border-radius:999px;display:flex;align-items:center;justify-content:center;\n background:var(--sl-accent);color:var(--sl-accent-ink)}\n.sl-booked-badge svg{width:30px;height:30px;stroke:currentColor;stroke-width:2.6;fill:none;stroke-linecap:round;stroke-linejoin:round}\n.sl-booked-title{font-weight:800;font-size:19px;color:var(--sl-text)}\n.sl-booked-sub{font-size:13px;color:var(--sl-muted);line-height:1.5;max-width:320px}\n.sl-booked-seats{font-weight:700;color:var(--sl-text)}\n\n/* a11y filter chips (over the map, top-left) */\n.sl-chips{position:absolute;top:12px;left:12px;z-index:5;display:flex;gap:6px;flex-wrap:wrap;max-width:70%}\n.sl-chip-f{display:inline-flex;align-items:center;gap:6px;padding:7px 12px;border-radius:999px;font-size:12px;font-weight:700;\n background:var(--sl-surface);border:1px solid var(--sl-line);color:var(--sl-muted);transition:color .15s,border-color .15s}\n.sl-chip-f:hover{color:var(--sl-text)}\n.sl-chip-f.on{background:var(--sl-accent);color:var(--sl-accent-ink);border-color:transparent}\n\n/* confirm popover */\n.sl-confirm{position:absolute;z-index:9;min-width:190px;background:var(--sl-surface);border:1px solid var(--sl-line);\n border-radius:12px;padding:12px;box-shadow:0 18px 50px -18px rgba(0,0,0,.7);transform:translate(-50%,calc(-100% - 14px))}\n.sl-confirm-label{font-weight:800;font-size:14px}\n.sl-confirm-meta{display:flex;align-items:center;gap:6px;font-size:12px;color:var(--sl-muted);margin-top:4px}\n.sl-confirm-meta b{color:var(--sl-text);margin-left:auto}\n.sl-confirm-row{display:flex;gap:8px;margin-top:10px}\n.sl-confirm-row button{flex:1;padding:8px;border-radius:8px;font-weight:700;font-size:12.5px}\n.sl-confirm-add{background:var(--sl-accent);color:var(--sl-accent-ink)}\n.sl-confirm-cancel{border:1px solid var(--sl-line);color:var(--sl-muted)}\n.sl-confirm-cancel:hover{color:var(--sl-text)}\n\n/* best-available row */\n.sl-ba{display:flex;align-items:center;gap:8px;padding:9px 11px;border:1px solid var(--sl-line);border-radius:var(--sl-r-sm)}\n.sl-ba select{background:var(--sl-surface);color:var(--sl-text);border:1px solid var(--sl-line);border-radius:7px;\n font:inherit;font-size:12px;padding:5px 6px;max-width:110px}\n.sl-ba-qty{display:flex;align-items:center;gap:7px}\n.sl-ba-qty button{width:24px;height:24px;border-radius:999px;background:var(--sl-surface);border:1px solid var(--sl-line);\n font-size:14px;font-weight:700;display:flex;align-items:center;justify-content:center}\n.sl-ba-qty span{min-width:14px;text-align:center;font-weight:800}\n.sl-ba-go{margin-left:auto;padding:7px 12px;border-radius:999px;border:1px solid var(--sl-line);font-weight:700;font-size:12px;transition:border-color .15s}\n.sl-ba-go:hover{border-color:var(--sl-muted)}\n\n/* screen-reader live region */\n.sl-sr{position:absolute;width:1px;height:1px;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}\n\n/* per-seat ticket-tier select + view-from-seat button in tray chips */\n.sl-chip .tier{background:var(--sl-bg);color:var(--sl-text);border:1px solid var(--sl-line);border-radius:7px;\n font:inherit;font-size:11px;padding:3px 5px;max-width:130px;cursor:pointer}\n.sl-chip .view{width:24px;height:24px;border-radius:999px;flex:none;display:flex;align-items:center;justify-content:center;\n color:var(--sl-muted);transition:color .15s}\n.sl-chip .view:hover{color:var(--sl-text)}\n.sl-chip .view svg{width:14px;height:14px;stroke:currentColor;stroke-width:2;fill:none;stroke-linecap:round;stroke-linejoin:round}\n\n/* arena: LOD rung pills (top-center over the map) */\n.sl-rungs{position:absolute;top:12px;left:50%;transform:translateX(-50%);z-index:5;display:none;\n background:var(--sl-surface);border:1px solid var(--sl-line);border-radius:999px;padding:3px}\n.sl-rungs.on{display:inline-flex;gap:2px}\n.sl-rungs button{padding:6px 13px;border-radius:999px;font-size:10.5px;font-weight:800;letter-spacing:.07em;\n color:var(--sl-muted);white-space:nowrap;transition:color .15s}\n.sl-rungs button:hover{color:var(--sl-text)}\n.sl-rungs button.on{background:var(--sl-accent);color:var(--sl-accent-ink)}\n\n/* multi-floor switcher (center-left rail over the map) */\n.sl-floors{position:absolute;top:50%;left:12px;transform:translateY(-50%);z-index:5;display:none;\n flex-direction:column;gap:6px;max-width:42%}\n.sl-floors.on{display:flex}\n.sl-floors button{padding:7px 13px;border-radius:999px;font-size:12px;font-weight:700;background:var(--sl-surface);\n border:1px solid var(--sl-line);color:var(--sl-muted);white-space:nowrap;max-width:100%;overflow:hidden;\n text-overflow:ellipsis;transition:color .15s,border-color .15s}\n.sl-floors button:hover{color:var(--sl-text)}\n.sl-floors button.on{background:var(--sl-accent);color:var(--sl-accent-ink);border-color:transparent}\n\n/* tapped-section summary card (top-center, under the rung pills) */\n.sl-seccard{position:absolute;top:54px;left:50%;transform:translateX(-50%);z-index:6;width:250px;\n max-width:calc(100% - 24px);background:var(--sl-surface);border:1px solid var(--sl-line);border-radius:12px;\n padding:12px 14px;box-shadow:0 18px 50px -18px rgba(0,0,0,.6);display:none}\n.sl-seccard.on{display:block}\n.sl-seccard-head{display:flex;align-items:center;gap:8px}\n.sl-seccard-dot{width:10px;height:10px;border-radius:50%;flex:none}\n.sl-seccard-name{font-weight:800;font-size:14px;flex:1;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n.sl-seccard-price{font-weight:800;font-size:12.5px;font-variant-numeric:tabular-nums}\n.sl-seccard-x{width:22px;height:22px;border-radius:999px;flex:none;display:flex;align-items:center;justify-content:center;\n color:var(--sl-muted);font-size:12px}\n.sl-seccard-x:hover{color:var(--sl-text)}\n.sl-seccard-zone{font-size:11.5px;color:var(--sl-muted);margin-top:6px}\n.sl-seccard-left{color:var(--sl-text);font-weight:700}\n.sl-seccard-mix{display:flex;flex-wrap:wrap;gap:6px 10px;margin-top:8px}\n.sl-seccard-mix-item{display:inline-flex;align-items:center;gap:5px;font-size:11.5px;color:var(--sl-muted)}\n.sl-seccard-mix-dot{width:8px;height:8px;border-radius:50%;flex:none}\n.sl-seccard-mix-price{font-weight:700;color:var(--sl-text)}\n.sl-seccard-foot{display:flex;align-items:center;justify-content:space-between;gap:8px;margin-top:10px}\n.sl-seccard-overview{font-size:12px;font-weight:800;color:var(--sl-accent)}\n.sl-seccard-hint{font-size:10.5px;color:var(--sl-muted)}\n\n/* view-from-seat button on the confirm popover */\n.sl-confirm-view{width:100%;margin-top:9px;padding:8px;border-radius:8px;border:1px solid var(--sl-line);\n color:var(--sl-text);font-weight:700;font-size:12px;display:flex;align-items:center;justify-content:center;gap:7px}\n.sl-confirm-view:hover{border-color:var(--sl-muted)}\n.sl-confirm-view svg{width:14px;height:14px;stroke:currentColor;stroke-width:2;fill:none;stroke-linecap:round;stroke-linejoin:round}\n\n/* 360° seat-view modal (fills the widget; drag-to-look-around equirectangular) */\n.sl-view{position:absolute;inset:0;z-index:12;display:flex;flex-direction:column;background:var(--sl-bg)}\n.sl-view-head{display:flex;align-items:center;gap:8px;padding:12px 16px;border-bottom:1px solid var(--sl-line);flex:none}\n.sl-view-title{font-weight:800;font-size:15px}\n.sl-view-cap{font-size:11px;color:var(--sl-muted)}\n.sl-view-x{margin-left:auto;width:32px;height:32px;border-radius:999px;border:1px solid var(--sl-line);color:var(--sl-muted);\n flex:none;display:flex;align-items:center;justify-content:center;transition:color .15s,border-color .15s}\n.sl-view-x:hover{color:var(--sl-text);border-color:var(--sl-muted)}\n.sl-view-x svg{width:14px;height:14px;stroke:currentColor;stroke-width:2;fill:none;stroke-linecap:round}\n.sl-view-pano{position:relative;flex:1;min-height:0;overflow:hidden;cursor:grab;background-color:#05070c;\n background-repeat:repeat-x;touch-action:none;user-select:none}\n.sl-view-pano.drag{cursor:grabbing}\n.sl-view-badge{position:absolute;top:12px;left:12px;padding:5px 11px;border-radius:999px;font-size:10px;font-weight:800;\n letter-spacing:.08em;background:var(--sl-surface);border:1px solid var(--sl-line);color:var(--sl-muted)}\n.sl-view-hint{position:absolute;left:50%;bottom:12px;transform:translateX(-50%);padding:6px 14px;border-radius:999px;\n font-size:11.5px;font-weight:600;background:var(--sl-surface);border:1px solid var(--sl-line);color:var(--sl-muted);\n white-space:nowrap;pointer-events:none;max-width:90%;overflow:hidden;text-overflow:ellipsis}\n\n/* modal host */\n.sl-modal-scrim{position:fixed;inset:0;z-index:2147483000;background:rgba(5,7,12,.66);display:flex;align-items:center;justify-content:center;padding:18px}\n.sl-modal-frame{width:min(1200px,100%);height:min(820px,100%);border-radius:16px;overflow:hidden;box-shadow:0 40px 120px -30px rgba(0,0,0,.8)}\n@media(max-width:640px){.sl-modal-scrim{padding:0}.sl-modal-frame{width:100%;height:100%;border-radius:0}}\n`;\n\nfunction ensureStyle(): void {\n if (document.getElementById(STYLE_ID)) return;\n const el = document.createElement('style');\n el.id = STYLE_ID;\n el.textContent = CSS;\n document.head.appendChild(el);\n}\n\n/** Merge order: defaults ← org chart theme ← host overrides. */\nfunction resolveTokens(chart: ChartTheme | undefined, host: SeatPickerTheme | undefined): Record<string, string> {\n const accent = host?.accent ?? chart?.accent ?? '#f4b740';\n const accentInk = host?.accentInk ?? chart?.accentInk ?? '#1a1200';\n return {\n '--sl-accent': accent,\n '--sl-accent-ink': accentInk,\n '--sl-bg': host?.background ?? chart?.background ?? '#0f1522',\n '--sl-surface': host?.surface ?? '#1a2234',\n '--sl-text': host?.text ?? chart?.textColor ?? '#eef1f8',\n '--sl-muted': host?.muted ?? '#8b93a7',\n '--sl-line': host?.line ?? 'rgba(139,147,167,.22)',\n '--sl-font': host?.fontFamily ?? chart?.fontFamily ?? \"-apple-system,BlinkMacSystemFont,'Segoe UI',Inter,sans-serif\",\n '--sl-radius': `${host?.radius ?? 14}px`,\n };\n}\n\nexport class SeatPicker {\n private readonly opts: SeatPickerOptions;\n private readonly controller: PickerController;\n\n private root: HTMLDivElement | null = null;\n private mapHost: HTMLDivElement | null = null;\n private rendered = false;\n private destroyed = false;\n\n // chrome refs\n private els: Record<string, HTMLElement> = {};\n private ro: ResizeObserver | null = null;\n private holdTimer: ReturnType<typeof setInterval> | null = null;\n private toastTimer: ReturnType<typeof setTimeout> | null = null;\n\n // state\n private currency = 'USD';\n private hold: HoldResult | null = null;\n /** Latest server expiry for the open hold (moves on extend). */\n private holdExpiresAt = 0;\n /** True once we handed off to checkout — arms booked-confirmation detection. */\n private handedOff = false;\n /** Guards single onBooked + single success overlay per hold. */\n private bookedShown = false;\n private extendEl: HTMLDivElement | null = null;\n private bookedEl: HTMLDivElement | null = null;\n private gaQty = new Map<string, number>();\n private tipEl: HTMLDivElement | null = null;\n private tipPos = { x: 0, y: 0 };\n private confirmEl: HTMLDivElement | null = null;\n private confirmSeat: ExpandedSeat | null = null;\n private srEl: HTMLDivElement | null = null;\n private a11yFilter: AccessibilityType | 'all' = 'all';\n private baQty = 2;\n private baCat = '';\n\n // arena / multi-floor / seat-view chrome\n private rungsEl: HTMLDivElement | null = null;\n private floorsEl: HTMLDivElement | null = null;\n private secCardEl: HTMLDivElement | null = null;\n private viewEl: HTMLDivElement | null = null;\n private viewCleanup: (() => void) | null = null;\n private allSeatsCache: ExpandedSeat[] | null = null;\n\n // modal plumbing (set by open())\n private modalScrim: HTMLElement | null = null;\n private prevFocus: Element | null = null;\n private escHandler: ((e: KeyboardEvent) => void) | null = null;\n\n /** Set by open(): closes the modal (scroll restore + destroy + onClose). */\n private closeModal: (() => void) | null = null;\n\n /**\n * Close the picker. In modal mode (SeatPicker.open()) this dismisses the\n * modal exactly like ESC/scrim/✕ — restores page scroll and fires onClose.\n * For inline mounts it simply destroys the widget.\n */\n close(): void {\n if (this.closeModal) this.closeModal();\n else this.destroy();\n }\n\n /** Mount the full picker as a document-level modal. Resolves after render. */\n static async open(options: Omit<SeatPickerOptions, 'container'>): Promise<SeatPicker> {\n ensureStyle();\n const scrim = document.createElement('div');\n scrim.className = 'sl-modal-scrim';\n const frame = document.createElement('div');\n frame.className = 'sl-modal-frame';\n scrim.appendChild(frame);\n document.body.appendChild(scrim);\n const prevOverflow = document.body.style.overflow;\n document.body.style.overflow = 'hidden';\n\n const picker = new SeatPicker({ ...options, container: frame });\n picker.modalScrim = scrim;\n picker.prevFocus = document.activeElement;\n const close = (): void => {\n document.body.style.overflow = prevOverflow;\n picker.destroy();\n options.onClose?.();\n };\n picker.closeModal = close;\n scrim.addEventListener('mousedown', (e) => {\n if (e.target === scrim) close();\n });\n picker.escHandler = (e: KeyboardEvent) => {\n if (e.key === 'Escape') close();\n };\n document.addEventListener('keydown', picker.escHandler);\n await picker.render();\n picker.els.close?.classList.add('on');\n picker.els.close?.addEventListener('click', close);\n return picker;\n }\n\n constructor(options: SeatPickerOptions) {\n if (!options || typeof options !== 'object') throw new Error('seatmap: options object is required');\n if (!options.event || typeof options.event !== 'string') throw new Error('seatmap: `event` key is required');\n if (!options.container) throw new Error('seatmap: `container` is required (or use SeatPicker.open())');\n this.opts = options;\n const api = new PubApi((options.apiBase ?? DEFAULT_API_BASE).replace(/\\/+$/, ''));\n this.controller = new PickerController({\n transport: api,\n eventKey: options.event,\n maxSelection: options.maxSelection ?? DEFAULT_MAX_SELECTION,\n currency: options.currency,\n flashOnLiveChange: true,\n colorblindSafe: options.colorblindSafe,\n onSelectionChange: () => this.syncTray(),\n onStatusChange: () => {\n this.syncPrices();\n this.evictTakenSelections();\n this.detectBooked();\n },\n onHoldExpired: () => {\n this.hold = null;\n this.handedOff = false;\n this.bookedShown = false;\n this.stopHoldTimer();\n this.gaQty.clear();\n this.toast(t('picker.holdExpired', undefined) || 'Your hold expired — seats released. Pick again.');\n this.syncTray();\n this.opts.onHoldExpired?.();\n },\n confirmSelection: options.confirmSelection,\n onSelect: (seat) => {\n if (this.opts.confirmSelection) this.showConfirm(seat);\n },\n onViewChange: () => {\n this.reanchorConfirm();\n this.syncRung();\n },\n // Tapped-section glide-in → surface (or clear) the section-summary card.\n onSectionFocus: (summary) => this.showSectionCard(summary),\n onFocusSeat: (seat) => this.announceSeat(seat),\n onSeatHover: (d) => this.updateTooltip(d),\n onHint: (m) => {\n if (m) this.toast(m);\n },\n onError: (err) => this.opts.onError?.(err),\n });\n }\n\n async render(): Promise<this> {\n if (this.rendered) return this;\n this.rendered = true;\n ensureStyle();\n await loadLocale(this.opts.locale);\n if (this.opts.messages) setStringOverrides(this.opts.messages);\n\n const mount = resolveContainer(this.opts.container!);\n const root = document.createElement('div');\n root.className = 'sl-picker';\n this.root = root;\n mount.appendChild(root);\n\n // skeleton first — tokens get re-applied once the chart theme arrives\n Object.entries(resolveTokens(undefined, this.opts.theme)).forEach(([k, v]) => root.style.setProperty(k, v));\n root.innerHTML = `\n <div class=\"sl-head\">\n <div class=\"sl-logo\" data-ref=\"logo\"></div>\n <div class=\"sl-head-info\">\n <div class=\"sl-head-name\" data-ref=\"name\"></div>\n <div class=\"sl-head-meta\" data-ref=\"meta\"></div>\n </div>\n <span class=\"sl-hold-pill\" data-ref=\"hold\"></span>\n <button type=\"button\" class=\"sl-close\" data-ref=\"close\" aria-label=\"Close\">\n <svg viewBox=\"0 0 24 24\"><line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"/><line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"/></svg>\n </button>\n </div>\n <div class=\"sl-body\">\n <div class=\"sl-map\">\n <div class=\"sl-map-host\" data-ref=\"map\"></div>\n <div class=\"sl-zoom\">\n <button type=\"button\" aria-label=\"Zoom in\" data-ref=\"zin\">+</button>\n <button type=\"button\" aria-label=\"Zoom out\" data-ref=\"zout\">−</button>\n <button type=\"button\" aria-label=\"Fit to screen\" data-ref=\"zfit\">\n <svg viewBox=\"0 0 24 24\"><path d=\"M8 3H5a2 2 0 0 0-2 2v3M16 3h3a2 2 0 0 1 2 2v3M8 21H5a2 2 0 0 1-2-2v-3M16 21h3a2 2 0 0 0 2-2v-3\"/></svg>\n </button>\n </div>\n <div class=\"sl-boot\" data-ref=\"boot\"><span class=\"sl-boot-spin\"></span>Loading seat map…</div>\n <div class=\"sl-toast\" data-ref=\"toast\" role=\"status\" aria-live=\"polite\"></div>\n </div>\n <div class=\"sl-side\">\n <div class=\"sl-sec\" data-ref=\"pricesSec\">Prices</div>\n <div class=\"sl-prices\" data-ref=\"prices\"></div>\n <div class=\"sl-sec\">Your seats</div>\n <div class=\"sl-tray\" data-ref=\"tray\"></div>\n <div class=\"sl-foot\">\n <div class=\"sl-total\"><span data-ref=\"count\"></span><b data-ref=\"total\"></b></div>\n <button type=\"button\" class=\"sl-cta\" data-ref=\"cta\" disabled></button>\n </div>\n </div>\n </div>`;\n root.querySelectorAll<HTMLElement>('[data-ref]').forEach((el) => {\n this.els[el.dataset.ref!] = el;\n });\n this.mapHost = this.els.map as HTMLDivElement;\n\n // container-adaptive layout\n this.ro = new ResizeObserver(() => {\n const w = root.clientWidth;\n root.dataset.layout = w < 640 ? 'narrow' : 'wide';\n });\n this.ro.observe(root);\n\n // zoom + tooltip wiring\n this.els.zin.addEventListener('click', () => this.controller.zoomIn());\n this.els.zout.addEventListener('click', () => this.controller.zoomOut());\n this.els.zfit.addEventListener('click', () => this.controller.zoomToFit());\n this.tipEl = document.createElement('div');\n this.tipEl.setAttribute('role', 'tooltip');\n this.tipEl.style.cssText =\n 'position:absolute;z-index:7;pointer-events:none;display:none;max-width:240px;background:var(--sl-surface);' +\n 'color:var(--sl-text);border:1px solid var(--sl-line);border-radius:10px;padding:9px 12px;font-size:12px;line-height:1.45;';\n this.els.map.appendChild(this.tipEl);\n this.els.map.addEventListener('mousemove', (e: MouseEvent) => {\n const r = this.els.map.getBoundingClientRect();\n this.tipPos = { x: e.clientX - r.left, y: e.clientY - r.top };\n if (this.tipEl && this.tipEl.style.display !== 'none') this.placeTooltip();\n });\n\n this.els.cta.addEventListener('click', () => void this.handleCta());\n\n const canvasHost = document.createElement('div');\n canvasHost.style.cssText = 'position:absolute;inset:0';\n this.mapHost.appendChild(canvasHost);\n const info = await this.controller.render(canvasHost);\n if (this.destroyed) return this;\n if (!info) {\n this.els.boot.innerHTML =\n '<div class=\"sl-boot-title\">The seat map didn’t load</div>' +\n '<div>Check your connection and try again.</div>' +\n '<button type=\"button\" class=\"sl-boot-retry\">Try again</button>';\n this.els.boot.querySelector('button')!.addEventListener('click', () => {\n // full remount: cheapest reliable recovery\n const container = this.opts.container!;\n const opts = this.opts;\n this.destroy();\n void new SeatPicker({ ...opts, container }).render();\n });\n return this;\n }\n this.els.boot.remove();\n\n if (info.mode === 'test') {\n const ribbon = document.createElement('div');\n ribbon.textContent = t('picker.testMode');\n ribbon.setAttribute('aria-label', t('picker.testMode'));\n ribbon.style.cssText =\n 'position:absolute;top:18px;right:-34px;z-index:6;transform:rotate(45deg);' +\n 'width:140px;text-align:center;padding:4px 0;background:#f4b740;color:#1a1200;' +\n 'font:800 10.5px/1.4 -apple-system,BlinkMacSystemFont,sans-serif;letter-spacing:.12em;' +\n 'box-shadow:0 2px 8px rgba(0,0,0,.25);pointer-events:none;';\n this.els.map.style.overflow = 'hidden';\n this.els.map.appendChild(ribbon);\n }\n\n // theme: defaults ← org chart theme ← host overrides\n const chartTheme = this.controller.doc?.theme;\n Object.entries(resolveTokens(chartTheme, this.opts.theme)).forEach(([k, v]) => root.style.setProperty(k, v));\n this.currency = info.currency ?? this.opts.currency ?? 'USD';\n\n // header\n const logoUrl = this.opts.theme?.logoUrl ?? chartTheme?.logoUrl;\n if (logoUrl) this.els.logo.innerHTML = `<img src=\"${logoUrl}\" alt=\"\">`;\n else this.els.logo.textContent = (this.opts.theme?.brandName ?? chartTheme?.brandName ?? info.eventName ?? '?').slice(0, 1).toUpperCase();\n this.els.name.textContent = info.eventName ?? '';\n const when = info.startsAt\n ? new Date(info.startsAt).toLocaleString(this.opts.locale, { month: 'short', day: 'numeric', hour: 'numeric', minute: '2-digit' })\n : '';\n this.els.meta.textContent = [info.venue, when].filter(Boolean).join(' · ');\n\n // Accessibility filter chips — only for types actually present in the chart.\n const present = new Set<AccessibilityType>();\n if (this.controller.doc) {\n for (const seat of expandChart(this.controller.doc)) {\n for (const type of seat.accessibility ?? []) present.add(type);\n if (seat.accessible && !seat.accessibility?.length) present.add('wheelchair');\n }\n }\n if (present.size) {\n const chips = document.createElement('div');\n chips.className = 'sl-chips';\n const GLYPH: Partial<Record<AccessibilityType, string>> = { wheelchair: '♿', companion: '🧑🤝🧑' };\n const mk = (key: AccessibilityType | 'all', label: string): string =>\n `<button type=\"button\" class=\"sl-chip-f${key === 'all' ? ' on' : ''}\" data-f=\"${key}\">${label}</button>`;\n chips.innerHTML =\n mk('all', 'All seats') +\n [...present]\n .map((type) => mk(type, `${GLYPH[type] ? GLYPH[type] + ' ' : ''}${type[0].toUpperCase()}${type.slice(1).replace(/-/g, ' ')}`))\n .join('');\n this.els.map.appendChild(chips);\n chips.querySelectorAll<HTMLButtonElement>('button').forEach((btn) => {\n btn.addEventListener('click', () => {\n const f = btn.dataset.f as AccessibilityType | 'all';\n this.a11yFilter = f;\n chips.querySelectorAll('button').forEach((b) => b.classList.toggle('on', b === btn));\n this.controller.setAccessibilityFilter(f === 'all' ? null : [f]);\n });\n });\n }\n\n // Colorblind-safe toggle rides in the zoom column.\n const cb = document.createElement('button');\n cb.type = 'button';\n cb.setAttribute('aria-label', 'Toggle colorblind-friendly colors');\n cb.setAttribute('aria-pressed', String(!!this.opts.colorblindSafe));\n cb.innerHTML = '<svg viewBox=\"0 0 24 24\"><path d=\"M1 12s4-7 11-7 11 7 11 7-4 7-11 7S1 12 1 12z\"/><circle cx=\"12\" cy=\"12\" r=\"3\"/></svg>';\n this.els.zfit.parentElement!.appendChild(cb);\n let cbOn = !!this.opts.colorblindSafe;\n cb.addEventListener('click', () => {\n cbOn = !cbOn;\n cb.setAttribute('aria-pressed', String(cbOn));\n this.controller.setColorblindSafe(cbOn);\n });\n\n // Screen-reader announcements for keyboard seat focus.\n this.srEl = document.createElement('div');\n this.srEl.className = 'sl-sr';\n this.srEl.setAttribute('aria-live', 'polite');\n root.appendChild(this.srEl);\n\n // Big-venue chrome: LOD rung pills, multi-floor switcher, section card.\n // Appended AFTER controller.render() — render() wipes the map host's children.\n this.buildArenaChrome();\n\n // \"Need more time?\" prompt (over the map) + booked-confirmation overlay (over\n // the whole widget). Both appended post-render for the same wipe reason.\n this.buildExtendPrompt();\n this.buildBookedOverlay();\n\n this.syncPrices();\n this.syncTray();\n return this;\n }\n\n /** The \"Need more time?\" prompt shown in the hold's final EXTEND_PROMPT_MS. */\n private buildExtendPrompt(): void {\n const el = document.createElement('div');\n el.className = 'sl-extend';\n el.setAttribute('role', 'status');\n el.innerHTML =\n `<span class=\"sl-extend-txt\" data-ref=\"extendTxt\"></span>` +\n `<button type=\"button\" class=\"sl-extend-btn\" data-ref=\"extendBtn\"></button>`;\n this.els.map.appendChild(el);\n this.extendEl = el;\n this.els.extendTxt = el.querySelector('[data-ref=\"extendTxt\"]') as HTMLElement;\n this.els.extendBtn = el.querySelector('[data-ref=\"extendBtn\"]') as HTMLElement;\n this.els.extendBtn.textContent = 'Add time';\n this.els.extendBtn.addEventListener('click', () => void this.handleExtend());\n }\n\n /** Success overlay + onBooked fire when the held seats settle to booked. */\n private buildBookedOverlay(): void {\n const el = document.createElement('div');\n el.className = 'sl-booked';\n el.setAttribute('role', 'status');\n el.setAttribute('aria-live', 'polite');\n el.innerHTML =\n `<div class=\"sl-booked-badge\"><svg viewBox=\"0 0 24 24\"><path d=\"M20 6L9 17l-5-5\"/></svg></div>` +\n `<div class=\"sl-booked-title\">You're all set</div>` +\n `<div class=\"sl-booked-sub\" data-ref=\"bookedSub\"></div>`;\n this.root!.appendChild(el);\n this.bookedEl = el;\n this.els.bookedSub = el.querySelector('[data-ref=\"bookedSub\"]') as HTMLElement;\n }\n\n // ---- arena / multi-floor chrome -------------------------------------------\n\n /** Build the rung pills (charts with sections) and floor switcher (>1 floor). */\n private buildArenaChrome(): void {\n const doc = this.controller.doc;\n if (!doc || !this.els.map) return;\n const hasSections = doc.objects.some((o) => o.type === 'section')\n || (doc.floors ?? []).some((f) => f.objects.some((o) => o.type === 'section'));\n\n // LOD rung pills — jump straight between zones / sections / seats.\n if (hasSections) {\n const RUNGS: LodRung[] = ['zones', 'sections', 'seats'];\n const pills = document.createElement('div');\n pills.className = 'sl-rungs on';\n pills.setAttribute('role', 'group');\n pills.setAttribute('aria-label', t('picker.zoomLevel'));\n const LABEL: Record<LodRung, string> = {\n zones: t('picker.rungLabel.zones'),\n sections: t('picker.rungLabel.sections'),\n seats: t('picker.rungLabel.seats'),\n };\n const TIP: Record<LodRung, string> = {\n zones: t('picker.rungTip.zones'),\n sections: t('picker.rungTip.sections'),\n seats: t('picker.rungTip.seats'),\n };\n pills.innerHTML = RUNGS.map(\n (r) => `<button type=\"button\" data-rung=\"${r}\" title=\"${TIP[r]}\" aria-pressed=\"false\">${LABEL[r]}</button>`,\n ).join('');\n pills.querySelectorAll<HTMLButtonElement>('button').forEach((btn) => {\n btn.addEventListener('click', () => this.controller.setRung(btn.dataset.rung as LodRung));\n });\n this.els.map.appendChild(pills);\n this.rungsEl = pills;\n this.syncRung();\n }\n\n // Multi-floor switcher — only when the chart truly has >1 floor.\n if (this.controller.isMultiFloor()) {\n const floors = this.controller.getFloors();\n const rail = document.createElement('div');\n rail.className = 'sl-floors on';\n rail.setAttribute('role', 'group');\n rail.setAttribute('aria-label', t('picker.floor'));\n rail.innerHTML = floors\n .map((f) => `<button type=\"button\" data-floor=\"${f.id}\">${f.name}</button>`)\n .join('');\n rail.querySelectorAll<HTMLButtonElement>('button').forEach((btn) => {\n btn.addEventListener('click', () => {\n this.controller.setFloor(btn.dataset.floor!);\n this.showSectionCard(null);\n this.syncFloors();\n this.syncRung();\n });\n });\n this.els.map.appendChild(rail);\n this.floorsEl = rail;\n this.syncFloors();\n }\n }\n\n /** Reflect the engine's current LOD rung onto the pill group. */\n private syncRung(): void {\n if (!this.rungsEl) return;\n const active = this.controller.getRung();\n this.rungsEl.querySelectorAll<HTMLButtonElement>('button').forEach((btn) => {\n const on = btn.dataset.rung === active;\n btn.classList.toggle('on', on);\n btn.setAttribute('aria-pressed', String(on));\n });\n }\n\n /** Reflect the active floor onto the switcher rail. */\n private syncFloors(): void {\n if (!this.floorsEl) return;\n const active = this.controller.getActiveFloorId();\n this.floorsEl.querySelectorAll<HTMLButtonElement>('button').forEach((btn) => {\n btn.classList.toggle('on', btn.dataset.floor === active);\n });\n }\n\n /** Show (or clear, on null) the tapped-section summary card. */\n private showSectionCard(summary: SectionSummary | null): void {\n if (!summary) {\n this.secCardEl?.remove();\n this.secCardEl = null;\n return;\n }\n if (!this.els.map) return;\n this.secCardEl?.remove();\n const priceLabel =\n summary.priceMin === summary.priceMax\n ? this.money(summary.priceMin)\n : `${this.money(summary.priceMin)}–${this.money(summary.priceMax)}`;\n const card = document.createElement('div');\n card.className = 'sl-seccard on';\n card.setAttribute('role', 'dialog');\n card.setAttribute('aria-label', t('picker.sectionSummaryAria', { label: summary.label }));\n const mix = summary.categories\n .map(\n (c) =>\n `<span class=\"sl-seccard-mix-item\"><span class=\"sl-seccard-mix-dot\" style=\"background:${c.color}\"></span>` +\n `${c.label} <span class=\"sl-seccard-mix-price\">${this.money(c.price)}</span></span>`,\n )\n .join('');\n card.innerHTML =\n `<div class=\"sl-seccard-head\"><span class=\"sl-seccard-dot\" style=\"background:${summary.color}\"></span>` +\n `<span class=\"sl-seccard-name\">${summary.label}</span>` +\n (summary.categories.length ? `<span class=\"sl-seccard-price\">${priceLabel}</span>` : '') +\n `<button type=\"button\" class=\"sl-seccard-x\" aria-label=\"${t('picker.closeSectionSummary')}\">✕</button></div>` +\n `<div class=\"sl-seccard-zone\">${summary.zoneLabel ? `${summary.zoneLabel} · ` : ''}` +\n `<span class=\"sl-seccard-left\">${tCount('picker.seatsLeftInSection', summary.seatsLeft)}</span></div>` +\n (mix ? `<div class=\"sl-seccard-mix\">${mix}</div>` : '') +\n `<div class=\"sl-seccard-foot\">` +\n `<button type=\"button\" class=\"sl-seccard-overview\">← ${t('picker.overview')}</button>` +\n `<span class=\"sl-seccard-hint\">${t('picker.tapSeatHint')}</span></div>`;\n card.querySelector('.sl-seccard-x')!.addEventListener('click', () => this.controller.overview());\n card.querySelector('.sl-seccard-overview')!.addEventListener('click', () => this.controller.overview());\n this.els.map.appendChild(card);\n this.secCardEl = card;\n }\n\n /** aria-live readout when keyboard focus lands on a seat. */\n private announceSeat(seat: ExpandedSeat | null): void {\n if (!this.srEl) return;\n if (!seat) {\n this.srEl.textContent = '';\n return;\n }\n const cat = this.controller.doc?.categories.find((c) => c.key === seat.categoryKey);\n const status = this.controller.getStatus(seat.id) ?? 'free';\n const statusText = status === 'free' ? 'available' : status === 'held' ? 'on hold' : 'taken';\n const price = cat?.tiers?.length ? cat.tiers[0].price : cat?.price;\n this.srEl.textContent = `Seat ${seat.label}, ${cat?.label ?? seat.categoryKey}${\n price != null ? `, ${this.money(price)}` : ''\n }, ${statusText}`;\n }\n\n // ---- confirm popover (opt-in confirmSelection mode) ------------------------\n\n private showConfirm(seat: ExpandedSeat): void {\n this.closeConfirm();\n if (this.tipEl) this.tipEl.style.display = 'none';\n const cat = this.controller.doc?.categories.find((c) => c.key === seat.categoryKey);\n const price = cat?.tiers?.length ? cat.tiers[0].price : cat?.price;\n const el = document.createElement('div');\n el.className = 'sl-confirm';\n el.innerHTML =\n `<div class=\"sl-confirm-label\">${seat.label}</div>` +\n `<div class=\"sl-confirm-meta\"><span class=\"sl-dot\" style=\"background:${cat?.color ?? '#6e7bff'}\"></span>` +\n `${cat?.label ?? seat.categoryKey}${price != null ? `<b>${this.money(price)}</b>` : ''}</div>` +\n (this.seatViewEnabled()\n ? `<button type=\"button\" class=\"sl-confirm-view\">` +\n `<svg viewBox=\"0 0 24 24\"><path d=\"M1 12s4-7 11-7 11 7 11 7-4 7-11 7S1 12 1 12z\"/><circle cx=\"12\" cy=\"12\" r=\"3\"/></svg>` +\n `${t('picker.open360')}</button>`\n : '') +\n `<div class=\"sl-confirm-row\">` +\n `<button type=\"button\" class=\"sl-confirm-cancel\">Cancel</button>` +\n `<button type=\"button\" class=\"sl-confirm-add\">Add seat</button></div>`;\n this.els.map.appendChild(el);\n this.confirmEl = el;\n this.confirmSeat = seat;\n this.reanchorConfirm();\n el.querySelector('.sl-confirm-view')?.addEventListener('click', () => this.openSeatView(seat));\n el.querySelector('.sl-confirm-add')!.addEventListener('click', () => this.closeConfirm());\n el.querySelector('.sl-confirm-cancel')!.addEventListener('click', () => {\n this.controller.deselect([seat.id]);\n this.closeConfirm();\n });\n }\n\n private reanchorConfirm(): void {\n if (!this.confirmEl || !this.confirmSeat) return;\n const p = this.controller.worldToScreen({ x: this.confirmSeat.x, y: this.confirmSeat.y });\n this.confirmEl.style.left = `${p.x}px`;\n this.confirmEl.style.top = `${p.y}px`;\n }\n\n private closeConfirm(): void {\n this.confirmEl?.remove();\n this.confirmEl = null;\n this.confirmSeat = null;\n }\n\n // ---- 360° view-from-seat modal --------------------------------------------\n\n private seatViewEnabled(): boolean {\n return this.opts.seatView !== false;\n }\n\n /** Every bookable seat (cached) — neighbor heads for the generated panorama. */\n private allSeats(): ExpandedSeat[] {\n if (!this.allSeatsCache) {\n const doc = this.controller.doc;\n this.allSeatsCache = doc ? expandChart(doc) : [];\n }\n return this.allSeatsCache;\n }\n\n /**\n * Open the drag-to-look-around 360° preview for a seat. Uses the organizer's\n * uploaded photo (seat.viewUrl) when present, else a panorama generated from\n * the chart geometry — the stage placed at this seat's true bearing + size.\n * Zero extra dependencies: an equirectangular image panned with `repeat-x`.\n */\n private openSeatView(seat: ExpandedSeat): void {\n if (!this.root || !this.seatViewEnabled()) return;\n this.closeSeatView();\n this.closeConfirm();\n\n const doc = this.controller.doc;\n const activeId = this.controller.getActiveFloorId();\n const focal = doc?.floors?.find((f) => f.id === activeId)?.focalPoint ?? doc?.focalPoint ?? { x: 0, y: 0 };\n let panoUrl: string;\n let caption: string;\n let real = false;\n if (seat.viewUrl) {\n panoUrl = seat.viewUrl;\n caption = t('picker.panorama360');\n real = true;\n } else {\n const pano = generateSeatPanorama(seat, focal, this.allSeats());\n panoUrl = pano.url;\n caption = t('picker.illustrationCaption', { m: pano.distanceM });\n }\n\n const el = document.createElement('div');\n el.className = 'sl-view';\n el.setAttribute('role', 'dialog');\n el.setAttribute('aria-label', t('picker.viewFromSeat', { label: seat.label }));\n el.innerHTML =\n `<div class=\"sl-view-head\">` +\n `<span class=\"sl-view-title\">${t('picker.viewFromSeat', { label: seat.label })}</span>` +\n `<span class=\"sl-view-cap\">${caption}</span>` +\n `<button type=\"button\" class=\"sl-view-x\" aria-label=\"Close\">` +\n `<svg viewBox=\"0 0 24 24\"><line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"/><line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"/></svg></button></div>` +\n `<div class=\"sl-view-pano\">` +\n `<span class=\"sl-view-badge\">${real ? t('picker.real360') : t('picker.preview')}</span>` +\n `<span class=\"sl-view-hint\">Drag to look around · scroll to zoom</span>` +\n `</div>`;\n this.root.appendChild(el);\n this.viewEl = el;\n\n const pano = el.querySelector<HTMLDivElement>('.sl-view-pano')!;\n pano.style.backgroundImage = `url(\"${panoUrl}\")`;\n\n // Equirectangular pan: repeat-x gives seamless 360° horizontal wrap; the\n // image is sized taller than the viewport so there's headroom to tilt.\n let zoom = 1.2;\n let posX = 0;\n let posY = 0;\n const apply = (): void => {\n const h = pano.clientHeight || 1;\n const bgH = h * zoom;\n const overV = Math.max(0, bgH - h);\n posY = Math.min(overV / 2, Math.max(-overV / 2, posY));\n pano.style.backgroundSize = `auto ${bgH}px`;\n pano.style.backgroundPosition = `${posX}px ${posY + overV / 2}px`;\n };\n apply();\n\n let dragging = false;\n let lastX = 0;\n let lastY = 0;\n const onDown = (e: PointerEvent): void => {\n dragging = true;\n lastX = e.clientX;\n lastY = e.clientY;\n pano.classList.add('drag');\n pano.setPointerCapture?.(e.pointerId);\n };\n const onMove = (e: PointerEvent): void => {\n if (!dragging) return;\n posX += e.clientX - lastX;\n posY += e.clientY - lastY;\n lastX = e.clientX;\n lastY = e.clientY;\n apply();\n };\n const onUp = (e: PointerEvent): void => {\n dragging = false;\n pano.classList.remove('drag');\n pano.releasePointerCapture?.(e.pointerId);\n };\n const onWheel = (e: WheelEvent): void => {\n e.preventDefault();\n zoom = Math.min(2.4, Math.max(1, zoom + (e.deltaY < 0 ? 0.12 : -0.12)));\n apply();\n };\n pano.addEventListener('pointerdown', onDown);\n pano.addEventListener('pointermove', onMove);\n pano.addEventListener('pointerup', onUp);\n pano.addEventListener('pointercancel', onUp);\n pano.addEventListener('wheel', onWheel, { passive: false });\n\n const closeBtn = el.querySelector<HTMLButtonElement>('.sl-view-x')!;\n closeBtn.addEventListener('click', () => this.closeSeatView());\n const onKey = (e: KeyboardEvent): void => {\n if (e.key === 'Escape') {\n e.stopPropagation();\n this.closeSeatView();\n }\n };\n el.addEventListener('keydown', onKey);\n closeBtn.focus();\n\n this.viewCleanup = () => {\n pano.removeEventListener('pointerdown', onDown);\n pano.removeEventListener('pointermove', onMove);\n pano.removeEventListener('pointerup', onUp);\n pano.removeEventListener('pointercancel', onUp);\n pano.removeEventListener('wheel', onWheel);\n el.removeEventListener('keydown', onKey);\n };\n }\n\n private closeSeatView(): void {\n this.viewCleanup?.();\n this.viewCleanup = null;\n this.viewEl?.remove();\n this.viewEl = null;\n }\n\n // ---- chrome sync ----------------------------------------------------------\n\n private money(n: number): string {\n try {\n return new Intl.NumberFormat(this.opts.locale, { style: 'currency', currency: this.currency }).format(n);\n } catch {\n return `${n} ${this.currency}`;\n }\n }\n\n private syncPrices(): void {\n const doc = this.controller.doc;\n if (!doc || !this.els.prices) return;\n const left = this.controller.categoryAvailability();\n this.els.prices.innerHTML = doc.categories\n .map((c) => {\n const price = c.tiers?.length ? c.tiers[0].price : c.price;\n return (\n `<div class=\"sl-price-row\" data-cat=\"${c.key}\"><span class=\"sl-dot\" style=\"background:${c.color}\"></span>` +\n `<span class=\"sl-price-label\">${c.label}</span>` +\n `<span class=\"sl-price-left\">${left[c.key] ?? 0} left</span>` +\n (price != null ? `<span class=\"sl-price-amt\">${this.money(price)}</span>` : '') +\n `</div>`\n );\n })\n .join('');\n // Legend-hover highlight: dim other categories on the map while hovering a row.\n this.els.prices.querySelectorAll<HTMLElement>('.sl-price-row').forEach((row) => {\n row.addEventListener('mouseenter', () => this.controller.getRenderer()?.setCategoryHighlight?.(row.dataset.cat ?? null));\n row.addEventListener('mouseleave', () => this.controller.getRenderer()?.setCategoryHighlight?.(null));\n });\n }\n\n /** A live delta took one of OUR selected (not yet held) seats — evict + tell the buyer. */\n private evictTakenSelections(): void {\n // Our own hold's WS echo paints our seats 'held' — never treat those as sniped.\n const ownLabels = new Set<string>(this.controller.currentHold()?.labels ?? []);\n const gone = this.controller\n .getSelection()\n .filter((s) => !ownLabels.has(s.label) && (this.controller.getStatus(s.id) ?? 'free') !== 'free');\n if (!gone.length) return;\n this.controller.deselect(gone.map((s) => s.id));\n this.toast(`Seat ${gone[0].label} was just taken by another buyer.`);\n }\n\n private syncTray(): void {\n if (!this.els.tray) return;\n const seats = this.controller.getSelection();\n const gaAreas = this.controller.getGAAreas();\n const heldItems = this.hold?.items ?? [];\n const parts: string[] = [];\n\n if (!seats.length && !heldItems.length && !gaAreas.length) {\n parts.push(`<div class=\"sl-tray-hint\">Tap a seat on the map, or let us pick the best available for you.</div>`);\n } else if (!seats.length && !heldItems.length) {\n parts.push(`<div class=\"sl-tray-hint\">Tap a seat on the map — or grab standing tickets below.</div>`);\n }\n\n // Held line items (best-available or a completed hold) — locked in, no remove.\n // Tier is server-committed on a hold, so it shows read-only (no re-pick).\n for (const item of heldItems) {\n const cat = this.controller.doc?.categories.find((c) => c.key === item.categoryKey);\n const tierName = item.tierId ? cat?.tiers?.find((ti) => ti.id === item.tierId)?.name : undefined;\n const canView = this.seatViewEnabled() && item.objectType !== 'ga' && !!this.controller.seatByLabel(item.label);\n parts.push(\n `<div class=\"sl-chip\"><b>${item.label}</b>` +\n `<span class=\"cat\">${cat?.label ?? item.categoryKey}${tierName ? ` · ${tierName}` : ''}</span>` +\n `<span class=\"amt\">${this.money(item.unitPrice * (item.quantity ?? 1))}</span>` +\n (canView\n ? `<button type=\"button\" class=\"view\" data-view-label=\"${item.label}\" aria-label=\"${t('picker.viewFromSeat', { label: item.label })}\">` +\n `<svg viewBox=\"0 0 24 24\"><path d=\"M1 12s4-7 11-7 11 7 11 7-4 7-11 7S1 12 1 12z\"/><circle cx=\"12\" cy=\"12\" r=\"3\"/></svg></button>`\n : '') +\n `</div>`,\n );\n }\n\n const heldLabels = new Set(heldItems.map((item) => item.label));\n const canView = this.seatViewEnabled();\n for (const s of seats.filter((seat) => !heldLabels.has(seat.label))) {\n const cat = this.controller.doc?.categories.find((c) => c.key === s.categoryKey);\n const tierSelect =\n s.tiers && s.tiers.length\n ? `<select class=\"tier\" data-tier=\"${s.id}\" aria-label=\"${t('picker.ticketTierFor', { label: s.label })}\">` +\n s.tiers\n .map((ti) => `<option value=\"${ti.id}\"${ti.id === s.tierId ? ' selected' : ''}>${ti.name} · ${this.money(ti.price)}</option>`)\n .join('') +\n `</select>`\n : '';\n const viewBtn = canView\n ? `<button type=\"button\" class=\"view\" data-view-label=\"${s.label}\" aria-label=\"${t('picker.viewFromSeat', { label: s.label })}\">` +\n `<svg viewBox=\"0 0 24 24\"><path d=\"M1 12s4-7 11-7 11 7 11 7-4 7-11 7S1 12 1 12z\"/><circle cx=\"12\" cy=\"12\" r=\"3\"/></svg></button>`\n : '';\n parts.push(\n `<div class=\"sl-chip\" data-seat=\"${s.id}\"><b>${s.label}</b>` +\n `<span class=\"cat\">${cat?.label ?? s.categoryKey}</span>` +\n tierSelect +\n `<span class=\"amt\">${this.money(s.price)}</span>` +\n viewBtn +\n `<button type=\"button\" class=\"rm\" aria-label=\"Remove ${s.label}\">` +\n `<svg viewBox=\"0 0 24 24\"><line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"/><line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"/></svg>` +\n `</button></div>`,\n );\n }\n\n for (const area of gaAreas) {\n const qty = this.gaQty.get(area.id) ?? 0;\n parts.push(\n `<div class=\"sl-ga\" data-ga=\"${area.id}\"><div class=\"sl-ga-info\">` +\n `<div class=\"sl-ga-name\">${area.label}</div>` +\n `<div class=\"sl-ga-sub\">${this.money(area.price)} · ${area.available} left</div></div>` +\n `<div class=\"sl-ga-qty\">` +\n `<button type=\"button\" data-d=\"-1\" aria-label=\"Fewer\">−</button><span>${qty}</span>` +\n `<button type=\"button\" data-d=\"1\" aria-label=\"More\">+</button></div></div>`,\n );\n }\n\n // Best available — qty (+ optional category) picked server-side and held atomically.\n if (!this.hold) {\n const cats = this.controller.doc?.categories ?? [];\n parts.push(\n `<div class=\"sl-ba\">` +\n (cats.length > 1\n ? `<select aria-label=\"Category\" data-ba-cat>` +\n `<option value=\"\">Any tier</option>` +\n cats.map((c) => `<option value=\"${c.key}\"${this.baCat === c.key ? ' selected' : ''}>${c.label}</option>`).join('') +\n `</select>`\n : '') +\n `<div class=\"sl-ba-qty\">` +\n `<button type=\"button\" data-ba=\"-1\" aria-label=\"Fewer seats\">−</button><span>${this.baQty}</span>` +\n `<button type=\"button\" data-ba=\"1\" aria-label=\"More seats\">+</button></div>` +\n `<button type=\"button\" class=\"sl-ba-go\">Best available</button></div>`,\n );\n }\n\n this.els.tray.innerHTML = parts.join('');\n this.els.tray.querySelectorAll<HTMLButtonElement>('[data-ba]').forEach((btn) => {\n btn.addEventListener('click', () => {\n this.baQty = Math.max(1, Math.min(8, this.baQty + Number(btn.dataset.ba)));\n this.syncTray();\n });\n });\n this.els.tray.querySelector<HTMLSelectElement>('[data-ba-cat]')?.addEventListener('change', (e) => {\n this.baCat = (e.target as HTMLSelectElement).value;\n });\n this.els.tray.querySelector<HTMLButtonElement>('.sl-ba-go')?.addEventListener('click', () => {\n void this.bestAvailable(this.baQty, this.baCat || undefined);\n });\n this.els.tray.querySelectorAll<HTMLElement>('.sl-chip .rm').forEach((btn) => {\n btn.addEventListener('click', () => {\n const id = (btn.closest('.sl-chip') as HTMLElement).dataset.seat!;\n this.controller.deselect([id]);\n });\n });\n // Per-seat ticket-tier pick (Adult/Child/…) — updates price via onSelectionChange.\n this.els.tray.querySelectorAll<HTMLSelectElement>('.sl-chip .tier').forEach((sel) => {\n sel.addEventListener('change', () => this.controller.setSeatTier(sel.dataset.tier!, sel.value || null));\n });\n // View-from-seat button (data-view-label = seat label) on fresh + held chips.\n this.els.tray.querySelectorAll<HTMLElement>('.sl-chip .view[data-view-label]').forEach((btn) => {\n btn.addEventListener('click', () => {\n const seat = this.controller.seatByLabel(btn.dataset.viewLabel!);\n if (seat) this.openSeatView(seat);\n });\n });\n this.els.tray.querySelectorAll<HTMLElement>('.sl-ga button').forEach((btn) => {\n btn.addEventListener('click', () => {\n const areaEl = btn.closest('.sl-ga') as HTMLElement;\n const id = areaEl.dataset.ga!;\n const area = gaAreas.find((a) => a.id === id);\n const next = Math.max(0, Math.min(area?.available ?? 0, (this.gaQty.get(id) ?? 0) + Number(btn.dataset.d)));\n this.gaQty.set(id, next);\n this.syncTray();\n });\n });\n\n // totals + CTA (held lines + fresh selections + GA)\n const gaTotal = gaAreas.reduce((sum, a) => sum + a.price * (this.gaQty.get(a.id) ?? 0), 0);\n const gaCount = [...this.gaQty.values()].reduce((a, b) => a + b, 0);\n const heldTotal = heldItems.reduce((sum, item) => sum + item.unitPrice * (item.quantity ?? 1), 0);\n const heldCount = heldItems.reduce((sum, item) => sum + (item.quantity ?? 1), 0);\n const freshSeats = seats.filter((seat) => !heldLabels.has(seat.label));\n const total = freshSeats.reduce((sum, s) => sum + s.price, 0) + gaTotal + heldTotal;\n const count = freshSeats.length + gaCount + heldCount;\n this.els.count.textContent = count\n ? `${count} ${count === 1 ? 'ticket' : 'tickets'}`\n : 'No seats selected';\n this.els.total.textContent = count ? this.money(total) : '';\n const cta = this.els.cta as HTMLButtonElement;\n cta.disabled = count === 0;\n cta.textContent = this.hold ? 'Continue to checkout' : count ? 'Hold seats & checkout' : 'Select seats';\n this.opts.onSelectionChange?.(seats);\n }\n\n private async handleCta(): Promise<void> {\n const cta = this.els.cta as HTMLButtonElement;\n // Best-available (or a prior CTA press) already holds the seats — hand off.\n // Held seats are NOT in the client selection (the server holds them), so\n // pass the hold's own seat list to the host.\n if (this.hold && !this.controller.getSelection().some((s) => !(this.hold!.items ?? []).some((i) => i.label === s.label))) {\n const seats = this.hold.seats ?? this.controller.getSelection();\n this.handedOff = true;\n this.opts.onCheckout?.(this.hold, seats, this.buildHandoff(this.hold));\n return;\n }\n cta.disabled = true;\n cta.textContent = 'Holding…';\n try {\n // seats first (controller.hold covers selected seats); GA quantities ride along\n let hold: HoldResult | null = null;\n const gaEntries = [...this.gaQty.entries()].filter(([, q]) => q > 0);\n // Snapshot before hold — the hold's own WS echo repaints these seats.\n const chosenSeats = this.controller.getSelection();\n if (chosenSeats.length) {\n const h = await this.controller.hold(undefined, this.opts.holdTtlMs);\n hold = h ? { holdId: h.holdId, expiresAt: h.expiresAt, seats: h.seats, items: h.items } : null;\n }\n for (const [areaId, qty] of gaEntries) {\n const h = await this.controller.holdGA(areaId, qty, { ttlMs: this.opts.holdTtlMs });\n hold = h ? { holdId: h.holdId, expiresAt: h.expiresAt, seats: h.seats, items: h.items } : hold;\n }\n if (!hold) {\n this.toast('One or more seats were just taken. Please pick again.');\n this.syncTray();\n return;\n }\n this.hold = hold;\n this.handedOff = true;\n this.startHoldTimer(hold.expiresAt);\n this.opts.onCheckout?.(hold, chosenSeats.length ? chosenSeats : hold.seats ?? [], this.buildHandoff(hold));\n } catch (err) {\n this.opts.onError?.(err);\n this.toast('One or more seats were just taken. Please pick again.');\n } finally {\n this.syncTray();\n }\n }\n\n private startHoldTimer(expiresAt: number): void {\n this.stopHoldTimer();\n this.holdExpiresAt = expiresAt;\n const pill = this.els.hold;\n const tick = (): void => {\n const ms = Math.max(0, this.holdExpiresAt - Date.now());\n const m = Math.floor(ms / 60000);\n const s = String(Math.floor((ms % 60000) / 1000)).padStart(2, '0');\n pill.textContent = `Held ${m}:${s}`;\n pill.classList.add('on');\n // Offer an extension in the final stretch (but not once it's booked/expired).\n this.setExtendPrompt(ms > 0 && ms <= EXTEND_PROMPT_MS, ms);\n if (ms <= 0) this.stopHoldTimer();\n };\n tick();\n this.holdTimer = setInterval(tick, 500);\n }\n\n private stopHoldTimer(): void {\n if (this.holdTimer) clearInterval(this.holdTimer);\n this.holdTimer = null;\n this.els.hold?.classList.remove('on');\n this.setExtendPrompt(false, 0);\n }\n\n /** Show/refresh (or hide) the \"Need more time?\" prompt with the live seconds left. */\n private setExtendPrompt(show: boolean, ms: number): void {\n if (!this.extendEl) return;\n if (show && this.controller.currentHold() && !this.bookedShown) {\n const secs = Math.ceil(ms / 1000);\n this.els.extendTxt.innerHTML = `Your seats are held for <b>0:${String(secs).padStart(2, '0')}</b>. Need more time?`;\n this.extendEl.classList.add('on');\n } else {\n this.extendEl.classList.remove('on');\n }\n }\n\n private async handleExtend(): Promise<void> {\n const btn = this.els.extendBtn as HTMLButtonElement;\n btn.disabled = true;\n const prev = btn.textContent;\n btn.textContent = 'Adding…';\n try {\n const h = await this.controller.extendHold(this.opts.holdTtlMs);\n if (h) {\n // The controller re-armed its own expiry; sync ours + the pill, hide prompt.\n this.hold = { holdId: h.holdId, expiresAt: h.expiresAt, seats: h.seats, items: h.items };\n this.holdExpiresAt = h.expiresAt;\n this.extendEl?.classList.remove('on');\n this.toast('More time added — your seats are still held.');\n } else {\n this.toast(\"Couldn't add more time — please head to checkout now.\");\n }\n } catch (err) {\n this.opts.onError?.(err);\n this.toast(\"Couldn't add more time — please head to checkout now.\");\n } finally {\n btn.disabled = false;\n btn.textContent = prev;\n }\n }\n\n /**\n * Fire the booked-confirmation state once the buyer's held seats settle to\n * booked. The controller clears its own hold the moment every held label reads\n * 'booked' over the realtime channel (clearBookedHoldIfSettled), and this runs\n * on the same onStatusChange — so `currentHold() === null` while we still hold\n * a checkout handoff means \"sold\", not expired (expiry clears via onHoldExpired\n * on a different path, which nulls this.hold first).\n */\n private detectBooked(): void {\n if (this.bookedShown || !this.handedOff || !this.hold) return;\n if (this.controller.currentHold() !== null) return; // hold still open\n this.showBooked();\n }\n\n private showBooked(): void {\n if (this.bookedShown || !this.hold) return;\n this.bookedShown = true;\n const handoff = this.buildHandoff(this.hold);\n this.stopHoldTimer();\n const n = handoff.lineItems.reduce((sum, i) => sum + i.quantity, 0);\n if (this.els.bookedSub) {\n this.els.bookedSub.innerHTML =\n `<span class=\"sl-booked-seats\">${n} ${n === 1 ? 'ticket' : 'tickets'}</span> confirmed. ` +\n `A confirmation is on its way.`;\n }\n this.bookedEl?.classList.add('on');\n this.opts.onBooked?.(handoff);\n }\n\n /** Assemble the stable {@link CheckoutHandoff} from a hold's server line items. */\n private buildHandoff(hold: HoldResult): CheckoutHandoff {\n const items = hold.items ?? [];\n const lineItems: CheckoutLineItem[] = items.map((it: HoldLineItem) => ({\n label: it.label,\n objectId: it.objectId,\n objectType: it.objectType,\n categoryKey: it.categoryKey,\n tierId: it.tierId,\n unitPrice: it.unitPrice,\n currency: it.currency ?? this.currency,\n quantity: it.quantity ?? 1,\n }));\n const currency = lineItems[0]?.currency ?? this.currency;\n const total = lineItems.reduce((sum, i) => sum + i.unitPrice * i.quantity, 0);\n return { holdId: hold.holdId, expiresAt: hold.expiresAt, currency, lineItems, total };\n }\n\n private toast(msg: string): void {\n const el = this.els.toast;\n if (!el) return;\n el.textContent = msg;\n el.classList.add('on');\n if (this.toastTimer) clearTimeout(this.toastTimer);\n this.toastTimer = setTimeout(() => el.classList.remove('on'), 4200);\n }\n\n private placeTooltip(): void {\n if (!this.tipEl) return;\n const hw = this.els.map.clientWidth;\n const tw = this.tipEl.offsetWidth;\n const th = this.tipEl.offsetHeight;\n let x = this.tipPos.x + 14;\n let y = this.tipPos.y - th - 12;\n if (x + tw > hw - 8) x = this.tipPos.x - tw - 14;\n if (y < 8) y = this.tipPos.y + 18;\n this.tipEl.style.left = `${Math.max(8, x)}px`;\n this.tipEl.style.top = `${Math.max(8, y)}px`;\n }\n\n private updateTooltip(details: SeatHoverDetails | null): void {\n if (!this.tipEl) return;\n if (!details) {\n this.tipEl.style.display = 'none';\n return;\n }\n const statusLine =\n details.status === 'free'\n ? ''\n : `<div style=\"margin-top:5px;font-size:10.5px;letter-spacing:.08em;text-transform:uppercase;font-weight:700\">${\n details.status === 'held' ? t('map.statusHeld') : t('map.statusTaken')\n }</div>`;\n this.tipEl.innerHTML =\n `<div style=\"font-weight:800;font-size:13px\">${details.label}</div>` +\n `<div style=\"display:flex;align-items:center;gap:6px;margin-top:4px\">` +\n `<span style=\"width:9px;height:9px;border-radius:50%;flex:none;background:${details.categoryColor}\"></span>` +\n `<span style=\"opacity:.75\">${details.categoryLabel}</span>` +\n `<span style=\"margin-left:auto;font-weight:800\">${this.money(details.price)}</span></div>` +\n statusLine;\n this.tipEl.style.display = 'block';\n this.placeTooltip();\n }\n\n // ---- public conveniences ----------------------------------------------------\n\n getSelection(): PickerSeat[] {\n return this.controller.getSelection();\n }\n\n async bestAvailable(qty: number, categoryKey?: string): Promise<HoldResult | null> {\n try {\n const h = await this.controller.bestAvailable(qty, categoryKey);\n if (h) {\n this.hold = { holdId: h.holdId, expiresAt: h.expiresAt, seats: h.seats, items: h.items };\n this.handedOff = false;\n this.bookedShown = false;\n this.startHoldTimer(h.expiresAt);\n this.syncTray();\n return this.hold;\n }\n return null;\n } catch (err) {\n this.opts.onError?.(err);\n return null;\n }\n }\n\n async release(): Promise<void> {\n await this.controller.release();\n this.hold = null;\n this.handedOff = false;\n this.bookedShown = false;\n this.stopHoldTimer();\n this.gaQty.clear();\n this.syncTray();\n }\n\n destroy(): void {\n this.destroyed = true;\n this.closeConfirm();\n this.closeSeatView();\n this.stopHoldTimer();\n if (this.toastTimer) clearTimeout(this.toastTimer);\n this.ro?.disconnect();\n this.ro = null;\n if (this.escHandler) document.removeEventListener('keydown', this.escHandler);\n this.controller.destroy();\n this.root?.remove();\n this.root = null;\n if (this.modalScrim) {\n this.modalScrim.remove();\n this.modalScrim = null;\n (this.prevFocus as HTMLElement | null)?.focus?.();\n }\n }\n}\n"],"mappings":"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","names":["resolveContainer","import_core","DEFAULT_API_BASE","DEFAULT_MAX_SELECTION","resolveContainer","pano","canView"]}
|