sliccy 0.1.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 (63) hide show
  1. package/LICENSE +191 -0
  2. package/README.md +512 -0
  3. package/dist/cli/chrome-launch.d.ts +47 -0
  4. package/dist/cli/chrome-launch.js +324 -0
  5. package/dist/cli/cli-log-dedup.d.ts +19 -0
  6. package/dist/cli/cli-log-dedup.js +62 -0
  7. package/dist/cli/electron-controller.d.ts +38 -0
  8. package/dist/cli/electron-controller.js +287 -0
  9. package/dist/cli/electron-main.d.ts +1 -0
  10. package/dist/cli/electron-main.js +183 -0
  11. package/dist/cli/electron-runtime.d.ts +58 -0
  12. package/dist/cli/electron-runtime.js +133 -0
  13. package/dist/cli/file-logger.d.ts +38 -0
  14. package/dist/cli/file-logger.js +207 -0
  15. package/dist/cli/index.d.ts +2 -0
  16. package/dist/cli/index.js +1023 -0
  17. package/dist/cli/launch-url.d.ts +9 -0
  18. package/dist/cli/launch-url.js +34 -0
  19. package/dist/cli/qa-setup.d.ts +1 -0
  20. package/dist/cli/qa-setup.js +36 -0
  21. package/dist/cli/release-package.d.ts +17 -0
  22. package/dist/cli/release-package.js +232 -0
  23. package/dist/cli/runtime-flags.d.ts +21 -0
  24. package/dist/cli/runtime-flags.js +154 -0
  25. package/dist/cli/sync-release-version.d.ts +2 -0
  26. package/dist/cli/sync-release-version.js +34 -0
  27. package/dist/tray-url-shared.d.ts +11 -0
  28. package/dist/tray-url-shared.js +56 -0
  29. package/dist/ui/assets/___vite-browser-external_commonjs-proxy-7ULRRj69.js +1 -0
  30. package/dist/ui/assets/__vite-browser-external-D7Ct-6yo.js +1 -0
  31. package/dist/ui/assets/addon-fit-DOCEibfw.js +12 -0
  32. package/dist/ui/assets/bsh-watchdog-D19WB0U1.js +2 -0
  33. package/dist/ui/assets/index-BVQAdk-Y.js +8 -0
  34. package/dist/ui/assets/index-BjJrFm2K.js +43 -0
  35. package/dist/ui/assets/index-C1dglHrI.js +3 -0
  36. package/dist/ui/assets/index-D3Enm5ux.js +13091 -0
  37. package/dist/ui/assets/index-D7hjyFh1.js +2 -0
  38. package/dist/ui/assets/index-D8uSC2sl.js +45 -0
  39. package/dist/ui/assets/index-DEglHp2j.js +1 -0
  40. package/dist/ui/assets/index-DvjzakYY.js +14406 -0
  41. package/dist/ui/assets/index-deZeJCgO.js +1 -0
  42. package/dist/ui/assets/index-mz3VYh0I.js +131 -0
  43. package/dist/ui/assets/index-r2m8Dpaz.js +54 -0
  44. package/dist/ui/assets/index-ygVJ3eFG.js +11 -0
  45. package/dist/ui/assets/lick-manager-proxy-G3WuipZ-.js +1 -0
  46. package/dist/ui/assets/magic-string.es-BPLJknd7.js +10 -0
  47. package/dist/ui/assets/oauth-service-DIahkF-o.js +1 -0
  48. package/dist/ui/assets/offscreen-client-ByVIJGHW.js +1 -0
  49. package/dist/ui/assets/pdfjs-uyZuKmOq.js +59 -0
  50. package/dist/ui/assets/pyodide-D73G_Ygx.mjs +4 -0
  51. package/dist/ui/assets/sql-wasm-BggYNCID.js +2 -0
  52. package/dist/ui/assets/stream-lEC9OYG2.js +1 -0
  53. package/dist/ui/assets/xterm-Bb8UKAlD.js +27 -0
  54. package/dist/ui/assets/xterm-DOrYoP_4.css +32 -0
  55. package/dist/ui/electron-overlay-entry.js +360 -0
  56. package/dist/ui/favicon.png +0 -0
  57. package/dist/ui/fonts/AdobeClean-Bold.otf +0 -0
  58. package/dist/ui/fonts/AdobeClean-ExtraBold.otf +0 -0
  59. package/dist/ui/fonts/AdobeClean-Medium.otf +0 -0
  60. package/dist/ui/fonts/AdobeClean-Regular.otf +0 -0
  61. package/dist/ui/index.html +1981 -0
  62. package/dist/ui/preview-sw.js +4 -0
  63. package/package.json +81 -0
