@starlove/orbit 1.2.1 → 1.3.1

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.
@@ -0,0 +1,742 @@
1
+ var Xn=Object.defineProperty;var _=(e,t)=>()=>(e&&(t=e(e=0)),t);var ut=(e,t)=>{for(var a in t)Xn(e,a,{get:t[a],enumerable:!0})};var y,ue,te,T,G,k,ke,Me,Kt,$e,pt,pe,ja,Jt,ie=_(()=>{y=e=>document.querySelector(e),ue=y("#boardMenuBtn"),te=y("#boardFlyout"),T=y("#kanban"),G=y("#drawer"),k=y("#drawerInner"),ke=y("#drawerBackdrop"),Me=y("#createFlyout"),Kt=y("#createFlyoutInner"),$e=y("#createFlyoutBackdrop"),pt=y("#searchInput"),pe=y("#searchResults"),ja=y("#themeToggle"),Jt=y("#themeIcon")});function Pe(e){try{return e??globalThis.localStorage??null}catch{return null}}function Yt(e){return typeof window<"u"&&typeof window.matchMedia=="function"?window.matchMedia(e):{matches:!1}}function mt(e=Pe()){let a=Pe(e)?.getItem?.(Ha);return a==="true"?!0:a==="false"?!1:null}function Wt(e=Yt){try{return!!e("(prefers-reduced-motion: reduce)")?.matches}catch{return!1}}function Ae({storage:e=Pe(),mediaMatcher:t=Yt}={}){return mt(e)??Wt(t)}function qa(e,t=Pe()){let a=Pe(t),n=e?"true":"false";return a?.setItem?.(Ha,n),e}function Ye({doc:e=globalThis.document,storage:t=Pe(),mediaMatcher:a=Yt}={}){let n=e?.documentElement,r=mt(t);return n&&(r===!0?n.setAttribute("data-motion","reduce"):r===!1?n.setAttribute("data-motion","full"):n.removeAttribute("data-motion")),Ae({storage:t,mediaMatcher:a})}var Ha,Vt=_(()=>{Ha="mab_reduce_motion"});function Be(e){try{return e??globalThis.localStorage??null}catch{return null}}function Fe(e){try{return e??globalThis.document??null}catch{return null}}function Xt(e){try{return e??globalThis.window??null}catch{return null}}function Qn(e){return Qt.has(e)?e:"light"}function za(e=Be()){let a=Be(e)?.getItem?.(Ua);return Qt.has(a)?a:null}function me({doc:e=Fe(),storage:t=Be()}={}){let a=Fe(e)?.documentElement?.getAttribute?.("data-theme");return Qt.has(a)?a:za(t)??"light"}function Ga({doc:e=Fe(),storage:t=Be()}={}){let a=za(t);return a&&Fe(e)?.documentElement?.setAttribute?.("data-theme",a),me({doc:e,storage:t})}function Zt(e,{doc:t=Fe(),storage:a=Be(),eventTarget:n=Xt(),notify:r=!0}={}){let o=Qn(e);return Fe(t)?.documentElement?.setAttribute?.("data-theme",o),Be(a)?.setItem?.(Ua,o),r&&Zn(o,n),o}function Ka(e={}){let t=me(e)==="dark"?"light":"dark";return Zt(t,e)}function Zn(e,t=Xt()){let a=Xt(t);if(typeof a?.dispatchEvent=="function"){if(typeof CustomEvent=="function"){a.dispatchEvent(new CustomEvent(ft,{detail:{theme:e}}));return}a.dispatchEvent({type:ft,detail:{theme:e}})}}var Ua,ft,Qt,ea=_(()=>{Ua="mab_theme",ft="orbit:theme-change",Qt=new Set(["light","dark"])});function We(e){return!e||!ht.has(e)?"lanes":e}var ht,bt=_(()=>{ht=new Set(["lanes","appearance","ai","notes","journal","repository","archive"])});var Wa={};ut(Wa,{boardLabelCatalog:()=>na,currentBoard:()=>q,getSettingsTab:()=>aa,isAiReadyState:()=>ra,selectableStatesForProject:()=>oa,state:()=>c,statesForProject:()=>Re,syncBoardSelection:()=>xe,ticketsForProject:()=>Y,upsertTicket:()=>ia,visibleStatesForProject:()=>Ee});function aa(){return We(c.settingsTab||localStorage.getItem("mab_settings_tab"))}function xe(){if(!c.data)return;let e=c.data.boards||[],t=c.boardId?e.find(a=>a.id===c.boardId):null;if(!t&&c.boardSlug&&(t=e.find(a=>a.slug===c.boardSlug)||e.find(a=>a.id===c.boardSlug)),!t){let a=c.data.active_board_id;t=e.find(n=>n.id===a)||e[0]||null}c.boardId=t?.id||"",c.boardSlug=t?.slug||""}function q(){return(c.data?.boards||[]).find(e=>e.id===c.boardId)}function na(){return c.boardId?(c.data?.labels||[]).filter(e=>e.board_id===c.boardId):[]}function Re(){return c.data.states.filter(e=>e.board_id===c.boardId)}function ra(e){return e?.role==="ai_ready"||e?.name==="AI Ready"}function Ee(){let e=Re();return q()?.ai_enabled!==0?e:e.filter(t=>!ra(t))}function oa(e=""){let t=Re();return q()?.ai_enabled!==0?t:t.filter(a=>!ra(a)||a.id===e)}function Y(){return c.data.tickets.filter(e=>e.board_id===c.boardId)}function or(e){return e?{id:e.id,board_id:e.board_id,board_slug:e.board_slug,number:e.number,title:e.title,type:e.type,state_name:e.state_name,state_role:e.state_role,priority:e.priority}:null}function ir(e){if(!c.data?.tickets)return;let t=c.data.tickets.filter(r=>r.board_id===e&&!r.archived_at),a=new Map(t.map(r=>[r.id,r])),n=new Map;for(let r of t)r.parent_ticket_id&&n.set(r.parent_ticket_id,(n.get(r.parent_ticket_id)||0)+1);for(let r of t)r.parent_ticket=r.parent_ticket_id?or(a.get(r.parent_ticket_id)):null,r.child_count=n.get(r.id)||0}function ia(e){if(!c.data?.tickets||!e?.id)return;let t=c.data.tickets.findIndex(r=>r.id===e.id),a=t>=0?c.data.tickets[t]:{},n={...a,...e,labels:e.labels||a.labels||[],comment_count:e.comment_count??a.comment_count??0,child_count:e.child_count??a.child_count??0,parent_ticket:e.parent_ticket||a.parent_ticket||null};t>=0?c.data.tickets.splice(t,1,n):c.data.tickets.push(n),c.data.tickets.sort((r,o)=>String(o.updated_at||"").localeCompare(String(r.updated_at||""))||String(r.id).localeCompare(String(o.id))),ir(n.board_id||c.boardId)}var c,U=_(()=>{bt();c={data:null,boardId:"",boardSlug:"",selectedTicketId:"",expandedCardIds:new Set,detailMode:"empty",settingsTab:We(localStorage.getItem("mab_settings_tab")),showPriority:localStorage.getItem("mab_show_priority")!=="false",eventSource:null}});function d(e){return String(e??"").replaceAll("&","&amp;").replaceAll("<","&lt;").replaceAll(">","&gt;").replaceAll('"',"&quot;").replaceAll("'","&#039;")}function cr(e){if(!e)return e;let t=e;for(let[a,n]of sr)t=t.split(a).join(n);return t}function X(e){return e?cr(String(e)).replace(/\r\n?/g,`
2
+ `):""}function ce(e){return d(X(e))}function lr(e){let t=String(e||"").trim();if(!t)return"";let a=t.replace(/[\u0000-\u001f\u007f\s]+/g,"").toLowerCase();if(/^(?:javascript|data|vbscript):/.test(a))return"";let n=a.match(/^([a-z][a-z0-9+.-]*):/);return n&&!dr.has(`${n[1]}:`)?"":t}function sa(e){let t=d(e);return t=t.replace(/(\*\*|__)(?=\S)([\s\S]*?\S)\1/g,"<strong>$2</strong>"),t=t.replace(/(\*|_)(?=\S)([^*_]*?\S)\1/g,"<em>$2</em>"),t}function ca(e){let t=/\[([^\]\n]+)\]\(([^)\s]+)(?:\s+"[^"]*")?\)/g,a="",n=0,r;for(;r=t.exec(e);){a+=sa(e.slice(n,r.index));let o=sa(r[1]),s=lr(r[2]);a+=s?`<a href="${d(s)}" target="_blank" rel="noopener noreferrer">${o}</a>`:o,n=r.index+r[0].length}return a+=sa(e.slice(n)),a}function gt(e){let t=String(e??""),a="",n=0;for(;n<t.length;){let r=t.indexOf("`",n);if(r===-1){a+=ca(t.slice(n));break}let o=t.indexOf("`",r+1);if(o===-1){a+=ca(t.slice(n));break}a+=ca(t.slice(n,r)),a+=`<code>${d(t.slice(r+1,o))}</code>`,n=o+1}return a}function ur(e){return`<p>${gt(e.join(`
3
+ `)).replaceAll(`
4
+ `,"<br>")}</p>`}function pr(e){let t=e.match(/^\[( |x|X)\]\s+(.*)$/);if(!t)return null;let a=t[1].toLowerCase()==="x",n=gt(t[2].trim()).replaceAll(`
5
+ `,"<br>");return{checked:a,html:`<input type="checkbox" disabled${a?" checked":""}> ${n}`}}function da(e){let t=X(e);if(!t.trim())return"";let a=[],n=t.split(`
6
+ `),r=[],o=null,s=null,i=()=>{r.length&&(a.push(ur(r)),r=[])},l=()=>{if(!o)return;let p=o.taskList?' class="task-list"':"";a.push(`<${o.type}${p}>${o.items.map(f=>`<li${f.taskClass?` class="${f.taskClass}"`:""}>${f.html}</li>`).join("")}</${o.type}>`),o=null},u=()=>{s&&(a.push(`<blockquote>${da(s.join(`
7
+ `))}</blockquote>`),s=null)},m=()=>{i(),l(),u()};for(let p=0;p<n.length;p+=1){let f=n[p];if(/^\s*```/.test(f)){m();let C=[];for(p+=1;p<n.length&&!/^\s*```\s*$/.test(n[p]);)C.push(n[p]),p+=1;a.push(`<pre><code>${d(C.join(`
8
+ `))}</code></pre>`);continue}if(/^\s*(?:-\s*){3,}\s*$/.test(f)||/^\s*(?:\*\s*){3,}\s*$/.test(f)||/^\s*(?:_\s*){3,}\s*$/.test(f)){m(),a.push("<hr>");continue}let b=f.match(/^\s{0,3}(#{1,6})\s+(.+?)\s*#*\s*$/);if(b){m();let C=b[1].length;a.push(`<h${C}>${gt(b[2])}</h${C}>`);continue}let w=f.match(/^\s{0,3}>\s?(.*)$/);if(w){i(),l(),s||(s=[]),s.push(w[1]);continue}if(s&&!f.trim()){u();continue}if(u(),!f.trim()){i(),l();continue}let $=f.match(/^\s*\d+[.)]\s+(.+)$/),P=f.match(/^\s*[-*+]\s+(.+)$/);if($||P){i();let C=$?"ol":"ul",J=($||P)[1].trim(),B=null;P&&(B=pr(J)),(!o||o.type!==C||!!o.taskList!=!!B)&&(l(),o={type:C,items:[],taskList:!!B}),B?o.items.push({html:B.html,taskClass:B.checked?"task-item task-item-done":"task-item"}):o.items.push({html:gt(J).replaceAll(`
9
+ `,"<br>")});continue}l(),r.push(f)}return m(),a.join("")}function Ve(e){return e?new Intl.DateTimeFormat(void 0,{month:"short",day:"numeric",hour:"numeric",minute:"2-digit"}).format(new Date(e)):""}function Va(e){return e?new Intl.DateTimeFormat(void 0,{year:"numeric",month:"short",day:"numeric",hour:"numeric",minute:"2-digit",second:"2-digit"}).format(new Date(e)):""}function ae(e){return`#${e.number}`}function Xe(e){let t=e?.state_role||e?.role||e?.state_name||e?.name||"state";return String(t).toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-|-$/g,"")||"state"}function N(e){return e==="epic"||e==="feature"||e==="bug"||e==="task"?e:"task"}function De(e){return{epic:"Epic",feature:"Feature",task:"Task",bug:"Bug"}[N(e)]||"Task"}function Xa(e){return{epic:"Epic",feature:"Feature",task:"Task",bug:"Bug"}[N(e)]||"Task"}function Ne(e){return{0:"MAYBE",1:"LOW",2:"MED",3:"HIGH",4:"URGENT"}[Number(e)]||"MED"}function Oe(e){let t=["maybe","low","med","high","urgent"],a=Number(e);return t[Number.isFinite(a)?Math.max(0,Math.min(4,a)):2]}function Qa(e=[]){return e.length?`
10
+ <div class="labels">
11
+ ${e.map(t=>`<span class="label" style="--label-color: ${d(t.color)}">${d(t.name)}</span>`).join("")}
12
+ </div>
13
+ `:""}function Za(e){let t=String(e||"").trim();if(!t)return"Not set";let a=t.match(/github\.com\/([^/\s]+)\/([^/\s]+?)(?:\.git)?$/i);if(a)return`${a[1]}/${a[2]}`;let n=t.match(/github\.com[:/]([^/\s]+)\/([^/\s]+?)(?:\.git)?$/i);return n?`${n[1]}/${n[2]}`:t}var sr,dr,ne=_(()=>{sr=[["\u0393\xC7\xF4","\u2013"],["\u0393\xC7\xF6","\u2014"],["\u0393\xC7\xA3",'"'],["\u0393\xC7\xA5",'"'],["\u0393\xC7\xFF","'"],["\u0393\xC7\xD6","'"],["\u0393\xC7\xAA","\u2026"],["\u0393\xC7\xF3","\u2022"],["\u0393\xC7\u2591","\u2030"],["\u0393\xC7\u2563","\u2039"],["\u0393\xC7\u2551","\u203A"],["\u0393\xF6\xC7","\u2500"],["\u0393\xF6\xE9","\u2502"],["\u0393\xF6\xEE","\u250C"],["\u0393\xF6\xC9","\u2510"],["\u0393\xF6\xF6","\u2514"],["\u0393\xF6\xFF","\u2518"],["\u0393\xF6\xA3","\u251C"],["\u0393\xF6\xF1","\u2524"],["\u0393\xF6\xBC","\u252C"],["\u0393\xF6\u2524","\u2534"],["\u0393\xF6\u255D","\u253C"],["\u0393\xF2\xC9","\u2550"],["\u0393\xF2\xE6","\u2551"],["\u0393\xF2\xC6","\u2552"],["\u0393\xF2\xF6","\u2554"],["\u0393\xF2\xA1","\u256D"],["\u0393\xF2\xAB","\u256E"],["\u0393\xF2\xBB","\u256F"],["\u0393\xF2\u2591","\u2570"],["\u0393\xFB\xE6","\u2591"],["\u0393\xFB\xC6","\u2592"],["\u0393\xFB\xF4","\u2593"],["\u0393\xFB\xC9","\u2590"],["\u0393\xFB\xEE","\u258C"],["\u0393\xFB\xC4",">"],["\u0393\xFB\xE1","\u25A0"],["\u0393\xFB\u255D","\u25BC"],["\u0393\xF9\xC5","\u25CF"],["\u0393\xF9\xEF","\u25CB"],["\u0393\xDC\xF2","\u2695"],["\u0393\xDC\xE1","\u26A0"],["\u0393\xDC\xED","\u26A1"],["\u0393\xDC\xF4","\u2693"],["\u0393\xE5\xC9","\u2190"],["\u0393\xE5\xE6","\u2191"],["\u0393\xE5\xC6","\u2192"],["\u0393\xE5\xF4","\u2193"],["\u0393\xE5\xF6","\u2194"],["\u252C\xE1"," "],["\u252C\u2310","\xA9"],["\u252C\xAB","\xAE"],["\u252C\u2591","\xB0"],["\u252C\xBA","\xA7"],["\u252C\u2556","\xB7"],["\u201C",'"'],["\u201D",'"'],["\u2018","'"],["\u2019","'"]];dr=new Set(["http:","https:","mailto:","tel:"])});function fr(){return Se&&Se.isConnected||(Se=document.createElement("div"),Se.className="toast-container",document.body.append(Se)),Se}function h(e,t="info",a=4e3){let n=fr(),r=document.createElement("div");r.className=`toast toast-${t}`,r.setAttribute("role","status");let o=mr[t];r.innerHTML=`<span class="toast-icon">${o}</span><span class="toast-msg">${d(e)}</span><button class="toast-close" aria-label="Dismiss">&times;</button>`,r.querySelector(".toast-close").addEventListener("click",()=>la(r)),n.prepend(r),requestAnimationFrame(()=>requestAnimationFrame(()=>r.classList.add("toast-enter")));let s=setTimeout(()=>la(r),a);r.addEventListener("mouseenter",()=>clearTimeout(s)),r.addEventListener("mouseleave",()=>{let i=setTimeout(()=>la(r),1500);r.addEventListener("mouseenter",()=>clearTimeout(i),{once:!0})})}function la(e){e.classList.contains("toast-exit")||(e.classList.add("toast-exit"),e.addEventListener("animationend",()=>e.remove(),{once:!0}))}function en(e,t){let a=new Blob([JSON.stringify(t,null,2)],{type:"application/json"}),n=URL.createObjectURL(a),r=document.createElement("a");r.href=n,r.download=e,document.body.append(r),r.click(),r.remove(),URL.revokeObjectURL(n)}function yt(e,t){let a=0;return(...n)=>{clearTimeout(a),a=setTimeout(()=>e(...n),t)}}var mr,Se,fe=_(()=>{ne();mr={info:'<svg viewBox="0 0 20 20" fill="currentColor"><path fill-rule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a.75.75 0 000 1.5h.253a.25.25 0 01.244.304l-.459 2.066A1.75 1.75 0 0010.747 15H11a.75.75 0 000-1.5h-.253a.25.25 0 01-.244-.304l.459-2.066A1.75 1.75 0 009.253 9H9z" clip-rule="evenodd"/></svg>',success:'<svg viewBox="0 0 20 20" fill="currentColor"><path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z" clip-rule="evenodd"/></svg>',warning:'<svg viewBox="0 0 24 24" fill="currentColor"><path fill-rule="evenodd" d="M9.401 3.003c1.155-2 4.043-2 5.197 0l7.355 12.748c1.154 2-.29 4.5-2.599 4.5H4.645c-2.309 0-3.752-2.5-2.598-4.5L9.4 3.003zM12 8.25a.75.75 0 01.75.75v3.75a.75.75 0 01-1.5 0V9a.75.75 0 01.75-.75zm0 8.25a.75.75 0 100-1.5.75.75 0 000 1.5z" clip-rule="evenodd"/></svg>',error:'<svg viewBox="0 0 20 20" fill="currentColor"><path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zM8.28 7.22a.75.75 0 00-1.06 1.06L8.94 10l-1.72 1.72a.75.75 0 101.06 1.06L10 11.06l1.72 1.72a.75.75 0 101.06-1.06L11.06 10l1.72-1.72a.75.75 0 00-1.06-1.06L10 8.94 8.28 7.22z" clip-rule="evenodd"/></svg>'},Se=null;h.info=(e,t)=>h(e,"info",t);h.success=(e,t)=>h(e,"success",t);h.warning=(e,t)=>h(e,"warning",t);h.error=(e,t)=>h(e,"error",t)});async function tn({method:e="GET",path:t,body:a,headers:n}){let r={"Content-Type":"application/json",...n||{}},o=await fetch(t,{method:e,headers:r,body:a!==void 0?JSON.stringify(a):void 0}),s=await o.text(),i=s?JSON.parse(s):{};if(!o.ok){let l=new Error(i.error||o.statusText);throw l.payload=i,l.status=o.status,l}return i}var an=_(()=>{});var nn={};ut(nn,{api:()=>v,bootstrapPath:()=>Qe,withBoardQuery:()=>x});function Qe(){return`/api/bootstrap${c.boardId?`?board_id=${encodeURIComponent(c.boardId)}`:c.boardSlug?`?board=${encodeURIComponent(c.boardSlug)}`:""}`}function x(e){if(!c.boardId||e.includes("board_id="))return e;let t=e.includes("?")?"&":"?";return`${e}${t}board_id=${encodeURIComponent(c.boardId)}`}async function v(e,t={}){try{return await tn({method:t.method||"GET",path:e,body:t.body,headers:t.headers})}catch(a){throw h.error(a.payload?.error||a.message||"Request failed"),a}}var Q=_(()=>{U();fe();an()});function pa(){ua+=1,G.hidden=!1,ke.hidden=!1,requestAnimationFrame(()=>{G.classList.add("is-open"),ke.classList.add("is-visible")})}function vt(){let e=++ua,t=G.classList.contains("is-open");G.classList.remove("is-open"),ke.classList.remove("is-visible");let a=()=>{if(ua!==e)return;G.hidden=!0,ke.hidden=!0,k.innerHTML="";let o=document.getElementById("drawerTitleBlock"),s=document.getElementById("drawerTabs");o&&(o.innerHTML=""),s&&(s.innerHTML="",s.hidden=!0),G.classList.remove("is-wide")};if(!t){a();return}let n=!1,r=()=>{n||(n=!0,a())};G.addEventListener("transitionend",r,{once:!0}),setTimeout(r,360)}function wt({eyebrow:e,title:t,titleAttrs:a,subtitleHtml:n,tabs:r,activeTab:o,onTabSelect:s,body:i,mode:l}){G.classList.toggle("is-settings",l==="settings"),G.classList.toggle("is-wide",l==="ticket"||l==="settings");let u=document.getElementById("drawerTitleBlock"),m=document.getElementById("drawerTabs"),f=` class="drawer-title drawer-title-text${a?.class?` ${a.class}`:""}"`;for(let[$,P]of Object.entries(a||{}))$!=="class"&&(f+=` ${$}="${d(String(P))}"`);let b=[];e&&b.push(`<span class="drawer-eyebrow">${d(e)}</span>`),b.push(`<h2${f}>${d(t??"")}</h2>`),n&&b.push(`<div class="drawer-subtitle">${n}</div>`),u.innerHTML=b.join(""),r&&r.length?(m.hidden=!1,m.innerHTML=r.map($=>`<button type="button" role="tab" class="drawer-tab ${$.id===o?"is-active":""}" data-drawer-tab="${d($.id)}" aria-selected="${$.id===o}">${d($.label)}</button>`).join(""),typeof s=="function"&&m.querySelectorAll(".drawer-tab").forEach($=>{$.addEventListener("click",()=>s($.dataset.drawerTab))})):(m.hidden=!0,m.innerHTML="");let w=document.getElementById("drawerArchiveBtn");w&&(w.hidden=c.detailMode!=="ticket"),k.innerHTML=i??""}var ua,kt=_(()=>{ie();U();ne();ua=0});function vr(e,t=Ee()){return e?[{id:"move",label:"Move to",children:t.map(a=>({id:`move:${a.id}`,label:a.name,action:"move",value:a.id,checked:a.id===e.state_id,disabled:a.id===e.state_id}))},{id:"priority",label:"Priority",children:br.map(a=>({id:`priority:${a}`,label:Ne(a),action:"priority",value:a,checked:Number(e.priority)===a,disabled:Number(e.priority)===a}))},{id:"type",label:"Type",children:hr.map(a=>({id:`type:${a}`,label:De(a),action:"type",value:a,checked:N(e.type)===a,disabled:N(e.type)===a}))},{id:"open",label:"Open",action:"open"},{id:"archive",label:"Archive",action:"archive",danger:!0}]:[]}function wr({x:e,y:t,menuWidth:a,menuHeight:n,viewportWidth:r,viewportHeight:o,margin:s=fa}){let i=Math.max(s,r-a-s),l=Math.max(s,o-n-s),u=e+a+s>r?e-a:e,m=t+n+s>o?t-n:t;return{left:Math.min(Math.max(s,u),i),top:Math.min(Math.max(s,m),l)}}function kr({triggerRect:e,submenuWidth:t,submenuHeight:a,viewportWidth:n,viewportHeight:r,margin:o=fa,gap:s=gr}){let i=Math.max(o,n-t-o),l=e.right+s,u=e.left-t-s,m=l+t+o<=n,p=u>=o,f=m||!p?l:u,b=Math.max(0,r-o*2),w=Math.min(a,b),$=Math.max(o,r-w-o),P=e.top-s;return{left:Math.min(Math.max(o,f),i),top:Math.min(Math.max(o,P),$),maxHeight:b}}function St({apiClient:e=v,navigator:t=null,confirmer:a=globalThis.confirm}={}){async function n(r,o){await e(x(`/api/tickets/${encodeURIComponent(r.id)}`),{method:"PATCH",body:o})}return{async open(r){return t?t({boardId:c.boardId,view:"ticket",ticketId:r.id}):null},async move(r,o){await n(r,{state_id:o})},async priority(r,o){await n(r,{priority:o})},async type(r,o){await n(r,{type:o})},async archive(r){return typeof a=="function"&&!a(`Archive "${r.title||"card"}"? You can restore it from Settings \u2192 Card Archive.`)?!1:(await e(x(`/api/tickets/${encodeURIComponent(r.id)}/archive`),{method:"POST"}),h.error(`Archived: ${r.title||"card"}`),!0)}}}function ba(e){ha=!!e}function re({restoreFocus:e=!1}={}){de(),Ze&&(Ze.abort(),Ze=null);for(let t of tt)t.isConnected&&t.remove();tt.clear(),K&&(K.querySelectorAll(".card-action-menu-item.has-submenu").forEach(t=>{let a=Le.get(t);a?.isConnected&&a.remove(),Le.delete(t)}),K.remove(),K=null),e&&$t?.isConnected&&$t.focus({preventScroll:!0}),$t=null}function $r({ticket:e,anchor:t,x:a,y:n,handlers:r=St(),onBeforeOpen:o=null}){if(re(),!e||ha)return null;typeof o=="function"&&o(),$t=t||document.activeElement;let s=document.createElement("div");s.className="card-action-menu",s.setAttribute("role","menu"),s.setAttribute("aria-label",`Actions for #${e.number||""} ${e.title||"card"}`.trim()),s.dataset.ticketId=e.id,s.innerHTML=sn(vr(e)),document.body.append(s),K=s,s.querySelectorAll(".card-action-menu-item.has-submenu").forEach(p=>{let f=p.querySelector(":scope > .card-action-submenu");f&&(f.remove(),document.body.append(f),Le.set(p,f),ma.set(f,p),Sr(f,e,r))});let i=s.getBoundingClientRect(),l=wr({x:a,y:n,menuWidth:i.width,menuHeight:i.height,viewportWidth:window.innerWidth,viewportHeight:window.innerHeight});s.style.left=`${l.left}px`,s.style.top=`${l.top}px`,Er(s,e,r),ya(s)?.focus({preventScroll:!0}),Ze=new AbortController;let m=Ze.signal;return requestAnimationFrame(()=>{document.addEventListener("pointerdown",Lr,{signal:m,capture:!0})}),document.addEventListener("keydown",Tr,{signal:m,capture:!0}),document.addEventListener("scroll",Ir,{signal:m,capture:!0,passive:!0}),window.addEventListener("resize",()=>re(),{signal:m,passive:!0}),window.addEventListener("blur",()=>re(),{signal:m}),s}function on(e,t,{handlers:a=St(),onBeforeOpen:n=null}={}){e.addEventListener("contextmenu",r=>{let o=r.target instanceof Element?r.target.closest(".card"):null;if(!o)return;let s=t(o.dataset.ticketId);if(s){if(r.preventDefault(),r.stopPropagation(),ha){re();return}$r({ticket:s,anchor:o,x:r.clientX,y:r.clientY,handlers:a,onBeforeOpen:n})}})}function sn(e){return`<ul class="card-action-menu-list" role="none">${e.map(xr).join("")}</ul>`}function xr(e){let t=!!e.children?.length,a=["card-action-menu-item"];t&&a.push("has-submenu"),e.danger&&a.push("is-danger");let n=e.checked?'<span class="card-action-check" aria-hidden="true">\u2713</span>':'<span class="card-action-check" aria-hidden="true"></span>',r=t?'<span class="card-action-arrow" aria-hidden="true">\u203A</span>':"";return`
14
+ <li class="${a.join(" ")}" role="none">
15
+ <button type="button"
16
+ class="card-action-button"
17
+ role="menuitem${e.checked?"checkbox":""}"
18
+ data-action="${d(e.action||"")}" data-value="${d(e.value??"")}" data-menu-id="${d(e.id)}"
19
+ ${e.disabled?"disabled":""}
20
+ ${e.checked?'aria-checked="true"':""}
21
+ ${t?'aria-haspopup="menu" aria-expanded="false"':""}>
22
+ ${t?"":n}
23
+ <span class="card-action-label">${d(e.label)}</span>
24
+ ${r}
25
+ </button>
26
+ ${t?`<div class="card-action-submenu" role="menu">${sn(e.children)}</div>`:""}
27
+ </li>
28
+ `}function Er(e,t,a){e.addEventListener("pointerover",n=>{let r=n.target instanceof Element?n.target.closest(".card-action-menu-item"):null;!r||!e.contains(r)||(r.classList.contains("has-submenu")?(de(),xt(r)):_r(e))},!0),e.addEventListener("focusin",n=>{let r=n.target instanceof Element?n.target.closest(".card-action-menu-item"):null;!r||!e.contains(r)||(r.classList.contains("has-submenu")?(de(),xt(r)):(de(),un(e)))}),e.addEventListener("click",n=>cn(n,e,t,a)),e.addEventListener("keydown",n=>dn(n,e))}function Sr(e,t,a){e.addEventListener("pointerenter",de),e.addEventListener("pointerover",n=>{n.target instanceof Element&&e.contains(n.target)&&de()},!0),e.addEventListener("click",n=>{K&&cn(n,K,t,a,e)}),e.addEventListener("keydown",n=>{K&&dn(n,K)})}function cn(e,t,a,n,r=t){let o=e.target instanceof Element?e.target.closest("button.card-action-button"):null;if(!o||!r.contains(o)||o.disabled)return;e.preventDefault(),e.stopPropagation();let s=o.closest(".card-action-menu-item");if(s?.classList.contains("has-submenu")){de(),xt(s),ya(Le.get(s))?.focus({preventScroll:!0});return}let i=o.dataset.action,l=o.dataset.value;if(re(),i==="open")return n.open(a);if(i==="move")return n.move(a,l);if(i==="priority")return n.priority(a,Number(l));if(i==="type")return n.type(a,l);if(i==="archive")return n.archive(a)}function dn(e,t){let a=e.target instanceof Element?e.target.closest("button.card-action-button"):null;if(!a)return;let n=a.closest(".card-action-submenu");if(!t.contains(a)&&!n)return;let o=a.closest(".card-action-menu-list"),s=a.closest(".card-action-menu-item");if(e.key==="Escape"){if(e.preventDefault(),n){let i=ma.get(n),l=i?.querySelector(":scope > .card-action-button");Et(i),l?.focus({preventScroll:!0})}else re({restoreFocus:!0});return}if(e.key==="ArrowDown"||e.key==="ArrowUp"){e.preventDefault(),Cr(o,a,e.key==="ArrowDown"?1:-1);return}if(e.key==="Home"||e.key==="End"){e.preventDefault();let i=ga(o);i[e.key==="Home"?0:i.length-1]?.focus({preventScroll:!0});return}if(e.key==="ArrowRight"&&s?.classList.contains("has-submenu")){e.preventDefault(),de(),xt(s),ya(Le.get(s))?.focus({preventScroll:!0});return}if(e.key==="ArrowLeft"&&n){let i=ma.get(n),l=i?.querySelector(":scope > .card-action-button");l&&(e.preventDefault(),Et(i),l.focus({preventScroll:!0}))}}function Lr(e){K&&(ln(e)||re())}function Tr(e){e.key==="Escape"&&K&&(e.preventDefault(),re({restoreFocus:!0}))}function Ir(e){K&&(ln(e)||re())}function ln(e){let t=e.target;if(!(t instanceof Node))return!1;if(K?.contains(t))return!0;for(let a of tt)if(a.contains(t))return!0;return!1}function xt(e){let t=e.parentElement?.children||[];for(let n of t)n!==e&&n.classList?.contains("has-submenu")&&n.classList.contains("is-open")&&Et(n);let a=Le.get(e);if(a){if(e.classList.contains("is-open")){rn(e,a);return}e.classList.add("is-open"),e.querySelector(":scope > .card-action-button")?.setAttribute("aria-expanded","true"),a.classList.add("is-open"),tt.add(a),rn(e,a)}}function Et(e){if(!e)return;e.classList.remove("is-open"),e.querySelector(":scope > .card-action-button")?.setAttribute("aria-expanded","false");let t=Le.get(e);t&&(t.classList.remove("is-open"),t.style.removeProperty("left"),t.style.removeProperty("top"),t.style.removeProperty("max-height"),tt.delete(t))}function un(e){e.querySelectorAll(".card-action-menu-item.has-submenu.is-open").forEach(Et)}function _r(e){de(),et=setTimeout(()=>{et=null,K===e&&un(e)},yr)}function de(){et!=null&&(clearTimeout(et),et=null)}function rn(e,t){let a=e.querySelector(":scope > .card-action-button");if(!t||!a)return;let n=Math.max(0,window.innerHeight-fa*2);t.style.maxHeight=`${n}px`,t.style.left="0px",t.style.top="0px";let r=t.getBoundingClientRect(),o=kr({triggerRect:a.getBoundingClientRect(),submenuWidth:r.width,submenuHeight:r.height,viewportWidth:window.innerWidth,viewportHeight:window.innerHeight});t.style.left=`${o.left}px`,t.style.top=`${o.top}px`,t.style.maxHeight=`${o.maxHeight}px`}function ga(e){if(!e)return[];let t=e.classList?.contains("card-action-menu-list")?e:e.querySelector(":scope > .card-action-menu-list");return t?[...t.querySelectorAll(":scope > .card-action-menu-item > .card-action-button")].filter(a=>!a.disabled):[]}function ya(e){return ga(e)[0]||null}function Cr(e,t,a){let n=ga(e);if(!n.length)return;let r=n.indexOf(t),o=r===-1?0:(r+a+n.length)%n.length;n[o].focus({preventScroll:!0})}var hr,br,fa,gr,yr,K,ha,Ze,$t,Le,ma,tt,et,pn=_(()=>{Q();U();ne();fe();hr=["epic","feature","task","bug"],br=[0,1,2,3,4],fa=8,gr=6,yr=180,K=null,ha=!1,Ze=null,$t=null,Le=new WeakMap,ma=new WeakMap,tt=new Set,et=null});function Mr(e){return e?typeof e=="string"?{readAt:e,count:0}:{readAt:e.readAt||null,count:Number(e.count)||0}:{readAt:null,count:0}}function at(e){if(!e)return new Map;let t=wa.get(e);if(t)return t;t=new Map;try{let a=localStorage.getItem(mn(e));if(a){let n=JSON.parse(a);for(let[r,o]of Object.entries(n))t.set(r,Mr(o))}}catch{}return wa.set(e,t),t}function Lt(e){let t=wa.get(e);if(t)try{let a={};for(let[n,r]of t)a[n]=r;localStorage.setItem(mn(e),JSON.stringify(a))}catch{}}function fn(e,t){let a=e.get(t);return a||(a={readAt:null,count:0},e.set(t,a)),a}function Tt(e){let t=e?.board_id||c.boardId;if(!t||!e?.id)return 0;let n=at(t).get(e.id);return n?n.count:localStorage.getItem(va(t))==="1"?1:0}function It(e,t){let a=c.boardId;if(!a||!e)return;let n=at(a),r=fn(n,e);r.count===0&&r.readAt&&t&&r.readAt>=t||(r.count=0,t&&(r.readAt=t),Lt(a))}function hn(e){let t=c.boardId;if(!t||!e)return;let a=at(t),n=fn(a,e);n.count=(n.count||0)+1,Lt(t)}function bn(e){let t=c.boardId;if(!t||!e)return;let a=at(t);a.has(e)&&(a.delete(e),Lt(t))}function gn(e,t){if(!e||localStorage.getItem(va(e))==="1")return;let a=at(e);for(let n of t||[])!a.has(n.id)&&n.updated_at&&a.set(n.id,{readAt:n.updated_at,count:0});Lt(e);try{localStorage.setItem(va(e),"1")}catch{}}var mn,va,wa,nt=_(()=>{U();mn=e=>`mab_card_read:${e}`,va=e=>`mab_card_read_seeded:${e}`,wa=new Map});function je(){let e=Ee(),t=Y();$a=new Map(t.map(a=>[a.id,a])),T.innerHTML=e.map(a=>Br(a,t)).join("")}function Pr(e){if(!e)return;let t=e.dataset.ticketId,a=!c.expandedCardIds.has(t);if(a){if(c.expandedCardIds.add(t),!e.querySelector(".card-expandable")){let r=$a.get(t),o=e.querySelector(".card-meta");r&&o&&o.insertAdjacentHTML("afterend",wn(r))}}else c.expandedCardIds.delete(t);e.classList.toggle("is-expanded",a);let n=e.querySelector("button.card-expand-trigger");n&&n.setAttribute("aria-expanded",a?"true":"false")}function yn(){ka=ka||St({navigator:A});let e=null,t=a=>{e!==a&&(e&&e.classList.remove("drag-over"),e=a,e&&e.classList.add("drag-over"))};T.addEventListener("dragstart",a=>{let n=a.target instanceof Element?a.target.closest(".card"):null;n&&(re(),ba(!0),a.dataTransfer.setData("text/plain",n.dataset.ticketId),a.dataTransfer.effectAllowed="move")}),T.addEventListener("dragover",a=>{let n=a.target instanceof Element?a.target.closest(".column"):null;n&&(a.preventDefault(),t(n))}),T.addEventListener("dragend",()=>{ba(!1),t(null),_t=!0,setTimeout(()=>{_t=!1},0)}),T.addEventListener("drop",async a=>{let n=a.target instanceof Element?a.target.closest(".column"):null;if(!n)return;a.preventDefault(),t(null);let r=a.dataTransfer.getData("text/plain");r&&(D(),await v(x(`/api/tickets/${r}`),{method:"PATCH",body:{state_id:n.dataset.stateId}}),await I())}),T.addEventListener("click",a=>{let n=a.target instanceof Element?a.target:a.target?.parentElement;if(!n)return;let r=n.closest("[data-add-to-state]");if(r){a.stopPropagation(),Mt(r.dataset.addToState||"");return}let o=n.closest("button.card-expand-trigger");if(o){a.stopPropagation(),a.preventDefault(),Pr(o.closest(".card"));return}if(n.closest("a")){a.stopPropagation();return}let s=n.closest(".epic-mini-header[data-ticket-id]");if(s){D(),A({boardId:c.boardId,view:"ticket",ticketId:s.dataset.ticketId});return}let i=n.closest(".card");if(i){if(_t){_t=!1,a.preventDefault(),a.stopPropagation();return}D(),A({boardId:c.boardId,view:"ticket",ticketId:i.dataset.ticketId})}}),on(T,a=>$a.get(a),{handlers:ka,onBeforeOpen:D})}function vn(){T.querySelectorAll(".card.selected").forEach(e=>e.classList.remove("selected")),c.selectedTicketId&&T.querySelectorAll(`.card[data-ticket-id="${CSS.escape(c.selectedTicketId)}"]`).forEach(e=>e.classList.add("selected"))}function Ar(e){let t=e.toLowerCase(),a={icon:'<svg class="empty-state-icon" viewBox="0 0 24 24"><path d="M18 6L6 18M6 6l12 12" opacity="0.5" /></svg>',title:"Nothing here",subtitle:"Tasks will appear when ready"};return t==="ai ready"?a={icon:`<svg class="empty-state-icon ai-sparkle" viewBox="0 0 24 24">
29
+ <path d="M12 3L14.5 9L21 11.5L14.5 14L12 20L9.5 14L3 11.5L9.5 9L12 3Z" fill="currentColor" opacity="0.65" />
30
+ <circle cx="12" cy="11.5" r="1.8" fill="#fff" />
31
+ </svg>`,title:"Ready for agents",subtitle:"Drop unblocked cards here \u2014 the claim-next tool picks them up"}:t.includes("progress")?a={icon:`<svg class="empty-state-icon orbit" viewBox="0 0 100 100">
32
+ <circle cx="50" cy="50" r="10" fill="currentColor" opacity="0.9" />
33
+ <circle class="ring" cx="50" cy="50" r="30" stroke="currentColor" stroke-dasharray="4 6" />
34
+ <circle class="satellite" cx="80" cy="50" r="4" fill="currentColor" />
35
+ </svg>`,title:"Work in progress",subtitle:"Active work will appear here"}:t.includes("review")?a={icon:`<svg class="empty-state-icon star" viewBox="0 0 24 24">
36
+ <path d="M12 2L14.5 9.5L22 12L14.5 14.5L12 22L9.5 14.5L2 12L9.5 9.5L12 2Z" fill="currentColor" />
37
+ </svg>`,title:"Under review",subtitle:"Quality gate before merge"}:t.includes("todo")||t.includes("backlog")?a={icon:`<svg class="empty-state-icon ai-sparkle" viewBox="0 0 24 24">
38
+ <path d="M12 3L14.5 9L21 11.5L14.5 14L12 20L9.5 14L3 11.5L9.5 9L12 3Z" fill="currentColor" opacity="0.5" />
39
+ <path d="M19 8L20 10L21 8L20 6L19 8ZM19 16L20 18L21 16L20 14L19 16ZM5 8L6 10L7 8L6 6L5 8Z" fill="currentColor" />
40
+ </svg>`,title:"Ready for launch",subtitle:"Create a card manually or task an AI to generate tasks"}:t.includes("done")||t.includes("finished")?a={icon:`<svg class="empty-state-icon" viewBox="0 0 24 24">
41
+ <circle cx="12" cy="12" r="10" />
42
+ <path d="M8 12L11 15L16 9" />
43
+ </svg>`,title:"Done",subtitle:"Move completed tickets here"}:t.includes("cancel")&&(a={icon:`<svg class="empty-state-icon" viewBox="0 0 24 24">
44
+ <circle cx="12" cy="12" r="10" opacity="0.2" />
45
+ <path d="M15 9L9 15M9 9l6 6" />
46
+ </svg>`,title:"Not moving forward",subtitle:"Parked or replaced"}),`
47
+ <div class="column-empty-state">
48
+ <div class="empty-state-visual">
49
+ <div class="empty-state-glow"></div>
50
+ ${a.icon}
51
+ </div>
52
+ <div class="empty-state-title">${d(a.title)}</div>
53
+ <div class="empty-state-subtitle">${d(a.subtitle)}</div>
54
+ </div>
55
+ `}function Br(e,t){let a=t.filter(i=>i.state_id===e.id),n=a.length===0,r=e.name==="AI Ready",o=["column","lane"];r&&o.push("column--ai-ready");let s=r?' data-accent="ai-ready"':"";return`
56
+ <section class="${o.join(" ")}" data-flat${s} data-state-id="${e.id}" data-state-name="${d(e.name)}">
57
+ <div class="column-head lane-head">
58
+ <h2 class="lane-title"${r?' title="Agent staging \u2014 cards here are picked up by the claim-next tool when unblocked"':""}>
59
+ ${r?'<span class="agent-dot" aria-hidden="true"></span>':""}${d(e.name)}
60
+ </h2>
61
+ <div class="column-head-actions lane-actions">
62
+ <button type="button" class="column-add-btn" data-variant="plus" data-add-to-state="${d(e.id)}" title="New card">+</button>
63
+ <span class="count">${a.length}</span>
64
+ </div>
65
+ </div>
66
+ ${n?Ar(e.name):Fr(a,t)}
67
+ <button type="button" class="add-card-phantom" data-add-to-state="${d(e.id)}">+ Add a card</button>
68
+ </section>
69
+ `}function Fr(e,t){let a=new Map(t.filter(i=>N(i.type)==="epic").map(i=>[i.id,i])),n=new Set(e.filter(i=>N(i.type)==="epic").map(i=>i.id)),r=new Map;for(let i of e)if(i.parent_ticket_id&&a.has(i.parent_ticket_id)){let l=r.get(i.parent_ticket_id)||[];l.push(i),r.set(i.parent_ticket_id,l)}let o=new Set,s=[];for(let i of e)if(!o.has(i.id)){if(N(i.type)==="epic"){let l=r.get(i.id)||[];if(l.length){let u=l.map(m=>rt(m,{asEpicChild:!0})).join("");s.push(`${rt(i)}<div class="epic-children">${u}</div>`),l.forEach(m=>o.add(m.id))}else s.push(rt(i));o.add(i.id);continue}if(!(i.parent_ticket_id&&n.has(i.parent_ticket_id))){if(i.parent_ticket_id&&a.has(i.parent_ticket_id)&&!n.has(i.parent_ticket_id)){let l=a.get(i.parent_ticket_id),u=r.get(i.parent_ticket_id)||[],m=u.map(p=>rt(p,{asEpicChild:!0})).join("");s.push(`${Rr(l)}<div class="epic-children">${m}</div>`),u.forEach(p=>o.add(p.id));continue}s.push(rt(i)),o.add(i.id)}}return s.join("")}function Rr(e){return`
70
+ <div class="epic-mini-header" data-ticket-id="${d(e.id)}" title="Open epic">
71
+ <div class="card-type-id type-pill-epic">
72
+ ${Ct("epic")}
73
+ <span class="card-type-label">EPIC</span>
74
+ </div>
75
+ <span class="ticket-number">${d(ae(e))}</span>
76
+ <span class="epic-mini-title">${d(e.title)}</span>
77
+ </div>
78
+ `}function xa(e){let t=Oe(e),a=Ne(e);return`<div class="card-priority-id priority-pill" data-variant="${d(t)}"><span class="card-priority-label">${d(a)}</span></div>`}function Ct(e){let t=N(e),a="",n="currentColor";switch(t){case"epic":n="#c084fc",a='<path d="M12 2L14.5 9.5L22 12L14.5 14.5L12 22L9.5 14.5L2 12L9.5 9.5L12 2Z" fill="currentColor" />';break;case"feature":n="#4ade80",a='<path d="M19 21l-7-5-7 5V5a2 2 0 012-2h10a2 2 0 012 2v16z" fill="currentColor" />';break;case"bug":n="#f87171",a='<circle cx="12" cy="12" r="10" /><path d="M12 8v4M12 16h.01" />';break;default:n="#60a5fa",a='<rect x="3" y="3" width="18" height="18" rx="2" /><path d="M9 12l2 2 4-4" />'}return`
79
+ <svg class="card-type-icon" viewBox="0 0 24 24" style="color: ${n}">
80
+ ${a}
81
+ </svg>
82
+ `}function rt(e,{asEpicChild:t=!1}={}){let a=N(e.type),n=Oe(e.priority),r=De(e.type).toUpperCase(),o=c.expandedCardIds.has(e.id),i=!!String(e.description||"").trim()||e.labels&&e.labels.length||e.parent_ticket||e.child_count,l=`
83
+ <span class="ticket-number">${d(ae(e))}</span>
84
+ <div class="card-type-id type-pill-${d(a)}">
85
+ ${Ct(e.type)}
86
+ <span class="card-type-label">${d(r)}</span>
87
+ </div>
88
+ ${c.showPriority?xa(e.priority):""}
89
+ ${i?'<svg class="card-expand-chevron" viewBox="0 0 24 24" aria-hidden="true"><path d="M6 9l6 6 6-6" /></svg>':""}
90
+ `,u=Tt(e),m=u===0?"":u===1?'<span class="card-unread-dot" role="status" aria-label="1 unread update"></span>':`<span class="card-unread-dot has-count" role="status" aria-label="${u} unread updates">${u>99?"99+":u}</span>`;return`
91
+ <article class="card type-${d(a)} priority-${d(n)}${o?" is-expanded":""}${t?" is-epic-child":""} ${e.id===c.selectedTicketId?"selected":""}" data-variant="${d(a)}" draggable="true" data-ticket-id="${e.id}">
92
+ ${m}
93
+ <h3>${d(e.title)}</h3>
94
+
95
+ <div class="card-meta">
96
+ ${i?`<button type="button" class="card-expand-trigger" data-variant="card-accordion" data-card-toggle aria-expanded="${o?"true":"false"}">${l}</button>`:`<div class="card-expand-trigger card-expand-trigger--static">${l}</div>`}
97
+ </div>
98
+
99
+ ${i&&o?wn(e):""}
100
+ </article>
101
+ `}function wn(e){return`
102
+ <div class="card-expandable">
103
+ ${!!String(e.description||"").trim()?`<div class="card-description markdown-body">${da(e.description)}</div>`:""}
104
+ ${Qa(e.labels)}
105
+ ${e.parent_ticket?`<div class="parent-line">-> ${d(ae(e.parent_ticket))}</div>`:""}
106
+ ${e.child_count?`<div class="child-count">${e.child_count} feature${e.child_count===1?"":"s"} inside</div>`:""}
107
+ </div>
108
+ `}function kn(){let a=()=>Math.max(T.clientWidth,1),n=!1,r=!1,o=0,s=0,i=0,l=p=>p instanceof Element?!!(p.closest(".card")||p.closest("a, button, input, select, textarea, [draggable='true']")):!1,u=(p,f)=>f===WheelEvent.DOM_DELTA_LINE?p*16:f===WheelEvent.DOM_DELTA_PAGE?p*a():p;T.addEventListener("wheel",p=>{if(p.defaultPrevented||p.ctrlKey)return;let f=p.deltaX||(p.shiftKey?p.deltaY:0);!f||!(Math.abs(f)>=Math.abs(p.deltaY)||p.shiftKey)||T.scrollWidth<=T.clientWidth||(p.preventDefault(),T.scrollLeft+=u(f,p.deltaMode))},{passive:!1}),T.addEventListener("pointerdown",p=>{p.button===0&&(l(p.target)||(n=!0,r=!1,i=p.pointerId,o=p.clientX,s=T.scrollLeft,T.classList.add("is-grabbing")))}),T.addEventListener("pointermove",p=>{if(!n||p.pointerId!==i)return;let f=p.clientX-o;if(!r&&Math.abs(f)>4){r=!0;try{T.setPointerCapture(i)}catch{}}r&&(p.preventDefault(),T.scrollLeft=s-f)});let m=p=>{if(!(!n||p&&p.pointerId!==i)){n=!1,T.classList.remove("is-grabbing");try{T.releasePointerCapture(i)}catch{}}};T.addEventListener("pointerup",m),T.addEventListener("pointercancel",m),T.addEventListener("pointerleave",m),T.addEventListener("click",p=>{r&&(p.stopPropagation(),p.preventDefault(),r=!1)},!0)}var $a,ka,_t,ot=_(()=>{ie();U();ne();Q();be();He();he();pn();nt();$a=new Map,ka=null,_t=!1});var $n,Te,O,qe=_(()=>{$n="full";$n="full";Te=$n,O={sse:Te==="full",ai:Te==="full",multiBoard:Te==="full",tokenAuth:Te==="full",attachments:Te==="full"}});async function ge(){let e=await v(`/api/boards/${c.boardId}/context?include_struck=true`),t=e.board,a=aa(),n=[{id:"lanes",label:"Lanes"},{id:"appearance",label:"Appearance"},{id:"archive",label:"Card Archive"},{id:"notes",label:"Notes"},{id:"journal",label:"Journal"},...O.ai?[{id:"ai",label:"AI"}]:[],{id:"repository",label:"Repository"}],r=a==="ai"&&!O.ai?"lanes":a;wt({eyebrow:"SETTINGS",mode:"settings",title:t.name,tabs:n,activeTab:r,onTabSelect:async o=>{A({boardId:c.boardId,view:"settings",tab:o})},body:Dr(e,r)}),no(e,r)}function Dr(e,t){switch(t){case"notes":return Zr(e);case"lanes":return En();case"appearance":return eo();case"ai":return O.ai?Nr(e):En();case"journal":return to(e);case"archive":return Yr();case"repository":default:return Wr(e)}}function Nr(e){let t=e.board,a=t.ai_enabled!==0,n=a?'<div class="separator" aria-hidden="true"></div>':"",r=a?Or(t):"",o=a&&O.multiBoard?Vr(t):"",s=a?jr(e):"";return`
109
+ <div class="section">
110
+ <label class="orbit-check" for="aiEnabledToggle">
111
+ <input
112
+ type="checkbox"
113
+ id="aiEnabledToggle"
114
+ ${a?"checked":""}
115
+ />
116
+ <span class="orbit-check-box" aria-hidden="true">
117
+ <svg viewBox="0 0 16 16" class="orbit-check-tick"><path d="M3.5 8.5l3 3 6-7" /></svg>
118
+ </span>
119
+ <span class="orbit-check-label">Enable AI</span>
120
+ </label>
121
+ <p class="description">Provisions the <strong>AI Ready</strong>, <strong>In Progress</strong>, and <strong>Review</strong> lanes if missing, surfaces agent context fields, and exposes the MCP setup snippet. Disabling AI hides the AI Ready column but keeps its cards in place.</p>
122
+ </div>
123
+ ${n}
124
+ ${r}
125
+ ${o?`${n}${o}`:""}
126
+ ${n}
127
+ ${s}
128
+ `}function Or(e){let t=`This project is about\u2026
129
+
130
+ How any AI agent should use this board and work in this repo.`,a=e.agent_instructions||"",n=!!a.trim(),r=n?"":"is-placeholder",o=n?ce(a):d(t);return`
131
+ <div class="section ai-subsection ai-context-setup">
132
+ <div class="ai-context-title-row">
133
+ <span class="section-mark" aria-hidden="true">Context</span>
134
+ <h3>Agent Instructions</h3>
135
+ </div>
136
+ <p class="description">This project-level context is provided to agents when they work on tickets.</p>
137
+ <div class="inline-md-field">
138
+ <div
139
+ class="inline-md-field-body preserved-text-body editable-field settings-agent-instructions-body ${r}"
140
+ data-edit-field="agent_instructions"
141
+ tabindex="0"
142
+ title="Click to edit"
143
+ role="button"
144
+ aria-label="Edit Agent Instructions"
145
+ >${o}</div>
146
+ </div>
147
+ </div>
148
+ `}function jr(e){let t=Pt(),a="claude-code",n=qr(e,t),r=Ea(a,n),o=Sa(t,n),s=Bt[a];return`
149
+ <details class="section ai-subsection mcp-setup" data-mcp-setup>
150
+ <summary>
151
+ <div class="mcp-title-row">
152
+ <span class="section-mark" aria-hidden="true">MCP</span>
153
+ <h3>Connect Your Agent to MCP</h3>
154
+ </div>
155
+ </summary>
156
+ <div>
157
+ <p class="description">A tiny service running on your computer alongside your AI agent, providing it with tools and context to collaborate with you more effectively. Tell your AI to use the snippet below, it knows what MCP is.</p>
158
+ <div class="mcp-flow">
159
+ <label>
160
+ <span>Operating system</span>
161
+ <select id="mcpOsSelect" class="select-chevron-field">
162
+ ${Object.entries(At).map(([i,l])=>`<option value="${i}" ${i===t?"selected":""}>${d(l.label)}</option>`).join("")}
163
+ </select>
164
+ </label>
165
+ <label>
166
+ <span>Agent app</span>
167
+ <select id="mcpClientSelect" class="select-chevron-field">
168
+ ${Object.entries(Bt).map(([i,l])=>`<option value="${i}" ${i===a?"selected":""}>${d(l.label)}</option>`).join("")}
169
+ </select>
170
+ </label>
171
+ </div>
172
+ <div class="mcp-path-grid">
173
+ <label>
174
+ <span>Orbit MCP server file</span>
175
+ <input id="mcpServerPathInput" value="${d(n.serverPath)}" />
176
+ </label>
177
+ </div>
178
+ </div>
179
+
180
+ <div class="mcp-options-stack">
181
+ <div class="mcp-option-card">
182
+ <div class="mcp-option-card-head">
183
+ <div>
184
+ <strong data-mcp-output-title>${d(s.label)} setup</strong>
185
+ <p class="description" data-mcp-helper>${d(s.helper)}</p>
186
+ </div>
187
+ <button type="button" data-variant="secondary" data-copy-mcp="config">Copy setup</button>
188
+ </div>
189
+ <div class="mcp-terminal">
190
+ <div class="mcp-terminal-chrome" aria-hidden="true"><span></span><span></span><span></span></div>
191
+ <pre class="mcp-snippet"><code data-mcp-config>${d(r)}</code></pre>
192
+ </div>
193
+ </div>
194
+
195
+ <div class="mcp-or-divider" aria-hidden="true"><span>OR</span></div>
196
+
197
+ <div class="mcp-option-card">
198
+ <div class="mcp-option-card-head">
199
+ <div>
200
+ <strong>Manual run command</strong>
201
+ <p class="description">Use this only when an app asks you to start the MCP server yourself.</p>
202
+ </div>
203
+ <button type="button" data-variant="secondary" data-copy-mcp="command">Copy command</button>
204
+ </div>
205
+ <div class="mcp-terminal">
206
+ <div class="mcp-terminal-chrome" aria-hidden="true"><span></span><span></span><span></span></div>
207
+ <pre class="mcp-snippet mcp-snippet--compact"><code data-mcp-command>${d(o)}</code></pre>
208
+ </div>
209
+ </div>
210
+ </div>
211
+ </details>
212
+ `}function Pt(){let e=String(navigator.userAgentData?.platform||navigator.platform||navigator.userAgent||"").toLowerCase();return e.includes("win")?"windows":e.includes("mac")?"macos":"linux"}function Hr(e){return{serverPath:(At[e]||At.linux).serverPath}}function qr(e,t){let a=Hr(t);return{serverPath:(e.deployment||{}).mcp_server_path||a.serverPath}}function xn(){return{serverPath:y("#mcpServerPathInput")?.value||""}}function Ea(e,t){if(e==="claude-code")return Kr(t);if(e==="codex")return Gr(t);if(e==="opencode")return Ur(t);if(e==="vscode")return zr(t);let a={mcpServers:{"starscape-orbit":{command:"node",args:[t.serverPath]}}};return JSON.stringify(a,null,2)}function Ur(e){return JSON.stringify({$schema:"https://opencode.ai/config.json",mcp:{"starscape-orbit":{type:"local",command:["node",e.serverPath],enabled:!0}}},null,2)}function zr(e){return JSON.stringify({servers:{starscapeOrbit:{type:"stdio",command:"node",args:[e.serverPath]}}},null,2)}function Gr(e){return`[mcp_servers.starscape-orbit]
213
+ command = "node"
214
+ args = ["${Jr(e.serverPath)}"]
215
+ enabled = true`}function Kr(e){return["claude mcp add starscape-orbit","--","node",Ln(e.serverPath)].join(" ")}function Sa(e,t){return`node ${Ln(t.serverPath)}`}function Ln(e){return`"${String(e||"").replace(/"/g,'\\"')}"`}function Jr(e){return String(e||"").replace(/\\/g,"\\\\").replace(/"/g,'\\"')}function Yr(){return`
216
+ <p class="description">Archived cards are hidden from the kanban, search, and agent claim-next. Restore to put a card back on the board, or delete to permanently remove it.</p>
217
+ <div class="section">
218
+ <div id="archiveList" class="archive-list">Loading\u2026</div>
219
+ </div>
220
+ `}function Wr(e){let t=e.board;return j.boardId!==t.id&&(j.boardId=t.id,j.step="idle",j.exported=!1),`
221
+ ${O.multiBoard?`
222
+ <div class="detail-head project-manual-head">
223
+ <div class="meta-grid">
224
+ <div class="meta meta--repo-path">
225
+ <span>Repo</span>
226
+ <strong>${d(Za(t.repo_url))}</strong>
227
+ <span>Path</span>
228
+ <strong>${d(t.system_path||e.deployment?.system_path||"Not available")}</strong>
229
+ </div>
230
+ </div>
231
+ </div>`:`
232
+ <p class="description">This board lives in your browser only. Export a snapshot if you want to move it to a real Orbit install, or import one to seed this preview.</p>`}
233
+
234
+ ${O.multiBoard?Xr(t):""}
235
+
236
+ <div class="section">
237
+ <h3>Board Snapshot</h3>
238
+ <p class="description">Import accepts Orbit snapshots or Trello board JSON exports. The default import creates a separate board and leaves this board untouched.</p>
239
+ ${O.attachments?`
240
+ <label class="orbit-check">
241
+ <input type="checkbox" id="exportProjectImages" />
242
+ <span class="orbit-check-box" aria-hidden="true">
243
+ <svg viewBox="0 0 16 16" class="orbit-check-tick"><path d="M3.5 8.5l3 3 6-7" /></svg>
244
+ </span>
245
+ <span>Include attached images</span>
246
+ </label>
247
+ <p class="description">Image exports are embedded in the .orbit.json snapshot and may be much larger.</p>
248
+ `:""}
249
+ <div class="deployment-actions">
250
+ <button type="button" data-variant="secondary" id="exportProject">Export</button>
251
+ <input type="file" id="importSnapshotAsNewFile" class="import-file-input" accept=".orbit.json,.json,application/json" />
252
+ <button type="button" data-variant="secondary" id="importSnapshotAsNewButton">Import as New Board</button>
253
+ </div>
254
+ </div>
255
+
256
+ <div class="section repository-danger-zone">
257
+ <h3>Replace Current Board</h3>
258
+ <p class="description">Advanced: replace this board from an Orbit snapshot or Trello export after making the normal pre-import backup. Type <strong>${d(t.slug||"")}</strong> to enable replacement.</p>
259
+ <label class="repository-confirm-field">
260
+ <span>Board slug</span>
261
+ <input id="replaceImportConfirmInput" autocomplete="off" spellcheck="false" placeholder="${d(t.slug||"")}" />
262
+ </label>
263
+ <div class="deployment-actions">
264
+ <input type="file" id="replaceCurrentBoardImportFile" class="import-file-input" accept=".orbit.json,.json,application/json" disabled />
265
+ <button type="button" data-variant="secondary" id="replaceCurrentBoardImportButton" disabled>Replace Current Board</button>
266
+ </div>
267
+ </div>
268
+
269
+ ${O.multiBoard?Qr(t):""}
270
+ `}function Vr(e){let t=!!e.system_path,a=!!e.manage_helper_files;return`
271
+ <div class="section ai-subsection helper-files-section">
272
+ <div class="ai-context-title-row">
273
+ <span class="section-mark" aria-hidden="true">Files</span>
274
+ <h3>AI Helper Files</h3>
275
+ </div>
276
+ <p class="description">Orbit can keep <code>SKILL-ORBIT.md</code> and <code>AGENTS.md</code> in this board's coding project folder so your AI agent knows how to use Orbit.${t?"":" Link a folder to enable this."}</p>
277
+ <div class="folder-picker-field helper-files-folder">
278
+ <input id="helperFolderInput" type="text" readonly placeholder="No folder linked" value="${d(e.system_path||"")}" />
279
+ <button type="button" id="helperPickFolderBtn">${t?"Change":"Browse"}</button>
280
+ </div>
281
+ <label class="orbit-check">
282
+ <input type="checkbox" id="manageHelperFilesToggle" ${a?"checked":""} ${t?"":"disabled"} />
283
+ <span class="orbit-check-box" aria-hidden="true">
284
+ <svg viewBox="0 0 16 16" class="orbit-check-tick"><path d="M3.5 8.5l3 3 6-7" /></svg>
285
+ </span>
286
+ <span>Generate &amp; maintain helper files in this folder</span>
287
+ </label>
288
+ </div>
289
+ `}function Xr(e){return`
290
+ <div class="section board-rename-section">
291
+ <h3>Board Name</h3>
292
+ <p class="description">Rename the board display name only. The canonical URL slug stays <strong>${d(e.slug||"")}</strong>, so existing board links keep working.</p>
293
+ <form id="boardRenameForm" class="field-form">
294
+ <label>
295
+ <span>Display name</span>
296
+ <input name="name" value="${d(e.name||"")}" maxlength="120" required />
297
+ </label>
298
+ <button type="submit" data-variant="secondary">Rename Board</button>
299
+ </form>
300
+ </div>
301
+ `}function Qr(e){let t=d(e.slug||"");if(j.step==="choice")return`
302
+ <div class="section repository-danger-zone">
303
+ <h3>Delete Board</h3>
304
+ <p class="description">Delete this board from Orbit and remove its repo-local Orbit files. Export a snapshot first if you may need this board again.</p>
305
+ <div class="repository-delete-actions">
306
+ <button type="button" data-variant="secondary" id="deleteBoardExportFirst">Export first</button>
307
+ <button type="button" data-variant="ghost" class="danger-button" id="deleteBoardSkipExport">Delete without exporting</button>
308
+ <button type="button" data-variant="ghost" id="deleteBoardCancel">Cancel</button>
309
+ </div>
310
+ </div>
311
+ `;if(j.step==="confirm"){let a=j.exported?"Snapshot exported. Type the board slug to confirm permanent deletion.":"Type the board slug to confirm permanent deletion.";return`
312
+ <div class="section repository-danger-zone is-confirming">
313
+ <h3>Delete Board</h3>
314
+ <p class="description">${d(a)}</p>
315
+ <label class="repository-confirm-field">
316
+ <span>Board slug</span>
317
+ <strong>${t}</strong>
318
+ <input id="deleteBoardConfirmInput" autocomplete="off" spellcheck="false" placeholder="${t}" autofocus />
319
+ </label>
320
+ <div class="repository-delete-actions">
321
+ <button type="button" data-variant="primary" class="danger-button" id="deleteBoardConfirm" disabled>Delete board permanently</button>
322
+ <button type="button" data-variant="ghost" id="deleteBoardCancel">Cancel</button>
323
+ </div>
324
+ </div>
325
+ `}return`
326
+ <div class="section repository-danger-zone">
327
+ <h3>Delete Board</h3>
328
+ <p class="description">Remove this board from Orbit and delete its repo-local Orbit files. This cannot be undone without an exported snapshot.</p>
329
+ <button type="button" data-variant="ghost" class="danger-button" id="deleteBoardStart">Delete Board</button>
330
+ </div>
331
+ `}function Zr(e){let t=e.board,a="Remember to mention SKILL-ORBIT.md to my AI agents if they get confused",n=t.project_notes||"",r=!!n.trim(),o=r?"":"is-placeholder",s=r?ce(n):d(a);return`
332
+ <div class="section ai-fields">
333
+ <div class="inline-md-field">
334
+ <span class="inline-md-field-label">Notes For You</span>
335
+ <div
336
+ class="inline-md-field-body preserved-text-body editable-field settings-notes-body ${o}"
337
+ data-edit-field="project_notes"
338
+ tabindex="0"
339
+ title="Click to edit"
340
+ role="button"
341
+ aria-label="Edit Notes For You"
342
+ >${s}</div>
343
+ </div>
344
+ </div>
345
+ `}function En(){return`
346
+ <div class="section">
347
+ <label class="orbit-check" for="showPriorityToggle">
348
+ <input
349
+ type="checkbox"
350
+ id="showPriorityToggle"
351
+ ${c.showPriority?"checked":""}
352
+ />
353
+ <span class="orbit-check-box" aria-hidden="true">
354
+ <svg viewBox="0 0 16 16" class="orbit-check-tick"><path d="M3.5 8.5l3 3 6-7" /></svg>
355
+ </span>
356
+ <span class="orbit-check-label">Show priority label on cards</span>
357
+ </label>
358
+ <p class="description lanes-description">Rename, reorder, add, or remove lanes.</p>
359
+ ${co()}
360
+ <form id="laneCreateForm" class="lane-create-form">
361
+ <input name="name" placeholder="New lane name..." required />
362
+ <button type="submit" data-variant="primary">Add Lane</button>
363
+ </form>
364
+ </div>
365
+ `}function eo(){let e=me(),t=Ae(),a=mt(),n=Wt(),r=a===null?`Using browser default (${n?"reduced motion":"motion allowed"}).`:"Using your saved preference.";return`
366
+ <div class="section appearance-theme-section">
367
+ <fieldset class="appearance-theme-field">
368
+ <legend>Theme</legend>
369
+ <div class="appearance-theme-options">
370
+ ${Sn("light","Light",e)}
371
+ ${Sn("dark","Dark",e)}
372
+ </div>
373
+ <p class="description">Applies the light/dark theme used by the top rail toggle.</p>
374
+ </fieldset>
375
+ </div>
376
+ <div class="section">
377
+ <label class="orbit-check" for="reduceMotionToggle">
378
+ <input
379
+ type="checkbox"
380
+ id="reduceMotionToggle"
381
+ ${t?"checked":""}
382
+ />
383
+ <span class="orbit-check-box" aria-hidden="true">
384
+ <svg viewBox="0 0 16 16" class="orbit-check-tick"><path d="M3.5 8.5l3 3 6-7" /></svg>
385
+ </span>
386
+ <span class="orbit-check-label">Reduce theme motion</span>
387
+ </label>
388
+ <p class="description">Turns off the animated starfield, meteors, and theme animations. ${d(r)}</p>
389
+ </div>
390
+ `}function Sn(e,t,a){return`
391
+ <label class="appearance-theme-option">
392
+ <input type="radio" name="themePreference" value="${e}" ${a===e?"checked":""} />
393
+ <span class="appearance-theme-option-mark" aria-hidden="true">
394
+ <svg
395
+ class="appearance-theme-option-icon"
396
+ width="16"
397
+ height="16"
398
+ viewBox="0 0 24 24"
399
+ fill="none"
400
+ stroke="currentColor"
401
+ stroke-width="2"
402
+ stroke-linecap="round"
403
+ stroke-linejoin="round"
404
+ >${e==="dark"?'<path d="M21 12.79A9 9 0 1111.21 3 7 7 0 0021 12.79z" />':'<circle cx="12" cy="12" r="5" /><path d="M12 1v2m0 18v2M4.2 4.2l1.4 1.4m12.8 12.8l1.4 1.4M1 12h2m18 0h2M4.2 19.8l1.4-1.4M18.4 5.6l1.4-1.4" />'}</svg>
405
+ </span>
406
+ <span class="appearance-theme-option-label">${t}</span>
407
+ </label>
408
+ `}function to(e){return`
409
+ ${e.board?.ai_enabled!==0?'<p class="description">Agent-facing project memory: decisions to follow and lessons to apply. Struck entries stay visible here but are excluded from agent context.</p>':""}
410
+ <div class="section">
411
+ ${oo(e.entries)}
412
+ <form id="projectEntryForm" class="comment-form project-entry-form">
413
+ <select name="type" class="select-chevron-field" aria-label="Entry type">
414
+ <option value="decision">Decision</option>
415
+ <option value="lesson">Lesson</option>
416
+ </select>
417
+ <input name="title" placeholder="Entry title..." required />
418
+ <textarea name="body" placeholder="Decision rationale or lesson: do X instead of Y when working with Z." required></textarea>
419
+ <button type="submit" data-variant="primary">Add Entry</button>
420
+ </form>
421
+ </div>
422
+ `}function ao(e){if(String(e||"").trimStart().startsWith("<"))throw new Error("That file looks like an HTML page instead of JSON. In Trello, use Export JSON/download the board JSON, not Save Page As.");try{return JSON.parse(e)}catch(a){throw new Error(a?.message||"invalid JSON")}}function no(e,t){let a=e.board;if(t==="repository"){let n=async(p=!!y("#exportProjectImages")?.checked)=>{let f=p?"?include_attachments=true":"",b=await v(`/api/boards/${encodeURIComponent(a.id)}/export${f}`),w=p?`${a.slug}.with-images.orbit.json`:`${a.slug}.orbit.json`;en(w,b)};y("#exportProject")?.addEventListener("click",async()=>{await n()}),y("#boardRenameForm")?.addEventListener("submit",async p=>{p.preventDefault();let f=new FormData(p.currentTarget),b=String(f.get("name")||"").trim();!b||b===a.name||(await v(`/api/boards/${encodeURIComponent(a.id)}`,{method:"PATCH",body:{name:b}}),await I(),c.detailMode="settings",h.success(`Renamed board to ${b}. Canonical slug unchanged: ${a.slug}`))});let r=async(p,f)=>{let b=await p.text(),w=ao(b);return v("/api/admin/import",{method:"POST",body:f(w)})},o=y("#importSnapshotAsNewFile");y("#importSnapshotAsNewButton")?.addEventListener("click",()=>{o?.click()}),o?.addEventListener("change",async p=>{let f=p.currentTarget,b=f.files?.[0];if(b)try{let w=await r(b,C=>({snapshot:C,create_new:!0,board_id:a.id}));c.boardId=w.imported_board_id,c.boardSlug=w.imported_board_slug,c.detailMode="empty",await I(),await A({boardId:w.imported_board_id,view:"board"});let $=w.imported_counts||{},P=Number.isFinite(Number($.tickets))?` (${$.tickets} cards)`:"";h.success(w.source_format==="trello-board-export"?`Trello board imported as new board${P}`:"Board imported as new board")}catch(w){h.error(`Import failed: ${w?.message||"invalid JSON"}`)}finally{f.value=""}});let s=y("#replaceImportConfirmInput"),i=y("#replaceCurrentBoardImportFile"),l=y("#replaceCurrentBoardImportButton");s?.addEventListener("input",()=>{let p=s.value.trim()!==a.slug;i&&(i.disabled=p),l&&(l.disabled=p)}),l?.addEventListener("click",()=>{l.disabled||i?.disabled||i?.click()}),i?.addEventListener("change",async p=>{let f=p.currentTarget,b=f.files?.[0];if(b){if(s.value.trim()!==a.slug){h.error("Type the board slug before replacing this board."),f.value="";return}try{let w=await r(b,C=>({snapshot:C,replace_existing:!0,board_id:a.id}));await I(),c.detailMode="settings";let $=w.imported_counts||{},P=Number.isFinite(Number($.tickets))?` (${$.tickets} cards)`:"";h.success(w.source_format==="trello-board-export"?`Trello board replaced from Trello import${P}`:"Board replaced from snapshot")}catch(w){h.error(`Import failed: ${w?.message||"invalid JSON"}`)}finally{f.value=""}}}),y("#deleteBoardStart")?.addEventListener("click",async()=>{j.step="choice",j.exported=!1,await ge()}),y("#deleteBoardExportFirst")?.addEventListener("click",async()=>{await n(),j.step="confirm",j.exported=!0,await ge()}),y("#deleteBoardSkipExport")?.addEventListener("click",async()=>{j.step="confirm",j.exported=!1,await ge()}),y("#deleteBoardCancel")?.addEventListener("click",async()=>{j.step="idle",j.exported=!1,await ge()});let u=y("#deleteBoardConfirmInput"),m=y("#deleteBoardConfirm");u?.addEventListener("input",()=>{m&&(m.disabled=u.value.trim()!==a.slug)}),m?.addEventListener("click",async()=>{await v(`/api/boards/${encodeURIComponent(a.id)}`,{method:"DELETE",body:{confirm_slug:a.slug,delete_files:!0}}),j.step="idle",j.exported=!1,await I(),h.success(`Deleted board: ${a.name}`),A({boardId:c.boardId,view:"board"},{replace:!0})})}if(t==="notes"){let n=k.querySelector('[data-edit-field="project_notes"]');if(n){let r=()=>Ie(n,{fieldName:"project_notes",multiline:!0,initialValue:a.project_notes||"",ariaLabel:"Edit Notes For You",rerender:async()=>{c.detailMode="settings",await ge()},commit:async o=>{await v(`/api/boards/${a.id}`,{method:"PATCH",body:{project_notes:X(o)}}),await I(),c.detailMode="settings",h.success("Saved")}});n.addEventListener("click",o=>{o.preventDefault(),r()}),n.addEventListener("keydown",o=>{(o.key==="Enter"||o.key===" ")&&(o.preventDefault(),r())})}}if(t==="lanes"&&(k.querySelectorAll("[data-lane-action]").forEach(n=>{n.addEventListener("click",async()=>{await lo(n)})}),k.querySelectorAll(".lane-row input, .lane-row select").forEach(n=>{n.addEventListener("change",async()=>{await In(n.closest(".lane-row"))})}),y("#laneCreateForm")?.addEventListener("submit",async n=>{n.preventDefault();let r=new FormData(n.currentTarget);await v(`/api/boards/${a.id}/states`,{method:"POST",body:Object.fromEntries(r.entries())}),await I(),c.detailMode="settings",h.success("Lane added")}),y("#showPriorityToggle")?.addEventListener("change",n=>{c.showPriority=!!n.currentTarget.checked,localStorage.setItem("mab_show_priority",c.showPriority?"true":"false"),je()})),t==="appearance"&&(k.querySelectorAll("input[name='themePreference']").forEach(n=>{n.addEventListener("change",r=>{if(!r.currentTarget.checked)return;let o=Zt(r.currentTarget.value);h.success(o==="dark"?"Dark theme enabled":"Light theme enabled")})}),y("#reduceMotionToggle")?.addEventListener("change",n=>{let r=!!n.currentTarget.checked;qa(r),Ye(),window.dispatchEvent(new CustomEvent("orbit:motion-preference-change",{detail:{reduce:r}})),h.success(r?"Theme motion reduced":"Theme motion enabled")})),t==="ai"){let n=()=>{let i=y("#mcpOsSelect")?.value||Pt(),l=y("#mcpClientSelect")?.value||"claude-code",u=Bt[l]||Bt.generic,m=xn(),p=Ea(l,m),f=Sa(i,m),b=k.querySelector("[data-mcp-os-note]");b&&(b.textContent=`Detected: ${At[Pt()]?.label||"Linux"}`);let w=k.querySelector("[data-mcp-client-format]");w&&(w.textContent=u.format);let $=k.querySelector("[data-mcp-output-title]");$&&($.textContent=`${u.label} setup`);let P=k.querySelector("[data-mcp-helper]");P&&(P.textContent=u.helper);let C=k.querySelector("[data-mcp-config]");C&&(C.textContent=p);let J=k.querySelector("[data-mcp-command]");J&&(J.textContent=f)};y("#mcpOsSelect")?.addEventListener("change",()=>n()),y("#mcpClientSelect")?.addEventListener("change",()=>n()),["#mcpServerPathInput"].forEach(i=>{y(i)?.addEventListener("input",()=>n())}),k.querySelectorAll("[data-copy-mcp]").forEach(i=>{i.addEventListener("click",async()=>{let l=y("#mcpOsSelect")?.value||Pt(),u=y("#mcpClientSelect")?.value||"claude-code",m=xn(),p=i.dataset.copyMcp==="command"?Sa(l,m):Ea(u,m);await ro(p),h.success(i.dataset.copyMcp==="command"?"MCP command copied":"MCP config copied")})});let r=k.querySelector('[data-edit-field="agent_instructions"]');if(r){let i=()=>Ie(r,{fieldName:"agent_instructions",multiline:!0,initialValue:a.agent_instructions||"",ariaLabel:"Edit Agent Instructions",rerender:async()=>{c.detailMode="settings",await ge()},commit:async l=>{await v(`/api/boards/${a.id}`,{method:"PATCH",body:{agent_instructions:X(l)}}),await I(),c.detailMode="settings",h.success("Saved")}});r.addEventListener("click",l=>{l.preventDefault(),i()}),r.addEventListener("keydown",l=>{(l.key==="Enter"||l.key===" ")&&(l.preventDefault(),i())})}y("#aiEnabledToggle")?.addEventListener("change",async i=>{let l=!!i.currentTarget.checked;await v(`/api/boards/${a.id}`,{method:"PATCH",body:{ai_enabled:l}}),await I(),c.detailMode="settings",h.success(l?"AI features enabled \u2014 agent lanes provisioned":"AI features disabled \u2014 AI Ready hidden")});let o=y("#helperPickFolderBtn");o?.addEventListener("click",async()=>{o.disabled=!0;try{let i=await v("/api/system/pick-folder",{method:"POST"});if(!i.path)return;await v(`/api/boards/${encodeURIComponent(a.id)}`,{method:"PATCH",body:{system_path:i.path}}),await I(),c.detailMode="settings",h.success("Linked coding project folder updated")}catch(i){h.error(i?.message||"Folder picker unavailable")}finally{o.disabled=!1}});let s=y("#manageHelperFilesToggle");s?.addEventListener("change",async()=>{let i=s.checked;s.disabled=!0;try{await v(`/api/boards/${encodeURIComponent(a.id)}`,{method:"PATCH",body:{manage_helper_files:i}}),await I(),c.detailMode="settings",h.success(i?"Generated SKILL-ORBIT.md and AGENTS.md \u2014 Orbit will keep them in sync":"Stopped maintaining helper files (existing files left in place)")}catch(l){s.checked=!i,s.disabled=!1,h.error(l?.message||"Could not update helper files setting")}})}if(t==="archive"){let n=y("#archiveList");if(n){let r=async()=>{try{let s=(await v(`/api/boards/${encodeURIComponent(a.id)}/archive`)).tickets||[];if(s.length===0){n.innerHTML='<p class="description">No archived cards yet. Click the trash icon in the card detail header to archive a card.</p>';return}n.innerHTML=`<div class="detail-card-grid">${s.map(i=>Ue(i,{archive:{id:i.id},disableOpen:!0})).join("")}</div>`}catch(o){n.innerHTML=`<p class="description">Could not load archive: ${d(o?.message||"unknown error")}</p>`}};r(),n.addEventListener("click",async o=>{let s=o.target.closest("[data-archive-restore]"),i=o.target.closest("[data-archive-delete]");if(!s&&!i)return;o.stopPropagation();let u=(s||i).closest("article")?.querySelector("h3")?.textContent||"card";if(s){let m=s.dataset.archiveRestore;await v(x(`/api/tickets/${encodeURIComponent(m)}/restore`),{method:"POST"}),h.success(`Restored: ${u}`),await I(),await r();return}if(i){let m=i.dataset.archiveDelete;if(!confirm(`Permanently delete "${u}"? This cannot be undone.`))return;await v(x(`/api/tickets/${encodeURIComponent(m)}`),{method:"DELETE"}),h.success(`Deleted: ${u}`),await r()}})}}t==="journal"&&(k.querySelectorAll("[data-entry-action='toggle-struck']").forEach(n=>{n.addEventListener("click",async()=>{await v(x(`/api/board-entries/${n.dataset.entryId}`),{method:"PATCH",body:{struck:n.dataset.struck!=="true"}}),await I(),c.detailMode="settings",h.info(n.dataset.struck==="true"?"Project entry restored":"Project entry struck")})}),y("#projectEntryForm")?.addEventListener("submit",async n=>{n.preventDefault();let r=new FormData(n.currentTarget);await v(`/api/boards/${a.id}/entries`,{method:"POST",body:Object.fromEntries(r.entries())}),await I(),c.detailMode="settings",h.success("Project entry added")}))}async function ro(e){if(navigator.clipboard?.writeText){await navigator.clipboard.writeText(e);return}let t=document.createElement("textarea");t.value=e,t.setAttribute("readonly",""),t.style.position="fixed",t.style.left="-9999px",document.body.append(t),t.select(),document.execCommand("copy"),t.remove()}function oo(e=[]){return e.length?e.map(t=>{let a=!!t.struck_at;return`
423
+ <div class="comment project-entry ${d(t.type)} ${a?"is-struck":""}">
424
+ <div class="comment-meta">
425
+ <div>
426
+ <strong>${d(t.type.toUpperCase())}: ${d(t.title)}</strong>
427
+ ${a?'<span class="project-entry-status">Excluded from agent context</span>':""}
428
+ </div>
429
+ <div class="project-entry-actions">
430
+ <span>${d(t.created_by)} - ${Ve(t.created_at)}</span>
431
+ <button
432
+ type="button"
433
+ data-variant="ghost"
434
+ class="project-entry-strike"
435
+ data-entry-action="toggle-struck"
436
+ data-entry-id="${d(t.id)}"
437
+ data-struck="${a?"true":"false"}"
438
+ aria-pressed="${a?"true":"false"}"
439
+ >${a?"Restore":"Strike"}</button>
440
+ </div>
441
+ </div>
442
+ <div class="comment-body">${d(t.body)}</div>
443
+ </div>
444
+ `}).join(""):'<p class="description">No project entries yet.</p>'}function io(e,t,a){return!!(t.get(e.id)||e.is_default||Tn.has(e.role)||a&&e.role==="ai_ready")}function so(e,t,a){let n=t.get(e.id)||0;return n>0?`Cannot delete \u2014 ${n} card${n===1?"":"s"} in this lane`:e.is_default?"Cannot delete \u2014 default lane for new cards (move it first)":Tn.has(e.role)?"Cannot delete \u2014 core kanban lane":a&&e.role==="ai_ready"?"Cannot delete \u2014 required by agent flow while AI is enabled":"Delete lane"}function co(){let e=Re(),t=q()?.ai_enabled!==0,a=new Map;for(let n of Y())a.set(n.state_id,(a.get(n.state_id)||0)+1);return`
445
+ <div class="lane-list">
446
+ ${e.map((n,r)=>{let o=n.role==="ai_ready",s=o?"AI Ready lane name is locked \u2014 disable AI to hide this column":"";return`
447
+ <div class="lane-row${o?" lane-row--locked":""}" data-lane-id="${n.id}">
448
+ <button type="button" data-variant="ghost" class="settings-lane-icon-btn" data-lane-action="up" ${r===0?"disabled":""} title="Move lane left" aria-label="Move lane left">\u2191</button>
449
+ <button type="button" data-variant="ghost" class="settings-lane-icon-btn" data-lane-action="down" ${r===e.length-1?"disabled":""} title="Move lane right" aria-label="Move lane right">\u2193</button>
450
+ <input name="name" value="${d(n.name)}" aria-label="Lane name" ${o?`readonly title="${d(s)}"`:""} />
451
+ <button type="button" data-variant="${n.is_default?"secondary":"ghost"}" class="settings-lane-new-toggle ${n.is_default?"is-on":""}" data-lane-action="toggle-default" aria-pressed="${n.is_default?"true":"false"}" title="${n.is_default?"Default lane for new cards \u2014 click another lane to move it":"Make this the default lane for new cards"}" aria-label="Default lane for new cards">
452
+ <span class="lane-new-sun" aria-hidden="true"></span>
453
+ <span class="lane-new-label">New</span>
454
+ </button>
455
+ <button type="button" data-variant="ghost" class="settings-lane-delete-btn danger-button" data-lane-action="delete" ${io(n,a,t)?"disabled":""} title="${so(n,a,t)}" aria-label="Delete lane">\xD7</button>
456
+ </div>
457
+ `}).join("")}
458
+ </div>
459
+ `}async function lo(e){let t=e.closest(".lane-row"),a=t.dataset.laneId,n=e.dataset.laneAction;if(n==="delete"){await v(x(`/api/states/${a}`),{method:"DELETE"}),await I(),c.detailMode="settings",h.success("Lane deleted");return}if(n==="toggle-default"){if(e.getAttribute("aria-pressed")==="true")return;k.querySelectorAll('[data-lane-action="toggle-default"]').forEach(l=>{l.setAttribute("aria-pressed","false"),l.setAttribute("data-variant","ghost"),l.classList.remove("is-on")}),e.setAttribute("aria-pressed","true"),e.setAttribute("data-variant","secondary"),e.classList.add("is-on"),await In(t,{silent:!0}),h.success("Default lane updated");return}let r=Re().map(i=>i.id),o=r.indexOf(a),s=n==="up"?o-1:o+1;s<0||s>=r.length||([r[o],r[s]]=[r[s],r[o]],await v(`/api/boards/${c.boardId}/states`,{method:"PATCH",body:{state_ids:r}}),await I(),c.detailMode="settings",h.success("Lanes reordered"))}async function In(e,{silent:t=!1}={}){let a=e.querySelector('input[name="name"]').value,r=e.querySelector('[data-lane-action="toggle-default"]')?.getAttribute("aria-pressed")==="true";await v(x(`/api/states/${e.dataset.laneId}`),{method:"PATCH",body:{name:a,is_default:r}}),await I(),c.detailMode="settings",t||h.success("Lane updated")}var j,At,Bt,Tn,_n=_(()=>{U();ie();ne();Q();fe();kt();be();ot();Ft();he();qe();Vt();ea();j={boardId:"",step:"idle",exported:!1};At={windows:{label:"Windows",shell:"PowerShell",serverPath:"C:\\Path\\To\\StarscapeOrbit\\src\\mcp-server.js"},macos:{label:"macOS",shell:"Terminal",serverPath:"/Users/you/apps/starscape-orbit/src/mcp-server.js"},linux:{label:"Linux",shell:"Terminal",serverPath:"/home/you/apps/starscape-orbit/src/mcp-server.js"}},Bt={"claude-code":{label:"Claude Code",format:"CLI command",helper:"Run this command once. Claude Code records the local Orbit tool server for the project."},codex:{label:"Codex",format:"config.toml",helper:"Paste this TOML into Codex config. Project-local config may require the project to be trusted."},cursor:{label:"Cursor",format:"MCP JSON",helper:"Paste this JSON into Cursor MCP settings. Cursor starts Orbit when an agent needs the tools."},vscode:{label:"VS Code",format:"mcp.json",helper:"Paste this JSON into VS Code's user or workspace MCP configuration."},opencode:{label:"OpenCode",format:"opencode.json",helper:"Paste this into OpenCode config under the local MCP server list."},openclaw:{label:"OpenClaw",format:"MCP JSON",helper:"Paste this JSON into OpenClaw's MCP server list. OpenClaw will spawn Orbit on demand."},generic:{label:"Other MCP app",format:"MCP JSON",helper:"Most MCP clients accept this JSON shape for local stdio servers."}};Tn=new Set(["in_progress","review"])});function _e(e){return String(e||"").trim()}function Ta(e){let t=_e(e);return t?t.replace(/^@+/,"").replace(/[-_]+/g," ").replace(/\s+/g," ").trim().replace(/\b\w/g,a=>a.toUpperCase()):""}function Mn({actor:e,actorId:t}={}){let a=_e(e),n=_e(t),r=a.toLowerCase(),o=n.toLowerCase();return a&&!La.has(r)&&!Cn.has(r)?Ta(a):n&&!La.has(o)&&!Cn.has(o)?Ta(n):""}function Ia({actor:e,actorType:t,actorId:a}={}){let n=_e(t).toLowerCase(),r=_e(e),o=r.toLowerCase();if(n==="agent"){let s=Mn({actor:r,actorId:a});return s?`Agent \xB7 ${s}`:"Agent"}return!r||La.has(o)?"You":Ta(r)}function Pn(e={}){let t=_e(e.kind).toLowerCase(),a=_e(e.author);if(uo.has(t)||t&&t!=="human_comment"){let r=Mn({actor:a});return r?`Agent \xB7 ${r}`:"Agent"}return Ia({actor:a,actorType:"human"})}var La,Cn,uo,An=_(()=>{La=new Set(["local","local-owner","owner"]),Cn=new Set(["agent","local-agent","orbit-agent"]),uo=new Set(["agent_note","checkpoint","completion"])});var Rn={};ut(Rn,{renderDetail:()=>ve,renderDetailCard:()=>Ue,renderInlinePreservedTextField:()=>Rt,startInlineEdit:()=>Ie});async function le(e,{renderBoardAfter:t=!1}={}){let[a,n,r]=await Promise.all([v(x(`/api/tickets/${e}/context?depth=1`)),v(x(`/api/tickets/${e}/history`)),v(x(`/api/tickets/${e}/comments`))]);a.ticket?.id===e&&(ia(a.ticket),t&&je(),!(c.detailMode!=="ticket"||c.selectedTicketId!==e)&&await ve({context:a,statusHistory:n,comments:r.comments||[]}))}async function ye(e,t){await v(x(`/api/tickets/${e}`),{method:"PATCH",body:t}),await le(e,{renderBoardAfter:!0})}function po(e,t,a){if(!e||!t||typeof t.clientX!="number"||typeof t.clientY!="number")return null;let n=null;if(document.caretPositionFromPoint){let r=document.caretPositionFromPoint(t.clientX,t.clientY);r?.offsetNode&&(r.offsetNode===e||e.contains(r.offsetNode))&&(n=document.createRange(),n.setStart(e,0),n.setEnd(r.offsetNode,r.offset))}else if(document.caretRangeFromPoint){let r=document.caretRangeFromPoint(t.clientX,t.clientY);r?.startContainer&&(r.startContainer===e||e.contains(r.startContainer))&&(n=document.createRange(),n.setStart(e,0),n.setEnd(r.startContainer,r.startOffset))}return n?Math.max(0,Math.min(a,n.toString().length)):null}function mo(e){let t=e?.closest?.(".drawer-inner");return t?{scrollContainer:t,nodeRect:e.getBoundingClientRect(),scrollTop:t.scrollTop}:null}function fo(e,t){if(!e?.scrollContainer||!t?.isConnected)return;let a=t.getBoundingClientRect(),n=Math.max(0,e.scrollContainer.scrollTop+(a.top-e.nodeRect.top));Number.isFinite(n)?e.scrollContainer.scrollTop=n:e.scrollContainer.scrollTop=e.scrollTop}function ho(e){try{e.focus({preventScroll:!0})}catch{e.focus()}}function Ie(e,t){if(!e||e.dataset.editing==="true")return;let{fieldName:a,multiline:n=!0,initialValue:r="",ariaLabel:o,emptyMessage:s,sourceEvent:i,rerender:l,commit:u}=t,m=n?mo(e):null,p=String(r),f=n?po(e,i,p.length):null;e.dataset.editing="true";let b=document.createElement(n?"textarea":"input");if(b.className=n?"inline-desc-editor":"inline-title-editor",b.value=p,a&&b.setAttribute("data-editing-field",a),o&&b.setAttribute("aria-label",o),!n)b.type="text",b.maxLength=500,b.autocomplete="off",b.spellcheck=!0;else{b.rows=Math.max(3,p.split(`
460
+ `).length+1);let E=e.getBoundingClientRect().height;Number.isFinite(E)&&E>0&&(b.style.minHeight=`${Math.ceil(E)}px`)}if(e.replaceWith(b),ho(b),!n)b.select();else{let E=f??0;b.setSelectionRange(E,E),fo(m,b)}let w=!1,$=()=>{document.removeEventListener("pointerdown",J,!0)},P=()=>{b.isConnected&&b.replaceWith(e),delete e.dataset.editing},C=()=>{w=!0,$(),P()};function J(E){w||E.target===b||b.contains(E.target)||b.blur()}document.addEventListener("pointerdown",J,!0);let B=async()=>{if(w)return;let E=n?b.value:b.value.trim();if(C(),String(E)===String(r)){l&&await l();return}if(s&&!E.trim()){h.warning(s),l&&await l();return}u&&await u(E)},S=async()=>{w||(C(),l&&await l())};b.addEventListener("blur",B),b.addEventListener("keydown",E=>{if(E.key==="Escape"){E.preventDefault(),S();return}E.key==="Enter"&&(n?(E.metaKey||E.ctrlKey)&&(E.preventDefault(),B()):(E.preventDefault(),B()))})}function bo(e){let t=e.id,a=()=>Ie(n,{fieldName:"title",multiline:!1,initialValue:e.title||"",ariaLabel:"Edit ticket title",emptyMessage:"Title cannot be empty",rerender:()=>ve(),commit:u=>ye(t,{title:u})}),n=G.querySelector('[data-edit-field="title"]');n&&(n.addEventListener("click",a),n.addEventListener("keydown",u=>{(u.key==="Enter"||u.key===" ")&&(u.preventDefault(),a())}));let r=k.querySelector('[data-edit-field="description"]'),o=u=>Ie(r,{fieldName:"description",multiline:!0,initialValue:e.description||"",ariaLabel:"Edit ticket description",sourceEvent:u,rerender:()=>ve(),commit:m=>ye(t,{description:X(m)})});r&&(r.addEventListener("click",u=>{u.preventDefault(),o(u)}),r.addEventListener("keydown",u=>{(u.key==="Enter"||u.key===" ")&&(u.preventDefault(),o())}));let s=[{key:"ai_plan",label:"AI plan"},{key:"implementation_summary",label:"Implementation summary"},{key:"implementation_updates",label:"Implementation updates / lessons"}];for(let{key:u,label:m}of s){let p=k.querySelector(`[data-edit-field="${u}"]`);if(!p)continue;let f=b=>Ie(p,{fieldName:u,multiline:!0,initialValue:e[u]||"",ariaLabel:`Edit ${m}`,sourceEvent:b,rerender:()=>ve(),commit:w=>ye(t,{[u]:X(w)})});p.addEventListener("click",b=>{b.preventDefault(),f(b)}),p.addEventListener("keydown",b=>{(b.key==="Enter"||b.key===" ")&&(b.preventDefault(),f())})}G.querySelectorAll(".meta-select[data-meta-field]").forEach(u=>{u.addEventListener("change",async()=>{let m=u.dataset.metaField;if(m==="type"){await ye(t,{type:u.value});return}if(m==="state_id"){await ye(t,{state_id:u.value});return}if(m==="parent_ticket_id"){await ye(t,{parent_ticket_id:u.value||null});return}m==="priority"&&await ye(t,{priority:Number(u.value)})})});let i=async u=>{await ye(t,{labels:u})};k.querySelectorAll("[data-remove-label]").forEach(u=>{u.addEventListener("click",async()=>{let m=u.getAttribute("data-remove-label"),p=(e.labels||[]).map(f=>f.name).filter(f=>f!==m);await i(p)})});let l=async()=>{let u=k.querySelector("[data-label-input]");if(!u)return;let m=u.value.trim();if(!m)return;let p=(e.labels||[]).map(f=>f.name);if(p.includes(m)){u.value="";return}p.push(m),u.value="",await i(p)};k.querySelector("[data-label-add]")?.addEventListener("click",()=>{l()}),k.querySelector("[data-label-input]")?.addEventListener("keydown",u=>{u.key==="Enter"&&(u.preventDefault(),l())})}async function ve(e={}){if(c.detailMode==="settings"){await ge(),pa();return}if(!c.selectedTicketId){vt();return}let t=c.selectedTicketId,a=g=>Object.prototype.hasOwnProperty.call(e,g),[n,r,o,s]=await Promise.all([a("context")?Promise.resolve(e.context):v(x(`/api/tickets/${t}/context?depth=1`)),a("statusHistory")?Promise.resolve(e.statusHistory):v(x(`/api/tickets/${t}/history`)),a("comments")?Promise.resolve(e.comments):v(x(`/api/tickets/${t}/comments`)).then(g=>g.comments||[]),a("attachmentList")?Promise.resolve(e.attachmentList):O.attachments?v(x(`/api/tickets/${t}/attachments`)).catch(()=>({attachments:[]})):Promise.resolve({attachments:[]})]);if(c.detailMode!=="ticket"||c.selectedTicketId!==t||n.ticket?.id!==t)return;let i=n.ticket;It(i.id,i.updated_at),document.querySelector(`.card[data-ticket-id="${CSS.escape(i.id)}"] .card-unread-dot`)?.remove();let l=oa(i.state_id),u=["epic","feature","task","bug"].map(g=>`<option value="${d(g)}" ${N(i.type)===g?"selected":""}>${d(Xa(g))}</option>`).join(""),m=l.map(g=>`<option value="${d(g.id)}" ${g.id===i.state_id?"selected":""}>${d(g.name)}</option>`).join(""),p=[0,1,2,3,4].map(g=>`<option value="${g}" ${Number(i.priority)===g?"selected":""}>${d(Ne(g))}</option>`).join(""),f=(i.labels||[]).map(g=>`
461
+ <span class="label-pill-removable" style="--label-color: ${d(g.color)}">
462
+ ${d(g.name)}
463
+ <button type="button" class="label-pill-remove" data-remove-label="${d(g.name)}" title="Remove label">\xD7</button>
464
+ </span>`).join(""),w=na().map(g=>g.name).filter(g=>!i.labels?.some(M=>M.name===g)).map(g=>`<option value="${d(g)}"></option>`).join(""),$=N(i.type),P=Oe(i.priority),C=l.find(g=>g.id===i.state_id),J=Xe(C),B=i.description?ce(i.description):d("No description yet."),S=i.description?"description preserved-text-body editable-field":"description editable-field is-placeholder",E=`
465
+ <span class="ticket-number">${d(ae(i))}</span>
466
+ <div class="detail-meta-badge-row" aria-label="Ticket metadata controls">
467
+ <select class="detail-meta-badge detail-state-badge meta-select" data-variant="${d(J)}" data-meta-field="state_id" aria-label="Ticket state">${m}</select>
468
+ <select class="detail-meta-badge detail-type-badge type-pill-${d($)} meta-select" data-meta-field="type" aria-label="Ticket type">${u}</select>
469
+ <select class="detail-meta-badge detail-priority-badge priority-pill meta-select" data-variant="${d(P)}" data-meta-field="priority" aria-label="Ticket priority">${p}</select>
470
+ </div>
471
+ `;wt({mode:"ticket",title:i.title,titleAttrs:{class:"editable-field","data-edit-field":"title",role:"button",tabindex:"0",title:"Click or press Enter to edit ticket title","aria-label":"Edit ticket title"},subtitleHtml:E,body:`
472
+ <div class="detail-head">
473
+ <p class="detail-updated" title="Last saved change">Updated ${d(Va(i.updated_at))}</p>
474
+ <div class="${S}" data-edit-field="description" tabindex="0" title="Click to edit">${B}</div>
475
+ <dl class="ticket-meta" id="ticketMetaGrid" data-ticket-id="${d(i.id)}">
476
+ <div class="ticket-meta-row ticket-meta-row--stack">
477
+ <dt>Labels</dt>
478
+ <dd>
479
+ <div class="label-pills-row" data-other-labels>${f}</div>
480
+ <div class="label-add-row">
481
+ <input type="text" class="label-add-input meta-inline-input" data-label-input list="board-label-suggestions" placeholder="Add label\u2026" aria-label="Add label" />
482
+ <datalist id="board-label-suggestions">${w}</datalist>
483
+ <button type="button" class="ghost meta-add-btn" data-label-add>Add</button>
484
+ </div>
485
+ </dd>
486
+ </div>
487
+ </dl>
488
+ </div>
489
+
490
+ ${Lo(i,n)}
491
+
492
+ ${O.attachments?yo(i,s.attachments||[]):""}
493
+
494
+ ${To(i,n)}
495
+
496
+ <div class="section">
497
+ <h3>Related</h3>
498
+ ${So(n.relations,i)}
499
+ </div>
500
+
501
+ ${q()?.ai_enabled!==0?`
502
+ <details class="section ai-fields" data-ai-plan-toggle data-ticket-id="${d(i.id)}"${go(i.id)?" open":""}>
503
+ <summary><h3>AI Plan / Implementation Record</h3></summary>
504
+ <div class="ai-fields-grid">
505
+ ${Rt({fieldName:"ai_plan",label:"AI-Written Plan",value:i.ai_plan,placeholder:"Paste or let an AI write the plan..."})}
506
+ ${Rt({fieldName:"implementation_summary",label:"Implementation Summary",value:i.implementation_summary,placeholder:"What changed, what shipped, what remains..."})}
507
+ ${Rt({fieldName:"implementation_updates",label:"Implementation Updates / Lessons",value:i.implementation_updates,placeholder:"Progress notes, mistakes to avoid, discoveries..."})}
508
+ </div>
509
+ </details>`:""}
510
+
511
+ <div class="section">
512
+ <h3>Status History</h3>
513
+ ${xo(r)}
514
+ </div>
515
+
516
+ <div class="section">
517
+ <h3>Comments</h3>
518
+ ${o.map(Eo).join("")||'<p class="description">No comments yet.</p>'}
519
+ <form class="comment-form" id="detailCommentForm">
520
+ <textarea name="body" placeholder="Add a comment, decision, or instruction..." required></textarea>
521
+ <button type="submit">Comment</button>
522
+ </form>
523
+ </div>
524
+ `}),bo(i),O.attachments&&ko(i),y("#detailCommentForm").addEventListener("submit",async g=>{g.preventDefault();let M=X(new FormData(g.currentTarget).get("body")).trim();M&&(await v(x(`/api/tickets/${i.id}/comments`),{method:"POST",body:{body:M}}),await le(i.id))}),k.querySelectorAll("[data-open-ticket]").forEach(g=>{g.addEventListener("click",async M=>{M.target.closest("[data-detach-child],[data-detach-parent],[data-detach-relation]")||A({boardId:c.boardId,view:"ticket",ticketId:g.dataset.openTicket})})}),k.querySelectorAll("[data-detach-child]").forEach(g=>{g.addEventListener("click",async M=>{M.stopPropagation();let R=g.dataset.detachChild;try{await v(x(`/api/tickets/${R}`),{method:"PATCH",body:{parent_ticket_id:null}})}catch(z){h.error(z.message||"Failed to remove child");return}await le(i.id,{renderBoardAfter:!0}),h.success("Removed from epic")})}),k.querySelectorAll("[data-detach-parent]").forEach(g=>{g.addEventListener("click",async M=>{M.stopPropagation();try{await v(x(`/api/tickets/${i.id}`),{method:"PATCH",body:{parent_ticket_id:null}})}catch(R){h.error(R.message||"Failed to remove parent");return}await le(i.id,{renderBoardAfter:!0}),h.success("Parent epic removed")})}),k.querySelectorAll("[data-detach-relation]").forEach(g=>{g.addEventListener("click",async M=>{M.stopPropagation();let R=g.dataset.detachRelation;try{await v(x(`/api/relations/${R}`),{method:"DELETE"})}catch(z){h.error(z.message||"Failed to remove relation");return}await le(i.id),h.success("Relation removed")})});let F=k.querySelector("[data-ai-plan-toggle]");F&&F.addEventListener("toggle",()=>{let g=F.dataset.ticketId;F.open?localStorage.setItem(`mab_ai_plan_open:${g}`,"1"):localStorage.removeItem(`mab_ai_plan_open:${g}`)});let H=k.querySelector("#parentEpicForm");if(H){let g=H.querySelector("[name=target]"),M=H.querySelector("[data-parent-epic-clear]"),R=()=>{H.classList.toggle("has-value",g.value.length>0)};g.addEventListener("input",R),R(),M.addEventListener("click",()=>{g.value="",R(),g.focus()}),H.addEventListener("submit",async z=>{z.preventDefault();let ee=String(new FormData(z.currentTarget).get("target")||"").trim();if(!ee)return;let W=Bn(ee,i.id);if(!W){h.warning("Pick an epic from the suggestions");return}let oe=Y().find(V=>V.id===W);if(!oe||N(oe.type)!=="epic"){h.warning("Parent must be an epic");return}try{await v(x(`/api/tickets/${i.id}`),{method:"PATCH",body:{parent_ticket_id:W}})}catch(V){h.error(V.message||"Failed to set parent epic");return}await le(i.id,{renderBoardAfter:!0}),h.success("Parent epic set")})}let L=k.querySelector("#relatedAddForm");if(L){let g=L.querySelector("[name=target]"),M=L.querySelector("[data-related-clear]"),R=()=>{L.classList.toggle("has-value",g.value.length>0)};g.addEventListener("input",R),R(),M.addEventListener("click",()=>{g.value="",R(),g.focus()}),L.addEventListener("submit",async z=>{z.preventDefault();let ee=new FormData(z.currentTarget),W=String(ee.get("target")||"").trim(),oe=String(ee.get("type")||"relates_to");if(!W)return;let V=Bn(W,i.id);if(!V){h.warning("Pick a ticket from the suggestions");return}try{await v(x("/api/relations"),{method:"POST",body:{source_ticket_id:i.id,target_ticket_id:V,type:oe}})}catch(Ce){h.error(Ce.message||"Failed to add relation");return}await le(i.id)})}pa()}function go(e){return localStorage.getItem(`mab_ai_plan_open:${e}`)==="1"}function yo(e,t=[]){let a=t.length?`<div class="attachment-grid">${t.map(n=>vo(e,n)).join("")}</div>`:'<p class="description">No images attached yet.</p>';return`
525
+ <div class="section attachments-section" data-attachment-section data-ticket-id="${d(e.id)}">
526
+ <div class="attachment-heading-row">
527
+ <h3>Images</h3>
528
+ <label class="ghost attachment-upload-button">
529
+ Upload
530
+ <input type="file" accept="image/*" multiple data-attachment-input />
531
+ </label>
532
+ </div>
533
+ <div class="attachment-dropzone" data-attachment-dropzone tabindex="0">
534
+ <strong>Paste, drag, or upload images</strong>
535
+ <span>PNG, JPG, GIF, WebP, SVG, BMP, or AVIF up to 10 MB each.</span>
536
+ </div>
537
+ ${a}
538
+ </div>
539
+ `}function vo(e,t){let a=d(t.original_name||"image"),n=`${wo(t.size_bytes)} \xB7 ${d(t.mime_type||"image")}`;if(t.missing)return`
540
+ <article class="attachment-card is-missing">
541
+ <div class="attachment-missing-thumb">Missing</div>
542
+ <div class="attachment-card-meta"><strong>${a}</strong><span>${n}</span></div>
543
+ <button type="button" class="attachment-delete" data-delete-attachment="${d(t.id)}" aria-label="Remove missing image">\xD7</button>
544
+ </article>
545
+ `;let r=x(t.content_url||`/api/tickets/${e.id}/attachments/${t.id}/content`);return`
546
+ <article class="attachment-card">
547
+ <button type="button" class="attachment-thumb-button" data-open-lightbox="${d(r)}" data-lightbox-title="${a}">
548
+ <img src="${d(r)}" alt="${a}" loading="lazy" />
549
+ </button>
550
+ <div class="attachment-card-meta"><strong>${a}</strong><span>${n}</span></div>
551
+ <button type="button" class="attachment-delete" data-delete-attachment="${d(t.id)}" aria-label="Remove image">\xD7</button>
552
+ </article>
553
+ `}function wo(e){let t=Number(e||0);return t<1024?`${t} B`:t<1024*1024?`${(t/1024).toFixed(1)} KB`:`${(t/(1024*1024)).toFixed(1)} MB`}function Fn(e){return[...e||[]].filter(t=>t&&String(t.type||"").startsWith("image/"))}async function _a(e,t){let a=Fn(t);if(!a.length){h.warning("No image files found");return}for(let n of a){let r=await fetch(x(`/api/tickets/${e.id}/attachments?filename=${encodeURIComponent(n.name||"image")}`),{method:"POST",headers:{"Content-Type":n.type||"application/octet-stream","X-File-Name":n.name||"image"},body:n});if(!r.ok){let o={};try{o=await r.json()}catch{}throw new Error(o.error||`Upload failed (${r.status})`)}}await le(e.id),h.success(a.length===1?"Image attached":`${a.length} images attached`)}function ko(e){let t=k.querySelector("[data-attachment-section]");if(!t)return;let a=t.querySelector("[data-attachment-input]");a?.addEventListener("change",async()=>{try{await _a(e,a.files),a.value=""}catch(r){h.error(r.message||"Upload failed")}});let n=t.querySelector("[data-attachment-dropzone]");n?.addEventListener("dragover",r=>{r.preventDefault(),n.classList.add("is-dragover")}),n?.addEventListener("dragleave",()=>n.classList.remove("is-dragover")),n?.addEventListener("drop",async r=>{r.preventDefault(),n.classList.remove("is-dragover");try{await _a(e,r.dataTransfer?.files||[])}catch(o){h.error(o.message||"Upload failed")}}),k.onpaste=async r=>{if(r.target.closest("input, textarea, [contenteditable='true']"))return;let o=Fn(r.clipboardData?.files||[]);if(o.length){r.preventDefault();try{await _a(e,o)}catch(s){h.error(s.message||"Paste upload failed")}}},t.querySelectorAll("[data-delete-attachment]").forEach(r=>{r.addEventListener("click",async()=>{try{await v(x(`/api/tickets/${e.id}/attachments/${r.dataset.deleteAttachment}`),{method:"DELETE"}),await le(e.id),h.success("Image removed")}catch(o){h.error(o.message||"Delete failed")}})}),t.querySelectorAll("[data-open-lightbox]").forEach(r=>{r.addEventListener("click",()=>$o(r.dataset.openLightbox,r.dataset.lightboxTitle||"Image"))})}function $o(e,t){document.querySelector(".attachment-lightbox")?.remove();let n=document.createElement("div");n.className="attachment-lightbox",n.innerHTML=`
554
+ <div class="attachment-lightbox-panel" role="dialog" aria-modal="true" aria-label="${d(t)}">
555
+ <button type="button" class="attachment-lightbox-close" aria-label="Close image">\xD7</button>
556
+ <img src="${d(e)}" alt="${d(t)}" />
557
+ <p>${d(t)}</p>
558
+ </div>
559
+ `;let r=()=>{document.removeEventListener("keydown",o),n.remove()};function o(s){s.key==="Escape"&&r()}n.addEventListener("click",s=>{(s.target===n||s.target.closest(".attachment-lightbox-close"))&&r()}),document.addEventListener("keydown",o),document.body.append(n)}function Bn(e,t){let a=e.trim(),n=a.match(/^#?(\d+)\b/),r=Y().filter(s=>s.id!==t);if(n){let s=Number(n[1]),i=r.find(l=>l.number===s);if(i)return i.id}let o=r.find(s=>`#${s.number} \u2014 ${s.title}`===a);return o?o.id:""}function xo(e){return!e||e.length===0?'<p class="description">No status changes yet.</p>':e.map(t=>{let a=t.body,n=a.from?d(a.from):"?",r=d(a.to||a.state||a.next_state||"?"),o=d(Ia({actor:t.actor,actorType:a.actor_type||"human",actorId:a.actor_id}));return`<div class="comment status-change">
560
+ <div class="comment-meta">
561
+ <span class="status-route">${n} \u2192 ${r}</span>
562
+ <span>${o} \xB7 ${Ve(t.created_at)}</span>
563
+ </div>
564
+ </div>`}).join("")}function Eo(e){return`
565
+ <div class="comment ${e.kind==="checkpoint"?"checkpoint":""}">
566
+ <div class="comment-meta">
567
+ <strong>${d(Pn(e))}</strong>
568
+ <span>${e.kind==="human_comment"?"":`${d(e.kind)} - `}${Ve(e.created_at)}</span>
569
+ </div>
570
+ <div class="comment-body preserved-text-body">${ce(e.body)}</div>
571
+ </div>
572
+ `}function Rt({fieldName:e,label:t,value:a,placeholder:n}){let r=a||"",o=!!r.trim(),s=o?ce(r):d(n||""),i=o?"":"is-placeholder";return`
573
+ <div class="inline-md-field">
574
+ <span class="inline-md-field-label">${d(t)}</span>
575
+ <div
576
+ class="inline-md-field-body preserved-text-body editable-field ${i}"
577
+ data-edit-field="${d(e)}"
578
+ tabindex="0"
579
+ title="Click to edit"
580
+ role="button"
581
+ aria-label="Edit ${d(t)}"
582
+ >${s}</div>
583
+ </div>
584
+ `}function So(e=[],t){let a=new Set(e.map(l=>l.other_ticket.id)),n=new Set;if(t?.parent_ticket_id&&n.add(t.parent_ticket_id),t?.id)for(let l of Y())l.parent_ticket_id===t.id&&n.add(l.id);let o=Y().filter(l=>l.id!==t?.id&&!a.has(l.id)&&!n.has(l.id)).map(l=>`<option value="#${l.number} \u2014 ${d(l.title)}"></option>`).join(""),s=e.length?`<div class="detail-card-grid">${e.map(l=>Io(l)).join("")}</div>`:"",i=`
585
+ <form id="relatedAddForm" class="related-add-row">
586
+ <div class="related-add-input-wrap">
587
+ <input type="text" name="target" class="related-add-input meta-inline-input" list="related-ticket-suggestions" placeholder="Add related ticket\u2026" aria-label="Add related ticket" autocomplete="off" />
588
+ <button type="button" class="related-add-clear" data-related-clear aria-label="Clear" tabindex="-1">\xD7</button>
589
+ <datalist id="related-ticket-suggestions">${o}</datalist>
590
+ </div>
591
+ <select name="type" class="related-add-type meta-inline" aria-label="Relation type">
592
+ <option value="relates_to">relates to</option>
593
+ <option value="blocks">blocks</option>
594
+ <option value="blocked_by">blocked by</option>
595
+ </select>
596
+ <button type="submit" class="ghost meta-add-btn">Add</button>
597
+ </form>
598
+ `;return s+i}function Lo(e,t){if(N(e.type)==="epic"){let n=t.child_tickets||[];return`
599
+ <div class="section">
600
+ <h3>Features inside this Epic</h3>
601
+ ${n.length?`<div class="detail-card-grid">${n.map(o=>Ue(o,{detach:{mode:"child",id:o.id}})).join("")}</div>`:'<p class="description">No child features yet. Create a feature / task card and set this epic as its parent.</p>'}
602
+ </div>
603
+ `}return""}function To(e,t){if(N(e.type)==="epic")return"";let n=Y().filter(o=>o.type==="epic"&&o.id!==e.id).map(o=>`<option value="#${o.number} \u2014 ${d(o.title)}"></option>`).join("");return`
604
+ <div class="section">
605
+ <h3>Epic</h3>
606
+ ${t.parent_ticket?`<div class="detail-card-grid detail-card-grid--single">${Ue(t.parent_ticket,{detach:{mode:"parent"}})}</div>`:`
607
+ <form id="parentEpicForm" class="related-add-row">
608
+ <div class="related-add-input-wrap">
609
+ <input type="text" name="target" class="related-add-input meta-inline-input" list="parent-epic-suggestions" placeholder="Set parent epic\u2026" aria-label="Set parent epic" autocomplete="off" />
610
+ <button type="button" class="related-add-clear" data-parent-epic-clear aria-label="Clear" tabindex="-1">\xD7</button>
611
+ <datalist id="parent-epic-suggestions">${n}</datalist>
612
+ </div>
613
+ <button type="submit" class="ghost meta-add-btn">Set</button>
614
+ </form>
615
+ `}
616
+ </div>
617
+ `}function Ue(e,t={}){let a=N(e.type),n=Oe(e.priority),r=Xe(e),o=De(e.type).toUpperCase(),s=t.eyebrow?`<span class="card-eyebrow">${d(t.eyebrow)}</span>`:"",i="";if(t.detach){let{mode:m,id:p}=t.detach,f="",b="";m==="child"?(f=`data-detach-child="${d(p)}"`,b="Remove from epic"):m==="parent"?(f='data-detach-parent="1"',b="Remove parent epic"):m==="relation"&&(f=`data-detach-relation="${d(p)}"`,b="Remove relation"),i=`<button type="button" class="card-detach-btn" ${f} aria-label="${b}" title="${b}">\xD7</button>`}else if(t.archive){let m=d(t.archive.id);i=`
618
+ <div class="card-archive-actions">
619
+ <button type="button" class="card-archive-btn card-archive-btn--restore" data-archive-restore="${m}" aria-label="Restore to board" title="Restore to board"><svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M3 12a9 9 0 1 0 3-6.7"/><path d="M3 4v5h5"/></svg></button>
620
+ <button type="button" class="card-archive-btn card-archive-btn--delete" data-archive-delete="${m}" aria-label="Delete permanently" title="Delete permanently"><svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M3 6h18"/><path d="M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/><path d="M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6"/><path d="M10 11v6"/><path d="M14 11v6"/></svg></button>
621
+ </div>
622
+ `}let l=Tt(e),u=l===0?"":l===1?'<span class="card-unread-dot" role="status" aria-label="1 unread update"></span>':`<span class="card-unread-dot has-count" role="status" aria-label="${l} unread updates">${l>99?"99+":l}</span>`;return`
623
+ <article class="card card--detail type-${d(a)} priority-${d(n)}" data-variant="${d(a)}"${t.disableOpen?"":` data-open-ticket="${d(e.id)}"`}>
624
+ ${u}
625
+ ${i}
626
+ ${s}
627
+ <h3>${d(e.title)}</h3>
628
+ <div class="card-meta">
629
+ <div class="card-expand-trigger card-expand-trigger--static">
630
+ <span class="ticket-number">${d(ae(e))}</span>
631
+ <div class="card-type-id type-pill-${d(a)}">
632
+ ${Ct(e.type)}
633
+ <span class="card-type-label">${d(o)}</span>
634
+ </div>
635
+ <span class="detail-card-state" data-variant="${d(r)}">${d(e.state_name||"State")}</span>
636
+ ${c.showPriority?xa(e.priority):""}
637
+ </div>
638
+ </div>
639
+ </article>
640
+ `}function Io(e){let t=String(e.type||"").replace(/_/g," "),a=e.direction==="incoming"?"from":"to";return Ue(e.other_ticket,{eyebrow:`${t} ${a}`,detach:{mode:"relation",id:e.id}})}var Ft=_(()=>{U();ie();ne();ot();kt();be();Q();qe();fe();_n();nt();An()});function Ca(){ze&&(clearTimeout(ze),ze=null),c.eventSource&&(c.eventSource.close(),c.eventSource=null);let e=new URLSearchParams;c.boardId&&e.set("board_id",c.boardId);let t=`/api/events/stream${e.toString()?`?${e}`:""}`,a=new EventSource(t);c.eventSource=a,a.addEventListener("open",()=>{Dt=1e3,Nt&&(h.success("Live updates reconnected"),Nt=!1)}),a.addEventListener("board",async n=>{let r;try{r=JSON.parse(n.data)}catch{return}let o=r.type,s=()=>c.data?.tickets?.find(u=>u.id===r.ticket_id),i=c.data?.actor?.name,l=r.actor&&i&&r.actor===i;if(r.ticket_id&&(l?It(r.ticket_id,r.timestamp):o==="ticket_deleted"?bn(r.ticket_id):_o.has(o)&&hn(r.ticket_id)),o==="ticket_created")h.success(`Card created: ${r.data.title||"New card"}`),we();else if(o==="state_changed"){let u=s(),m=u?`#${u.number} ${u.title}`:"Card";h.info(`${m} \u2192 ${r.data.to}`),we()}else if(o==="ticket_updated"){let u=s(),m=u?`#${u.number}`:"Card",p=r.data.fields?Object.keys(r.data.fields).join(", "):"";h.info(`${m} updated${p?`: ${p}`:""}`),we()}else if(o==="comment_created"){let u=s(),m=u?`#${u.number}`:"ticket";h.info(`New comment on ${m}`),we()}else if(o==="agent_claimed"){let u=s();h.info(`Agent claimed ${u?`#${u.number} ${u.title}`:"a ticket"}`),we()}else if(o==="checkpoint_requested"){let u=s();h.warning(`Checkpoint on ${u?`#${u.number}`:"ticket"} \u2014 needs human input`),we()}else if(o==="agent_completed"){let u=s();h.success(`Agent completed ${u?`#${u.number} ${u.title}`:"a ticket"}`),we()}else(o==="ticket_deleted"||o==="states_reordered"||o==="state_created"||o==="state_deleted"||o==="board_updated"||o==="board_imported")&&we()}),a.onerror=()=>{if(a.readyState!==EventSource.CLOSED||(Nt||(h.warning("Live updates disconnected \u2014 retrying\u2026"),Nt=!0),ze))return;let n=Dt;Dt=Math.min(Dt*2,3e4),ze=setTimeout(()=>{ze=null,Ca()},n)}}var _o,Dt,ze,Nt,we,Dn=_(()=>{U();Q();fe();he();nt();_o=new Set(["ticket_created","state_changed","ticket_updated","comment_created","agent_claimed","checkpoint_requested","agent_completed"]),Dt=1e3,ze=null,Nt=!1;we=yt(async()=>{let e=c.selectedTicketId,t=c.detailMode;c.data=await v(Qe()),xe(),c.selectedTicketId=e,c.detailMode=t,await Ot()},300)});function Mo(e){return X(e||"").split(`
641
+ `).map(t=>t.trim()).filter(Boolean).join(" ").replace(/\s+/g," ").trim()}function Po(e={}){return Mo(e.project_notes)||Ma}function Ao(e,t){if(!e?.id||!t?.data?.boards)return;let a=t.data.boards.findIndex(n=>n.id===e.id);a>=0&&t.data.boards.splice(a,1,{...t.data.boards[a],...e})}function Bo(e){let t=e?.project_notes||"",a=!!t.trim(),n=a?"":" is-placeholder",r=a?ce(t):d(Co);return`
642
+ <div
643
+ class="inline-md-field-body preserved-text-body editable-field brand-focus-notes-edit${n}"
644
+ data-edit-field="project_notes"
645
+ tabindex="0"
646
+ title="Click to edit"
647
+ role="button"
648
+ aria-label="Edit board notes"
649
+ >${r}</div>
650
+ `}function Ge(e=Z){Z=e||{};let t=Po(Z),a=document.getElementById("brandNotesBtn"),n=document.getElementById("brandNotesText"),r=document.getElementById("brandFocusNotes");a&&(a.hidden=!1,a.dataset.empty=t===Ma?"true":"false",a.setAttribute("aria-label",`Show board notes: ${t}`)),n&&(n.textContent=t===Ma?"":t),r&&(r.innerHTML=Bo(Z))}function it(e){let t=[document.getElementById("brandFocusBtn"),document.getElementById("brandNotesBtn")].filter(Boolean),a=document.getElementById("brandFocusPopover");if(a){for(let n of t)n.setAttribute("aria-expanded",e?"true":"false"),n.dataset.state=e?"open":"closed";a.hidden=!e}}function Nn(){let e=document.getElementById("brandFocusPopover");Ge(),it(!!e?.hidden)}async function On(e){let t=document.querySelector('#brandFocusPopover [data-edit-field="project_notes"]');if(!t||!Z?.id)return;let{startInlineEdit:a}=await Promise.resolve().then(()=>(Ft(),Rn));a(t,{fieldName:"project_notes",multiline:!0,initialValue:Z.project_notes||"",ariaLabel:"Edit board notes",sourceEvent:e,rerender:async()=>{Ge(Z),it(!0)},commit:async n=>{let[{api:r},{state:o}]=await Promise.all([Promise.resolve().then(()=>(Q(),nn)),Promise.resolve().then(()=>(U(),Wa))]),s=await r(`/api/boards/${encodeURIComponent(Z.id||o.boardId)}`,{method:"PATCH",body:{project_notes:X(n)}});Z={...Z,...s},Ao(Z,o),Ge(Z),it(!0)}})}function jn(){let e=document.getElementById("brandFocusBtn"),t=document.getElementById("brandNotesBtn"),a=document.getElementById("brandFocusPopover");!e||!t||!a||(e.addEventListener("click",n=>{n.stopPropagation(),Nn()}),t.addEventListener("click",n=>{n.stopPropagation(),Nn()}),a.addEventListener("click",n=>{n.stopPropagation(),n.target.closest('[data-edit-field="project_notes"]')&&On(n)}),a.addEventListener("keydown",n=>{n.key!=="Enter"&&n.key!==" "||n.target.closest('[data-edit-field="project_notes"]')&&(n.preventDefault(),On(n))}),document.addEventListener("click",n=>{n.target.closest("#brandFocusBtn")||n.target.closest("#brandNotesBtn")||n.target.closest("#brandFocusPopover")||it(!1)}),document.addEventListener("keydown",n=>{n.key==="Escape"&&it(!1)}))}var Ma,Co,Z,Pa=_(()=>{ne();Ma="No board notes yet",Co="Add board notes for yourself and your agents\u2026";Z={}});var qn={};ut(qn,{load:()=>I,render:()=>Ot,renderDetailOnly:()=>Fo});async function I(){se(),c.data=await v(Qe()),xe(),gn(c.boardId,c.data?.tickets||[]),await Ot(),O.sse&&c.boardId!==Hn&&(Hn=c.boardId,Ca())}async function Ot(){xe(),Aa(),Ge(q()),je(),await ve()}async function Fo(){xe(),Aa(),Ge(q()),vn(),await ve()}var Hn,he=_(()=>{U();Q();ot();Ft();st();Dn();nt();qe();Pa();Hn=null});function Fa(){return Me?.classList.contains("is-open")}function Mt(e){clearTimeout(Ba),se(),vt(),Kt.innerHTML=Ro(e||""),Do(),y("#createFlyoutClose")?.addEventListener("click",()=>D()),Me.hidden=!1,$e.hidden=!1,requestAnimationFrame(()=>{Me.classList.add("is-open"),$e.classList.add("is-visible")}),requestAnimationFrame(()=>{y("#createTicketTitle")?.focus()})}function D(){clearTimeout(Ba),Me.classList.remove("is-open"),$e.classList.remove("is-visible"),Ba=setTimeout(()=>{Me.hidden=!0,$e.hidden=!0,Kt.innerHTML=""},220)}function Ro(e){let t=Ee(),a=t.find(s=>s.is_default)||t[0],n=e&&t.some(s=>s.id===e)?e:a?.id||"",r=t.map(s=>`<option value="${d(s.id)}" ${s.id===n?"selected":""}>${d(s.name)}</option>`).join(""),o=Y().filter(s=>s.type==="epic").map(s=>`<option value="${d(s.id)}">${d(ae(s))}</option>`).join("");return`
651
+ <div class="create-flyout-head">
652
+ <h2>New card</h2>
653
+ <button type="button" class="create-flyout-close ghost" id="createFlyoutClose" aria-label="Close">\xD7</button>
654
+ </div>
655
+ <form id="createTicketForm" class="create-flyout-form">
656
+ <input id="createTicketTitle" name="title" type="text" placeholder="Title \u2014 what is this card?" autocomplete="off" required />
657
+ <textarea id="createTicketDescription" name="description" placeholder="Description (optional)"></textarea>
658
+ <div class="create-flyout-grid">
659
+ <label>
660
+ Lane
661
+ <select id="createTicketState" name="state" class="select-chevron-field" aria-label="Lane">${r}</select>
662
+ </label>
663
+ <label>
664
+ Type
665
+ <select id="createTicketType" name="type" class="select-chevron-field" aria-label="Ticket type">
666
+ <option value="epic">Epic</option>
667
+ <option value="feature">Feature</option>
668
+ <option value="task" selected>Task</option>
669
+ <option value="bug">Bug</option>
670
+ </select>
671
+ </label>
672
+ <label>
673
+ Priority
674
+ <select id="createTicketPriority" name="priority" class="select-chevron-field" aria-label="Priority">
675
+ <option value="0">MAYBE</option>
676
+ <option value="1">LOW</option>
677
+ <option value="2" selected>MED</option>
678
+ <option value="3">HIGH</option>
679
+ <option value="4">URGENT</option>
680
+ </select>
681
+ </label>
682
+ </div>
683
+ <label>
684
+ Parent epic
685
+ <select id="createTicketParent" name="parent_ticket_id" class="select-chevron-field" aria-label="Parent epic">
686
+ <option value="">None</option>
687
+ ${o}
688
+ </select>
689
+ </label>
690
+ <input id="createTicketLabels" name="labels" type="text" placeholder="Labels (comma-separated)" />
691
+ <button type="submit">Create card</button>
692
+ </form>
693
+ `}function Do(){let e=y("#createTicketForm");e&&e.addEventListener("submit",No)}async function No(e){e.preventDefault();let t=e.currentTarget,a=new FormData(t),n=String(a.get("labels")||"").split(",").map(o=>o.trim()).filter(Boolean),r=await v("/api/tickets",{method:"POST",body:{board_id:c.boardId,title:a.get("title"),description:a.get("description"),type:a.get("type"),parent_ticket_id:a.get("parent_ticket_id")||null,state_id:a.get("state"),priority:Number(a.get("priority")),labels:n}});D(),c.selectedTicketId=r.id,c.detailMode="ticket",await I(),Ke()}var Ba,He=_(()=>{ie();U();ne();Q();be();kt();st();he();Ba=0});function ct(){te&&(te.hidden=!0,te.innerHTML="",ue?.setAttribute("aria-expanded","false"))}function se(){ct()}function Aa(){if(!c.data)return;let e=(c.data.boards||[]).find(t=>t.id===c.boardId);if(ue){let t=e?.name||"Board";ue.innerHTML=`${Oo}<span class="topbar-chip-label">${d(t)}</span>`,ue.title=e?`${e.name} \u2014 slug: ${e.slug}`:"Choose board"}}function jo(){let a=(c.data.boards||[]).map(r=>`
694
+ <button type="button" class="menu-flyout-item ${r.id===c.boardId?"is-current":""}" data-variant="menu-item" data-pick-board="${d(r.id)}" role="menuitem">
695
+ <span class="menu-flyout-item-title">${d(r.name)}</span>
696
+ <span class="menu-flyout-item-meta">${d(r.slug)}</span>
697
+ </button>`).join("")||'<p class="menu-flyout-hint menu-flyout-hint--empty">No boards yet. Create one below if you can.</p>',n=O.multiBoard?`
698
+ <div class="menu-flyout-section">
699
+ <h3 class="menu-flyout-heading">New board</h3>
700
+ <form id="createBoardForm" class="menu-flyout-form">
701
+ <input name="name" type="text" required placeholder="Board name" autocomplete="off" />
702
+ <div class="folder-picker-field">
703
+ <input id="repoPathInput" name="repo_path" type="text" readonly placeholder="Coding project folder (optional)" autocomplete="off" />
704
+ <button type="button" id="pickRepoFolderBtn">Browse</button>
705
+ </div>
706
+ <div id="helperFilesReveal" hidden>
707
+ <p class="menu-flyout-hint menu-flyout-hint--intro">Orbit writes <code>SKILL-ORBIT.md</code> and <code>AGENTS.md</code> into this folder for your AI coding agent.</p>
708
+ <label class="menu-flyout-check">
709
+ <input id="helperFilesCheckbox" name="manage_helper_files" type="checkbox" checked />
710
+ <span>Generate AI helper files (<code>SKILL-ORBIT.md</code>, <code>AGENTS.md</code>)</span>
711
+ </label>
712
+ </div>
713
+ <input name="slug" type="text" placeholder="Slug (optional)" autocomplete="off" />
714
+ <input name="default_branch" type="text" placeholder="Default branch (optional)" autocomplete="off" />
715
+ <input name="repo_url" type="text" placeholder="Repo URL (optional)" autocomplete="off" />
716
+ <button type="submit">Create board</button>
717
+ </form>
718
+ </div>`:"";return`
719
+ <div class="menu-flyout-head">Board</div>
720
+ <div class="menu-flyout-list">${a}</div>
721
+ ${n}
722
+ `}function Ho(){te.querySelectorAll("[data-pick-board]").forEach(t=>{t.addEventListener("click",async a=>{a.stopPropagation();let n=t.getAttribute("data-pick-board");ct(),n!==c.boardId&&(D(),await A({boardId:n,view:"board"}))})});let e=te.querySelector("#createBoardForm");if(e){let t=e.querySelector("#pickRepoFolderBtn"),a=e.querySelector("#repoPathInput"),n=e.querySelector("#helperFilesReveal"),r=()=>{n&&(n.hidden=!a.value.trim())};r(),t?.addEventListener("click",async o=>{o.preventDefault(),t.disabled=!0;try{let s=await v("/api/system/pick-folder",{method:"POST"});s.path&&(a.value=s.path,a.dispatchEvent(new Event("input",{bubbles:!0})),r())}catch(s){h.error(s?.message||"Folder picker unavailable")}finally{t.disabled=!1}}),e.addEventListener("submit",async o=>{o.preventDefault();let s=new FormData(e),i=String(s.get("slug")||"").trim(),l=String(s.get("default_branch")||"").trim(),u=String(s.get("repo_url")||"").trim(),m=String(s.get("repo_path")||"").trim(),p=await v("/api/boards",{method:"POST",body:{name:s.get("name"),...m?{repo_path:m,manage_helper_files:s.get("manage_helper_files")==="on"}:{},...i?{slug:i}:{},...l?{default_branch:l}:{},...u?{repo_url:u}:{}}});ct(),c.boardId=p.id,c.selectedTicketId="",c.detailMode="settings",await I(),Ke(),h.success("Board created")})}}function Un(){D(),te.innerHTML=jo(),te.hidden=!1,ue?.setAttribute("aria-expanded","true"),Ho()}var Oo,st=_(()=>{ie();U();ne();Q();be();He();fe();he();qe();Oo=`
723
+ <svg
724
+ class="topbar-icon"
725
+ width="16"
726
+ height="16"
727
+ viewBox="0 0 24 24"
728
+ fill="none"
729
+ aria-hidden="true"
730
+ >
731
+ <rect x="4" y="4" width="6" height="16" rx="0.75" stroke="currentColor" stroke-width="2" />
732
+ <rect x="14" y="4" width="6" height="16" rx="0.75" stroke="currentColor" stroke-width="2" />
733
+ </svg>`});function zn(){return{...qo}}function Da(e=globalThis.location){if(typeof e=="string"){let t=new URL(e,"http://orbit.local");return{pathname:t.pathname||"/",search:t.search||"",hash:t.hash||""}}return{pathname:e?.pathname||"/",search:e?.search||"",hash:e?.hash||""}}function Ra(e){try{return decodeURIComponent(e)}catch{return e}}function Uo(e){return String(e||"").replace(/^#/,"").replace(/^\/+/,"").replace(/\/+$/,"").split("/").filter(Boolean)}function zo(e){if(!e.length)return null;let t=zn(),a=0;if(e[a]==="b"){if(!e[a+1])return null;t.boardSlug=Ra(e[a+1]),a+=2}else if(e[a]!=="t"&&e[a]!=="settings")return null;if(e[a]==="t"&&e[a+1])t.view="ticket",t.ticketId=Ra(e[a+1]);else if(e[a]==="settings"){t.view="settings";let n=e[a+1]?Ra(e[a+1]):"";n&&ht.has(n)&&(t.tab=n)}return t}function Gn(e){let t=String(e||"");return!t||t==="#"||t==="#/"?null:zo(Uo(t))}function jt(e=globalThis.location){let t=Da(e);return Gn(t.hash)||zn()}function dt(e=globalThis.location){let t=Da(e);return!!Gn(t.hash)}function Je({boardSlug:e="",view:t="board",ticketId:a="",tab:n=""}={}){let r=[];return e&&r.push("b",encodeURIComponent(e)),t==="ticket"&&a?r.push("t",encodeURIComponent(a)):t==="settings"&&(r.push("settings"),n&&ht.has(n)&&r.push(n)),"#/"+r.join("/")}function Ht(e=globalThis.location,t=jt(e)){return Da(e).hash===Je(t)}var qo,Na=_(()=>{bt();qo=Object.freeze({boardSlug:"",view:"board",ticketId:"",tab:""})});function Kn(e){if(!e)return null;let t=c.data?.boards||[];return t.find(a=>a.slug===e)||t.find(a=>a.id===e)||null}function Go(e={}){return e.boardSlug?e.boardSlug:e.boardId?Kn(e.boardId)?.slug||e.boardId:q()?.slug||c.boardSlug||""}function Ko(e={}){return{...e,boardSlug:Go(e)}}function Jo(){let e="board";return c.detailMode==="ticket"&&c.selectedTicketId?e="ticket":c.detailMode==="settings"&&(e="settings"),{boardSlug:q()?.slug||c.boardSlug,view:e,ticketId:c.selectedTicketId,tab:e==="settings"?We(c.settingsTab):""}}function Jn(e){qt=e}function Oa(){return jt(location)}async function A(e,{replace:t=!1}={}){let a=Ko(e),n=Je(a);if(Ht(location,a)){qt&&await lt();return}t?history.replaceState(null,"",n):history.pushState(null,"",n),qt&&await lt()}function Ke({replace:e=!1}={}){let t=Jo(),a=Je(t);Ht(location,t)||(e?history.replaceState(null,"",a):history.pushState(null,"",a))}async function lt(){let{load:e,renderDetailOnly:t}=await Promise.resolve().then(()=>(he(),qn)),a=Oa(),n=dt(location),r=c.boardId,s=Kn(a.boardSlug)||(a.boardSlug?q():null);s?(c.boardId=s.id,c.boardSlug=s.slug):a.boardSlug&&(c.boardSlug=a.boardSlug);let i=s?{...a,boardSlug:s.slug}:a;if(n&&!Ht(location,i)&&history.replaceState(null,"",Je(i)),a.view==="ticket")c.selectedTicketId=a.ticketId||"",c.detailMode=a.ticketId?"ticket":"empty";else if(a.view==="settings"){if(c.selectedTicketId="",c.detailMode="settings",a.tab){c.settingsTab=a.tab;try{localStorage.setItem("mab_settings_tab",a.tab)}catch{}}}else c.selectedTicketId="",c.detailMode="empty";if(se(),D(),c.boardId&&c.boardId!==r){await e();return}await t()}var qt,be=_(()=>{U();bt();st();He();Na();Na();qt=!1;window.addEventListener("popstate",()=>{qt&&lt()})});ie();Vt();ea();Ga(),Ye();var er=tr();ta();{let e=()=>{document.body.classList.toggle("is-scrolled",window.scrollY>4)};window.addEventListener("scroll",e,{passive:!0}),e()}Ja();ja?.addEventListener("click",()=>{Ka()});window.addEventListener(ft,()=>{Ja(),er.sync()});function Ja(){if(!Jt)return;let e=me()==="dark";Jt.innerHTML=e?'<path d="M21 12.79A9 9 0 1111.21 3 7 7 0 0021 12.79z" />':'<circle cx="12" cy="12" r="5" /><path d="M12 1v2m0 18v2M4.2 4.2l1.4 1.4m12.8 12.8l1.4 1.4M1 12h2m18 0h2M4.2 19.8l1.4-1.4M18.4 5.6l1.4-1.4" />'}function tr(){let e=document.querySelector(".grain");if(!e)return{sync:()=>{}};ar(e);let t=document.createElement("canvas");t.className="starfield-canvas",t.setAttribute("aria-hidden","true");let a=e.querySelector(".milky-way");a&&a.nextSibling?e.insertBefore(t,a.nextSibling):a?e.appendChild(t):e.insertBefore(t,e.firstChild);let n=t.getContext("2d"),r=Math.min(window.devicePixelRatio||1,2),o=0,s=0,i=[],l=0,u=!1,m={x:0,y:0,tx:0,ty:0};function p(){o=window.innerWidth,s=window.innerHeight,t.width=Math.round(o*r),t.height=Math.round(s*r),t.style.width=o+"px",t.style.height=s+"px",n.setTransform(r,0,0,r,0,0),f()}function f(){let S=o*s/1296e3,E=[{count:Math.round(320*S),depth:.12,sizes:[[1,.9],[1.4,.1]],glow:0},{count:Math.round(160*S),depth:.3,sizes:[[1,.5],[1.6,.4],[2.4,.1]],glow:1.8},{count:Math.round(44*S),depth:.58,sizes:[[1.8,.5],[2.6,.38],[3.6,.12]],glow:2.4}],F=Ya(12648430);i=[];for(let H of E)for(let L=0;L<H.count;L++){let g=rr(F(),H.sizes);i.push({x:F()*o,y:F()*s,size:g,depth:H.depth,glow:g>=2?H.glow:0,rgb:b(F()),period:2.2+F()*5.4,phase:F()*Math.PI*2,amp:.25+F()*.5,baseAlpha:g<1.5?.45+F()*.28:.55+F()*.22})}}function b(S){return S<.8?[255,255,255]:S<.93?[255,222,186]:[195,218,255]}function w(S){!o||!s||(m.tx=S.clientX/o-.5,m.ty=S.clientY/s-.5)}function $(S){m.x+=(m.tx-m.x)*.06,m.y+=(m.ty-m.y)*.06,n.clearRect(0,0,o,s),n.globalCompositeOperation="lighter";let E=S/1e3,F=70;for(let H=0;H<i.length;H++){let L=i[H],g=.5+.5*Math.sin(E*(2*Math.PI/L.period)+L.phase),M=L.baseAlpha*(1-L.amp+L.amp*g),R=L.x-m.x*L.depth*F,z=L.y-m.y*L.depth*F,[ee,W,oe]=L.rgb;if(L.glow>0){let V=L.size*L.glow,Ce=n.createRadialGradient(R,z,0,R,z,V);Ce.addColorStop(0,`rgba(${ee},${W},${oe},${M*.85})`),Ce.addColorStop(.35,`rgba(${ee},${W},${oe},${M*.3})`),Ce.addColorStop(1,`rgba(${ee},${W},${oe},0)`),n.fillStyle=Ce,n.beginPath(),n.arc(R,z,V,0,Math.PI*2),n.fill(),n.fillStyle=`rgba(${ee},${W},${oe},${M})`,n.beginPath(),n.arc(R,z,L.size/2,0,Math.PI*2),n.fill()}else{let V=L.size/2;n.fillStyle=`rgba(${ee},${W},${oe},${M})`,n.fillRect(R-V,z-V,L.size,L.size)}}n.globalCompositeOperation="source-over",u&&(l=requestAnimationFrame($))}function P(){n.clearRect(0,0,o,s),n.globalCompositeOperation="lighter";for(let S of i){let[E,F,H]=S.rgb;if(n.fillStyle=`rgba(${E},${F},${H},${S.baseAlpha})`,S.glow>0)n.beginPath(),n.arc(S.x,S.y,S.size/2,0,Math.PI*2),n.fill();else{let L=S.size/2;n.fillRect(S.x-L,S.y-L,S.size,S.size)}}n.globalCompositeOperation="source-over"}function C(){u||(u=!0,l=requestAnimationFrame($))}function J(){u=!1,cancelAnimationFrame(l)}function B(){let S=me()==="dark",E=Ae();if(!S){J(),n.clearRect(0,0,o,s);return}i.length||p(),E||document.hidden?(J(),P()):C()}return window.addEventListener("resize",()=>{p(),B()},{passive:!0}),window.addEventListener("pointermove",w,{passive:!0}),document.addEventListener("visibilitychange",B),window.matchMedia("(prefers-reduced-motion: reduce)").addEventListener("change",()=>{Ye(),B()}),window.addEventListener("orbit:motion-preference-change",B),p(),B(),{sync:B}}function ar(e){e.querySelectorAll(".signature-star").forEach(n=>n.remove());let t=Ya(6070757),a=7;for(let n=0;n<a;n++){let r=document.createElement("div");r.className="signature-star",r.setAttribute("aria-hidden","true"),r.style.left=(6+t()*88).toFixed(2)+"%",r.style.top=(8+t()*78).toFixed(2)+"%",r.style.animationDelay=(-t()*4.8).toFixed(2)+"s",e.appendChild(r)}}function ta(){let e=14e3+Math.random()*28e3;setTimeout(nr,e)}function nr(){let e=me()==="dark",t=Ae(),a=document.querySelector(".grain");if(!e||t||document.hidden||!a){ta();return}let n=window.innerWidth,r=window.innerHeight,o=Math.random()*n*.6,s=Math.random()*r*.55,i=380+Math.random()*520,l=18+Math.random()*26,u=l*Math.PI/180,m=o+Math.cos(u)*i,p=s+Math.sin(u)*i,f=document.createElement("div");f.className="meteor",f.setAttribute("aria-hidden","true"),f.style.setProperty("--from-x",o+"px"),f.style.setProperty("--from-y",s+"px"),f.style.setProperty("--to-x",m+"px"),f.style.setProperty("--to-y",p+"px"),f.style.setProperty("--angle",l+"deg"),a.appendChild(f),f.addEventListener("animationend",()=>f.remove(),{once:!0}),ta()}function rr(e,t){let a=0;for(let[n,r]of t)if(a+=r,e<a)return n;return t[t.length-1][0]}function Ya(e){let t=e>>>0;return function(){t=t+1831565813>>>0;let a=t;return a=Math.imul(a^a>>>15,a|1),a^=a+Math.imul(a^a>>>7,a|61),((a^a>>>14)>>>0)/4294967296}}ie();U();Q();fe();be();st();He();ot();ie();U();Q();be();ne();He();async function Yn(){let e=pt.value.trim();if(e.length<2){Ut();return}let t=q();if(!t)return;let a=await v(`/api/search?q=${encodeURIComponent(e)}&board=${encodeURIComponent(t.slug)}`);if(a.results.length===0){pe.hidden=!1,pe.innerHTML='<div class="search-hit">No results</div>';return}pe.hidden=!1,pe.innerHTML=a.results.map(n=>`
734
+ <div class="search-hit" data-ticket-id="${n.id}">
735
+ <span class="search-hit-main">
736
+ <strong>${d(ae(n))}</strong>
737
+ <span class="search-hit-title">${d(n.title)}</span>
738
+ </span>
739
+ <span class="search-hit-state" data-variant="${d(Xe(n))}">${d(n.state_name||"State")}</span>
740
+ </div>
741
+ `).join(""),pe.querySelectorAll("[data-ticket-id]").forEach(n=>{n.addEventListener("click",async()=>{D(),Ut(),A({boardId:c.boardId,view:"ticket",ticketId:n.dataset.ticketId})})})}function Ut(){pe.hidden=!0,pe.innerHTML=""}he();qe();function zt(e){e?.showModal()}function Wn(e){e?.open&&e.close()}function Gt(e){e&&(e.addEventListener("click",t=>{t.target===e&&Wn(e)}),e.querySelectorAll("[data-modal-close]").forEach(t=>{t.addEventListener("click",()=>Wn(e))}))}Pa();async function Yo(e){if(e)try{let t=await fetch("./version.json",{cache:"no-store"});if(!t.ok)return;let a=await t.json();a?.version&&(e.textContent=`v${a.version}`)}catch{}}function Vn(){let e=document.getElementById("helpDialog"),t=document.getElementById("helpBtn");!e||!t||(Gt(e),Yo(document.getElementById("helpDialogVersion")),t.addEventListener("click",()=>zt(e)))}async function Wo(){let e=document.getElementById("welcomeDialog");Gt(e),jn(),Vn(),Te==="preview"&&zt(e),y("#settingsBtn").addEventListener("click",async()=>{D(),se(),A({boardId:c.boardId,view:"settings",tab:c.settingsTab||"lanes"})}),ue?.addEventListener("click",a=>{if(a.stopPropagation(),!te.hidden){ct();return}Un()}),y("#newTicketBtn").addEventListener("click",()=>{if(Fa()){D();return}Mt("")}),$e.addEventListener("click",()=>{D()}),y("#drawerCloseBtn").addEventListener("click",()=>{A({boardId:c.boardId,view:"board"})}),y("#drawerArchiveBtn").addEventListener("click",async()=>{let a=c.selectedTicketId;if(!a||c.detailMode!=="ticket")return;let r=c.data?.tickets?.find(o=>o.id===a)?.title||"card";await v(x(`/api/tickets/${encodeURIComponent(a)}/archive`),{method:"POST"}),h.error(`Archived: ${r}`),await I(),A({boardId:c.boardId,view:"board"})}),ke.addEventListener("click",()=>{A({boardId:c.boardId,view:"board"})}),document.addEventListener("keydown",a=>{if(a.key!=="Escape")return;if(!te.hidden){se();return}if(Fa()){D();return}if(!G.classList.contains("is-open"))return;let n=document.activeElement;n?.classList?.contains("inline-title-editor")||n?.classList?.contains("inline-desc-editor")||A({boardId:c.boardId,view:"board"})}),pt.addEventListener("input",yt(Yn,220)),document.addEventListener("click",a=>{a.target.closest("#topbarSearch")||Ut(),a.target.closest(".topbar-menu")||se()}),kn(),yn();let t=Oa();t.boardSlug&&(c.boardSlug=t.boardSlug),await I(),Jn(!0),dt()?await lt():Ke({replace:!0})}Wo();
742
+ //# sourceMappingURL=app.js.map