@popcraft/kit 0.53.1 → 0.53.3

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 (77) hide show
  1. package/dist/chunks/{agent-B4XH7FCC.js → agent-DVKYZ5MR.js} +1 -1
  2. package/dist/chunks/{builtin-3TWJNRDI.js → builtin-VDSMLZXH.js} +5 -3
  3. package/dist/chunks/{buy-credits-VZ2J2SR7.js → buy-credits-424PQFK4.js} +2 -2
  4. package/dist/chunks/{check-template-GMNQVCCI.js → check-template-E5WVEJ54.js} +4 -2
  5. package/dist/chunks/{chunk-SMF4YIFH.js → chunk-3OXHJA4W.js} +1 -1
  6. package/dist/chunks/{chunk-U3PY5BWW.js → chunk-4SD7TX7R.js} +11 -11
  7. package/dist/chunks/{chunk-MYCQCAXZ.js → chunk-4SPJEVG6.js} +4 -4
  8. package/dist/chunks/{chunk-YHQGAEC5.js → chunk-524RSKF3.js} +1 -1
  9. package/dist/chunks/{chunk-5JMMBP5Q.js → chunk-5SVFCWRP.js} +60 -101
  10. package/dist/chunks/{chunk-P5HF37GX.js → chunk-6HQI4NQA.js} +2 -2
  11. package/dist/chunks/{chunk-GNNRFMXK.js → chunk-777OZHEF.js} +9 -9
  12. package/dist/chunks/{chunk-DBGETMUH.js → chunk-7IH7U6KU.js} +4 -4
  13. package/dist/chunks/{chunk-UDUHQLOJ.js → chunk-AEVF4O3X.js} +2 -2
  14. package/dist/chunks/{chunk-MJMCMLHB.js → chunk-BKRXB4FD.js} +1 -1
  15. package/dist/chunks/{chunk-UNJ2Y726.js → chunk-FJSJT5ZM.js} +4 -4
  16. package/dist/chunks/{chunk-Z557VFSN.js → chunk-FMWUXVVS.js} +1 -1
  17. package/dist/chunks/{chunk-XMO6D5A2.js → chunk-GUGOVTVN.js} +55 -7
  18. package/dist/chunks/{chunk-IROVLB4V.js → chunk-HS4CR6HU.js} +19 -5
  19. package/dist/chunks/{chunk-XJFTD3EZ.js → chunk-JOUHQ5HK.js} +1 -1
  20. package/dist/chunks/{chunk-7CNZ5HLR.js → chunk-MQ73SYLV.js} +4 -4
  21. package/dist/chunks/{chunk-NPTJQ2AF.js → chunk-NBFZY6QK.js} +1 -1
  22. package/dist/chunks/{chunk-AJPYEZRT.js → chunk-NQPNGZ3C.js} +2 -2
  23. package/dist/chunks/{chunk-D7XGMFYM.js → chunk-ODM6DFGO.js} +4 -4
  24. package/dist/chunks/{chunk-U54RHZSX.js → chunk-OE2LGHLL.js} +3 -3
  25. package/dist/chunks/chunk-OLQTCVWP.js +92 -0
  26. package/dist/chunks/{chunk-T4FFRJAH.js → chunk-OWWBFGCR.js} +3 -3
  27. package/dist/chunks/{chunk-TCPSVZN3.js → chunk-Q23DL77U.js} +5 -5
  28. package/dist/chunks/{chunk-UT6GKZJF.js → chunk-UPLMAXNQ.js} +1 -1
  29. package/dist/chunks/{chunk-5ICU2TQ2.js → chunk-VYWXAGEE.js} +8 -8
  30. package/dist/chunks/{chunk-KPKVF2TA.js → chunk-W5KNQERV.js} +2 -2
  31. package/dist/chunks/{chunk-DFY5UNVM.js → chunk-ZLHMVVTT.js} +45 -5
  32. package/dist/chunks/{chunk-7XP5CWQO.js → chunk-ZPETEA54.js} +183 -71
  33. package/dist/chunks/{client-DNVGPZXT.js → client-2L4XUPQN.js} +1 -1
  34. package/dist/chunks/{client-SE7SVRWK.js → client-6XOD422W.js} +2 -2
  35. package/dist/chunks/{client-77HZDECD.js → client-NOHRL7S3.js} +3 -3
  36. package/dist/chunks/{client-actions-UNYIWTLI.js → client-actions-K54NVVVW.js} +13 -12
  37. package/dist/chunks/{dangerous-WMMPM5TV.js → dangerous-4QU6QUOD.js} +5 -3
  38. package/dist/chunks/{delete-current-file-WB6ZWMBO.js → delete-current-file-RMINS2BA.js} +7 -6
  39. package/dist/chunks/{editor-seams-AZ2NUX6J.js → editor-seams-SW67BCBW.js} +18 -17
  40. package/dist/chunks/{editor-store-TPVGGNLW.js → editor-store-WPRQJL2A.js} +5 -5
  41. package/dist/chunks/{export-PGMO7YEU.js → export-ILWWIDBI.js} +1 -1
  42. package/dist/chunks/{export-watermark-UGGZ5TX6.js → export-watermark-2QVKO7OR.js} +7 -6
  43. package/dist/chunks/{eyedropper-HPK6A4PE.js → eyedropper-WCIR6LL5.js} +3 -2
  44. package/dist/chunks/{generate-media-Y6MB3ENV.js → generate-media-WCNTS5OY.js} +4 -4
  45. package/dist/chunks/{host-FNER4M32.js → host-GLRRFC2S.js} +12 -11
  46. package/dist/chunks/{integrations-LPVAVUUV.js → integrations-5I6DGN6S.js} +1 -1
  47. package/dist/chunks/{libraries-I6J7YJQE.js → libraries-INCBCGOZ.js} +7 -6
  48. package/dist/chunks/{live-ZRJ2GT3E.js → live-SGBLJFAC.js} +3 -2
  49. package/dist/chunks/{lottie-CBQTJRYU.js → lottie-ZWAKIFY2.js} +4 -4
  50. package/dist/chunks/{media-tool-LTK46STY.js → media-tool-KSXO2AAJ.js} +4 -3
  51. package/dist/chunks/{new-file-XH7E3IEZ.js → new-file-56ACDQ35.js} +5 -4
  52. package/dist/chunks/{pdf-NHOWFQ66.js → pdf-HK3GJ6QP.js} +3 -3
  53. package/dist/chunks/{player-check-4LAIMR3H.js → player-check-3HTULNTP.js} +4 -4
  54. package/dist/chunks/{plugin-LAZVW4F4.js → plugin-GJXXN4UQ.js} +4 -2
  55. package/dist/chunks/{plugin-import-P4PD76X3.js → plugin-import-N2J7NVET.js} +23 -22
  56. package/dist/chunks/{pptx-LHJRZA42.js → pptx-O7RRDHAR.js} +2 -2
  57. package/dist/chunks/{presence-WSPF6N32.js → presence-S6FAMSP4.js} +4 -3
  58. package/dist/chunks/{project-M3KF66GG.js → project-IH23X2UG.js} +3 -3
  59. package/dist/chunks/{publish-site-PUHKHZF4.js → publish-site-7YFHE7PV.js} +8 -7
  60. package/dist/chunks/{publish-store-PZMIV6LJ.js → publish-store-I3NKMHZK.js} +5 -5
  61. package/dist/chunks/{raster-actions-NS2NSYLC.js → raster-actions-PRMIAQQ7.js} +3 -2
  62. package/dist/chunks/{reference-images-CYSRQG7A.js → reference-images-TAWHPRYN.js} +2 -2
  63. package/dist/chunks/{resolvers-BQ5WXLUC.js → resolvers-UTQHZ6ET.js} +5 -5
  64. package/dist/chunks/{runner-PGFSW23U.js → runner-OVYUXA4W.js} +30 -24
  65. package/dist/chunks/{store-BXDDRMK7.js → store-BYSDY5PO.js} +14 -13
  66. package/dist/chunks/{storefront-prepare-EXR7OIWW.js → storefront-prepare-6IUMZTCQ.js} +1 -1
  67. package/dist/chunks/{svg-export-J2YVV3WM.js → svg-export-LMGINUQK.js} +5 -5
  68. package/dist/chunks/{svg-place-ZAG7VYF6.js → svg-place-LWB4XU2O.js} +2 -1
  69. package/dist/chunks/{sync-4AHF7NWR.js → sync-TFB3VWFP.js} +7 -6
  70. package/dist/chunks/{tabs-KFQNMNUM.js → tabs-CNE4XGIM.js} +10 -9
  71. package/dist/chunks/{team-QUBELR4W.js → team-DFOKEFOE.js} +1 -1
  72. package/dist/chunks/{team-client-NCOTLKC5.js → team-client-QHRXYUPI.js} +1 -1
  73. package/dist/chunks/{tools-T5XCKKCW.js → tools-YDR7QIHQ.js} +4 -2
  74. package/dist/chunks/{ui-commands-77JZN35K.js → ui-commands-HB4FFFXA.js} +20 -19
  75. package/dist/chunks/{versions-5HYBXUPA.js → versions-G4PGAFLF.js} +7 -6
  76. package/dist/index.js +1 -1
  77. package/package.json +1 -1
