velloo 0.1.0 → 0.3.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.
Files changed (114) hide show
  1. package/README.md +67 -41
  2. package/canvas/assets/index-CqXW6xA_.js +29 -0
  3. package/canvas/assets/index-gB0StCrx.css +2 -0
  4. package/canvas/assets/lucide-all-C_CNpsMs.js +1 -0
  5. package/canvas/assets/{radix-C3HaOB-d.js → radix-gmpYzWRH.js} +1 -1
  6. package/canvas/index.html +3 -3
  7. package/chunk-0zen7bzb.js +3 -0
  8. package/{chunk-h0c36khx.js → chunk-1jzhw3p4.js} +1 -1
  9. package/chunk-1n5kmsxb.js +2 -0
  10. package/{chunk-k6ferbam.js → chunk-2fgfex9b.js} +1 -1
  11. package/{chunk-t2ttkxe9.js → chunk-3g3dqej3.js} +1 -1
  12. package/chunk-3tmsrvaj.js +2 -0
  13. package/chunk-49cgk5s2.js +2 -0
  14. package/{chunk-e2ag33vd.js → chunk-4nqr089t.js} +2 -2
  15. package/chunk-52hxv18g.js +6 -0
  16. package/chunk-5ezzc1h2.js +688 -0
  17. package/{chunk-74skmg76.js → chunk-5wv5a52y.js} +1 -1
  18. package/chunk-6nzqhfqq.js +5 -0
  19. package/{chunk-fgw3hp2v.js → chunk-6zz9kfbd.js} +1 -1
  20. package/chunk-788t8y5x.js +2 -0
  21. package/chunk-7bvvbsqy.js +26 -0
  22. package/{chunk-cep3ktr3.js → chunk-7k7dpj5y.js} +1 -1
  23. package/{chunk-hs2j6s1v.js → chunk-7njj1qmq.js} +8 -31
  24. package/{chunk-8ssr8a8w.js → chunk-80fjfyha.js} +3 -6
  25. package/chunk-94vx1yb0.js +3 -0
  26. package/{chunk-n5007jcz.js → chunk-9f22qnge.js} +1 -1
  27. package/chunk-9g4tr0r6.js +2 -0
  28. package/{chunk-1gx45384.js → chunk-9nhw49vv.js} +7 -8
  29. package/{chunk-2z0k59hz.js → chunk-as08hzp3.js} +1 -1
  30. package/chunk-bhx8k09w.js +3 -0
  31. package/chunk-bpeezw7w.js +3 -0
  32. package/{chunk-b2ebm1t3.js → chunk-bvmtq0vn.js} +2 -2
  33. package/{chunk-w5rzk6ms.js → chunk-c4fym47a.js} +64 -20
  34. package/{chunk-d385435m.js → chunk-c6hywdvq.js} +1 -1
  35. package/{chunk-jnsfgtn9.js → chunk-cvn689d5.js} +1 -1
  36. package/chunk-cxzkkn12.js +2 -0
  37. package/{chunk-56vqqr8s.js → chunk-d9p6s05n.js} +1 -1
  38. package/{chunk-5js0qw32.js → chunk-dsks52m7.js} +1 -1
  39. package/{chunk-b7j86xq7.js → chunk-hfzg98c8.js} +1 -1
  40. package/{chunk-7e39xe21.js → chunk-js6mz7h1.js} +1 -1
  41. package/chunk-jx11jvq8.js +7 -0
  42. package/{chunk-2vx420g2.js → chunk-k6n249vb.js} +2 -2
  43. package/chunk-k7sehkm8.js +3 -0
  44. package/{chunk-k784090q.js → chunk-k9219kmj.js} +1 -1
  45. package/{chunk-65wb0g7d.js → chunk-kz4423th.js} +1 -1
  46. package/{chunk-g02nd9hn.js → chunk-m3czg1tt.js} +1 -1
  47. package/chunk-maz6z7tz.js +5 -0
  48. package/{chunk-rksq3w72.js → chunk-n9kcxaj7.js} +2 -2
  49. package/chunk-n9t36h0q.js +2 -0
  50. package/chunk-nr3ej3qf.js +5 -0
  51. package/{chunk-bk8b7f9a.js → chunk-nte0t7v3.js} +4 -3
  52. package/{chunk-kxk5x7g6.js → chunk-nycs0z7h.js} +1 -1
  53. package/{chunk-79ykzywe.js → chunk-pjtg3wnm.js} +1 -1
  54. package/chunk-qdnb2t6a.js +3 -0
  55. package/chunk-qgwhd4n6.js +86 -0
  56. package/chunk-sn9vg42q.js +2 -0
  57. package/{chunk-7p7ha0qk.js → chunk-t5bb30zy.js} +1 -1
  58. package/chunk-tbmkq7wy.js +6 -0
  59. package/chunk-tc4mzzfw.js +2 -0
  60. package/chunk-td5z2sm4.js +6 -0
  61. package/chunk-wa6qamwh.js +3 -0
  62. package/chunk-wcqqx6tz.js +2 -0
  63. package/chunk-wzngjjeb.js +10 -0
  64. package/chunk-xyfed1j0.js +2 -0
  65. package/chunk-y5r2w2z3.js +2 -0
  66. package/chunk-yeh9gb5w.js +3 -0
  67. package/cli.js +1 -1
  68. package/launcher.cjs +1 -1
  69. package/package.json +3 -3
  70. package/pkgs/helpers/src/descriptors.ts +7 -1
  71. package/pkgs/provider-antd/src/index.ts +1 -0
  72. package/pkgs/provider-chakra/src/index.ts +1 -0
  73. package/pkgs/provider-mui/src/index.ts +1 -0
  74. package/pkgs/provider-none/src/index.ts +42 -1
  75. package/pkgs/provider-none/src/intro.ts +2 -2
  76. package/pkgs/schema/src/config.ts +27 -1
  77. package/pkgs/schema/src/extension.ts +26 -0
  78. package/pkgs/schema/src/index.ts +18 -0
  79. package/pkgs/schema/src/migrate.ts +57 -4
  80. package/pkgs/schema/src/node.ts +99 -0
  81. package/pkgs/schema/src/repo.ts +98 -16
  82. package/pkgs/schema/src/screen.ts +7 -0
  83. package/pkgs/schema/src/svg-sanitize.ts +472 -59
  84. package/pkgs/shadcn-snapshot/dist/manifest.json +9 -1
  85. package/skills/velloo-setup/SKILL.md +70 -48
  86. package/canvas/assets/index-BCvDZiBo.css +0 -2
  87. package/canvas/assets/index-BcBJ11d2.js +0 -28
  88. package/canvas/assets/lucide-all-BdEyryfF.js +0 -1
  89. package/chunk-1bywxgc5.js +0 -4
  90. package/chunk-1y50g9vp.js +0 -2
  91. package/chunk-1yhc252b.js +0 -3
  92. package/chunk-2mv65qxs.js +0 -5
  93. package/chunk-329e3phg.js +0 -451
  94. package/chunk-40657ggd.js +0 -10
  95. package/chunk-582y60bv.js +0 -2
  96. package/chunk-5x173xay.js +0 -2
  97. package/chunk-75wbh438.js +0 -2
  98. package/chunk-7dggmqwq.js +0 -53
  99. package/chunk-946pcnt5.js +0 -5
  100. package/chunk-9vg3yafz.js +0 -3
  101. package/chunk-aapybh30.js +0 -6
  102. package/chunk-bjnhhsak.js +0 -2
  103. package/chunk-dt03awr1.js +0 -2
  104. package/chunk-erwfk47h.js +0 -3
  105. package/chunk-mq4znqv2.js +0 -2
  106. package/chunk-nfr3q7mg.js +0 -5
  107. package/chunk-nsqs1bqf.js +0 -2
  108. package/chunk-pphgrsxa.js +0 -2
  109. package/chunk-qpvj6kzq.js +0 -6
  110. package/chunk-qwv7xkms.js +0 -2
  111. package/chunk-tmtzxcs5.js +0 -2
  112. package/chunk-xr6f94rj.js +0 -2
  113. package/chunk-y0zxzefg.js +0 -5
  114. package/chunk-zf3xc1wz.js +0 -2
@@ -1,9 +1,9 @@
1
1
  // @bun
2
- import{isCancel,confirm,log,cancel,note,spinner,select,text,existingDesignFolder,isDesignFolderSync,isEmptyOrMissingSync,hasDesignConfig,resolveDesignFolder}from"./chunk-8ssr8a8w.js";import{BoardSchema,CURRENT_SCHEMA_VERSION,schemaVersionOf,planMigration,ConfigSchema,isComponentNode,ScreenSchema,SnippetSchema,ThemeSchema}from"./chunk-bk8b7f9a.js";import{parseThemeCss,writeJsonAtomic,writeText,managedDesignPath,managedDesignId,localDesignOf,writeLocalDesign,removeLocalDesign,resolveProjectPath,readRepoFeedback,writeRepoFeedback,writeFeedbackContactOk,loadDesignFolder,hostAppRootFrom,derivePalette,topUpTokens}from"./chunk-329e3phg.js";import{CHROMIUM_INSTALL_CMD,chromiumExecutable}from"./chunk-w5rzk6ms.js";import{snapshotVersion2}from"./chunk-jnsfgtn9.js";import{PROJECT_AGENT_IDS,resolveProjectRoot,manualSetupText,askAgentWiring,globallyWiredAgents,connect}from"./chunk-1gx45384.js";import{TOOL_VERSION}from"./chunk-65wb0g7d.js";import{fail}from"./chunk-s23gtejf.js";import{daemonRoot,ensureDaemon,stopDaemon}from"./chunk-k784090q.js";import{installedVellooBin,updateStatus,upgradeInstalledVelloo}from"./chunk-cep3ktr3.js";import{loadCredential,saveCredential}from"./chunk-b7j86xq7.js";import{BROWSER_PROMPT_DETAIL,BROWSER_PROMPT_SIZE,installChromiumInteractive}from"./chunk-k6ferbam.js";import{detectHost,findComponentsDir}from"./chunk-56vqqr8s.js";import{detectShell,completionsInstalled,installCompletions}from"./chunk-7dggmqwq.js";import{copyToClipboard}from"./chunk-vbk1qhdz.js";import{upgradeFolder}from"./chunk-y0zxzefg.js";import{verifyCredential,performDeviceLogin}from"./chunk-fgw3hp2v.js";import{openUrl}from"./chunk-hggap8fq.js";import{findManifest,findProjects,pickProject,checkoutRoot,isWithin,findGitRoot,registerProject,registerLocalDesign}from"./chunk-1bywxgc5.js";import{defaultCloudUrl}from"./chunk-2z0k59hz.js";import{require_picocolors}from"./chunk-jrsknzjt.js";import{__toESM,defineCommand}from"./chunk-2smsg2ct.js";import{noLibVersion}from"./chunk-cxe6jjwj.js";import{MUI_VERSION}from"./chunk-mzhdrawd.js";import{ANTD_VERSION}from"./chunk-0t68szgr.js";import{CHAKRA_VERSION}from"./chunk-nwx5700b.js";import{randomUUID as randomUUID2}from"crypto";import{dirname as dirname6,relative as relative11,resolve as resolve12}from"path";var import_picocolors12=__toESM(require_picocolors(),1);import{existsSync as existsSync2}from"fs";import{readFile as readFile4}from"fs/promises";import{join as join6,relative as relative3,resolve as resolve2,sep}from"path";import{readdir as readdir3}from"fs/promises";import{dirname as dirname3,join as join5,relative as relative2,resolve}from"path";import{readFile as readFile3}from"fs/promises";import{basename as basename3,dirname as dirname2,join as join4,relative}from"path";import{readFile}from"fs/promises";import{basename,join as join2}from"path";function titleCaseFromSegment(segment){if(segment==="")return"Index";if(segment==="index")return"Index";let cleaned=segment.replace(/^[_[]+|[\]]+$/g,"").replace(/[-_]+/g," ");if(!cleaned)return segment;return cleaned.charAt(0).toUpperCase()+cleaned.slice(1)}function idFromRoutePath(routePath){if(routePath==="/"||routePath==="")return"index";return routePath.replace(/^\//,"").replace(/\//g,"-").replace(/[[\]()]/g,"").replace(/^_/,"").replace(/[^a-zA-Z0-9-]/g,"-").replace(/-+/g,"-").replace(/^-|-$/g,"").toLowerCase()||"index"}function nameFromRoutePath(routePath){if(routePath==="/"||routePath==="")return"Home";return routePath.replace(/^\//,"").split("/").map(titleCaseFromSegment).join(" / ")}import{readdir,stat}from"fs/promises";import{join}from"path";async function*walkFiles(root){let entries;try{entries=await readdir(root)}catch{return}entries.sort((a,b)=>a.localeCompare(b));for(let name of entries){if(name.startsWith("."))continue;if(name==="node_modules"||name==="dist"||name===".next")continue;let full=join(root,name),s=await stat(full).catch(()=>null);if(!s)continue;if(s.isDirectory())yield*walkFiles(full);else if(s.isFile())yield full}}async function dirExists(path){return(await stat(path).catch(()=>null))?.isDirectory()??!1}var MAX_FILES=400,MAX_FILE_BYTES=262144,MAX_ROUTES=200;function isNoiseFile(file){let base=basename(file);if(/\.(test|spec|stories)\.[jt]sx?$/.test(base))return!0;return/\/(__tests__|__mocks__|mocks|stories|e2e|tests)\//.test(file)}function looksLikeRouteConfig(content){if(/\bcreate(Browser|Hash|Memory)Router\s*\(/.test(content))return!0;if(/\bcreateRoutesFromElements\s*\(/.test(content))return!0;if(/<Route[\s/>]/.test(content))return!0;return/\bpath\s*:\s*["'`]/.test(content)&&/\b(element|Component)\s*:/.test(content)}function atPropertyPosition(src,i){for(let j=i-1;j>=0;j--){let c=src[j];if(c===" "||c==="\t"||c===`
2
+ import{snapshotVersion2}from"./chunk-cvn689d5.js";import{BoardSchema,CURRENT_SCHEMA_VERSION,ConfigSchema,isComponentNode,ScreenSchema,SnippetSchema,ThemeSchema}from"./chunk-nte0t7v3.js";import{parseThemeCss,writeJsonAtomic,writeText,derivePalette}from"./chunk-5ezzc1h2.js";import{CHROMIUM_INSTALL_CMD,chromiumExecutable}from"./chunk-c4fym47a.js";import{TOOL_VERSION}from"./chunk-kz4423th.js";import{isCancel,confirm}from"./chunk-80fjfyha.js";import{BROWSER_PROMPT_DETAIL,BROWSER_PROMPT_SIZE,installChromiumInteractive}from"./chunk-2fgfex9b.js";import{detectShell,completionsInstalled,installCompletions}from"./chunk-qgwhd4n6.js";import{require_picocolors}from"./chunk-jrsknzjt.js";import{__toESM}from"./chunk-2smsg2ct.js";import{noLibVersion}from"./chunk-cxe6jjwj.js";import{MUI_VERSION}from"./chunk-mzhdrawd.js";import{ANTD_VERSION}from"./chunk-0t68szgr.js";import{CHAKRA_VERSION}from"./chunk-nwx5700b.js";import{readdir,stat}from"fs/promises";import{join}from"path";async function*walkFiles(root){let entries;try{entries=await readdir(root)}catch{return}entries.sort((a,b)=>a.localeCompare(b));for(let name of entries){if(name.startsWith("."))continue;if(name==="node_modules"||name==="dist"||name===".next")continue;let full=join(root,name),s=await stat(full).catch(()=>null);if(!s)continue;if(s.isDirectory())yield*walkFiles(full);else if(s.isFile())yield full}}async function dirExists(path){return(await stat(path).catch(()=>null))?.isDirectory()??!1}import{relative as relative3,resolve as resolve2,sep as sep3}from"path";import{readdir as readdir3}from"fs/promises";import{homedir}from"os";import{delimiter,dirname as dirname3,join as join5,relative as relative2,resolve,sep as sep2}from"path";import{readFile as readFile3,stat as stat2}from"fs/promises";import{basename as basename3,dirname as dirname2,join as join4,relative,sep}from"path";import{readFile}from"fs/promises";import{basename,join as join2}from"path";function titleCaseFromSegment(segment){if(segment==="")return"Index";if(segment==="index")return"Index";let cleaned=segment.replace(/^[_[]+|[\]]+$/g,"").replace(/[-_]+/g," ");if(!cleaned)return segment;return cleaned.charAt(0).toUpperCase()+cleaned.slice(1)}function idFromRoutePath(routePath){if(routePath==="/"||routePath==="")return"index";return routePath.replace(/^\//,"").replace(/\//g,"-").replace(/[[\]()]/g,"").replace(/^_/,"").replace(/[^a-zA-Z0-9-]/g,"-").replace(/-+/g,"-").replace(/^-|-$/g,"").toLowerCase()||"index"}function nameFromRoutePath(routePath){if(routePath==="/"||routePath==="")return"Home";return routePath.replace(/^\//,"").split("/").map(titleCaseFromSegment).join(" / ")}var MAX_FILES=400,MAX_FILE_BYTES=262144,MAX_ROUTES=200;function isNoiseFile(file){let base=basename(file);if(/\.(test|spec|stories)\.[jt]sx?$/.test(base))return!0;return/\/(__tests__|__mocks__|mocks|stories|e2e|tests)\//.test(file)}function looksLikeRouteConfig(content){if(/\bcreate(Browser|Hash|Memory)Router\s*\(/.test(content))return!0;if(/\bcreateRoutesFromElements\s*\(/.test(content))return!0;if(/<Route[\s/>]/.test(content))return!0;return/\bpath\s*:\s*["'`]/.test(content)&&/\b(element|Component)\s*:/.test(content)}function atPropertyPosition(src,i){for(let j=i-1;j>=0;j--){let c=src[j];if(c===" "||c==="\t"||c===`
3
3
  `||c==="\r")continue;return c==="{"||c===","}return!0}function parseObjectRoutes(src){let roots=[],stack=[],i=0,n=src.length;while(i<n){let c=src[i];if(c==='"'||c==="'"||c==="`"){let quote=c;i++;while(i<n&&src[i]!==quote)i+=src[i]==="\\"?2:1;i++;continue}if(c==="/"&&src[i+1]==="/"){let nl=src.indexOf(`
4
4
  `,i);i=nl===-1?n:nl+1;continue}if(c==="/"&&src[i+1]==="*"){let end=src.indexOf("*/",i+2);i=end===-1?n:end+2;continue}if(c==="{"){stack.push({children:[]}),i++;continue}if(c==="}"){let node=stack.pop();if(node){let parent=stack[stack.length-1];if(parent)parent.children.push(node);else roots.push(node)}i++;continue}let top=stack[stack.length-1];if(top&&c&&/[A-Za-z]/.test(c)&&atPropertyPosition(src,i)){let rest=src.slice(i,i+200),path=rest.match(/^path\s*:\s*(?:"([^"]*)"|'([^']*)'|`([^`]*)`)/),pathValue=path?path[1]??path[2]??path[3]:void 0;if(path&&pathValue!==void 0){top.path=pathValue,i+=path[0].length;continue}let index=rest.match(/^index\s*:\s*true/);if(index){top.index=!0,i+=index[0].length;continue}let element=rest.match(/^(?:element|Component)\s*:\s*\(?\s*<?\s*([A-Z][\w.]*)/);if(element?.[1]!==void 0){top.element=element[1],i+=element[0].length;continue}}i++}return roots}function parseJsxRoutes(src){let roots=[],stack=[],open=/<Route\b/g,close=/<\/Route\s*>/g,tags=[];for(let m of src.matchAll(open)){let start=m.index,i=start+m[0].length,depth=0,attrs="";while(i<src.length){let c=src[i];if(c==='"'||c==="'"){let q=c,from=i;i++;while(i<src.length&&src[i]!==q)i+=src[i]==="\\"?2:1;i++,attrs+=src.slice(from,i);continue}if(c==="{")depth++;if(c==="}")depth--;if(c===">"&&depth===0)break;attrs+=c,i++}let selfClosing=attrs.trimEnd().endsWith("/"),node={children:[]},path=attrs.match(/\bpath\s*=\s*(?:"([^"]*)"|'([^']*)'|\{\s*(?:"([^"]*)"|'([^']*)')\s*\})/),pathAttr=path?path[1]??path[2]??path[3]??path[4]:void 0;if(pathAttr!==void 0)node.path=pathAttr;if(/\bindex\b(?!\s*=\s*\{?\s*false)/.test(attrs))node.index=!0;let element=attrs.match(/\b(?:element|Component)\s*=\s*\{?\s*<?\s*([A-Z][\w.]*)/);if(element?.[1]!==void 0)node.element=element[1];tags.push({at:start,kind:"open",node,selfClosing})}for(let m of src.matchAll(close))tags.push({at:m.index,kind:"close"});tags.sort((a,b)=>a.at-b.at);for(let tag of tags)if(tag.kind==="open"&&tag.node){let parent=stack[stack.length-1];if(parent)parent.children.push(tag.node);else roots.push(tag.node);if(!tag.selfClosing)stack.push(tag.node)}else if(tag.kind==="close")stack.pop();return roots}function normalizeParams(path){return path.replace(/:(\w+)\??/g,"[$1]").replace(/\?/g,"")}function joinPaths(base,path){if(path.startsWith("/"))return path;return`${base==="/"?"":base}/${path}`.replace(/\/+/g,"/").replace(/\/$/,"")||"/"}function collectPaths(nodes,base,out){for(let node of nodes){if(out.size>=MAX_ROUTES)return;let resolved=node.path?joinPaths(base,normalizeParams(node.path)):base;if(node.children.length>0){if(collectPaths(node.children,resolved,out),node.path&&node.element&&!node.children.some((c)=>c.index))addPath(node,resolved,out);continue}if(node.index)addPath(node,base,out);else if(node.path)addPath(node,resolved,out)}}function addPath(node,routePath,out){if(node.element==="Navigate")return;if(routePath.includes("*"))return;out.set(routePath,!0)}async function scanReactRouter(appRoot){let srcDir=join2(appRoot,"src"),root=await dirExists(srcDir)?srcDir:appRoot,paths=new Map,sources=new Map,seen=0;for await(let file of walkFiles(root)){if(seen>=MAX_FILES||paths.size>=MAX_ROUTES)break;if(!/\.[jt]sx?$/.test(file)||isNoiseFile(file))continue;seen++;let content=await readFile(file,"utf8").catch(()=>null);if(!content||content.length>MAX_FILE_BYTES||!looksLikeRouteConfig(content))continue;let before=paths.size;if(collectPaths(parseObjectRoutes(content),"/",paths),collectPaths(parseJsxRoutes(content),"/",paths),paths.size>before){for(let p of paths.keys())if(!sources.has(p))sources.set(p,file)}}if(paths.size===0)return null;let routes=[...paths.keys()].map((routePath)=>({id:idFromRoutePath(routePath),name:nameFromRoutePath(routePath),routePath,sourceFile:sources.get(routePath)??root})),dedupedIds=new Set,deduped=routes.filter((r)=>{if(dedupedIds.has(r.id))return!1;return dedupedIds.add(r.id),!0});return deduped.sort((a,b)=>{if(a.id==="index")return-1;if(b.id==="index")return 1;return a.id.localeCompare(b.id)}),{framework:"react-router",routes:deduped,routesRoot:root}}import{existsSync}from"fs";import{readdir as readdir2,readFile as readFile2}from"fs/promises";import{basename as basename2,dirname,join as join3}from"path";var SKIP_DIRS=new Set(["node_modules","venv","env","__pycache__","migrations","site-packages","vendor","storage","tmp","log"]);async function collectFiles(root,match,maxDepth=5,maxFiles=500){let out=[];async function recurse(dir,depth){if(out.length>=maxFiles)return;let entries=await readdir2(dir,{withFileTypes:!0}).catch(()=>null);if(!entries)return;entries.sort((a,b)=>a.name.localeCompare(b.name));for(let entry of entries){if(out.length>=maxFiles)return;if(entry.name.startsWith("."))continue;if(entry.isDirectory()){if(SKIP_DIRS.has(entry.name)||depth>=maxDepth)continue;await recurse(join3(dir,entry.name),depth+1)}else if(entry.isFile()&&match(entry.name))out.push(join3(dir,entry.name))}}return await recurse(root,0),out}function normalizeParams2(path){return path.replace(/<(?:\w+:)?(\w+)>/g,"[$1]").replace(/\{(\w+)\??\}/g,"[$1]")}function normalizePath(raw){let trimmed=(raw.startsWith("/")?raw:`/${raw}`).replace(/\/+$/,"");return trimmed===""?"/":trimmed}function isPageRoute(routePath){let first=routePath.split("/").filter(Boolean)[0]??"";return first!=="api"&&first!=="admin"&&first!=="static"&&first!=="media"}function toRoute(routePath,sourceFile){return{id:idFromRoutePath(routePath),name:nameFromRoutePath(routePath),routePath,sourceFile}}function dedupeAndSort(routes){let seen=new Set,out=[];for(let r of routes){if(seen.has(r.id))continue;seen.add(r.id),out.push(r)}return out.sort((a,b)=>{if(a.id==="index")return-1;if(b.id==="index")return 1;return a.id.localeCompare(b.id)}),out}async function scanDjango(appRoot){let files=await collectFiles(appRoot,(n)=>n==="urls.py"),routes=[];for(let file of files){let content=await readFile2(file,"utf8").catch(()=>null);if(!content)continue;let pkgDir=dirname(file),prefix=existsSync(join3(pkgDir,"settings.py"))||pkgDir===appRoot?"":`/${basename2(pkgDir)}`,entry=/\b(?:path|re_path|url)\(\s*r?["']([^"']*)["']/g;for(let m of content.matchAll(entry)){let rest=content.slice(m.index,content.indexOf(`
5
5
  `,m.index));if(rest.includes("include(")||rest.includes("admin.site.urls"))continue;let raw=m[1]??"";if(raw=raw.replace(/^\^/,"").replace(/\$$/,""),raw=raw.replace(/\(\?P<(\w+)>[^)]*\)/g,"[$1]"),raw=normalizeParams2(raw),/[\\^$+*?()|]/.test(raw))continue;let routePath=normalizePath(`${prefix}/${raw}`.replace(/\/+/g,"/"));if(!isPageRoute(routePath))continue;routes.push(toRoute(routePath,file))}}return dedupeAndSort(routes)}async function scanPythonDecorators(appRoot){let files=await collectFiles(appRoot,(n)=>n.endsWith(".py")),routes=[];for(let file of files){let content=await readFile2(file,"utf8").catch(()=>null);if(!content)continue;let entry=/@\w+\.(route|get)\(\s*["']([^"']+)["']([^)\n]*)/g;for(let m of content.matchAll(entry)){let[,kind,raw,rest]=m;if(kind==="route"&&rest&&/methods\s*=/.test(rest)&&!/GET/.test(rest))continue;let routePath=normalizePath(normalizeParams2(raw??""));if(!isPageRoute(routePath))continue;routes.push(toRoute(routePath,file))}}return dedupeAndSort(routes)}async function scanRails(routesRb){let content=await readFile2(routesRb,"utf8").catch(()=>null);if(!content)return[];let routes=[];for(let line of content.split(`
6
- `)){if(/^\s*root\b/.test(line)){routes.push(toRoute("/",routesRb));continue}let get=line.match(/^\s*get\s+["']([^"']+)["']/);if(get?.[1]){let routePath=normalizePath(get[1].replace(/:(\w+)/g,"[$1]").replace(/\*\w+/g,""));if(isPageRoute(routePath))routes.push(toRoute(routePath,routesRb));continue}let res=line.match(/^\s*(resources|resource)\s+:(\w+)/);if(res?.[2]){let base=normalizePath(res[2]);if(!isPageRoute(base))continue;if(routes.push(toRoute(base,routesRb)),res[1]==="resources")routes.push(toRoute(`${base}/[id]`,routesRb))}}return dedupeAndSort(routes)}async function scanLaravel(webPhp){let content=await readFile2(webPhp,"utf8").catch(()=>null);if(!content)return[];let routes=[],entry=/Route::(?:get|view)\(\s*["']([^"']+)["']/g;for(let m of content.matchAll(entry)){let routePath=normalizePath(normalizeParams2(m[1]??""));if(!isPageRoute(routePath))continue;routes.push(toRoute(routePath,webPhp))}return dedupeAndSort(routes)}async function pythonDepDeclared(appRoot,pkg){let manifests=["requirements.txt","requirements-dev.txt","pyproject.toml","Pipfile"];for(let name of manifests){let content=await readFile2(join3(appRoot,name),"utf8").catch(()=>null);if(content&&pkg.test(content))return!0}return!1}async function scanServerRoutes(appRoot){if(existsSync(join3(appRoot,"manage.py")))return{framework:"django",routes:await scanDjango(appRoot),routesRoot:appRoot};let routesRb=join3(appRoot,"config","routes.rb");if(existsSync(routesRb))return{framework:"rails",routes:await scanRails(routesRb),routesRoot:appRoot};let webPhp=join3(appRoot,"routes","web.php");if(existsSync(join3(appRoot,"artisan"))&&existsSync(webPhp))return{framework:"laravel",routes:await scanLaravel(webPhp),routesRoot:appRoot};if(await pythonDepDeclared(appRoot,/\b(flask|fastapi)\b/i))return{framework:"flask",routes:await scanPythonDecorators(appRoot),routesRoot:appRoot};return null}var PAGE_EXTS=new Set([".tsx",".ts",".jsx",".js"]);function hasExt(file){let dot=file.lastIndexOf(".");if(dot===-1)return!1;return PAGE_EXTS.has(file.slice(dot))}function stripExt(file){let dot=file.lastIndexOf(".");return dot===-1?file:file.slice(0,dot)}async function scanNextApp(appDir){let out=[];for await(let file of walkFiles(appDir)){let base=basename3(file);if(stripExt(base)!=="page"||!hasExt(base))continue;let routePath=`/${relative(appDir,dirname2(file)).split("/").filter((s)=>!s.startsWith("(")).join("/")}`.replace(/\/$/,"")||"/",id=idFromRoutePath(routePath);out.push({id,name:nameFromRoutePath(routePath),routePath,sourceFile:file})}return dedupe(out)}async function scanNextPages(pagesDir){let out=[];for await(let file of walkFiles(pagesDir)){if(!hasExt(file))continue;let base=basename3(file);if(stripExt(base).startsWith("_"))continue;let rel=relative(pagesDir,file);if(rel.startsWith("api/")||rel==="api")continue;let segments=rel.split("/"),last=stripExt(segments.pop()??""),path=last==="index"?segments:[...segments,last],routePath=path.length===0?"/":`/${path.join("/")}`;out.push({id:idFromRoutePath(routePath),name:nameFromRoutePath(routePath),routePath,sourceFile:file})}return dedupe(out)}async function scanGenericPagesDir(dir){let out=[];for await(let file of walkFiles(dir)){if(!hasExt(file)&&!file.endsWith(".astro")&&!file.endsWith(".vue")&&!file.endsWith(".svelte"))continue;if(basename3(file).startsWith("_"))continue;let segments=relative(dir,file).split("/"),last=stripExt(segments.pop()??""),path=last==="index"?segments:[...segments,last],routePath=path.length===0?"/":`/${path.join("/")}`;out.push({id:idFromRoutePath(routePath),name:nameFromRoutePath(routePath),routePath,sourceFile:file})}return dedupe(out)}async function scanSvelteKit(dir){let out=[];for await(let file of walkFiles(dir)){if(basename3(file)!=="+page.svelte")continue;let rel=relative(dir,dirname2(file)),segments=rel===""?[]:rel.split("/").filter((s)=>!/^\(.*\)$/.test(s)),routePath=segments.length===0?"/":`/${segments.join("/")}`;out.push({id:idFromRoutePath(routePath),name:nameFromRoutePath(routePath),routePath,sourceFile:file})}return dedupe(out)}function tanstackSegment(seg){if(seg==="$")return"[splat]";if(seg.startsWith("$"))return`[${seg.slice(1)}]`;return seg}async function scanTanstackRouter(dir){let out=[];for await(let file of walkFiles(dir)){if(!hasExt(file))continue;let stem=stripExt(relative(dir,file));if(stem.endsWith(".lazy"))stem=stem.slice(0,-5);if(stem==="routeTree"||stem.endsWith(".gen"))continue;let raw=stem.split(/[/.]/).filter((s)=>s.length>0),leaf=raw[raw.length-1];if(!leaf)continue;if(leaf==="__root"||leaf==="route"||leaf.startsWith("_"))continue;if(raw.some((s)=>s.startsWith("-")))continue;let segments=[];for(let seg of raw){if(seg==="index"||seg==="route")continue;if(seg.startsWith("_"))continue;if(/^\(.*\)$/.test(seg))continue;segments.push(tanstackSegment(seg))}let routePath=segments.length===0?"/":`/${segments.join("/")}`;out.push({id:idFromRoutePath(routePath),name:nameFromRoutePath(routePath),routePath,sourceFile:file})}return dedupe(out)}async function tanstackRoutesDir(appRoot){try{let cfg=JSON.parse(await readFile3(join4(appRoot,"tsr.config.json"),"utf8"));if(typeof cfg.routesDirectory==="string")return join4(appRoot,cfg.routesDirectory)}catch{}return null}function dedupe(routes){let seen=new Set,out=[];for(let r of routes){if(seen.has(r.id))continue;seen.add(r.id),out.push(r)}return out.sort((a,b)=>{if(a.id==="index")return-1;if(b.id==="index")return 1;return a.id.localeCompare(b.id)}),out}async function readPackageJson(appRoot){try{let raw=await readFile3(join4(appRoot,"package.json"),"utf8");return JSON.parse(raw)}catch{return null}}async function detectFramework(appRoot){let pkg=await readPackageJson(appRoot),deps={...pkg?.dependencies??{},...pkg?.devDependencies??{}};if("next"in deps){if(await dirExists(join4(appRoot,"app")))return"next-app";if(await dirExists(join4(appRoot,"src","app")))return"next-app";if(await dirExists(join4(appRoot,"pages")))return"next-pages";if(await dirExists(join4(appRoot,"src","pages")))return"next-pages";return"next-app"}if("astro"in deps)return"astro";if("@sveltejs/kit"in deps)return"sveltekit";if("nuxt"in deps)return"nuxt";if("@tanstack/react-router"in deps||"@tanstack/react-start"in deps||"@tanstack/router-plugin"in deps)return"tanstack-router";if("react-router-dom"in deps||"react-router"in deps)return"react-router";if("vite"in deps)return"vite";return"unknown"}async function scanAppRoutes(appRoot){let framework=await detectFramework(appRoot);if(framework==="next-app"){let candidates=[join4(appRoot,"src","app"),join4(appRoot,"app")];for(let dir of candidates)if(await dirExists(dir))return{framework,routes:await scanNextApp(dir),routesRoot:dir}}if(framework==="next-pages"){let candidates=[join4(appRoot,"src","pages"),join4(appRoot,"pages")];for(let dir of candidates)if(await dirExists(dir))return{framework,routes:await scanNextPages(dir),routesRoot:dir}}if(framework==="astro"){let candidates=[join4(appRoot,"src","pages"),join4(appRoot,"pages")];for(let dir of candidates)if(await dirExists(dir))return{framework,routes:await scanGenericPagesDir(dir),routesRoot:dir}}if(framework==="sveltekit"){let dir=join4(appRoot,"src","routes");if(await dirExists(dir))return{framework,routes:await scanSvelteKit(dir),routesRoot:dir}}if(framework==="nuxt"){let candidates=[join4(appRoot,"app","pages"),join4(appRoot,"src","pages"),join4(appRoot,"pages")];for(let dir of candidates)if(await dirExists(dir))return{framework,routes:await scanGenericPagesDir(dir),routesRoot:dir}}if(framework==="tanstack-router"){let candidates=[await tanstackRoutesDir(appRoot),join4(appRoot,"src","routes"),join4(appRoot,"routes")];for(let dir of candidates)if(dir&&await dirExists(dir))return{framework,routes:await scanTanstackRouter(dir),routesRoot:dir}}if(framework==="react-router"){let result=await scanReactRouter(appRoot);if(result&&result.routes.length>0)return result}for(let dir of[join4(appRoot,"src","routes"),join4(appRoot,"src","pages"),join4(appRoot,"src","views"),join4(appRoot,"pages")])if(await dirExists(dir))return{framework:framework==="unknown"?"unknown":framework,routes:await scanGenericPagesDir(dir),routesRoot:dir};let server=await scanServerRoutes(appRoot);if(server)return server;return{framework,routes:[],routesRoot:appRoot}}var UI_DEPS=["react","next","astro","@sveltejs/kit","svelte","nuxt","vue"];async function looksLikeUiApp(appRoot){let pkg=await readPackageJson(appRoot);if(!pkg)return!1;let deps={...pkg.dependencies??{},...pkg.devDependencies??{}};return UI_DEPS.some((d)=>(d in deps))}var PREFERRED_DIRS=["frontend","web","webapp","client","ui","app","www","site"],SKIP_DIRS2=new Set(["node_modules","dist","build",".next",".turbo","out"]);function rank(rel){let segments=rel.split("/"),preferred=segments.reduce((best,seg)=>{let i=PREFERRED_DIRS.indexOf(seg.toLowerCase());return i===-1?best:Math.min(best,i)},PREFERRED_DIRS.length);return segments.length*100+preferred}async function gitPackageJsonDirs(appRoot){try{let proc=Bun.spawn(["git","-C",appRoot,"ls-files","--cached","--others","--exclude-standard","-z","--","package.json","*/package.json"],{stdout:"pipe",stderr:"ignore"}),out=await new Response(proc.stdout).text();if(await proc.exited!==0)return null;return out.split("\x00").filter((p)=>p.endsWith("package.json")&&!p.includes("node_modules/")).map((p)=>resolve(appRoot,dirname3(p)))}catch{return null}}async function walkPackageJsonDirs(root,maxDepth){let out=[];async function recurse(dir,depth){let entries=await readdir3(dir,{withFileTypes:!0}).catch(()=>null);if(!entries)return;if(entries.some((e)=>e.isFile()&&e.name==="package.json"))out.push(dir);if(depth>=maxDepth)return;for(let entry of entries){if(!entry.isDirectory()||entry.name.startsWith(".")||SKIP_DIRS2.has(entry.name))continue;await recurse(join5(dir,entry.name),depth+1)}}return await recurse(root,0),out}async function discoverScanRoots(appRoot){let out=[];if(await looksLikeUiApp(appRoot))out.push({dir:appRoot,rel:""});let dirs=await gitPackageJsonDirs(appRoot)??await walkPackageJsonDirs(appRoot,5),nested=[];for(let dir of new Set(dirs)){if(dir===appRoot)continue;if(await looksLikeUiApp(dir))nested.push({dir,rel:relative2(appRoot,dir)})}return nested.sort((a,b)=>rank(a.rel)-rank(b.rel)||a.rel.localeCompare(b.rel)),[...out,...nested]}function isSentinel(path){return path==="binary"||path.startsWith("~/")}function toPosix(path){return path.split(sep).join("/")||"."}function isUnder(parent,child){let rel=relative3(parent,child);return rel===""||!rel.startsWith("..")&&!/^(?:[\\/]|[A-Za-z]:)/.test(rel)}async function readConfig(folder){return ConfigSchema.parse(JSON.parse(await readFile4(join6(folder,".design","config.json"),"utf8")))}async function recordedAppRoot(designFolder){let folder=resolve2(designFolder),local=localDesignOf(folder);if(local){let path=resolve2(local.appRoot);return{path,kind:"local",localId:local.id,checkout:local.root,projectName:local.projectName,...appShape(path)}}let recorded=(await readConfig(folder)).hostApp?.root,path=recorded&&!isSentinel(recorded)?resolveProjectPath(folder,recorded):resolve2(folder,".."),found=await findManifest(folder).catch(()=>null),projectName=found?[...found.folders].find(([,p])=>resolve2(p)===folder)?.[0]:void 0;return{path,kind:"in-repo",...projectName?{projectName}:{},...found?{manifestPath:found.path}:{},...appShape(path)}}function appShape(path){let exists=existsSync2(path);return{exists,looksLikeApp:exists&&existsSync2(join6(path,"package.json"))}}async function planAppRootChange(designFolder,newRoot){let folder=resolve2(designFolder),current=await recordedAppRoot(folder),to=resolve2(newRoot),change={from:current.path,to,rewritten:[]};if(current.kind==="local"&&current.localId&&current.checkout&&current.projectName){if(!isUnder(current.checkout,to))throw Error(`An application root must live inside the design's checkout (${current.checkout}). ${to} is outside it.`);return change.local={id:current.localId,root:current.checkout,project:current.projectName},change}let config=await readConfig(folder),reanchor=(field,stored)=>{if(isSentinel(stored))return;let abs=resolveProjectPath(folder,stored);if(!isUnder(current.path,abs))return;let next=toPosix(relative3(folder,join6(to,relative3(current.path,abs))));if(next===stored)return;return change.rewritten.push({field,from:stored,to:next}),next};if(config.hostApp)reanchor("hostApp.root",config.hostApp.root);else change.rewritten.push({field:"hostApp.root",from:"(unset)",to:toPosix(relative3(folder,to))});for(let[name,app]of Object.entries(config.hostApps??{}))reanchor(`hostApps.${name}.root`,app.root);for(let[name,library]of Object.entries(config.libraries))if(library.source==="in-repo")reanchor(`libraries.${name}.componentsPath`,library.componentsPath);return change}async function applyAppRootChange(designFolder,change){let folder=resolve2(designFolder);if(change.local){await writeLocalDesign(change.local.id,{root:change.local.root,appRoot:change.to,projectName:change.local.project,...managedDesignId(folder)?{}:{designPath:folder}});return}let config=await readConfig(folder),patch=new Map(change.rewritten.map((r)=>[r.field,r.to])),hostRoot=patch.get("hostApp.root");if(hostRoot!==void 0)config.hostApp=config.hostApp?{...config.hostApp,root:hostRoot}:{root:hostRoot};for(let[name,app]of Object.entries(config.hostApps??{})){let next=patch.get(`hostApps.${name}.root`);if(next!==void 0)app.root=next}for(let[name,library]of Object.entries(config.libraries)){let next=patch.get(`libraries.${name}.componentsPath`);if(next!==void 0)library.componentsPath=next}await writeJsonAtomic(join6(folder,".design","config.json"),ConfigSchema.parse(config))}async function appRootCandidates(near){let start=resolve2(near),from=(await findManifest(start).catch(()=>null))?.dir??await findGitRoot(start)??start;return(await discoverScanRoots(from)).map((app)=>({dir:app.dir,rel:relative3(from,app.dir)||"."}))}async function appRootIsNotAnApp(appRoot){let abs=resolve2(appRoot);if(existsSync2(join6(abs,"package.json"))&&(await discoverScanRoots(abs))[0]?.dir===abs)return null;let candidates=(await appRootCandidates(abs)).filter((c)=>c.dir!==abs);return candidates.length>0?candidates:null}async function promptAppRootChoice(current,opts={}){let message=opts.message??"Which application is this design for?",currentHint=opts.currentHint??"recorded now",abs=resolve2(current),candidates=await appRootCandidates(abs),options=candidates.map((c)=>({value:c.dir,label:c.rel,...c.dir===abs?{hint:currentHint}:{}}));if(!candidates.some((c)=>c.dir===abs))options.push({value:abs,label:current,hint:currentHint});if(options.length<=1)return null;let chosen=await select({message,options});if(isCancel(chosen))return null;return chosen}import{createHash,randomUUID}from"crypto";import{existsSync as existsSync3,lstatSync,realpathSync}from"fs";import{cp,lstat,mkdir,readdir as readdir4,readFile as readFile5,rm}from"fs/promises";import{basename as basename4,dirname as dirname4,join as join7,relative as relative4,resolve as resolve3,sep as sep2}from"path";function physicalDestination(path){if(lstatSync(path,{throwIfNoEntry:!1}))return realpathSync(path);let parent=dirname4(path);return join7(physicalDestination(parent),relative4(parent,path))}var RUNTIME=[".design/cache",".velloo","node_modules"];async function rebaseDesignConfig(source,destination,appRoot,external){let config=ConfigSchema.parse(JSON.parse(await readFile5(join7(destination,".design/config.json"),"utf8"))),rebase=(path)=>{if(path==="binary"||path.startsWith("~/"))return path;let abs=resolveProjectPath(source,path),withinDesign=relative4(source,abs);if(withinDesign===""||withinDesign!==".."&&!withinDesign.startsWith(`..${sep2}`)&&!/^(?:[\\/]|[A-Za-z]:)/.test(withinDesign))return withinDesign.split(sep2).join("/")||".";return external?`project:${relative4(appRoot,abs).split(sep2).join("/")||"."}`:relative4(destination,abs).split(sep2).join("/")||"."};config.hostApp=config.hostApp?{...config.hostApp,root:rebase(config.hostApp.root)}:{root:rebase("..")};for(let app of Object.values(config.hostApps??{}))app.root=rebase(app.root);for(let library of Object.values(config.libraries))if(library.componentsPath)library.componentsPath=rebase(library.componentsPath);await writeJsonAtomic(join7(destination,".design/config.json"),config)}async function fingerprint(folder){let hash=createHash("sha256");async function walk(rel){if(rel===".git"||RUNTIME.some((p)=>rel===p||rel.startsWith(`${p}/`)))return;let path=join7(folder,rel),stat=await lstat(path);if(stat.isSymbolicLink())throw Error(`Cannot relocate symbolic link ${path}. Replace it with its actual design content first.`);if(stat.isDirectory())for(let name of(await readdir4(path)).sort())await walk(rel?`${rel}/${name}`:name);else if(stat.isFile())hash.update(rel).update("\x00").update(await readFile5(path));else throw Error(`Unsupported filesystem entry: ${path}`)}return await walk(""),hash.digest("hex")}async function planRelocation(source,cwd,to,external){if(Boolean(to)===external)throw Error("Choose exactly one destination: --external or --to <path>.");let projects=await findProjects(cwd),physicalSource=realpathSync(source),local=projects?.local.find((design)=>realOr(design.designRoot)===physicalSource),entries=[...projects?.repo?.folders??[]].filter(([,path])=>existsSync3(path)&&realpathSync(path)===physicalSource);if(!local&&entries.length!==1)throw Error("Run relocation from the checkout the design belongs to; the source must be one of its projects.");let repo=projects?.repo??null,root=local?.root??repo?.dir,name=local?.projectName??entries[0]?.[0],physicalRoot=realpathSync(root);if(physicalSource===physicalRoot)throw Error("Cannot relocate the application repository itself. Use a separate design directory.");if(external&&managedDesignId(source))throw Error("This design already lives in managed storage.");let destination=external?managedDesignPath(local?.id??randomUUID()):resolve3(cwd,to??""),physicalTarget=physicalDestination(destination),inRepo=!external&&isWithin(physicalRoot,physicalTarget);if(physicalTarget===physicalSource||physicalTarget.startsWith(physicalSource+sep2)||physicalSource.startsWith(physicalTarget+sep2))throw Error("Source and destination cannot contain each other.");if(existsSync3(destination))throw Error(`Destination is occupied: ${destination}. Choose a new path; nothing was changed.`);let manifestPath=repo?.path??join7(root,"velloo.json"),before=repo?await readFile5(repo.path,"utf8"):null,manifest;if(inRepo){let rel=relative4(physicalRoot,physicalTarget).split(sep2).join("/")||".";manifest={...repo?.manifest??{},projects:{...repo?.manifest.projects??{},[name]:rel}}}else if(repo&&name in repo.manifest.projects){let{[name]:_moved,...rest}=repo.manifest.projects,{defaultProject,...others}=repo.manifest;manifest=Object.keys(rest).length===0&&!others.feedback?null:{...others,projects:rest,...defaultProject&&defaultProject!==name?{defaultProject}:{}}}let config=ConfigSchema.parse(JSON.parse(await readFile5(join7(source,".design/config.json"),"utf8")));return{source,destination,root,appRoot:local?.appRoot??hostAppRootFrom(source,config.hostApp),projectName:name,sourceLocalId:local?.id,destinationLocal:inRepo?void 0:{id:local?.id??(external?basename4(destination):randomUUID()),...external?{}:{designPath:destination}},manifestPath,before,manifest}}function realOr(path){return existsSync3(path)?realpathSync(path):resolve3(path)}async function relocateDesign(plan){await stopDaemon(daemonRoot(plan.source));let original=await fingerprint(plan.source);await mkdir(dirname4(plan.destination),{recursive:!0}),await mkdir(plan.destination);let committed=!1;try{for(let entry of await readdir4(plan.source))await cp(join7(plan.source,entry),join7(plan.destination,entry),{recursive:!0,errorOnExist:!0,force:!1,filter:(path)=>!RUNTIME.some((p)=>{let rel=relative4(plan.source,path).split(sep2).join("/");return rel===p||rel.startsWith(`${p}/`)})});if(await fingerprint(plan.destination)!==original)throw Error("Copied content did not match the source.");if(await rebaseDesignConfig(plan.source,plan.destination,plan.appRoot,plan.destinationLocal!==void 0),await loadDesignFolder(plan.destination,{preferences:!1}),await fingerprint(plan.source)!==original)throw Error("The source changed during relocation. Close editors and retry.");if(await readFile5(plan.manifestPath,"utf8").catch(()=>null)!==plan.before)throw Error("The manifest changed during relocation. Review it and retry.");if(plan.destinationLocal){if(plan.sourceLocalId&&plan.sourceLocalId!==plan.destinationLocal.id)await removeLocalDesign(plan.sourceLocalId);await writeLocalDesign(plan.destinationLocal.id,{root:plan.root,appRoot:plan.appRoot,projectName:plan.projectName,...plan.destinationLocal.designPath?{designPath:plan.destinationLocal.designPath}:{}})}else if(plan.sourceLocalId)await removeLocalDesign(plan.sourceLocalId);if(plan.manifest===null)await rm(plan.manifestPath,{force:!0});else if(plan.manifest)await writeJsonAtomic(plan.manifestPath,plan.manifest);committed=!0}finally{if(!committed)await rm(plan.destination,{recursive:!0,force:!0})}try{await rm(plan.source,{recursive:!0})}catch(error){throw Error(`Relocation completed to ${plan.destination}, but the old copy remains at ${plan.source}. Remove it after checking the destination. ${error}`)}}import{relative as relative5,resolve as resolve4}from"path";function appSlug(rel){return rel.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-|-$/g,"")||"app"}function appPrefixes(rels){let shortOf=(rel)=>appSlug(rel.split("/").pop()??rel),counts=new Map;for(let rel of rels){let s=shortOf(rel);counts.set(s,(counts.get(s)??0)+1)}let out=new Map;for(let rel of rels){let short=shortOf(rel);out.set(rel,(counts.get(short)??0)>1?appSlug(rel):short)}return out}async function scanApps(appRoot,scanDir){let roots;if(scanDir?.trim()){let dir=resolve4(appRoot,scanDir.trim());roots=[{dir,rel:relative5(appRoot,dir)}]}else roots=await discoverScanRoots(appRoot);if(roots.length===0)roots.push({dir:appRoot,rel:""});let apps=[];for(let root of roots){let{framework,routes}=await scanAppRoutes(root.dir);if(routes.length===0)continue;apps.push({dir:root.dir,rel:root.rel,framework,routes})}if(apps.length>1){let prefixes=appPrefixes(apps.map((a)=>a.rel));for(let app of apps){let prefix=prefixes.get(app.rel)??appSlug(app.rel),label=titleCaseFromSegment(prefix);app.routes=app.routes.map((r)=>({...r,id:`${prefix}-${r.id}`,name:`${label} / ${r.name}`,appRel:app.rel}))}}return{apps,routes:apps.flatMap((a)=>a.routes)}}function primaryApp(apps,selected){if(apps.length<=1)return apps[0]??null;let counts=new Map;for(let r of selected){let key=r.appRel??"";counts.set(key,(counts.get(key)??0)+1)}let best=null,bestCount=-1;for(let app of apps){let n=counts.get(app.rel)??0;if(n>bestCount)best=app,bestCount=n}return best}function buildPlaceholderTree(route,hasBadge){return{$ref:"Box",props:{className:"mx-auto w-full max-w-4xl px-6 py-16"},children:[{$ref:"Box",props:{className:"flex flex-col items-center gap-6 text-center"},children:[hasBadge?{$ref:"Badge",props:{variant:"outline",children:route.routePath}}:{$ref:"Text",props:{variant:"muted",children:route.routePath}},{$ref:"Heading",props:{level:1,children:route.name}},{$ref:"Text",props:{variant:"lead",className:"max-w-xl",children:`This is a placeholder, generated from your app's route structure. Rebuild this screen in place \u2014 its id is already "${route.id}", so use compose mode "replace" (don't add_screen \u2014 that conflicts). Start with the hero, then add the supporting sections.`}},{$ref:"Card",props:{className:"mt-4 w-full max-w-2xl text-left"},children:[{$ref:"Box",props:{className:"flex flex-col gap-2 p-6"},children:[{$ref:"Text",props:{variant:"small",className:"uppercase tracking-wider",children:"Detected from"}},{$ref:"Text",props:{className:"font-mono text-sm",children:route.sourceFile}}]}]}]}]}}function buildMuiPlaceholderTree(route){return{$ref:"Container",props:{maxWidth:"md",sx:{py:8}},children:[{$ref:"Stack",props:{spacing:3,sx:{alignItems:"center",textAlign:"center"}},children:[{$ref:"Typography",props:{variant:"overline",color:"text.secondary",children:route.routePath}},{$ref:"Typography",props:{variant:"h3",children:route.name}},{$ref:"Typography",props:{variant:"body1",color:"text.secondary",sx:{maxWidth:520},children:`This is a placeholder, generated from your app's route structure. Rebuild this screen in place \u2014 its id is already "${route.id}", so use compose mode "replace" (don't add_screen \u2014 that conflicts). Start with the hero, then add the supporting sections.`}},{$ref:"Card",props:{variant:"outlined",sx:{mt:2,width:"100%",textAlign:"left"}},children:[{$ref:"CardContent",children:[{$ref:"Stack",props:{spacing:1},children:[{$ref:"Typography",props:{variant:"caption",color:"text.secondary",children:"Detected from"}},{$ref:"Typography",props:{variant:"body2",sx:{fontFamily:"monospace"},children:route.sourceFile}}]}]}]}]}]}}function buildAntdPlaceholderTree(route){return{$ref:"Flex",props:{vertical:!0,align:"center",gap:"large",style:{padding:"64px 24px",textAlign:"center"}},children:[{$ref:"Tag",props:{children:route.routePath}},{$ref:"TypographyTitle",props:{level:2,children:route.name}},{$ref:"TypographyParagraph",props:{type:"secondary",style:{maxWidth:520},children:`This is a placeholder, generated from your app's route structure. Rebuild this screen in place \u2014 its id is already "${route.id}", so use compose mode "replace" (don't add_screen \u2014 that conflicts). Start with the hero, then add the supporting sections.`}},{$ref:"Card",props:{title:"Detected from",style:{width:"100%",maxWidth:640,textAlign:"left",marginTop:16}},children:[{$ref:"TypographyText",props:{code:!0,children:route.sourceFile}}]}]}}function buildChakraPlaceholderTree(route){return{$ref:"Container",props:{maxW:"4xl",sx:{py:16}},children:[{$ref:"Stack",props:{spacing:6,sx:{alignItems:"center",textAlign:"center"}},children:[{$ref:"Badge",props:{variant:"outline",children:route.routePath}},{$ref:"Heading",props:{size:"xl",children:route.name}},{$ref:"Text",props:{sx:{maxW:"xl",color:"chakra-subtle-text"},children:`This is a placeholder, generated from your app's route structure. Rebuild this screen in place \u2014 its id is already "${route.id}", so use compose mode "replace" (don't add_screen \u2014 that conflicts). Start with the hero, then add the supporting sections.`}},{$ref:"Card",props:{variant:"outline",sx:{mt:2,w:"100%",textAlign:"left"}},children:[{$ref:"CardBody",children:[{$ref:"Stack",props:{spacing:1},children:[{$ref:"Text",props:{sx:{fontSize:"xs",textTransform:"uppercase",letterSpacing:"wider",color:"chakra-subtle-text"},children:"Detected from"}},{$ref:"Text",props:{sx:{fontFamily:"mono",fontSize:"sm"},children:route.sourceFile}}]}]}]}]}]}}function buildScreensFromScan(opts){let buildTree=(route)=>{if(opts.tree==="mui")return buildMuiPlaceholderTree(route);if(opts.tree==="antd")return buildAntdPlaceholderTree(route);if(opts.tree==="chakra")return buildChakraPlaceholderTree(route);return buildPlaceholderTree(route,opts.hasBadge)};return opts.routes.map((route)=>({id:route.id,name:route.name,tree:buildTree(route)}))}var MOBILE={w:390,h:844,gap:40};function sectionOf(routePath){return routePath.split("/").filter(Boolean)[0]??""}function buildAppBoard(id,name,routes,dims){let{w,h,cols,gutter}=dims,cellW=w+MOBILE.gap+MOBILE.w,rowH=Math.max(h,MOBILE.h)+gutter,gridFrames=(rs,startY,group)=>rs.flatMap((route,i)=>{let x=80+i%cols*(cellW+gutter),y=startY+Math.floor(i/cols)*rowH;return[{id:`f-${route.id}`,screen:route.id,x,y,w,h,label:route.name,...group?{group}:{}},{id:`f-${route.id}-m`,screen:route.id,x:x+w+MOBILE.gap,y,w:MOBILE.w,h:MOBILE.h,label:`${route.name} \xB7 Mobile`,...group?{group}:{}}]}),bandHeight=(count)=>Math.ceil(count/cols)*rowH,sections=new Map;for(let route of routes){let key=sectionOf(route.routePath),list=sections.get(key);if(list)list.push(route);else sections.set(key,[route])}let multi=[...sections.entries()].filter(([key,rs])=>key!==""&&rs.length>=2);if(routes.length<5||multi.length===0)return{id,name,frames:gridFrames(routes,80),groups:[]};let singles=routes.filter((r)=>!multi.some(([key])=>key===sectionOf(r.routePath))),frames=[],groups=[],y=80;if(singles.length>0)frames.push(...gridFrames(singles,y)),y+=bandHeight(singles.length)+gutter;for(let[key,rs]of multi){let groupId=`g-${idFromRoutePath(`/${key}`)}`;groups.push({id:groupId,name:titleCaseFromSegment(key)}),frames.push(...gridFrames(rs,y,groupId)),y+=bandHeight(rs.length)+gutter}return{id,name,frames,groups}}function buildBoardsFromScan(opts){let dims={w:opts.frameWidth??1024,h:opts.frameHeight??720,cols:opts.columns??3,gutter:opts.gutter??80},byApp=new Map;for(let route of opts.routes){let appRel=route.appRel??"",list=byApp.get(appRel);if(list)list.push(route);else byApp.set(appRel,[route])}return[...byApp.entries()].map(([appRel,routes])=>appRel===void 0?buildAppBoard("app","App",routes,dims):buildAppBoard(appSlug(appRel),appRel||"App",routes,dims))}var import_picocolors=__toESM(require_picocolors(),1);async function offerUpgradeBeforeInit(argv){if(process.env.VELLOO_DISABLE_UPDATE_CHECK==="1"||!process.stdin.isTTY)return!1;let status;try{status=await updateStatus({refresh:!0})}catch{return!1}if(!status.available||!status.upgradable||!status.latest)return!1;console.log(""),console.log(`${import_picocolors.default.yellow("A newer velloo is available:")} ${status.current} \u2192 ${import_picocolors.default.bold(status.latest)}`);let yes=await confirm({message:"Upgrade before setting up this design folder?",initialValue:!0});if(isCancel(yes)||!yes)return console.log(import_picocolors.default.dim(" Continuing on the current version.")),!1;try{if(!(await upgradeInstalledVelloo()).upgraded)return!1;let bin=installedVellooBin();if(!bin)return console.log(import_picocolors.default.dim(" Upgraded. Run `velloo init` again to continue on the new version.")),!0;let code=await Bun.spawn([bin,...argv],{stdin:"inherit",stdout:"inherit",stderr:"inherit",env:{...process.env,VELLOO_DISABLE_UPDATE_CHECK:"1"}}).exited;process.exit(code)}catch(error){return console.log(import_picocolors.default.yellow(` Could not upgrade (${error instanceof Error?error.message:String(error)}) \u2014 continuing on the current version.`)),!1}}import{resolve as resolve7}from"path";var default_default={name:"forest",colors:{background:"#F8F7F2",foreground:"#203C32",primary:{DEFAULT:"#244D3C",foreground:"#FFFFFF"},secondary:{DEFAULT:"#E9EDDF",foreground:"#294332"},muted:{DEFAULT:"#F0F0E8",foreground:"#626D63"},accent:{DEFAULT:"#E8EDDA",foreground:"#244D3C"},destructive:{DEFAULT:"oklch(0.577 0.245 27)",foreground:"oklch(0.985 0 0)"},card:{DEFAULT:"#FFFFFF",foreground:"#203C32"},popover:{DEFAULT:"oklch(0.99 0.01 145)",foreground:"oklch(0.21 0.04 145)"},border:"#DFE3D8",input:"#DFE3D8",ring:"oklch(0.42 0.12 145)"},colorsDark:{background:"#14251F",foreground:"#F0F1E8",primary:{DEFAULT:"#BED5A4",foreground:"#14251F"},secondary:{DEFAULT:"#2B4235",foreground:"#E8EDDF"},muted:{DEFAULT:"#263D31",foreground:"#B0BEAE"},accent:{DEFAULT:"#304737",foreground:"#E8EDDF"},card:{DEFAULT:"#1C3128",foreground:"#F0F1E8"},border:"#3B5143",input:"#3B5143"},typography:{fontFamily:{sans:'"DM Sans", Arial, sans-serif',mono:"ui-monospace, SFMono-Regular, monospace",display:'"DM Serif Display", Georgia, serif'},googleFonts:["DM+Serif+Display","DM+Sans:wght@400;500;600;700"],typesets:{default:{size:14,leading:1.5,flow:"1.25em",fontBody:"sans",fontHeading:"display",fontMono:"mono"},docs:{size:15,leading:1.75,flow:"1.5em"},chat:{leading:1.6,flow:"1em"},compact:{size:14,leading:1.6,flow:"1em"},reading:{size:18,leading:1.9,flow:"2em"}}},spacing:{"0":0,"1":4,"2":8,"3":12,"4":16,"6":24,"8":32,"12":48,"16":64},radius:{sm:4,md:6,lg:8,xl:12,full:9999}};function buildDefaultTheme(){return structuredClone(default_default)}var THEME_PRESETS=[{id:"elsewhere",label:"Elsewhere",seed:"#244d3c"},{id:"indigo",label:"Indigo",seed:"#5e6ad2"},{id:"violet",label:"Violet",seed:"#7c3aed"},{id:"blue",label:"Blue",seed:"#2563eb"},{id:"emerald",label:"Emerald",seed:"#059669"},{id:"rose",label:"Rose",seed:"#e11d48"},{id:"orange",label:"Orange",seed:"#ea580c"},{id:"amber",label:"Amber",seed:"#d97706"},{id:"zinc",label:"Zinc (neutral)",seed:"#52525b"}],CURATED_PRESET="elsewhere",DEFAULT_THEME_PRESET="elsewhere";function presetById(id){return id?THEME_PRESETS.find((p)=>p.id===id):void 0}function isValidPreset(id){return THEME_PRESETS.some((p)=>p.id===id)}function buildPresetTheme(id,name="default"){let base=buildDefaultTheme(),preset=presetById(id);if(!preset||preset.id===CURATED_PRESET)return{...base,name};let derived=derivePalette(preset.seed,base,name);return derived.ok?derived.value.theme:{...base,name}}import{dirname as dirname5,relative as relative6,resolve as resolve6}from"path";import{resolve as resolve5}from"path";var ASSET_SOURCES_default=`# Elsewhere image provenance
6
+ `)){if(/^\s*root\b/.test(line)){routes.push(toRoute("/",routesRb));continue}let get=line.match(/^\s*get\s+["']([^"']+)["']/);if(get?.[1]){let routePath=normalizePath(get[1].replace(/:(\w+)/g,"[$1]").replace(/\*\w+/g,""));if(isPageRoute(routePath))routes.push(toRoute(routePath,routesRb));continue}let res=line.match(/^\s*(resources|resource)\s+:(\w+)/);if(res?.[2]){let base=normalizePath(res[2]);if(!isPageRoute(base))continue;if(routes.push(toRoute(base,routesRb)),res[1]==="resources")routes.push(toRoute(`${base}/[id]`,routesRb))}}return dedupeAndSort(routes)}async function scanLaravel(webPhp){let content=await readFile2(webPhp,"utf8").catch(()=>null);if(!content)return[];let routes=[],entry=/Route::(?:get|view)\(\s*["']([^"']+)["']/g;for(let m of content.matchAll(entry)){let routePath=normalizePath(normalizeParams2(m[1]??""));if(!isPageRoute(routePath))continue;routes.push(toRoute(routePath,webPhp))}return dedupeAndSort(routes)}async function pythonDepDeclared(appRoot,pkg){let manifests=["requirements.txt","requirements-dev.txt","pyproject.toml","Pipfile"];for(let name of manifests){let content=await readFile2(join3(appRoot,name),"utf8").catch(()=>null);if(content&&pkg.test(content))return!0}return!1}async function scanServerRoutes(appRoot){if(existsSync(join3(appRoot,"manage.py")))return{framework:"django",routes:await scanDjango(appRoot),routesRoot:appRoot};let routesRb=join3(appRoot,"config","routes.rb");if(existsSync(routesRb))return{framework:"rails",routes:await scanRails(routesRb),routesRoot:appRoot};let webPhp=join3(appRoot,"routes","web.php");if(existsSync(join3(appRoot,"artisan"))&&existsSync(webPhp))return{framework:"laravel",routes:await scanLaravel(webPhp),routesRoot:appRoot};if(await pythonDepDeclared(appRoot,/\b(flask|fastapi)\b/i))return{framework:"flask",routes:await scanPythonDecorators(appRoot),routesRoot:appRoot};return null}function routeRelative(from,to){return relative(from,to).split(sep).join("/")}var PAGE_EXTS=new Set([".tsx",".ts",".jsx",".js"]);function hasExt(file){let dot=file.lastIndexOf(".");if(dot===-1)return!1;return PAGE_EXTS.has(file.slice(dot))}function stripExt(file){let dot=file.lastIndexOf(".");return dot===-1?file:file.slice(0,dot)}async function fileExists(path){return(await stat2(path).catch(()=>null))?.isFile()??!1}async function scanViteSpaRoot(appRoot){let htmlPath=join4(appRoot,"index.html");if(!await fileExists(htmlPath))return[];let candidates=[];try{let html=await readFile3(htmlPath,"utf8");for(let tag of html.matchAll(/<script\b[^>]*>/gi)){let source=tag[0];if(!/\btype\s*=\s*["']module["']/i.test(source))continue;let src=source.match(/\bsrc\s*=\s*["']([^"']+)["']/i)?.[1];if(!src||/^(?:https?:)?\/\//i.test(src))continue;candidates.push(src.replace(/^\.?\//,""))}}catch{}candidates.push("src/main.tsx","src/main.ts","src/main.jsx","src/main.js","src/index.tsx","src/index.ts","src/index.jsx","src/index.js");for(let rel of new Set(candidates)){let sourceFile=join4(appRoot,rel);if(await fileExists(sourceFile))return[{id:"index",name:"Home",routePath:"/",sourceFile}]}return[]}async function scanNextApp(appDir){let out=[];for await(let file of walkFiles(appDir)){let base=basename3(file);if(stripExt(base)!=="page"||!hasExt(base))continue;let routePath=`/${routeRelative(appDir,dirname2(file)).split("/").filter((s)=>!s.startsWith("(")).join("/")}`.replace(/\/$/,"")||"/",id=idFromRoutePath(routePath);out.push({id,name:nameFromRoutePath(routePath),routePath,sourceFile:file})}return dedupe(out)}async function scanNextPages(pagesDir){let out=[];for await(let file of walkFiles(pagesDir)){if(!hasExt(file))continue;let base=basename3(file);if(stripExt(base).startsWith("_"))continue;let rel=routeRelative(pagesDir,file);if(rel.startsWith("api/")||rel==="api")continue;let segments=rel.split("/"),last=stripExt(segments.pop()??""),path=last==="index"?segments:[...segments,last],routePath=path.length===0?"/":`/${path.join("/")}`;out.push({id:idFromRoutePath(routePath),name:nameFromRoutePath(routePath),routePath,sourceFile:file})}return dedupe(out)}async function scanGenericPagesDir(dir){let out=[];for await(let file of walkFiles(dir)){if(!hasExt(file)&&!file.endsWith(".astro")&&!file.endsWith(".vue")&&!file.endsWith(".svelte"))continue;if(basename3(file).startsWith("_"))continue;let segments=routeRelative(dir,file).split("/"),last=stripExt(segments.pop()??""),path=last==="index"?segments:[...segments,last],routePath=path.length===0?"/":`/${path.join("/")}`;out.push({id:idFromRoutePath(routePath),name:nameFromRoutePath(routePath),routePath,sourceFile:file})}return dedupe(out)}async function scanSvelteKit(dir){let out=[];for await(let file of walkFiles(dir)){if(basename3(file)!=="+page.svelte")continue;let rel=routeRelative(dir,dirname2(file)),segments=rel===""?[]:rel.split("/").filter((s)=>!/^\(.*\)$/.test(s)),routePath=segments.length===0?"/":`/${segments.join("/")}`;out.push({id:idFromRoutePath(routePath),name:nameFromRoutePath(routePath),routePath,sourceFile:file})}return dedupe(out)}function tanstackSegment(seg){if(seg==="$")return"[splat]";if(seg.startsWith("$"))return`[${seg.slice(1)}]`;return seg}async function scanTanstackRouter(dir){let out=[];for await(let file of walkFiles(dir)){if(!hasExt(file))continue;let stem=stripExt(routeRelative(dir,file));if(stem.endsWith(".lazy"))stem=stem.slice(0,-5);if(stem==="routeTree"||stem.endsWith(".gen"))continue;let raw=stem.split(/[/.]/).filter((s)=>s.length>0),leaf=raw[raw.length-1];if(!leaf)continue;if(leaf==="__root"||leaf==="route"||leaf.startsWith("_"))continue;if(raw.some((s)=>s.startsWith("-")))continue;let segments=[];for(let seg of raw){if(seg==="index"||seg==="route")continue;if(seg.startsWith("_"))continue;if(/^\(.*\)$/.test(seg))continue;segments.push(tanstackSegment(seg))}let routePath=segments.length===0?"/":`/${segments.join("/")}`;out.push({id:idFromRoutePath(routePath),name:nameFromRoutePath(routePath),routePath,sourceFile:file})}return dedupe(out)}async function tanstackRoutesDir(appRoot){try{let cfg=JSON.parse(await readFile3(join4(appRoot,"tsr.config.json"),"utf8"));if(typeof cfg.routesDirectory==="string")return join4(appRoot,cfg.routesDirectory)}catch{}return null}function dedupe(routes){let seen=new Set,out=[];for(let r of routes){if(seen.has(r.id))continue;seen.add(r.id),out.push(r)}return out.sort((a,b)=>{if(a.id==="index")return-1;if(b.id==="index")return 1;return a.id.localeCompare(b.id)}),out}async function readPackageJson(appRoot){try{let raw=await readFile3(join4(appRoot,"package.json"),"utf8");return JSON.parse(raw)}catch{return null}}async function detectFramework(appRoot){let pkg=await readPackageJson(appRoot),deps={...pkg?.dependencies??{},...pkg?.devDependencies??{}};if("next"in deps){if(await dirExists(join4(appRoot,"app")))return"next-app";if(await dirExists(join4(appRoot,"src","app")))return"next-app";if(await dirExists(join4(appRoot,"pages")))return"next-pages";if(await dirExists(join4(appRoot,"src","pages")))return"next-pages";return"next-app"}if("astro"in deps)return"astro";if("@sveltejs/kit"in deps)return"sveltekit";if("nuxt"in deps)return"nuxt";if("@tanstack/react-router"in deps||"@tanstack/react-start"in deps||"@tanstack/router-plugin"in deps)return"tanstack-router";if("react-router-dom"in deps||"react-router"in deps)return"react-router";if("vite"in deps)return"vite";return"unknown"}async function scanAppRoutes(appRoot){let framework=await detectFramework(appRoot);if(framework==="next-app"){let candidates=[join4(appRoot,"src","app"),join4(appRoot,"app")];for(let dir of candidates)if(await dirExists(dir))return{framework,routes:await scanNextApp(dir),routesRoot:dir}}if(framework==="next-pages"){let candidates=[join4(appRoot,"src","pages"),join4(appRoot,"pages")];for(let dir of candidates)if(await dirExists(dir))return{framework,routes:await scanNextPages(dir),routesRoot:dir}}if(framework==="astro"){let candidates=[join4(appRoot,"src","pages"),join4(appRoot,"pages")];for(let dir of candidates)if(await dirExists(dir))return{framework,routes:await scanGenericPagesDir(dir),routesRoot:dir}}if(framework==="sveltekit"){let dir=join4(appRoot,"src","routes");if(await dirExists(dir))return{framework,routes:await scanSvelteKit(dir),routesRoot:dir}}if(framework==="nuxt"){let candidates=[join4(appRoot,"app","pages"),join4(appRoot,"src","pages"),join4(appRoot,"pages")];for(let dir of candidates)if(await dirExists(dir))return{framework,routes:await scanGenericPagesDir(dir),routesRoot:dir}}if(framework==="tanstack-router"){let candidates=[await tanstackRoutesDir(appRoot),join4(appRoot,"src","routes"),join4(appRoot,"routes")];for(let dir of candidates)if(dir&&await dirExists(dir))return{framework,routes:await scanTanstackRouter(dir),routesRoot:dir}}if(framework==="react-router"){let result=await scanReactRouter(appRoot);if(result&&result.routes.length>0)return result}for(let dir of[join4(appRoot,"src","routes"),join4(appRoot,"src","pages"),join4(appRoot,"src","views"),join4(appRoot,"pages")])if(await dirExists(dir))return{framework:framework==="unknown"?"unknown":framework,routes:await scanGenericPagesDir(dir),routesRoot:dir};if(framework==="vite"){let routes=await scanViteSpaRoot(appRoot);if(routes.length>0)return{framework,routes,routesRoot:appRoot}}let server=await scanServerRoutes(appRoot);if(server)return server;return{framework,routes:[],routesRoot:appRoot}}var UI_DEPS=["react","next","astro","@sveltejs/kit","svelte","nuxt","vue"];async function looksLikeUiApp(appRoot){let pkg=await readPackageJson(appRoot);if(!pkg)return!1;let deps={...pkg.dependencies??{},...pkg.devDependencies??{}};return UI_DEPS.some((d)=>(d in deps))}var PREFERRED_DIRS=["frontend","web","webapp","client","ui","app","www","site"],SKIP_DIRS2=new Set(["node_modules","dist","build",".next",".turbo","out"]);function rank(rel){let segments=rel.split("/"),preferred=segments.reduce((best,seg)=>{let i=PREFERRED_DIRS.indexOf(seg.toLowerCase());return i===-1?best:Math.min(best,i)},PREFERRED_DIRS.length);return segments.length*100+preferred}async function gitPackageJsonDirs(appRoot){try{let proc=Bun.spawn(["git","-C",appRoot,"ls-files","--cached","--others","--exclude-standard","-z","--","package.json","*/package.json"],{stdout:"pipe",stderr:"ignore",env:scanGitEnv()}),out=await new Response(proc.stdout).text();if(await proc.exited!==0)return null;let dirs=out.split("\x00").filter((p)=>p.endsWith("package.json")&&!p.includes("node_modules/")).map((p)=>resolve(appRoot,dirname3(p)));return dirs.length>0?dirs:null}catch{return null}}function scanGitEnv(){let inherited=process.env.GIT_CEILING_DIRECTORIES,ceilings=inherited?[homedir(),inherited]:[homedir()];return{...process.env,GIT_CEILING_DIRECTORIES:ceilings.join(delimiter)}}async function walkPackageJsonDirs(root,maxDepth){let out=[];async function recurse(dir,depth){let entries=await readdir3(dir,{withFileTypes:!0}).catch(()=>null);if(!entries)return;if(entries.some((e)=>e.isFile()&&e.name==="package.json"))out.push(dir);if(depth>=maxDepth)return;for(let entry of entries){if(!entry.isDirectory()||entry.name.startsWith(".")||SKIP_DIRS2.has(entry.name))continue;await recurse(join5(dir,entry.name),depth+1)}}return await recurse(root,0),out}async function discoverScanRoots(appRoot){let out=[];if(await looksLikeUiApp(appRoot))out.push({dir:appRoot,rel:""});let dirs=await gitPackageJsonDirs(appRoot)??await walkPackageJsonDirs(appRoot,5),nested=[];for(let dir of new Set(dirs)){if(dir===appRoot)continue;if(await looksLikeUiApp(dir))nested.push({dir,rel:relative2(appRoot,dir).split(sep2).join("/")})}return nested.sort((a,b)=>rank(a.rel)-rank(b.rel)||a.rel.localeCompare(b.rel)),[...out,...nested]}function appSlug(rel){return rel.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-|-$/g,"")||"app"}function appPrefixes(rels){let shortOf=(rel)=>appSlug(rel.split("/").pop()??rel),counts=new Map;for(let rel of rels){let s=shortOf(rel);counts.set(s,(counts.get(s)??0)+1)}let out=new Map;for(let rel of rels){let short=shortOf(rel);out.set(rel,(counts.get(short)??0)>1?appSlug(rel):short)}return out}async function scanApps(appRoot,scanDir){let roots;if(scanDir?.trim()){let dir=resolve2(appRoot,scanDir.trim());roots=[{dir,rel:relative3(appRoot,dir).split(sep3).join("/")}]}else roots=await discoverScanRoots(appRoot);if(roots.length===0)roots.push({dir:appRoot,rel:""});let apps=[];for(let root of roots){let{framework,routes}=await scanAppRoutes(root.dir);if(routes.length===0)continue;apps.push({dir:root.dir,rel:root.rel,framework,routes})}if(apps.length>1){let prefixes=appPrefixes(apps.map((a)=>a.rel));for(let app of apps){let prefix=prefixes.get(app.rel)??appSlug(app.rel),label=titleCaseFromSegment(prefix);app.routes=app.routes.map((r)=>({...r,id:`${prefix}-${r.id}`,name:`${label} / ${r.name}`,appRel:app.rel}))}}return{apps,routes:apps.flatMap((a)=>a.routes)}}function primaryApp(apps,selected){if(apps.length<=1)return apps[0]??null;let counts=new Map;for(let r of selected){let key=r.appRel??"";counts.set(key,(counts.get(key)??0)+1)}let best=null,bestCount=-1;for(let app of apps){let n=counts.get(app.rel)??0;if(n>bestCount)best=app,bestCount=n}return best}function buildPlaceholderTree(route,hasBadge){return{$ref:"Box",props:{className:"mx-auto w-full max-w-4xl px-6 py-16"},children:[{$ref:"Box",props:{className:"flex flex-col items-center gap-6 text-center"},children:[hasBadge?{$ref:"Badge",props:{variant:"outline",children:route.routePath}}:{$ref:"Text",props:{variant:"muted",children:route.routePath}},{$ref:"Heading",props:{level:1,children:route.name}},{$ref:"Text",props:{variant:"lead",className:"max-w-xl",children:`This is a placeholder, generated from your app's route structure. Rebuild this screen in place \u2014 its id is already "${route.id}", so use compose mode "replace" (don't add_screen \u2014 that conflicts). Start with the hero, then add the supporting sections.`}},{$ref:"Card",props:{className:"mt-4 w-full max-w-2xl text-left"},children:[{$ref:"Box",props:{className:"flex flex-col gap-2 p-6"},children:[{$ref:"Text",props:{variant:"small",className:"uppercase tracking-wider",children:"Detected from"}},{$ref:"Text",props:{className:"font-mono text-sm",children:route.sourceFile}}]}]}]}]}}function buildMuiPlaceholderTree(route){return{$ref:"Container",props:{maxWidth:"md",sx:{py:8}},children:[{$ref:"Stack",props:{spacing:3,sx:{alignItems:"center",textAlign:"center"}},children:[{$ref:"Typography",props:{variant:"overline",color:"text.secondary",children:route.routePath}},{$ref:"Typography",props:{variant:"h3",children:route.name}},{$ref:"Typography",props:{variant:"body1",color:"text.secondary",sx:{maxWidth:520},children:`This is a placeholder, generated from your app's route structure. Rebuild this screen in place \u2014 its id is already "${route.id}", so use compose mode "replace" (don't add_screen \u2014 that conflicts). Start with the hero, then add the supporting sections.`}},{$ref:"Card",props:{variant:"outlined",sx:{mt:2,width:"100%",textAlign:"left"}},children:[{$ref:"CardContent",children:[{$ref:"Stack",props:{spacing:1},children:[{$ref:"Typography",props:{variant:"caption",color:"text.secondary",children:"Detected from"}},{$ref:"Typography",props:{variant:"body2",sx:{fontFamily:"monospace"},children:route.sourceFile}}]}]}]}]}]}}function buildAntdPlaceholderTree(route){return{$ref:"Flex",props:{vertical:!0,align:"center",gap:"large",style:{padding:"64px 24px",textAlign:"center"}},children:[{$ref:"Tag",props:{children:route.routePath}},{$ref:"TypographyTitle",props:{level:2,children:route.name}},{$ref:"TypographyParagraph",props:{type:"secondary",style:{maxWidth:520},children:`This is a placeholder, generated from your app's route structure. Rebuild this screen in place \u2014 its id is already "${route.id}", so use compose mode "replace" (don't add_screen \u2014 that conflicts). Start with the hero, then add the supporting sections.`}},{$ref:"Card",props:{title:"Detected from",style:{width:"100%",maxWidth:640,textAlign:"left",marginTop:16}},children:[{$ref:"TypographyText",props:{code:!0,children:route.sourceFile}}]}]}}function buildChakraPlaceholderTree(route){return{$ref:"Container",props:{maxW:"4xl",sx:{py:16}},children:[{$ref:"Stack",props:{spacing:6,sx:{alignItems:"center",textAlign:"center"}},children:[{$ref:"Badge",props:{variant:"outline",children:route.routePath}},{$ref:"Heading",props:{size:"xl",children:route.name}},{$ref:"Text",props:{sx:{maxW:"xl",color:"chakra-subtle-text"},children:`This is a placeholder, generated from your app's route structure. Rebuild this screen in place \u2014 its id is already "${route.id}", so use compose mode "replace" (don't add_screen \u2014 that conflicts). Start with the hero, then add the supporting sections.`}},{$ref:"Card",props:{variant:"outline",sx:{mt:2,w:"100%",textAlign:"left"}},children:[{$ref:"CardBody",children:[{$ref:"Stack",props:{spacing:1},children:[{$ref:"Text",props:{sx:{fontSize:"xs",textTransform:"uppercase",letterSpacing:"wider",color:"chakra-subtle-text"},children:"Detected from"}},{$ref:"Text",props:{sx:{fontFamily:"mono",fontSize:"sm"},children:route.sourceFile}}]}]}]}]}]}}function buildScreensFromScan(opts){let buildTree=(route)=>{if(opts.tree==="mui")return buildMuiPlaceholderTree(route);if(opts.tree==="antd")return buildAntdPlaceholderTree(route);if(opts.tree==="chakra")return buildChakraPlaceholderTree(route);return buildPlaceholderTree(route,opts.hasBadge)};return opts.routes.map((route)=>({id:route.id,name:route.name,route:route.routePath,tree:buildTree(route)}))}var MOBILE={w:390,h:844,gap:40};function sectionOf(routePath){return routePath.split("/").filter(Boolean)[0]??""}function buildAppBoard(id,name,routes,dims){let{w,h,cols,gutter}=dims,cellW=w+MOBILE.gap+MOBILE.w,rowH=Math.max(h,MOBILE.h)+gutter,gridFrames=(rs,startY,group)=>rs.flatMap((route,i)=>{let x=80+i%cols*(cellW+gutter),y=startY+Math.floor(i/cols)*rowH;return[{id:`f-${route.id}`,screen:route.id,x,y,w,h,label:route.name,...group?{group}:{}},{id:`f-${route.id}-m`,screen:route.id,x:x+w+MOBILE.gap,y,w:MOBILE.w,h:MOBILE.h,label:`${route.name} \xB7 Mobile`,...group?{group}:{}}]}),bandHeight=(count)=>Math.ceil(count/cols)*rowH,sections=new Map;for(let route of routes){let key=sectionOf(route.routePath),list=sections.get(key);if(list)list.push(route);else sections.set(key,[route])}let multi=[...sections.entries()].filter(([key,rs])=>key!==""&&rs.length>=2);if(routes.length<5||multi.length===0)return{id,name,frames:gridFrames(routes,80),groups:[]};let singles=routes.filter((r)=>!multi.some(([key])=>key===sectionOf(r.routePath))),frames=[],groups=[],y=80;if(singles.length>0)frames.push(...gridFrames(singles,y)),y+=bandHeight(singles.length)+gutter;for(let[key,rs]of multi){let groupId=`g-${idFromRoutePath(`/${key}`)}`;groups.push({id:groupId,name:titleCaseFromSegment(key)}),frames.push(...gridFrames(rs,y,groupId)),y+=bandHeight(rs.length)+gutter}return{id,name,frames,groups}}function buildBoardsFromScan(opts){let dims={w:opts.frameWidth??1024,h:opts.frameHeight??720,cols:opts.columns??3,gutter:opts.gutter??80},byApp=new Map;for(let route of opts.routes){let appRel=route.appRel??"",list=byApp.get(appRel);if(list)list.push(route);else byApp.set(appRel,[route])}return[...byApp.entries()].map(([appRel,routes])=>appRel===void 0?buildAppBoard("app","App",routes,dims):buildAppBoard(appSlug(appRel),appRel||"App",routes,dims))}import{dirname as dirname4,relative as relative4,resolve as resolve4,sep as sep4}from"path";import{resolve as resolve3}from"path";var ASSET_SOURCES_default=`# Elsewhere image provenance
7
7
 
8
8
  The six bundled travel photographs were generated for this repository on
9
9
  2026-09-14 and imported into the design folder through Velloo MCP. They are
@@ -41,35 +41,12 @@ Trips that feel a little more like you.`,className:"whitespace-pre-line mt-6 tex
41
41
  More looking forward.`,className:"font-display font-normal tracking-[-0.035em] text-3xl md:text-4xl whitespace-pre-line mt-3 text-white","data-accent":"ok"}},{$ref:"Text",$id:"elsewhere-overview-33",props:{children:"Your trip is coming together beautifully.",className:"text-xs mt-3 text-white/80","data-accent":"ok"}}]}]},{$ref:"Box",$id:"elsewhere-overview-34",props:{className:"grid grid-cols-2 md:grid-cols-4 gap-4"},children:[{$snippet:"elsewhere-metric",args:{label:"Departure",value:"12 October",note:"34 days to go"}},{$snippet:"elsewhere-metric",args:{label:"Your stay",value:"5 nights",note:"Higashiyama, Kyoto"}},{$snippet:"elsewhere-metric",args:{label:"Trip budget",value:"$3,200",note:"$1,470 still available"}},{$snippet:"elsewhere-metric",args:{label:"Your discoveries",value:"12 saved",note:"4 added to your itinerary"}}]},{$ref:"Box",$id:"elsewhere-overview-35",props:{className:"grid md:grid-cols-[1.4fr_1fr] gap-6"},children:[{$ref:"Card",$id:"elsewhere-overview-36",props:{className:"p-6 rounded-xl shadow-none gap-5"},children:[{$ref:"Box",$id:"elsewhere-overview-37",props:{className:"flex justify-between items-center"},children:[{$ref:"Heading",$id:"elsewhere-overview-38",props:{children:"A little room for spontaneity.",className:"font-display font-normal tracking-[-0.035em] text-2xl"}},{$ref:"Badge",$id:"elsewhere-overview-39",props:{variant:"secondary",className:"rounded-full px-3 py-1 font-normal",children:"On track"}}]},{$ref:"Box",$id:"elsewhere-overview-40",props:{className:"flex items-baseline gap-2"},children:[{$ref:"Heading",$id:"elsewhere-overview-41",props:{children:"$1,730",className:"font-display font-normal tracking-[-0.035em] text-4xl"}},{$ref:"Text",$id:"elsewhere-overview-42",props:{children:"of $3,200 planned",className:"text-xs text-muted-foreground"}}]},{$ref:"Progress",$id:"elsewhere-overview-43",props:{value:54,className:"h-2"}},{$ref:"Chart",$id:"elsewhere-overview-44",props:{kind:"bar",categories:["Stay","Food","Experiences","Transport"],series:[{name:"Planned",data:[970,360,240,160]}],className:"h-[200px] w-full",legend:!1,yLabel:"$"}},{$ref:"Box",$id:"elsewhere-overview-45",props:{className:"flex justify-between text-xs text-muted-foreground"},children:[{$ref:"Text",$id:"elsewhere-overview-46",props:{children:"A comfortable budget for two.",className:""}},{$ref:"Button",$id:"elsewhere-overview-47",props:{variant:"ghost",className:"rounded-full h-6 text-xs"},children:[{$ref:"Icon",$id:"elsewhere-overview-48",props:{name:"ArrowUpRight",className:"size-4"}},{$ref:"Text",$id:"elsewhere-overview-49",props:{children:"View budget",className:" text-inherit",style:{color:"inherit"}}}]}]}]},{$ref:"Card",$id:"elsewhere-overview-50",props:{className:"p-6 rounded-xl shadow-none gap-4"},children:[{$ref:"Box",$id:"elsewhere-overview-51",props:{className:"flex justify-between"},children:[{$ref:"Heading",$id:"elsewhere-overview-52",props:{children:"Kyoto in October",className:"font-display font-normal tracking-[-0.035em] text-2xl"}},{$ref:"Icon",$id:"elsewhere-overview-53",props:{name:"Sun",className:"size-5"}}]},{$ref:"Box",$id:"elsewhere-overview-54",props:{className:"flex items-baseline gap-2"},children:[{$ref:"Heading",$id:"elsewhere-overview-55",props:{children:"22\xB0",className:"font-display font-normal tracking-[-0.035em] text-4xl"}},{$ref:"Text",$id:"elsewhere-overview-56",props:{children:"a little cooler, a little quieter",className:"text-xs text-muted-foreground"}}]},{$ref:"Chart",$id:"elsewhere-overview-57",props:{kind:"line",categories:["May","Jun","Jul","Aug","Sep","Oct","Nov"],series:[{name:"Typical daytime \xB0C",data:[25,28,32,33,29,22,17]}],className:"h-[170px] w-full",legend:!1,yLabel:"\xB0C"}},{$ref:"Text",$id:"elsewhere-overview-58",props:{children:"Crisp mornings, warm afternoons. Pack a light layer and your most comfortable shoes.",className:"text-xs leading-6 text-muted-foreground"}}]}]},{$ref:"Card",$id:"elsewhere-overview-59",props:{className:"p-6 rounded-xl shadow-none gap-4"},children:[{$ref:"Box",$id:"elsewhere-overview-60",props:{className:"flex justify-between items-center"},children:[{$ref:"Heading",$id:"elsewhere-overview-61",props:{children:"The essentials, taken care of.",className:"font-display font-normal tracking-[-0.035em] text-2xl"}},{$ref:"Button",$id:"elsewhere-overview-62",props:{variant:"ghost",className:"rounded-full "},children:[{$ref:"Icon",$id:"elsewhere-overview-63",props:{name:"ArrowUpRight",className:"size-4"}},{$ref:"Text",$id:"elsewhere-overview-64",props:{children:"All bookings",className:" text-inherit",style:{color:"inherit"}}}]}]},{$ref:"Table",$id:"elsewhere-overview-65",props:{},children:[{$ref:"TableHeader",$id:"elsewhere-overview-66",props:{},children:[{$ref:"TableRow",$id:"elsewhere-overview-67",props:{},children:[{$ref:"TableHead",$id:"elsewhere-overview-68",props:{children:"Booking",className:"text-xs"}},{$ref:"TableHead",$id:"elsewhere-overview-69",props:{children:"Dates",className:"text-xs"}},{$ref:"TableHead",$id:"elsewhere-overview-70",props:{children:"Status",className:"text-xs"}},{$ref:"TableHead",$id:"elsewhere-overview-71",props:{children:"Total",className:"text-xs"}}]}]},{$ref:"TableBody",$id:"elsewhere-overview-72",props:{},children:[{$ref:"TableRow",$id:"elsewhere-overview-73",props:{},children:[{$ref:"TableCell",$id:"elsewhere-overview-74",props:{className:"py-4 text-xs"},children:[{$ref:"Text",$id:"elsewhere-overview-75",props:{children:"The Higashiyama House",className:""}}]},{$ref:"TableCell",$id:"elsewhere-overview-76",props:{className:"py-4 text-xs"},children:[{$ref:"Text",$id:"elsewhere-overview-77",props:{children:"12\u201317 Oct",className:""}}]},{$ref:"TableCell",$id:"elsewhere-overview-78",props:{className:"py-4 text-xs"},children:[{$ref:"Badge",$id:"elsewhere-overview-79",props:{variant:"secondary",className:"rounded-full px-3 py-1 font-normal",children:"Confirmed"}}]},{$ref:"TableCell",$id:"elsewhere-overview-80",props:{className:"py-4 text-xs"},children:[{$ref:"Text",$id:"elsewhere-overview-81",props:{children:"$970",className:""}}]}]},{$ref:"TableRow",$id:"elsewhere-overview-82",props:{},children:[{$ref:"TableCell",$id:"elsewhere-overview-83",props:{className:"py-4 text-xs"},children:[{$ref:"Text",$id:"elsewhere-overview-84",props:{children:"Tea with a local host",className:""}}]},{$ref:"TableCell",$id:"elsewhere-overview-85",props:{className:"py-4 text-xs"},children:[{$ref:"Text",$id:"elsewhere-overview-86",props:{children:"12 Oct \xB7 14:00",className:""}}]},{$ref:"TableCell",$id:"elsewhere-overview-87",props:{className:"py-4 text-xs"},children:[{$ref:"Badge",$id:"elsewhere-overview-88",props:{variant:"secondary",className:"rounded-full px-3 py-1 font-normal",children:"Reserved"}}]},{$ref:"TableCell",$id:"elsewhere-overview-89",props:{className:"py-4 text-xs"},children:[{$ref:"Text",$id:"elsewhere-overview-90",props:{children:"$64",className:""}}]}]},{$ref:"TableRow",$id:"elsewhere-overview-91",props:{},children:[{$ref:"TableCell",$id:"elsewhere-overview-92",props:{className:"py-4 text-xs"},children:[{$ref:"Text",$id:"elsewhere-overview-93",props:{children:"Airport transfer",className:""}}]},{$ref:"TableCell",$id:"elsewhere-overview-94",props:{className:"py-4 text-xs"},children:[{$ref:"Text",$id:"elsewhere-overview-95",props:{children:"12 Oct \xB7 08:10",className:""}}]},{$ref:"TableCell",$id:"elsewhere-overview-96",props:{className:"py-4 text-xs"},children:[{$ref:"Badge",$id:"elsewhere-overview-97",props:{variant:"secondary",className:"rounded-full px-3 py-1 font-normal",children:"To book"}}]},{$ref:"TableCell",$id:"elsewhere-overview-98",props:{className:"py-4 text-xs"},children:[{$ref:"Text",$id:"elsewhere-overview-99",props:{children:"$80",className:""}}]}]}]}]}]}]},{$ref:"Box",$id:"elsewhere-overview-100",props:{className:"px-6 md:px-14 py-8 border-t border-border flex justify-between items-center gap-4 flex-wrap"},children:[{$ref:"Text",$id:"elsewhere-overview-101",props:{children:"Go a little further. Stay a little longer.",className:"font-display text-lg"}},{$ref:"Text",$id:"elsewhere-overview-102",props:{children:"elsewhere / 2026",className:"text-[10px] uppercase tracking-widest text-muted-foreground"}}]}]}};var elsewhere_stay_default={id:"elsewhere-stay",name:"02 \xB7 A stay in Kyoto",tree:{$ref:"Box",$id:"elsewhere-stay-1",props:{className:"bg-background text-foreground min-h-screen font-sans"},children:[{$snippet:"elsewhere-nav",args:{}},{$ref:"Box",$id:"elsewhere-stay-2",props:{className:"px-6 md:px-14 py-7 space-y-6"},children:[{$ref:"Box",$id:"elsewhere-stay-3",props:{className:"flex justify-between items-center text-xs"},children:[{$ref:"Text",$id:"elsewhere-stay-4",props:{children:"Discover / Japan / Kyoto",className:"text-muted-foreground"}},{$ref:"Button",$id:"elsewhere-stay-5",props:{variant:"outline",className:"rounded-full "},children:[{$ref:"Icon",$id:"elsewhere-stay-6",props:{name:"Heart",className:"size-4"}},{$ref:"Text",$id:"elsewhere-stay-7",props:{children:"Save this stay",className:" text-inherit",style:{color:"inherit"}}}]}]},{$ref:"Box",$id:"elsewhere-stay-8",props:{className:"md:flex justify-between items-end space-y-3"},children:[{$ref:"Box",$id:"elsewhere-stay-9",props:{className:"space-y-3"},children:[{$ref:"Text",$id:"elsewhere-stay-10",props:{children:"THE ELSEWHERE COLLECTION",className:"text-[10px] uppercase tracking-[0.22em] font-semibold text-primary"}},{$ref:"Heading",$id:"elsewhere-stay-11",props:{children:"The Higashiyama House",className:"font-display font-normal tracking-[-0.035em] text-4xl md:text-5xl"}},{$ref:"Text",$id:"elsewhere-stay-12",props:{children:"A quiet address in the heart of old Kyoto.",className:"text-sm text-muted-foreground max-w-xl leading-6"}}]},{$ref:"Box",$id:"elsewhere-stay-13",props:{className:"flex items-center gap-2"},children:[{$ref:"Icon",$id:"elsewhere-stay-14",props:{name:"Star",className:"size-4 text-primary"}},{$ref:"Text",$id:"elsewhere-stay-15",props:{children:"4.98",className:"font-semibold text-sm"}},{$ref:"Text",$id:"elsewhere-stay-16",props:{children:"\xB7 86 thoughtful reviews",className:"text-xs text-muted-foreground"}}]}]},{$ref:"Box",$id:"elsewhere-stay-17",props:{className:"grid grid-cols-1 md:grid-cols-[1.65fr_1fr] gap-3"},children:[{$ref:"Box",$id:"elsewhere-stay-18",props:{className:"relative overflow-hidden h-[330px] md:h-[410px] rounded-xl"},children:[{$ref:"Image",$id:"elsewhere-stay-19",props:{src:"/assets/elsewhere-room.jpg",alt:"Quiet contemporary guest room",className:"absolute inset-0 h-full w-full",fill:!0}}]},{$ref:"Box",$id:"elsewhere-stay-20",props:{className:"hidden md:grid grid-rows-2 gap-3"},children:[{$ref:"Box",$id:"elsewhere-stay-21",props:{className:"relative overflow-hidden rounded-xl"},children:[{$ref:"Image",$id:"elsewhere-stay-22",props:{src:"/assets/elsewhere-kyoto.jpg",alt:"Yasaka Pagoda above a Kyoto street at sunset",className:"absolute inset-0 h-full w-full",fill:!0}}]},{$ref:"Box",$id:"elsewhere-stay-23",props:{className:"relative overflow-hidden rounded-xl"},children:[{$ref:"Image",$id:"elsewhere-stay-24",props:{src:"/assets/elsewhere-japan.jpg",alt:"japan travel photography",className:"absolute inset-0 h-full w-full",fill:!0}},{$ref:"Button",$id:"elsewhere-stay-25",props:{variant:"secondary",className:"rounded-full absolute bottom-4 right-4"},children:[{$ref:"Icon",$id:"elsewhere-stay-26",props:{name:"Images",className:"size-4"}},{$ref:"Text",$id:"elsewhere-stay-27",props:{children:"View all 12 photos",className:" text-inherit",style:{color:"inherit"}}}]}]}]}]},{$ref:"Box",$id:"elsewhere-stay-28",props:{className:"grid md:grid-cols-[1.65fr_1fr] gap-10 pt-2"},children:[{$ref:"Box",$id:"elsewhere-stay-29",props:{className:"space-y-7"},children:[{$ref:"Box",$id:"elsewhere-stay-30",props:{className:"flex items-center gap-2"},children:[{$ref:"Badge",$id:"elsewhere-stay-31",props:{variant:"secondary",className:"rounded-full px-3 py-1 font-normal",children:"Guest favourite"}},{$ref:"Badge",$id:"elsewhere-stay-32",props:{variant:"secondary",className:"rounded-full px-3 py-1 font-normal",children:"Design-led"}},{$ref:"Badge",$id:"elsewhere-stay-33",props:{variant:"secondary",className:"rounded-full px-3 py-1 font-normal",children:"Locally hosted"}}]},{$ref:"Heading",$id:"elsewhere-stay-34",props:{children:`A little sanctuary.
42
42
  An entire city at your door.`,className:"font-display font-normal tracking-[-0.035em] text-3xl whitespace-pre-line"}},{$ref:"Text",$id:"elsewhere-stay-35",props:{children:"Behind a discreet entrance, soft light falls across natural timber and linen. Step outside for morning markets, neighbourhood coffee, and the lanes of Higashiyama. This is Kyoto at your own pace.",className:"text-sm leading-7 text-muted-foreground max-w-2xl"}},{$ref:"Box",$id:"elsewhere-stay-36",props:{className:"grid grid-cols-2 md:grid-cols-4 gap-4 text-xs"},children:[{$ref:"Box",$id:"elsewhere-stay-37",props:{className:"flex items-center gap-2"},children:[{$ref:"Icon",$id:"elsewhere-stay-38",props:{name:"BedDouble",className:"size-4"}},{$ref:"Text",$id:"elsewhere-stay-39",props:{children:"2 guests",className:""}}]},{$ref:"Box",$id:"elsewhere-stay-40",props:{className:"flex items-center gap-2"},children:[{$ref:"Icon",$id:"elsewhere-stay-41",props:{name:"Bath",className:"size-4"}},{$ref:"Text",$id:"elsewhere-stay-42",props:{children:"Private bath",className:""}}]},{$ref:"Box",$id:"elsewhere-stay-43",props:{className:"flex items-center gap-2"},children:[{$ref:"Icon",$id:"elsewhere-stay-44",props:{name:"Wifi",className:"size-4"}},{$ref:"Text",$id:"elsewhere-stay-45",props:{children:"Fast Wi-Fi",className:""}}]},{$ref:"Box",$id:"elsewhere-stay-46",props:{className:"flex items-center gap-2"},children:[{$ref:"Icon",$id:"elsewhere-stay-47",props:{name:"Coffee",className:"size-4"}},{$ref:"Text",$id:"elsewhere-stay-48",props:{children:"Breakfast",className:""}}]}]},{$ref:"Separator",$id:"elsewhere-stay-49",props:{}},{$ref:"Box",$id:"elsewhere-stay-50",props:{className:"flex gap-4 items-center"},children:[{$ref:"Avatar",$id:"elsewhere-stay-51",props:{className:"size-8 border-2 border-background"},children:[{$ref:"AvatarFallback",$id:"elsewhere-stay-52",props:{children:"MK",className:"text-[10px] bg-secondary text-secondary-foreground"}}]},{$ref:"Box",$id:"elsewhere-stay-53",props:{className:""},children:[{$ref:"Text",$id:"elsewhere-stay-54",props:{children:"Hosted by Michiko",className:"font-semibold text-sm"}},{$ref:"Text",$id:"elsewhere-stay-55",props:{children:"Kyoto local \xB7 Welcoming guests since 2018",className:"text-xs text-muted-foreground"}}]}]}]},{$ref:"Card",$id:"elsewhere-stay-56",props:{className:"rounded-2xl p-6 shadow-sm gap-5"},children:[{$ref:"Box",$id:"elsewhere-stay-57",props:{className:"flex justify-between items-center"},children:[{$ref:"Box",$id:"elsewhere-stay-58",props:{className:"flex items-baseline gap-2"},children:[{$ref:"Heading",$id:"elsewhere-stay-59",props:{children:"$185",className:"font-display font-normal tracking-[-0.035em] text-3xl"}},{$ref:"Text",$id:"elsewhere-stay-60",props:{children:"/ night",className:"text-xs text-muted-foreground"}}]},{$ref:"Badge",$id:"elsewhere-stay-61",props:{variant:"secondary",className:"rounded-full px-3 py-1 font-normal",children:"Breakfast included"}}]},{$ref:"FieldGroup",$id:"elsewhere-stay-62",props:{},children:[{$ref:"Field",$id:"elsewhere-stay-63",props:{},children:[{$ref:"FieldLabel",$id:"elsewhere-stay-64",props:{children:"Your dates"}},{$ref:"Button",$id:"elsewhere-stay-65",props:{variant:"outline",className:"rounded-full justify-start rounded-lg w-full"},children:[{$ref:"Icon",$id:"elsewhere-stay-66",props:{name:"CalendarDays",className:"size-4"}},{$ref:"Text",$id:"elsewhere-stay-67",props:{children:"12 Oct \u2013 17 Oct 2026",className:" text-inherit",style:{color:"inherit"}}}]}]},{$ref:"Field",$id:"elsewhere-stay-68",props:{},children:[{$ref:"FieldLabel",$id:"elsewhere-stay-69",props:{children:"Travellers"}},{$ref:"NativeSelect",$id:"elsewhere-stay-70",props:{defaultValue:"2",className:"w-full"},children:[{$ref:"NativeSelectOption",$id:"elsewhere-stay-71",props:{value:"2",children:"2 adults \xB7 1 room"}},{$ref:"NativeSelectOption",$id:"elsewhere-stay-72",props:{value:"1",children:"1 adult \xB7 1 room"}}]}]}]},{$ref:"Box",$id:"elsewhere-stay-73",props:{className:"space-y-3 text-sm"},children:[{$ref:"Box",$id:"elsewhere-stay-74",props:{className:"flex justify-between"},children:[{$ref:"Text",$id:"elsewhere-stay-75",props:{children:"$185 \xD7 5 nights",className:""}},{$ref:"Text",$id:"elsewhere-stay-76",props:{children:"$925",className:""}}]},{$ref:"Box",$id:"elsewhere-stay-77",props:{className:"flex justify-between text-muted-foreground"},children:[{$ref:"Text",$id:"elsewhere-stay-78",props:{children:"Service fee",className:""}},{$ref:"Text",$id:"elsewhere-stay-79",props:{children:"$45",className:""}}]},{$ref:"Separator",$id:"elsewhere-stay-80",props:{}},{$ref:"Box",$id:"elsewhere-stay-81",props:{className:"flex justify-between font-semibold"},children:[{$ref:"Text",$id:"elsewhere-stay-82",props:{children:"Total",className:""}},{$ref:"Text",$id:"elsewhere-stay-83",props:{children:"$970",className:""}}]}]},{$ref:"Button",$id:"elsewhere-stay-84",props:{variant:"default",className:"rounded-full h-11 w-full"},children:[{$ref:"Icon",$id:"elsewhere-stay-85",props:{name:"Plus",className:"size-4"}},{$ref:"Text",$id:"elsewhere-stay-86",props:{children:"Add to my trip",className:" text-inherit",style:{color:"inherit"}}}]},{$ref:"Text",$id:"elsewhere-stay-87",props:{children:"Free cancellation until 5 October",className:"text-center text-xs text-muted-foreground"}}]}]}]},{$ref:"Box",$id:"elsewhere-stay-88",props:{className:"px-6 md:px-14 py-8 border-t border-border flex justify-between items-center gap-4 flex-wrap"},children:[{$ref:"Text",$id:"elsewhere-stay-89",props:{children:"Go a little further. Stay a little longer.",className:"font-display text-lg"}},{$ref:"Text",$id:"elsewhere-stay-90",props:{children:"elsewhere / 2026",className:"text-[10px] uppercase tracking-widest text-muted-foreground"}}]}]}};var elsewhere_trips_board_default={id:"elsewhere-trips-board",name:"B \xB7 The brief-to-plan workspace",tree:{$ref:"Box",$id:"agentic-2-1",props:{className:"min-h-screen bg-background text-foreground font-sans"},children:[{$snippet:"elsewhere-nav"},{$ref:"Box",$id:"agentic-2-2",props:{className:"px-12 py-10 space-y-8"},children:[{$ref:"Box",$id:"agentic-2-3",props:{className:"flex justify-between items-end"},children:[{$ref:"Box",$id:"agentic-2-4",props:{className:"space-y-3"},children:[{$ref:"Text",$id:"agentic-2-5",props:{children:"YOU SET THE DIRECTION",className:"text-[10px] uppercase tracking-[.2em] text-primary"}},{$ref:"Heading",$id:"agentic-2-6",props:{children:"A little brief. A thoughtful whole trip.",className:"font-display font-normal tracking-[-0.03em] text-5xl leading-[1.08]"}},{$ref:"Text",$id:"agentic-2-7",props:{children:"Tell your companion what matters. Watch the plan take shape, then make it yours.",className:"text-sm leading-7 text-muted-foreground max-w-2xl"}}]},{$ref:"Badge",$id:"agentic-2-8",props:{variant:"secondary",children:"New trip \xB7 Draft",className:"rounded-full px-3 py-1 text-[10px] font-normal"}}]},{$ref:"Box",$id:"agentic-2-9",props:{className:"grid grid-cols-[340px_1fr] gap-7 items-start"},children:[{$ref:"Box",$id:"agentic-2-10",props:{className:"space-y-6"},children:[{$ref:"Card",$id:"agentic-2-11",props:{className:"rounded-2xl shadow-none p-6 gap-5 "},children:[{$ref:"Heading",$id:"agentic-2-12",props:{children:"Your starting point",className:"font-display font-normal tracking-[-0.03em] text-3xl"}},{$ref:"FieldGroup",$id:"agentic-2-13",children:[{$ref:"Field",$id:"agentic-2-14",children:[{$ref:"FieldLabel",$id:"agentic-2-15",props:{children:"Where"}},{$ref:"Input",$id:"agentic-2-16",props:{defaultValue:"Kyoto, Japan",className:"bg-card"}}]},{$ref:"Field",$id:"agentic-2-17",children:[{$ref:"FieldLabel",$id:"agentic-2-18",props:{children:"When"}},{$ref:"Input",$id:"agentic-2-19",props:{defaultValue:"12\u201317 October 2026",className:"bg-card"}}]},{$ref:"Field",$id:"agentic-2-20",children:[{$ref:"FieldLabel",$id:"agentic-2-21",props:{children:"Who\u2019s coming"}},{$ref:"Input",$id:"agentic-2-22",props:{defaultValue:"2 travellers",className:"bg-card"}}]},{$ref:"Field",$id:"agentic-2-23",children:[{$ref:"FieldLabel",$id:"agentic-2-24",props:{children:"Comfortable budget"}},{$ref:"Input",$id:"agentic-2-25",props:{defaultValue:"$3,200",className:"bg-card"}}]}]},{$ref:"Separator",$id:"agentic-2-26"},{$ref:"Text",$id:"agentic-2-27",props:{children:"YOUR KIND OF TRIP",className:"text-[9px] tracking-widest text-muted-foreground"}},{$ref:"Box",$id:"agentic-2-28",props:{className:"flex flex-wrap gap-2"},children:[{$ref:"Badge",$id:"agentic-2-29",props:{variant:"secondary",children:"Local food",className:"rounded-full px-3 py-1 text-[10px] font-normal"}},{$ref:"Badge",$id:"agentic-2-30",props:{variant:"secondary",children:"Small galleries",className:"rounded-full px-3 py-1 text-[10px] font-normal"}},{$ref:"Badge",$id:"agentic-2-31",props:{variant:"secondary",children:"Quiet stays",className:"rounded-full px-3 py-1 text-[10px] font-normal"}},{$ref:"Badge",$id:"agentic-2-32",props:{variant:"secondary",children:"Slow mornings",className:"rounded-full px-3 py-1 text-[10px] font-normal"}}]},{$ref:"Field",$id:"agentic-2-33",children:[{$ref:"FieldLabel",$id:"agentic-2-34",props:{children:"Anything else?"}},{$ref:"Textarea",$id:"agentic-2-35",props:{defaultValue:"One early start is fine. Leave a couple of afternoons free. We would love a tea experience.",className:"min-h-[110px] bg-card"}}]},{$ref:"Button",$id:"agentic-2-36",props:{variant:"default",className:"rounded-full h-11 w-full"},children:[{$ref:"Icon",$id:"agentic-2-37",props:{name:"Sparkles",className:"size-4"}},{$ref:"Box",$id:"agentic-2-38",props:{className:"",children:"Build my first draft"}}]}]},{$ref:"Card",$id:"agentic-2-39",props:{className:"rounded-2xl shadow-none p-6 gap-5 bg-muted/40"},children:[{$ref:"Box",$id:"agentic-2-40",props:{className:"flex gap-2 items-center"},children:[{$ref:"Icon",$id:"agentic-2-41",props:{name:"Compass",className:"size-4"}},{$ref:"Text",$id:"agentic-2-42",props:{children:"A little research, taken care of.",className:"font-semibold text-sm"}}]},{$ref:"Box",$id:"agentic-2-43",props:{className:"divide-y divide-border"},children:[{$ref:"Box",$id:"agentic-2-44",props:{className:"flex items-center justify-between gap-3 py-3"},children:[{$ref:"Box",$id:"agentic-2-45",props:{className:"flex items-center gap-3"},children:[{$ref:"Icon",$id:"agentic-2-46",props:{name:"CircleCheck",className:"size-4 text-primary"}},{$ref:"Text",$id:"agentic-2-47",props:{children:"Matched your pace and interests",className:"text-xs"}}]},{$ref:"Text",$id:"agentic-2-48",props:{children:"Done",className:"text-[10px] text-muted-foreground"}}]},{$ref:"Box",$id:"agentic-2-49",props:{className:"flex items-center justify-between gap-3 py-3"},children:[{$ref:"Box",$id:"agentic-2-50",props:{className:"flex items-center gap-3"},children:[{$ref:"Icon",$id:"agentic-2-51",props:{name:"CircleCheck",className:"size-4 text-primary"}},{$ref:"Text",$id:"agentic-2-52",props:{children:"Compared 6 neighbourhood stays",className:"text-xs"}}]},{$ref:"Text",$id:"agentic-2-53",props:{children:"Done",className:"text-[10px] text-muted-foreground"}}]},{$ref:"Box",$id:"agentic-2-54",props:{className:"flex items-center justify-between gap-3 py-3"},children:[{$ref:"Box",$id:"agentic-2-55",props:{className:"flex items-center gap-3"},children:[{$ref:"Icon",$id:"agentic-2-56",props:{name:"CircleCheck",className:"size-4 text-primary"}},{$ref:"Text",$id:"agentic-2-57",props:{children:"Grouped nearby discoveries",className:"text-xs"}}]},{$ref:"Text",$id:"agentic-2-58",props:{children:"Done",className:"text-[10px] text-muted-foreground"}}]},{$ref:"Box",$id:"agentic-2-59",props:{className:"flex items-center justify-between gap-3 py-3"},children:[{$ref:"Box",$id:"agentic-2-60",props:{className:"flex items-center gap-3"},children:[{$ref:"Icon",$id:"agentic-2-61",props:{name:"CircleCheck",className:"size-4 text-primary"}},{$ref:"Text",$id:"agentic-2-62",props:{children:"Balanced the plan with your budget",className:"text-xs"}}]},{$ref:"Text",$id:"agentic-2-63",props:{children:"Done",className:"text-[10px] text-muted-foreground"}}]}]},{$ref:"Text",$id:"agentic-2-64",props:{children:"Suggestions prepared \xB7 Nothing booked",className:"text-[10px] text-muted-foreground"}}]},{$ref:"Card",$id:"agentic-2-65",props:{className:"rounded-2xl shadow-none p-6 gap-5 bg-secondary/30"},children:[{$ref:"Heading",$id:"agentic-2-66",props:{children:"Your companion remembers.",className:"font-display font-normal tracking-[-0.03em] text-2xl"}},{$ref:"Text",$id:"agentic-2-67",props:{children:"These preferences guide every suggestion. Change your brief any time to update the plan.",className:"text-xs leading-6 text-muted-foreground"}},{$ref:"Box",$id:"agentic-2-68",props:{className:"flex items-center gap-3"},children:[{$ref:"Switch",$id:"agentic-2-69",props:{defaultChecked:!0}},{$ref:"Text",$id:"agentic-2-70",props:{children:"Use my saved travel preferences",className:"text-xs"}}]}]}]},{$ref:"Box",$id:"agentic-2-71",props:{className:"space-y-6"},children:[{$ref:"Card",$id:"agentic-2-72",props:{className:"rounded-2xl shadow-none p-6 gap-5 "},children:[{$ref:"Box",$id:"agentic-2-73",props:{className:"flex justify-between items-center"},children:[{$ref:"Box",$id:"agentic-2-74",props:{className:"flex gap-3 items-center"},children:[{$ref:"Box",$id:"agentic-2-75",props:{className:"size-8 rounded-full bg-primary text-primary-foreground flex items-center justify-center shrink-0"},children:[{$ref:"Icon",$id:"agentic-2-76",props:{name:"Sparkles",className:"size-4"}}]},{$ref:"Box",$id:"agentic-2-77",props:{className:""},children:[{$ref:"Text",$id:"agentic-2-78",props:{children:"Your first draft is ready",className:"font-semibold text-sm"}},{$ref:"Text",$id:"agentic-2-79",props:{children:"Built around your brief \xB7 5 nights",className:"text-[10px] text-muted-foreground"}}]}]},{$ref:"Badge",$id:"agentic-2-80",props:{variant:"secondary",children:"Ready to refine",className:"rounded-full px-3 py-1 text-[10px] font-normal"}}]},{$ref:"Heading",$id:"agentic-2-81",props:{children:"Kyoto, with room to breathe.",className:"font-display font-normal tracking-[-0.03em] text-4xl"}},{$ref:"Text",$id:"agentic-2-82",props:{children:"A central stay, five gently paced days, and a budget with plenty of breathing room. Here\u2019s the direction I suggest.",className:"text-sm leading-7 text-muted-foreground"}},{$ref:"Box",$id:"agentic-2-83",props:{className:"grid grid-cols-3 gap-4"},children:[{$ref:"Box",$id:"agentic-2-84",props:{className:"bg-muted/60 rounded-xl p-4 space-y-1"},children:[{$ref:"Heading",$id:"agentic-2-85",props:{children:"$1,730",className:"font-display font-normal tracking-[-0.03em] text-2xl"}},{$ref:"Text",$id:"agentic-2-86",props:{children:"estimated total",className:"text-[10px] text-muted-foreground"}}]},{$ref:"Box",$id:"agentic-2-87",props:{className:"bg-muted/60 rounded-xl p-4 space-y-1"},children:[{$ref:"Heading",$id:"agentic-2-88",props:{children:"2",className:"font-display font-normal tracking-[-0.03em] text-2xl"}},{$ref:"Text",$id:"agentic-2-89",props:{children:"open afternoons",className:"text-[10px] text-muted-foreground"}}]},{$ref:"Box",$id:"agentic-2-90",props:{className:"bg-muted/60 rounded-xl p-4 space-y-1"},children:[{$ref:"Heading",$id:"agentic-2-91",props:{children:"4.8 km",className:"font-display font-normal tracking-[-0.03em] text-2xl"}},{$ref:"Text",$id:"agentic-2-92",props:{children:"longest walking day",className:"text-[10px] text-muted-foreground"}}]}]}]},{$ref:"Card",$id:"agentic-2-93",props:{className:"rounded-2xl shadow-none p-6 gap-5 "},children:[{$ref:"Box",$id:"agentic-2-94",props:{className:"flex justify-between"},children:[{$ref:"Heading",$id:"agentic-2-95",props:{children:"Choose your home base.",className:"font-display font-normal tracking-[-0.03em] text-3xl"}},{$ref:"Button",$id:"agentic-2-96",props:{variant:"ghost",className:"rounded-full text-xs"},children:[{$ref:"Icon",$id:"agentic-2-97",props:{name:"ArrowUpRight",className:"size-4"}},{$ref:"Box",$id:"agentic-2-98",props:{className:"",children:"Compare stays"}}]}]},{$ref:"Box",$id:"agentic-2-99",props:{className:"grid grid-cols-2 gap-4"},children:[{$ref:"Card",$id:"agentic-2-100",props:{className:"rounded-xl overflow-hidden p-0 gap-0 shadow-none"},children:[{$ref:"Box",$id:"agentic-2-101",props:{className:"relative overflow-hidden h-[155px]"},children:[{$ref:"Image",$id:"agentic-2-102",props:{src:"/assets/elsewhere-room.jpg",alt:"room travel inspiration",fill:!0,className:"absolute inset-0 w-full h-full"}}]},{$ref:"CardContent",$id:"agentic-2-103",props:{className:"p-4 space-y-3"},children:[{$ref:"Heading",$id:"agentic-2-104",props:{children:"Higashiyama House",className:"font-display font-normal tracking-[-0.03em] text-2xl"}},{$ref:"Text",$id:"agentic-2-105",props:{children:"$970 / FIVE NIGHTS",className:"text-[10px] text-primary"}},{$ref:"Text",$id:"agentic-2-106",props:{children:"Recommended for your walkable, food-first week.",className:"text-xs leading-6 text-muted-foreground"}}]}]},{$ref:"Card",$id:"agentic-2-107",props:{className:"rounded-xl overflow-hidden p-0 gap-0 shadow-none"},children:[{$ref:"Box",$id:"agentic-2-108",props:{className:"relative overflow-hidden h-[155px]"},children:[{$ref:"Image",$id:"agentic-2-109",props:{src:"/assets/elsewhere-forest.jpg",alt:"forest travel inspiration",fill:!0,className:"absolute inset-0 w-full h-full"}}]},{$ref:"CardContent",$id:"agentic-2-110",props:{className:"p-4 space-y-3"},children:[{$ref:"Heading",$id:"agentic-2-111",props:{children:"The Garden Retreat",className:"font-display font-normal tracking-[-0.03em] text-2xl"}},{$ref:"Text",$id:"agentic-2-112",props:{children:"$1,095 / FIVE NIGHTS",className:"text-[10px] text-primary"}},{$ref:"Text",$id:"agentic-2-113",props:{children:"A quieter setting with a little more travel time.",className:"text-xs leading-6 text-muted-foreground"}}]}]}]},{$ref:"Box",$id:"agentic-2-114",props:{className:"flex justify-between items-center"},children:[{$ref:"Badge",$id:"agentic-2-115",props:{variant:"secondary",children:"Higashiyama selected",className:"rounded-full px-3 py-1 text-[10px] font-normal"}},{$ref:"Text",$id:"agentic-2-116",props:{children:"Nothing reserved yet",className:"text-[10px] text-muted-foreground"}}]}]},{$ref:"Card",$id:"agentic-2-117",props:{className:"rounded-2xl shadow-none p-6 gap-5 "},children:[{$ref:"Box",$id:"agentic-2-118",props:{className:"flex justify-between items-center"},children:[{$ref:"Heading",$id:"agentic-2-119",props:{children:"Your days, laid out.",className:"font-display font-normal tracking-[-0.03em] text-3xl"}},{$ref:"Button",$id:"agentic-2-120",props:{variant:"outline",className:"rounded-full text-xs"},children:[{$ref:"Icon",$id:"agentic-2-121",props:{name:"SlidersHorizontal",className:"size-4"}},{$ref:"Box",$id:"agentic-2-122",props:{className:"",children:"Edit the pace"}}]}]},{$ref:"Tabs",$id:"agentic-2-123",props:{defaultValue:"plan"},children:[{$ref:"TabsList",$id:"agentic-2-124",props:{variant:"line"},children:[{$ref:"TabsTrigger",$id:"agentic-2-125",props:{value:"plan",children:"Day by day"}},{$ref:"TabsTrigger",$id:"agentic-2-126",props:{value:"map",children:"On the map"}}]}]},{$ref:"Box",$id:"agentic-2-127",props:{className:"divide-y divide-border"},children:[{$ref:"Box",$id:"agentic-2-128",props:{className:"flex gap-4 items-start py-5"},children:[{$ref:"Box",$id:"agentic-2-129",props:{className:"size-10 rounded-full bg-secondary flex justify-center items-center shrink-0"},children:[{$ref:"Text",$id:"agentic-2-130",props:{children:"01",className:"text-xs"}}]},{$ref:"Box",$id:"agentic-2-131",props:{className:"flex-1 space-y-2"},children:[{$ref:"Box",$id:"agentic-2-132",props:{className:"flex items-center justify-between"},children:[{$ref:"Text",$id:"agentic-2-133",props:{children:"Arrive gently",className:"text-sm font-semibold"}},{$ref:"Text",$id:"agentic-2-134",props:{children:"$100",className:"text-xs text-muted-foreground"}}]},{$ref:"Text",$id:"agentic-2-135",props:{children:"Nishiki Market \xB7 Gion lanes \xB7 Tea with a local host",className:"text-xs leading-6 text-muted-foreground"}}]}]},{$ref:"Box",$id:"agentic-2-136",props:{className:"flex gap-4 items-start py-5"},children:[{$ref:"Box",$id:"agentic-2-137",props:{className:"size-10 rounded-full bg-secondary flex justify-center items-center shrink-0"},children:[{$ref:"Text",$id:"agentic-2-138",props:{children:"02",className:"text-xs"}}]},{$ref:"Box",$id:"agentic-2-139",props:{className:"flex-1 space-y-2"},children:[{$ref:"Box",$id:"agentic-2-140",props:{className:"flex items-center justify-between"},children:[{$ref:"Text",$id:"agentic-2-141",props:{children:"A greener kind of morning",className:"text-sm font-semibold"}},{$ref:"Text",$id:"agentic-2-142",props:{children:"$85",className:"text-xs text-muted-foreground"}}]},{$ref:"Text",$id:"agentic-2-143",props:{children:"Early bamboo grove \xB7 Riverside lunch \xB7 An open afternoon",className:"text-xs leading-6 text-muted-foreground"}}]}]},{$ref:"Box",$id:"agentic-2-144",props:{className:"flex gap-4 items-start py-5"},children:[{$ref:"Box",$id:"agentic-2-145",props:{className:"size-10 rounded-full bg-secondary flex justify-center items-center shrink-0"},children:[{$ref:"Text",$id:"agentic-2-146",props:{children:"03",className:"text-xs"}}]},{$ref:"Box",$id:"agentic-2-147",props:{className:"flex-1 space-y-2"},children:[{$ref:"Box",$id:"agentic-2-148",props:{className:"flex items-center justify-between"},children:[{$ref:"Text",$id:"agentic-2-149",props:{children:"Follow your curiosity",className:"text-sm font-semibold"}},{$ref:"Text",$id:"agentic-2-150",props:{children:"$120",className:"text-xs text-muted-foreground"}}]},{$ref:"Text",$id:"agentic-2-151",props:{children:"Small galleries \xB7 Independent shops \xB7 Dinner in Pontocho",className:"text-xs leading-6 text-muted-foreground"}}]}]},{$ref:"Box",$id:"agentic-2-152",props:{className:"flex gap-4 items-start py-5"},children:[{$ref:"Box",$id:"agentic-2-153",props:{className:"size-10 rounded-full bg-secondary flex justify-center items-center shrink-0"},children:[{$ref:"Text",$id:"agentic-2-154",props:{children:"04",className:"text-xs"}}]},{$ref:"Box",$id:"agentic-2-155",props:{className:"flex-1 space-y-2"},children:[{$ref:"Box",$id:"agentic-2-156",props:{className:"flex items-center justify-between"},children:[{$ref:"Text",$id:"agentic-2-157",props:{children:"A little further afield",className:"text-sm font-semibold"}},{$ref:"Text",$id:"agentic-2-158",props:{children:"$110",className:"text-xs text-muted-foreground"}}]},{$ref:"Text",$id:"agentic-2-159",props:{children:"A day in Uji \xB7 Tea fields \xB7 Back before sunset",className:"text-xs leading-6 text-muted-foreground"}}]}]},{$ref:"Box",$id:"agentic-2-160",props:{className:"flex gap-4 items-start py-5"},children:[{$ref:"Box",$id:"agentic-2-161",props:{className:"size-10 rounded-full bg-secondary flex justify-center items-center shrink-0"},children:[{$ref:"Text",$id:"agentic-2-162",props:{children:"05",className:"text-xs"}}]},{$ref:"Box",$id:"agentic-2-163",props:{className:"flex-1 space-y-2"},children:[{$ref:"Box",$id:"agentic-2-164",props:{className:"flex items-center justify-between"},children:[{$ref:"Text",$id:"agentic-2-165",props:{children:"Leave room for one more thing",className:"text-sm font-semibold"}},{$ref:"Text",$id:"agentic-2-166",props:{children:"$65",className:"text-xs text-muted-foreground"}}]},{$ref:"Text",$id:"agentic-2-167",props:{children:"A slow breakfast \xB7 Your favourite neighbourhood \xB7 Homeward",className:"text-xs leading-6 text-muted-foreground"}}]}]}]},{$ref:"Alert",$id:"agentic-2-168",props:{className:"rounded-xl bg-secondary/30"},children:[{$ref:"Icon",$id:"agentic-2-169",props:{name:"Leaf",className:"size-4"}},{$ref:"AlertTitle",$id:"agentic-2-170",props:{children:"Two afternoons are deliberately open"}},{$ref:"AlertDescription",$id:"agentic-2-171",props:{children:"Day 2 and Day 4 leave space for whatever you discover along the way."}}]}]},{$ref:"Card",$id:"agentic-2-172",props:{className:"rounded-2xl shadow-none p-6 gap-5 "},children:[{$ref:"Box",$id:"agentic-2-173",props:{className:"flex gap-3 items-center"},children:[{$ref:"Box",$id:"agentic-2-174",props:{className:"size-8 rounded-full bg-primary text-primary-foreground flex items-center justify-center shrink-0"},children:[{$ref:"Icon",$id:"agentic-2-175",props:{name:"Sparkles",className:"size-4"}}]},{$ref:"Heading",$id:"agentic-2-176",props:{children:"Make a change. Keep the good parts.",className:"font-display font-normal tracking-[-0.03em] text-2xl"}}]},{$ref:"InputGroup",$id:"agentic-2-177",children:[{$ref:"InputGroupInput",$id:"agentic-2-178",props:{defaultValue:"Less temple hopping, more neighbourhood food."}},{$ref:"InputGroupAddon",$id:"agentic-2-179",props:{align:"inline-end"},children:[{$ref:"Button",$id:"agentic-2-180",props:{variant:"default",className:"rounded-full h-8 text-xs"},children:[{$ref:"Icon",$id:"agentic-2-181",props:{name:"ArrowUp",className:"size-4"}},{$ref:"Box",$id:"agentic-2-182",props:{className:"",children:"Update plan"}}]}]}]},{$ref:"Box",$id:"agentic-2-183",props:{className:"flex items-start gap-3 bg-secondary/40 rounded-xl p-4"},children:[{$ref:"Icon",$id:"agentic-2-184",props:{name:"CircleCheck",className:"size-4 mt-1 text-primary"}},{$ref:"Box",$id:"agentic-2-185",props:{className:"space-y-2"},children:[{$ref:"Text",$id:"agentic-2-186",props:{children:"Day 3 updated",className:"font-semibold text-xs"}},{$ref:"Text",$id:"agentic-2-187",props:{children:"A neighbourhood tasting walk replaces the temple circuit. Your stay and open afternoons are unchanged.",className:"text-xs leading-6 text-muted-foreground"}}]}]}]},{$ref:"Card",$id:"agentic-2-188",props:{className:"rounded-2xl shadow-none p-6 gap-5 "},children:[{$ref:"Heading",$id:"agentic-2-189",props:{children:"A budget that still has room.",className:"font-display font-normal tracking-[-0.03em] text-3xl"}},{$ref:"Chart",$id:"agentic-2-190",props:{kind:"bar",categories:["Stay","Food","Experiences","Transport"],series:[{name:"Estimated cost",data:[970,360,240,160]}],yLabel:"$",className:"h-[190px] w-full",legend:!1}},{$ref:"Box",$id:"agentic-2-191",props:{className:"space-y-3 text-xs"},children:[{$ref:"Box",$id:"agentic-2-192",props:{className:"flex justify-between"},children:[{$ref:"Text",$id:"agentic-2-193",props:{children:"Stay",className:"text-inherit"}},{$ref:"Text",$id:"agentic-2-194",props:{children:"$970",className:"text-inherit"}}]},{$ref:"Box",$id:"agentic-2-195",props:{className:"flex justify-between"},children:[{$ref:"Text",$id:"agentic-2-196",props:{children:"Food & coffee",className:"text-inherit"}},{$ref:"Text",$id:"agentic-2-197",props:{children:"$360",className:"text-inherit"}}]},{$ref:"Box",$id:"agentic-2-198",props:{className:"flex justify-between"},children:[{$ref:"Text",$id:"agentic-2-199",props:{children:"Experiences",className:"text-inherit"}},{$ref:"Text",$id:"agentic-2-200",props:{children:"$240",className:"text-inherit"}}]},{$ref:"Box",$id:"agentic-2-201",props:{className:"flex justify-between"},children:[{$ref:"Text",$id:"agentic-2-202",props:{children:"Local transport",className:"text-inherit"}},{$ref:"Text",$id:"agentic-2-203",props:{children:"$160",className:"text-inherit"}}]},{$ref:"Separator",$id:"agentic-2-204"},{$ref:"Box",$id:"agentic-2-205",props:{className:"flex justify-between font-semibold"},children:[{$ref:"Text",$id:"agentic-2-206",props:{children:"Estimated trip total",className:"text-inherit"}},{$ref:"Text",$id:"agentic-2-207",props:{children:"$1,730",className:"text-inherit"}}]},{$ref:"Box",$id:"agentic-2-208",props:{className:"flex justify-between text-muted-foreground"},children:[{$ref:"Text",$id:"agentic-2-209",props:{children:"Left for the unexpected",className:"text-inherit"}},{$ref:"Text",$id:"agentic-2-210",props:{children:"$1,470",className:"text-inherit"}}]}]}]},{$ref:"Card",$id:"agentic-2-211",props:{className:"rounded-2xl shadow-none p-6 gap-5 bg-secondary/35"},children:[{$ref:"Box",$id:"agentic-2-212",props:{className:"flex gap-3 items-center"},children:[{$ref:"Icon",$id:"agentic-2-213",props:{name:"CircleCheck",className:"size-5 text-primary"}},{$ref:"Heading",$id:"agentic-2-214",props:{children:"A trip that feels like you.",className:"font-display font-normal tracking-[-0.03em] text-2xl"}}]},{$ref:"Text",$id:"agentic-2-215",props:{children:"Save this draft to My trips. You can keep refining it with your companion, invite Jamie, and book each stay or experience when you\u2019re ready.",className:"text-xs leading-6 text-muted-foreground"}},{$ref:"Box",$id:"agentic-2-216",props:{className:"flex gap-3"},children:[{$ref:"Button",$id:"agentic-2-217",props:{variant:"default",className:"rounded-full h-11 px-6"},children:[{$ref:"Icon",$id:"agentic-2-218",props:{name:"Check",className:"size-4"}},{$ref:"Box",$id:"agentic-2-219",props:{className:"",children:"Save my trip"}}]},{$ref:"Button",$id:"agentic-2-220",props:{variant:"outline",className:"rounded-full h-11"},children:[{$ref:"Box",$id:"agentic-2-221",props:{className:"",children:"Keep refining"}}]}]},{$ref:"Text",$id:"agentic-2-222",props:{children:"Saving creates a private trip. Bookings happen separately.",className:"text-[10px] text-muted-foreground"}}]}]}]}]},{$ref:"Box",$id:"agentic-2-223",props:{className:"border-t border-border px-12 py-8 flex justify-between"},children:[{$ref:"Text",$id:"agentic-2-224",props:{children:"A little help. A world of possibilities.",className:"font-display text-xl"}},{$ref:"Text",$id:"agentic-2-225",props:{children:"ELSEWHERE / YOUR TRAVEL COMPANION",className:"text-[9px] tracking-widest text-muted-foreground"}}]}]}};var elsewhere_trips_journal_default={id:"elsewhere-trips-journal",name:"C \xB7 The inspiration-led companion",tree:{$ref:"Box",$id:"agentic-3-1",props:{className:"min-h-screen bg-background text-foreground font-sans"},children:[{$snippet:"elsewhere-nav"},{$ref:"Box",$id:"agentic-3-2",props:{className:"px-12 py-10 space-y-9"},children:[{$ref:"Box",$id:"agentic-3-3",props:{className:"space-y-3"},children:[{$ref:"Text",$id:"agentic-3-4",props:{children:"FOLLOW A FEELING",className:"text-[10px] uppercase tracking-[.2em] text-primary"}},{$ref:"Heading",$id:"agentic-3-5",props:{children:"Build a trip from the things you love.",className:"font-display font-normal tracking-[-0.03em] text-5xl leading-[1.08]"}},{$ref:"Text",$id:"agentic-3-6",props:{children:"Choose a few places, moods, and moments. Your companion will find the thread between them.",className:"text-sm leading-7 text-muted-foreground max-w-2xl"}}]},{$ref:"Box",$id:"agentic-3-7",props:{className:"grid grid-cols-[1fr_350px] gap-7 items-start"},children:[{$ref:"Box",$id:"agentic-3-8",props:{className:"space-y-8"},children:[{$ref:"Box",$id:"agentic-3-9",props:{className:"flex justify-between items-center"},children:[{$ref:"Heading",$id:"agentic-3-10",props:{children:"What draws you in?",className:"font-display font-normal tracking-[-0.03em] text-3xl"}},{$ref:"Badge",$id:"agentic-3-11",props:{variant:"secondary",children:"3 things you love",className:"rounded-full px-3 py-1 text-[10px] font-normal"}}]},{$ref:"Box",$id:"agentic-3-12",props:{className:"grid grid-cols-2 gap-5"},children:[{$ref:"Card",$id:"agentic-3-13",props:{className:"p-0 gap-0 rounded-2xl overflow-hidden shadow-none ring-2 ring-primary"},children:[{$ref:"Box",$id:"agentic-3-14",props:{className:"relative overflow-hidden h-[240px]"},children:[{$ref:"Image",$id:"agentic-3-15",props:{src:"/assets/elsewhere-kyoto.jpg",alt:"kyoto travel inspiration",fill:!0,className:"absolute inset-0 w-full h-full"}},{$ref:"Box",$id:"agentic-3-16",props:{className:"absolute top-4 right-4"},children:[{$ref:"Button",$id:"agentic-3-17",props:{variant:"default",className:"rounded-full h-8 text-xs"},children:[{$ref:"Icon",$id:"agentic-3-18",props:{name:"Check",className:"size-4"}},{$ref:"Box",$id:"agentic-3-19",props:{className:"",children:"Added"}}]}]}]},{$ref:"CardContent",$id:"agentic-3-20",props:{className:"p-5 space-y-2"},children:[{$ref:"Heading",$id:"agentic-3-21",props:{children:"Streets worth getting lost in",className:"font-display font-normal tracking-[-0.03em] text-2xl"}},{$ref:"Text",$id:"agentic-3-22",props:{children:"Lanterns, little shops, and the long way home.",className:"text-xs leading-6 text-muted-foreground"}}]}]},{$ref:"Card",$id:"agentic-3-23",props:{className:"p-0 gap-0 rounded-2xl overflow-hidden shadow-none ring-2 ring-primary"},children:[{$ref:"Box",$id:"agentic-3-24",props:{className:"relative overflow-hidden h-[240px]"},children:[{$ref:"Image",$id:"agentic-3-25",props:{src:"/assets/elsewhere-room.jpg",alt:"room travel inspiration",fill:!0,className:"absolute inset-0 w-full h-full"}},{$ref:"Box",$id:"agentic-3-26",props:{className:"absolute top-4 right-4"},children:[{$ref:"Button",$id:"agentic-3-27",props:{variant:"default",className:"rounded-full h-8 text-xs"},children:[{$ref:"Icon",$id:"agentic-3-28",props:{name:"Check",className:"size-4"}},{$ref:"Box",$id:"agentic-3-29",props:{className:"",children:"Added"}}]}]}]},{$ref:"CardContent",$id:"agentic-3-30",props:{className:"p-5 space-y-2"},children:[{$ref:"Heading",$id:"agentic-3-31",props:{children:"Somewhere that feels like a retreat",className:"font-display font-normal tracking-[-0.03em] text-2xl"}},{$ref:"Text",$id:"agentic-3-32",props:{children:"Warm timber, soft light, and a slow breakfast.",className:"text-xs leading-6 text-muted-foreground"}}]}]},{$ref:"Card",$id:"agentic-3-33",props:{className:"p-0 gap-0 rounded-2xl overflow-hidden shadow-none ring-2 ring-primary"},children:[{$ref:"Box",$id:"agentic-3-34",props:{className:"relative overflow-hidden h-[240px]"},children:[{$ref:"Image",$id:"agentic-3-35",props:{src:"/assets/elsewhere-forest.jpg",alt:"forest travel inspiration",fill:!0,className:"absolute inset-0 w-full h-full"}},{$ref:"Box",$id:"agentic-3-36",props:{className:"absolute top-4 right-4"},children:[{$ref:"Button",$id:"agentic-3-37",props:{variant:"default",className:"rounded-full h-8 text-xs"},children:[{$ref:"Icon",$id:"agentic-3-38",props:{name:"Check",className:"size-4"}},{$ref:"Box",$id:"agentic-3-39",props:{className:"",children:"Added"}}]}]}]},{$ref:"CardContent",$id:"agentic-3-40",props:{className:"p-5 space-y-2"},children:[{$ref:"Heading",$id:"agentic-3-41",props:{children:"A quieter kind of adventure",className:"font-display font-normal tracking-[-0.03em] text-2xl"}},{$ref:"Text",$id:"agentic-3-42",props:{children:"Green paths. Fresh air. No rush.",className:"text-xs leading-6 text-muted-foreground"}}]}]},{$ref:"Card",$id:"agentic-3-43",props:{className:"p-0 gap-0 rounded-2xl overflow-hidden shadow-none "},children:[{$ref:"Box",$id:"agentic-3-44",props:{className:"relative overflow-hidden h-[240px]"},children:[{$ref:"Image",$id:"agentic-3-45",props:{src:"/assets/elsewhere-japan.jpg",alt:"japan travel inspiration",fill:!0,className:"absolute inset-0 w-full h-full"}},{$ref:"Box",$id:"agentic-3-46",props:{className:"absolute top-4 right-4"},children:[{$ref:"Button",$id:"agentic-3-47",props:{variant:"secondary",className:"rounded-full h-8 text-xs"},children:[{$ref:"Icon",$id:"agentic-3-48",props:{name:"Plus",className:"size-4"}},{$ref:"Box",$id:"agentic-3-49",props:{className:"",children:"This feels like me"}}]}]}]},{$ref:"CardContent",$id:"agentic-3-50",props:{className:"p-5 space-y-2"},children:[{$ref:"Heading",$id:"agentic-3-51",props:{children:"Stay out a little later",className:"font-display font-normal tracking-[-0.03em] text-2xl"}},{$ref:"Text",$id:"agentic-3-52",props:{children:"Neighbourhood bars and another good story.",className:"text-xs leading-6 text-muted-foreground"}}]}]}]},{$ref:"Box",$id:"agentic-3-53",props:{className:"flex gap-2 flex-wrap"},children:[{$ref:"Button",$id:"agentic-3-54",props:{variant:"outline",className:"rounded-full text-xs"},children:[{$ref:"Icon",$id:"agentic-3-55",props:{name:"RefreshCw",className:"size-4"}},{$ref:"Box",$id:"agentic-3-56",props:{className:"",children:"More like these"}}]},{$ref:"Button",$id:"agentic-3-57",props:{variant:"outline",className:"rounded-full text-xs"},children:[{$ref:"Icon",$id:"agentic-3-58",props:{name:"Bookmark",className:"size-4"}},{$ref:"Box",$id:"agentic-3-59",props:{className:"",children:"Add a saved place"}}]},{$ref:"Button",$id:"agentic-3-60",props:{variant:"outline",className:"rounded-full text-xs"},children:[{$ref:"Icon",$id:"agentic-3-61",props:{name:"ImagePlus",className:"size-4"}},{$ref:"Box",$id:"agentic-3-62",props:{className:"",children:"Upload inspiration"}}]}]},{$ref:"Card",$id:"agentic-3-63",props:{className:"rounded-2xl shadow-none p-6 gap-5 "},children:[{$ref:"Box",$id:"agentic-3-64",props:{className:"flex gap-3 items-center"},children:[{$ref:"Box",$id:"agentic-3-65",props:{className:"size-8 rounded-full bg-primary text-primary-foreground flex items-center justify-center shrink-0"},children:[{$ref:"Icon",$id:"agentic-3-66",props:{name:"Sparkles",className:"size-4"}}]},{$ref:"Heading",$id:"agentic-3-67",props:{children:"I\u2019m seeing a lovely little pattern.",className:"font-display font-normal tracking-[-0.03em] text-3xl"}}]},{$ref:"Text",$id:"agentic-3-68",props:{children:"You\u2019re drawn to atmospheric streets, quiet places to stay, and time outdoors. Kyoto can give you all three without moving hotels.",className:"text-sm leading-7 text-muted-foreground"}},{$ref:"Box",$id:"agentic-3-69",props:{className:"relative overflow-hidden h-[220px] rounded-xl"},children:[{$ref:"Image",$id:"agentic-3-70",props:{src:"/assets/elsewhere-kyoto.jpg",alt:"kyoto travel inspiration",fill:!0,className:"absolute inset-0 w-full h-full"}}]},{$ref:"Box",$id:"agentic-3-71",props:{className:"flex justify-between items-center"},children:[{$ref:"Box",$id:"agentic-3-72",props:{className:"space-y-1"},children:[{$ref:"Heading",$id:"agentic-3-73",props:{children:"Kyoto is your kind of elsewhere.",className:"font-display font-normal tracking-[-0.03em] text-2xl"}},{$ref:"Text",$id:"agentic-3-74",props:{children:"Walkable neighbourhoods \xB7 Small discoveries \xB7 A gentle pace",className:"text-xs text-muted-foreground"}}]},{$ref:"Button",$id:"agentic-3-75",props:{variant:"default",className:"rounded-full text-xs"},children:[{$ref:"Icon",$id:"agentic-3-76",props:{name:"Check",className:"size-4"}},{$ref:"Box",$id:"agentic-3-77",props:{className:"",children:"Let\u2019s go with Kyoto"}}]}]}]},{$ref:"Card",$id:"agentic-3-78",props:{className:"rounded-2xl shadow-none p-6 gap-5 "},children:[{$ref:"Heading",$id:"agentic-3-79",props:{children:"A few little details.",className:"font-display font-normal tracking-[-0.03em] text-3xl"}},{$ref:"Box",$id:"agentic-3-80",props:{className:"grid grid-cols-3 gap-4"},children:[{$ref:"Field",$id:"agentic-3-81",children:[{$ref:"FieldLabel",$id:"agentic-3-82",props:{children:"Dates"}},{$ref:"Input",$id:"agentic-3-83",props:{defaultValue:"12\u201317 October",className:"bg-card"}}]},{$ref:"Field",$id:"agentic-3-84",children:[{$ref:"FieldLabel",$id:"agentic-3-85",props:{children:"Travellers"}},{$ref:"Input",$id:"agentic-3-86",props:{defaultValue:"2 people",className:"bg-card"}}]},{$ref:"Field",$id:"agentic-3-87",children:[{$ref:"FieldLabel",$id:"agentic-3-88",props:{children:"Budget"}},{$ref:"Input",$id:"agentic-3-89",props:{defaultValue:"$3,200",className:"bg-card"}}]}]},{$ref:"Button",$id:"agentic-3-90",props:{variant:"default",className:"rounded-full h-11 self-start"},children:[{$ref:"Icon",$id:"agentic-3-91",props:{name:"Sparkles",className:"size-4"}},{$ref:"Box",$id:"agentic-3-92",props:{className:"",children:"Turn this into a trip"}}]}]},{$ref:"Card",$id:"agentic-3-93",props:{className:"rounded-2xl shadow-none p-6 gap-5 "},children:[{$ref:"Box",$id:"agentic-3-94",props:{className:"flex justify-between items-center"},children:[{$ref:"Heading",$id:"agentic-3-95",props:{children:"Your collection becomes a journey.",className:"font-display font-normal tracking-[-0.03em] text-3xl"}},{$ref:"Badge",$id:"agentic-3-96",props:{variant:"secondary",children:"Draft 01",className:"rounded-full px-3 py-1 text-[10px] font-normal"}}]},{$ref:"Text",$id:"agentic-3-97",props:{children:"The places you chose, connected into days that make sense together.",className:"text-sm text-muted-foreground"}},{$ref:"Box",$id:"agentic-3-98",props:{className:"relative h-[650px] rounded-xl overflow-hidden"},children:[{$ref:"Image",$id:"agentic-3-99",props:{src:"/assets/elsewhere-kyoto-map.svg",alt:"An illustrated route connecting your Kyoto discoveries",fill:!0,className:"absolute inset-0 w-full h-full"}}]},{$ref:"Box",$id:"agentic-3-100",props:{className:"divide-y divide-border"},children:[{$ref:"Box",$id:"agentic-3-101",props:{className:"flex gap-4 items-start py-5"},children:[{$ref:"Box",$id:"agentic-3-102",props:{className:"size-10 rounded-full bg-secondary flex justify-center items-center shrink-0"},children:[{$ref:"Text",$id:"agentic-3-103",props:{children:"01",className:"text-xs"}}]},{$ref:"Box",$id:"agentic-3-104",props:{className:"flex-1 space-y-2"},children:[{$ref:"Box",$id:"agentic-3-105",props:{className:"flex items-center justify-between"},children:[{$ref:"Text",$id:"agentic-3-106",props:{children:"Arrive gently",className:"text-sm font-semibold"}},{$ref:"Text",$id:"agentic-3-107",props:{children:"$100",className:"text-xs text-muted-foreground"}}]},{$ref:"Text",$id:"agentic-3-108",props:{children:"Nishiki Market \xB7 Gion lanes \xB7 Tea with a local host",className:"text-xs leading-6 text-muted-foreground"}}]}]},{$ref:"Box",$id:"agentic-3-109",props:{className:"flex gap-4 items-start py-5"},children:[{$ref:"Box",$id:"agentic-3-110",props:{className:"size-10 rounded-full bg-secondary flex justify-center items-center shrink-0"},children:[{$ref:"Text",$id:"agentic-3-111",props:{children:"02",className:"text-xs"}}]},{$ref:"Box",$id:"agentic-3-112",props:{className:"flex-1 space-y-2"},children:[{$ref:"Box",$id:"agentic-3-113",props:{className:"flex items-center justify-between"},children:[{$ref:"Text",$id:"agentic-3-114",props:{children:"A greener kind of morning",className:"text-sm font-semibold"}},{$ref:"Text",$id:"agentic-3-115",props:{children:"$85",className:"text-xs text-muted-foreground"}}]},{$ref:"Text",$id:"agentic-3-116",props:{children:"Early bamboo grove \xB7 Riverside lunch \xB7 An open afternoon",className:"text-xs leading-6 text-muted-foreground"}}]}]},{$ref:"Box",$id:"agentic-3-117",props:{className:"flex gap-4 items-start py-5"},children:[{$ref:"Box",$id:"agentic-3-118",props:{className:"size-10 rounded-full bg-secondary flex justify-center items-center shrink-0"},children:[{$ref:"Text",$id:"agentic-3-119",props:{children:"03",className:"text-xs"}}]},{$ref:"Box",$id:"agentic-3-120",props:{className:"flex-1 space-y-2"},children:[{$ref:"Box",$id:"agentic-3-121",props:{className:"flex items-center justify-between"},children:[{$ref:"Text",$id:"agentic-3-122",props:{children:"Follow your curiosity",className:"text-sm font-semibold"}},{$ref:"Text",$id:"agentic-3-123",props:{children:"$120",className:"text-xs text-muted-foreground"}}]},{$ref:"Text",$id:"agentic-3-124",props:{children:"Small galleries \xB7 Independent shops \xB7 Dinner in Pontocho",className:"text-xs leading-6 text-muted-foreground"}}]}]},{$ref:"Box",$id:"agentic-3-125",props:{className:"flex gap-4 items-start py-5"},children:[{$ref:"Box",$id:"agentic-3-126",props:{className:"size-10 rounded-full bg-secondary flex justify-center items-center shrink-0"},children:[{$ref:"Text",$id:"agentic-3-127",props:{children:"04",className:"text-xs"}}]},{$ref:"Box",$id:"agentic-3-128",props:{className:"flex-1 space-y-2"},children:[{$ref:"Box",$id:"agentic-3-129",props:{className:"flex items-center justify-between"},children:[{$ref:"Text",$id:"agentic-3-130",props:{children:"A little further afield",className:"text-sm font-semibold"}},{$ref:"Text",$id:"agentic-3-131",props:{children:"$110",className:"text-xs text-muted-foreground"}}]},{$ref:"Text",$id:"agentic-3-132",props:{children:"A day in Uji \xB7 Tea fields \xB7 Back before sunset",className:"text-xs leading-6 text-muted-foreground"}}]}]},{$ref:"Box",$id:"agentic-3-133",props:{className:"flex gap-4 items-start py-5"},children:[{$ref:"Box",$id:"agentic-3-134",props:{className:"size-10 rounded-full bg-secondary flex justify-center items-center shrink-0"},children:[{$ref:"Text",$id:"agentic-3-135",props:{children:"05",className:"text-xs"}}]},{$ref:"Box",$id:"agentic-3-136",props:{className:"flex-1 space-y-2"},children:[{$ref:"Box",$id:"agentic-3-137",props:{className:"flex items-center justify-between"},children:[{$ref:"Text",$id:"agentic-3-138",props:{children:"Leave room for one more thing",className:"text-sm font-semibold"}},{$ref:"Text",$id:"agentic-3-139",props:{children:"$65",className:"text-xs text-muted-foreground"}}]},{$ref:"Text",$id:"agentic-3-140",props:{children:"A slow breakfast \xB7 Your favourite neighbourhood \xB7 Homeward",className:"text-xs leading-6 text-muted-foreground"}}]}]}]}]},{$ref:"Card",$id:"agentic-3-141",props:{className:"rounded-2xl shadow-none p-6 gap-5 bg-secondary/35"},children:[{$ref:"Box",$id:"agentic-3-142",props:{className:"flex gap-3 items-center"},children:[{$ref:"Icon",$id:"agentic-3-143",props:{name:"CircleCheck",className:"size-5 text-primary"}},{$ref:"Heading",$id:"agentic-3-144",props:{children:"A trip that feels like you.",className:"font-display font-normal tracking-[-0.03em] text-2xl"}}]},{$ref:"Text",$id:"agentic-3-145",props:{children:"Save this draft to My trips. You can keep refining it with your companion, invite Jamie, and book each stay or experience when you\u2019re ready.",className:"text-xs leading-6 text-muted-foreground"}},{$ref:"Box",$id:"agentic-3-146",props:{className:"flex gap-3"},children:[{$ref:"Button",$id:"agentic-3-147",props:{variant:"default",className:"rounded-full h-11 px-6"},children:[{$ref:"Icon",$id:"agentic-3-148",props:{name:"Check",className:"size-4"}},{$ref:"Box",$id:"agentic-3-149",props:{className:"",children:"Save my trip"}}]},{$ref:"Button",$id:"agentic-3-150",props:{variant:"outline",className:"rounded-full h-11"},children:[{$ref:"Box",$id:"agentic-3-151",props:{className:"",children:"Keep refining"}}]}]},{$ref:"Text",$id:"agentic-3-152",props:{children:"Saving creates a private trip. Bookings happen separately.",className:"text-[10px] text-muted-foreground"}}]}]},{$ref:"Box",$id:"agentic-3-153",props:{className:"space-y-6"},children:[{$ref:"Card",$id:"agentic-3-154",props:{className:"rounded-2xl shadow-none p-6 gap-5 "},children:[{$ref:"Box",$id:"agentic-3-155",props:{className:"flex gap-3 items-center"},children:[{$ref:"Box",$id:"agentic-3-156",props:{className:"size-8 rounded-full bg-primary text-primary-foreground flex items-center justify-center shrink-0"},children:[{$ref:"Icon",$id:"agentic-3-157",props:{name:"Sparkles",className:"size-4"}}]},{$ref:"Box",$id:"agentic-3-158",props:{className:""},children:[{$ref:"Text",$id:"agentic-3-159",props:{children:"Your travel companion",className:"font-semibold text-sm"}},{$ref:"Text",$id:"agentic-3-160",props:{children:"Learning what feels like you",className:"text-[10px] text-muted-foreground"}}]}]},{$ref:"Message",$id:"agentic-3-161",props:{align:"start",className:"w-full"},children:[{$ref:"MessageAvatar",$id:"agentic-3-162",children:[{$ref:"Box",$id:"agentic-3-163",props:{className:"size-8 rounded-full bg-primary text-primary-foreground flex items-center justify-center shrink-0"},children:[{$ref:"Icon",$id:"agentic-3-164",props:{name:"Sparkles",className:"size-4"}}]}]},{$ref:"Box",$id:"agentic-3-165",props:{className:"min-w-0 flex-1 space-y-2"},children:[{$ref:"MessageHeader",$id:"agentic-3-166",props:{className:"text-xs text-muted-foreground"},children:[{$ref:"Text",$id:"agentic-3-167",props:{children:"Elsewhere",className:"text-inherit"}}]},{$ref:"MessageContent",$id:"agentic-3-168",props:{className:"space-y-4"},children:[{$ref:"Text",$id:"agentic-3-169",props:{children:"Start with anything that catches your eye. A place, a room, even just a feeling.",className:"text-sm leading-7"}}]}]}]},{$ref:"Box",$id:"agentic-3-170",props:{className:"flex flex-wrap gap-2"},children:[{$ref:"Badge",$id:"agentic-3-171",props:{variant:"secondary",children:"Quiet corners",className:"rounded-full px-3 py-1 text-[10px] font-normal"}},{$ref:"Badge",$id:"agentic-3-172",props:{variant:"secondary",children:"Beautiful stays",className:"rounded-full px-3 py-1 text-[10px] font-normal"}},{$ref:"Badge",$id:"agentic-3-173",props:{variant:"secondary",children:"A little greenery",className:"rounded-full px-3 py-1 text-[10px] font-normal"}}]},{$ref:"Separator",$id:"agentic-3-174"},{$ref:"Message",$id:"agentic-3-175",props:{align:"end",className:"w-full"},children:[{$ref:"MessageAvatar",$id:"agentic-3-176",children:[{$ref:"Avatar",$id:"agentic-3-177",props:{className:"size-8"},children:[{$ref:"AvatarFallback",$id:"agentic-3-178",props:{children:"AL",className:"bg-secondary text-[10px]"}}]}]},{$ref:"Box",$id:"agentic-3-179",props:{className:"min-w-0 flex-1 space-y-2"},children:[{$ref:"MessageHeader",$id:"agentic-3-180",props:{className:"text-xs text-muted-foreground"},children:[{$ref:"Text",$id:"agentic-3-181",props:{children:"You",className:"text-inherit"}}]},{$ref:"MessageContent",$id:"agentic-3-182",props:{className:"bg-secondary/65 rounded-2xl px-5 py-4"},children:[{$ref:"Text",$id:"agentic-3-183",props:{children:"These are lovely. We\u2019d like to avoid changing hotels.",className:"text-sm leading-7"}}]}]}]},{$ref:"Message",$id:"agentic-3-184",props:{align:"start",className:"w-full"},children:[{$ref:"MessageAvatar",$id:"agentic-3-185",children:[{$ref:"Box",$id:"agentic-3-186",props:{className:"size-8 rounded-full bg-primary text-primary-foreground flex items-center justify-center shrink-0"},children:[{$ref:"Icon",$id:"agentic-3-187",props:{name:"Sparkles",className:"size-4"}}]}]},{$ref:"Box",$id:"agentic-3-188",props:{className:"min-w-0 flex-1 space-y-2"},children:[{$ref:"MessageHeader",$id:"agentic-3-189",props:{className:"text-xs text-muted-foreground"},children:[{$ref:"Text",$id:"agentic-3-190",props:{children:"Elsewhere",className:"text-inherit"}}]},{$ref:"MessageContent",$id:"agentic-3-191",props:{className:"space-y-4"},children:[{$ref:"Text",$id:"agentic-3-192",props:{children:"One thoughtful base, then. I\u2019ll keep the discoveries close enough for easy day trips.",className:"text-sm leading-7"}}]}]}]},{$ref:"Box",$id:"agentic-3-193",props:{className:"space-y-2 bg-secondary/40 rounded-xl p-4"},children:[{$ref:"Text",$id:"agentic-3-194",props:{children:"ADDED TO YOUR BRIEF",className:"text-[9px] tracking-widest text-primary"}},{$ref:"Text",$id:"agentic-3-195",props:{children:"One base \xB7 Easy day trips \xB7 Unhurried pace",className:"text-xs leading-6"}}]}]},{$ref:"Card",$id:"agentic-3-196",props:{className:"rounded-2xl shadow-none p-6 gap-5 "},children:[{$ref:"Text",$id:"agentic-3-197",props:{children:"YOUR COLLECTION",className:"text-[9px] tracking-widest text-muted-foreground"}},{$ref:"Box",$id:"agentic-3-198",props:{className:"flex gap-3 items-center"},children:[{$ref:"Box",$id:"agentic-3-199",props:{className:"relative overflow-hidden size-14 rounded-lg shrink-0"},children:[{$ref:"Image",$id:"agentic-3-200",props:{src:"/assets/elsewhere-kyoto.jpg",alt:"kyoto travel inspiration",fill:!0,className:"absolute inset-0 w-full h-full"}}]},{$ref:"Text",$id:"agentic-3-201",props:{children:"Kyoto\u2019s old streets",className:"text-xs"}}]},{$ref:"Box",$id:"agentic-3-202",props:{className:"flex gap-3 items-center"},children:[{$ref:"Box",$id:"agentic-3-203",props:{className:"relative overflow-hidden size-14 rounded-lg shrink-0"},children:[{$ref:"Image",$id:"agentic-3-204",props:{src:"/assets/elsewhere-room.jpg",alt:"room travel inspiration",fill:!0,className:"absolute inset-0 w-full h-full"}}]},{$ref:"Text",$id:"agentic-3-205",props:{children:"A warm, quiet guest room",className:"text-xs"}}]},{$ref:"Box",$id:"agentic-3-206",props:{className:"flex gap-3 items-center"},children:[{$ref:"Box",$id:"agentic-3-207",props:{className:"relative overflow-hidden size-14 rounded-lg shrink-0"},children:[{$ref:"Image",$id:"agentic-3-208",props:{src:"/assets/elsewhere-forest.jpg",alt:"forest travel inspiration",fill:!0,className:"absolute inset-0 w-full h-full"}}]},{$ref:"Text",$id:"agentic-3-209",props:{children:"A little time in the green",className:"text-xs"}}]}]},{$ref:"Card",$id:"agentic-3-210",props:{className:"rounded-2xl shadow-none p-6 gap-5 bg-card"},children:[{$ref:"Textarea",$id:"agentic-3-211",props:{placeholder:"A little more about us\u2026",className:"border-0 shadow-none resize-none p-0 min-h-[62px] bg-transparent text-sm"}},{$ref:"Box",$id:"agentic-3-212",props:{className:"flex justify-between items-center"},children:[{$ref:"Button",$id:"agentic-3-213",props:{variant:"ghost",className:"rounded-full px-0 text-xs"},children:[{$ref:"Icon",$id:"agentic-3-214",props:{name:"Paperclip",className:"size-4"}},{$ref:"Box",$id:"agentic-3-215",props:{className:"",children:"Add inspiration"}}]},{$ref:"Button",$id:"agentic-3-216",props:{variant:"default",className:"rounded-full h-9"},children:[{$ref:"Icon",$id:"agentic-3-217",props:{name:"ArrowUp",className:"size-4"}},{$ref:"Box",$id:"agentic-3-218",props:{className:"",children:"Send"}}]}]}]},{$ref:"Card",$id:"agentic-3-219",props:{className:"rounded-2xl shadow-none p-6 gap-5 bg-secondary/30"},children:[{$ref:"Icon",$id:"agentic-3-220",props:{name:"Heart",className:"size-6 text-primary"}},{$ref:"Heading",$id:"agentic-3-221",props:{children:`Your taste,
43
43
  not a template.`,className:"font-display font-normal tracking-[-0.03em] text-3xl whitespace-pre-line"}},{$ref:"Text",$id:"agentic-3-222",props:{children:"Every choice helps your companion make better suggestions. Remove a saved moment any time and the plan can adapt.",className:"text-xs leading-7 text-muted-foreground"}}]}]}]}]},{$ref:"Box",$id:"agentic-3-223",props:{className:"border-t border-border px-12 py-8 flex justify-between"},children:[{$ref:"Text",$id:"agentic-3-224",props:{children:"A little help. A world of possibilities.",className:"font-display text-xl"}},{$ref:"Text",$id:"agentic-3-225",props:{children:"ELSEWHERE / YOUR TRAVEL COMPANION",className:"text-[9px] tracking-widest text-muted-foreground"}}]}]}};var elsewhere_trips_library_default={id:"elsewhere-trips-library",name:"A \xB7 The conversational concierge",tree:{$ref:"Box",$id:"agentic-1-1",props:{className:"min-h-screen bg-background text-foreground font-sans"},children:[{$snippet:"elsewhere-nav"},{$ref:"Box",$id:"agentic-1-2",props:{className:"px-12 pt-10 pb-8"},children:[{$ref:"Box",$id:"agentic-1-3",props:{className:"space-y-3"},children:[{$ref:"Text",$id:"agentic-1-4",props:{children:"YOUR PERSONAL TRAVEL COMPANION",className:"text-[10px] uppercase tracking-[.2em] text-primary"}},{$ref:"Heading",$id:"agentic-1-5",props:{children:"Tell us what a good trip feels like.",className:"font-display font-normal tracking-[-0.03em] text-5xl leading-[1.08]"}},{$ref:"Text",$id:"agentic-1-6",props:{children:"A conversation, a few thoughtful suggestions, and a plan that gets more you with every turn.",className:"text-sm leading-7 text-muted-foreground max-w-2xl"}}]}]},{$ref:"Box",$id:"agentic-1-7",props:{className:"grid grid-cols-[1fr_410px] gap-9 px-12 pb-10"},children:[{$ref:"Box",$id:"agentic-1-8",props:{className:"space-y-7"},children:[{$ref:"Box",$id:"agentic-1-9",props:{className:"flex items-center justify-between pb-3 border-b border-border"},children:[{$ref:"Box",$id:"agentic-1-10",props:{className:"flex gap-3 items-center"},children:[{$ref:"Box",$id:"agentic-1-11",props:{className:"size-8 rounded-full bg-primary text-primary-foreground flex items-center justify-center shrink-0"},children:[{$ref:"Icon",$id:"agentic-1-12",props:{name:"Sparkles",className:"size-4"}}]},{$ref:"Box",$id:"agentic-1-13",props:{className:""},children:[{$ref:"Text",$id:"agentic-1-14",props:{children:"Elsewhere companion",className:"font-semibold text-sm"}},{$ref:"Text",$id:"agentic-1-15",props:{children:"Planning together \xB7 Kyoto",className:"text-[10px] text-muted-foreground"}}]}]},{$ref:"Button",$id:"agentic-1-16",props:{variant:"ghost",className:"rounded-full text-xs"},children:[{$ref:"Icon",$id:"agentic-1-17",props:{name:"RotateCcw",className:"size-4"}},{$ref:"Box",$id:"agentic-1-18",props:{className:"",children:"Start fresh"}}]}]},{$ref:"MessageGroup",$id:"agentic-1-19",props:{className:"space-y-7"},children:[{$ref:"Message",$id:"agentic-1-20",props:{align:"end",className:"w-full"},children:[{$ref:"MessageAvatar",$id:"agentic-1-21",children:[{$ref:"Avatar",$id:"agentic-1-22",props:{className:"size-8"},children:[{$ref:"AvatarFallback",$id:"agentic-1-23",props:{children:"AL",className:"bg-secondary text-[10px]"}}]}]},{$ref:"Box",$id:"agentic-1-24",props:{className:"min-w-0 flex-1 space-y-2"},children:[{$ref:"MessageHeader",$id:"agentic-1-25",props:{className:"text-xs text-muted-foreground"},children:[{$ref:"Text",$id:"agentic-1-26",props:{children:"You",className:"text-inherit"}}]},{$ref:"MessageContent",$id:"agentic-1-27",props:{className:"bg-secondary/65 rounded-2xl px-5 py-4"},children:[{$ref:"Text",$id:"agentic-1-28",props:{children:"Jamie and I have five nights in October. We love food, quiet streets and a beautiful little place to stay. Somewhere in Japan, around $3,200 for both of us.",className:"text-sm leading-7"}}]}]}]},{$ref:"Message",$id:"agentic-1-29",props:{align:"start",className:"w-full"},children:[{$ref:"MessageAvatar",$id:"agentic-1-30",children:[{$ref:"Box",$id:"agentic-1-31",props:{className:"size-8 rounded-full bg-primary text-primary-foreground flex items-center justify-center shrink-0"},children:[{$ref:"Icon",$id:"agentic-1-32",props:{name:"Sparkles",className:"size-4"}}]}]},{$ref:"Box",$id:"agentic-1-33",props:{className:"min-w-0 flex-1 space-y-2"},children:[{$ref:"MessageHeader",$id:"agentic-1-34",props:{className:"text-xs text-muted-foreground"},children:[{$ref:"Text",$id:"agentic-1-35",props:{children:"Elsewhere",className:"text-inherit"}}]},{$ref:"MessageContent",$id:"agentic-1-36",props:{className:"space-y-4"},children:[{$ref:"Text",$id:"agentic-1-37",props:{children:"Kyoto feels like a lovely fit. Before I shape the week: do you prefer slow mornings, or getting out early to beat the crowds?",className:"text-sm leading-7"}},{$ref:"Box",$id:"agentic-1-38",props:{className:"flex gap-2"},children:[{$ref:"Button",$id:"agentic-1-39",props:{variant:"secondary",className:"rounded-full text-xs"},children:[{$ref:"Icon",$id:"agentic-1-40",props:{name:"Coffee",className:"size-4"}},{$ref:"Box",$id:"agentic-1-41",props:{className:"",children:"Slow mornings"}}]},{$ref:"Button",$id:"agentic-1-42",props:{variant:"outline",className:"rounded-full text-xs"},children:[{$ref:"Icon",$id:"agentic-1-43",props:{name:"Sunrise",className:"size-4"}},{$ref:"Box",$id:"agentic-1-44",props:{className:"",children:"Early adventures"}}]},{$ref:"Button",$id:"agentic-1-45",props:{variant:"outline",className:"rounded-full text-xs"},children:[{$ref:"Box",$id:"agentic-1-46",props:{className:"",children:"A little of both"}}]}]}]}]}]},{$ref:"Message",$id:"agentic-1-47",props:{align:"end",className:"w-full"},children:[{$ref:"MessageAvatar",$id:"agentic-1-48",children:[{$ref:"Avatar",$id:"agentic-1-49",props:{className:"size-8"},children:[{$ref:"AvatarFallback",$id:"agentic-1-50",props:{children:"AL",className:"bg-secondary text-[10px]"}}]}]},{$ref:"Box",$id:"agentic-1-51",props:{className:"min-w-0 flex-1 space-y-2"},children:[{$ref:"MessageHeader",$id:"agentic-1-52",props:{className:"text-xs text-muted-foreground"},children:[{$ref:"Text",$id:"agentic-1-53",props:{children:"You",className:"text-inherit"}}]},{$ref:"MessageContent",$id:"agentic-1-54",props:{className:"bg-secondary/65 rounded-2xl px-5 py-4"},children:[{$ref:"Text",$id:"agentic-1-55",props:{children:"A little of both. One early start is fine, but please leave space to wander.",className:"text-sm leading-7"}}]}]}]},{$ref:"Message",$id:"agentic-1-56",props:{align:"start",className:"w-full"},children:[{$ref:"MessageAvatar",$id:"agentic-1-57",children:[{$ref:"Box",$id:"agentic-1-58",props:{className:"size-8 rounded-full bg-primary text-primary-foreground flex items-center justify-center shrink-0"},children:[{$ref:"Icon",$id:"agentic-1-59",props:{name:"Sparkles",className:"size-4"}}]}]},{$ref:"Box",$id:"agentic-1-60",props:{className:"min-w-0 flex-1 space-y-2"},children:[{$ref:"MessageHeader",$id:"agentic-1-61",props:{className:"text-xs text-muted-foreground"},children:[{$ref:"Text",$id:"agentic-1-62",props:{children:"Elsewhere",className:"text-inherit"}}]},{$ref:"MessageContent",$id:"agentic-1-63",props:{className:"space-y-4"},children:[{$ref:"Text",$id:"agentic-1-64",props:{children:"A good balance. I\u2019ll keep you in a walkable neighbourhood, group the bigger sights into one early morning, and leave two afternoons open.",className:"text-sm leading-7"}},{$ref:"Card",$id:"agentic-1-65",props:{className:"rounded-2xl shadow-none p-6 gap-5 bg-muted/40"},children:[{$ref:"Box",$id:"agentic-1-66",props:{className:"flex gap-2 items-center"},children:[{$ref:"Icon",$id:"agentic-1-67",props:{name:"Compass",className:"size-4"}},{$ref:"Text",$id:"agentic-1-68",props:{children:"A little research, taken care of.",className:"font-semibold text-sm"}}]},{$ref:"Box",$id:"agentic-1-69",props:{className:"divide-y divide-border"},children:[{$ref:"Box",$id:"agentic-1-70",props:{className:"flex items-center justify-between gap-3 py-3"},children:[{$ref:"Box",$id:"agentic-1-71",props:{className:"flex items-center gap-3"},children:[{$ref:"Icon",$id:"agentic-1-72",props:{name:"CircleCheck",className:"size-4 text-primary"}},{$ref:"Text",$id:"agentic-1-73",props:{children:"Matched your pace and interests",className:"text-xs"}}]},{$ref:"Text",$id:"agentic-1-74",props:{children:"Done",className:"text-[10px] text-muted-foreground"}}]},{$ref:"Box",$id:"agentic-1-75",props:{className:"flex items-center justify-between gap-3 py-3"},children:[{$ref:"Box",$id:"agentic-1-76",props:{className:"flex items-center gap-3"},children:[{$ref:"Icon",$id:"agentic-1-77",props:{name:"CircleCheck",className:"size-4 text-primary"}},{$ref:"Text",$id:"agentic-1-78",props:{children:"Compared 6 neighbourhood stays",className:"text-xs"}}]},{$ref:"Text",$id:"agentic-1-79",props:{children:"Done",className:"text-[10px] text-muted-foreground"}}]},{$ref:"Box",$id:"agentic-1-80",props:{className:"flex items-center justify-between gap-3 py-3"},children:[{$ref:"Box",$id:"agentic-1-81",props:{className:"flex items-center gap-3"},children:[{$ref:"Icon",$id:"agentic-1-82",props:{name:"CircleCheck",className:"size-4 text-primary"}},{$ref:"Text",$id:"agentic-1-83",props:{children:"Grouped nearby discoveries",className:"text-xs"}}]},{$ref:"Text",$id:"agentic-1-84",props:{children:"Done",className:"text-[10px] text-muted-foreground"}}]},{$ref:"Box",$id:"agentic-1-85",props:{className:"flex items-center justify-between gap-3 py-3"},children:[{$ref:"Box",$id:"agentic-1-86",props:{className:"flex items-center gap-3"},children:[{$ref:"Icon",$id:"agentic-1-87",props:{name:"CircleCheck",className:"size-4 text-primary"}},{$ref:"Text",$id:"agentic-1-88",props:{children:"Balanced the plan with your budget",className:"text-xs"}}]},{$ref:"Text",$id:"agentic-1-89",props:{children:"Done",className:"text-[10px] text-muted-foreground"}}]}]},{$ref:"Text",$id:"agentic-1-90",props:{children:"Suggestions prepared \xB7 Nothing booked",className:"text-[10px] text-muted-foreground"}}]}]}]}]},{$ref:"Message",$id:"agentic-1-91",props:{align:"start",className:"w-full"},children:[{$ref:"MessageAvatar",$id:"agentic-1-92",children:[{$ref:"Box",$id:"agentic-1-93",props:{className:"size-8 rounded-full bg-primary text-primary-foreground flex items-center justify-center shrink-0"},children:[{$ref:"Icon",$id:"agentic-1-94",props:{name:"Sparkles",className:"size-4"}}]}]},{$ref:"Box",$id:"agentic-1-95",props:{className:"min-w-0 flex-1 space-y-2"},children:[{$ref:"MessageHeader",$id:"agentic-1-96",props:{className:"text-xs text-muted-foreground"},children:[{$ref:"Text",$id:"agentic-1-97",props:{children:"Elsewhere",className:"text-inherit"}}]},{$ref:"MessageContent",$id:"agentic-1-98",props:{className:"space-y-4"},children:[{$ref:"Text",$id:"agentic-1-99",props:{children:"Two stays I think you\u2019ll love. Both keep the city close and the pace gentle.",className:"text-sm leading-7"}},{$ref:"Box",$id:"agentic-1-100",props:{className:"grid grid-cols-2 gap-4"},children:[{$ref:"Card",$id:"agentic-1-101",props:{className:"rounded-xl overflow-hidden p-0 gap-0 shadow-none"},children:[{$ref:"Box",$id:"agentic-1-102",props:{className:"relative overflow-hidden h-[155px]"},children:[{$ref:"Image",$id:"agentic-1-103",props:{src:"/assets/elsewhere-room.jpg",alt:"room travel inspiration",fill:!0,className:"absolute inset-0 w-full h-full"}}]},{$ref:"CardContent",$id:"agentic-1-104",props:{className:"p-4 space-y-3"},children:[{$ref:"Heading",$id:"agentic-1-105",props:{children:"Higashiyama House",className:"font-display font-normal tracking-[-0.03em] text-2xl"}},{$ref:"Text",$id:"agentic-1-106",props:{children:"$185 / NIGHT \xB7 BREAKFAST INCLUDED",className:"text-[10px] text-primary"}},{$ref:"Text",$id:"agentic-1-107",props:{children:"A quiet base, with old Kyoto right outside.",className:"text-xs leading-6 text-muted-foreground"}}]}]},{$ref:"Card",$id:"agentic-1-108",props:{className:"rounded-xl overflow-hidden p-0 gap-0 shadow-none"},children:[{$ref:"Box",$id:"agentic-1-109",props:{className:"relative overflow-hidden h-[155px]"},children:[{$ref:"Image",$id:"agentic-1-110",props:{src:"/assets/elsewhere-forest.jpg",alt:"forest travel inspiration",fill:!0,className:"absolute inset-0 w-full h-full"}}]},{$ref:"CardContent",$id:"agentic-1-111",props:{className:"p-4 space-y-3"},children:[{$ref:"Heading",$id:"agentic-1-112",props:{children:"The Garden Retreat",className:"font-display font-normal tracking-[-0.03em] text-2xl"}},{$ref:"Text",$id:"agentic-1-113",props:{children:"$210 / NIGHT \xB7 PRIVATE GARDEN",className:"text-[10px] text-primary"}},{$ref:"Text",$id:"agentic-1-114",props:{children:"More space to switch off, a little further out.",className:"text-xs leading-6 text-muted-foreground"}}]}]}]},{$ref:"Box",$id:"agentic-1-115",props:{className:"flex gap-3"},children:[{$ref:"Button",$id:"agentic-1-116",props:{variant:"default",className:"rounded-full text-xs"},children:[{$ref:"Icon",$id:"agentic-1-117",props:{name:"Check",className:"size-4"}},{$ref:"Box",$id:"agentic-1-118",props:{className:"",children:"Choose Higashiyama"}}]},{$ref:"Button",$id:"agentic-1-119",props:{variant:"outline",className:"rounded-full text-xs"},children:[{$ref:"Box",$id:"agentic-1-120",props:{className:"",children:"Show me more stays"}}]}]}]}]}]},{$ref:"Message",$id:"agentic-1-121",props:{align:"end",className:"w-full"},children:[{$ref:"MessageAvatar",$id:"agentic-1-122",children:[{$ref:"Avatar",$id:"agentic-1-123",props:{className:"size-8"},children:[{$ref:"AvatarFallback",$id:"agentic-1-124",props:{children:"AL",className:"bg-secondary text-[10px]"}}]}]},{$ref:"Box",$id:"agentic-1-125",props:{className:"min-w-0 flex-1 space-y-2"},children:[{$ref:"MessageHeader",$id:"agentic-1-126",props:{className:"text-xs text-muted-foreground"},children:[{$ref:"Text",$id:"agentic-1-127",props:{children:"You",className:"text-inherit"}}]},{$ref:"MessageContent",$id:"agentic-1-128",props:{className:"bg-secondary/65 rounded-2xl px-5 py-4"},children:[{$ref:"Text",$id:"agentic-1-129",props:{children:"Higashiyama looks perfect. Could we swap the busy temple afternoon for something quieter?",className:"text-sm leading-7"}}]}]}]},{$ref:"Message",$id:"agentic-1-130",props:{align:"start",className:"w-full"},children:[{$ref:"MessageAvatar",$id:"agentic-1-131",children:[{$ref:"Box",$id:"agentic-1-132",props:{className:"size-8 rounded-full bg-primary text-primary-foreground flex items-center justify-center shrink-0"},children:[{$ref:"Icon",$id:"agentic-1-133",props:{name:"Sparkles",className:"size-4"}}]}]},{$ref:"Box",$id:"agentic-1-134",props:{className:"min-w-0 flex-1 space-y-2"},children:[{$ref:"MessageHeader",$id:"agentic-1-135",props:{className:"text-xs text-muted-foreground"},children:[{$ref:"Text",$id:"agentic-1-136",props:{children:"Elsewhere",className:"text-inherit"}}]},{$ref:"MessageContent",$id:"agentic-1-137",props:{className:"space-y-4"},children:[{$ref:"Text",$id:"agentic-1-138",props:{children:"Absolutely. I\u2019ve replaced that afternoon with a small gallery walk and tea in a tucked-away courtyard. It saves $40 and leaves more time between stops.",className:"text-sm leading-7"}},{$ref:"Alert",$id:"agentic-1-139",props:{className:"bg-secondary/40 rounded-xl"},children:[{$ref:"Icon",$id:"agentic-1-140",props:{name:"RefreshCw",className:"size-4"}},{$ref:"AlertTitle",$id:"agentic-1-141",props:{children:"Your plan, adjusted"}},{$ref:"AlertDescription",$id:"agentic-1-142",props:{children:"Day 3 is quieter \xB7 Estimated total is now $1,730 \xB7 Two afternoons remain open"}}]}]}]}]}]},{$ref:"Card",$id:"agentic-1-143",props:{className:"rounded-2xl shadow-none p-6 gap-5 bg-card"},children:[{$ref:"Textarea",$id:"agentic-1-144",props:{placeholder:"One more thing\u2026",className:"border-0 shadow-none resize-none p-0 min-h-[62px] bg-transparent text-sm"}},{$ref:"Box",$id:"agentic-1-145",props:{className:"flex justify-between items-center"},children:[{$ref:"Button",$id:"agentic-1-146",props:{variant:"ghost",className:"rounded-full px-0 text-xs"},children:[{$ref:"Icon",$id:"agentic-1-147",props:{name:"Paperclip",className:"size-4"}},{$ref:"Box",$id:"agentic-1-148",props:{className:"",children:"Add inspiration"}}]},{$ref:"Button",$id:"agentic-1-149",props:{variant:"default",className:"rounded-full h-9"},children:[{$ref:"Icon",$id:"agentic-1-150",props:{name:"ArrowUp",className:"size-4"}},{$ref:"Box",$id:"agentic-1-151",props:{className:"",children:"Send"}}]}]}]},{$ref:"Card",$id:"agentic-1-152",props:{className:"rounded-2xl shadow-none p-6 gap-5 bg-secondary/35"},children:[{$ref:"Box",$id:"agentic-1-153",props:{className:"flex gap-3 items-center"},children:[{$ref:"Icon",$id:"agentic-1-154",props:{name:"CircleCheck",className:"size-5 text-primary"}},{$ref:"Heading",$id:"agentic-1-155",props:{children:"A trip that feels like you.",className:"font-display font-normal tracking-[-0.03em] text-2xl"}}]},{$ref:"Text",$id:"agentic-1-156",props:{children:"Save this draft to My trips. You can keep refining it with your companion, invite Jamie, and book each stay or experience when you\u2019re ready.",className:"text-xs leading-6 text-muted-foreground"}},{$ref:"Box",$id:"agentic-1-157",props:{className:"flex gap-3"},children:[{$ref:"Button",$id:"agentic-1-158",props:{variant:"default",className:"rounded-full h-11 px-6"},children:[{$ref:"Icon",$id:"agentic-1-159",props:{name:"Check",className:"size-4"}},{$ref:"Box",$id:"agentic-1-160",props:{className:"",children:"Save my trip"}}]},{$ref:"Button",$id:"agentic-1-161",props:{variant:"outline",className:"rounded-full h-11"},children:[{$ref:"Box",$id:"agentic-1-162",props:{className:"",children:"Keep refining"}}]}]},{$ref:"Text",$id:"agentic-1-163",props:{children:"Saving creates a private trip. Bookings happen separately.",className:"text-[10px] text-muted-foreground"}}]}]},{$ref:"Box",$id:"agentic-1-164",props:{className:"space-y-6"},children:[{$ref:"Card",$id:"agentic-1-165",props:{className:"rounded-2xl shadow-none p-6 gap-5 "},children:[{$ref:"Box",$id:"agentic-1-166",props:{className:"flex justify-between items-center"},children:[{$ref:"Text",$id:"agentic-1-167",props:{children:"YOUR TRIP, TAKING SHAPE",className:"text-[9px] tracking-widest text-muted-foreground"}},{$ref:"Badge",$id:"agentic-1-168",props:{variant:"secondary",children:"Draft 02",className:"rounded-full px-3 py-1 text-[10px] font-normal"}}]},{$ref:"Box",$id:"agentic-1-169",props:{className:"relative overflow-hidden h-[210px] rounded-xl"},children:[{$ref:"Image",$id:"agentic-1-170",props:{src:"/assets/elsewhere-kyoto.jpg",alt:"kyoto travel inspiration",fill:!0,className:"absolute inset-0 w-full h-full"}}]},{$ref:"Heading",$id:"agentic-1-171",props:{children:"A week in Kyoto",className:"font-display font-normal tracking-[-0.03em] text-3xl"}},{$ref:"Text",$id:"agentic-1-172",props:{children:"12\u201317 October 2026 \xB7 2 travellers",className:"text-xs text-muted-foreground"}},{$ref:"Box",$id:"agentic-1-173",props:{className:"flex flex-wrap gap-2"},children:[{$ref:"Badge",$id:"agentic-1-174",props:{variant:"secondary",children:"Slow mornings",className:"rounded-full px-3 py-1 text-[10px] font-normal"}},{$ref:"Badge",$id:"agentic-1-175",props:{variant:"secondary",children:"Local food",className:"rounded-full px-3 py-1 text-[10px] font-normal"}},{$ref:"Badge",$id:"agentic-1-176",props:{variant:"secondary",children:"Under $3,200",className:"rounded-full px-3 py-1 text-[10px] font-normal"}}]},{$ref:"Separator",$id:"agentic-1-177"},{$ref:"Box",$id:"agentic-1-178",props:{className:"space-y-3 text-xs"},children:[{$ref:"Box",$id:"agentic-1-179",props:{className:"flex justify-between"},children:[{$ref:"Text",$id:"agentic-1-180",props:{children:"Stay",className:"text-inherit"}},{$ref:"Text",$id:"agentic-1-181",props:{children:"$970",className:"text-inherit"}}]},{$ref:"Box",$id:"agentic-1-182",props:{className:"flex justify-between"},children:[{$ref:"Text",$id:"agentic-1-183",props:{children:"Food & coffee",className:"text-inherit"}},{$ref:"Text",$id:"agentic-1-184",props:{children:"$360",className:"text-inherit"}}]},{$ref:"Box",$id:"agentic-1-185",props:{className:"flex justify-between"},children:[{$ref:"Text",$id:"agentic-1-186",props:{children:"Experiences",className:"text-inherit"}},{$ref:"Text",$id:"agentic-1-187",props:{children:"$240",className:"text-inherit"}}]},{$ref:"Box",$id:"agentic-1-188",props:{className:"flex justify-between"},children:[{$ref:"Text",$id:"agentic-1-189",props:{children:"Local transport",className:"text-inherit"}},{$ref:"Text",$id:"agentic-1-190",props:{children:"$160",className:"text-inherit"}}]},{$ref:"Separator",$id:"agentic-1-191"},{$ref:"Box",$id:"agentic-1-192",props:{className:"flex justify-between font-semibold"},children:[{$ref:"Text",$id:"agentic-1-193",props:{children:"Estimated trip total",className:"text-inherit"}},{$ref:"Text",$id:"agentic-1-194",props:{children:"$1,730",className:"text-inherit"}}]},{$ref:"Box",$id:"agentic-1-195",props:{className:"flex justify-between text-muted-foreground"},children:[{$ref:"Text",$id:"agentic-1-196",props:{children:"Left for the unexpected",className:"text-inherit"}},{$ref:"Text",$id:"agentic-1-197",props:{children:"$1,470",className:"text-inherit"}}]}]},{$ref:"Button",$id:"agentic-1-198",props:{variant:"outline",className:"rounded-full w-full"},children:[{$ref:"Icon",$id:"agentic-1-199",props:{name:"ArrowUpRight",className:"size-4"}},{$ref:"Box",$id:"agentic-1-200",props:{className:"",children:"View full itinerary"}}]}]},{$ref:"Card",$id:"agentic-1-201",props:{className:"rounded-2xl shadow-none p-6 gap-5 "},children:[{$ref:"Heading",$id:"agentic-1-202",props:{children:"Five days, softly planned.",className:"font-display font-normal tracking-[-0.03em] text-2xl"}},{$ref:"Box",$id:"agentic-1-203",props:{className:"divide-y divide-border"},children:[{$ref:"Box",$id:"agentic-1-204",props:{className:"flex gap-4 items-start py-5"},children:[{$ref:"Box",$id:"agentic-1-205",props:{className:"size-10 rounded-full bg-secondary flex justify-center items-center shrink-0"},children:[{$ref:"Text",$id:"agentic-1-206",props:{children:"01",className:"text-xs"}}]},{$ref:"Box",$id:"agentic-1-207",props:{className:"flex-1 space-y-2"},children:[{$ref:"Box",$id:"agentic-1-208",props:{className:"flex items-center justify-between"},children:[{$ref:"Text",$id:"agentic-1-209",props:{children:"Arrive gently",className:"text-sm font-semibold"}},{$ref:"Text",$id:"agentic-1-210",props:{children:"$100",className:"text-xs text-muted-foreground"}}]},{$ref:"Text",$id:"agentic-1-211",props:{children:"Nishiki Market \xB7 Gion lanes \xB7 Tea with a local host",className:"text-xs leading-6 text-muted-foreground"}}]}]},{$ref:"Box",$id:"agentic-1-212",props:{className:"flex gap-4 items-start py-5"},children:[{$ref:"Box",$id:"agentic-1-213",props:{className:"size-10 rounded-full bg-secondary flex justify-center items-center shrink-0"},children:[{$ref:"Text",$id:"agentic-1-214",props:{children:"02",className:"text-xs"}}]},{$ref:"Box",$id:"agentic-1-215",props:{className:"flex-1 space-y-2"},children:[{$ref:"Box",$id:"agentic-1-216",props:{className:"flex items-center justify-between"},children:[{$ref:"Text",$id:"agentic-1-217",props:{children:"A greener kind of morning",className:"text-sm font-semibold"}},{$ref:"Text",$id:"agentic-1-218",props:{children:"$85",className:"text-xs text-muted-foreground"}}]},{$ref:"Text",$id:"agentic-1-219",props:{children:"Early bamboo grove \xB7 Riverside lunch \xB7 An open afternoon",className:"text-xs leading-6 text-muted-foreground"}}]}]},{$ref:"Box",$id:"agentic-1-220",props:{className:"flex gap-4 items-start py-5"},children:[{$ref:"Box",$id:"agentic-1-221",props:{className:"size-10 rounded-full bg-secondary flex justify-center items-center shrink-0"},children:[{$ref:"Text",$id:"agentic-1-222",props:{children:"03",className:"text-xs"}}]},{$ref:"Box",$id:"agentic-1-223",props:{className:"flex-1 space-y-2"},children:[{$ref:"Box",$id:"agentic-1-224",props:{className:"flex items-center justify-between"},children:[{$ref:"Text",$id:"agentic-1-225",props:{children:"Follow your curiosity",className:"text-sm font-semibold"}},{$ref:"Text",$id:"agentic-1-226",props:{children:"$120",className:"text-xs text-muted-foreground"}}]},{$ref:"Text",$id:"agentic-1-227",props:{children:"Small galleries \xB7 Independent shops \xB7 Dinner in Pontocho",className:"text-xs leading-6 text-muted-foreground"}}]}]},{$ref:"Box",$id:"agentic-1-228",props:{className:"flex gap-4 items-start py-5"},children:[{$ref:"Box",$id:"agentic-1-229",props:{className:"size-10 rounded-full bg-secondary flex justify-center items-center shrink-0"},children:[{$ref:"Text",$id:"agentic-1-230",props:{children:"04",className:"text-xs"}}]},{$ref:"Box",$id:"agentic-1-231",props:{className:"flex-1 space-y-2"},children:[{$ref:"Box",$id:"agentic-1-232",props:{className:"flex items-center justify-between"},children:[{$ref:"Text",$id:"agentic-1-233",props:{children:"A little further afield",className:"text-sm font-semibold"}},{$ref:"Text",$id:"agentic-1-234",props:{children:"$110",className:"text-xs text-muted-foreground"}}]},{$ref:"Text",$id:"agentic-1-235",props:{children:"A day in Uji \xB7 Tea fields \xB7 Back before sunset",className:"text-xs leading-6 text-muted-foreground"}}]}]},{$ref:"Box",$id:"agentic-1-236",props:{className:"flex gap-4 items-start py-5"},children:[{$ref:"Box",$id:"agentic-1-237",props:{className:"size-10 rounded-full bg-secondary flex justify-center items-center shrink-0"},children:[{$ref:"Text",$id:"agentic-1-238",props:{children:"05",className:"text-xs"}}]},{$ref:"Box",$id:"agentic-1-239",props:{className:"flex-1 space-y-2"},children:[{$ref:"Box",$id:"agentic-1-240",props:{className:"flex items-center justify-between"},children:[{$ref:"Text",$id:"agentic-1-241",props:{children:"Leave room for one more thing",className:"text-sm font-semibold"}},{$ref:"Text",$id:"agentic-1-242",props:{children:"$65",className:"text-xs text-muted-foreground"}}]},{$ref:"Text",$id:"agentic-1-243",props:{children:"A slow breakfast \xB7 Your favourite neighbourhood \xB7 Homeward",className:"text-xs leading-6 text-muted-foreground"}}]}]}]}]},{$ref:"Card",$id:"agentic-1-244",props:{className:"rounded-2xl shadow-none p-6 gap-5 bg-secondary/25"},children:[{$ref:"Text",$id:"agentic-1-245",props:{children:"WHY THIS FITS",className:"text-[9px] tracking-widest text-primary"}},{$ref:"Box",$id:"agentic-1-246",props:{className:"space-y-4"},children:[{$ref:"Text",$id:"agentic-1-247",props:{children:"A walkable base, so less time disappears into transport.",className:"text-xs leading-6"}},{$ref:"Text",$id:"agentic-1-248",props:{children:"One early start. Two open afternoons. Plenty of room to linger.",className:"text-xs leading-6"}},{$ref:"Text",$id:"agentic-1-249",props:{children:"Local food and small discoveries woven into every day.",className:"text-xs leading-6"}}]}]}]}]},{$ref:"Box",$id:"agentic-1-250",props:{className:"border-t border-border px-12 py-8 flex justify-between"},children:[{$ref:"Text",$id:"agentic-1-251",props:{children:"A little help. A world of possibilities.",className:"font-display text-xl"}},{$ref:"Text",$id:"agentic-1-252",props:{children:"ELSEWHERE / YOUR TRAVEL COMPANION",className:"text-[9px] tracking-widest text-muted-foreground"}}]}]}};var elsewhere_details_default={id:"elsewhere-details",name:"Agentic trip creation exploration",frames:[{id:"elsewhere-trips-library-desktop",screen:"elsewhere-trips-library",x:0,y:270,w:1440,h:2540,label:"A \xB7 The conversational concierge"},{id:"elsewhere-trips-board-desktop",screen:"elsewhere-trips-board",x:1580,y:270,w:1440,h:2909,label:"B \xB7 The brief-to-plan workspace"},{id:"elsewhere-trips-journal-desktop",screen:"elsewhere-trips-journal",x:3160,y:270,w:1440,h:3547,label:"C \xB7 The inspiration-led companion"}],groups:[]};var main_default={id:"main",name:"Elsewhere \xB7 The journey",frames:[{id:"elsewhere-discover-desktop",screen:"elsewhere-discover",x:0,y:0,w:1440,h:1361,label:"01 \xB7 Discover your elsewhere / Desktop",scheme:"light"},{id:"elsewhere-stay-desktop",screen:"elsewhere-stay",x:1550,y:0,w:1440,h:1337,label:"02 \xB7 A stay in Kyoto / Desktop"},{id:"elsewhere-itinerary-desktop",screen:"elsewhere-itinerary",x:0,y:1600,w:1440,h:1324,label:"03 \xB7 A day in Kyoto / Desktop"},{id:"elsewhere-overview-desktop",screen:"elsewhere-overview",x:1550,y:1600,w:1440,h:1543,label:"04 \xB7 Your trip, at a glance / Desktop",scheme:"light"},{id:"elsewhere-discover-mobile",screen:"elsewhere-discover",x:3100,y:0,w:390,h:2390,label:"Shared screen / Mobile"},{id:"elsewhere-itinerary-mobile",screen:"elsewhere-itinerary",x:3610,y:0,w:390,h:2000,label:"Shared screen / Mobile"},{id:"elsewhere-discover-dark",screen:"elsewhere-discover",x:0,y:3300,w:1440,h:1361,label:"Discover / Dark mode",scheme:"dark"},{id:"elsewhere-overview-dark",screen:"elsewhere-overview",x:1550,y:3300,w:1440,h:1543,label:"Trip overview / Dark mode",scheme:"dark"}],groups:[]};function buildSampleScreens(){return structuredClone([elsewhere_discover_default,elsewhere_itinerary_default,elsewhere_overview_default,elsewhere_stay_default,elsewhere_trips_board_default,elsewhere_trips_journal_default,elsewhere_trips_library_default])}function buildSampleBoards(){return structuredClone([main_default,elsewhere_details_default])}var elsewhere_destination_default={id:"elsewhere-destination",name:"DestinationCard",params:[{name:"image",type:"string"},{name:"name",type:"string"},{name:"country",type:"string"},{name:"note",type:"string"}],tree:{$ref:"Card",props:{className:"overflow-hidden p-0 gap-0 rounded-2xl shadow-none"},children:[{$ref:"Box",props:{className:"relative h-[210px] overflow-hidden"},children:[{$ref:"Image",props:{src:{$param:"image"},fill:!0,className:"absolute inset-0 h-full w-full"}},{$ref:"Button",props:{variant:"secondary",size:"icon",className:"absolute right-3 top-3 rounded-full size-8","aria-label":"Save destination"},children:[{$ref:"Icon",props:{name:"Heart",className:"size-4"}}]}]},{$ref:"CardContent",props:{className:"p-5"},children:[{$ref:"Text",props:{children:{$param:"country"},className:"text-[10px] uppercase tracking-[0.18em] text-muted-foreground"}},{$ref:"Box",props:{className:"flex items-center justify-between mt-2"},children:[{$ref:"Heading",props:{children:{$param:"name"},className:"font-display font-normal tracking-[-0.035em] text-3xl"}},{$ref:"Icon",props:{name:"ArrowUpRight",className:"size-4"}}]},{$ref:"Text",props:{children:{$param:"note"},className:"text-xs mt-2 text-muted-foreground"}}]}]}};var elsewhere_metric_default={id:"elsewhere-metric",name:"TripMetric",params:[{name:"label",type:"string"},{name:"value",type:"string"},{name:"note",type:"string"}],tree:{$ref:"Card",props:{className:"p-5 gap-3 rounded-xl shadow-none"},children:[{$ref:"Text",props:{children:{$param:"label"},className:"text-xs text-muted-foreground"}},{$ref:"Heading",props:{children:{$param:"value"},className:"font-display font-normal tracking-[-0.035em] text-3xl"}},{$ref:"Text",props:{children:{$param:"note"},className:"text-xs text-muted-foreground"}}]}};var elsewhere_nav_default={id:"elsewhere-nav",name:"ElsewhereNav",params:[],tree:{$ref:"Box",props:{className:"h-20 border-b border-border flex items-center justify-between px-6 md:px-14 bg-background"},children:[{$ref:"Box",props:{className:"flex items-center gap-2"},children:[{$ref:"SVG",props:{viewBox:"0 0 32 32",content:'<circle cx="16" cy="16" r="14" fill="none" stroke="currentColor" stroke-width="1.2"/><path d="M8 21 22 9l-4 15-3-7-7 4Z" fill="currentColor"/>',className:"size-8 text-primary"}},{$ref:"Text",props:{children:"elsewhere",className:"font-display text-[30px] tracking-[-0.05em]"}}]},{$ref:"Box",props:{className:"hidden md:flex items-center gap-8 text-sm"},children:[{$ref:"Text",props:{children:"Discover",className:"font-semibold"}},{$ref:"Text",props:{children:"Our kind of stays",className:"text-muted-foreground"}},{$ref:"Text",props:{children:"Field notes",className:"text-muted-foreground"}}]},{$ref:"Box",props:{className:"flex items-center gap-4"},children:[{$ref:"Button",props:{variant:"ghost",className:"rounded-full hidden md:inline-flex"},children:[{$ref:"Icon",props:{name:"Bookmark",className:"size-4"}},{$ref:"Text",props:{children:"My trips",className:""}}]},{$ref:"Avatar",props:{className:"size-8 border-2 border-background"},children:[{$ref:"AvatarFallback",props:{children:"AL",className:"text-[10px] bg-secondary text-secondary-foreground"}}]}]}]}};function buildSampleSnippets(){return structuredClone([elsewhere_destination_default,elsewhere_metric_default,elsewhere_nav_default])}function buildElsewhereScaffold(library,theme){let screens=buildSampleScreens(),snippets=buildSampleSnippets(),native=library==="shadcn-upstream"?void 0:nativeElsewhere(library,screens,snippets);return{theme,screens:native?.screens??screens,snippets:native?.snippets??snippets,boards:buildSampleBoards(),annotations:[],notes:[{boardId:"elsewhere-details",entries:structuredClone(elsewhere_details_notes_default)}],customCss:`${custom_default}
44
- ${native?.css??""}`,assetMetadata:structuredClone(assets_default),assetFiles:{"assets/elsewhere-alps.jpg":resolve5(import.meta.dir,elsewhere_alps_default),"assets/elsewhere-bali.jpg":resolve5(import.meta.dir,elsewhere_bali_default),"assets/elsewhere-forest.jpg":resolve5(import.meta.dir,elsewhere_forest_default),"assets/elsewhere-japan.jpg":resolve5(import.meta.dir,elsewhere_japan_default),"assets/elsewhere-kyoto-map.svg":resolve5(import.meta.dir,elsewhere_kyoto_map_default),"assets/elsewhere-kyoto.jpg":resolve5(import.meta.dir,elsewhere_kyoto_default),"assets/elsewhere-room.jpg":resolve5(import.meta.dir,elsewhere_room_default)},documents:{"ASSET-SOURCES.md":ASSET_SOURCES_default}}}function bundledComponentsSection(){return["## Bundled components","","The shadcn snapshot lives inside the velloo binary. No files were","written to your app. When you're ready to bring shadcn into your","project, run `npx shadcn@latest init` there separately, then","`velloo theme:export <app>` to align the theme.",""]}var WIZARD_PROVIDERS={"shadcn-upstream":{label:"shadcn",hint:"Real shadcn, Tailwind classes. Recommended.",order:0,defaultSource:"in-repo",asksComponentsSubfolder:!0,scanScreenOpts:{hasBadge:!0},planInstall(answers){let targetDir=resolve6(answers.appRoot,answers.componentsRelative);return{library:{id:"shadcn-upstream",version:snapshotVersion2,source:"in-repo",componentsPath:relative6(answers.folder,dirname5(targetDir))||"."},summary:{name:"shadcn (upstream)",location:`canvas reads client-safe components from ${answers.componentsRelative}; canvas-safe fallbacks cover missing or unsupported files`},pendingUpstream:{targetDir,relative:answers.componentsRelative}}},buildSampleScaffold:(theme)=>buildElsewhereScaffold("shadcn-upstream",theme),stylingFor:()=>{return},scanMatch:(detected)=>detected.uiLibrary==="shadcn",scanNote:(detected)=>`Detected ${detected.uiLibrary} \u2014 using that library.`,handoffComponentsLabel:"shadcn",readmeComponentsSection:(plan)=>plan.pendingUpstream?["## Bringing shadcn into your app","","Init did not write anything into your app. To add shadcn at",`\`${plan.pendingUpstream.relative}\`, ask your AI`,"agent (it was wired up during init) to finish setup \u2014 or run","`npx shadcn@latest add <component>` yourself. Client-safe files render","directly from the repo; overlays use labeled canvas adaptations and","broken or missing files visibly fall back to Velloo's snapshot. Then","`velloo theme:export <app>` aligns the theme.",""]:bundledComponentsSection()},none:{label:"No library",hint:"Plain Box / Stack / Text primitives.",order:9,defaultSource:"binary",asksComponentsSubfolder:!1,scanScreenOpts:{hasBadge:!1},planInstall:()=>({library:{id:"none",version:noLibVersion,source:"binary",componentsPath:"binary"},summary:{name:`no-library primitives (${noLibVersion})`,location:"bundled with velloo"}}),buildSampleScaffold:(theme)=>buildElsewhereScaffold("none",theme),stylingFor:(answers)=>({framework:answers.detected?.tailwindMajor?"tailwind":"none"}),scanMatch:(detected)=>Boolean(detected.unsupportedUi),scanNote:(detected)=>`Detected ${detected.unsupportedUi} (no velloo adapter yet) \u2014 using the no-framework adapter; approximate its components and preserve their imports with emit-as.`,handoffComponentsLabel:"velloo primitive",readmeComponentsSection:()=>bundledComponentsSection()},mui:{label:"Material UI",hint:"Real @mui/material, sx styling.",order:4,defaultSource:"binary",asksComponentsSubfolder:!1,scanScreenOpts:{hasBadge:!0,tree:"mui"},planInstall:()=>({library:{id:"mui",version:MUI_VERSION,source:"binary",componentsPath:"binary"},summary:{name:`Material UI v${MUI_VERSION}`,location:"bundled with velloo"}}),buildSampleScaffold:(theme)=>buildElsewhereScaffold("mui",theme),stylingFor:()=>{return},scanMatch:(detected)=>detected.uiLibrary==="mui",scanNote:(detected)=>`Detected ${detected.uiLibrary} \u2014 using that library.`,handoffComponentsLabel:"Material UI",readmeComponentsSection:()=>["## Material UI in your app","","The canvas renders **real Material UI** components (bundled with velloo,","emotion-rendered) \u2014 no files were written to your app. When you implement","a screen, `emit_code` emits idiomatic MUI (`sx` props + `@mui/material`","imports) and `emit_theme` emits a `createTheme(...)` module. For that code","to build, install the runtime deps in your app:","","```bash","npm install @mui/material @emotion/react @emotion/styled","```","","Once installed, velloo can also client-render the canvas against your","app's exact MUI version. Style nodes with the `sx` editor (canvas) or","`update_props`'s `style` (agent).",""]},antd:{label:"Ant Design",hint:"Real antd v5, inline style objects.",order:2,defaultSource:"binary",asksComponentsSubfolder:!1,scanScreenOpts:{hasBadge:!0,tree:"antd"},planInstall:()=>({library:{id:"antd",version:ANTD_VERSION,source:"binary",componentsPath:"binary"},summary:{name:`Ant Design v${ANTD_VERSION}`,location:"bundled with velloo"}}),buildSampleScaffold:(theme)=>buildElsewhereScaffold("antd",theme),stylingFor:()=>{return},scanMatch:(detected)=>detected.uiLibrary==="antd",scanNote:(detected)=>`Detected ${detected.uiLibrary} \u2014 using that library.`,handoffComponentsLabel:"Ant Design",readmeComponentsSection:()=>["## Ant Design in your app","","The canvas renders **real Ant Design** components (bundled with velloo,","cssinjs-rendered) \u2014 no files were written to your app. When you implement","a screen, `emit_code` emits idiomatic antd (inline `style` objects +","`antd` imports) and `emit_theme` emits a ConfigProvider `ThemeConfig`","module. For that code to build, install the runtime dep in your app:","","```bash","npm install antd","```","","Style nodes with the inline-style editor (canvas) or `update_props`'s `style` (agent).",""]},chakra:{label:"Chakra UI",hint:"Real Chakra v2, sx styling.",order:3,defaultSource:"binary",asksComponentsSubfolder:!1,scanScreenOpts:{hasBadge:!0,tree:"chakra"},planInstall:()=>({library:{id:"chakra",version:CHAKRA_VERSION,source:"binary",componentsPath:"binary"},summary:{name:`Chakra UI v${CHAKRA_VERSION}`,location:"bundled with velloo"}}),buildSampleScaffold:(theme)=>buildElsewhereScaffold("chakra",theme),stylingFor:()=>{return},scanMatch:(detected)=>detected.uiLibrary==="chakra",scanNote:(detected)=>`Detected ${detected.uiLibrary} \u2014 using that library.`,handoffComponentsLabel:"Chakra UI",readmeComponentsSection:()=>["## Chakra UI in your app","","The canvas renders **real Chakra UI v2** components (bundled with velloo,","emotion-rendered) \u2014 no files were written to your app. When you implement","a screen, `emit_code` emits idiomatic chakra (`sx` props +","`@chakra-ui/react` imports) and `emit_theme` emits an `extendTheme(...)`","module. For that code to build, install the runtime deps in your app:","","```bash","npm install @chakra-ui/react@2 @emotion/react @emotion/styled framer-motion","```","","Style nodes with the `sx` editor (canvas) or `update_props`'s `style` (agent).",""]}},LIBRARY_IDS=Object.keys(WIZARD_PROVIDERS),DEFAULT_LIBRARY_ID="shadcn-upstream";function interactiveLibraryChoices(){return LIBRARY_IDS.toSorted((a,b)=>WIZARD_PROVIDERS[a].order-WIZARD_PROVIDERS[b].order).map((id)=>({value:id,label:WIZARD_PROVIDERS[id].label,hint:WIZARD_PROVIDERS[id].hint}))}function planInstall(answers){return WIZARD_PROVIDERS[answers.library].planInstall(answers)}function sampleScaffold(answers,theme){return WIZARD_PROVIDERS[answers.library].buildSampleScaffold(theme,answers)}function scanAdoption(detected){for(let id of LIBRARY_IDS){let entry=WIZARD_PROVIDERS[id];if(entry.scanMatch?.(detected))return{library:id,note:entry.scanNote?.(detected)??""}}return}var STACKS=[{id:"nextjs",label:"Next.js",alias:"@/components/ui"},{id:"vite",label:"Vite (React)",alias:"@/components/ui"},{id:"astro",label:"Astro",alias:"@/components/ui"},{id:"remix",label:"Remix / React Router",alias:"~/components/ui"}],DEFAULT_STACK_ID="vite";function stackForFramework(framework){switch(framework){case"next-app":case"next-pages":return"nextjs";case"react-router":return"remix";case"astro":return"astro";default:return"vite"}}function stackById(id){return id?STACKS.find((s)=>s.id===id):void 0}function isValidStack(id){return STACKS.some((s)=>s.id===id)}var START_TO_CONTENT={"redesign-screen":"redesign-screen","redesign-component":"component",custom:"custom",sample:"sample",blank:"blank",scratch:"sample",scan:"scan"};function isValidLibraryId(v){return LIBRARY_IDS.includes(v)}function isValidContent(v){return v==="sample"||v==="blank"||v==="scan"||v==="redesign-screen"||v==="component"||v==="custom"}function isValidStart(v){return v in START_TO_CONTENT}function shouldRunWizard(args,stdinIsTTY){if(args.nonInteractive)return!1;return stdinIsTTY}function answersFromArgs(args){if(args.library&&!isValidLibraryId(args.library))throw Error(`unknown --library ${JSON.stringify(args.library)}. Valid: ${LIBRARY_IDS.join(" | ")}.`);if(args.start&&!isValidStart(args.start))throw Error(`unknown --start ${JSON.stringify(args.start)}. Valid: redesign-screen | redesign-component | custom | sample | blank | scan.`);if(args.initialContent&&!isValidContent(args.initialContent))throw Error(`unknown --initial-content ${JSON.stringify(args.initialContent)}. Valid: sample | blank | scan | redesign-screen | component | custom.`);let themePreset=args.themePreset?.trim()||void 0;if(themePreset&&!isValidPreset(themePreset))throw Error(`unknown --theme-preset ${JSON.stringify(args.themePreset)}.`);let stack=args.stack?.trim()||void 0;if(stack&&!isValidStack(stack))throw Error(`unknown --stack ${JSON.stringify(args.stack)}. Valid: nextjs | vite | astro | remix.`);let appRoot=resolve7(args.folder??"."),folder=resolve7(appRoot,args.designFolder??"velloo"),library=args.library??DEFAULT_LIBRARY_ID,initialContent=args.initialContent??"sample";if(args.start)initialContent=START_TO_CONTENT[args.start]??initialContent;let screenName=args.screenName?.trim()||void 0,componentDescription=args.component?.trim()||void 0,customRequest=args.request?.trim()||void 0;if(initialContent==="component"&&!componentDescription)throw Error("--component is required for --start=redesign-component.");if(initialContent==="custom"&&!customRequest)throw Error("--request is required for --start=custom.");if(initialContent==="redesign-screen"&&!screenName&&args.start==="redesign-screen");let source=WIZARD_PROVIDERS[library].defaultSource;return{appRoot,scanRoot:appRoot,folder,library,source,componentsRelative:args.componentsDir??"src/components/ui",initialContent,themePreset,...stack?{stack}:{},...screenName?{screenName}:{},...componentDescription?{componentDescription}:{},...customRequest?{customRequest}:{}}}import{readFile as readFile6,rm as rm2,writeFile}from"fs/promises";import{tmpdir}from"os";import{join as join8}from"path";var import_picocolors2=__toESM(require_picocolors(),1);import{relative as relative7}from"path";var SCREENS_PLACEHOLDER="{{screens}}";function libraryLabel(library){return WIZARD_PROVIDERS[library].handoffComponentsLabel}function appContextLines(answers){let lines=[],appRels=[...new Set((answers.selectedRoutes??[]).map((r)=>r.appRel).filter(Boolean))];if(appRels.length>1)lines.push(`This is a monorepo with ${appRels.length} apps (${appRels.map((r)=>`\`${r}\``).join(", ")}); each app's screens sit on their own board. Run the matching app's dev server when comparing screens.`);else{let uiRel=relative7(answers.appRoot,answers.scanRoot);if(uiRel&&!uiRel.startsWith(".."))lines.push(`This app's UI lives in \`${uiRel}/\` \u2014 run its dev server from there.`)}return lines}function setupFirstGuidance(){return"**Calibrate before you design** \u2014 run the **velloo-setup** skill first. The canvas draws with Velloo's own components themed by this folder's tokens, not this repo's component files, so an uncalibrated board won't look like my app. Import my stylesheet, set the real fonts, match the custom components that appear in what you're designing, and get the app running so there's something real to check against. Tell me in a line what you matched and what stayed unverified."}function compareGuidance(){return"Compare against the real app, not memory: iterate with `screenshot` + `compare_to_url` at the same viewport and fix the `topMismatches` in the order they're ranked. If a capture comes back `unverified`, the similarity number means nothing \u2014 and if the reason is a login wall, call `start_capture_session` so I can sign in and capture the page for you, then verify against it with `compare_to_url { captureId }`."}function captureSiteGuidance(url){return[`**Start by capturing the site.** Call \`start_capture_session { url: "${url}" }\` \u2014 it opens a browser window I drive. I'll log in if needed and hit "Capture page" on each page worth designing from; the call returns straight away, so poll \`list_captures\` until my captures appear.`,"Then read each one with `get_capture`: it gives you a structural outline (repeated blocks are marked \u2014 those are your component candidates), the site's CSS custom properties as `import_theme`-ready CSS, and its images. Run `import_theme` with that CSS before composing so the real tokens resolve.","Re-express the pages with real components against the theme \u2014 do not transcribe the DOM node-for-node. Verify each screen with `compare_to_url { captureId }`."].join(`
45
- `)}function exploreAlternativesGuidance(){return"After the faithful recreation, explore alternatives on the same board \u2014 side-by-side A/B/C (or more) frames or grouped explorations of different directions. Velloo's strength is comparing options visually; do not stop at a single redesign."}function wantsHandoff(answers){switch(answers.initialContent){case"scan":case"redesign-screen":case"component":case"custom":return!0;default:return!1}}function buildHandoffPrompt(answers,screens,boards){switch(answers.initialContent){case"redesign-screen":return buildRedesignScreenHandoff(answers,screens);case"component":return buildComponentHandoff(answers);case"custom":return buildCustomHandoff(answers);case"scan":return buildLegacyScanHandoff(answers,screens,boards);default:return buildLegacyScanHandoff(answers,screens,boards)}}function buildRedesignScreenHandoff(answers,screens){let name=answers.screenName?.trim()||screens[0]?.name||screens[0]?.id||"the chosen screen",lines=[`Recreate and then explore alternatives for **${name}** as a Velloo design. Work entirely through the velloo MCP tools.`,...appContextLines(answers)];if(screens.length>0)lines.push(`A placeholder screen is already scaffolded (desktop + mobile frames \u2014 edits sync). Design it with the project's ${libraryLabel(answers.library)} components:`,SCREENS_PLACEHOLDER);else lines.push(`- Create a Velloo screen for **${name}** using the project's ${libraryLabel(answers.library)} components.`);return lines.push(`1. ${setupFirstGuidance()}`,`2. **Recreate** the real page faithfully. ${compareGuidance()}`,`3. **Then explore alternatives** \u2014 ${exploreAlternativesGuidance()}`),lines.join(`
46
- `)}function buildComponentHandoff(answers){let target=answers.componentDescription?.trim()||"the component";return[`Redesign **${target}** in Velloo \u2014 recreate it, then explore alternatives. Work entirely through the velloo MCP tools.`,...appContextLines(answers),`A component-focused board is scaffolded. Target: **${target}**. Prefer a snippet if the piece should be reused.`,`1. ${setupFirstGuidance()}`,`2. **Recreate** the current component faithfully with the project's ${libraryLabel(answers.library)} components. ${compareGuidance()}`,`3. **Then explore alternatives** \u2014 ${exploreAlternativesGuidance()}`].join(`
47
- `)}function buildCustomHandoff(answers){return["Design this in Velloo. Work entirely through the velloo MCP tools.","","**Request:**",answers.customRequest?.trim()||"the design I described","",...answers.captureUrl?[captureSiteGuidance(answers.captureUrl),""]:[],setupFirstGuidance(),`Then design it with the project's ${libraryLabel(answers.library)} components. When comparing options, put alternatives side-by-side on the board (explorations) instead of overwriting a single direction.`].join(`
48
- `)}function buildLegacyScanHandoff(answers,screens,boards){let lines=["Recreate this app's pages as a Velloo design \u2014 one Velloo screen per page, faithful to the real UI. Work entirely through the velloo MCP tools (wired during setup)."];if(lines.push(...appContextLines(answers)),lines.push(setupFirstGuidance()),screens.length>0){if(lines.push(`These screens are already scaffolded from the app's routes \u2014 design these, and only these, with the project's ${libraryLabel(answers.library)} components:`,SCREENS_PLACEHOLDER),answers.agentPicksFirst)lines.push("Start with the highest-impact screen (usually the landing page or the main dashboard) and design it fully \u2014 it sets the quality bar. Then work through the rest.")}else lines.push(`- For each route/page in the app, create a Velloo screen that reproduces that page's UI from the project's ${libraryLabel(answers.library)} components.`);if(lines.push("- Each screen already has a desktop and a mobile frame on its board (same screen \u2014 edits sync); make sure layouts hold at both widths."),boards.some((b)=>b.groups.length>0))lines.push("- Frames are pre-grouped by route section \u2014 keep the groups tidy as flows evolve.");return lines.push(`- ${compareGuidance()}`),lines.join(`
49
- `)}function expandHandoffPrompt(prompt,screens){if(!prompt.includes(SCREENS_PLACEHOLDER))return prompt;let list=screens.map((s)=>` - ${s.name||s.id}`).join(`
50
- `);return prompt.split(SCREENS_PLACEHOLDER).join(list)}function detectEditor(){let env=(process.env.VISUAL||process.env.EDITOR||"").trim();if(env){let parts=env.split(/\s+/);if(parts[0]&&Bun.which(parts[0]))return parts}for(let cand of["nano","vim","vi"])if(Bun.which(cand))return[cand];return["vi"]}async function editPrompt(prompt){let file=join8(tmpdir(),`velloo-handoff-${process.pid}-${Date.now()}.md`);await writeFile(file,prompt,"utf8");let editor=detectEditor();try{return await Bun.spawn([...editor,file],{stdin:"inherit",stdout:"inherit",stderr:"inherit"}).exited,(await readFile6(file,"utf8")).trim()}catch{return null}finally{await rm2(file,{force:!0})}}var AGENT_LAUNCHERS=[{bin:"claude",label:"Claude Code",agentIds:["claude-code","claude-code-global"],argv:(p)=>["claude",p]},{bin:"cursor-agent",label:"Cursor CLI",agentIds:["cursor","cursor-global"],argv:(p)=>["cursor-agent",p]},{bin:"codex",label:"Codex CLI",agentIds:["codex","codex-global"],argv:(p)=>["codex",p]},{bin:"opencode",label:"opencode",agentIds:["opencode","opencode-global"],argv:(p)=>["opencode","--prompt",p]},{bin:"droid",label:"Droid",agentIds:["droid-global"],argv:(p)=>["droid",p]},{bin:"cline",label:"Cline",agentIds:["cline-global"],argv:(p)=>["cline",p]},{bin:"gemini",label:"Gemini CLI",agentIds:["gemini","gemini-global"],argv:(p)=>["gemini","-i",p]}];async function printAgentHandoff(answers,scaffold,interactive,wiredIds){if(!wantsHandoff(answers))return;let{screens}=scaffold,prompt=buildHandoffPrompt(answers,screens,scaffold.boards);console.log(import_picocolors2.default.bold(" Finish setup with your agent")),console.log(import_picocolors2.default.dim(" Paste this to your AI agent:")),console.log("");for(let line of prompt.split(`
51
- `))console.log(import_picocolors2.default.cyan(` ${line}`));if(prompt.includes(SCREENS_PLACEHOLDER))console.log(""),console.log(import_picocolors2.default.dim(` ${SCREENS_PLACEHOLDER} is replaced with your selected screens when the prompt is sent (an agent can also discover them with list_screens).`));if(console.log(""),!interactive)return;let launchers=AGENT_LAUNCHERS.filter((l)=>Bun.which(l.bin)&&l.agentIds.some((id)=>wiredIds.includes(id))),first=launchers[0],action=await select({message:first?"Start velloo and launch your agent to do this now?":"No wired agent CLI to launch \u2014 what next?",options:[...launchers.map((l)=>({value:`launch:${l.bin}`,label:`Yes \u2014 launch ${l.label} with this prompt`})),...first?[{value:"edit",label:"Edit the prompt first",hint:`opens ${detectEditor()[0]??"your editor"}`}]:[],{value:"copy",label:"Copy the prompt to my clipboard"},{value:"skip",label:first?"No \u2014 I'll run it later":"Skip"}],initialValue:first?`launch:${first.bin}`:"copy"});if(isCancel(action)||action==="skip")return;if(action==="copy"){let copied=await copyToClipboard(expandHandoffPrompt(prompt,screens));console.log(copied?` ${import_picocolors2.default.green("\u2713")} Prompt copied \u2014 paste it into your agent.`:import_picocolors2.default.dim(" Couldn't reach a clipboard tool \u2014 copy the prompt printed above."));return}let finalPrompt=prompt,launcher=first;if(action.startsWith("launch:"))launcher=launchers.find((l)=>`launch:${l.bin}`===action);else{let edited=await editPrompt(prompt);if(edited===null){console.error(" Couldn't open an editor. Set $EDITOR and retry, or copy the prompt above.");return}if(edited===""){console.log(import_picocolors2.default.dim(" Prompt was emptied \u2014 nothing launched."));return}if(finalPrompt=edited,launchers.length>1){let pick=await select({message:"Launch which agent?",options:launchers.map((l)=>({value:l.bin,label:l.label})),...launchers[0]?{initialValue:launchers[0].bin}:{}});if(isCancel(pick))return;launcher=launchers.find((l)=>l.bin===pick)}}if(!launcher)return;finalPrompt=expandHandoffPrompt(finalPrompt,screens);let canvasUrl;try{canvasUrl=(await ensureDaemon(answers.folder)).canvasUrl}catch(err){console.error(` Couldn't start the canvas (${err.message}). Run \`velloo run ${answers.folder}\` yourself, then paste the prompt above.`);return}let openCanvas=await confirm({message:"Open the board in your browser to watch? (your agent runs here in this terminal and may ask for MCP approval first)",initialValue:!0});if(!isCancel(openCanvas)&&openCanvas)await openUrl(canvasUrl);console.log(""),console.log(` Canvas running at ${import_picocolors2.default.cyan(canvasUrl)}.`),console.log(import_picocolors2.default.dim(` Launching ${launcher.label} here \u2014 it may ask you to approve the velloo MCP server first.`)),await Bun.spawn(launcher.argv(finalPrompt),{stdout:"inherit",stderr:"inherit",stdin:"inherit"}).exited}var import_picocolors3=__toESM(require_picocolors(),1),RGB={amber:[255,171,31],coral:[255,111,77]},ANSI256={amber:214,coral:209},TAGLINE="Design like a developer. Build like a designer.",V=[" "," ","oooo ooo"," `88. .8' "," `88..8' "," `888' "," `8' "],E=[" "," "," .ooooo. ","d88' `88b","888ooo888","888 .o","`Y8bod8P'"],L=["oooo ","`888 "," 888 "," 888 "," 888 "," 888 ","o888o"],O=[" "," "," .ooooo. ","d88' `88b","888 888","888 888","`Y8bod8P'"],MARK=[" .o8888888o. ","d88 88b ","88 .o8888888o. ","88 d88 88 88b","88 88 88 88","Y88 88 88P 88"," `o8888888P' 88"," Y88 88P"," `o8888888P' "],MARK_OWN=[" ccccccccccc ","ccc ccc ","cc aaaaaccaaaa ","cc aaa cc aaa","cc aa cc aa","ccc aa ccc aa"," ccccaaccccc aa"," aaa aaa"," aaaaaaaaaaa "];function supportsTruecolor(){let colorterm=process.env.COLORTERM??"";if(/truecolor|24bit/i.test(colorterm))return!0;if(process.env.TERM_PROGRAM==="Apple_Terminal")return!1;let program=process.env.TERM_PROGRAM??"";if(["iTerm.app","vscode","ghostty","WarpTerminal","WezTerm"].includes(program))return!0;return/truecolor|-direct$/i.test(process.env.TERM??"")}function paint(frame,text){if(!text||!import_picocolors3.default.isColorSupported)return text;if(supportsTruecolor()){let[r,g,b]=RGB[frame];return`\x1B[38;2;${r};${g};${b}m${text}\x1B[39m`}return`\x1B[38;5;${ANSI256[frame]}m${text}\x1B[39m`}function paintMarkRow(chars,owners){let out="",i=0;while(i<chars.length){let who=owners[i],j=i+1;while(j<owners.length&&owners[j]===who)j++;let slice=chars.slice(i,j);out+=who==="c"?paint("coral",slice):who==="a"?paint("amber",slice):slice,i=j}return out}function renderLogo(){return[...MARK.map((chars,i)=>{let mark=paintMarkRow(chars,MARK_OWN[i]??""),k=i-1,v=V[k],o=O[k],right=v===void 0||o===void 0?"":` ${import_picocolors3.default.bold(`${v}${E[k]}${L[k]}${L[k]}`)}${paint("amber",o)} ${paint("coral",o)}`;return` ${mark}${right}`}),""," "+import_picocolors3.default.dim(TAGLINE)].join(`
52
- `)}function printLogo(){console.log(""),console.log(renderLogo()),console.log("")}import{resolve as resolve8}from"path";var import_picocolors7=__toESM(require_picocolors(),1);var import_picocolors6=__toESM(require_picocolors(),1);var import_picocolors4=__toESM(require_picocolors(),1),DEFAULT_COMPONENTS_DIR="src/components/ui";function isAborted(value){return isCancel(value)}function subtitled(message,subtitle){return`${message}
53
- ${import_picocolors4.default.dim(subtitle)}`}function subtitledText(message,subtitle){return`${message}
54
- ${import_picocolors4.default.gray("\u2502")} ${import_picocolors4.default.dim(subtitle)}`}function noteSetup(appRoot,folder){note(import_picocolors4.default.dim(`App root: ${appRoot}
55
- Design: ${folder}`),"Setup")}var import_picocolors5=__toESM(require_picocolors(),1);async function promptShareAndFeedback(appRoot){let cloudUrl=defaultCloudUrl(),signedIn=!1,answered=await readRepoFeedback(appRoot);if(answered)return log.info(`Feedback tool: ${answered.enabled?"on":"off"} ${import_picocolors5.default.dim("(already set for this repo)")}`),{};let existing=await loadCredential(cloudUrl),existingEmail=existing?await verifyCredential(cloudUrl,existing.token):null;if(existingEmail)note(`Signed in as ${existingEmail}.`,"Velloo cloud"),signedIn=!0;if(!signedIn){let ok=await promptSignIn(cloudUrl);if(ok===null)return null;signedIn=ok}if(!signedIn)return{};let details=["The `send_feedback` tool lets your agent send free-text product feedback","about Velloo itself \u2014 a confusing tool, a missing capability, something","that slowed it down. Never about your design or your project.","","How it behaves:"," - The agent always shows you the exact message and asks before sending."," - It is instructed to never include your design content, code, or"," file/repo paths \u2014 only a plain-prose description of the issue.",' - "Yes": anonymous by construction \u2014 the message is sent with a'," blind-signed token (RFC 9474) instead of your account, so the server"," can verify it came from a real signed-in user but cannot tell which"," one. The whole flow lives in velloo's open-source CLI, so you don't"," have to take the cloud's word for it.",' - "Yes \u2014 contact OK": sent from your account so we can reply by email.',` - "No": the tool is never registered, so the agent can't send anything.`].join(`
56
- `),choice;for(;;){let picked=await select({message:"Enable the feedback tool? Your agent can send Velloo product feedback to improve it.",options:[{value:"yes",label:"Yes \u2014 anonymous feedback",hint:"agent always confirms with you before sending"},{value:"yes-contact",label:"Yes \u2014 and it's OK to contact me about it",hint:"we may follow up by email"},{value:"no",label:"No",hint:"the tool is disabled entirely"},{value:"details",label:"What exactly gets sent?",hint:"prints details, then re-asks"}],initialValue:"yes"});if(isAborted(picked))return null;if(picked!=="details"){choice=picked;break}note(details,"The feedback tool")}if(choice==="no")return{};if(choice==="yes"){let cred=await loadCredential(cloudUrl);if(cred){let spin=spinner();spin.start("Stocking anonymous feedback tokens"),await topUpTokens({url:cloudUrl,token:cred.token},10).then(()=>spin.stop("Anonymous feedback tokens ready")).catch(()=>spin.stop("Feedback enabled \u2014 tokens will be fetched on first send"))}}return{feedback:{enabled:!0,contactOk:choice==="yes-contact"}}}async function promptSignIn(cloudUrl){let wantShare=await confirm({message:"Share your designs for free? Sign up to publish branded share links.",initialValue:!0});if(isAborted(wantShare))return null;if(!wantShare)return!1;let spin=spinner(),signedIn=!1,controller=new AbortController,hadRaw=process.stdin.isRaw??!1;if(process.stdin.isTTY&&!hadRaw)process.stdin.setRawMode(!0),process.stdin.resume();let onKey=(buf)=>{if(buf[0]===27)controller.abort()};process.stdin.on("data",onKey);try{let cred=await performDeviceLogin(cloudUrl,({verificationUrl,userCode})=>{note(`Opening your browser to sign up (or sign in).
57
- If it doesn't open, visit:
58
- ${import_picocolors5.default.cyan(verificationUrl)}
59
- and enter the code: ${import_picocolors5.default.bold(userCode)}
60
-
61
- ${import_picocolors5.default.dim("Press Esc to skip and continue without signing in.")}`,"Sign up"),spin.start("Waiting for sign-in (Esc to skip)")},controller.signal);await saveCredential(cloudUrl,cred),spin.stop(`Signed in as ${cred.email}`),signedIn=!0}catch(err){if(controller.signal.aborted)spin.stop("Sign-in skipped \u2014 continuing without it.");else spin.stop("Sign-in failed"),note(`Couldn't sign in (${err instanceof Error?err.message:String(err)}).
62
- You can run ${import_picocolors5.default.cyan("velloo login")} anytime later.`,"Heads up")}finally{if(process.stdin.off("data",onKey),controller.signal.aborted&&process.stdin.isTTY){let drain=()=>{};process.stdin.on("data",drain),await new Promise((r)=>setTimeout(r,150)),process.stdin.off("data",drain)}if(process.stdin.isTTY&&!hadRaw)process.stdin.setRawMode(!1),process.stdin.pause()}return signedIn}var UI_LIBRARY_NAMES={shadcn:"shadcn",mui:"Material UI",antd:"Ant Design",chakra:"Chakra UI"};function describeDetected(d){let ui,canvas;if(d.uiLibrary==="shadcn")ui=`shadcn${d.shadcnStyle?` (${d.shadcnStyle})`:""}`,canvas="Velloo's own bundled shadcn components \u2014 your app's files are not imported, so designs stay in sync by matching the same upstream shadcn";else if(d.uiLibrary){let name=UI_LIBRARY_NAMES[d.uiLibrary];ui=name,canvas=`real ${name} components bundled with Velloo`}else if(d.unsupportedUi)ui=`${d.unsupportedUi} (no Velloo adapter yet)`,canvas="Velloo's no-library primitives stand in";else ui="none detected",canvas="Velloo's own bundled shadcn components";return[`UI library: ${ui}`,`Canvas uses: ${canvas}`,`Tailwind: ${d.tailwindMajor?`v${d.tailwindMajor}`:"not detected"}`,`theme css: ${d.globalsCssPath??"not found \u2014 will use a preset"}`].join(`
63
- `)}async function resolveComponentsDir(appRoot,hasHostApp,inherited){if(inherited)return{value:inherited};if(!hasHostApp)return{value:DEFAULT_COMPONENTS_DIR};let found=findComponentsDir(appRoot);if(found)return{value:found};let typed=await text({message:subtitledText("Components subfolder inside your app","Where your UI components live \u2014 emitted code imports from this path."),placeholder:DEFAULT_COMPONENTS_DIR,defaultValue:DEFAULT_COMPONENTS_DIR});if(isAborted(typed))return null;return{value:typed||DEFAULT_COMPONENTS_DIR}}async function resolveLibrary(ctx,initial=DEFAULT_LIBRARY_ID){if(ctx.pinnedLibrary){if(ctx.pinnedLibraryReason)log.info(`Component library: ${WIZARD_PROVIDERS[ctx.pinnedLibrary].label} ${import_picocolors6.default.dim(`(${ctx.pinnedLibraryReason})`)}`);return ctx.pinnedLibrary}let picked=await select({message:subtitled("Component library","What the canvas draws with, and what your emitted code imports."),options:interactiveLibraryChoices(),initialValue:initial});return isAborted(picked)?null:picked}async function tryAdoptLibraryFromApp(appRoot,scanDir){let spin=spinner();spin.start("Detecting your app's UI library");try{let primary=(await scanApps(appRoot,scanDir)).apps[0],scanRoot=primary?.dir??appRoot,detected=detectHost(scanRoot),adopted=scanAdoption(detected);if(spin.stop(adopted?`Detected ${WIZARD_PROVIDERS[adopted.library].label}`:"No UI library detected \u2014 you'll pick one next."),!adopted)return null;return{library:adopted.library,detected,scanRoot,stack:stackForFramework(primary?.framework)}}catch{return spin.stop("Couldn't scan the app \u2014 you'll pick a library next."),null}}async function promptLibraryThemePath(ctx,folder,agentWiring,initialContent,extra={},opts={}){let library=ctx.pinnedLibrary??DEFAULT_LIBRARY_ID;if(!opts.skipLibrary){let picked=await resolveLibrary(ctx);if(picked===null)return null;library=picked}let provider=WIZARD_PROVIDERS[library],source=provider.defaultSource,componentsRelative=DEFAULT_COMPONENTS_DIR;if(!opts.libraryOnly&&provider.asksComponentsSubfolder){let dir=await resolveComponentsDir(ctx.appRoot,ctx.hasHostApp,ctx.inheritComponentsDir);if(!dir)return null;componentsRelative=dir.value}let themePreset=initialContent==="blank"?"zinc":DEFAULT_THEME_PRESET,share=await promptShareAndFeedback(ctx.appRoot);if(share===null)return null;return noteSetup(ctx.appRoot,folder),{appRoot:ctx.appRoot,scanRoot:extra.scanRoot??ctx.appRoot,folder,library,source,componentsRelative,initialContent,themePreset,stack:extra.stack??DEFAULT_STACK_ID,...agentWiring?{agentWiring}:{},...share,...extra}}async function promptRedesignScreen(ctx,folder,agentWiring){let how=await select({message:subtitled("Which screen should your agent redesign?","Scanning finds your real routes; typing a name works for a screen that doesn't exist yet."),options:[{value:"scan",label:"Pick from my app's routes",hint:"Scan routes and choose one"},{value:"type",label:"Type a screen name",hint:"e.g. Pricing, Settings, Checkout"}],initialValue:"scan"});if(isAborted(how))return null;let selectedRoutes,screenName,scanRoot=ctx.appRoot,detected,library=ctx.pinnedLibrary??DEFAULT_LIBRARY_ID,stack=DEFAULT_STACK_ID;if(how==="scan"){let spin=spinner();spin.start("Scanning your app's routes");let scanned=await scanApps(ctx.appRoot,ctx.scanDir),appsSuffix=scanned.apps.length>1?` across ${scanned.apps.length} apps`:"";if(spin.stop(scanned.routes.length>0?`Found ${scanned.routes.length} screen${scanned.routes.length===1?"":"s"}${appsSuffix}`:"No routes detected \u2014 type a screen name instead."),scanned.routes.length===0){let typed=await promptScreenName();if(typed===null)return null;screenName=typed}else{let rankPrimary=scanned.apps[0];if(scanned.apps.length>1){let lines=scanned.apps.map((a)=>`${import_picocolors7.default.cyan(a.rel||".")} \u2014 ${a.routes.length} screen${a.routes.length===1?"":"s"}`);note(lines.join(`
64
- `),`Found ${scanned.apps.length} apps`)}let host=detectHost(rankPrimary?.dir??ctx.appRoot);note(describeDetected(host),"Detected in your app");let picked=await pickOneScreen(scanned);if(picked===null)return null;selectedRoutes=[picked],screenName=picked.name;let primary=primaryApp(scanned.apps,[picked])??rankPrimary;if(scanRoot=primary?.dir??ctx.appRoot,primary&&primary!==rankPrimary)host=detectHost(primary.dir);if(detected=host,stack=stackForFramework(primary?.framework),!ctx.pinnedLibrary){let adopted=scanAdoption(host);if(adopted)library=adopted.library}}}else{let typed=await promptScreenName();if(typed===null)return null;if(screenName=typed,!ctx.pinnedLibrary){let adopted=await tryAdoptLibraryFromApp(ctx.appRoot,ctx.scanDir);if(adopted)note(describeDetected(adopted.detected),"Detected in your app"),detected=adopted.detected,scanRoot=adopted.scanRoot,library=adopted.library,stack=adopted.stack}}let adoptedLibrary=detected?scanAdoption(detected)?.library:void 0,rest=await promptLibraryThemePath({...ctx,pinnedLibrary:ctx.pinnedLibrary??adoptedLibrary??library},folder,agentWiring,"redesign-screen",{screenName,selectedRoutes,detected,scanRoot,stack},{skipLibrary:Boolean(ctx.pinnedLibrary||adoptedLibrary),libraryOnly:Boolean(adoptedLibrary)});if(!rest)return null;let finalLibrary=ctx.pinnedLibrary??adoptedLibrary??rest.library;return{...rest,library:finalLibrary,source:WIZARD_PROVIDERS[finalLibrary].defaultSource,scanRoot,...detected?{detected}:{},...selectedRoutes?{selectedRoutes}:{},...screenName?{screenName}:{}}}async function promptScreenName(){let typed=await text({message:"Screen name",placeholder:"e.g. Pricing",validate(value){if(!value?.trim())return"Enter a screen name.";return}});return isAborted(typed)?null:String(typed).trim()}async function pickOneScreen(scanned){let{routes}=scanned,choice=await select({message:"Which screen?",options:routes.map((r)=>({value:r.id,label:r.name,hint:r.routePath})),...routes[0]?{initialValue:routes[0].id}:{}});if(isAborted(choice))return null;return routes.find((r)=>r.id===choice)??null}async function promptSample(ctx,folder,agentWiring){let library=await resolveLibrary(ctx);if(library===null)return null;let provider=WIZARD_PROVIDERS[library],source=provider.defaultSource,componentsRelative=DEFAULT_COMPONENTS_DIR;if(provider.asksComponentsSubfolder){let dir=await resolveComponentsDir(ctx.appRoot,ctx.hasHostApp,ctx.inheritComponentsDir);if(!dir)return null;componentsRelative=dir.value}let share=await promptShareAndFeedback(ctx.appRoot);if(share===null)return null;return noteSetup(ctx.appRoot,folder),{appRoot:ctx.appRoot,scanRoot:ctx.appRoot,folder,library,source,componentsRelative,initialContent:"sample",themePreset:DEFAULT_THEME_PRESET,stack:DEFAULT_STACK_ID,...agentWiring?{agentWiring}:{},...share}}async function buildBlankAnswers(ctx,folder,agentWiring,defaultLibrary="none"){let library=await resolveLibrary(ctx,defaultLibrary);if(library===null)return null;let share=await promptShareAndFeedback(ctx.appRoot);if(share===null)return null;return noteSetup(ctx.appRoot,folder),{appRoot:ctx.appRoot,scanRoot:ctx.appRoot,folder,library,source:WIZARD_PROVIDERS[library].defaultSource,componentsRelative:ctx.inheritComponentsDir??DEFAULT_COMPONENTS_DIR,initialContent:"blank",themePreset:"zinc",stack:DEFAULT_STACK_ID,...agentWiring?{agentWiring}:{},...share}}async function promptGoalWithAdoptedLibrary(ctx,folder,agentWiring,initialContent,extra={}){let adopted=ctx.pinnedLibrary?null:await tryAdoptLibraryFromApp(ctx.appRoot,ctx.scanDir);if(adopted)note(describeDetected(adopted.detected),"Detected in your app"),note(`Using ${WIZARD_PROVIDERS[adopted.library].label}.`,"Library");return promptLibraryThemePath({...ctx,pinnedLibrary:ctx.pinnedLibrary??adopted?.library},folder,agentWiring,initialContent,{...extra,...adopted?{detected:adopted.detected,scanRoot:adopted.scanRoot,stack:adopted.stack}:{}},{skipLibrary:Boolean(ctx.pinnedLibrary||adopted),libraryOnly:Boolean(adopted)})}function folderPathProblem(abs,shown){if(isDesignFolderSync(abs))return`${shown} is already a Velloo design folder \u2014 pick another path.`;if(!isEmptyOrMissingSync(abs))return`${shown} isn't empty \u2014 pick an empty path (or delete it first).`;return}function cancelled(){return cancel("Cancelled \u2014 no files were written."),{status:"abort"}}function outcome(answers){return answers?{status:"ok",answers}:cancelled()}function hostGoalOptions(hasHostApp){let selfContained=[{value:"sample",label:"Elsewhere welcome sample",hint:"Travel app with imagery, dark mode and three agentic trip explorations"},{value:"blank",label:"Blank",hint:"Empty canvas \u2014 you and your agent build it from nothing"}];if(!hasHostApp)return[{value:"capture-site",label:"Design from a live site",hint:"Open a browser, log in if needed, capture pages \u2014 then design from them"},...selfContained];return[{value:"redesign-screen",label:"Redesign a screen",hint:"Recreate one of your pages, then explore alternatives"},{value:"redesign-component",label:"Redesign a component",hint:"One region or widget \u2014 recreate it, then try variations"},{value:"custom",label:"Custom request",hint:"Describe any design you need and start there"},...selfContained]}async function promptBrief(opts){let answer=await text({message:subtitledText(opts.message,opts.subtitle),placeholder:opts.placeholder,validate:(value)=>opts.validate(value?.trim()??"")});return isAborted(answer)?null:String(answer).trim()}async function runInteractive(ctx){let folderDefault=ctx.secondFolder?"velloo-brand":"velloo",folderBase=ctx.folderBase??ctx.appRoot;if(ctx.presetFolder){let problem=folderPathProblem(resolve8(folderBase,ctx.presetFolder),ctx.presetFolder);if(problem)return cancel(problem),cancelled()}let folderInput=ctx.presetFolder??await text({message:subtitledText("Design folder name or path",ctx.secondFolder?"A second canvas in this repo \u2014 its own boards, theme, daemon and MCP endpoint.":"Your designs are plain files that live in this repo \u2014 commit them alongside your code."),placeholder:folderDefault,defaultValue:folderDefault,validate(value){let raw=(value||folderDefault).trim();if(raw==="")return"Path can't be empty.";return folderPathProblem(resolve8(folderBase,raw),raw)}});if(isAborted(folderInput))return cancelled();let folder=resolve8(folderBase,folderInput||folderDefault),root=await checkoutRoot(ctx.appRoot,folderBase),local=!isWithin(root,folder);if(local&&!ctx.presetFolder)log.info(`${folder} is outside ${root}, so it will be a local design: recorded only on this machine, not in velloo.json, and not version-controlled by this repo.`);let agentWiring;if(ctx.connectEnabled){let wiring=await askAgentWiring({skipWhenCovered:!0,projectRoot:root,globalOnly:local});if(wiring===null)return cancelled();agentWiring=wiring}let hasHostApp=(await discoverScanRoots(ctx.appRoot)).length>0,hostCtx={...ctx,hasHostApp},goal=await select({message:subtitled("How do you want to start your board?","Pick a real design task \u2014 your agent starts on it as soon as init finishes."),options:hostGoalOptions(hasHostApp),initialValue:hasHostApp?"redesign-screen":"sample"});if(isAborted(goal))return cancelled();if(goal==="redesign-screen")return outcome(await promptRedesignScreen(hostCtx,folder,agentWiring));if(goal==="redesign-component"){let desc=await promptBrief({message:"Component name or description",subtitle:"Whatever you'd call it in a code review \u2014 the agent finds it from this.",placeholder:"e.g. sidebar, pricing card, filter chip row",validate:(v)=>v?void 0:"Describe the component so the agent knows what to redesign."});if(desc===null)return cancelled();return outcome(await promptGoalWithAdoptedLibrary(hostCtx,folder,agentWiring,"component",{componentDescription:desc}))}if(goal==="custom"){let request=await promptBrief({message:"What design do you need?",subtitle:"A sentence is enough \u2014 it becomes the brief your agent works from.",placeholder:"e.g. a pricing page with three tiers and a FAQ",validate:(v)=>v?void 0:"Describe what you want designed."});if(request===null)return cancelled();return outcome(await promptGoalWithAdoptedLibrary(hostCtx,folder,agentWiring,"custom",{customRequest:request}))}if(goal==="capture-site"){let url=await promptBrief({message:"Site to design from",subtitle:"Init won't open it \u2014 your agent starts a capture session so you can log in first.",placeholder:"e.g. https://app.example.com/dashboard",validate(v){if(!v)return"Enter the URL of the site you want to design from.";try{let scheme=new URL(v).protocol;if(scheme!=="http:"&&scheme!=="https:")return"Use an http(s) URL."}catch{return"That doesn't look like a URL."}return}});if(url===null)return cancelled();return outcome(await promptGoalWithAdoptedLibrary(hostCtx,folder,agentWiring,"custom",{captureUrl:url,customRequest:`Recreate the pages I capture from ${url}, then explore alternatives.`}))}if(goal==="blank")return outcome(await buildBlankAnswers(ctx,folder,agentWiring));return outcome(await promptSample(hostCtx,folder,agentWiring))}var import_picocolors8=__toESM(require_picocolors(),1);var NOT_WIRED={wiredIds:[]};async function applyAgentWiring(folder,wiring){let result;if(wiring.agents.length>0)try{result=await connect({designFolder:folder,agents:wiring.agents,installSkill:!0})}catch{result=void 0}if(wiring.manual){console.log(""),console.log(import_picocolors8.default.bold(" Manual MCP setup"));for(let line of manualSetupText().split(`
65
- `))console.log(` ${line}`)}return{connected:result,wiredIds:[...wiring.preWired,...result?.configs.map((c)=>c.agent)??[]]}}function printWired(outcome){let connected=outcome.connected;if(!connected||connected.configs.length===0)return;let wired=connected.configs.map((c)=>c.agent).join(" + ");if(console.log(""),console.log(import_picocolors8.default.bold(" Agents wired")),console.log(` ${import_picocolors8.default.green("\u2713")} ${wired} ${import_picocolors8.default.dim(`(MCP config under ${connected.projectRoot})`)}`),connected.plugin)console.log(import_picocolors8.default.dim(" + Claude Code plugin (skills \xB7 commands \xB7 subagents)"));if(connected.skills?.length)console.log(import_picocolors8.default.dim(` + ${connected.skills.length} agent skill${connected.skills.length===1?"":"s"} (.agents/skills)`));if(connected.geminiExtension)console.log(import_picocolors8.default.dim(` + Gemini extension${connected.geminiExtension.linked?"":` (link it: gemini extensions link ${connected.geminiExtension.dir})`}`));if(connected.cursorRules?.installed)console.log(import_picocolors8.default.dim(" + Cursor rule"))}import{resolve as resolve10}from"path";var import_picocolors11=__toESM(require_picocolors(),1);import{mkdir as mkdir2,readdir as readdir5,readFile as readFile7,writeFile as writeFile2}from"fs/promises";import{join as join10,relative as relative8,resolve as resolve9}from"path";var import_picocolors9=__toESM(require_picocolors(),1);import{existsSync as existsSync4,readFileSync}from"fs";import{join as join9}from"path";var IDENT_CHAR=/[A-Za-z0-9_$]/;function skipWs(code,i){while(i<code.length&&/\s/.test(code.charAt(i)))i++;return i}function scanString(code,i){let quote=code.charAt(i);i++;while(i<code.length){let ch=code.charAt(i);if(ch==="\\"){i+=2;continue}if(ch===quote)return i+1;if(quote==="`"&&ch==="$"&&code.charAt(i+1)==="{"){i=scanBalanced(code,i+1);continue}if(quote!=="`"&&ch===`
44
+ ${native?.css??""}`,assetMetadata:structuredClone(assets_default),assetFiles:{"assets/elsewhere-alps.jpg":resolve3(import.meta.dir,elsewhere_alps_default),"assets/elsewhere-bali.jpg":resolve3(import.meta.dir,elsewhere_bali_default),"assets/elsewhere-forest.jpg":resolve3(import.meta.dir,elsewhere_forest_default),"assets/elsewhere-japan.jpg":resolve3(import.meta.dir,elsewhere_japan_default),"assets/elsewhere-kyoto-map.svg":resolve3(import.meta.dir,elsewhere_kyoto_map_default),"assets/elsewhere-kyoto.jpg":resolve3(import.meta.dir,elsewhere_kyoto_default),"assets/elsewhere-room.jpg":resolve3(import.meta.dir,elsewhere_room_default)},documents:{"ASSET-SOURCES.md":ASSET_SOURCES_default}}}function bundledComponentsSection(){return["## Bundled components","","The shadcn snapshot lives inside the velloo binary. No files were","written to your app. When you're ready to bring shadcn into your","project, run `npx shadcn@latest init` there separately, then","`velloo theme export <app>` to align the theme.",""]}var WIZARD_PROVIDERS={"shadcn-upstream":{label:"shadcn",hint:"Real shadcn, Tailwind classes. Recommended.",order:0,defaultSource:"in-repo",asksComponentsSubfolder:!0,scanScreenOpts:{hasBadge:!0},planInstall(answers){let targetDir=resolve4(answers.appRoot,answers.componentsRelative);return{library:{id:"shadcn-upstream",version:snapshotVersion2,source:"in-repo",componentsPath:relative4(answers.folder,dirname4(targetDir)).split(sep4).join("/")||"."},summary:{name:"shadcn (upstream)",location:`canvas reads client-safe components from ${answers.componentsRelative}; canvas-safe fallbacks cover missing or unsupported files`},pendingUpstream:{targetDir,relative:answers.componentsRelative}}},buildSampleScaffold:(theme)=>buildElsewhereScaffold("shadcn-upstream",theme),stylingFor:()=>{return},scanMatch:(detected)=>detected.uiLibrary==="shadcn",scanNote:(detected)=>`Detected ${detected.uiLibrary} \u2014 using that library.`,handoffComponentsLabel:"shadcn",readmeComponentsSection:(plan)=>plan.pendingUpstream?["## Bringing shadcn into your app","","Init did not write anything into your app. To add shadcn at",`\`${plan.pendingUpstream.relative}\`, ask your AI`,"agent (it was wired up during init) to finish setup \u2014 or run","`npx shadcn@latest add <component>` yourself. Client-safe files render","directly from the repo; overlays use labeled canvas adaptations and","broken or missing files visibly fall back to Velloo's snapshot. Then","`velloo theme export <app>` aligns the theme.",""]:bundledComponentsSection()},none:{label:"No library",hint:"Plain Box / Stack / Text primitives.",order:9,defaultSource:"binary",asksComponentsSubfolder:!1,scanScreenOpts:{hasBadge:!1},planInstall:()=>({library:{id:"none",version:noLibVersion,source:"binary",componentsPath:"binary"},summary:{name:`no-library primitives (${noLibVersion})`,location:"bundled with velloo"}}),buildSampleScaffold:(theme)=>buildElsewhereScaffold("none",theme),stylingFor:(answers)=>({framework:answers.detected?.tailwindMajor?"tailwind":"none"}),scanMatch:(detected)=>Boolean(detected.unsupportedUi),scanNote:(detected)=>`Detected ${detected.unsupportedUi} (no Velloo adapter) \u2014 the no-framework adapter supplies the primitives, and your ${detected.unsupportedUi} components render from your own install once the setup step writes their preview entry.`,handoffComponentsLabel:"velloo primitive",readmeComponentsSection:()=>["## Components","","Velloo's no-framework primitives ship inside the velloo binary. Your","app's own components \u2014 including ones from a UI framework Velloo has no","adapter for \u2014 appear on the Repo shelves of the canvas Library and render","from your own install, inside this design's preview entry (`preview.tsx`","here; the setup step writes it). `emit_code` keeps their exact imports.",""]},mui:{label:"Material UI",hint:"Real @mui/material, sx styling.",order:4,defaultSource:"binary",asksComponentsSubfolder:!1,scanScreenOpts:{hasBadge:!0,tree:"mui"},planInstall:()=>({library:{id:"mui",version:MUI_VERSION,source:"binary",componentsPath:"binary"},summary:{name:`Material UI v${MUI_VERSION}`,location:"bundled with velloo"}}),buildSampleScaffold:(theme)=>buildElsewhereScaffold("mui",theme),stylingFor:()=>{return},scanMatch:(detected)=>detected.uiLibrary==="mui",scanNote:(detected)=>`Detected ${detected.uiLibrary} \u2014 using that library.`,handoffComponentsLabel:"Material UI",readmeComponentsSection:()=>["## Material UI in your app","","The canvas renders **real Material UI** components (bundled with velloo,","emotion-rendered) \u2014 no files were written to your app. When you implement","a screen, `emit_code` emits idiomatic MUI (`sx` props + `@mui/material`","imports) and `emit_theme` emits a `createTheme(...)` module. For that code","to build, install the runtime deps in your app:","","```bash","npm install @mui/material @emotion/react @emotion/styled","```","","Once installed, velloo can also client-render the canvas against your","app's exact MUI version. Style nodes with the `sx` editor (canvas) or","`update_props`'s `style` (agent).",""]},antd:{label:"Ant Design",hint:"Real antd v5, inline style objects.",order:2,defaultSource:"binary",asksComponentsSubfolder:!1,scanScreenOpts:{hasBadge:!0,tree:"antd"},planInstall:()=>({library:{id:"antd",version:ANTD_VERSION,source:"binary",componentsPath:"binary"},summary:{name:`Ant Design v${ANTD_VERSION}`,location:"bundled with velloo"}}),buildSampleScaffold:(theme)=>buildElsewhereScaffold("antd",theme),stylingFor:()=>{return},scanMatch:(detected)=>detected.uiLibrary==="antd",scanNote:(detected)=>`Detected ${detected.uiLibrary} \u2014 using that library.`,handoffComponentsLabel:"Ant Design",readmeComponentsSection:()=>["## Ant Design in your app","","The canvas renders **real Ant Design** components (bundled with velloo,","cssinjs-rendered) \u2014 no files were written to your app. When you implement","a screen, `emit_code` emits idiomatic antd (inline `style` objects +","`antd` imports) and `emit_theme` emits a ConfigProvider `ThemeConfig`","module. For that code to build, install the runtime dep in your app:","","```bash","npm install antd","```","","Style nodes with the inline-style editor (canvas) or `update_props`'s `style` (agent).",""]},chakra:{label:"Chakra UI",hint:"Real Chakra v2, sx styling.",order:3,defaultSource:"binary",asksComponentsSubfolder:!1,scanScreenOpts:{hasBadge:!0,tree:"chakra"},planInstall:()=>({library:{id:"chakra",version:CHAKRA_VERSION,source:"binary",componentsPath:"binary"},summary:{name:`Chakra UI v${CHAKRA_VERSION}`,location:"bundled with velloo"}}),buildSampleScaffold:(theme)=>buildElsewhereScaffold("chakra",theme),stylingFor:()=>{return},scanMatch:(detected)=>detected.uiLibrary==="chakra",scanNote:(detected)=>`Detected ${detected.uiLibrary} \u2014 using that library.`,handoffComponentsLabel:"Chakra UI",readmeComponentsSection:()=>["## Chakra UI in your app","","The canvas renders **real Chakra UI v2** components (bundled with velloo,","emotion-rendered) \u2014 no files were written to your app. When you implement","a screen, `emit_code` emits idiomatic chakra (`sx` props +","`@chakra-ui/react` imports) and `emit_theme` emits an `extendTheme(...)`","module. For that code to build, install the runtime deps in your app:","","```bash","npm install @chakra-ui/react@2 @emotion/react @emotion/styled framer-motion","```","","Style nodes with the `sx` editor (canvas) or `update_props`'s `style` (agent).",""]}},LIBRARY_IDS=Object.keys(WIZARD_PROVIDERS),DEFAULT_LIBRARY_ID="shadcn-upstream";function interactiveLibraryChoices(){return LIBRARY_IDS.toSorted((a,b)=>WIZARD_PROVIDERS[a].order-WIZARD_PROVIDERS[b].order).map((id)=>({value:id,label:WIZARD_PROVIDERS[id].label,hint:WIZARD_PROVIDERS[id].hint}))}function planInstall(answers){return WIZARD_PROVIDERS[answers.library].planInstall(answers)}function sampleScaffold(answers,theme){return WIZARD_PROVIDERS[answers.library].buildSampleScaffold(theme,answers)}function scanAdoption(detected){for(let id of LIBRARY_IDS){let entry=WIZARD_PROVIDERS[id];if(entry.scanMatch?.(detected))return{library:id,note:entry.scanNote?.(detected)??""}}return}import{copyFile,mkdir,readdir as readdir4}from"fs/promises";import{join as join7,relative as relative5,resolve as resolve5,sep as sep5}from"path";function buildDefaultConfig(opts={}){return{schemaVersion:CURRENT_SCHEMA_VERSION,toolVersion:TOOL_VERSION,name:opts.name??"design",folderId:crypto.randomUUID(),libraries:{default:opts.library??{id:"shadcn-upstream",version:snapshotVersion2,source:"binary",componentsPath:"binary"}},defaultLibrary:"default",viewportPresets:[{name:"Mobile",w:390,h:844},{name:"Tablet",w:768,h:1024},{name:"Desktop",w:1440,h:900}],...opts.defaultScreen?{defaultScreen:opts.defaultScreen}:{},...opts.defaultBoard?{defaultBoard:opts.defaultBoard}:{},...opts.hostApp?{hostApp:opts.hostApp}:{},...opts.hostApps?{hostApps:opts.hostApps}:{},...opts.feedback?{feedback:opts.feedback}:{},...opts.styling?{styling:opts.styling}:{},...opts.codegen?{codegen:opts.codegen}:{}}}var DESKTOP={w:1280,h:800},MOBILE2={w:390,h:844,gap:40};function slugifyName(name,fallback="screen"){return name.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||fallback}function placeholderTree(label){return{$ref:"Box",props:{className:"flex min-h-screen flex-col items-center justify-center gap-3 p-8"},children:[{$ref:"Heading",props:{children:label,className:"text-2xl font-semibold"}},{$ref:"Text",props:{children:"Placeholder \u2014 ask your agent to recreate this, then explore alternatives.",className:"text-muted-foreground text-sm"}}]}}function desktopMobileFrames(screenId,label){return[{id:`f-${screenId}`,screen:screenId,x:80,y:80,w:DESKTOP.w,h:DESKTOP.h,label},{id:`f-${screenId}-m`,screen:screenId,x:80+DESKTOP.w+MOBILE2.gap,y:80,w:MOBILE2.w,h:MOBILE2.h,label:`${label} \xB7 Mobile`}]}function redesignScreenScaffold(theme,screenName){let id=slugifyName(screenName),screen={id,name:screenName.trim()||id,tree:placeholderTree(screenName.trim()||id)},board={id:"main",name:"Main",frames:desktopMobileFrames(id,screen.name),groups:[]};return{theme,screens:[screen],boards:[board],snippets:[],annotations:[],notes:[]}}function componentScaffold(theme,componentDescription){let label=componentDescription.trim()||"Component",id=slugifyName(label,"component"),screen={id,name:label,tree:placeholderTree(label)},board={id:"component",name:"Component",frames:desktopMobileFrames(id,label).map((f)=>({...f,group:"explorations"})),groups:[{id:"explorations",name:"Explorations"}]};return{theme,screens:[screen],boards:[board],snippets:[],annotations:[],notes:[]}}function customRequestScaffold(theme){return{theme,screens:[],boards:[{id:"main",name:"Main",frames:[],groups:[]}],snippets:[],annotations:[],notes:[]}}import{existsSync as existsSync2,readFileSync}from"fs";import{join as join6}from"path";var default_default={name:"forest",colors:{background:"#F8F7F2",foreground:"#203C32",primary:{DEFAULT:"#244D3C",foreground:"#FFFFFF"},secondary:{DEFAULT:"#E9EDDF",foreground:"#294332"},muted:{DEFAULT:"#F0F0E8",foreground:"#626D63"},accent:{DEFAULT:"#E8EDDA",foreground:"#244D3C"},destructive:{DEFAULT:"oklch(0.577 0.245 27)",foreground:"oklch(0.985 0 0)"},card:{DEFAULT:"#FFFFFF",foreground:"#203C32"},popover:{DEFAULT:"oklch(0.99 0.01 145)",foreground:"oklch(0.21 0.04 145)"},border:"#DFE3D8",input:"#DFE3D8",ring:"oklch(0.42 0.12 145)"},colorsDark:{background:"#14251F",foreground:"#F0F1E8",primary:{DEFAULT:"#BED5A4",foreground:"#14251F"},secondary:{DEFAULT:"#2B4235",foreground:"#E8EDDF"},muted:{DEFAULT:"#263D31",foreground:"#B0BEAE"},accent:{DEFAULT:"#304737",foreground:"#E8EDDF"},card:{DEFAULT:"#1C3128",foreground:"#F0F1E8"},border:"#3B5143",input:"#3B5143"},typography:{fontFamily:{sans:'"DM Sans", Arial, sans-serif',mono:"ui-monospace, SFMono-Regular, monospace",display:'"DM Serif Display", Georgia, serif'},googleFonts:["DM+Serif+Display","DM+Sans:wght@400;500;600;700"],typesets:{default:{size:14,leading:1.5,flow:"1.25em",fontBody:"sans",fontHeading:"display",fontMono:"mono"},docs:{size:15,leading:1.75,flow:"1.5em"},chat:{leading:1.6,flow:"1em"},compact:{size:14,leading:1.6,flow:"1em"},reading:{size:18,leading:1.9,flow:"2em"}}},spacing:{"0":0,"1":4,"2":8,"3":12,"4":16,"6":24,"8":32,"12":48,"16":64},radius:{sm:4,md:6,lg:8,xl:12,full:9999}};function buildDefaultTheme(){return structuredClone(default_default)}var THEME_PRESETS=[{id:"elsewhere",label:"Elsewhere",seed:"#244d3c"},{id:"indigo",label:"Indigo",seed:"#5e6ad2"},{id:"violet",label:"Violet",seed:"#7c3aed"},{id:"blue",label:"Blue",seed:"#2563eb"},{id:"emerald",label:"Emerald",seed:"#059669"},{id:"rose",label:"Rose",seed:"#e11d48"},{id:"orange",label:"Orange",seed:"#ea580c"},{id:"amber",label:"Amber",seed:"#d97706"},{id:"zinc",label:"Zinc (neutral)",seed:"#52525b"}],CURATED_PRESET="elsewhere",DEFAULT_THEME_PRESET="elsewhere";function presetById(id){return id?THEME_PRESETS.find((p)=>p.id===id):void 0}function isValidPreset(id){return THEME_PRESETS.some((p)=>p.id===id)}function buildPresetTheme(id,name="default"){let base=buildDefaultTheme(),preset=presetById(id);if(!preset||preset.id===CURATED_PRESET)return{...base,name};let derived=derivePalette(preset.seed,base,name);return derived.ok?derived.value.theme:{...base,name}}var IDENT_CHAR=/[A-Za-z0-9_$]/;function skipWs(code,i){while(i<code.length&&/\s/.test(code.charAt(i)))i++;return i}function scanString(code,i){let quote=code.charAt(i);i++;while(i<code.length){let ch=code.charAt(i);if(ch==="\\"){i+=2;continue}if(ch===quote)return i+1;if(quote==="`"&&ch==="$"&&code.charAt(i+1)==="{"){i=scanBalanced(code,i+1);continue}if(quote!=="`"&&ch===`
66
45
  `)return i;i++}return i}function scanBalanced(code,i){let open=code.charAt(i),close=open==="{"?"}":open==="("?")":"]",depth=0;while(i<code.length){let ch=code.charAt(i);if(ch==='"'||ch==="'"||ch==="`"){i=scanString(code,i);continue}if(ch===open)depth++;else if(ch===close){if(depth--,depth===0)return i+1}i++}return i}function stripComments(src){let out="",i=0;while(i<src.length){let ch=src.charAt(i);if(ch==="/"&&src.charAt(i+1)==="/"){while(i<src.length&&src.charAt(i)!==`
67
46
  `)i++;continue}if(ch==="/"&&src.charAt(i+1)==="*"){i+=2;while(i<src.length&&!(src.charAt(i)==="*"&&src.charAt(i+1)==="/"))i++;i+=2,out+=" ";continue}if(ch==='"'||ch==="'"||ch==="`"){let end=scanString(src,i);out+=src.slice(i,end),i=end;continue}out+=ch,i++}return out}var ESCAPES={n:`
68
47
  `,t:"\t",r:"\r",b:"\b",f:"\f",v:"\v","0":"\x00"};function parseStringLiteral(code,i){let quote=code.charAt(i),out="",j=i+1;while(j<code.length){let ch=code.charAt(j);if(ch==="\\"){let next=code.charAt(j+1);out+=ESCAPES[next]??next,j+=2;continue}if(ch===quote)return{value:out,end:j+1};if(quote==="`"&&ch==="$"&&code.charAt(j+1)==="{")return;if(quote!=="`"&&ch===`
69
- `)return;out+=ch,j++}return}function parseNumber(code,i){let m=/^(?:\d[\d_]*(?:\.[\d_]*)?|\.\d[\d_]*)(?:[eE][+-]?\d+)?/.exec(code.slice(i));if(!m)return;let value=Number(m[0].replace(/_/g,""));if(Number.isNaN(value))return;return{value,end:i+m[0].length}}function parseValue(code,i){let ch=code.charAt(i);if(ch==='"'||ch==="'"||ch==="`")return parseStringLiteral(code,i);if(ch==="{")return parseObjectLiteral(code,i);if(/[\d.]/.test(ch))return parseNumber(code,i);return}function skipEntry(code,i){while(i<code.length){let ch=code.charAt(i);if(ch===","||ch==="}")return i;if(ch==='"'||ch==="'"||ch==="`"){i=scanString(code,i);continue}if(ch==="{"||ch==="("||ch==="["){i=scanBalanced(code,i);continue}i++}return i}function parseObjectLiteral(code,i){let obj=new Map;i++;for(;;){if(i=skipWs(code,i),i>=code.length)return;let ch=code.charAt(i);if(ch==="}")return{value:obj,end:i+1};if(ch===","){i++;continue}let key;if(ch==='"'||ch==="'"){let parsed=parseStringLiteral(code,i);if(parsed)key=parsed.value,i=parsed.end}else{let m=/^[A-Za-z_$][A-Za-z0-9_$]*/.exec(code.slice(i));if(m)key=m[0],i+=m[0].length}if(i=skipWs(code,i),key===void 0||code.charAt(i)!==":"){i=skipEntry(code,i);continue}let parsed=parseValue(code,skipWs(code,i+1));if(parsed){let after=skipWs(code,parsed.end),term=code.charAt(after);if(term===","||term==="}"){obj.set(key,parsed.value),i=after;continue}}i=skipEntry(code,i)}}function findCreateThemeCall(code){let i=0;while(i<code.length){let ch=code.charAt(i);if(ch==='"'||ch==="'"||ch==="`"){i=scanString(code,i);continue}if(ch==="c"&&code.startsWith("createTheme",i)){let before=code.charAt(i-1),after=code.charAt(i+11);if((i===0||!IDENT_CHAR.test(before))&&!IDENT_CHAR.test(after)){let paren=skipWs(code,i+11);if(code.charAt(paren)==="(")return paren}}i++}return}function createThemeArg(src){let code=stripComments(src),paren=findCreateThemeCall(code);if(paren===void 0)return;let arg=skipWs(code,paren+1);if(code.charAt(arg)!=="{")return;return parseObjectLiteral(code,arg)?.value}function prop(obj,name){return obj.get(name)}function asObject(value){return value instanceof Map?value:void 0}function asString(value){return typeof value==="string"?value:void 0}function asNumber(value){return typeof value==="number"?value:void 0}function importThemeFromMui(filePath,presetId){let src;try{src=readFileSync(filePath,"utf8")}catch{return null}let root=createThemeArg(src);if(!root)return null;let palette=asObject(prop(root,"palette")),colors={},warnings=[],tokenCount=0;if(palette){let pairOf=(key)=>{let o=asObject(prop(palette,key));return{main:o&&asString(prop(o,"main")),contrastText:o&&asString(prop(o,"contrastText"))}},text=asObject(prop(palette,"text")),textPrimary=text&&asString(prop(text,"primary")),primary=pairOf("primary");if(primary.main)colors.primary={DEFAULT:primary.main,foreground:primary.contrastText??"#ffffff"},tokenCount++;let secondary=pairOf("secondary");if(secondary.main)colors.secondary={DEFAULT:secondary.main,foreground:secondary.contrastText??"#ffffff"},tokenCount++;let error=pairOf("error");if(error.main)colors.destructive={DEFAULT:error.main,foreground:error.contrastText??"#ffffff"},tokenCount++;let background=asObject(prop(palette,"background")),bgDefault=background&&asString(prop(background,"default")),bgPaper=background&&asString(prop(background,"paper"));if(bgDefault)colors.background=bgDefault,tokenCount++;if(bgPaper)colors.card={DEFAULT:bgPaper,foreground:textPrimary??"#111827"},tokenCount++;if(textPrimary)colors.foreground=textPrimary,tokenCount++;let divider=asString(prop(palette,"divider"));if(divider)colors.border=divider,tokenCount++}let shape=asObject(prop(root,"shape")),borderRadius=shape&&asNumber(prop(shape,"borderRadius")),typography=asObject(prop(root,"typography")),fontFamily=typography&&asString(prop(typography,"fontFamily"));if(tokenCount===0&&borderRadius===void 0&&fontFamily===void 0)return null;let base=buildPresetTheme(presetId,"default");return{theme:{...base,colors:{...base.colors,...colors},radius:borderRadius!==void 0?{...base.radius,md:borderRadius}:base.radius,typography:fontFamily?{...base.typography,fontFamily:{...base.typography.fontFamily,sans:fontFamily}}:base.typography},importedFrom:filePath,tokenCount,warnings}}function findMuiTheme(appRoot){let candidates=["src/theme.ts","src/theme.tsx","src/theme/index.ts","src/theme/index.tsx","theme.ts","src/styles/theme.ts","src/lib/theme.ts","app/theme.ts","src/app/theme.ts"];for(let rel of candidates){let abs=join9(appRoot,rel);if(!existsSync4(abs))continue;try{if(readFileSync(abs,"utf8").includes("createTheme("))return abs}catch{}}return}import{readFileSync as readFileSync2}from"fs";function importThemeFromGlobals(cssPath,presetId){let css;try{css=readFileSync2(cssPath,"utf8")}catch{return null}let parsed=parseThemeCss(css),tokenCount=Object.keys(parsed.colors).length+Object.keys(parsed.colorsDark).length;if(tokenCount===0&&parsed.radius===void 0&&parsed.fontFamily===void 0)return null;let base=buildPresetTheme(presetId,"default");return{theme:{...base,colors:{...base.colors,...parsed.colors},colorsDark:{...base.colorsDark??{},...parsed.colorsDark},radius:parsed.radius!==void 0?{...base.radius,md:parsed.radius}:base.radius,typography:parsed.fontFamily?{...base.typography,fontFamily:{...base.typography.fontFamily,...parsed.fontFamily}}:base.typography},importedFrom:cssPath,tokenCount,warnings:parsed.warnings}}async function readConfig2(folder){return JSON.parse(await readFile7(join10(folder,".design","config.json"),"utf8"))??{}}async function readFolderFacts(folder,appRoot){let config=await readConfig2(folder),libraries=config.libraries??{},defaultLibrary=typeof config.defaultLibrary==="string"?config.defaultLibrary:"",library=libraries[defaultLibrary]?.id??Object.values(libraries)[0]?.id??"unknown",project;try{let manifest=await findProjects(appRoot);if(manifest){for(let[name,path]of manifest.folders)if(resolve9(path)===resolve9(folder))project=name}}catch{}return{folder,library,schemaVersion:schemaVersionOf(config),pendingMigrations:planMigration(config).applied,toolVersionStale:config.toolVersion!==TOOL_VERSION,project}}function displayPath2(path){let rel=relative8(process.cwd(),path);return rel&&rel.length<path.length&&!rel.startsWith("../..")?rel:path}async function inheritedFromFolder(folder){try{let config=await readConfig2(folder),libraries=config.libraries??{},defaultLibrary=typeof config.defaultLibrary==="string"?config.defaultLibrary:"",codegen=config.codegen??{};return{library:libraries[defaultLibrary]?.id??Object.values(libraries)[0]?.id,componentsDir:codegen.componentsDir}}catch{return{library:void 0,componentsDir:void 0}}}function factsLine(facts,folder){let parts=[`${displayPath2(folder)}/`,facts.library,facts.pendingMigrations.length>0?`format v${facts.schemaVersion} \u2192 v${CURRENT_SCHEMA_VERSION}`:`format v${facts.schemaVersion} (current)`];if(facts.project)parts.push(`project "${facts.project}"`);return parts.join(" \xB7 ")}async function promptExistingFolderAction(facts,folder){let options=[];if(facts.pendingMigrations.length>0)options.push({value:"upgrade",label:"Upgrade folder format",hint:`v${facts.schemaVersion} \u2192 v${CURRENT_SCHEMA_VERSION}`});options.push({value:"another",label:"Create another design folder",hint:"a second canvas in this repo"},{value:"connect",label:"Connect agents",hint:"wire the MCP into Claude Code / Cursor"},{value:"scan",label:"Scan for new routes",hint:"add screens for routes you've since added"},{value:"theme",label:"Re-import theme from the app",hint:"pull the app's tokens again"},{value:"check",label:"Check setup",hint:"browser, agent wiring, velloo.json, host app"},{value:"open",label:"Open the canvas",hint:"velloo run"},{value:"cancel",label:"Cancel"}),log.info(import_picocolors9.default.dim(factsLine(facts,folder)));let action=await select({message:"Velloo is already set up here. What would you like to do?",options,initialValue:options[0]?.value??"cancel"});if(isCancel(action))return null;return action}async function runUpgrade(folder){let result=await upgradeFolder(folder);if(result.applied.length===0){console.log(import_picocolors9.default.dim(" Already on the current format \u2014 nothing to do."));return}console.log(`velloo: upgraded ${displayPath2(folder)} (v${result.from} \u2192 v${result.to})`);for(let step of result.applied)console.log(import_picocolors9.default.dim(` ${step}`));console.log(import_picocolors9.default.dim(` Refresh agent skills too with \`velloo upgrade ${displayPath2(folder)}\`.`))}async function runScan(folder,appRoot,scanDir){let scanned=await scanApps(appRoot,scanDir);if(scanned.routes.length===0){log.warn("No routes found \u2014 nothing to add.");return}let existing=[];try{existing=(await readdir5(join10(folder,"screens"))).filter((f)=>f.endsWith(".json")&&!f.endsWith(".annotations.json")).map((f)=>f.slice(0,-5))}catch{}let seen=new Set(existing),fresh=scanned.routes.filter((r)=>!seen.has(r.id));if(fresh.length===0){log.success(`All ${scanned.routes.length} routes already have screens \u2014 nothing to add.`);return}log.info(`${fresh.length} new route${fresh.length===1?"":"s"}: ${fresh.slice(0,8).map((r)=>r.routePath).join(", ")}${fresh.length>8?", \u2026":""}`);let go=await confirm({message:`Add ${fresh.length} placeholder screen(s) on a new board?`});if(isCancel(go)||!go){console.log(import_picocolors9.default.dim(" Nothing changed."));return}let libraries=(await readConfig2(folder)).libraries??{},libraryId=Object.values(libraries)[0]?.id??"shadcn-upstream",scanOpts=WIZARD_PROVIDERS[libraryId]?.scanScreenOpts??{hasBadge:!0},screens=buildScreensFromScan({routes:fresh,...scanOpts}),boards=buildBoardsFromScan({routes:fresh});await mkdir2(join10(folder,"screens"),{recursive:!0}),await mkdir2(join10(folder,"boards"),{recursive:!0});for(let screen of screens)await writeJson(join10(folder,"screens",`${screen.id}.json`),screen);let stamp=new Date().toISOString().slice(0,10),existingBoards=new Set((await readdir5(join10(folder,"boards")).catch(()=>[])).filter((f)=>f.endsWith(".json")&&!f.endsWith(".notes.json")).map((f)=>f.slice(0,-5)));for(let board of boards){let id=`${board.id}-${stamp}`,attempt=2;while(existingBoards.has(id))id=`${board.id}-${stamp}-${attempt++}`;existingBoards.add(id),await writeJson(join10(folder,"boards",`${id}.json`),{...board,id,name:`${board.name} \u2014 new routes ${stamp}`})}log.success(`Added ${screens.length} screen${screens.length===1?"":"s"} on ${boards.length} board${boards.length===1?"":"s"}.`)}async function runThemeReimport(folder,appRoot){let scanRoot=(await scanApps(appRoot)).apps[0]?.dir??appRoot,detected=detectHost(scanRoot),imported=null;if(detected.uiLibrary==="mui"){let themeFile=findMuiTheme(scanRoot);if(themeFile)imported=importThemeFromMui(themeFile)}if(!imported&&detected.globalsCssPath)imported=importThemeFromGlobals(detected.globalsCssPath);if(!imported){log.warn("Couldn't find a theme to import \u2014 no globals.css tokens and no MUI createTheme() in the app.");return}let from=displayPath2(imported.importedFrom);log.info(`Found ${imported.tokenCount} color token(s) in ${from}.`);let go=await confirm({message:"Replace theme/default.json with the app's tokens? Custom edits to it are lost.",initialValue:!1});if(isCancel(go)||!go){console.log(import_picocolors9.default.dim(" Nothing changed."));return}await writeJson(join10(folder,"theme","default.json"),imported.theme),log.success(`Theme re-imported from ${from}.`)}async function runCheckSetup(folder,appRoot){let facts=await readFolderFacts(folder,appRoot),config=await readConfig2(folder),ok=(s)=>console.log(` ${import_picocolors9.default.green("\u2713")} ${s}`),bad=(s)=>console.log(` ${import_picocolors9.default.yellow("!")} ${s}`);if(facts.pendingMigrations.length>0)bad(`folder format v${facts.schemaVersion} \u2014 v${CURRENT_SCHEMA_VERSION} available (\`velloo upgrade <folder>\`)`);else ok(`folder format v${facts.schemaVersion} (current)`);if(facts.toolVersionStale)bad(`agent skills recorded for velloo ${String(config.toolVersion)} \u2014 refresh with \`velloo upgrade <folder>\``);else ok(`agent skills current (velloo ${TOOL_VERSION})`);if(facts.project)ok(`registered in velloo.json as "${facts.project}"`);else bad("not registered in velloo.json \u2014 commands must name the path");let app=await recordedAppRoot(folder).catch(()=>null);if(app)if(!app.exists)bad(`host app ${displayPath2(app.path)} no longer exists`);else if(!app.looksLikeApp)bad(`host app ${displayPath2(app.path)} holds no package.json`);else ok(`host app at ${displayPath2(app.path)}`);let wired=await globallyWiredAgents();if(wired.length>0)ok(`agents wired globally: ${wired.join(", ")}`);else bad('no globally wired agents \u2014 run init again and pick "Connect agents"');let browser=await chromiumExecutable();if(browser)ok("browser installed (screenshots + publish)");else bad(`no browser for screenshots \u2014 install with \`${CHROMIUM_INSTALL_CMD}\``);if(!facts.project){let go=await confirm({message:"Register this folder in velloo.json?"});if(!isCancel(go)&&go){let reg=await registerProject(folder,appRoot);if(reg.created)log.success(`Registered as project "${reg.name}".`);else log.info("Already registered.")}}if(app&&!app.looksLikeApp)await repairAppRoot(folder,app.path);if(!browser)await installChromiumInteractive()}async function repairAppRoot(folder,current){let go=await confirm({message:"Point this design at a different application?"});if(isCancel(go)||!go)return;let target=await promptAppRootChoice(current);if(!target){log.info("No other application found in this repo \u2014 `velloo folder set-app-root --to <path>`.");return}let change=await planAppRootChange(folder,target);if(resolve9(change.to)===resolve9(change.from))return;await stopDaemon(daemonRoot(folder)),await applyAppRootChange(folder,change),log.success(`Application root is now ${displayPath2(change.to)}.`)}async function runOpenCanvas(folder){let rec=await ensureDaemon(folder);console.log(`velloo: canvas at ${rec.canvasUrl}`)}async function writeJson(path,value){await writeFile2(path,`${JSON.stringify(value,null,2)}
70
- `,"utf8")}import{homedir}from"os";import{isAbsolute,join as join11,relative as relative9,sep as sep3}from"path";var import_picocolors10=__toESM(require_picocolors(),1);function displayPath(path){let home=homedir(),rel=relative9(home,path);if(rel==="")return"~";return rel.startsWith("..")||isAbsolute(rel)?path:`~${sep3}${rel}`}function printSummary(folder,scaffold,plan,answers,importedFrom){let boardLabels=scaffold.boards.map((b)=>b.name).join(" + "),themeLabel=importedFrom?`imported from ${relative9(answers.appRoot,importedFrom)||importedFrom}`:presetById(answers.themePreset??DEFAULT_THEME_PRESET)?.label??"Indigo";if(console.log(""),console.log(import_picocolors10.default.green("\u2713 Velloo is installed and ready to use.")),console.log(import_picocolors10.default.dim(` Scaffolded ${displayPath(folder)}`)),console.log(""),scaffold.screens.length>0){console.log(` ${import_picocolors10.default.bold(boardLabels)} \u2014 ${scaffold.screens.length} screens across ${scaffold.boards.length} board${scaffold.boards.length===1?"":"s"}.`);let names=scaffold.screens.map((s)=>s.name||s.id),shown=names.slice(0,8),more=names.length-shown.length;if(console.log(import_picocolors10.default.dim(` ${shown.join(", ")}${more>0?`, +${more} more`:""}`)),answers.initialContent==="sample")console.log(import_picocolors10.default.dim(" Welcome sample \u2014 ready to remix."))}else console.log(import_picocolors10.default.dim(" Blank \u2014 no boards or screens yet."));console.log(""),console.log(import_picocolors10.default.bold(" Your setup")),console.log(` App root ${answers.appRoot}`),console.log(` Design ${folder}`),console.log(` Library ${plan.summary.name}`),console.log(` Theme ${themeLabel}`);let stack=stackById(answers.stack);if(stack)console.log(` Stack ${stack.label} (imports via ${stack.alias})`);if(plan.pendingUpstream)console.log(import_picocolors10.default.dim(` (real shadcn lands in ${plan.pendingUpstream.relative} when your agent finishes setup \u2014 nothing was written to your app)`))}function printExitInstructions(folder,outcome){console.log(""),console.log(import_picocolors10.default.bold(" How to use velloo"));let n=1;if(folder){if(outcome.wiredIds.length===0)console.log(` ${n++}. ${import_picocolors10.default.cyan(`velloo connect ${folder}`)} ${import_picocolors10.default.dim("(wire your AI agent's MCP config + guidance)")}`);console.log(` ${n++}. Reload MCP in your AI agent (or restart it) so it loads the new config ${import_picocolors10.default.dim("\u2014 it starts velloo itself")}.`),console.log(` ${n++}. ${import_picocolors10.default.cyan("velloo run")} ${import_picocolors10.default.dim("(opens the canvas; o open, b background, q stop)")}`),console.log("");let rel=relative9(process.cwd(),folder),readme=join11(rel.startsWith("..")?displayPath(folder):rel||".","README.md");console.log(` ${import_picocolors10.default.dim("Open")} ${import_picocolors10.default.cyan(readme)} ${import_picocolors10.default.dim("for the full guide.")}`)}else console.log(` ${n++}. ${import_picocolors10.default.cyan("velloo init")} ${import_picocolors10.default.dim("again when you're ready to scaffold a design folder")}`),console.log(` ${n++}. ${import_picocolors10.default.cyan("velloo run <folder>")} ${import_picocolors10.default.dim("opens the canvas for an existing design")}`),console.log(` ${n++}. ${import_picocolors10.default.cyan("velloo connect <folder>")} ${import_picocolors10.default.dim("wires your AI agent's MCP config")}`);console.log("")}async function printScreenshotReadiness(interactive){let installed=await chromiumExecutable()!==null;if(console.log(import_picocolors10.default.bold(" Screenshots")),console.log(import_picocolors10.default.dim(" Your agent's `screenshot` tool and `velloo render --to=png` use a headless")),console.log(import_picocolors10.default.dim(" browser. The canvas, editing, and `velloo publish` don't need it.")),installed){console.log(` ${import_picocolors10.default.green("\u2713")} ${import_picocolors10.default.dim("Browser installed \u2014 screenshots are ready.")}`),console.log("");return}if(interactive){let proceed=await confirm({message:`Install the screenshot browser now? ${BROWSER_PROMPT_SIZE}
71
- ${BROWSER_PROMPT_DETAIL}`,initialValue:!1});if(!isCancel(proceed)&&proceed){let ok=await installChromiumInteractive();console.log(ok?` ${import_picocolors10.default.green("\u2713")} ${import_picocolors10.default.dim("Browser installed \u2014 screenshots are ready.")}`:import_picocolors10.default.dim(` Screenshots aren't ready yet \u2014 fix per the messages above, or retry later: ${import_picocolors10.default.cyan(CHROMIUM_INSTALL_CMD)}`)),console.log("");return}}console.log(import_picocolors10.default.dim(` Add it anytime with: ${import_picocolors10.default.cyan(CHROMIUM_INSTALL_CMD)}`)),console.log("")}async function promptShellCompletions(interactive){if(!interactive)return;let shell=detectShell();if(!shell||completionsInstalled(void 0,shell))return;let proceed=await confirm({message:`Install shell completions now? (TAB completion for velloo commands in ${shell})`,initialValue:!0});if(isCancel(proceed)||!proceed){console.log(import_picocolors10.default.dim(` Anytime later: ${import_picocolors10.default.cyan("velloo completions --install")}`));return}try{let r=await installCompletions(shell);console.log(` ${import_picocolors10.default.green("\u2713")} ${shell} completions installed ${import_picocolors10.default.dim(shell==="fish"?"\u2014 new fish sessions pick them up.":`\u2014 restart your shell (or \`source ${r.rcPath}\`).`)}`)}catch(err){console.log(import_picocolors10.default.dim(` Couldn't install completions (${err.message}) \u2014 try \`velloo completions --install\` later.`))}}async function offerExistingFolderActions(appRoot,cliArgs){let projects=await findProjects(appRoot),project=projects?pickProject(projects,appRoot):null,existing=(project&&!cliArgs.designFolder?await resolveDesignFolder(project,"init",{cwd:appRoot,interactive:!0}):null)??(cliArgs.addFolder?await existingDesignFolder(appRoot)??resolve10(appRoot,"velloo"):resolve10(appRoot,cliArgs.designFolder??"velloo"));if(!await hasDesignConfig(existing))return{kind:"none"};let contextRoot=localDesignOf(existing)?.appRoot??appRoot,facts=await readFolderFacts(existing,contextRoot),action=cliArgs.addFolder?"another":await promptExistingFolderAction(facts,existing);if(action===null||action==="cancel")return console.log(import_picocolors11.default.dim(" Nothing changed.")),{kind:"handled"};if(action==="connect"){let wiring=await askAgentWiring({skipWhenCovered:!0,projectRoot:await resolveProjectRoot(existing),globalOnly:localDesignOf(existing)!==null}),wireOutcome=wiring?await applyAgentWiring(existing,wiring):NOT_WIRED;return printWired(wireOutcome),printExitInstructions(existing,wireOutcome),{kind:"handled"}}if(action!=="another"){if(action==="upgrade")await runUpgrade(existing);if(action==="scan")await runScan(existing,contextRoot,cliArgs.scanDir);if(action==="theme")await runThemeReimport(existing,contextRoot);if(action==="check")await runCheckSetup(existing,contextRoot);if(action==="open")await runOpenCanvas(existing);return{kind:"handled"}}return{kind:"another",inherited:await inheritedFromFolder(existing)}}import{copyFile,mkdir as mkdir3,readdir as readdir6}from"fs/promises";import{join as join12,relative as relative10,resolve as resolve11}from"path";function buildDefaultConfig(opts={}){return{schemaVersion:CURRENT_SCHEMA_VERSION,toolVersion:TOOL_VERSION,folderId:crypto.randomUUID(),libraries:{default:opts.library??{id:"shadcn-upstream",version:snapshotVersion2,source:"binary",componentsPath:"binary"}},defaultLibrary:"default",viewportPresets:[{name:"Mobile",w:390,h:844},{name:"Tablet",w:768,h:1024},{name:"Desktop",w:1440,h:900}],...opts.defaultScreen?{defaultScreen:opts.defaultScreen}:{},...opts.defaultBoard?{defaultBoard:opts.defaultBoard}:{},...opts.hostApp?{hostApp:opts.hostApp}:{},...opts.hostApps?{hostApps:opts.hostApps}:{},...opts.feedback?{feedback:opts.feedback}:{},...opts.styling?{styling:opts.styling}:{},...opts.codegen?{codegen:opts.codegen}:{}}}var DESKTOP={w:1280,h:800},MOBILE2={w:390,h:844,gap:40};function slugifyName(name,fallback="screen"){return name.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||fallback}function placeholderTree(label){return{$ref:"Box",props:{className:"flex min-h-screen flex-col items-center justify-center gap-3 p-8"},children:[{$ref:"Heading",props:{children:label,className:"text-2xl font-semibold"}},{$ref:"Text",props:{children:"Placeholder \u2014 ask your agent to recreate this, then explore alternatives.",className:"text-muted-foreground text-sm"}}]}}function desktopMobileFrames(screenId,label){return[{id:`f-${screenId}`,screen:screenId,x:80,y:80,w:DESKTOP.w,h:DESKTOP.h,label},{id:`f-${screenId}-m`,screen:screenId,x:80+DESKTOP.w+MOBILE2.gap,y:80,w:MOBILE2.w,h:MOBILE2.h,label:`${label} \xB7 Mobile`}]}function redesignScreenScaffold(theme,screenName){let id=slugifyName(screenName),screen={id,name:screenName.trim()||id,tree:placeholderTree(screenName.trim()||id)},board={id:"main",name:"Main",frames:desktopMobileFrames(id,screen.name),groups:[]};return{theme,screens:[screen],boards:[board],snippets:[],annotations:[],notes:[]}}function componentScaffold(theme,componentDescription){let label=componentDescription.trim()||"Component",id=slugifyName(label,"component"),screen={id,name:label,tree:placeholderTree(label)},board={id:"component",name:"Component",frames:desktopMobileFrames(id,label).map((f)=>({...f,group:"explorations"})),groups:[{id:"explorations",name:"Explorations"}]};return{theme,screens:[screen],boards:[board],snippets:[],annotations:[],notes:[]}}function customRequestScaffold(theme){return{theme,screens:[],boards:[{id:"main",name:"Main",frames:[],groups:[]}],snippets:[],annotations:[],notes:[]}}function renderDesignReadme(answers,plan,external=!1){let lines=[];lines.push("# Velloo design folder"),lines.push(""),lines.push("This folder is a Velloo design \u2014 pure JSON describing screens,"),lines.push("boards, snippets, and a theme. Velloo renders these with real"),lines.push(`React components from a pinned **${plan.summary.name}** snapshot.`),lines.push(""),lines.push("## Quick start"),lines.push(""),lines.push("```bash"),lines.push("velloo run ."),lines.push("```"),lines.push(""),lines.push("`velloo run .` starts the canvas and stays in the foreground \u2014 `b` keeps it"),lines.push("running in the background, `s` stops it, `o` opens the browser. It defaults"),lines.push("to http://localhost:7300, but uses a free port if that's taken. Your AI"),lines.push("agent drives the design over MCP \u2014 wire it once with `velloo connect`,"),lines.push("and it starts the velloo MCP server itself (no separate server to run)."),lines.push(""),lines.push("## Your setup"),lines.push(""),lines.push("| | |"),lines.push("|---|---|"),lines.push(`| Library | ${plan.summary.name} |`),lines.push(`| Components | ${external&&plan.pendingUpstream?`project:${plan.pendingUpstream.relative}`:plan.summary.location} |`),lines.push(`| App root | ${external?"project:. (local application binding)":answers.appRoot} |`);let contentLabel=answers.initialContent==="sample"?"Welcome sample":answers.initialContent==="scan"?"scanned from your app":answers.initialContent==="redesign-screen"?`redesign screen${answers.screenName?` (${answers.screenName})`:""}`:answers.initialContent==="component"?`component redesign${answers.componentDescription?` (${answers.componentDescription})`:""}`:answers.initialContent==="custom"?"custom request":"blank";return lines.push(`| Initial content | ${contentLabel} |`),lines.push(""),lines.push("## Layout"),lines.push(""),lines.push("```"),lines.push(".design/config.json tool + library declaration"),lines.push("theme/default.json color tokens (OKLCH)"),lines.push("screens/<id>.json one composition each (light + dark)"),lines.push("boards/<id>.json frame layouts on the canvas"),lines.push("snippets/<id>.json reusable subtrees with typed params"),lines.push("assets/ generated SVGs / images"),lines.push("```"),lines.push(""),lines.push(...WIZARD_PROVIDERS[answers.library].readmeComponentsSection(plan)),lines.push("## Composition helpers"),lines.push(""),lines.push("Alongside the component library, every design folder has a small set of"),lines.push("framework-neutral helpers:"),lines.push(""),lines.push("```"),lines.push("Box layout div \u2014 use it for every flex/grid wrapper"),lines.push("Heading/Text the type ladder"),lines.push("Icon a lucide glyph by name"),lines.push("SVG inline SVG markup"),lines.push("Image a file from assets/"),lines.push("Gradient a gradient fill surface"),lines.push("Layer absolute-positioned overlay"),lines.push("Divider a rule"),lines.push("Placeholder sized stand-in for art you haven't made yet"),lines.push("```"),lines.push(""),lines.push("`SVG` is the one worth knowing about: it inlines the markup, so the art"),lines.push("inherits `currentColor` and flips with your theme the way an `Image`"),lines.push("never will. It's the right answer for a logo or a brand mark \u2014 including"),lines.push("the ones lucide deliberately doesn't ship (GitHub, Google, Apple, X), so"),lines.push("reach for `SVG` there rather than an `Icon` name that won't resolve."),lines.push(""),lines.push("## What the AI agent sees"),lines.push(""),lines.push("Velloo's default MCP surface is three compact tools: `call_velloo`,"),lines.push("`run_velloo_plan`, and `operation_schema`. Their operation catalogue"),lines.push("covers discovery (`list_screens`, `list_components`, `get_theme`),"),lines.push("restricted-JSX composition (`compose`), focused edits (`update_props`,"),lines.push("`move_node`, \u2026), themes, inspection, screenshots, and code emission."),lines.push("A failed call returns the exact native schema needed to correct it."),lines.push(""),lines.push("Clients that prefer conventional function schemas can advertise every"),lines.push("native tool directly with `velloo mcp --surface full`."),lines.push(""),lines.push("Designs are static by construction \u2014 click handlers, routing, and forms"),lines.push("are no-ops in the canvas. The agent reads the design and writes real"),lines.push("code into your app via `emit_code`."),lines.push(""),lines.join(`
72
- `)}async function isEmptyOrMissing(path){try{return(await readdir6(path)).length===0}catch(err){if(err.code==="ENOENT")return!0;throw err}}function blankScaffold(theme){return{theme,screens:[],boards:[],snippets:[],annotations:[],notes:[]}}function resolveTheme(answers){if(answers.detected){if(answers.detected.uiLibrary==="mui"){let themeFile=findMuiTheme(answers.scanRoot);if(themeFile){let imported=importThemeFromMui(themeFile,answers.themePreset);if(imported)return{theme:imported.theme,importedFrom:imported.importedFrom}}}if(answers.detected.globalsCssPath){let imported=importThemeFromGlobals(answers.detected.globalsCssPath,answers.themePreset);if(imported)return{theme:imported.theme,importedFrom:imported.importedFrom}}}if(answers.initialContent==="blank")return{theme:buildPresetTheme(answers.themePreset??"zinc")};return{theme:buildPresetTheme(answers.themePreset??DEFAULT_THEME_PRESET)}}async function buildScaffold(answers,theme){if(answers.initialContent==="blank")return blankScaffold(theme);if(answers.initialContent==="component")return componentScaffold(theme,answers.componentDescription??"Component");if(answers.initialContent==="custom")return customRequestScaffold(theme);if(answers.initialContent==="redesign-screen"){if(answers.selectedRoutes&&answers.selectedRoutes.length>0){let routes=answers.selectedRoutes,screens=buildScreensFromScan({routes,...WIZARD_PROVIDERS[answers.library].scanScreenOpts}),boards=buildBoardsFromScan({routes});return{theme,screens,boards,snippets:[],annotations:[],notes:[]}}return redesignScreenScaffold(theme,answers.screenName??"Screen")}if(answers.initialContent==="scan"){let routes=answers.selectedRoutes??(await scanAppRoutes(answers.scanRoot)).routes;if(routes.length===0)return blankScaffold(theme);let screens=buildScreensFromScan({routes,...WIZARD_PROVIDERS[answers.library].scanScreenOpts}),boards=buildBoardsFromScan({routes});return{theme,screens,boards,snippets:[],annotations:[],notes:[]}}return sampleScaffold(answers,theme)}function defaultScreenForScaffold(scaffold){if(scaffold.screens.find((s)=>s.id==="landing"))return"landing";return scaffold.screens[0]?.id}async function writeScaffold(folder,scaffold,plan,answers,local=!1){let hostAppRoot=relative10(folder,answers.scanRoot),appRels=[...new Set((answers.selectedRoutes??[]).map((r)=>r.appRel).filter(Boolean))],hostApps;if(appRels.length>1){let prefixes=appPrefixes(appRels);hostApps={};for(let rel of appRels){let key=prefixes.get(rel);if(key)hostApps[key]={root:relative10(folder,resolve11(answers.appRoot,rel))}}}let styling=WIZARD_PROVIDERS[answers.library].stylingFor(answers),stack=stackById(answers.stack),hostAliases=componentAliases(stack?.alias,answers.componentsRelative),config=buildDefaultConfig({library:plan.library,defaultScreen:defaultScreenForScaffold(scaffold),defaultBoard:scaffold.boards[0]?.id,...hostAppRoot?{hostApp:{root:hostAppRoot,...hostAliases?{aliases:hostAliases}:{}}}:{},...hostApps?{hostApps}:{},...styling?{styling}:{},codegen:{...stack?{componentsAlias:stack.alias}:{},componentsDir:answers.componentsRelative}});config.boardOrder=scaffold.boards.map((b)=>b.id),ConfigSchema.parse(config),ThemeSchema.parse(scaffold.theme);for(let screen of scaffold.screens)ScreenSchema.parse(screen);for(let board of scaffold.boards)BoardSchema.parse(board);for(let snippet of scaffold.snippets)SnippetSchema.parse(snippet);await Promise.all([mkdir3(`${folder}/screens`,{recursive:!0}),mkdir3(`${folder}/boards`,{recursive:!0}),mkdir3(`${folder}/snippets`,{recursive:!0})]);let gitignore=["# Velloo runtime + debug artifacts \u2014 regenerated on demand, never commit.",".design/cache/",".velloo/",""].join(`
73
- `),writes=[writeJsonAtomic(`${folder}/.design/config.json`,config),writeJsonAtomic(`${folder}/theme/default.json`,scaffold.theme),writeText(`${folder}/.gitignore`,gitignore),writeText(`${folder}/assets/.gitkeep`,""),writeText(`${folder}/README.md`,renderDesignReadme(answers,plan,local))];for(let s of scaffold.screens)writes.push(writeJsonAtomic(`${folder}/screens/${s.id}.json`,s));for(let b of scaffold.boards)writes.push(writeJsonAtomic(`${folder}/boards/${b.id}.json`,b));for(let s of scaffold.snippets)writes.push(writeJsonAtomic(`${folder}/snippets/${s.id}.json`,s));for(let notes of scaffold.notes)writes.push(writeJsonAtomic(`${folder}/boards/${notes.boardId}.notes.json`,notes.entries));for(let annotations of scaffold.annotations)writes.push(writeJsonAtomic(`${folder}/screens/${annotations.screenId}.annotations.json`,annotations.entries));if(scaffold.customCss)writes.push(writeText(`${folder}/theme/custom.css`,scaffold.customCss));if(scaffold.assetMetadata)writes.push(writeJsonAtomic(`${folder}/assets.json`,scaffold.assetMetadata));for(let[path,text]of Object.entries(scaffold.documents??{}))writes.push(writeText(join12(folder,path),text));await mkdir3(join12(folder,"assets"),{recursive:!0});for(let[path,source]of Object.entries(scaffold.assetFiles??{}))writes.push(copyFile(source,join12(folder,path)));await Promise.all(writes)}function componentAliases(componentsAlias,componentsRelative){let alias=componentsAlias??"@/components/ui",marker="/components/ui",aliasAt=alias.lastIndexOf("/components/ui"),pathAt=componentsRelative.replaceAll("\\","/").lastIndexOf("/components/ui".slice(1));if(aliasAt<0||pathAt<0)return;let from=`${alias.slice(0,aliasAt).replace(/\/$/,"")}/*`,base=componentsRelative.replaceAll("\\","/").slice(0,pathAt).replace(/\/$/,"");return{[from]:base?`${base}/*`:"*"}}var init_default=defineCommand({meta:{name:"init",description:"Scaffold a new Velloo design folder"},args:{folder:{type:"positional",required:!1,description:"Your app root \u2014 where Velloo installs (default: current directory)"},designFolder:{type:"string",description:"Design folder, relative to the app root (default: velloo)"},external:{type:"boolean",description:"Keep the design in Velloo-managed storage outside the application repository"},force:{type:"boolean",default:!1,description:"Allow scaffolding into a non-empty design folder"},nonInteractive:{type:"boolean",default:!1,description:"Skip the wizard and use defaults / flags"},connect:{type:"boolean",default:!0,description:"Wire your AI agents' MCP config + guidance \u2014 Claude Code / Cursor / Codex / Continue; non-interactive default wires Claude Code + Cursor (use --no-connect to skip)"},start:{type:"string",description:"Goal: redesign-screen | redesign-component | custom | sample | blank | scan (legacy multi-route)"},scanDir:{type:"string",description:"Subfolder to scan when your UI isn't at the root (e.g. web/frontend). Auto-detected if omitted."},library:{type:"string",description:`Component library: ${LIBRARY_IDS.join(" | ")} (default ${DEFAULT_LIBRARY_ID})`},componentsDir:{type:"string",description:"Upstream components subfolder inside your app (default src/components/ui)"},initialContent:{type:"string",description:"Initial content: sample | blank | redesign-screen | component | custom | scan"},screenName:{type:"string",description:"Screen name for --start=redesign-screen (optional if routes are scanned)"},component:{type:"string",description:"Component name or description for --start=redesign-component"},request:{type:"string",description:"Free-text design request for --start=custom"},themePreset:{type:"string",description:"Theme preset: elsewhere | indigo | violet | blue | emerald | rose | orange | amber | zinc"},stack:{type:"string",description:"Your app's stack \u2014 sets the emitted import alias: nextjs | vite | astro (@/components/ui) | remix (~/components/ui)"},project:{type:"string",description:"Project name to register in the repo's velloo.json (default: derived from the folder path)"}},run:({args})=>runInit2(args)});async function runInit2(cliArgs){let appRoot=resolve12(cliArgs.folder??"."),launchRoot=appRoot,interactive=shouldRunWizard(cliArgs,Boolean(process.stdin.isTTY)),allowNonEmpty=cliArgs.force,secondFolder=!1,inherited={library:void 0,componentsDir:void 0};if(cliArgs.scanDir&&!await dirExists(resolve12(appRoot,cliArgs.scanDir)))fail("init",`--scan-dir "${cliArgs.scanDir}" doesn't exist under ${appRoot}.`);if(interactive&&await offerUpgradeBeforeInit(process.argv.slice(2)))return;if(interactive)printLogo();if(interactive&&!cliArgs.force&&!cliArgs.external){let existing=await offerExistingFolderActions(appRoot,cliArgs);if(existing.kind==="handled")return;if(existing.kind==="another")secondFolder=!0,inherited=existing.inherited}if(interactive&&!cliArgs.folder){let candidates=await appRootIsNotAnApp(appRoot).catch(()=>null);if(candidates){console.log(import_picocolors12.default.dim(` ${appRoot} holds ${candidates.length} app${candidates.length===1?"":"s"} but isn't one itself.`));let chosen=await promptAppRootChoice(appRoot,{currentHint:"this directory"});if(chosen)appRoot=chosen}}let external=cliArgs.external===!0,presetFolder=cliArgs.designFolder;if(external&&cliArgs.designFolder)fail("init","Choose --external or --design-folder, not both.");let candidateId=randomUUID2(),candidateFolder=managedDesignPath(candidateId);if(interactive&&cliArgs.external===void 0&&!cliArgs.designFolder){let storage=await select({message:"Where should the design live?",options:[{value:"repository",label:"Default in repo",hint:secondFolder?"./velloo-brand/":"./velloo/"},{value:"external",label:"Default out of repo",hint:`${displayPath(dirname6(candidateFolder))}/ \u2014 not version-controlled`},{value:"custom",label:"Custom name",hint:"Choose a design folder name or path"}]});if(isCancel(storage))return;if(external=storage==="external",storage==="repository")presetFolder=secondFolder?"velloo-brand":"velloo"}let managedId=external?candidateId:void 0,managedFolder=managedId?candidateFolder:void 0,answers;if(interactive){if(console.log(import_picocolors12.default.dim(` App root: ${appRoot} (the app this design targets)`)),managedFolder)console.log(import_picocolors12.default.dim(` Design: ${displayPath(managedFolder)} (outside the repo, not version-controlled)`));else if(presetFolder)console.log(import_picocolors12.default.dim(` Design: ${displayPath(resolve12(launchRoot,presetFolder))}`));if(launchRoot!==appRoot)console.log(import_picocolors12.default.dim(` Design folder and agent config go under ${launchRoot}.`));console.log("");let inheritedLibrary=inherited.library&&isValidLibraryId(inherited.library)?inherited.library:void 0,result=await runInteractive({appRoot,folderBase:launchRoot,secondFolder,...managedFolder||presetFolder?{presetFolder:managedFolder??presetFolder}:{},scanDir:cliArgs.scanDir,connectEnabled:cliArgs.connect!==!1,pinnedLibrary:cliArgs.library&&isValidLibraryId(cliArgs.library)?cliArgs.library:inheritedLibrary,...inheritedLibrary&&!cliArgs.library?{pinnedLibraryReason:"same as the design folder already in this repo"}:{},...inherited.componentsDir?{inheritComponentsDir:inherited.componentsDir}:{}});if(result.status==="abort")printExitInstructions(void 0,NOT_WIRED),process.exit(1);answers=result.answers}else{try{answers=answersFromArgs(cliArgs)}catch(err){fail("init",err.message)}console.log(`velloo: app root ${answers.appRoot}`)}if((answers.initialContent==="scan"||answers.initialContent==="redesign-screen")&&!answers.detected){let scanned=await scanApps(answers.appRoot,cliArgs.scanDir),primary=scanned.apps[0];if(primary)answers.scanRoot=primary.dir;if(scanned.apps.length>1)console.log(import_picocolors12.default.dim(` Found ${scanned.apps.length} apps (${scanned.apps.map((a)=>a.rel||".").join(", ")}) \u2014 one board per app.`));else if(primary?.rel&&primary.rel!==".")console.log(import_picocolors12.default.dim(` Scanning UI in ${primary.rel} (app root has no package.json).`));if(answers.selectedRoutes=answers.initialContent==="redesign-screen"?scanned.routes.slice(0,1):scanned.routes,answers.agentPicksFirst=answers.initialContent==="scan",answers.initialContent==="redesign-screen"&&scanned.routes[0])answers.screenName=answers.screenName??scanned.routes[0].name;answers.detected=detectHost(answers.scanRoot);let adopted=cliArgs.library?void 0:scanAdoption(answers.detected);if(adopted)answers.library=adopted.library,answers.source="binary",console.log(import_picocolors12.default.dim(` ${adopted.note}`))}if(managedFolder)answers.folder=managedFolder;let folder=answers.folder;if(!allowNonEmpty&&!await isEmptyOrMissing(folder))fail("init",`design folder is not empty: ${folder}
74
- Pick an empty path, or pass --force to scaffold over it.`);let plan;try{plan=planInstall(answers)}catch(err){fail("init",err.message)}if(interactive)console.log(import_picocolors12.default.dim(" Scaffolding your design folder\u2026"));let{theme,importedFrom}=resolveTheme(answers),scaffold;try{scaffold=await buildScaffold(answers,theme)}catch(err){fail("init",err.message)}let root=await checkoutRoot(answers.appRoot,launchRoot),localId=managedId??(isWithin(root,folder)?void 0:randomUUID2());try{if(await writeScaffold(folder,scaffold,plan,answers,localId!==void 0),localId)await rebaseDesignConfig(folder,folder,answers.appRoot,!0)}catch(error){if(localId)throw Error(`Could not finish the design at ${folder}. Existing content was retained. Check write permissions and free disk space before retrying. ${error instanceof Error?error.message:error}`);throw error}console.log(`velloo: scaffolded ${folder} (${snapshotVersion2})`);try{if(localId){let name=await registerLocalDesign({id:localId,root,appRoot:answers.appRoot,...managedId?{}:{designPath:folder},requestedName:cliArgs.project});console.log(import_picocolors12.default.dim(` Recorded as local design "${name}" for ${displayPath(root)} \u2014 on this machine only; nothing was added to the repository.`))}else{let reg=await registerProject(folder,answers.appRoot,cliArgs.project);if(reg.created)console.log(import_picocolors12.default.dim(` Registered as project "${reg.name}" in ${relative11(process.cwd(),reg.path)||reg.path}.`))}if(answers.feedback)await writeRepoFeedback(folder,answers.feedback),await writeFeedbackContactOk(answers.feedback.contactOk===!0)}catch(err){if(localId)fail("init",`Design retained at ${folder}, but registration failed: ${err.message}`);console.log(import_picocolors12.default.yellow(` Couldn't update the repo manifest: ${err.message}`))}if(importedFrom)console.log(import_picocolors12.default.dim(` Imported your theme from ${relative11(answers.appRoot,importedFrom)}.`));if(answers.initialContent==="scan"&&scaffold.screens.length===0)console.log(import_picocolors12.default.dim(" No routes detected \u2014 started you with a blank folder instead of a scan."));printSummary(folder,scaffold,plan,answers,importedFrom);let wireOutcome=NOT_WIRED;if(cliArgs.connect!==!1){let wiring=interactive?answers.agentWiring:localId?void 0:{agents:PROJECT_AGENT_IDS,manual:!1,preWired:[]};if(wiring)wireOutcome=await applyAgentWiring(folder,wiring);else if(localId&&!interactive)console.log(import_picocolors12.default.dim(" Agents not wired: a local design uses global configs \u2014 run `velloo connect`."))}printWired(wireOutcome),await printScreenshotReadiness(interactive),await promptShellCompletions(interactive),await printAgentHandoff(answers,scaffold,interactive,wireOutcome.wiredIds),printExitInstructions(folder,wireOutcome)}
75
- export{recordedAppRoot,planAppRootChange,applyAppRootChange,promptAppRootChoice,planRelocation,relocateDesign,displayPath,init_default,runInit2};
48
+ `)return;out+=ch,j++}return}function parseNumber(code,i){let m=/^(?:\d[\d_]*(?:\.[\d_]*)?|\.\d[\d_]*)(?:[eE][+-]?\d+)?/.exec(code.slice(i));if(!m)return;let value=Number(m[0].replace(/_/g,""));if(Number.isNaN(value))return;return{value,end:i+m[0].length}}function parseValue(code,i){let ch=code.charAt(i);if(ch==='"'||ch==="'"||ch==="`")return parseStringLiteral(code,i);if(ch==="{")return parseObjectLiteral(code,i);if(/[\d.]/.test(ch))return parseNumber(code,i);return}function skipEntry(code,i){while(i<code.length){let ch=code.charAt(i);if(ch===","||ch==="}")return i;if(ch==='"'||ch==="'"||ch==="`"){i=scanString(code,i);continue}if(ch==="{"||ch==="("||ch==="["){i=scanBalanced(code,i);continue}i++}return i}function parseObjectLiteral(code,i){let obj=new Map;i++;for(;;){if(i=skipWs(code,i),i>=code.length)return;let ch=code.charAt(i);if(ch==="}")return{value:obj,end:i+1};if(ch===","){i++;continue}let key;if(ch==='"'||ch==="'"){let parsed=parseStringLiteral(code,i);if(parsed)key=parsed.value,i=parsed.end}else{let m=/^[A-Za-z_$][A-Za-z0-9_$]*/.exec(code.slice(i));if(m)key=m[0],i+=m[0].length}if(i=skipWs(code,i),key===void 0||code.charAt(i)!==":"){i=skipEntry(code,i);continue}let parsed=parseValue(code,skipWs(code,i+1));if(parsed){let after=skipWs(code,parsed.end),term=code.charAt(after);if(term===","||term==="}"){obj.set(key,parsed.value),i=after;continue}}i=skipEntry(code,i)}}function findCreateThemeCall(code){let i=0;while(i<code.length){let ch=code.charAt(i);if(ch==='"'||ch==="'"||ch==="`"){i=scanString(code,i);continue}if(ch==="c"&&code.startsWith("createTheme",i)){let before=code.charAt(i-1),after=code.charAt(i+11);if((i===0||!IDENT_CHAR.test(before))&&!IDENT_CHAR.test(after)){let paren=skipWs(code,i+11);if(code.charAt(paren)==="(")return paren}}i++}return}function createThemeArg(src){let code=stripComments(src),paren=findCreateThemeCall(code);if(paren===void 0)return;let arg=skipWs(code,paren+1);if(code.charAt(arg)!=="{")return;return parseObjectLiteral(code,arg)?.value}function prop(obj,name){return obj.get(name)}function asObject(value){return value instanceof Map?value:void 0}function asString(value){return typeof value==="string"?value:void 0}function asNumber(value){return typeof value==="number"?value:void 0}function importThemeFromMui(filePath,presetId){let src;try{src=readFileSync(filePath,"utf8")}catch{return null}let root=createThemeArg(src);if(!root)return null;let palette=asObject(prop(root,"palette")),colors={},warnings=[],tokenCount=0;if(palette){let pairOf=(key)=>{let o=asObject(prop(palette,key));return{main:o&&asString(prop(o,"main")),contrastText:o&&asString(prop(o,"contrastText"))}},text=asObject(prop(palette,"text")),textPrimary=text&&asString(prop(text,"primary")),primary=pairOf("primary");if(primary.main)colors.primary={DEFAULT:primary.main,foreground:primary.contrastText??"#ffffff"},tokenCount++;let secondary=pairOf("secondary");if(secondary.main)colors.secondary={DEFAULT:secondary.main,foreground:secondary.contrastText??"#ffffff"},tokenCount++;let error=pairOf("error");if(error.main)colors.destructive={DEFAULT:error.main,foreground:error.contrastText??"#ffffff"},tokenCount++;let background=asObject(prop(palette,"background")),bgDefault=background&&asString(prop(background,"default")),bgPaper=background&&asString(prop(background,"paper"));if(bgDefault)colors.background=bgDefault,tokenCount++;if(bgPaper)colors.card={DEFAULT:bgPaper,foreground:textPrimary??"#111827"},tokenCount++;if(textPrimary)colors.foreground=textPrimary,tokenCount++;let divider=asString(prop(palette,"divider"));if(divider)colors.border=divider,tokenCount++}let shape=asObject(prop(root,"shape")),borderRadius=shape&&asNumber(prop(shape,"borderRadius")),typography=asObject(prop(root,"typography")),fontFamily=typography&&asString(prop(typography,"fontFamily"));if(tokenCount===0&&borderRadius===void 0&&fontFamily===void 0)return null;let base=buildPresetTheme(presetId,"default");return{theme:{...base,colors:{...base.colors,...colors},radius:borderRadius!==void 0?{...base.radius,md:borderRadius}:base.radius,typography:fontFamily?{...base.typography,fontFamily:{...base.typography.fontFamily,sans:fontFamily}}:base.typography},importedFrom:filePath,tokenCount,warnings}}function findMuiTheme(appRoot){let candidates=["src/theme.ts","src/theme.tsx","src/theme/index.ts","src/theme/index.tsx","theme.ts","src/styles/theme.ts","src/lib/theme.ts","app/theme.ts","src/app/theme.ts"];for(let rel of candidates){let abs=join6(appRoot,rel);if(!existsSync2(abs))continue;try{if(readFileSync(abs,"utf8").includes("createTheme("))return abs}catch{}}return}import{readFileSync as readFileSync2}from"fs";function importThemeFromGlobals(cssPath,presetId){let css;try{css=readFileSync2(cssPath,"utf8")}catch{return null}let parsed=parseThemeCss(css),tokenCount=Object.keys(parsed.colors).length+Object.keys(parsed.colorsDark).length;if(tokenCount===0&&parsed.radius===void 0&&parsed.fontFamily===void 0)return null;let base=buildPresetTheme(presetId,"default");return{theme:{...base,colors:{...base.colors,...parsed.colors},colorsDark:{...base.colorsDark??{},...parsed.colorsDark},radius:parsed.radius!==void 0?{...base.radius,md:parsed.radius}:base.radius,typography:parsed.fontFamily?{...base.typography,fontFamily:{...base.typography.fontFamily,...parsed.fontFamily}}:base.typography},importedFrom:cssPath,tokenCount,warnings:parsed.warnings}}function renderDesignReadme(answers,plan,external=!1){let lines=[];lines.push("# Velloo design folder"),lines.push(""),lines.push("This folder is a Velloo design \u2014 pure JSON describing screens,"),lines.push("boards, snippets, and a theme. Velloo renders these with real"),lines.push(`React components from a pinned **${plan.summary.name}** snapshot.`),lines.push(""),lines.push("## Quick start"),lines.push(""),lines.push("```bash"),lines.push("velloo run ."),lines.push("```"),lines.push(""),lines.push("`velloo run .` starts the canvas and stays in the foreground \u2014 `b` keeps it"),lines.push("running in the background, `s` stops it, `o` opens the browser. It defaults"),lines.push("to http://localhost:7300, but uses a free port if that's taken. Your AI"),lines.push("agent drives the design over MCP \u2014 wire it once with `velloo connect`,"),lines.push("and it starts the velloo MCP server itself (no separate server to run)."),lines.push(""),lines.push("## Your setup"),lines.push(""),lines.push("| | |"),lines.push("|---|---|"),lines.push(`| Library | ${plan.summary.name} |`),lines.push(`| Components | ${external&&plan.pendingUpstream?`app:${plan.pendingUpstream.relative}`:plan.summary.location} |`),lines.push(`| App root | ${external?"app:. (local application binding)":answers.appRoot} |`);let contentLabel=answers.initialContent==="sample"?"Welcome sample":answers.initialContent==="scan"?"scanned from your app":answers.initialContent==="redesign-screen"?`redesign screen${answers.screenName?` (${answers.screenName})`:""}`:answers.initialContent==="component"?`component redesign${answers.componentDescription?` (${answers.componentDescription})`:""}`:answers.initialContent==="custom"?"custom request":"blank";return lines.push(`| Initial content | ${contentLabel} |`),lines.push(""),lines.push("## Layout"),lines.push(""),lines.push("```"),lines.push(".design/config.json tool + library declaration"),lines.push("theme/default.json color tokens (OKLCH)"),lines.push("screens/<id>.json one composition each (light + dark)"),lines.push("boards/<id>.json frame layouts on the canvas"),lines.push("snippets/<id>.json reusable subtrees with typed params"),lines.push("assets/ generated SVGs / images"),lines.push("```"),lines.push(""),lines.push(...WIZARD_PROVIDERS[answers.library].readmeComponentsSection(plan)),lines.push("## Composition helpers"),lines.push(""),lines.push("Alongside the component library, every design folder has a small set of"),lines.push("framework-neutral helpers:"),lines.push(""),lines.push("```"),lines.push("Box layout div \u2014 use it for every flex/grid wrapper"),lines.push("Heading/Text the type ladder"),lines.push("Icon a lucide glyph by name"),lines.push("SVG inline SVG markup"),lines.push("Image a file from assets/"),lines.push("Gradient a gradient fill surface"),lines.push("Layer absolute-positioned overlay"),lines.push("Divider a rule"),lines.push("Placeholder sized stand-in for art you haven't made yet"),lines.push("```"),lines.push(""),lines.push("`SVG` is the one worth knowing about: it inlines the markup, so the art"),lines.push("inherits `currentColor` and flips with your theme the way an `Image`"),lines.push("never will. It's the right answer for a logo or a brand mark \u2014 including"),lines.push("the ones lucide deliberately doesn't ship (GitHub, Google, Apple, X), so"),lines.push("reach for `SVG` there rather than an `Icon` name that won't resolve."),lines.push(""),lines.push("## What the AI agent sees"),lines.push(""),lines.push("Velloo's default MCP surface is three compact tools: `call_velloo`,"),lines.push("`run_velloo_plan`, and `operation_schema`. Their operation catalogue"),lines.push("covers discovery (`list_screens`, `list_components`, `get_theme`),"),lines.push("restricted-JSX composition (`compose`), focused edits (`update_props`,"),lines.push("`move_node`, \u2026), themes, inspection, screenshots, and code emission."),lines.push("A failed call returns the exact native schema needed to correct it."),lines.push(""),lines.push("Clients that prefer conventional function schemas can advertise every"),lines.push("native tool directly with `velloo mcp --surface full`."),lines.push(""),lines.push("Designs are static by construction \u2014 click handlers, routing, and forms"),lines.push("are no-ops in the canvas. The agent reads the design and writes real"),lines.push("code into your app via `emit_code`."),lines.push(""),lines.join(`
49
+ `)}var STACKS=[{id:"nextjs",label:"Next.js",alias:"@/components/ui"},{id:"vite",label:"Vite (React)",alias:"@/components/ui"},{id:"astro",label:"Astro",alias:"@/components/ui"},{id:"remix",label:"Remix / React Router",alias:"~/components/ui"}],DEFAULT_STACK_ID="vite";function stackForFramework(framework){switch(framework){case"next-app":case"next-pages":return"nextjs";case"react-router":return"remix";case"astro":return"astro";default:return"vite"}}function stackById(id){return id?STACKS.find((s)=>s.id===id):void 0}function isValidStack(id){return STACKS.some((s)=>s.id===id)}async function isEmptyOrMissing(path){try{return(await readdir4(path)).length===0}catch(err){if(err.code==="ENOENT")return!0;throw err}}function blankScaffold(theme){return{theme,screens:[],boards:[],snippets:[],annotations:[],notes:[]}}function themePresetFor(answers){return answers.themePreset??(answers.initialContent==="blank"?"zinc":DEFAULT_THEME_PRESET)}function resolveTheme(answers){if(answers.detected){if(answers.detected.uiLibrary==="mui"){let themeFile=findMuiTheme(answers.scanRoot);if(themeFile){let imported=importThemeFromMui(themeFile,answers.themePreset);if(imported)return{theme:imported.theme,importedFrom:imported.importedFrom}}}if(answers.detected.globalsCssPath){let imported=importThemeFromGlobals(answers.detected.globalsCssPath,answers.themePreset);if(imported)return{theme:imported.theme,importedFrom:imported.importedFrom}}}return{theme:buildPresetTheme(themePresetFor(answers))}}async function buildScaffold(answers,theme){if(answers.initialContent==="blank")return blankScaffold(theme);if(answers.initialContent==="component")return componentScaffold(theme,answers.componentDescription??"Component");if(answers.initialContent==="custom")return customRequestScaffold(theme);if(answers.initialContent==="redesign-screen"){if(answers.selectedRoutes&&answers.selectedRoutes.length>0){let routes=answers.selectedRoutes,screens=buildScreensFromScan({routes,...WIZARD_PROVIDERS[answers.library].scanScreenOpts}),boards=buildBoardsFromScan({routes});return{theme,screens,boards,snippets:[],annotations:[],notes:[]}}return redesignScreenScaffold(theme,answers.screenName??"Screen")}if(answers.initialContent==="scan"){let routes=answers.selectedRoutes??(await scanAppRoutes(answers.scanRoot)).routes;if(routes.length===0)return blankScaffold(theme);let screens=buildScreensFromScan({routes,...WIZARD_PROVIDERS[answers.library].scanScreenOpts}),boards=buildBoardsFromScan({routes});return{theme,screens,boards,snippets:[],annotations:[],notes:[]}}return sampleScaffold(answers,theme)}function defaultScreenForScaffold(scaffold){if(scaffold.screens.find((s)=>s.id==="landing"))return"landing";return scaffold.screens[0]?.id}async function writeScaffold(folder,scaffold,plan,answers,name,local=!1){let hostAppRoot=relative5(folder,answers.scanRoot).split(sep5).join("/"),appRels=[...new Set((answers.selectedRoutes??[]).map((r)=>r.appRel).filter(Boolean))],hostApps;if(appRels.length>1){let prefixes=appPrefixes(appRels);hostApps={};for(let rel of appRels){let key=prefixes.get(rel);if(key)hostApps[key]={root:relative5(folder,resolve5(answers.appRoot,rel)).split(sep5).join("/")}}}let styling=WIZARD_PROVIDERS[answers.library].stylingFor(answers),stack=stackById(answers.stack),hostAliases=componentAliases(stack?.alias,answers.componentsRelative),config=buildDefaultConfig({name,library:plan.library,defaultScreen:defaultScreenForScaffold(scaffold),defaultBoard:scaffold.boards[0]?.id,...hostAppRoot?{hostApp:{root:hostAppRoot,...hostAliases?{aliases:hostAliases}:{}}}:{},...hostApps?{hostApps}:{},...styling?{styling}:{},codegen:{...stack?{componentsAlias:stack.alias}:{},componentsDir:answers.componentsRelative}});config.boardOrder=scaffold.boards.map((b)=>b.id),ConfigSchema.parse(config),ThemeSchema.parse(scaffold.theme);for(let screen of scaffold.screens)ScreenSchema.parse(screen);for(let board of scaffold.boards)BoardSchema.parse(board);for(let snippet of scaffold.snippets)SnippetSchema.parse(snippet);await Promise.all([mkdir(`${folder}/screens`,{recursive:!0}),mkdir(`${folder}/boards`,{recursive:!0}),mkdir(`${folder}/snippets`,{recursive:!0})]);let gitignore=["# Velloo runtime + debug artifacts \u2014 regenerated on demand, never commit.",".design/cache/",".velloo/",""].join(`
50
+ `),writes=[writeJsonAtomic(`${folder}/.design/config.json`,config),writeJsonAtomic(`${folder}/theme/default.json`,scaffold.theme),writeText(`${folder}/.gitignore`,gitignore),writeText(`${folder}/assets/.gitkeep`,""),writeText(`${folder}/README.md`,renderDesignReadme(answers,plan,local))];for(let s of scaffold.screens)writes.push(writeJsonAtomic(`${folder}/screens/${s.id}.json`,s));for(let b of scaffold.boards)writes.push(writeJsonAtomic(`${folder}/boards/${b.id}.json`,b));for(let s of scaffold.snippets)writes.push(writeJsonAtomic(`${folder}/snippets/${s.id}.json`,s));for(let notes of scaffold.notes)writes.push(writeJsonAtomic(`${folder}/boards/${notes.boardId}.notes.json`,notes.entries));for(let annotations of scaffold.annotations)writes.push(writeJsonAtomic(`${folder}/screens/${annotations.screenId}.annotations.json`,annotations.entries));if(scaffold.customCss)writes.push(writeText(`${folder}/theme/custom.css`,scaffold.customCss));if(scaffold.assetMetadata)writes.push(writeJsonAtomic(`${folder}/assets.json`,scaffold.assetMetadata));for(let[path,text]of Object.entries(scaffold.documents??{}))writes.push(writeText(join7(folder,path),text));await mkdir(join7(folder,"assets"),{recursive:!0});for(let[path,source]of Object.entries(scaffold.assetFiles??{}))writes.push(copyFile(source,join7(folder,path)));await Promise.all(writes)}function componentAliases(componentsAlias,componentsRelative){let alias=componentsAlias??"@/components/ui",marker="/components/ui",aliasAt=alias.lastIndexOf("/components/ui"),pathAt=componentsRelative.replaceAll("\\","/").lastIndexOf("/components/ui".slice(1));if(aliasAt<0||pathAt<0)return;let from=`${alias.slice(0,aliasAt).replace(/\/$/,"")}/*`,base=componentsRelative.replaceAll("\\","/").slice(0,pathAt).replace(/\/$/,"");return{[from]:base?`${base}/*`:"*"}}import{homedir as homedir2}from"os";import{isAbsolute,join as join8,relative as relative6,sep as sep6}from"path";var import_picocolors=__toESM(require_picocolors(),1);function displayPath(path){let home=homedir2(),rel=relative6(home,path);if(rel==="")return"~";return rel.startsWith("..")||isAbsolute(rel)?path:`~${sep6}${rel}`}function printSummary(folder,scaffold,plan,answers,importedFrom){let boardLabels=scaffold.boards.map((b)=>b.name).join(" + "),themeLabel=importedFrom?`imported from ${relative6(answers.appRoot,importedFrom)||importedFrom}`:presetById(themePresetFor(answers))?.label??themePresetFor(answers);if(console.log(""),console.log(import_picocolors.default.green("\u2713 Velloo is installed and ready to use.")),console.log(import_picocolors.default.dim(` Scaffolded ${displayPath(folder)}`)),console.log(""),scaffold.screens.length>0){console.log(` ${import_picocolors.default.bold(boardLabels)} \u2014 ${scaffold.screens.length} screens across ${scaffold.boards.length} board${scaffold.boards.length===1?"":"s"}.`);let names=scaffold.screens.map((s)=>s.name||s.id),shown=names.slice(0,8),more=names.length-shown.length;if(console.log(import_picocolors.default.dim(` ${shown.join(", ")}${more>0?`, +${more} more`:""}`)),answers.initialContent==="sample")console.log(import_picocolors.default.dim(" Welcome sample \u2014 ready to remix."))}else console.log(import_picocolors.default.dim(" Blank \u2014 no boards or screens yet."));console.log(""),console.log(import_picocolors.default.bold(" Your setup")),console.log(` App root ${answers.appRoot}`),console.log(` Design ${folder}`),console.log(` Library ${plan.summary.name}`),console.log(` Theme ${themeLabel}`);let stack=stackById(answers.stack);if(stack)console.log(` Stack ${stack.label} (imports via ${stack.alias})`);if(plan.pendingUpstream)console.log(import_picocolors.default.dim(` (real shadcn lands in ${plan.pendingUpstream.relative} when your agent finishes setup \u2014 nothing was written to your app)`))}function printExitInstructions(folder,outcome){console.log(""),console.log(import_picocolors.default.bold(" How to use velloo"));let n=1;if(folder){if(outcome.wiredIds.length===0)console.log(` ${n++}. ${import_picocolors.default.cyan(`velloo connect ${folder}`)} ${import_picocolors.default.dim("(wire your AI agent's MCP config + guidance)")}`);console.log(` ${n++}. Reload MCP in your AI agent (or restart it) so it loads the new config ${import_picocolors.default.dim("\u2014 it starts velloo itself")}.`),console.log(` ${n++}. ${import_picocolors.default.cyan("velloo run")} ${import_picocolors.default.dim("(opens the canvas; o open, b background, q stop)")}`),console.log("");let rel=relative6(process.cwd(),folder),readme=join8(rel.startsWith("..")?displayPath(folder):rel||".","README.md");console.log(` ${import_picocolors.default.dim("Open")} ${import_picocolors.default.cyan(readme)} ${import_picocolors.default.dim("for the full guide.")}`)}else console.log(` ${n++}. ${import_picocolors.default.cyan("velloo init")} ${import_picocolors.default.dim("again when you're ready to scaffold a design folder")}`),console.log(` ${n++}. ${import_picocolors.default.cyan("velloo run <design>")} ${import_picocolors.default.dim("opens the canvas for an existing design")}`),console.log(` ${n++}. ${import_picocolors.default.cyan("velloo connect <design>")} ${import_picocolors.default.dim("wires your AI agent's MCP config")}`);console.log("")}async function printScreenshotReadiness(interactive){let installed=await chromiumExecutable()!==null;if(console.log(import_picocolors.default.bold(" Screenshots")),console.log(import_picocolors.default.dim(" Your agent's `screenshot` tool and `velloo render --to=png` use a headless")),console.log(import_picocolors.default.dim(" browser. The canvas, editing, and `velloo publish` don't need it.")),installed){console.log(` ${import_picocolors.default.green("\u2713")} ${import_picocolors.default.dim("Browser installed \u2014 screenshots are ready.")}`),console.log("");return}if(interactive){let proceed=await confirm({message:`Install the screenshot browser now? ${BROWSER_PROMPT_SIZE}
51
+ ${BROWSER_PROMPT_DETAIL}`,initialValue:!1});if(!isCancel(proceed)&&proceed){let ok=await installChromiumInteractive();console.log(ok?` ${import_picocolors.default.green("\u2713")} ${import_picocolors.default.dim("Browser installed \u2014 screenshots are ready.")}`:import_picocolors.default.dim(` Screenshots aren't ready yet \u2014 fix per the messages above, or retry later: ${import_picocolors.default.cyan(CHROMIUM_INSTALL_CMD)}`)),console.log("");return}}console.log(import_picocolors.default.dim(` Add it anytime with: ${import_picocolors.default.cyan(CHROMIUM_INSTALL_CMD)}`)),console.log("")}async function promptShellCompletions(interactive){if(!interactive)return;let shell=detectShell();if(!shell||completionsInstalled(void 0,shell))return;let proceed=await confirm({message:`Install shell completions now? (TAB completion for velloo commands in ${shell})`,initialValue:!0});if(isCancel(proceed)||!proceed){console.log(import_picocolors.default.dim(` Anytime later: ${import_picocolors.default.cyan("velloo completions --install")}`));return}try{let r=await installCompletions(shell);console.log(` ${import_picocolors.default.green("\u2713")} ${shell} completions installed ${import_picocolors.default.dim(shell==="fish"?"\u2014 new fish sessions pick them up.":`\u2014 restart your shell (or \`source ${r.rcPath}\`).`)}`)}catch(err){console.log(import_picocolors.default.dim(` Couldn't install completions (${err.message}) \u2014 try \`velloo completions --install\` later.`))}}
52
+ export{dirExists,discoverScanRoots,scanApps,primaryApp,buildScreensFromScan,buildBoardsFromScan,DEFAULT_THEME_PRESET,isValidPreset,WIZARD_PROVIDERS,LIBRARY_IDS,DEFAULT_LIBRARY_ID,interactiveLibraryChoices,planInstall,scanAdoption,DEFAULT_STACK_ID,stackForFramework,isValidStack,importThemeFromMui,findMuiTheme,importThemeFromGlobals,isEmptyOrMissing,resolveTheme,buildScaffold,writeScaffold,displayPath,printSummary,printExitInstructions,printScreenshotReadiness,promptShellCompletions};