@seatlayer/js 0.93.0 → 0.95.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/manager.js CHANGED
@@ -1,14 +1,100 @@
1
- import{c as H,d as B,f as j}from"./chunk-RZ2VKZ44.js";import{A as Re,B as Ae,D as $e,a as P,b as S,c as z,d as le,e as ne,f as re,g as ce,h as de,i as he,j as pe,k as me,l as ue,m as be,n as ge,o as ve,p as fe,q as ye,r as xe,s as ke,t as Se,u as we,v as Le,w as Te,x as Me,y as Ce,z as Ee}from"./chunk-5VGXB6GJ.js";import"./chunk-OSZ7DOEH.js";var D={hold:"Held",release:"Released",expire:"Expired",book:"Booked",unbook:"Cancelled",block:"Blocked",unblock:"Unblocked"},w=class{constructor(e,t){this.host=e;this.fetchPage=t;this.closed=!1;this.busy=!1;this.generation=0;this.entries=[];this.next=null;this.summary=document.createElement("div");this.list=document.createElement("div");this.message=document.createElement("div");this.older=document.createElement("button");this.latest=document.createElement("button");e.className="slm-seat-history",this.summary.className="slm-history-counts",this.list.className="slm-history-list",this.list.setAttribute("role","region"),this.list.setAttribute("aria-label","Seat history"),this.list.tabIndex=0,this.message.className="slm-note",this.message.setAttribute("role","status"),this.older.className=this.latest.className="slm-btn ghost",this.older.textContent="Load older",this.older.hidden=!0,this.latest.textContent="New activity \xB7 Show latest",this.latest.hidden=!0,this.older.onclick=()=>{this.load(!0)},this.latest.onclick=()=>{this.list.scrollTop=0,this.latest.hidden=!0,this.load()},e.append(this.summary,this.latest,this.list,this.message,this.older),this.load()}destroy(){this.closed=!0,this.generation++}refresh(){this.busy||this.load(!1,!0)}async load(e=!1,t=!1){if(this.closed||this.busy||e&&!this.next)return;this.busy=!0,this.older.disabled=!0;let s=this.generation;t||(this.message.textContent="Loading history\u2026");try{let i=await this.fetchPage(e?this.next:void 0,this.action);if(this.closed||s!==this.generation)return;if(this.paintCounts(i),t&&this.entries.length&&i.entries[0]?.id!==this.entries[0]?.id&&this.list.scrollTop>24){this.latest.hidden=!1;return}let a=!t||i.entries[0]?.id!==this.entries[0]?.id;e?(this.entries=[...this.entries,...i.entries.filter(o=>!this.entries.some(l=>l.id===o.id))],this.next=i.nextBefore):a&&(this.entries=i.entries,this.next=i.nextBefore),a&&this.paintRows(),this.older.hidden=this.next===null,this.message.textContent=this.entries.length?"":"No recorded activity for this seat."}catch{if(!this.closed){this.message.textContent="History could not be loaded. ";let i=document.createElement("button");i.className="slm-btn ghost",i.textContent="Retry",i.onclick=()=>{this.load(e)},this.message.append(i)}}finally{this.busy=!1,this.older.disabled=!1}}paintCounts(e){let t=[{action:"",count:e.total},...e.counts];this.summary.replaceChildren(...t.map(({action:s,count:i})=>{let a=document.createElement("button");return a.type="button",a.textContent=s?`${D[s]??s} ${i}`:`${i} changes`,a.setAttribute("aria-pressed",String((this.action??"")===s)),a.onclick=()=>{this.busy||(this.action=s||void 0,this.entries=[],this.next=null,this.list.scrollTop=0,this.latest.hidden=!0,this.load())},a}))}paintRows(){let e=this.list.scrollTop;this.list.replaceChildren(...this.entries.map(t=>{let s=document.createElement("div");s.className="slm-history-row",s.dataset.action=t.action;let i=document.createElement("time");i.dateTime=new Date(t.at).toISOString(),i.textContent=new Date(t.at).toLocaleString(void 0,{year:"numeric",month:"short",day:"numeric",hour:"2-digit",minute:"2-digit",second:"2-digit"}),i.title=new Date(t.at).toString();let a=document.createElement("strong");return a.textContent=D[t.action]??t.action,s.append(i,a),s})),this.list.scrollTop=e}};var He={held:"HOLD",booked:"BOOK",expired:"EXPIRE",released:"RELEASE",cancelled:"CANCEL",blocked:"BLOCK",unblocked:"ON SALE",available:"FREE"},N={held:"Held",booked:"Booked",expired:"Hold expired",released:"Hold released",cancelled:"Booking cancelled",blocked:"Blocked",unblocked:"Back on sale",available:"Available again"},L=class{constructor(e,t,s){this.host=e;this.locate=s;this.items=[];this.shown=new Set;this.paused=!1;this.limit=100;this.signature="unrendered";this.abort=new AbortController;e.innerHTML='<button class="slm-new-activity" hidden></button><div class="slm-activity-list" role="region" aria-label="Recent activity" tabindex="0"></div><button class="slm-more-activity" hidden>Show more activity</button>',this.list=e.querySelector(".slm-activity-list"),this.newer=e.querySelector(".slm-new-activity"),this.more=e.querySelector(".slm-more-activity");let i={signal:this.abort.signal},a=()=>{this.paused=!1,this.signature="unrendered",this.list.scrollTop=0,this.render()};this.list.addEventListener("scroll",()=>{this.list.scrollTop>24&&(this.paused=!0)},i),this.list.addEventListener("focusin",()=>{this.paused=!0},i),this.list.addEventListener("toggle",o=>{o.target.open&&(this.paused=!0)},{...i,capture:!0}),this.newer.addEventListener("click",a,i),this.more.addEventListener("click",()=>{this.limit=200,this.signature="unrendered",this.render(!0)},i)}update(e){this.items=e,this.render()}render(e=!1){let t=this.items,s=t.filter(o=>!this.shown.has(o.id)).length;if(this.newer.hidden=!this.paused,this.newer.textContent=s?`${s} new activit${s===1?"y":"ies"} \xB7 Back to live`:"Reading earlier activity \xB7 Back to live",this.paused&&!e)return;let i=t.slice(0,this.limit),a=i.map(o=>`${o.id}:${o.verb}`).join("|");if(a!==this.signature){if(this.signature=a,this.shown=new Set(t.map(o=>o.id)),this.list.replaceChildren(),!i.length){let o=document.createElement("p");o.className="slm-activity-empty",o.textContent=this.items.length?"No activity matches these filters.":"Waiting for activity. Holds, bookings and releases will appear here.",this.list.append(o)}for(let o of i){let l=document.createElement("article");l.className="slm-activity-entry",l.dataset.status=o.status;let r=document.createElement("button");r.type="button",r.className="slm-activity-row";let c=`${N[o.verb]??o.verb} \xB7 ${o.count} seat${o.count===1?"":"s"} \xB7 ${o.sectionLabels?.join(", ")||"Event inventory"} \xB7 ${o.labels.join(", ")} \xB7 ${new Date(o.at).toLocaleString()}`;r.title=`${c} \u2014 click to show seats on the map`,r.setAttribute("aria-label",`Show seats on map: ${c}`),r.addEventListener("click",()=>this.locate(o.id));let n=document.createElement("time");n.dateTime=new Date(o.at).toISOString(),n.textContent=new Date(o.at).toLocaleTimeString([],{hour:"2-digit",minute:"2-digit"});let d=document.createElement("strong");d.textContent=He[o.verb]??o.verb,d.title=N[o.verb]??o.verb;let m=document.createElement("span");if(m.className="slm-activity-seats",m.textContent=o.labels.join(", "),r.append(n,d,m),l.append(r),o.count>1){let b=document.createElement("details");b.className="slm-activity-details";let g=document.createElement("summary");g.textContent="\u22EF",g.setAttribute("aria-label",`Show all ${o.count} seats`);let v=document.createElement("p");v.textContent=c,b.append(g,v),l.append(b)}this.list.append(l)}this.more.hidden=t.length<=this.limit}}destroy(){this.abort.abort()}};var T=class{constructor(e){this.host=e;this.moving=!1;this.space=!1;this.monitor=!1;this.selected=0;this.abort=new AbortController;let t=document.createElement("div");t.className="slm-navigation";let s=u=>`<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">${u}</svg>`,i=s('<path d="M8 13V6a2 2 0 0 1 4 0v6-8a2 2 0 0 1 4 0v8-6a2 2 0 0 1 4 0v10c0 4-3 6-7 6-3 0-5-2-7-5l-3-4a2 2 0 0 1 3-2l2 2Z"/>'),a=s('<path d="m5 3 14 10-7 1-3 7-4-18Z"/>'),o=s('<circle cx="10.5" cy="10.5" r="6.5"/><path d="m16 16 5 5"/>'),l=s('<path d="M7 6h10M12 1v10M7 18h10"/>'),r=s('<rect x="3" y="4" width="18" height="16" rx="2"/><path d="M15 4v16"/>');t.innerHTML=`<div class="slm-navigation-tools" role="group" aria-label="Map navigation">
1
+ import{s as _,t as K}from"./chunk-JELR6YYZ.js";import{A as Ve,B as Pe,C as je,D as qe,E as Ne,F as _e,G as Ke,H as Ue,I as We,J as Ge,K as Ze,L as Ye,M as Xe,N as Qe,O as Je,P as et,Q as tt,R as st,S as it,T as ot,V as at,a as L,b as U,c as k,d as F,e as W,f as G,g as Z,h as Y,i as O,j as M,k as x,l as X,m as Q,n as J,o as ee,p as te,q as T,r as m,s as D,t as se,u as V,v as ze,w as Ie,x as Fe,y as Oe,z as De}from"./chunk-DR5JXWLO.js";import{d as I,f as N}from"./chunk-RZ2VKZ44.js";import"./chunk-OSZ7DOEH.js";var ie={hold:"Held",release:"Released",expire:"Expired",book:"Booked",unbook:"Cancelled",block:"Blocked",unblock:"Unblocked"},C=class{constructor(e,t){this.host=e;this.fetchPage=t;this.closed=!1;this.busy=!1;this.generation=0;this.entries=[];this.next=null;this.summary=document.createElement("div");this.list=document.createElement("div");this.message=document.createElement("div");this.older=document.createElement("button");this.latest=document.createElement("button");e.className="slm-seat-history",this.summary.className="slm-history-counts",this.list.className="slm-history-list",this.list.setAttribute("role","region"),this.list.setAttribute("aria-label","Seat history"),this.list.tabIndex=0,this.message.className="slm-note",this.message.setAttribute("role","status"),this.older.className=this.latest.className="slm-btn ghost",this.older.textContent="Load older",this.older.hidden=!0,this.latest.textContent="New activity \xB7 Show latest",this.latest.hidden=!0,this.older.onclick=()=>{this.load(!0)},this.latest.onclick=()=>{this.list.scrollTop=0,this.latest.hidden=!0,this.load()},e.append(this.summary,this.latest,this.list,this.message,this.older),this.load()}destroy(){this.closed=!0,this.generation++}refresh(){this.busy||this.load(!1,!0)}async load(e=!1,t=!1){if(this.closed||this.busy||e&&!this.next)return;this.busy=!0,this.older.disabled=!0;let s=this.generation;t||(this.message.textContent="Loading history\u2026");try{let i=await this.fetchPage(e?this.next:void 0,this.action);if(this.closed||s!==this.generation)return;if(this.paintCounts(i),t&&this.entries.length&&i.entries[0]?.id!==this.entries[0]?.id&&this.list.scrollTop>24){this.latest.hidden=!1;return}let o=!t||i.entries[0]?.id!==this.entries[0]?.id;e?(this.entries=[...this.entries,...i.entries.filter(a=>!this.entries.some(l=>l.id===a.id))],this.next=i.nextBefore):o&&(this.entries=i.entries,this.next=i.nextBefore),o&&this.paintRows(),this.older.hidden=this.next===null,this.message.textContent=this.entries.length?"":"No recorded activity for this seat."}catch{if(!this.closed){this.message.textContent="History could not be loaded. ";let i=document.createElement("button");i.className="slm-btn ghost",i.textContent="Retry",i.onclick=()=>{this.load(e)},this.message.append(i)}}finally{this.busy=!1,this.older.disabled=!1}}paintCounts(e){let t=[{action:"",count:e.total},...e.counts];this.summary.replaceChildren(...t.map(({action:s,count:i})=>{let o=document.createElement("button");return o.type="button",o.textContent=s?`${ie[s]??s} ${i}`:`${i} changes`,o.setAttribute("aria-pressed",String((this.action??"")===s)),o.onclick=()=>{this.busy||(this.action=s||void 0,this.entries=[],this.next=null,this.list.scrollTop=0,this.latest.hidden=!0,this.load())},o}))}paintRows(){let e=this.list.scrollTop;this.list.replaceChildren(...this.entries.map(t=>{let s=document.createElement("div");s.className="slm-history-row",s.dataset.action=t.action;let i=document.createElement("time");i.dateTime=new Date(t.at).toISOString(),i.textContent=new Date(t.at).toLocaleString(void 0,{year:"numeric",month:"short",day:"numeric",hour:"2-digit",minute:"2-digit",second:"2-digit"}),i.title=new Date(t.at).toString();let o=document.createElement("strong");return o.textContent=ie[t.action]??t.action,s.append(i,o),s})),this.list.scrollTop=e}};var lt={held:"HOLD",booked:"BOOK",expired:"EXPIRE",released:"RELEASE",cancelled:"CANCEL",blocked:"BLOCK",unblocked:"ON SALE",available:"FREE"},oe={held:"Held",booked:"Booked",expired:"Hold expired",released:"Hold released",cancelled:"Booking cancelled",blocked:"Blocked",unblocked:"Back on sale",available:"Available again"},E=class{constructor(e,t,s){this.host=e;this.locate=s;this.items=[];this.shown=new Set;this.paused=!1;this.limit=100;this.signature="unrendered";this.abort=new AbortController;e.innerHTML='<button class="slm-new-activity" hidden></button><div class="slm-activity-list" role="region" aria-label="Recent activity" tabindex="0"></div><button class="slm-more-activity" hidden>Show more activity</button>',this.list=e.querySelector(".slm-activity-list"),this.newer=e.querySelector(".slm-new-activity"),this.more=e.querySelector(".slm-more-activity");let i={signal:this.abort.signal},o=()=>{this.paused=!1,this.signature="unrendered",this.list.scrollTop=0,this.render()};this.list.addEventListener("scroll",()=>{this.list.scrollTop>24&&(this.paused=!0)},i),this.list.addEventListener("focusin",()=>{this.paused=!0},i),this.list.addEventListener("toggle",a=>{a.target.open&&(this.paused=!0)},{...i,capture:!0}),this.newer.addEventListener("click",o,i),this.more.addEventListener("click",()=>{this.limit=200,this.signature="unrendered",this.render(!0)},i)}update(e){this.items=e,this.render()}render(e=!1){let t=this.items,s=t.filter(a=>!this.shown.has(a.id)).length;if(this.newer.hidden=!this.paused,this.newer.textContent=s?`${s} new activit${s===1?"y":"ies"} \xB7 Back to live`:"Reading earlier activity \xB7 Back to live",this.paused&&!e)return;let i=t.slice(0,this.limit),o=i.map(a=>`${a.id}:${a.verb}`).join("|");if(o!==this.signature){if(this.signature=o,this.shown=new Set(t.map(a=>a.id)),this.list.replaceChildren(),!i.length){let a=document.createElement("p");a.className="slm-activity-empty",a.textContent=this.items.length?"No activity matches these filters.":"Waiting for activity. Holds, bookings and releases will appear here.",this.list.append(a)}for(let a of i){let l=document.createElement("article");l.className="slm-activity-entry",l.dataset.status=a.status;let r=document.createElement("button");r.type="button",r.className="slm-activity-row";let c=`${oe[a.verb]??a.verb} \xB7 ${a.count} seat${a.count===1?"":"s"} \xB7 ${a.sectionLabels?.join(", ")||"Event inventory"} \xB7 ${a.labels.join(", ")} \xB7 ${new Date(a.at).toLocaleString()}`;r.title=`${c} \u2014 click to show seats on the map`,r.setAttribute("aria-label",`Show seats on map: ${c}`),r.addEventListener("click",()=>this.locate(a.id));let d=document.createElement("time");d.dateTime=new Date(a.at).toISOString(),d.textContent=new Date(a.at).toLocaleTimeString([],{hour:"2-digit",minute:"2-digit"});let h=document.createElement("strong");h.textContent=lt[a.verb]??a.verb,h.title=oe[a.verb]??a.verb;let p=document.createElement("span");if(p.className="slm-activity-seats",p.textContent=a.labels.join(", "),r.append(d,h,p),l.append(r),a.count>1){let u=document.createElement("details");u.className="slm-activity-details";let g=document.createElement("summary");g.textContent="\u22EF",g.setAttribute("aria-label",`Show all ${a.count} seats`);let f=document.createElement("p");f.textContent=c,u.append(g,f),l.append(u)}this.list.append(l)}this.more.hidden=t.length<=this.limit}}destroy(){this.abort.abort()}};var R=class{constructor(e){this.host=e;this.moving=!1;this.space=!1;this.monitor=!1;this.selected=0;this.abort=new AbortController;let t=document.createElement("div");t.className="slm-navigation";let s=b=>`<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">${b}</svg>`,i=s('<path d="M8 13V6a2 2 0 0 1 4 0v6-8a2 2 0 0 1 4 0v8-6a2 2 0 0 1 4 0v10c0 4-3 6-7 6-3 0-5-2-7-5l-3-4a2 2 0 0 1 3-2l2 2Z"/>'),o=s('<path d="m5 3 14 10-7 1-3 7-4-18Z"/>'),a=s('<circle cx="10.5" cy="10.5" r="6.5"/><path d="m16 16 5 5"/>'),l=s('<path d="M7 6h10M12 1v10M7 18h10"/>'),r=s('<rect x="3" y="4" width="18" height="16" rx="2"/><path d="M15 4v16"/>');t.innerHTML=`<div class="slm-navigation-tools" role="group" aria-label="Map navigation">
2
2
  <button type="button" data-nav="move" aria-label="Move" aria-pressed="false" title="Drag to move the map; hold Space temporarily">${i}</button>
3
- <button type="button" data-nav="select" aria-label="Select" aria-pressed="true" title="Drag to select seats \xB7 drag empty floor to move">${a}</button>
4
- <button type="button" data-nav="search" aria-label="Search" title="Search seats, rows or sections" aria-expanded="false">${o}</button>
3
+ <button type="button" data-nav="select" aria-label="Select" aria-pressed="true" title="Drag to select seats \xB7 drag empty floor to move">${o}</button>
4
+ <button type="button" data-nav="search" aria-label="Search" title="Search seats, rows or sections" aria-expanded="false">${a}</button>
5
5
  <button type="button" data-nav="zoom" aria-label="Zoom" title="Zoom controls" aria-expanded="false">${l}</button>
6
6
  <button type="button" hidden data-nav="out" aria-label="Zoom out">\u2212</button>
7
7
  <button type="button" hidden data-nav="in" aria-label="Zoom in">+</button>
8
8
  <span class="slm-navigation-count" role="status" aria-live="polite">0 selected</span>
9
9
  <button type="button" class="slm-navigation-clear" data-nav="clear" hidden title="Clear the selection">Clear</button>
10
10
  <button type="button" data-nav="rail" aria-label="Hide details" title="Hide details" aria-expanded="true">${r}</button>
11
- </div><div class="slm-navigation-search" hidden><input type="search" aria-label="Find section, row or seat" placeholder="Find section, row or seat"><div class="slm-navigation-results" hidden></div></div>`,e.map.after(t),this.bar=t,this.move=t.querySelector('[data-nav="move"]'),this.select=t.querySelector('[data-nav="select"]'),this.search=t.querySelector("input"),this.count=t.querySelector(".slm-navigation-count"),this.clear=t.querySelector('[data-nav="clear"]'),this.results=t.querySelector(".slm-navigation-results"),this.location=document.createElement("div"),this.location.className="slm-location",this.location.hidden=!0,this.location.setAttribute("role","status"),e.map.after(this.location);let c={signal:this.abort.signal},n=t.querySelector('[data-nav="search"]'),d=t.querySelector(".slm-navigation-search"),m=()=>{d.hidden=!0,this.results.hidden=!0,n.setAttribute("aria-expanded","false"),n.focus()};n.addEventListener("click",()=>{let u=d.hidden;d.hidden=!u,n.setAttribute("aria-expanded",String(u)),u&&this.search.focus()},c);let b=t.querySelector('[data-nav="zoom"]');b.addEventListener("click",()=>{let u=b.getAttribute("aria-expanded")!=="true";b.setAttribute("aria-expanded",String(u));for(let f of["in","out"])t.querySelector(`[data-nav="${f}"]`).hidden=!u},c),this.search.addEventListener("keydown",u=>{u.key==="Escape"&&m()},c),this.move.addEventListener("click",()=>this.setMoving(!0),c),this.select.addEventListener("click",()=>this.setMoving(!1),c),this.clear.addEventListener("click",()=>this.host.clearSelection(),c),t.querySelector('[data-nav="in"]').addEventListener("click",()=>{this.location.hidden=!0,e.pauseFollow(),e.zoomIn()},c),t.querySelector('[data-nav="out"]').addEventListener("click",()=>{this.location.hidden=!0,e.pauseFollow(),e.zoomOut()},c);let g=t.querySelector('[data-nav="rail"]');g.addEventListener("click",()=>{let u=e.root.classList.toggle("details-hidden");g.setAttribute("aria-expanded",String(!u)),g.setAttribute("aria-label",u?"Show details":"Hide details"),g.title=u?"Show details":"Hide details"},c),this.search.addEventListener("input",()=>this.find(),c),this.search.addEventListener("keydown",u=>{u.key==="Escape"&&(this.results.hidden=!0),u.key==="ArrowDown"&&(u.preventDefault(),this.results.querySelector("button")?.focus())},c),e.map.addEventListener("pointerdown",()=>{this.location.hidden=!0,e.pauseFollow(),e.root.focus({preventScroll:!0}),this.results.hidden=!0},{...c,capture:!0}),e.root.querySelector(".slm-rail")?.addEventListener("pointerdown",()=>e.pauseFollow(),{...c,capture:!0}),e.map.addEventListener("wheel",()=>{this.location.hidden=!0,e.pauseFollow()},{...c,passive:!0,capture:!0}),e.root.addEventListener("keydown",u=>{u.target?.closest('input,textarea,select,button,[contenteditable="true"]')||u.code!=="Space"||u.ctrlKey||u.metaKey||u.altKey||(u.preventDefault(),this.space||(this.space=!0,e.pauseFollow(),e.setMoving(!0)))},c);let v=()=>{this.space&&(this.space=!1,e.setMoving(this.moving))};window.addEventListener("keyup",u=>{u.code==="Space"&&v()},c),window.addEventListener("blur",v,c),window.addEventListener("resize",()=>{this.location.hidden=!0},c),e.root.querySelector('[data-ref="zfit"]')?.addEventListener("click",()=>{this.location.hidden=!0},c),e.root.addEventListener("focusout",u=>{e.root.contains(u.relatedTarget)||v()},c)}setMoving(e){this.moving=e,this.host.pauseFollow(),this.host.setMoving(e||this.space),this.move.setAttribute("aria-pressed",String(e)),this.select.setAttribute("aria-pressed",String(!e))}update(e,t=!1){this.monitor=t,this.count.hidden=t,this.paintClear(),this.move.hidden=!e,this.select.hidden=!e}selectionChanged(e){this.selected=e,this.count.textContent=`${e.toLocaleString()} selected`,this.paintClear()}paintClear(){this.clear.hidden=this.monitor||this.selected<1}find(){let e=this.search.value.trim();if(this.results.replaceChildren(),this.results.hidden=!e,!e)return;let t=this.host.targets(e);for(let s of t){let i=document.createElement("button");i.type="button",i.textContent=`${s.label} \xB7 ${s.detail}`,i.addEventListener("click",()=>{this.host.pauseFollow(),s.locate(),this.location.textContent=`${s.label} \xB7 ${s.detail}`,this.location.hidden=!1,this.results.hidden=!0,this.host.root.focus({preventScroll:!0})}),this.results.append(i)}t.length||(this.results.textContent="No matching section, row or seat.")}destroy(){this.abort.abort(),this.bar.remove(),this.location.remove()}};import{SeatmapRenderer as De,applyOrganizerSeatGlyph as Ne,clearOrganizerSeatGlyph as qe,isOrganizerGlyphPainted as _e,expandChart as Ve,computeSections as Ue,floorsOf as se,gaAreasOf as Ke,gaUnitLabels as Ge,UNGROUPED_ID as x}from"@seatlayer/core";var Be=/^[a-zA-Z0-9._-]+$/;function ze(h){let e;try{e=new URL(h,"https://seatlayer.invalid")}catch{return null}if(e.search||e.hash)return null;let t=/^\/v1\/events\/([^/]+)\/assets\/([^/]+)$/.exec(e.pathname);if(!t)return null;try{let s=decodeURIComponent(t[1]),i=decodeURIComponent(t[2]);return!s||!Be.test(i)?null:{eventKey:s,asset:i}}catch{return null}}function Ie(h){try{return/^\/v1\/events\/[^/]+\/assets(?:\/|$)/.test(new URL(h,"https://seatlayer.invalid").pathname)}catch{return!1}}var M=class{constructor(e,t){this.eventKey=e;this.load=t;this.pending=new Map;this.created=new Set;this.disposed=!1}resolve(e){let t=ze(e);if(!t)return Promise.resolve(Ie(e)?null:e);if(t.eventKey!==this.eventKey||this.disposed)return Promise.resolve(null);let s=`${t.eventKey}/${t.asset}`,i=this.pending.get(s);if(i)return i;let a=this.load(t.eventKey,t.asset).then(o=>{let l=URL.createObjectURL(o);return this.disposed?(URL.revokeObjectURL(l),null):(this.created.add(l),l)}).catch(o=>{throw this.pending.delete(s),o});return this.pending.set(s,a),a}async prepareRendererChart(e){let t=async a=>{if(!a?.url)return;let o=await this.resolve(a.url);if(!o)throw new Error("organizer_event_asset_scope_mismatch");a.url=o},s=async a=>{for(let o of a){if(o.type!=="decorImage")continue;let l=o,r=await this.resolve(l.href);if(!r)throw new Error("organizer_event_asset_scope_mismatch");l.href=r}},i=async a=>{await t(a.backgroundImage),await s(a.objects)};await i(e);for(let a of e.floors??[])await i(a);return e}dispose(){if(!this.disposed){this.disposed=!0;for(let e of this.created)URL.revokeObjectURL(e);this.created.clear(),this.pending.clear()}}};var q="seatlayer-manager-style",_="seatlayer-manager-channels-style",Oe=`
11
+ </div><div class="slm-navigation-search" hidden><input type="search" aria-label="Find section, row or seat" placeholder="Find section, row or seat"><div class="slm-navigation-results" hidden></div></div>`,e.map.after(t),this.bar=t,this.move=t.querySelector('[data-nav="move"]'),this.select=t.querySelector('[data-nav="select"]'),this.search=t.querySelector("input"),this.count=t.querySelector(".slm-navigation-count"),this.clear=t.querySelector('[data-nav="clear"]'),this.results=t.querySelector(".slm-navigation-results"),this.location=document.createElement("div"),this.location.className="slm-location",this.location.hidden=!0,this.location.setAttribute("role","status"),e.map.after(this.location);let c={signal:this.abort.signal},d=t.querySelector('[data-nav="search"]'),h=t.querySelector(".slm-navigation-search"),p=()=>{h.hidden=!0,this.results.hidden=!0,d.setAttribute("aria-expanded","false"),d.focus()};d.addEventListener("click",()=>{let b=h.hidden;h.hidden=!b,d.setAttribute("aria-expanded",String(b)),b&&this.search.focus()},c);let u=t.querySelector('[data-nav="zoom"]');u.addEventListener("click",()=>{let b=u.getAttribute("aria-expanded")!=="true";u.setAttribute("aria-expanded",String(b));for(let y of["in","out"])t.querySelector(`[data-nav="${y}"]`).hidden=!b},c),this.search.addEventListener("keydown",b=>{b.key==="Escape"&&p()},c),this.move.addEventListener("click",()=>this.setMoving(!0),c),this.select.addEventListener("click",()=>this.setMoving(!1),c),this.clear.addEventListener("click",()=>this.host.clearSelection(),c),t.querySelector('[data-nav="in"]').addEventListener("click",()=>{this.location.hidden=!0,e.pauseFollow(),e.zoomIn()},c),t.querySelector('[data-nav="out"]').addEventListener("click",()=>{this.location.hidden=!0,e.pauseFollow(),e.zoomOut()},c);let g=t.querySelector('[data-nav="rail"]');g.addEventListener("click",()=>{let b=e.root.classList.toggle("details-hidden");g.setAttribute("aria-expanded",String(!b)),g.setAttribute("aria-label",b?"Show details":"Hide details"),g.title=b?"Show details":"Hide details"},c),this.search.addEventListener("input",()=>this.find(),c),this.search.addEventListener("keydown",b=>{b.key==="Escape"&&(this.results.hidden=!0),b.key==="ArrowDown"&&(b.preventDefault(),this.results.querySelector("button")?.focus())},c),e.map.addEventListener("pointerdown",()=>{this.location.hidden=!0,e.pauseFollow(),e.root.focus({preventScroll:!0}),this.results.hidden=!0},{...c,capture:!0}),e.root.querySelector(".slm-rail")?.addEventListener("pointerdown",()=>e.pauseFollow(),{...c,capture:!0}),e.map.addEventListener("wheel",()=>{this.location.hidden=!0,e.pauseFollow()},{...c,passive:!0,capture:!0}),e.root.addEventListener("keydown",b=>{b.target?.closest('input,textarea,select,button,[contenteditable="true"]')||b.code!=="Space"||b.ctrlKey||b.metaKey||b.altKey||(b.preventDefault(),this.space||(this.space=!0,e.pauseFollow(),e.setMoving(!0)))},c);let f=()=>{this.space&&(this.space=!1,e.setMoving(this.moving))};window.addEventListener("keyup",b=>{b.code==="Space"&&f()},c),window.addEventListener("blur",f,c),window.addEventListener("resize",()=>{this.location.hidden=!0},c),e.root.querySelector('[data-ref="zfit"]')?.addEventListener("click",()=>{this.location.hidden=!0},c),e.root.addEventListener("focusout",b=>{e.root.contains(b.relatedTarget)||f()},c)}setMoving(e){this.moving=e,this.host.pauseFollow(),this.host.setMoving(e||this.space),this.move.setAttribute("aria-pressed",String(e)),this.select.setAttribute("aria-pressed",String(!e))}update(e,t=!1){this.monitor=t,this.count.hidden=t,this.paintClear(),this.move.hidden=!e,this.select.hidden=!e}selectionChanged(e){this.selected=e,this.count.textContent=`${e.toLocaleString()} selected`,this.paintClear()}paintClear(){this.clear.hidden=this.monitor||this.selected<1}find(){let e=this.search.value.trim();if(this.results.replaceChildren(),this.results.hidden=!e,!e)return;let t=this.host.targets(e);for(let s of t){let i=document.createElement("button");i.type="button",i.textContent=`${s.label} \xB7 ${s.detail}`,i.addEventListener("click",()=>{this.host.pauseFollow(),s.locate(),this.location.textContent=`${s.label} \xB7 ${s.detail}`,this.location.hidden=!1,this.results.hidden=!0,this.host.root.focus({preventScroll:!0})}),this.results.append(i)}t.length||(this.results.textContent="No matching section, row or seat.")}destroy(){this.abort.abort(),this.bar.remove(),this.location.remove()}};import{SeatmapRenderer as gt,applyOrganizerSeatGlyph as ft,clearOrganizerSeatGlyph as vt,isOrganizerGlyphPainted as yt,expandChart as xt,allObjects as wt,computeSections as kt,floorsOf as Ee,gaAreasOf as Re,gaUnitLabels as St,UNGROUPED_ID as v}from"@seatlayer/core";var nt=/^[a-zA-Z0-9._-]+$/;function rt(n){let e;try{e=new URL(n,"https://seatlayer.invalid")}catch{return null}if(e.search||e.hash)return null;let t=/^\/v1\/events\/([^/]+)\/assets\/([^/]+)$/.exec(e.pathname);if(!t)return null;try{let s=decodeURIComponent(t[1]),i=decodeURIComponent(t[2]);return!s||!nt.test(i)?null:{eventKey:s,asset:i}}catch{return null}}function ct(n){try{return/^\/v1\/events\/[^/]+\/assets(?:\/|$)/.test(new URL(n,"https://seatlayer.invalid").pathname)}catch{return!1}}var A=class{constructor(e,t){this.eventKey=e;this.load=t;this.pending=new Map;this.created=new Set;this.disposed=!1}resolve(e){let t=rt(e);if(!t)return Promise.resolve(ct(e)?null:e);if(t.eventKey!==this.eventKey||this.disposed)return Promise.resolve(null);let s=`${t.eventKey}/${t.asset}`,i=this.pending.get(s);if(i)return i;let o=this.load(t.eventKey,t.asset).then(a=>{let l=URL.createObjectURL(a);return this.disposed?(URL.revokeObjectURL(l),null):(this.created.add(l),l)}).catch(a=>{throw this.pending.delete(s),a});return this.pending.set(s,o),o}async prepareRendererChart(e){let t=async o=>{if(!o?.url)return;let a=await this.resolve(o.url);if(!a)throw new Error("organizer_event_asset_scope_mismatch");o.url=a},s=async o=>{for(let a of o){if(a.type!=="decorImage")continue;let l=a,r=await this.resolve(l.href);if(!r)throw new Error("organizer_event_asset_scope_mismatch");l.href=r}},i=async o=>{await t(o.backgroundImage),await s(o.objects)};await i(e);for(let o of e.floors??[])await i(o);return e}dispose(){if(!this.disposed){this.disposed=!0;for(let e of this.created)URL.revokeObjectURL(e);this.created.clear(),this.pending.clear()}}};function ae(n,e,t,s={}){let i=s.previous?null:document.activeElement??null;s.previous?.scrim.remove();let o=document.createElement("div");o.className="slm-ch-scrim",o.innerHTML=`<div class="slm-ch-dialog" role="dialog" aria-modal="true"
12
+ aria-labelledby="slm-ch-dlg-title" tabindex="-1">${e}</div>`,n.appendChild(o);let a=o.firstElementChild,l=!1,r={scrim:o,dialog:a,close:({restoreFocus:d=!0}={})=>{l||(l=!0,o.remove(),d&&i?.focus?.(),s.onClose?.())}};return a.querySelectorAll("[data-ch-close]").forEach(d=>{d.addEventListener("click",()=>r.close())}),o.addEventListener("keydown",d=>{if(d.key==="Escape"){d.stopPropagation(),r.close();return}if(d.key!=="Tab")return;let h=[...a.querySelectorAll('summary,button:not([disabled]),select:not([hidden]),input,textarea,a[href],[tabindex]:not([tabindex="-1"])')];if(!h.length)return;let p=h[0],u=h[h.length-1];d.shiftKey&&document.activeElement===p?(d.preventDefault(),u.focus()):!d.shiftKey&&document.activeElement===u&&(d.preventDefault(),p.focus())}),t(a),L(a),(a.querySelector("input,summary,button")??a).focus(),r}var le=`
13
+ .slm{--slm-ch-scrim:rgba(0,0,0,.58)}
14
+ .slm[data-theme=light]{--slm-ch-scrim:rgba(23,32,51,.42)}
15
+ .slm-ch-scrim{position:absolute;inset:0;z-index:12;background:var(--slm-ch-scrim);display:grid;place-items:center;
16
+ padding:18px;animation:slm-ch-fade var(--slm-mo-quick) var(--slm-mo-out)}
17
+ .slm-ch-dialog{width:min(460px,100%);max-height:100%;overflow:auto;overscroll-behavior:contain;background:var(--slm-surface);color:var(--slm-text);border:1px solid var(--slm-line);
18
+ border-radius:14px;padding:20px;box-shadow:0 24px 70px rgba(0,0,0,.6);
19
+ animation:slm-ch-rise var(--slm-mo-base) var(--slm-mo-out)}
20
+ .slm-ch-dialog h3{margin:0 0 4px;font-size:16px;font-weight:800;letter-spacing:-.01em}
21
+ .slm-ch-dialog .sub{font-size:12.5px;color:var(--slm-muted);line-height:1.5;margin-bottom:14px}
22
+ .slm-ch-dialog .foot{display:flex;gap:8px;margin-top:16px}
23
+ .slm-ch-dialog .foot .slm-btn{flex:1;min-width:0}
24
+ .slm-ch-dialog .foot .quiet{flex:none;padding:10px 14px;min-height:44px;color:var(--slm-muted);font-weight:700;font-size:13px}
25
+ @keyframes slm-ch-fade{from{opacity:0}to{opacity:1}}
26
+ @keyframes slm-ch-rise{from{opacity:0;transform:translateY(10px) scale(.985)}to{opacity:1;transform:none}}
27
+ .slm-ch-err{color:var(--slm-text);font-size:11.5px;margin-top:6px}
28
+ .slm-ch-seatlist{max-height:44vh;overflow:auto;overscroll-behavior:contain;border:1px solid var(--slm-line);
29
+ border-radius:10px;background:var(--slm-surface);margin-top:10px}
30
+ .slm-ch-seatgroup{padding:8px 10px;border-bottom:1px solid var(--slm-line);display:flex;align-items:center;
31
+ justify-content:space-between;gap:8px;font-size:11px;font-weight:800;color:var(--slm-muted);position:sticky;top:0;
32
+ background:var(--slm-surface)}
33
+ .slm-ch-seatgroup button{color:var(--slm-accent);font-weight:800;font-size:11px;min-height:32px}
34
+ .slm-ch-seatitem{display:flex;width:100%;min-height:40px;align-items:center;gap:9px;padding:8px 10px;border-bottom:1px solid var(--slm-line);
35
+ text-align:left;font-size:12.5px;line-height:1.3;color:var(--slm-text)}
36
+ .slm-ch-seatitem:hover:not(:disabled){background:var(--slm-tint)}
37
+ .slm-ch-seatitem .box{width:16px;height:16px;border-radius:4px;border:1px solid var(--slm-muted);display:grid;
38
+ place-items:center;font-size:10px;font-weight:900;color:transparent;flex:none}
39
+ .slm-ch-seatitem[aria-checked="true"] .box{border-color:var(--slm-accent);background:var(--slm-accent);color:var(--slm-accent-ink)}
40
+ .slm-ch-seatitem .meta{margin-left:auto;color:var(--slm-muted);font-size:10.5px}
41
+ .slm-ch-seatitem:disabled{opacity:.55;cursor:not-allowed}
42
+ .slm-ch-seatitem .dot{width:9px;height:9px;border-radius:999px;flex:none}
43
+ /* Seat list as the map reads: section \u2192 row line \u2192 seat chips tinted by status. */
44
+ /* The seat list gets a wider plate than the pickers: rows of chips need air. */
45
+ .slm-ch-dialog:has(.slm-ch-seatlist.grid){width:min(560px,100%);padding:22px 22px 20px}
46
+ .slm-ch-dialog:has(.slm-ch-seatlist.grid) .sub{margin-bottom:18px}
47
+ .slm-ch-seatlist-tools{display:flex;align-items:center;gap:14px;margin:0 0 14px}
48
+ .slm-ch-seatlist-tools .slm-find{flex:1;margin:0}
49
+ .slm-ch-seatlist-tools .slm-find .slm-input{min-height:34px}
50
+ .slm-ch-seatlegend{flex:none;display:flex;align-items:center;gap:4px 6px;flex-wrap:wrap;font-size:10.5px;color:var(--slm-muted);font-weight:700}
51
+ .slm-ch-seatlegend i{display:inline-block;width:10px;height:10px;border-radius:3px;margin-right:1px;vertical-align:-1px}
52
+ .slm-ch-seatlist.grid{max-height:52vh;margin-top:0}
53
+ .slm-ch-seatlist.grid .slm-ch-seatgroup{padding:10px 18px;letter-spacing:.06em;text-transform:uppercase;font-size:10.5px;background:var(--slm-tint)}
54
+ .slm-ch-seatlist.grid .slm-ch-seatgroup button{text-transform:none;letter-spacing:0}
55
+ .slm-ch-seatrow{display:grid;grid-template-columns:112px minmax(0,1fr);align-items:start;gap:16px;padding:12px 18px;border-bottom:1px solid var(--slm-line)}
56
+ .slm-ch-seatrow.loose{grid-template-columns:minmax(0,1fr)}
57
+ .slm-ch-seatrow:last-child{border-bottom:0}
58
+ .slm-ch-rowcheck{display:flex;align-items:center;gap:8px;min-height:32px;padding:4px 6px;margin-left:-6px;border-radius:7px;font-size:12px;font-weight:800;color:var(--slm-text);text-align:left}
59
+ .slm-ch-rowcheck:hover{background:var(--slm-tint)}
60
+ .slm-ch-rowcheck .box{width:15px;height:15px;flex:none;display:grid;place-items:center;border:1.5px solid var(--slm-muted);border-radius:4px;color:transparent;font-size:9px;font-weight:900;box-sizing:border-box}
61
+ .slm-ch-rowcheck[aria-checked="true"] .box{border-color:var(--slm-accent);background:var(--slm-accent);color:var(--slm-accent-ink)}
62
+ .slm-ch-rowcheck[aria-checked="mixed"] .box{border-color:var(--slm-accent);background:linear-gradient(var(--slm-accent),var(--slm-accent)) center/7px 2px no-repeat}
63
+ .slm-ch-rowcheck .name{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
64
+ .slm-ch-rowcheck .meta{margin-left:auto;padding-left:8px;color:var(--slm-muted);font-size:10.5px;font-weight:700;font-variant-numeric:tabular-nums}
65
+ .slm-ch-seatchips{display:flex;flex-wrap:wrap;gap:7px;padding:1px 0}
66
+ .slm .slm-ch-seatchip{min-width:34px;height:34px;padding:0 9px;border-radius:9px;border:1.5px solid var(--slm-line);background:var(--slm-surface);color:var(--slm-text);
67
+ font-size:11.5px;font-weight:800;font-variant-numeric:tabular-nums;box-sizing:border-box;line-height:1;position:relative}
68
+ .slm-ch-seatchip:hover{border-color:var(--slm-muted)}
69
+ .slm-ch-seatchip:focus-visible{outline:2px solid var(--slm-accent);outline-offset:1px}
70
+ .slm .slm-ch-seatchip.is-free,.slm-ch-seatlegend .is-free{border:1.5px solid;border-color:color-mix(in srgb,var(--slm-accent) 45%,var(--slm-line));background:color-mix(in srgb,var(--slm-accent) 10%,var(--slm-surface))}
71
+ .slm .slm-ch-seatchip.is-held,.slm-ch-seatlegend .is-held{border:1.5px solid;border-color:#f4b740;background:color-mix(in srgb,#f4b740 22%,var(--slm-surface))}
72
+ .slm .slm-ch-seatchip.is-booked,.slm-ch-seatlegend .is-booked{border:1.5px solid transparent;background:color-mix(in srgb,var(--slm-muted) 35%,var(--slm-surface));color:var(--slm-muted)}
73
+ .slm .slm-ch-seatchip.is-blocked,.slm-ch-seatlegend .is-blocked{border:1.5px dashed;border-color:var(--slm-muted);color:var(--slm-muted);background:transparent}
74
+ .slm .slm-ch-seatchip[aria-checked="true"]{border:1.5px solid var(--slm-accent);background:var(--slm-accent);color:var(--slm-accent-ink);box-shadow:0 0 0 2px color-mix(in srgb,var(--slm-accent) 30%,transparent)}
75
+ .slm-ch-seatfoot{align-items:center;gap:10px;margin-top:18px;padding-top:16px;border-top:1px solid var(--slm-line)}
76
+ .slm-ch-seatfoot .slm-ch-seatcount{flex:1;min-width:0;font-size:12px;font-weight:700;color:var(--slm-muted);font-variant-numeric:tabular-nums}
77
+ .slm-ch-seatfoot .slm-btn{flex:none;min-width:110px}
78
+ .slm-ch-seatfoot .quiet:disabled{opacity:.45}
79
+ .slm-ch-scopebar{display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:end;gap:10px;margin-top:12px}
80
+ .slm-ch-scopebar label{display:grid;gap:5px;color:var(--slm-muted);font-size:10.5px;font-weight:800}
81
+ .slm-ch-scopebar input{width:100%;min-height:40px;padding:8px 10px;border:1px solid var(--slm-line);border-radius:8px;
82
+ background:var(--slm-surface);color:var(--slm-text);font:inherit}
83
+ .slm-ch-scopesummary{padding-bottom:10px;color:var(--slm-muted);font-size:11px;font-variant-numeric:tabular-nums;white-space:nowrap}
84
+ .slm-ch-scopegroup{position:sticky;top:0;z-index:1;display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:center;
85
+ gap:6px;padding:6px 8px;border-bottom:1px solid var(--slm-line);background:var(--slm-surface)}
86
+ .slm-ch-groupcheck{display:flex;min-width:0;align-items:center;gap:8px;padding:5px 2px;text-align:left;font-size:11px;font-weight:800}
87
+ .slm-ch-groupcheck .box{width:16px;height:16px;flex:none;display:grid;place-items:center;border:1px solid var(--slm-muted);border-radius:4px;
88
+ color:transparent;font-size:10px}
89
+ .slm-ch-groupcheck[aria-checked="true"] .box,.slm-ch-groupcheck[aria-checked="mixed"] .box{border-color:var(--slm-accent);
90
+ background:var(--slm-accent);color:var(--slm-accent-ink)}
91
+ .slm-ch-groupcheck .meta{min-width:0;margin-left:auto;color:var(--slm-muted);font-size:10.5px;font-weight:600;white-space:nowrap}
92
+ .slm-ch-grouptoggle{min-height:32px;padding:5px 8px;color:var(--slm-accent);font-size:11px;font-weight:800}
93
+ .slm-ch-scopehint{padding:8px 10px;color:var(--slm-muted);font-size:10.5px;border-bottom:1px solid var(--slm-line)}
94
+ .slm-ch-scope-empty{padding:18px 12px;color:var(--slm-muted);font-size:11.5px;text-align:center}
95
+ @media(max-width:560px){.slm-ch-scopebar{grid-template-columns:1fr}.slm-ch-scopesummary{padding-bottom:0}}
96
+ @media (prefers-reduced-motion:reduce){.slm-ch-scrim,.slm-ch-dialog{animation:none!important}}
97
+ `;var ne="seatlayer-manager-style",re="seatlayer-manager-channels-style",dt=`${le}
12
98
  /* The floor was 480px, which trapped the cockpit in any host shorter than that:
13
99
  every ancestor here is overflow:hidden, so the bottom of the rail (Create
14
100
  channel, Show archived) was rendered but clipped away by the host and could
@@ -55,6 +141,7 @@ import{c as H,d as B,f as j}from"./chunk-RZ2VKZ44.js";import{A as Re,B as Ae,D a
55
141
  .slm-navigation-results{position:absolute;top:100%;left:0;right:0;max-height:240px;overflow:auto;padding:6px;background:var(--slm-surface);border:1px solid var(--slm-line);border-radius:8px;box-shadow:0 8px 24px #0003}
56
142
  .slm-navigation-results button{display:block;width:100%;text-align:left;margin-bottom:3px}
57
143
  .slm.details-hidden .slm-rail{display:none}
144
+ .slm.slm-minimal .slm-bar,.slm.slm-minimal .slm-rail,.slm.slm-minimal .slm-railhead,.slm.slm-minimal .slm-navigation-tools,.slm.slm-minimal .slm-blocklegend,.slm.slm-minimal .slm-minimap-mount,.slm.slm-minimal .slm-hint,.slm.slm-minimal .slm-eyebrow,.slm.slm-minimal .slm-note{display:none}
58
145
  .slm button:focus-visible,.slm input:focus-visible{outline:2px solid var(--slm-accent);outline-offset:2px}
59
146
  .slm[data-theme="light"] .slm-scope.read{color:#465169}
60
147
  .slm[data-theme="light"] .slm-scope.event,.slm[data-theme="light"] .slm-tablelock,.slm[data-theme="light"] .slm-kpidelta.down{color:#805500!important}
@@ -152,12 +239,63 @@ import{c as H,d as B,f as j}from"./chunk-RZ2VKZ44.js";import{A as Re,B as Ae,D a
152
239
  .slm-follow-status,.slm-heat-status{position:absolute;bottom:14px;right:12px;max-width:calc(100% - 120px);padding:6px 9px;border:1px solid var(--slm-line);border-radius:8px;background:var(--slm-bg);color:var(--slm-text);font-size:11px;z-index:5;pointer-events:none}
153
240
  .slm-heat-status{bottom:48px}
154
241
  .slm-barbtn.follow.on{background:rgba(34,160,107,.13);border-color:#22a06b;color:#5bd39b}
242
+ /* Full screen wears the View summary's box. It is a real <button>, so the
243
+ ".slm button" reset outranks the plain .slm-barbtn border \u2014 hence the
244
+ extra .slm here. Label hidden on the compact bar; the name is aria-label. */
245
+ .slm .slm-barbtn.slm-fullscreen{display:inline-flex;align-items:center;gap:6px;flex:none;white-space:nowrap;min-height:30px;padding:5px 10px;
246
+ border:1px solid var(--slm-line);border-radius:8px;font-size:12px}
247
+ .slm .slm-barbtn.slm-fullscreen:hover{border-color:var(--slm-muted)}
248
+ .slm-fullscreen-icon{display:inline-flex}
155
249
 
156
250
  /* body */
157
251
  .slm-body{display:flex;flex:1;min-height:0}
158
252
  .slm-map{position:relative;flex:1;min-width:0}
159
253
  .slm-map-host{position:absolute;inset:0}
160
254
  .slm-hud{position:absolute;left:12px;bottom:12px;display:flex;gap:8px}
255
+ /* Map chrome (plan item 7): crumb \xB7 zoom pills \xB7 minimap, one corner, bottom-right. */
256
+ .slm-mapchrome{position:absolute;right:12px;bottom:12px;z-index:5;display:flex;flex-direction:column;align-items:flex-end;gap:10px;pointer-events:none}
257
+ .slm-mapchrome>*{pointer-events:auto}
258
+ .slm-crumb{max-width:260px;padding:6px 11px;border-radius:999px;font-size:11.5px;font-weight:700;color:var(--slm-text);
259
+ background:color-mix(in srgb,var(--slm-surface) 88%,transparent);border:1px solid var(--slm-line);backdrop-filter:blur(8px);
260
+ white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-variant-numeric:tabular-nums}
261
+ .slm-blocklegend{display:flex;gap:10px;padding:5px 10px;border-radius:999px;font-size:10.5px;font-weight:700;color:var(--slm-muted);
262
+ background:color-mix(in srgb,var(--slm-surface) 88%,transparent);border:1px solid var(--slm-line);backdrop-filter:blur(8px);white-space:nowrap}
263
+ .slm-blocklegend span{display:inline-flex;align-items:center;gap:5px}
264
+ .slm-blocklegend i{width:9px;height:9px;border-radius:3px;display:inline-block}
265
+ /* Bottom-left of the map, clear of the zoom column and minimap on the right. */
266
+ .slm-blocklegend{position:absolute;left:12px;bottom:12px;z-index:5;align-items:center;flex-wrap:wrap;justify-content:flex-start;max-width:calc(100% - 250px);white-space:normal;row-gap:6px}
267
+ .slm.compact .slm-blocklegend{left:8px;bottom:8px;max-width:calc(100% - 96px)}
268
+ .slm-blocklegend i.seat{border-radius:50%}
269
+ .slm-legend-items{display:inline-flex;flex-wrap:wrap;align-items:center;gap:6px 10px}
270
+ .slm-colourby{display:inline-flex;padding:2px;border-radius:999px;background:var(--slm-line);gap:2px}
271
+ .slm .slm-colourby button{border:0;border-radius:999px;padding:3px 9px;font:inherit;font-size:10.5px;font-weight:700;color:var(--slm-muted);background:transparent;cursor:pointer}
272
+ .slm .slm-colourby button.on{color:var(--slm-text);background:var(--slm-surface);box-shadow:0 1px 2px rgba(0,0,0,.12)}
273
+ .slm .slm-colourby button:focus-visible{outline:2px solid var(--slm-accent,#6e7bff);outline-offset:1px}
274
+ .slm-blocklegend[hidden]{display:none}
275
+ .slm-zoom{display:flex;flex-direction:column;gap:5px;align-items:flex-end}
276
+ .slm .slm-zoombtn{width:34px;height:34px;padding:0;border-radius:10px;border:1px solid var(--slm-line);background:color-mix(in srgb,var(--slm-surface) 88%,transparent);
277
+ backdrop-filter:blur(8px);color:var(--slm-text);font-size:17px;font-weight:700;line-height:1;box-shadow:0 8px 24px -14px rgba(0,0,0,.6);display:grid;place-items:center}
278
+ .slm .slm-zoombtn.slm-zoombtn-venue{width:auto;padding:0 11px;font-size:11.5px;font-weight:800;letter-spacing:.02em}
279
+ .slm .slm-zoombtn:hover:not(:disabled){border-color:var(--slm-muted)}
280
+ .slm .slm-zoombtn:focus-visible{outline:2px solid var(--slm-accent);outline-offset:1px}
281
+ .slm .slm-zoombtn:disabled{opacity:.42;cursor:default}
282
+ .slm-minimap-mount{line-height:0}
283
+ .slm-minimap-mount:empty{display:none}
284
+ .slm .sl-minimap{border:1px solid var(--slm-line);border-radius:9px;overflow:hidden;background:var(--slm-surface);
285
+ box-shadow:0 12px 34px -14px rgba(0,0,0,.55);line-height:0;touch-action:none}
286
+ .slm .sl-minimap-bar{min-height:24px;padding:3px 5px 3px 8px;display:flex;align-items:center;gap:6px;border-bottom:1px solid var(--slm-line);
287
+ color:var(--slm-muted);font-size:9px;font-weight:800;line-height:1.2;letter-spacing:.06em;text-transform:uppercase}
288
+ .slm .sl-minimap-label{min-width:0;flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
289
+ .slm .sl-minimap-key{display:inline-flex;align-items:center;gap:3px;flex:none}
290
+ .slm .sl-minimap-key i{width:6px;height:6px;border-radius:999px;background:var(--slm-success,#22a06b)}
291
+ .slm .sl-minimap-key i.selected{background:var(--slm-accent)}
292
+ .slm .sl-minimap-key i.inactive{background:var(--slm-muted);opacity:.45}
293
+ .slm .sl-minimap-key i.focused{background:transparent;border:1.5px solid var(--slm-accent);width:7px;height:7px}
294
+ .slm .sl-minimap-close,.slm .sl-minimap-toggle{display:none}
295
+ .slm .sl-minimap canvas{display:block}
296
+ .slm .sl-minimap canvas:focus-visible{outline:2px solid var(--slm-accent);outline-offset:-3px}
297
+ .slm .sl-minimap canvas.sl-dragging{cursor:grabbing}
298
+ .slm.compact .slm-mapchrome{right:8px;bottom:8px}
161
299
  .slm .slm-hud-chip{padding:6px 11px;border-radius:999px;font-size:12px;font-weight:700;background:var(--slm-surface);
162
300
  border:1px solid var(--slm-line);color:var(--slm-text)}
163
301
  /* ONE top-centre lane. The zoom hint, the live-event pill and the Channels
@@ -171,6 +309,13 @@ import{c as H,d as B,f as j}from"./chunk-RZ2VKZ44.js";import{A as Re,B as Ae,D a
171
309
  push the others down by its own height plus the gap. Taken out of flow
172
310
  rather than display:none'd, so the fade in and out still runs. */
173
311
  .slm-lane>:not(.on){position:absolute;top:0;pointer-events:none}
312
+ /* The session-ended card: the map stays painted under it; one way back. */
313
+ .slm-ended{display:flex;flex-direction:column;gap:8px;width:360px;max-width:calc(100vw - 48px);box-sizing:border-box;padding:16px 18px;border-radius:12px;pointer-events:auto;
314
+ background:var(--slm-surface);border:1px solid var(--slm-line);box-shadow:0 18px 48px rgba(0,0,0,.3);color:var(--slm-text);text-align:left}
315
+ .slm-ended strong{font-size:14px;font-weight:800}
316
+ .slm-ended span{font-size:12.5px;line-height:1.5;color:var(--slm-muted)}
317
+ .slm-ended .slm-btn{align-self:flex-start;min-width:0;flex:none;margin-top:4px}
318
+ .slm-ended[data-busy="true"] .slm-btn{opacity:.6;pointer-events:none}
174
319
  .slm-zoomhint{padding:6px 13px;border-radius:999px;
175
320
  background:color-mix(in srgb,var(--slm-surface) 92%,transparent);color:var(--slm-text);
176
321
  border:1px solid var(--slm-line);font-size:12px;font-weight:700;pointer-events:none;opacity:0;
@@ -226,6 +371,77 @@ import{c as H,d as B,f as j}from"./chunk-RZ2VKZ44.js";import{A as Re,B as Ae,D a
226
371
 
227
372
  /* block toolbar */
228
373
  .slm-selbar{display:flex;align-items:baseline;gap:6px;margin-bottom:6px}
374
+ .slm-selbar .slm-selclear{margin-left:auto}
375
+ /* The shared seat chooser (plan item 5). Chips read as one quiet group \u2014 a
376
+ pill row, not four grey boxes \u2014 Find sits under them with its glyph, and
377
+ the selection bar is one line: the count, the tool's words, then two
378
+ small ghost buttons rather than link text in the accent colour (which
379
+ read as "disabled" next to the primary action). Tokens only, so the light
380
+ ground gets its own surface, line and ink. */
381
+ .slm-chooser{display:flex;flex-direction:column;gap:6px;margin-top:6px}
382
+ .slm-chooser .slm-ch-row2{display:flex;flex-wrap:wrap;gap:6px;margin:0}
383
+ .slm-chooser .slm-ch-row2 .slm-btn{flex:0 1 auto;min-width:0;min-height:32px;padding:6px 12px;border-radius:999px;
384
+ font-size:12px;font-weight:700;line-height:1.2;letter-spacing:0;
385
+ background:var(--slm-tint);border:1px solid var(--slm-line);color:var(--slm-text);box-shadow:none}
386
+ .slm-chooser .slm-ch-row2 .slm-btn:hover{border-color:var(--slm-muted);background:var(--slm-tint-strong)}
387
+ .slm-chooser .slm-ch-row2 .slm-btn:focus-visible{outline:2px solid var(--slm-accent);outline-offset:1px}
388
+ .slm-chooser .slm-ch-row2 .slm-btn:not(.ghost){background:var(--slm-accent);color:var(--slm-accent-ink);border-color:var(--slm-accent)}
389
+ .slm-find{position:relative;margin:2px 0 0}
390
+ .slm-find::before{content:"";position:absolute;left:11px;top:50%;width:13px;height:13px;transform:translateY(-50%);pointer-events:none;
391
+ background:currentColor;color:var(--slm-muted);
392
+ -webkit-mask:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.4' stroke-linecap='round'><circle cx='11' cy='11' r='7'/><path d='M20 20l-3.5-3.5'/></svg>") center/contain no-repeat;
393
+ mask:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.4' stroke-linecap='round'><circle cx='11' cy='11' r='7'/><path d='M20 20l-3.5-3.5'/></svg>") center/contain no-repeat}
394
+ .slm-find .slm-input{width:100%;box-sizing:border-box;margin:0;min-height:36px;padding:8px 10px 8px 32px;border-radius:10px;
395
+ background:var(--slm-surface);border:1px solid var(--slm-line);color:var(--slm-text);font-size:12.5px}
396
+ .slm-find .slm-input::placeholder{color:var(--slm-muted)}
397
+ .slm-find .slm-input:focus-visible{outline:2px solid var(--slm-accent);outline-offset:1px;border-color:var(--slm-accent)}
398
+ .slm-find-count{display:block;min-height:16px;margin:4px 0 0 2px;font-size:11px;color:var(--slm-muted);font-variant-numeric:tabular-nums}
399
+ .slm-find-count:empty{display:none}
400
+ .slm-selbar{display:flex;align-items:center;gap:8px;margin:10px 0 6px;padding:8px 0;border-top:1px solid var(--slm-line);border-bottom:1px solid var(--slm-line)}
401
+ .slm-selbar .slm-selactions{margin-left:auto;display:flex;gap:6px}
402
+ .slm-selbar .slm-selactions .slm-linkbtn,.slm-selbar .slm-selclear{min-height:28px;padding:4px 10px;border:1px solid var(--slm-line);border-radius:999px;white-space:nowrap;flex:none;
403
+ background:var(--slm-surface);color:var(--slm-text)!important;font-size:11.5px!important;font-weight:700!important;text-align:center}
404
+ .slm-selbar .slm-sellabel{min-width:0;line-height:1.3}
405
+ .slm-selbar .slm-selactions .slm-linkbtn:hover,.slm-selbar .slm-selclear:hover{border-color:var(--slm-muted);background:var(--slm-tint)}
406
+ .slm-selbar .slm-selclear{margin-left:0}
407
+ .slm-selbar .slm-selclear:disabled,.slm-selbar .slm-selactions .slm-linkbtn:disabled{opacity:.45}
408
+ .slm-catreset{margin-top:14px;padding-top:12px;border-top:1px solid var(--slm-line)}
409
+ .slm-catreset .slm-btn{width:100%}
410
+ .slm-catreset .slm-note{margin-top:6px}
411
+ /* The shared seat chooser (plan item 5): chip rows and the Find box under them. */
412
+ .slm-chooser{margin-top:2px}
413
+ .slm-find{position:relative;margin-top:8px}
414
+ .slm-find .slm-input{width:100%;box-sizing:border-box;margin:0;padding-right:8px}
415
+ .slm-find-count{display:block;min-height:16px;margin-top:4px;font-size:11px;color:var(--slm-muted);font-variant-numeric:tabular-nums}
416
+ .slm-find-count:empty{display:none}
417
+ /* Reading aids in the bar (plan item 5, slice D): the bar's Find and the View menu. */
418
+ .slm-findbar{flex:0 1 250px;min-width:120px}
419
+ .slm-findbar .slm-find{margin:0}
420
+ .slm-findbar .slm-find .slm-input{min-height:30px;padding:5px 9px 5px 30px;border-radius:8px;font-size:12px}
421
+ .slm-findbar .slm-find::before{left:10px;width:12px;height:12px}
422
+ .slm-findbar .slm-find-count{position:absolute;left:0;top:calc(100% + 3px);margin:0;padding:3px 9px;border-radius:7px;white-space:nowrap;z-index:5;
423
+ background:var(--slm-surface);border:1px solid var(--slm-line);color:var(--slm-text);font-size:11px;box-shadow:0 8px 24px rgba(0,0,0,.18)}
424
+ .slm-view{position:relative;flex:none}
425
+ .slm-view > summary{list-style:none;cursor:pointer;display:inline-flex;align-items:center;gap:5px;min-height:30px;padding:5px 10px;border-radius:8px;font-size:12px;user-select:none}
426
+ .slm-view > summary::-webkit-details-marker{display:none}
427
+ .slm-view > summary.away::after{content:"";width:6px;height:6px;border-radius:50%;background:var(--slm-accent)}
428
+ .slm-view[open] > summary{border-color:var(--slm-muted);background:var(--slm-tint)}
429
+ .slm-view-caret{font-size:10px;opacity:.7}
430
+ .slm-view-menu{position:absolute;right:0;top:calc(100% + 6px);z-index:30;min-width:238px;padding:6px;border-radius:12px;
431
+ background:var(--slm-surface);border:1px solid var(--slm-line);box-shadow:0 14px 40px rgba(0,0,0,.28)}
432
+ .slm-view-item{display:flex;align-items:center;gap:9px;width:100%;padding:7px 9px;border-radius:8px;border:0;background:transparent;color:var(--slm-text);font-size:12.5px;font-weight:600;text-align:left;cursor:pointer}
433
+ .slm-view-item:hover:not(:disabled){background:var(--slm-tint)}
434
+ .slm-view-item:focus-visible{outline:2px solid var(--slm-accent);outline-offset:-2px}
435
+ .slm-view-item:disabled{opacity:.45;cursor:default}
436
+ .slm-view-check{flex:none;width:15px;height:15px;border-radius:4px;border:1.5px solid var(--slm-muted);box-sizing:border-box}
437
+ .slm-view-item.on .slm-view-check{border-color:var(--slm-accent);background:var(--slm-accent);
438
+ -webkit-mask:none;mask:none;
439
+ background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' fill='none' stroke='white' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M2.5 6.4 5 8.9l4.6-5.6'/></svg>");background-size:11px;background-position:center;background-repeat:no-repeat}
440
+ .slm[data-theme="light"] .slm-view-item.on .slm-view-check{background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' fill='none' stroke='%230b1220' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M2.5 6.4 5 8.9l4.6-5.6'/></svg>")}
441
+ .slm-view-label{flex:1;min-width:0}
442
+ .slm-view-kbd{flex:none;font:600 10.5px/1 var(--slm-mono,ui-monospace,monospace);color:var(--slm-muted);padding:3px 5px;border:1px solid var(--slm-line);border-radius:5px}
443
+ .slm-view-note{margin:4px 3px 2px;padding:6px 8px 2px;border-top:1px solid var(--slm-line);font-size:11px;line-height:1.4;color:var(--slm-muted)}
444
+ .slm.compact .slm-findbar{flex:1 1 100%;min-width:0}
229
445
  .slm-selnum{font-size:26px;font-weight:800;font-variant-numeric:tabular-nums}
230
446
  .slm-sellabel{font-size:12px;color:var(--slm-muted);font-weight:600}
231
447
  .slm-row{display:flex;gap:8px;flex-wrap:wrap;margin-bottom:10px}
@@ -299,7 +515,7 @@ import{c as H,d as B,f as j}from"./chunk-RZ2VKZ44.js";import{A as Re,B as Ae,D a
299
515
  .slm-toast.ok{background:#1f7a4d;color:#fff;border-color:#1f7a4d}
300
516
 
301
517
  /* control-room actions + insights */
302
- .slm-bar-actions{display:flex;align-items:center;justify-self:end;gap:5px;flex-wrap:wrap}
518
+ .slm-bar-actions{display:flex;align-items:center;justify-self:end;gap:5px}
303
519
  .slm-barbtn.on{background:rgba(244,183,64,.13);border-color:#f4b740;color:var(--slm-text)}
304
520
  .slm-sectionlist{display:flex;flex-direction:column;gap:8px;margin-top:4px}
305
521
  .slm-sectionlist + .slm-eyebrow{margin-top:18px}
@@ -428,8 +644,9 @@ import{c as H,d as B,f as j}from"./chunk-RZ2VKZ44.js";import{A as Re,B as Ae,D a
428
644
  .slm.compact .slm-modes{display:none}
429
645
  .slm.compact .slm-tools{display:block;width:100%;padding:9px 13px;min-height:44px;border:1px solid var(--slm-line);
430
646
  border-radius:10px;background:var(--slm-surface);color:var(--slm-text);font-size:13px;font-weight:800}
431
- .slm.compact .slm-live{justify-self:end}.slm.compact .slm-bar-actions{grid-column:1/-1;justify-self:stretch}
432
- .slm.compact .slm-barbtn{flex:1;padding:6px 9px}.slm.compact .slm-kpis{grid-template-columns:repeat(4,minmax(0,1fr));gap:8px}
647
+ .slm.compact .slm-live{justify-self:end}.slm.compact .slm-bar-actions{grid-column:1/-1;justify-self:stretch;flex-wrap:wrap}
648
+ .slm.compact .slm-barbtn{flex:1;padding:6px 9px}
649
+ .slm.compact .slm-barbtn.slm-fullscreen{flex:none;justify-content:center;min-width:34px}.slm.compact .slm-fullscreen-label{display:none}.slm.compact .slm-kpis{grid-template-columns:repeat(4,minmax(0,1fr));gap:8px}
433
650
  .slm.compact .slm-kpi[data-kpi="viewing-map"],.slm.compact .slm-kpi[data-kpi="active-holds"],
434
651
  .slm.compact .slm-kpi[data-kpi="booked-pct"],.slm.compact .slm-kpi[data-kpi="booked-value"]{display:none}
435
652
  /* Reduced motion, as a BLANKET over the cockpit subtree rather than a list of
@@ -449,34 +666,65 @@ import{c as H,d as B,f as j}from"./chunk-RZ2VKZ44.js";import{A as Re,B as Ae,D a
449
666
  transition:none!important;
450
667
  scroll-behavior:auto!important}
451
668
  }
452
- `;function V(){if(typeof document>"u"||document.getElementById(q))return;let h=document.createElement("style");h.id=q,h.textContent=Oe,document.head.appendChild(h)}function U(h){if(typeof document>"u"||document.getElementById(_))return;let e=document.createElement("style");e.id=_,e.textContent=h,document.head.appendChild(e)}import{formatMoney as Fe}from"@seatlayer/core";function K(h){return h?h.mode:"open"}function G(h,e,t){switch(h){case"open":return null;case"hidden":return{mode:"hidden",labels:e};case"closed":return{mode:"closed",labels:e};case"timed":return{mode:"timed",revealAt:t?.revealAt??Date.now()+36e5,labels:e};case"threshold":return{mode:"threshold",thresholdPct:t?.thresholdPct??80,labels:e}}}function W(h){return new Date(h-new Date().getTimezoneOffset()*6e4).toISOString().slice(0,16)}function Z(h){if(typeof h=="string"){let e=document.querySelector(h);if(!e)throw new Error(`seatmanager: container "${h}" not found`);return e}if(!(h instanceof HTMLElement))throw new Error("seatmanager: container must be a CSS selector or an HTMLElement");return h}function I(h){if(!h.startsWith("mse_"))throw new Error("seatmanager: token must be a short-lived event-scoped mse_ grant minted by your backend; tenant secret keys are unsupported in browsers")}function E(h){return h==="blocked"?"not_for_sale":h}var je=["free","booked","held","blocked"],y={free:"#6e7bff",booked:"#9ca3af",held:"#f4b740",blocked:"#475569"},C={free:"Free",booked:"Sold",held:"Held",blocked:"Blocked"},Y=[`<span class="slm-legmark" style="background:${y.free}"></span> Free = category colour`,`<span class="slm-legmark" style="background:${y.booked}"></span> ${C.booked}`,`<span class="slm-legmark" style="background:${y.held}"></span> ${C.held}`,`<span class="slm-legcross" style="color:${y.blocked}">\u2715</span> ${C.blocked}`].join(" \xB7 "),X=je.map(h=>({key:h,label:C[h],color:y[h]}));function Q(h,e){let t=h??{},s=e?H[e]:null,i=e==="light";return{"--slm-bg":t.background??s?.background??"#0e1017","--slm-surface":s?.surface??"#181b24","--slm-text":s?.text??"#eef1f7","--slm-muted":s?.muted??"#8b93a7","--slm-line":s?.line??"rgba(255,255,255,.09)","--slm-tint":i?"rgba(23,32,51,.05)":"rgba(255,255,255,.035)","--slm-tint-strong":i?"rgba(23,32,51,.09)":"rgba(255,255,255,.07)","--slm-accent":t.accent??(i?"#4654c8":"#6e7bff"),"--slm-accent-ink":t.accentInk??"#ffffff","--slm-font":"-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif","--slm-radius":"14px"}}function J(h){return h?H[h].map:null}function ee(h,e){let t=Math.max(0,Math.round((e-h)/1e3));if(t<5)return"just now";if(t<60)return`${t}s ago`;let s=Math.round(t/60);return s<60?`${s}m ago`:`${Math.round(s/60)}h ago`}function R(h,e){return Fe(h,e,{maximumFractionDigits:0,fallback:(t,s)=>`${s} ${Math.round(t).toLocaleString()}`})}function p(h){return String(h??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#039;")}import{UNGROUPED_ID as Pe}from"@seatlayer/core";function O(h){return Object.entries(h).filter(([,e])=>e.mode==="closed").map(([e])=>e)}function A(h){let e=h.sectionsBase;if(!e)return{rows:[],hiddenSections:0,closedSections:0};let t=h.doc?.zones??[],s=new Map,i=[];for(let c of e.sections)if(c.zone&&t.some(n=>n.id===c.zone)){let n=s.get(c.zone)??[];n.push(c),s.set(c.zone,n)}else i.push(c);let a=[],o=0,l=0,r=(c,n,d,m=!1)=>{let b=h.availabilityRules[n.id]??null,g=h.effectiveClosed.has(n.id)||m,v=h.effectiveHidden.has(n.id)||d&&!g;c==="section"&&v&&(o+=1),c==="section"&&g&&(l+=1),a.push({kind:c,id:n.id,label:n.label,seatCount:n.seatCount,seatLabels:n.seatLabels,rule:b,hidden:v,closed:g,followsZone:c==="section"&&d})};for(let c of t){let n=s.get(c.id);if(!n||!n.length)continue;let d={id:c.id,label:c.label||"Zone",seatCount:n.reduce((g,v)=>g+v.seatCount,0),seatLabels:n.flatMap(g=>g.seatLabels)},m=!!h.availabilityRules[c.id],b=h.availabilityRules[c.id]?.mode==="closed";r("zone",d,!1);for(let g of n)r("section",g,m,b)}for(let c of i)r("section",c,!1);if(e.ungrouped){let c=e.ungrouped;r("section",{id:Pe,label:c.label,seatCount:c.seatCount,seatLabels:c.seatLabels},!1)}return{rows:a,hiddenSections:o,closedSections:l}}function te(h,e){let t=K(h.rule),s=`slm-availrow${h.kind==="zone"?" zone":""}${h.hidden?" hidden":""}${h.closed?" closed":""}`,i=e?" disabled":"",a=[["open","Open","Available to buy"],["closed","Closed","Visible on the map, unavailable to buy"],["hidden","Hidden","Removed from the buyer map"],["timed","Scheduled reveal","Open at a specific date and time"],["threshold","Demand-based reveal","Open when sales reach a percentage"]],o=h.followsZone?'<span class="slm-availfollows">Follows zone</span>':`<details class="slm-availpicker" data-avail-picker>
453
- <summary aria-label="Availability for ${p(h.label)}" ${e?'aria-disabled="true"':""}>${a.find(n=>n[0]===t)[1]}<span aria-hidden="true">\u2304</span></summary>
454
- <div class="slm-availchoices" aria-label="Availability options for ${p(h.label)}">
455
- ${a.map(([n,d,m])=>`<button type="button" data-avail-id="${p(h.id)}" data-avail-value="${n}" aria-pressed="${t===n}"${i}><span><b>${d}</b><small>${m}</small></span><span aria-hidden="true">${t===n?"\u2713":""}</span></button>`).join("")}
669
+ `;function ce(){if(typeof document>"u"||document.getElementById(ne))return;let n=document.createElement("style");n.id=ne,n.textContent=dt,document.head.appendChild(n)}function de(n){if(typeof document>"u"||document.getElementById(re))return;let e=document.createElement("style");e.id=re,e.textContent=n,document.head.appendChild(e)}function he(n){return n.total==null||n.free==null?n.label:n.free<=0?`${n.label} \xB7 sold out`:`${n.label} \xB7 ${n.free.toLocaleString()} of ${n.total.toLocaleString()} free`}function me(n){let t=_({focusedSection:n.focused?n.focused.label:null,seatsRevealed:n.seatsRevealed,atVenueFit:n.atVenueFit})==="none";return{crumb:n.focused?n.floor?`${n.floor} \xB7 ${he(n.focused)}`:he(n.focused):n.floor??"Venue",crumbShown:!!n.focused||!!n.floor,zoomInEnabled:!n.atCeiling,zoomOutEnabled:!t,venueEnabled:!t}}function pe(n={}){return`
670
+ <div class="slm-mapchrome" data-ref="mapchrome">
671
+ ${n.legend??""}
672
+ <div class="slm-crumb" data-ref="crumb" role="status" hidden></div>
673
+ <div class="slm-zoom" role="group" aria-label="Zoom">
674
+ <button type="button" class="slm-zoombtn" data-ref="zin" aria-label="Zoom in" title="Zoom in">+</button>
675
+ <button type="button" class="slm-zoombtn" data-ref="zout" aria-label="Zoom out one step" title="Zoom out one step (section, then venue)">\u2212</button>
676
+ <button type="button" class="slm-zoombtn slm-zoombtn-venue" data-ref="zfit" title="Whole venue">Venue</button>
677
+ </div>
678
+ <div class="slm-minimap-mount" data-ref="minimap"></div>
679
+ </div>`}function ue(n,e){n.crumb&&(n.crumb.textContent=e.crumb,n.crumb.hidden=!e.crumbShown);let t=(s,i)=>{s&&(s.disabled=!i,s.setAttribute("aria-disabled",String(!i)))};t(n.zin,e.zoomInEnabled),t(n.zout,e.zoomOutEnabled),t(n.zfit,e.venueEnabled)}var w={plenty:{min:.5,color:"#22a06b",label:"Plenty left",detail:"over half"},tight:{min:.15,color:"#f4b740",label:"Filling up",detail:"under half"},gone:{min:0,color:"#d9534f",label:"Nearly gone",detail:"under 15%"}},S={free:"#5b6db0",held:"#f4b740",sold:"#9ca3af"};function ht(n,e){let t=e>0?n/e:0;return t>=w.plenty.min?"plenty":t>=w.tight.min?"tight":"gone"}function mt(n,e,t,s=Date.now()){return n?.mode==="closed"||t?"Closed":n?.mode==="timed"&&n.revealAt&&n.revealAt>s?`Hidden until ${pt(n.revealAt,s)}`:n?.mode==="threshold"&&e?`Hidden until ${n.thresholdPct??0}% sold`:n?.mode==="hidden"||e?"Hidden":null}function pt(n,e){let t=new Date(n),s=t.toLocaleTimeString(void 0,{hour:"numeric",minute:t.getMinutes()?"2-digit":void 0}),i=(n-e)/864e5;return i<1&&t.getDate()===new Date(e).getDate()?s:i<6?`${t.toLocaleDateString(void 0,{weekday:"short"})} ${s}`:t.toLocaleDateString(void 0,{day:"numeric",month:"short"})}function be(n,e){let t=n.state==="sold-out"?"Sold out":mt(e.rule,e.hiddenNow,e.closedNow);return{tint:t==="Closed"||t==="Sold out"?null:e.colourBy==="type"?e.typeTint??null:w[ht(n.free,n.total)].color,stateWord:t}}function ge(){return`<div class="slm-blocklegend" data-ref="blocklegend" role="group" aria-label="Map colours">
680
+ <span class="slm-colourby" role="radiogroup" aria-label="Colour by">
681
+ <button type="button" role="radio" data-colour-by="full" aria-checked="true">How full</button>
682
+ <button type="button" role="radio" data-colour-by="type" aria-checked="false">Ticket type</button>
683
+ </span>
684
+ <span class="slm-legend-items" data-ref="legenditems"></span>
685
+ </div>`}function ut(n){let e=n.seats;return n.colourBy==="full"&&!e?[...Object.keys(w).map(t=>({label:`${w[t].label} \xB7 ${w[t].detail}`,color:w[t].color,seat:!1})),{label:"Sold out",color:S.sold,seat:!1}]:n.colourBy==="full"?[{label:"Free",color:S.free,seat:!0},{label:"Held",color:S.held,seat:!0},{label:"Sold",color:S.sold,seat:!0}]:[...n.types.map(t=>({label:t.label,color:t.color,seat:e})),...e?[{label:"Held",color:S.held,seat:!0}]:[],{label:e?"Sold":"Sold out",color:S.sold,seat:e}]}function fe(n,e){n.querySelectorAll("[data-colour-by]").forEach(s=>{let i=s.dataset.colourBy===e.colourBy;s.setAttribute("aria-checked",String(i)),s.classList.toggle("on",i)});let t=n.querySelector('[data-ref="legenditems"]');t&&t.replaceChildren(...ut(e).map(s=>{let i=document.createElement("span"),o=document.createElement("i");return o.style.background=s.color,s.seat&&o.classList.add("seat"),i.append(o,document.createTextNode(s.label)),i}))}var ve=[{key:"seatLabels",label:"Seat labels",letter:"S",hint:"Seat numbers where the zoom can carry them"},{key:"rowLabels",label:"Row labels",letter:"R",hint:"Row letters beside each row"},{key:"channelColours",label:"Channel colours",letter:"H",hint:"Channel flags and tints \u2014 the Channels tool\u2019s overlay"},{key:"momentum",label:"Booking momentum",letter:"M",hint:"Warm the sections booking fastest in the selected window"}],ye="seatlayer.controlRoom.mapView";function $(){return{seatLabels:!0,rowLabels:!0,categoryColours:!1,channelColours:!0,momentum:!1}}function xe(n){return n==="g"?"categoryColours":ve.find(t=>t.letter.toLowerCase()===n)?.key??null}function we(n=Se()){let e=$();if(!n)return e;try{let t=n.getItem(ye);if(!t)return e;let s=JSON.parse(t),i={...e};for(let o of Object.keys(e))typeof s[o]=="boolean"&&(i[o]=s[o]);return i}catch{return e}}function ke(n,e=Se()){if(e)try{e.setItem(ye,JSON.stringify(n))}catch{}}function Se(){try{return typeof localStorage>"u"?null:localStorage}catch{return null}}function Le(n,e){e.renderer?.setLabelLayers?.({seatLabels:n.seatLabels,rowLabels:n.rowLabels}),e.renderer?.setCategoryColours?.(n.categoryColours),e.channelsOverlay(n.channelColours)}function Me(){return`
686
+ <details class="slm-view" data-ref="view">
687
+ <summary class="slm-barbtn slm-view-summary" aria-haspopup="menu" title="How the map reads: labels, colours, momentum">View <span class="slm-view-caret" aria-hidden="true">\u25BE</span></summary>
688
+ <div class="slm-view-menu" role="menu" aria-label="Map view">${ve.map(e=>`
689
+ <button type="button" class="slm-view-item" role="menuitemcheckbox" data-view="${e.key}" aria-checked="false" title="${e.hint}">
690
+ <span class="slm-view-check" aria-hidden="true"></span>
691
+ <span class="slm-view-label">${e.label}</span>
692
+ <kbd class="slm-view-kbd" aria-hidden="true">\u21E7${e.letter}</kbd>
693
+ </button>`).join("")}
694
+ <div class="slm-view-note" data-ref="viewnote" hidden></div>
695
+ </div>
696
+ </details>`}function Te(n,e,t){let s=$(),i=!1;n.querySelectorAll("[data-view]").forEach(l=>{let r=l.dataset.view,c=e[r];l.setAttribute("aria-checked",String(c)),l.classList.toggle("on",c);let d=r==="channelColours"&&!t.channelColoursAvailable;l.disabled=d,l.setAttribute("aria-disabled",String(d)),!d&&c!==s[r]&&(i=!0)}),n.querySelector("summary")?.classList.toggle("away",i);let a=n.querySelector('[data-ref="viewnote"]');if(a){let l=[];t.channelColoursAvailable||l.push("Channel colours: open the Channels tool."),t.momentumLoading&&l.push("Booking momentum: loading the first snapshot\u2026"),a.hidden=!l.length,a.textContent=l.join(" ")}}import{UNGROUPED_ID as bt}from"@seatlayer/core";function P(n){return Object.entries(n).filter(([,e])=>e.mode==="closed").map(([e])=>e)}function B(n){let e=n.sectionsBase;if(!e)return{rows:[],hiddenSections:0,closedSections:0};let t=n.doc?.zones??[],s=new Map,i=[];for(let c of e.sections)if(c.zone&&t.some(d=>d.id===c.zone)){let d=s.get(c.zone)??[];d.push(c),s.set(c.zone,d)}else i.push(c);let o=[],a=0,l=0,r=(c,d,h,p=!1)=>{let u=n.availabilityRules[d.id]??null,g=n.effectiveClosed.has(d.id)||p,f=n.effectiveHidden.has(d.id)||h&&!g;c==="section"&&f&&(a+=1),c==="section"&&g&&(l+=1),o.push({kind:c,id:d.id,label:d.label,seatCount:d.seatCount,seatLabels:d.seatLabels,rule:u,hidden:f,closed:g,followsZone:c==="section"&&h})};for(let c of t){let d=s.get(c.id);if(!d||!d.length)continue;let h={id:c.id,label:c.label||"Zone",seatCount:d.reduce((g,f)=>g+f.seatCount,0),seatLabels:d.flatMap(g=>g.seatLabels)},p=!!n.availabilityRules[c.id],u=n.availabilityRules[c.id]?.mode==="closed";r("zone",h,!1);for(let g of d)r("section",g,p,u)}for(let c of i)r("section",c,!1);if(e.ungrouped){let c=e.ungrouped;r("section",{id:bt,label:c.label,seatCount:c.seatCount,seatLabels:c.seatLabels},!1)}return{rows:o,hiddenSections:a,closedSections:l}}function Ce(n,e){let t=W(n.rule),s=`slm-availrow${n.kind==="zone"?" zone":""}${n.hidden?" hidden":""}${n.closed?" closed":""}`,i=e?" disabled":"",o=[["open","Open","Available to buy"],["closed","Closed","Visible on the map, unavailable to buy"],["hidden","Hidden","Removed from the buyer map"],["timed","Scheduled reveal","Open at a specific date and time"],["threshold","Demand-based reveal","Open when sales reach a percentage"]],a=n.followsZone?'<span class="slm-availfollows">Follows zone</span>':`<details class="slm-availpicker" data-avail-picker>
697
+ <summary aria-label="Availability for ${m(n.label)}" ${e?'aria-disabled="true"':""}>${o.find(d=>d[0]===t)[1]}<span aria-hidden="true">\u2304</span></summary>
698
+ <div class="slm-availchoices" aria-label="Availability options for ${m(n.label)}">
699
+ ${o.map(([d,h,p])=>`<button type="button" data-avail-id="${m(n.id)}" data-avail-value="${d}" aria-pressed="${t===d}"${i}><span><b>${h}</b><small>${p}</small></span><span aria-hidden="true">${t===d?"\u2713":""}</span></button>`).join("")}
456
700
  </div>
457
- </details>`,l="";if(!h.followsZone&&t==="timed"){let n=h.rule?.revealAt?p(W(h.rule.revealAt)):"";l=`<div class="slm-availdetail">
458
- <input type="datetime-local" class="slm-input" data-avail-reveal="${p(h.id)}" value="${n}"${i} aria-label="Reveal time for ${p(h.label)}" />
459
- </div>`}else if(!h.followsZone&&t==="threshold"){let n=h.rule?.thresholdPct??80;l=`<div class="slm-availdetail">
701
+ </details>`,l="";if(!n.followsZone&&t==="timed"){let d=n.rule?.revealAt?m(Z(n.rule.revealAt)):"";l=`<div class="slm-availdetail">
702
+ <input type="datetime-local" class="slm-input" data-avail-reveal="${m(n.id)}" value="${d}"${i} aria-label="Reveal time for ${m(n.label)}" />
703
+ </div>`}else if(!n.followsZone&&t==="threshold"){let d=n.rule?.thresholdPct??80;l=`<div class="slm-availdetail">
460
704
  <span class="slm-availpctlabel">Reveal at</span>
461
- <input type="number" min="1" max="100" class="slm-input slm-availpct" data-avail-pct="${p(h.id)}" value="${p(n)}"${i} aria-label="Percent sold to reveal ${p(h.label)}" />
705
+ <input type="number" min="1" max="100" class="slm-input slm-availpct" data-avail-pct="${m(n.id)}" value="${m(d)}"${i} aria-label="Percent sold to reveal ${m(n.label)}" />
462
706
  <span class="slm-availpctlabel">% sold</span>
463
- </div>`}let r=h.closed?'<span class="slm-availbadge closed">Closed</span>':h.hidden?'<span class="slm-availbadge hidden">Hidden</span>':"",c=h.kind==="zone"?`<span class="slm-availcaret" aria-hidden="true">${h.hidden?"\u25B8":"\u25BE"}</span>`:"";return`<div class="${s}">
707
+ </div>`}let r=n.closed?'<span class="slm-availbadge closed">Closed</span>':n.hidden?'<span class="slm-availbadge hidden">Hidden</span>':"",c=n.kind==="zone"?`<span class="slm-availcaret" aria-hidden="true">${n.hidden?"\u25B8":"\u25BE"}</span>`:"";return`<div class="${s}">
464
708
  <div class="slm-availhead">
465
- <span class="slm-availlabel">${c}${p(h.label)}</span>
709
+ <span class="slm-availlabel">${c}${m(n.label)}</span>
466
710
  ${r}
467
- <span class="slm-availcount">${h.seatCount.toLocaleString()}</span>
711
+ <span class="slm-availcount">${n.seatCount.toLocaleString()}</span>
468
712
  </div>
469
- ${o}
713
+ ${a}
470
714
  ${l}
471
- </div>`}var We="https://api.seatlayer.io",$=200,ie=16,ae=4,oe=[{key:"watch",label:"Watch",tools:[{mode:"view",label:"Monitor",shortcut:"M",title:"Live board \u2014 inventory, activity and booking momentum. Read-only."},{mode:"inspect",label:"Inspect",shortcut:"I",title:"Click one seat to read its live status and booking context. Read-only."}]},{key:"manage",label:"Manage",tools:[{mode:"block",label:"Block",shortcut:"B",title:"Take seats off sale for this event, or put them back."},{mode:"sections",label:"Sections",shortcut:"S",title:"Open, close or hide sections for this event, on a schedule or on demand."},{mode:"categories",label:"Categories",shortcut:"G",title:"Move seats to a different price category for this event only."},{mode:"tables",label:"Tables",shortcut:"T",title:"Sell each table per chair or as one whole-table booking."},{mode:"channels",label:"Channels",shortcut:"C",title:"Allocate inventory to sales channels and share their links."}]},{key:"host",label:"Host tools",tools:[{mode:"select",label:"Select",shortcut:"X",title:"Select seats for your own back-office operation. The selection is handed to your app; nothing changes here."},{mode:"filterSections",label:"Filter",shortcut:"L",title:"Filter the map to one section for your own reporting."}]}],Ze=Object.fromEntries(oe.flatMap(h=>h.tools.map(e=>[e.shortcut.toLowerCase(),e.mode]))),F=class{constructor(e){this.els={};this.renderer=null;this.doc=null;this.selectObserver=null;this.seatHistoryPanel=null;this.activityPanel=null;this.navigation=null;this.movingMap=!1;this.socketSnapshotSeen=!1;this.monitorRefreshTimer=null;this.themeMode=null;this.colorSchemeStop=null;this.inventoryModelVersion=1;this.selectableObjectLabels=new Set;this.lastSelectionLabels=new Set;this.selectionWasValid=null;this.initialSelectionApplied=!1;this.labelToId=new Map;this.labelToSeat=new Map;this.allIds=[];this.gaUnitLabelSet=new Set;this.status=new Map;this.counts={held:0,booked:0,blocked:0};this.modelVersion=0;this.currency="USD";this.authoritativeCurrency=null;this.authoritativeGrossRevenue=0;this.revenueStatus="loading";this.revenueRequest=0;this.controlRoomSnapshot=null;this.serverBaseline=null;this.livePresence=null;this.liveGross=null;this.paintHandle=null;this.trendWindowMinutes=15;this.heatEnabled=!1;this.lastKpiValues=new Map;this.activeKpiDeltas=new Map;this.ws=null;this.reconnectTimer=null;this.attempt=0;this.closed=!1;this.connectionStatus="reconnecting";this.lastMessageAt=null;this.ready=!1;this.feed=[];this.feedTimer=null;this.toastTimer=null;this.liveEventTimer=null;this.kpiCleanupTimer=null;this.followLiveTimer=null;this.followSeatTimer=null;this.releaseAt=null;this.layoutObserver=null;this.tokenExpiresAt=null;this.tokenRefreshTimer=null;this.tokenRefreshInFlight=!1;this.sectionByObject=new Map;this.sectionLabelById=new Map;this.sectionsBase=null;this.filteredSectionLabel=null;this.availabilityRules={};this.effectiveHidden=new Set;this.effectiveClosed=new Set;this.availabilitySaving=!1;this.lastSyncedAt=null;this.blockBrowse=!1;this.blockedQuery="";this.blockedSection="";this.blockedResultLimit=100;this.unblockAllConfirmTimer=null;this.channels=null;this.channelCaps={view:!1,manage:!1};this.categoryCanManage=!1;this.tableCanManage=!1;this.tableBookingSaving=!1;this.channelCapabilityResolution=0;this.channelsLoading=null;this.onFullscreenChange=()=>{this.paintFullscreenButton(),this.updateContainerLayout(),this.renderer?.forceDraw()};this.onKeyDown=e=>{if(e.metaKey||e.ctrlKey||e.altKey||e.target?.matches('input,select,textarea,[contenteditable="true"]'))return;let s=e.key.toLowerCase(),i=Ze[s];if(i){if(!this.toolAvailable(i))return;this.setMode(i)}else if(s==="f")this.toggleFullscreen();else if(s==="escape"){if(!this.channels?.handleBack())if(this.getSelection().length)this.clearSelection();else return}else return;e.preventDefault()};this.onRailClick=e=>{let t=e.target,s=t?.closest("[data-section-focus]");if(s?.dataset.sectionFocus){this.locateSection(s.dataset.sectionFocus);return}let i=t?.closest("[data-feed-id]");i?.dataset.feedId&&this.locateActivity(i.dataset.feedId)};this.sectionOptions=[];I(e.token),this.assertSelectionOptions(e.maxSelectedObjects,e.numberOfPlacesToSelect),this.opts=e,this.key=e.eventKey,this.mode=e.mode??"view",this.selectableObjectLabels=new Set(e.selectableObjects??[]),this.categoryCanManage=new Set(e.capabilities??[]).has("event:categories:manage"),this.tableCanManage=new Set(e.capabilities??[]).has("event:tables:manage"),this.keepLive=e.keepLiveWhileHidden??!0,this.themeMode=e.themeMode??null,this.followLive=e.followLive??!1,this.currency=e.currency??"USD",this.tokenExpiresAt=e.tokenExpiresAt??null,this.api=new z(e.apiBase??We,e.token),this.organizerAssetUrls=new M(this.key,(t,s)=>this.withAuthRetry(()=>this.api.asset(t,s))),this.host=Z(e.container)}assertSelectionOptions(e,t){let s=i=>i===void 0||Number.isInteger(i)&&i>0;if(!s(e))throw new TypeError("maxSelectedObjects must be a positive integer");if(!s(t))throw new TypeError("numberOfPlacesToSelect must be a positive integer");if(e!==void 0&&t!==void 0&&e<t)throw new TypeError("maxSelectedObjects cannot be lower than numberOfPlacesToSelect")}async render(){V(),this.buildChrome();try{let e=await this.withAuthRetry(()=>this.api.chart(this.key));this.inventoryModelVersion=e.event.inventoryModelVersion===2?2:1,this.doc=await this.organizerAssetUrls.prepareRendererChart(e.doc),this.authoritativeCurrency=e.event.currency??null,this.currency=this.authoritativeCurrency??this.opts.currency??this.currency,this.buildUnitUniverse(this.doc),this.buildRenderer(),this.buildSectionOptions(),this.settleMode();let[,t]=await Promise.all([this.resnapshot(),this.refreshControlRoom().catch(s=>this.opts.onError?.(s)),this.refreshAvailability()]);t?.activity?this.seedFeed(t.activity):this.api.log(this.key,{limit:24}).then(s=>this.seedFeed(s.entries)).catch(()=>{}),this.connect(),this.startFeedClock(),this.ready=!0,await this.resolveChannelCapabilities(),this.setMode(this.mode),this.applyInitialSelection(),this.scheduleTokenRefresh(),this.opts.onReady?.()}catch(e){this.fail(e)}return this}setMode(e){this.toolAvailable(e)||(e="view"),e==="channels"&&!this.channels&&this.ensureChannels();let t=e!==this.mode,s=this.mode==="channels",i=this.mode==="filterSections";this.mode=e,t&&e!=="view"&&this.setFollowLive(!1),!this.renderer&&this.doc?this.buildRenderer():this.updateRendererInteraction(),t&&(this.renderer?.clearSelection(),this.syncSelection()),s&&e!=="channels"&&this.channels?.leave(),this.paintModeTabs(),this.paintRail(),this.applySectionCanvasTreatment(),i&&e!=="filterSections"&&this.renderer?.zoomToFit(),e==="channels"&&this.channels?.enter(),e==="select"&&this.applyInitialSelection(),t&&this.opts.onModeChange?.(e)}async resolveChannelCapabilities(){let e=++this.channelCapabilityResolution,t=this.opts.capabilities,s;if(t){let i=new Set(t);s={view:i.has("event:channels:view"),manage:i.has("event:channels:view")&&i.has("event:channels:manage")}}else s={view:!1,manage:!1};if(!s.view&&!t)try{await this.api.channels(this.key),s={view:!0,manage:!1}}catch{s={view:!1,manage:!1}}if(e===this.channelCapabilityResolution){if(this.channelCaps=s,!this.channelCaps.view){this.channels?.destroy(),this.channels=null,this.mode==="channels"?this.setMode("view"):this.paintModeTabs();return}this.channels?.setCapabilities(this.channelCaps),this.paintModeTabs()}}ensureChannels(){if(this.channelsLoading)return this.channelsLoading;if(this.channels)return Promise.resolve();let e=(async()=>{try{let t=await import("./channelsMode-KZU235GN.js");if(this.closed||!this.channelCaps.view||(this.channels||(U(t.CHANNELS_CSS),this.channels=new t.ChannelsMode(this.buildChannelsHost(),this.channelCaps),this.channels.onInteractionChange=()=>this.updateRendererInteraction()),this.mode!=="channels"))return;this.updateRendererInteraction(),this.paintRail(),this.channels.enter()}catch(t){if(this.closed)return;this.channelsLoading=null,this.mode==="channels"&&this.paintRail(),this.opts.onError?.(t)}})();return this.channelsLoading=e,e}buildChannelsHost(){return{eventKey:this.key,api:this.api,rail:this.els.rail,mapLayer:this.root.querySelector(".slm-map"),pillLane:this.els.lane,root:this.root,seats:()=>[...this.labelToSeat.values()].map(e=>({id:e.id,label:e.label,x:e.x,y:e.y})),statusOf:e=>this.status.get(e)??(this.labelToSeat.has(e)?"free":void 0),selectionLabels:()=>this.selectionLabels(),selectByLabels:e=>{this.selectByLabels(e)},clearSelection:()=>this.clearSelection(),selectSection:e=>{this.selectSection(e)},sections:()=>this.sectionOptions,labelsInSection:e=>this.renderer?.getSelectableInSection(e).map(t=>t.label)??[],rows:()=>{let e=new Map((this.doc?.objects??[]).map(s=>[s.id,s])),t=new Map;for(let s of this.labelToSeat.values()){let i=e.get(s.rowId);if(!i||i.type!=="row"&&i.type!=="table")continue;let a=s.logicalRowId??s.rowId,o=this.sectionByObject.get(s.rowId)??x,l=t.get(a)??{id:a,label:i.type==="row"?i.segmentedRow?.displayLabel??i.displayLabel??i.label:i.displayLabel??i.label,sectionId:o,sectionLabel:this.sectionLabelById.get(o)??"Other seats",labels:[]};l.labels.push(s.label),t.set(a,l)}return[...t.values()].sort((s,i)=>s.sectionLabel.localeCompare(i.sectionLabel,void 0,{numeric:!0,sensitivity:"base"})||s.label.localeCompare(i.label,void 0,{numeric:!0,sensitivity:"base"}))},categories:()=>(this.doc?.categories??[]).map(e=>({key:e.key,label:e.label??e.key,color:e.color,price:e.price,tiers:e.tiers?.map(t=>({id:t.id,name:t.name,price:t.price}))})),labelsInCategory:e=>[...this.labelToSeat.entries()].filter(([,t])=>t.categoryKey===e).map(([t])=>t),sectionOfLabel:e=>{let t=this.labelToSeat.get(e);if(!t)return null;let s=this.sectionByObject.get(t.rowId)??x;return{id:s,label:this.sectionLabelById.get(s)??"Other seats"}},worldToScreen:e=>this.renderer?.worldToScreen(e)??null,seatPixelSize:()=>this.seatPixelSize(),isSeatDetail:()=>this.renderer?.getRung?.()==="seats",showSectionOverview:()=>{this.renderer?.clearSectionFocus(),this.renderer?.setRung?.("sections")},focusSection:e=>this.renderer?.focusSection(e),isCompact:()=>!!this.root?.classList.contains("compact"),setMapInert:e=>{this.mapHost.toggleAttribute("inert",e),this.mapHost.setAttribute("aria-hidden",String(e))},toast:(e,t)=>this.toast(e,t),onError:e=>this.opts.onError?.(e)}}seatPixelSize(){let e=this.renderer?.getVisibleWorldRect?.(),t=this.mapHost?.clientWidth??0;return!e?.width||!t?6:Math.max(3,t/e.width*18)}setHeatOverlay(e){this.heatEnabled=e,this.applyHeatOverlay(),this.paintHeatButton()}setFollowLive(e){let t=this.followLive!==e;this.followLive=e,e||(this.followLiveTimer&&clearTimeout(this.followLiveTimer),this.followSeatTimer&&clearTimeout(this.followSeatTimer),this.followLiveTimer=null,this.followSeatTimer=null),this.paintFollowLiveButton(),t&&this.opts.onFollowLiveChange?.(e)}setKeepLiveWhileHidden(e){this.keepLive=e??!0,this.opts.keepLiveWhileHidden=e}setCurrency(e){this.opts.currency=e,!this.authoritativeCurrency&&(this.currency=e??"USD",this.ready&&this.recomputeTallies())}setTheme(e){this.opts.theme=e,this.applyThemeVars()}applyThemeVars(){if(!this.root)return;let e=B(this.themeMode);for(let[t,s]of Object.entries(Q(this.opts.theme,e)))this.root.style.setProperty(t,s);e?this.root.dataset.theme=e:delete this.root.dataset.theme}watchThemeMode(){this.colorSchemeStop?.(),this.colorSchemeStop=null,this.themeMode==="auto"&&(this.colorSchemeStop=j(()=>{this.closed||this.repaintForThemeMode()}))}repaintForThemeMode(){this.applyThemeVars();let e=this.renderer;if(!e||!this.doc)return;let t=e.getSelection().map(a=>a.id),s=e.getCameraPose(),i=e.getFocusedSection();e.setChart(this.themedDoc()),this.repaintAll(),this.applyHeatOverlay(),t.length&&e.select(t),i&&e.focusSection(i),e.setCameraPose(s),this.updateZoomHint()}setThemeMode(e){let t=e??null;this.closed||t===this.themeMode||(this.themeMode=t,this.opts.themeMode=t??void 0,this.watchThemeMode(),this.repaintForThemeMode())}getThemeMode(){return this.themeMode}themedDoc(){let e=this.doc,t=J(B(this.themeMode));return t?{...e,theme:{...e.theme??{},background:t}}:e}setCapabilities(e){this.opts.capabilities=e,this.categoryCanManage=new Set(e??[]).has("event:categories:manage"),this.tableCanManage=new Set(e??[]).has("event:tables:manage"),!this.categoryCanManage&&this.mode==="categories"||!this.tableCanManage&&this.mode==="tables"?this.setMode("view"):this.paintModeTabs(),this.ready&&this.resolveChannelCapabilities()}setTokenRefresh(e){this.opts.onTokenRefresh=e,this.scheduleTokenRefresh()}setTrendWindow(e){let t=Number.isFinite(e)?Math.floor(e):15;return this.trendWindowMinutes=Math.max(5,Math.min(60,t)),this.paintTrendWindow(),this.refreshControlRoom()}async enterFullscreen(){!this.root?.requestFullscreen||this.isFullscreen()||(await this.root.requestFullscreen(),this.root.focus({preventScroll:!0}))}async exitFullscreen(){typeof document>"u"||!this.isFullscreen()||await document.exitFullscreen()}isFullscreen(){return typeof document<"u"&&document.fullscreenElement===this.root}toggleFullscreen(){(this.isFullscreen()?this.exitFullscreen():this.enterFullscreen()).catch(t=>this.opts.onError?.(t))}setToken(e,t){I(e),this.api.setToken(e),this.opts.token=e,this.opts.tokenExpiresAt=t,this.tokenExpiresAt=t??null,this.scheduleTokenRefresh(),this.ready&&this.resolveChannelCapabilities()}scheduleTokenRefresh(){this.tokenRefreshTimer&&clearTimeout(this.tokenRefreshTimer),this.tokenRefreshTimer=null;let e=this.opts.onTokenRefresh,t=this.tokenExpiresAt;if(this.closed||!e||!t||!Number.isFinite(t))return;let s=t-Date.now(),i=Math.min(12e4,Math.max(3e4,s*.2)),a=Math.max(0,s-i);this.tokenRefreshTimer=setTimeout(()=>{this.tokenRefreshTimer=null,this.rotateToken()},a)}async rotateToken(){if(!(this.closed||this.tokenRefreshInFlight||!this.opts.onTokenRefresh)){this.tokenRefreshInFlight=!0;try{let e=await this.opts.onTokenRefresh();if(!e?.token||!Number.isFinite(e.expiresAt))throw new Error("invalid_token_refresh_result");this.setToken(e.token,e.expiresAt)}catch(e){this.opts.onError?.(e),this.closed||(this.tokenRefreshTimer=setTimeout(()=>{this.tokenRefreshTimer=null,this.rotateToken()},3e4))}finally{this.tokenRefreshInFlight=!1}}}async block(e,t={}){let s=(e??this.selectionLabels()).filter(a=>this.status.get(a)==="free");if(!s.length)return;let i=t.releaseAt??this.releaseAt??void 0;this.setSeatsLocal(s,"blocked");try{await this.api.block(this.key,s,{...t,releaseAt:i}),this.clearSelection(),this.done("block",s,i?`Blocked ${s.length} \u2014 auto-release ${new Date(i).toLocaleString()}.`:`Blocked ${s.length} seat${s.length===1?"":"s"}.`)}catch(a){this.setSeatsLocal(s,"free"),this.toastErr(a instanceof S&&a.status===409?"Some seats were just taken. Try again.":"Couldn't block those seats."),this.opts.onError?.(a)}}async unblock(e){let t=(e??this.selectionLabels()).filter(s=>this.status.get(s)==="blocked");if(t.length){this.setSeatsLocal(t,"free");try{await this.api.unblock(this.key,t),this.clearSelection(),this.done("unblock",t,`Unblocked ${t.length} seat${t.length===1?"":"s"}.`)}catch(s){this.setSeatsLocal(t,"blocked"),this.toastErr("Couldn't unblock those seats."),this.opts.onError?.(s)}}}async unblockAll(){let e=[...this.status.entries()].filter(([,t])=>t==="blocked").map(([t])=>t);if(e.length){this.setSeatsLocal(e,"free");try{let t=await this.api.unblockAll(this.key);this.clearSelection(),this.done("unblockAll",e,`Unblocked ${t.freed} seat${t.freed===1?"":"s"}.`)}catch(t){await this.resnapshot(),this.toastErr("Couldn't mark everything for sale."),this.opts.onError?.(t)}}}async cancelBooking(e,t){let s=e.filter(i=>this.status.get(i)==="booked");if(!(!s.length||!t)){this.setSeatsLocal(s,"free");try{await this.api.unbook(this.key,s,t),this.clearSelection(),this.done("cancelBooking",s,`Released ${s.length} booked unit${s.length===1?"":"s"}.`)}catch(i){this.setSeatsLocal(s,"booked"),this.toastErr("Couldn't release that booked inventory. Check the booking reference."),this.opts.onError?.(i)}}}async setCategory(e,t){let s=this.doc?.categories.find(a=>a.key===e),i=[...new Set(t??this.selectionLabels())].filter(a=>this.labelToSeat.has(a));if(!(!s||!i.length))try{let a=await this.withAuthRetry(()=>this.api.setCategory(this.key,i,e)),o={};for(let l of a.labels){let r=this.labelToSeat.get(l),c=this.labelToId.get(l);r&&(r.categoryKey=e),c&&(o[c]=e)}this.renderer?.setSeatCategories?.(o),this.clearSelection(),this.done("setCategory",a.labels,`Assigned ${a.labels.length.toLocaleString()} object${a.labels.length===1?"":"s"} to ${s.label??s.key}.`)}catch(a){this.toastErr("Couldn't update those event categories."),this.opts.onError?.(a)}}async setTableBooking(e,t,s={}){let i=[...new Set(e)].filter(Boolean);if(!(!i.length||this.tableBookingSaving)){if(this.inventoryModelVersion!==2){this.toastErr("Table booking controls require inventory model 2 for this event.");return}this.tableBookingSaving=!0,this.mode==="tables"&&this.renderTablesRail();try{let a=await this.withAuthRetry(()=>this.api.setTableBooking(this.key,i,t,s));await this.reloadEventChart(),this.done("setTableBooking",a.tableIds,`Updated ${a.tableIds.length.toLocaleString()} table${a.tableIds.length===1?"":"s"} to ${t==="individual"?"per-chair":t==="whole"?"whole-table":"flexible-group"} booking.`)}catch(a){let o=a instanceof S&&a.code==="table_inventory_in_use";this.toastErr(o?"Release held, booked, or blocked table inventory before changing its booking mode.":"Couldn't update table booking. No table mode was changed."),this.opts.onError?.(a)}finally{this.tableBookingSaving=!1,this.mode==="tables"&&this.renderTablesRail()}}}async reloadEventChart(){let e=await this.withAuthRetry(()=>this.api.chart(this.key));this.inventoryModelVersion=e.event.inventoryModelVersion===2?2:1;let t=await this.organizerAssetUrls.prepareRendererChart(e.doc);this.renderer?.destroy(),this.renderer=null,this.doc=t,this.labelToId.clear(),this.labelToSeat.clear(),this.allIds=[],this.gaUnitLabelSet.clear(),this.status.clear(),this.counts={held:0,booked:0,blocked:0},this.serverBaseline=null,this.lastSelectionLabels.clear(),this.buildUnitUniverse(t),this.buildRenderer(),this.buildSectionOptions(),this.settleMode(),await Promise.all([this.resnapshot(),this.refreshAvailability()]),this.paintRail()}selectAll(){if(this.mode==="select")return this.selectByLabels([...this.labelToSeat.values()].filter(t=>this.canSelectObject(t)).map(t=>t.label));let e=this.renderer?.selectAllSelectable()??[];return this.syncSelection(),e}selectSection(e){if(!this.renderer)return[];let t=this.renderer.getSelectableInSection(e);return this.renderer.selectByLabels(t.map(s=>s.label)),this.syncSelection(),this.renderer.getSelection()}setFilteredSection(e){let t=e.trim(),s=this.filterableSections().filter(o=>o.label===t);if(!s.length)throw new Error(`Unknown event section: ${e}`);let i=t!==this.filteredSectionLabel;this.filteredSectionLabel=t,this.mode==="filterSections"&&(this.applyFilteredSectionCanvas(s),this.renderFilterSectionsRail());let a=s.map(({id:o,label:l,seatCount:r,zone:c})=>({id:o,label:l,seatCount:r,...c?{zone:c}:{}}));return i&&this.opts.onFilteredSectionChange?.(a),a}clearFilteredSection(){let e=this.filteredSectionLabel!==null;this.filteredSectionLabel=null,this.renderer?.setDimmedSections(null),this.renderer?.clearSectionFocus(),this.renderer?.zoomToFit(),this.mode==="filterSections"&&this.renderFilterSectionsRail(),e&&this.opts.onFilteredSectionChange?.([])}getFilteredSections(){return this.filteredSectionLabel?this.filterableSections().filter(e=>e.label===this.filteredSectionLabel).map(({id:e,label:t,seatCount:s,zone:i})=>({id:e,label:t,seatCount:s,...i?{zone:i}:{}})):[]}selectByLabels(e){let t=e;if(this.mode==="select"){let s=new Set(this.selectionLabels()),i=this.selectionCap(),a=[...new Set(e)].filter(l=>!s.has(l)).map(l=>this.labelToSeat.get(l)).filter(l=>!!l&&this.canSelectObject(l)),o=Math.max(0,i-s.size);a.length>o&&this.opts.onSelectionLimit?.(i),t=a.slice(0,o).map(l=>l.label)}return this.renderer?.selectByLabels(t),this.syncSelection(),this.getSelection()}selectObjects(e){return this.selectByLabels(e)}deselectObjects(e){let t=e.map(s=>this.labelToId.get(s)).filter(s=>!!s);return this.renderer?.deselect(t),this.syncSelection(),this.getSelection()}selectCategories(e){let t=new Set(e);return this.selectByLabels([...this.labelToSeat.values()].filter(s=>t.has(s.categoryKey)).map(s=>s.label))}deselectCategories(e){let t=new Set(e);return this.deselectObjects(this.getSelection().filter(s=>t.has(s.categoryKey)).map(s=>s.label))}setSelectableObjects(e){this.opts.selectableObjects=[...e],this.selectableObjectLabels=new Set(e),this.reconcileSelectPolicy()}setUnavailableObjectsSelectable(e){this.opts.unavailableObjectsSelectable=e,this.reconcileSelectPolicy()}setObjectSelectable(e){this.opts.isObjectSelectable=e,this.reconcileSelectPolicy()}setMaxSelectedObjects(e){this.assertSelectionOptions(e,this.opts.numberOfPlacesToSelect),this.opts.maxSelectedObjects=e,this.trimSelectionToCap(),this.updateRendererInteraction(),this.syncSelection()}setNumberOfPlacesToSelect(e){this.assertSelectionOptions(this.opts.maxSelectedObjects,e),this.opts.numberOfPlacesToSelect=e,this.selectionWasValid=null,this.trimSelectionToCap(),this.updateRendererInteraction(),this.syncSelection()}getSelectionValidity(){let e=this.opts.numberOfPlacesToSelect;if(e===void 0)return null;let t=this.getSelection(),s=t.length;return{isValid:s===e,count:s,required:e,remaining:Math.max(0,e-s),objects:t}}clearSelection(){this.renderer?.clearSelection(),this.syncSelection()}getSelection(){return this.renderer?.getSelection()??[]}getReport(){return this.api.report(this.key).then(e=>(this.applyReportRevenue(e),e))}getControlRoomSnapshot(e=this.trendWindowMinutes){return this.setTrendWindow(e)}getConnection(){return{status:this.connectionStatus,lastMessageAt:this.lastMessageAt}}getLog(e={}){return this.api.log(this.key,e)}async setHoldTtl(e){try{await this.api.setHoldTtl(this.key,e),this.done("setHoldTtl",[],e?`Hold window set to ${Math.round(e/6e4)} min.`:"Hold window reset.")}catch(t){this.toastErr("Couldn't update the hold window."),this.opts.onError?.(t)}}zoomToFit(){if(this.mode==="filterSections"&&this.filteredSectionLabel){this.clearFilteredSection();return}this.renderer?.clearSectionFocus(),this.renderer?.zoomToFit()}destroy(){if(this.selectObserver?.disconnect(),this.closed=!0,this.monitorRefreshTimer&&clearTimeout(this.monitorRefreshTimer),this.monitorRefreshTimer=null,this.reconnectTimer&&clearTimeout(this.reconnectTimer),this.feedTimer&&clearInterval(this.feedTimer),this.toastTimer&&clearTimeout(this.toastTimer),this.liveEventTimer&&clearTimeout(this.liveEventTimer),this.kpiCleanupTimer&&clearTimeout(this.kpiCleanupTimer),this.followLiveTimer&&clearTimeout(this.followLiveTimer),this.followSeatTimer&&clearTimeout(this.followSeatTimer),this.unblockAllConfirmTimer&&clearTimeout(this.unblockAllConfirmTimer),this.paintHandle!==null&&typeof cancelAnimationFrame=="function"&&cancelAnimationFrame(this.paintHandle),this.paintHandle=null,this.channels?.destroy(),this.channels=null,this.channelsLoading=null,this.tokenRefreshTimer&&clearTimeout(this.tokenRefreshTimer),this.layoutObserver?.disconnect(),this.layoutObserver=null,this.colorSchemeStop?.(),this.colorSchemeStop=null,this.root?.removeEventListener("keydown",this.onKeyDown),this.els.rail?.removeEventListener("click",this.onRailClick),typeof document<"u"&&document.removeEventListener("fullscreenchange",this.onFullscreenChange),this.ws){try{this.ws.close()}catch{}this.ws=null}this.seatHistoryPanel?.destroy(),this.seatHistoryPanel=null,this.activityPanel?.destroy(),this.activityPanel=null,this.navigation?.destroy(),this.navigation=null,this.renderer?.destroy(),this.renderer=null,this.organizerAssetUrls.dispose(),this.root&&this.root.parentNode===this.host&&this.host.removeChild(this.root)}buildRenderer(){if(!this.doc)return;let e=this.isBulkSelectMode();this.renderer=new De(this.mapHost,{manageMode:!0,organizerGlyph:{apply:Ne,clear:qe,isPainted:_e},marqueeSelect:e&&!this.movingMap,maxSelection:this.selectionCap(),selectableStatuses:this.selectableStatuses(),currency:this.currency,onSelect:t=>this.handleSeatSelect(t),onDeselect:()=>this.syncSelection(),onSelectionLimit:t=>this.opts.onSelectionLimit?.(t),onMarquee:()=>this.syncSelection(),onSectionTap:t=>{if(this.mode==="filterSections"){let s=this.filterableSections().find(i=>i.id===t);s&&this.setFilteredSection(s.label);return}this.renderer?.focusSection(t),this.channels?.handleSectionFocus(t)},onViewChange:()=>{this.updateZoomHint(),this.channels?.handleViewChange()}}),this.renderer.setChart(this.themedDoc()),this.repaintAll(),this.applyHeatOverlay(),this.updateZoomHint()}isBulkSelectMode(){return this.mode==="block"||this.mode==="categories"||this.mode==="channels"&&this.channels?.usesMarqueeSelection()===!0}selectableStatuses(){return this.mode==="block"?["free","not_for_sale"]:this.mode==="select"||this.mode==="categories"||this.mode==="inspect"||this.isBulkSelectMode()||this.mode==="channels"&&this.channels?.canSelect()===!0?["free","held","booked","not_for_sale"]:[]}updateRendererInteraction(){let e=this.isBulkSelectMode();this.renderer?.setManageInteraction({manageMode:!0,organizerStatus:this.mode!=="channels",marqueeSelect:e&&!this.movingMap,maxSelection:this.selectionCap(),selectableStatuses:this.selectableStatuses()}),this.navigation?.update(e,this.mode==="view"),this.updateZoomHint()}handleSeatSelect(e){if(this.mode==="select"&&!this.canSelectObject(e)){this.renderer?.deselect([e.id]),this.syncSelection();return}if(this.mode==="inspect"){let t=this.getSelection().filter(s=>s.id!==e.id).map(s=>s.id);t.length&&this.renderer?.deselect(t)}this.syncSelection()}buildUnitUniverse(e){for(let t of Ve(e))this.labelToId.set(t.label,t.id),this.labelToSeat.set(t.label,t),this.allIds.push(t.id);for(let t of Ke(e))for(let s of Ge(t))this.labelToId.has(s)||this.gaUnitLabelSet.add(s)}unitTotal(){return this.allIds.length+this.gaUnitLabelSet.size}knownLabels(){return[...this.labelToId.keys(),...this.gaUnitLabelSet]}repaintAll(){let e=this.renderer;if(!e)return;this.allIds.length&&e.setStatus(this.allIds,"free");let t={free:[],held:[],booked:[],not_for_sale:[]};for(let[s,i]of this.status.entries()){let a=this.labelToId.get(s);a&&t[E(i)].push(a)}["held","booked","not_for_sale"].forEach(s=>{t[s].length&&e.setStatus(t[s],s)})}async connect(){if(this.closed)return;let e;try{if(e=(await this.withAuthRetry(()=>this.api.subscribeTicket(this.key))).protocols,!e.length)throw new Error("manage_subscribe_ticket_missing")}catch(s){this.setLive(!1),this.opts.onError?.(s),this.scheduleReconnect();return}if(this.closed)return;let t;try{t=new WebSocket(this.api.socketUrl(this.key),e)}catch(s){this.opts.onError?.(s),this.scheduleReconnect();return}this.ws=t,this.socketSnapshotSeen=!1,t.onopen=()=>{this.attempt=0,this.setLive(!0),this.resnapshot().then(()=>this.refreshControlRoom()).catch(s=>this.opts.onError?.(s)),this.refreshAvailability()},t.onmessage=s=>this.onMessage(s),t.onclose=()=>{this.ws===t&&(this.ws=null),this.setLive(!1),this.scheduleReconnect()},t.onerror=()=>{try{t.close()}catch{}}}scheduleReconnect(){if(this.closed||this.reconnectTimer)return;let e=Math.min(1e3*2**Math.min(this.attempt++,5),15e3);this.reconnectTimer=setTimeout(()=>{this.reconnectTimer=null,this.connect()},e)}onMessage(e){let t;try{t=JSON.parse(typeof e.data=="string"?e.data:"")}catch{return}if(!t||typeof t!="object")return;this.lastMessageAt=Date.now();let s=t;if((Array.isArray(s.hidden)||Array.isArray(s.closed))&&this.updateEffectiveAvailability(s.hidden,s.closed),s.type==="presence"){typeof s.shoppingSessions=="number"&&typeof s.activeHolds=="number"&&(this.livePresence={at:Date.now(),value:{shoppingSessions:s.shoppingSessions,activeHolds:s.activeHolds}},this.controlRoomSnapshot&&(this.controlRoomSnapshot={...this.controlRoomSnapshot,presence:this.livePresence.value},this.opts.onControlRoom?.(this.controlRoomSnapshot)),this.lastSyncedAt=Date.now(),this.recomputeTallies(),this.paintMonitorInsights());return}if(s.type!=="hidden"){if(s.seats&&typeof s.seats=="object")this.applySocketSnapshot(s.seats,typeof s.default=="string"?s.default:void 0);else if(Array.isArray(s.changes)){let i=[],a=new Map;for(let l of s.changes){let r=["free","held","booked","blocked"].includes(l.status)?l.status:"free",c=this.status.get(l.label)??"free";if(c===r)continue;this.setStatusLabel(l.label,r,c);let n=this.labelToId.get(l.label);n&&(this.renderer?.setStatus([n],E(r)),i.push(n));let d=this.verbFor(c,r),m=`${d}:${r}`,b=a.get(m)??{labels:[],verb:d,status:r};b.labels.push(l.label),a.set(m,b)}for(let l of a.values()){let r=this.pushActivity(l.labels,l.verb,l.status);r&&this.paintSpatialActivity(r)}a.size&&this.scheduleMonitorRefresh(),i.length&&(this.lastSyncedAt=Date.now(),this.afterPaint());let o=typeof s.bookedValue?.gross=="number"?s.bookedValue.gross:s.revenue?.gross;typeof o=="number"&&Number.isFinite(o)&&this.applyLiveGross(o),this.recomputeTallies()}}}applyLiveGross(e){if(this.liveGross={at:Date.now(),value:e},this.authoritativeGrossRevenue=e,this.revenueStatus="current",this.controlRoomSnapshot){let s={...this.controlRoomSnapshot.bookedValue??this.controlRoomSnapshot.revenue,gross:e};this.controlRoomSnapshot={...this.controlRoomSnapshot,bookedValue:s,revenue:s},this.opts.onControlRoom?.(this.controlRoomSnapshot)}}setStatusLabel(e,t,s=this.status.get(e)??"free"){this.status.set(e,t),s!==t&&(s!=="free"&&(this.counts[s]-=1),t!=="free"&&(this.counts[t]+=1))}applySocketSnapshot(e,t){let s=this.socketSnapshotSeen?this.status:null;if(this.applySnapshot(e,t),this.socketSnapshotSeen=!0,!s)return;let i=new Map;for(let a of new Set([...s.keys(),...this.status.keys()])){let o=s.get(a)??"free",l=this.status.get(a)??"free";if(o===l)continue;let r=this.verbFor(o,l),c=`${r}:${l}`,n=i.get(c)??{labels:[],verb:r,status:l};n.labels.push(a),i.set(c,n)}for(let a of i.values()){let o=this.pushActivity(a.labels,a.verb,a.status);o&&this.paintSpatialActivity(o)}i.size&&this.scheduleMonitorRefresh()}scheduleMonitorRefresh(){this.monitorRefreshTimer||(this.monitorRefreshTimer=setTimeout(()=>{this.monitorRefreshTimer=null,this.closed||this.refreshControlRoom().catch(e=>this.opts.onError?.(e))},150))}async resnapshot(){try{let e=await this.api.objects(this.key);this.applySnapshot(e.seats),this.updateEffectiveAvailability(e.hidden,e.closed),this.lastMessageAt=Date.now()}catch{}}applySnapshot(e,t){let s=a=>["free","held","booked","blocked"].includes(a)?a:"free",i=new Map;if(t!==void 0){let a=s(t);for(let o of this.knownLabels())i.set(o,a)}for(let[a,o]of Object.entries(e))i.set(a,s(o));this.status=i,this.modelVersion+=1,this.recountAll(),this.lastSyncedAt=Date.now(),this.repaintAll(),this.afterPaint(),this.recomputeTallies()}recountAll(){let e={held:0,booked:0,blocked:0};for(let t of this.status.values())t!=="free"&&(e[t]+=1);this.counts=e}setSeatsLocal(e,t){let s=[];for(let i of e){this.setStatusLabel(i,t);let a=this.labelToId.get(i);a&&s.push(a)}s.length&&this.renderer?.setStatus(s,E(t)),this.afterPaint(),this.recomputeTallies()}afterPaint(){this.keepLive&&typeof document<"u"&&document.hidden&&this.renderer?.forceDraw()}activityColor(e){return e==="held"?y.held:e==="booked"?y.booked:e==="blocked"?y.blocked:y.free}sectionsForLabels(e){let t=new Set;for(let i of e){let a=this.labelToSeat.get(i);if(!a)continue;let o=this.sectionByObject.get(a.rowId);o&&o!==x&&t.add(o)}let s=[...t];return{ids:s,labels:s.map(i=>this.sectionLabelById.get(i)??i)}}pulseSeatLabels(e,t){let s=this.activityColor(t);for(let i of e.slice(0,ie)){let a=this.labelToId.get(i);a&&this.renderer?.flashSeat(a,s)}}paintSpatialActivity(e){let t=e.sectionIds??this.sectionsForLabels(e.labels).ids,s=this.renderer?.getFocusedSection()??null;if(this.followLive&&t.length===1&&(e.status==="held"||e.status==="booked")){let a=this.root?.querySelector('[data-ref="followstatus"]');a&&(a.textContent=`Following ${e.labels.length===1?e.labels[0]:`${e.labels.length} seats`} \xB7 ${e.status}`),this.followLiveTimer&&clearTimeout(this.followLiveTimer),this.followSeatTimer&&clearTimeout(this.followSeatTimer),this.followLiveTimer=setTimeout(()=>{this.followLiveTimer=null,this.focusActivitySeats(e.labels,t[0]),this.followSeatTimer=setTimeout(()=>{this.followSeatTimer=null,this.pulseSeatLabels(e.labels,e.status)},520)},220);return}if(!s&&t.length){let a=this.activityColor(e.status);for(let o of t.slice(0,ae))this.renderer?.flashSection(o,a);return}(!t.length||s&&t.includes(s))&&this.pulseSeatLabels(e.labels,e.status)}locateSection(e){this.renderer?.focusSection(e)}focusActivitySeats(e,t){this.renderer?.focusSection(t);let s=e.slice(0,ie).map(r=>this.labelToSeat.get(r)).filter(r=>!!r);if(!s.length)return;let i=s.map(r=>r.x),a=s.map(r=>r.y),o=Math.min(...i),l=Math.min(...a);this.renderer?.focusRegion({x:o-150,y:l-100,width:Math.max(...i)-o+300,height:Math.max(...a)-l+200})}locateActivity(e){let t=this.feed.find(i=>i.id===e);if(!t)return;let s=t.sectionIds??this.sectionsForLabels(t.labels).ids;if(this.followSeatTimer&&clearTimeout(this.followSeatTimer),s.length===1){this.focusActivitySeats(t.labels,s[0]),this.followSeatTimer=setTimeout(()=>{this.followSeatTimer=null,this.pulseSeatLabels(t.labels,t.status)},520);return}this.zoomToFit(),this.followSeatTimer=setTimeout(()=>{if(this.followSeatTimer=null,s.length){let i=this.activityColor(t.status);for(let a of s.slice(0,ae))this.renderer?.flashSection(a,i)}else this.pulseSeatLabels(t.labels,t.status)},280)}showLiveEvent(e){let t=this.els.liveevent;if(!t)return;let s=e.sectionLabels??[],i=s.length===1?s[0]:s.length>1?`${s.length} sections`:e.label,a=e.count===1?"seat":"seats";t.innerHTML=`<span class="slm-liveeventdot" style="background:${this.activityColor(e.status)}"></span>
472
- <span class="slm-liveeventcopy">${p(i)} \xB7 ${e.count.toLocaleString()} ${a} ${p(e.verb)}</span>
473
- <span class="slm-liveeventhint">Live</span>`,t.classList.add("on"),this.liveEventTimer&&clearTimeout(this.liveEventTimer),this.liveEventTimer=setTimeout(()=>{this.liveEventTimer=null,t.classList.remove("on"),t.innerHTML=""},2800)}applyReportRevenue(e){this.authoritativeGrossRevenue=e.report.byCategory.reduce((t,s)=>{let i=Number.isFinite(s.bookedValue)?s.bookedValue:s.bookedRevenue;return t+(Number.isFinite(i)?i:0)},0),this.revenueStatus="current",this.recomputeTallies()}async refreshControlRoom(){let e=++this.revenueRequest,t=Date.now();try{let s=await this.api.controlRoom(this.key,this.trendWindowMinutes),i=s.bookedValue??s.revenue??{gross:0,bySection:[]},a=(i.bySection??[]).map(r=>{let c=Number.isFinite(r.bookedValue)?r.bookedValue:r.bookedRevenue;return{...r,bookedValue:c??0,bookedRevenue:c??0}}),o={...i,bySection:a},l={...s,bookedValue:o,revenue:o};if(e===this.revenueRequest){if(this.livePresence&&this.livePresence.at>=t?l={...l,presence:this.livePresence.value}:this.livePresence=null,this.liveGross&&this.liveGross.at>=t){let n={...l.bookedValue,gross:this.liveGross.value};l={...l,bookedValue:n,revenue:n}}else this.liveGross=null;this.controlRoomSnapshot=l,l.activity&&this.seedFeed(l.activity),this.rebaseServerTotals(l),this.lastSyncedAt=Date.now(),this.authoritativeGrossRevenue=l.bookedValue.gross,this.authoritativeCurrency=l.currency,this.currency=l.currency,this.revenueStatus="current",this.recomputeTallies(),this.applyHeatOverlay(),this.paintMonitorInsights(),this.seatHistoryPanel?.refresh();let r=this.getSelection().slice(-1)[0],c=this.els.rail?.querySelector("[data-seat-status]");r&&c&&(c.textContent=this.status.get(r.label)??"free"),this.opts.onControlRoom?.(l)}return l}catch(s){throw e===this.revenueRequest&&(this.revenueStatus="stale",this.recomputeTallies()),s}}rebaseServerTotals(e){let t=e.totals;if(!t||["free","held","booked","blocked"].some(s=>!Number.isFinite(t[s]))){this.serverBaseline=null;return}this.serverBaseline={model:this.modelVersion,server:{free:t.free,held:t.held,booked:t.booked,blocked:t.blocked},client:this.clientTallies()}}clientTallies(){let{held:e,booked:t,blocked:s}=this.counts;return{held:e,booked:t,blocked:s,free:Math.max(0,this.unitTotal()-e-t-s)}}buildTallies(){let e=this.clientTallies(),t=this.serverBaseline?.model===this.modelVersion?this.serverBaseline:null,s=l=>t?Math.max(0,t.server[l]+(e[l]-t.client[l])):e[l],i=this.controlRoomSnapshot?.event?.seatTotal,a={free:s("free"),held:s("held"),booked:s("booked"),blocked:s("blocked"),total:Number.isFinite(i)?i:this.unitTotal(),capacityPct:0,sellThroughPct:0,bookedValue:this.authoritativeGrossRevenue,grossRevenue:this.authoritativeGrossRevenue,bookedValueStatus:this.revenueStatus,revenueStatus:this.revenueStatus,currency:this.currency};a.capacityPct=a.total?Math.round(a.booked/a.total*100):0;let o=a.total-a.blocked;return a.sellThroughPct=o>0?Math.round(a.booked/o*100):0,a}recomputeTallies(){if(!this.closed){if(typeof requestAnimationFrame!="function"){this.flushTallies();return}this.paintHandle===null&&(this.paintHandle=requestAnimationFrame(()=>{this.paintHandle=null,this.flushTallies()}))}}flushTallies(){if(this.closed)return;let e=this.buildTallies();this.paintKpis(e),this.mode==="view"?(this.paintLegend(e),this.paintMonitorInsights()):this.mode==="inspect"?this.renderInspectRail(this.getSelection()):this.mode==="block"?this.paintSelBar(this.getSelection()):this.mode==="channels"&&this.channels?.handleSelectionChange(),this.opts.onTallies?.(e)}verbFor(e,t){return t==="held"?"held":t==="booked"?"booked":t==="blocked"?"blocked":t==="free"?e==="blocked"?"unblocked":e==="booked"?"cancelled":"available":t}pushActivity(e,t,s,i=Date.now()){let a=e[0];if(!a)return null;let o=this.sectionsForLabels(e),l={id:`${a}:${i}:${Math.random().toString(36).slice(2,6)}`,at:i,label:a,labels:[...e],count:e.length,verb:t,status:s,sectionIds:o.ids,sectionLabels:o.labels};return this.controlRoomSnapshot?.activity||this.feed.unshift(l),this.feed.length>$&&(this.feed.length=$),this.mode==="view"&&this.paintFeed(),this.showLiveEvent(l),this.opts.onActivity?.(l),l}seedFeed(e){this.controlRoomSnapshot?.activity&&(this.feed=this.feed.filter(i=>i.id.startsWith("log:")));let t={hold:"held",book:"booked",release:"released",expire:"expired",block:"blocked",unblock:"unblocked",unbook:"cancelled"},s={hold:"held",book:"booked",release:"free",expire:"free",block:"blocked",unblock:"free",unbook:"free"};for(let i of e){if(this.feed.some(r=>r.id===`log:${i.id}`))continue;let a=i.labels[0];if(!a)continue;let o=this.sectionsForLabels(i.labels),l={id:`log:${i.id}`,at:i.at,label:a,labels:[...i.labels],count:i.labels.length,verb:t[i.action]??i.action,status:s[i.action]??"free",sectionIds:o.ids,sectionLabels:o.labels};this.feed.push(l),this.opts.onActivity?.(l)}this.feed.sort((i,a)=>a.at-i.at),this.feed.length>$&&(this.feed.length=$),this.mode==="view"&&this.paintFeed()}startFeedClock(){this.feedTimer=setInterval(()=>{this.mode==="view"&&(this.paintFeed(),this.paintMonitorInsights())},1e4)}selectionCap(){return this.mode!=="select"?1e6:this.opts.numberOfPlacesToSelect??this.opts.maxSelectedObjects??1e6}canSelectObject(e){let t=this.status.get(e.label)??"free",s=this.opts.unavailableObjectsSelectable??!0,i=t==="free"||s||this.selectableObjectLabels.has(e.label);if(!this.opts.isObjectSelectable)return i;try{return this.opts.isObjectSelectable(e,i)===!0}catch(a){return this.opts.onError?.(a),!1}}applyInitialSelection(){this.initialSelectionApplied||this.mode!=="select"||!this.renderer||(this.initialSelectionApplied=!0,this.selectByLabels(this.opts.selectedObjects??[]))}trimSelectionToCap(){if(this.mode!=="select")return;let e=this.getSelection(),t=this.selectionCap();e.length<=t||this.renderer?.deselect(e.slice(t).map(s=>s.id))}reconcileSelectPolicy(){if(this.mode!=="select")return;let e=this.getSelection().filter(t=>!this.canSelectObject(t));e.length&&this.renderer?.deselect(e.map(t=>t.id)),this.trimSelectionToCap(),this.syncSelection()}selectionLabels(){return this.getSelection().map(e=>e.label)}syncSelection(){let e=this.getSelection();this.mode==="block"?this.paintSelBar(e):this.mode==="inspect"?this.renderInspectRail(e):this.mode==="select"?this.paintSelectSelection(e):this.mode==="categories"?this.paintCategorySelection(e):this.mode==="channels"&&this.channels?.handleSelectionChange();let t=new Map(e.map(s=>[s.label,s]));if(this.mode==="select"){for(let[i,a]of t)this.lastSelectionLabels.has(i)||this.opts.onObjectSelected?.(a);for(let i of this.lastSelectionLabels)if(!t.has(i)){let a=this.labelToSeat.get(i);a&&this.opts.onObjectDeselected?.(a)}let s=this.getSelectionValidity();s&&(this.opts.onSelectionValidityChange?.(s),this.selectionWasValid!==s.isValid&&(s.isValid?this.opts.onSelectionValid?.(s):this.opts.onSelectionInvalid?.(s)),this.selectionWasValid=s.isValid)}this.lastSelectionLabels=new Set(t.keys()),this.navigation?.selectionChanged(e.length),this.opts.onSelectionChange?.(e)}buildChrome(){let e=document.createElement("div");e.className="slm",e.tabIndex=0,e.setAttribute("role","region"),e.setAttribute("aria-label","SeatLayer live control room"),e.innerHTML=`
715
+ </div>`}var Lt="https://api.seatlayer.io",H=200,Ae=16,$e=4,He=[{key:"watch",label:"Watch",tools:[{mode:"view",label:"Monitor",shortcut:"M",title:"Live board \u2014 inventory, activity and booking momentum. Read-only."},{mode:"inspect",label:"Inspect",shortcut:"I",title:"Click one seat to read its live status and booking context. Read-only."}]},{key:"manage",label:"Manage",tools:[{mode:"block",label:"Block",shortcut:"B",title:"Take seats off sale for this event, or put them back."},{mode:"sections",label:"Sections",shortcut:"S",title:"Open, close or hide sections for this event, on a schedule or on demand."},{mode:"categories",label:"Categories",shortcut:"G",title:"Move seats to a different price category for this event only."},{mode:"tables",label:"Tables",shortcut:"T",title:"Sell each table per chair or as one whole-table booking."},{mode:"channels",label:"Channels",shortcut:"C",title:"Allocate inventory to sales channels and share their links."}]},{key:"host",label:"Host tools",tools:[{mode:"select",label:"Select",shortcut:"X",title:"Select seats for your own back-office operation. The selection is handed to your app; nothing changes here."},{mode:"filterSections",label:"Filter",shortcut:"L",title:"Filter the map to one section for your own reporting."}]}],Mt=3;function Tt(n){let e=n?.status;return e===401||e===403}var Be=n=>`<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">${n}</svg>`,j={enter:Be('<path d="M4 9V4h5M15 4h5v5M20 15v5h-5M9 20H4v-5"/>'),exit:Be('<path d="M9 4v5H4M20 9h-5V4M15 20v-5h5M4 15h5v5"/>')},Ct=Object.fromEntries(He.flatMap(n=>n.tools.map(e=>[e.shortcut.toLowerCase(),e.mode]))),q=class{constructor(e){this.els={};this.renderer=null;this.doc=null;this.selectObserver=null;this.seatHistoryPanel=null;this.activityPanel=null;this.navigation=null;this.movingMap=!1;this.marqueeShape="box";this.socketSnapshotSeen=!1;this.monitorRefreshTimer=null;this.themeMode=null;this.colorSchemeStop=null;this.inventoryModelVersion=1;this.selectableObjectLabels=new Set;this.lastSelectionLabels=new Set;this.selectionWasValid=null;this.initialSelectionApplied=!1;this.labelToId=new Map;this.labelToSeat=new Map;this.allIds=[];this.gaUnitLabelSet=new Set;this.tableChairIds=new Map;this.status=new Map;this.counts={held:0,booked:0,blocked:0};this.modelVersion=0;this.currency="USD";this.authoritativeCurrency=null;this.authoritativeGrossRevenue=0;this.revenueStatus="loading";this.revenueRequest=0;this.controlRoomSnapshot=null;this.serverBaseline=null;this.livePresence=null;this.liveGross=null;this.paintHandle=null;this.trendWindowMinutes=15;this.heatEnabled=!1;this.mapView=$();this.barFind=null;this.minimap=null;this.lastKpiValues=new Map;this.activeKpiDeltas=new Map;this.ws=null;this.reconnectTimer=null;this.attempt=0;this.closed=!1;this.connectionStatus="reconnecting";this.lastMessageAt=null;this.ready=!1;this.feed=[];this.feedTimer=null;this.toastTimer=null;this.liveEventTimer=null;this.kpiCleanupTimer=null;this.followLiveTimer=null;this.followSeatTimer=null;this.releaseAt=null;this.layoutObserver=null;this.tokenExpiresAt=null;this.tokenRefreshTimer=null;this.tokenRefreshInFlight=!1;this.tokenRefreshFailures=0;this.sessionEnded=!1;this.sectionByObject=new Map;this.sectionLabelById=new Map;this.sectionsBase=null;this.filteredSectionLabel=null;this.availabilityRules={};this.effectiveHidden=new Set;this.effectiveClosed=new Set;this.availabilitySaving=!1;this.lastSyncedAt=null;this.blockBrowse=!1;this.blockedQuery="";this.blockedSection="";this.blockedResultLimit=100;this.unblockAllConfirmTimer=null;this.channels=null;this.chooser=null;this.chooserDialog=null;this.categoryDifferences=null;this.channelCaps={view:!1,manage:!1};this.categoryCanManage=!1;this.tableCanManage=!1;this.tableBookingSaving=!1;this.channelCapabilityResolution=0;this.channelsLoading=null;this.onFullscreenChange=()=>{this.paintFullscreenButton(),this.updateContainerLayout(),this.renderer?.forceDraw()};this.onKeyDown=e=>{if(e.metaKey||e.ctrlKey||e.altKey||e.target?.matches('input,select,textarea,[contenteditable="true"]'))return;let s=e.key.toLowerCase(),i=e.shiftKey?xe(s):null;if(i){this.toggleMapView(i),e.preventDefault();return}if(s==="/"){let a=this.els.findbar?.querySelector("[data-ch-find-input]");a&&(a.focus(),a.select(),e.preventDefault());return}let o=Ct[s];if(o){if(!this.toolAvailable(o))return;this.setMode(o)}else if(s==="f")this.toggleFullscreen();else if(s==="escape"){let a=this.els.view;if(a?.open)a.open=!1,a.querySelector("summary")?.focus();else if(!this.channels?.handleBack())if(this.getSelection().length)this.clearSelection();else return}else return;e.preventDefault()};this.onRailClick=e=>{let t=e.target,s=t?.closest("[data-section-focus]");if(s?.dataset.sectionFocus){this.locateSection(s.dataset.sectionFocus);return}let i=t?.closest("[data-feed-id]");i?.dataset.feedId&&this.locateActivity(i.dataset.feedId)};this.typeKeyBySection=null;this.typeKeyBase=null;this.sectionOptions=[];O(e.token),this.assertSelectionOptions(e.maxSelectedObjects,e.numberOfPlacesToSelect),this.opts=e,this.key=e.eventKey,this.mode=e.mode??"view",this.selectableObjectLabels=new Set(e.selectableObjects??[]),this.categoryCanManage=new Set(e.capabilities??[]).has("event:categories:manage"),this.tableCanManage=new Set(e.capabilities??[]).has("event:tables:manage"),this.keepLive=e.keepLiveWhileHidden??!0,this.themeMode=e.themeMode??null,this.followLive=e.followLive??!1,this.currency=e.currency??"USD",this.tokenExpiresAt=e.tokenExpiresAt??null,this.api=new F(e.apiBase??Lt,e.token),this.organizerAssetUrls=new A(this.key,(t,s)=>this.withAuthRetry(()=>this.api.asset(t,s))),this.host=Y(e.container)}assertSelectionOptions(e,t){let s=i=>i===void 0||Number.isInteger(i)&&i>0;if(!s(e))throw new TypeError("maxSelectedObjects must be a positive integer");if(!s(t))throw new TypeError("numberOfPlacesToSelect must be a positive integer");if(e!==void 0&&t!==void 0&&e<t)throw new TypeError("maxSelectedObjects cannot be lower than numberOfPlacesToSelect")}async render(){ce(),this.buildChrome();try{let e=await this.withAuthRetry(()=>this.api.chart(this.key));this.inventoryModelVersion=e.event.inventoryModelVersion===2?2:1,this.doc=await this.organizerAssetUrls.prepareRendererChart(e.doc),this.authoritativeCurrency=e.event.currency??null,this.currency=this.authoritativeCurrency??this.opts.currency??this.currency,this.buildUnitUniverse(this.doc),this.buildRenderer(),this.buildSectionOptions(),this.settleMode();let[,t]=await Promise.all([this.resnapshot(),this.refreshControlRoom().catch(s=>this.opts.onError?.(s)),this.refreshAvailability()]);t?.activity?this.seedFeed(t.activity):this.api.log(this.key,{limit:24}).then(s=>this.seedFeed(s.entries)).catch(()=>{}),this.connect(),this.startFeedClock(),this.ready=!0,await this.resolveChannelCapabilities(),this.setMode(this.mode),this.applyInitialSelection(),this.scheduleTokenRefresh(),this.opts.onReady?.()}catch(e){this.fail(e)}return this}setMode(e){this.toolAvailable(e)||(e="view"),e==="channels"&&!this.channels&&this.ensureChannels();let t=e!==this.mode,s=this.mode==="channels",i=this.mode==="filterSections";this.mode=e,t&&e!=="view"&&this.setFollowLive(!1),!this.renderer&&this.doc?this.buildRenderer():this.updateRendererInteraction(),t&&(this.renderer?.clearSelection(),this.syncSelection()),s&&e!=="channels"&&this.channels?.leave(),t&&(this.highlightLabels(null),this.wireBarFind()),this.paintModeTabs(),this.paintRail(),this.paintMapViewMenu(),this.applyMapView(),this.applySectionCanvasTreatment(),i&&e!=="filterSections"&&this.renderer?.zoomToFit(),e==="channels"&&this.channels?.enter(),e==="select"&&this.applyInitialSelection(),t&&this.opts.onModeChange?.(e)}async resolveChannelCapabilities(){let e=++this.channelCapabilityResolution,t=this.opts.capabilities,s;if(t){let i=new Set(t);s={view:i.has("event:channels:view"),manage:i.has("event:channels:view")&&i.has("event:channels:manage")}}else s={view:!1,manage:!1};if(!s.view&&!t)try{await this.api.channels(this.key),s={view:!0,manage:!1}}catch{s={view:!1,manage:!1}}if(e===this.channelCapabilityResolution){if(this.channelCaps=s,!this.channelCaps.view){this.channels?.destroy(),this.channels=null,this.mode==="channels"?this.setMode("view"):this.paintModeTabs();return}this.channels?.setCapabilities(this.channelCaps),this.paintModeTabs()}}ensureChannels(){if(this.channelsLoading)return this.channelsLoading;if(this.channels)return Promise.resolve();let e=(async()=>{try{let t=await import("./channelsMode-YJO6FOPD.js");if(this.closed||!this.channelCaps.view||(this.channels||(de(t.CHANNELS_CSS),this.channels=new t.ChannelsMode(this.buildChannelsHost(),this.channelCaps),this.channels.onInteractionChange=()=>this.updateRendererInteraction()),this.mode!=="channels"))return;this.updateRendererInteraction(),this.paintRail(),this.channels.enter(),this.applyMapView(),this.paintMapViewMenu()}catch(t){if(this.closed)return;this.channelsLoading=null,this.mode==="channels"&&this.paintRail(),this.opts.onError?.(t)}})();return this.channelsLoading=e,e}buildChooserHost(){let e=s=>{let i=this.labelToSeat.get(s);return i?this.mode==="block"?this.isBlockSelectable(s):this.mode==="select"?this.canSelectObject(i):!0:!1};return{selectionLabels:()=>this.selectionLabels(),selectByLabels:s=>{this.selectByLabels(s)},clearSelection:()=>this.clearSelection(),selectSection:s=>{this.selectSection(s)},sections:()=>this.sectionOptions,labelsInSection:s=>(this.renderer?.getSelectableInSection(s)??[]).map(i=>i.label).filter(e),rows:()=>{let s=new Map((this.doc?.objects??[]).map(o=>[o.id,o])),i=new Map;for(let o of this.labelToSeat.values()){if(!e(o.label))continue;let a=s.get(o.rowId);if(!a||a.type!=="row"&&a.type!=="table")continue;let l=o.logicalRowId??o.rowId,r=this.sectionByObject.get(o.rowId)??v,c=i.get(l)??{id:l,label:a.type==="row"?a.segmentedRow?.displayLabel??a.displayLabel??a.label:a.displayLabel??a.label,sectionId:r,sectionLabel:this.sectionLabelById.get(r)??"Other seats",labels:[]};c.labels.push(o.label),i.set(l,c)}return[...i.values()].sort((o,a)=>o.sectionLabel.localeCompare(a.sectionLabel,void 0,{numeric:!0,sensitivity:"base"})||o.label.localeCompare(a.label,void 0,{numeric:!0,sensitivity:"base"}))},categories:()=>(this.doc?.categories??[]).map(s=>({key:s.key,label:s.label??s.key,color:s.color})),labelsInCategory:s=>[...this.labelToSeat.values()].filter(i=>i.categoryKey===s&&e(i.label)).map(i=>i.label),seats:()=>[...this.labelToSeat.values()].filter(s=>e(s.label)).map(s=>({label:s.label})),statusOf:s=>this.status.get(s)??(this.labelToSeat.has(s)?"free":void 0),sectionOfLabel:s=>{let i=this.labelToSeat.get(s);if(!i)return null;let o=this.sectionByObject.get(i.rowId)??v;return{id:o,label:this.sectionLabelById.get(o)??"Other seats"}},openDialog:(s,i)=>{this.chooserDialog=ae(this.root,s,i,{previous:this.chooserDialog,onClose:()=>{this.chooserDialog=null}})},closeDialog:()=>this.chooserDialog?.close(),highlight:s=>this.highlightLabels(s),...this.mode==="select"?{cap:this.selectionCap()}:{}}}wireBarFind(){let e=this.els.findbar;e&&(e.innerHTML=D({compact:!0}),this.barFind=new V({...this.buildChooserHost(),seats:()=>[...this.labelToSeat.values()].map(t=>({label:t.label})),frame:t=>this.frameLabels(t)}),this.barFind.wireFind(e,{enter:this.isChoosingTool()?"select":"frame"}))}isChoosingTool(){return this.isBulkSelectMode()||this.mode==="select"}frameLabels(e){let t=e.map(s=>this.labelToSeat.get(s)?.id).filter(s=>!!s);t.length&&(this.setFollowLive(!1),this.renderer?.focusSeats?.(t,{animate:!0}))}highlightLabels(e){if(!e){this.renderer?.setSeatHighlight?.(null);return}this.renderer?.setSeatHighlight?.(e.map(t=>this.labelToSeat.get(t)?.id).filter(t=>!!t))}toolChooser(){return this.chooserDialog?.close({restoreFocus:!1}),this.chooser=new V(this.buildChooserHost()),this.chooser}toolSelectionBar(e,t,s,i){return se({count:0,noun:"selected",breakdown:`<span class="slm-selactions"><button type="button" class="slm-linkbtn" data-ref="${i}">Select all</button></span>`,clearAttr:`data-ref="${s}"`}).replace('class="slm-selnum"',`class="slm-selnum" data-ref="${e}"`).replace('class="slm-sellabel"',`class="slm-sellabel" data-ref="${t}"`)}buildChannelsHost(){return{eventKey:this.key,api:this.api,rail:this.els.rail,mapLayer:this.root.querySelector(".slm-map"),pillLane:this.els.lane,root:this.root,seats:()=>[...this.labelToSeat.values()].map(e=>({id:e.id,label:e.label,x:e.x,y:e.y})),statusOf:e=>this.status.get(e)??(this.labelToSeat.has(e)?"free":void 0),selectionLabels:()=>this.selectionLabels(),selectByLabels:e=>{this.selectByLabels(e)},clearSelection:()=>this.clearSelection(),selectSection:e=>{this.selectSection(e)},sections:()=>this.sectionOptions,labelsInSection:e=>this.renderer?.getSelectableInSection(e).map(t=>t.label)??[],rows:()=>{let e=new Map((this.doc?.objects??[]).map(s=>[s.id,s])),t=new Map;for(let s of this.labelToSeat.values()){let i=e.get(s.rowId);if(!i||i.type!=="row"&&i.type!=="table")continue;let o=s.logicalRowId??s.rowId,a=this.sectionByObject.get(s.rowId)??v,l=t.get(o)??{id:o,label:i.type==="row"?i.segmentedRow?.displayLabel??i.displayLabel??i.label:i.displayLabel??i.label,sectionId:a,sectionLabel:this.sectionLabelById.get(a)??"Other seats",labels:[]};l.labels.push(s.label),t.set(o,l)}return[...t.values()].sort((s,i)=>s.sectionLabel.localeCompare(i.sectionLabel,void 0,{numeric:!0,sensitivity:"base"})||s.label.localeCompare(i.label,void 0,{numeric:!0,sensitivity:"base"}))},categories:()=>(this.doc?.categories??[]).map(e=>({key:e.key,label:e.label??e.key,color:e.color,price:e.price,tiers:e.tiers?.map(t=>({id:t.id,name:t.name,price:t.price}))})),labelsInCategory:e=>[...this.labelToSeat.entries()].filter(([,t])=>t.categoryKey===e).map(([t])=>t),sectionOfLabel:e=>{let t=this.labelToSeat.get(e);if(!t)return null;let s=this.sectionByObject.get(t.rowId)??v;return{id:s,label:this.sectionLabelById.get(s)??"Other seats"}},worldToScreen:e=>this.renderer?.worldToScreen(e)??null,seatPixelSize:()=>this.seatPixelSize(),isSeatDetail:()=>this.renderer?.getRung?.()==="seats",showSectionOverview:()=>{this.renderer?.clearSectionFocus(),this.renderer?.setRung?.("sections")},focusSection:e=>this.renderer?.focusSection(e),isCompact:()=>!!this.root?.classList.contains("compact"),setMapInert:e=>{this.mapHost.toggleAttribute("inert",e),this.mapHost.setAttribute("aria-hidden",String(e))},toast:(e,t)=>this.toast(e,t),onError:e=>this.opts.onError?.(e)}}seatPixelSize(){let e=this.renderer?.getVisibleWorldRect?.(),t=this.mapHost?.clientWidth??0;return!e?.width||!t?6:Math.max(3,t/e.width*18)}setHeatOverlay(e){this.heatEnabled=e,this.mapView.momentum!==e&&this.setMapView({momentum:e}),this.applyHeatOverlay(),this.paintHeatButton()}setMapView(e){let t={...this.mapView,...e};if(!Object.keys(t).some(o=>t[o]!==this.mapView[o]))return;let i=t.categoryColours!==this.mapView.categoryColours;this.mapView=t,ke(t),t.momentum!==this.heatEnabled&&this.setHeatOverlay(t.momentum),this.applyMapView(),this.paintMapViewMenu(),i&&(this.refreshBlockPaint(),this.paintMapChrome())}getColourBy(){return this.mapView.categoryColours?"type":"full"}setColourBy(e){this.setMapView({categoryColours:e==="type"})}getMapView(){return{...this.mapView}}toggleMapView(e){e==="channelColours"&&!this.channelColoursAvailable()||this.setMapView({[e]:!this.mapView[e]})}channelColoursAvailable(){return this.mode==="channels"&&this.channels!=null}applyMapView(){Le(this.mapView,{renderer:this.renderer,channelsOverlay:e=>this.channels?.setOverlayVisible(e)})}paintMapViewMenu(){let e=this.els.view;e&&Te(e,this.mapView,{channelColoursAvailable:this.channelColoursAvailable(),momentumLoading:this.mapView.momentum&&!this.controlRoomSnapshot})}setFollowLive(e){let t=this.followLive!==e;this.followLive=e,e||(this.followLiveTimer&&clearTimeout(this.followLiveTimer),this.followSeatTimer&&clearTimeout(this.followSeatTimer),this.followLiveTimer=null,this.followSeatTimer=null),this.paintFollowLiveButton(),t&&this.opts.onFollowLiveChange?.(e)}setKeepLiveWhileHidden(e){this.keepLive=e??!0,this.opts.keepLiveWhileHidden=e}setCurrency(e){this.opts.currency=e,!this.authoritativeCurrency&&(this.currency=e??"USD",this.ready&&this.recomputeTallies())}setTheme(e){this.opts.theme=e,this.applyThemeVars()}applyThemeVars(){if(!this.root)return;let e=I(this.themeMode);for(let[t,s]of Object.entries(J(this.opts.theme,e)))this.root.style.setProperty(t,s);e?this.root.dataset.theme=e:delete this.root.dataset.theme}watchThemeMode(){this.colorSchemeStop?.(),this.colorSchemeStop=null,this.themeMode==="auto"&&(this.colorSchemeStop=N(()=>{this.closed||this.repaintForThemeMode()}))}repaintForThemeMode(){this.applyThemeVars();let e=this.renderer;if(!e||!this.doc)return;let t=e.getSelection().map(o=>o.id),s=e.getCameraPose(),i=e.getFocusedSection();e.setChart(this.themedDoc()),this.repaintAll(),this.applyHeatOverlay(),t.length&&e.select(t),i&&e.focusSection(i),e.setCameraPose(s),this.updateZoomHint()}setThemeMode(e){let t=e??null;this.closed||t===this.themeMode||(this.themeMode=t,this.opts.themeMode=t??void 0,this.watchThemeMode(),this.repaintForThemeMode())}getThemeMode(){return this.themeMode}themedDoc(){let e=this.doc,t=ee(I(this.themeMode));return t?{...e,theme:{...e.theme??{},background:t}}:e}setCapabilities(e){this.opts.capabilities=e,this.categoryCanManage=new Set(e??[]).has("event:categories:manage"),this.tableCanManage=new Set(e??[]).has("event:tables:manage"),!this.categoryCanManage&&this.mode==="categories"||!this.tableCanManage&&this.mode==="tables"?this.setMode("view"):this.paintModeTabs(),this.ready&&this.resolveChannelCapabilities()}setTokenRefresh(e){this.opts.onTokenRefresh=e,this.scheduleTokenRefresh()}setTrendWindow(e){let t=Number.isFinite(e)?Math.floor(e):15;return this.trendWindowMinutes=Math.max(5,Math.min(60,t)),this.paintTrendWindow(),this.refreshControlRoom()}async enterFullscreen(){!this.root?.requestFullscreen||this.isFullscreen()||(await this.root.requestFullscreen(),this.root.focus({preventScroll:!0}))}async exitFullscreen(){typeof document>"u"||!this.isFullscreen()||await document.exitFullscreen()}isFullscreen(){return typeof document<"u"&&document.fullscreenElement===this.root}toggleFullscreen(){(this.isFullscreen()?this.exitFullscreen():this.enterFullscreen()).catch(t=>this.opts.onError?.(t))}setToken(e,t){O(e),this.api.setToken(e),this.opts.token=e,this.opts.tokenExpiresAt=t,this.tokenExpiresAt=t??null,this.scheduleTokenRefresh(),this.ready&&this.resolveChannelCapabilities()}scheduleTokenRefresh(){this.tokenRefreshTimer&&clearTimeout(this.tokenRefreshTimer),this.tokenRefreshTimer=null;let e=this.opts.onTokenRefresh,t=this.tokenExpiresAt;if(this.closed||!e||!t||!Number.isFinite(t))return;let s=t-Date.now(),i=Math.min(12e4,Math.max(3e4,s*.2)),o=Math.max(0,s-i);this.tokenRefreshTimer=setTimeout(()=>{this.tokenRefreshTimer=null,this.rotateToken()},o)}async rotateToken(){if(!(this.closed||this.sessionEnded||this.tokenRefreshInFlight||!this.opts.onTokenRefresh)){this.tokenRefreshInFlight=!0;try{let e=await this.opts.onTokenRefresh();if(!e?.token||!Number.isFinite(e.expiresAt))throw new Error("invalid_token_refresh_result");this.tokenRefreshFailures=0,this.setToken(e.token,e.expiresAt)}catch(e){this.opts.onError?.(e),this.tokenRefreshFailures+=1,!this.closed&&(this.tokenRefreshFailures>=Mt||Tt(e))?this.endSession():this.closed||(this.tokenRefreshTimer=setTimeout(()=>{this.tokenRefreshTimer=null,this.rotateToken()},3e4))}finally{this.tokenRefreshInFlight=!1}}}endSession(){if(this.sessionEnded)return;this.sessionEnded=!0,this.tokenRefreshTimer&&clearTimeout(this.tokenRefreshTimer),this.tokenRefreshTimer=null,this.reconnectTimer&&clearTimeout(this.reconnectTimer),this.reconnectTimer=null,this.monitorRefreshTimer&&clearTimeout(this.monitorRefreshTimer),this.monitorRefreshTimer=null;let e=this.ws;if(this.ws=null,e){e.onclose=null;try{e.close()}catch{}}this.setLive(!1),this.paintSessionEnded()}async retrySession(){if(this.closed||!this.sessionEnded)return!this.sessionEnded;if(!this.opts.onTokenRefresh)return!1;this.sessionEnded=!1,this.tokenRefreshFailures=0;let e=this.root?.querySelector('[data-ref="ended"]');return e?.setAttribute("data-busy","true"),await this.rotateToken(),this.sessionEnded?(e?.removeAttribute("data-busy"),!1):(e?.remove(),this.attempt=0,this.connect(),!0)}paintSessionEnded(){let e=this.els.lane;if(!e||e.querySelector('[data-ref="ended"]'))return;let t=document.createElement("div");t.className="slm-ended",t.setAttribute("data-ref","ended"),t.setAttribute("role","alertdialog"),t.setAttribute("aria-labelledby","slm-ended-title"),t.innerHTML=`
716
+ <strong id="slm-ended-title">This session ended</strong>
717
+ <span>The map is as it was when the connection stopped. Sign in again, then try again to pick the live stream back up.</span>
718
+ <button type="button" class="slm-btn" data-ref="ended-retry">Try again</button>`,t.querySelector('[data-ref="ended-retry"]').addEventListener("click",()=>{this.retrySession()}),e.appendChild(t)}async block(e,t={}){let s=(e??this.selectionLabels()).filter(o=>this.status.get(o)==="free");if(!s.length)return;let i=t.releaseAt??this.releaseAt??void 0;this.setSeatsLocal(s,"blocked");try{await this.api.block(this.key,s,{...t,releaseAt:i}),this.clearSelection(),this.done("block",s,i?`Blocked ${s.length} \u2014 auto-release ${new Date(i).toLocaleString()}.`:`Blocked ${s.length} seat${s.length===1?"":"s"}.`)}catch(o){this.setSeatsLocal(s,"free"),this.toastErr(o instanceof k&&o.status===409?"Some seats were just taken. Try again.":"Couldn't block those seats."),this.opts.onError?.(o)}}async unblock(e){let t=(e??this.selectionLabels()).filter(s=>this.status.get(s)==="blocked");if(t.length){this.setSeatsLocal(t,"free");try{await this.api.unblock(this.key,t),this.clearSelection(),this.done("unblock",t,`Unblocked ${t.length} seat${t.length===1?"":"s"}.`)}catch(s){this.setSeatsLocal(t,"blocked"),this.toastErr("Couldn't unblock those seats."),this.opts.onError?.(s)}}}async unblockAll(){let e=[...this.status.entries()].filter(([,t])=>t==="blocked").map(([t])=>t);if(e.length){this.setSeatsLocal(e,"free");try{let t=await this.api.unblockAll(this.key);this.clearSelection(),this.done("unblockAll",e,`Unblocked ${t.freed} seat${t.freed===1?"":"s"}.`)}catch(t){await this.resnapshot(),this.toastErr("Couldn't mark everything for sale."),this.opts.onError?.(t)}}}async cancelBooking(e,t){let s=e.filter(i=>this.status.get(i)==="booked");if(!(!s.length||!t)){this.setSeatsLocal(s,"free");try{await this.api.unbook(this.key,s,t),this.clearSelection(),this.done("cancelBooking",s,`Released ${s.length} booked unit${s.length===1?"":"s"}.`)}catch(i){this.setSeatsLocal(s,"booked"),this.toastErr("Couldn't release that booked inventory. Check the booking reference."),this.opts.onError?.(i)}}}async setCategory(e,t){let s=this.doc?.categories.find(o=>o.key===e),i=[...new Set(t??this.selectionLabels())].filter(o=>this.labelToSeat.has(o));if(!(!s||!i.length))try{let o=await this.withAuthRetry(()=>this.api.setCategory(this.key,i,e)),a={};for(let l of o.labels){let r=this.labelToSeat.get(l),c=this.labelToId.get(l);r&&(r.categoryKey=e),c&&(a[c]=e)}this.renderer?.setSeatCategories?.(a),this.clearSelection(),this.mode==="categories"&&this.loadCategoryDifferences(),this.done("setCategory",o.labels,`Assigned ${o.labels.length.toLocaleString()} object${o.labels.length===1?"":"s"} to ${s.label??s.key}.`)}catch(o){this.toastErr("Couldn't update those event categories."),this.opts.onError?.(o)}}async setTableBooking(e,t,s={}){let i=[...new Set(e)].filter(Boolean);if(!(!i.length||this.tableBookingSaving)){if(this.inventoryModelVersion!==2){this.toastErr("Table booking controls require inventory model 2 for this event.");return}this.tableBookingSaving=!0,this.mode==="tables"&&this.renderTablesRail();try{let o=await this.withAuthRetry(()=>this.api.setTableBooking(this.key,i,t,s));await this.reloadEventChart(),this.done("setTableBooking",o.tableIds,`Updated ${o.tableIds.length.toLocaleString()} table${o.tableIds.length===1?"":"s"} to ${t==="individual"?"per-chair":t==="whole"?"whole-table":"flexible-group"} booking.`)}catch(o){let a=o instanceof k&&o.code==="table_inventory_in_use";this.toastErr(a?"Release held, booked, or blocked table inventory before changing its booking mode.":"Couldn't update table booking. No table mode was changed."),this.opts.onError?.(o)}finally{this.tableBookingSaving=!1,this.mode==="tables"&&this.renderTablesRail()}}}async reloadEventChart(){let e=await this.withAuthRetry(()=>this.api.chart(this.key));this.inventoryModelVersion=e.event.inventoryModelVersion===2?2:1;let t=await this.organizerAssetUrls.prepareRendererChart(e.doc);this.renderer?.destroy(),this.renderer=null,this.doc=t,this.labelToId.clear(),this.labelToSeat.clear(),this.allIds=[],this.gaUnitLabelSet.clear(),this.tableChairIds.clear(),this.status.clear(),this.counts={held:0,booked:0,blocked:0},this.serverBaseline=null,this.lastSelectionLabels.clear(),this.buildUnitUniverse(t),this.buildRenderer(),this.buildSectionOptions(),this.settleMode(),await Promise.all([this.resnapshot(),this.refreshAvailability()]),this.paintRail()}selectAll(){if(this.mode==="select")return this.selectByLabels([...this.labelToSeat.values()].filter(t=>this.canSelectObject(t)).map(t=>t.label));let e=this.renderer?.selectAllSelectable()??[];return this.syncSelection(),e}selectSection(e){if(!this.renderer)return[];let t=this.renderer.getSelectableInSection(e);return this.renderer.selectByLabels(t.map(s=>s.label)),this.syncSelection(),this.renderer.getSelection()}setFilteredSection(e){let t=e.trim(),s=this.filterableSections().filter(a=>a.label===t);if(!s.length)throw new Error(`Unknown event section: ${e}`);let i=t!==this.filteredSectionLabel;this.filteredSectionLabel=t,this.mode==="filterSections"&&(this.applyFilteredSectionCanvas(s),this.renderFilterSectionsRail());let o=s.map(({id:a,label:l,seatCount:r,zone:c})=>({id:a,label:l,seatCount:r,...c?{zone:c}:{}}));return i&&this.opts.onFilteredSectionChange?.(o),o}focusSection(e){let t=e.trim(),s=this.filterableSections().filter(i=>i.label===t);return!this.renderer||!s.length?[]:(this.frameSections(s),s.map(({id:i,label:o,seatCount:a,zone:l})=>({id:i,label:o,seatCount:a,...l?{zone:l}:{}})))}clearFilteredSection(){let e=this.filteredSectionLabel!==null;this.filteredSectionLabel=null,this.renderer?.setDimmedSections(null),this.renderer?.clearSectionFocus(),this.renderer?.zoomToFit(),this.mode==="filterSections"&&this.renderFilterSectionsRail(),e&&this.opts.onFilteredSectionChange?.([])}getFilteredSections(){return this.filteredSectionLabel?this.filterableSections().filter(e=>e.label===this.filteredSectionLabel).map(({id:e,label:t,seatCount:s,zone:i})=>({id:e,label:t,seatCount:s,...i?{zone:i}:{}})):[]}selectByLabels(e){let t=e;if(this.mode==="select"){let s=new Set(this.selectionLabels()),i=this.selectionCap(),o=[...new Set(e)].filter(l=>!s.has(l)).map(l=>this.labelToSeat.get(l)).filter(l=>!!l&&this.canSelectObject(l)),a=Math.max(0,i-s.size);o.length>a&&this.opts.onSelectionLimit?.(i),t=o.slice(0,a).map(l=>l.label)}return this.renderer?.selectByLabels(t),this.syncSelection(),this.getSelection()}selectObjects(e){return this.selectByLabels(e)}deselectObjects(e){let t=e.map(s=>this.labelToId.get(s)).filter(s=>!!s);return this.renderer?.deselect(t),this.syncSelection(),this.getSelection()}selectCategories(e){let t=new Set(e);return this.selectByLabels([...this.labelToSeat.values()].filter(s=>t.has(s.categoryKey)).map(s=>s.label))}deselectCategories(e){let t=new Set(e);return this.deselectObjects(this.getSelection().filter(s=>t.has(s.categoryKey)).map(s=>s.label))}setSelectableObjects(e){this.opts.selectableObjects=[...e],this.selectableObjectLabels=new Set(e),this.reconcileSelectPolicy()}setUnavailableObjectsSelectable(e){this.opts.unavailableObjectsSelectable=e,this.reconcileSelectPolicy()}setObjectSelectable(e){this.opts.isObjectSelectable=e,this.reconcileSelectPolicy()}setMaxSelectedObjects(e){this.assertSelectionOptions(e,this.opts.numberOfPlacesToSelect),this.opts.maxSelectedObjects=e,this.trimSelectionToCap(),this.updateRendererInteraction(),this.syncSelection()}setNumberOfPlacesToSelect(e){this.assertSelectionOptions(this.opts.maxSelectedObjects,e),this.opts.numberOfPlacesToSelect=e,this.selectionWasValid=null,this.trimSelectionToCap(),this.updateRendererInteraction(),this.syncSelection()}getSelectionValidity(){let e=this.opts.numberOfPlacesToSelect;if(e===void 0)return null;let t=this.getSelection(),s=t.length;return{isValid:s===e,count:s,required:e,remaining:Math.max(0,e-s),objects:t}}clearSelection(){this.renderer?.clearSelection(),this.syncSelection()}getSelection(){return this.renderer?.getSelection()??[]}getReport(){return this.api.report(this.key).then(e=>(this.applyReportRevenue(e),e))}getControlRoomSnapshot(e=this.trendWindowMinutes){return this.setTrendWindow(e)}getConnection(){return{status:this.connectionStatus,lastMessageAt:this.lastMessageAt}}getLog(e={}){return this.api.log(this.key,e)}async setHoldTtl(e){try{await this.api.setHoldTtl(this.key,e),this.done("setHoldTtl",[],e?`Hold window set to ${Math.round(e/6e4)} min.`:"Hold window reset.")}catch(t){this.toastErr("Couldn't update the hold window."),this.opts.onError?.(t)}}zoomToFit(){if(this.mode==="filterSections"&&this.filteredSectionLabel){this.clearFilteredSection();return}this.renderer?.clearSectionFocus(),this.renderer?.zoomToFit()}zoomOutStep(){let e=this.renderer;if(!e)return;if(!e.zoomOutLevel)return void e.zoomOut();let t=!!e.getFocusedSection?.();e.zoomOutLevel()==="venue"&&t&&e.clearSectionFocus()}paintMapChrome(){let e=this.renderer;if(!e||!this.els.crumb)return;let t=e.getFocusedSection?.()??null,s=t?e.getMinimapSnapshot?.().sections.find(l=>l.id===t)??null:null,i=e.getFloors?.()??[],o=i.length>1?e.isFloorOverview?.()?"All floors":i.find(l=>l.id===e.getActiveFloorId?.())?.name??null:null,a=this.els.blocklegend;a&&fe(a,{colourBy:this.getColourBy(),seats:e.getRung?.()==="seats",types:this.legendTypes()}),ue(this.els,me({focused:s?{label:s.label,free:s.free,total:s.total}:null,floor:o,seatsRevealed:e.seatsRevealed?.()??!0,atVenueFit:e.atVenueFit?.(),atCeiling:e.canZoomIn?.()===!1||e.seatsPickable?.()===!0}))}sectionTypeKeys(){if(this.typeKeyBySection&&this.typeKeyBase===this.sectionsBase)return this.typeKeyBySection;let e=new Map;for(let t of this.filterableSections()){let s=new Map;for(let o of t.seatLabels){let a=this.labelToSeat.get(o)?.categoryKey;a&&s.set(a,(s.get(a)??0)+1)}let i=null;for(let[o,a]of s)(!i||a>s.get(i))&&(i=o);i&&e.set(t.id,i)}return this.typeKeyBySection=e,this.typeKeyBase=this.sectionsBase,e}sectionTypeTint(e){let t=this.sectionTypeKeys().get(e);return t?this.renderer?.categoryDisplayColor?.(t)??null:null}legendTypes(){let e=new Set;for(let t of this.labelToSeat.values())e.add(t.categoryKey);return(this.doc?.categories??[]).filter(t=>e.has(t.key)).map(t=>({label:t.label,color:this.renderer?.categoryDisplayColor?.(t.key)??t.color}))}refreshBlockPaint(){this.renderer?.refreshBlockPaint?.(),this.minimap?.refreshMinimap()}mapCamera(){return{getViewport:()=>{let e=this.renderer;return!e?.getVisibleWorldRect||!e.getWorldBounds?null:{visible:e.getVisibleWorldRect(),bounds:e.getWorldBounds()}},getMinimapSnapshot:()=>this.renderer?.getMinimapSnapshot?.()??{sections:[],seats:[]},panToWorld:e=>{this.setFollowLive(!1),this.renderer?.panToWorld?.(e)},clearSectionFocus:()=>this.renderer?.clearSectionFocus?.(),focusSection:e=>{this.setFollowLive(!1),this.renderer?.focusSection(e),this.channels?.handleSectionFocus(e)},overview:()=>{this.setFollowLive(!1),this.zoomToFit()},getFloors:()=>this.renderer?.getFloors?.()??[],getActiveFloorId:()=>this.renderer?.getActiveFloorId?.()??"",isFloorOverview:()=>this.renderer?.isFloorOverview?.()??!1,getRenderer:()=>this.renderer}}syncMinimap(){let e=this.els.minimapMount,t=!!this.root?.classList.contains("compact");if(!e||!this.renderer||t){this.minimap?.dispose(),this.minimap=null;return}if(this.minimap){this.minimap.refreshMinimap();return}this.minimap=K({controller:this.mapCamera(),root:()=>this.root,cssVar:s=>this.cssVar(s.replace(/^--sl-/,"--slm-")),focusedSectionLabel:()=>{},tint:s=>this.renderer?.categoryDisplayColor?.(s)||void 0},e),this.minimap.refreshMinimap()}cssVar(e){return this.root?getComputedStyle(this.root).getPropertyValue(e).trim():""}destroy(){if(this.selectObserver?.disconnect(),this.closed=!0,this.minimap?.dispose(),this.minimap=null,this.monitorRefreshTimer&&clearTimeout(this.monitorRefreshTimer),this.monitorRefreshTimer=null,this.reconnectTimer&&clearTimeout(this.reconnectTimer),this.feedTimer&&clearInterval(this.feedTimer),this.toastTimer&&clearTimeout(this.toastTimer),this.liveEventTimer&&clearTimeout(this.liveEventTimer),this.kpiCleanupTimer&&clearTimeout(this.kpiCleanupTimer),this.followLiveTimer&&clearTimeout(this.followLiveTimer),this.followSeatTimer&&clearTimeout(this.followSeatTimer),this.unblockAllConfirmTimer&&clearTimeout(this.unblockAllConfirmTimer),this.paintHandle!==null&&typeof cancelAnimationFrame=="function"&&cancelAnimationFrame(this.paintHandle),this.paintHandle=null,this.channels?.destroy(),this.channels=null,this.channelsLoading=null,this.tokenRefreshTimer&&clearTimeout(this.tokenRefreshTimer),this.layoutObserver?.disconnect(),this.layoutObserver=null,this.colorSchemeStop?.(),this.colorSchemeStop=null,this.root?.removeEventListener("keydown",this.onKeyDown),this.els.rail?.removeEventListener("click",this.onRailClick),typeof document<"u"&&document.removeEventListener("fullscreenchange",this.onFullscreenChange),this.ws){try{this.ws.close()}catch{}this.ws=null}this.seatHistoryPanel?.destroy(),this.seatHistoryPanel=null,this.activityPanel?.destroy(),this.activityPanel=null,this.navigation?.destroy(),this.navigation=null,this.renderer?.destroy(),this.renderer=null,this.organizerAssetUrls.dispose(),this.root&&this.root.parentNode===this.host&&this.host.removeChild(this.root)}buildRenderer(){if(!this.doc)return;let e=this.isBulkSelectMode();this.renderer=new gt(this.mapHost,{manageMode:!0,organizerGlyph:{apply:ft,clear:vt,isPainted:yt},marqueeSelect:e&&!this.movingMap,marqueeShape:this.marqueeShape,rowLabelSelect:this.rowLabelSelectable(),maxSelection:this.selectionCap(),selectableStatuses:this.selectableStatuses(),currency:this.currency,onSelect:t=>this.handleSeatSelect(t),onDeselect:()=>this.syncSelection(),onSelectionLimit:t=>this.opts.onSelectionLimit?.(t),onMarquee:()=>this.syncSelection(),onGAClick:t=>{if(this.mode!=="select"||!this.opts.onAreaClick||!this.doc)return;let s=Re(this.doc).find(i=>i.id===t);s&&this.opts.onAreaClick({id:s.id,label:s.label,name:s.displayLabel?.trim()||s.label})},onSectionTap:t=>{if(this.mode==="filterSections"){let s=this.filterableSections().find(i=>i.id===t);s&&this.setFilteredSection(s.label);return}this.renderer?.focusSection(t),this.channels?.handleSectionFocus(t)},onViewChange:()=>{this.updateZoomHint(),this.paintMapChrome(),this.minimap?.drawMinimapRect(),this.channels?.handleViewChange()},onFocusedSectionChange:()=>{this.paintMapChrome(),this.minimap?.refreshMinimap()},hoverFacts:t=>this.hoverFactsFor(t),blockPaint:t=>be(t,{rule:this.availabilityRules[t.id],hiddenNow:this.effectiveHidden.has(t.id),closedNow:this.effectiveClosed.has(t.id),colourBy:this.getColourBy(),typeTint:this.sectionTypeTint(t.id)}),openAtSectionsWhenDense:!0}),this.renderer.setChart(this.themedDoc()),this.repaintAll(),this.applyHeatOverlay(),this.applyMapView(),this.updateZoomHint(),this.minimap?.dispose(),this.minimap=null,this.syncMinimap(),this.paintMapChrome()}hoverFactsFor(e){let t=[...this.labelToSeat.values()].find(d=>d.id===e);if(!t)return null;let s=this.status.get(t.label)??"free",o=[{caption:"Status",value:{free:"Free",held:"Held",booked:"Booked",blocked:"Blocked"}[s]}],a=this.channels?.channelNameForLabel(t.label)??null;a&&o.push({caption:"Channel",value:a});let l=this.sectionByObject.get(t.rowId)??v,r=this.doc?.categories.find(d=>d.key===t.categoryKey),c=s==="free"&&!this.effectiveHidden.has(l)&&!this.effectiveClosed.has(l)&&r?.notForSale!==!0;return o.push({caption:"For sale",value:c?"Yes":s==="free"?"No":"\u2014"}),o}rowLabelSelectable(){return this.isBulkSelectMode()||this.mode==="select"}marqueeShapeChipsHtml(){let e=(t,s)=>`<button type="button" class="slm-btn${this.marqueeShape===t?"":" ghost"}" data-ref="shape-${t}"
719
+ aria-pressed="${this.marqueeShape===t}" title="${t==="box"?"Drag a rectangle over seats":"Draw a loop around seats"}">${s}</button>`;return`${e("box","Drag box")}${e("lasso","Lasso")}`}wireMarqueeShapeChips(){this.els.rail.querySelectorAll('[data-ref^="shape-"]').forEach(e=>{e.addEventListener("click",()=>{let t=e.dataset.ref==="shape-lasso"?"lasso":"box";t!==this.marqueeShape&&(this.marqueeShape=t,this.updateRendererInteraction(),this.els.rail.querySelectorAll('[data-ref^="shape-"]').forEach(s=>{let i=s.dataset.ref===`shape-${t}`;s.classList.toggle("ghost",!i),s.setAttribute("aria-pressed",String(i))}))})})}isBulkSelectMode(){return this.mode==="block"||this.mode==="categories"||this.mode==="channels"&&this.channels?.usesMarqueeSelection()===!0}selectableStatuses(){return this.mode==="block"?["free","not_for_sale"]:this.mode==="select"||this.mode==="categories"||this.mode==="inspect"||this.isBulkSelectMode()||this.mode==="channels"&&this.channels?.canSelect()===!0?["free","held","booked","not_for_sale"]:[]}updateRendererInteraction(){let e=this.isBulkSelectMode();this.renderer?.setManageInteraction({manageMode:!0,organizerStatus:this.mode!=="channels",marqueeSelect:e&&!this.movingMap,marqueeShape:this.marqueeShape,rowLabelSelect:this.rowLabelSelectable(),maxSelection:this.selectionCap(),selectableStatuses:this.selectableStatuses()}),this.navigation?.update(e,this.mode==="view"),this.updateZoomHint()}handleSeatSelect(e){if(this.mode==="select"&&!this.canSelectObject(e)){this.renderer?.deselect([e.id]),this.syncSelection();return}if(this.mode==="inspect"){let t=this.getSelection().filter(s=>s.id!==e.id).map(s=>s.id);t.length&&this.renderer?.deselect(t)}this.syncSelection()}buildUnitUniverse(e){let t=new Map;for(let i of wt(e))i.type==="table"&&t.set(i.id,i.label);let s=new Map;for(let i of xt(e))if(this.labelToId.set(i.label,i.id),this.labelToSeat.set(i.label,i),this.allIds.push(i.id),t.has(i.rowId)){let o=s.get(i.rowId)??[];o.push(i.id),s.set(i.rowId,o)}for(let[i,o]of s){let a=t.get(i);this.labelToId.has(a)||this.tableChairIds.set(a,o)}for(let i of Re(e))for(let o of St(i))this.labelToId.has(o)||this.gaUnitLabelSet.add(o)}unitTotal(){return this.allIds.length+this.gaUnitLabelSet.size}paintIds(e){let t=this.labelToId.get(e);return t?[t]:this.tableChairIds.get(e)??[]}knownLabels(){return[...this.labelToId.keys(),...this.gaUnitLabelSet]}repaintAll(){let e=this.renderer;if(!e)return;this.allIds.length&&e.setStatus(this.allIds,"free");let t={free:[],held:[],booked:[],not_for_sale:[]};for(let[s,i]of this.status.entries())t[M(i)].push(...this.paintIds(s));["held","booked","not_for_sale"].forEach(s=>{t[s].length&&e.setStatus(t[s],s)})}async connect(){if(this.closed||this.sessionEnded)return;let e;try{if(e=(await this.withAuthRetry(()=>this.api.subscribeTicket(this.key))).protocols,!e.length)throw new Error("manage_subscribe_ticket_missing")}catch(s){this.setLive(!1),this.opts.onError?.(s),this.scheduleReconnect();return}if(this.closed)return;let t;try{t=new WebSocket(this.api.socketUrl(this.key),e)}catch(s){this.opts.onError?.(s),this.scheduleReconnect();return}this.ws=t,this.socketSnapshotSeen=!1,t.onopen=()=>{this.attempt=0,this.setLive(!0),this.resnapshot().then(()=>this.refreshControlRoom()).catch(s=>this.opts.onError?.(s)),this.refreshAvailability()},t.onmessage=s=>this.onMessage(s),t.onclose=()=>{this.ws===t&&(this.ws=null),this.setLive(!1),this.scheduleReconnect()},t.onerror=()=>{try{t.close()}catch{}}}scheduleReconnect(){if(this.closed||this.sessionEnded||this.reconnectTimer)return;let e=Math.min(1e3*2**Math.min(this.attempt++,5),15e3);this.reconnectTimer=setTimeout(()=>{this.reconnectTimer=null,this.connect()},e)}onMessage(e){let t;try{t=JSON.parse(typeof e.data=="string"?e.data:"")}catch{return}if(!t||typeof t!="object")return;this.lastMessageAt=Date.now();let s=t;if((Array.isArray(s.hidden)||Array.isArray(s.closed))&&this.updateEffectiveAvailability(s.hidden,s.closed),s.type==="presence"){typeof s.shoppingSessions=="number"&&typeof s.activeHolds=="number"&&(this.livePresence={at:Date.now(),value:{shoppingSessions:s.shoppingSessions,activeHolds:s.activeHolds}},this.controlRoomSnapshot&&(this.controlRoomSnapshot={...this.controlRoomSnapshot,presence:this.livePresence.value},this.opts.onControlRoom?.(this.controlRoomSnapshot)),this.lastSyncedAt=Date.now(),this.recomputeTallies(),this.paintMonitorInsights());return}if(s.type!=="hidden"){if(s.seats&&typeof s.seats=="object")this.applySocketSnapshot(s.seats,typeof s.default=="string"?s.default:void 0);else if(Array.isArray(s.changes)){let i=[],o=new Map;for(let l of s.changes){let r=["free","held","booked","blocked"].includes(l.status)?l.status:"free",c=this.status.get(l.label)??"free";if(c===r)continue;this.setStatusLabel(l.label,r,c);let d=this.paintIds(l.label);d.length&&(this.renderer?.setStatus(d,M(r)),i.push(...d));let h=this.verbFor(c,r),p=`${h}:${r}`,u=o.get(p)??{labels:[],verb:h,status:r};u.labels.push(l.label),o.set(p,u)}for(let l of o.values()){let r=this.pushActivity(l.labels,l.verb,l.status);r&&this.paintSpatialActivity(r)}o.size&&this.scheduleMonitorRefresh(),i.length&&(this.lastSyncedAt=Date.now(),this.afterPaint());let a=typeof s.bookedValue?.gross=="number"?s.bookedValue.gross:s.revenue?.gross;typeof a=="number"&&Number.isFinite(a)&&this.applyLiveGross(a),this.recomputeTallies()}}}applyLiveGross(e){if(this.liveGross={at:Date.now(),value:e},this.authoritativeGrossRevenue=e,this.revenueStatus="current",this.controlRoomSnapshot){let s={...this.controlRoomSnapshot.bookedValue??this.controlRoomSnapshot.revenue,gross:e};this.controlRoomSnapshot={...this.controlRoomSnapshot,bookedValue:s,revenue:s},this.opts.onControlRoom?.(this.controlRoomSnapshot)}}setStatusLabel(e,t,s=this.status.get(e)??"free"){this.status.set(e,t),s!==t&&(s!=="free"&&(this.counts[s]-=1),t!=="free"&&(this.counts[t]+=1))}applySocketSnapshot(e,t){let s=this.socketSnapshotSeen?this.status:null;if(this.applySnapshot(e,t),this.socketSnapshotSeen=!0,!s)return;let i=new Map;for(let o of new Set([...s.keys(),...this.status.keys()])){let a=s.get(o)??"free",l=this.status.get(o)??"free";if(a===l)continue;let r=this.verbFor(a,l),c=`${r}:${l}`,d=i.get(c)??{labels:[],verb:r,status:l};d.labels.push(o),i.set(c,d)}for(let o of i.values()){let a=this.pushActivity(o.labels,o.verb,o.status);a&&this.paintSpatialActivity(a)}i.size&&this.scheduleMonitorRefresh()}scheduleMonitorRefresh(){this.monitorRefreshTimer||(this.monitorRefreshTimer=setTimeout(()=>{this.monitorRefreshTimer=null,this.closed||this.refreshControlRoom().catch(e=>this.opts.onError?.(e))},150))}async resnapshot(){try{let e=await this.api.objects(this.key);this.applySnapshot(e.seats),this.updateEffectiveAvailability(e.hidden,e.closed),this.lastMessageAt=Date.now()}catch{}}applySnapshot(e,t){let s=o=>["free","held","booked","blocked"].includes(o)?o:"free",i=new Map;if(t!==void 0){let o=s(t);for(let a of this.knownLabels())i.set(a,o)}for(let[o,a]of Object.entries(e))i.set(o,s(a));this.status=i,this.modelVersion+=1,this.recountAll(),this.lastSyncedAt=Date.now(),this.repaintAll(),this.afterPaint(),this.recomputeTallies()}recountAll(){let e={held:0,booked:0,blocked:0};for(let t of this.status.values())t!=="free"&&(e[t]+=1);this.counts=e}setSeatsLocal(e,t){let s=[];for(let i of e)this.setStatusLabel(i,t),s.push(...this.paintIds(i));s.length&&this.renderer?.setStatus(s,M(t)),this.afterPaint(),this.recomputeTallies()}afterPaint(){this.keepLive&&typeof document<"u"&&document.hidden&&this.renderer?.forceDraw()}activityColor(e){return e==="held"?x.held:e==="booked"?x.booked:e==="blocked"?x.blocked:x.free}sectionsForLabels(e){let t=new Set;for(let i of e){let o=this.labelToSeat.get(i);if(!o)continue;let a=this.sectionByObject.get(o.rowId);a&&a!==v&&t.add(a)}let s=[...t];return{ids:s,labels:s.map(i=>this.sectionLabelById.get(i)??i)}}pulseSeatLabels(e,t){let s=this.activityColor(t);for(let i of e.slice(0,Ae)){let o=this.labelToId.get(i);o&&this.renderer?.flashSeat(o,s)}}paintSpatialActivity(e){let t=e.sectionIds??this.sectionsForLabels(e.labels).ids,s=this.renderer?.getFocusedSection()??null;if(this.followLive&&t.length===1&&(e.status==="held"||e.status==="booked")){let o=this.root?.querySelector('[data-ref="followstatus"]');o&&(o.textContent=`Following ${e.labels.length===1?e.labels[0]:`${e.labels.length} seats`} \xB7 ${e.status}`),this.followLiveTimer&&clearTimeout(this.followLiveTimer),this.followSeatTimer&&clearTimeout(this.followSeatTimer),this.followLiveTimer=setTimeout(()=>{this.followLiveTimer=null,this.focusActivitySeats(e.labels,t[0]),this.followSeatTimer=setTimeout(()=>{this.followSeatTimer=null,this.pulseSeatLabels(e.labels,e.status)},520)},220);return}if(!s&&t.length){let o=this.activityColor(e.status);for(let a of t.slice(0,$e))this.renderer?.flashSection(a,o);return}(!t.length||s&&t.includes(s))&&this.pulseSeatLabels(e.labels,e.status)}locateSection(e){this.renderer?.focusSection(e)}focusActivitySeats(e,t){this.renderer?.focusSection(t);let s=e.slice(0,Ae).map(r=>this.labelToSeat.get(r)).filter(r=>!!r);if(!s.length)return;let i=s.map(r=>r.x),o=s.map(r=>r.y),a=Math.min(...i),l=Math.min(...o);this.renderer?.focusRegion({x:a-150,y:l-100,width:Math.max(...i)-a+300,height:Math.max(...o)-l+200})}locateActivity(e){let t=this.feed.find(i=>i.id===e);if(!t)return;let s=t.sectionIds??this.sectionsForLabels(t.labels).ids;if(this.followSeatTimer&&clearTimeout(this.followSeatTimer),s.length===1){this.focusActivitySeats(t.labels,s[0]),this.followSeatTimer=setTimeout(()=>{this.followSeatTimer=null,this.pulseSeatLabels(t.labels,t.status)},520);return}this.zoomToFit(),this.followSeatTimer=setTimeout(()=>{if(this.followSeatTimer=null,s.length){let i=this.activityColor(t.status);for(let o of s.slice(0,$e))this.renderer?.flashSection(o,i)}else this.pulseSeatLabels(t.labels,t.status)},280)}showLiveEvent(e){let t=this.els.liveevent;if(!t)return;let s=e.sectionLabels??[],i=s.length===1?s[0]:s.length>1?`${s.length} sections`:e.label,o=e.count===1?"seat":"seats";t.innerHTML=`<span class="slm-liveeventdot" style="background:${this.activityColor(e.status)}"></span>
720
+ <span class="slm-liveeventcopy">${m(i)} \xB7 ${e.count.toLocaleString()} ${o} ${m(e.verb)}</span>
721
+ <span class="slm-liveeventhint">Live</span>`,t.classList.add("on"),this.liveEventTimer&&clearTimeout(this.liveEventTimer),this.liveEventTimer=setTimeout(()=>{this.liveEventTimer=null,t.classList.remove("on"),t.innerHTML=""},2800)}applyReportRevenue(e){this.authoritativeGrossRevenue=e.report.byCategory.reduce((t,s)=>{let i=Number.isFinite(s.bookedValue)?s.bookedValue:s.bookedRevenue;return t+(Number.isFinite(i)?i:0)},0),this.revenueStatus="current",this.recomputeTallies()}async refreshControlRoom(){let e=++this.revenueRequest,t=Date.now();try{let s=await this.api.controlRoom(this.key,this.trendWindowMinutes),i=s.bookedValue??s.revenue??{gross:0,bySection:[]},o=(i.bySection??[]).map(r=>{let c=Number.isFinite(r.bookedValue)?r.bookedValue:r.bookedRevenue;return{...r,bookedValue:c??0,bookedRevenue:c??0}}),a={...i,bySection:o},l={...s,bookedValue:a,revenue:a};if(e===this.revenueRequest){if(this.livePresence&&this.livePresence.at>=t?l={...l,presence:this.livePresence.value}:this.livePresence=null,this.liveGross&&this.liveGross.at>=t){let d={...l.bookedValue,gross:this.liveGross.value};l={...l,bookedValue:d,revenue:d}}else this.liveGross=null;this.controlRoomSnapshot=l,l.activity&&this.seedFeed(l.activity),this.rebaseServerTotals(l),this.lastSyncedAt=Date.now(),this.authoritativeGrossRevenue=l.bookedValue.gross,this.authoritativeCurrency=l.currency,this.currency=l.currency,this.revenueStatus="current",this.recomputeTallies(),this.applyHeatOverlay(),this.paintMonitorInsights(),this.seatHistoryPanel?.refresh();let r=this.getSelection().slice(-1)[0],c=this.els.rail?.querySelector("[data-seat-status]");r&&c&&(c.textContent=this.status.get(r.label)??"free"),this.opts.onControlRoom?.(l)}return l}catch(s){throw e===this.revenueRequest&&(this.revenueStatus="stale",this.recomputeTallies()),s}}rebaseServerTotals(e){let t=e.totals;if(!t||["free","held","booked","blocked"].some(s=>!Number.isFinite(t[s]))){this.serverBaseline=null;return}this.serverBaseline={model:this.modelVersion,server:{free:t.free,held:t.held,booked:t.booked,blocked:t.blocked},client:this.clientTallies()}}clientTallies(){let{held:e,booked:t,blocked:s}=this.counts;return{held:e,booked:t,blocked:s,free:Math.max(0,this.unitTotal()-e-t-s)}}buildTallies(){let e=this.clientTallies(),t=this.serverBaseline?.model===this.modelVersion?this.serverBaseline:null,s=l=>t?Math.max(0,t.server[l]+(e[l]-t.client[l])):e[l],i=this.controlRoomSnapshot?.event?.seatTotal,o={free:s("free"),held:s("held"),booked:s("booked"),blocked:s("blocked"),total:Number.isFinite(i)?i:this.unitTotal(),capacityPct:0,sellThroughPct:0,bookedValue:this.authoritativeGrossRevenue,grossRevenue:this.authoritativeGrossRevenue,bookedValueStatus:this.revenueStatus,revenueStatus:this.revenueStatus,currency:this.currency};o.capacityPct=o.total?Math.round(o.booked/o.total*100):0;let a=o.total-o.blocked;return o.sellThroughPct=a>0?Math.round(o.booked/a*100):0,o}recomputeTallies(){if(!this.closed){if(typeof requestAnimationFrame!="function"){this.flushTallies();return}this.paintHandle===null&&(this.paintHandle=requestAnimationFrame(()=>{this.paintHandle=null,this.flushTallies()}))}}flushTallies(){if(this.closed)return;let e=this.buildTallies();this.paintKpis(e),this.minimap?.refreshMinimap(),this.mode==="view"?(this.paintLegend(e),this.paintMonitorInsights()):this.mode==="inspect"?this.renderInspectRail(this.getSelection()):this.mode==="block"?this.paintSelBar(this.getSelection()):this.mode==="channels"&&this.channels?.handleSelectionChange(),this.opts.onTallies?.(e)}verbFor(e,t){return t==="held"?"held":t==="booked"?"booked":t==="blocked"?"blocked":t==="free"?e==="blocked"?"unblocked":e==="booked"?"cancelled":"available":t}pushActivity(e,t,s,i=Date.now()){let o=e[0];if(!o)return null;let a=this.sectionsForLabels(e),l={id:`${o}:${i}:${Math.random().toString(36).slice(2,6)}`,at:i,label:o,labels:[...e],count:e.length,verb:t,status:s,sectionIds:a.ids,sectionLabels:a.labels};return this.controlRoomSnapshot?.activity||this.feed.unshift(l),this.feed.length>H&&(this.feed.length=H),this.mode==="view"&&this.paintFeed(),this.showLiveEvent(l),this.opts.onActivity?.(l),l}seedFeed(e){this.controlRoomSnapshot?.activity&&(this.feed=this.feed.filter(i=>i.id.startsWith("log:")));let t={hold:"held",book:"booked",release:"released",expire:"expired",block:"blocked",unblock:"unblocked",unbook:"cancelled"},s={hold:"held",book:"booked",release:"free",expire:"free",block:"blocked",unblock:"free",unbook:"free"};for(let i of e){if(this.feed.some(r=>r.id===`log:${i.id}`))continue;let o=i.labels[0];if(!o)continue;let a=this.sectionsForLabels(i.labels),l={id:`log:${i.id}`,at:i.at,label:o,labels:[...i.labels],count:i.labels.length,verb:t[i.action]??i.action,status:s[i.action]??"free",sectionIds:a.ids,sectionLabels:a.labels};this.feed.push(l),this.opts.onActivity?.(l)}this.feed.sort((i,o)=>o.at-i.at),this.feed.length>H&&(this.feed.length=H),this.mode==="view"&&this.paintFeed()}startFeedClock(){this.feedTimer=setInterval(()=>{this.mode==="view"&&(this.paintFeed(),this.paintMonitorInsights())},1e4)}selectionCap(){return this.mode!=="select"?1e6:this.opts.numberOfPlacesToSelect??this.opts.maxSelectedObjects??1e6}canSelectObject(e){let t=this.status.get(e.label)??"free",s=this.opts.unavailableObjectsSelectable??!0,i=t==="free"||s||this.selectableObjectLabels.has(e.label);if(!this.opts.isObjectSelectable)return i;try{return this.opts.isObjectSelectable(e,i)===!0}catch(o){return this.opts.onError?.(o),!1}}applyInitialSelection(){this.initialSelectionApplied||this.mode!=="select"||!this.renderer||(this.initialSelectionApplied=!0,this.selectByLabels(this.opts.selectedObjects??[]))}trimSelectionToCap(){if(this.mode!=="select")return;let e=this.getSelection(),t=this.selectionCap();e.length<=t||this.renderer?.deselect(e.slice(t).map(s=>s.id))}reconcileSelectPolicy(){if(this.mode!=="select")return;let e=this.getSelection().filter(t=>!this.canSelectObject(t));e.length&&this.renderer?.deselect(e.map(t=>t.id)),this.trimSelectionToCap(),this.syncSelection()}selectionLabels(){return this.getSelection().map(e=>e.label)}syncSelection(){let e=this.getSelection();this.mode==="block"?this.paintSelBar(e):this.mode==="inspect"?this.renderInspectRail(e):this.mode==="select"?this.paintSelectSelection(e):this.mode==="categories"?this.paintCategorySelection(e):this.mode==="channels"&&this.channels?.handleSelectionChange();let t=new Map(e.map(s=>[s.label,s]));if(this.mode==="select"){for(let[i,o]of t)this.lastSelectionLabels.has(i)||this.opts.onObjectSelected?.(o);for(let i of this.lastSelectionLabels)if(!t.has(i)){let o=this.labelToSeat.get(i);o&&this.opts.onObjectDeselected?.(o)}let s=this.getSelectionValidity();s&&(this.opts.onSelectionValidityChange?.(s),this.selectionWasValid!==s.isValid&&(s.isValid?this.opts.onSelectionValid?.(s):this.opts.onSelectionInvalid?.(s)),this.selectionWasValid=s.isValid)}this.lastSelectionLabels=new Set(t.keys()),this.navigation?.selectionChanged(e.length),this.opts.onSelectionChange?.(e)}buildChrome(){let e=document.createElement("div"),t=this.opts.chrome==="minimal";e.className=t?"slm slm-minimal":"slm",e.tabIndex=0,e.setAttribute("role","region"),e.setAttribute("aria-label",t?"Seat map":"SeatLayer live control room"),e.innerHTML=`
474
722
  <div class="slm-bar">
475
723
  <div class="slm-modes" data-ref="modes" role="tablist" aria-label="Control room tools">
476
- ${oe.map(i=>`<div class="slm-modegroup" data-group="${i.key}" role="presentation" hidden>
477
- <span class="slm-modegroup-label" aria-hidden="true">${p(i.label)}</span>
478
- ${i.tools.map(a=>`<button class="slm-mode" role="tab" data-mode="${a.mode}"
479
- title="${p(a.title)} (${a.shortcut})" aria-keyshortcuts="${a.shortcut}" hidden>${p(a.label)}</button>`).join("")}
724
+ ${He.map(o=>`<div class="slm-modegroup" data-group="${o.key}" role="presentation" hidden>
725
+ <span class="slm-modegroup-label" aria-hidden="true">${m(o.label)}</span>
726
+ ${o.tools.map(a=>`<button class="slm-mode" role="tab" data-mode="${a.mode}"
727
+ title="${m(a.title)} (${a.shortcut})" aria-keyshortcuts="${a.shortcut}" hidden>${m(a.label)}</button>`).join("")}
480
728
  </div>`).join("")}
481
729
  </div>
482
730
  <select class="slm-tools" data-ref="tools" aria-label="Control room tools"></select>
@@ -484,10 +732,10 @@ import{c as H,d as B,f as j}from"./chunk-RZ2VKZ44.js";import{A as Re,B as Ae,D a
484
732
  <div class="slm-bar-actions">
485
733
  <button class="slm-barbtn follow" data-ref="follow" aria-label="Follow live" aria-pressed="false"
486
734
  title="Stay on the current map view unless enabled">Auto-follow</button>
487
- <button class="slm-barbtn heat" data-ref="heat" aria-pressed="false"
488
- aria-label="Booking momentum overlay off"
489
- title="Highlight sections booking fastest in the selected time window">Heatmap</button>
490
- <button class="slm-barbtn" data-ref="fullscreen" title="Full screen (F)" aria-keyshortcuts="F">Full screen</button>
735
+ <div data-ref="findbar" class="slm-findbar">${D({compact:!0})}</div>
736
+ ${Me()}
737
+ <button type="button" class="slm-barbtn slm-fullscreen" data-ref="fullscreen" title="Full screen (F)" aria-label="Full screen"
738
+ aria-keyshortcuts="F"><span class="slm-fullscreen-icon" aria-hidden="true">${j.enter}</span><span class="slm-fullscreen-label">Full screen</span></button>
491
739
  </div>
492
740
  <div class="slm-kpis" data-ref="kpis"></div>
493
741
  </div>
@@ -500,16 +748,17 @@ import{c as H,d as B,f as j}from"./chunk-RZ2VKZ44.js";import{A as Re,B as Ae,D a
500
748
  </div>
501
749
  <div class="slm-heat-status" data-ref="heatstatus" role="status" hidden></div>
502
750
  <div class="slm-follow-status" data-ref="followstatus" role="status" hidden></div>
503
- <div class="slm-hud"><button class="slm-hud-chip" data-ref="zfit">Zoom to fit</button></div>
751
+ ${pe()}
752
+ ${ge()}
504
753
  </div>
505
754
  <aside class="slm-rail"><div class="slm-railscroll" data-ref="rail"></div></aside>
506
755
  </div>
507
756
  <div class="slm-toast" data-ref="toast"></div>
508
- `,this.host.appendChild(e),this.root=e,this.selectObserver=new MutationObserver(()=>{let i=e.querySelector(".slm-rail");i&&P(i)});let t=e.querySelector(".slm-rail");t&&this.selectObserver.observe(t,{childList:!0,subtree:!0}),this.applyThemeVars(),this.watchThemeMode(),this.updateContainerLayout(),typeof ResizeObserver<"u"&&(this.layoutObserver=new ResizeObserver(()=>this.updateContainerLayout()),this.layoutObserver.observe(e));let s=i=>e.querySelector(`[data-ref="${i}"]`);this.mapHost=s("maphost"),this.els={modes:s("modes"),tools:s("tools"),livetext:s("livetext"),kpis:s("kpis"),follow:s("follow"),heat:s("heat"),fullscreen:s("fullscreen"),lane:s("lane"),zoomhint:s("zoomhint"),liveevent:s("liveevent"),rail:s("rail"),toast:s("toast"),zfit:s("zfit")},this.els.modes.querySelectorAll("[data-mode]").forEach(i=>i.addEventListener("click",()=>this.setMode(i.dataset.mode))),this.els.tools.addEventListener("change",()=>this.setMode(this.els.tools.value)),this.els.zfit.addEventListener("click",()=>{this.setFollowLive(!1),this.zoomToFit()}),this.els.follow.addEventListener("click",()=>this.setFollowLive(!this.followLive)),this.els.heat.addEventListener("click",()=>this.setHeatOverlay(!this.heatEnabled)),this.els.fullscreen.addEventListener("click",()=>this.toggleFullscreen()),e.addEventListener("keydown",this.onKeyDown),this.els.rail.addEventListener("click",this.onRailClick),document.addEventListener("fullscreenchange",this.onFullscreenChange),this.paintModeTabs(),this.paintFollowLiveButton(),this.paintHeatButton(),this.paintFullscreenButton(),this.navigation=new T({root:e,map:this.mapHost,setMoving:i=>{this.movingMap=i,this.updateRendererInteraction()},pauseFollow:()=>{this.followLive&&this.setFollowLive(!1)},clearSelection:()=>this.clearSelection(),zoomIn:()=>this.renderer?.zoomIn(),zoomOut:()=>this.renderer?.zoomOut(),targets:i=>this.navigationTargets(i)}),this.navigation.update(this.isBulkSelectMode(),this.mode==="view")}navigationTargets(e){let t=e.toLocaleLowerCase(),s=[];for(let a of this.sectionOptions)if(a.label.toLocaleLowerCase().includes(t)&&s.push({label:a.label,detail:"Section",locate:()=>this.locateSection(a.id)}),s.length>=20)return s;let i=new Map;for(let a of this.labelToSeat.values()){let o=i.get(a.rowId)??{minX:a.x,minY:a.y,maxX:a.x,maxY:a.y};o.minX=Math.min(o.minX,a.x),o.minY=Math.min(o.minY,a.y),o.maxX=Math.max(o.maxX,a.x),o.maxY=Math.max(o.maxY,a.y),i.set(a.rowId,o)}for(let a of this.doc?se(this.doc).flatMap(o=>o.objects):[]){if(a.type!=="row"||!(a.displayLabel??a.label).toLocaleLowerCase().includes(t))continue;let o=i.get(a.id);if(!o)continue;let{minX:l,minY:r,maxX:c,maxY:n}=o;if(s.push({label:a.displayLabel??a.label,detail:"Row",locate:()=>{let d=this.sectionByObject.get(a.id);d&&this.renderer?.focusSection(d),this.renderer?.focusRegion({x:l-30,y:r-30,width:c-l+60,height:n-r+60},{minScale:1.2,animate:!1})}}),s.length>=20)return s}for(let a of this.labelToSeat.values())if(a.label.toLocaleLowerCase().includes(t)&&(s.push({label:a.label,detail:"Seat",locate:()=>{let o=this.sectionByObject.get(a.rowId);o&&this.renderer?.focusSection(o),this.renderer?.focusRegion({x:a.x-180,y:a.y-120,width:360,height:240},{animate:!1,minScale:1.5}),this.renderer?.flashSeat(a.id,this.activityColor(this.status.get(a.label)??"free"))}}),s.length>=20))break;return s}updateContainerLayout(){let e=this.root?.getBoundingClientRect().width||this.host.clientWidth;this.root?.classList.toggle("compact",e>0&&e<800),this.channels?.handleLayoutChange()}filterableSections(){return this.sectionsBase?[...this.sectionsBase.sections,...this.sectionsBase.ungrouped?[this.sectionsBase.ungrouped]:[]]:[]}applyFilteredSectionCanvas(e=this.filterableSections().filter(t=>t.label===this.filteredSectionLabel)){if(!this.renderer||this.mode!=="filterSections"||!e.length)return;let t=new Set(e.map(n=>n.id)),s=this.filterableSections().filter(n=>!t.has(n.id)).map(n=>n.id);this.renderer.clearSectionFocus(),this.renderer.setClosedSections(null),this.renderer.setDimmedSections(s);let i=e.flatMap(n=>n.seatLabels).map(n=>this.labelToSeat.get(n)).filter(n=>!!n&&Number.isFinite(n.x)&&Number.isFinite(n.y));if(!i.length){this.renderer.focusRegion(e[0].id);return}let a=Math.min(...i.map(n=>n.x)),o=Math.min(...i.map(n=>n.y)),l=Math.max(...i.map(n=>n.x)),r=Math.max(...i.map(n=>n.y)),c=Math.max(40,Math.max(l-a,r-o)*.08);this.renderer.focusRegion({x:a-c,y:o-c,width:Math.max(1,l-a)+c*2,height:Math.max(1,r-o)+c*2})}buildSectionOptions(){if(this.doc)try{let e=Ue(this.doc);this.sectionsBase=e,this.sectionOptions=[],this.sectionByObject=new Map(e.objectToSection),this.sectionLabelById.clear();for(let t of e.sections)this.sectionOptions.push({id:t.id,label:t.label}),this.sectionLabelById.set(t.id,t.label);e.ungrouped&&(this.sectionOptions.push({id:x,label:e.ungrouped.label}),this.sectionLabelById.set(x,e.ungrouped.label))}catch{}}toolAvailable(e){return e==="view"?!0:e==="channels"&&!this.channelCaps.view||e==="categories"&&!this.categoryCanManage||e==="tables"&&(!this.tableCanManage||!this.tables().length)?!1:!this.opts.tools||this.opts.tools.includes(e)}settleMode(){this.toolAvailable(this.mode)?this.paintModeTabs():this.setMode("view")}tables(){return(this.doc?se(this.doc):[]).flatMap(e=>e.objects).filter(e=>e.type==="table")}paintModeTabs(){let e=[];this.els.modes?.querySelectorAll(".slm-modegroup").forEach(s=>{let i=[];s.querySelectorAll("[data-mode]").forEach(a=>{let o=a.dataset.mode,l=this.toolAvailable(o);if(a.hidden=!l,!l)return;i.push({mode:o,label:a.textContent??o});let r=o===this.mode;a.classList.toggle("on",r),a.setAttribute("aria-selected",String(r)),a.tabIndex=r?0:-1}),s.hidden=i.length===0,i.length&&e.push({label:s.querySelector(".slm-modegroup-label")?.textContent??"",tools:i})});let t=this.els.tools;t&&(t.innerHTML=e.map(s=>`<optgroup label="${p(s.label)}">${s.tools.map(i=>`<option value="${i.mode}"${i.mode===this.mode?" selected":""}>${p(i.label)}</option>`).join("")}</optgroup>`).join(""),t.value=this.mode),this.root?.classList.toggle("block-mode",this.mode==="block")}railHeader(e,t,s){let i=t==="read"?"Read-only":t==="event"?"This event only":"Your app";return`<div class="slm-railhead"><p class="slm-eyebrow">${p(e)}</p><span class="slm-scope ${t}">${i}</span></div>
509
- <p class="slm-hint">${s}</p>`}paintFollowLiveButton(){let e=this.els.follow;if(!e)return;e.classList.toggle("on",this.followLive),e.setAttribute("aria-pressed",String(this.followLive)),e.textContent="Auto-follow";let t=this.root?.querySelector('[data-ref="followstatus"]');t&&(t.hidden=!this.followLive,t.textContent="Waiting for new holds or bookings"),e.setAttribute("title",this.followLive?"Following new holds and bookings. Turn off to keep the current view.":"Stay on the current map view. Enable to follow new holds and bookings.")}paintHeatButton(){let e=this.els.heat;e&&(e.classList.toggle("on",this.heatEnabled),e.setAttribute("aria-pressed",String(this.heatEnabled)),e.setAttribute("aria-label",`Booking momentum overlay ${this.heatEnabled?"on":"off"}`),e.setAttribute("title",`${this.heatEnabled?"Hide":"Highlight"} sections booking fastest in the selected time window`),e.textContent="Heatmap",this.paintMomentumHelp())}paintMomentumHelp(){let e=this.root?.querySelector('[data-ref="heatstatus"]');if(e){e.hidden=!this.heatEnabled;let a=this.controlRoomSnapshot?.velocity.bySection.some(o=>o.netBooked>0);e.textContent=this.controlRoomSnapshot?a?`Booking heatmap \xB7 last ${this.trendWindowMinutes}m \xB7 warmer = higher net booking rate`:`No positive net bookings in the last ${this.trendWindowMinutes}m`:"Loading booking heatmap\u2026"}let t=this.els.rail?.querySelector('[data-ref="momentumhelp"]');if(!t)return;t.hidden=!this.heatEnabled;let s=t.querySelector('[data-ref="momentumcopy"]');if(!s)return;let i=this.controlRoomSnapshot?.velocity.bySection.some(a=>a.netBooked>0);s.textContent=i?"Warmer sections have more completed bookings, adjusted for section size. Holds and viewers are not counted.":`No completed bookings in the last ${this.trendWindowMinutes} minutes.`}paintFullscreenButton(){this.els.fullscreen&&(this.els.fullscreen.textContent=this.isFullscreen()?"Exit full screen":"Full screen")}paintTrendWindow(){this.els.rail?.querySelectorAll("[data-window]").forEach(e=>{let t=Number(e.dataset.window);e.classList.toggle("on",t===this.trendWindowMinutes)})}setLive(e){this.root?.classList.toggle("live",e),this.els.livetext&&(this.els.livetext.textContent=e?"LIVE":"RECONNECTING"),this.paintMonitorInsights();let t=e?"live":"reconnecting";if(t!==this.connectionStatus){this.connectionStatus=t;try{this.opts.onConnectionChange?.(this.getConnection())}catch(s){this.opts.onError?.(s)}}}updateZoomHint(){let e=this.els.zoomhint;if(!e)return;let t=this.isBulkSelectMode()&&!this.movingMap&&this.renderer?.getRung?.()!=="seats";e.classList.toggle("on",!!t)}formatKpiDelta(e,t,s){let i=t>0?"+":"\u2212",a=Math.abs(t);return e==="booked-value"?`${i}${R(a,s)}`:e==="booked-pct"?`${i}${a.toLocaleString()}pt`:`${i}${a.toLocaleString()}`}paintKpis(e){if(!this.els.kpis)return;let t=e.bookedValueStatus==="current"?R(e.bookedValue,e.currency):"\u2014",s=this.presenceCounts(),i=[{key:"booked-inventory",raw:e.booked,n:e.booked.toLocaleString(),l:"Booked inventory",dot:y.booked,title:"Inventory units booked"},{key:"held-seats",raw:e.held,n:e.held.toLocaleString(),l:"Held inventory",dot:y.held,title:"Inventory currently held"},{key:"free-seats",raw:e.free,n:e.free.toLocaleString(),l:"Available",dot:y.free,title:"Inventory available to book"},{key:"blocked",raw:e.blocked,n:e.blocked.toLocaleString(),l:"Blocked",dot:y.blocked,title:"Inventory withheld from booking"},{key:"viewing-map",raw:s?.shoppingSessions??null,n:s?s.shoppingSessions.toLocaleString():"\u2014",l:"Viewing map",title:"Active map sessions right now"},{key:"active-holds",raw:s?.activeHolds??null,n:s?s.activeHolds.toLocaleString():"\u2014",l:"Active holds",title:"Sessions currently holding inventory"},{key:"booked-pct",raw:e.capacityPct,n:`${e.capacityPct}%`,l:"Booked",title:"Booked inventory as a share of the whole event"},{key:"booked-value",raw:e.bookedValueStatus==="current"?e.bookedValue:null,n:t,l:"Booked value",title:"Configured value attached to booked inventory"}],a=!1;this.els.kpis.innerHTML=i.map(o=>{let l=this.lastKpiValues.get(o.key),r=o.raw!=null&&l!=null&&o.raw!==l,c=r?o.raw-l:0;r&&(a=!0,this.activeKpiDeltas.set(o.key,{text:this.formatKpiDelta(o.key,c,e.currency),down:c<0})),o.raw!=null&&this.lastKpiValues.set(o.key,o.raw);let n=this.activeKpiDeltas.get(o.key);return`<div class="slm-kpi${n?" changed":""}" data-kpi="${o.key}" title="${p(o.title)}">
510
- <b>${o.dot?`<span class="dot" style="background:${o.dot}"></span>`:""}${o.n}</b><span>${o.l}</span>
511
- ${n?`<span class="slm-kpidelta${n.down?" down":""}">${n.text}</span>`:""}
512
- </div>`}).join(""),a&&(this.kpiCleanupTimer&&clearTimeout(this.kpiCleanupTimer),this.kpiCleanupTimer=setTimeout(()=>{this.kpiCleanupTimer=null,this.activeKpiDeltas.clear(),this.els.kpis?.querySelectorAll(".slm-kpidelta").forEach(o=>o.remove()),this.els.kpis?.querySelectorAll(".slm-kpi.changed").forEach(o=>o.classList.remove("changed"))},1500))}paintRail(){this.root?.classList.toggle("monitor-view",this.mode==="view"||this.mode==="inspect"),this.seatHistoryPanel?.destroy(),this.seatHistoryPanel=null,this.activityPanel?.destroy(),this.activityPanel=null,this.mode==="view"?this.renderViewRail():this.mode==="inspect"?this.renderInspectRail(this.getSelection()):this.mode==="select"?this.renderSelectRail():this.mode==="filterSections"?this.renderFilterSectionsRail():this.mode==="sections"?this.renderSectionsRail():this.mode==="categories"?this.renderCategoriesRail():this.mode==="tables"?this.renderTablesRail():this.mode==="channels"?this.channels?this.channels.paintRail():this.channelsLoading?this.els.rail.innerHTML='<div class="slm-empty" role="status">Loading sales channels\u2026</div>':this.els.rail.innerHTML='<div class="slm-empty" role="alert">Sales channels could not be loaded. Switch away and back to try again.</div>':this.renderBlockRail(),this.updateZoomHint()}renderViewRail(){this.els.rail.innerHTML=`
757
+ `,this.host.appendChild(e),this.root=e,this.selectObserver=new MutationObserver(()=>{let o=e.querySelector(".slm-rail");o&&(L(o),U(o))});let s=e.querySelector(".slm-rail");s&&this.selectObserver.observe(s,{childList:!0,subtree:!0}),this.applyThemeVars(),this.watchThemeMode(),this.updateContainerLayout(),typeof ResizeObserver<"u"&&(this.layoutObserver=new ResizeObserver(()=>this.updateContainerLayout()),this.layoutObserver.observe(e));let i=o=>e.querySelector(`[data-ref="${o}"]`);this.mapHost=i("maphost"),this.els={modes:i("modes"),tools:i("tools"),livetext:i("livetext"),kpis:i("kpis"),follow:i("follow"),view:i("view"),findbar:i("findbar"),fullscreen:i("fullscreen"),lane:i("lane"),zoomhint:i("zoomhint"),liveevent:i("liveevent"),rail:i("rail"),toast:i("toast"),mapchrome:i("mapchrome"),crumb:i("crumb"),zin:i("zin"),zout:i("zout"),zfit:i("zfit"),minimapMount:i("minimap"),blocklegend:i("blocklegend")},this.els.modes.querySelectorAll("[data-mode]").forEach(o=>o.addEventListener("click",()=>this.setMode(o.dataset.mode))),this.els.tools.addEventListener("change",()=>this.setMode(this.els.tools.value)),this.els.zfit.addEventListener("click",()=>{this.setFollowLive(!1),this.zoomToFit()}),this.els.zin.addEventListener("click",()=>{this.setFollowLive(!1),this.renderer?.zoomIn()}),this.els.zout.addEventListener("click",()=>{this.setFollowLive(!1),this.zoomOutStep()}),this.els.follow.addEventListener("click",()=>this.setFollowLive(!this.followLive)),this.els.blocklegend?.addEventListener("click",o=>{let a=o.target?.closest("[data-colour-by]");a?.dataset.colourBy&&this.setColourBy(a.dataset.colourBy)}),this.els.view.addEventListener("click",o=>{let a=o.target?.closest("[data-view]");a?.dataset.view&&this.toggleMapView(a.dataset.view)}),e.addEventListener("pointerdown",o=>{let a=this.els.view;a.open&&!a.contains(o.target)&&(a.open=!1)}),this.mapView=we(),this.opts.colourBy&&(this.mapView={...this.mapView,categoryColours:this.opts.colourBy==="type"}),this.heatEnabled=this.mapView.momentum,this.applyMapView(),this.wireBarFind(),this.els.fullscreen.addEventListener("click",()=>this.toggleFullscreen()),e.addEventListener("keydown",this.onKeyDown),this.els.rail.addEventListener("click",this.onRailClick),document.addEventListener("fullscreenchange",this.onFullscreenChange),this.paintModeTabs(),this.paintFollowLiveButton(),this.paintHeatButton(),this.paintMapViewMenu(),this.paintFullscreenButton(),this.navigation=new R({root:e,map:this.mapHost,setMoving:o=>{this.movingMap=o,this.updateRendererInteraction()},pauseFollow:()=>{this.followLive&&this.setFollowLive(!1)},clearSelection:()=>this.clearSelection(),zoomIn:()=>this.renderer?.zoomIn(),zoomOut:()=>this.renderer?.zoomOut(),targets:o=>this.navigationTargets(o)}),this.navigation.update(this.isBulkSelectMode(),this.mode==="view")}navigationTargets(e){let t=e.toLocaleLowerCase(),s=[];for(let o of this.sectionOptions)if(o.label.toLocaleLowerCase().includes(t)&&s.push({label:o.label,detail:"Section",locate:()=>this.locateSection(o.id)}),s.length>=20)return s;let i=new Map;for(let o of this.labelToSeat.values()){let a=i.get(o.rowId)??{minX:o.x,minY:o.y,maxX:o.x,maxY:o.y};a.minX=Math.min(a.minX,o.x),a.minY=Math.min(a.minY,o.y),a.maxX=Math.max(a.maxX,o.x),a.maxY=Math.max(a.maxY,o.y),i.set(o.rowId,a)}for(let o of this.doc?Ee(this.doc).flatMap(a=>a.objects):[]){if(o.type!=="row"||!(o.displayLabel??o.label).toLocaleLowerCase().includes(t))continue;let a=i.get(o.id);if(!a)continue;let{minX:l,minY:r,maxX:c,maxY:d}=a;if(s.push({label:o.displayLabel??o.label,detail:"Row",locate:()=>{let h=this.sectionByObject.get(o.id);h&&this.renderer?.focusSection(h),this.renderer?.focusRegion({x:l-30,y:r-30,width:c-l+60,height:d-r+60},{minScale:1.2,animate:!1})}}),s.length>=20)return s}for(let o of this.labelToSeat.values())if(o.label.toLocaleLowerCase().includes(t)&&(s.push({label:o.label,detail:"Seat",locate:()=>{let a=this.sectionByObject.get(o.rowId);a&&this.renderer?.focusSection(a),this.renderer?.focusRegion({x:o.x-180,y:o.y-120,width:360,height:240},{animate:!1,minScale:1.5}),this.renderer?.flashSeat(o.id,this.activityColor(this.status.get(o.label)??"free"))}}),s.length>=20))break;return s}updateContainerLayout(){let e=this.root?.getBoundingClientRect().width||this.host.clientWidth;this.root?.classList.toggle("compact",e>0&&e<800),this.channels?.handleLayoutChange(),this.syncMinimap()}filterableSections(){return this.sectionsBase?[...this.sectionsBase.sections,...this.sectionsBase.ungrouped?[this.sectionsBase.ungrouped]:[]]:[]}applyFilteredSectionCanvas(e=this.filterableSections().filter(t=>t.label===this.filteredSectionLabel)){if(!this.renderer||this.mode!=="filterSections"||!e.length)return;let t=new Set(e.map(i=>i.id)),s=this.filterableSections().filter(i=>!t.has(i.id)).map(i=>i.id);this.renderer.clearSectionFocus(),this.renderer.setClosedSections(null),this.renderer.setDimmedSections(s),this.frameSections(e)}frameSections(e){if(!this.renderer||!e.length)return;let t=e.flatMap(r=>r.seatLabels).map(r=>this.labelToSeat.get(r)).filter(r=>!!r&&Number.isFinite(r.x)&&Number.isFinite(r.y));if(!t.length){this.renderer.focusRegion(e[0].id);return}let s=Math.min(...t.map(r=>r.x)),i=Math.min(...t.map(r=>r.y)),o=Math.max(...t.map(r=>r.x)),a=Math.max(...t.map(r=>r.y)),l=Math.max(40,Math.max(o-s,a-i)*.08);this.renderer.focusRegion({x:s-l,y:i-l,width:Math.max(1,o-s)+l*2,height:Math.max(1,a-i)+l*2})}buildSectionOptions(){if(this.doc)try{let e=kt(this.doc);this.sectionsBase=e,this.sectionOptions=[],this.sectionByObject=new Map(e.objectToSection),this.sectionLabelById.clear();for(let t of e.sections)this.sectionOptions.push({id:t.id,label:t.label}),this.sectionLabelById.set(t.id,t.label);e.ungrouped&&(this.sectionOptions.push({id:v,label:e.ungrouped.label}),this.sectionLabelById.set(v,e.ungrouped.label))}catch{}}toolAvailable(e){return e==="view"?!0:e==="channels"&&!this.channelCaps.view||e==="categories"&&!this.categoryCanManage||e==="tables"&&(!this.tableCanManage||!this.tables().length)?!1:!this.opts.tools||this.opts.tools.includes(e)}settleMode(){this.toolAvailable(this.mode)?this.paintModeTabs():this.setMode("view")}tables(){return(this.doc?Ee(this.doc):[]).flatMap(e=>e.objects).filter(e=>e.type==="table")}paintModeTabs(){let e=[];this.els.modes?.querySelectorAll(".slm-modegroup").forEach(s=>{let i=[];s.querySelectorAll("[data-mode]").forEach(o=>{let a=o.dataset.mode,l=this.toolAvailable(a);if(o.hidden=!l,!l)return;i.push({mode:a,label:o.textContent??a});let r=a===this.mode;o.classList.toggle("on",r),o.setAttribute("aria-selected",String(r)),o.tabIndex=r?0:-1}),s.hidden=i.length===0,i.length&&e.push({label:s.querySelector(".slm-modegroup-label")?.textContent??"",tools:i})});let t=this.els.tools;t&&(t.innerHTML=e.map(s=>`<optgroup label="${m(s.label)}">${s.tools.map(i=>`<option value="${i.mode}"${i.mode===this.mode?" selected":""}>${m(i.label)}</option>`).join("")}</optgroup>`).join(""),t.value=this.mode),this.root?.classList.toggle("block-mode",this.mode==="block")}railHeader(e,t,s){let i=t==="read"?"Read-only":t==="event"?"This event only":"Your app";return`<div class="slm-railhead"><p class="slm-eyebrow">${m(e)}</p><span class="slm-scope ${t}">${i}</span></div>
758
+ <p class="slm-hint">${s}</p>`}paintFollowLiveButton(){let e=this.els.follow;if(!e)return;e.classList.toggle("on",this.followLive),e.setAttribute("aria-pressed",String(this.followLive)),e.textContent="Auto-follow";let t=this.root?.querySelector('[data-ref="followstatus"]');t&&(t.hidden=!this.followLive,t.textContent="Waiting for new holds or bookings"),e.setAttribute("title",this.followLive?"Following new holds and bookings. Turn off to keep the current view.":"Stay on the current map view. Enable to follow new holds and bookings.")}paintHeatButton(){this.paintMapViewMenu(),this.paintMomentumHelp()}paintMomentumHelp(){let e=this.root?.querySelector('[data-ref="heatstatus"]');if(e){e.hidden=!this.heatEnabled;let o=this.controlRoomSnapshot?.velocity.bySection.some(a=>a.netBooked>0);e.textContent=this.controlRoomSnapshot?o?`Booking heatmap \xB7 last ${this.trendWindowMinutes}m \xB7 warmer = higher net booking rate`:`No positive net bookings in the last ${this.trendWindowMinutes}m`:"Loading booking heatmap\u2026"}let t=this.els.rail?.querySelector('[data-ref="momentumhelp"]');if(!t)return;t.hidden=!this.heatEnabled;let s=t.querySelector('[data-ref="momentumcopy"]');if(!s)return;let i=this.controlRoomSnapshot?.velocity.bySection.some(o=>o.netBooked>0);s.textContent=i?"Warmer sections have more completed bookings, adjusted for section size. Holds and viewers are not counted.":`No completed bookings in the last ${this.trendWindowMinutes} minutes.`}paintFullscreenButton(){let e=this.els.fullscreen;if(!e)return;let t=this.isFullscreen(),s=t?"Exit full screen":"Full screen";e.setAttribute("aria-label",s),e.title=`${s} (F)`;let i=e.querySelector(".slm-fullscreen-label");i&&(i.textContent=s);let o=e.querySelector(".slm-fullscreen-icon");o&&(o.innerHTML=t?j.exit:j.enter)}paintTrendWindow(){this.els.rail?.querySelectorAll("[data-window]").forEach(e=>{let t=Number(e.dataset.window);e.classList.toggle("on",t===this.trendWindowMinutes)})}setLive(e){this.root?.classList.toggle("live",e),this.els.livetext&&(this.els.livetext.textContent=e?"LIVE":"RECONNECTING"),this.paintMonitorInsights();let t=e?"live":this.sessionEnded?"ended":"reconnecting";if(this.els.livetext&&!e&&this.sessionEnded&&(this.els.livetext.textContent="ENDED"),t!==this.connectionStatus){this.connectionStatus=t;try{this.opts.onConnectionChange?.(this.getConnection())}catch(s){this.opts.onError?.(s)}}}updateZoomHint(){let e=this.els.zoomhint;if(!e)return;let t=this.isBulkSelectMode()&&!this.movingMap&&this.renderer?.getRung?.()!=="seats";e.classList.toggle("on",!!t)}formatKpiDelta(e,t,s){let i=t>0?"+":"\u2212",o=Math.abs(t);return e==="booked-value"?`${i}${T(o,s)}`:e==="booked-pct"?`${i}${o.toLocaleString()}pt`:`${i}${o.toLocaleString()}`}paintKpis(e){if(!this.els.kpis)return;let t=e.bookedValueStatus==="current"?T(e.bookedValue,e.currency):"\u2014",s=this.presenceCounts(),i=[{key:"booked-inventory",raw:e.booked,n:e.booked.toLocaleString(),l:"Booked inventory",dot:x.booked,title:"Inventory units booked"},{key:"held-seats",raw:e.held,n:e.held.toLocaleString(),l:"Held inventory",dot:x.held,title:"Inventory currently held"},{key:"free-seats",raw:e.free,n:e.free.toLocaleString(),l:"Available",dot:x.free,title:"Inventory available to book"},{key:"blocked",raw:e.blocked,n:e.blocked.toLocaleString(),l:"Blocked",dot:x.blocked,title:"Inventory withheld from booking"},{key:"viewing-map",raw:s?.shoppingSessions??null,n:s?s.shoppingSessions.toLocaleString():"\u2014",l:"Viewing map",title:"Active map sessions right now"},{key:"active-holds",raw:s?.activeHolds??null,n:s?s.activeHolds.toLocaleString():"\u2014",l:"Active holds",title:"Sessions currently holding inventory"},{key:"booked-pct",raw:e.capacityPct,n:`${e.capacityPct}%`,l:"Booked",title:"Booked inventory as a share of the whole event"},{key:"booked-value",raw:e.bookedValueStatus==="current"?e.bookedValue:null,n:t,l:"Booked value",title:"Configured value attached to booked inventory"}],o=!1;this.els.kpis.innerHTML=i.map(a=>{let l=this.lastKpiValues.get(a.key),r=a.raw!=null&&l!=null&&a.raw!==l,c=r?a.raw-l:0;r&&(o=!0,this.activeKpiDeltas.set(a.key,{text:this.formatKpiDelta(a.key,c,e.currency),down:c<0})),a.raw!=null&&this.lastKpiValues.set(a.key,a.raw);let d=this.activeKpiDeltas.get(a.key);return`<div class="slm-kpi${d?" changed":""}" data-kpi="${a.key}" title="${m(a.title)}">
759
+ <b>${a.dot?`<span class="dot" style="background:${a.dot}"></span>`:""}${a.n}</b><span>${a.l}</span>
760
+ ${d?`<span class="slm-kpidelta${d.down?" down":""}">${d.text}</span>`:""}
761
+ </div>`}).join(""),o&&(this.kpiCleanupTimer&&clearTimeout(this.kpiCleanupTimer),this.kpiCleanupTimer=setTimeout(()=>{this.kpiCleanupTimer=null,this.activeKpiDeltas.clear(),this.els.kpis?.querySelectorAll(".slm-kpidelta").forEach(a=>a.remove()),this.els.kpis?.querySelectorAll(".slm-kpi.changed").forEach(a=>a.classList.remove("changed"))},1500))}paintRail(){this.root?.classList.toggle("monitor-view",this.mode==="view"||this.mode==="inspect"),this.seatHistoryPanel?.destroy(),this.seatHistoryPanel=null,this.activityPanel?.destroy(),this.activityPanel=null,this.mode==="view"?this.renderViewRail():this.mode==="inspect"?this.renderInspectRail(this.getSelection()):this.mode==="select"?this.renderSelectRail():this.mode==="filterSections"?this.renderFilterSectionsRail():this.mode==="sections"?this.renderSectionsRail():this.mode==="categories"?this.renderCategoriesRail():this.mode==="tables"?this.renderTablesRail():this.mode==="channels"?this.channels?this.channels.paintRail():this.channelsLoading?this.els.rail.innerHTML='<div class="slm-empty" role="status">Loading sales channels\u2026</div>':this.els.rail.innerHTML='<div class="slm-empty" role="alert">Sales channels could not be loaded. Switch away and back to try again.</div>':this.renderBlockRail(),this.updateZoomHint()}renderViewRail(){this.els.rail.innerHTML=`
513
762
  <div class="slm-monitor-head"><h2>Live activity</h2><span data-ref="presence" class="slm-monitor-connection"></span></div>
514
763
  <div class="slm-monitor-tabs" role="tablist" aria-label="Monitor details">
515
764
  <button role="tab" aria-selected="true" data-monitor-tab="activity">Activity</button>
@@ -528,120 +777,93 @@ import{c as H,d as B,f as j}from"./chunk-RZ2VKZ44.js";import{A as Re,B as Ae,D a
528
777
  </div>
529
778
  <div class="slm-sectionlist" data-ref="sections"></div>
530
779
  </div>
531
- `,this.els.presence=this.els.rail.querySelector('[data-ref="presence"]'),this.els.legend=this.els.rail.querySelector('[data-ref="legend"]'),this.els.sections=this.els.rail.querySelector('[data-ref="sections"]'),this.els.feed=this.els.rail.querySelector('[data-ref="feed"]'),this.activityPanel=new L(this.els.feed,this.sectionOptions,e=>{this.setFollowLive(!1),this.locateActivity(e)}),this.els.rail.querySelectorAll("[data-monitor-tab]").forEach(e=>e.addEventListener("click",()=>{let t=e.dataset.monitorTab;this.els.rail.querySelectorAll("[data-monitor-tab]").forEach(s=>s.setAttribute("aria-selected",String(s.dataset.monitorTab===t))),this.els.rail.querySelectorAll("[data-monitor-panel]").forEach(s=>{s.hidden=s.dataset.monitorPanel!==t})})),this.els.rail.querySelectorAll("[data-window]").forEach(e=>e.addEventListener("click",()=>{let t=Number(e.dataset.window);this.setTrendWindow(t).catch(s=>this.opts.onError?.(s))})),this.recomputeTallies(),this.paintMonitorInsights(),this.paintTrendWindow(),this.paintMomentumHelp(),this.paintFeed()}presenceCounts(){return this.livePresence?.value??this.controlRoomSnapshot?.presence??null}paintMonitorInsights(){if(this.mode!=="view")return;let e=this.controlRoomSnapshot;if(this.els.presence){let i=this.root?.classList.contains("live"),a=this.lastSyncedAt?ee(this.lastSyncedAt,Date.now()):"waiting";this.els.presence.textContent=i?"\u25CF Live":"Reconnecting",this.els.presence.title=`Last data received: ${a}`}if(!this.els.sections)return;if(!e){this.els.sections.innerHTML='<div class="slm-empty">Loading authoritative section metrics\u2026</div>';return}let t=new Map(e.velocity.bySection.map(i=>[i.sectionId,i])),s=[...e.bookedValue.bySection].sort((i,a)=>{let o=t.get(i.sectionId)?.netBooked??0;return(t.get(a.sectionId)?.netBooked??0)-o||a.bookedValue-i.bookedValue});this.els.sections.innerHTML=s.length?s.map(i=>{let a=t.get(i.sectionId),o=a?.netBooked??0,l=`${o>0?"+":""}${o}`,r=a?.trend==="rising"||a?.trend==="cooling"?a.trend:"steady";return`<button type="button" class="slm-sectionrow" data-section-focus="${p(i.sectionId)}" title="Focus ${p(i.sectionLabel)} on the map">
532
- <span class="slm-sectiontop"><span>${p(i.sectionLabel)}</span><span title="Configured value of currently booked inventory">${R(i.bookedValue,e.currency)}</span></span>
780
+ `,this.els.presence=this.els.rail.querySelector('[data-ref="presence"]'),this.els.legend=this.els.rail.querySelector('[data-ref="legend"]'),this.els.sections=this.els.rail.querySelector('[data-ref="sections"]'),this.els.feed=this.els.rail.querySelector('[data-ref="feed"]'),this.activityPanel=new E(this.els.feed,this.sectionOptions,e=>{this.setFollowLive(!1),this.locateActivity(e)}),this.els.rail.querySelectorAll("[data-monitor-tab]").forEach(e=>e.addEventListener("click",()=>{let t=e.dataset.monitorTab;this.els.rail.querySelectorAll("[data-monitor-tab]").forEach(s=>s.setAttribute("aria-selected",String(s.dataset.monitorTab===t))),this.els.rail.querySelectorAll("[data-monitor-panel]").forEach(s=>{s.hidden=s.dataset.monitorPanel!==t})})),this.els.rail.querySelectorAll("[data-window]").forEach(e=>e.addEventListener("click",()=>{let t=Number(e.dataset.window);this.setTrendWindow(t).catch(s=>this.opts.onError?.(s))})),this.recomputeTallies(),this.paintMonitorInsights(),this.paintTrendWindow(),this.paintMomentumHelp(),this.paintFeed()}presenceCounts(){return this.livePresence?.value??this.controlRoomSnapshot?.presence??null}paintMonitorInsights(){if(this.mode!=="view")return;let e=this.controlRoomSnapshot;if(this.els.presence){let i=this.root?.classList.contains("live"),o=this.lastSyncedAt?te(this.lastSyncedAt,Date.now()):"waiting";this.els.presence.textContent=i?"\u25CF Live":"Reconnecting",this.els.presence.title=`Last data received: ${o}`}if(!this.els.sections)return;if(!e){this.els.sections.innerHTML='<div class="slm-empty">Loading authoritative section metrics\u2026</div>';return}let t=new Map(e.velocity.bySection.map(i=>[i.sectionId,i])),s=[...e.bookedValue.bySection].sort((i,o)=>{let a=t.get(i.sectionId)?.netBooked??0;return(t.get(o.sectionId)?.netBooked??0)-a||o.bookedValue-i.bookedValue});this.els.sections.innerHTML=s.length?s.map(i=>{let o=t.get(i.sectionId),a=o?.netBooked??0,l=`${a>0?"+":""}${a}`,r=o?.trend==="rising"||o?.trend==="cooling"?o.trend:"steady";return`<button type="button" class="slm-sectionrow" data-section-focus="${m(i.sectionId)}" title="Focus ${m(i.sectionLabel)} on the map">
781
+ <span class="slm-sectiontop"><span>${m(i.sectionLabel)}</span><span title="Configured value of currently booked inventory">${T(i.bookedValue,e.currency)}</span></span>
533
782
  <span class="slm-sectionmeta"><span>${i.booked.toLocaleString()}/${i.total.toLocaleString()} booked \xB7 ${l} net in ${e.velocity.windowMinutes}m</span><span class="slm-trend ${r}">${r}</span><span class="slm-sectionlocate">Locate</span></span>
534
- </button>`}).join(""):'<div class="slm-empty">No section metrics are available for this chart.</div>',this.paintTrendWindow(),this.paintMomentumHelp()}applyHeatOverlay(){let e=this.controlRoomSnapshot;if(!this.heatEnabled||!e){this.renderer?.setSectionHeat(null);return}let t=new Map(e.bookedValue.bySection.map(o=>[o.sectionId,Math.max(1,o.total)])),s=e.velocity.bySection.map(o=>({sectionId:o.sectionId,rate:Math.max(0,o.netBooked)/(t.get(o.sectionId)??1)/e.velocity.windowMinutes})),i=Math.max(0,...s.map(o=>o.rate)),a={};for(let o of s)a[o.sectionId]=i>0?Math.sqrt(o.rate/i):0;this.renderer?.setSectionHeat(a)}renderSelectRail(){let e=this.doc?.categories??[],t=this.opts.numberOfPlacesToSelect,s=this.selectionCap();this.els.rail.innerHTML=`
783
+ </button>`}).join(""):'<div class="slm-empty">No section metrics are available for this chart.</div>',this.paintTrendWindow(),this.paintMomentumHelp()}applyHeatOverlay(){let e=this.controlRoomSnapshot;if(!this.heatEnabled||!e){this.renderer?.setSectionHeat(null);return}let t=new Map(e.bookedValue.bySection.map(a=>[a.sectionId,Math.max(1,a.total)])),s=e.velocity.bySection.map(a=>({sectionId:a.sectionId,rate:Math.max(0,a.netBooked)/(t.get(a.sectionId)??1)/e.velocity.windowMinutes})),i=Math.max(0,...s.map(a=>a.rate)),o={};for(let a of s)o[a.sectionId]=i>0?Math.sqrt(a.rate/i):0;this.renderer?.setSectionHeat(o)}renderSelectRail(){let e=this.opts.numberOfPlacesToSelect,t=this.selectionCap(),s=this.toolChooser();this.els.rail.innerHTML=`
535
784
  ${this.railHeader("Select","host","Pick seats for your own back-office operation \u2014 the selection is handed to your app. This tool is read-only inside the control room: it never books, releases or blocks seats by itself.")}
536
- <div class="slm-selbar" aria-live="polite"><span class="slm-selnum" data-ref="selectnum">0</span><span class="slm-sellabel" data-ref="selectmeta">selected</span></div>
537
- <p class="slm-note" data-ref="selectvalidity">${t?`Select exactly ${t.toLocaleString()} object${t===1?"":"s"}.`:`Up to ${s.toLocaleString()} objects may be selected.`}</p>
538
- <div class="slm-row">
539
- <button class="slm-btn ghost" data-ref="selectall">Select all</button>
540
- <button class="slm-btn ghost" data-ref="selectclear" disabled>Clear</button>
541
- </div>
542
- ${e.length?`<p class="slm-eyebrow" style="margin-top:8px">Select by category</p>
543
- <div class="slm-chipgrid">${e.map(i=>`
544
- <button class="slm-chip" type="button" data-select-cat="${p(i.key)}" aria-pressed="false">
545
- <span class="dot" style="background:${p(i.color??"#6e7bff")}"></span>
546
- <span>${p(i.label??i.key)}</span>
547
- <span class="slm-chipcount" data-cat-count>0</span>
548
- <span class="slm-chipcheck" aria-hidden="true">\u2713</span>
549
- </button>`).join("")}</div>`:""}`,this.els.selectnum=this.els.rail.querySelector('[data-ref="selectnum"]'),this.els.selectmeta=this.els.rail.querySelector('[data-ref="selectmeta"]'),this.els.selectvalidity=this.els.rail.querySelector('[data-ref="selectvalidity"]'),this.els.selectclear=this.els.rail.querySelector('[data-ref="selectclear"]'),this.els.rail.querySelector('[data-ref="selectall"]')?.addEventListener("click",()=>this.selectAll()),this.els.selectclear.addEventListener("click",()=>this.clearSelection()),this.els.rail.querySelectorAll("[data-select-cat]").forEach(i=>{i.addEventListener("click",()=>{let a=i.dataset.selectCat,o=[...this.labelToSeat.values()].filter(r=>r.categoryKey===a&&this.canSelectObject(r)),l=new Set(this.selectionLabels());o.length>0&&o.every(r=>l.has(r.label))?this.deselectCategories([a]):this.selectCategories([a])})}),this.paintSelectSelection(this.getSelection())}paintSelectSelection(e){if(!this.els.selectnum||!this.els.selectmeta)return;let t=e.length;this.els.selectnum.textContent=t.toLocaleString(),this.els.selectmeta.textContent=t===1?"object selected":"objects selected",this.els.selectclear.disabled=t===0;let s=this.getSelectionValidity();this.els.selectvalidity&&(this.els.selectvalidity.textContent=s?s.isValid?`Ready \u2014 exactly ${s.required.toLocaleString()} selected.`:`Select ${s.remaining.toLocaleString()} more to continue.`:`${Math.max(0,this.selectionCap()-t).toLocaleString()} selections remaining.`);let i=new Set(e.map(a=>a.label));this.els.rail?.querySelectorAll("[data-select-cat]").forEach(a=>{let o=a.dataset.selectCat,l=[...this.labelToSeat.values()].filter(d=>d.categoryKey===o&&this.canSelectObject(d)),r=l.filter(d=>i.has(d.label)).length,c=l.length>0&&r===l.length;a.classList.toggle("on",c),a.setAttribute("aria-pressed",String(c));let n=a.querySelector("[data-cat-count]");n&&(n.textContent=r?`${r}/${l.length}`:l.length.toLocaleString()),a.disabled=l.length===0})}renderFilterSectionsRail(){let e=new Map;for(let t of this.filterableSections())e.set(t.label,[...e.get(t.label)??[],t]);this.els.rail.innerHTML=`
785
+ <p class="slm-eyebrow slm-step"><span class="slm-stepnum">1</span>Choose seats</p>
786
+ <p class="slm-selecthelp">Tap seats on the map, tap a row label for the whole row, press \u2318A for all, or pick a category, section or rows below.</p>
787
+ ${s.chipsHtml()}
788
+ ${this.toolSelectionBar("selectnum","selectmeta","selectclear","selectall")}
789
+ <p class="slm-note" data-ref="selectvalidity">${e?`Select exactly ${e.toLocaleString()} object${e===1?"":"s"}.`:`Up to ${t.toLocaleString()} objects may be selected.`}</p>`,this.els.selectnum=this.els.rail.querySelector('[data-ref="selectnum"]'),this.els.selectmeta=this.els.rail.querySelector('[data-ref="selectmeta"]'),this.els.selectvalidity=this.els.rail.querySelector('[data-ref="selectvalidity"]'),this.els.selectclear=this.els.rail.querySelector('[data-ref="selectclear"]'),this.els.rail.querySelector('[data-ref="selectall"]')?.addEventListener("click",()=>this.selectAll()),this.els.selectclear.addEventListener("click",()=>this.clearSelection()),s.wire(this.els.rail),this.paintSelectSelection(this.getSelection())}paintSelectSelection(e){if(!this.els.selectnum||!this.els.selectmeta)return;let t=e.length;this.els.selectnum.textContent=t.toLocaleString(),this.els.selectmeta.textContent=t===1?"object selected":"objects selected",this.els.selectclear.disabled=t===0;let s=this.getSelectionValidity();this.els.selectvalidity&&(this.els.selectvalidity.textContent=s?s.isValid?`Ready \u2014 exactly ${s.required.toLocaleString()} selected.`:`Select ${s.remaining.toLocaleString()} more to continue.`:`${Math.max(0,this.selectionCap()-t).toLocaleString()} selections remaining.`)}renderFilterSectionsRail(){let e=new Map;for(let t of this.filterableSections())e.set(t.label,[...e.get(t.label)??[],t]);this.els.rail.innerHTML=`
550
790
  ${this.railHeader("Filter sections","host","Narrow the map to one section for your own reporting. Sections sharing a label stay together and the map frames their combined inventory. Nothing changes for buyers.")}
551
- ${e.size?`<div class="slm-sectionlist">${[...e].map(([t,s])=>{let i=t===this.filteredSectionLabel,a=s.reduce((o,l)=>o+l.seatCount,0);return`<button type="button" class="slm-sectionrow${i?" on":""}" data-filter-section="${p(t)}" aria-pressed="${i}">
552
- <span class="slm-sectiontop"><span>${p(t)}</span><span>${a.toLocaleString()}</span></span>
791
+ ${e.size?`<div class="slm-sectionlist">${[...e].map(([t,s])=>{let i=t===this.filteredSectionLabel,o=s.reduce((a,l)=>a+l.seatCount,0);return`<button type="button" class="slm-sectionrow${i?" on":""}" data-filter-section="${m(t)}" aria-pressed="${i}">
792
+ <span class="slm-sectiontop"><span>${m(t)}</span><span>${o.toLocaleString()}</span></span>
553
793
  <span class="slm-sectionmeta"><span>${s.length===1?"One section":`${s.length.toLocaleString()} matching sections`}</span><span class="slm-sectionlocate">${i?"Filtered":"Filter"}</span></span>
554
794
  </button>`}).join("")}</div>
555
- <button type="button" class="slm-btn ghost" data-clear-filter ${this.filteredSectionLabel?"":"disabled"}>Clear filter</button>`:'<div class="slm-empty">This chart has no filterable sections.</div>'}`,this.els.rail.querySelectorAll("[data-filter-section]").forEach(t=>{t.addEventListener("click",()=>this.setFilteredSection(t.dataset.filterSection))}),this.els.rail.querySelector("[data-clear-filter]")?.addEventListener("click",()=>this.clearFilteredSection())}categorySeats(e){return[...this.labelToSeat.values()].filter(t=>t.categoryKey===e&&this.canSelectObject(t))}renderCategoriesRail(){let e=this.doc?.categories??[];this.els.rail.innerHTML=`
795
+ <button type="button" class="slm-btn ghost" data-clear-filter ${this.filteredSectionLabel?"":"disabled"}>Clear filter</button>`:'<div class="slm-empty">This chart has no filterable sections.</div>'}`,this.els.rail.querySelectorAll("[data-filter-section]").forEach(t=>{t.addEventListener("click",()=>this.setFilteredSection(t.dataset.filterSection))}),this.els.rail.querySelector("[data-clear-filter]")?.addEventListener("click",()=>this.clearFilteredSection())}categorySeats(e){return[...this.labelToSeat.values()].filter(t=>t.categoryKey===e&&this.canSelectObject(t))}renderCategoriesRail(){let e=this.doc?.categories??[],t=this.toolChooser();this.els.rail.innerHTML=`
556
796
  ${this.railHeader("Categories","event","Move seats to a different price category for this event only. The reusable chart keeps its design, and seats already held or booked keep the price they were sold at.")}
557
797
  <p class="slm-eyebrow slm-step"><span class="slm-stepnum">1</span>Choose seats</p>
558
- <p class="slm-selecthelp">Click or drag seats on the map, press \u2318A for all, or tick a whole category. A ticked category is selected; tick it again to remove it.</p>
559
- <div class="slm-chiprow">${e.length?e.map(s=>`
560
- <button class="slm-chip" type="button" data-pick-category="${p(s.key)}" aria-pressed="false">
561
- <span class="dot" style="background:${p(s.color??"#6e7bff")}"></span>
562
- <span>${p(s.label??s.key)}</span>
563
- <span class="slm-chipcount" data-cat-count>0</span>
564
- <span class="slm-chipcheck" aria-hidden="true">\u2713</span>
565
- </button>`).join(""):'<span class="slm-empty">This chart has no categories.</span>'}</div>
566
- <div class="slm-selbar" aria-live="polite">
567
- <span class="slm-selnum" data-ref="categorynum">0</span>
568
- <span class="slm-sellabel" data-ref="categorymeta">selected</span>
569
- </div>
570
- <div class="slm-row">
571
- <button class="slm-btn ghost" data-ref="categoryall">Select all</button>
572
- <button class="slm-btn ghost" data-ref="categoryclear" disabled>Clear</button>
573
- </div>
798
+ <p class="slm-selecthelp">Click seats, drag a box or draw a lasso on the map, tap a row label for the whole row, press \u2318A for all, or pick below.</p>
799
+ ${t.chipsHtml({intents:this.marqueeShapeChipsHtml()})}
800
+ ${this.toolSelectionBar("categorynum","categorymeta","categoryclear","categoryall")}
574
801
  <p class="slm-eyebrow slm-step" style="margin-top:14px"><span class="slm-stepnum">2</span>Move them to</p>
575
802
  <p class="slm-selecthelp" data-ref="categoryhelp">Select seats first \u2014 then pick the category they should sell under.</p>
576
- <div class="slm-categoryassign">${e.map(s=>`
577
- <button type="button" class="slm-categoryrow" data-assign-category="${p(s.key)}" disabled>
578
- <span class="dot" style="background:${p(s.color??"#6e7bff")}"></span>
579
- <span class="slm-categorycopy"><b>${p(s.label??s.key)}</b><small data-cat-current>0 seats now</small></span>
803
+ <div class="slm-categoryassign">${e.length?e.map(i=>`
804
+ <button type="button" class="slm-categoryrow" data-assign-category="${m(i.key)}" disabled>
805
+ <span class="dot" style="background:${m(i.color??"#6e7bff")}"></span>
806
+ <span class="slm-categorycopy"><b>${m(i.label??i.key)}</b><small data-cat-current>0 seats now</small></span>
580
807
  <span class="slm-categoryact" data-cat-action>Move here</span>
581
- </button>`).join("")}</div>`;let t=s=>this.els.rail.querySelector(`[data-ref="${s}"]`);this.els.categorynum=t("categorynum"),this.els.categorymeta=t("categorymeta"),this.els.categoryhelp=t("categoryhelp"),this.els.categoryclear=t("categoryclear"),t("categoryall").addEventListener("click",()=>this.selectAll()),this.els.categoryclear.addEventListener("click",()=>this.clearSelection()),this.els.rail.querySelectorAll("[data-pick-category]").forEach(s=>{s.addEventListener("click",()=>{let i=s.dataset.pickCategory,a=this.categorySeats(i),o=new Set(this.selectionLabels());a.length>0&&a.every(l=>o.has(l.label))?this.deselectCategories([i]):this.selectCategories([i])})}),this.els.rail.querySelectorAll("[data-assign-category]").forEach(s=>{s.addEventListener("click",()=>{this.setCategory(s.dataset.assignCategory)})}),this.paintCategorySelection(this.getSelection())}paintCategorySelection(e){if(!this.els.categorynum)return;let t=e.length;this.els.categorynum.textContent=t.toLocaleString(),this.els.categoryclear.disabled=t===0;let s=new Map;for(let o of e)s.set(o.categoryKey,(s.get(o.categoryKey)??0)+1);let i=o=>this.doc?.categories.find(l=>l.key===o)?.label??o;this.els.categorymeta&&(this.els.categorymeta.textContent=t===0?"selected":`${t===1?"seat":"seats"} selected \xB7 ${[...s].map(([o,l])=>`${l.toLocaleString()} ${i(o)}`).join(", ")}`),this.els.categoryhelp&&(this.els.categoryhelp.textContent=t===0?"Select seats first \u2014 then pick the category they should sell under.":`Choose the category the ${t===1?"selected seat":`${t.toLocaleString()} selected seats`} should sell under. Applies immediately.`);let a=new Set(e.map(o=>o.label));this.els.rail?.querySelectorAll("[data-pick-category]").forEach(o=>{let l=o.dataset.pickCategory,r=this.categorySeats(l),c=r.filter(m=>a.has(m.label)).length,n=r.length>0&&c===r.length;o.classList.toggle("on",n),o.classList.toggle("partial",c>0&&!n),o.setAttribute("aria-pressed",String(n));let d=o.querySelector("[data-cat-count]");d&&(d.textContent=c?`${c.toLocaleString()}/${r.length.toLocaleString()}`:r.length.toLocaleString()),o.disabled=r.length===0}),this.els.rail?.querySelectorAll("[data-assign-category]").forEach(o=>{let l=o.dataset.assignCategory,r=[...this.labelToSeat.values()].filter(b=>b.categoryKey===l).length,c=s.get(l)??0,n=t>0&&c===t;o.disabled=t===0||n,o.classList.toggle("current",n);let d=o.querySelector("[data-cat-current]");d&&(d.textContent=`${r.toLocaleString()} ${r===1?"seat":"seats"} now`);let m=o.querySelector("[data-cat-action]");m&&(m.textContent=t===0?"Move here":n?"Already here":`Move ${(t-c).toLocaleString()} here`)})}renderTablesRail(){let e=this.tables(),t="Decide how each table sells for this event: every chair on its own, or the whole table as one booking. A table with held, booked, or blocked chairs is locked until that inventory is released, and channel allocations are kept.";if(this.inventoryModelVersion!==2){this.els.rail.innerHTML=`
808
+ </button>`).join(""):'<span class="slm-empty">This chart has no categories.</span>'}</div>
809
+ <div class="slm-catreset">
810
+ <button type="button" class="slm-btn ghost" data-ref="categoryreset" disabled>Reset to chart defaults</button>
811
+ <p class="slm-note" data-ref="categoryresetnote">Checking what differs from the chart\u2026</p>
812
+ </div>`;let s=i=>this.els.rail.querySelector(`[data-ref="${i}"]`);this.els.categorynum=s("categorynum"),this.els.categorymeta=s("categorymeta"),this.els.categoryhelp=s("categoryhelp"),this.els.categoryclear=s("categoryclear"),s("categoryall").addEventListener("click",()=>this.selectAll()),this.els.categoryclear.addEventListener("click",()=>this.clearSelection()),this.els.rail.querySelectorAll("[data-assign-category]").forEach(i=>{i.addEventListener("click",()=>{this.setCategory(i.dataset.assignCategory)})}),s("categoryreset").addEventListener("click",()=>{this.resetCategoriesToChart()}),t.wire(this.els.rail),this.wireMarqueeShapeChips(),this.paintCategorySelection(this.getSelection()),this.loadCategoryDifferences()}async loadCategoryDifferences(){let e=this.els.rail;if(!e||this.closed)return;let t=e.querySelector('[data-ref="categoryreset"]'),s=e.querySelector('[data-ref="categoryresetnote"]');if(!(!t||!s))try{let i=await this.withAuthRetry(()=>this.api.categoryDifferences(this.key));if(!t.isConnected)return;this.categoryDifferences=i.differing,this.paintCategoryReset()}catch(i){if(!t.isConnected)return;s.textContent="Could not check the chart\u2019s defaults. Reset is unavailable until it can.",this.opts.onError?.(i)}}paintCategoryReset(){let e=this.els.rail;if(!e)return;let t=e.querySelector('[data-ref="categoryreset"]'),s=e.querySelector('[data-ref="categoryresetnote"]');if(!t||!s)return;let i=this.categoryDifferences;i!=null&&(t.disabled=i===0,t.textContent=i?`Reset to chart defaults \xB7 ${i.toLocaleString()} seat${i===1?"":"s"}`:"Reset to chart defaults",s.textContent=i?"Puts every seat this event moved back in its chart category. Held and booked seats keep the price they were sold at.":"Every seat sells under its chart category.")}async resetCategoriesToChart(){let e=this.els.rail.querySelector('[data-ref="categoryreset"]');e&&(e.disabled=!0,e.textContent="Resetting\u2026");try{let t=await this.withAuthRetry(()=>this.api.resetCategoriesToChart(this.key));t.changed&&await this.reloadEventChart(),this.categoryDifferences=0,this.clearSelection(),this.mode==="categories"&&this.paintRail(),this.paintCategoryReset(),this.done("resetCategories",t.labels,t.changed?`Put ${t.labels.length.toLocaleString()} seat${t.labels.length===1?"":"s"} back on the chart\u2019s categories.`:"Every seat already sells under its chart category.")}catch(t){this.paintCategoryReset(),this.toastErr("Couldn\u2019t reset those categories. Nothing changed."),this.opts.onError?.(t)}}paintCategorySelection(e){if(!this.els.categorynum)return;let t=e.length;this.els.categorynum.textContent=t.toLocaleString(),this.els.categoryclear.disabled=t===0;let s=new Map;for(let o of e)s.set(o.categoryKey,(s.get(o.categoryKey)??0)+1);let i=o=>this.doc?.categories.find(a=>a.key===o)?.label??o;this.els.categorymeta&&(this.els.categorymeta.textContent=t===0?"selected":`${t===1?"seat":"seats"} selected \xB7 ${[...s].map(([o,a])=>`${a.toLocaleString()} ${i(o)}`).join(", ")}`),this.els.categoryhelp&&(this.els.categoryhelp.textContent=t===0?"Select seats first \u2014 then pick the category they should sell under.":`Choose the category the ${t===1?"selected seat":`${t.toLocaleString()} selected seats`} should sell under. Applies immediately.`),this.els.rail?.querySelectorAll("[data-assign-category]").forEach(o=>{let a=o.dataset.assignCategory,l=[...this.labelToSeat.values()].filter(p=>p.categoryKey===a).length,r=s.get(a)??0,c=t>0&&r===t;o.disabled=t===0||c,o.classList.toggle("current",c);let d=o.querySelector("[data-cat-current]");d&&(d.textContent=`${l.toLocaleString()} ${l===1?"seat":"seats"} now`);let h=o.querySelector("[data-cat-action]");h&&(h.textContent=t===0?"Move here":c?"Already here":`Move ${(t-r).toLocaleString()} here`)})}renderTablesRail(){let e=this.tables(),t="Decide how each table sells for this event: every chair on its own, or the whole table as one booking. A table with held, booked, or blocked chairs is locked until that inventory is released, and channel allocations are kept.";if(this.inventoryModelVersion!==2){this.els.rail.innerHTML=`
582
813
  ${this.railHeader("Tables","event",t)}
583
814
  <div class="slm-empty">This event still uses the older inventory model, which cannot switch tables between per-chair and whole-table selling. Upgrade the event's inventory model to unlock this tool.</div>`;return}if(!e.length){this.els.rail.innerHTML=`
584
815
  ${this.railHeader("Tables","event",t)}
585
- <div class="slm-empty">This chart has no tables. Add tables in the designer and they will appear here.</div>`;return}let s=d=>d.variableOccupancy?"variable":d.bookAsWhole?"whole":"individual",i=d=>{let m=0,b=0,g=0;for(let[u,f]of this.labelToSeat){if(f.rowId!==d.id)continue;let k=this.status.get(u);k==="held"?m++:k==="booked"?b++:k==="blocked"&&g++}let v=[b&&`${b} booked`,m&&`${m} held`,g&&`${g} blocked`].filter(Boolean);return v.length?v.join(" \xB7 "):null},a=e.map(d=>({table:d,current:s(d),locked:i(d)})),o=a.filter(d=>d.current==="individual").length,l=a.filter(d=>d.current==="whole").length,r=a.length-o-l,c=[`${o.toLocaleString()} per chair`,`${l.toLocaleString()} whole table`,r?`${r.toLocaleString()} flexible group`:""].filter(Boolean).join(" \xB7 "),n=this.tableBookingSaving;this.els.rail.innerHTML=`
816
+ <div class="slm-empty">This chart has no tables. Add tables in the designer and they will appear here.</div>`;return}let s=h=>h.variableOccupancy?"variable":h.bookAsWhole?"whole":"individual",i=h=>{let p=0,u=0,g=0;for(let[b,y]of this.labelToSeat){if(y.rowId!==h.id)continue;let z=this.status.get(b);z==="held"?p++:z==="booked"?u++:z==="blocked"&&g++}let f=[u&&`${u} booked`,p&&`${p} held`,g&&`${g} blocked`].filter(Boolean);return f.length?f.join(" \xB7 "):null},o=e.map(h=>({table:h,current:s(h),locked:i(h)})),a=o.filter(h=>h.current==="individual").length,l=o.filter(h=>h.current==="whole").length,r=o.length-a-l,c=[`${a.toLocaleString()} per chair`,`${l.toLocaleString()} whole table`,r?`${r.toLocaleString()} flexible group`:""].filter(Boolean).join(" \xB7 "),d=this.tableBookingSaving;this.els.rail.innerHTML=`
586
817
  ${this.railHeader("Tables","event",t)}
587
- <div class="slm-tablesummary"><b>${a.length.toLocaleString()} ${a.length===1?"table":"tables"}</b><span>${p(c)}</span></div>
818
+ <div class="slm-tablesummary"><b>${o.length.toLocaleString()} ${o.length===1?"table":"tables"}</b><span>${m(c)}</span></div>
588
819
  <p class="slm-eyebrow" style="margin-top:12px">Set every table at once</p>
589
820
  <div class="slm-row">
590
- <button class="slm-btn ghost" data-table-all="individual"${n?" disabled":""} title="Sell every chair on its own">All per chair</button>
591
- <button class="slm-btn ghost" data-table-all="whole"${n?" disabled":""} title="Sell every table as one booking">All whole table</button>
821
+ <button class="slm-btn ghost" data-table-all="individual"${d?" disabled":""} title="Sell every chair on its own">All per chair</button>
822
+ <button class="slm-btn ghost" data-table-all="whole"${d?" disabled":""} title="Sell every table as one booking">All whole table</button>
592
823
  </div>
593
824
  <p class="slm-eyebrow" style="margin-top:12px">Or one table at a time</p>
594
- <div class="slm-tablelist">${a.map(({table:d,current:m,locked:b})=>`<div class="slm-tablerow${b?" locked":""}">
595
- <span class="slm-tablecopy"><b>${p(d.displayLabel??d.label)}</b><small>${d.seatCount.toLocaleString()} chairs${b?` \xB7 <span class="slm-tablelock">Locked: ${p(b)}</span>`:""}</small></span>
596
- <select class="slm-select" data-table-mode="${p(d.id)}" aria-label="Booking mode for ${p(d.displayLabel??d.label)}"
597
- ${n||b?"disabled":""} ${b?`title="Release the ${p(b)} chairs before changing how this table sells"`:""}>
598
- <option value="individual"${m==="individual"?" selected":""}>Per chair</option>
599
- <option value="whole"${m==="whole"?" selected":""}>Whole table</option>
600
- ${m==="variable"?'<option value="variable" selected>Flexible group</option>':""}
825
+ <div class="slm-tablelist">${o.map(({table:h,current:p,locked:u})=>`<div class="slm-tablerow${u?" locked":""}">
826
+ <span class="slm-tablecopy"><b>${m(h.displayLabel??h.label)}</b><small>${h.seatCount.toLocaleString()} chairs${u?` \xB7 <span class="slm-tablelock">Locked: ${m(u)}</span>`:""}</small></span>
827
+ <select class="slm-select" data-table-mode="${m(h.id)}" aria-label="Booking mode for ${m(h.displayLabel??h.label)}"
828
+ ${d||u?"disabled":""} ${u?`title="Release the ${m(u)} chairs before changing how this table sells"`:""}>
829
+ <option value="individual"${p==="individual"?" selected":""}>Per chair</option>
830
+ <option value="whole"${p==="whole"?" selected":""}>Whole table</option>
831
+ ${p==="variable"?'<option value="variable" selected>Flexible group</option>':""}
601
832
  </select>
602
833
  </div>`).join("")}</div>
603
- <p class="slm-note">Changes apply immediately to this event. Flexible group sizes (minimum and maximum guests) are set through the API, never guessed here.</p>`,this.els.rail.querySelectorAll("[data-table-all]").forEach(d=>{d.addEventListener("click",()=>{this.setTableBooking(a.filter(m=>!m.locked).map(m=>m.table.id),d.dataset.tableAll)})}),this.els.rail.querySelectorAll("[data-table-mode]").forEach(d=>{d.addEventListener("change",()=>{this.setTableBooking([d.dataset.tableMode],d.value)})})}renderInspectRail(e){let t=e[e.length-1];if(!t){this.els.rail.innerHTML=`
834
+ <p class="slm-note">Changes apply immediately to this event. Flexible group sizes (minimum and maximum guests) are set through the API, never guessed here.</p>`,this.els.rail.querySelectorAll("[data-table-all]").forEach(h=>{h.addEventListener("click",()=>{this.setTableBooking(o.filter(p=>!p.locked).map(p=>p.table.id),h.dataset.tableAll)})}),this.els.rail.querySelectorAll("[data-table-mode]").forEach(h=>{h.addEventListener("change",()=>{this.setTableBooking([h.dataset.tableMode],h.value)})})}renderInspectRail(e){let t=e[e.length-1];if(!t){this.els.rail.innerHTML=`
604
835
  ${this.railHeader("Inspect","read","Click one seat on the map to read its live status, category, section and booking context. Nothing changes in this view.")}
605
- <div class="slm-empty">Select a seat on the map.</div>`;return}let s=this.status.get(t.label)??"free",i={free:"Free",held:"Held",booked:"Booked",blocked:"Blocked"},a=this.sectionByObject.get(t.rowId)??x,o=this.sectionLabelById.get(a)??"Other seats",l=this.doc?.categories.find(c=>c.key===t.categoryKey);this.els.rail.innerHTML=`
606
- <div class="slm-seat-heading"><h2>${p(t.label)}</h2><span data-seat-status>${i[s]}</span></div>
607
- <p class="slm-note">${p(o)} \xB7 ${p(l?.label??t.categoryKey)}</p>
608
- <div data-ref="seat-history"></div>`;let r=this.els.rail.querySelector('[data-ref="seat-history"]');this.seatHistoryPanel=new w(r,(c,n)=>this.withAuthRetry(()=>this.api.seatHistory(this.key,t.label,c,n)))}async refreshAvailability(){try{let e=await this.withAuthRetry(()=>this.api.availability(this.key));this.availabilityRules=e.rules??{},this.effectiveClosed=new Set(O(this.availabilityRules)),this.mode==="sections"&&this.renderSectionsRail(),this.applySectionCanvasTreatment()}catch(e){this.opts.onError?.(e)}}async withAuthRetry(e){try{return await e()}catch(t){if(t instanceof S&&t.status===401&&this.opts.onTokenRefresh&&!this.tokenRefreshInFlight)return await this.rotateToken(),e();throw t}}updateEffectiveAvailability(e,t){let s=!1;Array.isArray(e)&&(this.effectiveHidden=new Set(e.filter(i=>typeof i=="string")),s=!0),Array.isArray(t)&&(this.effectiveClosed=new Set(t.filter(i=>typeof i=="string")),s=!0),s&&(this.mode==="sections"&&this.renderSectionsRail(),this.applySectionCanvasTreatment())}applySectionCanvasTreatment(){this.renderer&&(this.mode==="sections"?(this.renderer.setDimmedSections([...this.effectiveHidden]),this.renderer.setClosedSections([...this.effectiveClosed])):this.mode==="filterSections"&&this.filteredSectionLabel?this.applyFilteredSectionCanvas():(this.renderer.setDimmedSections(null),this.renderer.setClosedSections(null)))}sectionRowsInput(){return{sectionsBase:this.sectionsBase,doc:this.doc,availabilityRules:this.availabilityRules,effectiveHidden:this.effectiveHidden,effectiveClosed:this.effectiveClosed}}renderSectionsRail(){let{rows:e,hiddenSections:t,closedSections:s}=A(this.sectionRowsInput());if(!e.length){this.els.rail.innerHTML=`
836
+ <div class="slm-empty">Select a seat on the map.</div>`;return}let s=this.status.get(t.label)??"free",i={free:"Free",held:"Held",booked:"Booked",blocked:"Blocked"},o=this.sectionByObject.get(t.rowId)??v,a=this.sectionLabelById.get(o)??"Other seats",l=this.doc?.categories.find(c=>c.key===t.categoryKey);this.els.rail.innerHTML=`
837
+ <div class="slm-seat-heading"><h2>${m(t.label)}</h2><span data-seat-status>${i[s]}</span></div>
838
+ <p class="slm-note">${m(a)} \xB7 ${m(l?.label??t.categoryKey)}</p>
839
+ <div data-ref="seat-history"></div>`;let r=this.els.rail.querySelector('[data-ref="seat-history"]');this.seatHistoryPanel=new C(r,(c,d)=>this.withAuthRetry(()=>this.api.seatHistory(this.key,t.label,c,d)))}async refreshAvailability(){try{let e=await this.withAuthRetry(()=>this.api.availability(this.key));this.availabilityRules=e.rules??{},this.effectiveClosed=new Set(P(this.availabilityRules)),this.mode==="sections"&&this.renderSectionsRail(),this.applySectionCanvasTreatment()}catch(e){this.opts.onError?.(e)}}async withAuthRetry(e){try{return await e()}catch(t){if(t instanceof k&&t.status===401&&this.opts.onTokenRefresh&&!this.tokenRefreshInFlight){if(await this.rotateToken(),this.sessionEnded)throw t;return e()}throw t instanceof k&&t.status===401&&!this.opts.onTokenRefresh&&this.endSession(),t}}updateEffectiveAvailability(e,t){let s=!1;Array.isArray(e)&&(this.effectiveHidden=new Set(e.filter(i=>typeof i=="string")),s=!0),Array.isArray(t)&&(this.effectiveClosed=new Set(t.filter(i=>typeof i=="string")),s=!0),s&&(this.mode==="sections"&&this.renderSectionsRail(),this.applySectionCanvasTreatment())}applySectionCanvasTreatment(){this.renderer&&(this.refreshBlockPaint(),this.mode==="sections"?(this.renderer.setDimmedSections([...this.effectiveHidden]),this.renderer.setClosedSections([...this.effectiveClosed])):this.mode==="filterSections"&&this.filteredSectionLabel?this.applyFilteredSectionCanvas():(this.renderer.setDimmedSections(null),this.renderer.setClosedSections(null)))}sectionRowsInput(){return{sectionsBase:this.sectionsBase,doc:this.doc,availabilityRules:this.availabilityRules,effectiveHidden:this.effectiveHidden,effectiveClosed:this.effectiveClosed}}renderSectionsRail(){let{rows:e,hiddenSections:t,closedSections:s}=B(this.sectionRowsInput());if(!e.length){this.els.rail.innerHTML=`
609
840
  ${this.railHeader("Sections","event","Draw sections or zones in the designer to schedule availability per area. This chart has none yet.")}
610
- <div class="slm-empty">No sections on this chart.</div>`;return}let i=[];t&&i.push(`${t} hidden`),s&&i.push(`${s} closed`);let a=i.length?i.join(" \xB7 "):"All sections open and on sale",o=t>0||s>0;this.els.rail.innerHTML=`
841
+ <div class="slm-empty">No sections on this chart.</div>`;return}let i=[];t&&i.push(`${t} hidden`),s&&i.push(`${s} closed`);let o=i.length?i.join(" \xB7 "):"All sections open and on sale",a=t>0||s>0;this.els.rail.innerHTML=`
611
842
  ${this.railHeader("Sections","event","Decide when each zone or section goes on sale for this event. 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.")}
612
- <div class="slm-availlist" data-ref="availlist">${e.map(l=>te(l,this.availabilitySaving)).join("")}</div>
843
+ <div class="slm-availlist" data-ref="availlist">${e.map(l=>Ce(l,this.availabilitySaving)).join("")}</div>
613
844
  <div class="slm-availsummary">
614
- <span class="slm-availdot${o?" warn":""}"></span>
615
- <span>${p(a)}</span>
845
+ <span class="slm-availdot${a?" warn":""}"></span>
846
+ <span>${m(o)}</span>
616
847
  </div>
617
848
  <div class="slm-availcallout">
618
849
  <span class="slm-availstar" aria-hidden="true">\u2726</span>
619
850
  <p><b>Auto-reveal at % sold</b> is demand-triggered release: the balcony opens itself the moment the stalls cross the threshold \u2014 no one has to be watching.</p>
620
- </div>`,this.wireSectionRail(),this.applySectionCanvasTreatment()}wireSectionRail(){let e=this.els.rail;e&&(e.querySelectorAll("[data-avail-id]").forEach(t=>{t.addEventListener("click",()=>this.setSectionMode(t.dataset.availId,t.dataset.availValue))}),e.querySelectorAll("[data-avail-picker]").forEach(t=>{t.querySelector("summary").addEventListener("click",s=>{this.availabilitySaving&&s.preventDefault(),e.querySelectorAll("[data-avail-picker]").forEach(i=>{i!==t&&(i.open=!1)})}),t.addEventListener("focusout",s=>{t.contains(s.relatedTarget)||(t.open=!1)}),t.addEventListener("keydown",s=>{if(s.key==="Escape"&&(t.open=!1,t.querySelector("summary").focus(),s.preventDefault()),s.key==="ArrowDown"||s.key==="ArrowUp"){if(this.availabilitySaving)return;s.preventDefault(),t.open=!0;let i=[...t.querySelectorAll("button")],a=i.indexOf(document.activeElement);i[(a+(s.key==="ArrowDown"?1:i.length-1)+i.length)%i.length]?.focus()}})}),e.querySelectorAll("[data-avail-reveal]").forEach(t=>{t.addEventListener("change",()=>{let s=new Date(t.value).getTime();Number.isFinite(s)&&this.setSectionRulePatch(t.dataset.availReveal,{revealAt:s})})}),e.querySelectorAll("[data-avail-pct]").forEach(t=>{t.addEventListener("change",()=>{let s=Math.max(1,Math.min(100,Number(t.value)||0));this.setSectionRulePatch(t.dataset.availPct,{thresholdPct:s})})}))}setSectionMode(e,t){let s=A(this.sectionRowsInput()).rows.find(l=>l.id===e),i=s?.seatLabels??this.availabilityRules[e]?.labels??[],a={...this.availabilityRules},o=G(t,i,this.availabilityRules[e]);if(o?a[e]=o:delete a[e],s?.kind==="zone"&&this.sectionsBase)for(let l of this.sectionsBase.sections)l.zone===e&&delete a[l.id];this.persistAvailability(a)}setSectionRulePatch(e,t){let s=this.availabilityRules[e];if(!s)return;let a=A(this.sectionRowsInput()).rows.find(o=>o.id===e)?.seatLabels??s.labels??[];this.persistAvailability({...this.availabilityRules,[e]:{...s,...t,labels:a}})}async persistAvailability(e){let t=this.availabilityRules;this.availabilityRules=e,this.availabilitySaving=!0,this.mode==="sections"&&this.renderSectionsRail();try{let s=await this.withAuthRetry(()=>this.api.setAvailability(this.key,e));this.availabilityRules=s.rules,this.effectiveHidden=new Set(s.hidden),this.effectiveClosed=new Set(O(s.rules)),this.availabilitySaving=!1,this.mode==="sections"&&this.renderSectionsRail(),this.applySectionCanvasTreatment()}catch(s){this.availabilityRules=t,this.availabilitySaving=!1,this.mode==="sections"&&this.renderSectionsRail(),this.toastErr("Couldn't update availability. Try again."),this.opts.onError?.(s)}}paintLegend(e){this.els.legend&&(this.els.legend.innerHTML=X.map(t=>`<div class="slm-legrow"><span class="slm-legdot" style="background:${t.color}"></span>
621
- <span class="slm-leglabel">${t.label}</span><span class="slm-legcount">${e[t.key].toLocaleString()}</span></div>`).join(""))}paintFeed(){this.activityPanel?.update(this.feed)}renderBlockRail(){let t=(this.doc?.categories??[]).map(n=>`<button class="slm-chip" type="button" data-cat="${p(n.key)}" aria-pressed="false">
622
- <span class="dot" style="background:${p(n.color??"#6e7bff")}"></span>
623
- <span>${p(n.label??n.key)}</span>
624
- <span class="slm-chipcount" data-cat-count>0</span>
625
- <span class="slm-chipcheck" aria-hidden="true">\u2713</span>
626
- </button>`).join(""),s=this.sectionOptions.length?`<div class="slm-field"><label>Select a whole section</label>
627
- <select class="slm-select" data-ref="section"><option value="">Choose a section\u2026</option>
628
- ${this.sectionOptions.map(n=>`<option value="${p(n.id)}">${p(n.label)}</option>`).join("")}</select></div>`:"",i=this.sectionOptions.map(n=>`<option value="${p(n.id)}">${p(n.label)}</option>`).join("");this.els.rail.innerHTML=`
851
+ </div>`,this.wireSectionRail(),this.applySectionCanvasTreatment()}wireSectionRail(){let e=this.els.rail;e&&(e.querySelectorAll("[data-avail-id]").forEach(t=>{t.addEventListener("click",()=>this.setSectionMode(t.dataset.availId,t.dataset.availValue))}),e.querySelectorAll("[data-avail-picker]").forEach(t=>{t.querySelector("summary").addEventListener("click",s=>{this.availabilitySaving&&s.preventDefault(),e.querySelectorAll("[data-avail-picker]").forEach(i=>{i!==t&&(i.open=!1)})}),t.addEventListener("focusout",s=>{t.contains(s.relatedTarget)||(t.open=!1)}),t.addEventListener("keydown",s=>{if(s.key==="Escape"&&(t.open=!1,t.querySelector("summary").focus(),s.preventDefault()),s.key==="ArrowDown"||s.key==="ArrowUp"){if(this.availabilitySaving)return;s.preventDefault(),t.open=!0;let i=[...t.querySelectorAll("button")],o=i.indexOf(document.activeElement);i[(o+(s.key==="ArrowDown"?1:i.length-1)+i.length)%i.length]?.focus()}})}),e.querySelectorAll("[data-avail-reveal]").forEach(t=>{t.addEventListener("change",()=>{let s=new Date(t.value).getTime();Number.isFinite(s)&&this.setSectionRulePatch(t.dataset.availReveal,{revealAt:s})})}),e.querySelectorAll("[data-avail-pct]").forEach(t=>{t.addEventListener("change",()=>{let s=Math.max(1,Math.min(100,Number(t.value)||0));this.setSectionRulePatch(t.dataset.availPct,{thresholdPct:s})})}))}setSectionMode(e,t){let s=B(this.sectionRowsInput()).rows.find(l=>l.id===e),i=s?.seatLabels??this.availabilityRules[e]?.labels??[],o={...this.availabilityRules},a=G(t,i,this.availabilityRules[e]);if(a?o[e]=a:delete o[e],s?.kind==="zone"&&this.sectionsBase)for(let l of this.sectionsBase.sections)l.zone===e&&delete o[l.id];this.persistAvailability(o)}setSectionRulePatch(e,t){let s=this.availabilityRules[e];if(!s)return;let o=B(this.sectionRowsInput()).rows.find(a=>a.id===e)?.seatLabels??s.labels??[];this.persistAvailability({...this.availabilityRules,[e]:{...s,...t,labels:o}})}async persistAvailability(e){let t=this.availabilityRules;this.availabilityRules=e,this.availabilitySaving=!0,this.mode==="sections"&&this.renderSectionsRail();try{let s=await this.withAuthRetry(()=>this.api.setAvailability(this.key,e));this.availabilityRules=s.rules,this.effectiveHidden=new Set(s.hidden),this.effectiveClosed=new Set(P(s.rules)),this.availabilitySaving=!1,this.mode==="sections"&&this.renderSectionsRail(),this.applySectionCanvasTreatment()}catch(s){this.availabilityRules=t,this.availabilitySaving=!1,this.mode==="sections"&&this.renderSectionsRail(),this.toastErr("Couldn't update availability. Try again."),this.opts.onError?.(s)}}paintLegend(e){this.els.legend&&(this.els.legend.innerHTML=Q.map(t=>`<div class="slm-legrow"><span class="slm-legdot" style="background:${t.color}"></span>
852
+ <span class="slm-leglabel">${t.label}</span><span class="slm-legcount">${e[t.key].toLocaleString()}</span></div>`).join(""))}paintFeed(){this.activityPanel?.update(this.feed)}renderBlockRail(){let e=this.toolChooser(),t=this.sectionOptions.map(l=>`<option value="${m(l.id)}">${m(l.label)}</option>`).join("");this.els.rail.innerHTML=`
629
853
  <div class="slm-monitor-tabs" role="tablist" aria-label="Blocking tools"><button role="tab" data-block-tab="edit" aria-selected="${!this.blockBrowse}">Block seats</button><button role="tab" data-block-tab="browse" aria-selected="${this.blockBrowse}">Find blocked</button></div>
630
- <p class="slm-note">${Y}</p>
631
- <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>
854
+ <p class="slm-note">${X}</p>
855
+ <div data-block-editor ${this.blockBrowse?"hidden":""}>
856
+ <p class="slm-eyebrow slm-step"><span class="slm-stepnum">1</span>Choose seats</p>
857
+ <p class="slm-selecthelp">Zoom into a section, then drag a box or draw a lasso on the map, tap a row label for the whole row, press \u2318A for all of it, or pick below.</p>
858
+ ${e.chipsHtml({intents:this.marqueeShapeChipsHtml()})}
859
+ </div>
860
+ ${this.toolSelectionBar("selnum","selmeta","clearsel","selall")}
861
+ <p class="slm-eyebrow slm-step" data-block-editor-step ${this.blockBrowse?"hidden":""}><span class="slm-stepnum">2</span>Then</p>
632
862
  <div class="slm-row">
633
863
  <button class="slm-btn" data-ref="doblock" disabled>Block</button>
634
864
  <button class="slm-btn ghost" data-ref="dounblock" disabled>Put back on sale</button>
635
865
  </div>
636
866
  <div data-block-editor ${this.blockBrowse?"hidden":""}>
637
- <div class="slm-row">
638
- <button class="slm-btn ghost" data-ref="selall">Select all</button>
639
- <button class="slm-btn ghost" data-ref="clearsel">Clear</button>
640
- </div>
641
- <p class="slm-eyebrow" style="margin-top:8px">Select by category</p>
642
- <p class="slm-selecthelp">Choose one or more. A checked category is selected; click it again to remove it.</p>
643
- <div class="slm-chiprow">${t||'<span class="slm-empty">No categories.</span>'}</div>
644
- ${s}
645
867
  <div class="slm-field">
646
868
  <label>Auto-release blocks at (optional)</label>
647
869
  <input type="datetime-local" class="slm-input" data-ref="release" />
@@ -657,7 +879,7 @@ import{c as H,d as B,f as j}from"./chunk-RZ2VKZ44.js";import{A as Re,B as Ae,D a
657
879
  <div class="slm-blockedtools">
658
880
  <input type="search" class="slm-input" data-ref="blockedsearch" placeholder="Find seat, row or category" aria-label="Search blocked seats" />
659
881
  <select class="slm-select" data-ref="blockedsection" aria-label="Filter blocked seats by section">
660
- <option value="">All sections</option>${i}
882
+ <option value="">All sections</option>${t}
661
883
  </select>
662
884
  </div>
663
885
  <div class="slm-blockedsummary">
@@ -670,5 +892,5 @@ import{c as H,d as B,f as j}from"./chunk-RZ2VKZ44.js";import{A as Re,B as Ae,D a
670
892
  <button class="slm-btn ghost" data-ref="markall" style="width:100%" disabled>Put all blocked seats on sale</button>
671
893
  <p class="slm-note slm-allnote" data-ref="markallnote">For a full reset only. You will be asked to confirm.</p>
672
894
  </div></details>
673
- `,this.els.rail.querySelectorAll("[data-block-tab]").forEach(n=>n.addEventListener("click",()=>{this.blockBrowse=n.dataset.blockTab==="browse",this.renderBlockRail()}));let a=n=>this.els.rail.querySelector(`[data-ref="${n}"]`);this.els.selnum=a("selnum"),this.els.doblock=a("doblock"),this.els.dounblock=a("dounblock"),this.els.selmeta=a("selmeta"),this.els.blockedcount=a("blockedcount"),this.els.blockedshowing=a("blockedshowing"),this.els.blockedlist=a("blockedlist"),this.els.selblocked=a("selblocked"),this.els.markall=a("markall"),this.els.markallnote=a("markallnote"),a("doblock").addEventListener("click",()=>{this.block()}),a("dounblock").addEventListener("click",()=>{this.unblock()}),a("selall").addEventListener("click",()=>this.selectAll()),a("clearsel").addEventListener("click",()=>this.clearSelection()),a("markall").addEventListener("click",()=>this.confirmUnblockAll()),this.els.rail.querySelectorAll("[data-cat]").forEach(n=>n.addEventListener("click",()=>this.toggleCategory(n.dataset.cat)));let o=this.els.rail.querySelector('[data-ref="section"]');o?.addEventListener("change",()=>{o.value&&(this.selectSection(o.value),o.value="")});let l=a("blockedsearch"),r=a("blockedsection");l.value=this.blockedQuery,r.value=this.blockedSection,l.addEventListener("input",()=>{this.blockedQuery=l.value,this.blockedResultLimit=100,this.paintBlockedInventory()}),r.addEventListener("change",()=>{this.blockedSection=r.value,this.blockedResultLimit=100,this.paintBlockedInventory()}),a("selblocked").addEventListener("click",()=>{this.toggleLabels(this.filteredBlockedSeats().map(n=>n.label))}),a("blockedlist").addEventListener("click",n=>{let d=n.target,m=d.closest("[data-block-seat-find]");if(m?.dataset.blockSeatFind){let u=this.labelToSeat.get(m.dataset.blockSeatFind);u&&(this.setFollowLive(!1),this.focusActivitySeats([u.label],this.sectionByObject.get(u.rowId)??x));return}let b=d.closest("[data-block-locate]"),g=d.closest("[data-block-group]");if(b||g){let u=b?.dataset.blockLocate??g?.dataset.blockGroup,f=this.filteredBlockedSeats().filter(k=>k.rowId===u);b&&f.length&&(this.setFollowLive(!1),this.focusActivitySeats(f.map(k=>k.label),this.sectionByObject.get(f[0].rowId)??x)),g&&this.toggleLabels(f.map(k=>k.label));return}let v=d.closest("[data-blocked-label]");v?.dataset.blockedLabel?this.toggleLabels([v.dataset.blockedLabel]):d.closest("[data-blocked-more]")&&(this.blockedResultLimit+=100,this.paintBlockedInventory())});let c=a("release");c.addEventListener("change",()=>{let n=c.value?new Date(c.value).getTime():NaN;this.releaseAt=Number.isFinite(n)&&n>Date.now()?n:null;let d=a("releasenote");d.textContent=this.releaseAt?`New blocks auto-release ${new Date(this.releaseAt).toLocaleString()}.`:c.value?"Pick a time in the future.":"Leave empty to block permanently."}),this.paintSelBar(this.getSelection())}toggleCategory(e){let t=[];for(let[s,i]of this.labelToSeat.entries())i.categoryKey===e&&this.isBlockSelectable(s)&&t.push(s);this.toggleLabels(t)}toggleLabels(e){if(!this.renderer)return;let t=e.filter(a=>this.labelToSeat.has(a)&&this.isBlockSelectable(a));if(!t.length)return;let s=new Set(this.selectionLabels());if(t.every(a=>s.has(a))){let a=t.map(o=>this.labelToId.get(o)).filter(o=>!!o);this.renderer.deselect(a)}else this.renderer.selectByLabels(t);this.syncSelection()}isBlockSelectable(e){let t=this.status.get(e)??"free";return t==="free"||t==="blocked"}paintSelBar(e){if(!this.els.selnum)return;this.els.selnum.textContent=e.length.toLocaleString();let t=e.filter(o=>(this.status.get(o.label)??"free")==="free").length,s=e.filter(o=>this.status.get(o.label)==="blocked").length;this.els.selmeta.textContent=e.length?`${t.toLocaleString()} available \xB7 ${s.toLocaleString()} blocked`:"selected";let i=this.els.doblock,a=this.els.dounblock;i.disabled=t===0,a.disabled=s===0,i.textContent=t?`Block ${t.toLocaleString()}`:"Block selected",a.textContent=s?`Put ${s.toLocaleString()} on sale`:"Put back on sale",this.paintCategoryControls(e),this.paintBlockedInventory()}paintCategoryControls(e){let t=new Set(e.map(s=>s.label));this.els.rail?.querySelectorAll("[data-cat]").forEach(s=>{let i=s.dataset.cat,a=[];for(let[n,d]of this.labelToSeat.entries())d.categoryKey===i&&this.isBlockSelectable(n)&&a.push(n);let o=a.filter(n=>t.has(n)).length,l=a.length>0&&o===a.length,r=o>0&&!l;s.disabled=a.length===0,s.classList.toggle("on",l),s.classList.toggle("partial",r),s.setAttribute("aria-pressed",l?"true":r?"mixed":"false"),s.setAttribute("title",l?`Remove all ${a.length.toLocaleString()} seats in this category from the selection`:r?`Select the remaining ${(a.length-o).toLocaleString()} seats in this category`:`Select all ${a.length.toLocaleString()} seats in this category`);let c=s.querySelector("[data-cat-count]");c&&(c.textContent=o?`${o.toLocaleString()}/${a.length.toLocaleString()}`:a.length.toLocaleString())})}filteredBlockedSeats(){let e=this.blockedQuery.trim().toLocaleLowerCase(),t=[];for(let[s,i]of this.labelToSeat.entries()){if(this.status.get(s)!=="blocked")continue;let a=this.sectionByObject.get(i.rowId)??x;if(!(this.blockedSection&&a!==this.blockedSection)){if(e){let o=this.doc?.categories.find(d=>d.key===i.categoryKey)?.label??i.categoryKey,l=this.sectionLabelById.get(a)??"Other seats",r=this.doc?.objects.find(d=>d.id===i.rowId),c=r?.type==="row"||r?.type==="table"?r.label:"";if(!`${s} ${o} ${l} ${c}`.toLocaleLowerCase().includes(e))continue}t.push(i)}}return t.sort((s,i)=>s.label.localeCompare(i.label,void 0,{numeric:!0,sensitivity:"base"}))}paintBlockedInventory(){if(!this.els.blockedlist)return;let e=[...this.status.entries()].filter(([,d])=>d==="blocked").length,t=this.filteredBlockedSeats(),s=t.slice(0,this.blockedResultLimit),i=new Set(this.selectionLabels()),a=t.filter(d=>i.has(d.label)).length,o=t.length>0&&a===t.length;this.els.blockedcount.textContent=e.toLocaleString(),this.els.blockedshowing.textContent=t.length?`Showing ${s.length.toLocaleString()} of ${t.length.toLocaleString()}`:e?"No matches":"No blocked seats";let l=this.els.selblocked;l.disabled=t.length===0,l.textContent=o?`Remove ${t.length.toLocaleString()} results`:`Select ${t.length.toLocaleString()} results`;let r=new Map;for(let d of t){let m=r.get(d.rowId)??[];m.push(d),r.set(d.rowId,m)}this.els.blockedshowing.textContent=`${t.length.toLocaleString()} seats \xB7 ${r.size} rows`,this.els.blockedlist.innerHTML=[...r.entries()].slice(0,this.blockedResultLimit).map(([d,m])=>{let b=this.sectionByObject.get(d)??x,g=this.sectionLabelById.get(b)??"Other seats",v=this.doc?.objects.find(f=>f.id===d),u=v&&"label"in v?v.label:m[0].label;return`<div class="slm-block-group"><div class="slm-block-grouphead"><button type="button" data-block-locate="${p(d)}" title="Show this row and nearby seats on the map"><b>${p(u)}</b><small>${p(g)} \xB7 ${m.length} blocked</small></button><button type="button" data-block-group="${p(d)}">Select row</button></div>
674
- <details><summary>Choose seats</summary>${m.map(f=>`<div class="slm-block-seatline"><button type="button" class="slm-blockeditem${i.has(f.label)?" on":""}" data-blocked-label="${p(f.label)}" aria-pressed="${i.has(f.label)}"><span class="slm-blockedcheck" aria-hidden="true">\u2713</span><span>${p(f.label)}</span></button><button type="button" data-block-seat-find="${p(f.label)}" aria-label="Show ${p(f.label)} and nearby seats">Show</button></div>`).join("")}</details></div>`}).join("")||'<div class="slm-blockedempty">No blocked seats match.</div>',r.size>this.blockedResultLimit&&(this.els.blockedlist.innerHTML+="<button data-blocked-more>Show more rows</button>");let c=this.els.markall,n=c.dataset.confirm==="true";c.disabled=e===0,c.textContent=n?`Confirm: put all ${e.toLocaleString()} on sale`:`Put all ${e.toLocaleString()} blocked seats on sale`}confirmUnblockAll(){let e=this.els.markall;if(!(!e||e.disabled)){if(e.dataset.confirm==="true"){this.resetUnblockAllConfirm(),this.unblockAll();return}e.dataset.confirm="true",e.classList.add("danger"),this.els.markallnote.textContent="This changes every blocked seat. Click the red button again to confirm.",this.paintBlockedInventory(),this.unblockAllConfirmTimer&&clearTimeout(this.unblockAllConfirmTimer),this.unblockAllConfirmTimer=setTimeout(()=>this.resetUnblockAllConfirm(),6e3)}}resetUnblockAllConfirm(){this.unblockAllConfirmTimer&&clearTimeout(this.unblockAllConfirmTimer),this.unblockAllConfirmTimer=null;let e=this.els.markall;e&&(delete e.dataset.confirm,e.classList.remove("danger"),this.els.markallnote&&(this.els.markallnote.textContent="For a full reset only. You will be asked to confirm."),this.paintBlockedInventory())}done(e,t,s){if(this.toastOk(s),t.length){let i=e==="block"?this.pushActivity(t,"blocked","blocked"):e==="unblock"||e==="unblockAll"?this.pushActivity(t,"unblocked","free"):e==="cancelBooking"?this.pushActivity(t,"cancelled","free"):null;i&&this.paintSpatialActivity(i)}e!=="setHoldTtl"&&this.refreshControlRoom().catch(i=>this.opts.onError?.(i)),this.opts.onActionComplete?.({action:e,labels:t,count:t.length})}toastOk(e){this.toast(e,"ok")}toastErr(e){this.toast(e,"err")}toast(e,t){let s=this.els.toast;s&&(s.textContent=e,s.className=`slm-toast on ${t}`,this.toastTimer&&clearTimeout(this.toastTimer),this.toastTimer=setTimeout(()=>{s.className="slm-toast"},3200))}fail(e){this.opts.onError?.(e),this.els.rail&&(this.els.rail.innerHTML=`<div class="slm-empty">Couldn't load this event. Check the event key and token.</div>`)}};export{we as ACCESS_LINK_DEFAULTS,$e as ChannelsMode,z as ManageApi,S as ManageApiError,le as PUBLIC_CHANNEL_ID,ne as PUBLIC_CHANNEL_NAME,F as SeatManager,xe as accessIntentDescription,ye as accessIntentLabel,fe as accessLine,Le as accessLinkBadge,Ce as accessLinkErrorCopy,Te as accessLinkIsLive,Me as accessLinkPolicyLines,ge as bucketRows,Ae as bucketRowsHtml,Ee as dropReviewRows,ke as intentForbidsCopy,Se as intentSwitchBlockedCopy,re as isPublicChannelId,ce as markerLetter,he as markerOf,ue as mutationCount,be as needsMoveConfirmation,me as planAssignment,ve as retryAfterCopy,pe as selectionSources,Re as stateBadge,de as suggestMarker};
895
+ `,this.els.rail.querySelectorAll("[data-block-tab]").forEach(l=>l.addEventListener("click",()=>{this.blockBrowse=l.dataset.blockTab==="browse",this.renderBlockRail()}));let s=l=>this.els.rail.querySelector(`[data-ref="${l}"]`);this.els.selnum=s("selnum"),this.els.doblock=s("doblock"),this.els.dounblock=s("dounblock"),this.els.selmeta=s("selmeta"),this.els.blockedcount=s("blockedcount"),this.els.blockedshowing=s("blockedshowing"),this.els.blockedlist=s("blockedlist"),this.els.selblocked=s("selblocked"),this.els.markall=s("markall"),this.els.markallnote=s("markallnote"),s("doblock").addEventListener("click",()=>{this.block()}),s("dounblock").addEventListener("click",()=>{this.unblock()}),s("selall").addEventListener("click",()=>this.selectAll()),s("clearsel").addEventListener("click",()=>this.clearSelection()),s("markall").addEventListener("click",()=>this.confirmUnblockAll()),e.wire(this.els.rail),this.wireMarqueeShapeChips();let i=s("blockedsearch"),o=s("blockedsection");i.value=this.blockedQuery,o.value=this.blockedSection,i.addEventListener("input",()=>{this.blockedQuery=i.value,this.blockedResultLimit=100,this.paintBlockedInventory()}),o.addEventListener("change",()=>{this.blockedSection=o.value,this.blockedResultLimit=100,this.paintBlockedInventory()}),s("selblocked").addEventListener("click",()=>{this.toggleLabels(this.filteredBlockedSeats().map(l=>l.label))}),s("blockedlist").addEventListener("click",l=>{let r=l.target,c=r.closest("[data-block-seat-find]");if(c?.dataset.blockSeatFind){let u=this.labelToSeat.get(c.dataset.blockSeatFind);u&&(this.setFollowLive(!1),this.focusActivitySeats([u.label],this.sectionByObject.get(u.rowId)??v));return}let d=r.closest("[data-block-locate]"),h=r.closest("[data-block-group]");if(d||h){let u=d?.dataset.blockLocate??h?.dataset.blockGroup,g=this.filteredBlockedSeats().filter(f=>f.rowId===u);d&&g.length&&(this.setFollowLive(!1),this.focusActivitySeats(g.map(f=>f.label),this.sectionByObject.get(g[0].rowId)??v)),h&&this.toggleLabels(g.map(f=>f.label));return}let p=r.closest("[data-blocked-label]");p?.dataset.blockedLabel?this.toggleLabels([p.dataset.blockedLabel]):r.closest("[data-blocked-more]")&&(this.blockedResultLimit+=100,this.paintBlockedInventory())});let a=s("release");a.addEventListener("change",()=>{let l=a.value?new Date(a.value).getTime():NaN;this.releaseAt=Number.isFinite(l)&&l>Date.now()?l:null;let r=s("releasenote");r.textContent=this.releaseAt?`New blocks auto-release ${new Date(this.releaseAt).toLocaleString()}.`:a.value?"Pick a time in the future.":"Leave empty to block permanently."}),this.paintSelBar(this.getSelection())}toggleLabels(e){if(!this.renderer)return;let t=e.filter(o=>this.labelToSeat.has(o)&&this.isBlockSelectable(o));if(!t.length)return;let s=new Set(this.selectionLabels());if(t.every(o=>s.has(o))){let o=t.map(a=>this.labelToId.get(a)).filter(a=>!!a);this.renderer.deselect(o)}else this.renderer.selectByLabels(t);this.syncSelection()}isBlockSelectable(e){let t=this.status.get(e)??"free";return t==="free"||t==="blocked"}paintSelBar(e){if(!this.els.selnum)return;this.els.selnum.textContent=e.length.toLocaleString();let t=e.filter(a=>(this.status.get(a.label)??"free")==="free").length,s=e.filter(a=>this.status.get(a.label)==="blocked").length;this.els.selmeta.textContent=e.length?`${t.toLocaleString()} available \xB7 ${s.toLocaleString()} blocked`:"selected";let i=this.els.doblock,o=this.els.dounblock;i.disabled=t===0,o.disabled=s===0,i.textContent=t?`Block ${t.toLocaleString()}`:"Block selected",o.textContent=s?`Put ${s.toLocaleString()} on sale`:"Put back on sale",this.paintBlockedInventory()}filteredBlockedSeats(){let e=this.blockedQuery.trim().toLocaleLowerCase(),t=[];for(let[s,i]of this.labelToSeat.entries()){if(this.status.get(s)!=="blocked")continue;let o=this.sectionByObject.get(i.rowId)??v;if(!(this.blockedSection&&o!==this.blockedSection)){if(e){let a=this.doc?.categories.find(h=>h.key===i.categoryKey)?.label??i.categoryKey,l=this.sectionLabelById.get(o)??"Other seats",r=this.doc?.objects.find(h=>h.id===i.rowId),c=r?.type==="row"||r?.type==="table"?r.label:"";if(!`${s} ${a} ${l} ${c}`.toLocaleLowerCase().includes(e))continue}t.push(i)}}return t.sort((s,i)=>s.label.localeCompare(i.label,void 0,{numeric:!0,sensitivity:"base"}))}paintBlockedInventory(){if(!this.els.blockedlist)return;let e=[...this.status.entries()].filter(([,h])=>h==="blocked").length,t=this.filteredBlockedSeats(),s=t.slice(0,this.blockedResultLimit),i=new Set(this.selectionLabels()),o=t.filter(h=>i.has(h.label)).length,a=t.length>0&&o===t.length;this.els.blockedcount.textContent=e.toLocaleString(),this.els.blockedshowing.textContent=t.length?`Showing ${s.length.toLocaleString()} of ${t.length.toLocaleString()}`:e?"No matches":"No blocked seats";let l=this.els.selblocked;l.disabled=t.length===0,l.textContent=a?`Remove ${t.length.toLocaleString()} results`:`Select ${t.length.toLocaleString()} results`;let r=new Map;for(let h of t){let p=r.get(h.rowId)??[];p.push(h),r.set(h.rowId,p)}this.els.blockedshowing.textContent=`${t.length.toLocaleString()} seats \xB7 ${r.size} rows`,this.els.blockedlist.innerHTML=[...r.entries()].slice(0,this.blockedResultLimit).map(([h,p])=>{let u=this.sectionByObject.get(h)??v,g=this.sectionLabelById.get(u)??"Other seats",f=this.doc?.objects.find(y=>y.id===h),b=f&&"label"in f?f.label:p[0].label;return`<div class="slm-block-group"><div class="slm-block-grouphead"><button type="button" data-block-locate="${m(h)}" title="Show this row and nearby seats on the map"><b>${m(b)}</b><small>${m(g)} \xB7 ${p.length} blocked</small></button><button type="button" data-block-group="${m(h)}">Select row</button></div>
896
+ <details><summary>Choose seats</summary>${p.map(y=>`<div class="slm-block-seatline"><button type="button" class="slm-blockeditem${i.has(y.label)?" on":""}" data-blocked-label="${m(y.label)}" aria-pressed="${i.has(y.label)}"><span class="slm-blockedcheck" aria-hidden="true">\u2713</span><span>${m(y.label)}</span></button><button type="button" data-block-seat-find="${m(y.label)}" aria-label="Show ${m(y.label)} and nearby seats">Show</button></div>`).join("")}</details></div>`}).join("")||'<div class="slm-blockedempty">No blocked seats match.</div>',r.size>this.blockedResultLimit&&(this.els.blockedlist.innerHTML+="<button data-blocked-more>Show more rows</button>");let c=this.els.markall,d=c.dataset.confirm==="true";c.disabled=e===0,c.textContent=d?`Confirm: put all ${e.toLocaleString()} on sale`:`Put all ${e.toLocaleString()} blocked seats on sale`}confirmUnblockAll(){let e=this.els.markall;if(!(!e||e.disabled)){if(e.dataset.confirm==="true"){this.resetUnblockAllConfirm(),this.unblockAll();return}e.dataset.confirm="true",e.classList.add("danger"),this.els.markallnote.textContent="This changes every blocked seat. Click the red button again to confirm.",this.paintBlockedInventory(),this.unblockAllConfirmTimer&&clearTimeout(this.unblockAllConfirmTimer),this.unblockAllConfirmTimer=setTimeout(()=>this.resetUnblockAllConfirm(),6e3)}}resetUnblockAllConfirm(){this.unblockAllConfirmTimer&&clearTimeout(this.unblockAllConfirmTimer),this.unblockAllConfirmTimer=null;let e=this.els.markall;e&&(delete e.dataset.confirm,e.classList.remove("danger"),this.els.markallnote&&(this.els.markallnote.textContent="For a full reset only. You will be asked to confirm."),this.paintBlockedInventory())}done(e,t,s){if(this.toastOk(s),t.length){let i=e==="block"?this.pushActivity(t,"blocked","blocked"):e==="unblock"||e==="unblockAll"?this.pushActivity(t,"unblocked","free"):e==="cancelBooking"?this.pushActivity(t,"cancelled","free"):null;i&&this.paintSpatialActivity(i)}e!=="setHoldTtl"&&this.refreshControlRoom().catch(i=>this.opts.onError?.(i)),this.opts.onActionComplete?.({action:e,labels:t,count:t.length})}toastOk(e){this.toast(e,"ok")}toastErr(e){this.toast(e,"err")}toast(e,t){let s=this.els.toast;s&&(s.textContent=e,s.className=`slm-toast on ${t}`,this.toastTimer&&clearTimeout(this.toastTimer),this.toastTimer=setTimeout(()=>{s.className="slm-toast"},3200))}fail(e){this.opts.onError?.(e),this.els.rail&&(this.els.rail.innerHTML=`<div class="slm-empty">Couldn't load this event. Check the event key and token.</div>`)}};export{Xe as ACCESS_LINK_DEFAULTS,at as ChannelsMode,F as ManageApi,k as ManageApiError,ze as PUBLIC_CHANNEL_ID,Ie as PUBLIC_CHANNEL_NAME,q as SeatManager,Ge as accessIntentDescription,We as accessIntentLabel,Ue as accessLine,Qe as accessLinkBadge,tt as accessLinkErrorCopy,Je as accessLinkIsLive,et as accessLinkPolicyLines,_e as bucketRows,ot as bucketRowsHtml,st as dropReviewRows,Ze as intentForbidsCopy,Ye as intentSwitchBlockedCopy,Fe as isPublicChannelId,Oe as markerLetter,Ve as markerOf,qe as mutationCount,Ne as needsMoveConfirmation,je as planAssignment,Ke as retryAfterCopy,Pe as selectionSources,it as stateBadge,De as suggestMarker};