@nonoun/native-ai 1.0.1

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 (144) hide show
  1. package/dist/a2ui/a2ui-diagnostics.d.ts +31 -0
  2. package/dist/a2ui/a2ui-diagnostics.d.ts.map +1 -0
  3. package/dist/a2ui/a2ui-element.d.ts +30 -0
  4. package/dist/a2ui/a2ui-element.d.ts.map +1 -0
  5. package/dist/a2ui/a2ui-presets.d.ts +22 -0
  6. package/dist/a2ui/a2ui-presets.d.ts.map +1 -0
  7. package/dist/a2ui/adapters/a2a-adapter.d.ts +38 -0
  8. package/dist/a2ui/adapters/a2a-adapter.d.ts.map +1 -0
  9. package/dist/a2ui/adapters/adapter-types.d.ts +19 -0
  10. package/dist/a2ui/adapters/adapter-types.d.ts.map +1 -0
  11. package/dist/a2ui/adapters/ag-ui-adapter.d.ts +42 -0
  12. package/dist/a2ui/adapters/ag-ui-adapter.d.ts.map +1 -0
  13. package/dist/a2ui/adapters/direct-adapter.d.ts +30 -0
  14. package/dist/a2ui/adapters/direct-adapter.d.ts.map +1 -0
  15. package/dist/a2ui/adapters/index.d.ts +8 -0
  16. package/dist/a2ui/adapters/index.d.ts.map +1 -0
  17. package/dist/a2ui/index.d.ts +15 -0
  18. package/dist/a2ui/index.d.ts.map +1 -0
  19. package/dist/a2ui/install.d.ts +23 -0
  20. package/dist/a2ui/install.d.ts.map +1 -0
  21. package/dist/a2ui/protocol/a2ui-adapter.d.ts +50 -0
  22. package/dist/a2ui/protocol/a2ui-adapter.d.ts.map +1 -0
  23. package/dist/a2ui/protocol/a2ui-component-map.d.ts +49 -0
  24. package/dist/a2ui/protocol/a2ui-component-map.d.ts.map +1 -0
  25. package/dist/a2ui/protocol/a2ui-converter.d.ts +34 -0
  26. package/dist/a2ui/protocol/a2ui-converter.d.ts.map +1 -0
  27. package/dist/a2ui/protocol/a2ui-surface.d.ts +33 -0
  28. package/dist/a2ui/protocol/a2ui-surface.d.ts.map +1 -0
  29. package/dist/a2ui/protocol/a2ui-transport.d.ts +80 -0
  30. package/dist/a2ui/protocol/a2ui-transport.d.ts.map +1 -0
  31. package/dist/a2ui/protocol/a2ui-types.d.ts +104 -0
  32. package/dist/a2ui/protocol/a2ui-types.d.ts.map +1 -0
  33. package/dist/a2ui/protocol/index.d.ts +13 -0
  34. package/dist/a2ui/protocol/index.d.ts.map +1 -0
  35. package/dist/a2ui/protocol/kernel-bridge.d.ts +114 -0
  36. package/dist/a2ui/protocol/kernel-bridge.d.ts.map +1 -0
  37. package/dist/a2ui/register.d.ts +11 -0
  38. package/dist/a2ui/register.d.ts.map +1 -0
  39. package/dist/a2ui/session/agent-session.d.ts +44 -0
  40. package/dist/a2ui/session/agent-session.d.ts.map +1 -0
  41. package/dist/a2ui/session/catalog.d.ts +41 -0
  42. package/dist/a2ui/session/catalog.d.ts.map +1 -0
  43. package/dist/a2ui/session/event-emitter.d.ts +17 -0
  44. package/dist/a2ui/session/event-emitter.d.ts.map +1 -0
  45. package/dist/a2ui/session/index.d.ts +9 -0
  46. package/dist/a2ui/session/index.d.ts.map +1 -0
  47. package/dist/a2ui/session/session-manager.d.ts +33 -0
  48. package/dist/a2ui/session/session-manager.d.ts.map +1 -0
  49. package/dist/a2ui/session/surface-registry.d.ts +32 -0
  50. package/dist/a2ui/session/surface-registry.d.ts.map +1 -0
  51. package/dist/a2ui/session/types.d.ts +27 -0
  52. package/dist/a2ui/session/types.d.ts.map +1 -0
  53. package/dist/adapter-mock-CmByL6zQ.js +845 -0
  54. package/dist/chat/avatar/chat-avatar-element.d.ts +18 -0
  55. package/dist/chat/avatar/chat-avatar-element.d.ts.map +1 -0
  56. package/dist/chat/avatar/index.d.ts +2 -0
  57. package/dist/chat/avatar/index.d.ts.map +1 -0
  58. package/dist/chat/avatar/n-chat-avatar.d.ts +2 -0
  59. package/dist/chat/avatar/n-chat-avatar.d.ts.map +1 -0
  60. package/dist/chat/chat-input-element.d.ts +32 -0
  61. package/dist/chat/chat-input-element.d.ts.map +1 -0
  62. package/dist/chat/chat-panel-element.d.ts +100 -0
  63. package/dist/chat/chat-panel-element.d.ts.map +1 -0
  64. package/dist/chat/feed/chat-feed-element.d.ts +48 -0
  65. package/dist/chat/feed/chat-feed-element.d.ts.map +1 -0
  66. package/dist/chat/feed/index.d.ts +2 -0
  67. package/dist/chat/feed/index.d.ts.map +1 -0
  68. package/dist/chat/feed/n-chat-feed.d.ts +2 -0
  69. package/dist/chat/feed/n-chat-feed.d.ts.map +1 -0
  70. package/dist/chat/gateway/adapter-chatgpt.d.ts +67 -0
  71. package/dist/chat/gateway/adapter-chatgpt.d.ts.map +1 -0
  72. package/dist/chat/gateway/adapter-claude.d.ts +68 -0
  73. package/dist/chat/gateway/adapter-claude.d.ts.map +1 -0
  74. package/dist/chat/gateway/adapter-mock.d.ts +3 -0
  75. package/dist/chat/gateway/adapter-mock.d.ts.map +1 -0
  76. package/dist/chat/gateway/adapter.d.ts +71 -0
  77. package/dist/chat/gateway/adapter.d.ts.map +1 -0
  78. package/dist/chat/gateway/controller.d.ts +46 -0
  79. package/dist/chat/gateway/controller.d.ts.map +1 -0
  80. package/dist/chat/gateway/index.d.ts +9 -0
  81. package/dist/chat/gateway/index.d.ts.map +1 -0
  82. package/dist/chat/gateway/runtime.d.ts +53 -0
  83. package/dist/chat/gateway/runtime.d.ts.map +1 -0
  84. package/dist/chat/gateway/types.d.ts +73 -0
  85. package/dist/chat/gateway/types.d.ts.map +1 -0
  86. package/dist/chat/gateway.d.ts +2 -0
  87. package/dist/chat/gateway.d.ts.map +1 -0
  88. package/dist/chat/index.d.ts +17 -0
  89. package/dist/chat/index.d.ts.map +1 -0
  90. package/dist/chat/message/chat-input-structured-element.d.ts +43 -0
  91. package/dist/chat/message/chat-input-structured-element.d.ts.map +1 -0
  92. package/dist/chat/message/chat-message-activity-element.d.ts +32 -0
  93. package/dist/chat/message/chat-message-activity-element.d.ts.map +1 -0
  94. package/dist/chat/message/chat-message-element.d.ts +44 -0
  95. package/dist/chat/message/chat-message-element.d.ts.map +1 -0
  96. package/dist/chat/message/chat-message-genui-element.d.ts +45 -0
  97. package/dist/chat/message/chat-message-genui-element.d.ts.map +1 -0
  98. package/dist/chat/message/chat-message-seed-element.d.ts +33 -0
  99. package/dist/chat/message/chat-message-seed-element.d.ts.map +1 -0
  100. package/dist/chat/message/chat-message-text-element.d.ts +37 -0
  101. package/dist/chat/message/chat-message-text-element.d.ts.map +1 -0
  102. package/dist/chat/message/chat-messages-element.d.ts +39 -0
  103. package/dist/chat/message/chat-messages-element.d.ts.map +1 -0
  104. package/dist/chat/message/index.d.ts +8 -0
  105. package/dist/chat/message/index.d.ts.map +1 -0
  106. package/dist/chat/message/n-chat-message.d.ts +2 -0
  107. package/dist/chat/message/n-chat-message.d.ts.map +1 -0
  108. package/dist/chat/register.d.ts +13 -0
  109. package/dist/chat/register.d.ts.map +1 -0
  110. package/dist/chat/stream/classify.d.ts +19 -0
  111. package/dist/chat/stream/classify.d.ts.map +1 -0
  112. package/dist/chat/stream/create-transport.d.ts +19 -0
  113. package/dist/chat/stream/create-transport.d.ts.map +1 -0
  114. package/dist/chat/stream/index.d.ts +9 -0
  115. package/dist/chat/stream/index.d.ts.map +1 -0
  116. package/dist/chat/stream/parse-json.d.ts +9 -0
  117. package/dist/chat/stream/parse-json.d.ts.map +1 -0
  118. package/dist/chat/stream/parse-ndjson.d.ts +9 -0
  119. package/dist/chat/stream/parse-ndjson.d.ts.map +1 -0
  120. package/dist/chat/stream/parse-sse.d.ts +9 -0
  121. package/dist/chat/stream/parse-sse.d.ts.map +1 -0
  122. package/dist/chat/stream/types.d.ts +42 -0
  123. package/dist/chat/stream/types.d.ts.map +1 -0
  124. package/dist/chat/telemetry/emitter.d.ts +20 -0
  125. package/dist/chat/telemetry/emitter.d.ts.map +1 -0
  126. package/dist/chat/telemetry/events.d.ts +11 -0
  127. package/dist/chat/telemetry/events.d.ts.map +1 -0
  128. package/dist/chat/telemetry/index.d.ts +5 -0
  129. package/dist/chat/telemetry/index.d.ts.map +1 -0
  130. package/dist/chat/telemetry/redactor.d.ts +17 -0
  131. package/dist/chat/telemetry/redactor.d.ts.map +1 -0
  132. package/dist/chat/telemetry/types.d.ts +27 -0
  133. package/dist/chat/telemetry/types.d.ts.map +1 -0
  134. package/dist/gateway.d.ts +2 -0
  135. package/dist/gateway.d.ts.map +1 -0
  136. package/dist/gateway.js +33 -0
  137. package/dist/index.d.ts +5 -0
  138. package/dist/index.d.ts.map +1 -0
  139. package/dist/native-ai.css +1404 -0
  140. package/dist/native-ai.js +11142 -0
  141. package/dist/register.d.ts +12 -0
  142. package/dist/register.d.ts.map +1 -0
  143. package/dist/register.js +0 -0
  144. package/package.json +66 -0
