proto-plugin 0.1.1 → 0.1.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 (109) hide show
  1. package/AGENTS.md +308 -29
  2. package/README.md +48 -6
  3. package/package.json +2 -1
  4. package/scripts/lib/host-config.example.sh +1 -1
  5. package/scripts/verify-prototype-preview-states.mjs +57 -0
  6. package/src/components/platform-ui/controls-panel-select.tsx +4 -3
  7. package/src/components/platform-ui/prototype-tool-dialog.tsx +117 -0
  8. package/src/components/platform-ui/sidebar.tsx +34 -16
  9. package/src/components/prototype-gallery-client.tsx +77 -37
  10. package/src/components/prototypes/design-exploration-variant-preview-shell.tsx +43 -0
  11. package/src/components/prototypes/prototype-brief-field.tsx +33 -0
  12. package/src/components/prototypes/prototype-change-log-panel.tsx +59 -55
  13. package/src/components/prototypes/prototype-comment-provider.tsx +0 -1
  14. package/src/components/prototypes/prototype-comment-storage-empty-state.tsx +41 -0
  15. package/src/components/prototypes/prototype-create-exploration-modal.tsx +41 -64
  16. package/src/components/prototypes/prototype-create-prototype-modal.tsx +102 -0
  17. package/src/components/prototypes/prototype-create-state-modal.tsx +31 -70
  18. package/src/components/prototypes/prototype-default-state-map-page.tsx +4 -4
  19. package/src/components/prototypes/prototype-design-brief-modal.tsx +10 -10
  20. package/src/components/prototypes/prototype-design-brief-panel.tsx +261 -231
  21. package/src/components/prototypes/prototype-floating-pill.module.scss +16 -9
  22. package/src/components/prototypes/prototype-mobbin-gallery.tsx +18 -2
  23. package/src/components/prototypes/prototype-review-chrome.tsx +21 -2
  24. package/src/components/prototypes/prototype-review-sidebar.tsx +7 -37
  25. package/src/components/prototypes/prototype-spec-panel-content.tsx +5 -5
  26. package/src/components/prototypes/prototype-spec-panel-empty-state.tsx +53 -0
  27. package/src/components/prototypes/prototype-state-canvas-overlay.module.scss +20 -47
  28. package/src/components/prototypes/prototype-state-canvas-overlay.tsx +4 -42
  29. package/src/components/prototypes/prototype-variant-explorer.tsx +32 -78
  30. package/src/components/prototypes/prototype-vercel-preview-modal.tsx +4 -3
  31. package/src/components/prototypes/state-map-annotation-tooltip.module.scss +7 -7
  32. package/src/components/shell/prototype-component-library-empty-state.tsx +59 -0
  33. package/src/components/shell/prototype-gallery-nav.tsx +124 -0
  34. package/src/components/shell/prototype-gallery-shell.tsx +45 -13
  35. package/src/components/shell/prototype-link-source-modal.tsx +100 -0
  36. package/src/components/shell/prototype-plugin-update-popup.tsx +74 -0
  37. package/src/components/ui/button.tsx +4 -2
  38. package/src/components/ui/dialog.tsx +44 -5
  39. package/src/components/ui/dropdown-menu.tsx +2 -2
  40. package/src/components/ui/input.tsx +1 -1
  41. package/src/components/ui/label.tsx +1 -1
  42. package/src/components/ui/option-select.tsx +3 -3
  43. package/src/components/ui/scroll-area.tsx +1 -1
  44. package/src/components/ui/separator.tsx +1 -1
  45. package/src/components/ui/slider.tsx +1 -1
  46. package/src/components/ui/switch.tsx +1 -1
  47. package/src/components/ui/tabs.tsx +1 -1
  48. package/src/components/ui/toggle-group.tsx +1 -1
  49. package/src/components/ui/tooltip.tsx +2 -2
  50. package/src/config/create-prototype-component-library-page.tsx +74 -0
  51. package/src/config/create-prototype-gallery-page.tsx +26 -23
  52. package/src/config/create-prototype-host-app.tsx +3 -15
  53. package/src/config/create-prototype-site-layout.tsx +14 -1
  54. package/src/config/create-prototype-state-map-page.tsx +44 -0
  55. package/src/config/prototype-site-layout-client.tsx +23 -6
  56. package/src/config/with-prototype.ts +54 -0
  57. package/src/index.ts +71 -11
  58. package/src/lib/copy-text-with-attachments.ts +35 -0
  59. package/src/lib/format-source-directory-name.ts +12 -0
  60. package/src/lib/platform-ui/sidebar-interactive-cursor.ts +19 -0
  61. package/src/lib/pr-split/build-pr-split-plan-prompt.ts +81 -0
  62. package/src/lib/pr-split/pr-split-highlight.ts +3 -0
  63. package/src/lib/prototype-comments/core/annotation-target.ts +12 -3
  64. package/src/lib/prototype-comments/core/comment-capture-blocked.ts +24 -0
  65. package/src/lib/prototype-comments/core/screenshot.ts +68 -31
  66. package/src/lib/prototype-comments/core/storage.ts +3 -6
  67. package/src/lib/prototype-comments/core/types.ts +2 -0
  68. package/src/lib/prototype-comments/hooks/useLayoutShift.ts +9 -2
  69. package/src/lib/prototype-comments/react/CommentCaptureToolbar.tsx +45 -10
  70. package/src/lib/prototype-comments/react/CommentProvider.tsx +19 -0
  71. package/src/lib/prototype-comments/ui/CommentModeToggleButton.tsx +34 -0
  72. package/src/lib/prototype-comments/ui/CommentsGrid.tsx +8 -16
  73. package/src/lib/prototype-comments/ui/CommentsSidebar.tsx +5 -19
  74. package/src/lib/prototype-comments/ui/capture-styles.module.scss +5 -1
  75. package/src/lib/prototype-comments/ui/comments-grid-card.module.scss +0 -7
  76. package/src/lib/prototypes/build-design-exploration-renderers.ts +44 -0
  77. package/src/lib/prototypes/changelog-description-prompt.ts +58 -0
  78. package/src/lib/prototypes/comment-storage-setup-prompt.ts +124 -0
  79. package/src/lib/prototypes/create-prototype-prompt.ts +96 -0
  80. package/src/lib/prototypes/create-prototype-registry.ts +5 -0
  81. package/src/lib/prototypes/design-exploration-types.ts +261 -10
  82. package/src/lib/prototypes/link-source-prompt.ts +93 -0
  83. package/src/lib/prototypes/populate-component-library-prompt.ts +64 -0
  84. package/src/lib/prototypes/proto-plugin-version.ts +19 -0
  85. package/src/lib/prototypes/prototype-config-types.ts +2 -0
  86. package/src/lib/prototypes/prototype-layout-classes.ts +19 -0
  87. package/src/lib/prototypes/prototype-preview-state-registry.ts +5 -2
  88. package/src/lib/prototypes/prototype-review-context.tsx +4 -4
  89. package/src/lib/prototypes/prototype-state-canvas-constants.ts +1 -1
  90. package/src/lib/prototypes/prototype-state-canvas-types.ts +0 -2
  91. package/src/lib/prototypes/prototype-storage-status.ts +31 -0
  92. package/src/lib/prototypes/sort-prototypes-by-creation-date.ts +43 -0
  93. package/src/lib/prototypes/upgrade-proto-plugin-prompt.ts +40 -0
  94. package/src/lib/prototypes/use-proto-plugin-version-check.ts +67 -0
  95. package/src/lib/prototypes/use-prototype-tool-theme.tsx +1 -1
  96. package/src/lib/prototypes/use-toolbar-hover-panel.ts +12 -1
  97. package/src/lib/prototypes/variant-set-lucide-icon.tsx +24 -0
  98. package/src/lib/tool-portal.ts +24 -0
  99. package/src/lib/use-copy-to-clipboard.ts +7 -13
  100. package/src/server/create-host-api-route.ts +14 -16
  101. package/src/server/create-prototype-api-routes.ts +0 -115
  102. package/src/server/proto-plugin-version-route.ts +145 -0
  103. package/src/server/prototype-storage-status-route.ts +29 -0
  104. package/src/server.ts +2 -8
  105. package/src/styles/globals.css +357 -69
  106. package/src/lib/prototypes/design-exploration-default-storage.ts +0 -68
  107. package/src/lib/prototypes/design-exploration-default.ts +0 -51
  108. package/src/lib/prototypes/use-design-exploration-default.ts +0 -114
  109. package/src/server/redis/prototype-design-exploration-default.ts +0 -32