@@ -76,6 +76,9 @@ import {
76
76
  reboxed,
77
77
  textAndShapeOf
78
78
  } from "./chunk-ZWKNYWUL.js";
79
+ import {
80
+ scaleSubtreePatches
81
+ } from "./chunk-OLQTCVWP.js";
79
82
  import {
80
83
  cleanAnchor,
81
84
  hrefOf
@@ -156,6 +159,9 @@ import {
156
159
  bindShaderAudio,
157
160
  retuneShaderAudio
158
161
  } from "./chunk-A54HJQ6T.js";
162
+ import {
163
+ pathBounds
164
+ } from "./chunk-7DATU5VX.js";
159
165
  import {
160
166
  HELPER_NAMES
161
167
  } from "./chunk-6YZC5UXW.js";
@@ -316,6 +322,7 @@ import {
316
322
  } from "./chunk-WLPGSUI2.js";
317
323
  import {
318
324
  addNode,
325
+ applyConstraints,
319
326
  createArrow,
320
327
  createEllipse,
321
328
  createFrame,
@@ -336,6 +343,7 @@ import {
336
343
  init_scene_graph,
337
344
  isPrintPage,
338
345
  moveNodeInZOrder,
346
+ placementUnder,
339
347
  printPageOf,
340
348
  removeNode,
341
349
  reparentNode,
@@ -586,7 +594,10 @@ init_scene_graph();
586
594
  init_types();
587
595
  var MAX_NODES = 200;
588
596
  var plural = (n, one, many = `${one}s`) => `${n} ${n === 1 ? one : many}`;
589
- var hexOf = (c) => c ? "#" + [c.r, c.g, c.b].map((v) => Math.round(Math.max(0, Math.min(1, v)) * 255).toString(16).padStart(2, "0")).join("") : "";
597
+ var hexOf = (c) => c ? "#" + [c.r, c.g, c.b].map((v) => {
598
+ const n = Number.isFinite(v) ? Math.max(0, Math.min(1, v)) : 0;
599
+ return Math.round(n * 255).toString(16).padStart(2, "0");
600
+ }).join("") : "";
590
601
  function nodeOrThrow(doc2, id) {
591
602
  const n = doc2.nodes[id];
592
603
  if (!n) throw new ToolError(`Unknown node id "${id}". Call get_document_outline or find_nodes first and use an id from there.`);
@@ -862,7 +873,7 @@ init_scene_graph();
862
873
  var licence = external_exports.enum(["commercial", "any"]).optional().describe("commercial (default): only licences that allow commercial use and edits (CC0, public domain, CC BY, CC BY-SA). any: every Creative Commons licence, including NC and ND.");
863
874
  var brief2 = (p) => ({ id: p.id, title: p.title, creator: p.credit.creator, licence: licenceLabel(p.credit), width: p.width, height: p.height, source: p.credit.sourceUrl });
864
875
  async function placeImportedPicture(ctx, imported, at, what, extra = {}) {
865
- const client = await import("./client-DNVGPZXT.js");
876
+ const client = await import("./client-2L4XUPQN.js");
866
877
  if (at.fillLayerId) {
867
878
  const doc2 = ctx.doc();
868
879
  const target = nodeOrThrow(doc2, at.fillLayerId);
@@ -908,7 +919,7 @@ var photoSearch = defineCommand({
908
919
  }
909
920
  },
910
921
  run: async (args) => {
911
- const { searchStockPhotos } = await import("./client-DNVGPZXT.js");
922
+ const { searchStockPhotos } = await import("./client-2L4XUPQN.js");
912
923
  const page = await searchStockPhotos(args.query, args.page ?? 1, { licence: args.licence });
913
924
  return {
914
925
  summary: `${page.results.length} photo${page.results.length === 1 ? "" : "s"} for \u201C${page.query}\u201D (page ${page.page} of ${page.pageCount || 1})`,
@@ -942,7 +953,7 @@ var photoInsert = defineCommand({
942
953
  run: async (args, ctx) => {
943
954
  if (!args.id && !args.query) throw new ToolError("Pass an id from search_photos, or a query.");
944
955
  if (args.id && !isPhotoId(args.id)) throw new ToolError(`"${args.id}" is not a photo id from search_photos.`);
945
- const client = await import("./client-DNVGPZXT.js");
956
+ const client = await import("./client-2L4XUPQN.js");
946
957
  let photo;
947
958
  if (args.id) photo = await client.stockPhotoInfo(args.id);
948
959
  else {
@@ -980,8 +991,15 @@ var mediaList = defineCommand({
980
991
  }
981
992
  },
982
993
  run: async (args) => {
983
- const { listLibraryMedia } = await import("./client-SE7SVRWK.js");
984
- const page = await listLibraryMedia(args);
994
+ const { listLibraryMedia } = await import("./client-6XOD422W.js");
995
+ const q = { ...args };
996
+ if (!q.workspace) {
997
+ const { syncStatus } = await import("./sync-TFB3VWFP.js");
998
+ const link2 = syncStatus().link;
999
+ if (!link2) throw new ToolError("This document is not saved to the cloud, so it has no team media library. Pass workspace.");
1000
+ q.workspace = (await listLibraryMedia({ file: link2.key, limit: 1 })).workspaceId;
1001
+ }
1002
+ const page = await listLibraryMedia(q);
985
1003
  return { summary: `${page.items.length} media item${page.items.length === 1 ? "" : "s"}${page.nextCursor ? " (more)" : ""}`, data: { workspaceId: page.workspaceId, items: page.items.map(brief3), nextCursor: page.nextCursor } };
986
1004
  }
987
1005
  });
@@ -1011,7 +1029,7 @@ var mediaInsert = defineCommand({
1011
1029
  run: async (args, ctx) => {
1012
1030
  const contentType = args.contentType ?? "image/*";
1013
1031
  if (!contentType.startsWith("image/")) throw new ToolError("insert_media places pictures; this item is not one.");
1014
- const { importLibraryPicture } = await import("./client-SE7SVRWK.js");
1032
+ const { importLibraryPicture } = await import("./client-6XOD422W.js");
1015
1033
  const item = { hash: args.hash, fileKey: args.fileKey, fileName: args.name ?? "Media", contentType, size: 0, createdAt: "", fileCount: 1, source: null };
1016
1034
  const imported = await importLibraryPicture(item);
1017
1035
  return placeImportedPicture(ctx, imported, args, `\u201C${imported.name}\u201D`, { hash: imported.hash });
@@ -1032,7 +1050,7 @@ var mediaDownload = defineCommand({
1032
1050
  // The Library's right-click menu: saves the item's file to the computer.
1033
1051
  expose: { ui: { label: "Download", palette: false } },
1034
1052
  run: async (args) => {
1035
- const { libraryBlob, libraryFileName } = await import("./client-SE7SVRWK.js");
1053
+ const { libraryBlob, libraryFileName } = await import("./client-6XOD422W.js");
1036
1054
  const { downloadBlob } = await import("./download-YRHNMQPH.js");
1037
1055
  const item = { hash: args.hash, fileKey: args.fileKey, fileName: args.name ?? "media", contentType: args.contentType ?? "", size: 0, createdAt: "", fileCount: 1, source: null };
1038
1056
  const blob = await libraryBlob(item);
@@ -1063,7 +1081,7 @@ var mediaDelete = defineCommand({
1063
1081
  }
1064
1082
  },
1065
1083
  run: async (args) => {
1066
- const { deleteLibraryMedia } = await import("./client-SE7SVRWK.js");
1084
+ const { deleteLibraryMedia } = await import("./client-6XOD422W.js");
1067
1085
  const out = await deleteLibraryMedia(args.workspace, args.hash);
1068
1086
  return { summary: `Deleted it from the library (it was in ${out.files} file${out.files === 1 ? "" : "s"})`, data: out };
1069
1087
  }
@@ -1077,13 +1095,13 @@ async function signedIn() {
1077
1095
  }
1078
1096
  async function publishedFile() {
1079
1097
  await signedIn();
1080
- const { openFileKey } = await import("./publish-site-PUHKHZF4.js");
1098
+ const { openFileKey } = await import("./publish-site-7YFHE7PV.js");
1081
1099
  const key = openFileKey();
1082
1100
  if (!key) throw new CommandError("This file is not saved to the cloud yet, so it has no site. Publish it first.", "failed");
1083
1101
  return key;
1084
1102
  }
1085
1103
  async function formsWithoutDatabase(key) {
1086
- const [{ useEditorStore }, { usesForms, formsGoNowhere }, { siteBackend }] = await Promise.all([import("./editor-store-TPVGGNLW.js"), import("./backend-Q4FQVKIS.js"), import("./integrations-LPVAVUUV.js")]);
1104
+ const [{ useEditorStore }, { usesForms, formsGoNowhere }, { siteBackend }] = await Promise.all([import("./editor-store-WPRQJL2A.js"), import("./backend-Q4FQVKIS.js"), import("./integrations-5I6DGN6S.js")]);
1087
1105
  const doc2 = useEditorStore.getState().document;
1088
1106
  if (!usesForms(doc2)) return false;
1089
1107
  return formsGoNowhere(doc2, await siteBackend(key).catch(() => void 0));
@@ -1119,7 +1137,7 @@ var publishSite = defineCommand({
1119
1137
  const { cleanSlug } = await import("./rules-QWGSAJAE.js");
1120
1138
  const address = p.address === void 0 ? void 0 : cleanSlug(p.address);
1121
1139
  if (address === null) throw new CommandError("That cannot be a site address: use 3 to 40 letters, digits and dashes.", "invalid_params");
1122
- const { publishOpenFile, NoScreens } = await import("./publish-site-PUHKHZF4.js");
1140
+ const { publishOpenFile, NoScreens } = await import("./publish-site-7YFHE7PV.js");
1123
1141
  try {
1124
1142
  const done = await publishOpenFile(address);
1125
1143
  ctx.notice(`Published version ${done.version}: ${done.url}`);
@@ -1174,7 +1192,7 @@ var publishListSites = defineCommand({
1174
1192
  },
1175
1193
  run: async (p) => {
1176
1194
  await signedIn();
1177
- const [{ workspaceSites }, { activeTeamWorkspaceId, useHyperyTeam }] = await Promise.all([import("./sites-L6JYZ4SV.js"), import("./team-QUBELR4W.js")]);
1195
+ const [{ workspaceSites }, { activeTeamWorkspaceId, useHyperyTeam }] = await Promise.all([import("./sites-L6JYZ4SV.js"), import("./team-DFOKEFOE.js")]);
1178
1196
  const workspaceId = p.workspaceId ?? activeTeamWorkspaceId() ?? useHyperyTeam.getState().personalWorkspaceId;
1179
1197
  if (!workspaceId) throw new CommandError("Your workspaces have not loaded yet. Try again in a moment.", "failed");
1180
1198
  const out = await workspaceSites(workspaceId);
@@ -1223,12 +1241,12 @@ var publishStatus = defineCommand({
1223
1241
  },
1224
1242
  run: async () => {
1225
1243
  await signedIn();
1226
- const [{ openFileKey }, { siteStatus }] = await Promise.all([import("./publish-site-PUHKHZF4.js"), import("./sites-L6JYZ4SV.js")]);
1244
+ const [{ openFileKey }, { siteStatus }] = await Promise.all([import("./publish-site-7YFHE7PV.js"), import("./sites-L6JYZ4SV.js")]);
1227
1245
  const key = openFileKey();
1228
1246
  const status = await siteStatus(key);
1229
1247
  const site = status.site;
1230
- const backend = key ? await (await import("./integrations-LPVAVUUV.js")).siteBackend(key).catch(() => null) : null;
1231
- const destinations = key ? await (await import("./integrations-LPVAVUUV.js")).listDestinations(key).catch(() => []) : [];
1248
+ const backend = key ? await (await import("./integrations-5I6DGN6S.js")).siteBackend(key).catch(() => null) : null;
1249
+ const destinations = key ? await (await import("./integrations-5I6DGN6S.js")).listDestinations(key).catch(() => []) : [];
1232
1250
  return {
1233
1251
  summary: !status.configured ? "This server does not publish websites" : !site ? "Not published yet" : site.currentVersion === null ? `Offline (${site.versions.length} versions kept) \u2014 ${site.url}` : `Version ${site.currentVersion} is online at ${site.url}`,
1234
1252
  data: { ...statusData(status), database: backend?.database ? { provider: backend.database.connection.provider, account: backend.database.connection.account, target: backend.database.target.map((t) => t.name), visitorsCanSignIn: backend.database.signIn } : null, destinations: destinations.map((d) => ({ destinationId: d.id, provider: d.connection.provider, account: d.connection.account, kind: d.capability, target: d.target.map((t) => t.name), lastSent: d.lastDeploy })) }
@@ -1259,7 +1277,7 @@ var publishStore = defineCommand({
1259
1277
  },
1260
1278
  run: async (p, ctx) => {
1261
1279
  await signedIn();
1262
- const { deployOpenStore } = await import("./publish-store-PZMIV6LJ.js");
1280
+ const { deployOpenStore } = await import("./publish-store-I3NKMHZK.js");
1263
1281
  const done = await deployOpenStore(ctx.doc(), ctx.pageId(), { destinationId: p.destinationId }).catch((e) => {
1264
1282
  throw new CommandError(e instanceof Error ? e.message : String(e), "failed");
1265
1283
  });
@@ -1288,7 +1306,7 @@ var integrationList = defineCommand({
1288
1306
  }
1289
1307
  },
1290
1308
  run: async ({ capability }) => {
1291
- const [{ cloudUser }, { integrationsWorkspaceId, listWorkspaceIntegrations }] = await Promise.all([import("./session-QE4TAG7G.js"), import("./integrations-LPVAVUUV.js")]);
1309
+ const [{ cloudUser }, { integrationsWorkspaceId, listWorkspaceIntegrations }] = await Promise.all([import("./session-QE4TAG7G.js"), import("./integrations-5I6DGN6S.js")]);
1292
1310
  if (!cloudUser()) throw new CommandError("You are not signed in: integrations belong to your account's workspace.", "denied");
1293
1311
  const workspaceId = integrationsWorkspaceId();
1294
1312
  if (!workspaceId) throw new CommandError("Your workspaces have not loaded yet. Try again in a moment.", "failed");
@@ -1329,7 +1347,7 @@ var integrationOpen = defineCommand({
1329
1347
  }
1330
1348
  });
1331
1349
  async function openFile() {
1332
- const [{ cloudUser }, { openFileKey }] = await Promise.all([import("./session-QE4TAG7G.js"), import("./publish-site-PUHKHZF4.js")]);
1350
+ const [{ cloudUser }, { openFileKey }] = await Promise.all([import("./session-QE4TAG7G.js"), import("./publish-site-7YFHE7PV.js")]);
1333
1351
  if (!cloudUser()) throw new CommandError("You are not signed in.", "denied");
1334
1352
  const key = openFileKey();
1335
1353
  if (!key) throw new CommandError("This file is not saved to the cloud yet. Publish it first (publish_site).", "failed");
@@ -1355,7 +1373,7 @@ var integrationListResources = defineCommand({
1355
1373
  }
1356
1374
  },
1357
1375
  run: async ({ connectionId, capability, path }) => {
1358
- const { listResources } = await import("./integrations-LPVAVUUV.js");
1376
+ const { listResources } = await import("./integrations-5I6DGN6S.js");
1359
1377
  const list = await listResources(connectionId, capability, asPath2(path));
1360
1378
  return {
1361
1379
  summary: list.level ? `${list.resources.length} at the ${list.level.label.toLowerCase()} level${list.canCreate ? " (a new one can be made)" : ""}` : "Nothing further to pick: the path is complete",
@@ -1390,7 +1408,7 @@ var integrationAddDestination = defineCommand({
1390
1408
  },
1391
1409
  run: async (p, ctx) => {
1392
1410
  const key = await openFile();
1393
- const { addDestination, createDestination, createResource } = await import("./integrations-LPVAVUUV.js");
1411
+ const { addDestination, createDestination, createResource } = await import("./integrations-5I6DGN6S.js");
1394
1412
  let made;
1395
1413
  if (p.create) made = await createDestination(key, p.capability, void 0, p.connectionId);
1396
1414
  else {
@@ -1427,7 +1445,7 @@ var integrationDeploy = defineCommand({
1427
1445
  },
1428
1446
  run: async (p, ctx) => {
1429
1447
  const key = await openFile();
1430
- const { deployDestination, listDestinations } = await import("./integrations-LPVAVUUV.js");
1448
+ const { deployDestination, listDestinations } = await import("./integrations-5I6DGN6S.js");
1431
1449
  const all = await listDestinations(key);
1432
1450
  const dest = p.destinationId ? all.find((d) => d.id === p.destinationId) : all.length === 1 ? all[0] : void 0;
1433
1451
  if (!dest) throw new CommandError(all.length ? `Say which destination: ${all.map((d) => `${d.id} (${d.target.map((t) => t.name).join(" / ")})`).join(", ")}.` : "This file has no destination yet. Add one first (add_site_destination).", "invalid_params");
@@ -1461,7 +1479,7 @@ var integrationAttachDatabase = defineCommand({
1461
1479
  },
1462
1480
  run: async (p, ctx) => {
1463
1481
  const key = await openFile();
1464
- const { attachDatabase, createDatabase, createResource, listResources } = await import("./integrations-LPVAVUUV.js");
1482
+ const { attachDatabase, createDatabase, createResource, listResources } = await import("./integrations-5I6DGN6S.js");
1465
1483
  if (p.create) return attached(await createDatabase(key, void 0, p.connectionId), ctx);
1466
1484
  if (!p.connectionId || !p.target) throw new CommandError("Say connectionId and target, or create: true.", "invalid_params");
1467
1485
  let target = asPath2(p.target);
@@ -1500,7 +1518,7 @@ var integrationSubmissions = defineCommand({
1500
1518
  },
1501
1519
  run: async ({ form, limit }) => {
1502
1520
  const key = await openFile();
1503
- const { listSubmissions } = await import("./integrations-LPVAVUUV.js");
1521
+ const { listSubmissions } = await import("./integrations-5I6DGN6S.js");
1504
1522
  const rows = await listSubmissions(key, { form, limit: limit ?? 20 });
1505
1523
  return { summary: rows.length ? `${rows.length} ${rows.length === 1 ? "submission" : "submissions"}, the newest ${new Date(rows[0].createdAt).toISOString()}` : "Nothing has been sent yet", data: { submissions: rows } };
1506
1524
  }
@@ -1525,7 +1543,7 @@ var integrationSetSignIn = defineCommand({
1525
1543
  },
1526
1544
  run: async ({ on }, ctx) => {
1527
1545
  const key = await openFile();
1528
- const { setSignIn } = await import("./integrations-LPVAVUUV.js");
1546
+ const { setSignIn } = await import("./integrations-5I6DGN6S.js");
1529
1547
  const done = await setSignIn(key, on);
1530
1548
  ctx.notice(on ? "Visitors can sign in." : "Sign-in is off.");
1531
1549
  return { summary: on ? "Visitors can now create accounts and sign in on the published site" : "Sign-in is off for the published site", data: { signIn: !!done.database?.signIn } };
@@ -1743,7 +1761,7 @@ var fontTeamList = defineCommand({
1743
1761
  agent: { name: "list_team_fonts", readOnly: true, description: "The team's fonts: faces uploaded once that every file of the team can use (family, weight, style)." }
1744
1762
  },
1745
1763
  run: async (args) => {
1746
- const { refreshTeamFonts } = await import("./team-client-NCOTLKC5.js");
1764
+ const { refreshTeamFonts } = await import("./team-client-QHRXYUPI.js");
1747
1765
  const fonts = await refreshTeamFonts(args.workspace);
1748
1766
  return { summary: plural(fonts.length, "team font"), data: { fonts: fonts.map((f) => ({ id: f.id, family: f.family, weight: f.weight, style: f.style, face: f.face, fileName: f.fileName })) } };
1749
1767
  }
@@ -1770,7 +1788,7 @@ var fontTeamAdd = defineCommand({
1770
1788
  run: async (args, ctx) => {
1771
1789
  const { bytes, fileName: fileName2 } = await fontBytes(args, ctx);
1772
1790
  const { face, family, weight, style } = await resolveFace(bytes, args);
1773
- const { uploadTeamFont } = await import("./team-client-NCOTLKC5.js");
1791
+ const { uploadTeamFont } = await import("./team-client-QHRXYUPI.js");
1774
1792
  const font = await uploadTeamFont(bytes, { family, weight, style, face: face.index, fileName: fileName2 }, args.workspace);
1775
1793
  return { summary: `Added ${family} ${weight}${style === "italic" ? " italic" : ""} to the team`, data: { font } };
1776
1794
  }
@@ -1792,7 +1810,7 @@ var fontTeamRemove = defineCommand({
1792
1810
  agent: { name: "remove_team_font", description: "Remove a font from the team (list_team_fonts). Files that use it fall back to another font unless they carry it themselves. The user approves every call." }
1793
1811
  },
1794
1812
  run: async (args) => {
1795
- const { removeTeamFont } = await import("./team-client-NCOTLKC5.js");
1813
+ const { removeTeamFont } = await import("./team-client-QHRXYUPI.js");
1796
1814
  const out = await removeTeamFont(args.id, args.workspace);
1797
1815
  return { summary: `Removed the team font${out.freed ? " and freed its storage" : ""}`, data: out };
1798
1816
  }
@@ -1803,7 +1821,7 @@ var fontTeamCommands = [fontTeamList, fontTeamAdd];
1803
1821
  init_define_POPCRAFT_COMPONENT_IDS();
1804
1822
  async function cloudFile() {
1805
1823
  const [{ syncStatus }, { cloudUser }] = await Promise.all([
1806
- import("./sync-4AHF7NWR.js"),
1824
+ import("./sync-TFB3VWFP.js"),
1807
1825
  import("./session-QE4TAG7G.js")
1808
1826
  ]);
1809
1827
  const link2 = syncStatus().link;
@@ -1865,7 +1883,7 @@ var fileTrash = defineCommand({
1865
1883
  agent: { name: "trash_file", description: "Delete the open file: a cloud file goes to the Trash (restorable), a signed-out local file is deleted for good. Then the editor goes back to Home. The user approves every call." }
1866
1884
  },
1867
1885
  run: async () => {
1868
- const { deleteCurrentFile, leaveDeletedFile } = await import("./delete-current-file-WB6ZWMBO.js");
1886
+ const { deleteCurrentFile, leaveDeletedFile } = await import("./delete-current-file-RMINS2BA.js");
1869
1887
  const { name: name2, kind } = await deleteCurrentFile();
1870
1888
  leaveDeletedFile();
1871
1889
  return { summary: kind === "cloud" ? `Moved \u201C${name2}\u201D to the Trash` : `Deleted \u201C${name2}\u201D` };
@@ -1978,11 +1996,11 @@ var fileDuplicate = defineCommand({
1978
1996
  },
1979
1997
  run: async (_p, ctx) => {
1980
1998
  const [{ syncStatus }, { cloudApi }, { isDesktopTabs }, { createFileInTab }, { openNewCloudFile }, { v4: uuid }] = await Promise.all([
1981
- import("./sync-4AHF7NWR.js"),
1999
+ import("./sync-TFB3VWFP.js"),
1982
2000
  import("./api-7ZHHFXRP.js"),
1983
2001
  import("./tab-mode-5ALKOT7S.js"),
1984
- import("./tabs-KFQNMNUM.js"),
1985
- import("./sync-4AHF7NWR.js"),
2002
+ import("./tabs-CNE4XGIM.js"),
2003
+ import("./sync-TFB3VWFP.js"),
1986
2004
  import("./dist-node-MAITLUAX.js")
1987
2005
  ]);
1988
2006
  const doc2 = ctx.doc();
@@ -2304,10 +2322,12 @@ var nodeFind = defineCommand({
2304
2322
  hits.push(n);
2305
2323
  if (hits.length >= limit) break;
2306
2324
  }
2325
+ const truncated = hits.length >= limit;
2307
2326
  return {
2308
- summary: `${plural(hits.length, "match", "matches")} for ${q || type || args.name || "everything here"}`,
2327
+ summary: `${plural(hits.length, "match", "matches")}${truncated ? "+ (capped)" : ""} for ${q || type || args.name || "everything here"}`,
2309
2328
  data: {
2310
2329
  count: hits.length,
2330
+ truncated,
2311
2331
  nodes: args.detail === "full" ? plain(hits) : hits.map((n) => ({ ...brief(n), page: pageOf2(doc2, n.id) }))
2312
2332
  }
2313
2333
  };
@@ -2349,11 +2369,23 @@ var nodeGet = defineCommand({
2349
2369
  return n2 ? plain(n2) : null;
2350
2370
  }
2351
2371
  const n = resolvedNodeOrThrow(doc2, id);
2352
- return args.detail === "full" ? plain(n) : describeProps(doc2, n);
2372
+ if (args.detail === "full") return plain(n);
2373
+ const props = describeProps(doc2, n);
2374
+ const warning = geometryMismatch(doc2, n.id);
2375
+ return warning ? { ...props, warning } : props;
2353
2376
  });
2354
2377
  return { summary: `Read ${plural(nodes.length, "layer")}`, data: { nodes } };
2355
2378
  }
2356
2379
  });
2380
+ function geometryMismatch(doc2, id) {
2381
+ const n = doc2.nodes[id];
2382
+ if (!n || n.type !== "VECTOR" || !n.paths?.length) return void 0;
2383
+ const pb = pathBounds(n.paths);
2384
+ if (!pb) return void 0;
2385
+ const gw = pb.maxX - pb.minX, gh = pb.maxY - pb.minY;
2386
+ if (Math.abs(gw - n.width) <= 1 && Math.abs(gh - n.height) <= 1) return void 0;
2387
+ return `box is ${Math.round(n.width)}\xD7${Math.round(n.height)} but the artwork is ${Math.round(gw)}\xD7${Math.round(gh)} \u2014 resize_nodes to reconcile them`;
2388
+ }
2357
2389
  var nodeMeasure = defineCommand({
2358
2390
  id: "node.measure",
2359
2391
  title: "Measure layers",
@@ -2382,7 +2414,8 @@ var nodeMeasure = defineCommand({
2382
2414
  });
2383
2415
  const each = ids.map((id) => {
2384
2416
  const rb = getWorldRenderBounds(doc2, id);
2385
- return { id, name: doc2.nodes[id].name, bounds: rb ? round(rb) : null };
2417
+ const warning = geometryMismatch(doc2, id);
2418
+ return { id, name: doc2.nodes[id].name, bounds: rb ? round(rb) : null, ...warning ? { warning } : {} };
2386
2419
  });
2387
2420
  const combined = round(box);
2388
2421
  return { summary: `Bounds: ${combined.width}\xD7${combined.height} at ${combined.x},${combined.y}`, data: { combined, nodes: each } };
@@ -2527,6 +2560,40 @@ var nodeCreate = defineCommand({
2527
2560
  }
2528
2561
  });
2529
2562
  var FORBIDDEN_PROPS = /* @__PURE__ */ new Set(["id", "type", "parentId", "childIds"]);
2563
+ function normalizeColor(c, key) {
2564
+ if (typeof c === "string") return parseHex(c);
2565
+ const o = c;
2566
+ const ch = o && ["r", "g", "b"].map((k) => o[k]);
2567
+ if (!ch || !ch.every((v) => typeof v === "number" && Number.isFinite(v))) {
2568
+ throw new ToolError(`${key} has a colour without numeric r, g and b. Give 0\u20131 channels, or use set_fills with a hex colour.`);
2569
+ }
2570
+ const nums = ch;
2571
+ const scale = nums.some((v) => v > 1) ? 255 : 1;
2572
+ const a = typeof o.a === "number" && Number.isFinite(o.a) ? o.a > 1 ? o.a / 255 : o.a : 1;
2573
+ return createColor(nums[0] / scale, nums[1] / scale, nums[2] / scale, a);
2574
+ }
2575
+ function normalizeSegments(v) {
2576
+ if (!Array.isArray(v)) return v;
2577
+ return v.map((seg) => {
2578
+ if (!seg || typeof seg !== "object") return seg;
2579
+ const s = { ...seg };
2580
+ for (const k of ["fills", "strokes", "textDecorationColor"]) if (k in s) s[k] = normalizePaints(s[k], k);
2581
+ return s;
2582
+ });
2583
+ }
2584
+ function normalizePaints(v, key) {
2585
+ if (!Array.isArray(v)) throw new ToolError(`${key} must be an array of paints.`);
2586
+ return v.map((p) => {
2587
+ const paint = p;
2588
+ if (!paint || typeof paint !== "object") throw new ToolError(`${key} must be an array of paint objects.`);
2589
+ const out = { ...paint };
2590
+ if ("color" in paint) out.color = normalizeColor(paint.color, key);
2591
+ if (Array.isArray(paint.gradientStops)) {
2592
+ out.gradientStops = paint.gradientStops.map((s) => ({ ...s, color: normalizeColor(s.color, key) }));
2593
+ }
2594
+ return out;
2595
+ });
2596
+ }
2530
2597
  var nodeUpdate = defineCommand({
2531
2598
  id: "node.update",
2532
2599
  title: "Update layers",
@@ -2575,13 +2642,34 @@ var nodeUpdate = defineCommand({
2575
2642
  for (const [k, v] of Object.entries(u.props)) {
2576
2643
  if (args.strict && FORBIDDEN_PROPS.has(k)) throw new ToolError(`update_nodes cannot change "${k}". Use reparent, delete_nodes or create_node instead.`);
2577
2644
  if (FORBIDDEN_PROPS.has(k) || v === void 0) continue;
2578
- patch[k] = v;
2645
+ patch[k] = k === "fills" || k === "strokes" ? normalizePaints(v, k) : k === "styledSegments" ? normalizeSegments(v) : v;
2579
2646
  changedKeys.add(k);
2580
2647
  }
2648
+ if ("fills" in patch) patch.fillStyleId = void 0;
2649
+ if ("strokes" in patch) patch.strokeStyleId = void 0;
2581
2650
  if (args.strict && !Object.keys(patch).length) throw new ToolError(`No properties given for "${u.id}".`);
2582
2651
  patches.set(u.id, patch);
2583
2652
  }
2584
- commitUpdates(ctx, doc2, patches);
2653
+ for (const [id, patch] of patches) {
2654
+ const p = patch;
2655
+ if (!("width" in p) && !("height" in p)) continue;
2656
+ const n = doc2.nodes[id];
2657
+ if (n.width <= 0 || n.height <= 0) continue;
2658
+ const w = p.width ?? n.width, h = p.height ?? n.height;
2659
+ if (n.type === "FRAME" || n.type === "COMPONENT" || n.type === "SECTION") continue;
2660
+ for (const [pid, sub] of scaleSubtreePatches(doc2.nodes, id, w / n.width, h / n.height)) {
2661
+ patches.set(pid, { ...patches.get(pid), ...sub });
2662
+ }
2663
+ }
2664
+ let committed = doc2;
2665
+ for (const [id, patch] of patches) {
2666
+ const p = patch;
2667
+ const n = doc2.nodes[id];
2668
+ if (("width" in p || "height" in p) && (n.type === "FRAME" || n.type === "COMPONENT" || n.type === "SECTION")) {
2669
+ committed = applyConstraints(committed, id, n.width, n.height, p.width ?? n.width, p.height ?? n.height);
2670
+ }
2671
+ }
2672
+ commitUpdates(ctx, committed, patches);
2585
2673
  return { summary: `Updated ${plural(patches.size, "layer")} (${[...changedKeys].slice(0, 6).join(", ")})`, data: { ids: [...patches.keys()] } };
2586
2674
  }
2587
2675
  });
@@ -2690,9 +2778,21 @@ var nodeResize = defineCommand({
2690
2778
  const n = doc2.nodes[id];
2691
2779
  const w = args.width ?? (args.scale ? n.width * args.scale : n.width);
2692
2780
  const h = args.height ?? (args.scale ? n.height * args.scale : n.height);
2693
- patches.set(id, { width: Math.max(AI_LIMITS.minSize, w), height: Math.max(AI_LIMITS.minSize, h) });
2781
+ const width = Math.max(AI_LIMITS.minSize, w), height = Math.max(AI_LIMITS.minSize, h);
2782
+ patches.set(id, { width, height });
2783
+ if (n.width <= 0 || n.height <= 0) continue;
2784
+ for (const [pid, patch] of scaleSubtreePatches(doc2.nodes, id, width / n.width, height / n.height)) {
2785
+ patches.set(pid, { ...patches.get(pid), ...patch });
2786
+ }
2694
2787
  }
2695
- commitUpdates(ctx, doc2, patches);
2788
+ let next = doc2;
2789
+ for (const id of ids) {
2790
+ const n = doc2.nodes[id], p = patches.get(id);
2791
+ if (n.type === "FRAME" || n.type === "COMPONENT" || n.type === "SECTION") {
2792
+ next = applyConstraints(next, id, n.width, n.height, p.width, p.height);
2793
+ }
2794
+ }
2795
+ commitUpdates(ctx, next, patches);
2696
2796
  return { summary: `Resized ${plural(ids.length, "layer")}`, data: { ids } };
2697
2797
  }
2698
2798
  });
@@ -2712,7 +2812,7 @@ var nodeReparent = defineCommand({
2712
2812
  plugin: { method: "reparentNodes" },
2713
2813
  agent: {
2714
2814
  name: "reparent",
2715
- description: "Move layers into another parent (frame, group or page), optionally at a child index. Positions stay in the new parent's coordinates, so move_nodes afterwards if they land off-screen."
2815
+ description: "Move layers into another parent (frame, group or page), optionally at a child index. Each layer keeps its position on screen (its coordinates are rebased into the new parent)."
2716
2816
  }
2717
2817
  },
2718
2818
  run: (args, ctx) => {
@@ -2723,6 +2823,8 @@ var nodeReparent = defineCommand({
2723
2823
  for (const id of args.ids) {
2724
2824
  nodeOrThrow(doc2, id);
2725
2825
  if (id === args.parentId) throw new ToolError("A layer cannot be its own parent.");
2826
+ const placed = placementUnder(next, id, args.parentId);
2827
+ if (placed) next = updateNode(next, id, placed);
2726
2828
  next = reparentNode(next, id, args.parentId, args.index);
2727
2829
  }
2728
2830
  ctx.commit(applyInvariants(next, [...args.ids, args.parentId]));
@@ -3029,6 +3131,9 @@ var nodeImportSvg = defineCommand({
3029
3131
  svg: external_exports.string().min(8).optional().describe("The full <svg>\u2026</svg> markup."),
3030
3132
  parentId: external_exports.string().optional(),
3031
3133
  at: external_exports.object({ x: external_exports.number(), y: external_exports.number() }).optional().describe("Place the layers in one frame centred on this point (parent coordinates) instead of at the SVG's own coordinates."),
3134
+ anchor: external_exports.enum(["center", "top-left"]).optional().describe("Whether `at` is the frame's centre (default) or its top-left corner."),
3135
+ width: external_exports.number().positive().optional().describe("With `at`: scale the artwork to fit this width (keeps proportions)."),
3136
+ height: external_exports.number().positive().optional().describe("With `at`: scale the artwork to fit this height (keeps proportions)."),
3032
3137
  name: external_exports.string().max(200).optional().describe("Name of that frame (with `at`)."),
3033
3138
  more: external_exports.array(external_exports.object({ svg: external_exports.string().min(8), name: external_exports.string().max(200).optional() })).max(50).optional().describe("Further SVGs placed in the same step (with `at`), each 24 px further down and right.")
3034
3139
  }),
@@ -3036,7 +3141,7 @@ var nodeImportSvg = defineCommand({
3036
3141
  plugin: { method: "importSvg" },
3037
3142
  agent: {
3038
3143
  name: "import_svg",
3039
- description: "Import SVG markup as editable layers under a parent (default: the current page). Pass `at` to place them in one frame centred on a point. Returns the ids of the new top-level layers."
3144
+ description: 'Import SVG markup as editable layers under a parent (default: the current page). Pass `at` (in the PARENT\'s coordinates) to place them in one frame centred on that point, or with its top-left there when anchor is "top-left"; add width and/or height to scale the artwork to fit that box. Returns the ids of the new top-level layers.'
3040
3145
  },
3041
3146
  // Paste, drop and File › Import: one undo step, and the ones that would not convert reported back so the
3042
3147
  // caller can place them as pictures instead (lib/editor/svg-paste.ts).
@@ -3047,14 +3152,14 @@ var nodeImportSvg = defineCommand({
3047
3152
  const parentId = args.parentId ?? ctx.pageId();
3048
3153
  const parent = nodeOrThrow(doc2, parentId);
3049
3154
  if (args.at) {
3050
- const [{ placeSvgLayers }, { internDataUrl: internDataUrl2 }] = await Promise.all([import("./svg-place-ZAG7VYF6.js"), import("./media-store-QUBUGXZ2.js")]);
3155
+ const [{ placeSvgLayers }, { internDataUrl: internDataUrl2 }] = await Promise.all([import("./svg-place-LWB4XU2O.js"), import("./media-store-QUBUGXZ2.js")]);
3051
3156
  const items = [...args.svg ? [{ svg: args.svg, name: args.name }] : [], ...args.more ?? []];
3052
3157
  if (!items.length) throw new ToolError("Pass the SVG markup.");
3053
3158
  let next2 = doc2;
3054
3159
  const added2 = [];
3055
3160
  const failed = [];
3056
3161
  items.forEach((item, i) => {
3057
- const placed = placeSvgLayers(next2, parentId, item.svg, { name: item.name || "SVG", cx: args.at.x + i * 24, cy: args.at.y + i * 24, intern: (url) => internDataUrl2(url) });
3162
+ const placed = placeSvgLayers(next2, parentId, item.svg, { name: item.name || "SVG", cx: args.at.x + i * 24, cy: args.at.y + i * 24, anchor: args.anchor, fit: { width: args.width, height: args.height }, intern: (url) => internDataUrl2(url) });
3058
3163
  if (placed) {
3059
3164
  next2 = placed.doc;
3060
3165
  added2.push(placed.id);
@@ -3839,7 +3944,7 @@ var paintSetFills = defineCommand({
3839
3944
  else if (mode === "replace" || !existing.length) fills = [paint];
3840
3945
  else if (mode === "add") fills = [...existing, paint];
3841
3946
  else fills = [paint, ...existing.slice(1)];
3842
- patches.set(id, { fills });
3947
+ patches.set(id, { fills, ...args.remove ? {} : { fillStyleId: void 0 } });
3843
3948
  }
3844
3949
  const what = args.gradient ? `a ${args.gradient.type.toLowerCase()} gradient` : args.image ? "an image" : args.color;
3845
3950
  commitUpdates(ctx, doc2, patches);
@@ -3906,7 +4011,7 @@ var paintSetStrokes = defineCommand({
3906
4011
  ...args.join !== void 0 ? { join: args.join } : {},
3907
4012
  ...args.dashPattern !== void 0 ? { dashPattern: args.dashPattern } : {}
3908
4013
  };
3909
- patches.set(id, { strokes: [merged, ...existing.slice(1)], ...order2 });
4014
+ patches.set(id, { strokes: [merged, ...existing.slice(1)], strokeStyleId: void 0, ...order2 });
3910
4015
  }
3911
4016
  commitUpdates(ctx, doc2, patches);
3912
4017
  return {
@@ -4016,7 +4121,8 @@ var paintReplaceColor = defineCommand({
4016
4121
  const rec = n;
4017
4122
  const patch = {};
4018
4123
  let hit = 0;
4019
- const paints = rec.fills;
4124
+ const fillStyle = rec.fillStyleId ? doc2.styles?.[rec.fillStyleId] : void 0;
4125
+ const paints = fillStyle?.type === "PAINT" ? fillStyle.paints : rec.fills;
4020
4126
  if (paints?.length) {
4021
4127
  let changed = false;
4022
4128
  const next = paints.map((p) => {
@@ -4043,7 +4149,10 @@ var paintReplaceColor = defineCommand({
4043
4149
  }
4044
4150
  return out;
4045
4151
  });
4046
- if (changed) patch.fills = next;
4152
+ if (changed) {
4153
+ patch.fills = next;
4154
+ if (rec.fillStyleId) patch.fillStyleId = void 0;
4155
+ }
4047
4156
  }
4048
4157
  const strokes = rec.strokes;
4049
4158
  if (strokes?.length) {
@@ -4055,7 +4164,10 @@ var paintReplaceColor = defineCommand({
4055
4164
  hit++;
4056
4165
  return { ...s, color: c };
4057
4166
  });
4058
- if (changed) patch.strokes = next;
4167
+ if (changed) {
4168
+ patch.strokes = next;
4169
+ if (rec.strokeStyleId) patch.strokeStyleId = void 0;
4170
+ }
4059
4171
  }
4060
4172
  const effects = effectsOf(n);
4061
4173
  if (effects.length) {
@@ -4086,7 +4198,7 @@ var paintReplaceColor = defineCommand({
4086
4198
  }
4087
4199
  }
4088
4200
  if (!swaps) throw new ToolError(`No ${args.from} found under ${args.rootId ?? "the selection"}. Check the color with get_node, or raise "tolerance".`);
4089
- ctx.commit({ ...doc2, nodes });
4201
+ ctx.commit(applyInvariants({ ...doc2, nodes }, touched));
4090
4202
  return { summary: `Replaced ${args.from} with ${args.to} in ${plural(touched.length, "layer")} (${swaps} paints)`, data: { ids: touched.slice(0, 50), swaps } };
4091
4203
  }
4092
4204
  });
@@ -4649,7 +4761,7 @@ var viewCopyLink = defineCommand({
4649
4761
  },
4650
4762
  run: async (args, ctx) => {
4651
4763
  const [{ syncStatus }, { fileUrl }, { withDeepLink }] = await Promise.all([
4652
- import("./sync-4AHF7NWR.js"),
4764
+ import("./sync-TFB3VWFP.js"),
4653
4765
  import("./api-7ZHHFXRP.js"),
4654
4766
  import("./deep-link-BD4WN46A.js")
4655
4767
  ]);
@@ -4974,7 +5086,7 @@ var pageGo = defineCommand({
4974
5086
  ] }
4975
5087
  },
4976
5088
  run: async ({ to }) => {
4977
- const { useEditorStore } = await import("./editor-store-TPVGGNLW.js");
5089
+ const { useEditorStore } = await import("./editor-store-WPRQJL2A.js");
4978
5090
  useEditorStore.getState().goToPrintPage(to);
4979
5091
  return { summary: typeof to === "number" ? `Page ${to + 1}` : `${to} page` };
4980
5092
  }
@@ -5008,7 +5120,7 @@ var pageSetup = defineCommand({
5008
5120
  }
5009
5121
  },
5010
5122
  run: async (args) => {
5011
- const { useEditorStore } = await import("./editor-store-TPVGGNLW.js");
5123
+ const { useEditorStore } = await import("./editor-store-WPRQJL2A.js");
5012
5124
  useEditorStore.getState().applyPageSetup(args);
5013
5125
  return { summary: `Page setup updated${args.kind ? ` (${args.kind.toLowerCase()})` : ""}` };
5014
5126
  }
@@ -5767,7 +5879,7 @@ async function docAtTime(doc2, ids, time2) {
5767
5879
  let frameId;
5768
5880
  if (time2 === void 0) {
5769
5881
  try {
5770
- const { useEditorStore } = await import("./editor-store-TPVGGNLW.js");
5882
+ const { useEditorStore } = await import("./editor-store-WPRQJL2A.js");
5771
5883
  const st = useEditorStore.getState();
5772
5884
  const target = st.transport?.target;
5773
5885
  if (st.mode !== "ANIMATE" || target?.kind !== "frame") return doc2;
@@ -5820,7 +5932,7 @@ var exportSvg = reportsMissingFonts(defineCommand({
5820
5932
  const node = nodeOrThrow(doc2, args.id);
5821
5933
  const renderer = ctx.use("canvas")();
5822
5934
  if (!renderer) throw new ToolError("SVG export needs the canvas renderer, which is not running (the editor canvas may not have initialised WebGPU). Use get_node or measure instead.");
5823
- const { exportNodeToSVG } = await import("./svg-export-J2YVV3WM.js");
5935
+ const { exportNodeToSVG } = await import("./svg-export-LMGINUQK.js");
5824
5936
  const svg = await exportNodeToSVG(renderer, node, doc2, doc2.styles);
5825
5937
  if (!svg) throw new ToolError(`"${node.name}" has nothing to export (it may be empty or zero-sized).`);
5826
5938
  const max = args.maxChars ?? 2e4;
@@ -5874,7 +5986,7 @@ var exportNodes = reportsMissingFonts(defineCommand({
5874
5986
  const nodes = ids.map((id) => nodeOrThrow(doc2, id));
5875
5987
  const renderer = ctx.use("canvas")();
5876
5988
  if (!renderer) throw new ToolError("Exporting needs the canvas renderer, which is not running (the editor canvas may not have initialised WebGPU). Use measure or export_svg instead.");
5877
- const { exportSettingFile, exportSettingsOf } = await import("./export-PGMO7YEU.js");
5989
+ const { exportSettingFile, exportSettingsOf } = await import("./export-ILWWIDBI.js");
5878
5990
  const { downloadBlob } = await import("./download-YRHNMQPH.js");
5879
5991
  const files = [];
5880
5992
  let savedByFormat = 0;
@@ -5885,7 +5997,7 @@ var exportNodes = reportsMissingFonts(defineCommand({
5885
5997
  };
5886
5998
  const asked = args.format ? [{ format: args.format, scale: args.scale ?? 1, suffix: args.suffix ?? "" }] : null;
5887
5999
  if (asked && args.format === "PDF" && args.singlePdf !== false && nodes.length > 1) {
5888
- const { exportNodesToPDF } = await import("./pdf-NHOWFQ66.js");
6000
+ const { exportNodesToPDF } = await import("./pdf-HK3GJ6QP.js");
5889
6001
  record(ids.join(","), `${doc2.name || "export"}.pdf`, await exportNodesToPDF(renderer, nodes, args.scale ?? 1, doc2, doc2.styles));
5890
6002
  } else {
5891
6003
  for (const n of nodes) {
@@ -5953,7 +6065,7 @@ var exportPdf = reportsMissingFonts(defineCommand({
5953
6065
  if (!nodes.length) throw new ToolError("There is nothing on this page to export.");
5954
6066
  const posed = await docAtTime(doc2, nodes.map((n) => n.id), args.time);
5955
6067
  nodes = nodes.map((n) => posed.nodes[n.id] ?? n);
5956
- const { exportNodesToPDF } = await import("./pdf-NHOWFQ66.js");
6068
+ const { exportNodesToPDF } = await import("./pdf-HK3GJ6QP.js");
5957
6069
  const { downloadBlob } = await import("./download-YRHNMQPH.js");
5958
6070
  const { scale, ids: _ids, time: _time, ...print } = args;
5959
6071
  void _ids;
@@ -5998,7 +6110,7 @@ var exportCopy = defineCommand({
5998
6110
  const renderer = ctx.use("canvas")();
5999
6111
  if (!renderer) throw new ToolError("Copying a layer needs the canvas renderer, which is not running.");
6000
6112
  const format = args.format ?? "PNG";
6001
- const { copyNodeAsPNG, copyNodeAsSVG } = await import("./export-PGMO7YEU.js");
6113
+ const { copyNodeAsPNG, copyNodeAsSVG } = await import("./export-ILWWIDBI.js");
6002
6114
  const ok = format === "SVG" ? await copyNodeAsSVG(renderer, node, doc2, doc2.styles) : await copyNodeAsPNG(renderer, node, doc2, doc2.styles, args.scale ?? 2);
6003
6115
  if (!ok) throw new ToolError(`"${node.name}" could not be copied as ${format} \u2014 it may be empty, or the browser refused clipboard access.`);
6004
6116
  return { summary: `Copied "${node.name}" as ${format}`, data: { id: node.id, format } };
@@ -6042,7 +6154,7 @@ var exportPages = reportsMissingFonts(defineCommand({
6042
6154
  nodes = nodes.map((n) => posed.nodes[n.id] ?? n);
6043
6155
  const format = args.format ?? "PNG";
6044
6156
  const dpi = args.dpi ?? (doc2.settings?.kind === "PRINT" ? doc2.settings.dpi ?? 300 : 96);
6045
- const { exportNodeToBlob } = await import("./export-PGMO7YEU.js");
6157
+ const { exportNodeToBlob } = await import("./export-ILWWIDBI.js");
6046
6158
  const { downloadBlob } = await import("./download-YRHNMQPH.js");
6047
6159
  const { zipFiles } = await import("./zip-export-ZYXDK4SM.js");
6048
6160
  const files = [];
@@ -6087,7 +6199,7 @@ var exportPptx = reportsMissingFonts(defineCommand({
6087
6199
  }
6088
6200
  }
6089
6201
  if (!nodes.length) throw new ToolError("There are no slides on this page to export.");
6090
- const { exportSlidesToPPTX } = await import("./pptx-LHJRZA42.js");
6202
+ const { exportSlidesToPPTX } = await import("./pptx-O7RRDHAR.js");
6091
6203
  const { downloadBlob } = await import("./download-YRHNMQPH.js");
6092
6204
  const blob = await exportSlidesToPPTX(renderer, nodes, doc2, doc2.styles);
6093
6205
  if (!blob) throw new ToolError("Those slides produced no file.");
@@ -6161,7 +6273,7 @@ async function runAnimationExport(format, args, ctx) {
6161
6273
  const filename = exportFileName(args.filename || targetName(doc2, target), format);
6162
6274
  const [{ exportAnimation }, { memoryDestination }] = await Promise.all([import("./video-TWXTQTP3.js"), import("./destination-DJEJM5KM.js")]);
6163
6275
  if (format === "lottie" || format === "dotlottie") return runLottieExport(renderer, doc2, spec, filename, ctx, memoryDestination, args.stateMachine);
6164
- const planWatermark = format !== "png" && await (await import("./export-watermark-UGGZ5TX6.js")).exportWatermark();
6276
+ const planWatermark = format !== "png" && await (await import("./export-watermark-2QVKO7OR.js")).exportWatermark();
6165
6277
  if (format !== "png") spec = { ...spec, watermark: planWatermark || args.watermark !== false };
6166
6278
  const dest = ctx.destination ? await ctx.destination(filename, FORMAT_MIME[format]) : memoryDestination(filename, FORMAT_MIME[format]);
6167
6279
  let stats;
@@ -6186,7 +6298,7 @@ async function runAnimationExport(format, args, ctx) {
6186
6298
  };
6187
6299
  }
6188
6300
  async function runLottieExport(renderer, doc2, spec, filename, ctx, memoryDestination, stateMachine) {
6189
- const { exportLottie: exportLottie2, lottieSupport } = await import("./lottie-CBQTJRYU.js");
6301
+ const { exportLottie: exportLottie2, lottieSupport } = await import("./lottie-ZWAKIFY2.js");
6190
6302
  const { FORMAT_MIME } = await import("./plan-LHP757QC.js");
6191
6303
  const support = lottieSupport(doc2, spec.target);
6192
6304
  if (!support.ok) throw new ToolError(`Lottie cannot carry this animation: ${support.blockers.join("; ")}. Export MP4, WebM or GIF instead.`);
@@ -6247,7 +6359,7 @@ var exportLottie = animationCommand((args) => args.container === "lottie" ? "dot
6247
6359
  });
6248
6360
  async function exportSite(doc2, pageId2, packaging, styling = "css", siteUrl) {
6249
6361
  const [{ completeSite, nextFilesOf, shareImageFiles, staticFilesOf, NoSiteRuntime, bytesOf }, { fileBase }, { zipFiles }, { downloadBlob }] = await Promise.all([
6250
- import("./project-M3KF66GG.js"),
6362
+ import("./project-IH23X2UG.js"),
6251
6363
  import("./web-TDSHIXQY.js"),
6252
6364
  import("./zip-export-ZYXDK4SM.js"),
6253
6365
  import("./download-YRHNMQPH.js")
@@ -6291,7 +6403,7 @@ var exportWeb = reportsMissingFonts(defineCommand({
6291
6403
  const node = id ? doc2.nodes[id] : void 0;
6292
6404
  if (!node) throw new ToolError("Select a frame or layer to export.");
6293
6405
  const { webTreeFor, extensionFor, externalAssets, fileBase, resolveWebAssets, serializeFor, flatten } = await import("./web-TDSHIXQY.js");
6294
- const { rendererAssetResolvers } = await import("./resolvers-BQ5WXLUC.js");
6406
+ const { rendererAssetResolvers } = await import("./resolvers-UTQHZ6ET.js");
6295
6407
  const { downloadBlob } = await import("./download-YRHNMQPH.js");
6296
6408
  const tree = webTreeFor(doc2, node.id, lang, { nodeCap: EXPORT_NODE_CAP, fullImageUrls: true });
6297
6409
  if (flatten(tree.root).some((n) => n.asset)) await resolveWebAssets(tree, rendererAssetResolvers(doc2));
@@ -6339,9 +6451,9 @@ var exportStorefront = defineCommand({
6339
6451
  run: async (args, ctx) => {
6340
6452
  const doc2 = ctx.doc();
6341
6453
  const [{ storefrontInputs }, { STOREFRONT_TARGETS }, { bytesOf }, { fileBase, flatten }, { zipFiles }, { downloadBlob }] = await Promise.all([
6342
- import("./storefront-prepare-EXR7OIWW.js"),
6454
+ import("./storefront-prepare-6IUMZTCQ.js"),
6343
6455
  import("./storefront-BPMM6QWK.js"),
6344
- import("./project-M3KF66GG.js"),
6456
+ import("./project-IH23X2UG.js"),
6345
6457
  import("./web-TDSHIXQY.js"),
6346
6458
  import("./zip-export-ZYXDK4SM.js"),
6347
6459
  import("./download-YRHNMQPH.js")
@@ -6402,7 +6514,7 @@ var exportBoard = defineCommand({
6402
6514
  const bounds = boardBounds(doc2, roots);
6403
6515
  const scale = boardScale(bounds, args.scale);
6404
6516
  const { documentForExport } = await import("./export-fills-MFME3KCW.js");
6405
- const { encodeImageData } = await import("./export-PGMO7YEU.js");
6517
+ const { encodeImageData } = await import("./export-ILWWIDBI.js");
6406
6518
  const clean = documentForExport(doc2);
6407
6519
  const image = await renderer.exportRegion(roots.map((n) => clean.nodes[n.id] ?? n), bounds, scale, clean, clean.styles, void 0, true);
6408
6520
  const blob = image && await encodeImageData(image, "PNG");
@@ -6736,7 +6848,7 @@ var visionRegenerateImage = defineCommand({
6736
6848
  const id = args.id ?? ctx.selection()[0];
6737
6849
  if (!id) throw new ToolError("Select a generated image to regenerate.");
6738
6850
  nodeOrThrow(ctx.doc(), id);
6739
- const { regenerateImage } = await import("./client-actions-UNYIWTLI.js");
6851
+ const { regenerateImage } = await import("./client-actions-K54NVVVW.js");
6740
6852
  regenerateImage(id, args.count);
6741
6853
  return { summary: args.count > 1 ? `Regenerating ${args.count} variants` : "Regenerating the image", data: { id, count: args.count } };
6742
6854
  }
@@ -9895,7 +10007,7 @@ var scriptRun = defineCommand({
9895
10007
  // A script is not the turn the user is watching: confirm-tier tools are refused inside it (dispatch, `nested`).
9896
10008
  actor: { ...ctx.actor, nested: true, label: "Script" },
9897
10009
  // A look_at inside the script sees the document as the script has left it so far, not as it was before.
9898
- use: ((name2) => name2 === "render" && ctx.can("render") ? (async (ids, options) => (await import("./agent-B4XH7FCC.js")).renderDocument(staged, ids, options)) : ctx.use(name2))
10010
+ use: ((name2) => name2 === "render" && ctx.can("render") ? (async (ids, options) => (await import("./agent-DVKYZ5MR.js")).renderDocument(staged, ids, options)) : ctx.use(name2))
9899
10011
  };
9900
10012
  let calls = 0;
9901
10013
  const images = [];
@@ -10715,7 +10827,7 @@ var docImportFile = defineCommand({
10715
10827
  const file = new File([body], args.name);
10716
10828
  if (file.size > MAX_BYTES) throw new ToolError(`"${args.name}" is larger than ${MAX_BYTES / 1024 / 1024} MB.`);
10717
10829
  const [{ buildImportedDocument }, { mergeImportedDocument }] = await Promise.all([
10718
- import("./plugin-import-P4PD76X3.js"),
10830
+ import("./plugin-import-N2J7NVET.js"),
10719
10831
  import("./import-merge-73U4J6IN.js")
10720
10832
  ]);
10721
10833
  const built = await buildImportedDocument(file);