@seatlayer/js 0.54.0 → 0.56.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,16 +1,16 @@
1
- "use strict";var $e=Object.defineProperty;var ft=Object.getOwnPropertyDescriptor;var yt=Object.getOwnPropertyNames;var kt=Object.prototype.hasOwnProperty;var j=(a,e,t)=>()=>{if(t)throw t[0];try{return a&&(e=a(a=0)),e}catch(s){throw t=[s],s}};var Fe=(a,e)=>{for(var t in e)$e(a,t,{get:e[t],enumerable:!0})},wt=(a,e,t,s)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of yt(e))!kt.call(a,n)&&n!==t&&$e(a,n,{get:()=>e[n],enumerable:!(s=ft(e,n))||s.enumerable});return a};var xt=a=>wt($e({},"__esModule",{value:!0}),a);async function qe(a){let t=(a.headers.get("content-type")??"").includes("application/json")?await a.json().catch(()=>null):null;if(!a.ok){let s=t;throw new f(a.status,s?.error??`request_failed_${a.status}`,s?.code,s?.conflicts,s?.details,typeof s?.message=="string"?s.message:void 0)}return t}function $(a){return a&&typeof a=="object"?a:{}}function ie(a,e,t=0){return typeof a=="number"&&Number.isFinite(a)?a:typeof e=="number"&&Number.isFinite(e)?e:t}function Ne(a,e){return a===null?null:typeof a=="number"&&Number.isFinite(a)?a:a!==void 0?null:typeof e=="number"&&Number.isFinite(e)?e:null}function Ve(a){let e=$(a),t=ie(e.bookedValue,e.bookedRevenue);return{...e,bookedValue:t,bookedRevenue:t}}function St(a){let e=$(a),t=$(e.report),s=Array.isArray(t.byCategory)?t.byCategory.map(i=>{let o=$(i),l=ie(o.bookedValue,o.bookedRevenue);return{...o,bookedValue:l,bookedRevenue:l}}):[],n=Array.isArray(t.bySection)?t.bySection.map(Ve):void 0;return{...e,report:{...t,byCategory:s,...n?{bySection:n}:{}}}}function Lt(a){let e=$(a),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:[],o={...n,gross:ie(t.gross,s.gross),bySection:i.map(Ve)},l=$(e.velocity),r=Array.isArray(l.bySection)?l.bySection.map(d=>{let c=$(d),p=ie(c.bookedValue,c.grossRevenue);return{...c,bookedValue:p,grossRevenue:p}}):[];return{...e,bookedValue:o,revenue:o,velocity:{...l,bySection:r}}}function Ct(a){let e=$(a),t=$(e.report),s=typeof t.includesBookedValue=="boolean"?t.includesBookedValue:t.includesRevenue===!0,n=Array.isArray(t.rows)?t.rows.map(l=>{let r=$(l),d=$(r.attribution),c=Ne(d.bookedValue,d.revenue);return{...r,attribution:{...d,bookedValue:c,revenue:c}}}):[],i=$(t.totals),o=Ne(i.bookedValue,i.revenue);return{...e,report:{...t,includesBookedValue:s,includesRevenue:s,rows:n,totals:{...i,bookedValue:o,revenue:o}}}}function Ae(a){let e=$(a),t=typeof e.includesBookedValue=="boolean"?e.includesBookedValue:e.includesRevenue===!0;return{...e,includesBookedValue:t,includesRevenue:t}}var f,U,ae=j(()=>{"use strict";f=class extends Error{constructor(e,t,s,n,i,o){super(t),this.name="ManageApiError",this.status=e,this.code=s,this.conflicts=n,this.details=i,this.serverMessage=o}};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(o=>qe(o))}async authBlob(e){let t=await fetch(`${this.base}${e}`,{method:"GET",headers:{Authorization:`Bearer ${this.token}`},credentials:"omit"});return t.ok||await qe(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 f(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}})}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}})}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(St)}controlRoom(e,t=15){return this.auth(`/v1/events/${encodeURIComponent(e)}/control-room?window=${t}`).then(Lt)}channelReport(e){return this.auth(`/v1/events/${encodeURIComponent(e)}/channels/report`).then(Ct)}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:Ae(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(Ae):[]}})}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:Ae(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 f(t.status,`request_failed_${t.status}`);return t.blob()}}});function P(a){return a==null||a===""||a===L}function z(a,e){let t=(a??"").trim();return((/\p{L}/u.exec(t)?.[0]??t[0]??"")||e).toUpperCase().slice(0,1)}function J(a,e){let t=new Set([...e].map(i=>z(i,"")).filter(Boolean)),s=z(a,"");return{letter:st.includes(s)&&!t.has(s)?s:[...st].find(i=>!t.has(i))??(s||"X"),color:he[t.size%he.length]}}function pe(a,e=0){return P(a.id)?{letter:z(a.marker,"P"),color:a.color||It}:{letter:z(a.marker||a.name,"?"),color:a.color||he[e%he.length]}}function ue(a,e,t){let s=new Map;for(let o of a){let l=He(e.get(o));s.set(l,(s.get(l)??0)+1)}let n=[{id:L,name:t?.publicSale?.name??A},...(t?.channels??[]).map(o=>({id:o.id,name:o.name}))],i=[];for(let o of n){let l=s.get(o.id);l&&i.push({channelId:o.id,name:o.name,count:l}),s.delete(o.id)}for(let[o,l]of s)i.push({channelId:o,name:P(o)?A:"Another channel",count:l});return i}function He(a){return P(a)?L:a}function Pe(a){return{count:a.length,labels:a.slice(0,nt),truncated:a.length>nt}}function me(a){let{labels:e,allocation:t,statusOf:s,nameOf:n}=a,i=He(a.targetChannelId),o=new Set,l=0,r=0,d=new Map,c=[],p=[],g=[];for(let m of e){if(o.has(m))continue;o.add(m);let u=s(m);if(!u){g.push(m);continue}let v=He(t.get(m));if(v===i){r+=1;continue}if(u==="held"){c.push(m);continue}if(u==="booked"){p.push(m);continue}v===L?l+=1:d.set(v,(d.get(v)??0)+1)}let w=[...d.entries()].map(([m,u])=>({channelId:m,name:n(m),count:u}));return{changedFromPublic:{count:l},movedFromOtherChannel:{count:w.reduce((m,u)=>m+u.count,0),channels:w},alreadyInTarget:{count:r},skippedHeld:Pe(c),skippedBooked:Pe(p),notFound:Pe(g)}}function K(a){return a.changedFromPublic.count+a.movedFromOtherChannel.count}function be(a){return a.movedFromOtherChannel.count>0}function ge(a,e){let t=[];a.changedFromPublic.count&&t.push({kind:"add",icon:"+",count:a.changedFromPublic.count,text:`${a.changedFromPublic.count.toLocaleString()} from ${A}`});for(let s of a.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 a.alreadyInTarget.count&&t.push({kind:"same",icon:"=",count:a.alreadyInTarget.count,text:`${a.alreadyInTarget.count.toLocaleString()} already in ${e}`,why:"unchanged"}),a.skippedHeld.count&&t.push({kind:"skip",icon:"\u23F8",count:a.skippedHeld.count,text:`${a.skippedHeld.count.toLocaleString()} in a buyer's checkout`,why:"can't move while held",peek:de(a.skippedHeld)}),a.skippedBooked.count&&t.push({kind:"skip",icon:"\u{1F512}",count:a.skippedBooked.count,text:`${a.skippedBooked.count.toLocaleString()} already sold`,why:"sales are never rewritten",peek:de(a.skippedBooked)}),a.notFound.count&&t.push({kind:"skip",icon:"?",count:a.notFound.count,text:`${a.notFound.count.toLocaleString()} not on this map`,why:"these seats are no longer part of the event",peek:de(a.notFound)}),t}function de(a){if(!a.labels.length)return;let e=a.labels.slice(0,4).join(", ");return a.truncated||a.labels.length>4?`${e}\u2026`:e}function ve(a){let e=a?.retryAfterMs??(a?.latestHoldExpiresAt?Math.max(0,a.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 fe(a){if(!a||!a.intent)return"\u2014";let e=a.intent==="server"?"Website integration":a.intent==="hosted_link"?"Buyer link":a.intent==="internal"?"Your staff sell these":"Protected reserve",t=a.hasActiveGrants?"in use now":a.lastMintAt?`last used ${new Date(a.lastMintAt).toLocaleDateString()}`:null,s=a.detail??t;return s?`${e} \xB7 ${s}`:e}function O(a){return a==="internal"?"Sell through your own staff":a==="server"?"Integrate a website or app":a==="hosted_link"?"Sell with a buyer link":"Keep as protected reserve"}function ye(a){switch(a){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 Et(a){return a==="hosted_link"?"hosted_link":a==="server"?"server":a==="staff"?"internal":null}function Y(a){let e=Be(a?.accessIntent),t=Et(a?.route),s=`This channel is set to "${O(e)}"`;return t?`${s}, so it cannot do that. Switch it to "${O(t)}" first.`:`${s}, so it cannot do that. Choose a different route for this channel first.`}function Be(a){return a==="internal"||a==="server"||a==="hosted_link"||a==="none"?a:"none"}function ce(a,e,t){return`${a.toLocaleString()} ${a===1?e:t}`}function ke(a){let e=Math.max(0,a?.liveAccessLinks??0),t=Math.max(0,a?.activeSessions??0),s=Be(a?.from),n=Be(a?.to),o=`${[e?ce(e,"buyer link is live","buyer links are live"):null,t?ce(t,"buyer is in a checkout","buyers are in a checkout"):null].filter(Boolean).join(", and ")||"Buyers are inside this channel"} on "${O(s)}". Moving it to "${O(n)}" changes what happens to them.`,l=[];return e&&l.push(`${ce(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&&l.push(`${ce(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:o,consequences:l}}function we(a){switch(a.status??a.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(a){return a.state==="active"&&a.status==="active"}function Mt(a){return Number.isFinite(a)?new Date(a).toLocaleString(void 0,{day:"numeric",month:"short",year:"numeric",hour:"numeric",minute:"2-digit"}):"\u2014"}function se(a){return[{k:"Expires",v:Mt(a.expiresAt)},{k:"Redemptions",v:`${a.redemptions.toLocaleString()} of ${a.maxRedemptions.toLocaleString()} used`},{k:"Seats per buyer",v:`${a.maxQuantity.toLocaleString()} seat${a.maxQuantity===1?"":"s"} maximum`},{k:"Covers",v:a.includePublic?"This channel's allocation and Public sale seats":"This channel's allocation only"}]}function q(a){let e=a?.serverMessage?.trim();switch(a?.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(a?.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 a?.status===403?"Hosted access links need channel-management permission.":e||"That did not go through. Try again."}}function it(a){return(a?.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?de({count:e.count,labels:e.labels,truncated:e.truncated??!1}):void 0}))}function xe(a){return a==="builtin"?"Built-in":a==="active"?"Active":a==="paused"?"Paused":"Archived"}var L,A,he,It,st,nt,ee,Se=j(()=>{"use strict";L="public",A="Public sale";he=["#a78bfa","#2dd4bf","#fb923c","#60a5fa","#f472b6","#a3e635","#f87171","#38bdf8","#c084fc","#facc15"],It="#f4b740",st="ABCDEFGHJKLMNPQRSTUVWXYZ";nt=12;ee={maxRedemptions:100,maxQuantity:4}});function W(a){return a.map((e,t)=>`
1
+ "use strict";var $e=Object.defineProperty;var ft=Object.getOwnPropertyDescriptor;var yt=Object.getOwnPropertyNames;var kt=Object.prototype.hasOwnProperty;var N=(l,e,t)=>()=>{if(t)throw t[0];try{return l&&(e=l(l=0)),e}catch(s){throw t=[s],s}};var qe=(l,e)=>{for(var t in e)$e(l,t,{get:e[t],enumerable:!0})},wt=(l,e,t,s)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of yt(e))!kt.call(l,n)&&n!==t&&$e(l,n,{get:()=>e[n],enumerable:!(s=ft(e,n))||s.enumerable});return l};var xt=l=>wt($e({},"__esModule",{value:!0}),l);async function _e(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 f(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 ie(l,e,t=0){return typeof l=="number"&&Number.isFinite(l)?l:typeof e=="number"&&Number.isFinite(e)?e:t}function je(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 Ve(l){let e=$(l),t=ie(e.bookedValue,e.bookedRevenue);return{...e,bookedValue:t,bookedRevenue:t}}function St(l){let e=$(l),t=$(e.report),s=Array.isArray(t.byCategory)?t.byCategory.map(i=>{let a=$(i),o=ie(a.bookedValue,a.bookedRevenue);return{...a,bookedValue:o,bookedRevenue:o}}):[],n=Array.isArray(t.bySection)?t.bySection.map(Ve):void 0;return{...e,report:{...t,byCategory:s,...n?{bySection:n}:{}}}}function Lt(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:ie(t.gross,s.gross),bySection:i.map(Ve)},o=$(e.velocity),r=Array.isArray(o.bySection)?o.bySection.map(d=>{let c=$(d),p=ie(c.bookedValue,c.grossRevenue);return{...c,bookedValue:p,grossRevenue:p}}):[];return{...e,bookedValue:a,revenue:a,velocity:{...o,bySection:r}}}function Ct(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=je(d.bookedValue,d.revenue);return{...r,attribution:{...d,bookedValue:c,revenue:c}}}):[],i=$(t.totals),a=je(i.bookedValue,i.revenue);return{...e,report:{...t,includesBookedValue:s,includesRevenue:s,rows:n,totals:{...i,bookedValue:a,revenue:a}}}}function Te(l){let e=$(l),t=typeof e.includesBookedValue=="boolean"?e.includesBookedValue:e.includesRevenue===!0;return{...e,includesBookedValue:t,includesRevenue:t}}var f,U,ae=N(()=>{"use strict";f=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=>_e(a))}async authBlob(e){let t=await fetch(`${this.base}${e}`,{method:"GET",headers:{Authorization:`Bearer ${this.token}`},credentials:"omit"});return t.ok||await _e(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 f(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(St)}controlRoom(e,t=15){return this.auth(`/v1/events/${encodeURIComponent(e)}/control-room?window=${t}`).then(Lt)}channelReport(e){return this.auth(`/v1/events/${encodeURIComponent(e)}/channels/report`).then(Ct)}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:Te(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(Te):[]}})}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:Te(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 f(t.status,`request_failed_${t.status}`);return t.blob()}}});function P(l){return l==null||l===""||l===C}function O(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=>O(i,"")).filter(Boolean)),s=O(l,"");return{letter:st.includes(s)&&!t.has(s)?s:[...st].find(i=>!t.has(i))??(s||"X"),color:he[t.size%he.length]}}function pe(l,e=0){return P(l.id)?{letter:O(l.marker,"P"),color:l.color||Et}:{letter:O(l.marker||l.name,"?"),color:l.color||he[e%he.length]}}function ue(l,e,t){let s=new Map;for(let a of l){let o=Be(e.get(a));s.set(o,(s.get(o)??0)+1)}let n=[{id:C,name:t?.publicSale?.name??T},...(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:P(a)?T:"Another channel",count:o});return i}function Be(l){return P(l)?C:l}function Pe(l){return{count:l.length,labels:l.slice(0,nt),truncated:l.length>nt}}function me(l){let{labels:e,allocation:t,statusOf:s,nameOf:n}=l,i=Be(l.targetChannelId),a=new Set,o=0,r=0,d=new Map,c=[],p=[],b=[];for(let g of e){if(a.has(g))continue;a.add(g);let m=s(g);if(!m){b.push(g);continue}let v=Be(t.get(g));if(v===i){r+=1;continue}if(m==="held"){c.push(g);continue}if(m==="booked"){p.push(g);continue}v===C?o+=1:d.set(v,(d.get(v)??0)+1)}let y=[...d.entries()].map(([g,m])=>({channelId:g,name:n(g),count:m}));return{changedFromPublic:{count:o},movedFromOtherChannel:{count:y.reduce((g,m)=>g+m.count,0),channels:y},alreadyInTarget:{count:r},skippedHeld:Pe(c),skippedBooked:Pe(p),notFound:Pe(b)}}function K(l){return l.changedFromPublic.count+l.movedFromOtherChannel.count}function be(l){return l.movedFromOtherChannel.count>0}function ge(l,e){let t=[];l.changedFromPublic.count&&t.push({kind:"add",icon:"+",count:l.changedFromPublic.count,text:`${l.changedFromPublic.count.toLocaleString()} from ${T}`});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:de(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:de(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:de(l.notFound)}),t}function de(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 ve(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 fe(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 z(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 ye(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 Mt(l){return l==="hosted_link"?"hosted_link":l==="server"?"server":l==="staff"?"internal":null}function Y(l){let e=He(l?.accessIntent),t=Mt(l?.route),s=`This channel is set to "${z(e)}"`;return t?`${s}, so it cannot do that. Switch it to "${z(t)}" first.`:`${s}, so it cannot do that. Choose a different route for this channel first.`}function He(l){return l==="internal"||l==="server"||l==="hosted_link"||l==="none"?l:"none"}function ce(l,e,t){return`${l.toLocaleString()} ${l===1?e:t}`}function ke(l){let e=Math.max(0,l?.liveAccessLinks??0),t=Math.max(0,l?.activeSessions??0),s=He(l?.from),n=He(l?.to),a=`${[e?ce(e,"buyer link is live","buyer links are live"):null,t?ce(t,"buyer is in a checkout","buyers are in a checkout"):null].filter(Boolean).join(", and ")||"Buyers are inside this channel"} on "${z(s)}". Moving it to "${z(n)}" changes what happens to them.`,o=[];return e&&o.push(`${ce(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(`${ce(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 we(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 It(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:It(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 _(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 it(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?de({count:e.count,labels:e.labels,truncated:e.truncated??!1}):void 0}))}function xe(l){return l==="builtin"?"Built-in":l==="active"?"Active":l==="paused"?"Paused":"Archived"}var C,T,he,Et,st,nt,ee,Se=N(()=>{"use strict";C="public",T="Public sale";he=["#a78bfa","#2dd4bf","#fb923c","#60a5fa","#f472b6","#a3e635","#f87171","#38bdf8","#c084fc","#facc15"],Et="#f4b740",st="ABCDEFGHJKLMNPQRSTUVWXYZ";nt=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">${h(e.icon)}</span>
4
4
  <span><b>${e.count.toLocaleString()}</b> ${h(e.text.replace(/^[\d,.\s]+/,""))}
5
5
  ${e.why?`<span class="why">\u2014 ${h(e.why)}</span>`:""}</span>
6
6
  ${e.peek?`<span class="peek">${h(e.peek)}</span>`:"<span></span>"}
7
- </div>`).join("")}function h(a){return String(a??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#039;")}function ot(a){return new Date(a-new Date(a).getTimezoneOffset()*6e4).toISOString().slice(0,16)}function De(a,e){let t=a.querySelector(e)?.value.trim()??"",s=Number(t);return t!==""&&Number.isInteger(s)?s:null}function ze(a){let e=a.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 at,Le=j(()=>{"use strict";at=`
7
+ </div>`).join("")}function h(l){return String(l??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#039;")}function ot(l){return new Date(l-new Date(l).getTimezoneOffset()*6e4).toISOString().slice(0,16)}function De(l,e){let t=l.querySelector(e)?.value.trim()??"",s=Number(t);return t!==""&&Number.isInteger(s)?s:null}function Oe(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 at,Le=N(()=>{"use strict";at=`
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 lt(a){let e=a.canvas,t=a.layer;if(!e||!t)return;let s=a.host.mapLayer.getBoundingClientRect(),n=Math.max(1,Math.round(s.width)),i=Math.max(1,Math.round(s.height)),o=typeof devicePixelRatio=="number"?Math.min(3,Math.max(1,devicePixelRatio)):1;(e.width!==n*o||e.height!==i*o)&&(e.width=n*o,e.height=i*o);let l=a.resolveCtx();if(!l)return;l.setTransform(o,0,0,o,0,0),l.clearRect(0,0,n,i);let r=a.host.isSeatDetail(),d=Math.max(3,a.host.seatPixelSize()),c=d/2,p=a.view==="preview"?a.previewProjection:null,g=p?new Set(p.available===!1?[]:p.eligible??[]):null,w=new Map,m=!r&&a.host.sections().length>1?new Map:null,u=a.view==="preview"&&r&&d<=15?new Map:null;for(let v of a.host.seats()){let H=a.host.statusOf(v.label)??"free",_=a.allocation.get(v.label)??L;if(_!==L){let x=w.get(_)??{x:0,y:0,n:0};x.x+=v.x,x.y+=v.y,x.n+=1,w.set(_,x)}if(!r){let x=a.host.sectionOfLabel(v.label),k=x?a.host.worldToScreen({x:v.x,y:v.y}):null;if(m&&x&&k){let y=m.get(x.id)??{label:x.label,minX:k.x,minY:k.y,maxX:k.x,maxY:k.y};y.minX=Math.min(y.minX,k.x),y.minY=Math.min(y.minY,k.y),y.maxX=Math.max(y.maxX,k.x),y.maxY=Math.max(y.maxY,k.y),m.set(x.id,y)}continue}if(H!=="free")continue;let F=null,I=null;if(a.view==="preview"?g?.has(v.label)?(F=Ht,I=Bt):(F=Dt,I=zt):_!==L&&(F=a.markerFor(_).color,I=Ot),!F)continue;let S=a.host.worldToScreen({x:v.x,y:v.y});if(S&&!(S.x<-d||S.y<-d||S.x>n+d||S.y>i+d)){if(u){let x=a.host.sectionOfLabel(v.label);if(x){let k=u.get(x.id)??{label:x.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),u.set(x.id,k)}}if(l.fillStyle=F,a.view==="preview"||_!==L){let x=Math.max(2,c+Math.min(1.5,c*.06));l.globalAlpha=1,l.beginPath(),l.arc(S.x,S.y,x,0,Math.PI*2),l.fill(),l.strokeStyle=I??F,l.lineWidth=a.view==="preview"?Math.max(1,Math.min(1.75,d*.13)):Math.max(1,Math.min(1.5,d*.1)),l.stroke(),a.view==="preview"&&g?.has(v.label)&&d>=22&&_t(l,v.label,S.x,S.y,x)}else l.globalAlpha=.85,l.fillRect(S.x-c,S.y-c,d,d)}}l.globalAlpha=1,u&&qt(l,u),Ft(m,a),Nt(w,a,l)}function _t(a,e,t,s,n){let i=n*1.55,o=Math.min(13,Math.max(7,n*.55)),l=6;for(;o>=l&&(a.font=`800 ${o}px var(--slm-font, system-ui, sans-serif)`,!(a.measureText(e).width<=i));)o-=.5;o<l||(a.fillStyle="#ffffff",a.textAlign="center",a.textBaseline="middle",a.fillText(e,t,s))}function Ft(a,e){let t=e.layer;if(t&&(t.querySelectorAll(".slm-ch-section-target").forEach(s=>s.remove()),!!a))for(let[s,n]of a){let i=n.maxX-n.minX,o=n.maxY-n.minY;if(i<20||o<20)continue;let l=document.createElement("button");l.type="button",l.className="slm-ch-section-target",l.style.left=`${n.minX-8}px`,l.style.top=`${n.minY-8}px`,l.style.width=`${i+16}px`,l.style.height=`${o+16}px`,l.setAttribute("aria-label",`Open ${n.label} seats`),l.addEventListener("click",()=>e.onSectionTargetClick(s)),t.appendChild(l)}}function qt(a,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,o=(t.minY+t.maxY)/2,l=Math.max(11,Math.min(15,n*.16));a.font=`800 ${l}px var(--slm-font, system-ui, sans-serif)`;let r=Math.min(s-8,a.measureText(t.label).width+18),d=l+10;a.fillStyle="rgba(11, 16, 28, .88)",a.fillRect(i-r/2,o-d/2,r,d),a.fillStyle="#f8fafc",a.textAlign="center",a.textBaseline="middle",a.fillText(t.label,i,o)}}function Nt(a,e,t){let s=e.layer;if(!s||(s.querySelectorAll(".slm-ch-flag").forEach(i=>i.remove()),e.view==="preview"))return;let n=[...a.entries()].sort((i,o)=>o[1].n-i[1].n).slice(0,Pt);for(let[i,o]of n){let l=e.list?.channels.find(p=>p.id===i);if(!l)continue;let r=e.host.worldToScreen({x:o.x/o.n,y:o.y/o.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:${h(d.color)}">${h(d.letter)}</span>${h(l.name)}${l.state==="paused"?" \xB7 Paused":""}`,s.appendChild(c)}}var Pt,Ht,Bt,Dt,zt,Ot,rt=j(()=>{"use strict";Se();Le();Pt=8,Ht="#6e7bff",Bt="#b9c0ff",Dt="#303846",zt="#4b5669",Ot="#101723"});var ct,dt=j(()=>{"use strict";ct=`
13
+ target="_blank" rel="noreferrer noopener">Read the website integration guide \u2192</a></p>`});function lt(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(),d=Math.max(3,l.host.seatPixelSize()),c=d/2,p=l.view==="preview"?l.previewProjection:null,b=p?new Set(p.available===!1?[]:p.eligible??[]):null,y=new Map,g=!r&&l.host.sections().length>1?new Map:null,m=l.view==="preview"&&r&&d<=15?new Map:null;for(let v of l.host.seats()){let B=l.host.statusOf(v.label)??"free",F=l.allocation.get(v.label)??C;if(F!==C){let x=y.get(F)??{x:0,y:0,n:0};x.x+=v.x,x.y+=v.y,x.n+=1,y.set(F,x)}if(!r){let x=l.host.sectionOfLabel(v.label),w=x?l.host.worldToScreen({x:v.x,y:v.y}):null;if(g&&x&&w){let k=g.get(x.id)??{label:x.label,minX:w.x,minY:w.y,maxX:w.x,maxY:w.y};k.minX=Math.min(k.minX,w.x),k.minY=Math.min(k.minY,w.y),k.maxX=Math.max(k.maxX,w.x),k.maxY=Math.max(k.maxY,w.y),g.set(x.id,k)}continue}if(B!=="free")continue;let q=null,E=null;if(l.view==="preview"?b?.has(v.label)?(q=Bt,E=Ht):(q=Dt,E=Ot):F!==C&&(q=l.markerFor(F).color,E=zt),!q)continue;let S=l.host.worldToScreen({x:v.x,y:v.y});if(S&&!(S.x<-d||S.y<-d||S.x>n+d||S.y>i+d)){if(m){let x=l.host.sectionOfLabel(v.label);if(x){let w=m.get(x.id)??{label:x.label,minX:S.x,minY:S.y,maxX:S.x,maxY:S.y};w.minX=Math.min(w.minX,S.x),w.minY=Math.min(w.minY,S.y),w.maxX=Math.max(w.maxX,S.x),w.maxY=Math.max(w.maxY,S.y),m.set(x.id,w)}}if(o.fillStyle=q,l.view==="preview"||F!==C){let x=Math.max(2,c+Math.min(1.5,c*.06));o.globalAlpha=1,o.beginPath(),o.arc(S.x,S.y,x,0,Math.PI*2),o.fill(),o.strokeStyle=E??q,o.lineWidth=l.view==="preview"?Math.max(1,Math.min(1.75,d*.13)):Math.max(1,Math.min(1.5,d*.1)),o.stroke(),l.view==="preview"&&b?.has(v.label)&&d>=22&&Ft(o,v.label,S.x,S.y,x)}else o.globalAlpha=.85,o.fillRect(S.x-c,S.y-c,d,d)}}o.globalAlpha=1,m&&_t(o,m),qt(g,l),jt(y,l,o)}function Ft(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 qt(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 _t(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),d=o+10;l.fillStyle="rgba(11, 16, 28, .88)",l.fillRect(i-r/2,a-d/2,r,d),l.fillStyle="#f8fafc",l.textAlign="center",l.textBaseline="middle",l.fillText(t.label,i,a)}}function jt(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,Pt);for(let[i,a]of n){let o=e.list?.channels.find(p=>p.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:${h(d.color)}">${h(d.letter)}</span>${h(o.name)}${o.state==="paused"?" \xB7 Paused":""}`,s.appendChild(c)}}var Pt,Bt,Ht,Dt,Ot,zt,rt=N(()=>{"use strict";Se();Le();Pt=8,Bt="#6e7bff",Ht="#b9c0ff",Dt="#303846",Ot="#4b5669",zt="#101723"});var ct,dt=N(()=>{"use strict";ct=`
14
14
  .slm{--slm-mo-instant:80ms;--slm-mo-quick:140ms;--slm-mo-base:200ms;--slm-mo-slow:320ms;--slm-mo-ambient:2000ms;
15
15
  --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
16
  --slm-mo-spring:cubic-bezier(.34,1.3,.64,1)}
@@ -116,6 +116,10 @@
116
116
  .slm-ch-selnum.bump{animation:slm-ch-bump var(--slm-mo-base) var(--slm-mo-spring)}
117
117
  .slm-ch-row2{display:flex;gap:8px;margin-top:8px}
118
118
  .slm-ch-row2 .slm-btn{flex:1;min-width:0}
119
+ .slm-ch-price-summary{display:flex;align-items:center;gap:10px;padding:11px;border:1px solid var(--slm-line);
120
+ border-radius:10px;background:var(--slm-surface);font-size:11.5px;line-height:1.45;color:var(--slm-muted)}
121
+ .slm-ch-price-summary span{flex:1;min-width:0}
122
+ .slm-ch-price-summary .slm-btn{flex:none;min-height:36px;padding:7px 10px}
119
123
  /* distribute routes \u2014 four choices, each with the one sentence that explains it.
120
124
  The current one is NAMED in its own card, never signalled by colour alone. */
121
125
  .slm-ch-dist{display:flex;flex-direction:column;gap:6px;padding:12px;margin-bottom:8px;border:1px solid var(--slm-line);
@@ -167,6 +171,14 @@
167
171
  border-radius:10px;background:rgba(244,183,64,.06);font-family:ui-monospace,Menlo,monospace;font-size:11px;
168
172
  overflow:hidden;white-space:nowrap;text-overflow:ellipsis}
169
173
  .slm-ch-err{color:#f1a4a6;font-size:11.5px;margin-top:6px}
174
+ .slm-ch-price-list{display:flex;flex-direction:column;gap:7px}
175
+ .slm-ch-price-row{display:grid;grid-template-columns:minmax(0,1fr) minmax(100px,132px);align-items:center;gap:12px;
176
+ padding:9px 0;border-bottom:1px solid var(--slm-line)}
177
+ .slm-ch-price-row:last-child{border-bottom:0}
178
+ .slm-ch-price-row>span{min-width:0;display:flex;flex-direction:column;gap:3px}
179
+ .slm-ch-price-row b{font-size:12.5px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
180
+ .slm-ch-price-row small{font-size:10.5px;color:var(--slm-muted);font-weight:500}
181
+ .slm-ch-price-row .slm-input{margin:0;text-align:right;font-variant-numeric:tabular-nums}
170
182
 
171
183
  /* buyer links \u2014 STATUS only; there is no Copy control on this card */
172
184
  .slm-ch-link{padding:10px 11px;border:1px solid var(--slm-line);border-radius:10px;background:var(--slm-surface);
@@ -232,11 +244,6 @@
232
244
  .slm-ch-grabbar{width:42px;height:4px;border-radius:2px;background:rgba(255,255,255,.22);margin:0 auto}
233
245
  .slm.compact .slm-ch-staged{bottom:auto;top:8px}
234
246
  .slm.compact .slm-btn,.slm.compact .slm-ch-row,.slm.compact .slm-ch-viewseg button{min-height:44px}
235
- .slm-tools{display:none}
236
- .slm.compact .slm-tools{display:block;width:100%;padding:9px 13px;min-height:44px;border:1px solid var(--slm-line);
237
- border-radius:10px;background:var(--slm-surface);color:var(--slm-text);font-size:13px;font-weight:800}
238
- .slm.compact .slm-modes{display:none}
239
-
240
247
  @media (prefers-reduced-motion:reduce){
241
248
  .slm-ch-layer,.slm-ch-banner,.slm-ch-staged,.slm-ch-row,.slm.compact.ch-sheet .slm-rail,
242
249
  .slm-ch-meter i,.slm-ch-radio{transition:none!important}
@@ -246,19 +253,19 @@
246
253
  .slm-ch-staged.shake{outline:2px solid #e5484d;outline-offset:2px}
247
254
  .slm-ch-staged.done{outline:2px solid #5bd39b;outline-offset:2px}
248
255
  }
249
- `});var pt={};Fe(pt,{CHANNELS_CSS:()=>ct,ChannelsMode:()=>ne,bucketRowsHtml:()=>W});var Vt,ht,T,ne,Oe=j(()=>{"use strict";Se();ae();rt();Le();dt();Le();Vt=3e4,ht=300,T=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=ht;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})},Vt),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??L),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 f&&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 o of i.allocations)P(o.channelId)||t.set(o.label,o.channelId);if(this.assignmentVersion=i.assignmentVersion,!i.nextAfterLabel)break;s=i.nextAfterLabel}e!==void 0&&e!==this.listSeq||(this.allocation=t)}channelById(e){if(P(e))return{id:L,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 pe(s??{id:e,name:"?",marker:null,color:null},t)}assignableChannels(){return[{id:L,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=me({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=`
256
+ `});var pt={};qe(pt,{CHANNELS_CSS:()=>ct,ChannelsMode:()=>ne,bucketRowsHtml:()=>W});var Vt,ht,A,ne,ze=N(()=>{"use strict";Se();ae();rt();Le();dt();Le();Vt=3e4,ht=300,A=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=ht;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})},Vt),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??C),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 f&&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)P(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(P(e))return{id:C,name:this.list?.publicSale?.name??T,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 pe(s??{id:e,name:"?",marker:null,color:null},t)}assignableChannels(){return[{id:C,name:this.list?.publicSale.name??T},...(this.list?.channels??[]).filter(e=>e.state!=="archived").map(e=>({id:e.id,name:e.name}))]}currentPlan(){let e=this.host.selectionLabels(),t=me({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=`
250
257
  <canvas class="slm-ch-canvas" data-ch="canvas" aria-hidden="true"></canvas>
251
258
  <div class="slm-ch-banner" data-ch="banner" role="status"></div>
252
259
  <div class="slm-ch-staged" data-ch="staged" role="group" aria-label="Staged channel changes"></div>
253
- <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||lt({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>T,o=t.skippedHeld.count+t.skippedBooked.count,l=[`<b>${e.length.toLocaleString()}</b> selected`,`<b>+${n.toLocaleString()}</b> to ${h(s)}`];t.alreadyInTarget.count&&l.push(`<b>${t.alreadyInTarget.count.toLocaleString()}</b> already in`),o&&l.push(`<b>${o.toLocaleString()}</b> can't move now`),this.setStaged(`
254
- <span>${l.join(" \xB7 ")}</span>
260
+ <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||lt({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)??T,n=K(t),i=e.length>A,a=t.skippedHeld.count+t.skippedBooked.count,o=[`<b>${e.length.toLocaleString()}</b> selected`,`<b>+${n.toLocaleString()}</b> to ${h(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(`
261
+ <span>${o.join(" \xB7 ")}</span>
255
262
  <span class="grow"></span>
256
263
  <button type="button" class="drop" data-ch-act="discard">Discard</button>
257
264
  <button type="button" class="go" data-ch-act="review"${i?" disabled":""}>
258
- ${i?`Maximum ${T.toLocaleString()} seats`:"Review changes"}
259
- </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:""},o=s==null?"":` \xB7 ${s.toLocaleString()} ${s===1?"seat":"seats"} available now`;n.innerHTML=`<span class="dot" style="background:${h(i.color)}"></span>
260
- Previewing buyer access \xB7 ${h(t)}${o} \xB7 read-only
261
- <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:L]}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(P)}),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 f?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>
265
+ ${i?`Maximum ${A.toLocaleString()} seats`:"Review changes"}
266
+ </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:${h(i.color)}"></span>
267
+ Previewing buyer access \xB7 ${h(t)}${a} \xB7 read-only
268
+ <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:C]}this.loadPreview()}this.paintRail(),this.paintOverlay(),this.paintStagedBar(),this.onInteractionChange?.()}async loadPreview(){let e=[...this.previewAudience],t=e.map(s=>this.nameOf(s)??T).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(P)}),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 f?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>
262
269
  <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>
263
270
  <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>
264
271
  <div class="slm-ch-alert err" role="alert" data-ch-state="list-error"><span>\u26A0</span>
@@ -277,14 +284,14 @@
277
284
  <div class="slm-ch-mapnav-head"><span>${e?`Viewing ${h(e)}`:"Section overview"}</span>
278
285
  <button type="button" data-ch-act="sections">All sections</button></div>
279
286
  ${n}
280
- </div>`}countsHtml(e,t){let s=(n,i,o,l="")=>{let r=this.lastCounts.get(`${t}:${n}`),d=r!=null&&r!==i?" bump":"";return this.lastCounts.set(`${t}:${n}`,i),`<span class="${l}"><b class="${d.trim()}">${i.toLocaleString()}</b> ${o}</span>`};return`<span class="slm-ch-counts">
287
+ </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">
281
288
  ${s("allocated",e.allocated,"allocated")}
282
289
  ${s("free",e.free,"free","free")}
283
290
  ${s("booked",e.booked,"sold")}
284
291
  ${e.held?s("held",e.held,"held"):""}
285
- </span>`}channelRowHtml(e,t={}){let s=this.markerFor(e.id),n=t.builtin?"builtin":e.state,i=e.state==="paused"||e.state==="archived"?" dim":"",o=!t.builtin&&this.caps.manage&&this.detailChannelId!==e.id,l=`slm-ch-row${t.builtin?" public":""}${e.state==="archived"?" archived":""}${this.detailChannelId===e.id?" on":""}${o?" open":""}`,r=!t.builtin&&this.caps.manage?`<button type="button" class="slm-ch-more" data-ch-menu="${h(e.id)}"
286
- aria-label="More actions for ${h(e.name)}" aria-haspopup="dialog">\u22EF</button>`:"",d=o?` role="button" tabindex="0" data-ch-open="${h(e.id)}"
287
- aria-label="Open ${h(e.name)}"`:"";return`<div class="${l}"${d}>
292
+ </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="${h(e.id)}"
293
+ aria-label="More actions for ${h(e.name)}" aria-haspopup="dialog">\u22EF</button>`:"",d=a?` role="button" tabindex="0" data-ch-open="${h(e.id)}"
294
+ aria-label="Open ${h(e.name)}"`:"";return`<div class="${o}"${d}>
288
295
  <span class="slm-ch-head">
289
296
  <span class="slm-ch-mk${i}" style="background:${h(s.color)}" aria-hidden="true">${h(s.letter)}</span>
290
297
  <span class="slm-ch-name">${h(e.name)}</span>
@@ -293,13 +300,13 @@
293
300
  </span>
294
301
  ${this.countsHtml(e.counts,e.id||"public")}
295
302
  ${t.builtin?"":`<span class="slm-ch-access">${h(fe(e.access))}</span>`}
296
- </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>`,o=this.caps.manage?'<button type="button" class="slm-btn ghost" style="width:100%" data-ch-act="create">+ Create channel</button>':"",l=this.caps.manage?"":'<p class="slm-note">You can see how inventory is allocated. Changing it needs channel-management permission.</p>';return`
303
+ </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 ghost" style="width:100%" data-ch-act="create">+ Create 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`
297
304
  <p class="slm-eyebrow">Sales channels</p>
298
305
  <p class="slm-hint">Channel colours and names are only visible to organizers, never to buyers.</p>
299
306
  <div class="slm-ch-list">${n}</div>
300
307
  ${i}
308
+ ${a}
301
309
  ${o}
302
- ${l}
303
310
  ${this.assignEntryHtml()}
304
311
  <p class="slm-note" style="margin-top:10px">
305
312
  <button type="button" class="slm-linkbtn" data-ch-act="toggle-archived" aria-pressed="${this.showArchived}"
@@ -308,7 +315,7 @@
308
315
  <button type="button" class="slm-btn ghost" style="width:100%;margin-top:8px"
309
316
  data-ch-act="assign-open" aria-expanded="false">Assign seats to a channel</button>
310
317
  <p class="slm-note">Move whole sections, rows, a dragged area or single seats out of public sale
311
- and into a channel. Nothing moves until you review and apply.</p>`:""}assignmentToolsHtml(e={}){let t=this.assignableChannels().map(l=>`<option value="${h(l.id)}"${l.id===this.targetChannelId?" selected":""}>${h(l.name)}</option>`).join(""),s=this.host.sections().length?'<button type="button" class="slm-btn ghost" data-ch-act="pick-sections">Sections</button>':"",n=this.assignmentRows().length?'<button type="button" class="slm-btn ghost" data-ch-act="pick-rows">Rows</button>':"",i=this.mapIntent==="assign"?"slm-btn":"slm-btn ghost";return`
318
+ and into a channel. Nothing moves until you review and apply.</p>`:""}assignmentToolsHtml(e={}){let t=this.assignableChannels().map(o=>`<option value="${h(o.id)}"${o.id===this.targetChannelId?" selected":""}>${h(o.name)}</option>`).join(""),s=this.host.sections().length?'<button type="button" class="slm-btn ghost" data-ch-act="pick-sections">Sections</button>':"",n=this.assignmentRows().length?'<button type="button" class="slm-btn ghost" data-ch-act="pick-rows">Rows</button>':"",i=this.mapIntent==="assign"?"slm-btn":"slm-btn ghost";return`
312
319
  <p class="slm-eyebrow">${e.collapsible?`<button type="button" class="slm-linkbtn" data-ch-act="assign-close"
313
320
  aria-expanded="true" style="float:right;font-weight:800">Done</button>`:""}Assign inventory</p>
314
321
  <div class="slm-field">
@@ -328,16 +335,16 @@
328
335
  multiple rows, a dragged area, or individual seats.</p>`}selectionRailHtml(e){let t=ue(e,this.allocation,this.list),s=this.conflict?`<div class="slm-ch-alert err" role="alert"><span>\u26A0</span>
329
336
  <span><b>Assignments changed while you were editing.</b> Nothing was applied.
330
337
  Your ${e.length.toLocaleString()}-seat selection is kept.
331
- <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>T,o=t.map(l=>{let r=this.markerFor(l.channelId);return`<div class="slm-ch-selsrc-row">
338
+ <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>A,a=t.map(o=>{let r=this.markerFor(o.channelId);return`<div class="slm-ch-selsrc-row">
332
339
  <span class="mk" style="background:${h(r.color)}" aria-hidden="true">${h(r.letter)}</span>
333
- <b>${l.count.toLocaleString()}</b><span>${h(l.name)}</span></div>`}).join("");return`
340
+ <b>${o.count.toLocaleString()}</b><span>${h(o.name)}</span></div>`}).join("");return`
334
341
  ${s}
335
342
  ${this.assignmentToolsHtml()}
336
343
  <div class="slm-selbar"><span class="slm-selnum slm-ch-selnum${n}">${e.length.toLocaleString()}</span>
337
344
  <span class="slm-sellabel">selected</span></div>
338
- <div class="slm-ch-selsrc" aria-live="polite" aria-label="Selection sources">${o}</div>
345
+ <div class="slm-ch-selsrc" aria-live="polite" aria-label="Selection sources">${a}</div>
339
346
  ${i?`<div class="slm-ch-alert warn" role="alert"><span>\u2139</span><span>
340
- <b>This selection is too large to apply at once.</b> Choose at most ${T.toLocaleString()}
347
+ <b>This selection is too large to apply at once.</b> Choose at most ${A.toLocaleString()}
341
348
  seats, for example by splitting the venue into row groups.</span></div>`:""}
342
349
  <p class="slm-note">Changes are staged \u2014 nothing moves until you review and apply.
343
350
  Seats in checkout or already sold are never moved.</p>
@@ -347,7 +354,7 @@
347
354
  </div>
348
355
  <p class="slm-note">The seat list offers the same selection with checkboxes for keyboard and screen-reader use.</p>`}detailRailHtml(e){let t=`<p class="slm-eyebrow">
349
356
  <button type="button" class="slm-linkbtn" data-ch-act="back" style="text-align:left">\u2039 All channels</button>
350
- </p>`,s=this.list?.channels.find(o=>o.id===e);if(!s)return`${t}
357
+ </p>`,s=this.list?.channels.find(r=>r.id===e);if(!s)return`${t}
351
358
  <div class="slm-ch-alert warn" role="status" data-ch-state="detail-gone"><span>\u2139</span>
352
359
  <span><b>This channel is no longer on this event.</b> It was archived or removed while you had it open.
353
360
  ${this.showArchived?"":"Archived channels are hidden \u2014 use \u201CShow archived\u201D on the list to see it."}</span></div>`;let n=this.caps.manage?`
@@ -357,23 +364,30 @@
357
364
  <button type="button" class="slm-btn ghost" data-ch-act="pause">${s.state==="paused"?"Resume":"Pause"}</button>
358
365
  <button type="button" class="slm-btn ghost" data-ch-act="archive">Archive\u2026</button>
359
366
  </div>
360
- <p class="slm-note">Archive returns the allocation to a destination you choose. Nothing is ever deleted silently.</p>`:"",i=this.caps.manage?this.distributeHtml(s):"";return`
367
+ <p class="slm-note">Archive returns the allocation to a destination you choose. Nothing is ever deleted silently.</p>`:"",i=this.caps.manage?this.distributeHtml(s):"",a=s.priceOverrides?.length??0,o=this.caps.manage&&this.host.api.updateChannelPricing?`
368
+ <p class="slm-eyebrow" style="margin-top:14px">Prices</p>
369
+ <div class="slm-ch-price-summary">
370
+ <span>${a?`${a.toLocaleString()} custom price${a===1?"":"s"} override the event price for this channel.`:"This channel uses the event prices."}</span>
371
+ <button type="button" class="slm-btn ghost" data-ch-act="pricing">Edit prices</button>
372
+ </div>
373
+ <p class="slm-note">Only buyers admitted to this channel see and pay these prices. Existing holds keep the price already promised.</p>`:"";return`
361
374
  ${t}
362
375
  <p class="slm-eyebrow">Channel \xB7 ${h(s.name)}</p>
363
376
  <div class="slm-ch-list">${this.channelRowHtml(s)}</div>
377
+ ${o}
364
378
  ${i}
365
- ${n}`}distributeHtml(e){let t=e.access?.intent??"none",s=e.access?.hasActiveGrants===!0,n=this.linksState!=="unsupported",i=this.links.some(te),o=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.",l=(r,d,c,p)=>{let g=r===t;return`<div class="slm-ch-dist${g?" on":""}" data-ch-route="${h(r)}">
366
- <b>${h(O(r))}${g?'<span class="cur">Current route</span>':""}</b>
379
+ ${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,p)=>{let b=r===t;return`<div class="slm-ch-dist${b?" on":""}" data-ch-route="${h(r)}">
380
+ <b>${h(z(r))}${b?'<span class="cur">Current route</span>':""}</b>
367
381
  <span class="why">${h(ye(r))}</span>
368
- ${g&&!c?"":`<button type="button" class="slm-btn${p&&!g?"":" ghost"}"
382
+ ${b&&!c?"":`<button type="button" class="slm-btn${p&&!b?"":" ghost"}"
369
383
  data-ch-act="${h(d)}">${h(c)}</button>`}
370
384
  </div>`};return`
371
385
  <p class="slm-eyebrow" style="margin-top:14px">Distribute</p>
372
- <p class="slm-hint">${h(o)}</p>
373
- ${n?l("hosted_link","link-create",i?"Create another buyer link":"Create buyer link",!0):""}
374
- ${l("server","embed-code",t==="server"?"Get embed code":"Use a website or app",!1)}
375
- ${l("internal","route-internal",t==="internal"?"":"Hand to your staff",!1)}
376
- ${l("none","route-none",t==="none"?"":"Keep as reserve",!1)}
386
+ <p class="slm-hint">${h(a)}</p>
387
+ ${n?o("hosted_link","link-create",i?"Create another buyer link":"Create buyer link",!0):""}
388
+ ${o("server","embed-code",t==="server"?"Get embed code":"Use a website or app",!1)}
389
+ ${o("internal","route-internal",t==="internal"?"":"Hand to your staff",!1)}
390
+ ${o("none","route-none",t==="none"?"":"Keep as reserve",!1)}
377
391
  ${this.hostedLinksHtml()}
378
392
  ${t==="server"?at:""}`}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 f?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>
379
393
  <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>
@@ -384,8 +398,8 @@
384
398
  <p class="slm-note">A link is shown once, when you create it. SeatLayer keeps only a fingerprint of it, so it
385
399
  can never be shown again \u2014 if a link is lost, rotate it and send the fresh one.</p>`:""}linkCardHtml(e){let t=we(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">${h(r.k)}</span>
386
400
  <span class="v">${h(r.v)}</span></div>`).join(""),i=e.activeSessions?`<div class="slm-ch-lkrow"><span class="k">Buyers inside now</span>
387
- <span class="v">${e.activeSessions.toLocaleString()}</span></div>`:"",o=e.lastRedeemedAt?`<div class="slm-ch-lkrow"><span class="k">Last opened</span>
388
- <span class="v">${h(new Date(e.lastRedeemedAt).toLocaleString())}</span></div>`:"",l=this.caps.manage&&te(e)?`<div class="slm-ch-row2">
401
+ <span class="v">${e.activeSessions.toLocaleString()}</span></div>`:"",a=e.lastRedeemedAt?`<div class="slm-ch-lkrow"><span class="k">Last opened</span>
402
+ <span class="v">${h(new Date(e.lastRedeemedAt).toLocaleString())}</span></div>`:"",o=this.caps.manage&&te(e)?`<div class="slm-ch-row2">
389
403
  <button type="button" class="slm-btn ghost" data-ch-rotate="${h(e.id)}">Rotate</button>
390
404
  <button type="button" class="slm-btn ghost" data-ch-revoke="${h(e.id)}">Revoke</button>
391
405
  </div>`:"";return`<div class="slm-ch-link">
@@ -396,16 +410,16 @@
396
410
  <div class="slm-ch-meter" role="img"
397
411
  aria-label="${e.redemptions.toLocaleString()} of ${e.maxRedemptions.toLocaleString()} redemptions used">
398
412
  <i style="width:${s}%"></i></div>
399
- ${n}${i}${o}
413
+ ${n}${i}${a}
400
414
  <div class="slm-ch-lkrow"><span class="k">The URL</span>
401
415
  <span class="v">Revealed once at creation \u2014 not recoverable</span></div>
402
- ${l}
403
- </div>`}previewRailHtml(){let e=[{id:L,name:this.list?.publicSale.name??A},...(this.list?.channels??[]).filter(p=>p.state!=="archived").map(p=>({id:p.id,name:p.name}))],t=this.previewAudience[0]??L,s=e.map(p=>`<option value="${h(p.id)}"${p.id===t?" selected":""}>${h(p.name)}</option>`).join(""),n=this.previewState==="unsupported"?`<div class="slm-ch-alert warn" data-ch-state="preview-unsupported"><span>\u2139</span>
416
+ ${o}
417
+ </div>`}previewRailHtml(){let e=[{id:C,name:this.list?.publicSale.name??T},...(this.list?.channels??[]).filter(p=>p.state!=="archived").map(p=>({id:p.id,name:p.name}))],t=this.previewAudience[0]??C,s=e.map(p=>`<option value="${h(p.id)}"${p.id===t?" selected":""}>${h(p.name)}</option>`).join(""),n=this.previewState==="unsupported"?`<div class="slm-ch-alert warn" data-ch-state="preview-unsupported"><span>\u2139</span>
404
418
  <span><b>Preview needs a newer server.</b> Allocation management works normally;
405
- 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>':"",o=this.previewState==="error"?`<div class="slm-ch-alert err" role="alert" data-ch-state="preview-error"><span>\u26A0</span>
419
+ 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>
406
420
  <span><b>Couldn't load the buyer preview.</b> Nothing is wrong with this audience's seats \u2014
407
421
  the simulation itself failed to load.
408
- <button type="button" data-ch-act="preview-retry">Try again</button></span></div>`:"",l=this.previewProjection?.available===!1?`<div class="slm-ch-alert warn" role="status"><span>\u23F8</span>
422
+ <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>
409
423
  <span><b>This private sale is not available.</b> ${h((this.previewProjection.unavailable??[]).map(p=>`${this.nameOf(p.channelId)??"This channel"} is ${p.state}`).join("; ")||"The audience cannot buy right now")}.
410
424
  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>
411
425
  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=P(t)?"":`
@@ -421,13 +435,13 @@
421
435
  ${c}
422
436
  <p class="slm-hint">This is the same projection the buyer SDK receives for this audience \u2014 not a local
423
437
  approximation. It is read-only: clicks open seat details, and no holds are created.</p>
424
- ${i}${o}${n}${l}
438
+ ${i}${a}${n}${o}
425
439
  <div class="slm-ch-legend">
426
440
  <div class="r"><span class="sw" style="background:#6e7bff"></span> Eligible &amp; free \u2014 buyable by this audience</div>
427
441
  <div class="r"><span class="sw" style="background:#3a4051"></span> Unavailable to this audience (one neutral state)</div>
428
442
  <div class="r"><span class="sw" style="background:#22a06b"></span> Sold \u2014 same as any buyer sees</div>
429
443
  </div>
430
- ${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(o=>{o.addEventListener("click",()=>this.setView(o.dataset.chView))}),e.querySelectorAll("[data-ch-map]").forEach(o=>{o.addEventListener("click",()=>{this.mapIntent=o.dataset.chMap==="assign"?"assign":"pan",this.mapIntent==="assign"&&(this.assignOpen=!0),this.paintRail(),this.onInteractionChange?.()})}),e.querySelectorAll("[data-ch-open]").forEach(o=>{let l=()=>this.openChannel(o.dataset.chOpen);o.addEventListener("click",l),o.addEventListener("keydown",r=>{r.key!=="Enter"&&r.key!==" "&&r.key!=="Spacebar"||(r.preventDefault(),l())})}),e.querySelectorAll("[data-ch-menu]").forEach(o=>{o.addEventListener("click",l=>{l.stopPropagation(),this.openDialog({kind:"menu",channelId:o.dataset.chMenu})}),o.addEventListener("keydown",l=>{l.stopPropagation()})}),e.querySelectorAll("[data-ch-rotate]").forEach(o=>{o.addEventListener("click",()=>this.openDialog({kind:"linkRotate",channelId:this.detailChannelId,linkId:o.dataset.chRotate}))}),e.querySelectorAll("[data-ch-revoke]").forEach(o=>{o.addEventListener("click",()=>this.openDialog({kind:"linkRevoke",channelId:this.detailChannelId,linkId:o.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(o=>{o.addEventListener("click",()=>this.railAction(o.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"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.paintRail();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(`
444
+ ${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.paintRail();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(`
431
445
  <h3 id="slm-ch-dlg-title">${h(e)}</h3>
432
446
  <div class="slm-field">
433
447
  <label for="slm-ch-choice">Choose one</label>
@@ -438,7 +452,7 @@
438
452
  <div class="foot">
439
453
  <button type="button" class="quiet" data-ch-close>Cancel</button>
440
454
  <button type="button" class="slm-btn" data-ch-confirm>Select</button>
441
- </div>`,n=>{n.querySelector("[data-ch-confirm]")?.addEventListener("click",()=>{let o=n.querySelector("#slm-ch-choice")?.value;this.closeDialog(),o&&s(o)})})}renderScopeDialog(e){let t=e.scope==="rows"?"rows":"sections",n=(t==="sections"?this.host.sections().map(l=>({id:l.id,label:l.label,group:"Sections",labels:this.host.labelsInSection(l.id)})):this.assignmentRows().map(l=>({id:l.id,label:l.label,group:l.sectionLabel,labels:l.labels}))).filter(l=>l.labels.length>0),i=new Map;for(let l of n){let r=i.get(l.group)??[];r.push(l),i.set(l.group,r)}if(t==="rows"){let l=[...i.entries()];this.renderScrim(`
455
+ </div>`,n=>{n.querySelector("[data-ch-confirm]")?.addEventListener("click",()=>{let a=n.querySelector("#slm-ch-choice")?.value;this.closeDialog(),a&&s(a)})})}renderScopeDialog(e){let t=e.scope==="rows"?"rows":"sections",n=(t==="sections"?this.host.sections().map(o=>({id:o.id,label:o.label,group:"Sections",labels:this.host.labelsInSection(o.id)})):this.assignmentRows().map(o=>({id:o.id,label:o.label,group:o.sectionLabel,labels:o.labels}))).filter(o=>o.labels.length>0),i=new Map;for(let o of n){let r=i.get(o.group)??[];r.push(o),i.set(o.group,r)}if(t==="rows"){let o=[...i.entries()];this.renderScrim(`
442
456
  <h3 id="slm-ch-dlg-title">Add multiple rows</h3>
443
457
  <p class="sub">Sections stay collapsed for speed. Select a whole section, expand only the rows you need, or search across every row.</p>
444
458
  <div class="slm-ch-scopebar">
@@ -451,21 +465,21 @@
451
465
  <div class="foot">
452
466
  <button type="button" class="quiet" data-ch-close>Cancel</button>
453
467
  <button type="button" class="slm-btn" data-ch-add-scope disabled>Add seats</button>
454
- </div>`,r=>{let d=new Map(n.map(y=>[y.id,y])),c=new Set,p=new Set,g=new Set(this.host.selectionLabels()),w=r.querySelector("[data-ch-add-scope]"),m=r.querySelector("[data-ch-error]"),u=r.querySelector("[data-ch-scope-list]"),v=r.querySelector("[data-ch-scope-search]"),H=r.querySelector("[data-ch-scope-summary]"),_=r.querySelector("[data-ch-scope-filter]"),F=200,I="",S=()=>{let y=new Set(g);for(let B of c)for(let D of d.get(B)?.labels??[])y.add(D);return y},x=()=>{let y=S(),B=y.size-g.size,D=y.size>T;w.disabled=B===0||D,w.textContent=D?`Maximum ${T.toLocaleString()} seats`:`Add ${B.toLocaleString()} seat${B===1?"":"s"}`,m.hidden=!D,m.textContent=D?`That would make ${y.size.toLocaleString()} selected seats. Choose fewer rows or sections.`:"",H.textContent=`${c.size.toLocaleString()} row${c.size===1?"":"s"} \xB7 ${B.toLocaleString()} seat${B===1?"":"s"} added`},k=()=>{let y=[],B=0,D=0;l.forEach(([E,R],G)=>{let N=E.toLocaleLowerCase(),V=I?R.filter(M=>`${N} ${M.label.toLocaleLowerCase()}`.includes(I)):R;if(I&&!V.length)return;B+=V.length;let _e=R.every(M=>c.has(M.id)),mt=!_e&&R.some(M=>c.has(M.id)),X=!!I||p.has(G),bt=Math.max(0,F-D),Q=X?V.slice(0,bt):[];D+=Q.length;let gt=R.reduce((M,vt)=>M+vt.labels.length,0);y.push(`<div class="slm-ch-scopegroup">
455
- <button type="button" class="slm-ch-groupcheck" role="checkbox" aria-checked="${_e?"true":mt?"mixed":"false"}"
456
- aria-label="Select all ${R.length.toLocaleString()} rows in ${h(E)}" data-ch-scope-group="${G}">
457
- <span class="box" aria-hidden="true">\u2713</span><span>${h(E)}</span>
468
+ </div>`,r=>{let d=new Map(n.map(k=>[k.id,k])),c=new Set,p=new Set,b=new Set(this.host.selectionLabels()),y=r.querySelector("[data-ch-add-scope]"),g=r.querySelector("[data-ch-error]"),m=r.querySelector("[data-ch-scope-list]"),v=r.querySelector("[data-ch-scope-search]"),B=r.querySelector("[data-ch-scope-summary]"),F=r.querySelector("[data-ch-scope-filter]"),q=200,E="",S=()=>{let k=new Set(b);for(let H of c)for(let D of d.get(H)?.labels??[])k.add(D);return k},x=()=>{let k=S(),H=k.size-b.size,D=k.size>A;y.disabled=H===0||D,y.textContent=D?`Maximum ${A.toLocaleString()} seats`:`Add ${H.toLocaleString()} seat${H===1?"":"s"}`,g.hidden=!D,g.textContent=D?`That would make ${k.size.toLocaleString()} selected seats. Choose fewer rows or sections.`:"",B.textContent=`${c.size.toLocaleString()} row${c.size===1?"":"s"} \xB7 ${H.toLocaleString()} seat${H===1?"":"s"} added`},w=()=>{let k=[],H=0,D=0;o.forEach(([M,R],G)=>{let j=M.toLocaleLowerCase(),V=E?R.filter(I=>`${j} ${I.label.toLocaleLowerCase()}`.includes(E)):R;if(E&&!V.length)return;H+=V.length;let Fe=R.every(I=>c.has(I.id)),mt=!Fe&&R.some(I=>c.has(I.id)),X=!!E||p.has(G),bt=Math.max(0,q-D),Q=X?V.slice(0,bt):[];D+=Q.length;let gt=R.reduce((I,vt)=>I+vt.labels.length,0);k.push(`<div class="slm-ch-scopegroup">
469
+ <button type="button" class="slm-ch-groupcheck" role="checkbox" aria-checked="${Fe?"true":mt?"mixed":"false"}"
470
+ aria-label="Select all ${R.length.toLocaleString()} rows in ${h(M)}" data-ch-scope-group="${G}">
471
+ <span class="box" aria-hidden="true">\u2713</span><span>${h(M)}</span>
458
472
  <span class="meta">${R.length.toLocaleString()} rows \xB7 ${gt.toLocaleString()} seats</span>
459
473
  </button>
460
- <button type="button" class="slm-ch-grouptoggle" aria-expanded="${X}" aria-label="${X?"Hide":"Show"} rows in ${h(E)}"
474
+ <button type="button" class="slm-ch-grouptoggle" aria-expanded="${X}" aria-label="${X?"Hide":"Show"} rows in ${h(M)}"
461
475
  data-ch-scope-toggle="${G}">${X?"Hide":"Show"}</button>
462
- </div>`),y.push(...Q.map(M=>`<button type="button" class="slm-ch-seatitem" role="checkbox"
463
- aria-checked="${c.has(M.id)}" data-ch-scope-id="${h(M.id)}">
464
- <span class="box" aria-hidden="true">\u2713</span><span>${h(M.label)}</span>
465
- <span class="meta">${M.labels.length.toLocaleString()} seat${M.labels.length===1?"":"s"}</span>
466
- </button>`)),X&&V.length>Q.length&&y.push(`<p class="slm-ch-scopehint">${(V.length-Q.length).toLocaleString()} more row${V.length-Q.length===1?"":"s"}. Search to narrow the list.</p>`)}),u.innerHTML=y.join("")||(I?`<div class="slm-ch-scope-empty" data-ch-state="scope-nomatch">No sections or rows match \u201C${h(I)}\u201D.</div>`:`<div class="slm-ch-scope-empty" data-ch-state="scope-empty">This chart has no rows with selectable seats.
467
- Use Drag box or the seat list instead.</div>`),_.textContent=I?`Showing ${D.toLocaleString()} of ${B.toLocaleString()} matching rows. Section checkboxes still select every row in that section.`:"Showing section groups. Expand one or search to see rows.",u.querySelectorAll("[data-ch-scope-group]").forEach(E=>E.addEventListener("click",()=>{let R=l[Number(E.dataset.chScopeGroup)]?.[1]??[],G=R.every(N=>c.has(N.id));for(let N of R)G?c.delete(N.id):c.add(N.id);k(),x()})),u.querySelectorAll("[data-ch-scope-toggle]").forEach(E=>E.addEventListener("click",()=>{let R=Number(E.dataset.chScopeToggle);p.has(R)?p.delete(R):p.add(R),k()})),u.querySelectorAll("[data-ch-scope-id]").forEach(E=>E.addEventListener("click",()=>{let R=E.dataset.chScopeId;c.has(R)?c.delete(R):c.add(R),k(),x()}))};v.addEventListener("input",()=>{I=v.value.trim().toLocaleLowerCase(),k(),x()}),w.addEventListener("click",()=>{let y=[...S()];!c.size||y.length>T||(this.closeDialog(),this.host.selectByLabels(y))}),k(),x()});return}let o=[...i.entries()].map(([l,r])=>`
468
- <div class="slm-ch-seatgroup"><span>${h(l)}</span></div>
476
+ </div>`),k.push(...Q.map(I=>`<button type="button" class="slm-ch-seatitem" role="checkbox"
477
+ aria-checked="${c.has(I.id)}" data-ch-scope-id="${h(I.id)}">
478
+ <span class="box" aria-hidden="true">\u2713</span><span>${h(I.label)}</span>
479
+ <span class="meta">${I.labels.length.toLocaleString()} seat${I.labels.length===1?"":"s"}</span>
480
+ </button>`)),X&&V.length>Q.length&&k.push(`<p class="slm-ch-scopehint">${(V.length-Q.length).toLocaleString()} more row${V.length-Q.length===1?"":"s"}. Search to narrow the list.</p>`)}),m.innerHTML=k.join("")||(E?`<div class="slm-ch-scope-empty" data-ch-state="scope-nomatch">No sections or rows match \u201C${h(E)}\u201D.</div>`:`<div class="slm-ch-scope-empty" data-ch-state="scope-empty">This chart has no rows with selectable seats.
481
+ Use Drag box or the seat list instead.</div>`),F.textContent=E?`Showing ${D.toLocaleString()} of ${H.toLocaleString()} matching rows. Section checkboxes still select every row in that section.`:"Showing section groups. Expand one or search to see rows.",m.querySelectorAll("[data-ch-scope-group]").forEach(M=>M.addEventListener("click",()=>{let R=o[Number(M.dataset.chScopeGroup)]?.[1]??[],G=R.every(j=>c.has(j.id));for(let j of R)G?c.delete(j.id):c.add(j.id);w(),x()})),m.querySelectorAll("[data-ch-scope-toggle]").forEach(M=>M.addEventListener("click",()=>{let R=Number(M.dataset.chScopeToggle);p.has(R)?p.delete(R):p.add(R),w()})),m.querySelectorAll("[data-ch-scope-id]").forEach(M=>M.addEventListener("click",()=>{let R=M.dataset.chScopeId;c.has(R)?c.delete(R):c.add(R),w(),x()}))};v.addEventListener("input",()=>{E=v.value.trim().toLocaleLowerCase(),w(),x()}),y.addEventListener("click",()=>{let k=[...S()];!c.size||k.length>A||(this.closeDialog(),this.host.selectByLabels(k))}),w(),x()});return}let a=[...i.entries()].map(([o,r])=>`
482
+ <div class="slm-ch-seatgroup"><span>${h(o)}</span></div>
469
483
  ${r.map(d=>`<button type="button" class="slm-ch-seatitem" role="checkbox"
470
484
  aria-checked="false" data-ch-scope-id="${h(d.id)}">
471
485
  <span class="box" aria-hidden="true">\u2713</span>
@@ -474,17 +488,17 @@
474
488
  </button>`).join("")}`).join("");this.renderScrim(`
475
489
  <h3 id="slm-ch-dlg-title">Add whole sections</h3>
476
490
  <p class="sub">Choose one or more. They are added to the seats already selected on the map.</p>
477
- <div class="slm-ch-seatlist">${o||`<div class="slm-ch-scope-empty" data-ch-state="scope-empty">This chart has no sections with selectable seats.
491
+ <div class="slm-ch-seatlist">${a||`<div class="slm-ch-scope-empty" data-ch-state="scope-empty">This chart has no sections with selectable seats.
478
492
  Use Drag box or the seat list instead.</div>`}</div>
479
493
  <p class="slm-ch-err" data-ch-error hidden></p>
480
494
  <div class="foot">
481
495
  <button type="button" class="quiet" data-ch-close>Cancel</button>
482
496
  <button type="button" class="slm-btn" data-ch-add-scope disabled>Add seats</button>
483
- </div>`,l=>{let r=new Map(n.map(u=>[u.id,u])),d=new Set,c=new Set(this.host.selectionLabels()),p=l.querySelector("[data-ch-add-scope]"),g=l.querySelector("[data-ch-error]"),w=()=>{let u=new Set(c);for(let v of d)for(let H of r.get(v)?.labels??[])u.add(H);return u},m=()=>{let u=w(),v=u.size-c.size,H=u.size>T;p.disabled=v===0||H,p.textContent=H?`Maximum ${T.toLocaleString()} seats`:`Add ${v.toLocaleString()} seat${v===1?"":"s"}`,g.hidden=!H,g.textContent=H?`That would make ${u.size.toLocaleString()} selected seats. Choose fewer rows or sections.`:""};l.querySelectorAll("[data-ch-scope-id]").forEach(u=>{u.addEventListener("click",()=>{let v=u.dataset.chScopeId;d.has(v)?d.delete(v):d.add(v),u.setAttribute("aria-checked",String(d.has(v))),m()})}),p.addEventListener("click",()=>{let u=[...w()];!d.size||u.length>T||(this.closeDialog(),this.host.selectByLabels(u))}),m()})}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==="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(o=>o.id===e.channelId),s=e.intentTo;if(!t||!s||!this.caps.manage){this.closeDialog();return}let{headline:n,consequences:i}=ke(e.switchBlocked);this.renderScrim(`
497
+ </div>`,o=>{let r=new Map(n.map(m=>[m.id,m])),d=new Set,c=new Set(this.host.selectionLabels()),p=o.querySelector("[data-ch-add-scope]"),b=o.querySelector("[data-ch-error]"),y=()=>{let m=new Set(c);for(let v of d)for(let B of r.get(v)?.labels??[])m.add(B);return m},g=()=>{let m=y(),v=m.size-c.size,B=m.size>A;p.disabled=v===0||B,p.textContent=B?`Maximum ${A.toLocaleString()} seats`:`Add ${v.toLocaleString()} seat${v===1?"":"s"}`,b.hidden=!B,b.textContent=B?`That would make ${m.size.toLocaleString()} selected seats. Choose fewer rows or sections.`:""};o.querySelectorAll("[data-ch-scope-id]").forEach(m=>{m.addEventListener("click",()=>{let v=m.dataset.chScopeId;d.has(v)?d.delete(v):d.add(v),m.setAttribute("aria-checked",String(d.has(v))),g()})}),p.addEventListener("click",()=>{let m=[...y()];!d.size||m.length>A||(this.closeDialog(),this.host.selectByLabels(m))}),g()})}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}=ke(e.switchBlocked);this.renderScrim(`
484
498
  <h3 id="slm-ch-dlg-title">Change how ${h(t.name)} reaches buyers?</h3>
485
499
  <p class="sub">${h(n)}</p>
486
500
  <div class="slm-ch-alert warn" role="alert"><span>\u26A0</span><span>
487
- ${i.map(o=>`<span style="display:block;margin-bottom:6px">${h(o)}</span>`).join("")}
501
+ ${i.map(a=>`<span style="display:block;margin-bottom:6px">${h(a)}</span>`).join("")}
488
502
  </span></div>
489
503
  ${e.pendingLink?`<p class="slm-note">Your new buyer link is created as soon as
490
504
  the route changes \u2014 you will not have to fill the form in again.</p>`:""}
@@ -492,9 +506,9 @@
492
506
  <div class="foot">
493
507
  <button type="button" class="quiet" data-ch-close>Leave it as it is</button>
494
508
  <button type="button" class="slm-btn" data-ch-intent-ack${e.busy?" disabled":""}>
495
- ${e.busy?"Changing\u2026":`Change to "${h(O(s))}"`}</button>
496
- </div>`,o=>{o.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"
497
- 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(l=>{l.addEventListener("click",()=>this.closeDialog())}),n.addEventListener("keydown",l=>{if(l.key==="Escape"){l.stopPropagation(),this.closeDialog();return}if(l.key!=="Tab")return;let r=[...i.querySelectorAll('button:not([disabled]),select,input,textarea,a[href],[tabindex]:not([tabindex="-1"])')];if(!r.length)return;let d=r[0],c=r[r.length-1];l.shiftKey&&document.activeElement===d?(l.preventDefault(),c.focus()):!l.shiftKey&&document.activeElement===c&&(l.preventDefault(),d.focus())}),t(i),(i.querySelector("input,select,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(`
509
+ ${e.busy?"Changing\u2026":`Change to "${h(z(s))}"`}</button>
510
+ </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"
511
+ 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('button:not([disabled]),select,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),(i.querySelector("input,select,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=>O(n.marker||n.name,"")),s=J("",t);this.renderScrim(`
498
512
  <h3 id="slm-ch-dlg-title">Create channel</h3>
499
513
  <p class="sub">A named allocation only the right audience can buy from. You'll pick the seats next.</p>
500
514
  <div class="slm-field">
@@ -519,22 +533,22 @@
519
533
  <button type="button" class="quiet" data-ch-close>Cancel</button>
520
534
  <button type="button" class="slm-btn ghost" data-ch-create="plain">Create without allocating</button>
521
535
  <button type="button" class="slm-btn" data-ch-create="allocate">Create and allocate seats</button>
522
- </div>`,n=>{let i=n.querySelector("#slm-ch-name"),o=n.querySelector("[data-ch-marker]");i.addEventListener("input",()=>{let l=J(i.value,t);o.textContent=l.letter,o.style.background=l.color}),n.querySelectorAll("[data-ch-create]").forEach(l=>{l.addEventListener("click",()=>{let r=l.dataset.chCreate==="allocate";this.createChannel(i.value,o.textContent??"",o.style.background,n.querySelector("#slm-ch-ref")?.value??"",r)})})})}async createChannel(e,t,s,n,i){let o=e.trim();if(!o){this.showDialogError("Give the channel a name your team will recognise.");return}try{let l=await this.host.api.createChannel(this.host.eventKey,{name:o,marker:z(t,"")||null,color:s||null,externalRef:n.trim()||null});this.closeDialog(),await this.refresh(),this.targetChannelId=l.channel.id,this.detailChannelId=i?null:l.channel.id,this.announce(`Channel ${o} created with 0 seats allocated.`),this.host.toast(i?`${o} created. Select seats on the map to allocate them.`:`${o} created.`,"ok"),this.paintRail()}catch(l){let r=l instanceof f?l.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(l)}}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,o=this.nameOf(n?.targetChannelId??this.targetChannelId)??A,l=ge(i,o),r=n?n.applied:K(s),d=!n&&t.length>0&&r===0,c=!n&&t.length>T,p=W(l),g=n?'<div class="foot"><button type="button" class="slm-btn" data-ch-close>Done</button></div>':`<div class="foot">
536
+ </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:O(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 f?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)??T,o=ge(i,a),r=n?n.applied:K(s),d=!n&&t.length>0&&r===0,c=!n&&t.length>A,p=W(o),b=n?'<div class="foot"><button type="button" class="slm-btn" data-ch-close>Done</button></div>':`<div class="foot">
523
537
  <button type="button" class="quiet" data-ch-close>Back</button>
524
538
  <button type="button" class="slm-btn" data-ch-apply ${d||c||e.busy?"disabled":""}>
525
539
  ${e.busy?"Applying\u2026":`Apply ${r.toLocaleString()} change${r===1?"":"s"}`}
526
540
  </button>
527
- </div>`,w=!n&&be(s)?'<p class="slm-note">Applying moves inventory out of another private channel. That is the line marked above.</p>':"",m=d?`<div class="slm-ch-alert warn"><span>\u2139</span><span>Nothing in this selection can move right now \u2014
528
- every seat is in a buyer's checkout, already sold, or already in ${h(o)}.</span></div>`:"",u=c?`<div class="slm-ch-alert warn" role="alert"><span>\u2139</span><span><b>Choose fewer seats.</b>
529
- One Apply can cover at most ${T.toLocaleString()} seats.</span></div>`:"";this.renderScrim(`
530
- <h3 id="slm-ch-dlg-title">${n?`Moved ${n.applied.toLocaleString()} seat${n.applied===1?"":"s"} to ${h(o)}`:`Move ${t.length.toLocaleString()} selected seat${t.length===1?"":"s"} to ${h(o)}`}</h3>
541
+ </div>`,y=!n&&be(s)?'<p class="slm-note">Applying moves inventory out of another private channel. That is the line marked above.</p>':"",g=d?`<div class="slm-ch-alert warn"><span>\u2139</span><span>Nothing in this selection can move right now \u2014
542
+ every seat is in a buyer's checkout, already sold, or already in ${h(a)}.</span></div>`:"",m=c?`<div class="slm-ch-alert warn" role="alert"><span>\u2139</span><span><b>Choose fewer seats.</b>
543
+ One Apply can cover at most ${A.toLocaleString()} seats.</span></div>`:"";this.renderScrim(`
544
+ <h3 id="slm-ch-dlg-title">${n?`Moved ${n.applied.toLocaleString()} seat${n.applied===1?"":"s"} to ${h(a)}`:`Move ${t.length.toLocaleString()} selected seat${t.length===1?"":"s"} to ${h(a)}`}</h3>
531
545
  <p class="sub">${n?"These are the exact counts the server applied.":"Every selected seat is in exactly one line below."}</p>
546
+ ${g}
532
547
  ${m}
533
- ${u}
534
548
  ${p||'<div class="slm-empty">Nothing selected.</div>'}
535
- ${w}
549
+ ${y}
536
550
  <p class="slm-ch-err" data-ch-error ${e.error?"":"hidden"}>${h(e.error??"")}</p>
537
- ${g}`,v=>{v.querySelector("[data-ch-apply]")?.addEventListener("click",()=>{this.apply()})}),n&&this.announce(`Applied ${n.applied} change${n.applied===1?"":"s"} to ${o}.`)}async apply(){if(!this.dialog||!this.caps.manage)return;let{labels:e}=this.currentPlan();if(e.length){if(e.length>T){this.showDialogError(`Choose at most ${T.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:P(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 f&&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 f&&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>
551
+ ${b}`,v=>{v.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>A){this.showDialogError(`Choose at most ${A.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:P(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 f&&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 f&&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)??T,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>
538
552
  <span>Assigned <b>${e.applied.toLocaleString()}</b> seat${e.applied===1?"":"s"} to ${h(t)}
539
553
  ${s?` \xB7 ${s.toLocaleString()} skipped`:""}</span>
540
554
  <span class="grow"></span>
@@ -551,7 +565,7 @@
551
565
  <p class="slm-note">Pausing stops new buyer access; checkouts already running can finish.
552
566
  Archiving closes the channel for good and returns its free seats to a destination you choose.
553
567
  Nothing is ever deleted silently.</p>
554
- <div class="foot"><button type="button" class="quiet" data-ch-close>Cancel</button></div>`,n=>{n.querySelectorAll("[data-ch-menu-act]").forEach(i=>{i.addEventListener("click",()=>{let o=i.dataset.chMenuAct;if(o==="open"){this.closeDialog(),this.openChannel(t.id);return}if(o==="rename"){this.openDialog({kind:"rename",channelId:t.id});return}if(o==="archive"){this.openDialog({kind:"archive",channelId:t.id});return}this.closeDialog(),this.togglePause(t.id)})})})}renderRenameDialog(e){let t=this.list?.channels.find(s=>s.id===e.channelId);if(!t){this.closeDialog();return}this.renderScrim(`
568
+ <div class="foot"><button type="button" class="quiet" data-ch-close>Cancel</button></div>`,n=>{n.querySelectorAll("[data-ch-menu-act]").forEach(i=>{i.addEventListener("click",()=>{let a=i.dataset.chMenuAct;if(a==="open"){this.closeDialog(),this.openChannel(t.id);return}if(a==="rename"){this.openDialog({kind:"rename",channelId:t.id});return}if(a==="archive"){this.openDialog({kind:"archive",channelId:t.id});return}this.closeDialog(),this.togglePause(t.id)})})})}renderRenameDialog(e){let t=this.list?.channels.find(s=>s.id===e.channelId);if(!t){this.closeDialog();return}this.renderScrim(`
555
569
  <h3 id="slm-ch-dlg-title">Rename ${h(t.name)}</h3>
556
570
  <p class="sub">Only your team and your reports see this name.</p>
557
571
  <div class="slm-field">
@@ -562,7 +576,24 @@
562
576
  <div class="foot">
563
577
  <button type="button" class="quiet" data-ch-close>Cancel</button>
564
578
  <button type="button" class="slm-btn" data-ch-rename>Save name</button>
565
- </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 f&&i.code==="channel_name_taken"?"That name is already used on this event.":"Couldn't rename the channel."),this.host.onError(i)})})})}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 f&&n.code==="channel_intent_switch_blocked"?(this.openDialog({kind:"intentSwitch",channelId:s,intentTo:e,switchBlocked:n.details}),!1):n instanceof f&&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(l=>l.id===e.channelId);if(!t){this.closeDialog();return}let s=e.archiveBlocked??null,n=!s&&t.counts.held>0,i=this.assignableChannels().filter(l=>l.id!==t.id),o=s?`<div class="slm-ch-alert warn" role="alert"><span>\u23F3</span>
579
+ </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 f&&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??""}`,p=r?.price??a.price??0,b=n.get(c),y=r?`${a.label} \xB7 ${r.name}`:a.label;return`<label class="slm-ch-price-row">
580
+ <span><b>${h(y)}</b><small>Event price ${h(String(p))}</small></span>
581
+ <input class="slm-input" type="number" min="0" max="1000000" step="0.01"
582
+ inputmode="decimal" aria-label="Custom price for ${h(y)}"
583
+ data-ch-price-category="${h(a.key)}" data-ch-price-tier="${h(d??"")}"
584
+ placeholder="${h(String(p))}" value="${b===void 0?"":h(String(b))}"
585
+ ${e.busy?"disabled":""} />
586
+ </label>`})).join("");this.renderScrim(`
587
+ <h3 id="slm-ch-dlg-title">Prices for ${h(t.name)}</h3>
588
+ <p class="sub">Set only the prices that differ for this audience. Leave a field blank to use the event price.</p>
589
+ <div class="slm-ch-price-list">${i||'<p class="slm-empty">This event has no priced categories.</p>'}</div>
590
+ <p class="slm-ch-err" data-ch-error ${e.error?"":"hidden"}>${h(e.error??"")}</p>
591
+ <div class="foot">
592
+ <button type="button" class="quiet" data-ch-close ${e.busy?"disabled":""}>Cancel</button>
593
+ <button type="button" class="slm-btn" data-ch-price-save ${e.busy||!i?"disabled":""}>
594
+ ${e.busy?"Saving\u2026":"Save prices"}
595
+ </button>
596
+ </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 f&&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 f&&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 f&&n.code==="channel_intent_switch_blocked"?(this.openDialog({kind:"intentSwitch",channelId:s,intentTo:e,switchBlocked:n.details}),!1):n instanceof f&&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>
566
597
  <span><b>${(s.heldUnits??s.activeHolds??0).toLocaleString()} seats are in a buyer's checkout right now.</b>
567
598
  Archive is unavailable while seats are held \u2014 try again ${h(ve(s))}.</span></div>`:n?`<div class="slm-ch-alert warn"><span>\u23F3</span>
568
599
  <span>${t.counts.held.toLocaleString()} seats are in a buyer's checkout right now.
@@ -570,11 +601,11 @@
570
601
  <h3 id="slm-ch-dlg-title">Archive ${h(t.name)}</h3>
571
602
  <p class="sub">The channel closes for good. Its seats move to a destination you choose;
572
603
  sales history keeps its attribution.</p>
573
- ${o}
604
+ ${a}
574
605
  <div class="slm-field">
575
606
  <label for="slm-ch-dest">Move the ${t.counts.free.toLocaleString()} remaining free seats to</label>
576
607
  <select class="slm-select" id="slm-ch-dest">
577
- ${i.map(l=>`<option value="${h(l.id)}">${h(l.name)}</option>`).join("")}
608
+ ${i.map(o=>`<option value="${h(o.id)}">${h(o.name)}</option>`).join("")}
578
609
  </select>
579
610
  </div>
580
611
  <p class="slm-note">${t.counts.booked.toLocaleString()} sold seats keep "${h(t.name)}" on their sale
@@ -584,22 +615,22 @@
584
615
  <div class="foot">
585
616
  <button type="button" class="quiet" data-ch-close>Cancel</button>
586
617
  <button type="button" class="slm-btn danger" data-ch-archive ${s?"disabled":""}>Archive channel</button>
587
- </div>`,l=>{l.querySelector("[data-ch-archive]")?.addEventListener("click",()=>{let r=l.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 f&&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 o=this.host.sectionOfLabel(i.label),l=o?.id??"",r=t.get(l)??{label:o?.label??"Other seats",seats:[]};r.seats.push({label:i.label,status:this.host.statusOf(i.label)??"free"}),t.set(l,r)}let n=[...t.entries()].map(([i,o])=>`
618
+ </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 f&&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])=>`
588
619
  <div class="slm-ch-seatgroup">
589
- <span>${h(o.label)}</span>
620
+ <span>${h(a.label)}</span>
590
621
  ${i?`<button type="button" data-ch-section="${h(i)}">Select section</button>`:""}
591
622
  </div>
592
- ${o.seats.map(l=>{let r=this.allocation.get(l.label)??L,d=this.nameOf(r)??A;return`<button type="button" class="slm-ch-seatitem" role="checkbox"
593
- aria-checked="${e.has(l.label)}" data-ch-seat="${h(l.label)}">
623
+ ${a.seats.map(o=>{let r=this.allocation.get(o.label)??C,d=this.nameOf(r)??T;return`<button type="button" class="slm-ch-seatitem" role="checkbox"
624
+ aria-checked="${e.has(o.label)}" data-ch-seat="${h(o.label)}">
594
625
  <span class="box" aria-hidden="true">\u2713</span>
595
- <span>${h(l.label)}</span>
596
- <span class="meta">${h(d)} \xB7 ${h(l.status)}</span>
626
+ <span>${h(o.label)}</span>
627
+ <span class="meta">${h(d)} \xB7 ${h(o.status)}</span>
597
628
  </button>`}).join("")}`).join("");this.renderScrim(`
598
629
  <h3 id="slm-ch-dlg-title">Seat list</h3>
599
630
  <p class="sub">The same selection as the map, with checkboxes. Space or Enter toggles a seat.</p>
600
631
  <div class="slm-ch-seatlist">${n||'<div class="slm-empty">No seats on this chart.</div>'}</div>
601
632
  ${s>this.seatListLimit?'<div class="foot"><button type="button" class="slm-btn ghost" data-ch-more>Show more seats</button></div>':""}
602
- <div class="foot"><button type="button" class="slm-btn" data-ch-close>Done</button></div>`,i=>{i.querySelectorAll("[data-ch-seat]").forEach(o=>{o.addEventListener("click",()=>{let l=o.dataset.chSeat,r=new Set(this.host.selectionLabels());r.has(l)?r.delete(l):r.add(l),this.host.clearSelection(),r.size&&this.host.selectByLabels([...r]),this.renderSeatListDialog()})}),i.querySelectorAll("[data-ch-section]").forEach(o=>{o.addEventListener("click",()=>{this.host.selectSection(o.dataset.chSection),this.renderSeatListDialog()})}),i.querySelector("[data-ch-more]")?.addEventListener("click",()=>{this.seatListLimit+=ht,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(`
633
+ <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+=ht,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(`
603
634
  <h3 id="slm-ch-dlg-title">Create a buyer link for ${h(t.name)}</h3>
604
635
  <p class="sub">Anyone who opens the link can buy from this channel's allocation \u2014 and only from it.
605
636
  You'll see the link once, right after you create it.</p>
@@ -638,9 +669,9 @@
638
669
  <div class="foot">
639
670
  <button type="button" class="quiet" data-ch-close>Cancel</button>
640
671
  <button type="button" class="slm-btn" data-ch-lk-create>Create link</button>
641
- </div>`,s=>{let n=s.querySelector("[data-ch-lk-expiry]"),i=s.querySelector("[data-ch-lk-when-field]"),o=s.querySelector("#slm-ch-lk-when");n.addEventListener("change",()=>{let l=n.value==="custom";i.hidden=!l,l&&!o.value&&(o.value=ot(Date.now()+7*864e5))}),s.querySelector("[data-ch-lk-create]")?.addEventListener("click",()=>{let l=De(s,"#slm-ch-lk-redemptions"),r=De(s,"#slm-ch-lk-quantity");if(l==null||r==null){this.showDialogError("Those two settings need to be whole numbers.");return}let d;if(n.value==="custom"&&(d=Date.parse(o.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:l,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(q(s instanceof f?s:void 0)),s instanceof f||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 f&&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 f&&n.code==="channel_access_intent_forbids"?Y(n.details):"Couldn't set this channel up for buyer links. Try again."),n instanceof f||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>
642
- <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(o=>`<div class="slm-ch-lkrow"><span class="k">${h(o.k)}</span>
643
- <span class="v">${h(o.v)}</span></div>`).join("");this.renderScrim(`
672
+ </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=ot(Date.now()+7*864e5))}),s.querySelector("[data-ch-lk-create]")?.addEventListener("click",()=>{let o=De(s,"#slm-ch-lk-redemptions"),r=De(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(_(s instanceof f?s:void 0)),s instanceof f||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 f&&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 f&&n.code==="channel_access_intent_forbids"?Y(n.details):"Couldn't set this channel up for buyer links. Try again."),n instanceof f||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>
673
+ <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">${h(a.k)}</span>
674
+ <span class="v">${h(a.v)}</span></div>`).join("");this.renderScrim(`
644
675
  <h3 id="slm-ch-dlg-title">Copy this link now</h3>
645
676
  <p class="sub">This is the only time SeatLayer can show it. We keep just a fingerprint, so it cannot be
646
677
  shown again \u2014 if it is lost, rotate the link for a fresh one.</p>
@@ -656,7 +687,7 @@
656
687
  ${i}
657
688
  <div class="foot">
658
689
  <button type="button" class="slm-btn" data-ch-close data-ch-lk-done>I've copied it</button>
659
- </div>`,o=>{let l=o.querySelector("[data-ch-lk-copy]");l?.addEventListener("click",()=>{let r=()=>{l.textContent="Copied",this.announce("Buyer link copied.")},d=typeof navigator>"u"?null:navigator.clipboard;if(d?.writeText){d.writeText(s).then(r,()=>ze(o));return}ze(o)})}),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>
690
+ </div>`,a=>{let o=a.querySelector("[data-ch-lk-copy]");o?.addEventListener("click",()=>{let r=()=>{o.textContent="Copied",this.announce("Buyer link copied.")},d=typeof navigator>"u"?null:navigator.clipboard;if(d?.writeText){d.writeText(s).then(r,()=>Oe(a));return}Oe(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>
660
691
  <span><b>${s.toLocaleString()} buyer${s===1?"":"s"}</b> got in with the current link
661
692
  and still ${s===1?"has":"have"} active access.</span></div>`:"";this.renderScrim(`
662
693
  <h3 id="slm-ch-dlg-title">Rotate the ${h(t.label||"buyer")} link?</h3>
@@ -678,7 +709,7 @@
678
709
  <div class="foot">
679
710
  <button type="button" class="quiet" data-ch-close>Cancel</button>
680
711
  <button type="button" class="slm-btn" data-ch-lk-rotate disabled>Rotate and copy new link</button>
681
- </div>`,i=>{let o=i.querySelector("[data-ch-lk-rotate]");i.querySelectorAll("[data-ch-rot]").forEach(l=>{l.addEventListener("change",()=>{o.disabled=!1})}),o.addEventListener("click",()=>{let l=[...i.querySelectorAll("[data-ch-rot]")].find(r=>r.checked);if(!l){this.showDialogError(q({code:"end_active_sessions_required"}));return}this.rotateLink(e.channelId,t.id,l.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(q(n instanceof f?n:void 0)),n instanceof f||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(`
712
+ </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(_({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 instanceof f?n:void 0)),n instanceof f||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(`
682
713
  <h3 id="slm-ch-dlg-title">Revoke the ${h(t.label||"buyer")} link?</h3>
683
714
  <p class="sub">It stops opening immediately and cannot be restored \u2014 there is no undo, and no way to
684
715
  bring the same URL back. Seats already bought through it keep their sale.</p>
@@ -692,7 +723,7 @@
692
723
  <div class="foot">
693
724
  <button type="button" class="quiet" data-ch-close>Cancel</button>
694
725
  <button type="button" class="slm-btn danger" data-ch-lk-revoke>Revoke link</button>
695
- </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(q(n instanceof f?n:void 0)),n instanceof f||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 Kt={};Fe(Kt,{ACCESS_LINK_DEFAULTS:()=>ee,ChannelsMode:()=>ne,ManageApi:()=>U,ManageApiError:()=>f,PUBLIC_CHANNEL_ID:()=>L,PUBLIC_CHANNEL_NAME:()=>A,SeatManager:()=>Re,accessIntentDescription:()=>ye,accessIntentLabel:()=>O,accessLine:()=>fe,accessLinkBadge:()=>we,accessLinkErrorCopy:()=>q,accessLinkIsLive:()=>te,accessLinkPolicyLines:()=>se,bucketRows:()=>ge,bucketRowsHtml:()=>W,dropReviewRows:()=>it,intentForbidsCopy:()=>Y,intentSwitchBlockedCopy:()=>ke,isPublicChannelId:()=>P,markerLetter:()=>z,markerOf:()=>pe,mutationCount:()=>K,needsMoveConfirmation:()=>be,planAssignment:()=>me,retryAfterCopy:()=>ve,selectionSources:()=>ue,stateBadge:()=>xe,suggestMarker:()=>J});module.exports=xt(Kt);var C=require("@seatlayer/core");ae();var Rt=/^[a-zA-Z0-9._-]+$/;function $t(a){let e;try{e=new URL(a,"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||!Rt.test(n)?null:{eventKey:s,asset:n}}catch{return null}}function At(a){try{return/^\/v1\/events\/[^/]+\/assets(?:\/|$)/.test(new URL(a,"https://seatlayer.invalid").pathname)}catch{return!1}}var oe=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=$t(e);if(!t)return Promise.resolve(At(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(o=>{let l=URL.createObjectURL(o);return this.disposed?(URL.revokeObjectURL(l),null):(this.created.add(l),l)}).catch(o=>{throw this.pending.delete(s),o});return this.pending.set(s,i),i}async prepareRendererChart(e){let t=async i=>{if(!i?.url)return;let o=await this.resolve(i.url);if(!o)throw new Error("organizer_event_asset_scope_mismatch");i.url=o},s=async i=>{for(let o of i){if(o.type!=="decorImage")continue;let l=o,r=await this.resolve(l.href);if(!r)throw new Error("organizer_event_asset_scope_mismatch");l.href=r}},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 je="seatlayer-manager-style",Ue="seatlayer-manager-channels-style",Tt=`
726
+ </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 instanceof f?n:void 0)),n instanceof f||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 Kt={};qe(Kt,{ACCESS_LINK_DEFAULTS:()=>ee,ChannelsMode:()=>ne,ManageApi:()=>U,ManageApiError:()=>f,PUBLIC_CHANNEL_ID:()=>C,PUBLIC_CHANNEL_NAME:()=>T,SeatManager:()=>Re,accessIntentDescription:()=>ye,accessIntentLabel:()=>z,accessLine:()=>fe,accessLinkBadge:()=>we,accessLinkErrorCopy:()=>_,accessLinkIsLive:()=>te,accessLinkPolicyLines:()=>se,bucketRows:()=>ge,bucketRowsHtml:()=>W,dropReviewRows:()=>it,intentForbidsCopy:()=>Y,intentSwitchBlockedCopy:()=>ke,isPublicChannelId:()=>P,markerLetter:()=>O,markerOf:()=>pe,mutationCount:()=>K,needsMoveConfirmation:()=>be,planAssignment:()=>me,retryAfterCopy:()=>ve,selectionSources:()=>ue,stateBadge:()=>xe,suggestMarker:()=>J});module.exports=xt(Kt);var L=require("@seatlayer/core");ae();var Rt=/^[a-zA-Z0-9._-]+$/;function $t(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||!Rt.test(n)?null:{eventKey:s,asset:n}}catch{return null}}function Tt(l){try{return/^\/v1\/events\/[^/]+\/assets(?:\/|$)/.test(new URL(l,"https://seatlayer.invalid").pathname)}catch{return!1}}var oe=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=$t(e);if(!t)return Promise.resolve(Tt(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 Ne="seatlayer-manager-style",Ue="seatlayer-manager-channels-style",At=`
696
727
  /* The floor was 480px, which trapped the cockpit in any host shorter than that:
697
728
  every ancestor here is overflow:hidden, so the bottom of the rail (Create
698
729
  channel, Show archived) was rendered but clipped away by the host and could
@@ -727,6 +758,7 @@
727
758
  .slm-bar{display:grid;grid-template-columns:auto auto auto minmax(0,1fr);align-items:center;column-gap:14px;row-gap:10px;
728
759
  padding:10px 16px;border-bottom:1px solid var(--slm-line);flex:none}
729
760
  .slm-modes{display:inline-flex;background:var(--slm-surface);border:1px solid var(--slm-line);border-radius:999px;padding:3px}
761
+ .slm-tools{display:none}
730
762
  .slm-mode{padding:6px 16px;border-radius:999px;font-weight:700;font-size:13px;color:var(--slm-muted)}
731
763
  .slm-mode.on{background:var(--slm-accent);color:var(--slm-accent-ink)}
732
764
  .slm-live{display:inline-flex;align-items:center;gap:6px;font-size:11px;letter-spacing:.12em;font-weight:800;color:var(--slm-muted)}
@@ -923,13 +955,26 @@
923
955
  .slm-inspect-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:16px 20px;margin-top:18px}
924
956
  .slm-inspect-grid>div{min-width:0}.slm-inspect-grid span{display:block;color:var(--slm-muted);font-size:10px;
925
957
  text-transform:uppercase;letter-spacing:.08em}.slm-inspect-grid b{display:block;margin-top:4px;font-size:13px;line-height:1.35;overflow-wrap:anywhere}
958
+ .slm-categoryassign{display:flex;flex-direction:column;gap:8px}
959
+ .slm-categoryrow{display:grid;grid-template-columns:auto minmax(0,1fr) auto auto;align-items:center;gap:8px;
960
+ padding:9px;border:1px solid var(--slm-line);border-radius:10px;background:var(--slm-surface)}
961
+ .slm-categoryrow>.dot{width:10px;height:10px;border-radius:50%}
962
+ .slm-categorycopy{display:flex;min-width:0;flex-direction:column;gap:2px}.slm-categorycopy b{font-size:12px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
963
+ .slm-categorycopy small{font-size:10px;color:var(--slm-muted)}.slm-categoryrow .slm-btn{width:auto;padding:6px 9px}
964
+ .slm-tablelist{display:flex;flex-direction:column;gap:8px;margin-top:12px}
965
+ .slm-tablerow{display:grid;grid-template-columns:minmax(0,1fr) minmax(140px,auto);align-items:center;gap:10px;
966
+ padding:10px;border:1px solid var(--slm-line);border-radius:10px;background:var(--slm-surface)}
967
+ .slm-tablecopy{display:flex;min-width:0;flex-direction:column;gap:2px}.slm-tablecopy b{font-size:12px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
968
+ .slm-tablecopy small{font-size:10px;color:var(--slm-muted)}.slm-tablerow .slm-select{min-width:140px}
926
969
  .slm:fullscreen{border-radius:0;min-height:100vh;background:var(--slm-bg)}
927
970
  .slm:fullscreen .slm-bar{padding:14px 22px}.slm:fullscreen .slm-kpi b{font-size:21px}.slm:fullscreen .slm-rail{width:360px}
928
971
 
929
972
  .slm.compact .slm-rail{width:100%;border-left:0;border-top:1px solid var(--slm-line);height:44%}
930
973
  .slm.compact .slm-body{flex-direction:column}
931
974
  .slm.compact .slm-bar{grid-template-columns:minmax(0,1fr) auto;gap:8px;padding:8px}
932
- .slm.compact .slm-modes{min-width:0}.slm.compact .slm-mode{padding-inline:11px}
975
+ .slm.compact .slm-modes{display:none}
976
+ .slm.compact .slm-tools{display:block;width:100%;padding:9px 13px;min-height:44px;border:1px solid var(--slm-line);
977
+ border-radius:10px;background:var(--slm-surface);color:var(--slm-text);font-size:13px;font-weight:800}
933
978
  .slm.compact .slm-live{justify-self:end}.slm.compact .slm-bar-actions{grid-column:1/-1;justify-self:stretch}
934
979
  .slm.compact .slm-barbtn{flex:1;padding:6px 9px}.slm.compact .slm-kpis{grid-template-columns:repeat(4,minmax(0,1fr));gap:8px}
935
980
  .slm.compact .slm-kpi[data-kpi="viewing-map"],.slm.compact .slm-kpi[data-kpi="active-holds"],
@@ -951,37 +996,41 @@
951
996
  transition:none!important;
952
997
  scroll-behavior:auto!important}
953
998
  }
954
- `;function Ke(){if(typeof document>"u"||document.getElementById(je))return;let a=document.createElement("style");a.id=je,a.textContent=Tt,document.head.appendChild(a)}function Ye(a){if(typeof document>"u"||document.getElementById(Ue))return;let e=document.createElement("style");e.id=Ue,e.textContent=a,document.head.appendChild(e)}var We=require("@seatlayer/core");function Ge(a){return a?a.mode:"open"}function Xe(a,e,t){switch(a){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 Qe(a){return new Date(a-new Date().getTimezoneOffset()*6e4).toISOString().slice(0,16)}function Ze(a){if(typeof a=="string"){let e=document.querySelector(a);if(!e)throw new Error(`seatmanager: container "${a}" not found`);return e}if(!(a instanceof HTMLElement))throw new Error("seatmanager: container must be a CSS selector or an HTMLElement");return a}function Te(a){if(!a.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 le(a){return a==="blocked"?"not_for_sale":a}var Je=[{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 Ie(a){let e=a??{};return{"--slm-bg":e.background??"#0e1017","--slm-surface":"#181b24","--slm-text":"#eef1f7","--slm-muted":"#8b93a7","--slm-line":"rgba(255,255,255,.09)","--slm-accent":e.accent??"#6e7bff","--slm-accent-ink":e.accentInk??"#ffffff","--slm-font":"-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif","--slm-radius":"14px"}}function Ee(a,e){let t=Math.max(0,Math.round((e-a)/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 Z(a,e){return(0,We.formatMoney)(a,e,{maximumFractionDigits:0,fallback:(t,s)=>`${s} ${Math.round(t).toLocaleString()}`})}function b(a){return String(a??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#039;")}var et=require("@seatlayer/core");function Me(a){return Object.entries(a).filter(([,e])=>e.mode==="closed").map(([e])=>e)}function re(a){let e=a.sectionsBase;if(!e)return{rows:[],hiddenSections:0,closedSections:0};let t=a.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=[],o=0,l=0,r=(d,c,p,g=!1)=>{let w=a.availabilityRules[c.id]??null,m=a.effectiveClosed.has(c.id)||g,u=a.effectiveHidden.has(c.id)||p&&!m;d==="section"&&u&&(o+=1),d==="section"&&m&&(l+=1),i.push({kind:d,id:c.id,label:c.label,seatCount:c.seatCount,seatLabels:c.seatLabels,rule:w,hidden:u,closed:m,followsZone:d==="section"&&p})};for(let d of t){let c=s.get(d.id);if(!c||!c.length)continue;let p={id:d.id,label:d.label||"Zone",seatCount:c.reduce((m,u)=>m+u.seatCount,0),seatLabels:c.flatMap(m=>m.seatLabels)},g=!!a.availabilityRules[d.id],w=a.availabilityRules[d.id]?.mode==="closed";r("zone",p,!1);for(let m of c)r("section",m,g,w)}for(let d of n)r("section",d,!1);if(e.ungrouped){let d=e.ungrouped;r("section",{id:et.UNGROUPED_ID,label:d.label,seatCount:d.seatCount,seatLabels:d.seatLabels},!1)}return{rows:i,hiddenSections:o,closedSections:l}}function tt(a,e){let t=Ge(a.rule),s=`slm-availrow${a.kind==="zone"?" zone":""}${a.hidden?" hidden":""}${a.closed?" closed":""}`,n=e?" disabled":"",i=(c,p)=>`<option value="${c}"${t===c?" selected":""}>${p}</option>`,o=a.followsZone?'<span class="slm-availfollows">Follows zone</span>':`<span class="slm-availselwrap">
955
- <select class="slm-select slm-availmode${t!=="open"?" on":""}" data-avail-id="${b(a.id)}"${n} aria-label="Availability for ${b(a.label)}">
999
+ `;function Ke(){if(typeof document>"u"||document.getElementById(Ne))return;let l=document.createElement("style");l.id=Ne,l.textContent=At,document.head.appendChild(l)}function Ye(l){if(typeof document>"u"||document.getElementById(Ue))return;let e=document.createElement("style");e.id=Ue,e.textContent=l,document.head.appendChild(e)}var We=require("@seatlayer/core");function Ge(l){return l?l.mode:"open"}function Xe(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 Qe(l){return new Date(l-new Date().getTimezoneOffset()*6e4).toISOString().slice(0,16)}function Ze(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 Ae(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 le(l){return l==="blocked"?"not_for_sale":l}var Je=[{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 Ee(l){let e=l??{};return{"--slm-bg":e.background??"#0e1017","--slm-surface":"#181b24","--slm-text":"#eef1f7","--slm-muted":"#8b93a7","--slm-line":"rgba(255,255,255,.09)","--slm-accent":e.accent??"#6e7bff","--slm-accent-ink":e.accentInk??"#ffffff","--slm-font":"-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif","--slm-radius":"14px"}}function Me(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 Z(l,e){return(0,We.formatMoney)(l,e,{maximumFractionDigits:0,fallback:(t,s)=>`${s} ${Math.round(t).toLocaleString()}`})}function u(l){return String(l??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#039;")}var et=require("@seatlayer/core");function Ie(l){return Object.entries(l).filter(([,e])=>e.mode==="closed").map(([e])=>e)}function re(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,p,b=!1)=>{let y=l.availabilityRules[c.id]??null,g=l.effectiveClosed.has(c.id)||b,m=l.effectiveHidden.has(c.id)||p&&!g;d==="section"&&m&&(a+=1),d==="section"&&g&&(o+=1),i.push({kind:d,id:c.id,label:c.label,seatCount:c.seatCount,seatLabels:c.seatLabels,rule:y,hidden:m,closed:g,followsZone:d==="section"&&p})};for(let d of t){let c=s.get(d.id);if(!c||!c.length)continue;let p={id:d.id,label:d.label||"Zone",seatCount:c.reduce((g,m)=>g+m.seatCount,0),seatLabels:c.flatMap(g=>g.seatLabels)},b=!!l.availabilityRules[d.id],y=l.availabilityRules[d.id]?.mode==="closed";r("zone",p,!1);for(let g of c)r("section",g,b,y)}for(let d of n)r("section",d,!1);if(e.ungrouped){let d=e.ungrouped;r("section",{id:et.UNGROUPED_ID,label:d.label,seatCount:d.seatCount,seatLabels:d.seatLabels},!1)}return{rows:i,hiddenSections:a,closedSections:o}}function tt(l,e){let t=Ge(l.rule),s=`slm-availrow${l.kind==="zone"?" zone":""}${l.hidden?" hidden":""}${l.closed?" closed":""}`,n=e?" disabled":"",i=(c,p)=>`<option value="${c}"${t===c?" selected":""}>${p}</option>`,a=l.followsZone?'<span class="slm-availfollows">Follows zone</span>':`<span class="slm-availselwrap">
1000
+ <select class="slm-select slm-availmode${t!=="open"?" on":""}" data-avail-id="${u(l.id)}"${n} aria-label="Availability for ${u(l.label)}">
956
1001
  ${i("open","Open \u2014 on sale")}
957
1002
  ${i("closed","Closed \u2014 visible, not on sale")}
958
1003
  ${i("hidden","Hidden \u2014 off the buyer map")}
959
1004
  ${i("timed","Reveal at a time")}
960
1005
  ${i("threshold","Auto-reveal at % sold")}
961
1006
  </select>
962
- </span>`,l="";if(!a.followsZone&&t==="timed"){let c=a.rule?.revealAt?b(Qe(a.rule.revealAt)):"";l=`<div class="slm-availdetail">
963
- <input type="datetime-local" class="slm-input" data-avail-reveal="${b(a.id)}" value="${c}"${n} aria-label="Reveal time for ${b(a.label)}" />
964
- </div>`}else if(!a.followsZone&&t==="threshold"){let c=a.rule?.thresholdPct??80;l=`<div class="slm-availdetail">
1007
+ </span>`,o="";if(!l.followsZone&&t==="timed"){let c=l.rule?.revealAt?u(Qe(l.rule.revealAt)):"";o=`<div class="slm-availdetail">
1008
+ <input type="datetime-local" class="slm-input" data-avail-reveal="${u(l.id)}" value="${c}"${n} aria-label="Reveal time for ${u(l.label)}" />
1009
+ </div>`}else if(!l.followsZone&&t==="threshold"){let c=l.rule?.thresholdPct??80;o=`<div class="slm-availdetail">
965
1010
  <span class="slm-availpctlabel">Reveal at</span>
966
- <input type="number" min="1" max="100" class="slm-input slm-availpct" data-avail-pct="${b(a.id)}" value="${b(c)}"${n} aria-label="Percent sold to reveal ${b(a.label)}" />
1011
+ <input type="number" min="1" max="100" class="slm-input slm-availpct" data-avail-pct="${u(l.id)}" value="${u(c)}"${n} aria-label="Percent sold to reveal ${u(l.label)}" />
967
1012
  <span class="slm-availpctlabel">% sold</span>
968
- </div>`}let r=a.closed?'<span class="slm-availbadge closed">Closed</span>':a.hidden?'<span class="slm-availbadge hidden">Hidden</span>':"",d=a.kind==="zone"?`<span class="slm-availcaret" aria-hidden="true">${a.hidden?"\u25B8":"\u25BE"}</span>`:"";return`<div class="${s}">
1013
+ </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}">
969
1014
  <div class="slm-availhead">
970
- <span class="slm-availlabel">${d}${b(a.label)}</span>
1015
+ <span class="slm-availlabel">${d}${u(l.label)}</span>
971
1016
  ${r}
972
- <span class="slm-availcount">${a.seatCount.toLocaleString()}</span>
973
- ${o}
1017
+ <span class="slm-availcount">${l.seatCount.toLocaleString()}</span>
1018
+ ${a}
974
1019
  </div>
975
- ${l}
976
- </div>`}var jt="https://api.seatlayer.io",Ce=80,Ut=16,ut=4,Re=class{constructor(e){this.els={};this.renderer=null;this.doc=null;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.availabilityRules={};this.effectiveHidden=new Set;this.effectiveClosed=new Set;this.availabilitySaving=!1;this.lastSyncedAt=null;this.blockedQuery="";this.blockedSection="";this.blockedResultLimit=100;this.unblockAllConfirmTimer=null;this.channels=null;this.channelCaps={view:!1,manage:!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();if(s==="m")this.setMode("view");else if(s==="i")this.setMode("inspect");else if(s==="b")this.setMode("block");else if(s==="s")this.setMode("sections");else if(s==="c"){if(!this.channelCaps.view)return;this.setMode("channels")}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=[];Te(e.token),this.opts=e,this.key=e.eventKey,this.mode=e.mode??"view",this.keepLive=e.keepLiveWhileHidden??!0,this.followLive=e.followLive??!1,this.currency=e.currency??"USD",this.tokenExpiresAt=e.tokenExpiresAt??null,this.api=new U(e.apiBase??jt,e.token),this.organizerAssetUrls=new oe(this.key,(t,s)=>this.withAuthRetry(()=>this.api.asset(t,s))),this.host=Ze(e.container)}async render(){Ke(),this.buildChrome();try{let e=await this.withAuthRetry(()=>this.api.chart(this.key));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();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.scheduleTokenRefresh(),this.opts.onReady?.()}catch(e){this.fail(e)}return this}setMode(e){e==="channels"&&!this.channelCaps.view&&(e="view"),e==="channels"&&!this.channels&&this.ensureChannels();let t=e!==this.mode,s=this.mode==="channels";this.mode=e,!this.renderer&&this.doc?this.buildRenderer():this.updateRendererInteraction(),t&&this.renderer?.clearSelection(),s&&e!=="channels"&&this.channels?.leave(),this.paintModeTabs(),this.paintRail(),this.applySectionCanvasTreatment(),e==="channels"&&this.channels?.enter(),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(()=>(Oe(),pt));if(this.closed||!this.channelCaps.view||(this.channels||(Ye(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,o=this.sectionByObject.get(s.rowId)??C.UNGROUPED_ID,l=t.get(i)??{id:i,label:n.type==="row"?n.segmentedRow?.displayLabel??n.displayLabel??n.label:n.displayLabel??n.label,sectionId:o,sectionLabel:this.sectionLabelById.get(o)??"Other seats",labels:[]};l.labels.push(s.label),t.set(i,l)}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})),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)??C.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){if(this.opts.theme=e,!!this.root)for(let[t,s]of Object.entries(Ie(e)))this.root.style.setProperty(t,s)}setCapabilities(e){this.opts.capabilities=e,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){Te(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 f&&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)}}}selectAll(){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()}selectByLabels(e){let t=this.renderer?.selectByLabels(e)??[];return this.syncSelection(),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(){this.renderer?.clearSectionFocus(),this.renderer?.zoomToFit()}destroy(){if(this.closed=!0,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.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.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 C.SeatmapRenderer(this.mapHost,{manageMode:!0,marqueeSelect:e,maxSelection:1e6,selectableStatuses:this.selectableStatuses(),currency:this.currency,onSelect:t=>this.handleSeatSelect(t),onDeselect:()=>this.syncSelection(),onMarquee:()=>this.syncSelection(),onSectionTap:t=>{this.renderer?.focusSection(t),this.channels?.handleSectionFocus(t)},onViewChange:()=>{this.updateZoomHint(),this.channels?.handleViewChange()}}),this.renderer.setChart(this.doc),this.repaintAll(),this.applyHeatOverlay(),this.updateZoomHint()}isBulkSelectMode(){return this.mode==="block"||this.mode==="channels"&&this.channels?.usesMarqueeSelection()===!0}selectableStatuses(){return this.mode==="block"?["free","not_for_sale"]: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,marqueeSelect:e,maxSelection:1e6,selectableStatuses:this.selectableStatuses()}),this.updateZoomHint()}handleSeatSelect(e){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,C.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,C.gaAreasOf)(e))for(let s of(0,C.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[le(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,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.applySnapshot(s.seats,typeof s.default=="string"?s.default:void 0);else if(Array.isArray(s.changes)){let n=[],i=new Map;for(let l of s.changes){let r=["free","held","booked","blocked"].includes(l.status)?l.status:"free",d=this.status.get(l.label)??"free";if(d===r)continue;this.setStatusLabel(l.label,r,d);let c=this.labelToId.get(l.label);c&&(this.renderer?.setStatus([c],le(r)),n.push(c));let p=this.verbFor(d,r),g=`${p}:${r}`,w=i.get(g)??{labels:[],verb:p,status:r};w.labels.push(l.label),i.set(g,w)}for(let l of i.values()){let r=this.pushActivity(l.labels,l.verb,l.status);r&&this.paintSpatialActivity(r)}n.length&&(this.lastSyncedAt=Date.now(),this.afterPaint());let o=typeof s.bookedValue?.gross=="number"?s.bookedValue.gross:s.revenue?.gross;typeof o=="number"&&Number.isFinite(o)&&this.applyLiveGross(o),this.recomputeTallies()}}}applyLiveGross(e){if(this.liveGross={at:Date.now(),value:e},this.authoritativeGrossRevenue=e,this.revenueStatus="current",this.controlRoomSnapshot){let s={...this.controlRoomSnapshot.bookedValue??this.controlRoomSnapshot.revenue,gross:e};this.controlRoomSnapshot={...this.controlRoomSnapshot,bookedValue:s,revenue:s},this.opts.onControlRoom?.(this.controlRoomSnapshot)}}setStatusLabel(e,t,s=this.status.get(e)??"free"){this.status.set(e,t),s!==t&&(s!=="free"&&(this.counts[s]-=1),t!=="free"&&(this.counts[t]+=1))}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 o of this.knownLabels())n.set(o,i)}for(let[i,o]of Object.entries(e))n.set(i,s(o));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,le(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 o=this.sectionByObject.get(i.rowId);o&&o!==C.UNGROUPED_ID&&t.add(o)}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,Ut)){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,n=this.followLive&&t.length===1&&(e.status==="held"||e.status==="booked");if(n&&s===t[0]){this.pulseSeatLabels(e.labels,e.status);return}if(n){this.followLiveTimer&&clearTimeout(this.followLiveTimer),this.followSeatTimer&&clearTimeout(this.followSeatTimer),this.followLiveTimer=setTimeout(()=>{this.followLiveTimer=null,this.renderer?.focusSection(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 o of t.slice(0,ut))this.renderer?.flashSection(o,i);return}(!t.length||s&&t.includes(s))&&this.pulseSeatLabels(e.labels,e.status)}locateSection(e){this.renderer?.focusSection(e)}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.locateSection(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,ut))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>
977
- <span class="slm-liveeventcopy">${b(n)} \xB7 ${e.count.toLocaleString()} ${i} ${b(e.verb)}</span>
978
- <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}}),o={...n,bySection:i},l={...s,bookedValue:o,revenue:o};if(e===this.revenueRequest){if(this.livePresence&&this.livePresence.at>=t?l={...l,presence:this.livePresence.value}:this.livePresence=null,this.liveGross&&this.liveGross.at>=t){let r={...l.bookedValue,gross:this.liveGross.value};l={...l,bookedValue:r,revenue:r}}else this.liveGross=null;this.controlRoomSnapshot=l,this.rebaseServerTotals(l),this.lastSyncedAt=Date.now(),this.authoritativeGrossRevenue=l.bookedValue.gross,this.authoritativeCurrency=l.currency,this.currency=l.currency,this.revenueStatus="current",this.recomputeTallies(),this.applyHeatOverlay(),this.paintMonitorInsights(),this.opts.onControlRoom?.(l)}return l}catch(s){throw e===this.revenueRequest&&(this.revenueStatus="stale",this.recomputeTallies()),s}}rebaseServerTotals(e){let t=e.totals;if(!t||["free","held","booked","blocked"].some(s=>!Number.isFinite(t[s]))){this.serverBaseline=null;return}this.serverBaseline={model:this.modelVersion,server:{free:t.free,held:t.held,booked:t.booked,blocked:t.blocked},client:this.clientTallies()}}clientTallies(){let{held:e,booked:t,blocked:s}=this.counts;return{held:e,booked:t,blocked:s,free:Math.max(0,this.unitTotal()-e-t-s)}}buildTallies(){let e=this.clientTallies(),t=this.serverBaseline?.model===this.modelVersion?this.serverBaseline:null,s=l=>t?Math.max(0,t.server[l]+(e[l]-t.client[l])):e[l],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 o=i.total-i.blocked;return i.sellThroughPct=o>0?Math.round(i.booked/o*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":"released":t}pushActivity(e,t,s,n=Date.now()){let i=e[0];if(!i)return null;let o=this.sectionsForLabels(e),l={id:`${i}:${n}:${Math.random().toString(36).slice(2,6)}`,at:n,label:i,labels:[...e],count:e.length,verb:t,status:s,sectionIds:o.ids,sectionLabels:o.labels};return this.feed.unshift(l),this.feed.length>Ce&&(this.feed.length=Ce),this.mode==="view"&&this.paintFeed(),this.showLiveEvent(l),this.opts.onActivity?.(l),l}seedFeed(e){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){let i=n.labels[0];if(!i)continue;let o=this.sectionsForLabels(n.labels),l={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:o.ids,sectionLabels:o.labels};this.feed.push(l),this.opts.onActivity?.(l)}this.feed.sort((n,i)=>i.at-n.at),this.feed.length>Ce&&(this.feed.length=Ce),this.mode==="view"&&this.paintFeed()}startFeedClock(){this.feedTimer=setInterval(()=>{this.mode==="view"&&(this.paintFeed(),this.paintMonitorInsights())},1e4)}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==="channels"&&this.channels?.handleSelectionChange(),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");let t=Ie(this.opts.theme);for(let[n,i]of Object.entries(t))e.style.setProperty(n,i);e.innerHTML=`
1020
+ ${o}
1021
+ </div>`}var Nt="https://api.seatlayer.io",Ce=80,Ut=16,ut=4,Re=class{constructor(e){this.els={};this.renderer=null;this.doc=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.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();if(s==="m")this.setMode("view");else if(s==="i")this.setMode("inspect");else if(s==="x")this.setMode("select");else if(s==="l")this.setMode("filterSections");else if(s==="b")this.setMode("block");else if(s==="s")this.setMode("sections");else if(s==="g")if(this.categoryCanManage)this.setMode("categories");else return;else if(s==="t")if(this.tableCanManage)this.setMode("tables");else return;else if(s==="c"){if(!this.channelCaps.view)return;this.setMode("channels")}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=[];Ae(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.followLive=e.followLive??!1,this.currency=e.currency??"USD",this.tokenExpiresAt=e.tokenExpiresAt??null,this.api=new U(e.apiBase??Nt,e.token),this.organizerAssetUrls=new oe(this.key,(t,s)=>this.withAuthRetry(()=>this.api.asset(t,s))),this.host=Ze(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(){Ke(),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();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){e==="channels"&&!this.channelCaps.view&&(e="view"),e==="categories"&&!this.categoryCanManage&&(e="view"),e==="tables"&&!this.tableCanManage&&(e="view"),e==="channels"&&!this.channels&&this.ensureChannels();let t=e!==this.mode,s=this.mode==="channels",n=this.mode==="filterSections";this.mode=e,!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(()=>(ze(),pt));if(this.closed||!this.channelCaps.view||(this.channels||(Ye(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)??L.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)??L.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){if(this.opts.theme=e,!!this.root)for(let[t,s]of Object.entries(Ee(e)))this.root.style.setProperty(t,s)}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){Ae(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 f&&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 f&&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(),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.closed=!0,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.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.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 L.SeatmapRenderer(this.mapHost,{manageMode:!0,marqueeSelect:e,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.doc),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,marqueeSelect:e,maxSelection:this.selectionCap(),selectableStatuses:this.selectableStatuses()}),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,L.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,L.gaAreasOf)(e))for(let s of(0,L.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[le(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,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.applySnapshot(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],le(r)),n.push(c));let p=this.verbFor(d,r),b=`${p}:${r}`,y=i.get(b)??{labels:[],verb:p,status:r};y.labels.push(o.label),i.set(b,y)}for(let o of i.values()){let r=this.pushActivity(o.labels,o.verb,o.status);r&&this.paintSpatialActivity(r)}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))}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,le(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!==L.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,Ut)){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,n=this.followLive&&t.length===1&&(e.status==="held"||e.status==="booked");if(n&&s===t[0]){this.pulseSeatLabels(e.labels,e.status);return}if(n){this.followLiveTimer&&clearTimeout(this.followLiveTimer),this.followSeatTimer&&clearTimeout(this.followSeatTimer),this.followLiveTimer=setTimeout(()=>{this.followLiveTimer=null,this.renderer?.focusSection(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,ut))this.renderer?.flashSection(a,i);return}(!t.length||s&&t.includes(s))&&this.pulseSeatLabels(e.labels,e.status)}locateSection(e){this.renderer?.focusSection(e)}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.locateSection(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,ut))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>
1022
+ <span class="slm-liveeventcopy">${u(n)} \xB7 ${e.count.toLocaleString()} ${i} ${u(e.verb)}</span>
1023
+ <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 r={...o.bookedValue,gross:this.liveGross.value};o={...o,bookedValue:r,revenue:r}}else this.liveGross=null;this.controlRoomSnapshot=o,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.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":"released":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.feed.unshift(o),this.feed.length>Ce&&(this.feed.length=Ce),this.mode==="view"&&this.paintFeed(),this.showLiveEvent(o),this.opts.onActivity?.(o),o}seedFeed(e){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){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>Ce&&(this.feed.length=Ce),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.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");let t=Ee(this.opts.theme);for(let[n,i]of Object.entries(t))e.style.setProperty(n,i);e.innerHTML=`
979
1024
  <div class="slm-bar">
980
1025
  <div class="slm-modes" data-ref="modes" role="tablist" aria-label="Manager tools">
981
1026
  <button class="slm-mode" role="tab" data-mode="view" title="Monitor (M)" aria-keyshortcuts="M">Monitor</button>
982
1027
  <button class="slm-mode" role="tab" data-mode="inspect" title="Inspect (I)" aria-keyshortcuts="I">Inspect</button>
1028
+ <button class="slm-mode" role="tab" data-mode="select" title="Select (X)" aria-keyshortcuts="X">Select</button>
1029
+ <button class="slm-mode" role="tab" data-mode="filterSections" title="Filter sections (L)" aria-keyshortcuts="L">Filter</button>
983
1030
  <button class="slm-mode" role="tab" data-mode="block" title="Block (B)" aria-keyshortcuts="B">Block</button>
984
1031
  <button class="slm-mode" role="tab" data-mode="sections" title="Sections (S)" aria-keyshortcuts="S">Sections</button>
1032
+ <button class="slm-mode" role="tab" data-mode="categories" title="Categories (G)" aria-keyshortcuts="G" hidden>Categories</button>
1033
+ <button class="slm-mode" role="tab" data-mode="tables" title="Tables (T)" aria-keyshortcuts="T" hidden>Tables</button>
985
1034
  <button class="slm-mode" role="tab" data-mode="channels" title="Channels (C)" aria-keyshortcuts="C" hidden>Channels</button>
986
1035
  </div>
987
1036
  <select class="slm-tools" data-ref="tools" aria-label="Manager tools"></select>
@@ -1006,10 +1055,10 @@
1006
1055
  <aside class="slm-rail"><div class="slm-railscroll" data-ref="rail"></div></aside>
1007
1056
  </div>
1008
1057
  <div class="slm-toast" data-ref="toast"></div>
1009
- `,this.host.appendChild(e),this.root=e,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.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()}updateContainerLayout(){let e=this.root?.getBoundingClientRect().width||this.host.clientWidth;this.root?.classList.toggle("compact",e>0&&e<800),this.channels?.handleLayoutChange()}buildSectionOptions(){if(this.doc)try{let e=(0,C.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:C.UNGROUPED_ID,label:e.ungrouped.label}),this.sectionLabelById.set(C.UNGROUPED_ID,e.ungrouped.label))}catch{}}paintModeTabs(){let e=[];this.els.modes?.querySelectorAll("[data-mode]").forEach(s=>{let n=s,i=n.dataset.mode,o=i!=="channels"||this.channelCaps.view;if(n.hidden=!o,!o)return;e.push({mode:i,label:n.textContent??i});let l=i===this.mode;n.classList.toggle("on",l),n.setAttribute("aria-selected",String(l)),n.tabIndex=l?0:-1});let t=this.els.tools;t&&(t.innerHTML=e.map(s=>`<option value="${s.mode}"${s.mode===this.mode?" selected":""}>${b(s.label)}</option>`).join(""),t.value=this.mode),this.root?.classList.toggle("block-mode",this.mode==="block")}paintFollowLiveButton(){let e=this.els.follow;e&&(e.classList.toggle("on",this.followLive),e.setAttribute("aria-pressed",String(this.followLive)),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="Booking momentum",this.paintMomentumHelp())}paintMomentumHelp(){let e=this.els.rail?.querySelector('[data-ref="momentumhelp"]');if(!e)return;e.hidden=!this.heatEnabled;let t=e.querySelector('[data-ref="momentumcopy"]');if(!t)return;let s=this.controlRoomSnapshot?.velocity.bySection.some(n=>n.netBooked>0);t.textContent=s?"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.mode==="block"&&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}${Z(i,s)}`:e==="booked-pct"?`${n}${i.toLocaleString()}pt`:`${n}${i.toLocaleString()}`}paintKpis(e){if(!this.els.kpis)return;let t=e.bookedValueStatus==="current"?Z(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(o=>{let l=this.lastKpiValues.get(o.key),r=o.raw!=null&&l!=null&&o.raw!==l,d=r?o.raw-l:0;r&&(i=!0,this.activeKpiDeltas.set(o.key,{text:this.formatKpiDelta(o.key,d,e.currency),down:d<0})),o.raw!=null&&this.lastKpiValues.set(o.key,o.raw);let c=this.activeKpiDeltas.get(o.key);return`<div class="slm-kpi${c?" changed":""}" data-kpi="${o.key}" title="${b(o.title)}">
1010
- <b>${o.dot?`<span class="dot" style="background:${o.dot}"></span>`:""}${o.n}</b><span>${o.l}</span>
1058
+ `,this.host.appendChild(e),this.root=e,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.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()}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,L.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:L.UNGROUPED_ID,label:e.ungrouped.label}),this.sectionLabelById.set(L.UNGROUPED_ID,e.ungrouped.label))}catch{}}paintModeTabs(){let e=[];this.els.modes?.querySelectorAll("[data-mode]").forEach(s=>{let n=s,i=n.dataset.mode,a=i==="channels"?this.channelCaps.view:i==="categories"?this.categoryCanManage:i==="tables"?this.tableCanManage:!0;if(n.hidden=!a,!a)return;e.push({mode:i,label:n.textContent??i});let o=i===this.mode;n.classList.toggle("on",o),n.setAttribute("aria-selected",String(o)),n.tabIndex=o?0:-1});let t=this.els.tools;t&&(t.innerHTML=e.map(s=>`<option value="${s.mode}"${s.mode===this.mode?" selected":""}>${u(s.label)}</option>`).join(""),t.value=this.mode),this.root?.classList.toggle("block-mode",this.mode==="block")}paintFollowLiveButton(){let e=this.els.follow;e&&(e.classList.toggle("on",this.followLive),e.setAttribute("aria-pressed",String(this.followLive)),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="Booking momentum",this.paintMomentumHelp())}paintMomentumHelp(){let e=this.els.rail?.querySelector('[data-ref="momentumhelp"]');if(!e)return;e.hidden=!this.heatEnabled;let t=e.querySelector('[data-ref="momentumcopy"]');if(!t)return;let s=this.controlRoomSnapshot?.velocity.bySection.some(n=>n.netBooked>0);t.textContent=s?"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.mode==="block"&&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}${Z(i,s)}`:e==="booked-pct"?`${n}${i.toLocaleString()}pt`:`${n}${i.toLocaleString()}`}paintKpis(e){if(!this.els.kpis)return;let t=e.bookedValueStatus==="current"?Z(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,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="${u(a.title)}">
1059
+ <b>${a.dot?`<span class="dot" style="background:${a.dot}"></span>`:""}${a.n}</b><span>${a.l}</span>
1011
1060
  ${c?`<span class="slm-kpidelta${c.down?" down":""}">${c.text}</span>`:""}
1012
- </div>`}).join(""),i&&(this.kpiCleanupTimer&&clearTimeout(this.kpiCleanupTimer),this.kpiCleanupTimer=setTimeout(()=>{this.kpiCleanupTimer=null,this.activeKpiDeltas.clear(),this.els.kpis?.querySelectorAll(".slm-kpidelta").forEach(o=>o.remove()),this.els.kpis?.querySelectorAll(".slm-kpi.changed").forEach(o=>o.classList.remove("changed"))},1500))}paintRail(){this.mode==="view"?this.renderViewRail():this.mode==="inspect"?this.renderInspectRail(this.getSelection()):this.mode==="sections"?this.renderSectionsRail():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=`
1061
+ </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.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=`
1013
1062
  <p class="slm-eyebrow">Monitor</p>
1014
1063
  <p class="slm-hint">Read-only. Inventory, map activity and booking movement update on the same live board.</p>
1015
1064
  <div class="slm-health" data-ref="presence"></div>
@@ -1027,56 +1076,114 @@
1027
1076
  <div class="slm-sectionlist" data-ref="sections"></div>
1028
1077
  <p class="slm-eyebrow">Activity</p>
1029
1078
  <div class="slm-feed" data-ref="feed"></div>
1030
- `,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.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?Ee(this.lastSyncedAt,Date.now()):"waiting",o=this.presenceCounts();this.els.presence.innerHTML=`
1031
- <div class="slm-healthitem" title="Active map sessions right now"><b>${o?o.shoppingSessions.toLocaleString():"\u2014"}</b><span>Viewing map</span></div>
1032
- <div class="slm-healthitem" title="Sessions currently holding inventory"><b>${o?o.activeHolds.toLocaleString():"\u2014"}</b><span>Active holds</span></div>
1079
+ `,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.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?Me(this.lastSyncedAt,Date.now()):"waiting",a=this.presenceCounts();this.els.presence.innerHTML=`
1080
+ <div class="slm-healthitem" title="Active map sessions right now"><b>${a?a.shoppingSessions.toLocaleString():"\u2014"}</b><span>Viewing map</span></div>
1081
+ <div class="slm-healthitem" title="Sessions currently holding inventory"><b>${a?a.activeHolds.toLocaleString():"\u2014"}</b><span>Active holds</span></div>
1033
1082
  <div class="slm-healthitem"><b>${n?"Healthy":"Reconnecting"}</b><span>Live connection</span></div>
1034
- <div class="slm-healthitem"><b>${i}</b><span>Last sync</span></div>`}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 o=t.get(n.sectionId)?.netBooked??0;return(t.get(i.sectionId)?.netBooked??0)-o||i.bookedValue-n.bookedValue});this.els.sections.innerHTML=s.length?s.map(n=>{let i=t.get(n.sectionId),o=i?.netBooked??0,l=`${o>0?"+":""}${o}`,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">
1035
- <span class="slm-sectiontop"><span>${b(n.sectionLabel)}</span><span>${Z(n.bookedValue,e.currency)}</span></span>
1036
- <span class="slm-sectionmeta"><span>${n.booked.toLocaleString()}/${n.total.toLocaleString()} booked \xB7 ${l} in ${e.velocity.windowMinutes}m</span><span class="slm-trend ${r}">${r}</span><span class="slm-sectionlocate">Locate</span></span>
1037
- </button>`}).join(""):'<div class="slm-empty">No section metrics are available for this chart.</div>',this.paintTrendWindow(),this.paintMomentumHelp()}applyHeatOverlay(){let e=this.controlRoomSnapshot;if(!this.heatEnabled||!e){this.renderer?.setSectionHeat(null);return}let t=new Map(e.bookedValue.bySection.map(o=>[o.sectionId,Math.max(1,o.total)])),s=e.velocity.bySection.map(o=>({sectionId:o.sectionId,rate:Math.max(0,o.netBooked)/(t.get(o.sectionId)??1)/e.velocity.windowMinutes})),n=Math.max(0,...s.map(o=>o.rate)),i={};for(let o of s)i[o.sectionId]=n>0?Math.sqrt(o.rate/n):0;this.renderer?.setSectionHeat(i)}renderInspectRail(e){let t=e[e.length-1];if(!t){this.els.rail.innerHTML=`
1083
+ <div class="slm-healthitem"><b>${i}</b><span>Last sync</span></div>`}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="${u(n.sectionId)}" title="Focus ${u(n.sectionLabel)} on the map">
1084
+ <span class="slm-sectiontop"><span>${u(n.sectionLabel)}</span><span>${Z(n.bookedValue,e.currency)}</span></span>
1085
+ <span class="slm-sectionmeta"><span>${n.booked.toLocaleString()}/${n.total.toLocaleString()} booked \xB7 ${o} in ${e.velocity.windowMinutes}m</span><span class="slm-trend ${r}">${r}</span><span class="slm-sectionlocate">Locate</span></span>
1086
+ </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=`
1087
+ <p class="slm-eyebrow">Custom selection</p>
1088
+ <p class="slm-hint">Select inventory for a host-defined back-office operation. This tool is read-only and never books, releases, or blocks seats by itself.</p>
1089
+ <div class="slm-selbar" aria-live="polite"><span class="slm-selnum" data-ref="selectnum">0</span><span class="slm-sellabel" data-ref="selectmeta">selected</span></div>
1090
+ <p class="slm-note" data-ref="selectvalidity">${t?`Select exactly ${t.toLocaleString()} object${t===1?"":"s"}.`:`Up to ${s.toLocaleString()} objects may be selected.`}</p>
1091
+ <div class="slm-row">
1092
+ <button class="slm-btn ghost" data-ref="selectall">Select all</button>
1093
+ <button class="slm-btn ghost" data-ref="selectclear" disabled>Clear</button>
1094
+ </div>
1095
+ ${e.length?`<p class="slm-eyebrow" style="margin-top:8px">Select by category</p>
1096
+ <div class="slm-chipgrid">${e.map(n=>`
1097
+ <button class="slm-chip" type="button" data-select-cat="${u(n.key)}" aria-pressed="false">
1098
+ <span class="dot" style="background:${u(n.color??"#6e7bff")}"></span>
1099
+ <span>${u(n.label??n.key)}</span>
1100
+ <span class="slm-chipcount" data-cat-count>0</span>
1101
+ <span class="slm-chipcheck" aria-hidden="true">\u2713</span>
1102
+ </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(p=>p.categoryKey===a&&this.canSelectObject(p)),r=o.filter(p=>n.has(p.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=`
1103
+ <p class="slm-eyebrow">Filter sections</p>
1104
+ <p class="slm-hint">Choose a section for host-owned reporting. Matching sections with the same label stay together and the map frames their combined inventory.</p>
1105
+ ${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="${u(t)}" aria-pressed="${n}">
1106
+ <span class="slm-sectiontop"><span>${u(t)}</span><span>${i.toLocaleString()}</span></span>
1107
+ <span class="slm-sectionmeta"><span>${s.length===1?"One section":`${s.length.toLocaleString()} matching sections`}</span><span class="slm-sectionlocate">${n?"Filtered":"Filter"}</span></span>
1108
+ </button>`}).join("")}</div>
1109
+ <button type="button" class="slm-btn ghost" data-clear-filter ${this.filteredSectionLabel?"":"disabled"}>Clear filter</button>`:'<div class="slm-empty">This chart has no filterable sections.</div>'}`,this.els.rail.querySelectorAll("[data-filter-section]").forEach(t=>{t.addEventListener("click",()=>this.setFilteredSection(t.dataset.filterSection))}),this.els.rail.querySelector("[data-clear-filter]")?.addEventListener("click",()=>this.clearFilteredSection())}renderCategoriesRail(){let e=this.doc?.categories??[];this.els.rail.innerHTML=`
1110
+ <p class="slm-eyebrow">Event categories</p>
1111
+ <p class="slm-hint">Override categories for this event only. The reusable chart and existing hold/booking value snapshots do not change.</p>
1112
+ <div class="slm-selbar" aria-live="polite"><span class="slm-selnum" data-ref="categorynum">0</span><span class="slm-sellabel">objects selected</span></div>
1113
+ <div class="slm-row">
1114
+ <button class="slm-btn ghost" data-ref="categoryall">Select all</button>
1115
+ <button class="slm-btn ghost" data-ref="categoryclear" disabled>Clear</button>
1116
+ </div>
1117
+ <p class="slm-eyebrow" style="margin-top:8px">Assign selected objects</p>
1118
+ <div class="slm-categoryassign">${e.map(t=>{let s=[...this.labelToSeat.values()].filter(n=>n.categoryKey===t.key).length;return`<div class="slm-categoryrow">
1119
+ <span class="dot" style="background:${u(t.color??"#6e7bff")}"></span>
1120
+ <span class="slm-categorycopy"><b>${u(t.label??t.key)}</b><small>${s.toLocaleString()} currently</small></span>
1121
+ <button type="button" class="slm-linkbtn" data-pick-category="${u(t.key)}">Select current</button>
1122
+ <button type="button" class="slm-btn" data-assign-category="${u(t.key)}" disabled>Apply</button>
1123
+ </div>`}).join("")}</div>`,this.els.categorynum=this.els.rail.querySelector('[data-ref="categorynum"]'),this.els.categoryclear=this.els.rail.querySelector('[data-ref="categoryclear"]'),this.els.rail.querySelector('[data-ref="categoryall"]')?.addEventListener("click",()=>this.selectAll()),this.els.categoryclear.addEventListener("click",()=>this.clearSelection()),this.els.rail.querySelectorAll("[data-pick-category]").forEach(t=>{t.addEventListener("click",()=>this.selectCategories([t.dataset.pickCategory]))}),this.els.rail.querySelectorAll("[data-assign-category]").forEach(t=>{t.addEventListener("click",()=>{this.setCategory(t.dataset.assignCategory)})}),this.paintCategorySelection(this.getSelection())}paintCategorySelection(e){this.els.categorynum&&(this.els.categorynum.textContent=e.length.toLocaleString(),this.els.categoryclear.disabled=e.length===0,this.els.rail?.querySelectorAll("[data-assign-category]").forEach(t=>{t.disabled=e.length===0,t.textContent=e.length?`Apply to ${e.length.toLocaleString()}`:"Apply"}))}renderTablesRail(){let e=(this.doc?(0,L.floorsOf)(this.doc):[]).flatMap(s=>s.objects).filter(s=>s.type==="table");if(this.inventoryModelVersion!==2){this.els.rail.innerHTML=`
1124
+ <p class="slm-eyebrow">Table booking</p>
1125
+ <p class="slm-hint">Per-event table modes require inventory model 2 so grouped tables have one authoritative inventory identity.</p>
1126
+ <div class="slm-empty">Upgrade this event's inventory model before changing table booking.</div>`;return}if(!e.length){this.els.rail.innerHTML=`
1127
+ <p class="slm-eyebrow">Table booking</p>
1128
+ <p class="slm-hint">Choose whether each event table is sold by chair or as one grouped booking.</p>
1129
+ <div class="slm-empty">This chart has no tables.</div>`;return}let t=s=>s.variableOccupancy?"variable":s.bookAsWhole?"whole":"individual";this.els.rail.innerHTML=`
1130
+ <p class="slm-eyebrow">Table booking</p>
1131
+ <p class="slm-hint">Change this event only. A table with held, booked, or blocked inventory cannot change mode, and channel allocations must survive.</p>
1132
+ <div class="slm-row">
1133
+ <button class="slm-btn ghost" data-table-all="individual"${this.tableBookingSaving?" disabled":""}>All per chair</button>
1134
+ <button class="slm-btn ghost" data-table-all="whole"${this.tableBookingSaving?" disabled":""}>All whole table</button>
1135
+ </div>
1136
+ <div class="slm-tablelist">${e.map(s=>{let n=t(s);return`<div class="slm-tablerow">
1137
+ <span class="slm-tablecopy"><b>${u(s.displayLabel??s.label)}</b><small>${s.seatCount.toLocaleString()} chairs</small></span>
1138
+ <select class="slm-select" data-table-mode="${u(s.id)}" ${this.tableBookingSaving?"disabled":""}>
1139
+ <option value="individual"${n==="individual"?" selected":""}>Book per chair</option>
1140
+ <option value="whole"${n==="whole"?" selected":""}>Book whole table</option>
1141
+ ${n==="variable"?'<option value="variable" selected>Flexible group</option>':""}
1142
+ </select>
1143
+ </div>`}).join("")}</div>
1144
+ <p class="slm-note">Flexible-group bounds remain available through <code>setTableBooking()</code>; the packaged rail never invents guest limits.</p>`,this.els.rail.querySelectorAll("[data-table-all]").forEach(s=>{s.addEventListener("click",()=>{this.setTableBooking(e.map(n=>n.id),s.dataset.tableAll)})}),this.els.rail.querySelectorAll("[data-table-mode]").forEach(s=>{s.addEventListener("change",()=>{this.setTableBooking([s.dataset.tableMode],s.value)})})}renderInspectRail(e){let t=e[e.length-1];if(!t){this.els.rail.innerHTML=`
1038
1145
  <p class="slm-eyebrow">Inspect seats</p>
1039
1146
  <p class="slm-hint">Select a seat to see its availability and booking context. Nothing changes in this view.</p>
1040
- <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)??C.UNGROUPED_ID,o=this.sectionLabelById.get(i)??"Other seats",l=this.doc?.categories.find(g=>g.key===t.categoryKey),r=this.controlRoomSnapshot?.bookedValue.bySection.find(g=>g.sectionId===i),d=this.doc?.objects.find(g=>g.id===t.rowId),c=d?.type==="row"?{label:"Row",value:d.label}:d?.type==="table"?{label:"Table",value:d.label}:t.kind==="booth"?{label:"Type",value:"Booth"}:null,p=t.kind==="booth"?"Booth":"Seat";this.els.rail.innerHTML=`
1147
+ <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)??L.UNGROUPED_ID,a=this.sectionLabelById.get(i)??"Other seats",o=this.doc?.categories.find(b=>b.key===t.categoryKey),r=this.controlRoomSnapshot?.bookedValue.bySection.find(b=>b.sectionId===i),d=this.doc?.objects.find(b=>b.id===t.rowId),c=d?.type==="row"?{label:"Row",value:d.label}:d?.type==="table"?{label:"Table",value:d.label}:t.kind==="booth"?{label:"Type",value:"Booth"}:null,p=t.kind==="booth"?"Booth":"Seat";this.els.rail.innerHTML=`
1041
1148
  <p class="slm-eyebrow">${p} details</p>
1042
1149
  <p class="slm-hint">Live availability and section performance.</p>
1043
1150
  <div class="slm-inspect-card">
1044
- <div class="slm-inspect-label">${b(t.label)}</div>
1151
+ <div class="slm-inspect-label">${u(t.label)}</div>
1045
1152
  <div class="slm-inspect-grid">
1046
1153
  <div><span>Status</span><b>${n[s]}</b></div>
1047
- <div><span>Section</span><b>${b(o)}</b></div>
1048
- ${c?`<div><span>${c.label}</span><b>${b(c.value)}</b></div>`:""}
1049
- <div><span>Category</span><b>${b(l?.label??t.categoryKey)}</b></div>
1154
+ <div><span>Section</span><b>${u(a)}</b></div>
1155
+ ${c?`<div><span>${c.label}</span><b>${u(c.value)}</b></div>`:""}
1156
+ <div><span>Category</span><b>${u(o?.label??t.categoryKey)}</b></div>
1050
1157
  <div><span>Booked in section</span><b>${r?`${r.booked} of ${r.total}`:"\u2014"}</b></div>
1051
1158
  <div><span>Section booked value</span><b>${r&&this.controlRoomSnapshot?Z(r.bookedValue,this.controlRoomSnapshot.currency):"\u2014"}</b></div>
1052
1159
  </div>
1053
- </div>`}async refreshAvailability(){try{let e=await this.withAuthRetry(()=>this.api.availability(this.key));this.availabilityRules=e.rules??{},this.effectiveClosed=new Set(Me(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 f&&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.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}=re(this.sectionRowsInput());if(!e.length){this.els.rail.innerHTML=`
1160
+ </div>`}async refreshAvailability(){try{let e=await this.withAuthRetry(()=>this.api.availability(this.key));this.availabilityRules=e.rules??{},this.effectiveClosed=new Set(Ie(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 f&&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}=re(this.sectionRowsInput());if(!e.length){this.els.rail.innerHTML=`
1054
1161
  <p class="slm-eyebrow">Availability windows</p>
1055
1162
  <p class="slm-hint">Draw sections or zones in the designer to schedule availability per area. This chart has none yet.</p>
1056
- <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",o=t>0||s>0;this.els.rail.innerHTML=`
1163
+ <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=`
1057
1164
  <p class="slm-eyebrow">Availability windows</p>
1058
1165
  <p class="slm-hint">Control when each zone or section goes on sale. Keep it hidden, reveal it at a set time, or <b>auto-reveal once the rest sells past a threshold</b>. Hidden seats vanish for buyers; closed seats stay on the map (flat grey) but can't be bought.</p>
1059
- <div class="slm-availlist" data-ref="availlist">${e.map(l=>tt(l,this.availabilitySaving)).join("")}</div>
1166
+ <div class="slm-availlist" data-ref="availlist">${e.map(o=>tt(o,this.availabilitySaving)).join("")}</div>
1060
1167
  <div class="slm-availsummary">
1061
- <span class="slm-availdot${o?" warn":""}"></span>
1062
- <span>${b(i)}</span>
1168
+ <span class="slm-availdot${a?" warn":""}"></span>
1169
+ <span>${u(i)}</span>
1063
1170
  </div>
1064
1171
  <div class="slm-availcallout">
1065
1172
  <span class="slm-availstar" aria-hidden="true">\u2726</span>
1066
1173
  <p><b>Auto-reveal at % sold</b> is our differentiator \u2014 demand-triggered release: the balcony opens itself the moment the stalls hit the threshold. Neither seats.io nor Ticketmaster ships this.</p>
1067
- </div>`,this.wireSectionRail(),this.applySectionCanvasTreatment()}wireSectionRail(){let e=this.els.rail;e&&(e.querySelectorAll("[data-avail-id]").forEach(t=>{t.addEventListener("change",()=>this.setSectionMode(t.dataset.availId,t.value))}),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=re(this.sectionRowsInput()).rows.find(l=>l.id===e),n=s?.seatLabels??this.availabilityRules[e]?.labels??[],i={...this.availabilityRules},o=Xe(t,n,this.availabilityRules[e]);if(o?i[e]=o:delete i[e],s?.kind==="zone"&&this.sectionsBase)for(let l of this.sectionsBase.sections)l.zone===e&&delete i[l.id];this.persistAvailability(i)}setSectionRulePatch(e,t){let s=this.availabilityRules[e];if(!s)return;let i=re(this.sectionRowsInput()).rows.find(o=>o.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(Me(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=Je.map(t=>`<div class="slm-legrow"><span class="slm-legdot" style="background:${t.color}"></span>
1068
- <span class="slm-leglabel">${t.label}</span><span class="slm-legcount">${e[t.key].toLocaleString()}</span></div>`).join(""))}paintFeed(){if(!this.els.feed)return;if(!this.feed.length){this.els.feed.innerHTML=`<div class="slm-empty">No activity yet \u2014 it'll stream in live.</div>`;return}let e=Date.now(),t={free:"#6e7bff",held:"#f4b740",booked:"#22a06b",blocked:"#8b94ac"};this.els.feed.innerHTML=this.feed.map(s=>{let n=s.count>1?` +${s.count-1}`:"",i=s.sectionLabels??[],o=i.length===1?i[0]:i.length>1?`${i.length} sections`:"";return`<button type="button" class="slm-feedrow" data-feed-id="${b(s.id)}" title="Locate this activity on the map">
1174
+ </div>`,this.wireSectionRail(),this.applySectionCanvasTreatment()}wireSectionRail(){let e=this.els.rail;e&&(e.querySelectorAll("[data-avail-id]").forEach(t=>{t.addEventListener("change",()=>this.setSectionMode(t.dataset.availId,t.value))}),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=re(this.sectionRowsInput()).rows.find(o=>o.id===e),n=s?.seatLabels??this.availabilityRules[e]?.labels??[],i={...this.availabilityRules},a=Xe(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=re(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(Ie(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=Je.map(t=>`<div class="slm-legrow"><span class="slm-legdot" style="background:${t.color}"></span>
1175
+ <span class="slm-leglabel">${t.label}</span><span class="slm-legcount">${e[t.key].toLocaleString()}</span></div>`).join(""))}paintFeed(){if(!this.els.feed)return;if(!this.feed.length){this.els.feed.innerHTML=`<div class="slm-empty">No activity yet \u2014 it'll stream in live.</div>`;return}let e=Date.now(),t={free:"#6e7bff",held:"#f4b740",booked:"#22a06b",blocked:"#8b94ac"};this.els.feed.innerHTML=this.feed.map(s=>{let n=s.count>1?` +${s.count-1}`:"",i=s.sectionLabels??[],a=i.length===1?i[0]:i.length>1?`${i.length} sections`:"";return`<button type="button" class="slm-feedrow" data-feed-id="${u(s.id)}" title="Locate this activity on the map">
1069
1176
  <span class="slm-feeddot" style="background:${t[s.status]}"></span>
1070
- <span class="slm-feedtext">${o?`<span class="slm-feedsection">${b(o)}</span>`:""}${s.count===1?"Seat":"Seats"} <b>${b(s.label)}${n}</b> ${b(s.verb)}</span>
1071
- <span class="slm-feedmeta"><span class="slm-feedtime">${Ee(s.at,e)}</span><span class="slm-feedlocate">Locate</span></span>
1072
- </button>`}).join("")}renderBlockRail(){let t=(this.doc?.categories??[]).map(c=>`<button class="slm-chip" type="button" data-cat="${b(c.key)}" aria-pressed="false">
1073
- <span class="dot" style="background:${b(c.color??"#6e7bff")}"></span>
1074
- <span>${b(c.label??c.key)}</span>
1177
+ <span class="slm-feedtext">${a?`<span class="slm-feedsection">${u(a)}</span>`:""}${s.count===1?"Seat":"Seats"} <b>${u(s.label)}${n}</b> ${u(s.verb)}</span>
1178
+ <span class="slm-feedmeta"><span class="slm-feedtime">${Me(s.at,e)}</span><span class="slm-feedlocate">Locate</span></span>
1179
+ </button>`}).join("")}renderBlockRail(){let t=(this.doc?.categories??[]).map(c=>`<button class="slm-chip" type="button" data-cat="${u(c.key)}" aria-pressed="false">
1180
+ <span class="dot" style="background:${u(c.color??"#6e7bff")}"></span>
1181
+ <span>${u(c.label??c.key)}</span>
1075
1182
  <span class="slm-chipcount" data-cat-count>0</span>
1076
1183
  <span class="slm-chipcheck" aria-hidden="true">\u2713</span>
1077
1184
  </button>`).join(""),s=this.sectionOptions.length?`<div class="slm-field"><label>Select a whole section</label>
1078
1185
  <select class="slm-select" data-ref="section"><option value="">Choose a section\u2026</option>
1079
- ${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=`
1186
+ ${this.sectionOptions.map(c=>`<option value="${u(c.id)}">${u(c.label)}</option>`).join("")}</select></div>`:"",n=this.sectionOptions.map(c=>`<option value="${u(c.id)}">${u(c.label)}</option>`).join("");this.els.rail.innerHTML=`
1080
1187
  <p class="slm-eyebrow">Block &amp; unblock</p>
1081
1188
  <p class="slm-hint">Drag a box on the map to marquee-select, \u2318A for all, or pick a category/section. Booked and held inventory is never actionable here.</p>
1082
1189
  <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>
@@ -1119,8 +1226,8 @@
1119
1226
  <button class="slm-btn ghost" data-ref="markall" style="width:100%" disabled>Put all blocked seats on sale</button>
1120
1227
  <p class="slm-note slm-allnote" data-ref="markallnote">For a full reset only. You will be asked to confirm.</p>
1121
1228
  </div>
1122
- `;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 o=this.els.rail.querySelector('[data-ref="section"]');o?.addEventListener("change",()=>{o.value&&(this.selectSection(o.value),o.value="")});let l=i("blockedsearch"),r=i("blockedsection");l.value=this.blockedQuery,r.value=this.blockedSection,l.addEventListener("input",()=>{this.blockedQuery=l.value,this.blockedResultLimit=100,this.paintBlockedInventory()}),r.addEventListener("change",()=>{this.blockedSection=r.value,this.blockedResultLimit=100,this.paintBlockedInventory()}),i("selblocked").addEventListener("click",()=>{this.toggleLabels(this.filteredBlockedSeats().map(c=>c.label))}),i("blockedlist").addEventListener("click",c=>{let p=c.target,g=p.closest("[data-blocked-label]");g?.dataset.blockedLabel?this.toggleLabels([g.dataset.blockedLabel]):p.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 p=i("releasenote");p.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(o=>this.labelToId.get(o)).filter(o=>!!o);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(o=>(this.status.get(o.label)??"free")==="free").length,s=e.filter(o=>this.status.get(o.label)==="blocked").length;this.els.selmeta.textContent=e.length?`${t.toLocaleString()} available \xB7 ${s.toLocaleString()} blocked`:"selected";let 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,p]of this.labelToSeat.entries())p.categoryKey===n&&this.isBlockSelectable(c)&&i.push(c);let o=i.filter(c=>t.has(c)).length,l=i.length>0&&o===i.length,r=o>0&&!l;s.disabled=i.length===0,s.classList.toggle("on",l),s.classList.toggle("partial",r),s.setAttribute("aria-pressed",l?"true":r?"mixed":"false"),s.setAttribute("title",l?`Remove all ${i.length.toLocaleString()} seats in this category from the selection`:r?`Select the remaining ${(i.length-o).toLocaleString()} seats in this category`:`Select all ${i.length.toLocaleString()} seats in this category`);let d=s.querySelector("[data-cat-count]");d&&(d.textContent=o?`${o.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)??C.UNGROUPED_ID;if(!(this.blockedSection&&i!==this.blockedSection)){if(e){let o=this.doc?.categories.find(p=>p.key===n.categoryKey)?.label??n.categoryKey,l=this.sectionLabelById.get(i)??"Other seats",r=this.doc?.objects.find(p=>p.id===n.rowId),d=r?.type==="row"||r?.type==="table"?r.label:"";if(!`${s} ${o} ${l} ${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(([,c])=>c==="blocked").length,t=this.filteredBlockedSeats(),s=t.slice(0,this.blockedResultLimit),n=new Set(this.selectionLabels()),i=t.filter(c=>n.has(c.label)).length,o=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 l=this.els.selblocked;l.disabled=t.length===0,l.textContent=o?`Remove ${t.length.toLocaleString()} results`:`Select ${t.length.toLocaleString()} results`,this.els.blockedlist.innerHTML=s.length?s.map(c=>{let p=this.sectionByObject.get(c.rowId)??C.UNGROUPED_ID,g=this.sectionLabelById.get(p)??"Other seats",w=this.doc?.categories.find(u=>u.key===c.categoryKey)?.label??c.categoryKey,m=n.has(c.label);return`<button type="button" class="slm-blockeditem${m?" on":""}" data-blocked-label="${b(c.label)}" aria-pressed="${m}">
1229
+ `;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 p=c.target,b=p.closest("[data-blocked-label]");b?.dataset.blockedLabel?this.toggleLabels([b.dataset.blockedLabel]):p.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 p=i("releasenote");p.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,p]of this.labelToSeat.entries())p.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)??L.UNGROUPED_ID;if(!(this.blockedSection&&i!==this.blockedSection)){if(e){let a=this.doc?.categories.find(p=>p.key===n.categoryKey)?.label??n.categoryKey,o=this.sectionLabelById.get(i)??"Other seats",r=this.doc?.objects.find(p=>p.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(([,c])=>c==="blocked").length,t=this.filteredBlockedSeats(),s=t.slice(0,this.blockedResultLimit),n=new Set(this.selectionLabels()),i=t.filter(c=>n.has(c.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`,this.els.blockedlist.innerHTML=s.length?s.map(c=>{let p=this.sectionByObject.get(c.rowId)??L.UNGROUPED_ID,b=this.sectionLabelById.get(p)??"Other seats",y=this.doc?.categories.find(m=>m.key===c.categoryKey)?.label??c.categoryKey,g=n.has(c.label);return`<button type="button" class="slm-blockeditem${g?" on":""}" data-blocked-label="${u(c.label)}" aria-pressed="${g}">
1123
1230
  <span class="slm-blockedcheck" aria-hidden="true">\u2713</span>
1124
- <span class="slm-blockedcopy"><span class="slm-blockedlabel">${b(c.label)}</span>
1125
- <span class="slm-blockedmeta">${b(g)} \xB7 ${b(w)}</span></span>
1126
- </button>`}).join("")+(t.length>s.length?'<button type="button" class="slm-blockedmore" data-blocked-more>Show 100 more</button>':""):`<div class="slm-blockedempty">${e?"No blocked seats match this search or section.":"No seats are blocked. Newly blocked seats will appear here."}</div>`;let r=this.els.markall,d=r.dataset.confirm==="true";r.disabled=e===0,r.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>`)}};Oe();Se();ae();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});
1231
+ <span class="slm-blockedcopy"><span class="slm-blockedlabel">${u(c.label)}</span>
1232
+ <span class="slm-blockedmeta">${u(b)} \xB7 ${u(y)}</span></span>
1233
+ </button>`}).join("")+(t.length>s.length?'<button type="button" class="slm-blockedmore" data-blocked-more>Show 100 more</button>':""):`<div class="slm-blockedempty">${e?"No blocked seats match this search or section.":"No seats are blocked. Newly blocked seats will appear here."}</div>`;let r=this.els.markall,d=r.dataset.confirm==="true";r.disabled=e===0,r.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>`)}};ze();Se();ae();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});