@@ -30,20 +30,35 @@
30
30
  --tool-chrome-pink-highlight: rgba(255, 70, 100, 0.13);
31
31
  --tool-chrome-yellow-highlight: rgba(217, 174, 0, 0.15);
32
32
  --tool-chrome-blue-highlight: rgba(0, 151, 254, 0.13);
33
- --tool-chrome-gray-highlight: rgba(255, 255, 255, 0.05);
34
-
35
- /* Tool chrome surfaces Cursor-style grey palette */
33
+ --tool-chrome-gray-highlight: rgba(255, 255, 255, 0.08);
34
+ --tool-chrome-button-bg: rgba(255, 255, 255, 0.14);
35
+ --tool-chrome-button-text: rgba(255, 255, 255, 0.92);
36
+ --tool-chrome-button-bg-hover: rgba(255, 255, 255, 0.22);
37
+ --tool-chrome-button-text-hover: #ffffff;
38
+
39
+ /* Tool chrome surfaces — deep dark palette.
40
+ Chrome (ground) is darkest for sidebar + header; content (bg) is a lighter
41
+ elevated panel for the gallery grid and review preview frame.
42
+
43
+ Neutral scale (measured against the #151515 content surface):
44
+ heading #f0f0f0 ~13:1 crisp titles
45
+ text #d0d0d0 ~9:1 body copy
46
+ muted #a0a0a0 ~5:1 labels, descriptions (AA)
47
+ icon #9a9a9a glyphs, dimmer than body
48
+ border #333333 hairline dividers
49
+ strong #454545 inputs, structural edges */
36
50
  --tool-chrome-ground: #121212;
37
- --tool-chrome-bg: #1e1e1e;
38
- --tool-chrome-surface: #1e1e1e;
51
+ --tool-chrome-bg: #151515;
52
+ --tool-chrome-surface: #1c1c1c;
39
53
  --tool-chrome-surface-muted: #181818;
40
- --tool-chrome-text: #e0e0e0;
41
- --tool-chrome-text-heading: #e0e0e0;
42
- --tool-chrome-text-muted: #888888;
43
- --tool-chrome-icon: #888888;
44
- --tool-chrome-icon-hover: #a3a3a3;
54
+ --tool-chrome-text: #d0d0d0;
55
+ --tool-chrome-text-heading: #f0f0f0;
56
+ --tool-chrome-text-muted: #9c9c9c;
57
+ --tool-chrome-icon: #9a9a9a;
58
+ --tool-chrome-icon-hover: #d4d4d4;
45
59
  --tool-chrome-border: #333333;
