@agent-native/core 0.42.0 → 0.44.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (139) hide show
  1. package/README.md +17 -56
  2. package/dist/chat-threads/store.d.ts.map +1 -1
  3. package/dist/chat-threads/store.js +71 -10
  4. package/dist/chat-threads/store.js.map +1 -1
  5. package/dist/cli/pr-visual-recap-workflow.d.ts +1 -1
  6. package/dist/cli/pr-visual-recap-workflow.d.ts.map +1 -1
  7. package/dist/cli/pr-visual-recap-workflow.js +1 -1
  8. package/dist/cli/pr-visual-recap-workflow.js.map +1 -1
  9. package/dist/cli/recap.d.ts.map +1 -1
  10. package/dist/cli/recap.js +13 -13
  11. package/dist/cli/recap.js.map +1 -1
  12. package/dist/cli/skills.d.ts +2 -6
  13. package/dist/cli/skills.d.ts.map +1 -1
  14. package/dist/cli/skills.js +21 -79
  15. package/dist/cli/skills.js.map +1 -1
  16. package/dist/client/AssistantChat.d.ts.map +1 -1
  17. package/dist/client/AssistantChat.js +76 -18
  18. package/dist/client/AssistantChat.js.map +1 -1
  19. package/dist/client/blocks/index.d.ts +9 -0
  20. package/dist/client/blocks/index.d.ts.map +1 -1
  21. package/dist/client/blocks/index.js +9 -0
  22. package/dist/client/blocks/index.js.map +1 -1
  23. package/dist/client/blocks/library/AnnotatedCodeBlock.d.ts.map +1 -1
  24. package/dist/client/blocks/library/AnnotatedCodeBlock.js +3 -3
  25. package/dist/client/blocks/library/AnnotatedCodeBlock.js.map +1 -1
  26. package/dist/client/blocks/library/ApiEndpointBlock.d.ts.map +1 -1
  27. package/dist/client/blocks/library/ApiEndpointBlock.js +1 -1
  28. package/dist/client/blocks/library/ApiEndpointBlock.js.map +1 -1
  29. package/dist/client/blocks/library/DiffBlock.d.ts.map +1 -1
  30. package/dist/client/blocks/library/DiffBlock.js +128 -19
  31. package/dist/client/blocks/library/DiffBlock.js.map +1 -1
  32. package/dist/client/blocks/library/FileTreeBlock.d.ts.map +1 -1
  33. package/dist/client/blocks/library/FileTreeBlock.js +31 -4
  34. package/dist/client/blocks/library/FileTreeBlock.js.map +1 -1
  35. package/dist/client/blocks/library/JsonExplorerBlock.js +1 -1
  36. package/dist/client/blocks/library/JsonExplorerBlock.js.map +1 -1
  37. package/dist/client/blocks/library/MermaidBlock.js +1 -1
  38. package/dist/client/blocks/library/MermaidBlock.js.map +1 -1
  39. package/dist/client/blocks/library/callout.config.d.ts +29 -0
  40. package/dist/client/blocks/library/callout.config.d.ts.map +1 -0
  41. package/dist/client/blocks/library/callout.config.js +33 -0
  42. package/dist/client/blocks/library/callout.config.js.map +1 -0
  43. package/dist/client/blocks/library/callout.d.ts +20 -0
  44. package/dist/client/blocks/library/callout.d.ts.map +1 -0
  45. package/dist/client/blocks/library/callout.js +61 -0
  46. package/dist/client/blocks/library/callout.js.map +1 -0
  47. package/dist/client/blocks/library/checklist.d.ts.map +1 -1
  48. package/dist/client/blocks/library/checklist.js +3 -3
  49. package/dist/client/blocks/library/checklist.js.map +1 -1
  50. package/dist/client/blocks/library/code-tabs.js +1 -1
  51. package/dist/client/blocks/library/code-tabs.js.map +1 -1
  52. package/dist/client/blocks/library/diagram.config.d.ts +64 -0
  53. package/dist/client/blocks/library/diagram.config.d.ts.map +1 -0
  54. package/dist/client/blocks/library/diagram.config.js +111 -0
  55. package/dist/client/blocks/library/diagram.config.js.map +1 -0
  56. package/dist/client/blocks/library/diagram.d.ts +16 -0
  57. package/dist/client/blocks/library/diagram.d.ts.map +1 -0
  58. package/dist/client/blocks/library/diagram.js +261 -0
  59. package/dist/client/blocks/library/diagram.js.map +1 -0
  60. package/dist/client/blocks/library/question-form.config.d.ts +69 -0
  61. package/dist/client/blocks/library/question-form.config.d.ts.map +1 -0
  62. package/dist/client/blocks/library/question-form.config.js +58 -0
  63. package/dist/client/blocks/library/question-form.config.js.map +1 -0
  64. package/dist/client/blocks/library/question-form.d.ts +20 -0
  65. package/dist/client/blocks/library/question-form.d.ts.map +1 -0
  66. package/dist/client/blocks/library/question-form.js +286 -0
  67. package/dist/client/blocks/library/question-form.js.map +1 -0
  68. package/dist/client/blocks/library/sanitize-html.d.ts +5 -0
  69. package/dist/client/blocks/library/sanitize-html.d.ts.map +1 -0
  70. package/dist/client/blocks/library/sanitize-html.js +240 -0
  71. package/dist/client/blocks/library/sanitize-html.js.map +1 -0
  72. package/dist/client/blocks/library/server-specs.d.ts.map +1 -1
  73. package/dist/client/blocks/library/server-specs.js +49 -0
  74. package/dist/client/blocks/library/server-specs.js.map +1 -1
  75. package/dist/client/blocks/library/specs.d.ts.map +1 -1
  76. package/dist/client/blocks/library/specs.js +9 -0
  77. package/dist/client/blocks/library/specs.js.map +1 -1
  78. package/dist/client/blocks/library/tabs.d.ts.map +1 -1
  79. package/dist/client/blocks/library/tabs.js +12 -12
  80. package/dist/client/blocks/library/tabs.js.map +1 -1
  81. package/dist/client/blocks/library/wireframe-kit.d.ts +260 -0
  82. package/dist/client/blocks/library/wireframe-kit.d.ts.map +1 -0
  83. package/dist/client/blocks/library/wireframe-kit.js +920 -0
  84. package/dist/client/blocks/library/wireframe-kit.js.map +1 -0
  85. package/dist/client/blocks/library/wireframe.config.d.ts +123 -0
  86. package/dist/client/blocks/library/wireframe.config.d.ts.map +1 -0
  87. package/dist/client/blocks/library/wireframe.config.js +311 -0
  88. package/dist/client/blocks/library/wireframe.config.js.map +1 -0
  89. package/dist/client/blocks/library/wireframe.d.ts +15 -0
  90. package/dist/client/blocks/library/wireframe.d.ts.map +1 -0
  91. package/dist/client/blocks/library/wireframe.js +206 -0
  92. package/dist/client/blocks/library/wireframe.js.map +1 -0
  93. package/dist/client/blocks/mdx.d.ts.map +1 -1
  94. package/dist/client/blocks/mdx.js +11 -0
  95. package/dist/client/blocks/mdx.js.map +1 -1
  96. package/dist/client/blocks/registry.d.ts +9 -0
  97. package/dist/client/blocks/registry.d.ts.map +1 -1
  98. package/dist/client/blocks/registry.js +12 -5
  99. package/dist/client/blocks/registry.js.map +1 -1
  100. package/dist/client/blocks/server.d.ts +1 -0
  101. package/dist/client/blocks/server.d.ts.map +1 -1
  102. package/dist/client/blocks/server.js +1 -0
  103. package/dist/client/blocks/server.js.map +1 -1
  104. package/dist/client/blocks/types.d.ts +8 -0
  105. package/dist/client/blocks/types.d.ts.map +1 -1
  106. package/dist/client/blocks/types.js.map +1 -1
  107. package/dist/client/rich-markdown-editor/DragHandle.d.ts.map +1 -1
  108. package/dist/client/rich-markdown-editor/DragHandle.js +112 -84
  109. package/dist/client/rich-markdown-editor/DragHandle.js.map +1 -1
  110. package/dist/client/rich-markdown-editor/RegistryBlockNode.d.ts.map +1 -1
  111. package/dist/client/rich-markdown-editor/RegistryBlockNode.js +1 -1
  112. package/dist/client/rich-markdown-editor/RegistryBlockNode.js.map +1 -1
  113. package/dist/client/rich-markdown-editor/SharedRichEditor.d.ts +9 -1
  114. package/dist/client/rich-markdown-editor/SharedRichEditor.d.ts.map +1 -1
  115. package/dist/client/rich-markdown-editor/SharedRichEditor.js +3 -1
  116. package/dist/client/rich-markdown-editor/SharedRichEditor.js.map +1 -1
  117. package/dist/client/rich-markdown-editor/extensions.d.ts +13 -1
  118. package/dist/client/rich-markdown-editor/extensions.d.ts.map +1 -1
  119. package/dist/client/rich-markdown-editor/extensions.js +4 -2
  120. package/dist/client/rich-markdown-editor/extensions.js.map +1 -1
  121. package/dist/client/rich-markdown-editor/useCollabReconcile.d.ts.map +1 -1
  122. package/dist/client/rich-markdown-editor/useCollabReconcile.js +11 -1
  123. package/dist/client/rich-markdown-editor/useCollabReconcile.js.map +1 -1
  124. package/dist/server/poll.d.ts.map +1 -1
  125. package/dist/server/poll.js +30 -14
  126. package/dist/server/poll.js.map +1 -1
  127. package/dist/styles/agent-native.css +1 -0
  128. package/dist/styles/blocks.css +1388 -0
  129. package/dist/templates/default/.agents/skills/storing-data/SKILL.md +2 -0
  130. package/dist/templates/workspace-core/.agents/skills/performance/SKILL.md +141 -0
  131. package/dist/templates/workspace-core/.agents/skills/storing-data/SKILL.md +2 -0
  132. package/docs/content/plan-plugin.md +8 -8
  133. package/docs/content/pr-visual-recap.md +2 -2
  134. package/docs/content/template-plan.md +94 -17
  135. package/package.json +2 -1
  136. package/src/templates/default/.agents/skills/storing-data/SKILL.md +2 -0
  137. package/src/templates/workspace-core/.agents/skills/performance/SKILL.md +141 -0
  138. package/src/templates/workspace-core/.agents/skills/storing-data/SKILL.md +2 -0
  139. package/docs/content/visual-plans.md +0 -82