@@ -0,0 +1,1404 @@
1
+ /**
2
+ * native-a2ui — A2UI Protocol Workbench
3
+ *
4
+ * Layout: chip-toggled multi-panel — preview left, N resizable panes right.
5
+ * Chrome & token patterns mirror <native-playground> for a unified devtool look.
6
+ * Loaded by consumers via: @import '@nonoun/native-ai/css'
7
+ */
8
+
9
+ @layer ui {
10
+
11
+ /* ── Host ── */
12
+
13
+ :where(native-a2ui) {
14
+ /* Devtool chrome tokens — mirrors native-playground */
15
+ --n-pg-chrome: var(--n-panel-neutral, #21252b);
16
+ --n-pg-editor-bg: var(--n-control-neutral, #282c34);
17
+ --n-pg-border-color: var(--n-border-muted-neutral, #3e4451);
18
+ --n-pg-border: 1px solid var(--n-pg-border-color);
19
+ --n-pg-text: var(--n-ink-neutral, #abb2bf);
20
+ --n-pg-text-muted: var(--n-ink-muted-neutral, #7d8799);
21
+ --n-pg-text-strong: var(--n-ink-strong-neutral, #e5e7eb);
22
+ --n-pg-accent: var(--n-ink-accent, #61afef);
23
+ --n-pg-run: var(--n-ink-success, #98c379);
24
+ --n-pg-run-hover: var(--n-ink-hover-success, #b5e890);
25
+ --n-pg-run-hover-bg: var(--n-control-success, #333d37);
26
+ --n-pg-warn: var(--n-ink-warning, #e5c07b);
27
+ --n-pg-error: var(--n-ink-danger, #e06c75);
28
+ --n-pg-preview-bg: var(--n-body-neutral, #ffffff);
29
+
30
+ display: grid;
31
+ grid-template-rows: auto 1fr;
32
+ min-height: 400px;
33
+ max-height: 80dvh;
34
+ border: var(--n-pg-border);
35
+ border-radius: var(--n-radius-lg, 0.75rem);
36
+ overflow: hidden;
37
+ background: var(--n-pg-editor-bg);
38
+ color: var(--n-pg-text);
39
+ user-select: none;
40
+ }
41
+
42
+ /* Allow text selection in content areas */
43
+ :where(native-a2ui) :where(.a2ui-preview-content),
44
+ :where(native-a2ui) :where(.a2ui-pane-content),
45
+ :where(native-a2ui) :where(.cm-editor) {
46
+ user-select: text;
47
+ }
48
+
49
+ /* Full-viewport presented state (PresentController sets [presented]) */
50
+ :where(native-a2ui)[presented] {
51
+ width: 100%;
52
+ height: 100%;
53
+ max-height: none;
54
+ justify-self: stretch;
55
+ align-self: stretch;
56
+ border: none;
57
+ border-radius: 0;
58
+ }
59
+
60
+ /* ── Dark chrome header toolbar (chips + expand) ── */
61
+
62
+ :where(native-a2ui) > :where(n-header) {
63
+ flex: none;
64
+ background: var(--n-pg-chrome);
65
+ --n-ink: var(--n-pg-text-muted);
66
+ --n-ink-hover: var(--n-pg-text);
67
+ --n-ink-strong: var(--n-pg-text-strong);
68
+ --n-border-muted: transparent;
69
+ }
70
+
71
+ /* Header button hover background */
72
+ :where(native-a2ui) > :where(n-header) :where(n-button):hover,
73
+ :where(native-a2ui) > :where(n-header) :where(n-button)[force-hover] {
74
+ background: var(--n-pg-editor-bg);
75
+ }
76
+
77
+ /* Chip active state — "panel is open" indicator */
78
+ :where(native-a2ui) > :where(n-header) :where(n-button)[data-active] {
79
+ background: var(--n-pg-editor-bg);
80
+ color: var(--n-pg-text-strong);
81
+ }
82
+
83
+ /* Play All button — green accent override (mirrors playground Run button) */
84
+ :where(native-a2ui) :where(n-button[data-role="run"]) {
85
+ --n-color: var(--n-pg-run);
86
+ --n-color-hover: var(--n-pg-run-hover);
87
+ }
88
+
89
+ :where(native-a2ui) :where(n-button[data-role="run"]):hover,
90
+ :where(native-a2ui) :where(n-button[data-role="run"])[force-hover] {
91
+ background: var(--n-pg-run-hover-bg);
92
+ }
93
+
94
+ /* ── Split: preview left, panes right ── */
95
+
96
+ :where(native-a2ui) :where(.a2ui-split) {
97
+ display: flex;
98
+ min-height: 0;
99
+ overflow: hidden;
100
+ }
101
+
102
+ /* ── Preview (left side) ── */
103
+
104
+ :where(native-a2ui) :where(.a2ui-preview) {
105
+ position: relative;
106
+ display: flex;
107
+ flex-direction: column;
108
+ flex: 1 1 50%;
109
+ min-width: 200px;
110
+ min-height: 0;
111
+ overflow: hidden;
112
+ }
113
+
114
+ /* When resized, respect the explicit width */
115
+ :where(native-a2ui) :where(.a2ui-preview[style*="width"]) {
116
+ flex: none;
117
+ }
118
+
119
+ :where(native-a2ui) :where(.a2ui-preview-content) {
120
+ flex: 1;
121
+ min-height: 0;
122
+ overflow: auto;
123
+ padding: 1rem;
124
+ background: var(--n-pg-preview-bg);
125
+ }
126
+
127
+ /* ── Resize Handle (shared by preview + panes) ── */
128
+
129
+ :where(native-a2ui) :where(.a2ui-resize-handle) {
130
+ position: absolute;
131
+ top: 0;
132
+ right: 0;
133
+ bottom: 0;
134
+ width: 6px;
135
+ cursor: col-resize;
136
+ background: transparent;
137
+ transition: background 150ms;
138
+ z-index: 1;
139
+ }
140
+
141
+ :where(native-a2ui) :where(.a2ui-resize-handle):hover,
142
+ :where(native-a2ui) :where([resizing]) :where(.a2ui-resize-handle) {
143
+ background: var(--n-pg-accent);
144
+ }
145
+
146
+ /* Hide handle on the last visible pane — nothing to resize against.
147
+ Hidden panes have display:none so :last-child among visible = no subsequent visible sibling. */
148
+ :where(native-a2ui) :where(.a2ui-pane):not([hidden]):not(:has(~ .a2ui-pane:not([hidden]))) > :where(.a2ui-resize-handle) {
149
+ display: none;
150
+ }
151
+
152
+ /* ── Pane (each toggled panel in the split) ── */
153
+
154
+ :where(native-a2ui) :where(.a2ui-pane) {
155
+ position: relative;
156
+ display: flex;
157
+ flex-direction: column;
158
+ flex: 1 1 0%;
159
+ min-width: 150px;
160
+ min-height: 0;
161
+ overflow: hidden;
162
+ border-left: var(--n-pg-border);
163
+ }
164
+
165
+ /* When resized (has explicit width from ResizeController), don't flex-grow */
166
+ :where(native-a2ui) :where(.a2ui-pane[style*="width"]) {
167
+ flex: none;
168
+ }
169
+
170
+ :where(native-a2ui) :where(.a2ui-pane[hidden]) {
171
+ display: none;
172
+ }
173
+
174
+ /* ── Pane Header (icon + label + close button) ── */
175
+
176
+ :where(native-a2ui) :where(.a2ui-pane) > :where(n-header) {
177
+ flex: none;
178
+ background: var(--n-pg-chrome);
179
+ border-bottom: var(--n-pg-border);
180
+ min-height: unset;
181
+ padding-block: 0;
182
+ padding-inline: 0.5rem;
183
+ --n-ink: var(--n-pg-text-muted);
184
+ --n-ink-hover: var(--n-pg-text);
185
+ --n-size: 1.75rem;
186
+ font-size: 0.75rem;
187
+ font-weight: 600;
188
+ text-transform: uppercase;
189
+ letter-spacing: 0.04em;
190
+ }
191
+
192
+ :where(native-a2ui) :where(.a2ui-pane) > :where(n-header) :where(n-icon) {
193
+ font-size: 0.875rem;
194
+ }
195
+
196
+ :where(native-a2ui) :where(.a2ui-pane) > :where(n-header) :where(n-button):hover,
197
+ :where(native-a2ui) :where(.a2ui-pane) > :where(n-header) :where(n-button)[force-hover] {
198
+ background: var(--n-pg-editor-bg);
199
+ }
200
+
201
+ /* ── Pane Content (inner scrollable area) ── */
202
+
203
+ :where(native-a2ui) :where(.a2ui-pane-content) {
204
+ flex: 1;
205
+ min-height: 0;
206
+ overflow: auto;
207
+ padding: 0.5rem;
208
+ font-family: var(--n-font-family-mono, ui-monospace, 'SF Mono', 'Cascadia Code', monospace);
209
+ font-size: 0.8125rem;
210
+ line-height: 1.5;
211
+ }
212
+
213
+ /* CodeMirror panes: editor fills space, no padding */
214
+ :where(native-a2ui) :where([data-panel="json-in"]) :where(.a2ui-pane-content),
215
+ :where(native-a2ui) :where([data-panel="js"]) :where(.a2ui-pane-content),
216
+ :where(native-a2ui) :where([data-panel="html"]) :where(.a2ui-pane-content),
217
+ :where(native-a2ui) :where([data-panel="css"]) :where(.a2ui-pane-content) {
218
+ padding: 0;
219
+ overflow: hidden;
220
+ }
221
+
222
+ /* ── Component Map Table (UI pane) ── */
223
+
224
+ :where(native-a2ui) :where(.a2ui-map-summary) {
225
+ padding: 0.375rem 0.5rem;
226
+ font-size: 0.6875rem;
227
+ color: var(--n-pg-text-muted);
228
+ border-bottom: var(--n-pg-border);
229
+ }
230
+
231
+ :where(native-a2ui) :where(.a2ui-component-map) {
232
+ width: 100%;
233
+ border-collapse: collapse;
234
+ font-size: 0.75rem;
235
+ line-height: 1.4;
236
+ }
237
+
238
+ :where(native-a2ui) :where(.a2ui-component-map) :where(th) {
239
+ text-align: left;
240
+ padding: 0.25rem 0.5rem;
241
+ color: var(--n-pg-text-muted);
242
+ font-weight: 600;
243
+ font-size: 0.6875rem;
244
+ text-transform: uppercase;
245
+ letter-spacing: 0.04em;
246
+ border-bottom: var(--n-pg-border);
247
+ position: sticky;
248
+ top: 0;
249
+ background: var(--n-pg-chrome);
250
+ }
251
+
252
+ :where(native-a2ui) :where(.a2ui-component-map) :where(td) {
253
+ padding: 0.1875rem 0.5rem;
254
+ border-bottom: 1px solid color-mix(in oklch, var(--n-pg-text-muted), transparent 85%);
255
+ white-space: nowrap;
256
+ }
257
+
258
+ :where(native-a2ui) :where(.a2ui-component-map) :where(code) {
259
+ font-family: var(--n-font-family-mono, ui-monospace, 'SF Mono', 'Cascadia Code', monospace);
260
+ font-size: 0.6875rem;
261
+ background: color-mix(in oklch, var(--n-pg-text-muted), transparent 88%);
262
+ padding: 0.0625rem 0.25rem;
263
+ border-radius: 0.1875rem;
264
+ }
265
+
266
+ :where(native-a2ui) :where(.a2ui-map-type) {
267
+ font-weight: 600;
268
+ }
269
+
270
+ :where(native-a2ui) :where(.a2ui-map-active) {
271
+ background: color-mix(in oklch, var(--n-pg-text), transparent 92%);
272
+ }
273
+
274
+ :where(native-a2ui) :where(.a2ui-map-active) :where(.a2ui-map-type) {
275
+ color: var(--n-color-accent-500, oklch(0.65 0.2 260));
276
+ }
277
+
278
+ :where(native-a2ui) :where(.a2ui-map-row) {
279
+ cursor: pointer;
280
+ }
281
+
282
+ :where(native-a2ui) :where(.a2ui-map-row):hover {
283
+ background: color-mix(in oklch, var(--n-pg-text), transparent 92%);
284
+ }
285
+
286
+ :where(native-a2ui) :where(.a2ui-map-category) {
287
+ color: var(--n-pg-text-muted);
288
+ font-size: 0.6875rem;
289
+ }
290
+
291
+ /* ── Component Detail View ── */
292
+
293
+ :where(native-a2ui) :where(.a2ui-map-back) {
294
+ font-size: 0.6875rem;
295
+ --n-color: var(--n-pg-accent);
296
+ --n-color-hover: var(--n-pg-text-strong);
297
+ border-radius: 0;
298
+ }
299
+
300
+ :where(native-a2ui) :where(.a2ui-map-detail) {
301
+ padding: 0.5rem;
302
+ }
303
+
304
+ :where(native-a2ui) :where(.a2ui-map-detail-title) {
305
+ font-size: 0.875rem;
306
+ font-weight: 600;
307
+ color: var(--n-pg-text-strong);
308
+ }
309
+
310
+ :where(native-a2ui) :where(.a2ui-map-detail-row) {
311
+ display: flex;
312
+ align-items: baseline;
313
+ gap: 0.5rem;
314
+ padding: 0.1875rem 0;
315
+ font-size: 0.75rem;
316
+ }
317
+
318
+ :where(native-a2ui) :where(.a2ui-map-detail-label) {
319
+ color: var(--n-pg-text-muted);
320
+ min-width: 4.5rem;
321
+ font-size: 0.6875rem;
322
+ text-transform: uppercase;
323
+ letter-spacing: 0.04em;
324
+ font-weight: 600;
325
+ }
326
+
327
+ :where(native-a2ui) :where(.a2ui-map-detail) :where(code) {
328
+ font-family: var(--n-font-family-mono, ui-monospace, 'SF Mono', 'Cascadia Code', monospace);
329
+ font-size: 0.6875rem;
330
+ background: color-mix(in oklch, var(--n-pg-text-muted), transparent 88%);
331
+ padding: 0.0625rem 0.25rem;
332
+ border-radius: 0.1875rem;
333
+ }
334
+
335
+ /* ── Detail Header (n-header with leading back + trailing tabs) ── */
336
+
337
+ :where(native-a2ui) :where(.a2ui-map-detail-header) {
338
+ padding-inline: 0.5rem;
339
+ padding-block: 0.25rem;
340
+ border-bottom: var(--n-pg-border);
341
+ }
342
+
343
+ :where(native-a2ui) :where(.a2ui-map-tab-bar) {
344
+ --n-background: var(--n-pg-surface);
345
+ --n-border-color: var(--n-pg-border-color);
346
+ --n-ink: var(--n-pg-text-muted);
347
+ --n-ink-strong: var(--n-pg-text-strong);
348
+ --n-border-muted: var(--n-pg-border-color);
349
+ }
350
+
351
+ /* ── Component Instance Editor ── */
352
+
353
+ :where(native-a2ui) :where(.a2ui-map-editor-section) {
354
+ display: flex;
355
+ flex-direction: column;
356
+ flex: 1;
357
+ min-height: 0;
358
+ }
359
+
360
+ :where(native-a2ui) :where(.a2ui-map-editor-toolbar) {
361
+ justify-content: flex-end;
362
+ padding-inline: 0.5rem;
363
+ --n-ink: var(--n-pg-run);
364
+ --n-ink-hover: var(--n-pg-run-hover);
365
+ --n-ground: var(--n-pg-chrome);
366
+ background: var(--n-pg-chrome);
367
+ }
368
+
369
+ :where(native-a2ui) :where(.a2ui-map-editor-section) :where(native-codemirror) {
370
+ flex: 1;
371
+ min-height: 0;
372
+ border-radius: 0;
373
+ overflow: hidden;
374
+ }
375
+
376
+ /* ── Compatible Alternatives ── */
377
+
378
+ :where(native-a2ui) :where(.a2ui-map-alternatives) {
379
+ margin-top: 0.75rem;
380
+ border-top: var(--n-pg-border);
381
+ padding-top: 0.5rem;
382
+ }
383
+
384
+ :where(native-a2ui) :where(.a2ui-map-alt-title) {
385
+ padding: 0 0.5rem 0.375rem;
386
+ font-size: 0.6875rem;
387
+ color: var(--n-pg-text-muted);
388
+ font-weight: 600;
389
+ text-transform: uppercase;
390
+ letter-spacing: 0.04em;
391
+ }
392
+
393
+ :where(native-a2ui) :where(.a2ui-map-alt-row) {
394
+ display: flex;
395
+ align-items: center;
396
+ gap: 0.5rem;
397
+ padding: 0.25rem 0.5rem;
398
+ font-size: 0.75rem;
399
+ cursor: pointer;
400
+ border-radius: 0.25rem;
401
+ }
402
+
403
+ :where(native-a2ui) :where(.a2ui-map-alt-row):hover {
404
+ background: color-mix(in oklch, var(--n-pg-text), transparent 92%);
405
+ }
406
+
407
+ :where(native-a2ui) :where(.a2ui-map-swap-icon) {
408
+ font-size: 0.75rem;
409
+ color: var(--n-pg-accent);
410
+ opacity: 0.5;
411
+ }
412
+
413
+ :where(native-a2ui) :where(.a2ui-map-alt-row):hover :where(.a2ui-map-swap-icon) {
414
+ opacity: 1;
415
+ }
416
+
417
+ :where(native-a2ui) :where(.a2ui-map-alt-row) :where(code) {
418
+ font-family: var(--n-font-family-mono, ui-monospace, 'SF Mono', 'Cascadia Code', monospace);
419
+ font-size: 0.6875rem;
420
+ background: color-mix(in oklch, var(--n-pg-text-muted), transparent 88%);
421
+ padding: 0.0625rem 0.25rem;
422
+ border-radius: 0.1875rem;
423
+ color: var(--n-pg-text-muted);
424
+ }
425
+
426
+ /* ── Toolbar (playback controls inside JSON-IN pane) ── */
427
+
428
+ :where(native-a2ui) :where([data-panel="json-in"]) > :where(n-toolbar) {
429
+ flex: none;
430
+ background: var(--n-pg-chrome);
431
+ border-bottom: var(--n-pg-border);
432
+ --n-ink: var(--n-pg-text-muted);
433
+ --n-ink-hover: var(--n-pg-text);
434
+ }
435
+
436
+ /* Override n-divider flex:1 inside toolbar — just be a thin line */
437
+ :where(native-a2ui) :where([data-panel="json-in"]) > :where(n-toolbar) :where(n-divider) {
438
+ flex: none;
439
+ }
440
+
441
+ /* Toolbar button hover */
442
+ :where(native-a2ui) :where([data-panel="json-in"]) > :where(n-toolbar) :where(n-button):hover,
443
+ :where(native-a2ui) :where([data-panel="json-in"]) > :where(n-toolbar) :where(n-button)[force-hover] {
444
+ background: var(--n-pg-editor-bg);
445
+ }
446
+
447
+ /* ── CodeMirror (mirrors playground overrides) ── */
448
+
449
+ :where(native-a2ui) :where(native-codemirror) {
450
+ flex: 1;
451
+ min-height: 0;
452
+ border-radius: 0;
453
+ }
454
+
455
+ :where(native-a2ui) :where(.cm-editor) {
456
+ font-size: 0.8125rem;
457
+ color-scheme: dark;
458
+ }
459
+
460
+ :where(native-a2ui) :where(.cm-scroller) {
461
+ overflow: auto;
462
+ }
463
+
464
+ :where(native-a2ui) :where(.cm-gutters) {
465
+ border-right: none;
466
+ }
467
+
468
+ /* ── Log Entries (shared by JSON-OUT and JS panes) ── */
469
+
470
+ :where(native-a2ui) :where(.a2ui-log-entry) {
471
+ padding: 0.25rem 0;
472
+ border-bottom: var(--n-pg-border);
473
+ }
474
+
475
+ :where(native-a2ui) :where(.a2ui-log-type) {
476
+ margin-right: 0.5rem;
477
+ font-size: 0.5625rem;
478
+ --n-surface: var(--n-pg-chrome);
479
+ --n-surface-ink: var(--n-pg-text-muted);
480
+ vertical-align: middle;
481
+ }
482
+
483
+ :where(native-a2ui) :where(.a2ui-log-type--sent) { --n-surface-ink: var(--n-pg-accent); }
484
+ :where(native-a2ui) :where(.a2ui-log-type--received) { --n-surface-ink: var(--n-pg-accent); }
485
+ :where(native-a2ui) :where(.a2ui-log-type--action) { --n-surface-ink: var(--n-pg-run); }
486
+ :where(native-a2ui) :where(.a2ui-log-type--error) { --n-surface-ink: var(--n-pg-error); }
487
+ :where(native-a2ui) :where(.a2ui-log-type--warning) { --n-surface-ink: var(--n-pg-warn); }
488
+ :where(native-a2ui) :where(.a2ui-log-type--info) { --n-surface-ink: var(--n-pg-text-muted); }
489
+
490
+ /* ── Tree View ── */
491
+
492
+ :where(native-a2ui) :where(.a2ui-tree-node) {
493
+ padding-left: 1rem;
494
+ }
495
+
496
+ :where(native-a2ui) :where(.a2ui-tree-label) {
497
+ cursor: default;
498
+ }
499
+
500
+ :where(native-a2ui) :where(.a2ui-tree-id) {
501
+ color: var(--n-pg-accent);
502
+ }
503
+
504
+ :where(native-a2ui) :where(.a2ui-tree-type) {
505
+ color: var(--n-pg-text-muted);
506
+ margin-left: 0.375rem;
507
+ }
508
+
509
+ :where(native-a2ui) :where(.a2ui-tree-tag) {
510
+ color: var(--n-pg-run);
511
+ margin-left: 0.375rem;
512
+ }
513
+
514
+ /* ── Cursor Highlight (sent/pending lines in editor) ── */
515
+
516
+ :where(native-a2ui) :where(.cm-a2ui-sent) {
517
+ opacity: 0.5;
518
+ }
519
+
520
+ :where(native-a2ui) :where(.cm-a2ui-next) {
521
+ background: var(--n-surface-accent, rgba(97, 175, 239, 0.1));
522
+ }
523
+
524
+ } /* @layer ui */
525
+ /* ════════════════════════════════════════════════════
526
+ native-chat — Chat component styles
527
+ ════════════════════════════════════════════════════
528
+
529
+ CSS Override Policy
530
+ ───────────────────
531
+ chat.css specializes core native-ui components for chat contexts.
532
+ All overrides use zero-specificity :where() selectors or properly
533
+ scoped attribute selectors per the CSS Single-Owner Principle.
534
+
535
+ 1. n-textarea (inside n-chat-input):
536
+ Transparent background/borders — composer field should not
537
+ show control chrome. Overrides textarea.css via source order
538
+ (both :where(), chat loads later).
539
+
540
+ 2. Sub-containers (n-header, n-body, n-footer):
541
+ Context-specific backgrounds and borders via --n-chat-panel-*
542
+ tokens. Overrides panel.css border pattern via source order.
543
+
544
+ 3. Aside overflow:
545
+ overflow: visible instead of panel.css's overflow-y: auto.
546
+ Chat panel delegates scrolling to its n-body sub-container.
547
+
548
+ 4. n-button gap (model picker):
549
+ Tighter gap via [justify="spread"] attribute selector (0,1,0)
550
+ beating button.css zero-specificity base rule.
551
+
552
+ ════════════════════════════════════════════════════ */
553
+
554
+ @layer ui {
555
+
556
+ /* ── :not(:defined) visibility guards ── */
557
+
558
+ :where(n-chat-input):not(:defined),
559
+ :where(n-chat-feed):not(:defined),
560
+ :where(n-chat-avatar):not(:defined),
561
+ :where(n-chat-message):not(:defined),
562
+ :where(n-chat-messages):not(:defined),
563
+ :where(n-chat-message-text):not(:defined),
564
+ :where(n-chat-message-activity):not(:defined),
565
+ :where(n-chat-message-seed):not(:defined),
566
+ :where(n-chat-message-genui):not(:defined),
567
+ :where(n-chat-input-structured):not(:defined) { visibility: hidden; }
568
+
569
+ /* ══════════════════════════════════════════════════
570
+ Chat Token Definitions
571
+ ══════════════════════════════════════════════════ */
572
+
573
+ :where(n-chat-feed),
574
+ :where(native-chat-panel) {
575
+ /* Feed */
576
+ --n-chat-gap: calc(var(--n-space) * 4);
577
+ --n-chat-message-gap: calc(var(--n-space) * 2);
578
+
579
+ /* Bubbles */
580
+ --n-chat-bubble-user: var(--n-button);
581
+ --n-chat-bubble-user-color: white;
582
+ --n-chat-bubble-assistant: var(--n-card);
583
+ --n-chat-bubble-assistant-color: var(--n-ink);
584
+ --n-chat-bubble-radius: var(--n-radius);
585
+ --n-chat-bubble-radius-avatar-side: var(--n-chat-bubble-radius);
586
+ --n-chat-bubble-radius-far-side: var(--n-chat-bubble-radius);
587
+ --n-chat-bubble-padding-block: calc(var(--n-space) * 2);
588
+ --n-chat-bubble-padding-inline: calc(var(--n-space) * 3);
589
+ --n-chat-bubble-max-width: 85%;
590
+
591
+ /* Avatar */
592
+ --n-chat-avatar-size: var(--n-size);
593
+ --n-chat-avatar-background: var(--n-control);
594
+ --n-chat-avatar-color: var(--n-ink-muted);
595
+
596
+ /* Activity */
597
+ --n-chat-activity-color: var(--n-ink-muted);
598
+
599
+ /* Seed */
600
+ --n-chat-seed-gap: var(--n-space);
601
+ --n-chat-seed-padding-block: var(--n-space);
602
+ --n-chat-seed-padding-inline: var(--n-chat-bubble-padding-inline);
603
+
604
+ /* Structured input */
605
+ --n-chat-structured-gap: calc(var(--n-space) * 2);
606
+ --n-chat-structured-padding: calc(var(--n-space) * 3);
607
+
608
+ /* Prose */
609
+ --n-chat-prose-gap: calc(var(--n-space) * 2);
610
+
611
+ /* Component-local tokens (magic number extraction) */
612
+ --n-chat-model-picker-max-width: 12rem;
613
+ --n-chat-activity-max-height: 20rem;
614
+ --n-chat-streaming-opacity: 0.85;
615
+ --n-chat-dot-pulse-duration: 1.2s;
616
+ }
617
+
618
+ /* ╭──────────────────────────────────────────────────────────╮
619
+ │ n-chat │
620
+ │ Chat controller. display:contents — no visual │
621
+ │ presence. The inner n-panel provides structure. │
622
+ │ n-chat wires gateway / gen-UI framework behavior. │
623
+ ╰──────────────────────────────────────────────────────────╯ */
624
+
625
+ :where(n-chat) {
626
+ display: contents;
627
+ }
628
+
629
+ /* ══════════════════════════════════════════════════
630
+ native-chat-panel
631
+ ══════════════════════════════════════════════════ */
632
+
633
+ :where(native-chat-panel) {
634
+ --n-ground: var(--n-panel);
635
+
636
+ /* Section surface token hooks — override on native-chat-panel to theme sections */
637
+ --n-chat-panel-header-background: transparent;
638
+ --n-chat-panel-header-border: var(--n-border-muted);
639
+ --n-chat-panel-header-label-font-weight: inherit;
640
+ --n-chat-panel-header-label-letter-spacing: inherit;
641
+ --n-chat-panel-body-background: transparent;
642
+ --n-chat-panel-footer-background: transparent;
643
+ --n-chat-panel-footer-border: var(--n-border-muted);
644
+
645
+ container-type: inline-size;
646
+ display: flex;
647
+ flex: 1 1 0%;
648
+ min-width: 0;
649
+ flex-direction: column;
650
+ background: var(--n-ground);
651
+ border-radius: var(--n-radius);
652
+ overflow: hidden;
653
+
654
+ font-size: var(--n-font-size);
655
+ line-height: var(--n-line-height);
656
+ }
657
+
658
+ /* ── Aside mode (collapsible side panel) ──
659
+ Base [aside] rule (panel.css) handles: display, width, min-width,
660
+ max-width, overflow, padding, transition + @starting-style.
661
+ Only override what chat-panel needs differently. */
662
+
663
+ :where(native-chat-panel)[aside][open] {
664
+ overflow: visible;
665
+ }
666
+
667
+ /* ── Sub-container integration ── */
668
+
669
+ :where(native-chat-panel) > :where(n-header) {
670
+ background: var(--n-chat-panel-header-background);
671
+ border-bottom: 1px solid var(--n-chat-panel-header-border);
672
+ }
673
+
674
+ :where(native-chat-panel) > :where(n-header) :where([slot="label"]) {
675
+ font-weight: var(--n-chat-panel-header-label-font-weight);
676
+ letter-spacing: var(--n-chat-panel-header-label-letter-spacing);
677
+ }
678
+
679
+ :where(native-chat-panel) :where(.n-chat-panel-header-trailing) {
680
+ display: inline-flex;
681
+ align-items: center;
682
+ gap: calc(var(--n-space) * 2);
683
+ }
684
+
685
+ :where(native-chat-panel) > :where(n-body) {
686
+ background: var(--n-chat-panel-body-background);
687
+ }
688
+
689
+ :where(native-chat-panel) > :where(n-footer) {
690
+ background: var(--n-chat-panel-footer-background);
691
+ border-top: 1px solid var(--n-chat-panel-footer-border);
692
+ }
693
+
694
+ /* ── Model picker ── */
695
+
696
+ :where(native-chat-panel) :where(n-select[data-role="model-picker"]) {
697
+ max-width: var(--n-chat-model-picker-max-width);
698
+ }
699
+
700
+ :where(native-chat-panel) :where(n-select[data-role="model-picker"]) :where(n-button[justify="spread"]) {
701
+ gap: calc(var(--n-space) * 0.5);
702
+ }
703
+
704
+ :where(native-chat-panel) :where(n-select[data-role="model-picker"]) :where([slot="label"]) {
705
+ overflow: hidden;
706
+ text-overflow: ellipsis;
707
+ white-space: nowrap;
708
+ }
709
+
710
+
711
+ /* ── n-chat-content ── */
712
+
713
+ :where(n-chat-content) {
714
+ display: flex;
715
+ flex: 1 1 0%;
716
+ min-width: 0;
717
+ min-height: 0;
718
+ flex-direction: column;
719
+ gap: calc(var(--n-space) * 2);
720
+ }
721
+
722
+ /* ══════════════════════════════════════════════════
723
+ n-chat-feed — scrollable thread coordinator
724
+ ══════════════════════════════════════════════════ */
725
+
726
+ :where(n-chat-feed) {
727
+ display: flex;
728
+ flex-direction: column;
729
+ gap: var(--n-chat-gap);
730
+ flex: 1 1 0%;
731
+ min-height: 0;
732
+ min-width: 0;
733
+ padding-block: calc(var(--n-space) * 4);
734
+ }
735
+
736
+ /* WHY: Opt-in scroll container — prevents layout conflicts when scroll
737
+ ownership belongs to a parent container. */
738
+ [scrollable]:where(n-chat-feed) {
739
+ overflow-y: auto;
740
+ scrollbar-width: thin;
741
+ scroll-behavior: smooth;
742
+ }
743
+
744
+ /* ── Date separator ── */
745
+
746
+ :where(n-chat-feed) > :where(.n-chat-date-separator) {
747
+ display: flex;
748
+ align-items: center;
749
+ justify-content: center;
750
+ padding-block: var(--n-space);
751
+ font-size: var(--n-font-size-sm);
752
+ color: var(--n-ink-muted);
753
+ user-select: none;
754
+ }
755
+
756
+ /* ── Virtual scroll spacers ── */
757
+
758
+ :where(n-chat-feed) > :where(.n-chat-feed-virtual-container) {
759
+ display: flex;
760
+ flex-direction: column;
761
+ gap: var(--n-chat-gap);
762
+ }
763
+
764
+ :where(n-chat-feed) :where(.n-virtual-spacer-top),
765
+ :where(n-chat-feed) :where(.n-virtual-spacer-bottom) {
766
+ flex-shrink: 0;
767
+ }
768
+
769
+ :where(n-chat-feed[hidden]) { display: none; }
770
+
771
+ /* ══════════════════════════════════════════════════
772
+ n-chat-messages — message group (bubble cluster)
773
+ ══════════════════════════════════════════════════ */
774
+
775
+ /* 2×2 grid: avatar | context + bubbles.
776
+ Col 1: avatar (spans both rows, bottom-aligned)
777
+ Col 2 row 1: .n-chat-context — metadata, reasoning, timestamps
778
+ Col 2 row 2: .n-chat-bubbles — message bubbles (flex column) */
779
+ :where(n-chat-messages) {
780
+ display: grid;
781
+ grid-template-columns: auto 1fr;
782
+ grid-template-rows: auto 1fr;
783
+ column-gap: var(--n-chat-message-gap);
784
+ align-self: flex-start;
785
+ max-width: var(--n-chat-bubble-max-width);
786
+ min-width: 0;
787
+ }
788
+
789
+ /* Avatar: col 1, spans both rows, bottom-align */
790
+ :where(n-chat-messages) > :where(n-chat-avatar) {
791
+ grid-column: 1;
792
+ grid-row: 1 / -1;
793
+ align-self: end;
794
+ }
795
+
796
+ /* Context area: col 2, row 1 — metadata above messages */
797
+ :where(n-chat-messages) > :where(.n-chat-context) {
798
+ grid-column: 2;
799
+ grid-row: 1;
800
+ display: flex;
801
+ flex-direction: column;
802
+ gap: var(--n-space);
803
+ min-width: 0;
804
+ }
805
+
806
+ /* Empty context collapses */
807
+ :where(n-chat-messages) > :where(.n-chat-context:empty) {
808
+ display: none;
809
+ }
810
+
811
+ /* Bubbles area: col 2, row 2 — flex column of messages */
812
+ :where(n-chat-messages) > :where(.n-chat-bubbles) {
813
+ grid-column: 2;
814
+ grid-row: 2;
815
+ display: flex;
816
+ flex-direction: column;
817
+ gap: var(--n-space);
818
+ min-width: 0;
819
+ }
820
+
821
+ /* Messages shrink-wrap to content width */
822
+ :where(.n-chat-bubbles) > :where(n-chat-message) {
823
+ width: fit-content;
824
+ max-width: 100%;
825
+ }
826
+
827
+ /* Avatar alignment overrides */
828
+ [avatar-align="top"]:where(n-chat-messages) > :where(n-chat-avatar) {
829
+ align-self: start;
830
+ }
831
+
832
+ [avatar-align="center"]:where(n-chat-messages) > :where(n-chat-avatar) {
833
+ align-self: center;
834
+ }
835
+
836
+ /* User messages: right-aligned, avatar on right */
837
+ [data-role="user"]:where(n-chat-messages) {
838
+ grid-template-columns: 1fr auto;
839
+ align-self: flex-end;
840
+ }
841
+
842
+ [data-role="user"]:where(n-chat-messages) > :where(n-chat-avatar) {
843
+ grid-column: 2;
844
+ }
845
+
846
+ [data-role="user"]:where(n-chat-messages) > :where(.n-chat-context),
847
+ [data-role="user"]:where(n-chat-messages) > :where(.n-chat-bubbles) {
848
+ grid-column: 1;
849
+ }
850
+
851
+ /* User bubbles align to the right edge */
852
+ [data-role="user"]:where(n-chat-messages) :where(.n-chat-bubbles) > :where(n-chat-message) {
853
+ align-self: flex-end;
854
+ }
855
+
856
+ :where(n-chat-messages[hidden]) { display: none; }
857
+
858
+ /* ══════════════════════════════════════════════════
859
+ n-chat-avatar — sender avatar
860
+ ══════════════════════════════════════════════════ */
861
+
862
+ :where(n-chat-avatar) {
863
+ display: inline-flex;
864
+ align-items: center;
865
+ justify-content: center;
866
+ flex-shrink: 0;
867
+
868
+ width: var(--n-chat-avatar-size);
869
+ height: var(--n-chat-avatar-size);
870
+ border-radius: 50%;
871
+ background: var(--n-chat-avatar-background);
872
+ color: var(--n-chat-avatar-color);
873
+
874
+ font-size: calc(var(--n-chat-avatar-size) * 0.4);
875
+ font-weight: var(--n-button-font-weight);
876
+ line-height: 1;
877
+ overflow: hidden;
878
+ user-select: none;
879
+ }
880
+
881
+ :where(n-chat-avatar) > :where(img) {
882
+ width: 100%;
883
+ height: 100%;
884
+ object-fit: cover;
885
+ border-radius: inherit;
886
+ }
887
+
888
+ :where(n-chat-avatar) > :where(n-icon) {
889
+ font-size: calc(var(--n-chat-avatar-size) * 0.5);
890
+ }
891
+
892
+ :where(n-chat-avatar[hidden]) { display: none; }
893
+
894
+ /* ══════════════════════════════════════════════════
895
+ n-chat-message — individual message bubble
896
+ ══════════════════════════════════════════════════ */
897
+
898
+ :where(n-chat-message) {
899
+ display: flex;
900
+ flex-direction: column;
901
+ gap: var(--n-space);
902
+ overflow: hidden;
903
+
904
+ /* Asymmetric radius: assistant = avatar on left */
905
+ border-radius:
906
+ var(--n-chat-bubble-radius-avatar-side)
907
+ var(--n-chat-bubble-radius-far-side)
908
+ var(--n-chat-bubble-radius-far-side)
909
+ var(--n-chat-bubble-radius-avatar-side);
910
+
911
+ background: var(--n-chat-bubble-assistant);
912
+ color: var(--n-chat-bubble-assistant-color);
913
+
914
+ word-wrap: break-word;
915
+ overflow-wrap: break-word;
916
+ }
917
+
918
+ /* User bubble: avatar on right — flip avatar-side / far-side corners */
919
+ [data-role="user"]:where(n-chat-message) {
920
+ border-radius:
921
+ var(--n-chat-bubble-radius-far-side)
922
+ var(--n-chat-bubble-radius-avatar-side)
923
+ var(--n-chat-bubble-radius-avatar-side)
924
+ var(--n-chat-bubble-radius-far-side);
925
+
926
+ background: var(--n-chat-bubble-user);
927
+ color: var(--n-chat-bubble-user-color);
928
+ }
929
+
930
+ /* Streaming status */
931
+ [status="streaming"]:where(n-chat-message) {
932
+ opacity: var(--n-chat-streaming-opacity);
933
+ }
934
+
935
+ /* Error status */
936
+ [status="error"]:where(n-chat-message) {
937
+ border: 1px solid var(--n-border-danger);
938
+ }
939
+
940
+ /* Partial status — stream ended without explicit completion */
941
+ [status="partial"]:where(n-chat-message) {
942
+ border-bottom: 2px dashed var(--n-border-muted);
943
+ }
944
+
945
+ /* Typing status — waiting for first stream chunk */
946
+ [status="typing"]:where(n-chat-message) :where(n-chat-message-text) :where(.n-chat-prose):empty::before {
947
+ content: '\25CF\25CF\25CF';
948
+ letter-spacing: 0.25em;
949
+ color: var(--n-ink-muted);
950
+ animation: n-chat-typing-dots var(--n-chat-dot-pulse-duration, 1.4s) ease-in-out infinite;
951
+ }
952
+
953
+ @keyframes n-chat-typing-dots {
954
+ 0%, 100% { opacity: 0.3; }
955
+ 50% { opacity: 1; }
956
+ }
957
+
958
+ /* ── Message actions toolbar ── */
959
+
960
+ :where(n-chat-message) > :where(n-toolbar[data-role="actions"]) {
961
+ opacity: 0;
962
+ transition: opacity var(--n-duration) var(--n-easing);
963
+ padding-inline: var(--n-chat-bubble-padding-inline);
964
+ }
965
+
966
+ :where(n-chat-message):hover > :where(n-toolbar[data-role="actions"]),
967
+ :where(n-chat-message):focus-within > :where(n-toolbar[data-role="actions"]),
968
+ :where(n-chat-message[force-hover]) > :where(n-toolbar[data-role="actions"]) {
969
+ opacity: 1;
970
+ }
971
+
972
+ /* Partial status — always show actions (contains continue button) */
973
+ [status="partial"]:where(n-chat-message) > :where(n-toolbar[data-role="actions"]) {
974
+ opacity: 1;
975
+ }
976
+
977
+ /* ── Below-bubble popover toolbar ── */
978
+
979
+ /* Popover toolbar: anchored below the message via CSS anchor positioning.
980
+ Toolbar is a child of n-chat-message with popover="manual", rendered in the
981
+ top layer. JS shows/hides via pointerenter/pointerleave + showPopover().
982
+ Entry/exit transition mirrors n-listbox[popover] (perspective + scale). */
983
+ :where(n-chat-message) > :where(n-toolbar[data-role="actions"][popover]) {
984
+ position: fixed;
985
+ inset: auto;
986
+ top: anchor(bottom);
987
+ left: anchor(center);
988
+ translate: -50% 0;
989
+ margin: 2px 0 0;
990
+ width: max-content;
991
+
992
+ transform-origin: top center;
993
+ opacity: 0;
994
+ transform: perspective(800px) scale(0.96) rotateX(-20deg);
995
+
996
+ transition:
997
+ opacity var(--n-duration) var(--n-easing),
998
+ transform var(--n-duration) var(--n-easing),
999
+ display var(--n-duration) var(--n-easing) allow-discrete,
1000
+ overlay var(--n-duration) var(--n-easing) allow-discrete;
1001
+ }
1002
+
1003
+ :where(n-chat-message) > :where(n-toolbar[data-role="actions"][popover]):popover-open {
1004
+ opacity: 1;
1005
+ transform: none;
1006
+ }
1007
+
1008
+ @starting-style {
1009
+ :where(n-chat-message) > :where(n-toolbar[data-role="actions"][popover]):popover-open {
1010
+ opacity: 0;
1011
+ transform: perspective(800px) scale(0.96) rotateX(-20deg);
1012
+ }
1013
+ }
1014
+
1015
+ /* Override n-toolbar display to respect popover hidden state */
1016
+ :where(n-toolbar[data-role="actions"][popover]):not(:popover-open) {
1017
+ display: none;
1018
+ }
1019
+
1020
+ :where(n-chat-message[hidden]) { display: none; }
1021
+
1022
+ /* ══════════════════════════════════════════════════
1023
+ n-chat-message-text — rich text / markdown
1024
+ ══════════════════════════════════════════════════ */
1025
+
1026
+ :where(n-chat-message-text) {
1027
+ display: block;
1028
+ padding-block: var(--n-chat-bubble-padding-block);
1029
+ padding-inline: var(--n-chat-bubble-padding-inline);
1030
+ }
1031
+
1032
+ /* ── Prose reset — typography inside rendered markdown ── */
1033
+
1034
+ :where(n-chat-message-text) :where(.n-chat-prose) {
1035
+ display: flex;
1036
+ flex-direction: column;
1037
+ gap: var(--n-chat-prose-gap);
1038
+ }
1039
+
1040
+ /* Universal block margin reset — flexbox gap handles spacing,
1041
+ so all block-level children must have zero margin */
1042
+ :where(n-chat-message-text) :where(
1043
+ p, h1, h2, h3, h4, h5, h6,
1044
+ ul, ol, li,
1045
+ blockquote, pre, hr,
1046
+ div, figure, figcaption,
1047
+ dl, dt, dd, details, summary
1048
+ ) {
1049
+ margin: 0;
1050
+ }
1051
+
1052
+ :where(n-chat-message-text) :where(h1, h2, h3, h4, h5, h6) {
1053
+ font-weight: var(--n-button-font-weight);
1054
+ line-height: 1.3;
1055
+ }
1056
+
1057
+ :where(n-chat-message-text) :where(h1) { font-size: 1.4em; }
1058
+ :where(n-chat-message-text) :where(h2) { font-size: 1.25em; }
1059
+ :where(n-chat-message-text) :where(h3) { font-size: 1.1em; }
1060
+
1061
+ :where(n-chat-message-text) :where(ul, ol) {
1062
+ padding-inline-start: 1.5em;
1063
+ }
1064
+
1065
+ :where(n-chat-message-text) :where(li) {
1066
+ margin-block: calc(var(--n-space) * 0.5);
1067
+ }
1068
+
1069
+ :where(n-chat-message-text) :where(blockquote) {
1070
+ padding-inline-start: calc(var(--n-space) * 3);
1071
+ border-inline-start: 3px solid var(--n-border-muted);
1072
+ color: var(--n-ink-muted);
1073
+ }
1074
+
1075
+ :where(n-chat-message-text) :where(code) {
1076
+ font-family: var(--n-font-mono);
1077
+ font-size: 0.9em;
1078
+ padding-block: 0.1em;
1079
+ padding-inline: 0.3em;
1080
+ background: var(--n-control);
1081
+ border-radius: calc(var(--n-radius) * 0.5);
1082
+ }
1083
+
1084
+ :where(n-chat-message-text) :where(pre) {
1085
+ padding-block: calc(var(--n-space) * 2);
1086
+ padding-inline: calc(var(--n-space) * 2);
1087
+ background: var(--n-control);
1088
+ border-radius: calc(var(--n-radius) * 0.5);
1089
+ overflow-x: auto;
1090
+ scrollbar-width: thin;
1091
+ }
1092
+
1093
+ :where(n-chat-message-text) :where(pre) :where(code) {
1094
+ padding-block: 0;
1095
+ padding-inline: 0;
1096
+ background: transparent;
1097
+ border-radius: 0;
1098
+ }
1099
+
1100
+ :where(n-chat-message-text) :where(a) {
1101
+ color: var(--n-ink-accent);
1102
+ text-decoration: underline;
1103
+ text-underline-offset: 0.15em;
1104
+ }
1105
+
1106
+ :where(n-chat-message-text) :where(a):hover {
1107
+ color: var(--n-ink-hover);
1108
+ }
1109
+
1110
+ :where(n-chat-message-text) :where(hr) {
1111
+ border: none;
1112
+ border-top: 1px solid var(--n-border-muted);
1113
+ }
1114
+
1115
+ :where(n-chat-message-text[hidden]) { display: none; }
1116
+
1117
+ /* ══════════════════════════════════════════════════
1118
+ n-chat-message-activity — typing / thinking
1119
+ ══════════════════════════════════════════════════ */
1120
+
1121
+ :where(n-chat-message-activity) {
1122
+ display: flex;
1123
+ flex-direction: column;
1124
+ gap: var(--n-space);
1125
+ color: var(--n-chat-activity-color);
1126
+ font-size: var(--n-font-size-sm);
1127
+ padding-block: var(--n-space);
1128
+ padding-inline: var(--n-chat-bubble-padding-inline);
1129
+ align-self: flex-start;
1130
+ }
1131
+
1132
+ :where(n-chat-message-activity) > :where(.n-chat-activity-row) {
1133
+ display: inline-flex;
1134
+ align-items: center;
1135
+ gap: calc(var(--n-space) * 1.5);
1136
+ }
1137
+
1138
+ :where(n-chat-message-activity) :where(.n-chat-activity-time) {
1139
+ font-variant-numeric: tabular-nums;
1140
+ min-width: 2.5em;
1141
+ }
1142
+
1143
+ :where(n-chat-message-activity) :where(.n-chat-activity-sep) {
1144
+ opacity: 0.4;
1145
+ }
1146
+
1147
+ /* Animated dots */
1148
+ :where(n-chat-message-activity) :where(.n-chat-activity-dots) {
1149
+ display: inline-flex;
1150
+ gap: 0.2em;
1151
+ margin-inline-start: 0.25em;
1152
+ }
1153
+
1154
+ :where(n-chat-message-activity) :where(.n-chat-activity-dots) > :where(i) {
1155
+ display: block;
1156
+ width: 0.25em;
1157
+ height: 0.25em;
1158
+ border-radius: 50%;
1159
+ background: currentColor;
1160
+ animation: n-chat-dot-pulse var(--n-chat-dot-pulse-duration) ease-in-out infinite;
1161
+ }
1162
+
1163
+ :where(n-chat-message-activity) :where(.n-chat-activity-dots) > :where(i:nth-child(2)) {
1164
+ animation-delay: 0.2s;
1165
+ }
1166
+
1167
+ :where(n-chat-message-activity) :where(.n-chat-activity-dots) > :where(i:nth-child(3)) {
1168
+ animation-delay: 0.4s;
1169
+ }
1170
+
1171
+ @keyframes n-chat-dot-pulse {
1172
+ 0%, 60%, 100% { opacity: 0.3; transform: scale(0.8); }
1173
+ 30% { opacity: 1; transform: scale(1); }
1174
+ }
1175
+
1176
+ /* Expandable state */
1177
+ :where(n-chat-message-activity) > :where(.n-chat-activity-row) {
1178
+ cursor: default;
1179
+ }
1180
+
1181
+ [expandable]:where(n-chat-message-activity) > :where(.n-chat-activity-row) {
1182
+ cursor: pointer;
1183
+ }
1184
+
1185
+ [expandable]:where(n-chat-message-activity) > :where(.n-chat-activity-row)::before {
1186
+ content: '▶';
1187
+ font-size: 0.65em;
1188
+ transition: transform var(--n-duration) var(--n-easing);
1189
+ }
1190
+
1191
+ [expanded][expandable]:where(n-chat-message-activity) > :where(.n-chat-activity-row)::before {
1192
+ transform: rotate(90deg);
1193
+ }
1194
+
1195
+ :where(n-chat-message-activity) > :where(.n-chat-activity-content) {
1196
+ padding-inline-start: calc(var(--n-space) * 3);
1197
+ font-family: var(--n-font-mono);
1198
+ font-size: var(--n-font-size-sm);
1199
+ max-height: var(--n-chat-activity-max-height);
1200
+ overflow-y: auto;
1201
+ scrollbar-width: thin;
1202
+ }
1203
+
1204
+ :where(n-chat-message-activity[hidden]) { display: none; }
1205
+
1206
+ @media (prefers-reduced-motion: reduce) {
1207
+ :where(n-chat-message-activity) :where(.n-chat-activity-dots) > :where(i) {
1208
+ animation: none;
1209
+ }
1210
+ }
1211
+
1212
+ /* ══════════════════════════════════════════════════
1213
+ n-chat-message-seed — suggestion chips
1214
+ ══════════════════════════════════════════════════ */
1215
+
1216
+ :where(n-chat-message-seed) {
1217
+ display: block;
1218
+ padding-block: var(--n-chat-seed-padding-block);
1219
+ padding-inline: var(--n-chat-seed-padding-inline);
1220
+ align-self: flex-start;
1221
+ }
1222
+
1223
+ :where(n-chat-message-seed) > :where(n-stack) {
1224
+ gap: var(--n-chat-seed-gap);
1225
+ }
1226
+
1227
+ :where(n-chat-message-seed)[aria-disabled="true"] {
1228
+ pointer-events: none;
1229
+ color: var(--n-color-disabled);
1230
+ cursor: not-allowed;
1231
+ }
1232
+
1233
+ :where(n-chat-message-seed[hidden]) { display: none; }
1234
+
1235
+ /* ══════════════════════════════════════════════════
1236
+ n-chat-message-genui — schema-rendered UI
1237
+ ══════════════════════════════════════════════════ */
1238
+
1239
+ :where(n-chat-message-genui) {
1240
+ display: block;
1241
+ min-width: 0;
1242
+ }
1243
+
1244
+ :where(n-chat-message-genui) > :where(.n-chat-genui-container) {
1245
+ display: flex;
1246
+ flex-direction: column;
1247
+ gap: var(--n-space);
1248
+ }
1249
+
1250
+ :where(n-chat-message-genui) :where(.n-chat-genui-error) {
1251
+ padding-block: var(--n-space);
1252
+ padding-inline: var(--n-space);
1253
+ color: var(--n-ink-danger);
1254
+ font-size: var(--n-font-size-sm);
1255
+ }
1256
+
1257
+ :where(n-chat-message-genui) :where(n-card[data-role="preview"]) {
1258
+ display: flex;
1259
+ align-items: center;
1260
+ justify-content: space-between;
1261
+ gap: calc(var(--n-space) * 2);
1262
+ }
1263
+
1264
+ :where(n-chat-message-genui[hidden]) { display: none; }
1265
+
1266
+ /* ══════════════════════════════════════════════════
1267
+ n-chat-input-structured — multi-choice input
1268
+ ══════════════════════════════════════════════════ */
1269
+
1270
+ :where(n-chat-input-structured) {
1271
+ display: flex;
1272
+ flex-direction: column;
1273
+ gap: var(--n-chat-structured-gap);
1274
+ padding-block: var(--n-chat-structured-padding);
1275
+ padding-inline: var(--n-chat-structured-padding);
1276
+ --n-background: var(--n-card);
1277
+ background: var(--n-background);
1278
+ border-radius: var(--n-chat-bubble-radius);
1279
+ align-self: stretch;
1280
+ }
1281
+
1282
+ :where(n-chat-input-structured) > :where(.n-chat-structured-question) {
1283
+ font-weight: var(--n-button-font-weight);
1284
+ }
1285
+
1286
+ :where(n-chat-input-structured) > :where(n-stack) {
1287
+ flex: 0 0 auto;
1288
+ gap: var(--n-chat-seed-gap);
1289
+ }
1290
+
1291
+ :where(n-chat-input-structured) > :where(.n-chat-structured-actions) {
1292
+ display: flex;
1293
+ align-items: center;
1294
+ justify-content: flex-end;
1295
+ gap: var(--n-space);
1296
+ }
1297
+
1298
+ :where(n-chat-input-structured)[aria-disabled="true"] {
1299
+ pointer-events: none;
1300
+ color: var(--n-color-disabled);
1301
+ cursor: not-allowed;
1302
+ }
1303
+
1304
+ :where(n-chat-input-structured[hidden]) { display: none; }
1305
+
1306
+ /* ══════════════════════════════════════════════════
1307
+ n-chat-input — composer
1308
+ ══════════════════════════════════════════════════ */
1309
+
1310
+ :where(n-chat-input) {
1311
+ display: flex;
1312
+ flex: 1 1 0%;
1313
+ flex-direction: column;
1314
+ min-width: 0;
1315
+ }
1316
+
1317
+ /* Compact: single row */
1318
+ [compact]:where(n-chat-input) {
1319
+ flex-direction: row;
1320
+ align-items: center;
1321
+ }
1322
+
1323
+ /* Textarea inside input — fully transparent, no padding */
1324
+ :where(n-chat-input) > :where(n-textarea) {
1325
+ --n-background: transparent;
1326
+ --n-background-hover: transparent;
1327
+ --n-background-active: transparent;
1328
+ --n-border-color: transparent;
1329
+ --n-border-color-hover: transparent;
1330
+ --n-border-color-active: transparent;
1331
+
1332
+ padding-block: 0;
1333
+ padding-inline: 0;
1334
+ border: none;
1335
+ border-radius: 0;
1336
+ resize: none;
1337
+ }
1338
+
1339
+ :where(n-chat-input) > :where(n-textarea):not(:state(empty)),
1340
+ :where(n-chat-input) > :where(n-textarea):not(:state(empty)):hover {
1341
+ background: transparent;
1342
+ border-color: transparent;
1343
+ }
1344
+
1345
+ :where(n-chat-input) > :where(n-textarea):focus {
1346
+ border-color: transparent;
1347
+ outline: none;
1348
+ }
1349
+
1350
+ /* ── n-chat-input-attachments ── */
1351
+
1352
+ :where(n-chat-input-attachments) {
1353
+ display: flex;
1354
+ flex-wrap: wrap;
1355
+ gap: calc(var(--n-space) * 2);
1356
+ }
1357
+
1358
+ /* ── n-chat-input-actions ── */
1359
+
1360
+ :where(n-chat-input-actions) {
1361
+ display: flex;
1362
+ align-items: center;
1363
+ justify-content: flex-end;
1364
+ gap: calc(var(--n-space) * 2);
1365
+ min-width: 0;
1366
+ }
1367
+
1368
+ [compact]:where(n-chat-input) > :where(n-chat-input-actions) {
1369
+ flex: none;
1370
+ }
1371
+
1372
+ }
1373
+
1374
+ /* ════════════════════════════════════════════════════
1375
+ .n-chat-starter — Starter surface preset
1376
+ ════════════════════════════════════════════════════
1377
+
1378
+ Harmonizes seed + structured input spacing when composed
1379
+ together as a starter surface (e.g. inside n-card, n-body).
1380
+
1381
+ Add `compact` attribute for tighter spacing (small cards,
1382
+ inline starters, sidebars).
1383
+
1384
+ Usage:
1385
+ <n-card class="n-chat-starter">
1386
+ <n-body>
1387
+ <n-chat-message-seed></n-chat-message-seed>
1388
+ <n-chat-input-structured question="..."></n-chat-input-structured>
1389
+ </n-body>
1390
+ </n-card>
1391
+ */
1392
+
1393
+ .n-chat-starter {
1394
+ --n-chat-seed-padding-inline: 0;
1395
+ --n-chat-seed-padding-block: 0;
1396
+ --n-chat-structured-padding: calc(var(--n-space) * 2);
1397
+ --n-chat-structured-gap: var(--n-space);
1398
+ }
1399
+
1400
+ .n-chat-starter[compact] {
1401
+ --n-chat-seed-gap: calc(var(--n-space) * 0.5);
1402
+ --n-chat-structured-padding: var(--n-space);
1403
+ --n-chat-structured-gap: calc(var(--n-space) * 0.5);
1404
+ }