46
- --tool-chrome-border-strong: #404040;
60
+ --tool-chrome-border-strong: #454545;
61
+ --tool-dialog-separator: #404040;
47
62
  --prototype-state-canvas-edge: var(--tool-chrome-icon-hover);
48
63
 
49
64
  --prototype-ground: var(--tool-chrome-ground);
@@ -51,10 +66,10 @@
51
66
  --tool-review-card-radius: 6px;
52
67
  --tool-review-card-shadow:
53
68
  0 1px 2px rgb(0 0 0 / 0.18),
54
- 0 0 0 1px #333333;
69
+ 0 0 0 1px var(--tool-chrome-border);
55
70
  --tool-review-card-shadow-hover:
56
71
  0 1px 3px rgb(0 0 0 / 0.22),
57
- 0 0 0 1px #404040;
72
+ 0 0 0 1px var(--tool-chrome-border-strong);
58
73
  --radius: 0.625rem;
59
74
 
60
75
  font-family: var(--tool-font-body);
@@ -68,14 +83,14 @@
68
83
  --bg-main: var(--tool-chrome-bg);
69
84
  --bg-top: var(--tool-chrome-surface);
70
85
  --bg-subtle: var(--tool-chrome-surface-muted);
71
- --bg-layered: #252525;
86
+ --bg-layered: #1c1c1c;
72
87
  --bg-invert: var(--tool-chrome-text-heading);
73
88
  --bg-white: var(--tool-chrome-bg);
74
89
 
75
90
  --text-primary: var(--tool-chrome-text);
76
91
  --text-secondary: var(--tool-chrome-text-muted);
77
- --text-tertiary: #666666;
78
- --text-invert: #121212;
92
+ --text-tertiary: #8a8a8a;
93
+ --text-invert: #0d0d0d;
79
94
 
80
95
  --border-faint: var(--tool-chrome-border);
81
96
  --border-solid: var(--tool-chrome-border);
@@ -95,6 +110,29 @@
95
110
  --shadow-md: 0 4px 12px 0 rgb(0 0 0 / 0.24);
96
111
  --shadow-lg: 0 8px 24px 0 rgb(0 0 0 / 0.28);
97
112
 
113
+ /*
114
+ * Host coss-ui @theme inline resolves utilities via shadcn tokens (--background,
115
+ * --foreground, …). Bridge them to tool chrome here; source previews reset
116
+ * these inside [data-prototype-screenshot] / [data-prototype-source-surface].
117
+ */
118
+ --background: var(--tool-chrome-bg);
119
+ --foreground: var(--tool-chrome-text-heading);
120
+ --card: var(--tool-chrome-surface);
121
+ --card-foreground: var(--tool-chrome-text-heading);
122
+ --popover: var(--tool-chrome-surface);
123
+ --popover-foreground: var(--tool-chrome-text-heading);
124
+ --secondary: var(--tool-chrome-surface-muted);
125
+ --secondary-foreground: var(--tool-chrome-text-heading);
126
+ --muted: var(--tool-chrome-surface-muted);
127
+ --muted-foreground: var(--tool-chrome-text-muted);
128
+ --accent: var(--tool-chrome-gray-highlight);
129
+ --accent-foreground: var(--tool-chrome-text-heading);
130
+ --destructive: var(--tool-chrome-pink);
131
+ --destructive-foreground: #ffffff;
132
+ --border: var(--tool-chrome-border);
133
+ --input: var(--tool-chrome-border-strong);
134
+ --ring: var(--tool-chrome-text-heading);
135
+
98
136
  /* Tailwind @theme inline */
99
137
  --color-background: var(--tool-chrome-bg);
100
138
  --color-foreground: var(--tool-chrome-text);
@@ -127,68 +165,129 @@
127
165
  --color-bg-main: var(--tool-chrome-bg);
128
166
  --color-bg-top: var(--tool-chrome-surface);
129
167
  --color-bg-subtle: var(--tool-chrome-surface-muted);
130
- --color-bg-layered: #252525;
168
+ --color-bg-layered: #1c1c1c;
131
169
  --color-bg-invert: var(--tool-chrome-text-heading);
132
170
  --color-bg-white: var(--tool-chrome-bg);
133
171
  --color-text-primary: var(--tool-chrome-text);
134
172
  --color-text-secondary: var(--tool-chrome-text-muted);
135
- --color-text-tertiary: #666666;
173
+ --color-text-tertiary: #8a8a8a;
136
174
  --color-text-invert: #121212;
137
175
 
138
176
  color: var(--tool-chrome-text);
139
- background-color: var(--tool-chrome-ground);
177
+ background-color: var(--tool-chrome-bg);
140
178
  }
141
179
 
142
180
  [data-prototype-root] * {
143
181
  font-family: inherit;
144
182
  }
145
183
 
