@seatlayer/js 0.52.0 → 0.53.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/LICENSE +16 -17
- package/README.md +2 -2
- package/dist/channelsMode-BX7s9bUl.d.cts +2241 -0
- package/dist/channelsMode-BX7s9bUl.d.ts +2241 -0
- package/dist/channelsMode-RUNPEHKD.js +1 -0
- package/dist/chunk-7F6RSJRL.js +695 -0
- package/dist/chunk-OSZ7DOEH.js +1 -0
- package/dist/hostedCheckout-3NTOVIZG.js +35 -0
- package/dist/index.cjs +19 -7750
- package/dist/index.d.cts +162 -106
- package/dist/index.d.ts +162 -106
- package/dist/index.js +18 -7375
- package/dist/manager.cjs +298 -5656
- package/dist/manager.d.cts +8 -2261
- package/dist/manager.d.ts +8 -2261
- package/dist/manager.js +71 -2418
- package/package.json +3 -8
- package/dist/channelsMode-S4GEWCWS.js +0 -12
- package/dist/channelsMode-S4GEWCWS.js.map +0 -1
- package/dist/chunk-5URCWBHM.js +0 -3683
- package/dist/chunk-5URCWBHM.js.map +0 -1
- package/dist/chunk-HMLY7DHA.js +0 -16
- package/dist/chunk-HMLY7DHA.js.map +0 -1
- package/dist/hostedCheckout-GVS6UKYA.js +0 -370
- package/dist/hostedCheckout-GVS6UKYA.js.map +0 -1
- package/dist/index.cjs.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/manager.cjs.map +0 -1
- package/dist/manager.js.map +0 -1
package/dist/manager.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/SeatManager.ts","../src/manageAssets.ts"],"sourcesContent":["/**\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 + configured booked value, 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: organizer chart/media, inventory, realtime and reports all carry a\n * short-lived event-scoped browser grant (`mse_…`) via {@link ManageApi}.\n * Tenant secret keys are unsupported in this browser surface, and organizer\n * authority is never downgraded to buyer `/pub`.\n */\nimport {\n SeatmapRenderer,\n expandChart,\n computeSections,\n gaAreasOf,\n gaUnitLabels,\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';\n// TYPE-ONLY, and it has to stay that way. Channels mode is a ~95 KB (minified)\n// sub-app that most cockpit visits never open, so it is reached through\n// `import('./channelsMode')` in `ensureChannels()`. A single value import here\n// would fold the whole thing back into first paint with nothing failing to say\n// so. Its stylesheet travels with it too: `CHANNELS_CSS` is injected by the\n// lazy load rather than concatenated into `MANAGER_CSS`.\nimport type {\n ChannelsMode, ChannelsCapabilities, ChannelsRowView,\n} from './channelsMode';\nimport type { ChannelSeatStatus } from './channelPlan';\nimport {\n ManageApi,\n ManageApiError,\n type ControlRoomActivityEntry,\n type ControlRoomSnapshot,\n type LogEntry,\n type ReportResult,\n} from './manageApi';\nimport { OrganizerAssetObjectUrls } from './manageAssets';\n\nexport type SeatManagerMode = 'view' | 'inspect' | 'block' | 'sections' | 'channels';\n\n/** Short-lived, event-scoped browser credential minted by a trusted backend. */\nexport type EventScopedManageToken = `mse_${string}`;\n\n/**\n * Capabilities the cockpit's token was minted with. Channels mode is gated on\n * these and fails CLOSED: no `event:channels:view` ⇒ no Channels pill at all;\n * view without `event:channels:manage` ⇒ read-only inspection with every\n * mutation control absent, not merely disabled.\n */\nexport type SeatManagerCapability =\n | 'event:view' | 'event:block' | 'event:cancel' | 'event:reports'\n | 'event:channels:view' | 'event:channels:manage';\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 bookedValue: number;\n /** @deprecated Use `bookedValue`. */\n grossRevenue: number;\n /** Booked value is never reconstructed from the chart's current list price. */\n bookedValueStatus: 'loading' | 'current' | 'stale';\n /** @deprecated Use `bookedValueStatus`. */\n revenueStatus: 'loading' | 'current' | 'stale';\n /** ISO-4217 currency for `bookedValue`. */\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 /**\n * Short-lived, event-scoped `mse_…` browser grant minted by your backend.\n * Tenant secret keys are unsupported in SeatManager and must stay server-side.\n */\n token: EventScopedManageToken;\n /** Absolute token expiry (epoch ms). Enables proactive in-place rotation. */\n tokenExpiresAt?: number;\n /** Initial mode. Default 'view'. */\n mode?: SeatManagerMode;\n /**\n * The capability set this token was minted with. Supply it whenever you mint\n * an `mse_…` grant — it is the only way the widget can know a delegated token\n * carries `event:channels:manage`, and without it Channels mode stays\n * read-only (fail-closed).\n */\n capabilities?: SeatManagerCapability[] | string[];\n /** ISO-4217 fallback currency for configured booked value (chart/event 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: EventScopedManageToken; 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 /**\n * The realtime link connected or dropped, with the moment the numbers on\n * screen were last known good.\n *\n * A host embedding this cockpit renders its own chrome around it, and until\n * now had no way to know the board had gone stale: the manager tracked the\n * drop internally (its own LIVE/RECONNECTING pill) and told nobody. A host\n * that polls on a timer and pauses while the tab is hidden therefore showed\n * arbitrarily old numbers that looked exactly like fresh ones.\n */\n onConnectionChange?: (state: SeatManagerConnection) => void;\n onError?: (err: unknown) => void;\n}\n\n/** Realtime link state, as reported to the embedding host. */\nexport interface SeatManagerConnection {\n /** `live` while the socket is open; `reconnecting` from drop until reopen. */\n status: 'live' | 'reconnecting';\n /**\n * `Date.now()` of the last snapshot or delta accepted from the server, or\n * null before the first one. This is the honest \"as of\" for whatever the host\n * is displaying — NOT the time the connection dropped, which is later and\n * would overstate freshness.\n */\n lastMessageAt: number | null;\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\nfunction assertBrowserManageToken(token: string): asserts token is EventScopedManageToken {\n if (!token.startsWith('mse_')) {\n throw new Error(\n 'seatmanager: token must be a short-lived event-scoped mse_ grant minted by your backend; '\n + 'tenant secret keys are unsupported in browsers',\n );\n }\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';\n/** Channels mode's stylesheet — injected with its lazy module, not before. */\nconst CHANNELS_STYLE_ID = 'seatlayer-manager-channels-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\n/** Exported so the motion contract can be asserted without a real browser —\n * see `SeatManagerMotion.test.ts`. Not part of the public package surface.\n * `@sl-css` opts it into build-time minification (cdn/minifyCssLiterals.ts). */\nexport const MANAGER_CSS = /* @sl-css */ `\n/* The floor was 480px, which trapped the cockpit in any host shorter than that:\n every ancestor here is overflow:hidden, so the bottom of the rail (Create\n channel, Show archived) was rendered but clipped away by the host and could\n not be reached by scrolling anything. 320px still keeps an unsized host from\n collapsing to the top bar, and the rail scrolls to its full content below. */\n.slm{position:relative;display:flex;flex-direction:column;width:100%;height:100%;min-height:320px;overflow:hidden;\n background:var(--slm-bg);color:var(--slm-text);font-family:var(--slm-font);border-radius:var(--slm-radius);\n /* Motion tokens (motion-system §2), declared by the cockpit ROOT rather than\n borrowed from CHANNELS_CSS. The base cockpit animates whether or not\n Channels mode is in use, so owning its own tokens is what stops a token\n edit from silently changing only half the surface. Channels mode declares\n the identical values so an embed of it stays self-contained. */\n --slm-mo-instant:80ms;--slm-mo-quick:140ms;--slm-mo-base:200ms;--slm-mo-slow:320ms;--slm-mo-ambient:2000ms;\n --slm-mo-out:cubic-bezier(.2,.8,.2,1);--slm-mo-in-out:cubic-bezier(.4,0,.2,1);--slm-mo-exit:cubic-bezier(.4,0,1,1);\n --slm-mo-spring:cubic-bezier(.34,1.3,.64,1)}\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/* FOUR columns, because the bar has four children: modes, the tools\n select, the live badge, and the actions. With three, the actions had no\n column and fell to an implicit second row — where justify-self:end\n aligned them to the right of column ONE, so they read as indented\n rather than as either edge. The 1fr moves to the last column so the\n actions sit hard right and the live badge hugs its own text instead of\n stretching across the free space.\n\n .slm.compact still spans the actions full-width on its own row below;\n that wrap is deliberate and is why this looked intermittent — the same\n broken layout had one designed cause and one accidental one. */\n.slm-bar{display:grid;grid-template-columns:auto 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);\n animation:slm-pulse var(--slm-mo-ambient) 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/* The one playful moment this surface is allowed (§2 --mo-spring). It ran at\n .58s against a 200ms catalog, which read as a different design language from\n the dashboard tile it mirrors; Channels mode's own count bump is the same\n pattern and must stay in step with it. */\n.slm-kpi.changed b{animation:slm-kpi-bump var(--slm-mo-base) var(--slm-mo-spring)}\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;\n transition:opacity var(--slm-mo-base) var(--slm-mo-out)}\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 var(--slm-mo-quick) var(--slm-mo-out),transform var(--slm-mo-base) var(--slm-mo-out);\n 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;min-height:0;overflow-y:auto;overscroll-behavior:contain;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;\n animation:slm-in var(--slm-mo-quick) var(--slm-mo-out)}\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;overscroll-behavior:contain;border:1px solid var(--slm-line);\n 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;\n transition:opacity var(--slm-mo-base) var(--slm-mo-out);\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;\n background:var(--slm-surface)!important;text-align:left!important;\n transition:border-color var(--slm-mo-quick) var(--slm-mo-out),transform var(--slm-mo-quick) var(--slm-mo-out)}\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);\n transition:border-color var(--slm-mo-quick) var(--slm-mo-out),opacity var(--slm-mo-quick) var(--slm-mo-out)}\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=\"viewing-map\"],.slm.compact .slm-kpi[data-kpi=\"active-holds\"],\n.slm.compact .slm-kpi[data-kpi=\"booked-pct\"],.slm.compact .slm-kpi[data-kpi=\"booked-value\"]{display:none}\n/* Reduced motion, as a BLANKET over the cockpit subtree rather than a list of\n selectors. The list this replaces named four animations and two transitions,\n and had silently fallen behind the stylesheet: the zoom hint, the toast and\n the availability rows all still animated for a user who had asked the OS for\n none. An enumerated list has to be edited every time a rule is added, and\n nothing fails when it isn't — so it drifts. This cannot.\n\n Motion is removed, never the information it carried: Channels mode's own\n block substitutes static outlines for its shake and success states, and it\n stays authoritative for those. No JS here waits on animationend or\n transitionend, so cutting them outright strands no state. */\n@media (prefers-reduced-motion:reduce){\n .slm,.slm *,.slm *::before,.slm *::after{\n animation:none!important;\n transition:none!important;\n scroll-behavior:auto!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 = MANAGER_CSS;\n document.head.appendChild(el);\n}\n\n/**\n * Channels mode's stylesheet, injected when its module arrives.\n *\n * It used to be concatenated into `MANAGER_CSS`, which meant the whole Channels\n * stylesheet was a static dependency of the cockpit's first paint even for the\n * majority of visits that never open Channels. Splitting it here is what lets\n * `channelsMode` leave the static graph entirely.\n *\n * Its own `<style>` element, and a second id, so the base cockpit's stylesheet\n * is never rewritten after mount — restyling a live surface is how a repaint\n * turns into a flash. Every rule inside is scoped under `.slm`, so arriving\n * late changes nothing that was already on screen.\n */\nfunction injectChannelsStyle(css: string): void {\n if (typeof document === 'undefined' || document.getElementById(CHANNELS_STYLE_ID)) return;\n const el = document.createElement('style');\n el.id = CHANNELS_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 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 /**\n * GA inventory units — real sellable labels the server counts, with NO seat\n * geometry and therefore no renderer binding. They live here rather than in\n * `labelToId`/`allIds` so every paint path keeps addressing paintable nodes\n * only, while the tally denominator finally covers the same universe the\n * numerator does. Without them a GA sale hit `booked` but not `total`:\n * Free under-reported by GA capacity and SOLD% could exceed 100%.\n */\n private gaUnitLabelSet = new Set<string>();\n private status = new Map<string, DoStatus>();\n /** Live non-free counters, moved by each delta rather than re-walked. */\n private counts: Record<Exclude<DoStatus, 'free'>, number> = { held: 0, booked: 0, blocked: 0 };\n /** Bumped whenever the seat model is replaced wholesale (a full snapshot). */\n private modelVersion = 0;\n private currency = 'USD';\n /** Currency read from the event/control-room projection; host currency is fallback only. */\n private authoritativeCurrency: string | null = null;\n private authoritativeGrossRevenue = 0;\n private revenueStatus: SeatManagerTallies['revenueStatus'] = 'loading';\n private revenueRequest = 0;\n private controlRoomSnapshot: ControlRoomSnapshot | null = null;\n /** Bearer-fetched organizer chart media, revoked with this manager. */\n private readonly organizerAssetUrls: OrganizerAssetObjectUrls;\n /**\n * The server's own totals, pinned to the client model they were read against.\n * Display = server baseline + (client now − client then), so the authoritative\n * numbers land exactly on arrival and deltas still move them between reads.\n * A wholesale model replacement invalidates the pairing (`model`), and the\n * client tallies — themselves a fresh authenticated read — take over.\n */\n private serverBaseline: {\n model: number;\n server: { free: number; held: number; booked: number; blocked: number };\n client: { free: number; held: number; booked: number; blocked: number };\n } | null = null;\n /** Latest presence frame, held whether or not a snapshot has landed yet. */\n private livePresence: { at: number; value: { shoppingSessions: number; activeHolds: number } } | null = null;\n /** Latest cumulative booked gross pushed on a delta frame. */\n private liveGross: { at: number; value: number } | null = null;\n /** Coalesces a burst of deltas into one KPI/rail repaint. */\n private paintHandle: number | 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 /** Mirrors the `live` root class, so the getter never has to read the DOM. */\n private connectionStatus: SeatManagerConnection['status'] = 'reconnecting';\n /** When the server last told us something. Stamped on accepted traffic only —\n * a socket that opens and says nothing has not refreshed anything. */\n private lastMessageAt: number | null = null;\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 /**\n * Sales channels (M6b).\n *\n * Two fields, and the split between them is the whole point. `channelCaps` is\n * AUTHORITY and is known early — it is read from the token's declared\n * capabilities before the first rail paint, so the Channels pill either\n * exists from the start or never appears. `channels` is the loaded sub-app,\n * and it now arrives late: its module is fetched on first entry into Channels\n * mode (`ensureChannels`), not at mount.\n *\n * So every gate that used to ask `!!this.channels` — the pill, the mode\n * whitelist, the `c` shortcut — asks `channelCaps.view` instead. Asking the\n * instance would make a permission the member genuinely has look like one\n * they do not for as long as a network fetch takes.\n */\n private channels: ChannelsMode | null = null;\n private channelCaps: ChannelsCapabilities = { view: false, manage: false };\n /** Supersedes an async capability probe after token/capability rotation. */\n private channelCapabilityResolution = 0;\n /** In-flight `import('./channelsMode')`, so concurrent entries load once. */\n private channelsLoading: Promise<void> | 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 === 'c') { if (!this.channelCaps.view) return; this.setMode('channels'); }\n else if (key === 'f') this.toggleFullscreen();\n else if (key === 'escape') { if (!this.channels?.handleBack()) return; }\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 assertBrowserManageToken(options.token);\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.organizerAssetUrls = new OrganizerAssetObjectUrls(\n this.key,\n (key, asset) => this.withAuthRetry(() => this.api.asset(key, asset)),\n );\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.withAuthRetry(() => this.api.chart(this.key));\n this.doc = await this.organizerAssetUrls.prepareRendererChart(res.doc);\n this.authoritativeCurrency = res.event.currency ?? null;\n this.currency = this.authoritativeCurrency ?? this.opts.currency ?? this.currency;\n this.buildUnitUniverse(this.doc);\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 void this.connect();\n this.startFeedClock();\n this.ready = true;\n // Resolve channel authority BEFORE the first rail paint so the pill either\n // exists from the start or never appears — a pill that pops in later reads\n // as a permission change that did not happen.\n await this.resolveChannelCapabilities();\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 // Fail closed: a host asking for a mode this token cannot use gets the\n // read-only board, never a half-rendered management surface. The test is\n // the CAPABILITY, not whether the lazy module has landed — see `channels`.\n if (mode === 'channels' && !this.channelCaps.view) mode = 'view';\n // First entry pays for the module. Kicked off before the paints below so\n // the fetch overlaps the mode switch instead of following it.\n if (mode === 'channels' && !this.channels) void this.ensureChannels();\n const changed = mode !== this.mode;\n const wasChannels = this.mode === 'channels';\n this.mode = mode;\n if (!this.renderer && this.doc) this.buildRenderer();\n else this.updateRendererInteraction();\n if (changed) this.renderer?.clearSelection();\n if (wasChannels && mode !== 'channels') this.channels?.leave();\n this.paintModeTabs();\n this.paintRail();\n this.applySectionCanvasTreatment();\n if (mode === 'channels') this.channels?.enter();\n if (changed) this.opts.onModeChange?.(mode);\n }\n\n /**\n * Decide what this token may do with sales channels.\n *\n * Declared capabilities win — a host that mints an `mse_…` grant knows exactly\n * what it asked for. A delegated token with no declaration is probed for read\n * access and then treated as READ-ONLY, because \"we could not tell\" must never\n * render mutation controls.\n */\n private async resolveChannelCapabilities(): Promise<void> {\n const resolution = ++this.channelCapabilityResolution;\n const declared = this.opts.capabilities;\n let next: ChannelsCapabilities;\n if (declared) {\n const set = new Set(declared as string[]);\n next = {\n view: set.has('event:channels:view'),\n manage: set.has('event:channels:view') && set.has('event:channels:manage'),\n };\n } else {\n next = { view: false, manage: false };\n }\n if (!next.view && !declared) {\n // Undeclared delegated token: probe read access once. Read-only either way.\n try {\n await this.api.channels(this.key);\n next = { view: true, manage: false };\n } catch {\n next = { view: false, manage: false };\n }\n }\n if (resolution !== this.channelCapabilityResolution) return;\n this.channelCaps = next;\n if (!this.channelCaps.view) {\n this.channels?.destroy();\n this.channels = null;\n if (this.mode === 'channels') this.setMode('view');\n else this.paintModeTabs();\n return;\n }\n // The instance is NOT built here any more — only the authority is settled.\n // Building it would load the sub-app on every mount, which is the cost this\n // split exists to remove. An instance that already exists (a token rotation\n // re-runs this) is told about the new capabilities in place.\n this.channels?.setCapabilities(this.channelCaps);\n this.paintModeTabs();\n }\n\n /**\n * Load Channels mode, once, on first entry.\n *\n * Everything about this method is shaped by one rule: the cockpit must stay\n * usable and honest while the module is in the air.\n *\n * - The promise is memoized, so a member who taps the pill twice, or a host\n * whose deep link and initial `mode` prop both ask for Channels, loads one\n * module and builds one instance.\n * - Authority is re-checked on arrival. A token rotation can revoke\n * `event:channels:view` between the tap and the load, and building the\n * sub-app for a token that no longer carries the capability would put\n * mutation controls on screen that every server call then refuses.\n * - The mode is re-checked too. Someone who taps Channels and then Monitor\n * before the chunk lands must not be yanked into Channels when it does; the\n * instance is kept (it is paid for) but only entered if we are still there.\n * - A failed load is stated in the rail rather than swallowed. Channels is a\n * whole surface — silently showing an empty one would read as \"this event\n * has no channels\", which is a lie about inventory.\n */\n private ensureChannels(): Promise<void> {\n if (this.channelsLoading) return this.channelsLoading;\n if (this.channels) return Promise.resolve();\n const load = (async () => {\n try {\n const mod = await import('./channelsMode');\n if (this.closed) return;\n // Re-read authority after the await — see above.\n if (!this.channelCaps.view) return;\n if (!this.channels) {\n injectChannelsStyle(mod.CHANNELS_CSS);\n this.channels = new mod.ChannelsMode(this.buildChannelsHost(), this.channelCaps);\n // Entering/leaving buyer preview flips the canvas between selectable\n // and strictly read-only, so re-arm the renderer when the view changes.\n this.channels.onInteractionChange = () => this.updateRendererInteraction();\n }\n if (this.mode !== 'channels') return;\n this.updateRendererInteraction();\n this.paintRail();\n this.channels.enter();\n } catch (err) {\n if (this.closed) return;\n // Allow a retry: the member can leave and re-enter the mode.\n this.channelsLoading = null;\n if (this.mode === 'channels') this.paintRail();\n this.opts.onError?.(err);\n }\n })();\n this.channelsLoading = load;\n return load;\n }\n\n /** The adapter between the cockpit's internals and Channels mode. */\n private buildChannelsHost() {\n return {\n eventKey: this.key,\n api: this.api,\n rail: this.els.rail,\n mapLayer: this.root.querySelector('.slm-map') as HTMLElement,\n root: this.root,\n seats: () => [...this.labelToSeat.values()].map((seat) => ({\n id: seat.id, label: seat.label, x: seat.x, y: seat.y,\n })),\n statusOf: (label: string): ChannelSeatStatus | undefined => this.status.get(label)\n ?? (this.labelToSeat.has(label) ? 'free' : undefined),\n selectionLabels: () => this.selectionLabels(),\n selectByLabels: (labels: string[]) => { this.selectByLabels(labels); },\n clearSelection: () => this.clearSelection(),\n selectSection: (sectionId: string) => { this.selectSection(sectionId); },\n sections: () => this.sectionOptions,\n labelsInSection: (sectionId: string) =>\n this.renderer?.getSelectableInSection(sectionId).map((seat) => seat.label) ?? [],\n // Logical rows, not physical row objects: a segmented row is authored as\n // several objects sharing one `logicalRowId`, and the organizer thinks of\n // it as one row. Tables carry seats too, so they are rows here as well.\n rows: (): ChannelsRowView[] => {\n const objects = new Map((this.doc?.objects ?? []).map((object) => [object.id, object]));\n const rows = new Map<string, ChannelsRowView>();\n for (const seat of this.labelToSeat.values()) {\n const object = objects.get(seat.rowId);\n if (!object || (object.type !== 'row' && object.type !== 'table')) continue;\n const id = seat.logicalRowId ?? seat.rowId;\n const sectionId = this.sectionByObject.get(seat.rowId) ?? UNGROUPED_ID;\n const row = rows.get(id) ?? {\n id,\n label: object.type === 'row'\n ? object.segmentedRow?.displayLabel ?? object.displayLabel ?? object.label\n : object.displayLabel ?? object.label,\n sectionId,\n sectionLabel: this.sectionLabelById.get(sectionId) ?? 'Other seats',\n labels: [],\n };\n row.labels.push(seat.label);\n rows.set(id, row);\n }\n return [...rows.values()].sort((left, right) =>\n left.sectionLabel.localeCompare(right.sectionLabel, undefined, { numeric: true, sensitivity: 'base' })\n || left.label.localeCompare(right.label, undefined, { numeric: true, sensitivity: 'base' }));\n },\n categories: () => (this.doc?.categories ?? []).map((category) => ({\n key: category.key, label: category.label ?? category.key, color: category.color,\n })),\n labelsInCategory: (key: string) => [...this.labelToSeat.entries()]\n .filter(([, seat]) => seat.categoryKey === key).map(([label]) => label),\n sectionOfLabel: (label: string) => {\n const seat = this.labelToSeat.get(label);\n if (!seat) return null;\n const id = this.sectionByObject.get(seat.rowId) ?? UNGROUPED_ID;\n return { id, label: this.sectionLabelById.get(id) ?? 'Other seats' };\n },\n worldToScreen: (point: { x: number; y: number }) => this.renderer?.worldToScreen(point) ?? null,\n seatPixelSize: () => this.seatPixelSize(),\n isSeatDetail: () => this.renderer?.getRung?.() === 'seats',\n showSectionOverview: () => {\n this.renderer?.clearSectionFocus();\n this.renderer?.setRung?.('sections');\n },\n focusSection: (sectionId: string) => this.renderer?.focusSection(sectionId),\n isCompact: () => !!this.root?.classList.contains('compact'),\n setMapInert: (inert: boolean) => {\n this.mapHost.toggleAttribute('inert', inert);\n this.mapHost.setAttribute('aria-hidden', String(inert));\n },\n toast: (message: string, kind: 'ok' | 'err') => this.toast(message, kind),\n onError: (err: unknown) => this.opts.onError?.(err),\n };\n }\n\n /** Actual on-screen seat diameter, for the channel overlay's marks. The\n * renderer's base seat radius is 9 chart units; retaining the camera scale\n * (rather than capping it) keeps every preview paint aligned with the real\n * chart geometry at deep zoom. */\n private seatPixelSize(): number {\n const rect = this.renderer?.getVisibleWorldRect?.();\n const width = this.mapHost?.clientWidth ?? 0;\n if (!rect?.width || !width) return 6;\n return Math.max(3, (width / rect.width) * 18);\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 /** Update background-tab repaint policy without rebuilding the board. */\n setKeepLiveWhileHidden(enabled: boolean | undefined): void {\n this.keepLive = enabled ?? true;\n this.opts.keepLiveWhileHidden = enabled;\n }\n\n /** Update the host fallback currency; an event/control-room currency still wins. */\n setCurrency(currency: string | undefined): void {\n this.opts.currency = currency;\n if (this.authoritativeCurrency) return;\n this.currency = currency ?? 'USD';\n if (this.ready) this.recomputeTallies();\n }\n\n /** Apply organizer chrome tokens in place without losing camera or selection. */\n setTheme(theme: ChartTheme | undefined): void {\n this.opts.theme = theme;\n if (!this.root) return;\n for (const [property, value] of Object.entries(themeVars(theme))) {\n this.root.style.setProperty(property, value);\n }\n }\n\n /** Replace the declared authority for the current token and fail closed. */\n setCapabilities(capabilities: SeatManagerOptions['capabilities']): void {\n this.opts.capabilities = capabilities;\n if (this.ready) void this.resolveChannelCapabilities();\n }\n\n /** Change proactive token-refresh policy without rebuilding the manager. */\n setTokenRefresh(onTokenRefresh: SeatManagerOptions['onTokenRefresh']): void {\n this.opts.onTokenRefresh = onTokenRefresh;\n this.scheduleTokenRefresh();\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: EventScopedManageToken, expiresAt?: number): void {\n assertBrowserManageToken(token);\n this.api.setToken(token);\n this.opts.token = token;\n this.opts.tokenExpiresAt = expiresAt;\n this.tokenExpiresAt = expiresAt ?? null;\n this.scheduleTokenRefresh();\n if (this.ready) void this.resolveChannelCapabilities();\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, `Released ${targets.length} booked unit${targets.length === 1 ? '' : 's'}.`);\n } catch (err) {\n this.setSeatsLocal(targets, 'booked');\n this.toastErr(\"Couldn't release that booked inventory. Check the booking 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 /**\n * The realtime link's current state and the \"as of\" behind it.\n *\n * Pair with `onConnectionChange` for the edges: a host that mounts after a\n * drop, or re-reads on tab focus, needs to be able to ASK rather than wait\n * for the next transition that may never come.\n */\n getConnection(): SeatManagerConnection {\n return { status: this.connectionStatus, lastMessageAt: this.lastMessageAt };\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 ? `Hold window set to ${Math.round(ms / 60000)} min.` : 'Hold window reset.');\n } catch (err) {\n this.toastErr(\"Couldn't update the hold window.\");\n this.opts.onError?.(err);\n }\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.paintHandle !== null && typeof cancelAnimationFrame === 'function') {\n cancelAnimationFrame(this.paintHandle);\n }\n this.paintHandle = null;\n this.channels?.destroy();\n this.channels = null;\n // A load still in flight is not cancellable, but `this.closed` makes its\n // continuation a no-op — so drop the memo rather than leaving a settled\n // promise that would make a later `ensureChannels()` resolve into nothing.\n this.channelsLoading = null;\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 this.organizerAssetUrls.dispose();\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 bulk = this.isBulkSelectMode();\n this.renderer = new SeatmapRenderer(this.mapHost, {\n manageMode: true,\n marqueeSelect: bulk,\n maxSelection: 1_000_000,\n selectableStatuses: this.selectableStatuses(),\n currency: this.currency,\n onSelect: (seat) => this.handleSeatSelect(seat),\n onDeselect: () => this.syncSelection(),\n onMarquee: () => this.syncSelection(),\n onSectionTap: (sectionId) => {\n this.renderer?.focusSection(sectionId);\n this.channels?.handleSectionFocus(sectionId);\n },\n onViewChange: () => { this.updateZoomHint(); this.channels?.handleViewChange(); },\n });\n this.renderer.setChart(this.doc);\n this.repaintAll();\n this.applyHeatOverlay();\n this.updateZoomHint();\n }\n\n /** Block always uses a marquee. Channels only enables its marquee after the\n * organizer deliberately chooses Assign seats; Pan map keeps desktop drag\n * available for large charts. */\n private isBulkSelectMode(): boolean {\n return this.mode === 'block' || (this.mode === 'channels' && this.channels?.usesMarqueeSelection() === true);\n }\n\n /**\n * Block never touches held or booked inventory, so it cannot select it.\n * Channels must be able to select it — the Review sheet's honesty depends on\n * counting the held and sold units inside a marquee and saying they will not\n * move, rather than silently omitting them from the selection.\n */\n private selectableStatuses(): SeatStatus[] {\n if (this.mode === 'block') return ['free', 'not_for_sale'];\n if (this.mode === 'inspect' || this.isBulkSelectMode()\n || (this.mode === 'channels' && this.channels?.canSelect() === true)) {\n return ['free', 'held', 'booked', 'not_for_sale'];\n }\n return [];\n }\n\n private updateRendererInteraction(): void {\n const bulk = this.isBulkSelectMode();\n this.renderer?.setManageInteraction({\n manageMode: true,\n marqueeSelect: bulk,\n maxSelection: 1_000_000,\n selectableStatuses: this.selectableStatuses(),\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 /**\n * Build the client's inventory universe from the chart.\n *\n * `expandChart` yields SEATS — it has no output for a GA area, whose capacity\n * is sold as N synthetic unit labels. The server's seat map keys, its deltas\n * and its `totals` all speak those labels, so a client that only knows seats\n * counts GA sales in the numerator (every key of the snapshot is written into\n * `status`) while leaving them out of the denominator. Registering the GA\n * units here — labels only, never a render binding — is what makes the two\n * agree.\n */\n private buildUnitUniverse(doc: ChartDoc): void {\n for (const seat of expandChart(doc)) {\n this.labelToId.set(seat.label, seat.id);\n this.labelToSeat.set(seat.label, seat);\n this.allIds.push(seat.id);\n }\n for (const area of gaAreasOf(doc)) {\n for (const label of gaUnitLabels(area)) {\n // A GA unit never shadows a seat label, and a joined area's provenance\n // can name the same unit twice across segments — the Set settles both.\n if (!this.labelToId.has(label)) this.gaUnitLabelSet.add(label);\n }\n }\n }\n\n /** Every sellable unit the client knows: seats + GA capacity. */\n private unitTotal(): number {\n return this.allIds.length + this.gaUnitLabelSet.size;\n }\n\n /** Every label the client models, whether or not it can be painted. */\n private knownLabels(): Iterable<string> {\n return [...this.labelToId.keys(), ...this.gaUnitLabelSet];\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 /**\n * Open the cockpit's realtime socket AS THE ORGANIZER.\n *\n * The scope has to be established before the upgrade, because a browser\n * `WebSocket` cannot send an Authorization header: the manage token is traded\n * over HTTPS for a one-use ticket which rides in `Sec-WebSocket-Protocol`.\n * Without it the server treats this socket as an anonymous public buyer and\n * projects its deltas, so any change inside a private channel allocation is\n * structurally suppressed and the map silently drifts.\n *\n * If the mint fails, remain reconnecting. An unticketed socket is a buyer\n * projection, so applying it to organizer state would be worse than staying\n * visibly offline while the host refreshes authority or upgrades the API.\n */\n private async connect(): Promise<void> {\n if (this.closed) return;\n let protocols: string[];\n try {\n protocols = (await this.withAuthRetry(() => this.api.subscribeTicket(this.key))).protocols;\n if (!protocols.length) throw new Error('manage_subscribe_ticket_missing');\n } catch (err) {\n this.setLive(false);\n this.opts.onError?.(err);\n this.scheduleReconnect();\n return;\n }\n if (this.closed) return;\n let ws: WebSocket;\n try {\n ws = new WebSocket(this.api.socketUrl(this.key), protocols);\n } catch (err) {\n this.opts.onError?.(err);\n this.scheduleReconnect();\n return;\n }\n this.ws = ws;\n ws.onopen = () => {\n this.attempt = 0;\n this.setLive(true);\n // Connect (and every reconnect) is where the server's own totals, booked\n // value and section metrics are re-established. Between connects the\n // delta stream carries both counts and configured value, so nothing polls.\n void this.resnapshot()\n .then(() => this.refreshControlRoom())\n .catch((err) => this.opts.onError?.(err));\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; void 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 // Stamped here, after parsing: unreadable frames prove the socket is open\n // but prove nothing about the numbers, and \"as of\" must mean the data.\n this.lastMessageAt = Date.now();\n const m = msg as {\n type?: string;\n seats?: Record<string, string>;\n /** Compact (protocol 1) snapshots send the modal status once and list\n * only the seats that differ from it. Absent on legacy frames. */\n default?: string;\n changes?: { label: string; status: string }[];\n /** Canonical cumulative configured value for booked inventory. */\n bookedValue?: { gross?: number };\n /** @deprecated Older workers called booked value `revenue`. */\n revenue?: { gross?: number };\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 // Presence used to be gated on a control-room snapshot already existing,\n // which silently dropped every frame in the window right after connect —\n // the exact window the cockpit is watched in. The counts are held on their\n // own field now and merged into the snapshot whenever one lands.\n if (typeof m.shoppingSessions === 'number' && typeof m.activeHolds === 'number') {\n this.livePresence = {\n at: Date.now(),\n value: { shoppingSessions: m.shoppingSessions, activeHolds: m.activeHolds },\n };\n if (this.controlRoomSnapshot) {\n this.controlRoomSnapshot = { ...this.controlRoomSnapshot, presence: this.livePresence.value };\n this.opts.onControlRoom?.(this.controlRoomSnapshot);\n }\n this.lastSyncedAt = Date.now();\n this.recomputeTallies();\n this.paintMonitorInsights();\n }\n return;\n }\n if (m.type === 'hidden') return;\n if (m.seats && typeof m.seats === 'object') {\n this.applySnapshot(m.seats, typeof m.default === 'string' ? m.default : undefined);\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.setStatusLabel(ch.label, st, prev);\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 // Money rides the frame now. GA-only sales register no renderer id, so a\n // refresh gated on `ids.length` never fired for them and GROSS SALES sat\n // frozen; a frame that carries the figure needs no fetch at all.\n const liveBookedValue = typeof m.bookedValue?.gross === 'number'\n ? m.bookedValue.gross\n : m.revenue?.gross;\n if (typeof liveBookedValue === 'number' && Number.isFinite(liveBookedValue)) {\n this.applyLiveGross(liveBookedValue);\n }\n this.recomputeTallies();\n }\n }\n\n /**\n * Adopt the cumulative booked gross a delta frame carried.\n *\n * Stashed with its arrival time so an in-flight control-room read can decide\n * whether it is holding the newer number: a frame that landed after the\n * request started is newer than the response, one that landed before is not.\n */\n private applyLiveGross(gross: number): void {\n this.liveGross = { at: Date.now(), value: gross };\n this.authoritativeGrossRevenue = gross;\n this.revenueStatus = 'current';\n if (this.controlRoomSnapshot) {\n const current = this.controlRoomSnapshot.bookedValue ?? this.controlRoomSnapshot.revenue;\n const bookedValue = { ...current, gross };\n this.controlRoomSnapshot = {\n ...this.controlRoomSnapshot,\n bookedValue,\n revenue: bookedValue,\n };\n this.opts.onControlRoom?.(this.controlRoomSnapshot);\n }\n }\n\n /** The single writer for a label's status, so the counters never drift. */\n private setStatusLabel(label: string, next: DoStatus, prev = this.status.get(label) ?? 'free'): void {\n this.status.set(label, next);\n if (prev === next) return;\n if (prev !== 'free') this.counts[prev] -= 1;\n if (next !== 'free') this.counts[next] += 1;\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 // A full snapshot over HTTP is server truth just as much as a delta is —\n // \"as of\" would otherwise ignore the freshest read the cockpit ever does.\n this.lastMessageAt = Date.now();\n } catch {\n /* transient — the delta stream keeps us fresh */\n }\n }\n\n /**\n * Replace the whole seat model.\n *\n * `fallback` is the compact frame's modal status: those snapshots list only\n * the seats that DIFFER from it, so every other known label takes it. Without\n * this the omitted majority would silently fall back to `free` — fine when\n * the mode really is free, wrong the moment it is not.\n */\n private applySnapshot(seats: Record<string, string>, fallback?: string): void {\n const known = (st: string): DoStatus =>\n (['free', 'held', 'booked', 'blocked'].includes(st) ? st : 'free') as DoStatus;\n const next = new Map<string, DoStatus>();\n if (fallback !== undefined) {\n const base = known(fallback);\n // GA units take the modal status too — they are inventory the server sells.\n for (const label of this.knownLabels()) next.set(label, base);\n }\n for (const [label, st] of Object.entries(seats)) {\n next.set(label, known(st));\n }\n this.status = next;\n this.modelVersion += 1;\n this.recountAll();\n this.lastSyncedAt = Date.now();\n this.repaintAll();\n this.afterPaint();\n this.recomputeTallies();\n }\n\n /** The one O(n) walk left: a wholesale model replacement re-bases the counters. */\n private recountAll(): void {\n const counts: Record<Exclude<DoStatus, 'free'>, number> = { held: 0, booked: 0, blocked: 0 };\n for (const st of this.status.values()) if (st !== 'free') counts[st] += 1;\n this.counts = counts;\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.setStatusLabel(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) => {\n const value = Number.isFinite(row.bookedValue) ? row.bookedValue : row.bookedRevenue;\n return sum + (Number.isFinite(value) ? value : 0);\n },\n 0,\n );\n this.revenueStatus = 'current';\n this.recomputeTallies();\n }\n\n /**\n * Read the server's own control-room projection.\n *\n * Called on mount, on every socket (re)connect and after an organizer action —\n * never on a timer and never per delta frame. Presence and gross that arrived\n * on the socket AFTER this request started are newer than the response, so\n * they survive it; anything older defers to the read.\n */\n private async refreshControlRoom(): Promise<ControlRoomSnapshot> {\n const request = ++this.revenueRequest;\n const requestedAt = Date.now();\n try {\n const fetched = await this.api.controlRoom(this.key, this.trendWindowMinutes);\n // A custom ManageApi-compatible host or one-window-old worker can still\n // supply only `revenue`. Normalize again at the widget boundary so the\n // canonical runtime contract does not depend on the concrete client.\n const incoming = fetched.bookedValue ?? fetched.revenue ?? { gross: 0, bySection: [] };\n const normalizedSections = (incoming.bySection ?? []).map((row) => {\n const value = Number.isFinite(row.bookedValue) ? row.bookedValue : row.bookedRevenue;\n return { ...row, bookedValue: value ?? 0, bookedRevenue: value ?? 0 };\n });\n const canonical = { ...incoming, bySection: normalizedSections };\n let snapshot = { ...fetched, bookedValue: canonical, revenue: canonical };\n if (request === this.revenueRequest) {\n if (this.livePresence && this.livePresence.at >= requestedAt) {\n snapshot = { ...snapshot, presence: this.livePresence.value };\n } else {\n this.livePresence = null;\n }\n if (this.liveGross && this.liveGross.at >= requestedAt) {\n const bookedValue = { ...snapshot.bookedValue, gross: this.liveGross.value };\n snapshot = { ...snapshot, bookedValue, revenue: bookedValue };\n } else {\n this.liveGross = null;\n }\n this.controlRoomSnapshot = snapshot;\n this.rebaseServerTotals(snapshot);\n this.lastSyncedAt = Date.now();\n this.authoritativeGrossRevenue = snapshot.bookedValue.gross;\n this.authoritativeCurrency = snapshot.currency;\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 // The host is handed the same object the cockpit adopted — a public\n // getter that disagreed with `onControlRoom` would be its own defect.\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 /** Pin the server's totals to the client model they were read against. */\n private rebaseServerTotals(snapshot: ControlRoomSnapshot): void {\n const totals = snapshot.totals;\n if (!totals || ['free', 'held', 'booked', 'blocked'].some(\n (key) => !Number.isFinite((totals as unknown as Record<string, number>)[key]),\n )) {\n this.serverBaseline = null;\n return;\n }\n this.serverBaseline = {\n model: this.modelVersion,\n server: { free: totals.free, held: totals.held, booked: totals.booked, blocked: totals.blocked },\n client: this.clientTallies(),\n };\n }\n\n /** What the client's own model says — GA units included since `render()`. */\n private clientTallies(): { free: number; held: number; booked: number; blocked: number } {\n const { held, booked, blocked } = this.counts;\n // The snapshot only carries non-free, so free is what is left over.\n return { held, booked, blocked, free: Math.max(0, this.unitTotal() - held - booked - blocked) };\n }\n\n /**\n * The numbers the KPI bar and rail render.\n *\n * The server is the authority: its totals land exactly as read, and the\n * delta-driven client model carries them forward until the next read. Before\n * the first snapshot — and after a wholesale model replacement invalidates the\n * pairing — the client model stands alone.\n */\n private buildTallies(): SeatManagerTallies {\n const client = this.clientTallies();\n const baseline = this.serverBaseline?.model === this.modelVersion ? this.serverBaseline : null;\n const of = (key: 'free' | 'held' | 'booked' | 'blocked'): number => (baseline\n ? Math.max(0, baseline.server[key] + (client[key] - baseline.client[key]))\n : client[key]);\n const seatTotal = this.controlRoomSnapshot?.event?.seatTotal;\n const t: SeatManagerTallies = {\n free: of('free'), held: of('held'), booked: of('booked'), blocked: of('blocked'),\n total: Number.isFinite(seatTotal) ? (seatTotal as number) : this.unitTotal(),\n capacityPct: 0,\n sellThroughPct: 0,\n bookedValue: this.authoritativeGrossRevenue,\n grossRevenue: this.authoritativeGrossRevenue,\n bookedValueStatus: this.revenueStatus,\n revenueStatus: this.revenueStatus,\n currency: this.currency,\n };\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 return t;\n }\n\n /**\n * Queue one KPI/rail repaint for this burst of changes.\n *\n * A delta frame can carry hundreds of seats and `paintKpis` rebuilds eight\n * nodes from scratch, so painting per change is what made an arena-sized\n * frame expensive. Coalescing on a frame keeps the burst to a single rebuild;\n * without `requestAnimationFrame` (SSR, an older test env) it paints inline\n * rather than dropping the update.\n */\n private recomputeTallies(): void {\n if (this.closed) return;\n if (typeof requestAnimationFrame !== 'function') { this.flushTallies(); return; }\n if (this.paintHandle !== null) return;\n this.paintHandle = requestAnimationFrame(() => {\n this.paintHandle = null;\n this.flushTallies();\n });\n }\n\n private flushTallies(): void {\n if (this.closed) return;\n const t = this.buildTallies();\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 else if (this.mode === 'channels') this.channels?.handleSelectionChange();\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 else if (this.mode === 'channels') this.channels?.handleSelectionChange();\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 <button class=\"slm-mode\" role=\"tab\" data-mode=\"channels\" title=\"Channels (C)\" aria-keyshortcuts=\"C\" hidden>Channels</button>\n </div>\n <select class=\"slm-tools\" data-ref=\"tools\" aria-label=\"Manager tools\"></select>\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=\"Booking momentum overlay off\"\n title=\"Highlight sections booking fastest in the selected time window\">Booking 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'), tools: ref('tools'), 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 // Below the compact breakpoint the pills collapse into ONE accessible Tools\n // picker (§13) — never a tab strip plus a second scrolling mechanism.\n this.els.tools.addEventListener('change', () =>\n this.setMode((this.els.tools as HTMLSelectElement).value 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 this.channels?.handleLayoutChange();\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 const available: Array<{ mode: SeatManagerMode; label: string }> = [];\n this.els.modes?.querySelectorAll('[data-mode]').forEach((b) => {\n const el = b as HTMLElement;\n const mode = el.dataset.mode as SeatManagerMode;\n // No channel-view capability ⇒ the pill is not rendered at all. A hidden\n // control is honest about authority; a disabled one advertises it.\n // Authority, not readiness: the pill must not wait on the lazy module.\n const permitted = mode !== 'channels' || this.channelCaps.view;\n el.hidden = !permitted;\n if (!permitted) return;\n available.push({ mode, label: el.textContent ?? mode });\n const active = mode === this.mode;\n el.classList.toggle('on', active);\n el.setAttribute('aria-selected', String(active));\n el.tabIndex = active ? 0 : -1;\n });\n const tools = this.els.tools as HTMLSelectElement | undefined;\n if (tools) {\n tools.innerHTML = available.map((entry) =>\n `<option value=\"${entry.mode}\"${entry.mode === this.mode ? ' selected' : ''}>${esc(entry.label)}</option>`).join('');\n tools.value = this.mode;\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 holds and bookings. Turn off to keep the current view.'\n : 'Stay on the current map view. Enable to follow new 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', `Booking momentum overlay ${this.heatEnabled ? 'on' : 'off'}`);\n button.setAttribute('title', `${this.heatEnabled ? 'Hide' : 'Highlight'} sections booking fastest in the selected time window`);\n button.textContent = 'Booking 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 // Tell the host only on a real edge. `connect()` can call this with the\n // same value it already had (an open that follows a reconnect attempt),\n // and a banner that re-announces itself on every retry is noise.\n const next: SeatManagerConnection['status'] = on ? 'live' : 'reconnecting';\n if (next === this.connectionStatus) return;\n this.connectionStatus = next;\n try {\n this.opts.onConnectionChange?.(this.getConnection());\n } catch (err) {\n // A host callback must never take the socket down with it.\n this.opts.onError?.(err);\n }\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 === 'booked-value') return `${sign}${fmtMoney(absolute, currency)}`;\n if (key === 'booked-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 bookedValue = t.bookedValueStatus === 'current' ? fmtMoney(t.bookedValue, t.currency) : '—';\n const presence = this.presenceCounts();\n // Two different units share this bar and used to be interleaved: \"Held\n // seats\" (seat units) sat next to \"Active holds\" (checkout sessions), which\n // read as the same quantity counted twice. Seat tallies are grouped, the\n // session-scale pair is grouped, and the session one is named for what it\n // is — a cart.\n const items: { key: string; raw: number | null; n: string; l: string; dot?: string; title: string }[] = [\n { key: 'booked-inventory', raw: t.booked, n: t.booked.toLocaleString(), l: 'Booked inventory', dot: '#22a06b', title: 'Inventory units booked' },\n { key: 'held-seats', raw: t.held, n: t.held.toLocaleString(), l: 'Held inventory', dot: '#f4b740', title: 'Inventory currently held' },\n { key: 'free-seats', raw: t.free, n: t.free.toLocaleString(), l: 'Available', dot: '#6e7bff', title: 'Inventory available to book' },\n { key: 'blocked', raw: t.blocked, n: t.blocked.toLocaleString(), l: 'Blocked', dot: '#8b94ac', title: 'Inventory withheld from booking' },\n { key: 'viewing-map', raw: presence?.shoppingSessions ?? null, n: presence ? presence.shoppingSessions.toLocaleString() : '—', l: 'Viewing map', title: 'Active map sessions right now' },\n { key: 'active-holds', raw: presence?.activeHolds ?? null, n: presence ? presence.activeHolds.toLocaleString() : '—', l: 'Active holds', title: 'Sessions currently holding inventory' },\n { key: 'booked-pct', raw: t.capacityPct, n: `${t.capacityPct}%`, l: 'Booked', title: 'Booked inventory as a share of the whole event' },\n { key: 'booked-value', raw: t.bookedValueStatus === 'current' ? t.bookedValue : null, n: bookedValue, l: 'Booked value', title: 'Configured value attached to booked inventory' },\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}\" title=\"${esc(item.title)}\">\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 if (this.mode === 'channels') {\n // The sub-app may still be in the air (see `ensureChannels`). Say which\n // of the two it is rather than leaving the rail blank: an empty Channels\n // rail reads as \"this event has no channels\", which is a claim about\n // inventory and would be false.\n if (this.channels) this.channels.paintRail();\n else if (this.channelsLoading) {\n this.els.rail.innerHTML = '<div class=\"slm-empty\" role=\"status\">Loading sales channels…</div>';\n } else {\n this.els.rail.innerHTML = '<div class=\"slm-empty\" role=\"alert\">Sales channels could not be loaded. Switch away and back to try again.</div>';\n }\n }\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, map activity and booking 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 inventory</p><p class=\"slm-note\">Configured booked value · booking momentum</p></div>\n <div class=\"slm-windows\" aria-label=\"Booking momentum 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 /** Live presence wins over the snapshot's copy — it is the fresher channel,\n * and it exists from the first frame rather than the first fetch. */\n private presenceCounts(): { shoppingSessions: number; activeHolds: number } | null {\n return this.livePresence?.value ?? this.controlRoomSnapshot?.presence ?? null;\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 const presence = this.presenceCounts();\n this.els.presence.innerHTML = `\n <div class=\"slm-healthitem\" title=\"Active map sessions right now\"><b>${presence ? presence.shoppingSessions.toLocaleString() : '—'}</b><span>Viewing map</span></div>\n <div class=\"slm-healthitem\" title=\"Sessions currently holding inventory\"><b>${presence ? 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.bookedValue.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.bookedValue - a.bookedValue;\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.bookedValue, snapshot.currency)}</span></span>\n <span class=\"slm-sectionmeta\"><span>${row.booked.toLocaleString()}/${row.total.toLocaleString()} booked · ${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.bookedValue.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 booking 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?.bookedValue.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>Booked in section</span><b>${sectionMetric ? `${sectionMetric.booked} of ${sectionMetric.total}` : '—'}</b></div>\n <div><span>Section booked value</span><b>${sectionMetric && this.controlRoomSnapshot ? fmtMoney(sectionMetric.bookedValue, 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 // An explicit organizer action is one of the three moments the server's own\n // totals and money are re-read (mount, (re)connect, action) — the cockpit\n // does not poll for them.\n if (action !== 'setHoldTtl') void this.refreshControlRoom().catch((err) => this.opts.onError?.(err));\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","import type { ChartDoc, ChartReferenceImage, DecorImageObject, Floor } from '@seatlayer/core';\n\nconst SAFE_ASSET = /^[a-zA-Z0-9._-]+$/;\n\nexport interface OrganizerEventAssetReference {\n eventKey: string;\n asset: string;\n}\n\n/** Parse only the authenticated organizer Event media route. */\nexport function organizerEventAssetReference(value: string): OrganizerEventAssetReference | null {\n let url: URL;\n try {\n url = new URL(value, 'https://seatlayer.invalid');\n } catch {\n return null;\n }\n if (url.search || url.hash) return null;\n const match = /^\\/v1\\/events\\/([^/]+)\\/assets\\/([^/]+)$/.exec(url.pathname);\n if (!match) return null;\n try {\n const eventKey = decodeURIComponent(match[1]);\n const asset = decodeURIComponent(match[2]);\n if (!eventKey || !SAFE_ASSET.test(asset)) return null;\n return { eventKey, asset };\n } catch {\n return null;\n }\n}\n\nfunction looksLikeOrganizerAsset(value: string): boolean {\n try {\n return /^\\/v1\\/events\\/[^/]+\\/assets(?:\\/|$)/.test(\n new URL(value, 'https://seatlayer.invalid').pathname,\n );\n } catch {\n return false;\n }\n}\n\nexport type OrganizerAssetLoader = (eventKey: string, asset: string) => Promise<Blob>;\n\n/**\n * One SeatManager-lifetime cache for media fetched with organizer authority.\n * Object URLs are process-local, carry no bearer, and are all revoked by\n * {@link dispose}.\n */\nexport class OrganizerAssetObjectUrls {\n private readonly pending = new Map<string, Promise<string | null>>();\n private readonly created = new Set<string>();\n private disposed = false;\n\n constructor(\n private readonly eventKey: string,\n private readonly load: OrganizerAssetLoader,\n ) {}\n\n resolve(reference: string): Promise<string | null> {\n const parsed = organizerEventAssetReference(reference);\n if (!parsed) {\n // A malformed SeatLayer organizer-media path is never treated as an\n // external image and loaded without its bearer.\n return Promise.resolve(looksLikeOrganizerAsset(reference) ? null : reference);\n }\n if (parsed.eventKey !== this.eventKey || this.disposed) return Promise.resolve(null);\n\n const cacheKey = `${parsed.eventKey}/${parsed.asset}`;\n const existing = this.pending.get(cacheKey);\n if (existing) return existing;\n\n const task = this.load(parsed.eventKey, parsed.asset).then((blob) => {\n const objectUrl = URL.createObjectURL(blob);\n if (this.disposed) {\n URL.revokeObjectURL(objectUrl);\n return null;\n }\n this.created.add(objectUrl);\n return objectUrl;\n }).catch((error) => {\n this.pending.delete(cacheKey);\n throw error;\n });\n this.pending.set(cacheKey, task);\n return task;\n }\n\n /**\n * Resolve the image fields the synchronous map renderer loads immediately.\n * View-from-seat media stays lazy: SeatManager does not open that buyer\n * surface, and eagerly downloading every row panorama would be unbounded.\n */\n async prepareRendererChart(doc: ChartDoc): Promise<ChartDoc> {\n const prepareBackground = async (background?: ChartReferenceImage): Promise<void> => {\n if (!background?.url) return;\n const resolved = await this.resolve(background.url);\n if (!resolved) throw new Error('organizer_event_asset_scope_mismatch');\n background.url = resolved;\n };\n const prepareObjects = async (objects: ChartDoc['objects']): Promise<void> => {\n for (const object of objects) {\n if (object.type !== 'decorImage') continue;\n const image = object as DecorImageObject;\n const resolved = await this.resolve(image.href);\n if (!resolved) throw new Error('organizer_event_asset_scope_mismatch');\n image.href = resolved;\n }\n };\n const prepareOwner = async (owner: Pick<ChartDoc, 'backgroundImage' | 'objects'> | Floor): Promise<void> => {\n await prepareBackground(owner.backgroundImage);\n await prepareObjects(owner.objects);\n };\n\n await prepareOwner(doc);\n for (const floor of doc.floors ?? []) await prepareOwner(floor);\n return doc;\n }\n\n dispose(): void {\n if (this.disposed) return;\n this.disposed = true;\n for (const url of this.created) URL.revokeObjectURL(url);\n this.created.clear();\n this.pending.clear();\n }\n}\n"],"mappings":"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AAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;A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","names":[]}
|