@seatlayer/js 0.23.0 → 0.24.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/README.md +54 -3
- package/dist/index.cjs +204 -20
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +117 -10
- package/dist/index.d.ts +117 -10
- package/dist/index.js +204 -20
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/SeatingChart.ts","../src/api.ts","../src/EmbeddedDesigner.ts","../src/SeatPicker.ts","../src/attachPickerFrame.ts","../src/SeatManager.ts","../src/manageApi.ts"],"sourcesContent":["/**\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 /** A prior active hold was restored with resumeHold(). */\n onHoldRestored?: (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 onHoldRestored: (h) => this.opts.onHoldRestored?.({ 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 /** Restore an active hold by its opaque id without extending its expiry. */\n async resumeHold(holdId: string): Promise<HoldResult | null> {\n try {\n const h = await this.controller.resumeHold(holdId);\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 /** Current active hold known to this chart, if any. */\n getCurrentHold(): HoldResult | null {\n const h = this.controller.currentHold();\n return h ? { holdId: h.holdId, expiresAt: h.expiresAt, seats: h.seats, items: h.items } : null;\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 /** Release selected labels from the current hold while keeping the remainder. */\n async releaseLabels(labels: string[]): Promise<boolean> {\n return this.controller.releaseLabels(labels);\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 /** Section/zone ids hidden from buyers this event (seats stripped from the map). */\n hidden?: string[];\n /** Section/zone ids in the `closed` state (Phase 2): rendered grey + not purchasable. */\n closed?: 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/** Browser-safe active-hold projection returned by the resume endpoint. */\nexport interface ResumedHoldResult extends HoldResult {\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 private readonly viewerId = typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function'\n ? crypto.randomUUID()\n : `viewer_${Math.random().toString(36).slice(2)}${Date.now().toString(36)}`;\n\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 resume(key: string, holdId: string): Promise<ResumedHoldResult> {\n return request(this.base, `/pub/events/${encodeURIComponent(key)}/hold/resume`, {\n method: 'POST',\n body: { holdId },\n });\n }\n\n release(key: string, labels: string[], holdId: string): Promise<{ ok: true; released?: string[] }> {\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 const params = new URLSearchParams({ surface: 'picker', viewerId: this.viewerId });\n return `${wsBase}/pub/events/${encodeURIComponent(key)}/subscribe?${params}`;\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 /**\n * Show the built-in branded loading skeleton and error/expiry card inside the\n * container while the Designer boots. Defaults to `true`. Set `false` when the\n * host renders its own loading and error chrome.\n */\n showLoadingState?: boolean;\n /**\n * If the Designer never posts `ready` within this many milliseconds, the host\n * transitions to the error card with a timeout message. Defaults to `20000`.\n * Only used when `showLoadingState` is enabled.\n */\n loadingTimeoutMs?: number;\n /**\n * How to size the iframe's height. The Designer is a full application (its\n * shell is `position:fixed; height:100dvh`), not flowing content, so it should\n * fill the viewport rather than be measured.\n *\n * - `'fill'` (default): grow the iframe so its bottom edge reaches the bottom\n * of the viewport — `window.innerHeight - iframe.top`, clamped to `minHeight`\n * — recomputed (rAF-throttled) on `resize` / `orientationchange` / `scroll`.\n * The legacy `seatlayer.designer.resize` message is ignored in this mode: it\n * is circular, because the fixed-position shell just echoes the iframe height.\n * - a number: a fixed pixel height. In this mode the legacy resize message is\n * still honoured (unless `autoResize` is `false`) so older hosts keep growing.\n */\n height?: 'fill' | number;\n /** Minimum height (px) that `'fill'` mode clamps to. Defaults to `480`. */\n minHeight?: number;\n /**\n * Auto-grow the iframe to the height the Designer reports over the resize\n * protocol (`seatlayer.designer.resize`). Only applies when `height` is a fixed\n * number; ignored in `'fill'` mode. Defaults to `true`. Set `false` when the\n * host sizes a fixed-height iframe itself.\n */\n autoResize?: boolean;\n /**\n * Called when the user presses \"Try again\" on the error card. Use it to mint a\n * fresh Designer session and call `setDesignerUrl()` with the new URL, which\n * recreates the iframe and returns to the loading state. When omitted, \"Try\n * again\" reloads the current `designerUrl` in place.\n */\n onRequestRelaunch?: () => void;\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\nconst DEFAULT_LOADING_TIMEOUT_MS = 20000;\nconst DEFAULT_MIN_FILL_HEIGHT = 480;\n\n/** Internal reason the error card is being shown, used to pick human copy. */\ntype ErrorCause = 'expired' | 'mismatch' | 'timeout' | 'load';\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/** Map an error message's `code` onto one of the human-copy causes. */\nfunction causeFromCode(code: string | undefined): ErrorCause {\n const value = (code ?? '').toLowerCase();\n if (value.includes('expire') || value.includes('revoke') || value === '401') return 'expired';\n if (value.includes('mismatch')) return 'mismatch';\n if (value.includes('timeout')) return 'timeout';\n return 'load';\n}\n\nconst ERROR_COPY: Record<ErrorCause, { title: string; body: string }> = {\n expired: {\n title: 'This design session expired',\n body: 'For your security, editing sessions are short-lived. Start a fresh one to keep designing.',\n },\n mismatch: {\n title: \"This editor doesn't match this chart\",\n body: 'The session that loaded belongs to a different chart or workspace. Reopen the designer to continue.',\n },\n timeout: {\n title: 'The designer is taking too long',\n body: 'It did not finish loading in time. This is usually a slow connection — try again.',\n },\n load: {\n title: \"We couldn't load the designer\",\n body: 'Something went wrong while opening the editor. Please try again.',\n },\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 private overlay: HTMLDivElement | null = null;\n private timeoutTimer: ReturnType<typeof setTimeout> | null = null;\n private phase: 'loading' | 'ready' | 'error' = 'loading';\n private restoreContainerPosition: string | null = null;\n // Host-side fullscreen pin: saved state we restore on `off`/Escape/destroy.\n private pinned = false;\n private frameStyleBeforeFs: string | null = null;\n private docOverflowBeforeFs: string | null = null;\n private bodyOverflowBeforeFs: string | null = null;\n private fsKeyHandler: ((event: KeyboardEvent) => void) | null = null;\n /** Latest height (px string) the Designer reported; re-applied after unpin. */\n private lastAutoHeight = '';\n // Viewport-fill sizing: pending rAF handle + whether listeners are attached.\n private fillRaf: number | null = null;\n private fillListening = false;\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 ?? 'fullscreen; clipboard-write';\n frame.referrerPolicy = this.options.referrerPolicy ?? 'origin';\n frame.src = url.toString();\n frame.style.width = '100%';\n // `'fill'` (default) is computed from the viewport once the frame is in the\n // DOM (see startFill); a numeric height is a fixed pixel box.\n frame.style.height = typeof this.options.height === 'number' ? `${this.options.height}px` : '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 const container = resolveContainer(this.options.container);\n window.addEventListener('message', this.handleMessage);\n container.append(frame);\n this.frame = frame;\n\n // Fill mode owns the height from the viewport now the frame is measurable.\n if (this.fillEnabled()) this.startFill();\n\n this.phase = 'loading';\n if (this.loadingStateEnabled()) {\n this.ensureContainerPositioned(container);\n this.renderOverlay(container, 'loading');\n const timeout = this.options.loadingTimeoutMs ?? DEFAULT_LOADING_TIMEOUT_MS;\n if (timeout > 0 && Number.isFinite(timeout)) {\n this.timeoutTimer = setTimeout(() => {\n if (this.phase === 'loading') this.showError('timeout');\n }, timeout);\n }\n }\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 // mount() tears everything down and re-enters the loading state.\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.stopFill();\n this.unpinFullscreen();\n this.clearTimeoutTimer();\n this.removeOverlay();\n this.restoreContainerStyle();\n this.frame?.remove();\n this.frame = null;\n this.designerOrigin = '';\n this.phase = 'loading';\n this.lastAutoHeight = '';\n }\n\n private loadingStateEnabled(): boolean {\n return this.options.showLoadingState !== false;\n }\n\n private autoResizeEnabled(): boolean {\n return this.options.autoResize !== false;\n }\n\n /** Fill mode is the default; a numeric `height` opts into a fixed pixel box. */\n private fillEnabled(): boolean {\n return typeof this.options.height !== 'number';\n }\n\n /**\n * Size the iframe so its bottom edge meets the bottom of the viewport\n * (`window.innerHeight - top`), clamped to `minHeight`. No-op while pinned\n * fullscreen (the pin fills the viewport itself).\n */\n private applyFill(): void {\n if (!this.frame || this.pinned) return;\n const min = this.options.minHeight ?? DEFAULT_MIN_FILL_HEIGHT;\n const top = this.frame.getBoundingClientRect().top;\n const target = Math.max(min, Math.round(window.innerHeight - top));\n this.frame.style.height = `${target}px`;\n }\n\n /** rAF-throttled fill recompute, so a burst of scroll/resize ticks coalesces. */\n private scheduleFill = (): void => {\n if (this.fillRaf !== null) return;\n this.fillRaf = requestAnimationFrame(() => {\n this.fillRaf = null;\n this.applyFill();\n });\n };\n\n private startFill(): void {\n this.applyFill();\n if (this.fillListening) return;\n this.fillListening = true;\n window.addEventListener('resize', this.scheduleFill);\n window.addEventListener('orientationchange', this.scheduleFill);\n window.addEventListener('scroll', this.scheduleFill, { passive: true });\n }\n\n private stopFill(): void {\n if (this.fillRaf !== null) {\n cancelAnimationFrame(this.fillRaf);\n this.fillRaf = null;\n }\n if (!this.fillListening) return;\n this.fillListening = false;\n window.removeEventListener('resize', this.scheduleFill);\n window.removeEventListener('orientationchange', this.scheduleFill);\n window.removeEventListener('scroll', this.scheduleFill);\n }\n\n /**\n * Pin the iframe over the host page as a viewport-filling overlay. We save the\n * iframe's inline style and the document scroll state so `unpinFullscreen`\n * restores everything exactly. Escape (host-side) also exits.\n */\n private pinFullscreen(): void {\n if (this.pinned || !this.frame) return;\n this.pinned = true;\n this.frameStyleBeforeFs = this.frame.getAttribute('style');\n Object.assign(this.frame.style, {\n position: 'fixed',\n inset: '0',\n width: '100vw',\n height: '100vh',\n margin: '0',\n border: '0',\n zIndex: '2147483000',\n background: '#101625',\n } satisfies Partial<CSSStyleDeclaration>);\n\n const docEl = document.documentElement;\n this.docOverflowBeforeFs = docEl.style.overflow;\n docEl.style.overflow = 'hidden';\n if (document.body) {\n this.bodyOverflowBeforeFs = document.body.style.overflow;\n document.body.style.overflow = 'hidden';\n }\n\n this.fsKeyHandler = (event: KeyboardEvent): void => {\n if (event.key === 'Escape') this.unpinFullscreen();\n };\n window.addEventListener('keydown', this.fsKeyHandler);\n }\n\n /** Undo `pinFullscreen`: restore the iframe style + scroll lock. Idempotent. */\n private unpinFullscreen(): void {\n if (!this.pinned) return;\n this.pinned = false;\n if (this.frame) {\n if (this.frameStyleBeforeFs === null) this.frame.removeAttribute('style');\n else this.frame.setAttribute('style', this.frameStyleBeforeFs);\n // Restore the right height for the mode: recompute the viewport fill, or\n // re-apply the last height the Designer reported (numeric mode).\n if (this.fillEnabled()) this.applyFill();\n else if (this.autoResizeEnabled() && this.lastAutoHeight) this.frame.style.height = this.lastAutoHeight;\n }\n this.frameStyleBeforeFs = null;\n\n if (this.docOverflowBeforeFs !== null) {\n document.documentElement.style.overflow = this.docOverflowBeforeFs;\n this.docOverflowBeforeFs = null;\n }\n if (this.bodyOverflowBeforeFs !== null && document.body) {\n document.body.style.overflow = this.bodyOverflowBeforeFs;\n this.bodyOverflowBeforeFs = null;\n }\n if (this.fsKeyHandler) {\n window.removeEventListener('keydown', this.fsKeyHandler);\n this.fsKeyHandler = null;\n }\n }\n\n private clearTimeoutTimer(): void {\n if (this.timeoutTimer !== null) {\n clearTimeout(this.timeoutTimer);\n this.timeoutTimer = null;\n }\n }\n\n private ensureContainerPositioned(container: HTMLElement): void {\n // The overlay is absolutely positioned; the container must establish a\n // positioning context. Only touch a `static` container, and remember to\n // restore it on destroy.\n const position = getComputedStyle(container).position;\n if (position === 'static') {\n this.restoreContainerPosition = container.style.position;\n container.style.position = 'relative';\n }\n }\n\n private restoreContainerStyle(): void {\n if (this.restoreContainerPosition === null) return;\n try {\n resolveContainer(this.options.container).style.position = this.restoreContainerPosition;\n } catch {\n /* container already gone — nothing to restore */\n }\n this.restoreContainerPosition = null;\n }\n\n private removeOverlay(): void {\n this.overlay?.remove();\n this.overlay = null;\n }\n\n private showError(cause: ErrorCause): void {\n this.phase = 'error';\n this.clearTimeoutTimer();\n if (!this.loadingStateEnabled()) return;\n let container: HTMLElement;\n try {\n container = resolveContainer(this.options.container);\n } catch {\n return;\n }\n this.renderOverlay(container, 'error', cause);\n }\n\n private handleTryAgain(): void {\n if (this.options.onRequestRelaunch) {\n // Host mints a fresh session and calls setDesignerUrl(), which re-mounts\n // the iframe and returns to the loading state.\n this.options.onRequestRelaunch();\n return;\n }\n // No relaunch hook: reload the same session URL in place.\n this.mount();\n }\n\n /**\n * Build (or rebuild) the overlay for the given phase. A single overlay element\n * is reused so we never stack stale skeletons or cards.\n */\n private renderOverlay(container: HTMLElement, phase: 'loading' | 'error', cause?: ErrorCause): void {\n this.removeOverlay();\n const overlay = document.createElement('div');\n overlay.setAttribute('data-seatlayer-designer-overlay', phase);\n overlay.setAttribute('role', phase === 'error' ? 'alert' : 'status');\n overlay.setAttribute('aria-live', 'polite');\n Object.assign(overlay.style, {\n position: 'absolute',\n inset: '0',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n background: '#101625',\n color: '#e6ebf5',\n fontFamily:\n '-apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, Helvetica, Arial, sans-serif',\n zIndex: '2',\n overflow: 'hidden',\n } satisfies Partial<CSSStyleDeclaration>);\n\n if (phase === 'loading') this.buildSkeleton(overlay);\n else this.buildErrorCard(overlay, cause ?? 'load');\n\n container.append(overlay);\n this.overlay = overlay;\n }\n\n private buildSkeleton(overlay: HTMLDivElement): void {\n // Scoped keyframes; the shimmer only runs when the user allows motion.\n const style = document.createElement('style');\n style.textContent = `\n@media (prefers-reduced-motion: no-preference) {\n @keyframes seatlayer-designer-shimmer {\n 0% { background-position: -320px 0; }\n 100% { background-position: 320px 0; }\n }\n [data-seatlayer-designer-overlay=\"loading\"] .sl-shimmer {\n animation: seatlayer-designer-shimmer 1.25s ease-in-out infinite;\n background-size: 640px 100%;\n }\n}`;\n overlay.append(style);\n\n const shimmer =\n 'linear-gradient(90deg, rgba(255,255,255,0.04) 25%, rgba(255,255,255,0.10) 37%, rgba(255,255,255,0.04) 63%)';\n\n const scaffold = document.createElement('div');\n Object.assign(scaffold.style, {\n position: 'absolute',\n inset: '0',\n display: 'flex',\n flexDirection: 'column',\n padding: '16px',\n gap: '14px',\n opacity: '0.9',\n } satisfies Partial<CSSStyleDeclaration>);\n\n const bar = (styles: Partial<CSSStyleDeclaration>): HTMLDivElement => {\n const node = document.createElement('div');\n node.className = 'sl-shimmer';\n Object.assign(node.style, {\n background: shimmer,\n borderRadius: '8px',\n } satisfies Partial<CSSStyleDeclaration>);\n Object.assign(node.style, styles);\n return node;\n };\n\n // Top toolbar row.\n scaffold.append(bar({ height: '40px', width: '100%', flex: '0 0 auto' }));\n\n // Body: side panel + canvas.\n const body = document.createElement('div');\n Object.assign(body.style, {\n display: 'flex',\n gap: '14px',\n flex: '1 1 auto',\n minHeight: '0',\n } satisfies Partial<CSSStyleDeclaration>);\n body.append(bar({ width: '220px', height: '100%', flex: '0 0 auto' }));\n body.append(bar({ flex: '1 1 auto', height: '100%' }));\n scaffold.append(body);\n\n overlay.append(scaffold);\n\n // Centered caption above the scaffold.\n const caption = document.createElement('div');\n Object.assign(caption.style, {\n position: 'relative',\n zIndex: '1',\n display: 'flex',\n alignItems: 'center',\n gap: '10px',\n padding: '10px 16px',\n borderRadius: '999px',\n background: 'rgba(16, 22, 37, 0.72)',\n fontSize: '13px',\n fontWeight: '500',\n letterSpacing: '0.01em',\n } satisfies Partial<CSSStyleDeclaration>);\n\n const dot = document.createElement('span');\n dot.className = 'sl-shimmer';\n Object.assign(dot.style, {\n width: '9px',\n height: '9px',\n borderRadius: '50%',\n background: shimmer,\n flex: '0 0 auto',\n } satisfies Partial<CSSStyleDeclaration>);\n caption.append(dot);\n caption.append(document.createTextNode('Loading designer…'));\n overlay.append(caption);\n }\n\n private buildErrorCard(overlay: HTMLDivElement, cause: ErrorCause): void {\n const copy = ERROR_COPY[cause];\n const card = document.createElement('div');\n Object.assign(card.style, {\n maxWidth: '420px',\n margin: '0 24px',\n padding: '28px',\n textAlign: 'center',\n background: 'rgba(255, 255, 255, 0.03)',\n border: '1px solid rgba(255, 255, 255, 0.08)',\n borderRadius: '16px',\n boxShadow: '0 12px 40px rgba(0, 0, 0, 0.35)',\n } satisfies Partial<CSSStyleDeclaration>);\n\n const heading = document.createElement('h2');\n heading.textContent = copy.title;\n Object.assign(heading.style, {\n margin: '0 0 8px',\n fontSize: '17px',\n fontWeight: '600',\n color: '#f4f7ff',\n } satisfies Partial<CSSStyleDeclaration>);\n\n const body = document.createElement('p');\n body.textContent = copy.body;\n Object.assign(body.style, {\n margin: '0 0 20px',\n fontSize: '13.5px',\n lineHeight: '1.5',\n color: '#aab4c8',\n } satisfies Partial<CSSStyleDeclaration>);\n\n const button = document.createElement('button');\n button.type = 'button';\n button.textContent = 'Try again';\n Object.assign(button.style, {\n appearance: 'none',\n cursor: 'pointer',\n border: '0',\n borderRadius: '10px',\n padding: '10px 22px',\n fontSize: '14px',\n fontWeight: '600',\n color: '#101625',\n background: '#7aa2ff',\n } satisfies Partial<CSSStyleDeclaration>);\n button.addEventListener('click', () => this.handleTryAgain());\n\n card.append(heading, body, button);\n overlay.append(card);\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\n // Layout protocol — origin-locked like everything else, but handled here\n // rather than dispatched to the host callbacks.\n if (data.type === 'seatlayer.designer.resize') {\n // Fill mode owns the height from the viewport; the reported scrollHeight is\n // circular (the fixed-position shell echoes the iframe height), so ignore\n // it. Only a fixed numeric height honours the legacy auto-grow.\n if (!this.fillEnabled() && this.autoResizeEnabled()\n && typeof data.px === 'number' && Number.isFinite(data.px) && data.px > 0) {\n this.lastAutoHeight = `${Math.round(data.px)}px`;\n // While pinned fullscreen the iframe fills the viewport; apply the\n // reported height only when not pinned (it's re-applied on unpin).\n if (!this.pinned) this.frame.style.height = this.lastAutoHeight;\n }\n return;\n }\n if (data.type === 'seatlayer.designer.fullscreen') {\n if (data.on === true) this.pinFullscreen();\n else if (data.on === false) this.unpinFullscreen();\n return;\n }\n\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 (\n (this.options.expectedChartId && message.chartId && message.chartId !== this.options.expectedChartId) ||\n (this.options.expectedWorkspaceId && message.workspaceId && message.workspaceId !== this.options.expectedWorkspaceId)\n ) {\n // A message from our exact iframe carrying the wrong identity is a real\n // session mismatch, not spoofing. Surface it (loading state on) rather than\n // dispatching it to the host callbacks.\n this.showError('mismatch');\n return;\n }\n\n switch (message.type) {\n case 'seatlayer.designer.ready':\n this.phase = 'ready';\n this.clearTimeoutTimer();\n this.removeOverlay();\n this.options.onReady?.(message);\n 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':\n this.showError(causeFromCode(message.code));\n this.options.onError?.(message);\n 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 contract: 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 generateSeatThumb,\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 PickerTransport,\n type SeatHoverDetails,\n type SectionSummary,\n} from '@seatlayer/core';\nimport { PubApi, type HoldLineItem, type HoldResult } from './api';\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/** Minimal shape of a section object read off the ChartDoc for the minimap. */\ninterface SectionLike {\n type: string;\n id: string;\n outline?: { x: number; y: number }[];\n color?: string;\n zone?: string;\n}\n\n/** Even-odd point-in-polygon test in world units (minimap click → section). */\nfunction pointInPolygon(x: number, y: number, poly: { x: number; y: number }[]): boolean {\n let inside = false;\n for (let i = 0, j = poly.length - 1; i < poly.length; j = i++) {\n const xi = poly[i].x, yi = poly[i].y, xj = poly[j].x, yj = poly[j].y;\n if (yi > y !== yj > y && x < ((xj - xi) * (y - yi)) / (yj - yi) + xi) inside = !inside;\n }\n return inside;\n}\n\n/** One price band in the F4 filter — a set of category keys within a price range. */\ninterface PriceBand {\n id: string;\n label: string;\n keys: string[];\n min: number;\n max: number;\n}\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-authoritative pricing — see {@link SeatPickerOptions.pricing}. */\nexport interface SeatPickerPricing {\n /** Unit prices by category key: a flat number, or `{ base, tiers: { tierId: price } }`. */\n prices?: Record<string, number | { base?: number; tiers?: Record<string, number> }>;\n /** Custom money renderer (e.g. `(n) => n + '€'`). Defaults to Intl currency formatting. */\n formatter?: (amount: number, currency: string) => string;\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 /**\n * Custom data transport. Defaults to the CORS-trivial PubApi against\n * `apiBase`. Inject to run the widget against another backend adapter (the\n * SeatLayer dashboard's own transport) or a fully local mock (demos).\n */\n transport?: PickerTransport;\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 /**\n * Hide the \"Powered by SeatLayer\" attribution badge in the side panel foot.\n * The chart theme's own `hideBadge` flag (paid orgs) also hides it — the badge\n * is shown only when BOTH this option and the theme flag are unset/false.\n */\n hideBadge?: boolean;\n /** Host theme overrides — see SeatPickerTheme. */\n theme?: SeatPickerTheme;\n /**\n * Host-authoritative pricing. When your shop charges different prices than\n * the chart's stored category prices, pass them here so the buyer sees the\n * price they will actually pay — on the map tooltip, confirm popover, price\n * panel, tray, totals, and in the checkout handoff's line items. Keyed by\n * category key; per-tier overrides nest under `tiers`. Unlisted categories\n * fall back to the chart price.\n */\n pricing?: SeatPickerPricing;\n /** Hold TTL in ms passed to hold(); server clamps to its own limits. */\n holdTtlMs?: number;\n /**\n * An opaque hold id supplied by the host to restore after navigation. It is\n * verified against the event and active server state before anything renders\n * as owned by this buyer.\n */\n initialHoldId?: string;\n /**\n * Automatically remember the active hold id in sessionStorage and restore it\n * when this event's picker mounts again. Default true. Set false when the host\n * owns hold persistence and supplies initialHoldId itself.\n */\n restoreHold?: boolean;\n /**\n * Confirm mode: tapping a seat shows a confirmation card with section, row,\n * seat, category, price and Select/Cancel before it enters the tray. Default\n * true for the full buyer picker; set false only when the host supplies its\n * own equivalent confirmation UI.\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 /**\n * Active hold changed because it was created, restored, extended, partially\n * released, or fully released. Hosts should persist this state for route\n * navigation and clear their checkout cart when `hold` becomes null.\n */\n onHoldChange?: (hold: HoldResult | null, seats: PickerSeat[], handoff: CheckoutHandoff | null) => void;\n /** The open hold expired server-side (widget already reset itself). */\n onHoldExpired?: () => void;\n /** A prior active hold was verified and restored into the tray. */\n onHoldRestored?: (hold: HoldResult, seats: PickerSeat[], handoff: CheckoutHandoff) => 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 transform-origin:right center}\n.sl-hold-pill.on{display:inline-flex;animation:slPillIn .34s cubic-bezier(.2,.8,.2,1) both}\n.sl-hold-dot{width:7px;height:7px;border-radius:50%;background:currentColor;opacity:.78;box-shadow:0 0 0 0 currentColor}\n.sl-hold-pill.is-expiring .sl-hold-dot{animation:slHoldPulse 1.4s ease-out infinite}\n.sl-hold-time{min-width:3.35em;text-align:left}\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:hidden}\n\n/* narrow (container < 640px): map-first — the map claims ~80-85% of the\n container and the side panel becomes a PEEKING bottom sheet (AXS/Ticketmaster\n mobile pattern). data-sheet on the root: \"peek\" (default: grab handle + one\n summary line) / \"open\" (room for rows + checkout, swipe up to open).\n Swipe handling lives on the sheet head ONLY — never the map host, so the\n map's raw-pointer gesture pipeline is untouched. */\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%;border-left:0;border-top:1px solid var(--sl-line);\n flex:none;height:min(72%,480px);overflow:hidden;transition:height .3s cubic-bezier(.2,.8,.2,1);overscroll-behavior:contain}\n.sl-picker[data-layout=\"narrow\"][data-sheet=\"open\"][data-has-selection=\"false\"] .sl-side{height:min(252px,52%)}\n.sl-picker[data-layout=\"narrow\"][data-sheet=\"peek\"] .sl-side{height:86px;overflow:hidden}\n.sl-picker[data-layout=\"narrow\"][data-sheet=\"peek\"] .sl-side > :not(.sl-sheet-head){display:none}\n.sl-picker[data-layout=\"narrow\"] .sl-tray{flex:1;min-height:0;overflow-y:auto;overscroll-behavior:contain}\n.sl-picker[data-layout=\"narrow\"] .sl-foot{position:static;background:var(--sl-bg)}\n.sl-picker[data-layout=\"narrow\"] .sl-foot.empty{display:none}\n.sl-picker[data-layout=\"narrow\"] .sl-sheet-head{order:0}\n.sl-picker[data-layout=\"narrow\"] .sl-seats-sec{display:none}\n.sl-picker[data-layout=\"narrow\"] .sl-tray{order:2}\n.sl-picker[data-layout=\"narrow\"] .sl-filtersec{order:3}\n.sl-picker[data-layout=\"narrow\"] .sl-filters{order:4}\n.sl-picker[data-layout=\"narrow\"] .sl-prices-sec{order:5}\n.sl-picker[data-layout=\"narrow\"] .sl-pricef{order:6}\n.sl-picker[data-layout=\"narrow\"] .sl-prices{order:7}\n.sl-picker[data-layout=\"narrow\"] .sl-foot{order:8}\n.sl-picker[data-layout=\"narrow\"] .sl-tray-hint,\n.sl-picker[data-layout=\"narrow\"] .sl-filtersec,\n.sl-picker[data-layout=\"narrow\"] .sl-filters,\n.sl-picker[data-layout=\"narrow\"] .sl-prices-sec,\n.sl-picker[data-layout=\"narrow\"] .sl-prices{display:none!important}\n.sl-picker[data-layout=\"narrow\"][data-has-selection=\"true\"] .sl-filtersec,\n.sl-picker[data-layout=\"narrow\"][data-has-selection=\"true\"] .sl-filters,\n.sl-picker[data-layout=\"narrow\"][data-has-selection=\"true\"] .sl-prices-sec{display:none}\n/* Reclaim the bottom sheet once the cart has anything: the \"Find best seats\"\n panel collapses too. EXCEPT the confirm (\"Replace your current choices?\") and\n in-flight busy states, which legitimately show with a non-empty cart — those\n set data-ba-active=\"true\" (see setAttribute alongside data-has-selection). */\n.sl-picker[data-layout=\"narrow\"][data-has-selection=\"true\"]:not([data-ba-active=\"true\"]) .sl-ba{display:none}\n/* touch chrome: pinch-zoom exists — hide +/− on the sheet layout (keep fit) */\n.sl-picker[data-layout=\"narrow\"] .sl-zoom [data-ref=\"zin\"],\n.sl-picker[data-layout=\"narrow\"] .sl-zoom [data-ref=\"zout\"]{display:none}\n\n/* bottom-sheet head: grab handle + one-line summary (narrow only). The WHOLE\n head is the tap/swipe toggle target (min 44px), so it reads as one control. */\n.sl-sheet-head{display:none;flex-direction:column;justify-content:center;padding:6px 12px 8px;min-height:56px;\n cursor:pointer;touch-action:none;user-select:none;-webkit-user-select:none;flex:none}\n.sl-picker[data-layout=\"narrow\"] .sl-sheet-head{display:flex}\n.sl-sheet-grab{width:36px;height:4px;border-radius:999px;background:var(--sl-muted);opacity:.55;margin:2px auto 7px}\n.sl-sheet-bar{display:flex;align-items:center;gap:10px;min-height:26px}\n.sl-sheet-peek{display:flex;align-items:center;gap:7px;flex:1;min-width:0;font-size:13px;font-weight:700;color:var(--sl-text);\n white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n.sl-sheet-peek .sub{color:var(--sl-muted);font-weight:600}\n/* collapsed-peek \"Continue\" affordance: a real accent pill, not plain text */\n.sl-sheet-peek .go{margin-left:auto;flex:none;display:inline-flex;align-items:center;min-height:30px;\n padding:6px 13px;border-radius:999px;background:var(--sl-accent);color:var(--sl-accent-ink);\n font-weight:800;font-size:12.5px}\n/* state chevron: points UP while peeking, rotates to point DOWN when open.\n Base keeps an explicit rotate(0) — transitioning to/from a bare 'none' leaves\n the value stuck in some engines, so both endpoints must be real transforms. */\n.sl-sheet-toggle{width:44px;height:44px;margin:-8px -8px -8px 0;border-radius:999px;flex:none;display:flex;\n align-items:center;justify-content:center;color:var(--sl-muted);transition:color .15s,background .15s}\n.sl-sheet-toggle:hover,.sl-sheet-toggle:focus-visible{color:var(--sl-text);background:color-mix(in srgb,var(--sl-line) 44%,transparent)}\n.sl-sheet-toggle svg{width:21px;height:21px;stroke:currentColor;stroke-width:2.4;fill:none;\n stroke-linecap:round;stroke-linejoin:round}\n.sl-sheet-toggle svg{transform:rotate(0deg);transition:transform .24s cubic-bezier(.2,.8,.2,1)}\n.sl-picker[data-sheet=\"open\"] .sl-sheet-toggle svg{transform:rotate(180deg)}\n\n/* consolidated Filters row inside the sheet (a11y chips + colorblind toggle\n dock here on narrow; they live on the map / zoom column on wide) */\n.sl-filtersec{display:none}\n.sl-filters{display:none;gap:6px;flex-wrap:wrap;align-items:center;padding:2px 16px 10px}\n.sl-picker[data-layout=\"narrow\"] .sl-filtersec.has,\n.sl-picker[data-layout=\"narrow\"] .sl-filters.has{display:none}\n.sl-picker[data-layout=\"narrow\"][data-has-selection=\"true\"] .sl-filtersec.has,\n.sl-picker[data-layout=\"narrow\"][data-has-selection=\"true\"] .sl-filters.has{display:none}\n.sl-cbbtn{width:32px;height:32px;border-radius:999px;background:var(--sl-surface);border:1px solid var(--sl-line);\n color:var(--sl-text);display:flex;align-items:center;justify-content:center;transition:border-color .15s}\n.sl-cbbtn:hover{border-color:var(--sl-muted)}\n.sl-cbbtn svg{width:14px;height:14px;stroke:currentColor;stroke-width:2;fill:none;stroke-linecap:round;stroke-linejoin:round}\n\n/* price panel — one compact filter control replaces the wrapping price-chip row. */\n.sl-sec{padding:14px 14px 4px;font-size:9.5px;letter-spacing:.14em;text-transform:uppercase;color:var(--sl-muted);font-weight:700}\n.sl-prices-sec{display:flex;align-items:center;justify-content:space-between;gap:10px;padding-top:13px}\n.sl-price-select{min-height:32px;max-width:130px;padding:5px 28px 5px 9px;border:1px solid var(--sl-line);border-radius:9px;\n background:var(--sl-surface);color:var(--sl-text);font:inherit;font-size:11px;font-weight:750;letter-spacing:0;text-transform:none}\n.sl-prices{display:flex;flex-direction:column;padding:4px 14px 8px;border-bottom:1px solid var(--sl-line)}\n.sl-prices-sec,.sl-prices,.sl-seats-sec{flex:none}\n.sl-price-row{display:flex;align-items:center;gap:7px;min-height:28px;font-size:12px;\n padding:0 6px;margin:0 -6px;border-radius:8px;cursor:pointer;transition:background .15s}\n.sl-price-row:hover,.sl-price-row:focus-visible{background:color-mix(in srgb,var(--sl-line) 40%,transparent)}\n.sl-price-row.sl-active{background:color-mix(in srgb,var(--sl-accent) 9%,transparent)}\n.sl-price-row.sl-active .sl-price-label{color:var(--sl-accent)}\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/* long category lists: capped by default, scroll once expanded */\n.sl-prices.sl-expanded{max-height:196px;overflow-y:auto;overscroll-behavior:contain;scrollbar-gutter:stable}\n.sl-price-more{display:flex;align-items:center;min-height:26px;padding:0;\n color:var(--sl-muted);font-size:11px;font-weight:750;transition:color .15s}\n.sl-price-more:hover,.sl-price-more:focus-visible{color:var(--sl-text)}\n/* held/sold key — one quiet caption line; the map itself teaches these states */\n.sl-status-key{display:flex;gap:11px;flex-wrap:wrap;padding:5px 0 0;margin-top:4px;border-top:1px solid var(--sl-line);color:var(--sl-muted);font-size:10px}\n.sl-status-item{display:inline-flex;align-items:center;gap:5px}\n.sl-status-icon{width:13px;height:13px;border-radius:999px;display:inline-flex;align-items:center;justify-content:center;\n color:#fff;background:#6b7280;line-height:1}\n.sl-status-icon svg{width:8px;height:8px;stroke:currentColor;stroke-width:2;fill:none;stroke-linecap:round;stroke-linejoin:round}\n.sl-status-icon.sold{background:#8b93a0}\n.sl-status-icon.sold svg{width:9px;height:9px;stroke-width:2.4}\n\n/* tray */\n.sl-seats-sec{display:flex;align-items:center;justify-content:space-between;gap:10px;padding-top:13px}\n.sl-seat-summary{font-size:10px;letter-spacing:0;text-transform:none;white-space:nowrap}\n.sl-tray{flex:1;padding:10px 14px 14px;display:flex;flex-direction:column;gap:7px;min-height:0;overflow-y:auto;\n overscroll-behavior:contain;scrollbar-gutter:stable}\n.sl-tray-hint{font-size:12.5px;color:var(--sl-muted);line-height:1.5}\n.sl-chip{position:relative;display:grid;grid-template-columns:minmax(0,1fr) 34px;align-items:stretch;\n flex:none;min-height:53px;border:1px solid var(--sl-line);border-radius:var(--sl-r-sm);overflow:hidden;\n background:var(--sl-surface);font-size:13px;transform-origin:center;transition:border-color .15s,background .15s}\n.sl-chip:hover{border-color:color-mix(in srgb,var(--sl-accent) 38%,var(--sl-line))}\n.sl-chip.sl-enter{animation:slChipIn .38s cubic-bezier(.2,.8,.2,1) both}\n.sl-chip.sl-leave{pointer-events:none;animation:slChipOut .16s ease-in both}\n.sl-chip.sl-held{border-color:var(--sl-line);background:color-mix(in srgb,var(--sl-accent) 7%,var(--sl-surface));\n box-shadow:inset 3px 0 0 color-mix(in srgb,var(--sl-accent) 72%,transparent)}\n.sl-ticket-state{width:17px;height:17px;border-radius:999px;flex:none;display:flex;align-items:center;justify-content:center;\n background:var(--sl-accent);color:var(--sl-accent-ink)}\n.sl-ticket-state.held{background:color-mix(in srgb,var(--sl-accent) 18%,var(--sl-surface));color:var(--sl-accent)}\n.sl-ticket-state svg{width:10px;height:10px;stroke:currentColor;stroke-width:2.6;fill:none;stroke-linecap:round;stroke-linejoin:round}\n.sl-chip-main{min-width:0;padding:8px 10px 8px 11px;display:flex;flex-direction:column;justify-content:center;gap:5px}\n.sl-chip-id{display:flex;gap:12px;min-width:0}\n.sl-chip-id .fld{min-width:0}\n.sl-chip-id .fld.sec{flex:1}\n.sl-chip-id .fld.mid{flex:none;text-align:center}\n.sl-chip-eb{display:block;font-size:8px;font-weight:700;letter-spacing:.12em;text-transform:uppercase;color:var(--sl-muted);margin-bottom:1px}\n.sl-chip-id .val{display:block;font-weight:600;font-size:13px;line-height:1.25;white-space:nowrap}\n.sl-chip-id .fld.sec .val{overflow:hidden;text-overflow:ellipsis}\n.sl-chip-sub{display:flex;align-items:center;gap:6px;min-width:0}\n.sl-chip .cat{color:var(--sl-muted);font-size:10.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;flex:none;white-space:nowrap}\n.sl-chip-rail{display:flex;flex-direction:column;border-left:1px solid var(--sl-line)}\n.sl-chip .rm,.sl-chip .view{flex:1;min-height:26px;border-radius:0;display:flex;align-items:center;justify-content:center;\n color:var(--sl-muted);transition:color .15s,background .15s}\n.sl-chip .view{border-top:1px solid var(--sl-line)}\n.sl-chip .rm:hover,.sl-chip .rm:focus-visible{color:#e5484d;background:color-mix(in srgb,#e5484d 9%,transparent)}\n.sl-chip .view:hover,.sl-chip .view:focus-visible{color:var(--sl-text);background:color-mix(in srgb,var(--sl-accent) 10%,transparent)}\n.sl-chip .rm svg{width:11px;height:11px;stroke:currentColor;stroke-width:2.4;fill:none;stroke-linecap:round}\n.sl-chip .view svg{width:13px;height:13px;stroke:currentColor;stroke-width:1.8;fill:none}\n/* live-activity strip — narrates WS availability deltas (social proof + urgency).\n Hidden until a delta actually happens: a static \"seats update in real time\"\n banner is dead vertical space, a \"2 seats just taken\" flash is a signal. */\n.sl-live{display:none;align-items:center;gap:7px;margin:10px 14px 0;padding:7px 9px;flex:none;\n border:1px solid var(--sl-line);border-radius:8px;background:color-mix(in srgb,var(--sl-accent) 4%,var(--sl-surface));\n font-size:11px;color:var(--sl-muted)}\n.sl-live .dot{width:6px;height:6px;border-radius:999px;background:#22a06b;box-shadow:0 0 6px rgba(34,160,107,.75);flex:none}\n.sl-live span:last-child{flex:1;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n.sl-live.on{display:flex;animation:slNoticeIn .38s cubic-bezier(.2,.8,.2,1) both}\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{position:relative;z-index:2;padding:12px 16px 14px;border-top:1px solid var(--sl-line);flex:none;\n background:var(--sl-bg);box-shadow:0 -10px 24px -22px rgba(0,0,0,.72)}\n.sl-hold-note{display:none;align-items:center;gap:7px;margin-bottom:8px;padding:7px 8px;border-radius:var(--sl-r-sm);\n border:1px solid var(--sl-line);background:color-mix(in srgb,var(--sl-accent) 7%,var(--sl-surface));\n box-shadow:inset 3px 0 0 color-mix(in srgb,var(--sl-accent) 72%,transparent);\n font-size:11.5px;line-height:1.35;color:var(--sl-muted)}\n.sl-hold-note.on{display:flex;animation:slNoticeIn .38s cubic-bezier(.2,.8,.2,1) both}\n.sl-hold-note svg{width:16px;height:16px;flex:none;stroke:var(--sl-accent);stroke-width:2.4;fill:none;\n stroke-linecap:round;stroke-linejoin:round}\n.sl-hold-note b{display:block;color:var(--sl-text);font-size:11.5px;white-space:nowrap}\n.sl-hold-copy{display:block;white-space:nowrap;font-size:10.5px}\n.sl-hold-note>span{flex:1;min-width:0}\n.sl-hold-change{flex:none;min-height:30px;padding:5px 8px;border-radius:8px;border:1px solid var(--sl-line);\n color:var(--sl-text);font-size:10.5px;font-weight:750;white-space:nowrap}\n.sl-hold-change:hover,.sl-hold-change:focus-visible{border-color:var(--sl-accent);color:var(--sl-accent)}\n.sl-hold-change:disabled{opacity:.58;cursor:wait}\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-value-pop{animation:slValuePop .32s cubic-bezier(.2,.8,.2,1)}\n/* Primary checkout CTA. Scoped under .sl-picker so it OUTWEIGHS the\n '.sl-picker button' reset (0,1,1) — an unscoped '.sl-cta' (0,1,0) loses to it\n and the button renders as plain text with no accent fill. */\n.sl-picker .sl-cta{display:flex;align-items:center;justify-content:center;width:100%;min-height:44px;\n padding:12px 16px;border-radius:var(--sl-r-sm);font-weight:800;font-size:14px;line-height:1.1;\n background:var(--sl-accent);color:var(--sl-accent-ink);\n transition:filter .15s,background .22s,color .22s,transform .12s,box-shadow .22s;gap:8px}\n.sl-picker .sl-cta:hover{filter:brightness(1.08)}\n.sl-picker .sl-cta:active{transform:translateY(1px);filter:brightness(.94)}\n.sl-picker .sl-cta.sl-ready{animation:slCtaReady .42s cubic-bezier(.2,.8,.2,1)}\n.sl-cta-spin,.sl-ba-spin{width:14px;height:14px;border-radius:50%;border:2px solid currentColor;border-right-color:transparent;\n animation:slspin .7s linear infinite;flex:none}\n/* Disabled (\"Select seats\"): quieter, but still a full-width button shape. */\n.sl-picker .sl-cta:disabled{background:var(--sl-surface);color:var(--sl-muted);opacity:1;\n cursor:not-allowed;filter:none;transform:none}\n\n/* Chrome anchor regions (Feature 6) — every persistent map overlay is APPENDED\n INTO one of these positioned flex containers and flows/stacks within it, so no\n two pieces of chrome free-float on top of each other. Regions never overlap:\n the top strip splits into left/center/right; rails + corners own their edge. */\n.sl-anchor{position:absolute;z-index:5;display:flex;gap:8px;pointer-events:none}\n.sl-anchor > *{pointer-events:auto}\n.sl-anchor[data-region=\"top-left\"]{top:12px;left:12px;flex-wrap:wrap;max-width:38%}\n.sl-anchor[data-region=\"top-center\"]{top:12px;left:50%;transform:translateX(-50%);flex-direction:column;\n align-items:center;max-width:44%}\n.sl-anchor[data-region=\"top-right\"]{top:12px;right:12px;justify-content:flex-end;flex-wrap:wrap;max-width:38%}\n.sl-anchor[data-region=\"left-rail\"]{top:50%;left:12px;transform:translateY(-50%);flex-direction:column;max-width:42%;gap:6px}\n.sl-anchor[data-region=\"bottom-left\"]{left:12px;bottom:12px;flex-direction:column;align-items:flex-start}\n.sl-anchor[data-region=\"bottom-center\"]{left:50%;bottom:14px;transform:translateX(-50%);z-index:9;\n flex-direction:column;align-items:center;gap:8px;max-width:92%}\n.sl-anchor[data-region=\"bottom-right\"]{right:12px;bottom:12px;flex-direction:column;align-items:flex-end;gap:6px}\n/* narrow: tighten the top strip so left/center can't crowd each other */\n.sl-picker[data-layout=\"narrow\"] .sl-anchor[data-region=\"top-left\"]{max-width:30%}\n.sl-picker[data-layout=\"narrow\"] .sl-anchor[data-region=\"top-center\"]{max-width:44%}\n\n/* TEST MODE badge — a small pill in the top-right region (shrinks on narrow) */\n.sl-testbadge{padding:5px 11px;border-radius:999px;font-size:10px;font-weight:800;letter-spacing:.1em;\n text-transform:uppercase;white-space:nowrap;background:var(--sl-accent);color:var(--sl-accent-ink);\n box-shadow:0 2px 8px rgba(0,0,0,.25)}\n.sl-picker[data-layout=\"narrow\"] .sl-testbadge{padding:3px 8px;font-size:8.5px;letter-spacing:.06em}\n\n/* zoom column (flows within the bottom-right region) */\n.sl-zoom{display:flex;flex-direction:column;gap:6px}\n/* CSS-fallback full screen (iOS Safari has no element fullscreen API) */\n.sl-picker.sl-fs{position:fixed;inset:0;z-index:2147483000;width:auto;height:auto;max-height:none;border-radius:0}\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 (toast flows in the bottom-center region) */\n.sl-toast{transform:translateY(6px) scale(.98);max-width:100%;\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 .22s,transform .22s;white-space:nowrap;\n overflow:hidden;text-overflow:ellipsis}\n.sl-toast.on{opacity:1;transform:translateY(0) scale(1)}\n.sl-toast.has-action{pointer-events:auto;display:flex;align-items:center;gap:12px;padding-right:8px}\n.sl-toast-action{min-height:30px;padding:5px 10px;border-radius:999px;background:var(--sl-accent);color:var(--sl-accent-ink);\n font:inherit;font-weight:800}\n.sl-toast[data-tone=\"error\"]{border-color:#ef4444}\n.sl-toast[data-tone=\"warning\"]{border-color:var(--sl-accent)}\n.sl-toast[data-tone=\"success\"]{border-color:#22c55e}\n.sl-toast.on[data-tone=\"error\"]{animation:slToastNudge .32s ease-out}\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 (flows in the bottom-center region, above the toast) */\n.sl-extend{transform:translateY(6px);\n display:none;align-items:center;gap:12px;max-width:100%;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: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:flex;flex-direction:column;align-items:center;\n justify-content:center;gap:12px;text-align:center;padding:28px;background:var(--sl-bg);opacity:0;visibility:hidden;\n pointer-events:none;transition:opacity .34s ease,visibility 0s linear .34s}\n.sl-booked.on{opacity:1;visibility:visible;pointer-events:auto;transition:opacity .34s ease,visibility 0s}\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);transform:scale(.72)}\n.sl-booked.on .sl-booked-badge{animation:slSuccessPop .58s cubic-bezier(.2,1.25,.3,1) .08s both}\n.sl-booked-badge svg{width:30px;height:30px;stroke:currentColor;stroke-width:2.6;fill:none;stroke-linecap:round;stroke-linejoin:round;\n stroke-dasharray:30;stroke-dashoffset:30}\n.sl-booked.on .sl-booked-badge svg{animation:slCheckDraw .42s ease-out .32s forwards}\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.sl-booked.on .sl-booked-title,.sl-booked.on .sl-booked-sub{animation:slCopyRise .42s ease-out both}\n.sl-booked.on .sl-booked-title{animation-delay:.22s}\n.sl-booked.on .sl-booked-sub{animation-delay:.3s}\n\n/* sold-out overlay — every SEATED category's live availability is 0. Centered\n over the map; a stub (disabled) \"Join waitlist\" button, exactly like the page.\n Suppressed when GA areas exist (GA capacity isn't seat-counted). Clears live\n the moment WS frees a seat up. */\n.sl-soldout{position:absolute;inset:0;z-index:10;display:none;flex-direction:column;align-items:center;\n justify-content:center;text-align:center;gap:8px;padding:24px;\n background:color-mix(in srgb,var(--sl-bg) 82%,transparent);backdrop-filter:blur(4px)}\n.sl-soldout.on{display:flex}\n.sl-soldout-eyebrow{font-size:10px;letter-spacing:.2em;text-transform:uppercase;color:var(--sl-accent);font-weight:800}\n.sl-soldout-title{font-size:32px;font-weight:800;color:var(--sl-text);line-height:1.05}\n.sl-soldout-copy{max-width:360px;font-size:13px;color:var(--sl-muted);line-height:1.5}\n.sl-picker .sl-soldout-btn{margin-top:10px;min-height:40px;padding:10px 18px;border-radius:var(--sl-r-sm);\n background:var(--sl-surface);color:var(--sl-muted);border:1px solid var(--sl-line);font-weight:800;font-size:13px;\n cursor:not-allowed;opacity:.85}\n\n/* sales-closed pill (header) — persistent read-only state when the event's sales\n window is closed at load or closes live mid-session. Neutral (not accent) so it\n reads as \"unavailable\", distinct from the accent hold pill next to it. */\n.sl-closed-pill{display:none;align-items:center;gap:6px;padding:6px 12px;border-radius:999px;flex:none;\n background:color-mix(in srgb,var(--sl-text) 12%,var(--sl-surface));color:var(--sl-text);\n font-weight:700;font-size:12px;white-space:nowrap}\n.sl-closed-pill.on{display:inline-flex}\n.sl-closed-pill svg{width:13px;height:13px;stroke:currentColor;stroke-width:2;fill:none;stroke-linecap:round;stroke-linejoin:round}\n\n/* \"Powered by SeatLayer\" attribution badge (side-panel foot) — the small gold\n rounded logo mark + wordmark. Hidden when the host opts out or the org's paid\n theme sets hideBadge. */\n.sl-powered{display:flex;align-items:center;justify-content:center;gap:6px;margin-top:10px;\n font-size:11px;letter-spacing:.03em;color:var(--sl-muted)}\n.sl-powered-mark{width:16px;height:16px;border-radius:4px;flex:none;display:flex;align-items:center;justify-content:center;\n background:var(--sl-accent);color:var(--sl-accent-ink)}\n.sl-powered-mark svg{width:11px;height:11px;fill:currentColor}\n\n/* a11y filter chips (flow within the top-left region) */\n.sl-chips{display:flex;gap:6px;flex-wrap:wrap}\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 card: a candidate is not in the tray until Select. Map gestures and\n floating chrome pause while the card owns focus, keeping the camera stable. */\n.sl-picker[data-confirming=\"true\"] .sl-map-host>:not(.sl-confirm){pointer-events:none}\n.sl-picker[data-confirming=\"true\"] .sl-anchor{pointer-events:none;opacity:.28;transition:opacity .16s}\n.sl-picker[data-confirming=\"true\"] .sl-side{pointer-events:none;opacity:.58;transition:opacity .16s}\n.sl-confirm{position:absolute;z-index:10;width:276px;max-width:calc(100% - 24px);overflow:hidden;pointer-events:auto;\n background:var(--sl-surface);border:1px solid color-mix(in srgb,var(--sl-line) 70%,var(--sl-text));\n border-radius:15px;box-shadow:0 24px 64px -18px rgba(0,0,0,.72);transform:translate(-50%,calc(-100% - 16px));\n animation:slConfirmIn .24s cubic-bezier(.2,.8,.2,1) both}\n.sl-confirm[data-placement=\"below\"]{transform:translate(-50%,16px);animation:slConfirmBelowIn .24s cubic-bezier(.2,.8,.2,1) both}\n.sl-confirm-grid{display:grid;grid-template-columns:minmax(0,1fr) minmax(52px,auto) minmax(52px,auto);border-bottom:1px solid var(--sl-line)}\n.sl-confirm-field{min-width:0;padding:12px 11px 10px;border-right:1px solid var(--sl-line)}\n.sl-confirm-field:last-child{border-right:0;text-align:center}\n.sl-confirm-field:nth-child(2){text-align:center}\n.sl-confirm-key{display:block;font-size:8.5px;letter-spacing:.12em;text-transform:uppercase;color:var(--sl-muted);font-weight:800}\n.sl-confirm-value{display:block;margin-top:4px;color:var(--sl-text);font-size:17px;line-height:1.1;font-weight:850;\n white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n/* Long venue section names must read in full: smaller type + up to two lines\n beats an ellipsis at identity-confirmation time. Row/seat stay big — they're\n short and they're what the buyer double-checks against the map. */\n.sl-confirm-field:first-child .sl-confirm-value{font-size:13.5px;line-height:1.25;white-space:normal;\n display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical}\n.sl-confirm-cat{display:flex;align-items:center;gap:8px;padding:10px 12px;background:color-mix(in srgb,var(--sl-cat) 76%,var(--sl-surface))}\n.sl-confirm-cat .sl-dot{border:2px solid rgba(255,255,255,.78);width:11px;height:11px}\n.sl-confirm-cat-name{font-size:13.5px;font-weight:800;color:#fff;flex:1;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n.sl-confirm-price{font-size:17px;font-weight:850;color:#fff;font-variant-numeric:tabular-nums}\n.sl-confirm-body{padding:11px 12px 12px}\n.sl-confirm-row{display:flex;gap:8px;margin-top:10px}\n.sl-confirm-row button{flex:1;min-height:44px;padding:9px 12px;border-radius:9px;font-weight:800;font-size:13px}\n.sl-confirm-add{background:var(--sl-accent)!important;color:var(--sl-accent-ink)!important;display:flex;align-items:center;justify-content:center;gap:7px}\n.sl-confirm-add svg{width:16px;height:16px;stroke:currentColor;stroke-width:2.8;fill:none;stroke-linecap:round;stroke-linejoin:round}\n.sl-confirm-cancel{background:color-mix(in srgb,var(--sl-line) 44%,transparent)!important;border:1px solid var(--sl-line)!important;color:var(--sl-muted)!important}\n.sl-confirm-cancel:hover{color:var(--sl-text)}\n.sl-picker[data-layout=\"narrow\"] .sl-confirm{left:50%!important;top:auto!important;bottom:14px;width:min(342px,calc(100% - 24px));\n transform:translateX(-50%);animation:slConfirmMobileIn .24s cubic-bezier(.2,.8,.2,1) both}\n\n/* hover preview — a COMPACT echo of the confirm card (deliberately smaller: it's\n a passing preview on hover, not the click/select action surface). Reuses the\n Section·Row·Seat identity grid so hover, confirm and the cart chip all share\n one visual language, just at three sizes. */\n.sl-tip{position:absolute;z-index:7;pointer-events:none;display:none;width:190px;overflow:hidden;\n background:var(--sl-surface);color:var(--sl-text);border:1px solid var(--sl-line);border-radius:11px;\n box-shadow:0 12px 30px -14px rgba(0,0,0,.6)}\n.sl-tip-grid{display:grid;grid-template-columns:1.3fr .85fr .85fr;border-bottom:1px solid var(--sl-line)}\n.sl-tip-grid.one{grid-template-columns:1fr}\n.sl-tip-field{min-width:0;padding:6px 9px;border-right:1px solid var(--sl-line)}\n.sl-tip-field:last-child{border-right:0;text-align:center}\n.sl-tip-grid:not(.one) .sl-tip-field:nth-child(2){text-align:center}\n.sl-tip-key{display:block;font-size:7.5px;letter-spacing:.1em;text-transform:uppercase;color:var(--sl-muted);font-weight:800}\n.sl-tip-val{display:block;margin-top:2px;color:var(--sl-text);font-size:13px;line-height:1.1;font-weight:750;\n white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n.sl-tip-cat{display:flex;align-items:center;gap:7px;padding:6px 10px;font-size:11px;\n background:color-mix(in srgb,var(--sl-cat) 12%,var(--sl-surface))}\n.sl-tip-dot{width:8px;height:8px;border-radius:50%;flex:none}\n.sl-tip-name{color:var(--sl-muted);flex:1;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n.sl-tip-amt{margin-left:auto;font-weight:800;color:var(--sl-text);font-variant-numeric:tabular-nums;font-size:12px}\n.sl-tip-status{padding:5px 10px 7px;font-size:8.5px;letter-spacing:.09em;text-transform:uppercase;font-weight:700;color:var(--sl-muted)}\n\n/* Best available is a first-class shortcut, not an anonymous utility row. */\n.sl-ba{position:relative;flex:none;overflow:hidden;display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:center;gap:7px;\n padding:13px;border:1px solid color-mix(in srgb,var(--sl-accent) 34%,var(--sl-line));border-radius:13px;\n background:linear-gradient(135deg,color-mix(in srgb,var(--sl-accent) 5%,var(--sl-surface)),color-mix(in srgb,var(--sl-accent) 11%,var(--sl-surface)))}\n.sl-ba::after{content:'✦';position:absolute;right:10px;top:3px;color:color-mix(in srgb,var(--sl-accent) 20%,transparent);font-size:42px;line-height:1}\n.sl-ba-title,.sl-ba-copy,.sl-ba select,.sl-ba-qty,.sl-ba-go{position:relative;z-index:1}\n.sl-ba-title{grid-column:1/-1;display:flex;align-items:center;gap:7px;font-size:13px;font-weight:850}\n.sl-ba-title .spark{color:var(--sl-accent);font-size:16px}\n.sl-ba-copy{grid-column:1/-1;margin:-4px 0 2px 23px;color:var(--sl-muted);font-size:10.5px;line-height:1.35}\n.sl-ba-copy .narrow{display:none}\n.sl-ba select{background:var(--sl-surface);color:var(--sl-text);border:1px solid var(--sl-line);border-radius:8px;\n font:inherit;font-size:11px;padding:7px 8px;min-width:0;width:100%;max-width:none}\n.sl-ba-qty{display:flex;align-items:center;gap:7px;padding:3px;border:1px solid var(--sl-line);border-radius:9px;background:var(--sl-surface)}\n.sl-ba-qty button{width:25px;height:25px;border-radius:7px;background:color-mix(in srgb,var(--sl-line) 35%,transparent);border:0;\n font-size:14px;font-weight:800;display:flex;align-items:center;justify-content:center}\n.sl-ba-qty span{min-width:14px;text-align:center;font-weight:800}\n.sl-picker .sl-ba-go{grid-column:1/-1;width:100%;min-height:37px;padding:7px 12px;border-radius:9px;background:var(--sl-accent);\n color:var(--sl-accent-ink);font-weight:800;font-size:12px;transition:filter .15s,opacity .15s;display:flex;align-items:center;justify-content:center;gap:6px;\n box-shadow:0 8px 18px color-mix(in srgb,var(--sl-accent) 18%,transparent)}\n.sl-picker .sl-ba-go:hover{filter:brightness(1.06)}\n.sl-picker .sl-ba-go:disabled{opacity:.62;cursor:wait}\n.sl-ba-replace{grid-column:1/-1;padding:3px 0 1px}\n.sl-ba-replace b{display:block;font-size:12.5px}\n.sl-ba-replace span{display:block;margin-top:3px;color:var(--sl-muted);font-size:10.5px;line-height:1.35}\n.sl-ba-actions{grid-column:1/-1;display:grid;grid-template-columns:1fr 1fr;gap:7px}\n.sl-ba-actions button{min-height:36px;border-radius:9px;border:1px solid var(--sl-line);font-size:11.5px;font-weight:800}\n.sl-ba-actions .replace{border-color:var(--sl-accent);background:var(--sl-accent);color:var(--sl-accent-ink)}\n.sl-picker[data-layout=\"narrow\"] .sl-ba{padding:11px}\n.sl-picker[data-layout=\"narrow\"] .sl-ba-copy .wide{display:none}\n.sl-picker[data-layout=\"narrow\"] .sl-ba-copy .narrow{display:inline}\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:6px;\n font:inherit;font-size:10px;padding:2px 4px;min-width:0;max-width:100%;cursor:pointer}\n\n/* arena: LOD rung pills (flow within the top-center region) */\n.sl-rungs{display:none;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/* narrow: shrink the rung pills so the centered row can't reach the corner regions */\n.sl-picker[data-layout=\"narrow\"] .sl-rungs button{padding:5px 9px;font-size:9px;letter-spacing:.03em}\n\n/* multi-floor switcher (flows within the left-rail region) */\n.sl-floors{display:none;flex-direction:column;gap:6px;max-width:100%}\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 — docks INSIDE the top-center anchor region on\n wide (flows below the rung pills, never over them, never floating over the\n seats at the tap point). Auto-collapses to a slim pill once seat-picking\n begins (first seat select, or a pan/zoom after the focus glide); tapping the\n pill re-expands; ✕ closes in both states. On narrow it renders as a compact\n strip inside the bottom sheet's peek head — never over the canvas. */\n.sl-seccard{width:250px;max-width:100%;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/* collapsed pill (wide) */\n.sl-seccard.mini{width:auto;padding:5px 7px 5px 12px;border-radius:999px;cursor:pointer}\n.sl-seccard.mini.on{display:inline-flex;align-items:center;gap:7px}\n.sl-seccard.mini .sl-seccard-name{font-size:12px;flex:none;max-width:120px}\n.sl-seccard.mini .sl-seccard-left{font-size:11px}\n/* narrow: compact strip inside the sheet head (peek area) */\n.sl-seccard.strip{width:100%;padding:7px 0 0;border:0;border-radius:0;box-shadow:none;background:none;cursor:default}\n.sl-seccard.strip.on{display:flex;align-items:center;gap:7px;font-size:12.5px}\n.sl-seccard.strip .sl-seccard-name{font-size:12.5px}\n.sl-seccard.strip .sl-seccard-price{margin-left:auto}\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/* Eager sightline preview inside the confirm card */\n.sl-confirm-thumbwrap{position:relative;display:block;width:100%;height:74px;margin:0 0 8px;padding:0!important;\n border-radius:9px;overflow:hidden;border:1px solid var(--sl-line);cursor:pointer}\n.sl-confirm-thumb{display:block;width:100%;height:100%;object-fit:cover}\n.sl-confirm-thumb-badge{position:absolute;right:7px;top:7px;display:inline-flex;align-items:center;gap:5px;\n font-size:10px;font-weight:700;color:#fff;background:rgba(10,14,22,0.72);border-radius:12px;padding:4px 9px;backdrop-filter:blur(3px)}\n.sl-confirm-sight{display:flex;align-items:center;gap:6px;font-size:11px;color:var(--sl-muted);margin-bottom:2px}\n.sl-confirm-sight span{color:#22a06b;font-weight:800}\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/* F3 minimap — venue overview + live viewport rect (flows in the bottom-left region) */\n.sl-minimap{border:1px solid var(--sl-line);border-radius:9px;\n overflow:hidden;background:var(--sl-surface);box-shadow:0 12px 34px -14px rgba(0,0,0,.55);line-height:0;cursor:pointer}\n.sl-minimap canvas{display:block}\n.sl-picker[data-layout=\"narrow\"] .sl-minimap{display:none}\n\n/* F4 legend reflection: rows + counts for out-of-band categories read muted */\n.sl-price-row.sl-dim{opacity:.4}\n.sl-seccard-mix-item.sl-dim{opacity:.4}\n\n/* Buyer-journey motion: every animation explains a state transition (selected,\n held, checkout handoff, conflict or booked). No decorative infinite motion\n except the expiring-hold pulse and active progress spinners. */\n@keyframes slPillIn{from{opacity:0;transform:translateX(7px) scale(.9)}to{opacity:1;transform:translateX(0) scale(1)}}\n@keyframes slHoldPulse{0%{box-shadow:0 0 0 0 currentColor;opacity:.9}75%,100%{box-shadow:0 0 0 7px transparent;opacity:.55}}\n@keyframes slChipIn{from{opacity:0;transform:translateY(8px) scale(.98)}to{opacity:1;transform:translateY(0) scale(1)}}\n@keyframes slChipOut{to{opacity:0;transform:translateX(10px) scale(.98)}}\n@keyframes slNoticeIn{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:translateY(0)}}\n@keyframes slValuePop{0%{opacity:.6;transform:translateY(3px)}55%{transform:translateY(-1px) scale(1.05)}100%{opacity:1;transform:none}}\n@keyframes slCtaReady{0%{transform:scale(.98);box-shadow:0 0 0 0 transparent}55%{transform:scale(1.01);box-shadow:0 0 0 5px color-mix(in srgb,var(--sl-accent) 18%,transparent)}100%{transform:none;box-shadow:none}}\n@keyframes slToastNudge{0%,100%{margin-left:0}30%{margin-left:-4px}60%{margin-left:3px}}\n@keyframes slSuccessPop{0%{opacity:0;transform:scale(.72)}65%{opacity:1;transform:scale(1.08)}100%{opacity:1;transform:scale(1)}}\n@keyframes slCheckDraw{to{stroke-dashoffset:0}}\n@keyframes slCopyRise{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}\n@keyframes slConfirmIn{from{opacity:0;transform:translate(-50%,calc(-100% - 8px)) scale(.96)}to{opacity:1;transform:translate(-50%,calc(-100% - 14px)) scale(1)}}\n@keyframes slConfirmBelowIn{from{opacity:0;transform:translate(-50%,8px) scale(.96)}to{opacity:1;transform:translate(-50%,16px) scale(1)}}\n@keyframes slConfirmMobileIn{from{opacity:0;transform:translate(-50%,10px) scale(.97)}to{opacity:1;transform:translate(-50%,0) scale(1)}}\n\n@media(prefers-reduced-motion:reduce){\n .sl-picker *,.sl-modal-scrim *{animation-duration:.001ms!important;animation-iteration-count:1!important;\n transition-duration:.001ms!important;scroll-behavior:auto!important}\n}\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\n/**\n * Colorblind-safe preference is a SHARED buyer preference across every SeatLayer\n * surface (the bespoke public page persists it too), so the widget reads/writes\n * the SAME localStorage key. All access is guarded — private-mode/SSR safe.\n */\nconst CB_STORAGE_KEY = 'seatmap.a11y.cb';\nfunction readStoredColorblind(): boolean | null {\n try {\n if (typeof window === 'undefined') return null;\n const raw = window.localStorage.getItem(CB_STORAGE_KEY);\n return raw == null ? null : raw === '1';\n } catch {\n return null;\n }\n}\nfunction writeStoredColorblind(on: boolean): void {\n try {\n window.localStorage.setItem(CB_STORAGE_KEY, on ? '1' : '0');\n } catch {\n /* private mode / storage disabled — preference is best-effort */\n }\n}\n\nexport class SeatPicker {\n private readonly opts: SeatPickerOptions;\n private readonly api: PickerTransport;\n private readonly apiBase: string;\n private readonly controller: PickerController;\n private readonly maxTickets: number;\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 /** Feature 6 anchor regions — positioned flex containers over the map. */\n private regions: 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 /** Short-lived UI motion timers; all are cancelled on destroy. */\n private motionTimers = new Set<ReturnType<typeof setTimeout>>();\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 baQty = 2;\n private baCat = '';\n private bestAvailableConfirm = false;\n private releasingHold = false;\n /** Event sales window is closed (read-only load state / live close). */\n private salesClosed = false;\n /** Every seated category's live availability is 0 (sold-out overlay is up). */\n private soldOut = false;\n private soldoutEl: HTMLDivElement | null = null;\n /** Resolved colorblind-safe state — stored preference wins over the option. */\n private cbSafe = false;\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 // F3 minimap\n private miniCanvas: HTMLCanvasElement | null = null;\n private miniBase: HTMLCanvasElement | null = null;\n private miniTf: { scale: number; offX: number; offY: number; dpr: number } | null = null;\n\n // F4 price-band filter — active band's category keys (null = all prices)\n private priceBandKeys: Set<string> | null = null;\n private focusedCatKey: string | null = null;\n private pricesExpanded = false;\n /** Last surfaced section summary (re-rendered when the price band changes). */\n private lastSection: SectionSummary | null = null;\n /** Section card collapsed to its slim pill (seat-picking has begun). */\n private secCardCollapsed = false;\n /** When the card was (re)shown — the focus glide's own view change must not collapse it. */\n private secCardShownAt = 0;\n /** Previous tray ticket count — first 0→n transition auto-expands the mobile sheet. */\n private lastTrayCount = 0;\n /** Previous computed total — drives a single explanatory value bump. */\n private lastTrayTotal = 0;\n /** Stable item keys prevent tray chips re-animating on unrelated realtime syncs. */\n private lastTrayKeys = new Set<string>();\n private bestAvailableBusy = false;\n private releasingLabels = new Set<string>();\n /** Selected labels awaiting the hold response; their own realtime echo can arrive first. */\n private holdingLabels = new Set<string>();\n private ctaPhase: 'idle' | 'holding' | 'checkout' = 'idle';\n // narrow-layout chrome that docks into the sheet's Filters row on mobile\n private a11yChipsEl: HTMLDivElement | null = null;\n private fsFallback = false;\n private fsChangeHandler: (() => void) | null = null;\n private fsEscHandler: ((e: KeyboardEvent) => void) | null = null;\n /** True once we've asked the host page to pin us fullscreen (framed, no native). */\n private framedFs = false;\n /** Last height (px) posted to a host frame; dedupes redundant reports. */\n private lastPostedHeight = 0;\n\n /**\n * Eager sightline preview for the confirm card: a cheap generated forward\n * view (or the organizer's real photo) plus a \"Nm to stage · clear\n * sightline\" line — the premium at-a-glance moment; click opens the 360.\n */\n private confirmThumbHtml(seat: ExpandedSeat): string {\n const doc = this.controller.doc;\n if (!doc) return '';\n let url = seat.viewUrl ?? '';\n let distance: number | null = null;\n if (!url) {\n try {\n const thumb = generateSeatThumb(seat, doc.focalPoint);\n url = thumb.url;\n distance = thumb.distanceM ?? null;\n } catch {\n return '';\n }\n }\n const sight = distance != null\n ? t('picker.sightline', { m: distance })\n : this.tf('picker.sightlineClear', 'Clear sightline');\n return (\n `<button type=\"button\" class=\"sl-confirm-view sl-confirm-thumbwrap\" aria-label=\"${t('picker.viewFromSeat', { label: seat.label })}\">` +\n `<img class=\"sl-confirm-thumb\" src=\"${url}\" alt=\"\" />` +\n `<span class=\"sl-confirm-thumb-badge\">🔭 ${this.tf('picker.viewFromHere', 'View from here')}</span>` +\n `</button>` +\n `<div class=\"sl-confirm-sight\"><span aria-hidden=\"true\">✓</span>${sight}</div>`\n );\n }\n\n /** True when the picker is rendered inside an iframe (snippet embed at /e/:key). */\n private isFramed(): boolean {\n return typeof window !== 'undefined' && window.parent !== window;\n }\n\n /**\n * Post a widget→host message when framed. targetOrigin is '*' because the\n * payload carries nothing sensitive (a height number / a fullscreen flag);\n * hosts verify `event.origin` on their side (see `attachPickerFrame`).\n */\n private postToHost(message: { type: string; [key: string]: unknown }): void {\n if (!this.isFramed()) return;\n try {\n window.parent.postMessage(message, '*');\n } catch {\n /* a hostile/cross-origin parent may reject postMessage — nothing to do */\n }\n }\n\n /**\n * Height (px) to advertise to a host frame.\n *\n * The picker fills whatever box it's given: `.sl-picker` is `height:100%;\n * overflow:hidden`, and the /e/:key shell mounts it `position:fixed; inset:0`.\n * So it has no intrinsic *document* height to read — `scrollHeight` just\n * collapses to the current viewport, which for a framed embed would echo the\n * host's own iframe height straight back (a circular value). We therefore\n * report a width-driven *desired* height: a pleasant landscape box on desktop,\n * taller on narrow widths where the bottom sheet needs room, clamped to the\n * widget's `min-height` of 420. Width is host-controlled and never moves in\n * response to the height we report, so this cannot feedback-loop.\n */\n private measureFramedHeight(): number {\n const root = this.root;\n if (!root) return 0;\n const width = root.clientWidth || (typeof window !== 'undefined' ? window.innerWidth : 0) || 0;\n if (width <= 0) return 0;\n const ratio = width < 640 ? 1.2 : 0.62;\n return Math.max(420, Math.round(width * ratio));\n }\n\n /** Post `seatlayer:height` to the host when framed and the value changed. */\n private reportFramedHeight(): void {\n if (!this.isFramed()) return;\n const px = this.measureFramedHeight();\n if (px <= 0 || px === this.lastPostedHeight) return;\n this.lastPostedHeight = px;\n this.postToHost({ type: 'seatlayer:height', px });\n }\n\n /** Full screen via the native API, falling back to a fixed-position overlay (iOS Safari). */\n private toggleFullscreen(): void {\n const root = this.root;\n if (!root) return;\n const active = !!document.fullscreenElement || this.fsFallback || this.framedFs;\n if (!active) {\n if (root.requestFullscreen) {\n root.requestFullscreen().catch(() => this.enterFsFallback());\n } else {\n this.enterFsFallback();\n }\n } else if (document.fullscreenElement) {\n void document.exitFullscreen().catch(() => {});\n } else if (this.framedFs) {\n this.setFramedFs(false);\n } else {\n this.setFsFallback(false);\n }\n }\n\n /**\n * Native element-fullscreen was unavailable or rejected. When framed, a CSS\n * `.sl-fs` overlay can't escape the iframe, so we ask the host page to pin us\n * (`seatlayer:fullscreen`). Otherwise (iOS Safari, same document) fall back to\n * the `.sl-fs` overlay as before.\n */\n private enterFsFallback(): void {\n if (this.isFramed()) this.setFramedFs(true);\n else this.setFsFallback(true);\n }\n\n /** Toggle host-driven (framed) fullscreen: post the flag + own the Esc key. */\n private setFramedFs(on: boolean): void {\n if (this.framedFs === on) return;\n this.framedFs = on;\n this.els.zfs?.setAttribute('aria-pressed', String(on || !!document.fullscreenElement));\n this.postToHost({ type: 'seatlayer:fullscreen', on });\n if (on && !this.fsEscHandler) {\n this.fsEscHandler = (e: KeyboardEvent): void => {\n if (e.key === 'Escape' && !document.fullscreenElement) this.setFramedFs(false);\n };\n window.addEventListener('keydown', this.fsEscHandler);\n } else if (!on && this.fsEscHandler) {\n window.removeEventListener('keydown', this.fsEscHandler);\n this.fsEscHandler = null;\n }\n requestAnimationFrame(() => this.controller.zoomToFit());\n }\n\n private setFsFallback(on: boolean): void {\n if (this.fsFallback === on) return;\n this.fsFallback = on;\n this.root?.classList.toggle('sl-fs', on);\n this.els.zfs?.setAttribute('aria-pressed', String(on || !!document.fullscreenElement));\n if (on && !this.fsEscHandler) {\n this.fsEscHandler = (e: KeyboardEvent): void => {\n if (e.key === 'Escape' && !document.fullscreenElement) this.setFsFallback(false);\n };\n window.addEventListener('keydown', this.fsEscHandler);\n } else if (!on && this.fsEscHandler) {\n window.removeEventListener('keydown', this.fsEscHandler);\n this.fsEscHandler = null;\n }\n requestAnimationFrame(() => this.controller.zoomToFit());\n }\n private cbEl: HTMLButtonElement | 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 let closing = false;\n const close = (): void => {\n if (closing) return;\n closing = true;\n document.body.style.overflow = prevOverflow;\n // Visually dismiss immediately, but let an abandoned auto-hold finish its\n // release request before tearing down the transport. This keeps closing a\n // modal from stranding inventory until the normal hold expiry.\n scrim.style.opacity = '0';\n scrim.style.pointerEvents = 'none';\n const finish = (): void => {\n picker.destroy();\n options.onClose?.();\n };\n if (picker.hold && !picker.handedOff) void picker.release().finally(finish);\n else finish();\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') return;\n if (picker.confirmSeat) {\n e.preventDefault();\n picker.cancelConfirm();\n } else if (picker.bestAvailableConfirm) {\n e.preventDefault();\n picker.bestAvailableConfirm = false;\n picker.syncTray();\n } else {\n close();\n }\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, confirmSelection: options.confirmSelection ?? true };\n this.apiBase = (options.apiBase ?? DEFAULT_API_BASE).replace(/\\/+$/, '');\n this.api = options.transport ?? new PubApi(this.apiBase);\n this.maxTickets = Math.max(1, Math.floor(options.maxSelection ?? DEFAULT_MAX_SELECTION));\n // Colorblind preference: the stored (cross-surface) value wins over the\n // option; the option is only the initial default when nothing is stored.\n this.cbSafe = readStoredColorblind() ?? !!options.colorblindSafe;\n this.controller = new PickerController({\n transport: this.api,\n eventKey: options.event,\n maxSelection: this.maxTickets,\n currency: options.currency,\n flashOnLiveChange: true,\n colorblindSafe: this.cbSafe,\n onSelectionChange: () => {\n this.syncTray();\n // Seat-picking has begun — collapse the section card out of the way.\n if (this.committedSelection().length) this.collapseSectionCard();\n },\n onStatusChange: () => {\n this.syncPrices();\n this.evictTakenSelections();\n this.detectBooked();\n // Live open/close of a section repaints the minimap's static overview.\n this.refreshMinimap();\n },\n onHoldExpired: () => {\n this.hold = null;\n this.forgetHold();\n this.handedOff = false;\n this.bookedShown = false;\n this.ctaPhase = 'idle';\n this.stopHoldTimer();\n this.gaQty.clear();\n this.toast(t('picker.holdExpired', undefined) || 'Your hold expired — seats released. Pick again.', 'warning');\n this.syncTray();\n this.emitHoldChange();\n this.opts.onHoldExpired?.();\n },\n confirmSelection: this.opts.confirmSelection,\n onSelect: (seat) => {\n // Sales-closed is a read-only state — refuse the pick (the controller\n // doesn't gate tapping; server would 409 the eventual hold anyway).\n if (this.salesClosed) {\n this.controller.deselect([seat.id]);\n this.toast(this.tf('picker.salesClosedToast', 'Sales are closed for this event.'), 'warning');\n return;\n }\n this.flashPickedSeat(seat.id);\n if (this.opts.confirmSelection) this.showConfirm(seat);\n },\n onDeselect: (seat) => {\n if (this.confirmSeat?.id === seat.id) this.dismissConfirm();\n },\n onSelectionLimit: () => {\n this.toast(`You can select up to ${this.maxTickets} tickets for this order.`, 'warning');\n },\n onViewChange: () => {\n this.reanchorConfirm();\n this.syncRung();\n this.drawMinimapRect();\n this.sectionCardOnView();\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 // Server declared the event closed mid-session (409 event_closed) — keep\n // the toast (raised by handleCta), and add the persistent read-only state.\n onSalesClosed: () => this.setSalesClosed(true),\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 root.tabIndex = -1;\n this.root = root;\n mount.appendChild(root);\n root.addEventListener('keydown', (e: KeyboardEvent) => {\n if (e.key !== 'Escape') return;\n if (this.confirmSeat) {\n e.preventDefault();\n e.stopPropagation();\n this.cancelConfirm();\n } else if (this.bestAvailableConfirm) {\n e.preventDefault();\n e.stopPropagation();\n this.bestAvailableConfirm = false;\n this.syncTray();\n }\n });\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 <span class=\"sl-closed-pill\" data-ref=\"closedPill\" role=\"status\">\n <svg viewBox=\"0 0 24 24\" aria-hidden=\"true\"><rect x=\"5\" y=\"11\" width=\"14\" height=\"9\" rx=\"2\"/><path d=\"M8 11V7a4 4 0 0 1 8 0v4\"/></svg>\n <span data-ref=\"closedPillText\"></span>\n </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\" data-ref=\"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 <button type=\"button\" aria-label=\"Full screen\" aria-pressed=\"false\" data-ref=\"zfs\">\n <svg viewBox=\"0 0 24 24\"><path d=\"M15 3h6v6M9 21H3v-6M21 3l-7 7M3 21l7-7\"/></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\" data-ref=\"side\">\n <div class=\"sl-sheet-head\" data-ref=\"sheetHead\">\n <div class=\"sl-sheet-grab\"></div>\n <div class=\"sl-sheet-bar\">\n <div class=\"sl-sheet-peek\" data-ref=\"peek\"></div>\n <button type=\"button\" class=\"sl-sheet-toggle\" data-ref=\"sheetToggle\" aria-label=\"Open ticket panel\" aria-expanded=\"false\">\n <svg viewBox=\"0 0 24 24\"><path d=\"M6 15l6-6 6 6\"/></svg>\n </button>\n </div>\n </div>\n <div class=\"sl-sec sl-filtersec\" data-ref=\"filtersSec\">Filters</div>\n <div class=\"sl-filters\" data-ref=\"filters\"></div>\n <div class=\"sl-sec sl-prices-sec\" data-ref=\"pricesSec\"><span>Ticket prices</span></div>\n <div class=\"sl-prices\" data-ref=\"prices\"></div>\n <div class=\"sl-live\" data-ref=\"live\" role=\"status\" aria-live=\"polite\"><span class=\"dot\" aria-hidden=\"true\"></span><span data-ref=\"liveText\">Live availability — seats update in real time</span></div>\n <div class=\"sl-sec sl-seats-sec\"><span>Your seats</span><span class=\"sl-seat-summary\" data-ref=\"seatSummary\"></span></div>\n <div class=\"sl-tray\" data-ref=\"tray\"></div>\n <div class=\"sl-foot\" data-ref=\"foot\">\n <div class=\"sl-hold-note\" data-ref=\"holdNote\" role=\"status\" aria-live=\"polite\">\n <svg viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M20 6L9 17l-5-5\"/></svg>\n <span><b data-ref=\"holdTitle\">Seats secured</b><span class=\"sl-hold-copy\" data-ref=\"holdCopy\">Checkout timer is running.</span></span>\n <button type=\"button\" class=\"sl-hold-change\" data-ref=\"holdChange\" aria-label=\"Release held tickets and choose different seats\">Change</button>\n </div>\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 (breakpoint keys off the CONTAINER, not the viewport)\n const applyLayout = (): void => {\n const w = root.clientWidth;\n if (w <= 0) return;\n // Report our desired height to a host frame on every size change (deduped),\n // not just when the layout breakpoint flips below.\n this.reportFramedHeight();\n const next = w < 640 ? 'narrow' : 'wide';\n if (root.dataset.layout === next) return;\n root.dataset.layout = next;\n // Entering the mobile sheet layout: start in the peek state (map-first).\n if (next === 'narrow' && !root.dataset.sheet) root.dataset.sheet = 'peek';\n this.dockLayoutChrome();\n };\n this.ro = new ResizeObserver(applyLayout);\n this.ro.observe(root);\n // Some environments defer the ResizeObserver's initial callback (backgrounded\n // tabs throttle delivery). Seed the layout synchronously + next frame so a\n // container that mounts already-wide gets data-layout=\"wide\" immediately,\n // instead of waiting on a resize that may never arrive.\n applyLayout();\n requestAnimationFrame(applyLayout);\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 // Full screen: native API with a CSS-fallback overlay for iOS Safari\n // (which has no element fullscreen). Esc exits both paths; the renderer's\n // ResizeObserver re-fits, plus an explicit zoomToFit for a crisp frame.\n this.els.zfs.addEventListener('click', () => this.toggleFullscreen());\n this.fsChangeHandler = (): void => {\n if (!document.fullscreenElement) this.setFsFallback(false);\n this.els.zfs?.setAttribute('aria-pressed', String(!!document.fullscreenElement || this.fsFallback || this.framedFs));\n requestAnimationFrame(() => this.controller.zoomToFit());\n };\n document.addEventListener('fullscreenchange', this.fsChangeHandler);\n\n // Mobile bottom sheet: swipe/tap on the sheet HEAD only (never the map host,\n // so the map's raw-pointer gesture pipeline is untouched). Swipe up → open\n // (≤50%); swipe down → peek; a plain tap toggles. The section-card strip's\n // ✕ lives inside the head — taps on the card must not toggle the sheet.\n const head = this.els.sheetHead;\n if (head) {\n const toggle = this.els.sheetToggle as HTMLButtonElement | undefined;\n const setSheet = (open: boolean): void => {\n root.dataset.sheet = open ? 'open' : 'peek';\n toggle?.setAttribute('aria-expanded', String(open));\n toggle?.setAttribute('aria-label', open ? 'Collapse ticket panel' : 'Open ticket panel');\n };\n setSheet(root.dataset.sheet === 'open');\n toggle?.addEventListener('click', (e) => {\n e.stopPropagation();\n setSheet(root.dataset.sheet !== 'open');\n });\n let startY = 0;\n let swiped = false;\n let tracking = false;\n head.addEventListener('pointerdown', (e: PointerEvent) => {\n tracking = true;\n swiped = false;\n startY = e.clientY;\n head.setPointerCapture?.(e.pointerId);\n });\n head.addEventListener('pointermove', (e: PointerEvent) => {\n if (!tracking || swiped) return;\n const dy = e.clientY - startY;\n if (dy < -18) {\n setSheet(true);\n swiped = true;\n } else if (dy > 18) {\n setSheet(false);\n swiped = true;\n }\n });\n head.addEventListener('pointerup', (e: PointerEvent) => {\n if (tracking && !swiped && Math.abs(e.clientY - startY) < 6) {\n if (!(e.target as HTMLElement).closest('.sl-seccard,.sl-sheet-toggle')) setSheet(root.dataset.sheet !== 'open');\n }\n tracking = false;\n head.releasePointerCapture?.(e.pointerId);\n });\n }\n this.tipEl = document.createElement('div');\n this.tipEl.setAttribute('role', 'tooltip');\n this.tipEl.className = 'sl-tip';\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 this.els.holdChange?.addEventListener('click', () => void this.handleChangeSeats());\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 // Read-only load state: the chart() payload carries salesClosed.\n this.salesClosed = !!info.salesClosed;\n\n // Feature 6: anchor regions for all persistent map chrome, then move the\n // pre-built zoom column + toast into their regions (both were in the skeleton).\n this.buildRegions();\n this.regions['bottom-right'].appendChild(this.els.zoom);\n this.regions['bottom-center'].appendChild(this.els.toast);\n\n if (info.mode === 'test') {\n // TEST MODE reads as a small badge in the top-right region (was a corner\n // ribbon that collided with the top-right control cluster on narrow widths).\n const badge = document.createElement('div');\n badge.className = 'sl-testbadge';\n badge.textContent = t('picker.testMode');\n badge.setAttribute('aria-label', t('picker.testMode'));\n this.regions['top-right'].appendChild(badge);\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 // \"Powered by SeatLayer\" attribution badge — hidden when the host opts out\n // OR the org's paid chart theme sets hideBadge (either being true hides it).\n this.buildBadge(chartTheme);\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.regions['top-left'].appendChild(chips);\n this.a11yChipsEl = chips;\n // Multi-select OR semantics (parity with the buyer page): each type chip\n // toggles independently; the active filter is the union; \"All seats\"\n // clears. A buyer needing wheelchair AND companion seats combines both.\n const active = new Set<AccessibilityType>();\n const syncChips = (): void => {\n chips.querySelectorAll<HTMLButtonElement>('button').forEach((b) => {\n const f = b.dataset.f as AccessibilityType | 'all';\n const on = f === 'all' ? active.size === 0 : active.has(f);\n b.classList.toggle('on', on);\n b.setAttribute('aria-pressed', String(on));\n });\n const filter = active.size ? [...active] : null;\n this.controller.setAccessibilityFilter(filter);\n // The accessibility filter dims/highlights individual SEAT dots, which\n // only render at the 'seats' rung. Applying it from a zoomed-out rung\n // (zones/sections) would silently dim seats the buyer can't see — so on\n // activation jump straight to seat detail, where the matching seats\n // stand out. Only when pills exist and we're not already there; never\n // on clear (so \"All seats\" doesn't yank the zoom).\n if (filter && this.rungsEl && this.controller.getRung() !== 'seats') {\n this.controller.setRung('seats');\n this.collapseSectionCard();\n this.syncRung();\n }\n };\n chips.querySelectorAll<HTMLButtonElement>('button').forEach((btn) => {\n btn.addEventListener('click', () => {\n const f = btn.dataset.f as AccessibilityType | 'all';\n if (f === 'all') active.clear();\n else if (active.has(f)) active.delete(f);\n else active.add(f);\n syncChips();\n });\n });\n }\n\n // Colorblind-safe toggle rides in the zoom column (wide) or the sheet's\n // Filters row (narrow) — dockLayoutChrome moves it between the two.\n const cb = document.createElement('button');\n cb.type = 'button';\n cb.className = 'sl-cbbtn';\n this.cbEl = cb;\n cb.setAttribute('aria-label', 'Toggle colorblind-friendly colors');\n // Rehydrated from the shared preference (constructor read stored → this.cbSafe).\n cb.setAttribute('aria-pressed', String(this.cbSafe));\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 cb.addEventListener('click', () => {\n this.cbSafe = !this.cbSafe;\n cb.setAttribute('aria-pressed', String(this.cbSafe));\n this.controller.setColorblindSafe(this.cbSafe);\n // Persist under the SAME key the public page uses (cross-surface preference).\n writeStoredColorblind(this.cbSafe);\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 // F3 minimap (venue overview + viewport rect) and F4 price-band filter.\n // Same post-render append (the map host was wiped by controller.render()).\n this.buildMinimap();\n this.buildPriceFilter();\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 this.buildSoldoutOverlay();\n\n // Dock layout-dependent chrome (a11y chips + colorblind toggle) for the\n // CURRENT layout — the initial applyLayout ran before these were built.\n this.dockLayoutChrome();\n\n await this.restoreRememberedHold();\n if (this.destroyed) return this;\n\n // Reflect the read-only load state (pill + disabled CTA/controls) with no\n // toast — a fresh mount into a closed event is not a live \"just closed\" event.\n if (this.salesClosed) this.applySalesClosed();\n this.syncPrices();\n this.syncTray();\n return this;\n }\n\n /**\n * Move layout-dependent chrome between its wide dock (map regions / zoom\n * column) and its narrow dock (the sheet's consolidated Filters row), and\n * re-render the section card in the form the layout wants (docked card/pill\n * on wide, sheet strip on narrow). Runs on every layout flip + once post-render.\n */\n private dockLayoutChrome(): void {\n const narrow = this.root?.dataset.layout === 'narrow';\n const filters = this.els.filters;\n if (filters) {\n if (narrow) {\n if (this.a11yChipsEl) filters.appendChild(this.a11yChipsEl);\n if (this.cbEl) filters.appendChild(this.cbEl);\n } else {\n if (this.a11yChipsEl) this.regions['top-left']?.appendChild(this.a11yChipsEl);\n if (this.cbEl) this.els.zoom?.appendChild(this.cbEl);\n }\n const has = narrow && filters.children.length > 0;\n filters.classList.toggle('has', has);\n this.els.filtersSec?.classList.toggle('has', has);\n }\n if (this.lastSection) this.renderSectionCard(this.lastSection);\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.regions['bottom-center'] ?? 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 /**\n * Localized string with a literal fallback. `t()` returns the key itself for\n * unknown keys, so this collapses that to `fallback` — while still honoring a\n * host `messages` override (which makes `t()` return the override, not the key).\n */\n private tf(key: string, fallback: string): string {\n const v = t(key);\n return v === key ? fallback : v;\n }\n\n /** Sold-out overlay — centered over the map, disabled waitlist stub (Gap 2). */\n private buildSoldoutOverlay(): void {\n if (!this.els.map) return;\n const el = document.createElement('div');\n el.className = 'sl-soldout';\n el.setAttribute('role', 'status');\n const name = (this.controller.doc?.theme?.brandName ?? this.opts.theme?.brandName ?? this.els.name?.textContent ?? this.tf('picker.soldOutEyebrow', 'This event')).toUpperCase();\n el.innerHTML =\n `<div class=\"sl-soldout-eyebrow\">${name}</div>` +\n `<div class=\"sl-soldout-title\">${this.tf('picker.soldOutTitle', 'Sold out')}</div>` +\n `<p class=\"sl-soldout-copy\">${this.tf('picker.soldOutCopy', \"Every seat is gone. Join the waitlist and we’ll email you if seats are released.\")}</p>` +\n `<button type=\"button\" class=\"sl-soldout-btn\" disabled>${this.tf('picker.waitlist', 'Join waitlist')}</button>`;\n this.els.map.appendChild(el);\n this.soldoutEl = el;\n }\n\n /**\n * Recompute the sold-out state on every price/availability sync. Sold-out ⇔\n * every SEATED category's live free count is 0. Suppressed when the chart has\n * GA areas (GA capacity isn't per-seat, so seated counts would read 0 and\n * falsely block standing room) — mirrors the public page. Clears live when WS\n * frees a seat up.\n */\n private syncSoldout(categories: Array<{ key: string }>, left: Record<string, number>): void {\n const hasGA = this.controller.getGAAreas().length > 0;\n const soldOut = this.isSoldOut(categories, left, hasGA);\n if (soldOut === this.soldOut) return;\n this.soldOut = soldOut;\n this.soldoutEl?.classList.toggle('on', soldOut);\n }\n\n /**\n * Pure sold-out predicate: every SEATED category's free count is 0, there is at\n * least one seated category, and there are no GA areas (GA capacity isn't\n * per-seat, so seated counts read 0 and would falsely block standing room).\n * `left` is seeded implicitly — a missing key means a fully-booked tier (0 free).\n */\n private isSoldOut(categories: Array<{ key: string }>, left: Record<string, number>, hasGA: boolean): boolean {\n return !hasGA && categories.length > 0 && categories.every((c) => (left[c.key] ?? 0) === 0);\n }\n\n /**\n * Sales-closed read-only state (Gap 3): persistent header pill, disabled CTA\n * with a closed label, and frozen best-available / GA controls. `setSalesClosed`\n * is the reactive entry (live 409 event_closed); `applySalesClosed` is the\n * idempotent DOM apply used at load and on transition.\n */\n private setSalesClosed(closed: boolean): void {\n if (this.salesClosed === closed) return;\n this.salesClosed = closed;\n this.applySalesClosed();\n }\n\n private applySalesClosed(): void {\n const pill = this.els.closedPill;\n if (pill) {\n pill.classList.toggle('on', this.salesClosed);\n const text = this.els.closedPillText ?? pill;\n text.textContent = this.tf('picker.salesClosedPill', 'Sales are closed');\n }\n this.root?.setAttribute('data-sales-closed', String(this.salesClosed));\n this.syncCta();\n this.syncTray();\n }\n\n /** The badge is hidden when the host opts out OR the org's theme sets hideBadge. */\n private badgeHidden(chartTheme?: ChartTheme): boolean {\n return !!(this.opts.hideBadge || chartTheme?.hideBadge);\n }\n\n /** Attribution badge in the side-panel foot (Gap 7). Hidden per host/theme. */\n private buildBadge(chartTheme: ChartTheme | undefined): void {\n if (this.badgeHidden(chartTheme)) return;\n const foot = this.els.foot;\n if (!foot) return;\n const el = document.createElement('div');\n el.className = 'sl-powered';\n el.innerHTML =\n `<span class=\"sl-powered-mark\" aria-hidden=\"true\">` +\n `<svg viewBox=\"0 0 24 24\"><path d=\"M4 15c0-1.1.9-2 2-2h12a2 2 0 0 1 2 2v3h-3v-2H7v2H4v-3Z\"/><rect x=\"7\" y=\"7\" width=\"10\" height=\"5\" rx=\"1.6\"/></svg>` +\n `</span><span>${this.tf('picker.poweredBy', 'Powered by SeatLayer')}</span>`;\n foot.appendChild(el);\n }\n\n // ---- Feature 6: chrome anchor regions -------------------------------------\n\n /**\n * Create the positioned flex containers that own every persistent map overlay.\n * Appended once after controller.render(); each chrome piece is then appended\n * INTO its region and flows within it, so nothing free-floats over anything\n * else. Regions carve the map into non-overlapping zones (top strip split into\n * left/center/right, left rail, and the three used corners).\n */\n private buildRegions(): void {\n if (!this.els.map) return;\n const REGIONS = ['top-left', 'top-center', 'top-right', 'left-rail', 'bottom-left', 'bottom-center', 'bottom-right'];\n for (const region of REGIONS) {\n const el = document.createElement('div');\n el.className = 'sl-anchor';\n el.dataset.region = region;\n this.els.map.appendChild(el);\n this.regions[region] = el;\n }\n }\n\n // ---- F3 minimap -----------------------------------------------------------\n\n /** Read a resolved --sl-* token value (canvas needs a real color, not var()). */\n private cssVar(name: string): string {\n return this.root ? getComputedStyle(this.root).getPropertyValue(name).trim() : '';\n }\n\n /** Motion is progressive enhancement; all state remains legible when reduced. */\n private reducedMotion(): boolean {\n return typeof window !== 'undefined' &&\n typeof window.matchMedia === 'function' &&\n window.matchMedia('(prefers-reduced-motion: reduce)').matches;\n }\n\n private scheduleMotion(fn: () => void, delay: number): void {\n const timer = setTimeout(() => {\n this.motionTimers.delete(timer);\n if (!this.destroyed) fn();\n }, delay);\n this.motionTimers.add(timer);\n }\n\n /** Restart one finite CSS animation without leaving a permanent state class. */\n private animateOnce(el: HTMLElement | undefined, className: string, duration = 600): void {\n if (!el || this.reducedMotion()) return;\n el.classList.remove(className);\n void el.offsetWidth;\n el.classList.add(className);\n this.scheduleMotion(() => el.classList.remove(className), duration);\n }\n\n /** Selection feedback belongs on the selected seat, not across the whole map. */\n private flashPickedSeat(id: string): void {\n if (this.reducedMotion()) return;\n this.controller.flashSeat(id, this.cssVar('--sl-accent') || '#f4b740');\n }\n\n /** A completed hold gets one short map ripple per concrete seat. */\n private flashHeldSeats(hold: HoldResult): void {\n if (this.reducedMotion()) return;\n const labels = (hold.items ?? []).filter((item) => item.objectType !== 'ga').map((item) => item.label);\n labels.slice(0, 10).forEach((label, index) => {\n const seat = this.controller.seatByLabel(label);\n if (!seat) return;\n this.scheduleMotion(\n () => this.controller.flashSeat(seat.id, this.cssVar('--sl-accent') || '#f4b740'),\n index * 55,\n );\n });\n }\n\n /** Update only the action affordance; selection callbacks must not refire. */\n private committedSelection(): PickerSeat[] {\n const candidateId = this.confirmSeat?.id;\n return this.controller.getSelection().filter((seat) => seat.id !== candidateId);\n }\n\n private pendingSelectionCount(): number {\n const heldItems = this.hold?.items ?? [];\n const heldLabels = new Set(heldItems.map((item) => item.label));\n const pendingSeats = this.committedSelection().filter((seat) => !heldLabels.has(seat.label)).length;\n return pendingSeats + this.pendingGACount();\n }\n\n private heldGACounts(): Map<string, number> {\n const heldGA = new Map<string, number>();\n for (const item of (this.hold?.items ?? []).filter((candidate) => candidate.objectType === 'ga')) {\n heldGA.set(item.objectId, (heldGA.get(item.objectId) ?? 0) + (item.quantity ?? 1));\n }\n return heldGA;\n }\n\n private pendingGACount(): number {\n const heldGA = this.heldGACounts();\n return [...this.gaQty.entries()].reduce(\n (sum, [areaId, qty]) => sum + Math.max(0, qty - (heldGA.get(areaId) ?? 0)),\n 0,\n );\n }\n\n private heldTicketCount(): number {\n return (this.hold?.items ?? []).reduce((sum, item) => sum + (item.quantity ?? 1), 0);\n }\n\n private totalTicketCount(): number {\n const heldLabels = new Set((this.hold?.items ?? []).map((item) => item.label));\n const freshSeats = this.committedSelection().filter((seat) => !heldLabels.has(seat.label)).length;\n return this.heldTicketCount() + freshSeats + this.pendingGACount();\n }\n\n /** Held tickets and standing quantities consume the same order-wide cap. */\n private updateSelectionCapacity(): void {\n const heldLabels = new Set((this.hold?.items ?? []).map((item) => item.label));\n const selectedHeld = this.committedSelection().filter((seat) => heldLabels.has(seat.label)).length;\n const remaining = Math.max(0, this.maxTickets - this.heldTicketCount() - this.pendingGACount());\n this.controller.setMaxSelection(selectedHeld + remaining);\n }\n\n private canAddTicket(): boolean {\n if (this.totalTicketCount() < this.maxTickets) return true;\n this.toast(`You can select up to ${this.maxTickets} tickets for this order.`, 'warning');\n return false;\n }\n\n private pendingGATotal(gaAreas: ReturnType<PickerController['getGAAreas']>): number {\n const heldGA = new Map<string, number>();\n for (const item of (this.hold?.items ?? []).filter((candidate) => candidate.objectType === 'ga')) {\n heldGA.set(item.objectId, (heldGA.get(item.objectId) ?? 0) + (item.quantity ?? 1));\n }\n return gaAreas.reduce(\n (sum, area) => sum + this.paidPrice(area.categoryKey, null, area.price) * Math.max(0, (this.gaQty.get(area.id) ?? 0) - (heldGA.get(area.id) ?? 0)),\n 0,\n );\n }\n\n private syncCta(count = this.lastTrayCount, pending = this.pendingSelectionCount()): void {\n const cta = this.els.cta as HTMLButtonElement | undefined;\n if (!cta) return;\n if (this.salesClosed) {\n cta.disabled = true;\n cta.textContent = this.tf('picker.salesClosedCta', 'Sales closed');\n return;\n }\n if (this.confirmSeat) {\n cta.disabled = true;\n cta.textContent = 'Confirm or cancel this seat';\n return;\n }\n if (this.ctaPhase === 'holding') {\n cta.disabled = true;\n cta.innerHTML = '<span class=\"sl-cta-spin\" aria-hidden=\"true\"></span>Securing seats…';\n return;\n }\n if (this.ctaPhase === 'checkout') {\n cta.disabled = true;\n cta.innerHTML = '<span class=\"sl-cta-spin\" aria-hidden=\"true\"></span>Opening checkout…';\n return;\n }\n cta.disabled = count === 0;\n cta.textContent = this.hold\n ? pending\n ? `Secure ${pending} more & checkout`\n : 'Continue to checkout'\n : count\n ? 'Hold seats & checkout'\n : 'Select seats';\n }\n\n private setCtaPhase(phase: 'idle' | 'holding' | 'checkout'): void {\n this.ctaPhase = phase;\n this.syncCta();\n if (phase === 'checkout') {\n this.scheduleMotion(() => {\n if (this.ctaPhase !== 'checkout') return;\n this.ctaPhase = 'idle';\n this.syncCta();\n }, 1100);\n }\n }\n\n /** Session-scoped capability key: isolated by API origin and event. */\n private holdStorageKey(): string {\n return `@seatlayer/hold/v1/${encodeURIComponent(this.apiBase)}/${encodeURIComponent(this.opts.event)}`;\n }\n\n private rememberedHoldId(): string | null {\n if (this.opts.initialHoldId) return this.opts.initialHoldId;\n if (this.opts.restoreHold === false || typeof window === 'undefined') return null;\n try {\n return window.sessionStorage.getItem(this.holdStorageKey());\n } catch {\n return null;\n }\n }\n\n private rememberHold(hold: HoldResult): void {\n if (this.opts.restoreHold === false || typeof window === 'undefined') return;\n try {\n // Persist only the opaque capability. Labels, prices and expiry are\n // always reloaded from the authoritative server projection.\n window.sessionStorage.setItem(this.holdStorageKey(), hold.holdId);\n } catch {\n // Storage can be unavailable in privacy/sandboxed embeds; the live picker\n // remains fully functional for the current mount.\n }\n }\n\n private forgetHold(): void {\n if (typeof window === 'undefined') return;\n try {\n window.sessionStorage.removeItem(this.holdStorageKey());\n } catch {\n // Best-effort cleanup only.\n }\n }\n\n private async resumeHoldFromServer(holdId: string, automatic: boolean): Promise<HoldResult | null> {\n try {\n const h = await this.controller.resumeHold(holdId);\n if (!h) return null;\n const restored: HoldResult = {\n holdId: h.holdId,\n expiresAt: h.expiresAt,\n seats: h.seats,\n items: h.items,\n };\n this.hold = restored;\n // A resumed capability came from an earlier checkout handoff. Keep it\n // alive if this picker mount is refreshed or torn down before the buyer\n // explicitly removes/releases it.\n this.handedOff = true;\n this.bookedShown = false;\n this.ctaPhase = 'idle';\n this.startHoldTimer(restored.expiresAt);\n this.rememberHold(restored);\n this.syncTray();\n this.emitHoldChange();\n this.opts.onHoldRestored?.(restored, restored.seats ?? [], this.buildHandoff(restored));\n if (automatic) this.toast('Your held tickets have been restored.', 'success');\n return restored;\n } catch (error) {\n const status = (error as { status?: number })?.status;\n if (status === 404 || status === 409) {\n // A stale/foreign/settled capability is expected recovery state, not a\n // picker failure. Drop it and let the buyer choose again.\n this.forgetHold();\n } else {\n this.opts.onError?.(error);\n }\n return null;\n }\n }\n\n private async restoreRememberedHold(): Promise<void> {\n const holdId = this.rememberedHoldId();\n if (holdId) await this.resumeHoldFromServer(holdId, true);\n }\n\n /** Section-bearing objects on the active floor (single-floor → doc.objects). */\n private activeFloorObjects(): SectionLike[] {\n const doc = this.controller.doc;\n if (!doc) return [];\n const floors = doc.floors;\n if (floors?.length) {\n const id = this.controller.getActiveFloorId();\n return ((floors.find((f) => f.id === id) ?? floors[0]).objects as unknown as SectionLike[]) ?? [];\n }\n return (doc.objects as unknown as SectionLike[]) ?? [];\n }\n\n /**\n * Build the overview minimap: a static venue thumbnail (section outlines, or\n * seat dots when the chart has no sections) with the live viewport rectangle\n * drawn on top. The rect tracks pan/zoom via the constructor's onViewChange.\n */\n private buildMinimap(): void {\n const vp = this.controller.getViewport();\n if (!vp || !this.els.map) return;\n const b = vp.bounds;\n if (!(b.width > 0 && b.height > 0)) return;\n\n const MAXW = 158;\n const MAXH = 118;\n const PAD = 6;\n const aspect = b.width / Math.max(1, b.height);\n let w = MAXW;\n let h = Math.round(MAXW / aspect);\n if (h > MAXH) {\n h = MAXH;\n w = Math.round(MAXH * aspect);\n }\n w = Math.max(64, w);\n h = Math.max(48, h);\n const dpr = Math.min(2, window.devicePixelRatio || 1);\n\n const wrap = document.createElement('div');\n wrap.className = 'sl-minimap';\n wrap.setAttribute('aria-hidden', 'true'); // decorative; the map itself is the keyboard surface\n const canvas = document.createElement('canvas');\n canvas.width = Math.round(w * dpr);\n canvas.height = Math.round(h * dpr);\n canvas.style.width = `${w}px`;\n canvas.style.height = `${h}px`;\n wrap.appendChild(canvas);\n (this.regions['bottom-left'] ?? this.els.map).appendChild(wrap);\n this.miniCanvas = canvas;\n\n // world → minimap (device px), contain + centre — matches thumb.ts.\n const scale = Math.min((w - PAD * 2) / Math.max(1, b.width), (h - PAD * 2) / Math.max(1, b.height)) * dpr;\n const offX = (w * dpr - b.width * scale) / 2 - b.x * scale;\n const offY = (h * dpr - b.height * scale) / 2 - b.y * scale;\n this.miniTf = { scale, offX, offY, dpr };\n\n const base = document.createElement('canvas');\n base.width = canvas.width;\n base.height = canvas.height;\n this.miniBase = base;\n\n // Click a section on the minimap → glide the camera into it (existing API).\n wrap.addEventListener('click', (e) => this.minimapJump(e));\n\n this.drawMinimapStatic();\n this.drawMinimapRect();\n }\n\n /** Repaint the static overview + rect (floor switch, live open/close). */\n private refreshMinimap(): void {\n if (!this.miniBase) return;\n this.drawMinimapStatic();\n this.drawMinimapRect();\n }\n\n /** Paint the venue overview into the offscreen base canvas. */\n private drawMinimapStatic(): void {\n const base = this.miniBase;\n const tf = this.miniTf;\n const doc = this.controller.doc;\n if (!base || !tf || !doc) return;\n const ctx = base.getContext('2d');\n if (!ctx) return;\n ctx.clearRect(0, 0, base.width, base.height);\n const fx = (x: number): number => x * tf.scale + tf.offX;\n const fy = (y: number): number => y * tf.scale + tf.offY;\n const line = this.cssVar('--sl-line') || 'rgba(139,147,167,.5)';\n const muted = this.cssVar('--sl-muted') || '#8b93a7';\n const accent = this.cssVar('--sl-accent') || '#6e7bff';\n const zoneColor = new Map((doc.zones ?? []).map((z) => [z.id, z.color] as const));\n\n let drewSection = false;\n for (const o of this.activeFloorObjects()) {\n if (o.type !== 'section' || !o.outline || o.outline.length < 3) continue;\n drewSection = true;\n const closed = this.controller.isSectionClosed(o.id);\n const fill = closed ? muted : o.color ?? (o.zone && zoneColor.get(o.zone)) ?? accent;\n ctx.beginPath();\n o.outline.forEach((p, i) => (i === 0 ? ctx.moveTo(fx(p.x), fy(p.y)) : ctx.lineTo(fx(p.x), fy(p.y))));\n ctx.closePath();\n ctx.globalAlpha = closed ? 0.26 : 0.42;\n ctx.fillStyle = fill;\n ctx.fill();\n ctx.globalAlpha = 0.85;\n ctx.lineWidth = Math.max(1, tf.dpr);\n ctx.strokeStyle = line;\n ctx.stroke();\n }\n ctx.globalAlpha = 1;\n\n // Section-less charts: fall back to faint category-colored seat dots.\n if (!drewSection) {\n const r = Math.max(1, tf.dpr);\n for (const seat of expandChart(doc)) {\n const cat = doc.categories.find((c) => c.key === seat.categoryKey);\n ctx.fillStyle = cat?.color ?? accent;\n ctx.beginPath();\n ctx.arc(fx(seat.x), fy(seat.y), r, 0, Math.PI * 2);\n ctx.fill();\n }\n }\n }\n\n /** Blit the base overview, then stroke the current viewport rectangle on top. */\n private drawMinimapRect(): void {\n const canvas = this.miniCanvas;\n const base = this.miniBase;\n const tf = this.miniTf;\n if (!canvas || !base || !tf) return;\n const ctx = canvas.getContext('2d');\n if (!ctx) return;\n ctx.clearRect(0, 0, canvas.width, canvas.height);\n ctx.drawImage(base, 0, 0);\n const vp = this.controller.getViewport();\n if (!vp) return;\n const v = vp.visible;\n const x = v.x * tf.scale + tf.offX;\n const y = v.y * tf.scale + tf.offY;\n const w = v.width * tf.scale;\n const h = v.height * tf.scale;\n const accent = this.cssVar('--sl-accent') || '#f4b740';\n ctx.save();\n ctx.globalAlpha = 0.14;\n ctx.fillStyle = accent;\n ctx.fillRect(x, y, w, h);\n ctx.globalAlpha = 1;\n ctx.lineWidth = Math.max(1.5, tf.dpr * 1.5);\n ctx.strokeStyle = accent;\n ctx.strokeRect(x, y, w, h);\n ctx.restore();\n }\n\n /** Minimap click → focus the section under the point (or overview on a miss). */\n private minimapJump(e: MouseEvent): void {\n const canvas = this.miniCanvas;\n const tf = this.miniTf;\n if (!canvas || !tf) return;\n const r = canvas.getBoundingClientRect();\n const px = (e.clientX - r.left) * (canvas.width / r.width);\n const py = (e.clientY - r.top) * (canvas.height / r.height);\n const wx = (px - tf.offX) / tf.scale;\n const wy = (py - tf.offY) / tf.scale;\n for (const o of this.activeFloorObjects()) {\n if (o.type !== 'section' || !o.outline || o.outline.length < 3) continue;\n if (this.controller.isSectionClosed(o.id)) continue;\n if (pointInPolygon(wx, wy, o.outline)) {\n this.controller.focusSection(o.id);\n return;\n }\n }\n this.controller.overview();\n }\n\n // ---- F4 price-band filter -------------------------------------------------\n\n /** Effective display price of a category: host pricing override → first tier → base. */\n private catPrice(c: { key?: string; price?: number; tiers?: { id?: string; price: number }[] }): number | undefined {\n const chart = c.tiers?.length ? c.tiers[0].price : c.price;\n if (chart === undefined || !c.key) return chart;\n return this.paidPrice(c.key, c.tiers?.[0]?.id ?? null, chart);\n }\n\n /** Derive price bands: one chip per distinct price (≤5), else quantile ranges. */\n private priceBands(): PriceBand[] {\n const doc = this.controller.doc;\n if (!doc) return [];\n const priced = doc.categories\n .map((c) => ({ key: c.key, price: this.catPrice(c) }))\n .filter((x): x is { key: string; price: number } => x.price != null);\n if (!priced.length) return [];\n const distinct = [...new Set(priced.map((p) => p.price))].sort((a, b) => a - b);\n if (distinct.length <= 5) {\n return distinct.map((price) => ({\n id: `p${price}`,\n label: this.money(price),\n keys: priced.filter((p) => p.price === price).map((p) => p.key),\n min: price,\n max: price,\n }));\n }\n // Many distinct prices → ~4 contiguous quantile bands (ranges).\n const chunk = Math.ceil(distinct.length / 4);\n const bands: PriceBand[] = [];\n for (let i = 0; i < distinct.length; i += chunk) {\n const slice = distinct.slice(i, i + chunk);\n const lo = slice[0];\n const hi = slice[slice.length - 1];\n bands.push({\n id: `b${i}`,\n label: lo === hi ? this.money(lo) : `${this.money(lo)}–${this.money(hi)}`,\n keys: priced.filter((p) => p.price >= lo && p.price <= hi).map((p) => p.key),\n min: lo,\n max: hi,\n });\n }\n return bands;\n }\n\n /** Build the compact price selector in the panel header. Choosing a band both\n * filters availability and smoothly frames the matching seats on the map. */\n private buildPriceFilter(): void {\n if (!this.els.prices || !this.els.pricesSec) return;\n const bands = this.priceBands();\n if (bands.length < 2) return;\n const select = document.createElement('select');\n select.className = 'sl-price-select';\n select.setAttribute('aria-label', 'Filter and focus seats by price');\n select.innerHTML = `<option value=\"all\">All prices</option>` + bands\n .map((band) => `<option value=\"${band.id}\">${band.label}</option>`)\n .join('');\n this.els.pricesSec.appendChild(select);\n select.addEventListener('change', () => {\n const band = bands.find((candidate) => candidate.id === select.value);\n const keys = band?.keys ?? null;\n this.focusedCatKey = null; // band filter supersedes any pinned row focus\n this.priceBandKeys = keys ? new Set(keys) : null;\n this.controller.setCategoryFilter(keys);\n this.controller.focusCategoryFilter(keys);\n // A band whose seats live on another deck switches floors — mirror it.\n this.syncFloors();\n this.syncRung();\n this.refreshMinimap();\n // Reflect the band in the legend rows + any open section card.\n this.syncPrices();\n if (this.lastSection) this.showSectionCard(this.lastSection);\n });\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', () => {\n const rung = btn.dataset.rung as LodRung;\n this.controller.setRung(rung);\n if (rung === 'seats') this.collapseSectionCard();\n });\n });\n this.regions['top-center'].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 this.refreshMinimap();\n });\n });\n this.regions['left-rail'].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 this.lastSection = summary;\n this.secCardEl?.remove();\n this.secCardEl = null;\n if (!summary) return;\n // At seat level the summary is context, not a blocking decision surface.\n // Keep it as the compact pill from the first seat-level paint.\n this.secCardCollapsed = this.controller.getRung() === 'seats';\n this.secCardShownAt = Date.now();\n this.renderSectionCard(summary);\n }\n\n /**\n * Render the section card in the form the layout + state want: expanded card\n * or slim pill in the top-center anchor region (wide), or a compact strip in\n * the sheet head (narrow). Never floats over the seats at the tap point.\n */\n private renderSectionCard(summary: SectionSummary): void {\n if (!this.els.map) return;\n this.secCardEl?.remove();\n // min/max over the section's categories at the price the buyer will PAY\n // (host pricing override aware) — not the chart's stored range.\n const paid = summary.categories.length\n ? summary.categories.map((c) => this.paidPrice(c.key, null, c.price))\n : [summary.priceMin, summary.priceMax];\n const paidMin = Math.min(...paid);\n const paidMax = Math.max(...paid);\n const priceLabel =\n paidMin === paidMax\n ? this.money(paidMin)\n : `${this.money(paidMin)}–${this.money(paidMax)}`;\n const leftLabel = tCount('picker.seatsLeftInSection', summary.seatsLeft);\n const xBtn = `<button type=\"button\" class=\"sl-seccard-x\" aria-label=\"${t('picker.closeSectionSummary')}\">✕</button>`;\n const card = document.createElement('div');\n const narrow = this.root?.dataset.layout === 'narrow';\n\n if (narrow) {\n // Compact strip inside the bottom sheet's peek head — never over the map.\n card.className = 'sl-seccard strip on';\n card.setAttribute('role', 'status');\n card.setAttribute('aria-label', t('picker.sectionSummaryAria', { label: summary.label }));\n card.innerHTML =\n `<span class=\"sl-seccard-dot\" style=\"background:${summary.color}\"></span>` +\n `<span class=\"sl-seccard-name\">${summary.label}</span>` +\n `<span class=\"sl-seccard-left\">${leftLabel}</span>` +\n (summary.categories.length ? `<span class=\"sl-seccard-price\">${priceLabel}</span>` : '') +\n xBtn;\n card.querySelector('.sl-seccard-x')!.addEventListener('click', () => this.controller.overview());\n (this.els.sheetHead ?? this.els.side ?? this.els.map).appendChild(card);\n } else if (this.secCardCollapsed) {\n // Slim pill — seat-picking has begun. Tap to re-expand; ✕ still closes.\n card.className = 'sl-seccard mini on';\n card.setAttribute('role', 'button');\n card.setAttribute('aria-label', t('picker.sectionSummaryAria', { label: summary.label }));\n card.innerHTML =\n `<span class=\"sl-seccard-dot\" style=\"background:${summary.color}\"></span>` +\n `<span class=\"sl-seccard-name\">${summary.label}</span>` +\n `<span class=\"sl-seccard-left\">${leftLabel}</span>` +\n xBtn;\n card.addEventListener('click', (e) => {\n if ((e.target as HTMLElement).closest('.sl-seccard-x')) return;\n this.secCardCollapsed = false;\n this.secCardShownAt = Date.now();\n this.renderSectionCard(summary);\n });\n card.querySelector('.sl-seccard-x')!.addEventListener('click', () => this.controller.overview());\n (this.regions['top-center'] ?? this.els.map).appendChild(card);\n } else {\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((c) => {\n const dim = this.priceBandKeys != null && !this.priceBandKeys.has(c.key);\n return (\n `<span class=\"sl-seccard-mix-item${dim ? ' sl-dim' : ''}\"><span class=\"sl-seccard-mix-dot\" style=\"background:${c.color}\"></span>` +\n `${c.label} <span class=\"sl-seccard-mix-price\">${this.money(this.paidPrice(c.key, null, c.price))}</span></span>`\n );\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 xBtn + `</div>` +\n `<div class=\"sl-seccard-zone\">${summary.zoneLabel ? `${summary.zoneLabel} · ` : ''}` +\n `<span class=\"sl-seccard-left\">${leftLabel}</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.regions['top-center'] ?? this.els.map).appendChild(card);\n }\n this.secCardEl = card;\n }\n\n /** Collapse the expanded card to its slim pill (seat-picking started). */\n private collapseSectionCard(): void {\n if (!this.secCardEl || this.secCardCollapsed || !this.lastSection) return;\n if (this.root?.dataset.layout === 'narrow') return; // strip is already compact\n this.secCardCollapsed = true;\n this.renderSectionCard(this.lastSection);\n }\n\n /**\n * onViewChange hook for the card. The focus glide's own settle (within the\n * grace window) enforces the ~25% coverage rule with the FINAL viewport; any\n * later pan/zoom means seat-picking has begun → collapse to the pill.\n */\n private sectionCardOnView(): void {\n if (!this.secCardEl || this.secCardCollapsed || !this.lastSection) return;\n if (this.root?.dataset.layout === 'narrow') return;\n if (this.controller.getRung() === 'seats') {\n this.collapseSectionCard();\n return;\n }\n if (Date.now() - this.secCardShownAt < 1400) {\n if (this.sectionCardCoverage() > 0.25) this.collapseSectionCard();\n return;\n }\n this.collapseSectionCard();\n }\n\n /** Fraction of the focused section's on-screen bbox covered by the card. */\n private sectionCardCoverage(): number {\n const card = this.secCardEl;\n const sec = this.lastSection;\n if (!card || !sec || !this.els.map) return 0;\n const outline = this.activeFloorObjects().find((o) => o.type === 'section' && o.id === sec.id)?.outline;\n if (!outline || outline.length < 3) return 0;\n const pts = outline.map((p) => this.controller.worldToScreen(p));\n const xs = pts.map((p) => p.x);\n const ys = pts.map((p) => p.y);\n const bx = Math.min(...xs);\n const by = Math.min(...ys);\n const bw = Math.max(...xs) - bx;\n const bh = Math.max(...ys) - by;\n if (bw <= 0 || bh <= 0) return 0;\n const mapR = this.els.map.getBoundingClientRect();\n const cr = card.getBoundingClientRect();\n const cx = cr.left - mapR.left;\n const cy = cr.top - mapR.top;\n const ox = Math.max(0, Math.min(cx + cr.width, bx + bw) - Math.max(cx, bx));\n const oy = Math.max(0, Math.min(cy + cr.height, by + bh) - Math.max(cy, by));\n return (ox * oy) / (bw * bh);\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 ? this.catPrice(cat) : undefined;\n this.srEl.textContent = `Seat ${seat.label}, ${cat?.label ?? seat.categoryKey}${\n price != null ? `, ${this.money(price)}` : ''\n }, ${statusText}`;\n }\n\n // ---- seat candidate confirmation ------------------------------------------\n\n private showConfirm(seat: ExpandedSeat): void {\n const previousId = this.confirmSeat?.id;\n this.confirmEl?.remove();\n this.confirmEl = null;\n this.confirmSeat = seat;\n this.root?.setAttribute('data-confirming', 'true');\n this.controller.setSelectionFocus(seat.id);\n if (previousId && previousId !== seat.id) this.controller.deselect([previousId]);\n if (this.tipEl) this.tipEl.style.display = 'none';\n const details = this.controller.seatDetails(seat.id);\n const cat = this.controller.doc?.categories.find((c) => c.key === seat.categoryKey);\n const chartPrice = details?.price ?? (cat?.tiers?.length ? cat.tiers[0].price : cat?.price);\n const price = chartPrice != null\n ? this.paidPrice(seat.categoryKey, details?.tierId ?? cat?.tiers?.[0]?.id ?? null, chartPrice)\n : undefined;\n const safe = (value: unknown): string => String(value ?? '—').replace(/[&<>\"]/g, (char) => ({\n '&': '&', '<': '<', '>': '>', '\"': '"',\n })[char]!);\n const el = document.createElement('div');\n el.className = 'sl-confirm';\n el.setAttribute('role', 'dialog');\n el.setAttribute('aria-modal', 'true');\n el.setAttribute('aria-label', `Confirm seat ${seat.label}`);\n el.style.setProperty('--sl-cat', cat?.color ?? '#6e7bff');\n el.innerHTML =\n `<div class=\"sl-confirm-grid\">` +\n `<div class=\"sl-confirm-field\"><span class=\"sl-confirm-key\">Section</span><span class=\"sl-confirm-value\">${safe(details?.sectionLabel)}</span></div>` +\n `<div class=\"sl-confirm-field\"><span class=\"sl-confirm-key\">Row</span><span class=\"sl-confirm-value\">${safe(this.rowShort(details))}</span></div>` +\n `<div class=\"sl-confirm-field\"><span class=\"sl-confirm-key\">Seat</span><span class=\"sl-confirm-value\">${safe(details?.seatNumber ?? seat.label)}</span></div>` +\n `</div>` +\n `<div class=\"sl-confirm-cat\"><span class=\"sl-dot\" style=\"background:${cat?.color ?? '#6e7bff'}\"></span>` +\n `<span class=\"sl-confirm-cat-name\">${safe(details?.categoryLabel ?? cat?.label ?? seat.categoryKey)}</span>` +\n (price != null ? `<span class=\"sl-confirm-price\">${this.money(price)}</span>` : '') + `</div>` +\n `<div class=\"sl-confirm-body\">` +\n (this.seatViewEnabled() ? this.confirmThumbHtml(seat) : '') +\n `<div class=\"sl-confirm-row\">` +\n `<button type=\"button\" class=\"sl-confirm-cancel\">Cancel</button>` +\n `<button type=\"button\" class=\"sl-confirm-add\"><svg viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M5 12.5l4 4L19 7\"/></svg>Select</button></div></div>`;\n this.els.map.appendChild(el);\n this.confirmEl = el;\n this.reanchorConfirm();\n el.querySelector('.sl-confirm-view')?.addEventListener('click', () => this.openSeatView(seat));\n el.querySelector('.sl-confirm-add')!.addEventListener('click', () => this.commitConfirm());\n el.querySelector('.sl-confirm-cancel')!.addEventListener('click', () => this.cancelConfirm());\n requestAnimationFrame(() => el.querySelector<HTMLButtonElement>('.sl-confirm-add')?.focus());\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 if (this.root?.dataset.layout === 'narrow') return;\n const mapWidth = this.els.map.clientWidth;\n const mapHeight = this.els.map.clientHeight;\n const cardWidth = this.confirmEl.offsetWidth || 276;\n const cardHeight = this.confirmEl.offsetHeight || 230;\n const half = cardWidth / 2 + 12;\n const x = Math.max(half, Math.min(mapWidth - half, p.x));\n const belowFits = p.y + cardHeight + 24 <= mapHeight;\n const placeBelow = p.y < cardHeight + 24 && belowFits;\n this.confirmEl.dataset.placement = placeBelow ? 'below' : 'above';\n this.confirmEl.style.left = `${x}px`;\n this.confirmEl.style.top = `${Math.max(8, Math.min(mapHeight - 8, p.y))}px`;\n }\n\n private dismissConfirm(): void {\n this.confirmEl?.remove();\n this.confirmEl = null;\n this.confirmSeat = null;\n this.root?.removeAttribute('data-confirming');\n this.controller.setSelectionFocus(null);\n }\n\n private commitConfirm(): void {\n if (!this.confirmSeat) return;\n this.dismissConfirm();\n this.collapseSectionCard();\n this.syncTray();\n }\n\n private cancelConfirm(): void {\n const seat = this.confirmSeat;\n if (!seat) return;\n this.controller.deselect([seat.id]);\n if (this.confirmSeat) this.dismissConfirm();\n this.root?.focus({ preventScroll: true });\n }\n\n private closeConfirm(): void {\n this.dismissConfirm();\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\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 const formatter = this.opts.pricing?.formatter;\n if (formatter) return formatter(n, this.currency);\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 /**\n * The price the buyer will actually pay for a category (+tier): the host's\n * `pricing` override when present, else the chart's stored price. Every\n * price the widget DISPLAYS or hands off must flow through here — a map\n * that shows one price while checkout charges another destroys trust.\n */\n private paidPrice(categoryKey: string | undefined, tierId: string | null | undefined, fallback: number): number {\n const entry = categoryKey ? this.opts.pricing?.prices?.[categoryKey] : undefined;\n if (entry === undefined) return fallback;\n if (typeof entry === 'number') return entry;\n if (tierId && entry.tiers?.[tierId] !== undefined) return entry.tiers[tierId];\n return entry.base ?? fallback;\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.narrateAvailability(doc.categories, left);\n this.syncSoldout(doc.categories, left);\n // Big events ship 10–20 ticket types; an uncapped list shoves \"Your seats\"\n // and the CTA below the fold. Cap the closed list and expand on demand\n // (never hide a single row behind a toggle — that costs more than it saves).\n const PRICE_LIMIT = 5;\n const overflow = doc.categories.length - PRICE_LIMIT;\n const collapsed = overflow > 1 && !this.pricesExpanded;\n const shown = collapsed ? doc.categories.slice(0, PRICE_LIMIT) : doc.categories;\n this.els.prices.classList.toggle('sl-expanded', overflow > 1 && this.pricesExpanded);\n this.els.prices.innerHTML = shown\n .map((c) => {\n const price = this.catPrice(c);\n const active = this.focusedCatKey === c.key;\n const dim = this.priceBandKeys != null && !this.priceBandKeys.has(c.key);\n return (\n `<div class=\"sl-price-row${dim ? ' sl-dim' : ''}${active ? ' sl-active' : ''}\" data-cat=\"${c.key}\"` +\n ` role=\"button\" tabindex=\"0\" aria-pressed=\"${active}\"` +\n ` title=\"${active ? 'Show all seats' : `Show ${c.label} seats on the map`}\">` +\n `<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 (overflow > 1\n ? `<button type=\"button\" class=\"sl-price-more\" aria-expanded=\"${!collapsed}\">` +\n (collapsed ? `Show all ${doc.categories.length} ticket types` : 'Show fewer') +\n `</button>`\n : '') +\n `<div class=\"sl-status-key\" aria-label=\"Seat status legend\">` +\n `<span class=\"sl-status-item\"><i class=\"sl-status-icon\" aria-hidden=\"true\">` +\n `<svg viewBox=\"0 0 24 24\"><rect x=\"5\" y=\"10\" width=\"14\" height=\"10\" rx=\"2\"/><path d=\"M8 10V7a4 4 0 0 1 8 0v3\"/></svg>` +\n `</i>Temporarily held</span>` +\n `<span class=\"sl-status-item\"><i class=\"sl-status-icon sold\" aria-hidden=\"true\">` +\n `<svg viewBox=\"0 0 24 24\"><path d=\"M7 17L17 7\"/></svg>` +\n `</i>Sold</span>` +\n `</div>`;\n // Legend-hover highlight: dim other categories on the map while hovering a row.\n // Click (or Enter/Space) pins that focus — filter + frame the category on\n // the map; a second click clears it.\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 const toggle = () => this.focusCategory(row.dataset.cat ?? '');\n row.addEventListener('click', toggle);\n row.addEventListener('keydown', (e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n toggle();\n }\n });\n });\n this.els.prices.querySelector<HTMLButtonElement>('.sl-price-more')?.addEventListener('click', () => {\n this.pricesExpanded = !this.pricesExpanded;\n this.syncPrices();\n });\n }\n\n /** Tap a price row → filter + frame that category on the map; tap again to\n * clear. Shares `priceBandKeys` with the band selector so the row-dim state\n * has one source of truth (and each control resets the other). */\n private focusCategory(key: string): void {\n if (!key) return;\n const next = this.focusedCatKey === key ? null : key;\n this.focusedCatKey = next;\n this.priceBandKeys = next ? new Set([next]) : null;\n const select = this.els.pricesSec?.querySelector<HTMLSelectElement>('.sl-price-select');\n if (select) select.value = 'all';\n this.controller.setCategoryFilter(next ? [next] : null);\n this.controller.focusCategoryFilter(next ? [next] : null);\n // Focusing a category on another deck switches floors — mirror that onto\n // the floor pills / rung pills / minimap, same as a manual deck switch.\n this.syncFloors();\n this.syncRung();\n this.refreshMinimap();\n this.syncPrices();\n if (this.lastSection) this.showSectionCard(this.lastSection);\n }\n\n /**\n * Live-activity strip: turn WS availability deltas into one quiet line of\n * social proof (\"2 seats just taken in VIP · 118 left\"). Diffs per-category\n * counts on every status change — no per-seat payload needed. Skips the very\n * first computation (initial load is not \"activity\").\n */\n private narrateAvailability(\n categories: Array<{ key: string; label: string }>,\n left: Record<string, number>,\n ): void {\n const textEl = this.els.liveText;\n const prev = this.lastCatAvail;\n this.lastCatAvail = { ...left };\n // A floor switch re-baselines availability (counts are per-rendered-floor,\n // and the post-switch status snapshot lands asynchronously a beat later).\n // Narrating across that window produces a phantom \"N seats just taken\", so\n // stay quiet until the new floor settles — only genuine WS deltas after\n // that are news.\n const floorId = this.controller.getActiveFloorId();\n if (floorId !== this.lastAvailFloorId) {\n this.lastAvailFloorId = floorId;\n this.availQuietUntil = performance.now() + 2000;\n }\n if (!textEl || !prev || performance.now() < this.availQuietUntil) return;\n for (const cat of categories) {\n const before = prev[cat.key];\n const now = left[cat.key] ?? 0;\n if (before === undefined || now >= before) continue;\n const taken = before - now;\n textEl.textContent = `${taken} seat${taken === 1 ? '' : 's'} just taken in ${cat.label} · ${now} left`;\n // Surface the strip only while it carries news, then give the space back.\n this.els.live?.classList.remove('on');\n // Reflow between remove/add restarts the entrance animation on repeats.\n void (this.els.live as HTMLElement | undefined)?.offsetWidth;\n this.els.live?.classList.add('on');\n if (this.liveTimer) clearTimeout(this.liveTimer);\n this.liveTimer = setTimeout(() => this.els.live?.classList.remove('on'), 8000);\n return;\n }\n }\n private lastCatAvail: Record<string, number> | null = null;\n private lastAvailFloorId = '';\n private availQuietUntil = 0;\n private liveTimer: ReturnType<typeof setTimeout> | null = null;\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>([\n ...(this.controller.currentHold()?.labels ?? []),\n ...this.holdingLabels,\n ]);\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.`, 'error');\n }\n\n private syncTray(): void {\n if (!this.els.tray) return;\n this.updateSelectionCapacity();\n const seats = this.committedSelection();\n const gaAreas = this.controller.getGAAreas();\n const heldItems = this.hold?.items ?? [];\n const parts: string[] = [];\n const nextTrayKeys = new Set<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 // Best available is the fastest path for buyers who haven't picked yet —\n // but the moment a seat lands in the tray, the ticket cards own this space.\n // (Busy/confirm states stay visible so an in-flight search isn't cut off.)\n const noPicks = !seats.length && !heldItems.length && !this.pendingGACount();\n if (!this.hold && (noPicks || this.bestAvailableBusy || this.bestAvailableConfirm)) {\n const cats = this.controller.doc?.categories ?? [];\n parts.push(this.bestAvailableConfirm\n ? `<div class=\"sl-ba\" role=\"alert\">` +\n `<div class=\"sl-ba-title\"><span class=\"spark\" aria-hidden=\"true\">✦</span>Replace your current choices?</div>` +\n `<div class=\"sl-ba-replace\"><b>We’ll find ${this.baQty} seats together.</b>` +\n `<span>Your manually selected tickets will be removed only after a new group is secured.</span></div>` +\n `<div class=\"sl-ba-actions\"><button type=\"button\" data-ba-cancel>Keep mine</button>` +\n `<button type=\"button\" class=\"replace\" data-ba-replace>Find new seats</button></div></div>`\n : `<div class=\"sl-ba\">` +\n `<div class=\"sl-ba-title\"><span class=\"spark\" aria-hidden=\"true\">✦</span>Find the best seats together</div>` +\n `<div class=\"sl-ba-copy\"><span class=\"wide\">We’ll choose the closest available group for you.</span>` +\n `<span class=\"narrow\">Closest available group, chosen instantly.</span></div>` +\n (cats.length > 1\n ? `<select aria-label=\"Preferred ticket type\" data-ba-cat>` +\n `<option value=\"\">Any ticket type</option>` +\n cats.map((c) => `<option value=\"${c.key}\"${this.baCat === c.key ? ' selected' : ''}>${c.label}</option>`).join('') +\n `</select>`\n : `<span aria-hidden=\"true\"></span>`) +\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\"${this.bestAvailableBusy ? ' disabled' : ''}>` +\n (this.bestAvailableBusy\n ? `<span class=\"sl-ba-spin\" aria-hidden=\"true\"></span>Finding the best seats…`\n : `Find ${this.baQty} best ${this.baQty === 1 ? 'seat' : 'seats'}`) +\n `</button></div>`);\n }\n\n // Held line items (best-available, completed, or restored). Tier is\n // server-committed, but each item can be released without discarding the\n // rest of the hold.\n // Ticket-card identity grid: SECTION | ROW | SEAT, echoing the confirm\n // popover so the buyer meets the same identity pattern at confirm and in\n // the cart. Falls back to the raw label when spatial context is missing\n // (GA lines, legacy labels).\n const idGrid = (seatId: string | null, label: string): string => {\n const d = seatId ? this.controller.seatDetails(seatId) : null;\n if (!d?.sectionLabel && !d?.rowLabel && !d?.seatNumber) {\n return `<div class=\"sl-chip-id\"><span class=\"fld sec\"><span class=\"sl-chip-eb\">Seat</span><span class=\"val\">${label}</span></span></div>`;\n }\n return (\n `<div class=\"sl-chip-id\">` +\n `<span class=\"fld sec\"><span class=\"sl-chip-eb\">Section</span><span class=\"val\">${d.sectionLabel ?? '—'}</span></span>` +\n (d.rowLabel ? `<span class=\"fld mid\"><span class=\"sl-chip-eb\">Row</span><span class=\"val\">${this.rowShort(d)}</span></span>` : '') +\n (d.seatNumber ? `<span class=\"fld mid\"><span class=\"sl-chip-eb\">Seat</span><span class=\"val\">${d.seatNumber}</span></span>` : '') +\n `</div>`\n );\n };\n // Right icon rail per the canonical mock: remove on top, seat view below.\n const iconRail = (rmAria: string, viewLabel: string | null): string =>\n `<div class=\"sl-chip-rail\">` +\n `<button type=\"button\" class=\"rm\" aria-label=\"${rmAria}\">` +\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>` +\n (viewLabel\n ? `<button type=\"button\" class=\"view\" data-view-label=\"${viewLabel}\" aria-label=\"${t('picker.viewFromSeat', { label: viewLabel })}\">` +\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 for (const item of heldItems) {\n const itemKey = `held:${item.label}`;\n nextTrayKeys.add(itemKey);\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 heldSeat = item.objectType !== 'ga' ? this.controller.seatByLabel(item.label) : null;\n const canView = this.seatViewEnabled() && !!heldSeat;\n parts.push(\n `<div class=\"sl-chip sl-held${this.lastTrayKeys.has(itemKey) ? '' : ' sl-enter'}\" data-key=\"${itemKey}\" data-held=\"${encodeURIComponent(item.label)}\"${heldSeat ? ` data-locate=\"${heldSeat.id}\"` : ''}>` +\n `<div class=\"sl-chip-main\">` +\n idGrid(heldSeat?.id ?? null, item.label) +\n `<div class=\"sl-chip-sub\">` +\n `<span class=\"sl-ticket-state held\" aria-label=\"Held for you\" title=\"Held for you\">` +\n `<svg viewBox=\"0 0 24 24\"><rect x=\"5\" y=\"10\" width=\"14\" height=\"10\" rx=\"2\"/><path d=\"M8 10V7a4 4 0 0 1 8 0v3\"/></svg></span>` +\n `<span class=\"cat\">${cat?.label ?? item.categoryKey}${tierName ? ` · ${tierName}` : ''}</span>` +\n `<span class=\"amt\">${this.money(this.paidPrice(item.categoryKey, item.tierId, item.unitPrice) * (item.quantity ?? 1))}</span>` +\n `</div></div>` +\n iconRail(`Remove held ticket ${item.label}`, canView ? item.label : null) +\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 itemKey = `seat:${s.id}`;\n nextTrayKeys.add(itemKey);\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(this.paidPrice(s.categoryKey, ti.id, ti.price))}</option>`)\n .join('') +\n `</select>`\n : '';\n parts.push(\n `<div class=\"sl-chip${this.lastTrayKeys.has(itemKey) ? '' : ' sl-enter'}\" data-key=\"${itemKey}\" data-seat=\"${s.id}\" data-locate=\"${s.id}\">` +\n `<div class=\"sl-chip-main\">` +\n idGrid(s.id, s.label) +\n `<div class=\"sl-chip-sub\">` +\n `<span class=\"sl-ticket-state\" aria-label=\"Selected\" title=\"Selected\">` +\n `<svg viewBox=\"0 0 24 24\"><path d=\"M5 12l4 4L19 6\"/></svg></span>` +\n `<span class=\"cat\">${cat?.label ?? s.categoryKey}</span>${tierSelect}` +\n `<span class=\"amt\">${this.money(this.paidPrice(s.categoryKey, s.tierId ?? null, s.price))}</span>` +\n `</div></div>` +\n iconRail(`Remove ${s.label}`, canView ? s.label : null) +\n `</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(this.paidPrice(area.categoryKey, null, 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 this.els.tray.innerHTML = parts.join('');\n this.lastTrayKeys = nextTrayKeys;\n this.els.tray.querySelectorAll<HTMLButtonElement>('[data-ba]').forEach((btn) => {\n btn.addEventListener('click', () => {\n this.baQty = Math.max(1, Math.min(this.maxTickets, 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 if (this.pendingSelectionCount() > 0) {\n this.bestAvailableConfirm = true;\n this.syncTray();\n this.els.tray.querySelector<HTMLButtonElement>('[data-ba-replace]')?.focus();\n return;\n }\n void this.bestAvailable(this.baQty, this.baCat || undefined);\n });\n this.els.tray.querySelector<HTMLButtonElement>('[data-ba-cancel]')?.addEventListener('click', () => {\n this.bestAvailableConfirm = false;\n this.syncTray();\n this.els.tray.querySelector<HTMLButtonElement>('.sl-ba-go')?.focus();\n });\n this.els.tray.querySelector<HTMLButtonElement>('[data-ba-replace]')?.addEventListener('click', () => {\n this.bestAvailableConfirm = false;\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 chip = btn.closest('.sl-chip') as HTMLElement;\n if (chip.dataset.held) {\n void this.removeHeldLabel(decodeURIComponent(chip.dataset.held), chip);\n return;\n }\n const id = chip.dataset.seat!;\n const label = this.controller.getSelection().find((sel) => sel.id === id)?.label ?? 'Seat';\n const remove = (): void => {\n this.controller.deselect([id]);\n this.toast(`${label} removed.`, 'neutral', {\n label: 'Undo',\n onClick: () => {\n const restored = this.controller.select([id]);\n this.toast(\n restored.length ? `${label} restored.` : `${label} is no longer available.`,\n restored.length ? 'success' : 'warning',\n );\n },\n });\n };\n if (this.reducedMotion()) {\n remove();\n return;\n }\n chip.classList.add('sl-leave');\n this.scheduleMotion(remove, 150);\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 // Card ↔ map linkage: hovering (or keyboard-focusing) a ticket card pulses\n // its seat on the map so the buyer can locate what they picked.\n this.els.tray.querySelectorAll<HTMLElement>('.sl-chip[data-locate]').forEach((chip) => {\n const locate = (): void => this.controller.flashSeat(chip.dataset.locate!, this.cssVar('--sl-accent') || '#f4b740');\n chip.addEventListener('mouseenter', locate);\n chip.addEventListener('focusin', locate);\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 delta = Number(btn.dataset.d);\n if (delta > 0 && !this.canAddTicket()) return;\n const next = Math.max(0, Math.min(area?.available ?? 0, (this.gaQty.get(id) ?? 0) + delta));\n this.gaQty.set(id, next);\n this.syncTray();\n });\n });\n\n // Sales closed: freeze the best-available + GA controls (read-only state).\n if (this.salesClosed) {\n this.els.tray\n .querySelectorAll<HTMLButtonElement | HTMLSelectElement>('.sl-ba-go,[data-ba],[data-ba-cat],[data-ba-replace],.sl-ga button')\n .forEach((el) => {\n el.disabled = true;\n });\n }\n\n // totals + CTA (held lines + fresh selections + GA)\n const gaTotal = this.pendingGATotal(gaAreas);\n const gaCount = this.pendingGACount();\n const heldTotal = heldItems.reduce((sum, item) => sum + this.paidPrice(item.categoryKey, item.tierId, 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 + this.paidPrice(s.categoryKey, s.tierId ?? null, s.price), 0) + gaTotal + heldTotal;\n const count = freshSeats.length + gaCount + heldCount;\n const pendingCount = this.pendingSelectionCount();\n const previousCount = this.lastTrayCount;\n const previousTotal = this.lastTrayTotal;\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 this.root?.setAttribute('data-has-selection', String(count > 0));\n // The best-available panel's confirm (\"Replace your current choices?\") and\n // in-flight busy states must survive the narrow-layout collapse that hides\n // .sl-ba once the cart is non-empty. Mark them so the CSS keeps them shown.\n this.root?.setAttribute(\n 'data-ba-active',\n String(this.bestAvailableConfirm || this.bestAvailableBusy),\n );\n this.els.foot?.classList.toggle('empty', count === 0);\n if (this.els.seatSummary) {\n this.els.seatSummary.textContent = count ? `${count} selected` : '';\n }\n this.syncCta(count, pendingCount);\n if (this.hold) {\n const securedCount = heldCount || this.hold.seats?.length || 0;\n if (this.els.holdTitle) {\n this.els.holdTitle.textContent = `${securedCount} secured`;\n }\n if (this.els.holdCopy) {\n this.els.holdCopy.textContent = pendingCount\n ? `${pendingCount} more selected`\n : 'Checkout timer running';\n }\n const change = this.els.holdChange as HTMLButtonElement | undefined;\n if (change) {\n change.disabled = this.releasingHold;\n change.textContent = this.releasingHold ? 'Releasing…' : 'Change';\n }\n }\n if (count !== previousCount) this.animateOnce(this.els.count, 'sl-value-pop', 380);\n if (total !== previousTotal) this.animateOnce(this.els.total, 'sl-value-pop', 380);\n if (previousCount === 0 && count > 0) this.animateOnce(this.els.cta, 'sl-ready', 520);\n\n // Mobile sheet: one-line peek summary. Selected → \"N tickets · $X · Continue\";\n // empty → \"From $min · Best available\". Tap (sheet head) expands the sheet.\n if (this.els.peek) {\n if (count) {\n // Sheet state is shown by the persistent chevron in the head; the pill is\n // the action affordance (\"Continue\"/\"Review\") — no inline text arrow.\n this.els.peek.innerHTML =\n `<span>${count} ${count === 1 ? 'ticket' : 'tickets'} · ${this.money(total)}</span>` +\n `<span class=\"go\">${this.hold ? (pendingCount ? 'Secure more' : 'Continue') : 'Review'}</span>`;\n } else {\n const prices = (this.controller.doc?.categories ?? [])\n .map((c) => this.catPrice(c))\n .filter((p): p is number => p != null);\n this.els.peek.innerHTML =\n (prices.length ? `<span>From ${this.money(Math.min(...prices))}</span>` : '<span>Pick your seats</span>') +\n `<span class=\"go\">✦ Best seats</span>`;\n }\n }\n // Keep the mobile map stable after selection. The persistent Review pill\n // exposes the updated count/total without covering the seat the buyer just\n // confirmed; opening the sheet remains an explicit tap or swipe.\n this.lastTrayCount = count;\n this.lastTrayTotal = total;\n\n this.opts.onSelectionChange?.(seats);\n }\n\n private async removeHeldLabel(label: string, chip?: HTMLElement): Promise<boolean> {\n if (!label || this.releasingLabels.has(label)) return false;\n this.releasingLabels.add(label);\n chip?.setAttribute('aria-busy', 'true');\n const button = chip?.querySelector<HTMLButtonElement>('.rm');\n if (button) button.disabled = true;\n try {\n const preserveAcrossNavigation = this.handedOff;\n const released = await this.controller.releaseLabels([label]);\n if (!released) {\n this.toast(`Couldn't remove ${label}. Your hold is unchanged.`, 'error');\n return false;\n }\n const remaining = this.controller.currentHold();\n this.hold = remaining\n ? { holdId: remaining.holdId, expiresAt: remaining.expiresAt, seats: remaining.seats, items: remaining.items }\n : null;\n this.handedOff = !!this.hold && preserveAcrossNavigation;\n this.bookedShown = false;\n this.ctaPhase = 'idle';\n if (this.hold) {\n this.startHoldTimer(this.hold.expiresAt);\n } else {\n this.stopHoldTimer();\n this.forgetHold();\n }\n this.syncTray();\n this.emitHoldChange();\n this.toast(`${label} removed from your hold.`, 'success');\n return true;\n } finally {\n this.releasingLabels.delete(label);\n chip?.removeAttribute('aria-busy');\n if (button?.isConnected) button.disabled = false;\n }\n }\n\n private async handleChangeSeats(): Promise<void> {\n if (!this.hold || this.releasingHold) return;\n this.releasingHold = true;\n const button = this.els.holdChange as HTMLButtonElement | undefined;\n if (button) {\n button.disabled = true;\n button.textContent = 'Releasing…';\n }\n try {\n await this.release();\n if (!this.hold) this.toast('Held tickets released. Choose your new seats.', 'success');\n } finally {\n this.releasingHold = false;\n if (button?.isConnected) {\n button.disabled = false;\n button.textContent = 'Change';\n }\n }\n }\n\n private async handleCta(): Promise<void> {\n if (this.salesClosed) return;\n if (this.totalTicketCount() > this.maxTickets) {\n this.toast(`Remove tickets until your order has ${this.maxTickets} or fewer.`, 'warning');\n return;\n }\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 const committed = this.committedSelection();\n if (this.hold && !committed.some((s) => !(this.hold!.items ?? []).some((i) => i.label === s.label))) {\n const seats = this.hold.seats ?? committed;\n this.handedOff = true;\n this.setCtaPhase('checkout');\n this.opts.onCheckout?.(this.hold, seats, this.buildHandoff(this.hold));\n return;\n }\n this.holdingLabels = new Set(committed.map((seat) => seat.label));\n this.setCtaPhase('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.committedSelection();\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.', 'error');\n this.setCtaPhase('idle');\n this.syncTray();\n return;\n }\n this.hold = hold;\n this.handedOff = true;\n this.startHoldTimer(hold.expiresAt);\n this.flashHeldSeats(hold);\n this.setCtaPhase('checkout');\n this.emitHoldChange();\n // The replacement hold can combine an earlier best-available set with\n // newly selected seats. Hand the host the complete held seat set; the\n // server-priced line items remain authoritative for GA and totals.\n this.opts.onCheckout?.(hold, hold.seats ?? chosenSeats, this.buildHandoff(hold));\n } catch (err) {\n this.opts.onError?.(err);\n const problem = err as { reason?: string; conflicts?: Array<{ label?: string }> };\n const labels = (problem.conflicts ?? []).map((conflict) => conflict.label).filter(Boolean).slice(0, 3);\n // The CTA's controller.hold() path doesn't surface onSalesClosed — apply the\n // persistent read-only state here (the toast below stays). book/bestAvailable\n // paths reach it via the onSalesClosed callback.\n if (problem.reason === 'event_closed') this.setSalesClosed(true);\n const message = problem.reason === 'event_closed'\n ? 'Seat sales have closed for this event.'\n : labels.length\n ? `${labels.join(', ')} ${labels.length === 1 ? 'is' : 'are'} no longer available. Choose another ${labels.length === 1 ? 'seat' : 'group'}.`\n : 'One or more seats were just taken. Please pick again.';\n this.toast(message, 'error');\n this.setCtaPhase('idle');\n } finally {\n this.holdingLabels.clear();\n if (this.ctaPhase === 'holding') this.ctaPhase = 'idle';\n this.syncTray();\n }\n }\n\n private startHoldTimer(expiresAt: number): void {\n this.stopHoldTimer();\n this.holdExpiresAt = expiresAt;\n if (this.hold) this.rememberHold(this.hold);\n const pill = this.els.hold;\n pill.innerHTML =\n '<span class=\"sl-hold-dot\" aria-hidden=\"true\"></span><span>Held</span><span class=\"sl-hold-time\" data-ref=\"holdTime\"></span>';\n const time = pill.querySelector<HTMLElement>('[data-ref=\"holdTime\"]');\n this.els.holdNote?.classList.add('on');\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 if (time) time.textContent = `${m}:${s}`;\n pill.classList.add('on');\n pill.classList.toggle('is-expiring', ms > 0 && ms <= EXTEND_PROMPT_MS);\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', 'is-expiring');\n this.els.holdNote?.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.rememberHold(this.hold);\n this.emitHoldChange();\n this.toast('More time added — your seats are still held.', 'success');\n } else {\n this.toast(\"Couldn't add more time — please head to checkout now.\", 'warning');\n }\n } catch (err) {\n this.opts.onError?.(err);\n this.toast(\"Couldn't add more time — please head to checkout now.\", 'warning');\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 this.forgetHold();\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 // Host `pricing` overrides win in the handoff too — the host gets back the\n // prices it will actually charge, so map display and order total agree.\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: this.paidPrice(it.categoryKey, it.tierId, 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 emitHoldChange(): void {\n const hold = this.hold;\n this.opts.onHoldChange?.(\n hold,\n hold?.seats ?? [],\n hold ? this.buildHandoff(hold) : null,\n );\n }\n\n private toast(\n msg: string,\n tone: 'neutral' | 'success' | 'warning' | 'error' = 'neutral',\n action?: { label: string; onClick: () => void },\n ): void {\n const el = this.els.toast;\n if (!el) return;\n el.replaceChildren();\n const copy = document.createElement('span');\n copy.textContent = msg;\n el.appendChild(copy);\n el.classList.toggle('has-action', !!action);\n if (action) {\n const button = document.createElement('button');\n button.type = 'button';\n button.className = 'sl-toast-action';\n button.textContent = action.label;\n button.addEventListener('click', action.onClick, { once: true });\n el.appendChild(button);\n }\n el.dataset.tone = tone;\n el.classList.add('on');\n if (this.toastTimer) clearTimeout(this.toastTimer);\n this.toastTimer = setTimeout(() => {\n el.classList.remove('on');\n el.classList.remove('has-action');\n el.dataset.tone = 'neutral';\n }, 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 /**\n * Row label without the redundant section prefix. Charts commonly name row\n * objects \"104-A\" while the Section column already shows \"104\" — so the Row\n * cell repeats the section and, in the compact hover card, truncates to\n * \"10…\". Strip a leading \"<section><sep>\" so Row reads a clean \"A\". Only when\n * the prefix is exact (won't touch \"1040-A\" under section \"104\"); otherwise\n * the label is shown verbatim.\n */\n private rowShort(details: { sectionLabel?: string; rowLabel?: string } | null | undefined): string | undefined {\n const row = details?.rowLabel;\n const sec = details?.sectionLabel;\n if (!row || !sec) return row;\n for (const sep of ['-', ' ', '·', '/', '_']) {\n const prefix = `${sec}${sep}`;\n if (row.startsWith(prefix) && row.length > prefix.length) return row.slice(prefix.length);\n }\n return row;\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 esc = (v: unknown): string =>\n String(v ?? '—').replace(/[&<>\"]/g, (ch) => ({ '&': '&', '<': '<', '>': '>', '\"': '"' }[ch]!));\n const price = this.money(this.paidPrice(details.categoryKey, details.tierId ?? null, details.price));\n // Identity grid — the same Section·Row·Seat card the buyer meets on confirm\n // and in the cart, just smaller. Falls back to a single field for a bare\n // label (GA / legacy seats with no spatial context).\n const hasLoc = details.sectionLabel || details.rowLabel || details.seatNumber;\n const grid = hasLoc\n ? `<div class=\"sl-tip-grid\">` +\n `<div class=\"sl-tip-field\"><span class=\"sl-tip-key\">Section</span><span class=\"sl-tip-val\">${esc(details.sectionLabel)}</span></div>` +\n `<div class=\"sl-tip-field\"><span class=\"sl-tip-key\">Row</span><span class=\"sl-tip-val\">${esc(this.rowShort(details))}</span></div>` +\n `<div class=\"sl-tip-field\"><span class=\"sl-tip-key\">Seat</span><span class=\"sl-tip-val\">${esc(details.seatNumber ?? details.label)}</span></div>` +\n `</div>`\n : `<div class=\"sl-tip-grid one\"><div class=\"sl-tip-field\"><span class=\"sl-tip-key\">Seat</span><span class=\"sl-tip-val\">${esc(details.label)}</span></div></div>`;\n const statusLine =\n details.status === 'free'\n ? ''\n : `<div class=\"sl-tip-status\">${details.status === 'held' ? t('map.statusHeld') : t('map.statusTaken')}</div>`;\n this.tipEl.style.setProperty('--sl-cat', details.categoryColor);\n this.tipEl.innerHTML =\n grid +\n `<div class=\"sl-tip-cat\"><span class=\"sl-tip-dot\" style=\"background:${details.categoryColor}\"></span>` +\n `<span class=\"sl-tip-name\">${esc(details.categoryLabel)}</span>` +\n `<span class=\"sl-tip-amt\">${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.committedSelection();\n }\n\n /** Current active/restored hold reflected in the tray. */\n getCurrentHold(): HoldResult | null {\n return this.hold;\n }\n\n /** Explicit host-driven hold restore (automatic session restore is on by default). */\n async resumeHold(holdId: string): Promise<HoldResult | null> {\n return this.resumeHoldFromServer(holdId, false);\n }\n\n /** Remove one server-held ticket while keeping the rest of the hold active. */\n async removeHeldTicket(label: string): Promise<boolean> {\n return this.removeHeldLabel(label);\n }\n\n async bestAvailable(qty: number, categoryKey?: string): Promise<HoldResult | null> {\n if (this.salesClosed || this.bestAvailableBusy) return null;\n qty = Math.max(1, Math.min(this.maxTickets, Math.floor(qty)));\n if (this.confirmSeat) this.cancelConfirm();\n this.bestAvailableConfirm = false;\n this.bestAvailableBusy = true;\n const button = this.els.tray?.querySelector<HTMLButtonElement>('.sl-ba-go');\n if (button) {\n button.disabled = true;\n button.innerHTML = '<span class=\"sl-ba-spin\" aria-hidden=\"true\"></span>Finding…';\n }\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.gaQty.clear();\n this.startHoldTimer(h.expiresAt);\n this.flashHeldSeats(this.hold);\n this.syncTray();\n this.emitHoldChange();\n return this.hold;\n }\n return null;\n } catch (err) {\n this.opts.onError?.(err);\n const reason = (err as { reason?: string })?.reason;\n const message = reason === 'not_enough_together'\n ? `We couldn't find ${qty} seats together. Try fewer seats or another ticket type.`\n : reason === 'sold_out'\n ? 'That ticket type is sold out. Try another ticket type.'\n : reason === 'event_closed'\n ? 'Seat sales have closed for this event.'\n : 'Those seats are no longer available. Try another quantity or ticket type.';\n this.toast(message, 'error');\n return null;\n } finally {\n this.bestAvailableBusy = false;\n this.syncTray();\n }\n }\n\n async release(): Promise<void> {\n const tracked = this.hold;\n const controllerHold = this.controller.currentHold();\n let released = true;\n if (controllerHold) {\n released = await this.controller.release();\n } else if (tracked) {\n // The live controller can legitimately settle/clear its local hold before\n // the shell finishes dismissing. The shell still owns the server handoff,\n // so release from that authoritative copy instead of silently no-oping.\n const labels = [...new Set([\n ...(tracked.items ?? []).map((item) => item.label),\n ...(tracked.seats ?? []).map((seat) => seat.label),\n ])];\n if (labels.length) {\n try {\n await this.api.release(this.opts.event, labels, tracked.holdId);\n } catch (error) {\n this.opts.onError?.(error);\n released = false;\n }\n }\n }\n if (!released) {\n this.toast(\"Couldn't release your tickets. Your hold is unchanged.\", 'error');\n return;\n }\n this.hold = null;\n this.forgetHold();\n this.handedOff = false;\n this.bookedShown = false;\n this.ctaPhase = 'idle';\n this.stopHoldTimer();\n this.gaQty.clear();\n this.syncTray();\n this.emitHoldChange();\n }\n\n destroy(): void {\n this.destroyed = true;\n // Closing/tearing down before checkout means the buyer abandoned any\n // best-available hold. Release it server-side; a handed-off checkout keeps\n // its hold alive across the host's route transition.\n if (this.hold && !this.handedOff) void this.controller.release();\n this.closeConfirm();\n this.closeSeatView();\n this.stopHoldTimer();\n if (this.toastTimer) clearTimeout(this.toastTimer);\n if (this.liveTimer) clearTimeout(this.liveTimer);\n for (const timer of this.motionTimers) clearTimeout(timer);\n this.motionTimers.clear();\n this.ro?.disconnect();\n this.ro = null;\n // Don't strand a host frame pinned fullscreen across a route teardown.\n if (this.framedFs) this.setFramedFs(false);\n if (this.escHandler) document.removeEventListener('keydown', this.escHandler);\n if (this.fsChangeHandler) document.removeEventListener('fullscreenchange', this.fsChangeHandler);\n if (this.fsEscHandler) window.removeEventListener('keydown', this.fsEscHandler);\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","/**\n * Host-side helper for embedding the SeatLayer picker as an iframe.\n *\n * The picker (the /e/:key page, mounted `position:fixed; inset:0`) reports its\n * desired height and fullscreen intent to whatever page frames it, using the\n * picker wire contract:\n *\n * • `{ type: 'seatlayer:height', px:number }` — grow the iframe to `px`.\n * • `{ type: 'seatlayer:fullscreen', on:boolean }` — pin/unpin over the host.\n *\n * A framed picker cannot escape its own iframe with CSS, so it delegates both\n * concerns to the host. `attachPickerFrame` wires those two behaviours onto a\n * picker iframe and returns a detach function that tears everything back down.\n */\nexport interface AttachPickerFrameOptions {\n /**\n * Origin to accept messages from. Defaults to the origin parsed from\n * `iframe.src`. Messages from any other origin (or any other window) are\n * ignored — the picker posts with `targetOrigin:'*'`, so the host is the side\n * that must verify `event.origin`.\n */\n origin?: string;\n}\n\n/**\n * Attach the picker resize + fullscreen protocol to a picker iframe.\n *\n * ```ts\n * const iframe = document.querySelector('iframe#seatlayer')!;\n * const detach = attachPickerFrame(iframe);\n * // …later, when removing the embed:\n * detach();\n * ```\n *\n * @param iframe The `<iframe>` element pointing at a SeatLayer picker embed.\n * @param opts Optional `{ origin }` override for the accepted message origin.\n * @returns A detach function: removes the listener and restores any pinned state.\n */\nexport function attachPickerFrame(\n iframe: HTMLIFrameElement,\n opts: AttachPickerFrameOptions = {},\n): () => void {\n let expectedOrigin = opts.origin ?? '';\n if (!expectedOrigin) {\n try {\n expectedOrigin = new URL(iframe.src, window.location.href).origin;\n } catch {\n expectedOrigin = '';\n }\n }\n\n let pinned = false;\n let frameStyleBeforeFs: string | null = null;\n let docOverflowBeforeFs: string | null = null;\n let bodyOverflowBeforeFs: string | null = null;\n let lastAutoHeight = '';\n let keyHandler: ((event: KeyboardEvent) => void) | null = null;\n\n const pin = (): void => {\n if (pinned) return;\n pinned = true;\n frameStyleBeforeFs = iframe.getAttribute('style');\n Object.assign(iframe.style, {\n position: 'fixed',\n inset: '0',\n width: '100vw',\n height: '100vh',\n margin: '0',\n border: '0',\n zIndex: '2147483000',\n background: '#101625',\n } satisfies Partial<CSSStyleDeclaration>);\n\n const docEl = document.documentElement;\n docOverflowBeforeFs = docEl.style.overflow;\n docEl.style.overflow = 'hidden';\n if (document.body) {\n bodyOverflowBeforeFs = document.body.style.overflow;\n document.body.style.overflow = 'hidden';\n }\n\n keyHandler = (event: KeyboardEvent): void => {\n if (event.key === 'Escape') unpin();\n };\n window.addEventListener('keydown', keyHandler);\n };\n\n const unpin = (): void => {\n if (!pinned) return;\n pinned = false;\n if (frameStyleBeforeFs === null) iframe.removeAttribute('style');\n else iframe.setAttribute('style', frameStyleBeforeFs);\n frameStyleBeforeFs = null;\n // Re-apply any height reported while we were pinned.\n if (lastAutoHeight) iframe.style.height = lastAutoHeight;\n\n if (docOverflowBeforeFs !== null) {\n document.documentElement.style.overflow = docOverflowBeforeFs;\n docOverflowBeforeFs = null;\n }\n if (bodyOverflowBeforeFs !== null && document.body) {\n document.body.style.overflow = bodyOverflowBeforeFs;\n bodyOverflowBeforeFs = null;\n }\n if (keyHandler) {\n window.removeEventListener('keydown', keyHandler);\n keyHandler = null;\n }\n };\n\n const onMessage = (event: MessageEvent<unknown>): void => {\n if (event.source !== iframe.contentWindow) return;\n if (expectedOrigin && event.origin !== expectedOrigin) return;\n if (!event.data || typeof event.data !== 'object') return;\n const data = event.data as Record<string, unknown>;\n\n if (data.type === 'seatlayer:height') {\n if (typeof data.px === 'number' && Number.isFinite(data.px) && data.px > 0) {\n lastAutoHeight = `${Math.round(data.px)}px`;\n // While pinned the iframe fills the viewport; the height is re-applied on unpin.\n if (!pinned) iframe.style.height = lastAutoHeight;\n }\n return;\n }\n if (data.type === 'seatlayer:fullscreen') {\n if (data.on === true) pin();\n else if (data.on === false) unpin();\n }\n };\n\n window.addEventListener('message', onMessage);\n\n return (): void => {\n window.removeEventListener('message', onMessage);\n unpin();\n };\n}\n","/**\n * SeatManager — the organizer manage surface, packaged for the SDK.\n *\n * Productizes the SeatLayer dashboard's ManageEventPage into a framework-\n * agnostic class (mirrors how SeatPicker productized the buyer flow). It mounts\n * the shared engine in `manageMode`, subscribes to the event's realtime channel\n * and drives three control-room tools on one persistent canvas:\n *\n * - **view** — a live board: realtime seat repaint (flash on hold/book),\n * live KPI tallies + gross revenue, and a streaming activity\n * feed derived from the delta stream + audit log. Read-only.\n * - **inspect** — select one seat to read its live inventory context.\n * - **block** — bulk-first block/unblock: marquee-drag, ⌘A select-all,\n * whole-category / whole-section select, single-seat fallback →\n * one batched block/unblock (optimistic, reconciled by the WS),\n * and timed auto-release.\n *\n * Auth: reads (chart/objects/WS) are public; writes/reports carry a Bearer\n * event-scoped manage token (`mse_…`) or a tenant secret key (`sk_…`) via\n * {@link ManageApi}. Box office + Sections + full Reports UI are M2/M3.\n */\nimport {\n SeatmapRenderer,\n expandChart,\n computeSections,\n UNGROUPED_ID,\n type AvailabilityRule,\n type ChartDoc,\n type ChartTheme,\n type ExpandedSeat,\n type SeatStatus,\n type SectionNode,\n} from '@seatlayer/core';\nimport {\n ManageApi,\n ManageApiError,\n type ControlRoomActivityEntry,\n type ControlRoomSnapshot,\n type LogEntry,\n type ReportResult,\n} from './manageApi';\n\nexport type SeatManagerMode = 'view' | 'inspect' | 'block' | 'sections';\n\n/** The select-state of a Sections-mode availability row. An absent rule is\n * `open` (on sale); otherwise the rule's own mode. */\nexport type AvailabilityMode = 'open' | 'closed' | 'hidden' | 'timed' | 'threshold';\n\n/** One row of the Sections rail — a zone header or a single section. */\ninterface SectionRow {\n kind: 'zone' | 'section';\n id: string;\n label: string;\n seatCount: number;\n /** Seat labels the id governs (sent as the rule's `labels`). */\n seatLabels: string[];\n rule: AvailabilityRule | null;\n /** Effective-hidden right now (manual hide, or a timed/threshold window not yet due). */\n hidden: boolean;\n /** Effective-closed right now — visible to buyers but off sale. */\n closed: boolean;\n /** A section whose parent zone carries a rule — its own control is a muted \"Follows zone\". */\n followsZone: boolean;\n}\n\n/** Map an availability rule to its Sections-rail select value (null rule = on sale). */\nexport function availabilityModeOf(rule: AvailabilityRule | null | undefined): AvailabilityMode {\n return rule ? rule.mode : 'open';\n}\n\n/**\n * Build the rule a chosen select mode implies for a set of seat labels, reusing\n * an existing rule's tuning where it carries over (a timed reveal time, a\n * threshold percent). `open` clears the rule (returns null → id dropped from the\n * map). Wire-identical to the EventDO's accepted rule shapes.\n */\nexport function availabilityRuleForMode(\n mode: AvailabilityMode,\n seatLabels: string[],\n prev?: AvailabilityRule | null,\n): AvailabilityRule | null {\n switch (mode) {\n case 'open':\n return null;\n case 'hidden':\n return { mode: 'hidden', labels: seatLabels };\n case 'closed':\n return { mode: 'closed', labels: seatLabels };\n case 'timed':\n return { mode: 'timed', revealAt: prev?.revealAt ?? Date.now() + 3_600_000, labels: seatLabels };\n case 'threshold':\n return { mode: 'threshold', thresholdPct: prev?.thresholdPct ?? 80, labels: seatLabels };\n }\n}\n\n/** epoch ms → a `datetime-local` input value (local time, minute precision). */\nfunction toLocalInput(ms: number): string {\n const d = new Date(ms - new Date().getTimezoneOffset() * 60_000);\n return d.toISOString().slice(0, 16);\n}\n\n/** DO seat status — 'blocked' has no engine analogue (→ 'not_for_sale'). */\ntype DoStatus = 'free' | 'held' | 'booked' | 'blocked';\n\n/** Live KPI snapshot pushed to `onTallies` on every state change. */\nexport interface SeatManagerTallies {\n free: number;\n held: number;\n booked: number;\n blocked: number;\n /** Total seats on the chart. */\n total: number;\n /** booked / total, 0–100. */\n capacityPct: number;\n /** booked / (total − blocked), 0–100 — sell-through of sellable inventory. */\n sellThroughPct: number;\n /** Exact Σ booked unit_price snapshots from the authenticated report. */\n grossRevenue: number;\n /** Revenue is never reconstructed from chart list price. */\n revenueStatus: 'loading' | 'current' | 'stale';\n /** ISO-4217 currency for grossRevenue. */\n currency: string;\n}\n\n/** One streamed activity line for the live feed. */\nexport interface SeatManagerActivity {\n id: string;\n at: number;\n label: string;\n /** Full labels affected by this one backend/realtime operation. */\n labels: string[];\n count: number;\n /** Human verb: held / booked / released / blocked / unblocked. */\n verb: string;\n status: DoStatus;\n /** Spatial context for grouped activity when the chart defines sections. */\n sectionIds?: string[];\n sectionLabels?: string[];\n}\n\n/** Fired after a successful organizer action, for host toasts/telemetry. */\nexport interface SeatManagerActionResult {\n action: 'block' | 'unblock' | 'unblockAll' | 'cancelBooking' | 'setHoldTtl';\n labels: string[];\n count: number;\n}\n\nexport interface SeatManagerOptions {\n /** CSS selector or element to mount into. */\n container: string | HTMLElement;\n /** API origin. Defaults to https://api.seatlayer.io. */\n apiBase?: string;\n /** Event key (e.g. `ev_xxx` / `west-end-p3`). */\n eventKey: string;\n /** Bearer manage token — event-scoped `mse_…` or a tenant secret `sk_…`. */\n token: string;\n /** Absolute token expiry (epoch ms). Enables proactive in-place rotation. */\n tokenExpiresAt?: number;\n /** Initial mode. Default 'view'. */\n mode?: SeatManagerMode;\n /** ISO-4217 fallback currency for revenue (chart/event currency wins). */\n currency?: string;\n /** Chart theme override for the chrome (rails/bar). Chart colors come from the doc. */\n theme?: ChartTheme;\n /**\n * Keep the canvas painting even when the tab is hidden/backgrounded (a war-room\n * board on a second monitor). Calls `forceDraw()` after each delta so Chrome's\n * rAF throttling on occluded tabs never leaves the board stale. Default true.\n */\n keepLiveWhileHidden?: boolean;\n /**\n * Opt in to camera-following for new buyer holds/bookings. Off by default so\n * a live event never steals an operator's current map context.\n */\n followLive?: boolean;\n /** Chart + first snapshot are loaded and the board is live. */\n onReady?: () => void;\n /** Live KPI tallies changed. */\n onTallies?: (tallies: SeatManagerTallies) => void;\n /** A grouped live/audit activity item arrived. */\n onActivity?: (activity: SeatManagerActivity) => void;\n /** Exact private control-room projection changed. */\n onControlRoom?: (snapshot: ControlRoomSnapshot) => void;\n /** Called before token expiry. The manager swaps the result without remounting. */\n onTokenRefresh?: () => Promise<{ token: string; expiresAt: number }>;\n /** Tool/mode changed from inside the shared cockpit. */\n onModeChange?: (mode: SeatManagerMode) => void;\n /** Follow-live preference changed from inside the cockpit. */\n onFollowLiveChange?: (enabled: boolean) => void;\n /** Block-mode selection changed (marquee / ⌘A / category / section / tap). */\n onSelectionChange?: (seats: ExpandedSeat[]) => void;\n /** A block/unblock/cancel action completed successfully. */\n onActionComplete?: (result: SeatManagerActionResult) => 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(`seatmanager: container \"${container}\" not found`);\n return el as HTMLElement;\n }\n if (!(container instanceof HTMLElement)) {\n throw new Error('seatmanager: container must be a CSS selector or an HTMLElement');\n }\n return container;\n}\n\n/** 'blocked' → renderer 'not_for_sale'; the rest pass through. */\nfunction toRenderStatus(s: DoStatus): SeatStatus {\n return s === 'blocked' ? 'not_for_sale' : s;\n}\n\nconst DEFAULT_API_BASE = 'https://api.seatlayer.io';\nconst STYLE_ID = 'seatlayer-manager-style';\nconst FEED_CAP = 80;\nconst MAX_LIVE_SEAT_PULSES = 16;\nconst MAX_LIVE_SECTION_PULSES = 4;\n\nconst LEGEND: { key: 'free' | 'held' | 'booked' | 'blocked'; label: string; color: string }[] = [\n { key: 'free', label: 'Free', color: '#6e7bff' },\n { key: 'held', label: 'Held', color: '#f4b740' },\n { key: 'booked', label: 'Booked', color: '#22a06b' },\n { key: 'blocked', label: 'Blocked', color: '#8b94ac' },\n];\n\nconst CSS = `\n.slm{position:relative;display:flex;flex-direction:column;width:100%;height:100%;min-height:480px;overflow:hidden;\n background:var(--slm-bg);color:var(--slm-text);font-family:var(--slm-font);border-radius:var(--slm-radius)}\n.slm *{box-sizing:border-box;margin:0;padding:0}\n.slm button{font:inherit;color:inherit;background:none;border:0;cursor:pointer}\n.slm input{font:inherit}\n\n/* top bar */\n.slm-bar{display:grid;grid-template-columns:auto auto minmax(0,1fr);align-items:center;column-gap:14px;row-gap:10px;\n padding:10px 16px;border-bottom:1px solid var(--slm-line);flex:none}\n.slm-modes{display:inline-flex;background:var(--slm-surface);border:1px solid var(--slm-line);border-radius:999px;padding:3px}\n.slm-mode{padding:6px 16px;border-radius:999px;font-weight:700;font-size:13px;color:var(--slm-muted)}\n.slm-mode.on{background:var(--slm-accent);color:var(--slm-accent-ink)}\n.slm-live{display:inline-flex;align-items:center;gap:6px;font-size:11px;letter-spacing:.12em;font-weight:800;color:var(--slm-muted)}\n.slm-live-dot{width:8px;height:8px;border-radius:50%;background:#8b94ac}\n.slm.live .slm-live-dot{background:#22a06b;box-shadow:0 0 0 0 rgba(34,160,107,.55);animation:slm-pulse 2s infinite}\n@keyframes slm-pulse{0%{box-shadow:0 0 0 0 rgba(34,160,107,.5)}70%{box-shadow:0 0 0 7px rgba(34,160,107,0)}100%{box-shadow:0 0 0 0 rgba(34,160,107,0)}}\n.slm-kpis{grid-column:1/-1;display:grid;grid-template-columns:repeat(8,minmax(0,1fr));width:100%;padding-top:10px;\n border-top:1px solid var(--slm-line)}\n.slm-kpi{position:relative;display:flex;min-width:0;flex-direction:column;align-items:center;padding:0 5px;line-height:1.15;text-align:center}\n.slm-kpi b{display:flex;min-width:0;align-items:baseline;justify-content:center;font-size:17px;font-weight:800;\n font-variant-numeric:tabular-nums;white-space:nowrap}\n.slm-kpi span{font-size:9.5px;letter-spacing:.1em;text-transform:uppercase;color:var(--slm-muted);font-weight:700}\n.slm-kpi .dot{display:inline-block;width:8px;height:8px;border-radius:50%;margin-right:5px;vertical-align:baseline}\n.slm-kpi.changed b{animation:slm-kpi-bump .58s cubic-bezier(.2,.8,.2,1)}\n.slm-kpidelta{position:absolute;right:4px;top:-12px;padding:2px 5px;border-radius:999px;background:rgba(34,160,107,.17);\n color:#5bd39b!important;font-size:9px!important;letter-spacing:0!important;text-transform:none!important;white-space:nowrap;\n animation:slm-kpi-delta 1.45s ease-out both;pointer-events:none}\n.slm-kpidelta.down{background:rgba(244,183,64,.14);color:#f7ca6b!important}\n@keyframes slm-kpi-bump{0%,100%{transform:none}35%{transform:translateY(-2px) scale(1.08);text-shadow:0 0 18px rgba(255,255,255,.24)}}\n@keyframes slm-kpi-delta{0%{opacity:0;transform:translateY(5px)}18%,72%{opacity:1;transform:none}100%{opacity:0;transform:translateY(-5px)}}\n.slm-barbtn{padding:7px 13px;border-radius:9px;border:1px solid var(--slm-line);color:var(--slm-text);font-weight:700;font-size:12.5px}\n.slm-barbtn:hover{border-color:var(--slm-muted)}\n.slm-barbtn.follow.on{background:rgba(34,160,107,.13);border-color:#22a06b;color:#5bd39b}\n\n/* body */\n.slm-body{display:flex;flex:1;min-height:0}\n.slm-map{position:relative;flex:1;min-width:0}\n.slm-map-host{position:absolute;inset:0}\n.slm-hud{position:absolute;left:12px;bottom:12px;display:flex;gap:8px}\n.slm-hud-chip{padding:6px 11px;border-radius:999px;font-size:12px;font-weight:700;background:var(--slm-surface);\n border:1px solid var(--slm-line);color:var(--slm-text)}\n.slm-zoomhint{position:absolute;left:50%;top:14px;transform:translateX(-50%);padding:6px 13px;border-radius:999px;\n background:rgba(0,0,0,.55);color:#fff;font-size:12px;font-weight:700;pointer-events:none;opacity:0;transition:opacity .2s}\n.slm-zoomhint.on{opacity:1}\n.slm-liveevent{position:absolute;left:50%;top:14px;z-index:4;display:flex;align-items:center;gap:8px;max-width:min(560px,calc(100% - 32px));\n padding:8px 12px;border:1px solid var(--slm-line);border-radius:999px;background:color-mix(in srgb,var(--slm-surface) 92%,transparent);\n box-shadow:0 10px 34px rgba(0,0,0,.32);opacity:0;transform:translate(-50%,-8px);pointer-events:none;\n transition:opacity .18s ease,transform .24s ease;backdrop-filter:blur(10px)}\n.slm-liveevent.on{opacity:1;transform:translate(-50%,0)}\n.slm.block-mode .slm-liveevent{top:52px}\n.slm-liveeventdot{width:8px;height:8px;border-radius:50%;flex:none}.slm-liveeventcopy{min-width:0;overflow:hidden;text-overflow:ellipsis;\n white-space:nowrap;font-size:12px;font-weight:800}.slm-liveeventhint{color:var(--slm-muted);font-size:10px;white-space:nowrap}\n.slm-rail{width:320px;flex:none;border-left:1px solid var(--slm-line);display:flex;flex-direction:column;min-height:0}\n.slm-railscroll{flex:1;overflow-y:auto;padding:16px}\n.slm-eyebrow{font-size:10px;letter-spacing:.14em;text-transform:uppercase;color:var(--slm-muted);font-weight:800;margin-bottom:6px}\n.slm-hint{font-size:12.5px;color:var(--slm-muted);line-height:1.5;margin-bottom:14px}\n\n/* legend rows */\n.slm-legend{display:flex;flex-direction:column;gap:2px;margin-bottom:16px}\n.slm-legrow{display:flex;align-items:center;gap:9px;padding:7px 2px;border-bottom:1px solid var(--slm-line)}\n.slm-legdot{width:10px;height:10px;border-radius:50%;flex:none}\n.slm-leglabel{flex:1;font-size:13px;font-weight:600}\n.slm-legcount{font-size:13px;font-weight:800;font-variant-numeric:tabular-nums}\n\n/* activity feed */\n.slm-feed{display:flex;flex-direction:column;gap:0}\n.slm-feedrow{display:flex!important;width:100%;align-items:center;gap:9px;padding:8px 2px!important;border-bottom:1px solid var(--slm-line)!important;\n border-radius:6px;font-size:12.5px;text-align:left!important;animation:slm-in .35s ease}\n.slm-feedrow:hover{background:rgba(255,255,255,.035)!important}\n@keyframes slm-in{from{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:none}}\n.slm-feeddot{width:8px;height:8px;border-radius:50%;flex:none}\n.slm-feedtext{flex:1;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n.slm-feedtext b{font-weight:800}\n.slm-feedsection{display:block;overflow:hidden;text-overflow:ellipsis;color:var(--slm-muted);font-size:10px;font-weight:750}\n.slm-feedmeta{display:flex;flex:none;flex-direction:column;align-items:flex-end;gap:1px}.slm-feedtime{font-size:10px;color:var(--slm-muted);font-variant-numeric:tabular-nums}\n.slm-feedlocate{font-size:9.5px;color:var(--slm-accent);font-weight:800}\n.slm-empty{font-size:12.5px;color:var(--slm-muted);padding:12px 0}\n\n/* block toolbar */\n.slm-selbar{display:flex;align-items:baseline;gap:8px;margin-bottom:10px}\n.slm-selnum{font-size:26px;font-weight:800;font-variant-numeric:tabular-nums}\n.slm-sellabel{font-size:12px;color:var(--slm-muted);font-weight:600}\n.slm-row{display:flex;gap:8px;flex-wrap:wrap;margin-bottom:10px}\n.slm-btn{flex:1;min-width:120px;padding:10px 14px;border-radius:10px;background:var(--slm-accent);color:var(--slm-accent-ink);\n font-weight:800;font-size:13px;text-align:center}\n.slm-btn:disabled{opacity:.45;cursor:not-allowed}\n.slm-btn.ghost{background:var(--slm-surface);border:1px solid var(--slm-line);color:var(--slm-text)}\n.slm-btn.danger{background:#c0392b;color:#fff}\n.slm-chiprow{display:flex;gap:6px;flex-wrap:wrap;margin-bottom:6px}\n.slm-chip{padding:6px 11px;border-radius:999px;border:1px solid var(--slm-line);background:var(--slm-surface);\n font-size:12px;font-weight:700;color:var(--slm-text);display:inline-flex;align-items:center;gap:6px}\n.slm-chip:hover{border-color:var(--slm-muted)}\n.slm-chip .dot{width:8px;height:8px;border-radius:50%}\n.slm-chip .slm-chipcount{min-width:18px;padding:1px 5px;border-radius:999px;background:rgba(255,255,255,.07);\n color:var(--slm-muted);font-size:10px;font-variant-numeric:tabular-nums;text-align:center}\n.slm-chip .slm-chipcheck{display:none;font-size:11px;line-height:1}\n.slm-chip.on{border-color:var(--slm-accent);background:color-mix(in srgb,var(--slm-accent) 20%,var(--slm-surface));\n box-shadow:0 0 0 1px color-mix(in srgb,var(--slm-accent) 45%,transparent)}\n.slm-chip.on .slm-chipcount{background:var(--slm-accent);color:var(--slm-accent-ink)}\n.slm-chip.on .slm-chipcheck{display:inline}\n.slm-chip.partial{border-style:dashed;border-color:var(--slm-accent)}\n.slm-chip:disabled{opacity:.42;cursor:not-allowed}\n.slm-selecthelp{margin:-1px 0 9px;color:var(--slm-muted);font-size:11px;line-height:1.4}\n.slm-field{margin:14px 0}\n.slm-field label{display:block;font-size:11px;font-weight:700;color:var(--slm-muted);margin-bottom:5px}\n.slm-input,.slm-select{width:100%;padding:8px 10px;border-radius:9px;border:1px solid var(--slm-line);\n background:var(--slm-surface);color:var(--slm-text)}\n.slm-note{font-size:11.5px;color:var(--slm-muted);margin-top:5px}\n.slm-blocked{margin-top:17px;padding-top:15px;border-top:1px solid var(--slm-line)}\n.slm-blockedhead{display:flex;align-items:baseline;justify-content:space-between;gap:10px;margin-bottom:8px}\n.slm-blockedhead .slm-eyebrow{margin-bottom:0}.slm-blockedtotal{font-size:11px;color:var(--slm-muted)}\n.slm-blockedtotal b{color:var(--slm-text);font-variant-numeric:tabular-nums}\n.slm-blockedtools{display:grid;grid-template-columns:minmax(0,1fr);gap:7px}\n.slm-blockedsummary{display:flex;align-items:center;justify-content:space-between;gap:8px;margin:9px 0 6px;\n color:var(--slm-muted);font-size:10.5px}\n.slm-linkbtn{font-size:11px!important;font-weight:800!important;color:var(--slm-accent)!important;text-align:right}\n.slm-linkbtn:disabled{opacity:.45;cursor:not-allowed}\n.slm-blockedlist{max-height:246px;overflow:auto;border:1px solid var(--slm-line);border-radius:10px;background:var(--slm-surface)}\n.slm-blockeditem{display:grid!important;grid-template-columns:18px minmax(0,1fr);width:100%;gap:8px;padding:8px 9px!important;\n border-bottom:1px solid var(--slm-line)!important;text-align:left!important}\n.slm-blockeditem:last-child{border-bottom:0!important}.slm-blockeditem:hover{background:rgba(255,255,255,.035)!important}\n.slm-blockeditem.on{background:color-mix(in srgb,var(--slm-accent) 13%,var(--slm-surface))!important}\n.slm-blockedcheck{display:flex;align-items:center;justify-content:center;width:16px;height:16px;margin-top:1px;border-radius:4px;\n border:1px solid var(--slm-muted);color:transparent;font-size:10px;font-weight:900}\n.slm-blockeditem.on .slm-blockedcheck{border-color:var(--slm-accent);background:var(--slm-accent);color:var(--slm-accent-ink)}\n.slm-blockedcopy{min-width:0}.slm-blockedlabel{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;\n font-size:12px;font-weight:800}.slm-blockedmeta{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;\n margin-top:2px;color:var(--slm-muted);font-size:10px}\n.slm-blockedmore{width:100%;padding:9px!important;color:var(--slm-accent)!important;font-size:11px!important;font-weight:800!important}\n.slm-blockedempty{padding:12px;color:var(--slm-muted);font-size:11.5px;line-height:1.45}\n.slm-allnote{margin-top:-4px;margin-bottom:10px}\n\n/* toast */\n.slm-toast{position:absolute;left:50%;bottom:16px;transform:translateX(-50%);padding:10px 16px;border-radius:10px;\n font-size:13px;font-weight:700;box-shadow:0 8px 24px rgba(0,0,0,.28);opacity:0;pointer-events:none;transition:opacity .2s;\n background:var(--slm-surface);color:var(--slm-text);border:1px solid var(--slm-line);z-index:5}\n.slm-toast.on{opacity:1}\n.slm-toast.err{background:#c0392b;color:#fff;border-color:#c0392b}\n.slm-toast.ok{background:#1f7a4d;color:#fff;border-color:#1f7a4d}\n\n/* control-room actions + insights */\n.slm-bar-actions{display:flex;align-items:center;justify-self:end;gap:7px}\n.slm-barbtn.on{background:rgba(244,183,64,.13);border-color:#f4b740;color:#f7ca6b}\n.slm-sectionlist{display:flex;flex-direction:column;gap:8px;margin-top:4px}\n.slm-sectionlist + .slm-eyebrow{margin-top:18px}\n.slm-sectionrow{width:100%;padding:10px!important;border:1px solid var(--slm-line)!important;border-radius:10px;background:var(--slm-surface)!important;text-align:left!important;transition:border-color .15s ease,transform .15s ease}\n.slm-sectionrow:hover{border-color:var(--slm-muted)!important;transform:translateY(-1px)}\n.slm-sectiontop,.slm-sectionmeta{display:flex;align-items:center;justify-content:space-between;gap:10px}\n.slm-sectiontop{font-size:12.5px;font-weight:800}.slm-sectionmeta{margin-top:5px;color:var(--slm-muted);font-size:11px}\n.slm-sectionmeta>span:first-child{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n.slm-trend{font-size:10px;text-transform:uppercase;letter-spacing:.08em}.slm-trend.rising{color:#22a06b}.slm-trend.cooling{color:#f4b740}\n.slm-sectionlocate{color:var(--slm-accent);font-size:9.5px;font-weight:800}\n.slm-health{display:grid;grid-template-columns:1fr 1fr;gap:8px;margin-bottom:16px}\n.slm-healthitem{padding:10px;border:1px solid var(--slm-line);border-radius:10px;background:var(--slm-surface)}\n.slm-healthitem b{display:block;font-size:17px;font-variant-numeric:tabular-nums}.slm-healthitem span{display:block;margin-top:2px;color:var(--slm-muted);font-size:10px;text-transform:uppercase;letter-spacing:.08em}\n.slm-sectionhead{display:flex;align-items:flex-start;justify-content:space-between;gap:10px;margin-top:18px}\n.slm-windows{display:flex;gap:3px;padding:2px;border:1px solid var(--slm-line);border-radius:8px;background:var(--slm-surface)}\n.slm-window{padding:4px 6px;border-radius:6px;font-size:10px;font-weight:800;color:var(--slm-muted)}.slm-window.on{background:var(--slm-accent);color:var(--slm-accent-ink)}\n.slm-momentumhelp{margin:10px 0 14px;padding:10px;border:1px solid rgba(244,183,64,.28);border-radius:10px;background:rgba(244,183,64,.07)}\n.slm-momentumhelp[hidden]{display:none}.slm-momentumscale{display:flex;align-items:center;gap:7px;color:var(--slm-muted);font-size:10px;font-weight:750;text-transform:uppercase;letter-spacing:.07em}\n.slm-momentumgradient{height:6px;min-width:64px;flex:1;border-radius:999px;background:linear-gradient(90deg,#f4b740,#ef4444)}\n.slm-momentumcopy{margin-top:7px;color:var(--slm-muted);font-size:11px;line-height:1.45}\n/* sections: availability windows */\n.slm-availlist{display:flex;flex-direction:column;gap:8px;margin:2px 0 12px}\n.slm-availrow{padding:10px;border:1px solid var(--slm-line);border-radius:10px;background:var(--slm-surface);transition:border-color .15s ease,opacity .15s ease}\n.slm-availrow.zone{background:color-mix(in srgb,var(--slm-surface) 82%,#000)}\n.slm-availrow.hidden{opacity:.62}.slm-availrow.closed{opacity:.82}\n.slm-availhead{display:flex;align-items:center;gap:8px}\n.slm-availlabel{display:flex;align-items:center;gap:5px;flex:1;min-width:0;font-size:12.5px;font-weight:800;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n.slm-availcaret{flex:none;color:var(--slm-muted);font-size:10px}\n.slm-availcount{flex:none;font-size:11px;font-weight:700;color:var(--slm-muted);font-variant-numeric:tabular-nums}\n.slm-availbadge{flex:none;font-size:9px;font-weight:800;letter-spacing:.04em;text-transform:uppercase;padding:2px 6px;border-radius:999px}\n.slm-availbadge.hidden{background:rgba(139,148,172,.18);color:#c2c9d8}\n.slm-availbadge.closed{background:rgba(244,183,64,.16);color:#f7ca6b}\n.slm-availselwrap{position:relative;flex:none;display:inline-flex}\n.slm-availmode{width:auto;max-width:190px;padding:6px 8px;font-size:11.5px;font-weight:700;cursor:pointer}\n.slm-availmode.on{border-color:var(--slm-accent);color:var(--slm-text)}\n.slm-availmode:disabled{opacity:.55;cursor:progress}\n.slm-availfollows{flex:none;padding:5px 10px;border:1px solid var(--slm-line);border-radius:7px;background:var(--slm-surface);color:var(--slm-muted);font-size:11px;font-weight:600;white-space:nowrap}\n.slm-availdetail{display:flex;align-items:center;gap:8px;margin-top:9px}\n.slm-availdetail .slm-input{flex:1}\n.slm-availpct{max-width:74px;flex:none!important}\n.slm-availpctlabel{font-size:11px;color:var(--slm-muted);font-weight:600;white-space:nowrap}\n.slm-availsummary{display:flex;align-items:center;gap:8px;padding:10px 12px;border:1px solid var(--slm-line);border-radius:9px;color:var(--slm-muted);font-size:12.5px}\n.slm-availdot{width:9px;height:9px;border-radius:50%;flex:none;background:#22a06b}.slm-availdot.warn{background:#f4b740}\n.slm-availcallout{display:flex;align-items:flex-start;gap:8px;margin-top:10px;padding:10px 12px;border:1px solid rgba(244,183,64,.45);border-radius:9px;background:rgba(244,183,64,.1)}\n.slm-availstar{flex:none;margin-top:1px;color:#f4b740;font-size:13px;line-height:1}\n.slm-availcallout p{font-size:11.5px;line-height:1.55;color:#f4d58a}.slm-availcallout b{color:#ffe4a3;font-weight:800}\n.slm-inspect-card{padding:16px;border:1px solid var(--slm-line);border-radius:12px;background:var(--slm-surface)}\n.slm-inspect-label{font-size:24px;font-weight:850;letter-spacing:-.02em;line-height:1.1}\n.slm-inspect-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:16px 20px;margin-top:18px}\n.slm-inspect-grid>div{min-width:0}.slm-inspect-grid span{display:block;color:var(--slm-muted);font-size:10px;\n text-transform:uppercase;letter-spacing:.08em}.slm-inspect-grid b{display:block;margin-top:4px;font-size:13px;line-height:1.35;overflow-wrap:anywhere}\n.slm:fullscreen{border-radius:0;min-height:100vh;background:var(--slm-bg)}\n.slm:fullscreen .slm-bar{padding:14px 22px}.slm:fullscreen .slm-kpi b{font-size:21px}.slm:fullscreen .slm-rail{width:360px}\n\n.slm.compact .slm-rail{width:100%;border-left:0;border-top:1px solid var(--slm-line);height:44%}\n.slm.compact .slm-body{flex-direction:column}\n.slm.compact .slm-bar{grid-template-columns:minmax(0,1fr) auto;gap:8px;padding:8px}\n.slm.compact .slm-modes{min-width:0}.slm.compact .slm-mode{padding-inline:11px}\n.slm.compact .slm-live{justify-self:end}.slm.compact .slm-bar-actions{grid-column:1/-1;justify-self:stretch}\n.slm.compact .slm-barbtn{flex:1;padding:6px 9px}.slm.compact .slm-kpis{grid-template-columns:repeat(4,minmax(0,1fr));gap:8px}\n.slm.compact .slm-kpi[data-kpi=\"buyers\"],.slm.compact .slm-kpi[data-kpi=\"active-holds\"],\n.slm.compact .slm-kpi[data-kpi=\"sold-pct\"],.slm.compact .slm-kpi[data-kpi=\"gross-sales\"]{display:none}\n@media (prefers-reduced-motion:reduce){\n .slm.live .slm-live-dot,.slm-feedrow,.slm-kpi.changed b,.slm-kpidelta{animation:none!important}\n .slm-liveevent,.slm-sectionrow{transition:none!important}\n}\n`;\n\nfunction injectStyle(): void {\n if (typeof document === 'undefined' || 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/** Resolve chrome tokens from a chart theme (dark war-room defaults). */\nfunction themeVars(theme: ChartTheme | undefined): Record<string, string> {\n const t = theme ?? {};\n return {\n '--slm-bg': t.background ?? '#0e1017',\n '--slm-surface': '#181b24',\n '--slm-text': '#eef1f7',\n '--slm-muted': '#8b93a7',\n '--slm-line': 'rgba(255,255,255,.09)',\n '--slm-accent': t.accent ?? '#6e7bff',\n '--slm-accent-ink': t.accentInk ?? '#ffffff',\n '--slm-font': \"-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif\",\n '--slm-radius': '14px',\n };\n}\n\nfunction relTime(at: number, now: number): string {\n const s = Math.max(0, Math.round((now - at) / 1000));\n if (s < 5) return 'just now';\n if (s < 60) return `${s}s ago`;\n const m = Math.round(s / 60);\n if (m < 60) return `${m}m ago`;\n return `${Math.round(m / 60)}h ago`;\n}\n\nfunction fmtMoney(amount: number, currency: string): string {\n try {\n return new Intl.NumberFormat(undefined, { style: 'currency', currency, maximumFractionDigits: 0 }).format(amount);\n } catch {\n return `${currency} ${Math.round(amount).toLocaleString()}`;\n }\n}\n\nfunction esc(value: unknown): string {\n return String(value ?? '')\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\"/g, '"')\n .replace(/'/g, ''');\n}\n\nexport class SeatManager {\n private readonly opts: SeatManagerOptions;\n private readonly api: ManageApi;\n private readonly key: string;\n private readonly keepLive: boolean;\n\n private host: HTMLElement;\n private root!: HTMLDivElement;\n private mapHost!: HTMLDivElement;\n private els: Record<string, HTMLElement> = {};\n\n private renderer: SeatmapRenderer | null = null;\n private doc: ChartDoc | null = null;\n private mode: SeatManagerMode;\n\n // label ⇄ id + status truth (backend speaks labels, engine speaks ids).\n private labelToId = new Map<string, string>();\n private labelToSeat = new Map<string, ExpandedSeat>();\n private allIds: string[] = [];\n private status = new Map<string, DoStatus>();\n private currency = 'USD';\n private authoritativeGrossRevenue = 0;\n private revenueStatus: SeatManagerTallies['revenueStatus'] = 'loading';\n private revenueRequest = 0;\n private revenueRefreshTimer: ReturnType<typeof setTimeout> | null = null;\n private controlRoomSnapshot: ControlRoomSnapshot | null = null;\n private trendWindowMinutes = 15;\n private heatEnabled = false;\n private followLive: boolean;\n private lastKpiValues = new Map<string, number>();\n private activeKpiDeltas = new Map<string, { text: string; down: boolean }>();\n\n // realtime socket\n private ws: WebSocket | null = null;\n private reconnectTimer: ReturnType<typeof setTimeout> | null = null;\n private attempt = 0;\n private closed = false;\n private ready = false;\n\n private feed: SeatManagerActivity[] = [];\n private feedTimer: ReturnType<typeof setInterval> | null = null;\n private toastTimer: ReturnType<typeof setTimeout> | null = null;\n private liveEventTimer: ReturnType<typeof setTimeout> | null = null;\n private kpiCleanupTimer: ReturnType<typeof setTimeout> | null = null;\n private followLiveTimer: ReturnType<typeof setTimeout> | null = null;\n private followSeatTimer: ReturnType<typeof setTimeout> | null = null;\n private releaseAt: number | null = null;\n private layoutObserver: ResizeObserver | null = null;\n private tokenExpiresAt: number | null = null;\n private tokenRefreshTimer: ReturnType<typeof setTimeout> | null = null;\n private tokenRefreshInFlight = false;\n private sectionByObject = new Map<string, string>();\n private sectionLabelById = new Map<string, string>();\n private sectionsBase: ReturnType<typeof computeSections> | null = null;\n // Sections mode (availability windows): organizer rules + the live effective\n // hidden/closed sets from the snapshot + WS (a timed/threshold rule fires DO-side).\n private availabilityRules: Record<string, AvailabilityRule> = {};\n private effectiveHidden = new Set<string>();\n private effectiveClosed = new Set<string>();\n private availabilitySaving = false;\n private lastSyncedAt: number | null = null;\n private blockedQuery = '';\n private blockedSection = '';\n private blockedResultLimit = 100;\n private unblockAllConfirmTimer: ReturnType<typeof setTimeout> | null = null;\n\n private readonly onFullscreenChange = (): void => {\n this.paintFullscreenButton();\n this.updateContainerLayout();\n this.renderer?.forceDraw();\n };\n\n private readonly onKeyDown = (event: KeyboardEvent): void => {\n if (event.metaKey || event.ctrlKey || event.altKey) return;\n const target = event.target as HTMLElement | null;\n if (target?.matches('input,select,textarea,[contenteditable=\"true\"]')) return;\n const key = event.key.toLowerCase();\n if (key === 'm') this.setMode('view');\n else if (key === 'i') this.setMode('inspect');\n else if (key === 'b') this.setMode('block');\n else if (key === 's') this.setMode('sections');\n else if (key === 'f') this.toggleFullscreen();\n else return;\n event.preventDefault();\n };\n\n private readonly onRailClick = (event: Event): void => {\n const target = event.target as HTMLElement | null;\n const sectionButton = target?.closest<HTMLElement>('[data-section-focus]');\n if (sectionButton?.dataset.sectionFocus) {\n this.locateSection(sectionButton.dataset.sectionFocus);\n return;\n }\n const feedButton = target?.closest<HTMLElement>('[data-feed-id]');\n if (feedButton?.dataset.feedId) this.locateActivity(feedButton.dataset.feedId);\n };\n\n constructor(options: SeatManagerOptions) {\n this.opts = options;\n this.key = options.eventKey;\n this.mode = options.mode ?? 'view';\n this.keepLive = options.keepLiveWhileHidden ?? true;\n this.followLive = options.followLive ?? false;\n this.currency = options.currency ?? 'USD';\n this.tokenExpiresAt = options.tokenExpiresAt ?? null;\n this.api = new ManageApi(options.apiBase ?? DEFAULT_API_BASE, options.token);\n this.host = resolveContainer(options.container);\n }\n\n /** Build the DOM, load the chart, subscribe to realtime, mount the board. */\n async render(): Promise<this> {\n injectStyle();\n this.buildChrome();\n try {\n const res = await this.api.chart(this.key);\n this.doc = res.doc;\n this.currency = res.event.currency ?? this.opts.currency ?? this.currency;\n const seats = expandChart(res.doc);\n for (const s of seats) {\n this.labelToId.set(s.label, s.id);\n this.labelToSeat.set(s.label, s);\n this.allIds.push(s.id);\n }\n this.buildRenderer();\n this.buildSectionOptions();\n const [, controlRoom] = await Promise.all([\n this.resnapshot(),\n this.refreshControlRoom().catch((err) => this.opts.onError?.(err)),\n this.refreshAvailability(),\n ]);\n // Restore recent activity through the view-safe control-room projection.\n // Older workers lack this field, so privileged/secret-key hosts retain the\n // legacy best-effort audit-log fallback during rolling upgrades.\n if (controlRoom?.activity) this.seedFeed(controlRoom.activity);\n else this.api.log(this.key, { limit: 24 }).then((page) => this.seedFeed(page.entries)).catch(() => {});\n this.connect();\n this.startFeedClock();\n this.ready = true;\n this.setMode(this.mode); // paint the right rail\n this.scheduleTokenRefresh();\n this.opts.onReady?.();\n } catch (err) {\n this.fail(err);\n }\n return this;\n }\n\n // ---- public API -----------------------------------------------------------\n\n setMode(mode: SeatManagerMode): void {\n const changed = mode !== this.mode;\n this.mode = mode;\n if (!this.renderer && this.doc) this.buildRenderer();\n else this.updateRendererInteraction();\n if (changed) this.renderer?.clearSelection();\n this.paintModeTabs();\n this.paintRail();\n this.applySectionCanvasTreatment();\n if (changed) this.opts.onModeChange?.(mode);\n }\n\n /** Toggle the normalized sales-velocity outline overlay without changing seat colors. */\n setHeatOverlay(enabled: boolean): void {\n this.heatEnabled = enabled;\n this.applyHeatOverlay();\n this.paintHeatButton();\n }\n\n /** Toggle opt-in camera following for new buyer hold/book events. */\n setFollowLive(enabled: boolean): void {\n const changed = this.followLive !== enabled;\n this.followLive = enabled;\n if (!enabled) {\n if (this.followLiveTimer) clearTimeout(this.followLiveTimer);\n if (this.followSeatTimer) clearTimeout(this.followSeatTimer);\n this.followLiveTimer = null;\n this.followSeatTimer = null;\n }\n this.paintFollowLiveButton();\n if (changed) this.opts.onFollowLiveChange?.(enabled);\n }\n\n /** Change the current-vs-previous sales window and refresh the private projection. */\n setTrendWindow(windowMinutes: number): Promise<ControlRoomSnapshot> {\n const normalized = Number.isFinite(windowMinutes) ? Math.floor(windowMinutes) : 15;\n this.trendWindowMinutes = Math.max(5, Math.min(60, normalized));\n this.paintTrendWindow();\n return this.refreshControlRoom();\n }\n\n async enterFullscreen(): Promise<void> {\n if (!this.root?.requestFullscreen || this.isFullscreen()) return;\n await this.root.requestFullscreen();\n this.root.focus({ preventScroll: true });\n }\n\n async exitFullscreen(): Promise<void> {\n if (typeof document === 'undefined' || !this.isFullscreen()) return;\n await document.exitFullscreen();\n }\n\n isFullscreen(): boolean {\n return typeof document !== 'undefined' && document.fullscreenElement === this.root;\n }\n\n private toggleFullscreen(): void {\n const request = this.isFullscreen() ? this.exitFullscreen() : this.enterFullscreen();\n void request.catch((err) => this.opts.onError?.(err));\n }\n\n /** Rotate the delegated credential without rebuilding DOM, canvas or socket. */\n setToken(token: string, expiresAt?: number): void {\n this.api.setToken(token);\n this.tokenExpiresAt = expiresAt ?? null;\n this.scheduleTokenRefresh();\n }\n\n private scheduleTokenRefresh(): void {\n if (this.tokenRefreshTimer) clearTimeout(this.tokenRefreshTimer);\n this.tokenRefreshTimer = null;\n const refresh = this.opts.onTokenRefresh;\n const expiresAt = this.tokenExpiresAt;\n if (this.closed || !refresh || !expiresAt || !Number.isFinite(expiresAt)) return;\n const remaining = expiresAt - Date.now();\n const lead = Math.min(120_000, Math.max(30_000, remaining * 0.2));\n const delay = Math.max(0, remaining - lead);\n this.tokenRefreshTimer = setTimeout(() => {\n this.tokenRefreshTimer = null;\n void this.rotateToken();\n }, delay);\n }\n\n private async rotateToken(): Promise<void> {\n if (this.closed || this.tokenRefreshInFlight || !this.opts.onTokenRefresh) return;\n this.tokenRefreshInFlight = true;\n try {\n const next = await this.opts.onTokenRefresh();\n if (!next?.token || !Number.isFinite(next.expiresAt)) throw new Error('invalid_token_refresh_result');\n this.setToken(next.token, next.expiresAt);\n } catch (err) {\n this.opts.onError?.(err);\n if (!this.closed) {\n this.tokenRefreshTimer = setTimeout(() => {\n this.tokenRefreshTimer = null;\n void this.rotateToken();\n }, 30_000);\n }\n } finally {\n this.tokenRefreshInFlight = false;\n }\n }\n\n /** Bulk block the given labels (or the current selection when omitted). */\n async block(labels?: string[], opts: { releaseAt?: number; reason?: string } = {}): Promise<void> {\n const targets = (labels ?? this.selectionLabels()).filter((l) => this.status.get(l) === 'free');\n if (!targets.length) return;\n const releaseAt = opts.releaseAt ?? this.releaseAt ?? undefined;\n // optimistic\n this.setSeatsLocal(targets, 'blocked');\n try {\n await this.api.block(this.key, targets, { ...opts, releaseAt });\n this.clearSelection();\n this.done('block', targets, releaseAt\n ? `Blocked ${targets.length} — auto-release ${new Date(releaseAt).toLocaleString()}.`\n : `Blocked ${targets.length} seat${targets.length === 1 ? '' : 's'}.`);\n } catch (err) {\n this.setSeatsLocal(targets, 'free'); // revert\n this.toastErr(err instanceof ManageApiError && err.status === 409\n ? 'Some seats were just taken. Try again.'\n : \"Couldn't block those seats.\");\n this.opts.onError?.(err);\n }\n }\n\n async unblock(labels?: string[]): Promise<void> {\n const targets = (labels ?? this.selectionLabels()).filter((l) => this.status.get(l) === 'blocked');\n if (!targets.length) return;\n this.setSeatsLocal(targets, 'free');\n try {\n await this.api.unblock(this.key, targets);\n this.clearSelection();\n this.done('unblock', targets, `Unblocked ${targets.length} seat${targets.length === 1 ? '' : 's'}.`);\n } catch (err) {\n this.setSeatsLocal(targets, 'blocked');\n this.toastErr(\"Couldn't unblock those seats.\");\n this.opts.onError?.(err);\n }\n }\n\n async unblockAll(): Promise<void> {\n const blocked = [...this.status.entries()].filter(([, s]) => s === 'blocked').map(([l]) => l);\n if (!blocked.length) return;\n this.setSeatsLocal(blocked, 'free');\n try {\n const res = await this.api.unblockAll(this.key);\n this.clearSelection();\n this.done('unblockAll', blocked, `Unblocked ${res.freed} seat${res.freed === 1 ? '' : 's'}.`);\n } catch (err) {\n await this.resnapshot();\n this.toastErr(\"Couldn't mark everything for sale.\");\n this.opts.onError?.(err);\n }\n }\n\n /** Cancel bookings (BOOKED → free), guarded by the original booking ref. */\n async cancelBooking(labels: string[], bookingRef: string): Promise<void> {\n const targets = labels.filter((l) => this.status.get(l) === 'booked');\n if (!targets.length || !bookingRef) return;\n this.setSeatsLocal(targets, 'free');\n try {\n await this.api.unbook(this.key, targets, bookingRef);\n this.clearSelection();\n this.done('cancelBooking', targets, `Cancelled ${targets.length} booking${targets.length === 1 ? '' : 's'}.`);\n } catch (err) {\n this.setSeatsLocal(targets, 'booked');\n this.toastErr(\"Couldn't cancel that booking. Check the reference.\");\n this.opts.onError?.(err);\n }\n }\n\n selectAll(): ExpandedSeat[] {\n const seats = this.renderer?.selectAllSelectable() ?? [];\n this.syncSelection();\n return seats;\n }\n\n selectSection(sectionId: string): ExpandedSeat[] {\n if (!this.renderer) return [];\n const seats = this.renderer.getSelectableInSection(sectionId);\n this.renderer.selectByLabels(seats.map((s) => s.label));\n this.syncSelection();\n return this.renderer.getSelection();\n }\n\n selectByLabels(labels: string[]): ExpandedSeat[] {\n const seats = this.renderer?.selectByLabels(labels) ?? [];\n this.syncSelection();\n return seats;\n }\n\n clearSelection(): void {\n this.renderer?.clearSelection();\n this.syncSelection();\n }\n\n getSelection(): ExpandedSeat[] {\n return this.renderer?.getSelection() ?? [];\n }\n\n getReport(): Promise<ReportResult> {\n return this.api.report(this.key).then((report) => {\n this.applyReportRevenue(report);\n return report;\n });\n }\n\n getControlRoomSnapshot(windowMinutes = this.trendWindowMinutes): Promise<ControlRoomSnapshot> {\n return this.setTrendWindow(windowMinutes);\n }\n\n getLog(opts: { limit?: number; before?: number } = {}): Promise<{ entries: LogEntry[]; nextBefore: number | null }> {\n return this.api.log(this.key, opts);\n }\n\n async setHoldTtl(ms: number | null): Promise<void> {\n try {\n await this.api.setHoldTtl(this.key, ms);\n this.done('setHoldTtl', [], ms ? `Checkout window set to ${Math.round(ms / 60000)} min.` : 'Checkout window reset.');\n } catch (err) {\n this.toastErr(\"Couldn't update the checkout window.\");\n this.opts.onError?.(err);\n }\n }\n\n /** M2 — box-office booking from free seats. Stubbed (route is session-only today). */\n boxBook(_labels: string[], _bookingRef: string): Promise<void> {\n this.toastErr('Box office ships in a later milestone.');\n return Promise.resolve();\n }\n\n zoomToFit(): void {\n this.renderer?.clearSectionFocus();\n this.renderer?.zoomToFit();\n }\n\n destroy(): void {\n this.closed = true;\n if (this.reconnectTimer) clearTimeout(this.reconnectTimer);\n if (this.feedTimer) clearInterval(this.feedTimer);\n if (this.toastTimer) clearTimeout(this.toastTimer);\n if (this.liveEventTimer) clearTimeout(this.liveEventTimer);\n if (this.kpiCleanupTimer) clearTimeout(this.kpiCleanupTimer);\n if (this.followLiveTimer) clearTimeout(this.followLiveTimer);\n if (this.followSeatTimer) clearTimeout(this.followSeatTimer);\n if (this.unblockAllConfirmTimer) clearTimeout(this.unblockAllConfirmTimer);\n if (this.revenueRefreshTimer) clearTimeout(this.revenueRefreshTimer);\n if (this.tokenRefreshTimer) clearTimeout(this.tokenRefreshTimer);\n this.layoutObserver?.disconnect();\n this.layoutObserver = null;\n this.root?.removeEventListener('keydown', this.onKeyDown);\n this.els.rail?.removeEventListener('click', this.onRailClick);\n if (typeof document !== 'undefined') document.removeEventListener('fullscreenchange', this.onFullscreenChange);\n if (this.ws) { try { this.ws.close(); } catch { /* ignore */ } this.ws = null; }\n this.renderer?.destroy();\n this.renderer = null;\n if (this.root && this.root.parentNode === this.host) this.host.removeChild(this.root);\n }\n\n // ---- renderer lifecycle ---------------------------------------------------\n\n private buildRenderer(): void {\n if (!this.doc) return;\n const block = this.mode === 'block';\n const inspect = this.mode === 'inspect';\n this.renderer = new SeatmapRenderer(this.mapHost, {\n manageMode: true,\n marqueeSelect: block,\n maxSelection: 1_000_000,\n selectableStatuses: block\n ? ['free', 'not_for_sale']\n : inspect ? ['free', 'held', 'booked', 'not_for_sale'] : [],\n currency: this.currency,\n onSelect: (seat) => this.handleSeatSelect(seat),\n onDeselect: () => this.syncSelection(),\n onMarquee: () => this.syncSelection(),\n onViewChange: () => this.updateZoomHint(),\n });\n this.renderer.setChart(this.doc);\n this.repaintAll();\n this.applyHeatOverlay();\n this.updateZoomHint();\n }\n\n private updateRendererInteraction(): void {\n const block = this.mode === 'block';\n const inspect = this.mode === 'inspect';\n this.renderer?.setManageInteraction({\n manageMode: true,\n marqueeSelect: block,\n maxSelection: 1_000_000,\n selectableStatuses: block\n ? ['free', 'not_for_sale']\n : inspect ? ['free', 'held', 'booked', 'not_for_sale'] : [],\n });\n this.updateZoomHint();\n }\n\n private handleSeatSelect(seat: ExpandedSeat): void {\n if (this.mode === 'inspect') {\n const others = this.getSelection()\n .filter((selected) => selected.id !== seat.id)\n .map((selected) => selected.id);\n if (others.length) this.renderer?.deselect(others);\n }\n this.syncSelection();\n }\n\n private repaintAll(): void {\n const r = this.renderer;\n if (!r) return;\n if (this.allIds.length) r.setStatus(this.allIds, 'free');\n const byStatus: Record<SeatStatus, string[]> = { free: [], held: [], booked: [], not_for_sale: [] };\n for (const [label, st] of this.status.entries()) {\n const id = this.labelToId.get(label);\n if (id) byStatus[toRenderStatus(st)].push(id);\n }\n (['held', 'booked', 'not_for_sale'] as SeatStatus[]).forEach((st) => {\n if (byStatus[st].length) r.setStatus(byStatus[st], st);\n });\n }\n\n // ---- realtime -------------------------------------------------------------\n\n private connect(): void {\n if (this.closed) return;\n let ws: WebSocket;\n try {\n ws = new WebSocket(this.api.socketUrl(this.key));\n } catch {\n this.scheduleReconnect();\n return;\n }\n this.ws = ws;\n ws.onopen = () => {\n this.attempt = 0;\n this.setLive(true);\n void this.resnapshot().then(() => this.scheduleRevenueRefresh(0));\n void this.refreshAvailability();\n };\n ws.onmessage = (e) => this.onMessage(e);\n ws.onclose = () => {\n if (this.ws === ws) this.ws = null;\n this.setLive(false);\n this.scheduleReconnect();\n };\n ws.onerror = () => { try { ws.close(); } catch { /* ignore */ } };\n }\n\n private scheduleReconnect(): void {\n if (this.closed || this.reconnectTimer) return;\n const delay = Math.min(1000 * 2 ** Math.min(this.attempt++, 5), 15000);\n this.reconnectTimer = setTimeout(() => { this.reconnectTimer = null; this.connect(); }, delay);\n }\n\n private onMessage(e: MessageEvent): void {\n let msg: unknown;\n try {\n msg = JSON.parse(typeof e.data === 'string' ? e.data : '');\n } catch {\n return;\n }\n if (!msg || typeof msg !== 'object') return;\n const m = msg as {\n type?: string;\n seats?: Record<string, string>;\n changes?: { label: string; status: string }[];\n shoppingSessions?: number;\n activeHolds?: number;\n hidden?: string[];\n closed?: string[];\n };\n // Availability state (effective hidden/closed) can ride any message and is the\n // dedicated payload of the 'hidden' broadcast — keep the Sections rail + canvas fresh.\n if (Array.isArray(m.hidden) || Array.isArray(m.closed)) {\n this.updateEffectiveAvailability(m.hidden, m.closed);\n }\n if (m.type === 'presence') {\n if (\n this.controlRoomSnapshot &&\n typeof m.shoppingSessions === 'number' &&\n typeof m.activeHolds === 'number'\n ) {\n this.controlRoomSnapshot = {\n ...this.controlRoomSnapshot,\n presence: { shoppingSessions: m.shoppingSessions, activeHolds: m.activeHolds },\n };\n this.lastSyncedAt = Date.now();\n this.recomputeTallies();\n this.paintMonitorInsights();\n this.opts.onControlRoom?.(this.controlRoomSnapshot);\n }\n return;\n }\n if (m.type === 'hidden') return;\n if (m.seats && typeof m.seats === 'object') {\n this.applySnapshot(m.seats);\n } else if (Array.isArray(m.changes)) {\n const ids: string[] = [];\n const groups = new Map<string, { labels: string[]; verb: string; status: DoStatus }>();\n for (const ch of m.changes) {\n const st = (['free', 'held', 'booked', 'blocked'].includes(ch.status) ? ch.status : 'free') as DoStatus;\n const prev = this.status.get(ch.label) ?? 'free';\n if (prev === st) continue;\n this.status.set(ch.label, st);\n const id = this.labelToId.get(ch.label);\n if (id) { this.renderer?.setStatus([id], toRenderStatus(st)); ids.push(id); }\n const verb = this.verbFor(prev, st);\n const groupKey = `${verb}:${st}`;\n const group = groups.get(groupKey) ?? { labels: [], verb, status: st };\n group.labels.push(ch.label);\n groups.set(groupKey, group);\n }\n for (const group of groups.values()) {\n const activity = this.pushActivity(group.labels, group.verb, group.status);\n if (activity) this.paintSpatialActivity(activity);\n }\n if (ids.length) {\n this.lastSyncedAt = Date.now();\n this.afterPaint();\n }\n this.recomputeTallies();\n if (ids.length) this.scheduleRevenueRefresh();\n }\n }\n\n private async resnapshot(): Promise<void> {\n try {\n const objs = await this.api.objects(this.key);\n this.applySnapshot(objs.seats);\n this.updateEffectiveAvailability(objs.hidden, objs.closed);\n } catch {\n /* transient — the delta stream keeps us fresh */\n }\n }\n\n private applySnapshot(seats: Record<string, string>): void {\n const next = new Map<string, DoStatus>();\n for (const [label, st] of Object.entries(seats)) {\n next.set(label, (['free', 'held', 'booked', 'blocked'].includes(st) ? st : 'free') as DoStatus);\n }\n this.status = next;\n this.lastSyncedAt = Date.now();\n this.repaintAll();\n this.afterPaint();\n this.recomputeTallies();\n }\n\n /** Optimistic local write shared by organizer actions. Paint and tally once,\n * even when an arena-sized operation changes hundreds of seats. */\n private setSeatsLocal(labels: string[], st: DoStatus): void {\n const ids: string[] = [];\n for (const label of labels) {\n this.status.set(label, st);\n const id = this.labelToId.get(label);\n if (id) ids.push(id);\n }\n if (ids.length) this.renderer?.setStatus(ids, toRenderStatus(st));\n this.afterPaint();\n this.recomputeTallies();\n }\n\n /** Keep the canvas painting on hidden/occluded tabs (war-room second monitor). */\n private afterPaint(): void {\n if (this.keepLive && typeof document !== 'undefined' && document.hidden) {\n this.renderer?.forceDraw();\n }\n }\n\n private activityColor(status: DoStatus): string {\n return status === 'held' ? '#f4b740'\n : status === 'booked' ? '#22a06b'\n : status === 'blocked' ? '#8b94ac'\n : '#6e7bff';\n }\n\n private sectionsForLabels(labels: string[]): { ids: string[]; labels: string[] } {\n const ids = new Set<string>();\n for (const label of labels) {\n const seat = this.labelToSeat.get(label);\n if (!seat) continue;\n const sectionId = this.sectionByObject.get(seat.rowId);\n if (sectionId && sectionId !== UNGROUPED_ID) ids.add(sectionId);\n }\n const sectionIds = [...ids];\n return {\n ids: sectionIds,\n labels: sectionIds.map((id) => this.sectionLabelById.get(id) ?? id),\n };\n }\n\n private pulseSeatLabels(labels: string[], status: DoStatus): void {\n const color = this.activityColor(status);\n for (const label of labels.slice(0, MAX_LIVE_SEAT_PULSES)) {\n const id = this.labelToId.get(label);\n if (id) this.renderer?.flashSeat(id, color);\n }\n }\n\n /** Render one grouped realtime operation at the right semantic zoom level. */\n private paintSpatialActivity(activity: SeatManagerActivity): void {\n const sectionIds = activity.sectionIds ?? this.sectionsForLabels(activity.labels).ids;\n const focused = this.renderer?.getFocusedSection() ?? null;\n const followable = this.followLive && sectionIds.length === 1 &&\n (activity.status === 'held' || activity.status === 'booked');\n\n if (followable && focused === sectionIds[0]) {\n this.pulseSeatLabels(activity.labels, activity.status);\n return;\n }\n if (followable) {\n if (this.followLiveTimer) clearTimeout(this.followLiveTimer);\n if (this.followSeatTimer) clearTimeout(this.followSeatTimer);\n this.followLiveTimer = setTimeout(() => {\n this.followLiveTimer = null;\n this.renderer?.focusSection(sectionIds[0]);\n this.followSeatTimer = setTimeout(() => {\n this.followSeatTimer = null;\n this.pulseSeatLabels(activity.labels, activity.status);\n }, 520);\n }, 220);\n return;\n }\n\n if (!focused && sectionIds.length) {\n const color = this.activityColor(activity.status);\n for (const sectionId of sectionIds.slice(0, MAX_LIVE_SECTION_PULSES)) {\n this.renderer?.flashSection(sectionId, color);\n }\n return;\n }\n if (!sectionIds.length || (focused && sectionIds.includes(focused))) {\n this.pulseSeatLabels(activity.labels, activity.status);\n }\n }\n\n private locateSection(sectionId: string): void {\n this.renderer?.focusSection(sectionId);\n }\n\n private locateActivity(activityId: string): void {\n const activity = this.feed.find((item) => item.id === activityId);\n if (!activity) return;\n const sectionIds = activity.sectionIds ?? this.sectionsForLabels(activity.labels).ids;\n if (this.followSeatTimer) clearTimeout(this.followSeatTimer);\n if (sectionIds.length === 1) {\n this.locateSection(sectionIds[0]);\n this.followSeatTimer = setTimeout(() => {\n this.followSeatTimer = null;\n this.pulseSeatLabels(activity.labels, activity.status);\n }, 520);\n return;\n }\n this.zoomToFit();\n this.followSeatTimer = setTimeout(() => {\n this.followSeatTimer = null;\n if (sectionIds.length) {\n const color = this.activityColor(activity.status);\n for (const sectionId of sectionIds.slice(0, MAX_LIVE_SECTION_PULSES)) {\n this.renderer?.flashSection(sectionId, color);\n }\n } else {\n this.pulseSeatLabels(activity.labels, activity.status);\n }\n }, 280);\n }\n\n private showLiveEvent(activity: SeatManagerActivity): void {\n const element = this.els.liveevent;\n if (!element) return;\n const sections = activity.sectionLabels ?? [];\n const place = sections.length === 1 ? sections[0]\n : sections.length > 1 ? `${sections.length} sections`\n : activity.label;\n const noun = activity.count === 1 ? 'seat' : 'seats';\n element.innerHTML = `<span class=\"slm-liveeventdot\" style=\"background:${this.activityColor(activity.status)}\"></span>\n <span class=\"slm-liveeventcopy\">${esc(place)} · ${activity.count.toLocaleString()} ${noun} ${esc(activity.verb)}</span>\n <span class=\"slm-liveeventhint\">Live</span>`;\n element.classList.add('on');\n if (this.liveEventTimer) clearTimeout(this.liveEventTimer);\n this.liveEventTimer = setTimeout(() => {\n this.liveEventTimer = null;\n element.classList.remove('on');\n element.innerHTML = '';\n }, 2800);\n }\n\n // ---- tallies + feed -------------------------------------------------------\n\n private applyReportRevenue(report: ReportResult): void {\n this.authoritativeGrossRevenue = report.report.byCategory.reduce(\n (sum, row) => sum + (Number.isFinite(row.bookedRevenue) ? row.bookedRevenue : 0),\n 0,\n );\n this.revenueStatus = 'current';\n this.recomputeTallies();\n }\n\n private async refreshControlRoom(): Promise<ControlRoomSnapshot> {\n const request = ++this.revenueRequest;\n try {\n const snapshot = await this.api.controlRoom(this.key, this.trendWindowMinutes);\n if (request === this.revenueRequest) {\n this.controlRoomSnapshot = snapshot;\n this.lastSyncedAt = Date.now();\n this.authoritativeGrossRevenue = snapshot.revenue.gross;\n this.currency = snapshot.currency;\n this.revenueStatus = 'current';\n this.recomputeTallies();\n this.applyHeatOverlay();\n this.paintMonitorInsights();\n this.opts.onControlRoom?.(snapshot);\n }\n return snapshot;\n } catch (err) {\n if (request === this.revenueRequest) {\n this.revenueStatus = 'stale';\n this.recomputeTallies();\n }\n throw err;\n }\n }\n\n private scheduleRevenueRefresh(delay = 140): void {\n this.revenueStatus = 'stale';\n this.recomputeTallies();\n if (this.revenueRefreshTimer) clearTimeout(this.revenueRefreshTimer);\n this.revenueRefreshTimer = setTimeout(() => {\n this.revenueRefreshTimer = null;\n void this.refreshControlRoom().catch((err) => this.opts.onError?.(err));\n }, delay);\n }\n\n private recomputeTallies(): void {\n const t: SeatManagerTallies = {\n free: 0, held: 0, booked: 0, blocked: 0,\n total: this.allIds.length, capacityPct: 0, sellThroughPct: 0,\n grossRevenue: this.authoritativeGrossRevenue,\n revenueStatus: this.revenueStatus,\n currency: this.currency,\n };\n // free = total − (held+booked+blocked); the snapshot only carries non-free.\n let nonFree = 0;\n for (const st of this.status.values()) {\n t[st] += 1;\n if (st !== 'free') nonFree += 1;\n }\n t.free = Math.max(0, t.total - nonFree);\n t.capacityPct = t.total ? Math.round((t.booked / t.total) * 100) : 0;\n const sellable = t.total - t.blocked;\n t.sellThroughPct = sellable > 0 ? Math.round((t.booked / sellable) * 100) : 0;\n this.paintKpis(t);\n if (this.mode === 'view') {\n this.paintLegend(t);\n this.paintMonitorInsights();\n } else if (this.mode === 'inspect') this.renderInspectRail(this.getSelection());\n else if (this.mode === 'block') this.paintSelBar(this.getSelection());\n this.opts.onTallies?.(t);\n }\n\n private verbFor(prev: DoStatus, next: DoStatus): string {\n if (next === 'held') return 'held';\n if (next === 'booked') return 'booked';\n if (next === 'blocked') return 'blocked';\n if (next === 'free') return prev === 'blocked' ? 'unblocked' : prev === 'booked' ? 'cancelled' : 'released';\n return next;\n }\n\n private pushActivity(labels: string[], verb: string, status: DoStatus, at = Date.now()): SeatManagerActivity | null {\n const label = labels[0];\n if (!label) return null;\n const sections = this.sectionsForLabels(labels);\n const item: SeatManagerActivity = {\n id: `${label}:${at}:${Math.random().toString(36).slice(2, 6)}`,\n at,\n label,\n labels: [...labels],\n count: labels.length,\n verb,\n status,\n sectionIds: sections.ids,\n sectionLabels: sections.labels,\n };\n this.feed.unshift(item);\n if (this.feed.length > FEED_CAP) this.feed.length = FEED_CAP;\n if (this.mode === 'view') this.paintFeed();\n this.showLiveEvent(item);\n this.opts.onActivity?.(item);\n return item;\n }\n\n private seedFeed(entries: ControlRoomActivityEntry[]): void {\n const verbByAction: Record<string, string> = {\n hold: 'held', book: 'booked', release: 'released', expire: 'expired', block: 'blocked', unblock: 'unblocked',\n unbook: 'cancelled',\n };\n const stByAction: Record<string, DoStatus> = {\n hold: 'held', book: 'booked', release: 'free', expire: 'free', block: 'blocked', unblock: 'free', unbook: 'free',\n };\n for (const e of entries) {\n const label = e.labels[0];\n if (!label) continue;\n const sections = this.sectionsForLabels(e.labels);\n const item: SeatManagerActivity = {\n id: `log:${e.id}`,\n at: e.at,\n label,\n labels: [...e.labels],\n count: e.labels.length,\n verb: verbByAction[e.action] ?? e.action,\n status: stByAction[e.action] ?? 'free',\n sectionIds: sections.ids,\n sectionLabels: sections.labels,\n };\n this.feed.push(item);\n this.opts.onActivity?.(item);\n }\n this.feed.sort((a, b) => b.at - a.at);\n if (this.feed.length > FEED_CAP) this.feed.length = FEED_CAP;\n if (this.mode === 'view') this.paintFeed();\n }\n\n private startFeedClock(): void {\n this.feedTimer = setInterval(() => {\n if (this.mode === 'view') {\n this.paintFeed();\n this.paintMonitorInsights();\n }\n }, 10000);\n }\n\n // ---- selection ------------------------------------------------------------\n\n private selectionLabels(): string[] {\n return this.getSelection().map((s) => s.label);\n }\n\n private syncSelection(): void {\n const seats = this.getSelection();\n if (this.mode === 'block') this.paintSelBar(seats);\n else if (this.mode === 'inspect') this.renderInspectRail(seats);\n this.opts.onSelectionChange?.(seats);\n }\n\n // ---- DOM: chrome ----------------------------------------------------------\n\n private buildChrome(): void {\n const root = document.createElement('div');\n root.className = 'slm';\n root.tabIndex = 0;\n root.setAttribute('role', 'region');\n root.setAttribute('aria-label', 'SeatLayer live control room');\n const vars = themeVars(this.opts.theme);\n for (const [k, v] of Object.entries(vars)) root.style.setProperty(k, v);\n root.innerHTML = `\n <div class=\"slm-bar\">\n <div class=\"slm-modes\" data-ref=\"modes\" role=\"tablist\" aria-label=\"Manager tools\">\n <button class=\"slm-mode\" role=\"tab\" data-mode=\"view\" title=\"Monitor (M)\" aria-keyshortcuts=\"M\">Monitor</button>\n <button class=\"slm-mode\" role=\"tab\" data-mode=\"inspect\" title=\"Inspect (I)\" aria-keyshortcuts=\"I\">Inspect</button>\n <button class=\"slm-mode\" role=\"tab\" data-mode=\"block\" title=\"Block (B)\" aria-keyshortcuts=\"B\">Block</button>\n <button class=\"slm-mode\" role=\"tab\" data-mode=\"sections\" title=\"Sections (S)\" aria-keyshortcuts=\"S\">Sections</button>\n </div>\n <span class=\"slm-live\"><span class=\"slm-live-dot\"></span><span data-ref=\"livetext\">CONNECTING</span></span>\n <div class=\"slm-bar-actions\">\n <button class=\"slm-barbtn follow\" data-ref=\"follow\" aria-pressed=\"false\"\n title=\"Stay on the current map view unless enabled\">Follow live</button>\n <button class=\"slm-barbtn\" data-ref=\"heat\" aria-pressed=\"false\"\n aria-label=\"Sales momentum overlay off\"\n title=\"Highlight sections selling fastest in the selected time window\">Sales momentum</button>\n <button class=\"slm-barbtn\" data-ref=\"fullscreen\" title=\"Full screen (F)\" aria-keyshortcuts=\"F\">Full screen</button>\n </div>\n <div class=\"slm-kpis\" data-ref=\"kpis\"></div>\n </div>\n <div class=\"slm-body\">\n <div class=\"slm-map\">\n <div class=\"slm-map-host\" data-ref=\"maphost\"></div>\n <div class=\"slm-zoomhint\" data-ref=\"zoomhint\">Zoom in to marquee-select</div>\n <div class=\"slm-liveevent\" data-ref=\"liveevent\" role=\"status\" aria-live=\"polite\"></div>\n <div class=\"slm-hud\"><button class=\"slm-hud-chip\" data-ref=\"zfit\">Zoom to fit</button></div>\n </div>\n <aside class=\"slm-rail\"><div class=\"slm-railscroll\" data-ref=\"rail\"></div></aside>\n </div>\n <div class=\"slm-toast\" data-ref=\"toast\"></div>\n `;\n this.host.appendChild(root);\n this.root = root;\n this.updateContainerLayout();\n if (typeof ResizeObserver !== 'undefined') {\n this.layoutObserver = new ResizeObserver(() => this.updateContainerLayout());\n this.layoutObserver.observe(root);\n }\n const ref = (n: string) => root.querySelector(`[data-ref=\"${n}\"]`) as HTMLElement;\n this.mapHost = ref('maphost') as HTMLDivElement;\n this.els = {\n modes: ref('modes'), livetext: ref('livetext'), kpis: ref('kpis'),\n follow: ref('follow'), heat: ref('heat'), fullscreen: ref('fullscreen'),\n zoomhint: ref('zoomhint'), liveevent: ref('liveevent'), rail: ref('rail'), toast: ref('toast'), zfit: ref('zfit'),\n };\n this.els.modes.querySelectorAll('[data-mode]').forEach((b) =>\n b.addEventListener('click', () => this.setMode((b as HTMLElement).dataset.mode as SeatManagerMode)));\n this.els.zfit.addEventListener('click', () => this.zoomToFit());\n this.els.follow.addEventListener('click', () => this.setFollowLive(!this.followLive));\n this.els.heat.addEventListener('click', () => this.setHeatOverlay(!this.heatEnabled));\n this.els.fullscreen.addEventListener('click', () => this.toggleFullscreen());\n root.addEventListener('keydown', this.onKeyDown);\n this.els.rail.addEventListener('click', this.onRailClick);\n document.addEventListener('fullscreenchange', this.onFullscreenChange);\n this.paintModeTabs();\n this.paintFollowLiveButton();\n this.paintHeatButton();\n this.paintFullscreenButton();\n }\n\n private updateContainerLayout(): void {\n const width = this.root?.getBoundingClientRect().width || this.host.clientWidth;\n this.root?.classList.toggle('compact', width > 0 && width < 800);\n }\n\n private sectionOptions: { id: string; label: string }[] = [];\n\n private buildSectionOptions(): void {\n if (!this.doc) return;\n try {\n const secs = computeSections(this.doc);\n this.sectionsBase = secs;\n this.sectionOptions = [];\n this.sectionByObject = new Map(secs.objectToSection);\n this.sectionLabelById.clear();\n for (const s of secs.sections) {\n this.sectionOptions.push({ id: s.id, label: s.label });\n this.sectionLabelById.set(s.id, s.label);\n }\n if (secs.ungrouped) {\n this.sectionOptions.push({ id: UNGROUPED_ID, label: secs.ungrouped.label });\n this.sectionLabelById.set(UNGROUPED_ID, secs.ungrouped.label);\n }\n } catch { /* no sections */ }\n }\n\n private paintModeTabs(): void {\n this.els.modes?.querySelectorAll('[data-mode]').forEach((b) => {\n const el = b as HTMLElement;\n const active = el.dataset.mode === this.mode;\n el.classList.toggle('on', active);\n el.setAttribute('aria-selected', String(active));\n el.tabIndex = active ? 0 : -1;\n });\n this.root?.classList.toggle('block-mode', this.mode === 'block');\n }\n\n private paintFollowLiveButton(): void {\n const button = this.els.follow;\n if (!button) return;\n button.classList.toggle('on', this.followLive);\n button.setAttribute('aria-pressed', String(this.followLive));\n button.setAttribute('title', this.followLive\n ? 'Following new buyer holds and bookings. Turn off to keep the current view.'\n : 'Stay on the current map view. Enable to follow new buyer holds and bookings.');\n }\n\n private paintHeatButton(): void {\n const button = this.els.heat;\n if (!button) return;\n button.classList.toggle('on', this.heatEnabled);\n button.setAttribute('aria-pressed', String(this.heatEnabled));\n button.setAttribute('aria-label', `Sales momentum overlay ${this.heatEnabled ? 'on' : 'off'}`);\n button.setAttribute('title', `${this.heatEnabled ? 'Hide' : 'Highlight'} sections selling fastest in the selected time window`);\n button.textContent = 'Sales momentum';\n this.paintMomentumHelp();\n }\n\n private paintMomentumHelp(): void {\n const help = this.els.rail?.querySelector('[data-ref=\"momentumhelp\"]') as HTMLElement | null;\n if (!help) return;\n help.hidden = !this.heatEnabled;\n const copy = help.querySelector('[data-ref=\"momentumcopy\"]');\n if (!copy) return;\n const hasRecentSales = this.controlRoomSnapshot?.velocity.bySection.some((row) => row.netBooked > 0);\n copy.textContent = hasRecentSales\n ? 'Warmer sections have more completed bookings, adjusted for section size. Holds and viewers are not counted.'\n : `No completed bookings in the last ${this.trendWindowMinutes} minutes.`;\n }\n\n private paintFullscreenButton(): void {\n if (!this.els.fullscreen) return;\n this.els.fullscreen.textContent = this.isFullscreen() ? 'Exit full screen' : 'Full screen';\n }\n\n private paintTrendWindow(): void {\n this.els.rail?.querySelectorAll('[data-window]').forEach((button) => {\n const value = Number((button as HTMLElement).dataset.window);\n button.classList.toggle('on', value === this.trendWindowMinutes);\n });\n }\n\n private setLive(on: boolean): void {\n this.root?.classList.toggle('live', on);\n if (this.els.livetext) this.els.livetext.textContent = on ? 'LIVE' : 'RECONNECTING';\n this.paintMonitorInsights();\n }\n\n private updateZoomHint(): void {\n const hint = this.els.zoomhint;\n if (!hint) return;\n const show = this.mode === 'block' && this.renderer?.getRung?.() !== 'seats';\n hint.classList.toggle('on', !!show);\n }\n\n private formatKpiDelta(key: string, delta: number, currency: string): string {\n const sign = delta > 0 ? '+' : '−';\n const absolute = Math.abs(delta);\n if (key === 'gross-sales') return `${sign}${fmtMoney(absolute, currency)}`;\n if (key === 'sold-pct') return `${sign}${absolute.toLocaleString()}pt`;\n return `${sign}${absolute.toLocaleString()}`;\n }\n\n private paintKpis(t: SeatManagerTallies): void {\n if (!this.els.kpis) return;\n const rev = t.revenueStatus === 'current' ? fmtMoney(t.grossRevenue, t.currency) : '—';\n const presence = this.controlRoomSnapshot?.presence;\n const items: { key: string; raw: number | null; n: string; l: string; dot?: string }[] = [\n { key: 'sold-seats', raw: t.booked, n: t.booked.toLocaleString(), l: 'Sold seats', dot: '#22a06b' },\n { key: 'held-seats', raw: t.held, n: t.held.toLocaleString(), l: 'Held seats', dot: '#f4b740' },\n { key: 'buyers', raw: presence?.shoppingSessions ?? null, n: presence ? presence.shoppingSessions.toLocaleString() : '—', l: 'Buyers' },\n { key: 'active-holds', raw: presence?.activeHolds ?? null, n: presence ? presence.activeHolds.toLocaleString() : '—', l: 'Active holds' },\n { key: 'free-seats', raw: t.free, n: t.free.toLocaleString(), l: 'Free seats', dot: '#6e7bff' },\n { key: 'blocked', raw: t.blocked, n: t.blocked.toLocaleString(), l: 'Blocked', dot: '#8b94ac' },\n { key: 'sold-pct', raw: t.capacityPct, n: `${t.capacityPct}%`, l: 'Sold' },\n { key: 'gross-sales', raw: t.revenueStatus === 'current' ? t.grossRevenue : null, n: rev, l: 'Gross sales' },\n ];\n let hasChanges = false;\n this.els.kpis.innerHTML = items.map((item) => {\n const previous = this.lastKpiValues.get(item.key);\n const changed = item.raw != null && previous != null && item.raw !== previous;\n const delta = changed ? item.raw! - previous! : 0;\n if (changed) {\n hasChanges = true;\n this.activeKpiDeltas.set(item.key, {\n text: this.formatKpiDelta(item.key, delta, t.currency),\n down: delta < 0,\n });\n }\n if (item.raw != null) this.lastKpiValues.set(item.key, item.raw);\n const activeDelta = this.activeKpiDeltas.get(item.key);\n return `<div class=\"slm-kpi${activeDelta ? ' changed' : ''}\" data-kpi=\"${item.key}\">\n <b>${item.dot ? `<span class=\"dot\" style=\"background:${item.dot}\"></span>` : ''}${item.n}</b><span>${item.l}</span>\n ${activeDelta ? `<span class=\"slm-kpidelta${activeDelta.down ? ' down' : ''}\">${activeDelta.text}</span>` : ''}\n </div>`;\n }).join('');\n if (hasChanges) {\n // The map above has already adopted the new values, so detect the rendered\n // change markers directly and remove their accessibility footprint after\n // the visual cue completes.\n if (this.kpiCleanupTimer) clearTimeout(this.kpiCleanupTimer);\n this.kpiCleanupTimer = setTimeout(() => {\n this.kpiCleanupTimer = null;\n this.activeKpiDeltas.clear();\n this.els.kpis?.querySelectorAll('.slm-kpidelta').forEach((element) => element.remove());\n this.els.kpis?.querySelectorAll('.slm-kpi.changed').forEach((element) => element.classList.remove('changed'));\n }, 1500);\n }\n }\n\n // ---- DOM: rails -----------------------------------------------------------\n\n private paintRail(): void {\n if (this.mode === 'view') this.renderViewRail();\n else if (this.mode === 'inspect') this.renderInspectRail(this.getSelection());\n else if (this.mode === 'sections') this.renderSectionsRail();\n else this.renderBlockRail();\n this.updateZoomHint();\n }\n\n private renderViewRail(): void {\n this.els.rail.innerHTML = `\n <p class=\"slm-eyebrow\">Monitor</p>\n <p class=\"slm-hint\">Read-only. Inventory, buyer presence and sales movement update on the same live board.</p>\n <div class=\"slm-health\" data-ref=\"presence\"></div>\n <div class=\"slm-legend\" data-ref=\"legend\"></div>\n <div class=\"slm-sectionhead\">\n <div><p class=\"slm-eyebrow\">Section performance</p><p class=\"slm-note\">Exact booked revenue · net sales velocity</p></div>\n <div class=\"slm-windows\" aria-label=\"Sales velocity window\">\n ${[5, 15, 30, 60].map((window) => `<button class=\"slm-window\" data-window=\"${window}\">${window}m</button>`).join('')}\n </div>\n </div>\n <div class=\"slm-momentumhelp\" data-ref=\"momentumhelp\" ${this.heatEnabled ? '' : 'hidden'}>\n <div class=\"slm-momentumscale\"><span>Warm</span><span class=\"slm-momentumgradient\"></span><span>Hot</span></div>\n <p class=\"slm-momentumcopy\" data-ref=\"momentumcopy\"></p>\n </div>\n <div class=\"slm-sectionlist\" data-ref=\"sections\"></div>\n <p class=\"slm-eyebrow\">Activity</p>\n <div class=\"slm-feed\" data-ref=\"feed\"></div>\n `;\n this.els.presence = this.els.rail.querySelector('[data-ref=\"presence\"]') as HTMLElement;\n this.els.legend = this.els.rail.querySelector('[data-ref=\"legend\"]') as HTMLElement;\n this.els.sections = this.els.rail.querySelector('[data-ref=\"sections\"]') as HTMLElement;\n this.els.feed = this.els.rail.querySelector('[data-ref=\"feed\"]') as HTMLElement;\n this.els.rail.querySelectorAll('[data-window]').forEach((button) => button.addEventListener('click', () => {\n const windowMinutes = Number((button as HTMLElement).dataset.window);\n void this.setTrendWindow(windowMinutes).catch((err) => this.opts.onError?.(err));\n }));\n this.recomputeTallies();\n this.paintMonitorInsights();\n this.paintTrendWindow();\n this.paintMomentumHelp();\n this.paintFeed();\n }\n\n private paintMonitorInsights(): void {\n if (this.mode !== 'view') return;\n const snapshot = this.controlRoomSnapshot;\n if (this.els.presence) {\n const connected = this.root?.classList.contains('live');\n const sync = this.lastSyncedAt ? relTime(this.lastSyncedAt, Date.now()) : 'waiting';\n this.els.presence.innerHTML = `\n <div class=\"slm-healthitem\"><b>${snapshot ? snapshot.presence.shoppingSessions.toLocaleString() : '—'}</b><span>Buyer sessions</span></div>\n <div class=\"slm-healthitem\"><b>${snapshot ? snapshot.presence.activeHolds.toLocaleString() : '—'}</b><span>Active holds</span></div>\n <div class=\"slm-healthitem\"><b>${connected ? 'Healthy' : 'Reconnecting'}</b><span>Live connection</span></div>\n <div class=\"slm-healthitem\"><b>${sync}</b><span>Last sync</span></div>`;\n }\n if (!this.els.sections) return;\n if (!snapshot) {\n this.els.sections.innerHTML = '<div class=\"slm-empty\">Loading authoritative section metrics…</div>';\n return;\n }\n const velocity = new Map(snapshot.velocity.bySection.map((row) => [row.sectionId, row]));\n const rows = [...snapshot.revenue.bySection].sort((a, b) => {\n const av = velocity.get(a.sectionId)?.netBooked ?? 0;\n const bv = velocity.get(b.sectionId)?.netBooked ?? 0;\n return bv - av || b.bookedRevenue - a.bookedRevenue;\n });\n this.els.sections.innerHTML = rows.length ? rows.map((row) => {\n const speed = velocity.get(row.sectionId);\n const net = speed?.netBooked ?? 0;\n const netLabel = `${net > 0 ? '+' : ''}${net}`;\n const trend = speed?.trend === 'rising' || speed?.trend === 'cooling' ? speed.trend : 'steady';\n return `<button type=\"button\" class=\"slm-sectionrow\" data-section-focus=\"${esc(row.sectionId)}\" title=\"Focus ${esc(row.sectionLabel)} on the map\">\n <span class=\"slm-sectiontop\"><span>${esc(row.sectionLabel)}</span><span>${fmtMoney(row.bookedRevenue, snapshot.currency)}</span></span>\n <span class=\"slm-sectionmeta\"><span>${row.booked.toLocaleString()}/${row.total.toLocaleString()} sold · ${netLabel} in ${snapshot.velocity.windowMinutes}m</span><span class=\"slm-trend ${trend}\">${trend}</span><span class=\"slm-sectionlocate\">Locate</span></span>\n </button>`;\n }).join('') : '<div class=\"slm-empty\">No section metrics are available for this chart.</div>';\n this.paintTrendWindow();\n this.paintMomentumHelp();\n }\n\n private applyHeatOverlay(): void {\n const snapshot = this.controlRoomSnapshot;\n if (!this.heatEnabled || !snapshot) {\n this.renderer?.setSectionHeat(null);\n return;\n }\n const capacity = new Map(snapshot.revenue.bySection.map((row) => [row.sectionId, Math.max(1, row.total)]));\n const rates = snapshot.velocity.bySection.map((row) => ({\n sectionId: row.sectionId,\n rate: Math.max(0, row.netBooked) / (capacity.get(row.sectionId) ?? 1) / snapshot.velocity.windowMinutes,\n }));\n const max = Math.max(0, ...rates.map((row) => row.rate));\n const scores: Record<string, number> = {};\n for (const row of rates) scores[row.sectionId] = max > 0 ? Math.sqrt(row.rate / max) : 0;\n this.renderer?.setSectionHeat(scores);\n }\n\n private renderInspectRail(seats: ExpandedSeat[]): void {\n const seat = seats[seats.length - 1];\n if (!seat) {\n this.els.rail.innerHTML = `\n <p class=\"slm-eyebrow\">Inspect seats</p>\n <p class=\"slm-hint\">Select a seat to see its availability and sales context. Nothing changes in this view.</p>\n <div class=\"slm-empty\">Select a seat on the map.</div>`;\n return;\n }\n const status = this.status.get(seat.label) ?? 'free';\n const statusLabel: Record<DoStatus, string> = { free: 'Free', held: 'Held', booked: 'Booked', blocked: 'Blocked' };\n const sectionId = this.sectionByObject.get(seat.rowId) ?? UNGROUPED_ID;\n const sectionLabel = this.sectionLabelById.get(sectionId) ?? 'Other seats';\n const category = this.doc?.categories.find((item) => item.key === seat.categoryKey);\n const sectionMetric = this.controlRoomSnapshot?.revenue.bySection.find((row) => row.sectionId === sectionId);\n const object = this.doc?.objects.find((item) => item.id === seat.rowId);\n const location = object?.type === 'row'\n ? { label: 'Row', value: object.label }\n : object?.type === 'table'\n ? { label: 'Table', value: object.label }\n : seat.kind === 'booth'\n ? { label: 'Type', value: 'Booth' }\n : null;\n const itemKind = seat.kind === 'booth' ? 'Booth' : 'Seat';\n this.els.rail.innerHTML = `\n <p class=\"slm-eyebrow\">${itemKind} details</p>\n <p class=\"slm-hint\">Live availability and section performance.</p>\n <div class=\"slm-inspect-card\">\n <div class=\"slm-inspect-label\">${esc(seat.label)}</div>\n <div class=\"slm-inspect-grid\">\n <div><span>Status</span><b>${statusLabel[status]}</b></div>\n <div><span>Section</span><b>${esc(sectionLabel)}</b></div>\n ${location ? `<div><span>${location.label}</span><b>${esc(location.value)}</b></div>` : ''}\n <div><span>Category</span><b>${esc(category?.label ?? seat.categoryKey)}</b></div>\n <div><span>Sold in section</span><b>${sectionMetric ? `${sectionMetric.booked} of ${sectionMetric.total}` : '—'}</b></div>\n <div><span>Section revenue</span><b>${sectionMetric && this.controlRoomSnapshot ? fmtMoney(sectionMetric.bookedRevenue, this.controlRoomSnapshot.currency) : '—'}</b></div>\n </div>\n </div>`;\n }\n\n // ---- sections: availability windows --------------------------------------\n\n /** Pull the organizer's availability rules (event:view). Called on load and on\n * every WS (re)connect, mirroring how the other panels re-hydrate. `closed` is\n * deterministic from the rules; `hidden` (which folds in already-due timed /\n * threshold windows) comes from the snapshot + WS effective set. */\n private async refreshAvailability(): Promise<void> {\n try {\n const res = await this.withAuthRetry(() => this.api.availability(this.key));\n this.availabilityRules = res.rules ?? {};\n this.effectiveClosed = new Set(this.closedIdsFromRules(this.availabilityRules));\n if (this.mode === 'sections') this.renderSectionsRail();\n this.applySectionCanvasTreatment();\n } catch (err) {\n this.opts.onError?.(err);\n }\n }\n\n /** Run a token-authed op; on a 401 re-mint via onTokenRefresh and retry once. */\n private async withAuthRetry<T>(op: () => Promise<T>): Promise<T> {\n try {\n return await op();\n } catch (err) {\n if (err instanceof ManageApiError && err.status === 401 && this.opts.onTokenRefresh && !this.tokenRefreshInFlight) {\n await this.rotateToken();\n return op();\n }\n throw err;\n }\n }\n\n private closedIdsFromRules(rules: Record<string, AvailabilityRule>): string[] {\n return Object.entries(rules).filter(([, r]) => r.mode === 'closed').map(([id]) => id);\n }\n\n /** Adopt a new effective hidden/closed set (from a snapshot or WS broadcast) and\n * repaint the rail + canvas when it actually moves. */\n private updateEffectiveAvailability(hidden?: string[], closed?: string[]): void {\n let changed = false;\n if (Array.isArray(hidden)) {\n this.effectiveHidden = new Set(hidden.filter((x): x is string => typeof x === 'string'));\n changed = true;\n }\n if (Array.isArray(closed)) {\n this.effectiveClosed = new Set(closed.filter((x): x is string => typeof x === 'string'));\n changed = true;\n }\n if (!changed) return;\n if (this.mode === 'sections') this.renderSectionsRail();\n this.applySectionCanvasTreatment();\n }\n\n /** Canvas read of the availability state: dim hidden sections to a whisper,\n * half-light closed sections, leave open sections normal. Only in Sections mode;\n * cleared in every other tool. */\n private applySectionCanvasTreatment(): void {\n if (!this.renderer) return;\n if (this.mode === 'sections') {\n this.renderer.setDimmedSections([...this.effectiveHidden]);\n this.renderer.setClosedSections([...this.effectiveClosed]);\n } else {\n this.renderer.setDimmedSections(null);\n this.renderer.setClosedSections(null);\n }\n }\n\n /** Zone-grouped render tree: each zone header then its sections (which follow the\n * zone window), then loose sections + the ungrouped bucket. Effective hidden /\n * closed come from the live sets, rules from the organizer map. */\n private buildSectionRows(): { rows: SectionRow[]; hiddenSections: number; closedSections: number } {\n const base = this.sectionsBase;\n if (!base) return { rows: [], hiddenSections: 0, closedSections: 0 };\n const zones = this.doc?.zones ?? [];\n const byZone = new Map<string, SectionNode[]>();\n const loose: SectionNode[] = [];\n for (const s of base.sections) {\n if (s.zone && zones.some((z) => z.id === s.zone)) {\n const list = byZone.get(s.zone) ?? [];\n list.push(s);\n byZone.set(s.zone, list);\n } else {\n loose.push(s);\n }\n }\n const rows: SectionRow[] = [];\n let hiddenSections = 0;\n let closedSections = 0;\n const push = (\n kind: 'zone' | 'section',\n node: { id: string; label: string; seatCount: number; seatLabels: string[] },\n zoneRuled: boolean,\n parentClosed = false,\n ): void => {\n const rule = this.availabilityRules[node.id] ?? null;\n const effClosed = this.effectiveClosed.has(node.id) || parentClosed;\n // A closed section stays visible-but-off-sale, never counted as hidden.\n const effHidden = this.effectiveHidden.has(node.id) || (zoneRuled && !effClosed);\n if (kind === 'section' && effHidden) hiddenSections += 1;\n if (kind === 'section' && effClosed) closedSections += 1;\n rows.push({\n kind, id: node.id, label: node.label, seatCount: node.seatCount, seatLabels: node.seatLabels,\n rule, hidden: effHidden, closed: effClosed, followsZone: kind === 'section' && zoneRuled,\n });\n };\n for (const z of zones) {\n const secs = byZone.get(z.id);\n if (!secs || !secs.length) continue;\n const zoneNode = {\n id: z.id,\n label: z.label || 'Zone',\n seatCount: secs.reduce((sum, s) => sum + s.seatCount, 0),\n seatLabels: secs.flatMap((s) => s.seatLabels),\n };\n const zoneRuled = !!this.availabilityRules[z.id];\n const zoneClosed = this.availabilityRules[z.id]?.mode === 'closed';\n push('zone', zoneNode, false);\n for (const s of secs) push('section', s, zoneRuled, zoneClosed);\n }\n for (const s of loose) push('section', s, false);\n if (base.ungrouped) {\n const u = base.ungrouped;\n push('section', { id: UNGROUPED_ID, label: u.label, seatCount: u.seatCount, seatLabels: u.seatLabels }, false);\n }\n return { rows, hiddenSections, closedSections };\n }\n\n private renderSectionsRail(): void {\n const { rows, hiddenSections, closedSections } = this.buildSectionRows();\n if (!rows.length) {\n this.els.rail.innerHTML = `\n <p class=\"slm-eyebrow\">Availability windows</p>\n <p class=\"slm-hint\">Draw sections or zones in the designer to schedule availability per area. This chart has none yet.</p>\n <div class=\"slm-empty\">No sections on this chart.</div>`;\n return;\n }\n const parts: string[] = [];\n if (hiddenSections) parts.push(`${hiddenSections} hidden`);\n if (closedSections) parts.push(`${closedSections} closed`);\n const summary = parts.length ? parts.join(' · ') : 'All sections open and on sale';\n const warn = hiddenSections > 0 || closedSections > 0;\n this.els.rail.innerHTML = `\n <p class=\"slm-eyebrow\">Availability windows</p>\n <p class=\"slm-hint\">Control when each zone or section goes on sale. Keep it hidden, reveal it at a set time, or <b>auto-reveal once the rest sells past a threshold</b>. Hidden seats vanish for buyers; closed seats stay on the map (flat grey) but can't be bought.</p>\n <div class=\"slm-availlist\" data-ref=\"availlist\">${rows.map((row) => this.sectionRowHtml(row)).join('')}</div>\n <div class=\"slm-availsummary\">\n <span class=\"slm-availdot${warn ? ' warn' : ''}\"></span>\n <span>${esc(summary)}</span>\n </div>\n <div class=\"slm-availcallout\">\n <span class=\"slm-availstar\" aria-hidden=\"true\">✦</span>\n <p><b>Auto-reveal at % sold</b> is our differentiator — demand-triggered release: the balcony opens itself the moment the stalls hit the threshold. Neither seats.io nor Ticketmaster ships this.</p>\n </div>`;\n this.wireSectionRail();\n this.applySectionCanvasTreatment();\n }\n\n private sectionRowHtml(row: SectionRow): string {\n const mode = availabilityModeOf(row.rule);\n const cls = `slm-availrow${row.kind === 'zone' ? ' zone' : ''}${row.hidden ? ' hidden' : ''}${row.closed ? ' closed' : ''}`;\n const disabled = this.availabilitySaving ? ' disabled' : '';\n const option = (value: AvailabilityMode, text: string): string =>\n `<option value=\"${value}\"${mode === value ? ' selected' : ''}>${text}</option>`;\n const control = row.followsZone\n ? '<span class=\"slm-availfollows\">Follows zone</span>'\n : `<span class=\"slm-availselwrap\">\n <select class=\"slm-select slm-availmode${mode !== 'open' ? ' on' : ''}\" data-avail-id=\"${esc(row.id)}\"${disabled} aria-label=\"Availability for ${esc(row.label)}\">\n ${option('open', 'Open — on sale')}\n ${option('closed', 'Closed — visible, not on sale')}\n ${option('hidden', 'Hidden — off the buyer map')}\n ${option('timed', 'Reveal at a time')}\n ${option('threshold', 'Auto-reveal at % sold')}\n </select>\n </span>`;\n let detail = '';\n if (!row.followsZone && mode === 'timed') {\n const value = row.rule?.revealAt ? esc(toLocalInput(row.rule.revealAt)) : '';\n detail = `<div class=\"slm-availdetail\">\n <input type=\"datetime-local\" class=\"slm-input\" data-avail-reveal=\"${esc(row.id)}\" value=\"${value}\"${disabled} aria-label=\"Reveal time for ${esc(row.label)}\" />\n </div>`;\n } else if (!row.followsZone && mode === 'threshold') {\n const pct = row.rule?.thresholdPct ?? 80;\n detail = `<div class=\"slm-availdetail\">\n <span class=\"slm-availpctlabel\">Reveal at</span>\n <input type=\"number\" min=\"1\" max=\"100\" class=\"slm-input slm-availpct\" data-avail-pct=\"${esc(row.id)}\" value=\"${esc(pct)}\"${disabled} aria-label=\"Percent sold to reveal ${esc(row.label)}\" />\n <span class=\"slm-availpctlabel\">% sold</span>\n </div>`;\n }\n const badge = row.closed\n ? '<span class=\"slm-availbadge closed\">Closed</span>'\n : row.hidden ? '<span class=\"slm-availbadge hidden\">Hidden</span>' : '';\n const caret = row.kind === 'zone' ? `<span class=\"slm-availcaret\" aria-hidden=\"true\">${row.hidden ? '▸' : '▾'}</span>` : '';\n return `<div class=\"${cls}\">\n <div class=\"slm-availhead\">\n <span class=\"slm-availlabel\">${caret}${esc(row.label)}</span>\n ${badge}\n <span class=\"slm-availcount\">${row.seatCount.toLocaleString()}</span>\n ${control}\n </div>\n ${detail}\n </div>`;\n }\n\n private wireSectionRail(): void {\n const rail = this.els.rail;\n if (!rail) return;\n rail.querySelectorAll<HTMLSelectElement>('[data-avail-id]').forEach((select) => {\n select.addEventListener('change', () => this.setSectionMode(select.dataset.availId!, select.value as AvailabilityMode));\n });\n rail.querySelectorAll<HTMLInputElement>('[data-avail-reveal]').forEach((input) => {\n input.addEventListener('change', () => {\n const ms = new Date(input.value).getTime();\n if (Number.isFinite(ms)) this.setSectionRulePatch(input.dataset.availReveal!, { revealAt: ms });\n });\n });\n rail.querySelectorAll<HTMLInputElement>('[data-avail-pct]').forEach((input) => {\n input.addEventListener('change', () => {\n const pct = Math.max(1, Math.min(100, Number(input.value) || 0));\n this.setSectionRulePatch(input.dataset.availPct!, { thresholdPct: pct });\n });\n });\n }\n\n /** Change one row's availability mode. A zone rule subsumes its child section\n * rules, so those are dropped from the map (the zone window is the truth). */\n private setSectionMode(id: string, mode: AvailabilityMode): void {\n const row = this.buildSectionRows().rows.find((r) => r.id === id);\n const seatLabels = row?.seatLabels ?? this.availabilityRules[id]?.labels ?? [];\n const next = { ...this.availabilityRules };\n const rule = availabilityRuleForMode(mode, seatLabels, this.availabilityRules[id]);\n if (rule) next[id] = rule;\n else delete next[id];\n if (row?.kind === 'zone' && this.sectionsBase) {\n for (const s of this.sectionsBase.sections) if (s.zone === id) delete next[s.id];\n }\n void this.persistAvailability(next);\n }\n\n /** Edit a timed reveal time / threshold percent on an existing row rule. */\n private setSectionRulePatch(id: string, patch: Partial<AvailabilityRule>): void {\n const cur = this.availabilityRules[id];\n if (!cur) return;\n const row = this.buildSectionRows().rows.find((r) => r.id === id);\n const labels = row?.seatLabels ?? cur.labels ?? [];\n void this.persistAvailability({ ...this.availabilityRules, [id]: { ...cur, ...patch, labels } });\n }\n\n /** Optimistically adopt the new rules, then reconcile with the server-cleaned\n * map + effective hidden/closed sets. Rolls back the rules on failure. */\n private async persistAvailability(next: Record<string, AvailabilityRule>): Promise<void> {\n const prev = this.availabilityRules;\n this.availabilityRules = next;\n this.availabilitySaving = true;\n if (this.mode === 'sections') this.renderSectionsRail();\n try {\n const res = await this.withAuthRetry(() => this.api.setAvailability(this.key, next));\n this.availabilityRules = res.rules;\n this.effectiveHidden = new Set(res.hidden);\n this.effectiveClosed = new Set(this.closedIdsFromRules(res.rules));\n this.availabilitySaving = false;\n if (this.mode === 'sections') this.renderSectionsRail();\n this.applySectionCanvasTreatment();\n } catch (err) {\n this.availabilityRules = prev;\n this.availabilitySaving = false;\n if (this.mode === 'sections') this.renderSectionsRail();\n this.toastErr(\"Couldn't update availability. Try again.\");\n this.opts.onError?.(err);\n }\n }\n\n private paintLegend(t: SeatManagerTallies): void {\n if (!this.els.legend) return;\n this.els.legend.innerHTML = LEGEND.map((l) =>\n `<div class=\"slm-legrow\"><span class=\"slm-legdot\" style=\"background:${l.color}\"></span>\n <span class=\"slm-leglabel\">${l.label}</span><span class=\"slm-legcount\">${t[l.key].toLocaleString()}</span></div>`).join('');\n }\n\n private paintFeed(): void {\n if (!this.els.feed) return;\n if (!this.feed.length) { this.els.feed.innerHTML = `<div class=\"slm-empty\">No activity yet — it'll stream in live.</div>`; return; }\n const now = Date.now();\n const color: Record<DoStatus, string> = { free: '#6e7bff', held: '#f4b740', booked: '#22a06b', blocked: '#8b94ac' };\n this.els.feed.innerHTML = this.feed.map((a) => {\n const extra = a.count > 1 ? ` +${a.count - 1}` : '';\n const sections = a.sectionLabels ?? [];\n const sectionCopy = sections.length === 1 ? sections[0] : sections.length > 1 ? `${sections.length} sections` : '';\n return `<button type=\"button\" class=\"slm-feedrow\" data-feed-id=\"${esc(a.id)}\" title=\"Locate this activity on the map\">\n <span class=\"slm-feeddot\" style=\"background:${color[a.status]}\"></span>\n <span class=\"slm-feedtext\">${sectionCopy ? `<span class=\"slm-feedsection\">${esc(sectionCopy)}</span>` : ''}${a.count === 1 ? 'Seat' : 'Seats'} <b>${esc(a.label)}${extra}</b> ${esc(a.verb)}</span>\n <span class=\"slm-feedmeta\"><span class=\"slm-feedtime\">${relTime(a.at, now)}</span><span class=\"slm-feedlocate\">Locate</span></span>\n </button>`;\n }).join('');\n }\n\n private renderBlockRail(): void {\n const cats = this.doc?.categories ?? [];\n const catChips = cats.map((c) =>\n `<button class=\"slm-chip\" type=\"button\" data-cat=\"${esc(c.key)}\" aria-pressed=\"false\">\n <span class=\"dot\" style=\"background:${esc(c.color ?? '#6e7bff')}\"></span>\n <span>${esc(c.label ?? c.key)}</span>\n <span class=\"slm-chipcount\" data-cat-count>0</span>\n <span class=\"slm-chipcheck\" aria-hidden=\"true\">✓</span>\n </button>`).join('');\n const sectionField = this.sectionOptions.length\n ? `<div class=\"slm-field\"><label>Select a whole section</label>\n <select class=\"slm-select\" data-ref=\"section\"><option value=\"\">Choose a section…</option>\n ${this.sectionOptions.map((s) => `<option value=\"${esc(s.id)}\">${esc(s.label)}</option>`).join('')}</select></div>`\n : '';\n const blockedSectionOptions = this.sectionOptions.map((s) =>\n `<option value=\"${esc(s.id)}\">${esc(s.label)}</option>`).join('');\n this.els.rail.innerHTML = `\n <p class=\"slm-eyebrow\">Block & unblock</p>\n <p class=\"slm-hint\">Drag a box on the map to marquee-select, ⌘A for all, or pick a category/section. Booked and held inventory is never actionable here.</p>\n <div class=\"slm-selbar\" aria-live=\"polite\"><span class=\"slm-selnum\" data-ref=\"selnum\">0</span><span class=\"slm-sellabel\" data-ref=\"selmeta\">selected</span></div>\n <div class=\"slm-row\">\n <button class=\"slm-btn\" data-ref=\"doblock\" disabled>Block</button>\n <button class=\"slm-btn ghost\" data-ref=\"dounblock\" disabled>Put back on sale</button>\n </div>\n <div class=\"slm-row\">\n <button class=\"slm-btn ghost\" data-ref=\"selall\">Select all</button>\n <button class=\"slm-btn ghost\" data-ref=\"clearsel\">Clear</button>\n </div>\n <p class=\"slm-eyebrow\" style=\"margin-top:8px\">Select by category</p>\n <p class=\"slm-selecthelp\">Choose one or more. A checked category is selected; click it again to remove it.</p>\n <div class=\"slm-chiprow\">${catChips || '<span class=\"slm-empty\">No categories.</span>'}</div>\n ${sectionField}\n <div class=\"slm-field\">\n <label>Auto-release blocks at (optional)</label>\n <input type=\"datetime-local\" class=\"slm-input\" data-ref=\"release\" />\n <p class=\"slm-note\" data-ref=\"releasenote\">Leave empty to block permanently.</p>\n </div>\n <section class=\"slm-blocked\" aria-labelledby=\"slm-blocked-title\">\n <div class=\"slm-blockedhead\">\n <p class=\"slm-eyebrow\" id=\"slm-blocked-title\">Blocked inventory</p>\n <span class=\"slm-blockedtotal\"><b data-ref=\"blockedcount\">0</b> out of sale</span>\n </div>\n <p class=\"slm-selecthelp\">Find blocked seats, select only the ones you need, then use “Put back on sale”.</p>\n <div class=\"slm-blockedtools\">\n <input type=\"search\" class=\"slm-input\" data-ref=\"blockedsearch\" placeholder=\"Find seat, row or category\" aria-label=\"Search blocked seats\" />\n <select class=\"slm-select\" data-ref=\"blockedsection\" aria-label=\"Filter blocked seats by section\">\n <option value=\"\">All sections</option>${blockedSectionOptions}\n </select>\n </div>\n <div class=\"slm-blockedsummary\">\n <span data-ref=\"blockedshowing\">No blocked seats</span>\n <button type=\"button\" class=\"slm-linkbtn\" data-ref=\"selblocked\" disabled>Select results</button>\n </div>\n <div class=\"slm-blockedlist\" data-ref=\"blockedlist\"></div>\n </section>\n <div class=\"slm-field\">\n <button class=\"slm-btn ghost\" data-ref=\"markall\" style=\"width:100%\" disabled>Put all blocked seats on sale</button>\n <p class=\"slm-note slm-allnote\" data-ref=\"markallnote\">For a full reset only. You will be asked to confirm.</p>\n </div>\n `;\n const r = (n: string) => this.els.rail.querySelector(`[data-ref=\"${n}\"]`) as HTMLElement;\n this.els.selnum = r('selnum'); this.els.doblock = r('doblock'); this.els.dounblock = r('dounblock');\n this.els.selmeta = r('selmeta'); this.els.blockedcount = r('blockedcount');\n this.els.blockedshowing = r('blockedshowing'); this.els.blockedlist = r('blockedlist');\n this.els.selblocked = r('selblocked'); this.els.markall = r('markall'); this.els.markallnote = r('markallnote');\n r('doblock').addEventListener('click', () => void this.block());\n r('dounblock').addEventListener('click', () => void this.unblock());\n r('selall').addEventListener('click', () => this.selectAll());\n r('clearsel').addEventListener('click', () => this.clearSelection());\n r('markall').addEventListener('click', () => this.confirmUnblockAll());\n this.els.rail.querySelectorAll('[data-cat]').forEach((b) =>\n b.addEventListener('click', () => this.toggleCategory((b as HTMLElement).dataset.cat!)));\n const sectionSel = this.els.rail.querySelector('[data-ref=\"section\"]') as HTMLSelectElement | null;\n sectionSel?.addEventListener('change', () => { if (sectionSel.value) { this.selectSection(sectionSel.value); sectionSel.value = ''; } });\n const blockedSearch = r('blockedsearch') as HTMLInputElement;\n const blockedSection = r('blockedsection') as HTMLSelectElement;\n blockedSearch.value = this.blockedQuery;\n blockedSection.value = this.blockedSection;\n blockedSearch.addEventListener('input', () => {\n this.blockedQuery = blockedSearch.value;\n this.blockedResultLimit = 100;\n this.paintBlockedInventory();\n });\n blockedSection.addEventListener('change', () => {\n this.blockedSection = blockedSection.value;\n this.blockedResultLimit = 100;\n this.paintBlockedInventory();\n });\n r('selblocked').addEventListener('click', () => {\n this.toggleLabels(this.filteredBlockedSeats().map((seat) => seat.label));\n });\n r('blockedlist').addEventListener('click', (event) => {\n const target = event.target as HTMLElement;\n const seatButton = target.closest<HTMLElement>('[data-blocked-label]');\n if (seatButton?.dataset.blockedLabel) this.toggleLabels([seatButton.dataset.blockedLabel]);\n else if (target.closest('[data-blocked-more]')) {\n this.blockedResultLimit += 100;\n this.paintBlockedInventory();\n }\n });\n const rel = r('release') as HTMLInputElement;\n rel.addEventListener('change', () => {\n const ms = rel.value ? new Date(rel.value).getTime() : NaN;\n this.releaseAt = Number.isFinite(ms) && ms > Date.now() ? ms : null;\n const note = r('releasenote');\n note.textContent = this.releaseAt\n ? `New blocks auto-release ${new Date(this.releaseAt).toLocaleString()}.`\n : rel.value ? 'Pick a time in the future.' : 'Leave empty to block permanently.';\n });\n this.paintSelBar(this.getSelection());\n }\n\n private toggleCategory(catKey: string): void {\n const labels: string[] = [];\n for (const [label, seat] of this.labelToSeat.entries()) {\n if (seat.categoryKey === catKey && this.isBlockSelectable(label)) labels.push(label);\n }\n this.toggleLabels(labels);\n }\n\n /** A category/filter is a real toggle: add the missing seats, or remove the\n * whole group when every eligible seat in it is already selected. */\n private toggleLabels(labels: string[]): void {\n if (!this.renderer) return;\n const eligible = labels.filter((label) => this.labelToSeat.has(label) && this.isBlockSelectable(label));\n if (!eligible.length) return;\n const selected = new Set(this.selectionLabels());\n const allSelected = eligible.every((label) => selected.has(label));\n if (allSelected) {\n const ids = eligible.map((label) => this.labelToId.get(label)).filter((id): id is string => Boolean(id));\n this.renderer.deselect(ids);\n } else {\n this.renderer.selectByLabels(eligible);\n }\n this.syncSelection();\n }\n\n private isBlockSelectable(label: string): boolean {\n const status = this.status.get(label) ?? 'free';\n return status === 'free' || status === 'blocked';\n }\n\n private paintSelBar(seats: ExpandedSeat[]): void {\n if (!this.els.selnum) return;\n this.els.selnum.textContent = seats.length.toLocaleString();\n const freeCount = seats.filter((s) => (this.status.get(s.label) ?? 'free') === 'free').length;\n const blockedCount = seats.filter((s) => this.status.get(s.label) === 'blocked').length;\n this.els.selmeta.textContent = seats.length\n ? `${freeCount.toLocaleString()} available · ${blockedCount.toLocaleString()} blocked`\n : 'selected';\n const blockButton = this.els.doblock as HTMLButtonElement;\n const unblockButton = this.els.dounblock as HTMLButtonElement;\n blockButton.disabled = freeCount === 0;\n unblockButton.disabled = blockedCount === 0;\n blockButton.textContent = freeCount ? `Block ${freeCount.toLocaleString()}` : 'Block selected';\n unblockButton.textContent = blockedCount ? `Put ${blockedCount.toLocaleString()} on sale` : 'Put back on sale';\n this.paintCategoryControls(seats);\n this.paintBlockedInventory();\n }\n\n private paintCategoryControls(seats: ExpandedSeat[]): void {\n const selected = new Set(seats.map((seat) => seat.label));\n this.els.rail?.querySelectorAll<HTMLButtonElement>('[data-cat]').forEach((button) => {\n const catKey = button.dataset.cat;\n const labels: string[] = [];\n for (const [label, seat] of this.labelToSeat.entries()) {\n if (seat.categoryKey === catKey && this.isBlockSelectable(label)) labels.push(label);\n }\n const picked = labels.filter((label) => selected.has(label)).length;\n const full = labels.length > 0 && picked === labels.length;\n const partial = picked > 0 && !full;\n button.disabled = labels.length === 0;\n button.classList.toggle('on', full);\n button.classList.toggle('partial', partial);\n button.setAttribute('aria-pressed', full ? 'true' : partial ? 'mixed' : 'false');\n button.setAttribute('title', full\n ? `Remove all ${labels.length.toLocaleString()} seats in this category from the selection`\n : partial\n ? `Select the remaining ${(labels.length - picked).toLocaleString()} seats in this category`\n : `Select all ${labels.length.toLocaleString()} seats in this category`);\n const count = button.querySelector<HTMLElement>('[data-cat-count]');\n if (count) count.textContent = picked ? `${picked.toLocaleString()}/${labels.length.toLocaleString()}` : labels.length.toLocaleString();\n });\n }\n\n private filteredBlockedSeats(): ExpandedSeat[] {\n const query = this.blockedQuery.trim().toLocaleLowerCase();\n const seats: ExpandedSeat[] = [];\n for (const [label, seat] of this.labelToSeat.entries()) {\n if (this.status.get(label) !== 'blocked') continue;\n const sectionId = this.sectionByObject.get(seat.rowId) ?? UNGROUPED_ID;\n if (this.blockedSection && sectionId !== this.blockedSection) continue;\n if (query) {\n const category = this.doc?.categories.find((item) => item.key === seat.categoryKey)?.label ?? seat.categoryKey;\n const section = this.sectionLabelById.get(sectionId) ?? 'Other seats';\n const object = this.doc?.objects.find((item) => item.id === seat.rowId);\n const objectLabel = object?.type === 'row' || object?.type === 'table' ? object.label : '';\n const haystack = `${label} ${category} ${section} ${objectLabel}`.toLocaleLowerCase();\n if (!haystack.includes(query)) continue;\n }\n seats.push(seat);\n }\n return seats.sort((a, b) => a.label.localeCompare(b.label, undefined, { numeric: true, sensitivity: 'base' }));\n }\n\n private paintBlockedInventory(): void {\n if (!this.els.blockedlist) return;\n const allBlocked = [...this.status.entries()].filter(([, status]) => status === 'blocked').length;\n const filtered = this.filteredBlockedSeats();\n const visible = filtered.slice(0, this.blockedResultLimit);\n const selected = new Set(this.selectionLabels());\n const selectedResults = filtered.filter((seat) => selected.has(seat.label)).length;\n const allResultsSelected = filtered.length > 0 && selectedResults === filtered.length;\n this.els.blockedcount.textContent = allBlocked.toLocaleString();\n this.els.blockedshowing.textContent = filtered.length\n ? `Showing ${visible.length.toLocaleString()} of ${filtered.length.toLocaleString()}`\n : allBlocked ? 'No matches' : 'No blocked seats';\n const selectResults = this.els.selblocked as HTMLButtonElement;\n selectResults.disabled = filtered.length === 0;\n selectResults.textContent = allResultsSelected\n ? `Remove ${filtered.length.toLocaleString()} results`\n : `Select ${filtered.length.toLocaleString()} results`;\n\n this.els.blockedlist.innerHTML = visible.length ? visible.map((seat) => {\n const sectionId = this.sectionByObject.get(seat.rowId) ?? UNGROUPED_ID;\n const section = this.sectionLabelById.get(sectionId) ?? 'Other seats';\n const category = this.doc?.categories.find((item) => item.key === seat.categoryKey)?.label ?? seat.categoryKey;\n const isSelected = selected.has(seat.label);\n return `<button type=\"button\" class=\"slm-blockeditem${isSelected ? ' on' : ''}\" data-blocked-label=\"${esc(seat.label)}\" aria-pressed=\"${isSelected}\">\n <span class=\"slm-blockedcheck\" aria-hidden=\"true\">✓</span>\n <span class=\"slm-blockedcopy\"><span class=\"slm-blockedlabel\">${esc(seat.label)}</span>\n <span class=\"slm-blockedmeta\">${esc(section)} · ${esc(category)}</span></span>\n </button>`;\n }).join('') + (filtered.length > visible.length\n ? `<button type=\"button\" class=\"slm-blockedmore\" data-blocked-more>Show 100 more</button>` : '')\n : `<div class=\"slm-blockedempty\">${allBlocked\n ? 'No blocked seats match this search or section.'\n : 'No seats are blocked. Newly blocked seats will appear here.'}</div>`;\n\n const markAll = this.els.markall as HTMLButtonElement;\n const armed = markAll.dataset.confirm === 'true';\n markAll.disabled = allBlocked === 0;\n markAll.textContent = armed\n ? `Confirm: put all ${allBlocked.toLocaleString()} on sale`\n : `Put all ${allBlocked.toLocaleString()} blocked seats on sale`;\n }\n\n private confirmUnblockAll(): void {\n const button = this.els.markall as HTMLButtonElement;\n if (!button || button.disabled) return;\n if (button.dataset.confirm === 'true') {\n this.resetUnblockAllConfirm();\n void this.unblockAll();\n return;\n }\n button.dataset.confirm = 'true';\n button.classList.add('danger');\n this.els.markallnote.textContent = 'This changes every blocked seat. Click the red button again to confirm.';\n this.paintBlockedInventory();\n if (this.unblockAllConfirmTimer) clearTimeout(this.unblockAllConfirmTimer);\n this.unblockAllConfirmTimer = setTimeout(() => this.resetUnblockAllConfirm(), 6000);\n }\n\n private resetUnblockAllConfirm(): void {\n if (this.unblockAllConfirmTimer) clearTimeout(this.unblockAllConfirmTimer);\n this.unblockAllConfirmTimer = null;\n const button = this.els.markall as HTMLButtonElement | undefined;\n if (!button) return;\n delete button.dataset.confirm;\n button.classList.remove('danger');\n if (this.els.markallnote) this.els.markallnote.textContent = 'For a full reset only. You will be asked to confirm.';\n this.paintBlockedInventory();\n }\n\n // ---- toast / done / fail --------------------------------------------------\n\n private done(action: SeatManagerActionResult['action'], labels: string[], msg: string): void {\n this.toastOk(msg);\n if (labels.length) {\n const activity = action === 'block'\n ? this.pushActivity(labels, 'blocked', 'blocked')\n : action === 'unblock' || action === 'unblockAll'\n ? this.pushActivity(labels, 'unblocked', 'free')\n : action === 'cancelBooking'\n ? this.pushActivity(labels, 'cancelled', 'free')\n : null;\n if (activity) this.paintSpatialActivity(activity);\n }\n if (action !== 'setHoldTtl') this.scheduleRevenueRefresh(0);\n this.opts.onActionComplete?.({ action, labels, count: labels.length });\n }\n\n private toastOk(msg: string): void { this.toast(msg, 'ok'); }\n private toastErr(msg: string): void { this.toast(msg, 'err'); }\n\n private toast(msg: string, kind: 'ok' | 'err'): void {\n const el = this.els.toast;\n if (!el) return;\n el.textContent = msg;\n el.className = `slm-toast on ${kind}`;\n if (this.toastTimer) clearTimeout(this.toastTimer);\n this.toastTimer = setTimeout(() => { el.className = 'slm-toast'; }, 3200);\n }\n\n private fail(err: unknown): void {\n this.opts.onError?.(err);\n if (this.els.rail) this.els.rail.innerHTML = `<div class=\"slm-empty\">Couldn't load this event. Check the event key and token.</div>`;\n }\n}\n","/**\n * Organizer manage-surface client for workers/api (the `/v1/events/:key/*`\n * inventory routes + the public realtime channel). Companion to api.ts (the\n * buyer `/pub/*` client) — kept separate because the manage surface is\n * token-authed (Bearer) and cross-origin from the CMS:\n *\n * - Writes + reports send `Authorization: Bearer <token>` where the token is\n * a short-lived, event-scoped organizer manage token (`mse_…`, minted by\n * NestJS) OR a tenant secret key (`sk_…`). Both are accepted by the worker's\n * `eitherAuth` on block / unblock / unblock-all / unbook / hold-ttl / report\n * / log. The Authorization header also exempts the call from the worker's\n * cookie-CSRF gate, so no extra client header is needed.\n * - `credentials: 'omit'` — there is no session cookie; the CMS runs\n * cross-origin. The worker's credentialed CORS still echoes the CMS origin.\n * - Realtime read (`/pub/events/:key/subscribe`, `/objects`, `/chart`) is\n * PUBLIC (wildcard CORS, no token) — the live board subscribes with no auth.\n *\n * `box-book` is intentionally omitted for M1 (box office ships in M2, and the\n * route is still session-only server-side).\n */\nimport type { AvailabilityRule, ChartDoc } from '@seatlayer/core';\n\nexport type { AvailabilityRule } from '@seatlayer/core';\n\nexport class ManageApiError extends Error {\n status: number;\n code?: string;\n /** Present when a block/unbook 409s because seats were just taken. */\n conflicts?: { label: string; reason?: string }[];\n\n constructor(status: number, message: string, code?: string, conflicts?: { label: string; reason?: string }[]) {\n super(message);\n this.name = 'ManageApiError';\n this.status = status;\n this.code = code;\n this.conflicts = conflicts;\n }\n}\n\nexport interface ReportByStatus {\n free: number;\n held: number;\n booked: number;\n not_for_sale: number;\n}\n\nexport interface ReportCategoryRow {\n category: string;\n total: number;\n free: number;\n held: number;\n booked: number;\n not_for_sale: number;\n /** Exact sum of booked unit_price snapshots, in major currency units. */\n bookedRevenue: number;\n}\n\nexport interface ReportCategoryMeta {\n key: string;\n label: string;\n color: string;\n price: number;\n}\n\nexport interface ReportResult {\n report: { byStatus: ReportByStatus; byCategory: ReportCategoryRow[]; bySection?: ControlRoomSectionMetric[] };\n event: { key: string; name: string; seatTotal: number; currency?: string };\n categories: ReportCategoryMeta[];\n}\n\nexport interface ControlRoomSectionMetric {\n sectionId: string;\n sectionLabel: string;\n zoneId: string | null;\n total: number;\n free: number;\n held: number;\n booked: number;\n not_for_sale: number;\n bookedRevenue: number;\n}\n\n/** Recent seat-state change safe for an event:view control-room grant. Full\n * audit references remain available only through the event:reports log API. */\nexport interface ControlRoomActivityEntry {\n id: number;\n at: number;\n action: string;\n labels: string[];\n}\n\nexport interface ControlRoomSnapshot {\n version: number;\n currency: string;\n totals: { free: number; held: number; booked: number; blocked: number };\n revenue: { gross: number; bySection: ControlRoomSectionMetric[] };\n velocity: {\n windowMinutes: number;\n bySection: Array<{\n sectionId: string;\n netBooked: number;\n grossRevenue: number;\n previousNetBooked: number;\n trend: 'rising' | 'steady' | 'cooling';\n }>;\n };\n presence: { shoppingSessions: number; activeHolds: number };\n /** Present on workers that support reload-safe activity hydration. */\n activity?: ControlRoomActivityEntry[];\n event: { key: string; name: string; seatTotal: number; currency?: string };\n}\n\nexport interface LogEntry {\n id: number;\n at: number;\n action: string;\n labels: string[];\n ref: string | null;\n}\n\nexport interface LogPage {\n entries: LogEntry[];\n nextBefore: number | null;\n}\n\nexport interface PubObjectsResult {\n /** Every non-free seat's status keyed by label (free seats omitted). */\n seats: Record<string, string>;\n hidden?: string[];\n closed?: string[];\n updatedAt: number;\n}\n\nexport interface PubChartResult {\n event: {\n key: string;\n name: string;\n status?: string;\n venue?: string | null;\n startsAt?: number | null;\n currency?: string;\n mode?: string;\n };\n doc: ChartDoc;\n}\n\nasync function parse<T>(res: Response): Promise<T> {\n const isJson = (res.headers.get('content-type') ?? '').includes('application/json');\n const data = isJson ? await res.json().catch(() => null) : null;\n if (!res.ok) {\n const err = data as { error?: string; code?: string; conflicts?: { label: string; reason?: string }[] } | null;\n throw new ManageApiError(res.status, err?.error ?? `request_failed_${res.status}`, err?.code, err?.conflicts);\n }\n return data as T;\n}\n\n/**\n * Bound to one apiBase + one event-scoped token. Rebuild (or `setToken`) when a\n * token is re-minted on 401.\n */\nexport class ManageApi {\n private base: string;\n private token: string;\n\n constructor(apiBase: string, token: string) {\n this.base = apiBase.replace(/\\/+$/, '');\n this.token = token;\n }\n\n /** Swap the Bearer token in place (SeatManager re-mints on 401). */\n setToken(token: string): void {\n this.token = token;\n }\n\n private auth<T>(path: string, init: { method?: 'GET' | 'POST'; body?: unknown } = {}): Promise<T> {\n const method = init.method ?? 'GET';\n const headers: Record<string, string> = { Authorization: `Bearer ${this.token}` };\n let body: string | undefined;\n if (init.body !== undefined) {\n headers['Content-Type'] = 'application/json';\n body = JSON.stringify(init.body);\n }\n return fetch(`${this.base}${path}`, { method, headers, body, credentials: 'omit' }).then((r) => parse<T>(r));\n }\n\n private pub<T>(path: string): Promise<T> {\n return fetch(`${this.base}${path}`, { credentials: 'omit' }).then((r) => parse<T>(r));\n }\n\n // ---- realtime read (public, no token) ----\n\n chart(key: string): Promise<PubChartResult> {\n return this.pub(`/pub/events/${encodeURIComponent(key)}/chart`);\n }\n\n objects(key: string): Promise<PubObjectsResult> {\n return this.pub(`/pub/events/${encodeURIComponent(key)}/objects`);\n }\n\n socketUrl(key: string): string {\n return `${this.base.replace(/^http/, 'ws')}/pub/events/${encodeURIComponent(key)}/subscribe?surface=manager`;\n }\n\n // ---- inventory writes (token) ----\n\n /** Take FREE seats off sale in one batched call. Optional `releaseAt` (epoch\n * ms, future) auto-returns them to sale; `reason` tags the block (M3 uses it).\n * Throws ManageApiError 409 (conflicts) if any seat was just taken. */\n block(\n key: string,\n labels: string[],\n opts: { releaseAt?: number; reason?: string } = {},\n ): Promise<{ ok: true; blocked: string[] }> {\n const body: Record<string, unknown> = { labels };\n if (typeof opts.releaseAt === 'number') body.releaseAt = opts.releaseAt;\n if (opts.reason) body.reason = opts.reason;\n return this.auth(`/v1/events/${encodeURIComponent(key)}/block`, { method: 'POST', body });\n }\n\n /** Return specific blocked seats to sale (one batched call). */\n unblock(key: string, labels: string[]): Promise<{ ok: true; unblocked: string[] }> {\n return this.auth(`/v1/events/${encodeURIComponent(key)}/unblock`, { method: 'POST', body: { labels } });\n }\n\n /** Return every blocked seat to sale; resolves with the freed count. */\n unblockAll(key: string): Promise<{ ok: true; freed: number }> {\n return this.auth(`/v1/events/${encodeURIComponent(key)}/unblock-all`, { method: 'POST' });\n }\n\n /** Cancel bookings — return BOOKED seats to free (credit not refunded).\n * Guarded by the original booking reference. */\n unbook(key: string, labels: string[], bookingRef: string): Promise<{ ok: true; unbooked: string[] }> {\n return this.auth(`/v1/events/${encodeURIComponent(key)}/unbook`, { method: 'POST', body: { labels, bookingRef } });\n }\n\n /** Set (ms, clamped 1–60 min server-side) or clear (null) the hold TTL. */\n setHoldTtl(key: string, holdTtlMs: number | null): Promise<{ ok: true; holdTtlMs: number | null }> {\n return this.auth(`/v1/events/${encodeURIComponent(key)}/hold-ttl`, { method: 'POST', body: { holdTtlMs } });\n }\n\n // ---- availability windows (token) ----\n\n /** The organizer's current per section/zone availability windows (needs\n * `event:view`). Ids absent from `rules` are open / on sale. */\n availability(key: string): Promise<{ rules: Record<string, AvailabilityRule> }> {\n return this.auth(`/v1/events/${encodeURIComponent(key)}/availability`);\n }\n\n /** Replace the availability windows for a set of section/zone ids (needs\n * `event:block`). Ids absent from `rules` become open / on sale; a zone rule\n * cascades to its sections. The worker derives each id's seat labels, so\n * `labels` on the sent rules is best-effort. Resolves with the authoritative\n * effective `hidden` set (a due rule may fire at once) and the server-cleaned\n * `rules` map (fired timed/threshold windows dropped). */\n setAvailability(\n key: string,\n rules: Record<string, AvailabilityRule>,\n ): Promise<{ ok: true; hidden: string[]; rules: Record<string, AvailabilityRule> }> {\n return this.auth(`/v1/events/${encodeURIComponent(key)}/availability`, { method: 'POST', body: { rules } });\n }\n\n // ---- reports (token) ----\n\n report(key: string): Promise<ReportResult> {\n return this.auth(`/v1/events/${encodeURIComponent(key)}/report`);\n }\n\n controlRoom(key: string, windowMinutes = 15): Promise<ControlRoomSnapshot> {\n return this.auth(`/v1/events/${encodeURIComponent(key)}/control-room?window=${windowMinutes}`);\n }\n\n log(key: string, opts: { limit?: number; before?: number } = {}): Promise<LogPage> {\n const params = new URLSearchParams();\n if (opts.limit != null) params.set('limit', String(opts.limit));\n if (opts.before != null) params.set('before', String(opts.before));\n const qs = params.toString();\n return this.auth(`/v1/events/${encodeURIComponent(key)}/log${qs ? `?${qs}` : ''}`);\n }\n\n /** CSV report as a Blob (Bearer auth can't ride a plain <a href>). Host builds\n * an object URL for download. */\n async reportCsv(key: string): Promise<Blob> {\n const res = await fetch(`${this.base}/v1/events/${encodeURIComponent(key)}/report.csv`, {\n headers: { Authorization: `Bearer ${this.token}` },\n credentials: 'omit',\n });\n if (!res.ok) throw new ManageApiError(res.status, `request_failed_${res.status}`);\n return res.blob();\n }\n}\n"],"mappings":";AASA,SAAS,kBAAkB,YAAY,oBAAoB,SAAiD;;;ACgBrG,IAAM,WAAN,cAAuB,MAAM;AAAA,EAQlC,YAAY,QAAgB,SAAiB,MAAe,WAA4B,QAAiB;AACvG,UAAM,OAAO;AACb,SAAK,OAAO;AACZ,SAAK,SAAS;AACd,SAAK,OAAO;AACZ,SAAK,YAAY;AACjB,SAAK,SAAS;AAAA,EAChB;AACF;AAuCA,eAAe,QACb,MACA,MACA,OAAoD,CAAC,GACzC;AACZ,QAAM,SAAS,KAAK,UAAU;AAC9B,QAAM,UAAkC,CAAC;AACzC,MAAI;AACJ,MAAI,KAAK,SAAS,QAAW;AAC3B,YAAQ,cAAc,IAAI;AAC1B,WAAO,KAAK,UAAU,KAAK,IAAI;AAAA,EACjC;AAEA,QAAM,MAAM,MAAM,MAAM,GAAG,IAAI,GAAG,IAAI,IAAI,EAAE,QAAQ,SAAS,MAAM,aAAa,OAAO,CAAC;AAExF,QAAM,UAAU,IAAI,QAAQ,IAAI,cAAc,KAAK,IAAI,SAAS,kBAAkB;AAClF,QAAM,OAAO,SAAS,MAAM,IAAI,KAAK,EAAE,MAAM,MAAM,IAAI,IAAI;AAE3D,MAAI,CAAC,IAAI,IAAI;AACX,UAAM,MAAM;AAGZ,UAAM,IAAI,SAAS,IAAI,QAAQ,KAAK,SAAS,kBAAkB,IAAI,MAAM,IAAI,KAAK,MAAM,KAAK,WAAW,KAAK,MAAM;AAAA,EACrH;AACA,SAAO;AACT;AAGO,IAAM,SAAN,MAAa;AAAA,EAKlB,YAA6B,MAAc;AAAd;AAJ7B,SAAiB,WAAW,OAAO,WAAW,eAAe,OAAO,OAAO,eAAe,aACtF,OAAO,WAAW,IAClB,UAAU,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,CAAC,CAAC,GAAG,KAAK,IAAI,EAAE,SAAS,EAAE,CAAC;AAAA,EAE/B;AAAA,EAE5C,MAAM,KAAsC;AAC1C,WAAO,QAAQ,KAAK,MAAM,eAAe,mBAAmB,GAAG,CAAC,QAAQ;AAAA,EAC1E;AAAA,EAEA,QAAQ,KAAwC;AAC9C,WAAO,QAAQ,KAAK,MAAM,eAAe,mBAAmB,GAAG,CAAC,UAAU;AAAA,EAC5E;AAAA,EAEA,KAAK,KAAa,YAA8D,OAAgB,eAA6C;AAC3I,WAAO,QAAQ,KAAK,MAAM,eAAe,mBAAmB,GAAG,CAAC,SAAS;AAAA,MACvE,QAAQ;AAAA,MACR,MAAM,EAAE,YAAY,GAAI,QAAQ,EAAE,MAAM,IAAI,CAAC,GAAI,GAAI,gBAAgB,EAAE,cAAc,IAAI,CAAC,EAAG;AAAA,IAC/F,CAAC;AAAA,EACH;AAAA,EAEA,cAAc,KAAa,KAAa,aAAoD;AAC1F,WAAO,QAAQ,KAAK,MAAM,eAAe,mBAAmB,GAAG,CAAC,mBAAmB;AAAA,MACjF,QAAQ;AAAA,MACR,MAAM,EAAE,KAAK,GAAI,cAAc,EAAE,YAAY,IAAI,CAAC,EAAG;AAAA,IACvD,CAAC;AAAA,EACH;AAAA,EAEA,OAAO,KAAa,QAA4C;AAC9D,WAAO,QAAQ,KAAK,MAAM,eAAe,mBAAmB,GAAG,CAAC,gBAAgB;AAAA,MAC9E,QAAQ;AAAA,MACR,MAAM,EAAE,OAAO;AAAA,IACjB,CAAC;AAAA,EACH;AAAA,EAEA,QAAQ,KAAa,QAAkB,QAA4D;AACjG,WAAO,QAAQ,KAAK,MAAM,eAAe,mBAAmB,GAAG,CAAC,YAAY;AAAA,MAC1E,QAAQ;AAAA,MACR,MAAM,EAAE,QAAQ,OAAO;AAAA,IACzB,CAAC;AAAA,EACH;AAAA;AAAA;AAAA,EAIA,OAAO,KAAa,QAAgB,OAAiF;AACnH,WAAO,QAAQ,KAAK,MAAM,eAAe,mBAAmB,GAAG,CAAC,WAAW;AAAA,MACzE,QAAQ;AAAA,MACR,MAAM,EAAE,QAAQ,GAAI,QAAQ,EAAE,MAAM,IAAI,CAAC,EAAG;AAAA,IAC9C,CAAC;AAAA,EACH;AAAA,EAEA,UAAU,KAAqB;AAC7B,UAAM,SAAS,KAAK,KAAK,QAAQ,SAAS,IAAI;AAC9C,UAAM,SAAS,IAAI,gBAAgB,EAAE,SAAS,UAAU,UAAU,KAAK,SAAS,CAAC;AACjF,WAAO,GAAG,MAAM,eAAe,mBAAmB,GAAG,CAAC,cAAc,MAAM;AAAA,EAC5E;AACF;;;ADzJA,IAAM,mBAAmB;AACzB,IAAM,wBAAwB;AAwE9B,SAAS,iBAAiB,WAA8C;AACtE,MAAI,OAAO,cAAc,UAAU;AACjC,UAAM,KAAK,SAAS,cAAc,SAAS;AAC3C,QAAI,CAAC,GAAI,OAAM,IAAI,MAAM,uBAAuB,SAAS,aAAa;AACtE,WAAO;AAAA,EACT;AACA,MAAI,EAAE,qBAAqB,cAAc;AACvC,UAAM,IAAI,MAAM,6DAA6D;AAAA,EAC/E;AACA,SAAO;AACT;AAEO,IAAM,eAAN,MAAmB;AAAA,EAaxB,YAAY,SAA8B;AAP1C,SAAQ,QAA4B;AACpC,SAAQ,SAAgC;AACxC,SAAQ,WAAW;AACnB,SAAQ,QAA+B;AACvC,SAAQ,SAAS,EAAE,GAAG,GAAG,GAAG,EAAE;AAC9B,SAAQ,YAA8C;AAGpD,QAAI,CAAC,WAAW,OAAO,YAAY,SAAU,OAAM,IAAI,MAAM,qCAAqC;AAClG,QAAI,CAAC,QAAQ,UAAW,OAAM,IAAI,MAAM,kCAAkC;AAC1E,QAAI,CAAC,QAAQ,SAAS,OAAO,QAAQ,UAAU,SAAU,OAAM,IAAI,MAAM,kCAAkC;AAE3G,SAAK,OAAO;AACZ,SAAK,YAAY,QAAQ;AACzB,UAAM,MAAM,IAAI,QAAQ,QAAQ,WAAW,kBAAkB,QAAQ,QAAQ,EAAE,CAAC;AAChF,SAAK,aAAa,IAAI,iBAAiB;AAAA,MACrC,WAAW;AAAA,MACX,UAAU,QAAQ;AAAA,MAClB,cAAc,QAAQ,gBAAgB;AAAA,MACtC,UAAU,QAAQ;AAAA,MAClB,mBAAmB,CAAC,UAAU,KAAK,KAAK,oBAAoB,KAAK;AAAA,MACjE,QAAQ,CAAC,MAAM,KAAK,KAAK,SAAS,EAAE,QAAQ,EAAE,QAAQ,WAAW,EAAE,WAAW,OAAO,EAAE,OAAO,OAAO,EAAE,MAAM,CAAC;AAAA,MAC9G,gBAAgB,CAAC,MAAM,KAAK,KAAK,iBAAiB,EAAE,QAAQ,EAAE,QAAQ,WAAW,EAAE,WAAW,OAAO,EAAE,OAAO,OAAO,EAAE,MAAM,CAAC;AAAA,MAC9H,eAAe,MAAM,KAAK,KAAK,gBAAgB;AAAA,MAC/C,WAAW,CAAC,WAAW;AACrB,cAAM,OAAO,KAAK,WAAW,WAAW,EAAE,KAAK,CAAC,cAAc,UAAU,OAAO,MAAM;AACrF,YAAI,KAAM,MAAK,KAAK,YAAY,IAAI;AAAA,MACtC;AAAA,MACA,SAAS,CAAC,QAAQ,KAAK,KAAK,UAAU,GAAG;AAAA,MACzC,WAAW,CAAC,YAAY,KAAK,KAAK,YAAY,OAAO;AAAA,MACrD,QAAQ,CAAC,YAAY,KAAK,KAAK,SAAS,OAAO;AAAA;AAAA;AAAA,MAG/C,mBAAmB;AAAA,MACnB,aAAa,CAAC,YAAY;AACxB,aAAK,KAAK,cAAc,OAAO;AAC/B,YAAI,KAAK,KAAK,gBAAgB,MAAO,MAAK,cAAc,OAAO;AAAA,MACjE;AAAA,MACA,gBAAgB,QAAQ;AAAA,IAC1B,CAAC;AAAA,EACH;AAAA;AAAA,EAGA,MAAM,SAAwB;AAC5B,QAAI,KAAK,SAAU,QAAO;AAC1B,SAAK,WAAW;AAKhB,UAAM,WAAW,KAAK,KAAK,MAAM;AACjC,QAAI,KAAK,KAAK,SAAU,oBAAmB,KAAK,KAAK,QAAQ;AAI7D,SAAK,QAAQ,iBAAiB,KAAK,KAAK,SAAS;AACjD,UAAM,OAAO,SAAS,cAAc,KAAK;AACzC,SAAK,MAAM,QAAQ;AACnB,SAAK,MAAM,SAAS;AACpB,SAAK,MAAM,WAAW;AACtB,SAAK,MAAM,YAAY,IAAI;AAC3B,SAAK,SAAS;AAEd,UAAM,OAAO,MAAM,KAAK,WAAW,OAAO,IAAI;AAC9C,QAAI,CAAC,MAAM;AACT,WAAK,WAAW;AAChB,aAAO;AAAA,IACT;AAMA,QAAI,KAAK,KAAK,gBAAgB,OAAO;AACnC,YAAM,MAAM,SAAS,cAAc,KAAK;AACxC,UAAI,aAAa,QAAQ,SAAS;AAClC,UAAI,MAAM,UACR;AAIF,WAAK,YAAY,GAAG;AACpB,WAAK,QAAQ;AACb,WAAK,YAAY,CAAC,MAAkB;AAClC,cAAM,IAAI,KAAK,sBAAsB;AACrC,aAAK,SAAS,EAAE,GAAG,EAAE,UAAU,EAAE,MAAM,GAAG,EAAE,UAAU,EAAE,IAAI;AAC5D,YAAI,KAAK,SAAS,KAAK,MAAM,MAAM,YAAY,OAAQ,MAAK,aAAa;AAAA,MAC3E;AACA,WAAK,iBAAiB,aAAa,KAAK,SAAS;AAAA,IACnD;AACA,QAAI,KAAK,SAAS,QAAQ;AACxB,WAAK,MAAM,WAAW;AACtB,YAAM,SAAS,SAAS,cAAc,KAAK;AAC3C,aAAO,cAAc,EAAE,iBAAiB;AACxC,aAAO,aAAa,cAAc,EAAE,iBAAiB,CAAC;AACtD,aAAO,MAAM,UACX;AAIF,WAAK,YAAY,MAAM;AAAA,IACzB;AACA,WAAO;AAAA,EACT;AAAA,EAEQ,eAAqB;AAC3B,QAAI,CAAC,KAAK,SAAS,CAAC,KAAK,OAAQ;AACjC,UAAM,KAAK,KAAK,OAAO;AACvB,UAAM,KAAK,KAAK,MAAM;AACtB,UAAM,KAAK,KAAK,MAAM;AACtB,QAAI,IAAI,KAAK,OAAO,IAAI;AACxB,QAAI,IAAI,KAAK,OAAO,IAAI,KAAK;AAC7B,QAAI,IAAI,KAAK,KAAK,EAAG,KAAI,KAAK,OAAO,IAAI,KAAK;AAC9C,QAAI,IAAI,EAAG,KAAI,KAAK,OAAO,IAAI;AAC/B,SAAK,MAAM,MAAM,OAAO,GAAG,KAAK,IAAI,GAAG,CAAC,CAAC;AACzC,SAAK,MAAM,MAAM,MAAM,GAAG,KAAK,IAAI,GAAG,CAAC,CAAC;AAAA,EAC1C;AAAA,EAEQ,cAAc,SAAwC;AAC5D,QAAI,CAAC,KAAK,MAAO;AACjB,QAAI,CAAC,SAAS;AACZ,WAAK,MAAM,MAAM,UAAU;AAC3B;AAAA,IACF;AACA,UAAM,SAAS,MAAM;AACnB,UAAI;AACF,eAAO,IAAI,KAAK,aAAa,QAAW,EAAE,OAAO,YAAY,UAAU,QAAQ,SAAS,CAAC,EAAE,OAAO,QAAQ,KAAK;AAAA,MACjH,QAAQ;AACN,eAAO,GAAG,QAAQ,KAAK,IAAI,QAAQ,QAAQ;AAAA,MAC7C;AAAA,IACF,GAAG;AACH,UAAM,aACJ,QAAQ,WAAW,SACf,KACA,4HACE,QAAQ,WAAW,SAAS,EAAE,gBAAgB,IAAI,EAAE,iBAAiB,CACvE;AACN,SAAK,MAAM,YACT,+CAA+C,QAAQ,KAAK,oKAEgB,QAAQ,aAAa,kBACxF,QAAQ,aAAa,oEAC+B,KAAK,kBAClE;AACF,SAAK,MAAM,MAAM,UAAU;AAC3B,SAAK,aAAa;AAAA,EACpB;AAAA;AAAA,EAGA,eAA+B;AAC7B,WAAO,KAAK,WAAW,aAAa;AAAA,EACtC;AAAA;AAAA,EAGA,MAAM,KAAK,UAA8B,CAAC,GAA+B;AACvE,QAAI;AACF,YAAM,IAAI,MAAM,KAAK,WAAW,KAAK,QAAW,QAAQ,KAAK;AAC7D,aAAO,IAAI,EAAE,QAAQ,EAAE,QAAQ,WAAW,EAAE,WAAW,OAAO,EAAE,OAAO,OAAO,EAAE,MAAM,IAAI;AAAA,IAC5F,SAAS,KAAK;AACZ,WAAK,KAAK,UAAU,GAAG;AACvB,aAAO;AAAA,IACT;AAAA,EACF;AAAA;AAAA,EAGA,MAAM,WAAW,QAA4C;AAC3D,QAAI;AACF,YAAM,IAAI,MAAM,KAAK,WAAW,WAAW,MAAM;AACjD,aAAO,IAAI,EAAE,QAAQ,EAAE,QAAQ,WAAW,EAAE,WAAW,OAAO,EAAE,OAAO,OAAO,EAAE,MAAM,IAAI;AAAA,IAC5F,SAAS,KAAK;AACZ,WAAK,KAAK,UAAU,GAAG;AACvB,aAAO;AAAA,IACT;AAAA,EACF;AAAA;AAAA,EAGA,iBAAoC;AAClC,UAAM,IAAI,KAAK,WAAW,YAAY;AACtC,WAAO,IAAI,EAAE,QAAQ,EAAE,QAAQ,WAAW,EAAE,WAAW,OAAO,EAAE,OAAO,OAAO,EAAE,MAAM,IAAI;AAAA,EAC5F;AAAA,EAEA,aAAmC;AACjC,WAAO,KAAK,WAAW,WAAW;AAAA,EACpC;AAAA,EAEA,MAAM,OACJ,QACA,KACA,UAAsD,CAAC,GAC3B;AAC5B,QAAI;AACF,YAAM,IAAI,MAAM,KAAK,WAAW,OAAO,QAAQ,KAAK,OAAO;AAC3D,aAAO,IAAI,EAAE,QAAQ,EAAE,QAAQ,WAAW,EAAE,WAAW,OAAO,EAAE,OAAO,OAAO,EAAE,MAAM,IAAI;AAAA,IAC5F,SAAS,KAAK;AACZ,WAAK,KAAK,UAAU,GAAG;AACvB,aAAO;AAAA,IACT;AAAA,EACF;AAAA;AAAA,EAGA,MAAM,cAAc,KAAa,aAA2D;AAC1F,QAAI;AACF,YAAM,IAAI,MAAM,KAAK,WAAW,cAAc,KAAK,WAAW;AAC9D,aAAO,IAAI,EAAE,QAAQ,EAAE,QAAQ,WAAW,EAAE,WAAW,QAAQ,EAAE,QAAQ,OAAO,EAAE,OAAO,OAAO,EAAE,MAAM,IAAI;AAAA,IAC9G,SAAS,KAAK;AACZ,WAAK,KAAK,UAAU,GAAG;AACvB,aAAO;AAAA,IACT;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,YAAY,QAAgB,QAA6B;AACvD,SAAK,WAAW,YAAY,QAAQ,MAAM;AAAA,EAC5C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,YAA4C;AAC1C,WAAO,KAAK,WAAW,UAAU;AAAA,EACnC;AAAA;AAAA,EAGA,SAAS,SAAuB;AAC9B,QAAI,KAAK,WAAW,UAAU,EAAE,UAAU,GAAG;AAC3C,cAAQ,KAAK,kEAA6D;AAC1E;AAAA,IACF;AACA,SAAK,WAAW,SAAS,OAAO;AAAA,EAClC;AAAA;AAAA,EAGA,kBAAkB,IAAmB;AACnC,SAAK,WAAW,kBAAkB,EAAE;AAAA,EACtC;AAAA;AAAA,EAGA,SAAe;AACb,SAAK,WAAW,OAAO;AAAA,EACzB;AAAA;AAAA,EAGA,UAAgB;AACd,SAAK,WAAW,QAAQ;AAAA,EAC1B;AAAA;AAAA,EAGA,YAAkB;AAChB,SAAK,WAAW,UAAU;AAAA,EAC5B;AAAA;AAAA,EAGA,MAAM,UAAyB;AAC7B,UAAM,KAAK,WAAW,QAAQ;AAAA,EAChC;AAAA;AAAA,EAGA,MAAM,cAAc,QAAoC;AACtD,WAAO,KAAK,WAAW,cAAc,MAAM;AAAA,EAC7C;AAAA;AAAA,EAGA,UAAgB;AACd,QAAI,KAAK,UAAU,KAAK,UAAW,MAAK,OAAO,oBAAoB,aAAa,KAAK,SAAS;AAC9F,SAAK,QAAQ;AACb,SAAK,YAAY;AACjB,SAAK,WAAW,QAAQ;AACxB,QAAI,KAAK,UAAU,KAAK,OAAO,WAAY,MAAK,OAAO,WAAW,YAAY,KAAK,MAAM;AACzF,SAAK,SAAS;AACd,SAAK,QAAQ;AACb,SAAK,WAAW;AAAA,EAClB;AACF;;;AExSA,IAAM,QAAQ,oBAAI,IAA+B;AAAA,EAC/C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAED,IAAM,6BAA6B;AACnC,IAAM,0BAA0B;AAKhC,SAASA,kBAAiB,WAA8C;AACtE,MAAI,OAAO,cAAc,SAAU,QAAO;AAC1C,QAAM,UAAU,SAAS,cAA2B,SAAS;AAC7D,MAAI,CAAC,QAAS,OAAM,IAAI,MAAM,yCAAyC,SAAS,EAAE;AAClF,SAAO;AACT;AAGA,SAAS,cAAc,MAAsC;AAC3D,QAAM,SAAS,QAAQ,IAAI,YAAY;AACvC,MAAI,MAAM,SAAS,QAAQ,KAAK,MAAM,SAAS,QAAQ,KAAK,UAAU,MAAO,QAAO;AACpF,MAAI,MAAM,SAAS,UAAU,EAAG,QAAO;AACvC,MAAI,MAAM,SAAS,SAAS,EAAG,QAAO;AACtC,SAAO;AACT;AAEA,IAAM,aAAkE;AAAA,EACtE,SAAS;AAAA,IACP,OAAO;AAAA,IACP,MAAM;AAAA,EACR;AAAA,EACA,UAAU;AAAA,IACR,OAAO;AAAA,IACP,MAAM;AAAA,EACR;AAAA,EACA,SAAS;AAAA,IACP,OAAO;AAAA,IACP,MAAM;AAAA,EACR;AAAA,EACA,MAAM;AAAA,IACJ,OAAO;AAAA,IACP,MAAM;AAAA,EACR;AACF;AAGO,IAAM,mBAAN,MAAuB;AAAA,EAoB5B,YAAY,SAAkC;AAlB9C,SAAQ,QAAkC;AAC1C,SAAQ,iBAAiB;AACzB,SAAQ,UAAiC;AACzC,SAAQ,eAAqD;AAC7D,SAAQ,QAAuC;AAC/C,SAAQ,2BAA0C;AAElD;AAAA,SAAQ,SAAS;AACjB,SAAQ,qBAAoC;AAC5C,SAAQ,sBAAqC;AAC7C,SAAQ,uBAAsC;AAC9C,SAAQ,eAAwD;AAEhE;AAAA,SAAQ,iBAAiB;AAEzB;AAAA,SAAQ,UAAyB;AACjC,SAAQ,gBAAgB;AAqGxB;AAAA,SAAQ,eAAe,MAAY;AACjC,UAAI,KAAK,YAAY,KAAM;AAC3B,WAAK,UAAU,sBAAsB,MAAM;AACzC,aAAK,UAAU;AACf,aAAK,UAAU;AAAA,MACjB,CAAC;AAAA,IACH;AAyTA,SAAQ,gBAAgB,CAAC,UAAiC;AACxD,UAAI,CAAC,KAAK,SAAS,MAAM,WAAW,KAAK,kBAAkB,MAAM,WAAW,KAAK,MAAM,cAAe;AACtG,UAAI,CAAC,MAAM,QAAQ,OAAO,MAAM,SAAS,SAAU;AACnD,YAAM,OAAO,MAAM;AAInB,UAAI,KAAK,SAAS,6BAA6B;AAI7C,YAAI,CAAC,KAAK,YAAY,KAAK,KAAK,kBAAkB,KAC3C,OAAO,KAAK,OAAO,YAAY,OAAO,SAAS,KAAK,EAAE,KAAK,KAAK,KAAK,GAAG;AAC7E,eAAK,iBAAiB,GAAG,KAAK,MAAM,KAAK,EAAE,CAAC;AAG5C,cAAI,CAAC,KAAK,OAAQ,MAAK,MAAM,MAAM,SAAS,KAAK;AAAA,QACnD;AACA;AAAA,MACF;AACA,UAAI,KAAK,SAAS,iCAAiC;AACjD,YAAI,KAAK,OAAO,KAAM,MAAK,cAAc;AAAA,iBAChC,KAAK,OAAO,MAAO,MAAK,gBAAgB;AACjD;AAAA,MACF;AAEA,UAAI,OAAO,KAAK,SAAS,YAAY,CAAC,MAAM,IAAI,KAAK,IAAiC,EAAG;AAEzF,YAAM,UAAmC;AAAA,QACvC,MAAM,KAAK;AAAA,QACX,SAAS,OAAO,KAAK,YAAY,WAAW,KAAK,UAAU;AAAA,QAC3D,aAAa,OAAO,KAAK,gBAAgB,WAAW,KAAK,cAAc;AAAA,QACvE,WAAW,OAAO,KAAK,cAAc,WAAW,KAAK,YAAY;AAAA,QACjE,MAAM,OAAO,KAAK,SAAS,WAAW,KAAK,OAAO;AAAA,QAClD,SAAS,OAAO,KAAK,YAAY,WAAW,KAAK,UAAU;AAAA,QAC3D,MAAM,KAAK;AAAA,MACb;AACA,UACG,KAAK,QAAQ,mBAAmB,QAAQ,WAAW,QAAQ,YAAY,KAAK,QAAQ,mBACpF,KAAK,QAAQ,uBAAuB,QAAQ,eAAe,QAAQ,gBAAgB,KAAK,QAAQ,qBACjG;AAIA,aAAK,UAAU,UAAU;AACzB;AAAA,MACF;AAEA,cAAQ,QAAQ,MAAM;AAAA,QACpB,KAAK;AACH,eAAK,QAAQ;AACb,eAAK,kBAAkB;AACvB,eAAK,cAAc;AACnB,eAAK,QAAQ,UAAU,OAAO;AAC9B;AAAA,QACF,KAAK;AAA4B,eAAK,QAAQ,UAAU,OAAO;AAAG;AAAA,QAClE,KAAK;AAAgC,eAAK,QAAQ,cAAc,OAAO;AAAG;AAAA,QAC1E,KAAK;AAA4B,eAAK,QAAQ,UAAU,OAAO;AAAG;AAAA,QAClE,KAAK;AACH,eAAK,UAAU,cAAc,QAAQ,IAAI,CAAC;AAC1C,eAAK,QAAQ,UAAU,OAAO;AAC9B;AAAA,MACJ;AAAA,IACF;AAheE,SAAK,UAAU;AAAA,EACjB;AAAA,EAEA,QAA2B;AACzB,SAAK,QAAQ;AACb,UAAM,MAAM,IAAI,IAAI,KAAK,QAAQ,aAAa,OAAO,SAAS,IAAI;AAClE,QAAI,IAAI,aAAa,YAAY,IAAI,aAAa,eAAe,IAAI,aAAa,aAAa;AAC7F,YAAM,IAAI,MAAM,2EAA2E;AAAA,IAC7F;AACA,SAAK,iBAAiB,IAAI;AAE1B,UAAM,QAAQ,SAAS,cAAc,QAAQ;AAC7C,UAAM,QAAQ,KAAK,QAAQ,SAAS;AACpC,UAAM,QAAQ,KAAK,QAAQ,SAAS;AACpC,UAAM,iBAAiB,KAAK,QAAQ,kBAAkB;AACtD,UAAM,MAAM,IAAI,SAAS;AACzB,UAAM,MAAM,QAAQ;AAGpB,UAAM,MAAM,SAAS,OAAO,KAAK,QAAQ,WAAW,WAAW,GAAG,KAAK,QAAQ,MAAM,OAAO;AAC5F,UAAM,MAAM,SAAS;AACrB,WAAO,OAAO,MAAM,OAAO,KAAK,QAAQ,KAAK;AAC7C,QAAI,KAAK,QAAQ,UAAW,OAAM,YAAY,KAAK,QAAQ;AAE3D,UAAM,YAAYA,kBAAiB,KAAK,QAAQ,SAAS;AACzD,WAAO,iBAAiB,WAAW,KAAK,aAAa;AACrD,cAAU,OAAO,KAAK;AACtB,SAAK,QAAQ;AAGb,QAAI,KAAK,YAAY,EAAG,MAAK,UAAU;AAEvC,SAAK,QAAQ;AACb,QAAI,KAAK,oBAAoB,GAAG;AAC9B,WAAK,0BAA0B,SAAS;AACxC,WAAK,cAAc,WAAW,SAAS;AACvC,YAAM,UAAU,KAAK,QAAQ,oBAAoB;AACjD,UAAI,UAAU,KAAK,OAAO,SAAS,OAAO,GAAG;AAC3C,aAAK,eAAe,WAAW,MAAM;AACnC,cAAI,KAAK,UAAU,UAAW,MAAK,UAAU,SAAS;AAAA,QACxD,GAAG,OAAO;AAAA,MACZ;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,eAAe,aAAwC;AACrD,SAAK,UAAU,EAAE,GAAG,KAAK,SAAS,YAAY;AAE9C,WAAO,KAAK,MAAM;AAAA,EACpB;AAAA,EAEA,YAAsC;AACpC,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,UAAgB;AACd,WAAO,oBAAoB,WAAW,KAAK,aAAa;AACxD,SAAK,SAAS;AACd,SAAK,gBAAgB;AACrB,SAAK,kBAAkB;AACvB,SAAK,cAAc;AACnB,SAAK,sBAAsB;AAC3B,SAAK,OAAO,OAAO;AACnB,SAAK,QAAQ;AACb,SAAK,iBAAiB;AACtB,SAAK,QAAQ;AACb,SAAK,iBAAiB;AAAA,EACxB;AAAA,EAEQ,sBAA+B;AACrC,WAAO,KAAK,QAAQ,qBAAqB;AAAA,EAC3C;AAAA,EAEQ,oBAA6B;AACnC,WAAO,KAAK,QAAQ,eAAe;AAAA,EACrC;AAAA;AAAA,EAGQ,cAAuB;AAC7B,WAAO,OAAO,KAAK,QAAQ,WAAW;AAAA,EACxC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,YAAkB;AACxB,QAAI,CAAC,KAAK,SAAS,KAAK,OAAQ;AAChC,UAAM,MAAM,KAAK,QAAQ,aAAa;AACtC,UAAM,MAAM,KAAK,MAAM,sBAAsB,EAAE;AAC/C,UAAM,SAAS,KAAK,IAAI,KAAK,KAAK,MAAM,OAAO,cAAc,GAAG,CAAC;AACjE,SAAK,MAAM,MAAM,SAAS,GAAG,MAAM;AAAA,EACrC;AAAA,EAWQ,YAAkB;AACxB,SAAK,UAAU;AACf,QAAI,KAAK,cAAe;AACxB,SAAK,gBAAgB;AACrB,WAAO,iBAAiB,UAAU,KAAK,YAAY;AACnD,WAAO,iBAAiB,qBAAqB,KAAK,YAAY;AAC9D,WAAO,iBAAiB,UAAU,KAAK,cAAc,EAAE,SAAS,KAAK,CAAC;AAAA,EACxE;AAAA,EAEQ,WAAiB;AACvB,QAAI,KAAK,YAAY,MAAM;AACzB,2BAAqB,KAAK,OAAO;AACjC,WAAK,UAAU;AAAA,IACjB;AACA,QAAI,CAAC,KAAK,cAAe;AACzB,SAAK,gBAAgB;AACrB,WAAO,oBAAoB,UAAU,KAAK,YAAY;AACtD,WAAO,oBAAoB,qBAAqB,KAAK,YAAY;AACjE,WAAO,oBAAoB,UAAU,KAAK,YAAY;AAAA,EACxD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,gBAAsB;AAC5B,QAAI,KAAK,UAAU,CAAC,KAAK,MAAO;AAChC,SAAK,SAAS;AACd,SAAK,qBAAqB,KAAK,MAAM,aAAa,OAAO;AACzD,WAAO,OAAO,KAAK,MAAM,OAAO;AAAA,MAC9B,UAAU;AAAA,MACV,OAAO;AAAA,MACP,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,YAAY;AAAA,IACd,CAAwC;AAExC,UAAM,QAAQ,SAAS;AACvB,SAAK,sBAAsB,MAAM,MAAM;AACvC,UAAM,MAAM,WAAW;AACvB,QAAI,SAAS,MAAM;AACjB,WAAK,uBAAuB,SAAS,KAAK,MAAM;AAChD,eAAS,KAAK,MAAM,WAAW;AAAA,IACjC;AAEA,SAAK,eAAe,CAAC,UAA+B;AAClD,UAAI,MAAM,QAAQ,SAAU,MAAK,gBAAgB;AAAA,IACnD;AACA,WAAO,iBAAiB,WAAW,KAAK,YAAY;AAAA,EACtD;AAAA;AAAA,EAGQ,kBAAwB;AAC9B,QAAI,CAAC,KAAK,OAAQ;AAClB,SAAK,SAAS;AACd,QAAI,KAAK,OAAO;AACd,UAAI,KAAK,uBAAuB,KAAM,MAAK,MAAM,gBAAgB,OAAO;AAAA,UACnE,MAAK,MAAM,aAAa,SAAS,KAAK,kBAAkB;AAG7D,UAAI,KAAK,YAAY,EAAG,MAAK,UAAU;AAAA,eAC9B,KAAK,kBAAkB,KAAK,KAAK,eAAgB,MAAK,MAAM,MAAM,SAAS,KAAK;AAAA,IAC3F;AACA,SAAK,qBAAqB;AAE1B,QAAI,KAAK,wBAAwB,MAAM;AACrC,eAAS,gBAAgB,MAAM,WAAW,KAAK;AAC/C,WAAK,sBAAsB;AAAA,IAC7B;AACA,QAAI,KAAK,yBAAyB,QAAQ,SAAS,MAAM;AACvD,eAAS,KAAK,MAAM,WAAW,KAAK;AACpC,WAAK,uBAAuB;AAAA,IAC9B;AACA,QAAI,KAAK,cAAc;AACrB,aAAO,oBAAoB,WAAW,KAAK,YAAY;AACvD,WAAK,eAAe;AAAA,IACtB;AAAA,EACF;AAAA,EAEQ,oBAA0B;AAChC,QAAI,KAAK,iBAAiB,MAAM;AAC9B,mBAAa,KAAK,YAAY;AAC9B,WAAK,eAAe;AAAA,IACtB;AAAA,EACF;AAAA,EAEQ,0BAA0B,WAA8B;AAI9D,UAAM,WAAW,iBAAiB,SAAS,EAAE;AAC7C,QAAI,aAAa,UAAU;AACzB,WAAK,2BAA2B,UAAU,MAAM;AAChD,gBAAU,MAAM,WAAW;AAAA,IAC7B;AAAA,EACF;AAAA,EAEQ,wBAA8B;AACpC,QAAI,KAAK,6BAA6B,KAAM;AAC5C,QAAI;AACF,MAAAA,kBAAiB,KAAK,QAAQ,SAAS,EAAE,MAAM,WAAW,KAAK;AAAA,IACjE,QAAQ;AAAA,IAER;AACA,SAAK,2BAA2B;AAAA,EAClC;AAAA,EAEQ,gBAAsB;AAC5B,SAAK,SAAS,OAAO;AACrB,SAAK,UAAU;AAAA,EACjB;AAAA,EAEQ,UAAU,OAAyB;AACzC,SAAK,QAAQ;AACb,SAAK,kBAAkB;AACvB,QAAI,CAAC,KAAK,oBAAoB,EAAG;AACjC,QAAI;AACJ,QAAI;AACF,kBAAYA,kBAAiB,KAAK,QAAQ,SAAS;AAAA,IACrD,QAAQ;AACN;AAAA,IACF;AACA,SAAK,cAAc,WAAW,SAAS,KAAK;AAAA,EAC9C;AAAA,EAEQ,iBAAuB;AAC7B,QAAI,KAAK,QAAQ,mBAAmB;AAGlC,WAAK,QAAQ,kBAAkB;AAC/B;AAAA,IACF;AAEA,SAAK,MAAM;AAAA,EACb;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,cAAc,WAAwB,OAA4B,OAA0B;AAClG,SAAK,cAAc;AACnB,UAAM,UAAU,SAAS,cAAc,KAAK;AAC5C,YAAQ,aAAa,mCAAmC,KAAK;AAC7D,YAAQ,aAAa,QAAQ,UAAU,UAAU,UAAU,QAAQ;AACnE,YAAQ,aAAa,aAAa,QAAQ;AAC1C,WAAO,OAAO,QAAQ,OAAO;AAAA,MAC3B,UAAU;AAAA,MACV,OAAO;AAAA,MACP,SAAS;AAAA,MACT,YAAY;AAAA,MACZ,gBAAgB;AAAA,MAChB,YAAY;AAAA,MACZ,OAAO;AAAA,MACP,YACE;AAAA,MACF,QAAQ;AAAA,MACR,UAAU;AAAA,IACZ,CAAwC;AAExC,QAAI,UAAU,UAAW,MAAK,cAAc,OAAO;AAAA,QAC9C,MAAK,eAAe,SAAS,SAAS,MAAM;AAEjD,cAAU,OAAO,OAAO;AACxB,SAAK,UAAU;AAAA,EACjB;AAAA,EAEQ,cAAc,SAA+B;AAEnD,UAAM,QAAQ,SAAS,cAAc,OAAO;AAC5C,UAAM,cAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAWpB,YAAQ,OAAO,KAAK;AAEpB,UAAM,UACJ;AAEF,UAAM,WAAW,SAAS,cAAc,KAAK;AAC7C,WAAO,OAAO,SAAS,OAAO;AAAA,MAC5B,UAAU;AAAA,MACV,OAAO;AAAA,MACP,SAAS;AAAA,MACT,eAAe;AAAA,MACf,SAAS;AAAA,MACT,KAAK;AAAA,MACL,SAAS;AAAA,IACX,CAAwC;AAExC,UAAM,MAAM,CAAC,WAAyD;AACpE,YAAM,OAAO,SAAS,cAAc,KAAK;AACzC,WAAK,YAAY;AACjB,aAAO,OAAO,KAAK,OAAO;AAAA,QACxB,YAAY;AAAA,QACZ,cAAc;AAAA,MAChB,CAAwC;AACxC,aAAO,OAAO,KAAK,OAAO,MAAM;AAChC,aAAO;AAAA,IACT;AAGA,aAAS,OAAO,IAAI,EAAE,QAAQ,QAAQ,OAAO,QAAQ,MAAM,WAAW,CAAC,CAAC;AAGxE,UAAM,OAAO,SAAS,cAAc,KAAK;AACzC,WAAO,OAAO,KAAK,OAAO;AAAA,MACxB,SAAS;AAAA,MACT,KAAK;AAAA,MACL,MAAM;AAAA,MACN,WAAW;AAAA,IACb,CAAwC;AACxC,SAAK,OAAO,IAAI,EAAE,OAAO,SAAS,QAAQ,QAAQ,MAAM,WAAW,CAAC,CAAC;AACrE,SAAK,OAAO,IAAI,EAAE,MAAM,YAAY,QAAQ,OAAO,CAAC,CAAC;AACrD,aAAS,OAAO,IAAI;AAEpB,YAAQ,OAAO,QAAQ;AAGvB,UAAM,UAAU,SAAS,cAAc,KAAK;AAC5C,WAAO,OAAO,QAAQ,OAAO;AAAA,MAC3B,UAAU;AAAA,MACV,QAAQ;AAAA,MACR,SAAS;AAAA,MACT,YAAY;AAAA,MACZ,KAAK;AAAA,MACL,SAAS;AAAA,MACT,cAAc;AAAA,MACd,YAAY;AAAA,MACZ,UAAU;AAAA,MACV,YAAY;AAAA,MACZ,eAAe;AAAA,IACjB,CAAwC;AAExC,UAAM,MAAM,SAAS,cAAc,MAAM;AACzC,QAAI,YAAY;AAChB,WAAO,OAAO,IAAI,OAAO;AAAA,MACvB,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,cAAc;AAAA,MACd,YAAY;AAAA,MACZ,MAAM;AAAA,IACR,CAAwC;AACxC,YAAQ,OAAO,GAAG;AAClB,YAAQ,OAAO,SAAS,eAAe,wBAAmB,CAAC;AAC3D,YAAQ,OAAO,OAAO;AAAA,EACxB;AAAA,EAEQ,eAAe,SAAyB,OAAyB;AACvE,UAAM,OAAO,WAAW,KAAK;AAC7B,UAAM,OAAO,SAAS,cAAc,KAAK;AACzC,WAAO,OAAO,KAAK,OAAO;AAAA,MACxB,UAAU;AAAA,MACV,QAAQ;AAAA,MACR,SAAS;AAAA,MACT,WAAW;AAAA,MACX,YAAY;AAAA,MACZ,QAAQ;AAAA,MACR,cAAc;AAAA,MACd,WAAW;AAAA,IACb,CAAwC;AAExC,UAAM,UAAU,SAAS,cAAc,IAAI;AAC3C,YAAQ,cAAc,KAAK;AAC3B,WAAO,OAAO,QAAQ,OAAO;AAAA,MAC3B,QAAQ;AAAA,MACR,UAAU;AAAA,MACV,YAAY;AAAA,MACZ,OAAO;AAAA,IACT,CAAwC;AAExC,UAAM,OAAO,SAAS,cAAc,GAAG;AACvC,SAAK,cAAc,KAAK;AACxB,WAAO,OAAO,KAAK,OAAO;AAAA,MACxB,QAAQ;AAAA,MACR,UAAU;AAAA,MACV,YAAY;AAAA,MACZ,OAAO;AAAA,IACT,CAAwC;AAExC,UAAM,SAAS,SAAS,cAAc,QAAQ;AAC9C,WAAO,OAAO;AACd,WAAO,cAAc;AACrB,WAAO,OAAO,OAAO,OAAO;AAAA,MAC1B,YAAY;AAAA,MACZ,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,cAAc;AAAA,MACd,SAAS;AAAA,MACT,UAAU;AAAA,MACV,YAAY;AAAA,MACZ,OAAO;AAAA,MACP,YAAY;AAAA,IACd,CAAwC;AACxC,WAAO,iBAAiB,SAAS,MAAM,KAAK,eAAe,CAAC;AAE5D,SAAK,OAAO,SAAS,MAAM,MAAM;AACjC,YAAQ,OAAO,IAAI;AAAA,EACrB;AAkEF;;;AC3mBA;AAAA,EACE,oBAAAC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,cAAAC;AAAA,EACA,sBAAAC;AAAA,EACA,KAAAC;AAAA,EACA;AAAA,OASK;AAGP,IAAMC,oBAAmB;AACzB,IAAMC,yBAAwB;AAE9B,IAAM,mBAAmB;AAYzB,SAAS,eAAe,GAAW,GAAW,MAA2C;AACvF,MAAI,SAAS;AACb,WAAS,IAAI,GAAG,IAAI,KAAK,SAAS,GAAG,IAAI,KAAK,QAAQ,IAAI,KAAK;AAC7D,UAAM,KAAK,KAAK,CAAC,EAAE,GAAG,KAAK,KAAK,CAAC,EAAE,GAAG,KAAK,KAAK,CAAC,EAAE,GAAG,KAAK,KAAK,CAAC,EAAE;AACnE,QAAI,KAAK,MAAM,KAAK,KAAK,KAAM,KAAK,OAAO,IAAI,OAAQ,KAAK,MAAM,GAAI,UAAS,CAAC;AAAA,EAClF;AACA,SAAO;AACT;AAqLA,SAASC,kBAAiB,WAA8C;AACtE,MAAI,OAAO,cAAc,UAAU;AACjC,UAAM,KAAK,SAAS,cAAc,SAAS;AAC3C,QAAI,CAAC,GAAI,OAAM,IAAI,MAAM,uBAAuB,SAAS,aAAa;AACtE,WAAO;AAAA,EACT;AACA,MAAI,EAAE,qBAAqB,cAAc;AACvC,UAAM,IAAI,MAAM,6DAA6D;AAAA,EAC/E;AACA,SAAO;AACT;AAGA,IAAM,WAAW;AACjB,IAAM,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAA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","names":["resolveContainer","PickerController","loadLocale","setStringOverrides","t","DEFAULT_API_BASE","DEFAULT_MAX_SELECTION","resolveContainer","PickerController","t","loadLocale","setStringOverrides","pano","canView","esc","expandChart","resolveContainer","DEFAULT_API_BASE","STYLE_ID","CSS","t","expandChart","request","window"]}
|
|
1
|
+
{"version":3,"sources":["../src/SeatingChart.ts","../src/api.ts","../src/EmbeddedDesigner.ts","../src/SeatPicker.ts","../src/attachPickerFrame.ts","../src/SeatManager.ts","../src/manageApi.ts"],"sourcesContent":["/**\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 /** A prior active hold was restored with resumeHold(). */\n onHoldRestored?: (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 onHoldRestored: (h) => this.opts.onHoldRestored?.({ 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\n // \"Powered by SeatLayer\" attribution — the SDK embed is canvas-only, so\n // (unlike the full SeatPicker widget) nothing else renders this badge; no\n // duplication guard is needed. Shown by default; hidden only when the SERVED\n // chart doc's theme sets hideBadge (the API forces that false for orgs\n // without the white-label entitlement, so the client can trust the flag).\n this.buildBadge(host);\n return this;\n }\n\n /**\n * Attribution badge pinned to the embed's bottom-right, linking to\n * seatlayer.io. Rendered as an absolutely-positioned overlay with\n * self-contained inline styles — the SDK embed ships no widget CSS, and an\n * overlay keeps it out of the layout flow so it never disturbs the SDK v0.22\n * fill-height resize contract. Mirrors the full widget's mark + wordmark and\n * reuses the `picker.poweredBy` i18n string.\n */\n private buildBadge(host: HTMLDivElement): void {\n if (this.controller.doc?.theme?.hideBadge) return;\n const badge = document.createElement('a');\n badge.href = 'https://seatlayer.io';\n badge.target = '_blank';\n badge.rel = 'noopener noreferrer';\n badge.setAttribute('aria-label', t('picker.poweredBy'));\n badge.style.cssText =\n 'position:absolute;bottom:10px;right:12px;z-index:5;' +\n 'display:inline-flex;align-items:center;gap:6px;padding:5px 9px;border-radius:999px;' +\n 'background:rgba(255,255,255,.92);color:#4a5163;text-decoration:none;' +\n 'font:600 11px/1 -apple-system,BlinkMacSystemFont,\"Segoe UI\",sans-serif;letter-spacing:.02em;' +\n 'box-shadow:0 2px 8px rgba(0,0,0,.12);';\n badge.innerHTML =\n '<span aria-hidden=\"true\" style=\"width:16px;height:16px;border-radius:4px;flex:none;' +\n 'display:flex;align-items:center;justify-content:center;background:#f4b740;color:#1a1200\">' +\n '<svg viewBox=\"0 0 24 24\" style=\"width:11px;height:11px;fill:currentColor\">' +\n '<path d=\"M4 15c0-1.1.9-2 2-2h12a2 2 0 0 1 2 2v3h-3v-2H7v2H4v-3Z\"/>' +\n '<rect x=\"7\" y=\"7\" width=\"10\" height=\"5\" rx=\"1.6\"/></svg></span>' +\n `<span>${t('picker.poweredBy')}</span>`;\n host.appendChild(badge);\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 /** Restore an active hold by its opaque id without extending its expiry. */\n async resumeHold(holdId: string): Promise<HoldResult | null> {\n try {\n const h = await this.controller.resumeHold(holdId);\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 /** Current active hold known to this chart, if any. */\n getCurrentHold(): HoldResult | null {\n const h = this.controller.currentHold();\n return h ? { holdId: h.holdId, expiresAt: h.expiresAt, seats: h.seats, items: h.items } : null;\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 /** Release selected labels from the current hold while keeping the remainder. */\n async releaseLabels(labels: string[]): Promise<boolean> {\n return this.controller.releaseLabels(labels);\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 /** Section/zone ids hidden from buyers this event (seats stripped from the map). */\n hidden?: string[];\n /** Section/zone ids in the `closed` state (Phase 2): rendered grey + not purchasable. */\n closed?: 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/** Browser-safe active-hold projection returned by the resume endpoint. */\nexport interface ResumedHoldResult extends HoldResult {\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 private readonly viewerId = typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function'\n ? crypto.randomUUID()\n : `viewer_${Math.random().toString(36).slice(2)}${Date.now().toString(36)}`;\n\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 resume(key: string, holdId: string): Promise<ResumedHoldResult> {\n return request(this.base, `/pub/events/${encodeURIComponent(key)}/hold/resume`, {\n method: 'POST',\n body: { holdId },\n });\n }\n\n release(key: string, labels: string[], holdId: string): Promise<{ ok: true; released?: string[] }> {\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 const params = new URLSearchParams({ surface: 'picker', viewerId: this.viewerId });\n return `${wsBase}/pub/events/${encodeURIComponent(key)}/subscribe?${params}`;\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 /**\n * Show the built-in branded loading skeleton and error/expiry card inside the\n * container while the Designer boots. Defaults to `true`. Set `false` when the\n * host renders its own loading and error chrome.\n */\n showLoadingState?: boolean;\n /**\n * If the Designer never posts `ready` within this many milliseconds, the host\n * transitions to the error card with a timeout message. Defaults to `20000`.\n * Only used when `showLoadingState` is enabled.\n */\n loadingTimeoutMs?: number;\n /**\n * How to size the iframe's height. The Designer is a full application (its\n * shell is `position:fixed; height:100dvh`), not flowing content, so it should\n * fill its box rather than be measured.\n *\n * - `'fill'` (default): container-aware. On mount the SDK probes whether the\n * host gave the container a DEFINITE (bounded) height:\n * - **Bounded container** (a fixed-height block, `height`/`max-height`,\n * `flex:1; min-h:0`, a resolved `%`, etc.) → the iframe fills 100% of\n * that block and tracks its size live via a `ResizeObserver`.\n * - **Content-sized container** (the block collapses to whatever the iframe\n * measures — typical full-page usage) → the iframe grows so its bottom\n * edge reaches the bottom of the viewport (`window.innerHeight -\n * iframe.top`), recomputed (rAF-throttled) on `resize` /\n * `orientationchange` / `scroll`.\n * Either way the result is clamped to `minHeight`. The verdict is cached but\n * re-probed on `resize`/`orientationchange` so a responsive host layout can\n * flip between the two. The legacy `seatlayer.designer.resize` message is\n * ignored in `'fill'` mode: it is circular, because the fixed-position shell\n * just echoes the iframe height.\n * - a number: a fixed pixel height. In this mode the legacy resize message is\n * still honoured (unless `autoResize` is `false`) so older hosts keep growing.\n *\n * All SDK-managed heights are written with `!important` priority so a host\n * theme's `iframe { height: … !important }` cannot override them.\n */\n height?: 'fill' | number;\n /** Minimum height (px) that `'fill'` mode clamps to. Defaults to `480`. */\n minHeight?: number;\n /**\n * Auto-grow the iframe to the height the Designer reports over the resize\n * protocol (`seatlayer.designer.resize`). Only applies when `height` is a fixed\n * number; ignored in `'fill'` mode. Defaults to `true`. Set `false` when the\n * host sizes a fixed-height iframe itself.\n */\n autoResize?: boolean;\n /**\n * Called when the user presses \"Try again\" on the error card. Use it to mint a\n * fresh Designer session and call `setDesignerUrl()` with the new URL, which\n * recreates the iframe and returns to the loading state. When omitted, \"Try\n * again\" reloads the current `designerUrl` in place.\n *\n * When supplied, it also powers automatic session renewal — see\n * {@link EmbeddedDesignerOptions.autoRenewSession}.\n */\n onRequestRelaunch?: () => void;\n /**\n * Keep long editing sessions alive without the user ever hitting the expiry\n * wall. Designer sessions are short-lived security tokens; when the host wires\n * `onRequestRelaunch` the SDK, with this enabled, will:\n *\n * - **Renew proactively.** From each `ready` message's `expiresAt` it schedules\n * a silent relaunch shortly before the session lapses (~3 min ahead; for a\n * TTL under 15 min it renews after 80% of the remaining life, and never\n * sooner than 30s after `ready`). The host mints a fresh session and swaps\n * `designerUrl`, so the editor keeps working with no error card.\n * - **Recover on expiry.** If an expiry error still slips through (a slept\n * laptop woke past the renewal window, say) it makes ONE automatic relaunch\n * attempt before showing the \"Try again\" card, and only falls back to the\n * card if that relaunch also fails.\n *\n * Defaults to `true` whenever `onRequestRelaunch` is provided; a no-op without\n * it. Set `false` to keep the fully manual \"Try again\" behavior.\n */\n autoRenewSession?: boolean;\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\nconst DEFAULT_LOADING_TIMEOUT_MS = 20000;\nconst DEFAULT_MIN_FILL_HEIGHT = 480;\n/**\n * Proactive session-renewal timing (see {@link EmbeddedDesigner.scheduleRenewal}).\n * We aim to relaunch a comfortable lead ahead of `expiresAt`; short-lived sessions\n * instead renew after a fraction of their life so the lead never overshoots the TTL.\n */\nconst RENEW_LEAD_MS = 3 * 60 * 1000; // standard lead: renew ~3 min before expiry\nconst RENEW_SHORT_TTL_MS = 15 * 60 * 1000; // below this TTL, use the fraction clamp\nconst RENEW_SHORT_TTL_FRACTION = 0.8; // short TTL: renew after 80% of remaining life\nconst RENEW_MIN_DELAY_MS = 30 * 1000; // never renew sooner than 30s after `ready`\n/**\n * Container-fill detection tunables. The probe drives the iframe to two extreme\n * heights within one synchronous task (no paint between reads, so no flash) and\n * watches whether the container tracks it.\n */\nconst FILL_PROBE_HEIGHT_PX = 100000; // \"huge\" iframe used to see if the box grows with it\nconst FILL_PROBE_TRACK_EPSILON_PX = 4; // container grew with the iframe ⇒ content-sized\nconst FILL_MIN_DEFINITE_HEIGHT_PX = 50; // a bounded box must keep at least this much height\n\n/** Internal reason the error card is being shown, used to pick human copy. */\ntype ErrorCause = 'expired' | 'mismatch' | 'timeout' | 'load';\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/** Map an error message's `code` onto one of the human-copy causes. */\nfunction causeFromCode(code: string | undefined): ErrorCause {\n const value = (code ?? '').toLowerCase();\n if (value.includes('expire') || value.includes('revoke') || value === '401') return 'expired';\n if (value.includes('mismatch')) return 'mismatch';\n if (value.includes('timeout')) return 'timeout';\n return 'load';\n}\n\nconst ERROR_COPY: Record<ErrorCause, { title: string; body: string }> = {\n expired: {\n title: 'This design session expired',\n body: 'For your security, editing sessions are short-lived. Start a fresh one to keep designing.',\n },\n mismatch: {\n title: \"This editor doesn't match this chart\",\n body: 'The session that loaded belongs to a different chart or workspace. Reopen the designer to continue.',\n },\n timeout: {\n title: 'The designer is taking too long',\n body: 'It did not finish loading in time. This is usually a slow connection — try again.',\n },\n load: {\n title: \"We couldn't load the designer\",\n body: 'Something went wrong while opening the editor. Please try again.',\n },\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 private overlay: HTMLDivElement | null = null;\n private timeoutTimer: ReturnType<typeof setTimeout> | null = null;\n /** Proactive session-renewal timer; armed from each `ready`, cleared on re-mount. */\n private renewTimer: ReturnType<typeof setTimeout> | null = null;\n /**\n * One automatic recovery relaunch is allowed per expiry. Reset ONLY when a fresh\n * `ready` arrives — deliberately not on re-mount — so a session that keeps failing\n * to load can't loop the host through endless silent relaunches.\n */\n private autoRecoverUsed = false;\n private phase: 'loading' | 'ready' | 'error' = 'loading';\n private restoreContainerPosition: string | null = null;\n // Host-side fullscreen pin: saved state we restore on `off`/Escape/destroy.\n private pinned = false;\n private frameStyleBeforeFs: string | null = null;\n private docOverflowBeforeFs: string | null = null;\n private bodyOverflowBeforeFs: string | null = null;\n private fsKeyHandler: ((event: KeyboardEvent) => void) | null = null;\n /** Latest height (px string) the Designer reported; re-applied after unpin. */\n private lastAutoHeight = '';\n // Fill sizing: pending rAF handles + whether window listeners are attached.\n private fillRaf: number | null = null;\n private reprobeRaf: number | null = null;\n private fillListening = false;\n /** Resolved container element (fill measurement + ResizeObserver target). */\n private containerEl: HTMLElement | null = null;\n /** Cached fill verdict: 'container' = bounded block, 'viewport' = full page. */\n private fillMode: 'viewport' | 'container' | null = null;\n /** Live block-size tracking in container-fill mode; disconnected on destroy. */\n private resizeObs: ResizeObserver | null = null;\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 ?? 'fullscreen; clipboard-write';\n frame.referrerPolicy = this.options.referrerPolicy ?? 'origin';\n frame.src = url.toString();\n // Width/height are written with `!important` priority so a host theme's\n // `iframe { height: … !important }` cannot beat the SDK's inline sizing.\n frame.style.setProperty('width', '100%', 'important');\n // `'fill'` (default) is (re)computed once the frame is in the DOM (see\n // startFill); a numeric height is a fixed pixel box.\n frame.style.setProperty(\n 'height',\n typeof this.options.height === 'number' ? `${this.options.height}px` : '100%',\n 'important',\n );\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 const container = resolveContainer(this.options.container);\n this.containerEl = container;\n window.addEventListener('message', this.handleMessage);\n container.append(frame);\n this.frame = frame;\n\n // Fill mode owns the height from the viewport now the frame is measurable.\n if (this.fillEnabled()) this.startFill();\n\n this.phase = 'loading';\n if (this.loadingStateEnabled()) {\n this.ensureContainerPositioned(container);\n this.renderOverlay(container, 'loading');\n const timeout = this.options.loadingTimeoutMs ?? DEFAULT_LOADING_TIMEOUT_MS;\n if (timeout > 0 && Number.isFinite(timeout)) {\n this.timeoutTimer = setTimeout(() => {\n if (this.phase === 'loading') this.showError('timeout');\n }, timeout);\n }\n }\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 // mount() tears everything down and re-enters the loading state.\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.stopFill();\n this.unpinFullscreen();\n this.clearTimeoutTimer();\n this.clearRenewTimer();\n this.removeOverlay();\n this.restoreContainerStyle();\n this.frame?.remove();\n this.frame = null;\n this.containerEl = null;\n this.fillMode = null;\n this.designerOrigin = '';\n this.phase = 'loading';\n this.lastAutoHeight = '';\n }\n\n private loadingStateEnabled(): boolean {\n return this.options.showLoadingState !== false;\n }\n\n private autoResizeEnabled(): boolean {\n return this.options.autoResize !== false;\n }\n\n /** Fill mode is the default; a numeric `height` opts into a fixed pixel box. */\n private fillEnabled(): boolean {\n return typeof this.options.height !== 'number';\n }\n\n /** Write an SDK-managed height with `!important` so a host theme can't win. */\n private setFrameHeight(value: string): void {\n this.frame?.style.setProperty('height', value, 'important');\n }\n\n /**\n * Decide whether the host gave the container a DEFINITE (bounded) height — a\n * fixed block the embed should fill 100% of — versus a content-sized container\n * that collapses to whatever the iframe measures (full-page usage).\n *\n * We drive the iframe to two extreme heights within a single synchronous task\n * and watch whether the container follows: a bounded box barely moves, a\n * content-sized one grows with the iframe. Because we restore the height before\n * yielding, the browser only lays out — it never paints the extremes, so there\n * is no visible flash. Works for px, resolved `%`, and flex (`flex:1;min-h:0`)\n * heights, and leaves a mere `min-height` floor classified as content-sized so\n * full-page hosts keep the old viewport-fill behavior.\n */\n private detectFillMode(): 'viewport' | 'container' {\n const container = this.containerEl;\n const frame = this.frame;\n if (this.pinned || !container || !frame) return this.fillMode ?? 'viewport';\n const measure = (): number => container.getBoundingClientRect().height;\n const savedValue = frame.style.getPropertyValue('height');\n const savedPriority = frame.style.getPropertyPriority('height');\n\n frame.style.setProperty('height', '0px', 'important');\n const collapsed = measure();\n frame.style.setProperty('height', `${FILL_PROBE_HEIGHT_PX}px`, 'important');\n const expanded = measure();\n\n if (savedValue) frame.style.setProperty('height', savedValue, savedPriority);\n else frame.style.removeProperty('height');\n\n const tracksIframe = expanded - collapsed > FILL_PROBE_TRACK_EPSILON_PX;\n const bounded = !tracksIframe && collapsed >= FILL_MIN_DEFINITE_HEIGHT_PX;\n return bounded ? 'container' : 'viewport';\n }\n\n /**\n * Size the iframe for the current fill verdict, clamped to `minHeight`. In\n * container mode it fills 100% of the bounded block; in viewport mode its\n * bottom edge meets the bottom of the viewport (`window.innerHeight - top`).\n * No-op while pinned fullscreen (the pin fills the viewport itself).\n */\n private applyFill(): void {\n if (!this.frame || this.pinned) return;\n const min = this.options.minHeight ?? DEFAULT_MIN_FILL_HEIGHT;\n if (this.fillMode === 'container' && this.containerEl) {\n const target = Math.max(min, Math.round(this.containerEl.getBoundingClientRect().height));\n this.setFrameHeight(`${target}px`);\n return;\n }\n const top = this.frame.getBoundingClientRect().top;\n const target = Math.max(min, Math.round(window.innerHeight - top));\n this.setFrameHeight(`${target}px`);\n }\n\n /** rAF-throttled fill recompute, so a burst of scroll/RO ticks coalesces. */\n private scheduleFill = (): void => {\n if (this.fillRaf !== null) return;\n this.fillRaf = requestAnimationFrame(() => {\n this.fillRaf = null;\n this.applyFill();\n });\n };\n\n /**\n * rAF-throttled re-probe: a host layout change (responsive breakpoint, a block\n * gaining/losing a definite height) can flip the verdict, so `resize` /\n * `orientationchange` re-detect and swap the container observer accordingly.\n */\n private scheduleReprobe = (): void => {\n if (this.reprobeRaf !== null) return;\n this.reprobeRaf = requestAnimationFrame(() => {\n this.reprobeRaf = null;\n if (this.pinned) return;\n this.fillMode = this.detectFillMode();\n this.syncContainerObserver();\n this.applyFill();\n });\n };\n\n /** Attach/detach the container ResizeObserver to match the current verdict. */\n private syncContainerObserver(): void {\n const want =\n this.fillMode === 'container' && !!this.containerEl && typeof ResizeObserver !== 'undefined';\n if (want && !this.resizeObs) {\n this.resizeObs = new ResizeObserver(() => this.scheduleFill());\n this.resizeObs.observe(this.containerEl!);\n } else if (!want && this.resizeObs) {\n this.resizeObs.disconnect();\n this.resizeObs = null;\n }\n }\n\n private startFill(): void {\n this.fillMode = this.detectFillMode();\n this.syncContainerObserver();\n this.applyFill();\n if (this.fillListening) return;\n this.fillListening = true;\n // Layout-changing events re-probe (the verdict can flip); scroll only shifts\n // the viewport-fill top offset, so it just re-applies.\n window.addEventListener('resize', this.scheduleReprobe);\n window.addEventListener('orientationchange', this.scheduleReprobe);\n window.addEventListener('scroll', this.scheduleFill, { passive: true });\n }\n\n private stopFill(): void {\n if (this.fillRaf !== null) {\n cancelAnimationFrame(this.fillRaf);\n this.fillRaf = null;\n }\n if (this.reprobeRaf !== null) {\n cancelAnimationFrame(this.reprobeRaf);\n this.reprobeRaf = null;\n }\n if (this.resizeObs) {\n this.resizeObs.disconnect();\n this.resizeObs = null;\n }\n if (!this.fillListening) return;\n this.fillListening = false;\n window.removeEventListener('resize', this.scheduleReprobe);\n window.removeEventListener('orientationchange', this.scheduleReprobe);\n window.removeEventListener('scroll', this.scheduleFill);\n }\n\n /**\n * Pin the iframe over the host page as a viewport-filling overlay. We save the\n * iframe's inline style and the document scroll state so `unpinFullscreen`\n * restores everything exactly. Escape (host-side) also exits.\n */\n private pinFullscreen(): void {\n if (this.pinned || !this.frame) return;\n this.pinned = true;\n this.frameStyleBeforeFs = this.frame.getAttribute('style');\n // Every pin property is `!important` so a host theme's `iframe { … }` rules\n // (height/width/inset) can't unpin us. `inset` is written as its four longhands\n // for reliability across engines. Restored wholesale via the saved style attr.\n const pin: Record<string, string> = {\n position: 'fixed',\n top: '0',\n right: '0',\n bottom: '0',\n left: '0',\n width: '100vw',\n height: '100vh',\n margin: '0',\n border: '0',\n 'z-index': '2147483000',\n background: '#101625',\n };\n for (const [property, value] of Object.entries(pin)) {\n this.frame.style.setProperty(property, value, 'important');\n }\n\n const docEl = document.documentElement;\n this.docOverflowBeforeFs = docEl.style.overflow;\n docEl.style.overflow = 'hidden';\n if (document.body) {\n this.bodyOverflowBeforeFs = document.body.style.overflow;\n document.body.style.overflow = 'hidden';\n }\n\n this.fsKeyHandler = (event: KeyboardEvent): void => {\n if (event.key === 'Escape') this.unpinFullscreen();\n };\n window.addEventListener('keydown', this.fsKeyHandler);\n }\n\n /** Undo `pinFullscreen`: restore the iframe style + scroll lock. Idempotent. */\n private unpinFullscreen(): void {\n if (!this.pinned) return;\n this.pinned = false;\n if (this.frame) {\n if (this.frameStyleBeforeFs === null) this.frame.removeAttribute('style');\n else this.frame.setAttribute('style', this.frameStyleBeforeFs);\n // Restore the right height for the mode: recompute the fill, or re-apply\n // the last height the Designer reported (numeric mode). Both use\n // `!important` so a host theme can't win after we unpin.\n if (this.fillEnabled()) this.applyFill();\n else if (this.autoResizeEnabled() && this.lastAutoHeight) this.setFrameHeight(this.lastAutoHeight);\n }\n this.frameStyleBeforeFs = null;\n\n if (this.docOverflowBeforeFs !== null) {\n document.documentElement.style.overflow = this.docOverflowBeforeFs;\n this.docOverflowBeforeFs = null;\n }\n if (this.bodyOverflowBeforeFs !== null && document.body) {\n document.body.style.overflow = this.bodyOverflowBeforeFs;\n this.bodyOverflowBeforeFs = null;\n }\n if (this.fsKeyHandler) {\n window.removeEventListener('keydown', this.fsKeyHandler);\n this.fsKeyHandler = null;\n }\n }\n\n private clearTimeoutTimer(): void {\n if (this.timeoutTimer !== null) {\n clearTimeout(this.timeoutTimer);\n this.timeoutTimer = null;\n }\n }\n\n /**\n * Auto-renewal (proactive + one expiry recovery) is on when the host wired a\n * relaunch hook and did not opt out. Without the hook there is nothing to call,\n * so it is a no-op.\n */\n private autoRenewEnabled(): boolean {\n return !!this.options.onRequestRelaunch && this.options.autoRenewSession !== false;\n }\n\n private clearRenewTimer(): void {\n if (this.renewTimer !== null) {\n clearTimeout(this.renewTimer);\n this.renewTimer = null;\n }\n }\n\n /**\n * Arm the proactive renewal timer from a `ready` message's `expiresAt` (epoch\n * ms). We relaunch a comfortable lead before expiry so the host can mint a fresh\n * session and swap `designerUrl` without the user ever seeing the expiry card:\n *\n * - normal TTL (≥ 15 min): renew {@link RENEW_LEAD_MS} (~3 min) before expiry;\n * - short TTL (< 15 min): renew after {@link RENEW_SHORT_TTL_FRACTION} (80%) of\n * the remaining life, so the lead can't overshoot the whole session;\n * - either way, never sooner than {@link RENEW_MIN_DELAY_MS} (30s) after `ready`\n * so a burst of `ready` messages can't spin the host.\n *\n * Re-armed on every `ready`; cleared on destroy / setDesignerUrl (via re-mount).\n * A no-op when auto-renewal is off or `expiresAt` is missing/already past — the\n * expiry-error path recovers a session that has already lapsed.\n */\n private scheduleRenewal(expiresAt: number | undefined): void {\n this.clearRenewTimer();\n if (!this.autoRenewEnabled()) return;\n if (typeof expiresAt !== 'number' || !Number.isFinite(expiresAt)) return;\n const remaining = expiresAt - Date.now();\n if (remaining <= 0) return;\n const lead =\n remaining < RENEW_SHORT_TTL_MS\n ? remaining * RENEW_SHORT_TTL_FRACTION\n : remaining - RENEW_LEAD_MS;\n const delay = Math.max(RENEW_MIN_DELAY_MS, lead);\n this.renewTimer = setTimeout(() => {\n this.renewTimer = null;\n // Silent renewal: the host mints a fresh session and swaps designerUrl,\n // which re-mounts the iframe and re-arms us from the next `ready`.\n if (this.autoRenewEnabled()) this.options.onRequestRelaunch!();\n }, delay);\n }\n\n private ensureContainerPositioned(container: HTMLElement): void {\n // The overlay is absolutely positioned; the container must establish a\n // positioning context. Only touch a `static` container, and remember to\n // restore it on destroy.\n const position = getComputedStyle(container).position;\n if (position === 'static') {\n this.restoreContainerPosition = container.style.position;\n container.style.position = 'relative';\n }\n }\n\n private restoreContainerStyle(): void {\n if (this.restoreContainerPosition === null) return;\n try {\n resolveContainer(this.options.container).style.position = this.restoreContainerPosition;\n } catch {\n /* container already gone — nothing to restore */\n }\n this.restoreContainerPosition = null;\n }\n\n private removeOverlay(): void {\n this.overlay?.remove();\n this.overlay = null;\n }\n\n private showError(cause: ErrorCause): void {\n this.phase = 'error';\n this.clearTimeoutTimer();\n if (!this.loadingStateEnabled()) return;\n let container: HTMLElement;\n try {\n container = resolveContainer(this.options.container);\n } catch {\n return;\n }\n this.renderOverlay(container, 'error', cause);\n }\n\n private handleTryAgain(): void {\n if (this.options.onRequestRelaunch) {\n // Host mints a fresh session and calls setDesignerUrl(), which re-mounts\n // the iframe and returns to the loading state.\n this.options.onRequestRelaunch();\n return;\n }\n // No relaunch hook: reload the same session URL in place.\n this.mount();\n }\n\n /**\n * Build (or rebuild) the overlay for the given phase. A single overlay element\n * is reused so we never stack stale skeletons or cards.\n */\n private renderOverlay(container: HTMLElement, phase: 'loading' | 'error', cause?: ErrorCause): void {\n this.removeOverlay();\n const overlay = document.createElement('div');\n overlay.setAttribute('data-seatlayer-designer-overlay', phase);\n overlay.setAttribute('role', phase === 'error' ? 'alert' : 'status');\n overlay.setAttribute('aria-live', 'polite');\n Object.assign(overlay.style, {\n position: 'absolute',\n inset: '0',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n background: '#101625',\n color: '#e6ebf5',\n fontFamily:\n '-apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, Helvetica, Arial, sans-serif',\n zIndex: '2',\n overflow: 'hidden',\n } satisfies Partial<CSSStyleDeclaration>);\n\n if (phase === 'loading') this.buildSkeleton(overlay);\n else this.buildErrorCard(overlay, cause ?? 'load');\n\n container.append(overlay);\n this.overlay = overlay;\n }\n\n private buildSkeleton(overlay: HTMLDivElement): void {\n // Scoped keyframes; the shimmer only runs when the user allows motion.\n const style = document.createElement('style');\n style.textContent = `\n@media (prefers-reduced-motion: no-preference) {\n @keyframes seatlayer-designer-shimmer {\n 0% { background-position: -320px 0; }\n 100% { background-position: 320px 0; }\n }\n [data-seatlayer-designer-overlay=\"loading\"] .sl-shimmer {\n animation: seatlayer-designer-shimmer 1.25s ease-in-out infinite;\n background-size: 640px 100%;\n }\n}`;\n overlay.append(style);\n\n const shimmer =\n 'linear-gradient(90deg, rgba(255,255,255,0.04) 25%, rgba(255,255,255,0.10) 37%, rgba(255,255,255,0.04) 63%)';\n\n const scaffold = document.createElement('div');\n Object.assign(scaffold.style, {\n position: 'absolute',\n inset: '0',\n display: 'flex',\n flexDirection: 'column',\n padding: '16px',\n gap: '14px',\n opacity: '0.9',\n } satisfies Partial<CSSStyleDeclaration>);\n\n const bar = (styles: Partial<CSSStyleDeclaration>): HTMLDivElement => {\n const node = document.createElement('div');\n node.className = 'sl-shimmer';\n Object.assign(node.style, {\n background: shimmer,\n borderRadius: '8px',\n } satisfies Partial<CSSStyleDeclaration>);\n Object.assign(node.style, styles);\n return node;\n };\n\n // Top toolbar row.\n scaffold.append(bar({ height: '40px', width: '100%', flex: '0 0 auto' }));\n\n // Body: side panel + canvas.\n const body = document.createElement('div');\n Object.assign(body.style, {\n display: 'flex',\n gap: '14px',\n flex: '1 1 auto',\n minHeight: '0',\n } satisfies Partial<CSSStyleDeclaration>);\n body.append(bar({ width: '220px', height: '100%', flex: '0 0 auto' }));\n body.append(bar({ flex: '1 1 auto', height: '100%' }));\n scaffold.append(body);\n\n overlay.append(scaffold);\n\n // Centered caption above the scaffold.\n const caption = document.createElement('div');\n Object.assign(caption.style, {\n position: 'relative',\n zIndex: '1',\n display: 'flex',\n alignItems: 'center',\n gap: '10px',\n padding: '10px 16px',\n borderRadius: '999px',\n background: 'rgba(16, 22, 37, 0.72)',\n fontSize: '13px',\n fontWeight: '500',\n letterSpacing: '0.01em',\n } satisfies Partial<CSSStyleDeclaration>);\n\n const dot = document.createElement('span');\n dot.className = 'sl-shimmer';\n Object.assign(dot.style, {\n width: '9px',\n height: '9px',\n borderRadius: '50%',\n background: shimmer,\n flex: '0 0 auto',\n } satisfies Partial<CSSStyleDeclaration>);\n caption.append(dot);\n caption.append(document.createTextNode('Loading designer…'));\n overlay.append(caption);\n }\n\n private buildErrorCard(overlay: HTMLDivElement, cause: ErrorCause): void {\n const copy = ERROR_COPY[cause];\n const card = document.createElement('div');\n Object.assign(card.style, {\n maxWidth: '420px',\n margin: '0 24px',\n padding: '28px',\n textAlign: 'center',\n background: 'rgba(255, 255, 255, 0.03)',\n border: '1px solid rgba(255, 255, 255, 0.08)',\n borderRadius: '16px',\n boxShadow: '0 12px 40px rgba(0, 0, 0, 0.35)',\n } satisfies Partial<CSSStyleDeclaration>);\n\n const heading = document.createElement('h2');\n heading.textContent = copy.title;\n Object.assign(heading.style, {\n margin: '0 0 8px',\n fontSize: '17px',\n fontWeight: '600',\n color: '#f4f7ff',\n } satisfies Partial<CSSStyleDeclaration>);\n\n const body = document.createElement('p');\n body.textContent = copy.body;\n Object.assign(body.style, {\n margin: '0 0 20px',\n fontSize: '13.5px',\n lineHeight: '1.5',\n color: '#aab4c8',\n } satisfies Partial<CSSStyleDeclaration>);\n\n const button = document.createElement('button');\n button.type = 'button';\n button.textContent = 'Try again';\n Object.assign(button.style, {\n appearance: 'none',\n cursor: 'pointer',\n border: '0',\n borderRadius: '10px',\n padding: '10px 22px',\n fontSize: '14px',\n fontWeight: '600',\n color: '#101625',\n background: '#7aa2ff',\n } satisfies Partial<CSSStyleDeclaration>);\n button.addEventListener('click', () => this.handleTryAgain());\n\n card.append(heading, body, button);\n overlay.append(card);\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\n // Layout protocol — origin-locked like everything else, but handled here\n // rather than dispatched to the host callbacks.\n if (data.type === 'seatlayer.designer.resize') {\n // Fill mode owns the height from the viewport; the reported scrollHeight is\n // circular (the fixed-position shell echoes the iframe height), so ignore\n // it. Only a fixed numeric height honours the legacy auto-grow.\n if (!this.fillEnabled() && this.autoResizeEnabled()\n && typeof data.px === 'number' && Number.isFinite(data.px) && data.px > 0) {\n this.lastAutoHeight = `${Math.round(data.px)}px`;\n // While pinned fullscreen the iframe fills the viewport; apply the\n // reported height only when not pinned (it's re-applied on unpin).\n // `!important` so a host theme's `iframe { height … }` can't win.\n if (!this.pinned) this.setFrameHeight(this.lastAutoHeight);\n }\n return;\n }\n if (data.type === 'seatlayer.designer.fullscreen') {\n if (data.on === true) this.pinFullscreen();\n else if (data.on === false) this.unpinFullscreen();\n return;\n }\n\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 (\n (this.options.expectedChartId && message.chartId && message.chartId !== this.options.expectedChartId) ||\n (this.options.expectedWorkspaceId && message.workspaceId && message.workspaceId !== this.options.expectedWorkspaceId)\n ) {\n // A message from our exact iframe carrying the wrong identity is a real\n // session mismatch, not spoofing. Surface it (loading state on) rather than\n // dispatching it to the host callbacks.\n this.showError('mismatch');\n return;\n }\n\n switch (message.type) {\n case 'seatlayer.designer.ready':\n this.phase = 'ready';\n this.clearTimeoutTimer();\n this.removeOverlay();\n // A fresh live session: clear the recovery guard and (re)arm proactive\n // renewal from this session's expiry.\n this.autoRecoverUsed = false;\n this.scheduleRenewal(message.expiresAt);\n this.options.onReady?.(message);\n 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': {\n const cause = causeFromCode(message.code);\n // Expiry is recoverable. If the host wired a relaunch hook, make ONE\n // silent auto-relaunch before ever showing the dead-end card — the user\n // never sees an overlay. Guarded (reset only on a fresh `ready`) so a\n // session that keeps failing to load falls through to the card instead of\n // looping the host.\n if (cause === 'expired' && this.autoRenewEnabled() && !this.autoRecoverUsed) {\n this.autoRecoverUsed = true;\n this.clearRenewTimer();\n this.options.onRequestRelaunch!();\n return;\n }\n this.showError(cause);\n this.options.onError?.(message);\n break;\n }\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 contract: 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 generateSeatThumb,\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 PickerTransport,\n type SeatHoverDetails,\n type SectionSummary,\n} from '@seatlayer/core';\nimport { PubApi, type HoldLineItem, type HoldResult } from './api';\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/** Minimal shape of a section object read off the ChartDoc for the minimap. */\ninterface SectionLike {\n type: string;\n id: string;\n outline?: { x: number; y: number }[];\n color?: string;\n zone?: string;\n}\n\n/** Even-odd point-in-polygon test in world units (minimap click → section). */\nfunction pointInPolygon(x: number, y: number, poly: { x: number; y: number }[]): boolean {\n let inside = false;\n for (let i = 0, j = poly.length - 1; i < poly.length; j = i++) {\n const xi = poly[i].x, yi = poly[i].y, xj = poly[j].x, yj = poly[j].y;\n if (yi > y !== yj > y && x < ((xj - xi) * (y - yi)) / (yj - yi) + xi) inside = !inside;\n }\n return inside;\n}\n\n/** One price band in the F4 filter — a set of category keys within a price range. */\ninterface PriceBand {\n id: string;\n label: string;\n keys: string[];\n min: number;\n max: number;\n}\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-authoritative pricing — see {@link SeatPickerOptions.pricing}. */\nexport interface SeatPickerPricing {\n /** Unit prices by category key: a flat number, or `{ base, tiers: { tierId: price } }`. */\n prices?: Record<string, number | { base?: number; tiers?: Record<string, number> }>;\n /** Custom money renderer (e.g. `(n) => n + '€'`). Defaults to Intl currency formatting. */\n formatter?: (amount: number, currency: string) => string;\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 /**\n * Custom data transport. Defaults to the CORS-trivial PubApi against\n * `apiBase`. Inject to run the widget against another backend adapter (the\n * SeatLayer dashboard's own transport) or a fully local mock (demos).\n */\n transport?: PickerTransport;\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 /**\n * Hide the \"Powered by SeatLayer\" attribution badge in the side panel foot.\n * The chart theme's own `hideBadge` flag (paid orgs) also hides it — the badge\n * is shown only when BOTH this option and the theme flag are unset/false.\n */\n hideBadge?: boolean;\n /** Host theme overrides — see SeatPickerTheme. */\n theme?: SeatPickerTheme;\n /**\n * Host-authoritative pricing. When your shop charges different prices than\n * the chart's stored category prices, pass them here so the buyer sees the\n * price they will actually pay — on the map tooltip, confirm popover, price\n * panel, tray, totals, and in the checkout handoff's line items. Keyed by\n * category key; per-tier overrides nest under `tiers`. Unlisted categories\n * fall back to the chart price.\n */\n pricing?: SeatPickerPricing;\n /** Hold TTL in ms passed to hold(); server clamps to its own limits. */\n holdTtlMs?: number;\n /**\n * An opaque hold id supplied by the host to restore after navigation. It is\n * verified against the event and active server state before anything renders\n * as owned by this buyer.\n */\n initialHoldId?: string;\n /**\n * Automatically remember the active hold id in sessionStorage and restore it\n * when this event's picker mounts again. Default true. Set false when the host\n * owns hold persistence and supplies initialHoldId itself.\n */\n restoreHold?: boolean;\n /**\n * Confirm mode: tapping a seat shows a confirmation card with section, row,\n * seat, category, price and Select/Cancel before it enters the tray. Default\n * true for the full buyer picker; set false only when the host supplies its\n * own equivalent confirmation UI.\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 /**\n * Active hold changed because it was created, restored, extended, partially\n * released, or fully released. Hosts should persist this state for route\n * navigation and clear their checkout cart when `hold` becomes null.\n */\n onHoldChange?: (hold: HoldResult | null, seats: PickerSeat[], handoff: CheckoutHandoff | null) => void;\n /** The open hold expired server-side (widget already reset itself). */\n onHoldExpired?: () => void;\n /** A prior active hold was verified and restored into the tray. */\n onHoldRestored?: (hold: HoldResult, seats: PickerSeat[], handoff: CheckoutHandoff) => 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 transform-origin:right center}\n.sl-hold-pill.on{display:inline-flex;animation:slPillIn .34s cubic-bezier(.2,.8,.2,1) both}\n.sl-hold-dot{width:7px;height:7px;border-radius:50%;background:currentColor;opacity:.78;box-shadow:0 0 0 0 currentColor}\n.sl-hold-pill.is-expiring .sl-hold-dot{animation:slHoldPulse 1.4s ease-out infinite}\n.sl-hold-time{min-width:3.35em;text-align:left}\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:hidden}\n\n/* narrow (container < 640px): map-first — the map claims ~80-85% of the\n container and the side panel becomes a PEEKING bottom sheet (AXS/Ticketmaster\n mobile pattern). data-sheet on the root: \"peek\" (default: grab handle + one\n summary line) / \"open\" (room for rows + checkout, swipe up to open).\n Swipe handling lives on the sheet head ONLY — never the map host, so the\n map's raw-pointer gesture pipeline is untouched. */\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%;border-left:0;border-top:1px solid var(--sl-line);\n flex:none;height:min(72%,480px);overflow:hidden;transition:height .3s cubic-bezier(.2,.8,.2,1);overscroll-behavior:contain}\n.sl-picker[data-layout=\"narrow\"][data-sheet=\"open\"][data-has-selection=\"false\"] .sl-side{height:min(252px,52%)}\n.sl-picker[data-layout=\"narrow\"][data-sheet=\"peek\"] .sl-side{height:86px;overflow:hidden}\n.sl-picker[data-layout=\"narrow\"][data-sheet=\"peek\"] .sl-side > :not(.sl-sheet-head){display:none}\n.sl-picker[data-layout=\"narrow\"] .sl-tray{flex:1;min-height:0;overflow-y:auto;overscroll-behavior:contain}\n.sl-picker[data-layout=\"narrow\"] .sl-foot{position:static;background:var(--sl-bg)}\n.sl-picker[data-layout=\"narrow\"] .sl-foot.empty{display:none}\n.sl-picker[data-layout=\"narrow\"] .sl-sheet-head{order:0}\n.sl-picker[data-layout=\"narrow\"] .sl-seats-sec{display:none}\n.sl-picker[data-layout=\"narrow\"] .sl-tray{order:2}\n.sl-picker[data-layout=\"narrow\"] .sl-filtersec{order:3}\n.sl-picker[data-layout=\"narrow\"] .sl-filters{order:4}\n.sl-picker[data-layout=\"narrow\"] .sl-prices-sec{order:5}\n.sl-picker[data-layout=\"narrow\"] .sl-pricef{order:6}\n.sl-picker[data-layout=\"narrow\"] .sl-prices{order:7}\n.sl-picker[data-layout=\"narrow\"] .sl-foot{order:8}\n.sl-picker[data-layout=\"narrow\"] .sl-tray-hint,\n.sl-picker[data-layout=\"narrow\"] .sl-filtersec,\n.sl-picker[data-layout=\"narrow\"] .sl-filters,\n.sl-picker[data-layout=\"narrow\"] .sl-prices-sec,\n.sl-picker[data-layout=\"narrow\"] .sl-prices{display:none!important}\n.sl-picker[data-layout=\"narrow\"][data-has-selection=\"true\"] .sl-filtersec,\n.sl-picker[data-layout=\"narrow\"][data-has-selection=\"true\"] .sl-filters,\n.sl-picker[data-layout=\"narrow\"][data-has-selection=\"true\"] .sl-prices-sec{display:none}\n/* Reclaim the bottom sheet once the cart has anything: the \"Find best seats\"\n panel collapses too. EXCEPT the confirm (\"Replace your current choices?\") and\n in-flight busy states, which legitimately show with a non-empty cart — those\n set data-ba-active=\"true\" (see setAttribute alongside data-has-selection). */\n.sl-picker[data-layout=\"narrow\"][data-has-selection=\"true\"]:not([data-ba-active=\"true\"]) .sl-ba{display:none}\n/* touch chrome: pinch-zoom exists — hide +/− on the sheet layout (keep fit) */\n.sl-picker[data-layout=\"narrow\"] .sl-zoom [data-ref=\"zin\"],\n.sl-picker[data-layout=\"narrow\"] .sl-zoom [data-ref=\"zout\"]{display:none}\n\n/* bottom-sheet head: grab handle + one-line summary (narrow only). The WHOLE\n head is the tap/swipe toggle target (min 44px), so it reads as one control. */\n.sl-sheet-head{display:none;flex-direction:column;justify-content:center;padding:6px 12px 8px;min-height:56px;\n cursor:pointer;touch-action:none;user-select:none;-webkit-user-select:none;flex:none}\n.sl-picker[data-layout=\"narrow\"] .sl-sheet-head{display:flex}\n.sl-sheet-grab{width:36px;height:4px;border-radius:999px;background:var(--sl-muted);opacity:.55;margin:2px auto 7px}\n.sl-sheet-bar{display:flex;align-items:center;gap:10px;min-height:26px}\n.sl-sheet-peek{display:flex;align-items:center;gap:7px;flex:1;min-width:0;font-size:13px;font-weight:700;color:var(--sl-text);\n white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n.sl-sheet-peek .sub{color:var(--sl-muted);font-weight:600}\n/* collapsed-peek \"Continue\" affordance: a real accent pill, not plain text */\n.sl-sheet-peek .go{margin-left:auto;flex:none;display:inline-flex;align-items:center;min-height:30px;\n padding:6px 13px;border-radius:999px;background:var(--sl-accent);color:var(--sl-accent-ink);\n font-weight:800;font-size:12.5px}\n/* state chevron: points UP while peeking, rotates to point DOWN when open.\n Base keeps an explicit rotate(0) — transitioning to/from a bare 'none' leaves\n the value stuck in some engines, so both endpoints must be real transforms. */\n.sl-sheet-toggle{width:44px;height:44px;margin:-8px -8px -8px 0;border-radius:999px;flex:none;display:flex;\n align-items:center;justify-content:center;color:var(--sl-muted);transition:color .15s,background .15s}\n.sl-sheet-toggle:hover,.sl-sheet-toggle:focus-visible{color:var(--sl-text);background:color-mix(in srgb,var(--sl-line) 44%,transparent)}\n.sl-sheet-toggle svg{width:21px;height:21px;stroke:currentColor;stroke-width:2.4;fill:none;\n stroke-linecap:round;stroke-linejoin:round}\n.sl-sheet-toggle svg{transform:rotate(0deg);transition:transform .24s cubic-bezier(.2,.8,.2,1)}\n.sl-picker[data-sheet=\"open\"] .sl-sheet-toggle svg{transform:rotate(180deg)}\n\n/* consolidated Filters row inside the sheet (a11y chips + colorblind toggle\n dock here on narrow; they live on the map / zoom column on wide) */\n.sl-filtersec{display:none}\n.sl-filters{display:none;gap:6px;flex-wrap:wrap;align-items:center;padding:2px 16px 10px}\n.sl-picker[data-layout=\"narrow\"] .sl-filtersec.has,\n.sl-picker[data-layout=\"narrow\"] .sl-filters.has{display:none}\n.sl-picker[data-layout=\"narrow\"][data-has-selection=\"true\"] .sl-filtersec.has,\n.sl-picker[data-layout=\"narrow\"][data-has-selection=\"true\"] .sl-filters.has{display:none}\n.sl-cbbtn{width:32px;height:32px;border-radius:999px;background:var(--sl-surface);border:1px solid var(--sl-line);\n color:var(--sl-text);display:flex;align-items:center;justify-content:center;transition:border-color .15s}\n.sl-cbbtn:hover{border-color:var(--sl-muted)}\n.sl-cbbtn svg{width:14px;height:14px;stroke:currentColor;stroke-width:2;fill:none;stroke-linecap:round;stroke-linejoin:round}\n\n/* price panel — one compact filter control replaces the wrapping price-chip row. */\n.sl-sec{padding:14px 14px 4px;font-size:9.5px;letter-spacing:.14em;text-transform:uppercase;color:var(--sl-muted);font-weight:700}\n.sl-prices-sec{display:flex;align-items:center;justify-content:space-between;gap:10px;padding-top:13px}\n.sl-price-select{min-height:32px;max-width:130px;padding:5px 28px 5px 9px;border:1px solid var(--sl-line);border-radius:9px;\n background:var(--sl-surface);color:var(--sl-text);font:inherit;font-size:11px;font-weight:750;letter-spacing:0;text-transform:none}\n.sl-prices{display:flex;flex-direction:column;padding:4px 14px 8px;border-bottom:1px solid var(--sl-line)}\n.sl-prices-sec,.sl-prices,.sl-seats-sec{flex:none}\n.sl-price-row{display:flex;align-items:center;gap:7px;min-height:28px;font-size:12px;\n padding:0 6px;margin:0 -6px;border-radius:8px;cursor:pointer;transition:background .15s}\n.sl-price-row:hover,.sl-price-row:focus-visible{background:color-mix(in srgb,var(--sl-line) 40%,transparent)}\n.sl-price-row.sl-active{background:color-mix(in srgb,var(--sl-accent) 9%,transparent)}\n.sl-price-row.sl-active .sl-price-label{color:var(--sl-accent)}\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/* long category lists: capped by default, scroll once expanded */\n.sl-prices.sl-expanded{max-height:196px;overflow-y:auto;overscroll-behavior:contain;scrollbar-gutter:stable}\n.sl-price-more{display:flex;align-items:center;min-height:26px;padding:0;\n color:var(--sl-muted);font-size:11px;font-weight:750;transition:color .15s}\n.sl-price-more:hover,.sl-price-more:focus-visible{color:var(--sl-text)}\n/* held/sold key — one quiet caption line; the map itself teaches these states */\n.sl-status-key{display:flex;gap:11px;flex-wrap:wrap;padding:5px 0 0;margin-top:4px;border-top:1px solid var(--sl-line);color:var(--sl-muted);font-size:10px}\n.sl-status-item{display:inline-flex;align-items:center;gap:5px}\n.sl-status-icon{width:13px;height:13px;border-radius:999px;display:inline-flex;align-items:center;justify-content:center;\n color:#fff;background:#6b7280;line-height:1}\n.sl-status-icon svg{width:8px;height:8px;stroke:currentColor;stroke-width:2;fill:none;stroke-linecap:round;stroke-linejoin:round}\n.sl-status-icon.sold{background:#8b93a0}\n.sl-status-icon.sold svg{width:9px;height:9px;stroke-width:2.4}\n\n/* tray */\n.sl-seats-sec{display:flex;align-items:center;justify-content:space-between;gap:10px;padding-top:13px}\n.sl-seat-summary{font-size:10px;letter-spacing:0;text-transform:none;white-space:nowrap}\n.sl-tray{flex:1;padding:10px 14px 14px;display:flex;flex-direction:column;gap:7px;min-height:0;overflow-y:auto;\n overscroll-behavior:contain;scrollbar-gutter:stable}\n.sl-tray-hint{font-size:12.5px;color:var(--sl-muted);line-height:1.5}\n.sl-chip{position:relative;display:grid;grid-template-columns:minmax(0,1fr) 34px;align-items:stretch;\n flex:none;min-height:53px;border:1px solid var(--sl-line);border-radius:var(--sl-r-sm);overflow:hidden;\n background:var(--sl-surface);font-size:13px;transform-origin:center;transition:border-color .15s,background .15s}\n.sl-chip:hover{border-color:color-mix(in srgb,var(--sl-accent) 38%,var(--sl-line))}\n.sl-chip.sl-enter{animation:slChipIn .38s cubic-bezier(.2,.8,.2,1) both}\n.sl-chip.sl-leave{pointer-events:none;animation:slChipOut .16s ease-in both}\n.sl-chip.sl-held{border-color:var(--sl-line);background:color-mix(in srgb,var(--sl-accent) 7%,var(--sl-surface));\n box-shadow:inset 3px 0 0 color-mix(in srgb,var(--sl-accent) 72%,transparent)}\n.sl-ticket-state{width:17px;height:17px;border-radius:999px;flex:none;display:flex;align-items:center;justify-content:center;\n background:var(--sl-accent);color:var(--sl-accent-ink)}\n.sl-ticket-state.held{background:color-mix(in srgb,var(--sl-accent) 18%,var(--sl-surface));color:var(--sl-accent)}\n.sl-ticket-state svg{width:10px;height:10px;stroke:currentColor;stroke-width:2.6;fill:none;stroke-linecap:round;stroke-linejoin:round}\n.sl-chip-main{min-width:0;padding:8px 10px 8px 11px;display:flex;flex-direction:column;justify-content:center;gap:5px}\n.sl-chip-id{display:flex;gap:12px;min-width:0}\n.sl-chip-id .fld{min-width:0}\n.sl-chip-id .fld.sec{flex:1}\n.sl-chip-id .fld.mid{flex:none;text-align:center}\n.sl-chip-eb{display:block;font-size:8px;font-weight:700;letter-spacing:.12em;text-transform:uppercase;color:var(--sl-muted);margin-bottom:1px}\n.sl-chip-id .val{display:block;font-weight:600;font-size:13px;line-height:1.25;white-space:nowrap}\n.sl-chip-id .fld.sec .val{overflow:hidden;text-overflow:ellipsis}\n.sl-chip-sub{display:flex;align-items:center;gap:6px;min-width:0}\n.sl-chip .cat{color:var(--sl-muted);font-size:10.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;flex:none;white-space:nowrap}\n.sl-chip-rail{display:flex;flex-direction:column;border-left:1px solid var(--sl-line)}\n.sl-chip .rm,.sl-chip .view{flex:1;min-height:26px;border-radius:0;display:flex;align-items:center;justify-content:center;\n color:var(--sl-muted);transition:color .15s,background .15s}\n.sl-chip .view{border-top:1px solid var(--sl-line)}\n.sl-chip .rm:hover,.sl-chip .rm:focus-visible{color:#e5484d;background:color-mix(in srgb,#e5484d 9%,transparent)}\n.sl-chip .view:hover,.sl-chip .view:focus-visible{color:var(--sl-text);background:color-mix(in srgb,var(--sl-accent) 10%,transparent)}\n.sl-chip .rm svg{width:11px;height:11px;stroke:currentColor;stroke-width:2.4;fill:none;stroke-linecap:round}\n.sl-chip .view svg{width:13px;height:13px;stroke:currentColor;stroke-width:1.8;fill:none}\n/* live-activity strip — narrates WS availability deltas (social proof + urgency).\n Hidden until a delta actually happens: a static \"seats update in real time\"\n banner is dead vertical space, a \"2 seats just taken\" flash is a signal. */\n.sl-live{display:none;align-items:center;gap:7px;margin:10px 14px 0;padding:7px 9px;flex:none;\n border:1px solid var(--sl-line);border-radius:8px;background:color-mix(in srgb,var(--sl-accent) 4%,var(--sl-surface));\n font-size:11px;color:var(--sl-muted)}\n.sl-live .dot{width:6px;height:6px;border-radius:999px;background:#22a06b;box-shadow:0 0 6px rgba(34,160,107,.75);flex:none}\n.sl-live span:last-child{flex:1;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n.sl-live.on{display:flex;animation:slNoticeIn .38s cubic-bezier(.2,.8,.2,1) both}\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{position:relative;z-index:2;padding:12px 16px 14px;border-top:1px solid var(--sl-line);flex:none;\n background:var(--sl-bg);box-shadow:0 -10px 24px -22px rgba(0,0,0,.72)}\n.sl-hold-note{display:none;align-items:center;gap:7px;margin-bottom:8px;padding:7px 8px;border-radius:var(--sl-r-sm);\n border:1px solid var(--sl-line);background:color-mix(in srgb,var(--sl-accent) 7%,var(--sl-surface));\n box-shadow:inset 3px 0 0 color-mix(in srgb,var(--sl-accent) 72%,transparent);\n font-size:11.5px;line-height:1.35;color:var(--sl-muted)}\n.sl-hold-note.on{display:flex;animation:slNoticeIn .38s cubic-bezier(.2,.8,.2,1) both}\n.sl-hold-note svg{width:16px;height:16px;flex:none;stroke:var(--sl-accent);stroke-width:2.4;fill:none;\n stroke-linecap:round;stroke-linejoin:round}\n.sl-hold-note b{display:block;color:var(--sl-text);font-size:11.5px;white-space:nowrap}\n.sl-hold-copy{display:block;white-space:nowrap;font-size:10.5px}\n.sl-hold-note>span{flex:1;min-width:0}\n.sl-hold-change{flex:none;min-height:30px;padding:5px 8px;border-radius:8px;border:1px solid var(--sl-line);\n color:var(--sl-text);font-size:10.5px;font-weight:750;white-space:nowrap}\n.sl-hold-change:hover,.sl-hold-change:focus-visible{border-color:var(--sl-accent);color:var(--sl-accent)}\n.sl-hold-change:disabled{opacity:.58;cursor:wait}\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-value-pop{animation:slValuePop .32s cubic-bezier(.2,.8,.2,1)}\n/* Primary checkout CTA. Scoped under .sl-picker so it OUTWEIGHS the\n '.sl-picker button' reset (0,1,1) — an unscoped '.sl-cta' (0,1,0) loses to it\n and the button renders as plain text with no accent fill. */\n.sl-picker .sl-cta{display:flex;align-items:center;justify-content:center;width:100%;min-height:44px;\n padding:12px 16px;border-radius:var(--sl-r-sm);font-weight:800;font-size:14px;line-height:1.1;\n background:var(--sl-accent);color:var(--sl-accent-ink);\n transition:filter .15s,background .22s,color .22s,transform .12s,box-shadow .22s;gap:8px}\n.sl-picker .sl-cta:hover{filter:brightness(1.08)}\n.sl-picker .sl-cta:active{transform:translateY(1px);filter:brightness(.94)}\n.sl-picker .sl-cta.sl-ready{animation:slCtaReady .42s cubic-bezier(.2,.8,.2,1)}\n.sl-cta-spin,.sl-ba-spin{width:14px;height:14px;border-radius:50%;border:2px solid currentColor;border-right-color:transparent;\n animation:slspin .7s linear infinite;flex:none}\n/* Disabled (\"Select seats\"): quieter, but still a full-width button shape. */\n.sl-picker .sl-cta:disabled{background:var(--sl-surface);color:var(--sl-muted);opacity:1;\n cursor:not-allowed;filter:none;transform:none}\n\n/* Chrome anchor regions (Feature 6) — every persistent map overlay is APPENDED\n INTO one of these positioned flex containers and flows/stacks within it, so no\n two pieces of chrome free-float on top of each other. Regions never overlap:\n the top strip splits into left/center/right; rails + corners own their edge. */\n.sl-anchor{position:absolute;z-index:5;display:flex;gap:8px;pointer-events:none}\n.sl-anchor > *{pointer-events:auto}\n.sl-anchor[data-region=\"top-left\"]{top:12px;left:12px;flex-wrap:wrap;max-width:38%}\n.sl-anchor[data-region=\"top-center\"]{top:12px;left:50%;transform:translateX(-50%);flex-direction:column;\n align-items:center;max-width:44%}\n.sl-anchor[data-region=\"top-right\"]{top:12px;right:12px;justify-content:flex-end;flex-wrap:wrap;max-width:38%}\n.sl-anchor[data-region=\"left-rail\"]{top:50%;left:12px;transform:translateY(-50%);flex-direction:column;max-width:42%;gap:6px}\n.sl-anchor[data-region=\"bottom-left\"]{left:12px;bottom:12px;flex-direction:column;align-items:flex-start}\n.sl-anchor[data-region=\"bottom-center\"]{left:50%;bottom:14px;transform:translateX(-50%);z-index:9;\n flex-direction:column;align-items:center;gap:8px;max-width:92%}\n.sl-anchor[data-region=\"bottom-right\"]{right:12px;bottom:12px;flex-direction:column;align-items:flex-end;gap:6px}\n/* narrow: tighten the top strip so left/center can't crowd each other */\n.sl-picker[data-layout=\"narrow\"] .sl-anchor[data-region=\"top-left\"]{max-width:30%}\n.sl-picker[data-layout=\"narrow\"] .sl-anchor[data-region=\"top-center\"]{max-width:44%}\n\n/* TEST MODE badge — a small pill in the top-right region (shrinks on narrow) */\n.sl-testbadge{padding:5px 11px;border-radius:999px;font-size:10px;font-weight:800;letter-spacing:.1em;\n text-transform:uppercase;white-space:nowrap;background:var(--sl-accent);color:var(--sl-accent-ink);\n box-shadow:0 2px 8px rgba(0,0,0,.25)}\n.sl-picker[data-layout=\"narrow\"] .sl-testbadge{padding:3px 8px;font-size:8.5px;letter-spacing:.06em}\n\n/* zoom column (flows within the bottom-right region) */\n.sl-zoom{display:flex;flex-direction:column;gap:6px}\n/* CSS-fallback full screen (iOS Safari has no element fullscreen API) */\n.sl-picker.sl-fs{position:fixed;inset:0;z-index:2147483000;width:auto;height:auto;max-height:none;border-radius:0}\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 (toast flows in the bottom-center region) */\n.sl-toast{transform:translateY(6px) scale(.98);max-width:100%;\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 .22s,transform .22s;white-space:nowrap;\n overflow:hidden;text-overflow:ellipsis}\n.sl-toast.on{opacity:1;transform:translateY(0) scale(1)}\n.sl-toast.has-action{pointer-events:auto;display:flex;align-items:center;gap:12px;padding-right:8px}\n.sl-toast-action{min-height:30px;padding:5px 10px;border-radius:999px;background:var(--sl-accent);color:var(--sl-accent-ink);\n font:inherit;font-weight:800}\n.sl-toast[data-tone=\"error\"]{border-color:#ef4444}\n.sl-toast[data-tone=\"warning\"]{border-color:var(--sl-accent)}\n.sl-toast[data-tone=\"success\"]{border-color:#22c55e}\n.sl-toast.on[data-tone=\"error\"]{animation:slToastNudge .32s ease-out}\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 (flows in the bottom-center region, above the toast) */\n.sl-extend{transform:translateY(6px);\n display:none;align-items:center;gap:12px;max-width:100%;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: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:flex;flex-direction:column;align-items:center;\n justify-content:center;gap:12px;text-align:center;padding:28px;background:var(--sl-bg);opacity:0;visibility:hidden;\n pointer-events:none;transition:opacity .34s ease,visibility 0s linear .34s}\n.sl-booked.on{opacity:1;visibility:visible;pointer-events:auto;transition:opacity .34s ease,visibility 0s}\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);transform:scale(.72)}\n.sl-booked.on .sl-booked-badge{animation:slSuccessPop .58s cubic-bezier(.2,1.25,.3,1) .08s both}\n.sl-booked-badge svg{width:30px;height:30px;stroke:currentColor;stroke-width:2.6;fill:none;stroke-linecap:round;stroke-linejoin:round;\n stroke-dasharray:30;stroke-dashoffset:30}\n.sl-booked.on .sl-booked-badge svg{animation:slCheckDraw .42s ease-out .32s forwards}\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.sl-booked.on .sl-booked-title,.sl-booked.on .sl-booked-sub{animation:slCopyRise .42s ease-out both}\n.sl-booked.on .sl-booked-title{animation-delay:.22s}\n.sl-booked.on .sl-booked-sub{animation-delay:.3s}\n\n/* sold-out overlay — every SEATED category's live availability is 0. Centered\n over the map; a stub (disabled) \"Join waitlist\" button, exactly like the page.\n Suppressed when GA areas exist (GA capacity isn't seat-counted). Clears live\n the moment WS frees a seat up. */\n.sl-soldout{position:absolute;inset:0;z-index:10;display:none;flex-direction:column;align-items:center;\n justify-content:center;text-align:center;gap:8px;padding:24px;\n background:color-mix(in srgb,var(--sl-bg) 82%,transparent);backdrop-filter:blur(4px)}\n.sl-soldout.on{display:flex}\n.sl-soldout-eyebrow{font-size:10px;letter-spacing:.2em;text-transform:uppercase;color:var(--sl-accent);font-weight:800}\n.sl-soldout-title{font-size:32px;font-weight:800;color:var(--sl-text);line-height:1.05}\n.sl-soldout-copy{max-width:360px;font-size:13px;color:var(--sl-muted);line-height:1.5}\n.sl-picker .sl-soldout-btn{margin-top:10px;min-height:40px;padding:10px 18px;border-radius:var(--sl-r-sm);\n background:var(--sl-surface);color:var(--sl-muted);border:1px solid var(--sl-line);font-weight:800;font-size:13px;\n cursor:not-allowed;opacity:.85}\n\n/* sales-closed pill (header) — persistent read-only state when the event's sales\n window is closed at load or closes live mid-session. Neutral (not accent) so it\n reads as \"unavailable\", distinct from the accent hold pill next to it. */\n.sl-closed-pill{display:none;align-items:center;gap:6px;padding:6px 12px;border-radius:999px;flex:none;\n background:color-mix(in srgb,var(--sl-text) 12%,var(--sl-surface));color:var(--sl-text);\n font-weight:700;font-size:12px;white-space:nowrap}\n.sl-closed-pill.on{display:inline-flex}\n.sl-closed-pill svg{width:13px;height:13px;stroke:currentColor;stroke-width:2;fill:none;stroke-linecap:round;stroke-linejoin:round}\n\n/* \"Powered by SeatLayer\" attribution badge (side-panel foot) — the small gold\n rounded logo mark + wordmark. Hidden when the host opts out or the org's paid\n theme sets hideBadge. */\n.sl-powered{display:flex;align-items:center;justify-content:center;gap:6px;margin-top:10px;\n font-size:11px;letter-spacing:.03em;color:var(--sl-muted)}\n.sl-powered-mark{width:16px;height:16px;border-radius:4px;flex:none;display:flex;align-items:center;justify-content:center;\n background:var(--sl-accent);color:var(--sl-accent-ink)}\n.sl-powered-mark svg{width:11px;height:11px;fill:currentColor}\n\n/* a11y filter chips (flow within the top-left region) */\n.sl-chips{display:flex;gap:6px;flex-wrap:wrap}\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 card: a candidate is not in the tray until Select. Map gestures and\n floating chrome pause while the card owns focus, keeping the camera stable. */\n.sl-picker[data-confirming=\"true\"] .sl-map-host>:not(.sl-confirm){pointer-events:none}\n.sl-picker[data-confirming=\"true\"] .sl-anchor{pointer-events:none;opacity:.28;transition:opacity .16s}\n.sl-picker[data-confirming=\"true\"] .sl-side{pointer-events:none;opacity:.58;transition:opacity .16s}\n.sl-confirm{position:absolute;z-index:10;width:276px;max-width:calc(100% - 24px);overflow:hidden;pointer-events:auto;\n background:var(--sl-surface);border:1px solid color-mix(in srgb,var(--sl-line) 70%,var(--sl-text));\n border-radius:15px;box-shadow:0 24px 64px -18px rgba(0,0,0,.72);transform:translate(-50%,calc(-100% - 16px));\n animation:slConfirmIn .24s cubic-bezier(.2,.8,.2,1) both}\n.sl-confirm[data-placement=\"below\"]{transform:translate(-50%,16px);animation:slConfirmBelowIn .24s cubic-bezier(.2,.8,.2,1) both}\n.sl-confirm-grid{display:grid;grid-template-columns:minmax(0,1fr) minmax(52px,auto) minmax(52px,auto);border-bottom:1px solid var(--sl-line)}\n.sl-confirm-field{min-width:0;padding:12px 11px 10px;border-right:1px solid var(--sl-line)}\n.sl-confirm-field:last-child{border-right:0;text-align:center}\n.sl-confirm-field:nth-child(2){text-align:center}\n.sl-confirm-key{display:block;font-size:8.5px;letter-spacing:.12em;text-transform:uppercase;color:var(--sl-muted);font-weight:800}\n.sl-confirm-value{display:block;margin-top:4px;color:var(--sl-text);font-size:17px;line-height:1.1;font-weight:850;\n white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n/* Long venue section names must read in full: smaller type + up to two lines\n beats an ellipsis at identity-confirmation time. Row/seat stay big — they're\n short and they're what the buyer double-checks against the map. */\n.sl-confirm-field:first-child .sl-confirm-value{font-size:13.5px;line-height:1.25;white-space:normal;\n display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical}\n.sl-confirm-cat{display:flex;align-items:center;gap:8px;padding:10px 12px;background:color-mix(in srgb,var(--sl-cat) 76%,var(--sl-surface))}\n.sl-confirm-cat .sl-dot{border:2px solid rgba(255,255,255,.78);width:11px;height:11px}\n.sl-confirm-cat-name{font-size:13.5px;font-weight:800;color:#fff;flex:1;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n.sl-confirm-price{font-size:17px;font-weight:850;color:#fff;font-variant-numeric:tabular-nums}\n.sl-confirm-body{padding:11px 12px 12px}\n.sl-confirm-row{display:flex;gap:8px;margin-top:10px}\n.sl-confirm-row button{flex:1;min-height:44px;padding:9px 12px;border-radius:9px;font-weight:800;font-size:13px}\n.sl-confirm-add{background:var(--sl-accent)!important;color:var(--sl-accent-ink)!important;display:flex;align-items:center;justify-content:center;gap:7px}\n.sl-confirm-add svg{width:16px;height:16px;stroke:currentColor;stroke-width:2.8;fill:none;stroke-linecap:round;stroke-linejoin:round}\n.sl-confirm-cancel{background:color-mix(in srgb,var(--sl-line) 44%,transparent)!important;border:1px solid var(--sl-line)!important;color:var(--sl-muted)!important}\n.sl-confirm-cancel:hover{color:var(--sl-text)}\n.sl-picker[data-layout=\"narrow\"] .sl-confirm{left:50%!important;top:auto!important;bottom:14px;width:min(342px,calc(100% - 24px));\n transform:translateX(-50%);animation:slConfirmMobileIn .24s cubic-bezier(.2,.8,.2,1) both}\n\n/* hover preview — a COMPACT echo of the confirm card (deliberately smaller: it's\n a passing preview on hover, not the click/select action surface). Reuses the\n Section·Row·Seat identity grid so hover, confirm and the cart chip all share\n one visual language, just at three sizes. */\n.sl-tip{position:absolute;z-index:7;pointer-events:none;display:none;width:190px;overflow:hidden;\n background:var(--sl-surface);color:var(--sl-text);border:1px solid var(--sl-line);border-radius:11px;\n box-shadow:0 12px 30px -14px rgba(0,0,0,.6)}\n.sl-tip-grid{display:grid;grid-template-columns:1.3fr .85fr .85fr;border-bottom:1px solid var(--sl-line)}\n.sl-tip-grid.one{grid-template-columns:1fr}\n.sl-tip-field{min-width:0;padding:6px 9px;border-right:1px solid var(--sl-line)}\n.sl-tip-field:last-child{border-right:0;text-align:center}\n.sl-tip-grid:not(.one) .sl-tip-field:nth-child(2){text-align:center}\n.sl-tip-key{display:block;font-size:7.5px;letter-spacing:.1em;text-transform:uppercase;color:var(--sl-muted);font-weight:800}\n.sl-tip-val{display:block;margin-top:2px;color:var(--sl-text);font-size:13px;line-height:1.1;font-weight:750;\n white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n.sl-tip-cat{display:flex;align-items:center;gap:7px;padding:6px 10px;font-size:11px;\n background:color-mix(in srgb,var(--sl-cat) 12%,var(--sl-surface))}\n.sl-tip-dot{width:8px;height:8px;border-radius:50%;flex:none}\n.sl-tip-name{color:var(--sl-muted);flex:1;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n.sl-tip-amt{margin-left:auto;font-weight:800;color:var(--sl-text);font-variant-numeric:tabular-nums;font-size:12px}\n.sl-tip-status{padding:5px 10px 7px;font-size:8.5px;letter-spacing:.09em;text-transform:uppercase;font-weight:700;color:var(--sl-muted)}\n\n/* Best available is a first-class shortcut, not an anonymous utility row. */\n.sl-ba{position:relative;flex:none;overflow:hidden;display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:center;gap:7px;\n padding:13px;border:1px solid color-mix(in srgb,var(--sl-accent) 34%,var(--sl-line));border-radius:13px;\n background:linear-gradient(135deg,color-mix(in srgb,var(--sl-accent) 5%,var(--sl-surface)),color-mix(in srgb,var(--sl-accent) 11%,var(--sl-surface)))}\n.sl-ba::after{content:'✦';position:absolute;right:10px;top:3px;color:color-mix(in srgb,var(--sl-accent) 20%,transparent);font-size:42px;line-height:1}\n.sl-ba-title,.sl-ba-copy,.sl-ba select,.sl-ba-qty,.sl-ba-go{position:relative;z-index:1}\n.sl-ba-title{grid-column:1/-1;display:flex;align-items:center;gap:7px;font-size:13px;font-weight:850}\n.sl-ba-title .spark{color:var(--sl-accent);font-size:16px}\n.sl-ba-copy{grid-column:1/-1;margin:-4px 0 2px 23px;color:var(--sl-muted);font-size:10.5px;line-height:1.35}\n.sl-ba-copy .narrow{display:none}\n.sl-ba select{background:var(--sl-surface);color:var(--sl-text);border:1px solid var(--sl-line);border-radius:8px;\n font:inherit;font-size:11px;padding:7px 8px;min-width:0;width:100%;max-width:none}\n.sl-ba-qty{display:flex;align-items:center;gap:7px;padding:3px;border:1px solid var(--sl-line);border-radius:9px;background:var(--sl-surface)}\n.sl-ba-qty button{width:25px;height:25px;border-radius:7px;background:color-mix(in srgb,var(--sl-line) 35%,transparent);border:0;\n font-size:14px;font-weight:800;display:flex;align-items:center;justify-content:center}\n.sl-ba-qty span{min-width:14px;text-align:center;font-weight:800}\n.sl-picker .sl-ba-go{grid-column:1/-1;width:100%;min-height:37px;padding:7px 12px;border-radius:9px;background:var(--sl-accent);\n color:var(--sl-accent-ink);font-weight:800;font-size:12px;transition:filter .15s,opacity .15s;display:flex;align-items:center;justify-content:center;gap:6px;\n box-shadow:0 8px 18px color-mix(in srgb,var(--sl-accent) 18%,transparent)}\n.sl-picker .sl-ba-go:hover{filter:brightness(1.06)}\n.sl-picker .sl-ba-go:disabled{opacity:.62;cursor:wait}\n.sl-ba-replace{grid-column:1/-1;padding:3px 0 1px}\n.sl-ba-replace b{display:block;font-size:12.5px}\n.sl-ba-replace span{display:block;margin-top:3px;color:var(--sl-muted);font-size:10.5px;line-height:1.35}\n.sl-ba-actions{grid-column:1/-1;display:grid;grid-template-columns:1fr 1fr;gap:7px}\n.sl-ba-actions button{min-height:36px;border-radius:9px;border:1px solid var(--sl-line);font-size:11.5px;font-weight:800}\n.sl-ba-actions .replace{border-color:var(--sl-accent);background:var(--sl-accent);color:var(--sl-accent-ink)}\n.sl-picker[data-layout=\"narrow\"] .sl-ba{padding:11px}\n.sl-picker[data-layout=\"narrow\"] .sl-ba-copy .wide{display:none}\n.sl-picker[data-layout=\"narrow\"] .sl-ba-copy .narrow{display:inline}\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:6px;\n font:inherit;font-size:10px;padding:2px 4px;min-width:0;max-width:100%;cursor:pointer}\n\n/* arena: LOD rung pills (flow within the top-center region) */\n.sl-rungs{display:none;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/* narrow: shrink the rung pills so the centered row can't reach the corner regions */\n.sl-picker[data-layout=\"narrow\"] .sl-rungs button{padding:5px 9px;font-size:9px;letter-spacing:.03em}\n\n/* multi-floor switcher (flows within the left-rail region) */\n.sl-floors{display:none;flex-direction:column;gap:6px;max-width:100%}\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 — docks INSIDE the top-center anchor region on\n wide (flows below the rung pills, never over them, never floating over the\n seats at the tap point). Auto-collapses to a slim pill once seat-picking\n begins (first seat select, or a pan/zoom after the focus glide); tapping the\n pill re-expands; ✕ closes in both states. On narrow it renders as a compact\n strip inside the bottom sheet's peek head — never over the canvas. */\n.sl-seccard{width:250px;max-width:100%;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/* collapsed pill (wide) */\n.sl-seccard.mini{width:auto;padding:5px 7px 5px 12px;border-radius:999px;cursor:pointer}\n.sl-seccard.mini.on{display:inline-flex;align-items:center;gap:7px}\n.sl-seccard.mini .sl-seccard-name{font-size:12px;flex:none;max-width:120px}\n.sl-seccard.mini .sl-seccard-left{font-size:11px}\n/* narrow: compact strip inside the sheet head (peek area) */\n.sl-seccard.strip{width:100%;padding:7px 0 0;border:0;border-radius:0;box-shadow:none;background:none;cursor:default}\n.sl-seccard.strip.on{display:flex;align-items:center;gap:7px;font-size:12.5px}\n.sl-seccard.strip .sl-seccard-name{font-size:12.5px}\n.sl-seccard.strip .sl-seccard-price{margin-left:auto}\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/* Eager sightline preview inside the confirm card */\n.sl-confirm-thumbwrap{position:relative;display:block;width:100%;height:74px;margin:0 0 8px;padding:0!important;\n border-radius:9px;overflow:hidden;border:1px solid var(--sl-line);cursor:pointer}\n.sl-confirm-thumb{display:block;width:100%;height:100%;object-fit:cover}\n.sl-confirm-thumb-badge{position:absolute;right:7px;top:7px;display:inline-flex;align-items:center;gap:5px;\n font-size:10px;font-weight:700;color:#fff;background:rgba(10,14,22,0.72);border-radius:12px;padding:4px 9px;backdrop-filter:blur(3px)}\n.sl-confirm-sight{display:flex;align-items:center;gap:6px;font-size:11px;color:var(--sl-muted);margin-bottom:2px}\n.sl-confirm-sight span{color:#22a06b;font-weight:800}\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/* F3 minimap — venue overview + live viewport rect (flows in the bottom-left region) */\n.sl-minimap{border:1px solid var(--sl-line);border-radius:9px;\n overflow:hidden;background:var(--sl-surface);box-shadow:0 12px 34px -14px rgba(0,0,0,.55);line-height:0;cursor:pointer}\n.sl-minimap canvas{display:block}\n.sl-picker[data-layout=\"narrow\"] .sl-minimap{display:none}\n\n/* F4 legend reflection: rows + counts for out-of-band categories read muted */\n.sl-price-row.sl-dim{opacity:.4}\n.sl-seccard-mix-item.sl-dim{opacity:.4}\n\n/* Buyer-journey motion: every animation explains a state transition (selected,\n held, checkout handoff, conflict or booked). No decorative infinite motion\n except the expiring-hold pulse and active progress spinners. */\n@keyframes slPillIn{from{opacity:0;transform:translateX(7px) scale(.9)}to{opacity:1;transform:translateX(0) scale(1)}}\n@keyframes slHoldPulse{0%{box-shadow:0 0 0 0 currentColor;opacity:.9}75%,100%{box-shadow:0 0 0 7px transparent;opacity:.55}}\n@keyframes slChipIn{from{opacity:0;transform:translateY(8px) scale(.98)}to{opacity:1;transform:translateY(0) scale(1)}}\n@keyframes slChipOut{to{opacity:0;transform:translateX(10px) scale(.98)}}\n@keyframes slNoticeIn{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:translateY(0)}}\n@keyframes slValuePop{0%{opacity:.6;transform:translateY(3px)}55%{transform:translateY(-1px) scale(1.05)}100%{opacity:1;transform:none}}\n@keyframes slCtaReady{0%{transform:scale(.98);box-shadow:0 0 0 0 transparent}55%{transform:scale(1.01);box-shadow:0 0 0 5px color-mix(in srgb,var(--sl-accent) 18%,transparent)}100%{transform:none;box-shadow:none}}\n@keyframes slToastNudge{0%,100%{margin-left:0}30%{margin-left:-4px}60%{margin-left:3px}}\n@keyframes slSuccessPop{0%{opacity:0;transform:scale(.72)}65%{opacity:1;transform:scale(1.08)}100%{opacity:1;transform:scale(1)}}\n@keyframes slCheckDraw{to{stroke-dashoffset:0}}\n@keyframes slCopyRise{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}\n@keyframes slConfirmIn{from{opacity:0;transform:translate(-50%,calc(-100% - 8px)) scale(.96)}to{opacity:1;transform:translate(-50%,calc(-100% - 14px)) scale(1)}}\n@keyframes slConfirmBelowIn{from{opacity:0;transform:translate(-50%,8px) scale(.96)}to{opacity:1;transform:translate(-50%,16px) scale(1)}}\n@keyframes slConfirmMobileIn{from{opacity:0;transform:translate(-50%,10px) scale(.97)}to{opacity:1;transform:translate(-50%,0) scale(1)}}\n\n@media(prefers-reduced-motion:reduce){\n .sl-picker *,.sl-modal-scrim *{animation-duration:.001ms!important;animation-iteration-count:1!important;\n transition-duration:.001ms!important;scroll-behavior:auto!important}\n}\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\n/**\n * Colorblind-safe preference is a SHARED buyer preference across every SeatLayer\n * surface (the bespoke public page persists it too), so the widget reads/writes\n * the SAME localStorage key. All access is guarded — private-mode/SSR safe.\n */\nconst CB_STORAGE_KEY = 'seatmap.a11y.cb';\nfunction readStoredColorblind(): boolean | null {\n try {\n if (typeof window === 'undefined') return null;\n const raw = window.localStorage.getItem(CB_STORAGE_KEY);\n return raw == null ? null : raw === '1';\n } catch {\n return null;\n }\n}\nfunction writeStoredColorblind(on: boolean): void {\n try {\n window.localStorage.setItem(CB_STORAGE_KEY, on ? '1' : '0');\n } catch {\n /* private mode / storage disabled — preference is best-effort */\n }\n}\n\nexport class SeatPicker {\n private readonly opts: SeatPickerOptions;\n private readonly api: PickerTransport;\n private readonly apiBase: string;\n private readonly controller: PickerController;\n private readonly maxTickets: number;\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 /** Feature 6 anchor regions — positioned flex containers over the map. */\n private regions: 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 /** Short-lived UI motion timers; all are cancelled on destroy. */\n private motionTimers = new Set<ReturnType<typeof setTimeout>>();\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 baQty = 2;\n private baCat = '';\n private bestAvailableConfirm = false;\n private releasingHold = false;\n /** Event sales window is closed (read-only load state / live close). */\n private salesClosed = false;\n /** Every seated category's live availability is 0 (sold-out overlay is up). */\n private soldOut = false;\n private soldoutEl: HTMLDivElement | null = null;\n /** Resolved colorblind-safe state — stored preference wins over the option. */\n private cbSafe = false;\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 // F3 minimap\n private miniCanvas: HTMLCanvasElement | null = null;\n private miniBase: HTMLCanvasElement | null = null;\n private miniTf: { scale: number; offX: number; offY: number; dpr: number } | null = null;\n\n // F4 price-band filter — active band's category keys (null = all prices)\n private priceBandKeys: Set<string> | null = null;\n private focusedCatKey: string | null = null;\n private pricesExpanded = false;\n /** Last surfaced section summary (re-rendered when the price band changes). */\n private lastSection: SectionSummary | null = null;\n /** Section card collapsed to its slim pill (seat-picking has begun). */\n private secCardCollapsed = false;\n /** When the card was (re)shown — the focus glide's own view change must not collapse it. */\n private secCardShownAt = 0;\n /** Previous tray ticket count — first 0→n transition auto-expands the mobile sheet. */\n private lastTrayCount = 0;\n /** Previous computed total — drives a single explanatory value bump. */\n private lastTrayTotal = 0;\n /** Stable item keys prevent tray chips re-animating on unrelated realtime syncs. */\n private lastTrayKeys = new Set<string>();\n private bestAvailableBusy = false;\n private releasingLabels = new Set<string>();\n /** Selected labels awaiting the hold response; their own realtime echo can arrive first. */\n private holdingLabels = new Set<string>();\n private ctaPhase: 'idle' | 'holding' | 'checkout' = 'idle';\n // narrow-layout chrome that docks into the sheet's Filters row on mobile\n private a11yChipsEl: HTMLDivElement | null = null;\n private fsFallback = false;\n private fsChangeHandler: (() => void) | null = null;\n private fsEscHandler: ((e: KeyboardEvent) => void) | null = null;\n /** True once we've asked the host page to pin us fullscreen (framed, no native). */\n private framedFs = false;\n /** Last height (px) posted to a host frame; dedupes redundant reports. */\n private lastPostedHeight = 0;\n\n /**\n * Eager sightline preview for the confirm card: a cheap generated forward\n * view (or the organizer's real photo) plus a \"Nm to stage · clear\n * sightline\" line — the premium at-a-glance moment; click opens the 360.\n */\n private confirmThumbHtml(seat: ExpandedSeat): string {\n const doc = this.controller.doc;\n if (!doc) return '';\n let url = seat.viewUrl ?? '';\n let distance: number | null = null;\n if (!url) {\n try {\n const thumb = generateSeatThumb(seat, doc.focalPoint);\n url = thumb.url;\n distance = thumb.distanceM ?? null;\n } catch {\n return '';\n }\n }\n const sight = distance != null\n ? t('picker.sightline', { m: distance })\n : this.tf('picker.sightlineClear', 'Clear sightline');\n return (\n `<button type=\"button\" class=\"sl-confirm-view sl-confirm-thumbwrap\" aria-label=\"${t('picker.viewFromSeat', { label: seat.label })}\">` +\n `<img class=\"sl-confirm-thumb\" src=\"${url}\" alt=\"\" />` +\n `<span class=\"sl-confirm-thumb-badge\">🔭 ${this.tf('picker.viewFromHere', 'View from here')}</span>` +\n `</button>` +\n `<div class=\"sl-confirm-sight\"><span aria-hidden=\"true\">✓</span>${sight}</div>`\n );\n }\n\n /** True when the picker is rendered inside an iframe (snippet embed at /e/:key). */\n private isFramed(): boolean {\n return typeof window !== 'undefined' && window.parent !== window;\n }\n\n /**\n * Post a widget→host message when framed. targetOrigin is '*' because the\n * payload carries nothing sensitive (a height number / a fullscreen flag);\n * hosts verify `event.origin` on their side (see `attachPickerFrame`).\n */\n private postToHost(message: { type: string; [key: string]: unknown }): void {\n if (!this.isFramed()) return;\n try {\n window.parent.postMessage(message, '*');\n } catch {\n /* a hostile/cross-origin parent may reject postMessage — nothing to do */\n }\n }\n\n /**\n * Height (px) to advertise to a host frame.\n *\n * The picker fills whatever box it's given: `.sl-picker` is `height:100%;\n * overflow:hidden`, and the /e/:key shell mounts it `position:fixed; inset:0`.\n * So it has no intrinsic *document* height to read — `scrollHeight` just\n * collapses to the current viewport, which for a framed embed would echo the\n * host's own iframe height straight back (a circular value). We therefore\n * report a width-driven *desired* height: a pleasant landscape box on desktop,\n * taller on narrow widths where the bottom sheet needs room, clamped to the\n * widget's `min-height` of 420. Width is host-controlled and never moves in\n * response to the height we report, so this cannot feedback-loop.\n */\n private measureFramedHeight(): number {\n const root = this.root;\n if (!root) return 0;\n const width = root.clientWidth || (typeof window !== 'undefined' ? window.innerWidth : 0) || 0;\n if (width <= 0) return 0;\n const ratio = width < 640 ? 1.2 : 0.62;\n return Math.max(420, Math.round(width * ratio));\n }\n\n /** Post `seatlayer:height` to the host when framed and the value changed. */\n private reportFramedHeight(): void {\n if (!this.isFramed()) return;\n const px = this.measureFramedHeight();\n if (px <= 0 || px === this.lastPostedHeight) return;\n this.lastPostedHeight = px;\n this.postToHost({ type: 'seatlayer:height', px });\n }\n\n /** Full screen via the native API, falling back to a fixed-position overlay (iOS Safari). */\n private toggleFullscreen(): void {\n const root = this.root;\n if (!root) return;\n const active = !!document.fullscreenElement || this.fsFallback || this.framedFs;\n if (!active) {\n if (root.requestFullscreen) {\n root.requestFullscreen().catch(() => this.enterFsFallback());\n } else {\n this.enterFsFallback();\n }\n } else if (document.fullscreenElement) {\n void document.exitFullscreen().catch(() => {});\n } else if (this.framedFs) {\n this.setFramedFs(false);\n } else {\n this.setFsFallback(false);\n }\n }\n\n /**\n * Native element-fullscreen was unavailable or rejected. When framed, a CSS\n * `.sl-fs` overlay can't escape the iframe, so we ask the host page to pin us\n * (`seatlayer:fullscreen`). Otherwise (iOS Safari, same document) fall back to\n * the `.sl-fs` overlay as before.\n */\n private enterFsFallback(): void {\n if (this.isFramed()) this.setFramedFs(true);\n else this.setFsFallback(true);\n }\n\n /** Toggle host-driven (framed) fullscreen: post the flag + own the Esc key. */\n private setFramedFs(on: boolean): void {\n if (this.framedFs === on) return;\n this.framedFs = on;\n this.els.zfs?.setAttribute('aria-pressed', String(on || !!document.fullscreenElement));\n this.postToHost({ type: 'seatlayer:fullscreen', on });\n if (on && !this.fsEscHandler) {\n this.fsEscHandler = (e: KeyboardEvent): void => {\n if (e.key === 'Escape' && !document.fullscreenElement) this.setFramedFs(false);\n };\n window.addEventListener('keydown', this.fsEscHandler);\n } else if (!on && this.fsEscHandler) {\n window.removeEventListener('keydown', this.fsEscHandler);\n this.fsEscHandler = null;\n }\n requestAnimationFrame(() => this.controller.zoomToFit());\n }\n\n private setFsFallback(on: boolean): void {\n if (this.fsFallback === on) return;\n this.fsFallback = on;\n this.root?.classList.toggle('sl-fs', on);\n this.els.zfs?.setAttribute('aria-pressed', String(on || !!document.fullscreenElement));\n if (on && !this.fsEscHandler) {\n this.fsEscHandler = (e: KeyboardEvent): void => {\n if (e.key === 'Escape' && !document.fullscreenElement) this.setFsFallback(false);\n };\n window.addEventListener('keydown', this.fsEscHandler);\n } else if (!on && this.fsEscHandler) {\n window.removeEventListener('keydown', this.fsEscHandler);\n this.fsEscHandler = null;\n }\n requestAnimationFrame(() => this.controller.zoomToFit());\n }\n private cbEl: HTMLButtonElement | 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 let closing = false;\n const close = (): void => {\n if (closing) return;\n closing = true;\n document.body.style.overflow = prevOverflow;\n // Visually dismiss immediately, but let an abandoned auto-hold finish its\n // release request before tearing down the transport. This keeps closing a\n // modal from stranding inventory until the normal hold expiry.\n scrim.style.opacity = '0';\n scrim.style.pointerEvents = 'none';\n const finish = (): void => {\n picker.destroy();\n options.onClose?.();\n };\n if (picker.hold && !picker.handedOff) void picker.release().finally(finish);\n else finish();\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') return;\n if (picker.confirmSeat) {\n e.preventDefault();\n picker.cancelConfirm();\n } else if (picker.bestAvailableConfirm) {\n e.preventDefault();\n picker.bestAvailableConfirm = false;\n picker.syncTray();\n } else {\n close();\n }\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, confirmSelection: options.confirmSelection ?? true };\n this.apiBase = (options.apiBase ?? DEFAULT_API_BASE).replace(/\\/+$/, '');\n this.api = options.transport ?? new PubApi(this.apiBase);\n this.maxTickets = Math.max(1, Math.floor(options.maxSelection ?? DEFAULT_MAX_SELECTION));\n // Colorblind preference: the stored (cross-surface) value wins over the\n // option; the option is only the initial default when nothing is stored.\n this.cbSafe = readStoredColorblind() ?? !!options.colorblindSafe;\n this.controller = new PickerController({\n transport: this.api,\n eventKey: options.event,\n maxSelection: this.maxTickets,\n currency: options.currency,\n flashOnLiveChange: true,\n colorblindSafe: this.cbSafe,\n onSelectionChange: () => {\n this.syncTray();\n // Seat-picking has begun — collapse the section card out of the way.\n if (this.committedSelection().length) this.collapseSectionCard();\n },\n onStatusChange: () => {\n this.syncPrices();\n this.evictTakenSelections();\n this.detectBooked();\n // Live open/close of a section repaints the minimap's static overview.\n this.refreshMinimap();\n },\n onHoldExpired: () => {\n this.hold = null;\n this.forgetHold();\n this.handedOff = false;\n this.bookedShown = false;\n this.ctaPhase = 'idle';\n this.stopHoldTimer();\n this.gaQty.clear();\n this.toast(t('picker.holdExpired', undefined) || 'Your hold expired — seats released. Pick again.', 'warning');\n this.syncTray();\n this.emitHoldChange();\n this.opts.onHoldExpired?.();\n },\n confirmSelection: this.opts.confirmSelection,\n onSelect: (seat) => {\n // Sales-closed is a read-only state — refuse the pick (the controller\n // doesn't gate tapping; server would 409 the eventual hold anyway).\n if (this.salesClosed) {\n this.controller.deselect([seat.id]);\n this.toast(this.tf('picker.salesClosedToast', 'Sales are closed for this event.'), 'warning');\n return;\n }\n this.flashPickedSeat(seat.id);\n if (this.opts.confirmSelection) this.showConfirm(seat);\n },\n onDeselect: (seat) => {\n if (this.confirmSeat?.id === seat.id) this.dismissConfirm();\n },\n onSelectionLimit: () => {\n this.toast(`You can select up to ${this.maxTickets} tickets for this order.`, 'warning');\n },\n onViewChange: () => {\n this.reanchorConfirm();\n this.syncRung();\n this.drawMinimapRect();\n this.sectionCardOnView();\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 // Server declared the event closed mid-session (409 event_closed) — keep\n // the toast (raised by handleCta), and add the persistent read-only state.\n onSalesClosed: () => this.setSalesClosed(true),\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 root.tabIndex = -1;\n this.root = root;\n mount.appendChild(root);\n root.addEventListener('keydown', (e: KeyboardEvent) => {\n if (e.key !== 'Escape') return;\n if (this.confirmSeat) {\n e.preventDefault();\n e.stopPropagation();\n this.cancelConfirm();\n } else if (this.bestAvailableConfirm) {\n e.preventDefault();\n e.stopPropagation();\n this.bestAvailableConfirm = false;\n this.syncTray();\n }\n });\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 <span class=\"sl-closed-pill\" data-ref=\"closedPill\" role=\"status\">\n <svg viewBox=\"0 0 24 24\" aria-hidden=\"true\"><rect x=\"5\" y=\"11\" width=\"14\" height=\"9\" rx=\"2\"/><path d=\"M8 11V7a4 4 0 0 1 8 0v4\"/></svg>\n <span data-ref=\"closedPillText\"></span>\n </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\" data-ref=\"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 <button type=\"button\" aria-label=\"Full screen\" aria-pressed=\"false\" data-ref=\"zfs\">\n <svg viewBox=\"0 0 24 24\"><path d=\"M15 3h6v6M9 21H3v-6M21 3l-7 7M3 21l7-7\"/></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\" data-ref=\"side\">\n <div class=\"sl-sheet-head\" data-ref=\"sheetHead\">\n <div class=\"sl-sheet-grab\"></div>\n <div class=\"sl-sheet-bar\">\n <div class=\"sl-sheet-peek\" data-ref=\"peek\"></div>\n <button type=\"button\" class=\"sl-sheet-toggle\" data-ref=\"sheetToggle\" aria-label=\"Open ticket panel\" aria-expanded=\"false\">\n <svg viewBox=\"0 0 24 24\"><path d=\"M6 15l6-6 6 6\"/></svg>\n </button>\n </div>\n </div>\n <div class=\"sl-sec sl-filtersec\" data-ref=\"filtersSec\">Filters</div>\n <div class=\"sl-filters\" data-ref=\"filters\"></div>\n <div class=\"sl-sec sl-prices-sec\" data-ref=\"pricesSec\"><span>Ticket prices</span></div>\n <div class=\"sl-prices\" data-ref=\"prices\"></div>\n <div class=\"sl-live\" data-ref=\"live\" role=\"status\" aria-live=\"polite\"><span class=\"dot\" aria-hidden=\"true\"></span><span data-ref=\"liveText\">Live availability — seats update in real time</span></div>\n <div class=\"sl-sec sl-seats-sec\"><span>Your seats</span><span class=\"sl-seat-summary\" data-ref=\"seatSummary\"></span></div>\n <div class=\"sl-tray\" data-ref=\"tray\"></div>\n <div class=\"sl-foot\" data-ref=\"foot\">\n <div class=\"sl-hold-note\" data-ref=\"holdNote\" role=\"status\" aria-live=\"polite\">\n <svg viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M20 6L9 17l-5-5\"/></svg>\n <span><b data-ref=\"holdTitle\">Seats secured</b><span class=\"sl-hold-copy\" data-ref=\"holdCopy\">Checkout timer is running.</span></span>\n <button type=\"button\" class=\"sl-hold-change\" data-ref=\"holdChange\" aria-label=\"Release held tickets and choose different seats\">Change</button>\n </div>\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 (breakpoint keys off the CONTAINER, not the viewport)\n const applyLayout = (): void => {\n const w = root.clientWidth;\n if (w <= 0) return;\n // Report our desired height to a host frame on every size change (deduped),\n // not just when the layout breakpoint flips below.\n this.reportFramedHeight();\n const next = w < 640 ? 'narrow' : 'wide';\n if (root.dataset.layout === next) return;\n root.dataset.layout = next;\n // Entering the mobile sheet layout: start in the peek state (map-first).\n if (next === 'narrow' && !root.dataset.sheet) root.dataset.sheet = 'peek';\n this.dockLayoutChrome();\n };\n this.ro = new ResizeObserver(applyLayout);\n this.ro.observe(root);\n // Some environments defer the ResizeObserver's initial callback (backgrounded\n // tabs throttle delivery). Seed the layout synchronously + next frame so a\n // container that mounts already-wide gets data-layout=\"wide\" immediately,\n // instead of waiting on a resize that may never arrive.\n applyLayout();\n requestAnimationFrame(applyLayout);\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 // Full screen: native API with a CSS-fallback overlay for iOS Safari\n // (which has no element fullscreen). Esc exits both paths; the renderer's\n // ResizeObserver re-fits, plus an explicit zoomToFit for a crisp frame.\n this.els.zfs.addEventListener('click', () => this.toggleFullscreen());\n this.fsChangeHandler = (): void => {\n if (!document.fullscreenElement) this.setFsFallback(false);\n this.els.zfs?.setAttribute('aria-pressed', String(!!document.fullscreenElement || this.fsFallback || this.framedFs));\n requestAnimationFrame(() => this.controller.zoomToFit());\n };\n document.addEventListener('fullscreenchange', this.fsChangeHandler);\n\n // Mobile bottom sheet: swipe/tap on the sheet HEAD only (never the map host,\n // so the map's raw-pointer gesture pipeline is untouched). Swipe up → open\n // (≤50%); swipe down → peek; a plain tap toggles. The section-card strip's\n // ✕ lives inside the head — taps on the card must not toggle the sheet.\n const head = this.els.sheetHead;\n if (head) {\n const toggle = this.els.sheetToggle as HTMLButtonElement | undefined;\n const setSheet = (open: boolean): void => {\n root.dataset.sheet = open ? 'open' : 'peek';\n toggle?.setAttribute('aria-expanded', String(open));\n toggle?.setAttribute('aria-label', open ? 'Collapse ticket panel' : 'Open ticket panel');\n };\n setSheet(root.dataset.sheet === 'open');\n toggle?.addEventListener('click', (e) => {\n e.stopPropagation();\n setSheet(root.dataset.sheet !== 'open');\n });\n let startY = 0;\n let swiped = false;\n let tracking = false;\n head.addEventListener('pointerdown', (e: PointerEvent) => {\n tracking = true;\n swiped = false;\n startY = e.clientY;\n head.setPointerCapture?.(e.pointerId);\n });\n head.addEventListener('pointermove', (e: PointerEvent) => {\n if (!tracking || swiped) return;\n const dy = e.clientY - startY;\n if (dy < -18) {\n setSheet(true);\n swiped = true;\n } else if (dy > 18) {\n setSheet(false);\n swiped = true;\n }\n });\n head.addEventListener('pointerup', (e: PointerEvent) => {\n if (tracking && !swiped && Math.abs(e.clientY - startY) < 6) {\n if (!(e.target as HTMLElement).closest('.sl-seccard,.sl-sheet-toggle')) setSheet(root.dataset.sheet !== 'open');\n }\n tracking = false;\n head.releasePointerCapture?.(e.pointerId);\n });\n }\n this.tipEl = document.createElement('div');\n this.tipEl.setAttribute('role', 'tooltip');\n this.tipEl.className = 'sl-tip';\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 this.els.holdChange?.addEventListener('click', () => void this.handleChangeSeats());\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 // Read-only load state: the chart() payload carries salesClosed.\n this.salesClosed = !!info.salesClosed;\n\n // Feature 6: anchor regions for all persistent map chrome, then move the\n // pre-built zoom column + toast into their regions (both were in the skeleton).\n this.buildRegions();\n this.regions['bottom-right'].appendChild(this.els.zoom);\n this.regions['bottom-center'].appendChild(this.els.toast);\n\n if (info.mode === 'test') {\n // TEST MODE reads as a small badge in the top-right region (was a corner\n // ribbon that collided with the top-right control cluster on narrow widths).\n const badge = document.createElement('div');\n badge.className = 'sl-testbadge';\n badge.textContent = t('picker.testMode');\n badge.setAttribute('aria-label', t('picker.testMode'));\n this.regions['top-right'].appendChild(badge);\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 // \"Powered by SeatLayer\" attribution badge — hidden when the host opts out\n // OR the org's paid chart theme sets hideBadge (either being true hides it).\n this.buildBadge(chartTheme);\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.regions['top-left'].appendChild(chips);\n this.a11yChipsEl = chips;\n // Multi-select OR semantics (parity with the buyer page): each type chip\n // toggles independently; the active filter is the union; \"All seats\"\n // clears. A buyer needing wheelchair AND companion seats combines both.\n const active = new Set<AccessibilityType>();\n const syncChips = (): void => {\n chips.querySelectorAll<HTMLButtonElement>('button').forEach((b) => {\n const f = b.dataset.f as AccessibilityType | 'all';\n const on = f === 'all' ? active.size === 0 : active.has(f);\n b.classList.toggle('on', on);\n b.setAttribute('aria-pressed', String(on));\n });\n const filter = active.size ? [...active] : null;\n this.controller.setAccessibilityFilter(filter);\n // The accessibility filter dims/highlights individual SEAT dots, which\n // only render at the 'seats' rung. Applying it from a zoomed-out rung\n // (zones/sections) would silently dim seats the buyer can't see — so on\n // activation jump straight to seat detail, where the matching seats\n // stand out. Only when pills exist and we're not already there; never\n // on clear (so \"All seats\" doesn't yank the zoom).\n if (filter && this.rungsEl && this.controller.getRung() !== 'seats') {\n this.controller.setRung('seats');\n this.collapseSectionCard();\n this.syncRung();\n }\n };\n chips.querySelectorAll<HTMLButtonElement>('button').forEach((btn) => {\n btn.addEventListener('click', () => {\n const f = btn.dataset.f as AccessibilityType | 'all';\n if (f === 'all') active.clear();\n else if (active.has(f)) active.delete(f);\n else active.add(f);\n syncChips();\n });\n });\n }\n\n // Colorblind-safe toggle rides in the zoom column (wide) or the sheet's\n // Filters row (narrow) — dockLayoutChrome moves it between the two.\n const cb = document.createElement('button');\n cb.type = 'button';\n cb.className = 'sl-cbbtn';\n this.cbEl = cb;\n cb.setAttribute('aria-label', 'Toggle colorblind-friendly colors');\n // Rehydrated from the shared preference (constructor read stored → this.cbSafe).\n cb.setAttribute('aria-pressed', String(this.cbSafe));\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 cb.addEventListener('click', () => {\n this.cbSafe = !this.cbSafe;\n cb.setAttribute('aria-pressed', String(this.cbSafe));\n this.controller.setColorblindSafe(this.cbSafe);\n // Persist under the SAME key the public page uses (cross-surface preference).\n writeStoredColorblind(this.cbSafe);\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 // F3 minimap (venue overview + viewport rect) and F4 price-band filter.\n // Same post-render append (the map host was wiped by controller.render()).\n this.buildMinimap();\n this.buildPriceFilter();\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 this.buildSoldoutOverlay();\n\n // Dock layout-dependent chrome (a11y chips + colorblind toggle) for the\n // CURRENT layout — the initial applyLayout ran before these were built.\n this.dockLayoutChrome();\n\n await this.restoreRememberedHold();\n if (this.destroyed) return this;\n\n // Reflect the read-only load state (pill + disabled CTA/controls) with no\n // toast — a fresh mount into a closed event is not a live \"just closed\" event.\n if (this.salesClosed) this.applySalesClosed();\n this.syncPrices();\n this.syncTray();\n return this;\n }\n\n /**\n * Move layout-dependent chrome between its wide dock (map regions / zoom\n * column) and its narrow dock (the sheet's consolidated Filters row), and\n * re-render the section card in the form the layout wants (docked card/pill\n * on wide, sheet strip on narrow). Runs on every layout flip + once post-render.\n */\n private dockLayoutChrome(): void {\n const narrow = this.root?.dataset.layout === 'narrow';\n const filters = this.els.filters;\n if (filters) {\n if (narrow) {\n if (this.a11yChipsEl) filters.appendChild(this.a11yChipsEl);\n if (this.cbEl) filters.appendChild(this.cbEl);\n } else {\n if (this.a11yChipsEl) this.regions['top-left']?.appendChild(this.a11yChipsEl);\n if (this.cbEl) this.els.zoom?.appendChild(this.cbEl);\n }\n const has = narrow && filters.children.length > 0;\n filters.classList.toggle('has', has);\n this.els.filtersSec?.classList.toggle('has', has);\n }\n if (this.lastSection) this.renderSectionCard(this.lastSection);\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.regions['bottom-center'] ?? 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 /**\n * Localized string with a literal fallback. `t()` returns the key itself for\n * unknown keys, so this collapses that to `fallback` — while still honoring a\n * host `messages` override (which makes `t()` return the override, not the key).\n */\n private tf(key: string, fallback: string): string {\n const v = t(key);\n return v === key ? fallback : v;\n }\n\n /** Sold-out overlay — centered over the map, disabled waitlist stub (Gap 2). */\n private buildSoldoutOverlay(): void {\n if (!this.els.map) return;\n const el = document.createElement('div');\n el.className = 'sl-soldout';\n el.setAttribute('role', 'status');\n const name = (this.controller.doc?.theme?.brandName ?? this.opts.theme?.brandName ?? this.els.name?.textContent ?? this.tf('picker.soldOutEyebrow', 'This event')).toUpperCase();\n el.innerHTML =\n `<div class=\"sl-soldout-eyebrow\">${name}</div>` +\n `<div class=\"sl-soldout-title\">${this.tf('picker.soldOutTitle', 'Sold out')}</div>` +\n `<p class=\"sl-soldout-copy\">${this.tf('picker.soldOutCopy', \"Every seat is gone. Join the waitlist and we’ll email you if seats are released.\")}</p>` +\n `<button type=\"button\" class=\"sl-soldout-btn\" disabled>${this.tf('picker.waitlist', 'Join waitlist')}</button>`;\n this.els.map.appendChild(el);\n this.soldoutEl = el;\n }\n\n /**\n * Recompute the sold-out state on every price/availability sync. Sold-out ⇔\n * every SEATED category's live free count is 0. Suppressed when the chart has\n * GA areas (GA capacity isn't per-seat, so seated counts would read 0 and\n * falsely block standing room) — mirrors the public page. Clears live when WS\n * frees a seat up.\n */\n private syncSoldout(categories: Array<{ key: string }>, left: Record<string, number>): void {\n const hasGA = this.controller.getGAAreas().length > 0;\n const soldOut = this.isSoldOut(categories, left, hasGA);\n if (soldOut === this.soldOut) return;\n this.soldOut = soldOut;\n this.soldoutEl?.classList.toggle('on', soldOut);\n }\n\n /**\n * Pure sold-out predicate: every SEATED category's free count is 0, there is at\n * least one seated category, and there are no GA areas (GA capacity isn't\n * per-seat, so seated counts read 0 and would falsely block standing room).\n * `left` is seeded implicitly — a missing key means a fully-booked tier (0 free).\n */\n private isSoldOut(categories: Array<{ key: string }>, left: Record<string, number>, hasGA: boolean): boolean {\n return !hasGA && categories.length > 0 && categories.every((c) => (left[c.key] ?? 0) === 0);\n }\n\n /**\n * Sales-closed read-only state (Gap 3): persistent header pill, disabled CTA\n * with a closed label, and frozen best-available / GA controls. `setSalesClosed`\n * is the reactive entry (live 409 event_closed); `applySalesClosed` is the\n * idempotent DOM apply used at load and on transition.\n */\n private setSalesClosed(closed: boolean): void {\n if (this.salesClosed === closed) return;\n this.salesClosed = closed;\n this.applySalesClosed();\n }\n\n private applySalesClosed(): void {\n const pill = this.els.closedPill;\n if (pill) {\n pill.classList.toggle('on', this.salesClosed);\n const text = this.els.closedPillText ?? pill;\n text.textContent = this.tf('picker.salesClosedPill', 'Sales are closed');\n }\n this.root?.setAttribute('data-sales-closed', String(this.salesClosed));\n this.syncCta();\n this.syncTray();\n }\n\n /** The badge is hidden when the host opts out OR the org's theme sets hideBadge. */\n private badgeHidden(chartTheme?: ChartTheme): boolean {\n return !!(this.opts.hideBadge || chartTheme?.hideBadge);\n }\n\n /** Attribution badge in the side-panel foot (Gap 7). Hidden per host/theme. */\n private buildBadge(chartTheme: ChartTheme | undefined): void {\n if (this.badgeHidden(chartTheme)) return;\n const foot = this.els.foot;\n if (!foot) return;\n const el = document.createElement('div');\n el.className = 'sl-powered';\n el.innerHTML =\n `<span class=\"sl-powered-mark\" aria-hidden=\"true\">` +\n `<svg viewBox=\"0 0 24 24\"><path d=\"M4 15c0-1.1.9-2 2-2h12a2 2 0 0 1 2 2v3h-3v-2H7v2H4v-3Z\"/><rect x=\"7\" y=\"7\" width=\"10\" height=\"5\" rx=\"1.6\"/></svg>` +\n `</span><span>${this.tf('picker.poweredBy', 'Powered by SeatLayer')}</span>`;\n foot.appendChild(el);\n }\n\n // ---- Feature 6: chrome anchor regions -------------------------------------\n\n /**\n * Create the positioned flex containers that own every persistent map overlay.\n * Appended once after controller.render(); each chrome piece is then appended\n * INTO its region and flows within it, so nothing free-floats over anything\n * else. Regions carve the map into non-overlapping zones (top strip split into\n * left/center/right, left rail, and the three used corners).\n */\n private buildRegions(): void {\n if (!this.els.map) return;\n const REGIONS = ['top-left', 'top-center', 'top-right', 'left-rail', 'bottom-left', 'bottom-center', 'bottom-right'];\n for (const region of REGIONS) {\n const el = document.createElement('div');\n el.className = 'sl-anchor';\n el.dataset.region = region;\n this.els.map.appendChild(el);\n this.regions[region] = el;\n }\n }\n\n // ---- F3 minimap -----------------------------------------------------------\n\n /** Read a resolved --sl-* token value (canvas needs a real color, not var()). */\n private cssVar(name: string): string {\n return this.root ? getComputedStyle(this.root).getPropertyValue(name).trim() : '';\n }\n\n /** Motion is progressive enhancement; all state remains legible when reduced. */\n private reducedMotion(): boolean {\n return typeof window !== 'undefined' &&\n typeof window.matchMedia === 'function' &&\n window.matchMedia('(prefers-reduced-motion: reduce)').matches;\n }\n\n private scheduleMotion(fn: () => void, delay: number): void {\n const timer = setTimeout(() => {\n this.motionTimers.delete(timer);\n if (!this.destroyed) fn();\n }, delay);\n this.motionTimers.add(timer);\n }\n\n /** Restart one finite CSS animation without leaving a permanent state class. */\n private animateOnce(el: HTMLElement | undefined, className: string, duration = 600): void {\n if (!el || this.reducedMotion()) return;\n el.classList.remove(className);\n void el.offsetWidth;\n el.classList.add(className);\n this.scheduleMotion(() => el.classList.remove(className), duration);\n }\n\n /** Selection feedback belongs on the selected seat, not across the whole map. */\n private flashPickedSeat(id: string): void {\n if (this.reducedMotion()) return;\n this.controller.flashSeat(id, this.cssVar('--sl-accent') || '#f4b740');\n }\n\n /** A completed hold gets one short map ripple per concrete seat. */\n private flashHeldSeats(hold: HoldResult): void {\n if (this.reducedMotion()) return;\n const labels = (hold.items ?? []).filter((item) => item.objectType !== 'ga').map((item) => item.label);\n labels.slice(0, 10).forEach((label, index) => {\n const seat = this.controller.seatByLabel(label);\n if (!seat) return;\n this.scheduleMotion(\n () => this.controller.flashSeat(seat.id, this.cssVar('--sl-accent') || '#f4b740'),\n index * 55,\n );\n });\n }\n\n /** Update only the action affordance; selection callbacks must not refire. */\n private committedSelection(): PickerSeat[] {\n const candidateId = this.confirmSeat?.id;\n return this.controller.getSelection().filter((seat) => seat.id !== candidateId);\n }\n\n private pendingSelectionCount(): number {\n const heldItems = this.hold?.items ?? [];\n const heldLabels = new Set(heldItems.map((item) => item.label));\n const pendingSeats = this.committedSelection().filter((seat) => !heldLabels.has(seat.label)).length;\n return pendingSeats + this.pendingGACount();\n }\n\n private heldGACounts(): Map<string, number> {\n const heldGA = new Map<string, number>();\n for (const item of (this.hold?.items ?? []).filter((candidate) => candidate.objectType === 'ga')) {\n heldGA.set(item.objectId, (heldGA.get(item.objectId) ?? 0) + (item.quantity ?? 1));\n }\n return heldGA;\n }\n\n private pendingGACount(): number {\n const heldGA = this.heldGACounts();\n return [...this.gaQty.entries()].reduce(\n (sum, [areaId, qty]) => sum + Math.max(0, qty - (heldGA.get(areaId) ?? 0)),\n 0,\n );\n }\n\n private heldTicketCount(): number {\n return (this.hold?.items ?? []).reduce((sum, item) => sum + (item.quantity ?? 1), 0);\n }\n\n private totalTicketCount(): number {\n const heldLabels = new Set((this.hold?.items ?? []).map((item) => item.label));\n const freshSeats = this.committedSelection().filter((seat) => !heldLabels.has(seat.label)).length;\n return this.heldTicketCount() + freshSeats + this.pendingGACount();\n }\n\n /** Held tickets and standing quantities consume the same order-wide cap. */\n private updateSelectionCapacity(): void {\n const heldLabels = new Set((this.hold?.items ?? []).map((item) => item.label));\n const selectedHeld = this.committedSelection().filter((seat) => heldLabels.has(seat.label)).length;\n const remaining = Math.max(0, this.maxTickets - this.heldTicketCount() - this.pendingGACount());\n this.controller.setMaxSelection(selectedHeld + remaining);\n }\n\n private canAddTicket(): boolean {\n if (this.totalTicketCount() < this.maxTickets) return true;\n this.toast(`You can select up to ${this.maxTickets} tickets for this order.`, 'warning');\n return false;\n }\n\n private pendingGATotal(gaAreas: ReturnType<PickerController['getGAAreas']>): number {\n const heldGA = new Map<string, number>();\n for (const item of (this.hold?.items ?? []).filter((candidate) => candidate.objectType === 'ga')) {\n heldGA.set(item.objectId, (heldGA.get(item.objectId) ?? 0) + (item.quantity ?? 1));\n }\n return gaAreas.reduce(\n (sum, area) => sum + this.paidPrice(area.categoryKey, null, area.price) * Math.max(0, (this.gaQty.get(area.id) ?? 0) - (heldGA.get(area.id) ?? 0)),\n 0,\n );\n }\n\n private syncCta(count = this.lastTrayCount, pending = this.pendingSelectionCount()): void {\n const cta = this.els.cta as HTMLButtonElement | undefined;\n if (!cta) return;\n if (this.salesClosed) {\n cta.disabled = true;\n cta.textContent = this.tf('picker.salesClosedCta', 'Sales closed');\n return;\n }\n if (this.confirmSeat) {\n cta.disabled = true;\n cta.textContent = 'Confirm or cancel this seat';\n return;\n }\n if (this.ctaPhase === 'holding') {\n cta.disabled = true;\n cta.innerHTML = '<span class=\"sl-cta-spin\" aria-hidden=\"true\"></span>Securing seats…';\n return;\n }\n if (this.ctaPhase === 'checkout') {\n cta.disabled = true;\n cta.innerHTML = '<span class=\"sl-cta-spin\" aria-hidden=\"true\"></span>Opening checkout…';\n return;\n }\n cta.disabled = count === 0;\n cta.textContent = this.hold\n ? pending\n ? `Secure ${pending} more & checkout`\n : 'Continue to checkout'\n : count\n ? 'Hold seats & checkout'\n : 'Select seats';\n }\n\n private setCtaPhase(phase: 'idle' | 'holding' | 'checkout'): void {\n this.ctaPhase = phase;\n this.syncCta();\n if (phase === 'checkout') {\n this.scheduleMotion(() => {\n if (this.ctaPhase !== 'checkout') return;\n this.ctaPhase = 'idle';\n this.syncCta();\n }, 1100);\n }\n }\n\n /** Session-scoped capability key: isolated by API origin and event. */\n private holdStorageKey(): string {\n return `@seatlayer/hold/v1/${encodeURIComponent(this.apiBase)}/${encodeURIComponent(this.opts.event)}`;\n }\n\n private rememberedHoldId(): string | null {\n if (this.opts.initialHoldId) return this.opts.initialHoldId;\n if (this.opts.restoreHold === false || typeof window === 'undefined') return null;\n try {\n return window.sessionStorage.getItem(this.holdStorageKey());\n } catch {\n return null;\n }\n }\n\n private rememberHold(hold: HoldResult): void {\n if (this.opts.restoreHold === false || typeof window === 'undefined') return;\n try {\n // Persist only the opaque capability. Labels, prices and expiry are\n // always reloaded from the authoritative server projection.\n window.sessionStorage.setItem(this.holdStorageKey(), hold.holdId);\n } catch {\n // Storage can be unavailable in privacy/sandboxed embeds; the live picker\n // remains fully functional for the current mount.\n }\n }\n\n private forgetHold(): void {\n if (typeof window === 'undefined') return;\n try {\n window.sessionStorage.removeItem(this.holdStorageKey());\n } catch {\n // Best-effort cleanup only.\n }\n }\n\n private async resumeHoldFromServer(holdId: string, automatic: boolean): Promise<HoldResult | null> {\n try {\n const h = await this.controller.resumeHold(holdId);\n if (!h) return null;\n const restored: HoldResult = {\n holdId: h.holdId,\n expiresAt: h.expiresAt,\n seats: h.seats,\n items: h.items,\n };\n this.hold = restored;\n // A resumed capability came from an earlier checkout handoff. Keep it\n // alive if this picker mount is refreshed or torn down before the buyer\n // explicitly removes/releases it.\n this.handedOff = true;\n this.bookedShown = false;\n this.ctaPhase = 'idle';\n this.startHoldTimer(restored.expiresAt);\n this.rememberHold(restored);\n this.syncTray();\n this.emitHoldChange();\n this.opts.onHoldRestored?.(restored, restored.seats ?? [], this.buildHandoff(restored));\n if (automatic) this.toast('Your held tickets have been restored.', 'success');\n return restored;\n } catch (error) {\n const status = (error as { status?: number })?.status;\n if (status === 404 || status === 409) {\n // A stale/foreign/settled capability is expected recovery state, not a\n // picker failure. Drop it and let the buyer choose again.\n this.forgetHold();\n } else {\n this.opts.onError?.(error);\n }\n return null;\n }\n }\n\n private async restoreRememberedHold(): Promise<void> {\n const holdId = this.rememberedHoldId();\n if (holdId) await this.resumeHoldFromServer(holdId, true);\n }\n\n /** Section-bearing objects on the active floor (single-floor → doc.objects). */\n private activeFloorObjects(): SectionLike[] {\n const doc = this.controller.doc;\n if (!doc) return [];\n const floors = doc.floors;\n if (floors?.length) {\n const id = this.controller.getActiveFloorId();\n return ((floors.find((f) => f.id === id) ?? floors[0]).objects as unknown as SectionLike[]) ?? [];\n }\n return (doc.objects as unknown as SectionLike[]) ?? [];\n }\n\n /**\n * Build the overview minimap: a static venue thumbnail (section outlines, or\n * seat dots when the chart has no sections) with the live viewport rectangle\n * drawn on top. The rect tracks pan/zoom via the constructor's onViewChange.\n */\n private buildMinimap(): void {\n const vp = this.controller.getViewport();\n if (!vp || !this.els.map) return;\n const b = vp.bounds;\n if (!(b.width > 0 && b.height > 0)) return;\n\n const MAXW = 158;\n const MAXH = 118;\n const PAD = 6;\n const aspect = b.width / Math.max(1, b.height);\n let w = MAXW;\n let h = Math.round(MAXW / aspect);\n if (h > MAXH) {\n h = MAXH;\n w = Math.round(MAXH * aspect);\n }\n w = Math.max(64, w);\n h = Math.max(48, h);\n const dpr = Math.min(2, window.devicePixelRatio || 1);\n\n const wrap = document.createElement('div');\n wrap.className = 'sl-minimap';\n wrap.setAttribute('aria-hidden', 'true'); // decorative; the map itself is the keyboard surface\n const canvas = document.createElement('canvas');\n canvas.width = Math.round(w * dpr);\n canvas.height = Math.round(h * dpr);\n canvas.style.width = `${w}px`;\n canvas.style.height = `${h}px`;\n wrap.appendChild(canvas);\n (this.regions['bottom-left'] ?? this.els.map).appendChild(wrap);\n this.miniCanvas = canvas;\n\n // world → minimap (device px), contain + centre — matches thumb.ts.\n const scale = Math.min((w - PAD * 2) / Math.max(1, b.width), (h - PAD * 2) / Math.max(1, b.height)) * dpr;\n const offX = (w * dpr - b.width * scale) / 2 - b.x * scale;\n const offY = (h * dpr - b.height * scale) / 2 - b.y * scale;\n this.miniTf = { scale, offX, offY, dpr };\n\n const base = document.createElement('canvas');\n base.width = canvas.width;\n base.height = canvas.height;\n this.miniBase = base;\n\n // Click a section on the minimap → glide the camera into it (existing API).\n wrap.addEventListener('click', (e) => this.minimapJump(e));\n\n this.drawMinimapStatic();\n this.drawMinimapRect();\n }\n\n /** Repaint the static overview + rect (floor switch, live open/close). */\n private refreshMinimap(): void {\n if (!this.miniBase) return;\n this.drawMinimapStatic();\n this.drawMinimapRect();\n }\n\n /** Paint the venue overview into the offscreen base canvas. */\n private drawMinimapStatic(): void {\n const base = this.miniBase;\n const tf = this.miniTf;\n const doc = this.controller.doc;\n if (!base || !tf || !doc) return;\n const ctx = base.getContext('2d');\n if (!ctx) return;\n ctx.clearRect(0, 0, base.width, base.height);\n const fx = (x: number): number => x * tf.scale + tf.offX;\n const fy = (y: number): number => y * tf.scale + tf.offY;\n const line = this.cssVar('--sl-line') || 'rgba(139,147,167,.5)';\n const muted = this.cssVar('--sl-muted') || '#8b93a7';\n const accent = this.cssVar('--sl-accent') || '#6e7bff';\n const zoneColor = new Map((doc.zones ?? []).map((z) => [z.id, z.color] as const));\n\n let drewSection = false;\n for (const o of this.activeFloorObjects()) {\n if (o.type !== 'section' || !o.outline || o.outline.length < 3) continue;\n drewSection = true;\n const closed = this.controller.isSectionClosed(o.id);\n const fill = closed ? muted : o.color ?? (o.zone && zoneColor.get(o.zone)) ?? accent;\n ctx.beginPath();\n o.outline.forEach((p, i) => (i === 0 ? ctx.moveTo(fx(p.x), fy(p.y)) : ctx.lineTo(fx(p.x), fy(p.y))));\n ctx.closePath();\n ctx.globalAlpha = closed ? 0.26 : 0.42;\n ctx.fillStyle = fill;\n ctx.fill();\n ctx.globalAlpha = 0.85;\n ctx.lineWidth = Math.max(1, tf.dpr);\n ctx.strokeStyle = line;\n ctx.stroke();\n }\n ctx.globalAlpha = 1;\n\n // Section-less charts: fall back to faint category-colored seat dots.\n if (!drewSection) {\n const r = Math.max(1, tf.dpr);\n for (const seat of expandChart(doc)) {\n const cat = doc.categories.find((c) => c.key === seat.categoryKey);\n ctx.fillStyle = cat?.color ?? accent;\n ctx.beginPath();\n ctx.arc(fx(seat.x), fy(seat.y), r, 0, Math.PI * 2);\n ctx.fill();\n }\n }\n }\n\n /** Blit the base overview, then stroke the current viewport rectangle on top. */\n private drawMinimapRect(): void {\n const canvas = this.miniCanvas;\n const base = this.miniBase;\n const tf = this.miniTf;\n if (!canvas || !base || !tf) return;\n const ctx = canvas.getContext('2d');\n if (!ctx) return;\n ctx.clearRect(0, 0, canvas.width, canvas.height);\n ctx.drawImage(base, 0, 0);\n const vp = this.controller.getViewport();\n if (!vp) return;\n const v = vp.visible;\n const x = v.x * tf.scale + tf.offX;\n const y = v.y * tf.scale + tf.offY;\n const w = v.width * tf.scale;\n const h = v.height * tf.scale;\n const accent = this.cssVar('--sl-accent') || '#f4b740';\n ctx.save();\n ctx.globalAlpha = 0.14;\n ctx.fillStyle = accent;\n ctx.fillRect(x, y, w, h);\n ctx.globalAlpha = 1;\n ctx.lineWidth = Math.max(1.5, tf.dpr * 1.5);\n ctx.strokeStyle = accent;\n ctx.strokeRect(x, y, w, h);\n ctx.restore();\n }\n\n /** Minimap click → focus the section under the point (or overview on a miss). */\n private minimapJump(e: MouseEvent): void {\n const canvas = this.miniCanvas;\n const tf = this.miniTf;\n if (!canvas || !tf) return;\n const r = canvas.getBoundingClientRect();\n const px = (e.clientX - r.left) * (canvas.width / r.width);\n const py = (e.clientY - r.top) * (canvas.height / r.height);\n const wx = (px - tf.offX) / tf.scale;\n const wy = (py - tf.offY) / tf.scale;\n for (const o of this.activeFloorObjects()) {\n if (o.type !== 'section' || !o.outline || o.outline.length < 3) continue;\n if (this.controller.isSectionClosed(o.id)) continue;\n if (pointInPolygon(wx, wy, o.outline)) {\n this.controller.focusSection(o.id);\n return;\n }\n }\n this.controller.overview();\n }\n\n // ---- F4 price-band filter -------------------------------------------------\n\n /** Effective display price of a category: host pricing override → first tier → base. */\n private catPrice(c: { key?: string; price?: number; tiers?: { id?: string; price: number }[] }): number | undefined {\n const chart = c.tiers?.length ? c.tiers[0].price : c.price;\n if (chart === undefined || !c.key) return chart;\n return this.paidPrice(c.key, c.tiers?.[0]?.id ?? null, chart);\n }\n\n /** Derive price bands: one chip per distinct price (≤5), else quantile ranges. */\n private priceBands(): PriceBand[] {\n const doc = this.controller.doc;\n if (!doc) return [];\n const priced = doc.categories\n .map((c) => ({ key: c.key, price: this.catPrice(c) }))\n .filter((x): x is { key: string; price: number } => x.price != null);\n if (!priced.length) return [];\n const distinct = [...new Set(priced.map((p) => p.price))].sort((a, b) => a - b);\n if (distinct.length <= 5) {\n return distinct.map((price) => ({\n id: `p${price}`,\n label: this.money(price),\n keys: priced.filter((p) => p.price === price).map((p) => p.key),\n min: price,\n max: price,\n }));\n }\n // Many distinct prices → ~4 contiguous quantile bands (ranges).\n const chunk = Math.ceil(distinct.length / 4);\n const bands: PriceBand[] = [];\n for (let i = 0; i < distinct.length; i += chunk) {\n const slice = distinct.slice(i, i + chunk);\n const lo = slice[0];\n const hi = slice[slice.length - 1];\n bands.push({\n id: `b${i}`,\n label: lo === hi ? this.money(lo) : `${this.money(lo)}–${this.money(hi)}`,\n keys: priced.filter((p) => p.price >= lo && p.price <= hi).map((p) => p.key),\n min: lo,\n max: hi,\n });\n }\n return bands;\n }\n\n /** Build the compact price selector in the panel header. Choosing a band both\n * filters availability and smoothly frames the matching seats on the map. */\n private buildPriceFilter(): void {\n if (!this.els.prices || !this.els.pricesSec) return;\n const bands = this.priceBands();\n if (bands.length < 2) return;\n const select = document.createElement('select');\n select.className = 'sl-price-select';\n select.setAttribute('aria-label', 'Filter and focus seats by price');\n select.innerHTML = `<option value=\"all\">All prices</option>` + bands\n .map((band) => `<option value=\"${band.id}\">${band.label}</option>`)\n .join('');\n this.els.pricesSec.appendChild(select);\n select.addEventListener('change', () => {\n const band = bands.find((candidate) => candidate.id === select.value);\n const keys = band?.keys ?? null;\n this.focusedCatKey = null; // band filter supersedes any pinned row focus\n this.priceBandKeys = keys ? new Set(keys) : null;\n this.controller.setCategoryFilter(keys);\n this.controller.focusCategoryFilter(keys);\n // A band whose seats live on another deck switches floors — mirror it.\n this.syncFloors();\n this.syncRung();\n this.refreshMinimap();\n // Reflect the band in the legend rows + any open section card.\n this.syncPrices();\n if (this.lastSection) this.showSectionCard(this.lastSection);\n });\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', () => {\n const rung = btn.dataset.rung as LodRung;\n this.controller.setRung(rung);\n if (rung === 'seats') this.collapseSectionCard();\n });\n });\n this.regions['top-center'].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 this.refreshMinimap();\n });\n });\n this.regions['left-rail'].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 this.lastSection = summary;\n this.secCardEl?.remove();\n this.secCardEl = null;\n if (!summary) return;\n // At seat level the summary is context, not a blocking decision surface.\n // Keep it as the compact pill from the first seat-level paint.\n this.secCardCollapsed = this.controller.getRung() === 'seats';\n this.secCardShownAt = Date.now();\n this.renderSectionCard(summary);\n }\n\n /**\n * Render the section card in the form the layout + state want: expanded card\n * or slim pill in the top-center anchor region (wide), or a compact strip in\n * the sheet head (narrow). Never floats over the seats at the tap point.\n */\n private renderSectionCard(summary: SectionSummary): void {\n if (!this.els.map) return;\n this.secCardEl?.remove();\n // min/max over the section's categories at the price the buyer will PAY\n // (host pricing override aware) — not the chart's stored range.\n const paid = summary.categories.length\n ? summary.categories.map((c) => this.paidPrice(c.key, null, c.price))\n : [summary.priceMin, summary.priceMax];\n const paidMin = Math.min(...paid);\n const paidMax = Math.max(...paid);\n const priceLabel =\n paidMin === paidMax\n ? this.money(paidMin)\n : `${this.money(paidMin)}–${this.money(paidMax)}`;\n const leftLabel = tCount('picker.seatsLeftInSection', summary.seatsLeft);\n const xBtn = `<button type=\"button\" class=\"sl-seccard-x\" aria-label=\"${t('picker.closeSectionSummary')}\">✕</button>`;\n const card = document.createElement('div');\n const narrow = this.root?.dataset.layout === 'narrow';\n\n if (narrow) {\n // Compact strip inside the bottom sheet's peek head — never over the map.\n card.className = 'sl-seccard strip on';\n card.setAttribute('role', 'status');\n card.setAttribute('aria-label', t('picker.sectionSummaryAria', { label: summary.label }));\n card.innerHTML =\n `<span class=\"sl-seccard-dot\" style=\"background:${summary.color}\"></span>` +\n `<span class=\"sl-seccard-name\">${summary.label}</span>` +\n `<span class=\"sl-seccard-left\">${leftLabel}</span>` +\n (summary.categories.length ? `<span class=\"sl-seccard-price\">${priceLabel}</span>` : '') +\n xBtn;\n card.querySelector('.sl-seccard-x')!.addEventListener('click', () => this.controller.overview());\n (this.els.sheetHead ?? this.els.side ?? this.els.map).appendChild(card);\n } else if (this.secCardCollapsed) {\n // Slim pill — seat-picking has begun. Tap to re-expand; ✕ still closes.\n card.className = 'sl-seccard mini on';\n card.setAttribute('role', 'button');\n card.setAttribute('aria-label', t('picker.sectionSummaryAria', { label: summary.label }));\n card.innerHTML =\n `<span class=\"sl-seccard-dot\" style=\"background:${summary.color}\"></span>` +\n `<span class=\"sl-seccard-name\">${summary.label}</span>` +\n `<span class=\"sl-seccard-left\">${leftLabel}</span>` +\n xBtn;\n card.addEventListener('click', (e) => {\n if ((e.target as HTMLElement).closest('.sl-seccard-x')) return;\n this.secCardCollapsed = false;\n this.secCardShownAt = Date.now();\n this.renderSectionCard(summary);\n });\n card.querySelector('.sl-seccard-x')!.addEventListener('click', () => this.controller.overview());\n (this.regions['top-center'] ?? this.els.map).appendChild(card);\n } else {\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((c) => {\n const dim = this.priceBandKeys != null && !this.priceBandKeys.has(c.key);\n return (\n `<span class=\"sl-seccard-mix-item${dim ? ' sl-dim' : ''}\"><span class=\"sl-seccard-mix-dot\" style=\"background:${c.color}\"></span>` +\n `${c.label} <span class=\"sl-seccard-mix-price\">${this.money(this.paidPrice(c.key, null, c.price))}</span></span>`\n );\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 xBtn + `</div>` +\n `<div class=\"sl-seccard-zone\">${summary.zoneLabel ? `${summary.zoneLabel} · ` : ''}` +\n `<span class=\"sl-seccard-left\">${leftLabel}</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.regions['top-center'] ?? this.els.map).appendChild(card);\n }\n this.secCardEl = card;\n }\n\n /** Collapse the expanded card to its slim pill (seat-picking started). */\n private collapseSectionCard(): void {\n if (!this.secCardEl || this.secCardCollapsed || !this.lastSection) return;\n if (this.root?.dataset.layout === 'narrow') return; // strip is already compact\n this.secCardCollapsed = true;\n this.renderSectionCard(this.lastSection);\n }\n\n /**\n * onViewChange hook for the card. The focus glide's own settle (within the\n * grace window) enforces the ~25% coverage rule with the FINAL viewport; any\n * later pan/zoom means seat-picking has begun → collapse to the pill.\n */\n private sectionCardOnView(): void {\n if (!this.secCardEl || this.secCardCollapsed || !this.lastSection) return;\n if (this.root?.dataset.layout === 'narrow') return;\n if (this.controller.getRung() === 'seats') {\n this.collapseSectionCard();\n return;\n }\n if (Date.now() - this.secCardShownAt < 1400) {\n if (this.sectionCardCoverage() > 0.25) this.collapseSectionCard();\n return;\n }\n this.collapseSectionCard();\n }\n\n /** Fraction of the focused section's on-screen bbox covered by the card. */\n private sectionCardCoverage(): number {\n const card = this.secCardEl;\n const sec = this.lastSection;\n if (!card || !sec || !this.els.map) return 0;\n const outline = this.activeFloorObjects().find((o) => o.type === 'section' && o.id === sec.id)?.outline;\n if (!outline || outline.length < 3) return 0;\n const pts = outline.map((p) => this.controller.worldToScreen(p));\n const xs = pts.map((p) => p.x);\n const ys = pts.map((p) => p.y);\n const bx = Math.min(...xs);\n const by = Math.min(...ys);\n const bw = Math.max(...xs) - bx;\n const bh = Math.max(...ys) - by;\n if (bw <= 0 || bh <= 0) return 0;\n const mapR = this.els.map.getBoundingClientRect();\n const cr = card.getBoundingClientRect();\n const cx = cr.left - mapR.left;\n const cy = cr.top - mapR.top;\n const ox = Math.max(0, Math.min(cx + cr.width, bx + bw) - Math.max(cx, bx));\n const oy = Math.max(0, Math.min(cy + cr.height, by + bh) - Math.max(cy, by));\n return (ox * oy) / (bw * bh);\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 ? this.catPrice(cat) : undefined;\n this.srEl.textContent = `Seat ${seat.label}, ${cat?.label ?? seat.categoryKey}${\n price != null ? `, ${this.money(price)}` : ''\n }, ${statusText}`;\n }\n\n // ---- seat candidate confirmation ------------------------------------------\n\n private showConfirm(seat: ExpandedSeat): void {\n const previousId = this.confirmSeat?.id;\n this.confirmEl?.remove();\n this.confirmEl = null;\n this.confirmSeat = seat;\n this.root?.setAttribute('data-confirming', 'true');\n this.controller.setSelectionFocus(seat.id);\n if (previousId && previousId !== seat.id) this.controller.deselect([previousId]);\n if (this.tipEl) this.tipEl.style.display = 'none';\n const details = this.controller.seatDetails(seat.id);\n const cat = this.controller.doc?.categories.find((c) => c.key === seat.categoryKey);\n const chartPrice = details?.price ?? (cat?.tiers?.length ? cat.tiers[0].price : cat?.price);\n const price = chartPrice != null\n ? this.paidPrice(seat.categoryKey, details?.tierId ?? cat?.tiers?.[0]?.id ?? null, chartPrice)\n : undefined;\n const safe = (value: unknown): string => String(value ?? '—').replace(/[&<>\"]/g, (char) => ({\n '&': '&', '<': '<', '>': '>', '\"': '"',\n })[char]!);\n const el = document.createElement('div');\n el.className = 'sl-confirm';\n el.setAttribute('role', 'dialog');\n el.setAttribute('aria-modal', 'true');\n el.setAttribute('aria-label', `Confirm seat ${seat.label}`);\n el.style.setProperty('--sl-cat', cat?.color ?? '#6e7bff');\n el.innerHTML =\n `<div class=\"sl-confirm-grid\">` +\n `<div class=\"sl-confirm-field\"><span class=\"sl-confirm-key\">Section</span><span class=\"sl-confirm-value\">${safe(details?.sectionLabel)}</span></div>` +\n `<div class=\"sl-confirm-field\"><span class=\"sl-confirm-key\">Row</span><span class=\"sl-confirm-value\">${safe(this.rowShort(details))}</span></div>` +\n `<div class=\"sl-confirm-field\"><span class=\"sl-confirm-key\">Seat</span><span class=\"sl-confirm-value\">${safe(details?.seatNumber ?? seat.label)}</span></div>` +\n `</div>` +\n `<div class=\"sl-confirm-cat\"><span class=\"sl-dot\" style=\"background:${cat?.color ?? '#6e7bff'}\"></span>` +\n `<span class=\"sl-confirm-cat-name\">${safe(details?.categoryLabel ?? cat?.label ?? seat.categoryKey)}</span>` +\n (price != null ? `<span class=\"sl-confirm-price\">${this.money(price)}</span>` : '') + `</div>` +\n `<div class=\"sl-confirm-body\">` +\n (this.seatViewEnabled() ? this.confirmThumbHtml(seat) : '') +\n `<div class=\"sl-confirm-row\">` +\n `<button type=\"button\" class=\"sl-confirm-cancel\">Cancel</button>` +\n `<button type=\"button\" class=\"sl-confirm-add\"><svg viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M5 12.5l4 4L19 7\"/></svg>Select</button></div></div>`;\n this.els.map.appendChild(el);\n this.confirmEl = el;\n this.reanchorConfirm();\n el.querySelector('.sl-confirm-view')?.addEventListener('click', () => this.openSeatView(seat));\n el.querySelector('.sl-confirm-add')!.addEventListener('click', () => this.commitConfirm());\n el.querySelector('.sl-confirm-cancel')!.addEventListener('click', () => this.cancelConfirm());\n requestAnimationFrame(() => el.querySelector<HTMLButtonElement>('.sl-confirm-add')?.focus());\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 if (this.root?.dataset.layout === 'narrow') return;\n const mapWidth = this.els.map.clientWidth;\n const mapHeight = this.els.map.clientHeight;\n const cardWidth = this.confirmEl.offsetWidth || 276;\n const cardHeight = this.confirmEl.offsetHeight || 230;\n const half = cardWidth / 2 + 12;\n const x = Math.max(half, Math.min(mapWidth - half, p.x));\n const belowFits = p.y + cardHeight + 24 <= mapHeight;\n const placeBelow = p.y < cardHeight + 24 && belowFits;\n this.confirmEl.dataset.placement = placeBelow ? 'below' : 'above';\n this.confirmEl.style.left = `${x}px`;\n this.confirmEl.style.top = `${Math.max(8, Math.min(mapHeight - 8, p.y))}px`;\n }\n\n private dismissConfirm(): void {\n this.confirmEl?.remove();\n this.confirmEl = null;\n this.confirmSeat = null;\n this.root?.removeAttribute('data-confirming');\n this.controller.setSelectionFocus(null);\n }\n\n private commitConfirm(): void {\n if (!this.confirmSeat) return;\n this.dismissConfirm();\n this.collapseSectionCard();\n this.syncTray();\n }\n\n private cancelConfirm(): void {\n const seat = this.confirmSeat;\n if (!seat) return;\n this.controller.deselect([seat.id]);\n if (this.confirmSeat) this.dismissConfirm();\n this.root?.focus({ preventScroll: true });\n }\n\n private closeConfirm(): void {\n this.dismissConfirm();\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\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 const formatter = this.opts.pricing?.formatter;\n if (formatter) return formatter(n, this.currency);\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 /**\n * The price the buyer will actually pay for a category (+tier): the host's\n * `pricing` override when present, else the chart's stored price. Every\n * price the widget DISPLAYS or hands off must flow through here — a map\n * that shows one price while checkout charges another destroys trust.\n */\n private paidPrice(categoryKey: string | undefined, tierId: string | null | undefined, fallback: number): number {\n const entry = categoryKey ? this.opts.pricing?.prices?.[categoryKey] : undefined;\n if (entry === undefined) return fallback;\n if (typeof entry === 'number') return entry;\n if (tierId && entry.tiers?.[tierId] !== undefined) return entry.tiers[tierId];\n return entry.base ?? fallback;\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.narrateAvailability(doc.categories, left);\n this.syncSoldout(doc.categories, left);\n // Big events ship 10–20 ticket types; an uncapped list shoves \"Your seats\"\n // and the CTA below the fold. Cap the closed list and expand on demand\n // (never hide a single row behind a toggle — that costs more than it saves).\n const PRICE_LIMIT = 5;\n const overflow = doc.categories.length - PRICE_LIMIT;\n const collapsed = overflow > 1 && !this.pricesExpanded;\n const shown = collapsed ? doc.categories.slice(0, PRICE_LIMIT) : doc.categories;\n this.els.prices.classList.toggle('sl-expanded', overflow > 1 && this.pricesExpanded);\n this.els.prices.innerHTML = shown\n .map((c) => {\n const price = this.catPrice(c);\n const active = this.focusedCatKey === c.key;\n const dim = this.priceBandKeys != null && !this.priceBandKeys.has(c.key);\n return (\n `<div class=\"sl-price-row${dim ? ' sl-dim' : ''}${active ? ' sl-active' : ''}\" data-cat=\"${c.key}\"` +\n ` role=\"button\" tabindex=\"0\" aria-pressed=\"${active}\"` +\n ` title=\"${active ? 'Show all seats' : `Show ${c.label} seats on the map`}\">` +\n `<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 (overflow > 1\n ? `<button type=\"button\" class=\"sl-price-more\" aria-expanded=\"${!collapsed}\">` +\n (collapsed ? `Show all ${doc.categories.length} ticket types` : 'Show fewer') +\n `</button>`\n : '') +\n `<div class=\"sl-status-key\" aria-label=\"Seat status legend\">` +\n `<span class=\"sl-status-item\"><i class=\"sl-status-icon\" aria-hidden=\"true\">` +\n `<svg viewBox=\"0 0 24 24\"><rect x=\"5\" y=\"10\" width=\"14\" height=\"10\" rx=\"2\"/><path d=\"M8 10V7a4 4 0 0 1 8 0v3\"/></svg>` +\n `</i>Temporarily held</span>` +\n `<span class=\"sl-status-item\"><i class=\"sl-status-icon sold\" aria-hidden=\"true\">` +\n `<svg viewBox=\"0 0 24 24\"><path d=\"M7 17L17 7\"/></svg>` +\n `</i>Sold</span>` +\n `</div>`;\n // Legend-hover highlight: dim other categories on the map while hovering a row.\n // Click (or Enter/Space) pins that focus — filter + frame the category on\n // the map; a second click clears it.\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 const toggle = () => this.focusCategory(row.dataset.cat ?? '');\n row.addEventListener('click', toggle);\n row.addEventListener('keydown', (e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n toggle();\n }\n });\n });\n this.els.prices.querySelector<HTMLButtonElement>('.sl-price-more')?.addEventListener('click', () => {\n this.pricesExpanded = !this.pricesExpanded;\n this.syncPrices();\n });\n }\n\n /** Tap a price row → filter + frame that category on the map; tap again to\n * clear. Shares `priceBandKeys` with the band selector so the row-dim state\n * has one source of truth (and each control resets the other). */\n private focusCategory(key: string): void {\n if (!key) return;\n const next = this.focusedCatKey === key ? null : key;\n this.focusedCatKey = next;\n this.priceBandKeys = next ? new Set([next]) : null;\n const select = this.els.pricesSec?.querySelector<HTMLSelectElement>('.sl-price-select');\n if (select) select.value = 'all';\n this.controller.setCategoryFilter(next ? [next] : null);\n this.controller.focusCategoryFilter(next ? [next] : null);\n // Focusing a category on another deck switches floors — mirror that onto\n // the floor pills / rung pills / minimap, same as a manual deck switch.\n this.syncFloors();\n this.syncRung();\n this.refreshMinimap();\n this.syncPrices();\n if (this.lastSection) this.showSectionCard(this.lastSection);\n }\n\n /**\n * Live-activity strip: turn WS availability deltas into one quiet line of\n * social proof (\"2 seats just taken in VIP · 118 left\"). Diffs per-category\n * counts on every status change — no per-seat payload needed. Skips the very\n * first computation (initial load is not \"activity\").\n */\n private narrateAvailability(\n categories: Array<{ key: string; label: string }>,\n left: Record<string, number>,\n ): void {\n const textEl = this.els.liveText;\n const prev = this.lastCatAvail;\n this.lastCatAvail = { ...left };\n // A floor switch re-baselines availability (counts are per-rendered-floor,\n // and the post-switch status snapshot lands asynchronously a beat later).\n // Narrating across that window produces a phantom \"N seats just taken\", so\n // stay quiet until the new floor settles — only genuine WS deltas after\n // that are news.\n const floorId = this.controller.getActiveFloorId();\n if (floorId !== this.lastAvailFloorId) {\n this.lastAvailFloorId = floorId;\n this.availQuietUntil = performance.now() + 2000;\n }\n if (!textEl || !prev || performance.now() < this.availQuietUntil) return;\n for (const cat of categories) {\n const before = prev[cat.key];\n const now = left[cat.key] ?? 0;\n if (before === undefined || now >= before) continue;\n const taken = before - now;\n textEl.textContent = `${taken} seat${taken === 1 ? '' : 's'} just taken in ${cat.label} · ${now} left`;\n // Surface the strip only while it carries news, then give the space back.\n this.els.live?.classList.remove('on');\n // Reflow between remove/add restarts the entrance animation on repeats.\n void (this.els.live as HTMLElement | undefined)?.offsetWidth;\n this.els.live?.classList.add('on');\n if (this.liveTimer) clearTimeout(this.liveTimer);\n this.liveTimer = setTimeout(() => this.els.live?.classList.remove('on'), 8000);\n return;\n }\n }\n private lastCatAvail: Record<string, number> | null = null;\n private lastAvailFloorId = '';\n private availQuietUntil = 0;\n private liveTimer: ReturnType<typeof setTimeout> | null = null;\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>([\n ...(this.controller.currentHold()?.labels ?? []),\n ...this.holdingLabels,\n ]);\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.`, 'error');\n }\n\n private syncTray(): void {\n if (!this.els.tray) return;\n this.updateSelectionCapacity();\n const seats = this.committedSelection();\n const gaAreas = this.controller.getGAAreas();\n const heldItems = this.hold?.items ?? [];\n const parts: string[] = [];\n const nextTrayKeys = new Set<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 // Best available is the fastest path for buyers who haven't picked yet —\n // but the moment a seat lands in the tray, the ticket cards own this space.\n // (Busy/confirm states stay visible so an in-flight search isn't cut off.)\n const noPicks = !seats.length && !heldItems.length && !this.pendingGACount();\n if (!this.hold && (noPicks || this.bestAvailableBusy || this.bestAvailableConfirm)) {\n const cats = this.controller.doc?.categories ?? [];\n parts.push(this.bestAvailableConfirm\n ? `<div class=\"sl-ba\" role=\"alert\">` +\n `<div class=\"sl-ba-title\"><span class=\"spark\" aria-hidden=\"true\">✦</span>Replace your current choices?</div>` +\n `<div class=\"sl-ba-replace\"><b>We’ll find ${this.baQty} seats together.</b>` +\n `<span>Your manually selected tickets will be removed only after a new group is secured.</span></div>` +\n `<div class=\"sl-ba-actions\"><button type=\"button\" data-ba-cancel>Keep mine</button>` +\n `<button type=\"button\" class=\"replace\" data-ba-replace>Find new seats</button></div></div>`\n : `<div class=\"sl-ba\">` +\n `<div class=\"sl-ba-title\"><span class=\"spark\" aria-hidden=\"true\">✦</span>Find the best seats together</div>` +\n `<div class=\"sl-ba-copy\"><span class=\"wide\">We’ll choose the closest available group for you.</span>` +\n `<span class=\"narrow\">Closest available group, chosen instantly.</span></div>` +\n (cats.length > 1\n ? `<select aria-label=\"Preferred ticket type\" data-ba-cat>` +\n `<option value=\"\">Any ticket type</option>` +\n cats.map((c) => `<option value=\"${c.key}\"${this.baCat === c.key ? ' selected' : ''}>${c.label}</option>`).join('') +\n `</select>`\n : `<span aria-hidden=\"true\"></span>`) +\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\"${this.bestAvailableBusy ? ' disabled' : ''}>` +\n (this.bestAvailableBusy\n ? `<span class=\"sl-ba-spin\" aria-hidden=\"true\"></span>Finding the best seats…`\n : `Find ${this.baQty} best ${this.baQty === 1 ? 'seat' : 'seats'}`) +\n `</button></div>`);\n }\n\n // Held line items (best-available, completed, or restored). Tier is\n // server-committed, but each item can be released without discarding the\n // rest of the hold.\n // Ticket-card identity grid: SECTION | ROW | SEAT, echoing the confirm\n // popover so the buyer meets the same identity pattern at confirm and in\n // the cart. Falls back to the raw label when spatial context is missing\n // (GA lines, legacy labels).\n const idGrid = (seatId: string | null, label: string): string => {\n const d = seatId ? this.controller.seatDetails(seatId) : null;\n if (!d?.sectionLabel && !d?.rowLabel && !d?.seatNumber) {\n return `<div class=\"sl-chip-id\"><span class=\"fld sec\"><span class=\"sl-chip-eb\">Seat</span><span class=\"val\">${label}</span></span></div>`;\n }\n return (\n `<div class=\"sl-chip-id\">` +\n `<span class=\"fld sec\"><span class=\"sl-chip-eb\">Section</span><span class=\"val\">${d.sectionLabel ?? '—'}</span></span>` +\n (d.rowLabel ? `<span class=\"fld mid\"><span class=\"sl-chip-eb\">Row</span><span class=\"val\">${this.rowShort(d)}</span></span>` : '') +\n (d.seatNumber ? `<span class=\"fld mid\"><span class=\"sl-chip-eb\">Seat</span><span class=\"val\">${d.seatNumber}</span></span>` : '') +\n `</div>`\n );\n };\n // Right icon rail per the canonical mock: remove on top, seat view below.\n const iconRail = (rmAria: string, viewLabel: string | null): string =>\n `<div class=\"sl-chip-rail\">` +\n `<button type=\"button\" class=\"rm\" aria-label=\"${rmAria}\">` +\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>` +\n (viewLabel\n ? `<button type=\"button\" class=\"view\" data-view-label=\"${viewLabel}\" aria-label=\"${t('picker.viewFromSeat', { label: viewLabel })}\">` +\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 for (const item of heldItems) {\n const itemKey = `held:${item.label}`;\n nextTrayKeys.add(itemKey);\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 heldSeat = item.objectType !== 'ga' ? this.controller.seatByLabel(item.label) : null;\n const canView = this.seatViewEnabled() && !!heldSeat;\n parts.push(\n `<div class=\"sl-chip sl-held${this.lastTrayKeys.has(itemKey) ? '' : ' sl-enter'}\" data-key=\"${itemKey}\" data-held=\"${encodeURIComponent(item.label)}\"${heldSeat ? ` data-locate=\"${heldSeat.id}\"` : ''}>` +\n `<div class=\"sl-chip-main\">` +\n idGrid(heldSeat?.id ?? null, item.label) +\n `<div class=\"sl-chip-sub\">` +\n `<span class=\"sl-ticket-state held\" aria-label=\"Held for you\" title=\"Held for you\">` +\n `<svg viewBox=\"0 0 24 24\"><rect x=\"5\" y=\"10\" width=\"14\" height=\"10\" rx=\"2\"/><path d=\"M8 10V7a4 4 0 0 1 8 0v3\"/></svg></span>` +\n `<span class=\"cat\">${cat?.label ?? item.categoryKey}${tierName ? ` · ${tierName}` : ''}</span>` +\n `<span class=\"amt\">${this.money(this.paidPrice(item.categoryKey, item.tierId, item.unitPrice) * (item.quantity ?? 1))}</span>` +\n `</div></div>` +\n iconRail(`Remove held ticket ${item.label}`, canView ? item.label : null) +\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 itemKey = `seat:${s.id}`;\n nextTrayKeys.add(itemKey);\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(this.paidPrice(s.categoryKey, ti.id, ti.price))}</option>`)\n .join('') +\n `</select>`\n : '';\n parts.push(\n `<div class=\"sl-chip${this.lastTrayKeys.has(itemKey) ? '' : ' sl-enter'}\" data-key=\"${itemKey}\" data-seat=\"${s.id}\" data-locate=\"${s.id}\">` +\n `<div class=\"sl-chip-main\">` +\n idGrid(s.id, s.label) +\n `<div class=\"sl-chip-sub\">` +\n `<span class=\"sl-ticket-state\" aria-label=\"Selected\" title=\"Selected\">` +\n `<svg viewBox=\"0 0 24 24\"><path d=\"M5 12l4 4L19 6\"/></svg></span>` +\n `<span class=\"cat\">${cat?.label ?? s.categoryKey}</span>${tierSelect}` +\n `<span class=\"amt\">${this.money(this.paidPrice(s.categoryKey, s.tierId ?? null, s.price))}</span>` +\n `</div></div>` +\n iconRail(`Remove ${s.label}`, canView ? s.label : null) +\n `</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(this.paidPrice(area.categoryKey, null, 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 this.els.tray.innerHTML = parts.join('');\n this.lastTrayKeys = nextTrayKeys;\n this.els.tray.querySelectorAll<HTMLButtonElement>('[data-ba]').forEach((btn) => {\n btn.addEventListener('click', () => {\n this.baQty = Math.max(1, Math.min(this.maxTickets, 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 if (this.pendingSelectionCount() > 0) {\n this.bestAvailableConfirm = true;\n this.syncTray();\n this.els.tray.querySelector<HTMLButtonElement>('[data-ba-replace]')?.focus();\n return;\n }\n void this.bestAvailable(this.baQty, this.baCat || undefined);\n });\n this.els.tray.querySelector<HTMLButtonElement>('[data-ba-cancel]')?.addEventListener('click', () => {\n this.bestAvailableConfirm = false;\n this.syncTray();\n this.els.tray.querySelector<HTMLButtonElement>('.sl-ba-go')?.focus();\n });\n this.els.tray.querySelector<HTMLButtonElement>('[data-ba-replace]')?.addEventListener('click', () => {\n this.bestAvailableConfirm = false;\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 chip = btn.closest('.sl-chip') as HTMLElement;\n if (chip.dataset.held) {\n void this.removeHeldLabel(decodeURIComponent(chip.dataset.held), chip);\n return;\n }\n const id = chip.dataset.seat!;\n const label = this.controller.getSelection().find((sel) => sel.id === id)?.label ?? 'Seat';\n const remove = (): void => {\n this.controller.deselect([id]);\n this.toast(`${label} removed.`, 'neutral', {\n label: 'Undo',\n onClick: () => {\n const restored = this.controller.select([id]);\n this.toast(\n restored.length ? `${label} restored.` : `${label} is no longer available.`,\n restored.length ? 'success' : 'warning',\n );\n },\n });\n };\n if (this.reducedMotion()) {\n remove();\n return;\n }\n chip.classList.add('sl-leave');\n this.scheduleMotion(remove, 150);\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 // Card ↔ map linkage: hovering (or keyboard-focusing) a ticket card pulses\n // its seat on the map so the buyer can locate what they picked.\n this.els.tray.querySelectorAll<HTMLElement>('.sl-chip[data-locate]').forEach((chip) => {\n const locate = (): void => this.controller.flashSeat(chip.dataset.locate!, this.cssVar('--sl-accent') || '#f4b740');\n chip.addEventListener('mouseenter', locate);\n chip.addEventListener('focusin', locate);\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 delta = Number(btn.dataset.d);\n if (delta > 0 && !this.canAddTicket()) return;\n const next = Math.max(0, Math.min(area?.available ?? 0, (this.gaQty.get(id) ?? 0) + delta));\n this.gaQty.set(id, next);\n this.syncTray();\n });\n });\n\n // Sales closed: freeze the best-available + GA controls (read-only state).\n if (this.salesClosed) {\n this.els.tray\n .querySelectorAll<HTMLButtonElement | HTMLSelectElement>('.sl-ba-go,[data-ba],[data-ba-cat],[data-ba-replace],.sl-ga button')\n .forEach((el) => {\n el.disabled = true;\n });\n }\n\n // totals + CTA (held lines + fresh selections + GA)\n const gaTotal = this.pendingGATotal(gaAreas);\n const gaCount = this.pendingGACount();\n const heldTotal = heldItems.reduce((sum, item) => sum + this.paidPrice(item.categoryKey, item.tierId, 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 + this.paidPrice(s.categoryKey, s.tierId ?? null, s.price), 0) + gaTotal + heldTotal;\n const count = freshSeats.length + gaCount + heldCount;\n const pendingCount = this.pendingSelectionCount();\n const previousCount = this.lastTrayCount;\n const previousTotal = this.lastTrayTotal;\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 this.root?.setAttribute('data-has-selection', String(count > 0));\n // The best-available panel's confirm (\"Replace your current choices?\") and\n // in-flight busy states must survive the narrow-layout collapse that hides\n // .sl-ba once the cart is non-empty. Mark them so the CSS keeps them shown.\n this.root?.setAttribute(\n 'data-ba-active',\n String(this.bestAvailableConfirm || this.bestAvailableBusy),\n );\n this.els.foot?.classList.toggle('empty', count === 0);\n if (this.els.seatSummary) {\n this.els.seatSummary.textContent = count ? `${count} selected` : '';\n }\n this.syncCta(count, pendingCount);\n if (this.hold) {\n const securedCount = heldCount || this.hold.seats?.length || 0;\n if (this.els.holdTitle) {\n this.els.holdTitle.textContent = `${securedCount} secured`;\n }\n if (this.els.holdCopy) {\n this.els.holdCopy.textContent = pendingCount\n ? `${pendingCount} more selected`\n : 'Checkout timer running';\n }\n const change = this.els.holdChange as HTMLButtonElement | undefined;\n if (change) {\n change.disabled = this.releasingHold;\n change.textContent = this.releasingHold ? 'Releasing…' : 'Change';\n }\n }\n if (count !== previousCount) this.animateOnce(this.els.count, 'sl-value-pop', 380);\n if (total !== previousTotal) this.animateOnce(this.els.total, 'sl-value-pop', 380);\n if (previousCount === 0 && count > 0) this.animateOnce(this.els.cta, 'sl-ready', 520);\n\n // Mobile sheet: one-line peek summary. Selected → \"N tickets · $X · Continue\";\n // empty → \"From $min · Best available\". Tap (sheet head) expands the sheet.\n if (this.els.peek) {\n if (count) {\n // Sheet state is shown by the persistent chevron in the head; the pill is\n // the action affordance (\"Continue\"/\"Review\") — no inline text arrow.\n this.els.peek.innerHTML =\n `<span>${count} ${count === 1 ? 'ticket' : 'tickets'} · ${this.money(total)}</span>` +\n `<span class=\"go\">${this.hold ? (pendingCount ? 'Secure more' : 'Continue') : 'Review'}</span>`;\n } else {\n const prices = (this.controller.doc?.categories ?? [])\n .map((c) => this.catPrice(c))\n .filter((p): p is number => p != null);\n this.els.peek.innerHTML =\n (prices.length ? `<span>From ${this.money(Math.min(...prices))}</span>` : '<span>Pick your seats</span>') +\n `<span class=\"go\">✦ Best seats</span>`;\n }\n }\n // Keep the mobile map stable after selection. The persistent Review pill\n // exposes the updated count/total without covering the seat the buyer just\n // confirmed; opening the sheet remains an explicit tap or swipe.\n this.lastTrayCount = count;\n this.lastTrayTotal = total;\n\n this.opts.onSelectionChange?.(seats);\n }\n\n private async removeHeldLabel(label: string, chip?: HTMLElement): Promise<boolean> {\n if (!label || this.releasingLabels.has(label)) return false;\n this.releasingLabels.add(label);\n chip?.setAttribute('aria-busy', 'true');\n const button = chip?.querySelector<HTMLButtonElement>('.rm');\n if (button) button.disabled = true;\n try {\n const preserveAcrossNavigation = this.handedOff;\n const released = await this.controller.releaseLabels([label]);\n if (!released) {\n this.toast(`Couldn't remove ${label}. Your hold is unchanged.`, 'error');\n return false;\n }\n const remaining = this.controller.currentHold();\n this.hold = remaining\n ? { holdId: remaining.holdId, expiresAt: remaining.expiresAt, seats: remaining.seats, items: remaining.items }\n : null;\n this.handedOff = !!this.hold && preserveAcrossNavigation;\n this.bookedShown = false;\n this.ctaPhase = 'idle';\n if (this.hold) {\n this.startHoldTimer(this.hold.expiresAt);\n } else {\n this.stopHoldTimer();\n this.forgetHold();\n }\n this.syncTray();\n this.emitHoldChange();\n this.toast(`${label} removed from your hold.`, 'success');\n return true;\n } finally {\n this.releasingLabels.delete(label);\n chip?.removeAttribute('aria-busy');\n if (button?.isConnected) button.disabled = false;\n }\n }\n\n private async handleChangeSeats(): Promise<void> {\n if (!this.hold || this.releasingHold) return;\n this.releasingHold = true;\n const button = this.els.holdChange as HTMLButtonElement | undefined;\n if (button) {\n button.disabled = true;\n button.textContent = 'Releasing…';\n }\n try {\n await this.release();\n if (!this.hold) this.toast('Held tickets released. Choose your new seats.', 'success');\n } finally {\n this.releasingHold = false;\n if (button?.isConnected) {\n button.disabled = false;\n button.textContent = 'Change';\n }\n }\n }\n\n private async handleCta(): Promise<void> {\n if (this.salesClosed) return;\n if (this.totalTicketCount() > this.maxTickets) {\n this.toast(`Remove tickets until your order has ${this.maxTickets} or fewer.`, 'warning');\n return;\n }\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 const committed = this.committedSelection();\n if (this.hold && !committed.some((s) => !(this.hold!.items ?? []).some((i) => i.label === s.label))) {\n const seats = this.hold.seats ?? committed;\n this.handedOff = true;\n this.setCtaPhase('checkout');\n this.opts.onCheckout?.(this.hold, seats, this.buildHandoff(this.hold));\n return;\n }\n this.holdingLabels = new Set(committed.map((seat) => seat.label));\n this.setCtaPhase('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.committedSelection();\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.', 'error');\n this.setCtaPhase('idle');\n this.syncTray();\n return;\n }\n this.hold = hold;\n this.handedOff = true;\n this.startHoldTimer(hold.expiresAt);\n this.flashHeldSeats(hold);\n this.setCtaPhase('checkout');\n this.emitHoldChange();\n // The replacement hold can combine an earlier best-available set with\n // newly selected seats. Hand the host the complete held seat set; the\n // server-priced line items remain authoritative for GA and totals.\n this.opts.onCheckout?.(hold, hold.seats ?? chosenSeats, this.buildHandoff(hold));\n } catch (err) {\n this.opts.onError?.(err);\n const problem = err as { reason?: string; conflicts?: Array<{ label?: string }> };\n const labels = (problem.conflicts ?? []).map((conflict) => conflict.label).filter(Boolean).slice(0, 3);\n // The CTA's controller.hold() path doesn't surface onSalesClosed — apply the\n // persistent read-only state here (the toast below stays). book/bestAvailable\n // paths reach it via the onSalesClosed callback.\n if (problem.reason === 'event_closed') this.setSalesClosed(true);\n const message = problem.reason === 'event_closed'\n ? 'Seat sales have closed for this event.'\n : labels.length\n ? `${labels.join(', ')} ${labels.length === 1 ? 'is' : 'are'} no longer available. Choose another ${labels.length === 1 ? 'seat' : 'group'}.`\n : 'One or more seats were just taken. Please pick again.';\n this.toast(message, 'error');\n this.setCtaPhase('idle');\n } finally {\n this.holdingLabels.clear();\n if (this.ctaPhase === 'holding') this.ctaPhase = 'idle';\n this.syncTray();\n }\n }\n\n private startHoldTimer(expiresAt: number): void {\n this.stopHoldTimer();\n this.holdExpiresAt = expiresAt;\n if (this.hold) this.rememberHold(this.hold);\n const pill = this.els.hold;\n pill.innerHTML =\n '<span class=\"sl-hold-dot\" aria-hidden=\"true\"></span><span>Held</span><span class=\"sl-hold-time\" data-ref=\"holdTime\"></span>';\n const time = pill.querySelector<HTMLElement>('[data-ref=\"holdTime\"]');\n this.els.holdNote?.classList.add('on');\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 if (time) time.textContent = `${m}:${s}`;\n pill.classList.add('on');\n pill.classList.toggle('is-expiring', ms > 0 && ms <= EXTEND_PROMPT_MS);\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', 'is-expiring');\n this.els.holdNote?.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.rememberHold(this.hold);\n this.emitHoldChange();\n this.toast('More time added — your seats are still held.', 'success');\n } else {\n this.toast(\"Couldn't add more time — please head to checkout now.\", 'warning');\n }\n } catch (err) {\n this.opts.onError?.(err);\n this.toast(\"Couldn't add more time — please head to checkout now.\", 'warning');\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 this.forgetHold();\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 // Host `pricing` overrides win in the handoff too — the host gets back the\n // prices it will actually charge, so map display and order total agree.\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: this.paidPrice(it.categoryKey, it.tierId, 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 emitHoldChange(): void {\n const hold = this.hold;\n this.opts.onHoldChange?.(\n hold,\n hold?.seats ?? [],\n hold ? this.buildHandoff(hold) : null,\n );\n }\n\n private toast(\n msg: string,\n tone: 'neutral' | 'success' | 'warning' | 'error' = 'neutral',\n action?: { label: string; onClick: () => void },\n ): void {\n const el = this.els.toast;\n if (!el) return;\n el.replaceChildren();\n const copy = document.createElement('span');\n copy.textContent = msg;\n el.appendChild(copy);\n el.classList.toggle('has-action', !!action);\n if (action) {\n const button = document.createElement('button');\n button.type = 'button';\n button.className = 'sl-toast-action';\n button.textContent = action.label;\n button.addEventListener('click', action.onClick, { once: true });\n el.appendChild(button);\n }\n el.dataset.tone = tone;\n el.classList.add('on');\n if (this.toastTimer) clearTimeout(this.toastTimer);\n this.toastTimer = setTimeout(() => {\n el.classList.remove('on');\n el.classList.remove('has-action');\n el.dataset.tone = 'neutral';\n }, 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 /**\n * Row label without the redundant section prefix. Charts commonly name row\n * objects \"104-A\" while the Section column already shows \"104\" — so the Row\n * cell repeats the section and, in the compact hover card, truncates to\n * \"10…\". Strip a leading \"<section><sep>\" so Row reads a clean \"A\". Only when\n * the prefix is exact (won't touch \"1040-A\" under section \"104\"); otherwise\n * the label is shown verbatim.\n */\n private rowShort(details: { sectionLabel?: string; rowLabel?: string } | null | undefined): string | undefined {\n const row = details?.rowLabel;\n const sec = details?.sectionLabel;\n if (!row || !sec) return row;\n for (const sep of ['-', ' ', '·', '/', '_']) {\n const prefix = `${sec}${sep}`;\n if (row.startsWith(prefix) && row.length > prefix.length) return row.slice(prefix.length);\n }\n return row;\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 esc = (v: unknown): string =>\n String(v ?? '—').replace(/[&<>\"]/g, (ch) => ({ '&': '&', '<': '<', '>': '>', '\"': '"' }[ch]!));\n const price = this.money(this.paidPrice(details.categoryKey, details.tierId ?? null, details.price));\n // Identity grid — the same Section·Row·Seat card the buyer meets on confirm\n // and in the cart, just smaller. Falls back to a single field for a bare\n // label (GA / legacy seats with no spatial context).\n const hasLoc = details.sectionLabel || details.rowLabel || details.seatNumber;\n const grid = hasLoc\n ? `<div class=\"sl-tip-grid\">` +\n `<div class=\"sl-tip-field\"><span class=\"sl-tip-key\">Section</span><span class=\"sl-tip-val\">${esc(details.sectionLabel)}</span></div>` +\n `<div class=\"sl-tip-field\"><span class=\"sl-tip-key\">Row</span><span class=\"sl-tip-val\">${esc(this.rowShort(details))}</span></div>` +\n `<div class=\"sl-tip-field\"><span class=\"sl-tip-key\">Seat</span><span class=\"sl-tip-val\">${esc(details.seatNumber ?? details.label)}</span></div>` +\n `</div>`\n : `<div class=\"sl-tip-grid one\"><div class=\"sl-tip-field\"><span class=\"sl-tip-key\">Seat</span><span class=\"sl-tip-val\">${esc(details.label)}</span></div></div>`;\n const statusLine =\n details.status === 'free'\n ? ''\n : `<div class=\"sl-tip-status\">${details.status === 'held' ? t('map.statusHeld') : t('map.statusTaken')}</div>`;\n this.tipEl.style.setProperty('--sl-cat', details.categoryColor);\n this.tipEl.innerHTML =\n grid +\n `<div class=\"sl-tip-cat\"><span class=\"sl-tip-dot\" style=\"background:${details.categoryColor}\"></span>` +\n `<span class=\"sl-tip-name\">${esc(details.categoryLabel)}</span>` +\n `<span class=\"sl-tip-amt\">${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.committedSelection();\n }\n\n /** Current active/restored hold reflected in the tray. */\n getCurrentHold(): HoldResult | null {\n return this.hold;\n }\n\n /** Explicit host-driven hold restore (automatic session restore is on by default). */\n async resumeHold(holdId: string): Promise<HoldResult | null> {\n return this.resumeHoldFromServer(holdId, false);\n }\n\n /** Remove one server-held ticket while keeping the rest of the hold active. */\n async removeHeldTicket(label: string): Promise<boolean> {\n return this.removeHeldLabel(label);\n }\n\n async bestAvailable(qty: number, categoryKey?: string): Promise<HoldResult | null> {\n if (this.salesClosed || this.bestAvailableBusy) return null;\n qty = Math.max(1, Math.min(this.maxTickets, Math.floor(qty)));\n if (this.confirmSeat) this.cancelConfirm();\n this.bestAvailableConfirm = false;\n this.bestAvailableBusy = true;\n const button = this.els.tray?.querySelector<HTMLButtonElement>('.sl-ba-go');\n if (button) {\n button.disabled = true;\n button.innerHTML = '<span class=\"sl-ba-spin\" aria-hidden=\"true\"></span>Finding…';\n }\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.gaQty.clear();\n this.startHoldTimer(h.expiresAt);\n this.flashHeldSeats(this.hold);\n this.syncTray();\n this.emitHoldChange();\n return this.hold;\n }\n return null;\n } catch (err) {\n this.opts.onError?.(err);\n const reason = (err as { reason?: string })?.reason;\n const message = reason === 'not_enough_together'\n ? `We couldn't find ${qty} seats together. Try fewer seats or another ticket type.`\n : reason === 'sold_out'\n ? 'That ticket type is sold out. Try another ticket type.'\n : reason === 'event_closed'\n ? 'Seat sales have closed for this event.'\n : 'Those seats are no longer available. Try another quantity or ticket type.';\n this.toast(message, 'error');\n return null;\n } finally {\n this.bestAvailableBusy = false;\n this.syncTray();\n }\n }\n\n async release(): Promise<void> {\n const tracked = this.hold;\n const controllerHold = this.controller.currentHold();\n let released = true;\n if (controllerHold) {\n released = await this.controller.release();\n } else if (tracked) {\n // The live controller can legitimately settle/clear its local hold before\n // the shell finishes dismissing. The shell still owns the server handoff,\n // so release from that authoritative copy instead of silently no-oping.\n const labels = [...new Set([\n ...(tracked.items ?? []).map((item) => item.label),\n ...(tracked.seats ?? []).map((seat) => seat.label),\n ])];\n if (labels.length) {\n try {\n await this.api.release(this.opts.event, labels, tracked.holdId);\n } catch (error) {\n this.opts.onError?.(error);\n released = false;\n }\n }\n }\n if (!released) {\n this.toast(\"Couldn't release your tickets. Your hold is unchanged.\", 'error');\n return;\n }\n this.hold = null;\n this.forgetHold();\n this.handedOff = false;\n this.bookedShown = false;\n this.ctaPhase = 'idle';\n this.stopHoldTimer();\n this.gaQty.clear();\n this.syncTray();\n this.emitHoldChange();\n }\n\n destroy(): void {\n this.destroyed = true;\n // Closing/tearing down before checkout means the buyer abandoned any\n // best-available hold. Release it server-side; a handed-off checkout keeps\n // its hold alive across the host's route transition.\n if (this.hold && !this.handedOff) void this.controller.release();\n this.closeConfirm();\n this.closeSeatView();\n this.stopHoldTimer();\n if (this.toastTimer) clearTimeout(this.toastTimer);\n if (this.liveTimer) clearTimeout(this.liveTimer);\n for (const timer of this.motionTimers) clearTimeout(timer);\n this.motionTimers.clear();\n this.ro?.disconnect();\n this.ro = null;\n // Don't strand a host frame pinned fullscreen across a route teardown.\n if (this.framedFs) this.setFramedFs(false);\n if (this.escHandler) document.removeEventListener('keydown', this.escHandler);\n if (this.fsChangeHandler) document.removeEventListener('fullscreenchange', this.fsChangeHandler);\n if (this.fsEscHandler) window.removeEventListener('keydown', this.fsEscHandler);\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","/**\n * Host-side helper for embedding the SeatLayer picker as an iframe.\n *\n * The picker (the /e/:key page, mounted `position:fixed; inset:0`) reports its\n * desired height and fullscreen intent to whatever page frames it, using the\n * picker wire contract:\n *\n * • `{ type: 'seatlayer:height', px:number }` — grow the iframe to `px`.\n * • `{ type: 'seatlayer:fullscreen', on:boolean }` — pin/unpin over the host.\n *\n * A framed picker cannot escape its own iframe with CSS, so it delegates both\n * concerns to the host. `attachPickerFrame` wires those two behaviours onto a\n * picker iframe and returns a detach function that tears everything back down.\n */\nexport interface AttachPickerFrameOptions {\n /**\n * Origin to accept messages from. Defaults to the origin parsed from\n * `iframe.src`. Messages from any other origin (or any other window) are\n * ignored — the picker posts with `targetOrigin:'*'`, so the host is the side\n * that must verify `event.origin`.\n */\n origin?: string;\n}\n\n/**\n * Attach the picker resize + fullscreen protocol to a picker iframe.\n *\n * ```ts\n * const iframe = document.querySelector('iframe#seatlayer')!;\n * const detach = attachPickerFrame(iframe);\n * // …later, when removing the embed:\n * detach();\n * ```\n *\n * @param iframe The `<iframe>` element pointing at a SeatLayer picker embed.\n * @param opts Optional `{ origin }` override for the accepted message origin.\n * @returns A detach function: removes the listener and restores any pinned state.\n */\nexport function attachPickerFrame(\n iframe: HTMLIFrameElement,\n opts: AttachPickerFrameOptions = {},\n): () => void {\n let expectedOrigin = opts.origin ?? '';\n if (!expectedOrigin) {\n try {\n expectedOrigin = new URL(iframe.src, window.location.href).origin;\n } catch {\n expectedOrigin = '';\n }\n }\n\n let pinned = false;\n let frameStyleBeforeFs: string | null = null;\n let docOverflowBeforeFs: string | null = null;\n let bodyOverflowBeforeFs: string | null = null;\n let lastAutoHeight = '';\n let keyHandler: ((event: KeyboardEvent) => void) | null = null;\n\n const pin = (): void => {\n if (pinned) return;\n pinned = true;\n frameStyleBeforeFs = iframe.getAttribute('style');\n Object.assign(iframe.style, {\n position: 'fixed',\n inset: '0',\n width: '100vw',\n height: '100vh',\n margin: '0',\n border: '0',\n zIndex: '2147483000',\n background: '#101625',\n } satisfies Partial<CSSStyleDeclaration>);\n\n const docEl = document.documentElement;\n docOverflowBeforeFs = docEl.style.overflow;\n docEl.style.overflow = 'hidden';\n if (document.body) {\n bodyOverflowBeforeFs = document.body.style.overflow;\n document.body.style.overflow = 'hidden';\n }\n\n keyHandler = (event: KeyboardEvent): void => {\n if (event.key === 'Escape') unpin();\n };\n window.addEventListener('keydown', keyHandler);\n };\n\n const unpin = (): void => {\n if (!pinned) return;\n pinned = false;\n if (frameStyleBeforeFs === null) iframe.removeAttribute('style');\n else iframe.setAttribute('style', frameStyleBeforeFs);\n frameStyleBeforeFs = null;\n // Re-apply any height reported while we were pinned.\n if (lastAutoHeight) iframe.style.height = lastAutoHeight;\n\n if (docOverflowBeforeFs !== null) {\n document.documentElement.style.overflow = docOverflowBeforeFs;\n docOverflowBeforeFs = null;\n }\n if (bodyOverflowBeforeFs !== null && document.body) {\n document.body.style.overflow = bodyOverflowBeforeFs;\n bodyOverflowBeforeFs = null;\n }\n if (keyHandler) {\n window.removeEventListener('keydown', keyHandler);\n keyHandler = null;\n }\n };\n\n const onMessage = (event: MessageEvent<unknown>): void => {\n if (event.source !== iframe.contentWindow) return;\n if (expectedOrigin && event.origin !== expectedOrigin) return;\n if (!event.data || typeof event.data !== 'object') return;\n const data = event.data as Record<string, unknown>;\n\n if (data.type === 'seatlayer:height') {\n if (typeof data.px === 'number' && Number.isFinite(data.px) && data.px > 0) {\n lastAutoHeight = `${Math.round(data.px)}px`;\n // While pinned the iframe fills the viewport; the height is re-applied on unpin.\n if (!pinned) iframe.style.height = lastAutoHeight;\n }\n return;\n }\n if (data.type === 'seatlayer:fullscreen') {\n if (data.on === true) pin();\n else if (data.on === false) unpin();\n }\n };\n\n window.addEventListener('message', onMessage);\n\n return (): void => {\n window.removeEventListener('message', onMessage);\n unpin();\n };\n}\n","/**\n * SeatManager — the organizer manage surface, packaged for the SDK.\n *\n * Productizes the SeatLayer dashboard's ManageEventPage into a framework-\n * agnostic class (mirrors how SeatPicker productized the buyer flow). It mounts\n * the shared engine in `manageMode`, subscribes to the event's realtime channel\n * and drives three control-room tools on one persistent canvas:\n *\n * - **view** — a live board: realtime seat repaint (flash on hold/book),\n * live KPI tallies + gross revenue, and a streaming activity\n * feed derived from the delta stream + audit log. Read-only.\n * - **inspect** — select one seat to read its live inventory context.\n * - **block** — bulk-first block/unblock: marquee-drag, ⌘A select-all,\n * whole-category / whole-section select, single-seat fallback →\n * one batched block/unblock (optimistic, reconciled by the WS),\n * and timed auto-release.\n *\n * Auth: reads (chart/objects/WS) are public; writes/reports carry a Bearer\n * event-scoped manage token (`mse_…`) or a tenant secret key (`sk_…`) via\n * {@link ManageApi}. Box office + Sections + full Reports UI are M2/M3.\n */\nimport {\n SeatmapRenderer,\n expandChart,\n computeSections,\n UNGROUPED_ID,\n type AvailabilityRule,\n type ChartDoc,\n type ChartTheme,\n type ExpandedSeat,\n type SeatStatus,\n type SectionNode,\n} from '@seatlayer/core';\nimport {\n ManageApi,\n ManageApiError,\n type ControlRoomActivityEntry,\n type ControlRoomSnapshot,\n type LogEntry,\n type ReportResult,\n} from './manageApi';\n\nexport type SeatManagerMode = 'view' | 'inspect' | 'block' | 'sections';\n\n/** The select-state of a Sections-mode availability row. An absent rule is\n * `open` (on sale); otherwise the rule's own mode. */\nexport type AvailabilityMode = 'open' | 'closed' | 'hidden' | 'timed' | 'threshold';\n\n/** One row of the Sections rail — a zone header or a single section. */\ninterface SectionRow {\n kind: 'zone' | 'section';\n id: string;\n label: string;\n seatCount: number;\n /** Seat labels the id governs (sent as the rule's `labels`). */\n seatLabels: string[];\n rule: AvailabilityRule | null;\n /** Effective-hidden right now (manual hide, or a timed/threshold window not yet due). */\n hidden: boolean;\n /** Effective-closed right now — visible to buyers but off sale. */\n closed: boolean;\n /** A section whose parent zone carries a rule — its own control is a muted \"Follows zone\". */\n followsZone: boolean;\n}\n\n/** Map an availability rule to its Sections-rail select value (null rule = on sale). */\nexport function availabilityModeOf(rule: AvailabilityRule | null | undefined): AvailabilityMode {\n return rule ? rule.mode : 'open';\n}\n\n/**\n * Build the rule a chosen select mode implies for a set of seat labels, reusing\n * an existing rule's tuning where it carries over (a timed reveal time, a\n * threshold percent). `open` clears the rule (returns null → id dropped from the\n * map). Wire-identical to the EventDO's accepted rule shapes.\n */\nexport function availabilityRuleForMode(\n mode: AvailabilityMode,\n seatLabels: string[],\n prev?: AvailabilityRule | null,\n): AvailabilityRule | null {\n switch (mode) {\n case 'open':\n return null;\n case 'hidden':\n return { mode: 'hidden', labels: seatLabels };\n case 'closed':\n return { mode: 'closed', labels: seatLabels };\n case 'timed':\n return { mode: 'timed', revealAt: prev?.revealAt ?? Date.now() + 3_600_000, labels: seatLabels };\n case 'threshold':\n return { mode: 'threshold', thresholdPct: prev?.thresholdPct ?? 80, labels: seatLabels };\n }\n}\n\n/** epoch ms → a `datetime-local` input value (local time, minute precision). */\nfunction toLocalInput(ms: number): string {\n const d = new Date(ms - new Date().getTimezoneOffset() * 60_000);\n return d.toISOString().slice(0, 16);\n}\n\n/** DO seat status — 'blocked' has no engine analogue (→ 'not_for_sale'). */\ntype DoStatus = 'free' | 'held' | 'booked' | 'blocked';\n\n/** Live KPI snapshot pushed to `onTallies` on every state change. */\nexport interface SeatManagerTallies {\n free: number;\n held: number;\n booked: number;\n blocked: number;\n /** Total seats on the chart. */\n total: number;\n /** booked / total, 0–100. */\n capacityPct: number;\n /** booked / (total − blocked), 0–100 — sell-through of sellable inventory. */\n sellThroughPct: number;\n /** Exact Σ booked unit_price snapshots from the authenticated report. */\n grossRevenue: number;\n /** Revenue is never reconstructed from chart list price. */\n revenueStatus: 'loading' | 'current' | 'stale';\n /** ISO-4217 currency for grossRevenue. */\n currency: string;\n}\n\n/** One streamed activity line for the live feed. */\nexport interface SeatManagerActivity {\n id: string;\n at: number;\n label: string;\n /** Full labels affected by this one backend/realtime operation. */\n labels: string[];\n count: number;\n /** Human verb: held / booked / released / blocked / unblocked. */\n verb: string;\n status: DoStatus;\n /** Spatial context for grouped activity when the chart defines sections. */\n sectionIds?: string[];\n sectionLabels?: string[];\n}\n\n/** Fired after a successful organizer action, for host toasts/telemetry. */\nexport interface SeatManagerActionResult {\n action: 'block' | 'unblock' | 'unblockAll' | 'cancelBooking' | 'setHoldTtl';\n labels: string[];\n count: number;\n}\n\nexport interface SeatManagerOptions {\n /** CSS selector or element to mount into. */\n container: string | HTMLElement;\n /** API origin. Defaults to https://api.seatlayer.io. */\n apiBase?: string;\n /** Event key (e.g. `ev_xxx` / `west-end-p3`). */\n eventKey: string;\n /** Bearer manage token — event-scoped `mse_…` or a tenant secret `sk_…`. */\n token: string;\n /** Absolute token expiry (epoch ms). Enables proactive in-place rotation. */\n tokenExpiresAt?: number;\n /** Initial mode. Default 'view'. */\n mode?: SeatManagerMode;\n /** ISO-4217 fallback currency for revenue (chart/event currency wins). */\n currency?: string;\n /** Chart theme override for the chrome (rails/bar). Chart colors come from the doc. */\n theme?: ChartTheme;\n /**\n * Keep the canvas painting even when the tab is hidden/backgrounded (a war-room\n * board on a second monitor). Calls `forceDraw()` after each delta so Chrome's\n * rAF throttling on occluded tabs never leaves the board stale. Default true.\n */\n keepLiveWhileHidden?: boolean;\n /**\n * Opt in to camera-following for new buyer holds/bookings. Off by default so\n * a live event never steals an operator's current map context.\n */\n followLive?: boolean;\n /** Chart + first snapshot are loaded and the board is live. */\n onReady?: () => void;\n /** Live KPI tallies changed. */\n onTallies?: (tallies: SeatManagerTallies) => void;\n /** A grouped live/audit activity item arrived. */\n onActivity?: (activity: SeatManagerActivity) => void;\n /** Exact private control-room projection changed. */\n onControlRoom?: (snapshot: ControlRoomSnapshot) => void;\n /** Called before token expiry. The manager swaps the result without remounting. */\n onTokenRefresh?: () => Promise<{ token: string; expiresAt: number }>;\n /** Tool/mode changed from inside the shared cockpit. */\n onModeChange?: (mode: SeatManagerMode) => void;\n /** Follow-live preference changed from inside the cockpit. */\n onFollowLiveChange?: (enabled: boolean) => void;\n /** Block-mode selection changed (marquee / ⌘A / category / section / tap). */\n onSelectionChange?: (seats: ExpandedSeat[]) => void;\n /** A block/unblock/cancel action completed successfully. */\n onActionComplete?: (result: SeatManagerActionResult) => 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(`seatmanager: container \"${container}\" not found`);\n return el as HTMLElement;\n }\n if (!(container instanceof HTMLElement)) {\n throw new Error('seatmanager: container must be a CSS selector or an HTMLElement');\n }\n return container;\n}\n\n/** 'blocked' → renderer 'not_for_sale'; the rest pass through. */\nfunction toRenderStatus(s: DoStatus): SeatStatus {\n return s === 'blocked' ? 'not_for_sale' : s;\n}\n\nconst DEFAULT_API_BASE = 'https://api.seatlayer.io';\nconst STYLE_ID = 'seatlayer-manager-style';\nconst FEED_CAP = 80;\nconst MAX_LIVE_SEAT_PULSES = 16;\nconst MAX_LIVE_SECTION_PULSES = 4;\n\nconst LEGEND: { key: 'free' | 'held' | 'booked' | 'blocked'; label: string; color: string }[] = [\n { key: 'free', label: 'Free', color: '#6e7bff' },\n { key: 'held', label: 'Held', color: '#f4b740' },\n { key: 'booked', label: 'Booked', color: '#22a06b' },\n { key: 'blocked', label: 'Blocked', color: '#8b94ac' },\n];\n\nconst CSS = `\n.slm{position:relative;display:flex;flex-direction:column;width:100%;height:100%;min-height:480px;overflow:hidden;\n background:var(--slm-bg);color:var(--slm-text);font-family:var(--slm-font);border-radius:var(--slm-radius)}\n.slm *{box-sizing:border-box;margin:0;padding:0}\n.slm button{font:inherit;color:inherit;background:none;border:0;cursor:pointer}\n.slm input{font:inherit}\n\n/* top bar */\n.slm-bar{display:grid;grid-template-columns:auto auto minmax(0,1fr);align-items:center;column-gap:14px;row-gap:10px;\n padding:10px 16px;border-bottom:1px solid var(--slm-line);flex:none}\n.slm-modes{display:inline-flex;background:var(--slm-surface);border:1px solid var(--slm-line);border-radius:999px;padding:3px}\n.slm-mode{padding:6px 16px;border-radius:999px;font-weight:700;font-size:13px;color:var(--slm-muted)}\n.slm-mode.on{background:var(--slm-accent);color:var(--slm-accent-ink)}\n.slm-live{display:inline-flex;align-items:center;gap:6px;font-size:11px;letter-spacing:.12em;font-weight:800;color:var(--slm-muted)}\n.slm-live-dot{width:8px;height:8px;border-radius:50%;background:#8b94ac}\n.slm.live .slm-live-dot{background:#22a06b;box-shadow:0 0 0 0 rgba(34,160,107,.55);animation:slm-pulse 2s infinite}\n@keyframes slm-pulse{0%{box-shadow:0 0 0 0 rgba(34,160,107,.5)}70%{box-shadow:0 0 0 7px rgba(34,160,107,0)}100%{box-shadow:0 0 0 0 rgba(34,160,107,0)}}\n.slm-kpis{grid-column:1/-1;display:grid;grid-template-columns:repeat(8,minmax(0,1fr));width:100%;padding-top:10px;\n border-top:1px solid var(--slm-line)}\n.slm-kpi{position:relative;display:flex;min-width:0;flex-direction:column;align-items:center;padding:0 5px;line-height:1.15;text-align:center}\n.slm-kpi b{display:flex;min-width:0;align-items:baseline;justify-content:center;font-size:17px;font-weight:800;\n font-variant-numeric:tabular-nums;white-space:nowrap}\n.slm-kpi span{font-size:9.5px;letter-spacing:.1em;text-transform:uppercase;color:var(--slm-muted);font-weight:700}\n.slm-kpi .dot{display:inline-block;width:8px;height:8px;border-radius:50%;margin-right:5px;vertical-align:baseline}\n.slm-kpi.changed b{animation:slm-kpi-bump .58s cubic-bezier(.2,.8,.2,1)}\n.slm-kpidelta{position:absolute;right:4px;top:-12px;padding:2px 5px;border-radius:999px;background:rgba(34,160,107,.17);\n color:#5bd39b!important;font-size:9px!important;letter-spacing:0!important;text-transform:none!important;white-space:nowrap;\n animation:slm-kpi-delta 1.45s ease-out both;pointer-events:none}\n.slm-kpidelta.down{background:rgba(244,183,64,.14);color:#f7ca6b!important}\n@keyframes slm-kpi-bump{0%,100%{transform:none}35%{transform:translateY(-2px) scale(1.08);text-shadow:0 0 18px rgba(255,255,255,.24)}}\n@keyframes slm-kpi-delta{0%{opacity:0;transform:translateY(5px)}18%,72%{opacity:1;transform:none}100%{opacity:0;transform:translateY(-5px)}}\n.slm-barbtn{padding:7px 13px;border-radius:9px;border:1px solid var(--slm-line);color:var(--slm-text);font-weight:700;font-size:12.5px}\n.slm-barbtn:hover{border-color:var(--slm-muted)}\n.slm-barbtn.follow.on{background:rgba(34,160,107,.13);border-color:#22a06b;color:#5bd39b}\n\n/* body */\n.slm-body{display:flex;flex:1;min-height:0}\n.slm-map{position:relative;flex:1;min-width:0}\n.slm-map-host{position:absolute;inset:0}\n.slm-hud{position:absolute;left:12px;bottom:12px;display:flex;gap:8px}\n.slm-hud-chip{padding:6px 11px;border-radius:999px;font-size:12px;font-weight:700;background:var(--slm-surface);\n border:1px solid var(--slm-line);color:var(--slm-text)}\n.slm-zoomhint{position:absolute;left:50%;top:14px;transform:translateX(-50%);padding:6px 13px;border-radius:999px;\n background:rgba(0,0,0,.55);color:#fff;font-size:12px;font-weight:700;pointer-events:none;opacity:0;transition:opacity .2s}\n.slm-zoomhint.on{opacity:1}\n.slm-liveevent{position:absolute;left:50%;top:14px;z-index:4;display:flex;align-items:center;gap:8px;max-width:min(560px,calc(100% - 32px));\n padding:8px 12px;border:1px solid var(--slm-line);border-radius:999px;background:color-mix(in srgb,var(--slm-surface) 92%,transparent);\n box-shadow:0 10px 34px rgba(0,0,0,.32);opacity:0;transform:translate(-50%,-8px);pointer-events:none;\n transition:opacity .18s ease,transform .24s ease;backdrop-filter:blur(10px)}\n.slm-liveevent.on{opacity:1;transform:translate(-50%,0)}\n.slm.block-mode .slm-liveevent{top:52px}\n.slm-liveeventdot{width:8px;height:8px;border-radius:50%;flex:none}.slm-liveeventcopy{min-width:0;overflow:hidden;text-overflow:ellipsis;\n white-space:nowrap;font-size:12px;font-weight:800}.slm-liveeventhint{color:var(--slm-muted);font-size:10px;white-space:nowrap}\n.slm-rail{width:320px;flex:none;border-left:1px solid var(--slm-line);display:flex;flex-direction:column;min-height:0}\n.slm-railscroll{flex:1;overflow-y:auto;padding:16px}\n.slm-eyebrow{font-size:10px;letter-spacing:.14em;text-transform:uppercase;color:var(--slm-muted);font-weight:800;margin-bottom:6px}\n.slm-hint{font-size:12.5px;color:var(--slm-muted);line-height:1.5;margin-bottom:14px}\n\n/* legend rows */\n.slm-legend{display:flex;flex-direction:column;gap:2px;margin-bottom:16px}\n.slm-legrow{display:flex;align-items:center;gap:9px;padding:7px 2px;border-bottom:1px solid var(--slm-line)}\n.slm-legdot{width:10px;height:10px;border-radius:50%;flex:none}\n.slm-leglabel{flex:1;font-size:13px;font-weight:600}\n.slm-legcount{font-size:13px;font-weight:800;font-variant-numeric:tabular-nums}\n\n/* activity feed */\n.slm-feed{display:flex;flex-direction:column;gap:0}\n.slm-feedrow{display:flex!important;width:100%;align-items:center;gap:9px;padding:8px 2px!important;border-bottom:1px solid var(--slm-line)!important;\n border-radius:6px;font-size:12.5px;text-align:left!important;animation:slm-in .35s ease}\n.slm-feedrow:hover{background:rgba(255,255,255,.035)!important}\n@keyframes slm-in{from{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:none}}\n.slm-feeddot{width:8px;height:8px;border-radius:50%;flex:none}\n.slm-feedtext{flex:1;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n.slm-feedtext b{font-weight:800}\n.slm-feedsection{display:block;overflow:hidden;text-overflow:ellipsis;color:var(--slm-muted);font-size:10px;font-weight:750}\n.slm-feedmeta{display:flex;flex:none;flex-direction:column;align-items:flex-end;gap:1px}.slm-feedtime{font-size:10px;color:var(--slm-muted);font-variant-numeric:tabular-nums}\n.slm-feedlocate{font-size:9.5px;color:var(--slm-accent);font-weight:800}\n.slm-empty{font-size:12.5px;color:var(--slm-muted);padding:12px 0}\n\n/* block toolbar */\n.slm-selbar{display:flex;align-items:baseline;gap:8px;margin-bottom:10px}\n.slm-selnum{font-size:26px;font-weight:800;font-variant-numeric:tabular-nums}\n.slm-sellabel{font-size:12px;color:var(--slm-muted);font-weight:600}\n.slm-row{display:flex;gap:8px;flex-wrap:wrap;margin-bottom:10px}\n.slm-btn{flex:1;min-width:120px;padding:10px 14px;border-radius:10px;background:var(--slm-accent);color:var(--slm-accent-ink);\n font-weight:800;font-size:13px;text-align:center}\n.slm-btn:disabled{opacity:.45;cursor:not-allowed}\n.slm-btn.ghost{background:var(--slm-surface);border:1px solid var(--slm-line);color:var(--slm-text)}\n.slm-btn.danger{background:#c0392b;color:#fff}\n.slm-chiprow{display:flex;gap:6px;flex-wrap:wrap;margin-bottom:6px}\n.slm-chip{padding:6px 11px;border-radius:999px;border:1px solid var(--slm-line);background:var(--slm-surface);\n font-size:12px;font-weight:700;color:var(--slm-text);display:inline-flex;align-items:center;gap:6px}\n.slm-chip:hover{border-color:var(--slm-muted)}\n.slm-chip .dot{width:8px;height:8px;border-radius:50%}\n.slm-chip .slm-chipcount{min-width:18px;padding:1px 5px;border-radius:999px;background:rgba(255,255,255,.07);\n color:var(--slm-muted);font-size:10px;font-variant-numeric:tabular-nums;text-align:center}\n.slm-chip .slm-chipcheck{display:none;font-size:11px;line-height:1}\n.slm-chip.on{border-color:var(--slm-accent);background:color-mix(in srgb,var(--slm-accent) 20%,var(--slm-surface));\n box-shadow:0 0 0 1px color-mix(in srgb,var(--slm-accent) 45%,transparent)}\n.slm-chip.on .slm-chipcount{background:var(--slm-accent);color:var(--slm-accent-ink)}\n.slm-chip.on .slm-chipcheck{display:inline}\n.slm-chip.partial{border-style:dashed;border-color:var(--slm-accent)}\n.slm-chip:disabled{opacity:.42;cursor:not-allowed}\n.slm-selecthelp{margin:-1px 0 9px;color:var(--slm-muted);font-size:11px;line-height:1.4}\n.slm-field{margin:14px 0}\n.slm-field label{display:block;font-size:11px;font-weight:700;color:var(--slm-muted);margin-bottom:5px}\n.slm-input,.slm-select{width:100%;padding:8px 10px;border-radius:9px;border:1px solid var(--slm-line);\n background:var(--slm-surface);color:var(--slm-text)}\n.slm-note{font-size:11.5px;color:var(--slm-muted);margin-top:5px}\n.slm-blocked{margin-top:17px;padding-top:15px;border-top:1px solid var(--slm-line)}\n.slm-blockedhead{display:flex;align-items:baseline;justify-content:space-between;gap:10px;margin-bottom:8px}\n.slm-blockedhead .slm-eyebrow{margin-bottom:0}.slm-blockedtotal{font-size:11px;color:var(--slm-muted)}\n.slm-blockedtotal b{color:var(--slm-text);font-variant-numeric:tabular-nums}\n.slm-blockedtools{display:grid;grid-template-columns:minmax(0,1fr);gap:7px}\n.slm-blockedsummary{display:flex;align-items:center;justify-content:space-between;gap:8px;margin:9px 0 6px;\n color:var(--slm-muted);font-size:10.5px}\n.slm-linkbtn{font-size:11px!important;font-weight:800!important;color:var(--slm-accent)!important;text-align:right}\n.slm-linkbtn:disabled{opacity:.45;cursor:not-allowed}\n.slm-blockedlist{max-height:246px;overflow:auto;border:1px solid var(--slm-line);border-radius:10px;background:var(--slm-surface)}\n.slm-blockeditem{display:grid!important;grid-template-columns:18px minmax(0,1fr);width:100%;gap:8px;padding:8px 9px!important;\n border-bottom:1px solid var(--slm-line)!important;text-align:left!important}\n.slm-blockeditem:last-child{border-bottom:0!important}.slm-blockeditem:hover{background:rgba(255,255,255,.035)!important}\n.slm-blockeditem.on{background:color-mix(in srgb,var(--slm-accent) 13%,var(--slm-surface))!important}\n.slm-blockedcheck{display:flex;align-items:center;justify-content:center;width:16px;height:16px;margin-top:1px;border-radius:4px;\n border:1px solid var(--slm-muted);color:transparent;font-size:10px;font-weight:900}\n.slm-blockeditem.on .slm-blockedcheck{border-color:var(--slm-accent);background:var(--slm-accent);color:var(--slm-accent-ink)}\n.slm-blockedcopy{min-width:0}.slm-blockedlabel{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;\n font-size:12px;font-weight:800}.slm-blockedmeta{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;\n margin-top:2px;color:var(--slm-muted);font-size:10px}\n.slm-blockedmore{width:100%;padding:9px!important;color:var(--slm-accent)!important;font-size:11px!important;font-weight:800!important}\n.slm-blockedempty{padding:12px;color:var(--slm-muted);font-size:11.5px;line-height:1.45}\n.slm-allnote{margin-top:-4px;margin-bottom:10px}\n\n/* toast */\n.slm-toast{position:absolute;left:50%;bottom:16px;transform:translateX(-50%);padding:10px 16px;border-radius:10px;\n font-size:13px;font-weight:700;box-shadow:0 8px 24px rgba(0,0,0,.28);opacity:0;pointer-events:none;transition:opacity .2s;\n background:var(--slm-surface);color:var(--slm-text);border:1px solid var(--slm-line);z-index:5}\n.slm-toast.on{opacity:1}\n.slm-toast.err{background:#c0392b;color:#fff;border-color:#c0392b}\n.slm-toast.ok{background:#1f7a4d;color:#fff;border-color:#1f7a4d}\n\n/* control-room actions + insights */\n.slm-bar-actions{display:flex;align-items:center;justify-self:end;gap:7px}\n.slm-barbtn.on{background:rgba(244,183,64,.13);border-color:#f4b740;color:#f7ca6b}\n.slm-sectionlist{display:flex;flex-direction:column;gap:8px;margin-top:4px}\n.slm-sectionlist + .slm-eyebrow{margin-top:18px}\n.slm-sectionrow{width:100%;padding:10px!important;border:1px solid var(--slm-line)!important;border-radius:10px;background:var(--slm-surface)!important;text-align:left!important;transition:border-color .15s ease,transform .15s ease}\n.slm-sectionrow:hover{border-color:var(--slm-muted)!important;transform:translateY(-1px)}\n.slm-sectiontop,.slm-sectionmeta{display:flex;align-items:center;justify-content:space-between;gap:10px}\n.slm-sectiontop{font-size:12.5px;font-weight:800}.slm-sectionmeta{margin-top:5px;color:var(--slm-muted);font-size:11px}\n.slm-sectionmeta>span:first-child{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n.slm-trend{font-size:10px;text-transform:uppercase;letter-spacing:.08em}.slm-trend.rising{color:#22a06b}.slm-trend.cooling{color:#f4b740}\n.slm-sectionlocate{color:var(--slm-accent);font-size:9.5px;font-weight:800}\n.slm-health{display:grid;grid-template-columns:1fr 1fr;gap:8px;margin-bottom:16px}\n.slm-healthitem{padding:10px;border:1px solid var(--slm-line);border-radius:10px;background:var(--slm-surface)}\n.slm-healthitem b{display:block;font-size:17px;font-variant-numeric:tabular-nums}.slm-healthitem span{display:block;margin-top:2px;color:var(--slm-muted);font-size:10px;text-transform:uppercase;letter-spacing:.08em}\n.slm-sectionhead{display:flex;align-items:flex-start;justify-content:space-between;gap:10px;margin-top:18px}\n.slm-windows{display:flex;gap:3px;padding:2px;border:1px solid var(--slm-line);border-radius:8px;background:var(--slm-surface)}\n.slm-window{padding:4px 6px;border-radius:6px;font-size:10px;font-weight:800;color:var(--slm-muted)}.slm-window.on{background:var(--slm-accent);color:var(--slm-accent-ink)}\n.slm-momentumhelp{margin:10px 0 14px;padding:10px;border:1px solid rgba(244,183,64,.28);border-radius:10px;background:rgba(244,183,64,.07)}\n.slm-momentumhelp[hidden]{display:none}.slm-momentumscale{display:flex;align-items:center;gap:7px;color:var(--slm-muted);font-size:10px;font-weight:750;text-transform:uppercase;letter-spacing:.07em}\n.slm-momentumgradient{height:6px;min-width:64px;flex:1;border-radius:999px;background:linear-gradient(90deg,#f4b740,#ef4444)}\n.slm-momentumcopy{margin-top:7px;color:var(--slm-muted);font-size:11px;line-height:1.45}\n/* sections: availability windows */\n.slm-availlist{display:flex;flex-direction:column;gap:8px;margin:2px 0 12px}\n.slm-availrow{padding:10px;border:1px solid var(--slm-line);border-radius:10px;background:var(--slm-surface);transition:border-color .15s ease,opacity .15s ease}\n.slm-availrow.zone{background:color-mix(in srgb,var(--slm-surface) 82%,#000)}\n.slm-availrow.hidden{opacity:.62}.slm-availrow.closed{opacity:.82}\n.slm-availhead{display:flex;align-items:center;gap:8px}\n.slm-availlabel{display:flex;align-items:center;gap:5px;flex:1;min-width:0;font-size:12.5px;font-weight:800;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n.slm-availcaret{flex:none;color:var(--slm-muted);font-size:10px}\n.slm-availcount{flex:none;font-size:11px;font-weight:700;color:var(--slm-muted);font-variant-numeric:tabular-nums}\n.slm-availbadge{flex:none;font-size:9px;font-weight:800;letter-spacing:.04em;text-transform:uppercase;padding:2px 6px;border-radius:999px}\n.slm-availbadge.hidden{background:rgba(139,148,172,.18);color:#c2c9d8}\n.slm-availbadge.closed{background:rgba(244,183,64,.16);color:#f7ca6b}\n.slm-availselwrap{position:relative;flex:none;display:inline-flex}\n.slm-availmode{width:auto;max-width:190px;padding:6px 8px;font-size:11.5px;font-weight:700;cursor:pointer}\n.slm-availmode.on{border-color:var(--slm-accent);color:var(--slm-text)}\n.slm-availmode:disabled{opacity:.55;cursor:progress}\n.slm-availfollows{flex:none;padding:5px 10px;border:1px solid var(--slm-line);border-radius:7px;background:var(--slm-surface);color:var(--slm-muted);font-size:11px;font-weight:600;white-space:nowrap}\n.slm-availdetail{display:flex;align-items:center;gap:8px;margin-top:9px}\n.slm-availdetail .slm-input{flex:1}\n.slm-availpct{max-width:74px;flex:none!important}\n.slm-availpctlabel{font-size:11px;color:var(--slm-muted);font-weight:600;white-space:nowrap}\n.slm-availsummary{display:flex;align-items:center;gap:8px;padding:10px 12px;border:1px solid var(--slm-line);border-radius:9px;color:var(--slm-muted);font-size:12.5px}\n.slm-availdot{width:9px;height:9px;border-radius:50%;flex:none;background:#22a06b}.slm-availdot.warn{background:#f4b740}\n.slm-availcallout{display:flex;align-items:flex-start;gap:8px;margin-top:10px;padding:10px 12px;border:1px solid rgba(244,183,64,.45);border-radius:9px;background:rgba(244,183,64,.1)}\n.slm-availstar{flex:none;margin-top:1px;color:#f4b740;font-size:13px;line-height:1}\n.slm-availcallout p{font-size:11.5px;line-height:1.55;color:#f4d58a}.slm-availcallout b{color:#ffe4a3;font-weight:800}\n.slm-inspect-card{padding:16px;border:1px solid var(--slm-line);border-radius:12px;background:var(--slm-surface)}\n.slm-inspect-label{font-size:24px;font-weight:850;letter-spacing:-.02em;line-height:1.1}\n.slm-inspect-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:16px 20px;margin-top:18px}\n.slm-inspect-grid>div{min-width:0}.slm-inspect-grid span{display:block;color:var(--slm-muted);font-size:10px;\n text-transform:uppercase;letter-spacing:.08em}.slm-inspect-grid b{display:block;margin-top:4px;font-size:13px;line-height:1.35;overflow-wrap:anywhere}\n.slm:fullscreen{border-radius:0;min-height:100vh;background:var(--slm-bg)}\n.slm:fullscreen .slm-bar{padding:14px 22px}.slm:fullscreen .slm-kpi b{font-size:21px}.slm:fullscreen .slm-rail{width:360px}\n\n.slm.compact .slm-rail{width:100%;border-left:0;border-top:1px solid var(--slm-line);height:44%}\n.slm.compact .slm-body{flex-direction:column}\n.slm.compact .slm-bar{grid-template-columns:minmax(0,1fr) auto;gap:8px;padding:8px}\n.slm.compact .slm-modes{min-width:0}.slm.compact .slm-mode{padding-inline:11px}\n.slm.compact .slm-live{justify-self:end}.slm.compact .slm-bar-actions{grid-column:1/-1;justify-self:stretch}\n.slm.compact .slm-barbtn{flex:1;padding:6px 9px}.slm.compact .slm-kpis{grid-template-columns:repeat(4,minmax(0,1fr));gap:8px}\n.slm.compact .slm-kpi[data-kpi=\"buyers\"],.slm.compact .slm-kpi[data-kpi=\"active-holds\"],\n.slm.compact .slm-kpi[data-kpi=\"sold-pct\"],.slm.compact .slm-kpi[data-kpi=\"gross-sales\"]{display:none}\n@media (prefers-reduced-motion:reduce){\n .slm.live .slm-live-dot,.slm-feedrow,.slm-kpi.changed b,.slm-kpidelta{animation:none!important}\n .slm-liveevent,.slm-sectionrow{transition:none!important}\n}\n`;\n\nfunction injectStyle(): void {\n if (typeof document === 'undefined' || 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/** Resolve chrome tokens from a chart theme (dark war-room defaults). */\nfunction themeVars(theme: ChartTheme | undefined): Record<string, string> {\n const t = theme ?? {};\n return {\n '--slm-bg': t.background ?? '#0e1017',\n '--slm-surface': '#181b24',\n '--slm-text': '#eef1f7',\n '--slm-muted': '#8b93a7',\n '--slm-line': 'rgba(255,255,255,.09)',\n '--slm-accent': t.accent ?? '#6e7bff',\n '--slm-accent-ink': t.accentInk ?? '#ffffff',\n '--slm-font': \"-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif\",\n '--slm-radius': '14px',\n };\n}\n\nfunction relTime(at: number, now: number): string {\n const s = Math.max(0, Math.round((now - at) / 1000));\n if (s < 5) return 'just now';\n if (s < 60) return `${s}s ago`;\n const m = Math.round(s / 60);\n if (m < 60) return `${m}m ago`;\n return `${Math.round(m / 60)}h ago`;\n}\n\nfunction fmtMoney(amount: number, currency: string): string {\n try {\n return new Intl.NumberFormat(undefined, { style: 'currency', currency, maximumFractionDigits: 0 }).format(amount);\n } catch {\n return `${currency} ${Math.round(amount).toLocaleString()}`;\n }\n}\n\nfunction esc(value: unknown): string {\n return String(value ?? '')\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\"/g, '"')\n .replace(/'/g, ''');\n}\n\nexport class SeatManager {\n private readonly opts: SeatManagerOptions;\n private readonly api: ManageApi;\n private readonly key: string;\n private readonly keepLive: boolean;\n\n private host: HTMLElement;\n private root!: HTMLDivElement;\n private mapHost!: HTMLDivElement;\n private els: Record<string, HTMLElement> = {};\n\n private renderer: SeatmapRenderer | null = null;\n private doc: ChartDoc | null = null;\n private mode: SeatManagerMode;\n\n // label ⇄ id + status truth (backend speaks labels, engine speaks ids).\n private labelToId = new Map<string, string>();\n private labelToSeat = new Map<string, ExpandedSeat>();\n private allIds: string[] = [];\n private status = new Map<string, DoStatus>();\n private currency = 'USD';\n private authoritativeGrossRevenue = 0;\n private revenueStatus: SeatManagerTallies['revenueStatus'] = 'loading';\n private revenueRequest = 0;\n private revenueRefreshTimer: ReturnType<typeof setTimeout> | null = null;\n private controlRoomSnapshot: ControlRoomSnapshot | null = null;\n private trendWindowMinutes = 15;\n private heatEnabled = false;\n private followLive: boolean;\n private lastKpiValues = new Map<string, number>();\n private activeKpiDeltas = new Map<string, { text: string; down: boolean }>();\n\n // realtime socket\n private ws: WebSocket | null = null;\n private reconnectTimer: ReturnType<typeof setTimeout> | null = null;\n private attempt = 0;\n private closed = false;\n private ready = false;\n\n private feed: SeatManagerActivity[] = [];\n private feedTimer: ReturnType<typeof setInterval> | null = null;\n private toastTimer: ReturnType<typeof setTimeout> | null = null;\n private liveEventTimer: ReturnType<typeof setTimeout> | null = null;\n private kpiCleanupTimer: ReturnType<typeof setTimeout> | null = null;\n private followLiveTimer: ReturnType<typeof setTimeout> | null = null;\n private followSeatTimer: ReturnType<typeof setTimeout> | null = null;\n private releaseAt: number | null = null;\n private layoutObserver: ResizeObserver | null = null;\n private tokenExpiresAt: number | null = null;\n private tokenRefreshTimer: ReturnType<typeof setTimeout> | null = null;\n private tokenRefreshInFlight = false;\n private sectionByObject = new Map<string, string>();\n private sectionLabelById = new Map<string, string>();\n private sectionsBase: ReturnType<typeof computeSections> | null = null;\n // Sections mode (availability windows): organizer rules + the live effective\n // hidden/closed sets from the snapshot + WS (a timed/threshold rule fires DO-side).\n private availabilityRules: Record<string, AvailabilityRule> = {};\n private effectiveHidden = new Set<string>();\n private effectiveClosed = new Set<string>();\n private availabilitySaving = false;\n private lastSyncedAt: number | null = null;\n private blockedQuery = '';\n private blockedSection = '';\n private blockedResultLimit = 100;\n private unblockAllConfirmTimer: ReturnType<typeof setTimeout> | null = null;\n\n private readonly onFullscreenChange = (): void => {\n this.paintFullscreenButton();\n this.updateContainerLayout();\n this.renderer?.forceDraw();\n };\n\n private readonly onKeyDown = (event: KeyboardEvent): void => {\n if (event.metaKey || event.ctrlKey || event.altKey) return;\n const target = event.target as HTMLElement | null;\n if (target?.matches('input,select,textarea,[contenteditable=\"true\"]')) return;\n const key = event.key.toLowerCase();\n if (key === 'm') this.setMode('view');\n else if (key === 'i') this.setMode('inspect');\n else if (key === 'b') this.setMode('block');\n else if (key === 's') this.setMode('sections');\n else if (key === 'f') this.toggleFullscreen();\n else return;\n event.preventDefault();\n };\n\n private readonly onRailClick = (event: Event): void => {\n const target = event.target as HTMLElement | null;\n const sectionButton = target?.closest<HTMLElement>('[data-section-focus]');\n if (sectionButton?.dataset.sectionFocus) {\n this.locateSection(sectionButton.dataset.sectionFocus);\n return;\n }\n const feedButton = target?.closest<HTMLElement>('[data-feed-id]');\n if (feedButton?.dataset.feedId) this.locateActivity(feedButton.dataset.feedId);\n };\n\n constructor(options: SeatManagerOptions) {\n this.opts = options;\n this.key = options.eventKey;\n this.mode = options.mode ?? 'view';\n this.keepLive = options.keepLiveWhileHidden ?? true;\n this.followLive = options.followLive ?? false;\n this.currency = options.currency ?? 'USD';\n this.tokenExpiresAt = options.tokenExpiresAt ?? null;\n this.api = new ManageApi(options.apiBase ?? DEFAULT_API_BASE, options.token);\n this.host = resolveContainer(options.container);\n }\n\n /** Build the DOM, load the chart, subscribe to realtime, mount the board. */\n async render(): Promise<this> {\n injectStyle();\n this.buildChrome();\n try {\n const res = await this.api.chart(this.key);\n this.doc = res.doc;\n this.currency = res.event.currency ?? this.opts.currency ?? this.currency;\n const seats = expandChart(res.doc);\n for (const s of seats) {\n this.labelToId.set(s.label, s.id);\n this.labelToSeat.set(s.label, s);\n this.allIds.push(s.id);\n }\n this.buildRenderer();\n this.buildSectionOptions();\n const [, controlRoom] = await Promise.all([\n this.resnapshot(),\n this.refreshControlRoom().catch((err) => this.opts.onError?.(err)),\n this.refreshAvailability(),\n ]);\n // Restore recent activity through the view-safe control-room projection.\n // Older workers lack this field, so privileged/secret-key hosts retain the\n // legacy best-effort audit-log fallback during rolling upgrades.\n if (controlRoom?.activity) this.seedFeed(controlRoom.activity);\n else this.api.log(this.key, { limit: 24 }).then((page) => this.seedFeed(page.entries)).catch(() => {});\n this.connect();\n this.startFeedClock();\n this.ready = true;\n this.setMode(this.mode); // paint the right rail\n this.scheduleTokenRefresh();\n this.opts.onReady?.();\n } catch (err) {\n this.fail(err);\n }\n return this;\n }\n\n // ---- public API -----------------------------------------------------------\n\n setMode(mode: SeatManagerMode): void {\n const changed = mode !== this.mode;\n this.mode = mode;\n if (!this.renderer && this.doc) this.buildRenderer();\n else this.updateRendererInteraction();\n if (changed) this.renderer?.clearSelection();\n this.paintModeTabs();\n this.paintRail();\n this.applySectionCanvasTreatment();\n if (changed) this.opts.onModeChange?.(mode);\n }\n\n /** Toggle the normalized sales-velocity outline overlay without changing seat colors. */\n setHeatOverlay(enabled: boolean): void {\n this.heatEnabled = enabled;\n this.applyHeatOverlay();\n this.paintHeatButton();\n }\n\n /** Toggle opt-in camera following for new buyer hold/book events. */\n setFollowLive(enabled: boolean): void {\n const changed = this.followLive !== enabled;\n this.followLive = enabled;\n if (!enabled) {\n if (this.followLiveTimer) clearTimeout(this.followLiveTimer);\n if (this.followSeatTimer) clearTimeout(this.followSeatTimer);\n this.followLiveTimer = null;\n this.followSeatTimer = null;\n }\n this.paintFollowLiveButton();\n if (changed) this.opts.onFollowLiveChange?.(enabled);\n }\n\n /** Change the current-vs-previous sales window and refresh the private projection. */\n setTrendWindow(windowMinutes: number): Promise<ControlRoomSnapshot> {\n const normalized = Number.isFinite(windowMinutes) ? Math.floor(windowMinutes) : 15;\n this.trendWindowMinutes = Math.max(5, Math.min(60, normalized));\n this.paintTrendWindow();\n return this.refreshControlRoom();\n }\n\n async enterFullscreen(): Promise<void> {\n if (!this.root?.requestFullscreen || this.isFullscreen()) return;\n await this.root.requestFullscreen();\n this.root.focus({ preventScroll: true });\n }\n\n async exitFullscreen(): Promise<void> {\n if (typeof document === 'undefined' || !this.isFullscreen()) return;\n await document.exitFullscreen();\n }\n\n isFullscreen(): boolean {\n return typeof document !== 'undefined' && document.fullscreenElement === this.root;\n }\n\n private toggleFullscreen(): void {\n const request = this.isFullscreen() ? this.exitFullscreen() : this.enterFullscreen();\n void request.catch((err) => this.opts.onError?.(err));\n }\n\n /** Rotate the delegated credential without rebuilding DOM, canvas or socket. */\n setToken(token: string, expiresAt?: number): void {\n this.api.setToken(token);\n this.tokenExpiresAt = expiresAt ?? null;\n this.scheduleTokenRefresh();\n }\n\n private scheduleTokenRefresh(): void {\n if (this.tokenRefreshTimer) clearTimeout(this.tokenRefreshTimer);\n this.tokenRefreshTimer = null;\n const refresh = this.opts.onTokenRefresh;\n const expiresAt = this.tokenExpiresAt;\n if (this.closed || !refresh || !expiresAt || !Number.isFinite(expiresAt)) return;\n const remaining = expiresAt - Date.now();\n const lead = Math.min(120_000, Math.max(30_000, remaining * 0.2));\n const delay = Math.max(0, remaining - lead);\n this.tokenRefreshTimer = setTimeout(() => {\n this.tokenRefreshTimer = null;\n void this.rotateToken();\n }, delay);\n }\n\n private async rotateToken(): Promise<void> {\n if (this.closed || this.tokenRefreshInFlight || !this.opts.onTokenRefresh) return;\n this.tokenRefreshInFlight = true;\n try {\n const next = await this.opts.onTokenRefresh();\n if (!next?.token || !Number.isFinite(next.expiresAt)) throw new Error('invalid_token_refresh_result');\n this.setToken(next.token, next.expiresAt);\n } catch (err) {\n this.opts.onError?.(err);\n if (!this.closed) {\n this.tokenRefreshTimer = setTimeout(() => {\n this.tokenRefreshTimer = null;\n void this.rotateToken();\n }, 30_000);\n }\n } finally {\n this.tokenRefreshInFlight = false;\n }\n }\n\n /** Bulk block the given labels (or the current selection when omitted). */\n async block(labels?: string[], opts: { releaseAt?: number; reason?: string } = {}): Promise<void> {\n const targets = (labels ?? this.selectionLabels()).filter((l) => this.status.get(l) === 'free');\n if (!targets.length) return;\n const releaseAt = opts.releaseAt ?? this.releaseAt ?? undefined;\n // optimistic\n this.setSeatsLocal(targets, 'blocked');\n try {\n await this.api.block(this.key, targets, { ...opts, releaseAt });\n this.clearSelection();\n this.done('block', targets, releaseAt\n ? `Blocked ${targets.length} — auto-release ${new Date(releaseAt).toLocaleString()}.`\n : `Blocked ${targets.length} seat${targets.length === 1 ? '' : 's'}.`);\n } catch (err) {\n this.setSeatsLocal(targets, 'free'); // revert\n this.toastErr(err instanceof ManageApiError && err.status === 409\n ? 'Some seats were just taken. Try again.'\n : \"Couldn't block those seats.\");\n this.opts.onError?.(err);\n }\n }\n\n async unblock(labels?: string[]): Promise<void> {\n const targets = (labels ?? this.selectionLabels()).filter((l) => this.status.get(l) === 'blocked');\n if (!targets.length) return;\n this.setSeatsLocal(targets, 'free');\n try {\n await this.api.unblock(this.key, targets);\n this.clearSelection();\n this.done('unblock', targets, `Unblocked ${targets.length} seat${targets.length === 1 ? '' : 's'}.`);\n } catch (err) {\n this.setSeatsLocal(targets, 'blocked');\n this.toastErr(\"Couldn't unblock those seats.\");\n this.opts.onError?.(err);\n }\n }\n\n async unblockAll(): Promise<void> {\n const blocked = [...this.status.entries()].filter(([, s]) => s === 'blocked').map(([l]) => l);\n if (!blocked.length) return;\n this.setSeatsLocal(blocked, 'free');\n try {\n const res = await this.api.unblockAll(this.key);\n this.clearSelection();\n this.done('unblockAll', blocked, `Unblocked ${res.freed} seat${res.freed === 1 ? '' : 's'}.`);\n } catch (err) {\n await this.resnapshot();\n this.toastErr(\"Couldn't mark everything for sale.\");\n this.opts.onError?.(err);\n }\n }\n\n /** Cancel bookings (BOOKED → free), guarded by the original booking ref. */\n async cancelBooking(labels: string[], bookingRef: string): Promise<void> {\n const targets = labels.filter((l) => this.status.get(l) === 'booked');\n if (!targets.length || !bookingRef) return;\n this.setSeatsLocal(targets, 'free');\n try {\n await this.api.unbook(this.key, targets, bookingRef);\n this.clearSelection();\n this.done('cancelBooking', targets, `Cancelled ${targets.length} booking${targets.length === 1 ? '' : 's'}.`);\n } catch (err) {\n this.setSeatsLocal(targets, 'booked');\n this.toastErr(\"Couldn't cancel that booking. Check the reference.\");\n this.opts.onError?.(err);\n }\n }\n\n selectAll(): ExpandedSeat[] {\n const seats = this.renderer?.selectAllSelectable() ?? [];\n this.syncSelection();\n return seats;\n }\n\n selectSection(sectionId: string): ExpandedSeat[] {\n if (!this.renderer) return [];\n const seats = this.renderer.getSelectableInSection(sectionId);\n this.renderer.selectByLabels(seats.map((s) => s.label));\n this.syncSelection();\n return this.renderer.getSelection();\n }\n\n selectByLabels(labels: string[]): ExpandedSeat[] {\n const seats = this.renderer?.selectByLabels(labels) ?? [];\n this.syncSelection();\n return seats;\n }\n\n clearSelection(): void {\n this.renderer?.clearSelection();\n this.syncSelection();\n }\n\n getSelection(): ExpandedSeat[] {\n return this.renderer?.getSelection() ?? [];\n }\n\n getReport(): Promise<ReportResult> {\n return this.api.report(this.key).then((report) => {\n this.applyReportRevenue(report);\n return report;\n });\n }\n\n getControlRoomSnapshot(windowMinutes = this.trendWindowMinutes): Promise<ControlRoomSnapshot> {\n return this.setTrendWindow(windowMinutes);\n }\n\n getLog(opts: { limit?: number; before?: number } = {}): Promise<{ entries: LogEntry[]; nextBefore: number | null }> {\n return this.api.log(this.key, opts);\n }\n\n async setHoldTtl(ms: number | null): Promise<void> {\n try {\n await this.api.setHoldTtl(this.key, ms);\n this.done('setHoldTtl', [], ms ? `Checkout window set to ${Math.round(ms / 60000)} min.` : 'Checkout window reset.');\n } catch (err) {\n this.toastErr(\"Couldn't update the checkout window.\");\n this.opts.onError?.(err);\n }\n }\n\n /** M2 — box-office booking from free seats. Stubbed (route is session-only today). */\n boxBook(_labels: string[], _bookingRef: string): Promise<void> {\n this.toastErr('Box office ships in a later milestone.');\n return Promise.resolve();\n }\n\n zoomToFit(): void {\n this.renderer?.clearSectionFocus();\n this.renderer?.zoomToFit();\n }\n\n destroy(): void {\n this.closed = true;\n if (this.reconnectTimer) clearTimeout(this.reconnectTimer);\n if (this.feedTimer) clearInterval(this.feedTimer);\n if (this.toastTimer) clearTimeout(this.toastTimer);\n if (this.liveEventTimer) clearTimeout(this.liveEventTimer);\n if (this.kpiCleanupTimer) clearTimeout(this.kpiCleanupTimer);\n if (this.followLiveTimer) clearTimeout(this.followLiveTimer);\n if (this.followSeatTimer) clearTimeout(this.followSeatTimer);\n if (this.unblockAllConfirmTimer) clearTimeout(this.unblockAllConfirmTimer);\n if (this.revenueRefreshTimer) clearTimeout(this.revenueRefreshTimer);\n if (this.tokenRefreshTimer) clearTimeout(this.tokenRefreshTimer);\n this.layoutObserver?.disconnect();\n this.layoutObserver = null;\n this.root?.removeEventListener('keydown', this.onKeyDown);\n this.els.rail?.removeEventListener('click', this.onRailClick);\n if (typeof document !== 'undefined') document.removeEventListener('fullscreenchange', this.onFullscreenChange);\n if (this.ws) { try { this.ws.close(); } catch { /* ignore */ } this.ws = null; }\n this.renderer?.destroy();\n this.renderer = null;\n if (this.root && this.root.parentNode === this.host) this.host.removeChild(this.root);\n }\n\n // ---- renderer lifecycle ---------------------------------------------------\n\n private buildRenderer(): void {\n if (!this.doc) return;\n const block = this.mode === 'block';\n const inspect = this.mode === 'inspect';\n this.renderer = new SeatmapRenderer(this.mapHost, {\n manageMode: true,\n marqueeSelect: block,\n maxSelection: 1_000_000,\n selectableStatuses: block\n ? ['free', 'not_for_sale']\n : inspect ? ['free', 'held', 'booked', 'not_for_sale'] : [],\n currency: this.currency,\n onSelect: (seat) => this.handleSeatSelect(seat),\n onDeselect: () => this.syncSelection(),\n onMarquee: () => this.syncSelection(),\n onViewChange: () => this.updateZoomHint(),\n });\n this.renderer.setChart(this.doc);\n this.repaintAll();\n this.applyHeatOverlay();\n this.updateZoomHint();\n }\n\n private updateRendererInteraction(): void {\n const block = this.mode === 'block';\n const inspect = this.mode === 'inspect';\n this.renderer?.setManageInteraction({\n manageMode: true,\n marqueeSelect: block,\n maxSelection: 1_000_000,\n selectableStatuses: block\n ? ['free', 'not_for_sale']\n : inspect ? ['free', 'held', 'booked', 'not_for_sale'] : [],\n });\n this.updateZoomHint();\n }\n\n private handleSeatSelect(seat: ExpandedSeat): void {\n if (this.mode === 'inspect') {\n const others = this.getSelection()\n .filter((selected) => selected.id !== seat.id)\n .map((selected) => selected.id);\n if (others.length) this.renderer?.deselect(others);\n }\n this.syncSelection();\n }\n\n private repaintAll(): void {\n const r = this.renderer;\n if (!r) return;\n if (this.allIds.length) r.setStatus(this.allIds, 'free');\n const byStatus: Record<SeatStatus, string[]> = { free: [], held: [], booked: [], not_for_sale: [] };\n for (const [label, st] of this.status.entries()) {\n const id = this.labelToId.get(label);\n if (id) byStatus[toRenderStatus(st)].push(id);\n }\n (['held', 'booked', 'not_for_sale'] as SeatStatus[]).forEach((st) => {\n if (byStatus[st].length) r.setStatus(byStatus[st], st);\n });\n }\n\n // ---- realtime -------------------------------------------------------------\n\n private connect(): void {\n if (this.closed) return;\n let ws: WebSocket;\n try {\n ws = new WebSocket(this.api.socketUrl(this.key));\n } catch {\n this.scheduleReconnect();\n return;\n }\n this.ws = ws;\n ws.onopen = () => {\n this.attempt = 0;\n this.setLive(true);\n void this.resnapshot().then(() => this.scheduleRevenueRefresh(0));\n void this.refreshAvailability();\n };\n ws.onmessage = (e) => this.onMessage(e);\n ws.onclose = () => {\n if (this.ws === ws) this.ws = null;\n this.setLive(false);\n this.scheduleReconnect();\n };\n ws.onerror = () => { try { ws.close(); } catch { /* ignore */ } };\n }\n\n private scheduleReconnect(): void {\n if (this.closed || this.reconnectTimer) return;\n const delay = Math.min(1000 * 2 ** Math.min(this.attempt++, 5), 15000);\n this.reconnectTimer = setTimeout(() => { this.reconnectTimer = null; this.connect(); }, delay);\n }\n\n private onMessage(e: MessageEvent): void {\n let msg: unknown;\n try {\n msg = JSON.parse(typeof e.data === 'string' ? e.data : '');\n } catch {\n return;\n }\n if (!msg || typeof msg !== 'object') return;\n const m = msg as {\n type?: string;\n seats?: Record<string, string>;\n changes?: { label: string; status: string }[];\n shoppingSessions?: number;\n activeHolds?: number;\n hidden?: string[];\n closed?: string[];\n };\n // Availability state (effective hidden/closed) can ride any message and is the\n // dedicated payload of the 'hidden' broadcast — keep the Sections rail + canvas fresh.\n if (Array.isArray(m.hidden) || Array.isArray(m.closed)) {\n this.updateEffectiveAvailability(m.hidden, m.closed);\n }\n if (m.type === 'presence') {\n if (\n this.controlRoomSnapshot &&\n typeof m.shoppingSessions === 'number' &&\n typeof m.activeHolds === 'number'\n ) {\n this.controlRoomSnapshot = {\n ...this.controlRoomSnapshot,\n presence: { shoppingSessions: m.shoppingSessions, activeHolds: m.activeHolds },\n };\n this.lastSyncedAt = Date.now();\n this.recomputeTallies();\n this.paintMonitorInsights();\n this.opts.onControlRoom?.(this.controlRoomSnapshot);\n }\n return;\n }\n if (m.type === 'hidden') return;\n if (m.seats && typeof m.seats === 'object') {\n this.applySnapshot(m.seats);\n } else if (Array.isArray(m.changes)) {\n const ids: string[] = [];\n const groups = new Map<string, { labels: string[]; verb: string; status: DoStatus }>();\n for (const ch of m.changes) {\n const st = (['free', 'held', 'booked', 'blocked'].includes(ch.status) ? ch.status : 'free') as DoStatus;\n const prev = this.status.get(ch.label) ?? 'free';\n if (prev === st) continue;\n this.status.set(ch.label, st);\n const id = this.labelToId.get(ch.label);\n if (id) { this.renderer?.setStatus([id], toRenderStatus(st)); ids.push(id); }\n const verb = this.verbFor(prev, st);\n const groupKey = `${verb}:${st}`;\n const group = groups.get(groupKey) ?? { labels: [], verb, status: st };\n group.labels.push(ch.label);\n groups.set(groupKey, group);\n }\n for (const group of groups.values()) {\n const activity = this.pushActivity(group.labels, group.verb, group.status);\n if (activity) this.paintSpatialActivity(activity);\n }\n if (ids.length) {\n this.lastSyncedAt = Date.now();\n this.afterPaint();\n }\n this.recomputeTallies();\n if (ids.length) this.scheduleRevenueRefresh();\n }\n }\n\n private async resnapshot(): Promise<void> {\n try {\n const objs = await this.api.objects(this.key);\n this.applySnapshot(objs.seats);\n this.updateEffectiveAvailability(objs.hidden, objs.closed);\n } catch {\n /* transient — the delta stream keeps us fresh */\n }\n }\n\n private applySnapshot(seats: Record<string, string>): void {\n const next = new Map<string, DoStatus>();\n for (const [label, st] of Object.entries(seats)) {\n next.set(label, (['free', 'held', 'booked', 'blocked'].includes(st) ? st : 'free') as DoStatus);\n }\n this.status = next;\n this.lastSyncedAt = Date.now();\n this.repaintAll();\n this.afterPaint();\n this.recomputeTallies();\n }\n\n /** Optimistic local write shared by organizer actions. Paint and tally once,\n * even when an arena-sized operation changes hundreds of seats. */\n private setSeatsLocal(labels: string[], st: DoStatus): void {\n const ids: string[] = [];\n for (const label of labels) {\n this.status.set(label, st);\n const id = this.labelToId.get(label);\n if (id) ids.push(id);\n }\n if (ids.length) this.renderer?.setStatus(ids, toRenderStatus(st));\n this.afterPaint();\n this.recomputeTallies();\n }\n\n /** Keep the canvas painting on hidden/occluded tabs (war-room second monitor). */\n private afterPaint(): void {\n if (this.keepLive && typeof document !== 'undefined' && document.hidden) {\n this.renderer?.forceDraw();\n }\n }\n\n private activityColor(status: DoStatus): string {\n return status === 'held' ? '#f4b740'\n : status === 'booked' ? '#22a06b'\n : status === 'blocked' ? '#8b94ac'\n : '#6e7bff';\n }\n\n private sectionsForLabels(labels: string[]): { ids: string[]; labels: string[] } {\n const ids = new Set<string>();\n for (const label of labels) {\n const seat = this.labelToSeat.get(label);\n if (!seat) continue;\n const sectionId = this.sectionByObject.get(seat.rowId);\n if (sectionId && sectionId !== UNGROUPED_ID) ids.add(sectionId);\n }\n const sectionIds = [...ids];\n return {\n ids: sectionIds,\n labels: sectionIds.map((id) => this.sectionLabelById.get(id) ?? id),\n };\n }\n\n private pulseSeatLabels(labels: string[], status: DoStatus): void {\n const color = this.activityColor(status);\n for (const label of labels.slice(0, MAX_LIVE_SEAT_PULSES)) {\n const id = this.labelToId.get(label);\n if (id) this.renderer?.flashSeat(id, color);\n }\n }\n\n /** Render one grouped realtime operation at the right semantic zoom level. */\n private paintSpatialActivity(activity: SeatManagerActivity): void {\n const sectionIds = activity.sectionIds ?? this.sectionsForLabels(activity.labels).ids;\n const focused = this.renderer?.getFocusedSection() ?? null;\n const followable = this.followLive && sectionIds.length === 1 &&\n (activity.status === 'held' || activity.status === 'booked');\n\n if (followable && focused === sectionIds[0]) {\n this.pulseSeatLabels(activity.labels, activity.status);\n return;\n }\n if (followable) {\n if (this.followLiveTimer) clearTimeout(this.followLiveTimer);\n if (this.followSeatTimer) clearTimeout(this.followSeatTimer);\n this.followLiveTimer = setTimeout(() => {\n this.followLiveTimer = null;\n this.renderer?.focusSection(sectionIds[0]);\n this.followSeatTimer = setTimeout(() => {\n this.followSeatTimer = null;\n this.pulseSeatLabels(activity.labels, activity.status);\n }, 520);\n }, 220);\n return;\n }\n\n if (!focused && sectionIds.length) {\n const color = this.activityColor(activity.status);\n for (const sectionId of sectionIds.slice(0, MAX_LIVE_SECTION_PULSES)) {\n this.renderer?.flashSection(sectionId, color);\n }\n return;\n }\n if (!sectionIds.length || (focused && sectionIds.includes(focused))) {\n this.pulseSeatLabels(activity.labels, activity.status);\n }\n }\n\n private locateSection(sectionId: string): void {\n this.renderer?.focusSection(sectionId);\n }\n\n private locateActivity(activityId: string): void {\n const activity = this.feed.find((item) => item.id === activityId);\n if (!activity) return;\n const sectionIds = activity.sectionIds ?? this.sectionsForLabels(activity.labels).ids;\n if (this.followSeatTimer) clearTimeout(this.followSeatTimer);\n if (sectionIds.length === 1) {\n this.locateSection(sectionIds[0]);\n this.followSeatTimer = setTimeout(() => {\n this.followSeatTimer = null;\n this.pulseSeatLabels(activity.labels, activity.status);\n }, 520);\n return;\n }\n this.zoomToFit();\n this.followSeatTimer = setTimeout(() => {\n this.followSeatTimer = null;\n if (sectionIds.length) {\n const color = this.activityColor(activity.status);\n for (const sectionId of sectionIds.slice(0, MAX_LIVE_SECTION_PULSES)) {\n this.renderer?.flashSection(sectionId, color);\n }\n } else {\n this.pulseSeatLabels(activity.labels, activity.status);\n }\n }, 280);\n }\n\n private showLiveEvent(activity: SeatManagerActivity): void {\n const element = this.els.liveevent;\n if (!element) return;\n const sections = activity.sectionLabels ?? [];\n const place = sections.length === 1 ? sections[0]\n : sections.length > 1 ? `${sections.length} sections`\n : activity.label;\n const noun = activity.count === 1 ? 'seat' : 'seats';\n element.innerHTML = `<span class=\"slm-liveeventdot\" style=\"background:${this.activityColor(activity.status)}\"></span>\n <span class=\"slm-liveeventcopy\">${esc(place)} · ${activity.count.toLocaleString()} ${noun} ${esc(activity.verb)}</span>\n <span class=\"slm-liveeventhint\">Live</span>`;\n element.classList.add('on');\n if (this.liveEventTimer) clearTimeout(this.liveEventTimer);\n this.liveEventTimer = setTimeout(() => {\n this.liveEventTimer = null;\n element.classList.remove('on');\n element.innerHTML = '';\n }, 2800);\n }\n\n // ---- tallies + feed -------------------------------------------------------\n\n private applyReportRevenue(report: ReportResult): void {\n this.authoritativeGrossRevenue = report.report.byCategory.reduce(\n (sum, row) => sum + (Number.isFinite(row.bookedRevenue) ? row.bookedRevenue : 0),\n 0,\n );\n this.revenueStatus = 'current';\n this.recomputeTallies();\n }\n\n private async refreshControlRoom(): Promise<ControlRoomSnapshot> {\n const request = ++this.revenueRequest;\n try {\n const snapshot = await this.api.controlRoom(this.key, this.trendWindowMinutes);\n if (request === this.revenueRequest) {\n this.controlRoomSnapshot = snapshot;\n this.lastSyncedAt = Date.now();\n this.authoritativeGrossRevenue = snapshot.revenue.gross;\n this.currency = snapshot.currency;\n this.revenueStatus = 'current';\n this.recomputeTallies();\n this.applyHeatOverlay();\n this.paintMonitorInsights();\n this.opts.onControlRoom?.(snapshot);\n }\n return snapshot;\n } catch (err) {\n if (request === this.revenueRequest) {\n this.revenueStatus = 'stale';\n this.recomputeTallies();\n }\n throw err;\n }\n }\n\n private scheduleRevenueRefresh(delay = 140): void {\n this.revenueStatus = 'stale';\n this.recomputeTallies();\n if (this.revenueRefreshTimer) clearTimeout(this.revenueRefreshTimer);\n this.revenueRefreshTimer = setTimeout(() => {\n this.revenueRefreshTimer = null;\n void this.refreshControlRoom().catch((err) => this.opts.onError?.(err));\n }, delay);\n }\n\n private recomputeTallies(): void {\n const t: SeatManagerTallies = {\n free: 0, held: 0, booked: 0, blocked: 0,\n total: this.allIds.length, capacityPct: 0, sellThroughPct: 0,\n grossRevenue: this.authoritativeGrossRevenue,\n revenueStatus: this.revenueStatus,\n currency: this.currency,\n };\n // free = total − (held+booked+blocked); the snapshot only carries non-free.\n let nonFree = 0;\n for (const st of this.status.values()) {\n t[st] += 1;\n if (st !== 'free') nonFree += 1;\n }\n t.free = Math.max(0, t.total - nonFree);\n t.capacityPct = t.total ? Math.round((t.booked / t.total) * 100) : 0;\n const sellable = t.total - t.blocked;\n t.sellThroughPct = sellable > 0 ? Math.round((t.booked / sellable) * 100) : 0;\n this.paintKpis(t);\n if (this.mode === 'view') {\n this.paintLegend(t);\n this.paintMonitorInsights();\n } else if (this.mode === 'inspect') this.renderInspectRail(this.getSelection());\n else if (this.mode === 'block') this.paintSelBar(this.getSelection());\n this.opts.onTallies?.(t);\n }\n\n private verbFor(prev: DoStatus, next: DoStatus): string {\n if (next === 'held') return 'held';\n if (next === 'booked') return 'booked';\n if (next === 'blocked') return 'blocked';\n if (next === 'free') return prev === 'blocked' ? 'unblocked' : prev === 'booked' ? 'cancelled' : 'released';\n return next;\n }\n\n private pushActivity(labels: string[], verb: string, status: DoStatus, at = Date.now()): SeatManagerActivity | null {\n const label = labels[0];\n if (!label) return null;\n const sections = this.sectionsForLabels(labels);\n const item: SeatManagerActivity = {\n id: `${label}:${at}:${Math.random().toString(36).slice(2, 6)}`,\n at,\n label,\n labels: [...labels],\n count: labels.length,\n verb,\n status,\n sectionIds: sections.ids,\n sectionLabels: sections.labels,\n };\n this.feed.unshift(item);\n if (this.feed.length > FEED_CAP) this.feed.length = FEED_CAP;\n if (this.mode === 'view') this.paintFeed();\n this.showLiveEvent(item);\n this.opts.onActivity?.(item);\n return item;\n }\n\n private seedFeed(entries: ControlRoomActivityEntry[]): void {\n const verbByAction: Record<string, string> = {\n hold: 'held', book: 'booked', release: 'released', expire: 'expired', block: 'blocked', unblock: 'unblocked',\n unbook: 'cancelled',\n };\n const stByAction: Record<string, DoStatus> = {\n hold: 'held', book: 'booked', release: 'free', expire: 'free', block: 'blocked', unblock: 'free', unbook: 'free',\n };\n for (const e of entries) {\n const label = e.labels[0];\n if (!label) continue;\n const sections = this.sectionsForLabels(e.labels);\n const item: SeatManagerActivity = {\n id: `log:${e.id}`,\n at: e.at,\n label,\n labels: [...e.labels],\n count: e.labels.length,\n verb: verbByAction[e.action] ?? e.action,\n status: stByAction[e.action] ?? 'free',\n sectionIds: sections.ids,\n sectionLabels: sections.labels,\n };\n this.feed.push(item);\n this.opts.onActivity?.(item);\n }\n this.feed.sort((a, b) => b.at - a.at);\n if (this.feed.length > FEED_CAP) this.feed.length = FEED_CAP;\n if (this.mode === 'view') this.paintFeed();\n }\n\n private startFeedClock(): void {\n this.feedTimer = setInterval(() => {\n if (this.mode === 'view') {\n this.paintFeed();\n this.paintMonitorInsights();\n }\n }, 10000);\n }\n\n // ---- selection ------------------------------------------------------------\n\n private selectionLabels(): string[] {\n return this.getSelection().map((s) => s.label);\n }\n\n private syncSelection(): void {\n const seats = this.getSelection();\n if (this.mode === 'block') this.paintSelBar(seats);\n else if (this.mode === 'inspect') this.renderInspectRail(seats);\n this.opts.onSelectionChange?.(seats);\n }\n\n // ---- DOM: chrome ----------------------------------------------------------\n\n private buildChrome(): void {\n const root = document.createElement('div');\n root.className = 'slm';\n root.tabIndex = 0;\n root.setAttribute('role', 'region');\n root.setAttribute('aria-label', 'SeatLayer live control room');\n const vars = themeVars(this.opts.theme);\n for (const [k, v] of Object.entries(vars)) root.style.setProperty(k, v);\n root.innerHTML = `\n <div class=\"slm-bar\">\n <div class=\"slm-modes\" data-ref=\"modes\" role=\"tablist\" aria-label=\"Manager tools\">\n <button class=\"slm-mode\" role=\"tab\" data-mode=\"view\" title=\"Monitor (M)\" aria-keyshortcuts=\"M\">Monitor</button>\n <button class=\"slm-mode\" role=\"tab\" data-mode=\"inspect\" title=\"Inspect (I)\" aria-keyshortcuts=\"I\">Inspect</button>\n <button class=\"slm-mode\" role=\"tab\" data-mode=\"block\" title=\"Block (B)\" aria-keyshortcuts=\"B\">Block</button>\n <button class=\"slm-mode\" role=\"tab\" data-mode=\"sections\" title=\"Sections (S)\" aria-keyshortcuts=\"S\">Sections</button>\n </div>\n <span class=\"slm-live\"><span class=\"slm-live-dot\"></span><span data-ref=\"livetext\">CONNECTING</span></span>\n <div class=\"slm-bar-actions\">\n <button class=\"slm-barbtn follow\" data-ref=\"follow\" aria-pressed=\"false\"\n title=\"Stay on the current map view unless enabled\">Follow live</button>\n <button class=\"slm-barbtn\" data-ref=\"heat\" aria-pressed=\"false\"\n aria-label=\"Sales momentum overlay off\"\n title=\"Highlight sections selling fastest in the selected time window\">Sales momentum</button>\n <button class=\"slm-barbtn\" data-ref=\"fullscreen\" title=\"Full screen (F)\" aria-keyshortcuts=\"F\">Full screen</button>\n </div>\n <div class=\"slm-kpis\" data-ref=\"kpis\"></div>\n </div>\n <div class=\"slm-body\">\n <div class=\"slm-map\">\n <div class=\"slm-map-host\" data-ref=\"maphost\"></div>\n <div class=\"slm-zoomhint\" data-ref=\"zoomhint\">Zoom in to marquee-select</div>\n <div class=\"slm-liveevent\" data-ref=\"liveevent\" role=\"status\" aria-live=\"polite\"></div>\n <div class=\"slm-hud\"><button class=\"slm-hud-chip\" data-ref=\"zfit\">Zoom to fit</button></div>\n </div>\n <aside class=\"slm-rail\"><div class=\"slm-railscroll\" data-ref=\"rail\"></div></aside>\n </div>\n <div class=\"slm-toast\" data-ref=\"toast\"></div>\n `;\n this.host.appendChild(root);\n this.root = root;\n this.updateContainerLayout();\n if (typeof ResizeObserver !== 'undefined') {\n this.layoutObserver = new ResizeObserver(() => this.updateContainerLayout());\n this.layoutObserver.observe(root);\n }\n const ref = (n: string) => root.querySelector(`[data-ref=\"${n}\"]`) as HTMLElement;\n this.mapHost = ref('maphost') as HTMLDivElement;\n this.els = {\n modes: ref('modes'), livetext: ref('livetext'), kpis: ref('kpis'),\n follow: ref('follow'), heat: ref('heat'), fullscreen: ref('fullscreen'),\n zoomhint: ref('zoomhint'), liveevent: ref('liveevent'), rail: ref('rail'), toast: ref('toast'), zfit: ref('zfit'),\n };\n this.els.modes.querySelectorAll('[data-mode]').forEach((b) =>\n b.addEventListener('click', () => this.setMode((b as HTMLElement).dataset.mode as SeatManagerMode)));\n this.els.zfit.addEventListener('click', () => this.zoomToFit());\n this.els.follow.addEventListener('click', () => this.setFollowLive(!this.followLive));\n this.els.heat.addEventListener('click', () => this.setHeatOverlay(!this.heatEnabled));\n this.els.fullscreen.addEventListener('click', () => this.toggleFullscreen());\n root.addEventListener('keydown', this.onKeyDown);\n this.els.rail.addEventListener('click', this.onRailClick);\n document.addEventListener('fullscreenchange', this.onFullscreenChange);\n this.paintModeTabs();\n this.paintFollowLiveButton();\n this.paintHeatButton();\n this.paintFullscreenButton();\n }\n\n private updateContainerLayout(): void {\n const width = this.root?.getBoundingClientRect().width || this.host.clientWidth;\n this.root?.classList.toggle('compact', width > 0 && width < 800);\n }\n\n private sectionOptions: { id: string; label: string }[] = [];\n\n private buildSectionOptions(): void {\n if (!this.doc) return;\n try {\n const secs = computeSections(this.doc);\n this.sectionsBase = secs;\n this.sectionOptions = [];\n this.sectionByObject = new Map(secs.objectToSection);\n this.sectionLabelById.clear();\n for (const s of secs.sections) {\n this.sectionOptions.push({ id: s.id, label: s.label });\n this.sectionLabelById.set(s.id, s.label);\n }\n if (secs.ungrouped) {\n this.sectionOptions.push({ id: UNGROUPED_ID, label: secs.ungrouped.label });\n this.sectionLabelById.set(UNGROUPED_ID, secs.ungrouped.label);\n }\n } catch { /* no sections */ }\n }\n\n private paintModeTabs(): void {\n this.els.modes?.querySelectorAll('[data-mode]').forEach((b) => {\n const el = b as HTMLElement;\n const active = el.dataset.mode === this.mode;\n el.classList.toggle('on', active);\n el.setAttribute('aria-selected', String(active));\n el.tabIndex = active ? 0 : -1;\n });\n this.root?.classList.toggle('block-mode', this.mode === 'block');\n }\n\n private paintFollowLiveButton(): void {\n const button = this.els.follow;\n if (!button) return;\n button.classList.toggle('on', this.followLive);\n button.setAttribute('aria-pressed', String(this.followLive));\n button.setAttribute('title', this.followLive\n ? 'Following new buyer holds and bookings. Turn off to keep the current view.'\n : 'Stay on the current map view. Enable to follow new buyer holds and bookings.');\n }\n\n private paintHeatButton(): void {\n const button = this.els.heat;\n if (!button) return;\n button.classList.toggle('on', this.heatEnabled);\n button.setAttribute('aria-pressed', String(this.heatEnabled));\n button.setAttribute('aria-label', `Sales momentum overlay ${this.heatEnabled ? 'on' : 'off'}`);\n button.setAttribute('title', `${this.heatEnabled ? 'Hide' : 'Highlight'} sections selling fastest in the selected time window`);\n button.textContent = 'Sales momentum';\n this.paintMomentumHelp();\n }\n\n private paintMomentumHelp(): void {\n const help = this.els.rail?.querySelector('[data-ref=\"momentumhelp\"]') as HTMLElement | null;\n if (!help) return;\n help.hidden = !this.heatEnabled;\n const copy = help.querySelector('[data-ref=\"momentumcopy\"]');\n if (!copy) return;\n const hasRecentSales = this.controlRoomSnapshot?.velocity.bySection.some((row) => row.netBooked > 0);\n copy.textContent = hasRecentSales\n ? 'Warmer sections have more completed bookings, adjusted for section size. Holds and viewers are not counted.'\n : `No completed bookings in the last ${this.trendWindowMinutes} minutes.`;\n }\n\n private paintFullscreenButton(): void {\n if (!this.els.fullscreen) return;\n this.els.fullscreen.textContent = this.isFullscreen() ? 'Exit full screen' : 'Full screen';\n }\n\n private paintTrendWindow(): void {\n this.els.rail?.querySelectorAll('[data-window]').forEach((button) => {\n const value = Number((button as HTMLElement).dataset.window);\n button.classList.toggle('on', value === this.trendWindowMinutes);\n });\n }\n\n private setLive(on: boolean): void {\n this.root?.classList.toggle('live', on);\n if (this.els.livetext) this.els.livetext.textContent = on ? 'LIVE' : 'RECONNECTING';\n this.paintMonitorInsights();\n }\n\n private updateZoomHint(): void {\n const hint = this.els.zoomhint;\n if (!hint) return;\n const show = this.mode === 'block' && this.renderer?.getRung?.() !== 'seats';\n hint.classList.toggle('on', !!show);\n }\n\n private formatKpiDelta(key: string, delta: number, currency: string): string {\n const sign = delta > 0 ? '+' : '−';\n const absolute = Math.abs(delta);\n if (key === 'gross-sales') return `${sign}${fmtMoney(absolute, currency)}`;\n if (key === 'sold-pct') return `${sign}${absolute.toLocaleString()}pt`;\n return `${sign}${absolute.toLocaleString()}`;\n }\n\n private paintKpis(t: SeatManagerTallies): void {\n if (!this.els.kpis) return;\n const rev = t.revenueStatus === 'current' ? fmtMoney(t.grossRevenue, t.currency) : '—';\n const presence = this.controlRoomSnapshot?.presence;\n const items: { key: string; raw: number | null; n: string; l: string; dot?: string }[] = [\n { key: 'sold-seats', raw: t.booked, n: t.booked.toLocaleString(), l: 'Sold seats', dot: '#22a06b' },\n { key: 'held-seats', raw: t.held, n: t.held.toLocaleString(), l: 'Held seats', dot: '#f4b740' },\n { key: 'buyers', raw: presence?.shoppingSessions ?? null, n: presence ? presence.shoppingSessions.toLocaleString() : '—', l: 'Buyers' },\n { key: 'active-holds', raw: presence?.activeHolds ?? null, n: presence ? presence.activeHolds.toLocaleString() : '—', l: 'Active holds' },\n { key: 'free-seats', raw: t.free, n: t.free.toLocaleString(), l: 'Free seats', dot: '#6e7bff' },\n { key: 'blocked', raw: t.blocked, n: t.blocked.toLocaleString(), l: 'Blocked', dot: '#8b94ac' },\n { key: 'sold-pct', raw: t.capacityPct, n: `${t.capacityPct}%`, l: 'Sold' },\n { key: 'gross-sales', raw: t.revenueStatus === 'current' ? t.grossRevenue : null, n: rev, l: 'Gross sales' },\n ];\n let hasChanges = false;\n this.els.kpis.innerHTML = items.map((item) => {\n const previous = this.lastKpiValues.get(item.key);\n const changed = item.raw != null && previous != null && item.raw !== previous;\n const delta = changed ? item.raw! - previous! : 0;\n if (changed) {\n hasChanges = true;\n this.activeKpiDeltas.set(item.key, {\n text: this.formatKpiDelta(item.key, delta, t.currency),\n down: delta < 0,\n });\n }\n if (item.raw != null) this.lastKpiValues.set(item.key, item.raw);\n const activeDelta = this.activeKpiDeltas.get(item.key);\n return `<div class=\"slm-kpi${activeDelta ? ' changed' : ''}\" data-kpi=\"${item.key}\">\n <b>${item.dot ? `<span class=\"dot\" style=\"background:${item.dot}\"></span>` : ''}${item.n}</b><span>${item.l}</span>\n ${activeDelta ? `<span class=\"slm-kpidelta${activeDelta.down ? ' down' : ''}\">${activeDelta.text}</span>` : ''}\n </div>`;\n }).join('');\n if (hasChanges) {\n // The map above has already adopted the new values, so detect the rendered\n // change markers directly and remove their accessibility footprint after\n // the visual cue completes.\n if (this.kpiCleanupTimer) clearTimeout(this.kpiCleanupTimer);\n this.kpiCleanupTimer = setTimeout(() => {\n this.kpiCleanupTimer = null;\n this.activeKpiDeltas.clear();\n this.els.kpis?.querySelectorAll('.slm-kpidelta').forEach((element) => element.remove());\n this.els.kpis?.querySelectorAll('.slm-kpi.changed').forEach((element) => element.classList.remove('changed'));\n }, 1500);\n }\n }\n\n // ---- DOM: rails -----------------------------------------------------------\n\n private paintRail(): void {\n if (this.mode === 'view') this.renderViewRail();\n else if (this.mode === 'inspect') this.renderInspectRail(this.getSelection());\n else if (this.mode === 'sections') this.renderSectionsRail();\n else this.renderBlockRail();\n this.updateZoomHint();\n }\n\n private renderViewRail(): void {\n this.els.rail.innerHTML = `\n <p class=\"slm-eyebrow\">Monitor</p>\n <p class=\"slm-hint\">Read-only. Inventory, buyer presence and sales movement update on the same live board.</p>\n <div class=\"slm-health\" data-ref=\"presence\"></div>\n <div class=\"slm-legend\" data-ref=\"legend\"></div>\n <div class=\"slm-sectionhead\">\n <div><p class=\"slm-eyebrow\">Section performance</p><p class=\"slm-note\">Exact booked revenue · net sales velocity</p></div>\n <div class=\"slm-windows\" aria-label=\"Sales velocity window\">\n ${[5, 15, 30, 60].map((window) => `<button class=\"slm-window\" data-window=\"${window}\">${window}m</button>`).join('')}\n </div>\n </div>\n <div class=\"slm-momentumhelp\" data-ref=\"momentumhelp\" ${this.heatEnabled ? '' : 'hidden'}>\n <div class=\"slm-momentumscale\"><span>Warm</span><span class=\"slm-momentumgradient\"></span><span>Hot</span></div>\n <p class=\"slm-momentumcopy\" data-ref=\"momentumcopy\"></p>\n </div>\n <div class=\"slm-sectionlist\" data-ref=\"sections\"></div>\n <p class=\"slm-eyebrow\">Activity</p>\n <div class=\"slm-feed\" data-ref=\"feed\"></div>\n `;\n this.els.presence = this.els.rail.querySelector('[data-ref=\"presence\"]') as HTMLElement;\n this.els.legend = this.els.rail.querySelector('[data-ref=\"legend\"]') as HTMLElement;\n this.els.sections = this.els.rail.querySelector('[data-ref=\"sections\"]') as HTMLElement;\n this.els.feed = this.els.rail.querySelector('[data-ref=\"feed\"]') as HTMLElement;\n this.els.rail.querySelectorAll('[data-window]').forEach((button) => button.addEventListener('click', () => {\n const windowMinutes = Number((button as HTMLElement).dataset.window);\n void this.setTrendWindow(windowMinutes).catch((err) => this.opts.onError?.(err));\n }));\n this.recomputeTallies();\n this.paintMonitorInsights();\n this.paintTrendWindow();\n this.paintMomentumHelp();\n this.paintFeed();\n }\n\n private paintMonitorInsights(): void {\n if (this.mode !== 'view') return;\n const snapshot = this.controlRoomSnapshot;\n if (this.els.presence) {\n const connected = this.root?.classList.contains('live');\n const sync = this.lastSyncedAt ? relTime(this.lastSyncedAt, Date.now()) : 'waiting';\n this.els.presence.innerHTML = `\n <div class=\"slm-healthitem\"><b>${snapshot ? snapshot.presence.shoppingSessions.toLocaleString() : '—'}</b><span>Buyer sessions</span></div>\n <div class=\"slm-healthitem\"><b>${snapshot ? snapshot.presence.activeHolds.toLocaleString() : '—'}</b><span>Active holds</span></div>\n <div class=\"slm-healthitem\"><b>${connected ? 'Healthy' : 'Reconnecting'}</b><span>Live connection</span></div>\n <div class=\"slm-healthitem\"><b>${sync}</b><span>Last sync</span></div>`;\n }\n if (!this.els.sections) return;\n if (!snapshot) {\n this.els.sections.innerHTML = '<div class=\"slm-empty\">Loading authoritative section metrics…</div>';\n return;\n }\n const velocity = new Map(snapshot.velocity.bySection.map((row) => [row.sectionId, row]));\n const rows = [...snapshot.revenue.bySection].sort((a, b) => {\n const av = velocity.get(a.sectionId)?.netBooked ?? 0;\n const bv = velocity.get(b.sectionId)?.netBooked ?? 0;\n return bv - av || b.bookedRevenue - a.bookedRevenue;\n });\n this.els.sections.innerHTML = rows.length ? rows.map((row) => {\n const speed = velocity.get(row.sectionId);\n const net = speed?.netBooked ?? 0;\n const netLabel = `${net > 0 ? '+' : ''}${net}`;\n const trend = speed?.trend === 'rising' || speed?.trend === 'cooling' ? speed.trend : 'steady';\n return `<button type=\"button\" class=\"slm-sectionrow\" data-section-focus=\"${esc(row.sectionId)}\" title=\"Focus ${esc(row.sectionLabel)} on the map\">\n <span class=\"slm-sectiontop\"><span>${esc(row.sectionLabel)}</span><span>${fmtMoney(row.bookedRevenue, snapshot.currency)}</span></span>\n <span class=\"slm-sectionmeta\"><span>${row.booked.toLocaleString()}/${row.total.toLocaleString()} sold · ${netLabel} in ${snapshot.velocity.windowMinutes}m</span><span class=\"slm-trend ${trend}\">${trend}</span><span class=\"slm-sectionlocate\">Locate</span></span>\n </button>`;\n }).join('') : '<div class=\"slm-empty\">No section metrics are available for this chart.</div>';\n this.paintTrendWindow();\n this.paintMomentumHelp();\n }\n\n private applyHeatOverlay(): void {\n const snapshot = this.controlRoomSnapshot;\n if (!this.heatEnabled || !snapshot) {\n this.renderer?.setSectionHeat(null);\n return;\n }\n const capacity = new Map(snapshot.revenue.bySection.map((row) => [row.sectionId, Math.max(1, row.total)]));\n const rates = snapshot.velocity.bySection.map((row) => ({\n sectionId: row.sectionId,\n rate: Math.max(0, row.netBooked) / (capacity.get(row.sectionId) ?? 1) / snapshot.velocity.windowMinutes,\n }));\n const max = Math.max(0, ...rates.map((row) => row.rate));\n const scores: Record<string, number> = {};\n for (const row of rates) scores[row.sectionId] = max > 0 ? Math.sqrt(row.rate / max) : 0;\n this.renderer?.setSectionHeat(scores);\n }\n\n private renderInspectRail(seats: ExpandedSeat[]): void {\n const seat = seats[seats.length - 1];\n if (!seat) {\n this.els.rail.innerHTML = `\n <p class=\"slm-eyebrow\">Inspect seats</p>\n <p class=\"slm-hint\">Select a seat to see its availability and sales context. Nothing changes in this view.</p>\n <div class=\"slm-empty\">Select a seat on the map.</div>`;\n return;\n }\n const status = this.status.get(seat.label) ?? 'free';\n const statusLabel: Record<DoStatus, string> = { free: 'Free', held: 'Held', booked: 'Booked', blocked: 'Blocked' };\n const sectionId = this.sectionByObject.get(seat.rowId) ?? UNGROUPED_ID;\n const sectionLabel = this.sectionLabelById.get(sectionId) ?? 'Other seats';\n const category = this.doc?.categories.find((item) => item.key === seat.categoryKey);\n const sectionMetric = this.controlRoomSnapshot?.revenue.bySection.find((row) => row.sectionId === sectionId);\n const object = this.doc?.objects.find((item) => item.id === seat.rowId);\n const location = object?.type === 'row'\n ? { label: 'Row', value: object.label }\n : object?.type === 'table'\n ? { label: 'Table', value: object.label }\n : seat.kind === 'booth'\n ? { label: 'Type', value: 'Booth' }\n : null;\n const itemKind = seat.kind === 'booth' ? 'Booth' : 'Seat';\n this.els.rail.innerHTML = `\n <p class=\"slm-eyebrow\">${itemKind} details</p>\n <p class=\"slm-hint\">Live availability and section performance.</p>\n <div class=\"slm-inspect-card\">\n <div class=\"slm-inspect-label\">${esc(seat.label)}</div>\n <div class=\"slm-inspect-grid\">\n <div><span>Status</span><b>${statusLabel[status]}</b></div>\n <div><span>Section</span><b>${esc(sectionLabel)}</b></div>\n ${location ? `<div><span>${location.label}</span><b>${esc(location.value)}</b></div>` : ''}\n <div><span>Category</span><b>${esc(category?.label ?? seat.categoryKey)}</b></div>\n <div><span>Sold in section</span><b>${sectionMetric ? `${sectionMetric.booked} of ${sectionMetric.total}` : '—'}</b></div>\n <div><span>Section revenue</span><b>${sectionMetric && this.controlRoomSnapshot ? fmtMoney(sectionMetric.bookedRevenue, this.controlRoomSnapshot.currency) : '—'}</b></div>\n </div>\n </div>`;\n }\n\n // ---- sections: availability windows --------------------------------------\n\n /** Pull the organizer's availability rules (event:view). Called on load and on\n * every WS (re)connect, mirroring how the other panels re-hydrate. `closed` is\n * deterministic from the rules; `hidden` (which folds in already-due timed /\n * threshold windows) comes from the snapshot + WS effective set. */\n private async refreshAvailability(): Promise<void> {\n try {\n const res = await this.withAuthRetry(() => this.api.availability(this.key));\n this.availabilityRules = res.rules ?? {};\n this.effectiveClosed = new Set(this.closedIdsFromRules(this.availabilityRules));\n if (this.mode === 'sections') this.renderSectionsRail();\n this.applySectionCanvasTreatment();\n } catch (err) {\n this.opts.onError?.(err);\n }\n }\n\n /** Run a token-authed op; on a 401 re-mint via onTokenRefresh and retry once. */\n private async withAuthRetry<T>(op: () => Promise<T>): Promise<T> {\n try {\n return await op();\n } catch (err) {\n if (err instanceof ManageApiError && err.status === 401 && this.opts.onTokenRefresh && !this.tokenRefreshInFlight) {\n await this.rotateToken();\n return op();\n }\n throw err;\n }\n }\n\n private closedIdsFromRules(rules: Record<string, AvailabilityRule>): string[] {\n return Object.entries(rules).filter(([, r]) => r.mode === 'closed').map(([id]) => id);\n }\n\n /** Adopt a new effective hidden/closed set (from a snapshot or WS broadcast) and\n * repaint the rail + canvas when it actually moves. */\n private updateEffectiveAvailability(hidden?: string[], closed?: string[]): void {\n let changed = false;\n if (Array.isArray(hidden)) {\n this.effectiveHidden = new Set(hidden.filter((x): x is string => typeof x === 'string'));\n changed = true;\n }\n if (Array.isArray(closed)) {\n this.effectiveClosed = new Set(closed.filter((x): x is string => typeof x === 'string'));\n changed = true;\n }\n if (!changed) return;\n if (this.mode === 'sections') this.renderSectionsRail();\n this.applySectionCanvasTreatment();\n }\n\n /** Canvas read of the availability state: dim hidden sections to a whisper,\n * half-light closed sections, leave open sections normal. Only in Sections mode;\n * cleared in every other tool. */\n private applySectionCanvasTreatment(): void {\n if (!this.renderer) return;\n if (this.mode === 'sections') {\n this.renderer.setDimmedSections([...this.effectiveHidden]);\n this.renderer.setClosedSections([...this.effectiveClosed]);\n } else {\n this.renderer.setDimmedSections(null);\n this.renderer.setClosedSections(null);\n }\n }\n\n /** Zone-grouped render tree: each zone header then its sections (which follow the\n * zone window), then loose sections + the ungrouped bucket. Effective hidden /\n * closed come from the live sets, rules from the organizer map. */\n private buildSectionRows(): { rows: SectionRow[]; hiddenSections: number; closedSections: number } {\n const base = this.sectionsBase;\n if (!base) return { rows: [], hiddenSections: 0, closedSections: 0 };\n const zones = this.doc?.zones ?? [];\n const byZone = new Map<string, SectionNode[]>();\n const loose: SectionNode[] = [];\n for (const s of base.sections) {\n if (s.zone && zones.some((z) => z.id === s.zone)) {\n const list = byZone.get(s.zone) ?? [];\n list.push(s);\n byZone.set(s.zone, list);\n } else {\n loose.push(s);\n }\n }\n const rows: SectionRow[] = [];\n let hiddenSections = 0;\n let closedSections = 0;\n const push = (\n kind: 'zone' | 'section',\n node: { id: string; label: string; seatCount: number; seatLabels: string[] },\n zoneRuled: boolean,\n parentClosed = false,\n ): void => {\n const rule = this.availabilityRules[node.id] ?? null;\n const effClosed = this.effectiveClosed.has(node.id) || parentClosed;\n // A closed section stays visible-but-off-sale, never counted as hidden.\n const effHidden = this.effectiveHidden.has(node.id) || (zoneRuled && !effClosed);\n if (kind === 'section' && effHidden) hiddenSections += 1;\n if (kind === 'section' && effClosed) closedSections += 1;\n rows.push({\n kind, id: node.id, label: node.label, seatCount: node.seatCount, seatLabels: node.seatLabels,\n rule, hidden: effHidden, closed: effClosed, followsZone: kind === 'section' && zoneRuled,\n });\n };\n for (const z of zones) {\n const secs = byZone.get(z.id);\n if (!secs || !secs.length) continue;\n const zoneNode = {\n id: z.id,\n label: z.label || 'Zone',\n seatCount: secs.reduce((sum, s) => sum + s.seatCount, 0),\n seatLabels: secs.flatMap((s) => s.seatLabels),\n };\n const zoneRuled = !!this.availabilityRules[z.id];\n const zoneClosed = this.availabilityRules[z.id]?.mode === 'closed';\n push('zone', zoneNode, false);\n for (const s of secs) push('section', s, zoneRuled, zoneClosed);\n }\n for (const s of loose) push('section', s, false);\n if (base.ungrouped) {\n const u = base.ungrouped;\n push('section', { id: UNGROUPED_ID, label: u.label, seatCount: u.seatCount, seatLabels: u.seatLabels }, false);\n }\n return { rows, hiddenSections, closedSections };\n }\n\n private renderSectionsRail(): void {\n const { rows, hiddenSections, closedSections } = this.buildSectionRows();\n if (!rows.length) {\n this.els.rail.innerHTML = `\n <p class=\"slm-eyebrow\">Availability windows</p>\n <p class=\"slm-hint\">Draw sections or zones in the designer to schedule availability per area. This chart has none yet.</p>\n <div class=\"slm-empty\">No sections on this chart.</div>`;\n return;\n }\n const parts: string[] = [];\n if (hiddenSections) parts.push(`${hiddenSections} hidden`);\n if (closedSections) parts.push(`${closedSections} closed`);\n const summary = parts.length ? parts.join(' · ') : 'All sections open and on sale';\n const warn = hiddenSections > 0 || closedSections > 0;\n this.els.rail.innerHTML = `\n <p class=\"slm-eyebrow\">Availability windows</p>\n <p class=\"slm-hint\">Control when each zone or section goes on sale. Keep it hidden, reveal it at a set time, or <b>auto-reveal once the rest sells past a threshold</b>. Hidden seats vanish for buyers; closed seats stay on the map (flat grey) but can't be bought.</p>\n <div class=\"slm-availlist\" data-ref=\"availlist\">${rows.map((row) => this.sectionRowHtml(row)).join('')}</div>\n <div class=\"slm-availsummary\">\n <span class=\"slm-availdot${warn ? ' warn' : ''}\"></span>\n <span>${esc(summary)}</span>\n </div>\n <div class=\"slm-availcallout\">\n <span class=\"slm-availstar\" aria-hidden=\"true\">✦</span>\n <p><b>Auto-reveal at % sold</b> is our differentiator — demand-triggered release: the balcony opens itself the moment the stalls hit the threshold. Neither seats.io nor Ticketmaster ships this.</p>\n </div>`;\n this.wireSectionRail();\n this.applySectionCanvasTreatment();\n }\n\n private sectionRowHtml(row: SectionRow): string {\n const mode = availabilityModeOf(row.rule);\n const cls = `slm-availrow${row.kind === 'zone' ? ' zone' : ''}${row.hidden ? ' hidden' : ''}${row.closed ? ' closed' : ''}`;\n const disabled = this.availabilitySaving ? ' disabled' : '';\n const option = (value: AvailabilityMode, text: string): string =>\n `<option value=\"${value}\"${mode === value ? ' selected' : ''}>${text}</option>`;\n const control = row.followsZone\n ? '<span class=\"slm-availfollows\">Follows zone</span>'\n : `<span class=\"slm-availselwrap\">\n <select class=\"slm-select slm-availmode${mode !== 'open' ? ' on' : ''}\" data-avail-id=\"${esc(row.id)}\"${disabled} aria-label=\"Availability for ${esc(row.label)}\">\n ${option('open', 'Open — on sale')}\n ${option('closed', 'Closed — visible, not on sale')}\n ${option('hidden', 'Hidden — off the buyer map')}\n ${option('timed', 'Reveal at a time')}\n ${option('threshold', 'Auto-reveal at % sold')}\n </select>\n </span>`;\n let detail = '';\n if (!row.followsZone && mode === 'timed') {\n const value = row.rule?.revealAt ? esc(toLocalInput(row.rule.revealAt)) : '';\n detail = `<div class=\"slm-availdetail\">\n <input type=\"datetime-local\" class=\"slm-input\" data-avail-reveal=\"${esc(row.id)}\" value=\"${value}\"${disabled} aria-label=\"Reveal time for ${esc(row.label)}\" />\n </div>`;\n } else if (!row.followsZone && mode === 'threshold') {\n const pct = row.rule?.thresholdPct ?? 80;\n detail = `<div class=\"slm-availdetail\">\n <span class=\"slm-availpctlabel\">Reveal at</span>\n <input type=\"number\" min=\"1\" max=\"100\" class=\"slm-input slm-availpct\" data-avail-pct=\"${esc(row.id)}\" value=\"${esc(pct)}\"${disabled} aria-label=\"Percent sold to reveal ${esc(row.label)}\" />\n <span class=\"slm-availpctlabel\">% sold</span>\n </div>`;\n }\n const badge = row.closed\n ? '<span class=\"slm-availbadge closed\">Closed</span>'\n : row.hidden ? '<span class=\"slm-availbadge hidden\">Hidden</span>' : '';\n const caret = row.kind === 'zone' ? `<span class=\"slm-availcaret\" aria-hidden=\"true\">${row.hidden ? '▸' : '▾'}</span>` : '';\n return `<div class=\"${cls}\">\n <div class=\"slm-availhead\">\n <span class=\"slm-availlabel\">${caret}${esc(row.label)}</span>\n ${badge}\n <span class=\"slm-availcount\">${row.seatCount.toLocaleString()}</span>\n ${control}\n </div>\n ${detail}\n </div>`;\n }\n\n private wireSectionRail(): void {\n const rail = this.els.rail;\n if (!rail) return;\n rail.querySelectorAll<HTMLSelectElement>('[data-avail-id]').forEach((select) => {\n select.addEventListener('change', () => this.setSectionMode(select.dataset.availId!, select.value as AvailabilityMode));\n });\n rail.querySelectorAll<HTMLInputElement>('[data-avail-reveal]').forEach((input) => {\n input.addEventListener('change', () => {\n const ms = new Date(input.value).getTime();\n if (Number.isFinite(ms)) this.setSectionRulePatch(input.dataset.availReveal!, { revealAt: ms });\n });\n });\n rail.querySelectorAll<HTMLInputElement>('[data-avail-pct]').forEach((input) => {\n input.addEventListener('change', () => {\n const pct = Math.max(1, Math.min(100, Number(input.value) || 0));\n this.setSectionRulePatch(input.dataset.availPct!, { thresholdPct: pct });\n });\n });\n }\n\n /** Change one row's availability mode. A zone rule subsumes its child section\n * rules, so those are dropped from the map (the zone window is the truth). */\n private setSectionMode(id: string, mode: AvailabilityMode): void {\n const row = this.buildSectionRows().rows.find((r) => r.id === id);\n const seatLabels = row?.seatLabels ?? this.availabilityRules[id]?.labels ?? [];\n const next = { ...this.availabilityRules };\n const rule = availabilityRuleForMode(mode, seatLabels, this.availabilityRules[id]);\n if (rule) next[id] = rule;\n else delete next[id];\n if (row?.kind === 'zone' && this.sectionsBase) {\n for (const s of this.sectionsBase.sections) if (s.zone === id) delete next[s.id];\n }\n void this.persistAvailability(next);\n }\n\n /** Edit a timed reveal time / threshold percent on an existing row rule. */\n private setSectionRulePatch(id: string, patch: Partial<AvailabilityRule>): void {\n const cur = this.availabilityRules[id];\n if (!cur) return;\n const row = this.buildSectionRows().rows.find((r) => r.id === id);\n const labels = row?.seatLabels ?? cur.labels ?? [];\n void this.persistAvailability({ ...this.availabilityRules, [id]: { ...cur, ...patch, labels } });\n }\n\n /** Optimistically adopt the new rules, then reconcile with the server-cleaned\n * map + effective hidden/closed sets. Rolls back the rules on failure. */\n private async persistAvailability(next: Record<string, AvailabilityRule>): Promise<void> {\n const prev = this.availabilityRules;\n this.availabilityRules = next;\n this.availabilitySaving = true;\n if (this.mode === 'sections') this.renderSectionsRail();\n try {\n const res = await this.withAuthRetry(() => this.api.setAvailability(this.key, next));\n this.availabilityRules = res.rules;\n this.effectiveHidden = new Set(res.hidden);\n this.effectiveClosed = new Set(this.closedIdsFromRules(res.rules));\n this.availabilitySaving = false;\n if (this.mode === 'sections') this.renderSectionsRail();\n this.applySectionCanvasTreatment();\n } catch (err) {\n this.availabilityRules = prev;\n this.availabilitySaving = false;\n if (this.mode === 'sections') this.renderSectionsRail();\n this.toastErr(\"Couldn't update availability. Try again.\");\n this.opts.onError?.(err);\n }\n }\n\n private paintLegend(t: SeatManagerTallies): void {\n if (!this.els.legend) return;\n this.els.legend.innerHTML = LEGEND.map((l) =>\n `<div class=\"slm-legrow\"><span class=\"slm-legdot\" style=\"background:${l.color}\"></span>\n <span class=\"slm-leglabel\">${l.label}</span><span class=\"slm-legcount\">${t[l.key].toLocaleString()}</span></div>`).join('');\n }\n\n private paintFeed(): void {\n if (!this.els.feed) return;\n if (!this.feed.length) { this.els.feed.innerHTML = `<div class=\"slm-empty\">No activity yet — it'll stream in live.</div>`; return; }\n const now = Date.now();\n const color: Record<DoStatus, string> = { free: '#6e7bff', held: '#f4b740', booked: '#22a06b', blocked: '#8b94ac' };\n this.els.feed.innerHTML = this.feed.map((a) => {\n const extra = a.count > 1 ? ` +${a.count - 1}` : '';\n const sections = a.sectionLabels ?? [];\n const sectionCopy = sections.length === 1 ? sections[0] : sections.length > 1 ? `${sections.length} sections` : '';\n return `<button type=\"button\" class=\"slm-feedrow\" data-feed-id=\"${esc(a.id)}\" title=\"Locate this activity on the map\">\n <span class=\"slm-feeddot\" style=\"background:${color[a.status]}\"></span>\n <span class=\"slm-feedtext\">${sectionCopy ? `<span class=\"slm-feedsection\">${esc(sectionCopy)}</span>` : ''}${a.count === 1 ? 'Seat' : 'Seats'} <b>${esc(a.label)}${extra}</b> ${esc(a.verb)}</span>\n <span class=\"slm-feedmeta\"><span class=\"slm-feedtime\">${relTime(a.at, now)}</span><span class=\"slm-feedlocate\">Locate</span></span>\n </button>`;\n }).join('');\n }\n\n private renderBlockRail(): void {\n const cats = this.doc?.categories ?? [];\n const catChips = cats.map((c) =>\n `<button class=\"slm-chip\" type=\"button\" data-cat=\"${esc(c.key)}\" aria-pressed=\"false\">\n <span class=\"dot\" style=\"background:${esc(c.color ?? '#6e7bff')}\"></span>\n <span>${esc(c.label ?? c.key)}</span>\n <span class=\"slm-chipcount\" data-cat-count>0</span>\n <span class=\"slm-chipcheck\" aria-hidden=\"true\">✓</span>\n </button>`).join('');\n const sectionField = this.sectionOptions.length\n ? `<div class=\"slm-field\"><label>Select a whole section</label>\n <select class=\"slm-select\" data-ref=\"section\"><option value=\"\">Choose a section…</option>\n ${this.sectionOptions.map((s) => `<option value=\"${esc(s.id)}\">${esc(s.label)}</option>`).join('')}</select></div>`\n : '';\n const blockedSectionOptions = this.sectionOptions.map((s) =>\n `<option value=\"${esc(s.id)}\">${esc(s.label)}</option>`).join('');\n this.els.rail.innerHTML = `\n <p class=\"slm-eyebrow\">Block & unblock</p>\n <p class=\"slm-hint\">Drag a box on the map to marquee-select, ⌘A for all, or pick a category/section. Booked and held inventory is never actionable here.</p>\n <div class=\"slm-selbar\" aria-live=\"polite\"><span class=\"slm-selnum\" data-ref=\"selnum\">0</span><span class=\"slm-sellabel\" data-ref=\"selmeta\">selected</span></div>\n <div class=\"slm-row\">\n <button class=\"slm-btn\" data-ref=\"doblock\" disabled>Block</button>\n <button class=\"slm-btn ghost\" data-ref=\"dounblock\" disabled>Put back on sale</button>\n </div>\n <div class=\"slm-row\">\n <button class=\"slm-btn ghost\" data-ref=\"selall\">Select all</button>\n <button class=\"slm-btn ghost\" data-ref=\"clearsel\">Clear</button>\n </div>\n <p class=\"slm-eyebrow\" style=\"margin-top:8px\">Select by category</p>\n <p class=\"slm-selecthelp\">Choose one or more. A checked category is selected; click it again to remove it.</p>\n <div class=\"slm-chiprow\">${catChips || '<span class=\"slm-empty\">No categories.</span>'}</div>\n ${sectionField}\n <div class=\"slm-field\">\n <label>Auto-release blocks at (optional)</label>\n <input type=\"datetime-local\" class=\"slm-input\" data-ref=\"release\" />\n <p class=\"slm-note\" data-ref=\"releasenote\">Leave empty to block permanently.</p>\n </div>\n <section class=\"slm-blocked\" aria-labelledby=\"slm-blocked-title\">\n <div class=\"slm-blockedhead\">\n <p class=\"slm-eyebrow\" id=\"slm-blocked-title\">Blocked inventory</p>\n <span class=\"slm-blockedtotal\"><b data-ref=\"blockedcount\">0</b> out of sale</span>\n </div>\n <p class=\"slm-selecthelp\">Find blocked seats, select only the ones you need, then use “Put back on sale”.</p>\n <div class=\"slm-blockedtools\">\n <input type=\"search\" class=\"slm-input\" data-ref=\"blockedsearch\" placeholder=\"Find seat, row or category\" aria-label=\"Search blocked seats\" />\n <select class=\"slm-select\" data-ref=\"blockedsection\" aria-label=\"Filter blocked seats by section\">\n <option value=\"\">All sections</option>${blockedSectionOptions}\n </select>\n </div>\n <div class=\"slm-blockedsummary\">\n <span data-ref=\"blockedshowing\">No blocked seats</span>\n <button type=\"button\" class=\"slm-linkbtn\" data-ref=\"selblocked\" disabled>Select results</button>\n </div>\n <div class=\"slm-blockedlist\" data-ref=\"blockedlist\"></div>\n </section>\n <div class=\"slm-field\">\n <button class=\"slm-btn ghost\" data-ref=\"markall\" style=\"width:100%\" disabled>Put all blocked seats on sale</button>\n <p class=\"slm-note slm-allnote\" data-ref=\"markallnote\">For a full reset only. You will be asked to confirm.</p>\n </div>\n `;\n const r = (n: string) => this.els.rail.querySelector(`[data-ref=\"${n}\"]`) as HTMLElement;\n this.els.selnum = r('selnum'); this.els.doblock = r('doblock'); this.els.dounblock = r('dounblock');\n this.els.selmeta = r('selmeta'); this.els.blockedcount = r('blockedcount');\n this.els.blockedshowing = r('blockedshowing'); this.els.blockedlist = r('blockedlist');\n this.els.selblocked = r('selblocked'); this.els.markall = r('markall'); this.els.markallnote = r('markallnote');\n r('doblock').addEventListener('click', () => void this.block());\n r('dounblock').addEventListener('click', () => void this.unblock());\n r('selall').addEventListener('click', () => this.selectAll());\n r('clearsel').addEventListener('click', () => this.clearSelection());\n r('markall').addEventListener('click', () => this.confirmUnblockAll());\n this.els.rail.querySelectorAll('[data-cat]').forEach((b) =>\n b.addEventListener('click', () => this.toggleCategory((b as HTMLElement).dataset.cat!)));\n const sectionSel = this.els.rail.querySelector('[data-ref=\"section\"]') as HTMLSelectElement | null;\n sectionSel?.addEventListener('change', () => { if (sectionSel.value) { this.selectSection(sectionSel.value); sectionSel.value = ''; } });\n const blockedSearch = r('blockedsearch') as HTMLInputElement;\n const blockedSection = r('blockedsection') as HTMLSelectElement;\n blockedSearch.value = this.blockedQuery;\n blockedSection.value = this.blockedSection;\n blockedSearch.addEventListener('input', () => {\n this.blockedQuery = blockedSearch.value;\n this.blockedResultLimit = 100;\n this.paintBlockedInventory();\n });\n blockedSection.addEventListener('change', () => {\n this.blockedSection = blockedSection.value;\n this.blockedResultLimit = 100;\n this.paintBlockedInventory();\n });\n r('selblocked').addEventListener('click', () => {\n this.toggleLabels(this.filteredBlockedSeats().map((seat) => seat.label));\n });\n r('blockedlist').addEventListener('click', (event) => {\n const target = event.target as HTMLElement;\n const seatButton = target.closest<HTMLElement>('[data-blocked-label]');\n if (seatButton?.dataset.blockedLabel) this.toggleLabels([seatButton.dataset.blockedLabel]);\n else if (target.closest('[data-blocked-more]')) {\n this.blockedResultLimit += 100;\n this.paintBlockedInventory();\n }\n });\n const rel = r('release') as HTMLInputElement;\n rel.addEventListener('change', () => {\n const ms = rel.value ? new Date(rel.value).getTime() : NaN;\n this.releaseAt = Number.isFinite(ms) && ms > Date.now() ? ms : null;\n const note = r('releasenote');\n note.textContent = this.releaseAt\n ? `New blocks auto-release ${new Date(this.releaseAt).toLocaleString()}.`\n : rel.value ? 'Pick a time in the future.' : 'Leave empty to block permanently.';\n });\n this.paintSelBar(this.getSelection());\n }\n\n private toggleCategory(catKey: string): void {\n const labels: string[] = [];\n for (const [label, seat] of this.labelToSeat.entries()) {\n if (seat.categoryKey === catKey && this.isBlockSelectable(label)) labels.push(label);\n }\n this.toggleLabels(labels);\n }\n\n /** A category/filter is a real toggle: add the missing seats, or remove the\n * whole group when every eligible seat in it is already selected. */\n private toggleLabels(labels: string[]): void {\n if (!this.renderer) return;\n const eligible = labels.filter((label) => this.labelToSeat.has(label) && this.isBlockSelectable(label));\n if (!eligible.length) return;\n const selected = new Set(this.selectionLabels());\n const allSelected = eligible.every((label) => selected.has(label));\n if (allSelected) {\n const ids = eligible.map((label) => this.labelToId.get(label)).filter((id): id is string => Boolean(id));\n this.renderer.deselect(ids);\n } else {\n this.renderer.selectByLabels(eligible);\n }\n this.syncSelection();\n }\n\n private isBlockSelectable(label: string): boolean {\n const status = this.status.get(label) ?? 'free';\n return status === 'free' || status === 'blocked';\n }\n\n private paintSelBar(seats: ExpandedSeat[]): void {\n if (!this.els.selnum) return;\n this.els.selnum.textContent = seats.length.toLocaleString();\n const freeCount = seats.filter((s) => (this.status.get(s.label) ?? 'free') === 'free').length;\n const blockedCount = seats.filter((s) => this.status.get(s.label) === 'blocked').length;\n this.els.selmeta.textContent = seats.length\n ? `${freeCount.toLocaleString()} available · ${blockedCount.toLocaleString()} blocked`\n : 'selected';\n const blockButton = this.els.doblock as HTMLButtonElement;\n const unblockButton = this.els.dounblock as HTMLButtonElement;\n blockButton.disabled = freeCount === 0;\n unblockButton.disabled = blockedCount === 0;\n blockButton.textContent = freeCount ? `Block ${freeCount.toLocaleString()}` : 'Block selected';\n unblockButton.textContent = blockedCount ? `Put ${blockedCount.toLocaleString()} on sale` : 'Put back on sale';\n this.paintCategoryControls(seats);\n this.paintBlockedInventory();\n }\n\n private paintCategoryControls(seats: ExpandedSeat[]): void {\n const selected = new Set(seats.map((seat) => seat.label));\n this.els.rail?.querySelectorAll<HTMLButtonElement>('[data-cat]').forEach((button) => {\n const catKey = button.dataset.cat;\n const labels: string[] = [];\n for (const [label, seat] of this.labelToSeat.entries()) {\n if (seat.categoryKey === catKey && this.isBlockSelectable(label)) labels.push(label);\n }\n const picked = labels.filter((label) => selected.has(label)).length;\n const full = labels.length > 0 && picked === labels.length;\n const partial = picked > 0 && !full;\n button.disabled = labels.length === 0;\n button.classList.toggle('on', full);\n button.classList.toggle('partial', partial);\n button.setAttribute('aria-pressed', full ? 'true' : partial ? 'mixed' : 'false');\n button.setAttribute('title', full\n ? `Remove all ${labels.length.toLocaleString()} seats in this category from the selection`\n : partial\n ? `Select the remaining ${(labels.length - picked).toLocaleString()} seats in this category`\n : `Select all ${labels.length.toLocaleString()} seats in this category`);\n const count = button.querySelector<HTMLElement>('[data-cat-count]');\n if (count) count.textContent = picked ? `${picked.toLocaleString()}/${labels.length.toLocaleString()}` : labels.length.toLocaleString();\n });\n }\n\n private filteredBlockedSeats(): ExpandedSeat[] {\n const query = this.blockedQuery.trim().toLocaleLowerCase();\n const seats: ExpandedSeat[] = [];\n for (const [label, seat] of this.labelToSeat.entries()) {\n if (this.status.get(label) !== 'blocked') continue;\n const sectionId = this.sectionByObject.get(seat.rowId) ?? UNGROUPED_ID;\n if (this.blockedSection && sectionId !== this.blockedSection) continue;\n if (query) {\n const category = this.doc?.categories.find((item) => item.key === seat.categoryKey)?.label ?? seat.categoryKey;\n const section = this.sectionLabelById.get(sectionId) ?? 'Other seats';\n const object = this.doc?.objects.find((item) => item.id === seat.rowId);\n const objectLabel = object?.type === 'row' || object?.type === 'table' ? object.label : '';\n const haystack = `${label} ${category} ${section} ${objectLabel}`.toLocaleLowerCase();\n if (!haystack.includes(query)) continue;\n }\n seats.push(seat);\n }\n return seats.sort((a, b) => a.label.localeCompare(b.label, undefined, { numeric: true, sensitivity: 'base' }));\n }\n\n private paintBlockedInventory(): void {\n if (!this.els.blockedlist) return;\n const allBlocked = [...this.status.entries()].filter(([, status]) => status === 'blocked').length;\n const filtered = this.filteredBlockedSeats();\n const visible = filtered.slice(0, this.blockedResultLimit);\n const selected = new Set(this.selectionLabels());\n const selectedResults = filtered.filter((seat) => selected.has(seat.label)).length;\n const allResultsSelected = filtered.length > 0 && selectedResults === filtered.length;\n this.els.blockedcount.textContent = allBlocked.toLocaleString();\n this.els.blockedshowing.textContent = filtered.length\n ? `Showing ${visible.length.toLocaleString()} of ${filtered.length.toLocaleString()}`\n : allBlocked ? 'No matches' : 'No blocked seats';\n const selectResults = this.els.selblocked as HTMLButtonElement;\n selectResults.disabled = filtered.length === 0;\n selectResults.textContent = allResultsSelected\n ? `Remove ${filtered.length.toLocaleString()} results`\n : `Select ${filtered.length.toLocaleString()} results`;\n\n this.els.blockedlist.innerHTML = visible.length ? visible.map((seat) => {\n const sectionId = this.sectionByObject.get(seat.rowId) ?? UNGROUPED_ID;\n const section = this.sectionLabelById.get(sectionId) ?? 'Other seats';\n const category = this.doc?.categories.find((item) => item.key === seat.categoryKey)?.label ?? seat.categoryKey;\n const isSelected = selected.has(seat.label);\n return `<button type=\"button\" class=\"slm-blockeditem${isSelected ? ' on' : ''}\" data-blocked-label=\"${esc(seat.label)}\" aria-pressed=\"${isSelected}\">\n <span class=\"slm-blockedcheck\" aria-hidden=\"true\">✓</span>\n <span class=\"slm-blockedcopy\"><span class=\"slm-blockedlabel\">${esc(seat.label)}</span>\n <span class=\"slm-blockedmeta\">${esc(section)} · ${esc(category)}</span></span>\n </button>`;\n }).join('') + (filtered.length > visible.length\n ? `<button type=\"button\" class=\"slm-blockedmore\" data-blocked-more>Show 100 more</button>` : '')\n : `<div class=\"slm-blockedempty\">${allBlocked\n ? 'No blocked seats match this search or section.'\n : 'No seats are blocked. Newly blocked seats will appear here.'}</div>`;\n\n const markAll = this.els.markall as HTMLButtonElement;\n const armed = markAll.dataset.confirm === 'true';\n markAll.disabled = allBlocked === 0;\n markAll.textContent = armed\n ? `Confirm: put all ${allBlocked.toLocaleString()} on sale`\n : `Put all ${allBlocked.toLocaleString()} blocked seats on sale`;\n }\n\n private confirmUnblockAll(): void {\n const button = this.els.markall as HTMLButtonElement;\n if (!button || button.disabled) return;\n if (button.dataset.confirm === 'true') {\n this.resetUnblockAllConfirm();\n void this.unblockAll();\n return;\n }\n button.dataset.confirm = 'true';\n button.classList.add('danger');\n this.els.markallnote.textContent = 'This changes every blocked seat. Click the red button again to confirm.';\n this.paintBlockedInventory();\n if (this.unblockAllConfirmTimer) clearTimeout(this.unblockAllConfirmTimer);\n this.unblockAllConfirmTimer = setTimeout(() => this.resetUnblockAllConfirm(), 6000);\n }\n\n private resetUnblockAllConfirm(): void {\n if (this.unblockAllConfirmTimer) clearTimeout(this.unblockAllConfirmTimer);\n this.unblockAllConfirmTimer = null;\n const button = this.els.markall as HTMLButtonElement | undefined;\n if (!button) return;\n delete button.dataset.confirm;\n button.classList.remove('danger');\n if (this.els.markallnote) this.els.markallnote.textContent = 'For a full reset only. You will be asked to confirm.';\n this.paintBlockedInventory();\n }\n\n // ---- toast / done / fail --------------------------------------------------\n\n private done(action: SeatManagerActionResult['action'], labels: string[], msg: string): void {\n this.toastOk(msg);\n if (labels.length) {\n const activity = action === 'block'\n ? this.pushActivity(labels, 'blocked', 'blocked')\n : action === 'unblock' || action === 'unblockAll'\n ? this.pushActivity(labels, 'unblocked', 'free')\n : action === 'cancelBooking'\n ? this.pushActivity(labels, 'cancelled', 'free')\n : null;\n if (activity) this.paintSpatialActivity(activity);\n }\n if (action !== 'setHoldTtl') this.scheduleRevenueRefresh(0);\n this.opts.onActionComplete?.({ action, labels, count: labels.length });\n }\n\n private toastOk(msg: string): void { this.toast(msg, 'ok'); }\n private toastErr(msg: string): void { this.toast(msg, 'err'); }\n\n private toast(msg: string, kind: 'ok' | 'err'): void {\n const el = this.els.toast;\n if (!el) return;\n el.textContent = msg;\n el.className = `slm-toast on ${kind}`;\n if (this.toastTimer) clearTimeout(this.toastTimer);\n this.toastTimer = setTimeout(() => { el.className = 'slm-toast'; }, 3200);\n }\n\n private fail(err: unknown): void {\n this.opts.onError?.(err);\n if (this.els.rail) this.els.rail.innerHTML = `<div class=\"slm-empty\">Couldn't load this event. Check the event key and token.</div>`;\n }\n}\n","/**\n * Organizer manage-surface client for workers/api (the `/v1/events/:key/*`\n * inventory routes + the public realtime channel). Companion to api.ts (the\n * buyer `/pub/*` client) — kept separate because the manage surface is\n * token-authed (Bearer) and cross-origin from the CMS:\n *\n * - Writes + reports send `Authorization: Bearer <token>` where the token is\n * a short-lived, event-scoped organizer manage token (`mse_…`, minted by\n * NestJS) OR a tenant secret key (`sk_…`). Both are accepted by the worker's\n * `eitherAuth` on block / unblock / unblock-all / unbook / hold-ttl / report\n * / log. The Authorization header also exempts the call from the worker's\n * cookie-CSRF gate, so no extra client header is needed.\n * - `credentials: 'omit'` — there is no session cookie; the CMS runs\n * cross-origin. The worker's credentialed CORS still echoes the CMS origin.\n * - Realtime read (`/pub/events/:key/subscribe`, `/objects`, `/chart`) is\n * PUBLIC (wildcard CORS, no token) — the live board subscribes with no auth.\n *\n * `box-book` is intentionally omitted for M1 (box office ships in M2, and the\n * route is still session-only server-side).\n */\nimport type { AvailabilityRule, ChartDoc } from '@seatlayer/core';\n\nexport type { AvailabilityRule } from '@seatlayer/core';\n\nexport class ManageApiError extends Error {\n status: number;\n code?: string;\n /** Present when a block/unbook 409s because seats were just taken. */\n conflicts?: { label: string; reason?: string }[];\n\n constructor(status: number, message: string, code?: string, conflicts?: { label: string; reason?: string }[]) {\n super(message);\n this.name = 'ManageApiError';\n this.status = status;\n this.code = code;\n this.conflicts = conflicts;\n }\n}\n\nexport interface ReportByStatus {\n free: number;\n held: number;\n booked: number;\n not_for_sale: number;\n}\n\nexport interface ReportCategoryRow {\n category: string;\n total: number;\n free: number;\n held: number;\n booked: number;\n not_for_sale: number;\n /** Exact sum of booked unit_price snapshots, in major currency units. */\n bookedRevenue: number;\n}\n\nexport interface ReportCategoryMeta {\n key: string;\n label: string;\n color: string;\n price: number;\n}\n\nexport interface ReportResult {\n report: { byStatus: ReportByStatus; byCategory: ReportCategoryRow[]; bySection?: ControlRoomSectionMetric[] };\n event: { key: string; name: string; seatTotal: number; currency?: string };\n categories: ReportCategoryMeta[];\n}\n\nexport interface ControlRoomSectionMetric {\n sectionId: string;\n sectionLabel: string;\n zoneId: string | null;\n total: number;\n free: number;\n held: number;\n booked: number;\n not_for_sale: number;\n bookedRevenue: number;\n}\n\n/** Recent seat-state change safe for an event:view control-room grant. Full\n * audit references remain available only through the event:reports log API. */\nexport interface ControlRoomActivityEntry {\n id: number;\n at: number;\n action: string;\n labels: string[];\n}\n\nexport interface ControlRoomSnapshot {\n version: number;\n currency: string;\n totals: { free: number; held: number; booked: number; blocked: number };\n revenue: { gross: number; bySection: ControlRoomSectionMetric[] };\n velocity: {\n windowMinutes: number;\n bySection: Array<{\n sectionId: string;\n netBooked: number;\n grossRevenue: number;\n previousNetBooked: number;\n trend: 'rising' | 'steady' | 'cooling';\n }>;\n };\n presence: { shoppingSessions: number; activeHolds: number };\n /** Present on workers that support reload-safe activity hydration. */\n activity?: ControlRoomActivityEntry[];\n event: { key: string; name: string; seatTotal: number; currency?: string };\n}\n\nexport interface LogEntry {\n id: number;\n at: number;\n action: string;\n labels: string[];\n ref: string | null;\n}\n\nexport interface LogPage {\n entries: LogEntry[];\n nextBefore: number | null;\n}\n\nexport interface PubObjectsResult {\n /** Every non-free seat's status keyed by label (free seats omitted). */\n seats: Record<string, string>;\n hidden?: string[];\n closed?: string[];\n updatedAt: number;\n}\n\nexport interface PubChartResult {\n event: {\n key: string;\n name: string;\n status?: string;\n venue?: string | null;\n startsAt?: number | null;\n currency?: string;\n mode?: string;\n };\n doc: ChartDoc;\n}\n\nasync function parse<T>(res: Response): Promise<T> {\n const isJson = (res.headers.get('content-type') ?? '').includes('application/json');\n const data = isJson ? await res.json().catch(() => null) : null;\n if (!res.ok) {\n const err = data as { error?: string; code?: string; conflicts?: { label: string; reason?: string }[] } | null;\n throw new ManageApiError(res.status, err?.error ?? `request_failed_${res.status}`, err?.code, err?.conflicts);\n }\n return data as T;\n}\n\n/**\n * Bound to one apiBase + one event-scoped token. Rebuild (or `setToken`) when a\n * token is re-minted on 401.\n */\nexport class ManageApi {\n private base: string;\n private token: string;\n\n constructor(apiBase: string, token: string) {\n this.base = apiBase.replace(/\\/+$/, '');\n this.token = token;\n }\n\n /** Swap the Bearer token in place (SeatManager re-mints on 401). */\n setToken(token: string): void {\n this.token = token;\n }\n\n private auth<T>(path: string, init: { method?: 'GET' | 'POST'; body?: unknown } = {}): Promise<T> {\n const method = init.method ?? 'GET';\n const headers: Record<string, string> = { Authorization: `Bearer ${this.token}` };\n let body: string | undefined;\n if (init.body !== undefined) {\n headers['Content-Type'] = 'application/json';\n body = JSON.stringify(init.body);\n }\n return fetch(`${this.base}${path}`, { method, headers, body, credentials: 'omit' }).then((r) => parse<T>(r));\n }\n\n private pub<T>(path: string): Promise<T> {\n return fetch(`${this.base}${path}`, { credentials: 'omit' }).then((r) => parse<T>(r));\n }\n\n // ---- realtime read (public, no token) ----\n\n chart(key: string): Promise<PubChartResult> {\n return this.pub(`/pub/events/${encodeURIComponent(key)}/chart`);\n }\n\n objects(key: string): Promise<PubObjectsResult> {\n return this.pub(`/pub/events/${encodeURIComponent(key)}/objects`);\n }\n\n socketUrl(key: string): string {\n return `${this.base.replace(/^http/, 'ws')}/pub/events/${encodeURIComponent(key)}/subscribe?surface=manager`;\n }\n\n // ---- inventory writes (token) ----\n\n /** Take FREE seats off sale in one batched call. Optional `releaseAt` (epoch\n * ms, future) auto-returns them to sale; `reason` tags the block (M3 uses it).\n * Throws ManageApiError 409 (conflicts) if any seat was just taken. */\n block(\n key: string,\n labels: string[],\n opts: { releaseAt?: number; reason?: string } = {},\n ): Promise<{ ok: true; blocked: string[] }> {\n const body: Record<string, unknown> = { labels };\n if (typeof opts.releaseAt === 'number') body.releaseAt = opts.releaseAt;\n if (opts.reason) body.reason = opts.reason;\n return this.auth(`/v1/events/${encodeURIComponent(key)}/block`, { method: 'POST', body });\n }\n\n /** Return specific blocked seats to sale (one batched call). */\n unblock(key: string, labels: string[]): Promise<{ ok: true; unblocked: string[] }> {\n return this.auth(`/v1/events/${encodeURIComponent(key)}/unblock`, { method: 'POST', body: { labels } });\n }\n\n /** Return every blocked seat to sale; resolves with the freed count. */\n unblockAll(key: string): Promise<{ ok: true; freed: number }> {\n return this.auth(`/v1/events/${encodeURIComponent(key)}/unblock-all`, { method: 'POST' });\n }\n\n /** Cancel bookings — return BOOKED seats to free (credit not refunded).\n * Guarded by the original booking reference. */\n unbook(key: string, labels: string[], bookingRef: string): Promise<{ ok: true; unbooked: string[] }> {\n return this.auth(`/v1/events/${encodeURIComponent(key)}/unbook`, { method: 'POST', body: { labels, bookingRef } });\n }\n\n /** Set (ms, clamped 1–60 min server-side) or clear (null) the hold TTL. */\n setHoldTtl(key: string, holdTtlMs: number | null): Promise<{ ok: true; holdTtlMs: number | null }> {\n return this.auth(`/v1/events/${encodeURIComponent(key)}/hold-ttl`, { method: 'POST', body: { holdTtlMs } });\n }\n\n // ---- availability windows (token) ----\n\n /** The organizer's current per section/zone availability windows (needs\n * `event:view`). Ids absent from `rules` are open / on sale. */\n availability(key: string): Promise<{ rules: Record<string, AvailabilityRule> }> {\n return this.auth(`/v1/events/${encodeURIComponent(key)}/availability`);\n }\n\n /** Replace the availability windows for a set of section/zone ids (needs\n * `event:block`). Ids absent from `rules` become open / on sale; a zone rule\n * cascades to its sections. The worker derives each id's seat labels, so\n * `labels` on the sent rules is best-effort. Resolves with the authoritative\n * effective `hidden` set (a due rule may fire at once) and the server-cleaned\n * `rules` map (fired timed/threshold windows dropped). */\n setAvailability(\n key: string,\n rules: Record<string, AvailabilityRule>,\n ): Promise<{ ok: true; hidden: string[]; rules: Record<string, AvailabilityRule> }> {\n return this.auth(`/v1/events/${encodeURIComponent(key)}/availability`, { method: 'POST', body: { rules } });\n }\n\n // ---- reports (token) ----\n\n report(key: string): Promise<ReportResult> {\n return this.auth(`/v1/events/${encodeURIComponent(key)}/report`);\n }\n\n controlRoom(key: string, windowMinutes = 15): Promise<ControlRoomSnapshot> {\n return this.auth(`/v1/events/${encodeURIComponent(key)}/control-room?window=${windowMinutes}`);\n }\n\n log(key: string, opts: { limit?: number; before?: number } = {}): Promise<LogPage> {\n const params = new URLSearchParams();\n if (opts.limit != null) params.set('limit', String(opts.limit));\n if (opts.before != null) params.set('before', String(opts.before));\n const qs = params.toString();\n return this.auth(`/v1/events/${encodeURIComponent(key)}/log${qs ? `?${qs}` : ''}`);\n }\n\n /** CSV report as a Blob (Bearer auth can't ride a plain <a href>). Host builds\n * an object URL for download. */\n async reportCsv(key: string): Promise<Blob> {\n const res = await fetch(`${this.base}/v1/events/${encodeURIComponent(key)}/report.csv`, {\n headers: { Authorization: `Bearer ${this.token}` },\n credentials: 'omit',\n });\n if (!res.ok) throw new ManageApiError(res.status, `request_failed_${res.status}`);\n return res.blob();\n }\n}\n"],"mappings":"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;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA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","names":["resolveContainer","target","PickerController","loadLocale","setStringOverrides","t","DEFAULT_API_BASE","DEFAULT_MAX_SELECTION","resolveContainer","PickerController","t","loadLocale","setStringOverrides","pano","canView","esc","expandChart","resolveContainer","DEFAULT_API_BASE","STYLE_ID","CSS","t","expandChart","request","window"]}
|