146
- [data-prototype-review-sidebar] {
184
+ /*
185
+ * Sidebar chrome — a content-dense reading surface, so it pins every semantic
186
+ * "content" token to the bright end of the neutral scale (headings crisp, body
187
+ * legible, muted labels still ~5:1). Borders step up one notch from the base so
188
+ * dividers and input edges read clearly against the elevated ground, without
189
+ * turning into harsh wireframe lines.
190
+ */
191
+ [data-prototype-review-sidebar],
192
+ [data-comments-sidebar],
193
+ [data-platform-sidebar] {
147
194
  font-family: var(--tool-font-body);
148
195
  --font-sans: var(--tool-font-body);
149
196
  --font-display: var(--tool-font-display);
150
197
  --font-mono: var(--tool-font-body);
151
198
 
152
199
  --tool-chrome-icon: #b0b0b0;
153
- --tool-chrome-icon-hover: #d8d8d8;
200
+ --tool-chrome-icon-hover: #e6e6e6;
201
+ --tool-chrome-gray-highlight: rgba(255, 255, 255, 0.09);
202
+ --tool-chrome-border: #3a3a3a;
203
+ --tool-chrome-border-strong: #4d4d4d;
204
+ --tool-chrome-input-surface: rgba(255, 255, 255, 0.035);
154
205
 
155
- color: var(--tool-chrome-icon);
156
-
157
- --tool-chrome-text: var(--tool-chrome-icon-hover);
158
- --tool-chrome-text-heading: var(--tool-chrome-icon-hover);
159
- --tool-chrome-text-muted: var(--tool-chrome-icon);
206
+ color: var(--tool-chrome-text);
160
207
 
161
208
  --bg-ground: var(--tool-chrome-ground);
162
209
  --bg-main: var(--tool-chrome-bg);
163
210
  --bg-top: var(--tool-chrome-bg);
164
211
  --bg-subtle: var(--tool-chrome-surface-muted);
165
- --bg-layered: #252525;
212
+ --bg-layered: #1a1a1a;
166
213
  --border-faint: var(--tool-chrome-border);
167
214
  --border-solid: var(--tool-chrome-border);
168
215
  --border-medium: var(--tool-chrome-border-strong);
169
216
 
170
- --text-primary: var(--tool-chrome-icon-hover);
171
- --text-secondary: var(--tool-chrome-icon);
172
- --text-tertiary: #909090;
217
+ --text-primary: var(--tool-chrome-text-heading);
218
+ --text-secondary: var(--tool-chrome-text);
219
+ --text-tertiary: var(--tool-chrome-text-muted);
220
+
221
+ --foreground: var(--tool-chrome-text-heading);
222
+ --muted-foreground: var(--tool-chrome-text-muted);
223
+ --border: var(--tool-chrome-border);
224
+ --input: var(--tool-chrome-border-strong);
173
225
 
174
226
  --color-background: var(--tool-chrome-bg);
175
- --color-foreground: var(--tool-chrome-icon-hover);
227
+ --color-foreground: var(--tool-chrome-text-heading);
176
228
  --color-card: var(--tool-chrome-surface);
177
- --color-card-foreground: var(--tool-chrome-icon-hover);
229
+ --color-card-foreground: var(--tool-chrome-text-heading);
178
230
  --color-muted: var(--tool-chrome-surface-muted);
179
- --color-muted-foreground: var(--tool-chrome-icon);
231
+ --color-muted-foreground: var(--tool-chrome-text-muted);
180
232
  --color-accent: var(--tool-chrome-gray-highlight);
181
- --color-accent-foreground: var(--tool-chrome-icon-hover);
233
+ --color-accent-foreground: var(--tool-chrome-text-heading);
182
234
  --color-border: var(--tool-chrome-border);
183
- --color-ring: var(--tool-chrome-icon-hover);
235
+ --color-border-faint: var(--tool-chrome-border);
236
+ --color-border-solid: var(--tool-chrome-border);
237
+ --color-border-medium: var(--tool-chrome-border-strong);
238
+ --color-input: var(--tool-chrome-border-strong);
239
+ --color-ring: var(--tool-chrome-text-heading);
184
240
  --color-bg-ground: var(--tool-chrome-ground);
185
241
  --color-bg-main: var(--tool-chrome-bg);
186
242
  --color-bg-top: var(--tool-chrome-bg);
187
243
  --color-bg-subtle: var(--tool-chrome-surface-muted);
188
- --color-bg-layered: #252525;
189
- --color-text-primary: var(--tool-chrome-icon-hover);
190
- --color-text-secondary: var(--tool-chrome-icon);
191
- --color-text-tertiary: #909090;
244
+ --color-bg-layered: #1a1a1a;
245
+ --color-text-primary: var(--tool-chrome-text-heading);
246
+ --color-text-secondary: var(--tool-chrome-text);
247
+ --color-text-tertiary: var(--tool-chrome-text-muted);
248
+ }
249
+
250
+ /* Give brief/prompt inputs a faint filled surface so the field reads as an
251
+ affordance rather than an empty hairline rectangle. */
252
+ [data-prototype-review-sidebar] textarea:not([data-prototype-screenshot] *),
253
+ [data-comments-sidebar] textarea:not([data-prototype-screenshot] *),
254
+ [data-platform-sidebar] textarea:not([data-prototype-screenshot] *) {
255
+ background-color: var(--tool-chrome-input-surface);
256
+ }
257
+
258
+ [data-prototype-review-sidebar] :is(
259
+ button:not(:disabled),
260
+ [role="button"]:not([aria-disabled="true"]),
261
+ a[href],
262
+ summary,
263
+ label:has([role="switch"]),
264
+ label:has(input[type="checkbox"])
265
+ ),
266
+ [data-comments-sidebar] :is(
267
+ button:not(:disabled),
268
+ [role="button"]:not([aria-disabled="true"]),
269
+ a[href],
270
+ summary,
271
+ label:has([role="switch"]),
272
+ label:has(input[type="checkbox"])
273
+ ),
274
+ [data-platform-sidebar] :is(
275
+ button:not(:disabled),
276
+ [role="button"]:not([aria-disabled="true"]),
277
+ a[href],
278
+ summary,
279
+ label:has([role="switch"]),
280
+ label:has(input[type="checkbox"])
281
+ ),
282
+ #prototype-comments-sidebar-root :is(
283
+ button:not(:disabled),
284
+ [role="button"]:not([aria-disabled="true"]),
285
+ a[href],
286
+ summary,
287
+ label:has([role="switch"]),
288
+ label:has(input[type="checkbox"])
289
+ ) {
290
+ cursor: pointer;
192
291
  }
