@seatlayer/js 0.90.0 → 0.92.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.cjs CHANGED
@@ -1,49 +1,63 @@
1
- "use strict";var Me=Object.defineProperty;var It=Object.getOwnPropertyDescriptor;var Ht=Object.getOwnPropertyNames;var Pt=Object.prototype.hasOwnProperty;var j=(l,e,t)=>()=>{if(t)throw t[0];try{return l&&(e=l(l=0)),e}catch(s){throw t=[s],s}};var Ue=(l,e)=>{for(var t in e)Me(l,t,{get:e[t],enumerable:!0})},Bt=(l,e,t,s)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of Ht(e))!Pt.call(l,n)&&n!==t&&Me(l,n,{get:()=>e[n],enumerable:!(s=It(e,n))||s.enumerable});return l};var Dt=l=>Bt(Me({},"__esModule",{value:!0}),l);function ne(l){l.querySelectorAll("select:not([data-themed])").forEach(e=>{e.dataset.themed="true";let t=document.createElement("details");t.className="slm-themed-picker";let s=document.createElement("summary"),n=document.createElement("div");n.className="slm-themed-options";let i=e.getAttribute("aria-label")||Array.from(e.labels??[]).map(o=>o.textContent).join(" ")||"Choose option";s.setAttribute("aria-label",i.trim()),t.append(s,n),e.after(t),e.hidden=!0;let a=()=>{s.textContent=e.selectedOptions[0]?.textContent??"Choose\u2026",s.setAttribute("aria-disabled",String(e.disabled)),n.replaceChildren(...Array.from(e.options).map(o=>{let r=document.createElement("button");return r.type="button",r.textContent=o.textContent,r.setAttribute("aria-label",o.textContent??""),r.disabled=e.disabled||o.disabled,r.setAttribute("aria-pressed",String(o.selected)),r.onclick=()=>{e.value=o.value,t.open=!1,a(),s.focus(),e.dispatchEvent(new Event("change",{bubbles:!0})),a()},r}))};a(),e.addEventListener("change",a),s.onclick=o=>{if(e.disabled){o.preventDefault();return}a(),l.querySelectorAll(".slm-themed-picker").forEach(r=>{r!==t&&(r.open=!1)})},t.addEventListener("focusout",o=>{t.contains(o.relatedTarget)||(t.open=!1)}),t.addEventListener("keydown",o=>{if(o.key==="Escape"&&(o.preventDefault(),o.stopPropagation(),t.open=!1,s.focus()),o.key==="ArrowDown"||o.key==="ArrowUp"){if(e.disabled)return;o.preventDefault(),t.open=!0;let r=Array.from(n.querySelectorAll("button:not(:disabled)")),c=r.indexOf(document.activeElement);r[(c+(o.key==="ArrowDown"?1:r.length-1)+r.length)%r.length]?.focus()}})})}var Ie=j(()=>{"use strict"});async function We(l){let t=(l.headers.get("content-type")??"").includes("application/json")?await l.json().catch(()=>null):null;if(!l.ok){let s=t;throw new y(l.status,s?.error??`request_failed_${l.status}`,s?.code,s?.conflicts,s?.details,typeof s?.message=="string"?s.message:void 0)}return t}function E(l){return l&&typeof l=="object"?l:{}}function le(l,e,t=0){return typeof l=="number"&&Number.isFinite(l)?l:typeof e=="number"&&Number.isFinite(e)?e:t}function Xe(l,e){return l===null?null:typeof l=="number"&&Number.isFinite(l)?l:l!==void 0?null:typeof e=="number"&&Number.isFinite(e)?e:null}function Ge(l){let e=E(l),t=le(e.bookedValue,e.bookedRevenue);return{...e,bookedValue:t,bookedRevenue:t}}function zt(l){let e=E(l),t=E(e.report),s=Array.isArray(t.byCategory)?t.byCategory.map(i=>{let a=E(i),o=le(a.bookedValue,a.bookedRevenue);return{...a,bookedValue:o,bookedRevenue:o}}):[],n=Array.isArray(t.bySection)?t.bySection.map(Ge):void 0;return{...e,report:{...t,byCategory:s,...n?{bySection:n}:{}}}}function Ft(l){let e=E(l),t=E(e.bookedValue),s=E(e.revenue),n=Object.keys(t).length?t:s,i=Array.isArray(t.bySection)?t.bySection:Array.isArray(s.bySection)?s.bySection:[],a={...n,gross:le(t.gross,s.gross),bySection:i.map(Ge)},o=E(e.velocity),r=Array.isArray(o.bySection)?o.bySection.map(c=>{let d=E(c),h=le(d.bookedValue,d.grossRevenue);return{...d,bookedValue:h,grossRevenue:h}}):[];return{...e,bookedValue:a,revenue:a,velocity:{...o,bySection:r}}}function qt(l){let e=E(l),t=E(e.report),s=typeof t.includesBookedValue=="boolean"?t.includesBookedValue:t.includesRevenue===!0,n=Array.isArray(t.rows)?t.rows.map(o=>{let r=E(o),c=E(r.attribution),d=Xe(c.bookedValue,c.revenue);return{...r,attribution:{...c,bookedValue:d,revenue:d}}}):[],i=E(t.totals),a=Xe(i.bookedValue,i.revenue);return{...e,report:{...t,includesBookedValue:s,includesRevenue:s,rows:n,totals:{...i,bookedValue:a,revenue:a}}}}function He(l){let e=E(l),t=typeof e.includesBookedValue=="boolean"?e.includesBookedValue:e.includesRevenue===!0;return{...e,includesBookedValue:t,includesRevenue:t}}var y,U,re=j(()=>{"use strict";y=class extends Error{constructor(e,t,s,n,i,a){super(t),this.name="ManageApiError",this.status=e,this.code=s,this.conflicts=n,this.details=i,this.serverMessage=a}};U=class{constructor(e,t){this.base=e.replace(/\/+$/,""),this.token=t}setToken(e){this.token=e}auth(e,t={}){let s=t.method??"GET",n={Authorization:`Bearer ${this.token}`},i;return t.body!==void 0&&(n["Content-Type"]="application/json",i=JSON.stringify(t.body)),fetch(`${this.base}${e}`,{method:s,headers:n,body:i,credentials:"omit"}).then(a=>We(a))}async authBlob(e){let t=await fetch(`${this.base}${e}`,{method:"GET",headers:{Authorization:`Bearer ${this.token}`},credentials:"omit"});return t.ok||await We(t),t.blob()}chart(e){return this.auth(`/v1/events/${encodeURIComponent(e)}/chart`)}asset(e,t){return/^[a-zA-Z0-9._-]+$/.test(t)?this.authBlob(`/v1/events/${encodeURIComponent(e)}/assets/${encodeURIComponent(t)}`):Promise.reject(new y(404,"not_found","not_found"))}objects(e){return this.auth(`/v1/events/${encodeURIComponent(e)}/objects`)}subscribeTicket(e){return this.auth(`/v1/events/${encodeURIComponent(e)}/subscribe-tickets`,{method:"POST"})}socketUrl(e){return`${this.base.replace(/^http/,"ws")}/pub/events/${encodeURIComponent(e)}/subscribe?surface=manager`}block(e,t,s={}){let n={labels:t};return typeof s.releaseAt=="number"&&(n.releaseAt=s.releaseAt),s.reason&&(n.reason=s.reason),this.auth(`/v1/events/${encodeURIComponent(e)}/block`,{method:"POST",body:n})}unblock(e,t){return this.auth(`/v1/events/${encodeURIComponent(e)}/unblock`,{method:"POST",body:{labels:t}})}unblockAll(e){return this.auth(`/v1/events/${encodeURIComponent(e)}/unblock-all`,{method:"POST"})}unbook(e,t,s){return this.auth(`/v1/events/${encodeURIComponent(e)}/unbook`,{method:"POST",body:{labels:t,bookingRef:s}})}setHoldTtl(e,t){return this.auth(`/v1/events/${encodeURIComponent(e)}/hold-ttl`,{method:"POST",body:{holdTtlMs:t}})}setCategory(e,t,s){return this.auth(`/v1/events/${encodeURIComponent(e)}/category-assignments`,{method:"POST",body:{labels:t,categoryKey:s}})}setTableBooking(e,t,s,n={}){return this.auth(`/v1/events/${encodeURIComponent(e)}/table-booking`,{method:"POST",body:{tableIds:t,mode:s,...n}})}bookings(e,t={}){let s=new URLSearchParams;t.q&&s.set("q",t.q),t.state&&s.set("state",t.state),t.cursor&&s.set("cursor",t.cursor),t.limit!=null&&s.set("limit",String(t.limit));let n=s.toString();return this.auth(`/v1/events/${encodeURIComponent(e)}/bookings${n?`?${n}`:""}`)}booking(e,t){return this.auth(`/v1/events/${encodeURIComponent(e)}/bookings/${encodeURIComponent(t)}`)}listBookings(e,t={}){return this.bookings(e,t)}retrieveBooking(e,t){return this.booking(e,t)}availability(e){return this.auth(`/v1/events/${encodeURIComponent(e)}/availability`)}setAvailability(e,t){return this.auth(`/v1/events/${encodeURIComponent(e)}/availability`,{method:"POST",body:{rules:t}})}channels(e,t={}){let s=t.includeArchived?"?includeArchived=1":"";return this.auth(`/v1/events/${encodeURIComponent(e)}/channels${s}`)}channelAllocation(e,t={}){let s=new URLSearchParams;t.afterLabel&&s.set("afterLabel",t.afterLabel),t.limit!=null&&s.set("limit",String(t.limit));let n=s.toString();return this.auth(`/v1/events/${encodeURIComponent(e)}/channels/allocation${n?`?${n}`:""}`)}channelAudit(e,t={}){let s=new URLSearchParams;t.limit!=null&&s.set("limit",String(t.limit)),t.before!=null&&s.set("before",String(t.before));let n=s.toString();return this.auth(`/v1/events/${encodeURIComponent(e)}/channels/audit${n?`?${n}`:""}`)}createChannel(e,t){return this.auth(`/v1/events/${encodeURIComponent(e)}/channels`,{method:"POST",body:t})}renameChannel(e,t,s){return this.auth(`/v1/events/${encodeURIComponent(e)}/channels/${encodeURIComponent(t)}`,{method:"PATCH",body:{name:s}})}updateChannelPricing(e,t,s,n){return this.auth(`/v1/events/${encodeURIComponent(e)}/channels/${encodeURIComponent(t)}`,{method:"PATCH",body:{priceOverrides:s,expectedPricingVersion:n}})}setChannelPaused(e,t,s){let n=s?"pause":"unpause";return this.auth(`/v1/events/${encodeURIComponent(e)}/channels/${encodeURIComponent(t)}/${n}`,{method:"POST",body:{}})}archiveChannel(e,t,s){return this.auth(`/v1/events/${encodeURIComponent(e)}/channels/${encodeURIComponent(t)}/archive`,{method:"POST",body:{destination:s}})}applyChannelAssignment(e,t){return this.auth(`/v1/events/${encodeURIComponent(e)}/channels/assignments`,{method:"POST",body:{targetChannelId:t.targetChannelId||null,labels:t.labels,assignmentVersion:t.assignmentVersion}})}channelPreview(e,t,s={}){let n=new URLSearchParams;t.length&&n.set("channelIds",t.join(",")),s.includePublic!=null&&n.set("includePublic",s.includePublic?"1":"0");let i=n.toString();return this.auth(`/v1/events/${encodeURIComponent(e)}/channels/preview${i?`?${i}`:""}`)}setChannelAccessIntent(e,t,s,n={}){return this.auth(`/v1/events/${encodeURIComponent(e)}/channels/${encodeURIComponent(t)}`,{method:"PATCH",body:{accessIntent:s,...n.acknowledgeLiveAccess?{acknowledgeLiveAccess:!0}:{},...n.reason?{reason:n.reason}:{}}})}createAccessLink(e,t,s={}){return this.auth(`/v1/events/${encodeURIComponent(e)}/channels/${encodeURIComponent(t)}/access-links`,{method:"POST",body:s})}accessLinks(e,t){return this.auth(`/v1/events/${encodeURIComponent(e)}/channels/${encodeURIComponent(t)}/access-links`)}rotateAccessLink(e,t,s,n){return this.auth(`/v1/events/${encodeURIComponent(e)}/channels/${encodeURIComponent(t)}/access-links/${encodeURIComponent(s)}/rotate`,{method:"POST",body:{endActiveSessions:n}})}revokeAccessLink(e,t,s,n=!1){let i=n?"?endActiveSessions=1":"";return this.auth(`/v1/events/${encodeURIComponent(e)}/channels/${encodeURIComponent(t)}/access-links/${encodeURIComponent(s)}${i}`,{method:"DELETE"})}report(e){return this.auth(`/v1/events/${encodeURIComponent(e)}/report`).then(zt)}seatHistory(e,t,s,n){let i=new URLSearchParams({label:t});return s&&i.set("before",String(s)),n&&i.set("action",n),this.auth(`/v1/events/${encodeURIComponent(e)}/seat-history?${i}`)}controlRoom(e,t=15){return this.auth(`/v1/events/${encodeURIComponent(e)}/control-room?window=${t}`).then(Ft)}channelReport(e){return this.auth(`/v1/events/${encodeURIComponent(e)}/channels/report`).then(qt)}createChannelReportLink(e,t,s={}){return this.auth(`/v1/events/${encodeURIComponent(e)}/channels/${encodeURIComponent(t)}/report-links`,{method:"POST",body:s}).then(n=>{let i=E(n);return{...i,link:He(i.link)}})}channelReportLinks(e,t){return this.auth(`/v1/events/${encodeURIComponent(e)}/channels/${encodeURIComponent(t)}/report-links`).then(s=>{let n=E(s);return{links:Array.isArray(n.links)?n.links.map(He):[]}})}revokeChannelReportLink(e,t,s){return this.auth(`/v1/events/${encodeURIComponent(e)}/channels/${encodeURIComponent(t)}/report-links/${encodeURIComponent(s)}`,{method:"DELETE"}).then(n=>{let i=E(n);return{...i,link:He(i.link)}})}log(e,t={}){let s=new URLSearchParams;t.limit!=null&&s.set("limit",String(t.limit)),t.before!=null&&s.set("before",String(t.before));let n=s.toString();return this.auth(`/v1/events/${encodeURIComponent(e)}/log${n?`?${n}`:""}`)}async reportCsv(e){let t=await fetch(`${this.base}/v1/events/${encodeURIComponent(e)}/report.csv`,{headers:{Authorization:`Bearer ${this.token}`},credentials:"omit"});if(!t.ok)throw new y(t.status,`request_failed_${t.status}`);return t.blob()}}});function B(l){return l==null||l===""||l===T}function z(l,e){let t=(l??"").trim();return((/\p{L}/u.exec(t)?.[0]??t[0]??"")||e).toUpperCase().slice(0,1)}function Q(l,e){let t=new Set([...e].map(i=>z(i,"")).filter(Boolean)),s=z(l,"");return{letter:ut.includes(s)&&!t.has(s)?s:[...ut].find(i=>!t.has(i))??(s||"X"),color:be[t.size%be.length]}}function ge(l,e=0){return B(l.id)?{letter:z(l.marker,"P"),color:l.color||Kt}:{letter:z(l.marker||l.name,"?"),color:l.color||be[e%be.length]}}function ve(l,e,t){let s=new Map;for(let a of l){let o=Fe(e.get(a));s.set(o,(s.get(o)??0)+1)}let n=[{id:T,name:t?.publicSale?.name??A},...(t?.channels??[]).map(a=>({id:a.id,name:a.name}))],i=[];for(let a of n){let o=s.get(a.id);o&&i.push({channelId:a.id,name:a.name,count:o}),s.delete(a.id)}for(let[a,o]of s)i.push({channelId:a,name:B(a)?A:"Another channel",count:o});return i}function Fe(l){return B(l)?T:l}function ze(l){return{count:l.length,labels:l.slice(0,bt),truncated:l.length>bt}}function fe(l){let{labels:e,allocation:t,statusOf:s,nameOf:n}=l,i=Fe(l.targetChannelId),a=new Set,o=0,r=0,c=new Map,d=[],h=[],u=[];for(let v of e){if(a.has(v))continue;a.add(v);let g=s(v);if(!g){u.push(v);continue}let m=Fe(t.get(v));if(m===i){r+=1;continue}if(g==="held"){d.push(v);continue}if(g==="booked"){h.push(v);continue}m===T?o+=1:c.set(m,(c.get(m)??0)+1)}let f=[...c.entries()].map(([v,g])=>({channelId:v,name:n(v),count:g}));return{changedFromPublic:{count:o},movedFromOtherChannel:{count:f.reduce((v,g)=>v+g.count,0),channels:f},alreadyInTarget:{count:r},skippedHeld:ze(d),skippedBooked:ze(h),notFound:ze(u)}}function K(l){return l.changedFromPublic.count+l.movedFromOtherChannel.count}function ye(l){return l.movedFromOtherChannel.count>0}function ke(l,e){let t=[];l.changedFromPublic.count&&t.push({kind:"add",icon:"+",count:l.changedFromPublic.count,text:`${l.changedFromPublic.count.toLocaleString()} from ${A}`});for(let s of l.movedFromOtherChannel.channels)t.push({kind:"move",icon:"\u21C4",count:s.count,text:`${s.count.toLocaleString()} moved out of ${s.name??"another channel"}`,why:"needs this confirmation"});return l.alreadyInTarget.count&&t.push({kind:"same",icon:"=",count:l.alreadyInTarget.count,text:`${l.alreadyInTarget.count.toLocaleString()} already in ${e}`,why:"unchanged"}),l.skippedHeld.count&&t.push({kind:"skip",icon:"\u23F8",count:l.skippedHeld.count,text:`${l.skippedHeld.count.toLocaleString()} in a buyer's checkout`,why:"can't move while held",peek:ue(l.skippedHeld)}),l.skippedBooked.count&&t.push({kind:"skip",icon:"\u{1F512}",count:l.skippedBooked.count,text:`${l.skippedBooked.count.toLocaleString()} already sold`,why:"sales are never rewritten",peek:ue(l.skippedBooked)}),l.notFound.count&&t.push({kind:"skip",icon:"?",count:l.notFound.count,text:`${l.notFound.count.toLocaleString()} not on this map`,why:"these seats are no longer part of the event",peek:ue(l.notFound)}),t}function ue(l){if(!l.labels.length)return;let e=l.labels.slice(0,4).join(", ");return l.truncated||l.labels.length>4?`${e}\u2026`:e}function xe(l){let e=l?.retryAfterMs??(l?.latestHoldExpiresAt?Math.max(0,l.latestHoldExpiresAt-Date.now()):0);if(!e)return"in a moment";let t=Math.ceil(e/6e4);return t<=1?"in about a minute":`in about ${t} minutes`}function we(l){if(!l||!l.intent)return"\u2014";let e=l.intent==="server"?"Website integration":l.intent==="hosted_link"?"Buyer link":l.intent==="internal"?"Your staff sell these":"Protected reserve",t=l.hasActiveGrants?"in use now":l.lastMintAt?`last used ${new Date(l.lastMintAt).toLocaleDateString()}`:null,s=l.detail??t;return s?`${e} \xB7 ${s}`:e}function F(l){return l==="internal"?"Sell through your own staff":l==="server"?"Integrate a website or app":l==="hosted_link"?"Sell with a buyer link":"Keep as protected reserve"}function Se(l){switch(l){case"internal":return"Only your own box office can sell these seats, through your secret key. Buyer links and website integrations are refused.";case"server":return"Your website's backend mints each buyer a short-lived session for these seats. Buyer links are refused; the code lives on the Embed page.";case"hosted_link":return"SeatLayer makes a link you send to a named group. They open it and buy only these seats. No other route can sell them.";default:return"Nobody can buy these seats. Every way of letting a buyer in \u2014 a buyer link, your website, even your own staff \u2014 is refused while this is the route. The seats stay out of public sale."}}function Yt(l){return l==="hosted_link"?"hosted_link":l==="server"?"server":l==="staff"?"internal":null}function Y(l){let e=qe(l?.accessIntent),t=Yt(l?.route),s=`This channel is set to "${F(e)}"`;return t?`${s}, so it cannot do that. Switch it to "${F(t)}" first.`:`${s}, so it cannot do that. Choose a different route for this channel first.`}function qe(l){return l==="internal"||l==="server"||l==="hosted_link"||l==="none"?l:"none"}function me(l,e,t){return`${l.toLocaleString()} ${l===1?e:t}`}function Le(l){let e=Math.max(0,l?.liveAccessLinks??0),t=Math.max(0,l?.activeSessions??0),s=qe(l?.from),n=qe(l?.to),a=`${[e?me(e,"buyer link is live","buyer links are live"):null,t?me(t,"buyer is in a checkout","buyers are in a checkout"):null].filter(Boolean).join(", and ")||"Buyers are inside this channel"} on "${F(s)}". Moving it to "${F(n)}" changes what happens to them.`,o=[];return e&&o.push(`${me(e,"buyer link closes","buyer links close")} immediately. Anyone who has not opened it yet never will \u2014 send a new link if you still need one.`),t&&o.push(`${me(t,"buyer who is already in a checkout keeps","buyers who are already in a checkout keep")} their seats and can finish paying. Nobody is thrown out. No new buyers come in this way, so the old route empties on its own within 12 hours.`),{headline:a,consequences:o}}function Ce(l){switch(l.status??l.state){case"active":return{text:"Active",kind:"active"};case"expired":return{text:"Expired",kind:"archived"};case"exhausted":return{text:"All used",kind:"paused"};case"rotated":return{text:"Replaced",kind:"archived"};default:return{text:"Revoked",kind:"archived"}}}function ee(l){return l.state==="active"&&l.status==="active"}function Wt(l){return Number.isFinite(l)?new Date(l).toLocaleString(void 0,{day:"numeric",month:"short",year:"numeric",hour:"numeric",minute:"2-digit"}):"\u2014"}function te(l){return[{k:"Expires",v:Wt(l.expiresAt)},{k:"Redemptions",v:`${l.redemptions.toLocaleString()} of ${l.maxRedemptions.toLocaleString()} used`},{k:"Seats per buyer",v:`${l.maxQuantity.toLocaleString()} seat${l.maxQuantity===1?"":"s"} maximum`},{k:"Covers",v:l.includePublic?"This channel's allocation and Public sale seats":"This channel's allocation only"}]}function N(l){let e=l?.serverMessage?.trim();switch(l?.code){case"invalid_expiry":case"invalid_max_redemptions":case"invalid_max_quantity":case"invalid_session_ttl":case"invalid_label":return e||"That setting is outside what a hosted link allows. Adjust it and try again.";case"too_many_access_links":return e||"This channel already has as many live links as it can hold. Revoke one before creating another.";case"access_link_not_active":return"That link is no longer active, so it cannot be rotated or revoked.";case"channel_unavailable":return"This channel is paused or archived, so it cannot let new buyers in. Resume it first.";case"channel_access_intent_forbids":return Y(l?.details);case"end_active_sessions_required":return"Choose what happens to the buyers who already came in through this link.";case"not_found":return"That link is no longer here. Refresh and try again.";default:return l?.status===403?"Hosted access links need channel-management permission.":e||"That did not go through. Try again."}}function gt(l){return(l?.channels??[]).map(e=>({kind:"skip",icon:"\u26A0",count:e.count,text:`${e.count.toLocaleString()} would leave ${e.name??"a channel"}`,why:"the new chart no longer has these seats",peek:e.labels?.length?ue({count:e.count,labels:e.labels,truncated:e.truncated??!1}):void 0}))}function Te(l){return l==="builtin"?"Built-in":l==="active"?"Active":l==="paused"?"Paused":"Archived"}var T,A,be,Kt,ut,bt,J,Re=j(()=>{"use strict";T="public",A="Public sale";be=["#a78bfa","#2dd4bf","#fb923c","#60a5fa","#f472b6","#a3e635","#f87171","#38bdf8","#c084fc","#facc15"],Kt="#f4b740",ut="ABCDEFGHJKLMNPQRSTUVWXYZ";bt=12;J={maxRedemptions:100,maxQuantity:4}});function W(l){return l.map((e,t)=>`
1
+ "use strict";var He=Object.defineProperty;var zt=Object.getOwnPropertyDescriptor;var Ft=Object.getOwnPropertyNames;var qt=Object.prototype.hasOwnProperty;var _=(l,e,t)=>()=>{if(t)throw t[0];try{return l&&(e=l(l=0)),e}catch(s){throw t=[s],s}};var Ke=(l,e)=>{for(var t in e)He(l,t,{get:e[t],enumerable:!0})},Nt=(l,e,t,s)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of Ft(e))!qt.call(l,n)&&n!==t&&He(l,n,{get:()=>e[n],enumerable:!(s=zt(e,n))||s.enumerable});return l};var _t=l=>Nt(He({},"__esModule",{value:!0}),l);function ie(l){l.querySelectorAll("select:not([data-themed])").forEach(e=>{e.dataset.themed="true";let t=document.createElement("details");t.className="slm-themed-picker";let s=document.createElement("summary"),n=document.createElement("div");n.className="slm-themed-options";let i=e.getAttribute("aria-label")||Array.from(e.labels??[]).map(o=>o.textContent).join(" ")||"Choose option";s.setAttribute("aria-label",i.trim()),t.append(s,n),e.after(t),e.hidden=!0;let a=()=>{s.textContent=e.selectedOptions[0]?.textContent??"Choose\u2026",s.setAttribute("aria-disabled",String(e.disabled)),n.replaceChildren(...Array.from(e.options).map(o=>{let r=document.createElement("button");return r.type="button",r.textContent=o.textContent,r.setAttribute("aria-label",o.textContent??""),r.disabled=e.disabled||o.disabled,r.setAttribute("aria-pressed",String(o.selected)),r.onclick=()=>{e.value=o.value,t.open=!1,a(),s.focus(),e.dispatchEvent(new Event("change",{bubbles:!0})),a()},r}))};a(),e.addEventListener("change",a),s.onclick=o=>{if(e.disabled){o.preventDefault();return}a(),l.querySelectorAll(".slm-themed-picker").forEach(r=>{r!==t&&(r.open=!1)})},t.addEventListener("focusout",o=>{t.contains(o.relatedTarget)||(t.open=!1)}),t.addEventListener("keydown",o=>{if(o.key==="Escape"&&(o.preventDefault(),o.stopPropagation(),t.open=!1,s.focus()),o.key==="ArrowDown"||o.key==="ArrowUp"){if(e.disabled)return;o.preventDefault(),t.open=!0;let r=Array.from(n.querySelectorAll("button:not(:disabled)")),d=r.indexOf(document.activeElement);r[(d+(o.key==="ArrowDown"?1:r.length-1)+r.length)%r.length]?.focus()}})})}var Pe=_(()=>{"use strict"});async function We(l){let t=(l.headers.get("content-type")??"").includes("application/json")?await l.json().catch(()=>null):null;if(!l.ok){let s=t;throw new x(l.status,s?.error??`request_failed_${l.status}`,s?.code,s?.conflicts,s?.details,typeof s?.message=="string"?s.message:void 0)}return t}function $(l){return l&&typeof l=="object"?l:{}}function re(l,e,t=0){return typeof l=="number"&&Number.isFinite(l)?l:typeof e=="number"&&Number.isFinite(e)?e:t}function Xe(l,e){return l===null?null:typeof l=="number"&&Number.isFinite(l)?l:l!==void 0?null:typeof e=="number"&&Number.isFinite(e)?e:null}function Ze(l){let e=$(l),t=re(e.bookedValue,e.bookedRevenue);return{...e,bookedValue:t,bookedRevenue:t}}function Vt(l){let e=$(l),t=$(e.report),s=Array.isArray(t.byCategory)?t.byCategory.map(i=>{let a=$(i),o=re(a.bookedValue,a.bookedRevenue);return{...a,bookedValue:o,bookedRevenue:o}}):[],n=Array.isArray(t.bySection)?t.bySection.map(Ze):void 0;return{...e,report:{...t,byCategory:s,...n?{bySection:n}:{}}}}function Ut(l){let e=$(l),t=$(e.bookedValue),s=$(e.revenue),n=Object.keys(t).length?t:s,i=Array.isArray(t.bySection)?t.bySection:Array.isArray(s.bySection)?s.bySection:[],a={...n,gross:re(t.gross,s.gross),bySection:i.map(Ze)},o=$(e.velocity),r=Array.isArray(o.bySection)?o.bySection.map(d=>{let c=$(d),h=re(c.bookedValue,c.grossRevenue);return{...c,bookedValue:h,grossRevenue:h}}):[];return{...e,bookedValue:a,revenue:a,velocity:{...o,bySection:r}}}function Kt(l){let e=$(l),t=$(e.report),s=typeof t.includesBookedValue=="boolean"?t.includesBookedValue:t.includesRevenue===!0,n=Array.isArray(t.rows)?t.rows.map(o=>{let r=$(o),d=$(r.attribution),c=Xe(d.bookedValue,d.revenue);return{...r,attribution:{...d,bookedValue:c,revenue:c}}}):[],i=$(t.totals),a=Xe(i.bookedValue,i.revenue);return{...e,report:{...t,includesBookedValue:s,includesRevenue:s,rows:n,totals:{...i,bookedValue:a,revenue:a}}}}function Be(l){let e=$(l),t=typeof e.includesBookedValue=="boolean"?e.includesBookedValue:e.includesRevenue===!0;return{...e,includesBookedValue:t,includesRevenue:t}}var x,K,ce=_(()=>{"use strict";x=class extends Error{constructor(e,t,s,n,i,a){super(t),this.name="ManageApiError",this.status=e,this.code=s,this.conflicts=n,this.details=i,this.serverMessage=a}};K=class{constructor(e,t){this.base=e.replace(/\/+$/,""),this.token=t}setToken(e){this.token=e}auth(e,t={}){let s=t.method??"GET",n={Authorization:`Bearer ${this.token}`},i;return t.body!==void 0&&(n["Content-Type"]="application/json",i=JSON.stringify(t.body)),fetch(`${this.base}${e}`,{method:s,headers:n,body:i,credentials:"omit"}).then(a=>We(a))}async authBlob(e){let t=await fetch(`${this.base}${e}`,{method:"GET",headers:{Authorization:`Bearer ${this.token}`},credentials:"omit"});return t.ok||await We(t),t.blob()}chart(e){return this.auth(`/v1/events/${encodeURIComponent(e)}/chart`)}asset(e,t){return/^[a-zA-Z0-9._-]+$/.test(t)?this.authBlob(`/v1/events/${encodeURIComponent(e)}/assets/${encodeURIComponent(t)}`):Promise.reject(new x(404,"not_found","not_found"))}objects(e){return this.auth(`/v1/events/${encodeURIComponent(e)}/objects`)}subscribeTicket(e){return this.auth(`/v1/events/${encodeURIComponent(e)}/subscribe-tickets`,{method:"POST"})}socketUrl(e){return`${this.base.replace(/^http/,"ws")}/pub/events/${encodeURIComponent(e)}/subscribe?surface=manager`}block(e,t,s={}){let n={labels:t};return typeof s.releaseAt=="number"&&(n.releaseAt=s.releaseAt),s.reason&&(n.reason=s.reason),this.auth(`/v1/events/${encodeURIComponent(e)}/block`,{method:"POST",body:n})}unblock(e,t){return this.auth(`/v1/events/${encodeURIComponent(e)}/unblock`,{method:"POST",body:{labels:t}})}unblockAll(e){return this.auth(`/v1/events/${encodeURIComponent(e)}/unblock-all`,{method:"POST"})}unbook(e,t,s){return this.auth(`/v1/events/${encodeURIComponent(e)}/unbook`,{method:"POST",body:{labels:t,bookingRef:s}})}setHoldTtl(e,t){return this.auth(`/v1/events/${encodeURIComponent(e)}/hold-ttl`,{method:"POST",body:{holdTtlMs:t}})}setCategory(e,t,s){return this.auth(`/v1/events/${encodeURIComponent(e)}/category-assignments`,{method:"POST",body:{labels:t,categoryKey:s}})}setTableBooking(e,t,s,n={}){return this.auth(`/v1/events/${encodeURIComponent(e)}/table-booking`,{method:"POST",body:{tableIds:t,mode:s,...n}})}bookings(e,t={}){let s=new URLSearchParams;t.q&&s.set("q",t.q),t.state&&s.set("state",t.state),t.cursor&&s.set("cursor",t.cursor),t.limit!=null&&s.set("limit",String(t.limit));let n=s.toString();return this.auth(`/v1/events/${encodeURIComponent(e)}/bookings${n?`?${n}`:""}`)}booking(e,t){return this.auth(`/v1/events/${encodeURIComponent(e)}/bookings/${encodeURIComponent(t)}`)}listBookings(e,t={}){return this.bookings(e,t)}retrieveBooking(e,t){return this.booking(e,t)}availability(e){return this.auth(`/v1/events/${encodeURIComponent(e)}/availability`)}setAvailability(e,t){return this.auth(`/v1/events/${encodeURIComponent(e)}/availability`,{method:"POST",body:{rules:t}})}channels(e,t={}){let s=t.includeArchived?"?includeArchived=1":"";return this.auth(`/v1/events/${encodeURIComponent(e)}/channels${s}`)}channelAllocation(e,t={}){let s=new URLSearchParams;t.afterLabel&&s.set("afterLabel",t.afterLabel),t.limit!=null&&s.set("limit",String(t.limit));let n=s.toString();return this.auth(`/v1/events/${encodeURIComponent(e)}/channels/allocation${n?`?${n}`:""}`)}channelAudit(e,t={}){let s=new URLSearchParams;t.limit!=null&&s.set("limit",String(t.limit)),t.before!=null&&s.set("before",String(t.before));let n=s.toString();return this.auth(`/v1/events/${encodeURIComponent(e)}/channels/audit${n?`?${n}`:""}`)}createChannel(e,t){return this.auth(`/v1/events/${encodeURIComponent(e)}/channels`,{method:"POST",body:t})}renameChannel(e,t,s){return this.auth(`/v1/events/${encodeURIComponent(e)}/channels/${encodeURIComponent(t)}`,{method:"PATCH",body:{name:s}})}updateChannelPricing(e,t,s,n){return this.auth(`/v1/events/${encodeURIComponent(e)}/channels/${encodeURIComponent(t)}`,{method:"PATCH",body:{priceOverrides:s,expectedPricingVersion:n}})}setChannelPaused(e,t,s){let n=s?"pause":"unpause";return this.auth(`/v1/events/${encodeURIComponent(e)}/channels/${encodeURIComponent(t)}/${n}`,{method:"POST",body:{}})}archiveChannel(e,t,s){return this.auth(`/v1/events/${encodeURIComponent(e)}/channels/${encodeURIComponent(t)}/archive`,{method:"POST",body:{destination:s}})}applyChannelAssignment(e,t){return this.auth(`/v1/events/${encodeURIComponent(e)}/channels/assignments`,{method:"POST",body:{targetChannelId:t.targetChannelId||null,labels:t.labels,assignmentVersion:t.assignmentVersion}})}channelPreview(e,t,s={}){let n=new URLSearchParams;t.length&&n.set("channelIds",t.join(",")),s.includePublic!=null&&n.set("includePublic",s.includePublic?"1":"0");let i=n.toString();return this.auth(`/v1/events/${encodeURIComponent(e)}/channels/preview${i?`?${i}`:""}`)}setChannelAccessIntent(e,t,s,n={}){return this.auth(`/v1/events/${encodeURIComponent(e)}/channels/${encodeURIComponent(t)}`,{method:"PATCH",body:{accessIntent:s,...n.acknowledgeLiveAccess?{acknowledgeLiveAccess:!0}:{},...n.reason?{reason:n.reason}:{}}})}createAccessLink(e,t,s={}){return this.auth(`/v1/events/${encodeURIComponent(e)}/channels/${encodeURIComponent(t)}/access-links`,{method:"POST",body:s})}accessLinks(e,t){return this.auth(`/v1/events/${encodeURIComponent(e)}/channels/${encodeURIComponent(t)}/access-links`)}rotateAccessLink(e,t,s,n){return this.auth(`/v1/events/${encodeURIComponent(e)}/channels/${encodeURIComponent(t)}/access-links/${encodeURIComponent(s)}/rotate`,{method:"POST",body:{endActiveSessions:n}})}revokeAccessLink(e,t,s,n=!1){let i=n?"?endActiveSessions=1":"";return this.auth(`/v1/events/${encodeURIComponent(e)}/channels/${encodeURIComponent(t)}/access-links/${encodeURIComponent(s)}${i}`,{method:"DELETE"})}report(e){return this.auth(`/v1/events/${encodeURIComponent(e)}/report`).then(Vt)}seatHistory(e,t,s,n){let i=new URLSearchParams({label:t});return s&&i.set("before",String(s)),n&&i.set("action",n),this.auth(`/v1/events/${encodeURIComponent(e)}/seat-history?${i}`)}controlRoom(e,t=15){return this.auth(`/v1/events/${encodeURIComponent(e)}/control-room?window=${t}`).then(Ut)}channelReport(e){return this.auth(`/v1/events/${encodeURIComponent(e)}/channels/report`).then(Kt)}createChannelReportLink(e,t,s={}){return this.auth(`/v1/events/${encodeURIComponent(e)}/channels/${encodeURIComponent(t)}/report-links`,{method:"POST",body:s}).then(n=>{let i=$(n);return{...i,link:Be(i.link)}})}channelReportLinks(e,t){return this.auth(`/v1/events/${encodeURIComponent(e)}/channels/${encodeURIComponent(t)}/report-links`).then(s=>{let n=$(s);return{links:Array.isArray(n.links)?n.links.map(Be):[]}})}revokeChannelReportLink(e,t,s){return this.auth(`/v1/events/${encodeURIComponent(e)}/channels/${encodeURIComponent(t)}/report-links/${encodeURIComponent(s)}`,{method:"DELETE"}).then(n=>{let i=$(n);return{...i,link:Be(i.link)}})}log(e,t={}){let s=new URLSearchParams;t.limit!=null&&s.set("limit",String(t.limit)),t.before!=null&&s.set("before",String(t.before));let n=s.toString();return this.auth(`/v1/events/${encodeURIComponent(e)}/log${n?`?${n}`:""}`)}async reportCsv(e){let t=await fetch(`${this.base}/v1/events/${encodeURIComponent(e)}/report.csv`,{headers:{Authorization:`Bearer ${this.token}`},credentials:"omit"});if(!t.ok)throw new x(t.status,`request_failed_${t.status}`);return t.blob()}}});function D(l){return l==null||l===""||l===T}function z(l,e){let t=(l??"").trim();return((/\p{L}/u.exec(t)?.[0]??t[0]??"")||e).toUpperCase().slice(0,1)}function J(l,e){let t=new Set([...e].map(i=>z(i,"")).filter(Boolean)),s=z(l,"");return{letter:gt.includes(s)&&!t.has(s)?s:[...gt].find(i=>!t.has(i))??(s||"X"),color:ve[t.size%ve.length]}}function fe(l,e=0){return D(l.id)?{letter:z(l.marker,"P"),color:l.color||Jt}:{letter:z(l.marker||l.name,"?"),color:l.color||ve[e%ve.length]}}function ye(l,e,t){let s=new Map;for(let a of l){let o=Ne(e.get(a));s.set(o,(s.get(o)??0)+1)}let n=[{id:T,name:t?.publicSale?.name??M},...(t?.channels??[]).map(a=>({id:a.id,name:a.name}))],i=[];for(let a of n){let o=s.get(a.id);o&&i.push({channelId:a.id,name:a.name,count:o}),s.delete(a.id)}for(let[a,o]of s)i.push({channelId:a,name:D(a)?M:"Another channel",count:o});return i}function Ne(l){return D(l)?T:l}function qe(l){return{count:l.length,labels:l.slice(0,vt),truncated:l.length>vt}}function ke(l){let{labels:e,allocation:t,statusOf:s,nameOf:n}=l,i=Ne(l.targetChannelId),a=new Set,o=0,r=0,d=new Map,c=[],h=[],u=[];for(let v of e){if(a.has(v))continue;a.add(v);let g=s(v);if(!g){u.push(v);continue}let m=Ne(t.get(v));if(m===i){r+=1;continue}if(g==="held"){c.push(v);continue}if(g==="booked"){h.push(v);continue}m===T?o+=1:d.set(m,(d.get(m)??0)+1)}let f=[...d.entries()].map(([v,g])=>({channelId:v,name:n(v),count:g}));return{changedFromPublic:{count:o},movedFromOtherChannel:{count:f.reduce((v,g)=>v+g.count,0),channels:f},alreadyInTarget:{count:r},skippedHeld:qe(c),skippedBooked:qe(h),notFound:qe(u)}}function Y(l){return l.changedFromPublic.count+l.movedFromOtherChannel.count}function xe(l){return l.movedFromOtherChannel.count>0}function we(l,e){let t=[];l.changedFromPublic.count&&t.push({kind:"add",icon:"+",count:l.changedFromPublic.count,text:`${l.changedFromPublic.count.toLocaleString()} from ${M}`});for(let s of l.movedFromOtherChannel.channels)t.push({kind:"move",icon:"\u21C4",count:s.count,text:`${s.count.toLocaleString()} moved out of ${s.name??"another channel"}`,why:"needs this confirmation"});return l.alreadyInTarget.count&&t.push({kind:"same",icon:"=",count:l.alreadyInTarget.count,text:`${l.alreadyInTarget.count.toLocaleString()} already in ${e}`,why:"unchanged"}),l.skippedHeld.count&&t.push({kind:"skip",icon:"\u23F8",count:l.skippedHeld.count,text:`${l.skippedHeld.count.toLocaleString()} in a buyer's checkout`,why:"can't move while held",peek:ge(l.skippedHeld)}),l.skippedBooked.count&&t.push({kind:"skip",icon:"\u{1F512}",count:l.skippedBooked.count,text:`${l.skippedBooked.count.toLocaleString()} already sold`,why:"sales are never rewritten",peek:ge(l.skippedBooked)}),l.notFound.count&&t.push({kind:"skip",icon:"?",count:l.notFound.count,text:`${l.notFound.count.toLocaleString()} not on this map`,why:"these seats are no longer part of the event",peek:ge(l.notFound)}),t}function ge(l){if(!l.labels.length)return;let e=l.labels.slice(0,4).join(", ");return l.truncated||l.labels.length>4?`${e}\u2026`:e}function Se(l){let e=l?.retryAfterMs??(l?.latestHoldExpiresAt?Math.max(0,l.latestHoldExpiresAt-Date.now()):0);if(!e)return"in a moment";let t=Math.ceil(e/6e4);return t<=1?"in about a minute":`in about ${t} minutes`}function Le(l){if(!l||!l.intent)return"\u2014";let e=l.intent==="server"?"Website integration":l.intent==="hosted_link"?"Buyer link":l.intent==="internal"?"Your staff sell these":"Protected reserve",t=l.hasActiveGrants?"in use now":l.lastMintAt?`last used ${new Date(l.lastMintAt).toLocaleDateString()}`:null,s=l.detail??t;return s?`${e} \xB7 ${s}`:e}function F(l){return l==="internal"?"Sell through your own staff":l==="server"?"Integrate a website or app":l==="hosted_link"?"Sell with a buyer link":"Keep as protected reserve"}function Ce(l){switch(l){case"internal":return"Only your own box office can sell these seats, through your secret key. Buyer links and website integrations are refused.";case"server":return"Your website's backend mints each buyer a short-lived session for these seats. Buyer links are refused; the code lives on the Embed page.";case"hosted_link":return"SeatLayer makes a link you send to a named group. They open it and buy only these seats. No other route can sell them.";default:return"Nobody can buy these seats. Every way of letting a buyer in \u2014 a buyer link, your website, even your own staff \u2014 is refused while this is the route. The seats stay out of public sale."}}function es(l){return l==="hosted_link"?"hosted_link":l==="server"?"server":l==="staff"?"internal":null}function G(l){let e=_e(l?.accessIntent),t=es(l?.route),s=`This channel is set to "${F(e)}"`;return t?`${s}, so it cannot do that. Switch it to "${F(t)}" first.`:`${s}, so it cannot do that. Choose a different route for this channel first.`}function _e(l){return l==="internal"||l==="server"||l==="hosted_link"||l==="none"?l:"none"}function be(l,e,t){return`${l.toLocaleString()} ${l===1?e:t}`}function Te(l){let e=Math.max(0,l?.liveAccessLinks??0),t=Math.max(0,l?.activeSessions??0),s=_e(l?.from),n=_e(l?.to),a=`${[e?be(e,"buyer link is live","buyer links are live"):null,t?be(t,"buyer is in a checkout","buyers are in a checkout"):null].filter(Boolean).join(", and ")||"Buyers are inside this channel"} on "${F(s)}". Moving it to "${F(n)}" changes what happens to them.`,o=[];return e&&o.push(`${be(e,"buyer link closes","buyer links close")} immediately. Anyone who has not opened it yet never will \u2014 send a new link if you still need one.`),t&&o.push(`${be(t,"buyer who is already in a checkout keeps","buyers who are already in a checkout keep")} their seats and can finish paying. Nobody is thrown out. No new buyers come in this way, so the old route empties on its own within 12 hours.`),{headline:a,consequences:o}}function Re(l){switch(l.status??l.state){case"active":return{text:"Active",kind:"active"};case"expired":return{text:"Expired",kind:"archived"};case"exhausted":return{text:"All used",kind:"paused"};case"rotated":return{text:"Replaced",kind:"archived"};default:return{text:"Revoked",kind:"archived"}}}function te(l){return l.state==="active"&&l.status==="active"}function ts(l){return Number.isFinite(l)?new Date(l).toLocaleString(void 0,{day:"numeric",month:"short",year:"numeric",hour:"numeric",minute:"2-digit"}):"\u2014"}function se(l){return[{k:"Expires",v:ts(l.expiresAt)},{k:"Redemptions",v:`${l.redemptions.toLocaleString()} of ${l.maxRedemptions.toLocaleString()} used`},{k:"Seats per buyer",v:`${l.maxQuantity.toLocaleString()} seat${l.maxQuantity===1?"":"s"} maximum`},{k:"Covers",v:l.includePublic?"This channel's allocation and Public sale seats":"This channel's allocation only"}]}function j(l){let e=l?.serverMessage?.trim();switch(l?.code){case"invalid_expiry":case"invalid_max_redemptions":case"invalid_max_quantity":case"invalid_session_ttl":case"invalid_label":return e||"That setting is outside what a hosted link allows. Adjust it and try again.";case"too_many_access_links":return e||"This channel already has as many live links as it can hold. Revoke one before creating another.";case"access_link_not_active":return"That link is no longer active, so it cannot be rotated or revoked.";case"channel_unavailable":return"This channel is paused or archived, so it cannot let new buyers in. Resume it first.";case"channel_access_intent_forbids":return G(l?.details);case"end_active_sessions_required":return"Choose what happens to the buyers who already came in through this link.";case"not_found":return"That link is no longer here. Refresh and try again.";default:return l?.status===403?"Hosted access links need channel-management permission.":e||"That did not go through. Try again."}}function ft(l){return(l?.channels??[]).map(e=>({kind:"skip",icon:"\u26A0",count:e.count,text:`${e.count.toLocaleString()} would leave ${e.name??"a channel"}`,why:"the new chart no longer has these seats",peek:e.labels?.length?ge({count:e.count,labels:e.labels,truncated:e.truncated??!1}):void 0}))}function $e(l){return l==="builtin"?"Built-in":l==="active"?"Active":l==="paused"?"Paused":"Archived"}var T,M,ve,Jt,gt,vt,ee,Ee=_(()=>{"use strict";T="public",M="Public sale";ve=["#a78bfa","#2dd4bf","#fb923c","#60a5fa","#f472b6","#a3e635","#f87171","#38bdf8","#c084fc","#facc15"],Jt="#f4b740",gt="ABCDEFGHJKLMNPQRSTUVWXYZ";vt=12;ee={maxRedemptions:100,maxQuantity:4}});function W(l){return l.map((e,t)=>`
2
2
  <div class="slm-ch-bucket" style="animation-delay:${Math.min(t,4)*30}ms">
3
3
  <span class="ico ${e.kind}" aria-hidden="true">${p(e.icon)}</span>
4
4
  <span><b>${e.count.toLocaleString()}</b> ${p(e.text.replace(/^[\d,.\s]+/,""))}
5
5
  ${e.why?`<span class="why">\u2014 ${p(e.why)}</span>`:""}</span>
6
6
  ${e.peek?`<span class="peek">${p(e.peek)}</span>`:"<span></span>"}
7
- </div>`).join("")}function p(l){return String(l??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#039;")}function ft(l){return new Date(l-new Date(l).getTimezoneOffset()*6e4).toISOString().slice(0,16)}function je(l,e){let t=l.querySelector(e)?.value.trim()??"",s=Number(t);return t!==""&&Number.isInteger(s)?s:null}function Ne(l){let e=l.querySelector("[data-ch-lk-url]");if(e)try{let t=document.createRange();t.selectNodeContents(e);let s=window.getSelection();s?.removeAllRanges(),s?.addRange(t)}catch{}}var vt,$e=j(()=>{"use strict";vt=`
7
+ </div>`).join("")}function p(l){return String(l??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#039;")}function xt(l){return new Date(l-new Date(l).getTimezoneOffset()*6e4).toISOString().slice(0,16)}function je(l,e){let t=l.querySelector(e)?.value.trim()??"",s=Number(t);return t!==""&&Number.isInteger(s)?s:null}function wt(l,e){let t=typeof navigator>"u"?null:navigator.clipboard;return t?.writeText?t.writeText(e).then(()=>!0,()=>yt(l,e)):Promise.resolve(yt(l,e))}function yt(l,e){let t=l.querySelector("[data-ch-lk-sink]");if(t&&typeof document.execCommand=="function")try{t.value=e,t.select(),t.setSelectionRange(0,e.length);let s=document.execCommand("copy");if(t.value="",s)return!0}catch{t.value=""}return ss(l),!1}function ss(l){let e=l.querySelector("[data-ch-lk-url]");if(e)try{let t=document.createRange();t.selectNodeContents(e);let s=window.getSelection();s?.removeAllRanges(),s?.addRange(t)}catch{}}var kt,Ae=_(()=>{"use strict";kt=`
8
8
  <p class="slm-eyebrow" style="margin-top:18px">On your website</p>
9
9
  <p class="slm-hint">There is nothing more to set up on this screen. Your own server mints a short-lived buyer
10
10
  access session for this channel with the SeatLayer server SDK and hands it to the widget. A channel name
11
11
  on its own never grants access.</p>
12
12
  <p class="slm-note"><a class="slm-linkbtn" href="https://docs.seatlayer.io/server-api/channels"
13
- target="_blank" rel="noreferrer noopener">Read the website integration guide \u2192</a></p>`});function yt(l){let e=l.canvas,t=l.layer;if(!e||!t)return;let s=l.host.mapLayer.getBoundingClientRect(),n=Math.max(1,Math.round(s.width)),i=Math.max(1,Math.round(s.height)),a=typeof devicePixelRatio=="number"?Math.min(3,Math.max(1,devicePixelRatio)):1;(e.width!==n*a||e.height!==i*a)&&(e.width=n*a,e.height=i*a);let o=l.resolveCtx();if(!o)return;o.setTransform(a,0,0,a,0,0),o.clearRect(0,0,n,i);let r=l.host.isSeatDetail(),c=Math.max(3,l.host.seatPixelSize()),d=c/2,h=l.view==="preview"?l.previewProjection:null,u=h?new Set(h.available===!1?[]:h.eligible??[]):null,f=new Map,v=!r&&l.host.sections().length>1?new Map:null,g=l.view==="preview"&&r&&c<=15?new Map:null;for(let m of l.host.seats()){let k=l.host.statusOf(m.label)??"free",R=l.allocation.get(m.label)??T;if(R!==T){let L=f.get(R)??{x:0,y:0,n:0};L.x+=m.x,L.y+=m.y,L.n+=1,f.set(R,L)}if(!r){let L=l.host.sectionOfLabel(m.label),w=L?l.host.worldToScreen({x:m.x,y:m.y}):null;if(v&&L&&w){let x=v.get(L.id)??{label:L.label,minX:w.x,minY:w.y,maxX:w.x,maxY:w.y};x.minX=Math.min(x.minX,w.x),x.minY=Math.min(x.minY,w.y),x.maxX=Math.max(x.maxX,w.x),x.maxY=Math.max(x.maxY,w.y),v.set(L.id,x)}continue}if(k!=="free")continue;let q=null,I=null;if(l.view==="preview"?u?.has(m.label)?(q=Gt,I=Zt):(q=Qt,I=Jt):R!==T&&(q=l.markerFor(R).color,I=es),!q)continue;let C=l.host.worldToScreen({x:m.x,y:m.y});if(C&&!(C.x<-c||C.y<-c||C.x>n+c||C.y>i+c)){if(g){let L=l.host.sectionOfLabel(m.label);if(L){let w=g.get(L.id)??{label:L.label,minX:C.x,minY:C.y,maxX:C.x,maxY:C.y};w.minX=Math.min(w.minX,C.x),w.minY=Math.min(w.minY,C.y),w.maxX=Math.max(w.maxX,C.x),w.maxY=Math.max(w.maxY,C.y),g.set(L.id,w)}}if(o.fillStyle=q,l.view==="preview"||R!==T){let L=Math.max(2,d+Math.min(1.5,d*.06));o.globalAlpha=1,o.beginPath(),o.arc(C.x,C.y,L,0,Math.PI*2),o.fill(),o.strokeStyle=I??q,o.lineWidth=l.view==="preview"?Math.max(1,Math.min(1.75,c*.13)):Math.max(1,Math.min(1.5,c*.1)),o.stroke(),l.view==="preview"&&u?.has(m.label)&&c>=22&&ts(o,m.label,C.x,C.y,L)}else o.globalAlpha=.85,o.fillRect(C.x-d,C.y-d,c,c)}}o.globalAlpha=1,g&&ns(o,g),ss(v,l),is(f,l,o)}function ts(l,e,t,s,n){let i=n*1.55,a=Math.min(13,Math.max(7,n*.55)),o=6;for(;a>=o&&(l.font=`800 ${a}px var(--slm-font, system-ui, sans-serif)`,!(l.measureText(e).width<=i));)a-=.5;a<o||(l.fillStyle="#ffffff",l.textAlign="center",l.textBaseline="middle",l.fillText(e,t,s))}function ss(l,e){let t=e.layer;if(t&&(t.querySelectorAll(".slm-ch-section-target").forEach(s=>s.remove()),!!l))for(let[s,n]of l){let i=n.maxX-n.minX,a=n.maxY-n.minY;if(i<20||a<20)continue;let o=document.createElement("button");o.type="button",o.className="slm-ch-section-target",o.style.left=`${n.minX-8}px`,o.style.top=`${n.minY-8}px`,o.style.width=`${i+16}px`,o.style.height=`${a+16}px`,o.setAttribute("aria-label",`Open ${n.label} seats`),o.addEventListener("click",()=>e.onSectionTargetClick(s)),t.appendChild(o)}}function ns(l,e){for(let t of e.values()){let s=t.maxX-t.minX,n=t.maxY-t.minY;if(s<52||n<26)continue;let i=(t.minX+t.maxX)/2,a=(t.minY+t.maxY)/2,o=Math.max(11,Math.min(15,n*.16));l.font=`800 ${o}px var(--slm-font, system-ui, sans-serif)`;let r=Math.min(s-8,l.measureText(t.label).width+18),c=o+10;l.fillStyle="rgba(11, 16, 28, .88)",l.fillRect(i-r/2,a-c/2,r,c),l.fillStyle="#f8fafc",l.textAlign="center",l.textBaseline="middle",l.fillText(t.label,i,a)}}function is(l,e,t){let s=e.layer;if(!s||(s.querySelectorAll(".slm-ch-flag").forEach(i=>i.remove()),e.view==="preview"))return;let n=[...l.entries()].sort((i,a)=>a[1].n-i[1].n).slice(0,Xt);for(let[i,a]of n){let o=e.list?.channels.find(h=>h.id===i);if(!o)continue;let r=e.host.worldToScreen({x:a.x/a.n,y:a.y/a.n});if(!r)continue;let c=e.markerFor(i),d=document.createElement("span");d.className="slm-ch-flag",d.style.left=`${r.x}px`,d.style.top=`${r.y}px`,d.innerHTML=`<span class="mk" style="background:${p(c.color)}">${p(c.letter)}</span>${p(o.name)}${o.state==="paused"?" \xB7 Paused":""}`,s.appendChild(d)}}var Xt,Gt,Zt,Qt,Jt,es,kt=j(()=>{"use strict";Re();$e();Xt=8,Gt="#6e7bff",Zt="#b9c0ff",Qt="#303846",Jt="#4b5669",es="#101723"});var xt,wt=j(()=>{"use strict";xt=`
14
- .slm{--slm-mo-instant:80ms;--slm-mo-quick:140ms;--slm-mo-base:200ms;--slm-mo-slow:320ms;--slm-mo-ambient:2000ms;
13
+ target="_blank" rel="noreferrer noopener">Read the website integration guide \u2192</a></p>`});function rs(l){return l?.dataset?.theme==="light"?ls:os}function Ct(l){let e=l.canvas,t=l.layer;if(!e||!t)return;let s=l.host.mapLayer.getBoundingClientRect(),n=Math.max(1,Math.round(s.width)),i=Math.max(1,Math.round(s.height)),a=typeof devicePixelRatio=="number"?Math.min(3,Math.max(1,devicePixelRatio)):1;(e.width!==n*a||e.height!==i*a)&&(e.width=n*a,e.height=i*a);let o=l.resolveCtx();if(!o)return;o.setTransform(a,0,0,a,0,0),o.clearRect(0,0,n,i);let r=rs(l.host.root),d=l.host.isSeatDetail(),c=Math.max(3,l.host.seatPixelSize()),h=c/2,u=l.view==="preview"?l.previewProjection:null,f=u?new Set(u.available===!1?[]:u.eligible??[]):null,v=new Map,g=!d&&l.host.sections().length>1?new Map:null,m=l.view==="preview"&&d&&c<=15?new Map:null;for(let y of l.host.seats()){let H=l.host.statusOf(y.label)??"free",q=l.allocation.get(y.label)??T;if(q!==T){let L=v.get(q)??{x:0,y:0,n:0};L.x+=y.x,L.y+=y.y,L.n+=1,v.set(q,L)}if(!d){let L=l.host.sectionOfLabel(y.label),k=L?l.host.worldToScreen({x:y.x,y:y.y}):null;if(g&&L&&k){let C=g.get(L.id)??{label:L.label,minX:k.x,minY:k.y,maxX:k.x,maxY:k.y};C.minX=Math.min(C.minX,k.x),C.minY=Math.min(C.minY,k.y),C.maxX=Math.max(C.maxX,k.x),C.maxY=Math.max(C.maxY,k.y),g.set(L.id,C)}continue}if(H!=="free")continue;let E=null,N=null;if(l.view==="preview"?f?.has(y.label)?(E=is,N=as):(E=r.unavailableFill,N=r.unavailableStroke):q!==T&&(E=l.markerFor(q).color,N=r.allocationStroke),!E)continue;let S=l.host.worldToScreen({x:y.x,y:y.y});if(S&&!(S.x<-c||S.y<-c||S.x>n+c||S.y>i+c)){if(m){let L=l.host.sectionOfLabel(y.label);if(L){let k=m.get(L.id)??{label:L.label,minX:S.x,minY:S.y,maxX:S.x,maxY:S.y};k.minX=Math.min(k.minX,S.x),k.minY=Math.min(k.minY,S.y),k.maxX=Math.max(k.maxX,S.x),k.maxY=Math.max(k.maxY,S.y),m.set(L.id,k)}}if(o.fillStyle=E,l.view==="preview"||q!==T){let L=Math.max(2,h+Math.min(1.5,h*.06));o.globalAlpha=1,o.beginPath(),o.arc(S.x,S.y,L,0,Math.PI*2),o.fill(),o.strokeStyle=N??E,o.lineWidth=l.view==="preview"?Math.max(1,Math.min(1.75,c*.13)):Math.max(1,Math.min(1.5,c*.1)),o.stroke(),l.view==="preview"&&f?.has(y.label)&&c>=22&&cs(o,y.label,S.x,S.y,L)}else o.globalAlpha=.85,o.fillRect(S.x-h,S.y-h,c,c)}}o.globalAlpha=1,m&&ms(o,m,r),ds(g,l),us(v,l,o)}function cs(l,e,t,s,n){let i=n*1.55,a=Math.min(13,Math.max(7,n*.55)),o=6;for(;a>=o&&(l.font=`800 ${a}px var(--slm-font, system-ui, sans-serif)`,!(l.measureText(e).width<=i));)a-=.5;a<o||(l.fillStyle="#ffffff",l.textAlign="center",l.textBaseline="middle",l.fillText(e,t,s))}function ds(l,e){let t=e.layer;if(t&&(t.querySelectorAll(".slm-ch-section-target").forEach(s=>s.remove()),!!l))for(let[s,n]of l){let i=n.maxX-n.minX,a=n.maxY-n.minY;if(i<20||a<20)continue;let o=document.createElement("button");o.type="button",o.className="slm-ch-section-target",o.style.left=`${n.minX-8}px`,o.style.top=`${n.minY-8}px`,o.style.width=`${i+16}px`,o.style.height=`${a+16}px`,o.setAttribute("aria-label",`Open ${n.label} seats`),ps(o,e,()=>e.onSectionTargetClick(s)),t.appendChild(o)}}function hs(l,e){let t={button:0,buttons:1,clientX:e.x,clientY:e.y,bubbles:!0,cancelable:!0,composed:!0};return typeof PointerEvent=="function"?new PointerEvent("pointerdown",{...t,pointerId:l.pointerId,pointerType:l.pointerType,isPrimary:!0}):new MouseEvent("pointerdown",t)}function Lt(l){return l.host.mapLayer.querySelector(".slm-map-host")??l.host.mapLayer}function ps(l,e,t){l.addEventListener("wheel",r=>{let d=Lt(e);d!==l&&(r.preventDefault(),d.dispatchEvent(new WheelEvent("wheel",{deltaX:r.deltaX,deltaY:r.deltaY,deltaZ:r.deltaZ,deltaMode:r.deltaMode,clientX:r.clientX,clientY:r.clientY,ctrlKey:r.ctrlKey,shiftKey:r.shiftKey,altKey:r.altKey,metaKey:r.metaKey,bubbles:!0,cancelable:!0,composed:!0})))},{passive:!1});let s=null,n=!1,i=()=>{s=null,e.layer?.classList.remove("panning"),window.removeEventListener("pointermove",a,!0),window.removeEventListener("pointerup",o,!0),window.removeEventListener("pointercancel",o,!0)};function a(r){if(!s||n||Math.abs(r.clientX-s.x)<St&&Math.abs(r.clientY-s.y)<St)return;n=!0;let d=s;e.layer?.classList.add("panning");let c=document.elementFromPoint?.(d.x,d.y)??null;(c&&c!==l?c:Lt(e)).dispatchEvent(hs(r,d))}function o(){i()}l.addEventListener("pointerdown",r=>{n=!1,s={x:r.clientX,y:r.clientY},window.addEventListener("pointermove",a,!0),window.addEventListener("pointerup",o,!0),window.addEventListener("pointercancel",o,!0)}),l.addEventListener("click",r=>{if(n){n=!1,r.preventDefault(),r.stopPropagation();return}t()})}function ms(l,e,t){for(let s of e.values()){let n=s.maxX-s.minX,i=s.maxY-s.minY;if(n<52||i<26)continue;let a=(s.minX+s.maxX)/2,o=(s.minY+s.maxY)/2,r=Math.max(11,Math.min(15,i*.16));l.font=`800 ${r}px var(--slm-font, system-ui, sans-serif)`;let d=Math.min(n-8,l.measureText(s.label).width+18),c=r+10;l.fillStyle=t.sectionPlate,l.fillRect(a-d/2,o-c/2,d,c),l.fillStyle=t.sectionPlateInk,l.textAlign="center",l.textBaseline="middle",l.fillText(s.label,a,o)}}function us(l,e,t){let s=e.layer;if(!s||(s.querySelectorAll(".slm-ch-flag").forEach(i=>i.remove()),e.view==="preview"))return;let n=[...l.entries()].sort((i,a)=>a[1].n-i[1].n).slice(0,ns);for(let[i,a]of n){let o=e.list?.channels.find(h=>h.id===i);if(!o)continue;let r=e.host.worldToScreen({x:a.x/a.n,y:a.y/a.n});if(!r)continue;let d=e.markerFor(i),c=document.createElement("span");c.className="slm-ch-flag",c.style.left=`${r.x}px`,c.style.top=`${r.y}px`,c.innerHTML=`<span class="mk" style="background:${p(d.color)}">${p(d.letter)}</span>${p(o.name)}${o.state==="paused"?" \xB7 Paused":""}`,s.appendChild(c)}}var ns,is,as,os,ls,St,Tt=_(()=>{"use strict";Ee();Ae();ns=8,is="#6e7bff",as="#b9c0ff",os={unavailableFill:"#303846",unavailableStroke:"#4b5669",allocationStroke:"#101723",sectionPlate:"rgba(11,16,28,.88)",sectionPlateInk:"#f8fafc"},ls={unavailableFill:"rgba(156,163,175,.55)",unavailableStroke:"rgba(107,114,128,.65)",allocationStroke:"#ffffff",sectionPlate:"rgba(255,255,255,.9)",sectionPlateInk:"#172033"};St=4});var Rt,$t=_(()=>{"use strict";Rt=`
14
+ .slm{--slm-ch-marker-ink:#0e1017;--slm-ch-scrim:rgba(0,0,0,.58);
15
+ --slm-mo-instant:80ms;--slm-mo-quick:140ms;--slm-mo-base:200ms;--slm-mo-slow:320ms;--slm-mo-ambient:2000ms;
15
16
  --slm-mo-out:cubic-bezier(.2,.8,.2,1);--slm-mo-in-out:cubic-bezier(.4,0,.2,1);--slm-mo-exit:cubic-bezier(.4,0,1,1);
16
17
  --slm-mo-spring:cubic-bezier(.34,1.3,.64,1)}
18
+ /* A channel's marker chip is painted in the CHANNEL's own colour, which is the
19
+ same in both themes, so its ink is a constant rather than a ground token \u2014
20
+ declared once here so a host can still override it. The scrim always DARKENS
21
+ (a light-ground modal dims with a dark veil too); only its strength changes. */
22
+ .slm[data-theme=light]{--slm-ch-scrim:rgba(23,32,51,.42)}
17
23
 
18
24
  /* map overlay: ONE layer, faded in as a whole (never per seat) */
19
25
  .slm-ch-layer{position:absolute;inset:0;overflow:hidden;pointer-events:none;opacity:0;transition:opacity var(--slm-mo-base) var(--slm-mo-out)}
20
26
  .slm-ch-layer.on{opacity:1}
21
27
  .slm-ch-canvas{position:absolute;inset:0;width:100%;height:100%}
22
28
  .slm-ch-flag{position:absolute;display:flex;align-items:center;gap:5px;padding:3px 8px;border-radius:999px;
23
- background:rgba(14,16,23,.88);border:1px solid var(--slm-line);font-size:10px;font-weight:800;letter-spacing:.04em;
29
+ background:color-mix(in srgb,var(--slm-surface) 92%,transparent);color:var(--slm-text);
30
+ border:1px solid var(--slm-line);font-size:10px;font-weight:800;letter-spacing:.04em;
24
31
  transform:translate(-50%,-50%);white-space:nowrap}
25
- .slm-ch-flag .mk{width:14px;height:14px;border-radius:4px;display:grid;place-items:center;font-size:8.5px;font-weight:800;color:#0e1017}
32
+ .slm-ch-flag .mk{width:14px;height:14px;border-radius:4px;display:grid;place-items:center;font-size:8.5px;font-weight:800;color:var(--slm-ch-marker-ink)}
26
33
  .slm-ch-section-target{position:absolute;pointer-events:auto;padding:0;border:0;border-radius:8px;background:transparent;cursor:zoom-in}
34
+ /* Set while a pointer gesture that started on a section target has turned into
35
+ a map pan: every target goes inert so the drag reaches the renderer host. */
36
+ .slm-ch-layer.panning .slm-ch-section-target{pointer-events:none}
27
37
  .slm-ch-section-target:focus-visible{outline:2px solid var(--slm-accent);outline-offset:-3px;background:color-mix(in srgb,var(--slm-accent) 12%,transparent)}
28
38
 
29
39
  /* preview banner \u2014 raised with the organizer chrome dim, as one transition */
30
- .slm-ch-banner{position:absolute;left:50%;top:14px;z-index:6;display:flex;align-items:center;gap:9px;padding:8px 14px;
31
- border-radius:999px;background:rgba(14,16,23,.92);border:1px solid var(--slm-line);font-size:12px;font-weight:700;
32
- transform:translate(-50%,-8px);opacity:0;pointer-events:none;
40
+ .slm-ch-banner{display:flex;align-items:center;gap:9px;padding:8px 14px;max-width:100%;
41
+ border-radius:999px;background:color-mix(in srgb,var(--slm-surface) 94%,transparent);color:var(--slm-text);
42
+ border:1px solid var(--slm-line);font-size:12px;font-weight:700;
43
+ transform:translateY(-8px);opacity:0;pointer-events:none;
33
44
  transition:opacity var(--slm-mo-base) var(--slm-mo-out),transform var(--slm-mo-base) var(--slm-mo-out)}
34
- .slm-ch-banner.on{opacity:1;transform:translate(-50%,0);pointer-events:auto}
45
+ .slm-ch-banner.on{opacity:1;transform:none;pointer-events:auto}
35
46
  .slm-ch-banner .dot{width:8px;height:8px;border-radius:50%}
36
47
  .slm-ch-banner button{color:var(--slm-accent);font-weight:800;font-size:11.5px;min-height:32px}
37
48
  .slm.ch-preview .slm-ch-flag{opacity:0;transition:opacity var(--slm-mo-base) var(--slm-mo-out)}
38
49
 
39
50
  /* sticky staged bar */
40
51
  .slm-ch-staged{position:absolute;left:12px;right:12px;bottom:12px;z-index:6;display:flex;align-items:center;gap:12px;
41
- padding:10px 14px;min-height:44px;border-radius:12px;background:rgba(24,27,36,.96);border:1px solid var(--slm-line);
52
+ padding:10px 14px;min-height:44px;border-radius:12px;color:var(--slm-text);
53
+ background:color-mix(in srgb,var(--slm-surface) 96%,transparent);border:1px solid var(--slm-line);
42
54
  box-shadow:0 12px 34px rgba(0,0,0,.45);font-size:12.5px;pointer-events:auto;
43
55
  transform:translateY(calc(100% + 18px));opacity:0;
44
56
  transition:transform var(--slm-mo-slow) var(--slm-mo-out),opacity var(--slm-mo-base) var(--slm-mo-out)}
45
57
  .slm-ch-staged.on{transform:none;opacity:1}
46
- .slm-ch-staged.done{background:rgba(31,122,77,.96);border-color:#1f7a4d}
58
+ /* Success keeps its own green \u2014 a semantic state, not a ground \u2014 so it states
59
+ its ink rather than inheriting a token that flips with the theme. */
60
+ .slm-ch-staged.done{background:rgba(31,122,77,.96);border-color:#1f7a4d;color:#fff}
47
61
  .slm-ch-staged.shake{animation:slm-ch-shake var(--slm-mo-slow) var(--slm-mo-in-out) 2}
48
62
  .slm-ch-staged b{font-variant-numeric:tabular-nums}
49
63
  .slm-ch-staged .grow{flex:1}
@@ -68,9 +82,19 @@
68
82
  .slm-ch-mapnav .slm-ch-viewseg{margin:8px 0 5px}
69
83
  .slm-ch-mapnav p{margin:0;font-size:11px;line-height:1.45;color:var(--slm-muted)}
70
84
  .slm-ch-list{display:flex;flex-direction:column;gap:8px;margin-bottom:12px}
71
- .slm-ch-listhead{display:flex;align-items:center;justify-content:space-between;gap:8px;margin:8px 0}
85
+ /* The list header is PINNED: it carries the only route to a new channel, and a
86
+ long channel list used to push that button past the fold. Sticky offsets are
87
+ measured from the scrollport's PADDING box, so the top offset is the negative
88
+ of the rail's own padding, and the header's matching padding covers that
89
+ strip \u2014 the list scrolls under an opaque header rather than through a gap
90
+ above it. The side bleed makes the rule reach both edges. */
91
+ .slm-ch-listhead{position:sticky;top:-16px;z-index:4;display:flex;align-items:center;justify-content:space-between;
92
+ gap:8px;margin:0 -16px 10px;padding:16px 16px 10px;background:var(--slm-surface);
93
+ border-bottom:1px solid var(--slm-line)}
72
94
  .slm-ch-listhead h2{margin:0;font-size:14px}
73
95
  .slm .slm-ch-listhead .slm-linkbtn{font-size:11px;color:var(--slm-text)}
96
+ /* Compact primary: the rail's own button, sized to sit on one header line. */
97
+ .slm .slm-ch-new{flex:none;min-width:0;padding:7px 11px;min-height:32px;font-size:11.5px}
74
98
  .slm[data-theme=light] .slm-ch-badge.active,.slm[data-theme=light] .slm-ch-counts .free b{color:#137047}
75
99
  .slm[data-theme=light] .slm-ch-badge.paused,.slm[data-theme=light] .slm-ch-badge.builtin{color:#815705}
76
100
  .slm[data-theme=light] .slm-ch-badge.archived{color:var(--slm-muted)}
@@ -82,7 +106,7 @@
82
106
  .slm-ch-row.archived{opacity:.68}
83
107
  .slm-ch-head{display:flex;align-items:center;gap:8px}
84
108
  .slm-ch-mk{width:20px;height:20px;border-radius:6px;display:grid;place-items:center;font-size:10px;font-weight:800;
85
- color:#0e1017;flex:none}
109
+ color:var(--slm-ch-marker-ink);flex:none}
86
110
  .slm-ch-mk.dim{opacity:.55}
87
111
  .slm-ch-name{flex:1;min-width:0;font-size:13px;font-weight:800;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
88
112
  .slm-ch-badge{flex:none;font-size:9px;font-weight:800;letter-spacing:.05em;text-transform:uppercase;padding:2px 7px;border-radius:999px}
@@ -116,7 +140,7 @@
116
140
  .slm-ch-selsrc{display:flex;flex-direction:column;gap:5px;margin:8px 0 12px}
117
141
  .slm-ch-selsrc-row{display:flex;align-items:center;gap:8px;font-size:12px;font-variant-numeric:tabular-nums}
118
142
  .slm-ch-selsrc-row .mk{width:15px;height:15px;border-radius:4px;display:grid;place-items:center;font-size:8px;
119
- font-weight:800;color:#0e1017}
143
+ font-weight:800;color:var(--slm-ch-marker-ink)}
120
144
  .slm-ch-selsrc-row b{min-width:30px;text-align:right;font-weight:800}
121
145
  .slm-ch-selsrc-row span{color:var(--slm-muted)}
122
146
  .slm-ch-selnum.bump{animation:slm-ch-bump var(--slm-mo-base) var(--slm-mo-spring)}
@@ -149,9 +173,9 @@
149
173
  .slm-ch-live{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}
150
174
 
151
175
  /* dialogs */
152
- .slm-ch-scrim{position:absolute;inset:0;z-index:12;background:rgba(4,6,12,.62);display:grid;place-items:center;
176
+ .slm-ch-scrim{position:absolute;inset:0;z-index:12;background:var(--slm-ch-scrim);display:grid;place-items:center;
153
177
  padding:18px;animation:slm-ch-fade var(--slm-mo-quick) var(--slm-mo-out)}
154
- .slm-ch-dialog{width:min(460px,100%);max-height:100%;overflow:auto;overscroll-behavior:contain;background:#12151f;border:1px solid var(--slm-line);
178
+ .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);
155
179
  border-radius:14px;padding:20px;box-shadow:0 24px 70px rgba(0,0,0,.6);
156
180
  animation:slm-ch-rise var(--slm-mo-base) var(--slm-mo-out)}
157
181
  .slm-ch-dialog h3{margin:0 0 4px;font-size:16px;font-weight:800;letter-spacing:-.01em}
@@ -167,14 +191,21 @@
167
191
  .slm-ch-bucket .ico{width:20px;height:20px;border-radius:6px;display:grid;place-items:center;font-size:10px;font-weight:800}
168
192
  .slm-ch-bucket .ico.add{background:rgba(34,160,107,.18);color:#5bd39b}
169
193
  .slm-ch-bucket .ico.move{background:rgba(167,139,250,.18);color:#c4b5fd}
170
- .slm-ch-bucket .ico.same{background:rgba(139,148,172,.14);color:#aab2c4}
194
+ .slm-ch-bucket .ico.same{background:var(--slm-tint-strong);color:var(--slm-muted)}
171
195
  .slm-ch-bucket .ico.skip{background:rgba(244,183,64,.16);color:#f7ca6b}
196
+ /* The three remaining icon inks are semantic (added / moved / skipped) and are
197
+ tuned for a dark ground; a light ground needs the darker end of the same hue
198
+ to stay readable, exactly as the status badges above already do. */
199
+ .slm[data-theme=light] .slm-ch-bucket .ico.add{color:#137047}
200
+ .slm[data-theme=light] .slm-ch-bucket .ico.move{color:#6d28d9}
201
+ .slm[data-theme=light] .slm-ch-bucket .ico.skip{color:#815705}
172
202
  .slm-ch-bucket b{font-variant-numeric:tabular-nums;font-weight:800}
173
203
  .slm-ch-bucket .why{color:var(--slm-muted);font-size:11px}
174
204
  .slm-ch-bucket .peek{color:var(--slm-muted);font-size:11px;font-variant-numeric:tabular-nums}
175
205
  @keyframes slm-ch-bucket{from{opacity:0;transform:translateY(4px)}to{opacity:1;transform:none}}
176
206
  .slm-ch-secret{display:flex;align-items:center;gap:8px;padding:10px 12px;border:1px dashed rgba(244,183,64,.55);
177
- border-radius:10px;background:rgba(244,183,64,.06);font-family:ui-monospace,Menlo,monospace;font-size:11px;
207
+ border-radius:10px;background:rgba(244,183,64,.06);color:var(--slm-text);
208
+ font-family:ui-monospace,Menlo,monospace;font-size:11px;
178
209
  overflow:hidden;white-space:nowrap;text-overflow:ellipsis}
179
210
  .slm-ch-err{color:var(--slm-text);font-size:11.5px;margin-top:6px}
180
211
  .slm-ch-price-list{display:flex;flex-direction:column;gap:7px}
@@ -186,12 +217,25 @@
186
217
  .slm-ch-price-row small{font-size:10.5px;color:var(--slm-muted);font-weight:500}
187
218
  .slm-ch-price-row .slm-input{margin:0;text-align:right;font-variant-numeric:tabular-nums}
188
219
 
189
- /* buyer links \u2014 STATUS only; there is no Copy control on this card */
220
+ /* buyer links \u2014 STATUS only on the listing card: the URL is revealed once, at
221
+ creation, and the server keeps only a fingerprint, so there is nothing for a
222
+ listing-card Copy to write. Copy lives on the reveal sheet, where the string
223
+ actually exists. */
190
224
  .slm-ch-link{padding:10px 11px;border:1px solid var(--slm-line);border-radius:10px;background:var(--slm-surface);
191
225
  margin-bottom:8px}
192
226
  .slm-ch-link .lk-head{display:flex;align-items:center;gap:8px}
193
227
  .slm-ch-link .lk-name{flex:1;min-width:0;font-size:12.5px;font-weight:800;overflow:hidden;text-overflow:ellipsis;
194
228
  white-space:nowrap}
229
+ /* The revealed URL: one mono line that truncates rather than wrapping the sheet
230
+ out of shape. The full string stays in the title attribute and in the copy. */
231
+ .slm-ch-copyrow{display:flex;align-items:center;gap:8px;margin-top:8px}
232
+ .slm-ch-copyrow .slm-ch-secret{flex:1;min-width:0;margin:0}
233
+ .slm-ch-copyrow .slm-btn{flex:none;min-width:0;padding:8px 12px;min-height:40px;font-size:12px;
234
+ transition:opacity var(--slm-mo-quick) var(--slm-mo-out)}
235
+ /* "Copied" is a moment on the same control, never a second control: the label
236
+ changes and the button dims for the length of the confirmation. */
237
+ .slm-ch-copyrow .slm-btn.copied{opacity:.72}
238
+ .slm-ch-copysink{position:absolute;left:-9999px;top:0;width:1px;height:1px;opacity:0}
195
239
  .slm-ch-lkrow{display:flex;gap:8px;margin-top:5px;font-size:11px;color:var(--slm-muted)}
196
240
  .slm-ch-lkrow .k{flex:none;min-width:104px}
197
241
  .slm-ch-lkrow .v{color:var(--slm-text);font-variant-numeric:tabular-nums}
@@ -239,12 +283,16 @@
239
283
 
240
284
  /* compact: bottom sheet with three detents (\xA713) */
241
285
  .slm.compact.ch-sheet .slm-rail{position:absolute;left:0;right:0;bottom:0;z-index:8;border-top:1px solid var(--slm-line);
242
- border-radius:18px 18px 0 0;background:#12151f;
286
+ border-radius:18px 18px 0 0;background:var(--slm-surface);color:var(--slm-text);
243
287
  transition:height var(--slm-mo-slow) var(--slm-mo-in-out)}
244
288
  .slm.compact.ch-sheet.detent-collapsed .slm-rail{height:132px}
245
289
  .slm.compact.ch-sheet.detent-medium .slm-rail{height:46%}
246
290
  .slm.compact.ch-sheet.detent-full .slm-rail{height:92%}
247
291
  .slm.compact.ch-sheet .slm-railscroll{padding:8px 14px calc(12px + env(safe-area-inset-bottom,0px))}
292
+ /* Same pinned header in the sheet, bled against the sheet's own padding so the
293
+ create action is in reach at every detent. */
294
+ .slm.compact.ch-sheet .slm-ch-listhead{top:-8px;margin:0 -14px 10px;padding:8px 14px 8px}
295
+ .slm.compact .slm-ch-new{min-height:40px}
248
296
  .slm-ch-grab{display:none}
249
297
  .slm.compact.ch-sheet .slm-ch-grab{display:flex;align-items:center;gap:10px;width:100%;padding:6px 0 10px}
250
298
  .slm-ch-grabbar{width:42px;height:4px;border-radius:2px;background:var(--slm-muted);margin:0 auto}
@@ -252,26 +300,26 @@
252
300
  .slm.compact .slm-btn,.slm.compact .slm-ch-row,.slm.compact .slm-ch-viewseg button{min-height:44px}
253
301
  @media (prefers-reduced-motion:reduce){
254
302
  .slm-ch-layer,.slm-ch-banner,.slm-ch-staged,.slm-ch-row,.slm.compact.ch-sheet .slm-rail,
255
- .slm-ch-meter i,.slm-ch-radio{transition:none!important}
303
+ .slm-ch-meter i,.slm-ch-radio,.slm-ch-copyrow .slm-btn{transition:none!important}
256
304
  .slm-ch-staged.shake,.slm-ch-tick,.slm-ch-bucket,.slm-ch-scrim,.slm-ch-dialog,
257
305
  .slm-ch-counts b.bump,.slm-ch-selnum.bump{animation:none!important}
258
306
  .slm-ch-busy::before{animation:none!important;opacity:1}
259
307
  .slm-ch-staged.shake{outline:2px solid #e5484d;outline-offset:2px}
260
308
  .slm-ch-staged.done{outline:2px solid #5bd39b;outline-offset:2px}
261
309
  }
262
- `});var Lt={};Ue(Lt,{CHANNELS_CSS:()=>xt,ChannelsMode:()=>se,bucketRowsHtml:()=>W});var as,St,M,se,_e=j(()=>{"use strict";Ie();Re();re();kt();$e();wt();$e();as=3e4,St=300,M=5e3,se=class{constructor(e,t){this.active=!1;this.list=null;this.allocation=new Map;this.assignmentVersion=0;this.loadError=null;this.loading=!0;this.view="inspect";this.mapIntent="pan";this.focusedSectionId=null;this.showArchived=!1;this.detailChannelId=null;this.assignOpen=!1;this.targetChannelId="";this.conflict=!1;this.dialog=null;this.detent="medium";this.seatListLimit=St;this.links=[];this.linksChannelId=null;this.linksState="idle";this.listSeq=0;this.linksSeq=0;this.previewAudience=[];this.previewIncludePublic=!1;this.previewProjection=null;this.previewState="idle";this.pollTimer=null;this.layer=null;this.canvas=null;this.ctx=void 0;this.bannerEl=null;this.stagedEl=null;this.liveEl=null;this.scrimEl=null;this.lastFocus=null;this.stagedDoneTimer=null;this.lastSelectionCount=0;this.lastCounts=new Map;this.assignmentRowsCache=null;this.railHtml=null;this.allocationVersion=null;this.onVisibility=null;this.host=e,this.caps=t}enter(){this.active||(this.active=!0,this.mapIntent="pan",this.assignOpen=!1,this.focusedSectionId=null,this.assignmentRowsCache=null,this.railHtml=null,this.ensureLayer(),this.host.root.classList.add("ch-mode"),this.applySheetClasses(),this.host.sections().length>1&&this.host.showSectionOverview(),this.paintRail(),this.onInteractionChange?.(),this.refresh(),this.pollTimer=setInterval(()=>{typeof document<"u"&&document.hidden||this.refresh({quiet:!0})},as),typeof document<"u"&&typeof document.addEventListener=="function"&&(this.onVisibility=()=>{this.active&&!document.hidden&&this.refresh({quiet:!0})},document.addEventListener("visibilitychange",this.onVisibility)))}leave(){this.active&&(this.active=!1,this.pollTimer&&clearInterval(this.pollTimer),this.pollTimer=null,this.onVisibility&&typeof document<"u"&&document.removeEventListener("visibilitychange",this.onVisibility),this.onVisibility=null,this.railHtml=null,this.closeDialog({restoreFocus:!1}),this.links=[],this.linksChannelId=null,this.linksState="idle",this.layer?.classList.remove("on"),this.host.root.classList.remove("ch-mode","ch-preview","ch-sheet","detent-collapsed","detent-medium","detent-full"),this.setBanner(!1),this.setStaged(null))}destroy(){this.leave(),this.stagedDoneTimer&&clearTimeout(this.stagedDoneTimer),this.layer?.remove(),this.layer=null}setCapabilities(e){this.caps=e,this.active&&this.paintRail()}isActive(){return this.active}canSelect(){return this.caps.manage&&this.view==="inspect"}usesMarqueeSelection(){return this.canSelect()&&this.mapIntent==="assign"}handleSectionFocus(e){this.active&&(this.focusedSectionId=e,this.paintRail())}applyRealtimeHint(){this.active&&this.refresh({quiet:!0})}handleSelectionChange(){this.active&&(this.paintSelection(),this.paintStagedBar())}handleViewChange(){this.active&&this.paintOverlay()}handleLayoutChange(){this.active&&(this.applySheetClasses(),this.paintOverlay())}async refresh(e={}){if(!this.caps.view)return;let t=++this.listSeq,s=()=>t!==this.listSeq;try{let n=await this.host.api.channels(this.host.eventKey,{includeArchived:this.showArchived});if(s())return;if(this.list=n,this.assignmentVersion=n.assignmentVersion,this.loadError=null,this.targetChannelId||(this.targetChannelId=n.channels.find(i=>i.state==="active")?.id??T),this.allocationVersion!==n.assignmentVersion){if(await this.loadAllocation(t),s())return;this.allocationVersion=n.assignmentVersion}if(this.detailChannelId&&await this.loadLinks(this.detailChannelId),s())return;this.loading=!1,this.active&&(this.paintRail(),this.paintOverlay())}catch(n){if(s())return;this.loading=!1,n instanceof y&&n.status===403&&(this.caps={view:!1,manage:!1}),this.loadError=n,e.quiet||this.host.onError(n),this.active&&this.paintRail()}}async loadAllocation(e){let t=new Map,s;for(let n=0;n<200;n+=1){if(e!==void 0&&e!==this.listSeq)return;let i=await this.host.api.channelAllocation(this.host.eventKey,{afterLabel:s,limit:1e3});for(let a of i.allocations)B(a.channelId)||t.set(a.label,a.channelId);if(this.assignmentVersion=i.assignmentVersion,!i.nextAfterLabel)break;s=i.nextAfterLabel}e!==void 0&&e!==this.listSeq||(this.allocation=t)}channelById(e){if(B(e))return{id:T,name:this.list?.publicSale?.name??A,marker:"P",color:null};let t=this.list?.channels.find(s=>s.id===e);return t?{id:e,name:t.name,marker:t.marker,color:t.color}:null}nameOf(e){return this.channelById(e)?.name??null}markerFor(e){let t=Math.max(0,this.list?.channels.findIndex(n=>n.id===e)??0),s=this.channelById(e);return ge(s??{id:e,name:"?",marker:null,color:null},t)}assignableChannels(){return[{id:T,name:this.list?.publicSale.name??A},...(this.list?.channels??[]).filter(e=>e.state!=="archived").map(e=>({id:e.id,name:e.name}))]}currentPlan(){let e=this.host.selectionLabels(),t=fe({labels:e,targetChannelId:this.targetChannelId,allocation:this.allocation,statusOf:s=>this.host.statusOf(s),nameOf:s=>this.nameOf(s)});return{labels:e,buckets:t,target:this.targetChannelId}}ensureLayer(){if(this.layer)return;let e=document.createElement("div");e.className="slm-ch-layer",e.innerHTML=`
310
+ `});var At={};Ke(At,{CHANNELS_CSS:()=>Rt,ChannelsMode:()=>ne,bucketRowsHtml:()=>W});var bs,Et,I,ne,Ve=_(()=>{"use strict";Pe();Ee();ce();Tt();Ae();$t();Ae();bs=3e4,Et=300,I=5e3,ne=class{constructor(e,t){this.active=!1;this.list=null;this.allocation=new Map;this.assignmentVersion=0;this.loadError=null;this.loading=!0;this.view="inspect";this.mapIntent="pan";this.focusedSectionId=null;this.showArchived=!1;this.detailChannelId=null;this.assignOpen=!1;this.targetChannelId="";this.conflict=!1;this.dialog=null;this.detent="medium";this.seatListLimit=Et;this.links=[];this.linksChannelId=null;this.linksState="idle";this.listSeq=0;this.linksSeq=0;this.previewAudience=[];this.previewIncludePublic=!1;this.previewProjection=null;this.previewState="idle";this.pollTimer=null;this.layer=null;this.canvas=null;this.ctx=void 0;this.bannerEl=null;this.stagedEl=null;this.liveEl=null;this.scrimEl=null;this.lastFocus=null;this.stagedDoneTimer=null;this.lastSelectionCount=0;this.lastCounts=new Map;this.assignmentRowsCache=null;this.railHtml=null;this.allocationVersion=null;this.onVisibility=null;this.host=e,this.caps=t}enter(){this.active||(this.active=!0,this.mapIntent="pan",this.assignOpen=!1,this.focusedSectionId=null,this.assignmentRowsCache=null,this.railHtml=null,this.ensureLayer(),this.host.root.classList.add("ch-mode"),this.applySheetClasses(),this.host.sections().length>1&&this.host.showSectionOverview(),this.paintRail(),this.onInteractionChange?.(),this.refresh(),this.pollTimer=setInterval(()=>{typeof document<"u"&&document.hidden||this.refresh({quiet:!0})},bs),typeof document<"u"&&typeof document.addEventListener=="function"&&(this.onVisibility=()=>{this.active&&!document.hidden&&this.refresh({quiet:!0})},document.addEventListener("visibilitychange",this.onVisibility)))}leave(){this.active&&(this.active=!1,this.pollTimer&&clearInterval(this.pollTimer),this.pollTimer=null,this.onVisibility&&typeof document<"u"&&document.removeEventListener("visibilitychange",this.onVisibility),this.onVisibility=null,this.railHtml=null,this.closeDialog({restoreFocus:!1}),this.links=[],this.linksChannelId=null,this.linksState="idle",this.layer?.classList.remove("on"),this.host.root.classList.remove("ch-mode","ch-preview","ch-sheet","detent-collapsed","detent-medium","detent-full"),this.setBanner(!1),this.setStaged(null))}destroy(){this.leave(),this.stagedDoneTimer&&clearTimeout(this.stagedDoneTimer),this.layer?.remove(),this.layer=null,this.bannerEl?.remove(),this.bannerEl=null}setCapabilities(e){this.caps=e,this.active&&this.paintRail()}isActive(){return this.active}canSelect(){return this.caps.manage&&this.view==="inspect"}usesMarqueeSelection(){return this.canSelect()&&this.mapIntent==="assign"}handleSectionFocus(e){this.active&&(this.focusedSectionId=e,this.paintRail())}applyRealtimeHint(){this.active&&this.refresh({quiet:!0})}handleSelectionChange(){this.active&&(this.paintSelection(),this.paintStagedBar())}handleViewChange(){this.active&&this.paintOverlay()}handleLayoutChange(){this.active&&(this.applySheetClasses(),this.paintOverlay())}async refresh(e={}){if(!this.caps.view)return;let t=++this.listSeq,s=()=>t!==this.listSeq;try{let n=await this.host.api.channels(this.host.eventKey,{includeArchived:this.showArchived});if(s())return;if(this.list=n,this.assignmentVersion=n.assignmentVersion,this.loadError=null,this.targetChannelId||(this.targetChannelId=n.channels.find(i=>i.state==="active")?.id??T),this.allocationVersion!==n.assignmentVersion){if(await this.loadAllocation(t),s())return;this.allocationVersion=n.assignmentVersion}if(this.detailChannelId&&await this.loadLinks(this.detailChannelId),s())return;this.loading=!1,this.active&&(this.paintRail(),this.paintOverlay())}catch(n){if(s())return;this.loading=!1,n instanceof x&&n.status===403&&(this.caps={view:!1,manage:!1}),this.loadError=n,e.quiet||this.host.onError(n),this.active&&this.paintRail()}}async loadAllocation(e){let t=new Map,s;for(let n=0;n<200;n+=1){if(e!==void 0&&e!==this.listSeq)return;let i=await this.host.api.channelAllocation(this.host.eventKey,{afterLabel:s,limit:1e3});for(let a of i.allocations)D(a.channelId)||t.set(a.label,a.channelId);if(this.assignmentVersion=i.assignmentVersion,!i.nextAfterLabel)break;s=i.nextAfterLabel}e!==void 0&&e!==this.listSeq||(this.allocation=t)}channelById(e){if(D(e))return{id:T,name:this.list?.publicSale?.name??M,marker:"P",color:null};let t=this.list?.channels.find(s=>s.id===e);return t?{id:e,name:t.name,marker:t.marker,color:t.color}:null}nameOf(e){return this.channelById(e)?.name??null}markerFor(e){let t=Math.max(0,this.list?.channels.findIndex(n=>n.id===e)??0),s=this.channelById(e);return fe(s??{id:e,name:"?",marker:null,color:null},t)}assignableChannels(){return[{id:T,name:this.list?.publicSale.name??M},...(this.list?.channels??[]).filter(e=>e.state!=="archived").map(e=>({id:e.id,name:e.name}))]}currentPlan(){let e=this.host.selectionLabels(),t=ke({labels:e,targetChannelId:this.targetChannelId,allocation:this.allocation,statusOf:s=>this.host.statusOf(s),nameOf:s=>this.nameOf(s)});return{labels:e,buckets:t,target:this.targetChannelId}}ensureLayer(){if(this.layer)return;let e=document.createElement("div");e.className="slm-ch-layer",e.innerHTML=`
263
311
  <canvas class="slm-ch-canvas" data-ch="canvas" aria-hidden="true"></canvas>
264
312
  <div class="slm-ch-banner" data-ch="banner" role="status"></div>
265
313
  <div class="slm-ch-staged" data-ch="staged" role="group" aria-label="Staged channel changes"></div>
266
- <div class="slm-ch-live" data-ch="live" role="status" aria-live="polite"></div>`,this.host.mapLayer.appendChild(e),this.layer=e,this.canvas=e.querySelector('[data-ch="canvas"]'),this.bannerEl=e.querySelector('[data-ch="banner"]'),this.stagedEl=e.querySelector('[data-ch="staged"]'),this.liveEl=e.querySelector('[data-ch="live"]'),requestAnimationFrame(()=>e.classList.add("on"))}announce(e){this.liveEl&&(this.liveEl.textContent=e)}paintOverlay(){let e=this.canvas,t=this.layer;!e||!t||yt({layer:t,canvas:e,resolveCtx:()=>{if(this.ctx===void 0)try{this.ctx=e.getContext("2d")}catch{this.ctx=null}return this.ctx},host:this.host,view:this.view,previewProjection:this.previewProjection,allocation:this.allocation,focusedSectionId:this.focusedSectionId,list:this.list,markerFor:s=>this.markerFor(s),onSectionTargetClick:s=>{this.focusedSectionId=s,this.host.focusSection(s),this.paintRail()}})}setStaged(e,t=""){let s=this.stagedEl;if(s){if(!e){s.classList.remove("on","done","shake"),s.innerHTML="";return}s.innerHTML=e,s.className=`slm-ch-staged on${t?` ${t}`:""}`}}paintStagedBar(){if(!this.active||this.view==="preview"||!this.caps.manage){this.setStaged(null);return}let{labels:e,buckets:t}=this.currentPlan();if(this.host.onStagedChange?.(K(t)),!e.length){this.setStaged(null);return}let s=this.nameOf(this.targetChannelId)??A,n=K(t),i=e.length>M,a=t.skippedHeld.count+t.skippedBooked.count,o=[`<b>${e.length.toLocaleString()}</b> selected`,`<b>+${n.toLocaleString()}</b> to ${p(s)}`];t.alreadyInTarget.count&&o.push(`<b>${t.alreadyInTarget.count.toLocaleString()}</b> already in`),a&&o.push(`<b>${a.toLocaleString()}</b> can't move now`),this.setStaged(`
314
+ <div class="slm-ch-live" data-ch="live" role="status" aria-live="polite"></div>`,this.host.mapLayer.appendChild(e),this.layer=e,this.canvas=e.querySelector('[data-ch="canvas"]'),this.bannerEl=e.querySelector('[data-ch="banner"]'),this.bannerEl&&this.host.pillLane&&this.host.pillLane.appendChild(this.bannerEl),this.stagedEl=e.querySelector('[data-ch="staged"]'),this.liveEl=e.querySelector('[data-ch="live"]'),requestAnimationFrame(()=>e.classList.add("on"))}announce(e){this.liveEl&&(this.liveEl.textContent=e)}paintOverlay(){let e=this.canvas,t=this.layer;!e||!t||Ct({layer:t,canvas:e,resolveCtx:()=>{if(this.ctx===void 0)try{this.ctx=e.getContext("2d")}catch{this.ctx=null}return this.ctx},host:this.host,view:this.view,previewProjection:this.previewProjection,allocation:this.allocation,focusedSectionId:this.focusedSectionId,list:this.list,markerFor:s=>this.markerFor(s),onSectionTargetClick:s=>{this.focusedSectionId=s,this.host.focusSection(s),this.paintRail()}})}setStaged(e,t=""){let s=this.stagedEl;if(s){if(!e){s.classList.remove("on","done","shake"),s.innerHTML="";return}s.innerHTML=e,s.className=`slm-ch-staged on${t?` ${t}`:""}`}}paintStagedBar(){if(!this.active||this.view==="preview"||!this.caps.manage){this.setStaged(null);return}let{labels:e,buckets:t}=this.currentPlan();if(this.host.onStagedChange?.(Y(t)),!e.length){this.setStaged(null);return}let s=this.nameOf(this.targetChannelId)??M,n=Y(t),i=e.length>I,a=t.skippedHeld.count+t.skippedBooked.count,o=[`<b>${e.length.toLocaleString()}</b> selected`,`<b>+${n.toLocaleString()}</b> to ${p(s)}`];t.alreadyInTarget.count&&o.push(`<b>${t.alreadyInTarget.count.toLocaleString()}</b> already in`),a&&o.push(`<b>${a.toLocaleString()}</b> can't move now`),this.setStaged(`
267
315
  <span>${o.join(" \xB7 ")}</span>
268
316
  <span class="grow"></span>
269
317
  <button type="button" class="drop" data-ch-act="discard">Discard</button>
270
318
  <button type="button" class="go" data-ch-act="review"${i?" disabled":""}>
271
- ${i?`Maximum ${M.toLocaleString()} seats`:"Review changes"}
319
+ ${i?`Maximum ${I.toLocaleString()} seats`:"Review changes"}
272
320
  </button>`),this.stagedEl?.querySelectorAll("[data-ch-act]").forEach(r=>{r.addEventListener("click",()=>{r.dataset.chAct==="discard"?this.host.clearSelection():this.openDialog({kind:"review"})})})}setBanner(e,t="",s){let n=this.bannerEl;if(!n)return;if(this.host.root.classList.toggle("ch-preview",e),!e){n.classList.remove("on"),n.innerHTML="";return}let i=this.previewAudience.length===1?this.markerFor(this.previewAudience[0]):{color:"var(--slm-accent)",letter:""},a=s==null?"":` \xB7 ${s.toLocaleString()} ${s===1?"seat":"seats"} available now`;n.innerHTML=`<span class="dot" style="background:${p(i.color)}"></span>
273
321
  Previewing buyer access \xB7 ${p(t)}${a} \xB7 read-only
274
- <button type="button" data-ch-act="exit-preview">Exit preview</button>`,n.classList.add("on"),n.querySelector('[data-ch-act="exit-preview"]')?.addEventListener("click",()=>this.setView("inspect"))}setView(e){if(this.view=e,e==="inspect")this.previewProjection=null,this.previewState="idle",this.setBanner(!1);else{if(!this.previewAudience.length){let t=this.list?.channels.find(s=>s.state==="active");this.previewAudience=[t?t.id:T]}this.loadPreview()}this.paintRail(),this.paintOverlay(),this.paintStagedBar(),this.onInteractionChange?.()}async loadPreview(){let e=[...this.previewAudience],t=e.map(s=>this.nameOf(s)??A).join(" + ");this.setBanner(!0,t),this.previewProjection=null,this.previewState="loading",this.active&&this.paintRail();try{this.previewProjection=await this.host.api.channelPreview(this.host.eventKey,e,{includePublic:this.previewIncludePublic||e.some(B)}),this.previewState="ready";let s=this.previewProjection.available===!1?void 0:this.previewProjection.counts?.eligible??this.previewProjection.eligible?.length;this.setBanner(!0,t,s)}catch(s){let n=s instanceof y?s.status:0;this.previewState=n===404||n===405||n===501?"unsupported":"error",this.previewProjection=null,this.previewState==="error"&&this.host.onError(s)}this.active&&(this.paintRail(),this.paintOverlay())}setRailHtml(e){if(e===this.railHtml)return!1;let t=this.host.rail,s=t.scrollTop;return t.innerHTML=e,this.railHtml=e,s&&(t.scrollTop=s),!0}paintRail(){if(!this.active)return;let e=this.host.rail;if(!this.caps.view){this.setRailHtml(`<p class="slm-eyebrow">Sales channels</p>
322
+ <button type="button" data-ch-act="exit-preview">Exit preview</button>`,n.classList.add("on"),n.querySelector('[data-ch-act="exit-preview"]')?.addEventListener("click",()=>this.setView("inspect"))}setView(e){if(this.view=e,e==="inspect")this.previewProjection=null,this.previewState="idle",this.setBanner(!1);else{if(!this.previewAudience.length){let t=this.list?.channels.find(s=>s.state==="active");this.previewAudience=[t?t.id:T]}this.loadPreview()}this.paintRail(),this.paintOverlay(),this.paintStagedBar(),this.onInteractionChange?.()}async loadPreview(){let e=[...this.previewAudience],t=e.map(s=>this.nameOf(s)??M).join(" + ");this.setBanner(!0,t),this.previewProjection=null,this.previewState="loading",this.active&&this.paintRail();try{this.previewProjection=await this.host.api.channelPreview(this.host.eventKey,e,{includePublic:this.previewIncludePublic||e.some(D)}),this.previewState="ready";let s=this.previewProjection.available===!1?void 0:this.previewProjection.counts?.eligible??this.previewProjection.eligible?.length;this.setBanner(!0,t,s)}catch(s){let n=s instanceof x?s.status:0;this.previewState=n===404||n===405||n===501?"unsupported":"error",this.previewProjection=null,this.previewState==="error"&&this.host.onError(s)}this.active&&(this.paintRail(),this.paintOverlay())}setRailHtml(e){if(e===this.railHtml)return!1;let t=this.host.rail,s=t.scrollTop;return t.innerHTML=e,this.railHtml=e,s&&(t.scrollTop=s),!0}paintRail(){if(!this.active)return;let e=this.host.rail;if(!this.caps.view){this.setRailHtml(`<p class="slm-eyebrow">Sales channels</p>
275
323
  <p class="slm-hint">You need channel-management permission on this event to see allocations.</p>`);return}if(this.loading&&!this.list){this.setRailHtml(`<p class="slm-eyebrow">Sales channels</p>
276
324
  <div class="slm-ch-busy" role="status" data-ch-state="list-loading">Loading channels and allocations\u2026</div>`);return}if(!this.list&&this.loadError){this.setRailHtml(`<p class="slm-eyebrow">Sales channels</p>
277
325
  <div class="slm-ch-alert err" role="alert" data-ch-state="list-error"><span>\u26A0</span>
@@ -283,23 +331,23 @@
283
331
  <button type="button" class="${t.trim()}" data-ch-view="preview"
284
332
  aria-pressed="${this.view==="preview"}">Buyer preview</button>
285
333
  </div>${this.mapNavigationHtml()}`}mapNavigationHtml(){if(this.host.sections().length<2)return"";let e=this.focusedSectionId?this.host.sections().find(t=>t.id===this.focusedSectionId)?.label??"section":null;return e?`<div class="slm-ch-mapnav-head"><span>${p(e)}</span>
286
- <button type="button" data-ch-act="sections">All sections</button></div>`:""}countsHtml(e,t){let s=(n,i,a,o="")=>{let r=this.lastCounts.get(`${t}:${n}`),c=r!=null&&r!==i?" bump":"";return this.lastCounts.set(`${t}:${n}`,i),`<span class="${o}"><b class="${c.trim()}">${i.toLocaleString()}</b> ${a}</span>`};return`<span class="slm-ch-counts">
334
+ <button type="button" data-ch-act="sections">All sections</button></div>`:""}countsHtml(e,t){let s=(n,i,a,o="")=>{let r=this.lastCounts.get(`${t}:${n}`),d=r!=null&&r!==i?" bump":"";return this.lastCounts.set(`${t}:${n}`,i),`<span class="${o}"><b class="${d.trim()}">${i.toLocaleString()}</b> ${a}</span>`};return`<span class="slm-ch-counts">
287
335
  ${s("allocated",e.allocated,"allocated")}
288
336
  ${s("free",e.free,"free","free")}
289
337
  ${s("booked",e.booked,"sold")}
290
338
  ${e.held?s("held",e.held,"held"):""}
291
339
  </span>`}channelRowHtml(e,t={}){let s=this.markerFor(e.id),n=t.builtin?"builtin":e.state,i=e.state==="paused"||e.state==="archived"?" dim":"",a=!t.builtin&&this.caps.manage&&this.detailChannelId!==e.id,o=`slm-ch-row${t.builtin?" public":""}${e.state==="archived"?" archived":""}${this.detailChannelId===e.id?" on":""}${a?" open":""}`,r=!t.builtin&&this.caps.manage?`<button type="button" class="slm-ch-more" data-ch-menu="${p(e.id)}"
292
- aria-label="More actions for ${p(e.name)}" aria-haspopup="dialog">\u22EF</button>`:"",c=a?` role="button" tabindex="0" data-ch-open="${p(e.id)}"
293
- aria-label="Open ${p(e.name)}"`:"";return`<div class="${o}"${c}>
340
+ aria-label="More actions for ${p(e.name)}" aria-haspopup="dialog">\u22EF</button>`:"",d=a?` role="button" tabindex="0" data-ch-open="${p(e.id)}"
341
+ aria-label="Open ${p(e.name)}"`:"";return`<div class="${o}"${d}>
294
342
  <span class="slm-ch-head">
295
343
  <span class="slm-ch-mk${i}" style="background:${p(s.color)}" aria-hidden="true">${p(s.letter)}</span>
296
344
  <span class="slm-ch-name">${p(e.name)}</span>
297
- <span class="slm-ch-badge ${n}">${p(Te(t.builtin?"builtin":e.state))}</span>
345
+ <span class="slm-ch-badge ${n}">${p($e(t.builtin?"builtin":e.state))}</span>
298
346
  ${r}
299
347
  </span>
300
348
  ${this.countsHtml(e.counts,e.id||"public")}
301
- ${t.builtin?"":`<span class="slm-ch-access">${p(we(e.access))}</span>`}
302
- </div>`}listRailHtml(){let e=this.list,t=e.channels.filter(r=>r.state==="archived").length,s=e.channels.filter(r=>this.showArchived||r.state!=="archived"),n=[this.channelRowHtml(e.publicSale,{builtin:!0}),...s.map((r,c)=>this.channelRowHtml(r,{index:c}))].join(""),i=s.length?"":`<p class="slm-note" data-ch-state="list-empty">${t&&!this.showArchived?`No open channels \u2014 every seat is on public sale. ${t.toLocaleString()} archived channel${t===1?" is":"s are"} hidden below.`:"No private channels yet \u2014 every seat is on public sale."}</p>`,a=this.caps.manage?'<button type="button" class="slm-linkbtn" data-ch-act="create">+ New channel</button>':"",o=this.caps.manage?"":'<p class="slm-note">You can see how inventory is allocated. Changing it needs channel-management permission.</p>';return`
349
+ ${t.builtin?"":`<span class="slm-ch-access">${p(Le(e.access))}</span>`}
350
+ </div>`}listRailHtml(){let e=this.list,t=e.channels.filter(r=>r.state==="archived").length,s=e.channels.filter(r=>this.showArchived||r.state!=="archived"),n=[this.channelRowHtml(e.publicSale,{builtin:!0}),...s.map((r,d)=>this.channelRowHtml(r,{index:d}))].join(""),i=s.length?"":`<p class="slm-note" data-ch-state="list-empty">${t&&!this.showArchived?`No open channels \u2014 every seat is on public sale. ${t.toLocaleString()} archived channel${t===1?" is":"s are"} hidden below.`:"No private channels yet \u2014 every seat is on public sale."}</p>`,a=this.caps.manage?'<button type="button" class="slm-btn slm-ch-new" data-ch-act="create">+ New channel</button>':"",o=this.caps.manage?"":'<p class="slm-note">You can see how inventory is allocated. Changing it needs channel-management permission.</p>';return`
303
351
  <div class="slm-ch-listhead"><h2>Sales channels</h2>${a}</div>
304
352
  <div class="slm-ch-list">${n}</div>
305
353
  ${i}
@@ -327,10 +375,10 @@
327
375
  <button type="button" class="slm-btn ghost" data-ch-act="seatlist">Seat list \u2328</button>
328
376
  </div>
329
377
  <p class="slm-note" style="margin-bottom:18px">Choose a destination, then add whole sections,
330
- multiple rows, a dragged area, or individual seats.</p>`}selectionRailHtml(e){let t=ve(e,this.allocation,this.list),s=this.conflict?`<div class="slm-ch-alert err" role="alert"><span>\u26A0</span>
378
+ multiple rows, a dragged area, or individual seats.</p>`}selectionRailHtml(e){let t=ye(e,this.allocation,this.list),s=this.conflict?`<div class="slm-ch-alert err" role="alert"><span>\u26A0</span>
331
379
  <span><b>Assignments changed while you were editing.</b> Nothing was applied.
332
380
  Your ${e.length.toLocaleString()}-seat selection is kept.
333
- <button type="button" data-ch-act="refresh-review">Refresh and review \u2192</button></span></div>`:"",n=e.length!==this.lastSelectionCount?" bump":"";this.lastSelectionCount=e.length;let i=e.length>M,a=t.map(o=>{let r=this.markerFor(o.channelId);return`<div class="slm-ch-selsrc-row">
381
+ <button type="button" data-ch-act="refresh-review">Refresh and review \u2192</button></span></div>`:"",n=e.length!==this.lastSelectionCount?" bump":"";this.lastSelectionCount=e.length;let i=e.length>I,a=t.map(o=>{let r=this.markerFor(o.channelId);return`<div class="slm-ch-selsrc-row">
334
382
  <span class="mk" style="background:${p(r.color)}" aria-hidden="true">${p(r.letter)}</span>
335
383
  <b>${o.count.toLocaleString()}</b><span>${p(o.name)}</span></div>`}).join("");return`
336
384
  ${s}
@@ -339,7 +387,7 @@
339
387
  <span class="slm-sellabel">selected</span></div>
340
388
  <div class="slm-ch-selsrc" aria-live="polite" aria-label="Selection sources">${a}</div>
341
389
  ${i?`<div class="slm-ch-alert warn" role="alert"><span>\u2139</span><span>
342
- <b>This selection is too large to apply at once.</b> Choose at most ${M.toLocaleString()}
390
+ <b>This selection is too large to apply at once.</b> Choose at most ${I.toLocaleString()}
343
391
  seats, for example by splitting the venue into row groups.</span></div>`:""}
344
392
  <p class="slm-note">Changes are staged \u2014 nothing moves until you review and apply.
345
393
  Seats in checkout or already sold are never moved.</p>
@@ -371,11 +419,11 @@
371
419
  <div class="slm-ch-list">${this.channelRowHtml(s)}</div>
372
420
  ${o}
373
421
  ${i}
374
- ${n}`}distributeHtml(e){let t=e.access?.intent??"none",s=e.access?.hasActiveGrants===!0,n=this.linksState!=="unsupported",i=this.links.some(ee),a=t==="none"?"Protected reserve \u2014 no route can sell these seats. Every buyer path is refused.":t==="internal"?"Your staff sell these seats. No buyer-facing route is open.":s?t==="server"?"Your website is letting buyers in. Only they can buy these seats.":"A buyer link is live. Only people with that link can buy these seats.":t==="server"?"Set up for your website \u2014 no buyer has come through yet. Seats stay reserved.":"Set up for buyer links \u2014 no buyer has come through yet. Seats stay reserved.",o=(r,c,d,h)=>{let u=r===t;return`<div class="slm-ch-dist${u?" on":""}" data-ch-route="${p(r)}">
422
+ ${n}`}distributeHtml(e){let t=e.access?.intent??"none",s=e.access?.hasActiveGrants===!0,n=this.linksState!=="unsupported",i=this.links.some(te),a=t==="none"?"Protected reserve \u2014 no route can sell these seats. Every buyer path is refused.":t==="internal"?"Your staff sell these seats. No buyer-facing route is open.":s?t==="server"?"Your website is letting buyers in. Only they can buy these seats.":"A buyer link is live. Only people with that link can buy these seats.":t==="server"?"Set up for your website \u2014 no buyer has come through yet. Seats stay reserved.":"Set up for buyer links \u2014 no buyer has come through yet. Seats stay reserved.",o=(r,d,c,h)=>{let u=r===t;return`<div class="slm-ch-dist${u?" on":""}" data-ch-route="${p(r)}">
375
423
  <b>${p(F(r))}${u?'<span class="cur">Current route</span>':""}</b>
376
- <span class="why">${p(Se(r))}</span>
377
- ${u&&!d?"":`<button type="button" class="slm-btn${h&&!u?"":" ghost"}"
378
- data-ch-act="${p(c)}">${p(d)}</button>`}
424
+ <span class="why">${p(Ce(r))}</span>
425
+ ${u&&!c?"":`<button type="button" class="slm-btn${h&&!u?"":" ghost"}"
426
+ data-ch-act="${p(d)}">${p(c)}</button>`}
379
427
  </div>`};return`
380
428
  <p class="slm-eyebrow" style="margin-top:14px">Distribute</p>
381
429
  <p class="slm-hint">${p(a)}</p>
@@ -384,17 +432,17 @@
384
432
  ${o("internal","route-internal",t==="internal"?"":"Hand to your staff",!1)}
385
433
  ${o("none","route-none",t==="none"?"":"Keep as reserve",!1)}
386
434
  ${this.hostedLinksHtml()}
387
- ${t==="server"?vt:""}`}async loadLinks(e){if(!this.caps.view)return;let t=++this.linksSeq,s=()=>t!==this.linksSeq||this.linksChannelId!==e;this.linksChannelId!==e&&(this.links=[],this.linksChannelId=e,this.linksState="loading");try{let n=await this.host.api.accessLinks(this.host.eventKey,e);if(s())return;this.links=n.links??[],this.linksState="ready"}catch(n){if(s())return;let i=n instanceof y?n.status:0;this.links=[],this.linksState=i===404||i===405||i===501?"unsupported":"error",this.linksState==="error"&&this.host.onError(n)}}hostedLinksHtml(){let e='<p class="slm-eyebrow" style="margin-top:18px">Buyer links</p>';return this.linksState==="unsupported"?`${e}<div class="slm-ch-alert warn" data-ch-state="links-unsupported"><span>\u2139</span>
435
+ ${t==="server"?kt:""}`}async loadLinks(e){if(!this.caps.view)return;let t=++this.linksSeq,s=()=>t!==this.linksSeq||this.linksChannelId!==e;this.linksChannelId!==e&&(this.links=[],this.linksChannelId=e,this.linksState="loading");try{let n=await this.host.api.accessLinks(this.host.eventKey,e);if(s())return;this.links=n.links??[],this.linksState="ready"}catch(n){if(s())return;let i=n instanceof x?n.status:0;this.links=[],this.linksState=i===404||i===405||i===501?"unsupported":"error",this.linksState==="error"&&this.host.onError(n)}}hostedLinksHtml(){let e='<p class="slm-eyebrow" style="margin-top:18px">Buyer links</p>';return this.linksState==="unsupported"?`${e}<div class="slm-ch-alert warn" data-ch-state="links-unsupported"><span>\u2139</span>
388
436
  <span><b>Buyer links need a newer server.</b> Everything else on this channel works normally.</span></div>`:this.linksState==="error"?`${e}<div class="slm-ch-alert err" role="alert" data-ch-state="links-error"><span>\u26A0</span>
389
437
  <span><b>Couldn't load this channel's links.</b> This is a failed read, not an empty list \u2014
390
438
  any live link is still working.
391
439
  <button type="button" data-ch-act="link-reload">Try again</button></span></div>`:this.linksState==="idle"||this.linksState==="loading"&&!this.links.length?`${e}<div class="slm-ch-busy" role="status" data-ch-state="links-loading">Loading buyer links\u2026</div>`:this.links.length?`${e}
392
440
  ${this.links.map(t=>this.linkCardHtml(t)).join("")}
393
441
  <p class="slm-note">A link is shown once, when you create it. SeatLayer keeps only a fingerprint of it, so it
394
- can never be shown again \u2014 if a link is lost, rotate it and send the fresh one.</p>`:""}linkCardHtml(e){let t=Ce(e),s=e.maxRedemptions>0?Math.min(100,Math.round(e.redemptions/e.maxRedemptions*100)):0,n=te(e).map(r=>`<div class="slm-ch-lkrow"><span class="k">${p(r.k)}</span>
442
+ can never be shown again \u2014 if a link is lost, rotate it and send the fresh one.</p>`:""}linkCardHtml(e){let t=Re(e),s=e.maxRedemptions>0?Math.min(100,Math.round(e.redemptions/e.maxRedemptions*100)):0,n=se(e).map(r=>`<div class="slm-ch-lkrow"><span class="k">${p(r.k)}</span>
395
443
  <span class="v">${p(r.v)}</span></div>`).join(""),i=e.activeSessions?`<div class="slm-ch-lkrow"><span class="k">Buyers inside now</span>
396
444
  <span class="v">${e.activeSessions.toLocaleString()}</span></div>`:"",a=e.lastRedeemedAt?`<div class="slm-ch-lkrow"><span class="k">Last opened</span>
397
- <span class="v">${p(new Date(e.lastRedeemedAt).toLocaleString())}</span></div>`:"",o=this.caps.manage&&ee(e)?`<div class="slm-ch-row2">
445
+ <span class="v">${p(new Date(e.lastRedeemedAt).toLocaleString())}</span></div>`:"",o=this.caps.manage&&te(e)?`<div class="slm-ch-row2">
398
446
  <button type="button" class="slm-btn ghost" data-ch-rotate="${p(e.id)}">Rotate</button>
399
447
  <button type="button" class="slm-btn ghost" data-ch-revoke="${p(e.id)}">Revoke</button>
400
448
  </div>`:"";return`<div class="slm-ch-link">
@@ -409,15 +457,15 @@
409
457
  <div class="slm-ch-lkrow"><span class="k">The URL</span>
410
458
  <span class="v">Revealed once at creation \u2014 not recoverable</span></div>
411
459
  ${o}
412
- </div>`}previewRailHtml(){let e=[{id:T,name:this.list?.publicSale.name??A},...(this.list?.channels??[]).filter(h=>h.state!=="archived").map(h=>({id:h.id,name:h.name}))],t=this.previewAudience[0]??T,s=e.map(h=>`<option value="${p(h.id)}"${h.id===t?" selected":""}>${p(h.name)}</option>`).join(""),n=this.previewState==="unsupported"?`<div class="slm-ch-alert warn" data-ch-state="preview-unsupported"><span>\u2139</span>
460
+ </div>`}previewRailHtml(){let e=[{id:T,name:this.list?.publicSale.name??M},...(this.list?.channels??[]).filter(h=>h.state!=="archived").map(h=>({id:h.id,name:h.name}))],t=this.previewAudience[0]??T,s=e.map(h=>`<option value="${p(h.id)}"${h.id===t?" selected":""}>${p(h.name)}</option>`).join(""),n=this.previewState==="unsupported"?`<div class="slm-ch-alert warn" data-ch-state="preview-unsupported"><span>\u2139</span>
413
461
  <span><b>Preview needs a newer server.</b> Allocation management works normally;
414
462
  the buyer-view simulation will appear once this event's API is updated.</span></div>`:"",i=this.previewState==="loading"?'<div class="slm-ch-busy" role="status" data-ch-state="preview-loading">Asking the server what this audience sees\u2026</div>':"",a=this.previewState==="error"?`<div class="slm-ch-alert err" role="alert" data-ch-state="preview-error"><span>\u26A0</span>
415
463
  <span><b>Couldn't load the buyer preview.</b> Nothing is wrong with this audience's seats \u2014
416
464
  the simulation itself failed to load.
417
465
  <button type="button" data-ch-act="preview-retry">Try again</button></span></div>`:"",o=this.previewProjection?.available===!1?`<div class="slm-ch-alert warn" role="status"><span>\u23F8</span>
418
466
  <span><b>This private sale is not available.</b> ${p((this.previewProjection.unavailable??[]).map(h=>`${this.nameOf(h.channelId)??"This channel"} is ${h.state}`).join("; ")||"The audience cannot buy right now")}.
419
- A buyer arriving with this access sees this message, not these seats.</span></div>`:"",r=this.previewProjection?.counts?.eligible??this.previewProjection?.eligible?.length,c=r!=null&&this.previewProjection?.available!==!1?`<div class="slm-ch-alert info"><span>\u2713</span><span><b>${r.toLocaleString()} ${r===1?"seat is":"seats are"} available now.</b>
420
- This is the exact buyer-visible allocation.${this.previewProjection?.includePublic===!1?" Public sale seats are <b>not</b> included in this access.":""}</span></div>`:"",d=B(t)?"":`
467
+ A buyer arriving with this access sees this message, not these seats.</span></div>`:"",r=this.previewProjection?.counts?.eligible??this.previewProjection?.eligible?.length,d=r!=null&&this.previewProjection?.available!==!1?`<div class="slm-ch-alert info"><span>\u2713</span><span><b>${r.toLocaleString()} ${r===1?"seat is":"seats are"} available now.</b>
468
+ This is the exact buyer-visible allocation.${this.previewProjection?.includePublic===!1?" Public sale seats are <b>not</b> included in this access.":""}</span></div>`:"",c=D(t)?"":`
421
469
  <label class="slm-note" style="display:flex;gap:8px;align-items:center;margin:10px 0">
422
470
  <input type="checkbox" data-ch-includepublic ${this.previewIncludePublic?"checked":""} />
423
471
  Also include Public sale seats in this grant
@@ -427,7 +475,7 @@
427
475
  <label for="slm-ch-audience">Audience</label>
428
476
  <select class="slm-select" id="slm-ch-audience" data-ch-audience>${s}</select>
429
477
  </div>
430
- ${d}
478
+ ${c}
431
479
  <p class="slm-hint">This is the same projection the buyer SDK receives for this audience \u2014 not a local
432
480
  approximation. It is read-only: clicks open seat details, and no holds are created.</p>
433
481
  ${i}${a}${n}${o}
@@ -436,7 +484,7 @@
436
484
  <div class="r"><span class="sw" style="background:#3a4051"></span> Unavailable to this audience (one neutral state)</div>
437
485
  <div class="r"><span class="sw" style="background:#22a06b"></span> Sold \u2014 same as any buyer sees</div>
438
486
  </div>
439
- ${c}`}paintSelection(){this.caps.manage&&this.host.selectionLabels().length&&(this.assignOpen=!0),this.view==="inspect"&&!this.detailChannelId&&this.paintRail()}wireRail(){let e=this.host.rail;e.querySelectorAll("[data-ch-view]").forEach(a=>{a.addEventListener("click",()=>this.setView(a.dataset.chView))}),e.querySelectorAll("[data-ch-map]").forEach(a=>{a.addEventListener("click",()=>{this.mapIntent=a.dataset.chMap==="assign"?"assign":"pan",this.mapIntent==="assign"&&(this.assignOpen=!0),this.paintRail(),this.onInteractionChange?.()})}),e.querySelectorAll("[data-ch-open]").forEach(a=>{let o=()=>this.openChannel(a.dataset.chOpen);a.addEventListener("click",o),a.addEventListener("keydown",r=>{r.key!=="Enter"&&r.key!==" "&&r.key!=="Spacebar"||(r.preventDefault(),o())})}),e.querySelectorAll("[data-ch-menu]").forEach(a=>{a.addEventListener("click",o=>{o.stopPropagation(),this.openDialog({kind:"menu",channelId:a.dataset.chMenu})}),a.addEventListener("keydown",o=>{o.stopPropagation()})}),e.querySelectorAll("[data-ch-rotate]").forEach(a=>{a.addEventListener("click",()=>this.openDialog({kind:"linkRotate",channelId:this.detailChannelId,linkId:a.dataset.chRotate}))}),e.querySelectorAll("[data-ch-revoke]").forEach(a=>{a.addEventListener("click",()=>this.openDialog({kind:"linkRevoke",channelId:this.detailChannelId,linkId:a.dataset.chRevoke}))});let t=e.querySelector("[data-ch-target]");t?.addEventListener("change",()=>{this.targetChannelId=t.value,this.conflict=!1,this.paintRail()});let s=e.querySelector("[data-ch-audience]");s?.addEventListener("change",()=>{this.previewAudience=[s.value],this.loadPreview()});let n=e.querySelector("[data-ch-includepublic]");n?.addEventListener("change",()=>{this.previewIncludePublic=n.checked,this.loadPreview()}),e.querySelector(".slm-ch-grab")?.addEventListener("click",()=>this.cycleDetent()),e.querySelectorAll("[data-ch-act]").forEach(a=>{a.addEventListener("click",()=>this.railAction(a.dataset.chAct))})}openChannel(e){this.detailChannelId=e,this.paintRail(),this.loadLinks(e).then(()=>this.paintRail())}railAction(e){switch(e){case"sections":this.focusedSectionId=null,this.host.showSectionOverview(),this.paintRail();break;case"create":this.openDialog({kind:"create"});break;case"review":this.openDialog({kind:"review"});break;case"rename":this.openDialog({kind:"rename",channelId:this.detailChannelId});break;case"pricing":this.openDialog({kind:"pricing",channelId:this.detailChannelId});break;case"archive":this.openDialog({kind:"archive",channelId:this.detailChannelId});break;case"seatlist":this.openDialog({kind:"seatlist"});break;case"pause":this.togglePause();break;case"discard":this.host.clearSelection();break;case"back":this.detailChannelId=null,this.linksChannelId=null,this.links=[],this.linksState="idle",this.paintRail();break;case"link-create":this.openDialog({kind:"linkCreate",channelId:this.detailChannelId});break;case"embed-code":this.chooseWebsiteIntegration();break;case"route-internal":this.setAccessIntent("internal");break;case"route-none":this.setAccessIntent("none");break;case"link-reload":this.detailChannelId&&this.reloadLinks();break;case"retry":this.refresh();break;case"toggle-archived":this.showArchived=!this.showArchived,this.refresh();break;case"refresh-review":this.conflict=!1,this.refresh().then(()=>this.openDialog({kind:"review"}));break;case"pick-sections":this.openDialog({kind:"scope",scope:"sections"});break;case"pick-rows":this.openDialog({kind:"scope",scope:"rows"});break;case"drag-select":this.mapIntent="assign",this.paintRail(),this.onInteractionChange?.();break;case"pick-category":this.pickCategory();break;case"assign-open":this.assignOpen=!0,this.mapIntent="assign",this.paintRail(),this.onInteractionChange?.();break;case"assign-close":this.assignOpen=!1,this.mapIntent="pan",this.paintRail(),this.onInteractionChange?.();break;case"preview-retry":this.loadPreview();break;default:break}}assignmentRows(){return this.assignmentRowsCache||(this.assignmentRowsCache=this.host.rows()),this.assignmentRowsCache}pickCategory(){let e=this.host.categories();e.length&&this.promptChoice("Select a whole category",e.map(t=>({value:t.key,label:t.label})),t=>{this.host.selectByLabels(this.host.labelsInCategory(t))})}promptChoice(e,t,s){this.renderScrim(`
487
+ ${d}`}paintSelection(){this.caps.manage&&this.host.selectionLabels().length&&(this.assignOpen=!0),this.view==="inspect"&&!this.detailChannelId&&this.paintRail()}wireRail(){let e=this.host.rail;e.querySelectorAll("[data-ch-view]").forEach(a=>{a.addEventListener("click",()=>this.setView(a.dataset.chView))}),e.querySelectorAll("[data-ch-map]").forEach(a=>{a.addEventListener("click",()=>{this.mapIntent=a.dataset.chMap==="assign"?"assign":"pan",this.mapIntent==="assign"&&(this.assignOpen=!0),this.paintRail(),this.onInteractionChange?.()})}),e.querySelectorAll("[data-ch-open]").forEach(a=>{let o=()=>this.openChannel(a.dataset.chOpen);a.addEventListener("click",o),a.addEventListener("keydown",r=>{r.key!=="Enter"&&r.key!==" "&&r.key!=="Spacebar"||(r.preventDefault(),o())})}),e.querySelectorAll("[data-ch-menu]").forEach(a=>{a.addEventListener("click",o=>{o.stopPropagation(),this.openDialog({kind:"menu",channelId:a.dataset.chMenu})}),a.addEventListener("keydown",o=>{o.stopPropagation()})}),e.querySelectorAll("[data-ch-rotate]").forEach(a=>{a.addEventListener("click",()=>this.openDialog({kind:"linkRotate",channelId:this.detailChannelId,linkId:a.dataset.chRotate}))}),e.querySelectorAll("[data-ch-revoke]").forEach(a=>{a.addEventListener("click",()=>this.openDialog({kind:"linkRevoke",channelId:this.detailChannelId,linkId:a.dataset.chRevoke}))});let t=e.querySelector("[data-ch-target]");t?.addEventListener("change",()=>{this.targetChannelId=t.value,this.conflict=!1,this.paintRail()});let s=e.querySelector("[data-ch-audience]");s?.addEventListener("change",()=>{this.previewAudience=[s.value],this.loadPreview()});let n=e.querySelector("[data-ch-includepublic]");n?.addEventListener("change",()=>{this.previewIncludePublic=n.checked,this.loadPreview()}),e.querySelector(".slm-ch-grab")?.addEventListener("click",()=>this.cycleDetent()),e.querySelectorAll("[data-ch-act]").forEach(a=>{a.addEventListener("click",()=>this.railAction(a.dataset.chAct))})}openChannel(e){this.detailChannelId=e,this.paintRail(),this.loadLinks(e).then(()=>this.paintRail())}railAction(e){switch(e){case"sections":this.focusedSectionId=null,this.host.showSectionOverview(),this.paintRail();break;case"create":this.openDialog({kind:"create"});break;case"review":this.openDialog({kind:"review"});break;case"rename":this.openDialog({kind:"rename",channelId:this.detailChannelId});break;case"pricing":this.openDialog({kind:"pricing",channelId:this.detailChannelId});break;case"archive":this.openDialog({kind:"archive",channelId:this.detailChannelId});break;case"seatlist":this.openDialog({kind:"seatlist"});break;case"pause":this.togglePause();break;case"discard":this.host.clearSelection();break;case"back":this.detailChannelId=null,this.linksChannelId=null,this.links=[],this.linksState="idle",this.paintRail();break;case"link-create":this.openDialog({kind:"linkCreate",channelId:this.detailChannelId});break;case"embed-code":this.chooseWebsiteIntegration();break;case"route-internal":this.setAccessIntent("internal");break;case"route-none":this.setAccessIntent("none");break;case"link-reload":this.detailChannelId&&this.reloadLinks();break;case"retry":this.refresh();break;case"toggle-archived":this.showArchived=!this.showArchived,this.refresh();break;case"refresh-review":this.conflict=!1,this.refresh().then(()=>this.openDialog({kind:"review"}));break;case"pick-sections":this.openDialog({kind:"scope",scope:"sections"});break;case"pick-rows":this.openDialog({kind:"scope",scope:"rows"});break;case"drag-select":this.mapIntent="assign",this.paintRail(),this.onInteractionChange?.();break;case"pick-category":this.pickCategory();break;case"assign-open":this.assignOpen=!0,this.mapIntent="assign",this.paintRail(),this.onInteractionChange?.();break;case"assign-close":this.assignOpen=!1,this.mapIntent="pan",this.paintRail(),this.onInteractionChange?.();break;case"preview-retry":this.loadPreview();break;default:break}}assignmentRows(){return this.assignmentRowsCache||(this.assignmentRowsCache=this.host.rows()),this.assignmentRowsCache}pickCategory(){let e=this.host.categories();e.length&&this.promptChoice("Select a whole category",e.map(t=>({value:t.key,label:t.label})),t=>{this.host.selectByLabels(this.host.labelsInCategory(t))})}promptChoice(e,t,s){this.renderScrim(`
440
488
  <h3 id="slm-ch-dlg-title">${p(e)}</h3>
441
489
  <div class="slm-field">
442
490
  <label for="slm-ch-choice">Choose one</label>
@@ -460,26 +508,26 @@
460
508
  <div class="foot">
461
509
  <button type="button" class="quiet" data-ch-close>Cancel</button>
462
510
  <button type="button" class="slm-btn" data-ch-add-scope disabled>Add seats</button>
463
- </div>`,r=>{let c=new Map(n.map(x=>[x.id,x])),d=new Set,h=new Set,u=new Set(this.host.selectionLabels()),f=r.querySelector("[data-ch-add-scope]"),v=r.querySelector("[data-ch-error]"),g=r.querySelector("[data-ch-scope-list]"),m=r.querySelector("[data-ch-scope-search]"),k=r.querySelector("[data-ch-scope-summary]"),R=r.querySelector("[data-ch-scope-filter]"),q=200,I="",C=()=>{let x=new Set(u);for(let D of d)for(let O of c.get(D)?.labels??[])x.add(O);return x},L=()=>{let x=C(),D=x.size-u.size,O=x.size>M;f.disabled=D===0||O,f.textContent=O?`Maximum ${M.toLocaleString()} seats`:`Add ${D.toLocaleString()} seat${D===1?"":"s"}`,v.hidden=!O,v.textContent=O?`That would make ${x.size.toLocaleString()} selected seats. Choose fewer rows or sections.`:"",k.textContent=`${d.size.toLocaleString()} row${d.size===1?"":"s"} \xB7 ${D.toLocaleString()} seat${D===1?"":"s"} added`},w=()=>{let x=[],D=0,O=0;o.forEach(([H,$],X)=>{let _=H.toLocaleLowerCase(),V=I?$.filter(P=>`${_} ${P.label.toLocaleLowerCase()}`.includes(I)):$;if(I&&!V.length)return;D+=V.length;let Ve=$.every(P=>d.has(P.id)),$t=!Ve&&$.some(P=>d.has(P.id)),G=!!I||h.has(X),Et=Math.max(0,q-O),Z=G?V.slice(0,Et):[];O+=Z.length;let At=$.reduce((P,Mt)=>P+Mt.labels.length,0);x.push(`<div class="slm-ch-scopegroup">
464
- <button type="button" class="slm-ch-groupcheck" role="checkbox" aria-checked="${Ve?"true":$t?"mixed":"false"}"
465
- aria-label="Select all ${$.length.toLocaleString()} rows in ${p(H)}" data-ch-scope-group="${X}">
466
- <span class="box" aria-hidden="true">\u2713</span><span>${p(H)}</span>
467
- <span class="meta">${$.length.toLocaleString()} rows \xB7 ${At.toLocaleString()} seats</span>
511
+ </div>`,r=>{let d=new Map(n.map(k=>[k.id,k])),c=new Set,h=new Set,u=new Set(this.host.selectionLabels()),f=r.querySelector("[data-ch-add-scope]"),v=r.querySelector("[data-ch-error]"),g=r.querySelector("[data-ch-scope-list]"),m=r.querySelector("[data-ch-scope-search]"),y=r.querySelector("[data-ch-scope-summary]"),H=r.querySelector("[data-ch-scope-filter]"),q=200,E="",N=()=>{let k=new Set(u);for(let C of c)for(let O of d.get(C)?.labels??[])k.add(O);return k},S=()=>{let k=N(),C=k.size-u.size,O=k.size>I;f.disabled=C===0||O,f.textContent=O?`Maximum ${I.toLocaleString()} seats`:`Add ${C.toLocaleString()} seat${C===1?"":"s"}`,v.hidden=!O,v.textContent=O?`That would make ${k.size.toLocaleString()} selected seats. Choose fewer rows or sections.`:"",y.textContent=`${c.size.toLocaleString()} row${c.size===1?"":"s"} \xB7 ${C.toLocaleString()} seat${C===1?"":"s"} added`},L=()=>{let k=[],C=0,O=0;o.forEach(([P,R],X)=>{let V=P.toLocaleLowerCase(),U=E?R.filter(B=>`${V} ${B.label.toLocaleLowerCase()}`.includes(E)):R;if(E&&!U.length)return;C+=U.length;let Ue=R.every(B=>c.has(B.id)),Pt=!Ue&&R.some(B=>c.has(B.id)),Z=!!E||h.has(X),Bt=Math.max(0,q-O),Q=Z?U.slice(0,Bt):[];O+=Q.length;let Dt=R.reduce((B,Ot)=>B+Ot.labels.length,0);k.push(`<div class="slm-ch-scopegroup">
512
+ <button type="button" class="slm-ch-groupcheck" role="checkbox" aria-checked="${Ue?"true":Pt?"mixed":"false"}"
513
+ aria-label="Select all ${R.length.toLocaleString()} rows in ${p(P)}" data-ch-scope-group="${X}">
514
+ <span class="box" aria-hidden="true">\u2713</span><span>${p(P)}</span>
515
+ <span class="meta">${R.length.toLocaleString()} rows \xB7 ${Dt.toLocaleString()} seats</span>
468
516
  </button>
469
- <button type="button" class="slm-ch-grouptoggle" aria-expanded="${G}" aria-label="${G?"Hide":"Show"} rows in ${p(H)}"
470
- data-ch-scope-toggle="${X}">${G?"Hide":"Show"}</button>
471
- </div>`),x.push(...Z.map(P=>`<button type="button" class="slm-ch-seatitem" role="checkbox"
472
- aria-checked="${d.has(P.id)}" data-ch-scope-id="${p(P.id)}">
473
- <span class="box" aria-hidden="true">\u2713</span><span>${p(P.label)}</span>
474
- <span class="meta">${P.labels.length.toLocaleString()} seat${P.labels.length===1?"":"s"}</span>
475
- </button>`)),G&&V.length>Z.length&&x.push(`<p class="slm-ch-scopehint">${(V.length-Z.length).toLocaleString()} more row${V.length-Z.length===1?"":"s"}. Search to narrow the list.</p>`)}),g.innerHTML=x.join("")||(I?`<div class="slm-ch-scope-empty" data-ch-state="scope-nomatch">No sections or rows match \u201C${p(I)}\u201D.</div>`:`<div class="slm-ch-scope-empty" data-ch-state="scope-empty">This chart has no rows with selectable seats.
476
- Use Drag box or the seat list instead.</div>`),R.textContent=I?`Showing ${O.toLocaleString()} of ${D.toLocaleString()} matching rows. Section checkboxes still select every row in that section.`:"Showing section groups. Expand one or search to see rows.",g.querySelectorAll("[data-ch-scope-group]").forEach(H=>H.addEventListener("click",()=>{let $=o[Number(H.dataset.chScopeGroup)]?.[1]??[],X=$.every(_=>d.has(_.id));for(let _ of $)X?d.delete(_.id):d.add(_.id);w(),L()})),g.querySelectorAll("[data-ch-scope-toggle]").forEach(H=>H.addEventListener("click",()=>{let $=Number(H.dataset.chScopeToggle);h.has($)?h.delete($):h.add($),w()})),g.querySelectorAll("[data-ch-scope-id]").forEach(H=>H.addEventListener("click",()=>{let $=H.dataset.chScopeId;d.has($)?d.delete($):d.add($),w(),L()}))};m.addEventListener("input",()=>{I=m.value.trim().toLocaleLowerCase(),w(),L()}),f.addEventListener("click",()=>{let x=[...C()];!d.size||x.length>M||(this.closeDialog(),this.host.selectByLabels(x))}),w(),L()});return}let a=[...i.entries()].map(([o,r])=>`
517
+ <button type="button" class="slm-ch-grouptoggle" aria-expanded="${Z}" aria-label="${Z?"Hide":"Show"} rows in ${p(P)}"
518
+ data-ch-scope-toggle="${X}">${Z?"Hide":"Show"}</button>
519
+ </div>`),k.push(...Q.map(B=>`<button type="button" class="slm-ch-seatitem" role="checkbox"
520
+ aria-checked="${c.has(B.id)}" data-ch-scope-id="${p(B.id)}">
521
+ <span class="box" aria-hidden="true">\u2713</span><span>${p(B.label)}</span>
522
+ <span class="meta">${B.labels.length.toLocaleString()} seat${B.labels.length===1?"":"s"}</span>
523
+ </button>`)),Z&&U.length>Q.length&&k.push(`<p class="slm-ch-scopehint">${(U.length-Q.length).toLocaleString()} more row${U.length-Q.length===1?"":"s"}. Search to narrow the list.</p>`)}),g.innerHTML=k.join("")||(E?`<div class="slm-ch-scope-empty" data-ch-state="scope-nomatch">No sections or rows match \u201C${p(E)}\u201D.</div>`:`<div class="slm-ch-scope-empty" data-ch-state="scope-empty">This chart has no rows with selectable seats.
524
+ Use Drag box or the seat list instead.</div>`),H.textContent=E?`Showing ${O.toLocaleString()} of ${C.toLocaleString()} matching rows. Section checkboxes still select every row in that section.`:"Showing section groups. Expand one or search to see rows.",g.querySelectorAll("[data-ch-scope-group]").forEach(P=>P.addEventListener("click",()=>{let R=o[Number(P.dataset.chScopeGroup)]?.[1]??[],X=R.every(V=>c.has(V.id));for(let V of R)X?c.delete(V.id):c.add(V.id);L(),S()})),g.querySelectorAll("[data-ch-scope-toggle]").forEach(P=>P.addEventListener("click",()=>{let R=Number(P.dataset.chScopeToggle);h.has(R)?h.delete(R):h.add(R),L()})),g.querySelectorAll("[data-ch-scope-id]").forEach(P=>P.addEventListener("click",()=>{let R=P.dataset.chScopeId;c.has(R)?c.delete(R):c.add(R),L(),S()}))};m.addEventListener("input",()=>{E=m.value.trim().toLocaleLowerCase(),L(),S()}),f.addEventListener("click",()=>{let k=[...N()];!c.size||k.length>I||(this.closeDialog(),this.host.selectByLabels(k))}),L(),S()});return}let a=[...i.entries()].map(([o,r])=>`
477
525
  <div class="slm-ch-seatgroup"><span>${p(o)}</span></div>
478
- ${r.map(c=>`<button type="button" class="slm-ch-seatitem" role="checkbox"
479
- aria-checked="false" data-ch-scope-id="${p(c.id)}">
526
+ ${r.map(d=>`<button type="button" class="slm-ch-seatitem" role="checkbox"
527
+ aria-checked="false" data-ch-scope-id="${p(d.id)}">
480
528
  <span class="box" aria-hidden="true">\u2713</span>
481
- <span>${p(c.label)}</span>
482
- <span class="meta">${c.labels.length.toLocaleString()} seat${c.labels.length===1?"":"s"}</span>
529
+ <span>${p(d.label)}</span>
530
+ <span class="meta">${d.labels.length.toLocaleString()} seat${d.labels.length===1?"":"s"}</span>
483
531
  </button>`).join("")}`).join("");this.renderScrim(`
484
532
  <h3 id="slm-ch-dlg-title">Add whole sections</h3>
485
533
  <p class="sub">Choose one or more. They are added to the seats already selected on the map.</p>
@@ -489,7 +537,7 @@
489
537
  <div class="foot">
490
538
  <button type="button" class="quiet" data-ch-close>Cancel</button>
491
539
  <button type="button" class="slm-btn" data-ch-add-scope disabled>Add seats</button>
492
- </div>`,o=>{let r=new Map(n.map(g=>[g.id,g])),c=new Set,d=new Set(this.host.selectionLabels()),h=o.querySelector("[data-ch-add-scope]"),u=o.querySelector("[data-ch-error]"),f=()=>{let g=new Set(d);for(let m of c)for(let k of r.get(m)?.labels??[])g.add(k);return g},v=()=>{let g=f(),m=g.size-d.size,k=g.size>M;h.disabled=m===0||k,h.textContent=k?`Maximum ${M.toLocaleString()} seats`:`Add ${m.toLocaleString()} seat${m===1?"":"s"}`,u.hidden=!k,u.textContent=k?`That would make ${g.size.toLocaleString()} selected seats. Choose fewer rows or sections.`:""};o.querySelectorAll("[data-ch-scope-id]").forEach(g=>{g.addEventListener("click",()=>{let m=g.dataset.chScopeId;c.has(m)?c.delete(m):c.add(m),g.setAttribute("aria-checked",String(c.has(m))),v()})}),h.addEventListener("click",()=>{let g=[...f()];!c.size||g.length>M||(this.closeDialog(),this.host.selectByLabels(g))}),v()})}openDialog(e){this.dialog=e,this.renderDialog()}renderDialog(){let e=this.dialog;e&&(e.kind==="create"?this.renderCreateDialog(e):e.kind==="review"?this.renderReviewDialog(e):e.kind==="scope"?this.renderScopeDialog(e):e.kind==="archive"?this.renderArchiveDialog(e):e.kind==="rename"?this.renderRenameDialog(e):e.kind==="pricing"?this.renderPricingDialog(e):e.kind==="seatlist"?this.renderSeatListDialog():e.kind==="menu"?this.renderMenuDialog(e):e.kind==="linkCreate"?this.renderLinkCreateDialog(e):e.kind==="linkRotate"?this.renderLinkRotateDialog(e):e.kind==="linkRevoke"?this.renderLinkRevokeDialog(e):e.kind==="intentSwitch"&&this.renderIntentSwitchDialog(e))}renderIntentSwitchDialog(e){let t=this.list?.channels.find(a=>a.id===e.channelId),s=e.intentTo;if(!t||!s||!this.caps.manage){this.closeDialog();return}let{headline:n,consequences:i}=Le(e.switchBlocked);this.renderScrim(`
540
+ </div>`,o=>{let r=new Map(n.map(g=>[g.id,g])),d=new Set,c=new Set(this.host.selectionLabels()),h=o.querySelector("[data-ch-add-scope]"),u=o.querySelector("[data-ch-error]"),f=()=>{let g=new Set(c);for(let m of d)for(let y of r.get(m)?.labels??[])g.add(y);return g},v=()=>{let g=f(),m=g.size-c.size,y=g.size>I;h.disabled=m===0||y,h.textContent=y?`Maximum ${I.toLocaleString()} seats`:`Add ${m.toLocaleString()} seat${m===1?"":"s"}`,u.hidden=!y,u.textContent=y?`That would make ${g.size.toLocaleString()} selected seats. Choose fewer rows or sections.`:""};o.querySelectorAll("[data-ch-scope-id]").forEach(g=>{g.addEventListener("click",()=>{let m=g.dataset.chScopeId;d.has(m)?d.delete(m):d.add(m),g.setAttribute("aria-checked",String(d.has(m))),v()})}),h.addEventListener("click",()=>{let g=[...f()];!d.size||g.length>I||(this.closeDialog(),this.host.selectByLabels(g))}),v()})}openDialog(e){this.dialog=e,this.renderDialog()}renderDialog(){let e=this.dialog;e&&(e.kind==="create"?this.renderCreateDialog(e):e.kind==="review"?this.renderReviewDialog(e):e.kind==="scope"?this.renderScopeDialog(e):e.kind==="archive"?this.renderArchiveDialog(e):e.kind==="rename"?this.renderRenameDialog(e):e.kind==="pricing"?this.renderPricingDialog(e):e.kind==="seatlist"?this.renderSeatListDialog():e.kind==="menu"?this.renderMenuDialog(e):e.kind==="linkCreate"?this.renderLinkCreateDialog(e):e.kind==="linkRotate"?this.renderLinkRotateDialog(e):e.kind==="linkRevoke"?this.renderLinkRevokeDialog(e):e.kind==="intentSwitch"&&this.renderIntentSwitchDialog(e))}renderIntentSwitchDialog(e){let t=this.list?.channels.find(a=>a.id===e.channelId),s=e.intentTo;if(!t||!s||!this.caps.manage){this.closeDialog();return}let{headline:n,consequences:i}=Te(e.switchBlocked);this.renderScrim(`
493
541
  <h3 id="slm-ch-dlg-title">Change how ${p(t.name)} reaches buyers?</h3>
494
542
  <p class="sub">${p(n)}</p>
495
543
  <div class="slm-ch-alert warn" role="alert"><span>\u26A0</span><span>
@@ -503,7 +551,7 @@
503
551
  <button type="button" class="slm-btn" data-ch-intent-ack${e.busy?" disabled":""}>
504
552
  ${e.busy?"Changing\u2026":`Change to "${p(F(s))}"`}</button>
505
553
  </div>`,a=>{a.querySelector("[data-ch-intent-ack]")?.addEventListener("click",()=>{this.acknowledgeIntentSwitch(s,e.pendingLink??null)})})}async acknowledgeIntentSwitch(e,t){let s=this.detailChannelId;if(!s){this.closeDialog();return}if(this.dialog&&(this.dialog.busy=!0,this.renderDialog()),!await this.setAccessIntent(e,{acknowledgeLiveAccess:!0})){this.dialog?.kind==="intentSwitch"&&(this.dialog.busy=!1,this.renderDialog());return}if(!t){this.closeDialog();return}this.dialog?.kind==="intentSwitch"&&(this.dialog.busy=!1,this.renderDialog()),await this.mintLink(s,t)}renderScrim(e,t){let s=this.scrimEl;s||(this.lastFocus=document.activeElement??null),s?.remove();let n=document.createElement("div");n.className="slm-ch-scrim",n.innerHTML=`<div class="slm-ch-dialog" role="dialog" aria-modal="true"
506
- aria-labelledby="slm-ch-dlg-title" tabindex="-1">${e}</div>`,this.host.root.appendChild(n),this.scrimEl=n;let i=n.firstElementChild;i.querySelectorAll("[data-ch-close]").forEach(o=>{o.addEventListener("click",()=>this.closeDialog())}),n.addEventListener("keydown",o=>{if(o.key==="Escape"){o.stopPropagation(),this.closeDialog();return}if(o.key!=="Tab")return;let r=[...i.querySelectorAll('summary,button:not([disabled]),select:not([hidden]),input,textarea,a[href],[tabindex]:not([tabindex="-1"])')];if(!r.length)return;let c=r[0],d=r[r.length-1];o.shiftKey&&document.activeElement===c?(o.preventDefault(),d.focus()):!o.shiftKey&&document.activeElement===d&&(o.preventDefault(),c.focus())}),t(i),ne(i),(i.querySelector("input,summary,button")??i).focus()}closeDialog(e={}){this.dialog=null,this.scrimEl?.remove(),this.scrimEl=null,e.restoreFocus!==!1&&this.lastFocus?.focus?.(),this.lastFocus=null}renderCreateDialog(e){let t=(this.list?.channels??[]).map(n=>z(n.marker||n.name,"")),s=Q("",t);this.renderScrim(`
554
+ aria-labelledby="slm-ch-dlg-title" tabindex="-1">${e}</div>`,this.host.root.appendChild(n),this.scrimEl=n;let i=n.firstElementChild;i.querySelectorAll("[data-ch-close]").forEach(o=>{o.addEventListener("click",()=>this.closeDialog())}),n.addEventListener("keydown",o=>{if(o.key==="Escape"){o.stopPropagation(),this.closeDialog();return}if(o.key!=="Tab")return;let r=[...i.querySelectorAll('summary,button:not([disabled]),select:not([hidden]),input,textarea,a[href],[tabindex]:not([tabindex="-1"])')];if(!r.length)return;let d=r[0],c=r[r.length-1];o.shiftKey&&document.activeElement===d?(o.preventDefault(),c.focus()):!o.shiftKey&&document.activeElement===c&&(o.preventDefault(),d.focus())}),t(i),ie(i),(i.querySelector("input,summary,button")??i).focus()}closeDialog(e={}){this.dialog=null,this.scrimEl?.remove(),this.scrimEl=null,e.restoreFocus!==!1&&this.lastFocus?.focus?.(),this.lastFocus=null}renderCreateDialog(e){let t=(this.list?.channels??[]).map(n=>z(n.marker||n.name,"")),s=J("",t);this.renderScrim(`
507
555
  <h3 id="slm-ch-dlg-title">Create channel</h3>
508
556
  <p class="sub">A named allocation only the right audience can buy from. You'll pick the seats next.</p>
509
557
  <div class="slm-field">
@@ -528,14 +576,14 @@
528
576
  <button type="button" class="quiet" data-ch-close>Cancel</button>
529
577
  <button type="button" class="slm-btn ghost" data-ch-create="plain">Create without allocating</button>
530
578
  <button type="button" class="slm-btn" data-ch-create="allocate">Create and allocate seats</button>
531
- </div>`,n=>{let i=n.querySelector("#slm-ch-name"),a=n.querySelector("[data-ch-marker]");i.addEventListener("input",()=>{let o=Q(i.value,t);a.textContent=o.letter,a.style.background=o.color}),n.querySelectorAll("[data-ch-create]").forEach(o=>{o.addEventListener("click",()=>{let r=o.dataset.chCreate==="allocate";this.createChannel(i.value,a.textContent??"",a.style.background,n.querySelector("#slm-ch-ref")?.value??"",r)})})})}async createChannel(e,t,s,n,i){let a=e.trim();if(!a){this.showDialogError("Give the channel a name your team will recognise.");return}try{let o=await this.host.api.createChannel(this.host.eventKey,{name:a,marker:z(t,"")||null,color:s||null,externalRef:n.trim()||null});this.closeDialog(),await this.refresh(),this.targetChannelId=o.channel.id,this.detailChannelId=i?null:o.channel.id,this.announce(`Channel ${a} created with 0 seats allocated.`),this.host.toast(i?`${a} created. Select seats on the map to allocate them.`:`${a} created.`,"ok"),this.paintRail()}catch(o){let r=o instanceof y?o.code:void 0;this.showDialogError(r==="channel_name_taken"?"That name is already used on this event. Pick another.":"Couldn't create the channel. Try again."),this.host.onError(o)}}showDialogError(e){let t=this.scrimEl?.querySelector("[data-ch-error]");t&&(t.textContent=e,t.hidden=!1)}renderReviewDialog(e){let{labels:t,buckets:s}=this.currentPlan(),n=e.applied,i=n?n.buckets:s,a=this.nameOf(n?.targetChannelId??this.targetChannelId)??A,o=ke(i,a),r=n?n.applied:K(s),c=!n&&t.length>0&&r===0,d=!n&&t.length>M,h=W(o),u=n?'<div class="foot"><button type="button" class="slm-btn" data-ch-close>Done</button></div>':`<div class="foot">
579
+ </div>`,n=>{let i=n.querySelector("#slm-ch-name"),a=n.querySelector("[data-ch-marker]");i.addEventListener("input",()=>{let o=J(i.value,t);a.textContent=o.letter,a.style.background=o.color}),n.querySelectorAll("[data-ch-create]").forEach(o=>{o.addEventListener("click",()=>{let r=o.dataset.chCreate==="allocate";this.createChannel(i.value,a.textContent??"",a.style.background,n.querySelector("#slm-ch-ref")?.value??"",r)})})})}async createChannel(e,t,s,n,i){let a=e.trim();if(!a){this.showDialogError("Give the channel a name your team will recognise.");return}try{let o=await this.host.api.createChannel(this.host.eventKey,{name:a,marker:z(t,"")||null,color:s||null,externalRef:n.trim()||null});this.closeDialog(),await this.refresh(),this.targetChannelId=o.channel.id,this.detailChannelId=i?null:o.channel.id,this.announce(`Channel ${a} created with 0 seats allocated.`),this.host.toast(i?`${a} created. Select seats on the map to allocate them.`:`${a} created.`,"ok"),this.paintRail()}catch(o){let r=o instanceof x?o.code:void 0;this.showDialogError(r==="channel_name_taken"?"That name is already used on this event. Pick another.":"Couldn't create the channel. Try again."),this.host.onError(o)}}showDialogError(e){let t=this.scrimEl?.querySelector("[data-ch-error]");t&&(t.textContent=e,t.hidden=!1)}renderReviewDialog(e){let{labels:t,buckets:s}=this.currentPlan(),n=e.applied,i=n?n.buckets:s,a=this.nameOf(n?.targetChannelId??this.targetChannelId)??M,o=we(i,a),r=n?n.applied:Y(s),d=!n&&t.length>0&&r===0,c=!n&&t.length>I,h=W(o),u=n?'<div class="foot"><button type="button" class="slm-btn" data-ch-close>Done</button></div>':`<div class="foot">
532
580
  <button type="button" class="quiet" data-ch-close>Back</button>
533
- <button type="button" class="slm-btn" data-ch-apply ${c||d||e.busy?"disabled":""}>
581
+ <button type="button" class="slm-btn" data-ch-apply ${d||c||e.busy?"disabled":""}>
534
582
  ${e.busy?"Applying\u2026":`Apply ${r.toLocaleString()} change${r===1?"":"s"}`}
535
583
  </button>
536
- </div>`,f=!n&&ye(s)?'<p class="slm-note">Applying moves inventory out of another private channel. That is the line marked above.</p>':"",v=c?`<div class="slm-ch-alert warn"><span>\u2139</span><span>Nothing in this selection can move right now \u2014
537
- every seat is in a buyer's checkout, already sold, or already in ${p(a)}.</span></div>`:"",g=d?`<div class="slm-ch-alert warn" role="alert"><span>\u2139</span><span><b>Choose fewer seats.</b>
538
- One Apply can cover at most ${M.toLocaleString()} seats.</span></div>`:"";this.renderScrim(`
584
+ </div>`,f=!n&&xe(s)?'<p class="slm-note">Applying moves inventory out of another private channel. That is the line marked above.</p>':"",v=d?`<div class="slm-ch-alert warn"><span>\u2139</span><span>Nothing in this selection can move right now \u2014
585
+ every seat is in a buyer's checkout, already sold, or already in ${p(a)}.</span></div>`:"",g=c?`<div class="slm-ch-alert warn" role="alert"><span>\u2139</span><span><b>Choose fewer seats.</b>
586
+ One Apply can cover at most ${I.toLocaleString()} seats.</span></div>`:"";this.renderScrim(`
539
587
  <h3 id="slm-ch-dlg-title">${n?`Moved ${n.applied.toLocaleString()} seat${n.applied===1?"":"s"} to ${p(a)}`:`Move ${t.length.toLocaleString()} selected seat${t.length===1?"":"s"} to ${p(a)}`}</h3>
540
588
  <p class="sub">${n?"These are the exact counts the server applied.":"Every selected seat is in exactly one line below."}</p>
541
589
  ${v}
@@ -543,7 +591,7 @@
543
591
  ${h||'<div class="slm-empty">Nothing selected.</div>'}
544
592
  ${f}
545
593
  <p class="slm-ch-err" data-ch-error ${e.error?"":"hidden"}>${p(e.error??"")}</p>
546
- ${u}`,m=>{m.querySelector("[data-ch-apply]")?.addEventListener("click",()=>{this.apply()})}),n&&this.announce(`Applied ${n.applied} change${n.applied===1?"":"s"} to ${a}.`)}async apply(){if(!this.dialog||!this.caps.manage)return;let{labels:e}=this.currentPlan();if(e.length){if(e.length>M){this.showDialogError(`Choose at most ${M.toLocaleString()} seats for one Apply.`);return}this.dialog={...this.dialog,busy:!0,error:null},this.renderDialog();try{let t=await this.host.api.applyChannelAssignment(this.host.eventKey,{targetChannelId:B(this.targetChannelId)?null:this.targetChannelId,labels:e,assignmentVersion:this.assignmentVersion});this.assignmentVersion=t.assignmentVersion,this.conflict=!1,await this.refresh({quiet:!0}),this.closeDialog({restoreFocus:!1}),this.host.clearSelection(),this.showApplied(t)}catch(t){if(t instanceof y&&t.status===409&&t.code==="channel_assignment_conflict"){this.conflict=!0,this.closeDialog(),this.shakeStaged(),this.paintRail(),this.announce("Assignments changed while you were editing. Nothing was applied and your selection is kept.");return}if(t instanceof y&&t.status===403){this.caps={view:this.caps.view,manage:!1},this.closeDialog(),this.paintRail(),this.host.toast("Changing channels needs channel-management permission.","err");return}this.dialog={kind:"review",busy:!1,error:"Couldn't apply those changes. Try again."},this.renderDialog(),this.host.onError(t)}}}showApplied(e){let t=this.nameOf(e.targetChannelId)??A,s=e.buckets.skippedHeld.count+e.buckets.skippedBooked.count+e.buckets.notFound.count;this.setStaged(`<span class="slm-ch-tick" aria-hidden="true">\u2713</span>
594
+ ${u}`,m=>{m.querySelector("[data-ch-apply]")?.addEventListener("click",()=>{this.apply()})}),n&&this.announce(`Applied ${n.applied} change${n.applied===1?"":"s"} to ${a}.`)}async apply(){if(!this.dialog||!this.caps.manage)return;let{labels:e}=this.currentPlan();if(e.length){if(e.length>I){this.showDialogError(`Choose at most ${I.toLocaleString()} seats for one Apply.`);return}this.dialog={...this.dialog,busy:!0,error:null},this.renderDialog();try{let t=await this.host.api.applyChannelAssignment(this.host.eventKey,{targetChannelId:D(this.targetChannelId)?null:this.targetChannelId,labels:e,assignmentVersion:this.assignmentVersion});this.assignmentVersion=t.assignmentVersion,this.conflict=!1,await this.refresh({quiet:!0}),this.closeDialog({restoreFocus:!1}),this.host.clearSelection(),this.showApplied(t)}catch(t){if(t instanceof x&&t.status===409&&t.code==="channel_assignment_conflict"){this.conflict=!0,this.closeDialog(),this.shakeStaged(),this.paintRail(),this.announce("Assignments changed while you were editing. Nothing was applied and your selection is kept.");return}if(t instanceof x&&t.status===403){this.caps={view:this.caps.view,manage:!1},this.closeDialog(),this.paintRail(),this.host.toast("Changing channels needs channel-management permission.","err");return}this.dialog={kind:"review",busy:!1,error:"Couldn't apply those changes. Try again."},this.renderDialog(),this.host.onError(t)}}}showApplied(e){let t=this.nameOf(e.targetChannelId)??M,s=e.buckets.skippedHeld.count+e.buckets.skippedBooked.count+e.buckets.notFound.count;this.setStaged(`<span class="slm-ch-tick" aria-hidden="true">\u2713</span>
547
595
  <span>Assigned <b>${e.applied.toLocaleString()}</b> seat${e.applied===1?"":"s"} to ${p(t)}
548
596
  ${s?` \xB7 ${s.toLocaleString()} skipped`:""}</span>
549
597
  <span class="grow"></span>
@@ -571,11 +619,11 @@
571
619
  <div class="foot">
572
620
  <button type="button" class="quiet" data-ch-close>Cancel</button>
573
621
  <button type="button" class="slm-btn" data-ch-rename>Save name</button>
574
- </div>`,s=>{s.querySelector("[data-ch-rename]")?.addEventListener("click",()=>{let n=s.querySelector("#slm-ch-newname")?.value??"";if(!n.trim()){this.showDialogError("A channel needs a name.");return}this.host.api.renameChannel(this.host.eventKey,t.id,n.trim()).then(()=>(this.closeDialog(),this.refresh())).catch(i=>{this.showDialogError(i instanceof y&&i.code==="channel_name_taken"?"That name is already used on this event.":"Couldn't rename the channel."),this.host.onError(i)})})})}renderPricingDialog(e){let t=this.list?.channels.find(a=>a.id===e.channelId),s=this.host.api.updateChannelPricing;if(!t||!s||!this.caps.manage){this.closeDialog();return}let n=new Map((t.priceOverrides??[]).map(a=>[`${a.categoryKey}\0${a.tierId??""}`,a.price])),i=this.host.categories().flatMap(a=>(a.tiers?.length?a.tiers:[null]).map(r=>{let c=r?.id??null,d=`${a.key}\0${c??""}`,h=r?.price??a.price??0,u=n.get(d),f=r?`${a.label} \xB7 ${r.name}`:a.label;return`<label class="slm-ch-price-row">
622
+ </div>`,s=>{s.querySelector("[data-ch-rename]")?.addEventListener("click",()=>{let n=s.querySelector("#slm-ch-newname")?.value??"";if(!n.trim()){this.showDialogError("A channel needs a name.");return}this.host.api.renameChannel(this.host.eventKey,t.id,n.trim()).then(()=>(this.closeDialog(),this.refresh())).catch(i=>{this.showDialogError(i instanceof x&&i.code==="channel_name_taken"?"That name is already used on this event.":"Couldn't rename the channel."),this.host.onError(i)})})})}renderPricingDialog(e){let t=this.list?.channels.find(a=>a.id===e.channelId),s=this.host.api.updateChannelPricing;if(!t||!s||!this.caps.manage){this.closeDialog();return}let n=new Map((t.priceOverrides??[]).map(a=>[`${a.categoryKey}\0${a.tierId??""}`,a.price])),i=this.host.categories().flatMap(a=>(a.tiers?.length?a.tiers:[null]).map(r=>{let d=r?.id??null,c=`${a.key}\0${d??""}`,h=r?.price??a.price??0,u=n.get(c),f=r?`${a.label} \xB7 ${r.name}`:a.label;return`<label class="slm-ch-price-row">
575
623
  <span><b>${p(f)}</b><small>Event price ${p(String(h))}</small></span>
576
624
  <input class="slm-input" type="number" min="0" max="1000000" step="0.01"
577
625
  inputmode="decimal" aria-label="Custom price for ${p(f)}"
578
- data-ch-price-category="${p(a.key)}" data-ch-price-tier="${p(c??"")}"
626
+ data-ch-price-category="${p(a.key)}" data-ch-price-tier="${p(d??"")}"
579
627
  placeholder="${p(String(h))}" value="${u===void 0?"":p(String(u))}"
580
628
  ${e.busy?"disabled":""} />
581
629
  </label>`})).join("");this.renderScrim(`
@@ -588,9 +636,9 @@
588
636
  <button type="button" class="slm-btn" data-ch-price-save ${e.busy||!i?"disabled":""}>
589
637
  ${e.busy?"Saving\u2026":"Save prices"}
590
638
  </button>
591
- </div>`,a=>{a.querySelector("[data-ch-price-save]")?.addEventListener("click",()=>{let o=[];for(let r of a.querySelectorAll("[data-ch-price-category]")){let c=r.value.trim();if(!c)continue;let d=Number(c);if(!Number.isFinite(d)||d<0||d>1e6){r.focus(),this.showDialogError("Enter a price from 0 to 1,000,000, or leave the field blank.");return}o.push({categoryKey:r.dataset.chPriceCategory,tierId:r.dataset.chPriceTier||null,price:d})}this.saveChannelPricing(t,o)})})}async saveChannelPricing(e,t){let s=this.host.api.updateChannelPricing;if(!(!s||!this.dialog||this.dialog.kind!=="pricing")){this.dialog={...this.dialog,busy:!0,error:null},this.renderDialog();try{await s.call(this.host.api,this.host.eventKey,e.id,t,e.pricingVersion??0),this.closeDialog(),await this.refresh(),this.host.toast(t.length?`Custom prices saved for ${e.name}.`:`${e.name} now uses event prices.`,"ok")}catch(n){if(n instanceof y&&n.code==="channel_pricing_conflict"){await this.refresh({quiet:!0}),this.dialog={kind:"pricing",channelId:e.id,error:"Prices changed in another window. Latest values are shown \u2014 review and save again."},this.renderDialog();return}this.dialog={kind:"pricing",channelId:e.id,error:n instanceof y&&n.serverMessage?n.serverMessage:"Couldn't save these prices. Try again."},this.renderDialog(),this.host.onError(n)}}}async chooseWebsiteIntegration(){this.detailChannelId&&await this.setAccessIntent("server")}async setAccessIntent(e,t={}){let s=this.detailChannelId;if(!s||!this.caps.manage)return!1;try{let n=await this.host.api.setChannelAccessIntent(this.host.eventKey,s,e,t);return await this.refresh(),this.host.toast(this.intentSavedCopy(e,n?.intentSwitch),"ok"),!0}catch(n){return n instanceof y&&n.code==="channel_intent_switch_blocked"?(this.openDialog({kind:"intentSwitch",channelId:s,intentTo:e,switchBlocked:n.details}),!1):n instanceof y&&n.code==="channel_access_intent_forbids"?(this.host.toast(Y(n.details),"err"),!1):(this.host.toast("Couldn't change how this channel reaches buyers.","err"),this.host.onError(n),!1)}}intentSavedCopy(e,t){let s=e==="server"?"Set to your website or app. The embed code is on the Embed page.":e==="internal"?"Only your own staff can sell this channel now.":e==="hosted_link"?"Set to buyer links. Create one to let buyers in.":"Kept as a protected reserve. No route can sell these seats.";if(!t)return s;let n=t.closedLinks?` ${t.closedLinks.toLocaleString()} buyer link${t.closedLinks===1?"":"s"} closed.`:"",i=t.keptSessions?` ${t.keptSessions.toLocaleString()} buyer${t.keptSessions===1?"":"s"} already in a checkout can still finish.`:"";return`${s}${n}${i}`}async togglePause(e=this.detailChannelId){let t=this.list?.channels.find(n=>n.id===e);if(!t||!this.caps.manage)return;let s=t.state!=="paused";try{await this.host.api.setChannelPaused(this.host.eventKey,t.id,s),await this.refresh(),this.host.toast(s?`${t.name} paused. Existing checkouts can finish; no new buyer access is issued.`:`${t.name} resumed.`,"ok")}catch(n){this.host.toast("Couldn't change that channel.","err"),this.host.onError(n)}}renderArchiveDialog(e){let t=this.list?.channels.find(o=>o.id===e.channelId);if(!t){this.closeDialog();return}let s=e.archiveBlocked??null,n=!s&&t.counts.held>0,i=this.assignableChannels().filter(o=>o.id!==t.id),a=s?`<div class="slm-ch-alert warn" role="alert"><span>\u23F3</span>
639
+ </div>`,a=>{a.querySelector("[data-ch-price-save]")?.addEventListener("click",()=>{let o=[];for(let r of a.querySelectorAll("[data-ch-price-category]")){let d=r.value.trim();if(!d)continue;let c=Number(d);if(!Number.isFinite(c)||c<0||c>1e6){r.focus(),this.showDialogError("Enter a price from 0 to 1,000,000, or leave the field blank.");return}o.push({categoryKey:r.dataset.chPriceCategory,tierId:r.dataset.chPriceTier||null,price:c})}this.saveChannelPricing(t,o)})})}async saveChannelPricing(e,t){let s=this.host.api.updateChannelPricing;if(!(!s||!this.dialog||this.dialog.kind!=="pricing")){this.dialog={...this.dialog,busy:!0,error:null},this.renderDialog();try{await s.call(this.host.api,this.host.eventKey,e.id,t,e.pricingVersion??0),this.closeDialog(),await this.refresh(),this.host.toast(t.length?`Custom prices saved for ${e.name}.`:`${e.name} now uses event prices.`,"ok")}catch(n){if(n instanceof x&&n.code==="channel_pricing_conflict"){await this.refresh({quiet:!0}),this.dialog={kind:"pricing",channelId:e.id,error:"Prices changed in another window. Latest values are shown \u2014 review and save again."},this.renderDialog();return}this.dialog={kind:"pricing",channelId:e.id,error:n instanceof x&&n.serverMessage?n.serverMessage:"Couldn't save these prices. Try again."},this.renderDialog(),this.host.onError(n)}}}async chooseWebsiteIntegration(){this.detailChannelId&&await this.setAccessIntent("server")}async setAccessIntent(e,t={}){let s=this.detailChannelId;if(!s||!this.caps.manage)return!1;try{let n=await this.host.api.setChannelAccessIntent(this.host.eventKey,s,e,t);return await this.refresh(),this.host.toast(this.intentSavedCopy(e,n?.intentSwitch),"ok"),!0}catch(n){return n instanceof x&&n.code==="channel_intent_switch_blocked"?(this.openDialog({kind:"intentSwitch",channelId:s,intentTo:e,switchBlocked:n.details}),!1):n instanceof x&&n.code==="channel_access_intent_forbids"?(this.host.toast(G(n.details),"err"),!1):(this.host.toast("Couldn't change how this channel reaches buyers.","err"),this.host.onError(n),!1)}}intentSavedCopy(e,t){let s=e==="server"?"Set to your website or app. The embed code is on the Embed page.":e==="internal"?"Only your own staff can sell this channel now.":e==="hosted_link"?"Set to buyer links. Create one to let buyers in.":"Kept as a protected reserve. No route can sell these seats.";if(!t)return s;let n=t.closedLinks?` ${t.closedLinks.toLocaleString()} buyer link${t.closedLinks===1?"":"s"} closed.`:"",i=t.keptSessions?` ${t.keptSessions.toLocaleString()} buyer${t.keptSessions===1?"":"s"} already in a checkout can still finish.`:"";return`${s}${n}${i}`}async togglePause(e=this.detailChannelId){let t=this.list?.channels.find(n=>n.id===e);if(!t||!this.caps.manage)return;let s=t.state!=="paused";try{await this.host.api.setChannelPaused(this.host.eventKey,t.id,s),await this.refresh(),this.host.toast(s?`${t.name} paused. Existing checkouts can finish; no new buyer access is issued.`:`${t.name} resumed.`,"ok")}catch(n){this.host.toast("Couldn't change that channel.","err"),this.host.onError(n)}}renderArchiveDialog(e){let t=this.list?.channels.find(o=>o.id===e.channelId);if(!t){this.closeDialog();return}let s=e.archiveBlocked??null,n=!s&&t.counts.held>0,i=this.assignableChannels().filter(o=>o.id!==t.id),a=s?`<div class="slm-ch-alert warn" role="alert"><span>\u23F3</span>
592
640
  <span><b>${(s.heldUnits??s.activeHolds??0).toLocaleString()} seats are in a buyer's checkout right now.</b>
593
- Archive is unavailable while seats are held \u2014 try again ${p(xe(s))}.</span></div>`:n?`<div class="slm-ch-alert warn"><span>\u23F3</span>
641
+ Archive is unavailable while seats are held \u2014 try again ${p(Se(s))}.</span></div>`:n?`<div class="slm-ch-alert warn"><span>\u23F3</span>
594
642
  <span>${t.counts.held.toLocaleString()} seats are in a buyer's checkout right now.
595
643
  Archive is refused while any seat is held \u2014 you can try, and we'll tell you when to come back.</span></div>`:"";this.renderScrim(`
596
644
  <h3 id="slm-ch-dlg-title">Archive ${p(t.name)}</h3>
@@ -610,22 +658,22 @@
610
658
  <div class="foot">
611
659
  <button type="button" class="quiet" data-ch-close>Cancel</button>
612
660
  <button type="button" class="slm-btn danger" data-ch-archive ${s?"disabled":""}>Archive channel</button>
613
- </div>`,o=>{o.querySelector("[data-ch-archive]")?.addEventListener("click",()=>{let r=o.querySelector("#slm-ch-dest")?.value??"";this.archive(t.id,r||null)})})}async archive(e,t){try{await this.host.api.archiveChannel(this.host.eventKey,e,t),this.closeDialog(),this.detailChannelId=null,await this.refresh(),this.host.toast("Channel archived. Its remaining seats moved to the destination you chose.","ok")}catch(s){if(s instanceof y&&s.status===409&&s.code==="channel_archive_blocked_by_holds"){this.dialog={kind:"archive",channelId:e,archiveBlocked:s.details??{}},this.renderDialog();return}this.showDialogError("Couldn't archive that channel. Try again."),this.host.onError(s)}}renderSeatListDialog(){let e=new Set(this.host.selectionLabels()),t=new Map,s=0;for(let i of this.host.seats()){if(s+=1,s>this.seatListLimit)break;let a=this.host.sectionOfLabel(i.label),o=a?.id??"",r=t.get(o)??{label:a?.label??"Other seats",seats:[]};r.seats.push({label:i.label,status:this.host.statusOf(i.label)??"free"}),t.set(o,r)}let n=[...t.entries()].map(([i,a])=>`
661
+ </div>`,o=>{o.querySelector("[data-ch-archive]")?.addEventListener("click",()=>{let r=o.querySelector("#slm-ch-dest")?.value??"";this.archive(t.id,r||null)})})}async archive(e,t){try{await this.host.api.archiveChannel(this.host.eventKey,e,t),this.closeDialog(),this.detailChannelId=null,await this.refresh(),this.host.toast("Channel archived. Its remaining seats moved to the destination you chose.","ok")}catch(s){if(s instanceof x&&s.status===409&&s.code==="channel_archive_blocked_by_holds"){this.dialog={kind:"archive",channelId:e,archiveBlocked:s.details??{}},this.renderDialog();return}this.showDialogError("Couldn't archive that channel. Try again."),this.host.onError(s)}}renderSeatListDialog(){let e=new Set(this.host.selectionLabels()),t=new Map,s=0;for(let i of this.host.seats()){if(s+=1,s>this.seatListLimit)break;let a=this.host.sectionOfLabel(i.label),o=a?.id??"",r=t.get(o)??{label:a?.label??"Other seats",seats:[]};r.seats.push({label:i.label,status:this.host.statusOf(i.label)??"free"}),t.set(o,r)}let n=[...t.entries()].map(([i,a])=>`
614
662
  <div class="slm-ch-seatgroup">
615
663
  <span>${p(a.label)}</span>
616
664
  ${i?`<button type="button" data-ch-section="${p(i)}">Select section</button>`:""}
617
665
  </div>
618
- ${a.seats.map(o=>{let r=this.allocation.get(o.label)??T,c=this.nameOf(r)??A;return`<button type="button" class="slm-ch-seatitem" role="checkbox"
666
+ ${a.seats.map(o=>{let r=this.allocation.get(o.label)??T,d=this.nameOf(r)??M;return`<button type="button" class="slm-ch-seatitem" role="checkbox"
619
667
  aria-checked="${e.has(o.label)}" data-ch-seat="${p(o.label)}">
620
668
  <span class="box" aria-hidden="true">\u2713</span>
621
669
  <span>${p(o.label)}</span>
622
- <span class="meta">${p(c)} \xB7 ${p(o.status)}</span>
670
+ <span class="meta">${p(d)} \xB7 ${p(o.status)}</span>
623
671
  </button>`}).join("")}`).join("");this.renderScrim(`
624
672
  <h3 id="slm-ch-dlg-title">Seat list</h3>
625
673
  <p class="sub">The same selection as the map, with checkboxes. Space or Enter toggles a seat.</p>
626
674
  <div class="slm-ch-seatlist">${n||'<div class="slm-empty">No seats on this chart.</div>'}</div>
627
675
  ${s>this.seatListLimit?'<div class="foot"><button type="button" class="slm-btn ghost" data-ch-more>Show more seats</button></div>':""}
628
- <div class="foot"><button type="button" class="slm-btn" data-ch-close>Done</button></div>`,i=>{i.querySelectorAll("[data-ch-seat]").forEach(a=>{a.addEventListener("click",()=>{let o=a.dataset.chSeat,r=new Set(this.host.selectionLabels());r.has(o)?r.delete(o):r.add(o),this.host.clearSelection(),r.size&&this.host.selectByLabels([...r]),this.renderSeatListDialog()})}),i.querySelectorAll("[data-ch-section]").forEach(a=>{a.addEventListener("click",()=>{this.host.selectSection(a.dataset.chSection),this.renderSeatListDialog()})}),i.querySelector("[data-ch-more]")?.addEventListener("click",()=>{this.seatListLimit+=St,this.renderSeatListDialog()})})}async reloadLinks(){let e=this.detailChannelId;e&&(this.linksState=this.links.length?this.linksState:"loading",await this.loadLinks(e),this.paintRail())}async reloadAfterLinkChange(e){if(this.detailChannelId===e){await this.refresh({quiet:!0});return}await this.loadLinks(e),this.active&&this.paintRail()}linkById(e){return this.links.find(t=>t.id===e)??null}renderLinkCreateDialog(e){let t=this.list?.channels.find(s=>s.id===e.channelId);if(!t||!this.caps.manage){this.closeDialog();return}this.renderScrim(`
676
+ <div class="foot"><button type="button" class="slm-btn" data-ch-close>Done</button></div>`,i=>{i.querySelectorAll("[data-ch-seat]").forEach(a=>{a.addEventListener("click",()=>{let o=a.dataset.chSeat,r=new Set(this.host.selectionLabels());r.has(o)?r.delete(o):r.add(o),this.host.clearSelection(),r.size&&this.host.selectByLabels([...r]),this.renderSeatListDialog()})}),i.querySelectorAll("[data-ch-section]").forEach(a=>{a.addEventListener("click",()=>{this.host.selectSection(a.dataset.chSection),this.renderSeatListDialog()})}),i.querySelector("[data-ch-more]")?.addEventListener("click",()=>{this.seatListLimit+=Et,this.renderSeatListDialog()})})}async reloadLinks(){let e=this.detailChannelId;e&&(this.linksState=this.links.length?this.linksState:"loading",await this.loadLinks(e),this.paintRail())}async reloadAfterLinkChange(e){if(this.detailChannelId===e){await this.refresh({quiet:!0});return}await this.loadLinks(e),this.active&&this.paintRail()}linkById(e){return this.links.find(t=>t.id===e)??null}renderLinkCreateDialog(e){let t=this.list?.channels.find(s=>s.id===e.channelId);if(!t||!this.caps.manage){this.closeDialog();return}this.renderScrim(`
629
677
  <h3 id="slm-ch-dlg-title">Create a buyer link for ${p(t.name)}</h3>
630
678
  <p class="sub">Anyone who opens the link can buy from this channel's allocation \u2014 and only from it.
631
679
  You'll see the link once, right after you create it.</p>
@@ -648,13 +696,13 @@
648
696
  <div class="slm-field">
649
697
  <label for="slm-ch-lk-redemptions">How many people can use it</label>
650
698
  <input class="slm-input" type="number" id="slm-ch-lk-redemptions" inputmode="numeric"
651
- value="${J.maxRedemptions}" />
699
+ value="${ee.maxRedemptions}" />
652
700
  <p class="slm-note">Each buyer who opens the link uses one.</p>
653
701
  </div>
654
702
  <div class="slm-field">
655
703
  <label for="slm-ch-lk-quantity">Seats per buyer</label>
656
704
  <input class="slm-input" type="number" id="slm-ch-lk-quantity" inputmode="numeric"
657
- value="${J.maxQuantity}" />
705
+ value="${ee.maxQuantity}" />
658
706
  </div>
659
707
  <label class="slm-note" style="display:flex;gap:8px;align-items:center;margin:2px 0 6px">
660
708
  <input type="checkbox" id="slm-ch-lk-public" />
@@ -664,17 +712,18 @@
664
712
  <div class="foot">
665
713
  <button type="button" class="quiet" data-ch-close>Cancel</button>
666
714
  <button type="button" class="slm-btn" data-ch-lk-create>Create link</button>
667
- </div>`,s=>{let n=s.querySelector("[data-ch-lk-expiry]"),i=s.querySelector("[data-ch-lk-when-field]"),a=s.querySelector("#slm-ch-lk-when");n.addEventListener("change",()=>{let o=n.value==="custom";i.hidden=!o,o&&!a.value&&(a.value=ft(Date.now()+7*864e5))}),s.querySelector("[data-ch-lk-create]")?.addEventListener("click",()=>{let o=je(s,"#slm-ch-lk-redemptions"),r=je(s,"#slm-ch-lk-quantity");if(o==null||r==null){this.showDialogError("Those two settings need to be whole numbers.");return}let c;if(n.value==="custom"&&(c=Date.parse(a.value),!Number.isFinite(c))){this.showDialogError("Pick the date and time the link should stop working.");return}this.createLink(t.id,{label:s.querySelector("#slm-ch-lk-label")?.value.trim()||null,includePublic:s.querySelector("#slm-ch-lk-public")?.checked??!1,...c===void 0?{}:{expiresAt:c},maxRedemptions:o,maxQuantity:r})})})}async createLink(e,t){await this.ensureHostedLinkRoute(e,t)&&await this.mintLink(e,t)}async mintLink(e,t){try{let s=await this.host.api.createAccessLink(this.host.eventKey,e,t);this.revealLink(s,{channelId:e}),await this.reloadAfterLinkChange(e)}catch(s){this.showDialogError(N(s instanceof y?s:void 0)),s instanceof y||this.host.onError(s)}}async ensureHostedLinkRoute(e,t){if((this.list?.channels.find(n=>n.id===e)?.access?.intent??"none")==="hosted_link")return!0;try{return await this.host.api.setChannelAccessIntent(this.host.eventKey,e,"hosted_link"),await this.refresh(),!0}catch(n){return n instanceof y&&n.code==="channel_intent_switch_blocked"?(this.openDialog({kind:"intentSwitch",channelId:e,intentTo:"hosted_link",switchBlocked:n.details,pendingLink:t}),!1):(this.showDialogError(n instanceof y&&n.code==="channel_access_intent_forbids"?Y(n.details):"Couldn't set this channel up for buyer links. Try again."),n instanceof y||this.host.onError(n),!1)}}revealLink(e,t){let s=e.url;this.dialog=null;let n=t.rotated?`<div class="slm-ch-alert warn" role="status"><span>\u26A0</span><span>
668
- <b>The old link has stopped working.</b> ${e.endedSessions?`${e.endedSessions.toLocaleString()} buyer${e.endedSessions===1?"":"s"} lost access immediately.`:"Buyers who already came in can finish; every new visit needs this link."}</span></div>`:"",i=te(e.link).map(a=>`<div class="slm-ch-lkrow"><span class="k">${p(a.k)}</span>
715
+ </div>`,s=>{let n=s.querySelector("[data-ch-lk-expiry]"),i=s.querySelector("[data-ch-lk-when-field]"),a=s.querySelector("#slm-ch-lk-when");n.addEventListener("change",()=>{let o=n.value==="custom";i.hidden=!o,o&&!a.value&&(a.value=xt(Date.now()+7*864e5))}),s.querySelector("[data-ch-lk-create]")?.addEventListener("click",()=>{let o=je(s,"#slm-ch-lk-redemptions"),r=je(s,"#slm-ch-lk-quantity");if(o==null||r==null){this.showDialogError("Those two settings need to be whole numbers.");return}let d;if(n.value==="custom"&&(d=Date.parse(a.value),!Number.isFinite(d))){this.showDialogError("Pick the date and time the link should stop working.");return}this.createLink(t.id,{label:s.querySelector("#slm-ch-lk-label")?.value.trim()||null,includePublic:s.querySelector("#slm-ch-lk-public")?.checked??!1,...d===void 0?{}:{expiresAt:d},maxRedemptions:o,maxQuantity:r})})})}async createLink(e,t){await this.ensureHostedLinkRoute(e,t)&&await this.mintLink(e,t)}async mintLink(e,t){try{let s=await this.host.api.createAccessLink(this.host.eventKey,e,t);this.revealLink(s,{channelId:e}),await this.reloadAfterLinkChange(e)}catch(s){this.showDialogError(j(s instanceof x?s:void 0)),s instanceof x||this.host.onError(s)}}async ensureHostedLinkRoute(e,t){if((this.list?.channels.find(n=>n.id===e)?.access?.intent??"none")==="hosted_link")return!0;try{return await this.host.api.setChannelAccessIntent(this.host.eventKey,e,"hosted_link"),await this.refresh(),!0}catch(n){return n instanceof x&&n.code==="channel_intent_switch_blocked"?(this.openDialog({kind:"intentSwitch",channelId:e,intentTo:"hosted_link",switchBlocked:n.details,pendingLink:t}),!1):(this.showDialogError(n instanceof x&&n.code==="channel_access_intent_forbids"?G(n.details):"Couldn't set this channel up for buyer links. Try again."),n instanceof x||this.host.onError(n),!1)}}revealLink(e,t){let s=e.url;this.dialog=null;let n=t.rotated?`<div class="slm-ch-alert warn" role="status"><span>\u26A0</span><span>
716
+ <b>The old link has stopped working.</b> ${e.endedSessions?`${e.endedSessions.toLocaleString()} buyer${e.endedSessions===1?"":"s"} lost access immediately.`:"Buyers who already came in can finish; every new visit needs this link."}</span></div>`:"",i=se(e.link).map(a=>`<div class="slm-ch-lkrow"><span class="k">${p(a.k)}</span>
669
717
  <span class="v">${p(a.v)}</span></div>`).join("");this.renderScrim(`
670
718
  <h3 id="slm-ch-dlg-title">Copy this link now</h3>
671
719
  <p class="sub">This is the only time SeatLayer can show it. We keep just a fingerprint, so it cannot be
672
720
  shown again \u2014 if it is lost, rotate the link for a fresh one.</p>
673
721
  ${n}
674
- <div class="slm-ch-secret" data-ch-lk-url>${p(s)}</div>
675
- <div class="slm-ch-row2" style="margin-top:8px">
676
- <button type="button" class="slm-btn" data-ch-lk-copy>Copy link</button>
722
+ <div class="slm-ch-copyrow">
723
+ <div class="slm-ch-secret" data-ch-lk-url title="${p(s)}">${p(s)}</div>
724
+ <button type="button" class="slm-btn" data-ch-lk-copy aria-live="polite">Copy</button>
677
725
  </div>
726
+ <input class="slm-ch-copysink" data-ch-lk-sink tabindex="-1" aria-hidden="true" readonly />
678
727
  <div class="slm-ch-alert warn" style="margin-top:12px"><span>\u26A0</span>
679
728
  <span>Anyone who opens this link can buy from this allocation. Send it only to the people it is meant
680
729
  for \u2014 forwarding it hands on the same access, and SeatLayer cannot tell the difference.</span></div>
@@ -682,7 +731,7 @@
682
731
  ${i}
683
732
  <div class="foot">
684
733
  <button type="button" class="slm-btn" data-ch-close data-ch-lk-done>I've copied it</button>
685
- </div>`,a=>{let o=a.querySelector("[data-ch-lk-copy]");o?.addEventListener("click",()=>{let r=()=>{o.textContent="Copied",this.announce("Buyer link copied.")},c=typeof navigator>"u"?null:navigator.clipboard;if(c?.writeText){c.writeText(s).then(r,()=>Ne(a));return}Ne(a)})}),this.announce("Your buyer link is ready and is shown once.")}renderLinkRotateDialog(e){let t=this.linkById(e.linkId);if(!t||!this.caps.manage){this.closeDialog();return}let s=t.activeSessions??0,n=s?`<div class="slm-ch-alert warn"><span>\u26A0</span>
734
+ </div>`,a=>{let o=a.querySelector("[data-ch-lk-copy]"),r=null;o?.addEventListener("click",()=>{wt(a,s).then(d=>{if(!d){o.textContent="Copy",o.classList.remove("copied"),this.announce("Copying was blocked. The link is selected \u2014 copy it by hand.");return}o.textContent="Copied",o.classList.add("copied"),this.announce("Buyer link copied."),r&&clearTimeout(r),r=setTimeout(()=>{o.textContent="Copy",o.classList.remove("copied")},1500)})})}),this.announce("Your buyer link is ready and is shown once.")}renderLinkRotateDialog(e){let t=this.linkById(e.linkId);if(!t||!this.caps.manage){this.closeDialog();return}let s=t.activeSessions??0,n=s?`<div class="slm-ch-alert warn"><span>\u26A0</span>
686
735
  <span><b>${s.toLocaleString()} buyer${s===1?"":"s"}</b> got in with the current link
687
736
  and still ${s===1?"has":"have"} active access.</span></div>`:"";this.renderScrim(`
688
737
  <h3 id="slm-ch-dlg-title">Rotate the ${p(t.label||"buyer")} link?</h3>
@@ -704,7 +753,7 @@
704
753
  <div class="foot">
705
754
  <button type="button" class="quiet" data-ch-close>Cancel</button>
706
755
  <button type="button" class="slm-btn" data-ch-lk-rotate disabled>Rotate and copy new link</button>
707
- </div>`,i=>{let a=i.querySelector("[data-ch-lk-rotate]");i.querySelectorAll("[data-ch-rot]").forEach(o=>{o.addEventListener("change",()=>{a.disabled=!1})}),a.addEventListener("click",()=>{let o=[...i.querySelectorAll("[data-ch-rot]")].find(r=>r.checked);if(!o){this.showDialogError(N({code:"end_active_sessions_required"}));return}this.rotateLink(e.channelId,t.id,o.value==="end")})})}async rotateLink(e,t,s){try{let n=await this.host.api.rotateAccessLink(this.host.eventKey,e,t,s);this.revealLink(n,{channelId:e,rotated:!0}),await this.reloadAfterLinkChange(e)}catch(n){this.showDialogError(N(n instanceof y?n:void 0)),n instanceof y||this.host.onError(n)}}renderLinkRevokeDialog(e){let t=this.linkById(e.linkId);if(!t||!this.caps.manage){this.closeDialog();return}let s=t.activeSessions??0;this.renderScrim(`
756
+ </div>`,i=>{let a=i.querySelector("[data-ch-lk-rotate]");i.querySelectorAll("[data-ch-rot]").forEach(o=>{o.addEventListener("change",()=>{a.disabled=!1})}),a.addEventListener("click",()=>{let o=[...i.querySelectorAll("[data-ch-rot]")].find(r=>r.checked);if(!o){this.showDialogError(j({code:"end_active_sessions_required"}));return}this.rotateLink(e.channelId,t.id,o.value==="end")})})}async rotateLink(e,t,s){try{let n=await this.host.api.rotateAccessLink(this.host.eventKey,e,t,s);this.revealLink(n,{channelId:e,rotated:!0}),await this.reloadAfterLinkChange(e)}catch(n){this.showDialogError(j(n instanceof x?n:void 0)),n instanceof x||this.host.onError(n)}}renderLinkRevokeDialog(e){let t=this.linkById(e.linkId);if(!t||!this.caps.manage){this.closeDialog();return}let s=t.activeSessions??0;this.renderScrim(`
708
757
  <h3 id="slm-ch-dlg-title">Revoke the ${p(t.label||"buyer")} link?</h3>
709
758
  <p class="sub">It stops opening immediately and cannot be restored \u2014 there is no undo, and no way to
710
759
  bring the same URL back. Seats already bought through it keep their sale.</p>
@@ -718,16 +767,17 @@
718
767
  <div class="foot">
719
768
  <button type="button" class="quiet" data-ch-close>Cancel</button>
720
769
  <button type="button" class="slm-btn danger" data-ch-lk-revoke>Revoke link</button>
721
- </div>`,n=>{n.querySelector("[data-ch-lk-revoke]")?.addEventListener("click",()=>{let i=n.querySelector("[data-ch-lk-endsessions]")?.checked??!1;this.revokeLink(e.channelId,t.id,i)})})}async revokeLink(e,t,s){try{let n=await this.host.api.revokeAccessLink(this.host.eventKey,e,t,s);this.closeDialog(),await this.reloadAfterLinkChange(e),this.host.toast(n.endedSessions?`Link revoked. ${n.endedSessions.toLocaleString()} buyer${n.endedSessions===1?"":"s"} lost access.`:"Link revoked. It no longer opens for anyone.","ok")}catch(n){this.showDialogError(N(n instanceof y?n:void 0)),n instanceof y||this.host.onError(n)}}applySheetClasses(){let e=this.host.root,t=this.host.isCompact();e.classList.toggle("ch-sheet",t&&this.active);for(let s of["collapsed","medium","full"])e.classList.toggle(`detent-${s}`,t&&this.active&&this.detent===s);this.host.setMapInert(t&&this.active&&this.detent==="full")}cycleDetent(){let e=["collapsed","medium","full"];this.detent=e[(e.indexOf(this.detent)+1)%e.length],this.applySheetClasses()}handleBack(){return this.scrimEl?(this.closeDialog(),!0):this.host.isCompact()&&this.detent==="full"?(this.detent="medium",this.applySheetClasses(),!0):!1}}});var rs={};Ue(rs,{ACCESS_LINK_DEFAULTS:()=>J,ChannelsMode:()=>se,ManageApi:()=>U,ManageApiError:()=>y,PUBLIC_CHANNEL_ID:()=>T,PUBLIC_CHANNEL_NAME:()=>A,SeatManager:()=>Ae,accessIntentDescription:()=>Se,accessIntentLabel:()=>F,accessLine:()=>we,accessLinkBadge:()=>Ce,accessLinkErrorCopy:()=>N,accessLinkIsLive:()=>ee,accessLinkPolicyLines:()=>te,bucketRows:()=>ke,bucketRowsHtml:()=>W,dropReviewRows:()=>gt,intentForbidsCopy:()=>Y,intentSwitchBlockedCopy:()=>Le,isPublicChannelId:()=>B,markerLetter:()=>z,markerOf:()=>ge,mutationCount:()=>K,needsMoveConfirmation:()=>ye,planAssignment:()=>fe,retryAfterCopy:()=>xe,selectionSources:()=>ve,stateBadge:()=>Te,suggestMarker:()=>Q});module.exports=Dt(rs);Ie();var Ke={hold:"Held",release:"Released",expire:"Expired",book:"Booked",unbook:"Cancelled",block:"Blocked",unblock:"Unblocked"},ie=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 n=await this.fetchPage(e?this.next:void 0,this.action);if(this.closed||s!==this.generation)return;if(this.paintCounts(n),t&&this.entries.length&&n.entries[0]?.id!==this.entries[0]?.id&&this.list.scrollTop>24){this.latest.hidden=!1;return}let i=!t||n.entries[0]?.id!==this.entries[0]?.id;e?(this.entries=[...this.entries,...n.entries.filter(a=>!this.entries.some(o=>o.id===a.id))],this.next=n.nextBefore):i&&(this.entries=n.entries,this.next=n.nextBefore),i&&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 n=document.createElement("button");n.className="slm-btn ghost",n.textContent="Retry",n.onclick=()=>{this.load(e)},this.message.append(n)}}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:n})=>{let i=document.createElement("button");return i.type="button",i.textContent=s?`${Ke[s]??s} ${n}`:`${n} changes`,i.setAttribute("aria-pressed",String((this.action??"")===s)),i.onclick=()=>{this.busy||(this.action=s||void 0,this.entries=[],this.next=null,this.list.scrollTop=0,this.latest.hidden=!0,this.load())},i}))}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 n=document.createElement("time");n.dateTime=new Date(t.at).toISOString(),n.textContent=new Date(t.at).toLocaleString(void 0,{year:"numeric",month:"short",day:"numeric",hour:"2-digit",minute:"2-digit",second:"2-digit"}),n.title=new Date(t.at).toString();let i=document.createElement("strong");return i.textContent=Ke[t.action]??t.action,s.append(n,i),s})),this.list.scrollTop=e}};var Ot={held:"HOLD",booked:"BOOK",expired:"EXPIRE",released:"RELEASE",cancelled:"CANCEL",blocked:"BLOCK",unblocked:"ON SALE",available:"FREE"},Ye={held:"Held",booked:"Booked",expired:"Hold expired",released:"Hold released",cancelled:"Booking cancelled",blocked:"Blocked",unblocked:"Back on sale",available:"Available again"},ae=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 n={signal:this.abort.signal},i=()=>{this.paused=!1,this.signature="unrendered",this.list.scrollTop=0,this.render()};this.list.addEventListener("scroll",()=>{this.list.scrollTop>24&&(this.paused=!0)},n),this.list.addEventListener("focusin",()=>{this.paused=!0},n),this.list.addEventListener("toggle",a=>{a.target.open&&(this.paused=!0)},{...n,capture:!0}),this.newer.addEventListener("click",i,n),this.more.addEventListener("click",()=>{this.limit=200,this.signature="unrendered",this.render(!0)},n)}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 n=t.slice(0,this.limit),i=n.map(a=>`${a.id}:${a.verb}`).join("|");if(i!==this.signature){if(this.signature=i,this.shown=new Set(t.map(a=>a.id)),this.list.replaceChildren(),!n.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 n){let o=document.createElement("article");o.className="slm-activity-entry",o.dataset.status=a.status;let r=document.createElement("button");r.type="button",r.className="slm-activity-row";let c=`${Ye[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=Ot[a.verb]??a.verb,h.title=Ye[a.verb]??a.verb;let u=document.createElement("span");if(u.className="slm-activity-seats",u.textContent=a.labels.join(", "),r.append(d,h,u),o.append(r),a.count>1){let f=document.createElement("details");f.className="slm-activity-details";let v=document.createElement("summary");v.textContent="\u22EF",v.setAttribute("aria-label",`Show all ${a.count} seats`);let g=document.createElement("p");g.textContent=c,f.append(v,g),o.append(f)}this.list.append(o)}this.more.hidden=t.length<=this.limit}}destroy(){this.abort.abort()}};var oe=class{constructor(e){this.host=e;this.moving=!1;this.space=!1;this.abort=new AbortController;let t=document.createElement("div");t.className="slm-navigation";let s=m=>`<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">${m}</svg>`,n=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"/>'),i=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"/>'),o=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">
770
+ </div>`,n=>{n.querySelector("[data-ch-lk-revoke]")?.addEventListener("click",()=>{let i=n.querySelector("[data-ch-lk-endsessions]")?.checked??!1;this.revokeLink(e.channelId,t.id,i)})})}async revokeLink(e,t,s){try{let n=await this.host.api.revokeAccessLink(this.host.eventKey,e,t,s);this.closeDialog(),await this.reloadAfterLinkChange(e),this.host.toast(n.endedSessions?`Link revoked. ${n.endedSessions.toLocaleString()} buyer${n.endedSessions===1?"":"s"} lost access.`:"Link revoked. It no longer opens for anyone.","ok")}catch(n){this.showDialogError(j(n instanceof x?n:void 0)),n instanceof x||this.host.onError(n)}}applySheetClasses(){let e=this.host.root,t=this.host.isCompact();e.classList.toggle("ch-sheet",t&&this.active);for(let s of["collapsed","medium","full"])e.classList.toggle(`detent-${s}`,t&&this.active&&this.detent===s);this.host.setMapInert(t&&this.active&&this.detent==="full")}cycleDetent(){let e=["collapsed","medium","full"];this.detent=e[(e.indexOf(this.detent)+1)%e.length],this.applySheetClasses()}handleBack(){return this.scrimEl?(this.closeDialog(),!0):this.host.isCompact()&&this.detent==="full"?(this.detent="medium",this.applySheetClasses(),!0):!1}}});var fs={};Ke(fs,{ACCESS_LINK_DEFAULTS:()=>ee,ChannelsMode:()=>ne,ManageApi:()=>K,ManageApiError:()=>x,PUBLIC_CHANNEL_ID:()=>T,PUBLIC_CHANNEL_NAME:()=>M,SeatManager:()=>Ie,accessIntentDescription:()=>Ce,accessIntentLabel:()=>F,accessLine:()=>Le,accessLinkBadge:()=>Re,accessLinkErrorCopy:()=>j,accessLinkIsLive:()=>te,accessLinkPolicyLines:()=>se,bucketRows:()=>we,bucketRowsHtml:()=>W,dropReviewRows:()=>ft,intentForbidsCopy:()=>G,intentSwitchBlockedCopy:()=>Te,isPublicChannelId:()=>D,markerLetter:()=>z,markerOf:()=>fe,mutationCount:()=>Y,needsMoveConfirmation:()=>xe,planAssignment:()=>ke,retryAfterCopy:()=>Se,selectionSources:()=>ye,stateBadge:()=>$e,suggestMarker:()=>J});module.exports=_t(fs);Pe();var Ye={hold:"Held",release:"Released",expire:"Expired",book:"Booked",unbook:"Cancelled",block:"Blocked",unblock:"Unblocked"},ae=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 n=await this.fetchPage(e?this.next:void 0,this.action);if(this.closed||s!==this.generation)return;if(this.paintCounts(n),t&&this.entries.length&&n.entries[0]?.id!==this.entries[0]?.id&&this.list.scrollTop>24){this.latest.hidden=!1;return}let i=!t||n.entries[0]?.id!==this.entries[0]?.id;e?(this.entries=[...this.entries,...n.entries.filter(a=>!this.entries.some(o=>o.id===a.id))],this.next=n.nextBefore):i&&(this.entries=n.entries,this.next=n.nextBefore),i&&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 n=document.createElement("button");n.className="slm-btn ghost",n.textContent="Retry",n.onclick=()=>{this.load(e)},this.message.append(n)}}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:n})=>{let i=document.createElement("button");return i.type="button",i.textContent=s?`${Ye[s]??s} ${n}`:`${n} changes`,i.setAttribute("aria-pressed",String((this.action??"")===s)),i.onclick=()=>{this.busy||(this.action=s||void 0,this.entries=[],this.next=null,this.list.scrollTop=0,this.latest.hidden=!0,this.load())},i}))}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 n=document.createElement("time");n.dateTime=new Date(t.at).toISOString(),n.textContent=new Date(t.at).toLocaleString(void 0,{year:"numeric",month:"short",day:"numeric",hour:"2-digit",minute:"2-digit",second:"2-digit"}),n.title=new Date(t.at).toString();let i=document.createElement("strong");return i.textContent=Ye[t.action]??t.action,s.append(n,i),s})),this.list.scrollTop=e}};var jt={held:"HOLD",booked:"BOOK",expired:"EXPIRE",released:"RELEASE",cancelled:"CANCEL",blocked:"BLOCK",unblocked:"ON SALE",available:"FREE"},Ge={held:"Held",booked:"Booked",expired:"Hold expired",released:"Hold released",cancelled:"Booking cancelled",blocked:"Blocked",unblocked:"Back on sale",available:"Available again"},oe=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 n={signal:this.abort.signal},i=()=>{this.paused=!1,this.signature="unrendered",this.list.scrollTop=0,this.render()};this.list.addEventListener("scroll",()=>{this.list.scrollTop>24&&(this.paused=!0)},n),this.list.addEventListener("focusin",()=>{this.paused=!0},n),this.list.addEventListener("toggle",a=>{a.target.open&&(this.paused=!0)},{...n,capture:!0}),this.newer.addEventListener("click",i,n),this.more.addEventListener("click",()=>{this.limit=200,this.signature="unrendered",this.render(!0)},n)}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 n=t.slice(0,this.limit),i=n.map(a=>`${a.id}:${a.verb}`).join("|");if(i!==this.signature){if(this.signature=i,this.shown=new Set(t.map(a=>a.id)),this.list.replaceChildren(),!n.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 n){let o=document.createElement("article");o.className="slm-activity-entry",o.dataset.status=a.status;let r=document.createElement("button");r.type="button",r.className="slm-activity-row";let d=`${Ge[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=`${d} \u2014 click to show seats on the map`,r.setAttribute("aria-label",`Show seats on map: ${d}`),r.addEventListener("click",()=>this.locate(a.id));let c=document.createElement("time");c.dateTime=new Date(a.at).toISOString(),c.textContent=new Date(a.at).toLocaleTimeString([],{hour:"2-digit",minute:"2-digit"});let h=document.createElement("strong");h.textContent=jt[a.verb]??a.verb,h.title=Ge[a.verb]??a.verb;let u=document.createElement("span");if(u.className="slm-activity-seats",u.textContent=a.labels.join(", "),r.append(c,h,u),o.append(r),a.count>1){let f=document.createElement("details");f.className="slm-activity-details";let v=document.createElement("summary");v.textContent="\u22EF",v.setAttribute("aria-label",`Show all ${a.count} seats`);let g=document.createElement("p");g.textContent=d,f.append(v,g),o.append(f)}this.list.append(o)}this.more.hidden=t.length<=this.limit}}destroy(){this.abort.abort()}};var le=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=m=>`<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">${m}</svg>`,n=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"/>'),i=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"/>'),o=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">
722
771
  <button type="button" data-nav="move" aria-label="Move" aria-pressed="false" title="Drag to move the map; hold Space temporarily">${n}</button>
723
- <button type="button" data-nav="select" aria-label="Select" aria-pressed="true" title="Drag to select seats">${i}</button>
772
+ <button type="button" data-nav="select" aria-label="Select" aria-pressed="true" title="Drag to select seats \xB7 drag empty floor to move">${i}</button>
724
773
  <button type="button" data-nav="search" aria-label="Search" title="Search seats, rows or sections" aria-expanded="false">${a}</button>
725
774
  <button type="button" data-nav="zoom" aria-label="Zoom" title="Zoom controls" aria-expanded="false">${o}</button>
726
775
  <button type="button" hidden data-nav="out" aria-label="Zoom out">\u2212</button>
727
776
  <button type="button" hidden data-nav="in" aria-label="Zoom in">+</button>
728
777
  <span class="slm-navigation-count" role="status" aria-live="polite">0 selected</span>
778
+ <button type="button" class="slm-navigation-clear" data-nav="clear" hidden title="Clear the selection">Clear</button>
729
779
  <button type="button" data-nav="rail" aria-label="Hide details" title="Hide details" aria-expanded="true">${r}</button>
730
- </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.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"),u=()=>{h.hidden=!0,this.results.hidden=!0,d.setAttribute("aria-expanded","false"),d.focus()};d.addEventListener("click",()=>{let m=h.hidden;h.hidden=!m,d.setAttribute("aria-expanded",String(m)),m&&this.search.focus()},c);let f=t.querySelector('[data-nav="zoom"]');f.addEventListener("click",()=>{let m=f.getAttribute("aria-expanded")!=="true";f.setAttribute("aria-expanded",String(m));for(let k of["in","out"])t.querySelector(`[data-nav="${k}"]`).hidden=!m},c),this.search.addEventListener("keydown",m=>{m.key==="Escape"&&u()},c),this.move.addEventListener("click",()=>this.setMoving(!0),c),this.select.addEventListener("click",()=>this.setMoving(!1),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 v=t.querySelector('[data-nav="rail"]');v.addEventListener("click",()=>{let m=e.root.classList.toggle("details-hidden");v.setAttribute("aria-expanded",String(!m)),v.setAttribute("aria-label",m?"Show details":"Hide details"),v.title=m?"Show details":"Hide details"},c),this.search.addEventListener("input",()=>this.find(),c),this.search.addEventListener("keydown",m=>{m.key==="Escape"&&(this.results.hidden=!0),m.key==="ArrowDown"&&(m.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",m=>{m.target?.closest('input,textarea,select,button,[contenteditable="true"]')||m.code!=="Space"||m.ctrlKey||m.metaKey||m.altKey||(m.preventDefault(),this.space||(this.space=!0,e.pauseFollow(),e.setMoving(!0)))},c);let g=()=>{this.space&&(this.space=!1,e.setMoving(this.moving))};window.addEventListener("keyup",m=>{m.code==="Space"&&g()},c),window.addEventListener("blur",g,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",m=>{e.root.contains(m.relatedTarget)||g()},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.bar.querySelector(".slm-navigation-count").hidden=t,this.move.hidden=!e,this.select.hidden=!e}selectionChanged(e){this.bar.querySelector(".slm-navigation-count").textContent=`${e.toLocaleString()} selected`}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 n=document.createElement("button");n.type="button",n.textContent=`${s.label} \xB7 ${s.detail}`,n.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(n)}t.length||(this.results.textContent="No matching section, row or seat.")}destroy(){this.abort.abort(),this.bar.remove(),this.location.remove()}};var S=require("@seatlayer/core");re();var jt=/^[a-zA-Z0-9._-]+$/;function Nt(l){let e;try{e=new URL(l,"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]),n=decodeURIComponent(t[2]);return!s||!jt.test(n)?null:{eventKey:s,asset:n}}catch{return null}}function _t(l){try{return/^\/v1\/events\/[^/]+\/assets(?:\/|$)/.test(new URL(l,"https://seatlayer.invalid").pathname)}catch{return!1}}var ce=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=Nt(e);if(!t)return Promise.resolve(_t(e)?null:e);if(t.eventKey!==this.eventKey||this.disposed)return Promise.resolve(null);let s=`${t.eventKey}/${t.asset}`,n=this.pending.get(s);if(n)return n;let i=this.load(t.eventKey,t.asset).then(a=>{let o=URL.createObjectURL(a);return this.disposed?(URL.revokeObjectURL(o),null):(this.created.add(o),o)}).catch(a=>{throw this.pending.delete(s),a});return this.pending.set(s,i),i}async prepareRendererChart(e){let t=async i=>{if(!i?.url)return;let a=await this.resolve(i.url);if(!a)throw new Error("organizer_event_asset_scope_mismatch");i.url=a},s=async i=>{for(let a of i){if(a.type!=="decorImage")continue;let o=a,r=await this.resolve(o.href);if(!r)throw new Error("organizer_event_asset_scope_mismatch");o.href=r}},n=async i=>{await t(i.backgroundImage),await s(i.objects)};await n(e);for(let i of e.floors??[])await n(i);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 Ze="seatlayer-manager-style",Qe="seatlayer-manager-channels-style",Vt=`
780
+ </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 d={signal:this.abort.signal},c=t.querySelector('[data-nav="search"]'),h=t.querySelector(".slm-navigation-search"),u=()=>{h.hidden=!0,this.results.hidden=!0,c.setAttribute("aria-expanded","false"),c.focus()};c.addEventListener("click",()=>{let m=h.hidden;h.hidden=!m,c.setAttribute("aria-expanded",String(m)),m&&this.search.focus()},d);let f=t.querySelector('[data-nav="zoom"]');f.addEventListener("click",()=>{let m=f.getAttribute("aria-expanded")!=="true";f.setAttribute("aria-expanded",String(m));for(let y of["in","out"])t.querySelector(`[data-nav="${y}"]`).hidden=!m},d),this.search.addEventListener("keydown",m=>{m.key==="Escape"&&u()},d),this.move.addEventListener("click",()=>this.setMoving(!0),d),this.select.addEventListener("click",()=>this.setMoving(!1),d),this.clear.addEventListener("click",()=>this.host.clearSelection(),d),t.querySelector('[data-nav="in"]').addEventListener("click",()=>{this.location.hidden=!0,e.pauseFollow(),e.zoomIn()},d),t.querySelector('[data-nav="out"]').addEventListener("click",()=>{this.location.hidden=!0,e.pauseFollow(),e.zoomOut()},d);let v=t.querySelector('[data-nav="rail"]');v.addEventListener("click",()=>{let m=e.root.classList.toggle("details-hidden");v.setAttribute("aria-expanded",String(!m)),v.setAttribute("aria-label",m?"Show details":"Hide details"),v.title=m?"Show details":"Hide details"},d),this.search.addEventListener("input",()=>this.find(),d),this.search.addEventListener("keydown",m=>{m.key==="Escape"&&(this.results.hidden=!0),m.key==="ArrowDown"&&(m.preventDefault(),this.results.querySelector("button")?.focus())},d),e.map.addEventListener("pointerdown",()=>{this.location.hidden=!0,e.pauseFollow(),e.root.focus({preventScroll:!0}),this.results.hidden=!0},{...d,capture:!0}),e.root.querySelector(".slm-rail")?.addEventListener("pointerdown",()=>e.pauseFollow(),{...d,capture:!0}),e.map.addEventListener("wheel",()=>{this.location.hidden=!0,e.pauseFollow()},{...d,passive:!0,capture:!0}),e.root.addEventListener("keydown",m=>{m.target?.closest('input,textarea,select,button,[contenteditable="true"]')||m.code!=="Space"||m.ctrlKey||m.metaKey||m.altKey||(m.preventDefault(),this.space||(this.space=!0,e.pauseFollow(),e.setMoving(!0)))},d);let g=()=>{this.space&&(this.space=!1,e.setMoving(this.moving))};window.addEventListener("keyup",m=>{m.code==="Space"&&g()},d),window.addEventListener("blur",g,d),window.addEventListener("resize",()=>{this.location.hidden=!0},d),e.root.querySelector('[data-ref="zfit"]')?.addEventListener("click",()=>{this.location.hidden=!0},d),e.root.addEventListener("focusout",m=>{e.root.contains(m.relatedTarget)||g()},d)}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 n=document.createElement("button");n.type="button",n.textContent=`${s.label} \xB7 ${s.detail}`,n.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(n)}t.length||(this.results.textContent="No matching section, row or seat.")}destroy(){this.abort.abort(),this.bar.remove(),this.location.remove()}};var w=require("@seatlayer/core");ce();var Yt=/^[a-zA-Z0-9._-]+$/;function Gt(l){let e;try{e=new URL(l,"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]),n=decodeURIComponent(t[2]);return!s||!Yt.test(n)?null:{eventKey:s,asset:n}}catch{return null}}function Wt(l){try{return/^\/v1\/events\/[^/]+\/assets(?:\/|$)/.test(new URL(l,"https://seatlayer.invalid").pathname)}catch{return!1}}var de=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=Gt(e);if(!t)return Promise.resolve(Wt(e)?null:e);if(t.eventKey!==this.eventKey||this.disposed)return Promise.resolve(null);let s=`${t.eventKey}/${t.asset}`,n=this.pending.get(s);if(n)return n;let i=this.load(t.eventKey,t.asset).then(a=>{let o=URL.createObjectURL(a);return this.disposed?(URL.revokeObjectURL(o),null):(this.created.add(o),o)}).catch(a=>{throw this.pending.delete(s),a});return this.pending.set(s,i),i}async prepareRendererChart(e){let t=async i=>{if(!i?.url)return;let a=await this.resolve(i.url);if(!a)throw new Error("organizer_event_asset_scope_mismatch");i.url=a},s=async i=>{for(let a of i){if(a.type!=="decorImage")continue;let o=a,r=await this.resolve(o.href);if(!r)throw new Error("organizer_event_asset_scope_mismatch");o.href=r}},n=async i=>{await t(i.backgroundImage),await s(i.objects)};await n(e);for(let i of e.floors??[])await n(i);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 Qe="seatlayer-manager-style",Je="seatlayer-manager-channels-style",Xt=`
731
781
  /* The floor was 480px, which trapped the cockpit in any host shorter than that:
732
782
  every ancestor here is overflow:hidden, so the bottom of the rail (Create
733
783
  channel, Show archived) was rendered but clipped away by the host and could
@@ -762,6 +812,9 @@
762
812
  .slm .slm-navigation .slm-navigation-tools button{width:32px;height:32px;min-width:32px;min-height:32px;padding:0;border:0;border-radius:5px;background:transparent;box-shadow:none;color:var(--slm-muted);cursor:pointer}
763
813
  .slm .slm-navigation .slm-navigation-tools button:hover{background:var(--slm-tint);color:var(--slm-text)}
764
814
  .slm .slm-navigation .slm-navigation-tools button[aria-pressed=true],.slm .slm-navigation .slm-navigation-tools button[data-nav=search][aria-expanded=true],.slm .slm-navigation .slm-navigation-tools button[data-nav=zoom][aria-expanded=true]{background:var(--slm-accent);color:var(--slm-accent-ink)}
815
+ /* the count's companion \u2014 a word, not a 32px icon well */
816
+ .slm .slm-navigation .slm-navigation-tools button.slm-navigation-clear{width:auto;min-width:0;height:26px;min-height:26px;
817
+ padding:0 9px;border-radius:999px;font-size:11.5px;font-weight:800;color:var(--slm-accent);background:var(--slm-tint)}
765
818
  .slm .slm-navigation .slm-navigation-tools button[data-nav=rail]{margin-left:4px;position:relative}
766
819
  .slm .slm-navigation .slm-navigation-tools button[data-nav=rail]::before{content:'';position:absolute;left:-4px;top:7px;bottom:7px;width:1px;background:var(--slm-line)}
767
820
  .slm .slm-navigation .slm-navigation-tools button:focus-visible{outline:2px solid var(--slm-accent);outline-offset:1px}
@@ -876,17 +929,28 @@
876
929
  .slm-hud{position:absolute;left:12px;bottom:12px;display:flex;gap:8px}
877
930
  .slm .slm-hud-chip{padding:6px 11px;border-radius:999px;font-size:12px;font-weight:700;background:var(--slm-surface);
878
931
  border:1px solid var(--slm-line);color:var(--slm-text)}
879
- .slm-zoomhint{position:absolute;left:50%;top:14px;transform:translateX(-50%);padding:6px 13px;border-radius:999px;
880
- background:rgba(0,0,0,.55);color:#fff;font-size:12px;font-weight:700;pointer-events:none;opacity:0;
932
+ /* ONE top-centre lane. The zoom hint, the live-event pill and the Channels
933
+ preview banner were each pinned to left:50%;top:14px, so any two of them
934
+ showing at once sat on top of each other and the block-mode nudge only
935
+ moved the collision. They stack here instead, in whatever combination is
936
+ actually on screen. */
937
+ .slm-lane{position:absolute;left:50%;top:14px;transform:translateX(-50%);z-index:6;display:flex;flex-direction:column;
938
+ align-items:center;gap:8px;max-width:min(560px,calc(100% - 32px));pointer-events:none}
939
+ /* Only what is SHOWING takes a slot: a faded-out pill left in the flow would
940
+ push the others down by its own height plus the gap. Taken out of flow
941
+ rather than display:none'd, so the fade in and out still runs. */
942
+ .slm-lane>:not(.on){position:absolute;top:0;pointer-events:none}
943
+ .slm-zoomhint{padding:6px 13px;border-radius:999px;
944
+ background:color-mix(in srgb,var(--slm-surface) 92%,transparent);color:var(--slm-text);
945
+ border:1px solid var(--slm-line);font-size:12px;font-weight:700;pointer-events:none;opacity:0;
881
946
  transition:opacity var(--slm-mo-base) var(--slm-mo-out)}
882
947
  .slm-zoomhint.on{opacity:1}
883
- .slm-liveevent{position:absolute;left:50%;top:14px;z-index:4;display:flex;align-items:center;gap:8px;max-width:min(560px,calc(100% - 32px));
948
+ .slm-liveevent{display:flex;align-items:center;gap:8px;max-width:100%;
884
949
  padding:8px 12px;border:1px solid var(--slm-line);border-radius:999px;background:color-mix(in srgb,var(--slm-surface) 92%,transparent);
885
- box-shadow:0 10px 34px rgba(0,0,0,.32);opacity:0;transform:translate(-50%,-8px);pointer-events:none;
950
+ box-shadow:0 10px 34px rgba(0,0,0,.32);opacity:0;transform:translateY(-8px);pointer-events:none;
886
951
  transition:opacity var(--slm-mo-quick) var(--slm-mo-out),transform var(--slm-mo-base) var(--slm-mo-out);
887
952
  backdrop-filter:blur(10px)}
888
- .slm-liveevent.on{opacity:1;transform:translate(-50%,0)}
889
- .slm.block-mode .slm-liveevent{top:52px}
953
+ .slm-liveevent.on{opacity:1;transform:none}
890
954
  .slm-liveeventdot{width:8px;height:8px;border-radius:50%;flex:none}.slm-liveeventcopy{min-width:0;overflow:hidden;text-overflow:ellipsis;
891
955
  white-space:nowrap;font-size:12px;font-weight:800}.slm-liveeventhint{color:var(--slm-muted);font-size:10px;white-space:nowrap}
892
956
  .slm-rail{width:320px;flex:none;border-left:1px solid var(--slm-line);display:flex;flex-direction:column;min-height:0}
@@ -907,6 +971,10 @@
907
971
  .slm-legend{display:flex;flex-direction:column;gap:2px;margin-bottom:16px}
908
972
  .slm-legrow{display:flex;align-items:center;gap:9px;padding:7px 2px;border-bottom:1px solid var(--slm-line)}
909
973
  .slm-legdot{width:10px;height:10px;border-radius:50%;flex:none}
974
+ /* The status key inside a note line: a swatch, and blocked's light disc with
975
+ its cross \u2014 the same two marks the map paints. */
976
+ .slm-legmark{display:inline-block;width:9px;height:9px;border-radius:50%;vertical-align:middle}
977
+ .slm-legcross{display:inline-block;width:12px;height:12px;line-height:12px;text-align:center;border-radius:50%;background:#f1f4f9;font-size:9px;font-weight:800;vertical-align:middle}
910
978
  .slm-leglabel{flex:1;font-size:13px;font-weight:600}
911
979
  .slm-legcount{font-size:13px;font-weight:800;font-variant-numeric:tabular-nums}
912
980
 
@@ -995,6 +1063,8 @@
995
1063
  background:var(--slm-surface);color:var(--slm-text);border:1px solid var(--slm-line);z-index:5}
996
1064
  .slm-toast.on{opacity:1}
997
1065
  .slm-toast.err{background:#c0392b;color:#fff;border-color:#c0392b}
1066
+ /* err/ok keep their semantic grounds, and state an ink that reads on both of
1067
+ them \u2014 these are states, not chrome, so they do not follow the theme. */
998
1068
  .slm-toast.ok{background:#1f7a4d;color:#fff;border-color:#1f7a4d}
999
1069
 
1000
1070
  /* control-room actions + insights */
@@ -1148,31 +1218,31 @@
1148
1218
  transition:none!important;
1149
1219
  scroll-behavior:auto!important}
1150
1220
  }
1151
- `;function Je(){if(typeof document>"u"||document.getElementById(Ze))return;let l=document.createElement("style");l.id=Ze,l.textContent=Vt,document.head.appendChild(l)}function et(l){if(typeof document>"u"||document.getElementById(Qe))return;let e=document.createElement("style");e.id=Qe,e.textContent=l,document.head.appendChild(e)}var nt=require("@seatlayer/core");var tt=require("@seatlayer/core/core/color");var Pe={light:{background:"#ffffff",surface:"#f6f7fb",text:"#172033",muted:"#667085",line:"rgba(23,32,51,.16)",map:"#e9edf4"},dark:{background:"#0f1522",surface:"#1a2234",text:"#eef1f8",muted:"#a5aec2",line:"rgba(165,174,194,.24)",map:"#0f1522"}};function Ut(){try{return window.matchMedia?.("(prefers-color-scheme: dark)").matches===!0}catch{return!1}}function Be(l){if(l)return l==="auto"?Ut()?"dark":"light":l}function st(l){let e;try{e=window.matchMedia?.("(prefers-color-scheme: dark)")}catch{return()=>{}}if(!e)return()=>{};let t=s=>l(s.matches);return typeof e.addEventListener=="function"?e.addEventListener("change",t):e.addListener?.(t),()=>{typeof e.removeEventListener=="function"?e.removeEventListener("change",t):e.removeListener?.(t)}}function it(l){return l?l.mode:"open"}function at(l,e,t){switch(l){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 ot(l){return new Date(l-new Date().getTimezoneOffset()*6e4).toISOString().slice(0,16)}function lt(l){if(typeof l=="string"){let e=document.querySelector(l);if(!e)throw new Error(`seatmanager: container "${l}" not found`);return e}if(!(l instanceof HTMLElement))throw new Error("seatmanager: container must be a CSS selector or an HTMLElement");return l}function De(l){if(!l.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 de(l){return l==="blocked"?"not_for_sale":l}var rt=[{key:"free",label:"Free",color:"#6e7bff"},{key:"held",label:"Held",color:"#f4b740"},{key:"booked",label:"Booked",color:"#22a06b"},{key:"blocked",label:"Blocked",color:"#8b94ac"}];function ct(l,e){let t=l??{},s=e?Pe[e]:null,n=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":n?"rgba(23,32,51,.05)":"rgba(255,255,255,.035)","--slm-tint-strong":n?"rgba(23,32,51,.09)":"rgba(255,255,255,.07)","--slm-accent":t.accent??(n?"#4654c8":"#6e7bff"),"--slm-accent-ink":t.accentInk??"#ffffff","--slm-font":"-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif","--slm-radius":"14px"}}function dt(l){return l?Pe[l].map:null}function ht(l,e){let t=Math.max(0,Math.round((e-l)/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 he(l,e){return(0,nt.formatMoney)(l,e,{maximumFractionDigits:0,fallback:(t,s)=>`${s} ${Math.round(t).toLocaleString()}`})}function b(l){return String(l??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#039;")}var pt=require("@seatlayer/core");function Oe(l){return Object.entries(l).filter(([,e])=>e.mode==="closed").map(([e])=>e)}function pe(l){let e=l.sectionsBase;if(!e)return{rows:[],hiddenSections:0,closedSections:0};let t=l.doc?.zones??[],s=new Map,n=[];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 n.push(c);let i=[],a=0,o=0,r=(c,d,h,u=!1)=>{let f=l.availabilityRules[d.id]??null,v=l.effectiveClosed.has(d.id)||u,g=l.effectiveHidden.has(d.id)||h&&!v;c==="section"&&g&&(a+=1),c==="section"&&v&&(o+=1),i.push({kind:c,id:d.id,label:d.label,seatCount:d.seatCount,seatLabels:d.seatLabels,rule:f,hidden:g,closed:v,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((v,g)=>v+g.seatCount,0),seatLabels:d.flatMap(v=>v.seatLabels)},u=!!l.availabilityRules[c.id],f=l.availabilityRules[c.id]?.mode==="closed";r("zone",h,!1);for(let v of d)r("section",v,u,f)}for(let c of n)r("section",c,!1);if(e.ungrouped){let c=e.ungrouped;r("section",{id:pt.UNGROUPED_ID,label:c.label,seatCount:c.seatCount,seatLabels:c.seatLabels},!1)}return{rows:i,hiddenSections:a,closedSections:o}}function mt(l,e){let t=it(l.rule),s=`slm-availrow${l.kind==="zone"?" zone":""}${l.hidden?" hidden":""}${l.closed?" closed":""}`,n=e?" disabled":"",i=[["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=l.followsZone?'<span class="slm-availfollows">Follows zone</span>':`<details class="slm-availpicker" data-avail-picker>
1152
- <summary aria-label="Availability for ${b(l.label)}" ${e?'aria-disabled="true"':""}>${i.find(d=>d[0]===t)[1]}<span aria-hidden="true">\u2304</span></summary>
1221
+ `;function et(){if(typeof document>"u"||document.getElementById(Qe))return;let l=document.createElement("style");l.id=Qe,l.textContent=Xt,document.head.appendChild(l)}function tt(l){if(typeof document>"u"||document.getElementById(Je))return;let e=document.createElement("style");e.id=Je,e.textContent=l,document.head.appendChild(e)}var it=require("@seatlayer/core");var st=require("@seatlayer/core/core/color");var De={light:{background:"#ffffff",surface:"#f6f7fb",text:"#172033",muted:"#667085",line:"rgba(23,32,51,.16)",map:"#e9edf4"},dark:{background:"#0f1522",surface:"#1a2234",text:"#eef1f8",muted:"#a5aec2",line:"rgba(165,174,194,.24)",map:"#0f1522"}};function Zt(){try{return window.matchMedia?.("(prefers-color-scheme: dark)").matches===!0}catch{return!1}}function Oe(l){if(l)return l==="auto"?Zt()?"dark":"light":l}function nt(l){let e;try{e=window.matchMedia?.("(prefers-color-scheme: dark)")}catch{return()=>{}}if(!e)return()=>{};let t=s=>l(s.matches);return typeof e.addEventListener=="function"?e.addEventListener("change",t):e.addListener?.(t),()=>{typeof e.removeEventListener=="function"?e.removeEventListener("change",t):e.removeListener?.(t)}}function at(l){return l?l.mode:"open"}function ot(l,e,t){switch(l){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 lt(l){return new Date(l-new Date().getTimezoneOffset()*6e4).toISOString().slice(0,16)}function rt(l){if(typeof l=="string"){let e=document.querySelector(l);if(!e)throw new Error(`seatmanager: container "${l}" not found`);return e}if(!(l instanceof HTMLElement))throw new Error("seatmanager: container must be a CSS selector or an HTMLElement");return l}function ze(l){if(!l.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 pe(l){return l==="blocked"?"not_for_sale":l}var Qt=["free","booked","held","blocked"],A={free:"#6e7bff",booked:"#9ca3af",held:"#f4b740",blocked:"#475569"},he={free:"Free",booked:"Sold",held:"Held",blocked:"Blocked"},ct=[`<span class="slm-legmark" style="background:${A.free}"></span> Free = category colour`,`<span class="slm-legmark" style="background:${A.booked}"></span> ${he.booked}`,`<span class="slm-legmark" style="background:${A.held}"></span> ${he.held}`,`<span class="slm-legcross" style="color:${A.blocked}">\u2715</span> ${he.blocked}`].join(" \xB7 "),dt=Qt.map(l=>({key:l,label:he[l],color:A[l]}));function ht(l,e){let t=l??{},s=e?De[e]:null,n=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":n?"rgba(23,32,51,.05)":"rgba(255,255,255,.035)","--slm-tint-strong":n?"rgba(23,32,51,.09)":"rgba(255,255,255,.07)","--slm-accent":t.accent??(n?"#4654c8":"#6e7bff"),"--slm-accent-ink":t.accentInk??"#ffffff","--slm-font":"-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif","--slm-radius":"14px"}}function pt(l){return l?De[l].map:null}function mt(l,e){let t=Math.max(0,Math.round((e-l)/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 me(l,e){return(0,it.formatMoney)(l,e,{maximumFractionDigits:0,fallback:(t,s)=>`${s} ${Math.round(t).toLocaleString()}`})}function b(l){return String(l??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#039;")}var ut=require("@seatlayer/core");function Fe(l){return Object.entries(l).filter(([,e])=>e.mode==="closed").map(([e])=>e)}function ue(l){let e=l.sectionsBase;if(!e)return{rows:[],hiddenSections:0,closedSections:0};let t=l.doc?.zones??[],s=new Map,n=[];for(let d of e.sections)if(d.zone&&t.some(c=>c.id===d.zone)){let c=s.get(d.zone)??[];c.push(d),s.set(d.zone,c)}else n.push(d);let i=[],a=0,o=0,r=(d,c,h,u=!1)=>{let f=l.availabilityRules[c.id]??null,v=l.effectiveClosed.has(c.id)||u,g=l.effectiveHidden.has(c.id)||h&&!v;d==="section"&&g&&(a+=1),d==="section"&&v&&(o+=1),i.push({kind:d,id:c.id,label:c.label,seatCount:c.seatCount,seatLabels:c.seatLabels,rule:f,hidden:g,closed:v,followsZone:d==="section"&&h})};for(let d of t){let c=s.get(d.id);if(!c||!c.length)continue;let h={id:d.id,label:d.label||"Zone",seatCount:c.reduce((v,g)=>v+g.seatCount,0),seatLabels:c.flatMap(v=>v.seatLabels)},u=!!l.availabilityRules[d.id],f=l.availabilityRules[d.id]?.mode==="closed";r("zone",h,!1);for(let v of c)r("section",v,u,f)}for(let d of n)r("section",d,!1);if(e.ungrouped){let d=e.ungrouped;r("section",{id:ut.UNGROUPED_ID,label:d.label,seatCount:d.seatCount,seatLabels:d.seatLabels},!1)}return{rows:i,hiddenSections:a,closedSections:o}}function bt(l,e){let t=at(l.rule),s=`slm-availrow${l.kind==="zone"?" zone":""}${l.hidden?" hidden":""}${l.closed?" closed":""}`,n=e?" disabled":"",i=[["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=l.followsZone?'<span class="slm-availfollows">Follows zone</span>':`<details class="slm-availpicker" data-avail-picker>
1222
+ <summary aria-label="Availability for ${b(l.label)}" ${e?'aria-disabled="true"':""}>${i.find(c=>c[0]===t)[1]}<span aria-hidden="true">\u2304</span></summary>
1153
1223
  <div class="slm-availchoices" aria-label="Availability options for ${b(l.label)}">
1154
- ${i.map(([d,h,u])=>`<button type="button" data-avail-id="${b(l.id)}" data-avail-value="${d}" aria-pressed="${t===d}"${n}><span><b>${h}</b><small>${u}</small></span><span aria-hidden="true">${t===d?"\u2713":""}</span></button>`).join("")}
1224
+ ${i.map(([c,h,u])=>`<button type="button" data-avail-id="${b(l.id)}" data-avail-value="${c}" aria-pressed="${t===c}"${n}><span><b>${h}</b><small>${u}</small></span><span aria-hidden="true">${t===c?"\u2713":""}</span></button>`).join("")}
1155
1225
  </div>
1156
- </details>`,o="";if(!l.followsZone&&t==="timed"){let d=l.rule?.revealAt?b(ot(l.rule.revealAt)):"";o=`<div class="slm-availdetail">
1157
- <input type="datetime-local" class="slm-input" data-avail-reveal="${b(l.id)}" value="${d}"${n} aria-label="Reveal time for ${b(l.label)}" />
1158
- </div>`}else if(!l.followsZone&&t==="threshold"){let d=l.rule?.thresholdPct??80;o=`<div class="slm-availdetail">
1226
+ </details>`,o="";if(!l.followsZone&&t==="timed"){let c=l.rule?.revealAt?b(lt(l.rule.revealAt)):"";o=`<div class="slm-availdetail">
1227
+ <input type="datetime-local" class="slm-input" data-avail-reveal="${b(l.id)}" value="${c}"${n} aria-label="Reveal time for ${b(l.label)}" />
1228
+ </div>`}else if(!l.followsZone&&t==="threshold"){let c=l.rule?.thresholdPct??80;o=`<div class="slm-availdetail">
1159
1229
  <span class="slm-availpctlabel">Reveal at</span>
1160
- <input type="number" min="1" max="100" class="slm-input slm-availpct" data-avail-pct="${b(l.id)}" value="${b(d)}"${n} aria-label="Percent sold to reveal ${b(l.label)}" />
1230
+ <input type="number" min="1" max="100" class="slm-input slm-availpct" data-avail-pct="${b(l.id)}" value="${b(c)}"${n} aria-label="Percent sold to reveal ${b(l.label)}" />
1161
1231
  <span class="slm-availpctlabel">% sold</span>
1162
- </div>`}let r=l.closed?'<span class="slm-availbadge closed">Closed</span>':l.hidden?'<span class="slm-availbadge hidden">Hidden</span>':"",c=l.kind==="zone"?`<span class="slm-availcaret" aria-hidden="true">${l.hidden?"\u25B8":"\u25BE"}</span>`:"";return`<div class="${s}">
1232
+ </div>`}let r=l.closed?'<span class="slm-availbadge closed">Closed</span>':l.hidden?'<span class="slm-availbadge hidden">Hidden</span>':"",d=l.kind==="zone"?`<span class="slm-availcaret" aria-hidden="true">${l.hidden?"\u25B8":"\u25BE"}</span>`:"";return`<div class="${s}">
1163
1233
  <div class="slm-availhead">
1164
- <span class="slm-availlabel">${c}${b(l.label)}</span>
1234
+ <span class="slm-availlabel">${d}${b(l.label)}</span>
1165
1235
  ${r}
1166
1236
  <span class="slm-availcount">${l.seatCount.toLocaleString()}</span>
1167
1237
  </div>
1168
1238
  ${a}
1169
1239
  ${o}
1170
- </div>`}var os="https://api.seatlayer.io",Ee=200,Ct=16,Tt=4,Rt=[{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."}]}],ls=Object.fromEntries(Rt.flatMap(l=>l.tools.map(e=>[e.shortcut.toLowerCase(),e.mode]))),Ae=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(),n=ls[s];if(n){if(!this.toolAvailable(n))return;this.setMode(n)}else if(s==="f")this.toggleFullscreen();else if(s==="escape"){if(!this.channels?.handleBack())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 n=t?.closest("[data-feed-id]");n?.dataset.feedId&&this.locateActivity(n.dataset.feedId)};this.sectionOptions=[];De(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 U(e.apiBase??os,e.token),this.organizerAssetUrls=new ce(this.key,(t,s)=>this.withAuthRetry(()=>this.api.asset(t,s))),this.host=lt(e.container)}assertSelectionOptions(e,t){let s=n=>n===void 0||Number.isInteger(n)&&n>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(){Je(),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",n=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(),n&&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 n=new Set(t);s={view:n.has("event:channels:view"),manage:n.has("event:channels:view")&&n.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 Promise.resolve().then(()=>(_e(),Lt));if(this.closed||!this.channelCaps.view||(this.channels||(et(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"),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 n=e.get(s.rowId);if(!n||n.type!=="row"&&n.type!=="table")continue;let i=s.logicalRowId??s.rowId,a=this.sectionByObject.get(s.rowId)??S.UNGROUPED_ID,o=t.get(i)??{id:i,label:n.type==="row"?n.segmentedRow?.displayLabel??n.displayLabel??n.label:n.displayLabel??n.label,sectionId:a,sectionLabel:this.sectionLabelById.get(a)??"Other seats",labels:[]};o.labels.push(s.label),t.set(i,o)}return[...t.values()].sort((s,n)=>s.sectionLabel.localeCompare(n.sectionLabel,void 0,{numeric:!0,sensitivity:"base"})||s.label.localeCompare(n.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)??S.UNGROUPED_ID;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=Be(this.themeMode);for(let[t,s]of Object.entries(ct(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=st(()=>{this.closed||this.repaintForThemeMode()}))}repaintForThemeMode(){this.applyThemeVars();let e=this.renderer;if(!e||!this.doc)return;let t=e.getSelection().map(i=>i.id),s=e.getCameraPose(),n=e.getFocusedSection();e.setChart(this.themedDoc()),this.repaintAll(),this.applyHeatOverlay(),t.length&&e.select(t),n&&e.focusSection(n),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=dt(Be(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){De(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(),n=Math.min(12e4,Math.max(3e4,s*.2)),i=Math.max(0,s-n);this.tokenRefreshTimer=setTimeout(()=>{this.tokenRefreshTimer=null,this.rotateToken()},i)}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(i=>this.status.get(i)==="free");if(!s.length)return;let n=t.releaseAt??this.releaseAt??void 0;this.setSeatsLocal(s,"blocked");try{await this.api.block(this.key,s,{...t,releaseAt:n}),this.clearSelection(),this.done("block",s,n?`Blocked ${s.length} \u2014 auto-release ${new Date(n).toLocaleString()}.`:`Blocked ${s.length} seat${s.length===1?"":"s"}.`)}catch(i){this.setSeatsLocal(s,"free"),this.toastErr(i instanceof y&&i.status===409?"Some seats were just taken. Try again.":"Couldn't block those seats."),this.opts.onError?.(i)}}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(n=>this.status.get(n)==="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(n){this.setSeatsLocal(s,"booked"),this.toastErr("Couldn't release that booked inventory. Check the booking reference."),this.opts.onError?.(n)}}}async setCategory(e,t){let s=this.doc?.categories.find(i=>i.key===e),n=[...new Set(t??this.selectionLabels())].filter(i=>this.labelToSeat.has(i));if(!(!s||!n.length))try{let i=await this.withAuthRetry(()=>this.api.setCategory(this.key,n,e)),a={};for(let o of i.labels){let r=this.labelToSeat.get(o),c=this.labelToId.get(o);r&&(r.categoryKey=e),c&&(a[c]=e)}this.renderer?.setSeatCategories?.(a),this.clearSelection(),this.done("setCategory",i.labels,`Assigned ${i.labels.length.toLocaleString()} object${i.labels.length===1?"":"s"} to ${s.label??s.key}.`)}catch(i){this.toastErr("Couldn't update those event categories."),this.opts.onError?.(i)}}async setTableBooking(e,t,s={}){let n=[...new Set(e)].filter(Boolean);if(!(!n.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 i=await this.withAuthRetry(()=>this.api.setTableBooking(this.key,n,t,s));await this.reloadEventChart(),this.done("setTableBooking",i.tableIds,`Updated ${i.tableIds.length.toLocaleString()} table${i.tableIds.length===1?"":"s"} to ${t==="individual"?"per-chair":t==="whole"?"whole-table":"flexible-group"} booking.`)}catch(i){let a=i instanceof y&&i.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?.(i)}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(a=>a.label===t);if(!s.length)throw new Error(`Unknown event section: ${e}`);let n=t!==this.filteredSectionLabel;this.filteredSectionLabel=t,this.mode==="filterSections"&&(this.applyFilteredSectionCanvas(s),this.renderFilterSectionsRail());let i=s.map(({id:a,label:o,seatCount:r,zone:c})=>({id:a,label:o,seatCount:r,...c?{zone:c}:{}}));return n&&this.opts.onFilteredSectionChange?.(i),i}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:n})=>({id:e,label:t,seatCount:s,...n?{zone:n}:{}})):[]}selectByLabels(e){let t=e;if(this.mode==="select"){let s=new Set(this.selectionLabels()),n=this.selectionCap(),i=[...new Set(e)].filter(o=>!s.has(o)).map(o=>this.labelToSeat.get(o)).filter(o=>!!o&&this.canSelectObject(o)),a=Math.max(0,n-s.size);i.length>a&&this.opts.onSelectionLimit?.(n),t=i.slice(0,a).map(o=>o.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 S.SeatmapRenderer(this.mapHost,{manageMode:!0,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(n=>n.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(0,S.expandChart)(e))this.labelToId.set(t.label,t.id),this.labelToSeat.set(t.label,t),this.allIds.push(t.id);for(let t of(0,S.gaAreasOf)(e))for(let s of(0,S.gaUnitLabels)(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,n]of this.status.entries()){let i=this.labelToId.get(s);i&&t[de(n)].push(i)}["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 n=[],i=new Map;for(let o of s.changes){let r=["free","held","booked","blocked"].includes(o.status)?o.status:"free",c=this.status.get(o.label)??"free";if(c===r)continue;this.setStatusLabel(o.label,r,c);let d=this.labelToId.get(o.label);d&&(this.renderer?.setStatus([d],de(r)),n.push(d));let h=this.verbFor(c,r),u=`${h}:${r}`,f=i.get(u)??{labels:[],verb:h,status:r};f.labels.push(o.label),i.set(u,f)}for(let o of i.values()){let r=this.pushActivity(o.labels,o.verb,o.status);r&&this.paintSpatialActivity(r)}i.size&&this.scheduleMonitorRefresh(),n.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 n=new Map;for(let i of new Set([...s.keys(),...this.status.keys()])){let a=s.get(i)??"free",o=this.status.get(i)??"free";if(a===o)continue;let r=this.verbFor(a,o),c=`${r}:${o}`,d=n.get(c)??{labels:[],verb:r,status:o};d.labels.push(i),n.set(c,d)}for(let i of n.values()){let a=this.pushActivity(i.labels,i.verb,i.status);a&&this.paintSpatialActivity(a)}n.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=i=>["free","held","booked","blocked"].includes(i)?i:"free",n=new Map;if(t!==void 0){let i=s(t);for(let a of this.knownLabels())n.set(a,i)}for(let[i,a]of Object.entries(e))n.set(i,s(a));this.status=n,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 n of e){this.setStatusLabel(n,t);let i=this.labelToId.get(n);i&&s.push(i)}s.length&&this.renderer?.setStatus(s,de(t)),this.afterPaint(),this.recomputeTallies()}afterPaint(){this.keepLive&&typeof document<"u"&&document.hidden&&this.renderer?.forceDraw()}activityColor(e){return e==="held"?"#f4b740":e==="booked"?"#22a06b":e==="blocked"?"#8b94ac":"#6e7bff"}sectionsForLabels(e){let t=new Set;for(let n of e){let i=this.labelToSeat.get(n);if(!i)continue;let a=this.sectionByObject.get(i.rowId);a&&a!==S.UNGROUPED_ID&&t.add(a)}let s=[...t];return{ids:s,labels:s.map(n=>this.sectionLabelById.get(n)??n)}}pulseSeatLabels(e,t){let s=this.activityColor(t);for(let n of e.slice(0,Ct)){let i=this.labelToId.get(n);i&&this.renderer?.flashSeat(i,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 i=this.root?.querySelector('[data-ref="followstatus"]');i&&(i.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 i=this.activityColor(e.status);for(let a of t.slice(0,Tt))this.renderer?.flashSection(a,i);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,Ct).map(r=>this.labelToSeat.get(r)).filter(r=>!!r);if(!s.length)return;let n=s.map(r=>r.x),i=s.map(r=>r.y),a=Math.min(...n),o=Math.min(...i);this.renderer?.focusRegion({x:a-150,y:o-100,width:Math.max(...n)-a+300,height:Math.max(...i)-o+200})}locateActivity(e){let t=this.feed.find(n=>n.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 n=this.activityColor(t.status);for(let i of s.slice(0,Tt))this.renderer?.flashSection(i,n)}else this.pulseSeatLabels(t.labels,t.status)},280)}showLiveEvent(e){let t=this.els.liveevent;if(!t)return;let s=e.sectionLabels??[],n=s.length===1?s[0]:s.length>1?`${s.length} sections`:e.label,i=e.count===1?"seat":"seats";t.innerHTML=`<span class="slm-liveeventdot" style="background:${this.activityColor(e.status)}"></span>
1240
+ </div>`}var gs="https://api.seatlayer.io",Me=200,Mt=16,It=4,Ht=[{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."}]}],vs=Object.fromEntries(Ht.flatMap(l=>l.tools.map(e=>[e.shortcut.toLowerCase(),e.mode]))),Ie=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(),n=vs[s];if(n){if(!this.toolAvailable(n))return;this.setMode(n)}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 n=t?.closest("[data-feed-id]");n?.dataset.feedId&&this.locateActivity(n.dataset.feedId)};this.sectionOptions=[];ze(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 K(e.apiBase??gs,e.token),this.organizerAssetUrls=new de(this.key,(t,s)=>this.withAuthRetry(()=>this.api.asset(t,s))),this.host=rt(e.container)}assertSelectionOptions(e,t){let s=n=>n===void 0||Number.isInteger(n)&&n>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(){et(),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",n=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(),n&&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 n=new Set(t);s={view:n.has("event:channels:view"),manage:n.has("event:channels:view")&&n.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 Promise.resolve().then(()=>(Ve(),At));if(this.closed||!this.channelCaps.view||(this.channels||(tt(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 n=e.get(s.rowId);if(!n||n.type!=="row"&&n.type!=="table")continue;let i=s.logicalRowId??s.rowId,a=this.sectionByObject.get(s.rowId)??w.UNGROUPED_ID,o=t.get(i)??{id:i,label:n.type==="row"?n.segmentedRow?.displayLabel??n.displayLabel??n.label:n.displayLabel??n.label,sectionId:a,sectionLabel:this.sectionLabelById.get(a)??"Other seats",labels:[]};o.labels.push(s.label),t.set(i,o)}return[...t.values()].sort((s,n)=>s.sectionLabel.localeCompare(n.sectionLabel,void 0,{numeric:!0,sensitivity:"base"})||s.label.localeCompare(n.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)??w.UNGROUPED_ID;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=Oe(this.themeMode);for(let[t,s]of Object.entries(ht(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=nt(()=>{this.closed||this.repaintForThemeMode()}))}repaintForThemeMode(){this.applyThemeVars();let e=this.renderer;if(!e||!this.doc)return;let t=e.getSelection().map(i=>i.id),s=e.getCameraPose(),n=e.getFocusedSection();e.setChart(this.themedDoc()),this.repaintAll(),this.applyHeatOverlay(),t.length&&e.select(t),n&&e.focusSection(n),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=pt(Oe(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){ze(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(),n=Math.min(12e4,Math.max(3e4,s*.2)),i=Math.max(0,s-n);this.tokenRefreshTimer=setTimeout(()=>{this.tokenRefreshTimer=null,this.rotateToken()},i)}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(i=>this.status.get(i)==="free");if(!s.length)return;let n=t.releaseAt??this.releaseAt??void 0;this.setSeatsLocal(s,"blocked");try{await this.api.block(this.key,s,{...t,releaseAt:n}),this.clearSelection(),this.done("block",s,n?`Blocked ${s.length} \u2014 auto-release ${new Date(n).toLocaleString()}.`:`Blocked ${s.length} seat${s.length===1?"":"s"}.`)}catch(i){this.setSeatsLocal(s,"free"),this.toastErr(i instanceof x&&i.status===409?"Some seats were just taken. Try again.":"Couldn't block those seats."),this.opts.onError?.(i)}}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(n=>this.status.get(n)==="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(n){this.setSeatsLocal(s,"booked"),this.toastErr("Couldn't release that booked inventory. Check the booking reference."),this.opts.onError?.(n)}}}async setCategory(e,t){let s=this.doc?.categories.find(i=>i.key===e),n=[...new Set(t??this.selectionLabels())].filter(i=>this.labelToSeat.has(i));if(!(!s||!n.length))try{let i=await this.withAuthRetry(()=>this.api.setCategory(this.key,n,e)),a={};for(let o of i.labels){let r=this.labelToSeat.get(o),d=this.labelToId.get(o);r&&(r.categoryKey=e),d&&(a[d]=e)}this.renderer?.setSeatCategories?.(a),this.clearSelection(),this.done("setCategory",i.labels,`Assigned ${i.labels.length.toLocaleString()} object${i.labels.length===1?"":"s"} to ${s.label??s.key}.`)}catch(i){this.toastErr("Couldn't update those event categories."),this.opts.onError?.(i)}}async setTableBooking(e,t,s={}){let n=[...new Set(e)].filter(Boolean);if(!(!n.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 i=await this.withAuthRetry(()=>this.api.setTableBooking(this.key,n,t,s));await this.reloadEventChart(),this.done("setTableBooking",i.tableIds,`Updated ${i.tableIds.length.toLocaleString()} table${i.tableIds.length===1?"":"s"} to ${t==="individual"?"per-chair":t==="whole"?"whole-table":"flexible-group"} booking.`)}catch(i){let a=i instanceof x&&i.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?.(i)}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(a=>a.label===t);if(!s.length)throw new Error(`Unknown event section: ${e}`);let n=t!==this.filteredSectionLabel;this.filteredSectionLabel=t,this.mode==="filterSections"&&(this.applyFilteredSectionCanvas(s),this.renderFilterSectionsRail());let i=s.map(({id:a,label:o,seatCount:r,zone:d})=>({id:a,label:o,seatCount:r,...d?{zone:d}:{}}));return n&&this.opts.onFilteredSectionChange?.(i),i}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:n})=>({id:e,label:t,seatCount:s,...n?{zone:n}:{}})):[]}selectByLabels(e){let t=e;if(this.mode==="select"){let s=new Set(this.selectionLabels()),n=this.selectionCap(),i=[...new Set(e)].filter(o=>!s.has(o)).map(o=>this.labelToSeat.get(o)).filter(o=>!!o&&this.canSelectObject(o)),a=Math.max(0,n-s.size);i.length>a&&this.opts.onSelectionLimit?.(n),t=i.slice(0,a).map(o=>o.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 w.SeatmapRenderer(this.mapHost,{manageMode:!0,organizerGlyph:{apply:w.applyOrganizerSeatGlyph,clear:w.clearOrganizerSeatGlyph,isPainted:w.isOrganizerGlyphPainted},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(n=>n.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(0,w.expandChart)(e))this.labelToId.set(t.label,t.id),this.labelToSeat.set(t.label,t),this.allIds.push(t.id);for(let t of(0,w.gaAreasOf)(e))for(let s of(0,w.gaUnitLabels)(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,n]of this.status.entries()){let i=this.labelToId.get(s);i&&t[pe(n)].push(i)}["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 n=[],i=new Map;for(let o of s.changes){let r=["free","held","booked","blocked"].includes(o.status)?o.status:"free",d=this.status.get(o.label)??"free";if(d===r)continue;this.setStatusLabel(o.label,r,d);let c=this.labelToId.get(o.label);c&&(this.renderer?.setStatus([c],pe(r)),n.push(c));let h=this.verbFor(d,r),u=`${h}:${r}`,f=i.get(u)??{labels:[],verb:h,status:r};f.labels.push(o.label),i.set(u,f)}for(let o of i.values()){let r=this.pushActivity(o.labels,o.verb,o.status);r&&this.paintSpatialActivity(r)}i.size&&this.scheduleMonitorRefresh(),n.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 n=new Map;for(let i of new Set([...s.keys(),...this.status.keys()])){let a=s.get(i)??"free",o=this.status.get(i)??"free";if(a===o)continue;let r=this.verbFor(a,o),d=`${r}:${o}`,c=n.get(d)??{labels:[],verb:r,status:o};c.labels.push(i),n.set(d,c)}for(let i of n.values()){let a=this.pushActivity(i.labels,i.verb,i.status);a&&this.paintSpatialActivity(a)}n.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=i=>["free","held","booked","blocked"].includes(i)?i:"free",n=new Map;if(t!==void 0){let i=s(t);for(let a of this.knownLabels())n.set(a,i)}for(let[i,a]of Object.entries(e))n.set(i,s(a));this.status=n,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 n of e){this.setStatusLabel(n,t);let i=this.labelToId.get(n);i&&s.push(i)}s.length&&this.renderer?.setStatus(s,pe(t)),this.afterPaint(),this.recomputeTallies()}afterPaint(){this.keepLive&&typeof document<"u"&&document.hidden&&this.renderer?.forceDraw()}activityColor(e){return e==="held"?A.held:e==="booked"?A.booked:e==="blocked"?A.blocked:A.free}sectionsForLabels(e){let t=new Set;for(let n of e){let i=this.labelToSeat.get(n);if(!i)continue;let a=this.sectionByObject.get(i.rowId);a&&a!==w.UNGROUPED_ID&&t.add(a)}let s=[...t];return{ids:s,labels:s.map(n=>this.sectionLabelById.get(n)??n)}}pulseSeatLabels(e,t){let s=this.activityColor(t);for(let n of e.slice(0,Mt)){let i=this.labelToId.get(n);i&&this.renderer?.flashSeat(i,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 i=this.root?.querySelector('[data-ref="followstatus"]');i&&(i.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 i=this.activityColor(e.status);for(let a of t.slice(0,It))this.renderer?.flashSection(a,i);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,Mt).map(r=>this.labelToSeat.get(r)).filter(r=>!!r);if(!s.length)return;let n=s.map(r=>r.x),i=s.map(r=>r.y),a=Math.min(...n),o=Math.min(...i);this.renderer?.focusRegion({x:a-150,y:o-100,width:Math.max(...n)-a+300,height:Math.max(...i)-o+200})}locateActivity(e){let t=this.feed.find(n=>n.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 n=this.activityColor(t.status);for(let i of s.slice(0,It))this.renderer?.flashSection(i,n)}else this.pulseSeatLabels(t.labels,t.status)},280)}showLiveEvent(e){let t=this.els.liveevent;if(!t)return;let s=e.sectionLabels??[],n=s.length===1?s[0]:s.length>1?`${s.length} sections`:e.label,i=e.count===1?"seat":"seats";t.innerHTML=`<span class="slm-liveeventdot" style="background:${this.activityColor(e.status)}"></span>
1171
1241
  <span class="slm-liveeventcopy">${b(n)} \xB7 ${e.count.toLocaleString()} ${i} ${b(e.verb)}</span>
1172
- <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 n=Number.isFinite(s.bookedValue)?s.bookedValue:s.bookedRevenue;return t+(Number.isFinite(n)?n: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),n=s.bookedValue??s.revenue??{gross:0,bySection:[]},i=(n.bySection??[]).map(r=>{let c=Number.isFinite(r.bookedValue)?r.bookedValue:r.bookedRevenue;return{...r,bookedValue:c??0,bookedRevenue:c??0}}),a={...n,bySection:i},o={...s,bookedValue:a,revenue:a};if(e===this.revenueRequest){if(this.livePresence&&this.livePresence.at>=t?o={...o,presence:this.livePresence.value}:this.livePresence=null,this.liveGross&&this.liveGross.at>=t){let d={...o.bookedValue,gross:this.liveGross.value};o={...o,bookedValue:d,revenue:d}}else this.liveGross=null;this.controlRoomSnapshot=o,o.activity&&this.seedFeed(o.activity),this.rebaseServerTotals(o),this.lastSyncedAt=Date.now(),this.authoritativeGrossRevenue=o.bookedValue.gross,this.authoritativeCurrency=o.currency,this.currency=o.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?.(o)}return o}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=o=>t?Math.max(0,t.server[o]+(e[o]-t.client[o])):e[o],n=this.controlRoomSnapshot?.event?.seatTotal,i={free:s("free"),held:s("held"),booked:s("booked"),blocked:s("blocked"),total:Number.isFinite(n)?n:this.unitTotal(),capacityPct:0,sellThroughPct:0,bookedValue:this.authoritativeGrossRevenue,grossRevenue:this.authoritativeGrossRevenue,bookedValueStatus:this.revenueStatus,revenueStatus:this.revenueStatus,currency:this.currency};i.capacityPct=i.total?Math.round(i.booked/i.total*100):0;let a=i.total-i.blocked;return i.sellThroughPct=a>0?Math.round(i.booked/a*100):0,i}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,n=Date.now()){let i=e[0];if(!i)return null;let a=this.sectionsForLabels(e),o={id:`${i}:${n}:${Math.random().toString(36).slice(2,6)}`,at:n,label:i,labels:[...e],count:e.length,verb:t,status:s,sectionIds:a.ids,sectionLabels:a.labels};return this.controlRoomSnapshot?.activity||this.feed.unshift(o),this.feed.length>Ee&&(this.feed.length=Ee),this.mode==="view"&&this.paintFeed(),this.showLiveEvent(o),this.opts.onActivity?.(o),o}seedFeed(e){this.controlRoomSnapshot?.activity&&(this.feed=this.feed.filter(n=>n.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 n of e){if(this.feed.some(r=>r.id===`log:${n.id}`))continue;let i=n.labels[0];if(!i)continue;let a=this.sectionsForLabels(n.labels),o={id:`log:${n.id}`,at:n.at,label:i,labels:[...n.labels],count:n.labels.length,verb:t[n.action]??n.action,status:s[n.action]??"free",sectionIds:a.ids,sectionLabels:a.labels};this.feed.push(o),this.opts.onActivity?.(o)}this.feed.sort((n,i)=>i.at-n.at),this.feed.length>Ee&&(this.feed.length=Ee),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,n=t==="free"||s||this.selectableObjectLabels.has(e.label);if(!this.opts.isObjectSelectable)return n;try{return this.opts.isObjectSelectable(e,n)===!0}catch(i){return this.opts.onError?.(i),!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[n,i]of t)this.lastSelectionLabels.has(n)||this.opts.onObjectSelected?.(i);for(let n of this.lastSelectionLabels)if(!t.has(n)){let i=this.labelToSeat.get(n);i&&this.opts.onObjectDeselected?.(i)}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=`
1242
+ <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 n=Number.isFinite(s.bookedValue)?s.bookedValue:s.bookedRevenue;return t+(Number.isFinite(n)?n: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),n=s.bookedValue??s.revenue??{gross:0,bySection:[]},i=(n.bySection??[]).map(r=>{let d=Number.isFinite(r.bookedValue)?r.bookedValue:r.bookedRevenue;return{...r,bookedValue:d??0,bookedRevenue:d??0}}),a={...n,bySection:i},o={...s,bookedValue:a,revenue:a};if(e===this.revenueRequest){if(this.livePresence&&this.livePresence.at>=t?o={...o,presence:this.livePresence.value}:this.livePresence=null,this.liveGross&&this.liveGross.at>=t){let c={...o.bookedValue,gross:this.liveGross.value};o={...o,bookedValue:c,revenue:c}}else this.liveGross=null;this.controlRoomSnapshot=o,o.activity&&this.seedFeed(o.activity),this.rebaseServerTotals(o),this.lastSyncedAt=Date.now(),this.authoritativeGrossRevenue=o.bookedValue.gross,this.authoritativeCurrency=o.currency,this.currency=o.currency,this.revenueStatus="current",this.recomputeTallies(),this.applyHeatOverlay(),this.paintMonitorInsights(),this.seatHistoryPanel?.refresh();let r=this.getSelection().slice(-1)[0],d=this.els.rail?.querySelector("[data-seat-status]");r&&d&&(d.textContent=this.status.get(r.label)??"free"),this.opts.onControlRoom?.(o)}return o}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=o=>t?Math.max(0,t.server[o]+(e[o]-t.client[o])):e[o],n=this.controlRoomSnapshot?.event?.seatTotal,i={free:s("free"),held:s("held"),booked:s("booked"),blocked:s("blocked"),total:Number.isFinite(n)?n:this.unitTotal(),capacityPct:0,sellThroughPct:0,bookedValue:this.authoritativeGrossRevenue,grossRevenue:this.authoritativeGrossRevenue,bookedValueStatus:this.revenueStatus,revenueStatus:this.revenueStatus,currency:this.currency};i.capacityPct=i.total?Math.round(i.booked/i.total*100):0;let a=i.total-i.blocked;return i.sellThroughPct=a>0?Math.round(i.booked/a*100):0,i}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,n=Date.now()){let i=e[0];if(!i)return null;let a=this.sectionsForLabels(e),o={id:`${i}:${n}:${Math.random().toString(36).slice(2,6)}`,at:n,label:i,labels:[...e],count:e.length,verb:t,status:s,sectionIds:a.ids,sectionLabels:a.labels};return this.controlRoomSnapshot?.activity||this.feed.unshift(o),this.feed.length>Me&&(this.feed.length=Me),this.mode==="view"&&this.paintFeed(),this.showLiveEvent(o),this.opts.onActivity?.(o),o}seedFeed(e){this.controlRoomSnapshot?.activity&&(this.feed=this.feed.filter(n=>n.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 n of e){if(this.feed.some(r=>r.id===`log:${n.id}`))continue;let i=n.labels[0];if(!i)continue;let a=this.sectionsForLabels(n.labels),o={id:`log:${n.id}`,at:n.at,label:i,labels:[...n.labels],count:n.labels.length,verb:t[n.action]??n.action,status:s[n.action]??"free",sectionIds:a.ids,sectionLabels:a.labels};this.feed.push(o),this.opts.onActivity?.(o)}this.feed.sort((n,i)=>i.at-n.at),this.feed.length>Me&&(this.feed.length=Me),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,n=t==="free"||s||this.selectableObjectLabels.has(e.label);if(!this.opts.isObjectSelectable)return n;try{return this.opts.isObjectSelectable(e,n)===!0}catch(i){return this.opts.onError?.(i),!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[n,i]of t)this.lastSelectionLabels.has(n)||this.opts.onObjectSelected?.(i);for(let n of this.lastSelectionLabels)if(!t.has(n)){let i=this.labelToSeat.get(n);i&&this.opts.onObjectDeselected?.(i)}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=`
1173
1243
  <div class="slm-bar">
1174
1244
  <div class="slm-modes" data-ref="modes" role="tablist" aria-label="Control room tools">
1175
- ${Rt.map(n=>`<div class="slm-modegroup" data-group="${n.key}" role="presentation" hidden>
1245
+ ${Ht.map(n=>`<div class="slm-modegroup" data-group="${n.key}" role="presentation" hidden>
1176
1246
  <span class="slm-modegroup-label" aria-hidden="true">${b(n.label)}</span>
1177
1247
  ${n.tools.map(i=>`<button class="slm-mode" role="tab" data-mode="${i.mode}"
1178
1248
  title="${b(i.title)} (${i.shortcut})" aria-keyshortcuts="${i.shortcut}" hidden>${b(i.label)}</button>`).join("")}
@@ -1193,8 +1263,10 @@
1193
1263
  <div class="slm-body">
1194
1264
  <div class="slm-map">
1195
1265
  <div class="slm-map-host" data-ref="maphost"></div>
1196
- <div class="slm-zoomhint" data-ref="zoomhint">Zoom in to marquee-select</div>
1197
- <div class="slm-liveevent" data-ref="liveevent" role="status" aria-live="polite"></div>
1266
+ <div class="slm-lane" data-ref="lane">
1267
+ <div class="slm-zoomhint" data-ref="zoomhint">Zoom in to select seats</div>
1268
+ <div class="slm-liveevent" data-ref="liveevent" role="status" aria-live="polite"></div>
1269
+ </div>
1198
1270
  <div class="slm-heat-status" data-ref="heatstatus" role="status" hidden></div>
1199
1271
  <div class="slm-follow-status" data-ref="followstatus" role="status" hidden></div>
1200
1272
  <div class="slm-hud"><button class="slm-hud-chip" data-ref="zfit">Zoom to fit</button></div>
@@ -1202,10 +1274,10 @@
1202
1274
  <aside class="slm-rail"><div class="slm-railscroll" data-ref="rail"></div></aside>
1203
1275
  </div>
1204
1276
  <div class="slm-toast" data-ref="toast"></div>
1205
- `,this.host.appendChild(e),this.root=e,this.selectObserver=new MutationObserver(()=>{let n=e.querySelector(".slm-rail");n&&ne(n)});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=n=>e.querySelector(`[data-ref="${n}"]`);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"),zoomhint:s("zoomhint"),liveevent:s("liveevent"),rail:s("rail"),toast:s("toast"),zfit:s("zfit")},this.els.modes.querySelectorAll("[data-mode]").forEach(n=>n.addEventListener("click",()=>this.setMode(n.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 oe({root:e,map:this.mapHost,setMoving:n=>{this.movingMap=n,this.updateRendererInteraction()},pauseFollow:()=>{this.followLive&&this.setFollowLive(!1)},zoomIn:()=>this.renderer?.zoomIn(),zoomOut:()=>this.renderer?.zoomOut(),targets:n=>this.navigationTargets(n)}),this.navigation.update(this.isBulkSelectMode(),this.mode==="view")}navigationTargets(e){let t=e.toLocaleLowerCase(),s=[];for(let i of this.sectionOptions)if(i.label.toLocaleLowerCase().includes(t)&&s.push({label:i.label,detail:"Section",locate:()=>this.locateSection(i.id)}),s.length>=20)return s;let n=new Map;for(let i of this.labelToSeat.values()){let a=n.get(i.rowId)??{minX:i.x,minY:i.y,maxX:i.x,maxY:i.y};a.minX=Math.min(a.minX,i.x),a.minY=Math.min(a.minY,i.y),a.maxX=Math.max(a.maxX,i.x),a.maxY=Math.max(a.maxY,i.y),n.set(i.rowId,a)}for(let i of this.doc?(0,S.floorsOf)(this.doc).flatMap(a=>a.objects):[]){if(i.type!=="row"||!(i.displayLabel??i.label).toLocaleLowerCase().includes(t))continue;let a=n.get(i.id);if(!a)continue;let{minX:o,minY:r,maxX:c,maxY:d}=a;if(s.push({label:i.displayLabel??i.label,detail:"Row",locate:()=>{let h=this.sectionByObject.get(i.id);h&&this.renderer?.focusSection(h),this.renderer?.focusRegion({x:o-30,y:r-30,width:c-o+60,height:d-r+60},{minScale:1.2,animate:!1})}}),s.length>=20)return s}for(let i of this.labelToSeat.values())if(i.label.toLocaleLowerCase().includes(t)&&(s.push({label:i.label,detail:"Seat",locate:()=>{let a=this.sectionByObject.get(i.rowId);a&&this.renderer?.focusSection(a),this.renderer?.focusRegion({x:i.x-180,y:i.y-120,width:360,height:240},{animate:!1,minScale:1.5}),this.renderer?.flashSeat(i.id,this.activityColor(this.status.get(i.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(d=>d.id)),s=this.filterableSections().filter(d=>!t.has(d.id)).map(d=>d.id);this.renderer.clearSectionFocus(),this.renderer.setClosedSections(null),this.renderer.setDimmedSections(s);let n=e.flatMap(d=>d.seatLabels).map(d=>this.labelToSeat.get(d)).filter(d=>!!d&&Number.isFinite(d.x)&&Number.isFinite(d.y));if(!n.length){this.renderer.focusRegion(e[0].id);return}let i=Math.min(...n.map(d=>d.x)),a=Math.min(...n.map(d=>d.y)),o=Math.max(...n.map(d=>d.x)),r=Math.max(...n.map(d=>d.y)),c=Math.max(40,Math.max(o-i,r-a)*.08);this.renderer.focusRegion({x:i-c,y:a-c,width:Math.max(1,o-i)+c*2,height:Math.max(1,r-a)+c*2})}buildSectionOptions(){if(this.doc)try{let e=(0,S.computeSections)(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:S.UNGROUPED_ID,label:e.ungrouped.label}),this.sectionLabelById.set(S.UNGROUPED_ID,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?(0,S.floorsOf)(this.doc):[]).flatMap(e=>e.objects).filter(e=>e.type==="table")}paintModeTabs(){let e=[];this.els.modes?.querySelectorAll(".slm-modegroup").forEach(s=>{let n=[];s.querySelectorAll("[data-mode]").forEach(i=>{let a=i.dataset.mode,o=this.toolAvailable(a);if(i.hidden=!o,!o)return;n.push({mode:a,label:i.textContent??a});let r=a===this.mode;i.classList.toggle("on",r),i.setAttribute("aria-selected",String(r)),i.tabIndex=r?0:-1}),s.hidden=n.length===0,n.length&&e.push({label:s.querySelector(".slm-modegroup-label")?.textContent??"",tools:n})});let t=this.els.tools;t&&(t.innerHTML=e.map(s=>`<optgroup label="${b(s.label)}">${s.tools.map(n=>`<option value="${n.mode}"${n.mode===this.mode?" selected":""}>${b(n.label)}</option>`).join("")}</optgroup>`).join(""),t.value=this.mode),this.root?.classList.toggle("block-mode",this.mode==="block")}railHeader(e,t,s){let n=t==="read"?"Read-only":t==="event"?"This event only":"Your app";return`<div class="slm-railhead"><p class="slm-eyebrow">${b(e)}</p><span class="slm-scope ${t}">${n}</span></div>
1206
- <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 i=this.controlRoomSnapshot?.velocity.bySection.some(a=>a.netBooked>0);e.textContent=this.controlRoomSnapshot?i?`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 n=this.controlRoomSnapshot?.velocity.bySection.some(i=>i.netBooked>0);s.textContent=n?"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 n=t>0?"+":"\u2212",i=Math.abs(t);return e==="booked-value"?`${n}${he(i,s)}`:e==="booked-pct"?`${n}${i.toLocaleString()}pt`:`${n}${i.toLocaleString()}`}paintKpis(e){if(!this.els.kpis)return;let t=e.bookedValueStatus==="current"?he(e.bookedValue,e.currency):"\u2014",s=this.presenceCounts(),n=[{key:"booked-inventory",raw:e.booked,n:e.booked.toLocaleString(),l:"Booked inventory",dot:"#22a06b",title:"Inventory units booked"},{key:"held-seats",raw:e.held,n:e.held.toLocaleString(),l:"Held inventory",dot:"#f4b740",title:"Inventory currently held"},{key:"free-seats",raw:e.free,n:e.free.toLocaleString(),l:"Available",dot:"#6e7bff",title:"Inventory available to book"},{key:"blocked",raw:e.blocked,n:e.blocked.toLocaleString(),l:"Blocked",dot:"#8b94ac",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"}],i=!1;this.els.kpis.innerHTML=n.map(a=>{let o=this.lastKpiValues.get(a.key),r=a.raw!=null&&o!=null&&a.raw!==o,c=r?a.raw-o:0;r&&(i=!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="${b(a.title)}">
1277
+ `,this.host.appendChild(e),this.root=e,this.selectObserver=new MutationObserver(()=>{let n=e.querySelector(".slm-rail");n&&ie(n)});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=n=>e.querySelector(`[data-ref="${n}"]`);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(n=>n.addEventListener("click",()=>this.setMode(n.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 le({root:e,map:this.mapHost,setMoving:n=>{this.movingMap=n,this.updateRendererInteraction()},pauseFollow:()=>{this.followLive&&this.setFollowLive(!1)},clearSelection:()=>this.clearSelection(),zoomIn:()=>this.renderer?.zoomIn(),zoomOut:()=>this.renderer?.zoomOut(),targets:n=>this.navigationTargets(n)}),this.navigation.update(this.isBulkSelectMode(),this.mode==="view")}navigationTargets(e){let t=e.toLocaleLowerCase(),s=[];for(let i of this.sectionOptions)if(i.label.toLocaleLowerCase().includes(t)&&s.push({label:i.label,detail:"Section",locate:()=>this.locateSection(i.id)}),s.length>=20)return s;let n=new Map;for(let i of this.labelToSeat.values()){let a=n.get(i.rowId)??{minX:i.x,minY:i.y,maxX:i.x,maxY:i.y};a.minX=Math.min(a.minX,i.x),a.minY=Math.min(a.minY,i.y),a.maxX=Math.max(a.maxX,i.x),a.maxY=Math.max(a.maxY,i.y),n.set(i.rowId,a)}for(let i of this.doc?(0,w.floorsOf)(this.doc).flatMap(a=>a.objects):[]){if(i.type!=="row"||!(i.displayLabel??i.label).toLocaleLowerCase().includes(t))continue;let a=n.get(i.id);if(!a)continue;let{minX:o,minY:r,maxX:d,maxY:c}=a;if(s.push({label:i.displayLabel??i.label,detail:"Row",locate:()=>{let h=this.sectionByObject.get(i.id);h&&this.renderer?.focusSection(h),this.renderer?.focusRegion({x:o-30,y:r-30,width:d-o+60,height:c-r+60},{minScale:1.2,animate:!1})}}),s.length>=20)return s}for(let i of this.labelToSeat.values())if(i.label.toLocaleLowerCase().includes(t)&&(s.push({label:i.label,detail:"Seat",locate:()=>{let a=this.sectionByObject.get(i.rowId);a&&this.renderer?.focusSection(a),this.renderer?.focusRegion({x:i.x-180,y:i.y-120,width:360,height:240},{animate:!1,minScale:1.5}),this.renderer?.flashSeat(i.id,this.activityColor(this.status.get(i.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(c=>c.id)),s=this.filterableSections().filter(c=>!t.has(c.id)).map(c=>c.id);this.renderer.clearSectionFocus(),this.renderer.setClosedSections(null),this.renderer.setDimmedSections(s);let n=e.flatMap(c=>c.seatLabels).map(c=>this.labelToSeat.get(c)).filter(c=>!!c&&Number.isFinite(c.x)&&Number.isFinite(c.y));if(!n.length){this.renderer.focusRegion(e[0].id);return}let i=Math.min(...n.map(c=>c.x)),a=Math.min(...n.map(c=>c.y)),o=Math.max(...n.map(c=>c.x)),r=Math.max(...n.map(c=>c.y)),d=Math.max(40,Math.max(o-i,r-a)*.08);this.renderer.focusRegion({x:i-d,y:a-d,width:Math.max(1,o-i)+d*2,height:Math.max(1,r-a)+d*2})}buildSectionOptions(){if(this.doc)try{let e=(0,w.computeSections)(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:w.UNGROUPED_ID,label:e.ungrouped.label}),this.sectionLabelById.set(w.UNGROUPED_ID,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?(0,w.floorsOf)(this.doc):[]).flatMap(e=>e.objects).filter(e=>e.type==="table")}paintModeTabs(){let e=[];this.els.modes?.querySelectorAll(".slm-modegroup").forEach(s=>{let n=[];s.querySelectorAll("[data-mode]").forEach(i=>{let a=i.dataset.mode,o=this.toolAvailable(a);if(i.hidden=!o,!o)return;n.push({mode:a,label:i.textContent??a});let r=a===this.mode;i.classList.toggle("on",r),i.setAttribute("aria-selected",String(r)),i.tabIndex=r?0:-1}),s.hidden=n.length===0,n.length&&e.push({label:s.querySelector(".slm-modegroup-label")?.textContent??"",tools:n})});let t=this.els.tools;t&&(t.innerHTML=e.map(s=>`<optgroup label="${b(s.label)}">${s.tools.map(n=>`<option value="${n.mode}"${n.mode===this.mode?" selected":""}>${b(n.label)}</option>`).join("")}</optgroup>`).join(""),t.value=this.mode),this.root?.classList.toggle("block-mode",this.mode==="block")}railHeader(e,t,s){let n=t==="read"?"Read-only":t==="event"?"This event only":"Your app";return`<div class="slm-railhead"><p class="slm-eyebrow">${b(e)}</p><span class="slm-scope ${t}">${n}</span></div>
1278
+ <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 i=this.controlRoomSnapshot?.velocity.bySection.some(a=>a.netBooked>0);e.textContent=this.controlRoomSnapshot?i?`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 n=this.controlRoomSnapshot?.velocity.bySection.some(i=>i.netBooked>0);s.textContent=n?"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 n=t>0?"+":"\u2212",i=Math.abs(t);return e==="booked-value"?`${n}${me(i,s)}`:e==="booked-pct"?`${n}${i.toLocaleString()}pt`:`${n}${i.toLocaleString()}`}paintKpis(e){if(!this.els.kpis)return;let t=e.bookedValueStatus==="current"?me(e.bookedValue,e.currency):"\u2014",s=this.presenceCounts(),n=[{key:"booked-inventory",raw:e.booked,n:e.booked.toLocaleString(),l:"Booked inventory",dot:A.booked,title:"Inventory units booked"},{key:"held-seats",raw:e.held,n:e.held.toLocaleString(),l:"Held inventory",dot:A.held,title:"Inventory currently held"},{key:"free-seats",raw:e.free,n:e.free.toLocaleString(),l:"Available",dot:A.free,title:"Inventory available to book"},{key:"blocked",raw:e.blocked,n:e.blocked.toLocaleString(),l:"Blocked",dot:A.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"}],i=!1;this.els.kpis.innerHTML=n.map(a=>{let o=this.lastKpiValues.get(a.key),r=a.raw!=null&&o!=null&&a.raw!==o,d=r?a.raw-o:0;r&&(i=!0,this.activeKpiDeltas.set(a.key,{text:this.formatKpiDelta(a.key,d,e.currency),down:d<0})),a.raw!=null&&this.lastKpiValues.set(a.key,a.raw);let c=this.activeKpiDeltas.get(a.key);return`<div class="slm-kpi${c?" changed":""}" data-kpi="${a.key}" title="${b(a.title)}">
1207
1279
  <b>${a.dot?`<span class="dot" style="background:${a.dot}"></span>`:""}${a.n}</b><span>${a.l}</span>
1208
- ${d?`<span class="slm-kpidelta${d.down?" down":""}">${d.text}</span>`:""}
1280
+ ${c?`<span class="slm-kpidelta${c.down?" down":""}">${c.text}</span>`:""}
1209
1281
  </div>`}).join(""),i&&(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=`
1210
1282
  <div class="slm-monitor-head"><h2>Live activity</h2><span data-ref="presence" class="slm-monitor-connection"></span></div>
1211
1283
  <div class="slm-monitor-tabs" role="tablist" aria-label="Monitor details">
@@ -1225,8 +1297,8 @@
1225
1297
  </div>
1226
1298
  <div class="slm-sectionlist" data-ref="sections"></div>
1227
1299
  </div>
1228
- `,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 ae(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 n=this.root?.classList.contains("live"),i=this.lastSyncedAt?ht(this.lastSyncedAt,Date.now()):"waiting";this.els.presence.textContent=n?"\u25CF Live":"Reconnecting",this.els.presence.title=`Last data received: ${i}`}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(n=>[n.sectionId,n])),s=[...e.bookedValue.bySection].sort((n,i)=>{let a=t.get(n.sectionId)?.netBooked??0;return(t.get(i.sectionId)?.netBooked??0)-a||i.bookedValue-n.bookedValue});this.els.sections.innerHTML=s.length?s.map(n=>{let i=t.get(n.sectionId),a=i?.netBooked??0,o=`${a>0?"+":""}${a}`,r=i?.trend==="rising"||i?.trend==="cooling"?i.trend:"steady";return`<button type="button" class="slm-sectionrow" data-section-focus="${b(n.sectionId)}" title="Focus ${b(n.sectionLabel)} on the map">
1229
- <span class="slm-sectiontop"><span>${b(n.sectionLabel)}</span><span title="Configured value of currently booked inventory">${he(n.bookedValue,e.currency)}</span></span>
1300
+ `,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 oe(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 n=this.root?.classList.contains("live"),i=this.lastSyncedAt?mt(this.lastSyncedAt,Date.now()):"waiting";this.els.presence.textContent=n?"\u25CF Live":"Reconnecting",this.els.presence.title=`Last data received: ${i}`}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(n=>[n.sectionId,n])),s=[...e.bookedValue.bySection].sort((n,i)=>{let a=t.get(n.sectionId)?.netBooked??0;return(t.get(i.sectionId)?.netBooked??0)-a||i.bookedValue-n.bookedValue});this.els.sections.innerHTML=s.length?s.map(n=>{let i=t.get(n.sectionId),a=i?.netBooked??0,o=`${a>0?"+":""}${a}`,r=i?.trend==="rising"||i?.trend==="cooling"?i.trend:"steady";return`<button type="button" class="slm-sectionrow" data-section-focus="${b(n.sectionId)}" title="Focus ${b(n.sectionLabel)} on the map">
1301
+ <span class="slm-sectiontop"><span>${b(n.sectionLabel)}</span><span title="Configured value of currently booked inventory">${me(n.bookedValue,e.currency)}</span></span>
1230
1302
  <span class="slm-sectionmeta"><span>${n.booked.toLocaleString()}/${n.total.toLocaleString()} booked \xB7 ${o} net in ${e.velocity.windowMinutes}m</span><span class="slm-trend ${r}">${r}</span><span class="slm-sectionlocate">Locate</span></span>
1231
1303
  </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})),n=Math.max(0,...s.map(a=>a.rate)),i={};for(let a of s)i[a.sectionId]=n>0?Math.sqrt(a.rate/n):0;this.renderer?.setSectionHeat(i)}renderSelectRail(){let e=this.doc?.categories??[],t=this.opts.numberOfPlacesToSelect,s=this.selectionCap();this.els.rail.innerHTML=`
1232
1304
  ${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.")}
@@ -1243,7 +1315,7 @@
1243
1315
  <span>${b(n.label??n.key)}</span>
1244
1316
  <span class="slm-chipcount" data-cat-count>0</span>
1245
1317
  <span class="slm-chipcheck" aria-hidden="true">\u2713</span>
1246
- </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(n=>{n.addEventListener("click",()=>{let i=n.dataset.selectCat,a=[...this.labelToSeat.values()].filter(r=>r.categoryKey===i&&this.canSelectObject(r)),o=new Set(this.selectionLabels());a.length>0&&a.every(r=>o.has(r.label))?this.deselectCategories([i]):this.selectCategories([i])})}),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 n=new Set(e.map(i=>i.label));this.els.rail?.querySelectorAll("[data-select-cat]").forEach(i=>{let a=i.dataset.selectCat,o=[...this.labelToSeat.values()].filter(h=>h.categoryKey===a&&this.canSelectObject(h)),r=o.filter(h=>n.has(h.label)).length,c=o.length>0&&r===o.length;i.classList.toggle("on",c),i.setAttribute("aria-pressed",String(c));let d=i.querySelector("[data-cat-count]");d&&(d.textContent=r?`${r}/${o.length}`:o.length.toLocaleString()),i.disabled=o.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=`
1318
+ </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(n=>{n.addEventListener("click",()=>{let i=n.dataset.selectCat,a=[...this.labelToSeat.values()].filter(r=>r.categoryKey===i&&this.canSelectObject(r)),o=new Set(this.selectionLabels());a.length>0&&a.every(r=>o.has(r.label))?this.deselectCategories([i]):this.selectCategories([i])})}),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 n=new Set(e.map(i=>i.label));this.els.rail?.querySelectorAll("[data-select-cat]").forEach(i=>{let a=i.dataset.selectCat,o=[...this.labelToSeat.values()].filter(h=>h.categoryKey===a&&this.canSelectObject(h)),r=o.filter(h=>n.has(h.label)).length,d=o.length>0&&r===o.length;i.classList.toggle("on",d),i.setAttribute("aria-pressed",String(d));let c=i.querySelector("[data-cat-count]");c&&(c.textContent=r?`${r}/${o.length}`:o.length.toLocaleString()),i.disabled=o.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=`
1247
1319
  ${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.")}
1248
1320
  ${e.size?`<div class="slm-sectionlist">${[...e].map(([t,s])=>{let n=t===this.filteredSectionLabel,i=s.reduce((a,o)=>a+o.seatCount,0);return`<button type="button" class="slm-sectionrow${n?" on":""}" data-filter-section="${b(t)}" aria-pressed="${n}">
1249
1321
  <span class="slm-sectiontop"><span>${b(t)}</span><span>${i.toLocaleString()}</span></span>
@@ -1275,23 +1347,23 @@
1275
1347
  <span class="dot" style="background:${b(s.color??"#6e7bff")}"></span>
1276
1348
  <span class="slm-categorycopy"><b>${b(s.label??s.key)}</b><small data-cat-current>0 seats now</small></span>
1277
1349
  <span class="slm-categoryact" data-cat-action>Move here</span>
1278
- </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 n=s.dataset.pickCategory,i=this.categorySeats(n),a=new Set(this.selectionLabels());i.length>0&&i.every(o=>a.has(o.label))?this.deselectCategories([n]):this.selectCategories([n])})}),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 a of e)s.set(a.categoryKey,(s.get(a.categoryKey)??0)+1);let n=a=>this.doc?.categories.find(o=>o.key===a)?.label??a;this.els.categorymeta&&(this.els.categorymeta.textContent=t===0?"selected":`${t===1?"seat":"seats"} selected \xB7 ${[...s].map(([a,o])=>`${o.toLocaleString()} ${n(a)}`).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 i=new Set(e.map(a=>a.label));this.els.rail?.querySelectorAll("[data-pick-category]").forEach(a=>{let o=a.dataset.pickCategory,r=this.categorySeats(o),c=r.filter(u=>i.has(u.label)).length,d=r.length>0&&c===r.length;a.classList.toggle("on",d),a.classList.toggle("partial",c>0&&!d),a.setAttribute("aria-pressed",String(d));let h=a.querySelector("[data-cat-count]");h&&(h.textContent=c?`${c.toLocaleString()}/${r.length.toLocaleString()}`:r.length.toLocaleString()),a.disabled=r.length===0}),this.els.rail?.querySelectorAll("[data-assign-category]").forEach(a=>{let o=a.dataset.assignCategory,r=[...this.labelToSeat.values()].filter(f=>f.categoryKey===o).length,c=s.get(o)??0,d=t>0&&c===t;a.disabled=t===0||d,a.classList.toggle("current",d);let h=a.querySelector("[data-cat-current]");h&&(h.textContent=`${r.toLocaleString()} ${r===1?"seat":"seats"} now`);let u=a.querySelector("[data-cat-action]");u&&(u.textContent=t===0?"Move here":d?"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=`
1350
+ </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 n=s.dataset.pickCategory,i=this.categorySeats(n),a=new Set(this.selectionLabels());i.length>0&&i.every(o=>a.has(o.label))?this.deselectCategories([n]):this.selectCategories([n])})}),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 a of e)s.set(a.categoryKey,(s.get(a.categoryKey)??0)+1);let n=a=>this.doc?.categories.find(o=>o.key===a)?.label??a;this.els.categorymeta&&(this.els.categorymeta.textContent=t===0?"selected":`${t===1?"seat":"seats"} selected \xB7 ${[...s].map(([a,o])=>`${o.toLocaleString()} ${n(a)}`).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 i=new Set(e.map(a=>a.label));this.els.rail?.querySelectorAll("[data-pick-category]").forEach(a=>{let o=a.dataset.pickCategory,r=this.categorySeats(o),d=r.filter(u=>i.has(u.label)).length,c=r.length>0&&d===r.length;a.classList.toggle("on",c),a.classList.toggle("partial",d>0&&!c),a.setAttribute("aria-pressed",String(c));let h=a.querySelector("[data-cat-count]");h&&(h.textContent=d?`${d.toLocaleString()}/${r.length.toLocaleString()}`:r.length.toLocaleString()),a.disabled=r.length===0}),this.els.rail?.querySelectorAll("[data-assign-category]").forEach(a=>{let o=a.dataset.assignCategory,r=[...this.labelToSeat.values()].filter(f=>f.categoryKey===o).length,d=s.get(o)??0,c=t>0&&d===t;a.disabled=t===0||c,a.classList.toggle("current",c);let h=a.querySelector("[data-cat-current]");h&&(h.textContent=`${r.toLocaleString()} ${r===1?"seat":"seats"} now`);let u=a.querySelector("[data-cat-action]");u&&(u.textContent=t===0?"Move here":c?"Already here":`Move ${(t-d).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=`
1279
1351
  ${this.railHeader("Tables","event",t)}
1280
1352
  <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=`
1281
1353
  ${this.railHeader("Tables","event",t)}
1282
- <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",n=h=>{let u=0,f=0,v=0;for(let[m,k]of this.labelToSeat){if(k.rowId!==h.id)continue;let R=this.status.get(m);R==="held"?u++:R==="booked"?f++:R==="blocked"&&v++}let g=[f&&`${f} booked`,u&&`${u} held`,v&&`${v} blocked`].filter(Boolean);return g.length?g.join(" \xB7 "):null},i=e.map(h=>({table:h,current:s(h),locked:n(h)})),a=i.filter(h=>h.current==="individual").length,o=i.filter(h=>h.current==="whole").length,r=i.length-a-o,c=[`${a.toLocaleString()} per chair`,`${o.toLocaleString()} whole table`,r?`${r.toLocaleString()} flexible group`:""].filter(Boolean).join(" \xB7 "),d=this.tableBookingSaving;this.els.rail.innerHTML=`
1354
+ <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",n=h=>{let u=0,f=0,v=0;for(let[m,y]of this.labelToSeat){if(y.rowId!==h.id)continue;let H=this.status.get(m);H==="held"?u++:H==="booked"?f++:H==="blocked"&&v++}let g=[f&&`${f} booked`,u&&`${u} held`,v&&`${v} blocked`].filter(Boolean);return g.length?g.join(" \xB7 "):null},i=e.map(h=>({table:h,current:s(h),locked:n(h)})),a=i.filter(h=>h.current==="individual").length,o=i.filter(h=>h.current==="whole").length,r=i.length-a-o,d=[`${a.toLocaleString()} per chair`,`${o.toLocaleString()} whole table`,r?`${r.toLocaleString()} flexible group`:""].filter(Boolean).join(" \xB7 "),c=this.tableBookingSaving;this.els.rail.innerHTML=`
1283
1355
  ${this.railHeader("Tables","event",t)}
1284
- <div class="slm-tablesummary"><b>${i.length.toLocaleString()} ${i.length===1?"table":"tables"}</b><span>${b(c)}</span></div>
1356
+ <div class="slm-tablesummary"><b>${i.length.toLocaleString()} ${i.length===1?"table":"tables"}</b><span>${b(d)}</span></div>
1285
1357
  <p class="slm-eyebrow" style="margin-top:12px">Set every table at once</p>
1286
1358
  <div class="slm-row">
1287
- <button class="slm-btn ghost" data-table-all="individual"${d?" disabled":""} title="Sell every chair on its own">All per chair</button>
1288
- <button class="slm-btn ghost" data-table-all="whole"${d?" disabled":""} title="Sell every table as one booking">All whole table</button>
1359
+ <button class="slm-btn ghost" data-table-all="individual"${c?" disabled":""} title="Sell every chair on its own">All per chair</button>
1360
+ <button class="slm-btn ghost" data-table-all="whole"${c?" disabled":""} title="Sell every table as one booking">All whole table</button>
1289
1361
  </div>
1290
1362
  <p class="slm-eyebrow" style="margin-top:12px">Or one table at a time</p>
1291
1363
  <div class="slm-tablelist">${i.map(({table:h,current:u,locked:f})=>`<div class="slm-tablerow${f?" locked":""}">
1292
1364
  <span class="slm-tablecopy"><b>${b(h.displayLabel??h.label)}</b><small>${h.seatCount.toLocaleString()} chairs${f?` \xB7 <span class="slm-tablelock">Locked: ${b(f)}</span>`:""}</small></span>
1293
1365
  <select class="slm-select" data-table-mode="${b(h.id)}" aria-label="Booking mode for ${b(h.displayLabel??h.label)}"
1294
- ${d||f?"disabled":""} ${f?`title="Release the ${b(f)} chairs before changing how this table sells"`:""}>
1366
+ ${c||f?"disabled":""} ${f?`title="Release the ${b(f)} chairs before changing how this table sells"`:""}>
1295
1367
  <option value="individual"${u==="individual"?" selected":""}>Per chair</option>
1296
1368
  <option value="whole"${u==="whole"?" selected":""}>Whole table</option>
1297
1369
  ${u==="variable"?'<option value="variable" selected>Flexible group</option>':""}
@@ -1299,14 +1371,14 @@
1299
1371
  </div>`).join("")}</div>
1300
1372
  <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(i.filter(u=>!u.locked).map(u=>u.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=`
1301
1373
  ${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.")}
1302
- <div class="slm-empty">Select a seat on the map.</div>`;return}let s=this.status.get(t.label)??"free",n={free:"Free",held:"Held",booked:"Booked",blocked:"Blocked"},i=this.sectionByObject.get(t.rowId)??S.UNGROUPED_ID,a=this.sectionLabelById.get(i)??"Other seats",o=this.doc?.categories.find(c=>c.key===t.categoryKey);this.els.rail.innerHTML=`
1374
+ <div class="slm-empty">Select a seat on the map.</div>`;return}let s=this.status.get(t.label)??"free",n={free:"Free",held:"Held",booked:"Booked",blocked:"Blocked"},i=this.sectionByObject.get(t.rowId)??w.UNGROUPED_ID,a=this.sectionLabelById.get(i)??"Other seats",o=this.doc?.categories.find(d=>d.key===t.categoryKey);this.els.rail.innerHTML=`
1303
1375
  <div class="slm-seat-heading"><h2>${b(t.label)}</h2><span data-seat-status>${n[s]}</span></div>
1304
1376
  <p class="slm-note">${b(a)} \xB7 ${b(o?.label??t.categoryKey)}</p>
1305
- <div data-ref="seat-history"></div>`;let r=this.els.rail.querySelector('[data-ref="seat-history"]');this.seatHistoryPanel=new ie(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(Oe(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 y&&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(n=>typeof n=="string")),s=!0),Array.isArray(t)&&(this.effectiveClosed=new Set(t.filter(n=>typeof n=="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}=pe(this.sectionRowsInput());if(!e.length){this.els.rail.innerHTML=`
1377
+ <div data-ref="seat-history"></div>`;let r=this.els.rail.querySelector('[data-ref="seat-history"]');this.seatHistoryPanel=new ae(r,(d,c)=>this.withAuthRetry(()=>this.api.seatHistory(this.key,t.label,d,c)))}async refreshAvailability(){try{let e=await this.withAuthRetry(()=>this.api.availability(this.key));this.availabilityRules=e.rules??{},this.effectiveClosed=new Set(Fe(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 x&&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(n=>typeof n=="string")),s=!0),Array.isArray(t)&&(this.effectiveClosed=new Set(t.filter(n=>typeof n=="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}=ue(this.sectionRowsInput());if(!e.length){this.els.rail.innerHTML=`
1306
1378
  ${this.railHeader("Sections","event","Draw sections or zones in the designer to schedule availability per area. This chart has none yet.")}
1307
1379
  <div class="slm-empty">No sections on this chart.</div>`;return}let n=[];t&&n.push(`${t} hidden`),s&&n.push(`${s} closed`);let i=n.length?n.join(" \xB7 "):"All sections open and on sale",a=t>0||s>0;this.els.rail.innerHTML=`
1308
1380
  ${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.")}
1309
- <div class="slm-availlist" data-ref="availlist">${e.map(o=>mt(o,this.availabilitySaving)).join("")}</div>
1381
+ <div class="slm-availlist" data-ref="availlist">${e.map(o=>bt(o,this.availabilitySaving)).join("")}</div>
1310
1382
  <div class="slm-availsummary">
1311
1383
  <span class="slm-availdot${a?" warn":""}"></span>
1312
1384
  <span>${b(i)}</span>
@@ -1314,17 +1386,17 @@
1314
1386
  <div class="slm-availcallout">
1315
1387
  <span class="slm-availstar" aria-hidden="true">\u2726</span>
1316
1388
  <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>
1317
- </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(n=>{n!==t&&(n.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 n=[...t.querySelectorAll("button")],i=n.indexOf(document.activeElement);n[(i+(s.key==="ArrowDown"?1:n.length-1)+n.length)%n.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=pe(this.sectionRowsInput()).rows.find(o=>o.id===e),n=s?.seatLabels??this.availabilityRules[e]?.labels??[],i={...this.availabilityRules},a=at(t,n,this.availabilityRules[e]);if(a?i[e]=a:delete i[e],s?.kind==="zone"&&this.sectionsBase)for(let o of this.sectionsBase.sections)o.zone===e&&delete i[o.id];this.persistAvailability(i)}setSectionRulePatch(e,t){let s=this.availabilityRules[e];if(!s)return;let i=pe(this.sectionRowsInput()).rows.find(a=>a.id===e)?.seatLabels??s.labels??[];this.persistAvailability({...this.availabilityRules,[e]:{...s,...t,labels:i}})}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(Oe(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=rt.map(t=>`<div class="slm-legrow"><span class="slm-legdot" style="background:${t.color}"></span>
1318
- <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(d=>`<button class="slm-chip" type="button" data-cat="${b(d.key)}" aria-pressed="false">
1319
- <span class="dot" style="background:${b(d.color??"#6e7bff")}"></span>
1320
- <span>${b(d.label??d.key)}</span>
1389
+ </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(n=>{n!==t&&(n.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 n=[...t.querySelectorAll("button")],i=n.indexOf(document.activeElement);n[(i+(s.key==="ArrowDown"?1:n.length-1)+n.length)%n.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=ue(this.sectionRowsInput()).rows.find(o=>o.id===e),n=s?.seatLabels??this.availabilityRules[e]?.labels??[],i={...this.availabilityRules},a=ot(t,n,this.availabilityRules[e]);if(a?i[e]=a:delete i[e],s?.kind==="zone"&&this.sectionsBase)for(let o of this.sectionsBase.sections)o.zone===e&&delete i[o.id];this.persistAvailability(i)}setSectionRulePatch(e,t){let s=this.availabilityRules[e];if(!s)return;let i=ue(this.sectionRowsInput()).rows.find(a=>a.id===e)?.seatLabels??s.labels??[];this.persistAvailability({...this.availabilityRules,[e]:{...s,...t,labels:i}})}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(Fe(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=dt.map(t=>`<div class="slm-legrow"><span class="slm-legdot" style="background:${t.color}"></span>
1390
+ <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(c=>`<button class="slm-chip" type="button" data-cat="${b(c.key)}" aria-pressed="false">
1391
+ <span class="dot" style="background:${b(c.color??"#6e7bff")}"></span>
1392
+ <span>${b(c.label??c.key)}</span>
1321
1393
  <span class="slm-chipcount" data-cat-count>0</span>
1322
1394
  <span class="slm-chipcheck" aria-hidden="true">\u2713</span>
1323
1395
  </button>`).join(""),s=this.sectionOptions.length?`<div class="slm-field"><label>Select a whole section</label>
1324
1396
  <select class="slm-select" data-ref="section"><option value="">Choose a section\u2026</option>
1325
- ${this.sectionOptions.map(d=>`<option value="${b(d.id)}">${b(d.label)}</option>`).join("")}</select></div>`:"",n=this.sectionOptions.map(d=>`<option value="${b(d.id)}">${b(d.label)}</option>`).join("");this.els.rail.innerHTML=`
1397
+ ${this.sectionOptions.map(c=>`<option value="${b(c.id)}">${b(c.label)}</option>`).join("")}</select></div>`:"",n=this.sectionOptions.map(c=>`<option value="${b(c.id)}">${b(c.label)}</option>`).join("");this.els.rail.innerHTML=`
1326
1398
  <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>
1327
- <p class="slm-note">\u25A7 Blocked \xB7 \u25CF Green: booked \xB7 \u25CF Gold: held</p>
1399
+ <p class="slm-note">${ct}</p>
1328
1400
  <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>
1329
1401
  <div class="slm-row">
1330
1402
  <button class="slm-btn" data-ref="doblock" disabled>Block</button>
@@ -1367,5 +1439,5 @@
1367
1439
  <button class="slm-btn ghost" data-ref="markall" style="width:100%" disabled>Put all blocked seats on sale</button>
1368
1440
  <p class="slm-note slm-allnote" data-ref="markallnote">For a full reset only. You will be asked to confirm.</p>
1369
1441
  </div></details>
1370
- `,this.els.rail.querySelectorAll("[data-block-tab]").forEach(d=>d.addEventListener("click",()=>{this.blockBrowse=d.dataset.blockTab==="browse",this.renderBlockRail()}));let i=d=>this.els.rail.querySelector(`[data-ref="${d}"]`);this.els.selnum=i("selnum"),this.els.doblock=i("doblock"),this.els.dounblock=i("dounblock"),this.els.selmeta=i("selmeta"),this.els.blockedcount=i("blockedcount"),this.els.blockedshowing=i("blockedshowing"),this.els.blockedlist=i("blockedlist"),this.els.selblocked=i("selblocked"),this.els.markall=i("markall"),this.els.markallnote=i("markallnote"),i("doblock").addEventListener("click",()=>{this.block()}),i("dounblock").addEventListener("click",()=>{this.unblock()}),i("selall").addEventListener("click",()=>this.selectAll()),i("clearsel").addEventListener("click",()=>this.clearSelection()),i("markall").addEventListener("click",()=>this.confirmUnblockAll()),this.els.rail.querySelectorAll("[data-cat]").forEach(d=>d.addEventListener("click",()=>this.toggleCategory(d.dataset.cat)));let a=this.els.rail.querySelector('[data-ref="section"]');a?.addEventListener("change",()=>{a.value&&(this.selectSection(a.value),a.value="")});let o=i("blockedsearch"),r=i("blockedsection");o.value=this.blockedQuery,r.value=this.blockedSection,o.addEventListener("input",()=>{this.blockedQuery=o.value,this.blockedResultLimit=100,this.paintBlockedInventory()}),r.addEventListener("change",()=>{this.blockedSection=r.value,this.blockedResultLimit=100,this.paintBlockedInventory()}),i("selblocked").addEventListener("click",()=>{this.toggleLabels(this.filteredBlockedSeats().map(d=>d.label))}),i("blockedlist").addEventListener("click",d=>{let h=d.target,u=h.closest("[data-block-seat-find]");if(u?.dataset.blockSeatFind){let m=this.labelToSeat.get(u.dataset.blockSeatFind);m&&(this.setFollowLive(!1),this.focusActivitySeats([m.label],this.sectionByObject.get(m.rowId)??S.UNGROUPED_ID));return}let f=h.closest("[data-block-locate]"),v=h.closest("[data-block-group]");if(f||v){let m=f?.dataset.blockLocate??v?.dataset.blockGroup,k=this.filteredBlockedSeats().filter(R=>R.rowId===m);f&&k.length&&(this.setFollowLive(!1),this.focusActivitySeats(k.map(R=>R.label),this.sectionByObject.get(k[0].rowId)??S.UNGROUPED_ID)),v&&this.toggleLabels(k.map(R=>R.label));return}let g=h.closest("[data-blocked-label]");g?.dataset.blockedLabel?this.toggleLabels([g.dataset.blockedLabel]):h.closest("[data-blocked-more]")&&(this.blockedResultLimit+=100,this.paintBlockedInventory())});let c=i("release");c.addEventListener("change",()=>{let d=c.value?new Date(c.value).getTime():NaN;this.releaseAt=Number.isFinite(d)&&d>Date.now()?d:null;let h=i("releasenote");h.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,n]of this.labelToSeat.entries())n.categoryKey===e&&this.isBlockSelectable(s)&&t.push(s);this.toggleLabels(t)}toggleLabels(e){if(!this.renderer)return;let t=e.filter(i=>this.labelToSeat.has(i)&&this.isBlockSelectable(i));if(!t.length)return;let s=new Set(this.selectionLabels());if(t.every(i=>s.has(i))){let i=t.map(a=>this.labelToId.get(a)).filter(a=>!!a);this.renderer.deselect(i)}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 n=this.els.doblock,i=this.els.dounblock;n.disabled=t===0,i.disabled=s===0,n.textContent=t?`Block ${t.toLocaleString()}`:"Block selected",i.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 n=s.dataset.cat,i=[];for(let[d,h]of this.labelToSeat.entries())h.categoryKey===n&&this.isBlockSelectable(d)&&i.push(d);let a=i.filter(d=>t.has(d)).length,o=i.length>0&&a===i.length,r=a>0&&!o;s.disabled=i.length===0,s.classList.toggle("on",o),s.classList.toggle("partial",r),s.setAttribute("aria-pressed",o?"true":r?"mixed":"false"),s.setAttribute("title",o?`Remove all ${i.length.toLocaleString()} seats in this category from the selection`:r?`Select the remaining ${(i.length-a).toLocaleString()} seats in this category`:`Select all ${i.length.toLocaleString()} seats in this category`);let c=s.querySelector("[data-cat-count]");c&&(c.textContent=a?`${a.toLocaleString()}/${i.length.toLocaleString()}`:i.length.toLocaleString())})}filteredBlockedSeats(){let e=this.blockedQuery.trim().toLocaleLowerCase(),t=[];for(let[s,n]of this.labelToSeat.entries()){if(this.status.get(s)!=="blocked")continue;let i=this.sectionByObject.get(n.rowId)??S.UNGROUPED_ID;if(!(this.blockedSection&&i!==this.blockedSection)){if(e){let a=this.doc?.categories.find(h=>h.key===n.categoryKey)?.label??n.categoryKey,o=this.sectionLabelById.get(i)??"Other seats",r=this.doc?.objects.find(h=>h.id===n.rowId),c=r?.type==="row"||r?.type==="table"?r.label:"";if(!`${s} ${a} ${o} ${c}`.toLocaleLowerCase().includes(e))continue}t.push(n)}}return t.sort((s,n)=>s.label.localeCompare(n.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),n=new Set(this.selectionLabels()),i=t.filter(h=>n.has(h.label)).length,a=t.length>0&&i===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 o=this.els.selblocked;o.disabled=t.length===0,o.textContent=a?`Remove ${t.length.toLocaleString()} results`:`Select ${t.length.toLocaleString()} results`;let r=new Map;for(let h of t){let u=r.get(h.rowId)??[];u.push(h),r.set(h.rowId,u)}this.els.blockedshowing.textContent=`${t.length.toLocaleString()} seats \xB7 ${r.size} rows`,this.els.blockedlist.innerHTML=[...r.entries()].slice(0,this.blockedResultLimit).map(([h,u])=>{let f=this.sectionByObject.get(h)??S.UNGROUPED_ID,v=this.sectionLabelById.get(f)??"Other seats",g=this.doc?.objects.find(k=>k.id===h),m=g&&"label"in g?g.label:u[0].label;return`<div class="slm-block-group"><div class="slm-block-grouphead"><button type="button" data-block-locate="${b(h)}" title="Show this row and nearby seats on the map"><b>${b(m)}</b><small>${b(v)} \xB7 ${u.length} blocked</small></button><button type="button" data-block-group="${b(h)}">Select row</button></div>
1371
- <details><summary>Choose seats</summary>${u.map(k=>`<div class="slm-block-seatline"><button type="button" class="slm-blockeditem${n.has(k.label)?" on":""}" data-blocked-label="${b(k.label)}" aria-pressed="${n.has(k.label)}"><span class="slm-blockedcheck" aria-hidden="true">\u2713</span><span>${b(k.label)}</span></button><button type="button" data-block-seat-find="${b(k.label)}" aria-label="Show ${b(k.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 n=e==="block"?this.pushActivity(t,"blocked","blocked"):e==="unblock"||e==="unblockAll"?this.pushActivity(t,"unblocked","free"):e==="cancelBooking"?this.pushActivity(t,"cancelled","free"):null;n&&this.paintSpatialActivity(n)}e!=="setHoldTtl"&&this.refreshControlRoom().catch(n=>this.opts.onError?.(n)),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>`)}};_e();Re();re();0&&(module.exports={ACCESS_LINK_DEFAULTS,ChannelsMode,ManageApi,ManageApiError,PUBLIC_CHANNEL_ID,PUBLIC_CHANNEL_NAME,SeatManager,accessIntentDescription,accessIntentLabel,accessLine,accessLinkBadge,accessLinkErrorCopy,accessLinkIsLive,accessLinkPolicyLines,bucketRows,bucketRowsHtml,dropReviewRows,intentForbidsCopy,intentSwitchBlockedCopy,isPublicChannelId,markerLetter,markerOf,mutationCount,needsMoveConfirmation,planAssignment,retryAfterCopy,selectionSources,stateBadge,suggestMarker});
1442
+ `,this.els.rail.querySelectorAll("[data-block-tab]").forEach(c=>c.addEventListener("click",()=>{this.blockBrowse=c.dataset.blockTab==="browse",this.renderBlockRail()}));let i=c=>this.els.rail.querySelector(`[data-ref="${c}"]`);this.els.selnum=i("selnum"),this.els.doblock=i("doblock"),this.els.dounblock=i("dounblock"),this.els.selmeta=i("selmeta"),this.els.blockedcount=i("blockedcount"),this.els.blockedshowing=i("blockedshowing"),this.els.blockedlist=i("blockedlist"),this.els.selblocked=i("selblocked"),this.els.markall=i("markall"),this.els.markallnote=i("markallnote"),i("doblock").addEventListener("click",()=>{this.block()}),i("dounblock").addEventListener("click",()=>{this.unblock()}),i("selall").addEventListener("click",()=>this.selectAll()),i("clearsel").addEventListener("click",()=>this.clearSelection()),i("markall").addEventListener("click",()=>this.confirmUnblockAll()),this.els.rail.querySelectorAll("[data-cat]").forEach(c=>c.addEventListener("click",()=>this.toggleCategory(c.dataset.cat)));let a=this.els.rail.querySelector('[data-ref="section"]');a?.addEventListener("change",()=>{a.value&&(this.selectSection(a.value),a.value="")});let o=i("blockedsearch"),r=i("blockedsection");o.value=this.blockedQuery,r.value=this.blockedSection,o.addEventListener("input",()=>{this.blockedQuery=o.value,this.blockedResultLimit=100,this.paintBlockedInventory()}),r.addEventListener("change",()=>{this.blockedSection=r.value,this.blockedResultLimit=100,this.paintBlockedInventory()}),i("selblocked").addEventListener("click",()=>{this.toggleLabels(this.filteredBlockedSeats().map(c=>c.label))}),i("blockedlist").addEventListener("click",c=>{let h=c.target,u=h.closest("[data-block-seat-find]");if(u?.dataset.blockSeatFind){let m=this.labelToSeat.get(u.dataset.blockSeatFind);m&&(this.setFollowLive(!1),this.focusActivitySeats([m.label],this.sectionByObject.get(m.rowId)??w.UNGROUPED_ID));return}let f=h.closest("[data-block-locate]"),v=h.closest("[data-block-group]");if(f||v){let m=f?.dataset.blockLocate??v?.dataset.blockGroup,y=this.filteredBlockedSeats().filter(H=>H.rowId===m);f&&y.length&&(this.setFollowLive(!1),this.focusActivitySeats(y.map(H=>H.label),this.sectionByObject.get(y[0].rowId)??w.UNGROUPED_ID)),v&&this.toggleLabels(y.map(H=>H.label));return}let g=h.closest("[data-blocked-label]");g?.dataset.blockedLabel?this.toggleLabels([g.dataset.blockedLabel]):h.closest("[data-blocked-more]")&&(this.blockedResultLimit+=100,this.paintBlockedInventory())});let d=i("release");d.addEventListener("change",()=>{let c=d.value?new Date(d.value).getTime():NaN;this.releaseAt=Number.isFinite(c)&&c>Date.now()?c:null;let h=i("releasenote");h.textContent=this.releaseAt?`New blocks auto-release ${new Date(this.releaseAt).toLocaleString()}.`:d.value?"Pick a time in the future.":"Leave empty to block permanently."}),this.paintSelBar(this.getSelection())}toggleCategory(e){let t=[];for(let[s,n]of this.labelToSeat.entries())n.categoryKey===e&&this.isBlockSelectable(s)&&t.push(s);this.toggleLabels(t)}toggleLabels(e){if(!this.renderer)return;let t=e.filter(i=>this.labelToSeat.has(i)&&this.isBlockSelectable(i));if(!t.length)return;let s=new Set(this.selectionLabels());if(t.every(i=>s.has(i))){let i=t.map(a=>this.labelToId.get(a)).filter(a=>!!a);this.renderer.deselect(i)}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 n=this.els.doblock,i=this.els.dounblock;n.disabled=t===0,i.disabled=s===0,n.textContent=t?`Block ${t.toLocaleString()}`:"Block selected",i.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 n=s.dataset.cat,i=[];for(let[c,h]of this.labelToSeat.entries())h.categoryKey===n&&this.isBlockSelectable(c)&&i.push(c);let a=i.filter(c=>t.has(c)).length,o=i.length>0&&a===i.length,r=a>0&&!o;s.disabled=i.length===0,s.classList.toggle("on",o),s.classList.toggle("partial",r),s.setAttribute("aria-pressed",o?"true":r?"mixed":"false"),s.setAttribute("title",o?`Remove all ${i.length.toLocaleString()} seats in this category from the selection`:r?`Select the remaining ${(i.length-a).toLocaleString()} seats in this category`:`Select all ${i.length.toLocaleString()} seats in this category`);let d=s.querySelector("[data-cat-count]");d&&(d.textContent=a?`${a.toLocaleString()}/${i.length.toLocaleString()}`:i.length.toLocaleString())})}filteredBlockedSeats(){let e=this.blockedQuery.trim().toLocaleLowerCase(),t=[];for(let[s,n]of this.labelToSeat.entries()){if(this.status.get(s)!=="blocked")continue;let i=this.sectionByObject.get(n.rowId)??w.UNGROUPED_ID;if(!(this.blockedSection&&i!==this.blockedSection)){if(e){let a=this.doc?.categories.find(h=>h.key===n.categoryKey)?.label??n.categoryKey,o=this.sectionLabelById.get(i)??"Other seats",r=this.doc?.objects.find(h=>h.id===n.rowId),d=r?.type==="row"||r?.type==="table"?r.label:"";if(!`${s} ${a} ${o} ${d}`.toLocaleLowerCase().includes(e))continue}t.push(n)}}return t.sort((s,n)=>s.label.localeCompare(n.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),n=new Set(this.selectionLabels()),i=t.filter(h=>n.has(h.label)).length,a=t.length>0&&i===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 o=this.els.selblocked;o.disabled=t.length===0,o.textContent=a?`Remove ${t.length.toLocaleString()} results`:`Select ${t.length.toLocaleString()} results`;let r=new Map;for(let h of t){let u=r.get(h.rowId)??[];u.push(h),r.set(h.rowId,u)}this.els.blockedshowing.textContent=`${t.length.toLocaleString()} seats \xB7 ${r.size} rows`,this.els.blockedlist.innerHTML=[...r.entries()].slice(0,this.blockedResultLimit).map(([h,u])=>{let f=this.sectionByObject.get(h)??w.UNGROUPED_ID,v=this.sectionLabelById.get(f)??"Other seats",g=this.doc?.objects.find(y=>y.id===h),m=g&&"label"in g?g.label:u[0].label;return`<div class="slm-block-group"><div class="slm-block-grouphead"><button type="button" data-block-locate="${b(h)}" title="Show this row and nearby seats on the map"><b>${b(m)}</b><small>${b(v)} \xB7 ${u.length} blocked</small></button><button type="button" data-block-group="${b(h)}">Select row</button></div>
1443
+ <details><summary>Choose seats</summary>${u.map(y=>`<div class="slm-block-seatline"><button type="button" class="slm-blockeditem${n.has(y.label)?" on":""}" data-blocked-label="${b(y.label)}" aria-pressed="${n.has(y.label)}"><span class="slm-blockedcheck" aria-hidden="true">\u2713</span><span>${b(y.label)}</span></button><button type="button" data-block-seat-find="${b(y.label)}" aria-label="Show ${b(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 d=this.els.markall,c=d.dataset.confirm==="true";d.disabled=e===0,d.textContent=c?`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 n=e==="block"?this.pushActivity(t,"blocked","blocked"):e==="unblock"||e==="unblockAll"?this.pushActivity(t,"unblocked","free"):e==="cancelBooking"?this.pushActivity(t,"cancelled","free"):null;n&&this.paintSpatialActivity(n)}e!=="setHoldTtl"&&this.refreshControlRoom().catch(n=>this.opts.onError?.(n)),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>`)}};Ve();Ee();ce();0&&(module.exports={ACCESS_LINK_DEFAULTS,ChannelsMode,ManageApi,ManageApiError,PUBLIC_CHANNEL_ID,PUBLIC_CHANNEL_NAME,SeatManager,accessIntentDescription,accessIntentLabel,accessLine,accessLinkBadge,accessLinkErrorCopy,accessLinkIsLive,accessLinkPolicyLines,bucketRows,bucketRowsHtml,dropReviewRows,intentForbidsCopy,intentSwitchBlockedCopy,isPublicChannelId,markerLetter,markerOf,mutationCount,needsMoveConfirmation,planAssignment,retryAfterCopy,selectionSources,stateBadge,suggestMarker});