@12ui/design 0.2.73 → 0.2.74

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/SKILL.md +1 -1
  2. package/dist/mcp-slate-command.d.ts.map +1 -1
  3. package/dist/mcp-slate-command.js +6 -1
  4. package/dist/mcp-slate-command.js.map +1 -1
  5. package/dist/mcp-slate-tool-defs.js +3 -3
  6. package/dist/mcp-slate-tool-defs.js.map +1 -1
  7. package/dist/mcp-slate-ui-copy.d.ts +30 -19
  8. package/dist/mcp-slate-ui-copy.d.ts.map +1 -1
  9. package/dist/mcp-slate-ui-copy.js +51 -23
  10. package/dist/mcp-slate-ui-copy.js.map +1 -1
  11. package/dist/mcp-slate-ui-script-dialog.d.ts +15 -14
  12. package/dist/mcp-slate-ui-script-dialog.d.ts.map +1 -1
  13. package/dist/mcp-slate-ui-script-dialog.js +61 -72
  14. package/dist/mcp-slate-ui-script-dialog.js.map +1 -1
  15. package/dist/mcp-slate-ui-script-inline.d.ts.map +1 -1
  16. package/dist/mcp-slate-ui-script-inline.js +9 -6
  17. package/dist/mcp-slate-ui-script-inline.js.map +1 -1
  18. package/dist/mcp-slate-ui-script-inspiration.d.ts +3 -2
  19. package/dist/mcp-slate-ui-script-inspiration.d.ts.map +1 -1
  20. package/dist/mcp-slate-ui-script-inspiration.js +29 -9
  21. package/dist/mcp-slate-ui-script-inspiration.js.map +1 -1
  22. package/dist/mcp-slate-ui-script-more.d.ts +16 -14
  23. package/dist/mcp-slate-ui-script-more.d.ts.map +1 -1
  24. package/dist/mcp-slate-ui-script-more.js +120 -56
  25. package/dist/mcp-slate-ui-script-more.js.map +1 -1
  26. package/dist/mcp-slate-ui-script-remote.d.ts +2 -2
  27. package/dist/mcp-slate-ui-script-remote.js +2 -2
  28. package/dist/mcp-slate-ui-script-scribble.js +1 -1
  29. package/dist/mcp-slate-ui-script-stage.d.ts +3 -2
  30. package/dist/mcp-slate-ui-script-stage.d.ts.map +1 -1
  31. package/dist/mcp-slate-ui-script-stage.js +7 -8
  32. package/dist/mcp-slate-ui-script-stage.js.map +1 -1
  33. package/dist/mcp-slate-ui-script-state.js +3 -3
  34. package/dist/mcp-slate-ui-script.d.ts +1 -2
  35. package/dist/mcp-slate-ui-script.d.ts.map +1 -1
  36. package/dist/mcp-slate-ui-script.js +6 -4
  37. package/dist/mcp-slate-ui-script.js.map +1 -1
  38. package/dist/mcp-slate-ui-styles-dialog.d.ts +12 -9
  39. package/dist/mcp-slate-ui-styles-dialog.d.ts.map +1 -1
  40. package/dist/mcp-slate-ui-styles-dialog.js +48 -26
  41. package/dist/mcp-slate-ui-styles-dialog.js.map +1 -1
  42. package/dist/mcp-slate-ui-styles-stage.d.ts +15 -8
  43. package/dist/mcp-slate-ui-styles-stage.d.ts.map +1 -1
  44. package/dist/mcp-slate-ui-styles-stage.js +32 -18
  45. package/dist/mcp-slate-ui-styles-stage.js.map +1 -1
  46. package/dist/mcp-slate-ui-styles.d.ts +5 -0
  47. package/dist/mcp-slate-ui-styles.d.ts.map +1 -1
  48. package/dist/mcp-slate-ui-styles.js +21 -6
  49. package/dist/mcp-slate-ui-styles.js.map +1 -1
  50. package/dist/mcp-slate-ui.d.ts.map +1 -1
  51. package/dist/mcp-slate-ui.js +4 -3
  52. package/dist/mcp-slate-ui.js.map +1 -1
  53. package/dist/slate-actions.d.ts +7 -2
  54. package/dist/slate-actions.d.ts.map +1 -1
  55. package/dist/slate-actions.js +14 -8
  56. package/dist/slate-actions.js.map +1 -1
  57. package/dist/slate-handoff-options.d.ts +1 -1
  58. package/dist/slate-handoff-options.d.ts.map +1 -1
  59. package/dist/slate-handoff-options.js +8 -18
  60. package/dist/slate-handoff-options.js.map +1 -1
  61. package/dist/slate-inspiration.d.ts +1 -1
  62. package/dist/slate-inspiration.js +1 -1
  63. package/dist/slate-view-contract.d.ts +2 -3
  64. package/dist/slate-view-contract.d.ts.map +1 -1
  65. package/dist/slate-workspace-parse.d.ts.map +1 -1
  66. package/dist/slate-workspace-parse.js +6 -1
  67. package/dist/slate-workspace-parse.js.map +1 -1
  68. package/open-design.json +2 -2
  69. package/package.json +1 -1
  70. package/dist/mcp-slate-ui-script-thumbtools.d.ts +0 -23
  71. package/dist/mcp-slate-ui-script-thumbtools.d.ts.map +0 -1
  72. package/dist/mcp-slate-ui-script-thumbtools.js +0 -103
  73. package/dist/mcp-slate-ui-script-thumbtools.js.map +0 -1
  74. package/dist/mcp-slate-ui-styles-thumbtools.d.ts +0 -10
  75. package/dist/mcp-slate-ui-styles-thumbtools.d.ts.map +0 -1
  76. package/dist/mcp-slate-ui-styles-thumbtools.js +0 -25
  77. package/dist/mcp-slate-ui-styles-thumbtools.js.map +0 -1
@@ -1,8 +1,9 @@
1
1
  /**
2
- * The dialogs (Design, Edit, Branch, Convert), the scribble layer of Edit and
3
- * the Inspiration tab. A dialog is a centred box over a dimmed workspace; it
2
+ * The dialogs (Edit, Branch, Convert), the scribble layer of Edit and the
3
+ * Inspiration tab. A dialog is a centred box over a dimmed workspace; it
4
4
  * scrolls inside itself when the window is short, and fills the width on a
5
- * phone.
5
+ * phone. The reference tiles are square and fluid: at least 192 px across in
6
+ * the card and 256 px in the workspace (--ref-min), two across under 420 px.
6
7
  */
7
8
  export const SLATE_UI_DIALOG_STYLES = String.raw `
8
9
  .modal { position: fixed; inset: 0; z-index: 20; display: grid; place-items: center; padding: 16px; background: rgba(0, 0, 0, .45); overflow: auto; }
@@ -13,61 +14,82 @@ export const SLATE_UI_DIALOG_STYLES = String.raw `
13
14
  .modalbox textarea:focus-visible { outline: 2px solid var(--ring); outline-offset: 1px; }
14
15
  .radios { display: flex; flex-wrap: wrap; gap: 6px 14px; }
15
16
  .radio { display: inline-flex; align-items: center; gap: 6px; }