@@ -0,0 +1,1981 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>slicc</title>
7
+ <link rel="icon" type="image/png" href="/favicon.png" />
8
+ <style>
9
+ /* ================================================================== */
10
+ /* Adobe Clean — @font-face (local dev) */
11
+ /* ================================================================== */
12
+ @font-face {
13
+ font-family: 'Adobe Clean';
14
+ src: url('/fonts/AdobeClean-Regular.otf') format('opentype');
15
+ font-weight: 400; font-style: normal; font-display: swap;
16
+ }
17
+ @font-face {
18
+ font-family: 'Adobe Clean';
19
+ src: url('/fonts/AdobeClean-Medium.otf') format('opentype');
20
+ font-weight: 500; font-style: normal; font-display: swap;
21
+ }
22
+ @font-face {
23
+ font-family: 'Adobe Clean';
24
+ src: url('/fonts/AdobeClean-Bold.otf') format('opentype');
25
+ font-weight: 700; font-style: normal; font-display: swap;
26
+ }
27
+ @font-face {
28
+ font-family: 'Adobe Clean';
29
+ src: url('/fonts/AdobeClean-ExtraBold.otf') format('opentype');
30
+ font-weight: 800; font-style: normal; font-display: swap;
31
+ }
32
+
33
+ /* ================================================================== */
34
+ /* Spectrum 2 Design Tokens — Dark Theme */
35
+ /* SLICC brand overrides applied where appropriate */
36
+ /* ================================================================== */
37
+ :root {
38
+ /* ── S2 Gray Scale (Dark Theme — inverted) ───────────────── */
39
+ --s2-gray-25: #1a1a1a;
40
+ --s2-gray-50: #1e1e1e;
41
+ --s2-gray-75: #252525;
42
+ --s2-gray-100: #2c2c2c;
43
+ --s2-gray-200: #3a3a3a;
44
+ --s2-gray-300: #4a4a4a;
45
+ --s2-gray-400: #5a5a5a;
46
+ --s2-gray-500: #6e6e6e;
47
+ --s2-gray-600: #8a8a8a;
48
+ --s2-gray-700: #a1a1a1;
49
+ --s2-gray-800: #cfcfcf;
50
+ --s2-gray-900: #e8e8e8;
51
+ --s2-gray-1000: #ffffff;
52
+
53
+ /* ── S2 Semantic Backgrounds (Dark) ──────────────────────── */
54
+ --s2-bg-base: var(--s2-gray-25);
55
+ --s2-bg-layer-1: var(--s2-gray-50);
56
+ --s2-bg-layer-2: var(--s2-gray-75);
57
+ --s2-bg-elevated: var(--s2-gray-100);
58
+ --s2-bg-sunken: #141414;
59
+
60
+ /* ── S2 Content Colors (Dark) ────────────────────────────── */
61
+ --s2-content-default: var(--s2-gray-900);
62
+ --s2-content-secondary: var(--s2-gray-700);
63
+ --s2-content-tertiary: var(--s2-gray-600);
64
+ --s2-content-disabled: var(--s2-gray-400);
65
+
66
+ /* ── SLICC Brand Colors ──────────────────────────────────── */
67
+ --slicc-cone: #ef7000;
68
+ --slicc-scoop-blue: #3562ff;
69
+ --slicc-scoop-purple: #a962e8;
70
+ --slicc-scoop-teal: #2db9be;
71
+ --slicc-accent: #15d675;
72
+
73
+ /* ── S2 Accent (mapped to SLICC brand blue) ─────────────── */
74
+ --s2-accent: var(--slicc-scoop-blue);
75
+ --s2-accent-hover: #4a75ff;
76
+ --s2-accent-down: #2a52e0;
77
+
78
+ /* ── S2 Semantic Colors ──────────────────────────────────── */
79
+ --s2-negative: #e34850;
80
+ --s2-positive: #2d9d78;
81
+ --s2-informative: var(--slicc-scoop-blue);
82
+ --s2-notice: #e68619;
83
+
84
+ /* ── S2 Border Colors ────────────────────────────────────── */
85
+ --s2-border-default: var(--s2-gray-300);
86
+ --s2-border-subtle: var(--s2-gray-200);
87
+ --s2-border-focus: var(--s2-accent);
88
+
89
+ /* ── S2 Typography ───────────────────────────────────────── */
90
+ --s2-font-family: 'Adobe Clean', 'Source Sans Pro', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
91
+ --s2-font-mono: 'Source Code Pro', 'JetBrains Mono', 'Fira Code', 'Cascadia Code', monospace;
92
+
93
+ /* Font sizes */
94
+ --s2-font-size-50: 11px;
95
+ --s2-font-size-75: 12px;
96
+ --s2-font-size-100: 14px;
97
+ --s2-font-size-200: 16px;
98
+ --s2-font-size-300: 18px;
99
+ --s2-font-size-400: 20px;
100
+ --s2-font-size-500: 22px;
101
+ --s2-font-size-600: 25px;
102
+
103
+ /* Line heights */
104
+ --s2-line-height-50: 14px;
105
+ --s2-line-height-75: 16px;
106
+ --s2-line-height-100: 18px;
107
+ --s2-line-height-200: 20px;
108
+ --s2-line-height-300: 22px;
109
+
110
+ /* ── S2 Spacing ──────────────────────────────────────────── */
111
+ --s2-spacing-50: 4px;
112
+ --s2-spacing-75: 6px;
113
+ --s2-spacing-100: 8px;
114
+ --s2-spacing-200: 12px;
115
+ --s2-spacing-300: 16px;
116
+ --s2-spacing-400: 24px;
117
+ --s2-spacing-500: 32px;
118
+ --s2-spacing-600: 40px;
119
+
120
+ /* ── S2 Radii ────────────────────────────────────────────── */
121
+ --s2-radius-s: 4px;
122
+ --s2-radius-default: 8px;
123
+ --s2-radius-l: 10px;
124
+ --s2-radius-xl: 16px;
125
+ --s2-radius-pill: 9999px;
126
+
127
+ /* ── S2 Shadows (Dark) ───────────────────────────────────── */
128
+ --s2-shadow-elevated: 0 4px 16px rgba(0,0,0,0.4), 0 1px 4px rgba(0,0,0,0.3);
129
+ --s2-shadow-container: 0 1px 4px rgba(0,0,0,0.2);
130
+
131
+ /* ── S2 Transitions ──────────────────────────────────────── */
132
+ --s2-transition-default: 130ms ease;
133
+
134
+ /* ── Header height ───────────────────────────────────────── */
135
+ --s2-header-height: 48px;
136
+ }
137
+
138
+ /* ================================================================== */
139
+ /* Spectrum 2 Design Tokens — Light Theme */
140
+ /* Applied via .theme-light class on <html> by src/ui/theme.ts */
141
+ /* ================================================================== */
142
+ :root.theme-light {
143
+ /* ── S2 Gray Scale (Light Theme) ─────────────────────────── */
144
+ --s2-gray-25: #ffffff;
145
+ --s2-gray-50: #f8f8f8;
146
+ --s2-gray-75: #f0f0f0;
147
+ --s2-gray-100: #e8e8e8;
148
+ --s2-gray-200: #d6d6d6;
149
+ --s2-gray-300: #c4c4c4;
150
+ --s2-gray-400: #a1a1a1;
151
+ --s2-gray-500: #8a8a8a;
152
+ --s2-gray-600: #6e6e6e;
153
+ --s2-gray-700: #5a5a5a;
154
+ --s2-gray-800: #3a3a3a;
155
+ --s2-gray-900: #1a1a1a;
156
+ --s2-gray-1000: #000000;
157
+
158
+ /* ── S2 Semantic Backgrounds (Light) ─────────────────────── */
159
+ --s2-bg-sunken: #f0f0f0;
160
+
161
+ /* ── S2 Accent (slightly darker for light bg contrast) ───── */
162
+ --s2-accent: #2b54db;
163
+ --s2-accent-hover: #1e44c4;
164
+ --s2-accent-down: #1a3aaa;
165
+
166
+ /* ── S2 Semantic Colors (Light — slightly adjusted) ──────── */
167
+ --s2-negative: #d73220;
168
+ --s2-positive: #268e6c;
169
+ --s2-notice: #d17a00;
170
+
171
+ /* ── S2 Shadows (Light) ──────────────────────────────────── */
172
+ --s2-shadow-elevated: 0 4px 16px rgba(0,0,0,0.10), 0 1px 4px rgba(0,0,0,0.06);
173
+ --s2-shadow-container: 0 1px 4px rgba(0,0,0,0.06);
174
+ }
175
+
176
+ /* Syntax tokens — light theme overrides */
177
+ .theme-light .tok-keyword { color: #8839ef; }
178
+ .theme-light .tok-string { color: #40a02b; }
179
+ .theme-light .tok-number { color: #d05d1a; }
180
+ .theme-light .tok-comment { color: var(--s2-gray-500); }
181
+ .theme-light .tok-punct { color: #1e66f5; }
182
+ .theme-light .tok-fn { color: #2b6cb0; }
183
+
184
+ /* Tooltip inverts in light mode */
185
+ .theme-light [data-tooltip]::after {
186
+ background: var(--s2-gray-900);
187
+ color: var(--s2-gray-25);
188
+ }
189
+ .theme-light [data-tooltip]::before {
190
+ border-bottom-color: var(--s2-gray-900);
191
+ }
192
+
193
+ /* Scrollbar lighter */
194
+ .theme-light ::-webkit-scrollbar-thumb { background: var(--s2-gray-300); }
195
+ .theme-light ::-webkit-scrollbar-thumb:hover { background: var(--s2-gray-400); }
196
+
197
+ /* ================================================================== */
198
+ /* Reset & Base */
199
+ /* ================================================================== */
200
+ *, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; }
201
+ html, body { height: 100%; overflow: hidden; }
202
+ body {
203
+ font-family: var(--s2-font-family);
204
+ background: var(--s2-bg-base);
205
+ color: var(--s2-content-default);
206
+ font-size: var(--s2-font-size-100);
207
+ line-height: 1.5;
208
+ }
209
+ #app { height: 100%; display: flex; flex-direction: column; }
210
+
211
+ /* S2 focus ring */
212
+ :focus-visible {
213
+ outline: 2px solid var(--s2-accent);
214
+ outline-offset: 2px;
215
+ }
216
+
217
+ /* S2 scrollbar styling */
218
+ ::-webkit-scrollbar { width: 6px; height: 6px; }
219
+ ::-webkit-scrollbar-track { background: transparent; }
220
+ ::-webkit-scrollbar-thumb { background: var(--s2-gray-300); border-radius: 3px; }
221
+ ::-webkit-scrollbar-thumb:hover { background: var(--s2-gray-400); }
222
+
223
+ /* ================================================================== */
224
+ /* Layout */
225
+ /* ================================================================== */
226
+ .layout { display: flex; flex: 1; min-height: 0; }
227
+ .layout__scoops {
228
+ display: flex; flex-direction: column;
229
+ min-width: 180px; max-width: 300px;
230
+ background: var(--s2-bg-layer-1);
231
+ }
232
+ .layout__left { display: flex; flex-direction: column; min-width: 320px; }
233
+ .layout__right {
234
+ display: flex; flex-direction: column; min-width: 240px;
235
+ overflow: hidden; background: var(--s2-bg-layer-1);
236
+ }
237
+ .layout__divider {
238
+ width: 1px; cursor: col-resize;
239
+ background: var(--s2-border-subtle);
240
+ flex-shrink: 0; transition: background var(--s2-transition-default);
241
+ position: relative;
242
+ }
243
+ .layout__divider::after {
244
+ content: ''; position: absolute; inset: 0; left: -3px; right: -3px;
245
+ }
246
+ .layout__divider:hover, .layout__divider.active {
247
+ background: var(--s2-accent);
248
+ }
249
+
250
+ /* ================================================================== */
251
+ /* Header (S2 App Frame Header — 48px) */
252
+ /* ================================================================== */
253
+ .header {
254
+ display: flex; align-items: center; justify-content: space-between;
255
+ padding: 0 var(--s2-spacing-300);
256
+ height: var(--s2-header-height); min-height: var(--s2-header-height);
257
+ background: var(--s2-bg-layer-1);
258
+ border-bottom: 1px solid var(--s2-border-subtle);
259
+ flex-shrink: 0;
260
+ z-index: 10;
261
+ }
262
+ .header__logo {
263
+ width: 22px; height: 22px;
264
+ margin-right: var(--s2-spacing-75);
265
+ flex-shrink: 0;
266
+ transition: viewBox 300ms ease;
267
+ }
268
+
269
+ /* Logo scoop entrance animation — drops in from above with bounce */
270
+ .logo-scoop-enter {
271
+ transform-box: fill-box;
272
+ transform-origin: center;
273
+ animation: scoop-drop 600ms cubic-bezier(0.34, 1.56, 0.64, 1) both;
274
+ }
275
+ @keyframes scoop-drop {
276
+ 0% { transform: translateY(-18px) scale(0.2); opacity: 0; }
277
+ 40% { transform: translateY(1px) scale(1.15); opacity: 1; }
278
+ 60% { transform: translateY(-2px) scale(0.95); }
279
+ 80% { transform: translateY(0.5px) scale(1.03); }
280
+ 100% { transform: translateY(0) scale(1); opacity: 1; }
281
+ }
282
+ /* Existing scoops wiggle when a new one arrives */
283
+ .logo-scoop-wiggle {
284
+ transform-box: fill-box;
285
+ transform-origin: center;
286
+ animation: scoop-wiggle 500ms ease both;
287
+ }
288
+ @keyframes scoop-wiggle {
289
+ 0% { transform: translateY(0); }
290
+ 20% { transform: translateY(1.5px); }
291
+ 40% { transform: translateY(-1px); }
292
+ 60% { transform: translateY(0.5px); }
293
+ 100% { transform: translateY(0); }
294
+ }
295
+ /* Cone squash when new scoop lands */
296
+ .logo-cone-squash {
297
+ transform-box: fill-box;
298
+ transform-origin: top center;
299
+ animation: cone-squash 500ms ease both;
300
+ }
301
+ @keyframes cone-squash {
302
+ 0% { transform: scaleY(1) scaleX(1); }
303
+ 30% { transform: scaleY(0.92) scaleX(1.06); }
304
+ 60% { transform: scaleY(1.03) scaleX(0.98); }
305
+ 100% { transform: scaleY(1) scaleX(1); }
306
+ }
307
+ .header__title {
308
+ font-size: var(--s2-font-size-100);
309
+ font-weight: 800;
310
+ color: var(--s2-content-default);
311
+ letter-spacing: -0.01em;
312
+ }
313
+ .header__actions { display: flex; gap: 2px; align-items: center; }
314
+ .header__separator {
315
+ width: 1px; height: 20px;
316
+ background: var(--s2-border-subtle);
317
+ margin: 0 var(--s2-spacing-75);
318
+ }
319
+
320
+ /* S2 Ghost Action Button — icon-only pill */
321
+ .header__btn {
322
+ background: transparent;
323
+ color: var(--s2-content-secondary);
324
+ border: none;
325
+ border-radius: var(--s2-radius-pill);
326
+ padding: 0;
327
+ width: 32px; height: 32px;
328
+ display: inline-flex; align-items: center; justify-content: center;
329
+ font-size: var(--s2-font-size-100);
330
+ font-family: var(--s2-font-family);
331
+ cursor: pointer;
332
+ transition: background var(--s2-transition-default), color var(--s2-transition-default), transform var(--s2-transition-default);
333
+ flex-shrink: 0;
334
+ position: relative;
335
+ }
336
+ .header__btn:hover {
337
+ background: var(--s2-gray-200);
338
+ color: var(--s2-content-default);
339
+ }
340
+ .header__btn:active { transform: scale(0.92); }
341
+ .header__btn svg { width: 16px; height: 16px; }
342
+ /* Text variant for standalone mode labels */
343
+ .header__btn--text {
344
+ width: auto; padding: var(--s2-spacing-50) var(--s2-spacing-200);
345
+ font-size: var(--s2-font-size-75); font-weight: 500;
346
+ border-radius: var(--s2-radius-default);
347
+ gap: var(--s2-spacing-75);
348
+ }
349
+
350
+ /* ================================================================== */
351
+ /* S2 Tooltip — neutral variant with tip arrow (bottom placement) */
352
+ /* ================================================================== */
353
+ [data-tooltip] { position: relative; }
354
+ /* Tooltip body */
355
+ [data-tooltip]::after {
356
+ content: attr(data-tooltip);
357
+ position: absolute;
358
+ top: calc(100% + 8px); left: 50%;
359
+ transform: translateX(-50%) translateY(-4px);
360
+ padding: 4px 8px;
361
+ max-width: 160px;
362
+ background: var(--s2-gray-900);
363
+ color: var(--s2-gray-25);
364
+ font-size: 11px; font-weight: 500;
365
+ font-family: var(--s2-font-family);
366
+ white-space: normal; text-align: center;
367
+ border-radius: var(--s2-radius-s);
368
+ pointer-events: none;
369
+ opacity: 0;
370
+ transition: opacity 130ms ease, transform 130ms ease;
371
+ z-index: 1000;
372
+ line-height: 1.3;
373
+ }
374
+ /* Tip arrow */
375
+ [data-tooltip]::before {
376
+ content: '';
377
+ position: absolute;
378
+ top: calc(100% + 0px); left: 50%;
379
+ transform: translateX(-50%) translateY(-4px);
380
+ border: 4px solid transparent;
381
+ border-bottom-color: var(--s2-gray-900);
382
+ pointer-events: none;
383
+ opacity: 0;
384
+ transition: opacity 130ms ease, transform 130ms ease;
385
+ z-index: 1000;
386
+ }
387
+ [data-tooltip]:hover::after,
388
+ [data-tooltip]:hover::before {
389
+ opacity: 1;
390
+ transform: translateX(-50%) translateY(0);
391
+ transition-delay: 300ms;
392
+ }
393
+ [data-tooltip]:active::after,
394
+ [data-tooltip]:active::before { opacity: 0; transition-delay: 0ms; }
395
+
396
+ /* ================================================================== */
397
+ /* Chat panel */
398
+ /* ================================================================== */
399
+ .chat { display: flex; flex-direction: column; flex: 1; min-height: 0; background: var(--s2-bg-base); position: relative; }
400
+ .chat__messages {
401
+ flex: 1; overflow-y: auto; padding: var(--s2-spacing-300);
402
+ display: flex; flex-direction: column; gap: var(--s2-spacing-100);
403
+ }
404
+
405
+ /* Jump pill — shown when auto-scroll is detached */
406
+ .chat__jump-pill {
407
+ position: absolute; bottom: 68px; left: 50%; transform: translateX(-50%);
408
+ background: var(--s2-bg-layer-2); color: var(--s2-content-default); border: 1px solid var(--s2-border-subtle);
409
+ border-radius: var(--s2-radius-l); padding: 5px 14px; font-size: 12px;
410
+ cursor: pointer; z-index: 10;
411
+ opacity: 0; pointer-events: none; transition: opacity 0.2s ease;
412
+ }
413
+ .chat__jump-pill--visible { opacity: 1; pointer-events: auto; }
414
+ .chat__jump-pill:hover { background: var(--s2-bg-elevated); }
415
+
416
+ /* S2 Message bubbles — user right-aligned, assistant left-aligned */
417
+ .msg {
418
+ padding: var(--s2-spacing-100) 0;
419
+ max-width: 100%; word-wrap: break-word;
420
+ }
421
+ .msg--user {
422
+ align-self: flex-end;
423
+ background: var(--s2-bg-layer-2);
424
+ border-radius: var(--s2-radius-default);
425
+ padding: var(--s2-spacing-100) var(--s2-spacing-200);
426
+ max-width: 85%;
427
+ }
428
+ .msg-group--continuation .msg--user { padding-left: 0; }
429
+ .msg--assistant {
430
+ background: transparent;
431
+ align-self: stretch;
432
+ }
433
+ .msg--assistant .msg__content {
434
+ white-space: normal;
435
+ color: var(--s2-gray-800);
436
+ }
437
+ .msg--assistant .msg__error {
438
+ margin: var(--s2-spacing-75) 0;
439
+ }
440
+ .msg--assistant .msg__error-label {
441
+ display: inline-flex;
442
+ align-items: center;
443
+ gap: 6px;
444
+ color: var(--s2-negative);
445
+ font-size: 10px;
446
+ font-weight: 600;
447
+ font-family: var(--s2-font-mono);
448
+ text-transform: uppercase;
449
+ letter-spacing: 0.04em;
450
+ }
451
+ .msg--assistant .msg__error-label::before {
452
+ content: '!';
453
+ width: 16px;
454
+ height: 16px;
455
+ border-radius: var(--s2-radius-s);
456
+ display: inline-flex;
457
+ align-items: center;
458
+ justify-content: center;
459
+ background: color-mix(in srgb, var(--s2-negative) 18%, transparent);
460
+ border: 1px solid color-mix(in srgb, var(--s2-negative) 45%, var(--s2-border-subtle));
461
+ }
462
+ .msg--assistant .msg__error-body {
463
+ margin-top: 2px;
464
+ padding: var(--s2-spacing-75);
465
+ border-left: 2px solid color-mix(in srgb, var(--s2-negative) 60%, var(--s2-border-subtle));
466
+ background: color-mix(in srgb, var(--s2-negative) 8%, var(--s2-bg-sunken));
467
+ border-radius: var(--s2-radius-s);
468
+ color: var(--s2-content-secondary);
469
+ font-family: var(--s2-font-mono);
470
+ font-size: var(--s2-font-size-50);
471
+ white-space: pre-wrap;
472
+ overflow-x: auto;
473
+ }
474
+ .msg--assistant .msg__error-body code {
475
+ font-size: inherit;
476
+ }
477
+
478
+ /* Inline sprinkle container — shtml code blocks hydrated into iframes */
479
+ .msg__inline-sprinkle {
480
+ margin: 0.6em 0;
481
+ border-radius: var(--s2-radius-default);
482
+ overflow: hidden;
483
+ min-height: 32px;
484
+ }
485
+ .msg__inline-sprinkle iframe {
486
+ display: block;
487
+ width: 100%;
488
+ border: none;
489
+ overflow: hidden;
490
+ background: transparent;
491
+ }
492
+
493
+ /* Continuation messages (same sender, no label) — indent message content only */
494
+ .msg-group--continuation .msg { padding-left: 26px; }
495
+
496
+ /* S2 Detail typography for role labels */
497
+ .msg__role {
498
+ font-size: var(--s2-font-size-50);
499
+ font-weight: 600;
500
+ color: var(--s2-content-tertiary);
501
+ margin-bottom: var(--s2-spacing-50);
502
+ display: flex; align-items: center; gap: var(--s2-spacing-75);
503
+ }
504
+ .msg--user .msg__role { color: var(--s2-content-secondary); }
505
+ .msg--assistant .msg__role { color: var(--s2-content-secondary); }
506
+
507
+ .msg__icon {
508
+ width: 18px; height: 18px; border-radius: var(--s2-radius-pill);
509
+ display: inline-flex; align-items: center; justify-content: center;
510
+ font-size: 10px; font-weight: 700; color: #fff; flex-shrink: 0;
511
+ }
512
+ .msg--user .msg__icon { background: var(--slicc-scoop-blue); }
513
+ .msg--assistant .msg__icon { background: var(--slicc-cone); }
514
+
515
+ /* Collapsible messages */
516
+ .msg__collapsible { cursor: pointer; }
517
+ .msg__collapsible summary {
518
+ list-style: none; cursor: pointer;
519
+ color: var(--s2-content-tertiary);
520
+ font-size: var(--s2-font-size-75);
521
+ padding: var(--s2-spacing-50) 0;
522
+ }
523
+ .msg__collapsible summary::-webkit-details-marker { display: none; }
524
+ .msg__collapsible summary::before {
525
+ content: '\25B8'; font-size: 10px;
526
+ color: var(--s2-content-tertiary);
527
+ transition: transform var(--s2-transition-default);
528
+ display: inline-block; margin-right: var(--s2-spacing-50);
529
+ }
530
+ .msg__collapsible[open] summary::before { transform: rotate(90deg); }
531
+ .msg__collapsible[open] .msg__content { margin-top: var(--s2-spacing-100); }
532
+
533
+ /* Message group */
534
+ .msg-group { display: flex; flex-direction: column; gap: var(--s2-spacing-50); }
535
+
536
+ /* ================================================================== */
537
+ /* Tool calls — S2 compact inline style */
538
+ /* ================================================================== */
539
+ .tool-call { padding: 0; font-size: var(--s2-font-size-75); margin-left: 20px; }
540
+ .tool-call summary {
541
+ list-style: none; cursor: pointer;
542
+ padding: 2px var(--s2-spacing-75);
543
+ display: flex; align-items: center; gap: var(--s2-spacing-50);
544
+ border-radius: var(--s2-radius-default);
545
+ color: var(--s2-content-tertiary);
546
+ transition: background var(--s2-transition-default);
547
+ }
548
+ .tool-call summary:hover { background: var(--s2-bg-layer-2); }
549
+ .tool-call summary::-webkit-details-marker { display: none; }
550
+ .tool-call__header { display: flex; align-items: center; gap: var(--s2-spacing-50); cursor: pointer; }
551
+ .tool-call__icon {
552
+ font-size: 10px; width: 18px; height: 18px;
553
+ display: inline-flex; align-items: center; justify-content: center;
554
+ border-radius: var(--s2-radius-s); background: var(--s2-gray-200);
555
+ flex-shrink: 0;
556
+ }
557
+ .tool-call__name { color: var(--s2-content-secondary); font-weight: 500; font-family: var(--s2-font-mono); font-size: var(--s2-font-size-50); }
558
+ .tool-call__preview {
559
+ color: var(--s2-content-tertiary); font-size: var(--s2-font-size-50);
560
+ margin-left: var(--s2-spacing-50);
561
+ overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
562
+ max-width: 300px; font-family: var(--s2-font-mono);
563
+ }
564
+ .tool-call__status {
565
+ margin-left: auto; font-size: 10px; font-weight: 500;
566
+ font-family: var(--s2-font-mono);
567
+ }
568
+ .tool-call__status--running {
569
+ color: var(--s2-content-tertiary);
570
+ }
571
+ .tool-call__status--running::after {
572
+ content: ''; display: inline-block; width: 16px; height: 2px;
573
+ background: var(--s2-content-tertiary); margin-left: 4px;
574
+ vertical-align: middle; border-radius: 1px;
575
+ animation: status-bar 1s ease-in-out infinite;
576
+ }
577
+ @keyframes status-bar {
578
+ 0%, 100% { opacity: 0.3; }
579
+ 50% { opacity: 1; }
580
+ }
581
+ .tool-call__status--success { color: var(--s2-content-tertiary); }
582
+ .tool-call__status--error { color: var(--s2-negative); }
583
+
584
+ .tool-call__details {
585
+ padding: var(--s2-spacing-50) var(--s2-spacing-75) var(--s2-spacing-75) 22px;
586
+ margin-top: 2px;
587
+ border-left: 2px solid var(--s2-border-subtle);
588
+ margin-left: var(--s2-spacing-75);
589
+ }
590
+ .tool-call__label {
591
+ font-size: 9px; color: var(--s2-content-tertiary);
592
+ text-transform: none; font-weight: 500;
593
+ margin-bottom: 2px;
594
+ }
595
+ .tool-call__input pre, .tool-call__result pre {
596
+ white-space: pre-wrap; font-family: var(--s2-font-mono);
597
+ font-size: var(--s2-font-size-50); color: var(--s2-content-secondary);
598
+ max-height: 150px; overflow-y: auto;
599
+ background: var(--s2-bg-sunken); padding: var(--s2-spacing-75);
600
+ border-radius: var(--s2-radius-s); margin: 0;
601
+ }
602
+ .tool-call__result--error pre { color: var(--s2-negative); }
603
+ .tool-call__screenshot {
604
+ max-width: 100%; max-height: 200px;
605
+ border-radius: var(--s2-radius-default);
606
+ margin-top: var(--s2-spacing-50);
607
+ cursor: pointer; border: 1px solid var(--s2-border-subtle);
608
+ transition: border-color var(--s2-transition-default);
609
+ }
610
+ .tool-call__screenshot:hover { border-color: var(--slicc-cone); }
611
+
612
+ /* ================================================================== */
613
+ /* Licks (webhook/cron events) */
614
+ /* ================================================================== */
615
+ .lick { padding: 0; font-size: var(--s2-font-size-75); margin-left: 20px; }
616
+ .lick summary {
617
+ list-style: none; cursor: pointer;
618
+ padding: 2px var(--s2-spacing-75);
619
+ display: flex; align-items: center; gap: var(--s2-spacing-50);
620
+ border-radius: var(--s2-radius-default);
621
+ color: var(--s2-content-tertiary);
622
+ transition: background var(--s2-transition-default);
623
+ }
624
+ .lick summary:hover { background: var(--s2-bg-layer-2); }
625
+ .lick summary::-webkit-details-marker { display: none; }
626
+ .lick__header { display: flex; align-items: center; gap: var(--s2-spacing-50); cursor: pointer; }
627
+ .lick__icon {
628
+ font-size: 10px; width: 18px; height: 18px;
629
+ display: inline-flex; align-items: center; justify-content: center;
630
+ border-radius: var(--s2-radius-s); background: var(--s2-gray-200);
631
+ flex-shrink: 0; font-weight: 700; color: var(--s2-content-secondary);
632
+ }
633
+ .lick__type { color: var(--s2-content-secondary); font-weight: 500; }
634
+ .lick__preview {
635
+ color: var(--s2-content-tertiary); font-size: var(--s2-font-size-50);
636
+ margin-left: var(--s2-spacing-50);
637
+ overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
638
+ max-width: 300px; font-family: var(--s2-font-mono);
639
+ }
640
+ .lick__details {
641
+ padding: var(--s2-spacing-50) var(--s2-spacing-75) var(--s2-spacing-75) 22px;
642
+ margin-top: 2px; border-left: 2px solid var(--s2-border-subtle);
643
+ margin-left: var(--s2-spacing-75);
644
+ font-size: var(--s2-font-size-75); color: var(--s2-content-secondary);
645
+ }
646
+ .lick__details pre {
647
+ background: var(--s2-bg-sunken); padding: var(--s2-spacing-75);
648
+ border-radius: var(--s2-radius-s); font-size: var(--s2-font-size-50);
649
+ overflow-x: auto;
650
+ }
651
+
652
+ /* ================================================================== */
653
+ /* Markdown prose inside messages */
654
+ /* ================================================================== */
655
+ .msg__content p, .msg__content ul, .msg__content ol,
656
+ .msg__content table, .msg__content blockquote { margin: 0.45em 0; }
657
+ .msg__content h1, .msg__content h2, .msg__content h3,
658
+ .msg__content h4, .msg__content h5, .msg__content h6 {
659
+ margin: 1.2em 0 0.35em; font-weight: 700;
660
+ }
661
+ .msg__content > :first-child { margin-top: 0; }
662
+ .msg__content > :last-child { margin-bottom: 0; }
663
+ .msg__content h1 { font-size: 22px; }
664
+ .msg__content h2 { font-size: var(--s2-font-size-300); }
665
+ .msg__content h3 { font-size: var(--s2-font-size-200); }
666
+ .msg__content ul, .msg__content ol { padding-left: 1.4em; }
667
+ .msg__content table { border-collapse: collapse; font-size: var(--s2-font-size-75); }
668
+ .msg__content th, .msg__content td {
669
+ border: 1px solid var(--s2-border-subtle);
670
+ padding: var(--s2-spacing-50) var(--s2-spacing-200);
671
+ text-align: left;
672
+ }
673
+ .msg__content th { background: var(--s2-bg-layer-2); font-weight: 700; }
674
+ .msg__content blockquote {
675
+ border-left: 3px solid var(--slicc-cone);
676
+ padding-left: var(--s2-spacing-200); color: var(--s2-content-secondary);
677
+ }
678
+ .msg__content a { color: #82aaff; text-decoration: none; }
679
+ .msg__content a:hover { text-decoration: underline; color: #a0c4ff; }
680
+ .msg__content a:visited { color: #82aaff; }
681
+ .msg pre {
682
+ background: var(--s2-bg-sunken); padding: var(--s2-spacing-200);
683
+ border-radius: var(--s2-radius-default);
684
+ overflow-x: auto; margin: var(--s2-spacing-100) 0;
685
+ font-size: 12px; font-family: var(--s2-font-mono);
686
+ white-space: pre-wrap;
687
+ border: 1px solid var(--s2-border-subtle);
688
+ }
689
+ .msg code { font-family: var(--s2-font-mono); font-size: 12px; }
690
+ .msg :not(pre) > code {
691
+ background: var(--s2-gray-200); padding: 2px 6px;
692
+ border-radius: var(--s2-radius-s); font-size: 0.9em;
693
+ }
694
+
695
+ /* S2-aligned syntax tokens */
696
+ .tok-keyword { color: #d19afc; }
697
+ .tok-string { color: #87d68d; }
698
+ .tok-number { color: #f5a76c; }
699
+ .tok-comment { color: var(--s2-gray-500); font-style: italic; }
700
+ .tok-punct { color: #7cc5e9; }
701
+ .tok-fn { color: #7ea8f8; }
702
+
703
+ /* Queued messages — dimmed to distinguish from sent messages */
704
+ .msg--queued { opacity: 0.55; }
705
+ .msg__queued-badge {
706
+ display: inline-block; margin-left: 8px; padding: 1px 6px;
707
+ font-size: 9px; font-weight: 600; text-transform: uppercase;
708
+ background: var(--s2-bg-elevated); color: var(--s2-content-disabled); border-radius: var(--s2-radius-s);
709
+ letter-spacing: 0.5px; vertical-align: middle;
710
+ }
711
+ .msg__queued-delete {
712
+ margin-left: 6px; background: none; border: none;
713
+ color: var(--s2-content-disabled); font-size: 14px; cursor: pointer;
714
+ padding: 0 4px; line-height: 1; vertical-align: middle;
715
+ }
716
+ .msg__queued-delete:hover { color: var(--s2-negative); }
717
+
718
+ /* Streaming cursor — uses accent color */
719
+ .streaming-cursor {
720
+ display: inline-block; width: 2px; height: 16px;
721
+ background: var(--s2-accent); margin-left: 2px;
722
+ animation: blink 1s step-end infinite; vertical-align: text-bottom;
723
+ border-radius: 1px;
724
+ }
725
+ @keyframes blink { 50% { opacity: 0; } }
726
+
727
+ /* ================================================================== */
728
+ /* Chat input — flat field with inline actions */
729
+ /* ================================================================== */
730
+ .chat__input-area {
731
+ padding: var(--s2-spacing-200) var(--s2-spacing-300);
732
+ background: var(--s2-bg-layer-1);
733
+ border-top: 1px solid var(--s2-border-subtle);
734
+ }
735
+ .chat__input-wrapper {
736
+ display: flex; align-items: flex-end;
737
+ border-radius: var(--s2-radius-default);
738
+ border: 1px solid var(--s2-border-default);
739
+ background: var(--s2-bg-sunken);
740
+ transition: border-color var(--s2-transition-default);
741
+ padding-right: var(--s2-spacing-50);
742
+ }
743
+ .chat__input-wrapper:focus-within {
744
+ border-color: var(--s2-accent);
745
+ }
746
+ .chat__textarea {
747
+ flex: 1; resize: none; min-height: 36px; max-height: 120px;
748
+ padding: 8px var(--s2-spacing-200);
749
+ border: none; background: transparent;
750
+ color: var(--s2-content-default);
751
+ font-family: var(--s2-font-family);
752
+ font-size: var(--s2-font-size-100);
753
+ line-height: 1.4; outline: none;
754
+ }
755
+ .chat__textarea::placeholder { color: var(--s2-content-disabled); }
756
+
757
+ /* Inline action buttons — inside the input wrapper */
758
+ .chat__input-actions {
759
+ display: flex; align-items: center; gap: 2px;
760
+ padding-bottom: 4px;
761
+ flex-shrink: 0;
762
+ }
763
+
764
+ /* S2 Accent fill send button (small, inside input) */
765
+ .chat__send-btn {
766
+ width: 28px; height: 28px; border: none;
767
+ border-radius: var(--s2-radius-default);
768
+ background: var(--s2-accent); color: #fff;
769
+ font-size: 12px; cursor: pointer;
770
+ display: flex; align-items: center; justify-content: center;
771
+ flex-shrink: 0;
772
+ transition: background var(--s2-transition-default), transform var(--s2-transition-default);
773
+ }
774
+ .chat__send-btn:hover { background: var(--s2-accent-hover); }
775
+ .chat__send-btn:active { transform: scale(0.92); }
776
+ .chat__send-btn:disabled { opacity: 0.3; cursor: not-allowed; }
777
+
778
+ /* S2 Stop button (inside input) */
779
+ .chat__stop-btn {
780
+ width: 28px; height: 28px; border: none;
781
+ border-radius: var(--s2-radius-default);
782
+ background: var(--s2-negative); color: #fff;
783
+ font-size: 10px; cursor: pointer;
784
+ display: flex; align-items: center; justify-content: center;
785
+ flex-shrink: 0;
786
+ transition: background var(--s2-transition-default), transform var(--s2-transition-default);
787
+ }
788
+ .chat__stop-btn:hover { background: #c43039; }
789
+ .chat__stop-btn:active { transform: scale(0.92); }
790
+
791
+ /* Mic button — subtle secondary action */
792
+ .chat__mic-btn {
793
+ width: 28px; height: 28px; border: none;
794
+ border-radius: var(--s2-radius-default);
795
+ background: transparent; color: var(--s2-content-disabled);
796
+ cursor: pointer;
797
+ display: flex; align-items: center; justify-content: center;
798
+ flex-shrink: 0;
799
+ transition: background var(--s2-transition-default), color var(--s2-transition-default), transform var(--s2-transition-default);
800
+ }
801
+ .chat__mic-btn svg { width: 14px; height: 14px; }
802
+ .chat__mic-btn:hover {
803
+ background: var(--s2-gray-200);
804
+ color: var(--s2-content-secondary);
805
+ }
806
+ .chat__mic-btn:disabled { opacity: 0.3; cursor: not-allowed; }
807
+ .chat__mic-btn--active {
808
+ color: var(--slicc-cone);
809
+ }
810
+ .chat__mic-btn--active.chat__mic-btn--listening,
811
+ .chat__mic-btn--listening {
812
+ background: var(--slicc-cone); color: #fff;
813
+ animation: mic-pulse 1.5s ease-in-out infinite;
814
+ }
815
+ .chat__mic-btn--listening:hover { background: #d96600; }
816
+ @keyframes mic-pulse {
817
+ 0%, 100% { transform: scale(1); opacity: 1; }
818
+ 50% { transform: scale(1.06); opacity: 0.85; }
819
+ }
820
+
821
+ /* ================================================================== */
822
+ /* Panel headers — S2 Title/XS style */
823
+ /* ================================================================== */
824
+ .panel-header {
825
+ display: flex; align-items: center;
826
+ padding: var(--s2-spacing-100) var(--s2-spacing-300);
827
+ background: var(--s2-bg-layer-1);
828
+ border-bottom: 1px solid var(--s2-border-subtle);
829
+ font-size: var(--s2-font-size-50);
830
+ font-weight: 700; color: var(--s2-content-tertiary);
831
+ letter-spacing: 0.05em;
832
+ text-transform: uppercase;
833
+ flex-shrink: 0;
834
+ }
835
+
836
+ /* ================================================================== */
837
+ /* Terminal panel — clean, minimal chrome */
838
+ /* ================================================================== */
839
+ .terminal-panel {
840
+ position: relative;
841
+ flex: 1; min-height: 0; display: flex; flex-direction: column;
842
+ background: var(--s2-bg-layer-1);
843
+ }
844
+ .terminal-panel__header {
845
+ position: absolute; top: 6px; right: var(--s2-spacing-200);
846
+ z-index: 1; display: flex; gap: 4px;
847
+ }
848
+ .terminal-panel__preview-btn {
849
+ display: inline-flex; align-items: center; justify-content: center;
850
+ width: 24px; height: 24px;
851
+ border: none; background: transparent;
852
+ color: var(--s2-content-disabled);
853
+ border-radius: var(--s2-radius-s);
854
+ cursor: default;
855
+ transition: color var(--s2-transition-default), background var(--s2-transition-default);
856
+ }
857
+ .terminal-panel__preview-btn:not(:disabled) {
858
+ color: var(--s2-content-tertiary); cursor: pointer;
859
+ }
860
+ .terminal-panel__preview-btn:not(:disabled):hover {
861
+ color: var(--s2-content-default);
862
+ background: var(--s2-gray-200);
863
+ }
864
+ .terminal-panel__preview-btn--active {
865
+ color: var(--s2-content-default);
866
+ background: var(--s2-gray-300);
867
+ }
868
+ .terminal-panel__preview-btn--active:hover {
869
+ background: var(--s2-gray-300);
870
+ }
871
+ .terminal-panel__preview-btn:focus-visible {
872
+ outline: 2px solid var(--s2-accent);
873
+ outline-offset: -2px;
874
+ }
875
+ .terminal-panel__view {
876
+ flex: 1; min-height: 0; overflow: hidden;
877
+ display: flex; flex-direction: column;
878
+ background: var(--s2-bg-sunken);
879
+ }
880
+ .terminal-panel__mount { flex: 1; min-height: 0; overflow: hidden; display: flex; flex-direction: column; }
881
+ .terminal-panel__terminal-host {
882
+ flex: 1; min-height: 0; overflow: hidden;
883
+ padding: 8px;
884
+ }
885
+ /* xterm.js overrides */
886
+ .terminal-panel__terminal-host .xterm { padding: 0; }
887
+ .terminal-panel__terminal-host .xterm-viewport { background-color: var(--s2-bg-sunken) !important; }
888
+ .terminal-panel__terminal-host .xterm-viewport::-webkit-scrollbar { width: 6px; }
889
+ .terminal-panel__terminal-host .xterm-viewport::-webkit-scrollbar-thumb {
890
+ background: var(--s2-gray-300); border-radius: 3px;
891
+ }
892
+ .terminal-panel__preview {
893
+ display: none; flex: 1; min-height: 0; overflow: auto;
894
+ padding: var(--s2-spacing-200);
895
+ background: var(--s2-bg-sunken);
896
+ }
897
+ .terminal-panel__preview--visible { display: flex; flex-direction: column; }
898
+ .terminal-panel__preview-item { display: flex; flex-direction: column; gap: var(--s2-spacing-100); }
899
+ .terminal-panel__preview-item + .terminal-panel__preview-item { margin-top: var(--s2-spacing-200); }
900
+ .terminal-panel__preview-label {
901
+ color: var(--s2-content-tertiary);
902
+ font-size: var(--s2-font-size-50);
903
+ font-family: var(--s2-font-mono);
904
+ }
905
+ .terminal-panel__preview-media {
906
+ display: block; width: 100%; max-width: 100%;
907
+ max-height: min(100%, 520px);
908
+ object-fit: contain; border-radius: var(--s2-radius-default);
909
+ background: var(--s2-bg-sunken);
910
+ border: 1px solid var(--s2-border-subtle);
911
+ }
912
+ .terminal-panel__empty-state {
913
+ flex: 1; min-height: 0; display: flex; align-items: center; justify-content: center;
914
+ padding: var(--s2-spacing-400);
915
+ color: var(--s2-content-disabled);
916
+ font-size: var(--s2-font-size-75);
917
+ }
918
+
919
+ /* ================================================================== */
920
+ /* Horizontal divider */
921
+ /* ================================================================== */
922
+ .layout__right-divider {
923
+ height: 1px; cursor: row-resize;
924
+ background: var(--s2-border-subtle);
925
+ flex-shrink: 0; transition: background var(--s2-transition-default);
926
+ position: relative;
927
+ }
928
+ .layout__right-divider::after {
929
+ content: ''; position: absolute; inset: 0; top: -3px; bottom: -3px;
930
+ }
931
+ .layout__right-divider:hover, .layout__right-divider.active {
932
+ background: var(--s2-accent);
933
+ }
934
+
935
+ /* ================================================================== */
936
+ /* File browser — S2 Tree View pattern */
937
+ /* ================================================================== */
938
+ .file-browser { flex: 1; min-height: 0; display: flex; flex-direction: column; }
939
+ .file-browser__body {
940
+ flex: 1; min-height: 0; overflow-y: auto;
941
+ padding: var(--s2-spacing-50) 0;
942
+ font-family: var(--s2-font-mono);
943
+ font-size: var(--s2-font-size-75);
944
+ }
945
+ .file-browser__item {
946
+ display: flex; align-items: center; gap: var(--s2-spacing-50);
947
+ padding: 3px var(--s2-spacing-100);
948
+ color: var(--s2-content-default);
949
+ white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
950
+ border-radius: var(--s2-radius-s);
951
+ margin: 0 var(--s2-spacing-50);
952
+ transition: background var(--s2-transition-default);
953
+ }
954
+ .file-browser__item:hover { background: var(--s2-bg-elevated); }
955
+ .file-browser__item--selected {
956
+ background: var(--s2-bg-elevated);
957
+ box-shadow: inset 2px 0 0 var(--s2-accent);
958
+ }
959
+ .file-browser__item--selected:hover {
960
+ background: var(--s2-bg-elevated);
961
+ }
962
+ .file-browser__item--selected.file-browser__item--copy-flash {
963
+ background: color-mix(in srgb, var(--s2-positive) 20%, transparent);
964
+ }
965
+ .file-browser__arrow {
966
+ width: 12px; display: flex; align-items: center; justify-content: center;
967
+ flex-shrink: 0; color: var(--s2-content-tertiary);
968
+ }
969
+ .file-browser__icon {
970
+ flex-shrink: 0; display: flex; align-items: center;
971
+ color: var(--s2-content-tertiary);
972
+ }
973
+ .file-browser__name { overflow: hidden; text-overflow: ellipsis; }
974
+ .file-browser__size {
975
+ margin-left: auto; color: var(--s2-content-tertiary);
976
+ font-size: var(--s2-font-size-50); flex-shrink: 0; padding-left: var(--s2-spacing-100);
977
+ }
978
+ .file-browser__action-btn {
979
+ background: transparent;
980
+ border: none;
981
+ color: var(--s2-content-tertiary);
982
+ cursor: pointer; font-size: 9px;
983
+ padding: 2px var(--s2-spacing-75);
984
+ border-radius: var(--s2-radius-pill);
985
+ flex-shrink: 0; line-height: 1.2;
986
+ font-family: var(--s2-font-mono);
987
+ font-weight: 600;
988
+ letter-spacing: 0.05em;
989
+ transition: all var(--s2-transition-default);
990
+ opacity: 0;
991
+ }
992
+ .file-browser__item:hover .file-browser__action-btn { opacity: 1; }
993
+ .file-browser__action-btn:hover {
994
+ background: var(--s2-accent); color: #fff;
995
+ }
996
+ .file-browser__action-btn:active { transform: scale(0.92); }
997
+ .file-browser__action-btn:disabled { opacity: 0; cursor: not-allowed; }
998
+
999
+ /* ================================================================== */
1000
+ /* Memory panel */
1001
+ /* ================================================================== */
1002
+ .memory-panel { flex: 1; min-height: 0; display: flex; flex-direction: column; overflow: hidden; }
1003
+ .memory-panel__body {
1004
+ flex: 1; min-height: 0; overflow-y: auto;
1005
+ padding: var(--s2-spacing-100);
1006
+ font-family: var(--s2-font-mono);
1007
+ font-size: var(--s2-font-size-75);
1008
+ height: 100%;
1009
+ }
1010
+ .memory-panel__section { margin-bottom: var(--s2-spacing-300); }
1011
+ .memory-panel__section-header {
1012
+ font-weight: 700; font-family: var(--s2-font-family);
1013
+ color: var(--slicc-cone);
1014
+ margin-bottom: var(--s2-spacing-100);
1015
+ padding-bottom: var(--s2-spacing-50);
1016
+ border-bottom: 1px solid var(--s2-border-subtle);
1017
+ font-size: var(--s2-font-size-75);
1018
+ }
1019
+ .memory-panel__memory-content {
1020
+ white-space: pre-wrap; color: var(--s2-content-default);
1021
+ line-height: 1.5;
1022
+ background: var(--s2-bg-sunken);
1023
+ padding: var(--s2-spacing-100);
1024
+ border-radius: var(--s2-radius-default);
1025
+ }
1026
+
1027
+ /* ================================================================== */
1028
+ /* Mini tabs — S2 Tabs pattern */
1029
+ /* ================================================================== */
1030
+ .mini-tabs {
1031
+ display: flex; gap: var(--s2-spacing-100);
1032
+ padding: 0 var(--s2-spacing-200);
1033
+ border-bottom: 1px solid var(--s2-border-subtle);
1034
+ flex-shrink: 0;
1035
+ }
1036
+ .mini-tabs__tab {
1037
+ position: relative;
1038
+ flex: none;
1039
+ padding: var(--s2-spacing-100) var(--s2-spacing-100);
1040
+ border: none; background: transparent;
1041
+ color: var(--s2-content-tertiary);
1042
+ font-size: var(--s2-font-size-75);
1043
+ font-weight: 500; font-family: var(--s2-font-family);
1044
+ cursor: pointer; white-space: nowrap;
1045
+ transition: color var(--s2-transition-default);
1046
+ }
1047
+ .mini-tabs__tab::after {
1048
+ content: ''; position: absolute;
1049
+ bottom: -1px; left: var(--s2-spacing-100); right: var(--s2-spacing-100);
1050
+ height: 2px; border-radius: 1px;
1051
+ background: transparent;
1052
+ transition: background var(--s2-transition-default);
1053
+ }
1054
+ .mini-tabs__tab:hover { color: var(--s2-content-default); }
1055
+ .mini-tabs__tab--active { color: var(--s2-content-default); }
1056
+ .mini-tabs__tab--active::after { background: var(--s2-content-default); }
1057
+ .mini-tabs__tab:focus-visible {
1058
+ outline: 2px solid var(--s2-accent);
1059
+ outline-offset: -2px; border-radius: var(--s2-radius-s);
1060
+ }
1061
+ .mini-tabs__tab:disabled {
1062
+ color: var(--s2-content-disabled); cursor: not-allowed;
1063
+ }
1064
+
1065
+ /* ================================================================== */
1066
+ /* Tab bar (extension mode) — S2 Tabs */
1067
+ /* ================================================================== */
1068
+ .tab-bar {
1069
+ display: flex; background: var(--s2-bg-layer-1);
1070
+ border-bottom: 1px solid var(--s2-border-subtle);
1071
+ flex-shrink: 0;
1072
+ }
1073
+ .tab-bar__tab {
1074
+ flex: 1; padding: var(--s2-spacing-100) 0;
1075
+ border: none; background: transparent;
1076
+ color: var(--s2-content-tertiary);
1077
+ font-size: var(--s2-font-size-75);
1078
+ font-weight: 600; font-family: var(--s2-font-family);
1079
+ cursor: pointer; text-align: center;
1080
+ border-bottom: 2px solid transparent;
1081
+ transition: color var(--s2-transition-default), border-color var(--s2-transition-default);
1082
+ letter-spacing: 0.02em;
1083
+ }
1084
+ .tab-bar__tab:hover { color: var(--s2-content-default); }
1085
+ .tab-bar__tab-close {
1086
+ display: inline-flex; align-items: center; justify-content: center;
1087
+ margin-left: 6px; width: 16px; height: 16px;
1088
+ border-radius: var(--s2-radius-s);
1089
+ font-size: 11px; line-height: 1;
1090
+ color: var(--s2-content-tertiary);
1091
+ opacity: 0.6;
1092
+ }
1093
+ .tab-bar__tab-close:hover {
1094
+ opacity: 1;
1095
+ color: var(--s2-negative);
1096
+ background: color-mix(in srgb, var(--s2-negative) 10%, transparent);
1097
+ }
1098
+ .tab-bar__tab--active {
1099
+ color: var(--s2-content-default);
1100
+ border-bottom-color: var(--s2-accent);
1101
+ }
1102
+ .tab-content { flex: 1; min-height: 0; display: flex; flex-direction: column; }
1103
+ .tab-content__panel {
1104
+ flex: 1; min-height: 0; display: flex; flex-direction: column;
1105
+ overflow: hidden;
1106
+ }
1107
+
1108
+ /* ================================================================== */
1109
+ /* Dialog — S2 Standard Dialog pattern */
1110
+ /* ================================================================== */
1111
+ .dialog-overlay {
1112
+ position: fixed; inset: 0;
1113
+ background: rgba(0,0,0,.55);
1114
+ display: flex; align-items: center; justify-content: center;
1115
+ z-index: 100;
1116
+ backdrop-filter: blur(4px);
1117
+ }
1118
+ .dialog {
1119
+ background: var(--s2-bg-layer-2);
1120
+ border-radius: var(--s2-radius-xl);
1121
+ padding: var(--s2-spacing-500);
1122
+ width: 440px; max-width: 90vw;
1123
+ box-shadow: var(--s2-shadow-elevated);
1124
+ border: 1px solid var(--s2-border-subtle);
1125
+ }
1126
+ .dialog__title {
1127
+ font-size: var(--s2-font-size-300);
1128
+ font-weight: 700;
1129
+ color: var(--s2-content-default);
1130
+ margin-bottom: var(--s2-spacing-100);
1131
+ }
1132
+ .dialog__desc {
1133
+ font-size: var(--s2-font-size-75);
1134
+ color: var(--s2-content-secondary);
1135
+ margin-bottom: var(--s2-spacing-300);
1136
+ line-height: 1.5;
1137
+ }
1138
+ .dialog__input {
1139
+ width: 100%;
1140
+ padding: var(--s2-spacing-100) var(--s2-spacing-200);
1141
+ border-radius: var(--s2-radius-default);
1142
+ border: 1px solid var(--s2-border-default);
1143
+ background: var(--s2-bg-sunken);
1144
+ color: var(--s2-content-default);
1145
+ font-family: var(--s2-font-mono);
1146
+ font-size: var(--s2-font-size-100);
1147
+ margin-bottom: var(--s2-spacing-300);
1148
+ outline: none;
1149
+ transition: border-color var(--s2-transition-default);
1150
+ }
1151
+ .dialog__input:focus { border-color: var(--s2-accent); }
1152
+
1153
+ /* S2 Accent fill button (pill) */
1154
+ .dialog__btn {
1155
+ width: 100%; padding: 10px;
1156
+ border: none; border-radius: var(--s2-radius-pill);
1157
+ background: var(--s2-accent); color: #fff;
1158
+ font-size: var(--s2-font-size-100);
1159
+ font-weight: 600; font-family: var(--s2-font-family);
1160
+ cursor: pointer;
1161
+ transition: background var(--s2-transition-default), transform var(--s2-transition-default);
1162
+ }
1163
+ .dialog__btn:hover { background: var(--s2-accent-hover); }
1164
+ .dialog__btn:active { transform: scale(0.98); }
1165
+ .dialog__btn:disabled { opacity: .4; cursor: not-allowed; }
1166
+ .dialog__btn--secondary {
1167
+ background: transparent; border: 1px solid var(--s2-border-default);
1168
+ color: var(--s2-content-default);
1169
+ }
1170
+ .dialog__btn--secondary:hover { background: var(--s2-gray-200); }
1171
+
1172
+ /* ================================================================== */
1173
+ /* SHTML Canvas Panel Components */
1174
+ /* ================================================================== */
1175
+
1176
+ /* Close button for panel tabs (standalone mode) */
1177
+ .mini-tabs__tab-close {
1178
+ display: inline-flex; align-items: center; justify-content: center;
1179
+ margin-left: 6px; width: 16px; height: 16px;
1180
+ border-radius: var(--s2-radius-s);
1181
+ font-size: 12px; line-height: 1;
1182
+ color: var(--s2-content-tertiary);
1183
+ }
1184
+ .mini-tabs__tab-close:hover {
1185
+ color: var(--s2-negative);
1186
+ background: color-mix(in srgb, var(--s2-negative) 10%, transparent);
1187
+ }
1188
+
1189
+ /* Sprinkle content wrapper */
1190
+ .sprinkle-content { padding: var(--s2-spacing-200); }
1191
+
1192
+ /* ── Action Card (inline sprinkle chat cards) ── */
1193
+ .sprinkle-action-card {
1194
+ display: flex;
1195
+ flex-direction: column;
1196
+ background: var(--s2-bg-layer-2);
1197
+ border: 1px solid var(--s2-border-subtle);
1198
+ border-radius: var(--s2-radius-l);
1199
+ overflow: hidden;
1200
+ }
1201
+ .sprinkle-action-card__header {
1202
+ display: flex;
1203
+ align-items: center;
1204
+ gap: var(--s2-spacing-100);
1205
+ padding: var(--s2-spacing-200) var(--s2-spacing-200) var(--s2-spacing-75);
1206
+ font-weight: 700;
1207
+ font-size: var(--s2-font-size-100);
1208
+ color: var(--s2-content-default);
1209
+ }
1210
+ .sprinkle-action-card__header .sprinkle-badge {
1211
+ margin-left: auto;
1212
+ }
1213
+ .sprinkle-action-card__body {
1214
+ padding: 0 var(--s2-spacing-200) var(--s2-spacing-100);
1215
+ font-size: var(--s2-font-size-75);
1216
+ color: var(--s2-content-secondary);
1217
+ line-height: 1.5;
1218
+ }
1219
+ .sprinkle-action-card__actions {
1220
+ display: flex;
1221
+ gap: var(--s2-spacing-100);
1222
+ justify-content: flex-end;
1223
+ padding: var(--s2-spacing-100) var(--s2-spacing-200);
1224
+ border-top: 1px solid var(--s2-border-subtle);
1225
+ }
1226
+
1227
+ /* ── Cards (S2 Cards — flex variant, 10px radius, shadow instead of border) ── */
1228
+ .sprinkle-card {
1229
+ background: var(--s2-bg-layer-2);
1230
+ border-radius: var(--s2-radius-l);
1231
+ padding: var(--s2-spacing-300);
1232
+ margin-bottom: var(--s2-spacing-200);
1233
+ box-shadow: var(--s2-shadow-container);
1234
+ transition: box-shadow 130ms ease;
1235
+ }
1236
+ .sprinkle-card:hover {
1237
+ box-shadow: var(--s2-shadow-elevated);
1238
+ }
1239
+ .sprinkle-stat-card {
1240
+ background: var(--s2-bg-layer-2);
1241
+ border-radius: var(--s2-radius-l);
1242
+ padding: var(--s2-spacing-200) var(--s2-spacing-300);
1243
+ text-align: center;
1244
+ box-shadow: var(--s2-shadow-container);
1245
+ transition: box-shadow 130ms ease;
1246
+ }
1247
+ .sprinkle-stat-card:hover {
1248
+ box-shadow: var(--s2-shadow-elevated);
1249
+ }
1250
+ .sprinkle-stat-card .value {
1251
+ font-size: var(--s2-font-size-500);
1252
+ font-weight: 800;
1253
+ color: var(--s2-content-default);
1254
+ line-height: 1.2;
1255
+ }
1256
+ .sprinkle-stat-card .label {
1257
+ font-size: var(--s2-font-size-75);
1258
+ font-weight: 500;
1259
+ color: var(--s2-content-secondary);
1260
+ margin-top: var(--s2-spacing-50);
1261
+ }
1262
+
1263
+ /* ── Tables (S2 Table — no uppercase, no letter-spacing, proper hierarchy) ── */
1264
+ .sprinkle-table {
1265
+ width: 100%; border-collapse: collapse;
1266
+ font-size: var(--s2-font-size-75);
1267
+ }
1268
+ .sprinkle-table th {
1269
+ text-align: left;
1270
+ padding: var(--s2-spacing-100) var(--s2-spacing-200);
1271
+ border-bottom: 2px solid var(--s2-border-default);
1272
+ color: var(--s2-content-secondary);
1273
+ font-weight: 700;
1274
+ font-size: var(--s2-font-size-75);
1275
+ }
1276
+ .sprinkle-table td {
1277
+ padding: var(--s2-spacing-100) var(--s2-spacing-200);
1278
+ border-bottom: 1px solid var(--s2-border-subtle);
1279
+ color: var(--s2-content-default);
1280
+ }
1281
+ .sprinkle-table tr:hover td {
1282
+ background: color-mix(in srgb, var(--s2-bg-elevated) 50%, transparent);
1283
+ }
1284
+
1285
+ /* ── Badges (S2 Badge — bold style default, 8px radius, solid fill + white text) ── */
1286
+ .sprinkle-badge {
1287
+ display: inline-flex; align-items: center;
1288
+ padding: 3px 8px; border-radius: var(--s2-radius-default);
1289
+ font-size: var(--s2-font-size-50); font-weight: 500;
1290
+ line-height: var(--s2-line-height-50);
1291
+ /* neutral/gray — bold style default */
1292
+ background: var(--s2-gray-400); color: #fff;
1293
+ }
1294
+ .sprinkle-badge--positive { background: var(--s2-positive); color: #fff; }
1295
+ .sprinkle-badge--negative { background: var(--s2-negative); color: #fff; }
1296
+ .sprinkle-badge--notice { background: var(--s2-notice); color: #fff; }
1297
+ .sprinkle-badge--informative { background: var(--s2-informative); color: #fff; }
1298
+ .sprinkle-badge--accent { background: var(--s2-accent); color: #fff; }
1299
+ /* subtle style variant — tinted backgrounds with colored text */
1300
+ .sprinkle-badge--subtle {
1301
+ background: color-mix(in srgb, var(--s2-gray-400) 15%, transparent);
1302
+ color: var(--s2-content-secondary);
1303
+ }
1304
+ .sprinkle-badge--subtle.sprinkle-badge--positive { background: color-mix(in srgb, var(--s2-positive) 15%, transparent); color: var(--s2-positive); }
1305
+ .sprinkle-badge--subtle.sprinkle-badge--negative { background: color-mix(in srgb, var(--s2-negative) 15%, transparent); color: var(--s2-negative); }
1306
+ .sprinkle-badge--subtle.sprinkle-badge--notice { background: color-mix(in srgb, var(--s2-notice) 15%, transparent); color: var(--s2-notice); }
1307
+ .sprinkle-badge--subtle.sprinkle-badge--informative { background: color-mix(in srgb, var(--s2-informative) 15%, transparent); color: var(--s2-informative); }
1308
+ .sprinkle-badge--subtle.sprinkle-badge--accent { background: color-mix(in srgb, var(--s2-accent) 15%, transparent); color: var(--s2-accent); }
1309
+ /* outline style variant — stroke with no fill */
1310
+ .sprinkle-badge--outline {
1311
+ background: transparent; color: var(--s2-content-secondary);
1312
+ box-shadow: inset 0 0 0 1px var(--s2-border-default);
1313
+ }
1314
+ .sprinkle-badge--outline.sprinkle-badge--positive { color: var(--s2-positive); box-shadow: inset 0 0 0 1px var(--s2-positive); }
1315
+ .sprinkle-badge--outline.sprinkle-badge--negative { color: var(--s2-negative); box-shadow: inset 0 0 0 1px var(--s2-negative); }
1316
+ .sprinkle-badge--outline.sprinkle-badge--notice { color: var(--s2-notice); box-shadow: inset 0 0 0 1px var(--s2-notice); }
1317
+ .sprinkle-badge--outline.sprinkle-badge--informative { color: var(--s2-informative); box-shadow: inset 0 0 0 1px var(--s2-informative); }
1318
+
1319
+ /* ── Status Lights (S2 Status Light — dot + label) ── */
1320
+ .sprinkle-status-light {
1321
+ display: inline-flex; align-items: center; gap: var(--s2-spacing-75);
1322
+ font-size: var(--s2-font-size-75);
1323
+ color: var(--s2-content-default);
1324
+ }
1325
+ .sprinkle-status-light::before {
1326
+ content: ''; width: 8px; height: 8px;
1327
+ border-radius: 50%; background: var(--s2-content-tertiary);
1328
+ flex-shrink: 0;
1329
+ }
1330
+ .sprinkle-status-light--positive::before { background: var(--s2-positive); }
1331
+ .sprinkle-status-light--negative::before { background: var(--s2-negative); }
1332
+ .sprinkle-status-light--notice::before { background: var(--s2-notice); }
1333
+ .sprinkle-status-light--informative::before { background: var(--s2-informative); }
1334
+
1335
+ /* ── Progress Bar (S2 Progress Bar — label + value above, track + fill) ── */
1336
+ .sprinkle-progress-bar {
1337
+ display: flex; flex-direction: column; gap: var(--s2-spacing-75);
1338
+ --_bar-color: var(--s2-accent);
1339
+ }
1340
+ .sprinkle-progress-bar--positive { --_bar-color: var(--s2-positive); }
1341
+ .sprinkle-progress-bar--negative { --_bar-color: var(--s2-negative); }
1342
+ .sprinkle-progress-bar--notice { --_bar-color: var(--s2-notice); }
1343
+ .sprinkle-progress-bar--informative { --_bar-color: var(--s2-informative); }
1344
+ .sprinkle-progress-bar__header {
1345
+ display: flex; justify-content: space-between; align-items: baseline;
1346
+ font-size: var(--s2-font-size-75); color: var(--s2-content-default);
1347
+ }
1348
+ .sprinkle-progress-bar__header .label { font-weight: 400; }
1349
+ .sprinkle-progress-bar__header .value { font-weight: 400; color: var(--s2-content-secondary); }
1350
+ .sprinkle-progress-bar__track {
1351
+ height: 4px; border-radius: var(--s2-radius-pill);
1352
+ background: var(--s2-gray-200); overflow: hidden;
1353
+ position: relative;
1354
+ }
1355
+ .sprinkle-progress-bar__track .fill {
1356
+ height: 100%; border-radius: var(--s2-radius-pill);
1357
+ background: var(--fill-color, var(--_bar-color, var(--s2-accent)));
1358
+ transition: width 300ms ease;
1359
+ }
1360
+ /* Auto-fill via --progress custom property on parent */
1361
+ .sprinkle-progress-bar__track::after {
1362
+ content: ''; position: absolute; inset: 0; right: auto;
1363
+ width: var(--progress, var(--value, 0%));
1364
+ border-radius: var(--s2-radius-pill);
1365
+ background: var(--fill-color, var(--_bar-color, var(--s2-accent)));
1366
+ transition: width 300ms ease;
1367
+ }
1368
+ .sprinkle-progress-bar__track:has(> .fill)::after { display: none; }
1369
+ /* Legacy / simple bar (no __track child) — also supports --progress custom prop */
1370
+ .sprinkle-progress-bar:not(:has(.sprinkle-progress-bar__track)) {
1371
+ height: 4px; width: 100%; border-radius: var(--s2-radius-pill);
1372
+ background: var(--s2-gray-200); overflow: hidden;
1373
+ flex-direction: row; position: relative;
1374
+ }
1375
+ .sprinkle-progress-bar:not(:has(.sprinkle-progress-bar__track)) > .fill {
1376
+ height: 100%; border-radius: var(--s2-radius-pill);
1377
+ background: var(--fill-color, var(--_bar-color, var(--s2-accent)));
1378
+ transition: width 300ms ease;
1379
+ }
1380
+ /* Auto-fill via --progress custom property (agent writes style="--progress: 75%") */
1381
+ .sprinkle-progress-bar:not(:has(.sprinkle-progress-bar__track))::after {
1382
+ content: ''; position: absolute; inset: 0; right: auto;
1383
+ width: var(--progress, var(--value, 0%));
1384
+ border-radius: var(--s2-radius-pill);
1385
+ background: var(--fill-color, var(--_bar-color, var(--s2-accent)));
1386
+ transition: width 300ms ease;
1387
+ }
1388
+ /* Hide pseudo when a .fill child exists (it handles its own width) */
1389
+ .sprinkle-progress-bar:not(:has(.sprinkle-progress-bar__track)):has(> .fill)::after {
1390
+ display: none;
1391
+ }
1392
+
1393
+ /* ── Meter (S2 Meter — label + value above, track + fill, semantic variants) ── */
1394
+ .sprinkle-meter {
1395
+ display: flex; flex-direction: column; gap: var(--s2-spacing-75);
1396
+ --_meter-color: var(--s2-informative);
1397
+ }
1398
+ .sprinkle-meter--positive { --_meter-color: var(--s2-positive); }
1399
+ .sprinkle-meter--notice { --_meter-color: var(--s2-notice); }
1400
+ .sprinkle-meter--negative { --_meter-color: var(--s2-negative); }
1401
+ .sprinkle-meter__header {
1402
+ display: flex; justify-content: space-between; align-items: baseline;
1403
+ font-size: var(--s2-font-size-75); color: var(--s2-content-default);
1404
+ }
1405
+ .sprinkle-meter__header .label { font-weight: 400; }
1406
+ .sprinkle-meter__header .value { font-weight: 400; color: var(--s2-content-secondary); }
1407
+ .sprinkle-meter__track {
1408
+ height: 4px; border-radius: var(--s2-radius-pill);
1409
+ background: var(--s2-gray-200); overflow: hidden;
1410
+ position: relative;
1411
+ }
1412
+ .sprinkle-meter__track .fill {
1413
+ height: 100%; border-radius: var(--s2-radius-pill);
1414
+ background: var(--fill-color, var(--_meter-color));
1415
+ transition: width 300ms ease;
1416
+ }
1417
+ .sprinkle-meter__track::after {
1418
+ content: ''; position: absolute; inset: 0; right: auto;
1419
+ width: var(--progress, var(--value, 0%));
1420
+ border-radius: var(--s2-radius-pill);
1421
+ background: var(--fill-color, var(--_meter-color));
1422
+ transition: width 300ms ease;
1423
+ }
1424
+ .sprinkle-meter__track:has(> .fill)::after { display: none; }
1425
+ /* Legacy / simple meter (no __track child) */
1426
+ .sprinkle-meter:not(:has(.sprinkle-meter__track)) {
1427
+ height: 4px; width: 100%; border-radius: var(--s2-radius-pill);
1428
+ background: var(--s2-gray-200); overflow: hidden;
1429
+ flex-direction: row; position: relative;
1430
+ }
1431
+ .sprinkle-meter:not(:has(.sprinkle-meter__track)) > .fill {
1432
+ height: 100%; border-radius: var(--s2-radius-pill);
1433
+ background: var(--fill-color, var(--_meter-color));
1434
+ transition: width 300ms ease;
1435
+ }
1436
+ .sprinkle-meter:not(:has(.sprinkle-meter__track))::after {
1437
+ content: ''; position: absolute; inset: 0; right: auto;
1438
+ width: var(--progress, var(--value, 0%));
1439
+ border-radius: var(--s2-radius-pill);
1440
+ background: var(--fill-color, var(--_meter-color));
1441
+ transition: width 300ms ease;
1442
+ }
1443
+ .sprinkle-meter:not(:has(.sprinkle-meter__track)):has(> .fill)::after { display: none; }
1444
+
1445
+ /* ── Key-Value List (supports <ul><li> with .key/.value, or <dl><dt><dd>) ── */
1446
+ .sprinkle-kv-list {
1447
+ list-style: none; padding: 0; margin: 0;
1448
+ }
1449
+ .sprinkle-kv-list li {
1450
+ display: flex; justify-content: space-between; align-items: center;
1451
+ padding: var(--s2-spacing-100) 0;
1452
+ border-bottom: 1px solid var(--s2-border-subtle);
1453
+ font-size: var(--s2-font-size-75);
1454
+ }
1455
+ .sprinkle-kv-list li:last-child { border-bottom: none; }
1456
+ .sprinkle-kv-list .key { color: var(--s2-content-secondary); font-weight: 400; }
1457
+ .sprinkle-kv-list .value { color: var(--s2-content-default); font-weight: 700; }
1458
+ /* <dl> variant */
1459
+ dl.sprinkle-kv-list {
1460
+ display: grid; grid-template-columns: auto 1fr;
1461
+ gap: 0; font-size: var(--s2-font-size-75);
1462
+ }
1463
+ dl.sprinkle-kv-list dt,
1464
+ dl.sprinkle-kv-list dd {
1465
+ padding: var(--s2-spacing-100) 0;
1466
+ border-bottom: 1px solid var(--s2-border-subtle);
1467
+ margin: 0;
1468
+ }
1469
+ dl.sprinkle-kv-list dt {
1470
+ color: var(--s2-content-secondary); font-weight: 400;
1471
+ padding-right: var(--s2-spacing-300);
1472
+ }
1473
+ dl.sprinkle-kv-list dd {
1474
+ color: var(--s2-content-default); font-weight: 700;
1475
+ text-align: right;
1476
+ }
1477
+ dl.sprinkle-kv-list dt:last-of-type,
1478
+ dl.sprinkle-kv-list dd:last-of-type { border-bottom: none; }
1479
+
1480
+ /* ── Buttons (S2 Button — pill rounding, cursor: default, all states) ── */
1481
+ .sprinkle-btn {
1482
+ display: inline-flex; align-items: center; justify-content: center; gap: var(--s2-spacing-75);
1483
+ height: 32px;
1484
+ padding: 0 16px;
1485
+ border: 2px solid var(--s2-border-default);
1486
+ border-radius: var(--s2-radius-pill);
1487
+ background: transparent;
1488
+ color: var(--s2-content-default);
1489
+ font-size: var(--s2-font-size-100); font-weight: 700;
1490
+ font-family: var(--s2-font-family);
1491
+ cursor: default;
1492
+ transition: background 130ms ease, border-color 130ms ease, transform 130ms ease, box-shadow 130ms ease;
1493
+ }
1494
+ .sprinkle-btn:hover { background: color-mix(in srgb, var(--s2-content-default) 6%, transparent); }
1495
+ .sprinkle-btn:active { transform: scale(0.98); }
1496
+ .sprinkle-btn:focus-visible {
1497
+ outline: 2px solid var(--s2-border-focus);
1498
+ outline-offset: 2px;
1499
+ }
1500
+ .sprinkle-btn:disabled, .sprinkle-btn[disabled] {
1501
+ opacity: 0.4; pointer-events: none;
1502
+ }
1503
+ /* Accent (fill) — S2 default CTA */
1504
+ .sprinkle-btn--primary {
1505
+ background: var(--s2-accent); color: #fff; border-color: transparent;
1506
+ }
1507
+ .sprinkle-btn--primary:hover { background: var(--s2-accent-hover); }
1508
+ .sprinkle-btn--primary:active { background: var(--s2-accent-down); transform: scale(0.98); }
1509
+ /* Secondary (outline) — visible stroke, no fill */
1510
+ .sprinkle-btn--secondary {
1511
+ background: transparent; border-color: var(--s2-border-default);
1512
+ color: var(--s2-content-default);
1513
+ }
1514
+ .sprinkle-btn--secondary:hover { background: color-mix(in srgb, var(--s2-content-default) 6%, transparent); }
1515
+ /* Negative (fill) — destructive */
1516
+ .sprinkle-btn--negative {
1517
+ background: var(--s2-negative); color: #fff; border-color: transparent;
1518
+ }
1519
+ .sprinkle-btn--negative:hover { background: color-mix(in srgb, var(--s2-negative) 85%, #000); }
1520
+
1521
+ /* ── Button Groups (S2 Button Group — gap-based, each button keeps its pill shape) ── */
1522
+ .sprinkle-btn-group {
1523
+ display: inline-flex; gap: var(--s2-spacing-100);
1524
+ }
1525
+
1526
+ /* ── Text Field (S2 Text Field — single-line input) ── */
1527
+ .sprinkle-text-field {
1528
+ width: 100%; padding: 7px 12px;
1529
+ font-size: var(--s2-font-size-75); font-family: var(--s2-font-family);
1530
+ color: var(--s2-content-default); background: var(--s2-bg-layer-2);
1531
+ border: 1px solid var(--s2-border-subtle); border-radius: var(--s2-radius-default);
1532
+ outline: none; transition: border-color var(--s2-transition-default);
1533
+ }
1534
+ .sprinkle-text-field::placeholder { color: var(--s2-content-disabled); }
1535
+ .sprinkle-text-field:hover { border-color: var(--s2-content-secondary); }
1536
+ .sprinkle-text-field:focus { border-color: var(--s2-accent); box-shadow: 0 0 0 1px var(--s2-accent); }
1537
+
1538
+ /* ── Layout Utilities ── */
1539
+ .sprinkle-grid {
1540
+ display: grid;
1541
+ grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
1542
+ gap: var(--s2-spacing-200);
1543
+ }
1544
+ .sprinkle-stack {
1545
+ display: flex; flex-direction: column;
1546
+ gap: var(--s2-spacing-200);
1547
+ }
1548
+ .sprinkle-row {
1549
+ display: flex; align-items: center;
1550
+ gap: var(--s2-spacing-200);
1551
+ }
1552
+
1553
+ /* ── Typography (S2 Type Roles) ── */
1554
+ /* Heading — ExtraBold 800, never below 18px */
1555
+ .sprinkle-heading {
1556
+ font-size: var(--s2-font-size-300);
1557
+ font-weight: 800;
1558
+ color: var(--s2-content-default);
1559
+ margin: 0 0 var(--s2-spacing-100);
1560
+ line-height: var(--s2-line-height-300);
1561
+ letter-spacing: 0;
1562
+ }
1563
+ /* Body — Regular 400, 1.5× line-height */
1564
+ .sprinkle-body {
1565
+ font-size: var(--s2-font-size-100);
1566
+ font-weight: 400;
1567
+ color: var(--s2-content-default);
1568
+ line-height: 1.5;
1569
+ letter-spacing: 0;
1570
+ }
1571
+ /* Detail — Medium 500 */
1572
+ .sprinkle-detail {
1573
+ font-size: var(--s2-font-size-50);
1574
+ font-weight: 500;
1575
+ color: var(--s2-content-secondary);
1576
+ line-height: var(--s2-line-height-50);
1577
+ letter-spacing: 0;
1578
+ }
1579
+
1580
+ /* ── Divider (S2 Divider — small = 1px, medium = 2px, large = 4px) ── */
1581
+ .sprinkle-divider {
1582
+ border: none;
1583
+ border-top: 1px solid var(--s2-border-subtle);
1584
+ margin: var(--s2-spacing-200) 0;
1585
+ }
1586
+ .sprinkle-divider--medium {
1587
+ border-top-width: 2px;
1588
+ border-top-color: var(--s2-border-default);
1589
+ margin: var(--s2-spacing-300) 0;
1590
+ }
1591
+
1592
+ /* ── Empty State ── */
1593
+ .sprinkle-empty-state {
1594
+ text-align: center;
1595
+ padding: var(--s2-spacing-500) var(--s2-spacing-300);
1596
+ color: var(--s2-content-tertiary);
1597
+ font-size: var(--s2-font-size-100);
1598
+ }
1599
+
1600
+ /* ── Layout: Sidebar ── */
1601
+ .sprinkle-sidebar {
1602
+ display: flex;
1603
+ gap: 0;
1604
+ min-height: 0;
1605
+ flex: 1;
1606
+ }
1607
+ .sprinkle-sidebar__nav {
1608
+ width: 240px;
1609
+ min-width: 240px;
1610
+ overflow-y: auto;
1611
+ border-right: 1px solid var(--s2-border-default);
1612
+ background: var(--s2-bg-layer-1);
1613
+ padding: var(--s2-spacing-200) 0;
1614
+ }
1615
+ .sprinkle-sidebar__nav-item {
1616
+ display: flex;
1617
+ align-items: center;
1618
+ gap: var(--s2-spacing-100);
1619
+ padding: var(--s2-spacing-100) var(--s2-spacing-200);
1620
+ font-size: var(--s2-font-size-75);
1621
+ color: var(--s2-content-secondary);
1622
+ cursor: default;
1623
+ border-radius: 0;
1624
+ transition: background 130ms ease, color 130ms ease;
1625
+ }
1626
+ .sprinkle-sidebar__nav-item:hover {
1627
+ background: var(--s2-bg-elevated);
1628
+ color: var(--s2-content-primary);
1629
+ }
1630
+ .sprinkle-sidebar__nav-item--active {
1631
+ background: color-mix(in srgb, var(--s2-accent) 10%, transparent);
1632
+ color: var(--s2-accent);
1633
+ font-weight: 600;
1634
+ }
1635
+ .sprinkle-sidebar__nav-label {
1636
+ padding: var(--s2-spacing-200) var(--s2-spacing-200) var(--s2-spacing-50);
1637
+ font-size: var(--s2-font-size-50);
1638
+ font-weight: 700;
1639
+ text-transform: uppercase;
1640
+ letter-spacing: 0.04em;
1641
+ color: var(--s2-content-tertiary);
1642
+ }
1643
+ .sprinkle-sidebar__main {
1644
+ flex: 1;
1645
+ min-width: 0;
1646
+ overflow-y: auto;
1647
+ padding: var(--s2-spacing-200);
1648
+ }
1649
+
1650
+ /* ── Layout: Split Pane ── */
1651
+ .sprinkle-split {
1652
+ display: flex;
1653
+ gap: 0;
1654
+ min-height: 0;
1655
+ flex: 1;
1656
+ }
1657
+ .sprinkle-split > * {
1658
+ flex: 1;
1659
+ min-width: 0;
1660
+ overflow-y: auto;
1661
+ }
1662
+ .sprinkle-split > :not(:last-child) {
1663
+ border-right: 1px solid var(--s2-border-default);
1664
+ }
1665
+ .sprinkle-split--vertical {
1666
+ flex-direction: column;
1667
+ }
1668
+ .sprinkle-split--vertical > :not(:last-child) {
1669
+ border-right: none;
1670
+ border-bottom: 1px solid var(--s2-border-default);
1671
+ }
1672
+
1673
+ /* ── Layout: Toolbar ── */
1674
+ .sprinkle-toolbar {
1675
+ display: flex;
1676
+ align-items: center;
1677
+ gap: var(--s2-spacing-100);
1678
+ padding: var(--s2-spacing-100) var(--s2-spacing-200);
1679
+ border-bottom: 1px solid var(--s2-border-default);
1680
+ background: var(--s2-bg-layer-1);
1681
+ min-height: 40px;
1682
+ flex-shrink: 0;
1683
+ }
1684
+ .sprinkle-toolbar__start {
1685
+ display: flex;
1686
+ align-items: center;
1687
+ gap: var(--s2-spacing-100);
1688
+ }
1689
+ .sprinkle-toolbar__center {
1690
+ display: flex;
1691
+ align-items: center;
1692
+ gap: var(--s2-spacing-100);
1693
+ flex: 1;
1694
+ justify-content: center;
1695
+ }
1696
+ .sprinkle-toolbar__end {
1697
+ display: flex;
1698
+ align-items: center;
1699
+ gap: var(--s2-spacing-100);
1700
+ margin-left: auto;
1701
+ }
1702
+
1703
+ /* ── Layout: Tabs ── */
1704
+ .sprinkle-tabs {
1705
+ display: flex;
1706
+ gap: 0;
1707
+ border-bottom: 1px solid var(--s2-border-default);
1708
+ background: var(--s2-bg-layer-1);
1709
+ flex-shrink: 0;
1710
+ overflow-x: auto;
1711
+ }
1712
+ .sprinkle-tabs__tab {
1713
+ padding: var(--s2-spacing-100) var(--s2-spacing-200);
1714
+ font-size: var(--s2-font-size-75);
1715
+ color: var(--s2-content-secondary);
1716
+ background: none;
1717
+ border: none;
1718
+ border-bottom: 2px solid transparent;
1719
+ cursor: default;
1720
+ white-space: nowrap;
1721
+ transition: color 130ms ease, border-color 130ms ease;
1722
+ }
1723
+ .sprinkle-tabs__tab:hover {
1724
+ color: var(--s2-content-primary);
1725
+ }
1726
+ .sprinkle-tabs__tab--active {
1727
+ color: var(--s2-accent);
1728
+ border-bottom-color: var(--s2-accent);
1729
+ font-weight: 600;
1730
+ }
1731
+ .sprinkle-tabs__panel {
1732
+ display: none;
1733
+ flex: 1;
1734
+ min-height: 0;
1735
+ overflow-y: auto;
1736
+ }
1737
+ .sprinkle-tabs__panel--active {
1738
+ display: flex;
1739
+ flex-direction: column;
1740
+ }
1741
+
1742
+ /* ── Layout: Dialog / Modal ── */
1743
+ .sprinkle-dialog {
1744
+ position: fixed;
1745
+ inset: 0;
1746
+ display: flex;
1747
+ align-items: center;
1748
+ justify-content: center;
1749
+ z-index: 100;
1750
+ }
1751
+ .sprinkle-dialog[hidden] { display: none; }
1752
+ .sprinkle-dialog__backdrop {
1753
+ position: absolute;
1754
+ inset: 0;
1755
+ background: rgba(0, 0, 0, 0.4);
1756
+ backdrop-filter: blur(2px);
1757
+ }
1758
+ .sprinkle-dialog__content {
1759
+ position: relative;
1760
+ background: var(--s2-bg-layer-2);
1761
+ border-radius: var(--s2-radius-xl);
1762
+ box-shadow: var(--s2-shadow-elevated);
1763
+ padding: var(--s2-spacing-400);
1764
+ max-width: min(560px, calc(100% - 32px));
1765
+ max-height: calc(100% - 64px);
1766
+ overflow-y: auto;
1767
+ min-width: 280px;
1768
+ }
1769
+ .sprinkle-dialog__header {
1770
+ display: flex;
1771
+ align-items: center;
1772
+ justify-content: space-between;
1773
+ margin-bottom: var(--s2-spacing-300);
1774
+ }
1775
+ .sprinkle-dialog__title {
1776
+ font-size: var(--s2-font-size-200);
1777
+ font-weight: 700;
1778
+ color: var(--s2-content-primary);
1779
+ }
1780
+ .sprinkle-dialog__close {
1781
+ width: 28px;
1782
+ height: 28px;
1783
+ border-radius: var(--s2-radius-pill);
1784
+ border: none;
1785
+ background: none;
1786
+ color: var(--s2-content-secondary);
1787
+ cursor: default;
1788
+ display: flex;
1789
+ align-items: center;
1790
+ justify-content: center;
1791
+ font-size: 18px;
1792
+ transition: background 130ms ease;
1793
+ }
1794
+ .sprinkle-dialog__close:hover {
1795
+ background: var(--s2-bg-elevated);
1796
+ }
1797
+ .sprinkle-dialog__footer {
1798
+ display: flex;
1799
+ justify-content: flex-end;
1800
+ gap: var(--s2-spacing-100);
1801
+ margin-top: var(--s2-spacing-300);
1802
+ }
1803
+
1804
+ /* ── Layout: Collapsible ── */
1805
+ .sprinkle-collapsible {}
1806
+ .sprinkle-collapsible__header {
1807
+ display: flex;
1808
+ align-items: center;
1809
+ gap: var(--s2-spacing-100);
1810
+ padding: var(--s2-spacing-100) var(--s2-spacing-200);
1811
+ cursor: default;
1812
+ font-size: var(--s2-font-size-100);
1813
+ font-weight: 600;
1814
+ color: var(--s2-content-primary);
1815
+ background: none;
1816
+ border: none;
1817
+ width: 100%;
1818
+ text-align: left;
1819
+ border-radius: var(--s2-radius-default);
1820
+ transition: background 130ms ease;
1821
+ }
1822
+ .sprinkle-collapsible__header:hover {
1823
+ background: var(--s2-bg-elevated);
1824
+ }
1825
+ .sprinkle-collapsible__chevron {
1826
+ display: inline-block;
1827
+ width: 16px;
1828
+ height: 16px;
1829
+ transition: transform 200ms ease;
1830
+ flex-shrink: 0;
1831
+ }
1832
+ .sprinkle-collapsible__chevron::before {
1833
+ content: '▶';
1834
+ font-size: 10px;
1835
+ color: var(--s2-content-tertiary);
1836
+ }
1837
+ .sprinkle-collapsible--open .sprinkle-collapsible__chevron {
1838
+ transform: rotate(90deg);
1839
+ }
1840
+ .sprinkle-collapsible__body {
1841
+ display: none;
1842
+ padding: var(--s2-spacing-100) var(--s2-spacing-200) var(--s2-spacing-200) calc(var(--s2-spacing-200) + 16px + var(--s2-spacing-100));
1843
+ }
1844
+ .sprinkle-collapsible--open .sprinkle-collapsible__body {
1845
+ display: block;
1846
+ }
1847
+
1848
+ /* ── Layout: Canvas / SVG Container ── */
1849
+ .sprinkle-canvas {
1850
+ position: relative;
1851
+ width: 100%;
1852
+ overflow: hidden;
1853
+ border-radius: var(--s2-radius-l);
1854
+ background: var(--s2-bg-layer-1);
1855
+ }
1856
+ .sprinkle-canvas--16x9 { aspect-ratio: 16 / 9; }
1857
+ .sprinkle-canvas--4x3 { aspect-ratio: 4 / 3; }
1858
+ .sprinkle-canvas--1x1 { aspect-ratio: 1 / 1; }
1859
+ .sprinkle-canvas svg,
1860
+ .sprinkle-canvas canvas {
1861
+ display: block;
1862
+ width: 100%;
1863
+ height: 100%;
1864
+ }
1865
+
1866
+ /* ── Container Query Responsive Rules ── */
1867
+ .sprinkle-panel { container-type: inline-size; }
1868
+
1869
+ @container (max-width: 400px) {
1870
+ .sprinkle-sidebar {
1871
+ flex-direction: column;
1872
+ }
1873
+ .sprinkle-sidebar__nav {
1874
+ width: 100%;
1875
+ min-width: 0;
1876
+ max-height: 200px;
1877
+ border-right: none;
1878
+ border-bottom: 1px solid var(--s2-border-default);
1879
+ }
1880
+ .sprinkle-grid {
1881
+ grid-template-columns: 1fr;
1882
+ }
1883
+ .sprinkle-split:not(.sprinkle-split--vertical) {
1884
+ flex-direction: column;
1885
+ }
1886
+ .sprinkle-split:not(.sprinkle-split--vertical) > :not(:last-child) {
1887
+ border-right: none;
1888
+ border-bottom: 1px solid var(--s2-border-default);
1889
+ }
1890
+ .sprinkle-toolbar {
1891
+ flex-wrap: wrap;
1892
+ }
1893
+ }
1894
+
1895
+ @container (min-width: 600px) {
1896
+ .sprinkle-sidebar__nav {
1897
+ width: 240px;
1898
+ min-width: 240px;
1899
+ }
1900
+ .sprinkle-grid {
1901
+ grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
1902
+ }
1903
+ }
1904
+
1905
+ /* ================================================================== */
1906
+ /* Skill drag/drop install feedback */
1907
+ /* ================================================================== */
1908
+ .skill-drop-overlay {
1909
+ position: fixed; inset: 0;
1910
+ display: flex; align-items: center; justify-content: center;
1911
+ background: rgba(0,0,0,.38);
1912
+ backdrop-filter: blur(3px);
1913
+ opacity: 0; pointer-events: none;
1914
+ transition: opacity var(--s2-transition-default);
1915
+ z-index: 180;
1916
+ }
1917
+ .skill-drop-overlay--visible { opacity: 1; }
1918
+ .skill-drop-overlay__card {
1919
+ min-width: min(420px, calc(100vw - 32px));
1920
+ max-width: calc(100vw - 32px);
1921
+ padding: var(--s2-spacing-400);
1922
+ border-radius: var(--s2-radius-xl);
1923
+ background: color-mix(in srgb, var(--s2-bg-layer-2) 92%, transparent);
1924
+ border: 1px dashed var(--s2-accent);
1925
+ box-shadow: var(--s2-shadow-elevated);
1926
+ text-align: center;
1927
+ }
1928
+ .skill-drop-overlay__title {
1929
+ font-size: var(--s2-font-size-300);
1930
+ font-weight: 700;
1931
+ color: var(--s2-content-default);
1932
+ }
1933
+ .skill-drop-overlay__desc {
1934
+ margin-top: var(--s2-spacing-75);
1935
+ color: var(--s2-content-secondary);
1936
+ font-size: var(--s2-font-size-75);
1937
+ font-family: var(--s2-font-mono);
1938
+ word-break: break-word;
1939
+ }
1940
+
1941
+ .skill-drop-toast-container {
1942
+ position: fixed;
1943
+ top: calc(var(--s2-header-height) + var(--s2-spacing-200));
1944
+ right: var(--s2-spacing-200);
1945
+ display: flex;
1946
+ flex-direction: column;
1947
+ gap: var(--s2-spacing-100);
1948
+ z-index: 190;
1949
+ pointer-events: none;
1950
+ }
1951
+ .skill-drop-toast {
1952
+ max-width: min(420px, calc(100vw - 32px));
1953
+ padding: var(--s2-spacing-200) var(--s2-spacing-300);
1954
+ border-radius: var(--s2-radius-default);
1955
+ background: var(--s2-bg-layer-2);
1956
+ color: var(--s2-content-default);
1957
+ border: 1px solid var(--s2-border-subtle);
1958
+ box-shadow: var(--s2-shadow-elevated);
1959
+ font-size: var(--s2-font-size-75);
1960
+ line-height: 1.45;
1961
+ opacity: 0;
1962
+ transform: translateY(-8px);
1963
+ transition: opacity 160ms ease, transform 160ms ease;
1964
+ }
1965
+ .skill-drop-toast--visible {
1966
+ opacity: 1;
1967
+ transform: translateY(0);
1968
+ }
1969
+ .skill-drop-toast--success {
1970
+ border-color: color-mix(in srgb, var(--s2-positive) 55%, var(--s2-border-subtle));
1971
+ }
1972
+ .skill-drop-toast--error {
1973
+ border-color: color-mix(in srgb, var(--s2-negative) 65%, var(--s2-border-subtle));
1974
+ }
1975
+ </style>
1976
+ <script type="module" crossorigin src="/assets/index-DvjzakYY.js"></script>
1977
+ </head>
1978
+ <body>
1979
+ <div id="app"></div>
1980
+ </body>
1981
+ </html>