193
292
 
194
293
  [data-prototype-root] ::selection {
@@ -198,6 +297,10 @@
198
297
 
199
298
  [data-prototype-root][data-prototype-comment-theme="light"] {
200
299
  --tool-chrome-gray-highlight: rgba(0, 0, 0, 0.05);
300
+ --tool-chrome-button-bg: rgba(0, 0, 0, 0.06);
301
+ --tool-chrome-button-text: rgba(0, 0, 0, 0.72);
302
+ --tool-chrome-button-bg-hover: rgba(0, 0, 0, 0.1);
303
+ --tool-chrome-button-text-hover: rgba(0, 0, 0, 0.92);
201
304
  --tool-chrome-ground: #f5f5f5;
202
305
  --tool-chrome-bg: #ffffff;
203
306
  --tool-chrome-surface: #ffffff;
@@ -209,6 +312,7 @@
209
312
  --tool-chrome-icon-hover: rgba(0, 0, 0, 0.85);
210
313
  --tool-chrome-border: rgba(0, 0, 0, 0.1);
211
314
  --tool-chrome-border-strong: rgba(0, 0, 0, 0.16);
315
+ --tool-dialog-separator: rgba(0, 0, 0, 0.12);
212
316
  --prototype-state-canvas-edge: rgba(0, 0, 0, 0.22);
213
317
 
214
318
  --bg-ground: var(--tool-chrome-ground);
@@ -231,6 +335,24 @@
231
335
  --tool-review-card-shadow: 0 1px 2px rgb(0 0 0 / 0.04);
232
336
  --tool-review-card-shadow-hover: 0 2px 4px rgb(0 0 0 / 0.06);
233
337
 
338
+ --background: var(--tool-chrome-bg);
339
+ --foreground: var(--tool-chrome-text-heading);
340
+ --card: var(--tool-chrome-surface);
341
+ --card-foreground: var(--tool-chrome-text-heading);
342
+ --popover: var(--tool-chrome-surface);
343
+ --popover-foreground: var(--tool-chrome-text-heading);
344
+ --secondary: var(--tool-chrome-surface-muted);
345
+ --secondary-foreground: var(--tool-chrome-text-heading);
346
+ --muted: var(--tool-chrome-surface-muted);
347
+ --muted-foreground: var(--tool-chrome-text-muted);
348
+ --accent: var(--tool-chrome-gray-highlight);
349
+ --accent-foreground: var(--tool-chrome-text-heading);
350
+ --destructive: var(--tool-chrome-pink);
351
+ --destructive-foreground: #ffffff;
352
+ --border: var(--tool-chrome-border);
353
+ --input: var(--tool-chrome-border-strong);
354
+ --ring: var(--tool-chrome-text-heading);
355
+
234
356
  --color-background: var(--tool-chrome-bg);
235
357
  --color-foreground: var(--tool-chrome-text-heading);
236
358
  --color-card: var(--tool-chrome-surface);
@@ -258,7 +380,7 @@
258
380
  --color-text-tertiary: rgba(0, 0, 0, 0.45);
259
381
 
260
382
  color: var(--tool-chrome-text);
261
- background-color: var(--tool-chrome-ground);
383
+ background-color: var(--tool-chrome-bg);
262
384
  }
263
385
 
264
386
  [data-prototype-root][data-prototype-comment-theme="light"] ::selection {
@@ -368,7 +490,7 @@ html.prototype-theme-transition-disable :is(*, *::before, *::after) {
368
490
 
369
491
  @media (hover: hover) and (pointer: fine) {
370
492
  [data-prototype-root] .tool-toolbar-button:hover {
371
- background: #252525;
493
+ background: var(--tool-chrome-surface);
372
494
  color: var(--tool-chrome-icon-hover);
373
495
  }
374
496
  }
@@ -445,8 +567,28 @@ html.prototype-theme-transition-disable :is(*, *::before, *::after) {
445
567
  }
446
568
 
447
569
  [data-prototype-root] .tool-variant-card.is-active {
448
- border-color: color-mix(in srgb, var(--tool-chrome-blue) 55%, transparent);
449
- box-shadow: var(--tool-review-card-shadow-hover);
570
+ border: 2px solid var(--tool-chrome-blue);
571
+ box-shadow: none;
572
+ }
573
+
574
+ [data-prototype-root] .tool-variant-default-badge {
575
+ color: var(--tool-chrome-blue);
576
+ font-size: 0.625rem;
577
+ font-weight: 600;
578
+ letter-spacing: 0.06em;
579
+ line-height: 1;
580
+ text-transform: uppercase;
581
+ white-space: nowrap;
582
+ }
583
+
584
+ [data-prototype-root] .tool-variant-original-badge {
585
+ color: var(--tool-chrome-text-muted);
586
+ font-size: 0.625rem;
587
+ font-weight: 600;
588
+ letter-spacing: 0.06em;
589
+ line-height: 1;
590
+ text-transform: uppercase;
591
+ white-space: nowrap;
450
592
  }
451
593
 
452
594
  [data-prototype-root] .tool-variant-card [data-prototype-screenshot] {
@@ -475,26 +617,90 @@ html.prototype-theme-transition-disable :is(*, *::before, *::after) {
475
617
  border-radius: calc(var(--radius) + 4px);
476
618
  border: 1px solid var(--tool-chrome-border);
477
619
  background: var(--tool-chrome-bg);
620
+ color: var(--tool-chrome-text);
621
+ color-scheme: dark;
478
622
  box-shadow:
479
623
  var(--shadow-lg),
480
- 0 0 0 1px #333333;
624
+ 0 0 0 1px #2a2a2a;
625
+
626
+ /*
627
+ * Product preview surfaces reset shadcn tokens to light values. Re-bridge the
628
+ * full tool chrome token set so modal chrome matches the gallery/home screen.
629
+ */
630
+ --bg-main: var(--tool-chrome-bg);
631
+ --bg-top: var(--tool-chrome-surface);
632
+ --bg-subtle: var(--tool-chrome-surface-muted);
633
+ --text-primary: var(--tool-chrome-text);
634
+ --text-secondary: var(--tool-chrome-text-muted);
635
+ --border-faint: var(--tool-chrome-border);
636
+ --border-solid: var(--tool-chrome-border);
637
+ --border-medium: var(--tool-chrome-border-strong);
638
+ --primary: var(--tool-chrome-blue);
639
+ --primary-foreground: #ffffff;
640
+ --primary-dark: var(--tool-chrome-blue-deep);
641
+ --focus-ring: var(--tool-chrome-text-heading);
642
+ --active: var(--tool-chrome-text-heading);
643
+ --input-border: var(--tool-chrome-border-strong);
644
+
645
+ --background: var(--tool-chrome-bg);
646
+ --foreground: var(--tool-chrome-text-heading);
647
+ --card: var(--tool-chrome-surface);
648
+ --card-foreground: var(--tool-chrome-text-heading);
649
+ --popover: var(--tool-chrome-surface);
650
+ --popover-foreground: var(--tool-chrome-text-heading);
651
+ --secondary: var(--tool-chrome-surface-muted);
652
+ --secondary-foreground: var(--tool-chrome-text-heading);
653
+ --muted: var(--tool-chrome-surface-muted);
654
+ --muted-foreground: var(--tool-chrome-text-muted);
655
+ --accent: var(--tool-chrome-gray-highlight);
656
+ --accent-foreground: var(--tool-chrome-text-heading);
657
+ --destructive: var(--tool-chrome-pink);
658
+ --destructive-foreground: #ffffff;
659
+ --border: var(--tool-chrome-border);
660
+ --input: var(--tool-chrome-border-strong);
661
+ --ring: var(--tool-chrome-text-heading);
662
+
663
+ --color-background: var(--tool-chrome-bg);
664
+ --color-foreground: var(--tool-chrome-text-heading);
665
+ --color-card: var(--tool-chrome-surface);
666
+ --color-card-foreground: var(--tool-chrome-text-heading);
667
+ --color-popover: var(--tool-chrome-surface);
668
+ --color-popover-foreground: var(--tool-chrome-text-heading);
669
+ --color-primary: var(--tool-chrome-blue);
670
+ --color-primary-foreground: #ffffff;
671
+ --color-primary-dark: var(--tool-chrome-blue-deep);
672
+ --color-secondary: var(--tool-chrome-surface-muted);
673
+ --color-secondary-foreground: var(--tool-chrome-text-heading);
674
+ --color-muted: var(--tool-chrome-surface-muted);
675
+ --color-muted-foreground: var(--tool-chrome-text-muted);
676
+ --color-accent: var(--tool-chrome-gray-highlight);
677
+ --color-accent-foreground: var(--tool-chrome-text-heading);
678
+ --color-destructive: var(--tool-chrome-pink);
679
+ --color-destructive-foreground: #ffffff;
680
+ --color-border: var(--tool-chrome-border);
681
+ --color-border-faint: var(--tool-chrome-border);
682
+ --color-border-solid: var(--tool-chrome-border);
683
+ --color-border-medium: var(--tool-chrome-border-strong);
684
+ --color-input: var(--tool-chrome-border-strong);
685
+ --color-ring: var(--tool-chrome-text-heading);
686
+ --color-focus-ring: var(--tool-chrome-text-heading);
687
+ --color-active: var(--tool-chrome-text-heading);
688
+ --color-bg-main: var(--tool-chrome-bg);
689
+ --color-bg-top: var(--tool-chrome-surface);
690
+ --color-bg-subtle: var(--tool-chrome-surface-muted);
691
+ --color-text-primary: var(--tool-chrome-text);
692
+ --color-text-secondary: var(--tool-chrome-text-muted);
481
693
  }
482
694
 
483
695
  [data-prototype-root][data-prototype-comment-theme="light"] .tool-dialog-surface {
696
+ color-scheme: light;
484
697
  box-shadow:
485
698
  var(--shadow-lg),
486
699
  0 0 0 1px rgba(0, 0, 0, 0.08);
487
700
  }
488
701
 
489
- [data-prototype-root] .tool-dialog-accent {
490
- height: 3px;
491
- flex-shrink: 0;
492
- background: linear-gradient(
493
- 90deg,
494
- var(--tool-chrome-pink) 0%,
495
- var(--tool-chrome-yellow) 50%,
496
- var(--tool-chrome-pink) 100%
497
- );
702
+ [data-prototype-root] .tool-dialog-separator {
703
+ background: var(--tool-dialog-separator);
498
704
  }
499
705
 
500
706
  [data-prototype-root] [role="tablist"] {
@@ -504,7 +710,11 @@ html.prototype-theme-transition-disable :is(*, *::before, *::after) {
504
710
 
505
711
  [data-prototype-root] [role="tab"][data-state="active"] {
506
712
  color: var(--tool-chrome-text-heading);
507
- box-shadow: var(--shadow-xs);
713
+ background: color-mix(in srgb, var(--tool-chrome-blue) 12%, var(--tool-chrome-surface-muted));
714
+ box-shadow:
715
+ var(--shadow-xs),
716
+ inset 0 0 0 1px color-mix(in srgb, var(--tool-chrome-blue) 35%, transparent);
717
+ font-weight: 600;
508
718
  }
509
719
 
510
720
  /* Section labels — compact nav chip scale */
@@ -516,16 +726,37 @@ html.prototype-theme-transition-disable :is(*, *::before, *::after) {
516
726
  color: var(--tool-chrome-text-muted);
517
727
  }
518
728
 
519
- /* State map chrome — one surface color for header + canvas pan area. */
729
+ /* State map chrome — dedicated canvas bed + node footer tokens per theme. */
520
730
  [data-prototype-root] [data-prototype-state-canvas] {
521
- background-color: var(--tool-chrome-bg);
731
+ --prototype-state-map-canvas-bg: var(--tool-chrome-ground);
732
+ --prototype-state-map-node-surface: var(--tool-chrome-surface);
733
+ --prototype-state-map-node-preview-bg: var(--tool-chrome-surface-muted);
734
+ --prototype-state-map-node-footer-bg: var(--tool-chrome-surface-muted);
735
+ --prototype-state-map-node-footer-border: var(--tool-chrome-border-strong);
736
+ --prototype-state-map-node-footer-text: var(--tool-chrome-text-heading);
737
+
738
+ background-color: var(--prototype-state-map-canvas-bg);
522
739
  color: var(--tool-chrome-text);
523
740
  }
524
741
 
525
- /* Restore host prototype preview theme inside screenshot capture.
526
- Uses neutral gray-scale tokens only — host apps can extend in their globals.css. */
742
+ [data-prototype-root][data-prototype-comment-theme="dark"] [data-prototype-state-canvas] {
743
+ --prototype-state-map-canvas-bg: var(--tool-chrome-ground);
744
+ --prototype-state-map-node-surface: var(--tool-chrome-surface);
745
+ --prototype-state-map-node-preview-bg: var(--tool-chrome-surface-muted);
746
+ --prototype-state-map-node-footer-bg: var(--tool-chrome-surface-muted);
747
+ --prototype-state-map-node-footer-border: var(--tool-chrome-border-strong);
748
+ --prototype-state-map-node-footer-text: var(--tool-chrome-text-heading);
749
+ }
750
+
751
+ /* Restore host prototype preview theme inside screenshot capture and source
752
+ surfaces (component library). Fixed product values — must not inherit tool
753
+ theme from [data-prototype-root]. Host apps extend with --product-* tokens. */
527
754
  [data-prototype-root] [data-prototype-screenshot],
528
- [data-prototype-screenshot] {
755
+ [data-prototype-screenshot],
756
+ [data-prototype-root] [data-prototype-source-surface],
757
+ [data-prototype-source-surface] {
758
+ color-scheme: light;
759
+
529
760
  --font-sans: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji",
530
761
  "Segoe UI Symbol", "Noto Color Emoji";
531
762
  --font-display: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji",
@@ -552,38 +783,95 @@ html.prototype-theme-transition-disable :is(*, *::before, *::after) {
552
783
  --focus-ring: var(--text-primary);
553
784
  --active: var(--color-gray-900);
554
785
  --radius: 4px;
555
- --color-background: #ffffff;
556
- --color-foreground: var(--color-gray-900);
786
+
787
+ /* shadcn base tokens — host [data-prototype-screenshot] rules override with --product-* */
788
+ --background: var(--bg-main);
789
+ --foreground: var(--text-primary);
790
+ --card: var(--bg-top);
791
+ --card-foreground: var(--text-primary);
792
+ --popover: var(--bg-top);
793
+ --popover-foreground: var(--text-primary);
794
+ --secondary: var(--bg-subtle);
795
+ --secondary-foreground: var(--text-primary);
796
+ --muted: color-mix(in srgb, var(--color-gray-900) 6%, transparent);
797
+ --muted-foreground: var(--text-secondary);
798
+ --accent: color-mix(in srgb, var(--color-gray-900) 6%, transparent);
799
+ --accent-foreground: var(--text-primary);
800
+ --destructive: var(--error);
801
+ --destructive-foreground: #ffffff;
802
+ --border: var(--border-solid);
803
+ --input: var(--border-medium);
804
+ --ring: var(--border-faint);
805
+
806
+ --color-background: var(--background);
807
+ --color-foreground: var(--foreground);
808
+ --color-card: var(--card);
809
+ --color-card-foreground: var(--card-foreground);
810
+ --color-popover: var(--popover);
811
+ --color-popover-foreground: var(--popover-foreground);
557
812
  --color-primary: var(--primary);
558
- --color-primary-foreground: #ffffff;
559
- --color-muted: color-mix(in srgb, var(--color-gray-900) 6%, transparent);
560
- --color-muted-foreground: var(--color-gray-500);
561
- --color-border: var(--border-solid);
813
+ --color-primary-foreground: var(--primary-foreground);
814
+ --color-secondary: var(--secondary);
815
+ --color-secondary-foreground: var(--secondary-foreground);
816
+ --color-muted: var(--muted);
817
+ --color-muted-foreground: var(--muted-foreground);
818
+ --color-accent: var(--accent);
819
+ --color-accent-foreground: var(--accent-foreground);
820
+ --color-destructive: var(--destructive);
821
+ --color-destructive-foreground: var(--destructive-foreground);
822
+ --color-border: var(--border);
562
823
  --color-border-faint: var(--border-faint);
563
824
  --color-border-solid: var(--border-solid);
564
825
  --color-border-medium: var(--border-medium);
565
826
  --color-border-hover: var(--border-medium);
566
- --color-ring: var(--border-faint);
827
+ --color-input: var(--input);
828
+ --color-ring: var(--ring);
567
829
  --color-focus-ring: var(--focus-ring);
568
830
  --color-active: var(--active);
831
+ --color-error: var(--error);
832
+ --color-success: var(--success);
569
833
  --color-bg-bedrock: var(--bg-bedrock);
570
834
  --color-bg-main: var(--bg-main);
571
835
  --color-bg-top: var(--bg-top);
572
836
  --color-bg-subtle: var(--bg-subtle);
573
837
  --color-bg-layered: var(--bg-layered);
574
838
  --color-bg-invert: var(--bg-invert);
575
- --color-bg-white: #ffffff;
839
+ --color-bg-white: var(--bg-white);
576
840
  --color-text-primary: var(--text-primary);
577
841
  --color-text-secondary: var(--text-secondary);
578
842
  --color-text-tertiary: var(--text-tertiary);
579
843
 
580
844
  font-family: var(--font-sans);
581
845
  font-size: initial;
582
- background-color: var(--bg-bedrock);
846
+ }
847
+
848
+ [data-prototype-root] [data-prototype-screenshot],
849
+ [data-prototype-screenshot] {
850
+ color: var(--text-primary);
851
+ background-color: var(--bg-main);
852
+ }
853
+
854
+ /* Source surfaces (component-library preview cards) pin light product tokens but
855
+ do NOT force a background — each card supplies its own via bg utilities
856
+ (bg-default → white, bg-brand, etc.) so they read as light components on the
857
+ dark page. */
858
+ [data-prototype-root] [data-prototype-source-surface],
859
+ [data-prototype-source-surface] {
860
+ color: var(--text-primary);
861
+ }
862
+
863
+ [data-prototype-root] [data-prototype-screenshot] ::selection,
864
+ [data-prototype-screenshot] ::selection,
865
+ [data-prototype-root] [data-prototype-source-surface] ::selection,
866
+ [data-prototype-source-surface] ::selection {
867
+ background: #b4d5fe;
868
+ color: var(--text-primary);
583
869
  }
584
870
 
585
871
  [data-prototype-root] [data-prototype-screenshot] *,
586
- [data-prototype-screenshot] * {
872
+ [data-prototype-screenshot] *,
873
+ [data-prototype-root] [data-prototype-source-surface] *,
874
+ [data-prototype-source-surface] * {
587
875
  font-family: inherit;
588
876
  }
589
877
 
@@ -1,68 +0,0 @@
1
- import {
2
- parseDesignExplorationDefault,
3
- type DesignExplorationDefaultRecord,
4
- } from "./design-exploration-default";
5
-
6
- export class DesignExplorationDefaultStorageError extends Error {
7
- constructor(message: string) {
8
- super(message);
9
- this.name = "DesignExplorationDefaultStorageError";
10
- }
11
- }
12
-
13
- export function createDesignExplorationDefaultStorageAdapter(
14
- slug: string,
15
- storageKeyPrefix: string,
16
- ) {
17
- const params = new URLSearchParams({ key: storageKeyPrefix });
18
- const url = `/api/prototypes/${encodeURIComponent(slug)}/design-exploration-default?${params}`;
19
-
20
- return {
21
- async load(): Promise<DesignExplorationDefaultRecord | null> {
22
- const response = await fetch(url);
23
-
24
- if (response.status === 503) {
25
- throw new DesignExplorationDefaultStorageError(
26
- "Design default storage is not configured. Set Upstash Redis env vars.",
27
- );
28
- }
29
-
30
- if (!response.ok) {
31
- const body = (await response.json().catch(() => null)) as {
32
- error?: string;
33
- } | null;
34
- throw new DesignExplorationDefaultStorageError(
35
- body?.error ?? "Failed to load design default variant.",
36
- );
37
- }
38
-
39
- const parsed: unknown = await response.json();
40
- if (parsed == null) return null;
41
-
42
- return parseDesignExplorationDefault(parsed);
43
- },
44
-
45
- async save(record: DesignExplorationDefaultRecord): Promise<void> {
46
- const response = await fetch(url, {
47
- method: "PUT",
48
- headers: { "Content-Type": "application/json" },
49
- body: JSON.stringify(record),
50
- });
51
-
52
- if (response.status === 503) {
53
- throw new DesignExplorationDefaultStorageError(
54
- "Design default storage is not configured. Set Upstash Redis env vars.",
55
- );
56
- }
57
-
58
- if (!response.ok) {
59
- const body = (await response.json().catch(() => null)) as {
60
- error?: string;
61
- } | null;
62
- throw new DesignExplorationDefaultStorageError(
63
- body?.error ?? "Failed to save design default variant.",
64
- );
65
- }
66
- },
67
- };
68
- }