16
- .refline { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; font-size: 12px; color: var(--text2); }
17
- .refthumbs { display: flex; flex-wrap: wrap; gap: 4px; }
18
- .refmini { display: block; width: 36px; height: 36px; border-radius: 4px; background: var(--bg3); object-fit: cover; object-position: top; }
17
+ /* One muted line: what a control does, or what will happen. */
18
+ .help { margin: 0; font-size: 12px; color: var(--text2); overflow-wrap: anywhere; }
19
+ .field > .help { margin-top: 4px; }
20
+ .hint { flex: 1 1 200px; min-width: 0; margin: 0; font-size: 12px; color: var(--text2); }
19
21
  .alert { margin: 0; color: var(--danger); font-size: 12px; overflow-wrap: anywhere; }
20
22
  .dialogbtns, .dialogtools { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
21
23
  .dialogbtns button, .dialogtools button { padding: 8px 12px; }
24
+ .dialogtools .hint { margin-right: auto; }
22
25
  /* The image of Edit, sized to the picture itself (a height cap of 60 percent of the window), so the scribble layer over it is exactly over the picture. */
23
26
  .imgwrap { position: relative; width: min(100%, calc(60vh * var(--ar, 1.5))); aspect-ratio: var(--ar, 1.5); margin: 0 auto; min-width: 0; border-radius: var(--radius); background: var(--bg3); overflow: hidden; touch-action: none; }
24
27
  .stageimg { display: block; width: 100%; height: 100%; object-fit: fill; user-select: none; -webkit-user-drag: none; }
25
28
  .scribble { position: absolute; inset: 0; width: 100%; height: 100%; cursor: crosshair; touch-action: none; }
26
29
  .searchrow { display: flex; gap: 8px; min-width: 0; }
27
30
  .searchrow .query { flex: 1 1 0; min-width: 0; }
28
- .insp.card { --refsize: 96px; }
29
- .insp.stage { --refsize: 128px; }
31
+ .insp { container-type: inline-size; }
32
+ .insp.card { --ref-min: 192px; }
33
+ .insp.stage { --ref-min: 256px; }
30
34
  .results { display: flex; flex-direction: column; gap: 16px; margin-top: 12px; }
31
35
  .refhead { margin: 0 0 6px; font-size: 13px; font-weight: 600; }
32
- .refgrid { display: grid; grid-template-columns: repeat(auto-fill, var(--refsize)); gap: 8px; }
33
- .refbtn { width: var(--refsize); height: var(--refsize); }
34
- .refbtn .thumb { object-position: center; }
36
+ .refgrid { display: grid; grid-template-columns: repeat(auto-fill, minmax(var(--ref-min), 1fr)); gap: 8px; }
37
+ @container (max-width: 419px) { .refgrid { grid-template-columns: repeat(2, 1fr); } }
38
+ .refbtn, .skeleton { width: 100%; aspect-ratio: 1; }
39
+ .skeleton { border-radius: 6px; background: var(--bg2); }
35
40
  .refbtn[aria-pressed="true"] { box-shadow: 0 0 0 2px var(--text); }
36
41
  .check { position: absolute; top: 6px; right: 6px; display: none; place-items: center; width: 20px; height: 20px; border-radius: 50%; background: var(--inverse); color: var(--inverse-text); }
37
42
  .refbtn[aria-pressed="true"] .check { display: grid; }
38
43
  .placeholder { display: grid; place-items: center; min-height: 160px; border: 1px dashed var(--border); border-radius: var(--radius); color: var(--text2); padding: 16px; text-align: center; }
39
44
  `;
40
45
  /**
41
- * The Generate more tile and its panel. The tile is deliberately quiet: a
42
- * hairline dashed border, a muted plus, no fill, no words; it takes the size
43
- * of the thumbnails around it (56 px in the card's strip, 72 px in the
44
- * selection). The panel is one bordered block under the thumbnails. In the
45
- * card, the script shortens the large image by the panel's height while it is
46
- * open (an inline --cap), or folds it when too little would be left.
46
+ * The Generate more tile and its panel. The tile is quiet but findable: a
47
+ * dashed border in the secondary text colour, a plus and the words "Generate
48
+ * more", no fill; it takes the size of the thumbnails around it (--thumb-card
49
+ * beside the card's strip, --thumb-rail in the selection). The panel is one bordered block under the thumbnails:
50
+ * heading, one helper line, the "Based on" switch, the selected inspiration as
51
+ * small chips, a note, the count and the two buttons. In the card, the script
52
+ * shortens the large image by the panel's height while it is open (an inline
53
+ * --cap), or folds it when too little would be left.
47
54
  */
48
55
  export const SLATE_UI_MORE_STYLES = String.raw `
49
- button.moretile { display: grid; place-items: center; flex: none; padding: 0; border: 1px dashed var(--border); border-radius: 6px; background: none; color: var(--text2); opacity: .75; }
50
- button.moretile:hover:not(:disabled), button.moretile[aria-expanded="true"] { opacity: 1; border-color: var(--text2); }
56
+ button.moretile { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px; flex: none; padding: 0; border: 1px dashed var(--text2); border-radius: 6px; background: none; color: var(--text2); font-size: 12px; font-weight: 500; line-height: 1.2; }
57
+ button.moretile:hover:not(:disabled), button.moretile[aria-expanded="true"] { color: var(--text); border-color: var(--text); }
51
58
  button.moretile:disabled { opacity: .35; }
52
- .strip .moretile { width: 56px; height: 56px; }
53
- .rail .moretile { width: 72px; height: 72px; }
59
+ .stripwrap .moretile { width: var(--thumb-card); height: var(--thumb-card); }
60
+ .rail .moretile { width: var(--thumb-rail); height: var(--thumb-rail); }
54
61
  .morepanel { display: flex; flex-direction: column; gap: 10px; min-width: 0; padding: 12px; border: 1px solid var(--border); border-radius: var(--radius); }
55
62
  #more:not(:empty) { padding-top: 10px; }
56
63
  #card .hero.folded { display: none; }
57
64
  .morehead { margin: 0; font-size: 13px; font-weight: 600; }
58
- .moreheadrow { display: flex; align-items: center; gap: 8px; min-width: 0; }
59
- .morethumb { display: block; flex: none; width: 28px; height: 28px; border-radius: 4px; background: var(--bg3); object-fit: cover; object-position: top; }
65
+ .moreswitch { display: flex; align-items: center; gap: 10px; min-width: 0; cursor: pointer; }
66
+ .morethumb { display: block; flex: none; width: 40px; height: 40px; border-radius: 4px; background: var(--bg3); object-fit: contain; object-position: center; }
67
+ .moreswitchtext { flex: 1 1 0; min-width: 0; font-weight: 600; overflow-wrap: anywhere; }
68
+ .moreswitch input[type="checkbox"] { appearance: none; -webkit-appearance: none; flex: none; position: relative; width: 36px; height: 20px; margin: 0; border: 1px solid var(--border); border-radius: 999px; background: var(--bg3); cursor: pointer; }
69
+ .moreswitch input[type="checkbox"]::after { content: ""; position: absolute; top: 2px; left: 2px; width: 14px; height: 14px; border-radius: 50%; background: var(--text2); transition: transform .12s; }
70
+ .moreswitch input[type="checkbox"]:checked { background: var(--inverse); border-color: var(--inverse); }
71
+ .moreswitch input[type="checkbox"]:checked::after { transform: translateX(16px); background: var(--inverse-text); }
72
+ .moreswitch input[type="checkbox"]:focus-visible { outline: 2px solid var(--ring); outline-offset: 2px; }
73
+ .moreswitch input[type="checkbox"]:disabled { opacity: .45; cursor: default; }
74
+ .morechips { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
75
+ .morechips .lbl { margin: 0; }
76
+ .refchips { display: flex; flex-wrap: wrap; gap: 6px; min-width: 0; }
77
+ .refchip { position: relative; flex: none; width: 48px; height: 48px; }
78
+ .refchipimg { display: block; width: 100%; height: 100%; border-radius: 4px; background: var(--bg3); object-fit: contain; object-position: center; }
79
+ button.refchipx { position: absolute; top: -6px; right: -6px; display: grid; place-items: center; width: 20px; height: 20px; padding: 0; border-radius: 50%; background: var(--inverse); color: var(--inverse-text); border-color: var(--bg); }
60
80
  .morepanel textarea { width: 100%; min-width: 0; padding: 8px 10px; font: inherit; color: var(--text); background: var(--bg); border: 1px solid var(--border); border-radius: var(--radius); resize: vertical; }
61
81
  .morepanel textarea:focus-visible { outline: 2px solid var(--ring); outline-offset: 1px; }
62
82
  .morerow { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; min-width: 0; }
63
83
  .morebtns { display: flex; gap: 8px; margin-left: auto; }
64
84
  .morerow button { padding: 8px 10px; }
65
- .seg { display: inline-flex; flex: none; border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden; }
66
- .segopt { position: relative; display: block; }
85
+ .seg { display: flex; flex: 1 1 auto; min-width: 0; max-width: 260px; border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden; }
86
+ .morehost .seg { max-width: none; flex-basis: 100%; }
87
+ .segopt { position: relative; display: block; flex: 1 1 0; min-width: 28px; }
67
88
  .segopt input { position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; opacity: 0; cursor: pointer; }
68
- .segopt span { display: block; min-width: 30px; padding: 7px 8px; text-align: center; font-weight: 600; }
89
+ .segopt span { display: block; padding: 7px 4px; text-align: center; font-weight: 600; }
69
90
  .segopt input:checked + span { background: var(--inverse); color: var(--inverse-text); }
70
91
  .segopt input:focus-visible + span { outline: 2px solid var(--ring); outline-offset: -2px; }
71
92
  .morepanel .alert { margin: 0; }
93
+ @media (prefers-reduced-motion: reduce) { .moreswitch input[type="checkbox"]::after { transition: none; } }
72
94
  `;
73
95
  //# sourceMappingURL=mcp-slate-ui-styles-dialog.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"mcp-slate-ui-styles-dialog.js","sourceRoot":"","sources":["../src/mcp-slate-ui-styles-dialog.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgC/C,CAAC;AAEF;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;CAwB7C,CAAC"}
1
+ {"version":3,"file":"mcp-slate-ui-styles-dialog.js","sourceRoot":"","sources":["../src/mcp-slate-ui-styles-dialog.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAoC/C,CAAC;AAEF;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAuC7C,CAAC"}
@@ -1,12 +1,19 @@
1
1
  /**
2
- * The fullscreen workspace: the selection on the left (220 px), one large
3
- * image with its band and action row in the middle. The Generate more tile
4
- * ends the selection and its panel opens under it. Fluid at any width
5
- * (`min-width: 0` on every grid and flex parent). From 640px the selection
6
- * stays on the left, 176 px wide until 900px so the image keeps its room in
7
- * the desktop app's default 708 px tab. Below 640px the selection becomes one
8
- * horizontal row above the image, scrolling inside itself, with each option's
9
- * version chips under its thumbnail.
2
+ * The fullscreen workspace: the selection on the left, one large image with
3
+ * its band and action row in the middle. The Generate more tile ends the
4
+ * selection and its panel opens under it. Fluid at any width (`min-width: 0`
5
+ * on every grid and flex parent).
6
+ *
7
+ * The selection's thumbnails are --thumb-rail (144 px), so its column is sized
8
+ * to hold whole ones: 168 px (one per row) from 640px to 899px, where the image
9
+ * keeps its room in the desktop app's default 708 px tab; 320 px (two per row)
10
+ * from 900px; 472 px (three per row) from 1400px. Below 640px the selection
11
+ * becomes one horizontal row above the image, scrolling inside itself, with each
12
+ * option's version chips under its thumbnail.
13
+ *
14
+ * The action row is right-aligned and as wide as the picture (--ar is set by
15
+ * the script on the shared parent), so Select, last, ends at the picture's
16
+ * right edge.
10
17
  */
11
18
  export declare const SLATE_UI_STAGE_STYLES: string;
12
19
  //# sourceMappingURL=mcp-slate-ui-styles-stage.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"mcp-slate-ui-styles-stage.d.ts","sourceRoot":"","sources":["../src/mcp-slate-ui-styles-stage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,eAAO,MAAM,qBAAqB,QAyCjC,CAAC"}
1
+ {"version":3,"file":"mcp-slate-ui-styles-stage.d.ts","sourceRoot":"","sources":["../src/mcp-slate-ui-styles-stage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,qBAAqB,QAgDjC,CAAC"}
@@ -1,53 +1,67 @@
1
1
  /**
2
- * The fullscreen workspace: the selection on the left (220 px), one large
3
- * image with its band and action row in the middle. The Generate more tile
4
- * ends the selection and its panel opens under it. Fluid at any width
5
- * (`min-width: 0` on every grid and flex parent). From 640px the selection
6
- * stays on the left, 176 px wide until 900px so the image keeps its room in
7
- * the desktop app's default 708 px tab. Below 640px the selection becomes one
8
- * horizontal row above the image, scrolling inside itself, with each option's
9
- * version chips under its thumbnail.
2
+ * The fullscreen workspace: the selection on the left, one large image with
3
+ * its band and action row in the middle. The Generate more tile ends the
4
+ * selection and its panel opens under it. Fluid at any width (`min-width: 0`
5
+ * on every grid and flex parent).
6
+ *
7
+ * The selection's thumbnails are --thumb-rail (144 px), so its column is sized
8
+ * to hold whole ones: 168 px (one per row) from 640px to 899px, where the image
9
+ * keeps its room in the desktop app's default 708 px tab; 320 px (two per row)
10
+ * from 900px; 472 px (three per row) from 1400px. Below 640px the selection
11
+ * becomes one horizontal row above the image, scrolling inside itself, with each
12
+ * option's version chips under its thumbnail.
13
+ *
14
+ * The action row is right-aligned and as wide as the picture (--ar is set by
15
+ * the script on the shared parent), so Select, last, ends at the picture's
16
+ * right edge.
10
17
  */
11
18
  export const SLATE_UI_STAGE_STYLES = String.raw `
12
19
  #stage { min-width: 0; max-width: 1800px; margin: 0 auto; display: flex; flex-direction: column; gap: 12px; }
13
20
  #stage.hidden { display: none !important; }
14
21
  .stagehead { display: flex; align-items: center; gap: 12px; min-width: 0; }
15
- .stagebody { display: grid; grid-template-columns: 220px minmax(0, 1fr); gap: 16px; min-width: 0; align-items: start; }
22
+ .stagebody { display: grid; grid-template-columns: 320px minmax(0, 1fr); gap: 16px; min-width: 0; align-items: start; }
16
23
  .selection { min-width: 0; display: flex; flex-direction: column; gap: 10px; max-height: calc(100vh - 96px); }
17
24
  .rail { flex: 1 1 auto; min-height: 0; min-width: 0; display: flex; flex-direction: column; gap: 14px; overflow: auto; padding: 4px; }
18
25
  .morehost:empty { display: none; }
19
26
  .moreslot { position: sticky; bottom: 0; padding: 4px 0; background: var(--bg); }
20
27
  .round { min-width: 0; }
21
28
  .roundhead { font-size: 13px; font-weight: 600; margin: 0 0 6px; }
22
- .options { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(auto-fill, 72px); gap: 10px 8px; }
23
- .option { min-width: 0; width: 72px; }
24
- .opt { display: block; width: 72px; height: 72px; }
29
+ .options { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(auto-fill, var(--thumb-rail)); gap: 10px 8px; }
30
+ .option { min-width: 0; width: var(--thumb-rail); }
31
+ .opt { display: block; width: var(--thumb-rail); height: var(--thumb-rail); }
25
32
  .chips { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 4px; }
26
33
  .chip { padding: 1px 7px; font-size: 11px; font-weight: 500; }
27
34
  .chip.selected { background: var(--inverse); color: var(--inverse-text); border-color: var(--inverse); }
28
35
  .main { min-width: 0; display: flex; flex-direction: column; gap: 10px; }
29
- #stage .hero { --cap: max(240px, calc(100vh - 230px)); }
36
+ #stage .main { --cap: max(240px, calc(100vh - 230px)); --w: min(100%, calc(var(--cap) * var(--ar, 100))); }
37
+ #stage .band, #stage .actionrow, #stage .main > .status { width: var(--w); margin-left: auto; margin-right: auto; }
30
38
  .band { display: flex; align-items: center; gap: 12px; min-height: 28px; min-width: 0; font-size: 13px; color: var(--text2); }
31
39
  .bandtext { min-width: 0; overflow-wrap: anywhere; }
32
40
  .textbtn { flex: none; padding: 2px 6px; border: 0; background: none; font-weight: 600; text-decoration: underline; }
33
- .actionrow { display: flex; flex-wrap: wrap; gap: 8px; min-width: 0; }
41
+ .actionrow { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 8px; min-width: 0; }
34
42
  .actionrow button { flex: none; }
35
- .inspiration { min-width: 0; max-width: 960px; width: 100%; margin: 0 auto; }
43
+ #stage .main > .status { text-align: right; }
44
+ .inspiration { min-width: 0; max-width: 1800px; width: 100%; margin: 0 auto; }
45
+ @media (min-width: 1400px) {
46
+ .stagebody { grid-template-columns: 472px minmax(0, 1fr); }
47
+ }
36
48
  @media (max-width: 480px) {
37
49
  .actionrow { gap: 6px; }
38
50
  .actionrow button { flex: 1 1 auto; padding: 8px 9px; }
51
+ #stage .main > .status { text-align: left; }
39
52
  }
40
53
  @media (max-width: 899px) {
41
- .stagebody { grid-template-columns: 176px minmax(0, 1fr); gap: 12px; }
54
+ .stagebody { grid-template-columns: 168px minmax(0, 1fr); gap: 12px; }
42
55
  }
43
56
  @media (max-width: 639px) {
44
57
  .stagebody { grid-template-columns: minmax(0, 1fr); }
45
58
  .selection { max-height: none; }
46
59
  .rail { flex: none; flex-direction: row; gap: 14px; overflow-x: auto; overflow-y: hidden; padding: 4px 4px 8px; }
47
- .moreslot { position: static; flex: none; align-self: flex-start; padding: 0; background: none; }
60
+ /* The selection is a row that scrolls sideways: the tile sticks to its right edge, so it is in view however many options there are. */
61
+ .moreslot { position: sticky; bottom: auto; right: 0; flex: none; align-self: flex-end; padding: 0 0 0 8px; }
48
62
  .round { flex: none; }
49
63
  .options { display: flex; }
50
- #stage .hero { --cap: 60vh; }
64
+ #stage .main { --cap: 60vh; }
51
65
  }
52
66
  `;
53
67
  //# sourceMappingURL=mcp-slate-ui-styles-stage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"mcp-slate-ui-styles-stage.js","sourceRoot":"","sources":["../src/mcp-slate-ui-styles-stage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAyC9C,CAAC"}
1
+ {"version":3,"file":"mcp-slate-ui-styles-stage.js","sourceRoot":"","sources":["../src/mcp-slate-ui-styles-stage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgD9C,CAAC"}
@@ -8,6 +8,11 @@
8
8
  * The layout is fluid by construction: the view never asks the host for a
9
9
  * width. Every flex/grid parent sets `min-width: 0` so no child can push the
10
10
  * frame wider than its pane, and the strip of thumbnails scrolls inside itself.
11
+ *
12
+ * Thumbnail sizes are tokens, one place each: --thumb-card (the card's strip, 112 px under a 480 px card and 144 px from
13
+ * it) and --thumb-rail (the workspace's selection, 144 px). The container queries read the card's own width (`main`).
14
+ * Every thumbnail (designs, inspiration, the Based on picture and the reference chips) is `object-fit: contain`, so the
15
+ * whole design shows at its own aspect ratio, letterboxed on the neutral tile background.
11
16
  */
12
17
  export declare const SLATE_UI_STYLES: string;
13
18
  //# sourceMappingURL=mcp-slate-ui-styles.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"mcp-slate-ui-styles.d.ts","sourceRoot":"","sources":["../src/mcp-slate-ui-styles.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,eAAO,MAAM,eAAe,QAwG3B,CAAC"}
1
+ {"version":3,"file":"mcp-slate-ui-styles.d.ts","sourceRoot":"","sources":["../src/mcp-slate-ui-styles.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,eAAe,QAkH3B,CAAC"}
@@ -8,6 +8,11 @@
8
8
  * The layout is fluid by construction: the view never asks the host for a
9
9
  * width. Every flex/grid parent sets `min-width: 0` so no child can push the
10
10
  * frame wider than its pane, and the strip of thumbnails scrolls inside itself.
11
+ *
12
+ * Thumbnail sizes are tokens, one place each: --thumb-card (the card's strip, 112 px under a 480 px card and 144 px from
13
+ * it) and --thumb-rail (the workspace's selection, 144 px). The container queries read the card's own width (`main`).
14
+ * Every thumbnail (designs, inspiration, the Based on picture and the reference chips) is `object-fit: contain`, so the
15
+ * whole design shows at its own aspect ratio, letterboxed on the neutral tile background.
11
16
  */
12
17
  export const SLATE_UI_STYLES = String.raw `
13
18
  /* Host variables win; these fallbacks keep the view usable when a host passes none. System fonts only. */
@@ -37,7 +42,10 @@ export const SLATE_UI_STYLES = String.raw `
37
42
  --ok: var(--color-text-success, var(--f-ok));
38
43
  --radius: var(--border-radius-md, 8px);
39
44
  --font: var(--font-sans, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif);
45
+ --thumb-rail: 144px;
40
46
  }
47
+ #card { --thumb-card: 112px; }
48
+ @container (min-width: 480px) { #card { --thumb-card: 144px; } }
41
49
  :root[data-theme="light"] { color-scheme: light; }
42
50
  :root[data-theme="dark"] { color-scheme: dark; }
43
51
  * { box-sizing: border-box; }
@@ -71,15 +79,22 @@ export const SLATE_UI_STYLES = String.raw `
71
79
  .heronote { padding: 32px 16px; color: var(--text2); text-align: center; overflow-wrap: anywhere; }
72
80
  .hero .badge, .thumbbtn .code, .opt .code { position: absolute; left: 8px; bottom: 8px; padding: 0 8px; border-radius: 999px; background: var(--inverse); color: var(--inverse-text); font-size: 12px; font-weight: 600; line-height: 20px; }
73
81
  .hero .hair { position: absolute; left: 0; right: 0; bottom: 0; }
74
- .pickrow { display: flex; align-items: center; gap: 12px; margin-top: 10px; min-width: 0; }
75
- .pickrow > button { flex: none; }
76
- /* One row of small thumbnails; more than fit scroll sideways inside the strip, never the page, with a fade at the edge. */
82
+ /* Under 640 px the strip takes the row and Select wraps to its own line at the right; from 640 px Select sits beside the strip. */
83
+ .pickrow { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; margin-top: 10px; min-width: 0; }
84
+ .pickrow > button { flex: none; margin-left: auto; }
85
+ /* The wrap holds the scrolling strip and, pinned at its right end outside the scroll, the Generate more tile, so the
86
+ tile is in view at every width and however many options there are. */
87
+ .stripwrap { flex: 1 1 100%; display: flex; align-items: center; gap: 8px; min-width: 0; }
88
+ @container (min-width: 640px) { .stripwrap { flex: 1 1 0; } }
89
+ /* One row of thumbnails; more than fit scroll sideways inside the strip, never the page, with a fade at the edge. */
77
90
  .strip { flex: 1 1 0; display: flex; gap: 8px; min-width: 0; margin: 0; padding: 4px; overflow-x: auto; }
78
91
  .strip.fade { -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 28px), transparent); mask-image: linear-gradient(to right, #000 calc(100% - 28px), transparent); }
79
92
  .thumbbtn, .opt, .refbtn { position: relative; padding: 0; border: 0; border-radius: 6px; background: var(--bg2); overflow: hidden; }
80
- .thumbbtn { flex: none; width: 56px; height: 56px; }
81
- .thumb { display: block; width: 100%; height: 100%; background: var(--bg3); object-fit: cover; object-position: top; }
82
- .thumbbtn .code, .opt .code { left: 3px; bottom: 3px; padding: 0 5px; font-size: 10px; line-height: 14px; }
93
+ .thumbbtn { flex: none; width: var(--thumb-card); height: var(--thumb-card); }
94
+ /* A thumbnail shows the whole design at its own aspect ratio: the tile stays the token's square, the picture is
95
+ contained in it and the rest is the neutral tile background, never a crop of the edges. */
96
+ .thumb { display: block; width: 100%; height: 100%; background: var(--bg3); object-fit: contain; object-position: center; }
97
+ .thumbbtn .code, .opt .code { left: 6px; bottom: 6px; padding: 0 7px; font-size: 11px; line-height: 18px; }
83
98
  .thumbbtn.selected, .opt.selected { box-shadow: 0 0 0 2px var(--text); }
84
99
  .thumbbtn.failed, .opt.failed { opacity: .5; }
85
100
  .shimmer { background: linear-gradient(100deg, var(--bg2) 30%, var(--bg3) 50%, var(--bg2) 70%); background-size: 200% 100%; animation: shimmer 1.4s linear infinite; }
@@ -1 +1 @@
1
- {"version":3,"file":"mcp-slate-ui-styles.js","sourceRoot":"","sources":["../src/mcp-slate-ui-styles.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAwGxC,CAAC"}
1
+ {"version":3,"file":"mcp-slate-ui-styles.js","sourceRoot":"","sources":["../src/mcp-slate-ui-styles.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkHxC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"mcp-slate-ui.d.ts","sourceRoot":"","sources":["../src/mcp-slate-ui.ts"],"names":[],"mappings":"AACA,OAAO,EAAsB,KAAK,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAMlF;;;;;;;;GAQG;AACH,eAAO,MAAM,gBAAgB,GAAI,YAAY;IAAE,MAAM,EAAE,aAAa,CAAA;CAAE,KAAG,MAuCxE,CAAC;AAEF,yDAAyD;AACzD,eAAO,MAAM,aAAa,QAAwC,CAAC"}
1
+ {"version":3,"file":"mcp-slate-ui.d.ts","sourceRoot":"","sources":["../src/mcp-slate-ui.ts"],"names":[],"mappings":"AACA,OAAO,EAAsB,KAAK,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAKlF;;;;;;;;GAQG;AACH,eAAO,MAAM,gBAAgB,GAAI,YAAY;IAAE,MAAM,EAAE,aAAa,CAAA;CAAE,KAAG,MAyCxE,CAAC;AAEF,yDAAyD;AACzD,eAAO,MAAM,aAAa,QAAwC,CAAC"}
@@ -3,7 +3,6 @@ import { buildSlateUiScript } from './mcp-slate-ui-script.js';
3
3
  import { SLATE_UI_STYLES } from './mcp-slate-ui-styles.js';
4
4
  import { SLATE_UI_DIALOG_STYLES, SLATE_UI_MORE_STYLES } from './mcp-slate-ui-styles-dialog.js';
5
5
  import { SLATE_UI_STAGE_STYLES } from './mcp-slate-ui-styles-stage.js';
6
- import { SLATE_UI_THUMBTOOLS_STYLES } from './mcp-slate-ui-styles-thumbtools.js';
7
6
  /**
8
7
  * The workspace view for one target, as one self-contained HTML document: no external script,
9
8
  * stylesheet, font, or URL, so it renders under the strictest host sandbox.
@@ -19,7 +18,7 @@ export const buildSlateUiHtml = ({ target }) => `<!doctype html>
19
18
  <meta charset="utf-8">
20
19
  <meta name="viewport" content="width=device-width, initial-scale=1">${target === 'local' ? '' : `\n<meta name="slate-target" content="${target}">`}
21
20
  <title>${COPY.title}</title>
22
- <style>${SLATE_UI_STYLES}${SLATE_UI_STAGE_STYLES}${SLATE_UI_DIALOG_STYLES}${SLATE_UI_MORE_STYLES}${SLATE_UI_THUMBTOOLS_STYLES}</style>
21
+ <style>${SLATE_UI_STYLES}${SLATE_UI_STAGE_STYLES}${SLATE_UI_DIALOG_STYLES}${SLATE_UI_MORE_STYLES}</style>
23
22
  </head>
24
23
  <body>
25
24
  <div id="fatal" class="hidden" role="alert"></div>
@@ -39,7 +38,9 @@ export const buildSlateUiHtml = ({ target }) => `<!doctype html>
39
38
  <div id="pane-designs">
40
39
  <div id="hero" class="hero"></div>
41
40
  <div class="pickrow">
42
- <div class="strip" id="strip" role="group" aria-label="${COPY.optionsGroup}"></div>
41
+ <div class="stripwrap" id="stripwrap">
42
+ <div class="strip" id="strip" role="group" aria-label="${COPY.optionsGroup}"></div>
43
+ </div>
43
44
  <button id="select" type="button" class="primary" disabled>${COPY.select}</button>
44
45
  </div>
45
46
  <div id="more"></div>
@@ -1 +1 @@
1
- {"version":3,"file":"mcp-slate-ui.js","sourceRoot":"","sources":["../src/mcp-slate-ui.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,IAAI,IAAI,EAAE,MAAM,wBAAwB,CAAC;AAC/D,OAAO,EAAE,kBAAkB,EAAsB,MAAM,0BAA0B,CAAC;AAClF,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,EAAE,sBAAsB,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AAC/F,OAAO,EAAE,qBAAqB,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,EAAE,0BAA0B,EAAE,MAAM,qCAAqC,CAAC;AAEjF;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,EAAE,MAAM,EAA6B,EAAU,EAAE,CAAC;;;;sEAIb,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,wCAAwC,MAAM,IAAI;SACzI,IAAI,CAAC,KAAK;SACV,eAAe,GAAG,qBAAqB,GAAG,sBAAsB,GAAG,oBAAoB,GAAG,0BAA0B;;;;;mBAK1G,IAAI,CAAC,KAAK;sCACS,IAAI,CAAC,KAAK;;;qDAGK,IAAI,CAAC,KAAK;+FACgC,IAAI,CAAC,UAAU;oGACV,IAAI,CAAC,cAAc;;sEAEjD,IAAI,CAAC,aAAa,YAAY,IAAI,CAAC,aAAa;;;;;;;iEAOrD,IAAI,CAAC,YAAY;qEACb,IAAI,CAAC,MAAM;;;;;;;;;UAStE,kBAAkB,CAAC,MAAM,CAAC;;;CAGnC,CAAC;AAEF,yDAAyD;AACzD,MAAM,CAAC,MAAM,aAAa,GAAG,gBAAgB,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC"}
1
+ {"version":3,"file":"mcp-slate-ui.js","sourceRoot":"","sources":["../src/mcp-slate-ui.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,IAAI,IAAI,EAAE,MAAM,wBAAwB,CAAC;AAC/D,OAAO,EAAE,kBAAkB,EAAsB,MAAM,0BAA0B,CAAC;AAClF,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,EAAE,sBAAsB,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AAC/F,OAAO,EAAE,qBAAqB,EAAE,MAAM,gCAAgC,CAAC;AAEvE;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,EAAE,MAAM,EAA6B,EAAU,EAAE,CAAC;;;;sEAIb,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,wCAAwC,MAAM,IAAI;SACzI,IAAI,CAAC,KAAK;SACV,eAAe,GAAG,qBAAqB,GAAG,sBAAsB,GAAG,oBAAoB;;;;;mBAK7E,IAAI,CAAC,KAAK;sCACS,IAAI,CAAC,KAAK;;;qDAGK,IAAI,CAAC,KAAK;+FACgC,IAAI,CAAC,UAAU;oGACV,IAAI,CAAC,cAAc;;sEAEjD,IAAI,CAAC,aAAa,YAAY,IAAI,CAAC,aAAa;;;;;;;;mEAQnD,IAAI,CAAC,YAAY;;qEAEf,IAAI,CAAC,MAAM;;;;;;;;;UAStE,kBAAkB,CAAC,MAAM,CAAC;;;CAGnC,CAAC;AAEF,yDAAyD;AACzD,MAAM,CAAC,MAAM,aAAa,GAAG,gBAAgB,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC"}
@@ -4,11 +4,16 @@ import type { SlateStroke } from './slate-view-contract.js';
4
4
  * runs at `run`, so the intent digest is over exactly what the runner gets.
5
5
  */
6
6
  /** How many options a round can draw, and how many it draws when the click does not say. */
7
- export declare const ROUND_OPTION_COUNTS: readonly [2, 4, 6, 8];
7
+ export declare const ROUND_OPTION_COUNTS: readonly [1, 2, 4, 8, 12];
8
8
  export type RoundOptionCount = (typeof ROUND_OPTION_COUNTS)[number];
9
9
  export declare const DEFAULT_ROUND_OPTION_COUNT: RoundOptionCount;
10
10
  export declare const NOTE_MAX_CHARACTERS = 600;
11
11
  export declare const EDIT_PROMPT_MAX_BYTES = 6000;
12
+ /**
13
+ * The stored instruction of an edit that carries marks and no words: what the agent and the drawing model are told the
14
+ * marks mean. One constant, used only when the trimmed text is empty (the Worker keeps an equal copy, pinned by a test).
15
+ */
16
+ export declare const EDIT_MARKS_ONLY_PROMPT = "Infer the change from the marks: an X or a cross-out means remove that element, a circle or a scribble means adjust it, and any words written there are the instruction.";
12
17
  export declare const STROKE_LIMITS: {
13
18
  readonly strokes: 24;
14
19
  readonly pointsPerStroke: 400;
@@ -32,7 +37,7 @@ export type SlateWorkAction = RoundAction | EditAction;
32
37
  export declare const cleanUserText: (value: string) => string;
33
38
  /** Freehand strokes as integer permille points; anything outside the limits is refused, never trimmed. */
34
39
  export declare const normalizeStrokes: (value: unknown) => SlateStroke[];
35
- /** A missing count is the default; anything but 2, 4, 6 or 8 is refused, never rounded. */
40
+ /** A missing count is the default; anything but 1, 2, 4, 8 or 12 is refused, never rounded. */
36
41
  export declare const normalizeRoundCount: (value: unknown) => RoundOptionCount;
37
42
  export declare const normalizeAction: (input: unknown) => SlateWorkAction;
38
43
  //# sourceMappingURL=slate-actions.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"slate-actions.d.ts","sourceRoot":"","sources":["../src/slate-actions.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAE5D;;;GAGG;AAEH,4FAA4F;AAC5F,eAAO,MAAM,mBAAmB,uBAAwB,CAAC;AACzD,MAAM,MAAM,gBAAgB,GAAG,CAAC,OAAO,mBAAmB,CAAC,CAAC,MAAM,CAAC,CAAC;AACpE,eAAO,MAAM,0BAA0B,EAAE,gBAAoB,CAAC;AAC9D,eAAO,MAAM,mBAAmB,MAAM,CAAC;AACvC,eAAO,MAAM,qBAAqB,OAAQ,CAAC;AAC3C,eAAO,MAAM,aAAa;;;;CAAqE,CAAC;AAEhG,MAAM,MAAM,WAAW,GAAG;IACxB,IAAI,EAAE,OAAO,CAAC;IACd,IAAI,EAAE,KAAK,GAAG,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,KAAK,EAAE,gBAAgB,CAAC;CACzB,CAAC;AACF,MAAM,MAAM,UAAU,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,WAAW,EAAE,CAAA;CAAE,CAAC;AACrG,MAAM,MAAM,eAAe,GAAG,WAAW,GAAG,UAAU,CAAC;AAQvD,2FAA2F;AAC3F,eAAO,MAAM,aAAa,GAAI,OAAO,MAAM,KAAG,MAG7C,CAAC;AAEF,0GAA0G;AAC1G,eAAO,MAAM,gBAAgB,GAAI,OAAO,OAAO,KAAG,WAAW,EAsB5D,CAAC;AAEF,2FAA2F;AAC3F,eAAO,MAAM,mBAAmB,GAAI,OAAO,OAAO,KAAG,gBAKpD,CAAC;AAEF,eAAO,MAAM,eAAe,GAAI,OAAO,OAAO,KAAG,eA8BhD,CAAC"}
1
+ {"version":3,"file":"slate-actions.d.ts","sourceRoot":"","sources":["../src/slate-actions.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAE5D;;;GAGG;AAEH,4FAA4F;AAC5F,eAAO,MAAM,mBAAmB,2BAA4B,CAAC;AAC7D,MAAM,MAAM,gBAAgB,GAAG,CAAC,OAAO,mBAAmB,CAAC,CAAC,MAAM,CAAC,CAAC;AACpE,eAAO,MAAM,0BAA0B,EAAE,gBAAoB,CAAC;AAC9D,eAAO,MAAM,mBAAmB,MAAM,CAAC;AACvC,eAAO,MAAM,qBAAqB,OAAQ,CAAC;AAC3C;;;GAGG;AACH,eAAO,MAAM,sBAAsB,6KAA6K,CAAC;AACjN,eAAO,MAAM,aAAa;;;;CAAqE,CAAC;AAEhG,MAAM,MAAM,WAAW,GAAG;IACxB,IAAI,EAAE,OAAO,CAAC;IACd,IAAI,EAAE,KAAK,GAAG,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,KAAK,EAAE,gBAAgB,CAAC;CACzB,CAAC;AACF,MAAM,MAAM,UAAU,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,WAAW,EAAE,CAAA;CAAE,CAAC;AACrG,MAAM,MAAM,eAAe,GAAG,WAAW,GAAG,UAAU,CAAC;AAQvD,2FAA2F;AAC3F,eAAO,MAAM,aAAa,GAAI,OAAO,MAAM,KAAG,MAG7C,CAAC;AAEF,0GAA0G;AAC1G,eAAO,MAAM,gBAAgB,GAAI,OAAO,OAAO,KAAG,WAAW,EAsB5D,CAAC;AAEF,+FAA+F;AAC/F,eAAO,MAAM,mBAAmB,GAAI,OAAO,OAAO,KAAG,gBAKpD,CAAC;AAEF,eAAO,MAAM,eAAe,GAAI,OAAO,OAAO,KAAG,eA+BhD,CAAC"}
@@ -5,10 +5,15 @@ import { VERSION_ID_PATTERN } from './slate-ids.js';
5
5
  * runs at `run`, so the intent digest is over exactly what the runner gets.
6
6
  */
7
7
  /** How many options a round can draw, and how many it draws when the click does not say. */
8
- export const ROUND_OPTION_COUNTS = [2, 4, 6, 8];
8
+ export const ROUND_OPTION_COUNTS = [1, 2, 4, 8, 12];
9
9
  export const DEFAULT_ROUND_OPTION_COUNT = 4;
10
10
  export const NOTE_MAX_CHARACTERS = 600;
11
11
  export const EDIT_PROMPT_MAX_BYTES = 6_000;
12
+ /**
13
+ * The stored instruction of an edit that carries marks and no words: what the agent and the drawing model are told the
14
+ * marks mean. One constant, used only when the trimmed text is empty (the Worker keeps an equal copy, pinned by a test).
15
+ */
16
+ export const EDIT_MARKS_ONLY_PROMPT = 'Infer the change from the marks: an X or a cross-out means remove that element, a circle or a scribble means adjust it, and any words written there are the instruction.';
12
17
  export const STROKE_LIMITS = { strokes: 24, pointsPerStroke: 400, pointsTotal: 3_000 };
13
18
  const isRecord = (value) => (!!value && typeof value === 'object' && !Array.isArray(value));
14
19
  const invalid = (message) => { throw new SlateError('invalid_input', message); };
@@ -48,7 +53,7 @@ export const normalizeStrokes = (value) => {
48
53
  });
49
54
  });
50
55
  };
51
- /** A missing count is the default; anything but 2, 4, 6 or 8 is refused, never rounded. */
56
+ /** A missing count is the default; anything but 1, 2, 4, 8 or 12 is refused, never rounded. */
52
57
  export const normalizeRoundCount = (value) => {
53
58
  if (value === undefined || value === null)
54
59
  return DEFAULT_ROUND_OPTION_COUNT;
@@ -88,14 +93,15 @@ export const normalizeAction = (input) => {
88
93
  const versionId = input.versionId;
89
94
  if (typeof versionId !== 'string' || !VERSION_ID_PATTERN.test(versionId))
90
95
  return invalid('versionId is not a version id');
91
- if (typeof input.prompt !== 'string')
96
+ if (input.prompt !== undefined && input.prompt !== null && typeof input.prompt !== 'string')
92
97
  return invalid('prompt must be text');
93
- const prompt = cleanUserText(input.prompt);
94
- if (!prompt)
95
- return invalid('Say what should change.');
96
- if (Buffer.byteLength(prompt) > EDIT_PROMPT_MAX_BYTES)
98
+ const strokes = normalizeStrokes(input.strokes);
99
+ const words = cleanUserText(input.prompt ?? '');
100
+ if (!words && strokes.length === 0)
101
+ return invalid('Draw on the image or say what should change.');
102
+ if (Buffer.byteLength(words) > EDIT_PROMPT_MAX_BYTES)
97
103
  return invalid(`An edit instruction can be at most ${EDIT_PROMPT_MAX_BYTES} bytes.`);
98
- return { kind: 'edit', versionId, prompt, strokes: normalizeStrokes(input.strokes) };
104
+ return { kind: 'edit', versionId, prompt: words || EDIT_MARKS_ONLY_PROMPT, strokes };
99
105
  }
100
106
  return invalid('action.kind must be round or edit');
101
107
  };
@@ -1 +1 @@
1
- {"version":3,"file":"slate-actions.js","sourceRoot":"","sources":["../src/slate-actions.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"slate-actions.js","sourceRoot":"","sources":["../src/slate-actions.ts"],"names":[],"mappings":"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"}
@@ -3,7 +3,7 @@ import type { SlateHandoffRecord } from './slate-view-contract.js';
3
3
  * What a Branch or Convert hand-off may carry, decided in one place: the
4
4
  * record parser, the `handoff` tool and the text the agent reads all use it.
5
5
  * The combinations are the CLI's own (`12ui convert`): local formats are HTML,
6
- * React and Assets with `--clean-assets`; every other format is the 12ui
6
+ * React and Assets; every other format is the 12ui
7
7
  * service and takes `--model`, `--width` and, for responsive HTML only,
8
8
  * `--responsive-quality`.
9
9
  */
@@ -1 +1 @@
1
- {"version":3,"file":"slate-handoff-options.d.ts","sourceRoot":"","sources":["../src/slate-handoff-options.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAsB,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAEvF;;;;;;;GAOG;AAEH,eAAO,MAAM,iCAAiC,OAAQ,CAAC;AAEvD,eAAO,MAAM,qBAAqB,sCAAuC,CAAC;AAC1E,eAAO,MAAM,uBAAuB,0GAEc,CAAC;AAEnD,KAAK,aAAa,GAAG,OAAO,CAAC,kBAAkB,EAAE;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,CAAC,CAAC,SAAS,CAAC,CAAC;AAChF,KAAK,cAAc,GAAG,OAAO,CAAC,kBAAkB,EAAE;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,CAAC,CAAC,SAAS,CAAC,CAAC;AAClF,MAAM,MAAM,oBAAoB,CAAC,CAAC,IAAI;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,OAAO,EAAE,CAAC,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAShG,qGAAqG;AACrG,eAAO,MAAM,gBAAgB,GAAI,OAAO,MAAM,KAAG,MAGhD,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAAI,OAAO,OAAO,KAAG,oBAAoB,CAAC,aAAa,CAWrF,CAAC;AAIF,eAAO,MAAM,mBAAmB,GAAI,OAAO,OAAO,KAAG,oBAAoB,CAAC,cAAc,CAoCvF,CAAC;AAEF,eAAO,MAAM,mBAAmB,GAAI,MAAM,OAAO,EAAE,OAAO,OAAO,KAAG,oBAAoB,CAAC,kBAAkB,CAAC,SAAS,CAAC,CAIrH,CAAC;AAEF,6FAA6F;AAC7F,eAAO,MAAM,eAAe,GAAI,SAAS,cAAc,EAAE,WAAW,MAAM,KAAG,MAAM,EAelF,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,GAAI,SAAS,cAAc,KAAG,MAM5D,CAAC"}
1
+ {"version":3,"file":"slate-handoff-options.d.ts","sourceRoot":"","sources":["../src/slate-handoff-options.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAsB,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAEvF;;;;;;;GAOG;AAEH,eAAO,MAAM,iCAAiC,OAAQ,CAAC;AAEvD,eAAO,MAAM,qBAAqB,sCAAuC,CAAC;AAC1E,eAAO,MAAM,uBAAuB,0GAEc,CAAC;AAEnD,KAAK,aAAa,GAAG,OAAO,CAAC,kBAAkB,EAAE;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,CAAC,CAAC,SAAS,CAAC,CAAC;AAChF,KAAK,cAAc,GAAG,OAAO,CAAC,kBAAkB,EAAE;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,CAAC,CAAC,SAAS,CAAC,CAAC;AAClF,MAAM,MAAM,oBAAoB,CAAC,CAAC,IAAI;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,OAAO,EAAE,CAAC,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAShG,qGAAqG;AACrG,eAAO,MAAM,gBAAgB,GAAI,OAAO,MAAM,KAAG,MAGhD,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAAI,OAAO,OAAO,KAAG,oBAAoB,CAAC,aAAa,CAUrF,CAAC;AAIF,eAAO,MAAM,mBAAmB,GAAI,OAAO,OAAO,KAAG,oBAAoB,CAAC,cAAc,CA+BvF,CAAC;AAEF,eAAO,MAAM,mBAAmB,GAAI,MAAM,OAAO,EAAE,OAAO,OAAO,KAAG,oBAAoB,CAAC,kBAAkB,CAAC,SAAS,CAAC,CAIrH,CAAC;AAEF,6FAA6F;AAC7F,eAAO,MAAM,eAAe,GAAI,SAAS,cAAc,EAAE,WAAW,MAAM,KAAG,MAAM,EAelF,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,GAAI,SAAS,cAAc,KAAG,MAK5D,CAAC"}
@@ -4,7 +4,7 @@ import { MAX_IMAGE_OUTPUT_WIDTH } from './image-output-width.js';
4
4
  * What a Branch or Convert hand-off may carry, decided in one place: the
5
5
  * record parser, the `handoff` tool and the text the agent reads all use it.
6
6
  * The combinations are the CLI's own (`12ui convert`): local formats are HTML,
7
- * React and Assets with `--clean-assets`; every other format is the 12ui
7
+ * React and Assets; every other format is the 12ui
8
8
  * service and takes `--model`, `--width` and, for responsive HTML only,
9
9
  * `--responsive-quality`.
10
10
  */
@@ -26,17 +26,15 @@ export const parseBranchOptions = (value) => {
26
26
  const extra = Object.keys(value).filter((key) => key !== 'explanation');
27
27
  if (extra.length > 0)
28
28
  return no(`Branch takes only an explanation, not ${extra.join(', ')}.`);
29
- if (typeof value.explanation !== 'string')
29
+ if (value.explanation !== undefined && value.explanation !== null && typeof value.explanation !== 'string')
30
30
  return no('options.explanation must be text');
31
- const explanation = cleanExplanation(value.explanation);
32
- if (!explanation)
33
- return no('Say what should be built.');
31
+ const explanation = cleanExplanation(value.explanation ?? '');
34
32
  if ([...explanation].length > BRANCH_EXPLANATION_MAX_CHARACTERS) {
35
33
  return no(`An explanation can be at most ${BRANCH_EXPLANATION_MAX_CHARACTERS} characters.`);
36
34
  }
37
35
  return ok({ explanation });
38
36
  };
39
- const CONVERT_KEYS = new Set(['engine', 'output', 'cleanAssets', 'model', 'width', 'responsiveQuality']);
37
+ const CONVERT_KEYS = new Set(['engine', 'output', 'model', 'width', 'responsiveQuality']);
40
38
  export const parseConvertOptions = (value) => {
41
39
  if (!isRecord(value))
42
40
  return no('options must be an object');
@@ -52,13 +50,6 @@ export const parseConvertOptions = (value) => {
52
50
  }
53
51
  const options = { engine, output: output };
54
52
  const present = (key) => value[key] !== undefined && value[key] !== null;
55
- if (present('cleanAssets')) {
56
- if (engine !== 'local')
57
- return no('cleanAssets applies only to a local conversion.');
58
- if (value.cleanAssets !== 'crop' && value.cleanAssets !== 'enhance')
59
- return no('cleanAssets must be crop or enhance');
60
- options.cleanAssets = value.cleanAssets;
61
- }
62
53
  if (present('model')) {
63
54
  if (engine !== 'service')
64
55
  return no('model applies only to a service conversion.');
@@ -104,7 +95,7 @@ export const convertCommands = (options, imagePath) => {
104
95
  ];
105
96
  return [`12ui convert ${image} ${flags.join(' ')}`];
106
97
  }
107
- const local = `12ui convert ${image} --output html --engine codex --image-backend native --clean-assets ${options.cleanAssets ?? 'enhance'}`;
98
+ const local = `12ui convert ${image} --output html --engine codex --image-backend native`;
108
99
  if (options.output === 'html')
109
100
  return [local];
110
101
  return [local, `12ui export <the local run directory the convert printed> --output ${options.output} --out-dir <directory>`];
@@ -117,11 +108,10 @@ export const convertCommands = (options, imagePath) => {
117
108
  export const convertChoiceWords = (options) => {
118
109
  if (options.engine === 'service')
119
110
  return `${CONVERSION_OUTPUT_FORMATS[options.output]?.label ?? options.output} from the 12ui service`;
120
- const clean = `asset cleanup ${options.cleanAssets ?? 'enhance'}`;
121
111
  if (options.output === 'react')
122
- return `React (whole-page JSX and CSS) from the local Codex engine, ${clean}`;
112
+ return 'React (whole-page JSX and CSS) from the local Codex engine';
123
113
  if (options.output === 'assets')
124
- return `image assets (the cut-out files) from the local Codex engine, ${clean}`;
125
- return `HTML from the local Codex engine, ${clean}`;
114
+ return 'image assets (the cut-out files) from the local Codex engine';
115
+ return 'HTML from the local Codex engine';
126
116
  };
127
117
  //# sourceMappingURL=slate-handoff-options.js.map