@@ -0,0 +1,1388 @@
1
+ /**
2
+ * Shared styling for the core block library (`client/blocks/library/*`).
3
+ *
4
+ * The block components emit app-neutral `an-block*` / `an-callout` classes that
5
+ * resolve against shadcn/ui theme tokens (`--foreground`, `--muted-foreground`,
6
+ * `--border`, `--card`, `--ring`) which EVERY template already defines — so the
7
+ * blocks render correctly in any app (plan, content, future templates) using
8
+ * that app's own palette. Templates may still add their own block classes for a
9
+ * bespoke look; because this file is imported via `agent-native.css` BEFORE a
10
+ * template's `global.css`, any template rule of equal specificity wins (this is
11
+ * how the plan template keeps its existing `.plan-callout` treatment while
12
+ * content gets the theme-token version here).
13
+ *
14
+ * Callout tone accents are fixed semantic hues (info=blue, decision=violet,
15
+ * risk=red, warning=amber, success=green) rather than theme tokens, since their
16
+ * meaning is universal; the dark variants are brightened to read on dark
17
+ * surfaces.
18
+ */
19
+
20
+ :root {
21
+ --an-callout-info: 218 85% 57%;
22
+ --an-callout-decision: 262 83% 58%;
23
+ --an-callout-risk: 0 84% 60%;
24
+ --an-callout-warning: 25 95% 48%;
25
+ --an-callout-success: 142 71% 38%;
26
+
27
+ /* Standardized small code-body size for every monospace code surface in the
28
+ core block library (diffs, annotated-code, JSON explorer, Mermaid source,
29
+ etc.). The block components reference this via `[font-size:var(--plan-code-size)]`;
30
+ without a definition the declaration is invalid and code falls back to the
31
+ large prose size. The plan template overrides this var in its own
32
+ `global.css`; this is the cross-app default. */
33
+ --plan-code-size: 0.75rem;
34
+ }
35
+
36
+ .dark {
37
+ --an-callout-info: 218 85% 67%;
38
+ --an-callout-decision: 263 88% 74%;
39
+ --an-callout-risk: 0 84% 67%;
40
+ --an-callout-warning: 28 96% 60%;
41
+ --an-callout-success: 142 60% 52%;
42
+ }
43
+
44
+ /* Small, muted eyebrow label above a block (block title). */
45
+ .an-block-label {
46
+ margin: 0 0 1rem;
47
+ color: hsl(var(--muted-foreground));
48
+ font-size: 0.8rem;
49
+ font-weight: 600;
50
+ letter-spacing: 0.04em;
51
+ line-height: 1.3;
52
+ }
53
+
54
+ /* Callout: a self-contained tinted box with a left accent bar and a tone. */
55
+ .an-callout {
56
+ max-width: 860px;
57
+ border-left: 3px solid hsl(var(--border));
58
+ border-radius: 0 8px 8px 0;
59
+ padding-block: 0.9rem;
60
+ padding-left: 1.25rem;
61
+ }
62
+
63
+ /* The body editor/reader may carry a leading margin; the box padding owns the
64
+ top rhythm, so drop it (a label, when present, keeps its own margin-bottom). */
65
+ .an-callout > .an-rich-md-wrapper {
66
+ margin-top: 0;
67
+ }
68
+
69
+ .an-callout[data-tone="info"] {
70
+ --an-callout-accent: var(--an-callout-info);
71
+ }
72
+ .an-callout[data-tone="decision"] {
73
+ --an-callout-accent: var(--an-callout-decision);
74
+ }
75
+ .an-callout[data-tone="risk"] {
76
+ --an-callout-accent: var(--an-callout-risk);
77
+ }
78
+ .an-callout[data-tone="warning"] {
79
+ --an-callout-accent: var(--an-callout-warning);
80
+ }
81
+ .an-callout[data-tone="success"] {
82
+ --an-callout-accent: var(--an-callout-success);
83
+ }
84
+
85
+ .an-callout[data-tone] {
86
+ border-left-color: hsl(var(--an-callout-accent));
87
+ background-image: linear-gradient(
88
+ 90deg,
89
+ hsl(var(--an-callout-accent) / 0.08),
90
+ hsl(var(--an-callout-accent) / 0.02) 38%,
91
+ transparent 72%
92
+ );
93
+ }
94
+
95
+ .an-callout[data-tone] .an-block-label {
96
+ color: hsl(var(--an-callout-accent));
97
+ }
98
+
99
+ /* ════════════════════════════════════════════════════════════════════════
100
+ Migrated plan block contract.
101
+
102
+ The core block library (`client/blocks/library/*`) still emits the legacy
103
+ `.plan-*` class names and the `text/bg/border-plan-*` color utilities. Those
104
+ were originally defined ONLY in `templates/plan/app/global.css`, so the
105
+ blocks rendered UNSTYLED in any other app (e.g. content). The structural
106
+ geometry below is migrated verbatim from plan; the only change is that COLOR
107
+ values now resolve against shadcn theme tokens (`--foreground`,
108
+ `--muted-foreground`, `--border`, `--muted`) instead of plan's `--plan-*`
109
+ surface vars — so each app renders the blocks in its own palette.
110
+
111
+ PLAN STAYS PIXEL-IDENTICAL. This file loads (via `agent-native.css`) BEFORE a
112
+ template's `global.css`, so plan's later-declared copies still win:
113
+ • Color utilities live in `@layer utilities` (matching plan); within the
114
+ layer, plan's later copy wins → plan unchanged, content gets these.
115
+ • Structural classes are un-layered (matching plan); source order makes
116
+ plan's later copy win.
117
+ Plan's document-layout / canvas / wireframe / chrome rules are NOT migrated —
118
+ they stay plan-only.
119
+
120
+ Token mapping:
121
+ --plan-text → --foreground
122
+ --plan-muted → --muted-foreground
123
+ --plan-line → --border
124
+ --plan-block → --muted
125
+ --plan-code → --muted
126
+ --plan-code-text → --foreground
127
+ ════════════════════════════════════════════════════════════════════════ */
128
+
129
+ /* ── Color utilities (layered so plan's later copy wins) ─────────────────── */
130
+ @layer utilities {
131
+ .bg-plan-block {
132
+ background-color: hsl(var(--muted));
133
+ }
134
+
135
+ .bg-plan-code {
136
+ background-color: hsl(var(--muted));
137
+ }
138
+
139
+ .text-plan-text {
140
+ color: hsl(var(--foreground));
141
+ }
142
+
143
+ .text-plan-muted {
144
+ color: hsl(var(--muted-foreground));
145
+ }
146
+
147
+ .text-plan-code-text {
148
+ color: hsl(var(--foreground));
149
+ }
150
+
151
+ .border-plan-line {
152
+ border-color: hsl(var(--border));
153
+ }
154
+ }
155
+
156
+ /* ── Block label + per-column header (structural) ────────────────────────── */
157
+
158
+ /* Small, muted eyebrow label above a block (block title). */
159
+ .plan-block-label {
160
+ margin: 0 0 1rem;
161
+ color: hsl(var(--muted-foreground));
162
+ font-size: 0.8rem;
163
+ font-weight: 600;
164
+ letter-spacing: 0.04em;
165
+ line-height: 1.3;
166
+ }
167
+
168
+ /* Per-column header for `columns` comparison blocks (e.g. Before / After). */
169
+ .plan-columns-label {
170
+ margin: 0 0 0.6rem;
171
+ color: hsl(var(--foreground));
172
+ font-size: 0.95rem;
173
+ font-weight: 600;
174
+ letter-spacing: 0.01em;
175
+ line-height: 1.3;
176
+ }
177
+
178
+ /* Nested block spacing (a block inside another block). */
179
+ .plan-block .plan-block {
180
+ margin-top: 1.75rem;
181
+ padding-top: 0;
182
+ border-top: 0;
183
+ }
184
+
185
+ .plan-block .plan-block .plan-block-label {
186
+ margin-bottom: 0.75rem;
187
+ }
188
+
189
+ /* Canonical document body / lede text size. */
190
+ .plan-doc-body {
191
+ font-size: 1.0625rem;
192
+ line-height: 1.75;
193
+ }
194
+
195
+ /* ── Notion-like rich-text block prose ───────────────────────────────────── */
196
+ .plan-rich-markdown-editor {
197
+ max-width: 820px;
198
+ color: hsl(var(--foreground));
199
+ }
200
+
201
+ .plan-rich-markdown-editor .an-rich-md-prose {
202
+ color: hsl(var(--foreground));
203
+ font-size: 1.0625rem;
204
+ line-height: 1.75;
205
+ }
206
+
207
+ .plan-rich-markdown-editor .an-rich-md-prose > :first-child {
208
+ margin-top: 0;
209
+ }
210
+
211
+ .plan-rich-markdown-editor .an-rich-md-prose > :last-child {
212
+ margin-bottom: 0;
213
+ }
214
+
215
+ .plan-rich-markdown-editor .an-rich-md-prose p {
216
+ margin: 0.9rem 0;
217
+ color: hsl(var(--muted-foreground));
218
+ }
219
+
220
+ .plan-rich-markdown-editor.an-table-cell-markdown {
221
+ max-width: none;
222
+ min-height: 1.5rem;
223
+ color: inherit;
224
+ }
225
+
226
+ .plan-rich-markdown-editor.an-table-cell-markdown .an-rich-md-prose {
227
+ min-height: 1.5rem;
228
+ color: inherit;
229
+ font-size: inherit;
230
+ line-height: inherit;
231
+ }
232
+
233
+ .plan-rich-markdown-editor.an-table-cell-markdown .an-rich-md-prose p {
234
+ min-height: 1.5rem;
235
+ margin: 0;
236
+ color: inherit;
237
+ }
238
+
239
+ .plan-rich-markdown-editor.an-table-cell-markdown
240
+ .an-rich-md-prose
241
+ > :first-child {
242
+ margin-top: 0;
243
+ }
244
+
245
+ .plan-rich-markdown-editor.an-table-cell-markdown
246
+ .an-rich-md-prose
247
+ > :last-child {
248
+ margin-bottom: 0;
249
+ }
250
+
251
+ /* Annotated-code side notes: compact prose so a note matches its small card. */
252
+ .plan-annotation-note > .plan-rich-markdown-editor {
253
+ margin-top: 0;
254
+ }
255
+ .plan-annotation-note .plan-rich-markdown-editor .an-rich-md-prose {
256
+ font-size: 0.8125rem;
257
+ line-height: 1.5;
258
+ color: inherit;
259
+ }
260
+ .plan-annotation-note .plan-rich-markdown-editor .an-rich-md-prose p {
261
+ margin: 0;
262
+ color: inherit;
263
+ }
264
+ .plan-annotation-note .plan-rich-markdown-editor .an-rich-md-prose p + p {
265
+ margin-top: 0.45rem;
266
+ }
267
+
268
+ .plan-rich-markdown-editor .an-rich-md-prose h1,
269
+ .plan-rich-markdown-editor .an-rich-md-prose h2,
270
+ .plan-rich-markdown-editor .an-rich-md-prose h3,
271
+ .plan-rich-markdown-editor .an-rich-md-prose h4 {
272
+ color: hsl(var(--foreground));
273
+ font-weight: 640;
274
+ letter-spacing: 0;
275
+ line-height: 1.2;
276
+ }
277
+
278
+ .plan-rich-markdown-editor .an-rich-md-prose h1 {
279
+ margin: 2.2rem 0 0.85rem;
280
+ font-size: 1.75rem;
281
+ }
282
+
283
+ .plan-rich-markdown-editor .an-rich-md-prose h2 {
284
+ margin: 2rem 0 0.75rem;
285
+ font-size: 1.45rem;
286
+ }
287
+
288
+ .plan-rich-markdown-editor .an-rich-md-prose h3 {
289
+ margin: 1.6rem 0 0.6rem;
290
+ font-size: 1.2rem;
291
+ }
292
+
293
+ .plan-rich-markdown-editor .an-rich-md-prose h4 {
294
+ margin: 1.3rem 0 0.5rem;
295
+ font-size: 1.05rem;
296
+ }
297
+
298
+ .plan-rich-markdown-editor .an-rich-md-prose ul:not(.an-rich-md-task-list),
299
+ .plan-rich-markdown-editor .an-rich-md-prose ol,
300
+ .plan-rich-markdown-editor .an-rich-md-task-list {
301
+ margin: 0.85rem 0;
302
+ color: hsl(var(--muted-foreground));
303
+ }
304
+
305
+ .plan-rich-markdown-editor .an-rich-md-prose li {
306
+ margin: 0.35rem 0;
307
+ }
308
+
309
+ .plan-rich-markdown-editor .an-rich-md-prose li::marker {
310
+ color: hsl(var(--border));
311
+ }
312
+
313
+ .plan-rich-markdown-editor .an-rich-md-link {
314
+ color: hsl(var(--ring));
315
+ text-decoration-color: hsl(var(--ring) / 0.55);
316
+ }
317
+
318
+ .plan-rich-markdown-editor .an-rich-md-prose strong {
319
+ color: hsl(var(--foreground));
320
+ }
321
+
322
+ .plan-rich-markdown-editor .an-rich-md-prose blockquote {
323
+ margin: 1.1rem 0;
324
+ border-left-color: hsl(var(--border));
325
+ color: hsl(var(--muted-foreground));
326
+ }
327
+
328
+ .plan-rich-markdown-editor .an-rich-md-prose hr {
329
+ border-top-color: hsl(var(--border));
330
+ }
331
+
332
+ /* Inline code only — never the block code inside <pre>. */
333
+ .plan-rich-markdown-editor .an-rich-md-prose :not(pre) > code {
334
+ background: hsl(var(--muted));
335
+ color: hsl(var(--foreground));
336
+ }
337
+
338
+ /* Block code surface fallback for any stray bare <pre>. */
339
+ .plan-rich-markdown-editor .an-rich-md-prose pre {
340
+ border: 1px solid hsl(var(--border));
341
+ background: hsl(var(--muted));
342
+ color: hsl(var(--foreground));
343
+ }
344
+
345
+ .plan-rich-markdown-editor .an-rich-md-table th,
346
+ .plan-rich-markdown-editor .an-rich-md-table td {
347
+ border-color: hsl(var(--border));
348
+ }
349
+
350
+ .plan-rich-markdown-editor .an-rich-md-table th {
351
+ background: hsl(var(--muted));
352
+ color: hsl(var(--foreground));
353
+ }
354
+
355
+ .plan-rich-markdown-editor .an-rich-md-table td {
356
+ color: hsl(var(--muted-foreground));
357
+ }
358
+
359
+ .plan-rich-markdown-editor .an-rich-md-task-list li input[type="checkbox"] {
360
+ accent-color: hsl(var(--ring));
361
+ }
362
+
363
+ /* ── Code block — shared read/edit surface (structural) ──────────────────── */
364
+
365
+ /* Read-only surface (Shiki-highlighted, collapses past `--plan-code-max-lines`). */
366
+ .plan-code-surface {
367
+ border-radius: 12px;
368
+ overflow: hidden;
369
+ border: 1px solid hsl(var(--border));
370
+ background: hsl(var(--muted));
371
+ }
372
+
373
+ .plan-code-surface-bar {
374
+ display: flex;
375
+ align-items: center;
376
+ justify-content: flex-end;
377
+ padding: 0.4rem 0.85rem;
378
+ border-bottom: 1px solid hsl(var(--border));
379
+ }
380
+
381
+ .plan-code-surface-lang {
382
+ font-family: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
383
+ font-size: 0.6875rem;
384
+ font-weight: 500;
385
+ letter-spacing: 0.02em;
386
+ color: hsl(var(--muted-foreground));
387
+ }
388
+
389
+ .plan-code-surface-scroll {
390
+ position: relative;
391
+ overflow: auto;
392
+ font-size: var(--plan-code-size);
393
+ line-height: 1.6;
394
+ }
395
+
396
+ /* Collapsed: clamp to N lines (+ the pre's top padding) and hide the rest. */
397
+ .plan-code-surface[data-collapsed="true"] .plan-code-surface-scroll {
398
+ max-height: calc(var(--plan-code-max-lines, 30) * 1lh + 0.85rem);
399
+ overflow: hidden;
400
+ }
401
+
402
+ .plan-code-surface-fade {
403
+ position: absolute;
404
+ inset: auto 0 0 0;
405
+ height: 3.5rem;
406
+ pointer-events: none;
407
+ background: linear-gradient(to bottom, transparent, hsl(var(--muted)) 92%);
408
+ }
409
+
410
+ .plan-code-surface-toggle {
411
+ display: block;
412
+ width: 100%;
413
+ padding: 0.45rem 0.85rem;
414
+ border-top: 1px solid hsl(var(--border));
415
+ background: transparent;
416
+ color: hsl(var(--muted-foreground));
417
+ font-size: 0.75rem;
418
+ font-weight: 500;
419
+ text-align: left;
420
+ cursor: pointer;
421
+ transition:
422
+ color 0.15s,
423
+ background-color 0.15s;
424
+ }
425
+
426
+ .plan-code-surface-toggle:hover {
427
+ color: hsl(var(--foreground));
428
+ background: color-mix(in srgb, hsl(var(--muted)) 60%, transparent);
429
+ }
430
+
431
+ .plan-code-surface .plan-shiki,
432
+ .plan-code-surface pre {
433
+ margin: 0;
434
+ padding: 0.85rem 1.1rem;
435
+ background: var(--shiki-light-bg, hsl(var(--muted))) !important;
436
+ color: var(--shiki-light, hsl(var(--foreground)));
437
+ font-family: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
438
+ font-size: var(--plan-code-size);
439
+ line-height: 1.6;
440
+ }
441
+
442
+ .plan-code-surface pre code {
443
+ color: inherit;
444
+ background: none;
445
+ padding: 0;
446
+ }
447
+
448
+ .plan-code-surface .plan-shiki pre,
449
+ .plan-code-surface .plan-shiki code {
450
+ background: var(--shiki-light-bg, transparent) !important;
451
+ }
452
+
453
+ .plan-code-surface .plan-shiki pre span {
454
+ color: var(--shiki-light);
455
+ }
456
+
457
+ .dark .plan-code-surface .plan-shiki,
458
+ .dark .plan-code-surface .plan-shiki pre {
459
+ background: var(--shiki-dark-bg, hsl(var(--muted))) !important;
460
+ color: var(--shiki-dark, hsl(var(--foreground)));
461
+ }
462
+
463
+ .dark .plan-code-surface .plan-shiki pre span {
464
+ color: var(--shiki-dark);
465
+ }
466
+
467
+ /* `code` primitive block: read wraps the surface with a borderless filename
468
+ header + hover chrome; edit is a single-bordered auto-growing surface. */
469
+ .plan-code {
470
+ position: relative;
471
+ }
472
+
473
+ .plan-code-head {
474
+ display: flex;
475
+ align-items: center;
476
+ justify-content: space-between;
477
+ gap: 0.75rem;
478
+ padding: 0 0.15rem 0.4rem;
479
+ }
480
+
481
+ .plan-code-filename {
482
+ display: inline-flex;
483
+ align-items: center;
484
+ gap: 0.4rem;
485
+ min-width: 0;
486
+ font-family: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
487
+ font-size: 0.78rem;
488
+ font-weight: 600;
489
+ color: hsl(var(--foreground));
490
+ }
491
+
492
+ .plan-code-muted {
493
+ color: hsl(var(--muted-foreground));
494
+ font-weight: 500;
495
+ }
496
+
497
+ .plan-code-chrome {
498
+ display: inline-flex;
499
+ align-items: center;
500
+ gap: 0.35rem;
501
+ opacity: 0;
502
+ transition: opacity 0.12s ease;
503
+ }
504
+
505
+ .plan-code:hover .plan-code-chrome,
506
+ .plan-code:focus-within .plan-code-chrome {
507
+ opacity: 1;
508
+ }
509
+
510
+ .plan-code-chrome-float {
511
+ position: absolute;
512
+ top: 0.5rem;
513
+ right: 0.5rem;
514
+ z-index: 2;
515
+ }
516
+
517
+ .plan-code-chip {
518
+ display: inline-flex;
519
+ align-items: center;
520
+ justify-content: center;
521
+ height: 1.75rem;
522
+ width: 1.75rem;
523
+ border-radius: 7px;
524
+ border: 1px solid hsl(var(--border));
525
+ background: hsl(var(--muted));
526
+ color: hsl(var(--muted-foreground));
527
+ cursor: pointer;
528
+ transition:
529
+ color 0.12s,
530
+ background-color 0.12s;
531
+ }
532
+
533
+ .plan-code-chip:hover {
534
+ color: hsl(var(--foreground));
535
+ background: hsl(var(--muted));
536
+ }
537
+
538
+ .plan-code-lang-select {
539
+ height: 1.75rem;
540
+ padding: 0 0.4rem;
541
+ border-radius: 7px;
542
+ border: 1px solid hsl(var(--border));
543
+ background: hsl(var(--muted));
544
+ color: hsl(var(--muted-foreground));
545
+ font-size: 0.72rem;
546
+ font-weight: 500;
547
+ cursor: pointer;
548
+ }
549
+
550
+ .plan-code-lang-select:hover {
551
+ color: hsl(var(--foreground));
552
+ }
553
+
554
+ /* Editable surface: ONE border, auto-grows to content (no drag-to-resize). */
555
+ .plan-code-editing {
556
+ overflow: hidden;
557
+ border: 1px solid hsl(var(--border));
558
+ border-radius: 12px;
559
+ /* Sit on the page background like the diff block — no distinct surface fill. */
560
+ background: transparent;
561
+ }
562
+
563
+ .plan-code-editing .plan-code-head {
564
+ padding: 0.4rem 0.5rem 0.4rem 0.85rem;
565
+ border-bottom: 1px solid hsl(var(--border));
566
+ }
567
+
568
+ .plan-code-editing:hover .plan-code-chrome,
569
+ .plan-code-editing:focus-within .plan-code-chrome {
570
+ opacity: 1;
571
+ }
572
+
573
+ /* Read view of the `code` block reuses the shared CodeSurface — flatten it for
574
+ the `code` primitive only so the snippet sits on the page (no gray box). */
575
+ .plan-code .plan-code-surface {
576
+ background: transparent;
577
+ }
578
+ .plan-code .plan-code-surface .plan-shiki,
579
+ .plan-code .plan-code-surface pre,
580
+ .dark .plan-code .plan-code-surface .plan-shiki,
581
+ .dark .plan-code .plan-code-surface pre {
582
+ background: transparent !important;
583
+ }
584
+
585
+ .plan-code-editor-body {
586
+ position: relative;
587
+ overflow: auto;
588
+ }
589
+
590
+ .plan-code-editor-layer,
591
+ .plan-code-editor-input {
592
+ margin: 0;
593
+ padding: 0.85rem 1.1rem;
594
+ font-family: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
595
+ font-size: 0.78rem;
596
+ line-height: 1.6;
597
+ white-space: pre;
598
+ tab-size: 2;
599
+ }
600
+
601
+ .plan-code-editor-layer {
602
+ position: absolute;
603
+ inset: 0;
604
+ overflow: hidden;
605
+ pointer-events: none;
606
+ color: hsl(var(--foreground));
607
+ /* This is a <pre>; a base `pre {}` style would leak in a bg + border + larger
608
+ font-size. Override so it's flat and lines up exactly with the textarea. */
609
+ background: transparent !important;
610
+ border: 0 !important;
611
+ border-radius: 0;
612
+ font-size: 0.78rem !important;
613
+ line-height: 1.6 !important;
614
+ }
615
+
616
+ .plan-code-editor-input {
617
+ position: relative;
618
+ display: block;
619
+ width: 100%;
620
+ min-height: 2.5rem;
621
+ resize: none;
622
+ overflow: hidden;
623
+ border: 0;
624
+ background: transparent;
625
+ color: transparent;
626
+ caret-color: hsl(var(--foreground));
627
+ outline: none;
628
+ }
629
+
630
+ .plan-code-editor-input::placeholder {
631
+ color: hsl(var(--muted-foreground));
632
+ }
633
+
634
+ /* Collapsed long snippet: fade the clipped bottom into the page background. */
635
+ .plan-code-editor-fade {
636
+ position: absolute;
637
+ inset: auto 0 0 0;
638
+ height: 3rem;
639
+ pointer-events: none;
640
+ background: linear-gradient(
641
+ to bottom,
642
+ transparent,
643
+ hsl(var(--background)) 92%
644
+ );
645
+ }
646
+
647
+ .plan-code-caption {
648
+ margin-top: 0.5rem;
649
+ font-size: 0.8rem;
650
+ color: hsl(var(--muted-foreground));
651
+ }
652
+
653
+ .plan-code-caption-input {
654
+ width: 100%;
655
+ padding: 0 0.15rem;
656
+ border: 0;
657
+ background: transparent;
658
+ font-size: 0.8rem;
659
+ color: hsl(var(--muted-foreground));
660
+ outline: none;
661
+ }
662
+
663
+ /* ── Editor node view (Tiptap): language picker header + highlighted <pre> ─── */
664
+ .an-code-block {
665
+ position: relative;
666
+ margin: 1.1rem 0;
667
+ border: 1px solid hsl(var(--border));
668
+ border-radius: 12px;
669
+ background: hsl(var(--muted));
670
+ overflow: hidden;
671
+ }
672
+
673
+ .an-code-block__header {
674
+ display: flex;
675
+ align-items: center;
676
+ padding: 0.3rem 0.55rem;
677
+ border-bottom: 1px solid hsl(var(--border));
678
+ min-height: 2rem;
679
+ }
680
+
681
+ .an-code-block__lang {
682
+ display: inline-flex;
683
+ align-items: center;
684
+ gap: 0.25rem;
685
+ padding: 0.15rem 0.5rem;
686
+ border: none;
687
+ border-radius: 6px;
688
+ background: transparent;
689
+ color: hsl(var(--muted-foreground));
690
+ font-family: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
691
+ font-size: 0.7rem;
692
+ font-weight: 500;
693
+ cursor: pointer;
694
+ transition:
695
+ background-color 0.15s,
696
+ color 0.15s;
697
+ }
698
+
699
+ .an-code-block__lang:hover {
700
+ background: color-mix(in srgb, hsl(var(--muted)) 70%, transparent);
701
+ color: hsl(var(--foreground));
702
+ }
703
+
704
+ .an-code-block__lang--readonly,
705
+ .an-code-block__lang--readonly:hover {
706
+ cursor: default;
707
+ background: transparent;
708
+ color: hsl(var(--muted-foreground));
709
+ }
710
+
711
+ /* The node-view wrapper owns the surface (border + bg), so the inner <pre> is
712
+ transparent. Scoped via `.an-rich-md-prose` so it applies in every editor. */
713
+ .an-rich-md-prose .an-code-block pre {
714
+ margin: 0;
715
+ padding: 0.85rem 1.1rem;
716
+ border: 0;
717
+ border-radius: 0;
718
+ background: transparent;
719
+ color: hsl(var(--foreground));
720
+ font-family: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
721
+ font-size: 0.78rem;
722
+ line-height: 1.6;
723
+ overflow-x: auto;
724
+ }
725
+
726
+ .an-code-block pre code {
727
+ background: none;
728
+ padding: 0;
729
+ color: inherit;
730
+ font-size: inherit;
731
+ }
732
+
733
+ /* Language picker popover (rendered in a portal by the shared Popover). */
734
+ .an-code-block__search {
735
+ width: 100%;
736
+ padding: 0.5rem 0.65rem;
737
+ background: transparent;
738
+ border: none;
739
+ border-bottom: 1px solid hsl(var(--border));
740
+ color: hsl(var(--foreground));
741
+ font-size: 0.8rem;
742
+ outline: none;
743
+ }
744
+
745
+ .an-code-block__list {
746
+ max-height: 220px;
747
+ overflow-y: auto;
748
+ padding: 0.25rem;
749
+ }
750
+
751
+ .an-code-block__option {
752
+ display: flex;
753
+ align-items: center;
754
+ justify-content: space-between;
755
+ width: 100%;
756
+ padding: 0.35rem 0.5rem;
757
+ border: none;
758
+ border-radius: 6px;
759
+ background: transparent;
760
+ color: hsl(var(--foreground));
761
+ font-size: 0.8rem;
762
+ text-align: left;
763
+ cursor: pointer;
764
+ }
765
+
766
+ .an-code-block__option:hover {
767
+ background: hsl(var(--accent));
768
+ }
769
+
770
+ .an-code-block__option.is-active {
771
+ color: hsl(var(--primary));
772
+ }
773
+
774
+ /* ════════════════════════════════════════════════════════════════════════
775
+ Wireframe kit + inline diagram + HTML-artboard styling.
776
+
777
+ Copied verbatim from the plan template's wireframe CSS
778
+ (wireframe/html-artboard.css + wireframe/kit/plan-wireframe-tokens.css).
779
+ These already reference plan palette vars with shadcn theme-token
780
+ FALLBACKS — e.g. var(--plan-text, hsl(var(--foreground))) — so in plan
781
+ they resolve to plan's palette (unchanged) and in any other app they
782
+ resolve to that app's theme tokens. Loaded globally here so the shared
783
+ wireframe + diagram blocks render in any app, not just plan.
784
+ ════════════════════════════════════════════════════════════════════════ */
785
+
786
+ /* Question form / visual questions: respondent-facing intake block. */
787
+ .an-questions-block {
788
+ max-width: 860px;
789
+ }
790
+
791
+ /*
792
+ * HTML artboard styling.
793
+ *
794
+ * The model writes a plain, semantic HTML mockup of a screen. This stylesheet
795
+ * gives that HTML the wireframe look WITHOUT the model having to specify colors,
796
+ * fonts, or borders: it themes bare elements via tokens that flip on
797
+ * [data-theme], swaps the font on [data-style] (sketchy handwriting vs clean
798
+ * sans), and exposes --wf-* tokens + a few helper classes the model can lean on.
799
+ * The rough.js overlay then redraws the bordered boxes as hand-drawn strokes.
800
+ *
801
+ * Scope: `.plan-html-frame`. Everything is contained so model HTML can't leak
802
+ * into the app chrome.
803
+ */
804
+
805
+ .plan-html-frame {
806
+ --wf-ink: var(--plan-text, hsl(var(--foreground)));
807
+ --wf-muted: var(--plan-muted, hsl(var(--muted-foreground)));
808
+ --wf-line: var(--plan-line, hsl(var(--border)));
809
+ /* Hand-drawn sketch stroke. Separate from --wf-ink (text) so the rough.js
810
+ overlay can run a touch softer than the body text — most important in dark
811
+ mode, where near-white text ink as a stroke makes harsh, eye-straining
812
+ borders. In light mode it matches the ink. */
813
+ /* Sketch stroke = a soft gray a step more pronounced than the hairline
814
+ --wf-line, so rough (broken) strokes still read clearly. Gentle, not hard
815
+ ink; text stays the dark --wf-ink above. */
816
+ --wf-sketch: var(--plan-muted-line, hsl(var(--border)));
817
+ --wf-paper: var(--plan-document, hsl(var(--background)));
818
+ --wf-card: var(--plan-block, hsl(var(--card)));
819
+ --wf-accent: hsl(var(--ring));
820
+ --wf-accent-fg: hsl(var(--primary-foreground));
821
+ --wf-accent-soft: color-mix(in srgb, var(--wf-accent) 11%, transparent);
822
+ --wf-warn: hsl(var(--destructive));
823
+ --wf-ok: var(--wf-accent);
824
+ --wf-radius: 9px;
825
+
826
+ --wf-font-hand: "Excalifont", "Comic Sans MS", "Bradley Hand", cursive;
827
+ --wf-font-clean:
828
+ ui-sans-serif, system-ui, -apple-system, "Segoe UI", Inter, sans-serif;
829
+ --wf-font: var(--wf-font-hand);
830
+
831
+ position: relative;
832
+ width: 100%;
833
+ /* `min-height` (not a fixed `height: 100%`) so an HTML mockup fills the
834
+ auto-height artboard's floor yet grows with its content instead of clipping.
835
+ The frame shell (ArtboardFrame) owns the height policy; the prototype-live
836
+ scroll mode below pins to 100% for an internally-scrolling canvas. */
837
+ min-height: 100%;
838
+ overflow: hidden;
839
+ box-sizing: border-box;
840
+ background: var(--wf-paper);
841
+ color: var(--wf-ink);
842
+ font-family: var(--wf-font);
843
+ font-size: 14px;
844
+ line-height: 1.45;
845
+ }
846
+
847
+ .plan-html-frame-content {
848
+ width: 100%;
849
+ min-height: 100%;
850
+ }
851
+
852
+ .plan-html-frame[data-prototype-live="true"] {
853
+ overflow: auto;
854
+ }
855
+ .plan-html-frame[data-prototype-live="true"] > .plan-html-frame-content {
856
+ height: 100%;
857
+ min-height: 0;
858
+ overflow: auto !important;
859
+ overscroll-behavior: contain;
860
+ }
861
+
862
+ .plan-html-frame[data-style="clean"] {
863
+ --wf-font: var(--wf-font-clean);
864
+ }
865
+
866
+ .plan-html-frame[data-render-mode="design"] {
867
+ --wf-font: var(--wf-font-clean);
868
+ background: transparent;
869
+ color: inherit;
870
+ font-family: var(--wf-font-clean);
871
+ font-size: 16px;
872
+ line-height: normal;
873
+ }
874
+
875
+ :where(.plan-html-frame[data-render-mode="design"] .plan-html-frame-content)
876
+ :where(h1, h2, h3, p, small, a, button, input, textarea, select, hr) {
877
+ all: revert;
878
+ box-sizing: border-box;
879
+ }
880
+
881
+ .plan-html-frame[data-render-mode="design"] button,
882
+ .plan-html-frame[data-render-mode="design"] [role="button"],
883
+ .plan-html-frame[data-render-mode="design"] [data-goto] {
884
+ cursor: pointer;
885
+ }
886
+
887
+ .plan-html-frame[data-render-mode="design"] [data-plan-design-selected] {
888
+ outline: 2px solid hsl(var(--ring)) !important;
889
+ outline-offset: 2px;
890
+ }
891
+
892
+ .plan-html-frame * {
893
+ box-sizing: border-box;
894
+ min-width: 0;
895
+ }
896
+
897
+ /* Bare semantic elements get the wireframe look from tokens. */
898
+ .plan-html-frame:not([data-render-mode="design"]) h1 {
899
+ font-size: 22px;
900
+ font-weight: 700;
901
+ line-height: 1.15;
902
+ margin: 0 0 8px;
903
+ }
904
+ .plan-html-frame:not([data-render-mode="design"]) h2 {
905
+ font-size: 17px;
906
+ font-weight: 700;
907
+ line-height: 1.2;
908
+ margin: 0 0 6px;
909
+ }
910
+ .plan-html-frame:not([data-render-mode="design"]) h3 {
911
+ font-size: 14px;
912
+ font-weight: 700;
913
+ margin: 0 0 4px;
914
+ }
915
+ .plan-html-frame:not([data-render-mode="design"]) p {
916
+ margin: 0 0 8px;
917
+ }
918
+ .plan-html-frame:not([data-render-mode="design"]) small,
919
+ .plan-html-frame:not([data-render-mode="design"]) .wf-muted {
920
+ color: var(--wf-muted);
921
+ font-size: 12.5px;
922
+ }
923
+ .plan-html-frame:not([data-render-mode="design"]) a {
924
+ color: var(--wf-accent);
925
+ text-decoration: none;
926
+ }
927
+ .plan-html-frame:not([data-render-mode="design"]) hr {
928
+ border: 0;
929
+ border-top: 1.4px solid var(--wf-line);
930
+ margin: 10px 0;
931
+ }
932
+
933
+ .plan-html-frame:not([data-render-mode="design"]) button,
934
+ .plan-html-frame:not([data-render-mode="design"]) .wf-btn {
935
+ display: inline-flex;
936
+ align-items: center;
937
+ justify-content: center;
938
+ gap: 6px;
939
+ font: inherit;
940
+ font-weight: 700;
941
+ color: var(--wf-ink);
942
+ /* Opaque paper fill (not transparent) so a floating / overlapping button —
943
+ a FAB, a sticky toolbar action like "+ Add habit" — never shows the
944
+ content behind it through its body. */
945
+ background: var(--wf-paper);
946
+ border: 1.4px solid var(--wf-line);
947
+ border-radius: var(--wf-radius);
948
+ padding: 7px 14px;
949
+ cursor: default;
950
+ }
951
+ .plan-html-frame[data-prototype-live="true"]
952
+ :is(button, .wf-btn, [role="button"], [data-goto]) {
953
+ cursor: pointer;
954
+ }
955
+ .plan-html-frame[data-prototype-live="true"] :is(button, .wf-btn):active {
956
+ transform: translateY(1px);
957
+ }
958
+ .plan-html-frame[data-prototype-live="true"] [hidden] {
959
+ display: none !important;
960
+ }
961
+ .plan-html-frame[data-prototype-live="true"] .is-done,
962
+ .plan-html-frame[data-prototype-live="true"] [data-done="true"] {
963
+ color: var(--wf-muted);
964
+ text-decoration: line-through;
965
+ text-decoration-thickness: 1.5px;
966
+ }
967
+ .plan-html-frame:not([data-render-mode="design"]) button.primary,
968
+ .plan-html-frame:not([data-render-mode="design"]) .wf-btn.primary,
969
+ .plan-html-frame:not([data-render-mode="design"]) [data-primary] {
970
+ background: var(--wf-accent);
971
+ border-color: var(--wf-accent);
972
+ color: var(--wf-accent-fg);
973
+ }
974
+
975
+ .plan-html-frame:not([data-render-mode="design"]) input,
976
+ .plan-html-frame:not([data-render-mode="design"]) textarea,
977
+ .plan-html-frame:not([data-render-mode="design"]) select {
978
+ font: inherit;
979
+ color: var(--wf-ink);
980
+ background: var(--wf-card);
981
+ border: 1.4px solid var(--wf-line);
982
+ border-radius: var(--wf-radius);
983
+ padding: 8px 10px;
984
+ width: 100%;
985
+ }
986
+ .plan-html-frame:not([data-render-mode="design"]) input[type="checkbox"],
987
+ .plan-html-frame:not([data-render-mode="design"]) input[type="radio"] {
988
+ width: 16px;
989
+ height: 16px;
990
+ padding: 0;
991
+ accent-color: var(--wf-accent);
992
+ flex: 0 0 auto;
993
+ }
994
+
995
+ .plan-html-frame:not([data-render-mode="design"]) .wf-card,
996
+ .plan-html-frame:not([data-render-mode="design"]) .wf-box {
997
+ background: var(--wf-card);
998
+ border: 1.4px solid var(--wf-line);
999
+ border-radius: var(--wf-radius);
1000
+ padding: 12px;
1001
+ }
1002
+ .plan-html-frame:not([data-render-mode="design"]) .wf-pill,
1003
+ .plan-html-frame:not([data-render-mode="design"]) .wf-chip {
1004
+ display: inline-flex;
1005
+ align-items: center;
1006
+ gap: 5px;
1007
+ border: 1.4px solid var(--wf-line);
1008
+ border-radius: 999px;
1009
+ padding: 2px 10px;
1010
+ font-size: 12.5px;
1011
+ }
1012
+ .plan-html-frame:not([data-render-mode="design"]) .wf-pill.accent {
1013
+ border-color: var(--wf-accent);
1014
+ color: var(--wf-accent);
1015
+ background: var(--wf-accent-soft);
1016
+ }
1017
+
1018
+ /* Once rough has drawn, hide the crisp borders so there's no doubling. Pills
1019
+ keep their rounded crisp border (the rough overlay rounds them too). */
1020
+ .plan-html-frame[data-rough-ready]
1021
+ :is(button, input, textarea, select, .wf-card, .wf-box, hr, [data-rough]) {
1022
+ border-color: transparent !important;
1023
+ }
1024
+
1025
+ /* Skeleton register: neutral textless geometry. */
1026
+ .plan-html-frame[data-skeleton="true"] {
1027
+ --wf-ink: var(--plan-muted-line, hsl(var(--border)));
1028
+ --wf-muted: var(--plan-muted-line, hsl(var(--border)));
1029
+ --wf-line: var(--plan-placeholder-line, hsl(var(--border)));
1030
+ --wf-card: var(--plan-block, hsl(var(--card)));
1031
+ --wf-accent: var(--plan-muted-line, hsl(var(--border)));
1032
+ --wf-accent-soft: var(--plan-block, hsl(var(--card)));
1033
+ }
1034
+ .plan-html-frame[data-skeleton="true"] * {
1035
+ color: transparent !important;
1036
+ }
1037
+
1038
+ /*
1039
+ * Inline architecture/code diagrams.
1040
+ *
1041
+ * These are document-local HTML/SVG fragments, not top-canvas wireframes. They
1042
+ * share the wireframe sketch preference so the same viewer toggle can switch
1043
+ * authored diagrams between crisp and hand-drawn presentation.
1044
+ */
1045
+
1046
+ .plan-diagram-shell {
1047
+ position: relative;
1048
+ width: 100%;
1049
+ }
1050
+
1051
+ .plan-diagram-frame {
1052
+ --wf-ink: var(--plan-text, hsl(var(--foreground)));
1053
+ --wf-muted: var(--plan-muted, hsl(var(--muted-foreground)));
1054
+ --wf-line: var(--plan-line, hsl(var(--border)));
1055
+ --wf-sketch: var(--plan-muted-line, hsl(var(--border)));
1056
+ --wf-paper: var(--plan-document, hsl(var(--background)));
1057
+ --wf-card: var(--plan-block, hsl(var(--card)));
1058
+ --wf-accent: hsl(var(--ring));
1059
+ --wf-accent-fg: hsl(var(--primary-foreground));
1060
+ --wf-accent-soft: color-mix(in srgb, var(--wf-accent) 11%, transparent);
1061
+ --wf-warn: hsl(var(--destructive));
1062
+ --wf-ok: var(--wf-accent);
1063
+ --wf-radius: 8px;
1064
+ --wf-font-hand: "Excalifont", "Comic Sans MS", "Bradley Hand", cursive;
1065
+ --wf-font-clean:
1066
+ ui-sans-serif, system-ui, -apple-system, "Segoe UI", Inter, sans-serif;
1067
+ --wf-font: var(--wf-font-clean);
1068
+
1069
+ position: relative;
1070
+ overflow: hidden;
1071
+ width: 100%;
1072
+ border: 0;
1073
+ border-radius: 10px;
1074
+ background: var(--wf-paper);
1075
+ color: var(--wf-ink);
1076
+ font-family: var(--wf-font);
1077
+ font-size: 14px;
1078
+ line-height: 1.4;
1079
+ }
1080
+
1081
+ .plan-diagram-frame[data-style="sketchy"] {
1082
+ --wf-font: var(--wf-font-hand);
1083
+ line-height: 1.32;
1084
+ }
1085
+
1086
+ .plan-diagram-frame * {
1087
+ box-sizing: border-box;
1088
+ min-width: 0;
1089
+ overflow-wrap: anywhere;
1090
+ text-wrap: pretty;
1091
+ }
1092
+
1093
+ .plan-diagram-frame-content {
1094
+ width: 100%;
1095
+ }
1096
+
1097
+ .plan-diagram-frame svg {
1098
+ display: block;
1099
+ max-width: 100%;
1100
+ }
1101
+
1102
+ .plan-diagram-frame :is(h1, h2, h3, p, small, strong) {
1103
+ margin: 0;
1104
+ }
1105
+
1106
+ .plan-diagram-frame :is(h1, h2, h3, strong) {
1107
+ color: var(--wf-ink);
1108
+ }
1109
+
1110
+ .plan-diagram-frame h1 {
1111
+ font-size: 20px;
1112
+ line-height: 1.15;
1113
+ }
1114
+
1115
+ .plan-diagram-frame h2 {
1116
+ font-size: 16px;
1117
+ line-height: 1.2;
1118
+ }
1119
+
1120
+ .plan-diagram-frame h3 {
1121
+ font-size: 14px;
1122
+ line-height: 1.2;
1123
+ }
1124
+
1125
+ .plan-diagram-frame :is(p, small, .diagram-muted) {
1126
+ color: var(--wf-muted);
1127
+ }
1128
+
1129
+ .plan-diagram-frame
1130
+ :is(.diagram-panel, .diagram-card, .diagram-node, .diagram-box) {
1131
+ border: 1.25px solid var(--wf-line);
1132
+ border-radius: var(--wf-radius);
1133
+ background: var(--wf-card);
1134
+ }
1135
+
1136
+ .plan-diagram-frame
1137
+ :is(
1138
+ .diagram-panel,
1139
+ .diagram-card,
1140
+ .diagram-node,
1141
+ .diagram-box,
1142
+ [class*="card"],
1143
+ [class*="panel"],
1144
+ [class*="box"]
1145
+ ) {
1146
+ border-color: var(--wf-line) !important;
1147
+ background: var(--wf-card) !important;
1148
+ color: var(--wf-ink) !important;
1149
+ }
1150
+
1151
+ .plan-diagram-frame :is(.diagram-node, .diagram-box, .diagram-card) {
1152
+ max-width: 100%;
1153
+ }
1154
+
1155
+ .plan-diagram-frame :is(.diagram-node, .diagram-box, .diagram-card) small {
1156
+ display: block;
1157
+ max-width: 100%;
1158
+ }
1159
+
1160
+ .plan-diagram-frame :is(.diagram-muted, [class*="muted"], small) {
1161
+ color: var(--wf-muted) !important;
1162
+ }
1163
+
1164
+ .plan-diagram-frame
1165
+ :is(.diagram-pill, [class*="pill"], [class*="badge"], [class*="chip"]) {
1166
+ border-color: var(--wf-line) !important;
1167
+ background: var(--wf-paper) !important;
1168
+ color: var(--wf-ink) !important;
1169
+ }
1170
+
1171
+ .plan-diagram-frame :is(.diagram-accent, [class*="accent"], [class*="active"]) {
1172
+ border-color: var(--wf-accent) !important;
1173
+ color: var(--wf-accent) !important;
1174
+ background: var(--wf-accent-soft) !important;
1175
+ }
1176
+
1177
+ .plan-diagram-frame :is(svg, line, path, polyline, polygon, rect, circle) {
1178
+ stroke: var(--wf-line) !important;
1179
+ }
1180
+
1181
+ .plan-diagram-frame
1182
+ :is(rect, circle, ellipse, polygon)[fill]:not([fill="none"]) {
1183
+ fill: var(--wf-card) !important;
1184
+ }
1185
+
1186
+ .plan-diagram-frame svg text {
1187
+ fill: var(--wf-ink) !important;
1188
+ }
1189
+
1190
+ .plan-diagram-frame[data-style="sketchy"]
1191
+ :is(.diagram-node, .diagram-box, .diagram-card) {
1192
+ line-height: 1.16;
1193
+ }
1194
+
1195
+ .plan-diagram-frame[data-style="sketchy"] :is(.diagram-node, .diagram-box) {
1196
+ padding-inline: 7px;
1197
+ }
1198
+
1199
+ .plan-diagram-frame .diagram-pill {
1200
+ display: inline-flex;
1201
+ align-items: center;
1202
+ border: 1px solid var(--wf-line);
1203
+ border-radius: 999px;
1204
+ padding: 2px 8px;
1205
+ color: var(--wf-ink);
1206
+ background: var(--wf-paper);
1207
+ }
1208
+
1209
+ .plan-diagram-frame :is(.diagram-accent, .diagram-pill.accent) {
1210
+ --rough-stroke: var(--wf-accent);
1211
+ border-color: var(--wf-accent) !important;
1212
+ color: var(--wf-accent) !important;
1213
+ background: var(--wf-accent-soft) !important;
1214
+ }
1215
+
1216
+ .plan-diagram-frame :is(.diagram-ok, .diagram-pill.ok) {
1217
+ --rough-stroke: var(--wf-ok);
1218
+ border-color: var(--wf-ok) !important;
1219
+ color: var(--wf-ok) !important;
1220
+ background: color-mix(in srgb, var(--wf-ok) 10%, transparent) !important;
1221
+ }
1222
+
1223
+ .plan-diagram-frame :is(.diagram-warn, .diagram-pill.warn) {
1224
+ --rough-stroke: var(--wf-warn);
1225
+ border-color: var(--wf-warn) !important;
1226
+ color: var(--wf-warn) !important;
1227
+ background: color-mix(in srgb, var(--wf-warn) 10%, transparent) !important;
1228
+ }
1229
+
1230
+ .plan-diagram-frame[data-rough-ready]
1231
+ :is(
1232
+ .diagram-panel,
1233
+ .diagram-card,
1234
+ .diagram-node,
1235
+ .diagram-box,
1236
+ .diagram-pill,
1237
+ [class*="card"],
1238
+ [class*="box"],
1239
+ [class*="panel"],
1240
+ [class*="pill"],
1241
+ [data-rough],
1242
+ hr
1243
+ ) {
1244
+ border-color: transparent !important;
1245
+ }
1246
+
1247
+ /*
1248
+ * Plan wireframe design tokens.
1249
+ *
1250
+ * The MODEL emits a lean kit tree (no geometry, no CSS). This stylesheet owns
1251
+ * ALL visual quality for the wireframe primitives: ink/paper/accent palette,
1252
+ * density-driven spacing/type, and the hand-drawn fonts. Every kit component in
1253
+ * ./* reads these CSS vars, so density / accent / theme are switchable by
1254
+ * toggling a single attribute on a `.plan-wf` scope — never by changing nodes.
1255
+ *
1256
+ * Scope: `.plan-wf` (set on the Screen wrapper). Tokens are scoped, not global,
1257
+ * so wireframes can sit alongside the normal app chrome without leaking fonts
1258
+ * or colors.
1259
+ */
1260
+
1261
+ /* Hand-drawn fonts. Excalifont is served by the app; no remote font dependency. */
1262
+
1263
+ .plan-wf {
1264
+ /* ---- Theme palette ----------------------------------------------------- */
1265
+ --ink: var(--plan-text, hsl(var(--foreground)));
1266
+ --ink-soft: var(--plan-muted, hsl(var(--muted-foreground)));
1267
+ --line: var(--plan-line, hsl(var(--border)));
1268
+ /* Sketch stroke = a soft gray a step more pronounced than --line so rough
1269
+ strokes read clearly; matches the HTML artboard. Text stays the dark --ink. */
1270
+ --wf-sketch: var(--plan-muted-line, hsl(var(--border)));
1271
+ --paper: var(--plan-document, hsl(var(--background)));
1272
+ --card: var(--plan-block, hsl(var(--card)));
1273
+ --accent: hsl(var(--ring));
1274
+ --accent-soft: color-mix(in srgb, var(--accent) 15%, transparent);
1275
+ --warn: hsl(var(--destructive));
1276
+ --warn-soft: color-mix(in srgb, var(--warn) 14%, transparent);
1277
+ --ok: var(--accent);
1278
+ --ok-soft: color-mix(in srgb, var(--ok) 15%, transparent);
1279
+
1280
+ /* Page backdrop behind artboards (board surface, not the screen paper). */
1281
+ --plan-wf-page-bg: var(--plan-canvas, hsl(var(--background)));
1282
+
1283
+ /* ---- Fonts ------------------------------------------------------------- */
1284
+ --font-hand:
1285
+ "Excalifont", "Comic Sans MS", "Bradley Hand", "Marker Felt", cursive;
1286
+ --font-script:
1287
+ "Excalifont", "Comic Sans MS", "Bradley Hand", "Marker Felt", cursive;
1288
+ --font-clean:
1289
+ ui-sans-serif, system-ui, -apple-system, "Segoe UI", Inter, sans-serif;
1290
+
1291
+ /* ---- Density (regular default) ----------------------------------------- */
1292
+ /* Density is selected via [data-density]; individual tokens below. */
1293
+ --gap: 11px;
1294
+ --pad: 12px;
1295
+ --fs: 14px;
1296
+ --radius: 7px;
1297
+ --stroke: 1.4px;
1298
+
1299
+ /* ---- Sketch wobble ----------------------------------------------------- */
1300
+ /* Default crisp (low sketch). setSketch() helper overrides these inline. */
1301
+ --wobble: none;
1302
+ }
1303
+
1304
+ /* Density variants. Match the reference DENSITY map exactly. */
1305
+ .plan-wf[data-density="compact"] {
1306
+ --gap: 7px;
1307
+ --pad: 9px;
1308
+ --fs: 13px;
1309
+ --radius: 6px;
1310
+ --stroke: 1.3px;
1311
+ }
1312
+
1313
+ .plan-wf[data-density="regular"] {
1314
+ --gap: 11px;
1315
+ --pad: 12px;
1316
+ --fs: 14px;
1317
+ --radius: 7px;
1318
+ --stroke: 1.4px;
1319
+ }
1320
+
1321
+ .plan-wf[data-density="roomy"] {
1322
+ --gap: 15px;
1323
+ --pad: 17px;
1324
+ --fs: 15px;
1325
+ --radius: 9px;
1326
+ --stroke: 1.6px;
1327
+ }
1328
+
1329
+ /* ---- Clean style: drop the hand-drawn font for a normal sans ------------- */
1330
+ /* In clean mode the rough overlay is off and frames get crisp CSS borders, so
1331
+ the handwriting font reads as out of place — switch to the sans stack. */
1332
+ .plan-wf[data-style="clean"] {
1333
+ --font-hand: var(--font-clean);
1334
+ --font-script: var(--font-clean);
1335
+ }
1336
+
1337
+ /* ---- Rough sketch layer -------------------------------------------------- */
1338
+ /* The hand-drawn outlines are drawn by the rough.js overlay (kit/rough.tsx).
1339
+ Once it has measured + drawn, hide the crisp CSS borders so there is never a
1340
+ doubled border — fills and text stay, only the outline is replaced. */
1341
+ .plan-wf[data-rough-ready] [data-rough] {
1342
+ border-color: transparent !important;
1343
+ }
1344
+
1345
+ /* ---- Skeleton / neutral loading register --------------------------------- */
1346
+ /* One block flips the WHOLE kit to a textless skeleton: no ink, no rough, no
1347
+ color — every primitive already reads these vars, so nothing else changes.
1348
+ A skeleton is boxes + bars only; real labels collapse to transparent so the
1349
+ silhouette is preserved without readable copy. */
1350
+ .plan-wf[data-skeleton="true"] {
1351
+ --ink: var(--skeleton-fill);
1352
+ --ink-soft: var(--skeleton-fill);
1353
+ --line: var(--skeleton-fill);
1354
+ --card: var(--skeleton-block);
1355
+ --accent: var(--skeleton-fill);
1356
+ --accent-soft: var(--skeleton-block);
1357
+ --warn: var(--skeleton-fill);
1358
+ --warn-soft: var(--skeleton-block);
1359
+ --ok: var(--skeleton-fill);
1360
+ --ok-soft: var(--skeleton-block);
1361
+ --stroke: 0px;
1362
+ --skeleton-fill: var(--plan-muted-line, hsl(var(--border)));
1363
+ --skeleton-block: var(--plan-block, hsl(var(--card)));
1364
+ }
1365
+ /* Textless: hide real labels but keep their layout footprint. */
1366
+ .plan-wf[data-skeleton="true"] * {
1367
+ color: transparent !important;
1368
+ border-color: transparent !important;
1369
+ }
1370
+ /* Soft rounded placeholder bars in skeleton mode. */
1371
+ .plan-wf[data-skeleton="true"] {
1372
+ --radius: 7px;
1373
+ }
1374
+
1375
+ @media (prefers-reduced-motion: no-preference) {
1376
+ .plan-wf[data-skeleton="true"] {
1377
+ animation: plan-skeleton-pulse 1.6s ease-in-out infinite;
1378
+ }
1379
+ }
1380
+ @keyframes plan-skeleton-pulse {
1381
+ 0%,
1382
+ 100% {
1383
+ opacity: 1;
1384
+ }
1385
+ 50% {
1386
+ opacity: 0.7;
1387
+ }
1388
+ }