viteboard 0.1.9 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/content-api-plugin.mjs +143 -1
- package/bin/pdf-export.mjs +337 -0
- package/content/machine/viteboard.json +1 -1
- package/dist/assets/index-CD-CmqNM.js +97 -0
- package/dist/assets/index-CD3PKrv7.css +1 -0
- package/dist/index.html +2 -2
- package/package.json +1 -1
- package/vite.config.ts +178 -1
- package/dist/assets/index-CE8x3f28.js +0 -95
- package/dist/assets/index-DvhOK1J_.css +0 -1
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
var ao=Object.defineProperty;var ro=(o,t,e)=>t in o?ao(o,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):o[t]=e;var m=(o,t,e)=>ro(o,typeof t!="symbol"?t+"":t,e);(function(){const t=document.createElement("link").relList;if(t&&t.supports&&t.supports("modulepreload"))return;for(const s of document.querySelectorAll('link[rel="modulepreload"]'))n(s);new MutationObserver(s=>{for(const i of s)if(i.type==="childList")for(const a of i.addedNodes)a.tagName==="LINK"&&a.rel==="modulepreload"&&n(a)}).observe(document,{childList:!0,subtree:!0});function e(s){const i={};return s.integrity&&(i.integrity=s.integrity),s.referrerPolicy&&(i.referrerPolicy=s.referrerPolicy),s.crossOrigin==="use-credentials"?i.credentials="include":s.crossOrigin==="anonymous"?i.credentials="omit":i.credentials="same-origin",i}function n(s){if(s.ep)return;s.ep=!0;const i=e(s);fetch(s.href,i)}})();const F="/__api";class fe extends Error{constructor(e,n){super(e);m(this,"currentRevision");this.name="RevisionConflictError",this.currentRevision=n}}async function z(o){var t;if(!o.ok){let e="";try{e=((t=await o.json())==null?void 0:t.error)??""}catch{}throw new Error(`${o.status} ${o.statusText}${e?` — ${e}`:""}`)}return o.json()}function H(o={}){return o}const k={async getWorkspace(){return z(await fetch(`${F}/workspace`,H()))},async removeProject(o){await z(await fetch(`${F}/workspace/project?id=${encodeURIComponent(o)}`,H({method:"DELETE"})))},async pickAndAddProject(){return z(await fetch(`${F}/workspace/pick-project`,H({method:"POST"})))},async addProject(o,t){return z(await fetch(`${F}/workspace/project`,H({method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({rootPath:o,label:t})})))},async ensureProjectDocsRoot(o){return(await z(await fetch(`${F}/workspace/project/docs-root`,H({method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({projectId:o})})))).root},async getTree(o){return(await z(await fetch(`${F}/tree?rootId=${encodeURIComponent(o)}`,H()))).tree},async getProjectTree(o){return(await z(await fetch(`${F}/project-tree?projectId=${encodeURIComponent(o)}`,H()))).tree},async createDocsFolder(o,t){await z(await fetch(`${F}/workspace/project/create-docs-folder`,H({method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({projectId:o,parentPath:t})})))},async readFile(o,t){return(await z(await fetch(`${F}/file?rootId=${encodeURIComponent(o)}&path=${encodeURIComponent(t)}`,H()))).content},async readFileWithRevision(o,t){return z(await fetch(`${F}/file?rootId=${encodeURIComponent(o)}&path=${encodeURIComponent(t)}`,H()))},async writeFile(o,t,e,n){const s=await fetch(`${F}/file`,H({method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({rootId:o,path:t,content:e,expectedRevision:n})}));if(s.status===409){const a=await s.json();throw new fe(a.error??"File changed on disk",a.currentRevision??null)}return(await z(s)).revision},async createDirectory(o,t){await z(await fetch(`${F}/directory`,H({method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({rootId:o,path:t})})))},async getBoard(o,t){const e=await fetch(`${F}/board?rootId=${encodeURIComponent(o)}&id=${encodeURIComponent(t)}`,H());return e.status===404?null:(await z(e)).doc},async getBoardWithRevision(o,t){const e=await fetch(`${F}/board?rootId=${encodeURIComponent(o)}&id=${encodeURIComponent(t)}`,H());return e.status===404?null:z(e)},async saveBoard(o,t,e,n){const s=await fetch(`${F}/board`,H({method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({rootId:o,id:t,doc:e,expectedRevision:n})}));if(s.status===409){const a=await s.json();throw new fe(a.error??"Board changed on disk",a.currentRevision??null)}return(await z(s)).revision},async deleteFile(o,t){await z(await fetch(`${F}/file?rootId=${encodeURIComponent(o)}&path=${encodeURIComponent(t)}`,H({method:"DELETE"})))},async renameFile(o,t,e,n=!1){await z(await fetch(`${F}/file`,H({method:"PATCH",headers:{"Content-Type":"application/json"},body:JSON.stringify({rootId:o,oldPath:t,newPath:e,ignoreMissing:n})})))},async deleteBoard(o,t){await z(await fetch(`${F}/board?rootId=${encodeURIComponent(o)}&id=${encodeURIComponent(t)}`,H({method:"DELETE"})))},assetUrl(o,t){return`${F}/asset?rootId=${encodeURIComponent(o)}&path=${encodeURIComponent(t)}`},async uploadAsset(o,t,e,n){return(await z(await fetch(`${F}/asset`,H({method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({rootId:o,name:t,base64:e,mimeType:n})})))).path},async cleanupManagedAssets(o,t=[]){return(await z(await fetch(`${F}/asset/cleanup`,H({method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({rootId:o,preservePaths:t})})))).removed}};function co(o,t){const e=o.find(i=>i.type==="dir"&&i.name===t);if(!e||e.type!=="dir")return[];const n=[],s=i=>{for(const a of i)a.type==="file"?n.push(a):s(a.children)};return s(e.children),n}function un(o){for(const t of o){if(t.type==="file"&&t.name.endsWith(".md"))return t.path;if(t.type==="dir"){const e=un(t.children);if(e)return e}}return null}function St(o){const t=[];for(const e of o.replace(/\\/g,"/").split("/")){const n=e.trim();if(!(!n||n===".")){if(n===".."){t.length>0&&t.pop();continue}t.push(n)}}return t.join("/")}function Bs(o){const t=St(o),e=t.lastIndexOf("/");return e===-1?"":t.slice(0,e)}function lo(o,t){if(/^(https?:|mailto:|tel:|#|data:)/.test(t))return t;if(t.startsWith("/"))return St(t);const e=Bs(o);return St(e?`${e}/${t}`:t)}function wn(o,t){const e=Bs(o),n=e?e.split("/").filter(Boolean):[],s=St(t).split("/").filter(Boolean);let i=0;for(;i<n.length&&i<s.length&&n[i]===s[i];)i++;const a=n.slice(i).map(()=>".."),r=s.slice(i);return[...a,...r].join("/")||s[s.length-1]||""}const ho=["sticky","task","rectangle","ellipse","text","line","arrow","connector","image","screenshot","frame","templateGroup"];function Ee(o){const t=new Set;for(const e of o.elements){const n=e.data.assetId;typeof n=="string"&&t.add(n)}return{...o.schemaUrl?{$schema:o.schemaUrl}:{},version:1,id:o.boardId,title:o.title,createdAt:o.createdAt,updatedAt:Date.now(),viewport:{...o.viewport},theme:o.theme,elements:o.elements,assetIds:[...t]}}function et(o){return typeof o=="number"&&Number.isFinite(o)}function Ms(o){if(typeof o!="object"||o===null)return null;const t=o;return typeof t.id!="string"||typeof t.type!="string"||!ho.includes(t.type)||!et(t.x)||!et(t.y)||!et(t.width)||!et(t.height)?null:{id:t.id,type:t.type,x:t.x,y:t.y,width:t.width,height:t.height,rotation:et(t.rotation)?t.rotation:0,zIndex:et(t.zIndex)?t.zIndex:0,locked:t.locked===!0,hidden:t.hidden===!0,createdAt:et(t.createdAt)?t.createdAt:Date.now(),updatedAt:et(t.updatedAt)?t.updatedAt:Date.now(),style:typeof t.style=="object"&&t.style!==null?t.style:{},data:typeof t.data=="object"&&t.data!==null?t.data:{}}}function We(o){if(typeof o!="object"||o===null)return null;const t=o;if(t.version!==1||typeof t.id!="string"||!Array.isArray(t.elements))return null;const e=[];for(const s of t.elements){const i=Ms(s);i&&e.push(i)}const n=t.viewport??{};return{...typeof t.$schema=="string"?{$schema:t.$schema}:{},version:1,id:t.id,title:typeof t.title=="string"?t.title.slice(0,200):"Imported Board",createdAt:et(t.createdAt)?t.createdAt:Date.now(),updatedAt:et(t.updatedAt)?t.updatedAt:Date.now(),viewport:{offsetX:et(n.offsetX)?n.offsetX:0,offsetY:et(n.offsetY)?n.offsetY:0,scale:et(n.scale)&&n.scale>.01&&n.scale<=40?n.scale:1},theme:t.theme==="dark"?"dark":"light",elements:e,assetIds:Array.isArray(t.assetIds)?t.assetIds.filter(s=>typeof s=="string"):[]}}const po="/board-v1.schema.json",uo=".board.json";function st(o){return o.replace(/\.board\.json$/,"")}function mo(o){return o.trim().replace(/^\/+/,"").replace(/\.board\.json$/,"")}function fo(o,t){return xe(o,t)[0]??""}function xe(o,t){const e=o.trim(),n=mo(o);if(!n)return[];if(e.startsWith("./")||e.startsWith("../")){const r=t.lastIndexOf("/"),c=r===-1?"":t.slice(0,r);return[St(c?`${c}/${n}`:n)]}if(e.startsWith("/")){const r=t.lastIndexOf("/"),c=r===-1?"":t.slice(0,r),l=St(c?`${c}/${n}`:n),d=[n];if(l&&l!==n&&d.push(l),c){const h=c.includes("/")?c.slice(0,c.lastIndexOf("/")):"",p=St(h?`${h}/${n}`:n);p&&!d.includes(p)&&d.push(p)}return d}const s=t.lastIndexOf("/"),i=s===-1?"":t.slice(0,s),a=St(i?`${i}/${n}`:n);return a&&a!==n?[a,n]:[n]}function Dn(o){return o.toLowerCase().replace(/[^\w\s-]/g,"").trim().replace(/\s+/g,"-").slice(0,48)||"board"}function go(o){return new Promise((t,e)=>{const n=new FileReader;n.onload=()=>{const s=n.result;t(s.slice(s.indexOf(",")+1))},n.onerror=()=>e(n.error),n.readAsDataURL(o)})}const at={async listIds(o){const t=await k.getTree(o);return yo(t).map(e=>st(e.path))},async list(o){const t=await this.listIds(o),e=[];for(const n of t){const s=await this.load(o,n);s&&e.push({id:n,title:s.title,elementCount:s.elements.length,updatedAt:s.updatedAt,filePath:`${n}.board.json`})}return e.sort((n,s)=>s.updatedAt-n.updatedAt),e},async load(o,t){const e=await k.getBoard(o,t);if(e)return We(e)??void 0},async save(o,t){await k.saveBoard(o,t.id,t)},async delete(o,t){await k.deleteBoard(o,t)},async move(o,t,e){const n=await this.load(o,t);if(!n)throw new Error("Board not found");const s=t.split("/").pop()??t,i=e.replace(/^\/+|\/+$/g,""),a=i?`${i}/${s}`:s;if(a===t)return t;if(new Set(await this.listIds(o)).has(a))throw new Error("A board already exists there");const c=Date.now();return await k.saveBoard(o,a,{...n,id:a,updatedAt:c}),await k.deleteBoard(o,t),a},async rename(o,t,e){const n=await this.load(o,t);if(!n)throw new Error("Board not found");const s=t.includes("/")?t.slice(0,t.lastIndexOf("/")):"",i=Dn(e),a=s?`${s}/${i}`:i,r=Date.now();if(a===t)return await k.saveBoard(o,t,{...n,title:e.trim()||n.title,updatedAt:r}),t;if(new Set(await this.listIds(o)).has(a))throw new Error("A board already exists with that name");return await k.saveBoard(o,a,{...n,id:a,title:e.trim()||n.title,updatedAt:r}),await k.deleteBoard(o,t),a},async create(o,t,e,n=""){const s=new Set(await this.listIds(o)),i=Dn(t);let r=`${n?`${n.replace(/^\/+|\/+$/g,"")}/`:""}${i}`;s.has(r)&&(r=`${r}-${Date.now().toString(36)}`);const c=Date.now(),l={$schema:po,version:1,id:r,title:t.trim()||"Untitled Board",createdAt:c,updatedAt:c,viewport:{offsetX:0,offsetY:0,scale:1},theme:e,elements:[],assetIds:[]};return await k.saveBoard(o,r,l),r},async uploadImage(o,t,e){const n=await go(t);return k.uploadAsset(o,e??"image.png",n,t.type)},async cleanupUnusedAssets(o,t=[]){return k.cleanupManagedAssets(o,t)}};function yo(o){const t=[],e=n=>{for(const s of n)s.type==="file"?s.name.endsWith(uo)&&t.push(s):e(s.children)};return e(o),t}const bo=new Set(["capabilities","assets"]);class vo{constructor(t,e){m(this,"element");m(this,"header");m(this,"nav");m(this,"footer");m(this,"links",new Map);m(this,"collapsibles",new Map);m(this,"collapsedState",new Map);m(this,"callbacks");m(this,"contextMenu");m(this,"draggedItem");m(this,"dropExpandTimer");m(this,"dropExpandTarget");m(this,"lastWorkspace",{projects:[]});m(this,"lastTreesByRoot",new Map);m(this,"lastTreesByProject",new Map);m(this,"rawModeProjects",new Set);m(this,"lastActiveHash","");m(this,"forceNextActiveSync",!0);this.callbacks=e,this.element=document.createElement("aside"),this.element.className="sidebar",this.header=document.createElement("div"),this.header.className="sidebar-header";const n=document.createElement("a");n.className="sidebar-brand",n.href="#/",n.textContent="ViteBoard",this.header.appendChild(n),this.nav=document.createElement("nav"),this.nav.className="sidebar-nav",this.footer=document.createElement("div"),this.footer.className="sidebar-footer";const s=document.createElement("button");s.className="sidebar-add-repo",s.type="button",s.textContent="Add Repo",s.title="Add a local project root",s.addEventListener("click",()=>this.callbacks.onAddRepo()),this.footer.appendChild(s),this.element.append(this.header,this.nav,this.footer),t.appendChild(this.element),document.addEventListener("pointerdown",i=>{this.contextMenu&&(this.contextMenu.contains(i.target)||this.closeContextMenu())},!0)}refresh(t,e,n){this.lastWorkspace=t,this.lastTreesByRoot=e,n&&(this.lastTreesByProject=n),this.render()}render(){const t=this.lastWorkspace,e=this.lastTreesByRoot;if(this.lastTreesByProject,this.nav.replaceChildren(),this.links.clear(),this.collapsibles.clear(),t.projects.length===0){const s=document.createElement("div");s.className="nav-group",s.appendChild(this.groupLabel("Workspace"));const i=document.createElement("div");i.className="nav-label nav-empty-copy",i.textContent="Add a project root to discover docs folders.",s.appendChild(i),this.nav.appendChild(s)}else for(const s of t.projects)this.nav.appendChild(this.projectSection(s,e));const n=document.createElement("div");n.className="nav-group",n.appendChild(this.groupLabel("System")),n.appendChild(this.link("#/tokens","Tokens","tokens-root")),this.nav.appendChild(n),this.setActive(location.hash,{forceSyncAncestors:this.forceNextActiveSync}),this.forceNextActiveSync=!1}setActive(t,e={}){var s,i;for(const a of new Set(this.links.values()))a.classList.remove("active");const n=this.links.get(t);if(n)n.classList.add("active");else if(t.startsWith("#/root/")){const a=t.match(/^#\/root\/([^/]+)\/(boards|capabilities|docs)(?:\/(.+))?$/);if(a){const[,r,c]=a,l=decodeURIComponent(r);c==="boards"?(s=this.links.get(Eo(l)))==null||s.classList.add("active"):c==="capabilities"&&((i=this.links.get(So(l)))==null||i.classList.add("active"))}}(e.forceSyncAncestors||t!==this.lastActiveHash)&&this.syncCollapsed(t),this.lastActiveHash=t}toggleRawMode(t){this.rawModeProjects.has(t)?this.rawModeProjects.delete(t):this.rawModeProjects.add(t),this.forceNextActiveSync=!0,this.render()}syncCollapsed(t){const e=this.ancestorKeys(t);for(const n of e)this.applyCollapsed(n,!1)}ancestorKeys(t){const e=new Set,n=t.match(/^#\/project\/([^/]+)(?:\/boards)?$/);if(n)return e.add(decodeURIComponent(n[1])),e;const s=t.match(/^#\/root\/([^/]+)\/(docs|boards|capabilities)(?:\/(.+))?$/);if(!s)return e;const i=decodeURIComponent(s[1]),a=s[2],r=s[3]?decodeURIComponent(s[3]):"";let c,l;for(const p of this.lastWorkspace.projects){const u=p.docsRoots.find(f=>f.id===i);if(u){c=p.id,l=u.displayPath;break}}if(!c||!l)return e;e.add(c),e.add(i);const d=l.split("/").filter(Boolean).slice(0,-1);let h="";for(const p of d){h=h?`${h}/${p}`:p;const u=`folder:${c}:${h}`;this.collapsibles.has(u)&&e.add(u)}if((a==="docs"||a==="capabilities")&&r){const u=(a==="capabilities"?`capabilities/${r}`:r).split("/");for(let f=1;f<u.length;f++){const y=u.slice(0,f).join("/"),b=`doc:${i}:${y}`;this.collapsibles.has(b)&&e.add(b)}}return e}projectSection(t,e){const{id:n,label:s,docsRoots:i}=t,a=this.rawModeProjects.has(n),r=document.createElement("div");r.className="nav-repo-body";const c=document.createElement("div");c.className="nav-group nav-repo-group";const l=document.createElement("div");l.className="nav-repo-header-row";const d=document.createElement("button");d.className="nav-repo-header",d.type="button";const h=document.createElement("span");h.className="nav-repo-chevron",h.textContent="›";const p=document.createElement("span");p.className="nav-repo-label-text",p.textContent=s;const u=!a&&i.find(v=>Tt(v.displayPath)==="docs"),f=document.createElement("span");f.className="nav-tree-badge",f.textContent="DOCS",f.hidden=!u;const y=document.createElement("button");y.className="nav-repo-more",y.type="button",y.title="Project options",y.innerHTML='<svg viewBox="0 0 16 16" width="14" height="14" fill="currentColor"><circle cx="8" cy="3" r="1.3"/><circle cx="8" cy="8" r="1.3"/><circle cx="8" cy="13" r="1.3"/></svg>',y.addEventListener("click",v=>{v.stopPropagation();const S=y.getBoundingClientRect();this.showContextMenu(S.right+4,S.top,s,[{icon:a?It:Wt,iconClass:a?"nav-ctx-doc":"nav-ctx-dir",label:a?"View: Docs":"View: Raw",action:()=>this.toggleRawMode(n)},{icon:ze,iconClass:"nav-ctx-edit",label:"Wiki",action:()=>{location.hash=`#/project/${encodeURIComponent(n)}`}},{kind:"divider"},{icon:It,iconClass:"nav-ctx-doc",label:"New Doc",action:()=>this.callbacks.onCreateProjectDoc(n)},{icon:jt,iconClass:"nav-ctx-board",label:"New Board",action:()=>this.callbacks.onCreateProjectBoard(n)},{icon:Wt,iconClass:"nav-ctx-dir",label:"New Directory",action:()=>this.callbacks.onCreateProjectDirectory(n)},{kind:"divider"},{icon:re,iconClass:"nav-ctx-delete",label:"Remove from workspace",action:()=>this.callbacks.onRemoveProject(n,s),danger:!0}])}),d.append(h,p,f),l.append(d,y),this.registerCollapsible(n,r,c,d,!0),d.addEventListener("click",()=>this.toggleCollapsible(n)),l.addEventListener("contextmenu",v=>{v.preventDefault(),v.stopPropagation(),y.click()});const b=Mo(t,this.lastTreesByProject.get(n)??[],e),w=a?b:fn(He(b));if(w.length===0){const v=document.createElement("div");v.className="nav-label nav-empty-copy",v.textContent="No folders found.",r.appendChild(v)}else r.appendChild(this.renderCanonicalNodes(t,w,0,a));return c.append(l,r),c}renderCanonicalNodes(t,e,n,s){const i=document.createElement("div");for(const a of Lo(e)){if(a.kind==="doc"||a.kind==="board"||a.kind==="capability"||a.kind==="file"){i.appendChild(this.renderCanonicalFile(a,n));continue}const r=document.createElement("div");r.className="nav-tree-group",r.style.setProperty("--tree-depth",String(n));const c=document.createElement("div");c.className="nav-tree-children",c.style.setProperty("--tree-depth",String(n+1));const l=document.createElement("button");l.className="nav-tree-row nav-tree-folder"+(a.kind==="docsRoot"?" nav-tree-docs-root":"")+(a.docsContainerRoot?" nav-tree-docs-container":"")+(a.root?"":" nav-tree-scaffold"),l.type="button",l.style.setProperty("--tree-depth",String(n));const d=document.createElement("span");d.className="nav-repo-chevron",d.textContent="›";const h=Io(a);h&&l.classList.add("nav-tree-capability-folder");const p=document.createElement("span");if(p.textContent=a.name,l.appendChild(d),h&&l.insertAdjacentHTML("beforeend",Qe),l.appendChild(p),a.kind==="docsRoot"||a.docsContainerRoot){const f=document.createElement("span");f.className="nav-tree-badge",f.textContent="DOCS",l.appendChild(f)}const u=a.kind==="docsRoot"||a.docsContainerRoot?(a.docsContainerRoot??a.root).id:a.root?`doc:${a.root.id}:${a.contentPath??""}`:`folder:${t.id}:${a.projectPath}`;if(this.registerCollapsible(u,c,r,l,!0),l.addEventListener("click",()=>this.toggleCollapsible(u)),a.kind==="docsRoot"||a.docsContainerRoot){const f=a.docsContainerRoot??a.root;l.addEventListener("contextmenu",y=>{y.preventDefault(),y.stopPropagation(),this.openDirContextMenu(y.clientX,y.clientY,f,"")}),this.enableDirectoryDropTarget(r,f.id,"")}else if(a.root){const f=a.root,y=a.contentPath??"";this.enableDragSource(l,{kind:"dir",rootId:f.id,path:y}),this.enableDirectoryDropTarget(r,f.id,y),r.addEventListener("contextmenu",b=>{b.preventDefault(),b.stopPropagation(),this.openDirContextMenu(b.clientX,b.clientY,f,y)})}else l.addEventListener("contextmenu",f=>{f.preventDefault(),f.stopPropagation(),this.showContextMenu(f.clientX,f.clientY,a.name,[{icon:Wt,iconClass:"nav-ctx-dir",label:"Create docs folder here",action:()=>this.callbacks.onCreateDocsFolder(t.id,a.projectPath)}])});c.appendChild(this.renderCanonicalNodes(t,a.children,n+1,s)),r.append(l,c),i.appendChild(r)}return i}renderCanonicalFile(t,e){if(t.kind==="file"){if(t.root&&t.contentPath&&ge(t.contentPath)){const l=document.createElement("button");return l.className="nav-link nav-tree-row nav-tree-file nav-tree-capability-file",l.type="button",l.style.setProperty("--tree-depth",String(e)),l.insertAdjacentHTML("afterbegin",tn),l.appendChild(document.createTextNode(t.name)),l.addEventListener("click",d=>{d.preventDefault(),this.callbacks.onOpenTextFile(t.root.id,t.contentPath)}),l.addEventListener("contextmenu",d=>{d.preventDefault(),d.stopPropagation(),this.openTextFileContextMenu(d.clientX,d.clientY,t.root,t.contentPath)}),l}const c=document.createElement("div");return c.className="nav-tree-row nav-tree-file",c.style.setProperty("--tree-depth",String(e)),c.textContent=t.name,c}const n=t.root,s=t.contentPath,i=t.kind==="doc"?An(n.id,s):t.kind==="board"?Nn(n.id,st(s)):To(n.id,s),a=t.kind==="doc"&&t.name==="index.md"?"Overview":Ot(t.kind==="board"?st(t.name):t.name),r=this.link(i,a,`${t.kind}:${n.id}:${s}`);return r.classList.add("nav-tree-row",`nav-tree-${t.kind}`),r.style.setProperty("--tree-depth",String(e)),r.insertAdjacentHTML("afterbegin",t.kind==="board"?jt:t.kind==="capability"?Qe:It),this.enableDragSource(r,t.kind==="board"?{kind:"board",rootId:n.id,boardId:st(s)}:t.kind==="capability"?{kind:"capability",rootId:n.id,path:s}:{kind:"doc",rootId:n.id,path:s}),r.addEventListener("contextmenu",c=>{c.preventDefault(),c.stopPropagation(),t.kind==="board"?this.openBoardContextMenu(c.clientX,c.clientY,n,st(s)):t.kind==="doc"&&this.openDocContextMenu(c.clientX,c.clientY,n,s)}),r}renderBrowseNode(t,e,n){if(e.type==="file"){const p=document.createElement("div");return p.className="nav-browse-file",p.textContent=e.name,p}if(e.name==="docs"){const p=t.docsRoots.find(u=>u.displayPath===e.path||u.displayPath.endsWith("/"+e.path));if(p){const u=n.get(p.id)??[];return this.docsRootSection(p,u)}}const i=Ps(e),a=`browse:${t.id}:${e.path}`,r=document.createElement("div");r.className=i?"nav-subgroup nav-collapsible-dir":"nav-subgroup nav-browse-dir";const c=document.createElement("div");c.className="nav-dir-body";const l=document.createElement("button");l.className=i?"nav-dir-toggle nav-dir-project":"nav-browse-dir-toggle",l.type="button";const d=document.createElement("span");d.className="nav-repo-chevron",d.textContent="›";const h=document.createElement("span");if(h.textContent=e.name,l.append(d,h),l.addEventListener("click",()=>this.toggleCollapsible(a)),i){const p=t.docsRoots.find(u=>u.displayPath.startsWith(e.path+"/")||u.displayPath===e.path);p&&l.addEventListener("contextmenu",u=>{u.preventDefault(),u.stopPropagation(),this.openDirContextMenu(u.clientX,u.clientY,p,"")})}else l.addEventListener("contextmenu",p=>{p.preventDefault(),p.stopPropagation(),this.showContextMenu(p.clientX,p.clientY,e.name,[{icon:Wt,iconClass:"nav-ctx-dir",label:"Create /docs/",action:()=>this.callbacks.onCreateDocsFolder(t.id,e.path)}])});for(const p of e.children)p.type==="dir"&&c.appendChild(this.renderBrowseNode(t,p,n));return this.registerCollapsible(a,c,r,l,!0),r.append(l,c),r}renderPathNodes(t,e,n,s=""){const i=document.createElement("div");for(const a of t)if(a.kind==="root")i.appendChild(this.docsRootSection(a.root,e.get(a.root.id)??[]));else{const r=s?`${s}/${a.segment}`:a.segment,c=`pathseg:${n}:${r}`,l=this.renderPathNodes(a.children,e,n,r);l.classList.add("nav-dir-body");const d=document.createElement("div");d.className="nav-subgroup nav-collapsible-dir";const h=$s(a),{row:p,toggle:u}=this.createDirectoryRow(a.segment,`#/project/${encodeURIComponent(n)}`,`${a.segment} wiki`,()=>this.toggleCollapsible(c),!0);h&&d.addEventListener("contextmenu",f=>{f.preventDefault(),f.stopPropagation(),this.openDirContextMenu(f.clientX,f.clientY,h,"")}),this.registerCollapsible(c,l,d,u,!0),d.append(p,l),i.appendChild(d)}return i}docsRootSection(t,e){const n=document.createElement("div");n.className="nav-subgroup nav-docs-root";const s=t.displayPath.split("/").pop()??t.displayPath;if(s.toLowerCase()!=="docs"){const a=document.createElement("div");a.className="nav-root-path-label",a.textContent=s,n.appendChild(a),a.addEventListener("contextmenu",r=>{r.preventDefault(),r.stopPropagation(),this.openDirContextMenu(r.clientX,r.clientY,t,"")})}return n.addEventListener("contextmenu",a=>{var r;(r=a.target)!=null&&r.closest(".nav-link, .nav-dir-toggle")||(a.preventDefault(),a.stopPropagation(),this.openDirContextMenu(a.clientX,a.clientY,t,""))}),this.enableDirectoryDropTarget(n,t.id,""),n.appendChild(this.docsNodes(t,wo(e),"",e)),n}createDirectoryRow(t,e,n,s,i=!1){const a=document.createElement("div");a.className="nav-dir-header-row";const r=document.createElement("button");r.className=i?"nav-dir-toggle nav-dir-project":"nav-dir-toggle nav-dir-docs",r.type="button";const c=document.createElement("span");c.className="nav-repo-chevron",c.innerHTML='<svg viewBox="0 0 16 16" width="10" height="10" fill="currentColor"><path d="M6 4l4 4-4 4"/></svg>';const l=document.createElement("span");l.textContent=t,r.append(c,l),r.addEventListener("click",s);const d=document.createElement("a");return d.className="nav-repo-wiki-link nav-dir-wiki-link",d.href=e,d.title=n,d.innerHTML='<svg viewBox="0 0 14 14" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="2" y="2" width="10" height="10" rx="2"/><path d="M5 5h4M5 7h4M5 9h2"/></svg>',d.addEventListener("click",h=>h.stopPropagation()),this.links.set(e,d),a.append(r,d),{row:a,toggle:r}}docsNodes(t,e,n,s){const i=document.createElement("div"),a=Ls(e),r=Co(s,n),c=[...a.map(l=>({kind:l.type==="file"&&ge(l.path)?"file":"doc",node:l})),...r.map(l=>({kind:"board",name:Ot(st(l.path).split("/").pop()??st(l.path)),boardId:st(l.path)}))].sort((l,d)=>{const h=l.kind==="doc"&&l.node.type==="file"&&l.node.name==="index.md",p=d.kind==="doc"&&d.node.type==="file"&&d.node.name==="index.md";if(h!==p)return h?-1:1;const u=(l.kind==="doc"||l.kind==="file")&&l.node.type==="file"&&mn(l.node.name),f=(d.kind==="doc"||d.kind==="file")&&d.node.type==="file"&&mn(d.node.name);if(u!==f)return u?-1:1;const y=(l.kind==="doc"||l.kind==="file")&&l.node.type==="dir",b=(d.kind==="doc"||d.kind==="file")&&d.node.type==="dir";if(y!==b)return y?-1:1;const w=l.kind==="board"?l.name:l.node.name,v=d.kind==="board"?d.name:d.node.name;return w.localeCompare(v)});for(const l of c)if(l.kind==="board"){const d=document.createElement("a");d.className="nav-link nav-link-board",d.href=Nn(t.id,l.boardId),d.insertAdjacentHTML("afterbegin",jt),d.appendChild(document.createTextNode(l.name));const h=`board:${t.id}:${l.boardId}`;this.links.set(h,d),this.links.set(d.href,d),this.enableDragSource(d,{kind:"board",rootId:t.id,boardId:l.boardId}),d.addEventListener("contextmenu",p=>{p.preventDefault(),p.stopPropagation(),this.openBoardContextMenu(p.clientX,p.clientY,t,l.boardId)}),i.appendChild(d)}else{const{node:d}=l;if(d.type==="file"){if(l.kind==="file"){const u=document.createElement("button");u.className="nav-link nav-tree-file nav-tree-capability-file",u.type="button",u.insertAdjacentHTML("afterbegin",tn),u.appendChild(document.createTextNode(d.name)),u.addEventListener("click",()=>this.callbacks.onOpenTextFile(t.id,d.path)),u.addEventListener("contextmenu",f=>{f.preventDefault(),f.stopPropagation(),this.openTextFileContextMenu(f.clientX,f.clientY,t,d.path)}),i.appendChild(u);continue}if(!d.name.endsWith(".md"))continue;const h=d.name==="index.md"?"Overview":Ot(d.name),p=this.link(An(t.id,d.path),h,`doc:${t.id}:${d.path}`);p.insertAdjacentHTML("afterbegin",It),this.enableDragSource(p,{kind:"doc",rootId:t.id,path:d.path}),p.addEventListener("contextmenu",u=>{u.preventDefault(),u.stopPropagation(),this.openDocContextMenu(u.clientX,u.clientY,t,d.path)}),i.appendChild(p)}else{const h=`doc:${t.id}:${d.path}`,p=this.docsNodes(t,d.children,d.path,s);p.classList.add("nav-dir-body");const u=document.createElement("div");u.className="nav-subgroup nav-collapsible-dir";const{row:f,toggle:y}=this.createDirectoryRow(Ot(d.name),`#/root/${encodeURIComponent(t.id)}/directory/${encodeURIComponent(d.path)}`,`${d.name} wiki`,b=>{b.button===0&&this.toggleCollapsible(h)},!1);this.enableDragSource(y,{kind:"dir",rootId:t.id,path:d.path}),u.addEventListener("contextmenu",b=>{b.preventDefault(),b.stopPropagation(),this.openDirContextMenu(b.clientX,b.clientY,t,d.path)}),this.enableDirectoryDropTarget(u,t.id,d.path),this.registerCollapsible(h,p,u,y,!0),u.append(f,p),i.appendChild(u)}}return i}enableDragSource(t,e){t.draggable=!0,t.addEventListener("dragstart",n=>{var s,i;this.closeContextMenu(),this.draggedItem=e,t.classList.add("nav-dragging"),(s=n.dataTransfer)==null||s.setData("application/x-docs-nav-item",JSON.stringify(e)),(i=n.dataTransfer)==null||i.setData("text/plain",Po(e)),n.dataTransfer&&(n.dataTransfer.effectAllowed="move")}),t.addEventListener("dragend",()=>{t.classList.remove("nav-dragging"),this.draggedItem=void 0,this.clearDropTargets()})}enableDirectoryDropTarget(t,e,n){t.addEventListener("dragover",s=>{const i=this.currentDragItem(s);!i||!this.canDropItem(i,e,n)||(s.preventDefault(),s.stopPropagation(),s.dataTransfer&&(s.dataTransfer.dropEffect="move"),t.classList.add("nav-drop-target"),this.scheduleDropExpand(t))}),t.addEventListener("dragleave",s=>{t.contains(s.relatedTarget)||(t.classList.remove("nav-drop-target"),this.clearDropExpand(t))}),t.addEventListener("drop",s=>{const i=this.currentDragItem(s);!i||!this.canDropItem(i,e,n)||(s.preventDefault(),s.stopPropagation(),this.clearDropExpand(t),this.clearDropTargets(),this.moveDraggedItem(i,n))})}scheduleDropExpand(t){this.dropExpandTarget===t||!t.dataset.collapsibleKey||(this.clearDropExpand(),this.dropExpandTarget=t,this.dropExpandTimer=window.setTimeout(()=>{const e=t.dataset.collapsibleKey;e&&this.applyCollapsed(e,!1),t.classList.add("nav-drop-auto-expanded"),this.dropExpandTimer=void 0},650))}clearDropExpand(t){var e;t&&this.dropExpandTarget!==t||(this.dropExpandTimer!==void 0&&window.clearTimeout(this.dropExpandTimer),this.dropExpandTimer=void 0,(e=this.dropExpandTarget)==null||e.classList.remove("nav-drop-auto-expanded"),this.dropExpandTarget=void 0)}currentDragItem(t){var n;if(this.draggedItem)return this.draggedItem;const e=(n=t.dataTransfer)==null?void 0:n.getData("application/x-docs-nav-item");if(e)try{const s=JSON.parse(e);if(s&&(s.kind==="doc"||s.kind==="capability"||s.kind==="board"||s.kind==="dir")&&typeof s.rootId=="string")return s}catch{}}canDropItem(t,e,n){if(t.rootId!==e)return!1;const s=Tt(n);if(t.kind==="doc")return Bt(t.path)!==s;if(t.kind==="capability")return s==="capabilities"||s.startsWith("capabilities/")&&Bt(t.path)!==s;if(t.kind==="board")return Bt(t.boardId)!==s;const i=Tt(t.path);return!i||i===s||Bt(i)===s?!1:!s.startsWith(`${i}/`)}moveDraggedItem(t,e){const n=Tt(e);t.kind==="doc"||t.kind==="capability"?this.callbacks.onMoveDoc(t.rootId,t.path,n):t.kind==="board"?this.callbacks.onMoveBoard(t.rootId,t.boardId,n):this.callbacks.onMoveDirectory(t.rootId,t.path,n)}clearDropTargets(){this.clearDropExpand(),this.element.querySelectorAll(".nav-drop-target").forEach(t=>{t.classList.remove("nav-drop-target")})}startInlineRename(t,e,n){const s=document.createElement("input");s.className="nav-inline-input",s.value=e.replace(/\.md$/,"");const i=t.parentElement;if(!i)return;t.style.display="none",i.insertBefore(s,t.nextSibling),s.focus(),s.select();let a=!1;const r=c=>{if(!a&&(a=!0,s.remove(),t.style.display="",c)){const l=s.value.trim();l&&l!==e.replace(/\.md$/,"")&&n(l)}};s.addEventListener("keydown",c=>{c.stopPropagation(),c.key==="Enter"&&(c.preventDefault(),r(!0)),c.key==="Escape"&&(c.preventDefault(),r(!1))}),s.addEventListener("blur",()=>r(!0))}startInlineCreate(t,e,n){const s=document.createElement("input");s.className="nav-inline-input",s.placeholder=e,t.insertBefore(s,t.firstChild),s.focus();let i=!1;const a=r=>{if(!i&&(i=!0,s.remove(),r)){const c=s.value.trim();c&&n(c)}};s.addEventListener("keydown",r=>{r.stopPropagation(),r.key==="Enter"&&(r.preventDefault(),a(!0)),r.key==="Escape"&&(r.preventDefault(),a(!1))}),s.addEventListener("blur",()=>a(!0))}registerCollapsible(t,e,n,s,i){this.collapsibles.set(t,{body:e,group:n,btn:s}),n.dataset.collapsibleKey=t,this.applyCollapsed(t,this.collapsedState.get(t)??i)}applyCollapsed(t,e){const n=this.collapsibles.get(t);n&&(this.collapsedState.set(t,e),n.body.hidden=e,n.group.classList.toggle("collapsed",e),n.btn.setAttribute("aria-expanded",String(!e)))}toggleCollapsible(t){const e=this.collapsibles.get(t);e&&this.applyCollapsed(t,!e.body.hidden)}openDirContextMenu(t,e,n,s){const i=s?Ot(s.split("/").pop()??s):n.displayPath.split("/").pop()??n.displayPath,a=[{icon:Wt,iconClass:"nav-ctx-dir",label:"New Directory",action:()=>this.callbacks.onCreateDirectory(n.id,s)},{icon:jt,iconClass:"nav-ctx-board",label:"New Board",action:()=>this.callbacks.onCreateBoard(n.id,s)},{icon:It,iconClass:"nav-ctx-doc",label:"New Doc",action:()=>this.callbacks.onCreateDoc(n.id,s)},{icon:Qe,iconClass:"nav-ctx-cap",label:"New Capability",action:()=>this.callbacks.onCreateCapability(n.id,s)},{icon:Te,iconClass:"nav-ctx-export",label:"Export",children:[{icon:Te,iconClass:"nav-ctx-export",label:"Export to PDF",action:()=>this.callbacks.onExportDirectory(n.id,s)}]}];s&&a.push({icon:Se,iconClass:"nav-ctx-rename",label:"Rename",action:()=>this.callbacks.onRenameDirectory(n.id,s)},{icon:re,iconClass:"nav-ctx-delete",label:"Delete",action:()=>this.callbacks.onDeleteDirectory(n.id,s)}),this.showContextMenu(t,e,i,a)}openEmptyProjectContextMenu(t,e,n,s){this.showContextMenu(t,e,s,[{icon:Wt,iconClass:"nav-ctx-dir",label:"New Directory",action:()=>this.callbacks.onCreateProjectDirectory(n)},{icon:jt,iconClass:"nav-ctx-board",label:"New Board",action:()=>this.callbacks.onCreateProjectBoard(n)},{icon:It,iconClass:"nav-ctx-doc",label:"New Doc",action:()=>this.callbacks.onCreateProjectDoc(n)}])}openDocContextMenu(t,e,n,s){const i=s.split("/").pop()??s;this.showContextMenu(t,e,i,[{icon:It,iconClass:"nav-ctx-doc",label:"Open",action:()=>this.callbacks.onOpenDoc(n.id,s)},{icon:ze,iconClass:"nav-ctx-edit",label:"Edit",action:()=>this.callbacks.onEditDoc(n.id,s)},{icon:Te,iconClass:"nav-ctx-export",label:"Export",children:[{icon:Te,iconClass:"nav-ctx-export",label:"Export to PDF",action:()=>this.callbacks.onExportDoc(n.id,s)}]},{kind:"divider"},{icon:Se,iconClass:"nav-ctx-rename",label:"Rename",action:()=>this.callbacks.onRenameDoc(n.id,s)},{icon:re,iconClass:"nav-ctx-delete",label:"Delete",action:()=>this.callbacks.onDeleteDoc(n.id,s),danger:!0}])}openTextFileContextMenu(t,e,n,s){const i=s.split("/").pop()??s;this.showContextMenu(t,e,i,[{icon:tn,iconClass:"nav-ctx-doc",label:"Open",action:()=>this.callbacks.onOpenTextFile(n.id,s)},{icon:ze,iconClass:"nav-ctx-edit",label:"Edit",action:()=>this.callbacks.onOpenTextFile(n.id,s)},{kind:"divider"},{icon:Se,iconClass:"nav-ctx-rename",label:"Rename",action:()=>this.callbacks.onRenameDoc(n.id,s)},{icon:re,iconClass:"nav-ctx-delete",label:"Delete",action:()=>this.callbacks.onDeleteDoc(n.id,s),danger:!0}])}openBoardContextMenu(t,e,n,s){const i=Ot(s.split("/").pop()??s);this.showContextMenu(t,e,i,[{icon:jt,iconClass:"nav-ctx-board",label:"Open",action:()=>this.callbacks.onOpenBoard(n.id,s)},{kind:"divider"},{icon:Se,iconClass:"nav-ctx-rename",label:"Rename",action:()=>this.callbacks.onRenameBoard(n.id,s)},{icon:re,iconClass:"nav-ctx-delete",label:"Delete",action:()=>this.callbacks.onDeleteBoard(n.id,s),danger:!0}])}showContextMenu(t,e,n,s){var c;this.closeContextMenu();const i=document.createElement("div");i.className="nav-context-menu",i.addEventListener("pointerdown",l=>l.stopPropagation());const a=document.createElement("div");a.className="nav-context-label",a.textContent=n,i.appendChild(a);const r=document.createElement("div");r.className="nav-context-divider",i.appendChild(r);for(const l of s){if(l.kind==="divider"){const f=document.createElement("div");f.className="nav-context-divider",i.appendChild(f);continue}const d=document.createElement("button"),h=!!((c=l.children)!=null&&c.length);d.className="nav-context-item"+(l.danger?" nav-context-item-danger":"")+(h?" nav-context-item-parent":""),d.type="button";const p=document.createElement("span");p.className=`nav-ctx-icon ${l.iconClass}`,p.innerHTML=l.icon;const u=document.createElement("span");if(u.textContent=l.label,d.append(p,u),h){const f=document.createElement("span");f.className="nav-context-chevron",f.innerHTML=xo,d.appendChild(f);const y=document.createElement("div");y.className="nav-context-submenu",y.addEventListener("pointerdown",b=>b.stopPropagation());for(const b of l.children??[]){const w=document.createElement("button");w.className="nav-context-item"+(b.danger?" nav-context-item-danger":""),w.type="button";const v=document.createElement("span");v.className=`nav-ctx-icon ${b.iconClass}`,v.innerHTML=b.icon;const S=document.createElement("span");S.textContent=b.label,w.append(v,S),w.addEventListener("click",()=>{this.closeContextMenu(),b.action()}),y.appendChild(w)}d.appendChild(y)}else if(l.action){const f=l.action;d.addEventListener("click",()=>{this.closeContextMenu(),f()})}i.appendChild(d)}i.style.position="fixed",i.style.left=`${t}px`,i.style.top=`${e}px`,document.body.appendChild(i),this.contextMenu=i,requestAnimationFrame(()=>{if(!this.contextMenu)return;const l=i.getBoundingClientRect();l.right>window.innerWidth&&(i.style.left=`${Math.max(0,t-l.width)}px`),l.bottom>window.innerHeight&&(i.style.top=`${Math.max(0,e-l.height)}px`)})}closeContextMenu(){var t;(t=this.contextMenu)==null||t.remove(),this.contextMenu=void 0}groupLabel(t){const e=document.createElement("div");return e.className="nav-label",e.textContent=t,e}link(t,e,n){const s=document.createElement("a");return s.className="nav-link",s.href=t,s.textContent=e,this.links.set(n,s),this.links.set(t,s),s}}const jt='<svg class="nav-node-icon nav-node-icon-board" viewBox="0 0 16 16" aria-hidden="true"><rect x="1" y="1" width="6" height="6" rx="1"/><rect x="9" y="1" width="6" height="6" rx="1"/><rect x="1" y="9" width="6" height="6" rx="1"/><rect x="9" y="9" width="6" height="6" rx="1"/></svg>',Qe='<svg class="nav-node-icon nav-node-icon-capability" viewBox="0 0 16 16" aria-hidden="true"><path d="M8 1l2 4.5 4.5 0.7-3.3 3.1 0.8 4.7-4-2.1-4 2.1 0.8-4.7L1.5 6.2l4.5-0.7z"/></svg>',It='<svg class="nav-node-icon nav-node-icon-doc" viewBox="0 0 16 16" aria-hidden="true"><path d="M3 1.5h6.5l3 3V14.5H3z"/><path d="M9.5 1.5V4.5h3" stroke="none"/><line x1="5" y1="7" x2="11" y2="7" stroke="var(--bg-canvas)" stroke-width="0.8"/><line x1="5" y1="9.5" x2="11" y2="9.5" stroke="var(--bg-canvas)" stroke-width="0.8"/><line x1="5" y1="12" x2="9" y2="12" stroke="var(--bg-canvas)" stroke-width="0.8"/></svg>',tn='<svg class="nav-node-icon nav-node-icon-doc" viewBox="0 0 16 16" aria-hidden="true"><path d="M3 1.5h6.5l3 3V14.5H3z"/><path d="M9.5 1.5V4.5h3" stroke="none"/><line x1="5" y1="7" x2="11" y2="7" stroke="var(--bg-canvas)" stroke-width="0.8"/><line x1="5" y1="9.5" x2="11" y2="9.5" stroke="var(--bg-canvas)" stroke-width="0.8"/></svg>',Wt='<svg class="nav-ctx-svg" viewBox="0 0 16 16" aria-hidden="true" fill="none" stroke="currentColor" stroke-width="1.45" stroke-linecap="round" stroke-linejoin="round"><path d="M2 4.5h4l1.4 1.6H14v6.4a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1z"/><path d="M2 4.5v-1a1 1 0 0 1 1-1h3l1.4 2"/></svg>',ze='<svg class="nav-ctx-svg" viewBox="0 0 16 16" aria-hidden="true" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M11 2l3 3-8 8H3v-3z"/></svg>',Se=ze,Te='<svg class="nav-ctx-svg" viewBox="0 0 16 16" aria-hidden="true" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M8 10.5V2.5M8 2.5L5.5 5M8 2.5L10.5 5M2.5 11.5V13a1 1 0 0 0 1 1h9a1 1 0 0 0 1-1v-1.5"/></svg>',xo='<svg class="nav-ctx-svg nav-ctx-chevron-svg" viewBox="0 0 16 16" aria-hidden="true" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"><path d="M6 3.5L10.5 8 6 12.5"/></svg>',re='<svg class="nav-ctx-svg" viewBox="0 0 16 16" aria-hidden="true" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M2 4h12M5 4V2h6v2M6 7v5M10 7v5M3 4l1 9a1 1 0 001 1h6a1 1 0 001-1l1-9"/></svg>';function Ls(o){return o.filter(t=>t.type==="file"?t.name.endsWith(".md")||ge(t.path):!bo.has(t.name)).map(t=>t.type==="file"?t:{...t,children:Ls(t.children)})}function wo(o){const t=o.find(e=>e.type==="dir"&&e.name.toLowerCase()==="docs");return!t||t.type!=="dir"?o:o.filter(e=>e!==t).concat(t.children)}function Co(o,t){const e=t?`${t}/`:"";return ko(o).filter(n=>e?n.path.startsWith(e)?!n.path.slice(e.length).includes("/"):!1:!n.path.includes("/"))}function ko(o){const t=[],e=n=>{for(const s of n)s.type==="file"?s.name.endsWith(".board.json")&&t.push(s):e(s.children)};return e(o),t}function An(o,t){return`#/root/${encodeURIComponent(o)}/docs/${encodeURIComponent(t)}`}function Eo(o){return`#/root/${encodeURIComponent(o)}/boards`}function Nn(o,t){return`#/root/${encodeURIComponent(o)}/boards/${encodeURIComponent(t)}`}function So(o){return`#/root/${encodeURIComponent(o)}/capabilities`}function To(o,t){return`#/root/${encodeURIComponent(o)}/capabilities/${encodeURIComponent(Bo(t))}`}function Bo(o){return o.replace(/^capabilities\//,"")}function Mo(o,t,e){const n=new Map,s=[],i=c=>{const l=Tt(c),d=n.get(l);if(d)return d;const h=Bt(l),p={id:`folder:${o.id}:${l}`,kind:"folder",name:l.split("/").pop()??o.label,projectPath:l,children:[]};return n.set(l,p),l&&h?i(h).children.push(p):s.push(p),p},a=c=>{for(const l of c)if(l.type==="dir")i(l.path),a(l.children);else{const d={id:`file:${o.id}:${l.path}`,kind:"file",name:l.name,projectPath:l.path,children:[]};n.set(l.path,d);const h=Bt(l.path);h?i(h).children.push(d):s.push(d)}};a(t);for(const c of o.docsRoots){const l=Tt(c.displayPath),d=i(l);d.kind="docsRoot",d.id=`root:${c.id}`,d.root=c,d.contentPath="";const h=p=>{for(const u of p){const f=[l,u.path].filter(Boolean).join("/");if(u.type==="dir"){const E=i(f);E.kind!=="docsRoot"&&(E.root=c,E.contentPath=u.path),h(u.children);continue}const y=u.name.endsWith(".board.json"),b=Is(u.path),w=ge(u.path);if(!u.name.endsWith(".md")&&!y&&!w)continue;const v=Bt(f),S=n.get(f),x=S??{id:"",kind:"file",name:u.name,projectPath:f,children:[]};x.id=`${y?"board":b?"capability":w?"file":"doc"}:${c.id}:${u.path}`,x.kind=y?"board":b?"capability":w?"file":"doc",x.root=c,x.contentPath=u.path,S||(n.set(f,x),v?i(v).children.push(x):s.push(x))}};h(e.get(c.id)??[])}const r=(c,l)=>{const d=c.kind==="docsRoot"?c.root:c.root??l;if(d&&(c.kind==="folder"||c.kind==="file")&&!c.contentPath){c.root=d;const h=Tt(d.displayPath);c.contentPath=c.projectPath.slice(h.length).replace(/^\//,"")}for(const h of c.children)r(h,d)};for(const c of s)r(c);return s}function Lo(o){return[...o].sort((t,e)=>{const n=s=>s.kind==="doc"&&s.name==="index.md"?0:(s.kind==="doc"||s.kind==="file")&&mn(s.name)?1:s.kind==="doc"?2:s.kind==="capability"?3:s.kind==="board"?4:s.kind==="folder"&&s.root&&!s.docsContainerRoot?5:s.kind==="folder"&&s.docsContainerRoot?6:s.kind==="folder"&&!s.root?7:s.kind==="docsRoot"?8:9;return n(t)-n(e)||t.name.localeCompare(e.name,void 0,{sensitivity:"accent"})})}function mn(o){return/^readme\.(md|txt)$/i.test(o)}function He(o,t,e=!1){const n=[];for(const s of o){if(s.kind==="docsRoot"){n.push({...s,children:He(s.children,!1,!0)});continue}if(e){if(s.kind==="file"){ge(s.contentPath??"")&&n.push(s);continue}if(s.kind==="folder"){const i=He(s.children,!1,!0);(s.name!=="assets"||i.length>0)&&n.push({...s,children:i})}else n.push(s);continue}if(s.kind==="folder"){const i=He(s.children);i.length>0&&n.push({...s,children:i})}}return n}function fn(o){var e;const t=[];for(const n of o){if(n.kind==="docsRoot"){t.push(...fn(n.children));continue}if(n.kind!=="folder"){t.push(n);continue}const s=(e=n.children.find(i=>i.kind==="docsRoot"))==null?void 0:e.root;t.push({...n,docsContainerRoot:s,children:fn(n.children)})}return t}function Ot(o){const t=o.replace(/\.md$/,"").replace(/[-_]/g," ");return t.charAt(0).toUpperCase()+t.slice(1)}function Is(o){if(!o.startsWith("capabilities/")||!o.endsWith(".md"))return!1;const t=o.slice(13);return t.includes("/")?t.endsWith("/index.md"):!0}function ge(o){return!o.startsWith("capabilities/")||o.endsWith(".board.json")?!1:!Is(o)}function Io(o){var t;return o.kind!=="folder"||!((t=o.contentPath)!=null&&t.startsWith("capabilities/"))?null:o.children.find(e=>e.kind==="capability"&&Bt(e.contentPath??"")===o.contentPath)??null}function Ps(o){if(o.type==="file")return!1;for(const t of o.children)if(t.type==="dir"&&t.name==="docs"||t.type==="dir"&&Ps(t))return!0;return!1}function Tt(o){return o.replace(/^\/+|\/+$/g,"")}function Bt(o){const t=Tt(o),e=t.lastIndexOf("/");return e===-1?"":t.slice(0,e)}function Po(o){return o.kind==="doc"||o.kind==="capability"?o.path:o.kind==="board"?o.boardId:o.path}function $s(o){if(o.kind==="root")return o.root;for(const t of o.children){const e=$s(t);if(e)return e}return null}function Zt(o,t={}){const{frontmatter:e,body:n}=$o(o);try{const s=Rs(n.split(`
|
|
2
|
+
`),t);return{frontmatter:e,html:s}}catch(s){return console.error("Markdown render failed",s),{frontmatter:e,html:`<div class="md-error"><strong>Could not render this document.</strong><pre>${Jt(String(s))}</pre></div>`}}}function $o(o){const t={};if(!o.startsWith("---"))return{frontmatter:t,body:o};const e=o.indexOf(`
|
|
3
|
+
---`,3);if(e===-1)return{frontmatter:t,body:o};const n=o.slice(3,e).trim();for(const i of n.split(`
|
|
4
|
+
`)){const a=i.indexOf(":");a!==-1&&(t[i.slice(0,a).trim()]=i.slice(a+1).trim())}const s=o.slice(e+4).replace(/^\n+/,"");return{frontmatter:t,body:s}}function Rs(o,t){const e=[];let n=0,s=0;const i=o.length*4+1e3;for(;n<o.length;){if(++s>i)throw new Error(`renderBlocks exceeded ${i} iterations at line ${n} — aborting to avoid an infinite loop`);const a=o[n];if(a.trim()===""){n++;continue}const r=a.match(/^(`{3,})\s*(\w+)?\s*$/);if(r){const d=r[1].length,h=(r[2]??"").toLowerCase(),p=new RegExp("^`{"+d+",}\\s*$"),u=[];for(n++;n<o.length&&!p.test(o[n]);)u.push(o[n]),n++;n++,h==="board"?e.push(Ao(As(u.join(`
|
|
5
|
+
`)))):e.push(`<pre class="code-block"><code${h?` class="language-${h}"`:""}>${Jt(u.join(`
|
|
6
|
+
`))}</code></pre>`);continue}const c=a.match(/^(#{1,6})\s+(.*)$/);if(c){const d=c[1].length,h=zt(c[2].trim(),t),p=zo(c[2]);e.push(`<h${d} id="${p}">${h}</h${d}>`),n++;continue}if(/^(-{3,}|\*{3,}|_{3,})\s*$/.test(a)){e.push("<hr />"),n++;continue}if(/^>\s?/.test(a)){const d=[];for(;n<o.length&&/^>\s?/.test(o[n]);)d.push(o[n].replace(/^>\s?/,"")),n++;e.push(`<blockquote>${Rs(d,t)}</blockquote>`);continue}if(a.includes("|")&&n+1<o.length&&Ro(o[n+1])){const d=[];for(;n<o.length&&o[n].includes("|")&&o[n].trim()!=="";)d.push(o[n]),n++;e.push(Do(d,t));continue}if(Vt(a)){const d=[];for(;n<o.length&&(Vt(o[n])||/^\s+\S/.test(o[n])||o[n].trim()==="");){if(o[n].trim()===""){const h=o[n+1];if(h===void 0||!Vt(h)&&!/^\s+\S/.test(h))break}d.push(o[n]),n++}e.push(Ds(d,t));continue}const l=[o[n]];for(n++;n<o.length&&o[n].trim()!==""&&!/^`{3,}/.test(o[n])&&!/^#{1,6}\s/.test(o[n])&&!/^>\s?/.test(o[n])&&!Vt(o[n])&&!/^(-{3,}|\*{3,}|_{3,})\s*$/.test(o[n]);)l.push(o[n]),n++;e.push(`<p>${zt(l.join(" ").trim(),t)}</p>`)}return e.join(`
|
|
7
|
+
`)}function Vt(o){return/^\s*([-*+]|\d+\.)\s+/.test(o)}function Ds(o,t){const e=o.filter(l=>Vt(l)).map(l=>l.match(/^\s*/)[0].length);if(e.length===0)return zt(o.join(" ").trim(),t);const n=Math.min(...e),s=[];let i=!1,a=null;for(const l of o){const d=l.match(/^\s*/)[0].length,h=l.match(/^\s*([-*+]|\d+\.)\s+(.*)$/);if(h&&d===n){i=/\d+\./.test(h[1]);let p=h[2],u=null;const f=p.match(/^\[([ xX])\]\s+(.*)$/);f&&(u=f[1].toLowerCase()==="x",p=f[2]),a={ordered:i,content:[p],checked:u},s.push(a)}else a&&a.content.push(l.slice(n))}const r=i?"ol":"ul",c=s.map(l=>{const d=l.content[0],h=l.content.slice(1);let p=zt(d,t);const u=h.filter(f=>f.trim()!=="");return u.some(f=>Vt(f))?p+=Ds(h,t):u.length&&(p+=" "+zt(u.join(" ").trim(),t)),l.checked!==null?`<li class="task">${`<input type="checkbox" disabled${l.checked?" checked":""} /> `}${p}</li>`:`<li>${p}</li>`}).join("");return`<${r}>${c}</${r}>`}function Ro(o){return/^\s*\|?\s*:?-{1,}:?\s*(\|\s*:?-{1,}:?\s*)*\|?\s*$/.test(o)}function en(o){return o.trim().replace(/^\|/,"").replace(/\|$/,"").split("|").map(t=>t.trim())}function Do(o,t){const e=en(o[0]),n=en(o[1]).map(r=>{const c=r.startsWith(":"),l=r.endsWith(":");return c&&l?"center":l?"right":c?"left":""}),s=o.slice(2).map(en),i=e.map((r,c)=>`<th${n[c]?` style="text-align:${n[c]}"`:""}>${zt(r,t)}</th>`).join(""),a=s.map(r=>`<tr>${r.map((c,l)=>`<td${n[l]?` style="text-align:${n[l]}"`:""}>${zt(c,t)}</td>`).join("")}</tr>`).join("");return`<div class="markdown-table-scroll"><table><thead><tr>${i}</tr></thead><tbody>${a}</tbody></table></div>`}function As(o){const t={};for(const n of o.split(`
|
|
8
|
+
`)){const s=n.replace(/#.*$/,"").trim();if(!s)continue;const i=s.indexOf(":");i!==-1&&(t[s.slice(0,i).trim()]=s.slice(i+1).trim())}let e=null;if(t.region){const n=t.region.split(",").map(s=>parseFloat(s.trim()));n.length===4&&n.every(s=>Number.isFinite(s))&&(e=[n[0],n[1],n[2],n[3]])}return{src:t.src??"",region:e,height:t.height?Math.max(120,parseInt(t.height,10)||360):360,title:t.title??null}}function Ao(o){const t=o.region?o.region.join(","):"";return`<figure class="board-embed" data-src="${At(o.src)}" data-region="${t}" data-height="${o.height}" data-title="${At(o.title??"")}"></figure>`}function zt(o,t){let e=o;const n=[];e=e.replace(/\\([\\`*_{}\[\]()#+\-.!|])/g,(a,r)=>(n.push(r),`${n.length-1}`));const s=[];e=e.replace(/`([^`]+)`/g,(a,r)=>(s.push(`<code>${Jt(Be(r,n))}</code>`),`\0${s.length-1}\0`));const i=[];return e=e.replace(/!\[([^\]]*)\]\(([^)\s]+)\)/g,(a,r,c)=>{const l=Be(c,n),d=Cn(l,t),h=No(l,t),p=Be(r,n),u=d===l?"":` data-md-src="${At(l)}"`;return i.push(`<img src="${At(h)}" alt="${At(p)}" loading="lazy"${u} />`),`${i.length-1}`}),e=e.replace(/\[([^\]]+)\]\(([^)\s]+)\)/g,(a,r,c)=>{const l=Be(c,n),d=Fo(l,t),p=/^(https?:|mailto:|tel:)/.test(l)?' target="_blank" rel="noopener noreferrer"':"",u=d===l?"":` data-md-href="${At(l)}"`;return i.push(`<a href="${At(d)}"${p}${u}>${Fn(r,n,s)}</a>`),`${i.length-1}`}),e=Fn(e,n,s),e=e.replace(/\u0002(\d+)\u0002/g,(a,r)=>i[Number(r)]??""),e}function Fn(o,t,e){let n=Jt(o);return n=n.replace(/\*\*([\s\S]+?)\*\*/g,"<strong>$1</strong>"),n=n.replace(/__([\s\S]+?)__/g,"<strong>$1</strong>"),n=n.replace(/(^|[^*])\*([^*\s][^*]*)\*/g,"$1<em>$2</em>"),n=n.replace(/(^|[^_])_([^_\s][^_]*)_/g,"$1<em>$2</em>"),n=n.replace(/\u0000(\d+)\u0000/g,(s,i)=>e[Number(i)]??""),n=n.replace(/\u0001(\d+)\u0001/g,(s,i)=>Jt(t[Number(i)]??"")),n}function Be(o,t){return o.replace(/\u0001(\d+)\u0001/g,(e,n)=>t[Number(n)]??"")}function No(o,t){if(/^(https?:|data:)/.test(o)||!t.rootId||!t.docPath)return o;const e=Cn(o,t);return e?k.assetUrl(t.rootId,e):o}function Fo(o,t){if(/^(https?:|mailto:|tel:|#|data:)/.test(o)||!t.rootId||!t.docPath)return o;const e=Cn(o,t);return e?e.endsWith(".md")?`#/root/${encodeURIComponent(t.rootId)}/docs/${encodeURIComponent(e)}`:k.assetUrl(t.rootId,e):o}function Cn(o,t){return t.docPath?lo(t.docPath,o):o}function Jt(o){return o.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">")}function At(o){return Jt(o).replace(/"/g,""")}function zo(o){return o.toLowerCase().replace(/[^\w\s-]/g,"").trim().replace(/\s+/g,"-")}class Ns{constructor(t,e,n){m(this,"cache",new Map);m(this,"loading",new Set);m(this,"missing",new Set);m(this,"assetStore");m(this,"onLoaded");m(this,"resolveSrcUrl");this.assetStore=t,this.onLoaded=e,this.resolveSrcUrl=n}get(t){const e=this.cache.get(t);return e||(!this.loading.has(t)&&!this.missing.has(t)&&this.load(t),null)}isMissing(t){return this.missing.has(t)}srcToUrl(t){return this.resolveSrcUrl?this.resolveSrcUrl(t):/^(https?:)?\/\//.test(t)||t.startsWith("/")||t.startsWith("data:")?t:`/__api/asset?path=${encodeURIComponent(t)}`}keyForSrc(t){return this.srcToUrl(t)}getBySrc(t){const e=this.srcToUrl(t),n=this.cache.get(e);return n||(!this.loading.has(e)&&!this.missing.has(e)&&this.loadUrl(e),null)}isMissingSrc(t){return this.missing.has(this.srcToUrl(t))}async loadUrl(t){this.loading.add(t);try{const e=await fetch(t);if(!e.ok){this.missing.add(t);return}const n=await e.blob(),s=await createImageBitmap(n);this.cache.set(t,s),this.onLoaded()}catch{this.missing.add(t)}finally{this.loading.delete(t)}}set(t,e){this.cache.set(t,e),this.missing.delete(t)}setBySrc(t,e){this.set(this.srcToUrl(t),e)}async load(t){this.loading.add(t);try{const e=await this.assetStore.get(t);if(!e){this.missing.add(t);return}const n=await createImageBitmap(e.blob);this.cache.set(t,n),this.onLoaded()}catch{this.missing.add(t)}finally{this.loading.delete(t)}}evict(t){const e=this.cache.get(t);e&&e.close(),this.cache.delete(t),this.missing.delete(t)}clear(){for(const t of this.cache.values())t.close();this.cache.clear(),this.missing.clear()}get size(){return this.cache.size}}const Ho="viteboard",jo=1;class Wo{constructor(){m(this,"dbPromise",null)}open(){return this.dbPromise?this.dbPromise:(this.dbPromise=new Promise((t,e)=>{const n=indexedDB.open(Ho,jo);n.onupgradeneeded=()=>{const s=n.result;s.objectStoreNames.contains("boards")||s.createObjectStore("boards",{keyPath:"id"}),s.objectStoreNames.contains("assets")||s.createObjectStore("assets",{keyPath:"id"})},n.onsuccess=()=>t(n.result),n.onerror=()=>e(n.error??new Error("IndexedDB open failed")),n.onblocked=()=>e(new Error("IndexedDB blocked"))}),this.dbPromise)}async put(t,e){const n=await this.open();return new Promise((s,i)=>{const a=n.transaction(t,"readwrite");a.objectStore(t).put(e),a.oncomplete=()=>s(),a.onerror=()=>i(a.error??new Error("IndexedDB write failed"))})}async get(t,e){const n=await this.open();return new Promise((s,i)=>{const r=n.transaction(t,"readonly").objectStore(t).get(e);r.onsuccess=()=>s(r.result),r.onerror=()=>i(r.error??new Error("IndexedDB read failed"))})}async delete(t,e){const n=await this.open();return new Promise((s,i)=>{const a=n.transaction(t,"readwrite");a.objectStore(t).delete(e),a.oncomplete=()=>s(),a.onerror=()=>i(a.error??new Error("IndexedDB delete failed"))})}async getAllKeys(t){const e=await this.open();return new Promise((n,s)=>{const a=e.transaction(t,"readonly").objectStore(t).getAllKeys();a.onsuccess=()=>n(a.result),a.onerror=()=>s(a.error??new Error("IndexedDB keys failed"))})}async getAll(t){const e=await this.open();return new Promise((n,s)=>{const a=e.transaction(t,"readonly").objectStore(t).getAll();a.onsuccess=()=>n(a.result),a.onerror=()=>s(a.error??new Error("IndexedDB read failed"))})}async clearStore(t){const e=await this.open();return new Promise((n,s)=>{const i=e.transaction(t,"readwrite");i.objectStore(t).clear(),i.oncomplete=()=>n(),i.onerror=()=>s(i.error??new Error("IndexedDB clear failed"))})}}const nt=new Wo;class Oo{async get(t){try{return await nt.get("assets",t)}catch{return}}async createFromBlob(t,e){const n=await Uo(t),s=await this.get(n);if(s)return s;const i=await createImageBitmap(t),a=Date.now(),r={id:n,type:"image",mimeType:t.type||"image/png",blob:t,width:i.width,height:i.height,sizeBytes:t.size,createdAt:a,updatedAt:a,name:e};return i.close(),await nt.put("assets",r),r}async put(t){await nt.put("assets",t)}async delete(t){await nt.delete("assets",t)}async getAllKeys(){try{return await nt.getAllKeys("assets")}catch{return[]}}async getAll(){try{return await nt.getAll("assets")}catch{return[]}}async totalSizeBytes(){return(await this.getAll()).reduce((e,n)=>e+n.sizeBytes,0)}async clearUnused(t){const e=await this.getAllKeys();let n=0;for(const s of e)t.has(s)||(await nt.delete("assets",s),n++);return n}async clearAll(){await nt.clearStore("assets")}}const pt=new Oo;async function Uo(o){const t=await crypto.subtle.digest("SHA-256",await o.arrayBuffer());return Array.from(new Uint8Array(t),e=>e.toString(16).padStart(2,"0")).join("")}const Gt=new Map,_o=2e3;function G(o){for(const t of Gt.keys())t.startsWith(o+"|")&&Gt.delete(t)}function Ye(o){if(o.data.shapeKind==="chevron"){if(typeof o.style.fontSize=="number"&&Number.isFinite(o.style.fontSize))return o.style.fontSize;const t=Math.abs(o.height)*.34,e=Math.abs(o.width)*.18;return Math.round(Math.max(13,Math.min(48,t,e)))}return o.style.fontSize??14}function qo(o,t,e,n){const s=Gt.get(t);if(s)return s;const i=[];for(const a of e.split(`
|
|
9
|
+
`)){if(a===""){i.push("");continue}const r=a.split(" ");let c="";for(const l of r){const d=c===""?l:c+" "+l;o.measureText(d).width>n&&c!==""?(i.push(c),c=l):c=d}i.push(c)}return Gt.size>_o&&Gt.clear(),Gt.set(t,i),i}function Qt(o,t,e,n,s,i){const a=Math.min(i,n/2,s/2);o.beginPath(),o.moveTo(t+a,e),o.arcTo(t+n,e,t+n,e+s,a),o.arcTo(t+n,e+s,t,e+s,a),o.arcTo(t,e+s,t,e,a),o.arcTo(t,e,t+n,e,a),o.closePath()}function Oe(o,t){const{ctx:e,lod:n}=t;if(e.save(),e.globalAlpha=o.style.opacity??1,n===0){Xo(o,t),e.restore();return}switch(o.type){case"sticky":Yo(o,t);break;case"task":Ko(o,t);break;case"rectangle":case"frame":zn(o,t);break;case"ellipse":ei(o,t);break;case"text":ni(o,t);break;case"line":case"arrow":case"connector":ii(o,t);break;case"image":case"screenshot":ai(o,t);break;default:zn(o,t)}e.restore()}function Xo(o,t){const{ctx:e}=t;if(o.type==="line"||o.type==="arrow"||o.type==="connector"){e.strokeStyle=o.style.stroke??(t.theme==="dark"?"#888":"#999"),e.lineWidth=Math.max(1/t.scale,o.style.strokeWidth??2),e.beginPath(),e.moveTo(o.x,o.y),e.lineTo(o.x+o.width,o.y+o.height),e.stroke();return}e.fillStyle=o.style.fill??(t.theme==="dark"?"#3a3d42":"#d8d8d4"),e.fillRect(o.x,o.y,o.width,o.height)}function Ke(o,t){o.style.shadow&&t.lod===2&&(t.ctx.shadowColor=t.theme==="dark"?"rgba(0,0,0,0.5)":"rgba(0,0,0,0.14)",t.ctx.shadowBlur=8*t.scale,t.ctx.shadowOffsetY=2*t.scale)}function Ve(o){o.ctx.shadowColor="transparent",o.ctx.shadowBlur=0,o.ctx.shadowOffsetY=0}function Yo(o,t){const{ctx:e,lod:n}=t,s=o.style.fill??"#fef08a";if(Ke(o,t),Qt(e,o.x,o.y,o.width,o.height,o.style.borderRadius??12),e.fillStyle=s,e.fill(),Ve(t),n===2){const i=o.data.text??"";i&&kn(o,t,i,14)}}function Ko(o,t){const{ctx:e,lod:n}=t,s=o.data.checked===!0,i=t.theme==="dark",a=o.style.borderRadius??14;if(Ke(o,t),Qt(e,o.x,o.y,o.width,o.height,a),e.fillStyle=o.style.fill??(i?"#17191b":"#ffffff"),e.fill(),Ve(t),e.strokeStyle=o.style.stroke??(i?"rgba(255,255,255,0.12)":"rgba(0,0,0,0.09)"),e.lineWidth=o.style.strokeWidth??1,e.stroke(),n<2)return;const r=Math.min(22,Math.max(16,o.height*.38)),c=o.x+16,l=o.y+o.height/2-r/2;Qt(e,c,l,r,r,6),e.fillStyle=s?"#0078d4":i?"#111314":"#f3f2f1",e.fill(),e.strokeStyle=s?"#0078d4":i?"rgba(255,255,255,0.18)":"rgba(0,0,0,0.13)",e.lineWidth=1.4,e.stroke(),s&&(e.strokeStyle="#ffffff",e.lineWidth=2.1,e.lineCap="round",e.lineJoin="round",e.beginPath(),e.moveTo(c+r*.26,l+r*.52),e.lineTo(c+r*.43,l+r*.68),e.lineTo(c+r*.75,l+r*.32),e.stroke());const d=o.data.text??"";if(!d)return;const h=50,p=16,u=o.style.fontSize??15,f=o.style.fontFamily??'-apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif';if(e.font=`${o.style.fontWeight??"650"} ${u}px ${f}`,e.fillStyle=s?i?"#a7aaa8":"#777777":o.style.textColor??(i?"#f6f6f3":"#252829"),e.textAlign="left",e.textBaseline="middle",e.save(),e.beginPath(),e.rect(o.x+h,o.y,Math.max(10,o.width-h-p),o.height),e.clip(),e.fillText(d,o.x+h,o.y+o.height/2),s){const y=e.measureText(d),b=o.y+o.height/2+1;e.strokeStyle=i?"rgba(167,170,168,0.58)":"rgba(119,119,119,0.48)",e.lineWidth=1.3,e.beginPath(),e.moveTo(o.x+h,b),e.lineTo(o.x+h+Math.min(y.width,o.width-h-p),b),e.stroke()}e.restore()}function zn(o,t){const{ctx:e,lod:n}=t,s=o.data.shapeKind??"rectangle",i=o.style.borderRadius??0;if(Ke(o,t),s==="diamond"?Vo(e,o):s==="triangle"?Go(e,o):s==="chevron"?Zo(e,o):s==="parallelogram"?Jo(e,o):s==="hexagon"?Qo(e,o):s==="cylinder"?ti(e,o):s==="pill"?Qt(e,o.x,o.y,o.width,o.height,Math.min(Math.abs(o.height)/2,Math.abs(o.width)/2)):i>0?Qt(e,o.x,o.y,o.width,o.height,i):(e.beginPath(),e.rect(o.x,o.y,o.width,o.height)),o.style.fill&&o.style.fill!=="transparent"&&(e.fillStyle=o.style.fill,e.fill()),Ve(t),o.style.stroke&&(o.style.strokeWidth??0)>0&&(e.strokeStyle=o.style.stroke,e.lineWidth=o.style.strokeWidth??1,e.stroke(),s==="cylinder")){const a=Math.abs(o.width)/2,r=Math.min(Math.abs(o.height)*.18,18);e.beginPath(),e.ellipse(o.x+o.width/2,o.y+r,a,r,0,0,Math.PI*2),e.stroke()}if(n===2){const a=o.data.text??"";if(a){const r=s==="chevron"?Math.min(Math.abs(o.width)*.18,Math.abs(o.height)*.55)+8:10;kn(o,t,a,r)}}}function Vo(o,t){const e=t.x,n=t.y,s=t.width,i=t.height;o.beginPath(),o.moveTo(e+s/2,n),o.lineTo(e+s,n+i/2),o.lineTo(e+s/2,n+i),o.lineTo(e,n+i/2),o.closePath()}function Go(o,t){const e=t.x,n=t.y,s=t.width,i=t.height;o.beginPath(),o.moveTo(e+s/2,n),o.lineTo(e+s,n+i),o.lineTo(e,n+i),o.closePath()}function Zo(o,t){const e=t.x,n=t.y,s=t.width,i=t.height,a=Math.min(Math.abs(s)*.22,Math.abs(i)*.62);o.beginPath(),o.moveTo(e,n),o.lineTo(e+s-a,n),o.lineTo(e+s,n+i/2),o.lineTo(e+s-a,n+i),o.lineTo(e,n+i),o.lineTo(e+a,n+i/2),o.closePath()}function Jo(o,t){const e=Math.min(Math.abs(t.width)*.2,Math.abs(t.height)*.55);o.beginPath(),o.moveTo(t.x+e,t.y),o.lineTo(t.x+t.width,t.y),o.lineTo(t.x+t.width-e,t.y+t.height),o.lineTo(t.x,t.y+t.height),o.closePath()}function Qo(o,t){const e=Math.min(Math.abs(t.width)*.22,Math.abs(t.height)*.5);o.beginPath(),o.moveTo(t.x+e,t.y),o.lineTo(t.x+t.width-e,t.y),o.lineTo(t.x+t.width,t.y+t.height/2),o.lineTo(t.x+t.width-e,t.y+t.height),o.lineTo(t.x+e,t.y+t.height),o.lineTo(t.x,t.y+t.height/2),o.closePath()}function ti(o,t){const e=Math.abs(t.width)/2,n=Math.min(Math.abs(t.height)*.18,18),s=t.x+t.width/2;o.beginPath(),o.ellipse(s,t.y+n,e,n,0,Math.PI,Math.PI*2),o.lineTo(t.x+t.width,t.y+t.height-n),o.ellipse(s,t.y+t.height-n,e,n,0,0,Math.PI),o.lineTo(t.x,t.y+n),o.closePath()}function ei(o,t){const{ctx:e,lod:n}=t;if(Ke(o,t),e.beginPath(),e.ellipse(o.x+o.width/2,o.y+o.height/2,Math.abs(o.width/2),Math.abs(o.height/2),0,0,Math.PI*2),o.style.fill&&o.style.fill!=="transparent"&&(e.fillStyle=o.style.fill,e.fill()),Ve(t),o.style.stroke&&(o.style.strokeWidth??0)>0&&(e.strokeStyle=o.style.stroke,e.lineWidth=o.style.strokeWidth??1,e.stroke()),n===2){const s=o.data.text??"";s&&kn(o,t,s,10)}}function ni(o,t){if(t.lod<2){t.ctx.fillStyle=t.theme==="dark"?"#55585e":"#c5c5c0",t.ctx.fillRect(o.x,o.y,o.width,Math.min(o.height,6/t.scale));return}const e=o.data.text??"";si(o,t,e)}function si(o,t,e){const{ctx:n}=t,s=Ye(o),i=o.style.fontFamily??'-apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif',a=o.style.textColor??(t.theme==="dark"?"#f2f2f2":"#1f2933"),r=Math.max(10,o.width),c=Fs(e),l=s*1.35;let d=o.y+l/2;n.save(),n.beginPath(),n.rect(o.x,o.y,o.width,o.height),n.clip(),n.textBaseline="middle",n.textAlign="left";for(const h of c){if(d>o.y+o.height)break;let p=h.text,u=o.x,f=s,y=a;if(h.kind==="heading"?f=h.level===1?s*1.35:h.level===2?s*1.18:s*1.08:h.kind==="quote"?(u+=14,y=t.theme==="dark"?"#cbd5e1":"#475569",n.fillStyle=t.theme==="dark"?"#334155":"#cbd5e1",n.fillRect(o.x+2,d-l/2+2,3,Math.max(l-4,10))):h.kind==="list"&&(u+=16,n.fillStyle=y,n.beginPath(),n.arc(o.x+6,d,2.2,0,Math.PI*2),n.fill()),h.kind==="code"){const v=p.split(/\r?\n/),S=f*1.45,x=v.length*S+12;n.fillStyle=t.theme==="dark"?"#111827":"#eef2f7",n.fillRect(o.x,d-l/2,Math.max(80,o.width),x);for(const E of v){if(d>o.y+o.height)break;const T=Hn(n,[{text:E,code:!0}],r-12,f,i);for(const B of T){let I=o.x+8;for(const R of B)gn(n,R,f,i),n.fillStyle=y,n.fillText(R.text,I,d+6),I+=n.measureText(R.text).width;d+=S}}d+=8;continue}const b=oi(p),w=Hn(n,b,r-(u-o.x),f,i);for(const v of w){if(d>o.y+o.height)break;let S=u;for(const x of v){if(gn(n,x,f,i),x.code){const E=n.measureText(x.text).width;n.fillStyle=t.theme==="dark"?"#1f2937":"#eef2f7",n.fillRect(S-2,d-f*.48,E+4,f*.96),n.fillStyle=y}else n.fillStyle=y;n.fillText(x.text,S,d),S+=n.measureText(x.text).width}d+=l}}n.restore()}function Fs(o){const t=o.split(/\r?\n/),e=[];for(let n=0;n<t.length;n++){const s=t[n],i=s.trimStart();if(!i){e.push({kind:"paragraph",text:""});continue}if(/^```/.test(i)){const l=[];for(n++;n<t.length&&!/^```/.test(t[n].trimStart());)l.push(t[n]),n++;e.push({kind:"code",text:l.join(`
|
|
10
|
+
`)});continue}const a=i.match(/^(#{1,3})\s+(.*)$/);if(a){e.push({kind:"heading",level:a[1].length,text:a[2]});continue}const r=i.match(/^>\s?(.*)$/);if(r){e.push({kind:"quote",text:r[1]});continue}const c=i.match(/^([-*+]|\d+\.)\s+(.*)$/);if(c){e.push({kind:"list",text:c[2]});continue}e.push({kind:"paragraph",text:s})}return e}function Nt(o){if(o.type!=="text")return;const t=String(o.data.text??""),e=Fs(t),n=Ye(o);let s=0;for(const i of e){if(i.kind==="code"){s+=Math.max(1,i.text.split(/\r?\n/).length)+1;continue}const a=Math.max(1,Math.floor(Math.max(120,o.width)/Math.max(6,n*.6))),r=i.text.replace(/[*_`#>-]/g,"");s+=Math.max(1,Math.ceil(Math.max(1,r.length)/a))}o.height=Math.max(n*1.45,s*n*1.35+8)}function oi(o){const t=[];let e=0;for(;e<o.length;){if(o.startsWith("**",e)){const s=o.indexOf("**",e+2);if(s!==-1){t.push({text:o.slice(e+2,s),bold:!0}),e=s+2;continue}}if(o.startsWith("*",e)){const s=o.indexOf("*",e+1);if(s!==-1){t.push({text:o.slice(e+1,s),italic:!0}),e=s+1;continue}}if(o.startsWith("`",e)){const s=o.indexOf("`",e+1);if(s!==-1){t.push({text:o.slice(e+1,s),code:!0}),e=s+1;continue}}let n=o.length;for(const s of["**","*","`"]){const i=o.indexOf(s,e+1);i!==-1&&i<n&&(n=i)}t.push({text:o.slice(e,n)}),e=n}return t.filter(n=>n.text.length>0)}function Hn(o,t,e,n,s){const i=[[]];let a=0;for(const r of t){const c=r.text.split(/(\s+)/);for(const l of c){if(!l)continue;const d={...r,text:l};gn(o,d,n,s);const h=o.measureText(l).width;a>0&&a+h>e&&l.trim()&&(i.push([]),a=0),i[i.length-1].push(d),a+=h}}return i}function gn(o,t,e,n){const s=t.bold?"700":"400",i=t.italic?"italic ":"",a=t.code?'"SF Mono", ui-monospace, Menlo, monospace':n;o.font=`${i}${s} ${e}px ${a}`}function kn(o,t,e,n,s="center",i="middle"){const{ctx:a}=t,r=o.data.shapeKind==="chevron",c=Ye(o),l=o.style.fontFamily??'-apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif',d=r?"750":o.style.fontWeight??"400";a.font=`${d} ${c}px ${l}`,a.fillStyle=o.style.textColor??(t.theme==="dark"&&o.type==="text"?"#f2f2f2":"#1f2933");const h=Math.max(10,o.width-n*2),p=`${o.id}|${o.updatedAt}|${c}|${h.toFixed(0)}`,u=qo(a,p,e,h),f=c*1.35,y=u.length*f;let b;i==="middle"?b=o.y+o.height/2-y/2+f/2:b=o.y+n+f/2,a.textBaseline="middle",a.textAlign=s;const w=s==="center"?o.x+o.width/2:o.x+n;a.save(),a.beginPath(),a.rect(o.x,o.y,o.width,o.height),a.clip();for(let v=0;v<u.length;v++)a.fillText(u[v],w,b+v*f);a.restore()}function ii(o,t){const{ctx:e,lod:n}=t,s=o.x,i=o.y,a=o.x+o.width,r=o.y+o.height,c=o.style.stroke??(t.theme==="dark"?"#d1d5db":"#374151"),l=o.style.strokeWidth??2;if(e.strokeStyle=c,e.fillStyle=c,e.lineWidth=l,e.setLineDash(o.style.strokeDash??[]),e.beginPath(),e.moveTo(s,i),e.lineTo(a,r),e.stroke(),e.setLineDash([]),n>=1){const d=Math.atan2(r-i,a-s),h=Math.max(11,l*5.5);(o.style.arrowEnd??o.type==="arrow")&&jn(e,a,r,d,h),o.style.arrowStart&&jn(e,s,i,d+Math.PI,h);const p=typeof o.data.text=="string"?o.data.text.trim():"";if(p)if(o.data.labelPosition==="sides"){const[u,f]=p.split("|").map(y=>y.trim());u&&nn(e,u,s,i,a,r,t,.24),f&&nn(e,f,s,i,a,r,t,.76)}else nn(e,p,s,i,a,r,t)}}function nn(o,t,e,n,s,i,a,r=.5){o.font='600 13px -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif';const h=o.measureText(t).width+7*2,p=21,u=e+(s-e)*r-h/2,f=n+(i-n)*r-p/2;o.fillStyle=a.theme==="dark"?"#202328":"#ffffff",Qt(o,u,f,h,p,4),o.fill(),o.strokeStyle=a.theme==="dark"?"#4a4d52":"#d8dade",o.lineWidth=1,o.stroke(),o.fillStyle=a.theme==="dark"?"#f2f2f2":"#1f2933",o.textAlign="center",o.textBaseline="middle",o.fillText(t,u+h/2,f+p/2)}function jn(o,t,e,n,s){o.beginPath(),o.moveTo(t,e),o.lineTo(t-s*Math.cos(n-Math.PI/6),e-s*Math.sin(n-Math.PI/6)),o.lineTo(t-s*Math.cos(n+Math.PI/6),e-s*Math.sin(n+Math.PI/6)),o.closePath(),o.fill()}function ai(o,t){const{ctx:e,imageCache:n}=t,s=o.data.src,i=o.data.assetId,a=s?n.getBySrc(s):i?n.get(i):null;if(a){if(t.lod===1&&t.scale<.15){e.fillStyle=t.theme==="dark"?"#3a3d42":"#d8d8d4",e.fillRect(o.x,o.y,o.width,o.height);return}e.drawImage(a,o.x,o.y,o.width,o.height)}else if(e.fillStyle=t.theme==="dark"?"#2a2d31":"#ececea",e.fillRect(o.x,o.y,o.width,o.height),e.strokeStyle=t.theme==="dark"?"#4a4d52":"#c9c9c5",e.lineWidth=1/t.scale,e.strokeRect(o.x,o.y,o.width,o.height),t.lod===2){const c=(s?n.isMissingSrc(s):i?n.isMissing(i):!1)?"Missing image":"Loading…";e.font="12px -apple-system, sans-serif",e.fillStyle=t.theme==="dark"?"#9ca3af":"#6b7280",e.textAlign="center",e.textBaseline="middle",e.fillText(c,o.x+o.width/2,o.y+o.height/2)}}class ri{constructor(t,e){m(this,"element");m(this,"canvas");m(this,"ctx");m(this,"imageCache");m(this,"doc",null);m(this,"region",[0,0,100,100]);m(this,"opts");m(this,"openLink");m(this,"ro");this.opts=e,this.element=t,t.classList.add("board-embed"),t.textContent="";const n=document.createElement("div");n.className="board-embed-frame",n.style.height=e.height+"px",this.canvas=document.createElement("canvas"),this.ctx=this.canvas.getContext("2d"),n.appendChild(this.canvas),t.appendChild(n);const s=document.createElement("a");s.className="board-embed-open";const i=e.region?`?region=${encodeURIComponent(e.region.join(","))}`:"";if(s.href=`#/root/${encodeURIComponent(e.rootId)}/boards/${encodeURIComponent(e.src)}${i}`,s.textContent="Open board →",this.openLink=s,n.appendChild(s),e.title){const a=document.createElement("figcaption");a.textContent=e.title,t.appendChild(a)}this.imageCache=new Ns(pt,()=>this.render(),a=>k.assetUrl(this.opts.rootId,a)),this.ro=new ResizeObserver(()=>this.render()),this.ro.observe(n),this.load()}async load(){var t;try{const e=(t=this.opts.srcCandidates)!=null&&t.length?this.opts.srcCandidates:[this.opts.src];let n=null,s=this.opts.src;for(const a of e){const r=await k.getBoard(this.opts.rootId,a);if(n=r?We(r):null,n){s=a;break}}if(!n)return this.renderError(`Board "${this.opts.src}" not found`);this.opts.src=s;const i=this.opts.region?`?region=${encodeURIComponent(this.opts.region.join(","))}`:"";this.openLink.href=`#/root/${encodeURIComponent(this.opts.rootId)}/boards/${encodeURIComponent(s)}${i}`,this.doc=n,this.region=this.opts.region??ci(n.elements),this.render()}catch{this.renderError("Failed to load board")}}renderError(t){var n;(n=this.element.querySelector(".board-embed-frame"))==null||n.classList.add("error");const e=this.element.querySelector(".board-embed-frame");if(e){e.innerHTML="";const s=document.createElement("span");s.className="board-embed-msg",s.textContent=t,e.appendChild(s)}}render(){if(!this.doc)return;const t=this.canvas.parentElement,e=Math.max(1,t.clientWidth),n=Math.max(1,t.clientHeight),s=Math.max(1,Math.min(4,(window.devicePixelRatio||1)*(this.opts.pixelRatioMultiplier??1)));this.canvas.width=Math.round(e*s),this.canvas.height=Math.round(n*s),this.canvas.style.width=e+"px",this.canvas.style.height=n+"px";const i=this.ctx;i.setTransform(s,0,0,s,0,0),i.clearRect(0,0,e,n),i.fillStyle=this.opts.theme==="dark"?"#111315":"#f3f2f1",i.fillRect(0,0,e,n);const[a,r,c,l]=this.region;if(c<=0||l<=0)return;const d=Math.min(e/c,n/l),h=(e-c*d)/2-a*d,p=(n-l*d)/2-r*d;i.save(),i.translate(h,p),i.scale(d,d);const u={ctx:i,scale:d,lod:2,theme:this.opts.theme,imageCache:this.imageCache},f=Math.max(c,l)*.1;for(const y of[...this.doc.elements].sort((b,w)=>b.zIndex-w.zIndex))y.hidden||y.x+y.width<a-f||y.x>a+c+f||y.y+y.height<r-f||y.y>r+l+f||Oe(y,u);i.restore()}setTheme(t){this.opts.theme!==t&&(this.opts.theme=t,this.render())}destroy(){this.ro.disconnect(),this.imageCache.clear()}}function ci(o){if(o.length===0)return[0,0,800,600];let t=1/0,e=1/0,n=-1/0,s=-1/0;for(const a of o)t=Math.min(t,a.x,a.x+a.width),e=Math.min(e,a.y,a.y+a.height),n=Math.max(n,a.x,a.x+a.width),s=Math.max(s,a.y,a.y+a.height);const i=40;return[t-i,e-i,n-t+i*2,s-e+i*2]}function me(){return document.documentElement.getAttribute("data-theme")==="dark"?"dark":"light"}function yn(o,t,e){const{html:n,frontmatter:s}=Zt(t,e),i=document.createElement("article");i.className="markdown-body",i.innerHTML=n,o.replaceChildren(i),i.querySelectorAll("pre.code-block").forEach(r=>{var h;const c=r.querySelector("code"),l=(h=c==null?void 0:c.textContent)==null?void 0:h.trimEnd();if(!l)return;const d=document.createElement("button");d.className="code-copy-btn",d.type="button",d.textContent="Copy",d.addEventListener("click",async()=>{try{await navigator.clipboard.writeText(l),d.textContent="Copied"}catch{d.textContent="Failed"}window.setTimeout(()=>{d.textContent="Copy"},1200)}),r.appendChild(d)});const a=[];return i.querySelectorAll("figure.board-embed").forEach(r=>{const c=r.dataset.src??"";if(!c)return;const l=xe(c,e.docPath),d=l[0]??"",h=r.dataset.region??"",p=h?h.split(",").map(Number):[],u=p.length===4&&p.every(b=>Number.isFinite(b))?[p[0],p[1],p[2],p[3]]:null,f=parseInt(r.dataset.height??"360",10)||360,y=r.dataset.title||null;try{a.push(new ri(r,{rootId:e.rootId,src:d,srcCandidates:l,region:u,height:f,title:y,theme:e.theme??me(),pixelRatioMultiplier:e.boardPreviewScale}))}catch(b){console.error("Board embed failed to mount",c,b),r.textContent=`Could not load board "${c}".`}}),{frontmatter:s,destroy:()=>{for(const r of a)r.destroy()},setTheme:r=>{for(const c of a)c.setTheme(r)}}}function V(o,t){const e=document.createElement("div");e.className="modal-backdrop";const n=document.createElement("div");n.className="modal",n.setAttribute("role","dialog"),n.setAttribute("aria-label",o);const s=document.createElement("button");s.className="modal-close",s.textContent="✕",s.setAttribute("aria-label","Close");const i=document.createElement("h2");i.textContent=o;const a=document.createElement("div"),r=()=>e.remove();s.addEventListener("click",r),e.addEventListener("click",c=>{c.target===e&&r()}),e.addEventListener("keydown",c=>{c.stopPropagation(),c.key==="Escape"&&r()}),n.appendChild(s),n.appendChild(i),n.appendChild(a),e.appendChild(n),document.body.appendChild(e),t(a,r),s.focus()}let ut=null,sn=null;function C(o){ut||(ut=document.createElement("div"),ut.className="toast",document.body.appendChild(ut)),ut.textContent=o,ut.classList.add("visible"),sn!==null&&clearTimeout(sn),sn=window.setTimeout(()=>{ut==null||ut.classList.remove("visible")},2600)}const Y={select:'<svg viewBox="0 0 24 24"><path d="M4 3l7 18 2.5-7.5L21 11z"/></svg>',hand:'<svg viewBox="0 0 24 24"><path d="M18 11V6.5a1.5 1.5 0 0 0-3 0V11m0-1V4.5a1.5 1.5 0 0 0-3 0V10m0 .5v-5a1.5 1.5 0 0 0-3 0V12m9-1v1.5a1.5 1.5 0 0 1 3 0V14c0 4-2.5 7-6.5 7S8 18.5 6 15l-1.8-3.2a1.4 1.4 0 0 1 2.3-1.5L8 12V7"/></svg>',sticky:'<svg viewBox="0 0 24 24"><path d="M5 4h14a1 1 0 0 1 1 1v9l-6 6H5a1 1 0 0 1-1-1V5a1 1 0 0 1 1-1z"/><path d="M14 20v-5a1 1 0 0 1 1-1h5"/></svg>',task:'<svg viewBox="0 0 24 24"><rect x="4" y="5" width="16" height="14" rx="3"/><path d="M8 12l2.3 2.3L16 8.8"/></svg>',rectangle:'<svg viewBox="0 0 24 24"><rect x="4" y="5" width="16" height="14" rx="2"/></svg>',ellipse:'<svg viewBox="0 0 24 24"><ellipse cx="12" cy="12" rx="8.5" ry="7"/></svg>',diamond:'<svg viewBox="0 0 24 24"><path d="M12 3l8 9-8 9-8-9z"/></svg>',triangle:'<svg viewBox="0 0 24 24"><path d="M12 4l9 16H3z"/></svg>',pill:'<svg viewBox="0 0 24 24"><rect x="3.5" y="7" width="17" height="10" rx="5"/></svg>',chevron:'<svg viewBox="0 0 24 24"><path d="M4 6h12l5 6-5 6H4l5-6z"/></svg>',parallelogram:'<svg viewBox="0 0 24 24"><path d="M7 5h13l-3 14H4z"/></svg>',hexagon:'<svg viewBox="0 0 24 24"><path d="M8 4h8l5 8-5 8H8l-5-8z"/></svg>',cylinder:'<svg viewBox="0 0 24 24"><ellipse cx="12" cy="6" rx="7" ry="3"/><path d="M5 6v11c0 1.7 3.1 3 7 3s7-1.3 7-3V6"/></svg>',arrowDashed:'<svg viewBox="0 0 24 24"><path stroke-dasharray="4 3" d="M4 12h14m0 0l-5-5m5 5l-5 5"/></svg>',arrowBoth:'<svg viewBox="0 0 24 24"><path d="M4 12h16m-16 0l5-5m-5 5l5 5m11-5l-5-5m5 5l-5 5"/></svg>',arrowLabel:'<svg viewBox="0 0 24 24"><path d="M3 17L17 7m0 0h-6m6 0v6"/><rect x="7" y="9" width="10" height="6" rx="1"/></svg>',text:'<svg viewBox="0 0 24 24"><path d="M5 6V4h14v2M12 4v16m-3 0h6"/></svg>',arrow:'<svg viewBox="0 0 24 24"><path d="M5 19L19 5m0 0h-7m7 0v7"/></svg>',image:'<svg viewBox="0 0 24 24"><rect x="3" y="4" width="18" height="16" rx="2"/><circle cx="9" cy="10" r="1.6"/><path d="M21 16l-5-5-9 9"/></svg>',templates:'<svg viewBox="0 0 24 24"><rect x="3" y="3" width="8" height="8" rx="1.5"/><rect x="13" y="3" width="8" height="8" rx="1.5"/><rect x="3" y="13" width="8" height="8" rx="1.5"/><rect x="13" y="13" width="8" height="8" rx="1.5"/></svg>',shapes:'<svg viewBox="0 0 24 24"><rect x="4" y="5" width="7" height="7" rx="1.5"/><circle cx="16.5" cy="8.5" r="3.5"/><path d="M7.5 14l3.8 6H3.7z"/><path d="M15 14h4l2 3-2 3h-4l2-3z"/></svg>',sun:'<svg viewBox="0 0 24 24"><circle cx="12" cy="12" r="4"/><path d="M12 2v2m0 16v2M4.9 4.9l1.4 1.4m11.4 11.4l1.4 1.4M2 12h2m16 0h2M4.9 19.1l1.4-1.4m11.4-11.4l1.4-1.4"/></svg>',moon:'<svg viewBox="0 0 24 24"><path d="M21 12.8A9 9 0 1 1 11.2 3 7 7 0 0 0 21 12.8z"/></svg>',export:'<svg viewBox="0 0 24 24"><path d="M12 15V3m0 0L7 8m5-5l5 5M4 17v2a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-2"/></svg>',import:'<svg viewBox="0 0 24 24"><path d="M12 3v12m0 0l-5-5m5 5l5-5M4 17v2a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-2"/></svg>',gauge:'<svg viewBox="0 0 24 24"><path d="M12 14l4-4M3.3 14a9 9 0 1 1 17.4 0"/></svg>',storage:'<svg viewBox="0 0 24 24"><ellipse cx="12" cy="5.5" rx="8" ry="2.5"/><path d="M4 5.5V12c0 1.4 3.6 2.5 8 2.5s8-1.1 8-2.5V5.5M4 12v6.5C4 19.9 7.6 21 12 21s8-1.1 8-2.5V12"/></svg>',flask:'<svg viewBox="0 0 24 24"><path d="M9 3h6M10 3v6L4.5 18a2 2 0 0 0 1.8 3h11.4a2 2 0 0 0 1.8-3L14 9V3"/><path d="M7 15h10"/></svg>',reset:'<svg viewBox="0 0 24 24"><path d="M3 12a9 9 0 1 0 2.6-6.3M3 4v5h5"/></svg>',camera:'<svg viewBox="0 0 24 24"><path d="M3 8a2 2 0 0 1 2-2h2l2-2h6l2 2h2a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/><circle cx="12" cy="13" r="3.5"/></svg>',trash:'<svg viewBox="0 0 24 24"><path d="M4 7h16M10 11v6m4-6v6M6 7l1 13a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1l1-13M9 7V4a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v3"/></svg>',embed:'<svg viewBox="0 0 24 24"><rect x="3" y="5" width="18" height="14" rx="2" stroke-dasharray="3 3"/><path d="M9 10l-2 2 2 2m6-4l2 2-2 2"/></svg>',arrowLeft:'<svg viewBox="0 0 24 24"><path d="M19 12H5m0 0l6-6m-6 6l6 6"/></svg>',search:'<svg viewBox="0 0 24 24"><circle cx="11" cy="11" r="7"/><path d="M20 20l-4-4"/></svg>',panelLeft:'<svg viewBox="0 0 24 24"><rect x="4" y="4" width="16" height="16" rx="2"/><path d="M10 4v16"/></svg>',edit:'<svg viewBox="0 0 24 24"><path d="M12 20h9"/><path d="M16.5 3.5a2.1 2.1 0 0 1 3 3L7 19l-4 1 1-4z"/></svg>',copy:'<svg viewBox="0 0 24 24"><rect x="8" y="8" width="11" height="11" rx="2"/><path d="M5 15H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v1"/></svg>',folder:'<svg viewBox="0 0 24 24"><path d="M4 7a2 2 0 0 1 2-2h4l2 2h6a2 2 0 0 1 2 2v7a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2z"/></svg>',folderOpen:'<svg viewBox="0 0 24 24"><path d="M4 7a2 2 0 0 1 2-2h4l2 2h6a2 2 0 0 1 2 2v1M4 8l1.5 9c.1.6.6 1 1.2 1h10.6c.6 0 1.1-.4 1.2-1L20 8z"/></svg>',file:'<svg viewBox="0 0 24 24"><path d="M13 3H6a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V10z"/><path d="M13 3v7h7"/></svg>',fileText:'<svg viewBox="0 0 24 24"><path d="M13 3H6a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V10z"/><path d="M13 3v7h7M10 13h4m-4 4h4"/></svg>',board:'<svg viewBox="0 0 24 24"><rect x="3" y="3" width="7" height="7" rx="1"/><rect x="12" y="3" width="9" height="7" rx="1"/><rect x="3" y="12" width="9" height="9" rx="1"/><rect x="14" y="12" width="7" height="9" rx="1"/></svg>',doc:'<svg viewBox="0 0 24 24"><path d="M14 3H6a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9z"/><path d="M14 3v6h6M10 13h4m-4 4h4m-4-8h1"/></svg>',skill:'<svg viewBox="0 0 24 24"><path d="M12 2l3.1 6.3 6.9 1-5 4.9 1.2 6.8-6.2-3.3-6.2 3.3 1.2-6.8-5-4.9 6.9-1z"/></svg>',plus:'<svg viewBox="0 0 24 24"><path d="M12 5v14m-7-7h14"/></svg>',moreVertical:'<svg viewBox="0 0 24 24"><circle cx="12" cy="12" r="1"/><circle cx="12" cy="5" r="1"/><circle cx="12" cy="19" r="1"/></svg>',chevronRight:'<svg viewBox="0 0 24 24"><path d="M9 18l6-6-6-6"/></svg>',chevronDown:'<svg viewBox="0 0 24 24"><path d="M6 9l6 6 6-6"/></svg>',wiki:'<svg viewBox="0 0 24 24"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><path d="M14 2v6h6M8 13h2m-2 4h6m-6-8h1"/></svg>',list:'<svg viewBox="0 0 24 24"><line x1="8" y1="6" x2="21" y2="6"/><line x1="8" y1="12" x2="21" y2="12"/><line x1="8" y1="18" x2="21" y2="18"/><circle cx="4" cy="6" r="1"/><circle cx="4" cy="12" r="1"/><circle cx="4" cy="18" r="1"/></svg>'};let ce=null;async function Wn(o){const t=await li(o);if(t.length===0)throw new Error("No markdown documents were found to export.");ce==null||ce();const e=di(o,t);let n={...e};const s=new Set(t.map($=>$.path));let i=null,a=!1;const r=L("docs-export-studio-backdrop"),c=L("docs-export-studio");c.setAttribute("role","dialog"),c.setAttribute("aria-modal","true"),c.setAttribute("aria-label","Publication studio");const l=L("docs-export-studio-header"),d=L("docs-export-studio-header-copy"),h=document.createElement("span");h.textContent="Publication studio";const p=document.createElement("h2");p.textContent=n.title;const u=document.createElement("p");u.textContent="Tune the publication, inspect the exact preview, then export the same document you are looking at.",d.append(h,p,u);const f=L("docs-export-studio-header-actions"),y=te("btn docs-export-primary-btn","Export PDF");y.innerHTML=`${Y.export}<span>Export PDF</span>`;const b=te("btn docs-export-secondary-btn docs-export-studio-close","Close");b.innerHTML='<span aria-hidden="true">x</span>',b.title="Close publication studio",b.setAttribute("aria-label","Close publication studio"),b.addEventListener("click",()=>Ce()),f.append(y,b),l.append(d,f);const w=L("docs-export-studio-layout"),v=L("docs-export-studio-controls"),S=L("docs-export-studio-controls-body");v.appendChild(S);const x=L("docs-export-preview-shell"),E=L("docs-export-preview-header"),M=L("docs-export-preview-header-copy"),T=document.createElement("span");T.textContent="Live preview";const B=document.createElement("strong");B.textContent=ye(n.title),M.append(T,B);const I=L("docs-export-preview-meta");E.append(M,I);const R=L("docs-export-preview-scroll");x.append(E,R),w.append(v,x),c.append(l,w),r.appendChild(c),document.body.appendChild(r);const lt=$t("Publication title",n.title),Lt=$t("Subtitle",n.subtitle,{placeholder:"Optional context line"}),dt=$t("Author",n.author,{placeholder:"Optional"}),O=$t("Organization",n.organization,{placeholder:"Optional"}),Z=$t("Publication date",n.publicationDate,{type:"date"}),N=$t("Classification",n.classification),it=Ii("Notice",n.legalNotice,{placeholder:"Optional legal or distribution note"}),K=on("Style",[{value:"clean",label:"Clean"},{value:"report",label:"Report"}],n.style),D=on("Paper",[{value:"A4",label:"A4"},{value:"Letter",label:"Letter"}],n.paper),J=on("Scale",[{value:"90",label:"90%"},{value:"100",label:"100%"},{value:"110",label:"110%"}],n.scale),j=_t("Include cover page",n.includeCoverPage,"Adds a formal front page before the content."),Q=_t("Include table of contents",n.includeTableOfContents,"Lists the included document sections before the publication begins."),tt=_t("Show file paths",n.includeFilePaths,"Displays repo-relative paths above included documents."),Ge=_t("Start each document on a new page",n.pageBreakBetweenDocs,"Useful when compiling a directory tree into one publication."),Ze=_t("Show page header",n.showHeaderChrome,"Adds a compact publication header bar to each included document section."),Je=_t("Show page footer",n.showFooterChrome,"Adds a compact publication footer bar to each included document section."),In=wi(n.logoDataUrl,()=>ae()),we=()=>t.filter($=>s.has($.path)),ie=o.kind==="dir"?xi(t,s,{onSelectionChange:()=>ae()}):null;S.append(Me(1,"Publication",[lt.field,Lt.field,K.field,D.field,J.field,In.field]),Me(2,"Metadata",[dt.field,O.field,Z.field,N.field,it.field]),Me(3,"Structure",[j.wrapper,Q.wrapper,tt.wrapper,Ge.wrapper,Ze.wrapper,Je.wrapper])),ie&&S.appendChild(Me(4,"Included documents",[ie.element]));const io=()=>{const $=we();i==null||i.handles.forEach(ke=>ke.destroy()),i==null||i.shell.remove(),i=hi(o,$,n),R.replaceChildren(i.shell)},Pn=()=>{const $=we();p.textContent=n.title,B.textContent=ye(n.title),I.replaceChildren(Le(`${$.length} ${$.length===1?"doc":"docs"}`),Le(n.style==="report"?"Report style":"Clean style"),Le(n.paper),Le(`${n.scale}%`)),y.disabled=$.length===0},ae=()=>{n={title:lt.input.value.trim()||e.title,subtitle:Lt.input.value.trim(),style:Pi(K.select.value)?K.select.value:e.style,paper:$i(D.select.value)?D.select.value:e.paper,scale:Ri(J.select.value)?J.select.value:e.scale,includeCoverPage:j.input.checked,includeTableOfContents:Q.input.checked&&we().length>1,includeFilePaths:tt.input.checked,pageBreakBetweenDocs:Ge.input.checked,showHeaderChrome:Ze.input.checked,showFooterChrome:Je.input.checked,author:dt.input.value.trim(),organization:O.input.value.trim(),publicationDate:Z.input.value.trim(),classification:N.input.value.trim(),legalNotice:it.textarea.value.trim(),logoDataUrl:In.getValue()},ie==null||ie.refresh(),Pn(),io()};y.addEventListener("click",async()=>{const $=we();if($.length===0){C("Select at least one document to export.");return}if(!i){C("Preview is still preparing.");return}y.disabled=!0;try{await pi(i.shell,o,$,n)}catch(ke){C(ke instanceof Error?ke.message:"Could not export PDF")}finally{y.disabled=!1,Pn()}}),[lt.input,Lt.input,dt.input,O.input,Z.input,N.input,it.textarea].forEach($=>$.addEventListener("input",ae)),[K.select,D.select,J.select,j.input,Q.input,tt.input,Ge.input,Ze.input,Je.input].forEach($=>{$.addEventListener("change",ae)});const $n=$=>{$.target===r&&Ce()},Rn=$=>{$.key==="Escape"&&($.preventDefault(),Ce())};r.addEventListener("mousedown",$n),document.addEventListener("keydown",Rn,!0);function Ce(){a||(a=!0,ce=null,r.removeEventListener("mousedown",$n),document.removeEventListener("keydown",Rn,!0),i==null||i.handles.forEach($=>$.destroy()),i=null,r.remove())}ce=Ce,ae(),lt.input.focus()}async function li(o){const t=o.tree??await k.getTree(o.root.id),e=o.kind==="doc"?[o.filePath]:Ci(t,o.dirPath),n=[...new Set(e)].sort(Ei);return(await Promise.all(n.map(async i=>({path:i,markdown:await k.readFile(o.root.id,i)})))).map(({path:i,markdown:a})=>{var c,l;const{frontmatter:r}=Zt(a);return{path:i,title:((c=r.title)==null?void 0:c.trim())||Ti(a)||Mt(zs(i)),summary:((l=r.summary)==null?void 0:l.trim())||"",markdown:a}})}function di(o,t){var n;return{title:o.kind==="doc"?((n=t[0])==null?void 0:n.title)||Mt(zs(o.filePath)):o.dirPath?Mt(En(o.dirPath)||o.root.displayPath.split("/").pop()||o.root.projectLabel):`${o.root.projectLabel} Docs`,subtitle:o.kind==="doc"?`${o.root.projectLabel} / ${o.root.displayPath} / ${o.filePath}`:`${o.root.projectLabel} / ${o.root.displayPath}${o.dirPath?` / ${o.dirPath}`:""}`,style:o.kind==="doc"?"clean":"report",paper:"A4",scale:"100",includeCoverPage:o.kind==="dir",includeTableOfContents:o.kind==="dir"&&t.length>1,includeFilePaths:o.kind==="dir",pageBreakBetweenDocs:o.kind==="dir",showHeaderChrome:!0,showFooterChrome:!0,author:"",organization:o.root.projectLabel,publicationDate:Mi(),classification:"Internal",legalNotice:"",logoDataUrl:""}}function hi(o,t,e){const n=L("docs-export-publication-shell");n.dataset.docsExportStyle=e.style,n.dataset.docsExportPaper=e.paper,n.dataset.docsExportMode=o.kind,n.dataset.docsExportScale=e.scale;const s=L("docs-export-publication");if(n.appendChild(s),t.length===0)return s.appendChild(vi()),{shell:n,handles:[]};e.includeCoverPage&&s.appendChild(gi(o,t,e)),e.includeTableOfContents&&t.length>1&&s.appendChild(yi(t,o,e));const i=[],a=o.kind==="dir"?t.map(c=>On(o,c.path).key):[];let r="";return t.forEach((c,l)=>{let d=null,h=!1;o.kind==="dir"&&(d=On(o,c.path),d.key&&d.key!==r&&(h=!0,r=d.key));const p=document.createElement("section");p.className="docs-export-doc",p.id=`docs-export-section-${l+1}`,h&&d&&p.appendChild(bi(d));const u=mi(o,c,e,l,t.length);u&&p.appendChild(u);const f=L("docs-export-doc-body");p.appendChild(f);const y=o.kind==="dir"?l<t.length-1&&a[l+1]!==a[l]:!1;l<t.length-1&&(e.pageBreakBetweenDocs||y)&&p.classList.add("docs-export-doc-break-after"),s.appendChild(p),i.push(yn(f,Li(c.markdown,c.title),{rootId:o.root.id,docPath:c.path,theme:"light",boardPreviewScale:2.5}))}),{shell:n,handles:i}}async function pi(o,t,e,n){var c;const s=await ui(o,n),i=fi(t,e,n),a=await fetch("/__api/export/pdf",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({html:s,fileName:ye(n.title),pdf:{paper:n.paper,marginTopMm:i.marginTopMm,marginBottomMm:i.marginBottomMm,marginLeftMm:14,marginRightMm:14,displayHeaderFooter:i.displayHeaderFooter,headerTemplate:i.headerTemplate,footerTemplate:i.footerTemplate}})});if(!a.ok){let l="";try{l=((c=await a.json())==null?void 0:c.error)??""}catch{}throw new Error(l||`PDF export failed (${a.status})`)}const r=await a.blob();Ai(r,ye(n.title))}async function ui(o,t){const e=o.cloneNode(!0),n=Array.from(o.querySelectorAll("canvas")),s=Array.from(e.querySelectorAll("canvas"));n.forEach((r,c)=>{var d;const l=document.createElement("img");l.src=r.toDataURL("image/png"),l.width=r.width,l.height=r.height,l.className=r.className,l.style.cssText=r.style.cssText,l.alt="Board preview",(d=s[c])==null||d.replaceWith(l)}),e.querySelectorAll(".code-copy-btn, .board-embed-open").forEach(r=>r.remove());const i=Di(),a=t.paper==="Letter"?"@page { size: Letter; }":"@page { size: A4; }";return["<!doctype html>",'<html data-theme="light" data-docs-export-print="true">',"<head>",'<meta charset="utf-8" />','<meta name="viewport" content="width=device-width, initial-scale=1" />',`<title>${je(ye("publication"))}</title>`,`<style>${i}</style>`,`<style>${a} html,body{margin:0;padding:0;background:var(--surface-raised);-webkit-print-color-adjust:exact;print-color-adjust:exact;} .docs-export-publication-shell{position:static!important;visibility:visible!important;pointer-events:auto!important;} .docs-export-publication{padding:0!important;background:transparent!important;} .docs-export-cover,.docs-export-toc,.docs-export-doc,.docs-export-branch-break{box-shadow:none!important;} </style>`,"</head>",`<body>${e.outerHTML}</body>`,"</html>"].join("")}function mi(o,t,e,n,s){const i=L("docs-export-doc-header"),a=document.createElement("p");a.className="docs-export-doc-eyebrow",a.textContent=o.kind==="dir"?Si(o,t.path):"Document";const r=document.createElement("div");r.className="docs-export-doc-context";const c=document.createElement("span");c.textContent=o.kind==="dir"?[o.root.projectLabel,se(o.dirPath)||o.root.displayPath].filter(Boolean).join(" / "):e.title.trim();const l=document.createElement("span");l.textContent=`Document ${String(n+1).padStart(2,"0")} of ${s}`;const d=document.createElement("h2");if(d.textContent=t.title,i.append(a,r,d),r.append(c,l),e.includeFilePaths){const h=document.createElement("div");h.className=`docs-export-doc-path${o.kind==="doc"?" docs-export-doc-path-single":""}`,h.textContent=t.path,i.appendChild(h)}return i}function fi(o,t,e){var l;const n=e.showHeaderChrome||e.showFooterChrome,s=qn([e.title.trim(),e.classification.trim()]).join(" / "),i=qn([e.organization.trim(),e.organization.trim().toLowerCase()===o.root.projectLabel.trim().toLowerCase()?"":o.root.projectLabel,Hs(e.publicationDate.trim())]).join(" / "),a=o.kind==="doc"?((l=t[0])==null?void 0:l.title)??e.title.trim():[se(o.dirPath)||o.root.displayPath,`${t.length} ${t.length===1?"doc":"docs"}`].filter(Boolean).join(" / "),r=e.showHeaderChrome?`<div style="width:100%;font:700 10px/1.2 Inter,Arial,sans-serif;color:#707070;letter-spacing:.05em;text-transform:uppercase;padding:0 2mm 3.5mm 2mm;border-bottom:1px solid rgba(0,0,0,.12);display:grid;grid-template-columns:minmax(0,1fr) auto;gap:12px;"><span style="color:#5a5a5a;">${je(s)}</span><span style="text-align:right;color:#777777;">${je(i)}</span></div>`:"<div></div>",c=e.showFooterChrome?`<div style="width:100%;font:700 10px/1.2 Inter,Arial,sans-serif;color:#707070;letter-spacing:.05em;text-transform:uppercase;padding:3.5mm 2mm 0 2mm;border-top:1px solid rgba(0,0,0,.12);display:grid;grid-template-columns:minmax(0,1fr) auto;gap:12px;"><span style="color:#5a5a5a;">${je(a)}</span><span style="text-align:right;color:#777777;">Page <span class="pageNumber"></span> of <span class="totalPages"></span></span></div>`:"<div></div>";return{displayHeaderFooter:n,headerTemplate:r,footerTemplate:c,marginTopMm:e.showHeaderChrome?28:14,marginBottomMm:e.showFooterChrome?20:14}}function gi(o,t,e){const n=document.createElement("section");n.className="docs-export-cover";const s=document.createElement("div");s.className="docs-export-cover-eyebrow",s.textContent=o.kind==="doc"?"Document export":"Directory export";const i=document.createElement("h1");i.textContent=e.title;const a=document.createElement("p");if(a.className="docs-export-cover-subtitle",a.textContent=e.subtitle.trim(),e.logoDataUrl){const l=document.createElement("img");l.className="docs-export-cover-logo",l.src=e.logoDataUrl,l.alt="Publication logo",n.appendChild(l)}const r=L("docs-export-cover-meta"),c=[Ut("Scope",o.kind==="doc"?"Single document":`${t.length} documents compiled`),Ut("Source",`${o.root.projectLabel} / ${o.root.displayPath}`),Ut("Author",e.author.trim()),Ut("Organization",e.organization.trim()),Ut("Date",Hs(e.publicationDate.trim())),Ut("Classification",e.classification.trim())].filter(Boolean);if(n.appendChild(s),n.appendChild(i),a.textContent&&n.appendChild(a),c.length&&(r.append(...c),n.appendChild(r)),e.legalNotice.trim()){const l=document.createElement("p");l.className="docs-export-cover-notice",l.textContent=e.legalNotice.trim(),n.appendChild(l)}return n}function yi(o,t,e){const n=document.createElement("section");n.className="docs-export-toc";const s=document.createElement("h2");s.textContent="Contents";const i=document.createElement("p");i.className="docs-export-toc-note",i.textContent=t.kind==="doc"?"Compiled from the current markdown file.":`${o.length} documents were flattened from the selected directory tree.`;const a=document.createElement("ol");return a.className="docs-export-toc-list",o.forEach((r,c)=>{const l=document.createElement("li"),d=document.createElement("a");d.className="docs-export-toc-row",d.href=`#docs-export-section-${c+1}`;const h=L("docs-export-toc-label"),p=document.createElement("strong");if(p.textContent=r.title,h.appendChild(p),e.includeFilePaths){const f=document.createElement("small");f.textContent=r.path,h.appendChild(f)}const u=document.createElement("span");u.textContent=String(c+1).padStart(2,"0"),d.append(h,u),l.appendChild(d),a.appendChild(l)}),n.append(s,i,a),n}function bi(o){const t=document.createElement("section");t.className="docs-export-branch-break";const e=document.createElement("p");e.className="docs-export-branch-breadcrumb",e.textContent=o.breadcrumb;const n=document.createElement("h2");n.textContent=o.title;const s=L("docs-export-branch-rule");return t.append(e,n,s),t}function vi(){const o=document.createElement("section");o.className="docs-export-empty-publication";const t=document.createElement("h2");t.textContent="No documents selected";const e=document.createElement("p");return e.textContent="Use the Included documents section to choose at least one document for this publication.",o.append(t,e),o}function On(o,t){const e=se(o.dirPath),s=(e&&t.startsWith(`${e}/`)?t.slice(e.length+1):t).split("/").filter(Boolean).slice(0,-1),i=s.join("/");return i?{key:i,breadcrumb:s.slice(0,-1).map(Mt).join(" / ")||o.root.projectLabel,title:Mt(s[s.length-1])}:{key:i,breadcrumb:o.root.projectLabel,title:Mt(En(e)||o.root.displayPath.split("/").pop()||o.root.projectLabel)}}function xi(o,t,e){const n=document.createElement("details");n.className="docs-export-disclosure";const s=document.createElement("summary");s.className="docs-export-disclosure-summary";const i=L("docs-export-disclosure-summary-text"),a=document.createElement("strong");a.textContent="Choose included documents";const r=document.createElement("small");i.append(a,r);const c=document.createElement("span");c.className="docs-export-disclosure-badge",s.append(i,c);const l=L("docs-export-disclosure-body"),d=$t("Search documents","",{placeholder:"Filter by title or path"});d.field.classList.add("docs-export-doc-search");const h=L("docs-export-doc-picker-actions"),p=te("btn docs-export-secondary-btn","Select all"),u=te("btn docs-export-secondary-btn","Clear all");p.addEventListener("click",v=>{v.preventDefault(),o.forEach(S=>t.add(S.path)),w(),e.onSelectionChange()}),u.addEventListener("click",v=>{v.preventDefault(),t.clear(),w(),e.onSelectionChange()}),h.append(p,u);const f=L("docs-export-doc-picker-list"),y=new Map,b=new Map;o.forEach(v=>{const S=document.createElement("label");S.className="docs-export-doc-picker-item",b.set(v.path,S);const x=document.createElement("input");x.type="checkbox",x.checked=!0,x.addEventListener("change",()=>{x.checked?t.add(v.path):t.delete(v.path),w(),e.onSelectionChange()}),y.set(v.path,x);const E=L("docs-export-doc-picker-copy"),M=document.createElement("strong");M.textContent=v.title;const T=document.createElement("small");if(T.textContent=v.path,E.append(M,T),v.summary){const B=document.createElement("p");B.textContent=v.summary,E.appendChild(B)}S.append(x,E),f.appendChild(S)}),d.input.addEventListener("input",()=>w()),l.append(d.field,h,f),n.append(s,l);function w(){const v=o.filter(x=>t.has(x.path)).length,S=_n(d.input.value);r.textContent=`${v} of ${o.length} included`,c.textContent=`${v}`,n.dataset.selectionState=v===0?"empty":v===o.length?"full":"partial",y.forEach((x,E)=>{x.checked=t.has(E);const M=b.get(E);if(!M)return;if(!S){M.hidden=!1;return}const T=o.find(I=>I.path===E),B=_n(`${(T==null?void 0:T.title)??""} ${E}`);M.hidden=!B.includes(S)}),u.disabled=v===0,p.disabled=v===o.length}return w(),{element:n,refresh:w}}function Me(o,t,e){const n=document.createElement("section");n.className="docs-export-studio-section";const s=L("docs-export-studio-section-heading"),i=document.createElement("span");i.textContent=String(o).padStart(2,"0");const a=document.createElement("strong");return a.textContent=t,s.append(i,a),n.appendChild(s),e.forEach(r=>n.appendChild(r)),n}function Ut(o,t){if(!t.trim())return null;const e=L("docs-export-cover-row"),n=document.createElement("span");n.textContent=o;const s=document.createElement("strong");return s.textContent=t,e.append(n,s),e}function Le(o){const t=document.createElement("span");return t.className="docs-export-preview-chip",t.textContent=o,t}function wi(o,t){let e=o;const n=L("docs-export-logo-field"),s=document.createElement("span");s.className="docs-export-logo-field-label",s.textContent="Title page logo";const i=L("docs-export-logo-actions"),a=document.createElement("input");a.type="file",a.accept="image/*",a.hidden=!0;const r=te("btn docs-export-secondary-btn","Upload logo"),c=te("btn docs-export-secondary-btn","Clear"),l=L("docs-export-logo-preview"),d=()=>{if(l.replaceChildren(),e){const h=document.createElement("img");h.src=e,h.alt="Selected logo preview",l.appendChild(h)}else l.textContent="No logo selected";c.disabled=!e};return r.addEventListener("click",()=>a.click()),c.addEventListener("click",()=>{e="",a.value="",d(),t()}),a.addEventListener("change",()=>{var u;const h=(u=a.files)==null?void 0:u[0];if(!h)return;const p=new FileReader;p.onload=()=>{e=typeof p.result=="string"?p.result:"",d(),t()},p.readAsDataURL(h)}),i.append(r,c),n.append(s,i,l,a),d(),{field:n,getValue:()=>e}}function Ci(o,t){const e=se(t);return ki(bn(o)).map(n=>n.path).filter(n=>e?n===e||n.startsWith(`${e}/`):!0)}function bn(o){return o.filter(t=>t.type==="file"?t.name.endsWith(".md"):t.name==="capabilities"||t.name==="assets"?!1:bn(t.children).length>0).map(t=>t.type==="file"?t:{...t,children:bn(t.children)})}function ki(o){const t=[],e=n=>{for(const s of n)s.type==="file"?t.push(s):e(s.children)};return e(o),t}function Ei(o,t){const e=Un(o),n=Un(t);return e.localeCompare(n)||o.localeCompare(t)}function Un(o){return o.split("/").filter(Boolean).map(t=>{const e=t.toLowerCase();if(e==="index.md")return"00000-index";if(e==="readme.md")return"00001-readme";const n=t.match(/^(\d+)/);return`${n?n[1].padStart(5,"0"):"99999"}-${e}`}).join("/")}function Si(o,t){if(o.kind!=="dir")return`${o.root.projectLabel} / ${t}`;const e=se(o.dirPath),s=(e&&t.startsWith(`${e}/`)?t.slice(e.length+1):t).split("/").filter(Boolean).slice(0,-1).map(i=>Mt(i));return s.length?s.join(" / "):e?Mt(En(e)):o.root.projectLabel}function ye(o){return`${Bi(o)}.pdf`}function Ti(o){for(const t of o.split(/\r?\n/)){const e=t.match(/^#{1,6}\s+(.+?)\s*#*\s*$/);if(e!=null&&e[1])return vn(e[1])}return null}function vn(o){return o.replace(/`([^`]+)`/g,"$1").replace(/\*\*([^*]+)\*\*/g,"$1").replace(/__([^_]+)__/g,"$1").replace(/\*([^*]+)\*/g,"$1").replace(/_([^_]+)_/g,"$1").replace(/\[([^\]]+)\]\([^)]+\)/g,"$1").replace(/<[^>]+>/g," ").replace(/\s+/g," ").trim()}function se(o){return o.replace(/^\/+|\/+$/g,"")}function _n(o){return o.toLowerCase().replace(/\s+/g," ").trim()}function Bi(o){return o.trim().replace(/[\\/:*?"<>|]+/g,"-").replace(/\s+/g," ").slice(0,120)||"export"}function zs(o){return o.split("/").pop()??o}function En(o){return se(o).split("/").filter(Boolean).pop()??""}function Mt(o){return o.replace(/\.md$/i,"").replace(/^\d+[-_\s]*/,"").replace(/[-_]+/g," ").replace(/\s+/g," ").trim().replace(/\b\w/g,t=>t.toUpperCase())||o}function Mi(){const o=new Date,t=o.getFullYear(),e=String(o.getMonth()+1).padStart(2,"0"),n=String(o.getDate()).padStart(2,"0");return`${t}-${e}-${n}`}function Hs(o){if(!o)return"";const t=new Date(`${o}T12:00:00Z`);return Number.isNaN(t.getTime())?o:new Intl.DateTimeFormat("en-CA",{timeZone:"UTC",month:"long",day:"numeric",year:"numeric"}).format(t)}function qn(o){const t=new Set,e=[];for(const n of o.map(s=>s.trim()).filter(Boolean)){const s=n.toLowerCase();t.has(s)||(t.add(s),e.push(n))}return e}function Li(o,t){var i;const e=o.split(/\r?\n/);let n=0;for(;n<e.length&&!e[n].trim();)n+=1;const s=(i=e[n])==null?void 0:i.match(/^#\s+(.+?)\s*#*\s*$/);if(!s||vn(s[1]).toLowerCase()!==vn(t).toLowerCase())return o;for(e.splice(n,1);n<e.length&&!e[n].trim();)e.splice(n,1);return e.join(`
|
|
11
|
+
`)}function $t(o,t,e={}){const n=document.createElement("label");n.className="docs-export-field";const s=document.createElement("span");s.textContent=o;const i=document.createElement("input");return i.type=e.type||"text",i.value=t,e.placeholder&&(i.placeholder=e.placeholder),n.append(s,i),{field:n,input:i}}function Ii(o,t,e={}){const n=document.createElement("label");n.className="docs-export-field docs-export-field-textarea";const s=document.createElement("span");s.textContent=o;const i=document.createElement("textarea");return i.rows=4,i.value=t,e.placeholder&&(i.placeholder=e.placeholder),n.append(s,i),{field:n,textarea:i}}function on(o,t,e){const n=document.createElement("label");n.className="docs-export-field";const s=document.createElement("span");s.textContent=o;const i=document.createElement("select");return t.forEach(a=>{const r=document.createElement("option");r.value=a.value,r.textContent=a.label,r.selected=a.value===e,i.appendChild(r)}),n.append(s,i),{field:n,select:i}}function _t(o,t,e){const n=document.createElement("label");n.className="docs-export-checkbox";const s=document.createElement("input");s.type="checkbox",s.checked=t;const i=L("docs-export-checkbox-copy"),a=document.createElement("strong");a.textContent=o;const r=document.createElement("small");return r.textContent=e,i.append(a,r),n.append(s,i),{input:s,wrapper:n}}function L(o){const t=document.createElement("div");return t.className=o,t}function te(o,t){const e=document.createElement("button");return e.className=o,e.type="button",e.textContent=t,e}function Pi(o){return o==="clean"||o==="report"}function $i(o){return o==="A4"||o==="Letter"}function Ri(o){return o==="90"||o==="100"||o==="110"}function Di(){let o="";for(const t of Array.from(document.styleSheets))try{const e=t.cssRules;for(const n of Array.from(e))o+=`${n.cssText}
|
|
12
|
+
`}catch{}return o}function Ai(o,t){const e=URL.createObjectURL(o),n=document.createElement("a");n.href=e,n.download=t,n.click(),URL.revokeObjectURL(e)}function je(o){return o.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/\"/g,""").replace(/'/g,"'")}const Ni=.05,Fi=40,js=1;function A(o,t,e){return{x:(o-e.offsetX)/e.scale,y:(t-e.offsetY)/e.scale}}function Ft(o,t,e){return{x:o*e.scale+e.offsetX,y:t*e.scale+e.offsetY}}function Ws(o){return Math.min(Fi,Math.max(Ni,o))}function be(o,t,e,n){const s=Ws(n),i={x:(t-o.offsetX)/o.scale,y:(e-o.offsetY)/o.scale};o.scale=s,o.offsetX=t-i.x*o.scale,o.offsetY=e-i.y*o.scale}function zi(o,t,e){const n=A(0,0,o),s=A(t,e,o);return{left:n.x,top:n.y,right:s.x,bottom:s.y}}class Hi{constructor(){m(this,"schemaUrl");m(this,"boardId","default-board");m(this,"title","Untitled Board");m(this,"createdAt",Date.now());m(this,"viewport",{offsetX:0,offsetY:0,scale:js});m(this,"theme","light");m(this,"elements",[]);m(this,"elementsById",new Map);m(this,"selectedIds",new Set);m(this,"hoveredId",null);m(this,"sortedCache",null);m(this,"changeListeners",[]);m(this,"renderListeners",[])}onChange(t){this.changeListeners.push(t)}onRenderNeeded(t){this.renderListeners.push(t)}emitChange(){this.sortedCache=null;for(const t of this.changeListeners)t();this.requestRender()}requestRender(){for(const t of this.renderListeners)t()}addElement(t){this.elements.push(t),this.elementsById.set(t.id,t),this.sortedCache=null}removeElement(t){const e=this.elementsById.get(t);if(!e)return;this.elementsById.delete(t);const n=this.elements.indexOf(e);return n>=0&&this.elements.splice(n,1),this.selectedIds.delete(t),this.sortedCache=null,e}getSorted(){return this.sortedCache||(this.sortedCache=[...this.elements].sort((t,e)=>t.zIndex-e.zIndex)),this.sortedCache}invalidateSort(){this.sortedCache=null}maxZIndex(){let t=0;for(const e of this.elements)e.zIndex>t&&(t=e.zIndex);return t}minZIndex(){let t=0;for(const e of this.elements)e.zIndex<t&&(t=e.zIndex);return t}getSelected(){const t=[];for(const e of this.selectedIds){const n=this.elementsById.get(e);n&&t.push(n)}return t}clearSelection(){this.selectedIds.clear()}getVisibleElements(t){const e=[];for(const n of this.getSorted())n.hidden||ji(n,t)&&e.push(n);return e}}function ji(o,t){const e=Math.min(o.x,o.x+o.width),n=Math.max(o.x,o.x+o.width),s=Math.min(o.y,o.y+o.height),i=Math.max(o.y,o.y+o.height);return!(n<t.left||e>t.right||i<t.top||s>t.bottom)}let an=0;function ve(){return an=(an+1)%65535,Date.now().toString(36)+"-"+an.toString(36)+"-"+Math.random().toString(36).slice(2,8)}function _(o,t={}){const e=Date.now();return{id:ve(),type:o,x:0,y:0,width:100,height:100,rotation:0,zIndex:0,locked:!1,hidden:!1,createdAt:e,updatedAt:e,style:{},data:{},...t}}const Xn=200;class Wi{constructor(){m(this,"undoStack",[]);m(this,"redoStack",[])}execute(t,e,n){const s={id:ve(),type:t,timestamp:Date.now(),do:e,undo:n};s.do(),this.undoStack.push(s),this.undoStack.length>Xn&&this.undoStack.shift(),this.redoStack.length=0}push(t,e,n){const s={id:ve(),type:t,timestamp:Date.now(),do:e,undo:n};this.undoStack.push(s),this.undoStack.length>Xn&&this.undoStack.shift(),this.redoStack.length=0}undo(){const t=this.undoStack.pop();return t?(t.undo(),this.redoStack.push(t),!0):!1}redo(){const t=this.redoStack.pop();return t?(t.do(),this.undoStack.push(t),!0):!1}clear(){this.undoStack.length=0,this.redoStack.length=0}}class Oi{constructor(t,e){m(this,"state");m(this,"commands");this.state=t,this.commands=e}deleteSelection(){const t=this.state.getSelected().filter(s=>!s.locked);if(t.length===0)return;const e=this.state,n=t.map(s=>s);this.commands.execute("delete",()=>{for(const s of n)e.removeElement(s.id);e.emitChange()},()=>{for(const s of n)e.elementsById.has(s.id)||e.addElement(s);e.emitChange()})}duplicateSelection(t=24){const e=this.state.getSelected();if(e.length===0)return[];const n=e.map(s=>this.cloneElement(s,t));this.insertElements(n,"duplicate"),this.state.clearSelection();for(const s of n)this.state.selectedIds.add(s.id);return this.state.requestRender(),n}cloneElement(t,e){const n=Date.now();return{...t,id:ve(),x:t.x+e,y:t.y+e,zIndex:this.state.maxZIndex()+1,createdAt:n,updatedAt:n,style:{...t.style},data:{...t.data}}}insertElements(t,e){const n=this.state;this.commands.execute(e,()=>{for(const s of t)n.elementsById.has(s.id)||n.addElement(s);n.emitChange()},()=>{for(const s of t)n.removeElement(s.id);n.emitChange()})}nudgeSelection(t,e){const n=this.state.getSelected().filter(c=>!c.locked);if(n.length===0)return;const s=this.state,i=n.map(c=>({id:c.id,x:c.x,y:c.y,updatedAt:c.updatedAt})),a=n.map(c=>({id:c.id,x:c.x+t,y:c.y+e,updatedAt:Date.now()})),r=c=>{for(const l of c){const d=s.elementsById.get(l.id);d&&(d.x=l.x,d.y=l.y,d.updatedAt=l.updatedAt)}s.emitChange()};this.commands.execute("nudge",()=>r(a),()=>r(i))}applyZChange(t){const e=this.state.getSelected();if(e.length===0)return;const n=this.state,s=e.map(r=>({id:r.id,z:r.zIndex}));for(const r of e)t(r);n.invalidateSort();const i=e.map(r=>({id:r.id,z:r.zIndex})),a=r=>{for(const c of r){const l=n.elementsById.get(c.id);l&&(l.zIndex=c.z)}n.invalidateSort(),n.emitChange()};this.commands.push("layer",()=>a(i),()=>a(s)),n.emitChange()}bringForward(){this.applyZChange(t=>t.zIndex+=1)}sendBackward(){this.applyZChange(t=>t.zIndex-=1)}bringToFront(){let t=this.state.maxZIndex();this.applyZChange(e=>e.zIndex=++t)}sendToBack(){let t=this.state.minZIndex();this.applyZChange(e=>e.zIndex=--t)}}const Ui=["image/png","image/jpeg","image/webp","image/gif"],_i=5*1024*1024;class qi{constructor(t,e,n,s,i){m(this,"state");m(this,"commands");m(this,"imageCache");m(this,"notify");m(this,"uploadImage");m(this,"uploadedImageByHash",new Map);this.state=t,this.commands=e,this.imageCache=n,this.notify=s,this.uploadImage=i}async insertBlob(t,e,n,s){if(!Ui.includes(t.type)){this.notify("Unsupported image type");return}t.size>_i&&this.notify("Large image added — consider optimizing it for git");let i=0,a=0,r=null;try{r=await createImageBitmap(t),i=r.width,a=r.height}catch{this.notify("Could not decode image");return}const c={originalWidth:i,originalHeight:a,alt:s};if(this.uploadImage)try{const b=await this.uploadOrReuseImage(t,s);c.src=b,r&&this.imageCache.setBySrc(b,r)}catch(b){this.notify("Failed to save image to disk"),console.error("Image upload failed",b);return}else try{const b=await pt.createFromBlob(t,s);c.assetId=b.id,r&&this.imageCache.set(b.id,r)}catch(b){this.notify("Failed to store image (storage quota?)"),console.error("Asset store failed",b);return}const l=A(e,n,this.state.viewport),d=480/Math.min(1,this.state.viewport.scale);let h=i,p=a;const u=Math.max(h,p);if(u>d){const b=d/u;h*=b,p*=b}const f=_("image",{x:l.x-h/2,y:l.y-p/2,width:h,height:p,zIndex:this.state.maxZIndex()+1,data:c}),y=this.state;this.commands.execute("insert-image",()=>{y.elementsById.has(f.id)||y.addElement(f),y.emitChange()},()=>{y.removeElement(f.id),y.emitChange()}),y.clearSelection(),y.selectedIds.add(f.id),y.requestRender()}async insertFiles(t,e,n){let s=0;for(const i of Array.from(t))i.type.startsWith("image/")&&(await this.insertBlob(i,e+s,n+s,i.name),s+=24)}async uploadOrReuseImage(t,e){if(!this.uploadImage)throw new Error("Missing uploadImage");const n=await Xi(t),s=this.uploadedImageByHash.get(n);if(s)return s;const i=await this.uploadImage(t,e);return this.uploadedImageByHash.set(n,i),i}}async function Xi(o){const t=await crypto.subtle.digest("SHA-256",await o.arrayBuffer());return Array.from(new Uint8Array(t),e=>e.toString(16).padStart(2,"0")).join("")}const Yn="application/x-viteboard-elements";class Yi{constructor(t,e,n,s){m(this,"state");m(this,"actions");m(this,"imageInsert");m(this,"internalClipboard",[]);m(this,"internalClipboardToken","");m(this,"lastPointer",{x:window.innerWidth/2,y:window.innerHeight/2});this.state=t,this.actions=e,this.imageInsert=n,window.addEventListener("pointermove",i=>{this.lastPointer={x:i.clientX,y:i.clientY}},{signal:s}),window.addEventListener("paste",i=>{this.isEditingText(i.target)||this.handlePaste(i)},{signal:s}),window.addEventListener("copy",i=>{this.isEditingText(i.target)||this.copySelection(i.clipboardData)&&i.preventDefault()},{signal:s}),window.addEventListener("cut",i=>{this.isEditingText(i.target)||this.copySelection(i.clipboardData)&&(this.actions.deleteSelection(),i.preventDefault())},{signal:s})}isEditingText(t){const e=t;return!!e&&(e.tagName==="TEXTAREA"||e.tagName==="INPUT"||e.isContentEditable)}copySelection(t){const e=this.state.getSelected();return e.length===0?!1:(this.internalClipboard=e.map(n=>({...n,style:{...n.style},data:{...n.data}})),this.internalClipboardToken=Date.now().toString(36)+"-"+Math.random().toString(36).slice(2,8),t&&this.writeClipboardPayload(t,e),!0)}async handlePaste(t){const e=t.clipboardData,n=e==null?void 0:e.items,s=e==null?void 0:e.getData("text/plain").trim();if(e&&this.isInternalClipboardPaste(e)){t.preventDefault(),this.pasteInternal();return}if(n){for(const i of n)if(i.type.startsWith("image/")){const a=i.getAsFile();if(a&&!s){t.preventDefault(),await this.imageInsert.insertBlob(a,this.lastPointer.x,this.lastPointer.y,"Pasted screenshot");return}}}if(!e&&this.internalClipboard.length>0){t.preventDefault(),this.pasteInternal();return}s&&(t.preventDefault(),this.pasteText(s))}writeClipboardPayload(t,e){try{t.clearData(),t.setData(Yn,this.internalClipboardToken),t.setData("text/plain",this.selectionText(e))}catch{}}isInternalClipboardPaste(t){const e=t.getData(Yn).trim();return!!e&&e===this.internalClipboardToken&&this.internalClipboard.length>0}selectionText(t){return t.map(n=>typeof n.data.text=="string"?n.data.text.trim():"").filter(Boolean).join(`
|
|
13
|
+
|
|
14
|
+
`)}pasteInternal(){const t=A(this.lastPointer.x,this.lastPointer.y,this.state.viewport);let e=1/0,n=1/0,s=-1/0,i=-1/0;for(const d of this.internalClipboard)e=Math.min(e,Math.min(d.x,d.x+d.width)),n=Math.min(n,Math.min(d.y,d.y+d.height)),s=Math.max(s,Math.max(d.x,d.x+d.width)),i=Math.max(i,Math.max(d.y,d.y+d.height));const a=(e+s)/2,r=(n+i)/2;let c=this.state.maxZIndex();const l=[];for(const d of this.internalClipboard){const h=Ms(d);if(!h)continue;const p=this.actions.cloneElement(h,0);p.x=h.x+(t.x-a),p.y=h.y+(t.y-r),p.zIndex=++c,l.push(p)}if(l.length!==0){this.actions.insertElements(l,"paste"),this.state.clearSelection();for(const d of l)this.state.selectedIds.add(d.id);this.state.requestRender()}}pasteText(t){const e=A(this.lastPointer.x,this.lastPointer.y,this.state.viewport),n=_("text",{x:e.x,y:e.y,width:Math.min(420,Math.max(160,t.length*8)),height:28,zIndex:this.state.maxZIndex()+1,style:{fontSize:16,textColor:this.state.theme==="dark"?"#f2f2f2":"#1f2933"},data:{text:t.slice(0,5e3)}});Nt(n),this.actions.insertElements([n],"paste-text"),this.state.clearSelection(),this.state.selectedIds.add(n.id),this.state.requestRender()}}function Ki(o,t){const{state:e,commands:n,actions:s,toolController:i}=o;window.addEventListener("keydown",a=>{const r=a.target;if(r&&(r.tagName==="TEXTAREA"||r.tagName==="INPUT"||r.isContentEditable))return;const c=a.metaKey||a.ctrlKey,l=a.shiftKey?10:1;if(!c)switch(a.key){case"ArrowLeft":a.preventDefault(),s.nudgeSelection(-l,0);return;case"ArrowRight":a.preventDefault(),s.nudgeSelection(l,0);return;case"ArrowUp":a.preventDefault(),s.nudgeSelection(0,-l);return;case"ArrowDown":a.preventDefault(),s.nudgeSelection(0,l);return}if(c){switch(a.key.toLowerCase()){case"d":a.preventDefault(),s.duplicateSelection();return;case"z":a.preventDefault(),a.shiftKey?n.redo():n.undo();return;case"]":a.preventDefault(),a.shiftKey?s.bringToFront():s.bringForward();return;case"[":a.preventDefault(),a.shiftKey?s.sendToBack():s.sendBackward();return;case"=":case"+":a.preventDefault(),be(e.viewport,window.innerWidth/2,window.innerHeight/2,e.viewport.scale*1.2),e.requestRender();return;case"-":a.preventDefault(),be(e.viewport,window.innerWidth/2,window.innerHeight/2,e.viewport.scale/1.2),e.requestRender();return;case"0":a.preventDefault(),o.resetView();return;case"a":a.preventDefault(),e.clearSelection();for(const d of e.elements)!d.locked&&!d.hidden&&e.selectedIds.add(d.id);e.requestRender();return}return}switch(a.key){case"Delete":case"Backspace":a.preventDefault(),s.deleteSelection();return;case"Escape":i.cancel(),i.setTool("select");return}switch(a.key.toLowerCase()){case"v":i.setTool("select");return;case"h":i.setTool("hand");return;case"s":i.setTool("sticky");return;case"r":i.setTool("rectangle");return;case"o":i.setTool("ellipse");return;case"t":i.setTool(a.shiftKey?"task":"text");return;case"a":i.setTool("arrow");return;case"i":i.setTool("image");return}},{signal:t})}function Vi(o){if(o.elements.length===0)return null;let t=1/0,e=1/0,n=-1/0,s=-1/0;for(const a of o.elements)a.hidden||(t=Math.min(t,Math.min(a.x,a.x+a.width)),e=Math.min(e,Math.min(a.y,a.y+a.height)),n=Math.max(n,Math.max(a.x,a.x+a.width)),s=Math.max(s,Math.max(a.y,a.y+a.height)));if(!Number.isFinite(t))return null;const i=48;return{x:t-i,y:e-i,w:n-t+i*2,h:s-e+i*2}}function Os(o,t,e,n){let i=Math.round(e.w*n),a=Math.round(e.h*n);if(i>8192||a>8192){const h=8192/Math.max(i,a);n*=h,i=Math.round(e.w*n),a=Math.round(e.h*n)}const r=document.createElement("canvas");r.width=Math.max(1,i),r.height=Math.max(1,a);const c=r.getContext("2d"),l=o.theme==="dark"?"#111315":"#f3f2f1";c.fillStyle=l,c.fillRect(0,0,r.width,r.height),c.scale(n,n),c.translate(-e.x,-e.y);const d=o.getSorted();for(const h of d)h.hidden||Math.max(h.x,h.x+h.width)<e.x||Math.min(h.x,h.x+h.width)>e.x+e.w||Math.max(h.y,h.y+h.height)<e.y||Math.min(h.y,h.y+h.height)>e.y+e.h||Oe(h,{ctx:c,scale:n,lod:2,theme:o.theme,imageCache:t});return r}function Us(o){return new Promise((t,e)=>{o.toBlob(n=>{n?t(n):e(new Error("PNG encode failed"))},"image/png")})}async function Gi(o,t,e,n){const s=o.viewport,i={x:-s.offsetX/s.scale,y:-s.offsetY/s.scale,w:e/s.scale,h:n/s.scale},a=Os(o,t,i,s.scale);return Us(a)}async function Zi(o,t){const e=Vi(o);if(!e)return null;const n=Os(o,t,e,1);return Us(n)}function Kn(o,t){const e=URL.createObjectURL(o),n=document.createElement("a");n.href=e,n.download=t,n.click(),URL.revokeObjectURL(e)}class Sn{constructor(t,e){m(this,"overlay");m(this,"rectEl");m(this,"abort",new AbortController);m(this,"start",null);m(this,"onComplete");m(this,"done",!1);this.onComplete=e,this.overlay=document.createElement("div"),this.overlay.className="embed-select-overlay";const n=document.createElement("div");n.className="embed-select-hint",n.textContent="Drag to select the area to embed · Esc to cancel",this.overlay.appendChild(n),this.rectEl=document.createElement("div"),this.rectEl.className="embed-select-rect",this.rectEl.style.display="none",this.overlay.appendChild(this.rectEl),t.appendChild(this.overlay);const s=this.abort.signal;this.overlay.addEventListener("pointerdown",i=>this.onDown(i),{signal:s}),this.overlay.addEventListener("pointermove",i=>this.onMove(i),{signal:s}),this.overlay.addEventListener("pointerup",i=>this.onUp(i),{signal:s}),window.addEventListener("keydown",i=>{i.key==="Escape"&&(i.preventDefault(),this.finish(null))},{signal:s})}static begin(t,e){new Sn(t,e)}onDown(t){t.preventDefault(),this.start={x:t.clientX,y:t.clientY},this.rectEl.style.display="block",this.draw(t.clientX,t.clientY),this.overlay.setPointerCapture(t.pointerId)}onMove(t){this.start&&this.draw(t.clientX,t.clientY)}onUp(t){if(!this.start)return;const e=this.rectFrom(t.clientX,t.clientY);if(e.w<8||e.h<8){this.finish(null);return}this.finish(e)}rectFrom(t,e){const n=this.start;return{x:Math.min(n.x,t),y:Math.min(n.y,e),w:Math.abs(t-n.x),h:Math.abs(e-n.y)}}draw(t,e){const n=this.rectFrom(t,e);this.rectEl.style.left=`${n.x}px`,this.rectEl.style.top=`${n.y}px`,this.rectEl.style.width=`${n.w}px`,this.rectEl.style.height=`${n.h}px`}finish(t){this.done||(this.done=!0,this.abort.abort(),this.overlay.remove(),this.onComplete(t))}}class Ji{constructor(t,e=3,n){m(this,"container");m(this,"layers",[]);m(this,"contexts",[]);m(this,"width",0);m(this,"height",0);m(this,"dpr",1);m(this,"resizeListeners",[]);this.container=document.createElement("div"),this.container.className="canvas-stack",t.appendChild(this.container);for(let s=0;s<e;s++){const i=document.createElement("canvas"),a=i.getContext("2d",{alpha:s!==0});this.container.appendChild(i),this.layers.push(i),this.contexts.push(a)}this.resize(),window.addEventListener("resize",()=>{this.resize();for(const s of this.resizeListeners)s()},{signal:n})}get interactionLayer(){return this.layers[this.layers.length-1]}onResize(t){this.resizeListeners.push(t)}resize(){this.dpr=Math.max(1,window.devicePixelRatio||1),this.width=window.innerWidth,this.height=window.innerHeight;for(const t of this.layers)t.width=Math.round(this.width*this.dpr),t.height=Math.round(this.height*this.dpr),t.style.width=this.width+"px",t.style.height=this.height+"px"}beginLayer(t){const e=this.contexts[t];return e.setTransform(this.dpr,0,0,this.dpr,0,0),e.clearRect(0,0,this.width,this.height),e}}class Qi{constructor(t,e,n){m(this,"surface");m(this,"state");m(this,"imageCache");m(this,"overlay",{marquee:null,preview:null});m(this,"lastRenderMs",0);m(this,"visibleCount",0);m(this,"cullingEnabled",!0);m(this,"lodEnabled",!0);this.surface=t,this.state=e,this.imageCache=n}getLod(){if(!this.lodEnabled)return 2;const t=this.state.viewport.scale;return t<.1?0:t<.25?1:2}render(){const t=performance.now();this.renderGrid(),this.renderObjects(),this.renderOverlay(),this.lastRenderMs=performance.now()-t}renderGrid(){const{surface:t,state:e}=this,n=t.beginLayer(0),s=e.viewport,i=getComputedStyle(document.documentElement).getPropertyValue("--bg-canvas").trim(),a=getComputedStyle(document.documentElement).getPropertyValue("--grid-dot").trim();n.fillStyle=i||"#f3f2f1",n.fillRect(0,0,t.width,t.height);let c=32*s.scale;if(!Number.isFinite(c)||c<=0)return;for(;c<16;)c*=2;for(;c>64;)c/=2;if(c<4)return;const l=(s.offsetX%c+c)%c,d=(s.offsetY%c+c)%c,h=Math.min(1.5,Math.max(.75,s.scale*.9));n.fillStyle=a||"rgba(0,0,0,0.14)",n.beginPath();for(let p=l;p<t.width;p+=c)for(let u=d;u<t.height;u+=c)n.moveTo(p+h,u),n.arc(p,u,h,0,Math.PI*2);n.fill()}renderObjects(){const{surface:t,state:e}=this,n=t.beginLayer(1),s=e.viewport;n.translate(s.offsetX,s.offsetY),n.scale(s.scale,s.scale);const i=zi(s,t.width,t.height),a=this.cullingEnabled?e.getVisibleElements(i):e.getSorted().filter(c=>!c.hidden);this.visibleCount=a.length;const r={ctx:n,scale:s.scale,lod:this.getLod(),theme:e.theme,imageCache:this.imageCache};for(const c of a)Oe(c,r)}renderOverlay(){const{surface:t,state:e}=this,n=t.beginLayer(2),s=e.viewport,i=getComputedStyle(document.documentElement).getPropertyValue("--selection").trim()||"#6e6e6e";if(e.hoveredId&&!e.selectedIds.has(e.hoveredId)){const r=e.elementsById.get(e.hoveredId);if(r){const c=this.elementScreenBBox(r);n.strokeStyle=i,n.globalAlpha=.45,n.lineWidth=1.5,n.strokeRect(c.x,c.y,c.w,c.h),n.globalAlpha=1}}const a=e.getSelected();if(a.length>0){n.strokeStyle=i,n.lineWidth=1.5;let r=1/0,c=1/0,l=-1/0,d=-1/0;for(const p of a){const u=this.elementScreenBBox(p);n.strokeRect(u.x,u.y,u.w,u.h),r=Math.min(r,u.x),c=Math.min(c,u.y),l=Math.max(l,u.x+u.w),d=Math.max(d,u.y+u.h)}a.length>1&&(n.setLineDash([4,4]),n.strokeRect(r-4,c-4,l-r+8,d-c+8),n.setLineDash([]));const h=a.length===1?this.elementScreenBBox(a[0]):{x:r,y:c,w:l-r,h:d-c};this.drawHandles(n,h,i)}if(this.overlay.marquee){const r=this.overlay.marquee;n.fillStyle=i+"22",n.strokeStyle=i,n.lineWidth=1,n.fillRect(r.x,r.y,r.w,r.h),n.strokeRect(r.x,r.y,r.w,r.h)}this.overlay.preview&&(n.save(),n.translate(s.offsetX,s.offsetY),n.scale(s.scale,s.scale),n.globalAlpha=.8,Oe(this.overlay.preview,{ctx:n,scale:s.scale,lod:2,theme:e.theme,imageCache:this.imageCache}),n.restore())}elementScreenBBox(t){const e=this.state.viewport,n=Math.min(t.x,t.x+t.width),s=Math.min(t.y,t.y+t.height),i=Math.max(t.x,t.x+t.width),a=Math.max(t.y,t.y+t.height),r=Ft(n,s,e),c=Ft(i,a,e);return{x:r.x,y:r.y,w:c.x-r.x,h:c.y-r.y}}drawHandles(t,e,n){const a=_s(e);t.fillStyle=getComputedStyle(document.documentElement).getPropertyValue("--bg-panel").trim()||"#fff",t.strokeStyle=n,t.lineWidth=1.5;for(const r of a)t.beginPath(),t.rect(r.x-4,r.y-4,8,8),t.fill(),t.stroke()}}function _s(o){const{x:t,y:e,w:n,h:s}=o;return[{id:"nw",x:t,y:e},{id:"n",x:t+n/2,y:e},{id:"ne",x:t+n,y:e},{id:"e",x:t+n,y:e+s/2},{id:"se",x:t+n,y:e+s},{id:"s",x:t+n/2,y:e+s},{id:"sw",x:t,y:e+s},{id:"w",x:t,y:e+s/2}]}class ta{constructor(t){m(this,"rafId",null);m(this,"renderFn");this.renderFn=t}requestRender(){this.rafId===null&&(this.rafId=requestAnimationFrame(()=>{this.rafId=null,this.renderFn()}))}cancel(){this.rafId!==null&&(cancelAnimationFrame(this.rafId),this.rafId=null)}}function ea(o,t,e,n,s,i){const a=s-e,r=i-n,c=a*a+r*r;if(c===0)return Math.hypot(o-e,t-n);let l=((o-e)*a+(t-n)*r)/c;return l=Math.max(0,Math.min(1,l)),Math.hypot(o-(e+l*a),t-(n+l*r))}class na{constructor(t){m(this,"state");m(this,"lastHitTestMs",0);this.state=t}hitTest(t,e,n){const s=performance.now(),i=this.state.getSorted(),a=6/n;let r=null;for(let c=i.length-1;c>=0;c--){const l=i[c];if(!(l.hidden||l.locked)&&this.hitsElement(l,t,e,a)){r=l;break}}return this.lastHitTestMs=performance.now()-s,r}hitsElement(t,e,n,s){if(t.type==="line"||t.type==="arrow"||t.type==="connector")return ea(e,n,t.x,t.y,t.x+t.width,t.y+t.height)<=Math.max(s,(t.style.strokeWidth??2)/2+s);const i=Math.min(t.x,t.x+t.width),a=Math.max(t.x,t.x+t.width),r=Math.min(t.y,t.y+t.height),c=Math.max(t.y,t.y+t.height);if(e<i||e>a||n<r||n>c)return!1;if(t.type==="ellipse"){const l=(i+a)/2,d=(r+c)/2,h=(a-i)/2,p=(c-r)/2;if(h===0||p===0)return!1;const u=(e-l)/h,f=(n-d)/p;return u*u+f*f<=1}return!0}elementsInRect(t,e,n,s){const i=Math.min(t,t+n),a=Math.max(t,t+n),r=Math.min(e,e+s),c=Math.max(e,e+s),l=[];for(const d of this.state.elements){if(d.hidden||d.locked)continue;const h=Math.min(d.x,d.x+d.width),p=Math.max(d.x,d.x+d.width),u=Math.min(d.y,d.y+d.height),f=Math.max(d.y,d.y+d.height);h>=i&&p<=a&&u>=r&&f<=c&&l.push(d)}return l}}class sa{constructor(){m(this,"fps",0);m(this,"frameCount",0);m(this,"lastSample",performance.now());m(this,"running",!1)}start(){if(this.running)return;this.running=!0;const t=()=>{if(!this.running)return;this.frameCount++;const e=performance.now(),n=e-this.lastSample;n>=1e3&&(this.fps=Math.round(this.frameCount*1e3/n),this.frameCount=0,this.lastSample=e),requestAnimationFrame(t)};requestAnimationFrame(t)}stop(){this.running=!1}}const oa=16,ia=720,Vn=120,aa=.0032;class ra{constructor(t,e,n,s){m(this,"tools",new Map);m(this,"active");m(this,"ctx");m(this,"target");m(this,"spaceDown",!1);m(this,"tempPanning",!1);m(this,"panLast",{x:0,y:0});m(this,"toolChangeListeners",[]);m(this,"signal");this.target=t,this.ctx=e,this.signal=s;for(const i of n)this.tools.set(i.name,i);this.active=this.tools.get("select"),this.bindEvents()}get activeName(){return this.active.name}onToolChange(t){this.toolChangeListeners.push(t)}setTool(t){var n,s,i,a,r;if(this.active.name===t){(s=(n=this.active).onActivate)==null||s.call(n,this.ctx);return}(a=(i=this.active).onDeactivate)==null||a.call(i,this.ctx);const e=this.tools.get(t);if(e){this.active=e,this.ctx.setCursor(e.cursor),(r=e.onActivate)==null||r.call(e,this.ctx);for(const c of this.toolChangeListeners)c(t)}}cancel(){var t,e;(e=(t=this.active).onCancel)==null||e.call(t,this.ctx)}bindEvents(){const t=this.target;t.addEventListener("pointerdown",e=>{if(e.button===1||e.button===2||this.spaceDown){e.preventDefault(),this.tempPanning=!0,this.panLast={x:e.clientX,y:e.clientY},this.ctx.setCursor("grabbing"),t.setPointerCapture(e.pointerId);return}e.button===0&&(t.setPointerCapture(e.pointerId),this.active.onPointerDown(e,this.ctx))}),t.addEventListener("pointermove",e=>{if(this.tempPanning){const n=this.ctx.state.viewport;n.offsetX+=e.clientX-this.panLast.x,n.offsetY+=e.clientY-this.panLast.y,this.panLast={x:e.clientX,y:e.clientY},this.ctx.state.requestRender();return}this.active.onPointerMove(e,this.ctx)}),t.addEventListener("pointerup",e=>{if(this.tempPanning){this.tempPanning=!1,this.ctx.setCursor(this.spaceDown?"grab":this.active.cursor);return}this.active.onPointerUp(e,this.ctx)}),t.addEventListener("pointercancel",()=>{this.tempPanning&&(this.tempPanning=!1,this.ctx.setCursor(this.spaceDown?"grab":this.active.cursor))}),t.addEventListener("dblclick",e=>{var n,s;(s=(n=this.active).onDoubleClick)==null||s.call(n,e,this.ctx)}),t.addEventListener("wheel",e=>{e.preventDefault();const n=this.ctx.state.viewport,s=Gn(e.deltaX,e.deltaMode,this.ctx.state.viewport.scale),i=Gn(e.deltaY,e.deltaMode,this.ctx.state.viewport.scale);if(e.ctrlKey||e.metaKey){const a=Math.exp(-ca(i)*aa);be(n,e.clientX,e.clientY,n.scale*a)}else e.shiftKey&&Math.abs(s)<Math.abs(i)?n.offsetX-=i:(n.offsetX-=s,n.offsetY-=i);this.ctx.state.requestRender()},{passive:!1}),window.addEventListener("keydown",e=>{e.code==="Space"&&!this.isEditingText(e)&&(this.spaceDown||(this.spaceDown=!0,this.tempPanning||this.ctx.setCursor("grab")),e.preventDefault())},{signal:this.signal}),window.addEventListener("keyup",e=>{e.code==="Space"&&(this.spaceDown=!1,this.tempPanning||this.ctx.setCursor(this.active.cursor))},{signal:this.signal}),t.addEventListener("contextmenu",e=>e.preventDefault())}isEditingText(t){const e=t.target;return!!e&&(e.tagName==="TEXTAREA"||e.tagName==="INPUT"||e.isContentEditable)}}function Gn(o,t,e){const s=o*(t===1?oa:t===2?ia:1),i=e<.5?.8:e>2?1.08:1;return s*i}function ca(o){return Math.max(-Vn,Math.min(Vn,o))}const Ie=7,la={nw:"nwse-resize",n:"ns-resize",ne:"nesw-resize",e:"ew-resize",se:"nwse-resize",s:"ns-resize",sw:"nesw-resize",w:"ew-resize"};class da{constructor(){m(this,"name","select");m(this,"cursor","default");m(this,"mode","none");m(this,"startScreen",{x:0,y:0});m(this,"startWorld",{x:0,y:0});m(this,"snapshots",[]);m(this,"activeHandle",null);m(this,"endpointIsStart",!1);m(this,"moved",!1);m(this,"pointerDownHitId",null)}onPointerDown(t,e){const{state:n,hitTester:s,renderer:i}=e;this.startScreen={x:t.clientX,y:t.clientY},this.startWorld=A(t.clientX,t.clientY,n.viewport),this.moved=!1;const a=this.hitHandle(t,e);if(a){this.mode="resize",this.activeHandle=a,this.takeSnapshots(n.getSelected());return}const r=n.getSelected();if(r.length===1&&this.isLinear(r[0])){const l=this.hitEndpoint(t,r[0],e);if(l!==null){this.mode="endpoint",this.endpointIsStart=l,this.takeSnapshots(r);return}}const c=s.hitTest(this.startWorld.x,this.startWorld.y,n.viewport.scale);if(c){this.pointerDownHitId=c.id,t.shiftKey?n.selectedIds.has(c.id)?n.selectedIds.delete(c.id):n.selectedIds.add(c.id):n.selectedIds.has(c.id)||(n.clearSelection(),n.selectedIds.add(c.id)),this.mode="move",this.takeSnapshots(n.getSelected()),n.requestRender();return}t.shiftKey||n.clearSelection(),this.mode="marquee",i.overlay.marquee={x:t.clientX,y:t.clientY,w:0,h:0},n.requestRender()}onPointerMove(t,e){const{state:n,renderer:s,hitTester:i}=e;if(this.mode==="none"){const d=this.hitHandle(t,e);if(d){e.setCursor(la[d]);return}const h=A(t.clientX,t.clientY,n.viewport),p=i.hitTest(h.x,h.y,n.viewport.scale),u=p?p.id:null;e.setCursor(p?"move":"default"),u!==n.hoveredId&&(n.hoveredId=u,n.requestRender());return}const a=t.clientX-this.startScreen.x,r=t.clientY-this.startScreen.y;Math.abs(a)+Math.abs(r)>2&&(this.moved=!0);const c=a/n.viewport.scale,l=r/n.viewport.scale;if(this.mode==="move"){for(const d of this.snapshots){const h=n.elementsById.get(d.id);!h||h.locked||(h.x=d.x+c,h.y=d.y+l)}n.requestRender()}else if(this.mode==="marquee")s.overlay.marquee={x:this.startScreen.x,y:this.startScreen.y,w:a,h:r},n.requestRender();else if(this.mode==="resize"&&this.activeHandle)this.applyResize(c,l,t.shiftKey,e),n.requestRender();else if(this.mode==="endpoint"){const d=this.snapshots[0],h=n.elementsById.get(d.id);h&&(this.endpointIsStart?(h.x=d.x+c,h.y=d.y+l,h.width=d.width-c,h.height=d.height-l):(h.width=d.width+c,h.height=d.height+l)),n.requestRender()}}onPointerUp(t,e){const{state:n,renderer:s,hitTester:i,commands:a}=e;if(this.mode==="marquee"){const r=s.overlay.marquee;if(s.overlay.marquee=null,r&&(Math.abs(r.w)>3||Math.abs(r.h)>3)){const c=A(r.x,r.y,n.viewport),l=A(r.x+r.w,r.y+r.h,n.viewport),d=i.elementsInRect(c.x,c.y,l.x-c.x,l.y-c.y);for(const h of d)n.selectedIds.add(h.id)}n.requestRender()}else if((this.mode==="move"||this.mode==="resize"||this.mode==="endpoint")&&this.moved){const r=this.snapshots,c=r.map(d=>{const h=n.elementsById.get(d.id);return{id:d.id,x:h.x,y:h.y,width:h.width,height:h.height}}),l=d=>{for(const h of d){const p=n.elementsById.get(h.id);p&&(p.x=h.x,p.y=h.y,p.width=h.width,p.height=h.height,p.updatedAt=Date.now(),G(p.id))}n.emitChange()};for(const d of c){const h=n.elementsById.get(d.id);h&&(h.updatedAt=Date.now(),G(h.id))}a.push(this.mode,()=>l(c),()=>l(r)),n.emitChange()}else this.mode==="move"&&!this.moved&&this.toggleTaskIfCheckboxClick(t,e);this.mode="none",this.activeHandle=null,this.snapshots=[],this.pointerDownHitId=null}onDoubleClick(t,e){const{state:n,hitTester:s}=e,i=A(t.clientX,t.clientY,n.viewport),a=s.hitTest(i.x,i.y,n.viewport.scale);a&&(a.type==="sticky"||a.type==="task"||a.type==="text"||a.type==="rectangle"||a.type==="ellipse"||a.type==="frame"||a.type==="arrow"||a.type==="line"||a.type==="connector")&&e.openTextEditor(a)}onCancel(t){if(this.mode!=="none"&&this.snapshots.length>0)for(const e of this.snapshots){const n=t.state.elementsById.get(e.id);n&&(n.x=e.x,n.y=e.y,n.width=e.width,n.height=e.height)}t.renderer.overlay.marquee=null,this.mode="none",t.state.clearSelection(),t.state.requestRender()}isLinear(t){return t.type==="line"||t.type==="arrow"||t.type==="connector"}takeSnapshots(t){this.snapshots=t.map(e=>({id:e.id,x:e.x,y:e.y,width:e.width,height:e.height}))}toggleTaskIfCheckboxClick(t,e){const{state:n,hitTester:s,commands:i}=e,a=A(t.clientX,t.clientY,n.viewport),r=s.hitTest(a.x,a.y,n.viewport.scale);if(!r||r.id!==this.pointerDownHitId||r.type!=="task"||!this.hitTaskCheckbox(a.x,a.y,r))return;const c=r.data.checked===!0,l=!c,d=r.id,h=p=>{const u=n.elementsById.get(d);u&&(u.data.checked=p,u.updatedAt=Date.now(),n.emitChange())};i.execute("toggle-task",()=>h(l),()=>h(c))}hitTaskCheckbox(t,e,n){const s=Math.min(22,Math.max(16,n.height*.38)),i=n.x+16,a=n.y+n.height/2-s/2,r=8;return t>=i-r&&t<=i+s+r&&e>=a-r&&e<=a+s+r}hitHandle(t,e){const{state:n,renderer:s}=e,i=n.getSelected();if(i.length===0||i.length===1&&this.isLinear(i[0]))return null;let a;if(i.length===1)a=s.elementScreenBBox(i[0]);else{let r=1/0,c=1/0,l=-1/0,d=-1/0;for(const h of i){const p=s.elementScreenBBox(h);r=Math.min(r,p.x),c=Math.min(c,p.y),l=Math.max(l,p.x+p.w),d=Math.max(d,p.y+p.h)}a={x:r,y:c,w:l-r,h:d-c}}for(const r of _s(a))if(Math.abs(t.clientX-r.x)<=Ie&&Math.abs(t.clientY-r.y)<=Ie)return r.id;return null}hitEndpoint(t,e,n){const s=n.state.viewport,i=e.x*s.scale+s.offsetX,a=e.y*s.scale+s.offsetY,r=(e.x+e.width)*s.scale+s.offsetX,c=(e.y+e.height)*s.scale+s.offsetY;return Math.hypot(t.clientX-i,t.clientY-a)<=Ie+2?!0:Math.hypot(t.clientX-r,t.clientY-c)<=Ie+2?!1:null}applyResize(t,e,n,s){const{state:i}=s,a=this.activeHandle;let r=1/0,c=1/0,l=-1/0,d=-1/0;for(const x of this.snapshots)r=Math.min(r,Math.min(x.x,x.x+x.width)),c=Math.min(c,Math.min(x.y,x.y+x.height)),l=Math.max(l,Math.max(x.x,x.x+x.width)),d=Math.max(d,Math.max(x.y,x.y+x.height));const h=l-r,p=d-c;if(h===0||p===0)return;let u=r,f=c,y=h,b=p;if(a.includes("e")&&(y=h+t),a.includes("w")&&(u=r+t,y=h-t),a.includes("s")&&(b=p+e),a.includes("n")&&(f=c+e,b=p-e),n&&(a==="nw"||a==="ne"||a==="se"||a==="sw")){const x=h/p;if(Math.abs(y/h)>Math.abs(b/p)){const E=y/x;a.includes("n")&&(f=f+(b-E)),b=E}else{const E=b*x;a.includes("w")&&(u=u+(y-E)),y=E}}const w=4;if(Math.abs(y)<w||Math.abs(b)<w)return;const v=y/h,S=b/p;for(const x of this.snapshots){const E=i.elementsById.get(x.id);!E||E.locked||(E.x=u+(x.x-r)*v,E.y=f+(x.y-c)*S,E.width=x.width*v,E.height=x.height*S,E.updatedAt=Date.now(),G(E.id))}}}class ha{constructor(){m(this,"name","hand");m(this,"cursor","grab");m(this,"panning",!1);m(this,"last",{x:0,y:0})}onPointerDown(t,e){this.panning=!0,this.last={x:t.clientX,y:t.clientY},e.setCursor("grabbing")}onPointerMove(t,e){if(!this.panning)return;const n=e.state.viewport;n.offsetX+=t.clientX-this.last.x,n.offsetY+=t.clientY-this.last.y,this.last={x:t.clientX,y:t.clientY},e.state.requestRender()}onPointerUp(t,e){this.panning=!1,e.setCursor("grab")}onCancel(t){this.panning=!1,t.setCursor("grab")}}const Ue=["#fef08a","#fdba74","#fca5a5","#f9a8d4","#d8b4fe","#a5b4fc","#93c5fd","#86efac"];let qs=Ue[0];function pa(){return qs}function ua(o){qs=o}class ma{constructor(){m(this,"name","sticky");m(this,"cursor","crosshair")}onPointerDown(t,e){const{state:n,commands:s}=e,i=A(t.clientX,t.clientY,n.viewport),a=_("sticky",{x:i.x-110,y:i.y-80,width:220,height:160,zIndex:n.maxZIndex()+1,style:{fill:pa(),borderRadius:12,shadow:!0,fontSize:15,textColor:"#1f2933"},data:{text:""}});s.execute("create-sticky",()=>{n.elementsById.has(a.id)||n.addElement(a),n.emitChange()},()=>{n.removeElement(a.id),n.emitChange()}),n.clearSelection(),n.selectedIds.add(a.id),e.setTool("select"),e.openTextEditor(a)}onPointerMove(t,e){}onPointerUp(t,e){}}class fa{constructor(){m(this,"name","task");m(this,"cursor","crosshair")}onPointerDown(t,e){const{state:n,commands:s}=e,i=A(t.clientX,t.clientY,n.viewport),a=n.theme==="dark",r=_("task",{x:i.x-140,y:i.y-28,width:280,height:56,zIndex:n.maxZIndex()+1,style:{fill:a?"#17191b":"#ffffff",stroke:a?"rgba(255,255,255,0.12)":"rgba(0,0,0,0.09)",strokeWidth:1,borderRadius:14,shadow:!0,fontSize:15,fontWeight:"650",textColor:a?"#f6f6f3":"#252829"},data:{text:"Task title",checked:!1}});s.execute("create-task",()=>{n.elementsById.has(r.id)||n.addElement(r),n.emitChange()},()=>{n.removeElement(r.id),n.emitChange()}),n.clearSelection(),n.selectedIds.add(r.id),e.setTool("select"),e.openTextEditor(r)}onPointerMove(t,e){}onPointerUp(t,e){}}class mt{constructor(t){m(this,"name");m(this,"cursor","crosshair");m(this,"shapeType");m(this,"shapeKind");m(this,"drawing",!1);m(this,"startWorld",{x:0,y:0});m(this,"preview",null);this.name=t,this.shapeKind=t,this.shapeType=t==="ellipse"?"ellipse":"rectangle"}onPointerDown(t,e){const{state:n}=e;this.drawing=!0,this.startWorld=A(t.clientX,t.clientY,n.viewport);const s=n.theme==="dark",i=!["rectangle","ellipse","pill","cylinder"].includes(this.shapeKind);this.preview=_(this.shapeType,{x:this.startWorld.x,y:this.startWorld.y,width:0,height:0,zIndex:n.maxZIndex()+1,style:{fill:i?"#0078d4":s?"#2a2d33":"#ffffff",stroke:i?"#495057":s?"#9ca3af":"#374151",strokeWidth:i?0:1.5,borderRadius:this.shapeKind==="pill"?999:this.shapeKind==="rectangle"?8:0,fontSize:14,textColor:i?"#ffffff":s?"#f2f2f2":"#1f2933"},data:{text:"",shapeKind:this.shapeKind}}),e.renderer.overlay.preview=this.preview}onPointerMove(t,e){if(!this.drawing||!this.preview)return;const n=A(t.clientX,t.clientY,e.state.viewport);let s=n.x-this.startWorld.x,i=n.y-this.startWorld.y;if(t.shiftKey){const a=Math.max(Math.abs(s),Math.abs(i));s=Math.sign(s||1)*a,i=Math.sign(i||1)*a}this.preview.x=Math.min(this.startWorld.x,this.startWorld.x+s),this.preview.y=Math.min(this.startWorld.y,this.startWorld.y+i),this.preview.width=Math.abs(s),this.preview.height=Math.abs(i),e.state.requestRender()}onPointerUp(t,e){const{state:n,commands:s}=e;if(!this.drawing||!this.preview)return;this.drawing=!1,e.renderer.overlay.preview=null;const i=this.preview;this.preview=null,(i.width<4||i.height<4)&&(i.width=this.shapeKind==="chevron"?210:160,i.height=this.shapeKind==="chevron"?76:100,i.x-=i.width/2,i.y-=i.height/2),s.execute("create-shape",()=>{n.elementsById.has(i.id)||n.addElement(i),n.emitChange()},()=>{n.removeElement(i.id),n.emitChange()}),n.clearSelection(),n.selectedIds.add(i.id),e.setTool("select")}onCancel(t){this.drawing=!1,this.preview=null,t.renderer.overlay.preview=null,t.state.requestRender()}}class ga{constructor(){m(this,"name","text");m(this,"cursor","text")}onPointerDown(t,e){const{state:n,commands:s}=e,i=A(t.clientX,t.clientY,n.viewport),a=_("text",{x:i.x,y:i.y-12,width:240,height:28,zIndex:n.maxZIndex()+1,style:{fontSize:16,textColor:n.theme==="dark"?"#f2f2f2":"#1f2933"},data:{text:""}});Nt(a),s.execute("create-text",()=>{n.elementsById.has(a.id)||n.addElement(a),n.emitChange()},()=>{n.removeElement(a.id),n.emitChange()}),n.clearSelection(),n.selectedIds.add(a.id),e.setTool("select"),e.openTextEditor(a)}onPointerMove(t,e){}onPointerUp(t,e){}}class le{constructor(t="arrow"){m(this,"name");m(this,"cursor","crosshair");m(this,"drawing",!1);m(this,"startWorld",{x:0,y:0});m(this,"preview",null);this.name=t}onPointerDown(t,e){const{state:n}=e;this.drawing=!0,this.startWorld=A(t.clientX,t.clientY,n.viewport),this.preview=_("arrow",{x:this.startWorld.x,y:this.startWorld.y,width:0,height:0,zIndex:n.maxZIndex()+1,style:{stroke:n.theme==="dark"?"#d1d5db":"#374151",strokeWidth:2,arrowEnd:!0,arrowStart:this.name==="twoWayArrow",strokeDash:this.name==="dashedArrow"||t.altKey?[8,6]:void 0},data:{text:"",labelPosition:this.name==="sidedLabelArrow"?"sides":"center"}}),e.renderer.overlay.preview=this.preview}onPointerMove(t,e){if(!this.drawing||!this.preview)return;const n=A(t.clientX,t.clientY,e.state.viewport);let s=n.x-this.startWorld.x,i=n.y-this.startWorld.y;if(t.shiftKey){const a=Math.atan2(i,s),r=Math.round(a/(Math.PI/4))*(Math.PI/4),c=Math.hypot(s,i);s=Math.cos(r)*c,i=Math.sin(r)*c}this.preview.width=s,this.preview.height=i,e.state.requestRender()}onPointerUp(t,e){const{state:n,commands:s}=e;if(!this.drawing||!this.preview)return;this.drawing=!1,e.renderer.overlay.preview=null;const i=this.preview;if(this.preview=null,Math.hypot(i.width,i.height)<8){n.requestRender();return}s.execute("create-arrow",()=>{n.elementsById.has(i.id)||n.addElement(i),n.emitChange()},()=>{n.removeElement(i.id),n.emitChange()}),n.clearSelection(),n.selectedIds.add(i.id),e.setTool("select"),(this.name==="labeledArrow"||this.name==="sidedLabelArrow")&&e.openTextEditor(i)}onCancel(t){this.drawing=!1,this.preview=null,t.renderer.overlay.preview=null,t.state.requestRender()}}class ya{constructor(t){m(this,"name","image");m(this,"cursor","default");m(this,"onInsert");this.onInsert=t}onActivate(t){const e=document.createElement("input");e.type="file",e.accept="image/png,image/jpeg,image/webp,image/gif",e.multiple=!0,e.onchange=()=>{e.files&&e.files.length>0&&this.onInsert(e.files,window.innerWidth/2,window.innerHeight/2),t.setTool("select")},e.oncancel=()=>t.setTool("select"),e.click()}onPointerDown(t,e){}onPointerMove(t,e){}onPointerUp(t,e){}}const Pe="psc:";class ba{constructor(){m(this,"lastSaveMs",0)}async saveBoard(t){const e=performance.now();try{await nt.put("boards",t),this.lastSaveMs=performance.now()-e,this.setPref("lastBoardId",t.id),this.setPref("recovery",JSON.stringify({id:t.id,title:t.title,updatedAt:t.updatedAt,elementCount:t.elements.length}))}catch(n){throw console.error("Board save failed",n),n}}async loadBoard(t){try{return await nt.get("boards",t)}catch(e){console.error("Board load failed",e);return}}async deleteBoard(t){await nt.delete("boards",t)}async clearAllBoards(){await nt.clearStore("boards")}async getAllBoards(){try{return await nt.getAll("boards")}catch{return[]}}setPref(t,e){try{localStorage.setItem(Pe+t,e)}catch{}}getPref(t){try{return localStorage.getItem(Pe+t)}catch{return null}}removePref(t){try{localStorage.removeItem(Pe+t)}catch{}}clearPrefs(){try{const t=[];for(let e=0;e<localStorage.length;e++){const n=localStorage.key(e);n&&n.startsWith(Pe)&&t.push(n)}for(const e of t)localStorage.removeItem(e)}catch{}}async estimateStorage(){try{if(navigator.storage&&navigator.storage.estimate){const t=await navigator.storage.estimate();return{usage:t.usage??0,quota:t.quota??0}}}catch{}return{usage:0,quota:0}}}const ct=new ba;function va(o){return new Promise((t,e)=>{const n=new FileReader;n.onload=()=>{const s=n.result;t(s.slice(s.indexOf(",")+1))},n.onerror=()=>e(n.error),n.readAsDataURL(o)})}function xa(o,t){const e=atob(o),n=new Uint8Array(e.length);for(let s=0;s<e.length;s++)n[s]=e.charCodeAt(s);return new Blob([n],{type:t})}function Zn(o,t){const e=new Blob([JSON.stringify(t)],{type:"application/json"}),n=URL.createObjectURL(e),s=document.createElement("a");s.href=n,s.download=o,s.click(),URL.revokeObjectURL(n)}function Jn(o){return o.replace(/[^a-z0-9-_ ]/gi,"").trim().slice(0,60)||"board"}class wa{exportBoardJson(t){Zn(`${Jn(t.title)}.json`,t)}async exportFullBundle(t){const e=[];for(const s of t.assetIds){const i=await pt.get(s);i&&e.push({id:i.id,mimeType:i.mimeType,width:i.width,height:i.height,name:i.name,base64:await va(i.blob)})}const n={bundleVersion:1,board:t,assets:e};Zn(`${Jn(t.title)}-bundle.json`,n)}async importFromFile(t){let e;try{e=JSON.parse(await t.text())}catch{return null}if(typeof e!="object"||e===null)return null;const n=e;if(n.bundleVersion===1&&Array.isArray(n.assets)){const s=We(n.board);if(!s)return null;const i=new Map;for(const a of n.assets){const r=await this.importAsset(a);r&&i.set(r.originalId,r.asset.id)}for(const a of s.elements){const r=a.data.assetId;typeof r=="string"&&i.has(r)&&(a.data.assetId=i.get(r))}return s.assetIds=[...i.values()],s}return We(e)}async importAsset(t){if(typeof t!="object"||t===null)return null;const e=t;if(typeof e.id!="string"||typeof e.base64!="string"||typeof e.mimeType!="string"||!e.mimeType.startsWith("image/"))return null;try{const n=xa(e.base64,e.mimeType),s=Date.now(),i={id:ve(),type:"image",mimeType:e.mimeType,blob:n,width:typeof e.width=="number"?e.width:0,height:typeof e.height=="number"?e.height:0,sizeBytes:n.size,createdAt:s,updatedAt:s,name:typeof e.name=="string"?e.name.slice(0,100):void 0};return await pt.put(i),{originalId:e.id,asset:i}}catch{return null}}}const rn=new wa,Ca=[{tool:"select",icon:"select",label:"Select",key:"V"},{tool:"hand",icon:"hand",label:"Hand",key:"H"},{tool:"sticky",icon:"sticky",label:"Sticky note",key:"S"},{tool:"task",icon:"task",label:"Task",key:""},{tool:"text",icon:"text",label:"Text",key:"T"},{tool:"image",icon:"image",label:"Image",key:"I"}],Xs=[{tool:"rectangle",icon:"rectangle",label:"Rectangle",key:"R"},{tool:"ellipse",icon:"ellipse",label:"Ellipse",key:"O"},{tool:"diamond",icon:"diamond",label:"Diamond",key:""},{tool:"triangle",icon:"triangle",label:"Triangle",key:""},{tool:"pill",icon:"pill",label:"Pill",key:""},{tool:"chevron",icon:"chevron",label:"Chevron",key:""},{tool:"parallelogram",icon:"parallelogram",label:"Parallelogram",key:""},{tool:"hexagon",icon:"hexagon",label:"Hexagon",key:""},{tool:"cylinder",icon:"cylinder",label:"Cylinder",key:""}],ka=[{tool:"arrow",icon:"arrow",label:"Arrow (hold Shift to snap)",key:"A"},{tool:"dashedArrow",icon:"arrowDashed",label:"Dashed arrow",key:""},{tool:"twoWayArrow",icon:"arrowBoth",label:"Two-way arrow",key:""},{tool:"labeledArrow",icon:"arrowLabel",label:"Centered label arrow",key:""},{tool:"sidedLabelArrow",icon:"arrowLabel",label:"Left and right labels",key:""}],Ea=new Set(Xs.map(o=>o.tool));class Sa{constructor(t,e){m(this,"element");m(this,"toolButtons",new Map);m(this,"shapeButtons",new Map);m(this,"shapeBtn");m(this,"shapeGroup");m(this,"arrowGroup");m(this,"themeBtn");this.element=document.createElement("div"),this.element.className="toolbar";for(const a of Ca){const r=this.makeButton(a.icon,a.label,a.key);r.addEventListener("click",()=>e.setTool(a.tool)),this.toolButtons.set(a.tool,r),this.element.appendChild(r),a.tool==="sticky"&&this.element.appendChild(this.makeShapePicker(e)),a.tool==="text"&&this.element.appendChild(this.makeArrowPicker(e))}this.element.appendChild(this.divider());const n=this.makeButton("templates","Templates","");n.addEventListener("click",e.openTemplates),this.element.appendChild(n),this.element.appendChild(this.divider()),this.themeBtn=this.makeButton("moon","Toggle theme",""),this.themeBtn.addEventListener("click",e.toggleTheme),this.element.appendChild(this.themeBtn);const s=this.makeButton("export","Export / Import","");s.addEventListener("click",e.openExportMenu),this.element.appendChild(s);const i=this.makeButton("flask","Stress test","");if(i.addEventListener("click",e.toggleStressPanel),this.element.appendChild(i),e.copyEmbed){this.element.appendChild(this.divider());const a=this.makeButton("embed","Copy embed of a region","");a.addEventListener("click",e.copyEmbed),this.element.appendChild(a)}t.appendChild(this.element)}makeButton(t,e,n){const s=document.createElement("button");s.className="tool-btn",s.setAttribute("aria-label",e),s.innerHTML=Y[t]??"";const i=document.createElement("span");if(i.className="tooltip",i.textContent=e,n){const a=document.createElement("kbd");a.textContent=n,i.appendChild(a)}return s.appendChild(i),s}makeShapePicker(t){this.shapeGroup=document.createElement("div"),this.shapeGroup.className="shape-tool-group",this.shapeBtn=this.makeButton("shapes","Shapes",""),this.shapeBtn.classList.add("shape-tool-trigger"),this.shapeBtn.addEventListener("click",n=>{n.stopPropagation(),this.shapeGroup.classList.toggle("open")});const e=document.createElement("div");e.className="shape-tool-popover";for(const n of Xs){const s=this.makeButton(n.icon,n.label,n.key);s.classList.add("shape-option-btn"),s.addEventListener("click",i=>{i.stopPropagation(),t.setTool(n.tool),this.shapeGroup.classList.remove("open")}),this.shapeButtons.set(n.tool,s),e.appendChild(s)}return this.shapeGroup.append(this.shapeBtn,e),this.shapeGroup}makeArrowPicker(t){this.arrowGroup=document.createElement("div"),this.arrowGroup.className="shape-tool-group";const e=this.makeButton("arrow","Arrow types","");e.classList.add("shape-tool-trigger"),e.addEventListener("click",s=>{s.stopPropagation(),this.arrowGroup.classList.toggle("open")});const n=document.createElement("div");n.className="shape-tool-popover";for(const s of ka){const i=this.makeButton(s.icon,s.label,s.key);i.classList.add("shape-option-btn"),i.addEventListener("click",a=>{a.stopPropagation(),t.setTool(s.tool),this.arrowGroup.classList.remove("open")}),this.toolButtons.set(s.tool,i),n.appendChild(i)}return this.arrowGroup.append(e,n),this.arrowGroup}divider(){const t=document.createElement("div");return t.className="toolbar-divider",t}setActiveTool(t){var e;for(const[n,s]of this.toolButtons)s.classList.toggle("active",n===t);for(const[n,s]of this.shapeButtons)s.classList.toggle("active",n===t);(e=this.shapeBtn)==null||e.classList.toggle("active",Ea.has(t))}setTheme(t){const e=this.themeBtn.querySelector(".tooltip");this.themeBtn.innerHTML=Y[t==="dark"?"sun":"moon"],e&&this.themeBtn.appendChild(e)}}class Ta{constructor(t,e,n){m(this,"zoomLabel");m(this,"titleInput");m(this,"titleMeasure");m(this,"statusEl");m(this,"statusTextEl");m(this,"statusActionBtn");const s=document.createElement("div");if(s.className="top-left",e.onExit){const u=document.createElement("button");u.className="control-btn back-btn",u.innerHTML=`${Y.arrowLeft}<span>ViteBoard</span>`,u.title="Save and back to ViteBoard",u.setAttribute("aria-label","Back to ViteBoard"),u.addEventListener("click",e.onExit),s.appendChild(u)}this.titleInput=document.createElement("input"),this.titleInput.className="board-title",this.titleInput.value=n,this.titleInput.maxLength=120,this.titleInput.setAttribute("aria-label","Board title"),this.titleInput.addEventListener("change",()=>e.onTitleChange(this.titleInput.value.trim()||"Untitled Board")),this.titleInput.addEventListener("input",()=>this.resizeTitleInput()),this.titleInput.addEventListener("keydown",u=>{u.stopPropagation(),u.key==="Enter"&&this.titleInput.blur()}),this.titleMeasure=document.createElement("span"),this.titleMeasure.className="board-title-measure",s.appendChild(this.titleInput),s.appendChild(this.titleMeasure),t.appendChild(s),this.resizeTitleInput();const i=document.createElement("div");i.className="top-right";const a=document.createElement("div");a.className="control-group";const r=this.btn("−","Zoom out (Ctrl/Cmd + wheel or Ctrl/Cmd + -)");r.addEventListener("click",e.zoomOut),a.appendChild(r),this.zoomLabel=this.btn("100%","Reset zoom to 100% (Ctrl/Cmd + 0)"),this.zoomLabel.classList.add("zoom-label"),this.zoomLabel.addEventListener("click",e.resetView),a.appendChild(this.zoomLabel);const c=this.btn("+","Zoom in (Ctrl/Cmd + wheel or Ctrl/Cmd + +)");c.addEventListener("click",e.zoomIn),a.appendChild(c),i.appendChild(a);const l=document.createElement("div");l.className="control-group";const d=this.iconBtn("reset","Reset view");d.addEventListener("click",e.resetView),l.appendChild(d);const h=this.iconBtn("storage","Storage manager");h.addEventListener("click",e.openStorageManager),l.appendChild(h);const p=this.iconBtn("gauge","Performance overlay");if(p.addEventListener("click",e.togglePerfOverlay),l.appendChild(p),e.deleteBoard){const u=this.iconBtn("trash","Delete board");u.classList.add("danger-control"),u.addEventListener("click",e.deleteBoard),l.appendChild(u)}i.appendChild(l),this.statusEl=document.createElement("div"),this.statusEl.className="board-live-status",this.statusEl.hidden=!0,this.statusTextEl=document.createElement("span"),this.statusActionBtn=document.createElement("button"),this.statusActionBtn.className="status-action-btn",this.statusActionBtn.hidden=!0,this.statusEl.append(this.statusTextEl,this.statusActionBtn),i.appendChild(this.statusEl),t.appendChild(i)}btn(t,e){const n=document.createElement("button");return n.className="control-btn",n.textContent=t,n.title=e,n.setAttribute("aria-label",e),n}iconBtn(t,e){const n=document.createElement("button");return n.className="control-btn",n.innerHTML=Y[t]??"",n.title=e,n.setAttribute("aria-label",e),n}setZoom(t){this.zoomLabel.textContent=Math.round(t*100)+"%"}setTitle(t){this.titleInput.value=t,this.resizeTitleInput()}setStatus(t,e,n){this.statusEl.hidden=!t,this.statusTextEl.textContent=t,this.statusEl.dataset.state=e,this.statusActionBtn.hidden=!n,this.statusActionBtn.textContent=(n==null?void 0:n.label)??"",this.statusActionBtn.onclick=(n==null?void 0:n.onClick)??null}resizeTitleInput(){if(!this.titleMeasure||!this.titleInput)return;this.titleMeasure.textContent=this.titleInput.value||"Untitled Board";const t=Math.ceil(this.titleMeasure.getBoundingClientRect().width+22),e=Math.max(180,window.innerWidth-460);this.titleInput.style.width=Math.min(Math.max(90,t),e)+"px"}}class Ba{constructor(t,e){m(this,"state");m(this,"commands");m(this,"textareas",[]);m(this,"editingId",null);this.state=t,this.commands=e}get isEditing(){return this.editingId!==null}open(t){if(this.close(),this.editingId=t.id,t.data.labelPosition==="sides"){this.openSideEditors(t);return}const e=document.createElement("textarea");e.className="text-editor",e.value=t.data.text??"",t.data.labelPosition==="sides"&&(e.placeholder="left label | right label"),this.position(e,t),document.body.appendChild(e),this.textareas=[e],e.focus(),e.select();const n=t.data.text??"";t.data.text="",t.updatedAt=Date.now(),G(t.id),this.state.requestRender();const s=()=>{const i=e.value;if(t.data.text=i,Nt(t),t.updatedAt=Date.now(),G(t.id),i!==n){const a=t.id,r=this.state;this.commands.push("edit-text",()=>{const c=r.elementsById.get(a);c&&(c.data.text=i,Nt(c),c.updatedAt=Date.now(),G(a),r.emitChange())},()=>{const c=r.elementsById.get(a);c&&(c.data.text=n,Nt(c),c.updatedAt=Date.now(),G(a),r.emitChange())})}this.state.emitChange(),this.close()};e.addEventListener("blur",s),e.addEventListener("keydown",i=>{i.stopPropagation(),i.key==="Escape"?(t.data.text=n,G(t.id),this.close(),this.state.requestRender()):i.key==="Enter"&&(i.metaKey||i.ctrlKey)&&e.blur()})}openSideEditors(t){const e=String(t.data.text??""),[n="",s=""]=e.split("|",2).map(d=>d.trim()),i=this.makeSideEditor("Left label",n),a=this.makeSideEditor("Right label",s);this.positionSideEditors(i,a,t),document.body.append(i,a),this.textareas=[i,a],i.focus(),i.select(),t.data.text="",t.updatedAt=Date.now(),G(t.id),this.state.requestRender();let r=!1;const c=()=>{if(r)return;r=!0;const d=`${i.value.trim()} | ${a.value.trim()}`;t.data.text=d,t.updatedAt=Date.now(),G(t.id),d!==e&&this.pushTextCommand(t.id,e,d),this.state.emitChange(),this.close()},l=()=>{r||(r=!0,t.data.text=e,G(t.id),this.close(),this.state.requestRender())};for(const d of[i,a])d.addEventListener("keydown",h=>{h.stopPropagation(),h.key==="Escape"?l():h.key==="Enter"&&(h.metaKey||h.ctrlKey)&&c()}),d.addEventListener("blur",()=>{window.setTimeout(()=>{this.textareas.includes(document.activeElement)||c()},0)})}makeSideEditor(t,e){const n=document.createElement("textarea");return n.className="text-editor text-editor-side",n.placeholder=t,n.value=e,n.style.fontFamily='-apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif',n.style.fontWeight="600",n.style.textAlign="center",n.style.lineHeight="1.35",n.style.color=this.state.theme==="dark"?"#f2f2f2":"#1f2933",n}positionSideEditors(t,e,n){const s=this.state.viewport,i=Ft(n.x,n.y,s),a=Ft(n.x+n.width,n.y+n.height,s),r=13*s.scale,c=Math.max(82,Math.min(150,Math.hypot(a.x-i.x,a.y-i.y)*.34)),l=Math.max(24,r*1.35+4);for(const[d,h]of[[t,.24],[e,.76]])d.style.left=i.x+(a.x-i.x)*h-c/2+"px",d.style.top=i.y+(a.y-i.y)*h-l/2+"px",d.style.width=c+"px",d.style.height=l+"px",d.style.fontSize=r+"px"}pushTextCommand(t,e,n){const s=this.state;this.commands.push("edit-text",()=>{const i=s.elementsById.get(t);i&&(i.data.text=n,Nt(i),i.updatedAt=Date.now(),G(t),s.emitChange())},()=>{const i=s.elementsById.get(t);i&&(i.data.text=e,Nt(i),i.updatedAt=Date.now(),G(t),s.emitChange())})}position(t,e){const n=this.state.viewport;if(e.type==="arrow"||e.type==="line"||e.type==="connector"){const b=Ft(e.x,e.y,n),w=Ft(e.x+e.width,e.y+e.height,n),v=13*n.scale,S=Math.max(100,Math.min(240,Math.hypot(w.x-b.x,w.y-b.y)-16)),x=Math.max(24,v*1.35+4);t.style.left=(b.x+w.x)/2-S/2+"px",t.style.top=(b.y+w.y)/2-x/2+"px",t.style.width=S+"px",t.style.height=x+"px",t.style.fontSize=v+"px",t.style.lineHeight="1.35",t.style.fontFamily='-apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif',t.style.fontWeight="600",t.style.color=this.state.theme==="dark"?"#f2f2f2":"#1f2933",t.style.textAlign="center";return}const s=Ft(e.x,e.y,n),i=e.data.shapeKind==="chevron",a=Ye(e)*n.scale,r=i?Math.min(Math.abs(e.width)*.18,Math.abs(e.height)*.55)+8:10,c=(e.type==="sticky"?14:e.type==="task"?50:e.type==="text"?0:r)*n.scale,l=e.type!=="text"&&e.type!=="task",d=i?e.height*n.scale:e.height*n.scale-(e.type==="sticky"?28:l?r*2:0)*n.scale,h=Math.max(1,String(e.data.text??"").split(/\r?\n/).length),p=Math.max(24,a*(i?1.18:1.35)*h+4),u=l?Math.min(Math.max(24,d),p):Math.max(24,d),f=l?Math.max(0,(e.height*n.scale-u)/2):e.type==="sticky"?14*n.scale:0,y=(e.type==="task"?16:e.type==="sticky"?14:e.type==="text"?0:r)*n.scale;t.style.left=s.x+c+"px",t.style.top=s.y+f+"px",t.style.width=Math.max(40,e.width*n.scale-c-y)+"px",t.style.height=u+"px",t.style.fontSize=a+"px",t.style.lineHeight=i?"1.18":"1.35",t.style.fontFamily=e.style.fontFamily??'-apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif',t.style.fontWeight=i?"750":e.style.fontWeight??"400",t.style.color=e.style.textColor??(this.state.theme==="dark"?"#f2f2f2":"#1f2933"),t.style.textAlign=e.type==="text"||e.type==="task"?"left":"center"}close(){if(this.textareas.length){const t=this.textareas;this.textareas=[],this.editingId=null;for(const e of t)e.remove()}}}function wt(o){return o==="dark"?{card:"#1e2126",cardStroke:"#3a3f46",heading:"#f2f2f2",text:"#c8cdd4",accent:"#4dabf7",sticky:"#fef08a",zone:"#22262c"}:{card:"#ffffff",cardStroke:"#d8dade",heading:"#1f2933",text:"#4b5563",accent:"#6e6e6e",sticky:"#fef08a",zone:"#f0f0ed"}}let oe=0;function Ct(o){oe=o}function W(o,t,e,n,s,i=""){return _("rectangle",{x:o,y:t,width:e,height:n,zIndex:++oe,style:{borderRadius:10,...s},data:{text:i}})}function P(o,t,e,n,s,i,a="600"){return _("text",{x:o,y:t,width:e,height:s*1.6,zIndex:++oe,style:{fontSize:s,textColor:i,fontWeight:a},data:{text:n}})}function q(o,t,e,n,s=180,i=120){return _("sticky",{x:o,y:t,width:s,height:i,zIndex:++oe,style:{fill:n,borderRadius:12,shadow:!0,fontSize:13,textColor:"#1f2933"},data:{text:e}})}function U(o,t,e,n,s,i={}){return _("arrow",{x:o,y:t,width:e-o,height:n-t,zIndex:++oe,style:{stroke:s,strokeWidth:2,arrowEnd:!0,arrowStart:i.arrowStart,strokeDash:i.dashed?[8,6]:void 0},data:{text:i.label??"",labelPosition:i.sides?"sides":"center"}})}function Ma(o,t,e,n,s,i=""){return _("ellipse",{x:o,y:t,width:e,height:n,zIndex:++oe,style:s,data:{text:i}})}function La(o,t,e,n){const s=wt(e);Ct(n);const i=[];return i.push(W(o,t,760,560,{fill:s.card,stroke:s.cardStroke,strokeWidth:1.5,borderRadius:16,shadow:!0})),i.push(P(o+28,t+22,400,"User Persona",22,s.heading,"700")),i.push(P(o+28,t+60,300,"Name",13,s.accent)),i.push(q(o+28,t+86,"Jordan Lee",s.sticky,200,64)),i.push(P(o+260,t+60,300,"Role",13,s.accent)),i.push(q(o+260,t+86,"Senior Product Manager","#a5b4fc",220,64)),i.push(P(o+510,t+60,300,"Buying trigger",13,s.accent)),i.push(q(o+510,t+86,"Team scaling pains","#fdba74",220,64)),[["Goals","Ship the right features faster","#86efac"],["Pain points","Scattered docs, unclear priorities","#fca5a5"],["Jobs to be done","Align team on what to build next","#93c5fd"],["Current workaround","Spreadsheets + slide decks","#d8b4fe"],["Success criteria","Stakeholders aligned in 1 meeting","#f9a8d4"],["Key quote",'"I need clarity, not more tools."',"#fef08a"]].forEach(([r,c,l],d)=>{const h=d%3,p=Math.floor(d/3),u=o+28+h*242,f=t+188+p*178;i.push(P(u,f,230,r,13,s.accent)),i.push(q(u,f+26,c,l,220,124))}),i}const cn=["Awareness","Discovery","Evaluation","Onboarding","Activation","Retention"],Ia=["#93c5fd","#a5b4fc","#d8b4fe","#f9a8d4","#fdba74","#86efac"];function Pa(o,t,e,n){const s=wt(e);Ct(n);const i=[],a=230,r=cn.length*a+56;return i.push(W(o,t,r,640,{fill:s.card,stroke:s.cardStroke,strokeWidth:1.5,borderRadius:16,shadow:!0})),i.push(P(o+28,t+22,500,"User Journey Map",22,s.heading,"700")),cn.forEach((c,l)=>{const d=o+28+l*a,h=t+70;i.push(W(d,h,a-16,48,{fill:Ia[l],borderRadius:10},c)),l<cn.length-1&&i.push(U(d+a-14,h+24,d+a-2,h+24,s.heading)),i.push(W(d,h+64,a-16,150,{fill:s.zone,borderRadius:10},"")),i.push(P(d+10,h+70,a-36,"Actions",12,s.accent)),i.push(q(d+14,h+96,"","#fef08a",a-44,100)),i.push(W(d,h+226,a-16,150,{fill:s.zone,borderRadius:10},"")),i.push(P(d+10,h+232,a-36,"Pain points",12,s.accent)),i.push(q(d+14,h+258,"","#fca5a5",a-44,100)),i.push(W(d,h+388,a-16,150,{fill:s.zone,borderRadius:10},"")),i.push(P(d+10,h+394,a-36,"Opportunities",12,s.accent)),i.push(q(d+14,h+420,"","#86efac",a-44,100))}),i}function $a(o,t,e,n){const s=wt(e);Ct(n);const i=[],a=680;i.push(W(o,t,a+120,a+130,{fill:s.card,stroke:s.cardStroke,strokeWidth:1.5,borderRadius:16,shadow:!0})),i.push(P(o+28,t+22,500,"Feature Prioritization Matrix",22,s.heading,"700"));const r=o+80,c=t+80,l=a/2;return i.push(W(r,c,l,l,{fill:"#86efac55",borderRadius:8})),i.push(W(r+l,c,l,l,{fill:"#93c5fd55",borderRadius:8})),i.push(W(r,c+l,l,l,{fill:"#fef08a55",borderRadius:8})),i.push(W(r+l,c+l,l,l,{fill:"#fca5a555",borderRadius:8})),i.push(P(r+16,c+12,300,"Quick wins",16,s.heading,"700")),i.push(P(r+l+16,c+12,300,"Strategic bets",16,s.heading,"700")),i.push(P(r+16,c+l+12,300,"Fill-ins",16,s.heading,"700")),i.push(P(r+l+16,c+l+12,300,"Avoid",16,s.heading,"700")),i.push(U(r-24,c+a,r-24,c,s.heading)),i.push(P(r-64,c+l-12,60,"Impact",14,s.text,"600")),i.push(U(r,c+a+24,r+a,c+a+24,s.heading)),i.push(P(r+l-30,c+a+34,80,"Effort",14,s.text,"600")),i.push(q(r+40,c+60,"Feature idea","#fef08a",150,90)),i.push(q(r+l+40,c+60,"Big bet","#a5b4fc",150,90)),i}const Qn=[["Problem","#fca5a5"],["User","#93c5fd"],["Context","#d8b4fe"],["Current workflow","#fdba74"],["Proposed solution","#86efac"],["Edge cases","#f9a8d4"],["Acceptance criteria","#a5b4fc"],["Dependencies","#fef08a"],["Risks","#fca5a5"]];function Ra(o,t,e,n){const s=wt(e);Ct(n);const i=[],a=3,r=280,c=210,l=a*r+56,h=Math.ceil(Qn.length/a)*c+100;return i.push(W(o,t,l,h,{fill:s.card,stroke:s.cardStroke,strokeWidth:1.5,borderRadius:16,shadow:!0})),i.push(P(o+28,t+22,500,"Product Requirements Flow",22,s.heading,"700")),Qn.forEach(([p,u],f)=>{const y=f%a,b=Math.floor(f/a),w=o+28+y*r,v=t+72+b*c;i.push(P(w,v,r-30,`${f+1}. ${p}`,14,s.accent)),i.push(q(w,v+30,"",u,r-28,c-60))}),i}function Da(o,t,e,n){const s=wt(e);Ct(n);const i=[];i.push(P(o,t-40,400,"System Diagram",22,s.heading,"700"));const a=(r,c,l,d,h,p)=>W(r,c,l,d,{fill:h,stroke:s.cardStroke,strokeWidth:1.5,borderRadius:12,shadow:!0,fontSize:15,fontWeight:"600",textColor:"#1f2933"},p);return i.push(Ma(o,t+130,110,110,{fill:"#f9a8d4",stroke:s.cardStroke,strokeWidth:1.5,fontSize:14,fontWeight:"600",textColor:"#1f2933"},"User")),i.push(a(o+200,t+140,180,90,"#93c5fd","Frontend")),i.push(a(o+470,t+140,180,90,"#a5b4fc","API / Server")),i.push(a(o+740,t+60,180,90,"#86efac","Database")),i.push(a(o+740,t+200,180,90,"#fdba74","External Service")),i.push(a(o+470,t+330,180,90,"#fef08a","Notification Service")),i.push(U(o+115,t+185,o+195,t+185,s.heading,{label:"uses"})),i.push(U(o+385,t+185,o+465,t+185,s.heading,{label:"request | response",sides:!0,arrowStart:!0})),i.push(U(o+655,t+165,o+735,t+110,s.heading,{label:"read"})),i.push(U(o+655,t+205,o+735,t+240,s.heading,{label:"webhook",dashed:!0})),i.push(U(o+560,t+235,o+560,t+325,s.heading,{label:"event",dashed:!0})),i.push(U(o+470,t+375,o+80,t+245,s.heading,{label:"notify",dashed:!0})),i}function Aa(o,t,e,n){const s=wt(e);Ct(n);const i=[];i.push(P(o+280,t-40,500,"Opportunity Solution Tree",22,s.heading,"700")),i.push(W(o+300,t,280,80,{fill:"#a5b4fc",borderRadius:12,shadow:!0,fontSize:15,fontWeight:"600",textColor:"#1f2933"},"Desired outcome"));const a=t+160,r=[o,o+300,o+600];for(const d of r)i.push(q(d,a,"Opportunity","#93c5fd",220,100)),i.push(U(o+440,t+85,d+110,a-5,s.heading));const c=a+180;for(const d of r)i.push(q(d,c,"Solution","#86efac",220,100)),i.push(U(d+110,a+105,d+110,c-5,s.heading));const l=c+180;for(const d of r)i.push(q(d,l,"Experiment","#fdba74",220,90)),i.push(U(d+110,c+105,d+110,l-5,s.heading));return i.push(P(o,l+120,400,"Signals / metrics",14,s.accent)),i.push(q(o,l+150,"What signal tells us this is working?","#fef08a",380,100)),i}function Na(o,t,e,n){const s=wt(e);Ct(n);const i=[];i.push(W(o,t,1060,620,{fill:s.card,stroke:s.cardStroke,strokeWidth:1.5,borderRadius:16,shadow:!0})),i.push(P(o+28,t+22,500,"Screenshot Review",22,s.heading,"700")),i.push(P(o+28,t+64,300,"Screenshot",13,s.accent));const a=_("frame",{x:o+28,y:t+92,width:480,height:360,zIndex:n+100,style:{fill:s.zone,stroke:s.cardStroke,strokeWidth:1.5,borderRadius:12,fontSize:13,textColor:s.text},data:{text:"Paste a screenshot here (Cmd/Ctrl+V)"}});return i.push(a),[["Observations","#93c5fd"],["Problems","#fca5a5"],["UX notes","#d8b4fe"],["Requirements","#86efac"]].forEach(([c,l],d)=>{const h=d%2,p=Math.floor(d/2),u=o+540+h*250,f=t+64+p*200;i.push(P(u,f,230,c,13,s.accent)),i.push(q(u,f+28,"",l,230,140))}),i.push(P(o+28,t+470,300,"Follow-up tasks",13,s.accent)),i.push(q(o+28,t+498,"","#fef08a",480,96)),i.push(P(o+540,t+470,300,"Decision",13,s.accent)),i.push(q(o+540,t+498,"","#fdba74",480,96)),i}function Fa(o,t,e,n){const s=wt(e);Ct(n);const i=[];i.push(P(o,t,880,"Workflow map",26,s.heading,"700"));const a=[["Request","#dbeafe"],["Review","#fef3c7"],["Deliver","#dcfce7"]];for(let r=0;r<a.length;r++){const c=o+r*280;i.push(W(c,t+130,180,96,{fill:a[r][1],stroke:s.cardStroke,strokeWidth:1.5,borderRadius:12,fontSize:16,fontWeight:"650",textColor:"#1f2933",shadow:!0},a[r][0]))}return i.push(U(o+180,t+178,o+280,t+178,s.accent,{label:"approve"})),i.push(U(o+460,t+178,o+560,t+178,s.accent,{label:"ship"})),i.push(U(o+650,t+226,o+370,t+310,"#9ca3af",{label:"feedback",dashed:!0})),i.push(W(o+280,t+300,180,72,{fill:s.zone,stroke:s.cardStroke,strokeWidth:1.5,borderRadius:10,fontSize:14,textColor:s.text},"Learn and iterate")),i}function za(o,t,e,n){const s=wt(e);Ct(n);const i=[];return i.push(P(o,t,800,"Handoff map",26,s.heading,"700")),[["Explore","#dbeafe"],["Decide","#fef3c7"],["Act","#dcfce7"]].forEach(([r,c],l)=>{i.push(W(o+l*270,t+150,170,92,{fill:c,stroke:s.cardStroke,strokeWidth:1.5,borderRadius:12,shadow:!0,fontSize:16,fontWeight:"650",textColor:"#1f2933"},r))}),i.push(U(o+170,t+196,o+270,t+196,s.accent,{label:"proposal"})),i.push(U(o+440,t+196,o+540,t+196,s.accent,{label:"owner | outcome",sides:!0,arrowStart:!0})),i.push(U(o+625,t+245,o+355,t+330,"#9ca3af",{label:"feedback",dashed:!0})),i.push(W(o+265,t+320,180,70,{fill:s.zone,stroke:s.cardStroke,strokeWidth:1.5,borderRadius:10,fontSize:14,textColor:s.text},"Review signal")),i}const Ha=[{id:"persona",name:"User Persona Card",description:"Name, role, goals, pain points, JTBD, success criteria.",build:La},{id:"journey",name:"User Journey Map",description:"Awareness → Retention stages with sticky note areas.",build:Pa},{id:"matrix",name:"Prioritization Matrix",description:"Impact vs effort: quick wins, strategic bets, fill-ins, avoid.",build:$a},{id:"requirements",name:"Requirements Flow",description:"Problem, user, context, solution, edge cases, risks.",build:Ra},{id:"system",name:"System Diagram Starter",description:"User, frontend, API, database, external services + arrows.",build:Da},{id:"ost",name:"Opportunity Solution Tree",description:"Outcome, opportunities, solutions, experiments, signals.",build:Aa},{id:"screenshot-review",name:"Screenshot Review Board",description:"Screenshot zone with observations, problems, UX notes.",build:Na},{id:"workflow",name:"Workflow Map",description:"Labeled handoffs, a dashed feedback loop, and editable steps.",build:Fa},{id:"handoff",name:"Handoff Map",description:"A shared decision flow with ownership, outcomes, and feedback.",build:za}];function ja(o,t){V("Insert a template",(e,n)=>{const s=document.createElement("div");s.className="template-grid";for(const i of Ha){const a=document.createElement("button");a.className="template-card";const r=document.createElement("span");r.className="t-name",r.textContent=i.name;const c=document.createElement("span");c.className="t-desc",c.textContent=i.description,a.appendChild(r),a.appendChild(c),a.addEventListener("click",()=>{Wa(o,t,i.build),n()}),s.appendChild(a)}e.appendChild(s)})}function Wa(o,t,e){const n=A(window.innerWidth/2,window.innerHeight/2,o.viewport),s=e(n.x-380,n.y-280,o.theme,o.maxZIndex());t.execute("insert-template",()=>{for(const i of s)o.elementsById.has(i.id)||o.addElement(i);o.emitChange()},()=>{for(const i of s)o.removeElement(i.id);o.emitChange()}),o.clearSelection();for(const i of s)o.selectedIds.add(i.id);o.requestRender()}function $e(o){return o<1024?o+" B":o<1024*1024?(o/1024).toFixed(1)+" KB":(o/(1024*1024)).toFixed(1)+" MB"}function Oa(o,t,e,n){V(n?"Storage":"Local storage",async(s,i)=>{const a=document.createElement("div");s.appendChild(a);const r=(f,y)=>{const b=document.createElement("div");b.className="storage-row";const w=document.createElement("span");w.textContent=f;const v=document.createElement("span");v.textContent=y,b.appendChild(w),b.appendChild(v),a.appendChild(b)};r("Elements on board",String(o.elements.length));const c=JSON.stringify(o.elements);if(r("Board data size",$e(c.length)),n)r("Workspace assets","Stored on disk under docs/assets");else{const f=await pt.getAllKeys();r("Image assets",String(f.length));const y=await pt.totalSizeBytes();r("Image asset size",$e(y))}const l=await ct.estimateStorage();!n&&l.quota>0&&r("Browser storage",`${$e(l.usage)} of ${$e(l.quota)}`);const d=document.createElement("div");d.className="modal-actions";const h=document.createElement("button");h.className="btn",h.textContent=n?"Clean unused managed assets":"Clear unused assets",h.addEventListener("click",async()=>{if(n){const w=o.elements.map(v=>typeof v.data.src=="string"?v.data.src:"").filter(Boolean);try{const v=await n(w);C(`Removed ${v} unused managed asset${v===1?"":"s"}`),i()}catch{C("Could not clean workspace assets")}return}const f=new Set,y=await ct.getAllBoards();for(const w of y)for(const v of w.elements){const S=v.data.assetId;typeof S=="string"&&f.add(S)}const b=await pt.clearUnused(f);C(`Removed ${b} unused asset${b===1?"":"s"}`),i()}),d.appendChild(h);const p=document.createElement("button");p.className="btn danger",p.textContent="Clear board",p.addEventListener("click",()=>{confirm("Remove all elements from this board?")&&(t(),i())}),d.appendChild(p);const u=document.createElement("button");u.className="btn danger",u.textContent=n?"Reset local-only data":"Reset all local data",u.addEventListener("click",()=>{confirm("Delete ALL local boards, assets and preferences? This cannot be undone.")&&(e(),i())}),d.appendChild(u),s.appendChild(d)})}class Ua{constructor(t,e,n,s,i,a){m(this,"element");m(this,"visible",!1);m(this,"state");m(this,"renderer");m(this,"hitTester");m(this,"monitor");m(this,"imageCache");m(this,"timer",null);m(this,"storageEstimate","–");this.state=e,this.renderer=n,this.hitTester=s,this.monitor=i,this.imageCache=a,this.element=document.createElement("div"),this.element.className="perf-overlay",t.appendChild(this.element)}toggle(){this.visible=!this.visible,this.element.classList.toggle("visible",this.visible),this.visible?(this.monitor.start(),this.update(),this.timer=window.setInterval(()=>this.update(),500),this.refreshStorage()):this.timer!==null&&(clearInterval(this.timer),this.timer=null)}async refreshStorage(){const t=await pt.totalSizeBytes();this.storageEstimate=(t/(1024*1024)).toFixed(1)+"MB"}update(){const t=this.state.viewport,e=[`FPS: ${this.monitor.fps}`,`Total elements: ${this.state.elements.length.toLocaleString()}`,`Visible elements: ${this.renderer.visibleCount.toLocaleString()}`,`Render time: ${this.renderer.lastRenderMs.toFixed(1)}ms`,`Hit-test time: ${this.hitTester.lastHitTestMs.toFixed(2)}ms`,`Save time: ${ct.lastSaveMs.toFixed(0)}ms`,`Image cache: ${this.imageCache.size}`,`Estimated storage: ${this.storageEstimate}`,`Zoom: ${Math.round(t.scale*100)}%`,`Viewport: x: ${Math.round(-t.offsetX/t.scale)}, y: ${Math.round(-t.offsetY/t.scale)}`,`Culling: ${this.renderer.cullingEnabled?"on":"off"} LOD: ${this.renderer.lodEnabled?"on":"off"}`];this.element.textContent=e.join(`
|
|
15
|
+
`)}}const Re=["#93c5fd","#a5b4fc","#86efac","#fdba74","#fca5a5","#d8b4fe","#f9a8d4","#fef08a","#ffffff","#e5e7eb"],ts=["Onboarding","Checkout","Retention","Activation","Churn risk","API gateway","User insight","Edge case","Quick win","Tech debt","Experiment","Metric","Persona","Journey","Feature flag"];function rt(o,t){return o+Math.random()*(t-o)}function ft(o){return o[Math.floor(Math.random()*o.length)]}const gt="stress";class _a{constructor(t){m(this,"state");m(this,"lastGenerateMs",0);this.state=t}generate(t){const e=performance.now(),n=Math.sqrt(t)*280,s=["sticky","rectangle","ellipse","text","arrow"];let i=this.state.maxZIndex();const a=[];for(let r=0;r<t;r++){const c=ft(s),l=rt(-n/2,n/2),d=rt(-n/2,n/2);let h;c==="sticky"?h=_("sticky",{x:l,y:d,width:220,height:160,zIndex:++i,style:{fill:ft(Ue),borderRadius:12,shadow:!0,fontSize:14,textColor:"#1f2933"},data:{text:ft(ts),[gt]:!0}}):c==="rectangle"||c==="ellipse"?h=_(c,{x:l,y:d,width:rt(80,300),height:rt(60,200),zIndex:++i,style:{fill:ft(Re),stroke:"#37415188",strokeWidth:1.5,borderRadius:c==="rectangle"?8:0},data:{[gt]:!0}}):c==="text"?h=_("text",{x:l,y:d,width:200,height:28,zIndex:++i,style:{fontSize:16,textColor:this.state.theme==="dark"?"#f2f2f2":"#1f2933"},data:{text:ft(ts),[gt]:!0}}):h=_("arrow",{x:l,y:d,width:rt(-250,250),height:rt(-250,250),zIndex:++i,style:{stroke:ft(Re),strokeWidth:2,arrowEnd:!0},data:{[gt]:!0}}),a.push(h)}for(const r of a)this.state.addElement(r);this.lastGenerateMs=performance.now()-e,this.state.emitChange()}generateImagePlaceholders(t){const e=Math.sqrt(t)*420;let n=this.state.maxZIndex();for(let s=0;s<t;s++){const i=_("image",{x:rt(-e/2,e/2),y:rt(-e/2,e/2),width:320,height:220,zIndex:++n,data:{assetId:"stress-placeholder-"+s,[gt]:!0}});this.state.addElement(i)}this.state.emitChange()}generateMixedPmBoard(){this.generate(300)}randomizePositions(){const t=Math.sqrt(this.state.elements.length)*280;for(const e of this.state.elements)e.data[gt]&&(e.x=rt(-t/2,t/2),e.y=rt(-t/2,t/2));this.state.emitChange()}randomizeColors(){for(const t of this.state.elements)t.data[gt]&&(t.type==="sticky"?t.style.fill=ft(Ue):t.type==="rectangle"||t.type==="ellipse"?t.style.fill=ft(Re):t.type==="arrow"&&(t.style.stroke=ft(Re)));this.state.emitChange()}randomizeZIndex(){for(const t of this.state.elements)t.data[gt]&&(t.zIndex=Math.floor(rt(0,this.state.elements.length)));this.state.invalidateSort(),this.state.emitChange()}clearGenerated(){const t=this.state.elements.filter(e=>e.data[gt]);for(const e of t)this.state.removeElement(e.id);this.state.emitChange()}}class qa{constructor(t,e,n){m(this,"element");m(this,"visible",!1);this.element=document.createElement("div"),this.element.className="stress-panel";const s=(a,r,c=!1)=>{const l=document.createElement("button");l.className="btn"+(c?" danger":""),l.textContent=a,l.addEventListener("click",r),this.element.appendChild(l)},i=a=>()=>{e.generate(a),C(`Generated ${a.toLocaleString()} elements in ${e.lastGenerateMs.toFixed(0)}ms`)};s("+100",i(100)),s("+1,000",i(1e3)),s("+5,000",i(5e3)),s("+10,000",i(1e4)),s("+20,000",i(2e4)),s("+100 images",()=>{e.generateImagePlaceholders(100),C("Generated 100 image placeholders")}),s("Mixed PM board",()=>{e.generateMixedPmBoard(),C("Generated mixed PM board")}),s("Shuffle positions",()=>e.randomizePositions()),s("Shuffle colors",()=>e.randomizeColors()),s("Shuffle z-index",()=>e.randomizeZIndex()),s("Toggle culling",()=>{n.cullingEnabled=!n.cullingEnabled,C(`Viewport culling ${n.cullingEnabled?"enabled":"disabled"}`),n.state.requestRender()}),s("Toggle LOD",()=>{n.lodEnabled=!n.lodEnabled,C(`Simplified rendering ${n.lodEnabled?"enabled":"disabled"}`),n.state.requestRender()}),s("Clear generated",()=>{e.clearGenerated(),C("Cleared generated elements")},!0),t.appendChild(this.element)}toggle(){this.visible=!this.visible,this.element.classList.toggle("visible",this.visible)}}const Xa=300,Ya=1e3,es=[{label:"Small",shortLabel:"S",fontSize:13,fontWeight:"400"},{label:"Body",shortLabel:"Body",fontSize:16,fontWeight:"400"},{label:"H3",shortLabel:"H3",fontSize:18,fontWeight:"650"},{label:"H2",shortLabel:"H2",fontSize:24,fontWeight:"700"},{label:"H1",shortLabel:"H1",fontSize:32,fontWeight:"750"}],Ka=new Set(["text"]),Va=new Set(["rectangle","ellipse","frame"]),Ga=["#0078d4","#4dabf7","#6e6e6e","#ffffff","#0f0f0f","#fef08a","#93c5fd","#fca5a5"],Za=[{label:"Black text",value:"#1f2933"},{label:"White text",value:"#ffffff"}];class Ja{constructor(t,e={}){m(this,"state",new Hi);m(this,"commands",new Wi);m(this,"surface");m(this,"renderer");m(this,"scheduler");m(this,"hitTester");m(this,"imageCache");m(this,"monitor",new sa);m(this,"actions");m(this,"imageInsert");m(this,"toolController");m(this,"textEditor");m(this,"toolbar");m(this,"topControls");m(this,"perfOverlay");m(this,"stressPanel");m(this,"boardSaveTimer",null);m(this,"viewportSaveTimer",null);m(this,"saveInFlight",null);m(this,"saveQueued",!1);m(this,"suppressPersistence",!1);m(this,"options");m(this,"listenerAbort",new AbortController);m(this,"root");m(this,"revision",null);m(this,"stale",!1);m(this,"bottomToolCluster",null);m(this,"stickyColorPopover",null);m(this,"textSizePopover",null);m(this,"shapeStylePopover",null);m(this,"layerMenu",null);this.root=t,this.options=e,e.boardId&&(this.state.boardId=e.boardId);const n=this.listenerAbort.signal;this.surface=new Ji(t,3,n),this.imageCache=new Ns(pt,()=>this.state.requestRender(),e.resolveAssetUrl),this.renderer=new Qi(this.surface,this.state,this.imageCache),this.scheduler=new ta(()=>this.renderer.render()),this.hitTester=new na(this.state),this.actions=new Oi(this.state,this.commands),this.textEditor=new Ba(this.state,this.commands),this.imageInsert=new qi(this.state,this.commands,this.imageCache,C,e.uploadImage),this.state.onRenderNeeded(()=>{var s;this.scheduler.requestRender(),(s=this.topControls)==null||s.setZoom(this.state.viewport.scale),this.suppressPersistence||this.scheduleViewportSave(),this.updateContextualToolPanels()}),this.state.onChange(()=>{this.suppressPersistence||this.scheduleBoardSave()}),this.surface.onResize(()=>this.state.requestRender()),this.setupTools(t,n),this.setupUi(t),this.setupSelectionOverlays(t,n),this.setupDragDrop(t),new Yi(this.state,this.actions,this.imageInsert,n),Ki({state:this.state,commands:this.commands,actions:this.actions,toolController:this.toolController,resetView:()=>this.resetView()},n),this.loadInitialState()}destroy(){this.boardSaveTimer!==null&&clearTimeout(this.boardSaveTimer),this.viewportSaveTimer!==null&&clearTimeout(this.viewportSaveTimer),this.listenerAbort.abort(),this.imageCache.clear()}setupTools(t,e){const n={state:this.state,renderer:this.renderer,surface:this.surface,hitTester:this.hitTester,commands:this.commands,setTool:s=>this.toolController.setTool(s),setCursor:s=>{this.surface.container.style.cursor=s},openTextEditor:s=>this.textEditor.open(s)};this.toolController=new ra(this.surface.container,n,[new da,new ha,new ma,new fa,new mt("rectangle"),new mt("ellipse"),new mt("diamond"),new mt("triangle"),new mt("pill"),new mt("chevron"),new mt("parallelogram"),new mt("hexagon"),new mt("cylinder"),new ga,new le,new le("dashedArrow"),new le("twoWayArrow"),new le("labeledArrow"),new le("sidedLabelArrow"),new ya((s,i,a)=>void this.imageInsert.insertFiles(s,i,a))],e),this.toolController.onToolChange(s=>{var i;(i=this.toolbar)==null||i.setActiveTool(s)})}setupUi(t){this.toolbar=new Sa(t,{setTool:n=>this.toolController.setTool(n),openTemplates:()=>ja(this.state,this.commands),toggleTheme:()=>this.toggleTheme(),openExportMenu:()=>this.openExportMenu(),toggleStressPanel:()=>this.stressPanel.toggle(),copyEmbed:this.options.onExit?()=>this.startEmbedSelection():void 0}),this.toolbar.setActiveTool("select"),this.topControls=new Ta(t,{onExit:this.options.onExit?()=>this.exitToDocs():void 0,resetView:()=>this.resetView(),zoomIn:()=>{be(this.state.viewport,window.innerWidth/2,window.innerHeight/2,this.state.viewport.scale*1.2),this.state.requestRender()},zoomOut:()=>{be(this.state.viewport,window.innerWidth/2,window.innerHeight/2,this.state.viewport.scale/1.2),this.state.requestRender()},openStorageManager:()=>Oa(this.state,()=>this.clearBoard(),()=>void this.resetAllLocalData(),this.options.cleanupUnusedAssets),togglePerfOverlay:()=>this.perfOverlay.toggle(),deleteBoard:this.options.deleteBoard?()=>this.confirmDeleteBoard():void 0,onTitleChange:n=>{this.state.title=n,this.state.emitChange()}},this.state.title),this.perfOverlay=new Ua(t,this.state,this.renderer,this.hitTester,this.monitor,this.imageCache);const e=new _a(this.state);this.stressPanel=new qa(t,e,this.renderer)}setupSelectionOverlays(t,e){this.bottomToolCluster=document.createElement("div"),this.bottomToolCluster.className="bottom-tool-cluster",t.appendChild(this.bottomToolCluster),this.bottomToolCluster.appendChild(this.toolbar.element),this.stickyColorPopover=document.createElement("div"),this.stickyColorPopover.className="context-tool-popover sticky-color-popover",this.stickyColorPopover.setAttribute("aria-hidden","true");for(const s of Ue){const i=document.createElement("button");i.type="button",i.className="sticky-color-btn",i.title="Set sticky color",i.setAttribute("aria-label",`Set sticky color ${s}`),i.style.setProperty("--swatch",s),i.addEventListener("click",()=>this.setSelectedStickyColor(s)),this.stickyColorPopover.appendChild(i)}this.bottomToolCluster.appendChild(this.stickyColorPopover),this.textSizePopover=document.createElement("div"),this.textSizePopover.className="context-tool-popover text-size-popover",this.textSizePopover.setAttribute("aria-hidden","true");for(const s of es){const i=document.createElement("button");i.type="button",i.className="text-size-btn",i.textContent=s.shortLabel,i.setAttribute("aria-label",`Set text size ${s.label}`),i.addEventListener("click",()=>this.setSelectedTextSize(s)),this.textSizePopover.appendChild(i)}this.bottomToolCluster.appendChild(this.textSizePopover),this.shapeStylePopover=document.createElement("div"),this.shapeStylePopover.className="context-tool-popover shape-style-popover",this.shapeStylePopover.setAttribute("aria-hidden","true");for(const s of Ga){const i=document.createElement("button");i.type="button",i.className="shape-fill-btn",i.title="Set shape color",i.setAttribute("aria-label",`Set shape color ${s}`),i.style.setProperty("--swatch",s),i.addEventListener("click",()=>this.setSelectedShapeFill(s)),this.shapeStylePopover.appendChild(i)}const n=document.createElement("div");n.className="context-tool-divider",this.shapeStylePopover.appendChild(n);for(const s of Za){const i=document.createElement("button");i.type="button",i.className="shape-text-color-btn",i.textContent=s.value==="#ffffff"?"W":"B",i.setAttribute("aria-label",s.label),i.addEventListener("click",()=>this.setSelectedShapeTextColor(s.value)),this.shapeStylePopover.appendChild(i)}this.bottomToolCluster.appendChild(this.shapeStylePopover),this.surface.interactionLayer.addEventListener("contextmenu",s=>this.openLayerMenu(s),{signal:e,capture:!0}),document.addEventListener("pointerdown",s=>{this.layerMenu&&!this.layerMenu.contains(s.target)&&this.closeLayerMenu()},{signal:e}),document.addEventListener("keydown",s=>{s.key==="Escape"&&this.closeLayerMenu()},{signal:e})}updateContextualToolPanels(){this.updateStickyColorPopover(),this.updateTextSizePopover(),this.updateShapeStylePopover()}setContextPanelVisible(t,e){t&&(t.classList.toggle("is-visible",e),t.setAttribute("aria-hidden",String(!e)))}updateStickyColorPopover(){var i;const t=this.stickyColorPopover;if(!t)return;const e=this.state.getSelected().filter(a=>a.type==="sticky"),n=e.length>0&&!this.textEditor.isEditing;if(this.setContextPanelVisible(t,n),!n)return;const s=(i=e[0])==null?void 0:i.style.fill;for(const a of t.children){const r=a,c=r.style.getPropertyValue("--swatch")===s;r.classList.toggle("active",c),r.setAttribute("aria-pressed",String(c))}}setSelectedStickyColor(t){ua(t);const e=this.state.getSelected().filter(r=>r.type==="sticky"&&!r.locked);if(e.length===0)return;const n=this.state,s=e.map(r=>({id:r.id,fill:r.style.fill,textColor:r.style.textColor,updatedAt:r.updatedAt})),i=e.map(r=>({id:r.id,fill:t,textColor:"#1f2933",updatedAt:Date.now()})),a=r=>{for(const c of r){const l=n.elementsById.get(c.id);l&&(l.style.fill=c.fill,l.style.textColor=c.textColor,l.updatedAt=c.updatedAt)}n.emitChange()};this.commands.execute("sticky-color",()=>a(i),()=>a(s))}updateTextSizePopover(){var i,a;const t=this.textSizePopover;if(!t)return;const e=this.selectedTextTargets(),n=e.length>0&&!this.textEditor.isEditing;if(this.setContextPanelVisible(t,n),!n)return;const s=((i=e[0])==null?void 0:i.style.fontSize)??(((a=e[0])==null?void 0:a.type)==="sticky"?15:16);for(const r of t.children){const c=r,l=es.find(h=>h.shortLabel===c.textContent),d=(l==null?void 0:l.fontSize)===s;c.classList.toggle("active",d),c.setAttribute("aria-pressed",String(d))}}selectedTextTargets(){return this.state.getSelected().filter(t=>Ka.has(t.type)&&!t.locked)}setSelectedTextSize(t){const e=this.selectedTextTargets();if(e.length===0)return;const n=this.state,s=e.map(r=>({id:r.id,fontSize:r.style.fontSize,fontWeight:r.style.fontWeight,height:r.height,updatedAt:r.updatedAt})),i=e.map(r=>({id:r.id,fontSize:t.fontSize,fontWeight:t.fontWeight,height:r.type==="text"?Math.max(r.height,Math.ceil(t.fontSize*1.45)):r.height,updatedAt:Date.now()})),a=r=>{for(const c of r){const l=n.elementsById.get(c.id);l&&(l.style.fontSize=c.fontSize,l.style.fontWeight=c.fontWeight,l.height=c.height,l.updatedAt=c.updatedAt,G(l.id))}n.emitChange()};this.commands.execute("text-size",()=>a(i),()=>a(s))}updateShapeStylePopover(){var a,r;const t=this.shapeStylePopover;if(!t)return;const e=this.selectedShapeTargets(),n=e.length>0&&!this.textEditor.isEditing;if(this.setContextPanelVisible(t,n),!n)return;const s=(a=e[0])==null?void 0:a.style.fill,i=((r=e[0])==null?void 0:r.style.textColor)??"#1f2933";for(const c of t.children){const l=c;if(l.classList.contains("shape-fill-btn")){const d=l.style.getPropertyValue("--swatch")===s;l.classList.toggle("active",d),l.setAttribute("aria-pressed",String(d))}if(l.classList.contains("shape-text-color-btn")){const h=l.textContent==="W"?i==="#ffffff":i!=="#ffffff";l.classList.toggle("active",h),l.setAttribute("aria-pressed",String(h))}}}selectedShapeTargets(){return this.state.getSelected().filter(t=>Va.has(t.type)&&!t.locked)}setSelectedShapeFill(t){const e=this.selectedShapeTargets();if(e.length===0)return;const n=this.state,s=e.map(r=>({id:r.id,fill:r.style.fill,updatedAt:r.updatedAt})),i=e.map(r=>({id:r.id,fill:t,updatedAt:Date.now()})),a=r=>{for(const c of r){const l=n.elementsById.get(c.id);l&&(l.style.fill=c.fill,l.updatedAt=c.updatedAt)}n.emitChange()};this.commands.execute("shape-fill",()=>a(i),()=>a(s))}setSelectedShapeTextColor(t){const e=this.selectedShapeTargets();if(e.length===0)return;const n=this.state,s=e.map(r=>({id:r.id,textColor:r.style.textColor,updatedAt:r.updatedAt})),i=e.map(r=>({id:r.id,textColor:t,updatedAt:Date.now()})),a=r=>{for(const c of r){const l=n.elementsById.get(c.id);l&&(l.style.textColor=c.textColor,l.updatedAt=c.updatedAt,G(l.id))}n.emitChange()};this.commands.execute("shape-text-color",()=>a(i),()=>a(s))}openLayerMenu(t){if(t.preventDefault(),t.stopPropagation(),this.textEditor.isEditing)return;const e=A(t.clientX,t.clientY,this.state.viewport),n=this.hitTester.hitTest(e.x,e.y,this.state.viewport.scale);n&&!this.state.selectedIds.has(n.id)&&(this.state.clearSelection(),this.state.selectedIds.add(n.id),this.state.requestRender());const s=this.state.getSelected();if(s.length===0){this.closeLayerMenu();return}this.closeLayerMenu();const i=document.createElement("div");i.className="layer-menu",i.setAttribute("role","menu");const a=document.createElement("div");a.className="layer-menu-label",a.textContent=s.length===1?"Layer":`${s.length} layers`,i.appendChild(a);const r=(l,d)=>{const h=document.createElement("button");h.type="button",h.setAttribute("role","menuitem"),h.textContent=l,h.addEventListener("click",()=>{d(),this.closeLayerMenu()}),i.appendChild(h)},c=()=>{const l=document.createElement("div");l.className="layer-menu-divider",i.appendChild(l)};r("Bring forward",()=>this.actions.bringForward()),r("Send backward",()=>this.actions.sendBackward()),c(),r("Bring to front",()=>this.actions.bringToFront()),r("Send to back",()=>this.actions.sendToBack()),this.root.appendChild(i),this.layerMenu=i,this.positionLayerMenu(i,t.clientX,t.clientY)}positionLayerMenu(t,e,n){t.style.left="0px",t.style.top="0px",requestAnimationFrame(()=>{const i=t.getBoundingClientRect(),a=Math.min(Math.max(12,e),window.innerWidth-i.width-12),r=Math.min(Math.max(12,n),window.innerHeight-i.height-12);t.style.left=`${a}px`,t.style.top=`${r}px`})}closeLayerMenu(){var t;(t=this.layerMenu)==null||t.remove(),this.layerMenu=null}exitToDocs(){this.boardSaveTimer!==null&&(clearTimeout(this.boardSaveTimer),this.boardSaveTimer=null),this.saveBoard().then(t=>{var e,n;t&&((n=(e=this.options).onExit)==null||n.call(e))})}startEmbedSelection(){Sn.begin(this.root,t=>{t&&this.copyEmbedSnippet(t)})}async copyEmbedSnippet(t){const e=this.state.viewport,n=A(t.x,t.y,e),s=A(t.x+t.w,t.y+t.h,e),i=Math.round(n.x),a=Math.round(n.y),r=Math.round(s.x-n.x),c=Math.round(s.y-n.y),l=`\`\`\`board
|
|
16
|
+
src: /${this.state.boardId}
|
|
17
|
+
region: ${i}, ${a}, ${r}, ${c}
|
|
18
|
+
height: 360
|
|
19
|
+
title: ${this.state.title}
|
|
20
|
+
\`\`\``;try{await navigator.clipboard.writeText(l),C("Embed snippet copied — paste it into any doc")}catch{C("Could not access clipboard")}}setupDragDrop(t){t.addEventListener("dragover",e=>{e.preventDefault(),e.dataTransfer&&(e.dataTransfer.dropEffect="copy")}),t.addEventListener("drop",e=>{var n;e.preventDefault(),(n=e.dataTransfer)!=null&&n.files&&e.dataTransfer.files.length>0&&this.imageInsert.insertFiles(e.dataTransfer.files,e.clientX,e.clientY)})}async loadInitialState(){this.suppressPersistence=!0;const t=ct.getPref("theme");if(t==="dark"||t==="light"?this.applyTheme(t):window.matchMedia("(prefers-color-scheme: dark)").matches&&this.applyTheme("dark"),this.options.loadBoard){try{const n=await this.options.loadBoard(this.options.boardId??this.state.boardId);n&&(this.revision=n.revision,this.stale=!1,this.applyDocument(n.doc),this.fitInitialRegion())}catch(n){console.error("Board file load failed",n),C("Could not load board file")}finally{this.suppressPersistence=!1}this.state.requestRender();return}const e=ct.getPref("lastBoardId")??"default-board";try{const n=await ct.loadBoard(e);n&&this.applyDocument(n)}catch(n){console.error("Board recovery failed",n),ct.getPref("recovery")&&C("Could not load saved board — starting fresh")}this.suppressPersistence=!1,this.state.requestRender()}applyDocument(t){this.state.schemaUrl=t.$schema,this.state.boardId=t.id,this.state.title=t.title,this.state.createdAt=t.createdAt,this.state.viewport={...t.viewport},this.state.elements=[],this.state.elementsById.clear();for(const e of t.elements)this.state.addElement(e);this.applyTheme(t.theme),this.topControls.setTitle(t.title),this.topControls.setZoom(t.viewport.scale),this.state.invalidateSort()}fitInitialRegion(){const t=this.options.initialRegion;if(!t)return;const[e,n,s,i]=t;if(s<=0||i<=0)return;const a=Math.min(120,Math.max(48,this.surface.width*.08)),r=88,c=124,l=Math.max(240,this.surface.width-a*2),d=Math.max(180,this.surface.height-r-c),h=Math.min(l/s,d/i),p=Math.max(.7,Math.min(1.1,this.state.viewport.scale*1.15)),u=Ws(Math.min(h*.58,p));this.state.viewport={scale:u,offsetX:a+(l-s*u)/2-e*u,offsetY:r+(d-i*u)/2-n*u},this.topControls.setZoom(u)}scheduleBoardSave(){this.boardSaveTimer!==null&&clearTimeout(this.boardSaveTimer),this.boardSaveTimer=window.setTimeout(()=>{this.boardSaveTimer=null,this.saveBoard()},Xa)}scheduleViewportSave(){this.viewportSaveTimer===null&&(this.viewportSaveTimer=window.setTimeout(()=>{this.viewportSaveTimer=null,this.saveBoard()},Ya))}async saveBoard(){if(this.saveInFlight)return this.saveQueued=!0,this.saveInFlight;const t=async()=>{if(this.stale)return C("Board changed elsewhere — reload before saving"),this.setBoardStatus("Changed elsewhere","stale"),!1;try{return this.options.saveBoard?(this.revision=await this.options.saveBoard(Ee(this.state)),this.stale=!1,this.setBoardStatus("Saved","saved")):await ct.saveBoard(Ee(this.state)),!0}catch(n){return n instanceof fe?(this.revision=n.currentRevision,this.stale=!0,this.setBoardStatus("Changed elsewhere","stale"),C("Board changed elsewhere — reload before saving"),!1):(C(this.options.saveBoard?"Save to file failed":"Save failed — browser storage may be full"),this.options.saveBoard&&this.setBoardStatus("Save failed","error"),!1)}};this.saveInFlight=t();const e=await this.saveInFlight;return this.saveInFlight=null,this.saveQueued&&!this.stale?(this.saveQueued=!1,this.saveBoard()):(this.saveQueued=!1,e)}markStale(){this.stale=!0,this.setBoardStatus("Changed elsewhere","stale")}async reloadLatest(){if(this.options.loadBoard&&window.confirm("Discard local edits and reload the latest board version?"))try{this.suppressPersistence=!0;const t=await this.options.loadBoard(this.options.boardId??this.state.boardId);if(!t){C("Could not reload board file"),this.suppressPersistence=!1;return}this.revision=t.revision,this.stale=!1,this.applyDocument(t.doc),this.state.requestRender(),this.setBoardStatus("Reloaded latest","saved")}catch{this.setBoardStatus("Reload failed","error"),C("Could not reload board file")}finally{this.suppressPersistence=!1}}setBoardStatus(t,e){var n;(n=this.topControls)==null||n.setStatus(t,e,e==="stale"&&this.options.loadBoard?{label:"Reload latest",onClick:()=>void this.reloadLatest()}:void 0)}applyTheme(t){var e;this.state.theme=t,document.documentElement.setAttribute("data-theme",t),ct.setPref("theme",t),(e=this.toolbar)==null||e.setTheme(t),this.state.requestRender()}toggleTheme(){this.applyTheme(this.state.theme==="dark"?"light":"dark"),this.scheduleBoardSave()}resetView(){this.state.viewport.offsetX=0,this.state.viewport.offsetY=0,this.state.viewport.scale=js,this.state.requestRender()}clearBoard(){const t=this.state,e=[...t.elements];this.commands.execute("clear-board",()=>{for(const n of e)t.removeElement(n.id);t.emitChange()},()=>{for(const n of e)t.elementsById.has(n.id)||t.addElement(n);t.emitChange()}),C("Board cleared")}async resetAllLocalData(){await ct.clearAllBoards(),await pt.clearAll(),ct.clearPrefs(),this.imageCache.clear(),this.commands.clear(),this.state.elements=[],this.state.elementsById.clear(),this.state.clearSelection(),this.state.invalidateSort(),this.resetView(),C("All local data cleared")}confirmDeleteBoard(){V("Delete board?",(t,e)=>{const n=document.createElement("p");n.className="modal-copy",n.textContent=`This will permanently delete "${this.state.title}" from the active docs root. This cannot be undone.`;const s=document.createElement("div");s.className="modal-actions";const i=document.createElement("button");i.className="btn",i.textContent="Cancel",i.addEventListener("click",e);const a=document.createElement("button");a.className="btn danger",a.textContent="Delete board",a.addEventListener("click",async()=>{var r,c,l;a.disabled=!0,this.boardSaveTimer!==null&&(clearTimeout(this.boardSaveTimer),this.boardSaveTimer=null),this.viewportSaveTimer!==null&&(clearTimeout(this.viewportSaveTimer),this.viewportSaveTimer=null);try{await((c=(r=this.options).deleteBoard)==null?void 0:c.call(r,this.state.boardId)),e(),C("Board deleted"),(l=this.options.onDeleted??this.options.onExit)==null||l()}catch{a.disabled=!1,C("Could not delete board")}}),s.append(i,a),t.append(n,s)})}openExportMenu(){V("Export & import",(t,e)=>{const n=document.createElement("div");n.className="modal-actions",n.style.flexDirection="column",n.style.alignItems="stretch";const s=(i,a,r=!1)=>{const c=document.createElement("button");c.className="btn"+(r?" primary":""),c.textContent=i,c.addEventListener("click",()=>{a(),e()}),n.appendChild(c)};s("Export current view as PNG",async()=>{const i=await Gi(this.state,this.imageCache,this.surface.width,this.surface.height);Kn(i,this.state.title+"-view.png")},!0),s("Export full board as PNG",async()=>{const i=await Zi(this.state,this.imageCache);i?Kn(i,this.state.title+"-board.png"):C("Board is empty")}),s("Export board JSON (no images)",()=>{rn.exportBoardJson(Ee(this.state))}),s("Export full bundle (JSON + images)",async()=>{await rn.exportFullBundle(Ee(this.state))}),s("Import board from file…",()=>this.pickImportFile()),t.appendChild(n)})}pickImportFile(){const t=document.createElement("input");t.type="file",t.accept="application/json,.json",t.onchange=async()=>{var s;const e=(s=t.files)==null?void 0:s[0];if(!e)return;const n=await rn.importFromFile(e);if(!n){C("Import failed — invalid board file");return}this.state.boardId=n.id,this.state.title=n.title,this.state.createdAt=n.createdAt,this.state.viewport={...n.viewport},this.state.elements=[],this.state.elementsById.clear(),this.state.clearSelection();for(const i of n.elements)this.state.addElement(i);this.applyTheme(n.theme),this.topControls.setTitle(n.title),this.commands.clear(),this.state.emitChange(),C("Board imported")},t.click()}}const ns="/__api/asset?path=",Ys=new Set(["P","DIV","UL","OL","H1","H2","H3","H4","H5","H6","BLOCKQUOTE","PRE","TABLE","FIGURE","HR"]);function Qa(o){const t=[];for(const e of Array.from(o.childNodes))Tn(t,e);return t.map(e=>e.replace(/[ \t]+$/gm,"")).join(`
|
|
21
|
+
|
|
22
|
+
`).replace(/\n{3,}/g,`
|
|
23
|
+
|
|
24
|
+
`).trim()+`
|
|
25
|
+
`}function Tn(o,t){const e=tr(t);e!==null&&e.trim()!==""&&o.push(e)}function tr(o){if(o.nodeType===Node.TEXT_NODE){const n=(o.textContent??"").trim();return n||null}if(o.nodeType!==Node.ELEMENT_NODE)return null;const t=o,e=t.tagName;switch(e){case"H1":case"H2":case"H3":case"H4":case"H5":case"H6":return"#".repeat(Number(e[1]))+" "+xt(t).trim();case"HR":return"---";case"P":return t.classList.contains("embed-caret-spacer")&&!nr(t)?null:os(t)?is(t):xn(xt(t).trim());case"BLOCKQUOTE":return ss(t).split(`
|
|
26
|
+
`).map(s=>s?`> ${s}`:">").join(`
|
|
27
|
+
`);case"UL":return _e(t,!1,0);case"OL":return _e(t,!0,0);case"PRE":{const n=t.querySelector("code"),s=ar(n??t),i=(n??t).textContent??"";return"```"+s+`
|
|
28
|
+
`+i.replace(/\n$/,"")+"\n```"}case"TABLE":return sr(t);case"FIGURE":return t.classList.contains("board-embed")?or(t):ss(t)||null;case"DIV":return os(t)?is(t):xn(xt(t).trim());case"BR":return null;default:return xt(t).trim()||null}}function ss(o){const t=[];for(const e of Array.from(o.childNodes))Tn(t,e);return t.join(`
|
|
29
|
+
|
|
30
|
+
`)}function os(o){for(const t of Array.from(o.children))if(Ys.has(t.tagName))return!0;return!1}function is(o){const t=[];let e="";const n=()=>{const s=xn(e.trim());s&&t.push(s),e=""};for(const s of Array.from(o.childNodes)){if(er(s)){n(),Tn(t,s);continue}e+=Bn(s)}return n(),t.join(`
|
|
31
|
+
|
|
32
|
+
`)||null}function er(o){return o.nodeType===Node.ELEMENT_NODE&&Ys.has(o.tagName)}function nr(o){for(const t of Array.from(o.childNodes)){if(t.nodeType===Node.TEXT_NODE&&(t.textContent??"").trim())return!0;if(t.nodeType!==Node.ELEMENT_NODE)continue;const e=t;if(e.tagName!=="BR"&&((e.textContent??"").trim()||["IMG","FIGURE","HR"].includes(e.tagName)))return!0}return!1}function _e(o,t,e){const n=[],s=" ".repeat(e);let i=0;for(const a of Array.from(o.children)){if(a.tagName!=="LI")continue;i++;const r=t?`${i}. `:"- ";let c="";const l=[];let d=null;for(const h of Array.from(a.childNodes)){if(h.nodeType===Node.ELEMENT_NODE){const p=h;if(p.tagName==="UL"){l.push(_e(p,!1,e+1));continue}if(p.tagName==="OL"){l.push(_e(p,!0,e+1));continue}if(p.tagName==="INPUT"){d=p.checked?"[x] ":"[ ] ";continue}}c+=Bn(h)}n.push(s+r+(d??"")+c.trim());for(const h of l)h&&n.push(h)}return n.join(`
|
|
33
|
+
`)}function sr(o){const t=Array.from(o.querySelectorAll("tr"));if(t.length===0)return"";const e=i=>Array.from(i.querySelectorAll("th,td")).map(a=>xt(a).trim()),n=e(t[0]),s=[];s.push("| "+n.join(" | ")+" |"),s.push("| "+n.map(()=>"---").join(" | ")+" |");for(let i=1;i<t.length;i++)s.push("| "+e(t[i]).join(" | ")+" |");return s.join(`
|
|
34
|
+
`)}function or(o){const t=["```board",`src: ${o.dataset.src??""}`];return o.dataset.region&&t.push(`region: ${o.dataset.region.split(",").map(e=>e.trim()).join(", ")}`),o.dataset.height&&t.push(`height: ${o.dataset.height}`),o.dataset.title&&t.push(`title: ${o.dataset.title}`),t.push("```"),t.join(`
|
|
35
|
+
`)}function xt(o){let t="";for(const e of Array.from(o.childNodes))t+=Bn(e);return t}function Bn(o){if(o.nodeType===Node.TEXT_NODE)return rs(o.textContent??"");if(o.nodeType!==Node.ELEMENT_NODE)return"";const t=o;switch(t.tagName){case"STRONG":case"B":return as("**",xt(t));case"EM":case"I":return as("*",xt(t));case"CODE":return rr(t.textContent??"");case"A":{const e=(t.getAttribute("data-md-href")??t.getAttribute("href")??"").trim(),n=xt(t).trim()||rs(e);return e?`[${cs(n)}](${ls(e)})`:n}case"IMG":return`)})`;case"BR":return`
|
|
36
|
+
`;default:return xt(t)}}function ir(o){const t=o.getAttribute("data-md-src");if(t)return t;const e=o.getAttribute("src")??"";return e.startsWith(ns)?decodeURIComponent(e.slice(ns.length)):e}function ar(o){const e=(o.getAttribute("class")??"").match(/language-(\w+)/);return e?e[1]:""}function as(o,t){const e=t.trim();return e?`${o}${e}${o}`:""}function rr(o){if(!o.includes("`"))return"`"+o+"`";const t=Math.max(...(o.match(/`+/g)??[""]).map(n=>n.length)),e="`".repeat(t+1);return`${e} ${o} ${e}`}function rs(o){return o.replace(/\\/g,"\\\\").replace(/\[/g,"\\[").replace(/\]/g,"\\]").replace(/\*/g,"\\*").replace(/_/g,"\\_").replace(/`/g,"\\`")}function xn(o){return o?/^#{1,6}\s/.test(o)||/^>\s?/.test(o)||/^([-+*]|\d+\.)\s+/.test(o)||/^`{3,}/.test(o)||/^(-{3,}|\*{3,}|_{3,})$/.test(o)?"\\"+o:o:null}function cs(o){return o.replace(/\\/g,"\\\\").replace(/\]/g,"\\]")}function ls(o){return o.trim().replace(/\s/g,"%20").replace(/\)/g,"%29").replace(/</g,"%3C").replace(/>/g,"%3E")}class Mn{constructor(t){m(this,"opts");m(this,"overlay");m(this,"scrollEl");m(this,"surface");m(this,"statusEl");m(this,"statusTextEl");m(this,"reloadBtn");m(this,"fileInput");m(this,"toolbarButtons",[]);m(this,"abort",new AbortController);m(this,"frontmatter","");m(this,"revision",null);m(this,"stale",!1);m(this,"saveTimer",null);m(this,"closed",!1);m(this,"history",[]);m(this,"historyIndex",-1);m(this,"applyingHistory",!1);this.opts=t,this.build(),this.load()}static open(t){return new Mn(t)}build(){this.overlay=yt("doc-editor");const t=yt("doc-editor-bar"),e=yt("doc-editor-bar-left"),n=ln("doc-editor-done","Done");n.addEventListener("click",()=>void this.close());const s=yt("doc-editor-path");s.textContent=this.opts.path,e.append(n,s),this.statusEl=yt("doc-editor-status"),this.statusTextEl=document.createElement("span"),this.reloadBtn=ln("status-action-btn","Reload latest"),this.reloadBtn.hidden=!0,this.reloadBtn.addEventListener("click",()=>void this.reloadLatest()),this.statusEl.append(this.statusTextEl,this.reloadBtn),this.setStatus("idle"),t.append(e,this.statusEl);const i=this.buildToolbar();this.scrollEl=yt("doc-editor-scroll"),this.surface=yt("markdown-body doc-editor-surface"),this.surface.contentEditable="true",this.surface.spellcheck=!0,this.scrollEl.appendChild(this.surface),this.fileInput=document.createElement("input"),this.fileInput.type="file",this.fileInput.accept="image/*",this.fileInput.style.display="none",this.fileInput.addEventListener("change",()=>{var c;const r=(c=this.fileInput.files)==null?void 0:c[0];r&&this.insertImageFile(r),this.fileInput.value=""}),this.overlay.append(t,i,this.scrollEl,this.fileInput),document.body.appendChild(this.overlay);const a=this.abort.signal;this.surface.addEventListener("input",()=>this.handleInput(),{signal:a}),this.surface.addEventListener("keyup",()=>this.updateToolbarState(),{signal:a}),this.surface.addEventListener("mouseup",()=>this.updateToolbarState(),{signal:a}),this.surface.addEventListener("click",r=>this.handleSurfaceClick(r),{signal:a}),document.addEventListener("selectionchange",()=>this.updateToolbarState(),{signal:a}),this.surface.addEventListener("paste",r=>this.onPaste(r),{signal:a}),this.surface.addEventListener("dragover",r=>r.preventDefault(),{signal:a}),this.surface.addEventListener("drop",r=>this.onDrop(r),{signal:a}),window.addEventListener("keydown",r=>{if(r.key==="Escape"&&document.activeElement!==this.surface&&this.close(),(r.metaKey||r.ctrlKey)&&r.key.toLowerCase()==="s"&&(r.preventDefault(),this.save()),(r.metaKey||r.ctrlKey)&&r.key.toLowerCase()==="z"){r.preventDefault(),r.shiftKey?this.redoHistory():this.undoHistory();return}if(r.ctrlKey&&!r.metaKey&&r.key.toLowerCase()==="y"){r.preventDefault(),this.redoHistory();return}this.handleEmbedDeleteKey(r)},{signal:a})}buildToolbar(){const t=yt("doc-editor-toolbar"),e=s=>{const i=yt("doc-editor-tb-group");return i.append(...s),i},n=(s,i,a,r=!1)=>{const c=ln("doc-editor-tb-btn",r?"":s);return r&&(c.innerHTML=Y[s]??"",c.classList.add("icon")),c.title=i,c.addEventListener("mousedown",l=>{l.preventDefault(),this.surface.focus(),a(),this.updateToolbarState(),this.scheduleSave()}),this.toolbarButtons.push(c),c};return t.append(e([n("¶","Paragraph",()=>this.formatBlock("P")),bt(n("H1","Heading 1",()=>this.formatBlock("H1")),"block","H1"),bt(n("H2","Heading 2",()=>this.formatBlock("H2")),"block","H2"),bt(n("H3","Heading 3",()=>this.formatBlock("H3")),"block","H3")]),e([bt(n("B","Bold (Cmd+B)",()=>document.execCommand("bold")),"command","bold"),bt(n("I","Italic (Cmd+I)",()=>document.execCommand("italic")),"command","italic"),bt(n("</>","Inline code",()=>this.toggleInlineCode()),"inline","CODE")]),e([bt(n("❝","Quote",()=>this.formatBlock("BLOCKQUOTE")),"block","BLOCKQUOTE"),bt(n("•","Bulleted list",()=>document.execCommand("insertUnorderedList")),"command","insertUnorderedList"),bt(n("1.","Numbered list",()=>document.execCommand("insertOrderedList")),"command","insertOrderedList"),n("{ }","Code block",()=>this.insertCodeBlock())]),e([n("↗","Link",()=>this.insertLink()),n("image","Image",()=>this.fileInput.click(),!0),n("―","Divider",()=>document.execCommand("insertHorizontalRule"))])),t}async load(t=this.opts.initialScrollTop??0,e=this.opts.initialScrollProgress){try{const n=await k.readFileWithRevision(this.opts.rootId,this.opts.path);this.revision=n.revision,this.stale=!1;const s=n.content,{fm:i,body:a}=lr(s);this.frontmatter=i;const{html:r}=Zt(a,{rootId:this.opts.rootId,docPath:this.opts.path});this.surface.innerHTML=r||"<p></p>",this.decorateEmbeds(),document.execCommand("defaultParagraphSeparator",!1,"p"),this.recordHistorySnapshot(!0),this.updateToolbarState(),this.setStatus("idle"),requestAnimationFrame(()=>{if(!this.closed){if(typeof e=="number"){cr(this.scrollEl,e);return}this.scrollEl.scrollTop=t}})}catch{this.surface.innerHTML="<p></p>",this.setStatus("error","Could not load file");return}}decorateEmbeds(){this.normalizeEmbedSpacing(),this.surface.querySelectorAll("figure.board-embed").forEach(t=>{t.contentEditable="false",t.tabIndex=0,t.setAttribute("role","button"),t.setAttribute("aria-label",`Board embed ${t.dataset.src??""}. Press Delete to remove.`),t.classList.add("embed-chip");const e=t.dataset.region?" · region":"";t.innerHTML=`<span class="embed-chip-icon">▦</span> Board embed: <strong>${t.dataset.src??""}</strong>${e}<span class="embed-chip-remove" aria-hidden="true">Delete</span>`,this.ensureEmbedCaretSpace(t)})}ensureEmbedCaretSpace(t){Rt(t.previousElementSibling)||t.before(de()),Rt(t.nextElementSibling)||t.after(de())}normalizeEmbedSpacing(){const t=Array.from(this.surface.querySelectorAll("figure.board-embed"));for(const n of t)ds(n.previousElementSibling),ds(n.nextElementSibling);let e=!1;for(const n of Array.from(this.surface.children)){if(!Rt(n)){e=!1;continue}if(Ks(n)){n.classList.remove("embed-caret-spacer"),e=!1;continue}if(e){n.remove();continue}e=!0}}handleSurfaceClick(t){const e=t.target,n=e==null?void 0:e.closest("figure.board-embed.embed-chip");!n||!this.surface.contains(n)||(t.preventDefault(),this.selectEmbed(n))}selectEmbed(t){this.surface.querySelectorAll(".embed-chip.selected").forEach(s=>s.classList.remove("selected")),t.classList.add("selected");const e=document.createRange();e.selectNode(t);const n=window.getSelection();n==null||n.removeAllRanges(),n==null||n.addRange(e),t.focus()}clearEmbedSelection(){this.surface.querySelectorAll(".embed-chip.selected").forEach(t=>t.classList.remove("selected"))}handleEmbedDeleteKey(t){if(t.key!=="Backspace"&&t.key!=="Delete")return!1;const e=document.activeElement,s=(e==null?void 0:e.closest("figure.board-embed.embed-chip.selected"))??this.surface.querySelector("figure.board-embed.embed-chip.selected")??this.embedAdjacentToCaret(t.key);if(!s||!this.surface.contains(s))return!1;t.preventDefault();const i=t.key==="Backspace"?s.previousElementSibling:s.nextElementSibling;return s.remove(),this.clearEmbedSelection(),this.placeCaretInBlock(Rt(i)?i:this.surface),this.recordHistorySnapshot(),this.scheduleSave(),!0}embedAdjacentToCaret(t){const e=window.getSelection();if(!e||e.rangeCount===0||!e.isCollapsed)return null;const n=e.anchorNode,s=dr(n,"P");if(!s||!this.surface.contains(s)||!Rt(s))return null;const i=t==="Backspace"?s.previousElementSibling:s.nextElementSibling;return i instanceof HTMLElement&&i.matches("figure.board-embed.embed-chip")?i:null}handleInput(){this.applyingHistory||(this.clearEmbedSelection(),this.recordHistorySnapshot(),this.scheduleSave())}placeCaretInBlock(t){const e=document.createRange();e.selectNodeContents(t),e.collapse(!1);const n=window.getSelection();n==null||n.removeAllRanges(),n==null||n.addRange(e),this.surface.focus()}scheduleSave(){this.normalizeEmbedSpacing(),this.saveTimer!==null&&clearTimeout(this.saveTimer),this.setStatus("saving"),this.saveTimer=window.setTimeout(()=>{this.saveTimer=null,this.save()},700)}async save(){if(this.saveTimer!==null&&(clearTimeout(this.saveTimer),this.saveTimer=null),this.stale)return this.setStatus("stale","Changed elsewhere — reload before saving"),!1;this.normalizeEmbedSpacing();const t=Qa(this.surface),e=this.frontmatter?`${this.frontmatter}
|
|
37
|
+
|
|
38
|
+
${t}`:t;try{return this.setStatus("saving"),this.revision=await k.writeFile(this.opts.rootId,this.opts.path,e,this.revision??void 0),this.stale=!1,this.setStatus("saved"),!0}catch(n){return n instanceof fe?(this.revision=n.currentRevision,this.stale=!0,this.setStatus("stale","Changed elsewhere — reload before saving"),!1):(this.setStatus("error","Save failed"),!1)}}async close(){if(this.closed||!await this.save())return;this.closed=!0;const e=this.scrollEl.scrollTop,n=hs(this.scrollEl);this.abort.abort(),this.overlay.remove(),this.opts.onClose(e,n)}markStale(){this.stale=!0,this.setStatus("stale","Changed elsewhere — reload before saving")}async reloadLatest(){window.confirm("Discard local edits and reload the latest version?")&&(this.saveTimer!==null&&(clearTimeout(this.saveTimer),this.saveTimer=null),await this.load(this.scrollEl.scrollTop,hs(this.scrollEl)))}formatBlock(t){document.execCommand("formatBlock",!1,`<${t}>`)}insertLink(){const t=window.getSelection(),e=t&&!t.isCollapsed?t.toString().trim():"",n=window.prompt("Link URL","https://");if(!n)return;const s=n.trim();s&&(e?document.execCommand("createLink",!1,s):document.execCommand("insertHTML",!1,`<a href="${us(s)}">${fr(s)}</a>`))}toggleInlineCode(){const t=window.getSelection();if(!t||t.rangeCount===0||t.isCollapsed)return;const e=t.getRangeAt(0),n=dn(e.commonAncestorContainer,"CODE");if(n){const i=n.parentNode;for(;n.firstChild;)i.insertBefore(n.firstChild,n);i.removeChild(n);return}const s=document.createElement("code");s.appendChild(e.extractContents()),e.insertNode(s),e.setStartAfter(s),e.collapse(!0),t.removeAllRanges(),t.addRange(e)}insertCodeBlock(){document.execCommand("insertHTML",!1,'<pre class="code-block"><code>code</code></pre><p><br></p>')}updateToolbarState(){const t=window.getSelection(),e=(t==null?void 0:t.anchorNode)??null,n=!!e&&this.surface.contains(e);for(const s of this.toolbarButtons){const i=s.dataset.stateType,a=s.dataset.stateValue;let r=!1;if(n&&i==="command"&&a)try{r=document.queryCommandState(a)}catch{r=!1}else(n&&i==="block"&&a||n&&i==="inline"&&a)&&(r=!!dn(e,a));s.classList.toggle("active",r),s.setAttribute("aria-pressed",r?"true":"false")}}onPaste(t){var s,i;const e=yr(((s=t.clipboardData)==null?void 0:s.getData("text/plain"))??"");if(e){t.preventDefault(),this.insertSpecialBlock(e);return}const n=(i=t.clipboardData)==null?void 0:i.items;if(n){for(const a of n)if(a.type.startsWith("image/")){const r=a.getAsFile();if(r){t.preventDefault(),this.insertImageFile(r);return}}}}insertSpecialBlock(t){this.surface.focus();const e=vr(t);this.insertBlockNode(e),this.decorateEmbeds(),this.selectEmbed(e),this.recordHistorySnapshot(),this.updateToolbarState(),this.scheduleSave()}insertBlockNode(t){const e=window.getSelection(),n=e&&e.rangeCount>0?e.getRangeAt(0):null;if(!n||!this.surface.contains(n.commonAncestorContainer)){this.surface.append(t,de()),this.placeCaretInBlock(this.surface.lastElementChild??this.surface);return}const s=hr(this.surface,n.commonAncestorContainer);if(s&&pr(s)&&!Rt(s)){this.replaceBlockWithInsertedNode(s,n,t);return}n.deleteContents();const i=de();n.insertNode(i),n.insertNode(t),this.placeCaretInBlock(i)}replaceBlockWithInsertedNode(t,e,n){const s=document.createRange();s.selectNodeContents(t),s.setEnd(e.startContainer,e.startOffset);const i=document.createRange();i.selectNodeContents(t),i.setStart(e.endContainer,e.endOffset);const a=ps(t,s.cloneContents()),r=ps(t,i.cloneContents()),c=t.parentNode;if(!c)return;a&&c.insertBefore(a,t),c.insertBefore(n,t),r&&c.insertBefore(r,t),c.removeChild(t);const l=r??de();r||c.insertBefore(l,n.nextSibling),this.placeCaretInBlock(l)}onDrop(t){var n,s;const e=(s=(n=t.dataTransfer)==null?void 0:n.files)==null?void 0:s[0];e&&e.type.startsWith("image/")&&(t.preventDefault(),this.insertImageFile(e))}async insertImageFile(t){this.setStatus("saving","Uploading image…");try{const e=await mr(t),n=await k.uploadAsset(this.opts.rootId,t.name,e),s=wn(this.opts.path,n),i=k.assetUrl(this.opts.rootId,n),a=t.name.replace(/\.[^.]+$/,"");this.surface.focus(),document.execCommand("insertHTML",!1,`<img src="${i}" data-md-src="${s}" alt="${us(a)}" /><p><br></p>`),this.recordHistorySnapshot(),await this.save()}catch{this.setStatus("error","Image upload failed")}}recordHistorySnapshot(t=!1){if(this.applyingHistory)return;this.normalizeEmbedSpacing();const e=this.surface.innerHTML;if(t){this.history=[e],this.historyIndex=0;return}this.history[this.historyIndex]!==e&&(this.history=this.history.slice(0,this.historyIndex+1),this.history.push(e),this.history.length>100&&this.history.shift(),this.historyIndex=this.history.length-1)}undoHistory(){this.historyIndex<=0||this.applyHistorySnapshot(this.historyIndex-1)}redoHistory(){this.historyIndex>=this.history.length-1||this.applyHistorySnapshot(this.historyIndex+1)}applyHistorySnapshot(t){const e=this.history[t];e!==void 0&&(this.applyingHistory=!0,this.historyIndex=t,this.surface.innerHTML=e,this.decorateEmbeds(),this.clearEmbedSelection(),this.placeCaretInBlock(this.surface.lastElementChild??this.surface),this.applyingHistory=!1,this.updateToolbarState(),this.scheduleSave())}setStatus(t,e){const n={idle:"",saving:e??"Saving…",saved:"Saved",stale:e??"Changed elsewhere",error:e??"Couldn't save"};this.statusTextEl.textContent=n[t],this.statusEl.dataset.state=t,this.reloadBtn.hidden=t!=="stale"}}function yt(o){const t=document.createElement("div");return t.className=o,t}function ln(o,t){const e=document.createElement("button");return e.className=o,e.textContent=t,e}function bt(o,t,e){return o.dataset.stateType=t,o.dataset.stateValue=e,o.setAttribute("aria-pressed","false"),o}function de(){const o=document.createElement("p");return o.className="embed-caret-spacer",o.appendChild(document.createElement("br")),o}function Rt(o){return!!o&&o.tagName==="P"&&o.classList.contains("embed-caret-spacer")}function ds(o){Rt(o)&&Ks(o)&&o.classList.remove("embed-caret-spacer")}function Ks(o){for(const t of Array.from(o.childNodes)){if(t.nodeType===Node.TEXT_NODE&&(t.textContent??"").trim())return!0;if(t.nodeType!==Node.ELEMENT_NODE)continue;const e=t;if(e.tagName!=="BR"&&((e.textContent??"").trim()||["IMG","FIGURE","HR"].includes(e.tagName)))return!0}return!1}function hs(o){const t=Math.max(1,o.scrollHeight-o.clientHeight);return o.scrollTop/t}function cr(o,t){const e=Math.max(0,o.scrollHeight-o.clientHeight);o.scrollTop=Math.max(0,Math.min(1,t))*e}function lr(o){if(!o.startsWith("---"))return{fm:"",body:o};const t=o.indexOf(`
|
|
39
|
+
---`,3);if(t===-1)return{fm:"",body:o};const e=o.slice(0,t+4),n=o.slice(t+4).replace(/^\n+/,"");return{fm:e,body:n}}function dn(o,t){let e=o;for(;e;){if(e.nodeType===Node.ELEMENT_NODE&&e.tagName===t)return e;e=e.parentNode}return null}function dr(o,t){let e=o;for(;e;){if(e.nodeType===Node.ELEMENT_NODE&&e.matches(t))return e;e=e.parentNode}return null}function hr(o,t){let e=t;for(;e&&e.parentNode!==o;)e=e.parentNode;return e instanceof HTMLElement?e:null}function pr(o){return o.tagName==="P"||o.tagName==="DIV"}function ps(o,t){if(!ur(t))return null;const e=document.createElement(o.tagName);return o.tagName==="P"&&o.classList.contains("embed-caret-spacer")&&(e.className="embed-caret-spacer"),e.appendChild(t),e}function ur(o){for(const t of Array.from(o.childNodes)){if(t.nodeType===Node.TEXT_NODE&&(t.textContent??"").trim())return!0;if(t.nodeType!==Node.ELEMENT_NODE)continue;const e=t;if(e.tagName!=="BR"&&!(e.tagName==="P"&&e.classList.contains("embed-caret-spacer"))&&((e.textContent??"").trim()||["IMG","FIGURE","HR"].includes(e.tagName)))return!0}return!1}function mr(o){return new Promise((t,e)=>{const n=new FileReader;n.onload=()=>{const s=n.result;t(s.slice(s.indexOf(",")+1))},n.onerror=()=>e(n.error),n.readAsDataURL(o)})}function us(o){return o.replace(/&/g,"&").replace(/"/g,""").replace(/</g,"<")}function fr(o){return o.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">")}const gr={board:o=>{const t=As(o);return t.src?{kind:"board",src:t.src,region:t.region,height:t.height,title:t.title}:null}};function yr(o){const t=br(o);if(!t)return null;const e=gr[t.language];return e?e(t.body):null}function br(o){const e=o.trim().match(/^(`{3,})\s*([^\s`]+)?\s*\n([\s\S]*?)\n\1\s*$/);return e?{language:(e[2]??"").toLowerCase(),body:e[3]}:null}function vr(o){switch(o.kind){case"board":return xr(o)}}function xr(o){const t=document.createElement("figure");return t.className="board-embed",t.dataset.src=o.src,t.dataset.height=String(o.height),o.region&&(t.dataset.region=o.region.join(",")),o.title&&(t.dataset.title=o.title),t}class Ln{constructor(t){m(this,"opts");m(this,"root");m(this,"statusEl");m(this,"statusTextEl");m(this,"reloadBtn");m(this,"textarea");m(this,"abort",new AbortController);m(this,"revision",null);m(this,"stale",!1);m(this,"saveTimer",null);m(this,"closed",!1);this.opts=t,this.build(),this.load()}static open(t){return new Ln(t)}build(){this.root=qt("doc-editor text-file-editor");const t=qt("doc-editor-bar"),e=qt("doc-editor-bar-left"),n=ms("doc-editor-done","Done");n.addEventListener("click",()=>void this.close());const s=qt("doc-editor-path");s.textContent=this.opts.path,e.append(n,s),this.statusEl=qt("doc-editor-status"),this.statusTextEl=document.createElement("span"),this.reloadBtn=ms("status-action-btn","Reload latest"),this.reloadBtn.hidden=!0,this.reloadBtn.addEventListener("click",()=>void this.reloadLatest()),this.statusEl.append(this.statusTextEl,this.reloadBtn),this.setStatus("idle"),t.append(e,this.statusEl);const i=qt("doc-editor-scroll text-file-editor-scroll");this.textarea=document.createElement("textarea"),this.textarea.className="text-file-editor-textarea",this.textarea.spellcheck=!1,i.appendChild(this.textarea),this.root.append(t,i),this.opts.host.appendChild(this.root);const a=this.abort.signal;this.textarea.addEventListener("input",()=>this.scheduleSave(),{signal:a}),window.addEventListener("keydown",r=>{if((r.metaKey||r.ctrlKey)&&r.key.toLowerCase()==="s"){r.preventDefault(),this.save();return}r.key==="Escape"&&document.activeElement!==this.textarea&&this.close()},{signal:a})}async load(){try{const t=await k.readFileWithRevision(this.opts.rootId,this.opts.path);this.revision=t.revision,this.stale=!1,this.textarea.value=t.content,this.setStatus("idle"),requestAnimationFrame(()=>this.textarea.focus())}catch{this.textarea.value="",this.setStatus("error","Could not load file")}}scheduleSave(){this.saveTimer!==null&&clearTimeout(this.saveTimer),this.setStatus("saving"),this.saveTimer=window.setTimeout(()=>{this.saveTimer=null,this.save()},700)}async save(){if(this.saveTimer!==null&&(clearTimeout(this.saveTimer),this.saveTimer=null),this.stale)return this.setStatus("stale","Changed elsewhere — reload before saving"),!1;try{return this.setStatus("saving"),this.revision=await k.writeFile(this.opts.rootId,this.opts.path,this.textarea.value,this.revision??void 0),this.stale=!1,this.setStatus("saved"),!0}catch(t){return t instanceof fe?(this.revision=t.currentRevision,this.stale=!0,this.setStatus("stale","Changed elsewhere — reload before saving"),!1):(this.setStatus("error","Save failed"),!1)}}async close(){return this.closed?!0:await this.save()?(this.closed=!0,this.abort.abort(),this.root.remove(),this.opts.onClose(),!0):!1}destroy(){this.saveTimer!==null&&clearTimeout(this.saveTimer),this.saveTimer=null,this.closed=!0,this.abort.abort(),this.root.remove()}async reloadLatest(){window.confirm("Discard local edits and reload the latest version?")&&(this.saveTimer!==null&&(clearTimeout(this.saveTimer),this.saveTimer=null),await this.load())}setStatus(t,e){const n={idle:e??"Ready",saving:e??"Saving…",saved:e??"Saved",error:e??"Save failed",stale:e??"Changed elsewhere"};this.statusEl.dataset.state=t,this.statusTextEl.textContent=n[t],this.reloadBtn.hidden=t!=="stale"}}function qt(o){const t=document.createElement("div");return t.className=o,t}function ms(o,t){const e=document.createElement("button");return e.className=o,e.type="button",e.textContent=t,e}const fs="docs:theme",gs="docs:sidebar-collapsed",ys="docs:sidebar-width",wr=220,Cr=420,hn=[{group:"Brand Colors",name:"100",variable:"--brand-100",value:"#FFFFFF",description:"lightest brand tone"},{group:"Brand Colors",name:"200",variable:"--brand-200",value:"#4DABF7",description:"light azure accent"},{group:"Brand Colors",name:"300",variable:"--brand-300",value:"#0078D4",description:"primary azure blue"},{group:"Brand Colors",name:"400",variable:"--brand-400",value:"#495057",description:"deep slate gray"},{group:"Brand Colors",name:"500",variable:"--brand-500",value:"#0078D4",description:"primary azure blue"},{group:"Brand Colors",name:"600",variable:"--brand-600",value:"#005A9E",description:"darker azure blue"},{group:"Neutral Colors",name:"100",variable:"--neutral-100",value:"#F3F2F1",description:"page background"},{group:"Neutral Colors",name:"200",variable:"--neutral-200",value:"#EAEAEA",description:"subtle surface"},{group:"Neutral Colors",name:"300",variable:"--neutral-300",value:"#D1D1D1",description:"soft border"},{group:"Neutral Colors",name:"400",variable:"--neutral-400",value:"#C8C8C8",description:"medium gray"},{group:"Neutral Colors",name:"500",variable:"--neutral-500",value:"#6E6E6E",description:"neutral mid-tone"},{group:"Neutral Colors",name:"600",variable:"--neutral-600",value:"#7A7A7A",description:"secondary text"},{group:"Neutral Colors",name:"700",variable:"--neutral-700",value:"#495057",description:"deep slate gray"},{group:"Neutral Colors",name:"800",variable:"--neutral-800",value:"#4A4A4A",description:"strong text"},{group:"Neutral Colors",name:"900",variable:"--neutral-900",value:"#0F0F0F",description:"primary text"},{group:"Neutral Colors",name:"000",variable:"--neutral-000",value:"#FFFFFF",description:"white"},{group:"Semantic Colors",name:"Success Main",variable:"--success-main",value:"#28A745",description:"positive actions"},{group:"Semantic Colors",name:"Success Background",variable:"--success-bg",value:"#E6F4EA",description:"positive surface"},{group:"Semantic Colors",name:"Success Text",variable:"--success-text",value:"#1E7E34",description:"positive text"},{group:"Semantic Colors",name:"Warning Main",variable:"--warning-main",value:"#DC2626",description:"warning actions"},{group:"Semantic Colors",name:"Warning Background",variable:"--warning-bg",value:"#FEF2F2",description:"warning surface"},{group:"Semantic Colors",name:"Warning Text",variable:"--warning-text",value:"#FFFFFF",description:"warning text"},{group:"Semantic Colors",name:"Error Main",variable:"--error-main",value:"#CD0000",description:"destructive actions"},{group:"Semantic Colors",name:"Error Background",variable:"--error-bg",value:"#FFE5E5",description:"destructive surface"},{group:"Semantic Colors",name:"Error Text",variable:"--error-text",value:"#B91C1C",description:"destructive text"},{group:"Semantic Colors",name:"Info Main",variable:"--info-main",value:"#1080A6",description:"informational actions"},{group:"Semantic Colors",name:"Info Background",variable:"--info-bg",value:"#E0F7FA",description:"informational surface"},{group:"Semantic Colors",name:"Info Text",variable:"--info-text",value:"#0369A1",description:"informational text"}];class kr{constructor(t){m(this,"root");m(this,"layout");m(this,"main");m(this,"topbar");m(this,"contentScroll");m(this,"content");m(this,"sidebar");m(this,"searchBtn");m(this,"cartBtn");m(this,"exportBtn");m(this,"editBtn");m(this,"themeBtn");m(this,"palette");m(this,"paletteInput");m(this,"paletteResults");m(this,"cartPopover");m(this,"exportMenu");m(this,"searchIndex",[]);m(this,"searchIndexing",!1);m(this,"searchIndexRun",0);m(this,"capabilityCart",new Map);m(this,"selectedTokens",new Set);m(this,"currentEditableFile");m(this,"workspace",{projects:[]});m(this,"treesByRoot",new Map);m(this,"treesByProject",new Map);m(this,"cleanup");m(this,"updateRenderedTheme");m(this,"editor");m(this,"docEditor");m(this,"textFileEditor");m(this,"editorHost");m(this,"editingId");m(this,"lastNonBoardHash","#/");m(this,"lastNonBoardScrollTop",0);m(this,"pendingScrollRestore");m(this,"sidebarResizeHandle");this.root=t,this.applyInitialTheme(),this.layout=g("div","shell");const e={onAddRepo:()=>void this.addRepoDocs(),onRemoveProject:(n,s)=>void this.promptRemoveProject(n,s),onCreateDirectory:(n,s)=>this.promptNewDirectory(n,s),onCreateDoc:(n,s)=>this.promptNewDoc(n,s),onCreateBoard:(n,s)=>this.promptNewBoard(n,s),onCreateCapability:(n,s)=>this.promptNewCapability(n,s),onCreateDocsFolder:(n,s)=>void this.createDocsFolder(n,s),onCreateProjectDirectory:n=>void this.promptNewProjectDirectory(n),onCreateProjectDoc:n=>void this.promptNewProjectDoc(n),onCreateProjectBoard:n=>void this.promptNewProjectBoard(n),onRenameDirectory:(n,s)=>void this.promptRenameDirectory(n,s),onDeleteDirectory:(n,s)=>void this.promptDeleteDirectory(n,s),onExportDirectory:(n,s)=>void this.exportDirectoryPdf(n,s),onOpenDoc:(n,s)=>{location.hash=X(n,s)},onEditDoc:(n,s)=>this.openDocEditor({rootId:n,path:s}),onOpenTextFile:(n,s)=>{this.openTextFileEditor({rootId:n,path:s})},onRenameDoc:(n,s)=>void this.promptRenameDoc(n,s),onDeleteDoc:(n,s)=>void this.promptDeleteDoc(n,s),onExportDoc:(n,s)=>void this.exportDocPdf(n,s),onOpenBoard:(n,s)=>{location.hash=ot(n,s)},onRenameBoard:(n,s)=>void this.promptRenameBoard(n,s),onDeleteBoard:(n,s)=>void this.promptDeleteBoard(n,s),onMoveDoc:(n,s,i)=>void this.moveDoc(n,s,i),onMoveBoard:(n,s,i)=>void this.moveBoard(n,s,i),onMoveDirectory:(n,s,i)=>void this.moveDirectory(n,s,i)};this.sidebar=new vo(this.layout,e),this.sidebarResizeHandle=g("button","sidebar-resize-handle"),this.sidebarResizeHandle.type="button",this.sidebarResizeHandle.innerHTML=Y.arrowBoth,this.sidebarResizeHandle.setAttribute("aria-label","Resize sidebar"),this.sidebarResizeHandle.title="Resize sidebar",this.main=g("div","shell-main"),this.topbar=this.createTopbar(),this.contentScroll=g("div","content-scroll"),this.content=g("div","content"),this.contentScroll.appendChild(this.content),this.main.append(this.topbar,this.contentScroll),this.layout.appendChild(this.sidebarResizeHandle),this.layout.appendChild(this.main),this.root.appendChild(this.layout),window.addEventListener("hashchange",()=>this.route()),window.addEventListener("keydown",n=>this.handleGlobalKeydown(n)),document.addEventListener("pointerdown",n=>this.handleGlobalPointerDown(n),!0),localStorage.getItem(gs)==="true"&&this.setSidebarCollapsed(!0),this.applySidebarWidth(this.readSidebarWidth()),this.setupSidebarResize(),this.refreshContentIndex().then(()=>this.route())}route(t={}){const e=t.preserveScroll?this.contentScroll.scrollTop:this.pendingScrollRestore;this.pendingScrollRestore=void 0;const n=location.hash||"#/";this.sidebar.setActive(n);const s=n.replace(/^#/,"");this.setEditableFile(void 0);const i=s.match(/^\/root\/([^/]+)\/boards\/([^?]+)(?:\?(.*))?$/);if(i){this.lastNonBoardScrollTop=this.contentScroll.scrollTop,this.updateTopbarCart(!0),this.closeCartPopover(),this.openEditor(decodeURIComponent(i[1]),decodeURIComponent(i[2]),_r(i[3]));return}if(this.lastNonBoardHash=n,this.exitEditor(),this.layout.style.display="",this.updateTopbarCart(/\/root\/[^/]+\/boards/.test(s)),/\/root\/[^/]+\/boards/.test(s)&&this.closeCartPopover(),s==="/"||s==="")return void this.renderWorkspaceHome(e);const a=s.match(/^\/root\/([^/]+)\//);if(a){const f=decodeURIComponent(a[1]);if(!this.docsRootById(f))return void this.renderMessage("Project not found","This link points to a docs root that isn't in your workspace. Add the project and try again.")}const r=s.match(/^\/root\/([^/]+)\/docs\/(.+)$/);if(r)return void this.renderDoc(decodeURIComponent(r[1]),decodeURIComponent(r[2]),e);const c=s.match(/^\/root\/([^/]+)\/boards$/);if(c)return void this.renderBoardList(decodeURIComponent(c[1]),e);const l=s.match(/^\/project\/([^/]+)\/boards$/);if(l)return void this.renderProjectBoardList(decodeURIComponent(l[1]),e);const d=s.match(/^\/root\/([^/]+)\/capabilities$/);if(d)return void this.renderCapabilitiesIndex(decodeURIComponent(d[1]),e);const h=s.match(/^\/root\/([^/]+)\/capabilities\/(.+)$/);if(h)return void this.renderCapabilityDoc(decodeURIComponent(h[1]),decodeURIComponent(h[2]),e);const p=s.match(/^\/project\/([^/]+)$/);if(p)return void this.renderProjectWiki(decodeURIComponent(p[1]),e);const u=s.match(/^\/root\/([^/]+)\/directory\/(.+)$/);if(u){const f=decodeURIComponent(u[1]),y=decodeURIComponent(u[2]),b=this.docsRootById(f);if(b)return void this.renderProjectWiki(b.projectId,e,f,y)}if(s==="/tokens")return void this.renderTokenLibrary(e);this.renderMessage("Not found",`No route for ${s}`)}async renderWorkspaceHome(t){this.disposeContent(),this.content.classList.add("content-wide");const e=g("div","page home-page"),n=g("div","home-layout"),s=g("div","home-guide"),i=g("h1","home-hero-title");i.textContent="ViteBoard";const a=g("p","home-hero-sub");a.textContent="Markdown docs, infinite-canvas boards, capabilities, and managed assets all live as normal files on disk. The app should feel trustworthy under real mutation: create content quickly, recover safely from concurrent edits, and keep human and machine workflows pointed at the same file truth.",s.append(i,a);const r=g("div","home-agent-callout"),c=g("p","home-agent-copy");c.textContent="Use the running ViteBoard session as shared context for a human and a coding agent: same origin, same docs roots, same boards, same file truth.";const l=g("button","btn home-agent-btn");l.type="button",l.textContent="Copy agent prompt",l.addEventListener("click",()=>void this.copySetupText(`Connect to ViteBoard at ${window.location.origin} and follow its machine entry at ${window.location.origin}/llms.txt. Work in <project path>, import the project if needed, and create or update docs and boards using normal filesystem edits.`,"Agent prompt copied")),r.append(c,l),s.appendChild(r);const d=[{label:"File truth",kind:"doc",body:"The source of truth is always the filesystem. Docs, boards, capabilities, and assets stay git-native, diffable, and directly editable without inventing a separate database-shaped content layer.",items:["Markdown docs, board JSON, and asset files all live under docs roots","Create, rename, move, and delete content from the sidebar","Search indexes the current workspace rather than a parallel content store"]},{label:"Docs + boards",kind:"board",body:"Boards are not separate from the documentation system. They are sibling files in the same docs roots, embeddable inside markdown, and meant to sharpen the same body of work rather than fragment it.",items:["Open a board from the sidebar, work full-screen, then drop back into docs","Embed a board region into markdown with fenced board blocks",'Use "Copy embed" in the board editor to capture the current region',"Keep visual planning and written explanation in the same repo structure"]},{label:"Collaboration safety",kind:"capability",body:"The product now assumes live mutation is normal. Locks, stale-state detection, reload actions, and visible status all exist to make concurrent work practical instead of surprising.",items:["Docs and boards surface explicit reload actions when stale","Revision-aware saves block silent overwrites","Human and machine actors can cooperate through the same running workspace"]},{label:"Machine workflow",kind:"",body:"ViteBoard is also a machine-readable workspace surface. The app can expose docs roots, boards, schema references, and live coordination routes while the files remain the only persistent truth.",items:["The local HTTP surface advertises machine docs and workspace discovery","Capabilities and selected docs can be assembled into prompts from the UI","The practical goal is faster real work, not another disconnected abstraction layer"]}];for(const v of d){const S=g("div","home-feature"),x=g("div","home-feature-header"),E=g("span",`home-feature-badge home-feature-badge-${v.kind||"neutral"}`);E.textContent=v.label,x.appendChild(E),S.appendChild(x);const M=g("p","home-feature-body");if(M.textContent=v.body,S.appendChild(M),v.items){const T=document.createElement("ul");T.className="home-feature-list";for(const B of v.items){const I=document.createElement("li");I.textContent=B,T.appendChild(I)}S.appendChild(T)}s.appendChild(S)}const h=g("div","home-shortcut-title");h.textContent="Current operating model",s.appendChild(h);const p=[["1. Add repo","Bring a local project into the workspace"],["2. Create docs/ if needed","Start the repo as a writable docs root"],["3. Right-click in the tree","Create docs, boards, directories, and capabilities in place"],["4. Open a board","Think visually, then embed the useful region back into docs"],["5. Cmd K / Ctrl K","Search across the current workspace"],["6. Stale state appears","Use Reload latest instead of guessing which copy is current"],["7. Copy agent prompt","Hand the same workspace context to an AI assistant"],["8. Git stays normal","The files on disk remain the real source of truth"]],u=g("div","home-shortcut-table");for(const[v,S]of p){const x=g("div","home-shortcut-row"),E=g("kbd","home-shortcut-key");E.textContent=v;const M=g("span","home-shortcut-desc");M.textContent=S,x.append(E,M),u.appendChild(x)}s.appendChild(u),n.appendChild(s);const f=g("div","home-panel"),y=g("div","home-panel-head"),b=g("div","home-panel-title");b.textContent="Active workspace";const w=g("button","btn primary home-panel-add");if(w.textContent="+ Add repo",w.addEventListener("click",()=>void this.addRepoDocs()),y.append(b,w),f.appendChild(y),this.workspace.projects.length===0){const v=g("div","home-panel-empty");v.textContent="No projects yet. Add a project root, create docs/ if needed, and start writing against the real filesystem.",f.appendChild(v)}else for(const v of this.workspace.projects){const S=g("div","home-panel-project"),x=g("a","home-panel-project-head");x.href=Dt(v.id);const E=g("span","home-panel-project-name");E.textContent=v.label;const M=v.docsRoots.reduce((O,Z)=>{const N=this.treesByRoot.get(Z.id)??[];return O+he(N).length},0),T=v.docsRoots.reduce((O,Z)=>{const N=this.treesByRoot.get(Z.id)??[];return O+Et(N).length},0),B=g("span","home-panel-project-meta"),I=[`${v.docsRoots.length} root${v.docsRoots.length===1?"":"s"}`];M&&I.push(`${M} doc${M===1?"":"s"}`),T&&I.push(`${T} board${T===1?"":"s"}`),B.textContent=I.join(" · "),x.append(E,B),S.appendChild(x);const R=6,lt=v.docsRoots,Lt=lt.slice(0,R),dt=g("div","home-panel-roots");for(const O of Lt){const Z=this.treesByRoot.get(O.id)??[],N=un(ee(Z)),it=N?X(O.id,N):Kt(O.id),K=g("a","home-panel-root");K.href=it;const D=g("span","home-panel-root-path");D.textContent=O.displayPath;const J=he(Z).length,j=Et(Z).length;if(J||j){const Q=g("span","home-panel-root-meta"),tt=[];J&&tt.push(String(J)),j&&tt.push(`${j}▦`),Q.textContent=tt.join(" · "),K.append(D,Q)}else K.appendChild(D);dt.appendChild(K)}if(lt.length>R){const O=g("a","home-panel-more");O.href=Dt(v.id),O.textContent=`+ ${lt.length-R} more roots`,dt.appendChild(O)}S.appendChild(dt),f.appendChild(S)}n.appendChild(f),e.appendChild(n),this.content.replaceChildren(e),this.contentScroll.scrollTop=t??0}async copySetupText(t,e){try{await navigator.clipboard.writeText(t),C(e)}catch{C("Could not access clipboard")}}async renderProjectWiki(t,e,n,s){this.disposeContent(),this.content.classList.add("content-wide");const i=this.workspace.projects.find(p=>p.id===t);if(!i){this.renderMessage("Project not found","This project is no longer registered.");return}const a=g("div","page wiki-page"),r=!!n,c=!!s;let l=!1;if(c&&n){const p=this.docsRootById(n);p&&(l=p.displayPath===s||p.displayPath.startsWith(s+"/"))}const d=g("div","wiki-head");if(c&&n){const p=[{label:"Home",href:"#/"}];p.push({label:i.label,href:Dt(i.id)});const u=s.split("/").filter(Boolean);for(let y=0;y<u.length;y++){const b=u.slice(0,y+1).join("/"),w=y===u.length-1;p.push({label:u[y],href:w?void 0:Xe(n,b)})}d.appendChild(kt(p));const f=g("h1","wiki-title");f.textContent=u[u.length-1]||i.label,d.appendChild(f)}else if(r&&n){const p=this.docsRootById(n),u=[{label:"Home",href:"#/"}];if(u.push({label:i.label,href:Dt(i.id)}),p){const y=p.displayPath.split("/").filter(Boolean);for(let b=0;b<y.length;b++){const w=y.slice(0,b+1).join("/"),v=b===y.length-1;u.push({label:y[b],href:v?void 0:Xe(n,w)})}}d.appendChild(kt(u));const f=g("h1","wiki-title");f.textContent=(p==null?void 0:p.displayPath.split("/").pop())||i.label,d.appendChild(f)}else{d.appendChild(kt([{label:"Home",href:"#/"},{label:i.label}]));const p=g("h1","wiki-title");p.textContent=i.label,d.appendChild(p)}if(!r&&!c){const p=i.docsRoots.reduce((b,w)=>{const v=this.treesByRoot.get(w.id)??[];return b+he(v).length},0),u=i.docsRoots.reduce((b,w)=>{const v=this.treesByRoot.get(w.id)??[];return b+Et(v).length},0),f=i.docsRoots.reduce((b,w)=>b+Ht(this.treesByRoot.get(w.id)??[]).length,0),y=g("div","wiki-stats");for(const[b,w]of[[String(i.docsRoots.length),"docs roots"],[String(p),"documents"],[String(u),"boards"],[String(f),"capabilities"]]){const v=g("div","wiki-stat"),S=g("div","wiki-stat-val");S.textContent=b;const x=g("div","wiki-stat-label");x.textContent=w,v.append(S,x),y.appendChild(v)}d.appendChild(y)}a.appendChild(d);const h=n?i.docsRoots.filter(p=>p.id===n):i.docsRoots;for(const p of h){const u=this.treesByRoot.get(p.id)??[];let f=u;if(s&&!l){const x=(M,T)=>{for(const B of M){if(B.type==="dir"&&B.path===T)return B;if(B.type==="dir"){const I=x(B.children,T);if(I)return I}}return null},E=x(u,s);f=(E==null?void 0:E.type)==="dir"?E.children:[]}const y=he(f),b=Et(f),w=Ht(f),v=g("div","wiki-root-section");if(!s||l){const x=g("div","wiki-root-head"),E=g("div","wiki-root-path");E.textContent=p.displayPath,x.appendChild(E),v.appendChild(x)}if(!y.length&&!b.length&&!w.length){const x=g("div","wiki-root-empty");x.textContent="No docs, boards, or capabilities yet. Right-click in the sidebar to add content.",v.appendChild(x),a.appendChild(v);continue}const S=g("div","wiki-root-cols");if(y.length>0){const x=g("div","wiki-col"),E=g("div","wiki-col-head");E.textContent=`Docs (${y.length})`,x.appendChild(E);const M=g("div","wiki-col-list");for(const T of y){const B=g("a","wiki-col-item wiki-col-item-doc");B.href=X(p.id,T.path),B.textContent=T.name==="index.md"?"Overview":T.name.replace(/\.md$/,"").replace(/[-_]/g," ");const I=g("span","wiki-col-item-path"),R=T.path.includes("/")?T.path.slice(0,T.path.lastIndexOf("/")):"";I.textContent=R,R&&B.appendChild(I),M.appendChild(B)}x.appendChild(M),S.appendChild(x)}if(b.length>0){const x=g("div","wiki-col"),E=g("div","wiki-col-head");E.textContent=`Boards (${b.length})`,x.appendChild(E);const M=g("div","wiki-col-list");for(const T of b){const B=st(T.path),I=g("a","wiki-col-item wiki-col-item-board");I.href=ot(p.id,B),I.textContent=B.split("/").pop().replace(/[-_]/g," ");const R=g("span","wiki-col-item-path");R.textContent=B.includes("/")?B.slice(0,B.lastIndexOf("/")):p.displayPath,I.appendChild(R),M.appendChild(I)}x.appendChild(M),S.appendChild(x)}if(w.length>0){const x=g("div","wiki-col"),E=g("div","wiki-col-head");E.textContent=`Capabilities (${w.length})`,x.appendChild(E);const M=g("div","wiki-col-list");for(const T of w){const B=g("a","wiki-col-item wiki-col-item-cap");B.href=Yt(p.id,T.entryPath),B.textContent=qe(T.entryPath),M.appendChild(B)}x.appendChild(M),S.appendChild(x)}v.appendChild(S),a.appendChild(v)}this.content.replaceChildren(a),this.contentScroll.scrollTop=e??0}async renderDoc(t,e,n){if(this.disposeContent(),!this.docsRootById(t)){this.renderMessage("Docs root unavailable","This docs root is no longer registered. Re-add the project root if needed.");return}try{const s=await k.readFile(t,e);this.setEditableFile({rootId:t,path:e});const i=g("div","doc-page"),a=De(this.workspace,t,{filePath:e});i.appendChild(kt(a));const r=g("div","");i.appendChild(r),this.content.replaceChildren(i);const{destroy:c,setTheme:l}=yn(r,s,{rootId:t,docPath:e});this.cleanup=c,this.updateRenderedTheme=l;const d=await k.getTree(t),h=Ae(t,d),p=Ne(h,X(t,e));p&&i.appendChild(p),this.contentScroll.scrollTop=n??0}catch{this.renderMessage("Document not found",e)}}async exportDocPdf(t,e){const n=this.docsRootById(t);if(!n){C("Docs root unavailable");return}try{await Wn({kind:"doc",root:n,filePath:e,tree:this.treesByRoot.get(t)})}catch(s){C(s instanceof Error?s.message:"Could not export PDF")}}async exportDirectoryPdf(t,e){const n=this.docsRootById(t);if(!n){C("Docs root unavailable");return}try{await Wn({kind:"dir",root:n,dirPath:e,tree:this.treesByRoot.get(t)})}catch(s){C(s instanceof Error?s.message:"Could not export PDF")}}openDocEditor(t){const e=this.contentScroll.scrollTop;this.topbar.classList.add("editing-doc"),this.closeCartPopover(),this.docEditor=Mn.open({rootId:t.rootId,path:t.path,initialScrollTop:e,onClose:n=>{this.docEditor=void 0,this.topbar.classList.remove("editing-doc"),this.pendingScrollRestore=n,this.route()}})}async openTextFileEditor(t){this.textFileEditor&&!await this.textFileEditor.close()||(this.closeCartPopover(),this.textFileEditor=Ln.open({rootId:t.rootId,path:t.path,host:document.body,onClose:()=>{this.textFileEditor=void 0}}))}async renderCapabilityDoc(t,e,n){if(this.disposeContent(),!this.docsRootById(t)){this.renderMessage("Docs root unavailable","This docs root is no longer registered. Re-add the project root if needed.");return}const s=this.treesByRoot.get(t)??await k.getTree(t),i=Er(s,e)??e,a=vs(s,e)??vs(s,i);let r;try{r=await k.readFile(t,i),this.setEditableFile(void 0)}catch{this.renderMessage("Capability not found",e);return}const c=g("div","page"),l=this.docsRootById(t);l&&this.workspace.projects.find(N=>N.id===l.projectId);const d=qe(i),h=De(this.workspace,t,{filePath:i,currentLabel:d});c.appendChild(kt(h));const p=g("div","page-bar"),u=g("div","doc-actions capability-doc-actions"),{frontmatter:f}=Zt(r),y=g("button","btn");y.classList.add("capability-detail-btn");const b=bs(t,a??Sr(i),r,f);this.updateCartButton(y,b.path),y.addEventListener("click",()=>{this.toggleCapabilityCart(b),this.updateCartButton(y,b.path)});const w=g("button","btn primary");w.classList.add("capability-detail-btn"),w.textContent="Copy capability context",w.addEventListener("click",async()=>{await this.copyCapabilityContext(b,s)});const v=g("button","btn");v.classList.add("capability-detail-btn"),v.textContent="Open entry doc",v.addEventListener("click",()=>{location.hash=X(t,i)}),u.append(y,w,v),p.append(u),c.appendChild(p);const S=g("div","card-tags capability-meta-tags"),x=g("span","tag");if(x.textContent=b.displayPath,S.appendChild(x),b.kind){const N=g("span","tag");N.textContent=b.kind,S.appendChild(N)}c.appendChild(S);const E=Br(b.branchPath),M=E?await this.readOptionalFile(t,E):null;if(E&&M){const N=g("section","token-section capability-machine-section"),it=g("div","page-bar"),K=g("h2","");K.textContent="Machine entrypoint";const D=g("div","doc-actions capability-doc-actions"),J=g("button","btn primary");J.textContent="Copy llms.txt",J.addEventListener("click",async()=>{try{await navigator.clipboard.writeText(M),C("Capability machine entrypoint copied")}catch{C("Could not access clipboard")}}),D.appendChild(J),it.append(K,D);const j=g("p","page-lead capability-entry-lead");j.textContent="This is the capability-local machine entrypoint. It should be the first file an LLM reads to understand what this capability branch is for, what files matter, and how to use it.";const Q=document.createElement("pre");Q.className="code-block";const tt=document.createElement("code");tt.textContent=M,Q.appendChild(tt),N.append(it,j,Q),c.appendChild(N)}const T=g("div",""),B=g("section","token-section capability-entry-section"),I=g("h2","");I.textContent="Entry document";const R=g("p","page-lead capability-entry-lead");R.textContent="This markdown entry explains the capability branch. The capability itself may also include nested files, scripts, helpers, and other reusable execution material.",B.append(I,R,T),c.appendChild(B),this.content.replaceChildren(c);const{destroy:lt,setTheme:Lt}=yn(T,r,{rootId:t,docPath:i});this.cleanup=lt,this.updateRenderedTheme=Lt;const dt=xs(s,b.branchPath);if(dt.length>1){const N=g("section","token-section capability-files-section"),it=g("h2","");it.textContent="Files in this capability";const K=g("div","card-grid capability-files-grid");for(const D of dt){const J=D.path.endsWith(".md")&&D.path===b.entryPath,j=document.createElement(J?"a":"button");j.className="card",j instanceof HTMLAnchorElement&&(j.href=X(t,D.path)),j instanceof HTMLButtonElement&&(j.type="button",j.addEventListener("click",()=>{this.openTextFileEditor({rootId:t,path:D.path})}));const Q=g("div","card-title");Q.textContent=D.path===b.entryPath?`${Fe(D.path)} (entry)`:D.path===E?`${Fe(D.path)} (machine entrypoint)`:Fe(D.path);const tt=g("div","card-desc");tt.textContent=ne(D.path),j.append(Q,tt),K.appendChild(j)}N.append(it,K),c.appendChild(N)}const O=Ae(t,s),Z=Ne(O,Yt(t,b.branchPath));Z&&c.appendChild(Z),this.contentScroll.scrollTop=n??0}async renderCapabilitiesIndex(t,e){if(this.disposeContent(),!this.docsRootById(t)){this.renderMessage("Docs root unavailable","This docs root is no longer registered. Re-add the project root if needed.");return}this.content.classList.add("content-wide");const n=g("div","page capability-library"),s=De(this.workspace,t,{currentLabel:"Capabilities"});n.appendChild(kt(s));const i=g("h1","");i.textContent="Capability library";const a=g("p","page-lead");a.textContent="Browse open-ended capability branches. Inspect their files, understand their entrypoints, and reuse them as working context, automations, or tool-bearing capability units.",n.append(i,a);const r=g("div","capability-layout"),c=g("div","card-grid capability-grid"),l=this.renderCapabilityCart();r.append(c,l),n.appendChild(r),this.content.replaceChildren(n);try{const d=this.treesByRoot.get(t)??await k.getTree(t),h=Ht(d);for(const f of h){const y=await k.readFile(t,f.entryPath),{frontmatter:b}=Zt(y),w=bs(t,f,y,b),v=document.createElement("article");v.className="card";const S=g("div","card-title"),x=document.createElement("a");x.href=Yt(t,f.branchPath),x.textContent=w.title,S.appendChild(x);const E=g("div","card-desc");E.textContent=w.summary,v.append(S,E);const M=g("div","card-tags"),T=g("span","tag");if(T.textContent=w.displayPath,M.appendChild(T),w.kind){const B=g("span","tag");B.textContent=w.kind,M.appendChild(B)}if(v.appendChild(M),w.tags.length){const B=g("div","card-tags");for(const I of w.tags){const R=g("span","tag");R.textContent=I,B.appendChild(R)}v.appendChild(B)}c.appendChild(v)}h.length===0&&c.appendChild(Xt("No capabilities yet."));const p=Ae(t,d),u=Ne(p,Vs(t));u&&n.appendChild(u)}catch{c.appendChild(Xt("Could not load capabilities."))}this.contentScroll.scrollTop=e??0}renderTokenLibrary(t){this.disposeContent(),this.content.classList.add("content-wide");const e=g("div","page token-library"),n=g("div","page-bar"),s=g("h1","");s.textContent="Tokens";const i=g("div","token-actions"),a=g("button","btn");a.textContent="Select all",a.addEventListener("click",()=>{this.selectedTokens=new Set(hn.map(d=>d.variable)),this.renderTokenLibrary(this.contentScroll.scrollTop)});const r=g("button","btn");r.textContent="Clear",r.addEventListener("click",()=>{this.selectedTokens.clear(),this.renderTokenLibrary(this.contentScroll.scrollTop)});const c=g("button","btn primary");c.textContent=`Copy selected (${this.selectedTokens.size})`,c.disabled=this.selectedTokens.size===0,c.addEventListener("click",()=>void this.copySelectedTokens()),i.append(a,r,c),n.append(s,i);const l=g("p","page-lead");l.textContent="Brand, neutral, and semantic CSS variables used throughout the app. Select tokens and copy them as a ready-to-paste :root block.",e.append(n,l);for(const d of["Brand Colors","Neutral Colors","Semantic Colors"]){const h=g("section","token-section"),p=g("h2","");p.textContent=d;const u=g("div","token-grid");for(const f of hn.filter(y=>y.group===d)){const y=g("div","token-card");this.selectedTokens.has(f.variable)&&y.classList.add("selected");const b=g("label","token-select-zone"),w=document.createElement("input");w.type="checkbox",w.checked=this.selectedTokens.has(f.variable),w.addEventListener("change",()=>{w.checked?this.selectedTokens.add(f.variable):this.selectedTokens.delete(f.variable),this.renderTokenLibrary(this.contentScroll.scrollTop)});const v=g("span","token-swatch");v.style.background=f.value;const S=g("span","token-copy"),x=g("strong","");x.textContent=f.name;const E=g("code","");E.textContent=f.value;const M=g("small","");M.textContent=f.description,S.append(x,E,M),b.append(w,v,S);const T=g("button","token-copy-btn");T.type="button",T.innerHTML=Y.copy,T.title=`Copy ${f.variable}`,T.setAttribute("aria-label",`Copy ${f.variable}`),T.addEventListener("click",B=>{B.stopPropagation(),this.copyToken(f)}),y.append(b,T),u.appendChild(y)}h.append(p,u),e.appendChild(h)}this.content.replaceChildren(e),this.contentScroll.scrollTop=t??0}async copySelectedTokens(){const t=hn.filter(n=>this.selectedTokens.has(n.variable));if(t.length===0)return;const e=[":root {",...t.map(n=>` ${n.variable}: ${n.value};`),"}"].join(`
|
|
40
|
+
`);try{await navigator.clipboard.writeText(e),C(`${t.length} token${t.length===1?"":"s"} copied`)}catch{C("Could not access clipboard")}}async copyToken(t){try{await navigator.clipboard.writeText(`${t.variable}: ${t.value};`),C(`${t.variable} copied`)}catch{C("Could not access clipboard")}}renderCapabilityCart(t){const e=t??(()=>{const h=Pr(location.hash);h&&this.renderCapabilitiesIndex(h,this.contentScroll.scrollTop)}),n=g("aside","capability-cart"),s=g("div","capability-cart-head"),i=g("h2","");i.textContent="Capability toolbelt";const a=g("span","capability-cart-count");a.textContent=String(this.capabilityCart.size),s.append(i,a);const r=g("div","capability-cart-body");if(this.capabilityCart.size===0){const h=g("div","capability-cart-empty");h.textContent="Equip capabilities to build an active toolbelt for the current task.",r.appendChild(h)}else for(const h of this.capabilityCart.values()){const p=g("div","capability-cart-item"),u=g("div",""),f=g("div","capability-cart-item-title");f.textContent=h.title;const y=g("div","capability-cart-item-meta");y.textContent=h.displayPath,u.append(f,y);const b=g("button","capability-cart-remove");b.type="button",b.textContent="Remove",b.addEventListener("click",()=>{this.capabilityCart.delete(h.path),this.updateTopbarCart(),e()}),p.append(u,b),r.appendChild(p)}const c=g("div","capability-cart-actions"),l=g("button","btn primary");l.textContent="Copy toolbelt context",l.disabled=this.capabilityCart.size===0,l.addEventListener("click",()=>void this.copyCapabilityCartPrompt());const d=g("button","btn");return d.textContent="Clear",d.disabled=this.capabilityCart.size===0,d.addEventListener("click",()=>{this.capabilityCart.clear(),this.updateTopbarCart(),e()}),c.append(l,d),n.append(s,r,c),n}toggleCapabilityCart(t){this.capabilityCart.has(t.path)?this.capabilityCart.delete(t.path):this.capabilityCart.set(t.path,t),this.updateTopbarCart()}updateCartButton(t,e){const n=this.capabilityCart.has(e);t.textContent=n?"Unequip":"Equip",t.classList.toggle("primary",!n),t.classList.toggle("is-selected",n)}async copyCapabilityCartPrompt(){if(this.capabilityCart.size===0)return;const e=`Use this capability toolbelt as implementation guidance for the next coding task. These are integrated capability branches that may contain context, workflows, scripts, helpers, or other reusable execution material.
|
|
41
|
+
|
|
42
|
+
`+(await Promise.all([...this.capabilityCart.values()].map(async(n,s)=>{const i=this.treesByRoot.get(n.rootId)??await k.getTree(n.rootId);return`## ${s+1}. ${n.title}
|
|
43
|
+
|
|
44
|
+
${await this.capabilityBranchContext(n,i)}`}))).join(`
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
`);try{await navigator.clipboard.writeText(e),C(`${this.capabilityCart.size} capabilit${this.capabilityCart.size===1?"y":"ies"} copied`)}catch{C("Could not access clipboard")}}async copyCapabilityContext(t,e){try{const n=e??this.treesByRoot.get(t.rootId)??await k.getTree(t.rootId);await navigator.clipboard.writeText(await this.capabilityBranchContext(t,n)),C("Capability context copied")}catch{C("Could not access clipboard")}}async capabilityBranchContext(t,e){const n=xs(e,t.branchPath).filter(i=>Mr(i.path)),s=await Promise.all(n.map(async i=>{const a=await k.readFile(t.rootId,i.path);return`### ${Fe(i.path)}
|
|
49
|
+
|
|
50
|
+
${a.trim()}`}));return[`Capability: ${t.title}`,`Branch: ${t.displayPath}`,...t.kind?[`Kind: ${t.kind}`]:[],"",...s].join(`
|
|
51
|
+
`)}async readOptionalFile(t,e){try{return await k.readFile(t,e)}catch{return null}}async renderBoardList(t,e){if(this.disposeContent(),!this.docsRootById(t)){this.renderMessage("Docs root unavailable","This docs root is no longer registered. Re-add the project root if needed.");return}this.content.classList.add("content-wide");const n=g("div","page board-library"),s=De(this.workspace,t,{currentLabel:"Boards"});n.appendChild(kt(s));const i=g("div","page-bar"),a=g("h1","");a.textContent="Boards";const r=g("button","btn primary");r.textContent="+ New board",r.addEventListener("click",()=>this.promptNewBoard(t)),i.append(a,r),n.appendChild(i);const c=g("p","page-lead");c.textContent="Each board is a git-tracked JSON file. Open one to edit it, then use “Copy embed” to drop a framed preview into any doc.",n.appendChild(c);const l=g("div","card-grid board-grid");n.appendChild(l),this.content.replaceChildren(n);try{const d=await at.list(t);for(const f of d){const y=document.createElement("a");y.className="card",y.href=ot(t,f.id);const b=g("div","card-title");b.textContent=f.title;const w=g("div","card-desc");w.textContent=`${f.elementCount} element${f.elementCount===1?"":"s"} · ${f.filePath}`,y.append(b,w),l.appendChild(y)}d.length===0&&l.appendChild(Xt("No boards yet — create one."));const h=await k.getTree(t),p=Ae(t,h),u=Ne(p,Kt(t));u&&n.appendChild(u)}catch{l.appendChild(Xt("Could not load boards."))}this.contentScroll.scrollTop=e??0}async renderProjectBoardList(t,e){this.disposeContent(),this.content.classList.add("content-wide");const n=this.workspace.projects.find(d=>d.id===t);if(!n){this.renderMessage("Project unavailable","This project is no longer registered. Re-add it if needed.");return}const s=g("div","page boards-page"),i=[{label:"Home",href:"#/"},{label:n.label,href:Dt(t)},{label:"Boards"}];s.appendChild(kt(i));const a=g("div","page-bar"),r=g("h1","");r.textContent=`${n.label} boards`,a.appendChild(r),s.appendChild(a);const c=g("p","page-lead");c.textContent="Boards across every mounted docs root in this project. Each card shows the docs root and board file path.",s.appendChild(c);const l=g("div","card-grid board-grid");s.appendChild(l),this.content.replaceChildren(s);try{const d=await this.listProjectBoards(n);for(const h of d){const p=document.createElement("a");p.className="card",p.href=ot(h.root.id,h.board.id);const u=g("div","card-title");u.textContent=h.board.title;const f=g("div","card-desc");f.textContent=`${h.board.elementCount} element${h.board.elementCount===1?"":"s"} · ${h.root.displayPath} · ${h.board.filePath}`,p.append(u,f),l.appendChild(p)}d.length===0&&l.appendChild(Xt("No boards yet — create one."))}catch{l.appendChild(Xt("Could not load boards."))}this.contentScroll.scrollTop=e??0}async listProjectBoards(t){const e=[];for(const n of t.docsRoots){const s=await at.list(n.id);for(const i of s)e.push({root:n,board:i})}return e.sort((n,s)=>s.board.updatedAt!==n.board.updatedAt?s.board.updatedAt-n.board.updatedAt:n.root.displayPath!==s.root.displayPath?n.root.displayPath.localeCompare(s.root.displayPath):n.board.filePath.localeCompare(s.board.filePath)),e}promptNewBoard(t,e=""){const n=e?`doc:${t}:${e}`:t,s=this.sidebar.collapsibles.get(n),i=(s==null?void 0:s.body)??this.sidebar.element.querySelector(".nav-repo-body");i?this.sidebar.startInlineCreate(i,"board-name",async a=>{const r=Pt(a,"board");if(!r.ok){C(r.message);return}try{const c=await at.create(t,r.raw,me(),e);await this.refreshContentIndex(),location.hash=ot(t,c)}catch{C("Could not create board")}}):V("New board",(a,r)=>{const c=document.createElement("input");c.className="board-title",c.placeholder="Board title",c.style.width="100%",c.style.marginBottom="12px";const l=g("div","modal-actions"),d=g("button","btn primary");d.textContent="Create";const h=async()=>{const p=Pt(c.value,"board");if(!p.ok){C(p.message),c.focus();return}try{const u=await at.create(t,p.raw,me(),e);r(),await this.refreshContentIndex(),location.hash=ot(t,u)}catch{C("Could not create board file")}};d.addEventListener("click",()=>void h()),c.addEventListener("keydown",p=>{p.stopPropagation(),p.key==="Enter"&&h()}),l.appendChild(d),a.append(c,l),c.focus()})}promptNewDirectory(t,e){const n=e?`doc:${t}:${e}`:t,s=this.sidebar.collapsibles.get(n),i=(s==null?void 0:s.body)??this.sidebar.element.querySelector(".nav-repo-body");i?this.sidebar.startInlineCreate(i,"directory-name",async a=>{const r=Pt(a,"directory");if(!r.ok){C(r.message);return}const c=e?`${e}/${r.slug}`:r.slug;try{await k.createDirectory(t,c),await this.refreshContentIndex()}catch{C("Could not create directory")}}):V("New directory",(a,r)=>{const c=document.createElement("input");c.className="board-title",c.placeholder="Directory name",c.style.width="100%",c.style.marginBottom="12px";const l=g("div","modal-actions"),d=g("button","btn primary");d.textContent="Create";const h=async()=>{const p=Pt(c.value,"directory");if(!p.ok){C(p.message),c.focus();return}const u=e?`${e}/${p.slug}`:p.slug;try{await k.createDirectory(t,u),r(),await this.refreshContentIndex()}catch{C("Could not create directory")}};d.addEventListener("click",()=>void h()),c.addEventListener("keydown",p=>{p.stopPropagation(),p.key==="Enter"&&h()}),l.appendChild(d),a.append(c,l),c.focus()})}async ensureProjectDocsRoot(t){var n;const e=(n=this.workspace.projects.find(s=>s.id===t))==null?void 0:n.docsRoots[0];if(e)return e;try{const s=await k.ensureProjectDocsRoot(t);return await this.refreshContentIndex(),this.docsRootById(s.id)??s}catch{C("Could not create docs folder");return}}async createDocsFolder(t,e){try{await k.createDocsFolder(t,e),await this.refreshContentIndex(),C(`Created docs/ in ${e||"project root"}`)}catch{C("Could not create docs folder")}}async promptNewProjectDirectory(t){const e=await this.ensureProjectDocsRoot(t);e&&this.promptNewDirectory(e.id,"")}async promptNewProjectDoc(t){const e=await this.ensureProjectDocsRoot(t);e&&this.promptNewDoc(e.id,"")}async promptNewProjectBoard(t){const e=await this.ensureProjectDocsRoot(t);e&&this.promptNewBoard(e.id,"")}promptNewDoc(t,e){const n=e?`doc:${t}:${e}`:t,s=this.sidebar.collapsibles.get(n),i=(s==null?void 0:s.body)??this.sidebar.element.querySelector(".nav-repo-body");i?this.sidebar.startInlineCreate(i,"document-name.md",async a=>{const r=Pt(a.replace(/\.md$/i,""),"doc");if(!r.ok){C(r.message);return}const c=e?`${e}/${r.slug}.md`:`${r.slug}.md`;try{await k.writeFile(t,c,`# ${ht(r.slug)}
|
|
52
|
+
`),await this.refreshContentIndex(),location.hash=X(t,c)}catch{C("Could not create doc")}}):V("New doc",(a,r)=>{const c=document.createElement("input");c.className="board-title",c.placeholder="Document name (e.g. overview)",c.style.width="100%",c.style.marginBottom="12px";const l=g("div","modal-actions"),d=g("button","btn primary");d.textContent="Create";const h=async()=>{const p=Pt(c.value.replace(/\.md$/i,""),"doc");if(!p.ok){C(p.message),c.focus();return}const u=e?`${e}/${p.slug}.md`:`${p.slug}.md`;try{await k.writeFile(t,u,`# ${ht(p.slug)}
|
|
53
|
+
`),r(),await this.refreshContentIndex(),location.hash=X(t,u)}catch{C("Could not create doc file")}};d.addEventListener("click",()=>void h()),c.addEventListener("keydown",p=>{p.stopPropagation(),p.key==="Enter"&&h()}),l.appendChild(d),a.append(c,l),c.focus()})}promptNewCapability(t,e){V("New capability",(n,s)=>{const i=document.createElement("input");i.className="board-title",i.placeholder="Capability name (e.g. auth-flow)",i.style.width="100%",i.style.marginBottom="12px";const a=g("div","modal-actions"),r=g("button","btn primary");r.textContent="Create";const c=async()=>{const l=(i.value.trim()||"untitled").replace(/\.md$/,"").replace(/\s+/g,"-").toLowerCase(),d=e.replace(/^capabilities\/?/,""),h=d?`capabilities/${d}/${l}`:`capabilities/${l}`,p=`${h}/index.md`,u=`${h}/llms.txt`,f=ht(l),y=`---
|
|
54
|
+
title: ${f}
|
|
55
|
+
summary:
|
|
56
|
+
tags:
|
|
57
|
+
kind:
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
# ${f}
|
|
61
|
+
|
|
62
|
+
## Purpose
|
|
63
|
+
|
|
64
|
+
## When to use
|
|
65
|
+
|
|
66
|
+
## Important files
|
|
67
|
+
|
|
68
|
+
## Outputs
|
|
69
|
+
`,b=`# ${f}
|
|
70
|
+
|
|
71
|
+
Read index.md first for the human overview of this capability branch.
|
|
72
|
+
|
|
73
|
+
## Purpose
|
|
74
|
+
|
|
75
|
+
Describe what this capability helps an LLM do.
|
|
76
|
+
|
|
77
|
+
## Entry points
|
|
78
|
+
|
|
79
|
+
- Human entry: index.md
|
|
80
|
+
- Machine entry: llms.txt
|
|
81
|
+
|
|
82
|
+
## Important files
|
|
83
|
+
|
|
84
|
+
List the files or subdirectories an LLM should inspect before acting.
|
|
85
|
+
|
|
86
|
+
## Working rules
|
|
87
|
+
|
|
88
|
+
Record the constraints, tools, scripts, or workflows that matter for this capability.
|
|
89
|
+
`;try{await k.createDirectory(t,h),await k.writeFile(t,p,y),await k.writeFile(t,u,b),s(),await this.refreshContentIndex(),location.hash=Yt(t,p)}catch{C("Could not create capability")}};r.addEventListener("click",()=>void c()),i.addEventListener("keydown",l=>{l.stopPropagation(),l.key==="Enter"&&c()}),a.appendChild(r),n.append(i,a),i.focus()})}promptRenameDoc(t,e){const n=e.includes("/")?e.slice(0,e.lastIndexOf("/")+1):"",s=e.replace(/\.md$/,"").split("/").pop()??"",i=`doc:${t}:${e}`,a=this.sidebar.links.get(i);a?this.sidebar.startInlineRename(a,s,async r=>{const c=r.replace(/\.md$/,"").replace(/\s+/g,"-").toLowerCase(),l=`${n}${c}.md`;if(l!==e)try{await k.renameFile(t,e,l),await this.refreshContentIndex(),location.hash=X(t,l)}catch{C("Could not rename doc")}}):V("Rename doc",(r,c)=>{const l=document.createElement("input");l.className="board-title",l.value=s,l.style.width="100%",l.style.marginBottom="12px",l.select();const d=g("div","modal-actions"),h=g("button","btn primary");h.textContent="Rename";const p=async()=>{const u=(l.value.trim()||s).replace(/\.md$/,"").replace(/\s+/g,"-").toLowerCase(),f=`${n}${u}.md`;if(f===e){c();return}try{await k.renameFile(t,e,f),c(),await this.refreshContentIndex(),location.hash=X(t,f)}catch{C("Could not rename doc")}};h.addEventListener("click",()=>void p()),l.addEventListener("keydown",u=>{u.stopPropagation(),u.key==="Enter"&&p()}),d.appendChild(h),r.append(l,d),l.focus()})}async moveDoc(t,e,n){const s=Ts(n,ue(e));if(s!==e)try{const i=new Set(Et(await k.getTree(t)).map(c=>st(c.path))),a=await k.readFile(t,e),r=Es(a,e,s,i);await k.renameFile(t,e,s),r!==a&&await k.writeFile(t,s,r),await this.refreshContentIndex(),location.hash===X(t,e)&&(location.hash=X(t,s)),C(`Moved ${ue(e)}`)}catch{C("Could not move doc")}}async moveBoard(t,e,n){try{const s=await at.move(t,e,n),i=await this.updateBoardEmbedReferences(t,e,s);await this.refreshContentIndex(),location.hash===ot(t,e)&&(location.hash=ot(t,s)),C(i>0?`Moved ${ue(e)} and updated ${i} embed${i===1?"":"s"}`:`Moved ${ue(e)}`)}catch(s){C(s instanceof Error?s.message:"Could not move board")}}async updateBoardEmbedReferences(t,e,n){if(e===n)return 0;const s=await k.getTree(t),i=eo(s);let a=0;for(const r of i){const c=await k.readFile(t,r.path),l=Fr(c,r.path,e,n);l!==c&&(await k.writeFile(t,r.path,l),a++)}return a}async moveDirectory(t,e,n){const s=ue(e),i=Ts(n,s);if(i!==e)try{const a=await k.getTree(t),r=new Set(Et(a).map(p=>st(p.path))),c=Ar(a,e),l=Nr(a,e),d=await Promise.all(l.map(async p=>[p.path,await k.readFile(t,p.path)]));await k.renameFile(t,e,i);let h=0;for(const[p,u]of d){const f=`${i}${p.slice(e.length)}`,y=Es(u,p,f,r);y!==u&&(await k.writeFile(t,f,y),h++)}for(const p of c){const u=`${i}${p.slice(e.length)}`;await this.rewriteMovedBoardDocumentId(t,p,u),h+=await this.updateBoardEmbedReferences(t,p,u)}await this.refreshContentIndex(),this.rewriteRouteAfterDirectoryMove(t,e,i),C(h>0?`Moved ${s} and updated ${h} embed${h===1?"":"s"}`:`Moved ${s}`)}catch{C("Could not move directory")}}promptRenameDirectory(t,e){const n=e.includes("/")?e.slice(0,e.lastIndexOf("/")+1):"",s=e.split("/").pop()??"";V("Rename directory",(i,a)=>{const r=document.createElement("input");r.className="board-title",r.value=s,r.style.width="100%",r.style.marginBottom="12px",r.select();const c=g("div","modal-actions"),l=g("button","btn primary");l.textContent="Rename";const d=async()=>{const h=(r.value.trim()||s).replace(/\s+/g,"-").toLowerCase(),p=`${n}${h}`;if(p===e){a();return}try{await k.renameFile(t,e,p),a(),await this.refreshContentIndex(),C(`Renamed to ${h}`)}catch{C("Could not rename directory")}};l.addEventListener("click",()=>void d()),r.addEventListener("keydown",h=>{h.stopPropagation(),h.key==="Enter"&&d()}),c.appendChild(l),i.append(r,c),r.focus()})}async promptDeleteDirectory(t,e){const n=e.split("/").pop()??e;if(confirm(`Delete "${n}" and all its contents? This cannot be undone.`))try{await k.deleteFile(t,e),await this.refreshContentIndex(),C(`Deleted ${n}`)}catch{C("Could not delete directory")}}async rewriteMovedBoardDocumentId(t,e,n){const s=await k.getBoard(t,n);s&&s.id!==n&&await k.saveBoard(t,n,{...s,id:n,updatedAt:Date.now()})}rewriteRouteAfterDirectoryMove(t,e,n){const s=encodeURIComponent(t),i=`#/root/${s}/docs/`,a=`#/root/${s}/boards/`,r=location.hash;if(r.startsWith(i)){const c=decodeURIComponent(r.slice(i.length));(c===e||c.startsWith(`${e}/`))&&(location.hash=X(t,`${n}${c.slice(e.length)}`))}else if(r.startsWith(a)){const c=decodeURIComponent(r.slice(a.length));(c===e||c.startsWith(`${e}/`))&&(location.hash=ot(t,`${n}${c.slice(e.length)}`))}}async promptDeleteDoc(t,e){const n=e.split("/").pop()??e;V("Delete doc",(s,i)=>{const a=g("p","modal-copy");a.textContent=`Delete "${n}"? This cannot be undone.`;const r=g("div","modal-actions"),c=g("button","btn danger");c.textContent="Delete",c.addEventListener("click",async()=>{try{await k.deleteFile(t,e),i(),await this.refreshContentIndex(),location.hash="#/"}catch{C("Could not delete doc")}});const l=g("button","btn");l.textContent="Cancel",l.addEventListener("click",i),r.append(c,l),s.append(a,r)})}async promptRenameBoard(t,e){const n=await at.load(t,e);if(!n){C("Board not found");return}V("Rename board",(s,i)=>{const a=document.createElement("input");a.className="board-title",a.value=n.title,a.style.width="100%",a.style.marginBottom="12px",a.select();const r=g("div","modal-actions"),c=g("button","btn primary");c.textContent="Rename";const l=async()=>{const d=Pt(a.value,"board");if(!d.ok){C(d.message),a.focus();return}try{const h=await at.rename(t,e,d.raw),p=await this.updateBoardEmbedReferences(t,e,h);i(),await this.refreshContentIndex(),location.hash===ot(t,e)&&(location.hash=ot(t,h)),p>0&&C(`Renamed board and updated ${p} embed${p===1?"":"s"}`)}catch(h){C(h instanceof Error?h.message:"Could not rename board")}};c.addEventListener("click",()=>void l()),a.addEventListener("keydown",d=>{d.stopPropagation(),d.key==="Enter"&&l()}),r.appendChild(c),s.append(a,r),a.focus()})}promptDeleteBoard(t,e){V("Delete board",(n,s)=>{const i=g("p","modal-copy");i.textContent=`Delete "${e}.board.json"? This cannot be undone.`;const a=g("div","modal-actions"),r=g("button","btn danger");r.textContent="Delete",r.addEventListener("click",async()=>{try{await at.delete(t,e),s(),await this.refreshContentIndex(),location.hash=Kt(t)}catch{C("Could not delete board")}});const c=g("button","btn");c.textContent="Cancel",c.addEventListener("click",s),a.append(r,c),n.append(i,a)})}async openEditor(t,e,n){if(!this.docsRootById(t)){this.renderMessage("Docs root unavailable","This docs root is no longer registered. Re-add the project root if needed.");return}this.editor&&this.editingId===`${t}:${e}`||(this.exitEditor(),this.disposeContent(),this.layout.style.display="none",this.editorHost=g("div","board-editor-host"),this.root.appendChild(this.editorHost),this.editingId=`${t}:${e}`,this.editor=new Ja(this.editorHost,{boardId:e,loadBoard:async s=>{const i=await k.getBoardWithRevision(t,s);return i||void 0},saveBoard:(s,i)=>k.saveBoard(t,s.id,s,i),deleteBoard:s=>at.delete(t,s),uploadImage:(s,i)=>at.uploadImage(t,s,i),cleanupUnusedAssets:s=>at.cleanupUnusedAssets(t,s),resolveAssetUrl:s=>k.assetUrl(t,s),initialRegion:n,onExit:()=>{this.pendingScrollRestore=this.lastNonBoardScrollTop,location.hash=this.lastNonBoardHash},onDeleted:()=>{location.hash=Kt(t)}}))}exitEditor(){this.editor&&(this.editor.destroy(),this.editor=void 0),this.editorHost&&(this.editorHost.remove(),this.editorHost=void 0),this.editingId=void 0,this.applyInitialTheme()}applyInitialTheme(){const t=localStorage.getItem(fs),e=t==="dark"||t==="light"?t:window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light";document.documentElement.setAttribute("data-theme",e)}toggleTheme(){var e;const t=me()==="dark"?"light":"dark";document.documentElement.setAttribute("data-theme",t),localStorage.setItem(fs,t),this.updateThemeButton(),(e=this.updateRenderedTheme)==null||e.call(this,t)}createTopbar(){const t=g("div","shell-topbar"),e=g("button","topbar-icon-btn");return e.innerHTML=Y.panelLeft,e.title="Toggle navigation",e.setAttribute("aria-label","Toggle navigation"),e.addEventListener("click",()=>this.setSidebarCollapsed(!this.layout.classList.contains("sidebar-collapsed"))),this.searchBtn=g("button","topbar-search"),this.searchBtn.type="button",this.searchBtn.innerHTML=`${Y.search}<span>Search docs</span><kbd>${this.shortcutLabel()}</kbd>`,this.searchBtn.addEventListener("click",()=>this.openCommandPalette()),this.cartBtn=g("button","topbar-cart"),this.cartBtn.type="button",this.cartBtn.hidden=!0,this.exportBtn=g("button","topbar-icon-btn topbar-export"),this.exportBtn.type="button",this.exportBtn.innerHTML=Y.export,this.exportBtn.title="Export options",this.exportBtn.setAttribute("aria-label","Export options"),this.exportBtn.setAttribute("aria-haspopup","menu"),this.exportBtn.setAttribute("aria-expanded","false"),this.exportBtn.addEventListener("click",()=>{this.toggleExportMenu()}),this.editBtn=g("button","btn topbar-edit"),this.editBtn.type="button",this.editBtn.innerHTML=`${Y.edit}<span>Edit</span>`,this.editBtn.title="Edit this document",this.editBtn.addEventListener("click",()=>{this.currentEditableFile&&this.openDocEditor(this.currentEditableFile)}),this.themeBtn=g("button","topbar-icon-btn topbar-theme"),this.themeBtn.type="button",this.themeBtn.title="Toggle theme",this.themeBtn.setAttribute("aria-label","Toggle theme"),this.themeBtn.addEventListener("click",()=>this.toggleTheme()),this.updateThemeButton(),t.append(e,this.searchBtn,this.exportBtn,this.editBtn,this.themeBtn),t}setSidebarCollapsed(t){this.layout.classList.toggle("sidebar-collapsed",t),localStorage.setItem(gs,String(t))}setupSidebarResize(){this.sidebarResizeHandle&&this.sidebarResizeHandle.addEventListener("pointerdown",t=>{var r;if(this.layout.classList.contains("sidebar-collapsed"))return;t.preventDefault();const e=t.clientX,n=this.readSidebarWidth(),s=t.pointerId;(r=this.sidebarResizeHandle)==null||r.setPointerCapture(s),document.body.classList.add("sidebar-resizing");const i=c=>{const l=pn(n+c.clientX-e);this.applySidebarWidth(l)},a=()=>{var c;(c=this.sidebarResizeHandle)==null||c.releasePointerCapture(s),document.body.classList.remove("sidebar-resizing"),window.removeEventListener("pointermove",i),window.removeEventListener("pointerup",a)};window.addEventListener("pointermove",i),window.addEventListener("pointerup",a)})}readSidebarWidth(){const t=Number(localStorage.getItem(ys)??270);return pn(t)}applySidebarWidth(t){const e=pn(t);this.layout.style.setProperty("--sidebar-width",`${e}px`),localStorage.setItem(ys,String(e))}setEditableFile(t){this.currentEditableFile=t,this.editBtn&&(this.exportBtn.hidden=!t,this.exportBtn.disabled=!t,this.editBtn.hidden=!t,this.editBtn.disabled=!t)}promptRemoveProject(t,e){V("Remove from workspace",(n,s)=>{const i=g("p","modal-copy");i.textContent=`Remove "${e}" from the workspace? The files on disk are not deleted.`;const a=g("div","modal-actions"),r=g("button","btn danger");r.textContent="Remove",r.addEventListener("click",async()=>{try{await k.removeProject(t),s(),await this.refreshContentIndex(),location.hash="#/"}catch{C("Could not remove project")}});const c=g("button","btn");c.textContent="Cancel",c.addEventListener("click",s),a.append(r,c),n.append(i,a)})}async addRepoDocs(){var t;try{const e=new Set(this.allDocsRoots().map(h=>h.id)),n=new Set(this.workspace.projects.map(h=>h.id));let s={cancelled:!1};try{s=await k.pickAndAddProject()}catch{const p=window.prompt("Project root path","");if(!p||!p.trim())return;const u=await k.addProject(p.trim());this.workspace=u,s={cancelled:!1,addedProjectId:(t=u.projects.find(f=>!n.has(f.id)))==null?void 0:t.id}}if(s.cancelled)return;await this.refreshContentIndex();let i=s.addedProjectId?this.workspace.projects.find(h=>h.id===s.addedProjectId):void 0,a=i==null?void 0:i.docsRoots[0];if(i&&i.docsRoots.length===0){const h=await this.promptCreateProjectDocsRoot(i.id,i.label);if(!h){location.hash=Dt(i.id),C(`Added ${i.label}. Create docs/ later or switch to Raw view from the project menu.`);return}i=this.workspace.projects.find(p=>p.id===(i==null?void 0:i.id)),a=h}const r=this.allDocsRoots(),c=a??r.find(h=>!e.has(h.id));if(!c){C("No docs folders found under that project root.");return}const l=this.treesByRoot.get(c.id)??[],d=un(ee(l));d?location.hash=X(c.id,d):location.hash=Kt(c.id),C(`Added ${c.projectLabel}.`)}catch(e){C(e instanceof Error?e.message:"Could not add project root.")}}promptCreateProjectDocsRoot(t,e){return new Promise(n=>{V("Create docs folder",(s,i)=>{let a=!1;const r=u=>{a||(a=!0,i(),n(u))},c=document.createElement("p");c.textContent=`${e} does not have a docs/ folder yet. Create one at the project root now?`;const l=document.createElement("p");l.textContent="You can keep the repo in the workspace and switch to Raw view later if you prefer.";const d=g("div","modal-actions"),h=g("button","btn primary");h.textContent="Create docs/",h.addEventListener("click",()=>{h.disabled=!0,p.disabled=!0,this.ensureProjectDocsRoot(t).then(u=>{if(!u){h.disabled=!1,p.disabled=!1;return}r(u)})});const p=g("button","btn");p.textContent="Maybe later",p.addEventListener("click",()=>r(void 0)),d.append(h,p),s.append(c,l,d)})})}updateTopbarCart(t=!1){this.cartBtn&&(this.cartBtn.hidden=!0)}toggleExportMenu(){var n;if(!this.exportBtn||this.exportBtn.hidden||!this.currentEditableFile)return;if((n=this.exportMenu)!=null&&n.classList.contains("visible")){this.closeExportMenu();return}this.closeCartPopover(),this.closeExportMenu();const t=g("div","topbar-export-menu");t.setAttribute("role","menu"),t.setAttribute("aria-label","Export options");const e=document.createElement("button");e.className="topbar-export-item",e.type="button",e.setAttribute("role","menuitem"),e.innerHTML=`${Y.export}<span>Export to PDF</span>`,e.addEventListener("click",()=>{const s=this.currentEditableFile;this.closeExportMenu(),s&&this.exportDocPdf(s.rootId,s.path)}),t.appendChild(e),this.topbar.appendChild(t),this.exportMenu=t,this.exportBtn.setAttribute("aria-expanded","true"),requestAnimationFrame(()=>e.focus()),t.classList.add("visible")}closeExportMenu(){var t,e;(t=this.exportMenu)==null||t.remove(),this.exportMenu=void 0,(e=this.exportBtn)==null||e.setAttribute("aria-expanded","false")}toggleCartPopover(){this.closeCartPopover()}closeCartPopover(){var t;this.content.classList.remove("cart-popover-open"),(t=this.cartPopover)==null||t.classList.remove("visible")}handleGlobalPointerDown(t){if(!this.exportMenu)return;const e=t.target;e&&(this.exportMenu.contains(e)||this.exportBtn.contains(e)||this.closeExportMenu())}updateThemeButton(){if(!this.themeBtn)return;const t=me()==="dark";this.themeBtn.innerHTML=t?Y.sun:Y.moon,this.themeBtn.title=t?"Switch to light mode":"Switch to dark mode",this.themeBtn.setAttribute("aria-label",this.themeBtn.title)}handleGlobalKeydown(t){if(t.key==="Escape"&&this.closeExportMenu(),(t.metaKey||t.ctrlKey)&&t.key.toLowerCase()==="k"){const e=t.target;if(e!=null&&e.closest(".doc-editor"))return;t.preventDefault(),this.openCommandPalette();return}if(t.key==="F2"){const e=location.hash,n=t.target;if(n!=null&&n.closest(".doc-editor, input, textarea, [contenteditable]"))return;t.preventDefault();const s=e.match(/^#\/root\/([^/]+)\/docs\/(.+)$/);if(s){const r=decodeURIComponent(s[1]),c=decodeURIComponent(s[2]);this.promptRenameDoc(r,c);return}const i=e.match(/^#\/root\/([^/]+)\/boards\/(.+)$/);if(i){const r=decodeURIComponent(i[1]),c=decodeURIComponent(i[2]);this.promptRenameBoard(r,c);return}const a=e.match(/^#\/root\/([^/]+)\/directory\/(.+)$/);if(a){const r=decodeURIComponent(a[1]),c=decodeURIComponent(a[2]);this.promptRenameDirectory(r,c);return}}}allDocsRoots(){return this.workspace.projects.flatMap(t=>t.docsRoots)}docsRootById(t){return this.allDocsRoots().find(e=>e.id===t)}async refreshContentIndex(){try{this.workspace=await k.getWorkspace()}catch{this.workspace={projects:[]},this.treesByRoot=new Map,this.treesByProject=new Map,this.sidebar.refresh(this.workspace,this.treesByRoot),this.searchIndex=[],this.searchIndexing=!1;return}const t=this.allDocsRoots(),e=await Promise.all(t.map(async s=>{try{return[s.id,await k.getTree(s.id)]}catch{return[s.id,[]]}}));this.treesByRoot=new Map(e);const n=await Promise.all(this.workspace.projects.map(async s=>{try{return[s.id,await k.getProjectTree(s.id)]}catch{return[s.id,[]]}}));this.treesByProject=new Map(n),this.sidebar.refresh(this.workspace,this.treesByRoot,this.treesByProject),this.refreshSearchIndexInBackground(t,this.treesByRoot)}async refreshSearchIndexInBackground(t,e){var i,a;const n=++this.searchIndexRun;this.searchIndexing=!0;const s=[];for(const r of t){const c=e.get(r.id)??[],l=[...he(c),...co(c,"capabilities")].filter(d=>d.type==="file"&&d.name.endsWith(".md"));for(const d of l){const h="path"in d?d.path:"";let p="";try{p=await k.readFile(r.id,h)}catch{}const{frontmatter:u}=Zt(p),f=to(p),y=u.title??Js(p)??ht(d.name),b=u.summary??Qs(f),w=h.startsWith("capabilities/")?"Capability":"Doc",v=h.startsWith("capabilities/")?Yt(r.id,h):X(r.id,h);s.push({title:y,path:`${r.projectLabel}/${r.displayPath}/${h}`,href:v,section:w,summary:b,body:f.map(S=>S.text).join(" "),chunks:f,rootId:r.id})}}n===this.searchIndexRun&&(this.searchIndex=s.filter(r=>r.body||r.title),this.searchIndexing=!1,this.paletteResults&&((i=this.palette)!=null&&i.classList.contains("visible"))&&this.renderSearchResults(((a=this.paletteInput)==null?void 0:a.value)??""))}openCommandPalette(){var t;this.palette||this.createCommandPalette(),(t=this.palette)==null||t.classList.add("visible"),document.body.style.overflow="hidden",this.paletteInput.value="",this.renderSearchResults(""),requestAnimationFrame(()=>{var e;return(e=this.paletteInput)==null?void 0:e.focus()})}closeCommandPalette(){var t;(t=this.palette)==null||t.classList.remove("visible"),document.body.style.overflow=""}createCommandPalette(){this.palette=g("div","command-palette");const t=g("div","command-panel"),e=g("div","command-search");e.innerHTML=Y.search,this.paletteInput=document.createElement("input"),this.paletteInput.type="search",this.paletteInput.placeholder="Search docs",this.paletteInput.setAttribute("aria-label","Search docs"),e.appendChild(this.paletteInput),this.paletteResults=g("div","command-results"),t.append(e,this.paletteResults),this.palette.appendChild(t),document.body.appendChild(this.palette),this.palette.addEventListener("mousedown",n=>{n.target===this.palette&&this.closeCommandPalette()}),this.paletteInput.addEventListener("input",()=>this.renderSearchResults(this.paletteInput.value)),this.paletteInput.addEventListener("keydown",n=>this.handlePaletteKeydown(n))}handlePaletteKeydown(t){var i,a,r,c,l;if(t.key==="Escape"){t.preventDefault(),this.closeCommandPalette();return}const e=[...((i=this.paletteResults)==null?void 0:i.querySelectorAll(".command-result"))??[]],n=(a=this.paletteResults)==null?void 0:a.querySelector(".command-result.active"),s=n?e.indexOf(n):-1;if(t.key==="ArrowDown"||t.key==="ArrowUp"){t.preventDefault();const d=t.key==="ArrowDown"?Math.min(s+1,e.length-1):Math.max(s-1,0);e.forEach(h=>h.classList.remove("active")),(r=e[d])==null||r.classList.add("active"),(c=e[d])==null||c.scrollIntoView({block:"nearest"})}t.key==="Enter"&&(t.preventDefault(),(l=n??e[0])==null||l.click())}renderSearchResults(t){if(!this.paletteResults)return;const e=$r(t),n=this.rankSearch(e).slice(0,8);if(this.paletteResults.replaceChildren(),n.length===0){const s=g("div","command-empty");s.textContent=this.searchIndex.length?"No matching docs.":this.searchIndexing?"Indexing docs...":"No docs indexed yet.",this.paletteResults.appendChild(s);return}for(const[s,i]of n.entries()){const{entry:a}=i,r=document.createElement("a");r.className="command-result",s===0&&r.classList.add("active"),r.href=a.href,r.addEventListener("click",()=>this.closeCommandPalette());const c=g("div","command-result-title");ks(c,a.title,e);const l=g("div","command-result-meta");l.textContent=[a.section,i.heading,a.path].filter(Boolean).join(" · ");const d=g("div","command-result-summary");ks(d,i.preview,e),r.append(c,l),d.textContent&&r.appendChild(d),this.paletteResults.appendChild(r)}}rankSearch(t){if(t.length===0)return this.searchIndex.map(s=>({entry:s,score:0,heading:"",preview:s.summary||s.body.slice(0,220)}));const e=t.map(vt).filter(Boolean),n=vt(t.join(" "));return this.searchIndex.map(s=>{const i=vt(s.title),a=vt(s.path),r=vt(s.summary);let c=pe(i,e,n,10);c+=pe(a,e,n,4),c+=pe(r,e,n,3);let l,d=0;for(const p of s.chunks){const u=pe(vt(p.heading),e,n,5),f=pe(p.normalized,e,n,p.kind==="heading"?8:2),y=u+f;y>d&&(d=y,l=p)}const h=c+d;return{entry:s,score:h,heading:l!=null&&l.heading&&l.heading!==s.title?l.heading:"",preview:l?jr(l.text,e):s.summary}}).filter(s=>s.score>0).sort((s,i)=>i.score-s.score||s.entry.title.localeCompare(i.entry.title))}shortcutLabel(){return/Mac|iPhone|iPad/.test(navigator.platform)?"⌘K":"Ctrl K"}disposeContent(){this.cleanup&&(this.cleanup(),this.cleanup=void 0),this.updateRenderedTheme=void 0,this.content.classList.remove("content-wide"),this.content.replaceChildren()}renderMessage(t,e){this.disposeContent();const n=g("div","page"),s=g("h1","");s.textContent=t;const i=g("p","page-lead");i.textContent=e,n.append(s,i),this.content.replaceChildren(n)}}function De(o,t,e={}){const n=[{label:"Home",href:"#/"}];let s;for(const c of o.projects){const l=c.docsRoots.find(d=>d.id===t);if(l){n.push({label:c.label,href:Dt(c.id)}),s=l;break}}if(s){const c=s.displayPath.split("/").filter(Boolean);for(let l=0;l<c.length;l++){const d=c.slice(0,l+1).join("/");n.push({label:c[l],href:Xe(t,d)})}}const a=(e.filePath??e.dirPath??"").split("/").filter(Boolean),r=e.filePath?a.slice(0,-1):a;for(let c=0;c<r.length;c++){const l=r.slice(0,c+1).join("/");n.push({label:ht(r[c]),href:Xe(t,l)})}if(e.currentLabel)n.push({label:e.currentLabel});else if(e.filePath){const c=a[a.length-1];n.push({label:c==="index.md"?"Overview":ht(c)})}return n}function kt(o){const t=g("nav","breadcrumb");t.setAttribute("aria-label","Breadcrumb");for(let e=0;e<o.length;e++){const n=o[e],s=e===o.length-1;if(!s&&n.href){const i=document.createElement("a");i.className="breadcrumb-link",i.href=n.href,i.textContent=n.label,t.appendChild(i)}else{const i=g("span","breadcrumb-current");i.textContent=n.label,t.appendChild(i)}if(!s){const i=g("span","breadcrumb-sep");i.textContent="/",i.setAttribute("aria-hidden","true"),t.appendChild(i)}}return t}function g(o,t){const e=document.createElement(o);return t&&(e.className=t),e}function Xt(o){const t=g("div","empty-note");return t.textContent=o,t}function bs(o,t,e,n){var s;return{path:`${o}:${t.branchPath}`,rootId:o,branchPath:t.branchPath,entryPath:t.entryPath,displayPath:t.routePath,title:n.title??Js(e)??qe(t.entryPath),summary:n.summary??Qs(to(e)),kind:((s=n.kind)==null?void 0:s.trim())||void 0,tags:n.tags?n.tags.split(",").map(i=>i.trim()).filter(Boolean):[],md:e}}function Ae(o,t){const e=[];function n(a){const c=[...ee(a)].sort((l,d)=>{const h=l.type==="file"&&l.name==="index.md"?-1:0,p=d.type==="file"&&d.name==="index.md"?-1:0;return h!==p?h-p:l.type!==d.type?l.type==="dir"?-1:1:l.name.localeCompare(d.name)});for(const l of c)if(l.type==="file"){const d=l.name==="index.md"?"Overview":ht(l.name);e.push({label:d,href:X(o,l.path)})}else n(l.children)}n(t);const s=Et(t).sort((a,r)=>a.path.localeCompare(r.path));if(s.length>0){e.push({label:"All Boards",href:Kt(o)});for(const a of s){const r=st(a.path);e.push({label:ht(r.split("/").pop()??r),href:ot(o,r)})}}const i=Ht(t);if(i.length>0){e.push({label:"All Capabilities",href:Vs(o)});for(const a of i)e.push({label:qe(a.entryPath),href:Yt(o,a.entryPath)})}return e}function Ne(o,t){const e=o.findIndex(a=>a.href===t);if(e===-1)return null;const n=e>0?o[e-1]:null,s=e<o.length-1?o[e+1]:null;if(!n&&!s)return null;const i=g("nav","page-nav");if(n){const a=g("a","page-nav-prev");a.href=n.href,a.innerHTML=`<span class="page-nav-arrow">←</span><span class="page-nav-label">${n.label}</span>`,i.appendChild(a)}else i.appendChild(g("span","page-nav-spacer"));if(s){const a=g("a","page-nav-next");a.href=s.href,a.innerHTML=`<span class="page-nav-label">${s.label}</span><span class="page-nav-arrow">→</span>`,i.appendChild(a)}return i}function Vs(o){return`#/root/${encodeURIComponent(o)}/capabilities`}function ee(o){return o.filter(t=>t.type==="file"?t.name.endsWith(".md"):t.name==="capabilities"||t.name==="assets"?!1:ee(t.children).length>0).map(t=>t.type==="file"?t:{...t,children:ee(t.children)})}function he(o){const t=[],e=n=>{for(const s of ee(n))s.type==="file"?t.push(s):e(s.children)};return e(o),t}function X(o,t){return`#/root/${encodeURIComponent(o)}/docs/${encodeURIComponent(t)}`}function Yt(o,t){return`#/root/${encodeURIComponent(o)}/capabilities/${encodeURIComponent(ne(t))}`}function Ht(o){const t=o.find(s=>s.type==="dir"&&s.name==="capabilities");if(!t||t.type!=="dir")return[];const e=[],n=s=>{for(const i of s){if(i.type==="file"){i.path.startsWith("capabilities/")&&i.name.endsWith(".md")&&!i.path.slice(13).includes("/")&&e.push({branchPath:i.path,entryPath:i.path,routePath:ne(i.path)});continue}const a=Ir(i);a&&e.push({branchPath:i.path,entryPath:a.path,routePath:ne(i.path)}),n(i.children)}};return n(t.children),e.sort((s,i)=>s.branchPath.localeCompare(i.branchPath))}function Er(o,t){const e=t.replace(/^\/+|\/+$/g,""),n=e.startsWith("capabilities/")?e:`capabilities/${e}`;if(n.endsWith(".md"))return n;const s=Ht(o).find(i=>i.branchPath===n||i.routePath===e);return(s==null?void 0:s.entryPath)??null}function vs(o,t){const e=t.replace(/^\/+|\/+$/g,""),n=e.startsWith("capabilities/")?e:`capabilities/${e}`,s=Ht(o).find(i=>i.branchPath===n||i.entryPath===n||i.routePath===e);return s||(Ht(o).filter(i=>n.startsWith(`${i.branchPath}/`)).sort((i,a)=>a.branchPath.length-i.branchPath.length)[0]??null)}function qe(o){if(o.endsWith("/index.md")){const t=o.slice(0,-9);return ht(t.split("/").pop()??t)}return ht(o.split("/").pop()??o)}function ne(o){const t=o.replace(/^capabilities\//,"");return t.endsWith("/index.md")?t.slice(0,-9):t}function Sr(o){return{branchPath:Tr(o),entryPath:o,routePath:ne(o)}}function Tr(o){return o.endsWith("/index.md")?o.slice(0,-9):o}function xs(o,t){const e=Gs(o,t);return e?e.type==="file"?[e]:Zs(e.children).sort(Lr):[]}function Fe(o){return ne(o)||"index.md"}function Br(o){return o.endsWith(".md")?null:`${o}/llms.txt`}function Mr(o){return/\.(md|txt|json|ya?ml|js|ts|mjs|cjs|sh|css|html)$/i.test(o)}function Gs(o,t){for(const e of o){if(e.path===t)return e;if(e.type==="dir"){const n=Gs(e.children,t);if(n)return n}}return null}function Zs(o){const t=[];for(const e of o)e.type==="file"?t.push(e):t.push(...Zs(e.children));return t}function Lr(o,t){const e=ws(o.path),n=ws(t.path);if(e!==n)return e.localeCompare(n);const s=Cs(o.name),i=Cs(t.name);return s!==i?s?-1:1:o.path.localeCompare(t.path)}function ws(o){const t=o.lastIndexOf("/");return t===-1?"":o.slice(0,t)}function Cs(o){return/^readme\.(md|txt)$/i.test(o)}function Ir(o){const t=o.children.find(e=>e.type==="file"&&e.name==="index.md");return t||(o.children.find(e=>e.type==="file"&&e.name.endsWith(".md"))??null)}function Kt(o){return`#/root/${encodeURIComponent(o)}/boards`}function ot(o,t){return`#/root/${encodeURIComponent(o)}/boards/${encodeURIComponent(t)}`}function Dt(o){return`#/project/${encodeURIComponent(o)}`}function Xe(o,t){return`#/root/${encodeURIComponent(o)}/directory/${encodeURIComponent(t)}`}function Pr(o){const t=o.match(/^#\/root\/([^/]+)/);return t?decodeURIComponent(t[1]):null}function Js(o){var t,e;return((e=(t=o.match(/^#\s+(.+)$/m))==null?void 0:t[1])==null?void 0:e.trim())??null}function $r(o){return[...new Set(o.trim().split(/\s+/).map(vt).filter(Boolean))]}function ks(o,t,e){const n=e.filter(Boolean).sort((a,r)=>r.length-a.length);if(n.length===0){o.textContent=t;return}const s=new RegExp(`(${n.map(Rr).join("|")})`,"ig");let i=0;for(const a of t.matchAll(s)){const r=a.index??0;r>i&&o.appendChild(document.createTextNode(t.slice(i,r)));const c=document.createElement("mark");c.textContent=a[0],o.appendChild(c),i=r+a[0].length}i<t.length&&o.appendChild(document.createTextNode(t.slice(i)))}function Rr(o){return o.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function Qs(o){var t;return((t=o.find(e=>e.kind==="text"&&e.text.length>0))==null?void 0:t.text.slice(0,180))??""}function to(o){const e=o.replace(/^---[\s\S]*?---\s*/,"").split(`
|
|
90
|
+
`),n=[];let s="",i=[];const a=(c,l="text",d=s)=>{const h=Ss(c);h&&n.push({heading:d,text:h,normalized:vt(h),kind:l})},r=()=>{i.length!==0&&(a(i.join(" "),"text"),i=[])};for(let c=0;c<e.length;c++){const l=e[c],d=l.match(/^(`{3,})\s*([\w-]+)?\s*$/);if(d){r();const u=d[1].length,f=(d[2]??"").toLowerCase(),y=new RegExp("^`{"+u+",}\\s*$"),b=[];for(c++;c<e.length&&!y.test(e[c]);)b.push(e[c]),c++;a(f==="board"?Dr(b.join(`
|
|
91
|
+
`)):b.join(`
|
|
92
|
+
`),f==="board"?"board":"code");continue}const h=l.match(/^(#{1,6})\s+(.+)$/);if(h){r(),s=Ss(h[2]),a(s,"heading",s);continue}if(l.trim()===""||/^(-{3,}|\*{3,}|_{3,})\s*$/.test(l)){r();continue}if(Wr(l))continue;const p=l.replace(/^>\s?/,"").replace(/^\s*([-*+]|\d+\.)\s+/,"").replace(/^\[([ xX])\]\s+/,"").replace(/\|/g," ");i.push(p)}return r(),n}function Dr(o){return o.split(`
|
|
93
|
+
`).map(t=>t.replace(/#.*$/,"").trim()).filter(Boolean).map(t=>t.replace(/^(\w+)\s*:\s*/,"$1 ")).join(" ")}function eo(o){const t=[],e=n=>{for(const s of n)s.type==="file"?s.name.endsWith(".md")&&t.push(s):e(s.children)};return e(o),t}function Et(o){const t=[],e=n=>{for(const s of n)s.type==="file"?s.name.endsWith(".board.json")&&t.push(s):e(s.children)};return e(o),t}function Ar(o,t){const e=t.replace(/^\/+|\/+$/g,"");return Et(o).map(n=>st(n.path)).filter(n=>n===e||n.startsWith(`${e}/`))}function Nr(o,t){const e=t.replace(/^\/+|\/+$/g,"");return eo(o).filter(n=>n.path.startsWith(`${e}/`))}function Es(o,t,e,n){if(t===e)return o;const s=o.split(`
|
|
94
|
+
`);let i=!1,a,r=!1;const c=s.map(l=>{if(!i){const u=l.match(/^(`{3,})\s*board\s*$/i);return u&&(i=!0,a=new RegExp("^`{"+u[1].length+",}\\s*$")),l}if(a!=null&&a.test(l))return i=!1,a=void 0,l;const d=l.match(/^(\s*src\s*:\s*)(.*)$/i);if(!d)return l;const h=no(d[2]);if(!h.value)return l;const p=Hr(h.value,t,e,n);return p===h.value?l:(r=!0,`${d[1]}${p}${h.suffix}`)});return r?c.join(`
|
|
95
|
+
`):o}function Fr(o,t,e,n){const s=o.split(`
|
|
96
|
+
`);let i=!1,a,r=!1;const c=s.map(l=>{if(!i){const u=l.match(/^(`{3,})\s*board\s*$/i);return u&&(i=!0,a=new RegExp("^`{"+u[1].length+",}\\s*$")),l}if(a!=null&&a.test(l))return i=!1,a=void 0,l;const d=l.match(/^(\s*src\s*:\s*)(.*)$/i);if(!d)return l;const h=no(d[2]);return!h.value||!xe(h.value,t).includes(e)?l:(r=!0,`${d[1]}${zr(h.value,t,e,n)}${h.suffix}`)});return r?c.join(`
|
|
97
|
+
`):o}function no(o){var i;const t=o.indexOf("#"),e=t===-1?o:o.slice(0,t),n=t===-1?"":o.slice(t),s=((i=e.match(/\s*$/))==null?void 0:i[0])??"";return{value:e.trim(),suffix:`${s}${n}`}}function zr(o,t,e,n){const s=o.trim(),i=s.startsWith("/"),a=s.startsWith("./")||s.startsWith("../"),r=s.endsWith(".board.json"),c=xe(s,t),l=!a&&c[0]!==e&&c.includes(e);if(i){const h=`/${n}`;return r&&!h.endsWith(".board.json")?`${h}.board.json`:h}let d=a||l?so(wn(t,n)):n;return r&&!d.endsWith(".board.json")&&(d=`${d}.board.json`),d}function Hr(o,t,e,n){const s=o.trim(),i=s.startsWith("./")||s.startsWith("../"),a=xe(s,t),r=a[0]??"",c=a.find(p=>p!==r&&n.has(p));if(!i&&(!c||n.has(r)))return o;const l=s.endsWith(".board.json"),d=i?fo(s,t):c;if(!d)return o;let h=so(wn(e,d));return l&&!h.endsWith(".board.json")&&(h=`${h}.board.json`),h}function so(o){return!o||o.startsWith("./")||o.startsWith("../")?o:`./${o}`}function Ss(o){return o.replace(/!\[([^\]]*)\]\(([^)]+)\)/g,"$1 $2").replace(/\[([^\]]+)\]\(([^)]+)\)/g,"$1 $2").replace(/`([^`]+)`/g,"$1").replace(/~~([\s\S]*?)~~/g,"$1").replace(/\*\*\*([\s\S]*?)\*\*\*/g,"$1").replace(/___([\s\S]*?)___/g,"$1").replace(/\*\*([\s\S]*?)\*\*/g,"$1").replace(/__([\s\S]*?)__/g,"$1").replace(/(^|[\s([{])\*([^*\s][\s\S]*?[^*\s])\*(?=$|[\s)\]},.!?:;])/g,"$1$2").replace(/(^|[\s([{])_([^_\s][\s\S]*?[^_\s])_(?=$|[\s)\]},.!?:;])/g,"$1$2").replace(/\\([\\`*_[\]{}()#+\-.!|>])/g,"$1").replace(/<[^>]+>/g," ").replace(/ /g," ").replace(/"/g,'"').replace(/'/g,"'").replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/(^|[\s([{])[*_]{1,3}(?=\S)/g,"$1").replace(new RegExp("(?<=\\S)[*_]{1,3}(?=$|[\\s)\\]},.!?:;])","g"),"").replace(/\s+/g," ").trim()}function vt(o){return o.normalize("NFKD").replace(/[\u0300-\u036f]/g,"").toLowerCase().replace(/[^a-z0-9]+/g," ").trim()}function pe(o,t,e,n){if(!o)return 0;let s=e&&o.includes(e)?n*4:0;for(const i of t)o===i&&(s+=n*5),o.startsWith(i)&&(s+=n*3),o.includes(i)&&(s+=n);return s}function jr(o,t){if(t.length===0)return o.slice(0,220);const e=vt(o),n=t.map(l=>e.indexOf(l)).filter(l=>l>=0).sort((l,d)=>l-d)[0];if(n===void 0)return o.slice(0,220);const s=e.length===0?0:n/e.length,i=Math.round(o.length*s),a=Math.max(0,i-90),r=Math.min(o.length,i+170),c=o.slice(a,r).trim();return`${a>0?"... ":""}${c}${r<o.length?" ...":""}`}function Wr(o){return/^\s*\|?\s*:?-{1,}:?\s*(\|\s*:?-{1,}:?\s*)*\|?\s*$/.test(o)}function ht(o){const t=o.replace(/\.md$/,"").replace(/[-_]/g," ");return t.charAt(0).toUpperCase()+t.slice(1)}function Or(o){return o.trim().replace(/[\\/]+/g,"-").replace(/\s+/g,"-").replace(/[^a-z0-9-_]/gi,"-").replace(/-+/g,"-").replace(/^-|-$/g,"").toLowerCase()}const Ur=new Set([".","..","assets","boards","capabilities","docs"]);function Pt(o,t){const e=t==="doc"?"doc":t,n=o.trim();if(!n)return{ok:!1,message:`Enter a ${e} name.`};if(n.length>80)return{ok:!1,message:"Name must be 80 characters or fewer."};if(/[\\/]/.test(n))return{ok:!1,message:"Name cannot contain slashes."};if(/^\.+$/.test(n))return{ok:!1,message:"Name cannot contain only dots."};if(n.startsWith("."))return{ok:!1,message:"Name cannot start with a dot."};if(/[<>:"|?*\x00-\x1F]/.test(n))return{ok:!1,message:"Name contains characters that are not allowed in files."};const s=Or(n);return s?s.length>64?{ok:!1,message:"Name is too long after formatting."}:Ur.has(s)?{ok:!1,message:`"${s}" is reserved by the workspace.`}:/[a-z0-9]/.test(s)?{ok:!0,raw:n,slug:s}:{ok:!1,message:"Name must include letters or numbers."}:{ok:!1,message:"Name must include letters or numbers."}}function ue(o){const t=o.replace(/^\/+|\/+$/g,"");return t.split("/").pop()??t}function Ts(o,t){const e=o.replace(/^\/+|\/+$/g,""),n=t.replace(/^\/+|\/+$/g,"");return e?`${e}/${n}`:n}function _r(o){if(!o)return;const t=new URLSearchParams(o).get("region");if(!t)return;const e=t.split(",").map(n=>Number(n.trim()));if(!(e.length!==4||e.some(n=>!Number.isFinite(n))||e[2]<=0||e[3]<=0))return[e[0],e[1],e[2],e[3]]}function pn(o){return Math.max(wr,Math.min(Cr,o))}const oo=document.getElementById("app");if(!oo)throw new Error("Missing #app root element");new kr(oo);
|